[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg (staging)
# HG changeset patch # User Alex Williamson <alex.williamson@xxxxxx> # Date 1194472128 25200 # Node ID a1247c2df2b41d7959c1626833c2a149dd705640 # Parent ef6415fdaf8a026aa6cba380b01152dc96cac449 # Parent d4c5a1cdcf2e6e9c98c99d218f8b80f8baca10cd merge with xen-unstable.hg (staging) --- tools/examples/block | 5 + tools/examples/network-bridge | 4 - tools/ioemu/hw/pass-through.c | 15 ++-- tools/ioemu/hw/pass-through.h | 2 tools/ioemu/hw/xen_machine_fv.c | 45 +++++------- xen/arch/ia64/xen/mm.c | 8 -- xen/arch/x86/domain.c | 23 +++--- xen/arch/x86/hvm/irq.c | 13 +-- xen/arch/x86/hvm/vmx/intr.c | 17 +++- xen/arch/x86/hvm/vmx/vtd/intel-iommu.c | 9 +- xen/arch/x86/hvm/vmx/vtd/io.c | 121 ++++++++++++++++++++++----------- xen/arch/x86/hvm/vmx/vtd/utils.c | 15 ++-- xen/arch/x86/hvm/vpt.c | 2 xen/arch/x86/mm.c | 71 ++++++++++++++++--- xen/arch/x86/mm/shadow/multi.c | 12 +-- xen/arch/x86/traps.c | 3 xen/common/grant_table.c | 6 - xen/include/asm-ia64/mm.h | 3 xen/include/asm-x86/domain.h | 7 + xen/include/asm-x86/hvm/irq.h | 29 +++++-- xen/include/asm-x86/mm.h | 28 ++++--- xen/include/asm-x86/page.h | 10 ++ 22 files changed, 289 insertions(+), 159 deletions(-) diff -r ef6415fdaf8a -r a1247c2df2b4 tools/examples/block --- a/tools/examples/block Wed Nov 07 11:01:23 2007 -0700 +++ b/tools/examples/block Wed Nov 07 14:48:48 2007 -0700 @@ -326,7 +326,10 @@ mount it read-write in a guest domain." fatal 'Failed to find an unused loop device' fi - do_or_die losetup "$loopdev" "$file" + status=$(losetup "$loopdev" "$file" || echo "failed") + if [ -n "$status" ]; then + do_or_die losetup -r "$loopdev" "$file" + fi xenstore_write "$XENBUS_PATH/node" "$loopdev" write_dev "$loopdev" release_lock "block" diff -r ef6415fdaf8a -r a1247c2df2b4 tools/examples/network-bridge --- a/tools/examples/network-bridge Wed Nov 07 11:01:23 2007 -0700 +++ b/tools/examples/network-bridge Wed Nov 07 14:48:48 2007 -0700 @@ -72,8 +72,8 @@ find_alt_device () { echo "$ifs" } -netdev=${netdev:-$(ip route list | awk '/^default / { print $NF }' | - sed 's/.* dev //')} +netdev=${netdev:-$(ip route list 0.0.0.0/0 | \ + sed 's/.*dev \([a-z]\+[0-9]\+\).*$/\1/')} if is_network_root ; then altdevs=$(find_alt_device $netdev) for netdev in $altdevs; do break; done diff -r ef6415fdaf8a -r a1247c2df2b4 tools/ioemu/hw/pass-through.c --- a/tools/ioemu/hw/pass-through.c Wed Nov 07 11:01:23 2007 -0700 +++ b/tools/ioemu/hw/pass-through.c Wed Nov 07 14:48:48 2007 -0700 @@ -20,8 +20,8 @@ * Guy Zana <guy@xxxxxxxxxxxx> * * This file implements direct PCI assignment to a HVM guest - * */ + #include "vl.h" #include "pass-through.h" #include "pci/header.h" @@ -127,9 +127,10 @@ void pt_iomem_map(PCIDevice *d, int i, u if ( !first_map ) { /* Remove old mapping */ - ret = xc_domain_memory_mapping(xc_handle, domid, old_ebase >> 12, - assigned_device->bases[i].access.maddr >> 12, - (e_size+0xFFF) >> 12, + ret = xc_domain_memory_mapping(xc_handle, domid, + old_ebase >> XC_PAGE_SHIFT, + assigned_device->bases[i].access.maddr >> XC_PAGE_SHIFT, + (e_size+XC_PAGE_MASK) >> XC_PAGE_SHIFT, DPCI_REMOVE_MAPPING); if ( ret != 0 ) { @@ -140,9 +141,9 @@ void pt_iomem_map(PCIDevice *d, int i, u /* Create new mapping */ ret = xc_domain_memory_mapping(xc_handle, domid, - assigned_device->bases[i].e_physbase >> 12, - assigned_device->bases[i].access.maddr >> 12, - (e_size+0xFFF) >> 12, + assigned_device->bases[i].e_physbase >> XC_PAGE_SHIFT, + assigned_device->bases[i].access.maddr >> XC_PAGE_SHIFT, + (e_size+XC_PAGE_MASK) >> XC_PAGE_SHIFT, DPCI_ADD_MAPPING); if ( ret != 0 ) PT_LOG("Error: create new mapping failed!\n"); diff -r ef6415fdaf8a -r a1247c2df2b4 tools/ioemu/hw/pass-through.h --- a/tools/ioemu/hw/pass-through.h Wed Nov 07 11:01:23 2007 -0700 +++ b/tools/ioemu/hw/pass-through.h Wed Nov 07 14:48:48 2007 -0700 @@ -40,7 +40,7 @@ /* Misc PCI constants that should be moved to a separate library :) */ #define PCI_CONFIG_SIZE (256) #define PCI_EXP_DEVCAP_FLR (1 << 28) -#define PCI_EXP_DEVCTL_FLR (0x1b) +#define PCI_EXP_DEVCTL_FLR (1 << 15) #define PCI_BAR_ENTRIES (6) struct pt_region { diff -r ef6415fdaf8a -r a1247c2df2b4 tools/ioemu/hw/xen_machine_fv.c --- a/tools/ioemu/hw/xen_machine_fv.c Wed Nov 07 11:01:23 2007 -0700 +++ b/tools/ioemu/hw/xen_machine_fv.c Wed Nov 07 14:48:48 2007 -0700 @@ -27,13 +27,6 @@ #include <xen/hvm/params.h> #include <sys/mman.h> -#ifndef PAGE_SIZE -#define PAGE_SIZE XC_PAGE_SIZE -#endif -#ifndef PAGE_SHIFT -#define PAGE_SHIFT XC_PAGE_SHIFT -#endif - #if defined(MAPCACHE) #if defined(__i386__) @@ -57,7 +50,7 @@ struct map_cache { struct map_cache { unsigned long paddr_index; uint8_t *vaddr_base; - DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>PAGE_SHIFT); + DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>XC_PAGE_SHIFT); }; static struct map_cache *mapcache_entry; @@ -71,9 +64,9 @@ static int qemu_map_cache_init(void) { unsigned long size; - nr_buckets = (((MAX_MCACHE_SIZE >> PAGE_SHIFT) + - (1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1) >> - (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)); + nr_buckets = (((MAX_MCACHE_SIZE >> XC_PAGE_SHIFT) + + (1UL << (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)) - 1) >> + (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)); /* * Use mmap() directly: lets us allocate a big hash table with no up-front @@ -81,7 +74,7 @@ static int qemu_map_cache_init(void) * that we actually use. All others will contain all zeroes. */ size = nr_buckets * sizeof(struct map_cache); - size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1); fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx size %lu\n", nr_buckets, size); mapcache_entry = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0); @@ -97,7 +90,7 @@ static void qemu_remap_bucket(struct map unsigned long address_index) { uint8_t *vaddr_base; - unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT]; + unsigned long pfns[MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT]; unsigned int i, j; if (entry->vaddr_base != NULL) { @@ -108,11 +101,11 @@ static void qemu_remap_bucket(struct map } } - for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++) - pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i; + for (i = 0; i < MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT; i++) + pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-XC_PAGE_SHIFT)) + i; vaddr_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE, - pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT); + pfns, MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT); if (vaddr_base == NULL) { fprintf(logfile, "xc_map_foreign_batch error %d\n", errno); exit(-1); @@ -121,10 +114,10 @@ static void qemu_remap_bucket(struct map entry->vaddr_base = vaddr_base; entry->paddr_index = address_index; - for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i += BITS_PER_LONG) { + for (i = 0; i < MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT; i += BITS_PER_LONG) { unsigned long word = 0; - j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> PAGE_SHIFT)) ? - (MCACHE_BUCKET_SIZE >> PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG; + j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT)) ? + (MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG; while (j > 0) word = (word << 1) | (((pfns[i + --j] >> 28) & 0xf) != 0xf); entry->valid_mapping[i / BITS_PER_LONG] = word; @@ -143,10 +136,10 @@ uint8_t *qemu_map_cache(target_phys_addr entry = &mapcache_entry[address_index % nr_buckets]; if (entry->vaddr_base == NULL || entry->paddr_index != address_index || - !test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping)) + !test_bit(address_offset>>XC_PAGE_SHIFT, entry->valid_mapping)) qemu_remap_bucket(entry, address_index); - if (!test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping)) + if (!test_bit(address_offset>>XC_PAGE_SHIFT, entry->valid_mapping)) return NULL; last_address_index = address_index; @@ -213,7 +206,7 @@ static void xen_init_fv(uint64_t ram_siz xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn); fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn); - shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, + shared_page = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ|PROT_WRITE, ioreq_pfn); if (shared_page == NULL) { fprintf(logfile, "map shared IO page returned error %d\n", errno); @@ -222,7 +215,7 @@ static void xen_init_fv(uint64_t ram_siz xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn); fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn); - buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, + buffered_io_page = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ|PROT_WRITE, ioreq_pfn); if (buffered_io_page == NULL) { fprintf(logfile, "map buffered IO page returned error %d\n", errno); @@ -272,9 +265,9 @@ static void xen_init_fv(uint64_t ram_siz /* VTI will not use memory between 3G~4G, so we just pass a legal pfn to make QEMU map continuous virtual memory space */ if (ram_size > MMIO_START) { - for (i = 0 ; i < (MEM_G >> PAGE_SHIFT); i++) - page_array[(MMIO_START >> PAGE_SHIFT) + i] = - (STORE_PAGE_START >> PAGE_SHIFT); + for (i = 0 ; i < (MEM_G >> XC_PAGE_SHIFT); i++) + page_array[(MMIO_START >> XC_PAGE_SHIFT) + i] = + (STORE_XC_PAGE_START >> XC_PAGE_SHIFT); } phys_ram_base = xc_map_foreign_batch(xc_handle, domid, diff -r ef6415fdaf8a -r a1247c2df2b4 xen/arch/ia64/xen/mm.c --- a/xen/arch/ia64/xen/mm.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/arch/ia64/xen/mm.c Wed Nov 07 14:48:48 2007 -0700 @@ -2894,11 +2894,9 @@ arch_memory_op(int op, XEN_GUEST_HANDLE( return 0; } -int -iomem_page_test(unsigned long mfn, struct page_info *page) -{ - return unlikely(!mfn_valid(mfn)) || - unlikely(page_get_owner(page) == dom_io); +int is_iomem_page(unsigned long mfn) +{ + return (!mfn_valid(mfn) || (page_get_owner(mfn_to_page(mfn)) == dom_io)); } /* diff -r ef6415fdaf8a -r a1247c2df2b4 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/arch/x86/domain.c Wed Nov 07 14:48:48 2007 -0700 @@ -415,7 +415,8 @@ int vcpu_initialise(struct vcpu *v) v->arch.cr3 = __pa(idle_pg_table); } - v->arch.guest_context.ctrlreg[4] = mmu_cr4_features; + v->arch.guest_context.ctrlreg[4] = + real_cr4_to_pv_guest_cr4(mmu_cr4_features); } v->arch.perdomain_ptes = @@ -573,17 +574,18 @@ void arch_domain_destroy(struct domain * unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4) { - unsigned long hv_cr4 = read_cr4(), hv_cr4_mask = ~X86_CR4_TSD; + unsigned long hv_cr4_mask, hv_cr4 = real_cr4_to_pv_guest_cr4(read_cr4()); + + hv_cr4_mask = ~X86_CR4_TSD; if ( cpu_has_de ) hv_cr4_mask &= ~X86_CR4_DE; - if ( (guest_cr4 & hv_cr4_mask) != - (hv_cr4 & hv_cr4_mask & ~(X86_CR4_PGE|X86_CR4_PSE)) ) + if ( (guest_cr4 & hv_cr4_mask) != (hv_cr4 & hv_cr4_mask) ) gdprintk(XENLOG_WARNING, "Attempt to change CR4 flags %08lx -> %08lx\n", hv_cr4 & ~(X86_CR4_PGE|X86_CR4_PSE), guest_cr4); - return (hv_cr4 & hv_cr4_mask) | (guest_cr4 & ~hv_cr4_mask); + return (hv_cr4 & hv_cr4_mask) | (guest_cr4 & ~hv_cr4_mask); } /* This is called by arch_final_setup_guest and do_boot_vcpu */ @@ -684,8 +686,8 @@ int arch_set_info_guest( v->arch.guest_context.user_regs.eflags |= EF_IE; cr4 = v->arch.guest_context.ctrlreg[4]; - v->arch.guest_context.ctrlreg[4] = - (cr4 == 0) ? mmu_cr4_features : pv_guest_cr4_fixup(cr4); + v->arch.guest_context.ctrlreg[4] = cr4 ? pv_guest_cr4_fixup(cr4) : + real_cr4_to_pv_guest_cr4(mmu_cr4_features); memset(v->arch.guest_context.debugreg, 0, sizeof(v->arch.guest_context.debugreg)); @@ -1223,11 +1225,14 @@ static void paravirt_ctxt_switch_from(st static void paravirt_ctxt_switch_to(struct vcpu *v) { + unsigned long cr4; + set_int80_direct_trap(v); switch_kernel_stack(v); - if ( unlikely(read_cr4() != v->arch.guest_context.ctrlreg[4]) ) - write_cr4(v->arch.guest_context.ctrlreg[4]); + cr4 = pv_guest_cr4_to_real_cr4(v->arch.guest_context.ctrlreg[4]); + if ( unlikely(cr4 != read_cr4()) ) + write_cr4(cr4); if ( unlikely(v->arch.guest_context.debugreg[7]) ) { diff -r ef6415fdaf8a -r a1247c2df2b4 xen/arch/x86/hvm/irq.c --- a/xen/arch/x86/hvm/irq.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/arch/x86/hvm/irq.c Wed Nov 07 14:48:48 2007 -0700 @@ -192,15 +192,12 @@ void hvm_set_pci_link_route(struct domai hvm_irq->pci_link.route[link] = isa_irq; /* PCI pass-through fixup. */ - if ( hvm_irq->dpci && hvm_irq->dpci->girq[old_isa_irq].valid ) - { - uint32_t device = hvm_irq->dpci->girq[old_isa_irq].device; - uint32_t intx = hvm_irq->dpci->girq[old_isa_irq].intx; - if ( link == hvm_pci_intx_link(device, intx) ) - { - hvm_irq->dpci->girq[isa_irq] = hvm_irq->dpci->girq[old_isa_irq]; + if ( hvm_irq->dpci && hvm_irq->dpci->link[link].valid ) + { + hvm_irq->dpci->girq[isa_irq] = hvm_irq->dpci->link[link]; + if ( hvm_irq->dpci->girq[old_isa_irq].device == + hvm_irq->dpci->link[link].device ) hvm_irq->dpci->girq[old_isa_irq].valid = 0; - } } if ( hvm_irq->pci_link_assert_count[link] == 0 ) diff -r ef6415fdaf8a -r a1247c2df2b4 xen/arch/x86/hvm/vmx/intr.c --- a/xen/arch/x86/hvm/vmx/intr.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/intr.c Wed Nov 07 14:48:48 2007 -0700 @@ -113,6 +113,7 @@ static void vmx_dirq_assist(struct vcpu uint32_t device, intx; struct domain *d = v->domain; struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; + struct dev_intx_gsi *dig; if ( !vtd_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) ) return; @@ -122,11 +123,17 @@ static void vmx_dirq_assist(struct vcpu irq = find_next_bit(hvm_irq_dpci->dirq_mask, NR_IRQS, irq + 1) ) { stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(irq)]); - - test_and_clear_bit(irq, &hvm_irq_dpci->dirq_mask); - device = hvm_irq_dpci->mirq[irq].device; - intx = hvm_irq_dpci->mirq[irq].intx; - hvm_pci_intx_assert(d, device, intx); + clear_bit(irq, &hvm_irq_dpci->dirq_mask); + + list_for_each_entry ( dig, &hvm_irq_dpci->mirq[irq].dig_list, list ) + { + device = dig->device; + intx = dig->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); + } /* * Set a timer to see if the guest can finish the interrupt or not. For diff -r ef6415fdaf8a -r a1247c2df2b4 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c --- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c Wed Nov 07 14:48:48 2007 -0700 @@ -688,6 +688,9 @@ static int iommu_enable_translation(stru break; cpu_relax(); } + + /* Disable PMRs when VT-d engine takes effect per spec definition */ + disable_pmr(iommu); spin_unlock_irqrestore(&iommu->register_lock, flags); return 0; } @@ -1767,7 +1770,7 @@ int iommu_setup(void) struct hvm_iommu *hd = domain_hvm_iommu(dom0); struct acpi_drhd_unit *drhd; struct iommu *iommu; - unsigned long i, status; + unsigned long i; if ( !vtd_enabled ) return 0; @@ -1796,10 +1799,6 @@ int iommu_setup(void) setup_dom0_rmrr(); if ( enable_vtd_translation() ) goto error; - - status = dmar_readl(iommu->reg, DMAR_PMEN_REG); - if (status & DMA_PMEN_PRS) - disable_pmr(iommu); return 0; diff -r ef6415fdaf8a -r a1247c2df2b4 xen/arch/x86/hvm/vmx/vtd/io.c --- a/xen/arch/x86/hvm/vmx/vtd/io.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/vtd/io.c Wed Nov 07 14:48:48 2007 -0700 @@ -47,14 +47,27 @@ static void pt_irq_time_out(void *data) { - struct hvm_irq_dpci_mapping *irq_map = data; - unsigned int guest_gsi, machine_gsi; - struct domain *d = irq_map->dom; - - guest_gsi = irq_map->guest_gsi; - machine_gsi = d->arch.hvm_domain.irq.dpci->girq[guest_gsi].machine_gsi; - clear_bit(machine_gsi, d->arch.hvm_domain.irq.dpci->dirq_mask); - hvm_dpci_eoi(irq_map->dom, guest_gsi, NULL); + struct hvm_mirq_dpci_mapping *irq_map = data; + unsigned int guest_gsi, machine_gsi = 0; + struct hvm_irq_dpci *dpci = irq_map->dom->arch.hvm_domain.irq.dpci; + struct dev_intx_gsi *dig; + uint32_t device, intx; + + list_for_each_entry ( dig, &irq_map->dig_list, list ) + { + guest_gsi = dig->gsi; + machine_gsi = dpci->girq[guest_gsi].machine_gsi; + device = dig->device; + intx = dig->intx; + hvm_pci_intx_deassert(irq_map->dom, device, intx); + } + + clear_bit(machine_gsi, dpci->dirq_mask); + stop_timer(&dpci->hvm_timer[irq_to_vector(machine_gsi)]); + spin_lock(&dpci->dirq_lock); + dpci->mirq[machine_gsi].pending = 0; + spin_unlock(&dpci->dirq_lock); + pirq_guest_eoi(irq_map->dom, machine_gsi); } int pt_irq_create_bind_vtd( @@ -62,8 +75,8 @@ int pt_irq_create_bind_vtd( { struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; uint32_t machine_gsi, guest_gsi; - uint32_t device, intx; - uint32_t link, isa_irq; + uint32_t device, intx, link; + struct dev_intx_gsi *dig; if ( hvm_irq_dpci == NULL ) { @@ -72,6 +85,9 @@ int pt_irq_create_bind_vtd( 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].dig_list); if ( cmpxchg((unsigned long *)&d->arch.hvm_domain.irq.dpci, 0, (unsigned long)hvm_irq_dpci) != 0 ) @@ -85,35 +101,42 @@ int pt_irq_create_bind_vtd( intx = pt_irq_bind->u.pci.intx; guest_gsi = hvm_pci_intx_gsi(device, intx); link = hvm_pci_intx_link(device, intx); - isa_irq = d->arch.hvm_domain.irq.pci_link.route[link]; - - hvm_irq_dpci->mirq[machine_gsi].valid = 1; - hvm_irq_dpci->mirq[machine_gsi].device = device; - hvm_irq_dpci->mirq[machine_gsi].intx = intx; - hvm_irq_dpci->mirq[machine_gsi].guest_gsi = guest_gsi; - hvm_irq_dpci->mirq[machine_gsi].dom = d; - + + dig = xmalloc(struct dev_intx_gsi); + if ( !dig ) + return -ENOMEM; + + dig->device = device; + dig->intx = intx; + dig->gsi = guest_gsi; + list_add_tail(&dig->list, + &hvm_irq_dpci->mirq[machine_gsi].dig_list); + hvm_irq_dpci->girq[guest_gsi].valid = 1; hvm_irq_dpci->girq[guest_gsi].device = device; hvm_irq_dpci->girq[guest_gsi].intx = intx; hvm_irq_dpci->girq[guest_gsi].machine_gsi = machine_gsi; - hvm_irq_dpci->girq[guest_gsi].dom = d; - - hvm_irq_dpci->girq[isa_irq].valid = 1; - hvm_irq_dpci->girq[isa_irq].device = device; - hvm_irq_dpci->girq[isa_irq].intx = intx; - hvm_irq_dpci->girq[isa_irq].machine_gsi = machine_gsi; - hvm_irq_dpci->girq[isa_irq].dom = d; - - init_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)], - pt_irq_time_out, &hvm_irq_dpci->mirq[machine_gsi], 0); - - /* Deal with GSI for legacy devices. */ - pirq_guest_bind(d->vcpu[0], machine_gsi, BIND_PIRQ__WILL_SHARE); - gdprintk(XENLOG_ERR, - "XEN_DOMCTL_irq_mapping: m_irq = %x device = %x intx = %x\n", + + hvm_irq_dpci->link[link].valid = 1; + hvm_irq_dpci->link[link].device = device; + hvm_irq_dpci->link[link].intx = intx; + hvm_irq_dpci->link[link].machine_gsi = machine_gsi; + + /* Bind the same mirq once in the same domain */ + if ( !hvm_irq_dpci->mirq[machine_gsi].valid ) + { + hvm_irq_dpci->mirq[machine_gsi].valid = 1; + hvm_irq_dpci->mirq[machine_gsi].dom = d; + + init_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)], + pt_irq_time_out, &hvm_irq_dpci->mirq[machine_gsi], 0); + /* Deal with gsi for legacy devices */ + pirq_guest_bind(d->vcpu[0], machine_gsi, BIND_PIRQ__WILL_SHARE); + } + + gdprintk(XENLOG_INFO, + "VT-d irq bind: m_irq = %x device = %x intx = %x\n", machine_gsi, device, intx); - return 0; } @@ -150,14 +173,22 @@ void hvm_dpci_eoi(struct domain *d, unsi return; machine_gsi = hvm_irq_dpci->girq[guest_gsi].machine_gsi; - stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)]); device = hvm_irq_dpci->girq[guest_gsi].device; intx = hvm_irq_dpci->girq[guest_gsi].intx; - gdprintk(XENLOG_INFO, "hvm_dpci_eoi:: device %x intx %x\n", - device, intx); hvm_pci_intx_deassert(d, device, intx); - if ( (ent == NULL) || !ent->fields.mask ) - pirq_guest_eoi(d, machine_gsi); + + spin_lock(&hvm_irq_dpci->dirq_lock); + if ( --hvm_irq_dpci->mirq[machine_gsi].pending == 0 ) + { + spin_unlock(&hvm_irq_dpci->dirq_lock); + + gdprintk(XENLOG_INFO, "hvm_dpci_eoi:: mirq = %x\n", machine_gsi); + stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)]); + if ( (ent == NULL) || !ent->fields.mask ) + pirq_guest_eoi(d, machine_gsi); + } + else + spin_unlock(&hvm_irq_dpci->dirq_lock); } void iommu_domain_destroy(struct domain *d) @@ -165,8 +196,9 @@ void iommu_domain_destroy(struct domain struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; uint32_t i; struct hvm_iommu *hd = domain_hvm_iommu(d); - struct list_head *ioport_list, *tmp; + struct list_head *ioport_list, *dig_list, *tmp; struct g2m_ioport *ioport; + struct dev_intx_gsi *dig; if ( !vtd_enabled ) return; @@ -178,7 +210,16 @@ void iommu_domain_destroy(struct domain { pirq_guest_unbind(d, i); kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(i)]); + + list_for_each_safe ( dig_list, tmp, + &hvm_irq_dpci->mirq[i].dig_list ) + { + dig = list_entry(dig_list, struct dev_intx_gsi, list); + list_del(&dig->list); + xfree(dig); + } } + d->arch.hvm_domain.irq.dpci = NULL; xfree(hvm_irq_dpci); } diff -r ef6415fdaf8a -r a1247c2df2b4 xen/arch/x86/hvm/vmx/vtd/utils.c --- a/xen/arch/x86/hvm/vmx/vtd/utils.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/vtd/utils.c Wed Nov 07 14:48:48 2007 -0700 @@ -67,25 +67,30 @@ int vtd_hw_check(void) /* Disable vt-d protected memory registers. */ void disable_pmr(struct iommu *iommu) { - unsigned long start_time, status; + unsigned long start_time; unsigned int val; val = dmar_readl(iommu->reg, DMAR_PMEN_REG); + if ( !(val & DMA_PMEN_PRS) ) + return; + dmar_writel(iommu->reg, DMAR_PMEN_REG, val & ~DMA_PMEN_EPM); start_time = jiffies; for ( ; ; ) { - status = dmar_readl(iommu->reg, DMAR_PMEN_REG); - if ( (status & DMA_PMEN_PRS) == 0 ) + val = dmar_readl(iommu->reg, DMAR_PMEN_REG); + if ( (val & DMA_PMEN_PRS) == 0 ) break; + if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) ) - panic("Cannot set QIE field for queue invalidation\n"); + panic("Disable PMRs timeout\n"); + cpu_relax(); } dprintk(XENLOG_INFO VTDPREFIX, - "disabled protected memory registers\n"); + "Disabled protected memory registers\n"); } #if defined(__x86_64__) diff -r ef6415fdaf8a -r a1247c2df2b4 xen/arch/x86/hvm/vpt.c --- a/xen/arch/x86/hvm/vpt.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/arch/x86/hvm/vpt.c Wed Nov 07 14:48:48 2007 -0700 @@ -59,7 +59,7 @@ static void pt_process_missed_ticks(stru if ( mode_is(pt->vcpu->domain, no_missed_tick_accounting) ) { pt->pending_intr_nr = 1; - pt->scheduled = now + pt->scheduled; + pt->scheduled = now + pt->period; } else { diff -r ef6415fdaf8a -r a1247c2df2b4 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/arch/x86/mm.c Wed Nov 07 14:48:48 2007 -0700 @@ -607,10 +607,9 @@ get_##level##_linear_pagetable( } -int iomem_page_test(unsigned long mfn, struct page_info *page) -{ - return unlikely(!mfn_valid(mfn)) || - unlikely(page_get_owner(page) == dom_io); +int is_iomem_page(unsigned long mfn) +{ + return (!mfn_valid(mfn) || (page_get_owner(mfn_to_page(mfn)) == dom_io)); } @@ -620,19 +619,19 @@ get_page_from_l1e( { unsigned long mfn = l1e_get_pfn(l1e); struct page_info *page = mfn_to_page(mfn); + uint32_t l1f = l1e_get_flags(l1e); int okay; - if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) + if ( !(l1f & _PAGE_PRESENT) ) return 1; - if ( unlikely(l1e_get_flags(l1e) & l1_disallow_mask(d)) ) - { - MEM_LOG("Bad L1 flags %x", - l1e_get_flags(l1e) & l1_disallow_mask(d)); + if ( unlikely(l1f & l1_disallow_mask(d)) ) + { + MEM_LOG("Bad L1 flags %x", l1f & l1_disallow_mask(d)); return 0; } - if ( iomem_page_test(mfn, page) ) + if ( is_iomem_page(mfn) ) { /* DOMID_IO reverts to caller for privilege checks. */ if ( d == dom_io ) @@ -657,7 +656,7 @@ get_page_from_l1e( * contribute to writeable mapping refcounts. (This allows the * qemu-dm helper process in dom0 to map the domain's memory without * messing up the count of "real" writable mappings.) */ - okay = (((l1e_get_flags(l1e) & _PAGE_RW) && + okay = (((l1f & _PAGE_RW) && !(unlikely(paging_mode_external(d) && (d != current->domain)))) ? get_page_and_type(page, d, PGT_writable_page) : get_page(page, d)); @@ -667,6 +666,36 @@ get_page_from_l1e( " for dom%d", mfn, get_gpfn_from_mfn(mfn), l1e_get_intpte(l1e), d->domain_id); + } + else if ( (pte_flags_to_cacheattr(l1f) != + ((page->count_info >> PGC_cacheattr_base) & 7)) && + !is_iomem_page(mfn) ) + { + uint32_t x, nx, y = page->count_info; + uint32_t cacheattr = pte_flags_to_cacheattr(l1f); + + if ( is_xen_heap_frame(page) ) + { + if ( (l1f & _PAGE_RW) && + !(unlikely(paging_mode_external(d) && + (d != current->domain))) ) + put_page_type(page); + put_page(page); + MEM_LOG("Attempt to change cache attributes of Xen heap page"); + return 0; + } + + while ( ((y >> PGC_cacheattr_base) & 7) != cacheattr ) + { + x = y; + nx = (x & ~PGC_cacheattr_mask) | (cacheattr << PGC_cacheattr_base); + y = cmpxchg(&page->count_info, x, nx); + } + +#ifdef __x86_64__ + map_pages_to_xen((unsigned long)mfn_to_virt(mfn), mfn, 1, + PAGE_HYPERVISOR | cacheattr_to_pte_flags(cacheattr)); +#endif } return okay; @@ -1825,6 +1854,24 @@ int get_page_type(struct page_info *page } return 1; +} + + +void cleanup_page_cacheattr(struct page_info *page) +{ + uint32_t cacheattr = (page->count_info >> PGC_cacheattr_base) & 7; + + if ( likely(cacheattr == 0) ) + return; + + page->count_info &= ~PGC_cacheattr_mask; + + BUG_ON(is_xen_heap_frame(page)); + +#ifdef __x86_64__ + map_pages_to_xen((unsigned long)page_to_virt(page), page_to_mfn(page), + 1, PAGE_HYPERVISOR); +#endif } @@ -3803,7 +3850,7 @@ static void __memguard_change_range(void { unsigned long _p = (unsigned long)p; unsigned long _l = (unsigned long)l; - unsigned long flags = __PAGE_HYPERVISOR | MAP_SMALL_PAGES; + unsigned int flags = __PAGE_HYPERVISOR | MAP_SMALL_PAGES; /* Ensure we are dealing with a page-aligned whole number of pages. */ ASSERT((_p&~PAGE_MASK) == 0); diff -r ef6415fdaf8a -r a1247c2df2b4 xen/arch/x86/mm/shadow/multi.c --- a/xen/arch/x86/mm/shadow/multi.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/arch/x86/mm/shadow/multi.c Wed Nov 07 14:48:48 2007 -0700 @@ -716,12 +716,14 @@ _sh_propagate(struct vcpu *v, goto done; } - // Must have a valid target_mfn unless this is a prefetch. In the - // case of a prefetch, an invalid mfn means that we can not usefully - // shadow anything, and so we return early. + // Must have a valid target_mfn unless this is a prefetch or an l1 + // pointing at MMIO space. In the case of a prefetch, an invalid + // mfn means that we can not usefully shadow anything, and so we + // return early. // - if ( shadow_mode_refcounts(d) && - !mfn_valid(target_mfn) && (p2mt != p2m_mmio_direct) ) + if ( !mfn_valid(target_mfn) + && !(level == 1 && (!shadow_mode_refcounts(d) + || p2mt == p2m_mmio_direct)) ) { ASSERT((ft == ft_prefetch)); *sp = shadow_l1e_empty(); diff -r ef6415fdaf8a -r a1247c2df2b4 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/arch/x86/traps.c Wed Nov 07 14:48:48 2007 -0700 @@ -1797,7 +1797,8 @@ static int emulate_privileged_op(struct case 4: /* Write CR4 */ v->arch.guest_context.ctrlreg[4] = pv_guest_cr4_fixup(*reg); - write_cr4(v->arch.guest_context.ctrlreg[4]); + write_cr4(pv_guest_cr4_to_real_cr4( + v->arch.guest_context.ctrlreg[4])); break; default: diff -r ef6415fdaf8a -r a1247c2df2b4 xen/common/grant_table.c --- a/xen/common/grant_table.c Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/common/grant_table.c Wed Nov 07 14:48:48 2007 -0700 @@ -332,7 +332,7 @@ __gnttab_map_grant_ref( if ( op->flags & GNTMAP_host_map ) { /* Could be an iomem page for setting up permission */ - if ( iomem_page_test(frame, mfn_to_page(frame)) ) + if ( is_iomem_page(frame) ) { is_iomem = 1; if ( iomem_permit_access(ld, frame, frame) ) @@ -527,7 +527,7 @@ __gnttab_unmap_common( op->flags)) < 0 ) goto unmap_out; } - else if ( iomem_page_test(op->frame, mfn_to_page(op->frame)) && + else if ( is_iomem_page(op->frame) && iomem_access_permitted(ld, op->frame, op->frame) ) { if ( (rc = iomem_deny_access(ld, op->frame, op->frame)) < 0 ) @@ -1651,7 +1651,7 @@ gnttab_release_mappings( BUG_ON(!(act->pin & GNTPIN_hstw_mask)); act->pin -= GNTPIN_hstw_inc; - if ( iomem_page_test(act->frame, mfn_to_page(act->frame)) && + if ( is_iomem_page(act->frame) && iomem_access_permitted(rd, act->frame, act->frame) ) rc = iomem_deny_access(rd, act->frame, act->frame); else diff -r ef6415fdaf8a -r a1247c2df2b4 xen/include/asm-ia64/mm.h --- a/xen/include/asm-ia64/mm.h Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/include/asm-ia64/mm.h Wed Nov 07 14:48:48 2007 -0700 @@ -185,8 +185,7 @@ static inline int get_page(struct page_i return 1; } -/* Decide whether this page looks like iomem or real memory */ -int iomem_page_test(unsigned long mfn, struct page_info *page); +int is_iomem_page(unsigned long mfn); extern void put_page_type(struct page_info *page); extern int get_page_type(struct page_info *page, u32 type); diff -r ef6415fdaf8a -r a1247c2df2b4 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/include/asm-x86/domain.h Wed Nov 07 14:48:48 2007 -0700 @@ -350,7 +350,14 @@ struct arch_vcpu /* Continue the current hypercall via func(data) on specified cpu. */ int continue_hypercall_on_cpu(int cpu, long (*func)(void *data), void *data); +/* Clean up CR4 bits that are not under guest control. */ unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4); + +/* Convert between guest-visible and real CR4 values. */ +#define pv_guest_cr4_to_real_cr4(c) \ + ((c) | (mmu_cr4_features & (X86_CR4_PGE | X86_CR4_PSE))) +#define real_cr4_to_pv_guest_cr4(c) \ + ((c) & ~(X86_CR4_PGE | X86_CR4_PSE)) #endif /* __ASM_DOMAIN_H__ */ diff -r ef6415fdaf8a -r a1247c2df2b4 xen/include/asm-x86/hvm/irq.h --- a/xen/include/asm-x86/hvm/irq.h Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/include/asm-x86/hvm/irq.h Wed Nov 07 14:48:48 2007 -0700 @@ -30,22 +30,35 @@ #include <asm/hvm/vioapic.h> #include <public/hvm/save.h> -struct hvm_irq_dpci_mapping { +struct dev_intx_gsi { + struct list_head list; + uint8_t device; + uint8_t intx; + uint8_t gsi; +}; + +struct hvm_mirq_dpci_mapping { + uint8_t valid; + int pending; + struct list_head dig_list; + struct domain *dom; +}; + +struct hvm_girq_dpci_mapping { uint8_t valid; uint8_t device; uint8_t intx; - struct domain *dom; - union { - uint8_t guest_gsi; - uint8_t machine_gsi; - }; + uint8_t machine_gsi; }; struct hvm_irq_dpci { + spinlock_t dirq_lock; /* Machine IRQ to guest device/intx mapping. */ - struct hvm_irq_dpci_mapping mirq[NR_IRQS]; + struct hvm_mirq_dpci_mapping mirq[NR_IRQS]; /* Guest IRQ to guest device/intx mapping. */ - struct hvm_irq_dpci_mapping girq[NR_IRQS]; + struct hvm_girq_dpci_mapping girq[NR_IRQS]; + /* Link to guest device/intx mapping. */ + struct hvm_girq_dpci_mapping link[4]; DECLARE_BITMAP(dirq_mask, NR_IRQS); struct timer hvm_timer[NR_IRQS]; }; diff -r ef6415fdaf8a -r a1247c2df2b4 xen/include/asm-x86/mm.h --- a/xen/include/asm-x86/mm.h Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/include/asm-x86/mm.h Wed Nov 07 14:48:48 2007 -0700 @@ -84,25 +84,23 @@ struct page_info #define _PGT_pae_xen_l2 26 #define PGT_pae_xen_l2 (1U<<_PGT_pae_xen_l2) - /* 16-bit count of uses of this frame as its current type. */ -#define PGT_count_mask ((1U<<16)-1) + /* 26-bit count of uses of this frame as its current type. */ +#define PGT_count_mask ((1U<<26)-1) /* Cleared when the owning guest 'frees' this page. */ #define _PGC_allocated 31 #define PGC_allocated (1U<<_PGC_allocated) /* Set on a *guest* page to mark it out-of-sync with its shadow */ -#define _PGC_out_of_sync 30 +#define _PGC_out_of_sync 30 #define PGC_out_of_sync (1U<<_PGC_out_of_sync) /* Set when is using a page as a page table */ -#define _PGC_page_table 29 +#define _PGC_page_table 29 #define PGC_page_table (1U<<_PGC_page_table) - /* 29-bit count of references to this frame. */ -#define PGC_count_mask ((1U<<29)-1) - -/* We trust the slab allocator in slab.c, and our use of it. */ -#define PageSlab(page) (1) -#define PageSetSlab(page) ((void)0) -#define PageClearSlab(page) ((void)0) + /* 3-bit PAT/PCD/PWT cache-attribute hint. */ +#define PGC_cacheattr_base 26 +#define PGC_cacheattr_mask (7U<<PGC_cacheattr_base) + /* 26-bit count of references to this frame. */ +#define PGC_count_mask ((1U<<26)-1) #define is_xen_heap_frame(pfn) ({ \ paddr_t maddr = page_to_maddr(pfn); \ @@ -147,6 +145,8 @@ void free_page_type(struct page_info *pa void free_page_type(struct page_info *page, unsigned long type); int _shadow_mode_refcounts(struct domain *d); +void cleanup_page_cacheattr(struct page_info *page); + static inline void put_page(struct page_info *page) { u32 nx, x, y = page->count_info; @@ -158,7 +158,10 @@ static inline void put_page(struct page_ while ( unlikely((y = cmpxchg(&page->count_info, x, nx)) != x) ); if ( unlikely((nx & PGC_count_mask) == 0) ) + { + cleanup_page_cacheattr(page); free_domheap_page(page); + } } @@ -196,8 +199,7 @@ static inline int get_page(struct page_i return 1; } -/* Decide whether this page looks like iomem or real memory */ -int iomem_page_test(unsigned long mfn, struct page_info *page); +int is_iomem_page(unsigned long mfn); void put_page_type(struct page_info *page); int get_page_type(struct page_info *page, unsigned long type); diff -r ef6415fdaf8a -r a1247c2df2b4 xen/include/asm-x86/page.h --- a/xen/include/asm-x86/page.h Wed Nov 07 11:01:23 2007 -0700 +++ b/xen/include/asm-x86/page.h Wed Nov 07 14:48:48 2007 -0700 @@ -360,6 +360,16 @@ int map_pages_to_xen( unsigned int flags); void destroy_xen_mappings(unsigned long v, unsigned long e); +/* Convert between PAT/PCD/PWT embedded in PTE flags and 3-bit cacheattr. */ +static inline uint32_t pte_flags_to_cacheattr(uint32_t flags) +{ + return ((flags >> 5) & 4) | ((flags >> 3) & 3); +} +static inline uint32_t cacheattr_to_pte_flags(uint32_t cacheattr) +{ + return ((cacheattr & 4) << 5) | ((cacheattr & 3) << 3); +} + #endif /* !__ASSEMBLY__ */ #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |