From: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
To: <pbonzini@redhat.com>, <rkrcmar@redhat.com>, <joro@8bytes.org>,
<bp@alien8.de>, <gleb@kernel.org>, <alex.williamson@redhat.com>
Cc: <kvm@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<wei@redhat.com>, <sherry.hurwitz@amd.com>,
Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Subject: [PART2 RFC v1 2/9] iommu/amd: Add data structure for guest vAPIC support
Date: Fri, 8 Apr 2016 07:49:23 -0500 [thread overview]
Message-ID: <1460119770-2896-3-git-send-email-Suravee.Suthikulpanit@amd.com> (raw)
In-Reply-To: <1460119770-2896-1-git-send-email-Suravee.Suthikulpanit@amd.com>
From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
This patch adds new data structure for the 128-bit IOMMU IRTE format,
which can support both legacy and GA interrupt remapping modes.
It also provides helper functions for setting up, accessing, and
updating interrupt remapping table entries in different mode.
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
drivers/iommu/amd_iommu.c | 188 ++++++++++++++++++++++++++++++++--------
drivers/iommu/amd_iommu_types.h | 63 ++++++++++++++
2 files changed, 217 insertions(+), 34 deletions(-)
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 374c129..af6079a 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3601,21 +3601,6 @@ EXPORT_SYMBOL(amd_iommu_device_info);
*
*****************************************************************************/
-union irte {
- u32 val;
- struct {
- u32 valid : 1,
- no_fault : 1,
- int_type : 3,
- rq_eoi : 1,
- dm : 1,
- rsvd_1 : 1,
- destination : 8,
- vector : 8,
- rsvd_2 : 8;
- } fields;
-};
-
struct irq_2_irte {
u16 devid; /* Device ID for IRTE table */
u16 index; /* Index into IRTE table*/
@@ -3624,6 +3609,7 @@ struct irq_2_irte {
struct amd_ir_data {
struct irq_2_irte irq_2_irte;
union irte irte_entry;
+ struct irte_ga irte_ga_entry;
union {
struct msi_msg msi_entry;
};
@@ -3650,7 +3636,60 @@ static void set_dte_irq_entry(u16 devid, struct irq_remap_table *table)
amd_iommu_dev_table[devid].data[2] = dte;
}
+void *amd_iommu_get_irte(struct irq_remap_table *table, int index)
+{
+ void *ret = NULL;
+
+ if (!amd_iommu_guest_ir) {
+ union irte *ptr = (union irte *)table->table;
+
+ ret = &ptr[index];
+ } else {
+ struct irte_ga *ptr = (struct irte_ga *)table->table;
+
+ ret = &ptr[index];
+ }
+ return ret;
+}
+
#define IRTE_ALLOCATED (~1U)
+static void set_irte_allocated(struct irq_remap_table *table, int index)
+{
+ if (!amd_iommu_guest_ir) {
+ table->table[index] = IRTE_ALLOCATED;
+ } else {
+ struct irte_ga *irte = amd_iommu_get_irte(table, index);
+
+ memset(&irte->lo.val, 0, sizeof(u64));
+ memset(&irte->hi.val, 0, sizeof(u64));
+ irte->hi.fields.vector = 0xff;
+ }
+}
+
+static bool is_irte_allocated(struct irq_remap_table *table, int index)
+{
+ if (!amd_iommu_guest_ir) {
+ union irte *irte = amd_iommu_get_irte(table, index);
+
+ return irte->val != 0;
+ } else {
+ struct irte_ga *irte = amd_iommu_get_irte(table, index);
+
+ return irte->hi.fields.vector != 0;
+ }
+}
+
+static void clear_irte(struct irq_remap_table *table, int index)
+{
+ if (!amd_iommu_guest_ir) {
+ table->table[index] = 0;
+ } else {
+ struct irte_ga *irte = amd_iommu_get_irte(table, index);
+
+ memset(&irte->lo.val, 0, sizeof(u64));
+ memset(&irte->hi.val, 0, sizeof(u64));
+ }
+}
static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic)
{
@@ -3697,13 +3736,18 @@ static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic)
goto out;
}
- memset(table->table, 0, MAX_IRQS_PER_TABLE * sizeof(u32));
+ if (!amd_iommu_guest_ir)
+ memset(table->table, 0,
+ MAX_IRQS_PER_TABLE * sizeof(u32));
+ else
+ memset(table->table, 0,
+ (MAX_IRQS_PER_TABLE * (sizeof(u64) * 2)));
if (ioapic) {
int i;
for (i = 0; i < 32; ++i)
- table->table[i] = IRTE_ALLOCATED;
+ set_irte_allocated(table, i);
}
irq_lookup_table[devid] = table;
@@ -3740,14 +3784,14 @@ static int alloc_irq_index(u16 devid, int count)
for (c = 0, index = table->min_index;
index < MAX_IRQS_PER_TABLE;
++index) {
- if (table->table[index] == 0)
+ if (!is_irte_allocated(table, index))
c += 1;
else
c = 0;
if (c == count) {
for (; c != 0; --c)
- table->table[index - c + 1] = IRTE_ALLOCATED;
+ set_irte_allocated(table, index - c + 1);
index -= count - 1;
goto out;
@@ -3762,6 +3806,42 @@ out:
return index;
}
+static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte)
+{
+ struct irq_remap_table *table;
+ struct amd_iommu *iommu;
+ unsigned long flags;
+ struct irte_ga *entry;
+ struct irte_ga tmp;
+
+ iommu = amd_iommu_rlookup_table[devid];
+ if (iommu == NULL)
+ return -EINVAL;
+
+ table = get_irq_table(devid, false);
+ if (!table)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&table->lock, flags);
+
+ entry = amd_iommu_get_irte(table, index);
+
+ memcpy(&tmp, entry, sizeof(struct irte_ga));
+
+ entry->lo.fields_remap.valid = 0;
+ entry->hi.val = irte->hi.val;
+ entry->hi.fields.ga_root_ptr = tmp.hi.fields.ga_root_ptr;
+ entry->lo.val = irte->lo.val;
+ entry->lo.fields_remap.valid = 1;
+
+ spin_unlock_irqrestore(&table->lock, flags);
+
+ iommu_flush_irt(iommu, devid);
+ iommu_completion_wait(iommu);
+
+ return 0;
+}
+
static int modify_irte(u16 devid, int index, union irte irte)
{
struct irq_remap_table *table;
@@ -3801,7 +3881,7 @@ static void free_irte(u16 devid, int index)
return;
spin_lock_irqsave(&table->lock, flags);
- table->table[index] = 0;
+ clear_irte(table, index);
spin_unlock_irqrestore(&table->lock, flags);
iommu_flush_irt(iommu, devid);
@@ -3889,19 +3969,33 @@ static void irq_remapping_prepare_irte(struct amd_ir_data *data,
{
struct irq_2_irte *irte_info = &data->irq_2_irte;
struct msi_msg *msg = &data->msi_entry;
- union irte *irte = &data->irte_entry;
struct IO_APIC_route_entry *entry;
data->irq_2_irte.devid = devid;
data->irq_2_irte.index = index + sub_handle;
/* Setup IRTE for IOMMU */
- irte->val = 0;
- irte->fields.vector = irq_cfg->vector;
- irte->fields.int_type = apic->irq_delivery_mode;
- irte->fields.destination = irq_cfg->dest_apicid;
- irte->fields.dm = apic->irq_dest_mode;
- irte->fields.valid = 1;
+ if (!amd_iommu_guest_ir) {
+ union irte *irte = &data->irte_entry;
+
+ irte->val = 0;
+ irte->fields.vector = irq_cfg->vector;
+ irte->fields.int_type = apic->irq_delivery_mode;
+ irte->fields.destination = irq_cfg->dest_apicid;
+ irte->fields.dm = apic->irq_dest_mode;
+ irte->fields.valid = 1;
+ } else {
+ struct irte_ga *irte = &data->irte_ga_entry;
+
+ irte->lo.val = 0;
+ irte->hi.val = 0;
+ irte->lo.fields_remap.guest_mode = 0;
+ irte->lo.fields_remap.int_type = apic->irq_delivery_mode;
+ irte->lo.fields_remap.dm = apic->irq_dest_mode;
+ irte->hi.fields.vector = irq_cfg->vector;
+ irte->lo.fields_remap.destination = irq_cfg->dest_apicid;
+ irte->lo.fields_remap.valid = 1;
+ }
switch (info->type) {
case X86_IRQ_ALLOC_TYPE_IOAPIC:
@@ -4037,7 +4131,13 @@ static void irq_remapping_activate(struct irq_domain *domain,
struct amd_ir_data *data = irq_data->chip_data;
struct irq_2_irte *irte_info = &data->irq_2_irte;
- modify_irte(irte_info->devid, irte_info->index, data->irte_entry);
+ if (!amd_iommu_guest_ir) {
+ data->irte_entry.fields.valid = 1;
+ modify_irte(irte_info->devid, irte_info->index, data->irte_entry);
+ } else if (amd_iommu_guest_ir >= AMD_IOMMU_GUEST_IR_LEGACY_GA) {
+ data->irte_ga_entry.lo.fields_remap.valid = 1;
+ modify_irte_ga(irte_info->devid, irte_info->index, &data->irte_ga_entry);
+ }
}
static void irq_remapping_deactivate(struct irq_domain *domain,
@@ -4045,10 +4145,14 @@ static void irq_remapping_deactivate(struct irq_domain *domain,
{
struct amd_ir_data *data = irq_data->chip_data;
struct irq_2_irte *irte_info = &data->irq_2_irte;
- union irte entry;
- entry.val = 0;
- modify_irte(irte_info->devid, irte_info->index, data->irte_entry);
+ if (!amd_iommu_guest_ir) {
+ data->irte_entry.fields.valid = 0;
+ modify_irte(irte_info->devid, irte_info->index, data->irte_entry);
+ } else {
+ data->irte_ga_entry.lo.fields_remap.valid = 0;
+ modify_irte_ga(irte_info->devid, irte_info->index, &data->irte_ga_entry);
+ }
}
static struct irq_domain_ops amd_ir_domain_ops = {
@@ -4075,9 +4179,19 @@ static int amd_ir_set_affinity(struct irq_data *data,
* Atomically updates the IRTE with the new destination, vector
* and flushes the interrupt entry cache.
*/
- ir_data->irte_entry.fields.vector = cfg->vector;
- ir_data->irte_entry.fields.destination = cfg->dest_apicid;
- modify_irte(irte_info->devid, irte_info->index, ir_data->irte_entry);
+ if (!amd_iommu_guest_ir) {
+ ir_data->irte_entry.fields.vector = cfg->vector;
+ ir_data->irte_entry.fields.destination = cfg->dest_apicid;
+ modify_irte(irte_info->devid, irte_info->index,
+ ir_data->irte_entry);
+ } else {
+ struct irte_ga *entry = &ir_data->irte_ga_entry;
+
+ entry->hi.fields.vector = cfg->vector;
+ entry->lo.fields_remap.destination = cfg->dest_apicid;
+ entry->lo.fields_remap.guest_mode = 0;
+ modify_irte_ga(irte_info->devid, irte_info->index, entry);
+ }
/*
* After this point, all the interrupts will start arriving
@@ -4097,19 +4211,25 @@ static void ir_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg)
}
static struct irq_chip amd_ir_chip = {
+ .name = "AMD-IR-IRQ-CHIP",
.irq_ack = ir_ack_apic_edge,
.irq_set_affinity = amd_ir_set_affinity,
.irq_compose_msi_msg = ir_compose_msi_msg,
};
+static const char amd_iommu_ir_domain_name[] = "AMD-IOMMU-IR-DOMAIN";
+static const char amd_iommu_msi_domain_name[] = "AMD-IOMMU-MSI-DOMAIN";
+
int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
{
iommu->ir_domain = irq_domain_add_tree(NULL, &amd_ir_domain_ops, iommu);
if (!iommu->ir_domain)
return -ENOMEM;
+ iommu->ir_domain->name = amd_iommu_ir_domain_name;
iommu->ir_domain->parent = arch_get_ir_parent_domain();
iommu->msi_domain = arch_create_msi_irq_domain(iommu->ir_domain);
+ iommu->msi_domain->name = amd_iommu_msi_domain_name;
return 0;
}
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 95414120..ec546f3 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -708,4 +708,67 @@ enum amd_iommu_intr_mode_type {
AMD_IOMMU_GUEST_IR_GA,
};
+union irte {
+ u32 val;
+ struct {
+ u32 valid : 1,
+ no_fault : 1,
+ int_type : 3,
+ rq_eoi : 1,
+ dm : 1,
+ rsvd_1 : 1,
+ destination : 8,
+ vector : 8,
+ rsvd_2 : 8;
+ } fields;
+};
+
+union irte_ga_lo {
+ u64 val;
+
+ /* For int remapping */
+ struct {
+ u64 valid : 1,
+ no_fault : 1,
+ /* ------ */
+ int_type : 3,
+ rq_eoi : 1,
+ dm : 1,
+ /* ------ */
+ guest_mode : 1,
+ destination : 8,
+ rsvd : 48;
+ } fields_remap;
+
+ /* For guest vAPIC */
+ struct {
+ u64 valid : 1,
+ no_fault : 1,
+ /* ------ */
+ ga_log_intr : 1,
+ rsvd1 : 3,
+ is_run : 1,
+ /* ------ */
+ guest_mode : 1,
+ destination : 8,
+ rsvd2 : 16,
+ ga_tag : 32;
+ } fields_vapic;
+};
+
+union irte_ga_hi {
+ u64 val;
+ struct {
+ u64 vector : 8,
+ rsvd_1 : 4,
+ ga_root_ptr : 40,
+ rsvd_2 : 12;
+ } fields;
+};
+
+struct irte_ga {
+ union irte_ga_lo lo;
+ union irte_ga_hi hi;
+};
+
#endif /* _ASM_X86_AMD_IOMMU_TYPES_H */
--
1.9.1
next prev parent reply other threads:[~2016-04-08 12:52 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-04-08 12:49 [PART2 RFC v1 0/9] iommu/AMD: Introduce IOMMU AVIC support Suravee Suthikulpanit
2016-04-08 12:49 ` [PART2 RFC v1 1/9] iommu/amd: Detect and enable guest vAPIC support Suravee Suthikulpanit
2016-05-09 11:49 ` Joerg Roedel
2016-06-02 20:38 ` Suravee Suthikulanit
2016-04-08 12:49 ` Suravee Suthikulpanit [this message]
2016-04-08 12:49 ` [PART2 RFC v1 3/9] iommu/amd: Detect and initialize guest vAPIC log Suravee Suthikulpanit
2016-04-08 12:49 ` [PART2 RFC v1 4/9] iommu/amd: Adding GALOG interrupt handler Suravee Suthikulpanit
2016-04-08 12:49 ` [PART2 RFC v1 5/9] iommu/amd: Introduce amd_iommu_update_ga() Suravee Suthikulpanit
2016-04-13 17:06 ` Radim Krčmář
2016-06-09 23:59 ` Suravee Suthikulpanit
2016-04-08 12:49 ` [PART2 RFC v1 6/9] iommu/amd: Implements irq_set_vcpu_affinity hook to setup GA mode for pass-through devices Suravee Suthikulpanit
2016-04-08 12:49 ` [PART2 RFC v1 7/9] svm: Introduce AMD IOMMU avic_ga_log_notifier Suravee Suthikulpanit
2016-04-08 12:49 ` [PART2 RFC v1 8/9] svm: Implements update_pi_irte hook to setup posted interrupt Suravee Suthikulpanit
2016-04-08 12:49 ` [PART2 RFC v1 9/9] svm: Update AMD IOMMU IRTE with vcpu scheduling information when enable AVIC Suravee Suthikulpanit
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=1460119770-2896-3-git-send-email-Suravee.Suthikulpanit@amd.com \
--to=suravee.suthikulpanit@amd.com \
--cc=alex.williamson@redhat.com \
--cc=bp@alien8.de \
--cc=gleb@kernel.org \
--cc=joro@8bytes.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=rkrcmar@redhat.com \
--cc=sherry.hurwitz@amd.com \
--cc=wei@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome