From: Jan Beulich <jbeulich@suse.com>
To: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Cc: "Alistair Francis" <alistair.francis@wdc.com>,
"Bob Eshleman" <bobbyeshleman@gmail.com>,
"Connor Davis" <connojdavis@gmail.com>,
"Andrew Cooper" <andrew.cooper3@citrix.com>,
"Anthony PERARD" <anthony.perard@vates.tech>,
"Michal Orzel" <michal.orzel@amd.com>,
"Julien Grall" <julien@xen.org>,
"Roger Pau Monné" <roger.pau@citrix.com>,
"Stefano Stabellini" <sstabellini@kernel.org>,
xen-devel@lists.xenproject.org
Subject: Re: [PATCH v3 13/20] xen/riscv: Implement p2m_free_subtree() and related helpers
Date: Wed, 6 Aug 2025 17:55:07 +0200 [thread overview]
Message-ID: <98dc796e-bb14-435e-8c19-53e5de60cc43@suse.com> (raw)
In-Reply-To: <41845723a7b0e3efd09095d13e57aace6f7747ef.1753973161.git.oleksii.kurochko@gmail.com>
On 31.07.2025 17:58, Oleksii Kurochko wrote:
> --- a/xen/arch/riscv/include/asm/p2m.h
> +++ b/xen/arch/riscv/include/asm/p2m.h
> @@ -79,10 +79,20 @@ typedef enum {
> p2m_ext_storage, /* Following types'll be stored outsude PTE bits: */
> p2m_grant_map_rw, /* Read/write grant mapping */
> p2m_grant_map_ro, /* Read-only grant mapping */
> + p2m_map_foreign_rw, /* Read/write RAM pages from foreign domain */
> + p2m_map_foreign_ro, /* Read-only RAM pages from foreign domain */
> } p2m_type_t;
>
> #define p2m_mmio_direct p2m_mmio_direct_io
>
> +/*
> + * Bits 8 and 9 are reserved for use by supervisor software;
> + * the implementation shall ignore this field.
> + * We are going to use to save in these bits frequently used types to avoid
> + * get/set of a type from radix tree.
> + */
> +#define P2M_TYPE_PTE_BITS_MASK 0x300
> +
> /* We use bitmaps and mask to handle groups of types */
> #define p2m_to_mask(t_) BIT(t_, UL)
>
> @@ -93,10 +103,16 @@ typedef enum {
> #define P2M_GRANT_TYPES (p2m_to_mask(p2m_grant_map_rw) | \
> p2m_to_mask(p2m_grant_map_ro))
>
> + /* Foreign mappings types */
Nit: Why so far to the right?
> --- a/xen/arch/riscv/p2m.c
> +++ b/xen/arch/riscv/p2m.c
> @@ -197,6 +197,16 @@ static pte_t *p2m_get_root_pointer(struct p2m_domain *p2m, gfn_t gfn)
> return __map_domain_page(p2m->root + root_table_indx);
> }
>
> +static p2m_type_t p2m_get_type(const pte_t pte)
> +{
> + p2m_type_t type = MASK_EXTR(pte.pte, P2M_TYPE_PTE_BITS_MASK);
> +
> + if ( type == p2m_ext_storage )
> + panic("unimplemented\n");
That is, as per p2m.h additions you pretend to add support for foreign types
here, but then you don't?
> @@ -248,11 +258,136 @@ static int p2m_next_level(struct p2m_domain *p2m, bool alloc_tbl,
> return P2M_TABLE_MAP_NONE;
> }
>
> +static void p2m_put_foreign_page(struct page_info *pg)
> +{
> + /*
> + * It’s safe to call put_page() here because arch_flush_tlb_mask()
> + * will be invoked if the page is reallocated before the end of
> + * this loop, which will trigger a flush of the guest TLBs.
> + */
> + put_page(pg);
> +}
How can one know the comment is true? arch_flush_tlb_mask() still lives in
stubs.c, and hence what it is eventually going to do (something like Arm's
vs more like x86'es) is entirely unknown right now.
> +/* Put any references on the single 4K page referenced by mfn. */
> +static void p2m_put_4k_page(mfn_t mfn, p2m_type_t type)
> +{
> + /* TODO: Handle other p2m types */
> +
> + if ( p2m_is_foreign(type) )
> + {
> + ASSERT(mfn_valid(mfn));
> + p2m_put_foreign_page(mfn_to_page(mfn));
> + }
> +
> + /*
> + * Detect the xenheap page and mark the stored GFN as invalid.
> + * We don't free the underlying page until the guest requested to do so.
> + * So we only need to tell the page is not mapped anymore in the P2M by
> + * marking the stored GFN as invalid.
> + */
> + if ( p2m_is_ram(type) && is_xen_heap_mfn(mfn) )
> + page_set_xenheap_gfn(mfn_to_page(mfn), INVALID_GFN);
Isn't this for grants? p2m_is_ram() doesn't cover p2m_grant_map_*.
> +}
> +
> +/* Put any references on the superpage referenced by mfn. */
> +static void p2m_put_2m_superpage(mfn_t mfn, p2m_type_t type)
> +{
> + struct page_info *pg;
> + unsigned int i;
> +
> + ASSERT(mfn_valid(mfn));
> +
> + pg = mfn_to_page(mfn);
> +
> + for ( i = 0; i < XEN_PT_ENTRIES; i++, pg++ )
> + p2m_put_foreign_page(pg);
> +}
In p2m_put_4k_page() you check the type, whereas here you don't.
> +/* Put any references on the page referenced by pte. */
> +static void p2m_put_page(const pte_t pte, unsigned int level)
> +{
> + mfn_t mfn = pte_get_mfn(pte);
> + p2m_type_t p2m_type = p2m_get_type(pte);
> +
> + ASSERT(pte_is_valid(pte));
> +
> + /*
> + * TODO: Currently we don't handle level 2 super-page, Xen is not
> + * preemptible and therefore some work is needed to handle such
> + * superpages, for which at some point Xen might end up freeing memory
> + * and therefore for such a big mapping it could end up in a very long
> + * operation.
> + */
> + switch ( level )
> + {
> + case 1:
> + return p2m_put_2m_superpage(mfn, p2m_type);
> +
> + case 0:
> + return p2m_put_4k_page(mfn, p2m_type);
> + }
Yet despite the comment not even an assertion for level 2 and up?
> /* Free pte sub-tree behind an entry */
> static void p2m_free_subtree(struct p2m_domain *p2m,
> pte_t entry, unsigned int level)
> {
> - panic("%s: hasn't been implemented yet\n", __func__);
> + unsigned int i;
> + pte_t *table;
> + mfn_t mfn;
> + struct page_info *pg;
> +
> + /* Nothing to do if the entry is invalid. */
> + if ( !pte_is_valid(entry) )
> + return;
> +
> + if ( pte_is_superpage(entry, level) || (level == 0) )
Perhaps swap the two conditions around?
> + {
> +#ifdef CONFIG_IOREQ_SERVER
> + /*
> + * If this gets called then either the entry was replaced by an entry
> + * with a different base (valid case) or the shattering of a superpage
> + * has failed (error case).
> + * So, at worst, the spurious mapcache invalidation might be sent.
> + */
> + if ( p2m_is_ram(p2m_get_type(p2m, entry)) &&
> + domain_has_ioreq_server(p2m->domain) )
> + ioreq_request_mapcache_invalidate(p2m->domain);
> +#endif
> +
> + p2m_put_page(entry, level);
> +
> + return;
> + }
> +
> + table = map_domain_page(pte_get_mfn(entry));
> + for ( i = 0; i < XEN_PT_ENTRIES; i++ )
> + p2m_free_subtree(p2m, table[i], level - 1);
In p2m_put_page() you comment towards concerns for level >= 2; no similar
concerns for the resulting recursion here?
> + unmap_domain_page(table);
> +
> + /*
> + * Make sure all the references in the TLB have been removed before
> + * freing the intermediate page table.
> + * XXX: Should we defer the free of the page table to avoid the
> + * flush?
> + */
> + p2m_tlb_flush_sync(p2m);
> +
> + mfn = pte_get_mfn(entry);
> + ASSERT(mfn_valid(mfn));
> +
> + pg = mfn_to_page(mfn);
> +
> + page_list_del(pg, &p2m->pages);
> + p2m_free_page(p2m, pg);
Once again I wonder whether this code path was actually tested: p2m_free_page()
also invokes page_list_del(), and double deletions typically won't end very
well.
Jan
next prev parent reply other threads:[~2025-08-06 15:55 UTC|newest]
Thread overview: 84+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-31 15:57 [PATCH v3 00/20] xen/riscv: introduce p2m functionality Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 01/20] xen/riscv: implement sbi_remote_hfence_gvma() Oleksii Kurochko
2025-08-04 13:52 ` Jan Beulich
2025-08-05 14:45 ` Oleksii Kurochko
2025-08-05 15:01 ` Jan Beulich
2025-07-31 15:58 ` [PATCH v3 02/20] xen/riscv: introduce sbi_remote_hfence_gvma_vmid() Oleksii Kurochko
2025-08-04 13:55 ` Jan Beulich
2025-08-05 14:57 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 03/20] xen/riscv: introduce VMID allocation and manegement Oleksii Kurochko
2025-08-04 15:19 ` Jan Beulich
2025-08-06 11:33 ` Oleksii Kurochko
2025-08-06 12:05 ` Jan Beulich
2025-08-06 16:24 ` Oleksii Kurochko
2025-08-06 16:50 ` Demi Marie Obenour
2025-08-07 8:43 ` Oleksii Kurochko
2025-08-07 10:11 ` Jan Beulich
2025-08-07 14:45 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 04/20] xen/riscv: introduce things necessary for p2m initialization Oleksii Kurochko
2025-08-04 15:53 ` Jan Beulich
2025-08-06 11:43 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 05/20] xen/riscv: construct the P2M pages pool for guests Oleksii Kurochko
2025-08-04 15:58 ` Jan Beulich
2025-08-05 10:40 ` Jan Beulich
2025-08-06 12:01 ` Oleksii Kurochko
2025-08-06 12:07 ` Jan Beulich
2025-07-31 15:58 ` [PATCH v3 06/20] xen/riscv: add root page table allocation Oleksii Kurochko
2025-08-05 10:37 ` Jan Beulich
2025-08-07 12:00 ` Oleksii Kurochko
2025-08-07 15:30 ` Jan Beulich
2025-08-07 15:59 ` Oleksii Kurochko
2025-08-07 16:03 ` Jan Beulich
2025-08-05 10:43 ` Jan Beulich
2025-08-07 13:35 ` Oleksii Kurochko
2025-08-07 15:57 ` Jan Beulich
2025-08-08 9:14 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 07/20] xen/riscv: introduce pte_{set,get}_mfn() Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 08/20] xen/riscv: add new p2m types and helper macros for type classification Oleksii Kurochko
2025-08-04 14:16 ` Jan Beulich
2025-08-07 15:41 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 09/20] xen/dom0less: abstract Arm-specific p2m type name for device MMIO mappings Oleksii Kurochko
2025-08-04 14:11 ` Jan Beulich
2025-08-07 15:23 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 10/20] xen/riscv: introduce page_{get,set}_xenheap_gfn() Oleksii Kurochko
2025-08-05 14:11 ` Jan Beulich
2025-08-08 9:16 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 11/20] xen/riscv: implement function to map memory in guest p2m Oleksii Kurochko
2025-08-05 15:20 ` Jan Beulich
2025-08-08 13:46 ` Oleksii Kurochko
2025-08-11 7:28 ` Jan Beulich
2025-08-11 9:29 ` Oleksii Kurochko
2025-08-11 9:35 ` Jan Beulich
2025-07-31 15:58 ` [PATCH v3 12/20] xen/riscv: implement p2m_set_range() Oleksii Kurochko
2025-08-05 16:04 ` Jan Beulich
2025-08-15 9:52 ` Oleksii Kurochko
2025-08-15 12:50 ` Jan Beulich
2025-08-18 11:03 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 13/20] xen/riscv: Implement p2m_free_subtree() and related helpers Oleksii Kurochko
2025-08-06 15:55 ` Jan Beulich [this message]
2025-08-14 15:09 ` Oleksii Kurochko
2025-08-14 15:17 ` Jan Beulich
2025-08-18 8:22 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 14/20] xen/riscv: Implement p2m_pte_from_mfn() and support PBMT configuration Oleksii Kurochko
2025-08-11 11:36 ` Jan Beulich
2025-08-11 14:44 ` Oleksii Kurochko
2025-08-11 15:11 ` Jan Beulich
2025-07-31 15:58 ` [PATCH v3 15/20] xen/riscv: implement p2m_next_level() Oleksii Kurochko
2025-08-11 11:44 ` Jan Beulich
2025-07-31 15:58 ` [PATCH v3 16/20] xen/riscv: Implement superpage splitting for p2m mappings Oleksii Kurochko
2025-08-11 11:59 ` Jan Beulich
2025-08-11 15:19 ` Oleksii Kurochko
2025-08-11 15:47 ` Jan Beulich
2025-07-31 15:58 ` [PATCH v3 17/20] xen/riscv: implement put_page() Oleksii Kurochko
2025-08-11 12:43 ` Jan Beulich
2025-08-11 15:32 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 18/20] xen/riscv: implement mfn_valid() and page reference, ownership handling helpers Oleksii Kurochko
2025-08-11 12:50 ` Jan Beulich
2025-08-11 15:34 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 19/20] xen/riscv: add support of page lookup by GFN Oleksii Kurochko
2025-08-11 13:25 ` Jan Beulich
2025-08-12 11:42 ` Oleksii Kurochko
2025-08-22 8:39 ` Oleksii Kurochko
2025-07-31 15:58 ` [PATCH v3 20/20] xen/riscv: introduce metadata table to store P2M type Oleksii Kurochko
2025-08-11 15:44 ` Jan Beulich
2025-08-12 14:52 ` Oleksii Kurochko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=98dc796e-bb14-435e-8c19-53e5de60cc43@suse.com \
--to=jbeulich@suse.com \
--cc=alistair.francis@wdc.com \
--cc=andrew.cooper3@citrix.com \
--cc=anthony.perard@vates.tech \
--cc=bobbyeshleman@gmail.com \
--cc=connojdavis@gmail.com \
--cc=julien@xen.org \
--cc=michal.orzel@amd.com \
--cc=oleksii.kurochko@gmail.com \
--cc=roger.pau@citrix.com \
--cc=sstabellini@kernel.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.