From: Peter Xu <peterx@redhat.com>
To: Alexander Gordeev <agordeev@redhat.com>
Cc: qemu-devel@nongnu.org, kvm@vger.kernel.org, drjones@redhat.com,
jan.kiszka@web.de, rkrcmar@redhat.com, pbonzini@redhat.com
Subject: Re: [kvm-unit-tests PATCH v8 12/14] x86: intel-iommu: add dmar test
Date: Tue, 3 Jan 2017 19:16:16 +0800 [thread overview]
Message-ID: <20170103111616.GI22664@pxdev.xzpeter.org> (raw)
In-Reply-To: <20170103103326.GA4280@agordeev.lab.eng.brq.redhat.com>
On Tue, Jan 03, 2017 at 11:33:27AM +0100, Alexander Gordeev wrote:
> On Mon, Dec 12, 2016 at 11:08:18AM +0800, Peter Xu wrote:
> > DMAR test is based on QEMU edu device. A 4B DMA memory copy is carried
> > out as the simplest DMAR test.
>
> Hi Peter,
>
> Sorry for missing to provide feedback on your series.
> I did just a cursory review, but did not notice few issue below.
>
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> > lib/pci.h | 5 ++
> > lib/x86/intel-iommu.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > lib/x86/intel-iommu.h | 4 ++
> > x86/Makefile.common | 1 +
> > x86/intel-iommu.c | 51 +++++++++++++++++++
> > 5 files changed, 194 insertions(+)
> >
> > diff --git a/lib/pci.h b/lib/pci.h
> > index d3052ef..26968b1 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 resource[PCI_BAR_NUM];
> > @@ -28,6 +31,8 @@ extern void pci_scan_bars(struct pci_dev *dev);
> > extern void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr);
> > extern 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 1887998..86b1805 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)
> > @@ -83,6 +119,103 @@ 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 *)(phys_to_virt(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_PHYS_TO_VIRT(x) \
> > + ((void *)(((uint64_t)phys_to_virt(x)) >> VTD_PAGE_SHIFT))
>
> I would say this macro is rather superfluous.
>
> > +/**
> > + * 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) >> VTD_PAGE_SHIFT;
> > + re->present = 1;
> > + printf("allocated vt-d root entry for PCI bus %d\n",
> > + bus_n);
> > + } else
> > + ce = VTD_PHYS_TO_VIRT(re->context_table_p);
>
> Seems, it should be instead something like:
>
> ce = phys_to_virt(re->context_table_p << VTD_PAGE_SHIFT);
Oops, you are right. It didn't encounter issue since current DMAR test
is too simple and only allocated one single page. :-)
I'll post a fix soon. Thanks!
-- peterx
WARNING: multiple messages have this Message-ID (diff)
From: Peter Xu <peterx@redhat.com>
To: Alexander Gordeev <agordeev@redhat.com>
Cc: qemu-devel@nongnu.org, kvm@vger.kernel.org, drjones@redhat.com,
jan.kiszka@web.de, rkrcmar@redhat.com, pbonzini@redhat.com
Subject: Re: [Qemu-devel] [kvm-unit-tests PATCH v8 12/14] x86: intel-iommu: add dmar test
Date: Tue, 3 Jan 2017 19:16:16 +0800 [thread overview]
Message-ID: <20170103111616.GI22664@pxdev.xzpeter.org> (raw)
In-Reply-To: <20170103103326.GA4280@agordeev.lab.eng.brq.redhat.com>
On Tue, Jan 03, 2017 at 11:33:27AM +0100, Alexander Gordeev wrote:
> On Mon, Dec 12, 2016 at 11:08:18AM +0800, Peter Xu wrote:
> > DMAR test is based on QEMU edu device. A 4B DMA memory copy is carried
> > out as the simplest DMAR test.
>
> Hi Peter,
>
> Sorry for missing to provide feedback on your series.
> I did just a cursory review, but did not notice few issue below.
>
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> > lib/pci.h | 5 ++
> > lib/x86/intel-iommu.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > lib/x86/intel-iommu.h | 4 ++
> > x86/Makefile.common | 1 +
> > x86/intel-iommu.c | 51 +++++++++++++++++++
> > 5 files changed, 194 insertions(+)
> >
> > diff --git a/lib/pci.h b/lib/pci.h
> > index d3052ef..26968b1 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 resource[PCI_BAR_NUM];
> > @@ -28,6 +31,8 @@ extern void pci_scan_bars(struct pci_dev *dev);
> > extern void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr);
> > extern 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 1887998..86b1805 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)
> > @@ -83,6 +119,103 @@ 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 *)(phys_to_virt(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_PHYS_TO_VIRT(x) \
> > + ((void *)(((uint64_t)phys_to_virt(x)) >> VTD_PAGE_SHIFT))
>
> I would say this macro is rather superfluous.
>
> > +/**
> > + * 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) >> VTD_PAGE_SHIFT;
> > + re->present = 1;
> > + printf("allocated vt-d root entry for PCI bus %d\n",
> > + bus_n);
> > + } else
> > + ce = VTD_PHYS_TO_VIRT(re->context_table_p);
>
> Seems, it should be instead something like:
>
> ce = phys_to_virt(re->context_table_p << VTD_PAGE_SHIFT);
Oops, you are right. It didn't encounter issue since current DMAR test
is too simple and only allocated one single page. :-)
I'll post a fix soon. Thanks!
-- peterx
next prev parent reply other threads:[~2017-01-03 11:16 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-12 3:08 [kvm-unit-tests PATCH v8 00/14] VT-d unit test Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 01/14] pci: fix missing extern for pci_testdev() Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 02/14] x86/asm: add cpu_relax() Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 03/14] libcflat: introduce is_power_of_2() Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 04/14] x86: intel-iommu: add vt-d init test Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 05/14] libcflat: add IS_ALIGNED() macro, and page sizes Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 06/14] libcflat: moving MIN/MAX here Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 07/14] vm/page: provide PGDIR_OFFSET() macro Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 08/14] pci: introduce struct pci_dev Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 09/14] pci: provide pci_scan_bars() Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 10/14] pci: provide pci_enable_defaults() Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 11/14] pci: edu: introduce pci-edu helpers Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 12/14] x86: intel-iommu: add dmar test Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2017-01-03 10:33 ` Alexander Gordeev
2017-01-03 10:33 ` [Qemu-devel] " Alexander Gordeev
2017-01-03 11:16 ` Peter Xu [this message]
2017-01-03 11:16 ` Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 13/14] pci: add msi support for 32/64bit address Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-12 3:08 ` [kvm-unit-tests PATCH v8 14/14] x86: intel-iommu: add IR MSI test Peter Xu
2016-12-12 3:08 ` [Qemu-devel] " Peter Xu
2016-12-22 11:06 ` [Qemu-devel] [kvm-unit-tests PATCH v8 00/14] VT-d unit test Andrew Jones
2016-12-22 11:52 ` Paolo Bonzini
2016-12-23 3:44 ` Peter Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170103111616.GI22664@pxdev.xzpeter.org \
--to=peterx@redhat.com \
--cc=agordeev@redhat.com \
--cc=drjones@redhat.com \
--cc=jan.kiszka@web.de \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=rkrcmar@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.