mirror of
https://github.com/lkl/linux.git
synced 2025-12-19 16:13:19 +09:00
Merge tag 'for-linus-6.6-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen updates from Juergen Gross: - a bunch of minor cleanups - a patch adding irqfd support for virtio backends running as user daemon supporting Xen guests * tag 'for-linus-6.6-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen: privcmd: Add support for irqfd xen/xenbus: Avoid a lockdep warning when adding a watch xen: Fix one kernel-doc comment xen: xenbus: Use helper function IS_ERR_OR_NULL() xen: Switch to use kmemdup() helper xen-pciback: Remove unused function declarations x86/xen: Make virt_to_pfn() a static inline xen: remove a confusing comment on auto-translated guest I/O xen/evtchn: Remove unused function declaration xen_set_affinity_evtchn()
This commit is contained in:
@@ -295,7 +295,10 @@ static inline unsigned long bfn_to_local_pfn(unsigned long mfn)
|
|||||||
|
|
||||||
/* VIRT <-> MACHINE conversion */
|
/* VIRT <-> MACHINE conversion */
|
||||||
#define virt_to_machine(v) (phys_to_machine(XPADDR(__pa(v))))
|
#define virt_to_machine(v) (phys_to_machine(XPADDR(__pa(v))))
|
||||||
#define virt_to_pfn(v) (PFN_DOWN(__pa(v)))
|
static inline unsigned long virt_to_pfn(const void *v)
|
||||||
|
{
|
||||||
|
return PFN_DOWN(__pa(v));
|
||||||
|
}
|
||||||
#define virt_to_mfn(v) (pfn_to_mfn(virt_to_pfn(v)))
|
#define virt_to_mfn(v) (pfn_to_mfn(virt_to_pfn(v)))
|
||||||
#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT))
|
#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT))
|
||||||
|
|
||||||
|
|||||||
@@ -523,7 +523,7 @@ static void __init xen_load_gdt_boot(const struct desc_ptr *dtr)
|
|||||||
BUG_ON(size > PAGE_SIZE);
|
BUG_ON(size > PAGE_SIZE);
|
||||||
BUG_ON(va & ~PAGE_MASK);
|
BUG_ON(va & ~PAGE_MASK);
|
||||||
|
|
||||||
pfn = virt_to_pfn(va);
|
pfn = virt_to_pfn((void *)va);
|
||||||
mfn = pfn_to_mfn(pfn);
|
mfn = pfn_to_mfn(pfn);
|
||||||
|
|
||||||
pte = pfn_pte(pfn, PAGE_KERNEL_RO);
|
pte = pfn_pte(pfn, PAGE_KERNEL_RO);
|
||||||
|
|||||||
@@ -2202,13 +2202,13 @@ static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order,
|
|||||||
mcs = __xen_mc_entry(0);
|
mcs = __xen_mc_entry(0);
|
||||||
|
|
||||||
if (in_frames)
|
if (in_frames)
|
||||||
in_frames[i] = virt_to_mfn(vaddr);
|
in_frames[i] = virt_to_mfn((void *)vaddr);
|
||||||
|
|
||||||
MULTI_update_va_mapping(mcs.mc, vaddr, VOID_PTE, 0);
|
MULTI_update_va_mapping(mcs.mc, vaddr, VOID_PTE, 0);
|
||||||
__set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY);
|
__set_phys_to_machine(virt_to_pfn((void *)vaddr), INVALID_P2M_ENTRY);
|
||||||
|
|
||||||
if (out_frames)
|
if (out_frames)
|
||||||
out_frames[i] = virt_to_pfn(vaddr);
|
out_frames[i] = virt_to_pfn((void *)vaddr);
|
||||||
}
|
}
|
||||||
xen_mc_issue(0);
|
xen_mc_issue(0);
|
||||||
}
|
}
|
||||||
@@ -2250,7 +2250,7 @@ static void xen_remap_exchanged_ptes(unsigned long vaddr, int order,
|
|||||||
MULTI_update_va_mapping(mcs.mc, vaddr,
|
MULTI_update_va_mapping(mcs.mc, vaddr,
|
||||||
mfn_pte(mfn, PAGE_KERNEL), flags);
|
mfn_pte(mfn, PAGE_KERNEL), flags);
|
||||||
|
|
||||||
set_phys_to_machine(virt_to_pfn(vaddr), mfn);
|
set_phys_to_machine(virt_to_pfn((void *)vaddr), mfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
xen_mc_issue(0);
|
xen_mc_issue(0);
|
||||||
@@ -2310,12 +2310,6 @@ int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order,
|
|||||||
int success;
|
int success;
|
||||||
unsigned long vstart = (unsigned long)phys_to_virt(pstart);
|
unsigned long vstart = (unsigned long)phys_to_virt(pstart);
|
||||||
|
|
||||||
/*
|
|
||||||
* Currently an auto-translated guest will not perform I/O, nor will
|
|
||||||
* it require PAE page directories below 4GB. Therefore any calls to
|
|
||||||
* this function are redundant and can be ignored.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (unlikely(order > MAX_CONTIG_ORDER))
|
if (unlikely(order > MAX_CONTIG_ORDER))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -2327,7 +2321,7 @@ int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order,
|
|||||||
xen_zap_pfn_range(vstart, order, in_frames, NULL);
|
xen_zap_pfn_range(vstart, order, in_frames, NULL);
|
||||||
|
|
||||||
/* 2. Get a new contiguous memory extent. */
|
/* 2. Get a new contiguous memory extent. */
|
||||||
out_frame = virt_to_pfn(vstart);
|
out_frame = virt_to_pfn((void *)vstart);
|
||||||
success = xen_exchange_memory(1UL << order, 0, in_frames,
|
success = xen_exchange_memory(1UL << order, 0, in_frames,
|
||||||
1, order, &out_frame,
|
1, order, &out_frame,
|
||||||
address_bits);
|
address_bits);
|
||||||
@@ -2360,7 +2354,7 @@ void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order)
|
|||||||
spin_lock_irqsave(&xen_reservation_lock, flags);
|
spin_lock_irqsave(&xen_reservation_lock, flags);
|
||||||
|
|
||||||
/* 1. Find start MFN of contiguous extent. */
|
/* 1. Find start MFN of contiguous extent. */
|
||||||
in_frame = virt_to_mfn(vstart);
|
in_frame = virt_to_mfn((void *)vstart);
|
||||||
|
|
||||||
/* 2. Zap current PTEs. */
|
/* 2. Zap current PTEs. */
|
||||||
xen_zap_pfn_range(vstart, order, NULL, out_frames);
|
xen_zap_pfn_range(vstart, order, NULL, out_frames);
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ static void __init xen_do_set_identity_and_remap_chunk(
|
|||||||
|
|
||||||
WARN_ON(size == 0);
|
WARN_ON(size == 0);
|
||||||
|
|
||||||
mfn_save = virt_to_mfn(buf);
|
mfn_save = virt_to_mfn((void *)buf);
|
||||||
|
|
||||||
for (ident_pfn_iter = start_pfn, remap_pfn_iter = remap_pfn;
|
for (ident_pfn_iter = start_pfn, remap_pfn_iter = remap_pfn;
|
||||||
ident_pfn_iter < ident_end_pfn;
|
ident_pfn_iter < ident_end_pfn;
|
||||||
@@ -503,7 +503,7 @@ void __init xen_remap_memory(void)
|
|||||||
unsigned long pfn_s = ~0UL;
|
unsigned long pfn_s = ~0UL;
|
||||||
unsigned long len = 0;
|
unsigned long len = 0;
|
||||||
|
|
||||||
mfn_save = virt_to_mfn(buf);
|
mfn_save = virt_to_mfn((void *)buf);
|
||||||
|
|
||||||
while (xen_remap_mfn != INVALID_P2M_ENTRY) {
|
while (xen_remap_mfn != INVALID_P2M_ENTRY) {
|
||||||
/* Map the remap information */
|
/* Map the remap information */
|
||||||
|
|||||||
@@ -269,6 +269,13 @@ config XEN_PRIVCMD
|
|||||||
disaggregated Xen setups this driver might be needed for other
|
disaggregated Xen setups this driver might be needed for other
|
||||||
domains, too.
|
domains, too.
|
||||||
|
|
||||||
|
config XEN_PRIVCMD_IRQFD
|
||||||
|
bool "Xen irqfd support"
|
||||||
|
depends on XEN_PRIVCMD && XEN_VIRTIO && EVENTFD
|
||||||
|
help
|
||||||
|
Using the irqfd mechanism a virtio backend running in a daemon can
|
||||||
|
speed up interrupt injection into a guest.
|
||||||
|
|
||||||
config XEN_ACPI_PROCESSOR
|
config XEN_ACPI_PROCESSOR
|
||||||
tristate "Xen ACPI processor"
|
tristate "Xen ACPI processor"
|
||||||
depends on XEN && XEN_PV_DOM0 && X86 && ACPI_PROCESSOR && CPU_FREQ
|
depends on XEN && XEN_PV_DOM0 && X86 && ACPI_PROCESSOR && CPU_FREQ
|
||||||
|
|||||||
@@ -1044,7 +1044,7 @@ EXPORT_SYMBOL_GPL(gnttab_pages_clear_private);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* gnttab_free_pages - free pages allocated by gnttab_alloc_pages()
|
* gnttab_free_pages - free pages allocated by gnttab_alloc_pages()
|
||||||
* @nr_pages; number of pages to free
|
* @nr_pages: number of pages to free
|
||||||
* @pages: the pages
|
* @pages: the pages
|
||||||
*/
|
*/
|
||||||
void gnttab_free_pages(int nr_pages, struct page **pages)
|
void gnttab_free_pages(int nr_pages, struct page **pages)
|
||||||
|
|||||||
@@ -9,11 +9,16 @@
|
|||||||
|
|
||||||
#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
|
#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
#include <linux/eventfd.h>
|
||||||
|
#include <linux/file.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/poll.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/mman.h>
|
#include <linux/mman.h>
|
||||||
@@ -833,6 +838,263 @@ out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_XEN_PRIVCMD_IRQFD
|
||||||
|
/* Irqfd support */
|
||||||
|
static struct workqueue_struct *irqfd_cleanup_wq;
|
||||||
|
static DEFINE_MUTEX(irqfds_lock);
|
||||||
|
static LIST_HEAD(irqfds_list);
|
||||||
|
|
||||||
|
struct privcmd_kernel_irqfd {
|
||||||
|
struct xen_dm_op_buf xbufs;
|
||||||
|
domid_t dom;
|
||||||
|
bool error;
|
||||||
|
struct eventfd_ctx *eventfd;
|
||||||
|
struct work_struct shutdown;
|
||||||
|
wait_queue_entry_t wait;
|
||||||
|
struct list_head list;
|
||||||
|
poll_table pt;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void irqfd_deactivate(struct privcmd_kernel_irqfd *kirqfd)
|
||||||
|
{
|
||||||
|
lockdep_assert_held(&irqfds_lock);
|
||||||
|
|
||||||
|
list_del_init(&kirqfd->list);
|
||||||
|
queue_work(irqfd_cleanup_wq, &kirqfd->shutdown);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void irqfd_shutdown(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct privcmd_kernel_irqfd *kirqfd =
|
||||||
|
container_of(work, struct privcmd_kernel_irqfd, shutdown);
|
||||||
|
u64 cnt;
|
||||||
|
|
||||||
|
eventfd_ctx_remove_wait_queue(kirqfd->eventfd, &kirqfd->wait, &cnt);
|
||||||
|
eventfd_ctx_put(kirqfd->eventfd);
|
||||||
|
kfree(kirqfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void irqfd_inject(struct privcmd_kernel_irqfd *kirqfd)
|
||||||
|
{
|
||||||
|
u64 cnt;
|
||||||
|
long rc;
|
||||||
|
|
||||||
|
eventfd_ctx_do_read(kirqfd->eventfd, &cnt);
|
||||||
|
|
||||||
|
xen_preemptible_hcall_begin();
|
||||||
|
rc = HYPERVISOR_dm_op(kirqfd->dom, 1, &kirqfd->xbufs);
|
||||||
|
xen_preemptible_hcall_end();
|
||||||
|
|
||||||
|
/* Don't repeat the error message for consecutive failures */
|
||||||
|
if (rc && !kirqfd->error) {
|
||||||
|
pr_err("Failed to configure irq for guest domain: %d\n",
|
||||||
|
kirqfd->dom);
|
||||||
|
}
|
||||||
|
|
||||||
|
kirqfd->error = rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync, void *key)
|
||||||
|
{
|
||||||
|
struct privcmd_kernel_irqfd *kirqfd =
|
||||||
|
container_of(wait, struct privcmd_kernel_irqfd, wait);
|
||||||
|
__poll_t flags = key_to_poll(key);
|
||||||
|
|
||||||
|
if (flags & EPOLLIN)
|
||||||
|
irqfd_inject(kirqfd);
|
||||||
|
|
||||||
|
if (flags & EPOLLHUP) {
|
||||||
|
mutex_lock(&irqfds_lock);
|
||||||
|
irqfd_deactivate(kirqfd);
|
||||||
|
mutex_unlock(&irqfds_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
irqfd_poll_func(struct file *file, wait_queue_head_t *wqh, poll_table *pt)
|
||||||
|
{
|
||||||
|
struct privcmd_kernel_irqfd *kirqfd =
|
||||||
|
container_of(pt, struct privcmd_kernel_irqfd, pt);
|
||||||
|
|
||||||
|
add_wait_queue_priority(wqh, &kirqfd->wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
||||||
|
{
|
||||||
|
struct privcmd_kernel_irqfd *kirqfd, *tmp;
|
||||||
|
__poll_t events;
|
||||||
|
struct fd f;
|
||||||
|
void *dm_op;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL);
|
||||||
|
if (!kirqfd)
|
||||||
|
return -ENOMEM;
|
||||||
|
dm_op = kirqfd + 1;
|
||||||
|
|
||||||
|
if (copy_from_user(dm_op, irqfd->dm_op, irqfd->size)) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto error_kfree;
|
||||||
|
}
|
||||||
|
|
||||||
|
kirqfd->xbufs.size = irqfd->size;
|
||||||
|
set_xen_guest_handle(kirqfd->xbufs.h, dm_op);
|
||||||
|
kirqfd->dom = irqfd->dom;
|
||||||
|
INIT_WORK(&kirqfd->shutdown, irqfd_shutdown);
|
||||||
|
|
||||||
|
f = fdget(irqfd->fd);
|
||||||
|
if (!f.file) {
|
||||||
|
ret = -EBADF;
|
||||||
|
goto error_kfree;
|
||||||
|
}
|
||||||
|
|
||||||
|
kirqfd->eventfd = eventfd_ctx_fileget(f.file);
|
||||||
|
if (IS_ERR(kirqfd->eventfd)) {
|
||||||
|
ret = PTR_ERR(kirqfd->eventfd);
|
||||||
|
goto error_fd_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Install our own custom wake-up handling so we are notified via a
|
||||||
|
* callback whenever someone signals the underlying eventfd.
|
||||||
|
*/
|
||||||
|
init_waitqueue_func_entry(&kirqfd->wait, irqfd_wakeup);
|
||||||
|
init_poll_funcptr(&kirqfd->pt, irqfd_poll_func);
|
||||||
|
|
||||||
|
mutex_lock(&irqfds_lock);
|
||||||
|
|
||||||
|
list_for_each_entry(tmp, &irqfds_list, list) {
|
||||||
|
if (kirqfd->eventfd == tmp->eventfd) {
|
||||||
|
ret = -EBUSY;
|
||||||
|
mutex_unlock(&irqfds_lock);
|
||||||
|
goto error_eventfd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_tail(&kirqfd->list, &irqfds_list);
|
||||||
|
mutex_unlock(&irqfds_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if there was an event already pending on the eventfd before we
|
||||||
|
* registered, and trigger it as if we didn't miss it.
|
||||||
|
*/
|
||||||
|
events = vfs_poll(f.file, &kirqfd->pt);
|
||||||
|
if (events & EPOLLIN)
|
||||||
|
irqfd_inject(kirqfd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not drop the file until the kirqfd is fully initialized, otherwise
|
||||||
|
* we might race against the EPOLLHUP.
|
||||||
|
*/
|
||||||
|
fdput(f);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error_eventfd:
|
||||||
|
eventfd_ctx_put(kirqfd->eventfd);
|
||||||
|
|
||||||
|
error_fd_put:
|
||||||
|
fdput(f);
|
||||||
|
|
||||||
|
error_kfree:
|
||||||
|
kfree(kirqfd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int privcmd_irqfd_deassign(struct privcmd_irqfd *irqfd)
|
||||||
|
{
|
||||||
|
struct privcmd_kernel_irqfd *kirqfd;
|
||||||
|
struct eventfd_ctx *eventfd;
|
||||||
|
|
||||||
|
eventfd = eventfd_ctx_fdget(irqfd->fd);
|
||||||
|
if (IS_ERR(eventfd))
|
||||||
|
return PTR_ERR(eventfd);
|
||||||
|
|
||||||
|
mutex_lock(&irqfds_lock);
|
||||||
|
|
||||||
|
list_for_each_entry(kirqfd, &irqfds_list, list) {
|
||||||
|
if (kirqfd->eventfd == eventfd) {
|
||||||
|
irqfd_deactivate(kirqfd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&irqfds_lock);
|
||||||
|
|
||||||
|
eventfd_ctx_put(eventfd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Block until we know all outstanding shutdown jobs have completed so
|
||||||
|
* that we guarantee there will not be any more interrupts once this
|
||||||
|
* deassign function returns.
|
||||||
|
*/
|
||||||
|
flush_workqueue(irqfd_cleanup_wq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long privcmd_ioctl_irqfd(struct file *file, void __user *udata)
|
||||||
|
{
|
||||||
|
struct privcmd_data *data = file->private_data;
|
||||||
|
struct privcmd_irqfd irqfd;
|
||||||
|
|
||||||
|
if (copy_from_user(&irqfd, udata, sizeof(irqfd)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
/* No other flags should be set */
|
||||||
|
if (irqfd.flags & ~PRIVCMD_IRQFD_FLAG_DEASSIGN)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* If restriction is in place, check the domid matches */
|
||||||
|
if (data->domid != DOMID_INVALID && data->domid != irqfd.dom)
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
if (irqfd.flags & PRIVCMD_IRQFD_FLAG_DEASSIGN)
|
||||||
|
return privcmd_irqfd_deassign(&irqfd);
|
||||||
|
|
||||||
|
return privcmd_irqfd_assign(&irqfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int privcmd_irqfd_init(void)
|
||||||
|
{
|
||||||
|
irqfd_cleanup_wq = alloc_workqueue("privcmd-irqfd-cleanup", 0, 0);
|
||||||
|
if (!irqfd_cleanup_wq)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void privcmd_irqfd_exit(void)
|
||||||
|
{
|
||||||
|
struct privcmd_kernel_irqfd *kirqfd, *tmp;
|
||||||
|
|
||||||
|
mutex_lock(&irqfds_lock);
|
||||||
|
|
||||||
|
list_for_each_entry_safe(kirqfd, tmp, &irqfds_list, list)
|
||||||
|
irqfd_deactivate(kirqfd);
|
||||||
|
|
||||||
|
mutex_unlock(&irqfds_lock);
|
||||||
|
|
||||||
|
destroy_workqueue(irqfd_cleanup_wq);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline long privcmd_ioctl_irqfd(struct file *file, void __user *udata)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int privcmd_irqfd_init(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void privcmd_irqfd_exit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_XEN_PRIVCMD_IRQFD */
|
||||||
|
|
||||||
static long privcmd_ioctl(struct file *file,
|
static long privcmd_ioctl(struct file *file,
|
||||||
unsigned int cmd, unsigned long data)
|
unsigned int cmd, unsigned long data)
|
||||||
{
|
{
|
||||||
@@ -868,6 +1130,10 @@ static long privcmd_ioctl(struct file *file,
|
|||||||
ret = privcmd_ioctl_mmap_resource(file, udata);
|
ret = privcmd_ioctl_mmap_resource(file, udata);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IOCTL_PRIVCMD_IRQFD:
|
||||||
|
ret = privcmd_ioctl_irqfd(file, udata);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -992,15 +1258,27 @@ static int __init privcmd_init(void)
|
|||||||
err = misc_register(&xen_privcmdbuf_dev);
|
err = misc_register(&xen_privcmdbuf_dev);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
pr_err("Could not register Xen hypercall-buf device\n");
|
pr_err("Could not register Xen hypercall-buf device\n");
|
||||||
misc_deregister(&privcmd_dev);
|
goto err_privcmdbuf;
|
||||||
return err;
|
}
|
||||||
|
|
||||||
|
err = privcmd_irqfd_init();
|
||||||
|
if (err != 0) {
|
||||||
|
pr_err("irqfd init failed\n");
|
||||||
|
goto err_irqfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_irqfd:
|
||||||
|
misc_deregister(&xen_privcmdbuf_dev);
|
||||||
|
err_privcmdbuf:
|
||||||
|
misc_deregister(&privcmd_dev);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit privcmd_exit(void)
|
static void __exit privcmd_exit(void)
|
||||||
{
|
{
|
||||||
|
privcmd_irqfd_exit();
|
||||||
misc_deregister(&privcmd_dev);
|
misc_deregister(&privcmd_dev);
|
||||||
misc_deregister(&xen_privcmdbuf_dev);
|
misc_deregister(&xen_privcmdbuf_dev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -473,11 +473,8 @@ static int xen_upload_processor_pm_data(void)
|
|||||||
if (!_pr)
|
if (!_pr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!pr_backup) {
|
if (!pr_backup)
|
||||||
pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
|
pr_backup = kmemdup(_pr, sizeof(*_pr), GFP_KERNEL);
|
||||||
if (pr_backup)
|
|
||||||
memcpy(pr_backup, _pr, sizeof(struct acpi_processor));
|
|
||||||
}
|
|
||||||
(void)upload_pm_data(_pr);
|
(void)upload_pm_data(_pr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ struct xen_pcibk_config_quirk {
|
|||||||
int xen_pcibk_config_quirks_add_field(struct pci_dev *dev, struct config_field
|
int xen_pcibk_config_quirks_add_field(struct pci_dev *dev, struct config_field
|
||||||
*field);
|
*field);
|
||||||
|
|
||||||
int xen_pcibk_config_quirks_remove_field(struct pci_dev *dev, int reg);
|
|
||||||
|
|
||||||
int xen_pcibk_config_quirks_init(struct pci_dev *dev);
|
int xen_pcibk_config_quirks_init(struct pci_dev *dev);
|
||||||
|
|
||||||
void xen_pcibk_config_field_free(struct config_field *field);
|
void xen_pcibk_config_field_free(struct config_field *field);
|
||||||
|
|||||||
@@ -201,6 +201,3 @@ static inline void xen_pcibk_lateeoi(struct xen_pcibk_device *pdev,
|
|||||||
int xen_pcibk_xenbus_register(void);
|
int xen_pcibk_xenbus_register(void);
|
||||||
void xen_pcibk_xenbus_unregister(void);
|
void xen_pcibk_xenbus_unregister(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Handles shared IRQs that can to device domain and control domain. */
|
|
||||||
void xen_pcibk_irq_handler(struct pci_dev *dev, int reset);
|
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ static void xenbus_check_frontend(char *class, char *dev)
|
|||||||
printk(KERN_DEBUG "XENBUS: frontend %s %s\n",
|
printk(KERN_DEBUG "XENBUS: frontend %s %s\n",
|
||||||
frontend, xenbus_strstate(fe_state));
|
frontend, xenbus_strstate(fe_state));
|
||||||
backend = xenbus_read(XBT_NIL, frontend, "backend", NULL);
|
backend = xenbus_read(XBT_NIL, frontend, "backend", NULL);
|
||||||
if (!backend || IS_ERR(backend))
|
if (IS_ERR_OR_NULL(backend))
|
||||||
goto out;
|
goto out;
|
||||||
err = xenbus_scanf(XBT_NIL, backend, "state", "%i", &be_state);
|
err = xenbus_scanf(XBT_NIL, backend, "state", "%i", &be_state);
|
||||||
if (err == 1)
|
if (err == 1)
|
||||||
|
|||||||
@@ -840,8 +840,8 @@ void xs_suspend(void)
|
|||||||
{
|
{
|
||||||
xs_suspend_enter();
|
xs_suspend_enter();
|
||||||
|
|
||||||
down_write(&xs_watch_rwsem);
|
|
||||||
mutex_lock(&xs_response_mutex);
|
mutex_lock(&xs_response_mutex);
|
||||||
|
down_write(&xs_watch_rwsem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void xs_resume(void)
|
void xs_resume(void)
|
||||||
@@ -866,8 +866,8 @@ void xs_resume(void)
|
|||||||
|
|
||||||
void xs_suspend_cancel(void)
|
void xs_suspend_cancel(void)
|
||||||
{
|
{
|
||||||
mutex_unlock(&xs_response_mutex);
|
|
||||||
up_write(&xs_watch_rwsem);
|
up_write(&xs_watch_rwsem);
|
||||||
|
mutex_unlock(&xs_response_mutex);
|
||||||
|
|
||||||
xs_suspend_exit();
|
xs_suspend_exit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,18 @@ struct privcmd_mmap_resource {
|
|||||||
__u64 addr;
|
__u64 addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* For privcmd_irqfd::flags */
|
||||||
|
#define PRIVCMD_IRQFD_FLAG_DEASSIGN (1 << 0)
|
||||||
|
|
||||||
|
struct privcmd_irqfd {
|
||||||
|
void __user *dm_op;
|
||||||
|
__u32 size; /* Size of structure pointed by dm_op */
|
||||||
|
__u32 fd;
|
||||||
|
__u32 flags;
|
||||||
|
domid_t dom;
|
||||||
|
__u8 pad[2];
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @cmd: IOCTL_PRIVCMD_HYPERCALL
|
* @cmd: IOCTL_PRIVCMD_HYPERCALL
|
||||||
* @arg: &privcmd_hypercall_t
|
* @arg: &privcmd_hypercall_t
|
||||||
@@ -125,5 +137,7 @@ struct privcmd_mmap_resource {
|
|||||||
_IOC(_IOC_NONE, 'P', 6, sizeof(domid_t))
|
_IOC(_IOC_NONE, 'P', 6, sizeof(domid_t))
|
||||||
#define IOCTL_PRIVCMD_MMAP_RESOURCE \
|
#define IOCTL_PRIVCMD_MMAP_RESOURCE \
|
||||||
_IOC(_IOC_NONE, 'P', 7, sizeof(struct privcmd_mmap_resource))
|
_IOC(_IOC_NONE, 'P', 7, sizeof(struct privcmd_mmap_resource))
|
||||||
|
#define IOCTL_PRIVCMD_IRQFD \
|
||||||
|
_IOC(_IOC_NONE, 'P', 8, sizeof(struct privcmd_irqfd))
|
||||||
|
|
||||||
#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
|
#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ void evtchn_put(evtchn_port_t evtchn);
|
|||||||
|
|
||||||
void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector);
|
void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector);
|
||||||
void rebind_evtchn_irq(evtchn_port_t evtchn, int irq);
|
void rebind_evtchn_irq(evtchn_port_t evtchn, int irq);
|
||||||
int xen_set_affinity_evtchn(struct irq_desc *desc, unsigned int tcpu);
|
|
||||||
|
|
||||||
static inline void notify_remote_via_evtchn(evtchn_port_t port)
|
static inline void notify_remote_via_evtchn(evtchn_port_t port)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user