Skip to content

Commit 2fcab2d

Browse files
hegdevasantjoergroedel
authored andcommitted
iommu/amd: Use ida interface to manage protection domain ID
Replace custom domain ID allocator with IDA interface. Signed-off-by: Vasant Hegde <vasant.hegde@amd.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/r/20241030063556.6104-3-vasant.hegde@amd.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 0169916 commit 2fcab2d

File tree

3 files changed

+35
-58
lines changed

3 files changed

+35
-58
lines changed

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -912,14 +912,14 @@ struct unity_map_entry {
912912
/* size of the dma_ops aperture as power of 2 */
913913
extern unsigned amd_iommu_aperture_order;
914914

915-
/* allocation bitmap for domain ids */
916-
extern unsigned long *amd_iommu_pd_alloc_bitmap;
917-
918915
extern bool amd_iommu_force_isolation;
919916

920917
/* Max levels of glxval supported */
921918
extern int amd_iommu_max_glx_val;
922919

920+
/* IDA to track protection domain IDs */
921+
extern struct ida pdom_ids;
922+
923923
/* Global EFR and EFR2 registers */
924924
extern u64 amd_iommu_efr;
925925
extern u64 amd_iommu_efr2;

drivers/iommu/amd/init.c

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,6 @@ bool amd_iommu_force_isolation __read_mostly;
194194

195195
unsigned long amd_iommu_pgsize_bitmap __ro_after_init = AMD_IOMMU_PGSIZES;
196196

197-
/*
198-
* AMD IOMMU allows up to 2^16 different protection domains. This is a bitmap
199-
* to know which ones are already in use.
200-
*/
201-
unsigned long *amd_iommu_pd_alloc_bitmap;
202-
203197
enum iommu_init_state {
204198
IOMMU_START_STATE,
205199
IOMMU_IVRS_DETECTED,
@@ -1082,7 +1076,12 @@ static bool __copy_device_table(struct amd_iommu *iommu)
10821076
if (dte_v && dom_id) {
10831077
pci_seg->old_dev_tbl_cpy[devid].data[0] = old_devtb[devid].data[0];
10841078
pci_seg->old_dev_tbl_cpy[devid].data[1] = old_devtb[devid].data[1];
1085-
__set_bit(dom_id, amd_iommu_pd_alloc_bitmap);
1079+
/* Reserve the Domain IDs used by previous kernel */
1080+
if (ida_alloc_range(&pdom_ids, dom_id, dom_id, GFP_ATOMIC) != dom_id) {
1081+
pr_err("Failed to reserve domain ID 0x%x\n", dom_id);
1082+
memunmap(old_devtb);
1083+
return false;
1084+
}
10861085
/* If gcr3 table existed, mask it out */
10871086
if (old_devtb[devid].data[0] & DTE_FLAG_GV) {
10881087
tmp = DTE_GCR3_VAL_B(~0ULL) << DTE_GCR3_SHIFT_B;
@@ -2985,9 +2984,7 @@ static bool __init check_ioapic_information(void)
29852984

29862985
static void __init free_dma_resources(void)
29872986
{
2988-
iommu_free_pages(amd_iommu_pd_alloc_bitmap,
2989-
get_order(MAX_DOMAIN_ID / 8));
2990-
amd_iommu_pd_alloc_bitmap = NULL;
2987+
ida_destroy(&pdom_ids);
29912988

29922989
free_unity_maps();
29932990
}
@@ -3055,20 +3052,6 @@ static int __init early_amd_iommu_init(void)
30553052
amd_iommu_target_ivhd_type = get_highest_supported_ivhd_type(ivrs_base);
30563053
DUMP_printk("Using IVHD type %#x\n", amd_iommu_target_ivhd_type);
30573054

3058-
/* Device table - directly used by all IOMMUs */
3059-
ret = -ENOMEM;
3060-
3061-
amd_iommu_pd_alloc_bitmap = iommu_alloc_pages(GFP_KERNEL,
3062-
get_order(MAX_DOMAIN_ID / 8));
3063-
if (amd_iommu_pd_alloc_bitmap == NULL)
3064-
goto out;
3065-
3066-
/*
3067-
* never allocate domain 0 because its used as the non-allocated and
3068-
* error value placeholder
3069-
*/
3070-
__set_bit(0, amd_iommu_pd_alloc_bitmap);
3071-
30723055
/*
30733056
* now the data structures are allocated and basically initialized
30743057
* start the real acpi table scan

drivers/iommu/amd/iommu.c

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/scatterlist.h>
1919
#include <linux/dma-map-ops.h>
2020
#include <linux/dma-direct.h>
21+
#include <linux/idr.h>
2122
#include <linux/iommu-helper.h>
2223
#include <linux/delay.h>
2324
#include <linux/amd-iommu.h>
@@ -52,8 +53,6 @@
5253
#define HT_RANGE_START (0xfd00000000ULL)
5354
#define HT_RANGE_END (0xffffffffffULL)
5455

55-
static DEFINE_SPINLOCK(pd_bitmap_lock);
56-
5756
LIST_HEAD(ioapic_map);
5857
LIST_HEAD(hpet_map);
5958
LIST_HEAD(acpihid_map);
@@ -70,6 +69,12 @@ struct iommu_cmd {
7069
u32 data[4];
7170
};
7271

72+
/*
73+
* AMD IOMMU allows up to 2^16 different protection domains. This is a bitmap
74+
* to know which ones are already in use.
75+
*/
76+
DEFINE_IDA(pdom_ids);
77+
7378
struct kmem_cache *amd_iommu_irq_cache;
7479

7580
static void detach_device(struct device *dev);
@@ -1643,31 +1648,14 @@ int amd_iommu_complete_ppr(struct device *dev, u32 pasid, int status, int tag)
16431648
*
16441649
****************************************************************************/
16451650

1646-
static u16 domain_id_alloc(void)
1651+
static int pdom_id_alloc(void)
16471652
{
1648-
unsigned long flags;
1649-
int id;
1650-
1651-
spin_lock_irqsave(&pd_bitmap_lock, flags);
1652-
id = find_first_zero_bit(amd_iommu_pd_alloc_bitmap, MAX_DOMAIN_ID);
1653-
BUG_ON(id == 0);
1654-
if (id > 0 && id < MAX_DOMAIN_ID)
1655-
__set_bit(id, amd_iommu_pd_alloc_bitmap);
1656-
else
1657-
id = 0;
1658-
spin_unlock_irqrestore(&pd_bitmap_lock, flags);
1659-
1660-
return id;
1653+
return ida_alloc_range(&pdom_ids, 1, MAX_DOMAIN_ID - 1, GFP_ATOMIC);
16611654
}
16621655

1663-
static void domain_id_free(int id)
1656+
static void pdom_id_free(int id)
16641657
{
1665-
unsigned long flags;
1666-
1667-
spin_lock_irqsave(&pd_bitmap_lock, flags);
1668-
if (id > 0 && id < MAX_DOMAIN_ID)
1669-
__clear_bit(id, amd_iommu_pd_alloc_bitmap);
1670-
spin_unlock_irqrestore(&pd_bitmap_lock, flags);
1658+
ida_free(&pdom_ids, id);
16711659
}
16721660

16731661
static void free_gcr3_tbl_level1(u64 *tbl)
@@ -1712,7 +1700,7 @@ static void free_gcr3_table(struct gcr3_tbl_info *gcr3_info)
17121700
gcr3_info->glx = 0;
17131701

17141702
/* Free per device domain ID */
1715-
domain_id_free(gcr3_info->domid);
1703+
pdom_id_free(gcr3_info->domid);
17161704

17171705
iommu_free_page(gcr3_info->gcr3_tbl);
17181706
gcr3_info->gcr3_tbl = NULL;
@@ -1739,6 +1727,7 @@ static int setup_gcr3_table(struct gcr3_tbl_info *gcr3_info,
17391727
{
17401728
int levels = get_gcr3_levels(pasids);
17411729
int nid = iommu ? dev_to_node(&iommu->dev->dev) : NUMA_NO_NODE;
1730+
int domid;
17421731

17431732
if (levels > amd_iommu_max_glx_val)
17441733
return -EINVAL;
@@ -1747,11 +1736,14 @@ static int setup_gcr3_table(struct gcr3_tbl_info *gcr3_info,
17471736
return -EBUSY;
17481737

17491738
/* Allocate per device domain ID */
1750-
gcr3_info->domid = domain_id_alloc();
1739+
domid = pdom_id_alloc();
1740+
if (domid <= 0)
1741+
return -ENOSPC;
1742+
gcr3_info->domid = domid;
17511743

17521744
gcr3_info->gcr3_tbl = iommu_alloc_page_node(nid, GFP_ATOMIC);
17531745
if (gcr3_info->gcr3_tbl == NULL) {
1754-
domain_id_free(gcr3_info->domid);
1746+
pdom_id_free(domid);
17551747
return -ENOMEM;
17561748
}
17571749

@@ -2262,7 +2254,7 @@ void protection_domain_free(struct protection_domain *domain)
22622254
WARN_ON(!list_empty(&domain->dev_list));
22632255
if (domain->domain.type & __IOMMU_DOMAIN_PAGING)
22642256
free_io_pgtable_ops(&domain->iop.pgtbl.ops);
2265-
domain_id_free(domain->id);
2257+
pdom_id_free(domain->id);
22662258
kfree(domain);
22672259
}
22682260

@@ -2277,16 +2269,18 @@ static void protection_domain_init(struct protection_domain *domain, int nid)
22772269
struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
22782270
{
22792271
struct protection_domain *domain;
2272+
int domid;
22802273

22812274
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
22822275
if (!domain)
22832276
return NULL;
22842277

2285-
domain->id = domain_id_alloc();
2286-
if (!domain->id) {
2278+
domid = pdom_id_alloc();
2279+
if (domid <= 0) {
22872280
kfree(domain);
22882281
return NULL;
22892282
}
2283+
domain->id = domid;
22902284

22912285
protection_domain_init(domain, nid);
22922286

@@ -2361,7 +2355,7 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
23612355

23622356
ret = pdom_setup_pgtable(domain, type, pgtable);
23632357
if (ret) {
2364-
domain_id_free(domain->id);
2358+
pdom_id_free(domain->id);
23652359
kfree(domain);
23662360
return ERR_PTR(ret);
23672361
}
@@ -2493,7 +2487,7 @@ void amd_iommu_init_identity_domain(void)
24932487
domain->ops = &identity_domain_ops;
24942488
domain->owner = &amd_iommu_ops;
24952489

2496-
identity_domain.id = domain_id_alloc();
2490+
identity_domain.id = pdom_id_alloc();
24972491

24982492
protection_domain_init(&identity_domain, NUMA_NO_NODE);
24992493
}

0 commit comments

Comments
 (0)