[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Merge xen-unstable into xen-ia64-unstable
# HG changeset patch # User djm@xxxxxxxxxxxxxxx # Node ID 61b3b357d827ce0d803b7fee2e72e65cfe2aec41 # Parent 93e27f7ca8a83da233a90ae11c75745c86ec639a # Parent d88e98fd4f7a6d007b3f905a1f3c36c53fd7427a Merge xen-unstable into xen-ia64-unstable diff -r 93e27f7ca8a8 -r 61b3b357d827 .hgignore --- a/.hgignore Thu Sep 29 22:22:02 2005 +++ b/.hgignore Thu Sep 29 23:28:44 2005 @@ -158,6 +158,7 @@ ^tools/xenstore/xs_dom0_test$ ^tools/xenstore/xs_random$ ^tools/xenstore/xs_stress$ +^tools/xenstore/xs_tdb_dump$ ^tools/xenstore/xs_test$ ^tools/xenstore/xs_watch_stress$ ^tools/xentrace/xenctx$ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Thu Sep 29 23:28:44 2005 @@ -2684,7 +2684,7 @@ # # File systems # -CONFIG_EXT2_FS=m +CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_SECURITY=y @@ -2913,7 +2913,7 @@ # CONFIG_KEYS_DEBUG_PROC_KEYS is not set CONFIG_SECURITY=y # CONFIG_SECURITY_NETWORK is not set -CONFIG_SECURITY_CAPABILITIES=m +CONFIG_SECURITY_CAPABILITIES=y CONFIG_SECURITY_ROOTPLUG=m CONFIG_SECURITY_SECLVL=m CONFIG_SECURITY_SELINUX=y diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c Thu Sep 29 23:28:44 2005 @@ -112,6 +112,10 @@ #ifdef CONFIG_HOTPLUG_CPU #include <asm/nmi.h> +#ifdef CONFIG_SMP +extern void smp_suspend(void); +extern void smp_resume(void); +#endif /* We don't actually take CPU down, just spin without interrupts. */ static inline void play_dead(void) { @@ -120,6 +124,14 @@ HYPERVISOR_yield(); __flush_tlb_all(); + /* + * Restore IPI/IRQ mappings before marking online to prevent + * race between pending interrupts and restoration of handler. + */ +#ifdef CONFIG_SMP + local_irq_enable(); /* XXX Needed for smp_resume(). Clean me up. */ + smp_resume(); +#endif cpu_set(smp_processor_id(), cpu_online_map); } #else @@ -135,10 +147,6 @@ * low exit latency (ie sit in a loop waiting for * somebody to say that they'd like to reschedule) */ -#ifdef CONFIG_SMP -extern void smp_suspend(void); -extern void smp_resume(void); -#endif void cpu_idle (void) { int cpu = _smp_processor_id(); @@ -166,9 +174,6 @@ HYPERVISOR_vcpu_down(cpu); #endif play_dead(); -#ifdef CONFIG_SMP - smp_resume(); -#endif local_irq_enable(); } diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/i386/kernel/smp.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smp.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smp.c Thu Sep 29 23:28:44 2005 @@ -131,21 +131,9 @@ static inline void __send_IPI_one(unsigned int cpu, int vector) { - unsigned int evtchn; - - evtchn = per_cpu(ipi_to_evtchn, cpu)[vector]; - // printk("send_IPI_mask_bitmask cpu %d vector %d evtchn %d\n", cpu, vector, evtchn); - if (evtchn) { -#if 0 - shared_info_t *s = HYPERVISOR_shared_info; - while (synch_test_bit(evtchn, &s->evtchn_pending[0]) || - synch_test_bit(evtchn, &s->evtchn_mask[0])) - ; -#endif - notify_via_evtchn(evtchn); - } else - printk("send_IPI to unbound port %d/%d", - cpu, vector); + int evtchn = per_cpu(ipi_to_evtchn, cpu)[vector]; + BUG_ON(evtchn < 0); + notify_remote_via_evtchn(evtchn); } void __send_IPI_shortcut(unsigned int shortcut, int vector) diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Thu Sep 29 23:28:44 2005 @@ -446,27 +446,6 @@ static int cpucount; - -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); /* @@ -484,7 +463,6 @@ while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) rep_nop(); local_setup_timer(); - ldebug_setup(); smp_intr_init(); local_irq_enable(); /* diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Thu Sep 29 23:28:44 2005 @@ -186,8 +186,8 @@ "mov %4,%%eax ; " "mov %%edx,%4 ; " "mul %5 ; " + "xor %5,%5 ; " "add %4,%%eax ; " - "xor %5,%5 ; " "adc %5,%%edx ; " : "=A" (product), "=r" (tmp1), "=r" (tmp2) : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) ); @@ -836,13 +836,6 @@ cpu_clear(smp_processor_id(), nohz_cpu_mask); } -void time_suspend(void) -{ - /* nothing */ - teardown_irq(per_cpu(timer_irq, 0), &irq_timer); - unbind_virq_from_irq(VIRQ_TIMER); -} - /* No locking required. We are only CPU running, and interrupts are off. */ void time_resume(void) { @@ -854,9 +847,6 @@ per_cpu(processed_system_time, 0) = processed_system_time; update_wallclock(); - - per_cpu(timer_irq, 0) = bind_virq_to_irq(VIRQ_TIMER); - (void)setup_irq(per_cpu(timer_irq, 0), &irq_timer); } #ifdef CONFIG_SMP diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c Thu Sep 29 23:28:44 2005 @@ -209,7 +209,10 @@ { unsigned long *p, page; - page = __pa(per_cpu(cur_pgd, smp_processor_id())); + preempt_disable(); + page = __pa(per_cpu(cur_pgd, smp_processor_id())); + preempt_enable(); + p = (unsigned long *)__va(page); p += (address >> 30) * 2; printk(KERN_ALERT "%08lx -> *pde = %08lx:%08lx\n", page, p[1], p[0]); @@ -237,7 +240,12 @@ { unsigned long page; + preempt_disable(); page = ((unsigned long *) per_cpu(cur_pgd, smp_processor_id())) + [address >> 22]; + preempt_enable(); + + page = ((unsigned long *) per_cpu(cur_pgd, get_cpu())) [address >> 22]; printk(KERN_ALERT "*pde = ma %08lx pa %08lx\n", page, machine_to_phys(page)); @@ -567,7 +575,9 @@ pmd_t *pmd, *pmd_k; pte_t *pte_k; + preempt_disable(); pgd = index + per_cpu(cur_pgd, smp_processor_id()); + preempt_enable(); pgd_k = init_mm.pgd + index; if (!pgd_present(*pgd_k)) diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/kernel/devmem.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/devmem.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/devmem.c Thu Sep 29 23:28:44 2005 @@ -144,3 +144,13 @@ .mmap = mmap_mem, .open = open_mem, }; + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Thu Sep 29 23:28:44 2005 @@ -3,7 +3,7 @@ * * Communication via Xen event channels. * - * Copyright (c) 2002-2004, K A Fraser + * Copyright (c) 2002-2005, K A Fraser * * This file may be distributed separately from the Linux kernel, or * incorporated into other software packages, subject to the following license: @@ -73,27 +73,33 @@ static u8 cpu_evtchn[NR_EVENT_CHANNELS]; static u32 cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/32]; -#define active_evtchns(cpu,sh,idx) \ - ((sh)->evtchn_pending[idx] & \ - cpu_evtchn_mask[cpu][idx] & \ - ~(sh)->evtchn_mask[idx]) - -void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) -{ - clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]); - set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]); - cpu_evtchn[chn] = cpu; +#define active_evtchns(cpu,sh,idx) \ + ((sh)->evtchn_pending[idx] & \ + cpu_evtchn_mask[cpu][idx] & \ + ~(sh)->evtchn_mask[idx]) + +static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) +{ + clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]); + set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]); + cpu_evtchn[chn] = cpu; +} + +static void init_evtchn_cpu_bindings(void) +{ + /* By default all event channels notify CPU#0. */ + memset(cpu_evtchn, 0, sizeof(cpu_evtchn)); + memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0])); } #else -#define active_evtchns(cpu,sh,idx) \ - ((sh)->evtchn_pending[idx] & \ - ~(sh)->evtchn_mask[idx]) - -void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) -{ -} +#define active_evtchns(cpu,sh,idx) \ + ((sh)->evtchn_pending[idx] & \ + ~(sh)->evtchn_mask[idx]) +#define bind_evtchn_to_cpu(chn,cpu) ((void)0) +#define init_evtchn_cpu_bindings() ((void)0) + #endif /* Upcall to generic IRQ layer. */ @@ -108,9 +114,9 @@ #elif defined (__x86_64__) #define IRQ_REG orig_rax #endif -#define do_IRQ(irq, regs) do { \ - (regs)->IRQ_REG = (irq); \ - do_IRQ((regs)); \ +#define do_IRQ(irq, regs) do { \ + (regs)->IRQ_REG = (irq); \ + do_IRQ((regs)); \ } while (0) #endif @@ -123,249 +129,241 @@ */ void force_evtchn_callback(void) { - (void)HYPERVISOR_xen_version(0, NULL); + (void)HYPERVISOR_xen_version(0, NULL); } EXPORT_SYMBOL(force_evtchn_callback); /* NB. Interrupts are disabled on entry. */ asmlinkage void evtchn_do_upcall(struct pt_regs *regs) { - u32 l1, l2; - unsigned int l1i, l2i, port; - int irq, cpu = smp_processor_id(); - shared_info_t *s = HYPERVISOR_shared_info; - vcpu_info_t *vcpu_info = &s->vcpu_data[cpu]; - - vcpu_info->evtchn_upcall_pending = 0; - - /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ - l1 = xchg(&vcpu_info->evtchn_pending_sel, 0); - while ( l1 != 0 ) - { - l1i = __ffs(l1); - l1 &= ~(1 << l1i); + u32 l1, l2; + unsigned int l1i, l2i, port; + int irq, cpu = smp_processor_id(); + shared_info_t *s = HYPERVISOR_shared_info; + vcpu_info_t *vcpu_info = &s->vcpu_data[cpu]; + + vcpu_info->evtchn_upcall_pending = 0; + + /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ + l1 = xchg(&vcpu_info->evtchn_pending_sel, 0); + while (l1 != 0) { + l1i = __ffs(l1); + l1 &= ~(1 << l1i); - while ( (l2 = active_evtchns(cpu, s, l1i)) != 0 ) - { - l2i = __ffs(l2); - l2 &= ~(1 << l2i); + while ((l2 = active_evtchns(cpu, s, l1i)) != 0) { + l2i = __ffs(l2); + l2 &= ~(1 << l2i); - port = (l1i << 5) + l2i; - if ( (irq = evtchn_to_irq[port]) != -1 ) { - do_IRQ(irq, regs); - } else - evtchn_device_upcall(port); - } - } + port = (l1i << 5) + l2i; + if ((irq = evtchn_to_irq[port]) != -1) + do_IRQ(irq, regs); + else + evtchn_device_upcall(port); + } + } } EXPORT_SYMBOL(evtchn_do_upcall); static int find_unbound_irq(void) { - int irq; - - for ( irq = 0; irq < NR_IRQS; irq++ ) - if ( irq_bindcount[irq] == 0 ) - break; - - if ( irq == NR_IRQS ) - panic("No available IRQ to bind to: increase NR_IRQS!\n"); - - return irq; + int irq; + + for (irq = 0; irq < NR_IRQS; irq++) + if (irq_bindcount[irq] == 0) + break; + + if (irq == NR_IRQS) + panic("No available IRQ to bind to: increase NR_IRQS!\n"); + + return irq; } int bind_virq_to_irq(int virq) { - evtchn_op_t op; - int evtchn, irq; - int cpu = smp_processor_id(); - - spin_lock(&irq_mapping_update_lock); - - if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 ) - { - op.cmd = EVTCHNOP_bind_virq; - op.u.bind_virq.virq = virq; - if ( HYPERVISOR_event_channel_op(&op) != 0 ) - panic("Failed to bind virtual IRQ %d\n", virq); - evtchn = op.u.bind_virq.port; - - irq = find_unbound_irq(); - evtchn_to_irq[evtchn] = irq; - irq_to_evtchn[irq] = evtchn; - - per_cpu(virq_to_irq, cpu)[virq] = irq; - - bind_evtchn_to_cpu(evtchn, cpu); - } - - irq_bindcount[irq]++; - - spin_unlock(&irq_mapping_update_lock); + evtchn_op_t op; + int evtchn, irq; + int cpu = smp_processor_id(); + + spin_lock(&irq_mapping_update_lock); + + if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) { + op.cmd = EVTCHNOP_bind_virq; + op.u.bind_virq.virq = virq; + BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); + evtchn = op.u.bind_virq.port; + + irq = find_unbound_irq(); + evtchn_to_irq[evtchn] = irq; + irq_to_evtchn[irq] = evtchn; + + per_cpu(virq_to_irq, cpu)[virq] = irq; + + bind_evtchn_to_cpu(evtchn, cpu); + } + + irq_bindcount[irq]++; + + spin_unlock(&irq_mapping_update_lock); - return irq; + return irq; } EXPORT_SYMBOL(bind_virq_to_irq); void unbind_virq_from_irq(int virq) { - evtchn_op_t op; - int cpu = smp_processor_id(); - int irq = per_cpu(virq_to_irq, cpu)[virq]; - int evtchn = irq_to_evtchn[irq]; - - spin_lock(&irq_mapping_update_lock); - - if ( --irq_bindcount[irq] == 0 ) - { - op.cmd = EVTCHNOP_close; - op.u.close.dom = DOMID_SELF; - op.u.close.port = evtchn; - if ( HYPERVISOR_event_channel_op(&op) != 0 ) - panic("Failed to unbind virtual IRQ %d\n", virq); - - /* - * This is a slight hack. Interdomain ports can be allocated directly - * by userspace, and at that point they get bound by Xen to vcpu 0. We - * therefore need to make sure that if we get an event on an event - * channel we don't know about vcpu 0 handles it. Binding channels to - * vcpu 0 when closing them achieves this. - */ - bind_evtchn_to_cpu(evtchn, 0); - evtchn_to_irq[evtchn] = -1; - irq_to_evtchn[irq] = -1; - per_cpu(virq_to_irq, cpu)[virq] = -1; - } - - spin_unlock(&irq_mapping_update_lock); + evtchn_op_t op; + int cpu = smp_processor_id(); + int irq = per_cpu(virq_to_irq, cpu)[virq]; + int evtchn = irq_to_evtchn[irq]; + + spin_lock(&irq_mapping_update_lock); + + if (--irq_bindcount[irq] == 0) { + op.cmd = EVTCHNOP_close; + op.u.close.dom = DOMID_SELF; + op.u.close.port = evtchn; + BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); + + /* + * This is a slight hack. Interdomain ports can be allocated + * directly by userspace, and at that point they get bound by + * Xen to vcpu 0. We therefore need to make sure that if we get + * an event on an event channel we don't know about vcpu 0 + * handles it. Binding channels to vcpu 0 when closing them + * achieves this. + */ + bind_evtchn_to_cpu(evtchn, 0); + evtchn_to_irq[evtchn] = -1; + irq_to_evtchn[irq] = -1; + per_cpu(virq_to_irq, cpu)[virq] = -1; + } + + spin_unlock(&irq_mapping_update_lock); } EXPORT_SYMBOL(unbind_virq_from_irq); int bind_ipi_to_irq(int ipi) { - evtchn_op_t op; - int evtchn, irq; - int cpu = smp_processor_id(); - - spin_lock(&irq_mapping_update_lock); - - if ( (evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == 0 ) - { - op.cmd = EVTCHNOP_bind_ipi; - if ( HYPERVISOR_event_channel_op(&op) != 0 ) - panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, cpu); - evtchn = op.u.bind_ipi.port; - - irq = find_unbound_irq(); - evtchn_to_irq[evtchn] = irq; - irq_to_evtchn[irq] = evtchn; - - per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn; - - bind_evtchn_to_cpu(evtchn, cpu); - } - else - { - irq = evtchn_to_irq[evtchn]; - } - - irq_bindcount[irq]++; - - spin_unlock(&irq_mapping_update_lock); - - return irq; + evtchn_op_t op; + int evtchn, irq; + int cpu = smp_processor_id(); + + spin_lock(&irq_mapping_update_lock); + + if ((evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == -1) { + op.cmd = EVTCHNOP_bind_ipi; + BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); + evtchn = op.u.bind_ipi.port; + + irq = find_unbound_irq(); + evtchn_to_irq[evtchn] = irq; + irq_to_evtchn[irq] = evtchn; + + per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn; + + bind_evtchn_to_cpu(evtchn, cpu); + } else { + irq = evtchn_to_irq[evtchn]; + } + + irq_bindcount[irq]++; + + spin_unlock(&irq_mapping_update_lock); + + return irq; } EXPORT_SYMBOL(bind_ipi_to_irq); void unbind_ipi_from_irq(int ipi) { - evtchn_op_t op; - int cpu = smp_processor_id(); - int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]; - int irq = evtchn_to_irq[evtchn]; - - spin_lock(&irq_mapping_update_lock); - - if ( --irq_bindcount[irq] == 0 ) - { - op.cmd = EVTCHNOP_close; - op.u.close.dom = DOMID_SELF; - op.u.close.port = evtchn; - if ( HYPERVISOR_event_channel_op(&op) != 0 ) - panic("Failed to unbind virtual IPI %d on cpu %d\n", ipi, cpu); - - /* See comments in unbind_virq_from_irq */ - bind_evtchn_to_cpu(evtchn, 0); - evtchn_to_irq[evtchn] = -1; - irq_to_evtchn[irq] = -1; - per_cpu(ipi_to_evtchn, cpu)[ipi] = 0; - } - - spin_unlock(&irq_mapping_update_lock); + evtchn_op_t op; + int cpu = smp_processor_id(); + int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]; + int irq = evtchn_to_irq[evtchn]; + + spin_lock(&irq_mapping_update_lock); + + if (--irq_bindcount[irq] == 0) { + op.cmd = EVTCHNOP_close; + op.u.close.dom = DOMID_SELF; + op.u.close.port = evtchn; + BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); + + /* See comments in unbind_virq_from_irq */ + bind_evtchn_to_cpu(evtchn, 0); + evtchn_to_irq[evtchn] = -1; + irq_to_evtchn[irq] = -1; + per_cpu(ipi_to_evtchn, cpu)[ipi] = -1; + } + + spin_unlock(&irq_mapping_update_lock); } EXPORT_SYMBOL(unbind_ipi_from_irq); int bind_evtchn_to_irq(unsigned int evtchn) { - int irq; - - spin_lock(&irq_mapping_update_lock); - - if ( (irq = evtchn_to_irq[evtchn]) == -1 ) - { - irq = find_unbound_irq(); - evtchn_to_irq[evtchn] = irq; - irq_to_evtchn[irq] = evtchn; - } - - irq_bindcount[irq]++; - - spin_unlock(&irq_mapping_update_lock); + int irq; + + spin_lock(&irq_mapping_update_lock); + + if ((irq = evtchn_to_irq[evtchn]) == -1) { + irq = find_unbound_irq(); + evtchn_to_irq[evtchn] = irq; + irq_to_evtchn[irq] = evtchn; + } + + irq_bindcount[irq]++; + + spin_unlock(&irq_mapping_update_lock); - return irq; + return irq; } EXPORT_SYMBOL(bind_evtchn_to_irq); -void unbind_evtchn_from_irq(unsigned int evtchn) -{ - int irq = evtchn_to_irq[evtchn]; - - spin_lock(&irq_mapping_update_lock); - - if ( --irq_bindcount[irq] == 0 ) - { - evtchn_to_irq[evtchn] = -1; - irq_to_evtchn[irq] = -1; - } - - spin_unlock(&irq_mapping_update_lock); +void unbind_evtchn_from_irq(unsigned int irq) +{ + evtchn_op_t op; + int evtchn = irq_to_evtchn[irq]; + + spin_lock(&irq_mapping_update_lock); + + if ((--irq_bindcount[irq] == 0) && (evtchn != -1)) { + op.cmd = EVTCHNOP_close; + op.u.close.dom = DOMID_SELF; + op.u.close.port = evtchn; + BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); + + evtchn_to_irq[evtchn] = -1; + irq_to_evtchn[irq] = -1; + } + + spin_unlock(&irq_mapping_update_lock); } EXPORT_SYMBOL(unbind_evtchn_from_irq); int bind_evtchn_to_irqhandler( - unsigned int evtchn, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char *devname, - void *dev_id) -{ - unsigned int irq; - int retval; - - irq = bind_evtchn_to_irq(evtchn); - retval = request_irq(irq, handler, irqflags, devname, dev_id); - if ( retval != 0 ) - unbind_evtchn_from_irq(evtchn); - - return retval; + unsigned int evtchn, + irqreturn_t (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char *devname, + void *dev_id) +{ + unsigned int irq; + int retval; + + irq = bind_evtchn_to_irq(evtchn); + retval = request_irq(irq, handler, irqflags, devname, dev_id); + if (retval != 0) + unbind_evtchn_from_irq(irq); + + return irq; } EXPORT_SYMBOL(bind_evtchn_to_irqhandler); -void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id) -{ - unsigned int irq = evtchn_to_irq[evtchn]; - free_irq(irq, dev_id); - unbind_evtchn_from_irq(evtchn); +void unbind_evtchn_from_irqhandler(unsigned int irq, void *dev_id) +{ + free_irq(irq, dev_id); + unbind_evtchn_from_irq(irq); } EXPORT_SYMBOL(unbind_evtchn_from_irqhandler); @@ -378,50 +376,50 @@ /* Rebind an evtchn so that it gets delivered to a specific cpu */ static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu) { - evtchn_op_t op; - int evtchn; - - spin_lock(&irq_mapping_update_lock); - evtchn = irq_to_evtchn[irq]; - if (!VALID_EVTCHN(evtchn)) { - spin_unlock(&irq_mapping_update_lock); - return; - } - - /* Tell Xen to send future instances of this interrupt to other vcpu. */ - op.cmd = EVTCHNOP_bind_vcpu; - op.u.bind_vcpu.port = evtchn; - op.u.bind_vcpu.vcpu = tcpu; - - /* - * If this fails, it usually just indicates that we're dealing with a virq - * or IPI channel, which don't actually need to be rebound. Ignore it, - * but don't do the xenlinux-level rebind in that case. - */ - if (HYPERVISOR_event_channel_op(&op) >= 0) - bind_evtchn_to_cpu(evtchn, tcpu); - - spin_unlock(&irq_mapping_update_lock); - - /* - * Now send the new target processor a NOP IPI. When this returns, it - * will check for any pending interrupts, and so service any that got - * delivered to the wrong processor by mistake. - * - * XXX: The only time this is called with interrupts disabled is from the - * hotplug/hotunplug path. In that case, all cpus are stopped with - * interrupts disabled, and the missed interrupts will be picked up when - * they start again. This is kind of a hack. - */ - if (!irqs_disabled()) - smp_call_function(do_nothing_function, NULL, 0, 0); + evtchn_op_t op; + int evtchn; + + spin_lock(&irq_mapping_update_lock); + evtchn = irq_to_evtchn[irq]; + if (!VALID_EVTCHN(evtchn)) { + spin_unlock(&irq_mapping_update_lock); + return; + } + + /* Send future instances of this interrupt to other vcpu. */ + op.cmd = EVTCHNOP_bind_vcpu; + op.u.bind_vcpu.port = evtchn; + op.u.bind_vcpu.vcpu = tcpu; + + /* + * If this fails, it usually just indicates that we're dealing with a + * virq or IPI channel, which don't actually need to be rebound. Ignore + * it, but don't do the xenlinux-level rebind in that case. + */ + if (HYPERVISOR_event_channel_op(&op) >= 0) + bind_evtchn_to_cpu(evtchn, tcpu); + + spin_unlock(&irq_mapping_update_lock); + + /* + * Now send the new target processor a NOP IPI. When this returns, it + * will check for any pending interrupts, and so service any that got + * delivered to the wrong processor by mistake. + * + * XXX: The only time this is called with interrupts disabled is from + * the hotplug/hotunplug path. In that case, all cpus are stopped with + * interrupts disabled, and the missed interrupts will be picked up + * when they start again. This is kind of a hack. + */ + if (!irqs_disabled()) + smp_call_function(do_nothing_function, NULL, 0, 0); } static void set_affinity_irq(unsigned irq, cpumask_t dest) { - unsigned tcpu = first_cpu(dest); - rebind_irq_to_cpu(irq, tcpu); + unsigned tcpu = first_cpu(dest); + rebind_irq_to_cpu(irq, tcpu); } /* @@ -430,83 +428,84 @@ static unsigned int startup_dynirq(unsigned int irq) { - int evtchn = irq_to_evtchn[irq]; - - if ( !VALID_EVTCHN(evtchn) ) - return 0; - unmask_evtchn(evtchn); - return 0; + int evtchn = irq_to_evtchn[irq]; + + if (VALID_EVTCHN(evtchn)) + unmask_evtchn(evtchn); + return 0; } static void shutdown_dynirq(unsigned int irq) { - int evtchn = irq_to_evtchn[irq]; - - if ( !VALID_EVTCHN(evtchn) ) - return; - mask_evtchn(evtchn); + int evtchn = irq_to_evtchn[irq]; + + if (VALID_EVTCHN(evtchn)) + mask_evtchn(evtchn); } static void enable_dynirq(unsigned int irq) { - int evtchn = irq_to_evtchn[irq]; - - unmask_evtchn(evtchn); + int evtchn = irq_to_evtchn[irq]; + + if (VALID_EVTCHN(evtchn)) + unmask_evtchn(evtchn); } static void disable_dynirq(unsigned int irq) { - int evtchn = irq_to_evtchn[irq]; - - mask_evtchn(evtchn); + int evtchn = irq_to_evtchn[irq]; + + if (VALID_EVTCHN(evtchn)) + mask_evtchn(evtchn); } static void ack_dynirq(unsigned int irq) { - int evtchn = irq_to_evtchn[irq]; - - mask_evtchn(evtchn); - clear_evtchn(evtchn); + int evtchn = irq_to_evtchn[irq]; + + if (VALID_EVTCHN(evtchn)) { + mask_evtchn(evtchn); + clear_evtchn(evtchn); + } } static void end_dynirq(unsigned int irq) { - int evtchn = irq_to_evtchn[irq]; - - if ( !(irq_desc[irq].status & IRQ_DISABLED) ) - unmask_evtchn(evtchn); + int evtchn = irq_to_evtchn[irq]; + + if (VALID_EVTCHN(evtchn) && !(irq_desc[irq].status & IRQ_DISABLED)) + unmask_evtchn(evtchn); } static struct hw_interrupt_type dynirq_type = { - "Dynamic-irq", - startup_dynirq, - shutdown_dynirq, - enable_dynirq, - disable_dynirq, - ack_dynirq, - end_dynirq, - set_affinity_irq + "Dynamic-irq", + startup_dynirq, + shutdown_dynirq, + enable_dynirq, + disable_dynirq, + ack_dynirq, + end_dynirq, + set_affinity_irq }; static inline void pirq_unmask_notify(int pirq) { - physdev_op_t op; - if ( unlikely(test_bit(pirq, &pirq_needs_unmask_notify[0])) ) - { - op.cmd = PHYSDEVOP_IRQ_UNMASK_NOTIFY; - (void)HYPERVISOR_physdev_op(&op); - } + physdev_op_t op; + if (unlikely(test_bit(pirq, &pirq_needs_unmask_notify[0]))) { + op.cmd = PHYSDEVOP_IRQ_UNMASK_NOTIFY; + (void)HYPERVISOR_physdev_op(&op); + } } static inline void pirq_query_unmask(int pirq) { - physdev_op_t op; - op.cmd = PHYSDEVOP_IRQ_STATUS_QUERY; - op.u.irq_status_query.irq = pirq; - (void)HYPERVISOR_physdev_op(&op); - clear_bit(pirq, &pirq_needs_unmask_notify[0]); - if ( op.u.irq_status_query.flags & PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY ) - set_bit(pirq, &pirq_needs_unmask_notify[0]); + physdev_op_t op; + op.cmd = PHYSDEVOP_IRQ_STATUS_QUERY; + op.u.irq_status_query.irq = pirq; + (void)HYPERVISOR_physdev_op(&op); + clear_bit(pirq, &pirq_needs_unmask_notify[0]); + if (op.u.irq_status_query.flags & PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY) + set_bit(pirq, &pirq_needs_unmask_notify[0]); } /* @@ -517,218 +516,252 @@ static unsigned int startup_pirq(unsigned int irq) { - evtchn_op_t op; - int evtchn; - - op.cmd = EVTCHNOP_bind_pirq; - op.u.bind_pirq.pirq = irq; - /* NB. We are happy to share unless we are probing. */ - op.u.bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE; - if ( HYPERVISOR_event_channel_op(&op) != 0 ) - { - if ( !probing_irq(irq) ) /* Some failures are expected when probing. */ - printk(KERN_INFO "Failed to obtain physical IRQ %d\n", irq); - return 0; - } - evtchn = op.u.bind_pirq.port; - - pirq_query_unmask(irq_to_pirq(irq)); - - bind_evtchn_to_cpu(evtchn, 0); - evtchn_to_irq[evtchn] = irq; - irq_to_evtchn[irq] = evtchn; - - unmask_evtchn(evtchn); - pirq_unmask_notify(irq_to_pirq(irq)); - - return 0; + evtchn_op_t op; + int evtchn; + + op.cmd = EVTCHNOP_bind_pirq; + op.u.bind_pirq.pirq = irq; + /* NB. We are happy to share unless we are probing. */ + op.u.bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE; + if (HYPERVISOR_event_channel_op(&op) != 0) { + if ( !probing_irq(irq) ) + printk(KERN_INFO "Failed to obtain physical " + "IRQ %d\n", irq); + return 0; + } + evtchn = op.u.bind_pirq.port; + + pirq_query_unmask(irq_to_pirq(irq)); + + bind_evtchn_to_cpu(evtchn, 0); + evtchn_to_irq[evtchn] = irq; + irq_to_evtchn[irq] = evtchn; + + unmask_evtchn(evtchn); + pirq_unmask_notify(irq_to_pirq(irq)); + + return 0; } static void shutdown_pirq(unsigned int irq) { - evtchn_op_t op; - int evtchn = irq_to_evtchn[irq]; - - if ( !VALID_EVTCHN(evtchn) ) - return; - - mask_evtchn(evtchn); - - op.cmd = EVTCHNOP_close; - op.u.close.dom = DOMID_SELF; - op.u.close.port = evtchn; - if ( HYPERVISOR_event_channel_op(&op) != 0 ) - panic("Failed to unbind physical IRQ %d\n", irq); - - bind_evtchn_to_cpu(evtchn, 0); - evtchn_to_irq[evtchn] = -1; - irq_to_evtchn[irq] = -1; + evtchn_op_t op; + int evtchn = irq_to_evtchn[irq]; + + if (!VALID_EVTCHN(evtchn)) + return; + + mask_evtchn(evtchn); + + op.cmd = EVTCHNOP_close; + op.u.close.dom = DOMID_SELF; + op.u.close.port = evtchn; + BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); + + bind_evtchn_to_cpu(evtchn, 0); + evtchn_to_irq[evtchn] = -1; + irq_to_evtchn[irq] = -1; } static void enable_pirq(unsigned int irq) { - int evtchn = irq_to_evtchn[irq]; - if ( !VALID_EVTCHN(evtchn) ) - return; - unmask_evtchn(evtchn); - pirq_unmask_notify(irq_to_pirq(irq)); + int evtchn = irq_to_evtchn[irq]; + + if (VALID_EVTCHN(evtchn)) { + unmask_evtchn(evtchn); + pirq_unmask_notify(irq_to_pirq(irq)); + } } static void disable_pirq(unsigned int irq) { - int evtchn = irq_to_evtchn[irq]; - if ( !VALID_EVTCHN(evtchn) ) - return; - mask_evtchn(evtchn); + int evtchn = irq_to_evtchn[irq]; + + if (VALID_EVTCHN(evtchn)) + mask_evtchn(evtchn); } static void ack_pirq(unsigned int irq) { - int evtchn = irq_to_evtchn[irq]; - if ( !VALID_EVTCHN(evtchn) ) - return; - mask_evtchn(evtchn); - clear_evtchn(evtchn); + int evtchn = irq_to_evtchn[irq]; + + if (VALID_EVTCHN(evtchn)) { + mask_evtchn(evtchn); + clear_evtchn(evtchn); + } } static void end_pirq(unsigned int irq) { - int evtchn = irq_to_evtchn[irq]; - if ( !VALID_EVTCHN(evtchn) ) - return; - if ( !(irq_desc[irq].status & IRQ_DISABLED) ) - { - unmask_evtchn(evtchn); - pirq_unmask_notify(irq_to_pirq(irq)); - } + int evtchn = irq_to_evtchn[irq]; + + if (VALID_EVTCHN(evtchn) && !(irq_desc[irq].status & IRQ_DISABLED)) { + unmask_evtchn(evtchn); + pirq_unmask_notify(irq_to_pirq(irq)); + } } static struct hw_interrupt_type pirq_type = { - "Phys-irq", - startup_pirq, - shutdown_pirq, - enable_pirq, - disable_pirq, - ack_pirq, - end_pirq, - set_affinity_irq + "Phys-irq", + startup_pirq, + shutdown_pirq, + enable_pirq, + disable_pirq, + ack_pirq, + end_pirq, + set_affinity_irq }; void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { - int evtchn = irq_to_evtchn[i]; - shared_info_t *s = HYPERVISOR_shared_info; - if ( !VALID_EVTCHN(evtchn) ) - return; - BUG_ON(!synch_test_bit(evtchn, &s->evtchn_mask[0])); - synch_set_bit(evtchn, &s->evtchn_pending[0]); -} - -void irq_suspend(void) -{ - int pirq, virq, irq, evtchn; - int cpu = smp_processor_id(); /* XXX */ - - /* Unbind VIRQs from event channels. */ - for ( virq = 0; virq < NR_VIRQS; virq++ ) - { - if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 ) - continue; - evtchn = irq_to_evtchn[irq]; - - /* Mark the event channel as unused in our table. */ - evtchn_to_irq[evtchn] = -1; - irq_to_evtchn[irq] = -1; - } - - /* Check that no PIRQs are still bound. */ - for ( pirq = 0; pirq < NR_PIRQS; pirq++ ) - if ( (evtchn = irq_to_evtchn[pirq_to_irq(pirq)]) != -1 ) - panic("Suspend attempted while PIRQ %d bound to evtchn %d.\n", - pirq, evtchn); + int evtchn = irq_to_evtchn[i]; + shared_info_t *s = HYPERVISOR_shared_info; + if (!VALID_EVTCHN(evtchn)) + return; + BUG_ON(!synch_test_bit(evtchn, &s->evtchn_mask[0])); + synch_set_bit(evtchn, &s->evtchn_pending[0]); +} + +void notify_remote_via_irq(int irq) +{ + int evtchn = irq_to_evtchn[irq]; + + if (VALID_EVTCHN(evtchn)) + notify_remote_via_evtchn(evtchn); } void irq_resume(void) { - evtchn_op_t op; - int virq, irq, evtchn; - int cpu = smp_processor_id(); /* XXX */ - - for ( evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++ ) - mask_evtchn(evtchn); /* New event-channel space is not 'live' yet. */ - - for ( virq = 0; virq < NR_VIRQS; virq++ ) - { - if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 ) - continue; - - /* Get a new binding from Xen. */ - op.cmd = EVTCHNOP_bind_virq; - op.u.bind_virq.virq = virq; - if ( HYPERVISOR_event_channel_op(&op) != 0 ) - panic("Failed to bind virtual IRQ %d\n", virq); - evtchn = op.u.bind_virq.port; + evtchn_op_t op; + int cpu, pirq, virq, ipi, irq, evtchn; + + init_evtchn_cpu_bindings(); + + /* New event-channel space is not 'live' yet. */ + for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++) + mask_evtchn(evtchn); + + /* Check that no PIRQs are still bound. */ + for (pirq = 0; pirq < NR_PIRQS; pirq++) + BUG_ON(irq_to_evtchn[pirq_to_irq(pirq)] != -1); + + /* Secondary CPUs must have no VIRQ or IPI bindings. */ + for (cpu = 1; cpu < NR_CPUS; cpu++) { + for (virq = 0; virq < NR_VIRQS; virq++) + BUG_ON(per_cpu(virq_to_irq, cpu)[virq] != -1); + for (ipi = 0; ipi < NR_IPIS; ipi++) + BUG_ON(per_cpu(ipi_to_evtchn, cpu)[ipi] != -1); + } + + /* No IRQ -> event-channel mappings. */ + for (irq = 0; irq < NR_IRQS; irq++) + irq_to_evtchn[irq] = -1; + + /* Primary CPU: rebind VIRQs automatically. */ + for (virq = 0; virq < NR_VIRQS; virq++) { + if ((irq = per_cpu(virq_to_irq, 0)[virq]) == -1) + continue; + + /* Get a new binding from Xen. */ + op.cmd = EVTCHNOP_bind_virq; + op.u.bind_virq.virq = virq; + BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); + evtchn = op.u.bind_virq.port; - /* Record the new mapping. */ - bind_evtchn_to_cpu(evtchn, 0); - evtchn_to_irq[evtchn] = irq; - irq_to_evtchn[irq] = evtchn; - - /* Ready for use. */ - unmask_evtchn(evtchn); - } + /* Record the new mapping. */ + evtchn_to_irq[evtchn] = irq; + irq_to_evtchn[irq] = evtchn; + + /* Ready for use. */ + unmask_evtchn(evtchn); + } + + /* Primary CPU: rebind IPIs automatically. */ + for (ipi = 0; ipi < NR_IPIS; ipi++) { + if ((evtchn = per_cpu(ipi_to_evtchn, 0)[ipi]) == -1) + continue; + + irq = evtchn_to_irq[evtchn]; + evtchn_to_irq[evtchn] = -1; + + /* Get a new binding from Xen. */ + op.cmd = EVTCHNOP_bind_ipi; + BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); + evtchn = op.u.bind_ipi.port; + + /* Record the new mapping. */ + evtchn_to_irq[evtchn] = irq; + irq_to_evtchn[irq] = evtchn; + + /* Ready for use. */ + unmask_evtchn(evtchn); + } + + /* Remove defunct event-channel -> IRQ mappings. */ + for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++) { + if ((evtchn_to_irq[evtchn] != -1) && + (irq_to_evtchn[evtchn_to_irq[evtchn]] == -1)) + evtchn_to_irq[evtchn] = -1; + } } void __init init_IRQ(void) { - int i; - int cpu; - - irq_ctx_init(0); - - spin_lock_init(&irq_mapping_update_lock); - -#ifdef CONFIG_SMP - /* By default all event channels notify CPU#0. */ - memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0])); -#endif - - for ( cpu = 0; cpu < NR_CPUS; cpu++ ) { - /* No VIRQ -> IRQ mappings. */ - for ( i = 0; i < NR_VIRQS; i++ ) - per_cpu(virq_to_irq, cpu)[i] = -1; - } - - /* No event-channel -> IRQ mappings. */ - for ( i = 0; i < NR_EVENT_CHANNELS; i++ ) - { - evtchn_to_irq[i] = -1; - mask_evtchn(i); /* No event channels are 'live' right now. */ - } - - /* No IRQ -> event-channel mappings. */ - for ( i = 0; i < NR_IRQS; i++ ) - irq_to_evtchn[i] = -1; - - for ( i = 0; i < NR_DYNIRQS; i++ ) - { - /* Dynamic IRQ space is currently unbound. Zero the refcnts. */ - irq_bindcount[dynirq_to_irq(i)] = 0; - - irq_desc[dynirq_to_irq(i)].status = IRQ_DISABLED; - irq_desc[dynirq_to_irq(i)].action = 0; - irq_desc[dynirq_to_irq(i)].depth = 1; - irq_desc[dynirq_to_irq(i)].handler = &dynirq_type; - } - - for ( i = 0; i < NR_PIRQS; i++ ) - { - /* Phys IRQ space is statically bound (1:1 mapping). Nail refcnts. */ - irq_bindcount[pirq_to_irq(i)] = 1; - - irq_desc[pirq_to_irq(i)].status = IRQ_DISABLED; - irq_desc[pirq_to_irq(i)].action = 0; - irq_desc[pirq_to_irq(i)].depth = 1; - irq_desc[pirq_to_irq(i)].handler = &pirq_type; - } -} + int i; + int cpu; + + irq_ctx_init(0); + + spin_lock_init(&irq_mapping_update_lock); + + init_evtchn_cpu_bindings(); + + /* No VIRQ or IPI bindings. */ + for (cpu = 0; cpu < NR_CPUS; cpu++) { + for (i = 0; i < NR_VIRQS; i++) + per_cpu(virq_to_irq, cpu)[i] = -1; + for (i = 0; i < NR_IPIS; i++) + per_cpu(ipi_to_evtchn, cpu)[i] = -1; + } + + /* No event-channel -> IRQ mappings. */ + for (i = 0; i < NR_EVENT_CHANNELS; i++) { + evtchn_to_irq[i] = -1; + mask_evtchn(i); /* No event channels are 'live' right now. */ + } + + /* No IRQ -> event-channel mappings. */ + for (i = 0; i < NR_IRQS; i++) + irq_to_evtchn[i] = -1; + + /* Dynamic IRQ space is currently unbound. Zero the refcnts. */ + for (i = 0; i < NR_DYNIRQS; i++) { + irq_bindcount[dynirq_to_irq(i)] = 0; + + irq_desc[dynirq_to_irq(i)].status = IRQ_DISABLED; + irq_desc[dynirq_to_irq(i)].action = 0; + irq_desc[dynirq_to_irq(i)].depth = 1; + irq_desc[dynirq_to_irq(i)].handler = &dynirq_type; + } + + /* Phys IRQ space is statically bound (1:1 mapping). Nail refcnts. */ + for (i = 0; i < NR_PIRQS; i++) + { + irq_bindcount[pirq_to_irq(i)] = 1; + + irq_desc[pirq_to_irq(i)].status = IRQ_DISABLED; + irq_desc[pirq_to_irq(i)].action = 0; + irq_desc[pirq_to_irq(i)].depth = 1; + irq_desc[pirq_to_irq(i)].handler = &pirq_type; + } +} + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/kernel/fixup.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/fixup.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/fixup.c Thu Sep 29 23:28:44 2005 @@ -37,51 +37,57 @@ #define DP(_f, _args...) printk(KERN_ALERT " " _f "\n" , ## _args ) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#define __LINKAGE fastcall -#else -#define __LINKAGE asmlinkage -#endif +fastcall void do_fixup_4gb_segment(struct pt_regs *regs, long error_code) +{ + static unsigned long printed = 0; + char info[100]; + int i; -__LINKAGE void do_fixup_4gb_segment(struct pt_regs *regs, long error_code) -{ - static unsigned long printed = 0; - char info[100]; - int i; + if (test_and_set_bit(0, &printed)) + return; - if ( !test_and_set_bit(0, &printed) ) - { - HYPERVISOR_vm_assist(VMASST_CMD_disable, - VMASST_TYPE_4gb_segments_notify); + HYPERVISOR_vm_assist( + VMASST_CMD_disable, VMASST_TYPE_4gb_segments_notify); - sprintf(info, "%s (pid=%d)", current->comm, current->tgid); + sprintf(info, "%s (pid=%d)", current->comm, current->tgid); - DP(""); - DP("***************************************************************"); - DP("***************************************************************"); - DP("** WARNING: Currently emulating unsupported memory accesses **"); - DP("** in /lib/tls libraries. The emulation is very **"); - DP("** slow. To ensure full performance you should **"); - DP("** execute the following as root: **"); - DP("** mv /lib/tls /lib/tls.disabled **"); - DP("** Offending process: %-38.38s **", info); - DP("***************************************************************"); - DP("***************************************************************"); - DP(""); - for ( i = 5; i > 0; i-- ) - { - printk("Pausing... %d", i); - mdelay(1000); - printk("\b\b\b\b\b\b\b\b\b\b\b\b"); - } - printk("Continuing...\n\n"); - } + DP(""); + DP("***************************************************************"); + DP("***************************************************************"); + DP("** WARNING: Currently emulating unsupported memory accesses **"); + DP("** in /lib/tls libraries. The emulation is very **"); + DP("** slow. To ensure full performance you should **"); + DP("** execute the following as root: **"); + DP("** mv /lib/tls /lib/tls.disabled **"); + DP("** Offending process: %-38.38s **", info); + DP("***************************************************************"); + DP("***************************************************************"); + DP(""); + + for (i = 5; i > 0; i--) { + printk("Pausing... %d", i); + mdelay(1000); + printk("\b\b\b\b\b\b\b\b\b\b\b\b"); + } + + printk("Continuing...\n\n"); } static int __init fixup_init(void) { - HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments_notify); - return 0; + HYPERVISOR_vm_assist( + VMASST_CMD_enable, VMASST_TYPE_4gb_segments_notify); + return 0; } __initcall(fixup_init); + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Thu Sep 29 23:28:44 2005 @@ -1,13 +1,10 @@ /****************************************************************************** * gnttab.c * - * Two sets of functionality: - * 1. Granting foreign access to our memory reservation. - * 2. Accessing others' memory reservations via grant references. - * (i.e., mechanisms for both sender and recipient of grant references) + * Granting foreign access to our memory reservation. * * Copyright (c) 2005, Christopher Clark - * Copyright (c) 2004, K A Fraser + * Copyright (c) 2004-2005, K A Fraser */ #include <linux/config.h> @@ -23,15 +20,15 @@ #include <asm/synch_bitops.h> #if 1 -#define ASSERT(_p) \ - if ( !(_p) ) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \ - #_p , __LINE__, __FILE__); *(int*)0=0; } +#define ASSERT(_p) \ + if ( !(_p) ) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \ + #_p , __LINE__, __FILE__); *(int*)0=0; } #else #define ASSERT(_p) ((void)0) #endif -#define WPRINTK(fmt, args...) \ - printk(KERN_WARNING "xen_grant: " fmt, ##args) +#define WPRINTK(fmt, args...) \ + printk(KERN_WARNING "xen_grant: " fmt, ##args) EXPORT_SYMBOL(gnttab_grant_foreign_access); @@ -49,11 +46,14 @@ EXPORT_SYMBOL(gnttab_grant_foreign_access_ref); EXPORT_SYMBOL(gnttab_grant_foreign_transfer_ref); +/* External tools reserve first few grant table entries. */ +#define NR_RESERVED_ENTRIES 8 + #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t)) #define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1) static grant_ref_t gnttab_list[NR_GRANT_ENTRIES]; -static int gnttab_free_count = NR_GRANT_ENTRIES; +static int gnttab_free_count; static grant_ref_t gnttab_free_head; static spinlock_t gnttab_list_lock = SPIN_LOCK_UNLOCKED; @@ -64,22 +64,22 @@ static int get_free_entries(int count) { - unsigned long flags; - int ref; - grant_ref_t head; - spin_lock_irqsave(&gnttab_list_lock, flags); - if (gnttab_free_count < count) { + unsigned long flags; + int ref; + grant_ref_t head; + spin_lock_irqsave(&gnttab_list_lock, flags); + if (gnttab_free_count < count) { + spin_unlock_irqrestore(&gnttab_list_lock, flags); + return -1; + } + ref = head = gnttab_free_head; + gnttab_free_count -= count; + while (count-- > 1) + head = gnttab_list[head]; + gnttab_free_head = gnttab_list[head]; + gnttab_list[head] = GNTTAB_LIST_END; spin_unlock_irqrestore(&gnttab_list_lock, flags); - return -1; - } - ref = head = gnttab_free_head; - gnttab_free_count -= count; - while (count-- > 1) - head = gnttab_list[head]; - gnttab_free_head = gnttab_list[head]; - gnttab_list[head] = GNTTAB_LIST_END; - spin_unlock_irqrestore(&gnttab_list_lock, flags); - return ref; + return ref; } #define get_free_entry() get_free_entries(1) @@ -87,38 +87,41 @@ static void do_free_callbacks(void) { - struct gnttab_free_callback *callback = gnttab_free_callback_list, *next; - gnttab_free_callback_list = NULL; - while (callback) { - next = callback->next; - if (gnttab_free_count >= callback->count) { - callback->next = NULL; - callback->fn(callback->arg); - } else { - callback->next = gnttab_free_callback_list; - gnttab_free_callback_list = callback; - } - callback = next; - } + struct gnttab_free_callback *callback, *next; + + callback = gnttab_free_callback_list; + gnttab_free_callback_list = NULL; + + while (callback != NULL) { + next = callback->next; + if (gnttab_free_count >= callback->count) { + callback->next = NULL; + callback->fn(callback->arg); + } else { + callback->next = gnttab_free_callback_list; + gnttab_free_callback_list = callback; + } + callback = next; + } } static inline void check_free_callbacks(void) { - if (unlikely(gnttab_free_callback_list)) - do_free_callbacks(); + if (unlikely(gnttab_free_callback_list)) + do_free_callbacks(); } static void put_free_entry(grant_ref_t ref) { - unsigned long flags; - spin_lock_irqsave(&gnttab_list_lock, flags); - gnttab_list[ref] = gnttab_free_head; - gnttab_free_head = ref; - gnttab_free_count++; - check_free_callbacks(); - spin_unlock_irqrestore(&gnttab_list_lock, flags); + unsigned long flags; + spin_lock_irqsave(&gnttab_list_lock, flags); + gnttab_list[ref] = gnttab_free_head; + gnttab_free_head = ref; + gnttab_free_count++; + check_free_callbacks(); + spin_unlock_irqrestore(&gnttab_list_lock, flags); } /* @@ -128,187 +131,189 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly) { - int ref; + int ref; - if ( unlikely((ref = get_free_entry()) == -1) ) - return -ENOSPC; - - shared[ref].frame = frame; - shared[ref].domid = domid; - wmb(); - shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); - - return ref; + if (unlikely((ref = get_free_entry()) == -1)) + return -ENOSPC; + + shared[ref].frame = frame; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); + + return ref; } void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, unsigned long frame, int readonly) { - shared[ref].frame = frame; - shared[ref].domid = domid; - wmb(); - shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); + shared[ref].frame = frame; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); } int gnttab_query_foreign_access(grant_ref_t ref) { - u16 nflags; - - nflags = shared[ref].flags; - - return ( nflags & (GTF_reading|GTF_writing) ); + u16 nflags; + + nflags = shared[ref].flags; + + return (nflags & (GTF_reading|GTF_writing)); } void gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) { - u16 flags, nflags; - - nflags = shared[ref].flags; - do { - if ( (flags = nflags) & (GTF_reading|GTF_writing) ) - printk(KERN_ALERT "WARNING: g.e. still in use!\n"); - } - while ( (nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) != flags ); + u16 flags, nflags; + + nflags = shared[ref].flags; + do { + if ( (flags = nflags) & (GTF_reading|GTF_writing) ) + printk(KERN_ALERT "WARNING: g.e. still in use!\n"); + } + while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) != + flags); } void gnttab_end_foreign_access(grant_ref_t ref, int readonly) { - gnttab_end_foreign_access_ref(ref, readonly); - put_free_entry(ref); + gnttab_end_foreign_access_ref(ref, readonly); + put_free_entry(ref); } int gnttab_grant_foreign_transfer(domid_t domid) { - int ref; - - if ( unlikely((ref = get_free_entry()) == -1) ) - return -ENOSPC; - - shared[ref].frame = 0; - shared[ref].domid = domid; - wmb(); - shared[ref].flags = GTF_accept_transfer; - - return ref; + int ref; + + if (unlikely((ref = get_free_entry()) == -1)) + return -ENOSPC; + + shared[ref].frame = 0; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_accept_transfer; + + return ref; } void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid) { - shared[ref].frame = 0; - shared[ref].domid = domid; - wmb(); - shared[ref].flags = GTF_accept_transfer; + shared[ref].frame = 0; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_accept_transfer; } unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref) { - unsigned long frame = 0; - u16 flags; - - flags = shared[ref].flags; - - /* - * If a transfer is committed then wait for the frame address to appear. - * Otherwise invalidate the grant entry against future use. - */ - if ( likely(flags != GTF_accept_transfer) || - (synch_cmpxchg(&shared[ref].flags, flags, 0) != GTF_accept_transfer) ) - while ( unlikely((frame = shared[ref].frame) == 0) ) - cpu_relax(); - - return frame; + unsigned long frame = 0; + u16 flags; + + flags = shared[ref].flags; + + /* + * If a transfer is committed then wait for the frame address to + * appear. Otherwise invalidate the grant entry against future use. + */ + if (likely(flags != GTF_accept_transfer) || + (synch_cmpxchg(&shared[ref].flags, flags, 0) != + GTF_accept_transfer)) + while (unlikely((frame = shared[ref].frame) == 0)) + cpu_relax(); + + return frame; } unsigned long gnttab_end_foreign_transfer(grant_ref_t ref) { - unsigned long frame = gnttab_end_foreign_transfer_ref(ref); - put_free_entry(ref); - return frame; + unsigned long frame = gnttab_end_foreign_transfer_ref(ref); + put_free_entry(ref); + return frame; } void gnttab_free_grant_reference(grant_ref_t ref) { - put_free_entry(ref); + put_free_entry(ref); } void gnttab_free_grant_references(grant_ref_t head) { - grant_ref_t ref; - unsigned long flags; - int count = 1; - if (head == GNTTAB_LIST_END) - return; - spin_lock_irqsave(&gnttab_list_lock, flags); - ref = head; - while (gnttab_list[ref] != GNTTAB_LIST_END) { - ref = gnttab_list[ref]; - count++; - } - gnttab_list[ref] = gnttab_free_head; - gnttab_free_head = head; - gnttab_free_count += count; - check_free_callbacks(); - spin_unlock_irqrestore(&gnttab_list_lock, flags); + grant_ref_t ref; + unsigned long flags; + int count = 1; + if (head == GNTTAB_LIST_END) + return; + spin_lock_irqsave(&gnttab_list_lock, flags); + ref = head; + while (gnttab_list[ref] != GNTTAB_LIST_END) { + ref = gnttab_list[ref]; + count++; + } + gnttab_list[ref] = gnttab_free_head; + gnttab_free_head = head; + gnttab_free_count += count; + check_free_callbacks(); + spin_unlock_irqrestore(&gnttab_list_lock, flags); } int gnttab_alloc_grant_references(u16 count, grant_ref_t *head) { - int h = get_free_entries(count); - - if (h == -1) - return -ENOSPC; - - *head = h; - - return 0; + int h = get_free_entries(count); + + if (h == -1) + return -ENOSPC; + + *head = h; + + return 0; } int gnttab_claim_grant_reference(grant_ref_t *private_head) { - grant_ref_t g = *private_head; - if (unlikely(g == GNTTAB_LIST_END)) - return -ENOSPC; - *private_head = gnttab_list[g]; - return g; + grant_ref_t g = *private_head; + if (unlikely(g == GNTTAB_LIST_END)) + return -ENOSPC; + *private_head = gnttab_list[g]; + return g; } void gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t release) { - gnttab_list[release] = *private_head; - *private_head = release; + gnttab_list[release] = *private_head; + *private_head = release; } void gnttab_request_free_callback(struct gnttab_free_callback *callback, void (*fn)(void *), void *arg, u16 count) { - unsigned long flags; - spin_lock_irqsave(&gnttab_list_lock, flags); - if (callback->next) - goto out; - callback->fn = fn; - callback->arg = arg; - callback->count = count; - callback->next = gnttab_free_callback_list; - gnttab_free_callback_list = callback; - check_free_callbacks(); + unsigned long flags; + spin_lock_irqsave(&gnttab_list_lock, flags); + if (callback->next) + goto out; + callback->fn = fn; + callback->arg = arg; + callback->count = count; + callback->next = gnttab_free_callback_list; + gnttab_free_callback_list = callback; + check_free_callbacks(); out: - spin_unlock_irqrestore(&gnttab_list_lock, flags); + spin_unlock_irqrestore(&gnttab_list_lock, flags); } /* @@ -323,79 +328,83 @@ grant_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) { - int ret; - privcmd_hypercall_t hypercall; - - /* XXX Need safety checks here if using for anything other - * than debugging */ - return -ENOSYS; - - if ( cmd != IOCTL_PRIVCMD_HYPERCALL ) - return -ENOSYS; - - if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) ) - return -EFAULT; - - if ( hypercall.op != __HYPERVISOR_grant_table_op ) - return -ENOSYS; - - /* hypercall-invoking asm taken from privcmd.c */ - __asm__ __volatile__ ( - "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; " - "movl 4(%%eax),%%ebx ;" - "movl 8(%%eax),%%ecx ;" - "movl 12(%%eax),%%edx ;" - "movl 16(%%eax),%%esi ;" - "movl 20(%%eax),%%edi ;" - "movl (%%eax),%%eax ;" - TRAP_INSTR "; " - "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx" - : "=a" (ret) : "0" (&hypercall) : "memory" ); - - return ret; + int ret; + privcmd_hypercall_t hypercall; + + /* + * XXX Need safety checks here if using for anything other + * than debugging. + */ + return -ENOSYS; + + if ( cmd != IOCTL_PRIVCMD_HYPERCALL ) + return -ENOSYS; + + if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) ) + return -EFAULT; + + if ( hypercall.op != __HYPERVISOR_grant_table_op ) + return -ENOSYS; + + /* hypercall-invoking asm taken from privcmd.c */ + __asm__ __volatile__ ( + "pushl %%ebx; pushl %%ecx; pushl %%edx; " + "pushl %%esi; pushl %%edi; " + "movl 4(%%eax),%%ebx ;" + "movl 8(%%eax),%%ecx ;" + "movl 12(%%eax),%%edx ;" + "movl 16(%%eax),%%esi ;" + "movl 20(%%eax),%%edi ;" + "movl (%%eax),%%eax ;" + TRAP_INSTR "; " + "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx" + : "=a" (ret) : "0" (&hypercall) : "memory" ); + + return ret; } static struct file_operations grant_file_ops = { - ioctl: grant_ioctl, + ioctl: grant_ioctl, }; static int grant_read(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len; - unsigned int i; - grant_entry_t *gt; - - gt = (grant_entry_t *)shared; - len = 0; - - for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) - /* TODO: safety catch here until this can handle >PAGE_SIZE output */ - if (len > (PAGE_SIZE - 200)) - { - len += sprintf( page + len, "Truncated.\n"); - break; - } - - if ( gt[i].flags ) - len += sprintf( page + len, - "Grant: ref (0x%x) flags (0x%hx) dom (0x%hx) frame (0x%x)\n", - i, - gt[i].flags, - gt[i].domid, - gt[i].frame ); - - *eof = 1; - return len; + int len; + unsigned int i; + grant_entry_t *gt; + + gt = (grant_entry_t *)shared; + len = 0; + + for (i = 0; i < NR_GRANT_ENTRIES; i++) { + if (len > (PAGE_SIZE - 200)) { + len += sprintf( page + len, "Truncated.\n"); + break; + } + } + + if (gt[i].flags) { + len += sprintf(page + len, + "Grant: ref (0x%x) flags (0x%hx) " + "dom (0x%hx) frame (0x%x)\n", + i, + gt[i].flags, + gt[i].domid, + gt[i].frame ); + } + + *eof = 1; + return len; } static int grant_write(struct file *file, const char __user *buffer, unsigned long count, void *data) { - /* TODO: implement this */ - return -ENOSYS; + /* TODO: implement this */ + return -ENOSYS; } #endif /* CONFIG_PROC_FS */ @@ -403,70 +412,81 @@ int gnttab_resume(void) { - gnttab_setup_table_t setup; - unsigned long frames[NR_GRANT_FRAMES]; - int i; - - setup.dom = DOMID_SELF; - setup.nr_frames = NR_GRANT_FRAMES; - setup.frame_list = frames; - - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1) != 0); - BUG_ON(setup.status != 0); - - for ( i = 0; i < NR_GRANT_FRAMES; i++ ) - set_fixmap(FIX_GNTTAB_END - i, frames[i] << PAGE_SHIFT); - - return 0; + gnttab_setup_table_t setup; + unsigned long frames[NR_GRANT_FRAMES]; + int i; + + setup.dom = DOMID_SELF; + setup.nr_frames = NR_GRANT_FRAMES; + setup.frame_list = frames; + + BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1)); + BUG_ON(setup.status != 0); + + for (i = 0; i < NR_GRANT_FRAMES; i++) + set_fixmap(FIX_GNTTAB_END - i, frames[i] << PAGE_SHIFT); + + return 0; } int gnttab_suspend(void) { - int i; - - for ( i = 0; i < NR_GRANT_FRAMES; i++ ) - clear_fixmap(FIX_GNTTAB_END - i); - - return 0; + int i; + + for (i = 0; i < NR_GRANT_FRAMES; i++) + clear_fixmap(FIX_GNTTAB_END - i); + + return 0; } static int __init gnttab_init(void) { - int i; - - if (xen_init() < 0) - return -ENODEV; - - BUG_ON(gnttab_resume()); - - shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END); - - for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) - gnttab_list[i] = i + 1; - + int i; + + if (xen_init() < 0) + return -ENODEV; + + BUG_ON(gnttab_resume()); + + shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END); + + for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++) + gnttab_list[i] = i + 1; + gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES; + gnttab_free_head = NR_RESERVED_ENTRIES; + #ifdef CONFIG_PROC_FS - /* - * /proc/xen/grant : used by libxc to access grant tables - */ - if ( (grant_pde = create_xen_proc_entry("grant", 0600)) == NULL ) - { - WPRINTK("Unable to create grant xen proc entry\n"); - return -1; - } - - grant_file_ops.read = grant_pde->proc_fops->read; - grant_file_ops.write = grant_pde->proc_fops->write; - - grant_pde->proc_fops = &grant_file_ops; - - grant_pde->read_proc = &grant_read; - grant_pde->write_proc = &grant_write; + /* + * /proc/xen/grant : used by libxc to access grant tables + */ + if ((grant_pde = create_xen_proc_entry("grant", 0600)) == NULL) { + WPRINTK("Unable to create grant xen proc entry\n"); + return -1; + } + + grant_file_ops.read = grant_pde->proc_fops->read; + grant_file_ops.write = grant_pde->proc_fops->write; + + grant_pde->proc_fops = &grant_file_ops; + + grant_pde->read_proc = &grant_read; + grant_pde->write_proc = &grant_write; #endif - printk("Grant table initialized\n"); - return 0; + printk("Grant table initialized\n"); + return 0; } __initcall(gnttab_init); + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/kernel/reboot.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Thu Sep 29 23:28:44 2005 @@ -12,7 +12,6 @@ #include <asm-xen/evtchn.h> #include <asm/hypervisor.h> #include <asm-xen/xen-public/dom0_ops.h> -#include <asm-xen/queues.h> #include <asm-xen/xenbus.h> #include <linux/cpu.h> #include <linux/kthread.h> @@ -43,12 +42,10 @@ HYPERVISOR_shutdown(); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) int reboot_thru_bios = 0; /* for dmi_scan.c */ EXPORT_SYMBOL(machine_restart); EXPORT_SYMBOL(machine_halt); EXPORT_SYMBOL(machine_power_off); -#endif /****************************************************************************** @@ -66,227 +63,194 @@ static int __do_suspend(void *ignore) { - int i, j, k, fpp; - -#ifdef CONFIG_XEN_USB_FRONTEND - extern void usbif_resume(); -#else -#define usbif_resume() do{}while(0) -#endif - - extern int gnttab_suspend(void); - extern int gnttab_resume(void); - - extern void time_suspend(void); - extern void time_resume(void); - extern unsigned long max_pfn; - extern unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[]; + int i, j, k, fpp; + + extern int gnttab_suspend(void); + extern int gnttab_resume(void); + + extern void time_resume(void); + extern unsigned long max_pfn; + extern unsigned long *pfn_to_mfn_frame_list_list; + extern unsigned long *pfn_to_mfn_frame_list[]; #ifdef CONFIG_SMP - extern void smp_suspend(void); - extern void smp_resume(void); - - static vcpu_guest_context_t suspended_cpu_records[NR_CPUS]; - cpumask_t prev_online_cpus, prev_present_cpus; - - void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt); - int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt); -#endif - - extern void xencons_suspend(void); - extern void xencons_resume(void); - - int err = 0; - - BUG_ON(smp_processor_id() != 0); - BUG_ON(in_interrupt()); + static vcpu_guest_context_t suspended_cpu_records[NR_CPUS]; + cpumask_t prev_online_cpus, prev_present_cpus; + + void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt); + int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt); +#endif + + extern void xencons_resume(void); + + int err = 0; + + BUG_ON(smp_processor_id() != 0); + BUG_ON(in_interrupt()); #if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU) - if (num_online_cpus() > 1) { - printk(KERN_WARNING - "Can't suspend SMP guests without CONFIG_HOTPLUG_CPU\n"); - return -EOPNOTSUPP; - } -#endif - - preempt_disable(); + if (num_online_cpus() > 1) { + printk(KERN_WARNING "Can't suspend SMP guests " + "without CONFIG_HOTPLUG_CPU\n"); + return -EOPNOTSUPP; + } +#endif + + xenbus_suspend(); + + preempt_disable(); #ifdef CONFIG_SMP - /* Take all of the other cpus offline. We need to be careful not - to get preempted between the final test for num_online_cpus() - == 1 and disabling interrupts, since otherwise userspace could - bring another cpu online, and then we'd be stuffed. At the - same time, cpu_down can reschedule, so we need to enable - preemption while doing that. This kind of sucks, but should be - correct. */ - /* (We don't need to worry about other cpus bringing stuff up, - since by the time num_online_cpus() == 1, there aren't any - other cpus) */ - cpus_clear(prev_online_cpus); - while (num_online_cpus() > 1) { + /* Take all of the other cpus offline. We need to be careful not + to get preempted between the final test for num_online_cpus() + == 1 and disabling interrupts, since otherwise userspace could + bring another cpu online, and then we'd be stuffed. At the + same time, cpu_down can reschedule, so we need to enable + preemption while doing that. This kind of sucks, but should be + correct. */ + /* (We don't need to worry about other cpus bringing stuff up, + since by the time num_online_cpus() == 1, there aren't any + other cpus) */ + cpus_clear(prev_online_cpus); + while (num_online_cpus() > 1) { + preempt_enable(); + for_each_online_cpu(i) { + if (i == 0) + continue; + err = cpu_down(i); + if (err != 0) { + printk(KERN_CRIT "Failed to take all CPUs " + "down: %d.\n", err); + goto out_reenable_cpus; + } + cpu_set(i, prev_online_cpus); + } + preempt_disable(); + } +#endif + + __cli(); + preempt_enable(); - for_each_online_cpu(i) { - if (i == 0) - continue; - err = cpu_down(i); - if (err != 0) { - printk(KERN_CRIT "Failed to take all CPUs down: %d.\n", err); - goto out_reenable_cpus; - } - cpu_set(i, prev_online_cpus); - } - preempt_disable(); - } -#endif - - __cli(); - - preempt_enable(); #ifdef CONFIG_SMP - cpus_clear(prev_present_cpus); - for_each_present_cpu(i) { - if (i == 0) - continue; - save_vcpu_context(i, &suspended_cpu_records[i]); - cpu_set(i, prev_present_cpus); - } -#endif + cpus_clear(prev_present_cpus); + for_each_present_cpu(i) { + if (i == 0) + continue; + save_vcpu_context(i, &suspended_cpu_records[i]); + cpu_set(i, prev_present_cpus); + } +#endif + + gnttab_suspend(); #ifdef __i386__ - mm_pin_all(); - kmem_cache_shrink(pgd_cache); -#endif - - time_suspend(); - -#ifdef CONFIG_SMP - smp_suspend(); -#endif - - xenbus_suspend(); - - xencons_suspend(); - - irq_suspend(); - - gnttab_suspend(); - - HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; - clear_fixmap(FIX_SHARED_INFO); - - xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn); - xen_start_info->console_mfn = mfn_to_pfn(xen_start_info->console_mfn); - - /* We'll stop somewhere inside this hypercall. When it returns, - we'll start resuming after the restore. */ - HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); - - shutting_down = SHUTDOWN_INVALID; - - set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); - - HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); - - memset(empty_zero_page, 0, PAGE_SIZE); + mm_pin_all(); + kmem_cache_shrink(pgd_cache); +#endif + + HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; + clear_fixmap(FIX_SHARED_INFO); + + xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn); + xen_start_info->console_mfn = mfn_to_pfn(xen_start_info->console_mfn); + + /* We'll stop somewhere inside this hypercall. When it returns, + we'll start resuming after the restore. */ + HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); + + shutting_down = SHUTDOWN_INVALID; + + set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); + + HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); + + memset(empty_zero_page, 0, PAGE_SIZE); - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = virt_to_mfn(pfn_to_mfn_frame_list_list); - fpp = PAGE_SIZE/sizeof(unsigned long); - for ( i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++ ) - { - if ( (j % fpp) == 0 ) - { - k++; - pfn_to_mfn_frame_list_list[k] = - virt_to_mfn(pfn_to_mfn_frame_list[k]); - j=0; - } - pfn_to_mfn_frame_list[k][j] = - virt_to_mfn(&phys_to_machine_mapping[i]); - } - HYPERVISOR_shared_info->arch.max_pfn = max_pfn; - - gnttab_resume(); - - irq_resume(); - - xencons_resume(); - - xenbus_resume(); + fpp = PAGE_SIZE/sizeof(unsigned long); + for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) { + if ((j % fpp) == 0) { + k++; + pfn_to_mfn_frame_list_list[k] = + virt_to_mfn(pfn_to_mfn_frame_list[k]); + j = 0; + } + pfn_to_mfn_frame_list[k][j] = + virt_to_mfn(&phys_to_machine_mapping[i]); + } + HYPERVISOR_shared_info->arch.max_pfn = max_pfn; + + gnttab_resume(); + + irq_resume(); + + time_resume(); #ifdef CONFIG_SMP - smp_resume(); -#endif - - time_resume(); - - usbif_resume(); - -#ifdef CONFIG_SMP - for_each_cpu_mask(i, prev_present_cpus) - restore_vcpu_context(i, &suspended_cpu_records[i]); -#endif - - __sti(); + for_each_cpu_mask(i, prev_present_cpus) + restore_vcpu_context(i, &suspended_cpu_records[i]); +#endif + + __sti(); + + xencons_resume(); + + xenbus_resume(); #ifdef CONFIG_SMP out_reenable_cpus: - for_each_cpu_mask(i, prev_online_cpus) { - j = cpu_up(i); - if (j != 0) { - printk(KERN_CRIT "Failed to bring cpu %d back up (%d).\n", - i, j); - err = j; - } - } -#endif - - return err; + for_each_cpu_mask(i, prev_online_cpus) { + j = cpu_up(i); + if (j != 0) { + printk(KERN_CRIT "Failed to bring cpu " + "%d back up (%d).\n", + i, j); + err = j; + } + } +#endif + + return err; } static int shutdown_process(void *__unused) { - static char *envp[] = { "HOME=/", "TERM=linux", - "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; - static char *restart_argv[] = { "/sbin/reboot", NULL }; - static char *poweroff_argv[] = { "/sbin/poweroff", NULL }; - - extern asmlinkage long sys_reboot(int magic1, int magic2, - unsigned int cmd, void *arg); - - daemonize( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - "shutdown" -#endif - ); - - switch ( shutting_down ) - { - case SHUTDOWN_POWEROFF: - if ( execve("/sbin/poweroff", poweroff_argv, envp) < 0 ) - { - sys_reboot(LINUX_REBOOT_MAGIC1, - LINUX_REBOOT_MAGIC2, - LINUX_REBOOT_CMD_POWER_OFF, - NULL); - } - break; - - case SHUTDOWN_REBOOT: - if ( execve("/sbin/reboot", restart_argv, envp) < 0 ) - { - sys_reboot(LINUX_REBOOT_MAGIC1, - LINUX_REBOOT_MAGIC2, - LINUX_REBOOT_CMD_RESTART, - NULL); - } - break; - } - - shutting_down = SHUTDOWN_INVALID; /* could try again */ - - return 0; + static char *envp[] = { "HOME=/", "TERM=linux", + "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; + static char *restart_argv[] = { "/sbin/reboot", NULL }; + static char *poweroff_argv[] = { "/sbin/poweroff", NULL }; + + extern asmlinkage long sys_reboot(int magic1, int magic2, + unsigned int cmd, void *arg); + + daemonize("shutdown"); + + switch (shutting_down) { + case SHUTDOWN_POWEROFF: + if (execve("/sbin/poweroff", poweroff_argv, envp) < 0) { + sys_reboot(LINUX_REBOOT_MAGIC1, + LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_POWER_OFF, + NULL); + } + break; + + case SHUTDOWN_REBOOT: + if (execve("/sbin/reboot", restart_argv, envp) < 0) { + sys_reboot(LINUX_REBOOT_MAGIC1, + LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART, + NULL); + } + break; + } + + shutting_down = SHUTDOWN_INVALID; /* could try again */ + + return 0; } static struct task_struct *kthread_create_on_cpu(int (*f)(void *arg), @@ -294,113 +258,109 @@ const char *name, int cpu) { - struct task_struct *p; - p = kthread_create(f, arg, name); - kthread_bind(p, cpu); - wake_up_process(p); - return p; + struct task_struct *p; + p = kthread_create(f, arg, name); + kthread_bind(p, cpu); + wake_up_process(p); + return p; } static void __shutdown_handler(void *unused) { - int err; - - if ( shutting_down != SHUTDOWN_SUSPEND ) - { - err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES); - if ( err < 0 ) - printk(KERN_ALERT "Error creating shutdown process!\n"); - } - else - { - kthread_create_on_cpu(__do_suspend, NULL, "suspender", 0); - } + int err; + + if (shutting_down != SHUTDOWN_SUSPEND) { + err = kernel_thread(shutdown_process, NULL, + CLONE_FS | CLONE_FILES); + if ( err < 0 ) + printk(KERN_ALERT "Error creating shutdown " + "process!\n"); + } else { + kthread_create_on_cpu(__do_suspend, NULL, "suspender", 0); + } } static void shutdown_handler(struct xenbus_watch *watch, const char *node) { - static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL); - char *str; - int err; + static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL); + char *str; + int err; again: - err = xenbus_transaction_start(); - if (err) - return; - str = (char *)xenbus_read("control", "shutdown", NULL); - /* Ignore read errors and empty reads. */ - if (XENBUS_IS_ERR_READ(str)) { - xenbus_transaction_end(1); - return; - } - - xenbus_write("control", "shutdown", ""); - - err = xenbus_transaction_end(0); - if (err == -EAGAIN) { + err = xenbus_transaction_start(); + if (err) + return; + str = (char *)xenbus_read("control", "shutdown", NULL); + /* Ignore read errors and empty reads. */ + if (XENBUS_IS_ERR_READ(str)) { + xenbus_transaction_end(1); + return; + } + + xenbus_write("control", "shutdown", ""); + + err = xenbus_transaction_end(0); + if (err == -EAGAIN) { + kfree(str); + goto again; + } + + if (strcmp(str, "poweroff") == 0) + shutting_down = SHUTDOWN_POWEROFF; + else if (strcmp(str, "reboot") == 0) + shutting_down = SHUTDOWN_REBOOT; + else if (strcmp(str, "suspend") == 0) + shutting_down = SHUTDOWN_SUSPEND; + else { + printk("Ignoring shutdown request: %s\n", str); + shutting_down = SHUTDOWN_INVALID; + } + kfree(str); - goto again; - } - - if (strcmp(str, "poweroff") == 0) - shutting_down = SHUTDOWN_POWEROFF; - else if (strcmp(str, "reboot") == 0) - shutting_down = SHUTDOWN_REBOOT; - else if (strcmp(str, "suspend") == 0) - shutting_down = SHUTDOWN_SUSPEND; - else { - printk("Ignoring shutdown request: %s\n", str); - shutting_down = SHUTDOWN_INVALID; - } - - kfree(str); - - if (shutting_down != SHUTDOWN_INVALID) - schedule_work(&shutdown_work); + + if (shutting_down != SHUTDOWN_INVALID) + schedule_work(&shutdown_work); } #ifdef CONFIG_MAGIC_SYSRQ static void sysrq_handler(struct xenbus_watch *watch, const char *node) { - char sysrq_key = '\0'; - int err; + char sysrq_key = '\0'; + int err; again: - err = xenbus_transaction_start(); - if (err) - return; - if (!xenbus_scanf("control", "sysrq", "%c", &sysrq_key)) { - printk(KERN_ERR "Unable to read sysrq code in control/sysrq\n"); - xenbus_transaction_end(1); - return; - } - - if (sysrq_key != '\0') - xenbus_printf("control", "sysrq", "%c", '\0'); - - err = xenbus_transaction_end(0); - if (err == -EAGAIN) - goto again; - - if (sysrq_key != '\0') { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - handle_sysrq(sysrq_key, NULL, NULL); -#else - handle_sysrq(sysrq_key, NULL, NULL, NULL); -#endif - } + err = xenbus_transaction_start(); + if (err) + return; + if (!xenbus_scanf("control", "sysrq", "%c", &sysrq_key)) { + printk(KERN_ERR "Unable to read sysrq code in " + "control/sysrq\n"); + xenbus_transaction_end(1); + return; + } + + if (sysrq_key != '\0') + xenbus_printf("control", "sysrq", "%c", '\0'); + + err = xenbus_transaction_end(0); + if (err == -EAGAIN) + goto again; + + if (sysrq_key != '\0') { + handle_sysrq(sysrq_key, NULL, NULL); + } } #endif static struct xenbus_watch shutdown_watch = { - .node = "control/shutdown", - .callback = shutdown_handler + .node = "control/shutdown", + .callback = shutdown_handler }; #ifdef CONFIG_MAGIC_SYSRQ static struct xenbus_watch sysrq_watch = { - .node ="control/sysrq", - .callback = sysrq_handler + .node ="control/sysrq", + .callback = sysrq_handler }; #endif @@ -413,39 +373,50 @@ unsigned long event, void *data) { - int err1 = 0; + int err1 = 0; #ifdef CONFIG_MAGIC_SYSRQ - int err2 = 0; -#endif - - BUG_ON(down_trylock(&xenbus_lock) == 0); - - err1 = register_xenbus_watch(&shutdown_watch); + int err2 = 0; +#endif + + BUG_ON(down_trylock(&xenbus_lock) == 0); + + err1 = register_xenbus_watch(&shutdown_watch); #ifdef CONFIG_MAGIC_SYSRQ - err2 = register_xenbus_watch(&sysrq_watch); -#endif - - if (err1) { - printk(KERN_ERR "Failed to set shutdown watcher\n"); - } + err2 = register_xenbus_watch(&sysrq_watch); +#endif + + if (err1) { + printk(KERN_ERR "Failed to set shutdown watcher\n"); + } #ifdef CONFIG_MAGIC_SYSRQ - if (err2) { - printk(KERN_ERR "Failed to set sysrq watcher\n"); - } -#endif - - return NOTIFY_DONE; + if (err2) { + printk(KERN_ERR "Failed to set sysrq watcher\n"); + } +#endif + + return NOTIFY_DONE; } static int __init setup_shutdown_event(void) { - xenstore_notifier.notifier_call = setup_shutdown_watcher; - - register_xenstore_notifier(&xenstore_notifier); + xenstore_notifier.notifier_call = setup_shutdown_watcher; + + register_xenstore_notifier(&xenstore_notifier); - return 0; + return 0; } subsys_initcall(setup_shutdown_event); + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ +# diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/kernel/smp.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/smp.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/smp.c Thu Sep 29 23:28:44 2005 @@ -11,6 +11,15 @@ int setup_profiling_timer(unsigned int multiplier) { printk("setup_profiling_timer\n"); - return 0; } + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/kernel/xen_proc.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/xen_proc.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/xen_proc.c Thu Sep 29 23:28:44 2005 @@ -6,13 +6,23 @@ struct proc_dir_entry *create_xen_proc_entry(const char *name, mode_t mode) { - if ( xen_base == NULL ) - if ( (xen_base = proc_mkdir("xen", &proc_root)) == NULL ) - panic("Couldn't create /proc/xen"); - return create_proc_entry(name, mode, xen_base); + if ( xen_base == NULL ) + if ( (xen_base = proc_mkdir("xen", &proc_root)) == NULL ) + panic("Couldn't create /proc/xen"); + return create_proc_entry(name, mode, xen_base); } void remove_xen_proc_entry(const char *name) { - remove_proc_entry(name, xen_base); + remove_proc_entry(name, xen_base); } + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S Thu Sep 29 23:28:44 2005 @@ -536,7 +536,7 @@ CFI_ENDPROC .endm -#ifdef CONFIG_SMP +#if 0 ENTRY(reschedule_interrupt) apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/genapic_xen.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/genapic_xen.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/genapic_xen.c Thu Sep 29 23:28:44 2005 @@ -31,14 +31,9 @@ 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); + int evtchn = per_cpu(ipi_to_evtchn, cpu)[vector]; + BUG_ON(evtchn < 0); + notify_remote_via_evtchn(evtchn); } void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest) diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Thu Sep 29 23:28:44 2005 @@ -771,11 +771,14 @@ virt_to_mfn(&phys_to_machine_mapping[i]); } HYPERVISOR_shared_info->arch.max_pfn = max_pfn; - - - - - + } + + if ( ! (xen_start_info->flags & SIF_INITDOMAIN)) + { + acpi_disabled = 1; +#ifdef CONFIG_ACPI_BOOT + acpi_ht = 0; +#endif } #endif diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c Thu Sep 29 23:28:44 2005 @@ -445,25 +445,6 @@ } #ifdef CONFIG_XEN -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); #endif @@ -498,7 +479,6 @@ enable_APIC_timer(); #else local_setup_timer(); - ldebug_setup(); smp_intr_init(); local_irq_enable(); #endif diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c Thu Sep 29 23:28:44 2005 @@ -149,7 +149,9 @@ pmd_t *pmd; pte_t *pte; + preempt_disable(); pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id()); + preempt_enable(); pgd += pgd_index(address); printk("PGD %lx ", pgd_val(*pgd)); @@ -252,7 +254,9 @@ /* On Xen the line below does not always work. Needs investigating! */ /*pgd = pgd_offset(current->mm ?: &init_mm, address);*/ + preempt_disable(); pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id()); + preempt_enable(); pgd += pgd_index(address); pgd_ref = pgd_offset_k(address); diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Thu Sep 29 23:28:44 2005 @@ -481,7 +481,7 @@ spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); /* Kick the relevant domain. */ - notify_via_evtchn(blkif->evtchn); + notify_remote_via_irq(blkif->irq); } void blkif_deschedule(blkif_t *blkif) diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/blkback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Thu Sep 29 23:28:44 2005 @@ -44,7 +44,7 @@ unsigned int handle; /* Physical parameters of the comms window. */ unsigned int evtchn; - unsigned int remote_evtchn; + unsigned int irq; /* Comms information. */ blkif_back_ring_t blk_ring; struct vm_struct *blk_ring_area; diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/blkback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Thu Sep 29 23:28:44 2005 @@ -71,8 +71,6 @@ evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain }; int err; - BUG_ON(blkif->remote_evtchn); - if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL ) return -ENOMEM; @@ -94,13 +92,12 @@ } blkif->evtchn = op.u.bind_interdomain.port1; - blkif->remote_evtchn = evtchn; sring = (blkif_sring_t *)blkif->blk_ring_area->addr; SHARED_RING_INIT(sring); BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); - bind_evtchn_to_irqhandler( + blkif->irq = bind_evtchn_to_irqhandler( blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif); blkif->status = CONNECTED; @@ -109,20 +106,12 @@ static void free_blkif(void *arg) { - evtchn_op_t op = { .cmd = EVTCHNOP_close }; blkif_t *blkif = (blkif_t *)arg; - op.u.close.port = blkif->evtchn; - op.u.close.dom = DOMID_SELF; - HYPERVISOR_event_channel_op(&op); - op.u.close.port = blkif->remote_evtchn; - op.u.close.dom = blkif->domid; - HYPERVISOR_event_channel_op(&op); + if (blkif->irq) + unbind_evtchn_from_irqhandler(blkif->irq, blkif); vbd_free(&blkif->vbd); - - if (blkif->evtchn) - unbind_evtchn_from_irqhandler(blkif->evtchn, blkif); if (blkif->blk_ring.sring) { unmap_frontend_page(blkif); diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Sep 29 23:28:44 2005 @@ -80,6 +80,15 @@ return; } + /* Map the shared frame, irq etc. */ + err = blkif_map(be->blkif, ring_ref, evtchn); + if (err) { + xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u", + ring_ref, evtchn); + return; + } + /* XXX From here on should 'blkif_unmap' on error. */ + again: /* Supply the information about the device the frontend needs */ err = xenbus_transaction_start(); @@ -109,14 +118,6 @@ if (err) { xenbus_dev_error(be->dev, err, "writing %s/sector-size", be->dev->nodename); - goto abort; - } - - /* Map the shared frame, irq etc. */ - err = blkif_map(be->blkif, ring_ref, evtchn); - if (err) { - xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u", - ring_ref, evtchn); goto abort; } diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Thu Sep 29 23:28:44 2005 @@ -57,10 +57,7 @@ #define MAXIMUM_OUTSTANDING_BLOCK_REQS \ (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE) -#define GRANTREF_INVALID (1<<15) -#define GRANT_INVALID_REF (0xFFFF) - -static int recovery = 0; /* Recovery in progress: protected by blkif_io_lock */ +#define GRANT_INVALID_REF 0 static void kick_pending_request_queues(struct blkfront_info *info); @@ -84,22 +81,10 @@ info->shadow_free = id; } -static inline void pickle_request(struct blk_shadow *s, blkif_request_t *r) -{ - - s->req = *r; -} - -static inline void unpickle_request(blkif_request_t *r, struct blk_shadow *s) -{ - - *r = s->req; -} - static inline void flush_requests(struct blkfront_info *info) { RING_PUSH_REQUESTS(&info->ring); - notify_via_evtchn(info->evtchn); + notify_remote_via_irq(info->irq); } static void kick_pending_request_queues(struct blkfront_info *info) @@ -235,7 +220,7 @@ rq_data_dir(req) ); info->shadow[id].frame[ring_req->nr_segments] = - buffer_mfn; + mfn_to_pfn(buffer_mfn); ring_req->frame_and_sects[ring_req->nr_segments] = blkif_fas_from_gref(ref, fsect, lsect); @@ -247,7 +232,7 @@ info->ring.req_prod_pvt++; /* Keep a private copy so we can reissue requests when recovering. */ - pickle_request(&info->shadow[id], ring_req); + info->shadow[id].req = *ring_req; gnttab_free_grant_references(gref_head); @@ -312,7 +297,7 @@ spin_lock_irqsave(&blkif_io_lock, flags); - if (unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery)) { + if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) { spin_unlock_irqrestore(&blkif_io_lock, flags); return IRQ_HANDLED; } @@ -372,8 +357,9 @@ if (info->ring_ref != GRANT_INVALID_REF) gnttab_end_foreign_access(info->ring_ref, 0); info->ring_ref = GRANT_INVALID_REF; - unbind_evtchn_from_irqhandler(info->evtchn, info); - info->evtchn = 0; + if (info->irq) + unbind_evtchn_from_irqhandler(info->irq, info); + info->evtchn = info->irq = 0; } static void blkif_recover(struct blkfront_info *info) @@ -401,36 +387,30 @@ if (copy[i].request == 0) continue; - /* Grab a request slot and unpickle shadow state into it. */ + /* Grab a request slot and copy shadow state into it. */ req = RING_GET_REQUEST( &info->ring, info->ring.req_prod_pvt); - unpickle_request(req, ©[i]); + *req = copy[i].req; /* We get a new request id, and must reset the shadow state. */ req->id = GET_ID_FROM_FREELIST(info); memcpy(&info->shadow[req->id], ©[i], sizeof(copy[i])); /* Rewrite any grant references invalidated by susp/resume. */ - for (j = 0; j < req->nr_segments; j++) { - if ( req->frame_and_sects[j] & GRANTREF_INVALID ) - gnttab_grant_foreign_access_ref( - blkif_gref_from_fas( - req->frame_and_sects[j]), - info->backend_id, - info->shadow[req->id].frame[j], - rq_data_dir( - (struct request *) - info->shadow[req->id].request)); - req->frame_and_sects[j] &= ~GRANTREF_INVALID; - } + for (j = 0; j < req->nr_segments; j++) + gnttab_grant_foreign_access_ref( + blkif_gref_from_fas(req->frame_and_sects[j]), + info->backend_id, + pfn_to_mfn(info->shadow[req->id].frame[j]), + rq_data_dir( + (struct request *) + info->shadow[req->id].request)); info->shadow[req->id].req = *req; info->ring.req_prod_pvt++; } kfree(copy); - - recovery = 0; /* info->ring->req_prod will be set when we flush_requests().*/ wmb(); @@ -438,7 +418,7 @@ /* Kicks things back into life. */ flush_requests(info); - /* Now safe to left other people use the interface. */ + /* Now safe to let other people use the interface. */ info->connected = BLKIF_STATE_CONNECTED; } @@ -450,10 +430,12 @@ err = bind_evtchn_to_irqhandler( info->evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", info); - if (err != 0) { + if (err <= 0) { WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err); return; } + + info->irq = err; } @@ -487,8 +469,8 @@ return; } + info->connected = BLKIF_STATE_CONNECTED; xlvbd_add(sectors, info->vdevice, binfo, sector_size, info); - info->connected = BLKIF_STATE_CONNECTED; blkif_state = BLKIF_STATE_CONNECTED; @@ -591,17 +573,6 @@ goto abort_transaction; } - info->backend = backend; - backend = NULL; - - info->watch.node = info->backend; - info->watch.callback = watch_for_status; - err = register_xenbus_watch(&info->watch); - if (err) { - message = "registering watch on backend"; - goto abort_transaction; - } - err = xenbus_transaction_end(0); if (err) { if (err == -EAGAIN) @@ -610,10 +581,17 @@ goto destroy_blkring; } - out: - if (backend) - kfree(backend); - return err; + info->watch.node = backend; + info->watch.callback = watch_for_status; + err = register_xenbus_watch(&info->watch); + if (err) { + message = "registering watch on backend"; + goto destroy_blkring; + } + + info->backend = backend; + + return 0; abort_transaction: xenbus_transaction_end(1); @@ -621,7 +599,10 @@ xenbus_dev_error(dev, err, "%s", message); destroy_blkring: blkif_free(info); - goto out; + out: + if (backend) + kfree(backend); + return err; } /* Setup supplies the backend dir, virtual device. @@ -702,9 +683,6 @@ kfree(info->backend); info->backend = NULL; - recovery = 1; - blkif_free(info); - return 0; } @@ -713,11 +691,12 @@ struct blkfront_info *info = dev->data; int err; - /* FIXME: Check geometry hasn't changed here... */ + blkif_free(info); + err = talk_to_backend(dev, info); - if (!err) { + if (!err) blkif_recover(info); - } + return err; } diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/blkfront/block.h --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Sep 29 23:28:44 2005 @@ -123,7 +123,7 @@ int backend_id; int ring_ref; blkif_front_ring_t ring; - unsigned int evtchn; + unsigned int evtchn, irq; struct xlbd_major_info *mi; request_queue_t *rq; struct work_struct work; diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Thu Sep 29 23:28:44 2005 @@ -842,7 +842,7 @@ spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); /* Kick the relevant domain. */ - notify_via_evtchn(blkif->evtchn); + notify_remote_via_irq(blkif->irq); } static struct miscdevice blktap_miscdev = { diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/blktap/common.h --- a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h Thu Sep 29 23:28:44 2005 @@ -46,7 +46,7 @@ unsigned int handle; /* Physical parameters of the comms window. */ unsigned int evtchn; - unsigned int remote_evtchn; + unsigned int irq; /* Comms information. */ blkif_back_ring_t blk_ring; struct vm_struct *blk_ring_area; diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/blktap/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c Thu Sep 29 23:28:44 2005 @@ -71,8 +71,6 @@ evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain }; int err; - BUG_ON(blkif->remote_evtchn); - if ((blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL) return -ENOMEM; @@ -93,35 +91,26 @@ return err; } - blkif->evtchn = op.u.bind_interdomain.port1; - blkif->remote_evtchn = evtchn; sring = (blkif_sring_t *)blkif->blk_ring_area->addr; SHARED_RING_INIT(sring); BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); - bind_evtchn_to_irqhandler( + blkif->irq = bind_evtchn_to_irqhandler( blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif); - blkif->status = CONNECTED; + + blkif->status = CONNECTED; return 0; } static void free_blkif(void *arg) { - evtchn_op_t op = { .cmd = EVTCHNOP_close }; blkif_t *blkif = (blkif_t *)arg; - op.u.close.port = blkif->evtchn; - op.u.close.dom = DOMID_SELF; - HYPERVISOR_event_channel_op(&op); - op.u.close.port = blkif->remote_evtchn; - op.u.close.dom = blkif->domid; - HYPERVISOR_event_channel_op(&op); - - if (blkif->evtchn) - unbind_evtchn_from_irqhandler(blkif->evtchn, blkif); + if (blkif->irq) + unbind_evtchn_from_irqhandler(blkif->irq, blkif); if (blkif->blk_ring.sring) { unmap_frontend_page(blkif); diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c --- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Thu Sep 29 23:28:44 2005 @@ -21,7 +21,6 @@ #include <linux/err.h> #include "xencons_ring.h" - struct ring_head { u32 cons; @@ -29,6 +28,7 @@ char buf[0]; } __attribute__((packed)); +static int xencons_irq; #define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head)) #define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE) @@ -46,7 +46,8 @@ /* don't block - write as much as possible and return */ -static int __xencons_ring_send(struct ring_head *ring, const char *data, unsigned len) +static int __xencons_ring_send( + struct ring_head *ring, const char *data, unsigned len) { int copied = 0; @@ -63,13 +64,9 @@ int xencons_ring_send(const char *data, unsigned len) { - struct ring_head *out = outring(); - int sent = 0; - - sent = __xencons_ring_send(out, data, len); - notify_via_evtchn(xen_start_info->console_evtchn); + int sent = __xencons_ring_send(outring(), data, len); + notify_remote_via_irq(xencons_irq); return sent; - } @@ -97,32 +94,28 @@ { int err; + if (xencons_irq) + unbind_evtchn_from_irqhandler(xencons_irq, inring()); + xencons_irq = 0; + if (!xen_start_info->console_evtchn) return 0; - err = bind_evtchn_to_irqhandler(xen_start_info->console_evtchn, - handle_input, 0, "xencons", inring()); - if (err) { + err = bind_evtchn_to_irqhandler( + xen_start_info->console_evtchn, + handle_input, 0, "xencons", inring()); + if (err <= 0) { xprintk("XEN console request irq failed %i\n", err); return err; } + xencons_irq = err; + return 0; -} - -void xencons_suspend(void) -{ - - if (!xen_start_info->console_evtchn) - return; - - unbind_evtchn_from_irqhandler(xen_start_info->console_evtchn, - inring()); } void xencons_resume(void) { - (void)xencons_ring_init(); } diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/netback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Sep 29 23:28:44 2005 @@ -21,8 +21,6 @@ #include <asm-xen/xen-public/grant_table.h> #include <asm-xen/gnttab.h> #include <asm-xen/driver_util.h> - -#define GRANT_INVALID_REF (0xFFFF) #if 0 #define ASSERT(_p) \ @@ -52,7 +50,7 @@ u16 rx_shmem_handle; grant_ref_t rx_shmem_ref; unsigned int evtchn; - unsigned int remote_evtchn; + unsigned int irq; /* The shared rings and indexes. */ netif_tx_interface_t *tx; diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/netback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Thu Sep 29 23:28:44 2005 @@ -15,18 +15,17 @@ spin_lock_bh(&dev->xmit_lock); netif->active = 1; spin_unlock_bh(&dev->xmit_lock); - (void)bind_evtchn_to_irqhandler( - netif->evtchn, netif_be_int, 0, dev->name, netif); + enable_irq(netif->irq); netif_schedule_work(netif); } static void __netif_down(netif_t *netif) { struct net_device *dev = netif->dev; + disable_irq(netif->irq); spin_lock_bh(&dev->xmit_lock); netif->active = 0; spin_unlock_bh(&dev->xmit_lock); - unbind_evtchn_from_irqhandler(netif->evtchn, netif); netif_deschedule_work(netif); } @@ -203,7 +202,10 @@ } netif->evtchn = op.u.bind_interdomain.port1; - netif->remote_evtchn = evtchn; + + netif->irq = bind_evtchn_to_irqhandler( + netif->evtchn, netif_be_int, 0, netif->dev->name, netif); + disable_irq(netif->irq); netif->tx = (netif_tx_interface_t *)netif->comms_area->addr; netif->rx = (netif_rx_interface_t *) @@ -224,21 +226,15 @@ static void free_netif_callback(void *arg) { - evtchn_op_t op = { .cmd = EVTCHNOP_close }; netif_t *netif = (netif_t *)arg; /* - * These can't be done in netif_disconnect() because at that point + * This can't be done in netif_disconnect() because at that point * there may be outstanding requests in the network stack whose * asynchronous responses must still be notified to the remote driver. */ - - op.u.close.port = netif->evtchn; - op.u.close.dom = DOMID_SELF; - HYPERVISOR_event_channel_op(&op); - op.u.close.port = netif->remote_evtchn; - op.u.close.dom = netif->domid; - HYPERVISOR_event_channel_op(&op); + if (netif->irq) + unbind_evtchn_from_irqhandler(netif->irq, netif); unregister_netdev(netif->dev); diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Sep 29 23:28:44 2005 @@ -42,7 +42,7 @@ static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE]; static gnttab_transfer_t grant_rx_op[MAX_PENDING_REQS]; -static unsigned char rx_notify[NR_EVENT_CHANNELS]; +static unsigned char rx_notify[NR_IRQS]; /* Don't currently gate addition of an interface to the tx scheduling list. */ #define tx_work_exists(_if) (1) @@ -209,7 +209,7 @@ { netif_t *netif = NULL; s8 status; - u16 size, id, evtchn; + u16 size, id, irq; multicall_entry_t *mcl; mmu_update_t *mmu; gnttab_transfer_t *gop; @@ -320,16 +320,16 @@ gop->status, netif->domid); /* XXX SMH: should free 'old_mfn' here */ status = NETIF_RSP_ERROR; - } - evtchn = netif->evtchn; + } + irq = netif->irq; id = netif->rx->ring[ MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id; if (make_rx_response(netif, id, status, (unsigned long)skb->data & ~PAGE_MASK, size, skb->proto_csum_valid) && - (rx_notify[evtchn] == 0)) { - rx_notify[evtchn] = 1; - notify_list[notify_nr++] = evtchn; + (rx_notify[irq] == 0)) { + rx_notify[irq] = 1; + notify_list[notify_nr++] = irq; } netif_put(netif); @@ -339,9 +339,9 @@ } while (notify_nr != 0) { - evtchn = notify_list[--notify_nr]; - rx_notify[evtchn] = 0; - notify_via_evtchn(evtchn); + irq = notify_list[--notify_nr]; + rx_notify[irq] = 0; + notify_remote_via_irq(irq); } /* More work to do? */ @@ -434,7 +434,6 @@ gop->host_addr = MMAP_VADDR(pending_idx); gop->dev_bus_addr = 0; gop->handle = grant_tx_ref[pending_idx]; - grant_tx_ref[pending_idx] = GRANT_INVALID_REF; gop++; } BUG_ON(HYPERVISOR_grant_table_op( @@ -718,7 +717,7 @@ mb(); /* Update producer before checking event threshold. */ if (i == netif->tx->event) - notify_via_evtchn(netif->evtchn); + notify_remote_via_irq(netif->irq); } static int make_rx_response(netif_t *netif, diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Sep 29 23:28:44 2005 @@ -1,7 +1,7 @@ /****************************************************************************** * Virtual network driver for conversing with remote driver backends. * - * Copyright (c) 2002-2004, K A Fraser + * Copyright (c) 2002-2005, K A Fraser * * This file may be distributed separately from the Linux kernel, or * incorporated into other software packages, subject to the following license: @@ -57,7 +57,7 @@ #include <asm-xen/xen-public/grant_table.h> #include <asm-xen/gnttab.h> -#define GRANT_INVALID_REF (0xFFFF) +#define GRANT_INVALID_REF 0 #ifndef __GFP_NOWARN #define __GFP_NOWARN 0 @@ -127,7 +127,7 @@ spinlock_t rx_lock; unsigned int handle; - unsigned int evtchn; + unsigned int evtchn, irq; /* What is the status of our connection to the remote backend? */ #define BEST_CLOSED 0 @@ -457,7 +457,7 @@ /* Only notify Xen if we really have to. */ mb(); if (np->tx->TX_TEST_IDX == i) - notify_via_evtchn(np->evtchn); + notify_remote_via_irq(np->irq); return 0; @@ -700,6 +700,7 @@ struct net_private *np; int i, requeue_idx; netif_tx_request_t *tx; + struct sk_buff *skb; np = netdev_priv(dev); spin_lock_irq(&np->tx_lock); @@ -711,7 +712,8 @@ np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0; np->rx->event = np->tx->event = 1; - /* Step 2: Rebuild the RX and TX ring contents. + /* + * Step 2: Rebuild the RX and TX ring contents. * NB. We could just free the queued TX packets now but we hope * that sending them out might do some good. We have to rebuild * the RX ring because some of our pages are currently flipped out @@ -722,56 +724,59 @@ * them. */ - /* Rebuild the TX buffer freelist and the TX ring itself. + /* + * Rebuild the TX buffer freelist and the TX ring itself. * NB. This reorders packets. We could keep more private state * to avoid this but maybe it doesn't matter so much given the * interface has been down. */ for (requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++) { - if ((unsigned long)np->tx_skbs[i] >= __PAGE_OFFSET) { - struct sk_buff *skb = np->tx_skbs[i]; - - tx = &np->tx->ring[requeue_idx++].req; - - tx->id = i; - gnttab_grant_foreign_access_ref( - np->grant_tx_ref[i], np->backend_id, - virt_to_mfn(np->tx_skbs[i]->data), - GNTMAP_readonly); - tx->gref = np->grant_tx_ref[i]; - tx->offset = (unsigned long)skb->data & ~PAGE_MASK; - tx->size = skb->len; - - np->stats.tx_bytes += skb->len; - np->stats.tx_packets++; - } + if ((unsigned long)np->tx_skbs[i] < __PAGE_OFFSET) + continue; + + skb = np->tx_skbs[i]; + + tx = &np->tx->ring[requeue_idx++].req; + + tx->id = i; + gnttab_grant_foreign_access_ref( + np->grant_tx_ref[i], np->backend_id, + virt_to_mfn(np->tx_skbs[i]->data), + GNTMAP_readonly); + tx->gref = np->grant_tx_ref[i]; + tx->offset = (unsigned long)skb->data & ~PAGE_MASK; + tx->size = skb->len; + tx->csum_blank = (skb->ip_summed == CHECKSUM_HW); + + np->stats.tx_bytes += skb->len; + np->stats.tx_packets++; } wmb(); np->tx->req_prod = requeue_idx; /* Rebuild the RX buffer freelist and the RX ring itself. */ for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) { - if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) { - gnttab_grant_foreign_transfer_ref( - np->grant_rx_ref[i], np->backend_id); - np->rx->ring[requeue_idx].req.gref = - np->grant_rx_ref[i]; - np->rx->ring[requeue_idx].req.id = i; - requeue_idx++; - } - } - + if ((unsigned long)np->rx_skbs[i] < __PAGE_OFFSET) + continue; + gnttab_grant_foreign_transfer_ref( + np->grant_rx_ref[i], np->backend_id); + np->rx->ring[requeue_idx].req.gref = + np->grant_rx_ref[i]; + np->rx->ring[requeue_idx].req.id = i; + requeue_idx++; + } wmb(); np->rx->req_prod = requeue_idx; - /* Step 3: All public and private state should now be sane. Get + /* + * Step 3: All public and private state should now be sane. Get * ready to start sending and receiving packets and give the driver * domain a kick because we've probably just requeued some * packets. */ np->backend_state = BEST_CONNECTED; wmb(); - notify_via_evtchn(np->evtchn); + notify_remote_via_irq(np->irq); network_tx_buf_gc(dev); if (np->user_state == UST_OPEN) @@ -798,7 +803,8 @@ #endif } -/* Move the vif into connected state. +/* + * Move the vif into connected state. * Sets the mac and event channel from the message. * Binds the irq to the event channel. */ @@ -809,7 +815,7 @@ memcpy(dev->dev_addr, np->mac, ETH_ALEN); np->evtchn = evtchn; network_connect(dev); - (void)bind_evtchn_to_irqhandler( + np->irq = bind_evtchn_to_irqhandler( np->evtchn, netif_int, SA_SAMPLE_RANDOM, dev->name, dev); (void)send_fake_arp(dev); show_device(np); @@ -1049,12 +1055,12 @@ gnttab_end_foreign_access(info->rx_ring_ref, 0); info->rx_ring_ref = GRANT_INVALID_REF; - unbind_evtchn_from_irqhandler(info->evtchn, info->netdev); - info->evtchn = 0; -} - -/* Stop network device and free tx/rx queues and irq. - */ + if (info->irq) + unbind_evtchn_from_irqhandler(info->irq, info->netdev); + info->evtchn = info->irq = 0; +} + +/* Stop network device and free tx/rx queues and irq. */ static void shutdown_device(struct net_private *np) { /* Stop old i/f to prevent errors whilst we rebuild the state. */ @@ -1148,17 +1154,6 @@ goto abort_transaction; } - info->backend = backend; - backend = NULL; - - info->watch.node = info->backend; - info->watch.callback = watch_for_status; - err = register_xenbus_watch(&info->watch); - if (err) { - message = "registering watch on backend"; - goto abort_transaction; - } - err = xenbus_transaction_end(0); if (err) { if (err == -EAGAIN) @@ -1167,12 +1162,19 @@ goto destroy_ring; } + info->watch.node = backend; + info->watch.callback = watch_for_status; + err = register_xenbus_watch(&info->watch); + if (err) { + message = "registering watch on backend"; + goto destroy_ring; + } + + info->backend = backend; + netif_state = NETIF_STATE_CONNECTED; - out: - if (backend) - kfree(backend); - return err; + return 0; abort_transaction: xenbus_transaction_end(1); @@ -1180,13 +1182,17 @@ xenbus_dev_error(dev, err, "%s", message); destroy_ring: shutdown_device(info); - goto out; -} - -/* Setup supplies the backend dir, virtual device. - - We place an event channel and shared frame entries. - We watch backend to wait if it's ok. */ + out: + if (backend) + kfree(backend); + return err; +} + +/* + * Setup supplies the backend dir, virtual device. + * We place an event channel and shared frame entries. + * We watch backend to wait if it's ok. + */ static int netfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { @@ -1241,24 +1247,17 @@ static int netfront_suspend(struct xenbus_device *dev) { struct netfront_info *info = dev->data; - unregister_xenbus_watch(&info->watch); kfree(info->backend); info->backend = NULL; - + return 0; +} + +static int netfront_resume(struct xenbus_device *dev) +{ + struct netfront_info *info = dev->data; netif_free(info); - - return 0; -} - -static int netfront_resume(struct xenbus_device *dev) -{ - struct net_private *np = dev->data; - int err; - - err = talk_to_backend(dev, np); - - return err; + return talk_to_backend(dev, info); } static struct xenbus_driver netfront = { diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/tpmback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Thu Sep 29 23:28:44 2005 @@ -35,7 +35,7 @@ /* Physical parameters of the comms window. */ unsigned int evtchn; - unsigned int remote_evtchn; + unsigned int irq; /* The shared rings and indexes. */ tpmif_tx_interface_t *tx; diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Thu Sep 29 23:28:44 2005 @@ -120,8 +120,6 @@ evtchn_op_t op = {.cmd = EVTCHNOP_bind_interdomain }; int err; - BUG_ON(tpmif->remote_evtchn); - if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL) return -ENOMEM; @@ -143,12 +141,11 @@ } tpmif->evtchn = op.u.bind_interdomain.port1; - tpmif->remote_evtchn = evtchn; tpmif->tx = (tpmif_tx_interface_t *)tpmif->tx_area->addr; - bind_evtchn_to_irqhandler(tpmif->evtchn, - tpmif_be_int, 0, "tpmif-backend", tpmif); + tpmif->irq = bind_evtchn_to_irqhandler( + tpmif->evtchn, tpmif_be_int, 0, "tpmif-backend", tpmif); tpmif->status = CONNECTED; tpmif->shmem_ref = shared_page; tpmif->active = 1; @@ -159,18 +156,10 @@ static void __tpmif_disconnect_complete(void *arg) { - evtchn_op_t op = {.cmd = EVTCHNOP_close }; tpmif_t *tpmif = (tpmif_t *) arg; - op.u.close.port = tpmif->evtchn; - op.u.close.dom = DOMID_SELF; - HYPERVISOR_event_channel_op(&op); - op.u.close.port = tpmif->remote_evtchn; - op.u.close.dom = tpmif->domid; - HYPERVISOR_event_channel_op(&op); - - if (tpmif->evtchn) - unbind_evtchn_from_irqhandler(tpmif->evtchn, tpmif); + if (tpmif->irq) + unbind_evtchn_from_irqhandler(tpmif->irq, tpmif); if (tpmif->tx) { unmap_frontend_page(tpmif); diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Thu Sep 29 23:28:44 2005 @@ -308,7 +308,7 @@ rc = offset; DPRINTK("Notifying frontend via event channel %d\n", tpmif->evtchn); - notify_via_evtchn(tpmif->evtchn); + notify_remote_via_irq(tpmif->irq); return rc; } diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Thu Sep 29 23:28:44 2005 @@ -88,6 +88,26 @@ return; } + err = tpmif_map(be->tpmif, ringref, evtchn); + if (err) { + xenbus_dev_error(be->dev, err, + "mapping shared-frame %lu port %u", + ringref, evtchn); + return; + } + + err = tpmif_vtpm_open(be->tpmif, + be->frontend_id, + be->instance); + if (err) { + xenbus_dev_error(be->dev, err, + "queueing vtpm open packet"); + /* + * Should close down this device and notify FE + * about closure. + */ + return; + } /* * Tell the front-end that we are ready to go - @@ -104,27 +124,6 @@ "ready", "%lu", ready); if (err) { xenbus_dev_error(be->dev, err, "writing 'ready'"); - goto abort; - } - - err = tpmif_map(be->tpmif, ringref, evtchn); - if (err) { - xenbus_dev_error(be->dev, err, - "mapping shared-frame %lu port %u", - ringref, evtchn); - goto abort; - } - - err = tpmif_vtpm_open(be->tpmif, - be->frontend_id, - be->instance); - if (err) { - xenbus_dev_error(be->dev, err, - "queueing vtpm open packet"); - /* - * Should close down this device and notify FE - * about closure. - */ goto abort; } diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Sep 29 23:28:44 2005 @@ -292,8 +292,10 @@ free_page((unsigned long)tp->tx); tp->tx = NULL; } - unbind_evtchn_from_irqhandler(tp->evtchn, NULL); - tp->evtchn = 0; + + if (tpm->irq) + unbind_evtchn_from_irqhandler(tp->irq, NULL); + tp->evtchn = tpm->irq = 0; } @@ -352,17 +354,6 @@ goto abort_transaction; } - info->backend = backend; - backend = NULL; - - info->watch.node = info->backend; - info->watch.callback = watch_for_status; - err = register_xenbus_watch(&info->watch); - if (err) { - message = "registering watch on backend"; - goto abort_transaction; - } - err = xenbus_transaction_end(0); if (err == -EAGAIN) goto again; @@ -371,10 +362,17 @@ goto destroy_tpmring; } -out: - if (backend) - kfree(backend); - return err; + info->watch.node = backend; + info->watch.callback = watch_for_status; + err = register_xenbus_watch(&info->watch); + if (err) { + message = "registering watch on backend"; + goto destroy_tpmring; + } + + info->backend = backend; + + return 0; abort_transaction: xenbus_transaction_end(1); @@ -382,7 +380,10 @@ xenbus_dev_error(dev, err, "%s", message); destroy_tpmring: destroy_tpmring(info, &my_private); - goto out; +out: + if (backend) + kfree(backend); + return err; } @@ -502,10 +503,12 @@ err = bind_evtchn_to_irqhandler( tp->evtchn, tpmif_int, SA_SAMPLE_RANDOM, "tpmif", tp); - if ( err != 0 ) { + if ( err <= 0 ) { WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err); return; } + + tp->irq = err; } static struct xenbus_device_id tpmfront_ids[] = { @@ -679,7 +682,7 @@ DPRINTK("Notifying backend via event channel %d\n", tp->evtchn); - notify_via_evtchn(tp->evtchn); + notify_remote_via_irq(tp->irq); spin_unlock_irq(&tp->tx_lock); return offset; diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Thu Sep 29 23:28:44 2005 @@ -5,7 +5,7 @@ struct tpm_private { tpmif_tx_interface_t *tx; - unsigned int evtchn; + unsigned int evtchn, irq; int connected; spinlock_t tx_lock; diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Thu Sep 29 23:28:44 2005 @@ -43,6 +43,8 @@ u8 flags; char buf[0]; } __attribute__((packed)); + +static int xenbus_irq; DECLARE_WAIT_QUEUE_HEAD(xb_waitq); @@ -145,7 +147,7 @@ data += avail; len -= avail; update_output_chunk(out, avail); - notify_via_evtchn(xen_start_info->store_evtchn); + notify_remote_via_irq(xenbus_irq); } while (len != 0); return 0; @@ -190,7 +192,7 @@ pr_debug("Finished read of %i bytes (%i to go)\n", avail, len); /* If it was full, tell them we've taken some. */ if (was_full) - notify_via_evtchn(xen_start_info->store_evtchn); + notify_remote_via_irq(xenbus_irq); } /* If we left something, wake watch thread to deal with it. */ @@ -205,31 +207,27 @@ { int err; + if (xenbus_irq) + unbind_evtchn_from_irqhandler(xenbus_irq, &xb_waitq); + xenbus_irq = 0; + if (!xen_start_info->store_evtchn) return 0; err = bind_evtchn_to_irqhandler( xen_start_info->store_evtchn, wake_waiting, 0, "xenbus", &xb_waitq); - if (err) { + if (err <= 0) { printk(KERN_ERR "XENBUS request irq failed %i\n", err); - unbind_evtchn_from_irq(xen_start_info->store_evtchn); return err; } + xenbus_irq = err; + /* FIXME zero out page -- domain builder should probably do this*/ memset(mfn_to_virt(xen_start_info->store_mfn), 0, PAGE_SIZE); return 0; -} - -void xb_suspend_comms(void) -{ - - if (!xen_start_info->store_evtchn) - return; - - unbind_evtchn_from_irqhandler(xen_start_info->store_evtchn, &xb_waitq); } /* diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h Thu Sep 29 23:28:44 2005 @@ -30,7 +30,6 @@ int xs_init(void); int xb_init_comms(void); -void xb_suspend_comms(void); /* Low level routines. */ int xb_write(const void *data, unsigned len); diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Sep 29 23:28:44 2005 @@ -607,7 +607,6 @@ down(&xenbus_lock); bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev); - xb_suspend_comms(); } void xenbus_resume(void) @@ -651,7 +650,6 @@ int err = 0; /* Initialize xenstore comms unless already done. */ - printk("store_evtchn = %i\n", xen_start_info->store_evtchn); err = xs_init(); if (err) { printk("XENBUS: Error initializing xenstore comms:" diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h Thu Sep 29 23:28:44 2005 @@ -80,11 +80,9 @@ * the usable vector space is 0x20-0xff (224 vectors) */ -#define NR_IPIS 8 - -#define RESCHEDULE_VECTOR 1 -#define INVALIDATE_TLB_VECTOR 2 -#define CALL_FUNCTION_VECTOR 3 +#define RESCHEDULE_VECTOR 0 +#define CALL_FUNCTION_VECTOR 1 +#define NR_IPIS 2 /* * The maximum number of vectors supported by i386 processors diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h Thu Sep 29 23:28:44 2005 @@ -78,11 +78,9 @@ * the usable vector space is 0x20-0xff (224 vectors) */ -#define NR_IPIS 8 - -#define RESCHEDULE_VECTOR 1 -#define INVALIDATE_TLB_VECTOR 2 -#define CALL_FUNCTION_VECTOR 3 +#define RESCHEDULE_VECTOR 0 +#define CALL_FUNCTION_VECTOR 1 +#define NR_IPIS 2 /* * The maximum number of vectors supported by i386 processors diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/include/asm-xen/balloon.h --- a/linux-2.6-xen-sparse/include/asm-xen/balloon.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/balloon.h Thu Sep 29 23:28:44 2005 @@ -58,3 +58,13 @@ #define balloon_unlock(__flags) spin_unlock_irqrestore(&balloon_lock, __flags) #endif /* __ASM_BALLOON_H__ */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/include/asm-xen/driver_util.h --- a/linux-2.6-xen-sparse/include/asm-xen/driver_util.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/driver_util.h Thu Sep 29 23:28:44 2005 @@ -14,3 +14,13 @@ extern void unlock_vm_area(struct vm_struct *area); #endif /* __ASM_XEN_DRIVER_UTIL_H__ */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/include/asm-xen/evtchn.h --- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Thu Sep 29 23:28:44 2005 @@ -4,7 +4,7 @@ * Communication via Xen event channels. * Also definitions for the device that demuxes notifications to userspace. * - * Copyright (c) 2004, K A Fraser + * Copyright (c) 2004-2005, K A Fraser * * This file may be distributed separately from the Linux kernel, or * incorporated into other software packages, subject to the following license: @@ -51,24 +51,36 @@ extern int bind_ipi_to_irq(int ipi); extern void unbind_ipi_from_irq(int ipi); -/* Dynamically bind an event-channel port to Linux IRQ space. */ +/* + * Dynamically bind an event-channel port to Linux IRQ space. + * BIND: Returns IRQ or error. + * UNBIND: Takes IRQ to unbind from; automatically closes the event channel. + */ extern int bind_evtchn_to_irq(unsigned int evtchn); -extern void unbind_evtchn_from_irq(unsigned int evtchn); +extern void unbind_evtchn_from_irq(unsigned int irq); /* * Dynamically bind an event-channel port to an IRQ-like callback handler. * On some platforms this may not be implemented via the Linux IRQ subsystem. - * You *cannot* trust the irq argument passed to the callback handler. + * The IRQ argument passed to the callback handler is the same as returned + * from the bind call. It may not correspond to a Linux IRQ number. + * BIND: Returns IRQ or error. + * UNBIND: Takes IRQ to unbind from; automatically closes the event channel. */ extern int bind_evtchn_to_irqhandler( - unsigned int evtchn, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char *devname, - void *dev_id); -extern void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id); + unsigned int evtchn, + irqreturn_t (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char *devname, + void *dev_id); +extern void unbind_evtchn_from_irqhandler(unsigned int irq, void *dev_id); -extern void irq_suspend(void); +/* + * Unlike notify_remote_via_evtchn(), this is safe to use across + * save/restore. Notifications on a broken connection are silently dropped. + */ +void notify_remote_via_irq(int irq); + extern void irq_resume(void); /* Entry point for notifications into Linux subsystems. */ @@ -79,42 +91,42 @@ static inline void mask_evtchn(int port) { - shared_info_t *s = HYPERVISOR_shared_info; - synch_set_bit(port, &s->evtchn_mask[0]); + shared_info_t *s = HYPERVISOR_shared_info; + synch_set_bit(port, &s->evtchn_mask[0]); } static inline void unmask_evtchn(int port) { - shared_info_t *s = HYPERVISOR_shared_info; - vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()]; + shared_info_t *s = HYPERVISOR_shared_info; + vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()]; - synch_clear_bit(port, &s->evtchn_mask[0]); + synch_clear_bit(port, &s->evtchn_mask[0]); - /* - * The following is basically the equivalent of 'hw_resend_irq'. Just like - * a real IO-APIC we 'lose the interrupt edge' if the channel is masked. - */ - if ( synch_test_bit (port, &s->evtchn_pending[0]) && - !synch_test_and_set_bit(port>>5, &vcpu_info->evtchn_pending_sel) ) - { - vcpu_info->evtchn_upcall_pending = 1; - if ( !vcpu_info->evtchn_upcall_mask ) - force_evtchn_callback(); - } + /* + * The following is basically the equivalent of 'hw_resend_irq'. Just + * like a real IO-APIC we 'lose the interrupt edge' if the channel is + * masked. + */ + if (synch_test_bit (port, &s->evtchn_pending[0]) && + !synch_test_and_set_bit(port>>5, &vcpu_info->evtchn_pending_sel)) { + vcpu_info->evtchn_upcall_pending = 1; + if (!vcpu_info->evtchn_upcall_mask) + force_evtchn_callback(); + } } static inline void clear_evtchn(int port) { - shared_info_t *s = HYPERVISOR_shared_info; - synch_clear_bit(port, &s->evtchn_pending[0]); + shared_info_t *s = HYPERVISOR_shared_info; + synch_clear_bit(port, &s->evtchn_pending[0]); } -static inline int notify_via_evtchn(int port) +static inline void notify_remote_via_evtchn(int port) { - evtchn_op_t op; - op.cmd = EVTCHNOP_send; - op.u.send.local_port = port; - return HYPERVISOR_event_channel_op(&op); + evtchn_op_t op; + op.cmd = EVTCHNOP_send; + op.u.send.local_port = port; + (void)HYPERVISOR_event_channel_op(&op); } /* @@ -133,3 +145,13 @@ #define EVTCHN_UNBIND _IO('E', 3) #endif /* __ASM_EVTCHN_H__ */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/include/asm-xen/foreign_page.h --- a/linux-2.6-xen-sparse/include/asm-xen/foreign_page.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/foreign_page.h Thu Sep 29 23:28:44 2005 @@ -28,3 +28,13 @@ ( (void (*) (struct page *)) (page)->mapping ) #endif /* __ASM_XEN_FOREIGN_PAGE_H__ */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/include/asm-xen/gnttab.h --- a/linux-2.6-xen-sparse/include/asm-xen/gnttab.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/gnttab.h Thu Sep 29 23:28:44 2005 @@ -6,7 +6,7 @@ * 2. Accessing others' memory reservations via grant references. * (i.e., mechanisms for both sender and recipient of grant references) * - * Copyright (c) 2004, K A Fraser + * Copyright (c) 2004-2005, K A Fraser * Copyright (c) 2005, Christopher Clark */ @@ -25,10 +25,10 @@ #endif struct gnttab_free_callback { - struct gnttab_free_callback *next; - void (*fn)(void *); - void *arg; - u16 count; + struct gnttab_free_callback *next; + void (*fn)(void *); + void *arg; + u16 count; }; int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, @@ -73,3 +73,13 @@ #endif #endif /* __ASM_GNTTAB_H__ */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/include/asm-xen/xen_proc.h --- a/linux-2.6-xen-sparse/include/asm-xen/xen_proc.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/xen_proc.h Thu Sep 29 23:28:44 2005 @@ -6,8 +6,18 @@ #include <linux/proc_fs.h> extern struct proc_dir_entry *create_xen_proc_entry( - const char *name, mode_t mode); + const char *name, mode_t mode); extern void remove_xen_proc_entry( - const char *name); + const char *name); #endif /* __ASM_XEN_PROC_H__ */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/include/asm-xen/xenbus.h --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Thu Sep 29 22:22:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Thu Sep 29 23:28:44 2005 @@ -139,3 +139,13 @@ #define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE) #endif /* _ASM_XEN_XENBUS_H */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/console/daemon/io.c --- a/tools/console/daemon/io.c Thu Sep 29 22:22:02 2005 +++ b/tools/console/daemon/io.c Thu Sep 29 23:28:44 2005 @@ -399,7 +399,7 @@ while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) { dom = lookup_domain(dominfo.domid); - if (dominfo.dying || dominfo.crashed || dominfo.shutdown) { + if (dominfo.dying) { if (dom) shutdown_domain(dom); } else { diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/debugger/gdb/README --- a/tools/debugger/gdb/README Thu Sep 29 22:22:02 2005 +++ b/tools/debugger/gdb/README Thu Sep 29 23:28:44 2005 @@ -20,10 +20,18 @@ To debug a running guest: 1. Use 'xm list' to discover its domain id ($domid). - 2. Run 'gdbserver-xen 127.0.0.1:9999 --attach $domid' - 3. Run 'gdb /path/to/vmlinux-syms-2.6.xx-xenU' + 2. Run 'gdbserver-xen 127.0.0.1:9999 --attach $domid'. + 3. Run 'gdb /path/to/vmlinux-syms-2.6.xx-xenU'. 4. From within the gdb client session: # directory /path/to/linux-2.6.xx-xenU [*] # target remote 127.0.0.1:9999 # bt # disass + +To debug a crashed guest: + 1. Add '(enable-dump yes)' to /etc/xen/xend-config.sxp before + starting xend. + 2. When the domain crashes, a core file is written to + '/var/xen/dump/<domain-name>.<domain-id>.core'. + 3. Run 'gdbserver-xen 127.0.0.1:9999 --file <core-file>'. + 4. Connect to the server as for a running guest. diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/firmware/vmxassist/gen.c --- a/tools/firmware/vmxassist/gen.c Thu Sep 29 22:22:02 2005 +++ b/tools/firmware/vmxassist/gen.c Thu Sep 29 23:28:44 2005 @@ -23,7 +23,7 @@ #include <vm86.h> int -main() +main(void) { printf("/* MACHINE GENERATED; DO NOT EDIT */\n"); printf("#define VMX_ASSIST_CTX_GS_SEL 0x%x\n", diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/firmware/vmxassist/head.S --- a/tools/firmware/vmxassist/head.S Thu Sep 29 22:22:02 2005 +++ b/tools/firmware/vmxassist/head.S Thu Sep 29 23:28:44 2005 @@ -110,6 +110,10 @@ _start: cli + /* save register parameters to C land */ + movl %edx, booting_cpu + movl %ebx, booting_vector + /* clear bss */ cld xorb %al, %al @@ -128,7 +132,6 @@ /* go ... */ call main jmp halt - /* * Something bad happened, print invoking %eip and loop forever diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/firmware/vmxassist/setup.c --- a/tools/firmware/vmxassist/setup.c Thu Sep 29 22:22:02 2005 +++ b/tools/firmware/vmxassist/setup.c Thu Sep 29 23:28:44 2005 @@ -29,6 +29,9 @@ #define min(a, b) ((a) > (b) ? (b) : (a)) +/* Which CPU are we booting, and what is the initial CS segment? */ +int booting_cpu, booting_vector; + unsigned long long gdt[] __attribute__ ((aligned(32))) = { 0x0000000000000000ULL, /* 0x00: reserved */ 0x0000890000000000ULL, /* 0x08: 32-bit TSS */ @@ -201,12 +204,17 @@ initialize_real_mode = 0; regs->eflags |= EFLAGS_VM | 0x02; regs->ves = regs->vds = regs->vfs = regs->vgs = 0xF000; - regs->cs = 0xF000; /* ROM BIOS POST entry point */ -#ifdef TEST - regs->eip = 0xFFE0; + if (booting_cpu == 0) { + regs->cs = 0xF000; /* ROM BIOS POST entry point */ +#ifdef TEST + regs->eip = 0xFFE0; #else - regs->eip = 0xFFF0; -#endif + regs->eip = 0xFFF0; +#endif + } else { + regs->cs = booting_vector << 8; /* AP entry point */ + regs->eip = 0; + } regs->uesp = 0; regs->uss = 0; printf("Starting emulated 16-bit real-mode: ip=%04x:%04x\n", @@ -215,8 +223,8 @@ mode = VM86_REAL; /* becomes previous mode */ set_mode(regs, VM86_REAL); - /* this should get us into 16-bit mode */ - return; + /* this should get us into 16-bit mode */ + return; } else { /* go from protected to real mode */ regs->eflags |= EFLAGS_VM; @@ -334,7 +342,12 @@ { unsigned long cr0; - printf("Start BIOS ...\n"); + if (booting_cpu == 0) + printf("Start BIOS ...\n"); + else + printf("Start AP %d from %08x ...\n", + booting_cpu, booting_vector << 12); + initialize_real_mode = 1; cr0 = get_cr0(); #ifndef TEST @@ -345,20 +358,28 @@ } int -main() -{ - banner(); +main(void) +{ + if (booting_cpu == 0) + banner(); + #ifdef TEST setup_paging(); #endif + setup_gdt(); setup_idt(); + #ifndef TEST - set_cr4(get_cr4() | CR4_VME); -#endif + set_cr4(get_cr4() | CR4_VME); +#endif + setup_ctx(); - setup_pic(); + + if (booting_cpu == 0) + setup_pic(); + start_bios(); + return 0; } - diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/firmware/vmxassist/vm86.c --- a/tools/firmware/vmxassist/vm86.c Thu Sep 29 22:22:02 2005 +++ b/tools/firmware/vmxassist/vm86.c Thu Sep 29 23:28:44 2005 @@ -470,10 +470,21 @@ unsigned long long entry; /* protected mode: use seg as index into gdt */ - if (sel == 0 || sel > oldctx.gdtr_limit) + if (sel > oldctx.gdtr_limit) return 0; + if (sel == 0) { + arbytes->fields.null_bit = 1; + return 1; + } + entry = ((unsigned long long *) oldctx.gdtr_base)[sel >> 3]; + + /* Check the P bit fisrt*/ + if (!((entry >> (15+32)) & 0x1) && sel != 0) { + return 0; + } + *base = (((entry >> (56-24)) & 0xFF000000) | ((entry >> (32-16)) & 0x00FF0000) | ((entry >> ( 16)) & 0x0000FFFF)); @@ -519,22 +530,42 @@ if (load_seg(regs->ves, &oldctx.es_base, &oldctx.es_limit, &oldctx.es_arbytes)) oldctx.es_sel = regs->ves; + else { + load_seg(0, &oldctx.es_base,&oldctx.es_limit, &oldctx.es_arbytes); + oldctx.es_sel = 0; + } if (load_seg(regs->uss, &oldctx.ss_base, &oldctx.ss_limit, &oldctx.ss_arbytes)) oldctx.ss_sel = regs->uss; + else { + load_seg(0, &oldctx.ss_base, &oldctx.ss_limit, &oldctx.ss_arbytes); + oldctx.ss_sel = 0; + } if (load_seg(regs->vds, &oldctx.ds_base, &oldctx.ds_limit, &oldctx.ds_arbytes)) oldctx.ds_sel = regs->vds; + else { + load_seg(0, &oldctx.ds_base, &oldctx.ds_limit, &oldctx.ds_arbytes); + oldctx.ds_sel = 0; + } if (load_seg(regs->vfs, &oldctx.fs_base, &oldctx.fs_limit, &oldctx.fs_arbytes)) oldctx.fs_sel = regs->vfs; + else { + load_seg(0, &oldctx.fs_base, &oldctx.fs_limit, &oldctx.fs_arbytes); + oldctx.fs_sel = 0; + } if (load_seg(regs->vgs, &oldctx.gs_base, &oldctx.gs_limit, &oldctx.gs_arbytes)) oldctx.gs_sel = regs->vgs; + else { + load_seg(0, &oldctx.gs_base, &oldctx.gs_limit, &oldctx.gs_arbytes); + oldctx.gs_sel = 0; + } /* initialize jump environment to warp back to protected mode */ regs->cs = CODE_SELECTOR; @@ -752,6 +783,9 @@ goto invalid; } break; + case 0x09: /* wbinvd */ + asm volatile ( "wbinvd" ); + return OPC_EMULATED; case 0x20: /* mov Rd, Cd (1h) */ case 0x22: if (!movcr(regs, prefix, opc)) diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/firmware/vmxassist/vmxloader.c --- a/tools/firmware/vmxassist/vmxloader.c Thu Sep 29 22:22:02 2005 +++ b/tools/firmware/vmxassist/vmxloader.c Thu Sep 29 23:28:44 2005 @@ -132,11 +132,12 @@ memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi)); } #endif - + puts("Loading VMXAssist ...\n"); memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist)); + puts("Go ...\n"); - ((void (*)())TEXTADDR)(); + asm volatile ( "jmp *%%eax" : : "a" (TEXTADDR), "d" (0) ); + return 0; } - diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/ioemu/vl.c --- a/tools/ioemu/vl.c Thu Sep 29 22:22:02 2005 +++ b/tools/ioemu/vl.c Thu Sep 29 23:28:44 2005 @@ -2385,7 +2385,8 @@ setup_mapping(int xc_handle, u32 dom, unsigned long toptab, unsigned long *mem_page_array, unsigned long *page_table_array, unsigned long v_start, unsigned long v_end) { l1_pgentry_t *vl1tab=NULL, *vl1e=NULL; - l2_pgentry_t *vl2tab[4], *vl2e=NULL, *vl2_table = NULL; + l2_pgentry_t *vl2tab[4] = {NULL, NULL, NULL, NULL}; + l2_pgentry_t *vl2e=NULL, *vl2_table = NULL; unsigned long l1tab; unsigned long ppt_alloc = 0; unsigned long count; diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/web/SrvBase.py --- a/tools/python/xen/web/SrvBase.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/web/SrvBase.py Thu Sep 29 23:28:44 2005 @@ -81,7 +81,14 @@ req.write("Operation not implemented: " + op) return '' else: - return op_method(op, req) + try: + return op_method(op, req) + except Exception, exn: + log.exception("Request %s failed.", op) + if req.useSxp(): + return ['xend.err', "Exception: " + str(exn)] + else: + return "<p>%s</p>" % str(exn) def print_path(self, req): """Print the path with hyperlinks. diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/web/http.py --- a/tools/python/xen/web/http.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/web/http.py Thu Sep 29 23:28:44 2005 @@ -22,6 +22,7 @@ from mimetools import Message from cStringIO import StringIO import math +import socket import time import cgi diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/PrettyPrint.py --- a/tools/python/xen/xend/PrettyPrint.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/PrettyPrint.py Thu Sep 29 23:28:44 2005 @@ -39,9 +39,9 @@ print '***PrettyItem>output>', self pass - def prettyprint(self, _, width): + def prettyprint(self, _): print '***PrettyItem>prettyprint>', self - return width + return self.width class PrettyString(PrettyItem): @@ -52,7 +52,7 @@ def output(self, out): out.write(self.value) - def prettyprint(self, line, _): + def prettyprint(self, line): line.output(self) def show(self, out): @@ -63,7 +63,7 @@ def output(self, out): out.write(' ' * self.width) - def prettyprint(self, line, _): + def prettyprint(self, line): line.output(self) def show(self, out): @@ -80,7 +80,7 @@ def output(self, out): out.write(' ' * self.width) - def prettyprint(self, line, _): + def prettyprint(self, line): if line.breaks(self.space): self.active = 1 line.newline(self.indent) @@ -97,7 +97,7 @@ block.newline() block.addtoline(self) - def prettyprint(self, line, _): + def prettyprint(self, line): line.newline(0) line.output(self) @@ -127,7 +127,7 @@ lastbreak.space = (width - lastwidth) self.width = width - def prettyprint(self, line, _): + def prettyprint(self, line): for x in self.content: x.prettyprint(line) @@ -168,7 +168,7 @@ def addtoline(self, x): self.lines[-1].write(x) - def prettyprint(self, line, _): + def prettyprint(self, line): self.indent = line.used line.block = self if not line.fits(self.width): @@ -252,7 +252,7 @@ self.block = self.block.parent def prettyprint(self, out=sys.stdout): - self.top.prettyprint(Line(out, self.width), self.width) + self.top.prettyprint(Line(out, self.width)) class SXPPrettyPrinter(PrettyPrinter): """An SXP prettyprinter. diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/XendCheckpoint.py Thu Sep 29 23:28:44 2005 @@ -10,8 +10,12 @@ import sxp from string import join from struct import pack, unpack, calcsize + from xen.util.xpopen import xPopen3 + import xen.lowlevel.xc + +import XendDomainInfo from xen.xend.xenstore.xsutil import IntroduceDomain from XendError import XendError @@ -74,7 +78,7 @@ if l.rstrip() == "suspend": log.info("suspending %d" % dominfo.domid) xd.domain_shutdown(dominfo.domid, reason='suspend') - dominfo.state_wait("suspended") + dominfo.state_wait(XendDomainInfo.STATE_VM_SUSPENDED) log.info("suspend %d done" % dominfo.domid) child.tochild.write("done\n") child.tochild.flush() diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/XendClient.py --- a/tools/python/xen/xend/XendClient.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/XendClient.py Thu Sep 29 23:28:44 2005 @@ -302,12 +302,6 @@ {'op' : 'devices', 'type' : type }) - def xend_domain_device(self, id, type, idx): - return self.xendPost(self.domainurl(id), - {'op' : 'device', - 'type' : type, - 'idx' : idx }) - def xend_domain_device_create(self, id, config): return self.xendPost(self.domainurl(id), {'op' : 'device_create', diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/XendDomain.py Thu Sep 29 23:28:44 2005 @@ -28,16 +28,11 @@ from xen.xend import sxp from xen.xend import XendRoot from xen.xend import XendCheckpoint -from xen.xend.XendDomainInfo import XendDomainInfo, shutdown_reason +from xen.xend.XendDomainInfo import XendDomainInfo from xen.xend import EventServer from xen.xend.XendError import XendError from xen.xend.XendLogging import log -from xen.xend import scheduler from xen.xend.server import relocate -from xen.xend.uuid import getUuid -from xen.xend.xenstore import XenNode, DBMap -from xen.xend.xenstore.xstransact import xstransact -from xen.xend.xenstore.xsutil import GetDomainPath xc = xen.lowlevel.xc.new() @@ -47,14 +42,7 @@ __all__ = [ "XendDomain" ] -SHUTDOWN_TIMEOUT = 30 -PRIV_DOMAIN = 0 - -def is_dead(dom): - return dom['crashed'] or dom['shutdown'] or ( - dom['dying'] and not(dom['running'] or dom['paused'] or - dom['blocked'])) - +PRIV_DOMAIN = 0 class XendDomainDict(dict): def get_by_name(self, name): @@ -77,11 +65,8 @@ # So we stuff the XendDomain instance (self) into xroot's components. xroot.add_component("xen.xend.XendDomain", self) self.domains = XendDomainDict() - self.domroot = "/domain" - self.vmroot = "/domain" - self.dbmap = DBMap(db=XenNode(self.vmroot)) self.watchReleaseDomain() - self.initial_refresh() + self.refresh() self.dom0_setup() def list(self): @@ -110,9 +95,7 @@ return map(lambda x: x.getName(), doms) def onReleaseDomain(self): - self.reap() self.refresh() - self.domain_restarts() def watchReleaseDomain(self): from xen.xend.xenstore.xswatch import xswatch @@ -141,43 +124,22 @@ dominfo = dominfo[0] return dominfo - def initial_refresh(self): - """Refresh initial domain info from db. - """ - doms = self.xen_domains() - self.dbmap.readDB() # XXX only needed for "xend" - for dom in doms.values(): - domid = dom['dom'] - dompath = GetDomainPath(domid) - if not dompath: - continue - vmpath = xstransact.Read(dompath, "vm") - if not vmpath: - continue - uuid = xstransact.Read(vmpath, "uuid") - if not uuid: - continue - log.info("recreating domain %d, uuid %s" % (domid, uuid)) - dompath = "/".join(dompath.split("/")[0:-1]) - try: - dominfo = XendDomainInfo.recreate(uuid, dompath, domid, dom) - except Exception, ex: - log.exception("Error recreating domain info: id=%d", domid) - continue - self._add_domain(dominfo) - self.reap() - self.refresh() - self.domain_restarts() + + def recreate_domain(self, xeninfo): + """Refresh initial domain info from db.""" + + dominfo = XendDomainInfo.recreate(xeninfo) + self._add_domain(dominfo) + return dominfo + def dom0_setup(self): dom0 = self.domain_lookup(PRIV_DOMAIN) if not dom0: - dom0 = self.dom0_unknown() - dom0.dom0_init_store() + dom0 = self.recreate_domain(self.xen_domain(PRIV_DOMAIN)) + dom0.dom0_init_store() dom0.dom0_enforce_vcpus() - def close(self): - pass def _add_domain(self, info, notify=True): """Add a domain entry to the tables. @@ -193,70 +155,45 @@ eserver.inject('xend.domain.create', [info.getName(), info.getDomid()]) - def _delete_domain(self, id, notify=True): + def _delete_domain(self, domid, notify=True): """Remove a domain from the tables. @param id: domain id @param notify: send a domain died event if true """ - info = self.domains.get(id) + info = self.domains.get(domid) if info: - del self.domains[id] + del self.domains[domid] info.cleanup() info.delete() if notify: eserver.inject('xend.domain.died', [info.getName(), info.getDomid()]) - # XXX this should not be needed - for domdb in self.dbmap.values(): - if not domdb.has_key("xend"): - continue - db = domdb.addChild("xend") - try: - domid = int(domdb["domid"].getData()) - except: - domid = None - if (domid is None) or (domid == id): - domdb.delete() - - def reap(self): - """Look for domains that have crashed or stopped. - Tidy them up. - """ - doms = self.xen_domains() - for d in doms.values(): - if not is_dead(d): - continue - domid = d['dom'] - dominfo = self.domains.get(domid) - if not dominfo or dominfo.is_terminated(): - continue - log.debug('domain died name=%s domid=%d', dominfo.getName(), domid) - if d['crashed'] and xroot.get_enable_dump(): - self.domain_dumpcore(domid) - if d['shutdown']: - reason = shutdown_reason(d['shutdown_reason']) - log.debug('shutdown name=%s id=%d reason=%s', - dominfo.getName(), domid, reason) - if reason == 'suspend': - dominfo.state_set("suspended") - continue - if reason in ['poweroff', 'reboot']: - self.domain_restart_schedule(domid, reason) - dominfo.destroy() + def refresh(self): """Refresh domain list from Xen. """ doms = self.xen_domains() - # Remove entries for domains that no longer exist. - # Update entries for existing domains. for d in self.domains.values(): info = doms.get(d.getDomid()) if info: d.update(info) - elif not d.restart_pending(): + else: self._delete_domain(d.getDomid()) + for d in doms: + if d not in self.domains: + try: + self.recreate_domain(doms[d]) + except: + log.exception( + "Failed to recreate information for domain %d. " + "Destroying it in the hope of recovery.", d) + try: + xc.domain_destroy(dom = d) + except: + log.exception('Destruction of %d failed.', d) + def update_domain(self, id): """Update information for a single domain. @@ -277,32 +214,8 @@ @param config: configuration @return: domain """ - dominfo = XendDomainInfo.create(self.dbmap.getPath(), config) + dominfo = XendDomainInfo.create(config) self._add_domain(dominfo) - return dominfo - - def domain_restart(self, dominfo): - """Restart a domain. - - @param dominfo: domain object - """ - log.info("Restarting domain: name=%s id=%s", dominfo.getName(), - dominfo.getDomid()) - eserver.inject("xend.domain.restart", - [dominfo.getName(), dominfo.getDomid(), "begin"]) - try: - dominfo.restart() - log.info('Restarted domain name=%s id=%s', dominfo.getName(), - dominfo.getDomid()) - eserver.inject("xend.domain.restart", - [dominfo.getName(), dominfo.getDomid(), - "success"]) - self.domain_unpause(dominfo.getDomid()) - except Exception, ex: - log.exception("Exception restarting domain: name=%s id=%s", - dominfo.getName(), dominfo.getDomid()) - eserver.inject("xend.domain.restart", - [dominfo.getName(), dominfo.getDomid(), "fail"]) return dominfo def domain_configure(self, config): @@ -318,13 +231,12 @@ nested = sxp.child_value(config, 'config') if nested: config = nested - return XendDomainInfo.restore(self.dbmap.getPath(), config) - - def domain_restore(self, src, progress=False): + return XendDomainInfo.restore(config) + + def domain_restore(self, src): """Restore a domain from file. @param src: source file - @param progress: output progress if true """ try: @@ -345,33 +257,7 @@ self.update_domain(id) return self.domains.get(id) - def dom0_unknown(self): - dom0 = PRIV_DOMAIN - uuid = None - info = self.xen_domain(dom0) - dompath = GetDomainPath(dom0) - if dompath: - vmpath = xstransact.Read(dompath, "vm") - if vmpath: - uuid = xstransact.Read(vmpath, "uuid") - if not uuid: - uuid = dompath.split("/")[-1] - dompath = "/".join(dompath.split("/")[0:-1]) - if not uuid: - uuid = getUuid() - dompath = self.domroot - log.info("Creating entry for unknown xend domain: id=%d uuid=%s", - dom0, uuid) - try: - dominfo = XendDomainInfo.recreate(uuid, dompath, dom0, info) - self._add_domain(dominfo) - return dominfo - except Exception, exn: - log.exception(exn) - raise XendError("Error recreating xend domain info: id=%d: %s" % - (dom0, str(exn))) - - + def domain_lookup(self, id): return self.domains.get(id) @@ -410,8 +296,9 @@ return xc.domain_pause(dom=dominfo.getDomid()) except Exception, ex: raise XendError(str(ex)) - - def domain_shutdown(self, id, reason='poweroff'): + + + def domain_shutdown(self, domid, reason='poweroff'): """Shutdown domain (nicely). - poweroff: restart according to exit code and restart mode - reboot: restart on exit @@ -422,89 +309,13 @@ @param id: domain id @param reason: shutdown type: poweroff, reboot, suspend, halt """ - dominfo = self.domain_lookup(id) - self.domain_restart_schedule(dominfo.getDomid(), reason, force=True) - eserver.inject('xend.domain.shutdown', [dominfo.getName(), - dominfo.getDomid(), reason]) - if reason == 'halt': - reason = 'poweroff' - val = dominfo.shutdown(reason) - if not reason in ['suspend']: - self.domain_shutdowns() - return val - - - def domain_sysrq(self, id, key): + self.callInfo(domid, XendDomainInfo.shutdown, reason) + + + def domain_sysrq(self, domid, key): """Send a SysRq to the specified domain.""" - return self.callInfo(id, XendDomainInfo.send_sysrq, key) - - - def domain_shutdowns(self): - """Process pending domain shutdowns. - Destroys domains whose shutdowns have timed out. - """ - timeout = SHUTDOWN_TIMEOUT + 1 - for dominfo in self.domains.values(): - if not dominfo.shutdown_pending: - # domain doesn't need shutdown - continue - id = dominfo.getDomid() - left = dominfo.shutdown_time_left(SHUTDOWN_TIMEOUT) - if left <= 0: - # Shutdown expired - destroy domain. - try: - log.info("Domain shutdown timeout expired: name=%s id=%s", - dominfo.getName(), id) - self.domain_destroy(id, reason= - dominfo.shutdown_pending['reason']) - except Exception: - pass - else: - # Shutdown still pending. - timeout = min(timeout, left) - if timeout <= SHUTDOWN_TIMEOUT: - # Pending shutdowns remain - reschedule. - scheduler.later(timeout, self.domain_shutdowns) - - def domain_restart_schedule(self, id, reason, force=False): - """Schedule a restart for a domain if it needs one. - - @param id: domain id - @param reason: shutdown reason - """ - log.debug('domain_restart_schedule> %d %s %d', id, reason, force) - dominfo = self.domain_lookup(id) - if not dominfo: - return - restart = (force and reason == 'reboot') or dominfo.restart_needed(reason) - if restart: - log.info('Scheduling restart for domain: name=%s id=%s', - dominfo.getName(), dominfo.getDomid()) - eserver.inject("xend.domain.restart", - [dominfo.getName(), dominfo.getDomid(), - "schedule"]) - dominfo.restarting() - else: - log.info('Cancelling restart for domain: name=%s id=%s', - dominfo.getName(), dominfo.getDomid()) - eserver.inject("xend.domain.restart", - [dominfo.getName(), dominfo.getDomid(), "cancel"]) - dominfo.restart_cancel() - - def domain_restarts(self): - """Execute any scheduled domain restarts for domains that have gone. - """ - doms = self.xen_domains() - for dominfo in self.domains.values(): - if not dominfo.restart_pending(): - continue - info = doms.get(dominfo.getDomid()) - if info: - # Don't execute restart for domains still running. - continue - # Remove it from the restarts. - log.info('restarting: %s' % dominfo.getName()) - self.domain_restart(dominfo) + return self.callInfo(domid, XendDomainInfo.send_sysrq, key) + def domain_destroy(self, domid, reason='halt'): """Terminate domain immediately. @@ -517,7 +328,6 @@ if domid == PRIV_DOMAIN: raise XendError("Cannot destroy privileged domain %i" % domid) - self.domain_restart_schedule(domid, reason, force=True) dominfo = self.domain_lookup(domid) if dominfo: val = dominfo.destroy() @@ -554,12 +364,11 @@ return None - def domain_save(self, id, dst, progress=False): + def domain_save(self, id, dst): """Start saving a domain to file. @param id: domain id @param dst: destination file - @param progress: output progress if true """ try: @@ -659,14 +468,6 @@ def domain_devtype_ls(self, domid, devtype): """Get list of device sxprs for the specified domain.""" return self.callInfo(domid, XendDomainInfo.getDeviceSxprs, devtype) - - - def domain_devtype_get(self, domid, devtype, devid): - """Get a device from a domain. - - @return: device object (or None) - """ - return self.callInfo(domid, XendDomainInfo.getDevice, devtype, devid) def domain_vif_limit_set(self, id, vif, credit, period): @@ -730,10 +531,16 @@ ## private: def callInfo(self, domid, fn, *args, **kwargs): - self.refresh() - dominfo = self.domains.get(domid) - if dominfo: - return fn(dominfo, *args, **kwargs) + try: + self.refresh() + dominfo = self.domains.get(domid) + if dominfo: + return fn(dominfo, *args, **kwargs) + except XendError: + raise + except Exception, exn: + log.exception("") + raise XendError(str(exn)) def instance(): diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/XendDomainInfo.py Thu Sep 29 23:28:44 2005 @@ -35,7 +35,9 @@ from xen.xend.server.channel import EventChannel from xen.xend import image +from xen.xend import scheduler from xen.xend import sxp +from xen.xend import XendRoot from xen.xend.XendBootloader import bootloader from xen.xend.XendLogging import log from xen.xend.XendError import XendError, VmError @@ -43,7 +45,7 @@ from xen.xend.uuid import getUuid from xen.xend.xenstore.xstransact import xstransact -from xen.xend.xenstore.xsutil import IntroduceDomain +from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain """Shutdown code for poweroff.""" DOMAIN_POWEROFF = 0 @@ -75,9 +77,6 @@ RESTART_NEVER, ] -STATE_RESTART_PENDING = 'pending' -STATE_RESTART_BOOTING = 'booting' - STATE_VM_OK = "ok" STATE_VM_TERMINATED = "terminated" STATE_VM_SUSPENDED = "suspended" @@ -92,7 +91,29 @@ SIF_TPM_BE_DOMAIN = (1<<7) +SHUTDOWN_TIMEOUT = 30 + + +DOMROOT = '/domain' +VMROOT = '/domain' + + xc = xen.lowlevel.xc.new() +xroot = XendRoot.instance() + + +## Configuration entries that we expect to round-trip -- be read from the +# config file or xc, written to save-files (i.e. through sxpr), and reused as +# config on restart or restore, all without munging. Some configuration +# entries are munged for backwards compatibility reasons, or because they +# don't come out of xc in the same form as they are specified in the config +# file, so those are handled separately. +ROUNDTRIPPING_CONFIG_ENTRIES = [ + ('name', str), + ('ssidref', int), + ('cpu_weight', float), + ('bootloader', str) + ] def domain_exists(name): @@ -133,47 +154,64 @@ MINIMUM_RESTART_TIME = 20 - def create(cls, dompath, config): + def create(cls, config): """Create a VM from a configuration. - @param dompath: The path to all domain information @param config configuration @raise: VmError for invalid configuration """ - log.debug("XendDomainInfo.create(%s, ...)", dompath) + log.debug("XendDomainInfo.create(...)") - vm = cls(getUuid(), dompath, cls.parseConfig(config)) + vm = cls(getUuid(), cls.parseConfig(config)) vm.construct() + vm.refreshShutdown() return vm create = classmethod(create) - def recreate(cls, uuid, dompath, domid, info): - """Create the VM object for an existing domain. - - @param dompath: The path to all domain information - @param info: domain info from xc - """ - - log.debug("XendDomainInfo.recreate(%s, %s, %s, %s)", uuid, dompath, - domid, info) - - return cls(uuid, dompath, info, domid, True) + def recreate(cls, xeninfo): + """Create the VM object for an existing domain.""" + + log.debug("XendDomainInfo.recreate(%s)", xeninfo) + + domid = xeninfo['dom'] + try: + dompath = GetDomainPath(domid) + if not dompath: + raise XendError( + 'No domain path in store for existing domain %d' % domid) + vmpath = xstransact.Read(dompath, "vm") + if not vmpath: + raise XendError( + 'No vm path in store for existing domain %d' % domid) + uuid = xstransact.Read(vmpath, "uuid") + if not uuid: + raise XendError( + 'No vm/uuid path in store for existing domain %d' % domid) + + except Exception, exn: + log.warn(str(exn)) + uuid = getUuid() + + log.info("Recreating domain %d, uuid %s", domid, uuid) + + vm = cls(uuid, xeninfo, domid, True) + vm.refreshShutdown(xeninfo) + return vm recreate = classmethod(recreate) - def restore(cls, dompath, config, uuid = None): + def restore(cls, config, uuid = None): """Create a domain and a VM object to do a restore. - @param dompath: The path to all domain information @param config: domain configuration @param uuid: uuid to use """ - log.debug("XendDomainInfo.restore(%s, %s, %s)", dompath, config, uuid) + log.debug("XendDomainInfo.restore(%s, %s)", config, uuid) if not uuid: uuid = getUuid() @@ -183,14 +221,12 @@ except TypeError, exn: raise VmError('Invalid ssidref in config: %s' % exn) - log.debug('restoring with ssidref = %d' % ssidref) - - vm = cls(uuid, dompath, cls.parseConfig(config), + vm = cls(uuid, cls.parseConfig(config), xc.domain_create(ssidref = ssidref)) - vm.clear_shutdown() vm.create_channel() vm.configure() vm.exportToDB() + vm.refreshShutdown() return vm restore = classmethod(restore) @@ -214,33 +250,28 @@ log.debug("parseConfig: config is %s" % str(config)) result = {} - imagecfg = "()" - - result['name'] = get_cfg('name') - result['ssidref'] = get_cfg('ssidref', int) + + for e in ROUNDTRIPPING_CONFIG_ENTRIES: + result[e[0]] = get_cfg(e[0], e[1]) + result['memory'] = get_cfg('memory', int) result['mem_kb'] = get_cfg('mem_kb', int) result['maxmem'] = get_cfg('maxmem', int) result['maxmem_kb'] = get_cfg('maxmem_kb', int) result['cpu'] = get_cfg('cpu', int) - result['cpu_weight'] = get_cfg('cpu_weight', float) - result['bootloader'] = get_cfg('bootloader') result['restart_mode'] = get_cfg('restart') + result['image'] = get_cfg('image') try: - imagecfg = get_cfg('image') - - if imagecfg: - result['image'] = imagecfg - result['vcpus'] = int(sxp.child_value(imagecfg, 'vcpus', - 1)) + if result['image']: + result['vcpus'] = int(sxp.child_value(result['image'], + 'vcpus', 1)) else: result['vcpus'] = 1 except TypeError, exn: raise VmError( 'Invalid configuration setting: vcpus = %s: %s' % - (sxp.child_value(imagecfg, 'vcpus', 1), - str(exn))) + (sxp.child_value(result['image'], 'vcpus', 1), str(exn))) result['backend'] = [] for c in sxp.children(config, 'backend'): @@ -258,12 +289,12 @@ parseConfig = classmethod(parseConfig) - def __init__(self, uuid, parentpath, info, domid = None, augment = False): + def __init__(self, uuid, info, domid = None, augment = False): self.uuid = uuid self.info = info - self.path = parentpath + "/" + uuid + self.path = DOMROOT + "/" + uuid if domid: self.domid = domid @@ -283,26 +314,26 @@ self.store_mfn = None self.console_channel = None self.console_mfn = None - - #todo: state: running, suspended + self.state = STATE_VM_OK self.state_updated = threading.Condition() - self.shutdown_pending = None - - self.restart_state = None - self.restart_time = None - self.restart_count = 0 - + self.writeVm("uuid", self.uuid) self.storeDom("vm", self.path) def augmentInfo(self): + """Augment self.info, as given to us through {@link #recreate}, with + values taken from the store. This recovers those values known to xend + but not to the hypervisor. + """ def useIfNeeded(name, val): if not self.infoIsSet(name) and val is not None: self.info[name] = val params = (("name", str), + ("restart-mode", str), + ("image", str), ("start-time", float)) from_store = self.gatherVm(*params) @@ -322,12 +353,17 @@ defaultInfo('name', lambda: "Domain-%d" % self.domid) defaultInfo('ssidref', lambda: 0) defaultInfo('restart_mode', lambda: RESTART_ONREBOOT) + defaultInfo('cpu', lambda: None) defaultInfo('cpu_weight', lambda: 1.0) defaultInfo('bootloader', lambda: None) defaultInfo('backend', lambda: []) defaultInfo('device', lambda: []) + defaultInfo('image', lambda: None) self.check_name(self.info['name']) + + if isinstance(self.info['image'], str): + self.info['image'] = sxp.from_string(self.info['image']) # Internally, we keep only maxmem_KiB, and not maxmem or maxmem_kb # (which come from outside, and are in MiB and KiB respectively). @@ -451,17 +487,16 @@ 'domid': str(self.domid), 'uuid': self.uuid, - 'restart_time': str(self.restart_time), - - 'xend/state': self.state, - 'xend/restart_count': str(self.restart_count), 'xend/restart_mode': str(self.info['restart_mode']), 'memory/target': str(self.info['memory_KiB']) } for (k, v) in self.info.items(): - to_store[k] = str(v) + if v: + to_store[k] = str(v) + + to_store['image'] = sxp.to_string(self.info['image']) log.debug("Storing %s" % str(to_store)) @@ -511,6 +546,88 @@ def getBackendFlags(self): return reduce(lambda x, y: x | backendFlags[y], self.info['backend'], 0) + + + def refreshShutdown(self, xeninfo = None): + if xeninfo is None: + xeninfo = dom_get(self.domid) + if xeninfo is None: + # The domain no longer exists. This will occur if we have + # scheduled a timer to check for shutdown timeouts and the + # shutdown succeeded. + return + + if xeninfo['dying']: + # Dying means that a domain has been destroyed, but has not yet + # been cleaned up by Xen. This could persist indefinitely if, + # for example, another domain has some of its pages mapped. + # We might like to diagnose this problem in the future, but for + # now all we can sensibly do is ignore it. + pass + + elif xeninfo['crashed']: + log.warn('Domain has crashed: name=%s id=%d.', + self.info['name'], self.domid) + + if xroot.get_enable_dump(): + self.dumpCore() + + self.maybeRestart('crashed') + + elif xeninfo['shutdown']: + reason = shutdown_reason(xeninfo['shutdown_reason']) + + log.info('Domain has shutdown: name=%s id=%d reason=%s.', + self.info['name'], self.domid, reason) + + self.clearRestart() + + if reason == 'suspend': + self.state_set(STATE_VM_SUSPENDED) + # Don't destroy the domain. XendCheckpoint will do this once + # it has finished. + elif reason in ['poweroff', 'reboot']: + self.maybeRestart(reason) + else: + self.destroy() + + else: + # Domain is alive. If we are shutting it down, then check + # the timeout on that, and destroy it if necessary. + + sst = self.readVm('xend/shutdown_start_time') + if sst: + sst = float(sst) + timeout = SHUTDOWN_TIMEOUT - time.time() + sst + if timeout < 0: + log.info( + "Domain shutdown timeout expired: name=%s id=%s", + self.info['name'], self.domid) + self.destroy() + else: + log.debug( + "Scheduling refreshShutdown on domain %d in %ds.", + self.domid, timeout) + scheduler.later(timeout, self.refreshShutdown) + + + def shutdown(self, reason): + if not reason in shutdown_reasons.values(): + raise XendError('invalid reason:' + reason) + self.storeVm("control/shutdown", reason) + if not reason == 'suspend': + self.storeVm('xend/shutdown_start_time', time.time()) + + + def clearRestart(self): + self.removeVm("xend/shutdown_start_time") + + + def maybeRestart(self, reason): + if self.restart_needed(reason): + self.restart() + else: + self.destroy() def dumpCore(self): @@ -526,18 +643,32 @@ self.domid, self.info['name'], str(exn)) + def closeChannel(self, channel, entry): + """Close the given channel, if set, and remove the given entry in the + store. Nothrow guarantee.""" + + try: + try: + if channel: + channel.close() + finally: + self.removeDom(entry) + except Exception, exn: + log.exception(exn) + + def closeStoreChannel(self): """Close the store channel, if any. Nothrow guarantee.""" - - try: - if self.store_channel: - try: - self.store_channel.close() - self.removeDom("store/port") - finally: - self.store_channel = None - except Exception, exn: - log.exception(exn) + + self.closeChannel(self.store_channel, "store/port") + self.store_channel = None + + + def closeConsoleChannel(self): + """Close the console channel, if any. Nothrow guarantee.""" + + self.closeChannel(self.console_channel, "console/port") + self.console_channel = None def setConsoleRef(self, ref): @@ -566,10 +697,13 @@ self.info.update(info) self.validateInfo() + self.refreshShutdown(info) log.debug("XendDomainInfo.update done on domain %d: %s", self.domid, self.info) + + ## private: def state_set(self, state): self.state_updated.acquire() @@ -577,13 +711,16 @@ self.state = state self.state_updated.notifyAll() self.state_updated.release() - self.exportToDB() + + + ## public: def state_wait(self, state): self.state_updated.acquire() while self.state != state: self.state_updated.wait() self.state_updated.release() + def __str__(self): s = "<domain" @@ -597,6 +734,25 @@ __repr__ = __str__ + def createDevice(self, deviceClass, devconfig): + return self.getDeviceController(deviceClass).createDevice(devconfig) + + + def configureDevice(self, deviceClass, devid, devconfig): + return self.getDeviceController(deviceClass).configureDevice( + devid, devconfig) + + + def destroyDevice(self, deviceClass, devid): + return self.getDeviceController(deviceClass).destroyDevice(devid) + + + def getDeviceSxprs(self, deviceClass): + return self.getDeviceController(deviceClass).sxprs() + + + ## private: + def getDeviceController(self, name): if name not in controllerClasses: raise XendError("unknown device type: " + str(name)) @@ -604,62 +760,53 @@ return controllerClasses[name](self) - def createDevice(self, deviceClass, devconfig): - return self.getDeviceController(deviceClass).createDevice(devconfig) - - - def configureDevice(self, deviceClass, devid, devconfig): - return self.getDeviceController(deviceClass).configureDevice( - devid, devconfig) - - - def destroyDevice(self, deviceClass, devid): - return self.getDeviceController(deviceClass).destroyDevice(devid) - + ## public: def sxpr(self): sxpr = ['domain', - ['domid', self.domid], - ['name', self.info['name']], - ['memory', self.info['memory_KiB'] / 1024], - ['ssidref', self.info['ssidref']]] - if self.uuid: - sxpr.append(['uuid', self.uuid]) - if self.info: - sxpr.append(['maxmem', self.info['maxmem_KiB'] / 1024]) - - if self.infoIsSet('device'): - for (_, c) in self.info['device']: - sxpr.append(['device', c]) - - def stateChar(name): - if name in self.info: - if self.info[name]: - return name[0] - else: - return '-' + ['domid', self.domid], + ['uuid', self.uuid], + ['memory', self.info['memory_KiB'] / 1024]] + + for e in ROUNDTRIPPING_CONFIG_ENTRIES: + if self.infoIsSet(e[0]): + sxpr.append([e[0], self.info[e[0]]]) + + sxpr.append(['maxmem', self.info['maxmem_KiB'] / 1024]) + + if self.infoIsSet('image'): + sxpr.append(['image', self.info['image']]) + + if self.infoIsSet('device'): + for (_, c) in self.info['device']: + sxpr.append(['device', c]) + + def stateChar(name): + if name in self.info: + if self.info[name]: + return name[0] else: - return '?' - - state = reduce( - lambda x, y: x + y, - map(stateChar, - ['running', 'blocked', 'paused', 'shutdown', 'crashed'])) - - sxpr.append(['state', state]) - if self.infoIsSet('shutdown'): - reason = shutdown_reason(self.info['shutdown_reason']) - sxpr.append(['shutdown_reason', reason]) - if self.infoIsSet('cpu_time'): - sxpr.append(['cpu_time', self.info['cpu_time']/1e9]) - sxpr.append(['vcpus', self.info['vcpus']]) - sxpr.append(['cpumap', self.info['cpumap']]) - if self.infoIsSet('vcpu_to_cpu'): - sxpr.append(['cpu', self.info['vcpu_to_cpu'][0]]) - # build a string, using '|' to separate items, show only up - # to number of vcpus in domain, and trim the trailing '|' - sxpr.append(['vcpu_to_cpu', ''.join(map(lambda x: str(x)+'|', - self.info['vcpu_to_cpu'][0:self.info['vcpus']]))[:-1]]) + return '-' + else: + return '?' + + state = reduce( + lambda x, y: x + y, + map(stateChar, + ['running', 'blocked', 'paused', 'shutdown', 'crashed', + 'dying'])) + + sxpr.append(['state', state]) + if self.infoIsSet('shutdown'): + reason = shutdown_reason(self.info['shutdown_reason']) + sxpr.append(['shutdown_reason', reason]) + if self.infoIsSet('cpu_time'): + sxpr.append(['cpu_time', self.info['cpu_time']/1e9]) + sxpr.append(['vcpus', self.info['vcpus']]) + sxpr.append(['cpumap', self.info['cpumap']]) + if self.infoIsSet('vcpu_to_cpu'): + sxpr.append(['cpu', self.info['vcpu_to_cpu'][0]]) + sxpr.append(['vcpu_to_cpu', self.prettyVCpuMap()]) if self.infoIsSet('start_time'): up_time = time.time() - self.info['start_time'] @@ -674,13 +821,16 @@ sxpr.append(['console_channel', self.console_channel.sxpr()]) if self.console_mfn: sxpr.append(['console_mfn', self.console_mfn]) - if self.restart_count: - sxpr.append(['restart_count', self.restart_count]) - if self.restart_state: - sxpr.append(['restart_state', self.restart_state]) - if self.restart_time: - sxpr.append(['restart_time', str(self.restart_time)]) + return sxpr + + + ## private: + + def prettyVCpuMap(self): + return '|'.join(map(str, + self.info['vcpu_to_cpu'][0:self.info['vcpus']])) + def check_name(self, name): """Check if a vm name is valid. Valid names contain alphabetic characters, @@ -719,11 +869,19 @@ @param config: configuration @raise: VmError on error """ - # todo - add support for scheduling params? + + log.debug('XendDomainInfo.construct: %s %s', + str(self.domid), + str(self.info['ssidref'])) + + self.domid = xc.domain_create(dom = 0, ssidref = self.info['ssidref']) + + if self.domid <= 0: + raise VmError('Creating domain failed: name=%s' % + self.info['name']) + try: self.initDomain() - - # Create domain devices. self.construct_image() self.configure() self.exportToDB() @@ -737,30 +895,23 @@ def initDomain(self): - log.debug('XendDomainInfo.initDomain: %s %s %s %s)', + log.debug('XendDomainInfo.initDomain: %s %s %s', str(self.domid), str(self.info['memory_KiB']), - str(self.info['ssidref']), str(self.info['cpu_weight'])) - self.domid = xc.domain_create(dom = self.domid or 0, - ssidref = self.info['ssidref']) - - if 'image' not in self.info: + if not self.infoIsSet('image'): raise VmError('Missing image in configuration') self.image = image.create(self, self.info['image'], self.info['device']) - if self.domid <= 0: - raise VmError('Creating domain failed: name=%s' % - self.info['name']) - if self.info['bootloader']: self.image.handleBootloading() xc.domain_setcpuweight(self.domid, self.info['cpu_weight']) + # XXX Merge with configure_maxmem? m = self.image.getDomainMemory(self.info['memory_KiB']) xc.domain_setmaxmem(self.domid, m) xc.domain_memory_increase_reservation(self.domid, m, 0, 0) @@ -794,6 +945,8 @@ self.configure_vcpus(self.info['vcpus']) + ## public: + def delete(self): """Delete the vm's db. """ @@ -803,48 +956,46 @@ log.warning("error in domain db delete: %s", ex) - def destroy_domain(self): - """Destroy the vm's domain. - The domain will not finally go away unless all vm - devices have been released. - """ - if self.domid is None: - return - try: - xc.domain_destroy(dom=self.domid) - except Exception, err: - log.exception("Domain destroy failed: %s", self.info['name']) - def cleanup(self): - """Cleanup vm resources: release devices. - """ - self.state = STATE_VM_TERMINATED + """Cleanup vm resources: release devices. Nothrow guarantee.""" + + self.state_set(STATE_VM_TERMINATED) self.release_devices() self.closeStoreChannel() - if self.console_channel: - # notify processes using this console? - try: - self.console_channel.close() - self.console_channel = None - except: - pass + self.closeConsoleChannel() + if self.image: try: self.image.destroy() - self.image = None except: - pass + log.exception( + "XendDomainInfo.cleanup: image.destroy() failed.") + self.image = None + def destroy(self): - """Cleanup vm and destroy domain. - """ - - log.debug("XendDomainInfo.destroy") - - self.destroy_domain() + """Cleanup vm and destroy domain. Nothrow guarantee.""" + + log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid)) + self.cleanup() - self.exportToDB() - return 0 + + try: + self.removeVm() + except Exception: + log.exception("Removing VM path failed.") + + try: + self.removeDom() + except Exception: + log.exception("Removing domain path failed.") + + try: + if self.domid is not None: + xc.domain_destroy(dom=self.domid) + except Exception: + log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.") + def is_terminated(self): """Check if a domain has been terminated. @@ -852,8 +1003,7 @@ return self.state == STATE_VM_TERMINATED def release_devices(self): - """Release all vm devices. - """ + """Release all vm devices. Nothrow guarantee.""" while True: t = xstransact("%s/device" % self.path) @@ -865,8 +1015,8 @@ # Log and swallow any exceptions in removal -- # there's nothing more we can do. log.exception( - "Device release failed: %s; %s; %s; %s" % - (self.info['name'], n, d, str(ex))) + "Device release failed: %s; %s; %s", + self.info['name'], n, d) if t.commit(): break @@ -902,8 +1052,7 @@ @raise: VmError for invalid devices """ - if not self.rebooting(): - self.create_configured_devices() + self.create_configured_devices() if self.image: self.image.createDeviceModel() @@ -942,23 +1091,6 @@ return reason == 'reboot' return False - def restart_cancel(self): - """Cancel a vm restart. - """ - self.restart_state = None - - def restarting(self): - """Put the vm into restart mode. - """ - self.restart_state = STATE_RESTART_PENDING - - def restart_pending(self): - """Test if the vm has a pending restart. - """ - return self.restart_state == STATE_RESTART_PENDING - - def rebooting(self): - return self.restart_state == STATE_RESTART_BOOTING def restart_check(self): """Check if domain restart is OK. @@ -976,23 +1108,37 @@ self.restart_time = tnow self.restart_count += 1 + def restart(self): - """Restart the domain after it has exited. - Reuses the domain id - - """ + """Restart the domain after it has exited. """ + + # self.restart_check() + self.cleanup() + + config = self.sxpr() + + if self.readVm('xend/restart_in_progress'): + log.error('Xend failed during restart of domain %d. ' + 'Refusing to restart to avoid loops.', + self.domid) + self.destroy() + return + + self.writeVm('xend/restart_in_progress', 'True') + try: - self.clear_shutdown() - self.state = STATE_VM_OK - self.shutdown_pending = None - self.restart_check() - self.exportToDB() - self.restart_state = STATE_RESTART_BOOTING - self.configure_bootloader() - self.construct() - self.exportToDB() + self.destroy() + try: + xd = get_component('xen.xend.XendDomain') + xd.domain_unpause(xd.domain_create(config).getDomid()) + except Exception, exn: + log.exception('Failed to restart domain %d.', self.domid) finally: - self.restart_state = None + self.removeVm('xend/restart_in_progress') + + # self.configure_bootloader() + # self.exportToDB() + def configure_bootloader(self): if not self.info['bootloader']: @@ -1006,7 +1152,8 @@ if dev: disk = sxp.child_value(dev, "uname") fn = blkdev_uname_to_file(disk) - blcfg = bootloader(self.info['bootloader'], fn, 1, self.info['vcpus']) + blcfg = bootloader(self.info['bootloader'], fn, 1, + self.info['vcpus']) if blcfg is None: msg = "Had a bootloader specified, but can't find disk" log.error(msg) @@ -1023,7 +1170,9 @@ def configure_maxmem(self): - xc.domain_setmaxmem(self.domid, maxmem_kb = self.info['maxmem_KiB']) + if self.image: + m = self.image.getDomainMemory(self.info['memory_KiB']) + xc.domain_setmaxmem(self.domid, maxmem_kb = m) def vcpu_hotplug(self, vcpu, state): @@ -1038,23 +1187,8 @@ availability = "online" self.storeVm("cpu/%d/availability" % vcpu, availability) - def shutdown(self, reason): - if not reason in shutdown_reasons.values(): - raise XendError('invalid reason:' + reason) - self.storeVm("control/shutdown", reason) - if not reason in ['suspend']: - self.shutdown_pending = {'start':time.time(), 'reason':reason} - - def clear_shutdown(self): - self.removeVm("control/shutdown") - def send_sysrq(self, key=0): self.storeVm("control/sysrq", '%c' % key) - - def shutdown_time_left(self, timeout): - if not self.shutdown_pending: - return 0 - return timeout - (time.time() - self.shutdown_pending['start']) def dom0_init_store(self): if not self.store_channel: @@ -1078,8 +1212,6 @@ def dom0_enforce_vcpus(self): dom = 0 # get max number of vcpus to use for dom0 from config - from xen.xend import XendRoot - xroot = XendRoot.instance() target = int(xroot.get_dom0_vcpus()) log.debug("number of vcpus to use is %d" % (target)) diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/server/DevController.py --- a/tools/python/xen/xend/server/DevController.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/server/DevController.py Thu Sep 29 23:28:44 2005 @@ -81,6 +81,13 @@ xstransact.Remove(backpath) + def sxprs(self): + """@return an s-expression describing all the devices of this + controller's device-class. + """ + return xstransact.ListRecursive(self.frontendRoot()) + + def sxpr(self, devid): """@return an s-expression describing the specified device. """ @@ -126,8 +133,8 @@ compulsory to use it; subclasses may prefer to allocate IDs based upon the device configuration instead. """ + path = self.frontendMiscPath() while True: - path = self.frontendMiscPath() t = xstransact(path) try: result = t.read("nextDeviceID") @@ -196,8 +203,11 @@ def frontendPath(self, devid): - return "%s/device/%s/%d" % (self.vm.getPath(), self.deviceClass, - devid) + return "%s/%d" % (self.frontendRoot(), devid) + + + def frontendRoot(self): + return "%s/device/%s" % (self.vm.getPath(), self.deviceClass) def frontendMiscPath(self): diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/server/SrvDaemon.py --- a/tools/python/xen/xend/server/SrvDaemon.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/server/SrvDaemon.py Thu Sep 29 23:28:44 2005 @@ -9,25 +9,23 @@ import sys import threading import linecache -import socket import pwd import re -import StringIO import traceback -import time -import glob - -from xen.xend import sxp -from xen.xend import PrettyPrint -from xen.xend import EventServer; eserver = EventServer.instance() -from xen.xend.XendError import XendError + +from xen.xend import EventServer from xen.xend.server import SrvServer from xen.xend.XendLogging import log -from xen.xend import XendRoot; xroot = XendRoot.instance() +from xen.xend import XendRoot import event import relocate from params import * + + +eserver = EventServer.instance() +xroot = XendRoot.instance() + class Daemon: """The xend daemon. @@ -233,7 +231,7 @@ except: pass - def print_trace(self, str): + def print_trace(self, string): for i in range(self.traceindent): ch = " " if (i % 5): @@ -241,7 +239,7 @@ else: ch = '|' self.tracefile.write(ch) - self.tracefile.write(str) + self.tracefile.write(string) def trace(self, frame, event, arg): if not self.traceon: @@ -289,7 +287,7 @@ try: os.setuid(pwd.getpwnam(XEND_USER)[2]) return 0 - except KeyError, error: + except KeyError: print >>sys.stderr, "Error: no such user '%s'" % XEND_USER return 1 diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/server/SrvDmesg.py --- a/tools/python/xen/xend/server/SrvDmesg.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/server/SrvDmesg.py Thu Sep 29 23:28:44 2005 @@ -13,14 +13,14 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ -import os -from xen.xend import sxp from xen.xend import XendDmesg from xen.web.SrvDir import SrvDir + class SrvDmesg(SrvDir): """Xen Dmesg output. @@ -47,6 +47,6 @@ def info(self): return self.xd.info() - def op_clear(self, op, req): + def op_clear(self, _1, _2): self.xd.clear() return 0 diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/server/SrvDomain.py --- a/tools/python/xen/xend/server/SrvDomain.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/server/SrvDomain.py Thu Sep 29 23:28:44 2005 @@ -150,17 +150,6 @@ val = fn(req.args, {'dom': self.dom.domid}) return val - def op_device(self, op, req): - fn = FormFn(self.xd.domain_devtype_get, - [['dom', 'int'], - ['type', 'str'], - ['idx', 'int']]) - val = fn(req.args, {'dom': self.dom.domid}) - if val: - return val.sxpr() - else: - raise XendError("invalid device") - def op_device_create(self, op, req): fn = FormFn(self.xd.domain_device_create, [['dom', 'int'], @@ -172,7 +161,7 @@ fn = FormFn(self.xd.domain_device_refresh, [['dom', 'int'], ['type', 'str'], - ['idx', 'str']]) + ['idx', 'int']]) val = fn(req.args, {'dom': self.dom.domid}) return val @@ -180,7 +169,7 @@ fn = FormFn(self.xd.domain_device_destroy, [['dom', 'int'], ['type', 'str'], - ['idx', 'str']]) + ['idx', 'int']]) val = fn(req.args, {'dom': self.dom.domid}) return val @@ -188,7 +177,7 @@ fn = FormFn(self.xd.domain_device_configure, [['dom', 'int'], ['config', 'sxpr'], - ['idx', 'str']]) + ['idx', 'int']]) val = fn(req.args, {'dom': self.dom.domid}) return val @@ -230,10 +219,6 @@ self.print_path(req) #self.ls() req.write('<p>%s</p>' % self.dom) - if self.dom.config: - req.write("<code><pre>") - PrettyPrint.prettyprint(self.dom.config, out=req) - req.write("</pre></code>") self.form(req) req.write('</body></html>') return '' diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/server/SrvDomainDir.py --- a/tools/python/xen/xend/server/SrvDomainDir.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/server/SrvDomainDir.py Thu Sep 29 23:28:44 2005 @@ -38,19 +38,17 @@ self.xd = XendDomain.instance() def domain(self, x): - val = None dom = self.xd.domain_lookup_by_name(x) if not dom: raise XendError('No such domain ' + str(x)) - val = SrvDomain(dom) - return val + return SrvDomain(dom) def get(self, x): v = SrvDir.get(self, x) if v is not None: return v - v = self.domain(x) - return v + else: + return self.domain(x) def op_create(self, op, req): """Create a domain. @@ -152,11 +150,11 @@ domains = self.xd.list_sorted() req.write('<ul>') for d in domains: - req.write('<li><a href="%s%s"> Domain %s</a>' - % (url, d.getName(), d.getName())) - req.write('id=%s' % d.getDomain()) - req.write('memory=%d'% d.getMemoryTarget()) - req.write('ssidref=%d'% d.getSsidref()) + req.write( + '<li><a href="%s%s">Domain %s</a>: id = %s, memory = %d, ' + 'ssidref = %d.' + % (url, d.getName(), d.getName(), d.getDomid(), + d.getMemoryTarget(), d.getSsidref())) req.write('</li>') req.write('</ul>') diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/server/SrvNode.py --- a/tools/python/xen/xend/server/SrvNode.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/server/SrvNode.py Thu Sep 29 23:28:44 2005 @@ -62,7 +62,7 @@ for d in self.info(): req.write('<li> %10s: %s' % (d[0], str(d[1]))) req.write('<li><a href="%sdmesg">Xen dmesg output</a>' % url) - req.write('<li><a href="%slog>Xend log</a>' % url) + req.write('<li><a href="%slog">Xend log</a>' % url) req.write('</ul>') req.write('</body></html>') diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xend/xenstore/xstransact.py --- a/tools/python/xen/xend/xenstore/xstransact.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xend/xenstore/xstransact.py Thu Sep 29 23:28:44 2005 @@ -1,4 +1,5 @@ # Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx> +# Copyright (C) 2005 XenSource Ltd # This file is subject to the terms and conditions of the GNU General # Public License. See the file "COPYING" in the main directory of @@ -8,6 +9,7 @@ import threading from xen.lowlevel import xs from xen.xend.xenstore.xsutil import xshandle + class xstransact: @@ -40,8 +42,15 @@ '%s, while reading %s' % (ex.args[1], path)) def read(self, *args): - if len(args) == 0: - raise TypeError + """If no arguments are given, return the value at this transaction's + path. If one argument is given, treat that argument as a subpath to + this transaction's path, and return the value at that path. + Otherwise, treat each argument as a subpath to this transaction's + path, and return a list composed of the values at each of those + instead. + """ + if len(args) == 0: + return xshandle().read(self.path) if len(args) == 1: return self._read(args[0]) ret = [] @@ -105,12 +114,49 @@ return [] def list(self, *args): - if len(args) == 0: - raise TypeError + """If no arguments are given, list this transaction's path, returning + the entries therein, or the empty list if no entries are found. + Otherwise, treat each argument as a subpath to this transaction's + path, and return the cumulative listing of each of those instead. + """ + if len(args) == 0: + ret = xshandle().ls(self.path) + if ret is None: + return [] + else: + return ret + else: + ret = [] + for key in args: + ret.extend(self._list(key)) + return ret + + + def list_recursive_(self, subdir, keys): ret = [] - for key in args: - ret.extend(self._list(key)) + for key in keys: + new_subdir = subdir + "/" + key + l = xshandle().ls(new_subdir) + if l: + ret.append([key, self.list_recursive_(new_subdir, l)]) + else: + ret.append([key, xshandle().read(new_subdir)]) return ret + + + def list_recursive(self, *args): + """If no arguments are given, list this transaction's path, returning + the entries therein, or the empty list if no entries are found. + Otherwise, treat each argument as a subpath to this transaction's + path, and return the cumulative listing of each of those instead. + """ + if len(args) == 0: + args = self.list() + if args is None or len(args) == 0: + return [] + + return self.list_recursive_(self.path, args) + def gather(self, *args): if len(args) and type(args[0]) != tuple: @@ -163,6 +209,13 @@ def Read(cls, path, *args): + """If only one argument is given (path), return the value stored at + that path. If two arguments are given, treat the second argument as a + subpath within the first, and return the value at the composed path. + Otherwise, treat each argument after the first as a subpath to the + given path, and return a list composed of the values at each of those + instead. This operation is performed inside a transaction. + """ while True: t = cls(path) try: @@ -206,6 +259,12 @@ Remove = classmethod(Remove) def List(cls, path, *args): + """If only one argument is given (path), list its contents, returning + the entries therein, or the empty list if no entries are found. + Otherwise, treat each further argument as a subpath to the given path, + and return the cumulative listing of each of those instead. This + operation is performed inside a transaction. + """ while True: t = cls(path) try: @@ -218,6 +277,25 @@ List = classmethod(List) + def ListRecursive(cls, path, *args): + """If only one argument is given (path), list its contents + recursively, returning the entries therein, or the empty list if no + entries are found. Otherwise, treat each further argument as a + subpath to the given path, and return the cumulative listing of each + of those instead. This operation is performed inside a transaction. + """ + while True: + t = cls(path) + try: + v = t.list_recursive(*args) + if t.commit(): + return v + except: + t.abort() + raise + + ListRecursive = classmethod(ListRecursive) + def Gather(cls, path, *args): while True: t = cls(path) diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Thu Sep 29 22:22:02 2005 +++ b/tools/python/xen/xm/main.py Thu Sep 29 23:28:44 2005 @@ -175,6 +175,10 @@ dom = args[0] # TODO: should check if this exists savefile = os.path.abspath(args[1]) + + if not os.access(os.path.dirname(savefile), os.W_OK): + err("xm save: Unable to create file %s" % savefile) + sys.exit(1) from xen.xend.XendClient import server server.xend_domain_save(dom, savefile) @@ -183,6 +187,10 @@ arg_check(args,1,"restore") savefile = os.path.abspath(args[0]) + + if not os.access(savefile, os.R_OK): + err("xm restore: Unable to read file %s" % savefile) + sys.exit(1) from xen.xend.XendClient import server info = server.xend_domain_restore(savefile) diff -r 93e27f7ca8a8 -r 61b3b357d827 tools/xenstore/xenstored_domain.c --- a/tools/xenstore/xenstored_domain.c Thu Sep 29 22:22:02 2005 +++ b/tools/xenstore/xenstored_domain.c Thu Sep 29 23:28:44 2005 @@ -63,6 +63,8 @@ /* The connection associated with this. */ struct connection *conn; + /* Have we noticed that this domain is shutdown? */ + int shutdown; }; static LIST_HEAD(domains); @@ -222,19 +224,25 @@ { xc_dominfo_t dominfo; struct domain *domain, *tmp; - int released = 0; + int notify = 0; list_for_each_entry_safe(domain, tmp, &domains, list) { if (xc_domain_getinfo(*xc_handle, domain->domid, 1, &dominfo) == 1 && - dominfo.domid == domain->domid && - !dominfo.dying && !dominfo.crashed && !dominfo.shutdown) - continue; + dominfo.domid == domain->domid) { + if ((dominfo.crashed || dominfo.shutdown) + && !domain->shutdown) { + domain->shutdown = 1; + notify = 1; + } + if (!dominfo.dying) + continue; + } talloc_free(domain->conn); - released++; - } - - if (released) + notify = 1; + } + + if (notify) fire_watches(NULL, "@releaseDomain", false); } @@ -272,6 +280,7 @@ struct domain *domain; domain = talloc(context, struct domain); domain->port = 0; + domain->shutdown = 0; domain->domid = domid; domain->path = talloc_strdup(domain, path); domain->page = xc_map_foreign_range(*xc_handle, domain->domid, diff -r 93e27f7ca8a8 -r 61b3b357d827 xen/arch/x86/shadow32.c --- a/xen/arch/x86/shadow32.c Thu Sep 29 22:22:02 2005 +++ b/xen/arch/x86/shadow32.c Thu Sep 29 23:28:44 2005 @@ -755,9 +755,13 @@ /* * Then free monitor_table. + * Note: for VMX guest, only BSP need do this free. */ - mfn = pagetable_get_pfn(v->arch.monitor_table); - free_domheap_page(&frame_table[mfn]); + if (!(VMX_DOMAIN(v) && v->vcpu_id)) { + mfn = pagetable_get_pfn(v->arch.monitor_table); + unmap_domain_page(v->arch.monitor_vtable); + free_domheap_page(&frame_table[mfn]); + } v->arch.monitor_table = mk_pagetable(0); v->arch.monitor_vtable = 0; @@ -1832,7 +1836,7 @@ } #endif - FSH_LOG("%s(gpfn=%lx, mfn=%lx) c=%08x t=%08x", __func__, + FSH_LOG("%s(gpfn=%lx, mfn=%lx) c=%08x t=%08lx", __func__, gpfn, mfn, page->count_info, page->u.inuse.type_info); // XXX this will require some more thought... Cross-domain sharing and @@ -3013,7 +3017,7 @@ l1_pgentry_t guest_pte = *p_guest_pte; l1_pgentry_t shadow_pte = *p_shadow_pte; l1_pgentry_t snapshot_pte = p_snapshot_pte ? *p_snapshot_pte : l1e_empty(); - l1_pgentry_t eff_guest_pte; + l1_pgentry_t eff_guest_pte = l1e_empty(); unsigned long mask, eff_guest_pfn, eff_guest_mfn, shadow_mfn; int errors = 0, guest_writable; int page_table_page; @@ -3070,7 +3074,7 @@ if ( (l1e_get_flags(shadow_pte) & _PAGE_RW ) && !guest_writable ) { - printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=0x%08x page_table_page=%d\n", + printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=%lx page_table_page=%d\n", eff_guest_pfn, eff_guest_mfn, shadow_mfn, frame_table[eff_guest_mfn].u.inuse.type_info, page_table_page); @@ -3081,7 +3085,7 @@ (l1e_get_flags(shadow_pte) & _PAGE_RW ) && !(guest_writable && (l1e_get_flags(eff_guest_pte) & _PAGE_DIRTY)) ) { - printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=0x%08x page_table_page=%d\n", + printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=%lx page_table_page=%d\n", eff_guest_pfn, eff_guest_mfn, shadow_mfn, frame_table[eff_guest_mfn].u.inuse.type_info, page_table_page); diff -r 93e27f7ca8a8 -r 61b3b357d827 xen/arch/x86/shadow_public.c --- a/xen/arch/x86/shadow_public.c Thu Sep 29 22:22:02 2005 +++ b/xen/arch/x86/shadow_public.c Thu Sep 29 23:28:44 2005 @@ -256,14 +256,15 @@ { unsigned long mfn; -// ASSERT( pagetable_val(v->arch.monitor_table) ); /* * free monitor_table. + * Note: for VMX guest, only BSP need do this free. */ - //mfn = (pagetable_val(v->arch.monitor_table)) >> PAGE_SHIFT; - mfn = pagetable_get_pfn(v->arch.monitor_table); - unmap_domain_page(v->arch.monitor_vtable); - free_domheap_page(&frame_table[mfn]); + if (!(VMX_DOMAIN(v) && v->vcpu_id)) { + mfn = pagetable_get_pfn(v->arch.monitor_table); + unmap_domain_page(v->arch.monitor_vtable); + free_domheap_page(&frame_table[mfn]); + } v->arch.monitor_table = mk_pagetable(0); v->arch.monitor_vtable = 0; } @@ -358,9 +359,13 @@ /* * Then free monitor_table. + * Note: for VMX guest, only BSP need do this free. */ - mfn = pagetable_get_pfn(v->arch.monitor_table); - free_domheap_page(&frame_table[mfn]); + if (!(VMX_DOMAIN(v) && v->vcpu_id)) { + mfn = pagetable_get_pfn(v->arch.monitor_table); + unmap_domain_page(v->arch.monitor_vtable); + free_domheap_page(&frame_table[mfn]); + } v->arch.monitor_table = mk_pagetable(0); v->arch.monitor_vtable = 0; diff -r 93e27f7ca8a8 -r 61b3b357d827 xen/arch/x86/time.c --- a/xen/arch/x86/time.c Thu Sep 29 22:22:02 2005 +++ b/xen/arch/x86/time.c Thu Sep 29 23:28:44 2005 @@ -119,8 +119,8 @@ "mov %4,%%eax ; " "mov %%edx,%4 ; " "mul %5 ; " + "xor %5,%5 ; " "add %4,%%eax ; " - "xor %5,%5 ; " "adc %5,%%edx ; " : "=A" (product), "=r" (tmp1), "=r" (tmp2) : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (scale->mul_frac) ); diff -r 93e27f7ca8a8 -r 61b3b357d827 xen/arch/x86/vmx_platform.c --- a/xen/arch/x86/vmx_platform.c Thu Sep 29 22:22:02 2005 +++ b/xen/arch/x86/vmx_platform.c Thu Sep 29 23:28:44 2005 @@ -667,6 +667,7 @@ mpcip->instr = inst->instr; mpcip->operand[0] = inst->operand[0]; /* source */ mpcip->operand[1] = inst->operand[1]; /* destination */ + mpcip->immediate = inst->immediate; if (inst->operand[0] & REGISTER) { /* dest is memory */ index = operand_index(inst->operand[0]); @@ -833,12 +834,16 @@ mmio_operands(IOREQ_TYPE_XOR, gpa, &mmio_inst, mpcip, regs); break; - case INSTR_CMP: - mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs); - break; - + case INSTR_CMP: /* Pass through */ case INSTR_TEST: - mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs); + mpcip->flags = mmio_inst.flags; + mpcip->instr = mmio_inst.instr; + mpcip->operand[0] = mmio_inst.operand[0]; /* source */ + mpcip->operand[1] = mmio_inst.operand[1]; /* destination */ + mpcip->immediate = mmio_inst.immediate; + + /* send the request and wait for the value */ + send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, mmio_inst.op_size, 0, IOREQ_READ, 0); break; default: diff -r 93e27f7ca8a8 -r 61b3b357d827 linux-2.6-xen-sparse/include/asm-xen/queues.h --- a/linux-2.6-xen-sparse/include/asm-xen/queues.h Thu Sep 29 22:22:02 2005 +++ /dev/null Thu Sep 29 23:28:44 2005 @@ -1,81 +0,0 @@ - -/* - * Oh dear. Task queues were removed from Linux 2.6 and replaced by work - * queues. Unfortunately the semantics is not the same. With task queues we - * can defer work until a particular event occurs -- this is not - * straightforwardly done with work queues (queued work is performed asap, or - * after some fixed timeout). Conversely, work queues are a (slightly) neater - * way of deferring work to a process context than using task queues in 2.4. - * - * This is a bit of a needless reimplementation -- should have just pulled - * the code from 2.4, but I tried leveraging work queues to simplify things. - * They didn't help. :-( - */ - -#ifndef __QUEUES_H__ -#define __QUEUES_H__ - -#include <linux/version.h> -#include <linux/list.h> -#include <linux/workqueue.h> - -struct tq_struct { - void (*fn)(void *); - void *arg; - struct list_head list; - unsigned long pending; -}; -#define INIT_TQUEUE(_name, _fn, _arg) \ - do { \ - INIT_LIST_HEAD(&(_name)->list); \ - (_name)->pending = 0; \ - (_name)->fn = (_fn); (_name)->arg = (_arg); \ - } while ( 0 ) -#define DECLARE_TQUEUE(_name, _fn, _arg) \ - struct tq_struct _name = { (_fn), (_arg), LIST_HEAD_INIT((_name).list), 0 } - -typedef struct { - struct list_head list; - spinlock_t lock; -} task_queue; -#define DECLARE_TASK_QUEUE(_name) \ - task_queue _name = { LIST_HEAD_INIT((_name).list), SPIN_LOCK_UNLOCKED } - -static inline int queue_task(struct tq_struct *tqe, task_queue *tql) -{ - unsigned long flags; - if ( test_and_set_bit(0, &tqe->pending) ) - return 0; - spin_lock_irqsave(&tql->lock, flags); - list_add_tail(&tqe->list, &tql->list); - spin_unlock_irqrestore(&tql->lock, flags); - return 1; -} - -static inline void run_task_queue(task_queue *tql) -{ - struct list_head head, *ent; - struct tq_struct *tqe; - unsigned long flags; - void (*fn)(void *); - void *arg; - - spin_lock_irqsave(&tql->lock, flags); - list_add(&head, &tql->list); - list_del_init(&tql->list); - spin_unlock_irqrestore(&tql->lock, flags); - - while ( !list_empty(&head) ) - { - ent = head.next; - list_del_init(ent); - tqe = list_entry(ent, struct tq_struct, list); - fn = tqe->fn; - arg = tqe->arg; - wmb(); - tqe->pending = 0; - fn(arg); - } -} - -#endif /* __QUEUES_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |