|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 3/6] xen/riscv: make Svpbmt no longer a required extension
Without the Svpbmt extension, memory attributes (such as cacheability and
ordering) are strictly tied to physical address ranges and enforced by the
hardware's Physical Memory Attributes (PMA) checker.
In this configuration, supervisor software relies on the platform's memory
map:
- peripheral device registers (MMIO) are physically mapped into
hardware-defined I/O regions (which are implicitly non-cacheable and
strongly-ordered)
- regular RAM is mapped as cacheable main memory.
S-mode paging can safely map these physical ranges without specifying
page-based memory types in the PTEs, as the hardware MMU and PMA pipeline
will correctly bypass caches for MMIO accesses and use caches for RAM
accesses, based on the target physical address.
Furthermore, on platforms that either feature fully hardware-coherent DMA
or don't expose non-coherent DMA agents to the OS, page-level programmatic
cache control via Svpbmt is not required, making it safe to boot and run
when Svpbmt is absent.
Drop Svpbmt from required_extensions. Introduce svpbmt_enabled, a
__ro_after_init flag computed once in init_csr_masks() from ISA
availability and the henvcfg.PBMTE bit. Xen cannot read menvcfg.PBMTE
directly, since menvcfg is M-mode-only and unreadable from HS-mode, but the
spec guarantees henvcfg.PBMTE reads as zero whenever menvcfg.PBMTE is zero,
so checking henvcfg.PBMTE alone is sufficient. Use svpbmt_enabled in
pte_pbmt_nocache()/pte_pbmt_io(), two new inline helpers that mask the PBMT
encoding down to 0 when Svpbmt is unavailable.
Also switch vcpu_csr_init() branch to determine if Svpbmt was enabled to
svpbmt_enabled as it does the same logic.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Baptiste Le Duc <baptiste.le-duc@xxxxxxxxxx>
---
Changes since v1:
- Replace the pte_pbmt() macro, which re-checked
riscv_isa_extension_available() on every call, with a svpbmt_enabled
flag cached once in init_csr_masks().
- Add pte_pbmt_nocache()/pte_pbmt_io() inline helpers instead, used by
PAGE_HYPERVISOR_NOCACHE/WC and p2m_pte_from_mfn().
- Switch vcpu_csr_init() to the same cached svpbmt_enabled flag instead
of re-deriving Svpbmt availability itself.
---
xen/arch/riscv/cpufeature.c | 1 -
xen/arch/riscv/domain.c | 10 ++++++++--
xen/arch/riscv/include/asm/page.h | 22 +++++++++++++++++++---
xen/arch/riscv/p2m.c | 2 +-
4 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/xen/arch/riscv/cpufeature.c b/xen/arch/riscv/cpufeature.c
index 19454544a7..986a6dec78 100644
--- a/xen/arch/riscv/cpufeature.c
+++ b/xen/arch/riscv/cpufeature.c
@@ -158,7 +158,6 @@ static const struct riscv_isa_ext_data __initconst
required_extensions[] = {
RISCV_ISA_EXT_DATA(zifencei),
RISCV_ISA_EXT_DATA(zihintpause),
RISCV_ISA_EXT_DATA(zbb),
- RISCV_ISA_EXT_DATA(svpbmt),
};
static bool __init is_lowercase_extension_name(const char *str)
diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c
index 2819ff4e7c..f6f20824e3 100644
--- a/xen/arch/riscv/domain.c
+++ b/xen/arch/riscv/domain.c
@@ -47,6 +47,8 @@ static struct csr_masks __ro_after_init csr_masks;
#define HENVCFG_VALID_MASK 0xe0000003000000ffUL
#define HSTATEEN0_VALID_MASK 0xde00000000000007UL
+bool __ro_after_init svpbmt_enabled;
+
void __init init_csr_masks(void)
{
/*
@@ -79,6 +81,10 @@ void __init init_csr_masks(void)
INIT_RO_ONE_MASK(HSTATEEN0, hstateen0);
}
+ svpbmt_enabled = (riscv_isa_extension_available(NULL,
+ RISCV_ISA_EXT_svpbmt)) && (ENVCFG_PBMTE &
+ csr_masks.henvcfg);
+
#undef INIT_CSR_MASK
#undef INIT_RO_ONE_MASK
}
@@ -97,8 +103,8 @@ static void vcpu_csr_init(struct vcpu *v)
*/
v->arch.hcounteren = HCOUNTEREN_TM;
- if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_svpbmt) )
- v->arch.henvcfg = ENVCFG_PBMTE & csr_masks.henvcfg;
+ if ( svpbmt_enabled )
+ v->arch.henvcfg = ENVCFG_PBMTE;
if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_smstateen) )
{
diff --git a/xen/arch/riscv/include/asm/page.h
b/xen/arch/riscv/include/asm/page.h
index 1977634efc..a7d087ff52 100644
--- a/xen/arch/riscv/include/asm/page.h
+++ b/xen/arch/riscv/include/asm/page.h
@@ -11,6 +11,7 @@
#include <xen/types.h>
#include <asm/atomic.h>
+#include <asm/cpufeature.h>
#include <asm/page-bits.h>
#define VPN_MASK (PAGETABLE_ENTRIES - 1UL)
@@ -42,7 +43,21 @@
* 01 - NC Non-cacheable, idempotent, weakly-ordered Main Memory
* 10 - IO Non-cacheable, non-idempotent, strongly-ordered I/O memory
* 11 - Rsvd Reserved for future standard use
+ *
+ * These bits are only meaningful when Svpbmt is enabled. Otherwise they must
+ * stay 0 (PMA).
*/
+extern bool svpbmt_enabled;
+static inline unsigned long pte_pbmt_nocache(void)
+{
+ return svpbmt_enabled ? BIT(61, UL) : 0;
+}
+
+static inline unsigned long pte_pbmt_io(void)
+{
+ return svpbmt_enabled ? BIT(62, UL) : 0;
+}
+
#define PTE_PBMT_NOCACHE BIT(61, UL)
#define PTE_PBMT_IO BIT(62, UL)
@@ -53,6 +68,7 @@
#define PAGE_HYPERVISOR_RX (PTE_VALID | PTE_READABLE | PTE_EXECUTABLE
| PTE_ACCESSED)
#define PAGE_HYPERVISOR PAGE_HYPERVISOR_RW
+
/*
* PAGE_HYPERVISOR_NOCACHE is used for ioremap().
*
@@ -60,8 +76,8 @@
* is that IO is non-idempotent and strongly ordered, which makes it a good
* candidate for mapping IOMEM.
*/
-#define PAGE_HYPERVISOR_NOCACHE (PAGE_HYPERVISOR_RW | PTE_PBMT_IO)
-#define PAGE_HYPERVISOR_WC (PAGE_HYPERVISOR_RW | PTE_PBMT_NOCACHE)
+#define PAGE_HYPERVISOR_NOCACHE (PAGE_HYPERVISOR_RW | pte_pbmt_io())
+#define PAGE_HYPERVISOR_WC (PAGE_HYPERVISOR_RW | pte_pbmt_nocache())
/*
* The PTE format does not contain the following bits within itself;
@@ -82,7 +98,7 @@ enum pbmt_type {
#define PTE_ACCESS_MASK (PTE_READABLE | PTE_WRITABLE | PTE_EXECUTABLE)
-#define PTE_PBMT_MASK (PTE_PBMT_NOCACHE | PTE_PBMT_IO)
+#define PTE_PBMT_MASK (BIT(61, UL) | BIT(62, UL))
/* Calculate the offsets into the pagetables for a given VA */
#define pt_linear_offset(lvl, va) ((va) >> XEN_PT_LEVEL_SHIFT(lvl))
diff --git a/xen/arch/riscv/p2m.c b/xen/arch/riscv/p2m.c
index 22ad4a2aee..15cbc92b76 100644
--- a/xen/arch/riscv/p2m.c
+++ b/xen/arch/riscv/p2m.c
@@ -658,7 +658,7 @@ static pte_t p2m_pte_from_mfn(mfn_t mfn, p2m_type_t t,
switch ( t )
{
case p2m_mmio_direct_io:
- e.pte |= PTE_PBMT_IO;
+ e.pte |= pte_pbmt_io();
break;
default:
--
2.55.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |