[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 13/17] xen/riscv: Implement p2m_entry_from_mfn() and support PBMT configuration
This patch adds the initial logic for constructing PTEs from MFNs in the RISC-V p2m subsystem. It includes: - Implementation of p2m_entry_from_mfn(): Generates a valid PTE using the given MFN, p2m_type_t, and p2m_access_t, including permission encoding and PBMT attribute setup. - New helper p2m_set_permission(): Encodes access rights (r, w, x) into the PTE based on both p2m type and access permissions. - p2m_type_radix_set(): Stores the p2m type in a radix tree keyed by the PTE for later retrieval. PBMT type encoding support: - Introduces an enum pbmt_type_t to represent the PBMT field values. - Maps types like p2m_mmio_direct_dev to pbmt_io, others default to pbmt_pma. Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx> --- Changes in V2: - New patch. It was a part of a big patch "xen/riscv: implement p2m mapping functionality" which was splitted to smaller. --- xen/arch/riscv/include/asm/page.h | 8 +++ xen/arch/riscv/p2m.c | 103 ++++++++++++++++++++++++++++-- 2 files changed, 107 insertions(+), 4 deletions(-) diff --git a/xen/arch/riscv/include/asm/page.h b/xen/arch/riscv/include/asm/page.h index c67b9578c9..1d1054fa5c 100644 --- a/xen/arch/riscv/include/asm/page.h +++ b/xen/arch/riscv/include/asm/page.h @@ -76,6 +76,14 @@ #define PTE_SMALL BIT(10, UL) #define PTE_POPULATE BIT(11, UL) +enum pbmt_type_t { + pbmt_pma, + pbmt_nc, + pbmt_io, + pbmt_rsvd, + pbmt_max, +}; + #define PTE_ACCESS_MASK (PTE_READABLE | PTE_WRITABLE | PTE_EXECUTABLE) #define PTE_PBMT_MASK (PTE_PBMT_NOCACHE | PTE_PBMT_IO) diff --git a/xen/arch/riscv/p2m.c b/xen/arch/riscv/p2m.c index 6b11e87b22..cba04acf38 100644 --- a/xen/arch/riscv/p2m.c +++ b/xen/arch/riscv/p2m.c @@ -345,6 +345,26 @@ static pte_t *p2m_get_root_pointer(struct p2m_domain *p2m, gfn_t gfn) return __map_domain_page(p2m->root + root_table_indx); } +static int p2m_type_radix_set(struct p2m_domain *p2m, pte_t pte, p2m_type_t t) +{ + int rc; + gfn_t gfn = mfn_to_gfn(p2m->domain, mfn_from_pte(pte)); + + rc = radix_tree_insert(&p2m->p2m_type, gfn_x(gfn), + radix_tree_int_to_ptr(t)); + if ( rc == -EEXIST ) + { + /* If a setting already exists, change it to the new one */ + radix_tree_replace_slot( + radix_tree_lookup_slot( + &p2m->p2m_type, gfn_x(gfn)), + radix_tree_int_to_ptr(t)); + rc = 0; + } + + return rc; +} + static p2m_type_t p2m_type_radix_get(struct p2m_domain *p2m, pte_t pte) { void *ptr; @@ -389,12 +409,87 @@ static inline void p2m_remove_pte(pte_t *p, bool clean_pte) p2m_write_pte(p, pte, clean_pte); } -static pte_t p2m_entry_from_mfn(struct p2m_domain *p2m, mfn_t mfn, - p2m_type_t t, p2m_access_t a) +static void p2m_set_permission(pte_t *e, p2m_type_t t, p2m_access_t a) { - panic("%s: hasn't been implemented yet\n", __func__); + /* First apply type permissions */ + switch ( t ) + { + case p2m_ram_rw: + e->pte |= PTE_ACCESS_MASK; + break; + + case p2m_mmio_direct_dev: + e->pte |= (PTE_READABLE | PTE_WRITABLE); + e->pte &= ~PTE_EXECUTABLE; + break; + + case p2m_invalid: + e->pte &= ~PTE_ACCESS_MASK; + break; + + default: + BUG(); + break; + } + + /* Then restrict with access permissions */ + switch ( a ) + { + case p2m_access_rwx: + break; + case p2m_access_wx: + e->pte &= ~PTE_READABLE; + break; + case p2m_access_rw: + e->pte &= ~PTE_EXECUTABLE; + break; + case p2m_access_w: + e->pte &= ~(PTE_READABLE | PTE_EXECUTABLE); + e->pte &= ~PTE_EXECUTABLE; + break; + case p2m_access_rx: + case p2m_access_rx2rw: + e->pte &= ~PTE_WRITABLE; + break; + case p2m_access_x: + e->pte &= ~(PTE_READABLE | PTE_WRITABLE); + break; + case p2m_access_r: + e->pte &= ~(PTE_WRITABLE | PTE_EXECUTABLE); + break; + case p2m_access_n: + case p2m_access_n2rwx: + e->pte &= ~PTE_ACCESS_MASK; + break; + default: + BUG(); + break; + } +} + +static pte_t p2m_entry_from_mfn(struct p2m_domain *p2m, mfn_t mfn, p2m_type_t t, p2m_access_t a) +{ + pte_t e = (pte_t) { 1 }; + + switch ( t ) + { + case p2m_mmio_direct_dev: + e.pte |= PTE_PBMT_IO; + break; + + default: + break; + } + + p2m_set_permission(&e, t, a); + + ASSERT(!(mfn_to_maddr(mfn) & ~PADDR_MASK)); + + pte_set_mfn(&e, mfn); + + BUG_ON(p2m_type_radix_set(p2m, e, t)); - return (pte_t) { .pte = 0 }; + return e; } #define GUEST_TABLE_MAP_NONE 0 -- 2.49.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |