All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 02/13] libcflat: introduce is_power_of_2()
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

Suggested-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
 lib/libcflat.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lib/libcflat.h b/lib/libcflat.h
index 72b1bf9..038ea1d 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -103,4 +103,9 @@ do {									\
 	}								\
 } while (0)
 
+static inline bool is_power_of_2(unsigned long n)
+{
+	return n && !(n & (n - 1));
+}
+
 #endif
-- 
2.7.4


^ permalink raw reply related

* [PATCH v3 03/13] x86: intel-iommu: add vt-d init test
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

Adding fundamental init test for Intel IOMMU. This includes basic
initialization of Intel IOMMU device, like DMAR (DMA Remapping),
IR (Interrupt Remapping), QI (Queue Invalidation), etc.

Further tests can use vtd_init() to initialize Intel IOMMU environment.

x86/unittests is updated to add this test.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 lib/x86/intel-iommu.c |  88 +++++++++++++++++++++++++++++++++++++
 lib/x86/intel-iommu.h | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++
 x86/Makefile.x86_64   |   2 +
 x86/intel-iommu.c     |  27 ++++++++++++
 x86/unittests.cfg     |   7 +++
 5 files changed, 242 insertions(+)
 create mode 100644 lib/x86/intel-iommu.c
 create mode 100644 lib/x86/intel-iommu.h
 create mode 100644 x86/intel-iommu.c

diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c
new file mode 100644
index 0000000..9890f34
--- /dev/null
+++ b/lib/x86/intel-iommu.c
@@ -0,0 +1,88 @@
+/*
+ * Intel IOMMU APIs
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * Authors:
+ *   Peter Xu <peterx@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or
+ * later.
+ */
+
+#include "intel-iommu.h"
+
+#define VTD_RTA_MASK  (PAGE_MASK)
+#define VTD_IRTA_MASK (PAGE_MASK)
+
+static uint64_t vtd_root_table(void)
+{
+	/* No extend root table support yet */
+	return vtd_readq(DMAR_RTADDR_REG) & VTD_RTA_MASK;
+}
+
+static uint64_t vtd_ir_table(void)
+{
+	return vtd_readq(DMAR_IRTA_REG) & VTD_IRTA_MASK;
+}
+
+static void vtd_gcmd_or(uint32_t cmd)
+{
+	uint32_t status;
+
+	/* We only allow set one bit for each time */
+	assert(is_power_of_2(cmd));
+
+	status = vtd_readl(DMAR_GSTS_REG);
+	vtd_writel(DMAR_GCMD_REG, status | cmd);
+
+	if (cmd & VTD_GCMD_ONE_SHOT_BITS) {
+		/* One-shot bits are taking effect immediately */
+		return;
+	}
+
+	/* Make sure IOMMU handled our command request */
+	while (!(vtd_readl(DMAR_GSTS_REG) & cmd))
+		cpu_relax();
+}
+
+static void vtd_dump_init_info(void)
+{
+	printf("VT-d version:   0x%x\n", vtd_readl(DMAR_VER_REG));
+	printf("     cap:       0x%016lx\n", vtd_readq(DMAR_CAP_REG));
+	printf("     ecap:      0x%016lx\n", vtd_readq(DMAR_ECAP_REG));
+}
+
+static void vtd_setup_root_table(void)
+{
+	void *root = alloc_page();
+
+	memset(root, 0, PAGE_SIZE);
+	vtd_writeq(DMAR_RTADDR_REG, virt_to_phys(root));
+	vtd_gcmd_or(VTD_GCMD_ROOT);
+	printf("DMAR table address: 0x%016lx\n", vtd_root_table());
+}
+
+static void vtd_setup_ir_table(void)
+{
+	void *root = alloc_page();
+
+	memset(root, 0, PAGE_SIZE);
+	/* 0xf stands for table size (2^(0xf+1) == 65536) */
+	vtd_writeq(DMAR_IRTA_REG, virt_to_phys(root) | 0xf);
+	vtd_gcmd_or(VTD_GCMD_IR_TABLE);
+	printf("IR table address: 0x%016lx\n", vtd_ir_table());
+}
+
+void vtd_init(void)
+{
+	setup_vm();
+	smp_init();
+
+	vtd_dump_init_info();
+	vtd_gcmd_or(VTD_GCMD_QI); /* Enable QI */
+	vtd_setup_root_table();
+	vtd_setup_ir_table();
+	vtd_gcmd_or(VTD_GCMD_DMAR); /* Enable DMAR */
+	vtd_gcmd_or(VTD_GCMD_IR);   /* Enable IR */
+}
diff --git a/lib/x86/intel-iommu.h b/lib/x86/intel-iommu.h
new file mode 100644
index 0000000..fae9ae5
--- /dev/null
+++ b/lib/x86/intel-iommu.h
@@ -0,0 +1,118 @@
+/*
+ * Intel IOMMU header
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * Authors:
+ *   Peter Xu <peterx@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or
+ * later.
+ *
+ * (From include/linux/intel-iommu.h)
+ */
+
+#ifndef __INTEL_IOMMU_H__
+#define __INTEL_IOMMU_H__
+
+#include "libcflat.h"
+#include "vm.h"
+#include "isr.h"
+#include "smp.h"
+#include "desc.h"
+#include "asm/io.h"
+
+#define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed90000ULL
+
+/*
+ * Intel IOMMU register specification
+ */
+#define DMAR_VER_REG            0x0  /* Arch version supported by this IOMMU */
+#define DMAR_CAP_REG            0x8  /* Hardware supported capabilities */
+#define DMAR_CAP_REG_HI         0xc  /* High 32-bit of DMAR_CAP_REG */
+#define DMAR_ECAP_REG           0x10 /* Extended capabilities supported */
+#define DMAR_ECAP_REG_HI        0X14
+#define DMAR_GCMD_REG           0x18 /* Global command */
+#define DMAR_GSTS_REG           0x1c /* Global status */
+#define DMAR_RTADDR_REG         0x20 /* Root entry table */
+#define DMAR_RTADDR_REG_HI      0X24
+#define DMAR_CCMD_REG           0x28 /* Context command */
+#define DMAR_CCMD_REG_HI        0x2c
+#define DMAR_FSTS_REG           0x34 /* Fault status */
+#define DMAR_FECTL_REG          0x38 /* Fault control */
+#define DMAR_FEDATA_REG         0x3c /* Fault event interrupt data */
+#define DMAR_FEADDR_REG         0x40 /* Fault event interrupt addr */
+#define DMAR_FEUADDR_REG        0x44 /* Upper address */
+#define DMAR_AFLOG_REG          0x58 /* Advanced fault control */
+#define DMAR_AFLOG_REG_HI       0X5c
+#define DMAR_PMEN_REG           0x64 /* Enable protected memory region */
+#define DMAR_PLMBASE_REG        0x68 /* PMRR low addr */
+#define DMAR_PLMLIMIT_REG       0x6c /* PMRR low limit */
+#define DMAR_PHMBASE_REG        0x70 /* PMRR high base addr */
+#define DMAR_PHMBASE_REG_HI     0X74
+#define DMAR_PHMLIMIT_REG       0x78 /* PMRR high limit */
+#define DMAR_PHMLIMIT_REG_HI    0x7c
+#define DMAR_IQH_REG            0x80 /* Invalidation queue head */
+#define DMAR_IQH_REG_HI         0X84
+#define DMAR_IQT_REG            0x88 /* Invalidation queue tail */
+#define DMAR_IQT_REG_HI         0X8c
+#define DMAR_IQA_REG            0x90 /* Invalidation queue addr */
+#define DMAR_IQA_REG_HI         0x94
+#define DMAR_ICS_REG            0x9c /* Invalidation complete status */
+#define DMAR_IRTA_REG           0xb8 /* Interrupt remapping table addr */
+#define DMAR_IRTA_REG_HI        0xbc
+#define DMAR_IECTL_REG          0xa0 /* Invalidation event control */
+#define DMAR_IEDATA_REG         0xa4 /* Invalidation event data */
+#define DMAR_IEADDR_REG         0xa8 /* Invalidation event address */
+#define DMAR_IEUADDR_REG        0xac /* Invalidation event address */
+#define DMAR_PQH_REG            0xc0 /* Page request queue head */
+#define DMAR_PQH_REG_HI         0xc4
+#define DMAR_PQT_REG            0xc8 /* Page request queue tail*/
+#define DMAR_PQT_REG_HI         0xcc
+#define DMAR_PQA_REG            0xd0 /* Page request queue address */
+#define DMAR_PQA_REG_HI         0xd4
+#define DMAR_PRS_REG            0xdc /* Page request status */
+#define DMAR_PECTL_REG          0xe0 /* Page request event control */
+#define DMAR_PEDATA_REG         0xe4 /* Page request event data */
+#define DMAR_PEADDR_REG         0xe8 /* Page request event address */
+#define DMAR_PEUADDR_REG        0xec /* Page event upper address */
+#define DMAR_MTRRCAP_REG        0x100 /* MTRR capability */
+#define DMAR_MTRRCAP_REG_HI     0x104
+#define DMAR_MTRRDEF_REG        0x108 /* MTRR default type */
+#define DMAR_MTRRDEF_REG_HI     0x10c
+
+#define VTD_GCMD_IR_TABLE       0x1000000
+#define VTD_GCMD_IR             0x2000000
+#define VTD_GCMD_QI             0x4000000
+#define VTD_GCMD_WBF            0x8000000  /* Write Buffer Flush */
+#define VTD_GCMD_SFL            0x20000000 /* Set Fault Log */
+#define VTD_GCMD_ROOT           0x40000000
+#define VTD_GCMD_DMAR           0x80000000
+#define VTD_GCMD_ONE_SHOT_BITS  (VTD_GCMD_IR_TABLE | VTD_GCMD_WBF | \
+				 VTD_GCMD_SFL | VTD_GCMD_ROOT)
+
+#define vtd_reg(reg) ((volatile void *)(Q35_HOST_BRIDGE_IOMMU_ADDR + reg))
+
+static inline void vtd_writel(unsigned int reg, uint32_t value)
+{
+	__raw_writel(value, vtd_reg(reg));
+}
+
+static inline void vtd_writeq(unsigned int reg, uint64_t value)
+{
+	__raw_writeq(value, vtd_reg(reg));
+}
+
+static inline uint32_t vtd_readl(unsigned int reg)
+{
+	return __raw_readl(vtd_reg(reg));
+}
+
+static inline uint64_t vtd_readq(unsigned int reg)
+{
+	return __raw_readq(vtd_reg(reg));
+}
+
+void vtd_init(void);
+
+#endif
diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64
index f82492b..3e2821e 100644
--- a/x86/Makefile.x86_64
+++ b/x86/Makefile.x86_64
@@ -4,6 +4,7 @@ ldarch = elf64-x86-64
 CFLAGS += -mno-red-zone
 
 cflatobjs += lib/x86/setjmp64.o
+cflatobjs += lib/x86/intel-iommu.o
 
 tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
 	  $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \
@@ -14,6 +15,7 @@ tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
 tests += $(TEST_DIR)/svm.flat
 tests += $(TEST_DIR)/vmx.flat
 tests += $(TEST_DIR)/tscdeadline_latency.flat
+tests += $(TEST_DIR)/intel-iommu.flat
 
 include $(TEST_DIR)/Makefile.common
 
diff --git a/x86/intel-iommu.c b/x86/intel-iommu.c
new file mode 100644
index 0000000..f247913
--- /dev/null
+++ b/x86/intel-iommu.c
@@ -0,0 +1,27 @@
+/*
+ * Intel IOMMU unit test.
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * Authors:
+ *   Peter Xu <peterx@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or
+ * later.
+ */
+
+#include "intel-iommu.h"
+
+int main(int argc, char *argv[])
+{
+	vtd_init();
+
+	report("fault status check", vtd_readl(DMAR_FSTS_REG) == 0);
+	report("QI enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_QI);
+	report("DMAR table setup", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_ROOT);
+	report("IR table setup", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR_TABLE);
+	report("DMAR enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_DMAR);
+	report("IR enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR);
+
+	return report_summary();
+}
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index 23395c6..5413838 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -217,3 +217,10 @@ extra_params = -cpu kvm64,hv_time,hv_synic,hv_stimer -device hyperv-testdev
 file = hyperv_clock.flat
 smp = 2
 extra_params = -cpu kvm64,hv_time
+
+[intel_iommu]
+file = intel-iommu.flat
+arch = x86_64
+timeout = 30
+smp = 4
+extra_params = -M q35,kernel-irqchip=split -device intel-iommu,intremap=on,eim=off -device edu
-- 
2.7.4


^ permalink raw reply related

* [PATCH v3 04/13] libcflat: add IS_ALIGNED() macro, and page sizes
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

These macros will be useful to do page alignment checks.

Reviewed-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
 lib/libcflat.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lib/libcflat.h b/lib/libcflat.h
index 038ea1d..d0b0fd1 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -33,6 +33,12 @@
 #define __ALIGN_MASK(x, mask)	(((x) + (mask)) & ~(mask))
 #define __ALIGN(x, a)		__ALIGN_MASK(x, (typeof(x))(a) - 1)
 #define ALIGN(x, a)		__ALIGN((x), (a))
+#define IS_ALIGNED(x, a)	(((x) & ((typeof(x))(a) - 1)) == 0)
+
+#define SZ_4K			0x1000
+#define SZ_64K			0x10000
+#define SZ_2M			0x200000
+#define SZ_1G			0x40000000
 
 typedef uint8_t		u8;
 typedef int8_t		s8;
-- 
2.7.4


^ permalink raw reply related

* [PATCH v3 05/13] libcflat: moving MIN/MAX here
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

That's something can be used outside alloc.c.

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

diff --git a/lib/alloc.c b/lib/alloc.c
index e1d7b8a..58af52b 100644
--- a/lib/alloc.c
+++ b/lib/alloc.c
@@ -7,9 +7,6 @@
 #include "asm/spinlock.h"
 #include "asm/io.h"
 
-#define MIN(a, b)		((a) < (b) ? (a) : (b))
-#define MAX(a, b)		((a) > (b) ? (a) : (b))
-
 #define PHYS_ALLOC_NR_REGIONS	256
 
 struct phys_alloc_region {
diff --git a/lib/libcflat.h b/lib/libcflat.h
index d0b0fd1..79695f6 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -40,6 +40,9 @@
 #define SZ_2M			0x200000
 #define SZ_1G			0x40000000
 
+#define MIN(a, b)		((a) < (b) ? (a) : (b))
+#define MAX(a, b)		((a) > (b) ? (a) : (b))
+
 typedef uint8_t		u8;
 typedef int8_t		s8;
 typedef uint16_t	u16;
-- 
2.7.4


^ permalink raw reply related

* [PATCH v3 06/13] vm/page: provide PGDIR_OFFSET() macro
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

This can be used in further patches.

Reviewed-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
 lib/x86/asm/page.h | 3 +++
 lib/x86/vm.c       | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/x86/asm/page.h b/lib/x86/asm/page.h
index 5044a49..c43bab2 100644
--- a/lib/x86/asm/page.h
+++ b/lib/x86/asm/page.h
@@ -41,5 +41,8 @@
 #define	PGDIR_MASK	1023
 #endif
 
+#define PGDIR_BITS(lvl)        (((lvl) - 1) * PGDIR_WIDTH + PAGE_SHIFT)
+#define PGDIR_OFFSET(va, lvl)  (((va) >> PGDIR_BITS(lvl)) & PGDIR_MASK)
+
 #endif /* !__ASSEMBLY__ */
 #endif
diff --git a/lib/x86/vm.c b/lib/x86/vm.c
index f7e778b..cda4c5f 100644
--- a/lib/x86/vm.c
+++ b/lib/x86/vm.c
@@ -48,7 +48,7 @@ unsigned long *install_pte(unsigned long *cr3,
     unsigned offset;
 
     for (level = PAGE_LEVEL; level > pte_level; --level) {
-	offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & PGDIR_MASK;
+	offset = PGDIR_OFFSET((unsigned long)virt, level);
 	if (!(pt[offset] & PT_PRESENT_MASK)) {
 	    unsigned long *new_pt = pt_page;
             if (!new_pt)
@@ -60,7 +60,7 @@ unsigned long *install_pte(unsigned long *cr3,
 	}
 	pt = phys_to_virt(pt[offset] & PT_ADDR_MASK);
     }
-    offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & PGDIR_MASK;
+    offset = PGDIR_OFFSET((unsigned long)virt, level);
     pt[offset] = pte;
     return &pt[offset];
 }
-- 
2.7.4


^ permalink raw reply related

* [PATCH v3 07/13] pci: introduce struct pci_dev
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

To extend current PCI framework, we need a per-device struct to store
device specific information. Time to have a pci_dev struct. Most of the
current PCI APIs are converted to use this pci_dev object as the first
argument. Currently it only contains one field "bdf", which is the bdf
of current device.

For a few APIs like pci_config_*() ops or pci_find_dev(), I kept the old
interface (use PCI BDF value rather than "struct pci_dev") since they
can be used in a open context that without any specific PCI device.

Reviewed-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
 lib/pci-host-generic.c |  9 +++++---
 lib/pci-testdev.c      | 10 +++++----
 lib/pci.c              | 56 ++++++++++++++++++++++++++++++--------------------
 lib/pci.h              | 24 ++++++++++++++--------
 x86/vmexit.c           | 18 ++++++++--------
 5 files changed, 72 insertions(+), 45 deletions(-)

diff --git a/lib/pci-host-generic.c b/lib/pci-host-generic.c
index 6ac0f15..ea83d72 100644
--- a/lib/pci-host-generic.c
+++ b/lib/pci-host-generic.c
@@ -211,6 +211,7 @@ static bool pci_alloc_resource(pcidevaddr_t dev, int bar_num, u64 *addr)
 
 bool pci_probe(void)
 {
+	struct pci_dev pci_dev;
 	pcidevaddr_t dev;
 	u8 header;
 	u32 cmd;
@@ -225,6 +226,8 @@ bool pci_probe(void)
 		if (!pci_dev_exists(dev))
 			continue;
 
+		pci_dev_init(&pci_dev, dev);
+
 		/* We are only interested in normal PCI devices */
 		header = pci_config_readb(dev, PCI_HEADER_TYPE);
 		if ((header & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_NORMAL)
@@ -236,15 +239,15 @@ bool pci_probe(void)
 			u64 addr;
 
 			if (pci_alloc_resource(dev, i, &addr)) {
-				pci_bar_set_addr(dev, i, addr);
+				pci_bar_set_addr(&pci_dev, i, addr);
 
-				if (pci_bar_is_memory(dev, i))
+				if (pci_bar_is_memory(&pci_dev, i))
 					cmd |= PCI_COMMAND_MEMORY;
 				else
 					cmd |= PCI_COMMAND_IO;
 			}
 
-			if (pci_bar_is64(dev, i))
+			if (pci_bar_is64(&pci_dev, i))
 				i++;
 		}
 
diff --git a/lib/pci-testdev.c b/lib/pci-testdev.c
index ad482d3..7d298e6 100644
--- a/lib/pci-testdev.c
+++ b/lib/pci-testdev.c
@@ -163,9 +163,10 @@ static int pci_testdev_all(struct pci_test_dev_hdr *test,
 
 int pci_testdev(void)
 {
+	struct pci_dev pci_dev;
+	pcidevaddr_t dev;
 	phys_addr_t addr;
 	void __iomem *mem, *io;
-	pcidevaddr_t dev;
 	int nr_tests = 0;
 	bool ret;
 
@@ -175,14 +176,15 @@ int pci_testdev(void)
 		       "check QEMU '-device pci-testdev' parameter\n");
 		return -1;
 	}
+	pci_dev_init(&pci_dev, dev);
 
-	ret = pci_bar_is_valid(dev, 0) && pci_bar_is_valid(dev, 1);
+	ret = pci_bar_is_valid(&pci_dev, 0) && pci_bar_is_valid(&pci_dev, 1);
 	assert(ret);
 
-	addr = pci_bar_get_addr(dev, 0);
+	addr = pci_bar_get_addr(&pci_dev, 0);
 	mem = ioremap(addr, PAGE_SIZE);
 
-	addr = pci_bar_get_addr(dev, 1);
+	addr = pci_bar_get_addr(&pci_dev, 1);
 	io = (void *)(unsigned long)addr;
 
 	nr_tests += pci_testdev_all(mem, &pci_testdev_mem_ops);
diff --git a/lib/pci.c b/lib/pci.c
index 6bd54cb..8f2356d 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -13,12 +13,18 @@ bool pci_dev_exists(pcidevaddr_t dev)
 		pci_config_readw(dev, PCI_DEVICE_ID) != 0xffff);
 }
 
+void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf)
+{
+       memset(dev, 0, sizeof(*dev));
+       dev->bdf = bdf;
+}
+
 /* Scan bus look for a specific device. Only bus 0 scanned for now. */
 pcidevaddr_t pci_find_dev(uint16_t vendor_id, uint16_t device_id)
 {
 	pcidevaddr_t dev;
 
-	for (dev = 0; dev < 256; ++dev) {
+	for (dev = 0; dev < PCI_DEVFN_MAX; ++dev) {
 		if (pci_config_readw(dev, PCI_VENDOR_ID) == vendor_id &&
 		    pci_config_readw(dev, PCI_DEVICE_ID) == device_id)
 			return dev;
@@ -33,12 +39,13 @@ uint32_t pci_bar_mask(uint32_t bar)
 		PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK;
 }
 
-uint32_t pci_bar_get(pcidevaddr_t dev, int bar_num)
+uint32_t pci_bar_get(struct pci_dev *dev, int bar_num)
 {
-	return pci_config_readl(dev, PCI_BASE_ADDRESS_0 + bar_num * 4);
+	return pci_config_readl(dev->bdf, PCI_BASE_ADDRESS_0 +
+				bar_num * 4);
 }
 
-phys_addr_t pci_bar_get_addr(pcidevaddr_t dev, int bar_num)
+phys_addr_t pci_bar_get_addr(struct pci_dev *dev, int bar_num)
 {
 	uint32_t bar = pci_bar_get(dev, bar_num);
 	uint32_t mask = pci_bar_mask(bar);
@@ -47,17 +54,18 @@ phys_addr_t pci_bar_get_addr(pcidevaddr_t dev, int bar_num)
 	if (pci_bar_is64(dev, bar_num))
 		addr |= (uint64_t)pci_bar_get(dev, bar_num + 1) << 32;
 
-	return pci_translate_addr(dev, addr);
+	return pci_translate_addr(dev->bdf, addr);
 }
 
-void pci_bar_set_addr(pcidevaddr_t dev, int bar_num, phys_addr_t addr)
+void pci_bar_set_addr(struct pci_dev *dev, int bar_num, phys_addr_t addr)
 {
 	int off = PCI_BASE_ADDRESS_0 + bar_num * 4;
 
-	pci_config_writel(dev, off, (uint32_t)addr);
+	pci_config_writel(dev->bdf, off, (uint32_t)addr);
 
 	if (pci_bar_is64(dev, bar_num))
-		pci_config_writel(dev, off + 4, (uint32_t)(addr >> 32));
+		pci_config_writel(dev->bdf, off + 4,
+				  (uint32_t)(addr >> 32));
 }
 
 /*
@@ -70,20 +78,21 @@ void pci_bar_set_addr(pcidevaddr_t dev, int bar_num, phys_addr_t addr)
  * The following pci_bar_size_helper() and pci_bar_size() functions
  * implement the algorithm.
  */
-static uint32_t pci_bar_size_helper(pcidevaddr_t dev, int bar_num)
+static uint32_t pci_bar_size_helper(struct pci_dev *dev, int bar_num)
 {
 	int off = PCI_BASE_ADDRESS_0 + bar_num * 4;
+	uint16_t bdf = dev->bdf;
 	uint32_t bar, val;
 
-	bar = pci_config_readl(dev, off);
-	pci_config_writel(dev, off, ~0u);
-	val = pci_config_readl(dev, off);
-	pci_config_writel(dev, off, bar);
+	bar = pci_config_readl(bdf, off);
+	pci_config_writel(bdf, off, ~0u);
+	val = pci_config_readl(bdf, off);
+	pci_config_writel(bdf, off, bar);
 
 	return val;
 }
 
-phys_addr_t pci_bar_size(pcidevaddr_t dev, int bar_num)
+phys_addr_t pci_bar_size(struct pci_dev *dev, int bar_num)
 {
 	uint32_t bar, size;
 
@@ -104,19 +113,19 @@ phys_addr_t pci_bar_size(pcidevaddr_t dev, int bar_num)
 	}
 }
 
-bool pci_bar_is_memory(pcidevaddr_t dev, int bar_num)
+bool pci_bar_is_memory(struct pci_dev *dev, int bar_num)
 {
 	uint32_t bar = pci_bar_get(dev, bar_num);
 
 	return !(bar & PCI_BASE_ADDRESS_SPACE_IO);
 }
 
-bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num)
+bool pci_bar_is_valid(struct pci_dev *dev, int bar_num)
 {
 	return pci_bar_get(dev, bar_num);
 }
 
-bool pci_bar_is64(pcidevaddr_t dev, int bar_num)
+bool pci_bar_is64(struct pci_dev *dev, int bar_num)
 {
 	uint32_t bar = pci_bar_get(dev, bar_num);
 
@@ -127,7 +136,7 @@ bool pci_bar_is64(pcidevaddr_t dev, int bar_num)
 		      PCI_BASE_ADDRESS_MEM_TYPE_64;
 }
 
-void pci_bar_print(pcidevaddr_t dev, int bar_num)
+void pci_bar_print(struct pci_dev *dev, int bar_num)
 {
 	phys_addr_t size, start, end;
 	uint32_t bar;
@@ -186,8 +195,11 @@ static void pci_dev_print(pcidevaddr_t dev)
 	uint8_t progif = pci_config_readb(dev, PCI_CLASS_PROG);
 	uint8_t subclass = pci_config_readb(dev, PCI_CLASS_DEVICE);
 	uint8_t class = pci_config_readb(dev, PCI_CLASS_DEVICE + 1);
+	struct pci_dev pci_dev;
 	int i;
 
+	pci_dev_init(&pci_dev, dev);
+
 	pci_dev_print_id(dev);
 	printf(" type %02x progif %02x class %02x subclass %02x\n",
 	       header, progif, class, subclass);
@@ -196,12 +208,12 @@ static void pci_dev_print(pcidevaddr_t dev)
 		return;
 
 	for (i = 0; i < 6; i++) {
-		if (pci_bar_size(dev, i)) {
+		if (pci_bar_size(&pci_dev, i)) {
 			printf("\t");
-			pci_bar_print(dev, i);
+			pci_bar_print(&pci_dev, i);
 			printf("\n");
 		}
-		if (pci_bar_is64(dev, i))
+		if (pci_bar_is64(&pci_dev, i))
 			i++;
 	}
 }
@@ -210,7 +222,7 @@ void pci_print(void)
 {
 	pcidevaddr_t dev;
 
-	for (dev = 0; dev < 256; ++dev) {
+	for (dev = 0; dev < PCI_DEVFN_MAX; ++dev) {
 		if (pci_dev_exists(dev))
 			pci_dev_print(dev);
 	}
diff --git a/lib/pci.h b/lib/pci.h
index 30f5381..d7140dd 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -15,6 +15,14 @@ enum {
 	PCIDEVADDR_INVALID = 0xffff,
 };
 
+#define PCI_DEVFN_MAX                   256
+
+struct pci_dev {
+	uint16_t bdf;
+};
+
+void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf);
+
 extern bool pci_probe(void);
 extern void pci_print(void);
 extern bool pci_dev_exists(pcidevaddr_t dev);
@@ -32,15 +40,15 @@ extern pcidevaddr_t pci_find_dev(uint16_t vendor_id, uint16_t device_id);
  * It is expected the caller is aware of the device BAR layout and never
  * tries to address the middle of a 64-bit register.
  */
-extern phys_addr_t pci_bar_get_addr(pcidevaddr_t dev, int bar_num);
-extern void pci_bar_set_addr(pcidevaddr_t dev, int bar_num, phys_addr_t addr);
-extern phys_addr_t pci_bar_size(pcidevaddr_t dev, int bar_num);
-extern uint32_t pci_bar_get(pcidevaddr_t dev, int bar_num);
+extern phys_addr_t pci_bar_get_addr(struct pci_dev *dev, int bar_num);
+extern void pci_bar_set_addr(struct pci_dev *dev, int bar_num, phys_addr_t addr);
+extern phys_addr_t pci_bar_size(struct pci_dev *dev, int bar_num);
+extern uint32_t pci_bar_get(struct pci_dev *dev, int bar_num);
 extern uint32_t pci_bar_mask(uint32_t bar);
-extern bool pci_bar_is64(pcidevaddr_t dev, int bar_num);
-extern bool pci_bar_is_memory(pcidevaddr_t dev, int bar_num);
-extern bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num);
-extern void pci_bar_print(pcidevaddr_t dev, int bar_num);
+extern bool pci_bar_is64(struct pci_dev *dev, int bar_num);
+extern bool pci_bar_is_memory(struct pci_dev *dev, int bar_num);
+extern bool pci_bar_is_valid(struct pci_dev *dev, int bar_num);
+extern void pci_bar_print(struct pci_dev *dev, int bar_num);
 extern void pci_dev_print_id(pcidevaddr_t dev);
 
 int pci_testdev(void);
diff --git a/x86/vmexit.c b/x86/vmexit.c
index 2d99d5f..63fa070 100644
--- a/x86/vmexit.c
+++ b/x86/vmexit.c
@@ -372,7 +372,8 @@ int main(int ac, char **av)
 	struct fadt_descriptor_rev1 *fadt;
 	int i;
 	unsigned long membar = 0;
-	pcidevaddr_t pcidev;
+	struct pci_dev pcidev;
+	int ret;
 
 	smp_init();
 	setup_vm();
@@ -385,21 +386,22 @@ int main(int ac, char **av)
 	pm_tmr_blk = fadt->pm_tmr_blk;
 	printf("PM timer port is %x\n", pm_tmr_blk);
 
-	pcidev = pci_find_dev(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_TEST);
-	if (pcidev != PCIDEVADDR_INVALID) {
+	ret = pci_find_dev(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_TEST);
+	if (ret != PCIDEVADDR_INVALID) {
+		pci_dev_init(&pcidev, ret);
 		for (i = 0; i < PCI_TESTDEV_NUM_BARS; i++) {
-			if (!pci_bar_is_valid(pcidev, i)) {
+			if (!pci_bar_is_valid(&pcidev, i)) {
 				continue;
 			}
-			if (pci_bar_is_memory(pcidev, i)) {
-				membar = pci_bar_get_addr(pcidev, i);
+			if (pci_bar_is_memory(&pcidev, i)) {
+				membar = pci_bar_get_addr(&pcidev, i);
 				pci_test.memaddr = ioremap(membar, PAGE_SIZE);
 			} else {
-				pci_test.iobar = pci_bar_get_addr(pcidev, i);
+				pci_test.iobar = pci_bar_get_addr(&pcidev, i);
 			}
 		}
 		printf("pci-testdev at 0x%x membar %lx iobar %x\n",
-		       pcidev, membar, pci_test.iobar);
+		       pcidev.bdf, membar, pci_test.iobar);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(tests); ++i)
-- 
2.7.4


^ permalink raw reply related

* [PATCH v3 08/13] pci: provide pci_scan_bars()
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

Let's provide a more general way to scan PCI bars, rather than read the
config registers every time.

Then let x86/vmexit.c leverage pci_scan_bars()

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 lib/pci.c    | 17 ++++++++++++++++-
 lib/pci.h    |  5 +++++
 x86/vmexit.c | 17 ++++++-----------
 3 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/lib/pci.c b/lib/pci.c
index 8f2356d..462c370 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -207,7 +207,7 @@ static void pci_dev_print(pcidevaddr_t dev)
 	if ((header & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_NORMAL)
 		return;
 
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < PCI_BAR_NUM; i++) {
 		if (pci_bar_size(&pci_dev, i)) {
 			printf("\t");
 			pci_bar_print(&pci_dev, i);
@@ -227,3 +227,18 @@ void pci_print(void)
 			pci_dev_print(dev);
 	}
 }
+
+void pci_scan_bars(struct pci_dev *dev)
+{
+	int i;
+
+	for (i = 0; i < PCI_BAR_NUM; i++) {
+		if (!pci_bar_is_valid(dev, i))
+			continue;
+		dev->bar[i] = pci_bar_get_addr(dev, i);
+		if (pci_bar_is64(dev, i)) {
+			i++;
+			dev->bar[i] = (phys_addr_t)0;
+		}
+	}
+}
diff --git a/lib/pci.h b/lib/pci.h
index d7140dd..338ad51 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -15,13 +15,16 @@ enum {
 	PCIDEVADDR_INVALID = 0xffff,
 };
 
+#define PCI_BAR_NUM                     6
 #define PCI_DEVFN_MAX                   256
 
 struct pci_dev {
 	uint16_t bdf;
+	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);
 
 extern bool pci_probe(void);
 extern void pci_print(void);
@@ -65,6 +68,8 @@ int pci_testdev(void);
  * pci-testdev supports at least three types of tests (via mmio and
  * portio BARs): no-eventfd, wildcard-eventfd and datamatch-eventfd
  */
+#define PCI_TESTDEV_BAR_MEM		0
+#define PCI_TESTDEV_BAR_IO		1
 #define PCI_TESTDEV_NUM_BARS		2
 #define PCI_TESTDEV_NUM_TESTS		3
 
diff --git a/x86/vmexit.c b/x86/vmexit.c
index 63fa070..a22f43f 100644
--- a/x86/vmexit.c
+++ b/x86/vmexit.c
@@ -389,17 +389,12 @@ int main(int ac, char **av)
 	ret = pci_find_dev(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_TEST);
 	if (ret != PCIDEVADDR_INVALID) {
 		pci_dev_init(&pcidev, ret);
-		for (i = 0; i < PCI_TESTDEV_NUM_BARS; i++) {
-			if (!pci_bar_is_valid(&pcidev, i)) {
-				continue;
-			}
-			if (pci_bar_is_memory(&pcidev, i)) {
-				membar = pci_bar_get_addr(&pcidev, i);
-				pci_test.memaddr = ioremap(membar, PAGE_SIZE);
-			} else {
-				pci_test.iobar = pci_bar_get_addr(&pcidev, i);
-			}
-		}
+		pci_scan_bars(&pcidev);
+		assert(pci_bar_is_memory(&pcidev, PCI_TESTDEV_BAR_MEM));
+		assert(!pci_bar_is_memory(&pcidev, PCI_TESTDEV_BAR_IO));
+		membar = pcidev.bar[PCI_TESTDEV_BAR_MEM];
+		pci_test.memaddr = ioremap(membar, PAGE_SIZE);
+		pci_test.iobar = pcidev.bar[PCI_TESTDEV_BAR_IO];
 		printf("pci-testdev at 0x%x membar %lx iobar %x\n",
 		       pcidev.bdf, membar, pci_test.iobar);
 	}
-- 
2.7.4


^ permalink raw reply related

* [PATCH v3 09/13] pci: provide pci_enable_defaults()
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

One helper function to set/clear specific bit in PCI_COMMAND register is
introduced. Then, provide a function to do most of the common PCI init
work.

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

diff --git a/lib/pci.c b/lib/pci.c
index 462c370..1c59e13 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -7,6 +7,18 @@
 #include "pci.h"
 #include "asm/pci.h"
 
+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);
+
+	/* No overlap is allowed */
+	assert((set & clr) == 0);
+	val |= set;
+	val &= ~clr;
+
+	pci_config_writew(dev->bdf, PCI_COMMAND, val);
+}
+
 bool pci_dev_exists(pcidevaddr_t dev)
 {
 	return (pci_config_readw(dev, PCI_VENDOR_ID) != 0xffff &&
@@ -242,3 +254,10 @@ void pci_scan_bars(struct pci_dev *dev)
 		}
 	}
 }
+
+void pci_enable_defaults(struct pci_dev *dev)
+{
+	pci_scan_bars(dev);
+	/* Enable device DMA operations */
+	pci_cmd_set_clr(dev, PCI_COMMAND_MASTER, 0);
+}
diff --git a/lib/pci.h b/lib/pci.h
index 338ad51..1e7be27 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -25,6 +25,8 @@ struct pci_dev {
 
 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_enable_defaults(struct pci_dev *dev);
 
 extern bool pci_probe(void);
 extern void pci_print(void);
-- 
2.7.4


^ permalink raw reply related

* [PATCH v3 10/13] pci: edu: introduce pci-edu helpers
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

QEMU edu device is a pci device that is originally written for
educational purpose, however it also suits for IOMMU unit test. Adding
helpers for this specific device to implement the device logic.

The device supports lots of functions, here only DMA operation is
supported.

The spec of the device can be found at:

  https://github.com/qemu/qemu/blob/master/docs/specs/edu.txt

Reviewed-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
 lib/pci-edu.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/pci-edu.h | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 155 insertions(+)
 create mode 100644 lib/pci-edu.c
 create mode 100644 lib/pci-edu.h

diff --git a/lib/pci-edu.c b/lib/pci-edu.c
new file mode 100644
index 0000000..c9a8b0c
--- /dev/null
+++ b/lib/pci-edu.c
@@ -0,0 +1,73 @@
+/*
+ * Edu PCI device.
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * Authors:
+ *   Peter Xu <peterx@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or
+ * later.
+ */
+
+#include "pci-edu.h"
+#include "asm/barrier.h"
+
+/* Return true if alive */
+static inline bool edu_check_alive(struct pci_edu_dev *dev)
+{
+	static uint32_t live_count = 1;
+	uint32_t value;
+
+	edu_reg_writel(dev, EDU_REG_ALIVE, live_count++);
+	value = edu_reg_readl(dev, EDU_REG_ALIVE);
+	return (live_count - 1 == ~value);
+}
+
+bool edu_init(struct pci_edu_dev *dev)
+{
+	pcidevaddr_t dev_addr;
+
+	dev_addr = pci_find_dev(PCI_VENDOR_ID_QEMU, PCI_DEVICE_ID_EDU);
+	if (dev_addr == PCIDEVADDR_INVALID)
+		return false;
+
+	pci_dev_init(&dev->pci_dev, dev_addr);
+	pci_enable_defaults(&dev->pci_dev);
+	assert(edu_check_alive(dev));
+	return true;
+}
+
+void edu_dma(struct pci_edu_dev *dev, iova_t iova,
+	     size_t size, int dev_offset, bool from_device)
+{
+	uint64_t from, to;
+	uint32_t cmd = EDU_CMD_DMA_START;
+
+	assert(size <= EDU_DMA_SIZE_MAX);
+	assert(dev_offset < EDU_DMA_SIZE_MAX &&
+	       dev_offset >= 0);
+
+	printf("edu device DMA start %s addr %p size 0x%lu off 0x%x\n",
+	       from_device ? "FROM" : "TO",
+	       (void *)iova, size, dev_offset);
+
+	if (from_device) {
+		from = dev_offset + EDU_DMA_START;
+		to = iova;
+		cmd |= EDU_CMD_DMA_FROM;
+	} else {
+		from = iova;
+		to = EDU_DMA_START + dev_offset;
+		cmd |= EDU_CMD_DMA_TO;
+	}
+
+	edu_reg_writeq(dev, EDU_REG_DMA_SRC, from);
+	edu_reg_writeq(dev, EDU_REG_DMA_DST, to);
+	edu_reg_writeq(dev, EDU_REG_DMA_COUNT, size);
+	edu_reg_writel(dev, EDU_REG_DMA_CMD, cmd);
+
+	/* Wait until DMA finished */
+	while (edu_reg_readl(dev, EDU_REG_DMA_CMD) & EDU_CMD_DMA_START)
+		cpu_relax();
+}
diff --git a/lib/pci-edu.h b/lib/pci-edu.h
new file mode 100644
index 0000000..b3a6e2b
--- /dev/null
+++ b/lib/pci-edu.h
@@ -0,0 +1,82 @@
+/*
+ * Edu PCI device header.
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * Authors:
+ *   Peter Xu <peterx@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or
+ * later.
+ *
+ * Edu device is a virtualized device in QEMU. Please refer to
+ * docs/specs/edu.txt in QEMU repository for EDU device manual.
+ */
+#ifndef __PCI_EDU_H__
+#define __PCI_EDU_H__
+
+#include "pci.h"
+#include "asm/io.h"
+
+#define  PCI_VENDOR_ID_QEMU              0x1234
+#define  PCI_DEVICE_ID_EDU               0x11e8
+
+/* The only bar used by EDU device */
+#define EDU_BAR_MEM                 0
+#define EDU_MAGIC                   0xed
+#define EDU_VERSION                 0x100
+#define EDU_DMA_BUF_SIZE            (1 << 20)
+#define EDU_INPUT_BUF_SIZE          256
+
+#define EDU_REG_ID                  0x0
+#define EDU_REG_ALIVE               0x4
+#define EDU_REG_FACTORIAL           0x8
+#define EDU_REG_STATUS              0x20
+#define EDU_REG_DMA_SRC             0x80
+#define EDU_REG_DMA_DST             0x88
+#define EDU_REG_DMA_COUNT           0x90
+#define EDU_REG_DMA_CMD             0x98
+
+#define EDU_CMD_DMA_START           0x01
+#define EDU_CMD_DMA_FROM            0x02
+#define EDU_CMD_DMA_TO              0x00
+
+#define EDU_STATUS_FACTORIAL        0x1
+#define EDU_STATUS_INT_ENABLE       0x80
+
+#define EDU_DMA_START               0x40000
+#define EDU_DMA_SIZE_MAX            4096
+
+struct pci_edu_dev {
+	struct pci_dev pci_dev;
+};
+
+#define edu_reg(d, r) (volatile void *)((d)->pci_dev.bar[EDU_BAR_MEM] + (r))
+
+static inline uint64_t edu_reg_readq(struct pci_edu_dev *dev, int reg)
+{
+	return __raw_readq(edu_reg(dev, reg));
+}
+
+static inline uint32_t edu_reg_readl(struct pci_edu_dev *dev, int reg)
+{
+	return __raw_readl(edu_reg(dev, reg));
+}
+
+static inline void edu_reg_writeq(struct pci_edu_dev *dev, int reg,
+				  uint64_t val)
+{
+	__raw_writeq(val, edu_reg(dev, reg));
+}
+
+static inline void edu_reg_writel(struct pci_edu_dev *dev, int reg,
+				  uint32_t val)
+{
+	__raw_writel(val, edu_reg(dev, reg));
+}
+
+bool edu_init(struct pci_edu_dev *dev);
+void edu_dma(struct pci_edu_dev *dev, iova_t iova,
+	     size_t size, int dev_offset, bool from_device);
+
+#endif
-- 
2.7.4


^ permalink raw reply related

* [PATCH v3 12/13] pci: add msi support for 32/64bit address
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-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 | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/pci.h |  3 +++
 2 files changed, 68 insertions(+)

diff --git a/lib/pci.c b/lib/pci.c
index 1c59e13..4eb5574 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -7,6 +7,70 @@
 #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;
+
+	assert(dev);
+
+	if (!dev->msi_offset) {
+		printf("MSI: dev 0x%x does not support MSI.\n", dev->bdf);
+		return false;
+	}
+
+	addr = dev->bdf;
+	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);
@@ -260,4 +324,5 @@ void 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);
 }
diff --git a/lib/pci.h b/lib/pci.h
index a2002ad..221db2f 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);
 void 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


^ permalink raw reply related

* [PATCH v3 11/13] x86: intel-iommu: add dmar test
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

DMAR test is based on QEMU edu device. A 4B DMA memory copy is carried
out as the simplest DMAR test.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 lib/pci.h             |   5 ++
 lib/x86/intel-iommu.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/x86/intel-iommu.h |  23 +++++++++
 x86/Makefile.common   |   1 +
 x86/intel-iommu.c     |  51 ++++++++++++++++++++
 5 files changed, 211 insertions(+)

diff --git a/lib/pci.h b/lib/pci.h
index 1e7be27..a2002ad 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -18,6 +18,9 @@ enum {
 #define PCI_BAR_NUM                     6
 #define PCI_DEVFN_MAX                   256
 
+#define PCI_BDF_GET_DEVFN(x)            ((x) & 0xff)
+#define PCI_BDF_GET_BUS(x)              (((x) >> 8) & 0xff)
+
 struct pci_dev {
 	uint16_t bdf;
 	phys_addr_t bar[PCI_BAR_NUM];
@@ -28,6 +31,8 @@ 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_enable_defaults(struct pci_dev *dev);
 
+typedef phys_addr_t iova_t;
+
 extern bool pci_probe(void);
 extern void pci_print(void);
 extern bool pci_dev_exists(pcidevaddr_t dev);
diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c
index 9890f34..c1b6164 100644
--- a/lib/x86/intel-iommu.c
+++ b/lib/x86/intel-iommu.c
@@ -11,6 +11,42 @@
  */
 
 #include "intel-iommu.h"
+#include "libcflat.h"
+
+/*
+ * VT-d in QEMU currently only support 39 bits address width, which is
+ * 3-level translation.
+ */
+#define VTD_PAGE_LEVEL      3
+#define VTD_CE_AW_39BIT     0x1
+
+typedef uint64_t vtd_pte_t;
+
+struct vtd_root_entry {
+	/* Quad 1 */
+	uint64_t present:1;
+	uint64_t __reserved:11;
+	uint64_t context_table_p:52;
+	/* Quad 2 */
+	uint64_t __reserved_2;
+} __attribute__ ((packed));
+typedef struct vtd_root_entry vtd_re_t;
+
+struct vtd_context_entry {
+	/* Quad 1 */
+	uint64_t present:1;
+	uint64_t disable_fault_report:1;
+	uint64_t trans_type:2;
+	uint64_t __reserved:8;
+	uint64_t slptptr:52;
+	/* Quad 2 */
+	uint64_t addr_width:3;
+	uint64_t __ignore:4;
+	uint64_t __reserved_2:1;
+	uint64_t domain_id:16;
+	uint64_t __reserved_3:40;
+} __attribute__ ((packed));
+typedef struct vtd_context_entry vtd_ce_t;
 
 #define VTD_RTA_MASK  (PAGE_MASK)
 #define VTD_IRTA_MASK (PAGE_MASK)
@@ -74,6 +110,101 @@ static void vtd_setup_ir_table(void)
 	printf("IR table address: 0x%016lx\n", vtd_ir_table());
 }
 
+static void vtd_install_pte(vtd_pte_t *root, iova_t iova,
+			    phys_addr_t pa, int level_target)
+{
+	int level;
+	unsigned int offset;
+	void *page;
+
+	for (level = VTD_PAGE_LEVEL; level > level_target; level--) {
+		offset = PGDIR_OFFSET(iova, level);
+		if (!(root[offset] & VTD_PTE_RW)) {
+			page = alloc_page();
+			memset(page, 0, PAGE_SIZE);
+			root[offset] = virt_to_phys(page) | VTD_PTE_RW;
+		}
+		root = (uint64_t *)(root[offset] & VTD_PTE_ADDR);
+	}
+
+	offset = PGDIR_OFFSET(iova, level);
+	root[offset] = pa | VTD_PTE_RW;
+	if (level != 1)
+		/* This is huge page */
+		root[offset] |= VTD_PTE_HUGE;
+}
+
+#define  VTD_FETCH_VIRT_ADDR(x) \
+	((void *)(((uint64_t)phys_to_virt(x)) >> PAGE_SHIFT))
+
+/**
+ * vtd_map_range: setup IO address mapping for specific memory range
+ *
+ * @sid: source ID of the device to setup
+ * @iova: start IO virtual address
+ * @pa: start physical address
+ * @size: size of the mapping area
+ */
+void vtd_map_range(uint16_t sid, iova_t iova, phys_addr_t pa, size_t size)
+{
+	uint8_t bus_n, devfn;
+	void *slptptr;
+	vtd_ce_t *ce;
+	vtd_re_t *re = phys_to_virt(vtd_root_table());
+
+	assert(IS_ALIGNED(iova, SZ_4K));
+	assert(IS_ALIGNED(pa, SZ_4K));
+	assert(IS_ALIGNED(size, SZ_4K));
+
+	bus_n = PCI_BDF_GET_BUS(sid);
+	devfn = PCI_BDF_GET_DEVFN(sid);
+
+	/* Point to the correct root entry */
+	re += bus_n;
+
+	if (!re->present) {
+		ce = alloc_page();
+		memset(ce, 0, PAGE_SIZE);
+		memset(re, 0, sizeof(*re));
+		re->context_table_p = virt_to_phys(ce) >> PAGE_SHIFT;
+		re->present = 1;
+		printf("allocated vt-d root entry for PCI bus %d\n",
+		       bus_n);
+	} else
+		ce = VTD_FETCH_VIRT_ADDR(re->context_table_p);
+
+	/* Point to the correct context entry */
+	ce += devfn;
+
+	if (!ce->present) {
+		slptptr = alloc_page();
+		memset(slptptr, 0, PAGE_SIZE);
+		memset(ce, 0, sizeof(*ce));
+		/* To make it simple, domain ID is the same as SID */
+		ce->domain_id = sid;
+		/* We only test 39 bits width case (3-level paging) */
+		ce->addr_width = VTD_CE_AW_39BIT;
+		ce->slptptr = virt_to_phys(slptptr) >> PAGE_SHIFT;
+		ce->trans_type = VTD_CONTEXT_TT_MULTI_LEVEL;
+		ce->present = 1;
+		/* No error reporting yet */
+		ce->disable_fault_report = 1;
+		printf("allocated vt-d context entry for devfn 0x%x\n",
+		       devfn);
+	} else
+		slptptr = VTD_FETCH_VIRT_ADDR(ce->slptptr);
+
+	while (size) {
+		/* TODO: currently we only map 4K pages (level = 1) */
+		printf("map 4K page IOVA 0x%lx to 0x%lx (sid=0x%04x)\n",
+		       iova, pa, sid);
+		vtd_install_pte(slptptr, iova, pa, 1);
+		size -= PAGE_SIZE;
+		iova += PAGE_SIZE;
+		pa += PAGE_SIZE;
+	}
+}
+
 void vtd_init(void)
 {
 	setup_vm();
diff --git a/lib/x86/intel-iommu.h b/lib/x86/intel-iommu.h
index fae9ae5..1352639 100644
--- a/lib/x86/intel-iommu.h
+++ b/lib/x86/intel-iommu.h
@@ -20,6 +20,7 @@
 #include "isr.h"
 #include "smp.h"
 #include "desc.h"
+#include "pci.h"
 #include "asm/io.h"
 
 #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed90000ULL
@@ -91,6 +92,27 @@
 #define VTD_GCMD_ONE_SHOT_BITS  (VTD_GCMD_IR_TABLE | VTD_GCMD_WBF | \
 				 VTD_GCMD_SFL | VTD_GCMD_ROOT)
 
+/* Supported Adjusted Guest Address Widths */
+#define VTD_CAP_SAGAW_SHIFT         8
+/* 39-bit AGAW, 3-level page-table */
+#define VTD_CAP_SAGAW_39bit         (0x2ULL << VTD_CAP_SAGAW_SHIFT)
+/* 48-bit AGAW, 4-level page-table */
+#define VTD_CAP_SAGAW_48bit         (0x4ULL << VTD_CAP_SAGAW_SHIFT)
+#define VTD_CAP_SAGAW               VTD_CAP_SAGAW_39bit
+
+/* Both 1G/2M huge pages */
+#define VTD_CAP_SLLPS               ((1ULL << 34) | (1ULL << 35))
+
+#define VTD_CONTEXT_TT_MULTI_LEVEL  0
+#define VTD_CONTEXT_TT_DEV_IOTLB    1
+#define VTD_CONTEXT_TT_PASS_THROUGH 2
+
+#define VTD_PTE_R                   (1 << 0)
+#define VTD_PTE_W                   (1 << 1)
+#define VTD_PTE_RW                  (VTD_PTE_R | VTD_PTE_W)
+#define VTD_PTE_ADDR                GENMASK_ULL(51, 12)
+#define VTD_PTE_HUGE                (1 << 7)
+
 #define vtd_reg(reg) ((volatile void *)(Q35_HOST_BRIDGE_IOMMU_ADDR + reg))
 
 static inline void vtd_writel(unsigned int reg, uint32_t value)
@@ -114,5 +136,6 @@ static inline uint64_t vtd_readq(unsigned int reg)
 }
 
 void vtd_init(void);
+void vtd_map_range(uint16_t sid, phys_addr_t iova, phys_addr_t pa, size_t size);
 
 #endif
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 356d879..1dad18b 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -3,6 +3,7 @@
 all: test_cases
 
 cflatobjs += lib/pci.o
+cflatobjs += lib/pci-edu.o
 cflatobjs += lib/x86/io.o
 cflatobjs += lib/x86/smp.o
 cflatobjs += lib/x86/vm.o
diff --git a/x86/intel-iommu.c b/x86/intel-iommu.c
index f247913..21fd57f 100644
--- a/x86/intel-iommu.c
+++ b/x86/intel-iommu.c
@@ -11,9 +11,50 @@
  */
 
 #include "intel-iommu.h"
+#include "pci-edu.h"
+
+#define VTD_TEST_DMAR_4B ("DMAR 4B memcpy test")
+
+void vtd_test_dmar(struct pci_edu_dev *dev)
+{
+	void *page = alloc_page();
+
+#define DMA_TEST_WORD (0x12345678)
+	/* Modify the first 4 bytes of the page */
+	*(uint32_t *)page = DMA_TEST_WORD;
+
+	/*
+	 * Map the newly allocated page into IOVA address 0 (size 4K)
+	 * of the device address space. Root entry and context entry
+	 * will be automatically created when needed.
+	 */
+	vtd_map_range(dev->pci_dev.bdf, 0, virt_to_phys(page), PAGE_SIZE);
+
+	/*
+	 * DMA the first 4 bytes of the page to EDU device buffer
+	 * offset 0.
+	 */
+	edu_dma(dev, 0, 4, 0, false);
+
+	/*
+	 * DMA the first 4 bytes of EDU device buffer into the page
+	 * with offset 4 (so it'll be using 4-7 bytes).
+	 */
+	edu_dma(dev, 4, 4, 0, true);
+
+	/*
+	 * Check data match between 0-3 bytes and 4-7 bytes of the
+	 * page.
+	 */
+	report(VTD_TEST_DMAR_4B, *((uint32_t *)page + 1) == DMA_TEST_WORD);
+
+	free_page(page);
+}
 
 int main(int argc, char *argv[])
 {
+	struct pci_edu_dev dev;
+
 	vtd_init();
 
 	report("fault status check", vtd_readl(DMAR_FSTS_REG) == 0);
@@ -22,6 +63,16 @@ int main(int argc, char *argv[])
 	report("IR table setup", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR_TABLE);
 	report("DMAR enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_DMAR);
 	report("IR enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR);
+	report("DMAR support 39 bits address width",
+	       vtd_readq(DMAR_CAP_REG) & VTD_CAP_SAGAW);
+	report("DMAR support huge pages", vtd_readq(DMAR_CAP_REG) & VTD_CAP_SLLPS);
+
+	if (!edu_init(&dev)) {
+		printf("Please specify \"-device edu\" to do "
+		       "further IOMMU tests.\n");
+		report_skip(VTD_TEST_DMAR_4B);
+	} else
+		vtd_test_dmar(&dev);
 
 	return report_summary();
 }
-- 
2.7.4


^ permalink raw reply related

* [PATCH v3 13/13] x86: intel-iommu: add IR MSI test
From: Peter Xu @ 2016-11-14 22:28 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini, peterx
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

First of all, vtd_setup_msi() is provided. It setup IRTE entries,
meanwhile, setup PCI device MSI vectors corresponding to VT-d spec.

Meanwhile, IR MSI test is added to intel IOMMU unit test. The basic IR
test is carried out by a edu INTR raise request. When write to the intr
raise register, interrupt will be generated. Type of interrupt will
depend on the setup (either INTx or MSI).

Suggested-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
 lib/pci-edu.h         |  1 +
 lib/x86/intel-iommu.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/x86/intel-iommu.h |  1 +
 x86/intel-iommu.c     | 44 +++++++++++++++++++++++-
 4 files changed, 139 insertions(+), 1 deletion(-)

diff --git a/lib/pci-edu.h b/lib/pci-edu.h
index b3a6e2b..a87219a 100644
--- a/lib/pci-edu.h
+++ b/lib/pci-edu.h
@@ -32,6 +32,7 @@
 #define EDU_REG_ALIVE               0x4
 #define EDU_REG_FACTORIAL           0x8
 #define EDU_REG_STATUS              0x20
+#define EDU_REG_INTR_RAISE          0x60
 #define EDU_REG_DMA_SRC             0x80
 #define EDU_REG_DMA_DST             0x88
 #define EDU_REG_DMA_COUNT           0x90
diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c
index c1b6164..9f1acea 100644
--- a/lib/x86/intel-iommu.c
+++ b/lib/x86/intel-iommu.c
@@ -12,6 +12,7 @@
 
 #include "intel-iommu.h"
 #include "libcflat.h"
+#include "pci.h"
 
 /*
  * VT-d in QEMU currently only support 39 bits address width, which is
@@ -48,6 +49,26 @@ struct vtd_context_entry {
 } __attribute__ ((packed));
 typedef struct vtd_context_entry vtd_ce_t;
 
+struct vtd_irte {
+	uint32_t present:1;
+	uint32_t fault_disable:1;    /* Fault Processing Disable */
+	uint32_t dest_mode:1;        /* Destination Mode */
+	uint32_t redir_hint:1;       /* Redirection Hint */
+	uint32_t trigger_mode:1;     /* Trigger Mode */
+	uint32_t delivery_mode:3;    /* Delivery Mode */
+	uint32_t __avail:4;          /* Available spaces for software */
+	uint32_t __reserved_0:3;     /* Reserved 0 */
+	uint32_t irte_mode:1;        /* IRTE Mode */
+	uint32_t vector:8;           /* Interrupt Vector */
+	uint32_t __reserved_1:8;     /* Reserved 1 */
+	uint32_t dest_id;            /* Destination ID */
+	uint16_t source_id:16;       /* Source-ID */
+	uint64_t sid_q:2;            /* Source-ID Qualifier */
+	uint64_t sid_vtype:2;        /* Source-ID Validation Type */
+	uint64_t __reserved_2:44;    /* Reserved 2 */
+} __attribute__ ((packed));
+typedef struct vtd_irte vtd_irte_t;
+
 #define VTD_RTA_MASK  (PAGE_MASK)
 #define VTD_IRTA_MASK (PAGE_MASK)
 
@@ -205,6 +226,79 @@ void vtd_map_range(uint16_t sid, iova_t iova, phys_addr_t pa, size_t size)
 	}
 }
 
+static uint16_t vtd_intr_index_alloc(void)
+{
+	static int index_ctr = 0;
+	assert(index_ctr < 65535);
+	return index_ctr++;
+}
+
+static void vtd_setup_irte(struct pci_dev *dev, vtd_irte_t *irte,
+			   int vector, int dest_id)
+{
+	assert(sizeof(vtd_irte_t) == 16);
+	memset(irte, 0, sizeof(*irte));
+	irte->fault_disable = 1;
+	irte->dest_mode = 0;	 /* physical */
+	irte->trigger_mode = 0;	 /* edge */
+	irte->delivery_mode = 0; /* fixed */
+	irte->irte_mode = 0;	 /* remapped */
+	irte->vector = vector;
+	irte->dest_id = dest_id;
+	irte->source_id = dev->bdf;
+	irte->sid_q = 0;
+	irte->sid_vtype = 1;     /* full-sid verify */
+	irte->present = 1;
+}
+
+struct vtd_msi_addr {
+	uint32_t __dont_care:2;
+	uint32_t handle_15:1;	 /* handle[15] */
+	uint32_t shv:1;
+	uint32_t interrupt_format:1;
+	uint32_t handle_0_14:15; /* handle[0:14] */
+	uint32_t head:12;	 /* 0xfee */
+	uint32_t addr_hi;	 /* not used except with x2apic */
+} __attribute__ ((packed));
+typedef struct vtd_msi_addr vtd_msi_addr_t;
+
+struct vtd_msi_data {
+	uint16_t __reserved;
+	uint16_t subhandle;
+} __attribute__ ((packed));
+typedef struct vtd_msi_data vtd_msi_data_t;
+
+/**
+ * vtd_setup_msi - setup MSI message for a device
+ *
+ * @dev: PCI device to setup MSI
+ * @vector: interrupt vector
+ * @dest_id: destination processor
+ */
+bool vtd_setup_msi(struct pci_dev *dev, int vector, int dest_id)
+{
+	vtd_msi_data_t msi_data = {};
+	vtd_msi_addr_t msi_addr = {};
+	vtd_irte_t *irte = phys_to_virt(vtd_ir_table());
+	uint16_t index = vtd_intr_index_alloc();
+
+	assert(sizeof(vtd_msi_addr_t) == 8);
+	assert(sizeof(vtd_msi_data_t) == 4);
+
+	printf("INTR: setup IRTE index %d\n", index);
+	vtd_setup_irte(dev, irte + index, vector, dest_id);
+
+	msi_addr.handle_15 = index >> 15 & 1;
+	msi_addr.shv = 0;
+	msi_addr.interrupt_format = 1;
+	msi_addr.handle_0_14 = index & 0x7fff;
+	msi_addr.head = 0xfee;
+	msi_data.subhandle = 0;
+
+	return pci_setup_msi(dev, *(uint64_t *)&msi_addr,
+			     *(uint32_t *)&msi_data);
+}
+
 void vtd_init(void)
 {
 	setup_vm();
diff --git a/lib/x86/intel-iommu.h b/lib/x86/intel-iommu.h
index 1352639..13feafa 100644
--- a/lib/x86/intel-iommu.h
+++ b/lib/x86/intel-iommu.h
@@ -137,5 +137,6 @@ static inline uint64_t vtd_readq(unsigned int reg)
 
 void vtd_init(void);
 void vtd_map_range(uint16_t sid, phys_addr_t iova, phys_addr_t pa, size_t size);
+bool vtd_setup_msi(struct pci_dev *dev, int vector, int dest_id);
 
 #endif
diff --git a/x86/intel-iommu.c b/x86/intel-iommu.c
index 21fd57f..753f90e 100644
--- a/x86/intel-iommu.c
+++ b/x86/intel-iommu.c
@@ -12,8 +12,10 @@
 
 #include "intel-iommu.h"
 #include "pci-edu.h"
+#include "x86/apic.h"
 
 #define VTD_TEST_DMAR_4B ("DMAR 4B memcpy test")
+#define VTD_TEST_IR_MSI ("IR MSI")
 
 void vtd_test_dmar(struct pci_edu_dev *dev)
 {
@@ -51,6 +53,43 @@ void vtd_test_dmar(struct pci_edu_dev *dev)
 	free_page(page);
 }
 
+static volatile bool edu_intr_recved;
+
+static void edu_isr(isr_regs_t *regs)
+{
+	edu_intr_recved = true;
+	eoi();
+}
+
+static void vtd_test_ir(struct pci_edu_dev *dev)
+{
+#define VTD_TEST_VECTOR (0xee)
+	/*
+	 * Setup EDU PCI device MSI, using interrupt remapping. By
+	 * default, EDU device is using INTx.
+	 */
+	if (!vtd_setup_msi(&dev->pci_dev, VTD_TEST_VECTOR, 0)) {
+		printf("edu device does not support MSI, skip test\n");
+		report_skip(VTD_TEST_IR_MSI);
+		return;
+	}
+
+	handle_irq(VTD_TEST_VECTOR, edu_isr);
+	irq_enable();
+
+	/* Manually trigger INTR */
+	edu_reg_writel(dev, EDU_REG_INTR_RAISE, 1);
+
+	while (!edu_intr_recved)
+		cpu_relax();
+
+	/* Clear INTR bits */
+	edu_reg_writel(dev, EDU_REG_INTR_RAISE, 0);
+
+	/* We are good as long as we reach here */
+	report(VTD_TEST_IR_MSI, true);
+}
+
 int main(int argc, char *argv[])
 {
 	struct pci_edu_dev dev;
@@ -71,8 +110,11 @@ int main(int argc, char *argv[])
 		printf("Please specify \"-device edu\" to do "
 		       "further IOMMU tests.\n");
 		report_skip(VTD_TEST_DMAR_4B);
-	} else
+		report_skip(VTD_TEST_IR_MSI);
+	} else {
 		vtd_test_dmar(&dev);
+		vtd_test_ir(&dev);
+	}
 
 	return report_summary();
 }
-- 
2.7.4


^ permalink raw reply related

* [PATCH 0/2] amd-xgbe: AMD XGBE driver updates 2016-11-14
From: Tom Lendacky @ 2016-11-14 22:28 UTC (permalink / raw)
  To: netdev; +Cc: julia.lawall, christophe.jaillet, David Miller

This patch series addresses some minor issues found in the recently
accepted patch series for the AMD XGBE driver.

The following fixes are included in this driver update series:

- Fix how a mask is applied to a Clause 37 register value
- Fix some coccinelle identified warnings

This patch series is based on net-next.

---

Tom Lendacky (2):
      amd-xgbe: Fix mask appliciation for Clause 37 register
      amd-xgbe: Fix up some coccinelle identified warnings


 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c   |    4 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |    5 ++---
 2 files changed, 4 insertions(+), 5 deletions(-)

-- 
Tom Lendacky

^ permalink raw reply

* [PATCH 1/2] amd-xgbe: Fix mask appliciation for Clause 37 register
From: Tom Lendacky @ 2016-11-14 22:28 UTC (permalink / raw)
  To: netdev; +Cc: julia.lawall, christophe.jaillet, David Miller
In-Reply-To: <20161114222827.25160.24791.stgit@tlendack-t1.amdoffice.net>

The application of a mask to clear an area of a clause 37 register value
was not properly applied. Update the code to do the proper application
of the mask.

Reported-by: Marion & Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 0ecae70..4c5b90e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -943,8 +943,8 @@ static void xgbe_an37_init(struct xgbe_prv_data *pdata)
 
 	/* Set up the Control register */
 	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
-	reg &= XGBE_AN_CL37_TX_CONFIG_MASK;
-	reg &= XGBE_AN_CL37_PCS_MODE_MASK;
+	reg &= ~XGBE_AN_CL37_TX_CONFIG_MASK;
+	reg &= ~XGBE_AN_CL37_PCS_MODE_MASK;
 
 	switch (pdata->an_mode) {
 	case XGBE_AN_MODE_CL37:

^ permalink raw reply related

* Re: [PATCH] rmc: Fix compiling issue with musl
From: Jianxun Zhang @ 2016-11-14 22:28 UTC (permalink / raw)
  To: openembedded-core
In-Reply-To: <1479161454-236511-1-git-send-email-jianxun.zhang@linux.intel.com>

OOPS. Please ignore this patch. It is for another BSP project!


> On Nov 14, 2016, at 2:10 PM, Jianxun Zhang <jianxun.zhang@linux.intel.com> wrote:
> 
> | src/rmcl/rmcl.c: In function 'query_policy_from_db':
> | src/rmcl/rmcl.c:254:25: error: unknown type name 'ssize_t'
> | ssize_t cmd_name_len = strlen((char *)&rmc_db[policy_idx]) + 1;
> | ^~~~~~~~
> 
> The musl C lib provides ssize_t but we need to enable it
> with a macro.
> 
> Signed-off-by: Jianxun Zhang <jianxun.zhang@linux.intel.com>
> ---
> Before maintainer(s) push "merge" button, please read this short summary.
> I feel there could be a better syntax to do it. And We could need to get
> an ack from Hernandez, Alejandro who reported this issue and seems still
> have (other) compiling errors even with this patch.
> 
> I submit this patch based on my thoughts and test out of tiny config.
> 
> Tests:
> () Specify TCLIBC = "musl" in local.conf in my build dir.
> () Build quark
> () I can see this issue happens without the fix
> () With this patch and do clean builds for quark and corei7-64,
> Compiling passes. Boot test passed on RMC targets quark and Broxton-m.
> 
> Thanks
> 
> 
> common/recipes-bsp/rmc/rmc.bb | 2 ++
> 1 file changed, 2 insertions(+)
> 
> diff --git a/common/recipes-bsp/rmc/rmc.bb b/common/recipes-bsp/rmc/rmc.bb
> index aeaf12e..61a1bdb 100644
> --- a/common/recipes-bsp/rmc/rmc.bb
> +++ b/common/recipes-bsp/rmc/rmc.bb
> @@ -24,6 +24,8 @@ COMPATIBLE_HOST = "(x86_64.*|i.86.*)-linux*"
> 
> EXTRA_OEMAKE='RMC_CFLAGS="-Wl,--hash-style=both"'
> 
> +EXTRA_OEMAKE_append_libc-musl = '" -D__NEED_ssize_t"'
> +
> # from gnu-efi, we should align arch-mapping with it.
> def rmc_efi_arch(d):
>     import re
> -- 
> 2.7.4
> 



^ permalink raw reply

* [PATCH 2/2] amd-xgbe: Fix up some coccinelle identified warnings
From: Tom Lendacky @ 2016-11-14 22:28 UTC (permalink / raw)
  To: netdev; +Cc: julia.lawall, christophe.jaillet, David Miller
In-Reply-To: <20161114222827.25160.24791.stgit@tlendack-t1.amdoffice.net>

Fix up some warnings that were identified by coccinelle:

Clean up an if/else block that can look confusing since the same statement
is executed in an "else if" check and the final "else" statement.

Change a variable from unsigned int to int since it is used in an if
statement checking the value to be less than 0.

Reported-by: Julia Lawall <julia.lawall@lip6.fr>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 4ba4332..348cc8c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -1766,8 +1766,6 @@ static void xgbe_phy_sfi_mode(struct xgbe_prv_data *pdata)
 			XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 1);
 		else if (phy_data->sfp_cable_len <= 3)
 			XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 2);
-		else if (phy_data->sfp_cable_len <= 5)
-			XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3);
 		else
 			XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3);
 	}
@@ -2346,7 +2344,8 @@ static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
 static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
 {
 	struct xgbe_phy_data *phy_data = pdata->phy_data;
-	unsigned int ret, reg;
+	unsigned int reg;
+	int ret;
 
 	*an_restart = 0;
 

^ permalink raw reply related

* [Buildroot] [PATCH] openjpeg: refresh patches
From: Peter Seiderer @ 2016-11-14 22:30 UTC (permalink / raw)
  To: buildroot
In-Reply-To: <15d0ff6af38ff41acb2129a619e49a0e3ba866d9.1479160710.git.baruch@tkos.co.il>

Hello Baruch,

On Mon, 14 Nov 2016 23:58:30 +0200, Baruch Siach <baruch@tkos.co.il> wrote:

> The 2.1.2 version bump did not take into account the recently added fixes.
> Update the patches to apply based on upstream pull requests #866 and #867.
> 
> Cc: Peter Seiderer <ps.report@gmx.net>
> Cc: Samuel Martin <s.martin49@gmail.com>
> Signed-off-by: Baruch Siach <baruch@tkos.co.il>
> ---
>  ...tiff-append-flags-found-by-pkg-config-if-.patch | 60 +++++++++++-----------
>  ...lcms2-append-flags-found-by-pkg-config-if.patch | 38 +++++++-------
>  2 files changed, 50 insertions(+), 48 deletions(-)
> 
> diff --git a/package/openjpeg/0001-thirdparty-tiff-append-flags-found-by-pkg-config-if-.patch b/package/openjpeg/0001-thirdparty-tiff-append-flags-found-by-pkg-config-if-.patch
> index be509024de86..bce790a47863 100644
> --- a/package/openjpeg/0001-thirdparty-tiff-append-flags-found-by-pkg-config-if-.patch
> +++ b/package/openjpeg/0001-thirdparty-tiff-append-flags-found-by-pkg-config-if-.patch
> @@ -17,56 +17,56 @@ Signed-off-by: Samuel Martin <s.martin49@gmail.com>
>   1 file changed, 21 insertions(+), 2 deletions(-)
>  
>  diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt
> -index d1e68ca..225f51d 100644
> +index cb24b43b58e2..cd6a5e1391b0 100644
>  --- a/thirdparty/CMakeLists.txt
>  +++ b/thirdparty/CMakeLists.txt
>  @@ -1,5 +1,9 @@
>   # 3rd party libs
>   
> -+IF(NOT BUILD_THIRDPARTY)
> ++if(NOT BUILD_THIRDPARTY)
>  +  include(FindPkgConfig)
> -+ENDIF(NOT BUILD_THIRDPARTY)
> ++endif(NOT BUILD_THIRDPARTY)
>  +
>   #------------
>   # Try to find lib Z
> - IF(BUILD_THIRDPARTY)
> -@@ -35,6 +39,9 @@ IF(BUILD_THIRDPARTY)
> -   SET(PNG_INCLUDE_DIRNAME ${OPENJPEG_SOURCE_DIR}/thirdparty/libpng PARENT_SCOPE)
> - ELSE (BUILD_THIRDPARTY)
> -   IF (ZLIB_FOUND)
> + if(BUILD_THIRDPARTY)
> +@@ -36,6 +40,9 @@ if(BUILD_THIRDPARTY)
> + else(BUILD_THIRDPARTY)
> +   if(ZLIB_FOUND)
> +     find_package(PNG)
>  +    # Static only build:
>  +    #   it is not necessary to invoke pkg_check_module on libpng, because libpng
>  +    #   only depends on zlib, which is already checked.
> -     FIND_PACKAGE(PNG)
> -     IF(PNG_FOUND)
> +     if(PNG_FOUND)
>         message(STATUS "Your system seems to have a PNG lib available, we will use it")
> -@@ -66,12 +73,24 @@ IF(BUILD_THIRDPARTY)
> -   SET(OPJ_HAVE_LIBTIFF 1 PARENT_SCOPE)
> - ELSE (BUILD_THIRDPARTY)
> -   FIND_PACKAGE(TIFF)
> +       set(OPJ_HAVE_PNG_H 1 PARENT_SCOPE)
> +@@ -66,12 +73,24 @@ if(BUILD_THIRDPARTY)
> +   set(OPJ_HAVE_LIBTIFF 1 PARENT_SCOPE)
> + else(BUILD_THIRDPARTY)
> +   find_package(TIFF)
>  +  # Static only build:
>  +  #   it is necessary to invoke pkg_check_module on libtiff since it may have
>  +  #   several other dependencies not declared by its cmake module, but they are
>  +  #   in the its pkgconfig module.
> -+  IF(PKG_CONFIG_FOUND)
> -+    FOREACH(pc_tiff_module tiff tiff3 tiff4 tiff-3 tiff-4 libtiff libtiff3 libtiff4 libtiff-3 libtiff-4)
> ++  if(PKG_CONFIG_FOUND)
> ++    foreach(pc_tiff_module tiff tiff3 tiff4 tiff-3 tiff-4 libtiff libtiff3 libtiff4 libtiff-3 libtiff-4)
>  +      pkg_check_modules(PC_TIFF QUIET ${pc_tiff_module})
> -+      IF(PC_TIFF_FOUND)
> ++      if(PC_TIFF_FOUND)
>  +        break()
> -+      ENDIF(PC_TIFF_FOUND)
> -+    ENDFOREACH()
> -+  ENDIF(PKG_CONFIG_FOUND)
> -   IF(TIFF_FOUND)
> ++      endif(PC_TIFF_FOUND)
> ++    endforeach()
> ++  endif(PKG_CONFIG_FOUND)
> +   if(TIFF_FOUND)
>       message(STATUS "Your system seems to have a TIFF lib available, we will use it")
> -     SET(OPJ_HAVE_TIFF_H 1 PARENT_SCOPE)
> -     SET(OPJ_HAVE_LIBTIFF 1 PARENT_SCOPE)
> --    SET(TIFF_LIBNAME ${TIFF_LIBRARIES} PARENT_SCOPE)
> --    SET(TIFF_INCLUDE_DIRNAME ${TIFF_INCLUDE_DIR} PARENT_SCOPE)
> -+    SET(TIFF_LIBNAME ${TIFF_LIBRARIES} ${PC_TIFF_STATIC_LIBRARIES} PARENT_SCOPE)
> -+    SET(TIFF_INCLUDE_DIRNAME ${TIFF_INCLUDE_DIR} ${PC_TIFF_STATIC_INCLUDE_DIRS} PARENT_SCOPE)
> -   ELSE (TIFF_FOUND) # not found
> -     SET(OPJ_HAVE_TIFF_H 0 PARENT_SCOPE)
> -     SET(OPJ_HAVE_LIBTIFF 0 PARENT_SCOPE)
> +     set(OPJ_HAVE_TIFF_H 1 PARENT_SCOPE)
> +     set(OPJ_HAVE_LIBTIFF 1 PARENT_SCOPE)
> +-    set(TIFF_LIBNAME ${TIFF_LIBRARIES} PARENT_SCOPE)
> +-    set(TIFF_INCLUDE_DIRNAME ${TIFF_INCLUDE_DIR} PARENT_SCOPE)
> ++    set(TIFF_LIBNAME ${TIFF_LIBRARIES} ${PC_TIFF_STATIC_LIBRARIES} PARENT_SCOPE)
> ++    set(TIFF_INCLUDE_DIRNAME ${TIFF_INCLUDE_DIR} ${PC_TIFF_STATIC_INCLUDE_DIRS} PARENT_SCOPE)
> +   else(TIFF_FOUND) # not found
> +     set(OPJ_HAVE_TIFF_H 0 PARENT_SCOPE)
> +     set(OPJ_HAVE_LIBTIFF 0 PARENT_SCOPE)
>  -- 
>  2.10.2
>  
> diff --git a/package/openjpeg/0002-thirdparty-lcms2-append-flags-found-by-pkg-config-if.patch b/package/openjpeg/0002-thirdparty-lcms2-append-flags-found-by-pkg-config-if.patch
> index 4366c0af88cf..5697b82de2e0 100644
> --- a/package/openjpeg/0002-thirdparty-lcms2-append-flags-found-by-pkg-config-if.patch
> +++ b/package/openjpeg/0002-thirdparty-lcms2-append-flags-found-by-pkg-config-if.patch
> @@ -7,9 +7,11 @@ Subject: [PATCH] thirdparty: lcms2: append flags found by pkg-config if
>  This change allows to get all required CFLAGS/LDFLAGS in case of static only
>  build.
>  
> -Fixes a buildroot build failure (see [1]).
> +Fixes a buildroot build failure (see [1], [2] and [3]).
>  
>  [1] http://autobuild.buildroot.net/results/5ce/5cee20afd8bef5268832cddcb3a5270746be7a57
> +[2] http://lists.busybox.net/pipermail/buildroot/2016-November/177187.html
> +[3] http://lists.busybox.net/pipermail/buildroot/2016-November/177188.html
>  
>  Signed-off-by: Peter Seiderer <ps.report@gmx.net>
>  ---
> @@ -17,31 +19,31 @@ Signed-off-by: Peter Seiderer <ps.report@gmx.net>
>   1 file changed, 9 insertions(+), 2 deletions(-)
>  
>  diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt
> -index 225f51d..42770ad 100644
> +index cd6a5e1391b0..a3a8494d89b1 100644
>  --- a/thirdparty/CMakeLists.txt
>  +++ b/thirdparty/CMakeLists.txt
> -@@ -113,12 +113,19 @@ IF( BUILD_THIRDPARTY)
> -   SET(OPJ_HAVE_LIBLCMS2 1 PARENT_SCOPE)
> - ELSE (BUILD_THIRDPARTY)
> -   FIND_PACKAGE(LCMS2)
> +@@ -113,12 +113,19 @@ if( BUILD_THIRDPARTY)
> +   set(OPJ_HAVE_LIBLCMS2 1 PARENT_SCOPE)
> + else(BUILD_THIRDPARTY)
> +   find_package(LCMS2)
>  +  # Static only build:
>  +  #   it is necessary to invoke pkg_check_module on lcms2 since it may have
>  +  #   several other dependencies not declared by its cmake module, but they are
>  +  #   in the its pkgconfig module.
> -+  IF(PKG_CONFIG_FOUND)
> ++  if(PKG_CONFIG_FOUND)
>  +    pkg_check_modules(PC_LCMS2 QUIET lcms2)
> -+  ENDIF(PKG_CONFIG_FOUND)
> -   IF(LCMS2_FOUND)
> ++  endif(PKG_CONFIG_FOUND)
> +   if(LCMS2_FOUND)
>       message(STATUS "Your system seems to have a LCMS2 lib available, we will use it")
> -     SET(OPJ_HAVE_LCMS2_H 1 PARENT_SCOPE)
> -     SET(OPJ_HAVE_LIBLCMS2 1 PARENT_SCOPE)
> --    SET(LCMS_LIBNAME ${LCMS2_LIBRARIES} PARENT_SCOPE)
> --    SET(LCMS_INCLUDE_DIRNAME ${LCMS2_INCLUDE_DIRS} PARENT_SCOPE)
> -+    SET(LCMS_LIBNAME ${LCMS2_LIBRARIES} ${PC_LCMS2_STATIC_LIBRARIES} PARENT_SCOPE)
> -+    SET(LCMS_INCLUDE_DIRNAME ${LCMS2_INCLUDE_DIRS} ${PC_LCMS2_STATIC_INCLUDE_DIRS} PARENT_SCOPE)
> -   ELSE (LCMS2_FOUND) # not found lcms2
> +     set(OPJ_HAVE_LCMS2_H 1 PARENT_SCOPE)
> +     set(OPJ_HAVE_LIBLCMS2 1 PARENT_SCOPE)
> +-    set(LCMS_LIBNAME ${LCMS2_LIBRARIES} PARENT_SCOPE)
> +-    set(LCMS_INCLUDE_DIRNAME ${LCMS2_INCLUDE_DIRS} PARENT_SCOPE)
> ++    set(LCMS_LIBNAME ${LCMS2_LIBRARIES} ${PC_LCMS2_STATIC_LIBRARIES} PARENT_SCOPE)
> ++    set(LCMS_INCLUDE_DIRNAME ${LCMS2_INCLUDE_DIRS} ${PC_LCMS2_STATIC_INCLUDE_DIRS} PARENT_SCOPE)
> +   else(LCMS2_FOUND) # not found lcms2
>       # try to find LCMS
> -     FIND_PACKAGE(LCMS)
> +     find_package(LCMS)
>  -- 
> -2.8.1
> +2.10.2
>  

Acked-by: Peter Seiderer <ps.report@gmx.net>

Regards,
Peter

^ permalink raw reply

* Re: [PATCH v3 14/14] drm/i915: Support explicit fencing for execbuf
From: Rafael Antognolli @ 2016-11-14 22:29 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx
In-Reply-To: <20161114085703.16540-14-chris@chris-wilson.co.uk>

Hi Chris,

I'm not sure you are waiting for this kind of feedback, but I've managed
to test this particular patch with Mesa, and I have some piglit tests
for it too. They are waiting for review, but at least the feature is
working as expected:

https://github.com/rantogno/piglit/commits/review/fences-v02

I used mesa and libdrm patches from more than a single set, but in case
you want to look they are here:

https://github.com/rantogno/mesa/commits/wip-fence
https://github.com/rantogno/libdrm/commits/wip-fence

And my kernel tree when I tested it:

https://github.com/rantogno/linux/commits/wip-fence

So in case it helps, you can add a

Tested-by: Rafael Antognolli <rafael.antognolli@intel.com>

PS: I can test it with this last series and everything more up to date,
if it will help to get this patch landed sooner.

Cheers,
Rafael

On Mon, Nov 14, 2016 at 08:57:03AM +0000, Chris Wilson wrote:
> Now that the user can opt-out of implicit fencing, we need to give them
> back control over the fencing. We employ sync_file to wrap our
> drm_i915_gem_request and provide an fd that userspace can merge with
> other sync_file fds and pass back to the kernel to wait upon before
> future execution.
> 
> Testcase: igt/gem_exec_fence
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/Kconfig               |  1 +
>  drivers/gpu/drm/i915/i915_drv.c            |  3 +-
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c | 54 +++++++++++++++++++++++++++---
>  include/uapi/drm/i915_drm.h                | 35 ++++++++++++++++++-
>  4 files changed, 86 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
> index beed5c1d2cd7..bed81fe1d2a7 100644
> --- a/drivers/gpu/drm/i915/Kconfig
> +++ b/drivers/gpu/drm/i915/Kconfig
> @@ -19,6 +19,7 @@ config DRM_I915
>  	select INPUT if ACPI
>  	select ACPI_VIDEO if ACPI
>  	select ACPI_BUTTON if ACPI
> +	select SYNC_FILE
>  	help
>  	  Choose this option if you have a system that has "Intel Graphics
>  	  Media Accelerator" or "HD Graphics" integrated graphics,
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 657c465a8d50..6fe7f41a5b5b 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -344,6 +344,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
>  	case I915_PARAM_HAS_COHERENT_PHYS_GTT:
>  	case I915_PARAM_HAS_EXEC_SOFTPIN:
>  	case I915_PARAM_HAS_EXEC_ASYNC:
> +	case I915_PARAM_HAS_EXEC_FENCE:
>  		/* For the time being all of these are always true;
>  		 * if some supported hardware does not have one of these
>  		 * features this value needs to be provided from
> @@ -2533,7 +2534,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
>  	DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
>  	DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
>  	DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
> -	DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW),
> +	DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2_WR, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW),
>  	DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
>  	DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
>  	DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> index 781b5559f86e..facec610b55a 100644
> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> @@ -28,6 +28,7 @@
>  
>  #include <linux/dma_remapping.h>
>  #include <linux/reservation.h>
> +#include <linux/sync_file.h>
>  #include <linux/uaccess.h>
>  
>  #include <drm/drmP.h>
> @@ -1597,6 +1598,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
>  	struct i915_execbuffer_params *params = &params_master;
>  	const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
>  	u32 dispatch_flags;
> +	struct dma_fence *in_fence = NULL;
> +	struct sync_file *out_fence = NULL;
> +	int out_fence_fd = -1;
>  	int ret;
>  	bool need_relocs;
>  
> @@ -1640,6 +1644,23 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
>  		dispatch_flags |= I915_DISPATCH_RS;
>  	}
>  
> +	if (args->flags & I915_EXEC_FENCE_IN) {
> +		in_fence = sync_file_get_fence(lower_32_bits(args->rsvd2));
> +		if (!in_fence) {
> +			ret = -EINVAL;
> +			goto pre_mutex_err;
> +		}
> +	}
> +
> +	if (args->flags & I915_EXEC_FENCE_OUT) {
> +		out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
> +		if (out_fence_fd < 0) {
> +			ret = out_fence_fd;
> +			out_fence_fd = -1;
> +			goto pre_mutex_err;
> +		}
> +	}
> +
>  	/* Take a local wakeref for preparing to dispatch the execbuf as
>  	 * we expect to access the hardware fairly frequently in the
>  	 * process. Upon first dispatch, we acquire another prolonged
> @@ -1784,6 +1805,21 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
>  		goto err_batch_unpin;
>  	}
>  
> +	if (in_fence) {
> +		ret = i915_gem_request_await_dma_fence(params->request,
> +						       in_fence);
> +		if (ret < 0)
> +			goto err_request;
> +	}
> +
> +	if (out_fence_fd != -1) {
> +		out_fence = sync_file_create(&params->request->fence);
> +		if (!out_fence) {
> +			ret = -ENOMEM;
> +			goto err_request;
> +		}
> +	}
> +
>  	/* Whilst this request exists, batch_obj will be on the
>  	 * active_list, and so will hold the active reference. Only when this
>  	 * request is retired will the the batch_obj be moved onto the
> @@ -1811,6 +1847,16 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
>  	ret = execbuf_submit(params, args, &eb->vmas);
>  err_request:
>  	__i915_add_request(params->request, ret == 0);
> +	if (out_fence) {
> +		if (ret == 0) {
> +			fd_install(out_fence_fd, out_fence->file);
> +			args->rsvd2 &= GENMASK_ULL(0, 31); /* keep in-fence */
> +			args->rsvd2 |= (u64)out_fence_fd << 32;
> +			out_fence_fd = -1;
> +		} else {
> +			fput(out_fence->file);
> +		}
> +	}
>  
>  err_batch_unpin:
>  	/*
> @@ -1832,6 +1878,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
>  	/* intel_gpu_busy should also get a ref, so it will free when the device
>  	 * is really idle. */
>  	intel_runtime_pm_put(dev_priv);
> +	if (out_fence_fd != -1)
> +		put_unused_fd(out_fence_fd);
> +	dma_fence_put(in_fence);
>  	return ret;
>  }
>  
> @@ -1939,11 +1988,6 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
>  		return -EINVAL;
>  	}
>  
> -	if (args->rsvd2 != 0) {
> -		DRM_DEBUG("dirty rvsd2 field\n");
> -		return -EINVAL;
> -	}
> -
>  	exec2_list = drm_malloc_gfp(args->buffer_count,
>  				    sizeof(*exec2_list),
>  				    GFP_TEMPORARY);
> diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
> index 4bd83c0b07db..90082269fb50 100644
> --- a/include/uapi/drm/i915_drm.h
> +++ b/include/uapi/drm/i915_drm.h
> @@ -246,6 +246,7 @@ typedef struct _drm_i915_sarea {
>  #define DRM_I915_OVERLAY_PUT_IMAGE	0x27
>  #define DRM_I915_OVERLAY_ATTRS	0x28
>  #define DRM_I915_GEM_EXECBUFFER2	0x29
> +#define DRM_I915_GEM_EXECBUFFER2_WR	DRM_I915_GEM_EXECBUFFER2
>  #define DRM_I915_GET_SPRITE_COLORKEY	0x2a
>  #define DRM_I915_SET_SPRITE_COLORKEY	0x2b
>  #define DRM_I915_GEM_WAIT	0x2c
> @@ -279,6 +280,7 @@ typedef struct _drm_i915_sarea {
>  #define DRM_IOCTL_I915_GEM_INIT		DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
>  #define DRM_IOCTL_I915_GEM_EXECBUFFER	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
>  #define DRM_IOCTL_I915_GEM_EXECBUFFER2	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2)
> +#define DRM_IOCTL_I915_GEM_EXECBUFFER2_WR	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2_WR, struct drm_i915_gem_execbuffer2)
>  #define DRM_IOCTL_I915_GEM_PIN		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
>  #define DRM_IOCTL_I915_GEM_UNPIN	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
>  #define DRM_IOCTL_I915_GEM_BUSY		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
> @@ -401,6 +403,12 @@ typedef struct drm_i915_irq_wait {
>   */
>  #define I915_PARAM_HAS_EXEC_ASYNC	 42
>  
> +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports explicit fence support -
> + * both being able to pass in a sync_file fd to wait upon before executing,
> + * and being able to return a new sync_file fd that is signaled when the
> + * current request is complete.
> + */
> +#define I915_PARAM_HAS_EXEC_FENCE	 43
>  
>  typedef struct drm_i915_getparam {
>  	__s32 param;
> @@ -854,7 +862,32 @@ struct drm_i915_gem_execbuffer2 {
>   */
>  #define I915_EXEC_RESOURCE_STREAMER     (1<<15)
>  
> -#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_RESOURCE_STREAMER<<1)
> +/* Setting I915_EXEC_FENCE_IN implies that lower_32_bits(rsvd2) represent
> + * a sync_file fd to wait upon (in a nonblocking manner) prior to executing
> + * the batch.
> + *
> + * Returns -EINVAL if the sync_file fd cannot be found.
> + */
> +#define I915_EXEC_FENCE_IN		(1<<16)
> +
> +/* Setting I915_EXEC_FENCE_OUT causes the ioctl to return a sync_file fd
> + * in the upper_32_bits(rsvd2) upon success. Ownership of the fd is given
> + * to the caller, and it should be close() after use. (The fd is a regular
> + * file descriptor and will be cleaned up on process termination. It holds
> + * a reference to the request, but nothing else.)
> + *
> + * The sync_file fd can be combined with other sync_file and passed either
> + * to execbuf using I915_EXEC_FENCE_IN, to atomic KMS ioctls (so that a flip
> + * will only occur after this request completes), or to other devices.
> + *
> + * Using I915_EXEC_FENCE_OUT requires use of
> + * DRM_IOCTL_I915_GEM_EXECBUFFER2_WR ioctl so that the result is written
> + * back to userspace. Failure to do so will cause the out-fence to always
> + * be reported as zero, and the real fence fd to be leaked.
> + */
> +#define I915_EXEC_FENCE_OUT		(1<<17)
> +
> +#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_OUT<<1))
>  
>  #define I915_EXEC_CONTEXT_ID_MASK	(0xffffffff)
>  #define i915_execbuffer2_set_context_id(eb2, context) \
> -- 
> 2.10.2
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* Re: [PATCH v6 0/9] tpm: cleanup/fixes in existing event log support
From: Jarkko Sakkinen @ 2016-11-14 22:33 UTC (permalink / raw)
  To: Nayna Jain
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1479117656-12403-1-git-send-email-nayna-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

On Mon, Nov 14, 2016 at 05:00:47AM -0500, Nayna Jain wrote:
> This patch set includes the cleanup and bug fixes patches, previously
> part of the "tpm: add the securityfs pseudo files support for TPM 2.0
> firmware event log" patch set, in order to upstream them more quickly.

I applied the patches. I'm not yet sure whether these are part of the
4.10 pull request or whether I postpone to 4.11 (my preference would be
4.10 but I do not want to close that right now). I'll do testing next
week before doing pull request.

I hope that the commits gets some reviews and testing now that they are
easily testable in my master branch.

/Jarkko

> 
> Changelog History:
> 
> v6:
> 
> - Patch "tpm: replace symbolic permission with octal for securityfs files"
>   - New Patch.
> - Patch "tpm: have event log use the tpm_chip"
>   - Changed commit description as per Jason's suggestion.
>   - Fixed bug related to kfree() for bios_event_log.
>   - Moved inode_unlock() just after get_device() in open().
>   - Returned -ENODEV for read_log() ENOMEM error and other errors as it is.
>   - Added comment in tpm_bios_log_teardown() to explain inode_lock()/unlock
>     reasoning.
>   - Splitted .owner into different patch.
> - Patch "tpm: fix the missing .owner in tpm_bios_measurements_ops"
>   - New Patch.
> - Patch "tpm: cleanup of printk error messages"
>   - Replaced dev_info() with dev_warn().
>   - Updated commit description subject line.
> 
> v5:
> 
> - Moved cleanup/fixes patches into this patch set.
> - Patch "fix the race condition between event log access and chip
> getting unregistered"
>   - updated subject line and commit description.
>   - modified fops code to use chip kref.
>   - modified fops to lock inode before accessing inode private data.
>   - renamed tpm_securityfs_data to tpm_chip_seqops, as it no more
>   holds bios log, but associates seqops with respective chip. For
>   the same reason, moved it to tpm.h
> - Patch "replace or remove printk error messages"
>   - cleaned up dev_dbg and used dev_info as applicable.
> 
> v4:
> 
> - Includes feedbacks from Jarkko and Jason.
> - Patch "tpm: define a generic open() method for ascii & bios
> measurements".
>   - Fix indentation issue.
> - Patch "tpm: replace the dynamically allocated bios_dir as
>   struct dentry array". 
>   - Continue to use bios_dir_count variable to use is_bad() checks and
>   to maintain correct order for securityfs_remove() during teardown.
>   - Reset chip->bios_dir_count in teardown() function.
> - Patch "tpm: validate the event log access before tpm_bios_log_setup".
>   - Retain TPM2 check which was removed in previous patch.
>   - Add tpm_bios_log_setup failure handling.
>   - Remove use of private data from v3 version of patch. Add a new
>   member to struct tpm_chip to achieve the same purpose.
> - Patch "tpm: redefine the read_log method to check for ACPI/OF 
> properties sequentially".
>   - Move replacement of CONFIG_TCG_IBMVTPM with CONFIG_OF to
>   this patch from patch 3.
>   - Replace -1 error code with -ENODEV.
> - Patch "tpm: replace the of_find_node_by_name() with dev of_node
> property".
>  - Uses chip->dev.parent->of_node.
>  - Created separate patch for cleanup of pr_err messages.
> - Patch "tpm: remove printk error messages".
>  - New Patch.
> - Patch "tpm: add the securityfs file support for TPM 2.0 event log".
>  - Parses event digests using event alg_id rather than event log header
>  alg_id.
>  - Uses of_property_match_string to differentiate tpm/vtpm compatible
>  property.
>  - Adds the comment for difference in tpm/vtpm endianness.
> 
> v3:
> 
> - Includes the review feedbacks as suggested by Jason.
> - Split of patches into one patch per idea.
> - Generic open() method for ascii/bios measurements.
> - Replacement of of **bios_dir with *bios_dir[3].
> - Verifying readlog() is successful before creating securityfs entries.
> - Generic readlog() to check for ACPI/OF in sequence.
> - read_log_of() method now uses of_node propertry rather than
> calling find_device_by_name.
> - read_log differentiates vtpm/tpm using its compatible property.
> - Cleans pr_err with dev_dbg.
> - Commit msgs subject line prefixed with tpm.
> 
> v2:
> 
> - Fixes issues as given in feedback by Jason.
> - Adds documentation for device tree.
> 
> Nayna Jain (9):
>   tpm: define a generic open() method for ascii & bios measurements
>   tpm: replace symbolic permission with octal for securityfs files
>   tpm: replace dynamically allocated bios_dir with a static array
>   tpm: drop tpm1_chip_register(/unregister)
>   tpm: have event log use the tpm_chip
>   tpm: fix the missing .owner in tpm_bios_measurements_ops
>   tpm: redefine read_log() to handle ACPI/OF at runtime
>   tpm: replace of_find_node_by_name() with dev of_node property
>   tpm: cleanup of printk error messages
> 
>  drivers/char/tpm/Makefile       |  14 +--
>  drivers/char/tpm/tpm-chip.c     |  33 ++----
>  drivers/char/tpm/tpm-sysfs.c    |   3 +
>  drivers/char/tpm/tpm.h          |  14 ++-
>  drivers/char/tpm/tpm_acpi.c     |  38 +++----
>  drivers/char/tpm/tpm_eventlog.c | 222 +++++++++++++++++++++-------------------
>  drivers/char/tpm/tpm_eventlog.h |  22 ++--
>  drivers/char/tpm/tpm_of.c       |  45 +++-----
>  8 files changed, 187 insertions(+), 204 deletions(-)
> 
> -- 
> 2.5.0
> 

------------------------------------------------------------------------------

^ permalink raw reply

* Re: [PATCH v6 0/9] tpm: cleanup/fixes in existing event log support
From: Jarkko Sakkinen @ 2016-11-14 22:33 UTC (permalink / raw)
  To: Nayna Jain
  Cc: tpmdd-devel, peterhuewe, tpmdd, jgunthorpe, linux-kernel,
	linux-security-module
In-Reply-To: <1479117656-12403-1-git-send-email-nayna@linux.vnet.ibm.com>

On Mon, Nov 14, 2016 at 05:00:47AM -0500, Nayna Jain wrote:
> This patch set includes the cleanup and bug fixes patches, previously
> part of the "tpm: add the securityfs pseudo files support for TPM 2.0
> firmware event log" patch set, in order to upstream them more quickly.

I applied the patches. I'm not yet sure whether these are part of the
4.10 pull request or whether I postpone to 4.11 (my preference would be
4.10 but I do not want to close that right now). I'll do testing next
week before doing pull request.

I hope that the commits gets some reviews and testing now that they are
easily testable in my master branch.

/Jarkko

> 
> Changelog History:
> 
> v6:
> 
> - Patch "tpm: replace symbolic permission with octal for securityfs files"
>   - New Patch.
> - Patch "tpm: have event log use the tpm_chip"
>   - Changed commit description as per Jason's suggestion.
>   - Fixed bug related to kfree() for bios_event_log.
>   - Moved inode_unlock() just after get_device() in open().
>   - Returned -ENODEV for read_log() ENOMEM error and other errors as it is.
>   - Added comment in tpm_bios_log_teardown() to explain inode_lock()/unlock
>     reasoning.
>   - Splitted .owner into different patch.
> - Patch "tpm: fix the missing .owner in tpm_bios_measurements_ops"
>   - New Patch.
> - Patch "tpm: cleanup of printk error messages"
>   - Replaced dev_info() with dev_warn().
>   - Updated commit description subject line.
> 
> v5:
> 
> - Moved cleanup/fixes patches into this patch set.
> - Patch "fix the race condition between event log access and chip
> getting unregistered"
>   - updated subject line and commit description.
>   - modified fops code to use chip kref.
>   - modified fops to lock inode before accessing inode private data.
>   - renamed tpm_securityfs_data to tpm_chip_seqops, as it no more
>   holds bios log, but associates seqops with respective chip. For
>   the same reason, moved it to tpm.h
> - Patch "replace or remove printk error messages"
>   - cleaned up dev_dbg and used dev_info as applicable.
> 
> v4:
> 
> - Includes feedbacks from Jarkko and Jason.
> - Patch "tpm: define a generic open() method for ascii & bios
> measurements".
>   - Fix indentation issue.
> - Patch "tpm: replace the dynamically allocated bios_dir as
>   struct dentry array". 
>   - Continue to use bios_dir_count variable to use is_bad() checks and
>   to maintain correct order for securityfs_remove() during teardown.
>   - Reset chip->bios_dir_count in teardown() function.
> - Patch "tpm: validate the event log access before tpm_bios_log_setup".
>   - Retain TPM2 check which was removed in previous patch.
>   - Add tpm_bios_log_setup failure handling.
>   - Remove use of private data from v3 version of patch. Add a new
>   member to struct tpm_chip to achieve the same purpose.
> - Patch "tpm: redefine the read_log method to check for ACPI/OF 
> properties sequentially".
>   - Move replacement of CONFIG_TCG_IBMVTPM with CONFIG_OF to
>   this patch from patch 3.
>   - Replace -1 error code with -ENODEV.
> - Patch "tpm: replace the of_find_node_by_name() with dev of_node
> property".
>  - Uses chip->dev.parent->of_node.
>  - Created separate patch for cleanup of pr_err messages.
> - Patch "tpm: remove printk error messages".
>  - New Patch.
> - Patch "tpm: add the securityfs file support for TPM 2.0 event log".
>  - Parses event digests using event alg_id rather than event log header
>  alg_id.
>  - Uses of_property_match_string to differentiate tpm/vtpm compatible
>  property.
>  - Adds the comment for difference in tpm/vtpm endianness.
> 
> v3:
> 
> - Includes the review feedbacks as suggested by Jason.
> - Split of patches into one patch per idea.
> - Generic open() method for ascii/bios measurements.
> - Replacement of of **bios_dir with *bios_dir[3].
> - Verifying readlog() is successful before creating securityfs entries.
> - Generic readlog() to check for ACPI/OF in sequence.
> - read_log_of() method now uses of_node propertry rather than
> calling find_device_by_name.
> - read_log differentiates vtpm/tpm using its compatible property.
> - Cleans pr_err with dev_dbg.
> - Commit msgs subject line prefixed with tpm.
> 
> v2:
> 
> - Fixes issues as given in feedback by Jason.
> - Adds documentation for device tree.
> 
> Nayna Jain (9):
>   tpm: define a generic open() method for ascii & bios measurements
>   tpm: replace symbolic permission with octal for securityfs files
>   tpm: replace dynamically allocated bios_dir with a static array
>   tpm: drop tpm1_chip_register(/unregister)
>   tpm: have event log use the tpm_chip
>   tpm: fix the missing .owner in tpm_bios_measurements_ops
>   tpm: redefine read_log() to handle ACPI/OF at runtime
>   tpm: replace of_find_node_by_name() with dev of_node property
>   tpm: cleanup of printk error messages
> 
>  drivers/char/tpm/Makefile       |  14 +--
>  drivers/char/tpm/tpm-chip.c     |  33 ++----
>  drivers/char/tpm/tpm-sysfs.c    |   3 +
>  drivers/char/tpm/tpm.h          |  14 ++-
>  drivers/char/tpm/tpm_acpi.c     |  38 +++----
>  drivers/char/tpm/tpm_eventlog.c | 222 +++++++++++++++++++++-------------------
>  drivers/char/tpm/tpm_eventlog.h |  22 ++--
>  drivers/char/tpm/tpm_of.c       |  45 +++-----
>  8 files changed, 187 insertions(+), 204 deletions(-)
> 
> -- 
> 2.5.0
> 

^ permalink raw reply

* Re: [PATCH 3/4] PCI: Add checks to mellanox_check_broken_intx_masking
From: Bjorn Helgaas @ 2016-11-14 22:35 UTC (permalink / raw)
  To: Gavin Shan; +Cc: Noa Osherovich, bhelgaas, linux-pci, majd
In-Reply-To: <20161114001535.GB14481@gwshan>

On Mon, Nov 14, 2016 at 11:15:35AM +1100, Gavin Shan wrote:
> On Sun, Nov 13, 2016 at 04:21:41PM +0200, Noa Osherovich wrote:
> >Mellanox devices were marked as having INTx masking ability broken.
> >As a result, the VFIO driver fails to start when more than one device
> >function is passed-through to a VM if both have the same INTx pin.
> >
> >Prior to Connect-IB, Mellanox devices exposed to the operating system
> >one PCI function per all ports.
> >Starting from Connect-IB, the devices are function-per-port. When
> >passing the second function to a VM, VFIO will fail to start.
> >
> >Exclude ConnectX-4, ConnectX4-Lx and Connect-IB from the list of
> >Mellanox devices marked as having broken INTx masking:
> >
> >- ConnectX-4 and ConnectX4-LX firmware version is checked. If INTx
> >  masking is supported, we unmark the broken INTx masking.
> >- Connect-IB does not support INTx currently so will not cause any
> >  problem.
> >
> >Fixes: 11e42532ada31 ('PCI: Assume all Mellanox devices have ...')
> >Signed-off-by: Noa Osherovich <noaos@mellanox.com>
> >Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
> 
> Reviewed-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
> 
> With below comments addressed:

Noa, would you mind refreshing this to address Gavin's comments?
I don't want to risk doing it myself and breaking something.

> >---
> > drivers/pci/quirks.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++------
> > 1 file changed, 55 insertions(+), 6 deletions(-)
> >
> >diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> >index d3977c847e1f..cbd6776e70e6 100644
> >--- a/drivers/pci/quirks.c
> >+++ b/drivers/pci/quirks.c
> >@@ -3192,21 +3192,70 @@ static void quirk_broken_intx_masking(struct pci_dev *dev)
> > 	PCI_DEVICE_ID_MELLANOX_CONNECTX2,
> > 	PCI_DEVICE_ID_MELLANOX_CONNECTX3,
> > 	PCI_DEVICE_ID_MELLANOX_CONNECTX3_PRO,
> >-	PCI_DEVICE_ID_MELLANOX_CONNECTIB,
> >-	PCI_DEVICE_ID_MELLANOX_CONNECTX4,
> >-	PCI_DEVICE_ID_MELLANOX_CONNECTX4_LX
> > };
> >
> >+#define CONNECTX_4_CURR_MAX_MINOR 99
> >+#define CONNECTX_4_INTX_SUPPORT_MINOR 14
> >+
> >+/*
> >+ * Checking ConnectX-4/LX FW version to see if it supports legacy interrupts.
> >+ * If so, don't mark it as broken.
> >+ * FW minor > 99 means older FW version format and no INTx masking support.
> >+ * FW minor < 14 means new FW version format and no INTx masking support.
> >+ */
> > static void mellanox_check_broken_intx_masking(struct pci_dev *dev)
> > {
> >+	__be32 __iomem *fw_ver;
> >+	u16 fw_major;
> >+	u16 fw_minor;
> >+	u16 fw_subminor;
> >+	u32 fw_maj_min;
> >+	u32 fw_sub_min;
> > 	int i;
> >
> >+	dev->broken_intx_masking = 1;
> >+
> > 	for (i = 0; i < ARRAY_SIZE(mellanox_broken_intx_devs); i++) {
> >-		if (dev->device == mellanox_broken_intx_devs[i]) {
> >-			dev->broken_intx_masking = 1;
> >+		if (dev->device == mellanox_broken_intx_devs[i])
> > 			return;
> >-		}
> > 	}
> >+
> >+	/* Getting here means Connect-IB cards and up. Connect-IB has no INTx
> >+	 * support so shouldn't be checked further
> >+	 */
> >+	if (dev->device == PCI_DEVICE_ID_MELLANOX_CONNECTIB) {
> >+		dev->broken_intx_masking = 0;
> >+		return;
> >+	}
> >+
> >+	/* For ConnectX-4 and ConnectX-4LX, need to check FW support */
> >+	if (pci_enable_device_mem(dev)) {
> >+		dev_warn(&dev->dev, "Can't enable device memory\n");
> >+		return;
> >+	}
> 
> It might be safer to set @broken_intx_masking in the failing path. On the
> following exit or failing path, the device needs to be disabled with function
> pci_disable_device(). Otherwise, &dev->enable_cnt, tracking if the device is
> enabled or not, will be unbalanced.
> 
> >+
> >+	/* Convert from PCI bus to resource space. */
> >+	fw_ver = ioremap(pci_resource_start(dev, 0), 4);
> >+	if (!fw_ver) {
> >+		dev_warn(&dev->dev, "Can't map ConnectX-4 initialization segment\n");
> >+		return;
> >+	}
> >+
> >+	/* Reading from resource space should be 32b aligned */
> >+	fw_maj_min = ioread32be(fw_ver);
> >+	fw_sub_min = ioread32be(fw_ver + 1);
> >+	fw_major = fw_maj_min & 0xffff;
> >+	fw_minor = fw_maj_min >> 16;
> >+	fw_subminor = fw_sub_min & 0xffff;
> >+	if (fw_minor > CONNECTX_4_CURR_MAX_MINOR ||
> >+	    fw_minor < CONNECTX_4_INTX_SUPPORT_MINOR)
> >+		dev_warn(&dev->dev, "ConnectX-4: FW %u.%u.%u doesn't support INTx masking, disabling. Please upgrade FW to %d.14.1100 and up for INTx support\n",
> >+			 fw_major, fw_minor, fw_subminor, dev->device ==
> >+			 PCI_DEVICE_ID_MELLANOX_CONNECTX4 ? 12 : 14);
> >+	else
> >+		dev->broken_intx_masking = 0;
> >+
> >+	iounmap(fw_ver);
> > }
> 
> Noa, it doesn't look quite correct: when a device ID doesn't match with
> anyone in the list, CONNECTIB, CONNECT4 or CONNECTX4_LX. The code goes
> though as it's CONNECT4 or CONNECT4_LX. The firmware version retrieved
> from MMIO register (BAR 0, offset 0/4) are checked. I don't think it's
> assured that the registers are for firmware version on the device. It
> seems you need more checks here: @broken_intx_masking is untouched and
> kept as 0 by default when the device ID isn't in the intrest list, which
> is the policy you introduced in PATCH[2/3]. Something like below would
> work:
> 
> static void mellanox_check_broken_intx_masking(struct pci_dev *pdev)
> {
>      /*
>       * Set @broken_intx_masking to 1 when device ID matches with
>       * anyone in the list. No code change to PATCH[2/3] is needed.
>       */
>      if (pdev->device in mellanox_broken_intx_devs) {
>          pdev->broken_intx_masking = 1;
>          return;
>      }
> 
>      if (dev->device == PCI_DEVICE_ID_MELLANOX_CONNECTIB)
>          return;
> 
>      if (dev->device != PCI_DEVICE_ID_MELLANOX_CONNECTX4 &&
>          dev->device != PCI_DEVICE_ID_MELLANOX_CONNECTX4_LE)
>          return;
> 
>      /* Check firmware version on CONNECT4 or CONNECT4_LE */
> }
> 
> >
> > DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX, PCI_ANY_ID,
> 
> Thanks,
> Gavin
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [patch] netlink.7: srcfix Change buffer size in example code about reading netlink message.
From: Rick Jones @ 2016-11-14 22:36 UTC (permalink / raw)
  To: dwilder, mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-man-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <e9409957290af5249750afa0f10de3a6-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

> Lets change the example so others don't propagate the problem further.
>
> Signed-off-by David Wilder <dwilder-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
>
> --- man7/netlink.7.orig 2016-11-14 13:30:36.522101156 -0800
> +++ man7/netlink.7      2016-11-14 13:30:51.002086354 -0800
> @@ -511,7 +511,7 @@
>  .in +4n
>  .nf
>  int len;
> -char buf[4096];
> +char buf[8192];

Since there doesn't seem to be a define one could use in the user space 
linux/netlink.h (?), but there are comments in the example code in the 
manpage, how about also including a brief comment to the effect that 
using 8192 bytes will avoid message truncation problems on platforms 
with a large PAGE_SIZE?

/* avoid msg truncation on > 4096 byte PAGE_SIZE platforms */

or something like that.

rick jones
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* THIS SERIES SHOULD BE: "[PATCH v4 00/13] VT-d unit test"
From: Peter Xu @ 2016-11-14 22:36 UTC (permalink / raw)
  To: kvm; +Cc: drjones, agordeev, jan.kiszka, rkrcmar, pbonzini
In-Reply-To: <1479162491-20764-1-git-send-email-peterx@redhat.com>

On Mon, Nov 14, 2016 at 05:27:58PM -0500, Peter Xu wrote:
> (Please ignore previous v3 version and use this one. My fault to not
>  configure base branch before publish :-( Sorry for the noise.)
> 
> This is v4 of vt-d unit test series.
> 
> Patch "libcflat: add IS_ALIGNED() macro, and page sizes" is picked up
> by Drew in the ARM GIC framework series, so please feel free to drop
> it when needed.
> 
> Online repo:
> 
>   https://github.com/xzpeter/kvm-unit-tests.git iommu-ut-v4
> 
> Please review. Thanks,

Ok this time the patches are correct but I forget to manually increase
the version number for git-publish.

Please... s/v3/v4/ in all patch titles and cover letter as well. Sorry
again. I won't repost if no one disagree.

Thanks,

-- peterx

^ permalink raw reply

* Re: "git subtree --squash" interacts poorly with revert, merge, and rebase
From: Matt McCutchen @ 2016-11-14 22:37 UTC (permalink / raw)
  To: git
In-Reply-To: <1478814800.2878.10.camel@mattmccutchen.net>

On Thu, 2016-11-10 at 16:53 -0500, Matt McCutchen wrote:
> On Wed, 2016-10-26 at 19:07 -0400, Matt McCutchen wrote:
> > 
> > Maybe we would never hit any of these problems in practice, but they
> > give me a bad enough feeling that I'm planning to write my own tool
> > that tracks the upstream commit ID in a file (like a submodule) and
> > doesn't generate any extra commits.  Without generating extra commits,
> > the only place to store the upstream content in the superproject would
> > be in another subtree, which would take up disk space in every working
> > tree unless developers manually set skip-worktree.  I think I prefer to
> > not store the upstream content and just have the tool fetch it from a
> > local subproject repository each time it's needed.
> > 
> > I'll of course post the tool on the web and would be happy to see it
> > integrated into "git subtree" if that makes sense, but I don't know how
> > much time I'd be willing to put into making that happen.
> 
> I have named my tool "git subtree-lite" and posted it here:
> 
> https://mattmccutchen.net/utils/git-subtree-lite.git/

As I was doing additional research in preparation for adding git-
subtree-lite to the tools page
(https://git.wiki.kernel.org/index.php/Interfaces,_frontends,_and_tools),
by chance I found an existing tool, Braid
(http://cristibalan.github.io/braid/), whose design meets my
requirements.  I have a few minor concerns, but assuming I'm able to
fix them without too much work and upstream accepts my patches, I plan
to switch to Braid.

I've made a properly marked section on the tools page for subproject
management tools:

https://git.wiki.kernel.org/index.php/Interfaces,_frontends,_and_tools#Subprojects_or_sets_of_repositories

in the hope that the next person with the same requirements as me finds
Braid.  (I unfortunately didn't check that page before starting, but I
will the next time I need something.)

Matt

^ permalink raw reply

* [U-Boot] [PULL 00/16] efi patch queue 2016-11-14
From: Alexander Graf @ 2016-11-14 22:37 UTC (permalink / raw)
  To: u-boot

Hi Tom,

This is my current patch queue for efi.  Please pull.

Alex


The following changes since commit 29e0cfb4f77f7aa369136302cee14a91e22dca71:

  Prepare v2016.11 (2016-11-14 11:27:11 -0500)

are available in the git repository at:

  git://github.com/agraf/u-boot.git tags/signed-efi-next

for you to fetch changes up to 58ad86288fd32f1f969ac654f2074c090f0abe32:

  x86: Enable EFI loader support (2016-11-14 23:24:04 +0100)

----------------------------------------------------------------
Patch queue for efi - 2016-11-14

Highlights this time around:

  - x86 efi_loader support
  - hello world efi test case
  - network device name is now representative
  - terminal output reports modes correctly

----------------------------------------------------------------
Emmanuel Vadot (1):
      efi_loader: console: Correctly report modes

Masahiro Yamada (1):
      efi_loader: fix depends on line of EFI_LOADER

Oleksandr Tymoshenko (1):
      efi: Use device device path type Messaging for network interface node

Simon Glass (13):
      x86: Correct a build warning in x86 tables
      efi: Correct cache flush alignment
      efi: Fix debug message address format
      x86: Tidy up selection of building the EFI stub
      efi: Makefile: Export variables for use with EFI
      efi: Add support for a hello world test program
      elf: arm: Add a few ARM relocation types
      efi: arm: Add EFI app support
      efi: arm: Add aarch64 EFI app support
      x86: Move efi .lds files into the 'lib' directory
      x86: Move efi .S files into the 'lib' directory
      efi: x86: Adjust EFI files support efi_loader
      x86: Enable EFI loader support

 Makefile                                           |  11 +-
 arch/arm/config.mk                                 |   7 ++
 arch/arm/cpu/armv8/config.mk                       |   4 +
 arch/arm/lib/Makefile                              |  10 ++
 arch/arm/lib/crt0_aarch64_efi.S                    | 135 ++++++++++++++++++++
 arch/arm/lib/crt0_arm_efi.S                        | 138 +++++++++++++++++++++
 arch/arm/lib/elf_aarch64_efi.lds                   |  70 +++++++++++
 arch/arm/lib/elf_arm_efi.lds                       |  70 +++++++++++
 arch/arm/lib/reloc_aarch64_efi.c                   |  87 +++++++++++++
 arch/arm/lib/reloc_arm_efi.c                       |  66 ++++++++++
 arch/arm/lib/relocate.S                            |   3 +-
 arch/arm/lib/relocate_64.S                         |   3 +-
 arch/x86/config.mk                                 |  20 ++-
 arch/x86/lib/Makefile                              |  23 ++++
 .../lib/{efi/crt0-efi-ia32.S => crt0_ia32_efi.S}   |   0
 .../{efi/crt0-efi-x86_64.S => crt0_x86_64_efi.S}   |   0
 arch/x86/lib/efi/Makefile                          |  18 ---
 arch/x86/{cpu/efi => lib}/elf_ia32_efi.lds         |   2 -
 arch/x86/{cpu/efi => lib}/elf_x86_64_efi.lds       |   2 -
 .../x86/lib/{efi/reloc_ia32.c => reloc_ia32_efi.c} |   0
 .../lib/{efi/reloc_x86_64.c => reloc_x86_64_efi.c} |   0
 arch/x86/lib/tables.c                              |   2 +
 cmd/Kconfig                                        |   9 ++
 cmd/bootefi.c                                      |  29 +++--
 configs/efi-x86_defconfig                          |   1 +
 doc/README.efi                                     |  14 +++
 doc/README.x86                                     |   1 -
 include/asm-generic/sections.h                     |   2 +
 include/efi.h                                      |   7 +-
 include/efi_api.h                                  |  13 ++
 include/elf.h                                      |  13 ++
 lib/efi/Makefile                                   |   4 +-
 lib/efi_loader/Kconfig                             |   2 +-
 lib/efi_loader/Makefile                            |   4 +
 lib/efi_loader/efi_console.c                       | 100 ++++++++++++---
 lib/efi_loader/efi_image_loader.c                  |   3 +-
 lib/efi_loader/efi_net.c                           |  17 +--
 lib/efi_loader/helloworld.c                        |  24 ++++
 scripts/Makefile.lib                               |  33 +++++
 39 files changed, 882 insertions(+), 65 deletions(-)
 create mode 100644 arch/arm/lib/crt0_aarch64_efi.S
 create mode 100644 arch/arm/lib/crt0_arm_efi.S
 create mode 100644 arch/arm/lib/elf_aarch64_efi.lds
 create mode 100644 arch/arm/lib/elf_arm_efi.lds
 create mode 100644 arch/arm/lib/reloc_aarch64_efi.c
 create mode 100644 arch/arm/lib/reloc_arm_efi.c
 rename arch/x86/lib/{efi/crt0-efi-ia32.S => crt0_ia32_efi.S} (100%)
 rename arch/x86/lib/{efi/crt0-efi-x86_64.S => crt0_x86_64_efi.S} (100%)
 rename arch/x86/{cpu/efi => lib}/elf_ia32_efi.lds (98%)
 rename arch/x86/{cpu/efi => lib}/elf_x86_64_efi.lds (98%)
 rename arch/x86/lib/{efi/reloc_ia32.c => reloc_ia32_efi.c} (100%)
 rename arch/x86/lib/{efi/reloc_x86_64.c => reloc_x86_64_efi.c} (100%)
 create mode 100644 lib/efi_loader/helloworld.c

^ permalink raw reply


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.