login
Login
/
Register
Search
Search this site:
Forums
News
Blogs
Features
Site
Home
»
Mailing list archives
»
linux-kernel
»
2010
»
November
»
16
Re: [PATCH] vfio: fix config virtualization, esp command byte
view
thread
Previous message: [
thread
] [
date
] [
author
]
Next message: [
thread
] [
date
] [
author
]
[view in full thread]
From: Alex Williamson
Subject:
Re: [PATCH] vfio: fix config virtualization, esp command byte
Date: Tuesday, November 16, 2010 - 10:54 am
On Tue, 2010-11-09 at 17:09 -0800, Tom Lyon wrote:
quoted text
> Cleans up config space virtualization, especialy handling of bytes > which have some virtual and some real bits, like PCI_COMMAND. > > Alex, I hope you can test this with your setups.
Sorry for the delay. FWIW, I'm not having much luck with this, I'll try to debug the problem. Thanks, Alex
quoted text
> Signed-off-by: Tom Lyon <pugs@cisco.com> > --- > drivers/vfio/vfio_pci_config.c | 166 +++++++++++++--------------------------- > 1 files changed, 53 insertions(+), 113 deletions(-) > > diff --git a/drivers/vfio/vfio_pci_config.c b/drivers/vfio/vfio_pci_config.c > index 8304316..7132ac4 100644 > --- a/drivers/vfio/vfio_pci_config.c > +++ b/drivers/vfio/vfio_pci_config.c > @@ -745,6 +745,8 @@ static int vfio_virt_init(struct vfio_dev *vdev) > */ > static void vfio_bar_restore(struct vfio_dev *vdev) > { > + if (vdev->pdev->is_virtfn) > + return; > printk(KERN_WARNING "%s: reset recovery - restoring bars\n", __func__); > > #define do_bar(off, which) \ > @@ -815,26 +817,15 @@ static inline int vfio_read_config_byte(struct vfio_dev *vdev, > static inline int vfio_write_config_byte(struct vfio_dev *vdev, > int pos, u8 val) > { > - vdev->vconfig[pos] = val; > return pci_user_write_config_byte(vdev->pdev, pos, val); > } > > /* handle virtualized fields in the basic config space */ > -static u8 vfio_virt_basic(struct vfio_dev *vdev, int write, > - u16 pos, u16 off, u8 val, u8 newval) > +static void vfio_virt_basic(struct vfio_dev *vdev, int write, u16 pos, u8 *rbp) > { > - switch (off) { > - /* > - * vendor and device are virt because they don't > - * show up otherwise for sr-iov vfs > - */ > - case PCI_VENDOR_ID: > - case PCI_VENDOR_ID + 1: > - case PCI_DEVICE_ID: > - case PCI_DEVICE_ID + 1: > - /* read only */ > - val = vdev->vconfig[pos]; > - break; > + u8 val; > + > + switch (pos) { > case PCI_COMMAND: > /* > * If the real mem or IO enable bits are zero > @@ -842,100 +833,58 @@ static u8 vfio_virt_basic(struct vfio_dev *vdev, int write, > * Restore the real BARs before allowing those > * bits to re-enable > */ > + val = vdev->vconfig[pos]; > if (vdev->pdev->is_virtfn) > val |= PCI_COMMAND_MEMORY; > if (write) { > - int upd = 0; > - > - upd = (newval & PCI_COMMAND_MEMORY) > > - (val & PCI_COMMAND_MEMORY); > - upd += (newval & PCI_COMMAND_IO) > > - (val & PCI_COMMAND_IO); > - if (upd) > - vfio_bar_restore(vdev); > - vfio_write_config_byte(vdev, pos, newval); > - } > - break; > - case PCI_BASE_ADDRESS_0: > - case PCI_BASE_ADDRESS_0+1: > - case PCI_BASE_ADDRESS_0+2: > - case PCI_BASE_ADDRESS_0+3: > - case PCI_BASE_ADDRESS_1: > - case PCI_BASE_ADDRESS_1+1: > - case PCI_BASE_ADDRESS_1+2: > - case PCI_BASE_ADDRESS_1+3: > - case PCI_BASE_ADDRESS_2: > - case PCI_BASE_ADDRESS_2+1: > - case PCI_BASE_ADDRESS_2+2: > - case PCI_BASE_ADDRESS_2+3: > - case PCI_BASE_ADDRESS_3: > - case PCI_BASE_ADDRESS_3+1: > - case PCI_BASE_ADDRESS_3+2: > - case PCI_BASE_ADDRESS_3+3: > - case PCI_BASE_ADDRESS_4: > - case PCI_BASE_ADDRESS_4+1: > - case PCI_BASE_ADDRESS_4+2: > - case PCI_BASE_ADDRESS_4+3: > - case PCI_BASE_ADDRESS_5: > - case PCI_BASE_ADDRESS_5+1: > - case PCI_BASE_ADDRESS_5+2: > - case PCI_BASE_ADDRESS_5+3: > - case PCI_ROM_ADDRESS: > - case PCI_ROM_ADDRESS+1: > - case PCI_ROM_ADDRESS+2: > - case PCI_ROM_ADDRESS+3: > - if (write) { > - vdev->vconfig[pos] = newval; > - vdev->bardirty = 1; > - } else { > - if (vdev->bardirty) > - vfio_bar_fixup(vdev); > - val = vdev->vconfig[pos]; > + > + if (((val & PCI_COMMAND_MEMORY) > > + (*rbp & PCI_COMMAND_MEMORY)) || > + ((val & PCI_COMMAND_IO) > > + (*rbp & PCI_COMMAND_IO))) > + vfio_bar_restore(vdev); > + *rbp &= ~(PCI_COMMAND_MEMORY + PCI_COMMAND_IO); > + *rbp |= val & (PCI_COMMAND_MEMORY + PCI_COMMAND_IO); > } > + vdev->vconfig[pos] = val; > break; > - default: > + case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5 + 3: > + case PCI_ROM_ADDRESS ... PCI_ROM_ADDRESS + 3: > if (write) > - vdev->vconfig[pos] = newval; > - else > - val = vdev->vconfig[pos]; > + vdev->bardirty = 1; > + else if (vdev->bardirty) > + vfio_bar_fixup(vdev); > break; > } > - return val; > } > > /* > * handle virtualized fields in msi capability > * easy, except for multiple-msi fields in flags byte > */ > -static u8 vfio_virt_msi(struct vfio_dev *vdev, int write, > - u16 pos, u16 off, u8 val, u8 newval) > +static void vfio_virt_msi(struct vfio_dev *vdev, int write, > + u16 pos, u16 off, u8 *rbp) > { > - if (off == PCI_MSI_FLAGS) { > - u8 num; > + u8 val; > + u8 num; > > + val = vdev->vconfig[pos]; > + if (off == PCI_MSI_FLAGS) { > if (write) { > if (!vdev->ev_msi) > - newval &= ~PCI_MSI_FLAGS_ENABLE; > - num = (newval & PCI_MSI_FLAGS_QSIZE) >> 4; > + val &= ~PCI_MSI_FLAGS_ENABLE; > + num = (val & PCI_MSI_FLAGS_QSIZE) >> 4; > if (num > vdev->msi_qmax) > num = vdev->msi_qmax; > - newval &= ~PCI_MSI_FLAGS_QSIZE; > - newval |= num << 4; > - vfio_write_config_byte(vdev, pos, newval); > + val &= ~PCI_MSI_FLAGS_QSIZE; > + val |= num << 4; > + *rbp = val; > } else { > - if (vfio_read_config_byte(vdev, pos, &val) < 0) > - return 0; > val &= ~PCI_MSI_FLAGS_QMASK; > val |= vdev->msi_qmax << 1; > } > - return val; > } > - > - if (write) > - vdev->vconfig[pos] = newval; > - else > - val = vdev->vconfig[pos]; > - return val; > + vdev->vconfig[pos] = val; > } > > static int vfio_config_rwbyte(int write, > @@ -950,6 +899,7 @@ static int vfio_config_rwbyte(int write, > struct perm_bits *perm; > u8 wr, virt; > int ret; > + u8 realbits = 0; > > cap = map[pos]; > if (cap == 0xFF) { /* unknown region */ > @@ -989,7 +939,7 @@ static int vfio_config_rwbyte(int write, > } > if (write && !wr) /* no writeable bits */ > return 0; > - if (!virt) { > + if (!virt) { /* no virtual bits */ > if (write) { > if (copy_from_user(&val, buf, 1)) > return -EFAULT; > @@ -1018,54 +968,44 @@ static int vfio_config_rwbyte(int write, > if (copy_from_user(&newval, buf, 1)) > return -EFAULT; > } > - /* > - * We get here if there are some virt bits > - * handle remaining real bits, if any > - */ > - if (~virt) { > - u8 rbits = (~virt) & wr; > > - ret = vfio_read_config_byte(vdev, pos, &val); > + if (~virt) { /* mix of real and virt bits */ > + /* update vconfig with latest hw bits */ > + ret = vfio_read_config_byte(vdev, pos, &realbits); > if (ret < 0) > return ret; > - if (write && rbits) { > - val &= ~rbits; > - val |= (newval & rbits); > - vfio_write_config_byte(vdev, pos, val); > - } > + vdev->vconfig[pos] = > + (vdev->vconfig[pos] & virt) | (realbits & ~virt); > } > + > + /* update vconfig with writeable bits */ > + vdev->vconfig[pos] = > + (vdev->vconfig[pos] & ~wr) | (newval & wr); > + > /* > - * Now handle entirely virtual fields > + * Now massage virtual fields > */ > if (pos < PCI_CFG_SPACE_SIZE) { > switch (cap) { > case PCI_CAP_ID_BASIC: /* virtualize BARs */ > - val = vfio_virt_basic(vdev, write, > - pos, off, val, newval); > + vfio_virt_basic(vdev, write, pos, &realbits); > break; > case PCI_CAP_ID_MSI: /* virtualize (parts of) MSI */ > - val = vfio_virt_msi(vdev, write, > - pos, off, val, newval); > - break; > - default: > - if (write) > - vdev->vconfig[pos] = newval; > - else > - val = vdev->vconfig[pos]; > + vfio_virt_msi(vdev, write, pos, off, &realbits); > break; > } > } else { > /* no virt fields yet in ecaps */ > switch (cap) { /* extended capabilities */ > default: > - if (write) > - vdev->vconfig[pos] = newval; > - else > - val = vdev->vconfig[pos]; > break; > } > } > - if (!write && copy_to_user(buf, &val, 1)) > + if (write && ~virt) { > + realbits = (realbits & virt) | (vdev->vconfig[pos] & ~virt); > + vfio_write_config_byte(vdev, pos, realbits); > + } > + if (!write && copy_to_user(buf, &vdev->vconfig[pos], 1)) > return -EFAULT; > return 0; > }
--
unsubscribe notice
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to
majordomo@vger.kernel.org
More majordomo info at
http://vger.kernel.org/majordomo-info.html
Please read the FAQ at
http://www.tux.org/lkml/
Previous message: [
thread
] [
date
] [
author
]
Next message: [
thread
] [
date
] [
author
]
Messages in current thread:
[PATCH] vfio: fix config virtualization, esp command byte
, Tom Lyon
, (Tue Nov 9, 6:09 pm)
Re: [PATCH] vfio: fix config virtualization, esp command byte
, Alex Williamson
, (Tue Nov 16, 10:54 am)
Re: [PATCH] vfio: fix config virtualization, esp command byte
, Alex Williamson
, (Tue Nov 16, 11:57 am)
Re: [PATCH] vfio: fix config virtualization, esp command byte
, Tom Lyon
, (Tue Nov 16, 10:14 pm)
Navigation
Mailing list archives
Recent posts
Popular discussions
linux-kernel
:
Rusty Russell
Re: 2.6.22-rc3-mm1
Eric Sandeen
Re: [PATCH] xfs: do not pass unused params to xfs_flush_pages
Bill Fink
Re: [PATCH] net: add ability to clear stats via ethtool - e1000/pcnet32
David Miller
Re: NO_HZ: timer interrupt stuck
Jeffrey V. Merkey
Re: Versioning file system
git
:
Johannes Schindelin
[PATCH] fetch: refuse to fetch into the current branch in a non-bare repository
Junio C Hamano
Re: [PATCH] http-push: making HTTP push more robust and more user-friendly
Oliver Kullmann
Re: how to move with history?
Junio C Hamano
Re: [PATCH 2/3] git-add--interactive: remove hunk coalescing
Shawn O. Pearce
Re: Bugs in Gitosis
linux-netdev
:
gregkh
Patch "IPv6: keep route for tentative address" has been added to the 2.6.34-stable...
Patrick McHardy
Re: [rfc 02/13] [RFC 02/13] netfilter: nf_conntrack_sip: Add callid parser
webmaster Maintenance
&#32852;&#31995;&#31995;&#32479;&#31649;&#29702;&#21592;
Krzysztof Oledzki
Re: Error: an inet prefix is expected rather than "0/0".
Paul Gortmaker
[PATCH net-next 09/16] tipc: Relocate trivial link status functions to header file
git-commits-head
:
Linux Kernel Mailing List
V4L/DVB: tm6000: add special usb request to quit i2c tuner transfer
Linux Kernel Mailing List
OMAP: DSS2: SDI driver
Linux Kernel Mailing List
PCI: introduce pci_pcie_cap()
Linux Kernel Mailing List
drivers/acpi: use kasprintf
Linux Kernel Mailing List
Staging: et131x: prune all the debug code
openbsd-misc
:
Ted Bullock
Re: Proliant DL380 G3 cannot get on network
Úlfar M. E. Johnson
installing openbsd in xen
Eric Furman
Re: Defending OpenBSD Performance
Damien Miller
Re: Patching a SSH 'Weakness'
Brian
CARP multicast and ADSL bridge
Colocation donated by:
Syndicate