# 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
|