[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] VT-d: Share VT-d code between x86 and IA64
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1207815607 -3600 # Node ID 85848be18ba22814bddeb82a4cfc99e14447cab1 # Parent 3105a548e2f54ca283794baf1cfbe9b8d34c9e96 VT-d: Share VT-d code between x86 and IA64 Declare arch-dependent functions in vtd.h, and implement them for x86. Signed-off-by: Weidong Han <weidong.han@xxxxxxxxx> --- xen/drivers/passthrough/io.c | 74 +++--------------- xen/drivers/passthrough/iommu.c | 2 xen/drivers/passthrough/vtd/Makefile | 2 xen/drivers/passthrough/vtd/iommu.c | 20 +++- xen/drivers/passthrough/vtd/vtd.h | 9 ++ xen/drivers/passthrough/vtd/x86/Makefile | 1 xen/drivers/passthrough/vtd/x86/vtd.c | 126 +++++++++++++++++++++++++++++++ xen/include/xen/iommu.h | 3 8 files changed, 171 insertions(+), 66 deletions(-) diff -r 3105a548e2f5 -r 85848be18ba2 xen/drivers/passthrough/io.c --- a/xen/drivers/passthrough/io.c Thu Apr 10 09:12:44 2008 +0100 +++ b/xen/drivers/passthrough/io.c Thu Apr 10 09:20:07 2008 +0100 @@ -25,7 +25,7 @@ static void pt_irq_time_out(void *data) { 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 hvm_irq_dpci *dpci = domain_get_irq_dpci(irq_map->dom); struct dev_intx_gsi_link *digl; uint32_t device, intx; @@ -49,7 +49,7 @@ int pt_irq_create_bind_vtd( 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 = d->arch.hvm_domain.irq.dpci; + struct hvm_irq_dpci *hvm_irq_dpci = domain_get_irq_dpci(d); uint32_t machine_gsi, guest_gsi; uint32_t device, intx, link; struct dev_intx_gsi_link *digl; @@ -65,11 +65,8 @@ int pt_irq_create_bind_vtd( for ( int i = 0; i < NR_IRQS; i++ ) INIT_LIST_HEAD(&hvm_irq_dpci->mirq[i].digl_list); - if ( cmpxchg((unsigned long *)&d->arch.hvm_domain.irq.dpci, - 0, (unsigned long)hvm_irq_dpci) != 0 ) + if ( domain_set_irq_dpci(d, hvm_irq_dpci) == 0 ) xfree(hvm_irq_dpci); - - hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; } machine_gsi = pt_irq_bind->machine_irq; @@ -116,7 +113,7 @@ int pt_irq_destroy_bind_vtd( 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 = d->arch.hvm_domain.irq.dpci; + struct hvm_irq_dpci *hvm_irq_dpci = domain_get_irq_dpci(d); uint32_t machine_gsi, guest_gsi; uint32_t device, intx, link; struct list_head *digl_list, *tmp; @@ -133,14 +130,15 @@ int pt_irq_destroy_bind_vtd( 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); - memset(&hvm_irq_dpci->girq[guest_gsi], 0, sizeof(struct hvm_girq_dpci_mapping)); + "pt_irq_destroy_bind_vtd: machine_gsi=%d " + "guest_gsi=%d, device=%d, intx=%d.\n", + machine_gsi, guest_gsi, device, intx); + 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].valid ) { - list_for_each_safe ( digl_list, tmp, &hvm_irq_dpci->mirq[machine_gsi].digl_list ) { @@ -174,10 +172,10 @@ int pt_irq_destroy_bind_vtd( int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq) { - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; - - if ( !iommu_enabled || (d == dom0) || (hvm_irq->dpci == NULL) || - !hvm_irq->dpci->mirq[mirq].valid ) + struct hvm_irq_dpci *dpci = domain_get_irq_dpci(d); + + if ( !iommu_enabled || (d == dom0) || !dpci || + !dpci->mirq[mirq].valid ) return 0; /* @@ -186,58 +184,18 @@ int hvm_do_IRQ_dpci(struct domain *d, un * this case the guest may not pick up the interrupt (e.g., masked at the * PIC) and we need to detect that. */ - set_bit(mirq, hvm_irq->dpci->dirq_mask); - set_timer(&hvm_irq->dpci->hvm_timer[irq_to_vector(mirq)], + set_bit(mirq, dpci->dirq_mask); + set_timer(&dpci->hvm_timer[irq_to_vector(mirq)], NOW() + PT_IRQ_TIME_OUT); vcpu_kick(d->vcpu[0]); return 1; } -static 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 = hvm_irq->dpci; - struct dev_intx_gsi_link *digl, *tmp; - int i; - - ASSERT(isairq < NR_ISAIRQS); - if ( !iommu_enabled || !dpci || - !test_bit(isairq, dpci->isairq_map) ) - return; - - /* Multiple mirq may be mapped to one isa irq */ - for ( i = 0; i < NR_IRQS; i++ ) - { - if ( !dpci->mirq[i].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); - gdprintk(XENLOG_INFO VTDPREFIX, - "hvm_dpci_isairq_eoi:: mirq = %x\n", i); - stop_timer(&dpci->hvm_timer[irq_to_vector(i)]); - pirq_guest_eoi(d, i); - } - else - spin_unlock(&dpci->dirq_lock); - } - } - } -} - void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi, union vioapic_redir_entry *ent) { - struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; + struct hvm_irq_dpci *hvm_irq_dpci = domain_get_irq_dpci(d); uint32_t device, intx, machine_gsi; if ( !iommu_enabled || (hvm_irq_dpci == NULL) || diff -r 3105a548e2f5 -r 85848be18ba2 xen/drivers/passthrough/iommu.c --- a/xen/drivers/passthrough/iommu.c Thu Apr 10 09:12:44 2008 +0100 +++ b/xen/drivers/passthrough/iommu.c Thu Apr 10 09:20:07 2008 +0100 @@ -58,7 +58,7 @@ int assign_device(struct domain *d, u8 b void iommu_domain_destroy(struct domain *d) { - struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; + struct hvm_irq_dpci *hvm_irq_dpci = domain_get_irq_dpci(d); uint32_t i; struct hvm_iommu *hd = domain_hvm_iommu(d); struct list_head *ioport_list, *digl_list, *tmp; diff -r 3105a548e2f5 -r 85848be18ba2 xen/drivers/passthrough/vtd/Makefile --- a/xen/drivers/passthrough/vtd/Makefile Thu Apr 10 09:12:44 2008 +0100 +++ b/xen/drivers/passthrough/vtd/Makefile Thu Apr 10 09:20:07 2008 +0100 @@ -1,3 +1,5 @@ obj-y += iommu.o +subdir-$(x86) += x86 + obj-y += iommu.o obj-y += dmar.o obj-y += utils.o diff -r 3105a548e2f5 -r 85848be18ba2 xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Thu Apr 10 09:12:44 2008 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Thu Apr 10 09:20:07 2008 +0100 @@ -32,6 +32,7 @@ #include "../pci_regs.h" #include "msi.h" #include "extern.h" +#include "vtd.h" #define domain_iommu_domid(d) ((d)->arch.hvm_domain.hvm_iommu.iommu_domid) @@ -158,11 +159,11 @@ struct iommu_flush *iommu_get_flush(stru return &(iommu->intel->flush); } -unsigned int x86_clflush_size; +unsigned int clflush_size; void clflush_cache_range(void *adr, int size) { int i; - for ( i = 0; i < size; i += x86_clflush_size ) + for ( i = 0; i < size; i += clflush_size ) clflush(adr + i); } @@ -172,10 +173,15 @@ static void __iommu_flush_cache(struct i clflush_cache_range(addr, size); } -#define iommu_flush_cache_entry(iommu, addr) \ - __iommu_flush_cache(iommu, addr, 8) -#define iommu_flush_cache_page(iommu, addr) \ - __iommu_flush_cache(iommu, addr, PAGE_SIZE_4K) +void iommu_flush_cache_entry(struct iommu *iommu, void *addr) +{ + __iommu_flush_cache(iommu, addr, 8); +} + +void iommu_flush_cache_page(struct iommu *iommu, void *addr) +{ + __iommu_flush_cache(iommu, addr, PAGE_SIZE_4K); +} int nr_iommus; /* context entry handling */ @@ -1954,7 +1960,7 @@ int iommu_setup(void) INIT_LIST_HEAD(&hd->pdev_list); /* setup clflush size */ - x86_clflush_size = ((cpuid_ebx(1) >> 8) & 0xff) * 8; + clflush_size = get_clflush_size(); /* Allocate IO page directory page for the domain. */ drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); diff -r 3105a548e2f5 -r 85848be18ba2 xen/drivers/passthrough/vtd/vtd.h --- a/xen/drivers/passthrough/vtd/vtd.h Thu Apr 10 09:12:44 2008 +0100 +++ b/xen/drivers/passthrough/vtd/vtd.h Thu Apr 10 09:20:07 2008 +0100 @@ -42,4 +42,13 @@ struct IO_APIC_route_remap_entry { }; }; +unsigned int get_clflush_size(void); +u64 alloc_pgtable_maddr(void); +void free_pgtable_maddr(u64 maddr); +void *map_vtd_domain_page(u64 maddr); +void unmap_vtd_domain_page(void *va); + +void iommu_flush_cache_entry(struct iommu *iommu, void *addr); +void iommu_flush_cache_page(struct iommu *iommu, void *addr); + #endif // _VTD_H_ diff -r 3105a548e2f5 -r 85848be18ba2 xen/drivers/passthrough/vtd/x86/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/drivers/passthrough/vtd/x86/Makefile Thu Apr 10 09:20:07 2008 +0100 @@ -0,0 +1,1 @@ +obj-y += vtd.o diff -r 3105a548e2f5 -r 85848be18ba2 xen/drivers/passthrough/vtd/x86/vtd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/drivers/passthrough/vtd/x86/vtd.c Thu Apr 10 09:20:07 2008 +0100 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2008, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Copyright (C) Allen Kay <allen.m.kay@xxxxxxxxx> + * Copyright (C) Weidong Han <weidong.han@xxxxxxxxx> + */ + +#include <xen/sched.h> +#include <xen/domain_page.h> +#include <xen/iommu.h> +#include "../iommu.h" +#include "../dmar.h" +#include "../vtd.h" + +void *map_vtd_domain_page(u64 maddr) +{ + return map_domain_page(maddr >> PAGE_SHIFT_4K); +} + +void unmap_vtd_domain_page(void *va) +{ + unmap_domain_page(va); +} + +/* Allocate page table, return its machine address */ +u64 alloc_pgtable_maddr(void) +{ + struct page_info *pg; + u64 *vaddr; + struct acpi_drhd_unit *drhd; + struct iommu *iommu; + + pg = alloc_domheap_page(NULL, 0); + vaddr = map_domain_page(page_to_mfn(pg)); + if ( !vaddr ) + return 0; + memset(vaddr, 0, PAGE_SIZE); + + drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); + iommu = drhd->iommu; + iommu_flush_cache_page(iommu, vaddr); + unmap_domain_page(vaddr); + + return page_to_maddr(pg); +} + +void free_pgtable_maddr(u64 maddr) +{ + if ( maddr != 0 ) + free_domheap_page(maddr_to_page(maddr)); +} + +unsigned int get_clflush_size(void) +{ + return ((cpuid_ebx(1) >> 8) & 0xff) * 8; +} + +struct hvm_irq_dpci *domain_get_irq_dpci(struct domain *domain) +{ + if ( !domain ) + return NULL; + + return domain->arch.hvm_domain.irq.dpci; +} + +int domain_set_irq_dpci(struct domain *domain, struct hvm_irq_dpci *dpci) +{ + if ( !domain || !dpci ) + return 0; + + domain->arch.hvm_domain.irq.dpci = dpci; + return 1; +} + +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 dev_intx_gsi_link *digl, *tmp; + int i; + + ASSERT(isairq < NR_ISAIRQS); + if ( !vtd_enabled || !dpci || + !test_bit(isairq, dpci->isairq_map) ) + return; + + /* Multiple mirq may be mapped to one isa irq */ + for ( i = 0; i < NR_IRQS; i++ ) + { + if ( !dpci->mirq[i].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); + gdprintk(XENLOG_INFO VTDPREFIX, + "hvm_dpci_isairq_eoi:: mirq = %x\n", i); + stop_timer(&dpci->hvm_timer[irq_to_vector(i)]); + pirq_guest_eoi(d, i); + } + else + spin_unlock(&dpci->dirq_lock); + } + } + } +} diff -r 3105a548e2f5 -r 85848be18ba2 xen/include/xen/iommu.h --- a/xen/include/xen/iommu.h Thu Apr 10 09:12:44 2008 +0100 +++ b/xen/include/xen/iommu.h Thu Apr 10 09:20:07 2008 +0100 @@ -98,6 +98,9 @@ struct qi_ctrl *iommu_qi_ctrl(struct iom struct qi_ctrl *iommu_qi_ctrl(struct iommu *iommu); struct ir_ctrl *iommu_ir_ctrl(struct iommu *iommu); struct iommu_flush *iommu_get_flush(struct iommu *iommu); +void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq); +struct hvm_irq_dpci *domain_get_irq_dpci(struct domain *domain); +int domain_set_irq_dpci(struct domain *domain, struct hvm_irq_dpci *dpci); #define PT_IRQ_TIME_OUT MILLISECS(8) #define VTDPREFIX "[VT-D]" _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |