Skip to content

Commit

Permalink
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/arm64/linux

Pull arm64 fixes from Will Deacon:
 "There's more here than we usually have at this stage, but that's
  mainly down to the stacktrace changes which came in slightly too late
  for the merge window.

  Summary:

   - Big bad batch of MAINTAINERS updates

   - Fix handling of SP alignment fault exceptions

   - Fix PSTATE.SSBS handling on heterogeneous systems

   - Fix fallout from moving to the generic vDSO implementation

   - Fix stack unwinding in the face of frame corruption

   - Fix off-by-one in IORT code

   - Minor SVE cleanups"

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
  ACPI/IORT: Fix off-by-one check in iort_dev_find_its_id()
  arm64: entry: SP Alignment Fault doesn't write to FAR_EL1
  arm64: Force SSBS on context switch
  MAINTAINERS: Update my email address
  MAINTAINERS: Update my email address
  MAINTAINERS: Fix spelling mistake in my name
  MAINTAINERS: Update my email address to @kernel.org
  arm64: mm: Drop pte_huge()
  arm64/sve: Fix a couple of magic numbers for the Z-reg count
  arm64/sve: Factor out FPSIMD to SVE state conversion
  arm64: stacktrace: Better handle corrupted stacks
  arm64: stacktrace: Factor out backtrace initialisation
  arm64: stacktrace: Constify stacktrace.h functions
  arm64: vdso: Cleanup Makefiles
  arm64: vdso: fix flip/flop vdso build bug
  arm64: vdso: Fix population of AT_SYSINFO_EHDR for compat vdso
  • Loading branch information
torvalds committed Jul 26, 2019
2 parents 4792ba1 + 5a46d3f commit 0ed2886
Show file tree
Hide file tree
Showing 17 changed files with 219 additions and 106 deletions.
3 changes: 3 additions & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Jason Gunthorpe <[email protected]> <[email protected]>
Javi Merino <[email protected]> <[email protected]>
<[email protected]> <[email protected]>
Jean Tourrilhes <[email protected]>
<[email protected]> <[email protected]>
Jeff Garzik <[email protected]>
Jeff Layton <[email protected]> <[email protected]>
Jeff Layton <[email protected]> <[email protected]>
Expand All @@ -116,6 +117,7 @@ John Stultz <[email protected]>
Juha Yrjola <at solidboot.com>
Juha Yrjola <[email protected]>
Juha Yrjola <[email protected]>
Julien Thierry <[email protected]> <[email protected]>
Kay Sievers <[email protected]>
Kenneth W Chen <[email protected]>
Konstantin Khlebnikov <[email protected]> <[email protected]>
Expand All @@ -132,6 +134,7 @@ Linus Lüssing <[email protected]> <[email protected]>
Li Yang <[email protected]> <[email protected]>
Li Yang <[email protected]> <[email protected]>
Maciej W. Rozycki <[email protected]> <[email protected]>
Marc Zyngier <[email protected]> <[email protected]>
Marcin Nowakowski <[email protected]> <[email protected]>
Mark Brown <[email protected]>
Mark Yao <[email protected]> <[email protected]>
Expand Down
14 changes: 7 additions & 7 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ F: include/uapi/linux/if_arcnet.h

ARM ARCHITECTED TIMER DRIVER
M: Mark Rutland <[email protected]>
M: Marc Zyngier <[email protected]>
M: Marc Zyngier <[email protected]>
L: [email protected] (moderated for non-subscribers)
S: Maintained
F: arch/arm/include/asm/arch_timer.h
Expand Down Expand Up @@ -8490,7 +8490,7 @@ S: Obsolete
F: include/uapi/linux/ipx.h

IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
M: Marc Zyngier <[email protected]>
M: Marc Zyngier <[email protected]>
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
F: Documentation/IRQ-domain.txt
Expand All @@ -8508,7 +8508,7 @@ F: kernel/irq/
IRQCHIP DRIVERS
M: Thomas Gleixner <[email protected]>
M: Jason Cooper <[email protected]>
M: Marc Zyngier <[email protected]>
M: Marc Zyngier <[email protected]>
L: [email protected]
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
Expand Down Expand Up @@ -8828,10 +8828,10 @@ F: arch/x86/include/asm/svm.h
F: arch/x86/kvm/svm.c

KERNEL VIRTUAL MACHINE FOR ARM/ARM64 (KVM/arm, KVM/arm64)
M: Marc Zyngier <[email protected]>
M: Marc Zyngier <[email protected]>
R: James Morse <[email protected]>
R: Julien Thierry <julien.thierry@arm.com>
R: Suzuki K Pouloze <[email protected]>
R: Julien Thierry <julien.thierry.kdev@gmail.com>
R: Suzuki K Poulose <[email protected]>
L: [email protected] (moderated for non-subscribers)
L: [email protected]
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git
Expand Down Expand Up @@ -17124,7 +17124,7 @@ F: drivers/virtio/virtio_input.c
F: include/uapi/linux/virtio_input.h

VIRTIO IOMMU DRIVER
M: Jean-Philippe Brucker <jean-philippe[email protected]>
M: Jean-Philippe Brucker <jean-philippe@linaro.org>
L: [email protected]
S: Maintained
F: drivers/iommu/virtio-iommu.c
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/include/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
({ \
set_thread_flag(TIF_32BIT); \
})
#ifdef CONFIG_GENERIC_COMPAT_VDSO
#ifdef CONFIG_COMPAT_VDSO
#define COMPAT_ARCH_DLINFO \
do { \
/* \
Expand Down
1 change: 0 additions & 1 deletion arch/arm64/include/asm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ static inline int pte_same(pte_t pte_a, pte_t pte_b)
/*
* Huge pte definitions.
*/
#define pte_huge(pte) (!(pte_val(pte) & PTE_TABLE_BIT))
#define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT))

/*
Expand Down
14 changes: 12 additions & 2 deletions arch/arm64/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,24 @@ static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
regs->pmr_save = GIC_PRIO_IRQON;
}

static inline void set_ssbs_bit(struct pt_regs *regs)
{
regs->pstate |= PSR_SSBS_BIT;
}

static inline void set_compat_ssbs_bit(struct pt_regs *regs)
{
regs->pstate |= PSR_AA32_SSBS_BIT;
}

static inline void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
{
start_thread_common(regs, pc);
regs->pstate = PSR_MODE_EL0t;

if (arm64_get_ssbd_state() != ARM64_SSBD_FORCE_ENABLE)
regs->pstate |= PSR_SSBS_BIT;
set_ssbs_bit(regs);

regs->sp = sp;
}
Expand All @@ -219,7 +229,7 @@ static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
#endif

if (arm64_get_ssbd_state() != ARM64_SSBD_FORCE_ENABLE)
regs->pstate |= PSR_AA32_SSBS_BIT;
set_compat_ssbs_bit(regs);

regs->compat_sp = sp;
}
Expand Down
78 changes: 65 additions & 13 deletions arch/arm64/include/asm/stacktrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,20 @@
#include <linux/percpu.h>
#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include <linux/types.h>

#include <asm/memory.h>
#include <asm/ptrace.h>
#include <asm/sdei.h>

struct stackframe {
unsigned long fp;
unsigned long pc;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
int graph;
#endif
};

enum stack_type {
STACK_TYPE_UNKNOWN,
STACK_TYPE_TASK,
STACK_TYPE_IRQ,
STACK_TYPE_OVERFLOW,
STACK_TYPE_SDEI_NORMAL,
STACK_TYPE_SDEI_CRITICAL,
__NR_STACK_TYPES
};

struct stack_info {
Expand All @@ -36,6 +30,37 @@ struct stack_info {
enum stack_type type;
};

/*
* A snapshot of a frame record or fp/lr register values, along with some
* accounting information necessary for robust unwinding.
*
* @fp: The fp value in the frame record (or the real fp)
* @pc: The fp value in the frame record (or the real lr)
*
* @stacks_done: Stacks which have been entirely unwound, for which it is no
* longer valid to unwind to.
*
* @prev_fp: The fp that pointed to this frame record, or a synthetic value
* of 0. This is used to ensure that within a stack, each
* subsequent frame record is at an increasing address.
* @prev_type: The type of stack this frame record was on, or a synthetic
* value of STACK_TYPE_UNKNOWN. This is used to detect a
* transition from one stack to another.
*
* @graph: When FUNCTION_GRAPH_TRACER is selected, holds the index of a
* replacement lr value in the ftrace graph stack.
*/
struct stackframe {
unsigned long fp;
unsigned long pc;
DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
unsigned long prev_fp;
enum stack_type prev_type;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
int graph;
#endif
};

extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame);
extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
int (*fn)(struct stackframe *, void *), void *data);
Expand Down Expand Up @@ -64,8 +89,9 @@ static inline bool on_irq_stack(unsigned long sp,
return true;
}

static inline bool on_task_stack(struct task_struct *tsk, unsigned long sp,
struct stack_info *info)
static inline bool on_task_stack(const struct task_struct *tsk,
unsigned long sp,
struct stack_info *info)
{
unsigned long low = (unsigned long)task_stack_page(tsk);
unsigned long high = low + THREAD_SIZE;
Expand Down Expand Up @@ -112,10 +138,13 @@ static inline bool on_overflow_stack(unsigned long sp,
* We can only safely access per-cpu stacks from current in a non-preemptible
* context.
*/
static inline bool on_accessible_stack(struct task_struct *tsk,
unsigned long sp,
struct stack_info *info)
static inline bool on_accessible_stack(const struct task_struct *tsk,
unsigned long sp,
struct stack_info *info)
{
if (info)
info->type = STACK_TYPE_UNKNOWN;

if (on_task_stack(tsk, sp, info))
return true;
if (tsk != current || preemptible())
Expand All @@ -130,4 +159,27 @@ static inline bool on_accessible_stack(struct task_struct *tsk,
return false;
}

static inline void start_backtrace(struct stackframe *frame,
unsigned long fp, unsigned long pc)
{
frame->fp = fp;
frame->pc = pc;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
frame->graph = 0;
#endif

/*
* Prime the first unwind.
*
* In unwind_frame() we'll check that the FP points to a valid stack,
* which can't be STACK_TYPE_UNKNOWN, and the first unwind will be
* treated as a transition to whichever stack that happens to be. The
* prev_fp value won't be used, but we set it to 0 such that it is
* definitely not an accessible stack address.
*/
bitmap_zero(frame->stacks_done, __NR_STACK_TYPES);
frame->prev_fp = 0;
frame->prev_type = STACK_TYPE_UNKNOWN;
}

#endif /* __ASM_STACKTRACE_H */
22 changes: 13 additions & 9 deletions arch/arm64/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -586,10 +586,8 @@ el1_sync:
b.eq el1_ia
cmp x24, #ESR_ELx_EC_SYS64 // configurable trap
b.eq el1_undef
cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
b.eq el1_sp_pc
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
b.eq el1_sp_pc
b.eq el1_pc
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL1
b.eq el1_undef
cmp x24, #ESR_ELx_EC_BREAKPT_CUR // debug exception in EL1
Expand All @@ -611,9 +609,11 @@ el1_da:
bl do_mem_abort

kernel_exit 1
el1_sp_pc:
el1_pc:
/*
* Stack or PC alignment exception handling
* PC alignment exception handling. We don't handle SP alignment faults,
* since we will have hit a recursive exception when trying to push the
* initial pt_regs.
*/
mrs x0, far_el1
inherit_daif pstate=x23, tmp=x2
Expand Down Expand Up @@ -732,9 +732,9 @@ el0_sync:
ccmp x24, #ESR_ELx_EC_WFx, #4, ne
b.eq el0_sys
cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
b.eq el0_sp_pc
b.eq el0_sp
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
b.eq el0_sp_pc
b.eq el0_pc
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0
b.eq el0_undef
cmp x24, #ESR_ELx_EC_BREAKPT_LOW // debug exception in EL0
Expand All @@ -758,7 +758,7 @@ el0_sync_compat:
cmp x24, #ESR_ELx_EC_FP_EXC32 // FP/ASIMD exception
b.eq el0_fpsimd_exc
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
b.eq el0_sp_pc
b.eq el0_pc
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0
b.eq el0_undef
cmp x24, #ESR_ELx_EC_CP15_32 // CP15 MRC/MCR trap
Expand Down Expand Up @@ -858,11 +858,15 @@ el0_fpsimd_exc:
mov x1, sp
bl do_fpsimd_exc
b ret_to_user
el0_sp:
ldr x26, [sp, #S_SP]
b el0_sp_pc
el0_pc:
mrs x26, far_el1
el0_sp_pc:
/*
* Stack or PC alignment exception handling
*/
mrs x26, far_el1
gic_prio_kentry_setup tmp=x0
enable_da_f
#ifdef CONFIG_TRACE_IRQFLAGS
Expand Down
29 changes: 15 additions & 14 deletions arch/arm64/kernel/fpsimd.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,18 @@ static __uint128_t arm64_cpu_to_le128(__uint128_t x)

#define arm64_le128_to_cpu(x) arm64_cpu_to_le128(x)

static void __fpsimd_to_sve(void *sst, struct user_fpsimd_state const *fst,
unsigned int vq)
{
unsigned int i;
__uint128_t *p;

for (i = 0; i < SVE_NUM_ZREGS; ++i) {
p = (__uint128_t *)ZREG(sst, vq, i);
*p = arm64_cpu_to_le128(fst->vregs[i]);
}
}

/*
* Transfer the FPSIMD state in task->thread.uw.fpsimd_state to
* task->thread.sve_state.
Expand All @@ -423,17 +435,12 @@ static void fpsimd_to_sve(struct task_struct *task)
unsigned int vq;
void *sst = task->thread.sve_state;
struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state;
unsigned int i;
__uint128_t *p;

if (!system_supports_sve())
return;

vq = sve_vq_from_vl(task->thread.sve_vl);
for (i = 0; i < 32; ++i) {
p = (__uint128_t *)ZREG(sst, vq, i);
*p = arm64_cpu_to_le128(fst->vregs[i]);
}
__fpsimd_to_sve(sst, fst, vq);
}

/*
Expand All @@ -459,7 +466,7 @@ static void sve_to_fpsimd(struct task_struct *task)
return;

vq = sve_vq_from_vl(task->thread.sve_vl);
for (i = 0; i < 32; ++i) {
for (i = 0; i < SVE_NUM_ZREGS; ++i) {
p = (__uint128_t const *)ZREG(sst, vq, i);
fst->vregs[i] = arm64_le128_to_cpu(*p);
}
Expand Down Expand Up @@ -550,20 +557,14 @@ void sve_sync_from_fpsimd_zeropad(struct task_struct *task)
unsigned int vq;
void *sst = task->thread.sve_state;
struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state;
unsigned int i;
__uint128_t *p;

if (!test_tsk_thread_flag(task, TIF_SVE))
return;

vq = sve_vq_from_vl(task->thread.sve_vl);

memset(sst, 0, SVE_SIG_REGS_SIZE(vq));

for (i = 0; i < 32; ++i) {
p = (__uint128_t *)ZREG(sst, vq, i);
*p = arm64_cpu_to_le128(fst->vregs[i]);
}
__fpsimd_to_sve(sst, fst, vq);
}

int sve_set_vector_length(struct task_struct *task,
Expand Down
7 changes: 1 addition & 6 deletions arch/arm64/kernel/perf_callchain.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,7 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
return;
}

frame.fp = regs->regs[29];
frame.pc = regs->pc;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
frame.graph = 0;
#endif

start_backtrace(&frame, regs->regs[29], regs->pc);
walk_stackframe(current, &frame, callchain_trace, entry);
}

Expand Down
Loading

0 comments on commit 0ed2886

Please sign in to comment.