hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling
If the whole SID range (32b) is invalidated (SMMU_CMD_CFGI_ALL), @end overflows and we fail to handle the command properly. Once this gets fixed, the current code really is awkward in the sense it loops over the whole range instead of removing the currently cached configs through a hash table lookup. Fix both the overflow and the lookup. Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20210309102742.30442-7-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
6d9cd115b9
commit
1194140b7f
@ -104,4 +104,9 @@ typedef struct SMMUIOTLBPageInvInfo {
|
||||
uint64_t mask;
|
||||
} SMMUIOTLBPageInvInfo;
|
||||
|
||||
typedef struct SMMUSIDRange {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
} SMMUSIDRange;
|
||||
|
||||
#endif
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "hw/arm/smmuv3.h"
|
||||
#include "smmuv3-internal.h"
|
||||
#include "smmu-internal.h"
|
||||
|
||||
/**
|
||||
* smmuv3_trigger_irq - pulse @irq if enabled and update
|
||||
@ -895,6 +896,20 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
SMMUDevice *sdev = (SMMUDevice *)key;
|
||||
uint32_t sid = smmu_get_sid(sdev);
|
||||
SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
|
||||
|
||||
if (sid < sid_range->start || sid > sid_range->end) {
|
||||
return false;
|
||||
}
|
||||
trace_smmuv3_config_cache_inv(sid);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int smmuv3_cmdq_consume(SMMUv3State *s)
|
||||
{
|
||||
SMMUState *bs = ARM_SMMU(s);
|
||||
@ -965,27 +980,18 @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
|
||||
}
|
||||
case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */
|
||||
{
|
||||
uint32_t start = CMD_SID(&cmd), end, i;
|
||||
uint32_t start = CMD_SID(&cmd);
|
||||
uint8_t range = CMD_STE_RANGE(&cmd);
|
||||
uint64_t end = start + (1ULL << (range + 1)) - 1;
|
||||
SMMUSIDRange sid_range = {start, end};
|
||||
|
||||
if (CMD_SSEC(&cmd)) {
|
||||
cmd_error = SMMU_CERROR_ILL;
|
||||
break;
|
||||
}
|
||||
|
||||
end = start + (1 << (range + 1)) - 1;
|
||||
trace_smmuv3_cmdq_cfgi_ste_range(start, end);
|
||||
|
||||
for (i = start; i <= end; i++) {
|
||||
IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, i);
|
||||
SMMUDevice *sdev;
|
||||
|
||||
if (!mr) {
|
||||
continue;
|
||||
}
|
||||
sdev = container_of(mr, SMMUDevice, iommu);
|
||||
smmuv3_flush_config(sdev);
|
||||
}
|
||||
g_hash_table_foreach_remove(bs->configs, smmuv3_invalidate_ste,
|
||||
&sid_range);
|
||||
break;
|
||||
}
|
||||
case SMMU_CMD_CFGI_CD:
|
||||
|
Loading…
Reference in New Issue
Block a user