* [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests
@ 2014-04-28 15:22 Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 01/18] libcflat: move stringification trick to a common place Paolo Bonzini
` (18 more replies)
0 siblings, 19 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
This series is structured as follows:
- patches 1 to 8 cleanup lib/x86/, remove gratuitous differences
between 32-bit and 64-bit, and unify code that is duplicated in
various ways
- patches 9 to 12 port some eventinj tests so that they run as
64-bit hosts too
- patches 13 to 15 are cleanups
- patches 16 to 18 add a testcase for SMAP (tested with QEMU by me
and, by the patch submitter, with KVM)
Paolo Bonzini (18):
libcflat: move stringification trick to a common place
x86: move size #defines to processor.h
x86: desc: change set_gdt_entry argument to selector
x86: desc: move idt_entry_t and gdt_entry_t to header
x86: desc: reuse cstart.S GDT and TSS
x86: taskswitch: use desc library
x86: unify GDT format between 32-bit and 64-bit
x86: move CR0 and CR4 constants to processor.h
x86: desc: support ISTs for alternate stacks in 64-bit mode
x86: eventinj: fix inline assembly and make it more robust to new compilers
x86: eventinj: enable NP test in 64-bit mode
x86: eventinj: port consecutive exception tests to x86-64
x86: xsave: use cpuid functions from processor.h
x86: svm: rename get_pte function
x86: vm: remove dead code
x86: vm: export get_pte and return a pointer to it
x86: vm: mark intermediate PTEs as user-accessible
x86: smap: new testcase
config-x86-common.mak | 4 +-
lib/libcflat.h | 3 +
lib/x86/desc.c | 166 +++++++++++++++++---------------------------------
lib/x86/desc.h | 80 ++++++++++++++++++++----
lib/x86/isr.c | 6 --
lib/x86/processor.h | 38 +++++++++++-
lib/x86/vm.c | 60 +++++++-----------
lib/x86/vm.h | 42 +++----------
x86/asyncpf.c | 1 -
x86/cstart.S | 16 +++++
x86/cstart64.S | 17 ++++--
x86/eventinj.c | 87 ++++++++++++++++----------
x86/pcid.c | 7 ---
x86/smap.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++
x86/svm.c | 18 +++---
x86/taskswitch.c | 134 +++-------------------------------------
x86/taskswitch2.c | 19 +++---
x86/vmexit.c | 6 --
x86/vmx.c | 32 +++++-----
x86/xsave.c | 58 ++----------------
20 files changed, 485 insertions(+), 465 deletions(-)
create mode 100644 x86/smap.c
--
1.8.3.1
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 01/18] libcflat: move stringification trick to a common place
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 02/18] x86: move size #defines to processor.h Paolo Bonzini
` (17 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Rename "str" to "xxstr" to avoid a conflict with lib/x86/processor.h.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/libcflat.h | 3 +++
x86/taskswitch2.c | 3 ---
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/libcflat.h b/lib/libcflat.h
index f734fde..3dc3788 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -22,6 +22,9 @@
#include <stdarg.h>
+#define xstr(s) xxstr(s)
+#define xxstr(s) #s
+
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
diff --git a/x86/taskswitch2.c b/x86/taskswitch2.c
index 3c8418e..08bcce9 100644
--- a/x86/taskswitch2.c
+++ b/x86/taskswitch2.c
@@ -9,9 +9,6 @@
#define MAIN_TSS_INDEX (FREE_GDT_INDEX + 0)
#define VM86_TSS_INDEX (FREE_GDT_INDEX + 1)
-#define xstr(s) str(s)
-#define str(s) #s
-
static volatile int test_count;
static volatile unsigned int test_divider;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 02/18] x86: move size #defines to processor.h
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 01/18] libcflat: move stringification trick to a common place Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 03/18] x86: desc: change set_gdt_entry argument to selector Paolo Bonzini
` (16 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
These are necessary in many testcases that includes hand-written
assembly, otherwise they will only run for either 32- or 64-bit.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/x86/desc.c | 10 ----------
lib/x86/isr.c | 6 ------
lib/x86/processor.h | 11 +++++++++++
x86/vmexit.c | 6 ------
4 files changed, 11 insertions(+), 22 deletions(-)
diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index f75ec1d..ac60686 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -101,16 +101,6 @@ void do_handle_exception(struct ex_regs *regs)
exit(7);
}
-#ifdef __x86_64__
-# define R "r"
-# define W "q"
-# define S "8"
-#else
-# define R "e"
-# define W "l"
-# define S "4"
-#endif
-
#define EX(NAME, N) extern char NAME##_fault; \
asm (".pushsection .text \n\t" \
#NAME"_fault: \n\t" \
diff --git a/lib/x86/isr.c b/lib/x86/isr.c
index 9986d17..7dcd38a 100644
--- a/lib/x86/isr.c
+++ b/lib/x86/isr.c
@@ -3,12 +3,6 @@
#include "vm.h"
#include "desc.h"
-#ifdef __x86_64__
-# define R "r"
-#else
-# define R "e"
-#endif
-
extern char isr_entry_point[];
asm (
diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index 29811d4..fabd480 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -4,6 +4,17 @@
#include "libcflat.h"
#include <stdint.h>
+#ifdef __x86_64__
+# define R "r"
+# define W "q"
+# define S "8"
+#else
+# define R "e"
+# define W "l"
+# define S "4"
+#endif
+
+
struct descriptor_table_ptr {
u16 limit;
ulong base;
diff --git a/x86/vmexit.c b/x86/vmexit.c
index cc24738..3bd0c81 100644
--- a/x86/vmexit.c
+++ b/x86/vmexit.c
@@ -47,12 +47,6 @@ static unsigned int inl(unsigned short port)
static int nr_cpus;
-#ifdef __x86_64__
-# define R "r"
-#else
-# define R "e"
-#endif
-
static void cpuid_test(void)
{
asm volatile ("push %%"R "bx; cpuid; pop %%"R "bx"
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 03/18] x86: desc: change set_gdt_entry argument to selector
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 01/18] libcflat: move stringification trick to a common place Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 02/18] x86: move size #defines to processor.h Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 04/18] x86: desc: move idt_entry_t and gdt_entry_t to header Paolo Bonzini
` (15 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
This interface, already used in taskswitch.c, is a bit easier to use.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/x86/desc.c | 20 +++++++++++---------
lib/x86/desc.h | 8 +++++---
x86/taskswitch2.c | 15 +++++++--------
3 files changed, 23 insertions(+), 20 deletions(-)
diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index ac60686..b8b5452 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -228,10 +228,11 @@ unsigned exception_error_code(void)
*/
static gdt_entry_t gdt[10];
-#define TSS_GDT_OFFSET 4
-void set_gdt_entry(int num, u32 base, u32 limit, u8 access, u8 gran)
+void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran)
{
+ int num = sel >> 3;
+
/* Setup the descriptor base address */
gdt[num].base_low = (base & 0xFFFF);
gdt[num].base_middle = (base >> 16) & 0xFF;
@@ -261,15 +262,15 @@ void setup_gdt(void)
/* The second entry is our Code Segment. The base address
* is 0, the limit is 4GBytes, it uses 4KByte granularity,
* uses 32-bit opcodes, and is a Code Segment descriptor. */
- set_gdt_entry(1, 0, 0xFFFFFFFF, 0x9A, 0xcf);
+ set_gdt_entry(KERNEL_CS, 0, 0xFFFFFFFF, 0x9A, 0xcf);
/* The third entry is our Data Segment. It's EXACTLY the
* same as our code segment, but the descriptor type in
* this entry's access byte says it's a Data Segment */
- set_gdt_entry(2, 0, 0xFFFFFFFF, 0x92, 0xcf);
+ set_gdt_entry(KERNEL_DS, 0, 0xFFFFFFFF, 0x92, 0xcf);
/* Same as code register above but not present */
- set_gdt_entry(3, 0, 0xFFFFFFFF, 0x1A, 0xcf);
+ set_gdt_entry(NP_SEL, 0, 0xFFFFFFFF, 0x1A, 0xcf);
/* Flush out the old GDT and install the new changes! */
@@ -280,7 +281,7 @@ void setup_gdt(void)
"mov %0, %%fs\n\t"
"mov %0, %%gs\n\t"
"mov %0, %%ss\n\t"
- "jmp $0x08, $.Lflush2\n\t"
+ "jmp $" xstr(KERNEL_CS), $.Lflush2\n\t"
".Lflush2: "::"r"(0x10));
}
@@ -315,10 +316,11 @@ void setup_tss32(void)
tss[i].ss0 = tss[i].ss1 = tss[i].ss2 = 0x10;
tss[i].esp = tss[i].esp0 = tss[i].esp1 = tss[i].esp2 =
(u32)tss_stack[i] + 4096;
- tss[i].cs = 0x08;
- tss[i].ds = tss[i].es = tss[i].fs = tss[i].gs = tss[i].ss = 0x10;
+ tss[i].cs = KERNEL_CS;
+ tss[i].ds = tss[i].es = tss[i].fs = tss[i].gs =
+ tss[i].ss = KERNEL_DS;
tss[i].iomap_base = (u16)desc_size;
- set_gdt_entry(TSS_GDT_OFFSET + i, (u32)&tss[i],
+ set_gdt_entry(TSS_MAIN + (i << 3), (u32)&tss[i],
desc_size - 1, 0x89, 0x0f);
}
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index b795aad..e3f1ea0 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -71,16 +71,18 @@ typedef struct {
#define UD_VECTOR 6
#define GP_VECTOR 13
+#define KERNEL_CS 0x08
+#define KERNEL_DS 0x10
+#define NP_SEL 0x18
#define TSS_MAIN 0x20
#define TSS_INTR 0x28
-
-#define NP_SEL 0x18
+#define FIRST_SPARE_SEL 0x30
unsigned exception_vector(void);
unsigned exception_error_code(void);
void set_idt_entry(int vec, void *addr, int dpl);
void set_idt_sel(int vec, u16 sel);
-void set_gdt_entry(int num, u32 base, u32 limit, u8 access, u8 gran);
+void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran);
void set_idt_task_gate(int vec, u16 sel);
void set_intr_task_gate(int e, void *fn);
void print_current_tss_info(void);
diff --git a/x86/taskswitch2.c b/x86/taskswitch2.c
index 08bcce9..de7e969 100644
--- a/x86/taskswitch2.c
+++ b/x86/taskswitch2.c
@@ -5,9 +5,8 @@
#include "processor.h"
#include "vm.h"
-#define FREE_GDT_INDEX 6
-#define MAIN_TSS_INDEX (FREE_GDT_INDEX + 0)
-#define VM86_TSS_INDEX (FREE_GDT_INDEX + 1)
+#define MAIN_TSS_SEL (FIRST_SPARE_SEL + 0)
+#define VM86_TSS_SEL (FIRST_SPARE_SEL + 8)
static volatile int test_count;
static volatile unsigned int test_divider;
@@ -217,15 +216,15 @@ void test_vm86_switch(void)
vm86_start[1] = 0x0b;
/* Main TSS */
- set_gdt_entry(MAIN_TSS_INDEX, (u32)&main_tss, sizeof(tss32_t) - 1, 0x89, 0);
- ltr(MAIN_TSS_INDEX << 3);
+ set_gdt_entry(MAIN_TSS_SEL, (u32)&main_tss, sizeof(tss32_t) - 1, 0x89, 0);
+ ltr(MAIN_TSS_SEL);
main_tss = (tss32_t) {
- .prev = VM86_TSS_INDEX << 3,
+ .prev = VM86_TSS_SEL,
.cr3 = read_cr3(),
};
/* VM86 TSS (marked as busy, so we can iret to it) */
- set_gdt_entry(VM86_TSS_INDEX, (u32)&vm86_tss, sizeof(tss32_t) - 1, 0x8b, 0);
+ set_gdt_entry(VM86_TSS_SEL, (u32)&vm86_tss, sizeof(tss32_t) - 1, 0x8b, 0);
vm86_tss = (tss32_t) {
.eflags = 0x20002,
.cr3 = read_cr3(),
@@ -236,7 +235,7 @@ void test_vm86_switch(void)
};
/* Setup task gate to main TSS for #UD */
- set_idt_task_gate(6, MAIN_TSS_INDEX << 3);
+ set_idt_task_gate(6, MAIN_TSS_SEL);
/* Jump into VM86 task with iret, #UD lets it come back immediately */
printf("Switch to VM86 task and back\n");
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 04/18] x86: desc: move idt_entry_t and gdt_entry_t to header
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (2 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 03/18] x86: desc: change set_gdt_entry argument to selector Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 05/18] x86: desc: reuse cstart.S GDT and TSS Paolo Bonzini
` (14 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/x86/desc.c | 27 ---------------------------
lib/x86/desc.h | 27 +++++++++++++++++++++++++++
2 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index b8b5452..32034cf 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -2,33 +2,6 @@
#include "desc.h"
#include "processor.h"
-typedef struct {
- unsigned short offset0;
- unsigned short selector;
- unsigned short ist : 3;
- unsigned short : 5;
- unsigned short type : 4;
- unsigned short : 1;
- unsigned short dpl : 2;
- unsigned short p : 1;
- unsigned short offset1;
-#ifdef __x86_64__
- unsigned offset2;
- unsigned reserved;
-#endif
-} idt_entry_t;
-
-typedef struct {
- u16 limit_low;
- u16 base_low;
- u8 base_middle;
- u8 access;
- u8 granularity;
- u8 base_high;
-} gdt_entry_t;
-
-extern idt_entry_t boot_idt[256];
-
void set_idt_entry(int vec, void *addr, int dpl)
{
idt_entry_t *e = &boot_idt[vec];
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index e3f1ea0..0614273 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -78,6 +78,33 @@ typedef struct {
#define TSS_INTR 0x28
#define FIRST_SPARE_SEL 0x30
+typedef struct {
+ unsigned short offset0;
+ unsigned short selector;
+ unsigned short ist : 3;
+ unsigned short : 5;
+ unsigned short type : 4;
+ unsigned short : 1;
+ unsigned short dpl : 2;
+ unsigned short p : 1;
+ unsigned short offset1;
+#ifdef __x86_64__
+ unsigned offset2;
+ unsigned reserved;
+#endif
+} idt_entry_t;
+
+typedef struct {
+ u16 limit_low;
+ u16 base_low;
+ u8 base_middle;
+ u8 access;
+ u8 granularity;
+ u8 base_high;
+} gdt_entry_t;
+
+extern idt_entry_t boot_idt[256];
+
unsigned exception_vector(void);
unsigned exception_error_code(void);
void set_idt_entry(int vec, void *addr, int dpl);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 05/18] x86: desc: reuse cstart.S GDT and TSS
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (3 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 04/18] x86: desc: move idt_entry_t and gdt_entry_t to header Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 06/18] x86: taskswitch: use desc library Paolo Bonzini
` (13 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
There is no particular reason to use a specific TSS in tests that
use task-switching. In fact, in many cases the tests just want
a separate interrupt stack and could run on 64-bit just as well
if the task-switching is abstracted.
As a first step, remove duplicate protected mode setup from desc.c's
users. Just leave some spare selectors in cstart.S's GDT before
the CPUs' main TSS. Then reuse CPU 0's TSS as TSS_MAIN.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/x86/desc.c | 98 ++++++++++++++-----------------------------------------
lib/x86/desc.h | 13 +++++---
x86/asyncpf.c | 1 -
x86/cstart.S | 16 +++++++++
x86/eventinj.c | 1 -
x86/taskswitch2.c | 1 -
6 files changed, 49 insertions(+), 81 deletions(-)
diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index 32034cf..812295c 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -193,69 +193,28 @@ unsigned exception_error_code(void)
* 0x00 - NULL descriptor
* 0x08 - Code segment
* 0x10 - Data segment
- * 0x18 - Not presend code segment
- * 0x20 - Primery task
- * 0x28 - Interrupt task
- *
- * 0x30 to 0x48 - Free to use for test cases
+ * 0x18 - Not present code segment
+ * 0x20 - Interrupt task
+ * 0x28 to 0x78 - Free to use for test cases
+ * 0x80 - Primary task (CPU 0)
*/
-static gdt_entry_t gdt[10];
-
void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran)
{
int num = sel >> 3;
/* Setup the descriptor base address */
- gdt[num].base_low = (base & 0xFFFF);
- gdt[num].base_middle = (base >> 16) & 0xFF;
- gdt[num].base_high = (base >> 24) & 0xFF;
+ gdt32[num].base_low = (base & 0xFFFF);
+ gdt32[num].base_middle = (base >> 16) & 0xFF;
+ gdt32[num].base_high = (base >> 24) & 0xFF;
/* Setup the descriptor limits */
- gdt[num].limit_low = (limit & 0xFFFF);
- gdt[num].granularity = ((limit >> 16) & 0x0F);
+ gdt32[num].limit_low = (limit & 0xFFFF);
+ gdt32[num].granularity = ((limit >> 16) & 0x0F);
/* Finally, set up the granularity and access flags */
- gdt[num].granularity |= (gran & 0xF0);
- gdt[num].access = access;
-}
-
-void setup_gdt(void)
-{
- struct descriptor_table_ptr gp;
- /* Setup the GDT pointer and limit */
- gp.limit = sizeof(gdt) - 1;
- gp.base = (ulong)&gdt;
-
- memset(gdt, 0, sizeof(gdt));
-
- /* Our NULL descriptor */
- set_gdt_entry(0, 0, 0, 0, 0);
-
- /* The second entry is our Code Segment. The base address
- * is 0, the limit is 4GBytes, it uses 4KByte granularity,
- * uses 32-bit opcodes, and is a Code Segment descriptor. */
- set_gdt_entry(KERNEL_CS, 0, 0xFFFFFFFF, 0x9A, 0xcf);
-
- /* The third entry is our Data Segment. It's EXACTLY the
- * same as our code segment, but the descriptor type in
- * this entry's access byte says it's a Data Segment */
- set_gdt_entry(KERNEL_DS, 0, 0xFFFFFFFF, 0x92, 0xcf);
-
- /* Same as code register above but not present */
- set_gdt_entry(NP_SEL, 0, 0xFFFFFFFF, 0x1A, 0xcf);
-
-
- /* Flush out the old GDT and install the new changes! */
- lgdt(&gp);
-
- asm volatile ("mov %0, %%ds\n\t"
- "mov %0, %%es\n\t"
- "mov %0, %%fs\n\t"
- "mov %0, %%gs\n\t"
- "mov %0, %%ss\n\t"
- "jmp $" xstr(KERNEL_CS), $.Lflush2\n\t"
- ".Lflush2: "::"r"(0x10));
+ gdt32[num].granularity |= (gran & 0xF0);
+ gdt32[num].access = access;
}
void set_idt_task_gate(int vec, u16 sel)
@@ -276,46 +235,39 @@ void set_idt_task_gate(int vec, u16 sel)
* 1 - interrupt task
*/
-static tss32_t tss[2];
-static char tss_stack[2][4096];
+static tss32_t tss_intr;
+static char tss_stack[4096];
void setup_tss32(void)
{
u16 desc_size = sizeof(tss32_t);
- int i;
-
- for (i = 0; i < 2; i++) {
- tss[i].cr3 = read_cr3();
- tss[i].ss0 = tss[i].ss1 = tss[i].ss2 = 0x10;
- tss[i].esp = tss[i].esp0 = tss[i].esp1 = tss[i].esp2 =
- (u32)tss_stack[i] + 4096;
- tss[i].cs = KERNEL_CS;
- tss[i].ds = tss[i].es = tss[i].fs = tss[i].gs =
- tss[i].ss = KERNEL_DS;
- tss[i].iomap_base = (u16)desc_size;
- set_gdt_entry(TSS_MAIN + (i << 3), (u32)&tss[i],
- desc_size - 1, 0x89, 0x0f);
- }
- ltr(TSS_MAIN);
+ tss.cr3 = read_cr3();
+ tss_intr.cr3 = read_cr3();
+ tss_intr.ss0 = tss_intr.ss1 = tss_intr.ss2 = 0x10;
+ tss_intr.esp = tss_intr.esp0 = tss_intr.esp1 = tss_intr.esp2 =
+ (u32)tss_stack + 4096;
+ tss_intr.cs = 0x08;
+ tss_intr.ds = tss_intr.es = tss_intr.fs = tss_intr.gs = tss_intr.ss = 0x10;
+ tss_intr.iomap_base = (u16)desc_size;
+ set_gdt_entry(TSS_INTR, (u32)&tss_intr, desc_size - 1, 0x89, 0x0f);
}
void set_intr_task_gate(int e, void *fn)
{
- tss[1].eip = (u32)fn;
+ tss_intr.eip = (u32)fn;
set_idt_task_gate(e, TSS_INTR);
}
void print_current_tss_info(void)
{
u16 tr = str();
- int i = (tr == TSS_MAIN) ? 0 : 1;
if (tr != TSS_MAIN && tr != TSS_INTR)
printf("Unknown TSS %x\n", tr);
else
- printf("TR=%x Main TSS back link %x. Current TSS back link %x\n",
- tr, tss[0].prev, tss[i].prev);
+ printf("TR=%x (%s) Main TSS back link %x. Intr TSS back link %x\n",
+ tr, tr ? "interrupt" : "main", tss.prev, tss_intr.prev);
}
#endif
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index 0614273..e0af335 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -3,10 +3,8 @@
void setup_idt(void);
#ifndef __x86_64__
-void setup_gdt(void);
void setup_tss32(void);
#else
-static inline void setup_gdt(void){}
static inline void setup_tss32(void){}
#endif
@@ -74,9 +72,9 @@ typedef struct {
#define KERNEL_CS 0x08
#define KERNEL_DS 0x10
#define NP_SEL 0x18
-#define TSS_MAIN 0x20
-#define TSS_INTR 0x28
-#define FIRST_SPARE_SEL 0x30
+#define TSS_INTR 0x20
+#define FIRST_SPARE_SEL 0x28
+#define TSS_MAIN 0x80
typedef struct {
unsigned short offset0;
@@ -105,6 +103,11 @@ typedef struct {
extern idt_entry_t boot_idt[256];
+#ifndef __x86_64__
+extern gdt_entry_t gdt32[];
+extern tss32_t tss;
+#endif
+
unsigned exception_vector(void);
unsigned exception_error_code(void);
void set_idt_entry(int vec, void *addr, int dpl);
diff --git a/x86/asyncpf.c b/x86/asyncpf.c
index 95e7741..5d269f7 100644
--- a/x86/asyncpf.c
+++ b/x86/asyncpf.c
@@ -89,7 +89,6 @@ int main(int ac, char **av)
setup_vm();
setup_idt();
- setup_gdt();
printf("install handler\n");
handle_exception(14, pf_isr);
apf_reason = 0;
diff --git a/x86/cstart.S b/x86/cstart.S
index bc8d563..ffa0768 100644
--- a/x86/cstart.S
+++ b/x86/cstart.S
@@ -28,10 +28,25 @@ i = 0
i = i + 1
.endr
+.globl gdt32
gdt32:
.quad 0
.quad 0x00cf9b000000ffff // flat 32-bit code segment
.quad 0x00cf93000000ffff // flat 32-bit data segment
+ .quad 0x00cf1b000000ffff // flat 32-bit code segment, not present
+
+ .quad 0 // 12 spare selectors
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
tss_descr:
.rept max_cpus
@@ -40,6 +55,7 @@ tss_descr:
gdt32_end:
i = 0
+.globl tss
tss:
.rept max_cpus
.long 0
diff --git a/x86/eventinj.c b/x86/eventinj.c
index a218aaf..900cfda 100644
--- a/x86/eventinj.c
+++ b/x86/eventinj.c
@@ -183,7 +183,6 @@ int main()
setup_vm();
setup_idt();
- setup_gdt();
setup_tss32();
handle_irq(32, tirq0);
diff --git a/x86/taskswitch2.c b/x86/taskswitch2.c
index de7e969..92fc941 100644
--- a/x86/taskswitch2.c
+++ b/x86/taskswitch2.c
@@ -252,7 +252,6 @@ int main()
{
setup_vm();
setup_idt();
- setup_gdt();
setup_tss32();
test_kernel_mode_int();
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 06/18] x86: taskswitch: use desc library
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (4 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 05/18] x86: desc: reuse cstart.S GDT and TSS Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 07/18] x86: unify GDT format between 32-bit and 64-bit Paolo Bonzini
` (12 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
The APIs in desc.c make it much simpler to understand what the test
is doing.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/x86/desc.c | 7 ++-
lib/x86/desc.h | 2 +
x86/taskswitch.c | 134 +++++--------------------------------------------------
3 files changed, 18 insertions(+), 125 deletions(-)
diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index 812295c..442c9a1 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -217,6 +217,11 @@ void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran)
gdt32[num].access = access;
}
+void set_gdt_task_gate(u16 sel, u16 tss_sel)
+{
+ set_gdt_entry(sel, tss_sel, 0, 0x85, 0); // task, present
+}
+
void set_idt_task_gate(int vec, u16 sel)
{
idt_entry_t *e = &boot_idt[vec];
@@ -235,7 +240,7 @@ void set_idt_task_gate(int vec, u16 sel)
* 1 - interrupt task
*/
-static tss32_t tss_intr;
+tss32_t tss_intr;
static char tss_stack[4096];
void setup_tss32(void)
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index e0af335..4689474 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -106,6 +106,7 @@ extern idt_entry_t boot_idt[256];
#ifndef __x86_64__
extern gdt_entry_t gdt32[];
extern tss32_t tss;
+extern tss32_t tss_intr;
#endif
unsigned exception_vector(void);
@@ -113,6 +114,7 @@ unsigned exception_error_code(void);
void set_idt_entry(int vec, void *addr, int dpl);
void set_idt_sel(int vec, u16 sel);
void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran);
+void set_gdt_task_gate(u16 tss_sel, u16 sel);
void set_idt_task_gate(int vec, u16 sel);
void set_intr_task_gate(int e, void *fn);
void print_current_tss_info(void);
diff --git a/x86/taskswitch.c b/x86/taskswitch.c
index 8ed8a93..423f51e 100644
--- a/x86/taskswitch.c
+++ b/x86/taskswitch.c
@@ -6,152 +6,38 @@
*/
#include "libcflat.h"
+#include "lib/x86/desc.h"
-#define FIRST_SPARE_SEL 0x18
-
-struct exception_frame {
- unsigned long error_code;
- unsigned long ip;
- unsigned long cs;
- unsigned long flags;
-};
-
-struct tss32 {
- unsigned short prev;
- unsigned short res1;
- unsigned long esp0;
- unsigned short ss0;
- unsigned short res2;
- unsigned long esp1;
- unsigned short ss1;
- unsigned short res3;
- unsigned long esp2;
- unsigned short ss2;
- unsigned short res4;
- unsigned long cr3;
- unsigned long eip;
- unsigned long eflags;
- unsigned long eax, ecx, edx, ebx, esp, ebp, esi, edi;
- unsigned short es;
- unsigned short res5;
- unsigned short cs;
- unsigned short res6;
- unsigned short ss;
- unsigned short res7;
- unsigned short ds;
- unsigned short res8;
- unsigned short fs;
- unsigned short res9;
- unsigned short gs;
- unsigned short res10;
- unsigned short ldt;
- unsigned short res11;
- unsigned short t:1;
- unsigned short res12:15;
- unsigned short iomap_base;
-};
-
-static char main_stack[4096];
-static char fault_stack[4096];
-static struct tss32 main_tss;
-static struct tss32 fault_tss;
-
-static unsigned long long gdt[] __attribute__((aligned(16))) = {
- 0,
- 0x00cf9b000000ffffull,
- 0x00cf93000000ffffull,
- 0, 0, /* TSS segments */
- 0, /* task return gate */
-};
-
-static unsigned long long gdtr;
+#define TSS_RETURN (FIRST_SPARE_SEL)
void fault_entry(void);
static __attribute__((used, regparm(1))) void
fault_handler(unsigned long error_code)
{
- unsigned short *desc;
-
- printf("fault at %x:%x, prev task %x, error code %x\n",
- main_tss.cs, main_tss.eip, fault_tss.prev, error_code);
+ print_current_tss_info();
+ printf("error code %x\n", error_code);
- main_tss.eip += 2;
+ tss.eip += 2;
- desc = (unsigned short *)&gdt[3];
- desc[2] &= ~0x0200;
+ gdt32[TSS_MAIN / 8].access &= ~2;
- desc = (unsigned short *)&gdt[5];
- desc[0] = 0;
- desc[1] = fault_tss.prev;
- desc[2] = 0x8500;
- desc[3] = 0;
+ set_gdt_task_gate(TSS_RETURN, tss_intr.prev);
}
asm (
"fault_entry:\n"
" mov (%esp),%eax\n"
" call fault_handler\n"
- " jmp $0x28, $0\n"
+ " jmp $" xstr(TSS_RETURN) ", $0\n"
);
-static void setup_tss(struct tss32 *tss, void *entry,
- void *stack_base, unsigned long stack_size)
-{
- unsigned long cr3;
- unsigned short cs, ds;
-
- asm ("mov %%cr3,%0" : "=r" (cr3));
- asm ("mov %%cs,%0" : "=r" (cs));
- asm ("mov %%ds,%0" : "=r" (ds));
-
- tss->ss0 = tss->ss1 = tss->ss2 = tss->ss = ds;
- tss->esp0 = tss->esp1 = tss->esp2 = tss->esp =
- (unsigned long)stack_base + stack_size;
- tss->ds = tss->es = tss->fs = tss->gs = ds;
- tss->cs = cs;
- tss->eip = (unsigned long)entry;
- tss->cr3 = cr3;
-}
-
-static void setup_tss_desc(unsigned short tss_sel, struct tss32 *tss)
-{
- unsigned long addr = (unsigned long)tss;
- unsigned short *desc;
-
- desc = (unsigned short *)&gdt[tss_sel/8];
- desc[0] = sizeof(*tss) - 1;
- desc[1] = addr;
- desc[2] = 0x8900 | ((addr & 0x00ff0000) >> 16);
- desc[3] = (addr & 0xff000000) >> 16;
-}
-
-static void set_intr_task(unsigned short tss_sel, int intr, struct tss32 *tss)
-{
- unsigned short *desc = (void *)(intr* sizeof(long) * 2);
-
- setup_tss_desc(tss_sel, tss);
-
- desc[0] = 0;
- desc[1] = tss_sel;
- desc[2] = 0x8500;
- desc[3] = 0;
-}
-
int main(int ac, char **av)
{
const long invalid_segment = 0x1234;
- gdtr = ((unsigned long long)(unsigned long)&gdt << 16) |
- (sizeof(gdt) - 1);
- asm ("lgdt %0" : : "m" (gdtr));
-
- setup_tss(&main_tss, 0, main_stack, sizeof(main_stack));
- setup_tss_desc(FIRST_SPARE_SEL, &main_tss);
- asm ("ltr %0" : : "r" ((unsigned short)FIRST_SPARE_SEL));
-
- setup_tss(&fault_tss, fault_entry, fault_stack, sizeof(fault_stack));
- set_intr_task(FIRST_SPARE_SEL+8, 13, &fault_tss);
+ setup_tss32();
+ set_intr_task_gate(13, fault_entry);
asm (
"mov %0,%%es\n"
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 07/18] x86: unify GDT format between 32-bit and 64-bit
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (5 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 06/18] x86: taskswitch: use desc library Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 08/18] x86: move CR0 and CR4 constants to processor.h Paolo Bonzini
` (11 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Except the TSS, which is 16-bytes in 64-bit mode, we can use the same
structure and share the constants. This will aid in porting tests
to 64-bit.
Multiple bitwidth and ring 3 selectors aren't used yet. I couldn't
make my mind on keeping vs. dropping them, in the end I kept the ring 3
selectors which have a chance of being used for SMAP or paging unit tests.
With this change, vmx.c can start using desc.h's constants and those
in vm.h (why vm.h?) can be dropped.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/x86/desc.c | 12 +++++++-----
lib/x86/desc.h | 6 ++++--
lib/x86/vm.h | 13 -------------
x86/cstart.S | 6 +++---
x86/cstart64.S | 16 ++++++++++++----
x86/vmx.c | 32 ++++++++++++++++----------------
6 files changed, 42 insertions(+), 43 deletions(-)
diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index 442c9a1..ec1fda3 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -191,11 +191,13 @@ unsigned exception_error_code(void)
/*
* GDT, with 6 entries:
* 0x00 - NULL descriptor
- * 0x08 - Code segment
- * 0x10 - Data segment
- * 0x18 - Not present code segment
- * 0x20 - Interrupt task
- * 0x28 to 0x78 - Free to use for test cases
+ * 0x08 - Code segment (ring 0)
+ * 0x10 - Data segment (ring 0)
+ * 0x18 - Not present code segment (ring 0)
+ * 0x20 - Code segment (ring 3)
+ * 0x28 - Data segment (ring 3)
+ * 0x30 - Interrupt task
+ * 0x38 to 0x78 - Free to use for test cases
* 0x80 - Primary task (CPU 0)
*/
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index 4689474..cd41a74 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -72,8 +72,10 @@ typedef struct {
#define KERNEL_CS 0x08
#define KERNEL_DS 0x10
#define NP_SEL 0x18
-#define TSS_INTR 0x20
-#define FIRST_SPARE_SEL 0x28
+#define USER_CS 0x20
+#define USER_DS 0x28
+#define TSS_INTR 0x30
+#define FIRST_SPARE_SEL 0x38
#define TSS_MAIN 0x80
typedef struct {
diff --git a/lib/x86/vm.h b/lib/x86/vm.h
index 6e0ce2b..03a9b4e 100644
--- a/lib/x86/vm.h
+++ b/lib/x86/vm.h
@@ -28,19 +28,6 @@
#define X86_CR4_PAE 0x00000020
#define X86_CR4_PCIDE 0x00020000
-#ifdef __x86_64__
-#define SEL_NULL_DESC 0x0
-#define SEL_KERN_CODE_64 0x8
-#define SEL_KERN_DATA_64 0x10
-#define SEL_USER_CODE_64 0x18
-#define SEL_USER_DATA_64 0x20
-#define SEL_CODE_32 0x28
-#define SEL_DATA_32 0x30
-#define SEL_CODE_16 0x38
-#define SEL_DATA_16 0x40
-#define SEL_TSS_RUN 0x48
-#endif
-
void setup_vm();
void *vmalloc(unsigned long size);
diff --git a/x86/cstart.S b/x86/cstart.S
index ffa0768..f9ba1fe 100644
--- a/x86/cstart.S
+++ b/x86/cstart.S
@@ -34,10 +34,10 @@ gdt32:
.quad 0x00cf9b000000ffff // flat 32-bit code segment
.quad 0x00cf93000000ffff // flat 32-bit data segment
.quad 0x00cf1b000000ffff // flat 32-bit code segment, not present
+ .quad 0x00cffb000000ffff // 64-bit code segment (user)
+ .quad 0x00cff3000000ffff // 64-bit data segment (user)
- .quad 0 // 12 spare selectors
- .quad 0
- .quad 0
+ .quad 0 // 10 spare selectors
.quad 0
.quad 0
.quad 0
diff --git a/x86/cstart64.S b/x86/cstart64.S
index 0fe76da..1a0c85e 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -54,12 +54,20 @@ gdt64:
.quad 0
.quad 0x00af9b000000ffff // 64-bit code segment
.quad 0x00cf93000000ffff // 64-bit data segment
+ .quad 0x00af1b000000ffff // 64-bit code segment, not present
.quad 0x00affb000000ffff // 64-bit code segment (user)
.quad 0x00cff3000000ffff // 64-bit data segment (user)
- .quad 0x00cf9b000000ffff // 32-bit code segment
- .quad 0x00cf92000000ffff // 32-bit code segment
- .quad 0x008F9A000000FFFF // 16-bit code segment
- .quad 0x008F92000000FFFF // 16-bit data segment
+
+ .quad 0 // 10 spare selectors
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
tss_descr:
.rept max_cpus
diff --git a/x86/vmx.c b/x86/vmx.c
index 2278078..1d28c6f 100644
--- a/x86/vmx.c
+++ b/x86/vmx.c
@@ -346,16 +346,16 @@ static void init_vmcs_host(void)
vmcs_write(HOST_CR3, read_cr3());
vmcs_write(HOST_CR4, read_cr4());
vmcs_write(HOST_SYSENTER_EIP, (u64)(&entry_sysenter));
- vmcs_write(HOST_SYSENTER_CS, SEL_KERN_CODE_64);
+ vmcs_write(HOST_SYSENTER_CS, KERNEL_CS);
/* 26.2.3 */
- vmcs_write(HOST_SEL_CS, SEL_KERN_CODE_64);
- vmcs_write(HOST_SEL_SS, SEL_KERN_DATA_64);
- vmcs_write(HOST_SEL_DS, SEL_KERN_DATA_64);
- vmcs_write(HOST_SEL_ES, SEL_KERN_DATA_64);
- vmcs_write(HOST_SEL_FS, SEL_KERN_DATA_64);
- vmcs_write(HOST_SEL_GS, SEL_KERN_DATA_64);
- vmcs_write(HOST_SEL_TR, SEL_TSS_RUN);
+ vmcs_write(HOST_SEL_CS, KERNEL_CS);
+ vmcs_write(HOST_SEL_SS, KERNEL_DS);
+ vmcs_write(HOST_SEL_DS, KERNEL_DS);
+ vmcs_write(HOST_SEL_ES, KERNEL_DS);
+ vmcs_write(HOST_SEL_FS, KERNEL_DS);
+ vmcs_write(HOST_SEL_GS, KERNEL_DS);
+ vmcs_write(HOST_SEL_TR, TSS_MAIN);
vmcs_write(HOST_BASE_TR, tss_descr.base);
vmcs_write(HOST_BASE_GDTR, gdt64_desc.base);
vmcs_write(HOST_BASE_IDTR, idt_descr.base);
@@ -389,7 +389,7 @@ static void init_vmcs_guest(void)
vmcs_write(GUEST_CR0, guest_cr0);
vmcs_write(GUEST_CR3, guest_cr3);
vmcs_write(GUEST_CR4, guest_cr4);
- vmcs_write(GUEST_SYSENTER_CS, SEL_KERN_CODE_64);
+ vmcs_write(GUEST_SYSENTER_CS, KERNEL_CS);
vmcs_write(GUEST_SYSENTER_ESP,
(u64)(guest_syscall_stack + PAGE_SIZE - 1));
vmcs_write(GUEST_SYSENTER_EIP, (u64)(&entry_sysenter));
@@ -397,13 +397,13 @@ static void init_vmcs_guest(void)
vmcs_write(GUEST_EFER, rdmsr(MSR_EFER));
/* 26.3.1.2 */
- vmcs_write(GUEST_SEL_CS, SEL_KERN_CODE_64);
- vmcs_write(GUEST_SEL_SS, SEL_KERN_DATA_64);
- vmcs_write(GUEST_SEL_DS, SEL_KERN_DATA_64);
- vmcs_write(GUEST_SEL_ES, SEL_KERN_DATA_64);
- vmcs_write(GUEST_SEL_FS, SEL_KERN_DATA_64);
- vmcs_write(GUEST_SEL_GS, SEL_KERN_DATA_64);
- vmcs_write(GUEST_SEL_TR, SEL_TSS_RUN);
+ vmcs_write(GUEST_SEL_CS, KERNEL_CS);
+ vmcs_write(GUEST_SEL_SS, KERNEL_DS);
+ vmcs_write(GUEST_SEL_DS, KERNEL_DS);
+ vmcs_write(GUEST_SEL_ES, KERNEL_DS);
+ vmcs_write(GUEST_SEL_FS, KERNEL_DS);
+ vmcs_write(GUEST_SEL_GS, KERNEL_DS);
+ vmcs_write(GUEST_SEL_TR, TSS_MAIN);
vmcs_write(GUEST_SEL_LDTR, 0);
vmcs_write(GUEST_BASE_CS, 0);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 08/18] x86: move CR0 and CR4 constants to processor.h
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (6 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 07/18] x86: unify GDT format between 32-bit and 64-bit Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 09/18] x86: desc: support ISTs for alternate stacks in 64-bit mode Paolo Bonzini
` (10 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Move them together with the inline function that read/write the
control registers.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/x86/processor.h | 14 ++++++++++++++
lib/x86/vm.h | 12 ------------
x86/pcid.c | 7 -------
3 files changed, 14 insertions(+), 19 deletions(-)
diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index fabd480..9cc1112 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -14,6 +14,20 @@
# define S "4"
#endif
+#define X86_CR0_PE 0x00000001
+#define X86_CR0_MP 0x00000002
+#define X86_CR0_TS 0x00000008
+#define X86_CR0_WP 0x00010000
+#define X86_CR0_PG 0x80000000
+#define X86_CR4_VMXE 0x00000001
+#define X86_CR4_TSD 0x00000004
+#define X86_CR4_DE 0x00000008
+#define X86_CR4_PSE 0x00000010
+#define X86_CR4_PAE 0x00000020
+#define X86_CR4_PCIDE 0x00020000
+
+#define X86_IA32_EFER 0xc0000080
+#define X86_EFER_LMA (1UL << 8)
struct descriptor_table_ptr {
u16 limit;
diff --git a/lib/x86/vm.h b/lib/x86/vm.h
index 03a9b4e..0b5b5c7 100644
--- a/lib/x86/vm.h
+++ b/lib/x86/vm.h
@@ -16,18 +16,6 @@
#define PTE_USER (1ull << 2)
#define PTE_ADDR (0xffffffffff000ull)
-#define X86_CR0_PE 0x00000001
-#define X86_CR0_MP 0x00000002
-#define X86_CR0_TS 0x00000008
-#define X86_CR0_WP 0x00010000
-#define X86_CR0_PG 0x80000000
-#define X86_CR4_VMXE 0x00000001
-#define X86_CR4_TSD 0x00000004
-#define X86_CR4_DE 0x00000008
-#define X86_CR4_PSE 0x00000010
-#define X86_CR4_PAE 0x00000020
-#define X86_CR4_PCIDE 0x00020000
-
void setup_vm();
void *vmalloc(unsigned long size);
diff --git a/x86/pcid.c b/x86/pcid.c
index 45adfd5..164e9a1 100644
--- a/x86/pcid.c
+++ b/x86/pcid.c
@@ -7,13 +7,6 @@
#define X86_FEATURE_PCID (1 << 17)
#define X86_FEATURE_INVPCID (1 << 10)
-#define X86_CR0_PG (1 << 31)
-#define X86_CR3_PCID_MASK 0x00000fff
-#define X86_CR4_PCIDE (1 << 17)
-
-#define X86_IA32_EFER 0xc0000080
-#define X86_EFER_LMA (1UL << 8)
-
struct invpcid_desc {
unsigned long pcid : 12;
unsigned long rsv : 52;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 09/18] x86: desc: support ISTs for alternate stacks in 64-bit mode
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (7 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 08/18] x86: move CR0 and CR4 constants to processor.h Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 10/18] x86: eventinj: fix inline assembly and make it more robust to new compilers Paolo Bonzini
` (9 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Introduce a new API that replaces setup_tss32 and set_intr_task_gate
in tests that run in both modes. This will enable three more tests in
eventinj to run in 64-bit mode.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/x86/desc.c | 26 ++++++++++++++++++++++++--
lib/x86/desc.h | 34 ++++++++++++++++++++++++++--------
x86/cstart64.S | 1 +
x86/eventinj.c | 6 +++---
4 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index ec1fda3..9a80f48 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -187,6 +187,8 @@ unsigned exception_error_code(void)
return error_code;
}
+static char intr_alt_stack[4096];
+
#ifndef __x86_64__
/*
* GDT, with 6 entries:
@@ -243,7 +245,6 @@ void set_idt_task_gate(int vec, u16 sel)
*/
tss32_t tss_intr;
-static char tss_stack[4096];
void setup_tss32(void)
{
@@ -253,7 +254,7 @@ void setup_tss32(void)
tss_intr.cr3 = read_cr3();
tss_intr.ss0 = tss_intr.ss1 = tss_intr.ss2 = 0x10;
tss_intr.esp = tss_intr.esp0 = tss_intr.esp1 = tss_intr.esp2 =
- (u32)tss_stack + 4096;
+ (u32)intr_alt_stack + 4096;
tss_intr.cs = 0x08;
tss_intr.ds = tss_intr.es = tss_intr.fs = tss_intr.gs = tss_intr.ss = 0x10;
tss_intr.iomap_base = (u16)desc_size;
@@ -266,6 +267,16 @@ void set_intr_task_gate(int e, void *fn)
set_idt_task_gate(e, TSS_INTR);
}
+void setup_alt_stack(void)
+{
+ setup_tss32();
+}
+
+void set_intr_alt_stack(int e, void *fn)
+{
+ set_intr_task_gate(e, fn);
+}
+
void print_current_tss_info(void)
{
u16 tr = str();
@@ -276,6 +287,17 @@ void print_current_tss_info(void)
printf("TR=%x (%s) Main TSS back link %x. Intr TSS back link %x\n",
tr, tr ? "interrupt" : "main", tss.prev, tss_intr.prev);
}
+#else
+void set_intr_alt_stack(int e, void *addr)
+{
+ set_idt_entry(e, addr, 0);
+ boot_idt[e].ist = 1;
+}
+
+void setup_alt_stack(void)
+{
+ tss.ist1 = (u64)intr_alt_stack + 4096;
+}
#endif
static bool exception;
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index cd41a74..33e721c 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -2,11 +2,7 @@
#define __IDT_TEST__
void setup_idt(void);
-#ifndef __x86_64__
-void setup_tss32(void);
-#else
-static inline void setup_tss32(void){}
-#endif
+void setup_alt_stack(void);
struct ex_regs {
unsigned long rax, rcx, rdx, rbx;
@@ -57,6 +53,24 @@ typedef struct {
u16 iomap_base;
} tss32_t;
+typedef struct __attribute__((packed)) {
+ u32 res1;
+ u64 rsp0;
+ u64 rsp1;
+ u64 rsp2;
+ u64 res2;
+ u64 ist1;
+ u64 ist2;
+ u64 ist3;
+ u64 ist4;
+ u64 ist5;
+ u64 ist6;
+ u64 ist7;
+ u64 res3;
+ u16 res4;
+ u16 iomap_base;
+} tss64_t;
+
#define ASM_TRY(catch) \
"movl $0, %%gs:4 \n\t" \
".pushsection .data.ex \n\t" \
@@ -109,6 +123,12 @@ extern idt_entry_t boot_idt[256];
extern gdt_entry_t gdt32[];
extern tss32_t tss;
extern tss32_t tss_intr;
+void set_gdt_task_gate(u16 tss_sel, u16 sel);
+void set_idt_task_gate(int vec, u16 sel);
+void set_intr_task_gate(int vec, void *fn);
+void setup_tss32(void);
+#else
+extern tss64_t tss;
#endif
unsigned exception_vector(void);
@@ -116,9 +136,7 @@ unsigned exception_error_code(void);
void set_idt_entry(int vec, void *addr, int dpl);
void set_idt_sel(int vec, u16 sel);
void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran);
-void set_gdt_task_gate(u16 tss_sel, u16 sel);
-void set_idt_task_gate(int vec, u16 sel);
-void set_intr_task_gate(int e, void *fn);
+void set_intr_alt_stack(int e, void *fn);
void print_current_tss_info(void);
void handle_exception(u8 v, void (*func)(struct ex_regs *regs));
diff --git a/x86/cstart64.S b/x86/cstart64.S
index 1a0c85e..7a1d79d 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -77,6 +77,7 @@ tss_descr:
gdt64_end:
i = 0
+.globl tss
tss:
.rept max_cpus
.long 0
diff --git a/x86/eventinj.c b/x86/eventinj.c
index 900cfda..2124bdf 100644
--- a/x86/eventinj.c
+++ b/x86/eventinj.c
@@ -183,7 +183,7 @@ int main()
setup_vm();
setup_idt();
- setup_tss32();
+ setup_alt_stack();
handle_irq(32, tirq0);
handle_irq(33, tirq1);
@@ -344,7 +344,7 @@ int main()
/* Generate DE and PF exceptions serially */
test_divider = 0;
- set_intr_task_gate(14, pf_tss);
+ set_intr_alt_stack(14, pf_tss);
handle_exception(0, de_isr);
printf("Try to divide by 0\n");
/* install read only pte */
@@ -363,7 +363,7 @@ int main()
/* Generate NP and PF exceptions serially */
printf("Before NP test\n");
test_count = 0;
- set_intr_task_gate(14, pf_tss);
+ set_intr_alt_stack(14, pf_tss);
handle_exception(11, np_isr);
set_idt_sel(33, NP_SEL);
/* install read only pte */
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 10/18] x86: eventinj: fix inline assembly and make it more robust to new compilers
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (8 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 09/18] x86: desc: support ISTs for alternate stacks in 64-bit mode Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 11/18] x86: eventinj: enable NP test in 64-bit mode Paolo Bonzini
` (8 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Using assembler trampolines instead of && fixes NMI IRET test.
There is another bug, however. Returns to the same privilege level do
not pop SS:RSP on 32-bit, so the nested NMI underflowed the stack at "s".
This is fixed in the new code. The new code doesn't set up SS:RSP and
instead leaves some space for the nested NMI handler on the alternate
stack. The old stack pointer is kept and restored when the nested
handler returns.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
x86/eventinj.c | 64 ++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 42 insertions(+), 22 deletions(-)
diff --git a/x86/eventinj.c b/x86/eventinj.c
index 2124bdf..1df3a43 100644
--- a/x86/eventinj.c
+++ b/x86/eventinj.c
@@ -59,17 +59,25 @@ static volatile int test_count;
ulong stack_phys;
void *stack_va;
-static void pf_tss(void)
+void do_pf_tss(void)
{
-start:
printf("PF running\n");
install_pte(phys_to_virt(read_cr3()), 1, stack_va,
stack_phys | PTE_PRESENT | PTE_WRITE, 0);
invlpg(stack_va);
- asm volatile ("iret");
- goto start;
}
+extern void pf_tss(void);
+
+asm (
+ "pf_tss: \n\t"
+ "call do_pf_tss \n\t"
+ "add $"S", %"R "sp\n\t" // discard error code
+ "iret"W" \n\t"
+ "jmp pf_tss\n\t"
+ );
+
+
static void of_isr(struct ex_regs *r)
{
printf("OF isr running\n");
@@ -114,39 +122,51 @@ static void nmi_isr(struct ex_regs *r)
printf("After nested NMI to self\n");
}
-unsigned long after_iret_addr;
+unsigned long *iret_stack;
static void nested_nmi_iret_isr(struct ex_regs *r)
{
printf("Nested NMI isr running rip=%x\n", r->rip);
- if (r->rip == after_iret_addr)
+ if (r->rip == iret_stack[-3])
test_count++;
}
+
+extern void do_iret(ulong phys_stack, void *virt_stack);
+
+// Return to same privilege level won't pop SS or SP, so
+// save it in RDX while we run on the nested stack
+
+asm("do_iret:"
+#ifdef __x86_64__
+ "mov %rdi, %rax \n\t" // phys_stack
+ "mov %rsi, %rdx \n\t" // virt_stack
+#else
+ "mov 4(%esp), %eax \n\t" // phys_stack
+ "mov 8(%esp), %edx \n\t" // virt_stack
+#endif
+ "xchg %"R "dx, %"R "sp \n\t" // point to new stack
+ "pushf"W" \n\t"
+ "mov %cs, %ecx \n\t"
+ "push"W" %"R "cx \n\t"
+ "push"W" $1f \n\t"
+ "outl %eax, $0xe4 \n\t" // flush page
+ "iret"W" \n\t"
+ "1: xchg %"R "dx, %"R "sp \n\t" // point to old stack
+ "ret\n\t"
+ );
+
static void nmi_iret_isr(struct ex_regs *r)
{
unsigned long *s = alloc_page();
test_count++;
- printf("NMI isr running %p stack %p\n", &&after_iret, s);
+ printf("NMI isr running stack %p\n", s);
handle_exception(2, nested_nmi_iret_isr);
printf("Sending nested NMI to self\n");
apic_self_nmi();
printf("After nested NMI to self\n");
- s[4] = read_ss();
- s[3] = 0; /* rsp */
- s[2] = read_rflags();
- s[1] = read_cs();
- s[0] = after_iret_addr = (unsigned long)&&after_iret;
- asm ("mov %%" R "sp, %0\n\t"
- "mov %1, %%" R "sp\n\t"
- "outl %2, $0xe4\n\t" /* flush stack page */
-#ifdef __x86_64__
- "iretq\n\t"
-#else
- "iretl\n\t"
-#endif
- : "=m"(s[3]) : "rm"(&s[0]), "a"((unsigned int)virt_to_phys(s)) : "memory");
-after_iret:
+ iret_stack = &s[128];
+ do_iret(virt_to_phys(s), iret_stack);
printf("After iret\n");
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 11/18] x86: eventinj: enable NP test in 64-bit mode
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (9 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 10/18] x86: eventinj: fix inline assembly and make it more robust to new compilers Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 12/18] x86: eventinj: port consecutive exception tests to x86-64 Paolo Bonzini
` (7 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Sharing the GDT between 32-bit and 64-bit means that the non-present
code segment is now always there, and the test just works.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
x86/eventinj.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/x86/eventinj.c b/x86/eventinj.c
index 1df3a43..050bc8c 100644
--- a/x86/eventinj.c
+++ b/x86/eventinj.c
@@ -83,6 +83,7 @@ static void of_isr(struct ex_regs *r)
printf("OF isr running\n");
test_count++;
}
+#endif
static void np_isr(struct ex_regs *r)
{
@@ -90,7 +91,6 @@ static void np_isr(struct ex_regs *r)
set_idt_sel(33, read_cs());
test_count++;
}
-#endif
static void de_isr(struct ex_regs *r)
{
@@ -316,7 +316,6 @@ int main()
while(test_count != 2); /* wait for second irq */
irq_disable();
-#ifndef __x86_64__
/* test fault durint NP delivery */
printf("Before NP test\n");
test_count = 0;
@@ -327,7 +326,6 @@ int main()
asm volatile ("int $33");
printf("After int33\n");
report("NP exception", test_count == 2);
-#endif
/* generate NMI that will fault on IDT */
test_count = 0;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 12/18] x86: eventinj: port consecutive exception tests to x86-64
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (10 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 11/18] x86: eventinj: enable NP test in 64-bit mode Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 13/18] x86: xsave: use cpuid functions from processor.h Paolo Bonzini
` (6 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Use ISTs instead of tasks.
One big remaining difference between 32- and 64-bits is that tasks
on 32-bits take care of saving registers. ISTs do not, only the
stack is affected.
For now, just save/restore caller-save registers in the assembly
wrapper, since there's just one test that uses ISTs. Later we
can extend the existing APIs to register exception handlers, so
that they can use tasks or ISTs too.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
x86/eventinj.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/x86/eventinj.c b/x86/eventinj.c
index 050bc8c..6547351 100644
--- a/x86/eventinj.c
+++ b/x86/eventinj.c
@@ -55,7 +55,6 @@ static void flush_idt_page()
static volatile unsigned int test_divider;
static volatile int test_count;
-#ifndef __x86_64__
ulong stack_phys;
void *stack_va;
@@ -69,15 +68,24 @@ void do_pf_tss(void)
extern void pf_tss(void);
-asm (
- "pf_tss: \n\t"
+asm ("pf_tss: \n\t"
+#ifdef __x86_64__
+ // no task on x86_64, save/restore caller-save regs
+ "push %rax; push %rcx; push %rdx; push %rsi; push %rdi\n"
+ "push %r8; push %r9; push %r10; push %r11\n"
+#endif
"call do_pf_tss \n\t"
- "add $"S", %"R "sp\n\t" // discard error code
+#ifdef __x86_64__
+ "pop %r11; pop %r10; pop %r9; pop %r8\n"
+ "pop %rdi; pop %rsi; pop %rdx; pop %rcx; pop %rax\n"
+#endif
+ "add $"S", %"R "sp\n\t" // discard error code
"iret"W" \n\t"
"jmp pf_tss\n\t"
);
+#ifndef __x86_64__
static void of_isr(struct ex_regs *r)
{
printf("OF isr running\n");
@@ -356,7 +364,6 @@ int main()
irq_disable();
printf("After NMI to self\n");
report("NMI", test_count == 2);
-#ifndef __x86_64__
stack_phys = (ulong)virt_to_phys(alloc_page());
stack_va = alloc_vpage();
@@ -395,7 +402,6 @@ int main()
restore_stack();
printf("After int33\n");
report("NP PF exceptions", test_count == 2);
-#endif
pt = alloc_page();
cr3 = (void*)read_cr3();
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 13/18] x86: xsave: use cpuid functions from processor.h
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (11 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 12/18] x86: eventinj: port consecutive exception tests to x86-64 Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 14/18] x86: svm: rename get_pte function Paolo Bonzini
` (5 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
x86/xsave.c | 58 ++++++----------------------------------------------------
1 file changed, 6 insertions(+), 52 deletions(-)
diff --git a/x86/xsave.c b/x86/xsave.c
index 057b0ff..cd2cdce 100644
--- a/x86/xsave.c
+++ b/x86/xsave.c
@@ -1,5 +1,6 @@
#include "libcflat.h"
#include "desc.h"
+#include "processor.h"
#ifdef __x86_64__
#define uint64_t unsigned long
@@ -7,42 +8,6 @@
#define uint64_t unsigned long long
#endif
-static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- /* ecx is often an input as well as an output. */
- asm volatile("cpuid"
- : "=a" (*eax),
- "=b" (*ebx),
- "=c" (*ecx),
- "=d" (*edx)
- : "0" (*eax), "2" (*ecx));
-}
-
-/*
- * Generic CPUID function
- * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
- * resulting in stale register contents being returned.
- */
-void cpuid(unsigned int op,
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- *eax = op;
- *ecx = 0;
- __cpuid(eax, ebx, ecx, edx);
-}
-
-/* Some CPUID calls want 'count' to be placed in ecx */
-void cpuid_count(unsigned int op, int count,
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- *eax = op;
- *ecx = count;
- __cpuid(eax, ebx, ecx, edx);
-}
-
int xgetbv_checking(u32 index, u64 *result)
{
u32 eax, edx;
@@ -68,13 +33,6 @@ int xsetbv_checking(u32 index, u64 value)
return exception_vector();
}
-unsigned long read_cr4(void)
-{
- unsigned long val;
- asm volatile("mov %%cr4,%0" : "=r" (val));
- return val;
-}
-
int write_cr4_checking(unsigned long val)
{
asm volatile(ASM_TRY("1f")
@@ -87,20 +45,16 @@ int write_cr4_checking(unsigned long val)
#define CPUID_1_ECX_OSXSAVE (1 << 27)
int check_cpuid_1_ecx(unsigned int bit)
{
- unsigned int eax, ebx, ecx, edx;
- cpuid(1, &eax, &ebx, &ecx, &edx);
- if (ecx & bit)
- return 1;
- return 0;
+ return (cpuid(1).c & bit) != 0;
}
uint64_t get_supported_xcr0(void)
{
- unsigned int eax, ebx, ecx, edx;
- cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
+ struct cpuid r;
+ r = cpuid_indexed(0xd, 0);
printf("eax %x, ebx %x, ecx %x, edx %x\n",
- eax, ebx, ecx, edx);
- return eax + ((u64)edx << 32);
+ r.a, r.b, r.c, r.d);
+ return r.a + ((u64)r.d << 32);
}
#define X86_CR4_OSXSAVE 0x00040000
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 14/18] x86: svm: rename get_pte function
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (12 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 13/18] x86: xsave: use cpuid functions from processor.h Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 15/18] x86: vm: remove dead code Paolo Bonzini
` (4 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
We will make it public in vm.c with the next patch.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
x86/svm.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/x86/svm.c b/x86/svm.c
index 9d910ae..5cfd77d 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -95,7 +95,7 @@ static void setup_svm(void)
pml4e[0] = ((u64)pdpe) | 0x27;
}
-static u64 *get_pte(u64 address)
+static u64 *npt_get_pte(u64 address)
{
int i1, i2;
@@ -502,14 +502,14 @@ static void npt_nx_prepare(struct test *test)
u64 *pte;
vmcb_ident(test->vmcb);
- pte = get_pte((u64)null_test);
+ pte = npt_get_pte((u64)null_test);
*pte |= (1ULL << 63);
}
static bool npt_nx_check(struct test *test)
{
- u64 *pte = get_pte((u64)null_test);
+ u64 *pte = npt_get_pte((u64)null_test);
*pte &= ~(1ULL << 63);
@@ -524,7 +524,7 @@ static void npt_us_prepare(struct test *test)
u64 *pte;
vmcb_ident(test->vmcb);
- pte = get_pte((u64)scratch_page);
+ pte = npt_get_pte((u64)scratch_page);
*pte &= ~(1ULL << 2);
}
@@ -536,7 +536,7 @@ static void npt_us_test(struct test *test)
static bool npt_us_check(struct test *test)
{
- u64 *pte = get_pte((u64)scratch_page);
+ u64 *pte = npt_get_pte((u64)scratch_page);
*pte |= (1ULL << 2);
@@ -566,7 +566,7 @@ static void npt_rw_prepare(struct test *test)
u64 *pte;
vmcb_ident(test->vmcb);
- pte = get_pte(0x80000);
+ pte = npt_get_pte(0x80000);
*pte &= ~(1ULL << 1);
}
@@ -580,7 +580,7 @@ static void npt_rw_test(struct test *test)
static bool npt_rw_check(struct test *test)
{
- u64 *pte = get_pte(0x80000);
+ u64 *pte = npt_get_pte(0x80000);
*pte |= (1ULL << 1);
@@ -594,14 +594,14 @@ static void npt_pfwalk_prepare(struct test *test)
u64 *pte;
vmcb_ident(test->vmcb);
- pte = get_pte(read_cr3());
+ pte = npt_get_pte(read_cr3());
*pte &= ~(1ULL << 1);
}
static bool npt_pfwalk_check(struct test *test)
{
- u64 *pte = get_pte(read_cr3());
+ u64 *pte = npt_get_pte(read_cr3());
*pte |= (1ULL << 1);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 15/18] x86: vm: remove dead code
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (13 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 14/18] x86: svm: rename get_pte function Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 16/18] x86: vm: export get_pte and return a pointer to it Paolo Bonzini
` (3 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/x86/vm.c | 17 -----------------
1 file changed, 17 deletions(-)
diff --git a/lib/x86/vm.c b/lib/x86/vm.c
index 188bf57..93aea71 100644
--- a/lib/x86/vm.c
+++ b/lib/x86/vm.c
@@ -116,23 +116,6 @@ void install_page(unsigned long *cr3,
}
-static inline void load_gdt(unsigned long *table, int nent)
-{
- struct descriptor_table_ptr descr;
-
- descr.limit = nent * 8 - 1;
- descr.base = (ulong)table;
- lgdt(&descr);
-}
-
-#define SEG_CS_32 8
-#define SEG_CS_64 16
-
-struct ljmp {
- void *ofs;
- unsigned short seg;
-};
-
static void setup_mmu_range(unsigned long *cr3, unsigned long start,
unsigned long len)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 16/18] x86: vm: export get_pte and return a pointer to it
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (14 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 15/18] x86: vm: remove dead code Paolo Bonzini
@ 2014-04-28 15:22 ` Paolo Bonzini
2014-04-28 15:23 ` [PATCH kvm-unit-tests 17/18] x86: vm: mark intermediate PTEs as user-accessible Paolo Bonzini
` (2 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
This lets us modify the flags for the PTE corresponding to a virtual address.
The SMAP testcase will use this to build supervisor-mode pages.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/x86/vm.c | 41 +++++++++++++++++++++--------------------
lib/x86/vm.h | 17 +++++++++--------
2 files changed, 30 insertions(+), 28 deletions(-)
diff --git a/lib/x86/vm.c b/lib/x86/vm.c
index 93aea71..3e7ca97 100644
--- a/lib/x86/vm.c
+++ b/lib/x86/vm.c
@@ -54,11 +54,11 @@ static unsigned long end_of_memory;
#define PGDIR_MASK 1023
#endif
-void install_pte(unsigned long *cr3,
- int pte_level,
- void *virt,
- unsigned long pte,
- unsigned long *pt_page)
+unsigned long *install_pte(unsigned long *cr3,
+ int pte_level,
+ void *virt,
+ unsigned long pte,
+ unsigned long *pt_page)
{
int level;
unsigned long *pt = cr3;
@@ -79,9 +79,10 @@ void install_pte(unsigned long *cr3,
}
offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & PGDIR_MASK;
pt[offset] = pte;
+ return &pt[offset];
}
-static unsigned long get_pte(unsigned long *cr3, void *virt)
+unsigned long *get_pte(unsigned long *cr3, void *virt)
{
int level;
unsigned long *pt = cr3, pte;
@@ -91,28 +92,28 @@ static unsigned long get_pte(unsigned long *cr3, void *virt)
offset = ((unsigned long)virt >> (((level-1) * PGDIR_WIDTH) + 12)) & PGDIR_MASK;
pte = pt[offset];
if (!(pte & PTE_PRESENT))
- return 0;
+ return NULL;
if (level == 2 && (pte & PTE_PSE))
- return pte;
+ return &pt[offset];
pt = phys_to_virt(pte & 0xffffffffff000ull);
}
offset = ((unsigned long)virt >> (((level-1) * PGDIR_WIDTH) + 12)) & PGDIR_MASK;
- pte = pt[offset];
- return pte;
+ return &pt[offset];
}
-void install_large_page(unsigned long *cr3,
- unsigned long phys,
- void *virt)
+unsigned long *install_large_page(unsigned long *cr3,
+ unsigned long phys,
+ void *virt)
{
- install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER | PTE_PSE, 0);
+ return install_pte(cr3, 2, virt,
+ phys | PTE_PRESENT | PTE_WRITE | PTE_USER | PTE_PSE, 0);
}
-void install_page(unsigned long *cr3,
- unsigned long phys,
- void *virt)
+unsigned long *install_page(unsigned long *cr3,
+ unsigned long phys,
+ void *virt)
{
- install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER, 0);
+ return install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER, 0);
}
@@ -194,7 +195,7 @@ void *vmalloc(unsigned long size)
uint64_t virt_to_phys_cr3(void *mem)
{
- return (get_pte(phys_to_virt(read_cr3()), mem) & PTE_ADDR) + ((ulong)mem & (PAGE_SIZE - 1));
+ return (*get_pte(phys_to_virt(read_cr3()), mem) & PTE_ADDR) + ((ulong)mem & (PAGE_SIZE - 1));
}
void vfree(void *mem)
@@ -202,7 +203,7 @@ void vfree(void *mem)
unsigned long size = ((unsigned long *)mem)[-1];
while (size) {
- free_page(phys_to_virt(get_pte(phys_to_virt(read_cr3()), mem) & PTE_ADDR));
+ free_page(phys_to_virt(*get_pte(phys_to_virt(read_cr3()), mem) & PTE_ADDR));
mem += PAGE_SIZE;
size -= PAGE_SIZE;
}
diff --git a/lib/x86/vm.h b/lib/x86/vm.h
index 0b5b5c7..bd73840 100644
--- a/lib/x86/vm.h
+++ b/lib/x86/vm.h
@@ -25,17 +25,18 @@ void *alloc_vpage(void);
void *alloc_vpages(ulong nr);
uint64_t virt_to_phys_cr3(void *mem);
-void install_pte(unsigned long *cr3,
- int pte_level,
- void *virt,
- unsigned long pte,
- unsigned long *pt_page);
+unsigned long *get_pte(unsigned long *cr3, void *virt);
+unsigned long *install_pte(unsigned long *cr3,
+ int pte_level,
+ void *virt,
+ unsigned long pte,
+ unsigned long *pt_page);
void *alloc_page();
-void install_large_page(unsigned long *cr3,unsigned long phys,
- void *virt);
-void install_page(unsigned long *cr3, unsigned long phys, void *virt);
+unsigned long *install_large_page(unsigned long *cr3,unsigned long phys,
+ void *virt);
+unsigned long *install_page(unsigned long *cr3, unsigned long phys, void *virt);
static inline unsigned long virt_to_phys(const void *virt)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 17/18] x86: vm: mark intermediate PTEs as user-accessible
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (15 preceding siblings ...)
2014-04-28 15:22 ` [PATCH kvm-unit-tests 16/18] x86: vm: export get_pte and return a pointer to it Paolo Bonzini
@ 2014-04-28 15:23 ` Paolo Bonzini
2014-04-28 15:23 ` [PATCH kvm-unit-tests 18/18] x86: smap: new testcase Paolo Bonzini
2014-05-27 9:22 ` [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:23 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
It is pointless to make the leaf user-accessible if the intermediate page
tables are not. In a real OS, what would matter is that the page tables
themselves are only accessible through a supervisor mapping.
The SMAP testcase will rely on the user bit, so fix it now.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/x86/vm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/x86/vm.c b/lib/x86/vm.c
index 3e7ca97..b820c7d 100644
--- a/lib/x86/vm.c
+++ b/lib/x86/vm.c
@@ -73,7 +73,7 @@ unsigned long *install_pte(unsigned long *cr3,
else
pt_page = 0;
memset(new_pt, 0, PAGE_SIZE);
- pt[offset] = virt_to_phys(new_pt) | PTE_PRESENT | PTE_WRITE;
+ pt[offset] = virt_to_phys(new_pt) | PTE_PRESENT | PTE_WRITE | PTE_USER;
}
pt = phys_to_virt(pt[offset] & 0xffffffffff000ull);
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH kvm-unit-tests 18/18] x86: smap: new testcase
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (16 preceding siblings ...)
2014-04-28 15:23 ` [PATCH kvm-unit-tests 17/18] x86: vm: mark intermediate PTEs as user-accessible Paolo Bonzini
@ 2014-04-28 15:23 ` Paolo Bonzini
2014-05-27 9:22 ` [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-04-28 15:23 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Test various combinations of the AC bit and reading/writing into
user pages at CPL=0.
One notable missing test is implicit kernel reads and writes (e.g.
reading the IDT/GDT/LDT/TSS). The interesting part of this is that
AC must be ignored in ring 3; the processor always behaves as if AC=0.
I skipped this because QEMU doesn't emulate this correctly, and because
right now there's no kvm-unit-tests infrastructure to run code in ring
3 at all.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
config-x86-common.mak | 4 +-
lib/x86/processor.h | 13 ++++-
x86/smap.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 171 insertions(+), 2 deletions(-)
create mode 100644 x86/smap.c
diff --git a/config-x86-common.mak b/config-x86-common.mak
index aa5a439..93c9fee 100644
--- a/config-x86-common.mak
+++ b/config-x86-common.mak
@@ -37,7 +37,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
$(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \
$(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat \
$(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \
- $(TEST_DIR)/init.flat
+ $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat
ifdef API
tests-common += api/api-sample
@@ -101,6 +101,8 @@ $(TEST_DIR)/asyncpf.elf: $(cstart.o) $(TEST_DIR)/asyncpf.o
$(TEST_DIR)/pcid.elf: $(cstart.o) $(TEST_DIR)/pcid.o
+$(TEST_DIR)/smap.elf: $(cstart.o) $(TEST_DIR)/smap.o
+
$(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o $(TEST_DIR)/vmx_tests.o
$(TEST_DIR)/debug.elf: $(cstart.o) $(TEST_DIR)/debug.o
diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index 9cc1112..7fc1026 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -25,6 +25,7 @@
#define X86_CR4_PSE 0x00000010
#define X86_CR4_PAE 0x00000020
#define X86_CR4_PCIDE 0x00020000
+#define X86_CR4_SMAP 0x00200000
#define X86_IA32_EFER 0xc0000080
#define X86_EFER_LMA (1UL << 8)
@@ -39,6 +40,16 @@ static inline void barrier(void)
asm volatile ("" : : : "memory");
}
+static inline void clac(void)
+{
+ asm volatile (".byte 0x0f, 0x01, 0xca" : : : "memory");
+}
+
+static inline void stac(void)
+{
+ asm volatile (".byte 0x0f, 0x01, 0xcb" : : : "memory");
+}
+
static inline u16 read_cs(void)
{
unsigned val;
@@ -330,7 +341,7 @@ static inline void irq_enable(void)
asm volatile("sti");
}
-static inline void invlpg(void *va)
+static inline void invlpg(volatile void *va)
{
asm volatile("invlpg (%0)" ::"r" (va) : "memory");
}
diff --git a/x86/smap.c b/x86/smap.c
new file mode 100644
index 0000000..d0b9e07
--- /dev/null
+++ b/x86/smap.c
@@ -0,0 +1,156 @@
+#include "libcflat.h"
+#include "lib/x86/desc.h"
+#include "lib/x86/processor.h"
+#include "lib/x86/vm.h"
+
+#define X86_FEATURE_SMAP 20
+#define X86_EFLAGS_AC (1 << 18)
+
+volatile int pf_count = 0;
+volatile int save;
+volatile unsigned test;
+
+
+// When doing ring 3 tests, page fault handlers will always run on a
+// separate stack (the ring 0 stack). Seems easier to use the alt_stack
+// mechanism for both ring 0 and ring 3.
+
+void do_pf_tss(unsigned long error_code)
+{
+ pf_count++;
+ save = test;
+
+#ifndef __x86_64__
+ tss.eflags |= X86_EFLAGS_AC;
+#endif
+}
+
+extern void pf_tss(void);
+asm ("pf_tss:\n"
+#ifdef __x86_64__
+ // no task on x86_64, save/restore caller-save regs
+ "push %rax; push %rcx; push %rdx; push %rsi; push %rdi\n"
+ "push %r8; push %r9; push %r10; push %r11\n"
+ "mov 9*8(%rsp),%rsi\n"
+#endif
+ "call do_pf_tss\n"
+#ifdef __x86_64__
+ "pop %r11; pop %r10; pop %r9; pop %r8\n"
+ "pop %rdi; pop %rsi; pop %rdx; pop %rcx; pop %rax\n"
+#endif
+ "add $"S", %"R "sp\n"
+#ifdef __x86_64__
+ "orl $" xstr(X86_EFLAGS_AC) ", 2*"S"(%"R "sp)\n" // set EFLAGS.AC and retry
+#endif
+ "iret"W" \n\t"
+ "jmp pf_tss\n\t");
+
+
+#define USER_BASE (1 << 24)
+#define USER_VAR(v) (*((__typeof__(&(v))) (((unsigned long)&v) + USER_BASE)))
+
+static void init_test(int i)
+{
+ pf_count = 0;
+ if (i) {
+ invlpg(&test);
+ invlpg(&USER_VAR(test));
+ }
+}
+
+int main(int ac, char **av)
+{
+ unsigned long i;
+
+ if (!(cpuid_indexed(7, 0).b & (1 << X86_FEATURE_SMAP))) {
+ printf("SMAP not enabled, exiting\n");
+ exit(1);
+ }
+
+ setup_vm();
+ setup_alt_stack();
+ set_intr_alt_stack(14, pf_tss);
+
+ // Map first 16MB as supervisor pages
+ for (i = 0; i < USER_BASE; i += PAGE_SIZE) {
+ *get_pte(phys_to_virt(read_cr3()), phys_to_virt(i)) &= ~PTE_USER;
+ invlpg((void *)i);
+ }
+
+ // Present the same 16MB as user pages in the 16MB-32MB range
+ for (i = USER_BASE; i < 2 * USER_BASE; i += PAGE_SIZE) {
+ *get_pte(phys_to_virt(read_cr3()), phys_to_virt(i)) &= ~USER_BASE;
+ invlpg((void *)i);
+ }
+
+ clac();
+ write_cr4(read_cr4() | X86_CR4_SMAP);
+ write_cr3(read_cr3());
+
+ for (i = 0; i < 2; i++) {
+ if (i)
+ printf("testing with INVLPG\n");
+ else
+ printf("testing without INVLPG\n");
+
+ init_test(i);
+ clac();
+ test = 42;
+ report("write to supervisor page", pf_count == 0 && test == 42);
+
+ init_test(i);
+ stac();
+ (void)USER_VAR(test);
+ report("read from user page with AC=1", pf_count == 0);
+
+ init_test(i);
+ clac();
+ (void)USER_VAR(test);
+ report("read from user page with AC=0", pf_count == 1 && save == 42);
+
+ init_test(i);
+ stac();
+ save = 0;
+ USER_VAR(test) = 43;
+ report("write to user page with AC=1", pf_count == 0 && test == 43);
+
+ init_test(i);
+ clac();
+ USER_VAR(test) = 44;
+ report("read from user page with AC=0", pf_count == 1 && test == 44 && save == 43);
+
+ init_test(i);
+ stac();
+ test = -1;
+ asm("or $(" xstr(USER_BASE) "), %"R "sp \n"
+ "push $44 \n "
+ "decl test\n"
+ "and $~(" xstr(USER_BASE) "), %"R "sp \n"
+ "pop %"R "ax\n"
+ "movl %eax, test");
+ report("write to user stack with AC=1", pf_count == 0 && test == 44);
+
+ init_test(i);
+ clac();
+ test = -1;
+ asm("or $(" xstr(USER_BASE) "), %"R "sp \n"
+ "push $45 \n "
+ "decl test\n"
+ "and $~(" xstr(USER_BASE) "), %"R "sp \n"
+ "pop %"R "ax\n"
+ "movl %eax, test");
+ report("write to user stack with AC=0", pf_count == 1 && test == 45 && save == -1);
+
+ /* This would be trapped by SMEP */
+ init_test(i);
+ clac();
+ asm("jmp 1f + "xstr(USER_BASE)" \n"
+ "1: jmp 2f - "xstr(USER_BASE)" \n"
+ "2:");
+ report("executing on user page with AC=0", pf_count == 0);
+ }
+
+ // TODO: implicit kernel access from ring 3 (e.g. int)
+
+ return report_summary();
+}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
` (17 preceding siblings ...)
2014-04-28 15:23 ` [PATCH kvm-unit-tests 18/18] x86: smap: new testcase Paolo Bonzini
@ 2014-05-27 9:22 ` Paolo Bonzini
18 siblings, 0 replies; 20+ messages in thread
From: Paolo Bonzini @ 2014-05-27 9:22 UTC (permalink / raw)
To: kvm; +Cc: jan.kiszka, drjones
Il 28/04/2014 17:22, Paolo Bonzini ha scritto:
> This series is structured as follows:
>
> - patches 1 to 8 cleanup lib/x86/, remove gratuitous differences
> between 32-bit and 64-bit, and unify code that is duplicated in
> various ways
>
> - patches 9 to 12 port some eventinj tests so that they run as
> 64-bit hosts too
>
> - patches 13 to 15 are cleanups
>
> - patches 16 to 18 add a testcase for SMAP (tested with QEMU by me
> and, by the patch submitter, with KVM)
I pushed most of this series, except patches 16 and 18.
I didn't add the SMAP testcase because Avi suggested on IRC adding the
SMAP testcases to access.flat. It's a good idea, but there are a lot of
TCG bugs in this area that access.flat detects, and they block my SMAP
testing. If I can fix these bugs, I'll add the testcases to
access.flat. Otherwise, I'll commit patches 16 and 18 too.
Paolo
> Paolo Bonzini (18):
> libcflat: move stringification trick to a common place
> x86: move size #defines to processor.h
> x86: desc: change set_gdt_entry argument to selector
> x86: desc: move idt_entry_t and gdt_entry_t to header
> x86: desc: reuse cstart.S GDT and TSS
> x86: taskswitch: use desc library
> x86: unify GDT format between 32-bit and 64-bit
> x86: move CR0 and CR4 constants to processor.h
> x86: desc: support ISTs for alternate stacks in 64-bit mode
> x86: eventinj: fix inline assembly and make it more robust to new compilers
> x86: eventinj: enable NP test in 64-bit mode
> x86: eventinj: port consecutive exception tests to x86-64
> x86: xsave: use cpuid functions from processor.h
> x86: svm: rename get_pte function
> x86: vm: remove dead code
> x86: vm: export get_pte and return a pointer to it
> x86: vm: mark intermediate PTEs as user-accessible
> x86: smap: new testcase
>
> config-x86-common.mak | 4 +-
> lib/libcflat.h | 3 +
> lib/x86/desc.c | 166 +++++++++++++++++---------------------------------
> lib/x86/desc.h | 80 ++++++++++++++++++++----
> lib/x86/isr.c | 6 --
> lib/x86/processor.h | 38 +++++++++++-
> lib/x86/vm.c | 60 +++++++-----------
> lib/x86/vm.h | 42 +++----------
> x86/asyncpf.c | 1 -
> x86/cstart.S | 16 +++++
> x86/cstart64.S | 17 ++++--
> x86/eventinj.c | 87 ++++++++++++++++----------
> x86/pcid.c | 7 ---
> x86/smap.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++
> x86/svm.c | 18 +++---
> x86/taskswitch.c | 134 +++-------------------------------------
> x86/taskswitch2.c | 19 +++---
> x86/vmexit.c | 6 --
> x86/vmx.c | 32 +++++-----
> x86/xsave.c | 58 ++----------------
> 20 files changed, 485 insertions(+), 465 deletions(-)
> create mode 100644 x86/smap.c
>
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2014-05-27 9:22 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-28 15:22 [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 01/18] libcflat: move stringification trick to a common place Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 02/18] x86: move size #defines to processor.h Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 03/18] x86: desc: change set_gdt_entry argument to selector Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 04/18] x86: desc: move idt_entry_t and gdt_entry_t to header Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 05/18] x86: desc: reuse cstart.S GDT and TSS Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 06/18] x86: taskswitch: use desc library Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 07/18] x86: unify GDT format between 32-bit and 64-bit Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 08/18] x86: move CR0 and CR4 constants to processor.h Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 09/18] x86: desc: support ISTs for alternate stacks in 64-bit mode Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 10/18] x86: eventinj: fix inline assembly and make it more robust to new compilers Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 11/18] x86: eventinj: enable NP test in 64-bit mode Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 12/18] x86: eventinj: port consecutive exception tests to x86-64 Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 13/18] x86: xsave: use cpuid functions from processor.h Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 14/18] x86: svm: rename get_pte function Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 15/18] x86: vm: remove dead code Paolo Bonzini
2014-04-28 15:22 ` [PATCH kvm-unit-tests 16/18] x86: vm: export get_pte and return a pointer to it Paolo Bonzini
2014-04-28 15:23 ` [PATCH kvm-unit-tests 17/18] x86: vm: mark intermediate PTEs as user-accessible Paolo Bonzini
2014-04-28 15:23 ` [PATCH kvm-unit-tests 18/18] x86: smap: new testcase Paolo Bonzini
2014-05-27 9:22 ` [PATCH kvm-unit-tests 00/18] lib/x86 TLC, extending tests for both 32- and 64-bits, and SMAP tests Paolo Bonzini
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.