xen: bug fixes for 4.0-rc3
- Fix a PV regression in 3.19. - Fix a dom0 crash on hosts with large numbers of PIRQs. - Prevent pcifront from disabling memory or I/O port access, which may trigger host crashes. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQEcBAABAgAGBQJVAx7tAAoJEFxbo/MsZsTRBFwH/2Uoza52iMRhHkC6kLRSAhTQ HxRbObmweDQCqru25IgDsX+09TqCcWMtqnUTwJ5KPt0ZiwPA4GS0n4InJ9ZbrhBM 9lXSWFfCKPUuhL6tyACQul5W4SDmZD0UHNl5uQYMH/C8UhktrdjF+CdUO3AvBAWU uMfwzNsI0HH0uPHhZv6npUoGgI7Pt2Vw7KOilZKCnRBztizQpLb+KUTTBKJT1YDN TsA10rQcmdVMd0Qjry0O0V2Hn3EWwA/1rMl29/6lf5dTcCdQVW1FK2X7B3DXh71D rZKkZYXkXRIcMRzy7JybumIuXfB21nw2jD32ItLFjYjrj7y0H3zxYuLEyocexkc= =pFjm -----END PGP SIGNATURE----- Merge tag 'stable/for-linus-4.0-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip Pull xen bug fixes from David Vrabel: - fix a PV regression in 3.19. - fix a dom0 crash on hosts with large numbers of PIRQs. - prevent pcifront from disabling memory or I/O port access, which may trigger host crashes. * tag 'stable/for-linus-4.0-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen-pciback: limit guest control of command register xen/events: avoid NULL pointer dereference in dom0 on large machines xen: Remove trailing semicolon from xenbus_register_frontend() definition x86/xen: correct bug in p2m list initialization
This commit is contained in:
commit
f47e331042
6 changed files with 65 additions and 22 deletions
|
@ -563,7 +563,7 @@ static bool alloc_p2m(unsigned long pfn)
|
|||
if (p2m_pfn == PFN_DOWN(__pa(p2m_missing)))
|
||||
p2m_init(p2m);
|
||||
else
|
||||
p2m_init_identity(p2m, pfn);
|
||||
p2m_init_identity(p2m, pfn & ~(P2M_PER_PAGE - 1));
|
||||
|
||||
spin_lock_irqsave(&p2m_update_lock, flags);
|
||||
|
||||
|
|
|
@ -526,20 +526,26 @@ static unsigned int __startup_pirq(unsigned int irq)
|
|||
pirq_query_unmask(irq);
|
||||
|
||||
rc = set_evtchn_to_irq(evtchn, irq);
|
||||
if (rc != 0) {
|
||||
pr_err("irq%d: Failed to set port to irq mapping (%d)\n",
|
||||
irq, rc);
|
||||
xen_evtchn_close(evtchn);
|
||||
return 0;
|
||||
}
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
bind_evtchn_to_cpu(evtchn, 0);
|
||||
info->evtchn = evtchn;
|
||||
|
||||
rc = xen_evtchn_port_setup(info);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
out:
|
||||
unmask_evtchn(evtchn);
|
||||
eoi_pirq(irq_get_irq_data(irq));
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc);
|
||||
xen_evtchn_close(evtchn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int startup_pirq(struct irq_data *data)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "conf_space.h"
|
||||
#include "conf_space_quirks.h"
|
||||
|
||||
static bool permissive;
|
||||
bool permissive;
|
||||
module_param(permissive, bool, 0644);
|
||||
|
||||
/* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word,
|
||||
|
|
|
@ -64,6 +64,8 @@ struct config_field_entry {
|
|||
void *data;
|
||||
};
|
||||
|
||||
extern bool permissive;
|
||||
|
||||
#define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
|
||||
|
||||
/* Add fields to a device - the add_fields macro expects to get a pointer to
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
#include "pciback.h"
|
||||
#include "conf_space.h"
|
||||
|
||||
struct pci_cmd_info {
|
||||
u16 val;
|
||||
};
|
||||
|
||||
struct pci_bar_info {
|
||||
u32 val;
|
||||
u32 len_val;
|
||||
|
@ -20,21 +24,35 @@ struct pci_bar_info {
|
|||
#define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
|
||||
#define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
|
||||
|
||||
/* Bits guests are allowed to control in permissive mode. */
|
||||
#define PCI_COMMAND_GUEST (PCI_COMMAND_MASTER|PCI_COMMAND_SPECIAL| \
|
||||
PCI_COMMAND_INVALIDATE|PCI_COMMAND_VGA_PALETTE| \
|
||||
PCI_COMMAND_WAIT|PCI_COMMAND_FAST_BACK)
|
||||
|
||||
static void *command_init(struct pci_dev *dev, int offset)
|
||||
{
|
||||
struct pci_cmd_info *cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
int err;
|
||||
|
||||
if (!cmd)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
err = pci_read_config_word(dev, PCI_COMMAND, &cmd->val);
|
||||
if (err) {
|
||||
kfree(cmd);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
int ret = pci_read_config_word(dev, offset, value);
|
||||
const struct pci_cmd_info *cmd = data;
|
||||
|
||||
ret = xen_pcibk_read_config_word(dev, offset, value, data);
|
||||
if (!pci_is_enabled(dev))
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < PCI_ROM_RESOURCE; i++) {
|
||||
if (dev->resource[i].flags & IORESOURCE_IO)
|
||||
*value |= PCI_COMMAND_IO;
|
||||
if (dev->resource[i].flags & IORESOURCE_MEM)
|
||||
*value |= PCI_COMMAND_MEMORY;
|
||||
}
|
||||
*value &= PCI_COMMAND_GUEST;
|
||||
*value |= cmd->val & ~PCI_COMMAND_GUEST;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -43,6 +61,8 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
|
|||
{
|
||||
struct xen_pcibk_dev_data *dev_data;
|
||||
int err;
|
||||
u16 val;
|
||||
struct pci_cmd_info *cmd = data;
|
||||
|
||||
dev_data = pci_get_drvdata(dev);
|
||||
if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
|
||||
|
@ -83,6 +103,19 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
cmd->val = value;
|
||||
|
||||
if (!permissive && (!dev_data || !dev_data->permissive))
|
||||
return 0;
|
||||
|
||||
/* Only allow the guest to control certain bits. */
|
||||
err = pci_read_config_word(dev, offset, &val);
|
||||
if (err || val == value)
|
||||
return err;
|
||||
|
||||
value &= PCI_COMMAND_GUEST;
|
||||
value |= val & ~PCI_COMMAND_GUEST;
|
||||
|
||||
return pci_write_config_word(dev, offset, value);
|
||||
}
|
||||
|
||||
|
@ -282,6 +315,8 @@ static const struct config_field header_common[] = {
|
|||
{
|
||||
.offset = PCI_COMMAND,
|
||||
.size = 2,
|
||||
.init = command_init,
|
||||
.release = bar_release,
|
||||
.u.w.read = command_read,
|
||||
.u.w.write = command_write,
|
||||
},
|
||||
|
|
|
@ -114,9 +114,9 @@ int __must_check __xenbus_register_backend(struct xenbus_driver *drv,
|
|||
const char *mod_name);
|
||||
|
||||
#define xenbus_register_frontend(drv) \
|
||||
__xenbus_register_frontend(drv, THIS_MODULE, KBUILD_MODNAME);
|
||||
__xenbus_register_frontend(drv, THIS_MODULE, KBUILD_MODNAME)
|
||||
#define xenbus_register_backend(drv) \
|
||||
__xenbus_register_backend(drv, THIS_MODULE, KBUILD_MODNAME);
|
||||
__xenbus_register_backend(drv, THIS_MODULE, KBUILD_MODNAME)
|
||||
|
||||
void xenbus_unregister_driver(struct xenbus_driver *drv);
|
||||
|
||||
|
|
Loading…
Reference in a new issue