|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v1 1/3] xen/riscv: implement software page table walking
On 20.01.2025 17:54, Oleksii Kurochko wrote:
> RISC-V doesn't have hardware feature to ask MMU to translate
> virtual address to physical address ( like Arm has, for example ),
> so software page table walking in implemented.
>
> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
> ---
> xen/arch/riscv/include/asm/mm.h | 2 ++
> xen/arch/riscv/pt.c | 56 +++++++++++++++++++++++++++++++++
> 2 files changed, 58 insertions(+)
>
> diff --git a/xen/arch/riscv/include/asm/mm.h b/xen/arch/riscv/include/asm/mm.h
> index 292aa48fc1..d46018c132 100644
> --- a/xen/arch/riscv/include/asm/mm.h
> +++ b/xen/arch/riscv/include/asm/mm.h
> @@ -15,6 +15,8 @@
>
> extern vaddr_t directmap_virt_start;
>
> +paddr_t pt_walk(vaddr_t va);
In the longer run, is returning just the PA really going to be sufficient?
If not, perhaps say a word on the limitation in the description.
> --- a/xen/arch/riscv/pt.c
> +++ b/xen/arch/riscv/pt.c
> @@ -274,6 +274,62 @@ static int pt_update_entry(mfn_t root, vaddr_t virt,
> return rc;
> }
>
> +paddr_t pt_walk(vaddr_t va)
> +{
> + const mfn_t root = get_root_page();
> + /*
> + * In pt_walk() only XEN_TALE_MAP_NONE and XEN_TABLE_SUPER_PAGE are
Nit: s/TALE/TABLE/ ?
> + * handled ( as they are only possible for page table walking ), so
Nit: Blanks again inside parentheses in a comment.
> + * initialize `ret` with "impossible" XEN_TABLE_MAP_NOMEM.
> + */
> + int ret = XEN_TABLE_MAP_NOMEM;
> + unsigned int level = HYP_PT_ROOT_LEVEL;
> + paddr_t pa = 0;
Seeing 0 as initializer here, just to double check: You do prevent MFN 0
to be handed to the page allocator, and you also don't use it "manually"
anywhere?
> + pte_t *table;
> +
> + DECLARE_OFFSETS(offsets, va);
> +
> + table = map_table(root);
> +
> + /*
> + * Find `pa` of an entry which corresponds to `va` by iterating for each
> + * page level and checking if the entry points to a next page table or
> + * to a page.
> + *
> + * Two cases are possible:
> + * - ret == XEN_TABLE_SUPER_PAGE means that the entry was find;
> + * (Despite of the name) XEN_TABLE_SUPER_PAGE covers 4k mapping too.
> + * - ret == XEN_TABLE_MAP_NONE means that requested `va` wasn't actually
> + * mapped.
> + */
> + while ( (ret != XEN_TABLE_MAP_NONE) && (ret != XEN_TABLE_SUPER_PAGE) )
> + {
> + /*
> + * This case shouldn't really occur as it will mean that for table
> + * level 0 a pointer to next page table has been written, but at
> + * level 0 it could be only a pointer to 4k page.
> + */
> + ASSERT(level <= HYP_PT_ROOT_LEVEL);
> +
> + ret = pt_next_level(false, &table, offsets[level]);
> + level--;
> + }
> +
> + if ( ret == XEN_TABLE_MAP_NONE )
> + dprintk(XENLOG_WARNING, "Is va(%#lx) really mapped?\n", va);
Even if it's a dprintk(), I'd recommend against adding such.
> + else if ( ret == XEN_TABLE_SUPER_PAGE )
> + pa = pte_to_paddr(*(table + offsets[level + 1]));
Missing "else if ( ret == XEN_TABLE_NORMAL )" (or maybe simply "else")?
> + /*
> + * There is no need for unmap_table() after each pt_next_level() call as
> + * pt_next_level() will do unmap_table() for the previous table before
> + * returning next level table.
> + */
> + unmap_table(table);
I don't think the comment is needed. You map once before the loop, so it's
natural that you unmap once after.
> + return pa;
Don't you want to OR in the low 12 bits of VA here (unless "pa" is still 0)?
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |