[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 5 of 6] amd iommu: Compress hyper-transport flags into a single byte



# HG changeset patch
# User Wei Wang <wei.wang2@xxxxxxx>
# Date 1320852003 -3600
# Node ID c75cf540a1fe57a439f9cb0503bf69f120066b92
# Parent  60d51bc20139471cf71e3d6854534d4176853de2
amd iommu: Compress hyper-transport flags into a single byte.
These flags are single bit, no need to be saved as integers.
Add 3 inline helpers to make single bit access easier.
Introduce iommu_has_ht_flag and set_iommu_ht_flags

Signed-off-by: Wei Wang <wei.wang2@xxxxxxx>

diff -r 60d51bc20139 -r c75cf540a1fe xen/drivers/passthrough/amd/iommu_detect.c
--- a/xen/drivers/passthrough/amd/iommu_detect.c        Wed Nov 09 16:20:02 
2011 +0100
+++ b/xen/drivers/passthrough/amd/iommu_detect.c        Wed Nov 09 16:20:03 
2011 +0100
@@ -98,25 +98,8 @@ int __init amd_iommu_detect_one_acpi(voi
     iommu->cap_offset = ivhd_block->cap_offset;
     iommu->mmio_base_phys = ivhd_block->mmio_base;
 
-    /* override IOMMU support flags */
-    iommu->coherent = get_field_from_byte(ivhd_block->header.flags,
-                        AMD_IOMMU_ACPI_COHERENT_MASK,
-                        AMD_IOMMU_ACPI_COHERENT_SHIFT);
-    iommu->iotlb_support = get_field_from_byte(ivhd_block->header.flags,
-                        AMD_IOMMU_ACPI_IOTLB_SUP_MASK,
-                        AMD_IOMMU_ACPI_IOTLB_SUP_SHIFT);
-    iommu->isochronous = get_field_from_byte(ivhd_block->header.flags,
-                        AMD_IOMMU_ACPI_ISOC_MASK,
-                        AMD_IOMMU_ACPI_ISOC_SHIFT);
-    iommu->res_pass_pw = get_field_from_byte(ivhd_block->header.flags,
-                        AMD_IOMMU_ACPI_RES_PASS_PW_MASK,
-                        AMD_IOMMU_ACPI_RES_PASS_PW_SHIFT);
-    iommu->pass_pw = get_field_from_byte(ivhd_block->header.flags,
-                        AMD_IOMMU_ACPI_PASS_PW_MASK,
-                        AMD_IOMMU_ACPI_PASS_PW_SHIFT);
-    iommu->ht_tunnel_enable = get_field_from_byte(ivhd_block->header.flags,
-                        AMD_IOMMU_ACPI_HT_TUN_ENB_MASK,
-                        AMD_IOMMU_ACPI_HT_TUN_ENB_SHIFT);
+    /* override IOMMU HT flags */
+    iommu->ht_flags = ivhd_block->header.flags;
 
     bus = PCI_BUS(iommu->bdf);
     dev = PCI_SLOT(iommu->bdf);
diff -r 60d51bc20139 -r c75cf540a1fe xen/drivers/passthrough/amd/iommu_init.c
--- a/xen/drivers/passthrough/amd/iommu_init.c  Wed Nov 09 16:20:02 2011 +0100
+++ b/xen/drivers/passthrough/amd/iommu_init.c  Wed Nov 09 16:20:03 2011 +0100
@@ -28,6 +28,7 @@
 #include <asm/hvm/svm/amd-iommu-proto.h>
 #include <asm-x86/fixmap.h>
 #include <mach_apic.h>
+#include <asm/hvm/svm/amd-iommu-acpi.h>
 
 static int __initdata nr_amd_iommus;
 
@@ -36,6 +37,12 @@ static struct radix_tree_root ivrs_maps;
 struct list_head amd_iommu_head;
 struct table_struct device_table;
 
+static int iommu_has_ht_flag(struct amd_iommu *iommu, uint8_t bit)
+{
+    u8 mask = (1U << bit) & 0xff;
+    return iommu->ht_flags & mask;
+}
+
 static int __init map_iommu_mmio_region(struct amd_iommu *iommu)
 {
     unsigned long mfn;
@@ -66,6 +73,34 @@ static void __init unmap_iommu_mmio_regi
     }
 }
 
+static void set_iommu_ht_flags(struct amd_iommu *iommu)
+{
+    u32 entry;
+    entry = readl(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET);
+
+    /* Setup HT flags */
+    iommu_has_ht_flag(iommu, AMD_IOMMU_ACPI_HT_TUN_ENB_SHIFT) ?
+        iommu_set_bit(&entry, IOMMU_CONTROL_HT_TUNNEL_TRANSLATION_SHIFT):
+        iommu_clear_bit(&entry, IOMMU_CONTROL_HT_TUNNEL_TRANSLATION_SHIFT);
+
+    iommu_has_ht_flag(iommu, AMD_IOMMU_ACPI_RES_PASS_PW_SHIFT) ?
+        iommu_set_bit(&entry, IOMMU_CONTROL_RESP_PASS_POSTED_WRITE_SHIFT):
+        iommu_clear_bit(&entry, IOMMU_CONTROL_RESP_PASS_POSTED_WRITE_SHIFT);
+
+    iommu_has_ht_flag(iommu, AMD_IOMMU_ACPI_ISOC_SHIFT) ?
+        iommu_set_bit(&entry, IOMMU_CONTROL_ISOCHRONOUS_SHIFT):
+        iommu_clear_bit(&entry, IOMMU_CONTROL_ISOCHRONOUS_SHIFT);
+
+    iommu_has_ht_flag(iommu, AMD_IOMMU_ACPI_PASS_PW_SHIFT) ?
+        iommu_set_bit(&entry, IOMMU_CONTROL_PASS_POSTED_WRITE_SHIFT):
+        iommu_clear_bit(&entry, IOMMU_CONTROL_PASS_POSTED_WRITE_SHIFT);
+
+    /* Force coherent */
+    iommu_set_bit(&entry, IOMMU_CONTROL_COHERENT_SHIFT);
+
+    writel(entry, iommu->mmio_base+IOMMU_CONTROL_MMIO_OFFSET);
+}
+
 static void register_iommu_dev_table_in_mmio_space(struct amd_iommu *iommu)
 {
     u64 addr_64, addr_lo, addr_hi;
@@ -150,33 +185,10 @@ static void set_iommu_translation_contro
 
     entry = readl(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET);
 
-    if ( enable )
-    {
-        set_field_in_reg_u32(iommu->ht_tunnel_support ? IOMMU_CONTROL_ENABLED :
-                         IOMMU_CONTROL_DISABLED, entry,
-                         IOMMU_CONTROL_HT_TUNNEL_TRANSLATION_MASK,
-                         IOMMU_CONTROL_HT_TUNNEL_TRANSLATION_SHIFT, &entry);
-        set_field_in_reg_u32(iommu->isochronous ? IOMMU_CONTROL_ENABLED :
-                         IOMMU_CONTROL_DISABLED, entry,
-                         IOMMU_CONTROL_ISOCHRONOUS_MASK,
-                         IOMMU_CONTROL_ISOCHRONOUS_SHIFT, &entry);
-        set_field_in_reg_u32(iommu->coherent ? IOMMU_CONTROL_ENABLED :
-                         IOMMU_CONTROL_DISABLED, entry,
-                         IOMMU_CONTROL_COHERENT_MASK,
-                         IOMMU_CONTROL_COHERENT_SHIFT, &entry);
-        set_field_in_reg_u32(iommu->res_pass_pw ? IOMMU_CONTROL_ENABLED :
-                         IOMMU_CONTROL_DISABLED, entry,
-                         IOMMU_CONTROL_RESP_PASS_POSTED_WRITE_MASK,
-                         IOMMU_CONTROL_RESP_PASS_POSTED_WRITE_SHIFT, &entry);
-        /* do not set PassPW bit */
-        set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, entry,
-                         IOMMU_CONTROL_PASS_POSTED_WRITE_MASK,
-                         IOMMU_CONTROL_PASS_POSTED_WRITE_SHIFT, &entry);
-    }
-    set_field_in_reg_u32(enable ? IOMMU_CONTROL_ENABLED :
-                         IOMMU_CONTROL_DISABLED, entry,
-                         IOMMU_CONTROL_TRANSLATION_ENABLE_MASK,
-                         IOMMU_CONTROL_TRANSLATION_ENABLE_SHIFT, &entry);
+    enable ?
+        iommu_set_bit(&entry, IOMMU_CONTROL_TRANSLATION_ENABLE_SHIFT):
+        iommu_clear_bit(&entry, IOMMU_CONTROL_TRANSLATION_ENABLE_SHIFT);
+
     writel(entry, iommu->mmio_base+IOMMU_CONTROL_MMIO_OFFSET);
 }
 
@@ -186,17 +198,17 @@ static void set_iommu_command_buffer_con
     u32 entry;
 
     entry = readl(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET);
-    set_field_in_reg_u32(enable ? IOMMU_CONTROL_ENABLED :
-                         IOMMU_CONTROL_DISABLED, entry,
-                         IOMMU_CONTROL_COMMAND_BUFFER_ENABLE_MASK,
-                         IOMMU_CONTROL_COMMAND_BUFFER_ENABLE_SHIFT, &entry);
 
     /*reset head and tail pointer manually before enablement */
-    if ( enable == IOMMU_CONTROL_ENABLED )
+    if ( enable )
     {
         writel(0x0, iommu->mmio_base + IOMMU_CMD_BUFFER_HEAD_OFFSET);
         writel(0x0, iommu->mmio_base + IOMMU_CMD_BUFFER_TAIL_OFFSET);
+
+        iommu_set_bit(&entry, IOMMU_CONTROL_COMMAND_BUFFER_ENABLE_SHIFT);
     }
+    else
+        iommu_clear_bit(&entry, IOMMU_CONTROL_COMMAND_BUFFER_ENABLE_SHIFT);
 
     writel(entry, iommu->mmio_base+IOMMU_CONTROL_MMIO_OFFSET);
 }
@@ -247,24 +259,24 @@ static void set_iommu_event_log_control(
     u32 entry;
 
     entry = readl(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET);
-    set_field_in_reg_u32(enable ? IOMMU_CONTROL_ENABLED :
-                         IOMMU_CONTROL_DISABLED, entry,
-                         IOMMU_CONTROL_EVENT_LOG_ENABLE_MASK,
-                         IOMMU_CONTROL_EVENT_LOG_ENABLE_SHIFT, &entry);
-    set_field_in_reg_u32(enable ? IOMMU_CONTROL_ENABLED :
-                         IOMMU_CONTROL_DISABLED, entry,
-                         IOMMU_CONTROL_EVENT_LOG_INT_MASK,
-                         IOMMU_CONTROL_EVENT_LOG_INT_SHIFT, &entry);
-    set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, entry,
-                         IOMMU_CONTROL_COMP_WAIT_INT_MASK,
-                         IOMMU_CONTROL_COMP_WAIT_INT_SHIFT, &entry);
 
     /*reset head and tail pointer manually before enablement */
-    if ( enable == IOMMU_CONTROL_ENABLED )
+    if ( enable )
     {
         writel(0x0, iommu->mmio_base + IOMMU_EVENT_LOG_HEAD_OFFSET);
         writel(0x0, iommu->mmio_base + IOMMU_EVENT_LOG_TAIL_OFFSET);
+
+        iommu_set_bit(&entry, IOMMU_CONTROL_EVENT_LOG_INT_SHIFT);
+        iommu_set_bit(&entry, IOMMU_CONTROL_EVENT_LOG_ENABLE_SHIFT);
     }
+    else
+    {
+        iommu_clear_bit(&entry, IOMMU_CONTROL_EVENT_LOG_INT_SHIFT);
+        iommu_clear_bit(&entry, IOMMU_CONTROL_EVENT_LOG_ENABLE_SHIFT);
+    }
+
+    iommu_clear_bit(&entry, IOMMU_CONTROL_COMP_WAIT_INT_SHIFT);
+
     writel(entry, iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET);
 }
 
@@ -313,9 +325,7 @@ static void amd_iommu_reset_event_log(st
     /* wait until EventLogRun bit = 0 */
     do {
         entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
-        log_run = get_field_from_reg_u32(entry,
-                                        IOMMU_STATUS_EVENT_LOG_RUN_MASK,
-                                        IOMMU_STATUS_EVENT_LOG_RUN_SHIFT);
+        log_run = iommu_get_bit(entry, IOMMU_STATUS_EVENT_LOG_RUN_SHIFT);
         loop_count--;
     } while ( log_run && loop_count );
 
@@ -330,11 +340,9 @@ static void amd_iommu_reset_event_log(st
 
     /* read event log for debugging */
     amd_iommu_read_event_log(iommu);
+    /*clear overflow bit */
+    iommu_clear_bit(&entry, IOMMU_STATUS_EVENT_OVERFLOW_SHIFT);
 
-    /*clear overflow bit */
-    set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, entry,
-                         IOMMU_STATUS_EVENT_OVERFLOW_MASK,
-                         IOMMU_STATUS_EVENT_OVERFLOW_SHIFT, &entry);
     writel(entry, iommu->mmio_base+IOMMU_STATUS_MMIO_OFFSET);
 
     /*reset event log base address */
@@ -519,7 +527,6 @@ static void amd_iommu_page_fault(int irq
 {
     u32 entry;
     unsigned long flags;
-    int of;
     struct amd_iommu *iommu = dev_id;
 
     spin_lock_irqsave(&iommu->lock, flags);
@@ -527,19 +534,14 @@ static void amd_iommu_page_fault(int irq
 
     /*check event overflow */
     entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
-    of = get_field_from_reg_u32(entry,
-                               IOMMU_STATUS_EVENT_OVERFLOW_MASK,
-                               IOMMU_STATUS_EVENT_OVERFLOW_SHIFT);
 
-    /* reset event log if event overflow */
-    if ( of )
+    if ( iommu_get_bit(entry, IOMMU_STATUS_EVENT_OVERFLOW_SHIFT) )
         amd_iommu_reset_event_log(iommu);
 
     /* reset interrupt status bit */
     entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
-    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
-                         IOMMU_STATUS_EVENT_LOG_INT_MASK,
-                         IOMMU_STATUS_EVENT_LOG_INT_SHIFT, &entry);
+    iommu_set_bit(&entry, IOMMU_STATUS_EVENT_LOG_INT_SHIFT);
+
     writel(entry, iommu->mmio_base+IOMMU_STATUS_MMIO_OFFSET);
     spin_unlock_irqrestore(&iommu->lock, flags);
 }
@@ -590,6 +592,7 @@ static void enable_iommu(struct amd_iomm
     iommu_msi_set_affinity(irq_to_desc(iommu->irq), &cpu_online_map);
     amd_iommu_msi_enable(iommu, IOMMU_CONTROL_ENABLED);
 
+    set_iommu_ht_flags(iommu);
     set_iommu_command_buffer_control(iommu, IOMMU_CONTROL_ENABLED);
     set_iommu_event_log_control(iommu, IOMMU_CONTROL_ENABLED);
     set_iommu_translation_control(iommu, IOMMU_CONTROL_ENABLED);
diff -r 60d51bc20139 -r c75cf540a1fe xen/include/asm-x86/amd-iommu.h
--- a/xen/include/asm-x86/amd-iommu.h   Wed Nov 09 16:20:02 2011 +0100
+++ b/xen/include/asm-x86/amd-iommu.h   Wed Nov 09 16:20:03 2011 +0100
@@ -57,11 +57,7 @@ struct amd_iommu {
     u8 ht_tunnel_support;
     u8 iotlb_support;
 
-    u8 isochronous;
-    u8 coherent;
-    u8 res_pass_pw;
-    u8 pass_pw;
-    u8 ht_tunnel_enable;
+    u8 ht_flags;
 
     void *mmio_base;
     unsigned long mmio_base_phys;
diff -r 60d51bc20139 -r c75cf540a1fe 
xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h     Wed Nov 09 16:20:02 
2011 +0100
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h     Wed Nov 09 16:20:03 
2011 +0100
@@ -166,4 +166,19 @@ static inline void __free_amd_iommu_tabl
     free_xenheap_pages(table, order);
 }
 
+static inline void iommu_set_bit(uint32_t *reg, uint32_t bit)
+{
+    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, *reg, 1U << bit, bit, reg);
+}
+
+static inline void iommu_clear_bit(uint32_t *reg, uint32_t bit)
+{
+    set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, *reg, 1U << bit, bit, reg);
+}
+
+static inline uint32_t iommu_get_bit(uint32_t reg, uint32_t bit)
+{
+    return get_field_from_reg_u32(reg, 1U << bit, bit);
+}
+
 #endif /* _ASM_X86_64_AMD_IOMMU_PROTO_H */


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.