mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 16:23:55 -06:00
hw/arm/smmuv3: Get prepared for range invalidation
Enhance the smmu_iotlb_inv_iova() helper with range invalidation. This uses the new fields passed in the NH_VA and NH_VAA commands: the size of the range, the level and the granule. As NH_VA and NH_VAA both use those fields, their decoding and handling is factorized in a new smmuv3_s1_range_inval() helper. Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20200728150815.11446-8-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
c0f9ef7037
commit
d52915616c
5 changed files with 69 additions and 31 deletions
|
@ -785,42 +785,49 @@ epilogue:
|
|||
* @n: notifier to be called
|
||||
* @asid: address space ID or negative value if we don't care
|
||||
* @iova: iova
|
||||
* @tg: translation granule (if communicated through range invalidation)
|
||||
* @num_pages: number of @granule sized pages (if tg != 0), otherwise 1
|
||||
*/
|
||||
static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
|
||||
IOMMUNotifier *n,
|
||||
int asid,
|
||||
dma_addr_t iova)
|
||||
int asid, dma_addr_t iova,
|
||||
uint8_t tg, uint64_t num_pages)
|
||||
{
|
||||
SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
|
||||
SMMUEventInfo event = {.inval_ste_allowed = true};
|
||||
SMMUTransTableInfo *tt;
|
||||
SMMUTransCfg *cfg;
|
||||
IOMMUTLBEntry entry;
|
||||
uint8_t granule = tg;
|
||||
|
||||
cfg = smmuv3_get_config(sdev, &event);
|
||||
if (!cfg) {
|
||||
return;
|
||||
}
|
||||
if (!tg) {
|
||||
SMMUEventInfo event = {.inval_ste_allowed = true};
|
||||
SMMUTransCfg *cfg = smmuv3_get_config(sdev, &event);
|
||||
SMMUTransTableInfo *tt;
|
||||
|
||||
if (asid >= 0 && cfg->asid != asid) {
|
||||
return;
|
||||
}
|
||||
if (!cfg) {
|
||||
return;
|
||||
}
|
||||
|
||||
tt = select_tt(cfg, iova);
|
||||
if (!tt) {
|
||||
return;
|
||||
if (asid >= 0 && cfg->asid != asid) {
|
||||
return;
|
||||
}
|
||||
|
||||
tt = select_tt(cfg, iova);
|
||||
if (!tt) {
|
||||
return;
|
||||
}
|
||||
granule = tt->granule_sz;
|
||||
}
|
||||
|
||||
entry.target_as = &address_space_memory;
|
||||
entry.iova = iova;
|
||||
entry.addr_mask = (1 << tt->granule_sz) - 1;
|
||||
entry.addr_mask = num_pages * (1 << granule) - 1;
|
||||
entry.perm = IOMMU_NONE;
|
||||
|
||||
memory_region_notify_one(n, &entry);
|
||||
}
|
||||
|
||||
/* invalidate an asid/iova tuple in all mr's */
|
||||
static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
|
||||
/* invalidate an asid/iova range tuple in all mr's */
|
||||
static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova,
|
||||
uint8_t tg, uint64_t num_pages)
|
||||
{
|
||||
SMMUDevice *sdev;
|
||||
|
||||
|
@ -828,28 +835,39 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
|
|||
IOMMUMemoryRegion *mr = &sdev->iommu;
|
||||
IOMMUNotifier *n;
|
||||
|
||||
trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova);
|
||||
trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova,
|
||||
tg, num_pages);
|
||||
|
||||
IOMMU_NOTIFIER_FOREACH(n, mr) {
|
||||
smmuv3_notify_iova(mr, n, asid, iova);
|
||||
smmuv3_notify_iova(mr, n, asid, iova, tg, num_pages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
|
||||
{
|
||||
uint8_t scale = 0, num = 0, ttl = 0;
|
||||
dma_addr_t addr = CMD_ADDR(cmd);
|
||||
uint8_t type = CMD_TYPE(cmd);
|
||||
uint16_t vmid = CMD_VMID(cmd);
|
||||
bool leaf = CMD_LEAF(cmd);
|
||||
uint8_t tg = CMD_TG(cmd);
|
||||
hwaddr num_pages = 1;
|
||||
int asid = -1;
|
||||
|
||||
if (tg) {
|
||||
scale = CMD_SCALE(cmd);
|
||||
num = CMD_NUM(cmd);
|
||||
ttl = CMD_TTL(cmd);
|
||||
num_pages = (num + 1) * (1 << (scale));
|
||||
}
|
||||
|
||||
if (type == SMMU_CMD_TLBI_NH_VA) {
|
||||
asid = CMD_ASID(cmd);
|
||||
}
|
||||
trace_smmuv3_s1_range_inval(vmid, asid, addr, leaf);
|
||||
smmuv3_inv_notifiers_iova(s, asid, addr);
|
||||
smmu_iotlb_inv_iova(s, asid, addr);
|
||||
trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
|
||||
smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
|
||||
smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl);
|
||||
}
|
||||
|
||||
static int smmuv3_cmdq_consume(SMMUv3State *s)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue