diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2007-05-02 13:27:16 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2007-05-02 13:27:16 -0400 |
commit | 7c3576d261ce046789a7db14f43303f8120910c7 (patch) | |
tree | ad27a8459bbcdb183fe2411aec3b840942992ad5 /arch/i386/kernel/head.S | |
parent | 7a61d35d4b4056e7711031202da7605e052f4137 (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.S | 31 |
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 |
324 | 1: movl $(__KERNEL_DS),%eax # reload all the segment registers | 323 | 1: 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 | ||
345 | 1: | ||
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 | */ | ||
372 | ENTRY(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 |
556 | ENTRY(start_pda) | ||
557 | .long boot_pda | ||
558 | |||
559 | ENTRY(stack_start) | 540 | ENTRY(stack_start) |
560 | .long init_thread_union+THREAD_SIZE | 541 | .long init_thread_union+THREAD_SIZE |
561 | .long __BOOT_DS | 542 | .long __BOOT_DS |