From nobody Sun Nov 9 17:55:51 2025 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=temperror (zoho.com: Error in retrieving data from DNS) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1551799208699267.38285914036464; Tue, 5 Mar 2019 07:20:08 -0800 (PST) Received: from localhost ([127.0.0.1]:44345 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h1BrS-0003H1-7d for importer@patchew.org; Tue, 05 Mar 2019 10:20:06 -0500 Received: from eggs.gnu.org ([209.51.188.92]:59297) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h1Bpz-0002WG-IR for qemu-devel@nongnu.org; Tue, 05 Mar 2019 10:18:41 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h1Bpr-0004kS-0I for qemu-devel@nongnu.org; Tue, 05 Mar 2019 10:18:34 -0500 Received: from mail-wm1-x341.google.com ([2a00:1450:4864:20::341]:53762) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1h1Bpn-0004gS-SX for qemu-devel@nongnu.org; Tue, 05 Mar 2019 10:18:25 -0500 Received: by mail-wm1-x341.google.com with SMTP id e74so2934462wmg.3 for ; Tue, 05 Mar 2019 07:18:23 -0800 (PST) Received: from localhost.localdomain ([102.166.88.40]) by smtp.gmail.com with ESMTPSA id l21sm7307610wme.38.2019.03.05.07.18.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 05 Mar 2019 07:18:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=NPezl40IUBzHEvD0QB2xSYNqi0gcdPI7Flz2kS4vfc0=; b=iYr0JmfhYIgtXUc/bkLJ6KxtZn6D2T4sINJVltkrfvvIaHT5BepOqDpZHPXQbOdDdy W4i+yUbrCPM3R+Q0Pu5uzzg+g95Qua/BYkKa1Ve4/L/VdNYGPWmbGEshsW75ExuPm0sU H49puSe//eCV50/TWPL/C0wc0sljAR3O61J4R/AWSmuOF/UI8UTy4ocf7XuxjPSyGUTB c4du37UzL8Lh9BPDeW8xLRNWvPAvbz321QgjDxoeh7DeKAv7P5XYB1GSkJ9GgrLAFwhD GvujoQPFUBn7q+ki/UeB9SiY/VX9J884rciFvzpPsZcJfj4ekdgW0l1F3552AgVTnlnQ jDpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=NPezl40IUBzHEvD0QB2xSYNqi0gcdPI7Flz2kS4vfc0=; b=TU32DOnM9SzI9XPjPrD6FAWkJH2QgjQCdqte2ojxxc0/fYQVh9Zzpf8zPAki2HXV/t lho16jx27vH2kSLYM56pdKENUglMnoHeoo0kp50EJbz6ZtbZUuBvOzJsFwf6jsElloKw A3PGTeKJ8cB9Xg+rY6IWcuLmCrIJa40fdKP8uYkcoFUeHKWpSrNL5FodXOjiuQZkqMS6 lrssZE4uQHAdQihNJqEKrXPVEUX9ZzD8f0arxG6uYWezFttbgHM7+vFtFZSP+KLJC8fw px9DOBrIUDLgMjN2Ogg/SM7kyRalShT1fQCPx+Yd2mdUS2CBZqS9POwF1OqHmfbKhD2v KM6A== X-Gm-Message-State: APjAAAX2oIbDWWrXrUr3+4wjg0gWJir1JBz9eF4FWNEmPEmzBxtEu2ro FvmqzCuBS6kIsaxDi0GnaO5RWLiF X-Google-Smtp-Source: APXvYqx5zQWUC6AyNjhwQo5YgVzFM49edSaBCy/+474w2aEVS+IiyzAF5G0SpPM1TMly7N6Cyt//Ug== X-Received: by 2002:a1c:3c02:: with SMTP id j2mr3197617wma.72.1551799100053; Tue, 05 Mar 2019 07:18:20 -0800 (PST) From: David Kiarie To: qemu-devel@nongnu.org Date: Tue, 5 Mar 2019 18:17:30 +0300 Message-Id: <20190305151731.31213-1-davidkiarie4@gmail.com> X-Mailer: git-send-email 2.21.0 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::341 Subject: [Qemu-devel] [PATCH] hw/i386: strip AMD IOMMU from Qemu X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mst@redhat.com, jan.kiszka@siemens.com, peterx@redhat.com, alexaltea123@gmail.com, pbonzini@redhat.com, David Kiarie , rth@twiddle.net Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Signed-off-by: David Kiarie --- hw/i386/Makefile.objs | 1 - hw/i386/acpi-build.c | 84 +-- hw/i386/amd_iommu.c | 1645 ----------------------------------------- hw/i386/amd_iommu.h | 373 ---------- hw/i386/pc_q35.c | 2 - hw/i386/trace-events | 43 -- 6 files changed, 1 insertion(+), 2147 deletions(-) delete mode 100644 hw/i386/amd_iommu.c delete mode 100644 hw/i386/amd_iommu.h diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 3de7ca2..681f36a 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -5,7 +5,6 @@ obj-$(CONFIG_I440FX) +=3D pc_piix.o obj-$(CONFIG_Q35) +=3D pc_q35.o obj-y +=3D pc_sysfw.o obj-$(CONFIG_VTD) +=3D x86-iommu.o intel_iommu.o -obj-$(CONFIG_AMD_IOMMU) +=3D x86-iommu.o amd_iommu.o obj-$(CONFIG_XEN) +=3D ../xenpv/ xen/ obj-$(CONFIG_VMPORT) +=3D vmport.o obj-$(CONFIG_VMMOUSE) +=3D vmmouse.o diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 9ecc96d..4984c17 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -60,7 +60,6 @@ #include "hw/acpi/aml-build.h" =20 #include "qom/qom-qobject.h" -#include "hw/i386/amd_iommu.h" #include "hw/i386/intel_iommu.h" =20 #include "hw/acpi/ipmi.h" @@ -2489,84 +2488,6 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linke= r) */ #define IOAPIC_SB_DEVID (uint64_t)PCI_BUILD_BDF(0, PCI_DEVFN(0x14, 0)) =20 -static void -build_amd_iommu(GArray *table_data, BIOSLinker *linker) -{ - int ivhd_table_len =3D 28; - int iommu_start =3D table_data->len; - AMDVIState *s =3D AMD_IOMMU_DEVICE(x86_iommu_get_default()); - - /* IVRS header */ - acpi_data_push(table_data, sizeof(AcpiTableHeader)); - /* IVinfo - IO virtualization information common to all - * IOMMU units in a system - */ - build_append_int_noprefix(table_data, 40UL << 8/* PASize */, 4); - /* reserved */ - build_append_int_noprefix(table_data, 0, 8); - - /* IVHD definition - type 10h */ - build_append_int_noprefix(table_data, 0x10, 1); - /* virtualization flags */ - build_append_int_noprefix(table_data, - (1UL << 0) | /* HtTunEn */ - (1UL << 4) | /* iotblSup */ - (1UL << 6) | /* PrefSup */ - (1UL << 7), /* PPRSup */ - 1); - - /* - * When interrupt remapping is supported, we add a special IVHD device - * for type IO-APIC. - */ - if (x86_iommu_ir_supported(x86_iommu_get_default())) { - ivhd_table_len +=3D 8; - } - /* IVHD length */ - build_append_int_noprefix(table_data, ivhd_table_len, 2); - /* DeviceID */ - build_append_int_noprefix(table_data, s->devid, 2); - /* Capability offset */ - build_append_int_noprefix(table_data, s->capab_offset, 2); - /* IOMMU base address */ - build_append_int_noprefix(table_data, s->mmio.addr, 8); - /* PCI Segment Group */ - build_append_int_noprefix(table_data, 0, 2); - /* IOMMU info */ - build_append_int_noprefix(table_data, 0, 2); - /* IOMMU Feature Reporting */ - build_append_int_noprefix(table_data, - (48UL << 30) | /* HATS */ - (48UL << 28) | /* GATS */ - (1UL << 2) | /* GTSup */ - (1UL << 6), /* GASup */ - 4); - /* - * Type 1 device entry reporting all devices - * These are 4-byte device entries currently reporting the range of - * Refer to Spec - Table 95:IVHD Device Entry Type Codes(4-byte) - */ - build_append_int_noprefix(table_data, 0x0000001, 4); - - /* - * Add a special IVHD device type. - * Refer to spec - Table 95: IVHD device entry type codes - * - * Linux IOMMU driver checks for the special IVHD device (type IO-APIC= ). - * See Linux kernel commit 'c2ff5cf5294bcbd7fa50f7d860e90a66db7e5059' - */ - if (x86_iommu_ir_supported(x86_iommu_get_default())) { - build_append_int_noprefix(table_data, - (0x1ull << 56) | /* type IOAPIC= */ - (IOAPIC_SB_DEVID << 40) | /* IOAPIC devi= d */ - 0x48, /* special dev= ice */ - 8); - } - - build_header(linker, table_data, (void *)(table_data->data + iommu_sta= rt), - "IVRS", table_data->len - iommu_start, 1, NULL, NULL); -} - typedef struct AcpiBuildState { /* Copy of table in RAM (for patching). */ @@ -2696,10 +2617,7 @@ void acpi_build(AcpiBuildTables *tables, MachineStat= e *machine) } if (x86_iommu_get_default()) { IommuType IOMMUType =3D x86_iommu_get_type(); - if (IOMMUType =3D=3D TYPE_AMD) { - acpi_add_table(table_offsets, tables_blob); - build_amd_iommu(tables_blob, tables->linker); - } else if (IOMMUType =3D=3D TYPE_INTEL) { + if (IOMMUType =3D=3D TYPE_INTEL) { acpi_add_table(table_offsets, tables_blob); build_dmar_q35(tables_blob, tables->linker); } diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c deleted file mode 100644 index 8ad707a..0000000 --- a/hw/i386/amd_iommu.c +++ /dev/null @@ -1,1645 +0,0 @@ -/* - * QEMU emulation of AMD IOMMU (AMD-Vi) - * - * Copyright (C) 2011 Eduard - Gabriel Munteanu - * Copyright (C) 2015 David Kiarie, - * - * 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 . - * - * Cache implementation inspired by hw/i386/intel_iommu.c - */ -#include "qemu/osdep.h" -#include "hw/i386/pc.h" -#include "hw/pci/msi.h" -#include "hw/pci/pci_bus.h" -#include "amd_iommu.h" -#include "qapi/error.h" -#include "qemu/error-report.h" -#include "hw/i386/apic_internal.h" -#include "trace.h" -#include "hw/i386/apic-msidef.h" - -/* used AMD-Vi MMIO registers */ -const char *amdvi_mmio_low[] =3D { - "AMDVI_MMIO_DEVTAB_BASE", - "AMDVI_MMIO_CMDBUF_BASE", - "AMDVI_MMIO_EVTLOG_BASE", - "AMDVI_MMIO_CONTROL", - "AMDVI_MMIO_EXCL_BASE", - "AMDVI_MMIO_EXCL_LIMIT", - "AMDVI_MMIO_EXT_FEATURES", - "AMDVI_MMIO_PPR_BASE", - "UNHANDLED" -}; -const char *amdvi_mmio_high[] =3D { - "AMDVI_MMIO_COMMAND_HEAD", - "AMDVI_MMIO_COMMAND_TAIL", - "AMDVI_MMIO_EVTLOG_HEAD", - "AMDVI_MMIO_EVTLOG_TAIL", - "AMDVI_MMIO_STATUS", - "AMDVI_MMIO_PPR_HEAD", - "AMDVI_MMIO_PPR_TAIL", - "UNHANDLED" -}; - -struct AMDVIAddressSpace { - uint8_t bus_num; /* bus number */ - uint8_t devfn; /* device function */ - AMDVIState *iommu_state; /* AMDVI - one per machine */ - MemoryRegion root; /* AMDVI Root memory map region */ - IOMMUMemoryRegion iommu; /* Device's address translation region */ - MemoryRegion iommu_ir; /* Device's interrupt remapping region */ - AddressSpace as; /* device's corresponding address space */ -}; - -/* AMDVI cache entry */ -typedef struct AMDVIIOTLBEntry { - uint16_t domid; /* assigned domain id */ - uint16_t devid; /* device owning entry */ - uint64_t perms; /* access permissions */ - uint64_t translated_addr; /* translated address */ - uint64_t page_mask; /* physical page size */ -} AMDVIIOTLBEntry; - -/* configure MMIO registers at startup/reset */ -static void amdvi_set_quad(AMDVIState *s, hwaddr addr, uint64_t val, - uint64_t romask, uint64_t w1cmask) -{ - stq_le_p(&s->mmior[addr], val); - stq_le_p(&s->romask[addr], romask); - stq_le_p(&s->w1cmask[addr], w1cmask); -} - -static uint16_t amdvi_readw(AMDVIState *s, hwaddr addr) -{ - return lduw_le_p(&s->mmior[addr]); -} - -static uint32_t amdvi_readl(AMDVIState *s, hwaddr addr) -{ - return ldl_le_p(&s->mmior[addr]); -} - -static uint64_t amdvi_readq(AMDVIState *s, hwaddr addr) -{ - return ldq_le_p(&s->mmior[addr]); -} - -/* internal write */ -static void amdvi_writeq_raw(AMDVIState *s, uint64_t val, hwaddr addr) -{ - stq_le_p(&s->mmior[addr], val); -} - -/* external write */ -static void amdvi_writew(AMDVIState *s, hwaddr addr, uint16_t val) -{ - uint16_t romask =3D lduw_le_p(&s->romask[addr]); - uint16_t w1cmask =3D lduw_le_p(&s->w1cmask[addr]); - uint16_t oldval =3D lduw_le_p(&s->mmior[addr]); - stw_le_p(&s->mmior[addr], - ((oldval & romask) | (val & ~romask)) & ~(val & w1cmask)); -} - -static void amdvi_writel(AMDVIState *s, hwaddr addr, uint32_t val) -{ - uint32_t romask =3D ldl_le_p(&s->romask[addr]); - uint32_t w1cmask =3D ldl_le_p(&s->w1cmask[addr]); - uint32_t oldval =3D ldl_le_p(&s->mmior[addr]); - stl_le_p(&s->mmior[addr], - ((oldval & romask) | (val & ~romask)) & ~(val & w1cmask)); -} - -static void amdvi_writeq(AMDVIState *s, hwaddr addr, uint64_t val) -{ - uint64_t romask =3D ldq_le_p(&s->romask[addr]); - uint64_t w1cmask =3D ldq_le_p(&s->w1cmask[addr]); - uint32_t oldval =3D ldq_le_p(&s->mmior[addr]); - stq_le_p(&s->mmior[addr], - ((oldval & romask) | (val & ~romask)) & ~(val & w1cmask)); -} - -/* OR a 64-bit register with a 64-bit value */ -static bool amdvi_test_mask(AMDVIState *s, hwaddr addr, uint64_t val) -{ - return amdvi_readq(s, addr) | val; -} - -/* OR a 64-bit register with a 64-bit value storing result in the register= */ -static void amdvi_assign_orq(AMDVIState *s, hwaddr addr, uint64_t val) -{ - amdvi_writeq_raw(s, addr, amdvi_readq(s, addr) | val); -} - -/* AND a 64-bit register with a 64-bit value storing result in the registe= r */ -static void amdvi_assign_andq(AMDVIState *s, hwaddr addr, uint64_t val) -{ - amdvi_writeq_raw(s, addr, amdvi_readq(s, addr) & val); -} - -static void amdvi_generate_msi_interrupt(AMDVIState *s) -{ - MSIMessage msg =3D {}; - MemTxAttrs attrs =3D { - .requester_id =3D pci_requester_id(&s->pci.dev) - }; - - if (msi_enabled(&s->pci.dev)) { - msg =3D msi_get_message(&s->pci.dev, 0); - address_space_stl_le(&address_space_memory, msg.address, msg.data, - attrs, NULL); - } -} - -static void amdvi_log_event(AMDVIState *s, uint64_t *evt) -{ - /* event logging not enabled */ - if (!s->evtlog_enabled || amdvi_test_mask(s, AMDVI_MMIO_STATUS, - AMDVI_MMIO_STATUS_EVT_OVF)) { - return; - } - - /* event log buffer full */ - if (s->evtlog_tail >=3D s->evtlog_len) { - amdvi_assign_orq(s, AMDVI_MMIO_STATUS, AMDVI_MMIO_STATUS_EVT_OVF); - /* generate interrupt */ - amdvi_generate_msi_interrupt(s); - return; - } - - if (dma_memory_write(&address_space_memory, s->evtlog + s->evtlog_tail, - &evt, AMDVI_EVENT_LEN)) { - trace_amdvi_evntlog_fail(s->evtlog, s->evtlog_tail); - } - - s->evtlog_tail +=3D AMDVI_EVENT_LEN; - amdvi_assign_orq(s, AMDVI_MMIO_STATUS, AMDVI_MMIO_STATUS_COMP_INT); - amdvi_generate_msi_interrupt(s); -} - -static void amdvi_setevent_bits(uint64_t *buffer, uint64_t value, int star= t, - int length) -{ - int index =3D start / 64, bitpos =3D start % 64; - uint64_t mask =3D MAKE_64BIT_MASK(start, length); - buffer[index] &=3D ~mask; - buffer[index] |=3D (value << bitpos) & mask; -} -/* - * AMDVi event structure - * 0:15 -> DeviceID - * 55:63 -> event type + miscellaneous info - * 63:127 -> related address - */ -static void amdvi_encode_event(uint64_t *evt, uint16_t devid, uint64_t add= r, - uint16_t info) -{ - amdvi_setevent_bits(evt, devid, 0, 16); - amdvi_setevent_bits(evt, info, 55, 8); - amdvi_setevent_bits(evt, addr, 63, 64); -} -/* log an error encountered during a page walk - * - * @addr: virtual address in translation request - */ -static void amdvi_page_fault(AMDVIState *s, uint16_t devid, - hwaddr addr, uint16_t info) -{ - uint64_t evt[4]; - - info |=3D AMDVI_EVENT_IOPF_I | AMDVI_EVENT_IOPF; - amdvi_encode_event(evt, devid, addr, info); - amdvi_log_event(s, evt); - pci_word_test_and_set_mask(s->pci.dev.config + PCI_STATUS, - PCI_STATUS_SIG_TARGET_ABORT); -} -/* - * log a master abort accessing device table - * @devtab : address of device table entry - * @info : error flags - */ -static void amdvi_log_devtab_error(AMDVIState *s, uint16_t devid, - hwaddr devtab, uint16_t info) -{ - uint64_t evt[4]; - - info |=3D AMDVI_EVENT_DEV_TAB_HW_ERROR; - - amdvi_encode_event(evt, devid, devtab, info); - amdvi_log_event(s, evt); - pci_word_test_and_set_mask(s->pci.dev.config + PCI_STATUS, - PCI_STATUS_SIG_TARGET_ABORT); -} -/* log an event trying to access command buffer - * @addr : address that couldn't be accessed - */ -static void amdvi_log_command_error(AMDVIState *s, hwaddr addr) -{ - uint64_t evt[4], info =3D AMDVI_EVENT_COMMAND_HW_ERROR; - - amdvi_encode_event(evt, 0, addr, info); - amdvi_log_event(s, evt); - pci_word_test_and_set_mask(s->pci.dev.config + PCI_STATUS, - PCI_STATUS_SIG_TARGET_ABORT); -} -/* log an illegal comand event - * @addr : address of illegal command - */ -static void amdvi_log_illegalcom_error(AMDVIState *s, uint16_t info, - hwaddr addr) -{ - uint64_t evt[4]; - - info |=3D AMDVI_EVENT_ILLEGAL_COMMAND_ERROR; - amdvi_encode_event(evt, 0, addr, info); - amdvi_log_event(s, evt); -} -/* log an error accessing device table - * - * @devid : device owning the table entry - * @devtab : address of device table entry - * @info : error flags - */ -static void amdvi_log_illegaldevtab_error(AMDVIState *s, uint16_t devid, - hwaddr addr, uint16_t info) -{ - uint64_t evt[4]; - - info |=3D AMDVI_EVENT_ILLEGAL_DEVTAB_ENTRY; - amdvi_encode_event(evt, devid, addr, info); - amdvi_log_event(s, evt); -} -/* log an error accessing a PTE entry - * @addr : address that couldn't be accessed - */ -static void amdvi_log_pagetab_error(AMDVIState *s, uint16_t devid, - hwaddr addr, uint16_t info) -{ - uint64_t evt[4]; - - info |=3D AMDVI_EVENT_PAGE_TAB_HW_ERROR; - amdvi_encode_event(evt, devid, addr, info); - amdvi_log_event(s, evt); - pci_word_test_and_set_mask(s->pci.dev.config + PCI_STATUS, - PCI_STATUS_SIG_TARGET_ABORT); -} - -static gboolean amdvi_uint64_equal(gconstpointer v1, gconstpointer v2) -{ - return *((const uint64_t *)v1) =3D=3D *((const uint64_t *)v2); -} - -static guint amdvi_uint64_hash(gconstpointer v) -{ - return (guint)*(const uint64_t *)v; -} - -static AMDVIIOTLBEntry *amdvi_iotlb_lookup(AMDVIState *s, hwaddr addr, - uint64_t devid) -{ - uint64_t key =3D (addr >> AMDVI_PAGE_SHIFT_4K) | - ((uint64_t)(devid) << AMDVI_DEVID_SHIFT); - return g_hash_table_lookup(s->iotlb, &key); -} - -static void amdvi_iotlb_reset(AMDVIState *s) -{ - assert(s->iotlb); - trace_amdvi_iotlb_reset(); - g_hash_table_remove_all(s->iotlb); -} - -static gboolean amdvi_iotlb_remove_by_devid(gpointer key, gpointer value, - gpointer user_data) -{ - AMDVIIOTLBEntry *entry =3D (AMDVIIOTLBEntry *)value; - uint16_t devid =3D *(uint16_t *)user_data; - return entry->devid =3D=3D devid; -} - -static void amdvi_iotlb_remove_page(AMDVIState *s, hwaddr addr, - uint64_t devid) -{ - uint64_t key =3D (addr >> AMDVI_PAGE_SHIFT_4K) | - ((uint64_t)(devid) << AMDVI_DEVID_SHIFT); - g_hash_table_remove(s->iotlb, &key); -} - -static void amdvi_update_iotlb(AMDVIState *s, uint16_t devid, - uint64_t gpa, IOMMUTLBEntry to_cache, - uint16_t domid) -{ - AMDVIIOTLBEntry *entry =3D g_new(AMDVIIOTLBEntry, 1); - uint64_t *key =3D g_new(uint64_t, 1); - uint64_t gfn =3D gpa >> AMDVI_PAGE_SHIFT_4K; - - /* don't cache erroneous translations */ - if (to_cache.perm !=3D IOMMU_NONE) { - trace_amdvi_cache_update(domid, PCI_BUS_NUM(devid), PCI_SLOT(devid= ), - PCI_FUNC(devid), gpa, to_cache.translated_addr); - - if (g_hash_table_size(s->iotlb) >=3D AMDVI_IOTLB_MAX_SIZE) { - amdvi_iotlb_reset(s); - } - - entry->domid =3D domid; - entry->perms =3D to_cache.perm; - entry->translated_addr =3D to_cache.translated_addr; - entry->page_mask =3D to_cache.addr_mask; - *key =3D gfn | ((uint64_t)(devid) << AMDVI_DEVID_SHIFT); - g_hash_table_replace(s->iotlb, key, entry); - } -} - -static void amdvi_completion_wait(AMDVIState *s, uint64_t *cmd) -{ - /* pad the last 3 bits */ - hwaddr addr =3D cpu_to_le64(extract64(cmd[0], 3, 49)) << 3; - uint64_t data =3D cpu_to_le64(cmd[1]); - - if (extract64(cmd[0], 51, 8)) { - amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), - s->cmdbuf + s->cmdbuf_head); - } - if (extract64(cmd[0], 0, 1)) { - if (dma_memory_write(&address_space_memory, addr, &data, - AMDVI_COMPLETION_DATA_SIZE)) { - trace_amdvi_completion_wait_fail(addr); - } - } - /* set completion interrupt */ - if (extract64(cmd[0], 1, 1)) { - amdvi_test_mask(s, AMDVI_MMIO_STATUS, AMDVI_MMIO_STATUS_COMP_INT); - /* generate interrupt */ - amdvi_generate_msi_interrupt(s); - } - trace_amdvi_completion_wait(addr, data); -} - -/* log error without aborting since linux seems to be using reserved bits = */ -static void amdvi_inval_devtab_entry(AMDVIState *s, uint64_t *cmd) -{ - uint16_t devid =3D cpu_to_le16((uint16_t)extract64(cmd[0], 0, 16)); - - /* This command should invalidate internal caches of which there isn't= */ - if (extract64(cmd[0], 15, 16) || cmd[1]) { - amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), - s->cmdbuf + s->cmdbuf_head); - } - trace_amdvi_devtab_inval(PCI_BUS_NUM(devid), PCI_SLOT(devid), - PCI_FUNC(devid)); -} - -static void amdvi_complete_ppr(AMDVIState *s, uint64_t *cmd) -{ - if (extract64(cmd[0], 15, 16) || extract64(cmd[0], 19, 8) || - extract64(cmd[1], 0, 2) || extract64(cmd[1], 3, 29) - || extract64(cmd[1], 47, 16)) { - amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), - s->cmdbuf + s->cmdbuf_head); - } - trace_amdvi_ppr_exec(); -} - -static void amdvi_inval_all(AMDVIState *s, uint64_t *cmd) -{ - if (extract64(cmd[0], 0, 60) || cmd[1]) { - amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), - s->cmdbuf + s->cmdbuf_head); - } - - amdvi_iotlb_reset(s); - trace_amdvi_all_inval(); -} - -static gboolean amdvi_iotlb_remove_by_domid(gpointer key, gpointer value, - gpointer user_data) -{ - AMDVIIOTLBEntry *entry =3D (AMDVIIOTLBEntry *)value; - uint16_t domid =3D *(uint16_t *)user_data; - return entry->domid =3D=3D domid; -} - -/* we don't have devid - we can't remove pages by address */ -static void amdvi_inval_pages(AMDVIState *s, uint64_t *cmd) -{ - uint16_t domid =3D cpu_to_le16((uint16_t)extract64(cmd[0], 32, 16)); - - if (extract64(cmd[0], 20, 12) || extract64(cmd[0], 16, 12) || - extract64(cmd[0], 3, 10)) { - amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), - s->cmdbuf + s->cmdbuf_head); - } - - g_hash_table_foreach_remove(s->iotlb, amdvi_iotlb_remove_by_domid, - &domid); - trace_amdvi_pages_inval(domid); -} - -static void amdvi_prefetch_pages(AMDVIState *s, uint64_t *cmd) -{ - if (extract64(cmd[0], 16, 8) || extract64(cmd[0], 20, 8) || - extract64(cmd[1], 1, 1) || extract64(cmd[1], 3, 1) || - extract64(cmd[1], 5, 7)) { - amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), - s->cmdbuf + s->cmdbuf_head); - } - - trace_amdvi_prefetch_pages(); -} - -static void amdvi_inval_inttable(AMDVIState *s, uint64_t *cmd) -{ - if (extract64(cmd[0], 16, 16) || cmd[1]) { - amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), - s->cmdbuf + s->cmdbuf_head); - return; - } - - trace_amdvi_intr_inval(); -} - -/* FIXME: Try to work with the specified size instead of all the pages - * when the S bit is on - */ -static void iommu_inval_iotlb(AMDVIState *s, uint64_t *cmd) -{ - - uint16_t devid =3D extract64(cmd[0], 0, 16); - if (extract64(cmd[1], 1, 1) || extract64(cmd[1], 3, 9)) { - amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), - s->cmdbuf + s->cmdbuf_head); - return; - } - - if (extract64(cmd[1], 0, 1)) { - g_hash_table_foreach_remove(s->iotlb, amdvi_iotlb_remove_by_devid, - &devid); - } else { - amdvi_iotlb_remove_page(s, cpu_to_le64(extract64(cmd[1], 12, 52)) = << 12, - cpu_to_le16(extract64(cmd[1], 0, 16))); - } - trace_amdvi_iotlb_inval(); -} - -/* not honouring reserved bits is regarded as an illegal command */ -static void amdvi_cmdbuf_exec(AMDVIState *s) -{ - uint64_t cmd[2]; - - if (dma_memory_read(&address_space_memory, s->cmdbuf + s->cmdbuf_head, - cmd, AMDVI_COMMAND_SIZE)) { - trace_amdvi_command_read_fail(s->cmdbuf, s->cmdbuf_head); - amdvi_log_command_error(s, s->cmdbuf + s->cmdbuf_head); - return; - } - - switch (extract64(cmd[0], 60, 4)) { - case AMDVI_CMD_COMPLETION_WAIT: - amdvi_completion_wait(s, cmd); - break; - case AMDVI_CMD_INVAL_DEVTAB_ENTRY: - amdvi_inval_devtab_entry(s, cmd); - break; - case AMDVI_CMD_INVAL_AMDVI_PAGES: - amdvi_inval_pages(s, cmd); - break; - case AMDVI_CMD_INVAL_IOTLB_PAGES: - iommu_inval_iotlb(s, cmd); - break; - case AMDVI_CMD_INVAL_INTR_TABLE: - amdvi_inval_inttable(s, cmd); - break; - case AMDVI_CMD_PREFETCH_AMDVI_PAGES: - amdvi_prefetch_pages(s, cmd); - break; - case AMDVI_CMD_COMPLETE_PPR_REQUEST: - amdvi_complete_ppr(s, cmd); - break; - case AMDVI_CMD_INVAL_AMDVI_ALL: - amdvi_inval_all(s, cmd); - break; - default: - trace_amdvi_unhandled_command(extract64(cmd[1], 60, 4)); - /* log illegal command */ - amdvi_log_illegalcom_error(s, extract64(cmd[1], 60, 4), - s->cmdbuf + s->cmdbuf_head); - } -} - -static void amdvi_cmdbuf_run(AMDVIState *s) -{ - if (!s->cmdbuf_enabled) { - trace_amdvi_command_error(amdvi_readq(s, AMDVI_MMIO_CONTROL)); - return; - } - - /* check if there is work to do. */ - while (s->cmdbuf_head !=3D s->cmdbuf_tail) { - trace_amdvi_command_exec(s->cmdbuf_head, s->cmdbuf_tail, s->cmdbuf= ); - amdvi_cmdbuf_exec(s); - s->cmdbuf_head +=3D AMDVI_COMMAND_SIZE; - amdvi_writeq_raw(s, s->cmdbuf_head, AMDVI_MMIO_COMMAND_HEAD); - - /* wrap head pointer */ - if (s->cmdbuf_head >=3D s->cmdbuf_len * AMDVI_COMMAND_SIZE) { - s->cmdbuf_head =3D 0; - } - } -} - -static void amdvi_mmio_trace(hwaddr addr, unsigned size) -{ - uint8_t index =3D (addr & ~0x2000) / 8; - - if ((addr & 0x2000)) { - /* high table */ - index =3D index >=3D AMDVI_MMIO_REGS_HIGH ? AMDVI_MMIO_REGS_HIGH := index; - trace_amdvi_mmio_read(amdvi_mmio_high[index], addr, size, addr & ~= 0x07); - } else { - index =3D index >=3D AMDVI_MMIO_REGS_LOW ? AMDVI_MMIO_REGS_LOW : i= ndex; - trace_amdvi_mmio_read(amdvi_mmio_low[index], addr, size, addr & ~0= x07); - } -} - -static uint64_t amdvi_mmio_read(void *opaque, hwaddr addr, unsigned size) -{ - AMDVIState *s =3D opaque; - - uint64_t val =3D -1; - if (addr + size > AMDVI_MMIO_SIZE) { - trace_amdvi_mmio_read_invalid(AMDVI_MMIO_SIZE, addr, size); - return (uint64_t)-1; - } - - if (size =3D=3D 2) { - val =3D amdvi_readw(s, addr); - } else if (size =3D=3D 4) { - val =3D amdvi_readl(s, addr); - } else if (size =3D=3D 8) { - val =3D amdvi_readq(s, addr); - } - amdvi_mmio_trace(addr, size); - - return val; -} - -static void amdvi_handle_control_write(AMDVIState *s) -{ - unsigned long control =3D amdvi_readq(s, AMDVI_MMIO_CONTROL); - s->enabled =3D !!(control & AMDVI_MMIO_CONTROL_AMDVIEN); - - s->ats_enabled =3D !!(control & AMDVI_MMIO_CONTROL_HTTUNEN); - s->evtlog_enabled =3D s->enabled && !!(control & - AMDVI_MMIO_CONTROL_EVENTLOGEN); - - s->evtlog_intr =3D !!(control & AMDVI_MMIO_CONTROL_EVENTINTEN); - s->completion_wait_intr =3D !!(control & AMDVI_MMIO_CONTROL_COMWAITINT= EN); - s->cmdbuf_enabled =3D s->enabled && !!(control & - AMDVI_MMIO_CONTROL_CMDBUFLEN); - s->ga_enabled =3D !!(control & AMDVI_MMIO_CONTROL_GAEN); - - /* update the flags depending on the control register */ - if (s->cmdbuf_enabled) { - amdvi_assign_orq(s, AMDVI_MMIO_STATUS, AMDVI_MMIO_STATUS_CMDBUF_RU= N); - } else { - amdvi_assign_andq(s, AMDVI_MMIO_STATUS, ~AMDVI_MMIO_STATUS_CMDBUF_= RUN); - } - if (s->evtlog_enabled) { - amdvi_assign_orq(s, AMDVI_MMIO_STATUS, AMDVI_MMIO_STATUS_EVT_RUN); - } else { - amdvi_assign_andq(s, AMDVI_MMIO_STATUS, ~AMDVI_MMIO_STATUS_EVT_RUN= ); - } - - trace_amdvi_control_status(control); - amdvi_cmdbuf_run(s); -} - -static inline void amdvi_handle_devtab_write(AMDVIState *s) - -{ - uint64_t val =3D amdvi_readq(s, AMDVI_MMIO_DEVICE_TABLE); - s->devtab =3D (val & AMDVI_MMIO_DEVTAB_BASE_MASK); - - /* set device table length */ - s->devtab_len =3D ((val & AMDVI_MMIO_DEVTAB_SIZE_MASK) + 1 * - (AMDVI_MMIO_DEVTAB_SIZE_UNIT / - AMDVI_MMIO_DEVTAB_ENTRY_SIZE)); -} - -static inline void amdvi_handle_cmdhead_write(AMDVIState *s) -{ - s->cmdbuf_head =3D amdvi_readq(s, AMDVI_MMIO_COMMAND_HEAD) - & AMDVI_MMIO_CMDBUF_HEAD_MASK; - amdvi_cmdbuf_run(s); -} - -static inline void amdvi_handle_cmdbase_write(AMDVIState *s) -{ - s->cmdbuf =3D amdvi_readq(s, AMDVI_MMIO_COMMAND_BASE) - & AMDVI_MMIO_CMDBUF_BASE_MASK; - s->cmdbuf_len =3D 1UL << (amdvi_readq(s, AMDVI_MMIO_CMDBUF_SIZE_BYTE) - & AMDVI_MMIO_CMDBUF_SIZE_MASK); - s->cmdbuf_head =3D s->cmdbuf_tail =3D 0; -} - -static inline void amdvi_handle_cmdtail_write(AMDVIState *s) -{ - s->cmdbuf_tail =3D amdvi_readq(s, AMDVI_MMIO_COMMAND_TAIL) - & AMDVI_MMIO_CMDBUF_TAIL_MASK; - amdvi_cmdbuf_run(s); -} - -static inline void amdvi_handle_excllim_write(AMDVIState *s) -{ - uint64_t val =3D amdvi_readq(s, AMDVI_MMIO_EXCL_LIMIT); - s->excl_limit =3D (val & AMDVI_MMIO_EXCL_LIMIT_MASK) | - AMDVI_MMIO_EXCL_LIMIT_LOW; -} - -static inline void amdvi_handle_evtbase_write(AMDVIState *s) -{ - uint64_t val =3D amdvi_readq(s, AMDVI_MMIO_EVENT_BASE); - s->evtlog =3D val & AMDVI_MMIO_EVTLOG_BASE_MASK; - s->evtlog_len =3D 1UL << (amdvi_readq(s, AMDVI_MMIO_EVTLOG_SIZE_BYTE) - & AMDVI_MMIO_EVTLOG_SIZE_MASK); -} - -static inline void amdvi_handle_evttail_write(AMDVIState *s) -{ - uint64_t val =3D amdvi_readq(s, AMDVI_MMIO_EVENT_TAIL); - s->evtlog_tail =3D val & AMDVI_MMIO_EVTLOG_TAIL_MASK; -} - -static inline void amdvi_handle_evthead_write(AMDVIState *s) -{ - uint64_t val =3D amdvi_readq(s, AMDVI_MMIO_EVENT_HEAD); - s->evtlog_head =3D val & AMDVI_MMIO_EVTLOG_HEAD_MASK; -} - -static inline void amdvi_handle_pprbase_write(AMDVIState *s) -{ - uint64_t val =3D amdvi_readq(s, AMDVI_MMIO_PPR_BASE); - s->ppr_log =3D val & AMDVI_MMIO_PPRLOG_BASE_MASK; - s->pprlog_len =3D 1UL << (amdvi_readq(s, AMDVI_MMIO_PPRLOG_SIZE_BYTE) - & AMDVI_MMIO_PPRLOG_SIZE_MASK); -} - -static inline void amdvi_handle_pprhead_write(AMDVIState *s) -{ - uint64_t val =3D amdvi_readq(s, AMDVI_MMIO_PPR_HEAD); - s->pprlog_head =3D val & AMDVI_MMIO_PPRLOG_HEAD_MASK; -} - -static inline void amdvi_handle_pprtail_write(AMDVIState *s) -{ - uint64_t val =3D amdvi_readq(s, AMDVI_MMIO_PPR_TAIL); - s->pprlog_tail =3D val & AMDVI_MMIO_PPRLOG_TAIL_MASK; -} - -/* FIXME: something might go wrong if System Software writes in chunks - * of one byte but linux writes in chunks of 4 bytes so currently it - * works correctly with linux but will definitely be busted if software - * reads/writes 8 bytes - */ -static void amdvi_mmio_reg_write(AMDVIState *s, unsigned size, uint64_t va= l, - hwaddr addr) -{ - if (size =3D=3D 2) { - amdvi_writew(s, addr, val); - } else if (size =3D=3D 4) { - amdvi_writel(s, addr, val); - } else if (size =3D=3D 8) { - amdvi_writeq(s, addr, val); - } -} - -static void amdvi_mmio_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - AMDVIState *s =3D opaque; - unsigned long offset =3D addr & 0x07; - - if (addr + size > AMDVI_MMIO_SIZE) { - trace_amdvi_mmio_write("error: addr outside region: max ", - (uint64_t)AMDVI_MMIO_SIZE, size, val, offset); - return; - } - - amdvi_mmio_trace(addr, size); - switch (addr & ~0x07) { - case AMDVI_MMIO_CONTROL: - amdvi_mmio_reg_write(s, size, val, addr); - amdvi_handle_control_write(s); - break; - case AMDVI_MMIO_DEVICE_TABLE: - amdvi_mmio_reg_write(s, size, val, addr); - /* set device table address - * This also suffers from inability to tell whether software - * is done writing - */ - if (offset || (size =3D=3D 8)) { - amdvi_handle_devtab_write(s); - } - break; - case AMDVI_MMIO_COMMAND_HEAD: - amdvi_mmio_reg_write(s, size, val, addr); - amdvi_handle_cmdhead_write(s); - break; - case AMDVI_MMIO_COMMAND_BASE: - amdvi_mmio_reg_write(s, size, val, addr); - /* FIXME - make sure System Software has finished writing incase - * it writes in chucks less than 8 bytes in a robust way.As for - * now, this hacks works for the linux driver - */ - if (offset || (size =3D=3D 8)) { - amdvi_handle_cmdbase_write(s); - } - break; - case AMDVI_MMIO_COMMAND_TAIL: - amdvi_mmio_reg_write(s, size, val, addr); - amdvi_handle_cmdtail_write(s); - break; - case AMDVI_MMIO_EVENT_BASE: - amdvi_mmio_reg_write(s, size, val, addr); - amdvi_handle_evtbase_write(s); - break; - case AMDVI_MMIO_EVENT_HEAD: - amdvi_mmio_reg_write(s, size, val, addr); - amdvi_handle_evthead_write(s); - break; - case AMDVI_MMIO_EVENT_TAIL: - amdvi_mmio_reg_write(s, size, val, addr); - amdvi_handle_evttail_write(s); - break; - case AMDVI_MMIO_EXCL_LIMIT: - amdvi_mmio_reg_write(s, size, val, addr); - amdvi_handle_excllim_write(s); - break; - /* PPR log base - unused for now */ - case AMDVI_MMIO_PPR_BASE: - amdvi_mmio_reg_write(s, size, val, addr); - amdvi_handle_pprbase_write(s); - break; - /* PPR log head - also unused for now */ - case AMDVI_MMIO_PPR_HEAD: - amdvi_mmio_reg_write(s, size, val, addr); - amdvi_handle_pprhead_write(s); - break; - /* PPR log tail - unused for now */ - case AMDVI_MMIO_PPR_TAIL: - amdvi_mmio_reg_write(s, size, val, addr); - amdvi_handle_pprtail_write(s); - break; - } -} - -static inline uint64_t amdvi_get_perms(uint64_t entry) -{ - return (entry & (AMDVI_DEV_PERM_READ | AMDVI_DEV_PERM_WRITE)) >> - AMDVI_DEV_PERM_SHIFT; -} - -/* validate that reserved bits are honoured */ -static bool amdvi_validate_dte(AMDVIState *s, uint16_t devid, - uint64_t *dte) -{ - if ((dte[0] & AMDVI_DTE_LOWER_QUAD_RESERVED) - || (dte[1] & AMDVI_DTE_MIDDLE_QUAD_RESERVED) - || (dte[2] & AMDVI_DTE_UPPER_QUAD_RESERVED) || dte[3]) { - amdvi_log_illegaldevtab_error(s, devid, - s->devtab + - devid * AMDVI_DEVTAB_ENTRY_SIZE, 0); - return false; - } - - return true; -} - -/* get a device table entry given the devid */ -static bool amdvi_get_dte(AMDVIState *s, int devid, uint64_t *entry) -{ - uint32_t offset =3D devid * AMDVI_DEVTAB_ENTRY_SIZE; - - if (dma_memory_read(&address_space_memory, s->devtab + offset, entry, - AMDVI_DEVTAB_ENTRY_SIZE)) { - trace_amdvi_dte_get_fail(s->devtab, offset); - /* log error accessing dte */ - amdvi_log_devtab_error(s, devid, s->devtab + offset, 0); - return false; - } - - *entry =3D le64_to_cpu(*entry); - if (!amdvi_validate_dte(s, devid, entry)) { - trace_amdvi_invalid_dte(entry[0]); - return false; - } - - return true; -} - -/* get pte translation mode */ -static inline uint8_t get_pte_translation_mode(uint64_t pte) -{ - return (pte >> AMDVI_DEV_MODE_RSHIFT) & AMDVI_DEV_MODE_MASK; -} - -static inline uint64_t pte_override_page_mask(uint64_t pte) -{ - uint8_t page_mask =3D 12; - uint64_t addr =3D (pte & AMDVI_DEV_PT_ROOT_MASK) ^ AMDVI_DEV_PT_ROOT_M= ASK; - /* find the first zero bit */ - while (addr & 1) { - page_mask++; - addr =3D addr >> 1; - } - - return ~((1ULL << page_mask) - 1); -} - -static inline uint64_t pte_get_page_mask(uint64_t oldlevel) -{ - return ~((1UL << ((oldlevel * 9) + 3)) - 1); -} - -static inline uint64_t amdvi_get_pte_entry(AMDVIState *s, uint64_t pte_add= r, - uint16_t devid) -{ - uint64_t pte; - - if (dma_memory_read(&address_space_memory, pte_addr, &pte, sizeof(pte)= )) { - trace_amdvi_get_pte_hwerror(pte_addr); - amdvi_log_pagetab_error(s, devid, pte_addr, 0); - pte =3D 0; - return pte; - } - - pte =3D le64_to_cpu(pte); - return pte; -} - -static void amdvi_page_walk(AMDVIAddressSpace *as, uint64_t *dte, - IOMMUTLBEntry *ret, unsigned perms, - hwaddr addr) -{ - unsigned level, present, pte_perms, oldlevel; - uint64_t pte =3D dte[0], pte_addr, page_mask; - - /* make sure the DTE has TV =3D 1 */ - if (pte & AMDVI_DEV_TRANSLATION_VALID) { - level =3D get_pte_translation_mode(pte); - if (level >=3D 7) { - trace_amdvi_mode_invalid(level, addr); - return; - } - if (level =3D=3D 0) { - goto no_remap; - } - - /* we are at the leaf page table or page table encodes a huge page= */ - while (level > 0) { - pte_perms =3D amdvi_get_perms(pte); - present =3D pte & 1; - if (!present || perms !=3D (perms & pte_perms)) { - amdvi_page_fault(as->iommu_state, as->devfn, addr, perms); - trace_amdvi_page_fault(addr); - return; - } - - /* go to the next lower level */ - pte_addr =3D pte & AMDVI_DEV_PT_ROOT_MASK; - /* add offset and load pte */ - pte_addr +=3D ((addr >> (3 + 9 * level)) & 0x1FF) << 3; - pte =3D amdvi_get_pte_entry(as->iommu_state, pte_addr, as->dev= fn); - if (!pte) { - return; - } - oldlevel =3D level; - level =3D get_pte_translation_mode(pte); - if (level =3D=3D 0x7) { - break; - } - } - - if (level =3D=3D 0x7) { - page_mask =3D pte_override_page_mask(pte); - } else { - page_mask =3D pte_get_page_mask(oldlevel); - } - - /* get access permissions from pte */ - ret->iova =3D addr & page_mask; - ret->translated_addr =3D (pte & AMDVI_DEV_PT_ROOT_MASK) & page_mas= k; - ret->addr_mask =3D ~page_mask; - ret->perm =3D amdvi_get_perms(pte); - return; - } -no_remap: - ret->iova =3D addr & AMDVI_PAGE_MASK_4K; - ret->translated_addr =3D addr & AMDVI_PAGE_MASK_4K; - ret->addr_mask =3D ~AMDVI_PAGE_MASK_4K; - ret->perm =3D amdvi_get_perms(pte); -} - -static void amdvi_do_translate(AMDVIAddressSpace *as, hwaddr addr, - bool is_write, IOMMUTLBEntry *ret) -{ - AMDVIState *s =3D as->iommu_state; - uint16_t devid =3D PCI_BUILD_BDF(as->bus_num, as->devfn); - AMDVIIOTLBEntry *iotlb_entry =3D amdvi_iotlb_lookup(s, addr, devid); - uint64_t entry[4]; - - if (iotlb_entry) { - trace_amdvi_iotlb_hit(PCI_BUS_NUM(devid), PCI_SLOT(devid), - PCI_FUNC(devid), addr, iotlb_entry->translated_addr); - ret->iova =3D addr & ~iotlb_entry->page_mask; - ret->translated_addr =3D iotlb_entry->translated_addr; - ret->addr_mask =3D iotlb_entry->page_mask; - ret->perm =3D iotlb_entry->perms; - return; - } - - if (!amdvi_get_dte(s, devid, entry)) { - return; - } - - /* devices with V =3D 0 are not translated */ - if (!(entry[0] & AMDVI_DEV_VALID)) { - goto out; - } - - amdvi_page_walk(as, entry, ret, - is_write ? AMDVI_PERM_WRITE : AMDVI_PERM_READ, addr); - - amdvi_update_iotlb(s, devid, addr, *ret, - entry[1] & AMDVI_DEV_DOMID_ID_MASK); - return; - -out: - ret->iova =3D addr & AMDVI_PAGE_MASK_4K; - ret->translated_addr =3D addr & AMDVI_PAGE_MASK_4K; - ret->addr_mask =3D ~AMDVI_PAGE_MASK_4K; - ret->perm =3D IOMMU_RW; -} - -static inline bool amdvi_is_interrupt_addr(hwaddr addr) -{ - return addr >=3D AMDVI_INT_ADDR_FIRST && addr <=3D AMDVI_INT_ADDR_LAST; -} - -static IOMMUTLBEntry amdvi_translate(IOMMUMemoryRegion *iommu, hwaddr addr, - IOMMUAccessFlags flag, int iommu_idx) -{ - AMDVIAddressSpace *as =3D container_of(iommu, AMDVIAddressSpace, iommu= ); - AMDVIState *s =3D as->iommu_state; - IOMMUTLBEntry ret =3D { - .target_as =3D &address_space_memory, - .iova =3D addr, - .translated_addr =3D 0, - .addr_mask =3D ~(hwaddr)0, - .perm =3D IOMMU_NONE - }; - - if (!s->enabled) { - /* AMDVI disabled - corresponds to iommu=3Doff not - * failure to provide any parameter - */ - ret.iova =3D addr & AMDVI_PAGE_MASK_4K; - ret.translated_addr =3D addr & AMDVI_PAGE_MASK_4K; - ret.addr_mask =3D ~AMDVI_PAGE_MASK_4K; - ret.perm =3D IOMMU_RW; - return ret; - } else if (amdvi_is_interrupt_addr(addr)) { - ret.iova =3D addr & AMDVI_PAGE_MASK_4K; - ret.translated_addr =3D addr & AMDVI_PAGE_MASK_4K; - ret.addr_mask =3D ~AMDVI_PAGE_MASK_4K; - ret.perm =3D IOMMU_WO; - return ret; - } - - amdvi_do_translate(as, addr, flag & IOMMU_WO, &ret); - trace_amdvi_translation_result(as->bus_num, PCI_SLOT(as->devfn), - PCI_FUNC(as->devfn), addr, ret.translated_addr); - return ret; -} - -static int amdvi_get_irte(AMDVIState *s, MSIMessage *origin, uint64_t *dte, - union irte *irte, uint16_t devid) -{ - uint64_t irte_root, offset; - - irte_root =3D dte[2] & AMDVI_IR_PHYS_ADDR_MASK; - offset =3D (origin->data & AMDVI_IRTE_OFFSET) << 2; - - trace_amdvi_ir_irte(irte_root, offset); - - if (dma_memory_read(&address_space_memory, irte_root + offset, - irte, sizeof(*irte))) { - trace_amdvi_ir_err("failed to get irte"); - return -AMDVI_IR_GET_IRTE; - } - - trace_amdvi_ir_irte_val(irte->val); - - return 0; -} - -static int amdvi_int_remap_legacy(AMDVIState *iommu, - MSIMessage *origin, - MSIMessage *translated, - uint64_t *dte, - X86IOMMUIrq *irq, - uint16_t sid) -{ - int ret; - union irte irte; - - /* get interrupt remapping table */ - ret =3D amdvi_get_irte(iommu, origin, dte, &irte, sid); - if (ret < 0) { - return ret; - } - - if (!irte.fields.valid) { - trace_amdvi_ir_target_abort("RemapEn is disabled"); - return -AMDVI_IR_TARGET_ABORT; - } - - if (irte.fields.guest_mode) { - error_report_once("guest mode is not zero"); - return -AMDVI_IR_ERR; - } - - if (irte.fields.int_type > AMDVI_IOAPIC_INT_TYPE_ARBITRATED) { - error_report_once("reserved int_type"); - return -AMDVI_IR_ERR; - } - - irq->delivery_mode =3D irte.fields.int_type; - irq->vector =3D irte.fields.vector; - irq->dest_mode =3D irte.fields.dm; - irq->redir_hint =3D irte.fields.rq_eoi; - irq->dest =3D irte.fields.destination; - - return 0; -} - -static int amdvi_get_irte_ga(AMDVIState *s, MSIMessage *origin, uint64_t *= dte, - struct irte_ga *irte, uint16_t devid) -{ - uint64_t irte_root, offset; - - irte_root =3D dte[2] & AMDVI_IR_PHYS_ADDR_MASK; - offset =3D (origin->data & AMDVI_IRTE_OFFSET) << 4; - trace_amdvi_ir_irte(irte_root, offset); - - if (dma_memory_read(&address_space_memory, irte_root + offset, - irte, sizeof(*irte))) { - trace_amdvi_ir_err("failed to get irte_ga"); - return -AMDVI_IR_GET_IRTE; - } - - trace_amdvi_ir_irte_ga_val(irte->hi.val, irte->lo.val); - return 0; -} - -static int amdvi_int_remap_ga(AMDVIState *iommu, - MSIMessage *origin, - MSIMessage *translated, - uint64_t *dte, - X86IOMMUIrq *irq, - uint16_t sid) -{ - int ret; - struct irte_ga irte; - - /* get interrupt remapping table */ - ret =3D amdvi_get_irte_ga(iommu, origin, dte, &irte, sid); - if (ret < 0) { - return ret; - } - - if (!irte.lo.fields_remap.valid) { - trace_amdvi_ir_target_abort("RemapEn is disabled"); - return -AMDVI_IR_TARGET_ABORT; - } - - if (irte.lo.fields_remap.guest_mode) { - error_report_once("guest mode is not zero"); - return -AMDVI_IR_ERR; - } - - if (irte.lo.fields_remap.int_type > AMDVI_IOAPIC_INT_TYPE_ARBITRATED) { - error_report_once("reserved int_type is set"); - return -AMDVI_IR_ERR; - } - - irq->delivery_mode =3D irte.lo.fields_remap.int_type; - irq->vector =3D irte.hi.fields.vector; - irq->dest_mode =3D irte.lo.fields_remap.dm; - irq->redir_hint =3D irte.lo.fields_remap.rq_eoi; - irq->dest =3D irte.lo.fields_remap.destination; - - return 0; -} - -static int __amdvi_int_remap_msi(AMDVIState *iommu, - MSIMessage *origin, - MSIMessage *translated, - uint64_t *dte, - X86IOMMUIrq *irq, - uint16_t sid) -{ - int ret; - uint8_t int_ctl; - - int_ctl =3D (dte[2] >> AMDVI_IR_INTCTL_SHIFT) & 3; - trace_amdvi_ir_intctl(int_ctl); - - switch (int_ctl) { - case AMDVI_IR_INTCTL_PASS: - memcpy(translated, origin, sizeof(*origin)); - return 0; - case AMDVI_IR_INTCTL_REMAP: - break; - case AMDVI_IR_INTCTL_ABORT: - trace_amdvi_ir_target_abort("int_ctl abort"); - return -AMDVI_IR_TARGET_ABORT; - default: - trace_amdvi_ir_err("int_ctl reserved"); - return -AMDVI_IR_ERR; - } - - if (iommu->ga_enabled) { - ret =3D amdvi_int_remap_ga(iommu, origin, translated, dte, irq, si= d); - } else { - ret =3D amdvi_int_remap_legacy(iommu, origin, translated, dte, irq= , sid); - } - - return ret; -} - -/* Interrupt remapping for MSI/MSI-X entry */ -static int amdvi_int_remap_msi(AMDVIState *iommu, - MSIMessage *origin, - MSIMessage *translated, - uint16_t sid) -{ - int ret =3D 0; - uint64_t pass =3D 0; - uint64_t dte[4] =3D { 0 }; - X86IOMMUIrq irq =3D { 0 }; - uint8_t dest_mode, delivery_mode; - - assert(origin && translated); - - /* - * When IOMMU is enabled, interrupt remap request will come either from - * IO-APIC or PCI device. If interrupt is from PCI device then it will - * have a valid requester id but if the interrupt is from IO-APIC - * then requester id will be invalid. - */ - if (sid =3D=3D X86_IOMMU_SID_INVALID) { - sid =3D AMDVI_IOAPIC_SB_DEVID; - } - - trace_amdvi_ir_remap_msi_req(origin->address, origin->data, sid); - - /* check if device table entry is set before we go further. */ - if (!iommu || !iommu->devtab_len) { - memcpy(translated, origin, sizeof(*origin)); - goto out; - } - - if (!amdvi_get_dte(iommu, sid, dte)) { - return -AMDVI_IR_ERR; - } - - /* Check if IR is enabled in DTE */ - if (!(dte[2] & AMDVI_IR_REMAP_ENABLE)) { - memcpy(translated, origin, sizeof(*origin)); - goto out; - } - - /* validate that we are configure with intremap=3Don */ - if (!x86_iommu_ir_supported(X86_IOMMU_DEVICE(iommu))) { - trace_amdvi_err("Interrupt remapping is enabled in the guest but " - "not in the host. Use intremap=3Don to enable inte= rrupt " - "remapping in amd-iommu."); - return -AMDVI_IR_ERR; - } - - if (origin->address & AMDVI_MSI_ADDR_HI_MASK) { - trace_amdvi_err("MSI address high 32 bits non-zero when " - "Interrupt Remapping enabled."); - return -AMDVI_IR_ERR; - } - - if ((origin->address & AMDVI_MSI_ADDR_LO_MASK) !=3D APIC_DEFAULT_ADDRE= SS) { - trace_amdvi_err("MSI is not from IOAPIC."); - return -AMDVI_IR_ERR; - } - - /* - * The MSI data register [10:8] are used to get the upstream interrupt= type. - * - * See MSI/MSI-X format: - * https://pdfs.semanticscholar.org/presentation/9420/c279e942eca56815= 7711ef5c92b800c40a79.pdf - * (page 5) - */ - delivery_mode =3D (origin->data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 7; - - switch (delivery_mode) { - case AMDVI_IOAPIC_INT_TYPE_FIXED: - case AMDVI_IOAPIC_INT_TYPE_ARBITRATED: - trace_amdvi_ir_delivery_mode("fixed/arbitrated"); - ret =3D __amdvi_int_remap_msi(iommu, origin, translated, dte, &irq= , sid); - if (ret < 0) { - goto remap_fail; - } else { - /* Translate IRQ to MSI messages */ - x86_iommu_irq_to_msi_message(&irq, translated); - goto out; - } - break; - case AMDVI_IOAPIC_INT_TYPE_SMI: - error_report("SMI is not supported!"); - ret =3D -AMDVI_IR_ERR; - break; - case AMDVI_IOAPIC_INT_TYPE_NMI: - pass =3D dte[3] & AMDVI_DEV_NMI_PASS_MASK; - trace_amdvi_ir_delivery_mode("nmi"); - break; - case AMDVI_IOAPIC_INT_TYPE_INIT: - pass =3D dte[3] & AMDVI_DEV_INT_PASS_MASK; - trace_amdvi_ir_delivery_mode("init"); - break; - case AMDVI_IOAPIC_INT_TYPE_EINT: - pass =3D dte[3] & AMDVI_DEV_EINT_PASS_MASK; - trace_amdvi_ir_delivery_mode("eint"); - break; - default: - trace_amdvi_ir_delivery_mode("unsupported delivery_mode"); - ret =3D -AMDVI_IR_ERR; - break; - } - - if (ret < 0) { - goto remap_fail; - } - - /* - * The MSI address register bit[2] is used to get the destination - * mode. The dest_mode 1 is valid for fixed and arbitrated interrupts - * only. - */ - dest_mode =3D (origin->address >> MSI_ADDR_DEST_MODE_SHIFT) & 1; - if (dest_mode) { - trace_amdvi_ir_err("invalid dest_mode"); - ret =3D -AMDVI_IR_ERR; - goto remap_fail; - } - - if (pass) { - memcpy(translated, origin, sizeof(*origin)); - } else { - trace_amdvi_ir_err("passthrough is not enabled"); - ret =3D -AMDVI_IR_ERR; - goto remap_fail; - } - -out: - trace_amdvi_ir_remap_msi(origin->address, origin->data, - translated->address, translated->data); - return 0; - -remap_fail: - return ret; -} - -static int amdvi_int_remap(X86IOMMUState *iommu, - MSIMessage *origin, - MSIMessage *translated, - uint16_t sid) -{ - return amdvi_int_remap_msi(AMD_IOMMU_DEVICE(iommu), origin, - translated, sid); -} - -static MemTxResult amdvi_mem_ir_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size, - MemTxAttrs attrs) -{ - int ret; - MSIMessage from =3D { 0, 0 }, to =3D { 0, 0 }; - uint16_t sid =3D AMDVI_IOAPIC_SB_DEVID; - - from.address =3D (uint64_t) addr + AMDVI_INT_ADDR_FIRST; - from.data =3D (uint32_t) value; - - trace_amdvi_mem_ir_write_req(addr, value, size); - - if (!attrs.unspecified) { - /* We have explicit Source ID */ - sid =3D attrs.requester_id; - } - - ret =3D amdvi_int_remap_msi(opaque, &from, &to, sid); - if (ret < 0) { - /* TODO: log the event using IOMMU log event interface */ - error_report_once("failed to remap interrupt from devid 0x%x", sid= ); - return MEMTX_ERROR; - } - - apic_get_class()->send_msi(&to); - - trace_amdvi_mem_ir_write(to.address, to.data); - return MEMTX_OK; -} - -static MemTxResult amdvi_mem_ir_read(void *opaque, hwaddr addr, - uint64_t *data, unsigned size, - MemTxAttrs attrs) -{ - return MEMTX_OK; -} - -static const MemoryRegionOps amdvi_ir_ops =3D { - .read_with_attrs =3D amdvi_mem_ir_read, - .write_with_attrs =3D amdvi_mem_ir_write, - .endianness =3D DEVICE_LITTLE_ENDIAN, - .impl =3D { - .min_access_size =3D 4, - .max_access_size =3D 4, - }, - .valid =3D { - .min_access_size =3D 4, - .max_access_size =3D 4, - } -}; - -static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int d= evfn) -{ - char name[128]; - AMDVIState *s =3D opaque; - AMDVIAddressSpace **iommu_as, *amdvi_dev_as; - int bus_num =3D pci_bus_num(bus); - - iommu_as =3D s->address_spaces[bus_num]; - - /* allocate memory during the first run */ - if (!iommu_as) { - iommu_as =3D g_malloc0(sizeof(AMDVIAddressSpace *) * PCI_DEVFN_MAX= ); - s->address_spaces[bus_num] =3D iommu_as; - } - - /* set up AMD-Vi region */ - if (!iommu_as[devfn]) { - snprintf(name, sizeof(name), "amd_iommu_devfn_%d", devfn); - - iommu_as[devfn] =3D g_malloc0(sizeof(AMDVIAddressSpace)); - iommu_as[devfn]->bus_num =3D (uint8_t)bus_num; - iommu_as[devfn]->devfn =3D (uint8_t)devfn; - iommu_as[devfn]->iommu_state =3D s; - - amdvi_dev_as =3D iommu_as[devfn]; - - /* - * Memory region relationships looks like (Address range shows - * only lower 32 bits to make it short in length...): - * - * |-----------------+-------------------+----------| - * | Name | Address range | Priority | - * |-----------------+-------------------+----------+ - * | amdvi_root | 00000000-ffffffff | 0 | - * | amdvi_iommu | 00000000-ffffffff | 1 | - * | amdvi_iommu_ir | fee00000-feefffff | 64 | - * |-----------------+-------------------+----------| - */ - memory_region_init_iommu(&amdvi_dev_as->iommu, - sizeof(amdvi_dev_as->iommu), - TYPE_AMD_IOMMU_MEMORY_REGION, - OBJECT(s), - "amd_iommu", UINT64_MAX); - memory_region_init(&amdvi_dev_as->root, OBJECT(s), - "amdvi_root", UINT64_MAX); - address_space_init(&amdvi_dev_as->as, &amdvi_dev_as->root, name); - memory_region_init_io(&amdvi_dev_as->iommu_ir, OBJECT(s), - &amdvi_ir_ops, s, "amd_iommu_ir", - AMDVI_INT_ADDR_SIZE); - memory_region_add_subregion_overlap(&amdvi_dev_as->root, - AMDVI_INT_ADDR_FIRST, - &amdvi_dev_as->iommu_ir, - 64); - memory_region_add_subregion_overlap(&amdvi_dev_as->root, 0, - MEMORY_REGION(&amdvi_dev_as->i= ommu), - 1); - } - return &iommu_as[devfn]->as; -} - -static const MemoryRegionOps mmio_mem_ops =3D { - .read =3D amdvi_mmio_read, - .write =3D amdvi_mmio_write, - .endianness =3D DEVICE_LITTLE_ENDIAN, - .impl =3D { - .min_access_size =3D 1, - .max_access_size =3D 8, - .unaligned =3D false, - }, - .valid =3D { - .min_access_size =3D 1, - .max_access_size =3D 8, - } -}; - -static void amdvi_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, - IOMMUNotifierFlag old, - IOMMUNotifierFlag new) -{ - AMDVIAddressSpace *as =3D container_of(iommu, AMDVIAddressSpace, iommu= ); - - if (new & IOMMU_NOTIFIER_MAP) { - error_report("device %02x.%02x.%x requires iommu notifier which is= not " - "currently supported", as->bus_num, PCI_SLOT(as->devf= n), - PCI_FUNC(as->devfn)); - exit(1); - } -} - -static void amdvi_init(AMDVIState *s) -{ - amdvi_iotlb_reset(s); - - s->devtab_len =3D 0; - s->cmdbuf_len =3D 0; - s->cmdbuf_head =3D 0; - s->cmdbuf_tail =3D 0; - s->evtlog_head =3D 0; - s->evtlog_tail =3D 0; - s->excl_enabled =3D false; - s->excl_allow =3D false; - s->mmio_enabled =3D false; - s->enabled =3D false; - s->ats_enabled =3D false; - s->cmdbuf_enabled =3D false; - - /* reset MMIO */ - memset(s->mmior, 0, AMDVI_MMIO_SIZE); - amdvi_set_quad(s, AMDVI_MMIO_EXT_FEATURES, AMDVI_EXT_FEATURES, - 0xffffffffffffffef, 0); - amdvi_set_quad(s, AMDVI_MMIO_STATUS, 0, 0x98, 0x67); - - /* reset device ident */ - pci_config_set_vendor_id(s->pci.dev.config, PCI_VENDOR_ID_AMD); - pci_config_set_prog_interface(s->pci.dev.config, 00); - pci_config_set_device_id(s->pci.dev.config, s->devid); - pci_config_set_class(s->pci.dev.config, 0x0806); - - /* reset AMDVI specific capabilities, all r/o */ - pci_set_long(s->pci.dev.config + s->capab_offset, AMDVI_CAPAB_FEATURES= ); - pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_BAR_LOW, - s->mmio.addr & ~(0xffff0000)); - pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_BAR_HIG= H, - (s->mmio.addr & ~(0xffff)) >> 16); - pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_RANGE, - 0xff000000); - pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_MISC, 0= ); - pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_MISC, - AMDVI_MAX_PH_ADDR | AMDVI_MAX_GVA_ADDR | AMDVI_MAX_VA_ADDR); -} - -static void amdvi_reset(DeviceState *dev) -{ - AMDVIState *s =3D AMD_IOMMU_DEVICE(dev); - - msi_reset(&s->pci.dev); - amdvi_init(s); -} - -static void amdvi_realize(DeviceState *dev, Error **err) -{ - int ret =3D 0; - AMDVIState *s =3D AMD_IOMMU_DEVICE(dev); - X86IOMMUState *x86_iommu =3D X86_IOMMU_DEVICE(dev); - MachineState *ms =3D MACHINE(qdev_get_machine()); - PCMachineState *pcms =3D PC_MACHINE(ms); - PCIBus *bus =3D pcms->bus; - - s->iotlb =3D g_hash_table_new_full(amdvi_uint64_hash, - amdvi_uint64_equal, g_free, g_free); - - /* This device should take care of IOMMU PCI properties */ - x86_iommu->type =3D TYPE_AMD; - qdev_set_parent_bus(DEVICE(&s->pci), &bus->qbus); - object_property_set_bool(OBJECT(&s->pci), true, "realized", err); - ret =3D pci_add_capability(&s->pci.dev, AMDVI_CAPAB_ID_SEC, 0, - AMDVI_CAPAB_SIZE, err); - if (ret < 0) { - return; - } - s->capab_offset =3D ret; - - ret =3D pci_add_capability(&s->pci.dev, PCI_CAP_ID_MSI, 0, - AMDVI_CAPAB_REG_SIZE, err); - if (ret < 0) { - return; - } - ret =3D pci_add_capability(&s->pci.dev, PCI_CAP_ID_HT, 0, - AMDVI_CAPAB_REG_SIZE, err); - if (ret < 0) { - return; - } - - /* Pseudo address space under root PCI bus. */ - pcms->ioapic_as =3D amdvi_host_dma_iommu(bus, s, AMDVI_IOAPIC_SB_DEVID= ); - - /* set up MMIO */ - memory_region_init_io(&s->mmio, OBJECT(s), &mmio_mem_ops, s, "amdvi-mm= io", - AMDVI_MMIO_SIZE); - - sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); - sysbus_mmio_map(SYS_BUS_DEVICE(s), 0, AMDVI_BASE_ADDR); - pci_setup_iommu(bus, amdvi_host_dma_iommu, s); - s->devid =3D object_property_get_int(OBJECT(&s->pci), "addr", err); - msi_init(&s->pci.dev, 0, 1, true, false, err); - amdvi_init(s); -} - -static const VMStateDescription vmstate_amdvi =3D { - .name =3D "amd-iommu", - .unmigratable =3D 1 -}; - -static void amdvi_instance_init(Object *klass) -{ - AMDVIState *s =3D AMD_IOMMU_DEVICE(klass); - - object_initialize(&s->pci, sizeof(s->pci), TYPE_AMD_IOMMU_PCI); -} - -static void amdvi_class_init(ObjectClass *klass, void* data) -{ - DeviceClass *dc =3D DEVICE_CLASS(klass); - X86IOMMUClass *dc_class =3D X86_IOMMU_CLASS(klass); - - dc->reset =3D amdvi_reset; - dc->vmsd =3D &vmstate_amdvi; - dc->hotpluggable =3D false; - dc_class->realize =3D amdvi_realize; - dc_class->int_remap =3D amdvi_int_remap; - /* Supported by the pc-q35-* machine types */ - dc->user_creatable =3D true; -} - -static const TypeInfo amdvi =3D { - .name =3D TYPE_AMD_IOMMU_DEVICE, - .parent =3D TYPE_X86_IOMMU_DEVICE, - .instance_size =3D sizeof(AMDVIState), - .instance_init =3D amdvi_instance_init, - .class_init =3D amdvi_class_init -}; - -static const TypeInfo amdviPCI =3D { - .name =3D "AMDVI-PCI", - .parent =3D TYPE_PCI_DEVICE, - .instance_size =3D sizeof(AMDVIPCIState), - .interfaces =3D (InterfaceInfo[]) { - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { }, - }, -}; - -static void amdvi_iommu_memory_region_class_init(ObjectClass *klass, void = *data) -{ - IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); - - imrc->translate =3D amdvi_translate; - imrc->notify_flag_changed =3D amdvi_iommu_notify_flag_changed; -} - -static const TypeInfo amdvi_iommu_memory_region_info =3D { - .parent =3D TYPE_IOMMU_MEMORY_REGION, - .name =3D TYPE_AMD_IOMMU_MEMORY_REGION, - .class_init =3D amdvi_iommu_memory_region_class_init, -}; - -static void amdviPCI_register_types(void) -{ - type_register_static(&amdviPCI); - type_register_static(&amdvi); - type_register_static(&amdvi_iommu_memory_region_info); -} - -type_init(amdviPCI_register_types); diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h deleted file mode 100644 index c52886f..0000000 --- a/hw/i386/amd_iommu.h +++ /dev/null @@ -1,373 +0,0 @@ -/* - * QEMU emulation of an AMD IOMMU (AMD-Vi) - * - * Copyright (C) 2011 Eduard - Gabriel Munteanu - * Copyright (C) 2015 David Kiarie, - * - * 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 . - */ - -#ifndef AMD_IOMMU_H_ -#define AMD_IOMMU_H_ - -#include "hw/hw.h" -#include "hw/pci/pci.h" -#include "hw/i386/x86-iommu.h" - -/* Capability registers */ -#define AMDVI_CAPAB_BAR_LOW 0x04 -#define AMDVI_CAPAB_BAR_HIGH 0x08 -#define AMDVI_CAPAB_RANGE 0x0C -#define AMDVI_CAPAB_MISC 0x10 - -#define AMDVI_CAPAB_SIZE 0x18 -#define AMDVI_CAPAB_REG_SIZE 0x04 - -/* Capability header data */ -#define AMDVI_CAPAB_ID_SEC 0xf -#define AMDVI_CAPAB_FLAT_EXT (1 << 28) -#define AMDVI_CAPAB_EFR_SUP (1 << 27) -#define AMDVI_CAPAB_FLAG_NPCACHE (1 << 26) -#define AMDVI_CAPAB_FLAG_HTTUNNEL (1 << 25) -#define AMDVI_CAPAB_FLAG_IOTLBSUP (1 << 24) -#define AMDVI_CAPAB_INIT_TYPE (3 << 16) - -/* No. of used MMIO registers */ -#define AMDVI_MMIO_REGS_HIGH 7 -#define AMDVI_MMIO_REGS_LOW 8 - -/* MMIO registers */ -#define AMDVI_MMIO_DEVICE_TABLE 0x0000 -#define AMDVI_MMIO_COMMAND_BASE 0x0008 -#define AMDVI_MMIO_EVENT_BASE 0x0010 -#define AMDVI_MMIO_CONTROL 0x0018 -#define AMDVI_MMIO_EXCL_BASE 0x0020 -#define AMDVI_MMIO_EXCL_LIMIT 0x0028 -#define AMDVI_MMIO_EXT_FEATURES 0x0030 -#define AMDVI_MMIO_COMMAND_HEAD 0x2000 -#define AMDVI_MMIO_COMMAND_TAIL 0x2008 -#define AMDVI_MMIO_EVENT_HEAD 0x2010 -#define AMDVI_MMIO_EVENT_TAIL 0x2018 -#define AMDVI_MMIO_STATUS 0x2020 -#define AMDVI_MMIO_PPR_BASE 0x0038 -#define AMDVI_MMIO_PPR_HEAD 0x2030 -#define AMDVI_MMIO_PPR_TAIL 0x2038 - -#define AMDVI_MMIO_SIZE 0x4000 - -#define AMDVI_MMIO_DEVTAB_SIZE_MASK ((1ULL << 12) - 1) -#define AMDVI_MMIO_DEVTAB_BASE_MASK (((1ULL << 52) - 1) & ~ \ - AMDVI_MMIO_DEVTAB_SIZE_MASK) -#define AMDVI_MMIO_DEVTAB_ENTRY_SIZE 32 -#define AMDVI_MMIO_DEVTAB_SIZE_UNIT 4096 - -/* some of this are similar but just for readability */ -#define AMDVI_MMIO_CMDBUF_SIZE_BYTE (AMDVI_MMIO_COMMAND_BASE + 7) -#define AMDVI_MMIO_CMDBUF_SIZE_MASK 0x0f -#define AMDVI_MMIO_CMDBUF_BASE_MASK AMDVI_MMIO_DEVTAB_BASE_MASK -#define AMDVI_MMIO_CMDBUF_HEAD_MASK (((1ULL << 19) - 1) & ~0x0f) -#define AMDVI_MMIO_CMDBUF_TAIL_MASK AMDVI_MMIO_EVTLOG_HEAD_MASK - -#define AMDVI_MMIO_EVTLOG_SIZE_BYTE (AMDVI_MMIO_EVENT_BASE + 7) -#define AMDVI_MMIO_EVTLOG_SIZE_MASK AMDVI_MMIO_CMDBUF_SIZE_MASK -#define AMDVI_MMIO_EVTLOG_BASE_MASK AMDVI_MMIO_CMDBUF_BASE_MASK -#define AMDVI_MMIO_EVTLOG_HEAD_MASK (((1ULL << 19) - 1) & ~0x0f) -#define AMDVI_MMIO_EVTLOG_TAIL_MASK AMDVI_MMIO_EVTLOG_HEAD_MASK - -#define AMDVI_MMIO_PPRLOG_SIZE_BYTE (AMDVI_MMIO_EVENT_BASE + 7) -#define AMDVI_MMIO_PPRLOG_HEAD_MASK AMDVI_MMIO_EVTLOG_HEAD_MASK -#define AMDVI_MMIO_PPRLOG_TAIL_MASK AMDVI_MMIO_EVTLOG_HEAD_MASK -#define AMDVI_MMIO_PPRLOG_BASE_MASK AMDVI_MMIO_EVTLOG_BASE_MASK -#define AMDVI_MMIO_PPRLOG_SIZE_MASK AMDVI_MMIO_EVTLOG_SIZE_MASK - -#define AMDVI_MMIO_EXCL_ENABLED_MASK (1ULL << 0) -#define AMDVI_MMIO_EXCL_ALLOW_MASK (1ULL << 1) -#define AMDVI_MMIO_EXCL_LIMIT_MASK AMDVI_MMIO_DEVTAB_BASE_MASK -#define AMDVI_MMIO_EXCL_LIMIT_LOW 0xfff - -/* mmio control register flags */ -#define AMDVI_MMIO_CONTROL_AMDVIEN (1ULL << 0) -#define AMDVI_MMIO_CONTROL_HTTUNEN (1ULL << 1) -#define AMDVI_MMIO_CONTROL_EVENTLOGEN (1ULL << 2) -#define AMDVI_MMIO_CONTROL_EVENTINTEN (1ULL << 3) -#define AMDVI_MMIO_CONTROL_COMWAITINTEN (1ULL << 4) -#define AMDVI_MMIO_CONTROL_CMDBUFLEN (1ULL << 12) -#define AMDVI_MMIO_CONTROL_GAEN (1ULL << 17) - -/* MMIO status register bits */ -#define AMDVI_MMIO_STATUS_CMDBUF_RUN (1 << 4) -#define AMDVI_MMIO_STATUS_EVT_RUN (1 << 3) -#define AMDVI_MMIO_STATUS_COMP_INT (1 << 2) -#define AMDVI_MMIO_STATUS_EVT_OVF (1 << 0) - -#define AMDVI_CMDBUF_ID_BYTE 0x07 -#define AMDVI_CMDBUF_ID_RSHIFT 4 - -#define AMDVI_CMD_COMPLETION_WAIT 0x01 -#define AMDVI_CMD_INVAL_DEVTAB_ENTRY 0x02 -#define AMDVI_CMD_INVAL_AMDVI_PAGES 0x03 -#define AMDVI_CMD_INVAL_IOTLB_PAGES 0x04 -#define AMDVI_CMD_INVAL_INTR_TABLE 0x05 -#define AMDVI_CMD_PREFETCH_AMDVI_PAGES 0x06 -#define AMDVI_CMD_COMPLETE_PPR_REQUEST 0x07 -#define AMDVI_CMD_INVAL_AMDVI_ALL 0x08 - -#define AMDVI_DEVTAB_ENTRY_SIZE 32 - -/* Device table entry bits 0:63 */ -#define AMDVI_DEV_VALID (1ULL << 0) -#define AMDVI_DEV_TRANSLATION_VALID (1ULL << 1) -#define AMDVI_DEV_MODE_MASK 0x7 -#define AMDVI_DEV_MODE_RSHIFT 9 -#define AMDVI_DEV_PT_ROOT_MASK 0xffffffffff000 -#define AMDVI_DEV_PT_ROOT_RSHIFT 12 -#define AMDVI_DEV_PERM_SHIFT 61 -#define AMDVI_DEV_PERM_READ (1ULL << 61) -#define AMDVI_DEV_PERM_WRITE (1ULL << 62) - -/* Device table entry bits 64:127 */ -#define AMDVI_DEV_DOMID_ID_MASK ((1ULL << 16) - 1) - -/* Event codes and flags, as stored in the info field */ -#define AMDVI_EVENT_ILLEGAL_DEVTAB_ENTRY (0x1U << 12) -#define AMDVI_EVENT_IOPF (0x2U << 12) -#define AMDVI_EVENT_IOPF_I (1U << 3) -#define AMDVI_EVENT_DEV_TAB_HW_ERROR (0x3U << 12) -#define AMDVI_EVENT_PAGE_TAB_HW_ERROR (0x4U << 12) -#define AMDVI_EVENT_ILLEGAL_COMMAND_ERROR (0x5U << 12) -#define AMDVI_EVENT_COMMAND_HW_ERROR (0x6U << 12) - -#define AMDVI_EVENT_LEN 16 -#define AMDVI_PERM_READ (1 << 0) -#define AMDVI_PERM_WRITE (1 << 1) - -#define AMDVI_FEATURE_PREFETCH (1ULL << 0) /* page prefetch = */ -#define AMDVI_FEATURE_PPR (1ULL << 1) /* PPR Support = */ -#define AMDVI_FEATURE_GT (1ULL << 4) /* Guest Translation= */ -#define AMDVI_FEATURE_IA (1ULL << 6) /* inval all support= */ -#define AMDVI_FEATURE_GA (1ULL << 7) /* guest VAPIC suppo= rt */ -#define AMDVI_FEATURE_HE (1ULL << 8) /* hardware error re= gs */ -#define AMDVI_FEATURE_PC (1ULL << 9) /* Perf counters = */ - -/* reserved DTE bits */ -#define AMDVI_DTE_LOWER_QUAD_RESERVED 0x80300000000000fc -#define AMDVI_DTE_MIDDLE_QUAD_RESERVED 0x0000000000000100 -#define AMDVI_DTE_UPPER_QUAD_RESERVED 0x08f0000000000000 - -/* AMDVI paging mode */ -#define AMDVI_GATS_MODE (2ULL << 12) -#define AMDVI_HATS_MODE (2ULL << 10) - -/* IOTLB */ -#define AMDVI_IOTLB_MAX_SIZE 1024 -#define AMDVI_DEVID_SHIFT 36 - -/* extended feature support */ -#define AMDVI_EXT_FEATURES (AMDVI_FEATURE_PREFETCH | AMDVI_FEATURE_PPR | \ - AMDVI_FEATURE_IA | AMDVI_FEATURE_GT | AMDVI_FEATURE_HE | \ - AMDVI_GATS_MODE | AMDVI_HATS_MODE | AMDVI_FEATURE_GA) - -/* capabilities header */ -#define AMDVI_CAPAB_FEATURES (AMDVI_CAPAB_FLAT_EXT | \ - AMDVI_CAPAB_FLAG_NPCACHE | AMDVI_CAPAB_FLAG_IOTLBSUP \ - | AMDVI_CAPAB_ID_SEC | AMDVI_CAPAB_INIT_TYPE | \ - AMDVI_CAPAB_FLAG_HTTUNNEL | AMDVI_CAPAB_EFR_SUP) - -/* AMDVI default address */ -#define AMDVI_BASE_ADDR 0xfed80000 - -/* page management constants */ -#define AMDVI_PAGE_SHIFT 12 -#define AMDVI_PAGE_SIZE (1ULL << AMDVI_PAGE_SHIFT) - -#define AMDVI_PAGE_SHIFT_4K 12 -#define AMDVI_PAGE_MASK_4K (~((1ULL << AMDVI_PAGE_SHIFT_4K) - 1)) - -#define AMDVI_MAX_VA_ADDR (48UL << 5) -#define AMDVI_MAX_PH_ADDR (40UL << 8) -#define AMDVI_MAX_GVA_ADDR (48UL << 15) - -/* Completion Wait data size */ -#define AMDVI_COMPLETION_DATA_SIZE 8 - -#define AMDVI_COMMAND_SIZE 16 -/* Completion Wait data size */ -#define AMDVI_COMPLETION_DATA_SIZE 8 - -#define AMDVI_COMMAND_SIZE 16 - -#define AMDVI_INT_ADDR_FIRST 0xfee00000 -#define AMDVI_INT_ADDR_LAST 0xfeefffff -#define AMDVI_INT_ADDR_SIZE (AMDVI_INT_ADDR_LAST - AMDVI_INT_ADDR_FIRS= T + 1) -#define AMDVI_MSI_ADDR_HI_MASK (0xffffffff00000000ULL) -#define AMDVI_MSI_ADDR_LO_MASK (0x00000000ffffffffULL) - -/* SB IOAPIC is always on this device in AMD systems */ -#define AMDVI_IOAPIC_SB_DEVID PCI_BUILD_BDF(0, PCI_DEVFN(0x14, 0)) - -/* Interrupt remapping errors */ -#define AMDVI_IR_ERR 0x1 -#define AMDVI_IR_GET_IRTE 0x2 -#define AMDVI_IR_TARGET_ABORT 0x3 - -/* Interrupt remapping */ -#define AMDVI_IR_REMAP_ENABLE 1ULL -#define AMDVI_IR_INTCTL_SHIFT 60 -#define AMDVI_IR_INTCTL_ABORT 0 -#define AMDVI_IR_INTCTL_PASS 1 -#define AMDVI_IR_INTCTL_REMAP 2 - -#define AMDVI_IR_PHYS_ADDR_MASK (((1ULL << 45) - 1) << 6) - -/* MSI data 10:0 bits (section 2.2.5.1 Fig 14) */ -#define AMDVI_IRTE_OFFSET 0x7ff - -/* Delivery mode of MSI data (same as IOAPIC deilver mode encoding) */ -#define AMDVI_IOAPIC_INT_TYPE_FIXED 0x0 -#define AMDVI_IOAPIC_INT_TYPE_ARBITRATED 0x1 -#define AMDVI_IOAPIC_INT_TYPE_SMI 0x2 -#define AMDVI_IOAPIC_INT_TYPE_NMI 0x4 -#define AMDVI_IOAPIC_INT_TYPE_INIT 0x5 -#define AMDVI_IOAPIC_INT_TYPE_EINT 0x7 - -/* Pass through interrupt */ -#define AMDVI_DEV_INT_PASS_MASK (1ULL << 56) -#define AMDVI_DEV_EINT_PASS_MASK (1ULL << 57) -#define AMDVI_DEV_NMI_PASS_MASK (1ULL << 58) -#define AMDVI_DEV_LINT0_PASS_MASK (1ULL << 62) -#define AMDVI_DEV_LINT1_PASS_MASK (1ULL << 63) - -/* Interrupt remapping table fields (Guest VAPIC not enabled) */ -union irte { - uint32_t val; - struct { - uint32_t valid:1, - no_fault:1, - int_type:3, - rq_eoi:1, - dm:1, - guest_mode:1, - destination:8, - vector:8, - rsvd:8; - } fields; -}; - -/* Interrupt remapping table fields (Guest VAPIC is enabled) */ -union irte_ga_lo { - uint64_t val; - - /* For int remapping */ - struct { - uint64_t valid:1, - no_fault:1, - /* ------ */ - int_type:3, - rq_eoi:1, - dm:1, - /* ------ */ - guest_mode:1, - destination:8, - rsvd_1:48; - } fields_remap; -}; - -union irte_ga_hi { - uint64_t val; - struct { - uint64_t vector:8, - rsvd_2:56; - } fields; -}; - -struct irte_ga { - union irte_ga_lo lo; - union irte_ga_hi hi; -}; - -#define TYPE_AMD_IOMMU_DEVICE "amd-iommu" -#define AMD_IOMMU_DEVICE(obj)\ - OBJECT_CHECK(AMDVIState, (obj), TYPE_AMD_IOMMU_DEVICE) - -#define TYPE_AMD_IOMMU_PCI "AMDVI-PCI" - -#define TYPE_AMD_IOMMU_MEMORY_REGION "amd-iommu-iommu-memory-region" - -typedef struct AMDVIAddressSpace AMDVIAddressSpace; - -/* functions to steal PCI config space */ -typedef struct AMDVIPCIState { - PCIDevice dev; /* The PCI device itself */ -} AMDVIPCIState; - -typedef struct AMDVIState { - X86IOMMUState iommu; /* IOMMU bus device */ - AMDVIPCIState pci; /* IOMMU PCI device */ - - uint32_t version; - uint32_t capab_offset; /* capability offset pointer */ - - uint64_t mmio_addr; - - uint32_t devid; /* auto-assigned devid */ - - bool enabled; /* IOMMU enabled */ - bool ats_enabled; /* address translation enabled */ - bool cmdbuf_enabled; /* command buffer enabled */ - bool evtlog_enabled; /* event log enabled */ - bool excl_enabled; - - hwaddr devtab; /* base address device table */ - size_t devtab_len; /* device table length */ - - hwaddr cmdbuf; /* command buffer base address */ - uint64_t cmdbuf_len; /* command buffer length */ - uint32_t cmdbuf_head; /* current IOMMU read position */ - uint32_t cmdbuf_tail; /* next Software write position */ - bool completion_wait_intr; - - hwaddr evtlog; /* base address event log */ - bool evtlog_intr; - uint32_t evtlog_len; /* event log length */ - uint32_t evtlog_head; /* current IOMMU write position */ - uint32_t evtlog_tail; /* current Software read position */ - - /* unused for now */ - hwaddr excl_base; /* base DVA - IOMMU exclusion range */ - hwaddr excl_limit; /* limit of IOMMU exclusion range */ - bool excl_allow; /* translate accesses to the exclusion ra= nge */ - bool excl_enable; /* exclusion range enabled */ - - hwaddr ppr_log; /* base address ppr log */ - uint32_t pprlog_len; /* ppr log len */ - uint32_t pprlog_head; /* ppr log head */ - uint32_t pprlog_tail; /* ppr log tail */ - - MemoryRegion mmio; /* MMIO region */ - uint8_t mmior[AMDVI_MMIO_SIZE]; /* read/write MMIO */ - uint8_t w1cmask[AMDVI_MMIO_SIZE]; /* read/write 1 clear mask */ - uint8_t romask[AMDVI_MMIO_SIZE]; /* MMIO read/only mask */ - bool mmio_enabled; - - /* for each served device */ - AMDVIAddressSpace **address_spaces[PCI_BUS_MAX]; - - /* IOTLB */ - GHashTable *iotlb; - - /* Interrupt remapping */ - bool ga_enabled; -} AMDVIState; - -#endif diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index cfb9043..dfb1d6d 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -44,7 +44,6 @@ #include "exec/address-spaces.h" #include "hw/i386/pc.h" #include "hw/i386/ich9.h" -#include "hw/i386/amd_iommu.h" #include "hw/i386/intel_iommu.h" #include "hw/display/ramfb.h" #include "hw/firmware/smbios.h" @@ -359,7 +358,6 @@ static void pc_q35_machine_options(MachineClass *m) m->default_display =3D "std"; m->default_kernel_irqchip_split =3D true; m->no_floppy =3D 1; - machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); m->max_cpus =3D 288; diff --git a/hw/i386/trace-events b/hw/i386/trace-events index 77244fc..7bf98e3 100644 --- a/hw/i386/trace-events +++ b/hw/i386/trace-events @@ -67,49 +67,6 @@ vtd_warn_invalid_qi_tail(uint16_t tail) "tail 0x%"PRIx16 vtd_warn_ir_vector(uint16_t sid, int index, int vec, int target) "sid 0x%"= PRIx16" index %d vec %d (should be: %d)" vtd_warn_ir_trigger(uint16_t sid, int index, int trig, int target) "sid 0x= %"PRIx16" index %d trigger %d (should be: %d)" =20 -# hw/i386/amd_iommu.c -amdvi_evntlog_fail(uint64_t addr, uint32_t head) "error: fail to write at = addr 0x%"PRIx64" + offset 0x%"PRIx32 -amdvi_cache_update(uint16_t domid, uint8_t bus, uint8_t slot, uint8_t func= , uint64_t gpa, uint64_t txaddr) " update iotlb domid 0x%"PRIx16" devid: %0= 2x:%02x.%x gpa 0x%"PRIx64" hpa 0x%"PRIx64 -amdvi_completion_wait_fail(uint64_t addr) "error: fail to write at address= 0x%"PRIx64 -amdvi_mmio_write(const char *reg, uint64_t addr, unsigned size, uint64_t v= al, uint64_t offset) "%s write addr 0x%"PRIx64", size %u, val 0x%"PRIx64", = offset 0x%"PRIx64 -amdvi_mmio_read(const char *reg, uint64_t addr, unsigned size, uint64_t of= fset) "%s read addr 0x%"PRIx64", size %u offset 0x%"PRIx64 -amdvi_mmio_read_invalid(int max, uint64_t addr, unsigned size) "error: add= r outside region (max 0x%x): read addr 0x%" PRIx64 ", size %u" -amdvi_command_error(uint64_t status) "error: Executing commands with comma= nd buffer disabled 0x%"PRIx64 -amdvi_command_read_fail(uint64_t addr, uint32_t head) "error: fail to acce= ss memory at 0x%"PRIx64" + 0x%"PRIx32 -amdvi_command_exec(uint32_t head, uint32_t tail, uint64_t buf) "command bu= ffer head at 0x%"PRIx32" command buffer tail at 0x%"PRIx32" command buffer = base at 0x%"PRIx64 -amdvi_unhandled_command(uint8_t type) "unhandled command 0x%"PRIx8 -amdvi_intr_inval(void) "Interrupt table invalidated" -amdvi_iotlb_inval(void) "IOTLB pages invalidated" -amdvi_prefetch_pages(void) "Pre-fetch of AMD-Vi pages requested" -amdvi_pages_inval(uint16_t domid) "AMD-Vi pages for domain 0x%"PRIx16 " in= validated" -amdvi_all_inval(void) "Invalidation of all AMD-Vi cache requested " -amdvi_ppr_exec(void) "Execution of PPR queue requested " -amdvi_devtab_inval(uint8_t bus, uint8_t slot, uint8_t func) "device table = entry for devid: %02x:%02x.%x invalidated" -amdvi_completion_wait(uint64_t addr, uint64_t data) "completion wait reque= sted with store address 0x%"PRIx64" and store data 0x%"PRIx64 -amdvi_control_status(uint64_t val) "MMIO_STATUS state 0x%"PRIx64 -amdvi_iotlb_reset(void) "IOTLB exceed size limit - reset " -amdvi_dte_get_fail(uint64_t addr, uint32_t offset) "error: failed to acces= s Device Entry devtab 0x%"PRIx64" offset 0x%"PRIx32 -amdvi_invalid_dte(uint64_t addr) "PTE entry at 0x%"PRIx64" is invalid " -amdvi_get_pte_hwerror(uint64_t addr) "hardware error eccessing PTE at addr= 0x%"PRIx64 -amdvi_mode_invalid(uint8_t level, uint64_t addr)"error: translation level = 0x%"PRIx8" translating addr 0x%"PRIx64 -amdvi_page_fault(uint64_t addr) "error: page fault accessing guest physica= l address 0x%"PRIx64 -amdvi_iotlb_hit(uint8_t bus, uint8_t slot, uint8_t func, uint64_t addr, ui= nt64_t txaddr) "hit iotlb devid %02x:%02x.%x gpa 0x%"PRIx64" hpa 0x%"PRIx64 -amdvi_translation_result(uint8_t bus, uint8_t slot, uint8_t func, uint64_t= addr, uint64_t txaddr) "devid: %02x:%02x.%x gpa 0x%"PRIx64" hpa 0x%"PRIx64 -amdvi_mem_ir_write_req(uint64_t addr, uint64_t val, uint32_t size) "addr 0= x%"PRIx64" data 0x%"PRIx64" size 0x%"PRIx32 -amdvi_mem_ir_write(uint64_t addr, uint64_t val) "addr 0x%"PRIx64" data 0x%= "PRIx64 -amdvi_ir_remap_msi_req(uint64_t addr, uint64_t data, uint8_t devid) "addr = 0x%"PRIx64" data 0x%"PRIx64" devid 0x%"PRIx8 -amdvi_ir_remap_msi(uint64_t addr, uint64_t data, uint64_t addr2, uint64_t = data2) "(addr 0x%"PRIx64", data 0x%"PRIx64") -> (addr 0x%"PRIx64", data 0x%= "PRIx64")" -amdvi_err(const char *str) "%s" -amdvi_ir_irte(uint64_t addr, uint64_t data) "addr 0x%"PRIx64" offset 0x%"P= RIx64 -amdvi_ir_irte_val(uint32_t data) "data 0x%"PRIx32 -amdvi_ir_err(const char *str) "%s" -amdvi_ir_intctl(uint8_t val) "int_ctl 0x%"PRIx8 -amdvi_ir_target_abort(const char *str) "%s" -amdvi_ir_delivery_mode(const char *str) "%s" -amdvi_ir_generate_msi_message(uint8_t vector, uint8_t delivery_mode, uint8= _t dest_mode, uint8_t dest, uint8_t rh) "vector %d delivery-mode %d dest-mo= de %d dest-id %d rh %d" -amdvi_ir_irte_ga(uint64_t addr, uint64_t data) "addr 0x%"PRIx64" offset 0x= %"PRIx64 -amdvi_ir_irte_ga_val(uint64_t hi, uint64_t lo) "hi 0x%"PRIx64" lo 0x%"PRIx= 64 - # hw/i386/vmport.c vmport_register(unsigned char command, void *func, void *opaque) "command:= 0x%02x func: %p opaque: %p" vmport_command(unsigned char command) "command: 0x%02x" --=20 2.21.0