Skip to content

Commit

Permalink
Merge tag 'for-linus-4.9-rc0-tag' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/xen/tip

Pull xen updates from David Vrabel:
 "xen features and fixes for 4.9:

   - switch to new CPU hotplug mechanism

   - support driver_override in pciback

   - require vector callback for HVM guests (the alternate mechanism via
     the platform device has been broken for ages)"

* tag 'for-linus-4.9-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  xen/x86: Update topology map for PV VCPUs
  xen/x86: Initialize per_cpu(xen_vcpu, 0) a little earlier
  xen/pciback: support driver_override
  xen/pciback: avoid multiple entries in slot list
  xen/pciback: simplify pcistub device handling
  xen: Remove event channel notification through Xen PCI platform device
  xen/events: Convert to hotplug state machine
  xen/x86: Convert to hotplug state machine
  x86/xen: add missing \n at end of printk warning message
  xen/grant-table: Use kmalloc_array() in arch_gnttab_valloc()
  xen: Make VPMU init message look less scary
  xen: rename xen_pmu_init() in sys-hypervisor.c
  hotplug: Prevent alloc/free of irq descriptors during cpu up/down (again)
  xen/x86: Move irq allocation from Xen smp_op.cpu_up()
  • Loading branch information
torvalds committed Oct 6, 2016
2 parents 6218590 + a6a198b commit 541efb7
Show file tree
Hide file tree
Showing 16 changed files with 208 additions and 239 deletions.
11 changes: 0 additions & 11 deletions arch/x86/include/asm/xen/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,4 @@ static inline int xen_irqs_disabled(struct pt_regs *regs)
/* No need for a barrier -- XCHG is a barrier on x86. */
#define xchg_xen_ulong(ptr, val) xchg((ptr), (val))

extern int xen_have_vector_callback;

/*
* Events delivered via platform PCI interrupts are always
* routed to vcpu 0 and hence cannot be rebound.
*/
static inline bool xen_support_evtchn_rebind(void)
{
return (!xen_hvm_domain() || xen_have_vector_callback);
}

#endif /* _ASM_X86_XEN_EVENTS_H */
2 changes: 1 addition & 1 deletion arch/x86/pci/xen.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ void __init xen_msi_init(void)

int __init pci_xen_hvm_init(void)
{
if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs))
if (!xen_feature(XENFEAT_hvm_pirqs))
return 0;

#ifdef CONFIG_ACPI
Expand Down
94 changes: 68 additions & 26 deletions arch/x86/xen/enlighten.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,10 @@ struct shared_info xen_dummy_shared_info;
void *xen_initial_gdt;

RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
__read_mostly int xen_have_vector_callback;
EXPORT_SYMBOL_GPL(xen_have_vector_callback);

static int xen_cpu_up_prepare(unsigned int cpu);
static int xen_cpu_up_online(unsigned int cpu);
static int xen_cpu_dead(unsigned int cpu);

/*
* Point at some empty memory to start with. We map the real shared_info
Expand Down Expand Up @@ -1519,10 +1521,7 @@ static void __init xen_pvh_early_guest_init(void)
if (!xen_feature(XENFEAT_auto_translated_physmap))
return;

if (!xen_feature(XENFEAT_hvm_callback_vector))
return;

xen_have_vector_callback = 1;
BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector));

xen_pvh_early_cpu_init(0, false);
xen_pvh_set_cr_flags(0);
Expand All @@ -1538,6 +1537,24 @@ static void __init xen_dom0_set_legacy_features(void)
x86_platform.legacy.rtc = 1;
}

static int xen_cpuhp_setup(void)
{
int rc;

rc = cpuhp_setup_state_nocalls(CPUHP_XEN_PREPARE,
"XEN_HVM_GUEST_PREPARE",
xen_cpu_up_prepare, xen_cpu_dead);
if (rc >= 0) {
rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
"XEN_HVM_GUEST_ONLINE",
xen_cpu_up_online, NULL);
if (rc < 0)
cpuhp_remove_state_nocalls(CPUHP_XEN_PREPARE);
}

return rc >= 0 ? 0 : rc;
}

/* First C function to be called on Xen boot */
asmlinkage __visible void __init xen_start_kernel(void)
{
Expand Down Expand Up @@ -1639,6 +1656,8 @@ asmlinkage __visible void __init xen_start_kernel(void)
possible map and a non-dummy shared_info. */
per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];

WARN_ON(xen_cpuhp_setup());

local_irq_disable();
early_boot_irqs_disabled = true;

Expand Down Expand Up @@ -1819,31 +1838,54 @@ static void __init init_hvm_pv_info(void)
xen_domain_type = XEN_HVM_DOMAIN;
}

static int xen_hvm_cpu_notify(struct notifier_block *self, unsigned long action,
void *hcpu)
static int xen_cpu_up_prepare(unsigned int cpu)
{
int cpu = (long)hcpu;
switch (action) {
case CPU_UP_PREPARE:
int rc;

if (xen_hvm_domain()) {
/*
* This can happen if CPU was offlined earlier and
* offlining timed out in common_cpu_die().
*/
if (cpu_report_state(cpu) == CPU_DEAD_FROZEN) {
xen_smp_intr_free(cpu);
xen_uninit_lock_cpu(cpu);
}

if (cpu_acpi_id(cpu) != U32_MAX)
per_cpu(xen_vcpu_id, cpu) = cpu_acpi_id(cpu);
else
per_cpu(xen_vcpu_id, cpu) = cpu;
xen_vcpu_setup(cpu);
if (xen_have_vector_callback) {
if (xen_feature(XENFEAT_hvm_safe_pvclock))
xen_setup_timer(cpu);
}
break;
default:
break;
}
return NOTIFY_OK;

if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
xen_setup_timer(cpu);

rc = xen_smp_intr_init(cpu);
if (rc) {
WARN(1, "xen_smp_intr_init() for CPU %d failed: %d\n",
cpu, rc);
return rc;
}
return 0;
}

static struct notifier_block xen_hvm_cpu_notifier = {
.notifier_call = xen_hvm_cpu_notify,
};
static int xen_cpu_dead(unsigned int cpu)
{
xen_smp_intr_free(cpu);

if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
xen_teardown_timer(cpu);

return 0;
}

static int xen_cpu_up_online(unsigned int cpu)
{
xen_init_lock_cpu(cpu);
return 0;
}

#ifdef CONFIG_KEXEC_CORE
static void xen_hvm_shutdown(void)
Expand Down Expand Up @@ -1871,10 +1913,10 @@ static void __init xen_hvm_guest_init(void)

xen_panic_handler_init();

if (xen_feature(XENFEAT_hvm_callback_vector))
xen_have_vector_callback = 1;
BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector));

xen_hvm_smp_init();
register_cpu_notifier(&xen_hvm_cpu_notifier);
WARN_ON(xen_cpuhp_setup());
xen_unplug_emulated_devices();
x86_init.irqs.intr_init = xen_init_IRQ;
xen_hvm_init_time_ops();
Expand Down Expand Up @@ -1910,7 +1952,7 @@ bool xen_hvm_need_lapic(void)
return false;
if (!xen_hvm_domain())
return false;
if (xen_feature(XENFEAT_hvm_pirqs) && xen_have_vector_callback)
if (xen_feature(XENFEAT_hvm_pirqs))
return false;
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/xen/grant-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ void arch_gnttab_unmap(void *shared, unsigned long nr_gframes)

static int arch_gnttab_valloc(struct gnttab_vm_area *area, unsigned nr_frames)
{
area->ptes = kmalloc(sizeof(pte_t *) * nr_frames, GFP_KERNEL);
area->ptes = kmalloc_array(nr_frames, sizeof(*area->ptes), GFP_KERNEL);
if (area->ptes == NULL)
return -ENOMEM;

Expand Down
2 changes: 1 addition & 1 deletion arch/x86/xen/platform-pci-unplug.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static int check_platform_magic(void)
}
break;
default:
printk(KERN_WARNING "Xen Platform PCI: unknown I/O protocol version");
printk(KERN_WARNING "Xen Platform PCI: unknown I/O protocol version\n");
return XEN_PLATFORM_ERR_PROTOCOL;
}

Expand Down
7 changes: 5 additions & 2 deletions arch/x86/xen/pmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,8 +547,11 @@ void xen_pmu_init(int cpu)
return;

fail:
pr_info_once("Could not initialize VPMU for cpu %d, error %d\n",
cpu, err);
if (err == -EOPNOTSUPP || err == -ENOSYS)
pr_info_once("VPMU disabled by hypervisor.\n");
else
pr_info_once("Could not initialize VPMU for cpu %d, error %d\n",
cpu, err);
free_pages((unsigned long)xenpmu_data, 0);
}

Expand Down
53 changes: 8 additions & 45 deletions arch/x86/xen/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ static void cpu_bringup(void)
cpu_data(cpu).x86_max_cores = 1;
set_cpu_sibling_map(cpu);

/*
* identify_cpu() may have set logical_pkg_id to -1 due
* to incorrect phys_proc_id. Let's re-comupte it.
*/
topology_update_package_map(apic->cpu_present_to_apicid(cpu), cpu);

xen_setup_cpu_clockevents();

notify_cpu_starting(cpu);
Expand Down Expand Up @@ -115,7 +121,7 @@ asmlinkage __visible void cpu_bringup_and_idle(int cpu)
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
}

static void xen_smp_intr_free(unsigned int cpu)
void xen_smp_intr_free(unsigned int cpu)
{
if (per_cpu(xen_resched_irq, cpu).irq >= 0) {
unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu).irq, NULL);
Expand Down Expand Up @@ -159,7 +165,7 @@ static void xen_smp_intr_free(unsigned int cpu)
per_cpu(xen_pmu_irq, cpu).name = NULL;
}
};
static int xen_smp_intr_init(unsigned int cpu)
int xen_smp_intr_init(unsigned int cpu)
{
int rc;
char *resched_name, *callfunc_name, *debug_name, *pmu_name;
Expand Down Expand Up @@ -475,8 +481,6 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
common_cpu_up(cpu, idle);

xen_setup_runstate_info(cpu);
xen_setup_timer(cpu);
xen_init_lock_cpu(cpu);

/*
* PV VCPUs are always successfully taken down (see 'while' loop
Expand All @@ -495,10 +499,6 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)

xen_pmu_init(cpu);

rc = xen_smp_intr_init(cpu);
if (rc)
return rc;

rc = HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL);
BUG_ON(rc);

Expand Down Expand Up @@ -769,47 +769,10 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
xen_init_lock_cpu(0);
}

static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
{
int rc;

/*
* This can happen if CPU was offlined earlier and
* offlining timed out in common_cpu_die().
*/
if (cpu_report_state(cpu) == CPU_DEAD_FROZEN) {
xen_smp_intr_free(cpu);
xen_uninit_lock_cpu(cpu);
}

/*
* xen_smp_intr_init() needs to run before native_cpu_up()
* so that IPI vectors are set up on the booting CPU before
* it is marked online in native_cpu_up().
*/
rc = xen_smp_intr_init(cpu);
WARN_ON(rc);
if (!rc)
rc = native_cpu_up(cpu, tidle);

/*
* We must initialize the slowpath CPU kicker _after_ the native
* path has executed. If we initialized it before none of the
* unlocker IPI kicks would reach the booting CPU as the booting
* CPU had not set itself 'online' in cpu_online_mask. That mask
* is checked when IPIs are sent (on HVM at least).
*/
xen_init_lock_cpu(cpu);
return rc;
}

void __init xen_hvm_smp_init(void)
{
if (!xen_have_vector_callback)
return;
smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
smp_ops.cpu_up = xen_hvm_cpu_up;
smp_ops.cpu_die = xen_cpu_die;
smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi;
smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi;
Expand Down
13 changes: 13 additions & 0 deletions arch/x86/xen/smp.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#ifndef _XEN_SMP_H

#ifdef CONFIG_SMP
extern void xen_send_IPI_mask(const struct cpumask *mask,
int vector);
extern void xen_send_IPI_mask_allbutself(const struct cpumask *mask,
Expand All @@ -8,6 +9,18 @@ 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);

#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) {}
#endif /* CONFIG_SMP */

#ifdef CONFIG_XEN_PVH
extern void xen_pvh_early_cpu_init(int cpu, bool entry);
#else
Expand Down
5 changes: 0 additions & 5 deletions arch/x86/xen/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,11 +432,6 @@ static void xen_hvm_setup_cpu_clockevents(void)

void __init xen_hvm_init_time_ops(void)
{
/* vector callback is needed otherwise we cannot receive interrupts
* on cpu > 0 and at this point we don't know how many cpus are
* available */
if (!xen_have_vector_callback)
return;
if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
"disable pv timer\n");
Expand Down
26 changes: 9 additions & 17 deletions drivers/xen/events/events_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1314,9 +1314,6 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
if (!VALID_EVTCHN(evtchn))
return -1;

if (!xen_support_evtchn_rebind())
return -1;

/* Send future instances of this interrupt to other vcpu. */
bind_vcpu.port = evtchn;
bind_vcpu.vcpu = xen_vcpu_nr(tcpu);
Expand Down Expand Up @@ -1650,20 +1647,15 @@ void xen_callback_vector(void)
{
int rc;
uint64_t callback_via;
if (xen_have_vector_callback) {
callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR);
rc = xen_set_callback_via(callback_via);
if (rc) {
pr_err("Request for Xen HVM callback vector failed\n");
xen_have_vector_callback = 0;
return;
}
pr_info("Xen HVM callback vector for event delivery is enabled\n");
/* in the restore case the vector has already been allocated */
if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors))
alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
xen_hvm_callback_vector);
}

callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR);
rc = xen_set_callback_via(callback_via);
BUG_ON(rc);
pr_info("Xen HVM callback vector for event delivery is enabled\n");
/* in the restore case the vector has already been allocated */
if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors))
alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
xen_hvm_callback_vector);
}
#else
void xen_callback_vector(void) {}
Expand Down
Loading

0 comments on commit 541efb7

Please sign in to comment.