/* Alternate p2m paging */
bool p2m_altp2m_get_or_propagate(struct p2m_domain *ap2m, unsigned long gfn_l,
mfn_t *mfn, p2m_type_t *p2mt,
- p2m_access_t *p2ma, unsigned int page_order);
+ p2m_access_t *p2ma, unsigned int *page_order);
/* Make a specific alternate p2m valid */
int p2m_init_altp2m_by_id(struct domain *d, unsigned int idx);
*/
bool p2m_altp2m_get_or_propagate(struct p2m_domain *ap2m, unsigned long gfn_l,
mfn_t *mfn, p2m_type_t *p2mt,
- p2m_access_t *p2ma, unsigned int page_order)
+ p2m_access_t *p2ma, unsigned int *page_order)
{
p2m_type_t ap2mt;
p2m_access_t ap2ma;
+ unsigned int cur_order;
unsigned long mask;
gfn_t gfn;
mfn_t amfn;
*/
p2m_lock(ap2m);
- amfn = get_gfn_type_access(ap2m, gfn_l, &ap2mt, &ap2ma, 0, NULL);
+ amfn = get_gfn_type_access(ap2m, gfn_l, &ap2mt, &ap2ma, 0, &cur_order);
+
+ if ( cur_order > *page_order )
+ cur_order = *page_order;
if ( !mfn_eq(amfn, INVALID_MFN) )
{
*mfn = amfn;
*p2mt = ap2mt;
*p2ma = ap2ma;
+ *page_order = cur_order;
return false;
}
if ( mfn_eq(*mfn, INVALID_MFN) )
{
p2m_unlock(ap2m);
+ *page_order = cur_order;
return false;
}
* to the start of the superpage. NB that we repupose `amfn`
* here.
*/
- mask = ~((1UL << page_order) - 1);
+ mask = ~((1UL << cur_order) - 1);
amfn = _mfn(mfn_x(*mfn) & mask);
gfn = _gfn(gfn_l & mask);
- rc = p2m_set_entry(ap2m, gfn, amfn, page_order, *p2mt, *p2ma);
+ rc = p2m_set_entry(ap2m, gfn, amfn, cur_order, *p2mt, *p2ma);
p2m_unlock(ap2m);
if ( rc )