i386: init early_gdt_descr and idle task properly on voyager
PATCH 1/1 i386: init early_gdt_descr and idle task properly on voyager
Initialize early_gdt_descr and idle task properly.
[ Incremental fix for "i386: introduce voyager smp_ops, fix voyager build" ]
--- 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(-)
===================================================================
arch/i386/kernel/smpboot.c +0 -3
@@ -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
===================================================================
arch/i386/mach-voyager/voyager_smp.c +2 -0
@@ -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 */
===================================================================
include/asm-i386/processor.h +3 -0
@@ -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 );
Quoted 3 lines · On Sunday 29 April 2007 02:21:27 Jeremy Fitzhardinge wrote:
Initialize
early_gdt_descrand 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
Quoted 3 lines · Jeremy Fitzhardinge
Initialize
early_gdt_descrand 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
arch/i386/kernel/cpu/common.c +19 -0
@@ -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
arch/i386/kernel/smpboot.c +0 -22
@@ -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
include/asm-i386/processor.h +4 -0
@@ -749,6 +749,10 @@ extern unsigned long boot_option_idle_ovextern 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 );
Quoted 9 lines · James Bottomley
Quoted 4 lines · Jeremy Fitzhardinge
Initialize
early_gdt_descrand 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
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.
--- 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(-)
===================================================================
arch/i386/kernel/Makefile +1 -0
@@ -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
===================================================================
arch/i386/kernel/smp.c +6 -59
89 lines not on this page · raw message
===================================================================
arch/i386/kernel/smpboot.c +0 -22
@@ -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
===================================================================
arch/i386/kernel/smpcommon.c new file +79 -0
79 lines not on this page · raw message
===================================================================
include/asm-i386/processor.h +4 -0
@@ -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;
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.
--- arch/i386/mach-voyager/voyager_smp.c | 73 ++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 29 deletions(-)
===================================================================
arch/i386/mach-voyager/voyager_smp.c +44 -29
179 lines not on this page · raw message
Quoted 5 lines · Jeremy Fitzhardinge
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.
--- arch/i386/mach-voyager/voyager_smp.c | 73 ++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 29 deletions(-)
===================================================================
arch/i386/mach-voyager/voyager_smp.c +40 -65
@@ -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 __initsmp_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, +};