]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
iommu/vt-d: Use bitfields for DMAR capabilities
authorParav Pandit <parav@nvidia.com>
Thu, 10 Jun 2021 02:01:11 +0000 (10:01 +0800)
committerJoerg Roedel <jroedel@suse.de>
Thu, 10 Jun 2021 07:06:13 +0000 (09:06 +0200)
IOTLB device presence, iommu coherency and snooping are boolean
capabilities. Use them as bits and keep them adjacent.

Structure layout before the reorg.
$ pahole -C dmar_domain drivers/iommu/intel/dmar.o
struct dmar_domain {
        int                        nid;                  /*     0     4 */
        unsigned int               iommu_refcnt[128];    /*     4   512 */
        /* --- cacheline 8 boundary (512 bytes) was 4 bytes ago --- */
        u16                        iommu_did[128];       /*   516   256 */
        /* --- cacheline 12 boundary (768 bytes) was 4 bytes ago --- */
        bool                       has_iotlb_device;     /*   772     1 */

        /* XXX 3 bytes hole, try to pack */

        struct list_head           devices;              /*   776    16 */
        struct list_head           subdevices;           /*   792    16 */
        struct iova_domain         iovad __attribute__((__aligned__(8)));
 /*   808  2320 */
        /* --- cacheline 48 boundary (3072 bytes) was 56 bytes ago --- */
        struct dma_pte *           pgd;                  /*  3128     8 */
        /* --- cacheline 49 boundary (3136 bytes) --- */
        int                        gaw;                  /*  3136     4 */
        int                        agaw;                 /*  3140     4 */
        int                        flags;                /*  3144     4 */
        int                        iommu_coherency;      /*  3148     4 */
        int                        iommu_snooping;       /*  3152     4 */
        int                        iommu_count;          /*  3156     4 */
        int                        iommu_superpage;      /*  3160     4 */

        /* XXX 4 bytes hole, try to pack */

        u64                        max_addr;             /*  3168     8 */
        u32                        default_pasid;        /*  3176     4 */

        /* XXX 4 bytes hole, try to pack */

        struct iommu_domain        domain;               /*  3184    72 */

        /* size: 3256, cachelines: 51, members: 18 */
        /* sum members: 3245, holes: 3, sum holes: 11 */
        /* forced alignments: 1 */
        /* last cacheline: 56 bytes */
} __attribute__((__aligned__(8)));

After arranging it for natural padding and to make flags as u8 bits, it
saves 8 bytes for the struct.

struct dmar_domain {
        int                        nid;                  /*     0     4 */
        unsigned int               iommu_refcnt[128];    /*     4   512 */
        /* --- cacheline 8 boundary (512 bytes) was 4 bytes ago --- */
        u16                        iommu_did[128];       /*   516   256 */
        /* --- cacheline 12 boundary (768 bytes) was 4 bytes ago --- */
        u8                         has_iotlb_device:1;   /*   772: 0  1 */
        u8                         iommu_coherency:1;    /*   772: 1  1 */
        u8                         iommu_snooping:1;     /*   772: 2  1 */

        /* XXX 5 bits hole, try to pack */
        /* XXX 3 bytes hole, try to pack */

        struct list_head           devices;              /*   776    16 */
        struct list_head           subdevices;           /*   792    16 */
        struct iova_domain         iovad __attribute__((__aligned__(8)));
 /*   808  2320 */
        /* --- cacheline 48 boundary (3072 bytes) was 56 bytes ago --- */
        struct dma_pte *           pgd;                  /*  3128     8 */
        /* --- cacheline 49 boundary (3136 bytes) --- */
        int                        gaw;                  /*  3136     4 */
        int                        agaw;                 /*  3140     4 */
        int                        flags;                /*  3144     4 */
        int                        iommu_count;          /*  3148     4 */
        int                        iommu_superpage;      /*  3152     4 */

        /* XXX 4 bytes hole, try to pack */

        u64                        max_addr;             /*  3160     8 */
        u32                        default_pasid;        /*  3168     4 */

        /* XXX 4 bytes hole, try to pack */

        struct iommu_domain        domain;               /*  3176    72 */

        /* size: 3248, cachelines: 51, members: 18 */
        /* sum members: 3236, holes: 3, sum holes: 11 */
        /* sum bitfield members: 3 bits, bit holes: 1, sum bit holes: 5 bits */
        /* forced alignments: 1 */
        /* last cacheline: 48 bytes */
} __attribute__((__aligned__(8)));

Signed-off-by: Parav Pandit <parav@nvidia.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Link: https://lore.kernel.org/r/20210530075053.264218-1-parav@nvidia.com
Link: https://lore.kernel.org/r/20210610020115.1637656-20-baolu.lu@linux.intel.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/intel/iommu.c
include/linux/intel-iommu.h

index 65458aee0d952e58d44a6b97e0262644769647e9..430ef2232d47a6e7f17f331d07d4ffd0466d517d 100644 (file)
@@ -626,12 +626,12 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain)
        bool found = false;
        int i;
 
-       domain->iommu_coherency = 1;
+       domain->iommu_coherency = true;
 
        for_each_domain_iommu(i, domain) {
                found = true;
                if (!iommu_paging_structure_coherency(g_iommus[i])) {
-                       domain->iommu_coherency = 0;
+                       domain->iommu_coherency = false;
                        break;
                }
        }
@@ -642,18 +642,18 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain)
        rcu_read_lock();
        for_each_active_iommu(iommu, drhd) {
                if (!iommu_paging_structure_coherency(iommu)) {
-                       domain->iommu_coherency = 0;
+                       domain->iommu_coherency = false;
                        break;
                }
        }
        rcu_read_unlock();
 }
 
-static int domain_update_iommu_snooping(struct intel_iommu *skip)
+static bool domain_update_iommu_snooping(struct intel_iommu *skip)
 {
        struct dmar_drhd_unit *drhd;
        struct intel_iommu *iommu;
-       int ret = 1;
+       bool ret = true;
 
        rcu_read_lock();
        for_each_active_iommu(iommu, drhd) {
@@ -666,7 +666,7 @@ static int domain_update_iommu_snooping(struct intel_iommu *skip)
                         */
                        if (!sm_supported(iommu) &&
                            !ecap_sc_support(iommu->ecap)) {
-                               ret = 0;
+                               ret = false;
                                break;
                        }
                }
@@ -4506,8 +4506,8 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width)
        adjust_width = guestwidth_to_adjustwidth(guest_width);
        domain->agaw = width_to_agaw(adjust_width);
 
-       domain->iommu_coherency = 0;
-       domain->iommu_snooping = 0;
+       domain->iommu_coherency = false;
+       domain->iommu_snooping = false;
        domain->iommu_superpage = 0;
        domain->max_addr = 0;
 
@@ -5131,7 +5131,7 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
 static bool intel_iommu_capable(enum iommu_cap cap)
 {
        if (cap == IOMMU_CAP_CACHE_COHERENCY)
-               return domain_update_iommu_snooping(NULL) == 1;
+               return domain_update_iommu_snooping(NULL);
        if (cap == IOMMU_CAP_INTR_REMAP)
                return irq_remapping_enabled == 1;
 
index f5cf31dd72809498bf5f143c15cc2e5292918e8b..2621eff04c825b069ac46ec39330c9a607121d4e 100644 (file)
@@ -546,7 +546,10 @@ struct dmar_domain {
                                         * domain ids are 16 bit wide according
                                         * to VT-d spec, section 9.3 */
 
-       bool has_iotlb_device;
+       u8 has_iotlb_device: 1;
+       u8 iommu_coherency: 1;          /* indicate coherency of iommu access */
+       u8 iommu_snooping: 1;           /* indicate snooping control feature */
+
        struct list_head devices;       /* all devices' list */
        struct list_head subdevices;    /* all subdevices' list */
        struct iova_domain iovad;       /* iova's that belong to this domain */
@@ -558,9 +561,6 @@ struct dmar_domain {
        int             agaw;
 
        int             flags;          /* flags to find out type of domain */
-
-       int             iommu_coherency;/* indicate coherency of iommu access */
-       int             iommu_snooping; /* indicate snooping control feature*/
        int             iommu_count;    /* reference count of iommu */
        int             iommu_superpage;/* Level of superpages supported:
                                           0 == 4KiB (no superpages), 1 == 2MiB,