Skip to content

Commit 8124407

Browse files
rosatomjjoergroedel
authored andcommitted
iommu/s390: allow larger region tables
Extend the aperture calculation to consider sizes beyond the maximum size of a region third table. Attempt to always use the smallest table size possible to avoid unnecessary extra steps during translation. Update reserved region calculations to use the appropriate table size. Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> Reviewed-by: Niklas Schnelle <schnelle@linux.ibm.com> Tested-by: Niklas Schnelle <schnelle@linux.ibm.com> Link: https://lore.kernel.org/r/20250411202433.181683-6-mjrosato@linux.ibm.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent d5fbc5e commit 8124407

File tree

2 files changed

+53
-18
lines changed

2 files changed

+53
-18
lines changed

arch/s390/include/asm/pci_dma.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ enum zpci_ioat_dtype {
2525
#define ZPCI_KEY (PAGE_DEFAULT_KEY << 5)
2626

2727
#define ZPCI_TABLE_SIZE_RT (1UL << 42)
28+
#define ZPCI_TABLE_SIZE_RS (1UL << 53)
2829

2930
#define ZPCI_IOTA_STO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_ST)
3031
#define ZPCI_IOTA_RTTO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RT)

drivers/iommu/s390-iommu.c

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -511,9 +511,25 @@ static bool s390_iommu_capable(struct device *dev, enum iommu_cap cap)
511511
}
512512
}
513513

514+
static inline u64 max_tbl_size(struct s390_domain *domain)
515+
{
516+
switch (domain->origin_type) {
517+
case ZPCI_TABLE_TYPE_RTX:
518+
return ZPCI_TABLE_SIZE_RT - 1;
519+
case ZPCI_TABLE_TYPE_RSX:
520+
return ZPCI_TABLE_SIZE_RS - 1;
521+
case ZPCI_TABLE_TYPE_RFX:
522+
return U64_MAX;
523+
default:
524+
return 0;
525+
}
526+
}
527+
514528
static struct iommu_domain *s390_domain_alloc_paging(struct device *dev)
515529
{
530+
struct zpci_dev *zdev = to_zpci_dev(dev);
516531
struct s390_domain *s390_domain;
532+
u64 aperture_size;
517533

518534
s390_domain = kzalloc(sizeof(*s390_domain), GFP_KERNEL);
519535
if (!s390_domain)
@@ -524,10 +540,26 @@ static struct iommu_domain *s390_domain_alloc_paging(struct device *dev)
524540
kfree(s390_domain);
525541
return NULL;
526542
}
543+
544+
aperture_size = min(s390_iommu_aperture,
545+
zdev->end_dma - zdev->start_dma + 1);
546+
if (aperture_size <= (ZPCI_TABLE_SIZE_RT - zdev->start_dma)) {
547+
s390_domain->origin_type = ZPCI_TABLE_TYPE_RTX;
548+
} else if (aperture_size <= (ZPCI_TABLE_SIZE_RS - zdev->start_dma) &&
549+
(zdev->dtsm & ZPCI_IOTA_DT_RS)) {
550+
s390_domain->origin_type = ZPCI_TABLE_TYPE_RSX;
551+
} else if (zdev->dtsm & ZPCI_IOTA_DT_RF) {
552+
s390_domain->origin_type = ZPCI_TABLE_TYPE_RFX;
553+
} else {
554+
/* Assume RTX available */
555+
s390_domain->origin_type = ZPCI_TABLE_TYPE_RTX;
556+
aperture_size = ZPCI_TABLE_SIZE_RT - zdev->start_dma;
557+
}
558+
zdev->end_dma = zdev->start_dma + aperture_size - 1;
559+
527560
s390_domain->domain.geometry.force_aperture = true;
528561
s390_domain->domain.geometry.aperture_start = 0;
529-
s390_domain->domain.geometry.aperture_end = ZPCI_TABLE_SIZE_RT - 1;
530-
s390_domain->origin_type = ZPCI_TABLE_TYPE_RTX;
562+
s390_domain->domain.geometry.aperture_end = max_tbl_size(s390_domain);
531563

532564
spin_lock_init(&s390_domain->list_lock);
533565
INIT_LIST_HEAD_RCU(&s390_domain->devices);
@@ -680,6 +712,8 @@ static void s390_iommu_get_resv_regions(struct device *dev,
680712
{
681713
struct zpci_dev *zdev = to_zpci_dev(dev);
682714
struct iommu_resv_region *region;
715+
u64 max_size, end_resv;
716+
unsigned long flags;
683717

684718
if (zdev->start_dma) {
685719
region = iommu_alloc_resv_region(0, zdev->start_dma, 0,
@@ -689,10 +723,21 @@ static void s390_iommu_get_resv_regions(struct device *dev,
689723
list_add_tail(&region->list, list);
690724
}
691725

692-
if (zdev->end_dma < ZPCI_TABLE_SIZE_RT - 1) {
693-
region = iommu_alloc_resv_region(zdev->end_dma + 1,
694-
ZPCI_TABLE_SIZE_RT - zdev->end_dma - 1,
695-
0, IOMMU_RESV_RESERVED, GFP_KERNEL);
726+
spin_lock_irqsave(&zdev->dom_lock, flags);
727+
if (zdev->s390_domain->type == IOMMU_DOMAIN_BLOCKED ||
728+
zdev->s390_domain->type == IOMMU_DOMAIN_IDENTITY) {
729+
spin_unlock_irqrestore(&zdev->dom_lock, flags);
730+
return;
731+
}
732+
733+
max_size = max_tbl_size(to_s390_domain(zdev->s390_domain));
734+
spin_unlock_irqrestore(&zdev->dom_lock, flags);
735+
736+
if (zdev->end_dma < max_size) {
737+
end_resv = max_size - zdev->end_dma;
738+
region = iommu_alloc_resv_region(zdev->end_dma + 1, end_resv,
739+
0, IOMMU_RESV_RESERVED,
740+
GFP_KERNEL);
696741
if (!region)
697742
return;
698743
list_add_tail(&region->list, list);
@@ -708,13 +753,9 @@ static struct iommu_device *s390_iommu_probe_device(struct device *dev)
708753

709754
zdev = to_zpci_dev(dev);
710755

711-
if (zdev->start_dma > zdev->end_dma ||
712-
zdev->start_dma > ZPCI_TABLE_SIZE_RT - 1)
756+
if (zdev->start_dma > zdev->end_dma)
713757
return ERR_PTR(-EINVAL);
714758

715-
if (zdev->end_dma > ZPCI_TABLE_SIZE_RT - 1)
716-
zdev->end_dma = ZPCI_TABLE_SIZE_RT - 1;
717-
718759
if (zdev->tlb_refresh)
719760
dev->iommu->shadow_on_flush = 1;
720761

@@ -999,7 +1040,6 @@ struct zpci_iommu_ctrs *zpci_get_iommu_ctrs(struct zpci_dev *zdev)
9991040

10001041
int zpci_init_iommu(struct zpci_dev *zdev)
10011042
{
1002-
u64 aperture_size;
10031043
int rc = 0;
10041044

10051045
rc = iommu_device_sysfs_add(&zdev->iommu_dev, NULL, NULL,
@@ -1017,12 +1057,6 @@ int zpci_init_iommu(struct zpci_dev *zdev)
10171057
if (rc)
10181058
goto out_sysfs;
10191059

1020-
zdev->start_dma = PAGE_ALIGN(zdev->start_dma);
1021-
aperture_size = min3(s390_iommu_aperture,
1022-
ZPCI_TABLE_SIZE_RT - zdev->start_dma,
1023-
zdev->end_dma - zdev->start_dma + 1);
1024-
zdev->end_dma = zdev->start_dma + aperture_size - 1;
1025-
10261060
return 0;
10271061

10281062
out_sysfs:

0 commit comments

Comments
 (0)