aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/head.S
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2007-05-02 13:27:16 -0400
committerAndi Kleen <andi@basil.nowhere.org>2007-05-02 13:27:16 -0400
commit7c3576d261ce046789a7db14f43303f8120910c7 (patch)
treead27a8459bbcdb183fe2411aec3b840942992ad5 /arch/i386/kernel/head.S
parent7a61d35d4b4056e7711031202da7605e052f4137 (diff)
[PATCH] i386: Convert PDA into the percpu section
Currently x86 (similar to x84-64) has a special per-cpu structure called "i386_pda" which can be easily and efficiently referenced via the %fs register. An ELF section is more flexible than a structure, allowing any piece of code to use this area. Indeed, such a section already exists: the per-cpu area. So this patch: (1) Removes the PDA and uses per-cpu variables for each current member. (2) Replaces the __KERNEL_PDA segment with __KERNEL_PERCPU. (3) Creates a per-cpu mirror of __per_cpu_offset called this_cpu_off, which can be used to calculate addresses for this CPU's variables. (4) Simplifies startup, because %fs doesn't need to be loaded with a special segment at early boot; it can be deferred until the first percpu area is allocated (or never for UP). The result is less code and one less x86-specific concept. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Signed-off-by: Andi Kleen <ak@suse.de> Cc: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/i386/kernel/head.S')
-rw-r--r--arch/i386/kernel/head.S31
1 files changed, 6 insertions, 25 deletions
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index bb36c24311b4..12277d8938df 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -317,12 +317,12 @@ is386: movl $2,%ecx # set MP
317 movl %eax,%cr0 317 movl %eax,%cr0
318 318
319 call check_x87 319 call check_x87
320 call setup_pda
321 lgdt early_gdt_descr 320 lgdt early_gdt_descr
322 lidt idt_descr 321 lidt idt_descr
323 ljmp $(__KERNEL_CS),$1f 322 ljmp $(__KERNEL_CS),$1f
3241: movl $(__KERNEL_DS),%eax # reload all the segment registers 3231: movl $(__KERNEL_DS),%eax # reload all the segment registers
325 movl %eax,%ss # after changing gdt. 324 movl %eax,%ss # after changing gdt.
325 movl %eax,%fs # gets reset once there's real percpu
326 326
327 movl $(__USER_DS),%eax # DS/ES contains default USER segment 327 movl $(__USER_DS),%eax # DS/ES contains default USER segment
328 movl %eax,%ds 328 movl %eax,%ds
@@ -332,16 +332,17 @@ is386: movl $2,%ecx # set MP
332 movl %eax,%gs 332 movl %eax,%gs
333 lldt %ax 333 lldt %ax
334 334
335 movl $(__KERNEL_PDA),%eax
336 mov %eax,%fs
337
338 cld # gcc2 wants the direction flag cleared at all times 335 cld # gcc2 wants the direction flag cleared at all times
339 pushl $0 # fake return address for unwinder 336 pushl $0 # fake return address for unwinder
340#ifdef CONFIG_SMP 337#ifdef CONFIG_SMP
341 movb ready, %cl 338 movb ready, %cl
342 movb $1, ready 339 movb $1, ready
343 cmpb $0,%cl # the first CPU calls start_kernel 340 cmpb $0,%cl # the first CPU calls start_kernel
344 jne initialize_secondary # all other CPUs call initialize_secondary 341 je 1f
342 movl $(__KERNEL_PERCPU), %eax
343 movl %eax,%fs # set this cpu's percpu
344 jmp initialize_secondary # all other CPUs call initialize_secondary
3451:
345#endif /* CONFIG_SMP */ 346#endif /* CONFIG_SMP */
346 jmp start_kernel 347 jmp start_kernel
347 348
@@ -365,23 +366,6 @@ check_x87:
365 ret 366 ret
366 367
367/* 368/*
368 * Point the GDT at this CPU's PDA. On boot this will be
369 * cpu_gdt_table and boot_pda; for secondary CPUs, these will be
370 * that CPU's GDT and PDA.
371 */
372ENTRY(setup_pda)
373 /* get the PDA pointer */
374 movl start_pda, %eax
375
376 /* slot the PDA address into the GDT */
377 mov early_gdt_descr+2, %ecx
378 mov %ax, (__KERNEL_PDA+0+2)(%ecx) /* base & 0x0000ffff */
379 shr $16, %eax
380 mov %al, (__KERNEL_PDA+4+0)(%ecx) /* base & 0x00ff0000 */
381 mov %ah, (__KERNEL_PDA+4+3)(%ecx) /* base & 0xff000000 */
382 ret
383
384/*
385 * setup_idt 369 * setup_idt
386 * 370 *
387 * sets up a idt with 256 entries pointing to 371 * sets up a idt with 256 entries pointing to
@@ -553,9 +537,6 @@ ENTRY(empty_zero_page)
553 * This starts the data section. 537 * This starts the data section.
554 */ 538 */
555.data 539.data
556ENTRY(start_pda)
557 .long boot_pda
558
559ENTRY(stack_start) 540ENTRY(stack_start)
560 .long init_thread_union+THREAD_SIZE 541 .long init_thread_union+THREAD_SIZE
561 .long __BOOT_DS 542 .long __BOOT_DS