Skip to content

Commit

Permalink
Merge tag 'stable/for-linus-4.0-rc3-tag' of git://git.kernel.org/pub/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
torvalds committed Mar 13, 2015
2 parents bbc54a0 + af6fc85 commit f47e331
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 23 deletions.
2 changes: 1 addition & 1 deletion arch/x86/xen/p2m.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
18 changes: 12 additions & 6 deletions drivers/xen/events/events_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion drivers/xen/xen-pciback/conf_space.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions drivers/xen/xen-pciback/conf_space.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
61 changes: 48 additions & 13 deletions drivers/xen/xen-pciback/conf_space_header.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,29 +24,45 @@ 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)

static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
/* 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)
{
int i;
int ret;

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;
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 ret = pci_read_config_word(dev, offset, value);
const struct pci_cmd_info *cmd = data;

*value &= PCI_COMMAND_GUEST;
*value |= cmd->val & ~PCI_COMMAND_GUEST;

return ret;
}

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)) {
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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,
},
Expand Down
4 changes: 2 additions & 2 deletions include/xen/xenbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit f47e331

Please sign in to comment.