Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c3576d2 authored by Jeremy Fitzhardinge's avatar Jeremy Fitzhardinge Committed by Andi Kleen
Browse files

[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: default avatarRusty Russell <rusty@rustcorp.com.au>
Signed-off-by: default avatarJeremy Fitzhardinge <jeremy@xensource.com>
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Cc: Andi Kleen <ak@suse.de>
parent 7a61d35d
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
#include <asm/processor.h>
#include <asm/thread_info.h>
#include <asm/elf.h>
#include <asm/pda.h>

#define DEFINE(sym, val) \
        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -101,10 +100,6 @@ void foo(void)

	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);

	BLANK();
 	OFFSET(PDA_cpu, i386_pda, cpu_number);
	OFFSET(PDA_pcurrent, i386_pda, pcurrent);

#ifdef CONFIG_PARAVIRT
	BLANK();
	OFFSET(PARAVIRT_enabled, paravirt_ops, paravirt_enabled);
+3 −14
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@
#include <asm/apic.h>
#include <mach_apic.h>
#endif
#include <asm/pda.h>

#include "cpu.h"

@@ -47,13 +46,10 @@ DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
	[GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */

	[GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
	[GDT_ENTRY_PDA] = { 0x00000000, 0x00c09200 }, /* set in setup_pda */
	[GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
} };
EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);

DEFINE_PER_CPU(struct i386_pda, _cpu_pda);
EXPORT_PER_CPU_SYMBOL(_cpu_pda);

static int cachesize_override __cpuinitdata = -1;
static int disable_x86_fxsr __cpuinitdata;
static int disable_x86_serial_nr __cpuinitdata = 1;
@@ -634,21 +630,14 @@ void __init early_cpu_init(void)
#endif
}

/* Make sure %gs is initialized properly in idle threads */
/* Make sure %fs is initialized properly in idle threads */
struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
{
	memset(regs, 0, sizeof(struct pt_regs));
	regs->xfs = __KERNEL_PDA;
	regs->xfs = __KERNEL_PERCPU;
	return regs;
}

/* Initial PDA used by boot CPU */
struct i386_pda boot_pda = {
	._pda = &boot_pda,
	.cpu_number = 0,
	.pcurrent = &init_task,
};

/*
 * cpu_init() initializes state that is per-CPU. Some data is already
 * initialized (naturally) in the bootstrap process, such as the GDT
+2 −3
Original line number Diff line number Diff line
@@ -132,7 +132,7 @@ VM_MASK = 0x00020000
	movl $(__USER_DS), %edx; \
	movl %edx, %ds; \
	movl %edx, %es; \
	movl $(__KERNEL_PDA), %edx; \
	movl $(__KERNEL_PERCPU), %edx; \
	movl %edx, %fs

#define RESTORE_INT_REGS \
@@ -556,7 +556,6 @@ END(syscall_badsys)

#define FIXUP_ESPFIX_STACK \
	/* since we are on a wrong stack, we cant make it a C code :( */ \
	movl %fs:PDA_cpu, %ebx; \
	PER_CPU(gdt_page, %ebx); \
	GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \
	addl %esp, %eax; \
@@ -681,7 +680,7 @@ error_code:
	pushl %fs
	CFI_ADJUST_CFA_OFFSET 4
	/*CFI_REL_OFFSET fs, 0*/
	movl $(__KERNEL_PDA), %ecx
	movl $(__KERNEL_PERCPU), %ecx
	movl %ecx, %fs
	UNWIND_ESPFIX_STACK
	popl %ecx
+6 −25
Original line number Diff line number Diff line
@@ -317,12 +317,12 @@ is386: movl $2,%ecx # set MP
	movl %eax,%cr0

	call check_x87
	call setup_pda
	lgdt early_gdt_descr
	lidt idt_descr
	ljmp $(__KERNEL_CS),$1f
1:	movl $(__KERNEL_DS),%eax	# reload all the segment registers
	movl %eax,%ss			# after changing gdt.
	movl %eax,%fs			# gets reset once there's real percpu

	movl $(__USER_DS),%eax		# DS/ES contains default USER segment
	movl %eax,%ds
@@ -332,16 +332,17 @@ is386: movl $2,%ecx # set MP
	movl %eax,%gs
	lldt %ax

	movl $(__KERNEL_PDA),%eax
	mov  %eax,%fs

	cld			# gcc2 wants the direction flag cleared at all times
	pushl $0		# fake return address for unwinder
#ifdef CONFIG_SMP
	movb ready, %cl
	movb $1, ready
	cmpb $0,%cl		# the first CPU calls start_kernel
	jne initialize_secondary # all other CPUs call initialize_secondary
	je   1f
	movl $(__KERNEL_PERCPU), %eax
	movl %eax,%fs		# set this cpu's percpu
	jmp initialize_secondary # all other CPUs call initialize_secondary
1:
#endif /* CONFIG_SMP */
	jmp start_kernel

@@ -364,23 +365,6 @@ check_x87:
	.byte 0xDB,0xE4		/* fsetpm for 287, ignored by 387 */
	ret

/*
 * Point the GDT at this CPU's PDA.  On boot this will be
 * cpu_gdt_table and boot_pda; for secondary CPUs, these will be
 * that CPU's GDT and PDA.
 */
ENTRY(setup_pda)
	/* get the PDA pointer */
	movl start_pda, %eax

	/* slot the PDA address into the GDT */
	mov early_gdt_descr+2, %ecx
	mov %ax, (__KERNEL_PDA+0+2)(%ecx)		/* base & 0x0000ffff */
	shr $16, %eax
	mov %al, (__KERNEL_PDA+4+0)(%ecx)		/* base & 0x00ff0000 */
	mov %ah, (__KERNEL_PDA+4+3)(%ecx)		/* base & 0xff000000 */
	ret

/*
 *  setup_idt
 *
@@ -553,9 +537,6 @@ ENTRY(empty_zero_page)
 * This starts the data section.
 */
.data
ENTRY(start_pda)
	.long boot_pda

ENTRY(stack_start)
	.long init_thread_union+THREAD_SIZE
	.long __BOOT_DS
+0 −2
Original line number Diff line number Diff line
@@ -28,5 +28,3 @@ EXPORT_SYMBOL(__read_lock_failed);
#endif

EXPORT_SYMBOL(csum_partial);

EXPORT_SYMBOL(_proxy_pda);
Loading