[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v7 7/8] xen/riscv: page table handling



On Tue, 2024-09-24 at 12:49 +0200, Jan Beulich wrote:
> On 13.09.2024 17:57, Oleksii Kurochko wrote:
> 
> 
> > @@ -68,6 +108,52 @@ static inline bool pte_is_valid(pte_t p)
> >      return p.pte & PTE_VALID;
> >  }
> >  
> > +/*
> > + * From the RISC-V spec:
> > + *   The V bit indicates whether the PTE is valid; if it is 0, all
> > other bits
> > + *   in the PTE are don’t-cares and may be used freely by
> > software.
> > + *
> > + *   If V=1 the encoding of PTE R/W/X bits could be find in Table
> > 4.5.
> 
> Please avoid using table numbers when not also specifying the precise
> doc
> version. Numbering changes, and it's table 5.5 in the doc I'm looking
> at.
> Use table names instead (also elsewhere of course).
> 
> > + *   Table 4.5 summarizes the encoding of the permission bits.
> > + *      X W R Meaning
> > + *      0 0 0 Pointer to next level of page table.
> > + *      0 0 1 Read-only page.
> > + *      0 1 0 Reserved for future use.
> > + *      0 1 1 Read-write page.
> > + *      1 0 0 Execute-only page.
> > + *      1 0 1 Read-execute page.
> > + *      1 1 0 Reserved for future use.
> > + *      1 1 1 Read-write-execute page.
> > + */
> > +inline bool pte_is_table(const pte_t p)
> 
> Missing static?
static is missed. I'll add it, thanks.

> 
> We normally omit "const" on function arguments; the frequent request
> to add
> missing const is on pointed-to types. If you still want to have it,
> ...
> 
> > +{
> > +    /*
> > +     * According to the spec if V=1 and W=1 then R also needs to
> > be 1 as
> > +     * R = 0 is reserved for future use ( look at the Table 4.5 )
> > so check
> > +     * in ASSERT that if (V==1 && W==1) then R isn't 0.
> > +     *
> > +     * PAGE_HYPERVISOR_RW contains PTE_VALID too.
> > +     */
> > +    ASSERT(((p.pte & PAGE_HYPERVISOR_RW) != (PTE_VALID |
> > PTE_WRITABLE)));
> > +
> > +    return ((p.pte & (PTE_VALID | PTE_ACCESS_MASK)) == PTE_VALID);
> > +}
> > +
> > +static inline bool pte_is_mapping(/*const*/ pte_t p)
> 
> ... I wonder why it's then commented out here.
I just experimented and missed to uncomment it. If "const" could be
omit for none pointed-to types then I prefer to drop const here and in
pte_is_table().

> > +#define XEN_TABLE_MAP_FAILED 0
> > +#define XEN_TABLE_SUPER_PAGE 1
> > +#define XEN_TABLE_NORMAL 2
> > +
> > +/*
> > + * Take the currently mapped table, find the corresponding entry,
> > + * and map the next table, if available.
> > + *
> > + * The alloc_tbl parameters indicates whether intermediate tables
> > should
> > + * be allocated when not present.
> > + *
> > + * Return values:
> > + *  XEN_TABLE_MAP_FAILED: Either alloc_only was set and the entry
> > + *  was empty, or allocating a new page failed.
> > + *  XEN_TABLE_NORMAL: next level or leaf mapped normally
> > + *  XEN_TABLE_SUPER_PAGE: The next entry points to a superpage.
> > + */
> > +static int pt_next_level(bool alloc_tbl, pte_t **table, unsigned
> > int offset)
> > +{
> > +    pte_t *entry;
> > +    mfn_t mfn;
> > +
> > +    entry = *table + offset;
> > +
> > +    if ( !pte_is_valid(*entry) )
> > +    {
> > +        if ( !alloc_tbl )
> > +            return XEN_TABLE_MAP_FAILED;
> > +
> > +        if ( create_table(entry) )
> > +            return XEN_TABLE_MAP_FAILED;
> 
> You're still losing the -ENOMEM here.
Agree, I will save the return value of create_table and return it.

> > +        rc = -EOPNOTSUPP;
> > +        goto out;
> > +    }
> > +
> > +    entry = table + offsets[level];
> > +
> > +    rc = -EINVAL;
> > +    if ( !pt_check_entry(*entry, mfn, flags) )
> > +        goto out;
> > +
> > +    /* We are removing the page */
> > +    if ( !(flags & PTE_VALID) )
> > +        /*
> > +         * there is also a check in pt_check_entry() which check
> > that
> > +         * mfn=INVALID_MFN
> > +         */
> 
> Nit: Comments are to start with a capital letter.
> 
> > +        pte.pte = 0;
> > +    else
> > +    {
> > +        /* We are inserting a mapping => Create new pte. */
> > +        if ( !mfn_eq(mfn, INVALID_MFN) )
> > +            pte = pte_from_mfn(mfn, PTE_VALID);
> > +        else /* We are updating the permission => Copy the current
> > pte. */
> > +        {
> > +            pte = *entry;
> > +            pte.pte &= ~(flags & PTE_ACCESS_MASK);
> 
> Why does "flags" need using here? Simply clearing all PTE_ACCESS_MASK
> bits
> will do, won't it? And only that will guarantee that flags which are
> to be
> clear will actually be cleared.
Agree, there is no any necessity for using "flags" here, they should be
dropped.

> 
> > +/*
> > + * If `mfn` equals `INVALID_MFN`, it indicates that the following
> > page table
> > + * update operation might be related to either:
> > + *   - populating the table (PTE_POPULATE will be set
> > additionaly),
> > + *   - destroying a mapping (PTE_VALID=0),
> > + *   - modifying an existing mapping (PTE_VALID=1).
> > + *
> > + * If `mfn` != INVALID_MFN and flags has PTE_VALID bit set then it
> > means that
> > + * inserting will be done.
> > + */
> > +static int pt_update(unsigned long virt,
> 
> Don't you have vaddr_t for variables/parameters like this one?
Yes, I have. I will update update this and re-check other places.

> 
> > +                     mfn_t mfn,
> > +                     unsigned long nr_mfns,
> > +                     unsigned int flags)
> > +{
> > +    int rc = 0;
> > +    unsigned long vfn = PFN_DOWN(virt);
> > +    unsigned long left = nr_mfns;
> > +
> > +    const mfn_t root = get_root_page();
> 
> Why the blank line between adjacent declarations?
No specific reason, just wanted to group variables by usage ( but then
it should be one blank after rc ).
But I will just drop the blank for consistency with other local
variable of other functions.

~ Oleksii




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.