# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1189608159 -3600
# Node ID ca495837a7223259ecbdc9f8b1ab69d08ed11002
# Parent 9dd580b8b056860fe7634bb964e2bcf201e87bd6
Generic and VT-d specific Xen header changes for PCI passthru.
Signed-off-by: Allen Kay <allen.m.kay@xxxxxxxxx>
Signed-off-by: Guy Zana <guy@xxxxxxxxxxxx>
---
xen/include/asm-x86/acpi.h | 2
xen/include/asm-x86/fixmap.h | 3
xen/include/asm-x86/hvm/domain.h | 5
xen/include/asm-x86/hvm/io.h | 1
xen/include/asm-x86/hvm/iommu.h | 40 ++
xen/include/asm-x86/hvm/irq.h | 16 +
xen/include/asm-x86/hvm/vmx/intel-iommu.h | 401 ++++++++++++++++++++++++++++++
xen/include/asm-x86/iommu.h | 79 +++++
xen/include/asm-x86/system.h | 3
xen/include/public/domctl.h | 68 +++++
xen/include/xen/acpi.h | 70 +++++
xen/include/xen/irq.h | 3
12 files changed, 690 insertions(+), 1 deletion(-)
diff -r 9dd580b8b056 -r ca495837a722 xen/include/asm-x86/acpi.h
--- a/xen/include/asm-x86/acpi.h Wed Sep 12 15:32:58 2007 +0100
+++ b/xen/include/asm-x86/acpi.h Wed Sep 12 15:42:39 2007 +0100
@@ -196,4 +196,6 @@ extern u8 x86_acpiid_to_apicid[];
extern u8 x86_acpiid_to_apicid[];
#define MAX_LOCAL_APIC 256
+extern int acpi_dmar_init(void);
+
#endif /*_ASM_ACPI_H*/
diff -r 9dd580b8b056 -r ca495837a722 xen/include/asm-x86/fixmap.h
--- a/xen/include/asm-x86/fixmap.h Wed Sep 12 15:32:58 2007 +0100
+++ b/xen/include/asm-x86/fixmap.h Wed Sep 12 15:42:39 2007 +0100
@@ -17,6 +17,7 @@
#include <asm/acpi.h>
#include <asm/page.h>
#include <xen/kexec.h>
+#include <asm/iommu.h>
/*
* Here we define all the compile-time 'special' virtual
@@ -40,6 +41,8 @@ enum fixed_addresses {
FIX_KEXEC_BASE_0,
FIX_KEXEC_BASE_END = FIX_KEXEC_BASE_0 \
+ ((KEXEC_XEN_NO_PAGES >> 1) * KEXEC_IMAGE_NR) - 1,
+ FIX_IOMMU_REGS_BASE_0,
+ FIX_IOMMU_REGS_END = FIX_IOMMU_REGS_BASE_0 + MAX_IOMMUS-1,
__end_of_fixed_addresses
};
diff -r 9dd580b8b056 -r ca495837a722 xen/include/asm-x86/hvm/domain.h
--- a/xen/include/asm-x86/hvm/domain.h Wed Sep 12 15:32:58 2007 +0100
+++ b/xen/include/asm-x86/hvm/domain.h Wed Sep 12 15:42:39 2007 +0100
@@ -21,10 +21,12 @@
#ifndef __ASM_X86_HVM_DOMAIN_H__
#define __ASM_X86_HVM_DOMAIN_H__
+#include <asm/iommu.h>
#include <asm/hvm/irq.h>
#include <asm/hvm/vpt.h>
#include <asm/hvm/vlapic.h>
#include <asm/hvm/io.h>
+#include <asm/hvm/iommu.h>
#include <public/hvm/params.h>
#include <public/hvm/save.h>
@@ -57,6 +59,9 @@ struct hvm_domain {
uint64_t params[HVM_NR_PARAMS];
unsigned long vmx_apic_access_mfn;
+
+ /* Pass-through */
+ struct hvm_iommu hvm_iommu;
};
#endif /* __ASM_X86_HVM_DOMAIN_H__ */
diff -r 9dd580b8b056 -r ca495837a722 xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h Wed Sep 12 15:32:58 2007 +0100
+++ b/xen/include/asm-x86/hvm/io.h Wed Sep 12 15:42:39 2007 +0100
@@ -151,6 +151,7 @@ extern void handle_mmio(unsigned long gp
extern void handle_mmio(unsigned long gpa);
extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
extern void hvm_io_assist(void);
+extern void hvm_dpci_eoi(unsigned int guest_irq, union vioapic_redir_entry
*ent);
#endif /* __ASM_X86_HVM_IO_H__ */
diff -r 9dd580b8b056 -r ca495837a722 xen/include/asm-x86/hvm/iommu.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/hvm/iommu.h Wed Sep 12 15:42:39 2007 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2006, 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>
+ */
+
+#ifndef __ASM_X86_HVM_IOMMU_H__
+#define __ASM_X86_HVM_IOMMU_H__
+
+#include <asm/iommu.h>
+#include <asm/hvm/irq.h>
+#include <asm/hvm/vpt.h>
+#include <asm/hvm/vlapic.h>
+#include <asm/hvm/io.h>
+#include <public/hvm/params.h>
+#include <public/hvm/save.h>
+
+struct hvm_iommu {
+ spinlock_t iommu_list_lock; /* protect iommu specific lists */
+ struct list_head pdev_list; /* direct accessed pci devices */
+ struct dma_pte *pgd; /* io page directory root */
+ spinlock_t mapping_lock; /* io page table lock */
+ int agaw; /* adjusted guest address width, 0 is level 2 30-bit */
+ struct list_head g2m_ioport_list; /* guest to machine ioport mapping */
+};
+
+#endif // __ASM_X86_HVM_IOMMU_H__
diff -r 9dd580b8b056 -r ca495837a722 xen/include/asm-x86/hvm/irq.h
--- a/xen/include/asm-x86/hvm/irq.h Wed Sep 12 15:32:58 2007 +0100
+++ b/xen/include/asm-x86/hvm/irq.h Wed Sep 12 15:42:39 2007 +0100
@@ -28,6 +28,16 @@
#include <asm/hvm/vpic.h>
#include <asm/hvm/vioapic.h>
#include <public/hvm/save.h>
+
+struct hvm_irq_mapping {
+ uint8_t valid;
+ uint8_t device;
+ uint8_t intx;
+ union {
+ uint8_t guest_gsi;
+ uint8_t machine_gsi;
+ };
+};
struct hvm_irq {
/*
@@ -88,6 +98,12 @@ struct hvm_irq {
/* Last VCPU that was delivered a LowestPrio interrupt. */
u8 round_robin_prev_vcpu;
+
+ /* machine irq to guest device/intx mapping */
+ struct hvm_irq_mapping mirq[NR_IRQS];
+ /* guest irq to guest device/intx mapping */
+ struct hvm_irq_mapping girq[NR_IRQS];
+ DECLARE_BITMAP(dirq_mask, NR_IRQS);
};
#define hvm_pci_intx_gsi(dev, intx) \
diff -r 9dd580b8b056 -r ca495837a722 xen/include/asm-x86/hvm/vmx/intel-iommu.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/hvm/vmx/intel-iommu.h Wed Sep 12 15:42:39 2007 +0100
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2006, 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) Ashok Raj <ashok.raj@xxxxxxxxx>
+ */
+
+#ifndef _INTEL_IOMMU_H_
+#define _INTEL_IOMMU_H_
+
+#include <xen/types.h>
+
+/*
+ * Intel IOMMU register specification per version 1.0 public spec.
+ */
+
+#define DMAR_VER_REG 0x0 /* Arch version supported by this IOMMU */
+#define DMAR_CAP_REG 0x8 /* Hardware supported capabilities */
+#define DMAR_ECAP_REG 0x10 /* Extended capabilities supported */
+#define DMAR_GCMD_REG 0x18 /* Global command register */
+#define DMAR_GSTS_REG 0x1c /* Global status register */
+#define DMAR_RTADDR_REG 0x20 /* Root entry table */
+#define DMAR_CCMD_REG 0x28 /* Context command reg */
+#define DMAR_FSTS_REG 0x34 /* Fault Status register */
+#define DMAR_FECTL_REG 0x38 /* Fault control register */
+#define DMAR_FEDATA_REG 0x3c /* Fault event interrupt data register */
+#define DMAR_FEADDR_REG 0x40 /* Fault event interrupt addr register */
+#define DMAR_FEUADDR_REG 0x44 /* Upper address register */
+#define DMAR_AFLOG_REG 0x58 /* Advanced Fault control */
+#define DMAR_PMEN_REG 0x64 /* Enable Protected Memory Region */
+#define DMAR_PLMBASE_REG 0x68 /* PMRR Low addr */
+#define DMAR_PLMLIMIT_REG 0x6c /* PMRR low limit */
+#define DMAR_PHMBASE_REG 0x70 /* pmrr high base addr */
+#define DMAR_PHMLIMIT_REG 0x78 /* pmrr high limit */
+#define DMAR_IQH_REG 0x80 /* invalidation queue head */
+#define DMAR_IQT_REG 0x88 /* invalidation queue tail */
+#define DMAR_IQA_REG 0x90 /* invalidation queue addr */
+#define DMAR_IRTA_REG 0xB8 /* intr remap */
+
+#define OFFSET_STRIDE (9)
+#define dmar_readl(dmar, reg) readl(dmar + reg)
+#define dmar_writel(dmar, reg, val) writel(val, dmar + reg)
+#define dmar_readq(dmar, reg) ({ \
+ u32 lo, hi; \
+ lo = dmar_readl(dmar, reg); \
+ hi = dmar_readl(dmar, reg + 4); \
+ (((u64) hi) << 32) + lo; })
+#define dmar_writeq(dmar, reg, val) do {\
+ dmar_writel(dmar, reg, (u32)val); \
+ dmar_writel(dmar, reg + 4, (u32)((u64) val >> 32)); \
+ } while (0)
+
+#define VER_MAJOR(v) (((v) & 0xf0) >> 4)
+#define VER_MINOR(v) ((v) & 0x0f)
+
+/*
+ * Decoding Capability Register
+ */
+#define cap_read_drain(c) (((c) >> 55) & 1)
+#define cap_write_drain(c) (((c) >> 54) & 1)
+#define cap_max_amask_val(c) (((c) >> 48) & 0x3f)
+#define cap_num_fault_regs(c) ((((c) >> 40) & 0xff) + 1)
+#define cap_pgsel_inv(c) (((c) >> 39) & 1)
+
+#define cap_super_page_val(c) (((c) >> 34) & 0xf)
+#define cap_super_offset(c) (((find_first_bit(&cap_super_page_val(c), 4)) \
+ * OFFSET_STRIDE) + 21)
+
+#define cap_fault_reg_offset(c) ((((c) >> 24) & 0x3ff) * 16)
+
+#define cap_isoch(c) (((c) >> 23) & 1)
+#define cap_qos(c) (((c) >> 22) & 1)
+#define cap_mgaw(c) ((((c) >> 16) & 0x3f) + 1)
+#define cap_sagaw(c) (((c) >> 8) & 0x1f)
+#define cap_caching_mode(c) (((c) >> 7) & 1)
+#define cap_phmr(c) (((c) >> 6) & 1)
+#define cap_plmr(c) (((c) >> 5) & 1)
+#define cap_rwbf(c) (((c) >> 4) & 1)
+#define cap_afl(c) (((c) >> 3) & 1)
+#define cap_ndoms(c) (2 ^ (4 + 2 * ((c) & 0x7)))
+/*
+ * Extended Capability Register
+ */
+
+#define ecap_niotlb_iunits(e) ((((e) >> 24) & 0xff) + 1)
+#define ecap_iotlb_offset(e) ((((e) >> 8) & 0x3ff) * 16)
+#define ecap_coherent(e) ((e >> 0) & 0x1)
+#define ecap_queued_inval(e) ((e >> 1) & 0x1)
+#define ecap_dev_iotlb(e) ((e >> 2) & 0x1)
+#define ecap_intr_remap(e) ((e >> 3) & 0x1)
+#define ecap_ext_intr(e) ((e >> 4) & 0x1)
+#define ecap_cache_hints(e) ((e >> 5) & 0x1)
+#define ecap_pass_thru(e) ((e >> 6) & 0x1)
+
+#define PAGE_SHIFT_4K (12)
+#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K)
+#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K)
+#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
+
+/* IOTLB_REG */
+#define DMA_TLB_FLUSH_GRANU_OFFSET 60
+#define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60)
+#define DMA_TLB_DSI_FLUSH (((u64)2) << 60)
+#define DMA_TLB_PSI_FLUSH (((u64)3) << 60)
+#define DMA_TLB_IIRG(x) (((x) >> 60) & 7)
+#define DMA_TLB_IAIG(val) (((val) >> 57) & 7)
+#define DMA_TLB_DID(x) (((u64)(x & 0xffff)) << 32)
+
+#define DMA_TLB_READ_DRAIN (((u64)1) << 49)
+#define DMA_TLB_WRITE_DRAIN (((u64)1) << 48)
+#define DMA_TLB_IVT (((u64)1) << 63)
+
+#define DMA_TLB_IVA_ADDR(x) ((((u64)x) >> 12) << 12)
+#define DMA_TLB_IVA_HINT(x) ((((u64)x) & 1) << 6)
+
+/* GCMD_REG */
+#define DMA_GCMD_TE (((u64)1) << 31)
+#define DMA_GCMD_SRTP (((u64)1) << 30)
+#define DMA_GCMD_SFL (((u64)1) << 29)
+#define DMA_GCMD_EAFL (((u64)1) << 28)
+#define DMA_GCMD_WBF (((u64)1) << 27)
+#define DMA_GCMD_QIE (((u64)1) << 26)
+#define DMA_GCMD_IRE (((u64)1) << 25)
+#define DMA_GCMD_SIRTP (((u64)1) << 24)
+
+/* GSTS_REG */
+#define DMA_GSTS_TES (((u64)1) << 31)
+#define DMA_GSTS_RTPS (((u64)1) << 30)
+#define DMA_GSTS_FLS (((u64)1) << 29)
+#define DMA_GSTS_AFLS (((u64)1) << 28)
+#define DMA_GSTS_WBFS (((u64)1) << 27)
+#define DMA_GSTS_IRTPS (((u64)1) << 24)
+#define DMA_GSTS_QIES (((u64)1) <<26)
+#define DMA_GSTS_IRES (((u64)1) <<25)
+
+/* CCMD_REG */
+#define DMA_CCMD_INVL_GRANU_OFFSET 61
+#define DMA_CCMD_ICC (((u64)1) << 63)
+#define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
+#define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61)
+#define DMA_CCMD_DEVICE_INVL (((u64)3) << 61)
+#define DMA_CCMD_FM(m) (((u64)((m) & 0x3)) << 32)
+#define DMA_CCMD_CIRG(x) ((((u64)3) << 61) & x)
+#define DMA_CCMD_MASK_NOBIT 0
+#define DMA_CCMD_MASK_1BIT 1
+#define DMA_CCMD_MASK_2BIT 2
+#define DMA_CCMD_MASK_3BIT 3
+#define DMA_CCMD_SID(s) (((u64)((s) & 0xffff)) << 16)
+#define DMA_CCMD_DID(d) ((u64)((d) & 0xffff))
+
+#define DMA_CCMD_CAIG_MASK(x) (((u64)x) & ((u64) 0x3 << 59))
+
+/* FECTL_REG */
+#define DMA_FECTL_IM (((u64)1) << 31)
+
+/* FSTS_REG */
+#define DMA_FSTS_PPF ((u64)2)
+#define DMA_FSTS_PFO ((u64)1)
+#define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
+
+/* FRCD_REG, 32 bits access */
+#define DMA_FRCD_F (((u64)1) << 31)
+#define dma_frcd_type(d) ((d >> 30) & 1)
+#define dma_frcd_fault_reason(c) (c & 0xff)
+#define dma_frcd_source_id(c) (c & 0xffff)
+#define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */
+
+/*
+ * 0: Present
+ * 1-11: Reserved
+ * 12-63: Context Ptr (12 - (haw-1))
+ * 64-127: Reserved
+ */
+struct root_entry {
+ u64 val;
+ u64 rsvd1;
+};
+#define root_present(root) ((root).val & 1)
+#define set_root_present(root) do {(root).val |= 1;} while(0)
+#define get_context_addr(root) ((root).val & PAGE_MASK_4K)
+#define set_root_value(root, value) \
+ do {(root).val |= ((value) & PAGE_MASK_4K);} while(0)
+
+struct context_entry {
+ u64 lo;
+ u64 hi;
+};
+#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry))
+#define context_present(c) ((c).lo & 1)
+#define context_fault_disable(c) (((c).lo >> 1) & 1)
+#define context_translation_type(c) (((c).lo >> 2) & 3)
+#define context_address_root(c) ((c).lo & PAGE_MASK_4K)
+#define context_address_width(c) ((c).hi & 7)
+#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1))
+
+#define context_set_present(c) do {(c).lo |= 1;} while(0)
+#define context_clear_present(c) do {(c).lo &= ~1;} while(0)
+#define context_set_fault_enable(c) \
+ do {(c).lo &= (((u64)-1) << 2) | 1;} while(0)
+
+#define context_set_translation_type(c, val) do { \
+ (c).lo &= (((u64)-1) << 4) | 3; \
+ (c).lo |= (val & 3) << 2; \
+ } while(0)
+#define CONTEXT_TT_MULTI_LEVEL 0
+#define CONTEXT_TT_DEV_IOTLB 1
+#define CONTEXT_TT_PASS_THRU 2
+
+#define context_set_address_root(c, val) \
+ do {(c).lo &= 0xfff; (c).lo |= (val) & PAGE_MASK_4K ;} while(0)
+#define context_set_address_width(c, val) \
+ do {(c).hi &= 0xfffffff8; (c).hi |= (val) & 7;} while(0)
+#define context_set_domain_id(c, val) \
+ do {(c).hi &= 0xff; (c).hi |= ((val + 1) & ((1 << 16) - 1)) << 8;} while(0)
+#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while(0)
+
+/*
+ * 0: readable
+ * 1: writable
+ * 2-6: reserved
+ * 7: super page
+ * 8-11: available
+ * 12-63: Host physcial address
+ */
+struct dma_pte {
+ u64 val;
+};
+#define dma_clear_pte(p) do {(p).val = 0;} while(0)
+#define dma_set_pte_readable(p) do {(p).val |= 1;} while(0)
+#define dma_set_pte_writable(p) do {(p).val |= 2;} while(0)
+#define dma_set_pte_superpage(p) do {(p).val |= 8;} while(0)
+#define dma_set_pte_prot(p, prot) do { (p).val = (((p).val >> 2) << 2) |
((prot) & 3);} while (0)
+#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
+#define dma_set_pte_addr(p, addr) do {(p).val |= ((addr) >> PAGE_SHIFT_4K) <<
PAGE_SHIFT_4K;} while(0)
+#define DMA_PTE_READ (1)
+#define DMA_PTE_WRITE (2)
+#define dma_pte_present(p) (((p).val & 3) != 0)
+
+/* interrupt remap entry */
+struct iremap_entry {
+ struct {
+ u64 present : 1,
+ fpd : 1,
+ dm : 1,
+ rh : 1,
+ tm : 1,
+ dlm : 3,
+ avail : 4,
+ res_1 : 4,
+ vector : 8,
+ res_2 : 8,
+ dst : 32;
+ }lo;
+ struct {
+ u64 sid : 16,
+ sq : 2,
+ svt : 2,
+ res_1 : 44;
+ }hi;
+};
+#define IREMAP_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct iremap_entry))
+#define iremap_present(v) ((v).lo & 1)
+#define iremap_fault_disable(v) (((v).lo >> 1) & 1)
+
+#define iremap_set_present(v) do {(v).lo |= 1;} while(0)
+#define iremap_clear_present(v) do {(v).lo &= ~1;} while(0)
+
+/* queue invalidation entry */
+struct qinval_entry {
+ union {
+ struct {
+ struct {
+ u64 type : 4,
+ granu : 2,
+ res_1 : 10,
+ did : 16,
+ sid : 16,
+ fm : 2,
+ res_2 : 14;
+ }lo;
+ struct {
+ u64 res;
+ }hi;
+ }cc_inv_dsc;
+ struct {
+ struct {
+ u64 type : 4,
+ granu : 2,
+ dw : 1,
+ dr : 1,
+ res_1 : 8,
+ did : 16,
+ res_2 : 32;
+ }lo;
+ struct {
+ u64 am : 6,
+ ih : 1,
+ res_1 : 5,
+ addr : 52;
+ }hi;
+ }iotlb_inv_dsc;
+ struct {
+ struct {
+ u64 type : 4,
+ res_1 : 12,
+ max_invs_pend: 5,
+ res_2 : 11,
+ sid : 16,
+ res_3 : 16;
+ }lo;
+ struct {
+ u64 size : 1,
+ res_1 : 11,
+ addr : 52;
+ }hi;
+ }dev_iotlb_inv_dsc;
+ struct {
+ struct {
+ u64 type : 4,
+ granu : 1,
+ res_1 : 22,
+ im : 5,
+ iidx : 16,
+ res_2 : 16;
+ }lo;
+ struct {
+ u64 res;
+ }hi;
+ }iec_inv_dsc;
+ struct {
+ struct {
+ u64 type : 4,
+ iflag : 1,
+ sw : 1,
+ fn : 1,
+ res_1 : 25,
+ sdata : 32;
+ }lo;
+ struct {
+ u64 res_1 : 2,
+ saddr : 62;
+ }hi;
+ }inv_wait_dsc;
+ }q;
+};
+
+struct poll_info {
+ u64 saddr;
+ u32 udata;
+};
+
+#define QINVAL_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct qinval_entry))
+#define qinval_present(v) ((v).lo & 1)
+#define qinval_fault_disable(v) (((v).lo >> 1) & 1)
+
+#define qinval_set_present(v) do {(v).lo |= 1;} while(0)
+#define qinval_clear_present(v) do {(v).lo &= ~1;} while(0)
+
+#define RESERVED_VAL 0
+
+#define TYPE_INVAL_CONTEXT 1
+#define TYPE_INVAL_IOTLB 2
+#define TYPE_INVAL_DEVICE_IOTLB 3
+#define TYPE_INVAL_IEC 4
+#define TYPE_INVAL_WAIT 5
+
+#define NOTIFY_TYPE_POLL 1
+#define NOTIFY_TYPE_INTR 1
+#define INTERRUTP_FLAG 1
+#define STATUS_WRITE 1
+#define FENCE_FLAG 1
+
+#define IEC_GLOBAL_INVL 0
+#define IEC_INDEX_INVL 1
+
+#define VTD_PAGE_TABLE_LEVEL_3 3
+#define VTD_PAGE_TABLE_LEVEL_4 4
+
+typedef paddr_t dma_addr_t;
+
+#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
+#define MAX_IOMMUS 32
+#define MAX_IOMMU_REGS 0xc0
+
+extern struct list_head acpi_drhd_units;
+extern struct list_head acpi_rmrr_units;
+extern struct list_head acpi_ioapic_units;
+
+#endif
diff -r 9dd580b8b056 -r ca495837a722 xen/include/asm-x86/iommu.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/iommu.h Wed Sep 12 15:42:39 2007 +0100
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2006, 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>
+ */
+
+#ifndef _IOMMU_H_
+#define _IOMMU_H_
+
+#include <xen/init.h>
+#include <xen/bitmap.h>
+#include <xen/irq.h>
+#include <xen/spinlock.h>
+#include <xen/mm.h>
+#include <xen/xmalloc.h>
+#include <asm/hvm/vmx/intel-iommu.h>
+#include <public/hvm/ioreq.h>
+
+extern int vtd_enabled;
+
+#define domain_hvm_iommu(d) (&d->arch.hvm_domain.hvm_iommu)
+#define domain_vmx_iommu(d) (&d->arch.hvm_domain.hvm_iommu.vmx_iommu)
+
+/*
+ * The PCI interface treats multi-function devices as independent
+ * devices. The slot/function address of each device is encoded
+ * in a single byte as follows:
+ *
+ * 15:8 = bus
+ * 7:3 = slot
+ * 2:0 = function
+ */
+#define PCI_DEVFN(slot,func) (((slot & 0x1f) << 3) | (func & 0x07))
+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
+
+struct pci_dev {
+ struct list_head list;
+ u8 bus;
+ u8 devfn;
+};
+
+struct iommu {
+ struct list_head list;
+ void __iomem *reg; /* Pointer to hardware regs, virtual addr */
+ u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
+ u64 cap;
+ u64 ecap;
+ spinlock_t lock; /* protect context, domain ids */
+ spinlock_t register_lock; /* protect iommu register handling */
+ struct root_entry *root_entry; /* virtual address */
+ unsigned int vector;
+};
+
+int iommu_setup(void);
+int iommu_domain_init(struct domain *d);
+int assign_device(struct domain *d, u8 bus, u8 devfn);
+int release_devices(struct domain *d);
+int iommu_map_page(struct domain *d, dma_addr_t gfn, dma_addr_t mfn);
+int iommu_unmap_page(struct domain *d, dma_addr_t gfn);
+void iommu_flush(struct domain *d, dma_addr_t gfn, u64 *p2m_entry);
+void iommu_set_pgd(struct domain *d);
+void iommu_domain_teardown(struct domain *d);
+int hvm_do_IRQ_dpci(struct domain *d, unsigned int irq);
+
+#endif // _IOMMU_H_
diff -r 9dd580b8b056 -r ca495837a722 xen/include/asm-x86/system.h
--- a/xen/include/asm-x86/system.h Wed Sep 12 15:32:58 2007 +0100
+++ b/xen/include/asm-x86/system.h Wed Sep 12 15:42:39 2007 +0100
@@ -13,6 +13,9 @@
#define wbinvd() \
__asm__ __volatile__ ("wbinvd": : :"memory");
+
+#define clflush(a) \
+ __asm__ __volatile__ ("clflush (%0)": :"r"(a));
#define nop() __asm__ __volatile__ ("nop")
diff -r 9dd580b8b056 -r ca495837a722 xen/include/public/domctl.h
--- a/xen/include/public/domctl.h Wed Sep 12 15:32:58 2007 +0100
+++ b/xen/include/public/domctl.h Wed Sep 12 15:42:39 2007 +0100
@@ -432,7 +432,69 @@ typedef struct xen_domctl_sendtrigger xe
typedef struct xen_domctl_sendtrigger xen_domctl_sendtrigger_t;
DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t);
-
+
+/* Assign PCI device to HVM guest. Sets up IOMMU structures. */
+#define XEN_DOMCTL_assign_device 37
+#define DPCI_ADD_MAPPING 1
+#define DPCI_REMOVE_MAPPING 0
+struct xen_domctl_assign_device {
+ uint32_t machine_bdf; /* machine PCI ID of assigned device */
+};
+typedef struct xen_domctl_assign_device xen_domctl_assign_device_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_assign_device_t);
+
+
+/* Pass-through interrupts: bind real irq -> hvm devfn. */
+#define XEN_DOMCTL_bind_pt_irq 38
+typedef enum pt_irq_type_e {
+ PT_IRQ_TYPE_PCI,
+ PT_IRQ_TYPE_ISA
+} pt_irq_type_t;
+struct xen_domctl_bind_pt_irq {
+ uint32_t machine_irq;
+ pt_irq_type_t irq_type;
+ uint32_t hvm_domid;
+
+ union {
+ struct {
+ uint8_t isa_irq;
+ } isa;
+ struct {
+ uint8_t bus;
+ uint8_t device;
+ uint8_t intx;
+ } pci;
+ } u;
+};
+typedef struct xen_domctl_bind_pt_irq xen_domctl_bind_pt_irq_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_bind_pt_irq_t);
+
+
+/* Bind machine I/O address range -> HVM address range. */
+#define XEN_DOMCTL_memory_mapping 39
+struct xen_domctl_memory_mapping {
+ uint64_t first_gfn; /* first page (hvm guest phys page) in range */
+ uint64_t first_mfn; /* first page (machine page) in range */
+ uint64_t nr_mfns; /* number of pages in range (>0) */
+ uint32_t add_mapping; /* add or remove mapping */
+ uint32_t padding; /* padding for 64-bit aligned structure */
+};
+typedef struct xen_domctl_memory_mapping xen_domctl_memory_mapping_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_memory_mapping_t);
+
+
+/* Bind machine I/O port range -> HVM I/O port range. */
+#define XEN_DOMCTL_ioport_mapping 40
+struct xen_domctl_ioport_mapping {
+ uint32_t first_gport; /* first guest IO port*/
+ uint32_t first_mport; /* first machine IO port */
+ uint32_t nr_ports; /* size of port range */
+ uint32_t add_mapping; /* add or remove mapping */
+};
+typedef struct xen_domctl_ioport_mapping xen_domctl_ioport_mapping_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_mapping_t);
+
+
struct xen_domctl {
uint32_t cmd;
uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
@@ -462,6 +524,10 @@ struct xen_domctl {
struct xen_domctl_hvmcontext hvmcontext;
struct xen_domctl_address_size address_size;
struct xen_domctl_sendtrigger sendtrigger;
+ struct xen_domctl_assign_device assign_device;
+ struct xen_domctl_bind_pt_irq bind_pt_irq;
+ struct xen_domctl_memory_mapping memory_mapping;
+ struct xen_domctl_ioport_mapping ioport_mapping;
uint8_t pad[128];
} u;
};
diff -r 9dd580b8b056 -r ca495837a722 xen/include/xen/acpi.h
--- a/xen/include/xen/acpi.h Wed Sep 12 15:32:58 2007 +0100
+++ b/xen/include/xen/acpi.h Wed Sep 12 15:42:39 2007 +0100
@@ -367,8 +367,78 @@ enum acpi_table_id {
ACPI_SPMI,
ACPI_HPET,
ACPI_MCFG,
+ ACPI_DMAR,
ACPI_TABLE_COUNT
};
+
+/* DMA Remapping Reporting Table (DMAR) */
+
+#define DMAR_FLAGS_INTR_REMAP 0x1 /* intr remap supported */
+struct acpi_table_dmar {
+ struct acpi_table_header header;
+ u8 haw; /* Host address Width */
+ u8 flags;
+ u8 reserved[10];
+} __attribute__ ((packed));
+
+struct acpi_dmar_entry_header {
+ u16 type;
+ u16 length;
+} __attribute__((packed));
+
+enum acpi_dmar_entry_type {
+ ACPI_DMAR_DRHD = 0,
+ ACPI_DMAR_RMRR,
+ ACPI_DMAR_ATSR,
+ ACPI_DMAR_ENTRY_COUNT
+};
+
+#define DRHD_FLAGS_INCLUDE_ALL 0x1 /* drhd remaps remaining devices */
+struct acpi_table_drhd {
+ struct acpi_dmar_entry_header header;
+ u8 flags;
+ u8 reserved;
+ u16 segment;
+ u64 address; /* register base address for this drhd */
+} __attribute__ ((packed));
+
+struct acpi_table_rmrr {
+ struct acpi_dmar_entry_header header;
+ u16 reserved;
+ u16 segment;
+ u64 base_address;
+ u64 end_address;
+} __attribute__ ((packed));
+
+struct acpi_table_atsr {
+ struct acpi_dmar_entry_header header;
+ u8 flags;
+ u8 reserved;
+ u16 segment;
+} __attribute__ ((packed));
+
+enum acpi_dev_scope_type {
+ ACPI_DEV_ENDPOINT=0x01, /* PCI Endpoing device */
+ ACPI_DEV_P2PBRIDGE, /* PCI-PCI Bridge */
+ ACPI_DEV_IOAPIC, /* IOAPIC device*/
+ ACPI_DEV_MSI_HPET, /* MSI capable HPET*/
+ ACPI_DEV_ENTRY_COUNT
+};
+
+struct acpi_dev_scope {
+ u8 dev_type;
+ u8 length;
+ u8 reserved[2];
+ u8 enum_id;
+ u8 start_bus;
+} __attribute__((packed));
+
+struct acpi_pci_path {
+ u8 dev;
+ u8 fn;
+} __attribute__((packed));
+
+typedef int (*acpi_dmar_entry_handler) (struct acpi_dmar_entry_header *header,
const unsigned long end);
typedef int (*acpi_table_handler) (unsigned long phys_addr, unsigned long
size);
diff -r 9dd580b8b056 -r ca495837a722 xen/include/xen/irq.h
--- a/xen/include/xen/irq.h Wed Sep 12 15:32:58 2007 +0100
+++ b/xen/include/xen/irq.h Wed Sep 12 15:42:39 2007 +0100
@@ -64,6 +64,9 @@ extern irq_desc_t irq_desc[NR_IRQS];
extern int setup_irq(unsigned int, struct irqaction *);
extern void free_irq(unsigned int);
+extern int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct cpu_user_regs *),
+ unsigned long irqflags, const char * devname, void *dev_id);
extern hw_irq_controller no_irq_type;
extern void no_action(int cpl, void *dev_id, struct cpu_user_regs *regs);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|