summaryrefslogtreecommitdiff
path: root/src/dev/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/dev/arm')
-rw-r--r--src/dev/arm/smmu_v3_cmdexec.cc22
1 files changed, 15 insertions, 7 deletions
diff --git a/src/dev/arm/smmu_v3_cmdexec.cc b/src/dev/arm/smmu_v3_cmdexec.cc
index 48896bf96..5b9dc6e4a 100644
--- a/src/dev/arm/smmu_v3_cmdexec.cc
+++ b/src/dev/arm/smmu_v3_cmdexec.cc
@@ -56,20 +56,28 @@ SMMUCommandExecProcess::main(Yield &yield)
busy = true;
while (true) {
- int sizeMask = mask(smmu.regs.cmdq_base & Q_BASE_SIZE_MASK);
+ // Masking depending on CMDQ_BASE.LOG2SIZE (log(number of
+ // queue entries)). Example: a value of 0b101 (32 entries)
+ // generates a 0b11111 mask.
+ int size_mask = mask(
+ smmu.regs.cmdq_base & Q_BASE_SIZE_MASK);
- if ((smmu.regs.cmdq_cons & sizeMask) ==
- (smmu.regs.cmdq_prod & sizeMask))
+ // In this case the wrap bit is considered (+1)
+ int size_mask_wrap = mask(
+ (smmu.regs.cmdq_base & Q_BASE_SIZE_MASK) + 1);
+
+ if ((smmu.regs.cmdq_cons & size_mask_wrap) ==
+ (smmu.regs.cmdq_prod & size_mask_wrap))
break; // command queue empty
- Addr cmdAddr =
+ Addr cmd_addr =
(smmu.regs.cmdq_base & Q_BASE_ADDR_MASK) +
- (smmu.regs.cmdq_cons & sizeMask) * sizeof(SMMUCommand);
+ (smmu.regs.cmdq_cons & size_mask) * sizeof(SMMUCommand);
// This deliberately resets the error field in cmdq_cons!
- smmu.regs.cmdq_cons = (smmu.regs.cmdq_cons + 1) & sizeMask;
+ smmu.regs.cmdq_cons = (smmu.regs.cmdq_cons + 1) & size_mask_wrap;
- doRead(yield, cmdAddr, &cmd, sizeof(SMMUCommand));
+ doRead(yield, cmd_addr, &cmd, sizeof(SMMUCommand));
smmu.processCommand(cmd);
}