[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [UNIKRAFT PATCH v2 1/4] plat/kvm: toggle PKE bit if HAVE_X86PKU is enabled
În vin., 11 dec. 2020 la 18:35, Hugo Lefeuvre < hle@xxxxxxxxxx> a scris: 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
|