From: ddugger@redhat.com <ddugger@redhat.com> Date: Mon, 23 Mar 2009 10:22:52 -0600 Subject: [xen] add VT-d public header files Message-id: 200903231622.n2NGMqkQ022029@sobek.n0ano.com O-Subject: [RHEL5.4 PATCH 2/21 V2] add VT-d public header files Bugzilla: 484227 RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com> RH-Acked-by: Chris Lalancette <clalance@redhat.com> add public iommu.h which define VT-d data structures and functions, and define some XEN_DOMCTL_xxx for VT-d Upstream Status: Accepted (CS 15883, 17195, 18627) BZ: 484227 Signed-off-by: Weidong Han <weidong.han@intel.com> Signed-off-by: Gerd Hoffman <kraxel@redhat.com> Signed-off-by: Don Dugger <donald.d.dugger@intel.com> diff --git a/include/asm-x86/hvm/iommu.h b/include/asm-x86/hvm/iommu.h new file mode 100644 index 0000000..6b63927 --- /dev/null +++ b/include/asm-x86/hvm/iommu.h @@ -0,0 +1,34 @@ +#ifndef __ASM_X86_HVM_IOMMU_H__ +#define __ASM_X86_HVM_IOMMU_H__ + +struct iommu_ops; +extern struct iommu_ops intel_iommu_ops; +extern int intel_vtd_setup(void); + +static inline struct iommu_ops *iommu_get_ops(void) +{ + switch ( boot_cpu_data.x86_vendor ) + { + case X86_VENDOR_INTEL: + return &intel_iommu_ops; + default: + BUG(); + } + + return NULL; +} + +static inline int iommu_hardware_setup(void) +{ + switch ( boot_cpu_data.x86_vendor ) + { + case X86_VENDOR_INTEL: + return intel_vtd_setup(); + default: + BUG(); + } + + return 0; +} + +#endif /* __ASM_X86_HVM_IOMMU_H__ */ diff --git a/include/public/domctl.h b/include/public/domctl.h index fa1dbd9..8542381 100644 --- a/include/public/domctl.h +++ b/include/public/domctl.h @@ -432,7 +432,88 @@ struct xen_domctl_sendtrigger { 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 XEN_DOMCTL_test_assign_device 45 +#define XEN_DOMCTL_deassign_device 47 +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); + +/* Retrieve sibling devices infomation of machine_bdf */ +#define XEN_DOMCTL_get_device_group 50 +struct xen_domctl_get_device_group { + uint32_t machine_bdf; /* IN */ + uint32_t max_sdevs; /* IN */ + uint32_t num_sdevs; /* OUT */ + XEN_GUEST_HANDLE_64(uint32_t) sdev_array; /* OUT */ +}; +typedef struct xen_domctl_get_device_group xen_domctl_get_device_group_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_get_device_group_t); + + +/* Pass-through interrupts: bind real irq -> hvm devfn. */ +#define XEN_DOMCTL_bind_pt_irq 38 +#define XEN_DOMCTL_unbind_pt_irq 48 +typedef enum pt_irq_type_e { + PT_IRQ_TYPE_PCI, + PT_IRQ_TYPE_ISA, + PT_IRQ_TYPE_MSI, +} 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; + struct { + uint8_t gvec; + uint32_t gflags; + } msi; + } 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 +#define DPCI_ADD_MAPPING 1 +#define DPCI_REMOVE_MAPPING 0 +struct xen_domctl_memory_mapping { + uint64_aligned_t first_gfn; /* first page (hvm guest phys page) in range */ + uint64_aligned_t first_mfn; /* first page (machine page) in range */ + uint64_aligned_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 +543,11 @@ struct xen_domctl { struct xen_domctl_hvmcontext hvmcontext; struct xen_domctl_address_size address_size; struct xen_domctl_sendtrigger sendtrigger; + struct xen_domctl_get_device_group get_device_group; + 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 --git a/include/xen/hvm/iommu.h b/include/xen/hvm/iommu.h new file mode 100644 index 0000000..2a66956 --- /dev/null +++ b/include/xen/hvm/iommu.h @@ -0,0 +1,50 @@ +/* + * 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@intel.com> + */ + +#ifndef __XEN_HVM_IOMMU_H__ +#define __XEN_HVM_IOMMU_H__ + +#include <xen/iommu.h> + +struct g2m_ioport { + struct list_head list; + unsigned int gport; + unsigned int mport; + unsigned int np; +}; + +struct hvm_iommu { + u64 pgd_maddr; /* io page directory machine address */ + 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 */ + domid_t iommu_domid; /* domain id stored in iommu */ + u64 iommu_bitmap; /* bitmap of iommu(s) that the domain uses */ + + /* amd iommu support */ + int domain_id; + int paging_mode; + void *root_table; + bool_t p2m_synchronized; + + /* iommu_ops */ + struct iommu_ops *platform_ops; +}; + +#endif /* __XEN_HVM_IOMMU_H__ */ diff --git a/include/xen/iommu.h b/include/xen/iommu.h new file mode 100644 index 0000000..0c8612b --- /dev/null +++ b/include/xen/iommu.h @@ -0,0 +1,105 @@ +/* + * 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@intel.com> + */ + +#ifndef _IOMMU_H_ +#define _IOMMU_H_ + +#include <xen/init.h> +#include <xen/spinlock.h> +#include <xen/pci.h> +#include <public/hvm/ioreq.h> +#include <public/domctl.h> + +extern int vtd_enabled; +extern int iommu_enabled; +extern int iommu_pv_enabled; +extern int force_iommu; +extern int iommu_passthrough; + +#define domain_hvm_iommu(d) (&d->arch.hvm_domain.hvm_iommu) + +#define MAX_IOMMUS 32 + +#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) + +struct iommu { + struct list_head list; + void __iomem *reg; /* Pointer to hardware regs, virtual addr */ + u32 index; /* Sequence number of iommu */ + u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */ + u32 nr_pt_levels; + u64 cap; + u64 ecap; + spinlock_t lock; /* protect context, domain ids */ + spinlock_t register_lock; /* protect iommu register handling */ + u64 root_maddr; /* root entry machine address */ + unsigned int vector; + struct intel_iommu *intel; +}; + +int iommu_add_device(struct pci_dev *pdev); +int iommu_remove_device(struct pci_dev *pdev); +int iommu_domain_init(struct domain *d); +void iommu_domain_destroy(struct domain *d); +int device_assigned(u8 bus, u8 devfn); +int assign_device(struct domain *d, u8 bus, u8 devfn); +int deassign_device(struct domain *d, u8 bus, u8 devfn); +int iommu_get_device_group(struct domain *d, u8 bus, u8 devfn, + XEN_GUEST_HANDLE_64(uint32_t) buf, int max_sdevs); +int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn); +int iommu_unmap_page(struct domain *d, unsigned long gfn); +void iommu_domain_teardown(struct domain *d); +int hvm_do_IRQ_dpci(struct domain *d, unsigned int irq); +int dpci_ioport_intercept(ioreq_t *p); +int pt_irq_create_bind_vtd(struct domain *d, + xen_domctl_bind_pt_irq_t *pt_irq_bind); +int pt_irq_destroy_bind_vtd(struct domain *d, + xen_domctl_bind_pt_irq_t *pt_irq_bind); +unsigned int io_apic_read_remap_rte(unsigned int apic, unsigned int reg); +void io_apic_write_remap_rte(unsigned int apic, + unsigned int reg, unsigned int value); + +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]" + +struct iommu_ops { + int (*init)(struct domain *d); + int (*add_device)(struct pci_dev *pdev); + int (*remove_device)(struct pci_dev *pdev); + int (*assign_device)(struct domain *d, u8 bus, u8 devfn); + void (*teardown)(struct domain *d); + int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn); + int (*unmap_page)(struct domain *d, unsigned long gfn); + int (*reassign_device)(struct domain *s, struct domain *t, + u8 bus, u8 devfn); + int (*get_device_group_id)(u8 bus, u8 devfn); +}; + +void iommu_suspend(void); +void iommu_resume(void); + +#endif /* _IOMMU_H_ */