mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Merge branch 'upstream/pvhvm' into upstream/xen
* upstream/pvhvm: Introduce CONFIG_XEN_PVHVM compile option blkfront: do not create a PV cdrom device if xen_hvm_guest support multiple .discard.* sections to avoid section type conflicts xen/pvhvm: fix build problem when !CONFIG_XEN xenfs: enable for HVM domains too x86: Call HVMOP_pagetable_dying on exit_mmap. x86: Unplug emulated disks and nics. x86: Use xen_vcpuop_clockevent, xen_clocksource and xen wallclock. xen: Fix find_unbound_irq in presence of ioapic irqs. xen: Add suspend/resume support for PV on HVM guests. xen: Xen PCI platform device driver. x86/xen: event channels delivery on HVM. x86: early PV on HVM features initialization. xen: Add support for HVM hypercalls. Conflicts: arch/x86/xen/enlighten.c arch/x86/xen/time.c
This commit is contained in:
commit
ca50a5f390
39 changed files with 1156 additions and 61 deletions
|
|
@ -62,4 +62,13 @@ config XEN_SYS_HYPERVISOR
|
|||
virtual environment, /sys/hypervisor will still be present,
|
||||
but will have no xen contents.
|
||||
|
||||
config XEN_PLATFORM_PCI
|
||||
tristate "xen platform pci device driver"
|
||||
depends on XEN_PVHVM
|
||||
default m
|
||||
help
|
||||
Driver for the Xen PCI Platform device: it is responsible for
|
||||
initializing xenbus and grant_table when running in a Xen HVM
|
||||
domain. As a consequence this driver is required to run any Xen PV
|
||||
frontend on Xen HVM.
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -9,4 +9,5 @@ obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
|
|||
obj-$(CONFIG_XEN_BALLOON) += balloon.o
|
||||
obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o
|
||||
obj-$(CONFIG_XENFS) += xenfs/
|
||||
obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
|
||||
obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
|
||||
obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/bootmem.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/desc.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/idle.h>
|
||||
|
|
@ -36,10 +37,14 @@
|
|||
#include <asm/xen/hypercall.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
|
||||
#include <xen/xen.h>
|
||||
#include <xen/hvm.h>
|
||||
#include <xen/xen-ops.h>
|
||||
#include <xen/events.h>
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/event_channel.h>
|
||||
#include <xen/interface/hvm/hvm_op.h>
|
||||
#include <xen/interface/hvm/params.h>
|
||||
|
||||
/*
|
||||
* This lock protects updates to the following mapping and reference-count
|
||||
|
|
@ -335,9 +340,18 @@ static int find_unbound_irq(void)
|
|||
int irq;
|
||||
struct irq_desc *desc;
|
||||
|
||||
for (irq = 0; irq < nr_irqs; irq++)
|
||||
for (irq = 0; irq < nr_irqs; irq++) {
|
||||
desc = irq_to_desc(irq);
|
||||
/* only 0->15 have init'd desc; handle irq > 16 */
|
||||
if (desc == NULL)
|
||||
break;
|
||||
if (desc->chip == &no_irq_chip)
|
||||
break;
|
||||
if (desc->chip != &xen_dynamic_chip)
|
||||
continue;
|
||||
if (irq_info[irq].type == IRQT_UNBOUND)
|
||||
break;
|
||||
}
|
||||
|
||||
if (irq == nr_irqs)
|
||||
panic("No available IRQ to bind to: increase nr_irqs!\n");
|
||||
|
|
@ -346,7 +360,7 @@ static int find_unbound_irq(void)
|
|||
if (WARN_ON(desc == NULL))
|
||||
return -1;
|
||||
|
||||
dynamic_irq_init(irq);
|
||||
dynamic_irq_init_keep_chip_data(irq);
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
|
@ -617,17 +631,13 @@ static DEFINE_PER_CPU(unsigned, xed_nesting_count);
|
|||
* a bitset of words which contain pending event bits. The second
|
||||
* level is a bitset of pending events themselves.
|
||||
*/
|
||||
void xen_evtchn_do_upcall(struct pt_regs *regs)
|
||||
static void __xen_evtchn_do_upcall(void)
|
||||
{
|
||||
int cpu = get_cpu();
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
struct shared_info *s = HYPERVISOR_shared_info;
|
||||
struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
|
||||
unsigned count;
|
||||
|
||||
exit_idle();
|
||||
irq_enter();
|
||||
|
||||
do {
|
||||
unsigned long pending_words;
|
||||
|
||||
|
|
@ -664,15 +674,32 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
|
|||
|
||||
count = __get_cpu_var(xed_nesting_count);
|
||||
__get_cpu_var(xed_nesting_count) = 0;
|
||||
} while(count != 1);
|
||||
} while (count != 1 || vcpu_info->evtchn_upcall_pending);
|
||||
|
||||
out:
|
||||
irq_exit();
|
||||
set_irq_regs(old_regs);
|
||||
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
void xen_evtchn_do_upcall(struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
|
||||
exit_idle();
|
||||
irq_enter();
|
||||
|
||||
__xen_evtchn_do_upcall();
|
||||
|
||||
irq_exit();
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
void xen_hvm_evtchn_do_upcall(void)
|
||||
{
|
||||
__xen_evtchn_do_upcall();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xen_hvm_evtchn_do_upcall);
|
||||
|
||||
/* Rebind a new event channel to an existing irq. */
|
||||
void rebind_evtchn_irq(int evtchn, int irq)
|
||||
{
|
||||
|
|
@ -708,7 +735,10 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
|
|||
struct evtchn_bind_vcpu bind_vcpu;
|
||||
int evtchn = evtchn_from_irq(irq);
|
||||
|
||||
if (!VALID_EVTCHN(evtchn))
|
||||
/* events delivered via platform PCI interrupts are always
|
||||
* routed to vcpu 0 */
|
||||
if (!VALID_EVTCHN(evtchn) ||
|
||||
(xen_hvm_domain() && !xen_have_vector_callback))
|
||||
return -1;
|
||||
|
||||
/* Send future instances of this interrupt to other vcpu. */
|
||||
|
|
@ -933,6 +963,44 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
|
|||
.retrigger = retrigger_dynirq,
|
||||
};
|
||||
|
||||
int xen_set_callback_via(uint64_t via)
|
||||
{
|
||||
struct xen_hvm_param a;
|
||||
a.domid = DOMID_SELF;
|
||||
a.index = HVM_PARAM_CALLBACK_IRQ;
|
||||
a.value = via;
|
||||
return HYPERVISOR_hvm_op(HVMOP_set_param, &a);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xen_set_callback_via);
|
||||
|
||||
#ifdef CONFIG_XEN_PVHVM
|
||||
/* Vector callbacks are better than PCI interrupts to receive event
|
||||
* channel notifications because we can receive vector callbacks on any
|
||||
* vcpu and we don't need PCI support or APIC interactions. */
|
||||
void xen_callback_vector(void)
|
||||
{
|
||||
int rc;
|
||||
uint64_t callback_via;
|
||||
if (xen_have_vector_callback) {
|
||||
callback_via = HVM_CALLBACK_VECTOR(XEN_HVM_EVTCHN_CALLBACK);
|
||||
rc = xen_set_callback_via(callback_via);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Request for Xen HVM callback vector"
|
||||
" failed.\n");
|
||||
xen_have_vector_callback = 0;
|
||||
return;
|
||||
}
|
||||
printk(KERN_INFO "Xen HVM callback vector for event delivery is "
|
||||
"enabled\n");
|
||||
/* in the restore case the vector has already been allocated */
|
||||
if (!test_bit(XEN_HVM_EVTCHN_CALLBACK, used_vectors))
|
||||
alloc_intr_gate(XEN_HVM_EVTCHN_CALLBACK, xen_hvm_callback_vector);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void xen_callback_vector(void) {}
|
||||
#endif
|
||||
|
||||
void __init xen_init_IRQ(void)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -947,5 +1015,10 @@ void __init xen_init_IRQ(void)
|
|||
for (i = 0; i < NR_EVENT_CHANNELS; i++)
|
||||
mask_evtchn(i);
|
||||
|
||||
irq_ctx_init(smp_processor_id());
|
||||
if (xen_hvm_domain()) {
|
||||
xen_callback_vector();
|
||||
native_init_IRQ();
|
||||
} else {
|
||||
irq_ctx_init(smp_processor_id());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,11 +37,13 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <xen/xen.h>
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/page.h>
|
||||
#include <xen/grant_table.h>
|
||||
#include <xen/interface/memory.h>
|
||||
#include <asm/xen/hypercall.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
|
|
@ -59,6 +61,8 @@ static unsigned int boot_max_nr_grant_frames;
|
|||
static int gnttab_free_count;
|
||||
static grant_ref_t gnttab_free_head;
|
||||
static DEFINE_SPINLOCK(gnttab_list_lock);
|
||||
unsigned long xen_hvm_resume_frames;
|
||||
EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
|
||||
|
||||
static struct grant_entry *shared;
|
||||
|
||||
|
|
@ -433,7 +437,7 @@ static unsigned int __max_nr_grant_frames(void)
|
|||
return query.max_nr_frames;
|
||||
}
|
||||
|
||||
static inline unsigned int max_nr_grant_frames(void)
|
||||
unsigned int gnttab_max_grant_frames(void)
|
||||
{
|
||||
unsigned int xen_max = __max_nr_grant_frames();
|
||||
|
||||
|
|
@ -441,6 +445,7 @@ static inline unsigned int max_nr_grant_frames(void)
|
|||
return boot_max_nr_grant_frames;
|
||||
return xen_max;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
|
||||
|
||||
static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
|
||||
{
|
||||
|
|
@ -449,6 +454,30 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
|
|||
unsigned int nr_gframes = end_idx + 1;
|
||||
int rc;
|
||||
|
||||
if (xen_hvm_domain()) {
|
||||
struct xen_add_to_physmap xatp;
|
||||
unsigned int i = end_idx;
|
||||
rc = 0;
|
||||
/*
|
||||
* Loop backwards, so that the first hypercall has the largest
|
||||
* index, ensuring that the table will grow only once.
|
||||
*/
|
||||
do {
|
||||
xatp.domid = DOMID_SELF;
|
||||
xatp.idx = i;
|
||||
xatp.space = XENMAPSPACE_grant_table;
|
||||
xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i;
|
||||
rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
|
||||
if (rc != 0) {
|
||||
printk(KERN_WARNING
|
||||
"grant table add_to_physmap failed, err=%d\n", rc);
|
||||
break;
|
||||
}
|
||||
} while (i-- > start_idx);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
|
||||
if (!frames)
|
||||
return -ENOMEM;
|
||||
|
|
@ -465,7 +494,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
|
|||
|
||||
BUG_ON(rc || setup.status);
|
||||
|
||||
rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(),
|
||||
rc = arch_gnttab_map_shared(frames, nr_gframes, gnttab_max_grant_frames(),
|
||||
&shared);
|
||||
BUG_ON(rc);
|
||||
|
||||
|
|
@ -476,9 +505,27 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
|
|||
|
||||
int gnttab_resume(void)
|
||||
{
|
||||
if (max_nr_grant_frames() < nr_grant_frames)
|
||||
unsigned int max_nr_gframes;
|
||||
|
||||
max_nr_gframes = gnttab_max_grant_frames();
|
||||
if (max_nr_gframes < nr_grant_frames)
|
||||
return -ENOSYS;
|
||||
return gnttab_map(0, nr_grant_frames - 1);
|
||||
|
||||
if (xen_pv_domain())
|
||||
return gnttab_map(0, nr_grant_frames - 1);
|
||||
|
||||
if (!shared) {
|
||||
shared = ioremap(xen_hvm_resume_frames, PAGE_SIZE * max_nr_gframes);
|
||||
if (shared == NULL) {
|
||||
printk(KERN_WARNING
|
||||
"Failed to ioremap gnttab share frames!");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
gnttab_map(0, nr_grant_frames - 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gnttab_suspend(void)
|
||||
|
|
@ -495,7 +542,7 @@ static int gnttab_expand(unsigned int req_entries)
|
|||
cur = nr_grant_frames;
|
||||
extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
|
||||
GREFS_PER_GRANT_FRAME);
|
||||
if (cur + extra > max_nr_grant_frames())
|
||||
if (cur + extra > gnttab_max_grant_frames())
|
||||
return -ENOSPC;
|
||||
|
||||
rc = gnttab_map(cur, cur + extra - 1);
|
||||
|
|
@ -505,15 +552,12 @@ static int gnttab_expand(unsigned int req_entries)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int __devinit gnttab_init(void)
|
||||
int gnttab_init(void)
|
||||
{
|
||||
int i;
|
||||
unsigned int max_nr_glist_frames, nr_glist_frames;
|
||||
unsigned int nr_init_grefs;
|
||||
|
||||
if (!xen_domain())
|
||||
return -ENODEV;
|
||||
|
||||
nr_grant_frames = 1;
|
||||
boot_max_nr_grant_frames = __max_nr_grant_frames();
|
||||
|
||||
|
|
@ -556,5 +600,18 @@ static int __devinit gnttab_init(void)
|
|||
kfree(gnttab_list);
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gnttab_init);
|
||||
|
||||
core_initcall(gnttab_init);
|
||||
static int __devinit __gnttab_init(void)
|
||||
{
|
||||
/* Delay grant-table initialization in the PV on HVM case */
|
||||
if (xen_hvm_domain())
|
||||
return 0;
|
||||
|
||||
if (!xen_pv_domain())
|
||||
return -ENODEV;
|
||||
|
||||
return gnttab_init();
|
||||
}
|
||||
|
||||
core_initcall(__gnttab_init);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/stop_machine.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#include <xen/xen.h>
|
||||
#include <xen/xenbus.h>
|
||||
#include <xen/grant_table.h>
|
||||
#include <xen/events.h>
|
||||
|
|
@ -17,6 +18,7 @@
|
|||
|
||||
#include <asm/xen/hypercall.h>
|
||||
#include <asm/xen/page.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
|
||||
enum shutdown_state {
|
||||
SHUTDOWN_INVALID = -1,
|
||||
|
|
@ -33,10 +35,30 @@ enum shutdown_state {
|
|||
static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int xen_hvm_suspend(void *data)
|
||||
{
|
||||
struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
|
||||
int *cancelled = data;
|
||||
|
||||
BUG_ON(!irqs_disabled());
|
||||
|
||||
*cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
|
||||
|
||||
xen_hvm_post_suspend(*cancelled);
|
||||
gnttab_resume();
|
||||
|
||||
if (!*cancelled) {
|
||||
xen_irq_resume();
|
||||
xen_timer_resume();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xen_suspend(void *data)
|
||||
{
|
||||
int *cancelled = data;
|
||||
int err;
|
||||
int *cancelled = data;
|
||||
|
||||
BUG_ON(!irqs_disabled());
|
||||
|
||||
|
|
@ -106,7 +128,10 @@ static void do_suspend(void)
|
|||
goto out_resume;
|
||||
}
|
||||
|
||||
err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
|
||||
if (xen_hvm_domain())
|
||||
err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0));
|
||||
else
|
||||
err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
|
||||
|
||||
dpm_resume_noirq(PMSG_RESUME);
|
||||
|
||||
|
|
@ -255,7 +280,19 @@ static int shutdown_event(struct notifier_block *notifier,
|
|||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int __init setup_shutdown_event(void)
|
||||
static int __init __setup_shutdown_event(void)
|
||||
{
|
||||
/* Delay initialization in the PV on HVM case */
|
||||
if (xen_hvm_domain())
|
||||
return 0;
|
||||
|
||||
if (!xen_pv_domain())
|
||||
return -ENODEV;
|
||||
|
||||
return xen_setup_shutdown_event();
|
||||
}
|
||||
|
||||
int xen_setup_shutdown_event(void)
|
||||
{
|
||||
static struct notifier_block xenstore_notifier = {
|
||||
.notifier_call = shutdown_event
|
||||
|
|
@ -264,5 +301,6 @@ static int __init setup_shutdown_event(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
|
||||
|
||||
subsys_initcall(setup_shutdown_event);
|
||||
subsys_initcall(__setup_shutdown_event);
|
||||
|
|
|
|||
207
drivers/xen/platform-pci.c
Normal file
207
drivers/xen/platform-pci.c
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/******************************************************************************
|
||||
* platform-pci.c
|
||||
*
|
||||
* Xen platform PCI device driver
|
||||
* Copyright (c) 2005, Intel Corporation.
|
||||
* Copyright (c) 2007, XenSource Inc.
|
||||
* Copyright (c) 2010, Citrix
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <xen/platform_pci.h>
|
||||
#include <xen/grant_table.h>
|
||||
#include <xen/xenbus.h>
|
||||
#include <xen/events.h>
|
||||
#include <xen/hvm.h>
|
||||
#include <xen/xen-ops.h>
|
||||
|
||||
#define DRV_NAME "xen-platform-pci"
|
||||
|
||||
MODULE_AUTHOR("[email protected] and [email protected]");
|
||||
MODULE_DESCRIPTION("Xen platform PCI device");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static unsigned long platform_mmio;
|
||||
static unsigned long platform_mmio_alloc;
|
||||
static unsigned long platform_mmiolen;
|
||||
static uint64_t callback_via;
|
||||
|
||||
unsigned long alloc_xen_mmio(unsigned long len)
|
||||
{
|
||||
unsigned long addr;
|
||||
|
||||
addr = platform_mmio + platform_mmio_alloc;
|
||||
platform_mmio_alloc += len;
|
||||
BUG_ON(platform_mmio_alloc > platform_mmiolen);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static uint64_t get_callback_via(struct pci_dev *pdev)
|
||||
{
|
||||
u8 pin;
|
||||
int irq;
|
||||
|
||||
irq = pdev->irq;
|
||||
if (irq < 16)
|
||||
return irq; /* ISA IRQ */
|
||||
|
||||
pin = pdev->pin;
|
||||
|
||||
/* We don't know the GSI. Specify the PCI INTx line instead. */
|
||||
return ((uint64_t)0x01 << 56) | /* PCI INTx identifier */
|
||||
((uint64_t)pci_domain_nr(pdev->bus) << 32) |
|
||||
((uint64_t)pdev->bus->number << 16) |
|
||||
((uint64_t)(pdev->devfn & 0xff) << 8) |
|
||||
((uint64_t)(pin - 1) & 3);
|
||||
}
|
||||
|
||||
static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id)
|
||||
{
|
||||
xen_hvm_evtchn_do_upcall();
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int xen_allocate_irq(struct pci_dev *pdev)
|
||||
{
|
||||
return request_irq(pdev->irq, do_hvm_evtchn_intr,
|
||||
IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
|
||||
"xen-platform-pci", pdev);
|
||||
}
|
||||
|
||||
static int platform_pci_resume(struct pci_dev *pdev)
|
||||
{
|
||||
int err;
|
||||
if (xen_have_vector_callback)
|
||||
return 0;
|
||||
err = xen_set_callback_via(callback_via);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "platform_pci_resume failure!\n");
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit platform_pci_init(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
int i, ret;
|
||||
long ioaddr, iolen;
|
||||
long mmio_addr, mmio_len;
|
||||
unsigned int max_nr_gframes;
|
||||
|
||||
i = pci_enable_device(pdev);
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
ioaddr = pci_resource_start(pdev, 0);
|
||||
iolen = pci_resource_len(pdev, 0);
|
||||
|
||||
mmio_addr = pci_resource_start(pdev, 1);
|
||||
mmio_len = pci_resource_len(pdev, 1);
|
||||
|
||||
if (mmio_addr == 0 || ioaddr == 0) {
|
||||
dev_err(&pdev->dev, "no resources found\n");
|
||||
ret = -ENOENT;
|
||||
goto pci_out;
|
||||
}
|
||||
|
||||
if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL) {
|
||||
dev_err(&pdev->dev, "MEM I/O resource 0x%lx @ 0x%lx busy\n",
|
||||
mmio_addr, mmio_len);
|
||||
ret = -EBUSY;
|
||||
goto pci_out;
|
||||
}
|
||||
|
||||
if (request_region(ioaddr, iolen, DRV_NAME) == NULL) {
|
||||
dev_err(&pdev->dev, "I/O resource 0x%lx @ 0x%lx busy\n",
|
||||
iolen, ioaddr);
|
||||
ret = -EBUSY;
|
||||
goto mem_out;
|
||||
}
|
||||
|
||||
platform_mmio = mmio_addr;
|
||||
platform_mmiolen = mmio_len;
|
||||
|
||||
if (!xen_have_vector_callback) {
|
||||
ret = xen_allocate_irq(pdev);
|
||||
if (ret) {
|
||||
dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
callback_via = get_callback_via(pdev);
|
||||
ret = xen_set_callback_via(callback_via);
|
||||
if (ret) {
|
||||
dev_warn(&pdev->dev, "Unable to set the evtchn callback "
|
||||
"err=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
max_nr_gframes = gnttab_max_grant_frames();
|
||||
xen_hvm_resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
|
||||
ret = gnttab_init();
|
||||
if (ret)
|
||||
goto out;
|
||||
xenbus_probe(NULL);
|
||||
ret = xen_setup_shutdown_event();
|
||||
if (ret)
|
||||
goto out;
|
||||
return 0;
|
||||
|
||||
out:
|
||||
release_region(ioaddr, iolen);
|
||||
mem_out:
|
||||
release_mem_region(mmio_addr, mmio_len);
|
||||
pci_out:
|
||||
pci_disable_device(pdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct pci_device_id platform_pci_tbl[] __devinitdata = {
|
||||
{PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
|
||||
{0,}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, platform_pci_tbl);
|
||||
|
||||
static struct pci_driver platform_driver = {
|
||||
.name = DRV_NAME,
|
||||
.probe = platform_pci_init,
|
||||
.id_table = platform_pci_tbl,
|
||||
#ifdef CONFIG_PM
|
||||
.resume_early = platform_pci_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init platform_pci_module_init(void)
|
||||
{
|
||||
/* no unplug has been done, IGNORE hasn't been specified: just
|
||||
* return now */
|
||||
if (!xen_platform_pci_unplug)
|
||||
return -ENODEV;
|
||||
|
||||
return pci_register_driver(&platform_driver);
|
||||
}
|
||||
|
||||
module_init(platform_pci_module_init);
|
||||
|
|
@ -56,6 +56,9 @@
|
|||
#include <xen/events.h>
|
||||
#include <xen/page.h>
|
||||
|
||||
#include <xen/platform_pci.h>
|
||||
#include <xen/hvm.h>
|
||||
|
||||
#include "xenbus_comms.h"
|
||||
#include "xenbus_probe.h"
|
||||
|
||||
|
|
@ -776,8 +779,23 @@ void xenbus_probe(struct work_struct *unused)
|
|||
/* Notify others that xenstore is up */
|
||||
blocking_notifier_call_chain(&xenstore_chain, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xenbus_probe);
|
||||
|
||||
static int __init xenbus_probe_init(void)
|
||||
static int __init xenbus_probe_initcall(void)
|
||||
{
|
||||
if (!xen_domain())
|
||||
return -ENODEV;
|
||||
|
||||
if (xen_initial_domain() || xen_hvm_domain())
|
||||
return 0;
|
||||
|
||||
xenbus_probe(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(xenbus_probe_initcall);
|
||||
|
||||
static int __init xenbus_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
|
|
@ -802,11 +820,24 @@ static int __init xenbus_probe_init(void)
|
|||
if (xen_initial_domain()) {
|
||||
/* dom0 not yet supported */
|
||||
} else {
|
||||
if (xen_hvm_domain()) {
|
||||
uint64_t v = 0;
|
||||
err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
|
||||
if (err)
|
||||
goto out_error;
|
||||
xen_store_evtchn = (int)v;
|
||||
err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
|
||||
if (err)
|
||||
goto out_error;
|
||||
xen_store_mfn = (unsigned long)v;
|
||||
xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE);
|
||||
} else {
|
||||
xen_store_evtchn = xen_start_info->store_evtchn;
|
||||
xen_store_mfn = xen_start_info->store_mfn;
|
||||
xen_store_interface = mfn_to_virt(xen_store_mfn);
|
||||
}
|
||||
xenstored_ready = 1;
|
||||
xen_store_evtchn = xen_start_info->store_evtchn;
|
||||
xen_store_mfn = xen_start_info->store_mfn;
|
||||
}
|
||||
xen_store_interface = mfn_to_virt(xen_store_mfn);
|
||||
|
||||
/* Initialize the interface to xenstore. */
|
||||
err = xs_init();
|
||||
|
|
@ -816,9 +847,6 @@ static int __init xenbus_probe_init(void)
|
|||
goto out_unreg_back;
|
||||
}
|
||||
|
||||
if (!xen_initial_domain())
|
||||
xenbus_probe(NULL);
|
||||
|
||||
#ifdef CONFIG_XEN_COMPAT_XENFS
|
||||
/*
|
||||
* Create xenfs mountpoint in /proc for compatibility with
|
||||
|
|
@ -839,7 +867,7 @@ static int __init xenbus_probe_init(void)
|
|||
return err;
|
||||
}
|
||||
|
||||
postcore_initcall(xenbus_probe_init);
|
||||
postcore_initcall(xenbus_init);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
|
@ -947,6 +975,9 @@ static void wait_for_devices(struct xenbus_driver *xendrv)
|
|||
#ifndef MODULE
|
||||
static int __init boot_wait_for_devices(void)
|
||||
{
|
||||
if (xen_hvm_domain() && !xen_platform_pci_unplug)
|
||||
return -ENODEV;
|
||||
|
||||
ready_to_wait_for_devices = 1;
|
||||
wait_for_devices(NULL);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ static struct file_system_type xenfs_type = {
|
|||
|
||||
static int __init xenfs_init(void)
|
||||
{
|
||||
if (xen_pv_domain())
|
||||
if (xen_domain())
|
||||
return register_filesystem(&xenfs_type);
|
||||
|
||||
printk(KERN_INFO "XENFS: not registering filesystem on non-xen platform\n");
|
||||
|
|
@ -74,7 +74,7 @@ static int __init xenfs_init(void)
|
|||
|
||||
static void __exit xenfs_exit(void)
|
||||
{
|
||||
if (xen_pv_domain())
|
||||
if (xen_domain())
|
||||
unregister_filesystem(&xenfs_type);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue