From patchwork Thu Aug 22 18:28:12 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 19427 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-gh0-f198.google.com (mail-gh0-f198.google.com [209.85.160.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id E6F08246AD for ; Thu, 22 Aug 2013 18:28:18 +0000 (UTC) Received: by mail-gh0-f198.google.com with SMTP id r13sf1769689ghr.1 for ; Thu, 22 Aug 2013 11:28:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-gm-message-state:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=bbmnV7zfvKJ7gETBx2e5Sk7eqLDANGFcdfzd/RN7cQY=; b=OSP/ZaRNA46Ymms8latj/qKl5CMH3UIu/kWlOVcv03983kg7dKbBVu1rchL49wlc9A qXYORkQG/306SBzdgcoXH/gU+974XEu1PnfYfhG8Rj20u0grildipmSxb8qUTtWfgumw uQAuqmBoepGubGCMR7d62p9gKt7Rx8/T3J4zEbznztiME1y3FiunfK5Xw/ET5zWGtcrU bNuybju6oMM5p8csb1ryMVPci6rpjvXRsQs4JXKI0n1ibsGS/0loM8Ek+q+Gg8x7SBTy PWZRgtL8OW0ac69HRQqIpwbt/AJzHlsI1zzeYfH7ZONFFyva/U4Lu58uCh3JWmExP86V /FJQ== X-Received: by 10.224.137.68 with SMTP id v4mr13738842qat.1.1377196098726; Thu, 22 Aug 2013 11:28:18 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.81.244 with SMTP id d20ls1259746qey.38.gmail; Thu, 22 Aug 2013 11:28:18 -0700 (PDT) X-Received: by 10.58.196.132 with SMTP id im4mr1904082vec.28.1377196098613; Thu, 22 Aug 2013 11:28:18 -0700 (PDT) Received: from mail-ve0-f177.google.com (mail-ve0-f177.google.com [209.85.128.177]) by mx.google.com with ESMTPS id j3si4360964vcs.98.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 22 Aug 2013 11:28:18 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.177 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.177; Received: by mail-ve0-f177.google.com with SMTP id cz11so1819678veb.36 for ; Thu, 22 Aug 2013 11:28:18 -0700 (PDT) X-Gm-Message-State: ALoCoQniusTRcpfHTCuDObCCJI7jb4avcstrGe/lN5XzvFVxqtYuXdbrT+yO9RAub7zZzEy7tx5R X-Received: by 10.58.237.105 with SMTP id vb9mr12639917vec.2.1377196098472; Thu, 22 Aug 2013 11:28:18 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp46820vcz; Thu, 22 Aug 2013 11:28:17 -0700 (PDT) X-Received: by 10.204.187.66 with SMTP id cv2mr43452bkb.52.1377196094987; Thu, 22 Aug 2013 11:28:14 -0700 (PDT) Received: from mnementh.archaic.org.uk (1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.1.0.0.b.8.0.1.0.0.2.ip6.arpa. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id f2si1846276bko.32.1969.12.31.16.00.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 22 Aug 2013 11:28:14 -0700 (PDT) Received-SPF: neutral (google.com: 2001:8b0:1d0::1 is neither permitted nor denied by best guess record for domain of pm215@archaic.org.uk) client-ip=2001:8b0:1d0::1; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1VCZcC-0001xG-IT; Thu, 22 Aug 2013 19:28:12 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, "Michael S. Tsirkin" Subject: [RFC 2/2] hw/pci-host/versatile: Implement IMAP registers Date: Thu, 22 Aug 2013 19:28:12 +0100 Message-Id: <1377196092-7482-3-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1377196092-7482-1-git-send-email-peter.maydell@linaro.org> References: <1377196092-7482-1-git-send-email-peter.maydell@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.177 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Rather than assuming that PCI bus master devices can DMA directly into system memory, correctly model the way the hardware does it: * the host controller has three BARs (one I/O and two memory) which can be mapped into PCI memory space in the usual way * each of these BARs is an alias of an area of system memory whose base address is defined by the host controller's SMAP registers * PCI bus master devices see the PCI memory space, in the same way as everybody else Linux programs the BARs and SMAP registers in such a way that (for system RAM) you get the identity mapping. Note that since the QEMU PCI core doesn't forbid PCI devices from attempting to do bus master accesses to their own MMIO BARs it is possible for a malicious guest to configure the controller into a hall-of-mirrors mapping of the PCI and system memory spaces into each other such that an access would loop infinitely. This will probably result in infinite recursion in QEMU in render_memory_region()... Signed-off-by: Peter Maydell --- hw/pci-host/versatile.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c index 9238d39..37c7425 100644 --- a/hw/pci-host/versatile.c +++ b/hw/pci-host/versatile.c @@ -75,11 +75,19 @@ typedef struct { /* Containers representing the PCI address spaces */ MemoryRegion pci_io_space; MemoryRegion pci_mem_space; + /* AddressSpace corresponding to pci_mem_space */ + AddressSpace pci_mem_as; /* Alias regions into PCI address spaces which we expose as sysbus regions. * The offsets into pci_mem_space are controlled by the imap registers. */ MemoryRegion pci_io_window; MemoryRegion pci_mem_window[3]; + /* Alias regions into system address space which we map into PCI + * memory space under the control of the SMAP registers. + * Note that which one of the BARs is the I/O bar differs for + * realview and versatile. + */ + MemoryRegion pci_bar[3]; PCIBus pci_bus; PCIDevice pci_dev; @@ -127,10 +135,38 @@ static void pci_vpb_update_all_windows(PCIVPBState *s) } } +static void pci_vpb_update_smap(PCIVPBState *s, int i) +{ + /* After a change to the SMAP registers, we need to update + * what part of the system address space we're aliasing + * into the PCI memory or IO space. (This is the inverse of + * the windows controlled by the IMAP registers, which + * map parts of PCI space into system space.) + */ + hwaddr offset; + + if (s->realview) { + offset = s->smap[i] & 0xf0000000; + } else { + offset = s->smap[i] << 28; + } + memory_region_set_alias_offset(&s->pci_bar[i], offset); +} + +static void pci_vpb_update_all_smaps(PCIVPBState *s) +{ + int i; + + for (i = 0; i < 3; i++) { + pci_vpb_update_smap(s, i); + } +} + static int pci_vpb_post_load(void *opaque, int version_id) { PCIVPBState *s = opaque; pci_vpb_update_all_windows(s); + pci_vpb_update_all_smaps(s); return 0; } @@ -195,6 +231,7 @@ static void pci_vpb_reg_write(void *opaque, hwaddr addr, { int win = (addr - PCI_SMAP0) >> 2; s->smap[win] = val; + pci_vpb_update_smap(s, win); break; } default: @@ -376,6 +413,13 @@ static void pci_vpb_reset(DeviceState *d) pci_vpb_update_all_windows(s); } +static AddressSpace *pci_vpb_dma_iommu(PCIBus *bus, void *opaque, int devfn) +{ + PCIVPBState *s = opaque; + + return &s->pci_mem_as; +} + static void pci_vpb_init(Object *obj) { PCIHostState *h = PCI_HOST_BRIDGE(obj); @@ -383,12 +427,15 @@ static void pci_vpb_init(Object *obj) memory_region_init(&s->pci_io_space, OBJECT(s), "pci_io", 1ULL << 32); memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 1ULL << 32); + address_space_init(&s->pci_mem_as, &s->pci_mem_space, "pci_mem"); pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), "pci", &s->pci_mem_space, &s->pci_io_space, PCI_DEVFN(11, 0), TYPE_PCI_BUS); h->bus = &s->pci_bus; + pci_setup_iommu(&s->pci_bus, pci_vpb_dma_iommu, s); + object_initialize(&s->pci_dev, TYPE_VERSATILE_PCI_HOST); qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus)); @@ -458,9 +505,34 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp) static int versatile_pci_host_init(PCIDevice *d) { + int i; + PCIVPBState *s = container_of(d->bus, PCIVPBState, pci_bus); + int iobar = s->realview ? 2 : 0; + pci_set_word(d->config + PCI_STATUS, PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM); pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10); + + /* The host allows its MMIO BARs to be mapped at PCI address zero + * (even though the PCI spec says 0 isn't a valid address), and + * Linux relies on this for PCI bus-mastering DMA to work. So we + * have to emulate this out-of-spec behaviour. + */ + d->cap_present |= QEMU_PCI_ADDR0_ALLOWED; + + /* Create alias regions corresponding to our own BARs */ + for (i = 0; i < 3; i++) { + uint8_t bar_type = PCI_BASE_ADDRESS_MEM_PREFETCH; + + memory_region_init_alias(&s->pci_bar[i], OBJECT(s), + "pci-vpb-bar0", get_system_memory(), 0, + 0x10000000); + if (i == iobar) { + bar_type = PCI_BASE_ADDRESS_SPACE_IO; + } + pci_register_bar(&s->pci_dev, i, bar_type, &s->pci_bar[i]); + } + return 0; }