merge with xen-unstable.hg

This commit is contained in:
Isaku Yamahata committed 2008-10-10 12:06:46 +09:00
commit 71c2db7e6e
36 files changed
+602 -435

No files matched your search

+3 -1
View File
@@ -75,7 +75,9 @@ $(LINUX_DIR)/include/linux/autoconf.h: $(LINUX_SRCDIR)/.valid-src
# 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 \
+40 -27
View File
@@ -54,13 +54,13 @@ static void *
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);
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);
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);
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);
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_t memsize)
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_t memsize)
/* 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_t memory_size_mb)
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_t memory_size_mb)
/* 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_t memory_size_mb)
p->header.type = 19;
p->header.length = sizeof(struct smbios_type_19);
p->header.handle = 0x1300;
p->header.handle = 0x1300 + instance;
p->starting_address = 0;
p->ending_address = (memory_size_mb-1) * 1024;
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_t memory_size_mb)
/* 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_t memory_size_mb)
p->header.type = 20;
p->header.length = sizeof(struct smbios_type_20);
p->header.handle = 0x1400;
p->header.handle = 0x1400 + instance;
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->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;
+4 -1
View File
@@ -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 @@ allow dom0_t evchn0-U_t:event {send};
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)
################################################################################
+1 -1
View File
@@ -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);
+3 -3
View File
@@ -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,
}
+4 -1
View File
@@ -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)
+1 -1
View File
@@ -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})
+1 -1
View File
@@ -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,())
+1
View File
@@ -459,6 +459,7 @@ void arch_domain_destroy(struct domain *d)
hvm_domain_destroy(d);
pci_release_devices(d);
free_domain_pirqs(d);
if ( !is_idle_domain(d) )
iommu_domain_destroy(d);
+3 -2
View File
@@ -124,9 +124,11 @@ static void svm_dirq_assist(struct vcpu *v)
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 *v)
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 *v)
*/
set_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, irq)],
NOW() + PT_IRQ_TIME_OUT);
spin_unlock(&d->event_lock);
}
}
+1 -1
View File
@@ -134,7 +134,7 @@ int vmsi_deliver(struct domain *d, int pirq)
"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;
+8 -7
View File
@@ -127,11 +127,13 @@ static void vmx_dirq_assist(struct vcpu *v)
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 *v)
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 *v)
*/
set_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, irq)],
NOW() + PT_IRQ_TIME_OUT);
spin_unlock(&d->event_lock);
}
}
+4
View File
@@ -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 */
+26 -18
View File
@@ -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(int irq)
/* 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;
vector = current_vector;
while (vector_irq[vector] != FREE_TO_ASSIGN) {
vector += 8;
if (vector > LAST_DYNAMIC_VECTOR)
vector = FIRST_DYNAMIC_VECTOR + ((vector + 1) & 7);
/* 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)) {
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;
+175 -5
View File
@@ -14,8 +14,11 @@
#include <xen/sched.h>
#include <xen/keyhandler.h>
#include <xen/compat.h>
#include <asm/current.h>
#include <xen/iocap.h>
#include <xen/iommu.h>
#include <asm/msi.h>
#include <asm/current.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 irq, int will_share)
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, int irq)
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 domain *d, int irq)
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);
@@ -731,6 +734,173 @@ int pirq_guest_force_unbind(struct domain *d, int irq)
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);
static void dump_irqs(unsigned char key)
+1 -1
View File
@@ -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",
+1 -60
View File
@@ -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;
}
+32 -174
View File
@@ -26,168 +26,12 @@ int
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 physdev_map_pirq *map)
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 physdev_map_pirq *map)
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;
}
_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 physdev_map_pirq *map)
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 physdev_unmap_pirq *unmap)
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_HANDLE(void) arg)
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;
+1
View File
@@ -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 = .;
+1
View File
@@ -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 = .;
+44 -44
View File
@@ -133,7 +133,7 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
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_unbound_t *alloc)
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(evtchn_bind_interdomain_t *bind)
/* 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(evtchn_bind_interdomain_t *bind)
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_virq_t *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_virq_t *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_ipi_t *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_ipi_t *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_pirq_t *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_pirq_t *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 *d1, int port1)
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 *d1, int port1)
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 *d1, int port1)
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, unsigned int lport)
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, unsigned int lport)
/* 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, unsigned int lport)
}
out:
spin_unlock(&ld->evtchn_lock);
spin_unlock(&ld->event_lock);
return ret;
}
@@ -656,7 +656,7 @@ static long evtchn_status(evtchn_status_t *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_t *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, unsigned int vcpu_id)
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, unsigned int vcpu_id)
}
out:
spin_unlock(&d->evtchn_lock);
spin_unlock(&d->event_lock);
return rc;
}
@@ -768,11 +768,11 @@ static long evtchn_unmask(evtchn_unmask_t *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_t *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 lport)
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 lport)
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(struct domain *d)
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(struct domain *d)
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)
+1
View File
@@ -1,5 +1,6 @@
subdir-y += char
subdir-y += cpufreq
subdir-y += pci
subdir-$(x86) += passthrough
subdir-$(HAS_ACPI) += acpi
subdir-$(HAS_VGA) += video
+95 -55
View File
@@ -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 ) )
if ( !test_and_set_bit(pirq, hvm_irq_dpci->mapping))
{
hvm_irq_dpci->mirq[pirq].flags |= HVM_IRQ_DPCI_VALID |
HVM_IRQ_DPCI_MSI ;
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);
}
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)
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;
{
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) )
if ( !test_and_set_bit(machine_gsi, hvm_irq_dpci->mapping))
{
hvm_irq_dpci->mirq[machine_gsi].flags |= HVM_IRQ_DPCI_VALID;
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, unsigned int mirq)
{
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,44 +245,46 @@ int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq)
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;
int pirq;
unsigned long flags;
irq_desc_t *desc;
int pirq;
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];
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;
}
spin_lock_irqsave(&desc->lock, flags);
desc->status &= ~IRQ_INPROGRESS;
spin_unlock_irqrestore(&desc->lock, flags);
desc->status &= ~IRQ_INPROGRESS;
spin_unlock_irq(&desc->lock);
pirq_guest_eoi(d, pirq);
}
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) ||
(guest_gsi >= NR_ISAIRQS &&
!hvm_irq_dpci->girq[guest_gsi].valid) )
if ( !iommu_enabled)
return;
if ( guest_gsi < NR_ISAIRQS )
@@ -264,23 +293,34 @@ void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
return;
}
machine_gsi = hvm_irq_dpci->girq[guest_gsi].machine_gsi;
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;
}
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);
}
+7 -5
View File
@@ -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 domain *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++ )
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) )
{
if ( !(hvm_irq_dpci->mirq[i].flags & HVM_IRQ_DPCI_VALID) )
continue;
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 domain *d)
d->arch.hvm_domain.irq.dpci = NULL;
xfree(hvm_irq_dpci);
}
spin_unlock(&d->event_lock);
}
void pci_release_devices(struct domain *d)
+5 -5
View File
@@ -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 @@ static int ioapic_rte_to_remap_entry(struct iommu *iommu,
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 @@ unsigned int io_apic_read_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);
+37
View File
@@ -23,6 +23,43 @@
#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 {
u64 val;
+16 -12
View File
@@ -85,37 +85,41 @@ int domain_set_irq_dpci(struct domain *domain, struct hvm_irq_dpci *dpci)
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;
/* Multiple mirq may be mapped to one isa irq */
for ( i = 0; i < NR_IRQS; i++ )
{
if ( !dpci->mirq[i].flags & HVM_IRQ_DPCI_VALID )
continue;
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 = find_first_bit(dpci->mapping, NR_PIRQS);
i < NR_PIRQS;
i = find_next_bit(dpci->mapping, NR_PIRQS, i + 1) )
{
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);
}
+1
View File
@@ -0,0 +1 @@
obj-y += pci.o
+64
View File
@@ -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;
}
+1 -1
View File
@@ -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];
+3 -3
View File
@@ -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];
+1
View File
@@ -190,5 +190,6 @@ static inline int ioapic_resume(void) {return 0};
#endif
extern int assign_irq_vector(int irq);
extern int free_irq_vector(int vector);
#endif
+9 -1
View File
@@ -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 @@ extern atomic_t irq_mis_count;
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)])
+2
View File
@@ -78,6 +78,8 @@ extern int pirq_guest_eoi(struct domain *d, int irq);
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)
{
+1 -1
View File
@@ -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;
@@ -248,11 +248,11 @@ ste_init_state(struct acm_sized_buffer *errors)
/* 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 *errors)
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 *errors)
goto out;
}
}
spin_unlock(&d->evtchn_lock);
spin_unlock(&d->event_lock);
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.