[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 2/3] x86/hvm: Allow writes to registers on the same page as MSI-X table
On Tue, Mar 28, 2023 at 02:05:14PM +0200, Marek Marczykowski-Górecki wrote: > On Tue, Mar 28, 2023 at 01:28:44PM +0200, Roger Pau Monné wrote: > > On Sat, Mar 25, 2023 at 03:49:23AM +0100, Marek Marczykowski-Górecki wrote: > > > + address >= entry->gtable + entry->table_len ) > > > + { > > > + adj_type = ADJ_IDX_LAST; > > > + pdev = entry->pdev; > > > + break; > > > + } > > > + } > > > + rcu_read_unlock(&msixtbl_rcu_lock); > > > + > > > + if ( !pdev ) > > > + return NULL; > > > + > > > + ASSERT(pdev->msix); > > > + > > > + if ( !pdev->msix->adj_access_table_idx[adj_type] ) > > > + { > > > + gdprintk(XENLOG_WARNING, > > > + "Page for adjacent MSI-X table access not initialized > > > for %pp\n", > > > + pdev); > > > + > > > + return NULL; > > > + } > > > + > > > + /* If PBA lives on the same page too, forbid writes. */ > > > + if ( write && ( > > > + (adj_type == ADJ_IDX_LAST && > > > + pdev->msix->table.last == pdev->msix->pba.first) || > > > + (adj_type == ADJ_IDX_FIRST && > > > + pdev->msix->table.first == pdev->msix->pba.last)) ) > > > + { > > > + gdprintk(XENLOG_WARNING, > > > + "MSI-X table and PBA of %pp live on the same page, " > > > + "writing to other registers there is not implemented\n", > > > + pdev); > > > > Don't you actually need to check that the passed address falls into the > > PBA array? PBA can be sharing the same page as the MSI-X table, but > > that doesn't imply there aren't holes also not used by either the PBA > > or the MSI-X table in such page. > > I don't know exact location of PBA, so I'm rejecting writes just in case > they do hit PBA (see commit message). Hm, maybe we should cache the address and size of the PBA in msix_capability_init(). > > > + > > > +} > > > + > > > +static bool cf_check msixtbl_page_accept( > > > + const struct hvm_io_handler *handler, const ioreq_t *r) > > > +{ > > > + ASSERT(r->type == IOREQ_TYPE_COPY); > > > + > > > + return msixtbl_page_handler_get_hwaddr( > > > + current->domain, r->addr, r->dir == IOREQ_WRITE); > > > > I think you want to accept it also if it's a write to the PBA, and > > just drop it. You should always pass write=false and then drop it in > > msixtbl_page_write() if it falls in the PBA region (but still return > > X86EMUL_OKAY). > > I don't want to interfere with msixtbl_mmio_page_ops, this handler is > only about accesses not hitting actual MSI-X structures. But msixtbl_mmio_page_ops doesn't handle PBA array accesses at all, so you won't interfere by accepting PBA writes here and dropping them in msixtbl_page_write()? Maybe there's some piece I'm missing. > > > +} > > > + > > > +static int cf_check msixtbl_page_read( > > > + const struct hvm_io_handler *handler, > > > + uint64_t address, uint32_t len, uint64_t *pval) > > > > Why use hvm_io_ops and not hvm_mmio_ops? You only care about MMIO > > accesses here. > > I followed how msixtbl_mmio_ops are registered. Should that also be > changed to hvm_mmio_ops? Maybe, but let's leave that for another series I think. Using hvm_mmio_ops and register_mmio_handler() together with the slightly simplified handlers will allow you to drop some of the code. > > > + > > > + if ( address & (len - 1) ) > > > + return X86EMUL_UNHANDLEABLE; > > > > You can use IS_ALIGNED for clarity. In my fix for this for vPCI Jan > > asked to split unaligned accesses into 1byte ones, but I think for > > guests it's better to just drop them unless there's a specific case > > that we need to handle. > > > > Also you should return X86EMUL_OKAY here, as the address is handled > > here, but the current way to handle it is to drop the access. > > > > Printing a debug message can be helpful in case unaligned accesses > > need to be implemented in order to support some device. > > > > > + > > > + hwaddr = msixtbl_page_handler_get_hwaddr( > > > + current->domain, address, false); > > > + > > > + if ( !hwaddr ) > > > + return X86EMUL_UNHANDLEABLE; > > > > Maybe X86EMUL_RETRY, since the page was there in the accept handler. > > How does X86EMUL_RETRY work? Is it trying to find the handler again? Hm, I'm not sure it works as I thought it does, so maybe not a good suggestion after all. > > > @@ -1090,6 +1118,16 @@ static void _pci_cleanup_msix(struct arch_msix > > > *msix) > > > WARN(); > > > msix->table.first = 0; > > > msix->table.last = 0; > > > + if ( msix->adj_access_table_idx[ADJ_IDX_FIRST] ) > > > + { > > > + msix_put_fixmap(msix, > > > msix->adj_access_table_idx[ADJ_IDX_FIRST]); > > > + msix->adj_access_table_idx[ADJ_IDX_FIRST] = 0; > > > + } > > > + if ( msix->adj_access_table_idx[ADJ_IDX_LAST] ) > > > + { > > > + msix_put_fixmap(msix, > > > msix->adj_access_table_idx[ADJ_IDX_LAST]); > > > + msix->adj_access_table_idx[ADJ_IDX_LAST] = 0; > > > > Isn't 0 a valid idx? You should check for >= 0 and also set > > to -1 once the fixmap entry has been put. > > I rely here on msix using specific range of fixmap indexes > (FIX_MSIX_TO_RESERV_BASE - FIX_MSIX_TO_RESERV_END), which isn't starting > at 0. For this reason also, I keep unused entries at 0 (no need explicit > initialization). Hm, OK, then you should also check that the return of msix_get_fixmap() is strictly > 0, as right now it's using >= (and thus would think 0 is a valid fixmap entry). Thanks, Roger.
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |