[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 07/18] IOMMU/x86: perform PV Dom0 mappings in batches
On 10.12.2021 10:36, Roger Pau Monné wrote: > On Fri, Dec 03, 2021 at 01:38:48PM +0100, Jan Beulich wrote: >> On 02.12.2021 15:10, Roger Pau Monné wrote: >>> On Fri, Sep 24, 2021 at 11:47:41AM +0200, Jan Beulich wrote: >>>> @@ -720,6 +795,17 @@ int __init dom0_construct_pv(struct doma >>>> /* Pages that are part of page tables must be read only. */ >>>> mark_pv_pt_pages_rdonly(d, l4start, vpt_start, nr_pt_pages); >>>> >>>> + /* >>>> + * This needs to come after all potentially excess >>>> + * get_page_and_type(..., PGT_writable_page) invocations; see the >>>> loop a >>>> + * few lines further up, where the effect of calling that function in >>>> an >>>> + * earlier loop iteration may get overwritten by a later one. >>>> + */ >>>> + if ( need_iommu_pt_sync(d) && >>>> + iommu_unmap(d, _dfn(PFN_DOWN(mpt_alloc) - nr_pt_pages), >>>> nr_pt_pages, >>>> + &flush_flags) ) >>>> + BUG(); >>> >>> Wouldn't such unmap better happen as part of changing the types of the >>> pages that become part of the guest page tables? >> >> Not sure - it's a single call here, but would be a call per page when >> e.g. moved into mark_pv_pt_pages_rdonly(). > > I see. So this would result in multiple calls when moved, plus all the > involved page shattering and aggregation logic. Overall it would be > less error prone, as the iommu unmap would happen next to the type > change, but I'm not going to insist if you think it's not worth it. > The page table structure pages shouldn't be that many anyway? Typically it wouldn't be that many, true. I'm not sure about "less error prone", though: We'd have more problems if the range unmapped here wasn't properly representing the set of page tables used. >>>> @@ -840,22 +928,41 @@ int __init dom0_construct_pv(struct doma >>>> #endif >>>> while ( pfn < nr_pages ) >>>> { >>>> - if ( (page = alloc_chunk(d, nr_pages - domain_tot_pages(d))) == >>>> NULL ) >>>> + count = domain_tot_pages(d); >>>> + if ( (page = alloc_chunk(d, nr_pages - count)) == NULL ) >>>> panic("Not enough RAM for DOM0 reservation\n"); >>>> + mfn = mfn_x(page_to_mfn(page)); >>>> + >>>> + if ( need_iommu_pt_sync(d) ) >>>> + { >>>> + rc = iommu_map(d, _dfn(mfn), _mfn(mfn), domain_tot_pages(d) - >>>> count, >>>> + IOMMUF_readable | IOMMUF_writable, >>>> &flush_flags); >>>> + if ( rc ) >>>> + printk(XENLOG_ERR >>>> + "pre-mapping MFN %lx (PFN %lx) into IOMMU failed: >>>> %d\n", >>>> + mfn, pfn, rc); >>>> + } >>>> + >>>> while ( pfn < domain_tot_pages(d) ) >>>> { >>>> - mfn = mfn_x(page_to_mfn(page)); >>>> + if ( !rc ) >>>> + make_pages_writable(page, 1); >>> >>> There's quite a lot of repetition of the pattern: allocate, iommu_map, >>> set as writable. Would it be possible to abstract this into some >>> kind of helper? >>> >>> I've realized some of the allocations use alloc_chunk while others use >>> alloc_domheap_pages, so it might require some work. >> >> Right, I'd leave the allocation part aside for the moment. I had actually >> considered to fold iommu_map() and make_pages_writable() into a common >> helper (or really rename make_pages_writable() and fold iommu_map() into >> there). What I lacked was a reasonable, not overly long name for such a >> function. > > I'm not overly good at naming, but I think we need to somehow find a > way to place those together into a single helper. > > I would be fine with naming this iommu_memory_{setup,add} or some > such. Marking the pages as writable is a result (or a requirement > might be a better way to express it?) of adding them to the IOMMU. > Would you be OK with one of those names? I'll use the suggestion as a basis and see how it ends up looking / feeling. >>>> @@ -372,16 +372,30 @@ void __hwdom_init arch_iommu_hwdom_init( >>>> perms & IOMMUF_writable ? >>>> p2m_access_rw >>>> : >>>> p2m_access_r, >>>> 0); >>>> + else if ( pfn != start + count || perms != start_perms ) >>>> + { >>>> + commit: >>>> + rc = iommu_map(d, _dfn(start), _mfn(start), count, >>>> + start_perms, &flush_flags); >>>> + SWAP(start, pfn); >>>> + start_perms = perms; >>>> + count = 1; >>>> + } >>>> else >>>> - rc = iommu_map(d, _dfn(pfn), _mfn(pfn), 1ul << PAGE_ORDER_4K, >>>> - perms, &flush_flags); >>>> + { >>>> + ++count; >>>> + rc = 0; >>>> + } >>>> >>>> if ( rc ) >>>> printk(XENLOG_WARNING "%pd: identity %smapping of %lx failed: >>>> %d\n", >>>> d, !paging_mode_translate(d) ? "IOMMU " : "", pfn, rc); >>> >>> Would be nice to print the count (or end pfn) in case it's a range. >> >> I can do so if you think it's worth further extra code. I can't use >> "count" here in particular, as that was updated already (in context >> above). The most reasonable change towards this would perhaps be to >> duplicate the printk() into both the "if()" and the "else if()" bodies. > > Maybe. The current message gives the impression that a single pfn has > been added and failed, but without printing the range that failed the > message will not be that helpful in diagnosing further issues that > might arise due to the mapping failure. I guess I'll make the change then. I'm still not really convinced though, as the presence of the message should be far more concerning than whether it's a single page or a range. As middle ground, would printk(XENLOG_WARNING "%pd: identity %smapping of %lx... failed: %d\n", be indicative enough of this perhaps not having been just a single page? Otoh splitting (and moving) the message would allow to drop the separate paging_mode_translate() check. Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |