static MemoryRegion root, sysmem;
static AddressSpace *shared_as_sysmem;
+static int smmuv3_oas_bits(uint32_t oas)
+{
+ static const int map[] = { 32, 36, 40, 42, 44, 48, 52, 56 };
+
+ g_assert(oas < ARRAY_SIZE(map));
+ return map[oas];
+}
+
static bool
smmuv3_accel_check_hw_compatible(SMMUv3State *s,
struct iommu_hw_info_arm_smmuv3 *info,
error_setg(errp, "Host SMMUv3 doesn't support Range Invalidation");
return false;
}
+ /* Check OAS value opted is compatible with Host SMMUv3 IPA */
+ if (FIELD_EX32(info->idr[5], IDR5, OAS) <
+ FIELD_EX32(s->idr[5], IDR5, OAS)) {
+ error_setg(errp, "Host SMMUv3 supports only %d-bit IPA, but the vSMMU "
+ "OAS implies %d-bit IPA",
+ smmuv3_oas_bits(FIELD_EX32(info->idr[5], IDR5, OAS)),
+ smmuv3_oas_bits(FIELD_EX32(s->idr[5], IDR5, OAS)));
+ return false;
+ }
/* QEMU SMMUv3 supports GRAN4K/GRAN16K/GRAN64K translation granules */
if (FIELD_EX32(info->idr[5], IDR5, GRAN4K) !=
/* QEMU SMMUv3 has no ATS. Advertise ATS if opt-in by property */
s->idr[0] = FIELD_DP32(s->idr[0], IDR0, ATS, s->ats);
+
+ /* Advertise 48-bit OAS in IDR5 when requested (default is 44 bits). */
+ if (s->oas == SMMU_OAS_48BIT) {
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS_48);
+ }
}
/* Based on SMUUv3 GPBA.ABORT configuration, attach a corresponding HWPT */
s->idr[3] = FIELD_DP32(s->idr[3], IDR3, RIL, 1);
s->idr[3] = FIELD_DP32(s->idr[3], IDR3, BBML, 2);
- s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS); /* 44 bits */
+ /* OAS: 44 bits */
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS_44);
/* 4K, 16K and 64K granule support */
s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1);
s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN16K, 1);
error_setg(errp, "ats can only be enabled if accel=on");
return false;
}
+ if (s->oas != SMMU_OAS_44BIT) {
+ error_setg(errp, "OAS must be 44 bits when accel=off");
+ return false;
+ }
return true;
}
return false;
}
+ if (s->oas != SMMU_OAS_44BIT && s->oas != SMMU_OAS_48BIT) {
+ error_setg(errp, "OAS can only be set to 44 or 48 bits");
+ return false;
+ }
+
return true;
}
/* RIL can be turned off for accel cases */
DEFINE_PROP_BOOL("ril", SMMUv3State, ril, true),
DEFINE_PROP_BOOL("ats", SMMUv3State, ats, false),
+ DEFINE_PROP_UINT8("oas", SMMUv3State, oas, 44),
};
static void smmuv3_instance_init(Object *obj)
object_class_property_set_description(klass, "ats",
"Enable/disable ATS support (for accel=on). Please ensure host "
"platform has ATS support before enabling this");
+ object_class_property_set_description(klass, "oas",
+ "Specify Output Address Size (for accel=on). Supported values "
+ "are 44 or 48 bits. Defaults to 44 bits");
}
static int smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,