|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 5/5] vtd: Move intremap table to xenheap
Interrupt remapping entries often needs to be accessed, and we're creating
pointers to it on demand, which brings a lot of complexity (e.g
GET_IREMAP_ENTRY() macro), move it to xenheap such that it's persistently
mapped and we won't have to worry about mapping and unmapping individual
intremap table pages.
Signed-off-by: Teddy Astie <teddy.astie@xxxxxxxxxx>
---
xen/drivers/passthrough/vtd/intremap.c | 61 +++++++++-----------------
xen/drivers/passthrough/vtd/iommu.h | 16 +------
xen/drivers/passthrough/vtd/utils.c | 22 +++-------
3 files changed, 26 insertions(+), 73 deletions(-)
diff --git a/xen/drivers/passthrough/vtd/intremap.c
b/xen/drivers/passthrough/vtd/intremap.c
index dd2788efd7..fc683516cb 100644
--- a/xen/drivers/passthrough/vtd/intremap.c
+++ b/xen/drivers/passthrough/vtd/intremap.c
@@ -17,6 +17,7 @@
* Copyright (C) Xiaohui Xin <xiaohui.xin@xxxxxxxxx>
*/
+#include <xen/mm.h>
#include <xen/irq.h>
#include <xen/sched.h>
#include <xen/iommu.h>
@@ -208,21 +209,19 @@ static void update_irte(struct vtd_iommu *iommu, struct
iremap_entry *entry,
/* Mark specified intr remap entry as free */
static void free_remap_entry(struct vtd_iommu *iommu, int index)
{
- struct iremap_entry *iremap_entry = NULL, *iremap_entries, new_ire = { };
+ struct iremap_entry *iremap_entry = NULL, new_ire = { };
if ( index < 0 || index > IREMAP_ENTRY_NR - 1 )
return;
ASSERT(spin_is_locked(&iommu->intremap.lock));
- GET_IREMAP_ENTRY(iommu->intremap.maddr, index,
- iremap_entries, iremap_entry);
+ iremap_entry = &iommu->intremap.entries[index];
update_irte(iommu, iremap_entry, &new_ire, false);
iommu_sync_cache(iremap_entry, sizeof(*iremap_entry));
iommu_flush_iec_index(iommu, 0, index);
- unmap_vtd_domain_page(iremap_entries);
iommu->intremap.num--;
}
@@ -232,25 +231,13 @@ static void free_remap_entry(struct vtd_iommu *iommu, int
index)
*/
static unsigned int alloc_remap_entry(struct vtd_iommu *iommu, unsigned int nr)
{
- struct iremap_entry *iremap_entries = NULL;
unsigned int i, found;
ASSERT(spin_is_locked(&iommu->intremap.lock));
for ( found = i = 0; i < IREMAP_ENTRY_NR; i++ )
{
- struct iremap_entry *p;
- if ( i % (1 << IREMAP_ENTRY_ORDER) == 0 )
- {
- /* This entry across page boundry */
- if ( iremap_entries )
- unmap_vtd_domain_page(iremap_entries);
-
- GET_IREMAP_ENTRY(iommu->intremap.maddr, i,
- iremap_entries, p);
- }
- else
- p = &iremap_entries[i % (1 << IREMAP_ENTRY_ORDER)];
+ struct iremap_entry *p = &iommu->intremap.entries[i];
if ( p->val ) /* not a free entry */
found = 0;
@@ -258,9 +245,6 @@ static unsigned int alloc_remap_entry(struct vtd_iommu
*iommu, unsigned int nr)
break;
}
- if ( iremap_entries )
- unmap_vtd_domain_page(iremap_entries);
-
if ( i < IREMAP_ENTRY_NR )
iommu->intremap.num += nr;
@@ -270,7 +254,7 @@ static unsigned int alloc_remap_entry(struct vtd_iommu
*iommu, unsigned int nr)
static int remap_entry_to_ioapic_rte(
struct vtd_iommu *iommu, int index, struct IO_APIC_route_entry *old_rte)
{
- struct iremap_entry *iremap_entry = NULL, *iremap_entries;
+ struct iremap_entry *iremap_entry = NULL;
unsigned long flags;
if ( index < 0 || index > IREMAP_ENTRY_NR - 1 )
@@ -283,15 +267,13 @@ static int remap_entry_to_ioapic_rte(
spin_lock_irqsave(&iommu->intremap.lock, flags);
- GET_IREMAP_ENTRY(iommu->intremap.maddr, index,
- iremap_entries, iremap_entry);
+ iremap_entry = &iommu->intremap.entries[index];
if ( iremap_entry->val == 0 )
{
dprintk(XENLOG_ERR VTDPREFIX,
"IO-APIC index (%d) has an empty entry\n",
index);
- unmap_vtd_domain_page(iremap_entries);
spin_unlock_irqrestore(&iommu->intremap.lock, flags);
return -EFAULT;
}
@@ -309,7 +291,6 @@ static int remap_entry_to_ioapic_rte(
old_rte->dest.logical.logical_dest = iremap_entry->remap.dst >> 8;
}
- unmap_vtd_domain_page(iremap_entries);
spin_unlock_irqrestore(&iommu->intremap.lock, flags);
return 0;
@@ -319,7 +300,7 @@ static int ioapic_rte_to_remap_entry(struct vtd_iommu
*iommu,
int apic, unsigned int ioapic_pin, struct IO_APIC_route_entry *old_rte,
struct IO_APIC_route_entry new_rte)
{
- struct iremap_entry *iremap_entry = NULL, *iremap_entries;
+ struct iremap_entry *iremap_entry = NULL;
struct iremap_entry new_ire;
struct IO_APIC_route_remap_entry *remap_rte;
int index;
@@ -347,8 +328,7 @@ static int ioapic_rte_to_remap_entry(struct vtd_iommu
*iommu,
return -EFAULT;
}
- GET_IREMAP_ENTRY(iommu->intremap.maddr, index,
- iremap_entries, iremap_entry);
+ iremap_entry = &iommu->intremap.entries[index];
new_ire = *iremap_entry;
@@ -388,7 +368,6 @@ static int ioapic_rte_to_remap_entry(struct vtd_iommu
*iommu,
iommu_sync_cache(iremap_entry, sizeof(*iremap_entry));
iommu_flush_iec_index(iommu, 0, index);
- unmap_vtd_domain_page(iremap_entries);
spin_unlock_irqrestore(&iommu->intremap.lock, flags);
return 0;
}
@@ -500,7 +479,7 @@ static int msi_msg_to_remap_entry(
struct vtd_iommu *iommu, struct pci_dev *pdev,
struct msi_desc *msi_desc, struct msi_msg *msg)
{
- struct iremap_entry *iremap_entry = NULL, *iremap_entries, new_ire = { };
+ struct iremap_entry *iremap_entry = NULL, new_ire = { };
struct msi_msg_remap_entry *remap_rte;
unsigned int index, i, nr = 1;
unsigned long flags;
@@ -556,8 +535,7 @@ static int msi_msg_to_remap_entry(
return -EFAULT;
}
- GET_IREMAP_ENTRY(iommu->intremap.maddr, index,
- iremap_entries, iremap_entry);
+ iremap_entry = &iommu->intremap.entries[index];
if ( !pi_desc )
{
@@ -604,7 +582,6 @@ static int msi_msg_to_remap_entry(
iommu_sync_cache(iremap_entry, sizeof(*iremap_entry));
iommu_flush_iec_index(iommu, 0, index);
- unmap_vtd_domain_page(iremap_entries);
spin_unlock_irqrestore(&iommu->intremap.lock, flags);
return alloc;
@@ -628,7 +605,7 @@ int __init cf_check intel_setup_hpet_msi(struct msi_desc
*msi_desc)
unsigned long flags;
int rc = 0;
- if ( !iommu->intremap.maddr )
+ if ( !iommu->intremap.entries )
return 0;
spin_lock_irqsave(&iommu->intremap.lock, flags);
@@ -663,7 +640,7 @@ int enable_intremap(struct vtd_iommu *iommu, int eim)
sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
/* Return if already enabled by Xen */
- if ( (sts & DMA_GSTS_IRES) && iommu->intremap.maddr )
+ if ( (sts & DMA_GSTS_IRES) && iommu->intremap.entries )
return 0;
if ( !(sts & DMA_GSTS_QIES) )
@@ -679,16 +656,18 @@ int enable_intremap(struct vtd_iommu *iommu, int eim)
" Compatibility Format Interrupts permitted on IOMMU #%u:"
" Device pass-through will be insecure\n", iommu->index);
- if ( iommu->intremap.maddr == 0 )
+ if ( !iommu->intremap.entries )
{
- iommu->intremap.maddr = alloc_pgtable_maddr(IREMAP_ARCH_PAGE_NR,
- iommu->node);
- if ( iommu->intremap.maddr == 0 )
+ iommu->intremap.entries =
+ alloc_xenheap_pages(get_order_from_pages(IREMAP_ARCH_PAGE_NR),
+ MEMF_node(iommu->node));
+ if ( !iommu->intremap.entries )
{
dprintk(XENLOG_WARNING VTDPREFIX,
- "Cannot allocate memory for ir_ctrl->iremap_maddr\n");
+ "Cannot allocate memory for iommu->intremap.entries\n");
return -ENOMEM;
}
+ memset(iommu->intremap.entries, 0, IREMAP_ARCH_PAGE_NR * PAGE_SIZE);
iommu->intremap.num = 0;
}
@@ -700,7 +679,7 @@ int enable_intremap(struct vtd_iommu *iommu, int eim)
* Interrupt Mode.
*/
dmar_writeq(iommu->reg, DMAR_IRTA_REG,
- iommu->intremap.maddr | IRTA_REG_TABLE_SIZE |
+ virt_to_maddr(iommu->intremap.entries) | IRTA_REG_TABLE_SIZE |
(eim ? IRTA_EIME : 0));
/* set SIRTP */
diff --git a/xen/drivers/passthrough/vtd/iommu.h
b/xen/drivers/passthrough/vtd/iommu.h
index ccb00889d7..0cd2c2ef3a 100644
--- a/xen/drivers/passthrough/vtd/iommu.h
+++ b/xen/drivers/passthrough/vtd/iommu.h
@@ -357,20 +357,6 @@ struct iremap_entry {
#define iremap_set_present(v) do {(v).lo |= 1;} while(0)
#define iremap_clear_present(v) do {(v).lo &= ~1;} while(0)
-/*
- * Get the intr remap entry:
- * maddr - machine addr of the table
- * index - index of the entry
- * entries - return addr of the page holding this entry, need unmap it
- * entry - return required entry
- */
-#define GET_IREMAP_ENTRY(maddr, index, entries, entry) \
-do { \
- entries = (struct iremap_entry *)map_vtd_domain_page( \
- (maddr) + (( (index) >> IREMAP_ENTRY_ORDER ) << PAGE_SHIFT ) ); \
- entry = &entries[(index) % (1 << IREMAP_ENTRY_ORDER)]; \
-} while(0)
-
/* queue invalidation entry */
struct qinval_entry {
union {
@@ -491,7 +477,7 @@ struct vtd_iommu {
uint64_t qinval_maddr; /* queue invalidation page machine address */
struct {
- uint64_t maddr; /* interrupt remap table machine address */
+ struct iremap_entry *entries; /* interrupt remap table entries */
unsigned int num; /* total num of used interrupt remap entry */
spinlock_t lock; /* lock for irq remapping table */
} intremap;
diff --git a/xen/drivers/passthrough/vtd/utils.c
b/xen/drivers/passthrough/vtd/utils.c
index 7c4d032f4f..3ae4d35e2d 100644
--- a/xen/drivers/passthrough/vtd/utils.c
+++ b/xen/drivers/passthrough/vtd/utils.c
@@ -187,11 +187,12 @@ void cf_check vtd_dump_iommu_info(unsigned char key)
{
/* Dump interrupt remapping table. */
uint64_t irta = dmar_readq(iommu->reg, DMAR_IRTA_REG);
- uint64_t iremap_maddr = irta & PAGE_MASK;
unsigned int nr_entry = 1 << ((irta & 0xF) + 1);
- struct iremap_entry *iremap_entries = NULL;
unsigned int print_cnt = 0;
+ /* Hardware must be using the same table as us. */
+ ASSERT((irta & PAGE_MASK) ==
virt_to_maddr(iommu->intremap.entries));
+
printk(" Interrupt remapping table (nr_entry=%#x. "
"Only dump P=1 entries here):\n", nr_entry);
printk("R means remapped format, P means posted format.\n");
@@ -199,18 +200,7 @@ void cf_check vtd_dump_iommu_info(unsigned char key)
printk("P: SVT SQ SID V AVL FPD PDA URG
P\n");
for ( i = 0; i < nr_entry; i++ )
{
- struct iremap_entry *p;
- if ( i % (1 << IREMAP_ENTRY_ORDER) == 0 )
- {
- /* This entry across page boundry */
- if ( iremap_entries )
- unmap_vtd_domain_page(iremap_entries);
-
- GET_IREMAP_ENTRY(iremap_maddr, i,
- iremap_entries, p);
- }
- else
- p = &iremap_entries[i % (1 << IREMAP_ENTRY_ORDER)];
+ struct iremap_entry *p = &iommu->intremap.entries[i];
if ( !p->remap.p )
continue;
@@ -231,8 +221,6 @@ void cf_check vtd_dump_iommu_info(unsigned char key)
print_cnt++;
}
- if ( iremap_entries )
- unmap_vtd_domain_page(iremap_entries);
if ( iommu->intremap.num != print_cnt )
printk("Warning: Print %u IRTE (actually have %u)!\n",
print_cnt, iommu->intremap.num);
@@ -251,7 +239,7 @@ void cf_check vtd_dump_iommu_info(unsigned char key)
{
iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid);
- if ( !iommu->intremap.maddr || !iommu->intremap.num )
+ if ( !iommu->intremap.entries || !iommu->intremap.num )
continue;
printk( "\nRedirection table of IOAPIC %x:\n", apic);
--
2.54.0
--
Teddy Astie | Vates XCP-ng Developer
XCP-ng & Xen Orchestra - Vates solutions
web: https://vates.tech
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |