[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 1/2] x86/mm: add API for marking only part of a MMIO page read only
On Wed, Jul 05, 2023 at 10:23:53AM +0200, Jan Beulich wrote: > On 01.07.2023 00:28, Marek Marczykowski-Górecki wrote: > > On Tue, May 30, 2023 at 01:56:34PM +0200, Jan Beulich wrote: > >> On 05.05.2023 23:25, Marek Marczykowski-Górecki wrote: > >>> --- a/xen/arch/x86/hvm/hvm.c > >>> +++ b/xen/arch/x86/hvm/hvm.c > >>> @@ -1990,6 +1990,14 @@ int hvm_hap_nested_page_fault(paddr_t gpa, > >>> unsigned long gla, > >>> goto out_put_gfn; > >>> } > >>> > >>> + if ( (p2mt == p2m_mmio_direct) && npfec.write_access && > >>> npfec.present && > >>> + subpage_mmio_write_accept(mfn, gla) && > >>> + (hvm_emulate_one_mmio(mfn_x(mfn), gla) == X86EMUL_OKAY) ) > >>> + { > >>> + rc = 1; > >>> + goto out_put_gfn; > >>> + } > >> > >> But npfec.write_access set doesn't mean it was a write permission > >> violation, does it? > > > > Doesn't it? IIUC it means it was a write attempt, to a mapped page > > (npfec.present), and since we've got EPT violation, it got denied. > > But the denial may have been for reasons other than the W bit being > clear, at least in principle? Abusing the bit now, even if in > practice there was no other possible reason on existing hardware > with the features we presently use, might lead to hard to locate > issues in case a different reason appears down the road. Ok, so how do you propose to check if it was a write violation? (...) > >> Since you mark the qwords which are to be protected, how is one to set > >> up safely two discontiguous ranges on the same page? I think I had > >> asked for v1 already why you don't do things the other way around: > >> Initially the entire page is protected, and then writable regions are > >> carved out. > > > > Because that's not how the API is used. This API is for those how want > > to write-protect some specific ranges (to be written exclusively by > > Xen). They don't need to even know what is else is on the same page. > > Take XHCI case as an example: it gets the range to write-protect by > > enumerating XHCI extended capabilities, which is a linked list. The > > driver gets info where XHCI console registers are. Things before/after > > them on that page may not even be XHCI extended caps at all. > > This in fact is very similar approach to already existing > > mmio_ro_ranges. > > While I agree there's a similarity, multiple entities caring about the > same MFN isn't an expected scenario there. Whereas here you explicitly > add support for such. > > Furthermore you sub-divide pages covered by mmio_ro_ranges here, so > defaulting to "full page protected" and then carving out sub-regions > would be the more natural approach imo. But then the API would be awkward to use. Instead of "mark this (smaller than a page) region as read-only" so Xen can use it safely, you would (likely) need marking _two_ regions as writable, after marking a page as read-only. So, either you'd need separate (3?) calls, array of ranges or something similar. > >> I guess I shouldn't further ask about overlapping r/o ranges and their > >> cleaning up. But at least a comment towards the restriction would be > >> nice. Perhaps even check upon registration that no part of the range > >> is already marked r/o. > > > > Yes, this is a good suggestion, I'll add that. > > As long as all restrictions are properly spelled out, this may be > sufficient. But please don't be surprised if I ask again on a > subsequent version. (...) > >>> +static void subpage_mmio_write_emulate( > >>> + mfn_t mfn, > >>> + unsigned int offset, > >>> + const void *data, > >>> + unsigned int len) > >>> +{ > >>> + struct subpage_ro_range *entry; > >>> + void __iomem *addr; > >>> + > >>> + rcu_read_lock(&subpage_ro_rcu); > >>> + > >>> + list_for_each_entry_rcu(entry, &subpage_ro_ranges, list) > >>> + { > >>> + if ( mfn_eq(entry->mfn, mfn) ) > >>> + { > >>> + if ( test_bit(offset / SUBPAGE_MMIO_RO_ALIGN, > >>> entry->ro_qwords) ) > >>> + goto write_ignored; > >> > >> I think you can get away with just a single "goto" by putting the gprintk() > >> (and its label) here. > > > > write_ignored label is used also below in "default" case (which should > > be unreachable, but still). > > Right, which is why I said 'just a single "goto"' (implying a label would > still be needed). > > > Do you suggest jumping from default case into here? > > Yes, that would be one way of structuring things. IMO jumping into a middle of some nested conditional/loop is harder to follow, I'd prefer to avoid such practice. Furthermore, if moving the gprintk here, it still needs "goto out_unlock", so it isn't really saving any "goto", just changing its target. -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab Attachment:
signature.asc
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |