mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
ANDROID: KVM: arm64: Wait on S2MPU.STATUS after invalidation
The S2MPU must wait for a v9 device to finish invalidation before accessing its SFRs. Failure to do so can result in memory transaction timeouts. Add a loop that polls the STATUS register while the return value has the BUSY and ON_INVALIDATING bits set. Test: builds, boots Bug: 190463801 Bug: 206761586 Signed-off-by: David Brazdil <dbrazdil@google.com> Change-Id: I00891dc3a8ad185d29757b8622a053a96237b803
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#define REG_NS_INTERRUPT_ENABLE_PER_VID_SET 0x20
|
||||
#define REG_NS_INTERRUPT_CLEAR 0x2c
|
||||
#define REG_NS_VERSION 0x60
|
||||
#define REG_NS_STATUS 0x68
|
||||
#define REG_NS_NUM_CONTEXT 0x100
|
||||
#define REG_NS_CONTEXT_CFG_VALID_VID 0x104
|
||||
#define REG_NS_ALL_INVALIDATION 0x1000
|
||||
@@ -67,6 +68,9 @@
|
||||
VERSION_MINOR_ARCH_VER_MASK | \
|
||||
VERSION_REV_ARCH_VER_MASK)
|
||||
|
||||
#define STATUS_BUSY BIT(0)
|
||||
#define STATUS_ON_INVALIDATING BIT(1)
|
||||
|
||||
#define NUM_CONTEXT_MASK GENMASK(3, 0)
|
||||
|
||||
#define CONTEXT_CFG_VALID_VID_CTX_VALID(ctx) BIT((4 * (ctx)) + 3)
|
||||
|
||||
@@ -113,10 +113,26 @@ static void __set_control_regs(struct s2mpu *dev)
|
||||
writel_relaxed(ctrl0, dev->va + REG_NS_CTRL0);
|
||||
}
|
||||
|
||||
/* Poll the given SFR as long as its value has all bits of a given mask set. */
|
||||
static void __wait_while(void __iomem *addr, u32 mask)
|
||||
{
|
||||
while ((readl_relaxed(addr) & mask) == mask)
|
||||
continue;
|
||||
}
|
||||
|
||||
static void __wait_for_invalidation_complete(struct s2mpu *dev)
|
||||
{
|
||||
/* Must not access SFRs while S2MPU is busy invalidating (v9 only). */
|
||||
if (is_version(dev, S2MPU_VERSION_9)) {
|
||||
__wait_while(dev->va + REG_NS_STATUS,
|
||||
STATUS_BUSY | STATUS_ON_INVALIDATING);
|
||||
}
|
||||
}
|
||||
|
||||
static void __all_invalidation(struct s2mpu *dev)
|
||||
{
|
||||
writel_relaxed(INVALIDATION_INVALIDATE,
|
||||
dev->va + REG_NS_ALL_INVALIDATION);
|
||||
writel_relaxed(INVALIDATION_INVALIDATE, dev->va + REG_NS_ALL_INVALIDATION);
|
||||
__wait_for_invalidation_complete(dev);
|
||||
}
|
||||
|
||||
static void __range_invalidation(struct s2mpu *dev, phys_addr_t first_byte,
|
||||
@@ -128,6 +144,7 @@ static void __range_invalidation(struct s2mpu *dev, phys_addr_t first_byte,
|
||||
writel_relaxed(start_ppn, dev->va + REG_NS_RANGE_INVALIDATION_START_PPN);
|
||||
writel_relaxed(end_ppn, dev->va + REG_NS_RANGE_INVALIDATION_END_PPN);
|
||||
writel_relaxed(INVALIDATION_INVALIDATE, dev->va + REG_NS_RANGE_INVALIDATION);
|
||||
__wait_for_invalidation_complete(dev);
|
||||
}
|
||||
|
||||
static void __set_l1entry_attr_with_prot(struct s2mpu *dev, unsigned int gb,
|
||||
|
||||
Reference in New Issue
Block a user