[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [UNIKRAFT PATCH v2 1/4] plat/kvm: toggle PKE bit if HAVE_X86PKU is enabled
Provided that PKU is advertised by cpuid (EAX=7, ECX=0, ECX bit 4), Memory Protection Keys can be enabled by setting bit 22 (PKE) in CR4 (see Intel 64 and IA-32 Architectures Software Developer's Manual Vol. 3A, Section 2.5 'Control Registers'). Since we do not want to pay the cost of MPK-related code when MPK is not enabled, we introduce a new HAVE_X86PKU property; MPK code is compile-guarded so that it does not get compiled in without HAVE_X86PKU. HAVE_X86PKU will be set by PKU kernel libraries later on. At boot time, if HAVE_X86PKU is enabled, the kernel now checks whether PKU is advertised by cpuid. If not, it aborts the boot process. The underlying idea is that images compiled with HAVE_X86PKU are *specialized* to be executed on PKU-enabled hardware. Hence, provided that HAVE_X86PKU is set, there is a guarantee that PKU is supported *and* enabled, effectively removing the need for checks later at runtime. This might benefit performance when the domain switching rate is high. Signed-off-by: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxxxxxxxxx> --- lib/Config.uk | 4 ++++ plat/common/include/x86/cpu.h | 15 +++++++++++++++ plat/common/include/x86/cpu_defs.h | 3 +++ plat/kvm/x86/entry64.S | 12 ++++++++++++ plat/kvm/x86/setup.c | 4 ++++ 5 files changed, 38 insertions(+) diff --git a/lib/Config.uk b/lib/Config.uk index e83ed30b..dac2d2fa 100644 --- a/lib/Config.uk +++ b/lib/Config.uk @@ -28,3 +28,7 @@ config HAVE_NW_STACK config HAVE_SYSCALL bool default n + +config HAVE_X86PKU + bool + default n diff --git a/plat/common/include/x86/cpu.h b/plat/common/include/x86/cpu.h index 5f1a35e4..d4c02e08 100644 --- a/plat/common/include/x86/cpu.h +++ b/plat/common/include/x86/cpu.h @@ -341,4 +341,19 @@ static inline void _init_syscall(void) } #endif /* CONFIG_HAVE_SYSCALL */ +#if CONFIG_HAVE_X86PKU +static inline void _check_ospke(void) +{ + __u32 eax, ebx, ecx, edx; + cpuid(0x7, 0, &eax, &ebx, &ecx, &edx); + if (!(ecx & X86_CPUID7_ECX_OSPKE)) { + /* if PKU is not enabled, abort the boot process. Images + * compiled with HAVE_X86PKU are *specialized* to be executed on + * PKU-enabled hardware. This allows us to avoid checks later at + * runtime. */ + UK_CRASH("CPU does not support PKU!\n"); + } +} +#endif /* CONFIG_HAVE_X86PKU */ + #endif /* __PLAT_COMMON_X86_CPU_H__ */ diff --git a/plat/common/include/x86/cpu_defs.h b/plat/common/include/x86/cpu_defs.h index dcbe2c65..74cff459 100644 --- a/plat/common/include/x86/cpu_defs.h +++ b/plat/common/include/x86/cpu_defs.h @@ -71,6 +71,7 @@ #define X86_CR4_OSXMMEXCPT (1 << 10) /* OS support for FP exceptions */ #define X86_CR4_FSGSBASE (1 << 16) /* enable FSGSBASE*/ #define X86_CR4_OSXSAVE (1 << 18) /* enable XSAVE, extended states */ +#define X86_CR4_PKE (1 << 22) /* enable protection keys */ /* * Intel CPU features in EFER @@ -86,6 +87,8 @@ #define X86_CPUID1_EDX_SSE (1 << 25) /* CPUID feature bits in EBX and ECX when EAX=7, ECX=0 */ #define X86_CPUID7_EBX_FSGSBASE (1 << 0) +#define X86_CPUID7_ECX_PKU (1 << 3) +#define X86_CPUID7_ECX_OSPKE (1 << 4) /* CPUID feature bits when EAX=0xd, ECX=1 */ #define X86_CPUIDD1_EAX_XSAVEOPT (1<<0) /* CPUID 80000001H:EDX feature list */ diff --git a/plat/kvm/x86/entry64.S b/plat/kvm/x86/entry64.S index 169f4c82..ef5e0e77 100644 --- a/plat/kvm/x86/entry64.S +++ b/plat/kvm/x86/entry64.S @@ -31,6 +31,9 @@ #include <kvm-x86/traps.h> #include <kvm-x86/multiboot_defs.h> +/* necessary for CONFIG_ macros to be accessible */ +#include <uk/config.h> + #define ENTRY(x) .globl x; .type x,%function; x: #define END(x) .size x, . - x @@ -227,6 +230,15 @@ noxsave: orl $(X86_CR4_FSGSBASE), %edi movq %rdi, %cr4 nofsgsbase: +#if CONFIG_HAVE_X86PKU + /* check for Memory Protection Keys (PKU) */ + testl $(X86_CPUID7_ECX_PKU), %ecx + jz nopku + /* if PKU is supported, enable it via CR4 */ + orl $(X86_CR4_PKE), %edi + movq %rdi, %cr4 +nopku: +#endif /* CONFIG_HAVE_X86PKU */ /* done setting up CPU capabilities */ /* read multiboot info pointer */ diff --git a/plat/kvm/x86/setup.c b/plat/kvm/x86/setup.c index 284ec793..e8c44a93 100644 --- a/plat/kvm/x86/setup.c +++ b/plat/kvm/x86/setup.c @@ -329,6 +329,10 @@ void _libkvmplat_entry(void *arg) _init_syscall(); #endif /* CONFIG_HAVE_SYSCALL */ +#if CONFIG_HAVE_X86PKU + _check_ospke(); +#endif /* CONFIG_HAVE_X86PKU */ + /* * Switch away from the bootstrap stack as early as possible. */ -- 2.20.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |