[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH 15/16] hw/misc: riscv_wgchecker: Check the slot settings in t
From: |
Jim Shu |
Subject: |
[RFC PATCH 15/16] hw/misc: riscv_wgchecker: Check the slot settings in translate |
Date: |
Wed, 12 Jun 2024 16:14:15 +0800 |
The final part of wgChecker we need to implement is actually using the
wgChecker slots programmed by guest to determine whether to block the
transaction or not.
Since this means we now change transaction mappings when
the guest writes to wgChecker slots, we must also call the IOMMU
notifiers at that point.
One tricky part here is that the perm of 'blocked_io_as' is the
condition of deny access. For example, if wgChecker only permits RO
access, the perm of 'downstream_as' will be IOMMU_RO and the perm of
'blocked_io_as' will be IOMMU_WO.
Signed-off-by: Jim Shu <jim.shu@sifive.com>
---
hw/misc/riscv_wgchecker.c | 70 ++++++++++++++++++++++++++++++++++++---
hw/misc/trace-events | 1 +
2 files changed, 67 insertions(+), 4 deletions(-)
diff --git a/hw/misc/riscv_wgchecker.c b/hw/misc/riscv_wgchecker.c
index 55e5e8127f..cab4e40921 100644
--- a/hw/misc/riscv_wgchecker.c
+++ b/hw/misc/riscv_wgchecker.c
@@ -100,6 +100,52 @@ REG32(SLOT_CFG, 0x010)
#define P_READ (1 << 0)
#define P_WRITE (1 << 1)
+static IOMMUAccessFlags wgc_perm_to_iommu_flags(int wgc_perm)
+{
+ if (wgc_perm == (P_READ | P_WRITE)) {
+ return IOMMU_RW;
+ } else if (wgc_perm & P_WRITE) {
+ return IOMMU_WO;
+ } else if (wgc_perm & P_READ) {
+ return IOMMU_RO;
+ } else {
+ return IOMMU_NONE;
+ }
+}
+
+static void wgchecker_iommu_notify_all(RISCVWgCheckerState *s)
+{
+ /*
+ * Do tlb_flush() to whole address space via memory_region_notify_iommu()
+ * when wgChecker changes it's config.
+ */
+
+ IOMMUTLBEvent event = {
+ .entry = {
+ .addr_mask = -1ULL,
+ }
+ };
+
+ trace_riscv_wgc_iommu_notify_all();
+
+ for (int i=0; i<WGC_NUM_REGIONS; i++) {
+ WgCheckerRegion *region = &s->mem_regions[i];
+ uint32_t nworlds = worldguard_config->nworlds;
+
+ if (!region->downstream) {
+ continue;
+ }
+ event.entry.iova = 0;
+ event.entry.translated_addr = 0;
+ event.type = IOMMU_NOTIFIER_UNMAP;
+ event.entry.perm = IOMMU_NONE;
+
+ for (int wid=0; wid<nworlds; wid++) {
+ memory_region_notify_iommu(®ion->upstream, wid, event);
+ }
+ }
+}
+
static void decode_napot(hwaddr a, hwaddr *sa, hwaddr *ea)
{
/*
@@ -309,6 +355,9 @@ static IOMMUTLBEntry riscv_wgc_translate(IOMMUMemoryRegion
*iommu,
{
WgCheckerRegion *region = container_of(iommu, WgCheckerRegion, upstream);
RISCVWgCheckerState *s = RISCV_WGCHECKER(region->wgchecker);
+ bool is_write;
+ WgAccessResult result;
+ int wgc_perm;
hwaddr phys_addr;
uint64_t region_size;
@@ -327,18 +376,25 @@ static IOMMUTLBEntry
riscv_wgc_translate(IOMMUMemoryRegion *iommu,
* Look at the wgChecker configuration for this address, and
* return a TLB entry directing the transaction at either
* downstream_as or blocked_io_as, as appropriate.
- * For the moment, always permit accesses.
*/
/* Use physical address instead of offset */
phys_addr = addr + region->region_offset;
+ is_write = (flags == IOMMU_WO);
- is_success = true;
+ result = wgc_check_access(s, phys_addr, iommu_idx, is_write);
trace_riscv_wgc_translate(phys_addr, flags,
- iommu_idx, is_success ? "pass" : "block");
+ iommu_idx, result.is_success ? "pass" : "block");
- ret.target_as = is_success ? ®ion->downstream_as :
®ion->blocked_io_as;
+ wgc_perm = result.perm;
+ if (!result.is_success) {
+ /* if target_as is blocked_io_as, the perm is the condition of deny
access. */
+ wgc_perm ^= (P_READ | P_WRITE);
+ }
+ ret.perm = wgc_perm_to_iommu_flags(wgc_perm);
+
+ ret.target_as = result.is_success ? ®ion->downstream_as :
®ion->blocked_io_as;
return ret;
}
@@ -604,6 +660,9 @@ static void riscv_wgchecker_writeq(void *opaque, hwaddr
addr,
break;
}
+ /* Flush softmmu TLB when wgChecker changes config. */
+ wgchecker_iommu_notify_all(s);
+
return;
}
@@ -699,6 +758,9 @@ static void riscv_wgchecker_writel(void *opaque, hwaddr
addr,
break;
}
+ /* Flush softmmu TLB when wgChecker changes config. */
+ wgchecker_iommu_notify_all(s);
+
return;
}
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index a64c7f0f9f..80907c45d2 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -359,3 +359,4 @@ riscv_wgchecker_mmio_write(uint64_t base, uint64_t offset,
unsigned int size, ui
riscv_wgc_mem_blocked_read(uint64_t addr, unsigned size, uint32_t wid)
"wgChecker blocked read: offset 0x%" PRIx64 " size %u wid %" PRIu32
riscv_wgc_mem_blocked_write(uint64_t addr, uint64_t data, unsigned size,
uint32_t wid) "wgChecker blocked write: offset 0x%" PRIx64 " data 0x%" PRIx64 "
size %u wid %" PRIu32
riscv_wgc_translate(uint64_t addr, int flags, int wid, const char *res)
"wgChecker translate: addr 0x%016" PRIx64 " flags 0x%x wid %d: %s"
+riscv_wgc_iommu_notify_all(void) "wgChecker iommu: notifying UNMAP for all"
--
2.17.1
- Re: [RFC PATCH 01/16] accel/tcg: Store section pointer in CPUTLBEntryFull, (continued)
[RFC PATCH 02/16] accel/tcg: memory access from CPU will pass access_type to IOMMU, Jim Shu, 2024/06/12
[RFC PATCH 04/16] hw/misc: riscv_worldguard: Add RISC-V WorldGuard global config, Jim Shu, 2024/06/12
[RFC PATCH 05/16] target/riscv: Add CPU options of WorldGuard CPU extension, Jim Shu, 2024/06/12
[RFC PATCH 07/16] target/riscv: Add defines for WorldGuard CSRs, Jim Shu, 2024/06/12
[RFC PATCH 11/16] hw/misc: riscv_worldguard: Add API to enable WG extension of CPU, Jim Shu, 2024/06/12
[RFC PATCH 13/16] hw/misc: riscv_wgchecker: Implement wgchecker slot registers, Jim Shu, 2024/06/12
[RFC PATCH 15/16] hw/misc: riscv_wgchecker: Check the slot settings in translate,
Jim Shu <=
[RFC PATCH 16/16] hw/riscv: virt: Add WorldGuard support, Jim Shu, 2024/06/12
[RFC PATCH 08/16] target/riscv: Allow global WG config to set WG CPU callbacks, Jim Shu, 2024/06/12
[RFC PATCH 09/16] target/riscv: Implement WorldGuard CSRs, Jim Shu, 2024/06/12
[RFC PATCH 06/16] target/riscv: Add hard-coded CPU state of WG extension, Jim Shu, 2024/06/12
[RFC PATCH 10/16] target/riscv: Add WID to MemTxAttrs of CPU memory transactions, Jim Shu, 2024/06/12
[RFC PATCH 12/16] hw/misc: riscv_wgchecker: Implement RISC-V WorldGuard Checker, Jim Shu, 2024/06/12
[RFC PATCH 03/16] exec: Add RISC-V WorldGuard WID to MemTxAttrs, Jim Shu, 2024/06/12
[RFC PATCH 14/16] hw/misc: riscv_wgchecker: Implement correct block-access behavior, Jim Shu, 2024/06/12