]> xenbits.xensource.com Git - xtf.git/commitdiff
Support the use of GDTs in PV guests
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 14 Feb 2018 17:37:09 +0000 (17:37 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 15 Feb 2018 13:50:49 +0000 (13:50 +0000)
GDT frames in PV guests need to be page aligned, and like pagetables, mapped
read-only.  Move gdt[] into __page_aligned_{data,bss} and leave it empty for
PV guests to begin with.

The PV arch_init_traps() code registers the frame with Xen, and tests wanting
to make use of it need to use hypercall_update_descriptor().

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
arch/x86/desc.c
arch/x86/include/arch/desc.h
arch/x86/link.lds.S
arch/x86/pv/traps.c
include/xtf/hypercall.h

index fad8355d4f6e58fc695eac3b34f96d5069b8a30e..e452e092c6ae6ff75d9fa94b5617899ea2bc5828 100644 (file)
@@ -4,8 +4,15 @@
 #include <arch/segment.h>
 #include <arch/symbolic-const.h>
 
-user_desc gdt[NR_GDT_ENTRIES] =
+#ifdef CONFIG_HVM
+#define gdt_section __page_aligned_data
+#else
+#define gdt_section __page_aligned_bss
+#endif
+
+user_desc gdt[NR_GDT_ENTRIES] gdt_section =
 {
+#ifdef CONFIG_HVM
     [GDTE_CS64_DPL0] = INIT_GDTE_SYM(0, 0xfffff, COMMON, CODE, DPL0, R, L),
     [GDTE_CS32_DPL0] = INIT_GDTE_SYM(0, 0xfffff, COMMON, CODE, DPL0, R, D),
     [GDTE_DS32_DPL0] = INIT_GDTE_SYM(0, 0xfffff, COMMON, DATA, DPL0, B, W),
@@ -16,16 +23,17 @@ user_desc gdt[NR_GDT_ENTRIES] =
 
     /* [GDTE_TSS]     */
     /* [GDTE_TSS + 1] */
+#endif
 };
 
+#if defined(CONFIG_HVM)
+
 desc_ptr gdt_ptr =
 {
     .limit = sizeof(gdt) - 1,
     .base = _u(&gdt),
 };
 
-#if defined(CONFIG_HVM)
-
 env_gate idt[256];
 
 desc_ptr idt_ptr =
index f722d82e1e8c8397b83750a6d62e01bf6a0c55df..e218e6ed58f454a6ffd2916183a46d0605fc91fd 100644 (file)
@@ -54,6 +54,8 @@ struct __packed seg_desc32 {
             };
             uint8_t base2;
         };
+        /* Full width backing integer. */
+        uint64_t raw;
     };
 };
 
index 736659a6bd50b401640d3d8530f908c9ecd6062a..03c94556c529b6d9b7570f7ecd58283a836a91f8 100644 (file)
@@ -102,6 +102,10 @@ ASSERT(IS_ALIGNED(pae32_l3_identmap, 32), "pae32_l3_ident misaligned");
 ASSERT(IS_ALIGNED(pse_l1_identmap, PAGE_SIZE), "pse_l1_identmap misaligned");
 ASSERT(IS_ALIGNED(pse_l2_identmap, PAGE_SIZE), "pse_l2_identmap misaligned");
 
+#else
+
+ASSERT(IS_ALIGNED(gdt, PAGE_SIZE), "gdt misaligned");
+
 #endif
 /*
  * Local variables:
index 336da9ef7ade01530b96d9960a1469c5d91831ab..ca0b9a3c12a3946b231b90f2e663dc0da74ba0d9 100644 (file)
@@ -96,6 +96,20 @@ void arch_init_traps(void)
     if ( rc )
         panic("Failed to set trap table: %d\n", rc);
 
+    /* Register gdt[] with Xen.  Need to map it read-only first. */
+    if ( hypercall_update_va_mapping(
+             _u(gdt), pte_from_virt(gdt, PF_SYM(AD, P)), UVMF_INVLPG) )
+        panic("Unable to remap gdt[] as read-only\n");
+
+    unsigned long gdt_frames[] = {
+        virt_to_mfn(gdt),
+    };
+    BUILD_BUG_ON(NR_GDT_ENTRIES > (PAGE_SIZE / sizeof(user_desc)));
+
+    rc = hypercall_set_gdt(gdt_frames, NR_GDT_ENTRIES);
+    if ( rc )
+        panic("Failed to set gdt: %d\n", rc);
+
     /* PV equivalent of setting tss.{esp0,ss0}. */
     rc = hypercall_stack_switch(__KERN_DS, &boot_stack[2 * PAGE_SIZE]);
     if ( rc )
index 9be25da0118af6a680fd387a6f1d96bc0d413001..64473e94acffdb52fcef4e2e83c9174eaa16160b 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <xtf/compiler.h>
 #include <xtf/types.h>
+#include <arch/desc.h>
 #include <arch/page.h>
 
 #if defined(__x86_64__)
@@ -61,11 +62,27 @@ static inline long hypercall_mmu_update(const mmu_update_t reqs[],
                       reqs, count, done, foreigndom);
 }
 
+static inline long hypercall_set_gdt(const unsigned long *mfns,
+                                     unsigned int entries)
+{
+    return HYPERCALL2(long, __HYPERVISOR_set_gdt, mfns, entries);
+}
+
 static inline long hypercall_stack_switch(const unsigned int ss, const void *sp)
 {
     return HYPERCALL2(long, __HYPERVISOR_stack_switch, ss, sp);
 }
 
+static inline long hypercall_update_descriptor(uint64_t maddr, user_desc desc)
+{
+#ifdef __x86_64__
+    return HYPERCALL2(long, __HYPERVISOR_update_descriptor, maddr, desc.raw);
+#else
+    return HYPERCALL4(long, __HYPERVISOR_update_descriptor,
+                      maddr, maddr >> 32, desc.lo, desc.hi);
+#endif
+}
+
 static inline long hypercall_memory_op(unsigned int cmd, void *arg)
 {
     return HYPERCALL2(long, __HYPERVISOR_memory_op, cmd, arg);