Skip to content
Snippets Groups Projects
Commit 74bfbe1b authored by Graeme Russ's avatar Graeme Russ
Browse files

x86: Rework Global Descriptor Table loading

The inline assembler is ugly and uses hard coded magic numbers. Make it more
elegant to allow cleaner implementation of future GDT related patches. The
compiler seems smart enough to generate the same code anyway

--
Changes for v2:
 - Rebased against revised patch #3
 - Use GDT size define instead of magic number
 - Added commit message
parent 109ad143
No related branches found
No related tags found
No related merge requests found
...@@ -55,35 +55,39 @@ struct gdt_ptr { ...@@ -55,35 +55,39 @@ struct gdt_ptr {
u32 ptr; u32 ptr;
} __packed; } __packed;
static void reload_gdt(void) static void load_ds(u32 segment)
{ {
/* asm volatile("movl %0, %%ds" : : "r" (segment * X86_GDT_ENTRY_SIZE));
* There are machines which are known to not boot with the GDT }
* being 8-byte unaligned. Intel recommends 16 byte alignment
*/ static void load_es(u32 segment)
static const u64 boot_gdt[] __attribute__((aligned(16))) = { {
/* CS: code, read/execute, 4 GB, base 0 */ asm volatile("movl %0, %%es" : : "r" (segment * X86_GDT_ENTRY_SIZE));
[X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff), }
/* DS: data, read/write, 4 GB, base 0 */
[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff), static void load_fs(u32 segment)
/* 16-bit CS: code, read/execute, 64 kB, base 0 */ {
[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x109b, 0, 0x0ffff), asm volatile("movl %0, %%fs" : : "r" (segment * X86_GDT_ENTRY_SIZE));
/* 16-bit DS: data, read/write, 64 kB, base 0 */ }
[X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x1093, 0, 0x0ffff),
}; static void load_gs(u32 segment)
static struct gdt_ptr gdt; {
asm volatile("movl %0, %%gs" : : "r" (segment * X86_GDT_ENTRY_SIZE));
gdt.len = sizeof(boot_gdt)-1; }
gdt.ptr = (u32)&boot_gdt;
static void load_ss(u32 segment)
asm volatile("lgdtl %0\n" \ {
"movl $((2+1)*8), %%ecx\n" \ asm volatile("movl %0, %%ss" : : "r" (segment * X86_GDT_ENTRY_SIZE));
"movl %%ecx, %%ds\n" \ }
"movl %%ecx, %%es\n" \
"movl %%ecx, %%fs\n" \ static void load_gdt(const u64 *boot_gdt, u16 num_entries)
"movl %%ecx, %%gs\n" \ {
"movl %%ecx, %%ss" \ struct gdt_ptr gdt;
: : "m" (gdt) : "ecx");
gdt.len = (num_entries * 8) - 1;
gdt.ptr = (u32)boot_gdt;
asm volatile("lgdtl %0\n" : : "m" (gdt));
} }
int x86_cpu_init_f(void) int x86_cpu_init_f(void)
...@@ -113,7 +117,27 @@ int x86_cpu_init_r(void) ...@@ -113,7 +117,27 @@ int x86_cpu_init_r(void)
"movl %%eax, %%cr0\n" "movl %%eax, %%cr0\n"
"wbinvd\n" : : "i" (nw_cd_rst) : "eax"); "wbinvd\n" : : "i" (nw_cd_rst) : "eax");
reload_gdt(); /*
* There are machines which are known to not boot with the GDT
* being 8-byte unaligned. Intel recommends 16 byte alignment
*/
static const u64 boot_gdt[] __aligned(16) = {
/* CS: code, read/execute, 4 GB, base 0 */
[X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
/* DS: data, read/write, 4 GB, base 0 */
[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
/* 16-bit CS: code, read/execute, 64 kB, base 0 */
[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x109b, 0, 0x0ffff),
/* 16-bit DS: data, read/write, 64 kB, base 0 */
[X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x1093, 0, 0x0ffff),
};
load_gdt(boot_gdt, X86_GDT_NUM_ENTRIES);
load_ds(X86_GDT_ENTRY_32BIT_DS);
load_es(X86_GDT_ENTRY_32BIT_DS);
load_fs(X86_GDT_ENTRY_32BIT_DS);
load_gs(X86_GDT_ENTRY_32BIT_DS);
load_ss(X86_GDT_ENTRY_32BIT_DS);
/* Initialize core interrupt and exception functionality of CPU */ /* Initialize core interrupt and exception functionality of CPU */
cpu_init_interrupts(); cpu_init_interrupts();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment