Merge tag 'stable/for-linus-3.5-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
Pull Xen updates from Konrad Rzeszutek Wilk: "Features: * Extend the APIC ops implementation and add IRQ_WORKER vector support so that 'perf' can work properly. * Fix self-ballooning code, and balloon logic when booting as initial domain. * Move array printing code to generic debugfs * Support XenBus domains. * Lazily free grants when a domain is dead/non-existent. * In M2P code use batching calls Bug-fixes: * Fix NULL dereference in allocation failure path (hvc_xen) * Fix unbinding of IRQ_WORKER vector during vCPU hot-unplug * Fix HVM guest resume - we would leak an PIRQ value instead of reusing the existing one." Fix up add-add onflicts in arch/x86/xen/enlighten.c due to addition of apic ipi interface next to the new apic_id functions. * tag 'stable/for-linus-3.5-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: xen: do not map the same GSI twice in PVHVM guests. hvc_xen: NULL dereference on allocation failure xen: Add selfballoning memory reservation tunable. xenbus: Add support for xenbus backend in stub domain xen/smp: unbind irqworkX when unplugging vCPUs. xen: enter/exit lazy_mmu_mode around m2p_override calls xen/acpi/sleep: Enable ACPI sleep via the __acpi_os_prepare_sleep xen: implement IRQ_WORK_VECTOR handler xen: implement apic ipi interface xen/setup: update VA mapping when releasing memory during setup xen/setup: Combine the two hypercall functions - since they are quite similar. xen/setup: Populate freed MFNs from non-RAM E820 entries and gaps to E820 RAM xen/setup: Only print "Freeing XXX-YYY pfn range: Z pages freed" if Z > 0 xen/gnttab: add deferred freeing logic debugfs: Add support to print u32 array in debugfs xen/p2m: An early bootup variant of set_phys_to_machine xen/p2m: Collapse early_alloc_p2m_middle redundant checks. xen/p2m: Allow alloc_p2m_middle to call reserve_brk depending on argument xen/p2m: Move code around to allow for better re-usage.
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/irq_work.h>
|
||||
|
||||
#include <asm/paravirt.h>
|
||||
#include <asm/desc.h>
|
||||
@@ -41,10 +42,12 @@ cpumask_var_t xen_cpu_initialized_map;
|
||||
static DEFINE_PER_CPU(int, xen_resched_irq);
|
||||
static DEFINE_PER_CPU(int, xen_callfunc_irq);
|
||||
static DEFINE_PER_CPU(int, xen_callfuncsingle_irq);
|
||||
static DEFINE_PER_CPU(int, xen_irq_work);
|
||||
static DEFINE_PER_CPU(int, xen_debug_irq) = -1;
|
||||
|
||||
static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id);
|
||||
static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id);
|
||||
static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id);
|
||||
|
||||
/*
|
||||
* Reschedule call back.
|
||||
@@ -143,6 +146,17 @@ static int xen_smp_intr_init(unsigned int cpu)
|
||||
goto fail;
|
||||
per_cpu(xen_callfuncsingle_irq, cpu) = rc;
|
||||
|
||||
callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
|
||||
rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
|
||||
cpu,
|
||||
xen_irq_work_interrupt,
|
||||
IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
|
||||
callfunc_name,
|
||||
NULL);
|
||||
if (rc < 0)
|
||||
goto fail;
|
||||
per_cpu(xen_irq_work, cpu) = rc;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -155,6 +169,8 @@ static int xen_smp_intr_init(unsigned int cpu)
|
||||
if (per_cpu(xen_callfuncsingle_irq, cpu) >= 0)
|
||||
unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu),
|
||||
NULL);
|
||||
if (per_cpu(xen_irq_work, cpu) >= 0)
|
||||
unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -407,6 +423,7 @@ static void xen_cpu_die(unsigned int cpu)
|
||||
unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
|
||||
unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
|
||||
unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
|
||||
unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
|
||||
xen_uninit_lock_cpu(cpu);
|
||||
xen_teardown_timer(cpu);
|
||||
|
||||
@@ -469,8 +486,8 @@ static void xen_smp_send_reschedule(int cpu)
|
||||
xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR);
|
||||
}
|
||||
|
||||
static void xen_send_IPI_mask(const struct cpumask *mask,
|
||||
enum ipi_vector vector)
|
||||
static void __xen_send_IPI_mask(const struct cpumask *mask,
|
||||
int vector)
|
||||
{
|
||||
unsigned cpu;
|
||||
|
||||
@@ -482,7 +499,7 @@ static void xen_smp_send_call_function_ipi(const struct cpumask *mask)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
xen_send_IPI_mask(mask, XEN_CALL_FUNCTION_VECTOR);
|
||||
__xen_send_IPI_mask(mask, XEN_CALL_FUNCTION_VECTOR);
|
||||
|
||||
/* Make sure other vcpus get a chance to run if they need to. */
|
||||
for_each_cpu(cpu, mask) {
|
||||
@@ -495,10 +512,86 @@ static void xen_smp_send_call_function_ipi(const struct cpumask *mask)
|
||||
|
||||
static void xen_smp_send_call_function_single_ipi(int cpu)
|
||||
{
|
||||
xen_send_IPI_mask(cpumask_of(cpu),
|
||||
__xen_send_IPI_mask(cpumask_of(cpu),
|
||||
XEN_CALL_FUNCTION_SINGLE_VECTOR);
|
||||
}
|
||||
|
||||
static inline int xen_map_vector(int vector)
|
||||
{
|
||||
int xen_vector;
|
||||
|
||||
switch (vector) {
|
||||
case RESCHEDULE_VECTOR:
|
||||
xen_vector = XEN_RESCHEDULE_VECTOR;
|
||||
break;
|
||||
case CALL_FUNCTION_VECTOR:
|
||||
xen_vector = XEN_CALL_FUNCTION_VECTOR;
|
||||
break;
|
||||
case CALL_FUNCTION_SINGLE_VECTOR:
|
||||
xen_vector = XEN_CALL_FUNCTION_SINGLE_VECTOR;
|
||||
break;
|
||||
case IRQ_WORK_VECTOR:
|
||||
xen_vector = XEN_IRQ_WORK_VECTOR;
|
||||
break;
|
||||
default:
|
||||
xen_vector = -1;
|
||||
printk(KERN_ERR "xen: vector 0x%x is not implemented\n",
|
||||
vector);
|
||||
}
|
||||
|
||||
return xen_vector;
|
||||
}
|
||||
|
||||
void xen_send_IPI_mask(const struct cpumask *mask,
|
||||
int vector)
|
||||
{
|
||||
int xen_vector = xen_map_vector(vector);
|
||||
|
||||
if (xen_vector >= 0)
|
||||
__xen_send_IPI_mask(mask, xen_vector);
|
||||
}
|
||||
|
||||
void xen_send_IPI_all(int vector)
|
||||
{
|
||||
int xen_vector = xen_map_vector(vector);
|
||||
|
||||
if (xen_vector >= 0)
|
||||
__xen_send_IPI_mask(cpu_online_mask, xen_vector);
|
||||
}
|
||||
|
||||
void xen_send_IPI_self(int vector)
|
||||
{
|
||||
int xen_vector = xen_map_vector(vector);
|
||||
|
||||
if (xen_vector >= 0)
|
||||
xen_send_IPI_one(smp_processor_id(), xen_vector);
|
||||
}
|
||||
|
||||
void xen_send_IPI_mask_allbutself(const struct cpumask *mask,
|
||||
int vector)
|
||||
{
|
||||
unsigned cpu;
|
||||
unsigned int this_cpu = smp_processor_id();
|
||||
|
||||
if (!(num_online_cpus() > 1))
|
||||
return;
|
||||
|
||||
for_each_cpu_and(cpu, mask, cpu_online_mask) {
|
||||
if (this_cpu == cpu)
|
||||
continue;
|
||||
|
||||
xen_smp_send_call_function_single_ipi(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
void xen_send_IPI_allbutself(int vector)
|
||||
{
|
||||
int xen_vector = xen_map_vector(vector);
|
||||
|
||||
if (xen_vector >= 0)
|
||||
xen_send_IPI_mask_allbutself(cpu_online_mask, xen_vector);
|
||||
}
|
||||
|
||||
static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
irq_enter();
|
||||
@@ -519,6 +612,16 @@ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
irq_enter();
|
||||
irq_work_run();
|
||||
inc_irq_stat(apic_irq_work_irqs);
|
||||
irq_exit();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct smp_ops xen_smp_ops __initconst = {
|
||||
.smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu,
|
||||
.smp_prepare_cpus = xen_smp_prepare_cpus,
|
||||
@@ -565,6 +668,7 @@ static void xen_hvm_cpu_die(unsigned int cpu)
|
||||
unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
|
||||
unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
|
||||
unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
|
||||
unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
|
||||
native_cpu_die(cpu);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user