#include <linux/init.h>
#include <linux/types.h>
#include <linux/list.h>
+ #include <linux/serial_core.h>
#include <asm/io.h>
#include <asm/xen/hypervisor.h>
return recv;
}
-static struct hv_ops domU_hvc_ops = {
+static const struct hv_ops domU_hvc_ops = {
.get_chars = domU_read_console,
.put_chars = domU_write_console,
.notifier_add = notifier_add_irq,
return len;
}
-static struct hv_ops dom0_hvc_ops = {
+static const struct hv_ops dom0_hvc_ops = {
.get_chars = dom0_read_console,
.put_chars = dom0_write_console,
.notifier_add = notifier_add_irq,
return -ENODEV;
}
+ static int xencons_info_pv_init(struct xencons_info *info, int vtermno)
+ {
+ info->evtchn = xen_start_info->console.domU.evtchn;
+ /* GFN == MFN for PV guest */
+ info->intf = gfn_to_virt(xen_start_info->console.domU.mfn);
+ info->vtermno = vtermno;
+
+ list_add_tail(&info->list, &xenconsoles);
+
+ return 0;
+ }
+
static int xen_pv_console_init(void)
{
struct xencons_info *info;
/* already configured */
return 0;
}
- info->evtchn = xen_start_info->console.domU.evtchn;
- /* GFN == MFN for PV guest */
- info->intf = gfn_to_virt(xen_start_info->console.domU.mfn);
- info->vtermno = HVC_COOKIE;
-
spin_lock(&xencons_lock);
- list_add_tail(&info->list, &xenconsoles);
+ xencons_info_pv_init(info, HVC_COOKIE);
spin_unlock(&xencons_lock);
return 0;
}
}
+#ifdef CONFIG_HVC_XEN_FRONTEND
static void xencons_disconnect_backend(struct xencons_info *info)
{
if (info->irq > 0)
return 0;
}
-#ifdef CONFIG_HVC_XEN_FRONTEND
static int xencons_remove(struct xenbus_device *dev)
{
return xen_console_remove(dev_get_drvdata(&dev->dev));
}
console_initcall(xen_cons_init);
+ #ifdef CONFIG_X86
+ static void xen_hvm_early_write(uint32_t vtermno, const char *str, int len)
+ {
+ if (xen_cpuid_base())
+ outsb(0xe9, str, len);
+ }
+ #else
+ static void xen_hvm_early_write(uint32_t vtermno, const char *str, int len) { }
+ #endif
+
#ifdef CONFIG_EARLY_PRINTK
+ static int __init xenboot_setup_console(struct console *console, char *string)
+ {
+ static struct xencons_info xenboot;
+
+ if (xen_initial_domain())
+ return 0;
+ if (!xen_pv_domain())
+ return -ENODEV;
+
+ return xencons_info_pv_init(&xenboot, 0);
+ }
+
static void xenboot_write_console(struct console *console, const char *string,
unsigned len)
{
unsigned int linelen, off = 0;
const char *pos;
- if (!xen_pv_domain())
+ if (!xen_pv_domain()) {
+ xen_hvm_early_write(0, string, len);
return;
+ }
dom0_write_console(0, string, len);
struct console xenboot_console = {
.name = "xenboot",
.write = xenboot_write_console,
+ .setup = xenboot_setup_console,
.flags = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
.index = -1,
};
if (xen_domain()) {
rc = dom0_write_console(0, str, len);
- #ifdef CONFIG_X86
- if (rc == -ENOSYS && xen_hvm_domain())
- goto outb_print;
-
- } else if (xen_cpuid_base()) {
- int i;
- outb_print:
- for (i = 0; i < len; i++)
- outb(str[i], 0xe9);
- #endif
+ if (rc != -ENOSYS || !xen_hvm_domain())
+ return;
}
+ xen_hvm_early_write(0, str, len);
}
void xen_raw_printk(const char *fmt, ...)
xen_raw_console_write(buf);
}
+
+ static void xenboot_earlycon_write(struct console *console,
+ const char *string,
+ unsigned len)
+ {
+ dom0_write_console(0, string, len);
+ }
+
+ static int __init xenboot_earlycon_setup(struct earlycon_device *device,
+ const char *opt)
+ {
+ device->con->write = xenboot_earlycon_write;
+ return 0;
+ }
+ EARLYCON_DECLARE(xenboot, xenboot_earlycon_setup);
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
- #include <linux/module.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
#include <linux/pagemap.h>
return NULL;
res->name = "System RAM";
- res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
ret = allocate_resource(&iomem_resource, res,
size, 0, -1,
}
#endif
- rc = add_memory_resource(nid, resource);
+ /*
+ * add_memory_resource() will call online_pages() which in its turn
+ * will call xen_online_page() callback causing deadlock if we don't
+ * release balloon_mutex here. Unlocking here is safe because the
+ * callers drop the mutex before trying again.
+ */
+ mutex_unlock(&balloon_mutex);
+ rc = add_memory_resource(nid, resource, memhp_auto_online);
+ mutex_lock(&balloon_mutex);
+
if (rc) {
pr_warn("Cannot add additional memory (%i)\n", rc);
goto err;
return 0;
}
-
subsys_initcall(balloon_init);
-
- MODULE_LICENSE("GPL");
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/module.h>
+ #include <linux/moduleparam.h>
#include <linux/wait.h>
#include <linux/bitops.h>
#include <xen/events.h>
/*
* PCI_COMMAND_MEMORY must be enabled, otherwise we may not be able
* to access the BARs where the MSI-X entries reside.
+ * But VF devices are unique in which the PF needs to be checked.
*/
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ pci_read_config_word(pci_physfn(dev), PCI_COMMAND, &cmd);
if (dev->msi_enabled || !(cmd & PCI_COMMAND_MEMORY))
return -ENXIO;
struct xen_pcibk_dev_data *dev_data = NULL;
struct xen_pci_op *op = &pdev->op;
int test_intx = 0;
+#ifdef CONFIG_PCI_MSI
+ unsigned int nr = 0;
+#endif
*op = pdev->sh_info->op;
barrier();
op->err = xen_pcibk_disable_msi(pdev, dev, op);
break;
case XEN_PCI_OP_enable_msix:
+ nr = op->value;
op->err = xen_pcibk_enable_msix(pdev, dev, op);
break;
case XEN_PCI_OP_disable_msix:
if (op->cmd == XEN_PCI_OP_enable_msix && op->err == 0) {
unsigned int i;
- for (i = 0; i < op->value; i++)
+ for (i = 0; i < nr; i++)
pdev->sh_info->op.msix_entries[i].vector =
op->msix_entries[i].vector;
}