All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lan Tianyu <tianyu.lan@intel.com>
To: xen-devel@lists.xen.org
Cc: Lan Tianyu <tianyu.lan@intel.com>,
	andrew.cooper3@citrix.com, kevin.tian@intel.com,
	jbeulich@suse.com, chao.gao@intel.com
Subject: [RFC PATCH 13/23] X86/vvtd: Process interrupt remapping request
Date: Fri, 17 Mar 2017 19:27:13 +0800	[thread overview]
Message-ID: <1489750043-17260-14-git-send-email-tianyu.lan@intel.com> (raw)
In-Reply-To: <1489750043-17260-1-git-send-email-tianyu.lan@intel.com>

From: Chao Gao <chao.gao@intel.com>

When a remapping interrupt request arrives, remapping hardware computes the
interrupt_index per the algorithm described in VTD spec
"Interrupt Remapping Table", interprets the IRTE and generates a remapped
interrupte request.

In this patch, a new function viommu_handle_irq_request() is introduced to
emulate the process how remapping hardware handles a remapping interrupt
request.

Signed-off-by: Chao Gao <chao.gao@intel.com>
Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
---
 xen/arch/x86/hvm/vvtd.c                | 295 ++++++++++++++++++++++++++++++++-
 xen/drivers/passthrough/vtd/iommu.h    |  15 ++
 xen/include/public/arch-x86/hvm/save.h |  18 ++
 xen/include/xen/hvm/irq.h              |   2 +
 4 files changed, 329 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/hvm/vvtd.c b/xen/arch/x86/hvm/vvtd.c
index a12b4d1..c5df77d 100644
--- a/xen/arch/x86/hvm/vvtd.c
+++ b/xen/arch/x86/hvm/vvtd.c
@@ -23,9 +23,13 @@
 #include <xen/types.h>
 #include <xen/viommu.h>
 #include <xen/xmalloc.h>
+#include <asm/apic.h>
 #include <asm/current.h>
+#include <asm/event.h>
 #include <asm/hvm/domain.h>
+#include <asm/io_apic.h>
 #include <asm/page.h>
+#include <asm/p2m.h>
 #include <public/viommu.h>
 
 #include "../../../drivers/passthrough/vtd/iommu.h"
@@ -38,6 +42,9 @@ struct hvm_hw_vvtd_regs {
 #define VIOMMU_STATUS_IRQ_REMAPPING_ENABLED     (1 << 0)
 #define VIOMMU_STATUS_DMA_REMAPPING_ENABLED     (1 << 1)
 
+#define vvtd_irq_remapping_enabled(vvtd) \
+            (vvtd->status & VIOMMU_STATUS_IRQ_REMAPPING_ENABLED)
+
 struct vvtd {
     /* VIOMMU_STATUS_XXX_REMAPPING_ENABLED */
     int status;
@@ -119,6 +126,138 @@ static inline uint8_t vvtd_get_reg_byte(struct vvtd *vtd, uint32_t reg)
     vvtd_set_reg(vvtd, (reg) + 4, (uint32_t)((val) >> 32)); \
 } while(0)
 
+static int map_guest_page(struct domain *d, uint64_t gfn, void **virt)
+{
+    struct page_info *p;
+
+    p = get_page_from_gfn(d, gfn, NULL, P2M_ALLOC);
+    if ( !p )
+        return -EINVAL;
+
+    if ( !get_page_type(p, PGT_writable_page) )
+    {
+        put_page(p);
+        return -EINVAL;
+    }
+
+    *virt = __map_domain_page_global(p);
+    if ( !*virt )
+    {
+        put_page_and_type(p);
+        return -ENOMEM;
+    }
+    return 0;
+}
+
+static void unmap_guest_page(void *virt)
+{
+    struct page_info *page;
+
+    if ( !virt )
+        return;
+
+    virt = (void *)((unsigned long)virt & PAGE_MASK);
+    page = mfn_to_page(domain_page_map_to_mfn(virt));
+
+    unmap_domain_page_global(virt);
+    put_page_and_type(page);
+}
+
+static void vvtd_inj_irq(
+    struct vlapic *target,
+    uint8_t vector,
+    uint8_t trig_mode,
+    uint8_t delivery_mode)
+{
+    VVTD_DEBUG(VVTD_DBG_INFO, "dest=v%d, delivery_mode=%x vector=%d "
+               "trig_mode=%d.",
+               vlapic_vcpu(target)->vcpu_id, delivery_mode,
+               vector, trig_mode);
+
+    ASSERT((delivery_mode == dest_Fixed) ||
+           (delivery_mode == dest_LowestPrio));
+
+    vlapic_set_irq(target, vector, trig_mode);
+}
+
+static int vvtd_delivery(
+    struct domain *d, int vector,
+    uint32_t dest, uint8_t dest_mode,
+    uint8_t delivery_mode, uint8_t trig_mode)
+{
+    struct vlapic *target;
+    struct vcpu *v;
+
+    switch ( delivery_mode )
+    {
+    case dest_LowestPrio:
+        target = vlapic_lowest_prio(d, NULL, 0, dest, dest_mode);
+        if ( target != NULL )
+        {
+            vvtd_inj_irq(target, vector, trig_mode, delivery_mode);
+            break;
+        }
+        VVTD_DEBUG(VVTD_DBG_INFO, "null round robin: vector=%02x\n", vector);
+        break;
+
+    case dest_Fixed:
+        for_each_vcpu ( d, v )
+            if ( vlapic_match_dest(vcpu_vlapic(v), NULL, 0, dest,
+                                   dest_mode) )
+                vvtd_inj_irq(vcpu_vlapic(v), vector,
+                             trig_mode, delivery_mode);
+        break;
+
+    case dest_NMI:
+        for_each_vcpu ( d, v )
+            if ( vlapic_match_dest(vcpu_vlapic(v), NULL, 0, dest, dest_mode)
+                 && !test_and_set_bool(v->nmi_pending) )
+                vcpu_kick(v);
+        break;
+
+    default:
+        printk(XENLOG_G_WARNING
+               "%pv: Unsupported VTD delivery mode %d for Dom%d\n",
+               current, delivery_mode, d->domain_id);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+static uint32_t irq_remapping_request_index(struct irq_remapping_request *irq)
+{
+    switch ( irq->type )
+    {
+    case VIOMMU_REQUEST_IRQ_MSI:
+        return IR_MSI_INDEX(irq->msg.msi.data, irq->msg.msi.addr);
+
+    case VIOMMU_REQUEST_IRQ_APIC:
+        return IR_IOAPIC_RTE_INDEX((struct ir_ioapic_rte *)&irq->msg.rte);
+
+    default:
+        break;
+    }
+    BUG();
+    return 0;
+}
+
+static inline uint32_t irte_dest(struct vvtd *vvtd,
+                                 struct iremap_entry *irte)
+{
+    uint64_t irta;
+
+    /* In xAPIC mode, only 8-bits([15:8]) are valid*/
+    vvtd_get_reg_quad(vvtd, DMAR_IRTA_REG, irta);
+    return (irta & IRTA_EIME) ? irte->remap.dst : (irte->remap.dst) >> 8 & 0xff;
+}
+
+static int vvtd_log_fault(struct vvtd *vvtd, struct irq_remapping_request *irq,
+                          int reason)
+{
+    return 0;
+}
+
 static int vvtd_handle_gcmd_sirtp(struct vvtd *vvtd, unsigned long val)
 {
     uint64_t irta;
@@ -276,6 +415,159 @@ static const struct hvm_mmio_ops vvtd_mmio_ops = {
     .write = vvtd_write
 };
 
+static bool ir_sid_valid(struct iremap_entry *irte, uint32_t source_id)
+{
+    return TRUE;
+}
+
+/* @log_fault: a flag to indicate whether we need log a fault when checking
+ * vIRTE. (1 means logging it, 0 means ignoring the fault). log_fault = 0 is
+ * used in parse process in which only the encoded attributes is cared.
+ */
+static int vvtd_get_entry(struct vvtd *vvtd,
+                          struct irq_remapping_request *irq,
+                          struct iremap_entry *dest,
+                          bool log_fault)
+{
+    int ret;
+    uint32_t entry = irq_remapping_request_index(irq);
+    struct iremap_entry  *irte, *irt_page;
+
+    ASSERT(entry < IREMAP_ENTRY_NR);
+
+    if ( entry > vvtd->irt_max_entry )
+    {
+        ret = VTD_FR_IR_INDEX_OVER;
+        goto handle_fault;
+    }
+
+    ret = map_guest_page(vvtd->domain, vvtd->irt + (entry >> IREMAP_ENTRY_ORDER),
+                         (void**)&irt_page);
+    if ( ret )
+    {
+        ret = VTD_FR_IR_ROOT_INVAL;
+        goto handle_fault;
+    }
+
+    irte = irt_page + (entry % (1 << IREMAP_ENTRY_ORDER));
+    dest->val = irte->val;
+    if ( !qinval_present(*irte) )
+    {
+        ret = VTD_FR_IR_ENTRY_P;
+        goto unmap_handle_fault;
+    }
+
+    /* Check reserved bits */
+    if ( (irte->remap.res_1 || irte->remap.res_2 || irte->remap.res_3 ||
+          irte->remap.res_4) )
+    {
+        ret = VTD_FR_IR_IRTE_RSVD;
+        goto unmap_handle_fault;
+    }
+
+    /* TODO:Intel64 platforms block compatibility format interrupt request */
+
+    if (!ir_sid_valid(irte, irq->source_id))
+    {
+        ret = VTD_FR_IR_SID_ERR;
+        goto unmap_handle_fault;
+    }
+    unmap_guest_page(irt_page);
+    return 0;
+
+unmap_handle_fault:
+    unmap_guest_page(irt_page);
+handle_fault:
+    if ( !log_fault )
+        goto out;
+
+    switch ( ret )
+    {
+    case VTD_FR_IR_SID_ERR:
+    case VTD_FR_IR_IRTE_RSVD:
+    case VTD_FR_IR_ENTRY_P:
+        if ( qinval_fault_disable(*irte) )
+            break;
+    /* fall through */
+    case VTD_FR_IR_INDEX_OVER:
+    case VTD_FR_IR_ROOT_INVAL:
+        vvtd_log_fault(vvtd, irq, ret);
+        break;
+
+    default:
+        gdprintk(XENLOG_G_INFO, "Can't handle VT-d fault %x\n", ret);
+        goto out;
+    }
+out:
+    return ret;
+}
+
+static int vvtd_ioapic_check(struct vvtd *vvtd,
+                             struct ir_ioapic_rte rte)
+{
+    VVTD_DEBUG(VVTD_DBG_INFO, "IOAPIC (%lx)", *(uint64_t *)&(rte));
+    ASSERT(rte.format);
+
+    if ( rte.reserved || rte.reserved1 || rte.reserved2[0] ||
+         rte.reserved2[1] || rte.reserved2[2] )
+        return VTD_FR_IR_REQ_RSVD;
+    return 0;
+}
+
+static int vvtd_msi_check(struct vvtd *vvtd,
+                          uint32_t data,
+                          uint64_t addr)
+{
+    ASSERT((addr >> 20) == 0xfee);
+    return 0;
+}
+
+static int vvtd_irq_request_sanity_check(struct vvtd *vvtd,
+                                         struct irq_remapping_request *irq)
+{
+    switch ( irq->type )
+    {
+    case VIOMMU_REQUEST_IRQ_MSI:
+        return vvtd_msi_check(vvtd, irq->msg.msi.data, irq->msg.msi.addr);
+
+    case VIOMMU_REQUEST_IRQ_APIC:
+        return vvtd_ioapic_check(vvtd, *(struct ir_ioapic_rte *)&irq->msg.rte);
+
+    default:
+        break;
+    }
+
+    BUG();
+    return 0;
+}
+
+static int vvtd_handle_irq_request(struct domain *d,
+                                   struct irq_remapping_request *irq)
+{
+    struct iremap_entry irte;
+    int ret;
+    struct vvtd *vvtd = domain_vvtd(d);
+
+    if ( !vvtd || !vvtd_irq_remapping_enabled(vvtd) )
+        return -EINVAL;
+
+    ret = vvtd_irq_request_sanity_check(vvtd, irq);
+    if ( ret )
+    {
+        vvtd_log_fault(vvtd, irq, ret);
+        return ret;
+    }
+
+    if ( !vvtd_get_entry(vvtd, irq, &irte, 1) )
+    {
+        vvtd_delivery(vvtd->domain, irte.remap.vector,
+                      irte_dest(vvtd, &irte), irte.remap.dm,
+                      irte.remap.dlm, irte.remap.tm);
+        return 0;
+    }
+    return -EFAULT;
+}
+
 static void vvtd_reset(struct vvtd *vvtd, uint64_t capability)
 {
     uint64_t cap, ecap;
@@ -374,5 +666,6 @@ static int vvtd_destroy(struct viommu *viommu)
 struct viommu_ops vvtd_hvm_vmx_ops = {
     .query_caps = vvtd_query_caps,
     .create = vvtd_create,
-    .destroy = vvtd_destroy
+    .destroy = vvtd_destroy,
+    .handle_irq_request = vvtd_handle_irq_request
 };
diff --git a/xen/drivers/passthrough/vtd/iommu.h b/xen/drivers/passthrough/vtd/iommu.h
index fd040d0..aa1f1a6 100644
--- a/xen/drivers/passthrough/vtd/iommu.h
+++ b/xen/drivers/passthrough/vtd/iommu.h
@@ -247,6 +247,21 @@
 #define dma_frcd_source_id(c) (c & 0xffff)
 #define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */
 
+enum VTD_FAULT_TYPE
+{
+    /* Interrupt remapping transition faults */
+    VTD_FR_IR_REQ_RSVD = 0x20,   /* One or more IR request reserved
+                                  * fields set */
+    VTD_FR_IR_INDEX_OVER = 0x21, /* Index value greater than max */
+    VTD_FR_IR_ENTRY_P = 0x22,    /* Present (P) not set in IRTE */
+    VTD_FR_IR_ROOT_INVAL = 0x23, /* IR Root table invalid */
+    VTD_FR_IR_IRTE_RSVD = 0x24,  /* IRTE Rsvd field non-zero with
+                                  * Present flag set */
+    VTD_FR_IR_REQ_COMPAT = 0x25, /* Encountered compatible IR
+                                  * request while disabled */
+    VTD_FR_IR_SID_ERR = 0x26,    /* Invalid Source-ID */
+};
+
 /*
  * 0: Present
  * 1-11: Reserved
diff --git a/xen/include/public/arch-x86/hvm/save.h b/xen/include/public/arch-x86/hvm/save.h
index 419a3b2..6127f89 100644
--- a/xen/include/public/arch-x86/hvm/save.h
+++ b/xen/include/public/arch-x86/hvm/save.h
@@ -363,6 +363,24 @@ DECLARE_HVM_SAVE_TYPE(PIC, 3, struct hvm_hw_vpic);
 
 #define VIOAPIC_NUM_PINS  48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */
 
+struct ir_ioapic_rte
+{
+    uint8_t vector;
+    uint8_t reserved:3; /* Reserved(0) */
+    uint8_t index2:1;   /* Interrupt Index [15] */
+    uint8_t delivery_status:1;
+    uint8_t polarity:1;
+    uint8_t remote_irr:1;
+    uint8_t trig_mode:1;
+    uint8_t mask:1;
+    uint8_t reserved1:7; /* Reserved(0) */
+    uint8_t reserved2[3]; /* Reserved(0) */
+    uint16_t format:1; /* Should always be 1 */
+    uint16_t index1:15; /* Interrupt Index [14:0] */
+};
+
+#define IR_IOAPIC_RTE_INDEX(rte)    (((rte)->index2 << 15) + (rte)->index1)
+
 struct hvm_hw_vioapic {
     uint64_t base_address;
     uint32_t ioregsel;
diff --git a/xen/include/xen/hvm/irq.h b/xen/include/xen/hvm/irq.h
index d3f8623..ea332bb 100644
--- a/xen/include/xen/hvm/irq.h
+++ b/xen/include/xen/hvm/irq.h
@@ -65,6 +65,8 @@ struct hvm_gmsi_info {
     int dest_vcpu_id; /* -1 :multi-dest, non-negative: dest_vcpu_id */
 };
 
+#define IR_MSI_INDEX(data, addr) (((((addr) & 0x4) << 13) + (((addr) & 0xfffff) >> 5)) + (!!((addr) & 0x8)) * ((data) & 0xffff))
+
 struct hvm_girq_dpci_mapping {
     struct list_head list;
     uint8_t bus;
-- 
1.8.3.1


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  parent reply	other threads:[~2017-03-17 11:27 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-17 11:27 [RFC PATCH 00/23] xen/vIOMMU: Add vIOMMU support with irq remapping fucntion on Intel platform Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 1/23] VIOMMU: Add vIOMMU helper functions to create, destroy and query capabilities Lan Tianyu
2017-03-21 19:56   ` Julien Grall
2017-03-22  8:36     ` Tian, Kevin
2017-03-22 12:41       ` Lan, Tianyu
2017-03-22  8:45     ` Lan Tianyu
2017-03-22 11:40       ` Julien Grall
2017-03-22 13:32         ` Lan, Tianyu
2017-03-17 11:27 ` [RFC PATCH 2/23] DMOP: Introduce new DMOP commands for vIOMMU support Lan Tianyu
2017-04-17 14:36   ` Konrad Rzeszutek Wilk
2017-04-18  7:24     ` Lan Tianyu
2017-04-18 13:32       ` Konrad Rzeszutek Wilk
2017-03-17 11:27 ` [RFC PATCH 3/23] VIOMMU: Add irq request callback to deal with irq remapping Lan Tianyu
2017-04-17 14:39   ` Konrad Rzeszutek Wilk
2017-04-18  8:18     ` Lan Tianyu
2017-04-18 13:36       ` Konrad Rzeszutek Wilk
2017-03-17 11:27 ` [RFC PATCH 4/23] VIOMMU: Add get irq info callback to convert irq remapping request Lan Tianyu
2017-04-17 14:39   ` Konrad Rzeszutek Wilk
2017-03-17 11:27 ` [RFC PATCH 5/23] Tools/libxc: Add viommu operations in libxc Lan Tianyu
2017-03-28 16:24   ` Wei Liu
2017-03-29  0:40     ` Chao Gao
2017-03-29  9:08       ` Paul Durrant
2017-03-30 19:57         ` Chao Gao
2017-04-14 15:38           ` Lan, Tianyu
2017-04-17 11:08             ` Wei Liu
2017-04-17 12:01               ` Lan Tianyu
2017-05-11 12:35                 ` Wei Liu
2017-05-11 12:31                   ` Lan Tianyu
2017-04-18  9:08             ` Paul Durrant
2017-04-18  9:59               ` Lan Tianyu
2017-04-18 14:15                 ` Paul Durrant
2017-04-19 12:21                   ` Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 6/23] Tools/libacpi: Add DMA remapping reporting (DMAR) ACPI table structures Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 7/23] Tools/libacpi: Add new fields in acpi_config to build DMAR table Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 8/23] Tools/libacpi: Add a user configurable parameter to control vIOMMU attributes Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 9/23] Tools/libxl: Inform device model to create a guest with a vIOMMU device Lan Tianyu
2017-03-28 16:24   ` Wei Liu
2017-03-17 11:27 ` [RFC PATCH 10/23] x86/hvm: Introduce a emulated VTD for HVM Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 11/23] X86/vvtd: Add MMIO handler for VVTD Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 12/23] X86/vvtd: Set Interrupt Remapping Table Pointer through GCMD Lan Tianyu
2017-03-17 11:27 ` Lan Tianyu [this message]
2017-03-17 11:27 ` [RFC PATCH 14/23] X86/vvtd: decode interrupt attribute from IRTE Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 15/23] X86/vioapic: Hook interrupt delivery of vIOAPIC Lan Tianyu
2017-04-17 14:43   ` Konrad Rzeszutek Wilk
2017-04-18  8:34     ` Lan Tianyu
2017-04-18 13:37       ` Konrad Rzeszutek Wilk
2017-03-17 11:27 ` [RFC PATCH 16/23] X86/vvtd: Enable Queued Invalidation through GCMD Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 17/23] X86/vvtd: Enable Interrupt Remapping " Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 18/23] x86/vpt: Get interrupt vector through a vioapic interface Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 19/23] passthrough: move some fields of hvm_gmsi_info to a sub-structure Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 20/23] Tools/libxc: Add a new interface to bind msi-ir with pirq Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 21/23] X86/vmsi: Hook guest MSI injection Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 22/23] X86/vvtd: Handle interrupt translation faults Lan Tianyu
2017-03-17 11:27 ` [RFC PATCH 23/23] X86/vvtd: Add queued invalidation (QI) support Lan Tianyu
2017-03-20 14:23 ` [RFC PATCH 00/23] xen/vIOMMU: Add vIOMMU support with irq remapping fucntion on Intel platform Roger Pau Monné
2017-03-21  2:28   ` Lan Tianyu
2017-03-21  5:29     ` Lan Tianyu
2017-03-29  8:00       ` Roger Pau Monné
2017-03-29  3:52         ` Chao Gao
2017-04-17 14:41   ` Konrad Rzeszutek Wilk
2017-04-18  8:19     ` Lan Tianyu

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=1489750043-17260-14-git-send-email-tianyu.lan@intel.com \
    --to=tianyu.lan@intel.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=chao.gao@intel.com \
    --cc=jbeulich@suse.com \
    --cc=kevin.tian@intel.com \
    --cc=xen-devel@lists.xen.org \
    /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.