Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f47e3310 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents bbc54a00 af6fc858
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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);

+12 −6
Original line number Diff line number Diff line
@@ -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)
+1 −1
Original line number Diff line number Diff line
@@ -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,
+2 −0
Original line number Diff line number Diff line
@@ -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
+48 −13
Original line number Diff line number Diff line
@@ -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,22 +24,36 @@ 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;
	struct pci_cmd_info *cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
	int err;

	ret = xen_pcibk_read_config_word(dev, offset, value, data);
	if (!pci_is_enabled(dev))
		return ret;
	if (!cmd)
		return ERR_PTR(-ENOMEM);

	err = pci_read_config_word(dev, PCI_COMMAND, &cmd->val);
	if (err) {
		kfree(cmd);
		return ERR_PTR(err);
	}

	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;
	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;
}

@@ -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,
	},
Loading