[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen staging] AMD/IOMMU: Move headers to be local
commit 17d20e2ce648c2f0ac5784132f67a50ade7cc688 Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> AuthorDate: Mon Feb 3 13:09:17 2020 +0000 Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> CommitDate: Mon Feb 10 15:27:50 2020 +0000 AMD/IOMMU: Move headers to be local We currently have amd-iommu-defs.h, amd-iommu-proto.h and amd-iommu.h, and no references outside of the AMD IOMMU driver. Keep iommu-defs.h as is, but merge amd-iommu.h and amd-iommu-proto.h to just iommu.h, and move them both into drivers/passthrough/amd/. (While merging, drop the bogus #pragma pack around the *_entry structures.) Take the opportunity to trim the include lists, including x86/mm/p2m.c which (AFAICT) hasn't needed this include since c/s aef3f2275 "x86/mm/p2m: break into common, pt-implementation and pod parts" in 2011. No functional change. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Acked-by: George Dunlap <george.dunlap@xxxxxxxxxx> Acked-by: Jan Beulich <jbeulich@xxxxxxxx> --- xen/arch/x86/mm/p2m.c | 1 - xen/drivers/passthrough/amd/iommu-defs.h | 519 ++++++++++++++++++++++++++ xen/drivers/passthrough/amd/iommu.h | 449 ++++++++++++++++++++++ xen/drivers/passthrough/amd/iommu_acpi.c | 7 +- xen/drivers/passthrough/amd/iommu_cmd.c | 4 +- xen/drivers/passthrough/amd/iommu_detect.c | 7 +- xen/drivers/passthrough/amd/iommu_guest.c | 4 +- xen/drivers/passthrough/amd/iommu_init.c | 13 +- xen/drivers/passthrough/amd/iommu_intr.c | 9 +- xen/drivers/passthrough/amd/iommu_map.c | 8 +- xen/drivers/passthrough/amd/pci_amd_iommu.c | 9 +- xen/include/asm-x86/amd-iommu.h | 190 ---------- xen/include/asm-x86/hvm/svm/amd-iommu-defs.h | 519 -------------------------- xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 284 -------------- 14 files changed, 987 insertions(+), 1036 deletions(-) diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index def13f657b..fd9f09536d 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -38,7 +38,6 @@ #include <asm/mem_sharing.h> #include <asm/hvm/nestedhvm.h> #include <asm/altp2m.h> -#include <asm/hvm/svm/amd-iommu-proto.h> #include <asm/vm_event.h> #include <xsm/xsm.h> diff --git a/xen/drivers/passthrough/amd/iommu-defs.h b/xen/drivers/passthrough/amd/iommu-defs.h new file mode 100644 index 0000000000..f8b62cb033 --- /dev/null +++ b/xen/drivers/passthrough/amd/iommu-defs.h @@ -0,0 +1,519 @@ +/* + * Copyright (C) 2007 Advanced Micro Devices, Inc. + * Author: Leo Duran <leo.duran@xxxxxxx> + * Author: Wei Wang <wei.wang2@xxxxxxx> - adapted to xen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef AMD_IOMMU_DEFS_H +#define AMD_IOMMU_DEFS_H + +/* IOMMU Command Buffer entries: in power of 2 increments, minimum of 256 */ +#define IOMMU_CMD_BUFFER_DEFAULT_ENTRIES 512 + +/* IOMMU Event Log entries: in power of 2 increments, minimum of 256 */ +#define IOMMU_EVENT_LOG_DEFAULT_ENTRIES 512 + +/* IOMMU PPR Log entries: in power of 2 increments, minimum of 256 */ +#define IOMMU_PPR_LOG_DEFAULT_ENTRIES 512 + +#define PTE_PER_TABLE_SHIFT 9 +#define PTE_PER_TABLE_SIZE (1 << PTE_PER_TABLE_SHIFT) +#define PTE_PER_TABLE_MASK (~(PTE_PER_TABLE_SIZE - 1)) +#define PTE_PER_TABLE_ALIGN(entries) \ + (((entries) + PTE_PER_TABLE_SIZE - 1) & PTE_PER_TABLE_MASK) +#define PTE_PER_TABLE_ALLOC(entries) \ + PAGE_SIZE * (PTE_PER_TABLE_ALIGN(entries) >> PTE_PER_TABLE_SHIFT) + +#define amd_offset_level_address(offset, level) \ + ((uint64_t)(offset) << (12 + (PTE_PER_TABLE_SHIFT * ((level) - 1)))) + +#define PCI_MIN_CAP_OFFSET 0x40 +#define PCI_MAX_CAP_BLOCKS 48 +#define PCI_CAP_PTR_MASK 0xFC + +/* IOMMU Capability */ +#define PCI_CAP_ID_MASK 0x000000FF +#define PCI_CAP_ID_SHIFT 0 +#define PCI_CAP_NEXT_PTR_MASK 0x0000FF00 +#define PCI_CAP_NEXT_PTR_SHIFT 8 +#define PCI_CAP_TYPE_MASK 0x00070000 +#define PCI_CAP_TYPE_SHIFT 16 +#define PCI_CAP_REV_MASK 0x00F80000 +#define PCI_CAP_REV_SHIFT 19 +#define PCI_CAP_IOTLB_MASK 0x01000000 +#define PCI_CAP_IOTLB_SHIFT 24 +#define PCI_CAP_HT_TUNNEL_MASK 0x02000000 +#define PCI_CAP_HT_TUNNEL_SHIFT 25 +#define PCI_CAP_NP_CACHE_MASK 0x04000000 +#define PCI_CAP_NP_CACHE_SHIFT 26 +#define PCI_CAP_EFRSUP_SHIFT 27 +#define PCI_CAP_RESET_MASK 0x80000000 +#define PCI_CAP_RESET_SHIFT 31 + +#define PCI_CAP_TYPE_IOMMU 0x3 + +#define PCI_CAP_MMIO_BAR_LOW_OFFSET 0x04 +#define PCI_CAP_MMIO_BAR_HIGH_OFFSET 0x08 +#define PCI_CAP_MMIO_BAR_LOW_MASK 0xFFFFC000 +#define IOMMU_MMIO_REGION_LENGTH 0x4000 + +#define PCI_CAP_RANGE_OFFSET 0x0C +#define PCI_CAP_BUS_NUMBER_MASK 0x0000FF00 +#define PCI_CAP_BUS_NUMBER_SHIFT 8 +#define PCI_CAP_FIRST_DEVICE_MASK 0x00FF0000 +#define PCI_CAP_FIRST_DEVICE_SHIFT 16 +#define PCI_CAP_LAST_DEVICE_MASK 0xFF000000 +#define PCI_CAP_LAST_DEVICE_SHIFT 24 + +#define PCI_CAP_UNIT_ID_MASK 0x0000001F +#define PCI_CAP_UNIT_ID_SHIFT 0 +#define PCI_CAP_MISC_INFO_OFFSET 0x10 +#define PCI_CAP_MSI_NUMBER_MASK 0x0000001F +#define PCI_CAP_MSI_NUMBER_SHIFT 0 + +/* Device Table */ +#define IOMMU_DEV_TABLE_BASE_LOW_OFFSET 0x00 +#define IOMMU_DEV_TABLE_BASE_HIGH_OFFSET 0x04 +#define IOMMU_DEV_TABLE_SIZE_MASK 0x000001FF +#define IOMMU_DEV_TABLE_SIZE_SHIFT 0 + +#define IOMMU_DEV_TABLE_ENTRIES_PER_BUS 256 +#define IOMMU_DEV_TABLE_ENTRY_SIZE 32 +#define IOMMU_DEV_TABLE_U32_PER_ENTRY (IOMMU_DEV_TABLE_ENTRY_SIZE / 4) + +#define IOMMU_DEV_TABLE_SYS_MGT_DMA_ABORTED 0x0 +#define IOMMU_DEV_TABLE_SYS_MGT_MSG_FORWARDED 0x1 +#define IOMMU_DEV_TABLE_SYS_MGT_INT_FORWARDED 0x2 +#define IOMMU_DEV_TABLE_SYS_MGT_DMA_FORWARDED 0x3 + +#define IOMMU_DEV_TABLE_IO_CONTROL_ABORTED 0x0 +#define IOMMU_DEV_TABLE_IO_CONTROL_FORWARDED 0x1 +#define IOMMU_DEV_TABLE_IO_CONTROL_TRANSLATED 0x2 + +#define IOMMU_DEV_TABLE_INT_CONTROL_ABORTED 0x0 +#define IOMMU_DEV_TABLE_INT_CONTROL_FORWARDED 0x1 +#define IOMMU_DEV_TABLE_INT_CONTROL_TRANSLATED 0x2 + +struct amd_iommu_dte { + /* 0 - 63 */ + bool v:1; + bool tv:1; + unsigned int :5; + unsigned int had:2; + unsigned int paging_mode:3; + uint64_t pt_root:40; + bool ppr:1; + bool gprp:1; + bool giov:1; + bool gv:1; + unsigned int glx:2; + unsigned int gcr3_trp_14_12:3; + bool ir:1; + bool iw:1; + unsigned int :1; + + /* 64 - 127 */ + unsigned int domain_id:16; + unsigned int gcr3_trp_30_15:16; + bool i:1; + bool se:1; + bool sa:1; + unsigned int ioctl:2; + bool cache:1; + bool sd:1; + bool ex:1; + unsigned int sys_mgt:2; + unsigned int :1; + unsigned int gcr3_trp_51_31:21; + + /* 128 - 191 */ + bool iv:1; + unsigned int int_tab_len:4; + bool ig:1; + uint64_t it_root:46; + unsigned int :4; + bool init_pass:1; + bool ext_int_pass:1; + bool nmi_pass:1; + unsigned int :1; + unsigned int int_ctl:2; + bool lint0_pass:1; + bool lint1_pass:1; + + /* 192 - 255 */ + uint64_t :54; + bool attr_v:1; + bool mode0_fc:1; + unsigned int snoop_attr:8; +}; + +/* Command Buffer */ +#define IOMMU_CMD_BUFFER_BASE_LOW_OFFSET 0x08 +#define IOMMU_CMD_BUFFER_BASE_HIGH_OFFSET 0x0C +#define IOMMU_CMD_BUFFER_HEAD_OFFSET 0x2000 +#define IOMMU_CMD_BUFFER_TAIL_OFFSET 0x2008 +#define IOMMU_CMD_BUFFER_LENGTH_MASK 0x0F000000 +#define IOMMU_CMD_BUFFER_LENGTH_SHIFT 24 + +#define IOMMU_CMD_BUFFER_ENTRY_SIZE 16 +#define IOMMU_CMD_BUFFER_POWER_OF2_ENTRIES_PER_PAGE 8 + +#define IOMMU_CMD_OPCODE_MASK 0xF0000000 +#define IOMMU_CMD_OPCODE_SHIFT 28 +#define IOMMU_CMD_COMPLETION_WAIT 0x1 +#define IOMMU_CMD_INVALIDATE_DEVTAB_ENTRY 0x2 +#define IOMMU_CMD_INVALIDATE_IOMMU_PAGES 0x3 +#define IOMMU_CMD_INVALIDATE_IOTLB_PAGES 0x4 +#define IOMMU_CMD_INVALIDATE_INT_TABLE 0x5 +#define IOMMU_CMD_COMPLETE_PPR_REQUEST 0x7 +#define IOMMU_CMD_INVALIDATE_IOMMU_ALL 0x8 + +/* COMPLETION_WAIT command */ +#define IOMMU_COMP_WAIT_DATA_BUFFER_SIZE 8 +#define IOMMU_COMP_WAIT_DATA_BUFFER_ALIGNMENT 8 +#define IOMMU_COMP_WAIT_S_FLAG_MASK 0x00000001 +#define IOMMU_COMP_WAIT_S_FLAG_SHIFT 0 +#define IOMMU_COMP_WAIT_I_FLAG_MASK 0x00000002 +#define IOMMU_COMP_WAIT_I_FLAG_SHIFT 1 +#define IOMMU_COMP_WAIT_F_FLAG_MASK 0x00000004 +#define IOMMU_COMP_WAIT_F_FLAG_SHIFT 2 +#define IOMMU_COMP_WAIT_ADDR_LOW_MASK 0xFFFFFFF8 +#define IOMMU_COMP_WAIT_ADDR_LOW_SHIFT 3 +#define IOMMU_COMP_WAIT_ADDR_HIGH_MASK 0x000FFFFF +#define IOMMU_COMP_WAIT_ADDR_HIGH_SHIFT 0 + +/* INVALIDATE_IOMMU_PAGES command */ +#define IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_MASK 0x0000FFFF +#define IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_SHIFT 0 +#define IOMMU_INV_IOMMU_PAGES_S_FLAG_MASK 0x00000001 +#define IOMMU_INV_IOMMU_PAGES_S_FLAG_SHIFT 0 +#define IOMMU_INV_IOMMU_PAGES_PDE_FLAG_MASK 0x00000002 +#define IOMMU_INV_IOMMU_PAGES_PDE_FLAG_SHIFT 1 +#define IOMMU_INV_IOMMU_PAGES_ADDR_LOW_MASK 0xFFFFF000 +#define IOMMU_INV_IOMMU_PAGES_ADDR_LOW_SHIFT 12 +#define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK 0xFFFFFFFF +#define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT 0 + +/* INVALIDATE_DEVTAB_ENTRY command */ +#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_MASK 0x0000FFFF +#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_SHIFT 0 + +/* INVALIDATE_INTERRUPT_TABLE command */ +#define IOMMU_INV_INT_TABLE_DEVICE_ID_MASK 0x0000FFFF +#define IOMMU_INV_INT_TABLE_DEVICE_ID_SHIFT 0 + +/* INVALIDATE_IOTLB_PAGES command */ +#define IOMMU_INV_IOTLB_PAGES_MAXPEND_MASK 0xff000000 +#define IOMMU_INV_IOTLB_PAGES_MAXPEND_SHIFT 24 +#define IOMMU_INV_IOTLB_PAGES_PASID1_MASK 0x00ff0000 +#define IOMMU_INV_IOTLB_PAGES_PASID1_SHIFT 16 +#define IOMMU_INV_IOTLB_PAGES_PASID2_MASK 0x0fff0000 +#define IOMMU_INV_IOTLB_PAGES_PASID2_SHIFT 16 +#define IOMMU_INV_IOTLB_PAGES_QUEUEID_MASK 0x0000ffff +#define IOMMU_INV_IOTLB_PAGES_QUEUEID_SHIFT 0 +#define IOMMU_INV_IOTLB_PAGES_DEVICE_ID_MASK 0x0000FFFF +#define IOMMU_INV_IOTLB_PAGES_DEVICE_ID_SHIFT 0 +#define IOMMU_INV_IOTLB_PAGES_ADDR_LOW_MASK 0xFFFFF000 +#define IOMMU_INV_IOTLB_PAGES_ADDR_LOW_SHIFT 12 +#define IOMMU_INV_IOTLB_PAGES_ADDR_HIGH_MASK 0xFFFFFFFF +#define IOMMU_INV_IOTLB_PAGES_ADDR_HIGH_SHIFT 0 +#define IOMMU_INV_IOTLB_PAGES_S_FLAG_MASK 0x00000001 +#define IOMMU_INV_IOTLB_PAGES_S_FLAG_SHIFT 0 + +/* Event Log */ +#define IOMMU_EVENT_LOG_BASE_LOW_OFFSET 0x10 +#define IOMMU_EVENT_LOG_BASE_HIGH_OFFSET 0x14 +#define IOMMU_EVENT_LOG_HEAD_OFFSET 0x2010 +#define IOMMU_EVENT_LOG_TAIL_OFFSET 0x2018 +#define IOMMU_EVENT_LOG_LENGTH_MASK 0x0F000000 +#define IOMMU_EVENT_LOG_LENGTH_SHIFT 24 +#define IOMMU_EVENT_LOG_HEAD_MASK 0x0007FFF0 +#define IOMMU_EVENT_LOG_HEAD_SHIFT 4 +#define IOMMU_EVENT_LOG_TAIL_MASK 0x0007FFF0 +#define IOMMU_EVENT_LOG_TAIL_SHIFT 4 + +#define IOMMU_EVENT_LOG_ENTRY_SIZE 16 +#define IOMMU_EVENT_LOG_POWER_OF2_ENTRIES_PER_PAGE 8 +#define IOMMU_EVENT_LOG_U32_PER_ENTRY (IOMMU_EVENT_LOG_ENTRY_SIZE / 4) + +#define IOMMU_EVENT_CODE_MASK 0xF0000000 +#define IOMMU_EVENT_CODE_SHIFT 28 +#define IOMMU_EVENT_ILLEGAL_DEV_TABLE_ENTRY 0x1 +#define IOMMU_EVENT_IO_PAGE_FAULT 0x2 +#define IOMMU_EVENT_DEV_TABLE_HW_ERROR 0x3 +#define IOMMU_EVENT_PAGE_TABLE_HW_ERROR 0x4 +#define IOMMU_EVENT_ILLEGAL_COMMAND_ERROR 0x5 +#define IOMMU_EVENT_COMMAND_HW_ERROR 0x6 +#define IOMMU_EVENT_IOTLB_INV_TIMEOUT 0x7 +#define IOMMU_EVENT_INVALID_DEV_REQUEST 0x8 + +#define IOMMU_EVENT_DOMAIN_ID_MASK 0x0000FFFF +#define IOMMU_EVENT_DOMAIN_ID_SHIFT 0 +#define IOMMU_EVENT_DEVICE_ID_MASK 0x0000FFFF +#define IOMMU_EVENT_DEVICE_ID_SHIFT 0 +#define IOMMU_EVENT_FLAGS_SHIFT 16 +#define IOMMU_EVENT_FLAGS_MASK 0x0FFF0000 + +/* PPR Log */ +#define IOMMU_PPR_LOG_ENTRY_SIZE 16 +#define IOMMU_PPR_LOG_POWER_OF2_ENTRIES_PER_PAGE 8 +#define IOMMU_PPR_LOG_U32_PER_ENTRY (IOMMU_PPR_LOG_ENTRY_SIZE / 4) + +#define IOMMU_PPR_LOG_BASE_LOW_OFFSET 0x0038 +#define IOMMU_PPR_LOG_BASE_HIGH_OFFSET 0x003C +#define IOMMU_PPR_LOG_BASE_LOW_MASK 0xFFFFF000 +#define IOMMU_PPR_LOG_BASE_LOW_SHIFT 12 +#define IOMMU_PPR_LOG_BASE_HIGH_MASK 0x000FFFFF +#define IOMMU_PPR_LOG_BASE_HIGH_SHIFT 0 +#define IOMMU_PPR_LOG_LENGTH_MASK 0x0F000000 +#define IOMMU_PPR_LOG_LENGTH_SHIFT 24 +#define IOMMU_PPR_LOG_HEAD_MASK 0x0007FFF0 +#define IOMMU_PPR_LOG_HEAD_SHIFT 4 +#define IOMMU_PPR_LOG_TAIL_MASK 0x0007FFF0 +#define IOMMU_PPR_LOG_TAIL_SHIFT 4 +#define IOMMU_PPR_LOG_HEAD_OFFSET 0x2030 +#define IOMMU_PPR_LOG_TAIL_OFFSET 0x2038 +#define IOMMU_PPR_LOG_DEVICE_ID_MASK 0x0000FFFF +#define IOMMU_PPR_LOG_DEVICE_ID_SHIFT 0 +#define IOMMU_PPR_LOG_CODE_MASK 0xF0000000 +#define IOMMU_PPR_LOG_CODE_SHIFT 28 + +#define IOMMU_LOG_ENTRY_TIMEOUT 1000 + +/* Control Register */ +#define IOMMU_CONTROL_MMIO_OFFSET 0x18 + +union amd_iommu_control { + uint64_t raw; + struct { + bool iommu_en:1; + bool ht_tun_en:1; + bool event_log_en:1; + bool event_int_en:1; + bool com_wait_int_en:1; + unsigned int inv_timeout:3; + bool pass_pw:1; + bool res_pass_pw:1; + bool coherent:1; + bool isoc:1; + bool cmd_buf_en:1; + bool ppr_log_en:1; + bool ppr_int_en:1; + bool ppr_en:1; + bool gt_en:1; + bool ga_en:1; + unsigned int crw:4; + bool smif_en:1; + bool slf_wb_dis:1; + bool smif_log_en:1; + unsigned int gam_en:3; + bool ga_log_en:1; + bool ga_int_en:1; + unsigned int dual_ppr_log_en:2; + unsigned int dual_event_log_en:2; + unsigned int dev_tbl_seg_en:3; + unsigned int priv_abrt_en:2; + bool ppr_auto_rsp_en:1; + bool marc_en:1; + bool blk_stop_mrk_en:1; + bool ppr_auto_rsp_aon:1; + bool domain_id_pne:1; + unsigned int :1; + bool eph_en:1; + unsigned int had_update:2; + bool gd_update_dis:1; + unsigned int :1; + bool xt_en:1; + bool int_cap_xt_en:1; + bool vcmd_en:1; + bool viommu_en:1; + bool ga_update_dis:1; + bool gappi_en:1; + unsigned int :8; + }; +}; + +/* Exclusion Register */ +#define IOMMU_EXCLUSION_BASE_LOW_OFFSET 0x20 +#define IOMMU_EXCLUSION_BASE_HIGH_OFFSET 0x24 +#define IOMMU_EXCLUSION_LIMIT_LOW_OFFSET 0x28 +#define IOMMU_EXCLUSION_LIMIT_HIGH_OFFSET 0x2C +#define IOMMU_EXCLUSION_BASE_LOW_MASK 0xFFFFF000 +#define IOMMU_EXCLUSION_BASE_LOW_SHIFT 12 +#define IOMMU_EXCLUSION_BASE_HIGH_MASK 0xFFFFFFFF +#define IOMMU_EXCLUSION_BASE_HIGH_SHIFT 0 +#define IOMMU_EXCLUSION_RANGE_ENABLE_MASK 0x00000001 +#define IOMMU_EXCLUSION_RANGE_ENABLE_SHIFT 0 +#define IOMMU_EXCLUSION_ALLOW_ALL_MASK 0x00000002 +#define IOMMU_EXCLUSION_ALLOW_ALL_SHIFT 1 +#define IOMMU_EXCLUSION_LIMIT_LOW_MASK 0xFFFFF000 +#define IOMMU_EXCLUSION_LIMIT_LOW_SHIFT 12 +#define IOMMU_EXCLUSION_LIMIT_HIGH_MASK 0xFFFFFFFF +#define IOMMU_EXCLUSION_LIMIT_HIGH_SHIFT 0 + +/* Extended Feature Register */ +#define IOMMU_EXT_FEATURE_MMIO_OFFSET 0x30 + +union amd_iommu_ext_features { + uint64_t raw; + struct { + unsigned int pref_sup:1; + unsigned int ppr_sup:1; + unsigned int xt_sup:1; + unsigned int nx_sup:1; + unsigned int gt_sup:1; + unsigned int gappi_sup:1; + unsigned int ia_sup:1; + unsigned int ga_sup:1; + unsigned int he_sup:1; + unsigned int pc_sup:1; + unsigned int hats:2; + unsigned int gats:2; + unsigned int glx_sup:2; + unsigned int smif_sup:2; + unsigned int smif_rc:3; + unsigned int gam_sup:3; + unsigned int dual_ppr_log_sup:2; + unsigned int :2; + unsigned int dual_event_log_sup:2; + unsigned int :1; + unsigned int sats_sup:1; + unsigned int pas_max:5; + unsigned int us_sup:1; + unsigned int dev_tbl_seg_sup:2; + unsigned int ppr_early_of_sup:1; + unsigned int ppr_auto_rsp_sup:1; + unsigned int marc_sup:2; + unsigned int blk_stop_mrk_sup:1; + unsigned int perf_opt_sup:1; + unsigned int msi_cap_mmio_sup:1; + unsigned int :1; + unsigned int gio_sup:1; + unsigned int ha_sup:1; + unsigned int eph_sup:1; + unsigned int attr_fw_sup:1; + unsigned int hd_sup:1; + unsigned int :1; + unsigned int inv_iotlb_type_sup:1; + unsigned int viommu_sup:1; + unsigned int vm_guard_io_sup:1; + unsigned int vm_table_size:4; + unsigned int ga_update_dis_sup:1; + unsigned int :2; + } flds; +}; + +/* x2APIC Control Registers */ +#define IOMMU_XT_INT_CTRL_MMIO_OFFSET 0x0170 +#define IOMMU_XT_PPR_INT_CTRL_MMIO_OFFSET 0x0178 +#define IOMMU_XT_GA_INT_CTRL_MMIO_OFFSET 0x0180 + +union amd_iommu_x2apic_control { + uint64_t raw; + struct { + unsigned int :2; + unsigned int dest_mode:1; + unsigned int :5; + unsigned int dest_lo:24; + unsigned int vector:8; + unsigned int int_type:1; /* DM in IOMMU spec 3.04 */ + unsigned int :15; + unsigned int dest_hi:8; + }; +}; + +/* Status Register*/ +#define IOMMU_STATUS_MMIO_OFFSET 0x2020 +#define IOMMU_STATUS_EVENT_OVERFLOW_MASK 0x00000001 +#define IOMMU_STATUS_EVENT_OVERFLOW_SHIFT 0 +#define IOMMU_STATUS_EVENT_LOG_INT_MASK 0x00000002 +#define IOMMU_STATUS_EVENT_LOG_INT_SHIFT 1 +#define IOMMU_STATUS_COMP_WAIT_INT_MASK 0x00000004 +#define IOMMU_STATUS_COMP_WAIT_INT_SHIFT 2 +#define IOMMU_STATUS_EVENT_LOG_RUN_MASK 0x00000008 +#define IOMMU_STATUS_EVENT_LOG_RUN_SHIFT 3 +#define IOMMU_STATUS_CMD_BUFFER_RUN_MASK 0x00000010 +#define IOMMU_STATUS_CMD_BUFFER_RUN_SHIFT 4 +#define IOMMU_STATUS_PPR_LOG_OVERFLOW_MASK 0x00000020 +#define IOMMU_STATUS_PPR_LOG_OVERFLOW_SHIFT 5 +#define IOMMU_STATUS_PPR_LOG_INT_MASK 0x00000040 +#define IOMMU_STATUS_PPR_LOG_INT_SHIFT 6 +#define IOMMU_STATUS_PPR_LOG_RUN_MASK 0x00000080 +#define IOMMU_STATUS_PPR_LOG_RUN_SHIFT 7 +#define IOMMU_STATUS_GAPIC_LOG_OVERFLOW_MASK 0x00000100 +#define IOMMU_STATUS_GAPIC_LOG_OVERFLOW_SHIFT 8 +#define IOMMU_STATUS_GAPIC_LOG_INT_MASK 0x00000200 +#define IOMMU_STATUS_GAPIC_LOG_INT_SHIFT 9 +#define IOMMU_STATUS_GAPIC_LOG_RUN_MASK 0x00000400 +#define IOMMU_STATUS_GAPIC_LOG_RUN_SHIFT 10 + +/* I/O Page Table */ +#define IOMMU_PAGE_TABLE_ENTRY_SIZE 8 +#define IOMMU_PAGE_TABLE_U32_PER_ENTRY (IOMMU_PAGE_TABLE_ENTRY_SIZE / 4) +#define IOMMU_PAGE_TABLE_ALIGNMENT 4096 + +struct amd_iommu_pte { + uint64_t pr:1; + uint64_t ignored0:4; + uint64_t a:1; + uint64_t d:1; + uint64_t ignored1:2; + uint64_t next_level:3; + uint64_t mfn:40; + uint64_t reserved:7; + uint64_t u:1; + uint64_t fc:1; + uint64_t ir:1; + uint64_t iw:1; + uint64_t ignored2:1; +}; + +/* Paging modes */ +#define IOMMU_PAGING_MODE_DISABLED 0x0 + +/* Flags */ +#define IOMMU_CONTROL_DISABLED 0 +#define IOMMU_CONTROL_ENABLED 1 + +#define INV_IOMMU_ALL_PAGES_ADDRESS ((1ULL << 63) - 1) + +#define IOMMU_RING_BUFFER_PTR_MASK 0x0007FFF0 +#define IOMMU_RING_BUFFER_PTR_SHIFT 4 + +#define IOMMU_CMD_DEVICE_ID_MASK 0x0000FFFF +#define IOMMU_CMD_DEVICE_ID_SHIFT 0 + +#define IOMMU_CMD_ADDR_LOW_MASK 0xFFFFF000 +#define IOMMU_CMD_ADDR_LOW_SHIFT 12 +#define IOMMU_CMD_ADDR_HIGH_MASK 0xFFFFFFFF +#define IOMMU_CMD_ADDR_HIGH_SHIFT 0 + +#define IOMMU_REG_BASE_ADDR_LOW_MASK 0xFFFFF000 +#define IOMMU_REG_BASE_ADDR_LOW_SHIFT 12 +#define IOMMU_REG_BASE_ADDR_HIGH_MASK 0x000FFFFF +#define IOMMU_REG_BASE_ADDR_HIGH_SHIFT 0 + +#endif /* AMD_IOMMU_DEFS_H */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/drivers/passthrough/amd/iommu.h b/xen/drivers/passthrough/amd/iommu.h new file mode 100644 index 0000000000..f590de8cbf --- /dev/null +++ b/xen/drivers/passthrough/amd/iommu.h @@ -0,0 +1,449 @@ +/* + * Copyright (C) 2007 Advanced Micro Devices, Inc. + * Author: Leo Duran <leo.duran@xxxxxxx> + * Author: Wei Wang <wei.wang2@xxxxxxx> - adapted to xen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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, see <http://www.gnu.org/licenses/>. + */ +#ifndef AMD_IOMMU_H +#define AMD_IOMMU_H + +#include <xen/init.h> +#include <xen/types.h> +#include <xen/list.h> +#include <xen/spinlock.h> +#include <xen/tasklet.h> +#include <xen/sched.h> +#include <xen/domain_page.h> + +#include <asm/msi.h> +#include <asm/apicdef.h> + +#include "iommu-defs.h" + +#define iommu_found() (!list_empty(&amd_iommu_head)) + +extern struct list_head amd_iommu_head; + +typedef struct event_entry +{ + uint32_t data[4]; +} event_entry_t; + +typedef struct ppr_entry +{ + uint32_t data[4]; +} ppr_entry_t; + +typedef struct cmd_entry +{ + uint32_t data[4]; +} cmd_entry_t; + +struct table_struct { + void *buffer; + unsigned long entries; + unsigned long alloc_size; +}; + +struct ring_buffer { + void *buffer; + unsigned long entries; + unsigned long alloc_size; + uint32_t tail; + uint32_t head; + spinlock_t lock; /* protect buffer pointers */ +}; + +typedef struct iommu_cap { + uint32_t header; /* offset 00h */ + uint32_t base_low; /* offset 04h */ + uint32_t base_hi; /* offset 08h */ + uint32_t range; /* offset 0Ch */ + uint32_t misc; /* offset 10h */ +} iommu_cap_t; + +struct amd_iommu { + struct list_head list; + spinlock_t lock; /* protect iommu */ + + u16 seg; + u16 bdf; + struct msi_desc msi; + + u16 cap_offset; + iommu_cap_t cap; + + u8 ht_flags; + union amd_iommu_ext_features features; + + void *mmio_base; + unsigned long mmio_base_phys; + + union amd_iommu_control ctrl; + + struct table_struct dev_table; + struct ring_buffer cmd_buffer; + struct ring_buffer event_log; + struct ring_buffer ppr_log; + + int exclusion_enable; + int exclusion_allow_all; + uint64_t exclusion_base; + uint64_t exclusion_limit; + + int enabled; + + struct list_head ats_devices; +}; + +struct ivrs_mappings { + uint16_t dte_requestor_id; + bool valid:1; + bool dte_allow_exclusion:1; + bool unity_map_enable:1; + bool write_permission:1; + bool read_permission:1; + + /* ivhd device data settings */ + uint8_t device_flags; + + unsigned long addr_range_start; + unsigned long addr_range_length; + struct amd_iommu *iommu; + + /* per device interrupt remapping table */ + void *intremap_table; + unsigned long *intremap_inuse; + spinlock_t intremap_lock; +}; + +extern unsigned int ivrs_bdf_entries; +extern u8 ivhd_type; + +struct ivrs_mappings *get_ivrs_mappings(u16 seg); +int iterate_ivrs_mappings(int (*)(u16 seg, struct ivrs_mappings *)); +int iterate_ivrs_entries(int (*)(const struct amd_iommu *, + struct ivrs_mappings *, uint16_t)); + +/* iommu tables in guest space */ +struct mmio_reg { + uint32_t lo; + uint32_t hi; +}; + +struct guest_dev_table { + struct mmio_reg reg_base; + uint32_t size; +}; + +struct guest_buffer { + struct mmio_reg reg_base; + struct mmio_reg reg_tail; + struct mmio_reg reg_head; + uint32_t entries; +}; + +struct guest_iommu_msi { + uint8_t vector; + uint8_t dest; + uint8_t dest_mode; + uint8_t delivery_mode; + uint8_t trig_mode; +}; + +/* virtual IOMMU structure */ +struct guest_iommu { + + struct domain *domain; + spinlock_t lock; + bool_t enabled; + + struct guest_dev_table dev_table; + struct guest_buffer cmd_buffer; + struct guest_buffer event_log; + struct guest_buffer ppr_log; + + struct tasklet cmd_buffer_tasklet; + + uint64_t mmio_base; /* MMIO base address */ + + /* MMIO regs */ + union amd_iommu_control reg_ctrl; /* MMIO offset 0018h */ + struct mmio_reg reg_status; /* MMIO offset 2020h */ + union amd_iommu_ext_features reg_ext_feature; /* MMIO offset 0030h */ + + /* guest interrupt settings */ + struct guest_iommu_msi msi; +}; + +extern bool_t iommuv2_enabled; + +struct acpi_ivrs_hardware; + +#define for_each_amd_iommu(amd_iommu) \ + list_for_each_entry(amd_iommu, \ + &amd_iommu_head, list) + +#define DMA_32BIT_MASK 0x00000000ffffffffULL + +#define AMD_IOMMU_DEBUG(fmt, args...) \ + do \ + { \ + if ( iommu_debug ) \ + printk(XENLOG_INFO "AMD-Vi: " fmt, ## args); \ + } while(0) + +/* amd-iommu-detect functions */ +int amd_iommu_get_ivrs_dev_entries(void); +int amd_iommu_get_supported_ivhd_type(void); +int amd_iommu_detect_one_acpi(const struct acpi_ivrs_hardware *); +int amd_iommu_detect_acpi(void); +void get_iommu_features(struct amd_iommu *iommu); + +/* amd-iommu-init functions */ +int amd_iommu_prepare(bool xt); +int amd_iommu_init(bool xt); +int amd_iommu_init_late(void); +int amd_iommu_update_ivrs_mapping_acpi(void); +int iov_adjust_irq_affinities(void); + +int amd_iommu_get_paging_mode(unsigned long entries); +int amd_iommu_quarantine_init(struct domain *d); + +/* mapping functions */ +int __must_check amd_iommu_map_page(struct domain *d, dfn_t dfn, + mfn_t mfn, unsigned int flags, + unsigned int *flush_flags); +int __must_check amd_iommu_unmap_page(struct domain *d, dfn_t dfn, + unsigned int *flush_flags); +int __must_check amd_iommu_alloc_root(struct domain_iommu *hd); +int amd_iommu_reserve_domain_unity_map(struct domain *domain, + paddr_t phys_addr, unsigned long size, + int iw, int ir); +int __must_check amd_iommu_flush_iotlb_pages(struct domain *d, dfn_t dfn, + unsigned int page_count, + unsigned int flush_flags); +int __must_check amd_iommu_flush_iotlb_all(struct domain *d); + +/* device table functions */ +int get_dma_requestor_id(uint16_t seg, uint16_t bdf); +void amd_iommu_set_intremap_table(struct amd_iommu_dte *dte, + const void *ptr, + const struct amd_iommu *iommu, + bool valid); +void amd_iommu_set_root_page_table(struct amd_iommu_dte *dte, + uint64_t root_ptr, uint16_t domain_id, + uint8_t paging_mode, bool valid); +void iommu_dte_add_device_entry(struct amd_iommu_dte *dte, + const struct ivrs_mappings *ivrs_dev); +void iommu_dte_set_guest_cr3(struct amd_iommu_dte *dte, uint16_t dom_id, + uint64_t gcr3_mfn, bool gv, uint8_t glx); + +/* send cmd to iommu */ +void amd_iommu_flush_all_pages(struct domain *d); +void amd_iommu_flush_pages(struct domain *d, unsigned long dfn, + unsigned int order); +void amd_iommu_flush_iotlb(u8 devfn, const struct pci_dev *pdev, + uint64_t gaddr, unsigned int order); +void amd_iommu_flush_device(struct amd_iommu *iommu, uint16_t bdf); +void amd_iommu_flush_intremap(struct amd_iommu *iommu, uint16_t bdf); +void amd_iommu_flush_all_caches(struct amd_iommu *iommu); + +/* find iommu for bdf */ +struct amd_iommu *find_iommu_for_device(int seg, int bdf); + +/* interrupt remapping */ +bool iov_supports_xt(void); +int amd_iommu_setup_ioapic_remapping(void); +void *amd_iommu_alloc_intremap_table( + const struct amd_iommu *, unsigned long **, unsigned int nr); +int amd_iommu_free_intremap_table( + const struct amd_iommu *, struct ivrs_mappings *, uint16_t); +unsigned int amd_iommu_intremap_table_order( + const void *irt, const struct amd_iommu *iommu); +void amd_iommu_ioapic_update_ire( + unsigned int apic, unsigned int reg, unsigned int value); +unsigned int amd_iommu_read_ioapic_from_ire( + unsigned int apic, unsigned int reg); +int amd_iommu_msi_msg_update_ire( + struct msi_desc *msi_desc, struct msi_msg *msg); +void amd_iommu_read_msi_from_ire( + struct msi_desc *msi_desc, struct msi_msg *msg); +int amd_setup_hpet_msi(struct msi_desc *msi_desc); +void amd_iommu_dump_intremap_tables(unsigned char key); + +extern struct ioapic_sbdf { + u16 bdf, seg; + u8 id; + bool cmdline; + u16 *pin_2_idx; +} ioapic_sbdf[MAX_IO_APICS]; + +extern unsigned int nr_ioapic_sbdf; +unsigned int ioapic_id_to_index(unsigned int apic_id); +unsigned int get_next_ioapic_sbdf_index(void); + +extern struct hpet_sbdf { + u16 bdf, seg, id; + enum { + HPET_NONE, + HPET_CMDL, + HPET_IVHD, + } init; +} hpet_sbdf; + +extern void *shared_intremap_table; +extern unsigned long *shared_intremap_inuse; + +/* power management support */ +void amd_iommu_resume(void); +int __must_check amd_iommu_suspend(void); +void amd_iommu_crash_shutdown(void); + +/* guest iommu support */ +void amd_iommu_send_guest_cmd(struct amd_iommu *iommu, u32 cmd[]); +void guest_iommu_add_ppr_log(struct domain *d, u32 entry[]); +void guest_iommu_add_event_log(struct domain *d, u32 entry[]); +int guest_iommu_init(struct domain* d); +void guest_iommu_destroy(struct domain *d); +int guest_iommu_set_base(struct domain *d, uint64_t base); + +static inline u32 get_field_from_reg_u32(u32 reg_value, u32 mask, u32 shift) +{ + u32 field; + field = (reg_value & mask) >> shift; + return field; +} + +static inline u32 set_field_in_reg_u32(u32 field, u32 reg_value, + u32 mask, u32 shift, u32 *reg) +{ + reg_value &= ~mask; + reg_value |= (field << shift) & mask; + if (reg) + *reg = reg_value; + return reg_value; +} + +static inline unsigned long region_to_pages(unsigned long addr, unsigned long size) +{ + return (PAGE_ALIGN(addr + size) - (addr & PAGE_MASK)) >> PAGE_SHIFT; +} + +static inline struct page_info* alloc_amd_iommu_pgtable(void) +{ + struct page_info *pg; + void *vaddr; + + pg = alloc_domheap_page(NULL, 0); + if ( pg == NULL ) + return 0; + vaddr = __map_domain_page(pg); + memset(vaddr, 0, PAGE_SIZE); + unmap_domain_page(vaddr); + return pg; +} + +static inline void free_amd_iommu_pgtable(struct page_info *pg) +{ + if ( pg != 0 ) + free_domheap_page(pg); +} + +static inline void* __alloc_amd_iommu_tables(int order) +{ + void *buf; + buf = alloc_xenheap_pages(order, 0); + return buf; +} + +static inline void __free_amd_iommu_tables(void *table, int order) +{ + free_xenheap_pages(table, order); +} + +static inline void iommu_set_bit(uint32_t *reg, uint32_t bit) +{ + set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, *reg, 1U << bit, bit, reg); +} + +static inline void iommu_clear_bit(uint32_t *reg, uint32_t bit) +{ + set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, *reg, 1U << bit, bit, reg); +} + +static inline uint32_t iommu_get_bit(uint32_t reg, uint32_t bit) +{ + return get_field_from_reg_u32(reg, 1U << bit, bit); +} + +static inline int iommu_has_cap(struct amd_iommu *iommu, uint32_t bit) +{ + return !!(iommu->cap.header & (1u << bit)); +} + +/* access tail or head pointer of ring buffer */ +static inline uint32_t iommu_get_rb_pointer(uint32_t reg) +{ + return get_field_from_reg_u32(reg, IOMMU_RING_BUFFER_PTR_MASK, + IOMMU_RING_BUFFER_PTR_SHIFT); +} + +static inline void iommu_set_rb_pointer(uint32_t *reg, uint32_t val) +{ + set_field_in_reg_u32(val, *reg, IOMMU_RING_BUFFER_PTR_MASK, + IOMMU_RING_BUFFER_PTR_SHIFT, reg); +} + +/* access device id field from iommu cmd */ +static inline uint16_t iommu_get_devid_from_cmd(uint32_t cmd) +{ + return get_field_from_reg_u32(cmd, IOMMU_CMD_DEVICE_ID_MASK, + IOMMU_CMD_DEVICE_ID_SHIFT); +} + +static inline void iommu_set_devid_to_cmd(uint32_t *cmd, uint16_t id) +{ + set_field_in_reg_u32(id, *cmd, IOMMU_CMD_DEVICE_ID_MASK, + IOMMU_CMD_DEVICE_ID_SHIFT, cmd); +} + +/* access address field from iommu cmd */ +static inline uint32_t iommu_get_addr_lo_from_cmd(uint32_t cmd) +{ + return get_field_from_reg_u32(cmd, IOMMU_CMD_ADDR_LOW_MASK, + IOMMU_CMD_ADDR_LOW_SHIFT); +} + +static inline uint32_t iommu_get_addr_hi_from_cmd(uint32_t cmd) +{ + return get_field_from_reg_u32(cmd, IOMMU_CMD_ADDR_LOW_MASK, + IOMMU_CMD_ADDR_HIGH_SHIFT); +} + +/* access iommu base addresses field from mmio regs */ +static inline void iommu_set_addr_lo_to_reg(uint32_t *reg, uint32_t addr) +{ + set_field_in_reg_u32(addr, *reg, IOMMU_REG_BASE_ADDR_LOW_MASK, + IOMMU_REG_BASE_ADDR_LOW_SHIFT, reg); +} + +static inline void iommu_set_addr_hi_to_reg(uint32_t *reg, uint32_t addr) +{ + set_field_in_reg_u32(addr, *reg, IOMMU_REG_BASE_ADDR_HIGH_MASK, + IOMMU_REG_BASE_ADDR_HIGH_SHIFT, reg); +} + +#endif /* AMD_IOMMU_H */ diff --git a/xen/drivers/passthrough/amd/iommu_acpi.c b/xen/drivers/passthrough/amd/iommu_acpi.c index 6c5f8e46ec..f4abbfd9dc 100644 --- a/xen/drivers/passthrough/amd/iommu_acpi.c +++ b/xen/drivers/passthrough/amd/iommu_acpi.c @@ -17,13 +17,12 @@ * along with this program; If not, see <http://www.gnu.org/licenses/>. */ -#include <xen/errno.h> #include <xen/acpi.h> #include <xen/param.h> -#include <asm/apicdef.h> + #include <asm/io_apic.h> -#include <asm/amd-iommu.h> -#include <asm/hvm/svm/amd-iommu-proto.h> + +#include "iommu.h" /* Some helper structures, particularly to deal with ranges. */ diff --git a/xen/drivers/passthrough/amd/iommu_cmd.c b/xen/drivers/passthrough/amd/iommu_cmd.c index af3a1fb865..92eaab407b 100644 --- a/xen/drivers/passthrough/amd/iommu_cmd.c +++ b/xen/drivers/passthrough/amd/iommu_cmd.c @@ -17,9 +17,7 @@ * along with this program; If not, see <http://www.gnu.org/licenses/>. */ -#include <xen/sched.h> -#include <asm/amd-iommu.h> -#include <asm/hvm/svm/amd-iommu-proto.h> +#include "iommu.h" #include "../ats.h" static int queue_iommu_command(struct amd_iommu *iommu, u32 cmd[]) diff --git a/xen/drivers/passthrough/amd/iommu_detect.c b/xen/drivers/passthrough/amd/iommu_detect.c index d782e66eee..8312bb4b6f 100644 --- a/xen/drivers/passthrough/amd/iommu_detect.c +++ b/xen/drivers/passthrough/amd/iommu_detect.c @@ -17,13 +17,10 @@ * along with this program; If not, see <http://www.gnu.org/licenses/>. */ -#include <xen/errno.h> #include <xen/acpi.h> -#include <xen/iommu.h> #include <xen/pci.h> -#include <xen/pci_regs.h> -#include <asm/amd-iommu.h> -#include <asm/hvm/svm/amd-iommu-proto.h> + +#include "iommu.h" static int __init get_iommu_msi_capabilities( u16 seg, u8 bus, u8 dev, u8 func, struct amd_iommu *iommu) diff --git a/xen/drivers/passthrough/amd/iommu_guest.c b/xen/drivers/passthrough/amd/iommu_guest.c index 4ed6519e6e..aaf12fe1cb 100644 --- a/xen/drivers/passthrough/amd/iommu_guest.c +++ b/xen/drivers/passthrough/amd/iommu_guest.c @@ -16,11 +16,9 @@ * along with this program; If not, see <http://www.gnu.org/licenses/>. */ -#include <xen/sched.h> #include <asm/p2m.h> -#include <asm/amd-iommu.h> -#include <asm/hvm/svm/amd-iommu-proto.h> +#include "iommu.h" #define IOMMU_MMIO_SIZE 0x8000 #define IOMMU_MMIO_PAGE_NR 0x8 diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index 2f26fed4a3..0ffc83a843 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -17,18 +17,11 @@ * along with this program; If not, see <http://www.gnu.org/licenses/>. */ -#include <xen/errno.h> #include <xen/acpi.h> -#include <xen/keyhandler.h> -#include <xen/pci.h> -#include <xen/pci_regs.h> -#include <xen/irq.h> -#include <asm/amd-iommu.h> -#include <asm/msi.h> -#include <asm/hvm/svm/amd-iommu-proto.h> -#include <asm-x86/fixmap.h> -#include <mach_apic.h> #include <xen/delay.h> +#include <xen/keyhandler.h> + +#include "iommu.h" static int __initdata nr_amd_iommus; static bool __initdata pci_init; diff --git a/xen/drivers/passthrough/amd/iommu_intr.c b/xen/drivers/passthrough/amd/iommu_intr.c index 5e92c023f8..e1cc13b873 100644 --- a/xen/drivers/passthrough/amd/iommu_intr.c +++ b/xen/drivers/passthrough/amd/iommu_intr.c @@ -16,13 +16,12 @@ * along with this program; If not, see <http://www.gnu.org/licenses/>. */ -#include <xen/err.h> -#include <xen/sched.h> -#include <asm/amd-iommu.h> -#include <asm/hvm/svm/amd-iommu-proto.h> -#include <asm/io_apic.h> #include <xen/softirq.h> +#include <asm/io_apic.h> + +#include "iommu.h" + union irte32 { uint32_t raw; struct { diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c index 4e041b960f..2f3b47b366 100644 --- a/xen/drivers/passthrough/amd/iommu_map.c +++ b/xen/drivers/passthrough/amd/iommu_map.c @@ -18,12 +18,8 @@ */ #include <xen/acpi.h> -#include <xen/sched.h> -#include <asm/p2m.h> -#include <asm/amd-iommu.h> -#include <asm/hvm/svm/amd-iommu-proto.h> -#include "../ats.h" -#include <xen/pci.h> + +#include "iommu.h" /* Given pfn and page table level, return pde index */ static unsigned int pfn_to_pde_idx(unsigned long pfn, unsigned int level) diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index dd3401f0dc..3112653960 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -17,15 +17,12 @@ * along with this program; If not, see <http://www.gnu.org/licenses/>. */ -#include <xen/sched.h> #include <xen/iocap.h> -#include <xen/pci.h> -#include <xen/pci_regs.h> -#include <xen/paging.h> #include <xen/softirq.h> + #include <asm/acpi.h> -#include <asm/amd-iommu.h> -#include <asm/hvm/svm/amd-iommu-proto.h> + +#include "iommu.h" #include "../ats.h" static bool_t __read_mostly init_done; diff --git a/xen/include/asm-x86/amd-iommu.h b/xen/include/asm-x86/amd-iommu.h deleted file mode 100644 index 83ababdc8c..0000000000 --- a/xen/include/asm-x86/amd-iommu.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2007 Advanced Micro Devices, Inc. - * Author: Leo Duran <leo.duran@xxxxxxx> - * Author: Wei Wang <wei.wang2@xxxxxxx> - adapted to xen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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, see <http://www.gnu.org/licenses/>. - */ -#ifndef _ASM_X86_64_AMD_IOMMU_H -#define _ASM_X86_64_AMD_IOMMU_H - -#include <xen/init.h> -#include <xen/types.h> -#include <xen/list.h> -#include <xen/spinlock.h> -#include <xen/tasklet.h> -#include <asm/msi.h> -#include <asm/hvm/svm/amd-iommu-defs.h> - -#define iommu_found() (!list_empty(&amd_iommu_head)) - -extern struct list_head amd_iommu_head; - -#pragma pack(1) -typedef struct event_entry -{ - uint32_t data[4]; -} event_entry_t; - -typedef struct ppr_entry -{ - uint32_t data[4]; -} ppr_entry_t; - -typedef struct cmd_entry -{ - uint32_t data[4]; -} cmd_entry_t; -#pragma pack() - -struct table_struct { - void *buffer; - unsigned long entries; - unsigned long alloc_size; -}; - -struct ring_buffer { - void *buffer; - unsigned long entries; - unsigned long alloc_size; - uint32_t tail; - uint32_t head; - spinlock_t lock; /* protect buffer pointers */ -}; - -typedef struct iommu_cap { - uint32_t header; /* offset 00h */ - uint32_t base_low; /* offset 04h */ - uint32_t base_hi; /* offset 08h */ - uint32_t range; /* offset 0Ch */ - uint32_t misc; /* offset 10h */ -} iommu_cap_t; - -struct amd_iommu { - struct list_head list; - spinlock_t lock; /* protect iommu */ - - u16 seg; - u16 bdf; - struct msi_desc msi; - - u16 cap_offset; - iommu_cap_t cap; - - u8 ht_flags; - union amd_iommu_ext_features features; - - void *mmio_base; - unsigned long mmio_base_phys; - - union amd_iommu_control ctrl; - - struct table_struct dev_table; - struct ring_buffer cmd_buffer; - struct ring_buffer event_log; - struct ring_buffer ppr_log; - - int exclusion_enable; - int exclusion_allow_all; - uint64_t exclusion_base; - uint64_t exclusion_limit; - - int enabled; - - struct list_head ats_devices; -}; - -struct ivrs_mappings { - uint16_t dte_requestor_id; - bool valid:1; - bool dte_allow_exclusion:1; - bool unity_map_enable:1; - bool write_permission:1; - bool read_permission:1; - - /* ivhd device data settings */ - uint8_t device_flags; - - unsigned long addr_range_start; - unsigned long addr_range_length; - struct amd_iommu *iommu; - - /* per device interrupt remapping table */ - void *intremap_table; - unsigned long *intremap_inuse; - spinlock_t intremap_lock; -}; - -extern unsigned int ivrs_bdf_entries; -extern u8 ivhd_type; - -struct ivrs_mappings *get_ivrs_mappings(u16 seg); -int iterate_ivrs_mappings(int (*)(u16 seg, struct ivrs_mappings *)); -int iterate_ivrs_entries(int (*)(const struct amd_iommu *, - struct ivrs_mappings *, uint16_t)); - -/* iommu tables in guest space */ -struct mmio_reg { - uint32_t lo; - uint32_t hi; -}; - -struct guest_dev_table { - struct mmio_reg reg_base; - uint32_t size; -}; - -struct guest_buffer { - struct mmio_reg reg_base; - struct mmio_reg reg_tail; - struct mmio_reg reg_head; - uint32_t entries; -}; - -struct guest_iommu_msi { - uint8_t vector; - uint8_t dest; - uint8_t dest_mode; - uint8_t delivery_mode; - uint8_t trig_mode; -}; - -/* virtual IOMMU structure */ -struct guest_iommu { - - struct domain *domain; - spinlock_t lock; - bool_t enabled; - - struct guest_dev_table dev_table; - struct guest_buffer cmd_buffer; - struct guest_buffer event_log; - struct guest_buffer ppr_log; - - struct tasklet cmd_buffer_tasklet; - - uint64_t mmio_base; /* MMIO base address */ - - /* MMIO regs */ - union amd_iommu_control reg_ctrl; /* MMIO offset 0018h */ - struct mmio_reg reg_status; /* MMIO offset 2020h */ - union amd_iommu_ext_features reg_ext_feature; /* MMIO offset 0030h */ - - /* guest interrupt settings */ - struct guest_iommu_msi msi; -}; - -extern bool_t iommuv2_enabled; - -#endif /* _ASM_X86_64_AMD_IOMMU_H */ diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h deleted file mode 100644 index 78368f16d9..0000000000 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Copyright (C) 2007 Advanced Micro Devices, Inc. - * Author: Leo Duran <leo.duran@xxxxxxx> - * Author: Wei Wang <wei.wang2@xxxxxxx> - adapted to xen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _ASM_X86_64_AMD_IOMMU_DEFS_H -#define _ASM_X86_64_AMD_IOMMU_DEFS_H - -/* IOMMU Command Buffer entries: in power of 2 increments, minimum of 256 */ -#define IOMMU_CMD_BUFFER_DEFAULT_ENTRIES 512 - -/* IOMMU Event Log entries: in power of 2 increments, minimum of 256 */ -#define IOMMU_EVENT_LOG_DEFAULT_ENTRIES 512 - -/* IOMMU PPR Log entries: in power of 2 increments, minimum of 256 */ -#define IOMMU_PPR_LOG_DEFAULT_ENTRIES 512 - -#define PTE_PER_TABLE_SHIFT 9 -#define PTE_PER_TABLE_SIZE (1 << PTE_PER_TABLE_SHIFT) -#define PTE_PER_TABLE_MASK (~(PTE_PER_TABLE_SIZE - 1)) -#define PTE_PER_TABLE_ALIGN(entries) \ - (((entries) + PTE_PER_TABLE_SIZE - 1) & PTE_PER_TABLE_MASK) -#define PTE_PER_TABLE_ALLOC(entries) \ - PAGE_SIZE * (PTE_PER_TABLE_ALIGN(entries) >> PTE_PER_TABLE_SHIFT) - -#define amd_offset_level_address(offset, level) \ - ((uint64_t)(offset) << (12 + (PTE_PER_TABLE_SHIFT * ((level) - 1)))) - -#define PCI_MIN_CAP_OFFSET 0x40 -#define PCI_MAX_CAP_BLOCKS 48 -#define PCI_CAP_PTR_MASK 0xFC - -/* IOMMU Capability */ -#define PCI_CAP_ID_MASK 0x000000FF -#define PCI_CAP_ID_SHIFT 0 -#define PCI_CAP_NEXT_PTR_MASK 0x0000FF00 -#define PCI_CAP_NEXT_PTR_SHIFT 8 -#define PCI_CAP_TYPE_MASK 0x00070000 -#define PCI_CAP_TYPE_SHIFT 16 -#define PCI_CAP_REV_MASK 0x00F80000 -#define PCI_CAP_REV_SHIFT 19 -#define PCI_CAP_IOTLB_MASK 0x01000000 -#define PCI_CAP_IOTLB_SHIFT 24 -#define PCI_CAP_HT_TUNNEL_MASK 0x02000000 -#define PCI_CAP_HT_TUNNEL_SHIFT 25 -#define PCI_CAP_NP_CACHE_MASK 0x04000000 -#define PCI_CAP_NP_CACHE_SHIFT 26 -#define PCI_CAP_EFRSUP_SHIFT 27 -#define PCI_CAP_RESET_MASK 0x80000000 -#define PCI_CAP_RESET_SHIFT 31 - -#define PCI_CAP_TYPE_IOMMU 0x3 - -#define PCI_CAP_MMIO_BAR_LOW_OFFSET 0x04 -#define PCI_CAP_MMIO_BAR_HIGH_OFFSET 0x08 -#define PCI_CAP_MMIO_BAR_LOW_MASK 0xFFFFC000 -#define IOMMU_MMIO_REGION_LENGTH 0x4000 - -#define PCI_CAP_RANGE_OFFSET 0x0C -#define PCI_CAP_BUS_NUMBER_MASK 0x0000FF00 -#define PCI_CAP_BUS_NUMBER_SHIFT 8 -#define PCI_CAP_FIRST_DEVICE_MASK 0x00FF0000 -#define PCI_CAP_FIRST_DEVICE_SHIFT 16 -#define PCI_CAP_LAST_DEVICE_MASK 0xFF000000 -#define PCI_CAP_LAST_DEVICE_SHIFT 24 - -#define PCI_CAP_UNIT_ID_MASK 0x0000001F -#define PCI_CAP_UNIT_ID_SHIFT 0 -#define PCI_CAP_MISC_INFO_OFFSET 0x10 -#define PCI_CAP_MSI_NUMBER_MASK 0x0000001F -#define PCI_CAP_MSI_NUMBER_SHIFT 0 - -/* Device Table */ -#define IOMMU_DEV_TABLE_BASE_LOW_OFFSET 0x00 -#define IOMMU_DEV_TABLE_BASE_HIGH_OFFSET 0x04 -#define IOMMU_DEV_TABLE_SIZE_MASK 0x000001FF -#define IOMMU_DEV_TABLE_SIZE_SHIFT 0 - -#define IOMMU_DEV_TABLE_ENTRIES_PER_BUS 256 -#define IOMMU_DEV_TABLE_ENTRY_SIZE 32 -#define IOMMU_DEV_TABLE_U32_PER_ENTRY (IOMMU_DEV_TABLE_ENTRY_SIZE / 4) - -#define IOMMU_DEV_TABLE_SYS_MGT_DMA_ABORTED 0x0 -#define IOMMU_DEV_TABLE_SYS_MGT_MSG_FORWARDED 0x1 -#define IOMMU_DEV_TABLE_SYS_MGT_INT_FORWARDED 0x2 -#define IOMMU_DEV_TABLE_SYS_MGT_DMA_FORWARDED 0x3 - -#define IOMMU_DEV_TABLE_IO_CONTROL_ABORTED 0x0 -#define IOMMU_DEV_TABLE_IO_CONTROL_FORWARDED 0x1 -#define IOMMU_DEV_TABLE_IO_CONTROL_TRANSLATED 0x2 - -#define IOMMU_DEV_TABLE_INT_CONTROL_ABORTED 0x0 -#define IOMMU_DEV_TABLE_INT_CONTROL_FORWARDED 0x1 -#define IOMMU_DEV_TABLE_INT_CONTROL_TRANSLATED 0x2 - -struct amd_iommu_dte { - /* 0 - 63 */ - bool v:1; - bool tv:1; - unsigned int :5; - unsigned int had:2; - unsigned int paging_mode:3; - uint64_t pt_root:40; - bool ppr:1; - bool gprp:1; - bool giov:1; - bool gv:1; - unsigned int glx:2; - unsigned int gcr3_trp_14_12:3; - bool ir:1; - bool iw:1; - unsigned int :1; - - /* 64 - 127 */ - unsigned int domain_id:16; - unsigned int gcr3_trp_30_15:16; - bool i:1; - bool se:1; - bool sa:1; - unsigned int ioctl:2; - bool cache:1; - bool sd:1; - bool ex:1; - unsigned int sys_mgt:2; - unsigned int :1; - unsigned int gcr3_trp_51_31:21; - - /* 128 - 191 */ - bool iv:1; - unsigned int int_tab_len:4; - bool ig:1; - uint64_t it_root:46; - unsigned int :4; - bool init_pass:1; - bool ext_int_pass:1; - bool nmi_pass:1; - unsigned int :1; - unsigned int int_ctl:2; - bool lint0_pass:1; - bool lint1_pass:1; - - /* 192 - 255 */ - uint64_t :54; - bool attr_v:1; - bool mode0_fc:1; - unsigned int snoop_attr:8; -}; - -/* Command Buffer */ -#define IOMMU_CMD_BUFFER_BASE_LOW_OFFSET 0x08 -#define IOMMU_CMD_BUFFER_BASE_HIGH_OFFSET 0x0C -#define IOMMU_CMD_BUFFER_HEAD_OFFSET 0x2000 -#define IOMMU_CMD_BUFFER_TAIL_OFFSET 0x2008 -#define IOMMU_CMD_BUFFER_LENGTH_MASK 0x0F000000 -#define IOMMU_CMD_BUFFER_LENGTH_SHIFT 24 - -#define IOMMU_CMD_BUFFER_ENTRY_SIZE 16 -#define IOMMU_CMD_BUFFER_POWER_OF2_ENTRIES_PER_PAGE 8 - -#define IOMMU_CMD_OPCODE_MASK 0xF0000000 -#define IOMMU_CMD_OPCODE_SHIFT 28 -#define IOMMU_CMD_COMPLETION_WAIT 0x1 -#define IOMMU_CMD_INVALIDATE_DEVTAB_ENTRY 0x2 -#define IOMMU_CMD_INVALIDATE_IOMMU_PAGES 0x3 -#define IOMMU_CMD_INVALIDATE_IOTLB_PAGES 0x4 -#define IOMMU_CMD_INVALIDATE_INT_TABLE 0x5 -#define IOMMU_CMD_COMPLETE_PPR_REQUEST 0x7 -#define IOMMU_CMD_INVALIDATE_IOMMU_ALL 0x8 - -/* COMPLETION_WAIT command */ -#define IOMMU_COMP_WAIT_DATA_BUFFER_SIZE 8 -#define IOMMU_COMP_WAIT_DATA_BUFFER_ALIGNMENT 8 -#define IOMMU_COMP_WAIT_S_FLAG_MASK 0x00000001 -#define IOMMU_COMP_WAIT_S_FLAG_SHIFT 0 -#define IOMMU_COMP_WAIT_I_FLAG_MASK 0x00000002 -#define IOMMU_COMP_WAIT_I_FLAG_SHIFT 1 -#define IOMMU_COMP_WAIT_F_FLAG_MASK 0x00000004 -#define IOMMU_COMP_WAIT_F_FLAG_SHIFT 2 -#define IOMMU_COMP_WAIT_ADDR_LOW_MASK 0xFFFFFFF8 -#define IOMMU_COMP_WAIT_ADDR_LOW_SHIFT 3 -#define IOMMU_COMP_WAIT_ADDR_HIGH_MASK 0x000FFFFF -#define IOMMU_COMP_WAIT_ADDR_HIGH_SHIFT 0 - -/* INVALIDATE_IOMMU_PAGES command */ -#define IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_MASK 0x0000FFFF -#define IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_SHIFT 0 -#define IOMMU_INV_IOMMU_PAGES_S_FLAG_MASK 0x00000001 -#define IOMMU_INV_IOMMU_PAGES_S_FLAG_SHIFT 0 -#define IOMMU_INV_IOMMU_PAGES_PDE_FLAG_MASK 0x00000002 -#define IOMMU_INV_IOMMU_PAGES_PDE_FLAG_SHIFT 1 -#define IOMMU_INV_IOMMU_PAGES_ADDR_LOW_MASK 0xFFFFF000 -#define IOMMU_INV_IOMMU_PAGES_ADDR_LOW_SHIFT 12 -#define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK 0xFFFFFFFF -#define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT 0 - -/* INVALIDATE_DEVTAB_ENTRY command */ -#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_MASK 0x0000FFFF -#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_SHIFT 0 - -/* INVALIDATE_INTERRUPT_TABLE command */ -#define IOMMU_INV_INT_TABLE_DEVICE_ID_MASK 0x0000FFFF -#define IOMMU_INV_INT_TABLE_DEVICE_ID_SHIFT 0 - -/* INVALIDATE_IOTLB_PAGES command */ -#define IOMMU_INV_IOTLB_PAGES_MAXPEND_MASK 0xff000000 -#define IOMMU_INV_IOTLB_PAGES_MAXPEND_SHIFT 24 -#define IOMMU_INV_IOTLB_PAGES_PASID1_MASK 0x00ff0000 -#define IOMMU_INV_IOTLB_PAGES_PASID1_SHIFT 16 -#define IOMMU_INV_IOTLB_PAGES_PASID2_MASK 0x0fff0000 -#define IOMMU_INV_IOTLB_PAGES_PASID2_SHIFT 16 -#define IOMMU_INV_IOTLB_PAGES_QUEUEID_MASK 0x0000ffff -#define IOMMU_INV_IOTLB_PAGES_QUEUEID_SHIFT 0 -#define IOMMU_INV_IOTLB_PAGES_DEVICE_ID_MASK 0x0000FFFF -#define IOMMU_INV_IOTLB_PAGES_DEVICE_ID_SHIFT 0 -#define IOMMU_INV_IOTLB_PAGES_ADDR_LOW_MASK 0xFFFFF000 -#define IOMMU_INV_IOTLB_PAGES_ADDR_LOW_SHIFT 12 -#define IOMMU_INV_IOTLB_PAGES_ADDR_HIGH_MASK 0xFFFFFFFF -#define IOMMU_INV_IOTLB_PAGES_ADDR_HIGH_SHIFT 0 -#define IOMMU_INV_IOTLB_PAGES_S_FLAG_MASK 0x00000001 -#define IOMMU_INV_IOTLB_PAGES_S_FLAG_SHIFT 0 - -/* Event Log */ -#define IOMMU_EVENT_LOG_BASE_LOW_OFFSET 0x10 -#define IOMMU_EVENT_LOG_BASE_HIGH_OFFSET 0x14 -#define IOMMU_EVENT_LOG_HEAD_OFFSET 0x2010 -#define IOMMU_EVENT_LOG_TAIL_OFFSET 0x2018 -#define IOMMU_EVENT_LOG_LENGTH_MASK 0x0F000000 -#define IOMMU_EVENT_LOG_LENGTH_SHIFT 24 -#define IOMMU_EVENT_LOG_HEAD_MASK 0x0007FFF0 -#define IOMMU_EVENT_LOG_HEAD_SHIFT 4 -#define IOMMU_EVENT_LOG_TAIL_MASK 0x0007FFF0 -#define IOMMU_EVENT_LOG_TAIL_SHIFT 4 - -#define IOMMU_EVENT_LOG_ENTRY_SIZE 16 -#define IOMMU_EVENT_LOG_POWER_OF2_ENTRIES_PER_PAGE 8 -#define IOMMU_EVENT_LOG_U32_PER_ENTRY (IOMMU_EVENT_LOG_ENTRY_SIZE / 4) - -#define IOMMU_EVENT_CODE_MASK 0xF0000000 -#define IOMMU_EVENT_CODE_SHIFT 28 -#define IOMMU_EVENT_ILLEGAL_DEV_TABLE_ENTRY 0x1 -#define IOMMU_EVENT_IO_PAGE_FAULT 0x2 -#define IOMMU_EVENT_DEV_TABLE_HW_ERROR 0x3 -#define IOMMU_EVENT_PAGE_TABLE_HW_ERROR 0x4 -#define IOMMU_EVENT_ILLEGAL_COMMAND_ERROR 0x5 -#define IOMMU_EVENT_COMMAND_HW_ERROR 0x6 -#define IOMMU_EVENT_IOTLB_INV_TIMEOUT 0x7 -#define IOMMU_EVENT_INVALID_DEV_REQUEST 0x8 - -#define IOMMU_EVENT_DOMAIN_ID_MASK 0x0000FFFF -#define IOMMU_EVENT_DOMAIN_ID_SHIFT 0 -#define IOMMU_EVENT_DEVICE_ID_MASK 0x0000FFFF -#define IOMMU_EVENT_DEVICE_ID_SHIFT 0 -#define IOMMU_EVENT_FLAGS_SHIFT 16 -#define IOMMU_EVENT_FLAGS_MASK 0x0FFF0000 - -/* PPR Log */ -#define IOMMU_PPR_LOG_ENTRY_SIZE 16 -#define IOMMU_PPR_LOG_POWER_OF2_ENTRIES_PER_PAGE 8 -#define IOMMU_PPR_LOG_U32_PER_ENTRY (IOMMU_PPR_LOG_ENTRY_SIZE / 4) - -#define IOMMU_PPR_LOG_BASE_LOW_OFFSET 0x0038 -#define IOMMU_PPR_LOG_BASE_HIGH_OFFSET 0x003C -#define IOMMU_PPR_LOG_BASE_LOW_MASK 0xFFFFF000 -#define IOMMU_PPR_LOG_BASE_LOW_SHIFT 12 -#define IOMMU_PPR_LOG_BASE_HIGH_MASK 0x000FFFFF -#define IOMMU_PPR_LOG_BASE_HIGH_SHIFT 0 -#define IOMMU_PPR_LOG_LENGTH_MASK 0x0F000000 -#define IOMMU_PPR_LOG_LENGTH_SHIFT 24 -#define IOMMU_PPR_LOG_HEAD_MASK 0x0007FFF0 -#define IOMMU_PPR_LOG_HEAD_SHIFT 4 -#define IOMMU_PPR_LOG_TAIL_MASK 0x0007FFF0 -#define IOMMU_PPR_LOG_TAIL_SHIFT 4 -#define IOMMU_PPR_LOG_HEAD_OFFSET 0x2030 -#define IOMMU_PPR_LOG_TAIL_OFFSET 0x2038 -#define IOMMU_PPR_LOG_DEVICE_ID_MASK 0x0000FFFF -#define IOMMU_PPR_LOG_DEVICE_ID_SHIFT 0 -#define IOMMU_PPR_LOG_CODE_MASK 0xF0000000 -#define IOMMU_PPR_LOG_CODE_SHIFT 28 - -#define IOMMU_LOG_ENTRY_TIMEOUT 1000 - -/* Control Register */ -#define IOMMU_CONTROL_MMIO_OFFSET 0x18 - -union amd_iommu_control { - uint64_t raw; - struct { - bool iommu_en:1; - bool ht_tun_en:1; - bool event_log_en:1; - bool event_int_en:1; - bool com_wait_int_en:1; - unsigned int inv_timeout:3; - bool pass_pw:1; - bool res_pass_pw:1; - bool coherent:1; - bool isoc:1; - bool cmd_buf_en:1; - bool ppr_log_en:1; - bool ppr_int_en:1; - bool ppr_en:1; - bool gt_en:1; - bool ga_en:1; - unsigned int crw:4; - bool smif_en:1; - bool slf_wb_dis:1; - bool smif_log_en:1; - unsigned int gam_en:3; - bool ga_log_en:1; - bool ga_int_en:1; - unsigned int dual_ppr_log_en:2; - unsigned int dual_event_log_en:2; - unsigned int dev_tbl_seg_en:3; - unsigned int priv_abrt_en:2; - bool ppr_auto_rsp_en:1; - bool marc_en:1; - bool blk_stop_mrk_en:1; - bool ppr_auto_rsp_aon:1; - bool domain_id_pne:1; - unsigned int :1; - bool eph_en:1; - unsigned int had_update:2; - bool gd_update_dis:1; - unsigned int :1; - bool xt_en:1; - bool int_cap_xt_en:1; - bool vcmd_en:1; - bool viommu_en:1; - bool ga_update_dis:1; - bool gappi_en:1; - unsigned int :8; - }; -}; - -/* Exclusion Register */ -#define IOMMU_EXCLUSION_BASE_LOW_OFFSET 0x20 -#define IOMMU_EXCLUSION_BASE_HIGH_OFFSET 0x24 -#define IOMMU_EXCLUSION_LIMIT_LOW_OFFSET 0x28 -#define IOMMU_EXCLUSION_LIMIT_HIGH_OFFSET 0x2C -#define IOMMU_EXCLUSION_BASE_LOW_MASK 0xFFFFF000 -#define IOMMU_EXCLUSION_BASE_LOW_SHIFT 12 -#define IOMMU_EXCLUSION_BASE_HIGH_MASK 0xFFFFFFFF -#define IOMMU_EXCLUSION_BASE_HIGH_SHIFT 0 -#define IOMMU_EXCLUSION_RANGE_ENABLE_MASK 0x00000001 -#define IOMMU_EXCLUSION_RANGE_ENABLE_SHIFT 0 -#define IOMMU_EXCLUSION_ALLOW_ALL_MASK 0x00000002 -#define IOMMU_EXCLUSION_ALLOW_ALL_SHIFT 1 -#define IOMMU_EXCLUSION_LIMIT_LOW_MASK 0xFFFFF000 -#define IOMMU_EXCLUSION_LIMIT_LOW_SHIFT 12 -#define IOMMU_EXCLUSION_LIMIT_HIGH_MASK 0xFFFFFFFF -#define IOMMU_EXCLUSION_LIMIT_HIGH_SHIFT 0 - -/* Extended Feature Register */ -#define IOMMU_EXT_FEATURE_MMIO_OFFSET 0x30 - -union amd_iommu_ext_features { - uint64_t raw; - struct { - unsigned int pref_sup:1; - unsigned int ppr_sup:1; - unsigned int xt_sup:1; - unsigned int nx_sup:1; - unsigned int gt_sup:1; - unsigned int gappi_sup:1; - unsigned int ia_sup:1; - unsigned int ga_sup:1; - unsigned int he_sup:1; - unsigned int pc_sup:1; - unsigned int hats:2; - unsigned int gats:2; - unsigned int glx_sup:2; - unsigned int smif_sup:2; - unsigned int smif_rc:3; - unsigned int gam_sup:3; - unsigned int dual_ppr_log_sup:2; - unsigned int :2; - unsigned int dual_event_log_sup:2; - unsigned int :1; - unsigned int sats_sup:1; - unsigned int pas_max:5; - unsigned int us_sup:1; - unsigned int dev_tbl_seg_sup:2; - unsigned int ppr_early_of_sup:1; - unsigned int ppr_auto_rsp_sup:1; - unsigned int marc_sup:2; - unsigned int blk_stop_mrk_sup:1; - unsigned int perf_opt_sup:1; - unsigned int msi_cap_mmio_sup:1; - unsigned int :1; - unsigned int gio_sup:1; - unsigned int ha_sup:1; - unsigned int eph_sup:1; - unsigned int attr_fw_sup:1; - unsigned int hd_sup:1; - unsigned int :1; - unsigned int inv_iotlb_type_sup:1; - unsigned int viommu_sup:1; - unsigned int vm_guard_io_sup:1; - unsigned int vm_table_size:4; - unsigned int ga_update_dis_sup:1; - unsigned int :2; - } flds; -}; - -/* x2APIC Control Registers */ -#define IOMMU_XT_INT_CTRL_MMIO_OFFSET 0x0170 -#define IOMMU_XT_PPR_INT_CTRL_MMIO_OFFSET 0x0178 -#define IOMMU_XT_GA_INT_CTRL_MMIO_OFFSET 0x0180 - -union amd_iommu_x2apic_control { - uint64_t raw; - struct { - unsigned int :2; - unsigned int dest_mode:1; - unsigned int :5; - unsigned int dest_lo:24; - unsigned int vector:8; - unsigned int int_type:1; /* DM in IOMMU spec 3.04 */ - unsigned int :15; - unsigned int dest_hi:8; - }; -}; - -/* Status Register*/ -#define IOMMU_STATUS_MMIO_OFFSET 0x2020 -#define IOMMU_STATUS_EVENT_OVERFLOW_MASK 0x00000001 -#define IOMMU_STATUS_EVENT_OVERFLOW_SHIFT 0 -#define IOMMU_STATUS_EVENT_LOG_INT_MASK 0x00000002 -#define IOMMU_STATUS_EVENT_LOG_INT_SHIFT 1 -#define IOMMU_STATUS_COMP_WAIT_INT_MASK 0x00000004 -#define IOMMU_STATUS_COMP_WAIT_INT_SHIFT 2 -#define IOMMU_STATUS_EVENT_LOG_RUN_MASK 0x00000008 -#define IOMMU_STATUS_EVENT_LOG_RUN_SHIFT 3 -#define IOMMU_STATUS_CMD_BUFFER_RUN_MASK 0x00000010 -#define IOMMU_STATUS_CMD_BUFFER_RUN_SHIFT 4 -#define IOMMU_STATUS_PPR_LOG_OVERFLOW_MASK 0x00000020 -#define IOMMU_STATUS_PPR_LOG_OVERFLOW_SHIFT 5 -#define IOMMU_STATUS_PPR_LOG_INT_MASK 0x00000040 -#define IOMMU_STATUS_PPR_LOG_INT_SHIFT 6 -#define IOMMU_STATUS_PPR_LOG_RUN_MASK 0x00000080 -#define IOMMU_STATUS_PPR_LOG_RUN_SHIFT 7 -#define IOMMU_STATUS_GAPIC_LOG_OVERFLOW_MASK 0x00000100 -#define IOMMU_STATUS_GAPIC_LOG_OVERFLOW_SHIFT 8 -#define IOMMU_STATUS_GAPIC_LOG_INT_MASK 0x00000200 -#define IOMMU_STATUS_GAPIC_LOG_INT_SHIFT 9 -#define IOMMU_STATUS_GAPIC_LOG_RUN_MASK 0x00000400 -#define IOMMU_STATUS_GAPIC_LOG_RUN_SHIFT 10 - -/* I/O Page Table */ -#define IOMMU_PAGE_TABLE_ENTRY_SIZE 8 -#define IOMMU_PAGE_TABLE_U32_PER_ENTRY (IOMMU_PAGE_TABLE_ENTRY_SIZE / 4) -#define IOMMU_PAGE_TABLE_ALIGNMENT 4096 - -struct amd_iommu_pte { - uint64_t pr:1; - uint64_t ignored0:4; - uint64_t a:1; - uint64_t d:1; - uint64_t ignored1:2; - uint64_t next_level:3; - uint64_t mfn:40; - uint64_t reserved:7; - uint64_t u:1; - uint64_t fc:1; - uint64_t ir:1; - uint64_t iw:1; - uint64_t ignored2:1; -}; - -/* Paging modes */ -#define IOMMU_PAGING_MODE_DISABLED 0x0 - -/* Flags */ -#define IOMMU_CONTROL_DISABLED 0 -#define IOMMU_CONTROL_ENABLED 1 - -#define INV_IOMMU_ALL_PAGES_ADDRESS ((1ULL << 63) - 1) - -#define IOMMU_RING_BUFFER_PTR_MASK 0x0007FFF0 -#define IOMMU_RING_BUFFER_PTR_SHIFT 4 - -#define IOMMU_CMD_DEVICE_ID_MASK 0x0000FFFF -#define IOMMU_CMD_DEVICE_ID_SHIFT 0 - -#define IOMMU_CMD_ADDR_LOW_MASK 0xFFFFF000 -#define IOMMU_CMD_ADDR_LOW_SHIFT 12 -#define IOMMU_CMD_ADDR_HIGH_MASK 0xFFFFFFFF -#define IOMMU_CMD_ADDR_HIGH_SHIFT 0 - -#define IOMMU_REG_BASE_ADDR_LOW_MASK 0xFFFFF000 -#define IOMMU_REG_BASE_ADDR_LOW_SHIFT 12 -#define IOMMU_REG_BASE_ADDR_HIGH_MASK 0x000FFFFF -#define IOMMU_REG_BASE_ADDR_HIGH_SHIFT 0 - -#endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */ - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h deleted file mode 100644 index b5c0d50119..0000000000 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (C) 2007 Advanced Micro Devices, Inc. - * Author: Leo Duran <leo.duran@xxxxxxx> - * Author: Wei Wang <wei.wang2@xxxxxxx> - adapted to xen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _ASM_X86_64_AMD_IOMMU_PROTO_H -#define _ASM_X86_64_AMD_IOMMU_PROTO_H - -#include <xen/sched.h> -#include <asm/amd-iommu.h> -#include <asm/apicdef.h> -#include <xen/domain_page.h> - -struct acpi_ivrs_hardware; - -#define for_each_amd_iommu(amd_iommu) \ - list_for_each_entry(amd_iommu, \ - &amd_iommu_head, list) - -#define DMA_32BIT_MASK 0x00000000ffffffffULL - -#define AMD_IOMMU_DEBUG(fmt, args...) \ - do \ - { \ - if ( iommu_debug ) \ - printk(XENLOG_INFO "AMD-Vi: " fmt, ## args); \ - } while(0) - -/* amd-iommu-detect functions */ -int amd_iommu_get_ivrs_dev_entries(void); -int amd_iommu_get_supported_ivhd_type(void); -int amd_iommu_detect_one_acpi(const struct acpi_ivrs_hardware *); -int amd_iommu_detect_acpi(void); -void get_iommu_features(struct amd_iommu *iommu); - -/* amd-iommu-init functions */ -int amd_iommu_prepare(bool xt); -int amd_iommu_init(bool xt); -int amd_iommu_init_late(void); -int amd_iommu_update_ivrs_mapping_acpi(void); -int iov_adjust_irq_affinities(void); - -int amd_iommu_get_paging_mode(unsigned long entries); -int amd_iommu_quarantine_init(struct domain *d); - -/* mapping functions */ -int __must_check amd_iommu_map_page(struct domain *d, dfn_t dfn, - mfn_t mfn, unsigned int flags, - unsigned int *flush_flags); -int __must_check amd_iommu_unmap_page(struct domain *d, dfn_t dfn, - unsigned int *flush_flags); -int __must_check amd_iommu_alloc_root(struct domain_iommu *hd); -int amd_iommu_reserve_domain_unity_map(struct domain *domain, - paddr_t phys_addr, unsigned long size, - int iw, int ir); -int __must_check amd_iommu_flush_iotlb_pages(struct domain *d, dfn_t dfn, - unsigned int page_count, - unsigned int flush_flags); -int __must_check amd_iommu_flush_iotlb_all(struct domain *d); - -/* device table functions */ -int get_dma_requestor_id(uint16_t seg, uint16_t bdf); -void amd_iommu_set_intremap_table(struct amd_iommu_dte *dte, - const void *ptr, - const struct amd_iommu *iommu, - bool valid); -void amd_iommu_set_root_page_table(struct amd_iommu_dte *dte, - uint64_t root_ptr, uint16_t domain_id, - uint8_t paging_mode, bool valid); -void iommu_dte_add_device_entry(struct amd_iommu_dte *dte, - const struct ivrs_mappings *ivrs_dev); -void iommu_dte_set_guest_cr3(struct amd_iommu_dte *dte, uint16_t dom_id, - uint64_t gcr3_mfn, bool gv, uint8_t glx); - -/* send cmd to iommu */ -void amd_iommu_flush_all_pages(struct domain *d); -void amd_iommu_flush_pages(struct domain *d, unsigned long dfn, - unsigned int order); -void amd_iommu_flush_iotlb(u8 devfn, const struct pci_dev *pdev, - uint64_t gaddr, unsigned int order); -void amd_iommu_flush_device(struct amd_iommu *iommu, uint16_t bdf); -void amd_iommu_flush_intremap(struct amd_iommu *iommu, uint16_t bdf); -void amd_iommu_flush_all_caches(struct amd_iommu *iommu); - -/* find iommu for bdf */ -struct amd_iommu *find_iommu_for_device(int seg, int bdf); - -/* interrupt remapping */ -bool iov_supports_xt(void); -int amd_iommu_setup_ioapic_remapping(void); -void *amd_iommu_alloc_intremap_table( - const struct amd_iommu *, unsigned long **, unsigned int nr); -int amd_iommu_free_intremap_table( - const struct amd_iommu *, struct ivrs_mappings *, uint16_t); -unsigned int amd_iommu_intremap_table_order( - const void *irt, const struct amd_iommu *iommu); -void amd_iommu_ioapic_update_ire( - unsigned int apic, unsigned int reg, unsigned int value); -unsigned int amd_iommu_read_ioapic_from_ire( - unsigned int apic, unsigned int reg); -int amd_iommu_msi_msg_update_ire( - struct msi_desc *msi_desc, struct msi_msg *msg); -void amd_iommu_read_msi_from_ire( - struct msi_desc *msi_desc, struct msi_msg *msg); -int amd_setup_hpet_msi(struct msi_desc *msi_desc); -void amd_iommu_dump_intremap_tables(unsigned char key); - -extern struct ioapic_sbdf { - u16 bdf, seg; - u8 id; - bool cmdline; - u16 *pin_2_idx; -} ioapic_sbdf[MAX_IO_APICS]; - -extern unsigned int nr_ioapic_sbdf; -unsigned int ioapic_id_to_index(unsigned int apic_id); -unsigned int get_next_ioapic_sbdf_index(void); - -extern struct hpet_sbdf { - u16 bdf, seg, id; - enum { - HPET_NONE, - HPET_CMDL, - HPET_IVHD, - } init; -} hpet_sbdf; - -extern void *shared_intremap_table; -extern unsigned long *shared_intremap_inuse; - -/* power management support */ -void amd_iommu_resume(void); -int __must_check amd_iommu_suspend(void); -void amd_iommu_crash_shutdown(void); - -/* guest iommu support */ -void amd_iommu_send_guest_cmd(struct amd_iommu *iommu, u32 cmd[]); -void guest_iommu_add_ppr_log(struct domain *d, u32 entry[]); -void guest_iommu_add_event_log(struct domain *d, u32 entry[]); -int guest_iommu_init(struct domain* d); -void guest_iommu_destroy(struct domain *d); -int guest_iommu_set_base(struct domain *d, uint64_t base); - -static inline u32 get_field_from_reg_u32(u32 reg_value, u32 mask, u32 shift) -{ - u32 field; - field = (reg_value & mask) >> shift; - return field; -} - -static inline u32 set_field_in_reg_u32(u32 field, u32 reg_value, - u32 mask, u32 shift, u32 *reg) -{ - reg_value &= ~mask; - reg_value |= (field << shift) & mask; - if (reg) - *reg = reg_value; - return reg_value; -} - -static inline unsigned long region_to_pages(unsigned long addr, unsigned long size) -{ - return (PAGE_ALIGN(addr + size) - (addr & PAGE_MASK)) >> PAGE_SHIFT; -} - -static inline struct page_info* alloc_amd_iommu_pgtable(void) -{ - struct page_info *pg; - void *vaddr; - - pg = alloc_domheap_page(NULL, 0); - if ( pg == NULL ) - return 0; - vaddr = __map_domain_page(pg); - memset(vaddr, 0, PAGE_SIZE); - unmap_domain_page(vaddr); - return pg; -} - -static inline void free_amd_iommu_pgtable(struct page_info *pg) -{ - if ( pg != 0 ) - free_domheap_page(pg); -} - -static inline void* __alloc_amd_iommu_tables(int order) -{ - void *buf; - buf = alloc_xenheap_pages(order, 0); - return buf; -} - -static inline void __free_amd_iommu_tables(void *table, int order) -{ - free_xenheap_pages(table, order); -} - -static inline void iommu_set_bit(uint32_t *reg, uint32_t bit) -{ - set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, *reg, 1U << bit, bit, reg); -} - -static inline void iommu_clear_bit(uint32_t *reg, uint32_t bit) -{ - set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, *reg, 1U << bit, bit, reg); -} - -static inline uint32_t iommu_get_bit(uint32_t reg, uint32_t bit) -{ - return get_field_from_reg_u32(reg, 1U << bit, bit); -} - -static inline int iommu_has_cap(struct amd_iommu *iommu, uint32_t bit) -{ - return !!(iommu->cap.header & (1u << bit)); -} - -/* access tail or head pointer of ring buffer */ -static inline uint32_t iommu_get_rb_pointer(uint32_t reg) -{ - return get_field_from_reg_u32(reg, IOMMU_RING_BUFFER_PTR_MASK, - IOMMU_RING_BUFFER_PTR_SHIFT); -} - -static inline void iommu_set_rb_pointer(uint32_t *reg, uint32_t val) -{ - set_field_in_reg_u32(val, *reg, IOMMU_RING_BUFFER_PTR_MASK, - IOMMU_RING_BUFFER_PTR_SHIFT, reg); -} - -/* access device id field from iommu cmd */ -static inline uint16_t iommu_get_devid_from_cmd(uint32_t cmd) -{ - return get_field_from_reg_u32(cmd, IOMMU_CMD_DEVICE_ID_MASK, - IOMMU_CMD_DEVICE_ID_SHIFT); -} - -static inline void iommu_set_devid_to_cmd(uint32_t *cmd, uint16_t id) -{ - set_field_in_reg_u32(id, *cmd, IOMMU_CMD_DEVICE_ID_MASK, - IOMMU_CMD_DEVICE_ID_SHIFT, cmd); -} - -/* access address field from iommu cmd */ -static inline uint32_t iommu_get_addr_lo_from_cmd(uint32_t cmd) -{ - return get_field_from_reg_u32(cmd, IOMMU_CMD_ADDR_LOW_MASK, - IOMMU_CMD_ADDR_LOW_SHIFT); -} - -static inline uint32_t iommu_get_addr_hi_from_cmd(uint32_t cmd) -{ - return get_field_from_reg_u32(cmd, IOMMU_CMD_ADDR_LOW_MASK, - IOMMU_CMD_ADDR_HIGH_SHIFT); -} - -/* access iommu base addresses field from mmio regs */ -static inline void iommu_set_addr_lo_to_reg(uint32_t *reg, uint32_t addr) -{ - set_field_in_reg_u32(addr, *reg, IOMMU_REG_BASE_ADDR_LOW_MASK, - IOMMU_REG_BASE_ADDR_LOW_SHIFT, reg); -} - -static inline void iommu_set_addr_hi_to_reg(uint32_t *reg, uint32_t addr) -{ - set_field_in_reg_u32(addr, *reg, IOMMU_REG_BASE_ADDR_HIGH_MASK, - IOMMU_REG_BASE_ADDR_HIGH_SHIFT, reg); -} - -#endif /* _ASM_X86_64_AMD_IOMMU_PROTO_H */ -- generated by git-patchbot for /home/xen/git/xen.git#staging _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |