X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fi386%2Fmach-voyager%2Fvoyager_smp.c;h=74aeedf277f424896c1beaf01580468ecfbe90b5;hb=refs%2Fheads%2Fvserver;hp=8165626a5c30ba0e2967d9419ea8648033ba91c0;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c index 8165626a5..74aeedf27 100644 --- a/arch/i386/mach-voyager/voyager_smp.c +++ b/arch/i386/mach-voyager/voyager_smp.c @@ -9,7 +9,6 @@ * This file provides all the same external entries as smp.c but uses * the voyager hal to provide the functionality */ -#include #include #include #include @@ -29,6 +28,7 @@ #include #include #include +#include /* TLB state -- visible externally, indexed physically */ DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 }; @@ -86,8 +86,8 @@ static int ack_QIC_CPI(__u8 cpi); static void ack_special_QIC_CPI(__u8 cpi); static void ack_VIC_CPI(__u8 cpi); static void send_CPI_allbutself(__u8 cpi); -static void enable_vic_irq(unsigned int irq); -static void disable_vic_irq(unsigned int irq); +static void mask_vic_irq(unsigned int irq); +static void unmask_vic_irq(unsigned int irq); static unsigned int startup_vic_irq(unsigned int irq); static void enable_local_vic_irq(unsigned int irq); static void disable_local_vic_irq(unsigned int irq); @@ -100,6 +100,7 @@ static void do_boot_cpu(__u8 cpuid); static void do_quad_bootstrap(void); int hard_smp_processor_id(void); +int safe_smp_processor_id(void); /* Inline functions */ static inline void @@ -126,10 +127,10 @@ send_QIC_CPI(__u32 cpuset, __u8 cpi) } static inline void -wrapper_smp_local_timer_interrupt(struct pt_regs *regs) +wrapper_smp_local_timer_interrupt(void) { irq_enter(); - smp_local_timer_interrupt(regs); + smp_local_timer_interrupt(); irq_exit(); } @@ -205,15 +206,12 @@ ack_CPI(__u8 cpi) /* The VIC IRQ descriptors -- these look almost identical to the * 8259 IRQs except that masks and things must be kept per processor */ -static struct hw_interrupt_type vic_irq_type = { - .typename = "VIC-level", - .startup = startup_vic_irq, - .shutdown = disable_vic_irq, - .enable = enable_vic_irq, - .disable = disable_vic_irq, - .ack = before_handle_vic_irq, - .end = after_handle_vic_irq, - .set_affinity = set_vic_irq_affinity, +static struct irq_chip vic_chip = { + .name = "VIC", + .startup = startup_vic_irq, + .mask = mask_vic_irq, + .unmask = unmask_vic_irq, + .set_affinity = set_vic_irq_affinity, }; /* used to count up as CPUs are brought on line (starts at 0) */ @@ -425,6 +423,7 @@ find_smp_config(void) VOYAGER_SUS_IN_CONTROL_PORT); current_thread_info()->cpu = boot_cpu_id; + write_pda(cpu_number, boot_cpu_id); } /* @@ -461,7 +460,7 @@ start_secondary(void *unused) /* external functions not defined in the headers */ extern void calibrate_delay(void); - cpu_init(); + secondary_cpu_init(); /* OK, we're in the routine */ ack_CPI(VIC_CPU_BOOT_CPI); @@ -581,6 +580,15 @@ do_boot_cpu(__u8 cpu) /* init_tasks (in sched.c) is indexed logically */ stack_start.esp = (void *) idle->thread.esp; + /* Pre-allocate and initialize the CPU's GDT and PDA so it + doesn't have to do any memory allocation during the + delicate CPU-bringup phase. */ + if (!init_gdt(cpu, idle)) { + printk(KERN_INFO "Couldn't allocate GDT/PDA for CPU %d\n", cpu); + cpucount--; + return; + } + irq_ctx_init(cpu); /* Note: Don't modify initial ss override */ @@ -661,6 +669,7 @@ do_boot_cpu(__u8 cpu) print_cpu_info(&cpu_data[cpu]); wmb(); cpu_set(cpu, cpu_callout_map); + cpu_set(cpu, cpu_present_map); } else { printk("CPU%d FAILED TO BOOT: ", cpu); @@ -763,6 +772,12 @@ initialize_secondary(void) set_current(hard_get_current()); #endif + /* + * switch to the per CPU GDT we already set up + * in do_boot_cpu() + */ + cpu_set_gdt(current_thread_info()->cpu); + /* * We don't actually need to load the full TSS, * basically just the stack pointer and the eip. @@ -785,7 +800,7 @@ fastcall void smp_vic_sys_interrupt(struct pt_regs *regs) { ack_CPI(VIC_SYS_INT); - printk("Voyager SYSTEM INTERRUPT\n"); + printk("Voyager SYSTEM INTERRUPT\n"); } /* Handle a voyager CMN_INT; These interrupts occur either because of @@ -1134,15 +1149,19 @@ EXPORT_SYMBOL(smp_call_function); fastcall void smp_apic_timer_interrupt(struct pt_regs *regs) { - wrapper_smp_local_timer_interrupt(regs); + struct pt_regs *old_regs = set_irq_regs(regs); + wrapper_smp_local_timer_interrupt(); + set_irq_regs(old_regs); } /* All of the QUAD interrupt GATES */ fastcall void smp_qic_timer_interrupt(struct pt_regs *regs) { + struct pt_regs *old_regs = set_irq_regs(regs); ack_QIC_CPI(QIC_TIMER_CPI); - wrapper_smp_local_timer_interrupt(regs); + wrapper_smp_local_timer_interrupt(); + set_irq_regs(old_regs); } fastcall void @@ -1176,6 +1195,7 @@ smp_qic_call_function_interrupt(struct pt_regs *regs) fastcall void smp_vic_cpi_interrupt(struct pt_regs *regs) { + struct pt_regs *old_regs = set_irq_regs(regs); __u8 cpu = smp_processor_id(); if(is_cpu_quad()) @@ -1184,7 +1204,7 @@ smp_vic_cpi_interrupt(struct pt_regs *regs) ack_VIC_CPI(VIC_CPI_LEVEL0); if(test_and_clear_bit(VIC_TIMER_CPI, &vic_cpi_mailbox[cpu])) - wrapper_smp_local_timer_interrupt(regs); + wrapper_smp_local_timer_interrupt(); if(test_and_clear_bit(VIC_INVALIDATE_CPI, &vic_cpi_mailbox[cpu])) smp_invalidate_interrupt(); if(test_and_clear_bit(VIC_RESCHEDULE_CPI, &vic_cpi_mailbox[cpu])) @@ -1193,6 +1213,7 @@ smp_vic_cpi_interrupt(struct pt_regs *regs) smp_enable_irq_interrupt(); if(test_and_clear_bit(VIC_CALL_FUNCTION_CPI, &vic_cpi_mailbox[cpu])) smp_call_function_interrupt(); + set_irq_regs(old_regs); } static void @@ -1247,6 +1268,12 @@ hard_smp_processor_id(void) return 0; } +int +safe_smp_processor_id(void) +{ + return hard_smp_processor_id(); +} + /* broadcast a halt to all other CPUs */ void smp_send_stop(void) @@ -1257,10 +1284,10 @@ smp_send_stop(void) /* this function is triggered in time.c when a clock tick fires * we need to re-broadcast the tick to all CPUs */ void -smp_vic_timer_interrupt(struct pt_regs *regs) +smp_vic_timer_interrupt(void) { send_CPI_allbutself(VIC_TIMER_CPI); - smp_local_timer_interrupt(regs); + smp_local_timer_interrupt(); } /* local (per CPU) timer interrupt. It does both profiling and @@ -1272,12 +1299,12 @@ smp_vic_timer_interrupt(struct pt_regs *regs) * value into /proc/profile. */ void -smp_local_timer_interrupt(struct pt_regs * regs) +smp_local_timer_interrupt(void) { int cpu = smp_processor_id(); long weight; - profile_tick(CPU_PROFILING, regs); + profile_tick(CPU_PROFILING); if (--per_cpu(prof_counter, cpu) <= 0) { /* * The multiplier may have changed since the last time we got @@ -1295,7 +1322,7 @@ smp_local_timer_interrupt(struct pt_regs * regs) per_cpu(prof_counter, cpu); } - update_process_times(user_mode_vm(regs)); + update_process_times(user_mode_vm(get_irq_regs())); } if( ((1<cpu = hard_smp_processor_id(); + write_pda(cpu_number, hard_smp_processor_id()); +}