* [PATCH] i386: init early_gdt_descr and idle task properly on voyager @ 2007-04-29 0:21 Jeremy Fitzhardinge 2007-04-29 0:52 ` Andi Kleen 2007-04-30 18:26 ` James Bottomley 0 siblings, 2 replies; 5+ messages in thread From: Jeremy Fitzhardinge @ 2007-04-29 0:21 UTC (permalink / raw) To: Andi Kleen; +Cc: James Bottomley, Eric W. Biederman, Linux Kernel Mailing List Initialize early_gdt_descr and idle task properly. [ Incremental fix for "i386: introduce voyager smp_ops, fix voyager build" ] Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: Eric W. Biederman <ebiederm@xmission.com> --- arch/i386/kernel/smpboot.c | 3 --- arch/i386/mach-voyager/voyager_smp.c | 2 ++ include/asm-i386/processor.h | 3 +++ 3 files changed, 5 insertions(+), 3 deletions(-) =================================================================== --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -763,9 +763,6 @@ static inline struct task_struct * alloc #define alloc_idle_task(cpu) fork_idle(cpu) #endif -/* Defined in head.S */ -extern struct Xgt_desc_struct early_gdt_descr; - static int __cpuinit do_boot_cpu(int apicid, int cpu) /* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad =================================================================== --- a/arch/i386/mach-voyager/voyager_smp.c +++ b/arch/i386/mach-voyager/voyager_smp.c @@ -580,6 +580,8 @@ do_boot_cpu(__u8 cpu) stack_start.esp = (void *) idle->thread.esp; init_gdt(cpu); + per_cpu(current_task, cpu) = idle; + early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); irq_ctx_init(cpu); /* Note: Don't modify initial ss override */ =================================================================== --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -749,6 +749,9 @@ extern void enable_sep_cpu(void); extern void enable_sep_cpu(void); extern int sysenter_setup(void); +/* Defined in head.S */ +extern struct Xgt_desc_struct early_gdt_descr; + extern void cpu_set_gdt(int); extern void switch_to_new_gdt(void); extern void cpu_init(void); ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] i386: init early_gdt_descr and idle task properly on voyager 2007-04-29 0:21 [PATCH] i386: init early_gdt_descr and idle task properly on voyager Jeremy Fitzhardinge @ 2007-04-29 0:52 ` Andi Kleen 2007-04-30 18:26 ` James Bottomley 1 sibling, 0 replies; 5+ messages in thread From: Andi Kleen @ 2007-04-29 0:52 UTC (permalink / raw) To: Jeremy Fitzhardinge Cc: James Bottomley, Eric W. Biederman, Linux Kernel Mailing List On Sunday 29 April 2007 02:21:27 Jeremy Fitzhardinge wrote: > Initialize early_gdt_descr and idle task properly. > > [ Incremental fix for "i386: introduce voyager smp_ops, fix voyager build" ] Please do a merged patch again and I'm waiting for it being tested. -Andi ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] i386: init early_gdt_descr and idle task properly on voyager 2007-04-29 0:21 [PATCH] i386: init early_gdt_descr and idle task properly on voyager Jeremy Fitzhardinge 2007-04-29 0:52 ` Andi Kleen @ 2007-04-30 18:26 ` James Bottomley 2007-04-30 18:33 ` Jeremy Fitzhardinge 1 sibling, 1 reply; 5+ messages in thread From: James Bottomley @ 2007-04-30 18:26 UTC (permalink / raw) To: Jeremy Fitzhardinge Cc: Andi Kleen, Eric W. Biederman, Linux Kernel Mailing List On Sat, 2007-04-28 at 17:21 -0700, Jeremy Fitzhardinge wrote: > Initialize early_gdt_descr and idle task properly. > > [ Incremental fix for "i386: introduce voyager smp_ops, fix voyager build" ] Still not quite enough. this is what I need to complete the build: James Index: voyager-2.6/arch/i386/kernel/cpu/common.c =================================================================== --- voyager-2.6.orig/arch/i386/kernel/cpu/common.c 2007-04-30 12:49:45.000000000 -0500 +++ voyager-2.6/arch/i386/kernel/cpu/common.c 2007-04-30 13:03:42.000000000 -0500 @@ -21,6 +21,9 @@ #include "cpu.h" +DEFINE_PER_CPU(unsigned long, this_cpu_off); +EXPORT_PER_CPU_SYMBOL(this_cpu_off); + DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_KERNEL_CS] = { 0x0000ffff, 0x00cf9a00 }, [GDT_ENTRY_KERNEL_DS] = { 0x0000ffff, 0x00cf9200 }, @@ -650,6 +653,22 @@ void switch_to_new_gdt(void) asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory"); } +/* Initialize the CPU's GDT. This is either the boot CPU doing itself + (still using the master per-cpu area), or a CPU doing it for a + secondary which will soon come up. */ +__cpuinit void init_gdt(int cpu) +{ + struct desc_struct *gdt = get_cpu_gdt_table(cpu); + + pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a, + (u32 *)&gdt[GDT_ENTRY_PERCPU].b, + __per_cpu_offset[cpu], 0xFFFFF, + 0x80 | DESCTYPE_S | 0x2, 0x8); + + per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; + per_cpu(cpu_number, cpu) = cpu; +} + /* * cpu_init() initializes state that is per-CPU. Some data is already * initialized (naturally) in the bootstrap process, such as the GDT Index: voyager-2.6/arch/i386/kernel/smpboot.c =================================================================== --- voyager-2.6.orig/arch/i386/kernel/smpboot.c 2007-04-30 12:49:45.000000000 -0500 +++ voyager-2.6/arch/i386/kernel/smpboot.c 2007-04-30 13:03:45.000000000 -0500 @@ -99,9 +99,6 @@ EXPORT_SYMBOL(x86_cpu_to_apicid); u8 apicid_2_node[MAX_APICID]; -DEFINE_PER_CPU(unsigned long, this_cpu_off); -EXPORT_PER_CPU_SYMBOL(this_cpu_off); - /* * Trampoline 80x86 program as an array. */ @@ -764,25 +761,6 @@ static inline struct task_struct * alloc #define alloc_idle_task(cpu) fork_idle(cpu) #endif -/* Initialize the CPU's GDT. This is either the boot CPU doing itself - (still using the master per-cpu area), or a CPU doing it for a - secondary which will soon come up. */ -static __cpuinit void init_gdt(int cpu) -{ - struct desc_struct *gdt = get_cpu_gdt_table(cpu); - - pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a, - (u32 *)&gdt[GDT_ENTRY_PERCPU].b, - __per_cpu_offset[cpu], 0xFFFFF, - 0x80 | DESCTYPE_S | 0x2, 0x8); - - per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; - per_cpu(cpu_number, cpu) = cpu; -} - -/* Defined in head.S */ -extern struct Xgt_desc_struct early_gdt_descr; - static int __cpuinit do_boot_cpu(int apicid, int cpu) /* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad Index: voyager-2.6/include/asm-i386/processor.h =================================================================== --- voyager-2.6.orig/include/asm-i386/processor.h 2007-04-30 12:49:45.000000000 -0500 +++ voyager-2.6/include/asm-i386/processor.h 2007-04-30 12:54:47.000000000 -0500 @@ -749,6 +749,10 @@ extern unsigned long boot_option_idle_ov extern void enable_sep_cpu(void); extern int sysenter_setup(void); +/* Defined in head.S */ +extern struct Xgt_desc_struct early_gdt_descr; + +extern void init_gdt(int cpu); extern void cpu_set_gdt(int); extern void switch_to_new_gdt(void); extern void cpu_init(void); ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] i386: init early_gdt_descr and idle task properly on voyager 2007-04-30 18:26 ` James Bottomley @ 2007-04-30 18:33 ` Jeremy Fitzhardinge 2007-05-01 14:51 ` James Bottomley 0 siblings, 1 reply; 5+ messages in thread From: Jeremy Fitzhardinge @ 2007-04-30 18:33 UTC (permalink / raw) To: James Bottomley; +Cc: Andi Kleen, Eric W. Biederman, Linux Kernel Mailing List [-- Attachment #1: Type: text/plain, Size: 472 bytes --] James Bottomley wrote: > On Sat, 2007-04-28 at 17:21 -0700, Jeremy Fitzhardinge wrote: > >> Initialize early_gdt_descr and idle task properly. >> >> [ Incremental fix for "i386: introduce voyager smp_ops, fix voyager build" ] >> > > Still not quite enough. this is what I need to complete the build: > Yep. I fixed this up in a later pair of patches: "i386-common-smp.patch" and "i386-fix-voyager-build.patch". Does it work for you when you do this? J [-- Attachment #2: i386-common-smp.patch --] [-- Type: text/x-patch, Size: 8789 bytes --] Subject: i386: move common parts of smp into their own file Several parts of kernel/smp.c and smpboot.c are generally useful for other subarchitectures and paravirt_ops implementations, so make them available for reuse. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: Eric W. Biederman <ebiederm@xmission.com> --- arch/i386/kernel/Makefile | 1 arch/i386/kernel/smp.c | 65 +++------------------------------- arch/i386/kernel/smpboot.c | 22 ----------- arch/i386/kernel/smpcommon.c | 79 ++++++++++++++++++++++++++++++++++++++++++ include/asm-i386/processor.h | 4 ++ 5 files changed, 90 insertions(+), 81 deletions(-) =================================================================== --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_X86_SMP) += smp.o smpboot.o tsc_sync.o +obj-$(CONFIG_SMP) += smpcommon.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o =================================================================== --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -468,7 +468,7 @@ void flush_tlb_all(void) * it goes straight through and wastes no time serializing * anything. Worst case is that we lose a reschedule ... */ -void native_smp_send_reschedule(int cpu) +static void native_smp_send_reschedule(int cpu) { WARN_ON(cpu_is_offline(cpu)); send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR); @@ -547,9 +547,10 @@ static void __smp_call_function(void (*f * You must not call this function with disabled interrupts or from a * hardware interrupt handler or from a bottom half handler. */ -int native_smp_call_function_mask(cpumask_t mask, - void (*func)(void *), void *info, - int wait) +static int +native_smp_call_function_mask(cpumask_t mask, + void (*func)(void *), void *info, + int wait) { struct call_data_struct data; cpumask_t allbutself; @@ -600,60 +601,6 @@ int native_smp_call_function_mask(cpumas return 0; } -/** - * smp_call_function(): Run a function on all other CPUs. - * @func: The function to run. This must be fast and non-blocking. - * @info: An arbitrary pointer to pass to the function. - * @nonatomic: Unused. - * @wait: If true, wait (atomically) until function has completed on other CPUs. - * - * Returns 0 on success, else a negative status code. - * - * If @wait is true, then returns once @func has returned; otherwise - * it returns just before the target cpu calls @func. - * - * You must not call this function with disabled interrupts or from a - * hardware interrupt handler or from a bottom half handler. - */ -int smp_call_function(void (*func) (void *info), void *info, int nonatomic, - int wait) -{ - return smp_call_function_mask(cpu_online_map, func, info, wait); -} -EXPORT_SYMBOL(smp_call_function); - -/** - * smp_call_function_single - Run a function on another CPU - * @cpu: The target CPU. Cannot be the calling CPU. - * @func: The function to run. This must be fast and non-blocking. - * @info: An arbitrary pointer to pass to the function. - * @nonatomic: Unused. - * @wait: If true, wait until function has completed on other CPUs. - * - * Returns 0 on success, else a negative status code. - * - * If @wait is true, then returns once @func has returned; otherwise - * it returns just before the target cpu calls @func. - */ -int smp_call_function_single(int cpu, void (*func) (void *info), void *info, - int nonatomic, int wait) -{ - /* prevent preemption and reschedule on another processor */ - int ret; - int me = get_cpu(); - if (cpu == me) { - WARN_ON(1); - put_cpu(); - return -EBUSY; - } - - ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait); - - put_cpu(); - return ret; -} -EXPORT_SYMBOL(smp_call_function_single); - static void stop_this_cpu (void * dummy) { local_irq_disable(); @@ -671,7 +618,7 @@ static void stop_this_cpu (void * dummy) * this function calls the 'stop' function on all other CPUs in the system. */ -void native_smp_send_stop(void) +static void native_smp_send_stop(void) { /* Don't deadlock on the call lock in panic */ int nolock = !spin_trylock(&call_lock); =================================================================== --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -99,9 +99,6 @@ EXPORT_SYMBOL(x86_cpu_to_apicid); u8 apicid_2_node[MAX_APICID]; -DEFINE_PER_CPU(unsigned long, this_cpu_off); -EXPORT_PER_CPU_SYMBOL(this_cpu_off); - /* * Trampoline 80x86 program as an array. */ @@ -766,25 +763,6 @@ static inline struct task_struct * alloc #define alloc_idle_task(cpu) fork_idle(cpu) #endif -/* Initialize the CPU's GDT. This is either the boot CPU doing itself - (still using the master per-cpu area), or a CPU doing it for a - secondary which will soon come up. */ -static __cpuinit void init_gdt(int cpu) -{ - struct desc_struct *gdt = get_cpu_gdt_table(cpu); - - pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a, - (u32 *)&gdt[GDT_ENTRY_PERCPU].b, - __per_cpu_offset[cpu], 0xFFFFF, - 0x80 | DESCTYPE_S | 0x2, 0x8); - - per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; - per_cpu(cpu_number, cpu) = cpu; -} - -/* Defined in head.S */ -extern struct Xgt_desc_struct early_gdt_descr; - static int __cpuinit do_boot_cpu(int apicid, int cpu) /* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad =================================================================== --- /dev/null +++ b/arch/i386/kernel/smpcommon.c @@ -0,0 +1,79 @@ +/* + * SMP stuff which is common to all sub-architectures. + */ +#include <linux/module.h> +#include <asm/smp.h> + +DEFINE_PER_CPU(unsigned long, this_cpu_off); +EXPORT_PER_CPU_SYMBOL(this_cpu_off); + +/* Initialize the CPU's GDT. This is either the boot CPU doing itself + (still using the master per-cpu area), or a CPU doing it for a + secondary which will soon come up. */ +__cpuinit void init_gdt(int cpu) +{ + struct desc_struct *gdt = get_cpu_gdt_table(cpu); + + pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a, + (u32 *)&gdt[GDT_ENTRY_PERCPU].b, + __per_cpu_offset[cpu], 0xFFFFF, + 0x80 | DESCTYPE_S | 0x2, 0x8); + + per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; + per_cpu(cpu_number, cpu) = cpu; +} + + +/** + * smp_call_function(): Run a function on all other CPUs. + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @nonatomic: Unused. + * @wait: If true, wait (atomically) until function has completed on other CPUs. + * + * Returns 0 on success, else a negative status code. + * + * If @wait is true, then returns once @func has returned; otherwise + * it returns just before the target cpu calls @func. + * + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler or from a bottom half handler. + */ +int smp_call_function(void (*func) (void *info), void *info, int nonatomic, + int wait) +{ + return smp_call_function_mask(cpu_online_map, func, info, wait); +} +EXPORT_SYMBOL(smp_call_function); + +/** + * smp_call_function_single - Run a function on another CPU + * @cpu: The target CPU. Cannot be the calling CPU. + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @nonatomic: Unused. + * @wait: If true, wait until function has completed on other CPUs. + * + * Returns 0 on success, else a negative status code. + * + * If @wait is true, then returns once @func has returned; otherwise + * it returns just before the target cpu calls @func. + */ +int smp_call_function_single(int cpu, void (*func) (void *info), void *info, + int nonatomic, int wait) +{ + /* prevent preemption and reschedule on another processor */ + int ret; + int me = get_cpu(); + if (cpu == me) { + WARN_ON(1); + put_cpu(); + return -EBUSY; + } + + ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait); + + put_cpu(); + return ret; +} +EXPORT_SYMBOL(smp_call_function_single); =================================================================== --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -749,9 +749,13 @@ extern void enable_sep_cpu(void); extern void enable_sep_cpu(void); extern int sysenter_setup(void); +/* Defined in head.S */ +extern struct Xgt_desc_struct early_gdt_descr; + extern void cpu_set_gdt(int); extern void switch_to_new_gdt(void); extern void cpu_init(void); +extern void init_gdt(int cpu); extern int force_mwait; [-- Attachment #3: i386-fix-voyager-build.patch --] [-- Type: text/x-patch, Size: 5957 bytes --] Subject: i386: fix voyager build This adds an smp_ops for voyager, and hooks things up appropriately. This is the first baby-step to making subarch runtime switchable. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: Eric W. Biederman <ebiederm@xmission.com> --- arch/i386/mach-voyager/voyager_smp.c | 73 ++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 29 deletions(-) =================================================================== --- a/arch/i386/mach-voyager/voyager_smp.c +++ b/arch/i386/mach-voyager/voyager_smp.c @@ -28,7 +28,6 @@ #include <asm/pgalloc.h> #include <asm/tlbflush.h> #include <asm/arch_hooks.h> -#include <asm/pda.h> /* TLB state -- visible externally, indexed physically */ DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 }; @@ -423,7 +422,7 @@ find_smp_config(void) VOYAGER_SUS_IN_CONTROL_PORT); current_thread_info()->cpu = boot_cpu_id; - write_pda(cpu_number, boot_cpu_id); + x86_write_percpu(cpu_number, boot_cpu_id); } /* @@ -436,7 +435,7 @@ smp_store_cpu_info(int id) *c = boot_cpu_data; - identify_cpu(c); + identify_secondary_cpu(c); } /* set up the trampoline and return the physical address of the code */ @@ -460,7 +459,7 @@ start_secondary(void *unused) /* external functions not defined in the headers */ extern void calibrate_delay(void); - secondary_cpu_init(); + cpu_init(); /* OK, we're in the routine */ ack_CPI(VIC_CPU_BOOT_CPI); @@ -580,7 +579,9 @@ do_boot_cpu(__u8 cpu) /* init_tasks (in sched.c) is indexed logically */ stack_start.esp = (void *) idle->thread.esp; - init_gdt(cpu, idle); + init_gdt(cpu); + per_cpu(current_task, cpu) = idle; + early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); irq_ctx_init(cpu); /* Note: Don't modify initial ss override */ @@ -884,8 +885,8 @@ smp_invalidate_interrupt(void) /* This routine is called with a physical cpu mask */ static void -flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, - unsigned long va) +voyager_flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, + unsigned long va) { int stuck = 50000; @@ -937,7 +938,7 @@ flush_tlb_current_task(void) cpu_mask = cpus_addr(mm->cpu_vm_mask)[0] & ~(1 << smp_processor_id()); local_flush_tlb(); if (cpu_mask) - flush_tlb_others(cpu_mask, mm, FLUSH_ALL); + voyager_flush_tlb_others(cpu_mask, mm, FLUSH_ALL); preempt_enable(); } @@ -959,7 +960,7 @@ flush_tlb_mm (struct mm_struct * mm) leave_mm(smp_processor_id()); } if (cpu_mask) - flush_tlb_others(cpu_mask, mm, FLUSH_ALL); + voyager_flush_tlb_others(cpu_mask, mm, FLUSH_ALL); preempt_enable(); } @@ -980,7 +981,7 @@ void flush_tlb_page(struct vm_area_struc } if (cpu_mask) - flush_tlb_others(cpu_mask, mm, va); + voyager_flush_tlb_others(cpu_mask, mm, va); preempt_enable(); } @@ -1076,12 +1077,13 @@ smp_call_function_interrupt(void) [RETURNS] 0 on success, else a negative status code. Does not return until remote CPUs are nearly ready to execute <<func>> or are or have executed. */ -int -smp_call_function (void (*func) (void *info), void *info, int retry, - int wait) +static int +voyager_smp_call_function_mask (cpumask_t cpumask, + void (*func) (void *info), void *info, + int wait) { struct call_data_struct data; - __u32 mask = cpus_addr(cpu_online_map)[0]; + u32 mask = cpumask.bits[0]; mask &= ~(1<<smp_processor_id()); @@ -1116,7 +1118,6 @@ smp_call_function (void (*func) (void *i return 0; } -EXPORT_SYMBOL(smp_call_function); /* Sorry about the name. In an APIC based system, the APICs * themselves are programmed to send a timer interrupt. This is used @@ -1231,8 +1232,8 @@ smp_alloc_memory(void) } /* send a reschedule CPI to one CPU by physical CPU number*/ -void -smp_send_reschedule(int cpu) +static void +voyager_smp_send_reschedule(int cpu) { send_one_CPI(cpu, VIC_RESCHEDULE_CPI); } @@ -1261,8 +1262,8 @@ safe_smp_processor_id(void) } /* broadcast a halt to all other CPUs */ -void -smp_send_stop(void) +static void +voyager_smp_send_stop(void) { smp_call_function(smp_stop_cpu_function, NULL, 1, 1); } @@ -1924,23 +1925,26 @@ smp_voyager_power_off(void *dummy) smp_stop_cpu_function(NULL); } -void __init -smp_prepare_cpus(unsigned int max_cpus) +static void __init +voyager_smp_prepare_cpus(unsigned int max_cpus) { /* FIXME: ignore max_cpus for now */ smp_boot_cpus(); } -void __devinit smp_prepare_boot_cpu(void) -{ +static void __devinit voyager_smp_prepare_boot_cpu(void) +{ + init_gdt(smp_processor_id()); + switch_to_new_gdt(); + cpu_set(smp_processor_id(), cpu_online_map); cpu_set(smp_processor_id(), cpu_callout_map); cpu_set(smp_processor_id(), cpu_possible_map); cpu_set(smp_processor_id(), cpu_present_map); } -int __devinit -__cpu_up(unsigned int cpu) +static int __devinit +voyager_cpu_up(unsigned int cpu) { /* This only works at boot for x86. See "rewrite" above. */ if (cpu_isset(cpu, smp_commenced_mask)) @@ -1956,8 +1960,8 @@ __cpu_up(unsigned int cpu) return 0; } -void __init -smp_cpus_done(unsigned int max_cpus) +static void __init +voyager_smp_cpus_done(unsigned int max_cpus) { zap_low_mappings(); } @@ -1966,5 +1970,16 @@ smp_setup_processor_id(void) smp_setup_processor_id(void) { current_thread_info()->cpu = hard_smp_processor_id(); - write_pda(cpu_number, hard_smp_processor_id()); -} + x86_write_percpu(cpu_number, hard_smp_processor_id()); +} + +struct smp_ops smp_ops = { + .smp_prepare_boot_cpu = voyager_smp_prepare_boot_cpu, + .smp_prepare_cpus = voyager_smp_prepare_cpus, + .cpu_up = voyager_cpu_up, + .smp_cpus_done = voyager_smp_cpus_done, + + .smp_send_stop = voyager_smp_send_stop, + .smp_send_reschedule = voyager_smp_send_reschedule, + .smp_call_function_mask = voyager_smp_call_function_mask, +}; ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] i386: init early_gdt_descr and idle task properly on voyager 2007-04-30 18:33 ` Jeremy Fitzhardinge @ 2007-05-01 14:51 ` James Bottomley 0 siblings, 0 replies; 5+ messages in thread From: James Bottomley @ 2007-05-01 14:51 UTC (permalink / raw) To: Jeremy Fitzhardinge Cc: Andi Kleen, Eric W. Biederman, Linux Kernel Mailing List On Mon, 2007-04-30 at 11:33 -0700, Jeremy Fitzhardinge wrote: > Yep. I fixed this up in a later pair of patches: > "i386-common-smp.patch" and > "i386-fix-voyager-build.patch". > > Does it work for you when you do this? Not quite ... the voyager build fix doesn't quite fix the build. The attached is what I need to fully build and boot voyager James --- Subject: i386: fix voyager build This adds an smp_ops for voyager, and hooks things up appropriately. This is the first baby-step to making subarch runtime switchable. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: Eric W. Biederman <ebiederm@xmission.com> --- arch/i386/mach-voyager/voyager_smp.c | 73 ++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 29 deletions(-) =================================================================== Index: voyager-2.6/arch/i386/mach-voyager/voyager_smp.c =================================================================== --- voyager-2.6.orig/arch/i386/mach-voyager/voyager_smp.c 2007-05-01 09:21:24.000000000 -0500 +++ voyager-2.6/arch/i386/mach-voyager/voyager_smp.c 2007-05-01 09:36:47.000000000 -0500 @@ -28,7 +28,6 @@ #include <asm/pgalloc.h> #include <asm/tlbflush.h> #include <asm/arch_hooks.h> -#include <asm/pda.h> /* TLB state -- visible externally, indexed physically */ DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 }; @@ -423,7 +422,7 @@ find_smp_config(void) VOYAGER_SUS_IN_CONTROL_PORT); current_thread_info()->cpu = boot_cpu_id; - write_pda(cpu_number, boot_cpu_id); + x86_write_percpu(cpu_number, boot_cpu_id); } /* @@ -436,7 +435,7 @@ smp_store_cpu_info(int id) *c = boot_cpu_data; - identify_cpu(c); + identify_secondary_cpu(c); } /* set up the trampoline and return the physical address of the code */ @@ -460,7 +459,7 @@ start_secondary(void *unused) /* external functions not defined in the headers */ extern void calibrate_delay(void); - secondary_cpu_init(); + cpu_init(); /* OK, we're in the routine */ ack_CPI(VIC_CPU_BOOT_CPI); @@ -571,7 +570,9 @@ do_boot_cpu(__u8 cpu) /* init_tasks (in sched.c) is indexed logically */ stack_start.esp = (void *) idle->thread.esp; - init_gdt(cpu, idle); + init_gdt(cpu); + per_cpu(current_task, cpu) = idle; + early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); irq_ctx_init(cpu); /* Note: Don't modify initial ss override */ @@ -858,8 +859,8 @@ smp_invalidate_interrupt(void) /* This routine is called with a physical cpu mask */ static void -flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, - unsigned long va) +voyager_flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, + unsigned long va) { int stuck = 50000; @@ -911,7 +912,7 @@ flush_tlb_current_task(void) cpu_mask = cpus_addr(mm->cpu_vm_mask)[0] & ~(1 << smp_processor_id()); local_flush_tlb(); if (cpu_mask) - flush_tlb_others(cpu_mask, mm, FLUSH_ALL); + voyager_flush_tlb_others(cpu_mask, mm, FLUSH_ALL); preempt_enable(); } @@ -933,7 +934,7 @@ flush_tlb_mm (struct mm_struct * mm) leave_mm(smp_processor_id()); } if (cpu_mask) - flush_tlb_others(cpu_mask, mm, FLUSH_ALL); + voyager_flush_tlb_others(cpu_mask, mm, FLUSH_ALL); preempt_enable(); } @@ -954,7 +955,7 @@ void flush_tlb_page(struct vm_area_struc } if (cpu_mask) - flush_tlb_others(cpu_mask, mm, va); + voyager_flush_tlb_others(cpu_mask, mm, va); preempt_enable(); } @@ -1043,11 +1044,12 @@ smp_call_function_interrupt(void) } static int -__smp_call_function_mask (void (*func) (void *info), void *info, int retry, - int wait, __u32 mask) +voyager_smp_call_function_mask (cpumask_t cpumask, void (*func) (void *info), + void *info, int wait) { struct call_data_struct data; + u32 mask = cpus_addr(cpumask)[0]; mask &= ~(1<<smp_processor_id()); if (!mask) @@ -1082,47 +1084,6 @@ __smp_call_function_mask (void (*func) ( return 0; } -/* Call this function on all CPUs using the function_interrupt above - <func> The function to run. This must be fast and non-blocking. - <info> An arbitrary pointer to pass to the function. - <retry> If true, keep retrying until ready. - <wait> If true, wait until function has completed on other CPUs. - [RETURNS] 0 on success, else a negative status code. Does not return until - remote CPUs are nearly ready to execute <<func>> or are or have executed. -*/ -int -smp_call_function(void (*func) (void *info), void *info, int retry, - int wait) -{ - __u32 mask = cpus_addr(cpu_online_map)[0]; - - return __smp_call_function_mask(func, info, retry, wait, mask); -} -EXPORT_SYMBOL(smp_call_function); - -/* - * smp_call_function_single - Run a function on another CPU - * @func: The function to run. This must be fast and non-blocking. - * @info: An arbitrary pointer to pass to the function. - * @nonatomic: Currently unused. - * @wait: If true, wait until function has completed on other CPUs. - * - * Retrurns 0 on success, else a negative status code. - * - * Does not return until the remote CPU is nearly ready to execute <func> - * or is or has executed. - */ - -int -smp_call_function_single(int cpu, void (*func) (void *info), void *info, - int nonatomic, int wait) -{ - __u32 mask = 1 << cpu; - - return __smp_call_function_mask(func, info, nonatomic, wait, mask); -} -EXPORT_SYMBOL(smp_call_function_single); - /* Sorry about the name. In an APIC based system, the APICs * themselves are programmed to send a timer interrupt. This is used * by linux to reschedule the processor. Voyager doesn't have this, @@ -1236,8 +1197,8 @@ smp_alloc_memory(void) } /* send a reschedule CPI to one CPU by physical CPU number*/ -void -smp_send_reschedule(int cpu) +static void +voyager_smp_send_reschedule(int cpu) { send_one_CPI(cpu, VIC_RESCHEDULE_CPI); } @@ -1266,8 +1227,8 @@ safe_smp_processor_id(void) } /* broadcast a halt to all other CPUs */ -void -smp_send_stop(void) +static void +voyager_smp_send_stop(void) { smp_call_function(smp_stop_cpu_function, NULL, 1, 1); } @@ -1929,23 +1890,26 @@ smp_voyager_power_off(void *dummy) smp_stop_cpu_function(NULL); } -void __init -smp_prepare_cpus(unsigned int max_cpus) +static void __init +voyager_smp_prepare_cpus(unsigned int max_cpus) { /* FIXME: ignore max_cpus for now */ smp_boot_cpus(); } -void __devinit smp_prepare_boot_cpu(void) +static void __devinit voyager_smp_prepare_boot_cpu(void) { + init_gdt(smp_processor_id()); + switch_to_new_gdt(); + cpu_set(smp_processor_id(), cpu_online_map); cpu_set(smp_processor_id(), cpu_callout_map); cpu_set(smp_processor_id(), cpu_possible_map); cpu_set(smp_processor_id(), cpu_present_map); } -int __devinit -__cpu_up(unsigned int cpu) +static int __devinit +voyager_cpu_up(unsigned int cpu) { /* This only works at boot for x86. See "rewrite" above. */ if (cpu_isset(cpu, smp_commenced_mask)) @@ -1961,8 +1925,8 @@ __cpu_up(unsigned int cpu) return 0; } -void __init -smp_cpus_done(unsigned int max_cpus) +static void __init +voyager_smp_cpus_done(unsigned int max_cpus) { zap_low_mappings(); } @@ -1971,5 +1935,16 @@ void __init smp_setup_processor_id(void) { current_thread_info()->cpu = hard_smp_processor_id(); - write_pda(cpu_number, hard_smp_processor_id()); + x86_write_percpu(cpu_number, hard_smp_processor_id()); } + +struct smp_ops smp_ops = { + .smp_prepare_boot_cpu = voyager_smp_prepare_boot_cpu, + .smp_prepare_cpus = voyager_smp_prepare_cpus, + .cpu_up = voyager_cpu_up, + .smp_cpus_done = voyager_smp_cpus_done, + + .smp_send_stop = voyager_smp_send_stop, + .smp_send_reschedule = voyager_smp_send_reschedule, + .smp_call_function_mask = voyager_smp_call_function_mask, +}; ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2007-05-01 14:51 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-04-29 0:21 [PATCH] i386: init early_gdt_descr and idle task properly on voyager Jeremy Fitzhardinge 2007-04-29 0:52 ` Andi Kleen 2007-04-30 18:26 ` James Bottomley 2007-04-30 18:33 ` Jeremy Fitzhardinge 2007-05-01 14:51 ` James Bottomley
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox