[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH for-4.19? 2/2] xen/x86: remove foreign mappings from the p2m on teardown
On 30.04.2024 18:58, Roger Pau Monne wrote: > @@ -2695,6 +2691,70 @@ int p2m_set_altp2m_view_visibility(struct domain *d, > unsigned int altp2m_idx, > return rc; > } > > +/* > + * Remove foreign mappings from the p2m, as that drops the page reference > taken > + * when mapped. > + */ > +int relinquish_p2m_mapping(struct domain *d) > +{ > + struct p2m_domain *p2m = p2m_get_hostp2m(d); Are there any guarantees made anywhere that altp2m-s and nested P2Ms can't hold foreign mappings? p2m_entry_modify() certainly treats them all the same. > + unsigned long gfn = gfn_x(p2m->max_gfn); > + int rc = 0; > + > + if ( !paging_mode_translate(d) ) > + return 0; > + > + BUG_ON(!d->is_dying); > + > + p2m_lock(p2m); > + > + /* Iterate over the whole p2m on debug builds to ensure correctness. */ > + while ( gfn && (IS_ENABLED(CONFIG_DEBUG) || p2m->nr_foreign) ) > + { > + unsigned int order; > + p2m_type_t t; > + p2m_access_t a; > + > + _get_gfn_type_access(p2m, _gfn(gfn - 1), &t, &a, 0, &order, 0); > + ASSERT(IS_ALIGNED(gfn, 1u << order)); This heavily relies on the sole place where max_gfn is updated being indeed sufficient. > + gfn -= 1 << order; Please be consistent with the kind of 1 you shift left. Perhaps anyway both better as 1UL. > + if ( t == p2m_map_foreign ) > + { > + ASSERT(p2m->nr_foreign); > + ASSERT(order == 0); > + /* > + * Foreign mappings can only be of order 0, hence there's no need > + * to align the gfn to the entry order. Otherwise we would need > to > + * adjust gfn to point to the start of the page if order > 0. > + */ I'm a little irritated by this comment. Ahead of the enclosing if() you already rely on (and assert) GFN being suitably aligned. > + rc = p2m_set_entry(p2m, _gfn(gfn), INVALID_MFN, order, > p2m_invalid, > + p2m->default_access); > + if ( rc ) > + { > + printk(XENLOG_ERR > + "%pd: failed to unmap foreign page %" PRI_gfn " order > %u error %d\n", > + d, gfn, order, rc); > + ASSERT_UNREACHABLE(); > + break; > + } Together with the updating of ->max_gfn further down, for a release build this means: A single attempt to clean up the domain would fail when such a set-entry fails. However, another attempt to clean up despite the earlier error would then not retry for the failed GFN, but continue one below. That's unexpected: I'd either see such a domain remain as a zombie forever, or a best effort continuation of all cleanup right away. > + } > + > + if ( !(gfn & 0xfff) && hypercall_preempt_check() ) By going from gfn's low bits you may check way more often than necessary when encountering large pages. Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |