[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v4 1/2] x86/mm: add API for marking only part of a MMIO page read only
On Fri, Jun 07, 2024 at 09:01:25AM +0200, Jan Beulich wrote: > On 22.05.2024 17:39, Marek Marczykowski-Górecki wrote: > > --- a/xen/arch/x86/include/asm/mm.h > > +++ b/xen/arch/x86/include/asm/mm.h > > @@ -522,9 +522,34 @@ extern struct rangeset *mmio_ro_ranges; > > void memguard_guard_stack(void *p); > > void memguard_unguard_stack(void *p); > > > > +/* > > + * Add more precise r/o marking for a MMIO page. Range specified here > > + * will still be R/O, but the rest of the page (not marked as R/O via > > another > > + * call) will have writes passed through. > > + * The start address and the size must be aligned to MMIO_RO_SUBPAGE_GRAN. > > + * > > + * This API cannot be used for overlapping ranges, nor for pages already > > added > > + * to mmio_ro_ranges separately. > > + * > > + * Since there is currently no subpage_mmio_ro_remove(), relevant device > > should > > + * not be hot-unplugged. > > Yet there are no guarantees whatsoever. I think we should refuse > hot-unplug attempts (not just here, but also e.g. for an EHCI > controller that we use the debug feature of), but doing so would > likely require coordination with Dom0. Nothing to be done right > here, of course. > > > + * Return values: > > + * - negative: error > > + * - 0: success > > + */ > > +#define MMIO_RO_SUBPAGE_GRAN 8 > > +int subpage_mmio_ro_add(paddr_t start, size_t size); > > +#ifdef CONFIG_HVM > > +bool subpage_mmio_write_accept(mfn_t mfn, unsigned long gla); > > +#endif > > I'd suggest to omit the #ifdef here. The declaration alone doesn't > hurt, and the #ifdef harms readability (if only a bit). Ok. > > --- a/xen/arch/x86/mm.c > > +++ b/xen/arch/x86/mm.c > > @@ -150,6 +150,17 @@ bool __read_mostly machine_to_phys_mapping_valid; > > > > struct rangeset *__read_mostly mmio_ro_ranges; > > > > +/* Handling sub-page read-only MMIO regions */ > > +struct subpage_ro_range { > > + struct list_head list; > > + mfn_t mfn; > > + void __iomem *mapped; > > + DECLARE_BITMAP(ro_elems, PAGE_SIZE / MMIO_RO_SUBPAGE_GRAN); > > +}; > > + > > +static LIST_HEAD(subpage_ro_ranges); > > With modifications all happen from __init code, this likely wants > to be LIST_HEAD_RO_AFTER_INIT() (which would need introducing, to > parallel LIST_HEAD_READ_MOSTLY()). Makes sense. And then I would be comfortable with dropping the spinlock as Roger suggested. I tried to make this API a bit more generic than I currently need, but indeed it can be simplified for this particular use case. > > +int __init subpage_mmio_ro_add( > > + paddr_t start, > > + size_t size) > > +{ > > + mfn_t mfn_start = maddr_to_mfn(start); > > + paddr_t end = start + size - 1; > > + mfn_t mfn_end = maddr_to_mfn(end); > > + unsigned int offset_end = 0; > > + int rc; > > + bool subpage_start, subpage_end; > > + > > + ASSERT(IS_ALIGNED(start, MMIO_RO_SUBPAGE_GRAN)); > > + ASSERT(IS_ALIGNED(size, MMIO_RO_SUBPAGE_GRAN)); > > + if ( !IS_ALIGNED(size, MMIO_RO_SUBPAGE_GRAN) ) > > + size = ROUNDUP(size, MMIO_RO_SUBPAGE_GRAN); > > I'm puzzled: You first check suitable alignment and then adjust size > to have suitable granularity. Either it is a mistake to call the > function with a bad size, or it is not. If it's a mistake, the > release build alternative to the assertion would be to return an > error. If it's not a mistake, the assertion ought to go away. > > If the assertion is to stay, then I'll further question why the > other one doesn't also have release build safety fallback logic. For some reason I read your earlier comment as a request to (try to) continue safely in this case. But indeed an error is a better option, it isn't supposed to happen anyway. > > + if ( !size ) > > + return 0; > > + > > + if ( mfn_eq(mfn_start, mfn_end) ) > > + { > > + /* Both starting and ending parts handled at once */ > > + subpage_start = PAGE_OFFSET(start) || PAGE_OFFSET(end) != > > PAGE_SIZE - 1; > > + subpage_end = false; > > + } > > + else > > + { > > + subpage_start = PAGE_OFFSET(start); > > + subpage_end = PAGE_OFFSET(end) != PAGE_SIZE - 1; > > + } > > Since you calculate "end" before adjusting "size", the logic here > depends on there being the assertion further up. > > Jan -- Best Regards, Marek Marczykowski-Górecki Invisible Things Lab Attachment:
signature.asc
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |