1 #include <xen/init.h>
2 #include <xen/lib.h>
3 #include <xen/mm.h>
4 #include <xen/percpu.h>
5 
6 #include <asm/desc.h>
7 
8 /*
9  * Native and Compat GDTs used by Xen.
10  *
11  * The R1 and R3 descriptors are fixed in Xen's ABI for PV guests.  All other
12  * descriptors are in principle variable, with the following restrictions.
13  *
14  * All R0 descriptors must line up in both GDTs to allow for correct
15  * interrupt/exception handling.
16  *
17  * The SYSCALL/SYSRET GDT layout requires:
18  *  - R0 long mode code followed by R0 data.
19  *  - R3 compat code, followed by R3 data, followed by R3 long mode code.
20  *
21  * The SYSENTER GDT layout requirements are compatible with SYSCALL.  Xen does
22  * not use the SYSEXIT instruction, and does not provide a compatible GDT.
23  *
24  * These tables are used directly by CPU0, and used as the template for the
25  * GDTs of other CPUs.  Everything from the TSS onwards is unique per CPU.
26  */
27 
28 #define SEL2GDT(sel) (((sel) >> 3) - FIRST_RESERVED_GDT_ENTRY)
29 
30 __section(".data.page_aligned") __aligned(PAGE_SIZE)
31 seg_desc_t boot_gdt[PAGE_SIZE / sizeof(seg_desc_t)] =
32 {
33     /* 0xe008 - Ring 0 code, 64bit mode */
34     [SEL2GDT(__HYPERVISOR_CS)] =      { 0x00af9b000000ffff },
35 
36     /* 0xe010 - Ring 0 data */
37     [SEL2GDT(__HYPERVISOR_DS32)] =    { 0x00cf93000000ffff },
38 
39     /* 0xe018 - reserved */
40 
41     /* 0xe023 - Ring 3 code, compatibility */
42     [SEL2GDT(FLAT_RING3_CS32)] =      { 0x00cffb000000ffff },
43 
44     /* 0xe02b - Ring 3 data */
45     [SEL2GDT(FLAT_RING3_DS32)] =      { 0x00cff3000000ffff },
46 
47     /* 0xe033 - Ring 3 code, 64-bit mode */
48     [SEL2GDT(FLAT_RING3_CS64)] =      { 0x00affb000000ffff },
49 
50     /* 0xe038 - reserved */
51     /* 0xe040 - TSS */
52     /* 0xe050 - LDT */
53 
54     /* 0xe060 - per-CPU entry (limit == cpu) */
55     [SEL2GDT(PER_CPU_SELECTOR)] =     { 0x0000910000000000 },
56 };
57 
58 #ifdef CONFIG_PV32
59 __section(".data.page_aligned") __aligned(PAGE_SIZE)
60 seg_desc_t boot_compat_gdt[PAGE_SIZE / sizeof(seg_desc_t)] =
61 {
62     /* 0xe008 - Ring 0 code, 64bit mode */
63     [SEL2GDT(__HYPERVISOR_CS)] =      { 0x00af9b000000ffff },
64 
65     /* 0xe010 - Ring 0 data */
66     [SEL2GDT(__HYPERVISOR_DS32)] =    { 0x00cf93000000ffff },
67 
68     /* 0xe019 - Ring 1 code, compatibility */
69     [SEL2GDT(FLAT_COMPAT_RING1_CS)] = { 0x00cfbb000000ffff },
70 
71     /* 0xe021 - Ring 1 data */
72     [SEL2GDT(FLAT_COMPAT_RING1_DS)] = { 0x00cfb3000000ffff },
73 
74     /* 0xe02b - Ring 3 code, compatibility */
75     [SEL2GDT(FLAT_COMPAT_RING3_CS)] = { 0x00cffb000000ffff },
76 
77     /* 0xe033 - Ring 3 data */
78     [SEL2GDT(FLAT_COMPAT_RING3_DS)] = { 0x00cff3000000ffff },
79 
80     /* 0xe038 - reserved */
81     /* 0xe040 - TSS */
82     /* 0xe050 - LDT */
83 
84     /* 0xe060 - per-CPU entry (limit == cpu) */
85     [SEL2GDT(PER_CPU_SELECTOR)] =     { 0x0000910000000000 },
86 };
87 #endif
88 
89 /*
90  * Used by each CPU as it starts up, to enter C with a suitable %cs.
91  * References boot_cpu_gdt_table for a short period, until the CPUs switch
92  * onto their per-CPU GDTs.
93  */
94 const struct desc_ptr boot_gdtr = {
95     .limit = LAST_RESERVED_GDT_BYTE,
96     .base = (unsigned long)(boot_gdt - FIRST_RESERVED_GDT_ENTRY),
97 };
98 
99 /*
100  * Local variables:
101  * mode: C
102  * c-file-style: "BSD"
103  * c-basic-offset: 4
104  * tab-width: 4
105  * indent-tabs-mode: nil
106  * End:
107  */
108