|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v6 19/19] xen/riscv: introduce metadata table to store P2M type
On 12/11/25 10:39 AM, Jan Beulich wrote: On 10.12.2025 13:44, Oleksii Kurochko wrote:On 12/10/25 8:06 AM, Jan Beulich wrote:On 09.12.2025 18:09, Oleksii Kurochko wrote:On 12/9/25 2:47 PM, Jan Beulich wrote:On 24.11.2025 13:33, Oleksii Kurochko wrote: I am thinking if it won't be too intrusive, I think that I am okay to introduce that now. As to suggestions - hardly any of the fields in struct page_info for the page can be used when the page is a metadata one. Simply record the count there?
I suppose that|union u| could be used.
The only thing that confuses me is the shadow paging implementation on x86.
In|struct page_info|, it has the following:
/* Context-dependent fields follow... */
union {
/* Page is in use: ((count_info & PGC_count_mask) != 0). */
struct {
/* Type reference count and various PGT_xxx flags and fields. */
unsigned long type_info;
} inuse;
/* Page is in use as a shadow: count_info == 0. */
struct {
....
} sh;
/* Page is on a free list: ((count_info & PGC_count_mask) == 0). */
union {
So it seems that something in the shadow code must set|count_info| to zero for
shadow pages. But I cannot find where this happens. I would expect it to be done
in|shadow_alloc()|, when the page is taken from the free list. However, pages
from the free list donot have|count_info == 0| since|alloc_heap_pages()
|initializes|count_info|.
What guarantees that|count_info| will be zero for shadow tables?
Interestingly, in the shadow p2m page free code, there is logic that resets
|count_info| to zero:
{
struct domain *owner = page_get_owner(pg);
/* Should still have no owner and count zero. */
if ( owner || (pg->count_info & PGC_count_mask) )
{
printk(XENLOG_ERR
"d%d: Odd p2m page %"PRI_mfn" d=%d c=%lx t=%"PRtype_info"\n",
d->domain_id, mfn_x(page_to_mfn(pg)),
owner ? owner->domain_id : DOMID_INVALID,
pg->count_info, pg->u.inuse.type_info);
pg->count_info &= ~PGC_count_mask;
page_set_owner(pg, NULL);
}
...
And another question: since|u.sh.*| is updated, it effectively overwrites
|u.inuse.type_info|. But|u.inuse.type_info| is used by|free_domheap_pages()|,
which is called from|shadow_free()|:
void free_domheap_pages(struct page_info *pg, unsigned int order)
{
...
if ( pg[i].u.inuse.type_info & PGT_count_mask )
{
printk(XENLOG_ERR
"pg[%u] MFN %"PRI_mfn" c=%#lx o=%u v=%#lx t=%#x\n",
i, mfn_x(page_to_mfn(pg + i)),
pg[i].count_info, pg[i].v.free.order,
pg[i].u.free.val, pg[i].tlbflush_timestamp);
BUG();
}
...
Why is it acceptable that|u.inuse.type_info| will likely not be zero, since
|u.sh.*| modifies the same union field, at least during shadow page allocation?
Finally, as to "rather expensive": Scanning a 4k page to hold all zeroes can't be all that expensive? In any event that expensiveness needs weighing carefully against the risk of getting the counter maintenance wrong. It depends on how often|p2m_set_type()| will be called. In the worst case, it will require a loop that performs up to 512 iterations to scan a 4 KB page (512 * sizeof(struct mt_d) = 4096), which I think could be expensive if|p2m_set_type()| is invoked frequently. ~ Oleksii
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |