Message ID | 20170922182614.27885-1-james.morse@arm.com |
---|---|
Headers | show |
Series | arm64/firmware: Software Delegated Exception Interface | expand |
On Fri, Sep 22, 2017 at 07:26:05PM +0100, James Morse wrote: > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c > index cd52d365d1f0..8e4c7da2b126 100644 > --- a/arch/arm64/kernel/cpufeature.c > +++ b/arch/arm64/kernel/cpufeature.c > @@ -865,6 +865,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = { > .capability = ARM64_HAS_VIRT_HOST_EXTN, > .def_scope = SCOPE_SYSTEM, > .matches = runs_at_el2, > + .enable = cpu_copy_el2regs, > }, > { > .desc = "32-bit EL0 Support", > @@ -1308,3 +1309,25 @@ static int __init enable_mrs_emulation(void) > } > > late_initcall(enable_mrs_emulation); > + > +int cpu_copy_el2regs(void *__unused) > +{ > + int do_copyregs = 0; > + > + /* > + * Copy register values that aren't redirected by hardware. > + * > + * Before code patching, we only set tpidr_el1, all CPUs need to copy > + * this value to tpidr_el2 before we patch the code. Once we've done > + * that, freshly-onlined CPUs will set tpidr_el2, so we don't need to > + * do anything here. > + */ > + asm volatile(ALTERNATIVE("mov %0, #1", "mov %0, #0", > + ARM64_HAS_VIRT_HOST_EXTN) > + : "=r" (do_copyregs) : : ); Can you just do: if (cpu_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN)) write_sysreg(read_sysreg(tpidr_el1), tpidr_el2); At this point the capability bits should be set and the jump labels enabled. Otherwise: Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, Sep 22, 2017 at 07:26:09PM +0100, James Morse wrote: > diff --git a/arch/arm64/include/asm/vmap_stack.h b/arch/arm64/include/asm/vmap_stack.h > new file mode 100644 > index 000000000000..f41d043cac31 > --- /dev/null > +++ b/arch/arm64/include/asm/vmap_stack.h > @@ -0,0 +1,41 @@ > +/* > + * Copyright (C) 2017 ARM Ltd. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see <http://www.gnu.org/licenses/>. > + */ > +#ifndef __ASM_VMAP_STACK_H > +#define __ASM_VMAP_STACK_H > + > +#include <linux/vmalloc.h> > +#include <asm/memory.h> > +#include <asm/pgtable.h> > +#include <asm/thread_info.h> > + > +#ifdef CONFIG_VMAP_STACK > +/* > + * To ensure that VMAP'd stack overflow detection works correctly, all VMAP'd > + * stacks need to have the same alignment. > + */ > +static inline unsigned long *arch_alloc_vmap_stack(size_t stack_size, int node) > +{ > + return __vmalloc_node_range(stack_size, THREAD_ALIGN, > + VMALLOC_START, VMALLOC_END, > + THREADINFO_GFP, PAGE_KERNEL, 0, node, > + __builtin_return_address(0)); > +} > + > +#else > +unsigned long *arch_alloc_vmap_stack(size_t stack_size, int node); // link error Do you actually need this here? The calling site (at least in this patch), is surrounded by CONFIG_VMAP_STACK. Removing the dummy declaration should be fine (I haven't read the rest of the patches yet, maybe it's needed later; would a BUILD_BUG do?).
On Fri, Sep 22, 2017 at 07:26:08PM +0100, James Morse wrote: > The Software Delegated Exception Interface (SDEI) is an ARM standard > for registering callbacks from the platform firmware into the OS. > This is typically used to implement firmware notifications (such as > firmware-first RAS) or promote an IRQ that has been promoted to a > firmware-assisted NMI. > > Add the code for detecting the SDEI version and the framework for > registering and unregistering events. Subsequent patches will add the > arch-specific backend code and the necessary power management hooks. > > Only shared events are supported, power management, private events and > discovery for ACPI systems will be added by later patches. > > Signed-off-by: James Morse <james.morse@arm.com> > --- > Changes since v2: > * Copy the priority into the structure the arch asm handler gets. This > is used for VMAP stacks where we can't know if a critical event interrupted > a normal priority event, thus they need separate stacks. > > Changes since v1: > * Changed entry point to unsigned long, if we support non-vhe systems this > won't be a valid pointer > * Made invoke_sdei_fn() pass the only register we are interested in, instead > of the whole arm_smccc_res > * Made all the locking WARN_ON()s lockdep_assert_held()s. > * Moved more messages from 'err' to 'warn'. > * Made IS_SDEI_CALL() not depend on whether the config option is selected. > * Made 'event failed' messages rate limited. > > drivers/firmware/Kconfig | 7 + > drivers/firmware/Makefile | 1 + > drivers/firmware/arm_sdei.c | 616 ++++++++++++++++++++++++++++++++++++++++++++ > include/linux/sdei.h | 100 +++++++ > include/uapi/linux/sdei.h | 91 +++++++ > 5 files changed, 815 insertions(+) > create mode 100644 drivers/firmware/arm_sdei.c > create mode 100644 include/linux/sdei.h > create mode 100644 include/uapi/linux/sdei.h I haven't reviewed this patch (yet...). However, I think it's worth adding a MAINTAINERS entry with your name on it (unless you really want to distance yourself from this code once merged ;)). Thanks.
Hi Catalin, On 13/10/17 16:31, Catalin Marinas wrote: > On Fri, Sep 22, 2017 at 07:26:05PM +0100, James Morse wrote: >> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c >> index cd52d365d1f0..8e4c7da2b126 100644 >> --- a/arch/arm64/kernel/cpufeature.c >> +++ b/arch/arm64/kernel/cpufeature.c >> @@ -1308,3 +1309,25 @@ static int __init enable_mrs_emulation(void) >> } >> >> late_initcall(enable_mrs_emulation); >> + >> +int cpu_copy_el2regs(void *__unused) >> +{ >> + int do_copyregs = 0; >> + >> + /* >> + * Copy register values that aren't redirected by hardware. >> + * >> + * Before code patching, we only set tpidr_el1, all CPUs need to copy >> + * this value to tpidr_el2 before we patch the code. Once we've done >> + * that, freshly-onlined CPUs will set tpidr_el2, so we don't need to >> + * do anything here. >> + */ >> + asm volatile(ALTERNATIVE("mov %0, #1", "mov %0, #0", >> + ARM64_HAS_VIRT_HOST_EXTN) >> + : "=r" (do_copyregs) : : ); > > Can you just do: > > if (cpu_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN)) > write_sysreg(read_sysreg(tpidr_el1), tpidr_el2); > > At this point the capability bits should be set and the jump labels > enabled. These are enabled too early, we haven't done patching yet. We need to copy tpidr_el1 -> tpidr_el2 on all CPUs that are online before code patching. After code patching new CPUs set tpidr_el2 when they come online, so we don't need to do the copy... but this enable method is still called. There is nothing for us to do, and tpidr_el1 now contains junk, so the copy cpu_have_const_cap() is great for knowing if we have a feature, here we want to know if we've done the patching for this feature. I can wrap the ALTERNATIVE() into a helper, something like: > arm64_alternatives_applied(ARM64_HAS_VIRT_HOST_EXTN) which should make it clearer. Christoffer had the same question at connect, so I evidently haven't found the right way of describing this yet. > Otherwise: > > Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Thanks for taking a look, I'll leave this RB until your happy with the ALTERNATIVE() hackery above. James -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, Sep 22, 2017 at 07:26:05PM +0100, James Morse wrote: > diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h > index 29adab8138c3..8f2d0f7d193b 100644 > --- a/arch/arm64/include/asm/processor.h > +++ b/arch/arm64/include/asm/processor.h > @@ -193,5 +193,6 @@ static inline void spin_lock_prefetch(const void *ptr) > > int cpu_enable_pan(void *__unused); > int cpu_enable_cache_maint_trap(void *__unused); > +int cpu_copy_el2regs(void *__unused); > > #endif /* __ASM_PROCESSOR_H */ > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c > index cd52d365d1f0..8e4c7da2b126 100644 > --- a/arch/arm64/kernel/cpufeature.c > +++ b/arch/arm64/kernel/cpufeature.c [...] > +int cpu_copy_el2regs(void *__unused) Can this be static? I couldn't find it used anywhere else apart from cpufeature.c
On Fri, Sep 22, 2017 at 07:26:10PM +0100, James Morse wrote: > diff --git a/arch/arm64/include/asm/sdei.h b/arch/arm64/include/asm/sdei.h > new file mode 100644 > index 000000000000..ed329e01a301 > --- /dev/null > +++ b/arch/arm64/include/asm/sdei.h > @@ -0,0 +1,63 @@ > +/* > + * Copyright (C) 2017 ARM Ltd. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see <http://www.gnu.org/licenses/>. > + */ > +#ifndef __ASM_SDEI_H > +#define __ASM_SDEI_H > + > +/* Values for sdei_exit_mode */ > +#define SDEI_EXIT_HVC 0 > +#define SDEI_EXIT_SMC 1 > + > +#define SDEI_STACK_SIZE IRQ_STACK_SIZE > + > +#ifndef __ASSEMBLY__ > + > +#include <linux/linkage.h> > +#include <linux/types.h> > + > +#include <asm/virt.h> > + > +extern unsigned long sdei_exit_mode; > + > +/* Software Delegated Exception entry point from firmware*/ > +asmlinkage void __sdei_asm_handler(unsigned long event_num, unsigned long arg, > + unsigned long pc, unsigned long pstate); > + > +/* > + * The above entry point does the minimum to call C code. This function does > + * anything else, before calling the driver. > + */ > +struct sdei_registered_event; > +asmlinkage unsigned long __sdei_handler(struct pt_regs *regs, > + struct sdei_registered_event *arg); > + > +extern unsigned long sdei_arch_get_entry_point(int conduit); Nitpick: drop the "extern" here. > diff --git a/arch/arm64/kernel/sdei-entry.S b/arch/arm64/kernel/sdei-entry.S > new file mode 100644 > index 000000000000..cf12f8da0789 > --- /dev/null > +++ b/arch/arm64/kernel/sdei-entry.S > @@ -0,0 +1,122 @@ > +/* > + * Software Delegated Exception entry point from firmware to the kernel. > + * > + * Copyright (C) 2017 ARM Ltd. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include <linux/linkage.h> > + > +#include <asm/alternative.h> > +#include <asm/asm-offsets.h> > +#include <asm/assembler.h> > +#include <asm/memory.h> > +#include <asm/ptrace.h> > +#include <asm/sdei.h> > +#include <uapi/linux/sdei.h> > + > +/* > + * Software Delegated Exception entry point. > + * > + * x0: Event number Currently the only event number is 0. Shall we plan for having other events in the future or we just ignore this argument? > + * x1: struct sdei_registered_event argument from registration time. > + * x2: interrupted PC > + * x3: interrupted PSTATE [...] > +/* > + * __sdei_handler() returns one of: > + * SDEI_EV_HANDLED - success, return to the interrupted context. > + * SDEI_EV_FAILED - failure, return this error code to firmare. > + * virtual-address - success, return to this address. > + */ > +static __kprobes unsigned long _sdei_handler(struct pt_regs *regs, > + struct sdei_registered_event *arg) > +{ > + u32 mode; > + int i, err = 0; > + int clobbered_registers = 4; Maybe const int here if you want to avoid magic numbers in the 'for' loop below. Otherwise it looks like some variable you intend to modify in this function. > + u64 elr = read_sysreg(elr_el1); > + u32 kernel_mode = read_sysreg(CurrentEL) | 1; /* +SPSel */ > + unsigned long vbar = read_sysreg(vbar_el1); > + > + /* Retrieve the missing registers values */ > + for (i = 0; i < clobbered_registers; i++) { > + /* from within the handler, this call always succeeds */ > + sdei_api_event_context(i, ®s->regs[i]); > + } > + > + /* > + * We didn't take an exception to get here, set PAN. UAO will be cleared > + * by sdei_event_handler()s set_fs(USER_DS) call. > + */ > + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, > + CONFIG_ARM64_PAN)); Can you use uaccess_disable() directly? > diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig > index d8a9859f6102..1f6633b337aa 100644 > --- a/drivers/firmware/Kconfig > +++ b/drivers/firmware/Kconfig > @@ -50,6 +50,7 @@ config ARM_SCPI_POWER_DOMAIN > > config ARM_SDE_INTERFACE > bool "ARM Software Delegated Exception Interface (SDEI)" > + depends on ARM64 > help > The Software Delegated Exception Interface (SDEI) is an ARM > standard for registering callbacks from the platform firmware > diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c > index 4b3c7fd99c34..3ea6a19ae439 100644 > --- a/drivers/firmware/arm_sdei.c > +++ b/drivers/firmware/arm_sdei.c > @@ -154,6 +154,7 @@ int sdei_api_event_context(u32 query, u64 *result) > return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_CONTEXT, query, 0, 0, 0, 0, > result); > } > +NOKPROBE_SYMBOL(sdei_api_event_context); Should this be part of the patch introducing arm_sdei.c? > > static int sdei_api_event_get_info(u32 event, u32 info, u64 *result) > { > diff --git a/include/linux/sdei.h b/include/linux/sdei.h > index bb3dd000771e..df3fe6373e32 100644 > --- a/include/linux/sdei.h > +++ b/include/linux/sdei.h > @@ -32,6 +32,8 @@ enum sdei_conduit_types { > CONDUIT_HVC, > }; > > +#include <asm/sdei.h> > + > /* Arch code should override this to set the entry point from firmware... */ > #ifndef sdei_arch_get_entry_point > #define sdei_arch_get_entry_point(conduit) (0) Same here. This should not be built before the Kconfig change anyway.
On Fri, Sep 22, 2017 at 07:26:11PM +0100, James Morse wrote: > diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h > index f24bfb2b9a2d..466b949474df 100644 > --- a/include/linux/cpuhotplug.h > +++ b/include/linux/cpuhotplug.h > @@ -88,6 +88,7 @@ enum cpuhp_state { > CPUHP_AP_PERF_XTENSA_STARTING, > CPUHP_AP_PERF_METAG_STARTING, > CPUHP_AP_MIPS_OP_LOONGSON3_STARTING, > + CPUHP_AP_SDEI_STARTING, Nitpick: how generic is this as to apply to other architectures? Probably not, so shall we prefix this with ARM_? Not actually a strong preferences but similar question for the definitions in the sdei.h files (and maybe the filenames themselves).
Hi Catalin, On 16/10/17 14:41, Catalin Marinas wrote: > On Fri, Sep 22, 2017 at 07:26:10PM +0100, James Morse wrote: >> diff --git a/arch/arm64/kernel/sdei-entry.S b/arch/arm64/kernel/sdei-entry.S >> new file mode 100644 >> index 000000000000..cf12f8da0789 >> --- /dev/null >> +++ b/arch/arm64/kernel/sdei-entry.S >> @@ -0,0 +1,122 @@ >> +/* >> + * Software Delegated Exception entry point from firmware to the kernel. >> + * >> + * Copyright (C) 2017 ARM Ltd. >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 as >> + * published by the Free Software Foundation. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + * >> + * You should have received a copy of the GNU General Public License >> + * along with this program. If not, see <http://www.gnu.org/licenses/>. >> + */ >> + >> +#include <linux/linkage.h> >> + >> +#include <asm/alternative.h> >> +#include <asm/asm-offsets.h> >> +#include <asm/assembler.h> >> +#include <asm/memory.h> >> +#include <asm/ptrace.h> >> +#include <asm/sdei.h> >> +#include <uapi/linux/sdei.h> >> + >> +/* >> + * Software Delegated Exception entry point. >> + * >> + * x0: Event number > > Currently the only event number is 0. Shall we plan for having other > events in the future or we just ignore this argument? '0' is the only event number specified by the SDEI specification. For use with RAS the event number is read from the HEST. (and there may me more than one of them). >> + * x1: struct sdei_registered_event argument from registration time. >> + * x2: interrupted PC >> + * x3: interrupted PSTATE > [...] >> +/* >> + * __sdei_handler() returns one of: >> + * SDEI_EV_HANDLED - success, return to the interrupted context. >> + * SDEI_EV_FAILED - failure, return this error code to firmare. >> + * virtual-address - success, return to this address. >> + */ >> +static __kprobes unsigned long _sdei_handler(struct pt_regs *regs, >> + struct sdei_registered_event *arg) >> +{ >> + u32 mode; >> + int i, err = 0; >> + int clobbered_registers = 4; > Maybe const int here if you want to avoid magic numbers in the 'for' > loop below. Otherwise it looks like some variable you intend to modify > in this function. Sure. (this was modified in my various attempts to get this working on non-vhe systems with KVM). >> + u64 elr = read_sysreg(elr_el1); >> + u32 kernel_mode = read_sysreg(CurrentEL) | 1; /* +SPSel */ >> + unsigned long vbar = read_sysreg(vbar_el1); >> + >> + /* Retrieve the missing registers values */ >> + for (i = 0; i < clobbered_registers; i++) { >> + /* from within the handler, this call always succeeds */ >> + sdei_api_event_context(i, ®s->regs[i]); >> + } >> + >> + /* >> + * We didn't take an exception to get here, set PAN. UAO will be cleared >> + * by sdei_event_handler()s set_fs(USER_DS) call. >> + */ >> + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, >> + CONFIG_ARM64_PAN)); > Can you use uaccess_disable() directly? Wouldn't this invoke sw-pan's __uaccess_ttbr0_disable(): > write_sysreg(ttbr, ttbr0_el1); Probing depends on VHE if booted at EL2, can we guarantee to have PAN (and therefore not-SW-PAN) too? (otherwise I can add 'depends on !ARM64_SW_TTBR0_PAN' to the Kconfig) >> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig >> index d8a9859f6102..1f6633b337aa 100644 >> --- a/drivers/firmware/Kconfig >> +++ b/drivers/firmware/Kconfig >> @@ -50,6 +50,7 @@ config ARM_SCPI_POWER_DOMAIN >> >> config ARM_SDE_INTERFACE >> bool "ARM Software Delegated Exception Interface (SDEI)" >> + depends on ARM64 >> help >> The Software Delegated Exception Interface (SDEI) is an ARM >> standard for registering callbacks from the platform firmware >> diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c >> index 4b3c7fd99c34..3ea6a19ae439 100644 >> --- a/drivers/firmware/arm_sdei.c >> +++ b/drivers/firmware/arm_sdei.c >> @@ -154,6 +154,7 @@ int sdei_api_event_context(u32 query, u64 *result) >> return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_CONTEXT, query, 0, 0, 0, 0, >> result); >> } >> +NOKPROBE_SYMBOL(sdei_api_event_context); > Should this be part of the patch introducing arm_sdei.c? Yes. >> static int sdei_api_event_get_info(u32 event, u32 info, u64 *result) >> { >> diff --git a/include/linux/sdei.h b/include/linux/sdei.h >> index bb3dd000771e..df3fe6373e32 100644 >> --- a/include/linux/sdei.h >> +++ b/include/linux/sdei.h >> @@ -32,6 +32,8 @@ enum sdei_conduit_types { >> CONDUIT_HVC, >> }; >> >> +#include <asm/sdei.h> >> + >> /* Arch code should override this to set the entry point from firmware... */ >> #ifndef sdei_arch_get_entry_point >> #define sdei_arch_get_entry_point(conduit) (0) > > Same here. This should not be built before the Kconfig change anyway. (I've been building this on x86 to check I'd not done anything arm64 specific outside the arch code...) Sure, I'll move this hunk and the Kconfig create a place holder asm/sdei.h in the earlier patch. Thanks, James -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Catalin, On 13/10/17 16:42, Catalin Marinas wrote: > On Fri, Sep 22, 2017 at 07:26:09PM +0100, James Morse wrote: >> diff --git a/arch/arm64/include/asm/vmap_stack.h b/arch/arm64/include/asm/vmap_stack.h >> new file mode 100644 >> index 000000000000..f41d043cac31 >> --- /dev/null >> +++ b/arch/arm64/include/asm/vmap_stack.h >> @@ -0,0 +1,41 @@ >> +#ifndef __ASM_VMAP_STACK_H >> +#define __ASM_VMAP_STACK_H >> + >> +#include <linux/vmalloc.h> >> +#include <asm/memory.h> >> +#include <asm/pgtable.h> >> +#include <asm/thread_info.h> >> + >> +#ifdef CONFIG_VMAP_STACK >> +/* >> + * To ensure that VMAP'd stack overflow detection works correctly, all VMAP'd >> + * stacks need to have the same alignment. >> + */ >> +static inline unsigned long *arch_alloc_vmap_stack(size_t stack_size, int node) >> +{ >> + return __vmalloc_node_range(stack_size, THREAD_ALIGN, >> + VMALLOC_START, VMALLOC_END, >> + THREADINFO_GFP, PAGE_KERNEL, 0, node, >> + __builtin_return_address(0)); >> +} >> + >> +#else >> +unsigned long *arch_alloc_vmap_stack(size_t stack_size, int node); // link error > Do you actually need this here? The calling site (at least in this > patch), is surrounded by CONFIG_VMAP_STACK. Removing the dummy > declaration should be fine (I haven't read the rest of the patches yet, > maybe it's needed later; This was to avoid having to #ifdef the calling site I add in a later patch. > would a BUILD_BUG do?). Ah, you can put those in header files, yes that would be clearer. Thanks, James -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Catalin, On 16/10/17 14:52, Catalin Marinas wrote: > On Fri, Sep 22, 2017 at 07:26:11PM +0100, James Morse wrote: >> diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h >> index f24bfb2b9a2d..466b949474df 100644 >> --- a/include/linux/cpuhotplug.h >> +++ b/include/linux/cpuhotplug.h >> @@ -88,6 +88,7 @@ enum cpuhp_state { >> CPUHP_AP_PERF_XTENSA_STARTING, >> CPUHP_AP_PERF_METAG_STARTING, >> CPUHP_AP_MIPS_OP_LOONGSON3_STARTING, >> + CPUHP_AP_SDEI_STARTING, > > Nitpick: how generic is this as to apply to other architectures? > Probably not, so shall we prefix this with ARM_? This may get used on 32bit ARM. I blindly copied PSCI, which doesn't have a prefix. But it makes sense to have one. > Not actually a strong preferences but similar question for the > definitions in the sdei.h files (and maybe the filenames themselves). Thanks, James -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Catalin, On 16/10/17 10:58, Catalin Marinas wrote: > On Fri, Oct 13, 2017 at 05:50:45PM +0100, James Morse wrote: >> On 13/10/17 16:31, Catalin Marinas wrote: >>> On Fri, Sep 22, 2017 at 07:26:05PM +0100, James Morse wrote: >>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c >>>> index cd52d365d1f0..8e4c7da2b126 100644 >>>> --- a/arch/arm64/kernel/cpufeature.c >>>> +++ b/arch/arm64/kernel/cpufeature.c >> >>>> @@ -1308,3 +1309,25 @@ static int __init enable_mrs_emulation(void) >>>> } >>>> >>>> late_initcall(enable_mrs_emulation); >>>> + >>>> +int cpu_copy_el2regs(void *__unused) >>>> +{ >>>> + int do_copyregs = 0; >>>> + >>>> + /* >>>> + * Copy register values that aren't redirected by hardware. >>>> + * >>>> + * Before code patching, we only set tpidr_el1, all CPUs need to copy >>>> + * this value to tpidr_el2 before we patch the code. Once we've done >>>> + * that, freshly-onlined CPUs will set tpidr_el2, so we don't need to >>>> + * do anything here. >>>> + */ >>>> + asm volatile(ALTERNATIVE("mov %0, #1", "mov %0, #0", >>>> + ARM64_HAS_VIRT_HOST_EXTN) >>>> + : "=r" (do_copyregs) : : ); >>> >>> Can you just do: >>> >>> if (cpu_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN)) >>> write_sysreg(read_sysreg(tpidr_el1), tpidr_el2); >>> >>> At this point the capability bits should be set and the jump labels >>> enabled. >> >> These are enabled too early, we haven't done patching yet. >> >> We need to copy tpidr_el1 -> tpidr_el2 on all CPUs that are online before code >> patching. >> >> After code patching new CPUs set tpidr_el2 when they come online, so we don't >> need to do the copy... but this enable method is still called. There is nothing >> for us to do, and tpidr_el1 now contains junk, so the copy > Ah, I get it now (should've read the comment but I usually expect the > code to be obvious; it wasn't, at least to me, in this case ;)). > You could have added the sysreg copying directly in the asm volatile. I was trying to stick to the sysreg C accessors, and thought there would be more registers that needed copying. (I discovered this VHE doesn't remap all the _ELx registers quite late.) > Anyway, I think it's better if we keep it entirely in C with this hunk > (untested): [...] Yes, that looks much better. I got tangled up in 'which alternative', but you're right, they are all applied in one go so it doesn't matter. > if (!READ_ONCE(alternatives_applied)) > write_sysreg(read_sysreg(tpidr_el1), tpidr_el2); I don't think this READ_ONCE() is needed, that only matters within the stop_machine()/alternatives-patching code that modifies the value on one CPU. Thanks, James -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, Oct 17, 2017 at 05:34:13PM +0100, James Morse wrote: > On 16/10/17 14:41, Catalin Marinas wrote: > > On Fri, Sep 22, 2017 at 07:26:10PM +0100, James Morse wrote: > >> + u64 elr = read_sysreg(elr_el1); > >> + u32 kernel_mode = read_sysreg(CurrentEL) | 1; /* +SPSel */ > >> + unsigned long vbar = read_sysreg(vbar_el1); > >> + > >> + /* Retrieve the missing registers values */ > >> + for (i = 0; i < clobbered_registers; i++) { > >> + /* from within the handler, this call always succeeds */ > >> + sdei_api_event_context(i, ®s->regs[i]); > >> + } > >> + > >> + /* > >> + * We didn't take an exception to get here, set PAN. UAO will be cleared > >> + * by sdei_event_handler()s set_fs(USER_DS) call. > >> + */ > >> + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, > >> + CONFIG_ARM64_PAN)); > > > Can you use uaccess_disable() directly? > > Wouldn't this invoke sw-pan's __uaccess_ttbr0_disable(): > > write_sysreg(ttbr, ttbr0_el1); > > Probing depends on VHE if booted at EL2, can we guarantee to have PAN (and > therefore not-SW-PAN) too? > > (otherwise I can add 'depends on !ARM64_SW_TTBR0_PAN' to the Kconfig) We want the Kconfig to be able to include all features. What you can do though is: select ARM64_PAN if ARM64_SW_TTBR0_PAN With VHE (ARMv8.2) we can guarantee that hardware PAN is around.