Skip to content

Commit

Permalink
arm64: rsi: Add support for checking whether an MMIO is protected
Browse files Browse the repository at this point in the history
On Arm CCA, with RMM-v1.0, all MMIO regions are shared. However, in
the future, an Arm CCA-v1.0 compliant guest may be run in a lesser
privileged partition in the Realm World (with Arm CCA-v1.1 Planes
feature). In this case, some of the MMIO regions may be emulated
by a higher privileged component in the Realm world, i.e, protected.

Thus the guest must decide today, whether a given MMIO region is shared
vs Protected and create the stage1 mapping accordingly. On Arm CCA, this
detection is based on the "IPA State" (RIPAS == RIPAS_IO). Provide a
helper to run this check on a given range of MMIO.

Also, provide a arm64 helper which may be hooked in by other solutions.

Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Gavin Shan <gshan@redhat.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Steven Price <steven.price@arm.com>
Link: https://lore.kernel.org/r/20241017131434.40935-5-steven.price@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
  • Loading branch information
Suzuki K Poulose authored and Catalin Marinas committed Oct 23, 2024
1 parent 3993069 commit 3715894
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 0 deletions.
8 changes: 8 additions & 0 deletions arch/arm64/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <asm/early_ioremap.h>
#include <asm/alternative.h>
#include <asm/cpufeature.h>
#include <asm/rsi.h>

/*
* Generic IO read/write. These perform native-endian accesses.
Expand Down Expand Up @@ -318,4 +319,11 @@ extern bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
unsigned long flags);
#define arch_memremap_can_ram_remap arch_memremap_can_ram_remap

static inline bool arm64_is_protected_mmio(phys_addr_t phys_addr, size_t size)
{
if (unlikely(is_realm_world()))
return __arm64_is_protected_mmio(phys_addr, size);
return false;
}

#endif /* __ASM_IO_H */
2 changes: 2 additions & 0 deletions arch/arm64/include/asm/rsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ DECLARE_STATIC_KEY_FALSE(rsi_present);

void __init arm64_rsi_init(void);

bool __arm64_is_protected_mmio(phys_addr_t base, size_t size);

static inline bool is_realm_world(void)
{
return static_branch_unlikely(&rsi_present);
Expand Down
21 changes: 21 additions & 0 deletions arch/arm64/include/asm/rsi_cmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,27 @@ static inline unsigned long rsi_get_realm_config(struct realm_config *cfg)
return res.a0;
}

static inline unsigned long rsi_ipa_state_get(phys_addr_t start,
phys_addr_t end,
enum ripas *state,
phys_addr_t *top)
{
struct arm_smccc_res res;

arm_smccc_smc(SMC_RSI_IPA_STATE_GET,
start, end, 0, 0, 0, 0, 0,
&res);

if (res.a0 == RSI_SUCCESS) {
if (top)
*top = res.a1;
if (state)
*state = res.a2;
}

return res.a0;
}

static inline long rsi_set_addr_range_state(phys_addr_t start,
phys_addr_t end,
enum ripas state,
Expand Down
26 changes: 26 additions & 0 deletions arch/arm64/kernel/rsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,32 @@ static void __init arm64_rsi_setup_memory(void)
}
}

bool __arm64_is_protected_mmio(phys_addr_t base, size_t size)
{
enum ripas ripas;
phys_addr_t end, top;

/* Overflow ? */
if (WARN_ON(base + size <= base))
return false;

end = ALIGN(base + size, RSI_GRANULE_SIZE);
base = ALIGN_DOWN(base, RSI_GRANULE_SIZE);

while (base < end) {
if (WARN_ON(rsi_ipa_state_get(base, end, &ripas, &top)))
break;
if (WARN_ON(top <= base))
break;
if (ripas != RSI_RIPAS_DEV)
break;
base = top;
}

return base >= end;
}
EXPORT_SYMBOL(__arm64_is_protected_mmio);

void __init arm64_rsi_init(void)
{
if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
Expand Down

0 comments on commit 3715894

Please sign in to comment.