[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] upgrade 2.6.12 - testing wanted



* Li, Xin B (xin.b.li@xxxxxxxxx) wrote:
> bash-3.00# taskset 2 ls
> (XEN) Domain 0 (vcpu#1) crashed on cpu#1:
> (XEN) CPU:    1
> (XEN) EIP:    e033:[<0000003d00000000>]
> (XEN) EFLAGS: 0000000000000206
> (XEN) rax: 00000000000000cc   rbx: 00007ffffffffc20   rcx:
> 0000003d4b9b29f9   rdx: 00007ffffffffc20
> (XEN) rsi: 0000000000000080   rdi: 0000000000000000   rbp:
> 00007fffffffffaf   rsp: ffff88000f507fc8
> (XEN) r8:  0000000000000080   r9:  00007ffffffffc20   r10:
> 00007ffffffffb80   r11: 0000000000000206
> (XEN) r12: 00007fffffffffae   r13: 00007ffffffffe48   r14:
> 0000000000000004   r15: 0000000000000000
> (XEN) Guest stack trace from rsp=ffff88000f507fc8:
> (XEN)    0000003d4b9b29f9 0000000000000206 0000003d4b9b29f9
> 000000000000e033 0000000000000206 00007fffffffde30 000000000000e02b
> (XEN) Domain 0 shutdown: rebooting machine.
> 
> So, I think cpu 1 is not completely properly initialized for running
> user applications.

Yes, that's exactly the same I'm seeing. The EIP is quite distinct.
Looks like mmap area with low 32bits zeroed.

> BTW, when can you share us your SMP patch against 2.6.12?

How about now? ;-)


Index: xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/head.S
===================================================================
--- xen-unstable-12.orig/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/head.S
+++ xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/head.S
@@ -43,7 +43,6 @@
 startup_64:
 ENTRY(_start)
         cld                
-       movq init_rsp(%rip),%rsp
        /* Copy the necessary stuff from xen_start_info structure. */
        movq  $xen_start_info_union,%rdi
        movq  $64,%rcx          /* sizeof (union xen_start_info_union) / sizeof 
(long) */
@@ -54,6 +53,7 @@ ENTRY(_start)
        cld
 #endif /* CONFIG_SMP */
 
+       movq init_rsp(%rip),%rsp
        /* zero EFLAGS after setting rsp */
        pushq $0
        popfq
@@ -140,6 +140,7 @@ ENTRY(cpu_gdt_table)
        .quad   0,0                     /* TSS */
        .quad   0,0                     /* LDT */
        .quad   0,0,0                   /* three TLS descriptors */ 
+       .quad   0                       /* unused now?   __KERNEL16_CS - 16bit 
PM for S3 wakeup. */
 
 gdt_end:       
        /* asm/segment.h:GDT_ENTRIES must match this */ 
Index: xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/Makefile
===================================================================
--- xen-unstable-12.orig/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/Makefile
+++ xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/Makefile
@@ -25,10 +25,10 @@ obj-$(CONFIG_ACPI_BOOT)             += acpi/
 c-obj-$(CONFIG_X86_MSR)                += msr.o
 obj-$(CONFIG_MICROCODE)                += microcode.o
 obj-$(CONFIG_X86_CPUID)                += cpuid.o
-#obj-$(CONFIG_SMP)             += smp.o smpboot.o trampoline.o
+obj-$(CONFIG_SMP)              += smp.o smpboot.o
 obj-$(CONFIG_X86_LOCAL_APIC)   += apic.o
 c-obj-$(CONFIG_X86_LOCAL_APIC) += nmi.o
-obj-$(CONFIG_X86_IO_APIC)      += io_apic.o mpparse.o
+obj-$(CONFIG_X86_IO_APIC)      += io_apic.o mpparse.o genapic_xen.o
 c-obj-$(CONFIG_X86_IO_APIC)    += genapic.o genapic_cluster.o genapic_flat.o
 #obj-$(CONFIG_PM)              += suspend.o
 #obj-$(CONFIG_SOFTWARE_SUSPEND)        += suspend_asm.o
@@ -54,7 +54,7 @@ intel_cacheinfo-y             += ../../../i386/kern
 quirks-y                       += ../../../i386/kernel/quirks.o
 
 c-link := init_task.o
-s-link := vsyscall.o 
+s-link := vsyscall.o
 
 $(patsubst %.o,$(obj)/%.c,$(c-obj-y) $(c-obj-m) $(c-link)) $(patsubst 
%.o,$(obj)/%.S,$(s-obj-y) $(s-link)):
        @ln -fsn $(srctree)/arch/x86_64/kernel/$(notdir $@) $@
Index: xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/setup64.c
===================================================================
--- 
xen-unstable-12.orig/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/setup64.c
+++ xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/setup64.c
@@ -265,13 +265,13 @@ void __init cpu_init (void)
         * Initialize the per-CPU GDT with the boot GDT,
         * and set up the GDT descriptor:
         */
+#if 0
        if (cpu) {
                memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE);
        }       
 
        cpu_gdt_descr[cpu].size = GDT_SIZE;
        cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu];
-#if 0
        asm volatile("lgdt %0" :: "m" (cpu_gdt_descr[cpu]));
        asm volatile("lidt %0" :: "m" (idt_descr));
 #endif
Index: xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/setup.c
===================================================================
--- xen-unstable-12.orig/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/setup.c
+++ xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/setup.c
@@ -599,6 +599,17 @@ static void __init print_memory_map(char
         }
 }
 
+void __init smp_alloc_memory(void)
+{
+       int cpu;
+
+       for (cpu = 1; cpu < NR_CPUS; cpu++) {
+               cpu_gdt_descr[cpu].address = (unsigned long)
+                       alloc_bootmem_low_pages(PAGE_SIZE);
+               /* XXX free unused pages later */
+       }
+}
+
 void __init setup_arch(char **cmdline_p)
 {
        int i, j;
@@ -738,6 +749,9 @@ void __init setup_arch(char **cmdline_p)
                }
        }
 #endif
+#ifdef CONFIG_SMP
+       smp_alloc_memory();
+#endif
        paging_init();
 #ifdef CONFIG_X86_LOCAL_APIC
        /*
Index: 
xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/xen_entry.S
===================================================================
--- 
xen-unstable-12.orig/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/xen_entry.S
+++ xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/xen_entry.S
@@ -8,11 +8,14 @@
 #define sizeof_vcpu_shift              3
 
 #ifdef CONFIG_SMP
-#define preempt_disable(reg)   incl threadinfo_preempt_count(reg)
-#define preempt_enable(reg)    decl threadinfo_preempt_count(reg)
+//#define preempt_disable(reg) incl threadinfo_preempt_count(reg)
+//#define preempt_enable(reg)  decl threadinfo_preempt_count(reg)
+#define preempt_disable(reg)
+#define preempt_enable(reg)
 #define XEN_GET_VCPU_INFO(reg) preempt_disable(%rbp)                   ; \
                                movq %gs:pda_cpunumber,reg              ; \
-                               shl  $sizeof_vcpu_shift,reg             ; \
+                               shl  $32, reg                           ; \
+                               shr  $32-sizeof_vcpu_shift,reg          ; \
                                addq HYPERVISOR_shared_info,reg
 #define XEN_PUT_VCPU_INFO(reg) preempt_enable(%rbp)                    ; \
 #define XEN_PUT_VCPU_INFO_fixup .byte 0xff,0xff,0xff
Index: xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/irq.c
===================================================================
--- xen-unstable-12.orig/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/irq.c
+++ xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/irq.c
@@ -20,7 +20,11 @@
  */
 
 atomic_t irq_err_count;
-
+#ifdef CONFIG_X86_IO_APIC
+#ifdef APIC_MISMATCH_DEBUG
+atomic_t irq_mis_count;
+#endif
+#endif
 
 /*
  * Generic, controller-independent functions:
Index: xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/smp.c
===================================================================
--- xen-unstable-12.orig/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/smp.c
+++ xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/smp.c
@@ -24,10 +24,15 @@
 #include <asm/mtrr.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
+#if 1 /* Xen */
 #include <asm/mach_apic.h>
+#endif
 #include <asm/mmu_context.h>
 #include <asm/proto.h>
 #include <asm/apicdef.h>
+#include <asm-xen/evtchn.h>
+
+#define xxprint(msg) HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg)
 
 /*
  *     Smarter SMP flushing macros. 
@@ -103,6 +108,7 @@ static inline void leave_mm (unsigned lo
  * 2) Leave the mm if we are in the lazy tlb mode.
  */
 
+#if 0 /* Xen */
 asmlinkage void smp_invalidate_interrupt (void)
 {
        unsigned long cpu;
@@ -251,6 +257,20 @@ void flush_tlb_all(void)
        on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
 }
 
+#else
+asmlinkage void smp_invalidate_interrupt (void)
+{ return; }
+void flush_tlb_current_task(void)
+{ xen_tlb_flush_mask(&current->mm->cpu_vm_mask); }
+void flush_tlb_mm (struct mm_struct * mm)
+{ xen_tlb_flush_mask(&mm->cpu_vm_mask); }
+void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
+{ xen_invlpg_mask(&vma->vm_mm->cpu_vm_mask, va); }
+void flush_tlb_all(void)
+{ xen_tlb_flush_all(); }
+#endif /* Xen */
+
+
 void smp_kdb_stop(void)
 {
        send_IPI_allbutself(KDB_VECTOR);
@@ -310,13 +330,13 @@ static void __smp_call_function (void (*
 
        /* Wait for response */
        while (atomic_read(&data.started) != cpus)
-               cpu_relax();
+               barrier();
 
        if (!wait)
                return;
 
        while (atomic_read(&data.finished) != cpus)
-               cpu_relax();
+               barrier();
 }
 
 /*
@@ -350,7 +370,11 @@ void smp_stop_cpu(void)
         */
        cpu_clear(smp_processor_id(), cpu_online_map);
        local_irq_disable();
+#if 1
+       xxprint("stop_this_cpu disable_local_APIC\n");
+#else
        disable_local_APIC();
+#endif
        local_irq_enable(); 
 }
 
@@ -364,8 +388,10 @@ static void smp_really_stop_cpu(void *du
 void smp_send_stop(void)
 {
        int nolock = 0;
+#if 0
        if (reboot_force)
                return;
+#endif
        /* Don't deadlock on the call lock in panic */
        if (!spin_trylock(&call_lock)) {
                /* ignore locking because we have paniced anyways */
@@ -376,7 +402,11 @@ void smp_send_stop(void)
                spin_unlock(&call_lock);
 
        local_irq_disable();
+#if 1
+       xxprint("stop_this_cpu disable_local_APIC\n");
+#else
        disable_local_APIC();
+#endif
        local_irq_enable();
 }
 
@@ -385,18 +415,17 @@ void smp_send_stop(void)
  * all the work is done automatically when
  * we return from the interrupt.
  */
-asmlinkage void smp_reschedule_interrupt(void)
+asmlinkage irqreturn_t smp_reschedule_interrupt(void)
 {
-       ack_APIC_irq();
+       return IRQ_HANDLED;
 }
 
-asmlinkage void smp_call_function_interrupt(void)
+asmlinkage irqreturn_t smp_call_function_interrupt(void)
 {
        void (*func) (void *info) = call_data->func;
        void *info = call_data->info;
        int wait = call_data->wait;
 
-       ack_APIC_irq();
        /*
         * Notify initiating CPU that I've grabbed the data and am
         * about to execute the function
@@ -413,6 +442,8 @@ asmlinkage void smp_call_function_interr
                mb();
                atomic_inc(&call_data->finished);
        }
+       
+       return IRQ_HANDLED;
 }
 
 int safe_smp_processor_id(void)
@@ -422,7 +453,9 @@ int safe_smp_processor_id(void)
        if (disable_apic)
                return 0;
 
-       apicid = hard_smp_processor_id();
+//     apicid = hard_smp_processor_id();
+       return smp_processor_id();
+
        if (x86_cpu_to_apicid[apicid] == apicid)
                return apicid;
 
Index: xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/traps.c
===================================================================
--- xen-unstable-12.orig/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/traps.c
+++ xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/traps.c
@@ -953,6 +953,17 @@ void __init trap_init(void)
        cpu_init();
 }
 
+void smp_trap_init(trap_info_t *trap_ctxt)
+{
+       trap_info_t *t = trap_table;
+
+       for (t = trap_table; t->address; t++) {
+               trap_ctxt[t->vector].flags = t->flags;
+               trap_ctxt[t->vector].cs = t->cs;
+               trap_ctxt[t->vector].address = t->address;
+       }
+}
+
 
 /* Actual parsing is done early in setup.c. */
 static int __init oops_dummy(char *s)
Index: xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/smpboot.c
===================================================================
--- 
xen-unstable-12.orig/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/smpboot.c
+++ xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/smpboot.c
@@ -57,6 +57,7 @@
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
 #include <asm/nmi.h>
+#include <asm/arch_hooks.h>
 
 /* Change for real CPU hotplug. Note other files need to be fixed
    first too. */
@@ -96,6 +97,7 @@ cpumask_t cpu_sibling_map[NR_CPUS] __cac
 cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
 EXPORT_SYMBOL(cpu_core_map);
 
+#if 0
 /*
  * Trampoline 80x86 program as an array.
  */
@@ -115,6 +117,7 @@ static unsigned long __cpuinit setup_tra
        memcpy(tramp, trampoline_data, trampoline_end - trampoline_data);
        return virt_to_phys(tramp);
 }
+#endif
 
 /*
  * The bootstrap kernel entry code has set these up. Save them for
@@ -130,6 +133,7 @@ static void __cpuinit smp_store_cpu_info
        print_cpu_info(c);
 }
 
+#if 0
 /*
  * New Funky TSC sync algorithm borrowed from IA64.
  * Main advantage is that it doesn't reset the TSCs fully and
@@ -331,6 +335,7 @@ static __init int notscsync_setup(char *
        return 0;
 }
 __setup("notscsync", notscsync_setup);
+#endif
 
 static atomic_t init_deasserted __cpuinitdata;
 
@@ -343,6 +348,7 @@ void __cpuinit smp_callin(void)
        int cpuid, phys_id;
        unsigned long timeout;
 
+#if 0
        /*
         * If waken up by an INIT in an 82489DX configuration
         * we may get here before an INIT-deassert IPI reaches
@@ -352,10 +358,11 @@ void __cpuinit smp_callin(void)
        while (!atomic_read(&init_deasserted))
                cpu_relax();
 
+#endif
        /*
         * (This works even if the APIC is not enabled.)
         */
-       phys_id = GET_APIC_ID(apic_read(APIC_ID));
+       phys_id = smp_processor_id();
        cpuid = smp_processor_id();
        if (cpu_isset(cpuid, cpu_callin_map)) {
                panic("smp_callin: phys CPU#%d, CPU#%d already present??\n",
@@ -389,6 +396,7 @@ void __cpuinit smp_callin(void)
                        cpuid);
        }
 
+#if 0
        /*
         * the boot CPU has finished the init stage and is spinning
         * on callin_map until we finish. We are free to set up this
@@ -398,6 +406,7 @@ void __cpuinit smp_callin(void)
 
        Dprintk("CALLIN, before setup_local_APIC().\n");
        setup_local_APIC();
+#endif
 
        /*
         * Get our bogomips.
@@ -405,7 +414,9 @@ void __cpuinit smp_callin(void)
        calibrate_delay();
        Dprintk("Stack at about %p\n",&cpuid);
 
+#if 0
        disable_APIC_timer();
+#endif
 
        /*
         * Save our processor parameters
@@ -417,6 +428,27 @@ void __cpuinit smp_callin(void)
         */
        cpu_set(cpuid, cpu_callin_map);
 }
+#include <linux/interrupt.h>
+static irqreturn_t ldebug_interrupt(
+       int irq, void *dev_id, struct pt_regs *regs)
+{
+       return IRQ_HANDLED;
+}
+
+static DEFINE_PER_CPU(int, ldebug_irq);
+static char ldebug_name[NR_CPUS][15];
+
+void ldebug_setup(void)
+{
+       int cpu = smp_processor_id();
+
+       per_cpu(ldebug_irq, cpu) = bind_virq_to_irq(VIRQ_DEBUG);
+       sprintf(ldebug_name[cpu], "ldebug%d", cpu);
+       BUG_ON(request_irq(per_cpu(ldebug_irq, cpu), ldebug_interrupt,
+                          SA_INTERRUPT, ldebug_name[cpu], NULL));
+}
+
+extern void local_setup_timer(void);
 
 /*
  * Setup code on secondary processor (after comming out of the trampoline)
@@ -434,6 +466,7 @@ void __cpuinit start_secondary(void)
        /* otherwise gcc will move up the smp_processor_id before the cpu_init 
*/
        barrier();
 
+#if 0
        Dprintk("cpu %d: setting up apic clock\n", smp_processor_id());         
        setup_secondary_APIC_clock();
 
@@ -446,6 +479,12 @@ void __cpuinit start_secondary(void)
        }
 
        enable_APIC_timer();
+#else
+       local_setup_timer();
+       ldebug_setup();
+       smp_intr_init();
+       local_irq_enable();
+#endif
 
        /*
         * Allow the master to continue.
@@ -453,10 +492,12 @@ void __cpuinit start_secondary(void)
        cpu_set(smp_processor_id(), cpu_online_map);
        mb();
 
+#if 0
        /* Wait for TSC sync to not schedule things before.
           We still process interrupts, which could see an inconsistent
           time in that window unfortunately. */
        tsc_sync_wait();
+#endif
 
        cpu_idle();
 }
@@ -502,6 +543,7 @@ static void inquire_remote_apic(int apic
 }
 #endif
 
+#if 0
 /*
  * Kick the secondary to wake up.
  */
@@ -627,6 +669,7 @@ static int __cpuinit wakeup_secondary_vi
 
        return (send_status | accept_status);
 }
+#endif
 
 /*
  * Boot one CPU.
@@ -637,6 +680,14 @@ static int __cpuinit do_boot_cpu(int cpu
        unsigned long boot_error;
        int timeout;
        unsigned long start_rip;
+#if 1
+       vcpu_guest_context_t ctxt;
+       extern void startup_64_smp(void);
+       extern void hypervisor_callback(void);
+       extern void failsafe_callback(void);
+       extern void smp_trap_init(trap_info_t *);
+       int i;
+#endif
        /*
         * We can't use kernel_thread since we must avoid to
         * reschedule the child.
@@ -649,7 +700,7 @@ static int __cpuinit do_boot_cpu(int cpu
 
        cpu_pda[cpu].pcurrent = idle;
 
-       start_rip = setup_trampoline();
+       start_rip = (unsigned long)startup_64_smp;
 
        init_rsp = idle->thread.rsp;
        per_cpu(init_tss,cpu).rsp0 = init_rsp;
@@ -666,6 +717,94 @@ static int __cpuinit do_boot_cpu(int cpu
 
        atomic_set(&init_deasserted, 0);
 
+#if 1
+       if (cpu_gdt_descr[0].size > PAGE_SIZE)
+               BUG();
+       cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
+       memcpy((void *)cpu_gdt_descr[cpu].address,
+               (void *)cpu_gdt_descr[0].address, cpu_gdt_descr[0].size);
+
+       memset(&ctxt, 0, sizeof(ctxt));
+
+       ctxt.flags = VGCF_IN_KERNEL;
+       ctxt.user_regs.ds = __USER_DS;
+       ctxt.user_regs.es = __USER_DS;
+       ctxt.user_regs.fs = 0;
+       ctxt.user_regs.gs = 0;
+       ctxt.user_regs.ss = __KERNEL_DS|0x3;
+       ctxt.user_regs.cs = __KERNEL_CS|0x3;
+       ctxt.user_regs.rip = start_rip;
+       ctxt.user_regs.rsp = idle->thread.rsp;
+       ctxt.user_regs.eflags = (1<<9) | (1<<2) | (idle->thread.io_pl<<12);
+
+       /* FPU is set up to default initial state. */
+       memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
+
+       /* Virtual IDT is empty at start-of-day. */
+       for ( i = 0; i < 256; i++ )
+       {
+               ctxt.trap_ctxt[i].vector = i;
+               ctxt.trap_ctxt[i].cs     = FLAT_KERNEL_CS;
+       }
+       smp_trap_init(ctxt.trap_ctxt);
+
+       /* No LDT. */
+       ctxt.ldt_ents = 0;
+
+       {
+               unsigned long va;
+               int f;
+
+               for (va = cpu_gdt_descr[cpu].address, f = 0;
+                    va < cpu_gdt_descr[cpu].address + cpu_gdt_descr[cpu].size;
+                    va += PAGE_SIZE, f++) {
+                       ctxt.gdt_frames[f] = virt_to_machine(va) >> PAGE_SHIFT;
+                       make_page_readonly((void *)va);
+               }
+               ctxt.gdt_ents = GDT_ENTRIES;
+       }
+
+       /* Ring 1 stack is the initial stack. */
+       ctxt.kernel_ss = __KERNEL_DS;
+       ctxt.kernel_sp = idle->thread.rsp;
+
+       /* Callback handlers. */
+       ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
+       ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
+
+       ctxt.ctrlreg[3] = (unsigned long)virt_to_machine(init_level4_pgt);
+
+       boot_error = HYPERVISOR_boot_vcpu(cpu, &ctxt);
+
+       if (!boot_error) {
+               /*
+                * allow APs to start initializing.
+                */
+               Dprintk("Before Callout %d.\n", cpu);
+               cpu_set(cpu, cpu_callout_map);
+               Dprintk("After Callout %d.\n", cpu);
+
+               /*
+                * Wait 5s total for a response
+                */
+               for (timeout = 0; timeout < 50000; timeout++) {
+                       if (cpu_isset(cpu, cpu_callin_map))
+                               break;  /* It has booted */
+                       udelay(100);
+               }
+
+               if (cpu_isset(cpu, cpu_callin_map)) {
+                       /* number CPUs logically, starting from 1 (BSP is 0) */
+                       Dprintk("OK.\n");
+                       printk("CPU%d: ", cpu);
+                       print_cpu_info(&cpu_data[cpu]);
+                       Dprintk("CPU has booted.\n");
+               } else {
+                       boot_error= 1;
+               }
+       }
+       x86_cpu_to_apicid[cpu] = apicid;
+#else
        Dprintk("Setting warm reset code and vector.\n");
 
        CMOS_WRITE(0xa, 0xf);
@@ -729,6 +868,7 @@ static int __cpuinit do_boot_cpu(int cpu
 #endif
                }
        }
+#endif
        if (boot_error) {
                cpu_clear(cpu, cpu_callout_map); /* was set here 
(do_boot_cpu()) */
                clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */
@@ -857,11 +997,13 @@ static __cpuinit void enforce_max_cpus(u
  */
 static int __cpuinit smp_sanity_check(unsigned max_cpus)
 {
+#if 0
        if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
                printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
                       hard_smp_processor_id());
                physid_set(hard_smp_processor_id(), phys_cpu_present_map);
        }
+#endif
 
        /*
         * If we couldn't find an SMP configuration at boot time,
@@ -876,6 +1018,7 @@ static int __cpuinit smp_sanity_check(un
                return -1;
        }
 
+#if 0
        /*
         * Should not be necessary because the MP table should list the boot
         * CPU too, but we do it for the sake of robustness anyway.
@@ -896,16 +1039,17 @@ static int __cpuinit smp_sanity_check(un
                nr_ioapics = 0;
                return -1;
        }
+#endif
 
        /*
         * If SMP should be disabled, then really disable it!
         */
        if (!max_cpus) {
+               HYPERVISOR_shared_info->n_vcpu = 1;
                printk(KERN_INFO "SMP mode deactivated, forcing use of dummy 
APIC emulation.\n");
                nr_ioapics = 0;
                return -1;
        }
-
        return 0;
 }
 
@@ -928,7 +1072,7 @@ void __cpuinit smp_prepare_cpus(unsigned
         */
        for (i = 0; i < NR_CPUS; i++) {
                int apicid = cpu_present_to_apicid(i);
-               if (physid_isset(apicid, phys_cpu_present_map)) {
+               if (i < HYPERVISOR_shared_info->n_vcpu) {
                        cpu_set(i, cpu_present_map);
                        /* possible map would be different if we supported real
                           CPU hotplug. */
@@ -942,7 +1086,9 @@ void __cpuinit smp_prepare_cpus(unsigned
                return;
        }
 
+       smp_intr_init();
 
+#if 0
        /*
         * Switch from PIC to APIC mode.
         */
@@ -954,6 +1100,7 @@ void __cpuinit smp_prepare_cpus(unsigned
                      GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id);
                /* Or can we switch back to PIC here? */
        }
+#endif
 
        /*
         * Now start the IO-APICs
@@ -967,7 +1114,9 @@ void __cpuinit smp_prepare_cpus(unsigned
         * Set up local APIC timer on boot CPU.
         */
 
+#if 0
        setup_boot_APIC_clock();
+#endif
 }
 
 /*
@@ -1021,6 +1170,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
  */
 void __cpuinit smp_cpus_done(unsigned int max_cpus)
 {
+#if 0
        zap_low_mappings();
        smp_cleanup_boot();
 
@@ -1028,8 +1178,35 @@ void __cpuinit smp_cpus_done(unsigned in
        setup_ioapic_dest();
 #endif
 
-       detect_siblings();
        time_init_gtod();
 
        check_nmi_watchdog();
+#endif
+       detect_siblings();
+}
+
+extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *);
+extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *);
+
+static DEFINE_PER_CPU(int, resched_irq);
+static DEFINE_PER_CPU(int, callfunc_irq);
+static char resched_name[NR_CPUS][15];
+static char callfunc_name[NR_CPUS][15];
+
+void __init smp_intr_init(void)
+{
+       int cpu = smp_processor_id();
+
+       per_cpu(resched_irq, cpu) =
+               bind_ipi_on_cpu_to_irq(cpu, RESCHEDULE_VECTOR);
+       sprintf(resched_name[cpu], "resched%d", cpu);
+       BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
+                          SA_INTERRUPT, resched_name[cpu], NULL));
+
+       per_cpu(callfunc_irq, cpu) =
+               bind_ipi_on_cpu_to_irq(cpu, CALL_FUNCTION_VECTOR);
+       sprintf(callfunc_name[cpu], "callfunc%d", cpu);
+       BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
+                          smp_call_function_interrupt,
+                          SA_INTERRUPT, callfunc_name[cpu], NULL));
 }
Index: xen-unstable-12/linux-2.6.12-xen0/arch/x86_64/kernel/genapic.c
===================================================================
--- xen-unstable-12.orig/linux-2.6.12-xen0/arch/x86_64/kernel/genapic.c
+++ xen-unstable-12/linux-2.6.12-xen0/arch/x86_64/kernel/genapic.c
@@ -31,9 +31,9 @@ u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0
 
 extern struct genapic apic_cluster;
 extern struct genapic apic_flat;
+extern struct genapic apic_xen;
 
-struct genapic *genapic = &apic_flat;
-
+struct genapic *genapic = &apic_xen;
 
 /*
  * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
@@ -94,12 +94,16 @@ void __init clustered_apic_check(void)
                genapic = &apic_cluster;
 
 print:
+       /* hardcode to xen apic functions */
+       genapic = &apic_xen;
        printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
 }
 
 /* Same for both flat and clustered. */
 
+extern void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned 
int dest);
+
 void send_IPI_self(int vector)
 {
-       __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
+       xen_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
 }
Index: xen-unstable-12/linux-2.6.12-xen0/arch/xen/x86_64/kernel/genapic_xen.c
===================================================================
--- /dev/null
+++ xen-unstable-12/linux-2.6.12-xen0/arch/xen/x86_64/kernel/genapic_xen.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2004 James Cleverdon, IBM.
+ * Subject to the GNU Public License, v.2
+ *
+ * Xen APIC subarch code.  Maximum 8 CPUs, logical delivery.
+ *
+ * Hacked for x86-64 by James Cleverdon from i386 architecture code by
+ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
+ * James Cleverdon.
+ *
+ * Hacked to pieces for Xen by Chris Wright.
+ */
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <asm/smp.h>
+#include <asm/ipi.h>
+#include <asm-xen/evtchn.h>
+
+//#undef Dprintk
+//#define Dprintk(x...) printk(x)
+
+DECLARE_PER_CPU(int, ipi_to_evtchn[NR_IPIS]);
+
+static inline void __send_IPI_one(unsigned int cpu, int vector)
+{
+       unsigned int evtchn;
+       Dprintk("%s\n", __FUNCTION__);
+
+       evtchn = per_cpu(ipi_to_evtchn, cpu)[vector];
+       if (evtchn)
+               notify_via_evtchn(evtchn);
+       else
+               printk("send_IPI to unbound port %d/%d", cpu, vector);
+
+}
+
+void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int 
dest)
+{
+       int cpu;
+
+       switch (shortcut) {
+       case APIC_DEST_SELF:
+               __send_IPI_one(smp_processor_id(), vector);
+               break;
+       case APIC_DEST_ALLBUT:
+               for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+                       if (cpu == smp_processor_id())
+                               continue;
+                       if (cpu_isset(cpu, cpu_online_map)) {
+                               __send_IPI_one(cpu, vector);
+                       }
+               }
+               break;
+       case APIC_DEST_ALLINC:
+               for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+                       if (cpu_isset(cpu, cpu_online_map)) {
+                               __send_IPI_one(cpu, vector);
+                       }
+               }
+               break;
+       default:
+               printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
+                      vector);
+               break;
+       }
+
+}
+
+static cpumask_t xen_target_cpus(void)
+{
+       return cpu_online_map;
+}
+
+/*
+ * Set up the logical destination ID.
+ * Do nothing, not called now.
+ */
+static void xen_init_apic_ldr(void)
+{
+       Dprintk("%s\n", __FUNCTION__);
+       return;
+}
+
+static void xen_send_IPI_allbutself(int vector)
+{
+       /*
+        * if there are no other CPUs in the system then
+        * we get an APIC send error if we try to broadcast.
+        * thus we have to avoid sending IPIs in this case.
+        */
+       Dprintk("%s\n", __FUNCTION__);
+       if (num_online_cpus() > 1)
+               xen_send_IPI_shortcut(APIC_DEST_ALLBUT, vector, 
APIC_DEST_LOGICAL);
+}
+
+static void xen_send_IPI_all(int vector)
+{
+       Dprintk("%s\n", __FUNCTION__);
+       xen_send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
+}
+
+static void xen_send_IPI_mask(cpumask_t cpumask, int vector)
+{
+       unsigned long mask = cpus_addr(cpumask)[0];
+       unsigned int cpu;
+       unsigned long flags;
+
+       Dprintk("%s\n", __FUNCTION__);
+       local_irq_save(flags);
+       WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
+
+       for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+               if (cpu_isset(cpu, cpumask)) {
+                       __send_IPI_one(cpu, vector);
+               }
+       }
+       local_irq_restore(flags);
+}
+
+static int xen_apic_id_registered(void)
+{
+       /* better be set */
+       Dprintk("%s\n", __FUNCTION__);
+       return physid_isset(smp_processor_id(), phys_cpu_present_map);
+}
+
+static unsigned int xen_cpu_mask_to_apicid(cpumask_t cpumask)
+{
+       Dprintk("%s\n", __FUNCTION__);
+       return cpus_addr(cpumask)[0] & APIC_ALL_CPUS;
+}
+
+static unsigned int phys_pkg_id(int index_msb)
+{
+       u32 ebx;
+
+       Dprintk("%s\n", __FUNCTION__);
+       ebx = cpuid_ebx(1);
+       return ((ebx >> 24) & 0xFF) >> index_msb;
+}
+
+struct genapic apic_xen =  {
+       .name = "xen",
+       .int_delivery_mode = dest_LowestPrio,
+       .int_dest_mode = (APIC_DEST_LOGICAL != 0),
+       .int_delivery_dest = APIC_DEST_LOGICAL | APIC_DM_LOWEST,
+       .target_cpus = xen_target_cpus,
+       .apic_id_registered = xen_apic_id_registered,
+       .init_apic_ldr = xen_init_apic_ldr,
+       .send_IPI_all = xen_send_IPI_all,
+       .send_IPI_allbutself = xen_send_IPI_allbutself,
+       .send_IPI_mask = xen_send_IPI_mask,
+       .cpu_mask_to_apicid = xen_cpu_mask_to_apicid,
+       .phys_pkg_id = phys_pkg_id,
+};
Index: xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/mpparse.c
===================================================================
--- 
xen-unstable-12.orig/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/mpparse.c
+++ xen-unstable-12/linux-2.6.12-xen-sparse/arch/xen/x86_64/kernel/mpparse.c
@@ -105,7 +105,8 @@ static int __init mpf_checksum(unsigned 
        return sum & 0xFF;
 }
 
-#ifndef CONFIG_XEN
+//#ifndef CONFIG_XEN
+#if 1
 static void __init MP_processor_info (struct mpc_config_processor *m)
 {
        int ver;
@@ -702,7 +703,8 @@ void __init mp_register_lapic (
        if (id == boot_cpu_physical_apicid)
                boot_cpu = 1;
 
-#ifndef CONFIG_XEN
+#if 1
+//#ifndef CONFIG_XEN
        processor.mpc_type = MP_PROCESSOR;
        processor.mpc_apicid = id;
        processor.mpc_apicver = 0x10; /* TBD: lapic version */

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.