All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleksii Kurochko <oleksii.kurochko@gmail.com>
To: Jan Beulich <jbeulich@suse.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 v2 17/17] xen/riscv: add support of page lookup by GFN
Date: Mon, 21 Jul 2025 11:43:23 +0200	[thread overview]
Message-ID: <d4cc7511-da13-4f29-87f7-e799b533a4ac@gmail.com> (raw)
In-Reply-To: <c942d1ad-d3b5-42ed-a26d-5859e3efc93d@suse.com>

[-- Attachment #1: Type: text/plain, Size: 9627 bytes --]


On 7/2/25 1:44 PM, Jan Beulich wrote:
> On 10.06.2025 15:05, Oleksii Kurochko wrote:
>> Introduce helper functions for safely querying the P2M (physical-to-machine)
>> mapping:
>>   - add p2m_read_lock(), p2m_read_unlock(), and p2m_is_locked() for managing
>>     P2M lock state.
>>   - Implement p2m_get_entry() to retrieve mapping details for a given GFN,
>>     including MFN, page order, and validity.
>>   - Add p2m_lookup() to encapsulate read-locked MFN retrieval.
>>   - Introduce p2m_get_page_from_gfn() to convert a GFN into a page_info
>>     pointer, acquiring a reference to the page if valid.
>>
>> Implementations are based on Arm's functions with some minor modifications:
>> - p2m_get_entry():
>>    - Reverse traversal of page tables, as RISC-V uses the opposite order
>>      compared to Arm.
>>    - Removed the return of p2m_access_t from p2m_get_entry() since
>>      mem_access_settings is not introduced for RISC-V.
> Didn't I see uses of p2m_access in earlier patches? If you don't mean to have
> that, then please consistently {every,no}where.

Yes, it was used. I think it would be better just usage of p2m_access from earlier
patches.

>>    - Updated BUILD_BUG_ON() to check using the level 0 mask, which corresponds
>>      to Arm's THIRD_MASK.
>>    - Replaced open-coded bit shifts with the BIT() macro.
>>    - Other minor changes, such as using RISC-V-specific functions to validate
>>      P2M PTEs, and replacing Arm-specific GUEST_* macros with their RISC-V
>>      equivalents.
>> - p2m_get_page_from_gfn():
>>    - Removed p2m_is_foreign() and related logic, as this functionality is not
>>      implemented for RISC-V.
> Yet I expect you'll need this, sooner or later.

Then I'll add correspondent code in this patch.

>> --- a/xen/arch/riscv/p2m.c
>> +++ b/xen/arch/riscv/p2m.c
>> @@ -1055,3 +1055,134 @@ int guest_physmap_add_entry(struct domain *d,
>>   {
>>       return p2m_insert_mapping(d, gfn, (1 << page_order), mfn, t);
>>   }
>> +
>> +/*
>> + * Get the details of a given gfn.
>> + *
>> + * If the entry is present, the associated MFN will be returned and the
>> + * access and type filled up. The page_order will correspond to the
> You removed p2m_access_t * from the parameters; you need to also update
> the comment then accordingly.
>
>> + * order of the mapping in the page table (i.e it could be a superpage).
>> + *
>> + * If the entry is not present, INVALID_MFN will be returned and the
>> + * page_order will be set according to the order of the invalid range.
>> + *
>> + * valid will contain the value of bit[0] (e.g valid bit) of the
>> + * entry.
>> + */
>> +static mfn_t p2m_get_entry(struct p2m_domain *p2m, gfn_t gfn,
>> +                           p2m_type_t *t,
>> +                           unsigned int *page_order,
>> +                           bool *valid)
>> +{
>> +    paddr_t addr = gfn_to_gaddr(gfn);
>> +    unsigned int level = 0;
>> +    pte_t entry, *table;
>> +    int rc;
>> +    mfn_t mfn = INVALID_MFN;
>> +    p2m_type_t _t;
> Please no local variables with leading underscores. In x86 we commonly
> name such variables p2mt.
>
>> +    DECLARE_OFFSETS(offsets, addr);
> This is the sole use of "addr". Is such a local variable really worth having?

Not really, I'll drop it.

>> +    ASSERT(p2m_is_locked(p2m));
>> +    BUILD_BUG_ON(XEN_PT_LEVEL_MAP_MASK(0) != PAGE_MASK);
>> +
>> +    /* Allow t to be NULL */
>> +    t = t ?: &_t;
>> +
>> +    *t = p2m_invalid;
>> +
>> +    if ( valid )
>> +        *valid = false;
>> +
>> +    /* XXX: Check if the mapping is lower than the mapped gfn */
>> +
>> +    /* This gfn is higher than the highest the p2m map currently holds */
>> +    if ( gfn_x(gfn) > gfn_x(p2m->max_mapped_gfn) )
>> +    {
>> +        for ( level = P2M_ROOT_LEVEL; level ; level-- )
> Nit: Stray blank before the 2nd semicolon. (Again at least once below.)
>
>> +            if ( (gfn_x(gfn) & (XEN_PT_LEVEL_MASK(level) >> PAGE_SHIFT)) >
>> +                 gfn_x(p2m->max_mapped_gfn) )
>> +                break;
>> +
>> +        goto out;
>> +    }
>> +
>> +    table = p2m_get_root_pointer(p2m, gfn);
>> +
>> +    /*
>> +     * the table should always be non-NULL because the gfn is below
>> +     * p2m->max_mapped_gfn and the root table pages are always present.
>> +     */
>> +    if ( !table )
>> +    {
>> +        ASSERT_UNREACHABLE();
>> +        level = P2M_ROOT_LEVEL;
>> +        goto out;
>> +    }
>> +
>> +    for ( level = P2M_ROOT_LEVEL; level ; level-- )
>> +    {
>> +        rc = p2m_next_level(p2m, true, level, &table, offsets[level]);
>> +        if ( (rc == GUEST_TABLE_MAP_NONE) && (rc != GUEST_TABLE_MAP_NOMEM) )
> This condition looks odd. As written the rhs of the && is redundant.

And it is wrong. It should:
  if ( (rc == P2M_TABLE_MAP_NONE) || (rc == P2M_TABLE_MAP_NOMEM) )

>> +            goto out_unmap;
>> +        else if ( rc != GUEST_TABLE_NORMAL )
> As before, no real need for "else" in such cases.
>
>> +            break;
>> +    }
>> +
>> +    entry = table[offsets[level]];
>> +
>> +    if ( p2me_is_valid(p2m, entry) )
>> +    {
>> +        *t = p2m_type_radix_get(p2m, entry);
> If the incoming argument is NULL, the somewhat expensive radix tree lookup
> is unnecessary here.

Good point.

>> +        mfn = pte_get_mfn(entry);
>> +        /*
>> +         * The entry may point to a superpage. Find the MFN associated
>> +         * to the GFN.
>> +         */
>> +        mfn = mfn_add(mfn,
>> +                      gfn_x(gfn) & (BIT(XEN_PT_LEVEL_ORDER(level), UL) - 1));
>> +
>> +        if ( valid )
>> +            *valid = pte_is_valid(entry);
> Interesting. Why not the P2M counterpart of the function? Yes, the comment
> ahead of the function says so, but I don't see why the valid bit suddenly
> is relevant here (besides the P2M type).

This valid variable is expected to be used in the caller (something what Arm does here
https://gitlab.com/xen-project/xen/-/blob/staging/xen/arch/arm/p2m.c#L375) to check if
it is needed to do flush_page_to_ram(), so if the the valid bit in PTE was set to 0
then it means nothing should be flushed as entry wasn't used as it marked invalid.

>> +    }
>> +
>> +out_unmap:
>> +    unmap_domain_page(table);
>> +
>> +out:
> Nit: Style (bot labels).
>
>> +    if ( page_order )
>> +        *page_order = XEN_PT_LEVEL_ORDER(level);
>> +
>> +    return mfn;
>> +}
>> +
>> +static mfn_t p2m_lookup(struct domain *d, gfn_t gfn, p2m_type_t *t)
> pointer-to-const for the 1st arg? But again more likely struct p2m_domain *
> anyway?

|struct p2_domain| would be better, but I’m not really sure that a
pointer-to-const can be used here. I expect that, in that case,
|p2m_read_lock()| would also need to accept a pointer-to-const, and since it
calls|read_lock()| internally, that could be a problem because|read_lock() |accepts a|rwlock_t *l|.

>> +{
>> +    mfn_t mfn;
>> +    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>> +
>> +    p2m_read_lock(p2m);
>> +    mfn = p2m_get_entry(p2m, gfn, t, NULL, NULL);
>> +    p2m_read_unlock(p2m);
>> +
>> +    return mfn;
>> +}
>> +
>> +struct page_info *p2m_get_page_from_gfn(struct domain *d, gfn_t gfn,
> Same here - likely you mean struct p2m_domain * instead.
>
>> +                                        p2m_type_t *t)
>> +{
>> +    p2m_type_t p2mt = {0};
> Why a compound initializer for something that isn't a compound object?
> And why plain 0 for something that is an enumerated type?

Agree, it should be a compound initializer. I'll drop it.

>
>> +    struct page_info *page;
>> +
>> +    mfn_t mfn = p2m_lookup(d, gfn, &p2mt);
>> +
>> +    if ( t )
>> +        *t = p2mt;
> What's wrong with passing t directly to p2m_lookup()?

It was needed before when the code of p2m_get_page_from_gfn() looked like:
   struct page_info *p2m_get_page_from_gfn(struct domain *d, gfn_t gfn,
                                           p2m_type_t *t)
   {
       struct page_info *page;
       p2m_type_t p2mt;
       mfn_t mfn = p2m_lookup(d, gfn, &p2mt);
   
       if ( t )
           *t = p2mt;
   
       if ( !p2m_is_any_ram(p2mt) )
           return NULL;
So it was needed to make sure that p2m_is_any_ram(*t) doesn't try to dereference
a NULL pointer.

Even with the current one implementation the similar issue could be with if use
*t instead of p2mt:
   struct page_info *p2m_get_page_from_gfn(struct p2m_domain *p2m, gfn_t gfn,
                                           p2m_type_t *t)
   {
       ...
       if ( p2m_is_foreign(p2mt) )
       {
           struct domain *fdom = page_get_owner_and_reference(page);

And the second reason it is because of p2m_get_entry() (which is used inside
p2m_lookup()) could return for `t` a pointer to local variable:
   static mfn_t p2m_get_entry(struct p2m_domain *p2m, gfn_t gfn,
                              p2m_type_t *t,
                              unsigned int *page_order,
                              bool *valid)
   {
       ...
       p2m_type_t p2mt;
       ...
       /* Allow t to be NULL */
       t = t ?: &p2mt;
       ...

What looks wrong. I will remove this part of the code and pass
`t` directly to p2m_lookup().

And after p2m_lookup() call will just check if t argument is NULL then init
it with p2mt:
    struct page_info *p2m_get_page_from_gfn(struct p2m_domain *p2m, gfn_t gfn,
                                            p2m_type_t *t)
    {
        struct page_info *page;
        p2m_type_t p2mt = p2m_invalid;
        mfn_t mfn = p2m_lookup(p2m, gfn, t);
    
        if ( !mfn_valid(mfn) )
            return NULL;
    
        if ( !t )
            p2mt = *t;
    
        ...
    }

Thanks.

~ Oleksii

[-- Attachment #2: Type: text/html, Size: 12968 bytes --]

  reply	other threads:[~2025-07-21  9:43 UTC|newest]

Thread overview: 161+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-10 13:05 [PATCH v2 00/17] xen/riscv: introduce p2m functionality Oleksii Kurochko
2025-06-10 13:05 ` [PATCH v2 01/17] xen/riscv: implement sbi_remote_hfence_gvma() Oleksii Kurochko
2025-06-18 15:15   ` Jan Beulich
2025-06-23 14:31     ` Oleksii Kurochko
2025-06-23 14:39       ` Jan Beulich
2025-06-23 14:45         ` Oleksii Kurochko
2025-06-24 10:33     ` Oleksii Kurochko
2025-06-24 10:48       ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 02/17] xen/riscv: introduce sbi_remote_hfence_gvma_vmid() Oleksii Kurochko
2025-06-18 15:20   ` Jan Beulich
2025-06-23 14:38     ` Oleksii Kurochko
2025-06-10 13:05 ` [PATCH v2 03/17] xen/riscv: introduce guest domain's VMID allocation and manegement Oleksii Kurochko
2025-06-18 15:46   ` Jan Beulich
2025-06-24  9:46     ` Oleksii Kurochko
2025-06-24 10:44       ` Jan Beulich
2025-06-24 13:47         ` Oleksii Kurochko
2025-06-24 14:01           ` Jan Beulich
2025-06-24 15:32             ` Oleksii Kurochko
2025-06-26 10:05             ` Oleksii Kurochko
2025-06-26 10:41               ` Jan Beulich
2025-06-26 11:34                 ` Oleksii Kurochko
2025-06-26 11:43                   ` Juergen Gross
2025-06-26 12:05                     ` Oleksii Kurochko
2025-06-26 12:17                     ` Teddy Astie
2025-06-26 12:37                       ` Jan Beulich
2025-06-26 12:16                   ` Jan Beulich
2025-06-26 12:25                     ` Oleksii Kurochko
2025-06-10 13:05 ` [PATCH v2 04/17] xen/riscv: construct the P2M pages pool for guests Oleksii Kurochko
2025-06-18 15:53   ` Jan Beulich
2025-06-25 14:48     ` Oleksii Kurochko
2025-06-25 14:55       ` Jan Beulich
2025-07-01 13:04   ` Jan Beulich
2025-07-02 10:30     ` Oleksii Kurochko
2025-07-02 10:34       ` Jan Beulich
2025-07-02 11:17         ` Oleksii Kurochko
2025-07-02 11:48     ` Oleksii Kurochko
2025-07-02 11:56       ` Jan Beulich
2025-07-02 12:34         ` Oleksii Kurochko
2025-07-02 12:49           ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 05/17] xen/riscv: introduce things necessary for p2m initialization Oleksii Kurochko
2025-06-18 16:08   ` Jan Beulich
2025-06-25 15:31     ` Oleksii Kurochko
2025-06-25 15:53       ` Jan Beulich
2025-06-26  8:40         ` Oleksii Kurochko
2025-06-26 11:01           ` Jan Beulich
2025-06-26 11:55             ` Oleksii Kurochko
2025-06-10 13:05 ` [PATCH v2 06/17] xen/riscv: add root page table allocation Oleksii Kurochko
2025-06-30 15:22   ` Jan Beulich
2025-06-30 16:18     ` Oleksii Kurochko
2025-07-01  6:29       ` Jan Beulich
2025-07-01  9:44         ` Oleksii Kurochko
2025-07-01 10:27           ` Jan Beulich
2025-07-01 14:02             ` Oleksii Kurochko
2025-07-01 14:28               ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 07/17] xen/riscv: introduce pte_{set,get}_mfn() Oleksii Kurochko
2025-06-26 14:57   ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 08/17] xen/riscv: add new p2m types and helper macros for type classification Oleksii Kurochko
2025-06-26 14:59   ` Jan Beulich
2025-06-30 14:33     ` Oleksii Kurochko
2025-06-30 14:38       ` Oleksii Kurochko
2025-06-30 14:45         ` Jan Beulich
2025-06-30 15:27           ` Oleksii Kurochko
2025-06-30 15:50             ` Jan Beulich
2025-07-02 10:13               ` Oleksii Kurochko
2025-07-02 10:36                 ` Jan Beulich
2025-06-30 14:42       ` Jan Beulich
2025-06-30 15:13         ` Oleksii Kurochko
2025-06-30 15:27           ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 09/17] xen/riscv: introduce page_set_xenheap_gfn() Oleksii Kurochko
2025-06-30 15:48   ` Jan Beulich
2025-07-02 15:59     ` Oleksii Kurochko
2025-07-03  5:59       ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 10/17] xen/riscv: implement guest_physmap_add_entry() for mapping GFNs to MFNs Oleksii Kurochko
2025-06-30 15:59   ` Jan Beulich
2025-07-03 11:02     ` Oleksii Kurochko
2025-07-03 11:33       ` Jan Beulich
2025-07-03 11:54         ` Oleksii Kurochko
2025-07-03 13:09           ` Jan Beulich
2025-07-03 13:28             ` Oleksii Kurochko
2025-07-03 13:34               ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 11/17] xen/riscv: implement p2m_set_entry() and __p2m_set_entry() Oleksii Kurochko
2025-07-01 13:49   ` Jan Beulich
2025-07-04 15:01     ` Oleksii Kurochko
2025-07-07  7:20       ` Jan Beulich
2025-07-07 11:46         ` Oleksii Kurochko
2025-07-07 12:53           ` Jan Beulich
2025-07-07 15:00             ` Oleksii Kurochko
2025-07-07 15:15               ` Jan Beulich
2025-07-07 16:10                 ` Oleksii Kurochko
2025-07-08  7:10                   ` Jan Beulich
2025-07-08  9:01                     ` Oleksii Kurochko
2025-07-08 10:37                       ` Oleksii Kurochko
2025-07-08 12:45                         ` Jan Beulich
2025-07-08 15:42                           ` Oleksii Kurochko
2025-07-08 16:04                             ` Jan Beulich
2025-07-09  8:24                               ` Oleksii Kurochko
2025-07-09  8:41                                 ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 12/17] xen/riscv: Implement p2m_free_entry() and related helpers Oleksii Kurochko
2025-07-01 14:23   ` Jan Beulich
2025-07-11 15:56     ` Oleksii Kurochko
2025-07-14  7:15       ` Jan Beulich
2025-07-14 16:01         ` Oleksii Kurochko
2025-07-14 16:17           ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 13/17] xen/riscv: Implement p2m_entry_from_mfn() and support PBMT configuration Oleksii Kurochko
2025-07-01 15:08   ` Jan Beulich
2025-07-15 14:47     ` Oleksii Kurochko
2025-07-16 11:31       ` Jan Beulich
2025-07-16 16:07         ` Oleksii Kurochko
2025-07-16 16:18           ` Jan Beulich
2025-07-17  8:56             ` Oleksii Kurochko
2025-07-17 10:25               ` Jan Beulich
2025-07-18  9:52                 ` Oleksii Kurochko
2025-07-21 12:18                   ` Jan Beulich
2025-07-22 10:41                     ` Oleksii Kurochko
2025-07-22 11:34                       ` Oleksii Kurochko
2025-07-22 12:00                         ` Jan Beulich
2025-07-22 14:25                           ` Oleksii Kurochko
2025-07-22 14:35                             ` Jan Beulich
2025-07-22 16:07                               ` Oleksii Kurochko
2025-07-23  9:46                                 ` Jan Beulich
2025-07-28  8:52                                   ` Oleksii Kurochko
2025-07-28  9:09                                     ` Jan Beulich
2025-07-28 11:37                                       ` Oleksii Kurochko
2025-07-28 11:49                                         ` Jan Beulich
2025-07-22 11:54                       ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 14/17] xen/riscv: implement p2m_next_level() Oleksii Kurochko
2025-07-02  8:35   ` Jan Beulich
2025-07-16 11:32     ` Oleksii Kurochko
2025-07-16 11:43       ` Jan Beulich
2025-07-16 15:53         ` Oleksii Kurochko
2025-07-16 16:12           ` Jan Beulich
2025-07-17  9:42             ` Oleksii Kurochko
2025-07-17 10:37               ` Jan Beulich
2025-07-18 11:19                 ` Oleksii Kurochko
2025-07-21 13:14                   ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 15/17] xen/riscv: Implement superpage splitting for p2m mappings Oleksii Kurochko
2025-07-02  9:25   ` Jan Beulich
2025-07-17 16:37     ` Oleksii Kurochko
2025-07-21 13:34       ` Jan Beulich
2025-07-22 14:57         ` Oleksii Kurochko
2025-07-22 16:02           ` Jan Beulich
2025-07-23 19:51             ` Oleksii Kurochko
2025-07-24  7:58               ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 16/17] xen/riscv: implement mfn_valid() and page reference, ownership handling helpers Oleksii Kurochko
2025-07-02 10:09   ` Jan Beulich
2025-07-02 10:28     ` Jan Beulich
2025-07-18 14:37       ` Oleksii Kurochko
2025-07-21 13:39         ` Jan Beulich
2025-07-22 12:03           ` Oleksii Kurochko
2025-07-22 12:05             ` Jan Beulich
2025-07-29 13:47               ` Oleksii Kurochko
2025-07-29 14:48                 ` Jan Beulich
2025-07-02 12:52     ` Orzel, Michal
2025-07-18 14:49     ` Oleksii Kurochko
2025-07-21 13:42       ` Jan Beulich
2025-07-22 13:38         ` Oleksii Kurochko
2025-07-21 13:53       ` Jan Beulich
2025-06-10 13:05 ` [PATCH v2 17/17] xen/riscv: add support of page lookup by GFN Oleksii Kurochko
2025-07-02 11:44   ` Jan Beulich
2025-07-21  9:43     ` Oleksii Kurochko [this message]
2025-07-21 14:06       ` Jan Beulich

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=d4cc7511-da13-4f29-87f7-e799b533a4ac@gmail.com \
    --to=oleksii.kurochko@gmail.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=jbeulich@suse.com \
    --cc=julien@xen.org \
    --cc=michal.orzel@amd.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.