mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-31 04:01:48 -04:00
Features:
* Extend the APIC ops implementation and add IRQ_WORKER vector support so that 'perf' can work properly.
* Fix self-ballooning code, and balloon logic when booting as initial domain.
* Move array printing code to generic debugfs
* Support XenBus domains.
* Lazily free grants when a domain is dead/non-existent.
* In M2P code use batching calls
Bug-fixes:
* Fix NULL dereference in allocation failure path (hvc_xen)
* Fix unbinding of IRQ_WORKER vector during vCPU hot-unplug
* Fix HVM guest resume - we would leak an PIRQ value instead of reusing the existing one.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
iQEcBAABAgAGBQJPu9MpAAoJEFjIrFwIi8fJaNQH/RylThiO+O+LBpPrO8VRUw+2
/Io98T7ZK2ggoUeaJx0C8irM0JMFAkxGMcfX3w9fwNt/BTec4s++4JhbN1jYN0da
6a0PqINo+M8y73So6CBfuJDCunaRLGKVG/ibIO3Y3WAff51/H+DMvO7uYYDAE0aA
mikyOxnaty0DiG5i4JGDHGmCzDASfK/jgGccZ03m6522mDx5ZIbTzZWONLfz8dqT
rbxnn9vrNLgEYWuzyLMwW0GymToUtt01xBQvwJLAbhn8lr1WBRBLpxXA+5iYNQrn
Ri25G7keYJhG4uwZfaHnR+4HTrmhlGzK1Z96dkqpGUaeIcdyWmPMp22VtBBiwG8=
=uyRr
-----END PGP SIGNATURE-----
Merge tag 'stable/for-linus-3.5-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
Pull Xen updates from Konrad Rzeszutek Wilk:
"Features:
* Extend the APIC ops implementation and add IRQ_WORKER vector
support so that 'perf' can work properly.
* Fix self-ballooning code, and balloon logic when booting as initial
domain.
* Move array printing code to generic debugfs
* Support XenBus domains.
* Lazily free grants when a domain is dead/non-existent.
* In M2P code use batching calls
Bug-fixes:
* Fix NULL dereference in allocation failure path (hvc_xen)
* Fix unbinding of IRQ_WORKER vector during vCPU hot-unplug
* Fix HVM guest resume - we would leak an PIRQ value instead of
reusing the existing one."
Fix up add-add onflicts in arch/x86/xen/enlighten.c due to addition of
apic ipi interface next to the new apic_id functions.
* tag 'stable/for-linus-3.5-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
xen: do not map the same GSI twice in PVHVM guests.
hvc_xen: NULL dereference on allocation failure
xen: Add selfballoning memory reservation tunable.
xenbus: Add support for xenbus backend in stub domain
xen/smp: unbind irqworkX when unplugging vCPUs.
xen: enter/exit lazy_mmu_mode around m2p_override calls
xen/acpi/sleep: Enable ACPI sleep via the __acpi_os_prepare_sleep
xen: implement IRQ_WORK_VECTOR handler
xen: implement apic ipi interface
xen/setup: update VA mapping when releasing memory during setup
xen/setup: Combine the two hypercall functions - since they are quite similar.
xen/setup: Populate freed MFNs from non-RAM E820 entries and gaps to E820 RAM
xen/setup: Only print "Freeing XXX-YYY pfn range: Z pages freed" if Z > 0
xen/gnttab: add deferred freeing logic
debugfs: Add support to print u32 array in debugfs
xen/p2m: An early bootup variant of set_phys_to_machine
xen/p2m: Collapse early_alloc_p2m_middle redundant checks.
xen/p2m: Allow alloc_p2m_middle to call reserve_brk depending on argument
xen/p2m: Move code around to allow for better re-usage.
This commit is contained in:
commit
b5f4035adf
27 changed files with 827 additions and 226 deletions
|
|
@ -17,7 +17,7 @@ obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
|
|||
obj-$(CONFIG_XEN_PVHVM) += platform-pci.o
|
||||
obj-$(CONFIG_XEN_TMEM) += tmem.o
|
||||
obj-$(CONFIG_SWIOTLB_XEN) += swiotlb-xen.o
|
||||
obj-$(CONFIG_XEN_DOM0) += pci.o
|
||||
obj-$(CONFIG_XEN_DOM0) += pci.o acpi.o
|
||||
obj-$(CONFIG_XEN_PCIDEV_BACKEND) += xen-pciback/
|
||||
obj-$(CONFIG_XEN_PRIVCMD) += xen-privcmd.o
|
||||
obj-$(CONFIG_XEN_ACPI_PROCESSOR) += xen-acpi-processor.o
|
||||
|
|
|
|||
62
drivers/xen/acpi.c
Normal file
62
drivers/xen/acpi.c
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/******************************************************************************
|
||||
* acpi.c
|
||||
* acpi file for domain 0 kernel
|
||||
*
|
||||
* Copyright (c) 2011 Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
* Copyright (c) 2011 Yu Ke ke.yu@intel.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation; or, when distributed
|
||||
* separately from the Linux kernel or incorporated into other
|
||||
* software packages, subject to the following license:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this source file (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <xen/acpi.h>
|
||||
#include <xen/interface/platform.h>
|
||||
#include <asm/xen/hypercall.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
|
||||
int xen_acpi_notify_hypervisor_state(u8 sleep_state,
|
||||
u32 pm1a_cnt, u32 pm1b_cnt)
|
||||
{
|
||||
struct xen_platform_op op = {
|
||||
.cmd = XENPF_enter_acpi_sleep,
|
||||
.interface_version = XENPF_INTERFACE_VERSION,
|
||||
.u = {
|
||||
.enter_acpi_sleep = {
|
||||
.pm1a_cnt_val = (u16)pm1a_cnt,
|
||||
.pm1b_cnt_val = (u16)pm1b_cnt,
|
||||
.sleep_state = sleep_state,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if ((pm1a_cnt & 0xffff0000) || (pm1b_cnt & 0xffff0000)) {
|
||||
WARN(1, "Using more than 16bits of PM1A/B 0x%x/0x%x!"
|
||||
"Email [email protected] Thank you.\n", \
|
||||
pm1a_cnt, pm1b_cnt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
HYPERVISOR_dom0_op(&op);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -611,7 +611,7 @@ static void disable_pirq(struct irq_data *data)
|
|||
disable_dynirq(data);
|
||||
}
|
||||
|
||||
static int find_irq_by_gsi(unsigned gsi)
|
||||
int xen_irq_from_gsi(unsigned gsi)
|
||||
{
|
||||
struct irq_info *info;
|
||||
|
||||
|
|
@ -625,6 +625,7 @@ static int find_irq_by_gsi(unsigned gsi)
|
|||
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xen_irq_from_gsi);
|
||||
|
||||
/*
|
||||
* Do not make any assumptions regarding the relationship between the
|
||||
|
|
@ -644,7 +645,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
|
|||
|
||||
mutex_lock(&irq_mapping_update_lock);
|
||||
|
||||
irq = find_irq_by_gsi(gsi);
|
||||
irq = xen_irq_from_gsi(gsi);
|
||||
if (irq != -1) {
|
||||
printk(KERN_INFO "xen_map_pirq_gsi: returning irq %d for gsi %u\n",
|
||||
irq, gsi);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/vmalloc.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/hardirq.h>
|
||||
|
||||
#include <xen/xen.h>
|
||||
#include <xen/interface/xen.h>
|
||||
|
|
@ -426,10 +427,8 @@ static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly)
|
|||
nflags = *pflags;
|
||||
do {
|
||||
flags = nflags;
|
||||
if (flags & (GTF_reading|GTF_writing)) {
|
||||
printk(KERN_ALERT "WARNING: g.e. still in use!\n");
|
||||
if (flags & (GTF_reading|GTF_writing))
|
||||
return 0;
|
||||
}
|
||||
} while ((nflags = sync_cmpxchg(pflags, flags, 0)) != flags);
|
||||
|
||||
return 1;
|
||||
|
|
@ -458,12 +457,103 @@ static int gnttab_end_foreign_access_ref_v2(grant_ref_t ref, int readonly)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
|
||||
static inline int _gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
|
||||
{
|
||||
return gnttab_interface->end_foreign_access_ref(ref, readonly);
|
||||
}
|
||||
|
||||
int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
|
||||
{
|
||||
if (_gnttab_end_foreign_access_ref(ref, readonly))
|
||||
return 1;
|
||||
pr_warn("WARNING: g.e. %#x still in use!\n", ref);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref);
|
||||
|
||||
struct deferred_entry {
|
||||
struct list_head list;
|
||||
grant_ref_t ref;
|
||||
bool ro;
|
||||
uint16_t warn_delay;
|
||||
struct page *page;
|
||||
};
|
||||
static LIST_HEAD(deferred_list);
|
||||
static void gnttab_handle_deferred(unsigned long);
|
||||
static DEFINE_TIMER(deferred_timer, gnttab_handle_deferred, 0, 0);
|
||||
|
||||
static void gnttab_handle_deferred(unsigned long unused)
|
||||
{
|
||||
unsigned int nr = 10;
|
||||
struct deferred_entry *first = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&gnttab_list_lock, flags);
|
||||
while (nr--) {
|
||||
struct deferred_entry *entry
|
||||
= list_first_entry(&deferred_list,
|
||||
struct deferred_entry, list);
|
||||
|
||||
if (entry == first)
|
||||
break;
|
||||
list_del(&entry->list);
|
||||
spin_unlock_irqrestore(&gnttab_list_lock, flags);
|
||||
if (_gnttab_end_foreign_access_ref(entry->ref, entry->ro)) {
|
||||
put_free_entry(entry->ref);
|
||||
if (entry->page) {
|
||||
pr_debug("freeing g.e. %#x (pfn %#lx)\n",
|
||||
entry->ref, page_to_pfn(entry->page));
|
||||
__free_page(entry->page);
|
||||
} else
|
||||
pr_info("freeing g.e. %#x\n", entry->ref);
|
||||
kfree(entry);
|
||||
entry = NULL;
|
||||
} else {
|
||||
if (!--entry->warn_delay)
|
||||
pr_info("g.e. %#x still pending\n",
|
||||
entry->ref);
|
||||
if (!first)
|
||||
first = entry;
|
||||
}
|
||||
spin_lock_irqsave(&gnttab_list_lock, flags);
|
||||
if (entry)
|
||||
list_add_tail(&entry->list, &deferred_list);
|
||||
else if (list_empty(&deferred_list))
|
||||
break;
|
||||
}
|
||||
if (!list_empty(&deferred_list) && !timer_pending(&deferred_timer)) {
|
||||
deferred_timer.expires = jiffies + HZ;
|
||||
add_timer(&deferred_timer);
|
||||
}
|
||||
spin_unlock_irqrestore(&gnttab_list_lock, flags);
|
||||
}
|
||||
|
||||
static void gnttab_add_deferred(grant_ref_t ref, bool readonly,
|
||||
struct page *page)
|
||||
{
|
||||
struct deferred_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
|
||||
const char *what = KERN_WARNING "leaking";
|
||||
|
||||
if (entry) {
|
||||
unsigned long flags;
|
||||
|
||||
entry->ref = ref;
|
||||
entry->ro = readonly;
|
||||
entry->page = page;
|
||||
entry->warn_delay = 60;
|
||||
spin_lock_irqsave(&gnttab_list_lock, flags);
|
||||
list_add_tail(&entry->list, &deferred_list);
|
||||
if (!timer_pending(&deferred_timer)) {
|
||||
deferred_timer.expires = jiffies + HZ;
|
||||
add_timer(&deferred_timer);
|
||||
}
|
||||
spin_unlock_irqrestore(&gnttab_list_lock, flags);
|
||||
what = KERN_DEBUG "deferring";
|
||||
}
|
||||
printk("%s g.e. %#x (pfn %#lx)\n",
|
||||
what, ref, page ? page_to_pfn(page) : -1);
|
||||
}
|
||||
|
||||
void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
|
||||
unsigned long page)
|
||||
{
|
||||
|
|
@ -471,12 +561,9 @@ void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
|
|||
put_free_entry(ref);
|
||||
if (page != 0)
|
||||
free_page(page);
|
||||
} else {
|
||||
/* XXX This needs to be fixed so that the ref and page are
|
||||
placed on a list to be freed up later. */
|
||||
printk(KERN_WARNING
|
||||
"WARNING: leaking g.e. and page still in use!\n");
|
||||
}
|
||||
} else
|
||||
gnttab_add_deferred(ref, readonly,
|
||||
page ? virt_to_page(page) : NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gnttab_end_foreign_access);
|
||||
|
||||
|
|
@ -741,6 +828,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
|
|||
struct page **pages, unsigned int count)
|
||||
{
|
||||
int i, ret;
|
||||
bool lazy = false;
|
||||
pte_t *pte;
|
||||
unsigned long mfn;
|
||||
|
||||
|
|
@ -751,6 +839,11 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
|
|||
if (xen_feature(XENFEAT_auto_translated_physmap))
|
||||
return ret;
|
||||
|
||||
if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
|
||||
arch_enter_lazy_mmu_mode();
|
||||
lazy = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/* Do not add to override if the map failed. */
|
||||
if (map_ops[i].status)
|
||||
|
|
@ -769,6 +862,9 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (lazy)
|
||||
arch_leave_lazy_mmu_mode();
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gnttab_map_refs);
|
||||
|
|
@ -777,6 +873,7 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
|
|||
struct page **pages, unsigned int count, bool clear_pte)
|
||||
{
|
||||
int i, ret;
|
||||
bool lazy = false;
|
||||
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count);
|
||||
if (ret)
|
||||
|
|
@ -785,12 +882,20 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
|
|||
if (xen_feature(XENFEAT_auto_translated_physmap))
|
||||
return ret;
|
||||
|
||||
if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
|
||||
arch_enter_lazy_mmu_mode();
|
||||
lazy = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ret = m2p_remove_override(pages[i], clear_pte);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (lazy)
|
||||
arch_leave_lazy_mmu_mode();
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
|
||||
|
|
|
|||
|
|
@ -105,6 +105,12 @@ static unsigned int selfballoon_interval __read_mostly = 5;
|
|||
*/
|
||||
static unsigned int selfballoon_min_usable_mb;
|
||||
|
||||
/*
|
||||
* Amount of RAM in MB to add to the target number of pages.
|
||||
* Can be used to reserve some more room for caches and the like.
|
||||
*/
|
||||
static unsigned int selfballoon_reserved_mb;
|
||||
|
||||
static void selfballoon_process(struct work_struct *work);
|
||||
static DECLARE_DELAYED_WORK(selfballoon_worker, selfballoon_process);
|
||||
|
||||
|
|
@ -217,7 +223,8 @@ static void selfballoon_process(struct work_struct *work)
|
|||
cur_pages = totalram_pages;
|
||||
tgt_pages = cur_pages; /* default is no change */
|
||||
goal_pages = percpu_counter_read_positive(&vm_committed_as) +
|
||||
totalreserve_pages;
|
||||
totalreserve_pages +
|
||||
MB2PAGES(selfballoon_reserved_mb);
|
||||
#ifdef CONFIG_FRONTSWAP
|
||||
/* allow space for frontswap pages to be repatriated */
|
||||
if (frontswap_selfshrinking && frontswap_enabled)
|
||||
|
|
@ -397,6 +404,30 @@ static DEVICE_ATTR(selfballoon_min_usable_mb, S_IRUGO | S_IWUSR,
|
|||
show_selfballoon_min_usable_mb,
|
||||
store_selfballoon_min_usable_mb);
|
||||
|
||||
SELFBALLOON_SHOW(selfballoon_reserved_mb, "%d\n",
|
||||
selfballoon_reserved_mb);
|
||||
|
||||
static ssize_t store_selfballoon_reserved_mb(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
unsigned long val;
|
||||
int err;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
err = strict_strtoul(buf, 10, &val);
|
||||
if (err || val == 0)
|
||||
return -EINVAL;
|
||||
selfballoon_reserved_mb = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(selfballoon_reserved_mb, S_IRUGO | S_IWUSR,
|
||||
show_selfballoon_reserved_mb,
|
||||
store_selfballoon_reserved_mb);
|
||||
|
||||
|
||||
#ifdef CONFIG_FRONTSWAP
|
||||
SELFBALLOON_SHOW(frontswap_selfshrinking, "%d\n", frontswap_selfshrinking);
|
||||
|
|
@ -480,6 +511,7 @@ static struct attribute *selfballoon_attrs[] = {
|
|||
&dev_attr_selfballoon_downhysteresis.attr,
|
||||
&dev_attr_selfballoon_uphysteresis.attr,
|
||||
&dev_attr_selfballoon_min_usable_mb.attr,
|
||||
&dev_attr_selfballoon_reserved_mb.attr,
|
||||
#ifdef CONFIG_FRONTSWAP
|
||||
&dev_attr_frontswap_selfshrinking.attr,
|
||||
&dev_attr_frontswap_hysteresis.attr,
|
||||
|
|
|
|||
|
|
@ -234,3 +234,9 @@ int xb_init_comms(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xb_deinit_comms(void)
|
||||
{
|
||||
unbind_from_irqhandler(xenbus_irq, &xb_waitq);
|
||||
xenbus_irq = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
int xs_init(void);
|
||||
int xb_init_comms(void);
|
||||
void xb_deinit_comms(void);
|
||||
|
||||
/* Low level routines. */
|
||||
int xb_write(const void *data, unsigned len);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,11 @@
|
|||
|
||||
#include <xen/xen.h>
|
||||
#include <xen/page.h>
|
||||
#include <xen/xenbus.h>
|
||||
#include <xen/xenbus_dev.h>
|
||||
#include <xen/grant_table.h>
|
||||
#include <xen/events.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
|
||||
#include "xenbus_comms.h"
|
||||
|
||||
|
|
@ -22,6 +26,50 @@ static int xenbus_backend_open(struct inode *inode, struct file *filp)
|
|||
return nonseekable_open(inode, filp);
|
||||
}
|
||||
|
||||
static long xenbus_alloc(domid_t domid)
|
||||
{
|
||||
struct evtchn_alloc_unbound arg;
|
||||
int err = -EEXIST;
|
||||
|
||||
xs_suspend();
|
||||
|
||||
/* If xenstored_ready is nonzero, that means we have already talked to
|
||||
* xenstore and set up watches. These watches will be restored by
|
||||
* xs_resume, but that requires communication over the port established
|
||||
* below that is not visible to anyone until the ioctl returns.
|
||||
*
|
||||
* This can be resolved by splitting the ioctl into two parts
|
||||
* (postponing the resume until xenstored is active) but this is
|
||||
* unnecessarily complex for the intended use where xenstored is only
|
||||
* started once - so return -EEXIST if it's already running.
|
||||
*/
|
||||
if (xenstored_ready)
|
||||
goto out_err;
|
||||
|
||||
gnttab_grant_foreign_access_ref(GNTTAB_RESERVED_XENSTORE, domid,
|
||||
virt_to_mfn(xen_store_interface), 0 /* writable */);
|
||||
|
||||
arg.dom = DOMID_SELF;
|
||||
arg.remote_dom = domid;
|
||||
|
||||
err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &arg);
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
if (xen_store_evtchn > 0)
|
||||
xb_deinit_comms();
|
||||
|
||||
xen_store_evtchn = arg.port;
|
||||
|
||||
xs_resume();
|
||||
|
||||
return arg.port;
|
||||
|
||||
out_err:
|
||||
xs_suspend_cancel();
|
||||
return err;
|
||||
}
|
||||
|
||||
static long xenbus_backend_ioctl(struct file *file, unsigned int cmd, unsigned long data)
|
||||
{
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
|
|
@ -33,6 +81,9 @@ static long xenbus_backend_ioctl(struct file *file, unsigned int cmd, unsigned l
|
|||
return xen_store_evtchn;
|
||||
return -ENODEV;
|
||||
|
||||
case IOCTL_XENBUS_BACKEND_SETUP:
|
||||
return xenbus_alloc(data);
|
||||
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue