Skip to content

Commit 556af58

Browse files
committed
Merge branch 'core' into amd/amd-vi
2 parents e3a682e + a33bf8d commit 556af58

File tree

11 files changed

+254
-199
lines changed

11 files changed

+254
-199
lines changed

drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
120120
mutex_init(&tdev->iommu.mutex);
121121

122122
if (device_iommu_mapped(dev)) {
123-
tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type);
124-
if (!tdev->iommu.domain)
123+
tdev->iommu.domain = iommu_paging_domain_alloc(dev);
124+
if (IS_ERR(tdev->iommu.domain))
125125
goto error;
126126

127127
/*

drivers/iommu/amd/amd_iommu.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ extern int amd_iommu_gpt_level;
4646
extern unsigned long amd_iommu_pgsize_bitmap;
4747

4848
/* Protection domain ops */
49+
void amd_iommu_init_identity_domain(void);
4950
struct protection_domain *protection_domain_alloc(unsigned int type, int nid);
5051
void protection_domain_free(struct protection_domain *domain);
5152
struct iommu_domain *amd_iommu_domain_alloc_sva(struct device *dev,
@@ -118,9 +119,14 @@ static inline bool check_feature2(u64 mask)
118119
return (amd_iommu_efr2 & mask);
119120
}
120121

122+
static inline bool amd_iommu_v2_pgtbl_supported(void)
123+
{
124+
return (check_feature(FEATURE_GIOSUP) && check_feature(FEATURE_GT));
125+
}
126+
121127
static inline bool amd_iommu_gt_ppr_supported(void)
122128
{
123-
return (check_feature(FEATURE_GT) &&
129+
return (amd_iommu_v2_pgtbl_supported() &&
124130
check_feature(FEATURE_PPR) &&
125131
check_feature(FEATURE_EPHSUP));
126132
}

drivers/iommu/amd/init.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2070,14 +2070,6 @@ static int __init iommu_init_pci(struct amd_iommu *iommu)
20702070

20712071
init_iommu_perf_ctr(iommu);
20722072

2073-
if (amd_iommu_pgtable == AMD_IOMMU_V2) {
2074-
if (!check_feature(FEATURE_GIOSUP) ||
2075-
!check_feature(FEATURE_GT)) {
2076-
pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n");
2077-
amd_iommu_pgtable = AMD_IOMMU_V1;
2078-
}
2079-
}
2080-
20812073
if (is_rd890_iommu(iommu->dev)) {
20822074
int i, j;
20832075

@@ -2172,6 +2164,9 @@ static int __init amd_iommu_init_pci(void)
21722164
struct amd_iommu_pci_seg *pci_seg;
21732165
int ret;
21742166

2167+
/* Init global identity domain before registering IOMMU */
2168+
amd_iommu_init_identity_domain();
2169+
21752170
for_each_iommu(iommu) {
21762171
ret = iommu_init_pci(iommu);
21772172
if (ret) {
@@ -3087,6 +3082,13 @@ static int __init early_amd_iommu_init(void)
30873082
FIELD_GET(FEATURE_GATS, amd_iommu_efr) == GUEST_PGTABLE_5_LEVEL)
30883083
amd_iommu_gpt_level = PAGE_MODE_5_LEVEL;
30893084

3085+
if (amd_iommu_pgtable == AMD_IOMMU_V2) {
3086+
if (!amd_iommu_v2_pgtbl_supported()) {
3087+
pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n");
3088+
amd_iommu_pgtable = AMD_IOMMU_V1;
3089+
}
3090+
}
3091+
30903092
/* Disable any previously enabled IOMMUs */
30913093
if (!is_kdump_kernel() || amd_iommu_disabled)
30923094
disable_iommus();

drivers/iommu/amd/iommu.c

Lines changed: 98 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ struct kmem_cache *amd_iommu_irq_cache;
7474

7575
static void detach_device(struct device *dev);
7676

77+
static int amd_iommu_attach_device(struct iommu_domain *dom,
78+
struct device *dev);
79+
7780
static void set_dte_entry(struct amd_iommu *iommu,
7881
struct iommu_dev_data *dev_data);
7982

@@ -2263,43 +2266,41 @@ void protection_domain_free(struct protection_domain *domain)
22632266
kfree(domain);
22642267
}
22652268

2269+
static void protection_domain_init(struct protection_domain *domain, int nid)
2270+
{
2271+
spin_lock_init(&domain->lock);
2272+
INIT_LIST_HEAD(&domain->dev_list);
2273+
INIT_LIST_HEAD(&domain->dev_data_list);
2274+
domain->iop.pgtbl.cfg.amd.nid = nid;
2275+
}
2276+
22662277
struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
22672278
{
2268-
struct io_pgtable_ops *pgtbl_ops;
22692279
struct protection_domain *domain;
2270-
int pgtable;
22712280

22722281
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
22732282
if (!domain)
22742283
return NULL;
22752284

22762285
domain->id = domain_id_alloc();
2277-
if (!domain->id)
2278-
goto err_free;
2286+
if (!domain->id) {
2287+
kfree(domain);
2288+
return NULL;
2289+
}
22792290

2280-
spin_lock_init(&domain->lock);
2281-
INIT_LIST_HEAD(&domain->dev_list);
2282-
INIT_LIST_HEAD(&domain->dev_data_list);
2283-
domain->iop.pgtbl.cfg.amd.nid = nid;
2291+
protection_domain_init(domain, nid);
2292+
2293+
return domain;
2294+
}
2295+
2296+
static int pdom_setup_pgtable(struct protection_domain *domain,
2297+
unsigned int type, int pgtable)
2298+
{
2299+
struct io_pgtable_ops *pgtbl_ops;
22842300

2285-
switch (type) {
22862301
/* No need to allocate io pgtable ops in passthrough mode */
2287-
case IOMMU_DOMAIN_IDENTITY:
2288-
case IOMMU_DOMAIN_SVA:
2289-
return domain;
2290-
case IOMMU_DOMAIN_DMA:
2291-
pgtable = amd_iommu_pgtable;
2292-
break;
2293-
/*
2294-
* Force IOMMU v1 page table when allocating
2295-
* domain for pass-through devices.
2296-
*/
2297-
case IOMMU_DOMAIN_UNMANAGED:
2298-
pgtable = AMD_IOMMU_V1;
2299-
break;
2300-
default:
2301-
goto err_id;
2302-
}
2302+
if (!(type & __IOMMU_DOMAIN_PAGING))
2303+
return 0;
23032304

23042305
switch (pgtable) {
23052306
case AMD_IOMMU_V1:
@@ -2309,25 +2310,20 @@ struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
23092310
domain->pd_mode = PD_MODE_V2;
23102311
break;
23112312
default:
2312-
goto err_id;
2313+
return -EINVAL;
23132314
}
23142315

23152316
pgtbl_ops =
23162317
alloc_io_pgtable_ops(pgtable, &domain->iop.pgtbl.cfg, domain);
23172318
if (!pgtbl_ops)
2318-
goto err_id;
2319+
return -ENOMEM;
23192320

2320-
return domain;
2321-
err_id:
2322-
domain_id_free(domain->id);
2323-
err_free:
2324-
kfree(domain);
2325-
return NULL;
2321+
return 0;
23262322
}
23272323

2328-
static inline u64 dma_max_address(void)
2324+
static inline u64 dma_max_address(int pgtable)
23292325
{
2330-
if (amd_iommu_pgtable == AMD_IOMMU_V1)
2326+
if (pgtable == AMD_IOMMU_V1)
23312327
return ~0ULL;
23322328

23332329
/* V2 with 4/5 level page table */
@@ -2340,11 +2336,13 @@ static bool amd_iommu_hd_support(struct amd_iommu *iommu)
23402336
}
23412337

23422338
static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
2343-
struct device *dev, u32 flags)
2339+
struct device *dev,
2340+
u32 flags, int pgtable)
23442341
{
23452342
bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
23462343
struct protection_domain *domain;
23472344
struct amd_iommu *iommu = NULL;
2345+
int ret;
23482346

23492347
if (dev)
23502348
iommu = get_amd_iommu_from_dev(dev);
@@ -2356,16 +2354,20 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
23562354
if (amd_iommu_snp_en && (type == IOMMU_DOMAIN_IDENTITY))
23572355
return ERR_PTR(-EINVAL);
23582356

2359-
if (dirty_tracking && !amd_iommu_hd_support(iommu))
2360-
return ERR_PTR(-EOPNOTSUPP);
2361-
23622357
domain = protection_domain_alloc(type,
23632358
dev ? dev_to_node(dev) : NUMA_NO_NODE);
23642359
if (!domain)
23652360
return ERR_PTR(-ENOMEM);
23662361

2362+
ret = pdom_setup_pgtable(domain, type, pgtable);
2363+
if (ret) {
2364+
domain_id_free(domain->id);
2365+
kfree(domain);
2366+
return ERR_PTR(ret);
2367+
}
2368+
23672369
domain->domain.geometry.aperture_start = 0;
2368-
domain->domain.geometry.aperture_end = dma_max_address();
2370+
domain->domain.geometry.aperture_end = dma_max_address(pgtable);
23692371
domain->domain.geometry.force_aperture = true;
23702372
domain->domain.pgsize_bitmap = domain->iop.pgtbl.cfg.pgsize_bitmap;
23712373

@@ -2383,8 +2385,16 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
23832385
static struct iommu_domain *amd_iommu_domain_alloc(unsigned int type)
23842386
{
23852387
struct iommu_domain *domain;
2388+
int pgtable = amd_iommu_pgtable;
23862389

2387-
domain = do_iommu_domain_alloc(type, NULL, 0);
2390+
/*
2391+
* Force IOMMU v1 page table when allocating
2392+
* domain for pass-through devices.
2393+
*/
2394+
if (type == IOMMU_DOMAIN_UNMANAGED)
2395+
pgtable = AMD_IOMMU_V1;
2396+
2397+
domain = do_iommu_domain_alloc(type, NULL, 0, pgtable);
23882398
if (IS_ERR(domain))
23892399
return NULL;
23902400

@@ -2398,11 +2408,36 @@ amd_iommu_domain_alloc_user(struct device *dev, u32 flags,
23982408

23992409
{
24002410
unsigned int type = IOMMU_DOMAIN_UNMANAGED;
2411+
struct amd_iommu *iommu = NULL;
2412+
const u32 supported_flags = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
2413+
IOMMU_HWPT_ALLOC_PASID;
2414+
2415+
if (dev)
2416+
iommu = get_amd_iommu_from_dev(dev);
24012417

2402-
if ((flags & ~IOMMU_HWPT_ALLOC_DIRTY_TRACKING) || parent || user_data)
2418+
if ((flags & ~supported_flags) || parent || user_data)
24032419
return ERR_PTR(-EOPNOTSUPP);
24042420

2405-
return do_iommu_domain_alloc(type, dev, flags);
2421+
/* Allocate domain with v2 page table if IOMMU supports PASID. */
2422+
if (flags & IOMMU_HWPT_ALLOC_PASID) {
2423+
if (!amd_iommu_pasid_supported())
2424+
return ERR_PTR(-EOPNOTSUPP);
2425+
2426+
return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V2);
2427+
}
2428+
2429+
/* Allocate domain with v1 page table for dirty tracking */
2430+
if (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) {
2431+
if (iommu && amd_iommu_hd_support(iommu)) {
2432+
return do_iommu_domain_alloc(type, dev,
2433+
flags, AMD_IOMMU_V1);
2434+
}
2435+
2436+
return ERR_PTR(-EOPNOTSUPP);
2437+
}
2438+
2439+
/* If nothing specific is required use the kernel commandline default */
2440+
return do_iommu_domain_alloc(type, dev, 0, amd_iommu_pgtable);
24062441
}
24072442

24082443
void amd_iommu_domain_free(struct iommu_domain *dom)
@@ -2444,6 +2479,25 @@ static struct iommu_domain blocked_domain = {
24442479
}
24452480
};
24462481

2482+
static struct protection_domain identity_domain;
2483+
2484+
static const struct iommu_domain_ops identity_domain_ops = {
2485+
.attach_dev = amd_iommu_attach_device,
2486+
};
2487+
2488+
void amd_iommu_init_identity_domain(void)
2489+
{
2490+
struct iommu_domain *domain = &identity_domain.domain;
2491+
2492+
domain->type = IOMMU_DOMAIN_IDENTITY;
2493+
domain->ops = &identity_domain_ops;
2494+
domain->owner = &amd_iommu_ops;
2495+
2496+
identity_domain.id = domain_id_alloc();
2497+
2498+
protection_domain_init(&identity_domain, NUMA_NO_NODE);
2499+
}
2500+
24472501
static int amd_iommu_attach_device(struct iommu_domain *dom,
24482502
struct device *dev)
24492503
{
@@ -2842,6 +2896,7 @@ static int amd_iommu_dev_disable_feature(struct device *dev,
28422896
const struct iommu_ops amd_iommu_ops = {
28432897
.capable = amd_iommu_capable,
28442898
.blocked_domain = &blocked_domain,
2899+
.identity_domain = &identity_domain.domain,
28452900
.domain_alloc = amd_iommu_domain_alloc,
28462901
.domain_alloc_user = amd_iommu_domain_alloc_user,
28472902
.domain_alloc_sva = amd_iommu_domain_alloc_sva,

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3084,7 +3084,8 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
30843084
const struct iommu_user_data *user_data)
30853085
{
30863086
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
3087-
const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
3087+
const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
3088+
IOMMU_HWPT_ALLOC_PASID;
30883089
struct arm_smmu_domain *smmu_domain;
30893090
int ret;
30903091

@@ -3093,6 +3094,9 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
30933094
if (parent || user_data)
30943095
return ERR_PTR(-EOPNOTSUPP);
30953096

3097+
if (flags & IOMMU_HWPT_ALLOC_PASID)
3098+
return arm_smmu_domain_alloc_paging(dev);
3099+
30963100
smmu_domain = arm_smmu_domain_alloc();
30973101
if (IS_ERR(smmu_domain))
30983102
return ERR_CAST(smmu_domain);

drivers/iommu/iommu-sysfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ static void release_device(struct device *dev)
3434
kfree(dev);
3535
}
3636

37-
static struct class iommu_class = {
37+
static const struct class iommu_class = {
3838
.name = "iommu",
3939
.dev_release = release_device,
4040
.dev_groups = dev_groups,

0 commit comments

Comments
 (0)