diff options
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 17 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common_64.c | 37 |
2 files changed, 54 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 6bbdbc24f2ba..e0ca51f4f2d3 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -40,6 +40,22 @@ | |||
40 | 40 | ||
41 | static struct cpu_dev *this_cpu __cpuinitdata; | 41 | static struct cpu_dev *this_cpu __cpuinitdata; |
42 | 42 | ||
43 | #ifdef CONFIG_X86_64 | ||
44 | /* We need valid kernel segments for data and code in long mode too | ||
45 | * IRET will check the segment types kkeil 2000/10/28 | ||
46 | * Also sysret mandates a special GDT layout | ||
47 | */ | ||
48 | /* The TLS descriptors are currently at a different place compared to i386. | ||
49 | Hopefully nobody expects them at a fixed place (Wine?) */ | ||
50 | DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { | ||
51 | [GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } }, | ||
52 | [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } }, | ||
53 | [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } }, | ||
54 | [GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } }, | ||
55 | [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } }, | ||
56 | [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } }, | ||
57 | } }; | ||
58 | #else | ||
43 | DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { | 59 | DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { |
44 | [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, | 60 | [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, |
45 | [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, | 61 | [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, |
@@ -74,6 +90,7 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { | |||
74 | [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } }, | 90 | [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } }, |
75 | [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } }, | 91 | [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } }, |
76 | } }; | 92 | } }; |
93 | #endif | ||
77 | EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); | 94 | EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); |
78 | 95 | ||
79 | static int cachesize_override __cpuinitdata = -1; | 96 | static int cachesize_override __cpuinitdata = -1; |
diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 5daec699acf0..b4890504284d 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c | |||
@@ -39,6 +39,7 @@ | |||
39 | 39 | ||
40 | static struct cpu_dev *this_cpu __cpuinitdata; | 40 | static struct cpu_dev *this_cpu __cpuinitdata; |
41 | 41 | ||
42 | #ifdef CONFIG_X86_64 | ||
42 | /* We need valid kernel segments for data and code in long mode too | 43 | /* We need valid kernel segments for data and code in long mode too |
43 | * IRET will check the segment types kkeil 2000/10/28 | 44 | * IRET will check the segment types kkeil 2000/10/28 |
44 | * Also sysret mandates a special GDT layout | 45 | * Also sysret mandates a special GDT layout |
@@ -53,6 +54,42 @@ DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { | |||
53 | [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } }, | 54 | [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } }, |
54 | [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } }, | 55 | [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } }, |
55 | } }; | 56 | } }; |
57 | #else | ||
58 | DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { | ||
59 | [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, | ||
60 | [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, | ||
61 | [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } }, | ||
62 | [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } }, | ||
63 | /* | ||
64 | * Segments used for calling PnP BIOS have byte granularity. | ||
65 | * They code segments and data segments have fixed 64k limits, | ||
66 | * the transfer segment sizes are set at run time. | ||
67 | */ | ||
68 | /* 32-bit code */ | ||
69 | [GDT_ENTRY_PNPBIOS_CS32] = { { { 0x0000ffff, 0x00409a00 } } }, | ||
70 | /* 16-bit code */ | ||
71 | [GDT_ENTRY_PNPBIOS_CS16] = { { { 0x0000ffff, 0x00009a00 } } }, | ||
72 | /* 16-bit data */ | ||
73 | [GDT_ENTRY_PNPBIOS_DS] = { { { 0x0000ffff, 0x00009200 } } }, | ||
74 | /* 16-bit data */ | ||
75 | [GDT_ENTRY_PNPBIOS_TS1] = { { { 0x00000000, 0x00009200 } } }, | ||
76 | /* 16-bit data */ | ||
77 | [GDT_ENTRY_PNPBIOS_TS2] = { { { 0x00000000, 0x00009200 } } }, | ||
78 | /* | ||
79 | * The APM segments have byte granularity and their bases | ||
80 | * are set at run time. All have 64k limits. | ||
81 | */ | ||
82 | /* 32-bit code */ | ||
83 | [GDT_ENTRY_APMBIOS_BASE] = { { { 0x0000ffff, 0x00409a00 } } }, | ||
84 | /* 16-bit code */ | ||
85 | [GDT_ENTRY_APMBIOS_BASE+1] = { { { 0x0000ffff, 0x00009a00 } } }, | ||
86 | /* data */ | ||
87 | [GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } }, | ||
88 | |||
89 | [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } }, | ||
90 | [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } }, | ||
91 | } }; | ||
92 | #endif | ||
56 | EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); | 93 | EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); |
57 | 94 | ||
58 | __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; | 95 | __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; |