diff options
author | dfr <dfr@FreeBSD.org> | 2009-03-11 15:30:12 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2009-03-11 15:30:12 +0000 |
commit | 598fb4217fe304b2d9dae488867c35e7213e3ba5 (patch) | |
tree | 633dc40712503605071c68975d2c972638554000 /sys/xen | |
parent | 2ee25eb1a489668e88e623440b968811e9f6d5b3 (diff) | |
parent | 0b3e97d804d73af27fba381fd51fe0dd48a9cb06 (diff) | |
download | FreeBSD-src-598fb4217fe304b2d9dae488867c35e7213e3ba5.zip FreeBSD-src-598fb4217fe304b2d9dae488867c35e7213e3ba5.tar.gz |
Merge in support for Xen HVM on amd64 architecture.
Diffstat (limited to 'sys/xen')
-rw-r--r-- | sys/xen/evtchn/evtchn.c | 220 | ||||
-rw-r--r-- | sys/xen/evtchn/evtchn_dev.c | 14 | ||||
-rw-r--r-- | sys/xen/features.c | 6 | ||||
-rw-r--r-- | sys/xen/features.h | 20 | ||||
-rw-r--r-- | sys/xen/gnttab.c | 158 | ||||
-rw-r--r-- | sys/xen/gnttab.h | 15 | ||||
-rw-r--r-- | sys/xen/hypervisor.h | 17 | ||||
-rw-r--r-- | sys/xen/interface/arch-x86/xen.h | 5 | ||||
-rw-r--r-- | sys/xen/interface/hvm/params.h | 2 | ||||
-rw-r--r-- | sys/xen/reboot.c | 262 | ||||
-rw-r--r-- | sys/xen/xen_intr.h | 64 | ||||
-rw-r--r-- | sys/xen/xenbus/xenbus_probe.c | 1 | ||||
-rw-r--r-- | sys/xen/xenbus/xenbus_xs.c | 35 |
13 files changed, 569 insertions, 250 deletions
diff --git a/sys/xen/evtchn/evtchn.c b/sys/xen/evtchn/evtchn.c index 884270c..61b738b 100644 --- a/sys/xen/evtchn/evtchn.c +++ b/sys/xen/evtchn/evtchn.c @@ -13,56 +13,28 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> +#include <sys/limits.h> #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/mutex.h> #include <sys/interrupt.h> #include <sys/pcpu.h> +#include <sys/smp.h> #include <machine/cpufunc.h> #include <machine/intr_machdep.h> + #include <machine/xen/xen-os.h> +#include <machine/xen/xenvar.h> #include <xen/xen_intr.h> #include <machine/xen/synch_bitops.h> #include <xen/evtchn.h> #include <xen/hypervisor.h> #include <sys/smp.h> - - -/* linux helper functions that got sucked in - * rename and move XXX - */ - - -static inline int find_first_bit(const unsigned long *addr, unsigned size) -{ - int d0, d1; - int res; - - /* This looks at memory. Mark it volatile to tell gcc not to move it around */ - __asm__ __volatile__( - "xorl %%eax,%%eax\n\t" - "repe; scasl\n\t" - "jz 1f\n\t" - "leal -4(%%edi),%%edi\n\t" - "bsfl (%%edi),%%eax\n" - "1:\tsubl %%ebx,%%edi\n\t" - "shll $3,%%edi\n\t" - "addl %%edi,%%eax" - :"=a" (res), "=&c" (d0), "=&D" (d1) - :"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory"); - return res; -} - -#define min_t(type,x,y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) -#define first_cpu(src) __first_cpu(&(src), NR_CPUS) -static inline int __first_cpu(const xen_cpumask_t *srcp, int nbits) -{ - return min_t(int, nbits, find_first_bit(srcp->bits, nbits)); -} +#include <xen/xen_intr.h> +#include <xen/evtchn.h> static inline unsigned long __ffs(unsigned long word) { @@ -166,7 +138,7 @@ static int irq_bindcount[NR_IRQS]; #ifdef SMP static uint8_t cpu_evtchn[NR_EVENT_CHANNELS]; -static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG]; +static unsigned long cpu_evtchn_mask[MAX_VIRT_CPUS][NR_EVENT_CHANNELS/LONG_BIT]; #define active_evtchns(cpu,sh,idx) \ ((sh)->evtchn_pending[idx] & \ @@ -220,7 +192,7 @@ evtchn_do_upcall(struct trapframe *frame) shared_info_t *s; vcpu_info_t *vcpu_info; - cpu = smp_processor_id(); + cpu = PCPU_GET(cpuid); s = HYPERVISOR_shared_info; vcpu_info = &s->vcpu_info[cpu]; @@ -236,7 +208,7 @@ evtchn_do_upcall(struct trapframe *frame) while ((l2 = active_evtchns(cpu, s, l1i)) != 0) { l2i = __ffs(l2); - port = (l1i * BITS_PER_LONG) + l2i; + port = (l1i * LONG_BIT) + l2i; if ((irq = evtchn_to_irq[port]) != -1) { struct intsrc *isrc = intr_lookup_source(irq); /* @@ -258,7 +230,7 @@ ipi_pcpu(unsigned int cpu, int vector) { int irq; - irq = per_cpu(ipi_to_irq, cpu)[vector]; + irq = PCPU_GET(ipi_to_irq[vector]); notify_remote_via_irq(irq); } @@ -310,11 +282,12 @@ bind_local_port_to_irq(unsigned int local_port) mtx_lock_spin(&irq_mapping_update_lock); - PANIC_IF(evtchn_to_irq[local_port] != -1); - + KASSERT(evtchn_to_irq[local_port] == -1, + ("evtchn_to_irq inconsistent")); + if ((irq = find_unbound_irq()) < 0) { struct evtchn_close close = { .port = local_port }; - PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)); + HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); goto out; } @@ -368,21 +341,20 @@ bind_virq_to_irq(unsigned int virq, unsigned int cpu) mtx_lock_spin(&irq_mapping_update_lock); - if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) { + if ((irq = pcpu_find(cpu)->pc_virq_to_irq[virq]) == -1) { if ((irq = find_unbound_irq()) < 0) goto out; bind_virq.virq = virq; bind_virq.vcpu = cpu; - PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, - &bind_virq) != 0); + HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind_virq); evtchn = bind_virq.port; evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); - per_cpu(virq_to_irq, cpu)[virq] = irq; + pcpu_find(cpu)->pc_virq_to_irq[virq] = irq; bind_evtchn_to_cpu(evtchn, cpu); } @@ -407,18 +379,18 @@ bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) mtx_lock_spin(&irq_mapping_update_lock); - if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) { + if ((irq = pcpu_find(cpu)->pc_ipi_to_irq[ipi]) == -1) { if ((irq = find_unbound_irq()) < 0) goto out; bind_ipi.vcpu = cpu; - PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi) != 0); + HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi); evtchn = bind_ipi.port; evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); - per_cpu(ipi_to_irq, cpu)[ipi] = irq; + pcpu_find(cpu)->pc_ipi_to_irq[ipi] = irq; bind_evtchn_to_cpu(evtchn, cpu); } @@ -432,24 +404,27 @@ out: } -void +static void unbind_from_irq(int irq) { struct evtchn_close close; int evtchn = evtchn_from_irq(irq); + int cpu; mtx_lock_spin(&irq_mapping_update_lock); if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) { close.port = evtchn; - PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0); + HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); switch (type_from_irq(irq)) { case IRQT_VIRQ: - per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))[index_from_irq(irq)] = -1; + cpu = cpu_from_evtchn(evtchn); + pcpu_find(cpu)->pc_virq_to_irq[index_from_irq(irq)] = -1; break; case IRQT_IPI: - per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))[index_from_irq(irq)] = -1; + cpu = cpu_from_evtchn(evtchn); + pcpu_find(cpu)->pc_ipi_to_irq[index_from_irq(irq)] = -1; break; default: break; @@ -467,11 +442,8 @@ unbind_from_irq(int irq) int bind_caller_port_to_irqhandler(unsigned int caller_port, - const char *devname, - driver_intr_t handler, - void *arg, - unsigned long irqflags, - unsigned int *irqp) + const char *devname, driver_intr_t handler, void *arg, + unsigned long irqflags, unsigned int *irqp) { unsigned int irq; int error; @@ -493,13 +465,9 @@ bind_caller_port_to_irqhandler(unsigned int caller_port, } int -bind_listening_port_to_irqhandler( - unsigned int remote_domain, - const char *devname, - driver_intr_t handler, - void *arg, - unsigned long irqflags, - unsigned int *irqp) +bind_listening_port_to_irqhandler(unsigned int remote_domain, + const char *devname, driver_intr_t handler, void *arg, + unsigned long irqflags, unsigned int *irqp) { unsigned int irq; int error; @@ -519,14 +487,10 @@ bind_listening_port_to_irqhandler( } int -bind_interdomain_evtchn_to_irqhandler( - unsigned int remote_domain, - unsigned int remote_port, - const char *devname, - driver_filter_t filter, - driver_intr_t handler, - unsigned long irqflags, - unsigned int *irqp) +bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, + unsigned int remote_port, const char *devname, + driver_filter_t filter, driver_intr_t handler, + unsigned long irqflags, unsigned int *irqp) { unsigned int irq; int error; @@ -546,14 +510,9 @@ bind_interdomain_evtchn_to_irqhandler( } int -bind_virq_to_irqhandler(unsigned int virq, - unsigned int cpu, - const char *devname, - driver_filter_t filter, - driver_intr_t handler, - void *arg, - unsigned long irqflags, - unsigned int *irqp) +bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, + const char *devname, driver_filter_t filter, driver_intr_t handler, + unsigned long irqflags, unsigned int *irqp) { unsigned int irq; int error; @@ -573,12 +532,9 @@ bind_virq_to_irqhandler(unsigned int virq, } int -bind_ipi_to_irqhandler(unsigned int ipi, - unsigned int cpu, - const char *devname, - driver_filter_t filter, - unsigned long irqflags, - unsigned int *irqp) +bind_ipi_to_irqhandler(unsigned int ipi, unsigned int cpu, + const char *devname, driver_filter_t filter, + unsigned long irqflags, unsigned int *irqp) { unsigned int irq; int error; @@ -636,9 +592,9 @@ rebind_irq_to_cpu(unsigned irq, unsigned tcpu) } -static void set_affinity_irq(unsigned irq, xen_cpumask_t dest) +static void set_affinity_irq(unsigned irq, cpumask_t dest) { - unsigned tcpu = first_cpu(dest); + unsigned tcpu = ffs(dest) - 1; rebind_irq_to_cpu(irq, tcpu); } #endif @@ -656,13 +612,11 @@ static void xenpic_dynirq_enable_source(struct intsrc *isrc); static void xenpic_dynirq_disable_source(struct intsrc *isrc, int); static void xenpic_dynirq_eoi_source(struct intsrc *isrc); static void xenpic_dynirq_enable_intr(struct intsrc *isrc); -static void xenpic_dynirq_disable_intr(struct intsrc *isrc); static void xenpic_pirq_enable_source(struct intsrc *isrc); static void xenpic_pirq_disable_source(struct intsrc *isrc, int); static void xenpic_pirq_eoi_source(struct intsrc *isrc); static void xenpic_pirq_enable_intr(struct intsrc *isrc); -static void xenpic_pirq_disable_intr(struct intsrc *isrc); static int xenpic_vector(struct intsrc *isrc); @@ -677,7 +631,6 @@ struct pic xenpic_dynirq_template = { .pic_disable_source = xenpic_dynirq_disable_source, .pic_eoi_source = xenpic_dynirq_eoi_source, .pic_enable_intr = xenpic_dynirq_enable_intr, - .pic_disable_intr = xenpic_dynirq_disable_intr, .pic_vector = xenpic_vector, .pic_source_pending = xenpic_source_pending, .pic_suspend = xenpic_suspend, @@ -689,7 +642,6 @@ struct pic xenpic_pirq_template = { .pic_disable_source = xenpic_pirq_disable_source, .pic_eoi_source = xenpic_pirq_eoi_source, .pic_enable_intr = xenpic_pirq_enable_intr, - .pic_disable_intr = xenpic_pirq_disable_intr, .pic_vector = xenpic_vector, .pic_source_pending = xenpic_source_pending, .pic_suspend = xenpic_suspend, @@ -748,20 +700,6 @@ xenpic_dynirq_enable_intr(struct intsrc *isrc) } static void -xenpic_dynirq_disable_intr(struct intsrc *isrc) -{ - unsigned int irq; - struct xenpic_intsrc *xp; - - xp = (struct xenpic_intsrc *)isrc; - mtx_lock_spin(&irq_mapping_update_lock); - xp->xp_masked = 1; - irq = xenpic_vector(isrc); - mask_evtchn(evtchn_from_irq(irq)); - mtx_unlock_spin(&irq_mapping_update_lock); -} - -static void xenpic_dynirq_eoi_source(struct intsrc *isrc) { unsigned int irq; @@ -825,7 +763,7 @@ notify_remote_via_irq(int irq) if (VALID_EVTCHN(evtchn)) notify_remote_via_evtchn(evtchn); else - panic("invalid evtchn"); + panic("invalid evtchn %d", irq); } /* required for support of physical devices */ @@ -899,32 +837,6 @@ xenpic_pirq_enable_intr(struct intsrc *isrc) } static void -xenpic_pirq_disable_intr(struct intsrc *isrc) -{ - unsigned int irq; - int evtchn; - struct evtchn_close close; - - mtx_lock_spin(&irq_mapping_update_lock); - irq = xenpic_vector(isrc); - evtchn = evtchn_from_irq(irq); - - if (!VALID_EVTCHN(evtchn)) - goto done; - - mask_evtchn(evtchn); - - close.port = evtchn; - PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0); - - bind_evtchn_to_cpu(evtchn, 0); - evtchn_to_irq[evtchn] = -1; - irq_info[irq] = IRQ_UNBOUND; - done: - mtx_unlock_spin(&irq_mapping_update_lock); -} - -static void xenpic_pirq_enable_source(struct intsrc *isrc) { int evtchn; @@ -998,7 +910,7 @@ void unmask_evtchn(int port) { shared_info_t *s = HYPERVISOR_shared_info; - unsigned int cpu = smp_processor_id(); + unsigned int cpu = PCPU_GET(cpuid); vcpu_info_t *vcpu_info = &s->vcpu_info[cpu]; /* Slow path (hypercall) if this is a non-local port. */ @@ -1016,7 +928,7 @@ unmask_evtchn(int port) * masked. */ if (synch_test_bit(port, &s->evtchn_pending) && - !synch_test_and_set_bit(port / BITS_PER_LONG, + !synch_test_and_set_bit(port / LONG_BIT, &vcpu_info->evtchn_pending_sel)) { vcpu_info->evtchn_upcall_pending = 1; if (!vcpu_info->evtchn_upcall_mask) @@ -1039,15 +951,21 @@ void irq_resume(void) mask_evtchn(evtchn); /* Check that no PIRQs are still bound. */ - for (pirq = 0; pirq < NR_PIRQS; pirq++) - PANIC_IF(irq_info[pirq_to_irq(pirq)] != IRQ_UNBOUND); + for (pirq = 0; pirq < NR_PIRQS; pirq++) { + KASSERT(irq_info[pirq_to_irq(pirq)] == IRQ_UNBOUND, + ("pirq_to_irq inconsistent")); + } /* Secondary CPUs must have no VIRQ or IPI bindings. */ - for (cpu = 1; cpu < NR_CPUS; cpu++) { - for (virq = 0; virq < NR_VIRQS; virq++) - PANIC_IF(per_cpu(virq_to_irq, cpu)[virq] != -1); - for (ipi = 0; ipi < NR_IPIS; ipi++) - PANIC_IF(per_cpu(ipi_to_irq, cpu)[ipi] != -1); + for (cpu = 1; cpu < MAX_VIRT_CPUS; cpu++) { + for (virq = 0; virq < NR_VIRQS; virq++) { + KASSERT(pcpu_find(cpu)->pc_virq_to_irq[virq] == -1, + ("virq_to_irq inconsistent")); + } + for (ipi = 0; ipi < NR_IPIS; ipi++) { + KASSERT(pcpu_find(cpu)->pc_ipi_to_irq[ipi] == -1, + ("ipi_to_irq inconsistent")); + } } /* No IRQ <-> event-channel mappings. */ @@ -1058,15 +976,16 @@ void irq_resume(void) /* Primary CPU: rebind VIRQs automatically. */ for (virq = 0; virq < NR_VIRQS; virq++) { - if ((irq = per_cpu(virq_to_irq, 0)[virq]) == -1) + if ((irq = pcpu_find(0)->pc_virq_to_irq[virq]) == -1) continue; - PANIC_IF(irq_info[irq] != mk_irq_info(IRQT_VIRQ, virq, 0)); + KASSERT(irq_info[irq] == mk_irq_info(IRQT_VIRQ, virq, 0), + ("irq_info inconsistent")); /* Get a new binding from Xen. */ bind_virq.virq = virq; bind_virq.vcpu = 0; - PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind_virq) != 0); + HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind_virq); evtchn = bind_virq.port; /* Record the new mapping. */ @@ -1079,15 +998,16 @@ void irq_resume(void) /* Primary CPU: rebind IPIs automatically. */ for (ipi = 0; ipi < NR_IPIS; ipi++) { - if ((irq = per_cpu(ipi_to_irq, 0)[ipi]) == -1) + if ((irq = pcpu_find(0)->pc_ipi_to_irq[ipi]) == -1) continue; - PANIC_IF(irq_info[irq] != mk_irq_info(IRQT_IPI, ipi, 0)); + KASSERT(irq_info[irq] == mk_irq_info(IRQT_IPI, ipi, 0), + ("irq_info inconsistent")); /* Get a new binding from Xen. */ memset(&op, 0, sizeof(op)); bind_ipi.vcpu = 0; - PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi) != 0); + HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi); evtchn = bind_ipi.port; /* Record the new mapping. */ @@ -1111,9 +1031,9 @@ evtchn_init(void *dummy __unused) /* No VIRQ or IPI bindings. */ for (cpu = 0; cpu < mp_ncpus; cpu++) { for (i = 0; i < NR_VIRQS; i++) - per_cpu(virq_to_irq, cpu)[i] = -1; + pcpu_find(cpu)->pc_virq_to_irq[i] = -1; for (i = 0; i < NR_IPIS; i++) - per_cpu(ipi_to_irq, cpu)[i] = -1; + pcpu_find(cpu)->pc_ipi_to_irq[i] = -1; } /* No event-channel -> IRQ mappings. */ diff --git a/sys/xen/evtchn/evtchn_dev.c b/sys/xen/evtchn/evtchn_dev.c index ea12860..4253d8a 100644 --- a/sys/xen/evtchn/evtchn_dev.c +++ b/sys/xen/evtchn/evtchn_dev.c @@ -23,8 +23,6 @@ __FBSDID("$FreeBSD$"); #include <sys/fcntl.h> #include <sys/ioccom.h> -#include <machine/cpufunc.h> -#include <machine/intr_machdep.h> #include <machine/xen/xen-os.h> #include <xen/xen_intr.h> #include <machine/bus.h> @@ -234,14 +232,14 @@ evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg, __evtchn_reset_buffer_ring(); break; case EVTCHN_BIND: - if ( !synch_test_and_set_bit((int)arg, &bound_ports[0]) ) - unmask_evtchn((int)arg); + if ( !synch_test_and_set_bit((uintptr_t)arg, &bound_ports[0]) ) + unmask_evtchn((uintptr_t)arg); else rc = EINVAL; break; case EVTCHN_UNBIND: - if ( synch_test_and_clear_bit((int)arg, &bound_ports[0]) ) - mask_evtchn((int)arg); + if ( synch_test_and_clear_bit((uintptr_t)arg, &bound_ports[0]) ) + mask_evtchn((uintptr_t)arg); else rc = EINVAL; break; @@ -383,12 +381,12 @@ evtchn_dev_init(void *dummy __unused) /* (DEVFS) automatically destroy the symlink with its destination. */ devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle); #endif - printk("Event-channel device installed.\n"); + if (bootverbose) + printf("Event-channel device installed.\n"); return 0; } - SYSINIT(evtchn_dev_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, evtchn_dev_init, NULL); diff --git a/sys/xen/features.c b/sys/xen/features.c index 876a7d1..f28fe04 100644 --- a/sys/xen/features.c +++ b/sys/xen/features.c @@ -1,10 +1,12 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> + #include <machine/xen/xen-os.h> #include <xen/hypervisor.h> -#include <machine/xen/features.h> +#include <xen/features.h> uint8_t xen_features[XENFEAT_NR_SUBMAPS * 32] /* __read_mostly */; diff --git a/sys/xen/features.h b/sys/xen/features.h new file mode 100644 index 0000000..b4cce2f --- /dev/null +++ b/sys/xen/features.h @@ -0,0 +1,20 @@ +/****************************************************************************** + * features.h + * + * Query the features reported by Xen. + * + * Copyright (c) 2006, Ian Campbell + */ + +#ifndef __ASM_XEN_FEATURES_H__ +#define __ASM_XEN_FEATURES_H__ + +#include <xen/interface/version.h> + +extern void setup_xen_features(void); + +extern uint8_t xen_features[XENFEAT_NR_SUBMAPS * 32]; + +#define xen_feature(flag) (xen_features[flag]) + +#endif /* __ASM_XEN_FEATURES_H__ */ diff --git a/sys/xen/gnttab.c b/sys/xen/gnttab.c index 9675655..d05790b 100644 --- a/sys/xen/gnttab.c +++ b/sys/xen/gnttab.c @@ -25,28 +25,20 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/malloc.h> #include <sys/mman.h> -#include <vm/vm.h> -#include <vm/vm_extern.h> - -#include <vm/vm_page.h> -#include <vm/vm_kern.h> +#include <machine/xen/xen-os.h> #include <xen/hypervisor.h> #include <machine/xen/synch_bitops.h> -#include <xen/gnttab.h> -#define cmpxchg(a, b, c) atomic_cmpset_int((volatile u_int *)(a),(b),(c)) +#include <xen/hypervisor.h> +#include <xen/gnttab.h> -#if 1 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s': line %d, file %s\n", \ - #_p , __LINE__, __FILE__); *(int*)0=0; } -#else -#define ASSERT(_p) ((void)0) -#endif +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_extern.h> +#include <vm/pmap.h> -#define WPRINTK(fmt, args...) \ - printk("xen_grant: " fmt, ##args) +#define cmpxchg(a, b, c) atomic_cmpset_int((volatile u_int *)(a),(b),(c)) /* External tools reserve first few grant table entries. */ #define NR_RESERVED_ENTRIES 8 @@ -72,14 +64,14 @@ static int gnttab_expand(unsigned int req_entries); static int get_free_entries(int count, int *entries) { - int ref, rc; + int ref, error; grant_ref_t head; mtx_lock(&gnttab_list_lock); if ((gnttab_free_count < count) && - ((rc = gnttab_expand(count - gnttab_free_count)) != 0)) { + ((error = gnttab_expand(count - gnttab_free_count)) != 0)) { mtx_unlock(&gnttab_list_lock); - return (rc); + return (error); } ref = head = gnttab_free_head; gnttab_free_count -= count; @@ -163,6 +155,7 @@ 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(); @@ -213,7 +206,8 @@ gnttab_end_foreign_access(grant_ref_t ref, void *page) } int -gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn) +gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn, + grant_ref_t *result) { int error, ref; @@ -223,7 +217,8 @@ gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn) gnttab_grant_foreign_transfer_ref(ref, domid, pfn); - return (ref); + *result = ref; + return (0); } void @@ -261,7 +256,7 @@ gnttab_end_foreign_transfer_ref(grant_ref_t ref) /* Read the frame number /after/ reading completion status. */ rmb(); frame = shared[ref].frame; - PANIC_IF(frame == 0); + KASSERT(frame != 0, ("grant table inconsistent")); return (frame); } @@ -320,6 +315,7 @@ gnttab_alloc_grant_references(uint16_t count, grant_ref_t *head) int gnttab_empty_grant_references(const grant_ref_t *private_head) { + return (*private_head == GNTTAB_LIST_END); } @@ -331,20 +327,20 @@ gnttab_claim_grant_reference(grant_ref_t *private_head) if (unlikely(g == GNTTAB_LIST_END)) return (ENOSPC); *private_head = gnttab_entry(g); - return (g); } void gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t release) { + gnttab_entry(release) = *private_head; *private_head = release; } void gnttab_request_free_callback(struct gnttab_free_callback *callback, - void (*fn)(void *), void *arg, uint16_t count) + void (*fn)(void *), void *arg, uint16_t count) { mtx_lock(&gnttab_list_lock); @@ -387,7 +383,8 @@ grow_gnttab_list(unsigned int more_frames) for (i = nr_grant_frames; i < new_nr_grant_frames; i++) { - gnttab_list[i] = (grant_ref_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT); + gnttab_list[i] = (grant_ref_t *) + malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT); if (!gnttab_list[i]) goto grow_nomem; @@ -405,12 +402,12 @@ grow_gnttab_list(unsigned int more_frames) check_free_callbacks(); - return 0; + return (0); grow_nomem: for ( ; i >= nr_grant_frames; i--) free(gnttab_list[i], M_DEVBUF); - return (-ENOMEM); + return (ENOMEM); } static unsigned int @@ -464,6 +461,8 @@ unmap_pte_fn(pte_t *pte, struct page *pmd_page, } #endif +#ifndef XENHVM + static int gnttab_map(unsigned int start_idx, unsigned int end_idx) { @@ -486,50 +485,117 @@ gnttab_map(unsigned int start_idx, unsigned int end_idx) free(frames, M_DEVBUF); return (ENOSYS); } - PANIC_IF(rc || setup.status); + KASSERT(!(rc || setup.status), + ("unexpected result from grant_table_op")); if (shared == NULL) { vm_offset_t area; area = kmem_alloc_nofault(kernel_map, PAGE_SIZE * max_nr_grant_frames()); - PANIC_IF(area == 0); + KASSERT(area, ("can't allocate VM space for grant table")); shared = (grant_entry_t *)area; } + for (i = 0; i < nr_gframes; i++) PT_SET_MA(((caddr_t)shared) + i*PAGE_SIZE, ((vm_paddr_t)frames[i]) << PAGE_SHIFT | PG_RW | PG_V); free(frames, M_DEVBUF); - return 0; + return (0); } int gnttab_resume(void) { + if (max_nr_grant_frames() < nr_grant_frames) - return -ENOSYS; - return gnttab_map(0, nr_grant_frames - 1); + return (ENOSYS); + return (gnttab_map(0, nr_grant_frames - 1)); } int gnttab_suspend(void) { - int i, pages; + int i; + + for (i = 0; i < nr_grant_frames; i++) + pmap_kremove((vm_offset_t) shared + i * PAGE_SIZE); + + return (0); +} + +#else /* XENHVM */ - pages = (PAGE_SIZE*nr_grant_frames) >> PAGE_SHIFT; +#include <dev/xen/xenpci/xenpcivar.h> - for (i = 0; i < pages; i++) - PT_SET_MA(shared + (i*PAGE_SIZE), (vm_paddr_t)0); +static vm_paddr_t resume_frames; + +static int gnttab_map(unsigned int start_idx, unsigned int end_idx) +{ + struct xen_add_to_physmap xatp; + unsigned int i = end_idx; + + /* + * Loop backwards, so that the first hypercall has the largest index, + * ensuring that the table will grow only once. + */ + do { + xatp.domid = DOMID_SELF; + xatp.idx = i; + xatp.space = XENMAPSPACE_grant_table; + xatp.gpfn = (resume_frames >> PAGE_SHIFT) + i; + if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) + panic("HYPERVISOR_memory_op failed to map gnttab"); + } while (i-- > start_idx); + + if (shared == NULL) { + vm_offset_t area; + + area = kmem_alloc_nofault(kernel_map, + PAGE_SIZE * max_nr_grant_frames()); + KASSERT(area, ("can't allocate VM space for grant table")); + shared = (grant_entry_t *)area; + } + + for (i = start_idx; i <= end_idx; i++) { + pmap_kenter((vm_offset_t) shared + i * PAGE_SIZE, + resume_frames + i * PAGE_SIZE); + } return (0); } +int +gnttab_resume(void) +{ + int error; + unsigned int max_nr_gframes, nr_gframes; + + nr_gframes = nr_grant_frames; + max_nr_gframes = max_nr_grant_frames(); + if (max_nr_gframes < nr_gframes) + return (ENOSYS); + + if (!resume_frames) { + error = xenpci_alloc_space(PAGE_SIZE * max_nr_gframes, + &resume_frames); + if (error) { + printf("error mapping gnttab share frames\n"); + return (error); + } + } + + return (gnttab_map(0, nr_gframes - 1)); +} + +#endif + static int gnttab_expand(unsigned int req_entries) { - int rc; + int error; unsigned int cur, extra; cur = nr_grant_frames; @@ -538,10 +604,11 @@ gnttab_expand(unsigned int req_entries) if (cur + extra > max_nr_grant_frames()) return (ENOSPC); - if ((rc = gnttab_map(cur, cur + extra - 1)) == 0) - rc = grow_gnttab_list(extra); + error = gnttab_map(cur, cur + extra - 1); + if (!error) + error = grow_gnttab_list(extra); - return rc; + return (error); } int @@ -552,7 +619,7 @@ gnttab_init() unsigned int nr_init_grefs; if (!is_running_on_xen()) - return -ENODEV; + return (ENODEV); nr_grant_frames = 1; boot_max_nr_grant_frames = __max_nr_grant_frames(); @@ -571,7 +638,8 @@ gnttab_init() return (ENOMEM); for (i = 0; i < nr_grant_frames; i++) { - gnttab_list[i] = (grant_ref_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT); + gnttab_list[i] = (grant_ref_t *) + malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT); if (gnttab_list[i] == NULL) goto ini_nomem; } @@ -588,8 +656,10 @@ gnttab_init() gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES; gnttab_free_head = NR_RESERVED_ENTRIES; - printk("Grant table initialized\n"); - return 0; + if (bootverbose) + printf("Grant table initialized\n"); + + return (0); ini_nomem: for (i--; i >= 0; i--) diff --git a/sys/xen/gnttab.h b/sys/xen/gnttab.h index bcefbbc..8348af5 100644 --- a/sys/xen/gnttab.h +++ b/sys/xen/gnttab.h @@ -36,10 +36,12 @@ #ifndef __ASM_GNTTAB_H__ +#include <xen/interface/grant_table.h> + #include <xen/hypervisor.h> #include <xen/interface/grant_table.h> #include <machine/xen/xen-os.h> -#include <machine/xen/features.h> +#include <xen/features.h> struct gnttab_free_callback { struct gnttab_free_callback *next; @@ -50,6 +52,10 @@ struct gnttab_free_callback { int gnttab_init(void); +/* + * Allocate a grant table reference and return it in *result. Returns + * zero on success or errno on error. + */ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int flags, grant_ref_t *result); @@ -68,7 +74,7 @@ int gnttab_end_foreign_access_ref(grant_ref_t ref); */ void gnttab_end_foreign_access(grant_ref_t ref, void *page); -int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn); +int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn, grant_ref_t *result); unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref); unsigned long gnttab_end_foreign_transfer(grant_ref_t ref); @@ -104,6 +110,10 @@ void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid, int gnttab_suspend(void); int gnttab_resume(void); +#if 0 + +#include <xen/features.h> + static inline void gnttab_set_map_op(struct gnttab_map_grant_ref *map, vm_paddr_t addr, uint32_t flags, grant_ref_t ref, domid_t domid) @@ -149,5 +159,6 @@ gnttab_set_replace_op(struct gnttab_unmap_and_replace *unmap, vm_paddr_t addr, unmap->handle = handle; } +#endif #endif /* __ASM_GNTTAB_H__ */ diff --git a/sys/xen/hypervisor.h b/sys/xen/hypervisor.h index 369b0c4..0d93f66 100644 --- a/sys/xen/hypervisor.h +++ b/sys/xen/hypervisor.h @@ -8,11 +8,19 @@ * $FreeBSD$ */ -#ifndef __HYPERVISOR_H__ -#define __HYPERVISOR_H__ +#ifndef __XEN_HYPERVISOR_H__ +#define __XEN_HYPERVISOR_H__ + +#ifdef XENHVM + +#define is_running_on_xen() (HYPERVISOR_shared_info != NULL) + +#else #define is_running_on_xen() 1 +#endif + #ifdef PAE #ifndef CONFIG_X86_PAE #define CONFIG_X86_PAE @@ -27,6 +35,7 @@ #include <xen/interface/physdev.h> #include <xen/interface/sched.h> #include <xen/interface/callback.h> +#include <xen/interface/memory.h> #include <machine/xen/hypercall.h> #if defined(__amd64__) @@ -131,7 +140,7 @@ MULTI_update_va_mapping( mcl->op = __HYPERVISOR_update_va_mapping; mcl->args[0] = va; #if defined(__amd64__) - mcl->args[1] = new_val.pte; + mcl->args[1] = new_val; #elif defined(PAE) mcl->args[1] = (uint32_t)(new_val & 0xffffffff) ; mcl->args[2] = (uint32_t)(new_val >> 32); @@ -142,4 +151,4 @@ MULTI_update_va_mapping( mcl->args[MULTI_UVMFLAGS_INDEX] = flags; } -#endif /* __HYPERVISOR_H__ */ +#endif /* __XEN_HYPERVISOR_H__ */ diff --git a/sys/xen/interface/arch-x86/xen.h b/sys/xen/interface/arch-x86/xen.h index 038048e..2c878ef 100644 --- a/sys/xen/interface/arch-x86/xen.h +++ b/sys/xen/interface/arch-x86/xen.h @@ -32,7 +32,8 @@ #define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ typedef struct { type *p; } __guest_handle_ ## name #else -#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ +#error "using old handle" +#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ typedef type * __guest_handle_ ## name #endif @@ -50,7 +51,7 @@ #if defined(__i386__) #include <xen/interface/arch-x86/xen-x86_32.h> #elif defined(__x86_64__) -#include "xen-x86_64.h" +#include <xen/interface/arch-x86/xen-x86_64.h> #endif #ifndef __ASSEMBLY__ diff --git a/sys/xen/interface/hvm/params.h b/sys/xen/interface/hvm/params.h index 5f75ed7..6befa78 100644 --- a/sys/xen/interface/hvm/params.h +++ b/sys/xen/interface/hvm/params.h @@ -21,7 +21,7 @@ #ifndef __XEN_PUBLIC_HVM_PARAMS_H__ #define __XEN_PUBLIC_HVM_PARAMS_H__ -#include "hvm_op.h" +#include <xen/interface/hvm/hvm_op.h> /* * Parameter space for HVMOP_{set,get}_param. diff --git a/sys/xen/reboot.c b/sys/xen/reboot.c new file mode 100644 index 0000000..892dfbf --- /dev/null +++ b/sys/xen/reboot.c @@ -0,0 +1,262 @@ +/* + * + * Copyright (c) 2004 Christian Limpach. + * Copyright (c) 2004-2006,2008 Kip Macy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christian Limpach. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/reboot.h> +#include <sys/sched.h> +#include <sys/smp.h> +#include <sys/systm.h> + +#include <machine/xen/xen-os.h> +#include <xen/hypervisor.h> +#include <xen/gnttab.h> +#include <xen/xen_intr.h> +#include <xen/xenbus/xenbusvar.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#ifdef XENHVM + +#include <dev/xen/xenpci/xenpcivar.h> + +#else + +static void xen_suspend(void); + +#endif + +static void +shutdown_handler(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + char *str; + struct xenbus_transaction xbt; + int error, howto; + + howto = 0; + + again: + error = xenbus_transaction_start(&xbt); + if (error) + return; + + error = xenbus_read(xbt, "control", "shutdown", NULL, (void **) &str); + + /* Ignore read errors and empty reads. */ + if (error || strlen(str) == 0) { + xenbus_transaction_end(xbt, 1); + return; + } + + xenbus_write(xbt, "control", "shutdown", ""); + + error = xenbus_transaction_end(xbt, 0); + if (error == EAGAIN) { + free(str, M_DEVBUF); + goto again; + } + + if (strcmp(str, "reboot") == 0) + howto = 0; + else if (strcmp(str, "poweroff") == 0) + howto |= (RB_POWEROFF | RB_HALT); + else if (strcmp(str, "halt") == 0) +#ifdef XENHVM + /* + * We rely on acpi powerdown to halt the VM. + */ + howto |= (RB_POWEROFF | RB_HALT); +#else + howto |= RB_HALT; +#endif + else if (strcmp(str, "suspend") == 0) + howto = -1; + else { + printf("Ignoring shutdown request: %s\n", str); + goto done; + } + + if (howto == -1) { + xen_suspend(); + goto done; + } + + shutdown_nice(howto); + done: + free(str, M_DEVBUF); +} + +#ifndef XENHVM + +/* + * In HV mode, we let acpi take care of halts and reboots. + */ + +static void +xen_shutdown_final(void *arg, int howto) +{ + + if (howto & (RB_HALT | RB_POWEROFF)) + HYPERVISOR_shutdown(SHUTDOWN_poweroff); + else + HYPERVISOR_shutdown(SHUTDOWN_reboot); +} + +#endif + +static struct xenbus_watch shutdown_watch = { + .node = "control/shutdown", + .callback = shutdown_handler +}; + +static void +setup_shutdown_watcher(void *unused) +{ + + if (register_xenbus_watch(&shutdown_watch)) + printf("Failed to set shutdown watcher\n"); +#ifndef XENHVM + EVENTHANDLER_REGISTER(shutdown_final, xen_shutdown_final, NULL, + SHUTDOWN_PRI_LAST); +#endif +} + +SYSINIT(shutdown, SI_SUB_PSEUDO, SI_ORDER_ANY, setup_shutdown_watcher, NULL); + +#ifndef XENHVM + +extern void xencons_suspend(void); +extern void xencons_resume(void); + +static void +xen_suspend() +{ + int i, j, k, fpp; + unsigned long max_pfn, start_info_mfn; + +#ifdef SMP + cpumask_t map; + /* + * Bind us to CPU 0 and stop any other VCPUs. + */ + mtx_lock_spin(&sched_lock); + sched_bind(curthread, 0); + mtx_unlock_spin(&sched_lock); + KASSERT(PCPU_GET(cpuid) == 0, ("xen_suspend: not running on cpu 0")); + + map = PCPU_GET(other_cpus) & ~stopped_cpus; + if (map) + stop_cpus(map); +#endif + + if (DEVICE_SUSPEND(root_bus) != 0) { + printf("xen_suspend: device_suspend failed\n"); + if (map) + restart_cpus(map); + return; + } + + local_irq_disable(); + + xencons_suspend(); + gnttab_suspend(); + + max_pfn = HYPERVISOR_shared_info->arch.max_pfn; + + void *shared_info = HYPERVISOR_shared_info; + HYPERVISOR_shared_info = NULL; + pmap_kremove((vm_offset_t) shared_info); + PT_UPDATES_FLUSH(); + + xen_start_info->store_mfn = MFNTOPFN(xen_start_info->store_mfn); + xen_start_info->console.domU.mfn = MFNTOPFN(xen_start_info->console.domU.mfn); + + /* + * We'll stop somewhere inside this hypercall. When it returns, + * we'll start resuming after the restore. + */ + start_info_mfn = VTOMFN(xen_start_info); + pmap_suspend(); + HYPERVISOR_suspend(start_info_mfn); + pmap_resume(); + + pmap_kenter_ma((vm_offset_t) shared_info, xen_start_info->shared_info); + HYPERVISOR_shared_info = shared_info; + + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = + VTOMFN(xen_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++; + xen_pfn_to_mfn_frame_list_list[k] = + VTOMFN(xen_pfn_to_mfn_frame_list[k]); + j = 0; + } + xen_pfn_to_mfn_frame_list[k][j] = + VTOMFN(&xen_phys_machine[i]); + } + HYPERVISOR_shared_info->arch.max_pfn = max_pfn; + + gnttab_resume(); + irq_resume(); + local_irq_enable(); + xencons_resume(); + +#ifdef CONFIG_SMP + for_each_cpu(i) + vcpu_prepare(i); + +#endif + /* + * Only resume xenbus /after/ we've prepared our VCPUs; otherwise + * the VCPU hotplug callback can race with our vcpu_prepare + */ + DEVICE_RESUME(root_bus); + +#ifdef SMP + sched_unbind(curthread); + if (map) + restart_cpus(map); +#endif +} + +#endif diff --git a/sys/xen/xen_intr.h b/sys/xen/xen_intr.h index 528fa7f..68f5943 100644 --- a/sys/xen/xen_intr.h +++ b/sys/xen/xen_intr.h @@ -29,37 +29,63 @@ #define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE) #define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE) -/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */ -extern void unbind_from_irq(int irq); +/* + * Dynamic binding of event channels and VIRQ sources to guest IRQ space. + */ +/* + * Bind a caller port event channel to an interrupt handler. If + * successful, the guest IRQ number is returned in *irqp. Return zero + * on success or errno otherwise. + */ extern int bind_caller_port_to_irqhandler(unsigned int caller_port, const char *devname, driver_intr_t handler, void *arg, unsigned long irqflags, unsigned int *irqp); + +/* + * Bind a listening port to an interrupt handler. If successful, the + * guest IRQ number is returned in *irqp. Return zero on success or + * errno otherwise. + */ extern int bind_listening_port_to_irqhandler(unsigned int remote_domain, - const char *devname, driver_intr_t handler, void *arg, unsigned long irqflags, - unsigned int *irqp); + const char *devname, driver_intr_t handler, void *arg, + unsigned long irqflags, unsigned int *irqp); + +/* + * Bind a VIRQ to an interrupt handler. If successful, the guest IRQ + * number is returned in *irqp. Return zero on success or errno + * otherwise. + */ extern int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, const char *devname, driver_filter_t filter, driver_intr_t handler, void *arg, unsigned long irqflags, unsigned int *irqp); -extern int bind_ipi_to_irqhandler(unsigned int ipi, - unsigned int cpu, - const char *devname, - driver_filter_t handler, - unsigned long irqflags, - unsigned int *irqp); -extern int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, - unsigned int remote_port, - const char *devname, - driver_filter_t filter, - driver_intr_t handler, - unsigned long irqflags, - unsigned int *irqp); +/* + * Bind an IPI to an interrupt handler. If successful, the guest + * IRQ number is returned in *irqp. Return zero on success or errno + * otherwise. + */ +extern int bind_ipi_to_irqhandler(unsigned int ipi, unsigned int cpu, + const char *devname, driver_filter_t filter, + unsigned long irqflags, unsigned int *irqp); +/* + * Bind an interdomain event channel to an interrupt handler. If + * successful, the guest IRQ number is returned in *irqp. Return zero + * on success or errno otherwise. + */ +extern int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, + unsigned int remote_port, const char *devname, + driver_filter_t filter, driver_intr_t handler, + unsigned long irqflags, unsigned int *irqp); +/* + * Unbind an interrupt handler using the guest IRQ number returned + * when it was bound. + */ +extern void unbind_from_irqhandler(unsigned int irq); -extern void unbind_from_irqhandler(unsigned int evtchn); -static __inline__ int irq_cannonicalize(int irq) +static __inline__ int irq_cannonicalize(unsigned int irq) { return (irq == 2) ? 9 : irq; } diff --git a/sys/xen/xenbus/xenbus_probe.c b/sys/xen/xenbus/xenbus_probe.c index 3d2cb4b..f04f8ec 100644 --- a/sys/xen/xenbus/xenbus_probe.c +++ b/sys/xen/xenbus/xenbus_probe.c @@ -565,7 +565,6 @@ xenbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value) return (ENOENT); } -SYSCTL_DECL(_dev); SYSCTL_NODE(_dev, OID_AUTO, xen, CTLFLAG_RD, NULL, "Xen"); SYSCTL_INT(_dev_xen, OID_AUTO, xsd_port, CTLFLAG_RD, &xen_store_evtchn, 0, ""); SYSCTL_ULONG(_dev_xen, OID_AUTO, xsd_kva, CTLFLAG_RD, (u_long *) &xen_store, 0, ""); diff --git a/sys/xen/xenbus/xenbus_xs.c b/sys/xen/xenbus/xenbus_xs.c index 9e0f779..8069556 100644 --- a/sys/xen/xenbus/xenbus_xs.c +++ b/sys/xen/xenbus/xenbus_xs.c @@ -142,21 +142,17 @@ xs_read_reply(enum xsd_sockmsg_type *type, unsigned int *len, void **result) mtx_lock(&xs_state.reply_lock); while (TAILQ_EMPTY(&xs_state.reply_list)) { - while (TAILQ_EMPTY(&xs_state.reply_list)) { - error = mtx_sleep(&xs_state.reply_waitq, - &xs_state.reply_lock, - PCATCH, "xswait", hz/10); - if (error && error != EWOULDBLOCK) { - mtx_unlock(&xs_state.reply_lock); - return (error); - } - + while (TAILQ_EMPTY(&xs_state.reply_list)) { + error = mtx_sleep(&xs_state.reply_waitq, + &xs_state.reply_lock, + PCATCH, "xswait", hz/10); + if (error && error != EWOULDBLOCK) { + mtx_unlock(&xs_state.reply_lock); + return (error); } - - } + } - msg = TAILQ_FIRST(&xs_state.reply_list); TAILQ_REMOVE(&xs_state.reply_list, msg, list); @@ -202,7 +198,8 @@ xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void **result) sx_xlock(&xs_state.request_mutex); - error = xb_write(msg, sizeof(*msg) + msg->len, &xs_state.request_mutex.lock_object); + error = xb_write(msg, sizeof(*msg) + msg->len, + &xs_state.request_mutex.lock_object); if (error) { msg->type = XS_ERROR; } else { @@ -243,7 +240,8 @@ xs_talkv(struct xenbus_transaction t, enum xsd_sockmsg_type type, sx_xlock(&xs_state.request_mutex); - error = xb_write(&msg, sizeof(msg), &xs_state.request_mutex.lock_object); + error = xb_write(&msg, sizeof(msg), + &xs_state.request_mutex.lock_object); if (error) { sx_xunlock(&xs_state.request_mutex); printf("xs_talkv failed %d\n", error); @@ -251,7 +249,8 @@ xs_talkv(struct xenbus_transaction t, enum xsd_sockmsg_type type, } for (i = 0; i < num_vecs; i++) { - error = xb_write(iovec[i].iov_base, iovec[i].iov_len, &xs_state.request_mutex.lock_object); + error = xb_write(iovec[i].iov_base, iovec[i].iov_len, + &xs_state.request_mutex.lock_object); if (error) { sx_xunlock(&xs_state.request_mutex); printf("xs_talkv failed %d\n", error); @@ -791,7 +790,8 @@ xs_process_msg(enum xsd_sockmsg_type *type) msg = malloc(sizeof(*msg), M_DEVBUF, M_WAITOK); mtx_lock(&xs_state.reply_lock); - error = xb_read(&msg->hdr, sizeof(msg->hdr), &xs_state.reply_lock.lock_object); + error = xb_read(&msg->hdr, sizeof(msg->hdr), + &xs_state.reply_lock.lock_object); mtx_unlock(&xs_state.reply_lock); if (error) { free(msg, M_DEVBUF); @@ -800,7 +800,8 @@ xs_process_msg(enum xsd_sockmsg_type *type) body = malloc(msg->hdr.len + 1, M_DEVBUF, M_WAITOK); mtx_lock(&xs_state.reply_lock); - error = xb_read(body, msg->hdr.len, &xs_state.reply_lock.lock_object); + error = xb_read(body, msg->hdr.len, + &xs_state.reply_lock.lock_object); mtx_unlock(&xs_state.reply_lock); if (error) { free(body, M_DEVBUF); |