1 /*P:600 The x86 architecture has segments, which involve a table of descriptors
2 * which can be used to do funky things with virtual address interpretation.
3 * We originally used to use segments so the Guest couldn't alter the
4 * Guest<->Host Switcher, and then we had to trim Guest segments, and restore
5 * for userspace per-thread segments, but trim again for on userspace->kernel
6 * transitions... This nightmarish creation was contained within this file,
7 * where we knew not to tread without heavy armament and a change of underwear.
9 * In these modern times, the segment handling code consists of simple sanity
10 * checks, and the worst you'll experience reading this code is butterfly-rash
11 * from frolicking through its parklike serenity. :*/
14 static int desc_ok(const struct desc_struct
*gdt
)
16 /* MBZ=0, P=1, DT=1 */
17 return ((gdt
->b
& 0x00209000) == 0x00009000);
20 static int segment_present(const struct desc_struct
*gdt
)
22 return gdt
->b
& 0x8000;
25 static int ignored_gdt(unsigned int num
)
27 return (num
== GDT_ENTRY_TSS
28 || num
== GDT_ENTRY_LGUEST_CS
29 || num
== GDT_ENTRY_LGUEST_DS
30 || num
== GDT_ENTRY_DOUBLEFAULT_TSS
);
33 /* We don't allow removal of CS, DS or SS; it doesn't make sense. */
34 static void check_segment_use(struct lguest
*lg
, unsigned int desc
)
36 if (lg
->regs
->gs
/ 8 == desc
)
38 if (lg
->regs
->fs
/ 8 == desc
)
40 if (lg
->regs
->es
/ 8 == desc
)
42 if (lg
->regs
->ds
/ 8 == desc
43 || lg
->regs
->cs
/ 8 == desc
44 || lg
->regs
->ss
/ 8 == desc
)
45 kill_guest(lg
, "Removed live GDT entry %u", desc
);
48 static void fixup_gdt_table(struct lguest
*lg
, unsigned start
, unsigned end
)
52 for (i
= start
; i
< end
; i
++) {
53 /* We never copy these ones to real gdt */
57 /* We could fault in switch_to_guest if they are using
58 * a removed segment. */
59 if (!segment_present(&lg
->gdt
[i
])) {
60 check_segment_use(lg
, i
);
64 if (!desc_ok(&lg
->gdt
[i
]))
65 kill_guest(lg
, "Bad GDT descriptor %i", i
);
67 /* DPL 0 presumably means "for use by guest". */
68 if ((lg
->gdt
[i
].b
& 0x00006000) == 0)
69 lg
->gdt
[i
].b
|= (GUEST_PL
<< 13);
71 /* Set accessed bit, since gdt isn't writable. */
72 lg
->gdt
[i
].b
|= 0x00000100;
76 void setup_default_gdt_entries(struct lguest_ro_state
*state
)
78 struct desc_struct
*gdt
= state
->guest_gdt
;
79 unsigned long tss
= (unsigned long)&state
->guest_tss
;
81 /* Hypervisor segments. */
82 gdt
[GDT_ENTRY_LGUEST_CS
] = FULL_EXEC_SEGMENT
;
83 gdt
[GDT_ENTRY_LGUEST_DS
] = FULL_SEGMENT
;
85 /* This is the one which we *cannot* copy from guest, since tss
86 is depended on this lguest_ro_state, ie. this cpu. */
87 gdt
[GDT_ENTRY_TSS
].a
= 0x00000067 | (tss
<< 16);
88 gdt
[GDT_ENTRY_TSS
].b
= 0x00008900 | (tss
& 0xFF000000)
89 | ((tss
>> 16) & 0x000000FF);
92 void setup_guest_gdt(struct lguest
*lg
)
94 lg
->gdt
[GDT_ENTRY_KERNEL_CS
] = FULL_EXEC_SEGMENT
;
95 lg
->gdt
[GDT_ENTRY_KERNEL_DS
] = FULL_SEGMENT
;
96 lg
->gdt
[GDT_ENTRY_KERNEL_CS
].b
|= (GUEST_PL
<< 13);
97 lg
->gdt
[GDT_ENTRY_KERNEL_DS
].b
|= (GUEST_PL
<< 13);
100 /* This is a fast version for the common case where only the three TLS entries
102 void copy_gdt_tls(const struct lguest
*lg
, struct desc_struct
*gdt
)
106 for (i
= GDT_ENTRY_TLS_MIN
; i
<= GDT_ENTRY_TLS_MAX
; i
++)
110 void copy_gdt(const struct lguest
*lg
, struct desc_struct
*gdt
)
114 for (i
= 0; i
< GDT_ENTRIES
; i
++)
119 void load_guest_gdt(struct lguest
*lg
, unsigned long table
, u32 num
)
121 if (num
> ARRAY_SIZE(lg
->gdt
))
122 kill_guest(lg
, "too many gdt entries %i", num
);
124 lgread(lg
, lg
->gdt
, table
, num
* sizeof(lg
->gdt
[0]));
125 fixup_gdt_table(lg
, 0, ARRAY_SIZE(lg
->gdt
));
126 lg
->changed
|= CHANGED_GDT
;
129 void guest_load_tls(struct lguest
*lg
, unsigned long gtls
)
131 struct desc_struct
*tls
= &lg
->gdt
[GDT_ENTRY_TLS_MIN
];
133 lgread(lg
, tls
, gtls
, sizeof(*tls
)*GDT_ENTRY_TLS_ENTRIES
);
134 fixup_gdt_table(lg
, GDT_ENTRY_TLS_MIN
, GDT_ENTRY_TLS_MAX
+1);
135 lg
->changed
|= CHANGED_GDT_TLS
;