xen: branch for v6.11-rc1
-----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRTLbB6QfY48x44uB6AXGG7T9hjvgUCZpS2TQAKCRCAXGG7T9hj vjryAQDy08vSiCNYnO4K0AXO9KhCLsXMpbdevTE0yHdtSW/IwQD/eOmrntgBArA4 PfQanbzM3Rj+h6p1zsfvW98DgmFrfAQ= =tG6C -----END PGP SIGNATURE----- Merge tag 'for-linus-6.11-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip Pull xen updates from Juergen Gross: - some trivial cleanups - a fix for the Xen timer - add boot time selectable debug capability to the Xen multicall handling - two fixes for the recently added Xen irqfd handling * tag 'for-linus-6.11-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: x86/xen: remove deprecated xen_nopvspin boot parameter x86/xen: eliminate some private header files x86/xen: make some functions static xen: make multicall debug boot time selectable xen/arm: Convert comma to semicolon xen: privcmd: Fix possible access to a freed kirqfd instance xen: privcmd: Switch from mutex to spinlock for irqfds xen: add missing MODULE_DESCRIPTION() macros x86/xen: Convert comma to semicolon x86/xen/time: Reduce Xen timer tick xen/manage: Constify struct shutdown_handler
This commit is contained in:
commit
f83e38fc9f
@ -7420,17 +7420,18 @@
|
|||||||
Crash from Xen panic notifier, without executing late
|
Crash from Xen panic notifier, without executing late
|
||||||
panic() code such as dumping handler.
|
panic() code such as dumping handler.
|
||||||
|
|
||||||
|
xen_mc_debug [X86,XEN,EARLY]
|
||||||
|
Enable multicall debugging when running as a Xen PV guest.
|
||||||
|
Enabling this feature will reduce performance a little
|
||||||
|
bit, so it should only be enabled for obtaining extended
|
||||||
|
debug data in case of multicall errors.
|
||||||
|
|
||||||
xen_msr_safe= [X86,XEN,EARLY]
|
xen_msr_safe= [X86,XEN,EARLY]
|
||||||
Format: <bool>
|
Format: <bool>
|
||||||
Select whether to always use non-faulting (safe) MSR
|
Select whether to always use non-faulting (safe) MSR
|
||||||
access functions when running as Xen PV guest. The
|
access functions when running as Xen PV guest. The
|
||||||
default value is controlled by CONFIG_XEN_PV_MSR_SAFE.
|
default value is controlled by CONFIG_XEN_PV_MSR_SAFE.
|
||||||
|
|
||||||
xen_nopvspin [X86,XEN,EARLY]
|
|
||||||
Disables the qspinlock slowpath using Xen PV optimizations.
|
|
||||||
This parameter is obsoleted by "nopvspin" parameter, which
|
|
||||||
has equivalent effect for XEN platform.
|
|
||||||
|
|
||||||
xen_nopv [X86]
|
xen_nopv [X86]
|
||||||
Disables the PV optimizations forcing the HVM guest to
|
Disables the PV optimizations forcing the HVM guest to
|
||||||
run as generic HVM guest with no PV drivers.
|
run as generic HVM guest with no PV drivers.
|
||||||
|
@ -109,7 +109,7 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
|
|||||||
* immediate unmapping.
|
* immediate unmapping.
|
||||||
*/
|
*/
|
||||||
map_ops[i].status = GNTST_general_error;
|
map_ops[i].status = GNTST_general_error;
|
||||||
unmap.host_addr = map_ops[i].host_addr,
|
unmap.host_addr = map_ops[i].host_addr;
|
||||||
unmap.handle = map_ops[i].handle;
|
unmap.handle = map_ops[i].handle;
|
||||||
map_ops[i].handle = INVALID_GRANT_HANDLE;
|
map_ops[i].handle = INVALID_GRANT_HANDLE;
|
||||||
if (map_ops[i].flags & GNTMAP_device_map)
|
if (map_ops[i].flags & GNTMAP_device_map)
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
#include <xen/xen.h>
|
#include <xen/xen.h>
|
||||||
#include <xen/interface/physdev.h>
|
#include <xen/interface/physdev.h>
|
||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
#include "pmu.h"
|
|
||||||
#include "smp.h"
|
|
||||||
|
|
||||||
static unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
|
static unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
|
||||||
{
|
{
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#include "debugfs.h"
|
#include "xen-ops.h"
|
||||||
|
|
||||||
static struct dentry *d_xen_debug;
|
static struct dentry *d_xen_debug;
|
||||||
|
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
#ifndef _XEN_DEBUGFS_H
|
|
||||||
#define _XEN_DEBUGFS_H
|
|
||||||
|
|
||||||
struct dentry * __init xen_init_debugfs(void);
|
|
||||||
|
|
||||||
#endif /* _XEN_DEBUGFS_H */
|
|
@ -20,8 +20,6 @@
|
|||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
|
||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
#include "smp.h"
|
|
||||||
#include "pmu.h"
|
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(hypercall_page);
|
EXPORT_SYMBOL_GPL(hypercall_page);
|
||||||
|
|
||||||
|
@ -28,8 +28,6 @@
|
|||||||
#include <asm/xen/page.h>
|
#include <asm/xen/page.h>
|
||||||
|
|
||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
#include "mmu.h"
|
|
||||||
#include "smp.h"
|
|
||||||
|
|
||||||
static unsigned long shared_info_pfn;
|
static unsigned long shared_info_pfn;
|
||||||
|
|
||||||
|
@ -85,10 +85,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
#include "mmu.h"
|
|
||||||
#include "smp.h"
|
|
||||||
#include "multicalls.h"
|
|
||||||
#include "pmu.h"
|
|
||||||
|
|
||||||
#include "../kernel/cpu/cpu.h" /* get_cpu_cap() */
|
#include "../kernel/cpu/cpu.h" /* get_cpu_cap() */
|
||||||
|
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
#include <asm/xen/hypercall.h>
|
#include <asm/xen/hypercall.h>
|
||||||
#include <xen/interface/memory.h>
|
#include <xen/interface/memory.h>
|
||||||
|
|
||||||
#include "multicalls.h"
|
#include "xen-ops.h"
|
||||||
#include "mmu.h"
|
|
||||||
|
|
||||||
unsigned long arbitrary_virt_to_mfn(void *vaddr)
|
unsigned long arbitrary_virt_to_mfn(void *vaddr)
|
||||||
{
|
{
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
#ifndef _XEN_MMU_H
|
|
||||||
|
|
||||||
#include <linux/linkage.h>
|
|
||||||
#include <asm/page.h>
|
|
||||||
|
|
||||||
enum pt_level {
|
|
||||||
PT_PGD,
|
|
||||||
PT_P4D,
|
|
||||||
PT_PUD,
|
|
||||||
PT_PMD,
|
|
||||||
PT_PTE
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
|
|
||||||
|
|
||||||
void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
|
|
||||||
|
|
||||||
pte_t xen_ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep);
|
|
||||||
void xen_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr,
|
|
||||||
pte_t *ptep, pte_t pte);
|
|
||||||
|
|
||||||
unsigned long xen_read_cr2_direct(void);
|
|
||||||
|
|
||||||
extern void xen_init_mmu_ops(void);
|
|
||||||
extern void xen_hvm_init_mmu_ops(void);
|
|
||||||
#endif /* _XEN_MMU_H */
|
|
@ -5,7 +5,7 @@
|
|||||||
#include <xen/interface/xen.h>
|
#include <xen/interface/xen.h>
|
||||||
#include <xen/hvm.h>
|
#include <xen/hvm.h>
|
||||||
|
|
||||||
#include "mmu.h"
|
#include "xen-ops.h"
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_VMCORE
|
#ifdef CONFIG_PROC_VMCORE
|
||||||
/*
|
/*
|
||||||
|
@ -82,9 +82,7 @@
|
|||||||
#include <xen/hvc-console.h>
|
#include <xen/hvc-console.h>
|
||||||
#include <xen/swiotlb-xen.h>
|
#include <xen/swiotlb-xen.h>
|
||||||
|
|
||||||
#include "multicalls.h"
|
#include "xen-ops.h"
|
||||||
#include "mmu.h"
|
|
||||||
#include "debugfs.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes for functions called via PV_CALLEE_SAVE_REGS_THUNK() in order
|
* Prototypes for functions called via PV_CALLEE_SAVE_REGS_THUNK() in order
|
||||||
@ -128,7 +126,7 @@ static DEFINE_SPINLOCK(xen_reservation_lock);
|
|||||||
* looking at another vcpu's cr3 value, it should use this variable.
|
* looking at another vcpu's cr3 value, it should use this variable.
|
||||||
*/
|
*/
|
||||||
DEFINE_PER_CPU(unsigned long, xen_cr3); /* cr3 stored as physaddr */
|
DEFINE_PER_CPU(unsigned long, xen_cr3); /* cr3 stored as physaddr */
|
||||||
DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */
|
static DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */
|
||||||
|
|
||||||
static phys_addr_t xen_pt_base, xen_pt_size __initdata;
|
static phys_addr_t xen_pt_base, xen_pt_size __initdata;
|
||||||
|
|
||||||
@ -305,16 +303,17 @@ static void xen_set_pte(pte_t *ptep, pte_t pteval)
|
|||||||
__xen_set_pte(ptep, pteval);
|
__xen_set_pte(ptep, pteval);
|
||||||
}
|
}
|
||||||
|
|
||||||
pte_t xen_ptep_modify_prot_start(struct vm_area_struct *vma,
|
static pte_t xen_ptep_modify_prot_start(struct vm_area_struct *vma,
|
||||||
unsigned long addr, pte_t *ptep)
|
unsigned long addr, pte_t *ptep)
|
||||||
{
|
{
|
||||||
/* Just return the pte as-is. We preserve the bits on commit */
|
/* Just return the pte as-is. We preserve the bits on commit */
|
||||||
trace_xen_mmu_ptep_modify_prot_start(vma->vm_mm, addr, ptep, *ptep);
|
trace_xen_mmu_ptep_modify_prot_start(vma->vm_mm, addr, ptep, *ptep);
|
||||||
return *ptep;
|
return *ptep;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xen_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr,
|
static void xen_ptep_modify_prot_commit(struct vm_area_struct *vma,
|
||||||
pte_t *ptep, pte_t pte)
|
unsigned long addr,
|
||||||
|
pte_t *ptep, pte_t pte)
|
||||||
{
|
{
|
||||||
struct mmu_update u;
|
struct mmu_update u;
|
||||||
|
|
||||||
|
@ -23,26 +23,21 @@
|
|||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
#include <linux/hardirq.h>
|
#include <linux/hardirq.h>
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/jump_label.h>
|
||||||
|
#include <linux/printk.h>
|
||||||
|
|
||||||
#include <asm/xen/hypercall.h>
|
#include <asm/xen/hypercall.h>
|
||||||
|
|
||||||
#include "multicalls.h"
|
#include "xen-ops.h"
|
||||||
#include "debugfs.h"
|
|
||||||
|
|
||||||
#define MC_BATCH 32
|
#define MC_BATCH 32
|
||||||
|
|
||||||
#define MC_DEBUG 0
|
|
||||||
|
|
||||||
#define MC_ARGS (MC_BATCH * 16)
|
#define MC_ARGS (MC_BATCH * 16)
|
||||||
|
|
||||||
|
|
||||||
struct mc_buffer {
|
struct mc_buffer {
|
||||||
unsigned mcidx, argidx, cbidx;
|
unsigned mcidx, argidx, cbidx;
|
||||||
struct multicall_entry entries[MC_BATCH];
|
struct multicall_entry entries[MC_BATCH];
|
||||||
#if MC_DEBUG
|
|
||||||
struct multicall_entry debug[MC_BATCH];
|
|
||||||
void *caller[MC_BATCH];
|
|
||||||
#endif
|
|
||||||
unsigned char args[MC_ARGS];
|
unsigned char args[MC_ARGS];
|
||||||
struct callback {
|
struct callback {
|
||||||
void (*fn)(void *);
|
void (*fn)(void *);
|
||||||
@ -50,13 +45,98 @@ struct mc_buffer {
|
|||||||
} callbacks[MC_BATCH];
|
} callbacks[MC_BATCH];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mc_debug_data {
|
||||||
|
struct multicall_entry entries[MC_BATCH];
|
||||||
|
void *caller[MC_BATCH];
|
||||||
|
size_t argsz[MC_BATCH];
|
||||||
|
unsigned long *args[MC_BATCH];
|
||||||
|
};
|
||||||
|
|
||||||
static DEFINE_PER_CPU(struct mc_buffer, mc_buffer);
|
static DEFINE_PER_CPU(struct mc_buffer, mc_buffer);
|
||||||
|
static struct mc_debug_data mc_debug_data_early __initdata;
|
||||||
|
static struct mc_debug_data __percpu *mc_debug_data __refdata =
|
||||||
|
&mc_debug_data_early;
|
||||||
DEFINE_PER_CPU(unsigned long, xen_mc_irq_flags);
|
DEFINE_PER_CPU(unsigned long, xen_mc_irq_flags);
|
||||||
|
|
||||||
|
static struct static_key mc_debug __ro_after_init;
|
||||||
|
static bool mc_debug_enabled __initdata;
|
||||||
|
|
||||||
|
static int __init xen_parse_mc_debug(char *arg)
|
||||||
|
{
|
||||||
|
mc_debug_enabled = true;
|
||||||
|
static_key_slow_inc(&mc_debug);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
early_param("xen_mc_debug", xen_parse_mc_debug);
|
||||||
|
|
||||||
|
static int __init mc_debug_enable(void)
|
||||||
|
{
|
||||||
|
struct mc_debug_data __percpu *mcdb;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (!mc_debug_enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mcdb = alloc_percpu(struct mc_debug_data);
|
||||||
|
if (!mcdb) {
|
||||||
|
pr_err("xen_mc_debug inactive\n");
|
||||||
|
static_key_slow_dec(&mc_debug);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Be careful when switching to percpu debug data. */
|
||||||
|
local_irq_save(flags);
|
||||||
|
xen_mc_flush();
|
||||||
|
mc_debug_data = mcdb;
|
||||||
|
local_irq_restore(flags);
|
||||||
|
|
||||||
|
pr_info("xen_mc_debug active\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
early_initcall(mc_debug_enable);
|
||||||
|
|
||||||
|
/* Number of parameters of hypercalls used via multicalls. */
|
||||||
|
static const uint8_t hpcpars[] = {
|
||||||
|
[__HYPERVISOR_mmu_update] = 4,
|
||||||
|
[__HYPERVISOR_stack_switch] = 2,
|
||||||
|
[__HYPERVISOR_fpu_taskswitch] = 1,
|
||||||
|
[__HYPERVISOR_update_descriptor] = 2,
|
||||||
|
[__HYPERVISOR_update_va_mapping] = 3,
|
||||||
|
[__HYPERVISOR_mmuext_op] = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void print_debug_data(struct mc_buffer *b, struct mc_debug_data *mcdb,
|
||||||
|
int idx)
|
||||||
|
{
|
||||||
|
unsigned int arg;
|
||||||
|
unsigned int opidx = mcdb->entries[idx].op & 0xff;
|
||||||
|
unsigned int pars = 0;
|
||||||
|
|
||||||
|
pr_err(" call %2d: op=%lu result=%ld caller=%pS ", idx + 1,
|
||||||
|
mcdb->entries[idx].op, b->entries[idx].result,
|
||||||
|
mcdb->caller[idx]);
|
||||||
|
if (opidx < ARRAY_SIZE(hpcpars))
|
||||||
|
pars = hpcpars[opidx];
|
||||||
|
if (pars) {
|
||||||
|
pr_cont("pars=");
|
||||||
|
for (arg = 0; arg < pars; arg++)
|
||||||
|
pr_cont("%lx ", mcdb->entries[idx].args[arg]);
|
||||||
|
}
|
||||||
|
if (mcdb->argsz[idx]) {
|
||||||
|
pr_cont("args=");
|
||||||
|
for (arg = 0; arg < mcdb->argsz[idx] / 8; arg++)
|
||||||
|
pr_cont("%lx ", mcdb->args[idx][arg]);
|
||||||
|
}
|
||||||
|
pr_cont("\n");
|
||||||
|
}
|
||||||
|
|
||||||
void xen_mc_flush(void)
|
void xen_mc_flush(void)
|
||||||
{
|
{
|
||||||
struct mc_buffer *b = this_cpu_ptr(&mc_buffer);
|
struct mc_buffer *b = this_cpu_ptr(&mc_buffer);
|
||||||
struct multicall_entry *mc;
|
struct multicall_entry *mc;
|
||||||
|
struct mc_debug_data *mcdb = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i;
|
int i;
|
||||||
@ -69,10 +149,11 @@ void xen_mc_flush(void)
|
|||||||
|
|
||||||
trace_xen_mc_flush(b->mcidx, b->argidx, b->cbidx);
|
trace_xen_mc_flush(b->mcidx, b->argidx, b->cbidx);
|
||||||
|
|
||||||
#if MC_DEBUG
|
if (static_key_false(&mc_debug)) {
|
||||||
memcpy(b->debug, b->entries,
|
mcdb = this_cpu_ptr(mc_debug_data);
|
||||||
b->mcidx * sizeof(struct multicall_entry));
|
memcpy(mcdb->entries, b->entries,
|
||||||
#endif
|
b->mcidx * sizeof(struct multicall_entry));
|
||||||
|
}
|
||||||
|
|
||||||
switch (b->mcidx) {
|
switch (b->mcidx) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -103,21 +184,14 @@ void xen_mc_flush(void)
|
|||||||
pr_err("%d of %d multicall(s) failed: cpu %d\n",
|
pr_err("%d of %d multicall(s) failed: cpu %d\n",
|
||||||
ret, b->mcidx, smp_processor_id());
|
ret, b->mcidx, smp_processor_id());
|
||||||
for (i = 0; i < b->mcidx; i++) {
|
for (i = 0; i < b->mcidx; i++) {
|
||||||
if (b->entries[i].result < 0) {
|
if (static_key_false(&mc_debug)) {
|
||||||
#if MC_DEBUG
|
print_debug_data(b, mcdb, i);
|
||||||
pr_err(" call %2d: op=%lu arg=[%lx] result=%ld\t%pS\n",
|
} else if (b->entries[i].result < 0) {
|
||||||
i + 1,
|
|
||||||
b->debug[i].op,
|
|
||||||
b->debug[i].args[0],
|
|
||||||
b->entries[i].result,
|
|
||||||
b->caller[i]);
|
|
||||||
#else
|
|
||||||
pr_err(" call %2d: op=%lu arg=[%lx] result=%ld\n",
|
pr_err(" call %2d: op=%lu arg=[%lx] result=%ld\n",
|
||||||
i + 1,
|
i + 1,
|
||||||
b->entries[i].op,
|
b->entries[i].op,
|
||||||
b->entries[i].args[0],
|
b->entries[i].args[0],
|
||||||
b->entries[i].result);
|
b->entries[i].result);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -155,9 +229,13 @@ struct multicall_space __xen_mc_entry(size_t args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret.mc = &b->entries[b->mcidx];
|
ret.mc = &b->entries[b->mcidx];
|
||||||
#if MC_DEBUG
|
if (static_key_false(&mc_debug)) {
|
||||||
b->caller[b->mcidx] = __builtin_return_address(0);
|
struct mc_debug_data *mcdb = this_cpu_ptr(mc_debug_data);
|
||||||
#endif
|
|
||||||
|
mcdb->caller[b->mcidx] = __builtin_return_address(0);
|
||||||
|
mcdb->argsz[b->mcidx] = args;
|
||||||
|
mcdb->args[b->mcidx] = (unsigned long *)(&b->args[argidx]);
|
||||||
|
}
|
||||||
b->mcidx++;
|
b->mcidx++;
|
||||||
ret.args = &b->args[argidx];
|
ret.args = &b->args[argidx];
|
||||||
b->argidx = argidx + args;
|
b->argidx = argidx + args;
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
#ifndef _XEN_MULTICALLS_H
|
|
||||||
#define _XEN_MULTICALLS_H
|
|
||||||
|
|
||||||
#include <trace/events/xen.h>
|
|
||||||
|
|
||||||
#include "xen-ops.h"
|
|
||||||
|
|
||||||
/* Multicalls */
|
|
||||||
struct multicall_space
|
|
||||||
{
|
|
||||||
struct multicall_entry *mc;
|
|
||||||
void *args;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Allocate room for a multicall and its args */
|
|
||||||
struct multicall_space __xen_mc_entry(size_t args);
|
|
||||||
|
|
||||||
DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags);
|
|
||||||
|
|
||||||
/* Call to start a batch of multiple __xen_mc_entry()s. Must be
|
|
||||||
paired with xen_mc_issue() */
|
|
||||||
static inline void xen_mc_batch(void)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
/* need to disable interrupts until this entry is complete */
|
|
||||||
local_irq_save(flags);
|
|
||||||
trace_xen_mc_batch(xen_get_lazy_mode());
|
|
||||||
__this_cpu_write(xen_mc_irq_flags, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct multicall_space xen_mc_entry(size_t args)
|
|
||||||
{
|
|
||||||
xen_mc_batch();
|
|
||||||
return __xen_mc_entry(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Flush all pending multicalls */
|
|
||||||
void xen_mc_flush(void);
|
|
||||||
|
|
||||||
/* Issue a multicall if we're not in a lazy mode */
|
|
||||||
static inline void xen_mc_issue(unsigned mode)
|
|
||||||
{
|
|
||||||
trace_xen_mc_issue(mode);
|
|
||||||
|
|
||||||
if ((xen_get_lazy_mode() & mode) == 0)
|
|
||||||
xen_mc_flush();
|
|
||||||
|
|
||||||
/* restore flags saved in xen_mc_batch */
|
|
||||||
local_irq_restore(this_cpu_read(xen_mc_irq_flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up a callback to be called when the current batch is flushed */
|
|
||||||
void xen_mc_callback(void (*fn)(void *), void *data);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to extend the arguments of the previous multicall command. The
|
|
||||||
* previous command's op must match. If it does, then it attempts to
|
|
||||||
* extend the argument space allocated to the multicall entry by
|
|
||||||
* arg_size bytes.
|
|
||||||
*
|
|
||||||
* The returned multicall_space will return with mc pointing to the
|
|
||||||
* command on success, or NULL on failure, and args pointing to the
|
|
||||||
* newly allocated space.
|
|
||||||
*/
|
|
||||||
struct multicall_space xen_mc_extend_args(unsigned long op, size_t arg_size);
|
|
||||||
|
|
||||||
#endif /* _XEN_MULTICALLS_H */
|
|
@ -81,7 +81,6 @@
|
|||||||
#include <xen/balloon.h>
|
#include <xen/balloon.h>
|
||||||
#include <xen/grant_table.h>
|
#include <xen/grant_table.h>
|
||||||
|
|
||||||
#include "multicalls.h"
|
|
||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
|
|
||||||
#define P2M_MID_PER_PAGE (PAGE_SIZE / sizeof(unsigned long *))
|
#define P2M_MID_PER_PAGE (PAGE_SIZE / sizeof(unsigned long *))
|
||||||
@ -730,7 +729,7 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
|
|||||||
* immediate unmapping.
|
* immediate unmapping.
|
||||||
*/
|
*/
|
||||||
map_ops[i].status = GNTST_general_error;
|
map_ops[i].status = GNTST_general_error;
|
||||||
unmap[0].host_addr = map_ops[i].host_addr,
|
unmap[0].host_addr = map_ops[i].host_addr;
|
||||||
unmap[0].handle = map_ops[i].handle;
|
unmap[0].handle = map_ops[i].handle;
|
||||||
map_ops[i].handle = INVALID_GRANT_HANDLE;
|
map_ops[i].handle = INVALID_GRANT_HANDLE;
|
||||||
if (map_ops[i].flags & GNTMAP_device_map)
|
if (map_ops[i].flags & GNTMAP_device_map)
|
||||||
@ -740,7 +739,7 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
|
|||||||
|
|
||||||
if (kmap_ops) {
|
if (kmap_ops) {
|
||||||
kmap_ops[i].status = GNTST_general_error;
|
kmap_ops[i].status = GNTST_general_error;
|
||||||
unmap[1].host_addr = kmap_ops[i].host_addr,
|
unmap[1].host_addr = kmap_ops[i].host_addr;
|
||||||
unmap[1].handle = kmap_ops[i].handle;
|
unmap[1].handle = kmap_ops[i].handle;
|
||||||
kmap_ops[i].handle = INVALID_GRANT_HANDLE;
|
kmap_ops[i].handle = INVALID_GRANT_HANDLE;
|
||||||
if (kmap_ops[i].flags & GNTMAP_device_map)
|
if (kmap_ops[i].flags & GNTMAP_device_map)
|
||||||
@ -795,7 +794,6 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
|
|||||||
|
|
||||||
#ifdef CONFIG_XEN_DEBUG_FS
|
#ifdef CONFIG_XEN_DEBUG_FS
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include "debugfs.h"
|
|
||||||
static int p2m_dump_show(struct seq_file *m, void *v)
|
static int p2m_dump_show(struct seq_file *m, void *v)
|
||||||
{
|
{
|
||||||
static const char * const type_name[] = {
|
static const char * const type_name[] = {
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include <xen/interface/xenpmu.h>
|
#include <xen/interface/xenpmu.h>
|
||||||
|
|
||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
#include "pmu.h"
|
|
||||||
|
|
||||||
/* x86_pmu.handle_irq definition */
|
/* x86_pmu.handle_irq definition */
|
||||||
#include "../events/perf_event.h"
|
#include "../events/perf_event.h"
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
#ifndef __XEN_PMU_H
|
|
||||||
#define __XEN_PMU_H
|
|
||||||
|
|
||||||
#include <xen/interface/xenpmu.h>
|
|
||||||
|
|
||||||
extern bool is_xen_pmu;
|
|
||||||
|
|
||||||
irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id);
|
|
||||||
#ifdef CONFIG_XEN_HAVE_VPMU
|
|
||||||
void xen_pmu_init(int cpu);
|
|
||||||
void xen_pmu_finish(int cpu);
|
|
||||||
#else
|
|
||||||
static inline void xen_pmu_init(int cpu) {}
|
|
||||||
static inline void xen_pmu_finish(int cpu) {}
|
|
||||||
#endif
|
|
||||||
bool pmu_msr_read(unsigned int msr, uint64_t *val, int *err);
|
|
||||||
bool pmu_msr_write(unsigned int msr, uint32_t low, uint32_t high, int *err);
|
|
||||||
int pmu_apic_update(uint32_t reg);
|
|
||||||
unsigned long long xen_read_pmc(int counter);
|
|
||||||
|
|
||||||
#endif /* __XEN_PMU_H */
|
|
@ -34,7 +34,6 @@
|
|||||||
#include <xen/features.h>
|
#include <xen/features.h>
|
||||||
#include <xen/hvc-console.h>
|
#include <xen/hvc-console.h>
|
||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
#include "mmu.h"
|
|
||||||
|
|
||||||
#define GB(x) ((uint64_t)(x) * 1024 * 1024 * 1024)
|
#define GB(x) ((uint64_t)(x) * 1024 * 1024 * 1024)
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include <xen/hvc-console.h>
|
#include <xen/hvc-console.h>
|
||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
#include "smp.h"
|
|
||||||
|
|
||||||
static DEFINE_PER_CPU(struct xen_common_irq, xen_resched_irq) = { .irq = -1 };
|
static DEFINE_PER_CPU(struct xen_common_irq, xen_resched_irq) = { .irq = -1 };
|
||||||
static DEFINE_PER_CPU(struct xen_common_irq, xen_callfunc_irq) = { .irq = -1 };
|
static DEFINE_PER_CPU(struct xen_common_irq, xen_callfunc_irq) = { .irq = -1 };
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
#ifndef _XEN_SMP_H
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
|
|
||||||
void asm_cpu_bringup_and_idle(void);
|
|
||||||
asmlinkage void cpu_bringup_and_idle(void);
|
|
||||||
|
|
||||||
extern void xen_send_IPI_mask(const struct cpumask *mask,
|
|
||||||
int vector);
|
|
||||||
extern void xen_send_IPI_mask_allbutself(const struct cpumask *mask,
|
|
||||||
int vector);
|
|
||||||
extern void xen_send_IPI_allbutself(int vector);
|
|
||||||
extern void xen_send_IPI_all(int vector);
|
|
||||||
extern void xen_send_IPI_self(int vector);
|
|
||||||
|
|
||||||
extern int xen_smp_intr_init(unsigned int cpu);
|
|
||||||
extern void xen_smp_intr_free(unsigned int cpu);
|
|
||||||
int xen_smp_intr_init_pv(unsigned int cpu);
|
|
||||||
void xen_smp_intr_free_pv(unsigned int cpu);
|
|
||||||
|
|
||||||
void xen_smp_count_cpus(void);
|
|
||||||
void xen_smp_cpus_done(unsigned int max_cpus);
|
|
||||||
|
|
||||||
void xen_smp_send_reschedule(int cpu);
|
|
||||||
void xen_smp_send_call_function_ipi(const struct cpumask *mask);
|
|
||||||
void xen_smp_send_call_function_single_ipi(int cpu);
|
|
||||||
|
|
||||||
void __noreturn xen_cpu_bringup_again(unsigned long stack);
|
|
||||||
|
|
||||||
struct xen_common_irq {
|
|
||||||
int irq;
|
|
||||||
char *name;
|
|
||||||
};
|
|
||||||
#else /* CONFIG_SMP */
|
|
||||||
|
|
||||||
static inline int xen_smp_intr_init(unsigned int cpu)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static inline void xen_smp_intr_free(unsigned int cpu) {}
|
|
||||||
|
|
||||||
static inline int xen_smp_intr_init_pv(unsigned int cpu)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static inline void xen_smp_intr_free_pv(unsigned int cpu) {}
|
|
||||||
static inline void xen_smp_count_cpus(void) { }
|
|
||||||
#endif /* CONFIG_SMP */
|
|
||||||
|
|
||||||
#endif
|
|
@ -5,8 +5,6 @@
|
|||||||
#include <xen/events.h>
|
#include <xen/events.h>
|
||||||
|
|
||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
#include "smp.h"
|
|
||||||
|
|
||||||
|
|
||||||
static void __init xen_hvm_smp_prepare_boot_cpu(void)
|
static void __init xen_hvm_smp_prepare_boot_cpu(void)
|
||||||
{
|
{
|
||||||
|
@ -46,9 +46,6 @@
|
|||||||
|
|
||||||
#include <xen/hvc-console.h>
|
#include <xen/hvc-console.h>
|
||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
#include "mmu.h"
|
|
||||||
#include "smp.h"
|
|
||||||
#include "pmu.h"
|
|
||||||
|
|
||||||
cpumask_var_t xen_cpu_initialized_map;
|
cpumask_var_t xen_cpu_initialized_map;
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
static DEFINE_PER_CPU(int, lock_kicker_irq) = -1;
|
static DEFINE_PER_CPU(int, lock_kicker_irq) = -1;
|
||||||
static DEFINE_PER_CPU(char *, irq_name);
|
static DEFINE_PER_CPU(char *, irq_name);
|
||||||
static DEFINE_PER_CPU(atomic_t, xen_qlock_wait_nest);
|
static DEFINE_PER_CPU(atomic_t, xen_qlock_wait_nest);
|
||||||
static bool xen_pvspin = true;
|
|
||||||
|
|
||||||
static void xen_qlock_kick(int cpu)
|
static void xen_qlock_kick(int cpu)
|
||||||
{
|
{
|
||||||
@ -68,7 +67,7 @@ void xen_init_lock_cpu(int cpu)
|
|||||||
int irq;
|
int irq;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (!xen_pvspin)
|
if (nopvspin)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
WARN(per_cpu(lock_kicker_irq, cpu) >= 0, "spinlock on CPU%d exists on IRQ%d!\n",
|
WARN(per_cpu(lock_kicker_irq, cpu) >= 0, "spinlock on CPU%d exists on IRQ%d!\n",
|
||||||
@ -95,7 +94,7 @@ void xen_uninit_lock_cpu(int cpu)
|
|||||||
{
|
{
|
||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
if (!xen_pvspin)
|
if (nopvspin)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
kfree(per_cpu(irq_name, cpu));
|
kfree(per_cpu(irq_name, cpu));
|
||||||
@ -125,10 +124,10 @@ PV_CALLEE_SAVE_REGS_THUNK(xen_vcpu_stolen);
|
|||||||
void __init xen_init_spinlocks(void)
|
void __init xen_init_spinlocks(void)
|
||||||
{
|
{
|
||||||
/* Don't need to use pvqspinlock code if there is only 1 vCPU. */
|
/* Don't need to use pvqspinlock code if there is only 1 vCPU. */
|
||||||
if (num_possible_cpus() == 1 || nopvspin)
|
if (num_possible_cpus() == 1)
|
||||||
xen_pvspin = false;
|
nopvspin = true;
|
||||||
|
|
||||||
if (!xen_pvspin) {
|
if (nopvspin) {
|
||||||
printk(KERN_DEBUG "xen: PV spinlocks disabled\n");
|
printk(KERN_DEBUG "xen: PV spinlocks disabled\n");
|
||||||
static_branch_disable(&virt_spin_lock_key);
|
static_branch_disable(&virt_spin_lock_key);
|
||||||
return;
|
return;
|
||||||
@ -143,12 +142,3 @@ void __init xen_init_spinlocks(void)
|
|||||||
pv_ops.lock.kick = xen_qlock_kick;
|
pv_ops.lock.kick = xen_qlock_kick;
|
||||||
pv_ops.lock.vcpu_is_preempted = PV_CALLEE_SAVE(xen_vcpu_stolen);
|
pv_ops.lock.vcpu_is_preempted = PV_CALLEE_SAVE(xen_vcpu_stolen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init int xen_parse_nopvspin(char *arg)
|
|
||||||
{
|
|
||||||
pr_notice("\"xen_nopvspin\" is deprecated, please use \"nopvspin\" instead\n");
|
|
||||||
xen_pvspin = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
early_param("xen_nopvspin", xen_parse_nopvspin);
|
|
||||||
|
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
#include <asm/fixmap.h>
|
#include <asm/fixmap.h>
|
||||||
|
|
||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
#include "mmu.h"
|
|
||||||
#include "pmu.h"
|
|
||||||
|
|
||||||
static DEFINE_PER_CPU(u64, spec_ctrl);
|
static DEFINE_PER_CPU(u64, spec_ctrl);
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include "xen-ops.h"
|
#include "xen-ops.h"
|
||||||
|
|
||||||
/* Minimum amount of time until next clock event fires */
|
/* Minimum amount of time until next clock event fires */
|
||||||
#define TIMER_SLOP 100000
|
#define TIMER_SLOP 1
|
||||||
|
|
||||||
static u64 xen_sched_clock_offset __read_mostly;
|
static u64 xen_sched_clock_offset __read_mostly;
|
||||||
|
|
||||||
|
@ -5,8 +5,15 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/clocksource.h>
|
#include <linux/clocksource.h>
|
||||||
#include <linux/irqreturn.h>
|
#include <linux/irqreturn.h>
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
|
#include <xen/interface/xenpmu.h>
|
||||||
#include <xen/xen-ops.h>
|
#include <xen/xen-ops.h>
|
||||||
|
|
||||||
|
#include <asm/page.h>
|
||||||
|
|
||||||
|
#include <trace/events/xen.h>
|
||||||
|
|
||||||
/* These are code, but not functions. Defined in entry.S */
|
/* These are code, but not functions. Defined in entry.S */
|
||||||
extern const char xen_failsafe_callback[];
|
extern const char xen_failsafe_callback[];
|
||||||
|
|
||||||
@ -23,14 +30,11 @@ void xen_copy_trap_info(struct trap_info *traps);
|
|||||||
|
|
||||||
DECLARE_PER_CPU_ALIGNED(struct vcpu_info, xen_vcpu_info);
|
DECLARE_PER_CPU_ALIGNED(struct vcpu_info, xen_vcpu_info);
|
||||||
DECLARE_PER_CPU(unsigned long, xen_cr3);
|
DECLARE_PER_CPU(unsigned long, xen_cr3);
|
||||||
DECLARE_PER_CPU(unsigned long, xen_current_cr3);
|
|
||||||
|
|
||||||
extern struct start_info *xen_start_info;
|
extern struct start_info *xen_start_info;
|
||||||
extern struct shared_info xen_dummy_shared_info;
|
extern struct shared_info xen_dummy_shared_info;
|
||||||
extern struct shared_info *HYPERVISOR_shared_info;
|
extern struct shared_info *HYPERVISOR_shared_info;
|
||||||
|
|
||||||
extern bool xen_fifo_events;
|
|
||||||
|
|
||||||
void xen_setup_mfn_list_list(void);
|
void xen_setup_mfn_list_list(void);
|
||||||
void xen_build_mfn_list_list(void);
|
void xen_build_mfn_list_list(void);
|
||||||
void xen_setup_machphys_mapping(void);
|
void xen_setup_machphys_mapping(void);
|
||||||
@ -177,4 +181,142 @@ static inline void xen_hvm_post_suspend(int suspend_cancelled) {}
|
|||||||
|
|
||||||
void xen_add_extra_mem(unsigned long start_pfn, unsigned long n_pfns);
|
void xen_add_extra_mem(unsigned long start_pfn, unsigned long n_pfns);
|
||||||
|
|
||||||
|
struct dentry * __init xen_init_debugfs(void);
|
||||||
|
|
||||||
|
enum pt_level {
|
||||||
|
PT_PGD,
|
||||||
|
PT_P4D,
|
||||||
|
PT_PUD,
|
||||||
|
PT_PMD,
|
||||||
|
PT_PTE
|
||||||
|
};
|
||||||
|
|
||||||
|
bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
|
||||||
|
void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
|
||||||
|
unsigned long xen_read_cr2_direct(void);
|
||||||
|
void xen_init_mmu_ops(void);
|
||||||
|
void xen_hvm_init_mmu_ops(void);
|
||||||
|
|
||||||
|
/* Multicalls */
|
||||||
|
struct multicall_space
|
||||||
|
{
|
||||||
|
struct multicall_entry *mc;
|
||||||
|
void *args;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Allocate room for a multicall and its args */
|
||||||
|
struct multicall_space __xen_mc_entry(size_t args);
|
||||||
|
|
||||||
|
DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags);
|
||||||
|
|
||||||
|
/* Call to start a batch of multiple __xen_mc_entry()s. Must be
|
||||||
|
paired with xen_mc_issue() */
|
||||||
|
static inline void xen_mc_batch(void)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
/* need to disable interrupts until this entry is complete */
|
||||||
|
local_irq_save(flags);
|
||||||
|
trace_xen_mc_batch(xen_get_lazy_mode());
|
||||||
|
__this_cpu_write(xen_mc_irq_flags, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct multicall_space xen_mc_entry(size_t args)
|
||||||
|
{
|
||||||
|
xen_mc_batch();
|
||||||
|
return __xen_mc_entry(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flush all pending multicalls */
|
||||||
|
void xen_mc_flush(void);
|
||||||
|
|
||||||
|
/* Issue a multicall if we're not in a lazy mode */
|
||||||
|
static inline void xen_mc_issue(unsigned mode)
|
||||||
|
{
|
||||||
|
trace_xen_mc_issue(mode);
|
||||||
|
|
||||||
|
if ((xen_get_lazy_mode() & mode) == 0)
|
||||||
|
xen_mc_flush();
|
||||||
|
|
||||||
|
/* restore flags saved in xen_mc_batch */
|
||||||
|
local_irq_restore(this_cpu_read(xen_mc_irq_flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up a callback to be called when the current batch is flushed */
|
||||||
|
void xen_mc_callback(void (*fn)(void *), void *data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to extend the arguments of the previous multicall command. The
|
||||||
|
* previous command's op must match. If it does, then it attempts to
|
||||||
|
* extend the argument space allocated to the multicall entry by
|
||||||
|
* arg_size bytes.
|
||||||
|
*
|
||||||
|
* The returned multicall_space will return with mc pointing to the
|
||||||
|
* command on success, or NULL on failure, and args pointing to the
|
||||||
|
* newly allocated space.
|
||||||
|
*/
|
||||||
|
struct multicall_space xen_mc_extend_args(unsigned long op, size_t arg_size);
|
||||||
|
|
||||||
|
extern bool is_xen_pmu;
|
||||||
|
|
||||||
|
irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id);
|
||||||
|
#ifdef CONFIG_XEN_HAVE_VPMU
|
||||||
|
void xen_pmu_init(int cpu);
|
||||||
|
void xen_pmu_finish(int cpu);
|
||||||
|
#else
|
||||||
|
static inline void xen_pmu_init(int cpu) {}
|
||||||
|
static inline void xen_pmu_finish(int cpu) {}
|
||||||
|
#endif
|
||||||
|
bool pmu_msr_read(unsigned int msr, uint64_t *val, int *err);
|
||||||
|
bool pmu_msr_write(unsigned int msr, uint32_t low, uint32_t high, int *err);
|
||||||
|
int pmu_apic_update(uint32_t reg);
|
||||||
|
unsigned long long xen_read_pmc(int counter);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
|
||||||
|
void asm_cpu_bringup_and_idle(void);
|
||||||
|
asmlinkage void cpu_bringup_and_idle(void);
|
||||||
|
|
||||||
|
extern void xen_send_IPI_mask(const struct cpumask *mask,
|
||||||
|
int vector);
|
||||||
|
extern void xen_send_IPI_mask_allbutself(const struct cpumask *mask,
|
||||||
|
int vector);
|
||||||
|
extern void xen_send_IPI_allbutself(int vector);
|
||||||
|
extern void xen_send_IPI_all(int vector);
|
||||||
|
extern void xen_send_IPI_self(int vector);
|
||||||
|
|
||||||
|
extern int xen_smp_intr_init(unsigned int cpu);
|
||||||
|
extern void xen_smp_intr_free(unsigned int cpu);
|
||||||
|
int xen_smp_intr_init_pv(unsigned int cpu);
|
||||||
|
void xen_smp_intr_free_pv(unsigned int cpu);
|
||||||
|
|
||||||
|
void xen_smp_count_cpus(void);
|
||||||
|
void xen_smp_cpus_done(unsigned int max_cpus);
|
||||||
|
|
||||||
|
void xen_smp_send_reschedule(int cpu);
|
||||||
|
void xen_smp_send_call_function_ipi(const struct cpumask *mask);
|
||||||
|
void xen_smp_send_call_function_single_ipi(int cpu);
|
||||||
|
|
||||||
|
void __noreturn xen_cpu_bringup_again(unsigned long stack);
|
||||||
|
|
||||||
|
struct xen_common_irq {
|
||||||
|
int irq;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
#else /* CONFIG_SMP */
|
||||||
|
|
||||||
|
static inline int xen_smp_intr_init(unsigned int cpu)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline void xen_smp_intr_free(unsigned int cpu) {}
|
||||||
|
|
||||||
|
static inline int xen_smp_intr_init_pv(unsigned int cpu)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline void xen_smp_intr_free_pv(unsigned int cpu) {}
|
||||||
|
static inline void xen_smp_count_cpus(void) { }
|
||||||
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
#endif /* XEN_OPS_H */
|
#endif /* XEN_OPS_H */
|
||||||
|
@ -729,4 +729,5 @@ static void __exit evtchn_cleanup(void)
|
|||||||
module_init(evtchn_init);
|
module_init(evtchn_init);
|
||||||
module_exit(evtchn_cleanup);
|
module_exit(evtchn_cleanup);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Xen /dev/xen/evtchn device driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -208,7 +208,7 @@ static void do_reboot(void)
|
|||||||
orderly_reboot();
|
orderly_reboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct shutdown_handler shutdown_handlers[] = {
|
static const struct shutdown_handler shutdown_handlers[] = {
|
||||||
{ "poweroff", true, do_poweroff },
|
{ "poweroff", true, do_poweroff },
|
||||||
{ "halt", false, do_poweroff },
|
{ "halt", false, do_poweroff },
|
||||||
{ "reboot", true, do_reboot },
|
{ "reboot", true, do_reboot },
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "privcmd.h"
|
#include "privcmd.h"
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Xen Mmap of hypercall buffers");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
struct privcmd_buf_private {
|
struct privcmd_buf_private {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/srcu.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
@ -48,6 +49,7 @@
|
|||||||
|
|
||||||
#include "privcmd.h"
|
#include "privcmd.h"
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Xen hypercall passthrough driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
#define PRIV_VMA_LOCKED ((void *)1)
|
#define PRIV_VMA_LOCKED ((void *)1)
|
||||||
@ -845,7 +847,8 @@ out:
|
|||||||
#ifdef CONFIG_XEN_PRIVCMD_EVENTFD
|
#ifdef CONFIG_XEN_PRIVCMD_EVENTFD
|
||||||
/* Irqfd support */
|
/* Irqfd support */
|
||||||
static struct workqueue_struct *irqfd_cleanup_wq;
|
static struct workqueue_struct *irqfd_cleanup_wq;
|
||||||
static DEFINE_MUTEX(irqfds_lock);
|
static DEFINE_SPINLOCK(irqfds_lock);
|
||||||
|
DEFINE_STATIC_SRCU(irqfds_srcu);
|
||||||
static LIST_HEAD(irqfds_list);
|
static LIST_HEAD(irqfds_list);
|
||||||
|
|
||||||
struct privcmd_kernel_irqfd {
|
struct privcmd_kernel_irqfd {
|
||||||
@ -873,6 +876,9 @@ static void irqfd_shutdown(struct work_struct *work)
|
|||||||
container_of(work, struct privcmd_kernel_irqfd, shutdown);
|
container_of(work, struct privcmd_kernel_irqfd, shutdown);
|
||||||
u64 cnt;
|
u64 cnt;
|
||||||
|
|
||||||
|
/* Make sure irqfd has been initialized in assign path */
|
||||||
|
synchronize_srcu(&irqfds_srcu);
|
||||||
|
|
||||||
eventfd_ctx_remove_wait_queue(kirqfd->eventfd, &kirqfd->wait, &cnt);
|
eventfd_ctx_remove_wait_queue(kirqfd->eventfd, &kirqfd->wait, &cnt);
|
||||||
eventfd_ctx_put(kirqfd->eventfd);
|
eventfd_ctx_put(kirqfd->eventfd);
|
||||||
kfree(kirqfd);
|
kfree(kirqfd);
|
||||||
@ -909,9 +915,11 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync, void *key)
|
|||||||
irqfd_inject(kirqfd);
|
irqfd_inject(kirqfd);
|
||||||
|
|
||||||
if (flags & EPOLLHUP) {
|
if (flags & EPOLLHUP) {
|
||||||
mutex_lock(&irqfds_lock);
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&irqfds_lock, flags);
|
||||||
irqfd_deactivate(kirqfd);
|
irqfd_deactivate(kirqfd);
|
||||||
mutex_unlock(&irqfds_lock);
|
spin_unlock_irqrestore(&irqfds_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -929,10 +937,11 @@ irqfd_poll_func(struct file *file, wait_queue_head_t *wqh, poll_table *pt)
|
|||||||
static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
||||||
{
|
{
|
||||||
struct privcmd_kernel_irqfd *kirqfd, *tmp;
|
struct privcmd_kernel_irqfd *kirqfd, *tmp;
|
||||||
|
unsigned long flags;
|
||||||
__poll_t events;
|
__poll_t events;
|
||||||
struct fd f;
|
struct fd f;
|
||||||
void *dm_op;
|
void *dm_op;
|
||||||
int ret;
|
int ret, idx;
|
||||||
|
|
||||||
kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL);
|
kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL);
|
||||||
if (!kirqfd)
|
if (!kirqfd)
|
||||||
@ -968,18 +977,19 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
|||||||
init_waitqueue_func_entry(&kirqfd->wait, irqfd_wakeup);
|
init_waitqueue_func_entry(&kirqfd->wait, irqfd_wakeup);
|
||||||
init_poll_funcptr(&kirqfd->pt, irqfd_poll_func);
|
init_poll_funcptr(&kirqfd->pt, irqfd_poll_func);
|
||||||
|
|
||||||
mutex_lock(&irqfds_lock);
|
spin_lock_irqsave(&irqfds_lock, flags);
|
||||||
|
|
||||||
list_for_each_entry(tmp, &irqfds_list, list) {
|
list_for_each_entry(tmp, &irqfds_list, list) {
|
||||||
if (kirqfd->eventfd == tmp->eventfd) {
|
if (kirqfd->eventfd == tmp->eventfd) {
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
mutex_unlock(&irqfds_lock);
|
spin_unlock_irqrestore(&irqfds_lock, flags);
|
||||||
goto error_eventfd;
|
goto error_eventfd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
idx = srcu_read_lock(&irqfds_srcu);
|
||||||
list_add_tail(&kirqfd->list, &irqfds_list);
|
list_add_tail(&kirqfd->list, &irqfds_list);
|
||||||
mutex_unlock(&irqfds_lock);
|
spin_unlock_irqrestore(&irqfds_lock, flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if there was an event already pending on the eventfd before we
|
* Check if there was an event already pending on the eventfd before we
|
||||||
@ -989,6 +999,8 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
|||||||
if (events & EPOLLIN)
|
if (events & EPOLLIN)
|
||||||
irqfd_inject(kirqfd);
|
irqfd_inject(kirqfd);
|
||||||
|
|
||||||
|
srcu_read_unlock(&irqfds_srcu, idx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not drop the file until the kirqfd is fully initialized, otherwise
|
* Do not drop the file until the kirqfd is fully initialized, otherwise
|
||||||
* we might race against the EPOLLHUP.
|
* we might race against the EPOLLHUP.
|
||||||
@ -1011,12 +1023,13 @@ static int privcmd_irqfd_deassign(struct privcmd_irqfd *irqfd)
|
|||||||
{
|
{
|
||||||
struct privcmd_kernel_irqfd *kirqfd;
|
struct privcmd_kernel_irqfd *kirqfd;
|
||||||
struct eventfd_ctx *eventfd;
|
struct eventfd_ctx *eventfd;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
eventfd = eventfd_ctx_fdget(irqfd->fd);
|
eventfd = eventfd_ctx_fdget(irqfd->fd);
|
||||||
if (IS_ERR(eventfd))
|
if (IS_ERR(eventfd))
|
||||||
return PTR_ERR(eventfd);
|
return PTR_ERR(eventfd);
|
||||||
|
|
||||||
mutex_lock(&irqfds_lock);
|
spin_lock_irqsave(&irqfds_lock, flags);
|
||||||
|
|
||||||
list_for_each_entry(kirqfd, &irqfds_list, list) {
|
list_for_each_entry(kirqfd, &irqfds_list, list) {
|
||||||
if (kirqfd->eventfd == eventfd) {
|
if (kirqfd->eventfd == eventfd) {
|
||||||
@ -1025,7 +1038,7 @@ static int privcmd_irqfd_deassign(struct privcmd_irqfd *irqfd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&irqfds_lock);
|
spin_unlock_irqrestore(&irqfds_lock, flags);
|
||||||
|
|
||||||
eventfd_ctx_put(eventfd);
|
eventfd_ctx_put(eventfd);
|
||||||
|
|
||||||
@ -1073,13 +1086,14 @@ static int privcmd_irqfd_init(void)
|
|||||||
static void privcmd_irqfd_exit(void)
|
static void privcmd_irqfd_exit(void)
|
||||||
{
|
{
|
||||||
struct privcmd_kernel_irqfd *kirqfd, *tmp;
|
struct privcmd_kernel_irqfd *kirqfd, *tmp;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
mutex_lock(&irqfds_lock);
|
spin_lock_irqsave(&irqfds_lock, flags);
|
||||||
|
|
||||||
list_for_each_entry_safe(kirqfd, tmp, &irqfds_list, list)
|
list_for_each_entry_safe(kirqfd, tmp, &irqfds_list, list)
|
||||||
irqfd_deactivate(kirqfd);
|
irqfd_deactivate(kirqfd);
|
||||||
|
|
||||||
mutex_unlock(&irqfds_lock);
|
spin_unlock_irqrestore(&irqfds_lock, flags);
|
||||||
|
|
||||||
destroy_workqueue(irqfd_cleanup_wq);
|
destroy_workqueue(irqfd_cleanup_wq);
|
||||||
}
|
}
|
||||||
|
@ -1708,5 +1708,6 @@ static void __exit xen_pcibk_cleanup(void)
|
|||||||
module_init(xen_pcibk_init);
|
module_init(xen_pcibk_init);
|
||||||
module_exit(xen_pcibk_cleanup);
|
module_exit(xen_pcibk_cleanup);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Xen PCI-device stub driver");
|
||||||
MODULE_LICENSE("Dual BSD/GPL");
|
MODULE_LICENSE("Dual BSD/GPL");
|
||||||
MODULE_ALIAS("xen-backend:pci");
|
MODULE_ALIAS("xen-backend:pci");
|
||||||
|
@ -144,4 +144,6 @@ static inline void xen_evtchn_close(evtchn_port_t port)
|
|||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern bool xen_fifo_events;
|
||||||
|
|
||||||
#endif /* _XEN_EVENTS_H */
|
#endif /* _XEN_EVENTS_H */
|
||||||
|
@ -583,7 +583,7 @@ EXPORT_SYMBOL(queued_spin_lock_slowpath);
|
|||||||
#include "qspinlock_paravirt.h"
|
#include "qspinlock_paravirt.h"
|
||||||
#include "qspinlock.c"
|
#include "qspinlock.c"
|
||||||
|
|
||||||
bool nopvspin __initdata;
|
bool nopvspin;
|
||||||
static __init int parse_nopvspin(char *arg)
|
static __init int parse_nopvspin(char *arg)
|
||||||
{
|
{
|
||||||
nopvspin = true;
|
nopvspin = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user