136 lines
5.1 KiB
Diff
136 lines
5.1 KiB
Diff
|
|
From 03964c037862a594b4eb7d2e3754acd32c01c80b Mon Sep 17 00:00:00 2001
|
||
|
|
From: Nicolin Chen <nicolinc@nvidia.com>
|
||
|
|
Date: Thu, 22 Sep 2022 14:06:07 -0700
|
||
|
|
Subject: [PATCH] hw/arm/smmuv3: Read host SMMU device info
|
||
|
|
|
||
|
|
Read the underlying SMMU device info and set corresponding IDR bits.
|
||
|
|
|
||
|
|
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
|
||
|
|
---
|
||
|
|
hw/arm/smmuv3.c | 77 ++++++++++++++++++++++++++++++++++++
|
||
|
|
hw/arm/trace-events | 1 +
|
||
|
|
include/hw/arm/smmu-common.h | 1 +
|
||
|
|
3 files changed, 79 insertions(+)
|
||
|
|
|
||
|
|
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
|
||
|
|
index db111220c7..4208325ab3 100644
|
||
|
|
--- a/hw/arm/smmuv3.c
|
||
|
|
+++ b/hw/arm/smmuv3.c
|
||
|
|
@@ -254,6 +254,80 @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *info)
|
||
|
|
info->recorded = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
+static void smmuv3_nested_init_regs(SMMUv3State *s)
|
||
|
|
+{
|
||
|
|
+ SMMUState *bs = ARM_SMMU(s);
|
||
|
|
+ SMMUDevice *sdev;
|
||
|
|
+ uint32_t data_type;
|
||
|
|
+ uint32_t val;
|
||
|
|
+ int ret;
|
||
|
|
+
|
||
|
|
+ if (!bs->nested || !bs->viommu) {
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ sdev = QLIST_FIRST(&bs->viommu->device_list);
|
||
|
|
+ if (!sdev) {
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (sdev->info.idr[0]) {
|
||
|
|
+ error_report("reusing the previous hw_info");
|
||
|
|
+ goto out;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ ret = smmu_dev_get_info(sdev, &data_type, sizeof(sdev->info), &sdev->info);
|
||
|
|
+ if (ret) {
|
||
|
|
+ error_report("failed to get SMMU device info");
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (data_type != IOMMU_HW_INFO_TYPE_ARM_SMMUV3) {
|
||
|
|
+ error_report( "Wrong data type (%d)!", data_type);
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+out:
|
||
|
|
+ trace_smmuv3_get_device_info(sdev->info.idr[0], sdev->info.idr[1],
|
||
|
|
+ sdev->info.idr[3], sdev->info.idr[5]);
|
||
|
|
+
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[0], IDR0, BTM);
|
||
|
|
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, BTM, val);
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[0], IDR0, ATS);
|
||
|
|
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, ATS, val);
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[0], IDR0, ASID16);
|
||
|
|
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, ASID16, val);
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[0], IDR0, TERM_MODEL);
|
||
|
|
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TERM_MODEL, val);
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[0], IDR0, STALL_MODEL);
|
||
|
|
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, STALL_MODEL, val);
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[0], IDR0, STLEVEL);
|
||
|
|
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, STLEVEL, val);
|
||
|
|
+
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[1], IDR1, SIDSIZE);
|
||
|
|
+ s->idr[1] = FIELD_DP32(s->idr[1], IDR1, SIDSIZE, val);
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[1], IDR1, SSIDSIZE);
|
||
|
|
+ s->idr[1] = FIELD_DP32(s->idr[1], IDR1, SSIDSIZE, val);
|
||
|
|
+
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[3], IDR3, HAD);
|
||
|
|
+ s->idr[3] = FIELD_DP32(s->idr[3], IDR3, HAD, val);
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[3], IDR3, RIL);
|
||
|
|
+ s->idr[3] = FIELD_DP32(s->idr[3], IDR3, RIL, val);
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[3], IDR3, BBML);
|
||
|
|
+ s->idr[3] = FIELD_DP32(s->idr[3], IDR3, BBML, val);
|
||
|
|
+
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[5], IDR5, GRAN4K);
|
||
|
|
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, val);
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[5], IDR5, GRAN16K);
|
||
|
|
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN16K, val);
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[5], IDR5, GRAN64K);
|
||
|
|
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN64K, val);
|
||
|
|
+ val = FIELD_EX32(sdev->info.idr[5], IDR5, OAS);
|
||
|
|
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, val);
|
||
|
|
+
|
||
|
|
+ /* FIXME check iidr and aidr registrs too */
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
static void smmuv3_init_regs(SMMUv3State *s)
|
||
|
|
{
|
||
|
|
/* Based on sys property, the stages supported in smmu will be advertised.*/
|
||
|
|
@@ -292,6 +366,9 @@ static void smmuv3_init_regs(SMMUv3State *s)
|
||
|
|
s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN16K, 1);
|
||
|
|
s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1);
|
||
|
|
|
||
|
|
+ /* Override IDR fields with HW caps */
|
||
|
|
+ smmuv3_nested_init_regs(s);
|
||
|
|
+
|
||
|
|
s->cmdq.base = deposit64(s->cmdq.base, 0, 5, SMMU_CMDQS);
|
||
|
|
s->cmdq.prod = 0;
|
||
|
|
s->cmdq.cons = 0;
|
||
|
|
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
|
||
|
|
index 58e0636e95..1e3d86382d 100644
|
||
|
|
--- a/hw/arm/trace-events
|
||
|
|
+++ b/hw/arm/trace-events
|
||
|
|
@@ -55,5 +55,6 @@ smmuv3_cmdq_tlbi_s12_vmid(uint16_t vmid) "vmid=%d"
|
||
|
|
smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
|
||
|
|
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
|
||
|
|
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
|
||
|
|
+smmuv3_get_device_info(uint32_t idr0, uint32_t idr1, uint32_t idr3, uint32_t idr5) "idr0=0x%x idr1=0x%x idr3=0x%x idr5=0x%x"
|
||
|
|
smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint16_t vmid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d vmid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64
|
||
|
|
|
||
|
|
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
|
||
|
|
index 37dfeed026..d120c352cf 100644
|
||
|
|
--- a/include/hw/arm/smmu-common.h
|
||
|
|
+++ b/include/hw/arm/smmu-common.h
|
||
|
|
@@ -146,6 +146,7 @@ typedef struct SMMUDevice {
|
||
|
|
AddressSpace as_sysmem;
|
||
|
|
uint32_t cfg_cache_hits;
|
||
|
|
uint32_t cfg_cache_misses;
|
||
|
|
+ struct iommu_hw_info_arm_smmuv3 info;
|
||
|
|
QLIST_ENTRY(SMMUDevice) next;
|
||
|
|
} SMMUDevice;
|
||
|
|
|
||
|
|
--
|
||
|
|
2.41.0.windows.1
|
||
|
|
|