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
|
||||
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]
|
||||
Format: <bool>
|
||||
Select whether to always use non-faulting (safe) MSR
|
||||
access functions when running as Xen PV guest. The
|
||||
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]
|
||||
Disables the PV optimizations forcing the HVM guest to
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
map_ops[i].handle = INVALID_GRANT_HANDLE;
|
||||
if (map_ops[i].flags & GNTMAP_device_map)
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include <xen/xen.h>
|
||||
#include <xen/interface/physdev.h>
|
||||
#include "xen-ops.h"
|
||||
#include "pmu.h"
|
||||
#include "smp.h"
|
||||
|
||||
static unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "debugfs.h"
|
||||
#include "xen-ops.h"
|
||||
|
||||
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 "xen-ops.h"
|
||||
#include "smp.h"
|
||||
#include "pmu.h"
|
||||
|
||||
EXPORT_SYMBOL_GPL(hypercall_page);
|
||||
|
||||
|
@ -28,8 +28,6 @@
|
||||
#include <asm/xen/page.h>
|
||||
|
||||
#include "xen-ops.h"
|
||||
#include "mmu.h"
|
||||
#include "smp.h"
|
||||
|
||||
static unsigned long shared_info_pfn;
|
||||
|
||||
|
@ -85,10 +85,6 @@
|
||||
#endif
|
||||
|
||||
#include "xen-ops.h"
|
||||
#include "mmu.h"
|
||||
#include "smp.h"
|
||||
#include "multicalls.h"
|
||||
#include "pmu.h"
|
||||
|
||||
#include "../kernel/cpu/cpu.h" /* get_cpu_cap() */
|
||||
|
||||
|
@ -5,8 +5,7 @@
|
||||
#include <asm/xen/hypercall.h>
|
||||
#include <xen/interface/memory.h>
|
||||
|
||||
#include "multicalls.h"
|
||||
#include "mmu.h"
|
||||
#include "xen-ops.h"
|
||||
|
||||
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/hvm.h>
|
||||
|
||||
#include "mmu.h"
|
||||
#include "xen-ops.h"
|
||||
|
||||
#ifdef CONFIG_PROC_VMCORE
|
||||
/*
|
||||
|
@ -82,9 +82,7 @@
|
||||
#include <xen/hvc-console.h>
|
||||
#include <xen/swiotlb-xen.h>
|
||||
|
||||
#include "multicalls.h"
|
||||
#include "mmu.h"
|
||||
#include "debugfs.h"
|
||||
#include "xen-ops.h"
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
|
||||
@ -305,7 +303,7 @@ static void xen_set_pte(pte_t *ptep, pte_t 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)
|
||||
{
|
||||
/* Just return the pte as-is. We preserve the bits on commit */
|
||||
@ -313,7 +311,8 @@ pte_t xen_ptep_modify_prot_start(struct vm_area_struct *vma,
|
||||
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,
|
||||
unsigned long addr,
|
||||
pte_t *ptep, pte_t pte)
|
||||
{
|
||||
struct mmu_update u;
|
||||
|
@ -23,26 +23,21 @@
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/jump_label.h>
|
||||
#include <linux/printk.h>
|
||||
|
||||
#include <asm/xen/hypercall.h>
|
||||
|
||||
#include "multicalls.h"
|
||||
#include "debugfs.h"
|
||||
#include "xen-ops.h"
|
||||
|
||||
#define MC_BATCH 32
|
||||
|
||||
#define MC_DEBUG 0
|
||||
|
||||
#define MC_ARGS (MC_BATCH * 16)
|
||||
|
||||
|
||||
struct mc_buffer {
|
||||
unsigned mcidx, argidx, cbidx;
|
||||
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];
|
||||
struct callback {
|
||||
void (*fn)(void *);
|
||||
@ -50,13 +45,98 @@ struct mc_buffer {
|
||||
} 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 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);
|
||||
|
||||
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)
|
||||
{
|
||||
struct mc_buffer *b = this_cpu_ptr(&mc_buffer);
|
||||
struct multicall_entry *mc;
|
||||
struct mc_debug_data *mcdb = NULL;
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
@ -69,10 +149,11 @@ void xen_mc_flush(void)
|
||||
|
||||
trace_xen_mc_flush(b->mcidx, b->argidx, b->cbidx);
|
||||
|
||||
#if MC_DEBUG
|
||||
memcpy(b->debug, b->entries,
|
||||
if (static_key_false(&mc_debug)) {
|
||||
mcdb = this_cpu_ptr(mc_debug_data);
|
||||
memcpy(mcdb->entries, b->entries,
|
||||
b->mcidx * sizeof(struct multicall_entry));
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (b->mcidx) {
|
||||
case 0:
|
||||
@ -103,21 +184,14 @@ void xen_mc_flush(void)
|
||||
pr_err("%d of %d multicall(s) failed: cpu %d\n",
|
||||
ret, b->mcidx, smp_processor_id());
|
||||
for (i = 0; i < b->mcidx; i++) {
|
||||
if (b->entries[i].result < 0) {
|
||||
#if MC_DEBUG
|
||||
pr_err(" call %2d: op=%lu arg=[%lx] result=%ld\t%pS\n",
|
||||
i + 1,
|
||||
b->debug[i].op,
|
||||
b->debug[i].args[0],
|
||||
b->entries[i].result,
|
||||
b->caller[i]);
|
||||
#else
|
||||
if (static_key_false(&mc_debug)) {
|
||||
print_debug_data(b, mcdb, i);
|
||||
} else if (b->entries[i].result < 0) {
|
||||
pr_err(" call %2d: op=%lu arg=[%lx] result=%ld\n",
|
||||
i + 1,
|
||||
b->entries[i].op,
|
||||
b->entries[i].args[0],
|
||||
b->entries[i].result);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,9 +229,13 @@ struct multicall_space __xen_mc_entry(size_t args)
|
||||
}
|
||||
|
||||
ret.mc = &b->entries[b->mcidx];
|
||||
#if MC_DEBUG
|
||||
b->caller[b->mcidx] = __builtin_return_address(0);
|
||||
#endif
|
||||
if (static_key_false(&mc_debug)) {
|
||||
struct mc_debug_data *mcdb = this_cpu_ptr(mc_debug_data);
|
||||
|
||||
mcdb->caller[b->mcidx] = __builtin_return_address(0);
|
||||
mcdb->argsz[b->mcidx] = args;
|
||||
mcdb->args[b->mcidx] = (unsigned long *)(&b->args[argidx]);
|
||||
}
|
||||
b->mcidx++;
|
||||
ret.args = &b->args[argidx];
|
||||
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/grant_table.h>
|
||||
|
||||
#include "multicalls.h"
|
||||
#include "xen-ops.h"
|
||||
|
||||
#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.
|
||||
*/
|
||||
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;
|
||||
map_ops[i].handle = INVALID_GRANT_HANDLE;
|
||||
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) {
|
||||
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;
|
||||
kmap_ops[i].handle = INVALID_GRANT_HANDLE;
|
||||
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
|
||||
#include <linux/debugfs.h>
|
||||
#include "debugfs.h"
|
||||
static int p2m_dump_show(struct seq_file *m, void *v)
|
||||
{
|
||||
static const char * const type_name[] = {
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <xen/interface/xenpmu.h>
|
||||
|
||||
#include "xen-ops.h"
|
||||
#include "pmu.h"
|
||||
|
||||
/* x86_pmu.handle_irq definition */
|
||||
#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/hvc-console.h>
|
||||
#include "xen-ops.h"
|
||||
#include "mmu.h"
|
||||
|
||||
#define GB(x) ((uint64_t)(x) * 1024 * 1024 * 1024)
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include <xen/hvc-console.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_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-ops.h"
|
||||
#include "smp.h"
|
||||
|
||||
|
||||
static void __init xen_hvm_smp_prepare_boot_cpu(void)
|
||||
{
|
||||
|
@ -46,9 +46,6 @@
|
||||
|
||||
#include <xen/hvc-console.h>
|
||||
#include "xen-ops.h"
|
||||
#include "mmu.h"
|
||||
#include "smp.h"
|
||||
#include "pmu.h"
|
||||
|
||||
cpumask_var_t xen_cpu_initialized_map;
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
static DEFINE_PER_CPU(int, lock_kicker_irq) = -1;
|
||||
static DEFINE_PER_CPU(char *, irq_name);
|
||||
static DEFINE_PER_CPU(atomic_t, xen_qlock_wait_nest);
|
||||
static bool xen_pvspin = true;
|
||||
|
||||
static void xen_qlock_kick(int cpu)
|
||||
{
|
||||
@ -68,7 +67,7 @@ void xen_init_lock_cpu(int cpu)
|
||||
int irq;
|
||||
char *name;
|
||||
|
||||
if (!xen_pvspin)
|
||||
if (nopvspin)
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
if (!xen_pvspin)
|
||||
if (nopvspin)
|
||||
return;
|
||||
|
||||
kfree(per_cpu(irq_name, cpu));
|
||||
@ -125,10 +124,10 @@ PV_CALLEE_SAVE_REGS_THUNK(xen_vcpu_stolen);
|
||||
void __init xen_init_spinlocks(void)
|
||||
{
|
||||
/* Don't need to use pvqspinlock code if there is only 1 vCPU. */
|
||||
if (num_possible_cpus() == 1 || nopvspin)
|
||||
xen_pvspin = false;
|
||||
if (num_possible_cpus() == 1)
|
||||
nopvspin = true;
|
||||
|
||||
if (!xen_pvspin) {
|
||||
if (nopvspin) {
|
||||
printk(KERN_DEBUG "xen: PV spinlocks disabled\n");
|
||||
static_branch_disable(&virt_spin_lock_key);
|
||||
return;
|
||||
@ -143,12 +142,3 @@ void __init xen_init_spinlocks(void)
|
||||
pv_ops.lock.kick = xen_qlock_kick;
|
||||
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 "xen-ops.h"
|
||||
#include "mmu.h"
|
||||
#include "pmu.h"
|
||||
|
||||
static DEFINE_PER_CPU(u64, spec_ctrl);
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "xen-ops.h"
|
||||
|
||||
/* 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;
|
||||
|
||||
|
@ -5,8 +5,15 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#include <xen/interface/xenpmu.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 */
|
||||
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(unsigned long, xen_cr3);
|
||||
DECLARE_PER_CPU(unsigned long, xen_current_cr3);
|
||||
|
||||
extern struct start_info *xen_start_info;
|
||||
extern struct shared_info xen_dummy_shared_info;
|
||||
extern struct shared_info *HYPERVISOR_shared_info;
|
||||
|
||||
extern bool xen_fifo_events;
|
||||
|
||||
void xen_setup_mfn_list_list(void);
|
||||
void xen_build_mfn_list_list(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);
|
||||
|
||||
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 */
|
||||
|
@ -729,4 +729,5 @@ static void __exit evtchn_cleanup(void)
|
||||
module_init(evtchn_init);
|
||||
module_exit(evtchn_cleanup);
|
||||
|
||||
MODULE_DESCRIPTION("Xen /dev/xen/evtchn device driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -208,7 +208,7 @@ static void do_reboot(void)
|
||||
orderly_reboot();
|
||||
}
|
||||
|
||||
static struct shutdown_handler shutdown_handlers[] = {
|
||||
static const struct shutdown_handler shutdown_handlers[] = {
|
||||
{ "poweroff", true, do_poweroff },
|
||||
{ "halt", false, do_poweroff },
|
||||
{ "reboot", true, do_reboot },
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "privcmd.h"
|
||||
|
||||
MODULE_DESCRIPTION("Xen Mmap of hypercall buffers");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
struct privcmd_buf_private {
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/srcu.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/errno.h>
|
||||
@ -48,6 +49,7 @@
|
||||
|
||||
#include "privcmd.h"
|
||||
|
||||
MODULE_DESCRIPTION("Xen hypercall passthrough driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#define PRIV_VMA_LOCKED ((void *)1)
|
||||
@ -845,7 +847,8 @@ out:
|
||||
#ifdef CONFIG_XEN_PRIVCMD_EVENTFD
|
||||
/* Irqfd support */
|
||||
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);
|
||||
|
||||
struct privcmd_kernel_irqfd {
|
||||
@ -873,6 +876,9 @@ static void irqfd_shutdown(struct work_struct *work)
|
||||
container_of(work, struct privcmd_kernel_irqfd, shutdown);
|
||||
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_put(kirqfd->eventfd);
|
||||
kfree(kirqfd);
|
||||
@ -909,9 +915,11 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync, void *key)
|
||||
irqfd_inject(kirqfd);
|
||||
|
||||
if (flags & EPOLLHUP) {
|
||||
mutex_lock(&irqfds_lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&irqfds_lock, flags);
|
||||
irqfd_deactivate(kirqfd);
|
||||
mutex_unlock(&irqfds_lock);
|
||||
spin_unlock_irqrestore(&irqfds_lock, flags);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct privcmd_kernel_irqfd *kirqfd, *tmp;
|
||||
unsigned long flags;
|
||||
__poll_t events;
|
||||
struct fd f;
|
||||
void *dm_op;
|
||||
int ret;
|
||||
int ret, idx;
|
||||
|
||||
kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL);
|
||||
if (!kirqfd)
|
||||
@ -968,18 +977,19 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
||||
init_waitqueue_func_entry(&kirqfd->wait, irqfd_wakeup);
|
||||
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) {
|
||||
if (kirqfd->eventfd == tmp->eventfd) {
|
||||
ret = -EBUSY;
|
||||
mutex_unlock(&irqfds_lock);
|
||||
spin_unlock_irqrestore(&irqfds_lock, flags);
|
||||
goto error_eventfd;
|
||||
}
|
||||
}
|
||||
|
||||
idx = srcu_read_lock(&irqfds_srcu);
|
||||
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
|
||||
@ -989,6 +999,8 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
||||
if (events & EPOLLIN)
|
||||
irqfd_inject(kirqfd);
|
||||
|
||||
srcu_read_unlock(&irqfds_srcu, idx);
|
||||
|
||||
/*
|
||||
* Do not drop the file until the kirqfd is fully initialized, otherwise
|
||||
* 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 eventfd_ctx *eventfd;
|
||||
unsigned long flags;
|
||||
|
||||
eventfd = eventfd_ctx_fdget(irqfd->fd);
|
||||
if (IS_ERR(eventfd))
|
||||
return PTR_ERR(eventfd);
|
||||
|
||||
mutex_lock(&irqfds_lock);
|
||||
spin_lock_irqsave(&irqfds_lock, flags);
|
||||
|
||||
list_for_each_entry(kirqfd, &irqfds_list, list) {
|
||||
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);
|
||||
|
||||
@ -1073,13 +1086,14 @@ static int privcmd_irqfd_init(void)
|
||||
static void privcmd_irqfd_exit(void)
|
||||
{
|
||||
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)
|
||||
irqfd_deactivate(kirqfd);
|
||||
|
||||
mutex_unlock(&irqfds_lock);
|
||||
spin_unlock_irqrestore(&irqfds_lock, flags);
|
||||
|
||||
destroy_workqueue(irqfd_cleanup_wq);
|
||||
}
|
||||
|
@ -1708,5 +1708,6 @@ static void __exit xen_pcibk_cleanup(void)
|
||||
module_init(xen_pcibk_init);
|
||||
module_exit(xen_pcibk_cleanup);
|
||||
|
||||
MODULE_DESCRIPTION("Xen PCI-device stub driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_ALIAS("xen-backend:pci");
|
||||
|
@ -144,4 +144,6 @@ static inline void xen_evtchn_close(evtchn_port_t port)
|
||||
BUG();
|
||||
}
|
||||
|
||||
extern bool xen_fifo_events;
|
||||
|
||||
#endif /* _XEN_EVENTS_H */
|
||||
|
@ -583,7 +583,7 @@ EXPORT_SYMBOL(queued_spin_lock_slowpath);
|
||||
#include "qspinlock_paravirt.h"
|
||||
#include "qspinlock.c"
|
||||
|
||||
bool nopvspin __initdata;
|
||||
bool nopvspin;
|
||||
static __init int parse_nopvspin(char *arg)
|
||||
{
|
||||
nopvspin = true;
|
||||
|
Loading…
Reference in New Issue
Block a user