From: Wei Liu <wei.liu2@citrix.com>
To: Xen-devel <xen-devel@lists.xenproject.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
Wei Liu <wei.liu2@citrix.com>,
Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>,
Jan Beulich <JBeulich@suse.com>
Subject: [PATCH RFC 06/10] passthrough/amd: remove guest iommu support
Date: Wed, 21 Feb 2018 21:46:57 +0000 [thread overview]
Message-ID: <20180221214701.1646-7-wei.liu2@citrix.com> (raw)
In-Reply-To: <20180221214701.1646-1-wei.liu2@citrix.com>
It is never used and it is getting in the way of cleaning up.
The only callsite of guest_iommu_add_ppr_log has no effect because
guest iommu is not initialised.
Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
Cc: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
xen/drivers/passthrough/x86/amd/Makefile | 1 -
xen/drivers/passthrough/x86/amd/iommu_guest.c | 927 --------------------------
xen/drivers/passthrough/x86/amd/iommu_init.c | 21 +-
xen/include/asm-x86/amd-iommu.h | 51 --
xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 8 -
xen/include/asm-x86/iommu.h | 1 -
6 files changed, 6 insertions(+), 1003 deletions(-)
delete mode 100644 xen/drivers/passthrough/x86/amd/iommu_guest.c
diff --git a/xen/drivers/passthrough/x86/amd/Makefile b/xen/drivers/passthrough/x86/amd/Makefile
index 95c04ed237..415146fcdb 100644
--- a/xen/drivers/passthrough/x86/amd/Makefile
+++ b/xen/drivers/passthrough/x86/amd/Makefile
@@ -5,4 +5,3 @@ obj-y += pci_amd_iommu.o
obj-bin-y += iommu_acpi.init.o
obj-y += iommu_intr.o
obj-y += iommu_cmd.o
-obj-y += iommu_guest.o
diff --git a/xen/drivers/passthrough/x86/amd/iommu_guest.c b/xen/drivers/passthrough/x86/amd/iommu_guest.c
deleted file mode 100644
index 96175bb9ac..0000000000
--- a/xen/drivers/passthrough/x86/amd/iommu_guest.c
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
- * Copyright (C) 2011 Advanced Micro Devices, Inc.
- * Author: Wei Wang <wei.wang2@amd.com>
- *
- * 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/>.
- */
-
-#include <xen/sched.h>
-#include <asm/p2m.h>
-#include <asm/amd-iommu.h>
-#include <asm/hvm/svm/amd-iommu-proto.h>
-
-
-#define IOMMU_MMIO_SIZE 0x8000
-#define IOMMU_MMIO_PAGE_NR 0x8
-#define RING_BF_LENGTH_MASK 0x0F000000
-#define RING_BF_LENGTH_SHIFT 24
-
-#define PASMAX_9_bit 0x8
-#define GUEST_CR3_1_LEVEL 0x0
-#define GUEST_ADDRESS_SIZE_6_LEVEL 0x2
-#define HOST_ADDRESS_SIZE_6_LEVEL 0x2
-
-#define guest_iommu_set_status(iommu, bit) \
- iommu_set_bit(&((iommu)->reg_status.lo), bit)
-
-#define guest_iommu_clear_status(iommu, bit) \
- iommu_clear_bit(&((iommu)->reg_status.lo), bit)
-
-#define reg_to_u64(reg) (((uint64_t)reg.hi << 32) | reg.lo )
-#define u64_to_reg(reg, val) \
- do \
- { \
- (reg)->lo = (u32)(val); \
- (reg)->hi = (val) >> 32; \
- } while (0)
-
-static unsigned int machine_bdf(struct domain *d, uint16_t guest_bdf)
-{
- return guest_bdf;
-}
-
-static uint16_t guest_bdf(struct domain *d, uint16_t machine_bdf)
-{
- return machine_bdf;
-}
-
-static inline struct guest_iommu *domain_iommu(struct domain *d)
-{
- return dom_iommu(d)->arch.g_iommu;
-}
-
-static inline struct guest_iommu *vcpu_iommu(struct vcpu *v)
-{
- return dom_iommu(v->domain)->arch.g_iommu;
-}
-
-static void guest_iommu_enable(struct guest_iommu *iommu)
-{
- iommu->enabled = 1;
-}
-
-static void guest_iommu_disable(struct guest_iommu *iommu)
-{
- iommu->enabled = 0;
-}
-
-static uint64_t get_guest_cr3_from_dte(dev_entry_t *dte)
-{
- uint64_t gcr3_1, gcr3_2, gcr3_3;
-
- gcr3_1 = get_field_from_reg_u32(dte->data[1],
- IOMMU_DEV_TABLE_GCR3_1_MASK,
- IOMMU_DEV_TABLE_GCR3_1_SHIFT);
- gcr3_2 = get_field_from_reg_u32(dte->data[2],
- IOMMU_DEV_TABLE_GCR3_2_MASK,
- IOMMU_DEV_TABLE_GCR3_2_SHIFT);
- gcr3_3 = get_field_from_reg_u32(dte->data[3],
- IOMMU_DEV_TABLE_GCR3_3_MASK,
- IOMMU_DEV_TABLE_GCR3_3_SHIFT);
-
- return ((gcr3_3 << 31) | (gcr3_2 << 15 ) | (gcr3_1 << 12)) >> PAGE_SHIFT;
-}
-
-static uint16_t get_domid_from_dte(dev_entry_t *dte)
-{
- return get_field_from_reg_u32(dte->data[2], IOMMU_DEV_TABLE_DOMAIN_ID_MASK,
- IOMMU_DEV_TABLE_DOMAIN_ID_SHIFT);
-}
-
-static uint16_t get_glx_from_dte(dev_entry_t *dte)
-{
- return get_field_from_reg_u32(dte->data[1], IOMMU_DEV_TABLE_GLX_MASK,
- IOMMU_DEV_TABLE_GLX_SHIFT);
-}
-
-static uint16_t get_gv_from_dte(dev_entry_t *dte)
-{
- return get_field_from_reg_u32(dte->data[1],IOMMU_DEV_TABLE_GV_MASK,
- IOMMU_DEV_TABLE_GV_SHIFT);
-}
-
-static unsigned int host_domid(struct domain *d, uint64_t g_domid)
-{
- /* Only support one PPR device in guest for now */
- return d->domain_id;
-}
-
-static unsigned long get_gfn_from_base_reg(uint64_t base_raw)
-{
- base_raw &= PADDR_MASK;
- ASSERT ( base_raw != 0 );
- return base_raw >> PAGE_SHIFT;
-}
-
-static void guest_iommu_deliver_msi(struct domain *d)
-{
- uint8_t vector, dest, dest_mode, delivery_mode, trig_mode;
- struct guest_iommu *iommu = domain_iommu(d);
-
- vector = iommu->msi.vector;
- dest = iommu->msi.dest;
- dest_mode = iommu->msi.dest_mode;
- delivery_mode = iommu->msi.delivery_mode;
- trig_mode = iommu->msi.trig_mode;
-
- vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
-}
-
-static unsigned long guest_iommu_get_table_mfn(struct domain *d,
- uint64_t base_raw,
- unsigned int entry_size,
- unsigned int pos)
-{
- unsigned long idx, gfn, mfn;
- p2m_type_t p2mt;
-
- gfn = get_gfn_from_base_reg(base_raw);
- idx = (pos * entry_size) >> PAGE_SHIFT;
-
- mfn = mfn_x(get_gfn(d, gfn + idx, &p2mt));
- put_gfn(d, gfn);
-
- return mfn;
-}
-
-static void guest_iommu_enable_dev_table(struct guest_iommu *iommu)
-{
- uint32_t length_raw = get_field_from_reg_u32(iommu->dev_table.reg_base.lo,
- IOMMU_DEV_TABLE_SIZE_MASK,
- IOMMU_DEV_TABLE_SIZE_SHIFT);
- iommu->dev_table.size = (length_raw + 1) * PAGE_SIZE;
-}
-
-static void guest_iommu_enable_ring_buffer(struct guest_iommu *iommu,
- struct guest_buffer *buffer,
- uint32_t entry_size)
-{
- uint32_t length_raw = get_field_from_reg_u32(buffer->reg_base.hi,
- RING_BF_LENGTH_MASK,
- RING_BF_LENGTH_SHIFT);
- buffer->entries = 1 << length_raw;
-}
-
-void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
-{
- uint16_t gdev_id;
- unsigned long mfn, tail, head;
- ppr_entry_t *log, *log_base;
- struct guest_iommu *iommu;
-
- if ( !is_hvm_domain(d) )
- return;
-
- iommu = domain_iommu(d);
- if ( !iommu )
- return;
-
- tail = iommu_get_rb_pointer(iommu->ppr_log.reg_tail.lo);
- head = iommu_get_rb_pointer(iommu->ppr_log.reg_head.lo);
-
- if ( tail >= iommu->ppr_log.entries || head >= iommu->ppr_log.entries )
- {
- AMD_IOMMU_DEBUG("Error: guest iommu ppr log overflows\n");
- guest_iommu_disable(iommu);
- return;
- }
-
- mfn = guest_iommu_get_table_mfn(d, reg_to_u64(iommu->ppr_log.reg_base),
- sizeof(ppr_entry_t), tail);
- ASSERT(mfn_valid(_mfn(mfn)));
-
- log_base = map_domain_page(_mfn(mfn));
- log = log_base + tail % (PAGE_SIZE / sizeof(ppr_entry_t));
-
- /* Convert physical device id back into virtual device id */
- gdev_id = guest_bdf(d, iommu_get_devid_from_cmd(entry[0]));
- iommu_set_devid_to_cmd(&entry[0], gdev_id);
-
- memcpy(log, entry, sizeof(ppr_entry_t));
-
- /* Now shift ppr log tail pointer */
- if ( ++tail >= iommu->ppr_log.entries )
- {
- tail = 0;
- guest_iommu_set_status(iommu, IOMMU_STATUS_PPR_LOG_OVERFLOW_SHIFT);
- }
- iommu_set_rb_pointer(&iommu->ppr_log.reg_tail.lo, tail);
- unmap_domain_page(log_base);
-
- guest_iommu_deliver_msi(d);
-}
-
-void guest_iommu_add_event_log(struct domain *d, u32 entry[])
-{
- uint16_t dev_id;
- unsigned long mfn, tail, head;
- event_entry_t *log, *log_base;
- struct guest_iommu *iommu;
-
- if ( !is_hvm_domain(d) )
- return;
-
- iommu = domain_iommu(d);
- if ( !iommu )
- return;
-
- tail = iommu_get_rb_pointer(iommu->event_log.reg_tail.lo);
- head = iommu_get_rb_pointer(iommu->event_log.reg_head.lo);
-
- if ( tail >= iommu->event_log.entries || head >= iommu->event_log.entries )
- {
- AMD_IOMMU_DEBUG("Error: guest iommu event overflows\n");
- guest_iommu_disable(iommu);
- return;
- }
-
- mfn = guest_iommu_get_table_mfn(d, reg_to_u64(iommu->event_log.reg_base),
- sizeof(event_entry_t), tail);
- ASSERT(mfn_valid(_mfn(mfn)));
-
- log_base = map_domain_page(_mfn(mfn));
- log = log_base + tail % (PAGE_SIZE / sizeof(event_entry_t));
-
- /* re-write physical device id into virtual device id */
- dev_id = guest_bdf(d, iommu_get_devid_from_cmd(entry[0]));
- iommu_set_devid_to_cmd(&entry[0], dev_id);
- memcpy(log, entry, sizeof(event_entry_t));
-
- /* Now shift event log tail pointer */
- if ( ++tail >= iommu->event_log.entries )
- {
- tail = 0;
- guest_iommu_set_status(iommu, IOMMU_STATUS_EVENT_OVERFLOW_SHIFT);
- }
-
- iommu_set_rb_pointer(&iommu->event_log.reg_tail.lo, tail);
- unmap_domain_page(log_base);
-
- guest_iommu_deliver_msi(d);
-}
-
-static int do_complete_ppr_request(struct domain *d, cmd_entry_t *cmd)
-{
- uint16_t dev_id;
- struct amd_iommu *iommu;
-
- dev_id = machine_bdf(d, iommu_get_devid_from_cmd(cmd->data[0]));
- iommu = find_iommu_for_device(0, dev_id);
-
- if ( !iommu )
- {
- AMD_IOMMU_DEBUG("%s: Fail to find iommu for bdf %x\n",
- __func__, dev_id);
- return -ENODEV;
- }
-
- /* replace virtual device id into physical */
- iommu_set_devid_to_cmd(&cmd->data[0], dev_id);
- amd_iommu_send_guest_cmd(iommu, cmd->data);
-
- return 0;
-}
-
-static int do_invalidate_pages(struct domain *d, cmd_entry_t *cmd)
-{
- uint16_t gdom_id, hdom_id;
- struct amd_iommu *iommu = NULL;
-
- gdom_id = get_field_from_reg_u32(cmd->data[1],
- IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_MASK,
- IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_SHIFT);
-
- hdom_id = host_domid(d, gdom_id);
- set_field_in_reg_u32(hdom_id, cmd->data[1],
- IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_MASK,
- IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_SHIFT, &cmd->data[1]);
-
- for_each_amd_iommu ( iommu )
- amd_iommu_send_guest_cmd(iommu, cmd->data);
-
- return 0;
-}
-
-static int do_invalidate_all(struct domain *d, cmd_entry_t *cmd)
-{
- struct amd_iommu *iommu = NULL;
-
- for_each_amd_iommu ( iommu )
- amd_iommu_flush_all_pages(d);
-
- return 0;
-}
-
-static int do_invalidate_iotlb_pages(struct domain *d, cmd_entry_t *cmd)
-{
- struct amd_iommu *iommu;
- uint16_t dev_id;
-
- dev_id = machine_bdf(d, iommu_get_devid_from_cmd(cmd->data[0]));
-
- iommu = find_iommu_for_device(0, dev_id);
- if ( !iommu )
- {
- AMD_IOMMU_DEBUG("%s: Fail to find iommu for bdf %x\n",
- __func__, dev_id);
- return -ENODEV;
- }
-
- iommu_set_devid_to_cmd(&cmd->data[0], dev_id);
- amd_iommu_send_guest_cmd(iommu, cmd->data);
-
- return 0;
-}
-
-static int do_completion_wait(struct domain *d, cmd_entry_t *cmd)
-{
- bool_t com_wait_int_en, com_wait_int, i, s;
- struct guest_iommu *iommu;
- unsigned long gfn;
- p2m_type_t p2mt;
-
- iommu = domain_iommu(d);
-
- i = iommu_get_bit(cmd->data[0], IOMMU_COMP_WAIT_I_FLAG_SHIFT);
- s = iommu_get_bit(cmd->data[0], IOMMU_COMP_WAIT_S_FLAG_SHIFT);
-
- if ( i )
- guest_iommu_set_status(iommu, IOMMU_STATUS_COMP_WAIT_INT_SHIFT);
-
- if ( s )
- {
- uint64_t gaddr_lo, gaddr_hi, gaddr_64, data;
- void *vaddr;
-
- data = (uint64_t)cmd->data[3] << 32 | cmd->data[2];
- gaddr_lo = get_field_from_reg_u32(cmd->data[0],
- IOMMU_COMP_WAIT_ADDR_LOW_MASK,
- IOMMU_COMP_WAIT_ADDR_LOW_SHIFT);
- gaddr_hi = get_field_from_reg_u32(cmd->data[1],
- IOMMU_COMP_WAIT_ADDR_HIGH_MASK,
- IOMMU_COMP_WAIT_ADDR_HIGH_SHIFT);
-
- gaddr_64 = (gaddr_hi << 32) | (gaddr_lo << 3);
-
- gfn = gaddr_64 >> PAGE_SHIFT;
- vaddr = map_domain_page(get_gfn(d, gfn ,&p2mt));
- put_gfn(d, gfn);
-
- write_u64_atomic((uint64_t *)(vaddr + (gaddr_64 & (PAGE_SIZE-1))),
- data);
- unmap_domain_page(vaddr);
- }
-
- com_wait_int_en = iommu_get_bit(iommu->reg_ctrl.lo,
- IOMMU_CONTROL_COMP_WAIT_INT_SHIFT);
- com_wait_int = iommu_get_bit(iommu->reg_status.lo,
- IOMMU_STATUS_COMP_WAIT_INT_SHIFT);
-
- if ( com_wait_int_en && com_wait_int )
- guest_iommu_deliver_msi(d);
-
- return 0;
-}
-
-static int do_invalidate_dte(struct domain *d, cmd_entry_t *cmd)
-{
- uint16_t gbdf, mbdf, req_id, gdom_id, hdom_id;
- dev_entry_t *gdte, *mdte, *dte_base;
- struct amd_iommu *iommu = NULL;
- struct guest_iommu *g_iommu;
- uint64_t gcr3_gfn, gcr3_mfn;
- uint8_t glx, gv;
- unsigned long dte_mfn, flags;
- p2m_type_t p2mt;
-
- g_iommu = domain_iommu(d);
- gbdf = iommu_get_devid_from_cmd(cmd->data[0]);
- mbdf = machine_bdf(d, gbdf);
-
- /* Guest can only update DTEs for its passthru devices */
- if ( mbdf == 0 || gbdf == 0 )
- return 0;
-
- /* Sometimes guest invalidates devices from non-exists dtes */
- if ( (gbdf * sizeof(dev_entry_t)) > g_iommu->dev_table.size )
- return 0;
-
- dte_mfn = guest_iommu_get_table_mfn(d,
- reg_to_u64(g_iommu->dev_table.reg_base),
- sizeof(dev_entry_t), gbdf);
- ASSERT(mfn_valid(_mfn(dte_mfn)));
-
- /* Read guest dte information */
- dte_base = map_domain_page(_mfn(dte_mfn));
-
- gdte = dte_base + gbdf % (PAGE_SIZE / sizeof(dev_entry_t));
-
- gdom_id = get_domid_from_dte(gdte);
- gcr3_gfn = get_guest_cr3_from_dte(gdte);
- glx = get_glx_from_dte(gdte);
- gv = get_gv_from_dte(gdte);
-
- unmap_domain_page(dte_base);
-
- /* Do not update host dte before gcr3 has been set */
- if ( gcr3_gfn == 0 )
- return 0;
-
- gcr3_mfn = mfn_x(get_gfn(d, gcr3_gfn, &p2mt));
- put_gfn(d, gcr3_gfn);
-
- ASSERT(mfn_valid(_mfn(gcr3_mfn)));
-
- iommu = find_iommu_for_device(0, mbdf);
- if ( !iommu )
- {
- AMD_IOMMU_DEBUG("%s: Fail to find iommu for bdf %x!\n",
- __func__, mbdf);
- return -ENODEV;
- }
-
- /* Setup host device entry */
- hdom_id = host_domid(d, gdom_id);
- req_id = get_dma_requestor_id(iommu->seg, mbdf);
- mdte = iommu->dev_table.buffer + (req_id * sizeof(dev_entry_t));
-
- spin_lock_irqsave(&iommu->lock, flags);
- iommu_dte_set_guest_cr3((u32 *)mdte, hdom_id,
- gcr3_mfn << PAGE_SHIFT, gv, glx);
-
- amd_iommu_flush_device(iommu, req_id);
- spin_unlock_irqrestore(&iommu->lock, flags);
-
- return 0;
-}
-
-static void guest_iommu_process_command(unsigned long _d)
-{
- unsigned long opcode, tail, head, entries_per_page, cmd_mfn;
- cmd_entry_t *cmd, *cmd_base;
- struct domain *d = (struct domain *)_d;
- struct guest_iommu *iommu;
-
- iommu = domain_iommu(d);
-
- if ( !iommu->enabled )
- return;
-
- head = iommu_get_rb_pointer(iommu->cmd_buffer.reg_head.lo);
- tail = iommu_get_rb_pointer(iommu->cmd_buffer.reg_tail.lo);
-
- /* Tail pointer is rolled over by guest driver, value outside
- * cmd_buffer_entries cause iommu disabled
- */
-
- if ( tail >= iommu->cmd_buffer.entries ||
- head >= iommu->cmd_buffer.entries )
- {
- AMD_IOMMU_DEBUG("Error: guest iommu cmd buffer overflows\n");
- guest_iommu_disable(iommu);
- return;
- }
-
- entries_per_page = PAGE_SIZE / sizeof(cmd_entry_t);
-
- while ( head != tail )
- {
- int ret = 0;
-
- cmd_mfn = guest_iommu_get_table_mfn(d,
- reg_to_u64(iommu->cmd_buffer.reg_base),
- sizeof(cmd_entry_t), head);
- ASSERT(mfn_valid(_mfn(cmd_mfn)));
-
- cmd_base = map_domain_page(_mfn(cmd_mfn));
- cmd = cmd_base + head % entries_per_page;
-
- opcode = get_field_from_reg_u32(cmd->data[1],
- IOMMU_CMD_OPCODE_MASK,
- IOMMU_CMD_OPCODE_SHIFT);
- switch ( opcode )
- {
- case IOMMU_CMD_COMPLETION_WAIT:
- ret = do_completion_wait(d, cmd);
- break;
- case IOMMU_CMD_INVALIDATE_DEVTAB_ENTRY:
- ret = do_invalidate_dte(d, cmd);
- break;
- case IOMMU_CMD_INVALIDATE_IOMMU_PAGES:
- ret = do_invalidate_pages(d, cmd);
- break;
- case IOMMU_CMD_INVALIDATE_IOTLB_PAGES:
- ret = do_invalidate_iotlb_pages(d, cmd);
- break;
- case IOMMU_CMD_INVALIDATE_INT_TABLE:
- break;
- case IOMMU_CMD_COMPLETE_PPR_REQUEST:
- ret = do_complete_ppr_request(d, cmd);
- break;
- case IOMMU_CMD_INVALIDATE_IOMMU_ALL:
- ret = do_invalidate_all(d, cmd);
- break;
- default:
- AMD_IOMMU_DEBUG("CMD: Unknown command cmd_type = %lx "
- "head = %ld\n", opcode, head);
- break;
- }
-
- unmap_domain_page(cmd_base);
- if ( ++head >= iommu->cmd_buffer.entries )
- head = 0;
- if ( ret )
- guest_iommu_disable(iommu);
- }
-
- /* Now shift cmd buffer head pointer */
- iommu_set_rb_pointer(&iommu->cmd_buffer.reg_head.lo, head);
- return;
-}
-
-static int guest_iommu_write_ctrl(struct guest_iommu *iommu, uint64_t newctrl)
-{
- bool_t cmd_en, event_en, iommu_en, ppr_en, ppr_log_en;
- bool_t cmd_en_old, event_en_old, iommu_en_old;
- bool_t cmd_run;
-
- iommu_en = iommu_get_bit(newctrl,
- IOMMU_CONTROL_TRANSLATION_ENABLE_SHIFT);
- iommu_en_old = iommu_get_bit(iommu->reg_ctrl.lo,
- IOMMU_CONTROL_TRANSLATION_ENABLE_SHIFT);
-
- cmd_en = iommu_get_bit(newctrl,
- IOMMU_CONTROL_COMMAND_BUFFER_ENABLE_SHIFT);
- cmd_en_old = iommu_get_bit(iommu->reg_ctrl.lo,
- IOMMU_CONTROL_COMMAND_BUFFER_ENABLE_SHIFT);
- cmd_run = iommu_get_bit(iommu->reg_status.lo,
- IOMMU_STATUS_CMD_BUFFER_RUN_SHIFT);
- event_en = iommu_get_bit(newctrl,
- IOMMU_CONTROL_EVENT_LOG_ENABLE_SHIFT);
- event_en_old = iommu_get_bit(iommu->reg_ctrl.lo,
- IOMMU_CONTROL_EVENT_LOG_ENABLE_SHIFT);
-
- ppr_en = iommu_get_bit(newctrl,
- IOMMU_CONTROL_PPR_ENABLE_SHIFT);
- ppr_log_en = iommu_get_bit(newctrl,
- IOMMU_CONTROL_PPR_LOG_ENABLE_SHIFT);
-
- if ( iommu_en )
- {
- guest_iommu_enable(iommu);
- guest_iommu_enable_dev_table(iommu);
- }
-
- if ( iommu_en && cmd_en )
- {
- guest_iommu_enable_ring_buffer(iommu, &iommu->cmd_buffer,
- sizeof(cmd_entry_t));
- /* Enable iommu command processing */
- tasklet_schedule(&iommu->cmd_buffer_tasklet);
- }
-
- if ( iommu_en && event_en )
- {
- guest_iommu_enable_ring_buffer(iommu, &iommu->event_log,
- sizeof(event_entry_t));
- guest_iommu_set_status(iommu, IOMMU_STATUS_EVENT_LOG_RUN_SHIFT);
- guest_iommu_clear_status(iommu, IOMMU_STATUS_EVENT_OVERFLOW_SHIFT);
- }
-
- if ( iommu_en && ppr_en && ppr_log_en )
- {
- guest_iommu_enable_ring_buffer(iommu, &iommu->ppr_log,
- sizeof(ppr_entry_t));
- guest_iommu_set_status(iommu, IOMMU_STATUS_PPR_LOG_RUN_SHIFT);
- guest_iommu_clear_status(iommu, IOMMU_STATUS_PPR_LOG_OVERFLOW_SHIFT);
- }
-
- if ( iommu_en && cmd_en_old && !cmd_en )
- {
- /* Disable iommu command processing */
- tasklet_kill(&iommu->cmd_buffer_tasklet);
- }
-
- if ( event_en_old && !event_en )
- guest_iommu_clear_status(iommu, IOMMU_STATUS_EVENT_LOG_RUN_SHIFT);
-
- if ( iommu_en_old && !iommu_en )
- guest_iommu_disable(iommu);
-
- u64_to_reg(&iommu->reg_ctrl, newctrl);
- return 0;
-}
-
-static uint64_t iommu_mmio_read64(struct guest_iommu *iommu,
- unsigned long offset)
-{
- uint64_t val;
-
- switch ( offset )
- {
- case IOMMU_DEV_TABLE_BASE_LOW_OFFSET:
- val = reg_to_u64(iommu->dev_table.reg_base);
- break;
- case IOMMU_CMD_BUFFER_BASE_LOW_OFFSET:
- val = reg_to_u64(iommu->cmd_buffer.reg_base);
- break;
- case IOMMU_EVENT_LOG_BASE_LOW_OFFSET:
- val = reg_to_u64(iommu->event_log.reg_base);
- break;
- case IOMMU_PPR_LOG_BASE_LOW_OFFSET:
- val = reg_to_u64(iommu->ppr_log.reg_base);
- break;
- case IOMMU_CMD_BUFFER_HEAD_OFFSET:
- val = reg_to_u64(iommu->cmd_buffer.reg_head);
- break;
- case IOMMU_CMD_BUFFER_TAIL_OFFSET:
- val = reg_to_u64(iommu->cmd_buffer.reg_tail);
- break;
- case IOMMU_EVENT_LOG_HEAD_OFFSET:
- val = reg_to_u64(iommu->event_log.reg_head);
- break;
- case IOMMU_EVENT_LOG_TAIL_OFFSET:
- val = reg_to_u64(iommu->event_log.reg_tail);
- break;
- case IOMMU_PPR_LOG_HEAD_OFFSET:
- val = reg_to_u64(iommu->ppr_log.reg_head);
- break;
- case IOMMU_PPR_LOG_TAIL_OFFSET:
- val = reg_to_u64(iommu->ppr_log.reg_tail);
- break;
- case IOMMU_CONTROL_MMIO_OFFSET:
- val = reg_to_u64(iommu->reg_ctrl);
- break;
- case IOMMU_STATUS_MMIO_OFFSET:
- val = reg_to_u64(iommu->reg_status);
- break;
- case IOMMU_EXT_FEATURE_MMIO_OFFSET:
- val = reg_to_u64(iommu->reg_ext_feature);
- break;
-
- default:
- AMD_IOMMU_DEBUG("Guest reads unknown mmio offset = %lx\n", offset);
- val = 0;
- break;
- }
-
- return val;
-}
-
-static int guest_iommu_mmio_read(struct vcpu *v, unsigned long addr,
- unsigned int len, unsigned long *pval)
-{
- struct guest_iommu *iommu = vcpu_iommu(v);
- unsigned long offset;
- uint64_t val;
- uint32_t mmio, shift;
- uint64_t mask = 0;
-
- offset = addr - iommu->mmio_base;
-
- if ( unlikely((offset & (len - 1 )) || (len > 8)) )
- {
- AMD_IOMMU_DEBUG("iommu mmio read access is not aligned:"
- " offset = %lx, len = %x\n", offset, len);
- return X86EMUL_UNHANDLEABLE;
- }
-
- mask = (len == 8) ? ~0ULL : (1ULL << (len * 8)) - 1;
- shift = (offset & 7u) * 8;
-
- /* mmio access is always aligned on 8-byte boundary */
- mmio = offset & (~7u);
-
- spin_lock(&iommu->lock);
- val = iommu_mmio_read64(iommu, mmio);
- spin_unlock(&iommu->lock);
-
- *pval = (val >> shift ) & mask;
-
- return X86EMUL_OKAY;
-}
-
-static void guest_iommu_mmio_write64(struct guest_iommu *iommu,
- unsigned long offset, uint64_t val)
-{
- switch ( offset )
- {
- case IOMMU_DEV_TABLE_BASE_LOW_OFFSET:
- u64_to_reg(&iommu->dev_table.reg_base, val);
- break;
- case IOMMU_CMD_BUFFER_BASE_LOW_OFFSET:
- u64_to_reg(&iommu->cmd_buffer.reg_base, val);
- break;
- case IOMMU_EVENT_LOG_BASE_LOW_OFFSET:
- u64_to_reg(&iommu->event_log.reg_base, val);
- break;
- case IOMMU_PPR_LOG_BASE_LOW_OFFSET:
- u64_to_reg(&iommu->ppr_log.reg_base, val);
- break;
- case IOMMU_CONTROL_MMIO_OFFSET:
- guest_iommu_write_ctrl(iommu, val);
- break;
- case IOMMU_CMD_BUFFER_HEAD_OFFSET:
- u64_to_reg(&iommu->cmd_buffer.reg_head, val);
- break;
- case IOMMU_CMD_BUFFER_TAIL_OFFSET:
- u64_to_reg(&iommu->cmd_buffer.reg_tail, val);
- tasklet_schedule(&iommu->cmd_buffer_tasklet);
- break;
- case IOMMU_EVENT_LOG_HEAD_OFFSET:
- u64_to_reg(&iommu->event_log.reg_head, val);
- break;
- case IOMMU_EVENT_LOG_TAIL_OFFSET:
- u64_to_reg(&iommu->event_log.reg_tail, val);
- break;
- case IOMMU_PPR_LOG_HEAD_OFFSET:
- u64_to_reg(&iommu->ppr_log.reg_head, val);
- break;
- case IOMMU_PPR_LOG_TAIL_OFFSET:
- u64_to_reg(&iommu->ppr_log.reg_tail, val);
- break;
- case IOMMU_STATUS_MMIO_OFFSET:
- val &= IOMMU_STATUS_EVENT_OVERFLOW_MASK |
- IOMMU_STATUS_EVENT_LOG_INT_MASK |
- IOMMU_STATUS_COMP_WAIT_INT_MASK |
- IOMMU_STATUS_PPR_LOG_OVERFLOW_MASK |
- IOMMU_STATUS_PPR_LOG_INT_MASK |
- IOMMU_STATUS_GAPIC_LOG_OVERFLOW_MASK |
- IOMMU_STATUS_GAPIC_LOG_INT_MASK;
- u64_to_reg(&iommu->reg_status, reg_to_u64(iommu->reg_status) & ~val);
- break;
-
- default:
- AMD_IOMMU_DEBUG("guest writes unknown mmio offset = %lx,"
- " val = %" PRIx64 "\n", offset, val);
- break;
- }
-}
-
-static int guest_iommu_mmio_write(struct vcpu *v, unsigned long addr,
- unsigned int len, unsigned long val)
-{
- struct guest_iommu *iommu = vcpu_iommu(v);
- unsigned long offset;
- uint64_t reg_old, mmio;
- uint32_t shift;
- uint64_t mask = 0;
-
- offset = addr - iommu->mmio_base;
-
- if ( unlikely((offset & (len - 1)) || (len > 8)) )
- {
- AMD_IOMMU_DEBUG("iommu mmio write access is not aligned:"
- " offset = %lx, len = %x\n", offset, len);
- return X86EMUL_UNHANDLEABLE;
- }
-
- mask = (len == 8) ? ~0ULL : (1ULL << (len * 8)) - 1;
- shift = (offset & 7) * 8;
-
- /* mmio access is always aligned on 8-byte boundary */
- mmio = offset & ~7;
-
- spin_lock(&iommu->lock);
-
- reg_old = iommu_mmio_read64(iommu, mmio);
- reg_old &= ~(mask << shift);
- val = reg_old | ((val & mask) << shift);
- guest_iommu_mmio_write64(iommu, mmio, val);
-
- spin_unlock(&iommu->lock);
-
- return X86EMUL_OKAY;
-}
-
-int guest_iommu_set_base(struct domain *d, uint64_t base)
-{
- p2m_type_t t;
- struct guest_iommu *iommu = domain_iommu(d);
-
- if ( !iommu )
- return -EACCES;
-
- iommu->mmio_base = base;
- base >>= PAGE_SHIFT;
-
- for ( int i = 0; i < IOMMU_MMIO_PAGE_NR; i++ )
- {
- unsigned long gfn = base + i;
-
- get_gfn_query(d, gfn, &t);
- p2m_change_type_one(d, gfn, t, p2m_mmio_dm);
- put_gfn(d, gfn);
- }
-
- return 0;
-}
-
-/* Initialize mmio read only bits */
-static void guest_iommu_reg_init(struct guest_iommu *iommu)
-{
- uint32_t lower, upper;
-
- lower = upper = 0;
- /* Support prefetch */
- iommu_set_bit(&lower,IOMMU_EXT_FEATURE_PREFSUP_SHIFT);
- /* Support PPR log */
- iommu_set_bit(&lower,IOMMU_EXT_FEATURE_PPRSUP_SHIFT);
- /* Support guest translation */
- iommu_set_bit(&lower,IOMMU_EXT_FEATURE_GTSUP_SHIFT);
- /* Support invalidate all command */
- iommu_set_bit(&lower,IOMMU_EXT_FEATURE_IASUP_SHIFT);
-
- /* Host translation size has 6 levels */
- set_field_in_reg_u32(HOST_ADDRESS_SIZE_6_LEVEL, lower,
- IOMMU_EXT_FEATURE_HATS_MASK,
- IOMMU_EXT_FEATURE_HATS_SHIFT,
- &lower);
- /* Guest translation size has 6 levels */
- set_field_in_reg_u32(GUEST_ADDRESS_SIZE_6_LEVEL, lower,
- IOMMU_EXT_FEATURE_GATS_MASK,
- IOMMU_EXT_FEATURE_GATS_SHIFT,
- &lower);
- /* Single level gCR3 */
- set_field_in_reg_u32(GUEST_CR3_1_LEVEL, lower,
- IOMMU_EXT_FEATURE_GLXSUP_MASK,
- IOMMU_EXT_FEATURE_GLXSUP_SHIFT, &lower);
- /* 9 bit PASID */
- set_field_in_reg_u32(PASMAX_9_bit, upper,
- IOMMU_EXT_FEATURE_PASMAX_MASK,
- IOMMU_EXT_FEATURE_PASMAX_SHIFT, &upper);
-
- iommu->reg_ext_feature.lo = lower;
- iommu->reg_ext_feature.hi = upper;
-}
-
-static int guest_iommu_mmio_range(struct vcpu *v, unsigned long addr)
-{
- struct guest_iommu *iommu = vcpu_iommu(v);
-
- return iommu && addr >= iommu->mmio_base &&
- addr < iommu->mmio_base + IOMMU_MMIO_SIZE;
-}
-
-static const struct hvm_mmio_ops iommu_mmio_ops = {
- .check = guest_iommu_mmio_range,
- .read = guest_iommu_mmio_read,
- .write = guest_iommu_mmio_write
-};
-
-/* Domain specific initialization */
-int guest_iommu_init(struct domain* d)
-{
- struct guest_iommu *iommu;
- struct domain_iommu *hd = dom_iommu(d);
-
- if ( !is_hvm_domain(d) || !iommu_enabled || !iommuv2_enabled ||
- !has_viommu(d) )
- return 0;
-
- iommu = xzalloc(struct guest_iommu);
- if ( !iommu )
- {
- AMD_IOMMU_DEBUG("Error allocating guest iommu structure.\n");
- return 1;
- }
-
- guest_iommu_reg_init(iommu);
- iommu->mmio_base = ~0ULL;
- iommu->domain = d;
- hd->arch.g_iommu = iommu;
-
- tasklet_init(&iommu->cmd_buffer_tasklet,
- guest_iommu_process_command, (unsigned long)d);
-
- spin_lock_init(&iommu->lock);
-
- register_mmio_handler(d, &iommu_mmio_ops);
-
- return 0;
-}
-
-void guest_iommu_destroy(struct domain *d)
-{
- struct guest_iommu *iommu;
-
- iommu = domain_iommu(d);
- if ( !iommu )
- return;
-
- tasklet_kill(&iommu->cmd_buffer_tasklet);
- xfree(iommu);
-
- dom_iommu(d)->arch.g_iommu = NULL;
-}
diff --git a/xen/drivers/passthrough/x86/amd/iommu_init.c b/xen/drivers/passthrough/x86/amd/iommu_init.c
index 474992a75a..c0742d1cee 100644
--- a/xen/drivers/passthrough/x86/amd/iommu_init.c
+++ b/xen/drivers/passthrough/x86/amd/iommu_init.c
@@ -638,12 +638,15 @@ static void iommu_check_event_log(struct amd_iommu *iommu)
spin_unlock_irqrestore(&iommu->lock, flags);
}
+/*
+ * XXX Originally this function calls (dead) guest_iommu code. It does
+ * nothing other than zero'ing the entry (and handling erratum). This
+ * is what is looks like when all dead code is deleted.
+ */
void parse_ppr_log_entry(struct amd_iommu *iommu, u32 entry[])
{
- u16 device_id;
- u8 bus, devfn, code;
- struct pci_dev *pdev;
+ u8 code;
int count = 0;
code = get_field_from_reg_u32(entry[1], IOMMU_PPR_LOG_CODE_MASK,
@@ -668,18 +671,6 @@ void parse_ppr_log_entry(struct amd_iommu *iommu, u32 entry[])
IOMMU_PPR_LOG_CODE_SHIFT);
}
- /* here device_id is physical value */
- device_id = iommu_get_devid_from_cmd(entry[0]);
- bus = PCI_BUS(device_id);
- devfn = PCI_DEVFN2(device_id);
-
- pcidevs_lock();
- pdev = pci_get_real_pdev(iommu->seg, bus, devfn);
- pcidevs_unlock();
-
- if ( pdev )
- guest_iommu_add_ppr_log(pdev->domain, entry);
-
memset(entry, 0, IOMMU_PPR_LOG_ENTRY_SIZE);
}
diff --git a/xen/include/asm-x86/amd-iommu.h b/xen/include/asm-x86/amd-iommu.h
index 02715b482b..102518a864 100644
--- a/xen/include/asm-x86/amd-iommu.h
+++ b/xen/include/asm-x86/amd-iommu.h
@@ -134,57 +134,6 @@ struct ivrs_mappings *get_ivrs_mappings(u16 seg);
int iterate_ivrs_mappings(int (*)(u16 seg, struct ivrs_mappings *));
int iterate_ivrs_entries(int (*)(u16 seg, struct ivrs_mappings *));
-/* 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 */
- struct mmio_reg reg_ctrl; /* MMIO offset 0018h */
- struct mmio_reg reg_status; /* MMIO offset 2020h */
- struct mmio_reg 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-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
index 99bc21c7b3..9163dc9035 100644
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
@@ -130,14 +130,6 @@ 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;
diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h
index 14ad0489a6..8cb7bec26b 100644
--- a/xen/include/asm-x86/iommu.h
+++ b/xen/include/asm-x86/iommu.h
@@ -41,7 +41,6 @@ struct arch_iommu
/* amd iommu support */
int paging_mode;
struct page_info *root_table;
- struct guest_iommu *g_iommu;
};
extern const struct iommu_ops intel_iommu_ops;
--
2.11.0
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
next prev parent reply other threads:[~2018-02-21 21:47 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-21 21:46 [PATCH RFC 00/10] x86 passthrough code cleanup Wei Liu
2018-02-21 21:46 ` [PATCH RFC 01/10] passthrough: rearrange x86 code Wei Liu
2018-04-23 15:27 ` Jan Beulich
2018-02-21 21:46 ` [PATCH RFC 02/10] passthrough: split out x86 PCI code to x86/pci.c Wei Liu
2018-02-26 10:57 ` Julien Grall
2018-04-23 15:34 ` Jan Beulich
2018-04-24 9:08 ` Julien Grall
2018-02-21 21:46 ` [PATCH RFC 03/10] x86/passthrough: io.c is used for HVM only Wei Liu
2018-04-23 15:37 ` Jan Beulich
2018-02-21 21:46 ` [PATCH RFC 04/10] x86/passthrough: arch_pci_clean_irqs is " Wei Liu
2018-02-21 21:46 ` [PATCH RFC 05/10] x86/passthrough: move hvm_dpci_isairq_eoi Wei Liu
2018-04-23 15:39 ` Jan Beulich
2018-02-21 21:46 ` Wei Liu [this message]
2018-05-02 17:10 ` [PATCH RFC 06/10] passthrough/amd: remove guest iommu support Suravee Suthikulpanit
2018-02-21 21:46 ` [PATCH RFC 07/10] passthrough/amd: split out hvm code from iommu_map.c Wei Liu
2018-04-23 15:43 ` Jan Beulich
2018-05-02 17:32 ` Suravee Suthikulpanit
2018-02-21 21:46 ` [PATCH RFC 08/10] passthrough/amd: make clear_iommu_pte_present static Wei Liu
2018-02-21 21:47 ` [PATCH RFC 09/10] passthrough/intel: put some code under CONFIG_HVM Wei Liu
2018-04-23 15:47 ` Jan Beulich
2018-02-21 21:47 ` [PATCH RFC 10/10] x86: check hvm domain before calling pt_irq_destroy_bind Wei Liu
2018-02-23 5:12 ` [PATCH RFC 00/10] x86 passthrough code cleanup Tian, Kevin
2018-02-23 16:08 ` Wei Liu
2018-02-24 3:23 ` Tian, Kevin
2018-02-26 8:20 ` Jan Beulich
2018-02-26 12:45 ` Wei Liu
2018-02-24 4:39 ` Doug Goldstein
2018-02-26 0:47 ` Marek Marczykowski-Górecki
2018-02-26 12:49 ` Wei Liu
2018-03-08 12:18 ` Wei Liu
2018-03-08 12:37 ` Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180221214701.1646-7-wei.liu2@citrix.com \
--to=wei.liu2@citrix.com \
--cc=JBeulich@suse.com \
--cc=andrew.cooper3@citrix.com \
--cc=suravee.suthikulpanit@amd.com \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).