From patchwork Sat Aug 16 05:55:40 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Le Tan X-Patchwork-Id: 380453 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 2737C140129 for ; Sat, 16 Aug 2014 15:58:50 +1000 (EST) Received: from localhost ([::1]:34407 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XIX0q-0005ay-3C for incoming@patchwork.ozlabs.org; Sat, 16 Aug 2014 01:58:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58511) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XIWzC-0002oQ-Fb for qemu-devel@nongnu.org; Sat, 16 Aug 2014 01:57:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XIWyz-0000CF-5z for qemu-devel@nongnu.org; Sat, 16 Aug 2014 01:57:06 -0400 Received: from mail-pd0-x236.google.com ([2607:f8b0:400e:c02::236]:32844) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XIWyy-0000C0-LJ for qemu-devel@nongnu.org; Sat, 16 Aug 2014 01:56:53 -0400 Received: by mail-pd0-f182.google.com with SMTP id fp1so4415709pdb.41 for ; Fri, 15 Aug 2014 22:56:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=uVlHWqEmYBkAzfhRq7W65moN7VXWCV5R5JA9GI1pkUA=; b=idgl/Xb/u+j7/Vg2NdKQA0l83F29XmKwSbozDk5xlzKD8Y2OQtOGQVM0qongdnhkJx pouObGssDleRRt7QWsulhgg0NuytmznIvA1J9Rp83xXX5HoSzcFxRYf/YBPbssFmtxsD ilNAC8FBFwMH//roz4Gk18aWsvs2tMH42nuctLW5l30w3UZYpkeoD0Ynq8gFDYjPPhUz 6khGEC7MAT2mKthdH/pwDwIDp67b53Y8AbtiXUIM7BkbFWP29dBJ3w1vrYbXIrk6snWv Wc+OWOqo19/cjsgpXtu8WPhl8ZyrjBsWvr3EjwLKbnrLGBjSqDt1USMsnEv5vUOJA4aP Emsw== X-Received: by 10.70.91.167 with SMTP id cf7mr23956991pdb.3.1408168611613; Fri, 15 Aug 2014 22:56:51 -0700 (PDT) Received: from localhost.localdomain ([222.29.39.139]) by mx.google.com with ESMTPSA id y3sm14738460pdm.69.2014.08.15.22.56.48 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 15 Aug 2014 22:56:50 -0700 (PDT) From: Le Tan To: qemu-devel@nongnu.org Date: Sat, 16 Aug 2014 13:55:40 +0800 Message-Id: <1408168544-28605-5-git-send-email-tamlokveer@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1408168544-28605-1-git-send-email-tamlokveer@gmail.com> References: <1408168544-28605-1-git-send-email-tamlokveer@gmail.com> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:400e:c02::236 Cc: "Michael S. Tsirkin" , Stefan Weil , Knut Omang , Le Tan , Alex Williamson , Jan Kiszka , Anthony Liguori , Paolo Bonzini Subject: [Qemu-devel] [PATCH v4 4/8] intel-iommu: add Intel IOMMU emulation to q35 and add a machine option "iommu" as a switch X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add Intel IOMMU emulation to q35 chipset and expose it to the guest. 1. Add a machine option. Users can use "-machine iommu=on|off" in the command line to enable/disable Intel IOMMU. The default is off. 2. Accroding to the machine option, q35 will initialize the Intel IOMMU and use pci_setup_iommu() to setup q35_host_dma_iommu() as the IOMMU function for the pci bus. 3. q35_host_dma_iommu() will return different address space according to the bus_num and devfn of the device. Signed-off-by: Le Tan --- hw/core/machine.c | 17 +++++++++++++++++ hw/pci-host/q35.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ include/hw/boards.h | 1 + include/hw/pci-host/q35.h | 2 ++ qemu-options.hx | 5 ++++- vl.c | 4 ++++ 6 files changed, 74 insertions(+), 1 deletion(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 7a66c57..0708de5 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -235,6 +235,20 @@ static void machine_set_firmware(Object *obj, const char *value, Error **errp) ms->firmware = g_strdup(value); } +static bool machine_get_iommu(Object *obj, Error **errp) +{ + MachineState *ms = MACHINE(obj); + + return ms->iommu; +} + +static void machine_set_iommu(Object *obj, bool value, Error **errp) +{ + MachineState *ms = MACHINE(obj); + + ms->iommu = value; +} + static void machine_initfn(Object *obj) { object_property_add_str(obj, "accel", @@ -274,6 +288,9 @@ static void machine_initfn(Object *obj) object_property_add_bool(obj, "usb", machine_get_usb, machine_set_usb, NULL); object_property_add_str(obj, "firmware", machine_get_firmware, machine_set_firmware, NULL); + object_property_add_bool(obj, "iommu", + machine_get_iommu, + machine_set_iommu, NULL); } static void machine_finalize(Object *obj) diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index a0a3068..ad8f1b9 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -347,6 +347,48 @@ static void mch_reset(DeviceState *qdev) mch_update(mch); } +static AddressSpace *q35_host_dma_iommu(PCIBus *bus, void *opaque, int devfn) +{ + IntelIOMMUState *s = opaque; + VTDAddressSpace **pvtd_as; + int bus_num = pci_bus_num(bus); + + assert(0 <= bus_num && bus_num <= VTD_PCI_BUS_MAX); + assert(0 <= devfn && devfn <= VTD_PCI_DEVFN_MAX); + + pvtd_as = s->address_spaces[bus_num]; + if (!pvtd_as) { + /* No corresponding free() */ + pvtd_as = g_malloc0(sizeof(VTDAddressSpace *) * VTD_PCI_DEVFN_MAX); + s->address_spaces[bus_num] = pvtd_as; + } + if (!pvtd_as[devfn]) { + pvtd_as[devfn] = g_malloc0(sizeof(VTDAddressSpace)); + + pvtd_as[devfn]->bus_num = (uint8_t)bus_num; + pvtd_as[devfn]->devfn = (uint8_t)devfn; + pvtd_as[devfn]->iommu_state = s; + memory_region_init_iommu(&pvtd_as[devfn]->iommu, OBJECT(s), + &s->iommu_ops, "intel_iommu", UINT64_MAX); + address_space_init(&pvtd_as[devfn]->as, + &pvtd_as[devfn]->iommu, "intel_iommu"); + } + return &pvtd_as[devfn]->as; +} + +static void mch_init_dmar(MCHPCIState *mch) +{ + PCIBus *pci_bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch))); + + mch->iommu = INTEL_IOMMU_DEVICE(qdev_create(NULL, TYPE_INTEL_IOMMU_DEVICE)); + object_property_add_child(OBJECT(mch), "intel-iommu", + OBJECT(mch->iommu), NULL); + qdev_init_nofail(DEVICE(mch->iommu)); + sysbus_mmio_map(SYS_BUS_DEVICE(mch->iommu), 0, Q35_HOST_BRIDGE_IOMMU_ADDR); + + pci_setup_iommu(pci_bus, q35_host_dma_iommu, mch->iommu); +} + static int mch_init(PCIDevice *d) { int i; @@ -370,6 +412,10 @@ static int mch_init(PCIDevice *d) &mch->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE); } + /* Intel IOMMU (VT-d) */ + if (qemu_opt_get_bool(qemu_get_machine_opts(), "iommu", false)) { + mch_init_dmar(mch); + } return 0; } diff --git a/include/hw/boards.h b/include/hw/boards.h index 605a970..dfb6718 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -123,6 +123,7 @@ struct MachineState { bool mem_merge; bool usb; char *firmware; + bool iommu; ram_addr_t ram_size; ram_addr_t maxram_size; diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h index d9ee978..025d6e6 100644 --- a/include/hw/pci-host/q35.h +++ b/include/hw/pci-host/q35.h @@ -33,6 +33,7 @@ #include "hw/acpi/acpi.h" #include "hw/acpi/ich9.h" #include "hw/pci-host/pam.h" +#include "hw/i386/intel_iommu.h" #define TYPE_Q35_HOST_DEVICE "q35-pcihost" #define Q35_HOST_DEVICE(obj) \ @@ -60,6 +61,7 @@ typedef struct MCHPCIState { uint64_t pci_hole64_size; PcGuestInfo *guest_info; uint32_t short_root_bus; + IntelIOMMUState *iommu; } MCHPCIState; typedef struct Q35PCIHost { diff --git a/qemu-options.hx b/qemu-options.hx index 96516c1..7406a17 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -35,7 +35,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ " kernel_irqchip=on|off controls accelerated irqchip support\n" " kvm_shadow_mem=size of KVM shadow MMU\n" " dump-guest-core=on|off include guest memory in a core dump (default=on)\n" - " mem-merge=on|off controls memory merge support (default: on)\n", + " mem-merge=on|off controls memory merge support (default: on)\n" + " iommu=on|off controls emulated Intel IOMMU (VT-d) support (default=off)\n", QEMU_ARCH_ALL) STEXI @item -machine [type=]@var{name}[,prop=@var{value}[,...]] @@ -58,6 +59,8 @@ Include guest memory in a core dump. The default is on. Enables or disables memory merge support. This feature, when supported by the host, de-duplicates identical memory pages among VMs instances (enabled by default). +@item iommu=on|off +Enables or disables emulated Intel IOMMU (VT-d) support. The default is off. @end table ETEXI diff --git a/vl.c b/vl.c index a8029d5..2ab1643 100644 --- a/vl.c +++ b/vl.c @@ -388,6 +388,10 @@ static QemuOptsList qemu_machine_opts = { .name = PC_MACHINE_MAX_RAM_BELOW_4G, .type = QEMU_OPT_SIZE, .help = "maximum ram below the 4G boundary (32bit boundary)", + },{ + .name = "iommu", + .type = QEMU_OPT_BOOL, + .help = "Set on/off to enable/disable Intel IOMMU (VT-d)", }, { /* End of list */ } },