Message ID | 1556019478-10835-1-git-send-email-igor.druzhinin@citrix.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | x86/mtrr: recalculate P2M type for domains with iocaps | expand |
>>> On 23.04.19 at 13:37, <igor.druzhinin@citrix.com> wrote: > This change reflects the logic in epte_get_entry_emt() and allows > changes in guest MTTRs to be reflected in EPT for domains having > direct access to certain hardware memory regions but without IOMMU > context assigned (e.g. XenGT). > > Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com> Fundamentally I'm happy to get both in sync, so Reviewed-by: Jan Beulich <jbeulich@suse.com> But I have a question: > void memory_type_changed(struct domain *d) > { > - if ( has_iommu_pt(d) && d->vcpu && d->vcpu[0] ) > + if ( (has_iommu_pt(d) || cache_flush_permitted(d)) && d->vcpu && d->vcpu[0] ) > { > p2m_memory_type_changed(d); > flush_all(FLUSH_CACHE); Wouldn't cache_flush_permitted() alone suffice, both here and there? Even if anyone was to pass-through a device without any MMIO or I/O port BAR, the memory type (which is a CPU side thing only, i.e. doesn't affect DMA by the device) shouldn't matter in that case (leaving aside the fact that a BAR-less device is unlikely to be DMA-capable, unless the programming of the DMA operations was to happen through vendor specific config space accesses). Jan
On 25/04/2019 14:30, Jan Beulich wrote: >>>> On 23.04.19 at 13:37, <igor.druzhinin@citrix.com> wrote: >> This change reflects the logic in epte_get_entry_emt() and allows >> changes in guest MTTRs to be reflected in EPT for domains having >> direct access to certain hardware memory regions but without IOMMU >> context assigned (e.g. XenGT). >> >> Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com> > > Fundamentally I'm happy to get both in sync, so > Reviewed-by: Jan Beulich <jbeulich@suse.com> > > But I have a question: > >> void memory_type_changed(struct domain *d) >> { >> - if ( has_iommu_pt(d) && d->vcpu && d->vcpu[0] ) >> + if ( (has_iommu_pt(d) || cache_flush_permitted(d)) && d->vcpu && d->vcpu[0] ) >> { >> p2m_memory_type_changed(d); >> flush_all(FLUSH_CACHE); > > Wouldn't cache_flush_permitted() alone suffice, both here and > there? Even if anyone was to pass-through a device without any > MMIO or I/O port BAR, the memory type (which is a CPU side > thing only, i.e. doesn't affect DMA by the device) shouldn't > matter in that case (leaving aside the fact that a BAR-less > device is unlikely to be DMA-capable, unless the programming > of the DMA operations was to happen through vendor specific > config space accesses). > I don't think it's correct in case of EPT sharing with IOMMU as the section 3.6.5 of VT-d spec implies there is direct effect of caching information present in IOMMU page table on device accesses within processor coherency domain. So even in case there are no BARs passed to the domain, drivers inside it and devices operation on its memory could still have assumptions on device memory access properties. Igor
>>> On 25.04.19 at 16:50, <igor.druzhinin@citrix.com> wrote: > On 25/04/2019 14:30, Jan Beulich wrote: >>>>> On 23.04.19 at 13:37, <igor.druzhinin@citrix.com> wrote: >>> void memory_type_changed(struct domain *d) >>> { >>> - if ( has_iommu_pt(d) && d->vcpu && d->vcpu[0] ) >>> + if ( (has_iommu_pt(d) || cache_flush_permitted(d)) && d->vcpu && d->vcpu[0] ) >>> { >>> p2m_memory_type_changed(d); >>> flush_all(FLUSH_CACHE); >> >> Wouldn't cache_flush_permitted() alone suffice, both here and >> there? Even if anyone was to pass-through a device without any >> MMIO or I/O port BAR, the memory type (which is a CPU side >> thing only, i.e. doesn't affect DMA by the device) shouldn't >> matter in that case (leaving aside the fact that a BAR-less >> device is unlikely to be DMA-capable, unless the programming >> of the DMA operations was to happen through vendor specific >> config space accesses). > > I don't think it's correct in case of EPT sharing with IOMMU as the > section 3.6.5 of VT-d spec implies there is direct effect of caching > information present in IOMMU page table on device accesses within > processor coherency domain. So even in case there are no BARs passed to > the domain, drivers inside it and devices operation on its memory could > still have assumptions on device memory access properties. But that's a First-Level Translation subsection. For us right now section 3.7.4 is relevant, while in the future 3.8.4 may become relevant too. As per 3.7.4 all leaf page (actual data) accesses are of WB type anyway. Once 3.8.4 becomes applicable, we'd likely have to support IOMMU side MTRRs as well, or else the MTRR imposed memory type would be uniformly UC, allowing for only UC and WC effective memory types. Jan
On 25/04/2019 16:49, Jan Beulich wrote: >>>> On 25.04.19 at 16:50, <igor.druzhinin@citrix.com> wrote: >> On 25/04/2019 14:30, Jan Beulich wrote: >>>>>> On 23.04.19 at 13:37, <igor.druzhinin@citrix.com> wrote: >>>> void memory_type_changed(struct domain *d) >>>> { >>>> - if ( has_iommu_pt(d) && d->vcpu && d->vcpu[0] ) >>>> + if ( (has_iommu_pt(d) || cache_flush_permitted(d)) && d->vcpu && d->vcpu[0] ) >>>> { >>>> p2m_memory_type_changed(d); >>>> flush_all(FLUSH_CACHE); >>> >>> Wouldn't cache_flush_permitted() alone suffice, both here and >>> there? Even if anyone was to pass-through a device without any >>> MMIO or I/O port BAR, the memory type (which is a CPU side >>> thing only, i.e. doesn't affect DMA by the device) shouldn't >>> matter in that case (leaving aside the fact that a BAR-less >>> device is unlikely to be DMA-capable, unless the programming >>> of the DMA operations was to happen through vendor specific >>> config space accesses). >> >> I don't think it's correct in case of EPT sharing with IOMMU as the >> section 3.6.5 of VT-d spec implies there is direct effect of caching >> information present in IOMMU page table on device accesses within >> processor coherency domain. So even in case there are no BARs passed to >> the domain, drivers inside it and devices operation on its memory could >> still have assumptions on device memory access properties. > > But that's a First-Level Translation subsection. For us right now > section 3.7.4 is relevant, while in the future 3.8.4 may become > relevant too. As per 3.7.4 all leaf page (actual data) accesses > are of WB type anyway. > > Once 3.8.4 becomes applicable, we'd likely have to support IOMMU > side MTRRs as well, or else the MTRR imposed memory type would > be uniformly UC, allowing for only UC and WC effective memory > types. > Oh yes, sorry that I mixed them up. In that case, probably yes - simply cache_flush_permitted() would suffice. Although there are things that I'm not sure about: - whether iocaps are always used by software in Dom0 when passing through certain physical memory and whether their usage is enforced by Xen - there are could be assumptions elsewhere that with IOMMU context assigned guest caching choice is in effect - since that fact has been perpetuated in Xen code for very long time Igor
>>> On 25.04.19 at 18:22, <igor.druzhinin@citrix.com> wrote: > Although there are things that I'm not sure about: > - whether iocaps are always used by software in Dom0 when passing > through certain physical memory and whether their usage is enforced by Xen I'm afraid I'm struggling to understand what exactly you mean. Passing through a device without also registering the BARs for use by the target guest simply wouldn't yield a functioning device (in the guest). Arguably it shouldn't be a separate domctl, but that's how the people originally implementing pass-through chose to structure things. It has the advantage of devices working where Dom0 knows about extra resources (MMIO or I/O ports) when Xen doesn't. It has the disadvantage of being dependent on Xen, Dom0 kernel, and the tool stack interacting correctly (rather than all logic being in a single component). There was a similarly odd arrangement in the original implementation of MSI-X, where Xen depended upon Dom0 reporting the MSI-X table base. Nowadays we read the BAR ourselves and simply check that the value matches what Dom0 has passed. > - there are could be assumptions elsewhere that with IOMMU context > assigned guest caching choice is in effect - since that fact has been > perpetuated in Xen code for very long time Agreed - there's a certain chance that other places in Xen have similar logic. But there's an equal chance that other places in Xen similarly check only one of the two, when, in the spirit of your patch, they really mean to check both. This could only be clarified by doing a full audit. Jan
diff --git a/xen/arch/x86/hvm/mtrr.c b/xen/arch/x86/hvm/mtrr.c index b8fa340..7ccd85b 100644 --- a/xen/arch/x86/hvm/mtrr.c +++ b/xen/arch/x86/hvm/mtrr.c @@ -783,7 +783,7 @@ HVM_REGISTER_SAVE_RESTORE(MTRR, hvm_save_mtrr_msr, hvm_load_mtrr_msr, 1, void memory_type_changed(struct domain *d) { - if ( has_iommu_pt(d) && d->vcpu && d->vcpu[0] ) + if ( (has_iommu_pt(d) || cache_flush_permitted(d)) && d->vcpu && d->vcpu[0] ) { p2m_memory_type_changed(d); flush_all(FLUSH_CACHE);
This change reflects the logic in epte_get_entry_emt() and allows changes in guest MTTRs to be reflected in EPT for domains having direct access to certain hardware memory regions but without IOMMU context assigned (e.g. XenGT). Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com> --- xen/arch/x86/hvm/mtrr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)