kvmarm.lists.cs.columbia.edu archive mirror
 help / color / mirror / Atom feed
From: Julien Thierry <julien.thierry@arm.com>
To: kvmarm@lists.cs.columbia.edu
Cc: Andre.Przywara@arm.com, Sami.Mujawar@arm.com,
	will.deacon@arm.com, kvm@vger.kernel.org
Subject: [PATCH kvmtool 13/16] vfio: Add support for BAR configuration
Date: Thu,  7 Mar 2019 08:36:14 +0000	[thread overview]
Message-ID: <1551947777-13044-14-git-send-email-julien.thierry@arm.com> (raw)
In-Reply-To: <1551947777-13044-1-git-send-email-julien.thierry@arm.com>

When a guest can reassign BARs, kvmtool needs to maintain the vfio_region
consistent with their corresponding BARs. Take the new updated addresses
from the PCI header read back from the vfio driver.

Also, to modify the BARs, it is expected that guests will disable
IO/Memory response in the PCI command. Support this by mapping/unmapping
regions when the corresponding response gets enabled/disabled.

Signed-off-by: Julien Thierry <julien.thierry@arm.com>
---
 vfio/core.c |  8 +++---
 vfio/pci.c  | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 82 insertions(+), 8 deletions(-)

diff --git a/vfio/core.c b/vfio/core.c
index 0ed1e6f..b554897 100644
--- a/vfio/core.c
+++ b/vfio/core.c
@@ -202,14 +202,13 @@ static int vfio_setup_trap_region(struct kvm *kvm, struct vfio_device *vdev,
 				  struct vfio_region *region)
 {
 	if (region->is_ioport) {
-		int port = pci_get_io_port_block(region->info.size);
+		int port = ioport__register(kvm, region->port_base,
+					    &vfio_ioport_ops,
+					    region->info.size, region);
 
-		port = ioport__register(kvm, port, &vfio_ioport_ops,
-					region->info.size, region);
 		if (port < 0)
 			return port;
 
-		region->port_base = port;
 		return 0;
 	}
 
@@ -258,6 +257,7 @@ void vfio_unmap_region(struct kvm *kvm, struct vfio_region *region)
 {
 	if (region->host_addr) {
 		munmap(region->host_addr, region->info.size);
+		region->host_addr = NULL;
 	} else if (region->is_ioport) {
 		ioport__unregister(kvm, region->port_base);
 	} else {
diff --git a/vfio/pci.c b/vfio/pci.c
index 03de3c1..474f1c1 100644
--- a/vfio/pci.c
+++ b/vfio/pci.c
@@ -1,3 +1,4 @@
+#include "kvm/ioport.h"
 #include "kvm/irq.h"
 #include "kvm/kvm.h"
 #include "kvm/kvm-cpu.h"
@@ -452,6 +453,64 @@ static void vfio_pci_cfg_read(struct kvm *kvm, struct pci_device_header *pci_hdr
 			      sz, offset);
 }
 
+static void vfio_pci_cfg_handle_command(struct kvm *kvm, struct vfio_device *vdev,
+					void *data, int sz)
+{
+	struct pci_device_header *hdr = &vdev->pci.hdr;
+	bool switch_io;
+	bool switch_mem;
+	u16 cmd;
+	int i;
+
+	cmd = ioport__read16(data);
+	switch_io = !!((cmd ^ hdr->command) & PCI_COMMAND_IO);
+	switch_mem = !!((cmd ^ hdr->command) & PCI_COMMAND_MEMORY);
+
+	for (i = VFIO_PCI_BAR0_REGION_INDEX; i <= VFIO_PCI_BAR5_REGION_INDEX; ++i) {
+		struct vfio_region *region = &vdev->regions[i];
+
+		if (region->is_ioport && switch_io) {
+			if (cmd & PCI_COMMAND_IO)
+				vfio_map_region(kvm, vdev, region);
+			else
+				vfio_unmap_region(kvm, region);
+		}
+
+		if (!region->is_ioport && switch_mem) {
+			if (cmd & PCI_COMMAND_MEMORY)
+				vfio_map_region(kvm, vdev, region);
+			else
+				vfio_unmap_region(kvm, region);
+		}
+	}
+}
+
+static void vfio_pci_cfg_update_bar(struct kvm *kvm, struct vfio_device *vdev, int bar)
+{
+	struct pci_device_header *hdr = &vdev->pci.hdr;
+	struct vfio_region *bar_region;
+
+	bar_region = &vdev->regions[bar + VFIO_PCI_BAR0_REGION_INDEX];
+
+	if (bar_region->is_ioport) {
+		if (hdr->command & PCI_COMMAND_IO)
+			vfio_unmap_region(kvm, bar_region);
+
+		bar_region->port_base = hdr->bar[bar] & PCI_BASE_ADDRESS_IO_MASK;
+
+		if (hdr->command & PCI_COMMAND_IO)
+			vfio_map_region(kvm, vdev, bar_region);
+	} else {
+		if (hdr->command & PCI_COMMAND_MEMORY)
+			vfio_unmap_region(kvm, bar_region);
+
+		bar_region->guest_phys_addr = hdr->bar[bar] & PCI_BASE_ADDRESS_MEM_MASK;
+
+		if (hdr->command & PCI_COMMAND_MEMORY)
+			vfio_map_region(kvm, vdev, bar_region);
+	}
+}
+
 static void vfio_pci_cfg_write(struct kvm *kvm, struct pci_device_header *pci_hdr,
 			       u8 offset, void *data, int sz)
 {
@@ -475,9 +534,15 @@ static void vfio_pci_cfg_write(struct kvm *kvm, struct pci_device_header *pci_hd
 	if (pdev->irq_modes & VFIO_PCI_IRQ_MODE_MSI)
 		vfio_pci_msi_cap_write(kvm, vdev, offset, data, sz);
 
+	if (offset == PCI_COMMAND)
+		vfio_pci_cfg_handle_command(kvm, vdev, data, sz);
+
 	if (pread(vdev->fd, base + offset, sz, info->offset + offset) != sz)
 		vfio_dev_warn(vdev, "Failed to read %d bytes from Configuration Space at 0x%x",
 			      sz, offset);
+
+	if (offset >= PCI_BASE_ADDRESS_0 && offset <= PCI_BASE_ADDRESS_5)
+		vfio_pci_cfg_update_bar(kvm, vdev, offset - PCI_BASE_ADDRESS_0);
 }
 
 static ssize_t vfio_pci_msi_cap_size(struct msi_cap_64 *cap_hdr)
@@ -801,6 +866,7 @@ static int vfio_pci_configure_bar(struct kvm *kvm, struct vfio_device *vdev,
 	size_t map_size;
 	struct vfio_pci_device *pdev = &vdev->pci;
 	struct vfio_region *region = &vdev->regions[nr];
+	bool map_now;
 
 	if (nr >= vdev->info.num_regions)
 		return 0;
@@ -840,12 +906,20 @@ static int vfio_pci_configure_bar(struct kvm *kvm, struct vfio_device *vdev,
 		/* Grab some MMIO space in the guest */
 		map_size = ALIGN(region->info.size, PAGE_SIZE);
 		region->guest_phys_addr = pci_get_io_space_block(map_size);
+
+		map_now = pdev->hdr.command & PCI_COMMAND_MEMORY;
+	} else {
+		region->port_base = pci_get_io_port_block(region->info.size);
+
+		map_now = pdev->hdr.command & PCI_COMMAND_IO;
 	}
 
-	/* Map the BARs into the guest or setup a trap region. */
-	ret = vfio_map_region(kvm, vdev, region);
-	if (ret)
-		return ret;
+	if (map_now) {
+		/* Map the BARs into the guest or setup a trap region. */
+		ret = vfio_map_region(kvm, vdev, region);
+		if (ret)
+			return ret;
+	}
 
 	return 0;
 }
-- 
1.9.1

  parent reply	other threads:[~2019-03-07  8:36 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-07  8:36 [PATCH kvmtool 00/16] Support PCI BAR configuration Julien Thierry
2019-03-07  8:36 ` [PATCH kvmtool 01/16] Makefile: Only compile vesa for archs that need it Julien Thierry
2019-04-04 13:43   ` Andre Przywara
2019-03-07  8:36 ` [PATCH kvmtool 02/16] brlock: Always pass argument to br_read_lock/unlock Julien Thierry
2019-04-04 13:43   ` Andre Przywara
2019-03-07  8:36 ` [PATCH kvmtool 03/16] brlock: fix build with KVM_BRLOCK_DEBUG Julien Thierry
2019-04-04 13:43   ` Andre Przywara
2019-03-07  8:36 ` [PATCH kvmtool 04/16] pci: Fix BAR resource sizing arbitration Julien Thierry
2019-04-04 13:44   ` Andre Przywara
2019-03-07  8:36 ` [PATCH kvmtool 05/16] ioport: pci: Move port allocations to PCI devices Julien Thierry
2019-04-04 13:45   ` Andre Przywara
2019-04-30  9:50     ` Julien Thierry
2019-04-30  9:50       ` Julien Thierry
2019-03-07  8:36 ` [PATCH kvmtool 06/16] pci: Fix ioport allocation size Julien Thierry
2019-04-04 13:46   ` Andre Przywara
2019-03-07  8:36 ` [PATCH kvmtool 07/16] arm/pci: Fix PCI IO region Julien Thierry
2019-03-07  8:36 ` [PATCH kvmtool 08/16] arm/pci: Do not use first PCI IO space bytes for devices Julien Thierry
2019-04-05 15:31   ` Andre Przywara
2019-06-14  8:32     ` Julien Thierry
2019-03-07  8:36 ` [PATCH kvmtool 09/16] brlock: Use rwlock instead of pause Julien Thierry
2019-03-07  8:36 ` [PATCH kvmtool 10/16] ref_cnt: Add simple ref counting API Julien Thierry
2019-03-07  8:36 ` [PATCH kvmtool 11/16] mmio: Allow mmio callbacks to be called without locking Julien Thierry
2019-03-07  8:36 ` [PATCH kvmtool 12/16] ioport: Allow ioport " Julien Thierry
2019-03-07  8:36 ` Julien Thierry [this message]
2019-03-07  8:36 ` [PATCH kvmtool 14/16] virtio/pci: Make memory and IO BARs independent Julien Thierry
2019-03-07  8:36 ` [PATCH kvmtool 15/16] virtio/pci: update virtio mapping when PCI BARs are reconfigured Julien Thierry
2019-03-07  8:36 ` [PATCH kvmtool 16/16] arm/fdt: Remove PCI probe only property Julien Thierry
2019-04-26 14:09 ` [PATCH kvmtool 00/16] Support PCI BAR configuration Will Deacon
2019-04-26 14:09   ` Will Deacon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1551947777-13044-14-git-send-email-julien.thierry@arm.com \
    --to=julien.thierry@arm.com \
    --cc=Andre.Przywara@arm.com \
    --cc=Sami.Mujawar@arm.com \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=will.deacon@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).