aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlauber Costa <gcosta@redhat.com>2008-05-28 19:19:53 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-08 06:48:16 -0400
commita939098afcfa5f81d3474782ec15c6d114e57763 (patch)
tree62c21fb10d6b58dc8247c34e68ab5562e045b8d0
parent736f12bff9d9e7b4e895c64f73b190c8383fc2a1 (diff)
x86: move x86_64 gdt closer to i386
i386 and x86_64 used two different schemes for maintaining the gdt. With this patch, x86_64 initial gdt table is defined in a .c file, same way as i386 is now. Also, we call it "gdt_page", and the descriptor, "early_gdt_descr". This way we achieve common naming, which can allow for more code integration. Signed-off-by: Glauber Costa <gcosta@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/head_64.S48
-rw-r--r--arch/x86/kernel/setup64.c5
-rw-r--r--arch/x86/kernel/setup_64.c19
-rw-r--r--arch/x86/kernel/smpboot.c12
-rw-r--r--arch/x86/kernel/x8664_ksyms_64.c5
-rw-r--r--include/asm-x86/desc.h24
-rw-r--r--include/asm-x86/segment.h23
7 files changed, 48 insertions, 88 deletions
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 918a2711aff6..32f5a114d1a2 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -203,7 +203,7 @@ ENTRY(secondary_startup_64)
203 * addresses where we're currently running on. We have to do that here 203 * addresses where we're currently running on. We have to do that here
204 * because in 32bit we couldn't load a 64bit linear address. 204 * because in 32bit we couldn't load a 64bit linear address.
205 */ 205 */
206 lgdt cpu_gdt_descr(%rip) 206 lgdt early_gdt_descr(%rip)
207 207
208 /* set up data segments. actually 0 would do too */ 208 /* set up data segments. actually 0 would do too */
209 movl $__KERNEL_DS,%eax 209 movl $__KERNEL_DS,%eax
@@ -391,54 +391,16 @@ NEXT_PAGE(level2_spare_pgt)
391 391
392 .data 392 .data
393 .align 16 393 .align 16
394 .globl cpu_gdt_descr 394 .globl early_gdt_descr
395cpu_gdt_descr: 395early_gdt_descr:
396 .word gdt_end-cpu_gdt_table-1 396 .word GDT_ENTRIES*8-1
397gdt: 397 .quad per_cpu__gdt_page
398 .quad cpu_gdt_table
399#ifdef CONFIG_SMP
400 .rept NR_CPUS-1
401 .word 0
402 .quad 0
403 .endr
404#endif
405 398
406ENTRY(phys_base) 399ENTRY(phys_base)
407 /* This must match the first entry in level2_kernel_pgt */ 400 /* This must match the first entry in level2_kernel_pgt */
408 .quad 0x0000000000000000 401 .quad 0x0000000000000000
409 402
410/* We need valid kernel segments for data and code in long mode too
411 * IRET will check the segment types kkeil 2000/10/28
412 * Also sysret mandates a special GDT layout
413 */
414
415 .section .data.page_aligned, "aw"
416 .align PAGE_SIZE
417
418/* The TLS descriptors are currently at a different place compared to i386.
419 Hopefully nobody expects them at a fixed place (Wine?) */
420 403
421ENTRY(cpu_gdt_table)
422 .quad 0x0000000000000000 /* NULL descriptor */
423 .quad 0x00cf9b000000ffff /* __KERNEL32_CS */
424 .quad 0x00af9b000000ffff /* __KERNEL_CS */
425 .quad 0x00cf93000000ffff /* __KERNEL_DS */
426 .quad 0x00cffb000000ffff /* __USER32_CS */
427 .quad 0x00cff3000000ffff /* __USER_DS, __USER32_DS */
428 .quad 0x00affb000000ffff /* __USER_CS */
429 .quad 0x0 /* unused */
430 .quad 0,0 /* TSS */
431 .quad 0,0 /* LDT */
432 .quad 0,0,0 /* three TLS descriptors */
433 .quad 0x0000f40000000000 /* node/CPU stored in limit */
434gdt_end:
435 /* asm/segment.h:GDT_ENTRIES must match this */
436 /* This should be a multiple of the cache line size */
437 /* GDTs of other CPUs are now dynamically allocated */
438
439 /* zero the remaining page */
440 .fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0
441
442 .section .bss, "aw", @nobits 404 .section .bss, "aw", @nobits
443 .align L1_CACHE_BYTES 405 .align L1_CACHE_BYTES
444ENTRY(idt_table) 406ENTRY(idt_table)
diff --git a/arch/x86/kernel/setup64.c b/arch/x86/kernel/setup64.c
index fc1a56da8240..70ff07186772 100644
--- a/arch/x86/kernel/setup64.c
+++ b/arch/x86/kernel/setup64.c
@@ -202,11 +202,8 @@ void __cpuinit cpu_init (void)
202 * Initialize the per-CPU GDT with the boot GDT, 202 * Initialize the per-CPU GDT with the boot GDT,
203 * and set up the GDT descriptor: 203 * and set up the GDT descriptor:
204 */ 204 */
205 if (cpu)
206 memcpy(get_cpu_gdt_table(cpu), cpu_gdt_table, GDT_SIZE);
207 205
208 cpu_gdt_descr[cpu].size = GDT_SIZE; 206 switch_to_new_gdt();
209 load_gdt((const struct desc_ptr *)&cpu_gdt_descr[cpu]);
210 load_idt((const struct desc_ptr *)&idt_descr); 207 load_idt((const struct desc_ptr *)&idt_descr);
211 208
212 memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8); 209 memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8);
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 504caeaffd58..a93300de4da9 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -81,8 +81,6 @@
81#define ARCH_SETUP 81#define ARCH_SETUP
82#endif 82#endif
83 83
84#include "cpu/cpu.h"
85
86/* 84/*
87 * Machine setup.. 85 * Machine setup..
88 */ 86 */
@@ -228,6 +226,23 @@ static inline void copy_edd(void)
228} 226}
229#endif 227#endif
230 228
229/* Overridden in paravirt.c if CONFIG_PARAVIRT */
230void __attribute__((weak)) __init memory_setup(void)
231{
232 machine_specific_memory_setup();
233}
234
235/* Current gdt points %fs at the "master" per-cpu area: after this,
236 * it's on the real one. */
237void switch_to_new_gdt(void)
238{
239 struct desc_ptr gdt_descr;
240
241 gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
242 gdt_descr.size = GDT_SIZE - 1;
243 load_gdt(&gdt_descr);
244}
245
231/* 246/*
232 * setup_arch - architecture-specific boot-time initializations 247 * setup_arch - architecture-specific boot-time initializations
233 * 248 *
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index a71e3cad5470..fe2bd515d6cc 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -849,14 +849,8 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
849 .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), 849 .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
850 }; 850 };
851 INIT_WORK(&c_idle.work, do_fork_idle); 851 INIT_WORK(&c_idle.work, do_fork_idle);
852#ifdef CONFIG_X86_64
853 /* allocate memory for gdts of secondary cpus. Hotplug is considered */
854 if (!cpu_gdt_descr[cpu].address &&
855 !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) {
856 printk(KERN_ERR "Failed to allocate GDT for CPU %d\n", cpu);
857 return -1;
858 }
859 852
853#ifdef CONFIG_X86_64
860 /* Allocate node local memory for AP pdas */ 854 /* Allocate node local memory for AP pdas */
861 if (cpu > 0) { 855 if (cpu > 0) {
862 boot_error = get_local_pda(cpu); 856 boot_error = get_local_pda(cpu);
@@ -898,7 +892,6 @@ do_rest:
898#ifdef CONFIG_X86_32 892#ifdef CONFIG_X86_32
899 per_cpu(current_task, cpu) = c_idle.idle; 893 per_cpu(current_task, cpu) = c_idle.idle;
900 init_gdt(cpu); 894 init_gdt(cpu);
901 early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
902 c_idle.idle->thread.ip = (unsigned long) start_secondary; 895 c_idle.idle->thread.ip = (unsigned long) start_secondary;
903 /* Stack for startup_32 can be just as for start_secondary onwards */ 896 /* Stack for startup_32 can be just as for start_secondary onwards */
904 irq_ctx_init(cpu); 897 irq_ctx_init(cpu);
@@ -908,6 +901,7 @@ do_rest:
908 initial_code = (unsigned long)start_secondary; 901 initial_code = (unsigned long)start_secondary;
909 clear_tsk_thread_flag(c_idle.idle, TIF_FORK); 902 clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
910#endif 903#endif
904 early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
911 stack_start.sp = (void *) c_idle.idle->thread.sp; 905 stack_start.sp = (void *) c_idle.idle->thread.sp;
912 906
913 /* start_ip had better be page-aligned! */ 907 /* start_ip had better be page-aligned! */
@@ -1252,8 +1246,8 @@ void __init native_smp_prepare_boot_cpu(void)
1252 int me = smp_processor_id(); 1246 int me = smp_processor_id();
1253#ifdef CONFIG_X86_32 1247#ifdef CONFIG_X86_32
1254 init_gdt(me); 1248 init_gdt(me);
1255 switch_to_new_gdt();
1256#endif 1249#endif
1250 switch_to_new_gdt();
1257 /* already set me in cpu_online_map in boot_cpu_init() */ 1251 /* already set me in cpu_online_map in boot_cpu_init() */
1258 cpu_set(me, cpu_callout_map); 1252 cpu_set(me, cpu_callout_map);
1259 per_cpu(cpu_state, me) = CPU_ONLINE; 1253 per_cpu(cpu_state, me) = CPU_ONLINE;
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index f6c05d0410fb..2f306a826897 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -53,8 +53,3 @@ EXPORT_SYMBOL(init_level4_pgt);
53EXPORT_SYMBOL(load_gs_index); 53EXPORT_SYMBOL(load_gs_index);
54 54
55EXPORT_SYMBOL(_proxy_pda); 55EXPORT_SYMBOL(_proxy_pda);
56
57#ifdef CONFIG_PARAVIRT
58/* Virtualized guests may want to use it */
59EXPORT_SYMBOL_GPL(cpu_gdt_descr);
60#endif
diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h
index b3875d4b4fab..07f9f2b17be8 100644
--- a/include/asm-x86/desc.h
+++ b/include/asm-x86/desc.h
@@ -29,11 +29,17 @@ static inline void fill_ldt(struct desc_struct *desc,
29extern struct desc_ptr idt_descr; 29extern struct desc_ptr idt_descr;
30extern gate_desc idt_table[]; 30extern gate_desc idt_table[];
31 31
32struct gdt_page {
33 struct desc_struct gdt[GDT_ENTRIES];
34} __attribute__((aligned(PAGE_SIZE)));
35DECLARE_PER_CPU(struct gdt_page, gdt_page);
36
37static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
38{
39 return per_cpu(gdt_page, cpu).gdt;
40}
41
32#ifdef CONFIG_X86_64 42#ifdef CONFIG_X86_64
33extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
34extern struct desc_ptr cpu_gdt_descr[];
35/* the cpu gdt accessor */
36#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
37 43
38static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func, 44static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
39 unsigned dpl, unsigned ist, unsigned seg) 45 unsigned dpl, unsigned ist, unsigned seg)
@@ -51,16 +57,6 @@ static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
51} 57}
52 58
53#else 59#else
54struct gdt_page {
55 struct desc_struct gdt[GDT_ENTRIES];
56} __attribute__((aligned(PAGE_SIZE)));
57DECLARE_PER_CPU(struct gdt_page, gdt_page);
58
59static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
60{
61 return per_cpu(gdt_page, cpu).gdt;
62}
63
64static inline void pack_gate(gate_desc *gate, unsigned char type, 60static inline void pack_gate(gate_desc *gate, unsigned char type,
65 unsigned long base, unsigned dpl, unsigned flags, 61 unsigned long base, unsigned dpl, unsigned flags,
66 unsigned short seg) 62 unsigned short seg)
diff --git a/include/asm-x86/segment.h b/include/asm-x86/segment.h
index ed5131dd7d92..dfc8601c0892 100644
--- a/include/asm-x86/segment.h
+++ b/include/asm-x86/segment.h
@@ -61,18 +61,14 @@
61#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1) 61#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
62 62
63#define GDT_ENTRY_DEFAULT_USER_CS 14 63#define GDT_ENTRY_DEFAULT_USER_CS 14
64#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS * 8 + 3)
65 64
66#define GDT_ENTRY_DEFAULT_USER_DS 15 65#define GDT_ENTRY_DEFAULT_USER_DS 15
67#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS * 8 + 3)
68 66
69#define GDT_ENTRY_KERNEL_BASE 12 67#define GDT_ENTRY_KERNEL_BASE 12
70 68
71#define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE + 0) 69#define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE + 0)
72#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8)
73 70
74#define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE + 1) 71#define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE + 1)
75#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8)
76 72
77#define GDT_ENTRY_TSS (GDT_ENTRY_KERNEL_BASE + 4) 73#define GDT_ENTRY_TSS (GDT_ENTRY_KERNEL_BASE + 4)
78#define GDT_ENTRY_LDT (GDT_ENTRY_KERNEL_BASE + 5) 74#define GDT_ENTRY_LDT (GDT_ENTRY_KERNEL_BASE + 5)
@@ -139,10 +135,11 @@
139#else 135#else
140#include <asm/cache.h> 136#include <asm/cache.h>
141 137
142#define __KERNEL_CS 0x10 138#define GDT_ENTRY_KERNEL32_CS 1
143#define __KERNEL_DS 0x18 139#define GDT_ENTRY_KERNEL_CS 2
140#define GDT_ENTRY_KERNEL_DS 3
144 141
145#define __KERNEL32_CS 0x08 142#define __KERNEL32_CS (GDT_ENTRY_KERNEL32_CS * 8)
146 143
147/* 144/*
148 * we cannot use the same code segment descriptor for user and kernel 145 * we cannot use the same code segment descriptor for user and kernel
@@ -150,10 +147,10 @@
150 * The segment offset needs to contain a RPL. Grr. -AK 147 * The segment offset needs to contain a RPL. Grr. -AK
151 * GDT layout to get 64bit syscall right (sysret hardcodes gdt offsets) 148 * GDT layout to get 64bit syscall right (sysret hardcodes gdt offsets)
152 */ 149 */
153 150#define GDT_ENTRY_DEFAULT_USER32_CS 4
154#define __USER32_CS 0x23 /* 4*8+3 */ 151#define GDT_ENTRY_DEFAULT_USER_DS 5
155#define __USER_DS 0x2b /* 5*8+3 */ 152#define GDT_ENTRY_DEFAULT_USER_CS 6
156#define __USER_CS 0x33 /* 6*8+3 */ 153#define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS * 8 + 3)
157#define __USER32_DS __USER_DS 154#define __USER32_DS __USER_DS
158 155
159#define GDT_ENTRY_TSS 8 /* needs two entries */ 156#define GDT_ENTRY_TSS 8 /* needs two entries */
@@ -175,6 +172,10 @@
175 172
176#endif 173#endif
177 174
175#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8)
176#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8)
177#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS* 8 + 3)
178#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS* 8 + 3)
178#ifndef CONFIG_PARAVIRT 179#ifndef CONFIG_PARAVIRT
179#define get_kernel_rpl() 0 180#define get_kernel_rpl() 0
180#endif 181#endif