Skip to content

Commit 934f98d

Browse files
committed
Merge tag 'vfio-v4.4-rc1' of git://github.com/awilliam/linux-vfio
Pull VFIO updates from Alex Williamson: - Use kernel interfaces for VPD emulation (Alex Williamson) - Platform fix for releasing IRQs (Eric Auger) - Type1 IOMMU always advertises PAGE_SIZE support when smaller mapping sizes are available (Eric Auger) - Platform fixes for incorrectly using copies of structures rather than pointers to structures (James Morse) - Rework platform reset modules, fix leak, and add AMD xgbe reset module (Eric Auger) - Fix vfio_device_get_from_name() return value (Joerg Roedel) - No-IOMMU interface (Alex Williamson) - Fix potential out of bounds array access in PCI config handling (Dan Carpenter) * tag 'vfio-v4.4-rc1' of git://github.com/awilliam/linux-vfio: vfio/pci: make an array larger vfio: Include No-IOMMU mode vfio: Fix bug in vfio_device_get_from_name() VFIO: platform: reset: AMD xgbe reset module vfio: platform: reset: calxedaxgmac: fix ioaddr leak vfio: platform: add dev_info on device reset vfio: platform: use list of registered reset function vfio: platform: add compat in vfio_platform_device vfio: platform: reset: calxedaxgmac: add reset function registration vfio: platform: introduce module_vfio_reset_handler macro vfio: platform: add capability to register a reset function vfio: platform: introduce vfio-platform-base module vfio/platform: store mapped memory in region, instead of an on-stack copy vfio/type1: handle case where IOMMU does not support PAGE_SIZE size VFIO: platform: clear IRQ_NOAUTOEN when de-assigning the IRQ vfio/pci: Use kernel VPD access functions vfio: Whitelist PCI bridges
2 parents f3996e6 + 222e684 commit 934f98d

17 files changed

+616
-90
lines changed

drivers/vfio/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@ menuconfig VFIO
3131

3232
If you don't know what to do here, say N.
3333

34+
menuconfig VFIO_NOIOMMU
35+
bool "VFIO No-IOMMU support"
36+
depends on VFIO
37+
help
38+
VFIO is built on the ability to isolate devices using the IOMMU.
39+
Only with an IOMMU can userspace access to DMA capable devices be
40+
considered secure. VFIO No-IOMMU mode enables IOMMU groups for
41+
devices without IOMMU backing for the purpose of re-using the VFIO
42+
infrastructure in a non-secure mode. Use of this mode will result
43+
in an unsupportable kernel and will therefore taint the kernel.
44+
Device assignment to virtual machines is also not possible with
45+
this mode since there is no IOMMU to provide DMA translation.
46+
47+
If you don't know what to do here, say N.
48+
3449
source "drivers/vfio/pci/Kconfig"
3550
source "drivers/vfio/platform/Kconfig"
3651
source "virt/lib/Kconfig"

drivers/vfio/pci/vfio_pci.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -940,13 +940,13 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
940940
if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
941941
return -EINVAL;
942942

943-
group = iommu_group_get(&pdev->dev);
943+
group = vfio_iommu_group_get(&pdev->dev);
944944
if (!group)
945945
return -EINVAL;
946946

947947
vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
948948
if (!vdev) {
949-
iommu_group_put(group);
949+
vfio_iommu_group_put(group, &pdev->dev);
950950
return -ENOMEM;
951951
}
952952

@@ -957,7 +957,7 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
957957

958958
ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev);
959959
if (ret) {
960-
iommu_group_put(group);
960+
vfio_iommu_group_put(group, &pdev->dev);
961961
kfree(vdev);
962962
return ret;
963963
}
@@ -993,7 +993,7 @@ static void vfio_pci_remove(struct pci_dev *pdev)
993993
if (!vdev)
994994
return;
995995

996-
iommu_group_put(pdev->dev.iommu_group);
996+
vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
997997
kfree(vdev);
998998

999999
if (vfio_pci_is_vga(pdev)) {

drivers/vfio/pci/vfio_pci_config.c

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
* 0: Removed from the user visible capability list
4747
* FF: Variable length
4848
*/
49-
static u8 pci_cap_length[] = {
49+
static const u8 pci_cap_length[PCI_CAP_ID_MAX + 1] = {
5050
[PCI_CAP_ID_BASIC] = PCI_STD_HEADER_SIZEOF, /* pci config header */
5151
[PCI_CAP_ID_PM] = PCI_PM_SIZEOF,
5252
[PCI_CAP_ID_AGP] = PCI_AGP_SIZEOF,
@@ -74,7 +74,7 @@ static u8 pci_cap_length[] = {
7474
* 0: Removed or masked from the user visible capabilty list
7575
* FF: Variable length
7676
*/
77-
static u16 pci_ext_cap_length[] = {
77+
static const u16 pci_ext_cap_length[PCI_EXT_CAP_ID_MAX + 1] = {
7878
[PCI_EXT_CAP_ID_ERR] = PCI_ERR_ROOT_COMMAND,
7979
[PCI_EXT_CAP_ID_VC] = 0xFF,
8080
[PCI_EXT_CAP_ID_DSN] = PCI_EXT_CAP_DSN_SIZEOF,
@@ -671,6 +671,73 @@ static int __init init_pci_cap_pm_perm(struct perm_bits *perm)
671671
return 0;
672672
}
673673

674+
static int vfio_vpd_config_write(struct vfio_pci_device *vdev, int pos,
675+
int count, struct perm_bits *perm,
676+
int offset, __le32 val)
677+
{
678+
struct pci_dev *pdev = vdev->pdev;
679+
__le16 *paddr = (__le16 *)(vdev->vconfig + pos - offset + PCI_VPD_ADDR);
680+
__le32 *pdata = (__le32 *)(vdev->vconfig + pos - offset + PCI_VPD_DATA);
681+
u16 addr;
682+
u32 data;
683+
684+
/*
685+
* Write through to emulation. If the write includes the upper byte
686+
* of PCI_VPD_ADDR, then the PCI_VPD_ADDR_F bit is written and we
687+
* have work to do.
688+
*/
689+
count = vfio_default_config_write(vdev, pos, count, perm, offset, val);
690+
if (count < 0 || offset > PCI_VPD_ADDR + 1 ||
691+
offset + count <= PCI_VPD_ADDR + 1)
692+
return count;
693+
694+
addr = le16_to_cpu(*paddr);
695+
696+
if (addr & PCI_VPD_ADDR_F) {
697+
data = le32_to_cpu(*pdata);
698+
if (pci_write_vpd(pdev, addr & ~PCI_VPD_ADDR_F, 4, &data) != 4)
699+
return count;
700+
} else {
701+
if (pci_read_vpd(pdev, addr, 4, &data) != 4)
702+
return count;
703+
*pdata = cpu_to_le32(data);
704+
}
705+
706+
/*
707+
* Toggle PCI_VPD_ADDR_F in the emulated PCI_VPD_ADDR register to
708+
* signal completion. If an error occurs above, we assume that not
709+
* toggling this bit will induce a driver timeout.
710+
*/
711+
addr ^= PCI_VPD_ADDR_F;
712+
*paddr = cpu_to_le16(addr);
713+
714+
return count;
715+
}
716+
717+
/* Permissions for Vital Product Data capability */
718+
static int __init init_pci_cap_vpd_perm(struct perm_bits *perm)
719+
{
720+
if (alloc_perm_bits(perm, pci_cap_length[PCI_CAP_ID_VPD]))
721+
return -ENOMEM;
722+
723+
perm->writefn = vfio_vpd_config_write;
724+
725+
/*
726+
* We always virtualize the next field so we can remove
727+
* capabilities from the chain if we want to.
728+
*/
729+
p_setb(perm, PCI_CAP_LIST_NEXT, (u8)ALL_VIRT, NO_WRITE);
730+
731+
/*
732+
* Both the address and data registers are virtualized to
733+
* enable access through the pci_vpd_read/write functions
734+
*/
735+
p_setw(perm, PCI_VPD_ADDR, (u16)ALL_VIRT, (u16)ALL_WRITE);
736+
p_setd(perm, PCI_VPD_DATA, ALL_VIRT, ALL_WRITE);
737+
738+
return 0;
739+
}
740+
674741
/* Permissions for PCI-X capability */
675742
static int __init init_pci_cap_pcix_perm(struct perm_bits *perm)
676743
{
@@ -790,6 +857,7 @@ void vfio_pci_uninit_perm_bits(void)
790857
free_perm_bits(&cap_perms[PCI_CAP_ID_BASIC]);
791858

792859
free_perm_bits(&cap_perms[PCI_CAP_ID_PM]);
860+
free_perm_bits(&cap_perms[PCI_CAP_ID_VPD]);
793861
free_perm_bits(&cap_perms[PCI_CAP_ID_PCIX]);
794862
free_perm_bits(&cap_perms[PCI_CAP_ID_EXP]);
795863
free_perm_bits(&cap_perms[PCI_CAP_ID_AF]);
@@ -807,7 +875,7 @@ int __init vfio_pci_init_perm_bits(void)
807875

808876
/* Capabilities */
809877
ret |= init_pci_cap_pm_perm(&cap_perms[PCI_CAP_ID_PM]);
810-
cap_perms[PCI_CAP_ID_VPD].writefn = vfio_raw_config_write;
878+
ret |= init_pci_cap_vpd_perm(&cap_perms[PCI_CAP_ID_VPD]);
811879
ret |= init_pci_cap_pcix_perm(&cap_perms[PCI_CAP_ID_PCIX]);
812880
cap_perms[PCI_CAP_ID_VNDR].writefn = vfio_raw_config_write;
813881
ret |= init_pci_cap_exp_perm(&cap_perms[PCI_CAP_ID_EXP]);

drivers/vfio/platform/Makefile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
2-
vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
1+
vfio-platform-base-y := vfio_platform_common.o vfio_platform_irq.o
2+
vfio-platform-y := vfio_platform.o
33

44
obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
5+
obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform-base.o
56
obj-$(CONFIG_VFIO_PLATFORM) += reset/
67

78
vfio-amba-y := vfio_amba.o
89

910
obj-$(CONFIG_VFIO_AMBA) += vfio-amba.o
11+
obj-$(CONFIG_VFIO_AMBA) += vfio-platform-base.o
1012
obj-$(CONFIG_VFIO_AMBA) += reset/

drivers/vfio/platform/reset/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,11 @@ config VFIO_PLATFORM_CALXEDAXGMAC_RESET
55
Enables the VFIO platform driver to handle reset for Calxeda xgmac
66

77
If you don't know what to do here, say N.
8+
9+
config VFIO_PLATFORM_AMDXGBE_RESET
10+
tristate "VFIO support for AMD XGBE reset"
11+
depends on VFIO_PLATFORM
12+
help
13+
Enables the VFIO platform driver to handle reset for AMD XGBE
14+
15+
If you don't know what to do here, say N.

drivers/vfio/platform/reset/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
vfio-platform-calxedaxgmac-y := vfio_platform_calxedaxgmac.o
2+
vfio-platform-amdxgbe-y := vfio_platform_amdxgbe.o
23

34
ccflags-y += -Idrivers/vfio/platform
45

56
obj-$(CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET) += vfio-platform-calxedaxgmac.o
7+
obj-$(CONFIG_VFIO_PLATFORM_AMDXGBE_RESET) += vfio-platform-amdxgbe.o
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* VFIO platform driver specialized for AMD xgbe reset
3+
* reset code is inherited from AMD xgbe native driver
4+
*
5+
* Copyright (c) 2015 Linaro Ltd.
6+
* www.linaro.org
7+
*
8+
* This program is free software; you can redistribute it and/or modify it
9+
* under the terms and conditions of the GNU General Public License,
10+
* version 2, as published by the Free Software Foundation.
11+
*
12+
* This program is distributed in the hope it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15+
* more details.
16+
*
17+
* You should have received a copy of the GNU General Public License along with
18+
* this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
#include <linux/module.h>
22+
#include <linux/kernel.h>
23+
#include <linux/init.h>
24+
#include <linux/io.h>
25+
#include <uapi/linux/mdio.h>
26+
#include <linux/delay.h>
27+
28+
#include "vfio_platform_private.h"
29+
30+
#define DMA_MR 0x3000
31+
#define MAC_VR 0x0110
32+
#define DMA_ISR 0x3008
33+
#define MAC_ISR 0x00b0
34+
#define PCS_MMD_SELECT 0xff
35+
#define MDIO_AN_INT 0x8002
36+
#define MDIO_AN_INTMASK 0x8001
37+
38+
static unsigned int xmdio_read(void *ioaddr, unsigned int mmd,
39+
unsigned int reg)
40+
{
41+
unsigned int mmd_address, value;
42+
43+
mmd_address = (mmd << 16) | ((reg) & 0xffff);
44+
iowrite32(mmd_address >> 8, ioaddr + (PCS_MMD_SELECT << 2));
45+
value = ioread32(ioaddr + ((mmd_address & 0xff) << 2));
46+
return value;
47+
}
48+
49+
static void xmdio_write(void *ioaddr, unsigned int mmd,
50+
unsigned int reg, unsigned int value)
51+
{
52+
unsigned int mmd_address;
53+
54+
mmd_address = (mmd << 16) | ((reg) & 0xffff);
55+
iowrite32(mmd_address >> 8, ioaddr + (PCS_MMD_SELECT << 2));
56+
iowrite32(value, ioaddr + ((mmd_address & 0xff) << 2));
57+
}
58+
59+
int vfio_platform_amdxgbe_reset(struct vfio_platform_device *vdev)
60+
{
61+
struct vfio_platform_region *xgmac_regs = &vdev->regions[0];
62+
struct vfio_platform_region *xpcs_regs = &vdev->regions[1];
63+
u32 dma_mr_value, pcs_value, value;
64+
unsigned int count;
65+
66+
if (!xgmac_regs->ioaddr) {
67+
xgmac_regs->ioaddr =
68+
ioremap_nocache(xgmac_regs->addr, xgmac_regs->size);
69+
if (!xgmac_regs->ioaddr)
70+
return -ENOMEM;
71+
}
72+
if (!xpcs_regs->ioaddr) {
73+
xpcs_regs->ioaddr =
74+
ioremap_nocache(xpcs_regs->addr, xpcs_regs->size);
75+
if (!xpcs_regs->ioaddr)
76+
return -ENOMEM;
77+
}
78+
79+
/* reset the PHY through MDIO*/
80+
pcs_value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_PCS, MDIO_CTRL1);
81+
pcs_value |= MDIO_CTRL1_RESET;
82+
xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_PCS, MDIO_CTRL1, pcs_value);
83+
84+
count = 50;
85+
do {
86+
msleep(20);
87+
pcs_value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_PCS,
88+
MDIO_CTRL1);
89+
} while ((pcs_value & MDIO_CTRL1_RESET) && --count);
90+
91+
if (pcs_value & MDIO_CTRL1_RESET)
92+
pr_warn("%s XGBE PHY reset timeout\n", __func__);
93+
94+
/* disable auto-negotiation */
95+
value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_CTRL1);
96+
value &= ~MDIO_AN_CTRL1_ENABLE;
97+
xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_CTRL1, value);
98+
99+
/* disable AN IRQ */
100+
xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
101+
102+
/* clear AN IRQ */
103+
xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_AN_INT, 0);
104+
105+
/* MAC software reset */
106+
dma_mr_value = ioread32(xgmac_regs->ioaddr + DMA_MR);
107+
dma_mr_value |= 0x1;
108+
iowrite32(dma_mr_value, xgmac_regs->ioaddr + DMA_MR);
109+
110+
usleep_range(10, 15);
111+
112+
count = 2000;
113+
while (count-- && (ioread32(xgmac_regs->ioaddr + DMA_MR) & 1))
114+
usleep_range(500, 600);
115+
116+
if (!count)
117+
pr_warn("%s MAC SW reset failed\n", __func__);
118+
119+
return 0;
120+
}
121+
122+
module_vfio_reset_handler("amd,xgbe-seattle-v1a", vfio_platform_amdxgbe_reset);
123+
124+
MODULE_VERSION("0.1");
125+
MODULE_LICENSE("GPL v2");
126+
MODULE_AUTHOR("Eric Auger <eric.auger@linaro.org>");
127+
MODULE_DESCRIPTION("Reset support for AMD xgbe vfio platform device");

drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
#define DRIVER_AUTHOR "Eric Auger <eric.auger@linaro.org>"
3131
#define DRIVER_DESC "Reset support for Calxeda xgmac vfio platform device"
3232

33-
#define CALXEDAXGMAC_COMPAT "calxeda,hb-xgmac"
34-
3533
/* XGMAC Register definitions */
3634
#define XGMAC_CONTROL 0x00000000 /* MAC Configuration */
3735

@@ -61,24 +59,25 @@ static inline void xgmac_mac_disable(void __iomem *ioaddr)
6159

6260
int vfio_platform_calxedaxgmac_reset(struct vfio_platform_device *vdev)
6361
{
64-
struct vfio_platform_region reg = vdev->regions[0];
62+
struct vfio_platform_region *reg = &vdev->regions[0];
6563

66-
if (!reg.ioaddr) {
67-
reg.ioaddr =
68-
ioremap_nocache(reg.addr, reg.size);
69-
if (!reg.ioaddr)
64+
if (!reg->ioaddr) {
65+
reg->ioaddr =
66+
ioremap_nocache(reg->addr, reg->size);
67+
if (!reg->ioaddr)
7068
return -ENOMEM;
7169
}
7270

7371
/* disable IRQ */
74-
writel(0, reg.ioaddr + XGMAC_DMA_INTR_ENA);
72+
writel(0, reg->ioaddr + XGMAC_DMA_INTR_ENA);
7573

7674
/* Disable the MAC core */
77-
xgmac_mac_disable(reg.ioaddr);
75+
xgmac_mac_disable(reg->ioaddr);
7876

7977
return 0;
8078
}
81-
EXPORT_SYMBOL_GPL(vfio_platform_calxedaxgmac_reset);
79+
80+
module_vfio_reset_handler("calxeda,hb-xgmac", vfio_platform_calxedaxgmac_reset);
8281

8382
MODULE_VERSION(DRIVER_VERSION);
8483
MODULE_LICENSE("GPL v2");

drivers/vfio/platform/vfio_amba.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
6767
vdev->flags = VFIO_DEVICE_FLAGS_AMBA;
6868
vdev->get_resource = get_amba_resource;
6969
vdev->get_irq = get_amba_irq;
70+
vdev->parent_module = THIS_MODULE;
7071

7172
ret = vfio_platform_probe_common(vdev, &adev->dev);
7273
if (ret) {

drivers/vfio/platform/vfio_platform.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ static int vfio_platform_probe(struct platform_device *pdev)
6565
vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM;
6666
vdev->get_resource = get_platform_resource;
6767
vdev->get_irq = get_platform_irq;
68+
vdev->parent_module = THIS_MODULE;
6869

6970
ret = vfio_platform_probe_common(vdev, &pdev->dev);
7071
if (ret)

0 commit comments

Comments
 (0)