All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Xu <peterx@redhat.com>
To: kvm@vger.kernel.org
Cc: drjones@redhat.com, rkrcmar@redhat.com, peterx@redhat.com,
	agordeev@redhat.com, jan.kiszka@web.de, pbonzini@redhat.com
Subject: [PATCH kvm-unit-tests v2 15/17] pci: add msi support for 32/64bit address
Date: Wed,  9 Nov 2016 10:10:22 -0500	[thread overview]
Message-ID: <1478704224-20472-16-git-send-email-peterx@redhat.com> (raw)
In-Reply-To: <1478704224-20472-1-git-send-email-peterx@redhat.com>

pci_cap_walk() is provided to allow walk through all the capability bits
for a specific PCI device. If a cap handler is provided, it'll be
triggered if the cap is detected along the cap walk.

MSI cap handler is the first one supported. We can add more cap handler
in the future.

Meanwhile, pci_setup_msi() API is provided to support basic 32/64 bit
address MSI setup.

Reviewed-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
 lib/pci.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/pci.h |  3 +++
 2 files changed, 67 insertions(+)

diff --git a/lib/pci.c b/lib/pci.c
index 971f02e..5b474f2 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -7,6 +7,69 @@
 #include "pci.h"
 #include "asm/pci.h"
 
+typedef void (*pci_cap_handler)(struct pci_dev *dev, int cap_offset);
+
+static void pci_cap_msi_handler(struct pci_dev *dev, int cap_offset)
+{
+	printf("Detected MSI for device 0x%x offset 0x%x\n",
+	       dev->bdf, cap_offset);
+	dev->msi_offset = cap_offset;
+}
+
+static pci_cap_handler cap_handlers[PCI_CAP_ID_MAX + 1] = {
+	[PCI_CAP_ID_MSI] = pci_cap_msi_handler,
+};
+
+void pci_cap_walk(struct pci_dev *dev)
+{
+	uint8_t cap_offset;
+	uint8_t cap_id;
+
+	cap_offset = pci_config_readb(dev->bdf, PCI_CAPABILITY_LIST);
+	while (cap_offset) {
+		cap_id = pci_config_readb(dev->bdf, cap_offset);
+		printf("PCI detected cap 0x%x\n", cap_id);
+		if (cap_handlers[cap_id])
+			cap_handlers[cap_id](dev, cap_offset);
+		cap_offset = pci_config_readb(dev->bdf, cap_offset + 1);
+	}
+}
+
+bool pci_setup_msi(struct pci_dev *dev, uint64_t msi_addr, uint32_t msi_data)
+{
+	uint16_t msi_control;
+	uint16_t offset;
+	pcidevaddr_t addr = dev->bdf;
+
+	assert(dev);
+
+	if (!dev->msi_offset) {
+		printf("MSI: dev 0x%x does not support MSI.\n", addr);
+		return false;
+	}
+
+	offset = dev->msi_offset;
+	msi_control = pci_config_readw(addr, offset + PCI_MSI_FLAGS);
+	pci_config_writel(addr, offset + PCI_MSI_ADDRESS_LO,
+			  msi_addr & 0xffffffff);
+
+	if (msi_control & PCI_MSI_FLAGS_64BIT) {
+		pci_config_writel(addr, offset + PCI_MSI_ADDRESS_HI,
+				  (uint32_t)(msi_addr >> 32));
+		pci_config_writel(addr, offset + PCI_MSI_DATA_64, msi_data);
+		printf("MSI: dev 0x%x init 64bit address: ", addr);
+	} else {
+		pci_config_writel(addr, offset + PCI_MSI_DATA_32, msi_data);
+		printf("MSI: dev 0x%x init 32bit address: ", addr);
+	}
+	printf("addr=0x%lx, data=0x%x\n", msi_addr, msi_data);
+
+	msi_control |= PCI_MSI_FLAGS_ENABLE;
+	pci_config_writew(addr, offset + PCI_MSI_FLAGS, msi_control);
+
+	return true;
+}
+
 void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr)
 {
 	uint16_t val = pci_config_readw(dev->bdf, PCI_COMMAND);
@@ -255,5 +318,6 @@ int pci_enable_defaults(struct pci_dev *dev)
 	pci_scan_bars(dev);
 	/* Enable device DMA operations */
 	pci_cmd_set_clr(dev, PCI_COMMAND_MASTER, 0);
+	pci_cap_walk(dev);
 	return 0;
 }
diff --git a/lib/pci.h b/lib/pci.h
index c4fef98..a5a1454 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -23,13 +23,16 @@ enum {
 
 struct pci_dev {
 	uint16_t bdf;
+	uint16_t msi_offset;
 	phys_addr_t bar[PCI_BAR_NUM];
 };
 
 void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf);
 void pci_scan_bars(struct pci_dev *dev);
 void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr);
+void pci_cap_walk(struct pci_dev *dev);
 int pci_enable_defaults(struct pci_dev *dev);
+bool pci_setup_msi(struct pci_dev *dev, uint64_t msi_addr, uint32_t msi_data);
 
 typedef phys_addr_t iova_t;
 
-- 
2.7.4


  parent reply	other threads:[~2016-11-09 15:10 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-09 15:10 [PATCH kvm-unit-tests v2 00/17] VT-d unit test Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 01/17] x86/asm: add cpu_relax() Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 02/17] libcflat: introduce is_power_of_2() Peter Xu
2016-11-10 18:20   ` Andrew Jones
2016-11-14 20:14     ` Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 03/17] x86: intel-iommu: add vt-d init test Peter Xu
2016-11-10 19:09   ` Andrew Jones
2016-11-14 20:18     ` Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 04/17] libcflat: add IS_ALIGNED() macro, and page sizes Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 05/17] libcflat: moving MIN/MAX here Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 06/17] vm/page: provide PGDIR_OFFSET() macro Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 07/17] pci: introduce struct pci_dev Peter Xu
2016-11-10 19:21   ` Andrew Jones
2016-11-14 20:22     ` Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 08/17] pci: provide pci_scan_bars() Peter Xu
2016-11-10 19:24   ` Andrew Jones
2016-11-14 20:33     ` Peter Xu
2016-11-14 21:18       ` Andrew Jones
2016-11-14 21:27         ` Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 09/17] x86/vmexit: leverage pci_scan_bars() Peter Xu
2016-11-10 19:27   ` Andrew Jones
2016-11-14 20:35     ` Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 10/17] pci: provide pci_cmd_set_clr() Peter Xu
2016-11-10 19:31   ` Andrew Jones
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 11/17] pci: provide pci_enable_defaults() Peter Xu
2016-11-10 19:33   ` Andrew Jones
2016-11-14 20:42     ` Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 12/17] pci: add bdf helpers Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 13/17] pci: edu: introduce pci-edu helpers Peter Xu
2016-11-10 19:45   ` Andrew Jones
2016-11-14 20:48     ` Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 14/17] x86: intel-iommu: add dmar test Peter Xu
2016-11-10 19:53   ` Andrew Jones
2016-11-14 20:54     ` Peter Xu
2016-11-09 15:10 ` Peter Xu [this message]
2016-11-10 20:10   ` [PATCH kvm-unit-tests v2 15/17] pci: add msi support for 32/64bit address Andrew Jones
2016-11-14 20:58     ` Peter Xu
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 16/17] x86: intel-iommu: add IR MSI test Peter Xu
2016-11-10 20:18   ` Andrew Jones
2016-11-09 15:10 ` [PATCH kvm-unit-tests v2 17/17] x86/unittests: add intel-iommu test Peter Xu
2016-11-10 20:21   ` Andrew Jones
2016-11-14 21:07     ` Peter Xu
2016-11-09 15:19 ` [PATCH kvm-unit-tests v2 00/17] VT-d unit test Peter Xu
2016-11-10 20:25 ` Andrew Jones
2016-11-14 21:19   ` Peter Xu

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=1478704224-20472-16-git-send-email-peterx@redhat.com \
    --to=peterx@redhat.com \
    --cc=agordeev@redhat.com \
    --cc=drjones@redhat.com \
    --cc=jan.kiszka@web.de \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=rkrcmar@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.