[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User Isaku Yamahata <yamahata@xxxxxxxxxxxxx> # Date 1223608006 -32400 # Node ID c2fc4d26ef18b53b19c4ca03a836b1b75143d158 # Parent af8eaa3cf78200568bdfd7e7d87a546c53e6bd7b # Parent 6ab55f716ce3c7a8d52fcb1211491954635a2d1d merge with xen-unstable.hg --- buildconfigs/mk.linux-2.6-common | 4 tools/firmware/hvmloader/smbios.c | 79 +++++---- tools/flask/policy/policy/modules/xen/xen.te | 5 tools/misc/xenpm.c | 2 tools/pygrub/src/LiloConf.py | 6 tools/python/xen/util/xsm/flask/flask.py | 5 tools/python/xen/xend/XendDomainInfo.py | 2 tools/python/xen/xend/image.py | 2 xen/arch/x86/domain.c | 1 xen/arch/x86/hvm/svm/intr.c | 5 xen/arch/x86/hvm/vmsi.c | 2 xen/arch/x86/hvm/vmx/intr.c | 15 - xen/arch/x86/i8259.c | 4 xen/arch/x86/io_apic.c | 50 +++-- xen/arch/x86/irq.c | 180 ++++++++++++++++++++ xen/arch/x86/mm.c | 2 xen/arch/x86/pci.c | 61 ------- xen/arch/x86/physdev.c | 208 +++--------------------- xen/arch/x86/x86_32/xen.lds.S | 1 xen/arch/x86/x86_64/xen.lds.S | 1 xen/common/event_channel.c | 88 +++++----- xen/drivers/Makefile | 1 xen/drivers/passthrough/io.c | 182 ++++++++++++--------- xen/drivers/passthrough/pci.c | 14 - xen/drivers/passthrough/vtd/intremap.c | 10 - xen/drivers/passthrough/vtd/vtd.h | 37 ++++ xen/drivers/passthrough/vtd/x86/vtd.c | 26 +-- xen/drivers/pci/Makefile | 1 xen/drivers/pci/pci.c | 64 +++++++ xen/include/asm-x86/domain.h | 2 xen/include/asm-x86/hvm/irq.h | 6 xen/include/asm-x86/io_apic.h | 1 xen/include/asm-x86/irq.h | 10 + xen/include/xen/irq.h | 2 xen/include/xen/sched.h | 2 xen/xsm/acm/acm_simple_type_enforcement_hooks.c | 8 36 files changed, 628 insertions(+), 461 deletions(-) diff -r af8eaa3cf782 -r c2fc4d26ef18 buildconfigs/mk.linux-2.6-common --- a/buildconfigs/mk.linux-2.6-common Fri Oct 10 11:58:03 2008 +0900 +++ b/buildconfigs/mk.linux-2.6-common Fri Oct 10 12:06:46 2008 +0900 @@ -75,7 +75,9 @@ endif # tree. Finally attempt to use make defconfig. set -e ; \ CONFIG_VERSION=$$(sed -ne 's/$$(XENGUEST)//; s/^EXTRAVERSION = //p' $(LINUX_SRCDIR)/Makefile); \ - if [ -r $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) ] ; then \ + if [ ! -z "$(XEN_LINUX_CONFIG)" -a -r $(XEN_LINUX_CONFIG) ]; then \ + cp $(XEN_LINUX_CONFIG) $(CONFIG_FILE); \ + elif [ -r $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) ] ; then \ cp $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) $(CONFIG_FILE) ; \ elif [ -e $(LINUX_SRCDIR)/buildconfigs/create_config.sh ] ; then \ cd $(LINUX_SRCDIR) && sh buildconfigs/create_config.sh \ diff -r af8eaa3cf782 -r c2fc4d26ef18 tools/firmware/hvmloader/smbios.c --- a/tools/firmware/hvmloader/smbios.c Fri Oct 10 11:58:03 2008 +0900 +++ b/tools/firmware/hvmloader/smbios.c Fri Oct 10 12:06:46 2008 +0900 @@ -54,13 +54,13 @@ smbios_type_4_init(void *start, unsigned smbios_type_4_init(void *start, unsigned int cpu_number, char *cpu_manufacturer); static void * -smbios_type_16_init(void *start, uint32_t memory_size_mb); -static void * -smbios_type_17_init(void *start, uint32_t memory_size_mb); -static void * -smbios_type_19_init(void *start, uint32_t memory_size_mb); -static void * -smbios_type_20_init(void *start, uint32_t memory_size_mb); +smbios_type_16_init(void *start, uint32_t memory_size_mb, int nr_mem_devs); +static void * +smbios_type_17_init(void *start, uint32_t memory_size_mb, int instance); +static void * +smbios_type_19_init(void *start, uint32_t memory_size_mb, int instance); +static void * +smbios_type_20_init(void *start, uint32_t memory_size_mb, int instance); static void * smbios_type_32_init(void *start); static void * @@ -92,6 +92,7 @@ write_smbios_tables(void *start, unsigned cpu_num, nr_structs = 0, max_struct_size = 0; char *p, *q; char cpu_manufacturer[15]; + int i, nr_mem_devs; get_cpu_manufacturer(cpu_manufacturer, 15); @@ -111,10 +112,19 @@ write_smbios_tables(void *start, do_struct(smbios_type_3_init(p)); for ( cpu_num = 1; cpu_num <= vcpus; cpu_num++ ) do_struct(smbios_type_4_init(p, cpu_num, cpu_manufacturer)); - do_struct(smbios_type_16_init(p, memsize)); - do_struct(smbios_type_17_init(p, memsize)); - do_struct(smbios_type_19_init(p, memsize)); - do_struct(smbios_type_20_init(p, memsize)); + + /* Each 'memory device' covers up to 16GB of address space. */ + nr_mem_devs = (memsize + 0x3fff) >> 14; + do_struct(smbios_type_16_init(p, memsize, nr_mem_devs)); + for ( i = 0; i < nr_mem_devs; i++ ) + { + uint32_t dev_memsize = ((i == (nr_mem_devs - 1)) + ? (memsize & 0x3fff) : 0x4000); + do_struct(smbios_type_17_init(p, dev_memsize, i)); + do_struct(smbios_type_19_init(p, dev_memsize, i)); + do_struct(smbios_type_20_init(p, dev_memsize, i)); + } + do_struct(smbios_type_32_init(p)); do_struct(smbios_type_127_init(p)); @@ -441,7 +451,7 @@ smbios_type_4_init( /* Type 16 -- Physical Memory Array */ static void * -smbios_type_16_init(void *start, uint32_t memsize) +smbios_type_16_init(void *start, uint32_t memsize, int nr_mem_devs) { struct smbios_type_16 *p = (struct smbios_type_16*)start; @@ -456,7 +466,7 @@ smbios_type_16_init(void *start, uint32_ p->error_correction = 0x01; /* other */ p->maximum_capacity = memsize * 1024; p->memory_error_information_handle = 0xfffe; /* none provided */ - p->number_of_memory_devices = 1; + p->number_of_memory_devices = nr_mem_devs; start += sizeof(struct smbios_type_16); *((uint16_t *)start) = 0; @@ -465,22 +475,22 @@ smbios_type_16_init(void *start, uint32_ /* Type 17 -- Memory Device */ static void * -smbios_type_17_init(void *start, uint32_t memory_size_mb) -{ +smbios_type_17_init(void *start, uint32_t memory_size_mb, int instance) +{ + char buf[16]; struct smbios_type_17 *p = (struct smbios_type_17 *)start; memset(p, 0, sizeof(*p)); p->header.type = 17; p->header.length = sizeof(struct smbios_type_17); - p->header.handle = 0x1100; + p->header.handle = 0x1100 + instance; p->physical_memory_array_handle = 0x1000; p->total_width = 64; p->data_width = 64; - /* truncate memory_size_mb to 16 bits and clear most significant - bit [indicates size in MB] */ - p->size = (uint16_t) memory_size_mb & 0x7fff; + ASSERT((memory_size_mb & ~0x7fff) == 0); + p->size = memory_size_mb; p->form_factor = 0x09; /* DIMM */ p->device_set = 0; p->device_locator_str = 1; @@ -489,8 +499,11 @@ smbios_type_17_init(void *start, uint32_ p->type_detail = 0; start += sizeof(struct smbios_type_17); - strcpy((char *)start, "DIMM 1"); - start += strlen("DIMM 1") + 1; + strcpy(start, "DIMM "); + start += strlen("DIMM "); + itoa(buf, instance); + strcpy(start, buf); + start += strlen(buf) + 1; *((uint8_t *)start) = 0; return start+1; @@ -498,7 +511,7 @@ smbios_type_17_init(void *start, uint32_ /* Type 19 -- Memory Array Mapped Address */ static void * -smbios_type_19_init(void *start, uint32_t memory_size_mb) +smbios_type_19_init(void *start, uint32_t memory_size_mb, int instance) { struct smbios_type_19 *p = (struct smbios_type_19 *)start; @@ -506,10 +519,10 @@ smbios_type_19_init(void *start, uint32_ p->header.type = 19; p->header.length = sizeof(struct smbios_type_19); - p->header.handle = 0x1300; - - p->starting_address = 0; - p->ending_address = (memory_size_mb-1) * 1024; + p->header.handle = 0x1300 + instance; + + p->starting_address = instance << 24; + p->ending_address = p->starting_address + (memory_size_mb << 10) - 1; p->memory_array_handle = 0x1000; p->partition_width = 1; @@ -520,7 +533,7 @@ smbios_type_19_init(void *start, uint32_ /* Type 20 -- Memory Device Mapped Address */ static void * -smbios_type_20_init(void *start, uint32_t memory_size_mb) +smbios_type_20_init(void *start, uint32_t memory_size_mb, int instance) { struct smbios_type_20 *p = (struct smbios_type_20 *)start; @@ -528,12 +541,12 @@ smbios_type_20_init(void *start, uint32_ p->header.type = 20; p->header.length = sizeof(struct smbios_type_20); - p->header.handle = 0x1400; - - p->starting_address = 0; - p->ending_address = (memory_size_mb-1)*1024; - p->memory_device_handle = 0x1100; - p->memory_array_mapped_address_handle = 0x1300; + p->header.handle = 0x1400 + instance; + + p->starting_address = instance << 24; + p->ending_address = p->starting_address + (memory_size_mb << 10) - 1; + p->memory_device_handle = 0x1100 + instance; + p->memory_array_mapped_address_handle = 0x1300 + instance; p->partition_row_position = 1; p->interleave_position = 0; p->interleaved_data_depth = 0; diff -r af8eaa3cf782 -r c2fc4d26ef18 tools/flask/policy/policy/modules/xen/xen.te --- a/tools/flask/policy/policy/modules/xen/xen.te Fri Oct 10 11:58:03 2008 +0900 +++ b/tools/flask/policy/policy/modules/xen/xen.te Fri Oct 10 12:06:46 2008 +0900 @@ -33,7 +33,7 @@ define(`create_domain', ` getvcpuinfo getaddrsize getvcpuaffinity}; allow $1 $2:shadow {enable}; allow $1 $2:mmu {map_read map_write memorymap adjust pinpage}; - allow $2 $2:mmu {map_read map_write pinpage}; + allow $2 $2:mmu {map_read map_write adjust pinpage}; allow $2 domio_t:mmu {map_read}; allow $2 $2:grant {query setup}; allow $1 $2:grant {map_read unmap}; @@ -110,6 +110,9 @@ create_channel(domU_t, dom0_t, evchnU-0_ create_channel(domU_t, dom0_t, evchnU-0_t) allow domU_t evchnU-0_t:event {send}; +allow dom0_t dom0_t:event {send}; +allow dom0_t domU_t:grant {copy}; + manage_domain(dom0_t, domU_t) ################################################################################ diff -r af8eaa3cf782 -r c2fc4d26ef18 tools/misc/xenpm.c --- a/tools/misc/xenpm.c Fri Oct 10 11:58:03 2008 +0900 +++ b/tools/misc/xenpm.c Fri Oct 10 12:06:46 2008 +0900 @@ -161,7 +161,7 @@ int main(int argc, char **argv) break; } - ret = xc_pm_get_pxstat(xc_fd, 0, pxstat); + ret = xc_pm_get_pxstat(xc_fd, i, pxstat); if( ret ) { fprintf(stderr, "failed to get P-states statistics information\n"); free(pxstat->trans_pt); diff -r af8eaa3cf782 -r c2fc4d26ef18 tools/pygrub/src/LiloConf.py --- a/tools/pygrub/src/LiloConf.py Fri Oct 10 11:58:03 2008 +0900 +++ b/tools/pygrub/src/LiloConf.py Fri Oct 10 12:06:46 2008 +0900 @@ -142,7 +142,7 @@ class LiloConfigFile(object): self.images.append(image) def _get_default(self): - for i in range(0, len(self.images) - 1): + for i in range(len(self.images)): if self.images[i].title == self._default: return i return 0 @@ -150,8 +150,8 @@ class LiloConfigFile(object): self._default = val default = property(_get_default, _set_default) - commands = { "default": "self.default", - "timeout": "self.timeout", + commands = { "default": "default", + "timeout": "timeout", "prompt": None, "relocatable": None, } diff -r af8eaa3cf782 -r c2fc4d26ef18 tools/python/xen/util/xsm/flask/flask.py --- a/tools/python/xen/util/xsm/flask/flask.py Fri Oct 10 11:58:03 2008 +0900 +++ b/tools/python/xen/util/xsm/flask/flask.py Fri Oct 10 12:06:46 2008 +0900 @@ -35,7 +35,10 @@ def calc_dom_ssidref_from_info(info): return ssidref def set_security_label(policy, label): - return label + if label: + return label + else: + return "" def ssidref2security_label(ssidref): label = ssidref2label(ssidref) diff -r af8eaa3cf782 -r c2fc4d26ef18 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Fri Oct 10 11:58:03 2008 +0900 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Oct 10 12:06:46 2008 +0900 @@ -1303,7 +1303,7 @@ class XendDomainInfo: t.mkdir() t.set_permissions({'dom' : self.domid, 'read' : True}) t.write('vm', self.vmpath) - for i in [ 'device', 'control', 'error' ]: + for i in [ 'device', 'control', 'error', 'memory' ]: t.mkdir(i) t.set_permissions(i, {'dom' : self.domid}) diff -r af8eaa3cf782 -r c2fc4d26ef18 tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Fri Oct 10 11:58:03 2008 +0900 +++ b/tools/python/xen/xend/image.py Fri Oct 10 12:06:46 2008 +0900 @@ -502,7 +502,7 @@ class ImageHandler: if fifo_fd >= 0: self._openSentinel(sentinel_path_fifo) os.close(fifo_fd) - self.pid = self.vm._gatherDom(('image/device-model-pid', int)) + self.pid = self.vm.gatherDom(('image/device-model-pid', int)) log.debug("%s device model rediscovered, pid %s sentinel fifo %s", name, self.pid, sentinel_path_fifo) self.sentinel_thread = thread.start_new_thread(self._sentinel_watch,()) diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/domain.c Fri Oct 10 12:06:46 2008 +0900 @@ -459,6 +459,7 @@ void arch_domain_destroy(struct domain * hvm_domain_destroy(d); pci_release_devices(d); + free_domain_pirqs(d); if ( !is_idle_domain(d) ) iommu_domain_destroy(d); diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/hvm/svm/intr.c --- a/xen/arch/x86/hvm/svm/intr.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/hvm/svm/intr.c Fri Oct 10 12:06:46 2008 +0900 @@ -124,9 +124,11 @@ static void svm_dirq_assist(struct vcpu if ( !test_and_clear_bit(irq, &hvm_irq_dpci->dirq_mask) ) continue; + spin_lock(&d->event_lock); if ( test_bit(_HVM_IRQ_DPCI_MSI, &hvm_irq_dpci->mirq[irq].flags) ) { hvm_pci_msi_assert(d, irq); + spin_unlock(&d->event_lock); continue; } @@ -137,9 +139,7 @@ static void svm_dirq_assist(struct vcpu device = digl->device; intx = digl->intx; hvm_pci_intx_assert(d, device, intx); - spin_lock(&hvm_irq_dpci->dirq_lock); hvm_irq_dpci->mirq[irq].pending++; - spin_unlock(&hvm_irq_dpci->dirq_lock); } /* @@ -151,6 +151,7 @@ static void svm_dirq_assist(struct vcpu */ set_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, irq)], NOW() + PT_IRQ_TIME_OUT); + spin_unlock(&d->event_lock); } } diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/hvm/vmsi.c --- a/xen/arch/x86/hvm/vmsi.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/hvm/vmsi.c Fri Oct 10 12:06:46 2008 +0900 @@ -134,7 +134,7 @@ int vmsi_deliver(struct domain *d, int p "vector=%x trig_mode=%x\n", dest, dest_mode, delivery_mode, vector, trig_mode); - if ( !(hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_MSI) ) + if ( !test_bit(_HVM_IRQ_DPCI_MSI, &hvm_irq_dpci->mirq[pirq].flags) ) { gdprintk(XENLOG_WARNING, "pirq %x not msi \n", pirq); return 0; diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/hvm/vmx/intr.c --- a/xen/arch/x86/hvm/vmx/intr.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/hvm/vmx/intr.c Fri Oct 10 12:06:46 2008 +0900 @@ -127,11 +127,13 @@ static void vmx_dirq_assist(struct vcpu if ( !test_and_clear_bit(irq, &hvm_irq_dpci->dirq_mask) ) continue; - if ( test_bit(_HVM_IRQ_DPCI_MSI, &hvm_irq_dpci->mirq[irq].flags) ) - { - hvm_pci_msi_assert(d, irq); - continue; - } + spin_lock(&d->event_lock); + if ( test_bit(_HVM_IRQ_DPCI_MSI, &hvm_irq_dpci->mirq[irq].flags) ) + { + hvm_pci_msi_assert(d, irq); + spin_unlock(&d->event_lock); + continue; + } stop_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, irq)]); @@ -140,9 +142,7 @@ static void vmx_dirq_assist(struct vcpu device = digl->device; intx = digl->intx; hvm_pci_intx_assert(d, device, intx); - spin_lock(&hvm_irq_dpci->dirq_lock); hvm_irq_dpci->mirq[irq].pending++; - spin_unlock(&hvm_irq_dpci->dirq_lock); } /* @@ -154,6 +154,7 @@ static void vmx_dirq_assist(struct vcpu */ set_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, irq)], NOW() + PT_IRQ_TIME_OUT); + spin_unlock(&d->event_lock); } } diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/i8259.c --- a/xen/arch/x86/i8259.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/i8259.c Fri Oct 10 12:06:46 2008 +0900 @@ -408,6 +408,10 @@ void __init init_IRQ(void) irq_desc[LEGACY_VECTOR(i)].handler = &i8259A_irq_type; } + /* Never allocate the hypercall vector or Linux/BSD fast-trap vector. */ + vector_irq[HYPERCALL_VECTOR] = NEVER_ASSIGN; + vector_irq[0x80] = NEVER_ASSIGN; + apic_intr_init(); /* Set the clock to HZ Hz */ diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/io_apic.c --- a/xen/arch/x86/io_apic.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/io_apic.c Fri Oct 10 12:06:46 2008 +0900 @@ -87,7 +87,8 @@ static struct irq_pin_list { } irq_2_pin[PIN_MAP_SIZE]; static int irq_2_pin_free_entry = NR_IRQS; -int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1}; +int vector_irq[NR_VECTORS] __read_mostly = { + [0 ... NR_VECTORS - 1] = FREE_TO_ASSIGN}; /* * The common case is 1:1 IRQ<->pin mappings. Sometimes there are @@ -666,40 +667,47 @@ static inline int IO_APIC_irq_trigger(in /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ u8 irq_vector[NR_IRQ_VECTORS] __read_mostly; +int free_irq_vector(int vector) +{ + int irq; + + BUG_ON((vector > LAST_DYNAMIC_VECTOR) || (vector < FIRST_DYNAMIC_VECTOR)); + + spin_lock(&vector_lock); + if ((irq = vector_irq[vector]) == AUTO_ASSIGN) + vector_irq[vector] = FREE_TO_ASSIGN; + spin_unlock(&vector_lock); + + return (irq == AUTO_ASSIGN) ? 0 : -EINVAL; +} + int assign_irq_vector(int irq) { - static unsigned current_vector = FIRST_DYNAMIC_VECTOR, offset = 0; + static unsigned current_vector = FIRST_DYNAMIC_VECTOR; unsigned vector; BUG_ON(irq >= NR_IRQ_VECTORS); + spin_lock(&vector_lock); - if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) { + if ((irq != AUTO_ASSIGN) && (IO_APIC_VECTOR(irq) > 0)) { spin_unlock(&vector_lock); return IO_APIC_VECTOR(irq); } -next: - current_vector += 8; - - /* Skip the hypercall vector. */ - if (current_vector == HYPERCALL_VECTOR) - goto next; - - /* Skip the Linux/BSD fast-trap vector. */ - if (current_vector == 0x80) - goto next; - - if (current_vector > LAST_DYNAMIC_VECTOR) { - offset++; - if (!(offset%8)) { + vector = current_vector; + while (vector_irq[vector] != FREE_TO_ASSIGN) { + vector += 8; + if (vector > LAST_DYNAMIC_VECTOR) + vector = FIRST_DYNAMIC_VECTOR + ((vector + 1) & 7); + + if (vector == current_vector) { spin_unlock(&vector_lock); return -ENOSPC; } - current_vector = FIRST_DYNAMIC_VECTOR + offset; - } - - vector = current_vector; + } + + current_vector = vector; vector_irq[vector] = irq; if (irq != AUTO_ASSIGN) IO_APIC_VECTOR(irq) = vector; diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/irq.c --- a/xen/arch/x86/irq.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/irq.c Fri Oct 10 12:06:46 2008 +0900 @@ -14,8 +14,11 @@ #include <xen/sched.h> #include <xen/keyhandler.h> #include <xen/compat.h> +#include <xen/iocap.h> +#include <xen/iommu.h> +#include <asm/msi.h> #include <asm/current.h> -#include <xen/iommu.h> +#include <public/physdev.h> /* opt_noirqbalance: If true, software IRQ balancing/affinity is disabled. */ int opt_noirqbalance = 0; @@ -282,7 +285,7 @@ static void __do_IRQ_guest(int vector) * The descriptor is returned locked. This function is safe against changes * to the per-domain irq-to-vector mapping. */ -static irq_desc_t *domain_spin_lock_irq_desc( +irq_desc_t *domain_spin_lock_irq_desc( struct domain *d, int irq, unsigned long *pflags) { unsigned int vector; @@ -511,7 +514,7 @@ int pirq_guest_bind(struct vcpu *v, int int rc = 0; cpumask_t cpumask = CPU_MASK_NONE; - WARN_ON(!spin_is_locked(&v->domain->evtchn_lock)); + WARN_ON(!spin_is_locked(&v->domain->event_lock)); BUG_ON(!local_irq_is_enabled()); retry: @@ -681,7 +684,7 @@ void pirq_guest_unbind(struct domain *d, irq_desc_t *desc; int vector; - WARN_ON(!spin_is_locked(&d->evtchn_lock)); + WARN_ON(!spin_is_locked(&d->event_lock)); BUG_ON(!local_irq_is_enabled()); desc = domain_spin_lock_irq_desc(d, irq, NULL); @@ -708,7 +711,7 @@ int pirq_guest_force_unbind(struct domai irq_guest_action_t *action; int i, bound = 0; - WARN_ON(!spin_is_locked(&d->evtchn_lock)); + WARN_ON(!spin_is_locked(&d->event_lock)); BUG_ON(!local_irq_is_enabled()); desc = domain_spin_lock_irq_desc(d, irq, NULL); @@ -729,6 +732,173 @@ int pirq_guest_force_unbind(struct domai out: spin_unlock_irq(&desc->lock); return bound; +} + +int get_free_pirq(struct domain *d, int type, int index) +{ + int i; + + ASSERT(spin_is_locked(&d->event_lock)); + + if ( type == MAP_PIRQ_TYPE_GSI ) + { + for ( i = 16; i < NR_PIRQS; i++ ) + if ( !d->arch.pirq_vector[i] ) + break; + if ( i == NR_PIRQS ) + return -ENOSPC; + } + else + { + for ( i = NR_PIRQS - 1; i >= 16; i-- ) + if ( !d->arch.pirq_vector[i] ) + break; + if ( i == 16 ) + return -ENOSPC; + } + + return i; +} + +int map_domain_pirq( + struct domain *d, int pirq, int vector, int type, void *data) +{ + int ret = 0; + int old_vector, old_pirq; + irq_desc_t *desc; + unsigned long flags; + + ASSERT(spin_is_locked(&d->event_lock)); + + if ( !IS_PRIV(current->domain) ) + return -EPERM; + + if ( pirq < 0 || pirq >= NR_PIRQS || vector < 0 || vector >= NR_VECTORS ) + { + dprintk(XENLOG_G_ERR, "dom%d: invalid pirq %d or vector %d\n", + d->domain_id, pirq, vector); + return -EINVAL; + } + + old_vector = d->arch.pirq_vector[pirq]; + old_pirq = d->arch.vector_pirq[vector]; + + if ( (old_vector && (old_vector != vector) ) || + (old_pirq && (old_pirq != pirq)) ) + { + dprintk(XENLOG_G_ERR, "dom%d: pirq %d or vector %d already mapped\n", + d->domain_id, pirq, vector); + return -EINVAL; + } + + ret = irq_permit_access(d, pirq); + if ( ret ) + { + dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d\n", + d->domain_id, pirq); + return ret; + } + + desc = &irq_desc[vector]; + spin_lock_irqsave(&desc->lock, flags); + + if ( type == MAP_PIRQ_TYPE_MSI ) + { + struct msi_info *msi = (struct msi_info *)data; + if ( desc->handler != &no_irq_type ) + dprintk(XENLOG_G_ERR, "dom%d: vector %d in use\n", + d->domain_id, vector); + desc->handler = &pci_msi_type; + ret = pci_enable_msi(msi); + if ( ret ) + goto done; + } + + d->arch.pirq_vector[pirq] = vector; + d->arch.vector_pirq[vector] = pirq; + +done: + spin_unlock_irqrestore(&desc->lock, flags); + return ret; +} + +/* The pirq should have been unbound before this call. */ +int unmap_domain_pirq(struct domain *d, int pirq) +{ + unsigned long flags; + irq_desc_t *desc; + int vector, ret = 0; + bool_t forced_unbind; + + if ( (pirq < 0) || (pirq >= NR_PIRQS) ) + return -EINVAL; + + if ( !IS_PRIV(current->domain) ) + return -EINVAL; + + ASSERT(spin_is_locked(&d->event_lock)); + + vector = d->arch.pirq_vector[pirq]; + if ( vector <= 0 ) + { + dprintk(XENLOG_G_ERR, "dom%d: pirq %d not mapped\n", + d->domain_id, pirq); + ret = -EINVAL; + goto done; + } + + forced_unbind = pirq_guest_force_unbind(d, pirq); + if ( forced_unbind ) + dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n", + d->domain_id, pirq); + + desc = &irq_desc[vector]; + spin_lock_irqsave(&desc->lock, flags); + + BUG_ON(vector != d->arch.pirq_vector[pirq]); + + if ( desc->msi_desc ) + pci_disable_msi(vector); + + if ( desc->handler == &pci_msi_type ) + { + desc->handler = &no_irq_type; + free_irq_vector(vector); + } + + if ( !forced_unbind ) + { + d->arch.pirq_vector[pirq] = 0; + d->arch.vector_pirq[vector] = 0; + } + else + { + d->arch.pirq_vector[pirq] = -vector; + d->arch.vector_pirq[vector] = -pirq; + } + + spin_unlock_irqrestore(&desc->lock, flags); + + ret = irq_deny_access(d, pirq); + if ( ret ) + dprintk(XENLOG_G_ERR, "dom%d: could not deny access to irq %d\n", + d->domain_id, pirq); + + done: + return ret; +} + +void free_domain_pirqs(struct domain *d) +{ + int i; + + spin_lock(&d->event_lock); + + for ( i = 0; i < NR_PIRQS; i++ ) + if ( d->arch.pirq_vector[i] > 0 ) + unmap_domain_pirq(d, i); + + spin_unlock(&d->event_lock); } extern void dump_ioapic_irq_info(void); diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/mm.c Fri Oct 10 12:06:46 2008 +0900 @@ -3067,7 +3067,7 @@ static int destroy_grant_pte_mapping( ol1e = *(l1_pgentry_t *)va; /* Check that the virtual address supplied is actually mapped to frame. */ - if ( unlikely((l1e_get_intpte(ol1e) >> PAGE_SHIFT) != frame) ) + if ( unlikely(l1e_get_pfn(ol1e) != frame) ) { page_unlock(page); MEM_LOG("PTE entry %lx for address %"PRIx64" doesn't match frame %lx", diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/pci.c --- a/xen/arch/x86/pci.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/pci.c Fri Oct 10 12:06:46 2008 +0900 @@ -1,12 +1,9 @@ /****************************************************************************** * pci.c * - * PCI access functions. + * Architecture-dependent PCI access functions. */ -#include <xen/config.h> -#include <xen/pci.h> -#include <xen/pci_regs.h> #include <xen/spinlock.h> #include <asm/io.h> @@ -118,59 +115,3 @@ void pci_conf_write32( pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4, data); } -int pci_find_cap_offset(u8 bus, u8 dev, u8 func, u8 cap) -{ - u8 id; - int max_cap = 48; - u8 pos = PCI_CAPABILITY_LIST; - u16 status; - - status = pci_conf_read16(bus, dev, func, PCI_STATUS); - if ( (status & PCI_STATUS_CAP_LIST) == 0 ) - return 0; - - while ( max_cap-- ) - { - pos = pci_conf_read8(bus, dev, func, pos); - if ( pos < 0x40 ) - break; - - pos &= ~3; - id = pci_conf_read8(bus, dev, func, pos + PCI_CAP_LIST_ID); - - if ( id == 0xff ) - break; - else if ( id == cap ) - return pos; - - pos += PCI_CAP_LIST_NEXT; - } - - return 0; -} - -int pci_find_next_cap(u8 bus, unsigned int devfn, u8 pos, int cap) -{ - u8 id; - int ttl = 48; - - while ( ttl-- ) - { - pos = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos); - if ( pos < 0x40 ) - break; - - pos &= ~3; - id = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), - pos + PCI_CAP_LIST_ID); - - if ( id == 0xff ) - break; - if ( id == cap ) - return pos; - - pos += PCI_CAP_LIST_NEXT; - } - return 0; -} - diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/physdev.c Fri Oct 10 12:06:46 2008 +0900 @@ -26,168 +26,12 @@ ioapic_guest_write( ioapic_guest_write( unsigned long physbase, unsigned int reg, u32 pval); -static int get_free_pirq(struct domain *d, int type, int index) -{ - int i; - - ASSERT(spin_is_locked(&d->evtchn_lock)); - - if ( type == MAP_PIRQ_TYPE_GSI ) - { - for ( i = 16; i < NR_PIRQS; i++ ) - if ( !d->arch.pirq_vector[i] ) - break; - if ( i == NR_PIRQS ) - return -ENOSPC; - } - else - { - for ( i = NR_PIRQS - 1; i >= 16; i-- ) - if ( !d->arch.pirq_vector[i] ) - break; - if ( i == 16 ) - return -ENOSPC; - } - - return i; -} - -static int map_domain_pirq(struct domain *d, int pirq, int vector, - struct physdev_map_pirq *map) -{ - int ret = 0; - int old_vector, old_pirq; - struct msi_info msi; - irq_desc_t *desc; - unsigned long flags; - - ASSERT(spin_is_locked(&d->evtchn_lock)); - - if ( !IS_PRIV(current->domain) ) - return -EPERM; - - if ( pirq < 0 || pirq >= NR_PIRQS || vector < 0 || vector >= NR_VECTORS ) - { - dprintk(XENLOG_G_ERR, "dom%d: invalid pirq %d or vector %d\n", - d->domain_id, pirq, vector); - return -EINVAL; - } - - old_vector = d->arch.pirq_vector[pirq]; - old_pirq = d->arch.vector_pirq[vector]; - - if ( (old_vector && (old_vector != vector) ) || - (old_pirq && (old_pirq != pirq)) ) - { - dprintk(XENLOG_G_ERR, "dom%d: pirq %d or vector %d already mapped\n", - d->domain_id, pirq, vector); - return -EINVAL; - } - - ret = irq_permit_access(d, pirq); - if ( ret ) - { - dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d\n", - d->domain_id, pirq); - return ret; - } - - desc = &irq_desc[vector]; - spin_lock_irqsave(&desc->lock, flags); - - if ( map && MAP_PIRQ_TYPE_MSI == map->type ) - { - if ( desc->handler != &no_irq_type ) - dprintk(XENLOG_G_ERR, "dom%d: vector %d in use\n", - d->domain_id, vector); - desc->handler = &pci_msi_type; - - msi.bus = map->bus; - msi.devfn = map->devfn; - msi.entry_nr = map->entry_nr; - msi.table_base = map->table_base; - msi.vector = vector; - - ret = pci_enable_msi(&msi); - if ( ret ) - goto done; - } - - d->arch.pirq_vector[pirq] = vector; - d->arch.vector_pirq[vector] = pirq; - -done: - spin_unlock_irqrestore(&desc->lock, flags); - return ret; -} - -/* The pirq should have been unbound before this call. */ -static int unmap_domain_pirq(struct domain *d, int pirq) -{ - unsigned long flags; - irq_desc_t *desc; - int vector, ret = 0; - bool_t forced_unbind; - - if ( (pirq < 0) || (pirq >= NR_PIRQS) ) - return -EINVAL; - - if ( !IS_PRIV(current->domain) ) - return -EINVAL; - - ASSERT(spin_is_locked(&d->evtchn_lock)); - - vector = d->arch.pirq_vector[pirq]; - if ( vector <= 0 ) - { - dprintk(XENLOG_G_ERR, "dom%d: pirq %d not mapped\n", - d->domain_id, pirq); - ret = -EINVAL; - goto done; - } - - forced_unbind = pirq_guest_force_unbind(d, pirq); - if ( forced_unbind ) - dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n", - d->domain_id, pirq); - - desc = &irq_desc[vector]; - spin_lock_irqsave(&desc->lock, flags); - - BUG_ON(vector != d->arch.pirq_vector[pirq]); - - if ( desc->msi_desc ) - pci_disable_msi(vector); - - if ( desc->handler == &pci_msi_type ) - desc->handler = &no_irq_type; - - if ( !forced_unbind ) - { - d->arch.pirq_vector[pirq] = 0; - d->arch.vector_pirq[vector] = 0; - } - else - { - d->arch.pirq_vector[pirq] = -vector; - d->arch.vector_pirq[vector] = -pirq; - } - - spin_unlock_irqrestore(&desc->lock, flags); - - ret = irq_deny_access(d, pirq); - if ( ret ) - dprintk(XENLOG_G_ERR, "dom%d: could not deny access to irq %d\n", - d->domain_id, pirq); - - done: - return ret; -} - static int physdev_map_pirq(struct physdev_map_pirq *map) { struct domain *d; int vector, pirq, ret = 0; + struct msi_info _msi; + void *map_data = NULL; if ( !IS_PRIV(current->domain) ) return -EPERM; @@ -206,6 +50,7 @@ static int physdev_map_pirq(struct physd goto free_domain; } + /* Verify or get vector. */ switch ( map->type ) { case MAP_PIRQ_TYPE_GSI: @@ -220,31 +65,42 @@ static int physdev_map_pirq(struct physd if ( !vector ) { dprintk(XENLOG_G_ERR, "dom%d: map irq with no vector %d\n", - d->domain_id, map->index); + d->domain_id, vector); ret = -EINVAL; goto free_domain; } break; + case MAP_PIRQ_TYPE_MSI: vector = map->index; - if ( vector == -1 ) - vector = assign_irq_vector(AUTO_ASSIGN); + if ( vector == -1 ) + vector = assign_irq_vector(AUTO_ASSIGN); if ( vector < 0 || vector >= NR_VECTORS ) { dprintk(XENLOG_G_ERR, "dom%d: map irq with wrong vector %d\n", - d->domain_id, map->index); + d->domain_id, vector); ret = -EINVAL; goto free_domain; } - break; + + _msi.bus = map->bus; + _msi.devfn = map->devfn; + _msi.entry_nr = map->entry_nr; + _msi.table_base = map->table_base; + _msi.vector = vector; + map_data = &_msi; + break; + default: - dprintk(XENLOG_G_ERR, "dom%d: wrong map_pirq type %x\n", d->domain_id, map->type); + dprintk(XENLOG_G_ERR, "dom%d: wrong map_pirq type %x\n", + d->domain_id, map->type); ret = -EINVAL; goto free_domain; } - spin_lock(&d->evtchn_lock); + /* Verify or get pirq. */ + spin_lock(&d->event_lock); if ( map->pirq < 0 ) { if ( d->arch.vector_pirq[vector] ) @@ -284,13 +140,14 @@ static int physdev_map_pirq(struct physd pirq = map->pirq; } - - ret = map_domain_pirq(d, pirq, vector, map); - - if ( !ret ) + ret = map_domain_pirq(d, pirq, vector, map->type, map_data); + if ( ret == 0 ) map->pirq = pirq; + done: - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); + if ( (ret != 0) && (map->type == MAP_PIRQ_TYPE_MSI) && (map->index == -1) ) + free_irq_vector(vector); free_domain: rcu_unlock_domain(d); return ret; @@ -312,9 +169,9 @@ static int physdev_unmap_pirq(struct phy if ( d == NULL ) return -ESRCH; - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); ret = unmap_domain_pirq(d, unmap->pirq); - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); rcu_unlock_domain(d); @@ -441,9 +298,10 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H irq_op.vector = assign_irq_vector(irq); - spin_lock(&dom0->evtchn_lock); - ret = map_domain_pirq(dom0, irq_op.irq, irq_op.vector, NULL); - spin_unlock(&dom0->evtchn_lock); + spin_lock(&dom0->event_lock); + ret = map_domain_pirq(dom0, irq_op.irq, irq_op.vector, + MAP_PIRQ_TYPE_GSI, NULL); + spin_unlock(&dom0->event_lock); if ( copy_to_guest(arg, &irq_op, 1) != 0 ) ret = -EFAULT; diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/x86_32/xen.lds.S --- a/xen/arch/x86/x86_32/xen.lds.S Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/x86_32/xen.lds.S Fri Oct 10 12:06:46 2008 +0900 @@ -69,6 +69,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); __init_end = .; + __per_cpu_shift = PERCPU_SHIFT; /* kdump assist */ __per_cpu_start = .; .data.percpu : { *(.data.percpu) } :text __per_cpu_data_end = .; diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/arch/x86/x86_64/xen.lds.S --- a/xen/arch/x86/x86_64/xen.lds.S Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/arch/x86/x86_64/xen.lds.S Fri Oct 10 12:06:46 2008 +0900 @@ -67,6 +67,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); __init_end = .; + __per_cpu_shift = PERCPU_SHIFT; /* kdump assist */ __per_cpu_start = .; .data.percpu : { *(.data.percpu) } :text __per_cpu_data_end = .; diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/common/event_channel.c --- a/xen/common/event_channel.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/common/event_channel.c Fri Oct 10 12:06:46 2008 +0900 @@ -133,7 +133,7 @@ static long evtchn_alloc_unbound(evtchn_ if ( rc ) return rc; - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); if ( (port = get_free_port(d)) < 0 ) ERROR_EXIT_DOM(port, d); @@ -150,7 +150,7 @@ static long evtchn_alloc_unbound(evtchn_ alloc->port = port; out: - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); rcu_unlock_domain(d); return rc; @@ -174,14 +174,14 @@ static long evtchn_bind_interdomain(evtc /* Avoid deadlock by first acquiring lock of domain with smaller id. */ if ( ld < rd ) { - spin_lock(&ld->evtchn_lock); - spin_lock(&rd->evtchn_lock); + spin_lock(&ld->event_lock); + spin_lock(&rd->event_lock); } else { if ( ld != rd ) - spin_lock(&rd->evtchn_lock); - spin_lock(&ld->evtchn_lock); + spin_lock(&rd->event_lock); + spin_lock(&ld->event_lock); } if ( (lport = get_free_port(ld)) < 0 ) @@ -216,9 +216,9 @@ static long evtchn_bind_interdomain(evtc bind->local_port = lport; out: - spin_unlock(&ld->evtchn_lock); + spin_unlock(&ld->event_lock); if ( ld != rd ) - spin_unlock(&rd->evtchn_lock); + spin_unlock(&rd->event_lock); rcu_unlock_domain(rd); @@ -244,7 +244,7 @@ static long evtchn_bind_virq(evtchn_bind ((v = d->vcpu[vcpu]) == NULL) ) return -ENOENT; - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); if ( v->virq_to_evtchn[virq] != 0 ) ERROR_EXIT(-EEXIST); @@ -260,7 +260,7 @@ static long evtchn_bind_virq(evtchn_bind v->virq_to_evtchn[virq] = bind->port = port; out: - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); return rc; } @@ -277,7 +277,7 @@ static long evtchn_bind_ipi(evtchn_bind_ (d->vcpu[vcpu] == NULL) ) return -ENOENT; - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); if ( (port = get_free_port(d)) < 0 ) ERROR_EXIT(port); @@ -289,7 +289,7 @@ static long evtchn_bind_ipi(evtchn_bind_ bind->port = port; out: - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); return rc; } @@ -308,7 +308,7 @@ static long evtchn_bind_pirq(evtchn_bind if ( !irq_access_permitted(d, pirq) ) return -EPERM; - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); if ( d->pirq_to_evtchn[pirq] != 0 ) ERROR_EXIT(-EEXIST); @@ -333,7 +333,7 @@ static long evtchn_bind_pirq(evtchn_bind bind->port = port; out: - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); return rc; } @@ -348,7 +348,7 @@ static long __evtchn_close(struct domain long rc = 0; again: - spin_lock(&d1->evtchn_lock); + spin_lock(&d1->event_lock); if ( !port_is_valid(d1, port1) ) { @@ -404,12 +404,12 @@ static long __evtchn_close(struct domain if ( d1 < d2 ) { - spin_lock(&d2->evtchn_lock); + spin_lock(&d2->event_lock); } else if ( d1 != d2 ) { - spin_unlock(&d1->evtchn_lock); - spin_lock(&d2->evtchn_lock); + spin_unlock(&d1->event_lock); + spin_lock(&d2->event_lock); goto again; } } @@ -454,11 +454,11 @@ static long __evtchn_close(struct domain if ( d2 != NULL ) { if ( d1 != d2 ) - spin_unlock(&d2->evtchn_lock); + spin_unlock(&d2->event_lock); put_domain(d2); } - spin_unlock(&d1->evtchn_lock); + spin_unlock(&d1->event_lock); return rc; } @@ -476,11 +476,11 @@ int evtchn_send(struct domain *d, unsign struct vcpu *rvcpu; int rport, ret = 0; - spin_lock(&ld->evtchn_lock); + spin_lock(&ld->event_lock); if ( unlikely(!port_is_valid(ld, lport)) ) { - spin_unlock(&ld->evtchn_lock); + spin_unlock(&ld->event_lock); return -EINVAL; } @@ -489,7 +489,7 @@ int evtchn_send(struct domain *d, unsign /* Guest cannot send via a Xen-attached event channel. */ if ( unlikely(lchn->consumer_is_xen) ) { - spin_unlock(&ld->evtchn_lock); + spin_unlock(&ld->event_lock); return -EINVAL; } @@ -527,7 +527,7 @@ int evtchn_send(struct domain *d, unsign } out: - spin_unlock(&ld->evtchn_lock); + spin_unlock(&ld->event_lock); return ret; } @@ -656,7 +656,7 @@ static long evtchn_status(evtchn_status_ if ( rc ) return rc; - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); if ( !port_is_valid(d, port) ) { @@ -704,7 +704,7 @@ static long evtchn_status(evtchn_status_ status->vcpu = chn->notify_vcpu_id; out: - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); rcu_unlock_domain(d); return rc; @@ -720,7 +720,7 @@ long evtchn_bind_vcpu(unsigned int port, if ( (vcpu_id >= ARRAY_SIZE(d->vcpu)) || (d->vcpu[vcpu_id] == NULL) ) return -ENOENT; - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); if ( !port_is_valid(d, port) ) { @@ -756,7 +756,7 @@ long evtchn_bind_vcpu(unsigned int port, } out: - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); return rc; } @@ -768,11 +768,11 @@ static long evtchn_unmask(evtchn_unmask_ int port = unmask->port; struct vcpu *v; - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); if ( unlikely(!port_is_valid(d, port)) ) { - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); return -EINVAL; } @@ -790,7 +790,7 @@ static long evtchn_unmask(evtchn_unmask_ vcpu_mark_events_pending(v); } - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); return 0; } @@ -944,7 +944,7 @@ int alloc_unbound_xen_event_channel( struct domain *d = local_vcpu->domain; int port; - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); if ( (port = get_free_port(d)) < 0 ) goto out; @@ -956,7 +956,7 @@ int alloc_unbound_xen_event_channel( chn->u.unbound.remote_domid = remote_domid; out: - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); return port; } @@ -968,11 +968,11 @@ void free_xen_event_channel( struct evtchn *chn; struct domain *d = local_vcpu->domain; - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); if ( unlikely(d->is_dying) ) { - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); return; } @@ -981,7 +981,7 @@ void free_xen_event_channel( BUG_ON(!chn->consumer_is_xen); chn->consumer_is_xen = 0; - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); (void)__evtchn_close(d, port); } @@ -993,7 +993,7 @@ void notify_via_xen_event_channel(int lp struct domain *ld = current->domain, *rd; int rport; - spin_lock(&ld->evtchn_lock); + spin_lock(&ld->event_lock); ASSERT(port_is_valid(ld, lport)); lchn = evtchn_from_port(ld, lport); @@ -1007,13 +1007,13 @@ void notify_via_xen_event_channel(int lp evtchn_set_pending(rd->vcpu[rchn->notify_vcpu_id], rport); } - spin_unlock(&ld->evtchn_lock); + spin_unlock(&ld->event_lock); } int evtchn_init(struct domain *d) { - spin_lock_init(&d->evtchn_lock); + spin_lock_init(&d->event_lock); if ( get_free_port(d) != 0 ) return -EINVAL; evtchn_from_port(d, 0)->state = ECS_RESERVED; @@ -1027,7 +1027,7 @@ void evtchn_destroy(struct domain *d) /* After this barrier no new event-channel allocations can occur. */ BUG_ON(!d->is_dying); - spin_barrier(&d->evtchn_lock); + spin_barrier(&d->event_lock); /* Close all existing event channels. */ for ( i = 0; port_is_valid(d, i); i++ ) @@ -1037,14 +1037,14 @@ void evtchn_destroy(struct domain *d) } /* Free all event-channel buckets. */ - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); for ( i = 0; i < NR_EVTCHN_BUCKETS; i++ ) { xsm_free_security_evtchn(d->evtchn[i]); xfree(d->evtchn[i]); d->evtchn[i] = NULL; } - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); } static void domain_dump_evtchn_info(struct domain *d) @@ -1053,7 +1053,7 @@ static void domain_dump_evtchn_info(stru printk("Domain %d polling vCPUs: %08lx\n", d->domain_id, d->poll_mask[0]); - if ( !spin_trylock(&d->evtchn_lock) ) + if ( !spin_trylock(&d->event_lock) ) return; printk("Event channel information for domain %d:\n", @@ -1094,7 +1094,7 @@ static void domain_dump_evtchn_info(stru printk(" x=%d\n", chn->consumer_is_xen); } - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); } static void dump_evtchn_info(unsigned char key) diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/drivers/Makefile --- a/xen/drivers/Makefile Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/drivers/Makefile Fri Oct 10 12:06:46 2008 +0900 @@ -1,5 +1,6 @@ subdir-y += char subdir-y += char subdir-y += cpufreq +subdir-y += pci subdir-$(x86) += passthrough subdir-$(HAS_ACPI) += acpi subdir-$(HAS_VGA) += video diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/drivers/passthrough/io.c --- a/xen/drivers/passthrough/io.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/drivers/passthrough/io.c Fri Oct 10 12:06:46 2008 +0900 @@ -26,10 +26,14 @@ static void pt_irq_time_out(void *data) struct hvm_mirq_dpci_mapping *irq_map = data; unsigned int guest_gsi, machine_gsi = 0; int vector; - struct hvm_irq_dpci *dpci = domain_get_irq_dpci(irq_map->dom); + struct hvm_irq_dpci *dpci = NULL; struct dev_intx_gsi_link *digl; uint32_t device, intx; + spin_lock(&irq_map->dom->event_lock); + + dpci = domain_get_irq_dpci(irq_map->dom); + ASSERT(dpci); list_for_each_entry ( digl, &irq_map->digl_list, list ) { guest_gsi = digl->gsi; @@ -41,55 +45,65 @@ static void pt_irq_time_out(void *data) clear_bit(machine_gsi, dpci->dirq_mask); vector = domain_irq_to_vector(irq_map->dom, machine_gsi); - stop_timer(&dpci->hvm_timer[vector]); - spin_lock(&dpci->dirq_lock); dpci->mirq[machine_gsi].pending = 0; - spin_unlock(&dpci->dirq_lock); + spin_unlock(&irq_map->dom->event_lock); pirq_guest_eoi(irq_map->dom, machine_gsi); } int pt_irq_create_bind_vtd( struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind) { - struct hvm_irq_dpci *hvm_irq_dpci = domain_get_irq_dpci(d); + struct hvm_irq_dpci *hvm_irq_dpci = NULL; uint32_t machine_gsi, guest_gsi; uint32_t device, intx, link; struct dev_intx_gsi_link *digl; - + int pirq = pt_irq_bind->machine_irq; + + if ( pirq < 0 || pirq >= NR_PIRQS ) + return -EINVAL; + + spin_lock(&d->event_lock); + + hvm_irq_dpci = domain_get_irq_dpci(d); if ( hvm_irq_dpci == NULL ) { hvm_irq_dpci = xmalloc(struct hvm_irq_dpci); if ( hvm_irq_dpci == NULL ) + { + spin_unlock(&d->event_lock); return -ENOMEM; - + } memset(hvm_irq_dpci, 0, sizeof(*hvm_irq_dpci)); - spin_lock_init(&hvm_irq_dpci->dirq_lock); for ( int i = 0; i < NR_IRQS; i++ ) INIT_LIST_HEAD(&hvm_irq_dpci->mirq[i].digl_list); - - if ( domain_set_irq_dpci(d, hvm_irq_dpci) == 0 ) - xfree(hvm_irq_dpci); + } + + if ( domain_set_irq_dpci(d, hvm_irq_dpci) == 0 ) + { + xfree(hvm_irq_dpci); + spin_unlock(&d->event_lock); + return -EINVAL; } if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI ) { - int pirq = pt_irq_bind->machine_irq; - - if ( pirq < 0 || pirq >= NR_IRQS ) - return -EINVAL; - - if ( !(hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_VALID ) ) - { - hvm_irq_dpci->mirq[pirq].flags |= HVM_IRQ_DPCI_VALID | - HVM_IRQ_DPCI_MSI ; + + if ( !test_and_set_bit(pirq, hvm_irq_dpci->mapping)) + { + set_bit(_HVM_IRQ_DPCI_MSI, &hvm_irq_dpci->mirq[pirq].flags); + hvm_irq_dpci->mirq[pirq].gmsi.gvec = pt_irq_bind->u.msi.gvec; + hvm_irq_dpci->mirq[pirq].gmsi.gflags = pt_irq_bind->u.msi.gflags; + hvm_irq_dpci->msi_gvec_pirq[pt_irq_bind->u.msi.gvec] = pirq; + /* bind after hvm_irq_dpci is setup to avoid race with irq handler*/ pirq_guest_bind(d->vcpu[0], pirq, 0); } - - hvm_irq_dpci->mirq[pirq].flags |= HVM_IRQ_DPCI_VALID |HVM_IRQ_DPCI_MSI ; - hvm_irq_dpci->mirq[pirq].gmsi.gvec = pt_irq_bind->u.msi.gvec; - hvm_irq_dpci->mirq[pirq].gmsi.gflags = pt_irq_bind->u.msi.gflags; - hvm_irq_dpci->msi_gvec_pirq[pt_irq_bind->u.msi.gvec] = pirq; - + else if (hvm_irq_dpci->mirq[pirq].gmsi.gvec != pt_irq_bind->u.msi.gvec + ||hvm_irq_dpci->msi_gvec_pirq[pt_irq_bind->u.msi.gvec] != pirq) + + { + spin_unlock(&d->event_lock); + return -EBUSY; + } } else { @@ -102,7 +116,10 @@ int pt_irq_create_bind_vtd( digl = xmalloc(struct dev_intx_gsi_link); if ( !digl ) + { + spin_unlock(&d->event_lock); return -ENOMEM; + } digl->device = device; digl->intx = intx; @@ -117,11 +134,11 @@ int pt_irq_create_bind_vtd( hvm_irq_dpci->girq[guest_gsi].machine_gsi = machine_gsi; /* Bind the same mirq once in the same domain */ - if ( !(hvm_irq_dpci->mirq[machine_gsi].flags & HVM_IRQ_DPCI_VALID) ) - { - hvm_irq_dpci->mirq[machine_gsi].flags |= HVM_IRQ_DPCI_VALID; + if ( !test_and_set_bit(machine_gsi, hvm_irq_dpci->mapping)) + { hvm_irq_dpci->mirq[machine_gsi].dom = d; + /* Init timer before binding */ init_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, machine_gsi)], pt_irq_time_out, &hvm_irq_dpci->mirq[machine_gsi], 0); /* Deal with gsi for legacy devices */ @@ -132,37 +149,45 @@ int pt_irq_create_bind_vtd( "VT-d irq bind: m_irq = %x device = %x intx = %x\n", machine_gsi, device, intx); } + spin_unlock(&d->event_lock); return 0; } int pt_irq_destroy_bind_vtd( struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind) { - struct hvm_irq_dpci *hvm_irq_dpci = domain_get_irq_dpci(d); + struct hvm_irq_dpci *hvm_irq_dpci = NULL; uint32_t machine_gsi, guest_gsi; uint32_t device, intx, link; struct list_head *digl_list, *tmp; struct dev_intx_gsi_link *digl; - - if ( hvm_irq_dpci == NULL ) - return 0; machine_gsi = pt_irq_bind->machine_irq; device = pt_irq_bind->u.pci.device; intx = pt_irq_bind->u.pci.intx; guest_gsi = hvm_pci_intx_gsi(device, intx); link = hvm_pci_intx_link(device, intx); - hvm_irq_dpci->link_cnt[link]--; gdprintk(XENLOG_INFO, "pt_irq_destroy_bind_vtd: machine_gsi=%d " "guest_gsi=%d, device=%d, intx=%d.\n", machine_gsi, guest_gsi, device, intx); + spin_lock(&d->event_lock); + + hvm_irq_dpci = domain_get_irq_dpci(d); + + if ( hvm_irq_dpci == NULL ) + { + spin_unlock(&d->event_lock); + return -EINVAL; + } + + hvm_irq_dpci->link_cnt[link]--; memset(&hvm_irq_dpci->girq[guest_gsi], 0, sizeof(struct hvm_girq_dpci_mapping)); /* clear the mirq info */ - if ( (hvm_irq_dpci->mirq[machine_gsi].flags & HVM_IRQ_DPCI_VALID) ) + if ( test_bit(machine_gsi, hvm_irq_dpci->mapping)) { list_for_each_safe ( digl_list, tmp, &hvm_irq_dpci->mirq[machine_gsi].digl_list ) @@ -185,9 +210,10 @@ int pt_irq_destroy_bind_vtd( kill_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, machine_gsi)]); hvm_irq_dpci->mirq[machine_gsi].dom = NULL; hvm_irq_dpci->mirq[machine_gsi].flags = 0; - } - } - + clear_bit(machine_gsi, hvm_irq_dpci->mapping); + } + } + spin_unlock(&d->event_lock); gdprintk(XENLOG_INFO, "XEN_DOMCTL_irq_unmapping: m_irq = %x device = %x intx = %x\n", machine_gsi, device, intx); @@ -199,8 +225,9 @@ int hvm_do_IRQ_dpci(struct domain *d, un { struct hvm_irq_dpci *dpci = domain_get_irq_dpci(d); + ASSERT(spin_is_locked(&irq_desc[domain_irq_to_vector(d, mirq)].lock)); if ( !iommu_enabled || (d == dom0) || !dpci || - !dpci->mirq[mirq].flags & HVM_IRQ_DPCI_VALID ) + !test_bit(mirq, dpci->mapping)) return 0; /* @@ -218,69 +245,82 @@ int hvm_do_IRQ_dpci(struct domain *d, un return 1; } - void hvm_dpci_msi_eoi(struct domain *d, int vector) { struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; + irq_desc_t *desc; int pirq; - unsigned long flags; - irq_desc_t *desc; if ( !iommu_enabled || (hvm_irq_dpci == NULL) ) return; + spin_lock(&d->event_lock); pirq = hvm_irq_dpci->msi_gvec_pirq[vector]; if ( ( pirq >= 0 ) && (pirq < NR_PIRQS) && - (hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_VALID) && - (hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_MSI) ) - { - int vec; - vec = domain_irq_to_vector(d, pirq); - desc = &irq_desc[vec]; - - spin_lock_irqsave(&desc->lock, flags); - desc->status &= ~IRQ_INPROGRESS; - spin_unlock_irqrestore(&desc->lock, flags); - - pirq_guest_eoi(d, pirq); - } + test_bit(pirq, hvm_irq_dpci->mapping) && + (test_bit(_HVM_IRQ_DPCI_MSI, &hvm_irq_dpci->mirq[pirq].flags))) + { + BUG_ON(!local_irq_is_enabled()); + desc = domain_spin_lock_irq_desc(d, pirq, NULL); + if (!desc) + { + spin_unlock(&d->event_lock); + return; + } + + desc->status &= ~IRQ_INPROGRESS; + spin_unlock_irq(&desc->lock); + + pirq_guest_eoi(d, pirq); + } + + spin_unlock(&d->event_lock); } void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi, union vioapic_redir_entry *ent) { - struct hvm_irq_dpci *hvm_irq_dpci = domain_get_irq_dpci(d); + struct hvm_irq_dpci *hvm_irq_dpci = NULL; uint32_t device, intx, machine_gsi; - if ( !iommu_enabled || (hvm_irq_dpci == NULL) || + if ( !iommu_enabled) + return; + + if ( guest_gsi < NR_ISAIRQS ) + { + hvm_dpci_isairq_eoi(d, guest_gsi); + return; + } + + spin_lock(&d->event_lock); + hvm_irq_dpci = domain_get_irq_dpci(d); + + if((hvm_irq_dpci == NULL) || (guest_gsi >= NR_ISAIRQS && !hvm_irq_dpci->girq[guest_gsi].valid) ) + { + spin_unlock(&d->event_lock); return; - - if ( guest_gsi < NR_ISAIRQS ) - { - hvm_dpci_isairq_eoi(d, guest_gsi); - return; - } - - machine_gsi = hvm_irq_dpci->girq[guest_gsi].machine_gsi; + } + device = hvm_irq_dpci->girq[guest_gsi].device; intx = hvm_irq_dpci->girq[guest_gsi].intx; hvm_pci_intx_deassert(d, device, intx); - spin_lock(&hvm_irq_dpci->dirq_lock); + machine_gsi = hvm_irq_dpci->girq[guest_gsi].machine_gsi; if ( --hvm_irq_dpci->mirq[machine_gsi].pending == 0 ) { - spin_unlock(&hvm_irq_dpci->dirq_lock); - if ( (ent == NULL) || !ent->fields.mask ) { + /* + * No need to get vector lock for timer + * since interrupt is still not EOIed + */ stop_timer(&hvm_irq_dpci->hvm_timer[ domain_irq_to_vector(d, machine_gsi)]); pirq_guest_eoi(d, machine_gsi); } } - else - spin_unlock(&hvm_irq_dpci->dirq_lock); -} + spin_unlock(&d->event_lock); +} diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/drivers/passthrough/pci.c --- a/xen/drivers/passthrough/pci.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/drivers/passthrough/pci.c Fri Oct 10 12:06:46 2008 +0900 @@ -154,7 +154,7 @@ int pci_remove_device(u8 bus, u8 devfn) static void pci_clean_dpci_irqs(struct domain *d) { - struct hvm_irq_dpci *hvm_irq_dpci = domain_get_irq_dpci(d); + struct hvm_irq_dpci *hvm_irq_dpci = NULL; uint32_t i; struct list_head *digl_list, *tmp; struct dev_intx_gsi_link *digl; @@ -165,13 +165,14 @@ static void pci_clean_dpci_irqs(struct d if ( !is_hvm_domain(d) && !need_iommu(d) ) return; + spin_lock(&d->event_lock); + hvm_irq_dpci = domain_get_irq_dpci(d); if ( hvm_irq_dpci != NULL ) { - for ( i = 0; i < NR_IRQS; i++ ) - { - if ( !(hvm_irq_dpci->mirq[i].flags & HVM_IRQ_DPCI_VALID) ) - continue; - + for ( i = find_first_bit(hvm_irq_dpci->mapping, NR_PIRQS); + i < NR_PIRQS; + i = find_next_bit(hvm_irq_dpci->mapping, NR_PIRQS, i + 1) ) + { pirq_guest_unbind(d, i); kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(i)]); @@ -188,6 +189,7 @@ static void pci_clean_dpci_irqs(struct d d->arch.hvm_domain.irq.dpci = NULL; xfree(hvm_irq_dpci); } + spin_unlock(&d->event_lock); } void pci_release_devices(struct domain *d) diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/drivers/passthrough/vtd/intremap.c --- a/xen/drivers/passthrough/vtd/intremap.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/drivers/passthrough/vtd/intremap.c Fri Oct 10 12:06:46 2008 +0900 @@ -44,7 +44,7 @@ u16 apicid_to_bdf(int apic_id) } static int remap_entry_to_ioapic_rte( - struct iommu *iommu, struct IO_APIC_route_entry *old_rte) + struct iommu *iommu, struct IO_xAPIC_route_entry *old_rte) { struct iremap_entry *iremap_entry = NULL, *iremap_entries; struct IO_APIC_route_remap_entry *remap_rte; @@ -90,13 +90,13 @@ static int remap_entry_to_ioapic_rte( } static int ioapic_rte_to_remap_entry(struct iommu *iommu, - int apic_id, struct IO_APIC_route_entry *old_rte, + int apic_id, struct IO_xAPIC_route_entry *old_rte, unsigned int rte_upper, unsigned int value) { struct iremap_entry *iremap_entry = NULL, *iremap_entries; struct iremap_entry new_ire; struct IO_APIC_route_remap_entry *remap_rte; - struct IO_APIC_route_entry new_rte; + struct IO_xAPIC_route_entry new_rte; int index; unsigned long flags; struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu); @@ -177,7 +177,7 @@ unsigned int io_apic_read_remap_rte( unsigned int io_apic_read_remap_rte( unsigned int apic, unsigned int reg) { - struct IO_APIC_route_entry old_rte = { 0 }; + struct IO_xAPIC_route_entry old_rte = { 0 }; struct IO_APIC_route_remap_entry *remap_rte; int rte_upper = (reg & 1) ? 1 : 0; struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid); @@ -222,7 +222,7 @@ void io_apic_write_remap_rte( void io_apic_write_remap_rte( unsigned int apic, unsigned int reg, unsigned int value) { - struct IO_APIC_route_entry old_rte = { 0 }; + struct IO_xAPIC_route_entry old_rte = { 0 }; struct IO_APIC_route_remap_entry *remap_rte; unsigned int rte_upper = (reg & 1) ? 1 : 0; struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid); diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/drivers/passthrough/vtd/vtd.h --- a/xen/drivers/passthrough/vtd/vtd.h Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/drivers/passthrough/vtd/vtd.h Fri Oct 10 12:06:46 2008 +0900 @@ -22,6 +22,43 @@ #define _VTD_H_ #include <xen/iommu.h> + +/* Accomodate both IOAPIC and IOSAPIC. */ +struct IO_xAPIC_route_entry { + __u32 vector : 8, + delivery_mode : 3, /* 000: FIXED + * 001: lowest prio + * 111: ExtINT + */ + dest_mode : 1, /* 0: physical, 1: logical */ + delivery_status : 1, + polarity : 1, + irr : 1, + trigger : 1, /* 0: edge, 1: level */ + mask : 1, /* 0: enabled, 1: disabled */ + __reserved_2 : 15; + + union { + struct { __u32 + __reserved_1 : 24, + physical_dest : 4, + __reserved_2 : 4; + } physical; + + struct { __u32 + __reserved_1 : 24, + logical_dest : 8; + } logical; + +#ifdef __ia64__ + struct { __u32 + __reserved_1 : 16, + dest_id : 16; + }; +#endif + } dest; + +} __attribute__ ((packed)); struct IO_APIC_route_remap_entry { union { diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/drivers/passthrough/vtd/x86/vtd.c --- a/xen/drivers/passthrough/vtd/x86/vtd.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/drivers/passthrough/vtd/x86/vtd.c Fri Oct 10 12:06:46 2008 +0900 @@ -85,37 +85,41 @@ void hvm_dpci_isairq_eoi(struct domain * void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq) { struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; - struct hvm_irq_dpci *dpci = domain_get_irq_dpci(d); + struct hvm_irq_dpci *dpci = NULL; struct dev_intx_gsi_link *digl, *tmp; int i; ASSERT(isairq < NR_ISAIRQS); - if ( !vtd_enabled || !dpci || - !test_bit(isairq, dpci->isairq_map) ) + if ( !vtd_enabled) return; + spin_lock(&d->event_lock); + + dpci = domain_get_irq_dpci(d); + + if ( !dpci || !test_bit(isairq, dpci->isairq_map) ) + { + spin_unlock(&d->event_lock); + return; + } /* Multiple mirq may be mapped to one isa irq */ - for ( i = 0; i < NR_IRQS; i++ ) + for ( i = find_first_bit(dpci->mapping, NR_PIRQS); + i < NR_PIRQS; + i = find_next_bit(dpci->mapping, NR_PIRQS, i + 1) ) { - if ( !dpci->mirq[i].flags & HVM_IRQ_DPCI_VALID ) - continue; - list_for_each_entry_safe ( digl, tmp, &dpci->mirq[i].digl_list, list ) { if ( hvm_irq->pci_link.route[digl->link] == isairq ) { hvm_pci_intx_deassert(d, digl->device, digl->intx); - spin_lock(&dpci->dirq_lock); if ( --dpci->mirq[i].pending == 0 ) { - spin_unlock(&dpci->dirq_lock); stop_timer(&dpci->hvm_timer[domain_irq_to_vector(d, i)]); pirq_guest_eoi(d, i); } - else - spin_unlock(&dpci->dirq_lock); } } } + spin_unlock(&d->event_lock); } diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/drivers/pci/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/drivers/pci/Makefile Fri Oct 10 12:06:46 2008 +0900 @@ -0,0 +1,1 @@ +obj-y += pci.o diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/drivers/pci/pci.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/drivers/pci/pci.c Fri Oct 10 12:06:46 2008 +0900 @@ -0,0 +1,64 @@ +/****************************************************************************** + * pci.c + * + * Architecture-independent PCI access functions. + */ + +#include <xen/pci.h> +#include <xen/pci_regs.h> + +int pci_find_cap_offset(u8 bus, u8 dev, u8 func, u8 cap) +{ + u8 id; + int max_cap = 48; + u8 pos = PCI_CAPABILITY_LIST; + u16 status; + + status = pci_conf_read16(bus, dev, func, PCI_STATUS); + if ( (status & PCI_STATUS_CAP_LIST) == 0 ) + return 0; + + while ( max_cap-- ) + { + pos = pci_conf_read8(bus, dev, func, pos); + if ( pos < 0x40 ) + break; + + pos &= ~3; + id = pci_conf_read8(bus, dev, func, pos + PCI_CAP_LIST_ID); + + if ( id == 0xff ) + break; + else if ( id == cap ) + return pos; + + pos += PCI_CAP_LIST_NEXT; + } + + return 0; +} + +int pci_find_next_cap(u8 bus, unsigned int devfn, u8 pos, int cap) +{ + u8 id; + int ttl = 48; + + while ( ttl-- ) + { + pos = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos); + if ( pos < 0x40 ) + break; + + pos &= ~3; + id = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + pos + PCI_CAP_LIST_ID); + + if ( id == 0xff ) + break; + if ( id == cap ) + return pos; + + pos += PCI_CAP_LIST_NEXT; + } + return 0; +} diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/include/asm-x86/domain.h Fri Oct 10 12:06:46 2008 +0900 @@ -235,7 +235,7 @@ struct arch_domain /* Shadow translated domain: P2M mapping */ pagetable_t phys_table; - /* NB. protected by d->evtchn_lock and by irq_desc[vector].lock */ + /* NB. protected by d->event_lock and by irq_desc[vector].lock */ int vector_pirq[NR_VECTORS]; int pirq_vector[NR_PIRQS]; diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/include/asm-x86/hvm/irq.h --- a/xen/include/asm-x86/hvm/irq.h Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/include/asm-x86/hvm/irq.h Fri Oct 10 12:06:46 2008 +0900 @@ -25,6 +25,7 @@ #include <xen/types.h> #include <xen/spinlock.h> #include <asm/irq.h> +#include <asm/pirq.h> #include <asm/hvm/hvm.h> #include <asm/hvm/vpic.h> #include <asm/hvm/vioapic.h> @@ -38,8 +39,6 @@ struct dev_intx_gsi_link { uint8_t link; }; -#define HVM_IRQ_DPCI_VALID 0x1 -#define HVM_IRQ_DPCI_MSI 0x2 #define _HVM_IRQ_DPCI_MSI 0x1 struct hvm_gmsi_info { @@ -64,9 +63,10 @@ struct hvm_girq_dpci_mapping { #define NR_ISAIRQS 16 #define NR_LINK 4 +/* Protected by domain's event_lock */ struct hvm_irq_dpci { - spinlock_t dirq_lock; /* Machine IRQ to guest device/intx mapping. */ + DECLARE_BITMAP(mapping, NR_PIRQS); struct hvm_mirq_dpci_mapping mirq[NR_IRQS]; /* Guest IRQ to guest device/intx mapping. */ struct hvm_girq_dpci_mapping girq[NR_IRQS]; diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/include/asm-x86/io_apic.h --- a/xen/include/asm-x86/io_apic.h Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/include/asm-x86/io_apic.h Fri Oct 10 12:06:46 2008 +0900 @@ -190,5 +190,6 @@ static inline int ioapic_resume(void) {r #endif extern int assign_irq_vector(int irq); +extern int free_irq_vector(int vector); #endif diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/include/asm-x86/irq.h --- a/xen/include/asm-x86/irq.h Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/include/asm-x86/irq.h Fri Oct 10 12:06:46 2008 +0900 @@ -19,7 +19,9 @@ extern int vector_irq[NR_VECTORS]; extern u8 irq_vector[NR_IRQ_VECTORS]; -#define AUTO_ASSIGN -1 +#define AUTO_ASSIGN -1 +#define NEVER_ASSIGN -2 +#define FREE_TO_ASSIGN -3 #define platform_legacy_irq(irq) ((irq) < 16) @@ -52,6 +54,12 @@ int pirq_acktype(struct domain *d, int i int pirq_acktype(struct domain *d, int irq); int pirq_shared(struct domain *d , int irq); +int map_domain_pirq(struct domain *d, int pirq, int vector, int type, + void *data); +int unmap_domain_pirq(struct domain *d, int pirq); +int get_free_pirq(struct domain *d, int type, int index); +void free_domain_pirqs(struct domain *d); + #define domain_irq_to_vector(d, irq) ((d)->arch.pirq_vector[(irq)]) #define domain_vector_to_irq(d, vec) ((d)->arch.vector_pirq[(vec)]) diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/include/xen/irq.h --- a/xen/include/xen/irq.h Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/include/xen/irq.h Fri Oct 10 12:06:46 2008 +0900 @@ -78,6 +78,8 @@ extern int pirq_guest_unmask(struct doma extern int pirq_guest_unmask(struct domain *d); extern int pirq_guest_bind(struct vcpu *v, int irq, int will_share); extern void pirq_guest_unbind(struct domain *d, int irq); +extern irq_desc_t *domain_spin_lock_irq_desc( + struct domain *d, int irq, unsigned long *pflags); static inline void set_native_irq_info(int irq, cpumask_t mask) { diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/include/xen/sched.h --- a/xen/include/xen/sched.h Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/include/xen/sched.h Fri Oct 10 12:06:46 2008 +0900 @@ -188,7 +188,7 @@ struct domain /* Event channel information. */ struct evtchn *evtchn[NR_EVTCHN_BUCKETS]; - spinlock_t evtchn_lock; + spinlock_t event_lock; struct grant_table *grant_table; diff -r af8eaa3cf782 -r c2fc4d26ef18 xen/xsm/acm/acm_simple_type_enforcement_hooks.c --- a/xen/xsm/acm/acm_simple_type_enforcement_hooks.c Fri Oct 10 11:58:03 2008 +0900 +++ b/xen/xsm/acm/acm_simple_type_enforcement_hooks.c Fri Oct 10 12:06:46 2008 +0900 @@ -248,11 +248,11 @@ ste_init_state(struct acm_sized_buffer * /* a) check for event channel conflicts */ for ( bucket = 0; bucket < NR_EVTCHN_BUCKETS; bucket++ ) { - spin_lock(&d->evtchn_lock); + spin_lock(&d->event_lock); ports = d->evtchn[bucket]; if ( ports == NULL) { - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); break; } @@ -280,7 +280,7 @@ ste_init_state(struct acm_sized_buffer * printkd("%s: Policy violation in event channel domain " "%x -> domain %x.\n", __func__, d->domain_id, rdomid); - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); acm_array_append_tuple(errors, ACM_EVTCHN_SHARING_VIOLATION, @@ -288,7 +288,7 @@ ste_init_state(struct acm_sized_buffer * goto out; } } - spin_unlock(&d->evtchn_lock); + spin_unlock(&d->event_lock); } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |