Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1591381 > unrolled thread

[PATCH v2 00/21] x86/xen: untangle PV and PVHVM guest support code

Started byVitaly Kuznetsov <vkuznets@redhat.com>
First post2017-03-02 19:20 +0100
Last post2017-03-13 10:40 +0100
Articles 20 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 00/21] x86/xen: untangle PV and PVHVM guest support code Vitaly Kuznetsov <vkuznets@redhat.com> - 2017-03-02 19:20 +0100
    [PATCH v2 11/21] x86/xen: split off smp_pv.c Vitaly Kuznetsov <vkuznets@redhat.com> - 2017-03-02 19:20 +0100
      Re: [PATCH v2 11/21] x86/xen: split off smp_pv.c Juergen Gross <jgross@suse.com> - 2017-03-13 10:40 +0100
    [PATCH v2 12/21] x86/xen: split off mmu_hvm.c Vitaly Kuznetsov <vkuznets@redhat.com> - 2017-03-02 20:00 +0100
    [PATCH v2 09/21] x86/xen: split xen_cpu_die() Vitaly Kuznetsov <vkuznets@redhat.com> - 2017-03-02 20:00 +0100
      Re: [PATCH v2 09/21] x86/xen: split xen_cpu_die() Juergen Gross <jgross@suse.com> - 2017-03-13 08:40 +0100
    [PATCH v2 02/21] x86/xen: globalize have_vcpu_info_placement Vitaly Kuznetsov <vkuznets@redhat.com> - 2017-03-02 23:10 +0100
      Re: [PATCH v2 02/21] x86/xen: globalize have_vcpu_info_placement Juergen Gross <jgross@suse.com> - 2017-03-08 16:10 +0100
    [PATCH v2 01/21] x86/xen: separate PV and HVM hypervisors Vitaly Kuznetsov <vkuznets@redhat.com> - 2017-03-02 23:10 +0100
      Re: [PATCH v2 01/21] x86/xen: separate PV and HVM hypervisors Juergen Gross <jgross@suse.com> - 2017-03-08 16:10 +0100
    [PATCH v2 05/21] x86/xen: split off enlighten_hvm.c Vitaly Kuznetsov <vkuznets@redhat.com> - 2017-03-02 23:10 +0100
      Re: [PATCH v2 05/21] x86/xen: split off enlighten_hvm.c Juergen Gross <jgross@suse.com> - 2017-03-08 16:40 +0100
    [PATCH v2 10/21] x86/xen: split off smp_hvm.c Vitaly Kuznetsov <vkuznets@redhat.com> - 2017-03-02 23:10 +0100
      Re: [PATCH v2 10/21] x86/xen: split off smp_hvm.c Juergen Gross <jgross@suse.com> - 2017-03-13 08:40 +0100
    [PATCH v2 03/21] x86/xen: add CONFIG_XEN_PV to Kconfig Vitaly Kuznetsov <vkuznets@redhat.com> - 2017-03-02 23:20 +0100
      Re: [PATCH v2 03/21] x86/xen: add CONFIG_XEN_PV to Kconfig Juergen Gross <jgross@suse.com> - 2017-03-08 16:20 +0100
    Re: [Xen-devel] [PATCH v2 00/21] x86/xen: untangle PV and PVHVM guest  support code Boris Ostrovsky <boris.ostrovsky@oracle.com> - 2017-03-05 19:10 +0100
      Re: [Xen-devel] [PATCH v2 00/21] x86/xen: untangle PV and PVHVM guest support code Vitaly Kuznetsov <vkuznets@redhat.com> - 2017-03-13 14:10 +0100
    Re: [PATCH v2 06/21] x86/xen: split off enlighten_pv.c Juergen Gross <jgross@suse.com> - 2017-03-08 16:20 +0100
    Re: [PATCH v2 13/21] x86/xen: split off mmu_pv.c Juergen Gross <jgross@suse.com> - 2017-03-13 10:40 +0100

#1591381 — [PATCH v2 00/21] x86/xen: untangle PV and PVHVM guest support code

FromVitaly Kuznetsov <vkuznets@redhat.com>
Date2017-03-02 19:20 +0100
Subject[PATCH v2 00/21] x86/xen: untangle PV and PVHVM guest support code
Message-ID<tgDbb-5KR-3@gated-at.bofh.it>
Changes since v1:
- Patches 1,2 and 3 were split and reordered to avoid adding temporary
  #ifdefs [Juergen Gross]
- Juergen's R-b added to what is now patches 14 and 15 (patches 4 and 5
  in v1). Due to re-ordering there are some tiny diffrences but I opted
  for keeping the tag.

Some patches are known to produce checkpatch.pl WARNINGS and a couple of
ERRORs, I fixed a few (mostly in _hvm* code I split) and I refrained from
fixing the rest to make it easier to review. I think that we may leave PV
code as it is as sooner or later it will go away.

Original description:

I have a long-standing idea to separate PV and PVHVM code in kernel and 
introduce Kconfig options to make it possible to enable the required
parts only breaking the current 'all or nothing' approach.

Motivation:
- Xen related x86 code in kernel is rather big and it is unclear which
  parts of it are required for PV, for HVM or for both. With PVH coming
  into picture is becomes even more tangled. It makes it hard to
  understand/audit the code.

- In some case we may want to avoid bloating kernel by supporting Xen
  guests we don't need. In particular, 90% of the code in arch/x86/xen/ is
  required to support PV guests and one may require PVHVM support only.

- PV guests are supposed to go away one day and such code separation would
  help us to get ready.

This series adds XEN_PV Kconfig option and makes it possible to build PV-only
and PVHVM-only kernels. It also makes it possible to disable Dom0 support.

Some patches are rather big but this is mostly just moving code around, no
functional changes intended. I smoke tested it with PV-only and PVHVM-only
builds, booted and did save/restore test. I also tried the newly introduced
PVHv2 guest, it even worked!

Vitaly Kuznetsov (21):
  x86/xen: separate PV and HVM hypervisors
  x86/xen: globalize have_vcpu_info_placement
  x86/xen: add CONFIG_XEN_PV to Kconfig
  x86/xen: split off enlighten_pvh.c
  x86/xen: split off enlighten_hvm.c
  x86/xen: split off enlighten_pv.c
  x86/xen: split xen_smp_intr_init()/xen_smp_intr_free()
  x86/xen: split xen_smp_prepare_boot_cpu()
  x86/xen: split xen_cpu_die()
  x86/xen: split off smp_hvm.c
  x86/xen: split off smp_pv.c
  x86/xen: split off mmu_hvm.c
  x86/xen: split off mmu_pv.c
  x86/xen: split suspend.c for PV and PVHVM guests
  x86/xen: put setup.c, pmu.c and apic.c under CONFIG_XEN_PV
  x86/xen: define startup_xen for XEN PV only
  x86/xen: create stubs for HVM-only builds in page.h
  xen/balloon: decorate PV-only parts with #ifdef CONFIG_XEN_PV
  xen: create xen_create/destroy_contiguous_region() stubs for PVHVM
    only builds
  x86/xen: enable PVHVM-only builds
  x86/xen: rename some PV-only functions in smp_pv.c

 arch/x86/include/asm/hypervisor.h |    3 +-
 arch/x86/include/asm/xen/page.h   |   25 +
 arch/x86/kernel/cpu/hypervisor.c  |    7 +-
 arch/x86/kernel/process_64.c      |    2 +-
 arch/x86/xen/Kconfig              |   33 +-
 arch/x86/xen/Makefile             |   16 +-
 arch/x86/xen/enlighten.c          | 1904 +------------------------
 arch/x86/xen/enlighten_hvm.c      |  210 +++
 arch/x86/xen/enlighten_pv.c       | 1561 +++++++++++++++++++++
 arch/x86/xen/enlighten_pvh.c      |  114 ++
 arch/x86/xen/mmu.c                | 2776 +------------------------------------
 arch/x86/xen/mmu_hvm.c            |   79 ++
 arch/x86/xen/mmu_pv.c             | 2635 +++++++++++++++++++++++++++++++++++
 arch/x86/xen/pmu.h                |    5 +
 arch/x86/xen/smp.c                |  516 +------
 arch/x86/xen/smp.h                |   16 +
 arch/x86/xen/smp_hvm.c            |   58 +
 arch/x86/xen/smp_pv.c             |  499 +++++++
 arch/x86/xen/suspend.c            |   54 -
 arch/x86/xen/suspend_hvm.c        |   22 +
 arch/x86/xen/suspend_pv.c         |   44 +
 arch/x86/xen/xen-head.S           |    4 +
 arch/x86/xen/xen-ops.h            |   21 +
 drivers/xen/balloon.c             |   30 +-
 include/xen/xen-ops.h             |   14 +
 25 files changed, 5461 insertions(+), 5187 deletions(-)
 create mode 100644 arch/x86/xen/enlighten_hvm.c
 create mode 100644 arch/x86/xen/enlighten_pv.c
 create mode 100644 arch/x86/xen/enlighten_pvh.c
 create mode 100644 arch/x86/xen/mmu_hvm.c
 create mode 100644 arch/x86/xen/mmu_pv.c
 create mode 100644 arch/x86/xen/smp_hvm.c
 create mode 100644 arch/x86/xen/smp_pv.c
 create mode 100644 arch/x86/xen/suspend_hvm.c
 create mode 100644 arch/x86/xen/suspend_pv.c

-- 
2.9.3

[toc] | [next] | [standalone]


#1591383 — [PATCH v2 11/21] x86/xen: split off smp_pv.c

FromVitaly Kuznetsov <vkuznets@redhat.com>
Date2017-03-02 19:20 +0100
Subject[PATCH v2 11/21] x86/xen: split off smp_pv.c
Message-ID<tgDuy-67m-21@gated-at.bofh.it>
In reply to#1591381
Basically, smp.c is renamed to smp_pv.c and some code moved out to common
smp.c. struct xen_common_irq delcaration ended up in smp.h.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 arch/x86/xen/Makefile |   2 +-
 arch/x86/xen/smp.c    | 487 +-----------------------------------------------
 arch/x86/xen/smp.h    |   5 +
 arch/x86/xen/smp_pv.c | 499 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 508 insertions(+), 485 deletions(-)
 create mode 100644 arch/x86/xen/smp_pv.c

diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index bc7df8c..ebf3522 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -20,7 +20,7 @@ obj-$(CONFIG_XEN_PVH)			+= enlighten_pvh.o
 
 obj-$(CONFIG_EVENT_TRACING) += trace.o
 
-obj-$(CONFIG_SMP)		+= smp.o
+obj-$(CONFIG_SMP)		+= smp.o smp_pv.o
 obj-$(CONFIG_XEN_PVHVM_SMP)  	+= smp_hvm.o
 obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
 obj-$(CONFIG_XEN_DEBUG_FS)	+= debugfs.o
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index c692336..82ac611 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -1,62 +1,21 @@
-/*
- * Xen SMP support
- *
- * This file implements the Xen versions of smp_ops.  SMP under Xen is
- * very straightforward.  Bringing a CPU up is simply a matter of
- * loading its initial context and setting it running.
- *
- * IPIs are handled through the Xen event mechanism.
- *
- * Because virtual CPUs can be scheduled onto any real CPU, there's no
- * useful topology information for the kernel to make use of.  As a
- * result, all CPUs are treated as if they're single-core and
- * single-threaded.
- */
-#include <linux/sched.h>
-#include <linux/err.h>
-#include <linux/slab.h>
 #include <linux/smp.h>
-#include <linux/irq_work.h>
-#include <linux/tick.h>
-
-#include <asm/paravirt.h>
-#include <asm/desc.h>
-#include <asm/pgtable.h>
-#include <asm/cpu.h>
-
-#include <xen/interface/xen.h>
-#include <xen/interface/vcpu.h>
-#include <xen/interface/xenpmu.h>
-
-#include <asm/xen/interface.h>
-#include <asm/xen/hypercall.h>
+#include <linux/slab.h>
+#include <linux/cpumask.h>
+#include <linux/percpu.h>
 
-#include <xen/xen.h>
-#include <xen/page.h>
 #include <xen/events.h>
 
 #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;
 
-struct xen_common_irq {
-	int irq;
-	char *name;
-};
 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_callfuncsingle_irq) = { .irq = -1 };
-static DEFINE_PER_CPU(struct xen_common_irq, xen_irq_work) = { .irq = -1 };
 static DEFINE_PER_CPU(struct xen_common_irq, xen_debug_irq) = { .irq = -1 };
-static DEFINE_PER_CPU(struct xen_common_irq, xen_pmu_irq) = { .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.
@@ -69,42 +28,6 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static void cpu_bringup(void)
-{
-	int cpu;
-
-	cpu_init();
-	touch_softlockup_watchdog();
-	preempt_disable();
-
-	/* PVH runs in ring 0 and allows us to do native syscalls. Yay! */
-	if (!xen_feature(XENFEAT_supervisor_mode_kernel)) {
-		xen_enable_sysenter();
-		xen_enable_syscall();
-	}
-	cpu = smp_processor_id();
-	smp_store_cpu_info(cpu);
-	cpu_data(cpu).x86_max_cores = 1;
-	set_cpu_sibling_map(cpu);
-
-	xen_setup_cpu_clockevents();
-
-	notify_cpu_starting(cpu);
-
-	set_cpu_online(cpu, true);
-
-	cpu_set_state_online(cpu);  /* Implies full memory barrier. */
-
-	/* We can take interrupts now: we're officially "up". */
-	local_irq_enable();
-}
-
-asmlinkage __visible void cpu_bringup_and_idle(void)
-{
-	cpu_bringup();
-	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
-}
-
 void xen_smp_intr_free(unsigned int cpu)
 {
 	if (per_cpu(xen_resched_irq, cpu).irq >= 0) {
@@ -134,23 +57,6 @@ void xen_smp_intr_free(unsigned int cpu)
 	}
 }
 
-void xen_smp_intr_free_pv(unsigned int cpu)
-{
-	if (per_cpu(xen_irq_work, cpu).irq >= 0) {
-		unbind_from_irqhandler(per_cpu(xen_irq_work, cpu).irq, NULL);
-		per_cpu(xen_irq_work, cpu).irq = -1;
-		kfree(per_cpu(xen_irq_work, cpu).name);
-		per_cpu(xen_irq_work, cpu).name = NULL;
-	}
-
-	if (per_cpu(xen_pmu_irq, cpu).irq >= 0) {
-		unbind_from_irqhandler(per_cpu(xen_pmu_irq, cpu).irq, NULL);
-		per_cpu(xen_pmu_irq, cpu).irq = -1;
-		kfree(per_cpu(xen_pmu_irq, cpu).name);
-		per_cpu(xen_pmu_irq, cpu).name = NULL;
-	}
-}
-
 int xen_smp_intr_init(unsigned int cpu)
 {
 	int rc;
@@ -208,360 +114,6 @@ int xen_smp_intr_init(unsigned int cpu)
 	return rc;
 }
 
-int xen_smp_intr_init_pv(unsigned int cpu)
-{
-	int rc;
-	char *callfunc_name, *pmu_name;
-
-	callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
-	rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
-				    cpu,
-				    xen_irq_work_interrupt,
-				    IRQF_PERCPU|IRQF_NOBALANCING,
-				    callfunc_name,
-				    NULL);
-	if (rc < 0)
-		goto fail;
-	per_cpu(xen_irq_work, cpu).irq = rc;
-	per_cpu(xen_irq_work, cpu).name = callfunc_name;
-
-	if (is_xen_pmu(cpu)) {
-		pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu);
-		rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu,
-					     xen_pmu_irq_handler,
-					     IRQF_PERCPU|IRQF_NOBALANCING,
-					     pmu_name, NULL);
-		if (rc < 0)
-			goto fail;
-		per_cpu(xen_pmu_irq, cpu).irq = rc;
-		per_cpu(xen_pmu_irq, cpu).name = pmu_name;
-	}
-
-	return 0;
-
- fail:
-	xen_smp_intr_free_pv(cpu);
-	return rc;
-}
-
-static void __init xen_fill_possible_map(void)
-{
-	int i, rc;
-
-	if (xen_initial_domain())
-		return;
-
-	for (i = 0; i < nr_cpu_ids; i++) {
-		rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
-		if (rc >= 0) {
-			num_processors++;
-			set_cpu_possible(i, true);
-		}
-	}
-}
-
-static void __init xen_filter_cpu_maps(void)
-{
-	int i, rc;
-	unsigned int subtract = 0;
-
-	if (!xen_initial_domain())
-		return;
-
-	num_processors = 0;
-	disabled_cpus = 0;
-	for (i = 0; i < nr_cpu_ids; i++) {
-		rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
-		if (rc >= 0) {
-			num_processors++;
-			set_cpu_possible(i, true);
-		} else {
-			set_cpu_possible(i, false);
-			set_cpu_present(i, false);
-			subtract++;
-		}
-	}
-#ifdef CONFIG_HOTPLUG_CPU
-	/* This is akin to using 'nr_cpus' on the Linux command line.
-	 * Which is OK as when we use 'dom0_max_vcpus=X' we can only
-	 * have up to X, while nr_cpu_ids is greater than X. This
-	 * normally is not a problem, except when CPU hotplugging
-	 * is involved and then there might be more than X CPUs
-	 * in the guest - which will not work as there is no
-	 * hypercall to expand the max number of VCPUs an already
-	 * running guest has. So cap it up to X. */
-	if (subtract)
-		nr_cpu_ids = nr_cpu_ids - subtract;
-#endif
-
-}
-
-static void __init xen_pv_smp_prepare_boot_cpu(void)
-{
-	BUG_ON(smp_processor_id() != 0);
-	native_smp_prepare_boot_cpu();
-
-	if (!xen_feature(XENFEAT_writable_page_tables))
-		/* We've switched to the "real" per-cpu gdt, so make
-		 * sure the old memory can be recycled. */
-		make_lowmem_page_readwrite(xen_initial_gdt);
-
-#ifdef CONFIG_X86_32
-	/*
-	 * Xen starts us with XEN_FLAT_RING1_DS, but linux code
-	 * expects __USER_DS
-	 */
-	loadsegment(ds, __USER_DS);
-	loadsegment(es, __USER_DS);
-#endif
-
-	xen_filter_cpu_maps();
-	xen_setup_vcpu_info_placement();
-
-	/*
-	 * The alternative logic (which patches the unlock/lock) runs before
-	 * the smp bootup up code is activated. Hence we need to set this up
-	 * the core kernel is being patched. Otherwise we will have only
-	 * modules patched but not core code.
-	 */
-	xen_init_spinlocks();
-}
-
-static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
-{
-	unsigned cpu;
-	unsigned int i;
-
-	if (skip_ioapic_setup) {
-		char *m = (max_cpus == 0) ?
-			"The nosmp parameter is incompatible with Xen; " \
-			"use Xen dom0_max_vcpus=1 parameter" :
-			"The noapic parameter is incompatible with Xen";
-
-		xen_raw_printk(m);
-		panic(m);
-	}
-	xen_init_lock_cpu(0);
-
-	smp_store_boot_cpu_info();
-	cpu_data(0).x86_max_cores = 1;
-
-	for_each_possible_cpu(i) {
-		zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL);
-		zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
-		zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
-	}
-	set_cpu_sibling_map(0);
-
-	xen_pmu_init(0);
-
-	if (xen_smp_intr_init(0))
-		BUG();
-
-	if (!alloc_cpumask_var(&xen_cpu_initialized_map, GFP_KERNEL))
-		panic("could not allocate xen_cpu_initialized_map\n");
-
-	cpumask_copy(xen_cpu_initialized_map, cpumask_of(0));
-
-	/* Restrict the possible_map according to max_cpus. */
-	while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
-		for (cpu = nr_cpu_ids - 1; !cpu_possible(cpu); cpu--)
-			continue;
-		set_cpu_possible(cpu, false);
-	}
-
-	for_each_possible_cpu(cpu)
-		set_cpu_present(cpu, true);
-}
-
-static int
-cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
-{
-	struct vcpu_guest_context *ctxt;
-	struct desc_struct *gdt;
-	unsigned long gdt_mfn;
-
-	/* used to tell cpu_init() that it can proceed with initialization */
-	cpumask_set_cpu(cpu, cpu_callout_mask);
-	if (cpumask_test_and_set_cpu(cpu, xen_cpu_initialized_map))
-		return 0;
-
-	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
-	if (ctxt == NULL)
-		return -ENOMEM;
-
-	gdt = get_cpu_gdt_table(cpu);
-
-#ifdef CONFIG_X86_32
-	ctxt->user_regs.fs = __KERNEL_PERCPU;
-	ctxt->user_regs.gs = __KERNEL_STACK_CANARY;
-#endif
-	memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
-
-	ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle;
-	ctxt->flags = VGCF_IN_KERNEL;
-	ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */
-	ctxt->user_regs.ds = __USER_DS;
-	ctxt->user_regs.es = __USER_DS;
-	ctxt->user_regs.ss = __KERNEL_DS;
-
-	xen_copy_trap_info(ctxt->trap_ctxt);
-
-	ctxt->ldt_ents = 0;
-
-	BUG_ON((unsigned long)gdt & ~PAGE_MASK);
-
-	gdt_mfn = arbitrary_virt_to_mfn(gdt);
-	make_lowmem_page_readonly(gdt);
-	make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
-
-	ctxt->gdt_frames[0] = gdt_mfn;
-	ctxt->gdt_ents      = GDT_ENTRIES;
-
-	ctxt->kernel_ss = __KERNEL_DS;
-	ctxt->kernel_sp = idle->thread.sp0;
-
-#ifdef CONFIG_X86_32
-	ctxt->event_callback_cs     = __KERNEL_CS;
-	ctxt->failsafe_callback_cs  = __KERNEL_CS;
-#else
-	ctxt->gs_base_kernel = per_cpu_offset(cpu);
-#endif
-	ctxt->event_callback_eip    =
-		(unsigned long)xen_hypervisor_callback;
-	ctxt->failsafe_callback_eip =
-		(unsigned long)xen_failsafe_callback;
-	ctxt->user_regs.cs = __KERNEL_CS;
-	per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir);
-
-	ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
-	ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_gfn(swapper_pg_dir));
-	if (HYPERVISOR_vcpu_op(VCPUOP_initialise, xen_vcpu_nr(cpu), ctxt))
-		BUG();
-
-	kfree(ctxt);
-	return 0;
-}
-
-static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
-{
-	int rc;
-
-	common_cpu_up(cpu, idle);
-
-	xen_setup_runstate_info(cpu);
-
-	/*
-	 * PV VCPUs are always successfully taken down (see 'while' loop
-	 * in xen_cpu_die()), so -EBUSY is an error.
-	 */
-	rc = cpu_check_up_prepare(cpu);
-	if (rc)
-		return rc;
-
-	/* make sure interrupts start blocked */
-	per_cpu(xen_vcpu, cpu)->evtchn_upcall_mask = 1;
-
-	rc = cpu_initialize_context(cpu, idle);
-	if (rc)
-		return rc;
-
-	xen_pmu_init(cpu);
-
-	rc = HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL);
-	BUG_ON(rc);
-
-	while (cpu_report_state(cpu) != CPU_ONLINE)
-		HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
-
-	return 0;
-}
-
-static void xen_smp_cpus_done(unsigned int max_cpus)
-{
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-static int xen_cpu_disable(void)
-{
-	unsigned int cpu = smp_processor_id();
-	if (cpu == 0)
-		return -EBUSY;
-
-	cpu_disable_common();
-
-	load_cr3(swapper_pg_dir);
-	return 0;
-}
-
-static void xen_pv_cpu_die(unsigned int cpu)
-{
-	while (HYPERVISOR_vcpu_op(VCPUOP_is_up,
-				  xen_vcpu_nr(cpu), NULL)) {
-		__set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/10);
-	}
-
-	if (common_cpu_die(cpu) == 0) {
-		xen_smp_intr_free(cpu);
-		xen_uninit_lock_cpu(cpu);
-		xen_teardown_timer(cpu);
-		xen_pmu_finish(cpu);
-	}
-}
-
-static void xen_play_dead(void) /* used only with HOTPLUG_CPU */
-{
-	play_dead_common();
-	HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(smp_processor_id()), NULL);
-	cpu_bringup();
-	/*
-	 * commit 4b0c0f294 (tick: Cleanup NOHZ per cpu data on cpu down)
-	 * clears certain data that the cpu_idle loop (which called us
-	 * and that we return from) expects. The only way to get that
-	 * data back is to call:
-	 */
-	tick_nohz_idle_enter();
-
-	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
-}
-
-#else /* !CONFIG_HOTPLUG_CPU */
-static int xen_cpu_disable(void)
-{
-	return -ENOSYS;
-}
-
-static void xen_pv_cpu_die(unsigned int cpu)
-{
-	BUG();
-}
-
-static void xen_play_dead(void)
-{
-	BUG();
-}
-
-#endif
-static void stop_self(void *v)
-{
-	int cpu = smp_processor_id();
-
-	/* make sure we're not pinning something down */
-	load_cr3(swapper_pg_dir);
-	/* should set up a minimal gdt */
-
-	set_cpu_online(cpu, false);
-
-	HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(cpu), NULL);
-	BUG();
-}
-
-static void xen_stop_other_cpus(int wait)
-{
-	smp_call_function(stop_self, NULL, wait);
-}
-
 void xen_smp_send_reschedule(int cpu)
 {
 	xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR);
@@ -696,36 +248,3 @@ 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_pv_smp_prepare_boot_cpu,
-	.smp_prepare_cpus = xen_smp_prepare_cpus,
-	.smp_cpus_done = xen_smp_cpus_done,
-
-	.cpu_up = xen_cpu_up,
-	.cpu_die = xen_pv_cpu_die,
-	.cpu_disable = xen_cpu_disable,
-	.play_dead = xen_play_dead,
-
-	.stop_other_cpus = xen_stop_other_cpus,
-	.smp_send_reschedule = xen_smp_send_reschedule,
-
-	.send_call_func_ipi = xen_smp_send_call_function_ipi,
-	.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi,
-};
-
-void __init xen_smp_init(void)
-{
-	smp_ops = xen_smp_ops;
-	xen_fill_possible_map();
-}
diff --git a/arch/x86/xen/smp.h b/arch/x86/xen/smp.h
index bf36e79..3245343 100644
--- a/arch/x86/xen/smp.h
+++ b/arch/x86/xen/smp.h
@@ -17,6 +17,11 @@ extern void xen_smp_intr_free_pv(unsigned int cpu);
 extern void xen_smp_send_reschedule(int cpu);
 extern void xen_smp_send_call_function_ipi(const struct cpumask *mask);
 extern void xen_smp_send_call_function_single_ipi(int cpu);
+
+struct xen_common_irq {
+	int irq;
+	char *name;
+};
 #else /* CONFIG_SMP */
 
 static inline int xen_smp_intr_init(unsigned int cpu)
diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c
new file mode 100644
index 0000000..e20718a
--- /dev/null
+++ b/arch/x86/xen/smp_pv.c
@@ -0,0 +1,499 @@
+/*
+ * Xen SMP support
+ *
+ * This file implements the Xen versions of smp_ops.  SMP under Xen is
+ * very straightforward.  Bringing a CPU up is simply a matter of
+ * loading its initial context and setting it running.
+ *
+ * IPIs are handled through the Xen event mechanism.
+ *
+ * Because virtual CPUs can be scheduled onto any real CPU, there's no
+ * useful topology information for the kernel to make use of.  As a
+ * result, all CPUs are treated as if they're single-core and
+ * single-threaded.
+ */
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/irq_work.h>
+#include <linux/tick.h>
+
+#include <asm/paravirt.h>
+#include <asm/desc.h>
+#include <asm/pgtable.h>
+#include <asm/cpu.h>
+
+#include <xen/interface/xen.h>
+#include <xen/interface/vcpu.h>
+#include <xen/interface/xenpmu.h>
+
+#include <asm/xen/interface.h>
+#include <asm/xen/hypercall.h>
+
+#include <xen/xen.h>
+#include <xen/page.h>
+#include <xen/events.h>
+
+#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;
+
+static DEFINE_PER_CPU(struct xen_common_irq, xen_irq_work) = { .irq = -1 };
+static DEFINE_PER_CPU(struct xen_common_irq, xen_pmu_irq) = { .irq = -1 };
+
+static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id);
+
+static void cpu_bringup(void)
+{
+	int cpu;
+
+	cpu_init();
+	touch_softlockup_watchdog();
+	preempt_disable();
+
+	/* PVH runs in ring 0 and allows us to do native syscalls. Yay! */
+	if (!xen_feature(XENFEAT_supervisor_mode_kernel)) {
+		xen_enable_sysenter();
+		xen_enable_syscall();
+	}
+	cpu = smp_processor_id();
+	smp_store_cpu_info(cpu);
+	cpu_data(cpu).x86_max_cores = 1;
+	set_cpu_sibling_map(cpu);
+
+	xen_setup_cpu_clockevents();
+
+	notify_cpu_starting(cpu);
+
+	set_cpu_online(cpu, true);
+
+	cpu_set_state_online(cpu);  /* Implies full memory barrier. */
+
+	/* We can take interrupts now: we're officially "up". */
+	local_irq_enable();
+}
+
+asmlinkage __visible void cpu_bringup_and_idle(void)
+{
+	cpu_bringup();
+	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
+}
+
+void xen_smp_intr_free_pv(unsigned int cpu)
+{
+	if (per_cpu(xen_irq_work, cpu).irq >= 0) {
+		unbind_from_irqhandler(per_cpu(xen_irq_work, cpu).irq, NULL);
+		per_cpu(xen_irq_work, cpu).irq = -1;
+		kfree(per_cpu(xen_irq_work, cpu).name);
+		per_cpu(xen_irq_work, cpu).name = NULL;
+	}
+
+	if (per_cpu(xen_pmu_irq, cpu).irq >= 0) {
+		unbind_from_irqhandler(per_cpu(xen_pmu_irq, cpu).irq, NULL);
+		per_cpu(xen_pmu_irq, cpu).irq = -1;
+		kfree(per_cpu(xen_pmu_irq, cpu).name);
+		per_cpu(xen_pmu_irq, cpu).name = NULL;
+	}
+}
+
+int xen_smp_intr_init_pv(unsigned int cpu)
+{
+	int rc;
+	char *callfunc_name, *pmu_name;
+
+	callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
+	rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
+				    cpu,
+				    xen_irq_work_interrupt,
+				    IRQF_PERCPU|IRQF_NOBALANCING,
+				    callfunc_name,
+				    NULL);
+	if (rc < 0)
+		goto fail;
+	per_cpu(xen_irq_work, cpu).irq = rc;
+	per_cpu(xen_irq_work, cpu).name = callfunc_name;
+
+	if (is_xen_pmu(cpu)) {
+		pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu);
+		rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu,
+					     xen_pmu_irq_handler,
+					     IRQF_PERCPU|IRQF_NOBALANCING,
+					     pmu_name, NULL);
+		if (rc < 0)
+			goto fail;
+		per_cpu(xen_pmu_irq, cpu).irq = rc;
+		per_cpu(xen_pmu_irq, cpu).name = pmu_name;
+	}
+
+	return 0;
+
+ fail:
+	xen_smp_intr_free_pv(cpu);
+	return rc;
+}
+
+static void __init xen_fill_possible_map(void)
+{
+	int i, rc;
+
+	if (xen_initial_domain())
+		return;
+
+	for (i = 0; i < nr_cpu_ids; i++) {
+		rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
+		if (rc >= 0) {
+			num_processors++;
+			set_cpu_possible(i, true);
+		}
+	}
+}
+
+static void __init xen_filter_cpu_maps(void)
+{
+	int i, rc;
+	unsigned int subtract = 0;
+
+	if (!xen_initial_domain())
+		return;
+
+	num_processors = 0;
+	disabled_cpus = 0;
+	for (i = 0; i < nr_cpu_ids; i++) {
+		rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
+		if (rc >= 0) {
+			num_processors++;
+			set_cpu_possible(i, true);
+		} else {
+			set_cpu_possible(i, false);
+			set_cpu_present(i, false);
+			subtract++;
+		}
+	}
+#ifdef CONFIG_HOTPLUG_CPU
+	/* This is akin to using 'nr_cpus' on the Linux command line.
+	 * Which is OK as when we use 'dom0_max_vcpus=X' we can only
+	 * have up to X, while nr_cpu_ids is greater than X. This
+	 * normally is not a problem, except when CPU hotplugging
+	 * is involved and then there might be more than X CPUs
+	 * in the guest - which will not work as there is no
+	 * hypercall to expand the max number of VCPUs an already
+	 * running guest has. So cap it up to X. */
+	if (subtract)
+		nr_cpu_ids = nr_cpu_ids - subtract;
+#endif
+
+}
+
+static void __init xen_pv_smp_prepare_boot_cpu(void)
+{
+	BUG_ON(smp_processor_id() != 0);
+	native_smp_prepare_boot_cpu();
+
+	if (!xen_feature(XENFEAT_writable_page_tables))
+		/* We've switched to the "real" per-cpu gdt, so make
+		 * sure the old memory can be recycled. */
+		make_lowmem_page_readwrite(xen_initial_gdt);
+
+#ifdef CONFIG_X86_32
+	/*
+	 * Xen starts us with XEN_FLAT_RING1_DS, but linux code
+	 * expects __USER_DS
+	 */
+	loadsegment(ds, __USER_DS);
+	loadsegment(es, __USER_DS);
+#endif
+
+	xen_filter_cpu_maps();
+	xen_setup_vcpu_info_placement();
+
+	/*
+	 * The alternative logic (which patches the unlock/lock) runs before
+	 * the smp bootup up code is activated. Hence we need to set this up
+	 * the core kernel is being patched. Otherwise we will have only
+	 * modules patched but not core code.
+	 */
+	xen_init_spinlocks();
+}
+
+static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
+{
+	unsigned cpu;
+	unsigned int i;
+
+	if (skip_ioapic_setup) {
+		char *m = (max_cpus == 0) ?
+			"The nosmp parameter is incompatible with Xen; " \
+			"use Xen dom0_max_vcpus=1 parameter" :
+			"The noapic parameter is incompatible with Xen";
+
+		xen_raw_printk(m);
+		panic(m);
+	}
+	xen_init_lock_cpu(0);
+
+	smp_store_boot_cpu_info();
+	cpu_data(0).x86_max_cores = 1;
+
+	for_each_possible_cpu(i) {
+		zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL);
+		zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
+		zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
+	}
+	set_cpu_sibling_map(0);
+
+	xen_pmu_init(0);
+
+	if (xen_smp_intr_init(0))
+		BUG();
+
+	if (!alloc_cpumask_var(&xen_cpu_initialized_map, GFP_KERNEL))
+		panic("could not allocate xen_cpu_initialized_map\n");
+
+	cpumask_copy(xen_cpu_initialized_map, cpumask_of(0));
+
+	/* Restrict the possible_map according to max_cpus. */
+	while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
+		for (cpu = nr_cpu_ids - 1; !cpu_possible(cpu); cpu--)
+			continue;
+		set_cpu_possible(cpu, false);
+	}
+
+	for_each_possible_cpu(cpu)
+		set_cpu_present(cpu, true);
+}
+
+static int
+cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
+{
+	struct vcpu_guest_context *ctxt;
+	struct desc_struct *gdt;
+	unsigned long gdt_mfn;
+
+	/* used to tell cpu_init() that it can proceed with initialization */
+	cpumask_set_cpu(cpu, cpu_callout_mask);
+	if (cpumask_test_and_set_cpu(cpu, xen_cpu_initialized_map))
+		return 0;
+
+	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
+	if (ctxt == NULL)
+		return -ENOMEM;
+
+	gdt = get_cpu_gdt_table(cpu);
+
+#ifdef CONFIG_X86_32
+	ctxt->user_regs.fs = __KERNEL_PERCPU;
+	ctxt->user_regs.gs = __KERNEL_STACK_CANARY;
+#endif
+	memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
+
+	ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle;
+	ctxt->flags = VGCF_IN_KERNEL;
+	ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */
+	ctxt->user_regs.ds = __USER_DS;
+	ctxt->user_regs.es = __USER_DS;
+	ctxt->user_regs.ss = __KERNEL_DS;
+
+	xen_copy_trap_info(ctxt->trap_ctxt);
+
+	ctxt->ldt_ents = 0;
+
+	BUG_ON((unsigned long)gdt & ~PAGE_MASK);
+
+	gdt_mfn = arbitrary_virt_to_mfn(gdt);
+	make_lowmem_page_readonly(gdt);
+	make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
+
+	ctxt->gdt_frames[0] = gdt_mfn;
+	ctxt->gdt_ents      = GDT_ENTRIES;
+
+	ctxt->kernel_ss = __KERNEL_DS;
+	ctxt->kernel_sp = idle->thread.sp0;
+
+#ifdef CONFIG_X86_32
+	ctxt->event_callback_cs     = __KERNEL_CS;
+	ctxt->failsafe_callback_cs  = __KERNEL_CS;
+#else
+	ctxt->gs_base_kernel = per_cpu_offset(cpu);
+#endif
+	ctxt->event_callback_eip    =
+		(unsigned long)xen_hypervisor_callback;
+	ctxt->failsafe_callback_eip =
+		(unsigned long)xen_failsafe_callback;
+	ctxt->user_regs.cs = __KERNEL_CS;
+	per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir);
+
+	ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
+	ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_gfn(swapper_pg_dir));
+	if (HYPERVISOR_vcpu_op(VCPUOP_initialise, xen_vcpu_nr(cpu), ctxt))
+		BUG();
+
+	kfree(ctxt);
+	return 0;
+}
+
+static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
+{
+	int rc;
+
+	common_cpu_up(cpu, idle);
+
+	xen_setup_runstate_info(cpu);
+
+	/*
+	 * PV VCPUs are always successfully taken down (see 'while' loop
+	 * in xen_cpu_die()), so -EBUSY is an error.
+	 */
+	rc = cpu_check_up_prepare(cpu);
+	if (rc)
+		return rc;
+
+	/* make sure interrupts start blocked */
+	per_cpu(xen_vcpu, cpu)->evtchn_upcall_mask = 1;
+
+	rc = cpu_initialize_context(cpu, idle);
+	if (rc)
+		return rc;
+
+	xen_pmu_init(cpu);
+
+	rc = HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL);
+	BUG_ON(rc);
+
+	while (cpu_report_state(cpu) != CPU_ONLINE)
+		HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
+
+	return 0;
+}
+
+static void xen_smp_cpus_done(unsigned int max_cpus)
+{
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int xen_cpu_disable(void)
+{
+	unsigned int cpu = smp_processor_id();
+	if (cpu == 0)
+		return -EBUSY;
+
+	cpu_disable_common();
+
+	load_cr3(swapper_pg_dir);
+	return 0;
+}
+
+static void xen_pv_cpu_die(unsigned int cpu)
+{
+	while (HYPERVISOR_vcpu_op(VCPUOP_is_up,
+				  xen_vcpu_nr(cpu), NULL)) {
+		__set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ/10);
+	}
+
+	if (common_cpu_die(cpu) == 0) {
+		xen_smp_intr_free(cpu);
+		xen_uninit_lock_cpu(cpu);
+		xen_teardown_timer(cpu);
+		xen_pmu_finish(cpu);
+	}
+}
+
+static void xen_play_dead(void) /* used only with HOTPLUG_CPU */
+{
+	play_dead_common();
+	HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(smp_processor_id()), NULL);
+	cpu_bringup();
+	/*
+	 * commit 4b0c0f294 (tick: Cleanup NOHZ per cpu data on cpu down)
+	 * clears certain data that the cpu_idle loop (which called us
+	 * and that we return from) expects. The only way to get that
+	 * data back is to call:
+	 */
+	tick_nohz_idle_enter();
+
+	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
+}
+
+#else /* !CONFIG_HOTPLUG_CPU */
+static int xen_cpu_disable(void)
+{
+	return -ENOSYS;
+}
+
+static void xen_pv_cpu_die(unsigned int cpu)
+{
+	BUG();
+}
+
+static void xen_play_dead(void)
+{
+	BUG();
+}
+
+#endif
+static void stop_self(void *v)
+{
+	int cpu = smp_processor_id();
+
+	/* make sure we're not pinning something down */
+	load_cr3(swapper_pg_dir);
+	/* should set up a minimal gdt */
+
+	set_cpu_online(cpu, false);
+
+	HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(cpu), NULL);
+	BUG();
+}
+
+static void xen_stop_other_cpus(int wait)
+{
+	smp_call_function(stop_self, NULL, wait);
+}
+
+static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id)
+{
+	irq_enter();
+	generic_smp_call_function_interrupt();
+	inc_irq_stat(irq_call_count);
+	irq_exit();
+
+	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_pv_smp_prepare_boot_cpu,
+	.smp_prepare_cpus = xen_smp_prepare_cpus,
+	.smp_cpus_done = xen_smp_cpus_done,
+
+	.cpu_up = xen_cpu_up,
+	.cpu_die = xen_pv_cpu_die,
+	.cpu_disable = xen_cpu_disable,
+	.play_dead = xen_play_dead,
+
+	.stop_other_cpus = xen_stop_other_cpus,
+	.smp_send_reschedule = xen_smp_send_reschedule,
+
+	.send_call_func_ipi = xen_smp_send_call_function_ipi,
+	.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi,
+};
+
+void __init xen_smp_init(void)
+{
+	smp_ops = xen_smp_ops;
+	xen_fill_possible_map();
+}
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1599138 — Re: [PATCH v2 11/21] x86/xen: split off smp_pv.c

FromJuergen Gross <jgross@suse.com>
Date2017-03-13 10:40 +0100
SubjectRe: [PATCH v2 11/21] x86/xen: split off smp_pv.c
Message-ID<tkuCl-6Ws-5@gated-at.bofh.it>
In reply to#1591383
On 02/03/17 18:53, Vitaly Kuznetsov wrote:
> Basically, smp.c is renamed to smp_pv.c and some code moved out to common
> smp.c. struct xen_common_irq delcaration ended up in smp.h.
> 
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>

Reviewed-by: Juergen Gross <jgross@suse.com>


Juergen

[toc] | [prev] | [next] | [standalone]


#1591396 — [PATCH v2 12/21] x86/xen: split off mmu_hvm.c

FromVitaly Kuznetsov <vkuznets@redhat.com>
Date2017-03-02 20:00 +0100
Subject[PATCH v2 12/21] x86/xen: split off mmu_hvm.c
Message-ID<tgE7f-6oo-5@gated-at.bofh.it>
In reply to#1591381
Move PVHVM related code to mmu_hvm.c.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 arch/x86/xen/Makefile  |  2 +-
 arch/x86/xen/mmu.c     | 74 ----------------------------------------------
 arch/x86/xen/mmu_hvm.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+), 75 deletions(-)
 create mode 100644 arch/x86/xen/mmu_hvm.c

diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index ebf3522..6a95a8b 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -15,7 +15,7 @@ obj-y		:= enlighten.o setup.o multicalls.o mmu.o irq.o \
 			grant-table.o suspend.o platform-pci-unplug.o \
 			p2m.o apic.o pmu.o enlighten_pv.o
 
-obj-$(CONFIG_XEN_PVHVM)		+= enlighten_hvm.o
+obj-$(CONFIG_XEN_PVHVM)		+= enlighten_hvm.o mmu_hvm.o
 obj-$(CONFIG_XEN_PVH)			+= enlighten_pvh.o
 
 obj-$(CONFIG_EVENT_TRACING) += trace.o
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index f6740b5..4dfcb06 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2689,80 +2689,6 @@ void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order)
 }
 EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
 
-#ifdef CONFIG_XEN_PVHVM
-#ifdef CONFIG_PROC_VMCORE
-/*
- * This function is used in two contexts:
- * - the kdump kernel has to check whether a pfn of the crashed kernel
- *   was a ballooned page. vmcore is using this function to decide
- *   whether to access a pfn of the crashed kernel.
- * - the kexec kernel has to check whether a pfn was ballooned by the
- *   previous kernel. If the pfn is ballooned, handle it properly.
- * Returns 0 if the pfn is not backed by a RAM page, the caller may
- * handle the pfn special in this case.
- */
-static int xen_oldmem_pfn_is_ram(unsigned long pfn)
-{
-	struct xen_hvm_get_mem_type a = {
-		.domid = DOMID_SELF,
-		.pfn = pfn,
-	};
-	int ram;
-
-	if (HYPERVISOR_hvm_op(HVMOP_get_mem_type, &a))
-		return -ENXIO;
-
-	switch (a.mem_type) {
-		case HVMMEM_mmio_dm:
-			ram = 0;
-			break;
-		case HVMMEM_ram_rw:
-		case HVMMEM_ram_ro:
-		default:
-			ram = 1;
-			break;
-	}
-
-	return ram;
-}
-#endif
-
-static void xen_hvm_exit_mmap(struct mm_struct *mm)
-{
-	struct xen_hvm_pagetable_dying a;
-	int rc;
-
-	a.domid = DOMID_SELF;
-	a.gpa = __pa(mm->pgd);
-	rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
-	WARN_ON_ONCE(rc < 0);
-}
-
-static int is_pagetable_dying_supported(void)
-{
-	struct xen_hvm_pagetable_dying a;
-	int rc = 0;
-
-	a.domid = DOMID_SELF;
-	a.gpa = 0x00;
-	rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
-	if (rc < 0) {
-		printk(KERN_DEBUG "HVMOP_pagetable_dying not supported\n");
-		return 0;
-	}
-	return 1;
-}
-
-void __init xen_hvm_init_mmu_ops(void)
-{
-	if (is_pagetable_dying_supported())
-		pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
-#ifdef CONFIG_PROC_VMCORE
-	register_oldmem_pfn_is_ram(&xen_oldmem_pfn_is_ram);
-#endif
-}
-#endif
-
 #define REMAP_BATCH_SIZE 16
 
 struct remap_data {
diff --git a/arch/x86/xen/mmu_hvm.c b/arch/x86/xen/mmu_hvm.c
new file mode 100644
index 0000000..1c57f1c
--- /dev/null
+++ b/arch/x86/xen/mmu_hvm.c
@@ -0,0 +1,79 @@
+#include <linux/types.h>
+#include <linux/crash_dump.h>
+
+#include <xen/interface/xen.h>
+#include <xen/hvm.h>
+
+#include "mmu.h"
+
+#ifdef CONFIG_PROC_VMCORE
+/*
+ * This function is used in two contexts:
+ * - the kdump kernel has to check whether a pfn of the crashed kernel
+ *   was a ballooned page. vmcore is using this function to decide
+ *   whether to access a pfn of the crashed kernel.
+ * - the kexec kernel has to check whether a pfn was ballooned by the
+ *   previous kernel. If the pfn is ballooned, handle it properly.
+ * Returns 0 if the pfn is not backed by a RAM page, the caller may
+ * handle the pfn special in this case.
+ */
+static int xen_oldmem_pfn_is_ram(unsigned long pfn)
+{
+	struct xen_hvm_get_mem_type a = {
+		.domid = DOMID_SELF,
+		.pfn = pfn,
+	};
+	int ram;
+
+	if (HYPERVISOR_hvm_op(HVMOP_get_mem_type, &a))
+		return -ENXIO;
+
+	switch (a.mem_type) {
+	case HVMMEM_mmio_dm:
+		ram = 0;
+		break;
+	case HVMMEM_ram_rw:
+	case HVMMEM_ram_ro:
+	default:
+		ram = 1;
+		break;
+	}
+
+	return ram;
+}
+#endif
+
+static void xen_hvm_exit_mmap(struct mm_struct *mm)
+{
+	struct xen_hvm_pagetable_dying a;
+	int rc;
+
+	a.domid = DOMID_SELF;
+	a.gpa = __pa(mm->pgd);
+	rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
+	WARN_ON_ONCE(rc < 0);
+}
+
+static int is_pagetable_dying_supported(void)
+{
+	struct xen_hvm_pagetable_dying a;
+	int rc = 0;
+
+	a.domid = DOMID_SELF;
+	a.gpa = 0x00;
+	rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
+	if (rc < 0) {
+		printk(KERN_DEBUG "HVMOP_pagetable_dying not supported\n");
+		return 0;
+	}
+	return 1;
+}
+
+void __init xen_hvm_init_mmu_ops(void)
+{
+	if (is_pagetable_dying_supported())
+		pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
+#ifdef CONFIG_PROC_VMCORE
+	register_oldmem_pfn_is_ram(&xen_oldmem_pfn_is_ram);
+#endif
+}
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1591397 — [PATCH v2 09/21] x86/xen: split xen_cpu_die()

FromVitaly Kuznetsov <vkuznets@redhat.com>
Date2017-03-02 20:00 +0100
Subject[PATCH v2 09/21] x86/xen: split xen_cpu_die()
Message-ID<tgE7f-6oo-9@gated-at.bofh.it>
In reply to#1591381
Split xen_cpu_die() into xen_pv_cpu_die() and xen_hvm_cpu_die() to support
further splitting of smp.c.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 arch/x86/xen/smp.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 6c8a3a5..6c4b415 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -513,10 +513,10 @@ static int xen_cpu_disable(void)
 	return 0;
 }
 
-static void xen_cpu_die(unsigned int cpu)
+static void xen_pv_cpu_die(unsigned int cpu)
 {
-	while (xen_pv_domain() && HYPERVISOR_vcpu_op(VCPUOP_is_up,
-						     xen_vcpu_nr(cpu), NULL)) {
+	while (HYPERVISOR_vcpu_op(VCPUOP_is_up,
+				  xen_vcpu_nr(cpu), NULL)) {
 		__set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout(HZ/10);
 	}
@@ -529,6 +529,15 @@ static void xen_cpu_die(unsigned int cpu)
 	}
 }
 
+static void xen_hvm_cpu_die(unsigned int cpu)
+{
+	if (common_cpu_die(cpu) == 0) {
+		xen_smp_intr_free(cpu);
+		xen_uninit_lock_cpu(cpu);
+		xen_teardown_timer(cpu);
+	}
+}
+
 static void xen_play_dead(void) /* used only with HOTPLUG_CPU */
 {
 	play_dead_common();
@@ -551,7 +560,12 @@ static int xen_cpu_disable(void)
 	return -ENOSYS;
 }
 
-static void xen_cpu_die(unsigned int cpu)
+static void xen_pv_cpu_die(unsigned int cpu)
+{
+	BUG();
+}
+
+static void xen_hvm_cpu_die(unsigned int cpu)
 {
 	BUG();
 }
@@ -732,7 +746,7 @@ static const struct smp_ops xen_smp_ops __initconst = {
 	.smp_cpus_done = xen_smp_cpus_done,
 
 	.cpu_up = xen_cpu_up,
-	.cpu_die = xen_cpu_die,
+	.cpu_die = xen_pv_cpu_die,
 	.cpu_disable = xen_cpu_disable,
 	.play_dead = xen_play_dead,
 
@@ -761,7 +775,7 @@ void __init xen_hvm_smp_init(void)
 {
 	smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
 	smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
-	smp_ops.cpu_die = xen_cpu_die;
+	smp_ops.cpu_die = xen_hvm_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;
 	smp_ops.smp_prepare_boot_cpu = xen_hvm_smp_prepare_boot_cpu;
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1598917 — Re: [PATCH v2 09/21] x86/xen: split xen_cpu_die()

FromJuergen Gross <jgross@suse.com>
Date2017-03-13 08:40 +0100
SubjectRe: [PATCH v2 09/21] x86/xen: split xen_cpu_die()
Message-ID<tksKe-5zs-13@gated-at.bofh.it>
In reply to#1591397
On 02/03/17 18:53, Vitaly Kuznetsov wrote:
> Split xen_cpu_die() into xen_pv_cpu_die() and xen_hvm_cpu_die() to support
> further splitting of smp.c.
> 
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>

Reviewed-by: Juergen Gross <jgross@suse.com>


Juergen

[toc] | [prev] | [next] | [standalone]


#1591501 — [PATCH v2 02/21] x86/xen: globalize have_vcpu_info_placement

FromVitaly Kuznetsov <vkuznets@redhat.com>
Date2017-03-02 23:10 +0100
Subject[PATCH v2 02/21] x86/xen: globalize have_vcpu_info_placement
Message-ID<tgH57-85-1@gated-at.bofh.it>
In reply to#1591381
have_vcpu_info_placement applies to both PV and HVM and as we're going
to split the code we need to make it global.

Rename to xen_have_vcpu_info_placement.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 arch/x86/xen/enlighten.c | 12 ++++++------
 arch/x86/xen/xen-ops.h   |  2 ++
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 4c1a582..de77be9 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -164,7 +164,7 @@ struct shared_info *HYPERVISOR_shared_info = &xen_dummy_shared_info;
  *
  * 0: not available, 1: available
  */
-static int have_vcpu_info_placement = 1;
+int xen_have_vcpu_info_placement = 1;
 
 struct tls_descs {
 	struct desc_struct desc[3];
@@ -228,7 +228,7 @@ void xen_vcpu_setup(int cpu)
 		per_cpu(xen_vcpu, cpu) =
 			&HYPERVISOR_shared_info->vcpu_info[xen_vcpu_nr(cpu)];
 
-	if (!have_vcpu_info_placement) {
+	if (!xen_have_vcpu_info_placement) {
 		if (cpu >= MAX_VIRT_CPUS)
 			clamp_max_cpus();
 		return;
@@ -251,7 +251,7 @@ void xen_vcpu_setup(int cpu)
 
 	if (err) {
 		printk(KERN_DEBUG "register_vcpu_info failed: err=%d\n", err);
-		have_vcpu_info_placement = 0;
+		xen_have_vcpu_info_placement = 0;
 		clamp_max_cpus();
 	} else {
 		/* This cpu is using the registered vcpu info, even if
@@ -280,7 +280,7 @@ void xen_vcpu_restore(void)
 
 		xen_setup_runstate_info(cpu);
 
-		if (have_vcpu_info_placement)
+		if (xen_have_vcpu_info_placement)
 			xen_vcpu_setup(cpu);
 
 		if (other_cpu && is_up &&
@@ -1159,7 +1159,7 @@ void xen_setup_vcpu_info_placement(void)
 	 * xen_vcpu_setup managed to place the vcpu_info within the
 	 * percpu area for all cpus, so make use of it.
 	 */
-	if (have_vcpu_info_placement) {
+	if (xen_have_vcpu_info_placement) {
 		pv_irq_ops.save_fl = __PV_IS_CALLEE_SAVE(xen_save_fl_direct);
 		pv_irq_ops.restore_fl = __PV_IS_CALLEE_SAVE(xen_restore_fl_direct);
 		pv_irq_ops.irq_disable = __PV_IS_CALLEE_SAVE(xen_irq_disable_direct);
@@ -1178,7 +1178,7 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf,
 
 #define SITE(op, x)							\
 	case PARAVIRT_PATCH(op.x):					\
-	if (have_vcpu_info_placement) {					\
+	if (xen_have_vcpu_info_placement) {				\
 		start = (char *)xen_##x##_direct;			\
 		end = xen_##x##_direct_end;				\
 		reloc = xen_##x##_direct_reloc;				\
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index f6a41c4..2b162f6 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -76,6 +76,8 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
 
 bool xen_vcpu_stolen(int vcpu);
 
+extern int xen_have_vcpu_info_placement;
+
 void xen_vcpu_setup(int cpu);
 void xen_setup_vcpu_info_placement(void);
 
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1595243 — Re: [PATCH v2 02/21] x86/xen: globalize have_vcpu_info_placement

FromJuergen Gross <jgross@suse.com>
Date2017-03-08 16:10 +0100
SubjectRe: [PATCH v2 02/21] x86/xen: globalize have_vcpu_info_placement
Message-ID<tiLnY-8jK-19@gated-at.bofh.it>
In reply to#1591501
On 02/03/17 18:53, Vitaly Kuznetsov wrote:
> have_vcpu_info_placement applies to both PV and HVM and as we're going
> to split the code we need to make it global.
> 
> Rename to xen_have_vcpu_info_placement.
> 
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>

Reviewed-by: Juergen Gross <jgross@suse.com>


Juergen

[toc] | [prev] | [next] | [standalone]


#1591502 — [PATCH v2 01/21] x86/xen: separate PV and HVM hypervisors

FromVitaly Kuznetsov <vkuznets@redhat.com>
Date2017-03-02 23:10 +0100
Subject[PATCH v2 01/21] x86/xen: separate PV and HVM hypervisors
Message-ID<tgH57-85-7@gated-at.bofh.it>
In reply to#1591381
As a preparation to splitting the code we need to untangle it:

x86_hyper_xen -> x86_hyper_xen_hvm and x86_hyper_xen_pv
xen_platform() -> xen_platform_hvm() and xen_platform_pv()
xen_cpu_up_prepare() -> xen_cpu_up_prepare_pv() and xen_cpu_up_prepare_hvm()
xen_cpu_dead() -> xen_cpu_dead_pv() and xen_cpu_dead_pv_hvm()

Add two parameters to xen_cpuhp_setup() to pass proper cpu_up_prepare and
cpu_dead hooks. xen_set_cpu_features() is now PV-only so the redundant
xen_pv_domain() check can be dropped.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 arch/x86/include/asm/hypervisor.h |   3 +-
 arch/x86/kernel/cpu/hypervisor.c  |   3 +-
 arch/x86/xen/enlighten.c          | 113 +++++++++++++++++++++++++-------------
 3 files changed, 78 insertions(+), 41 deletions(-)

diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h
index 67942b6..6f7545c6 100644
--- a/arch/x86/include/asm/hypervisor.h
+++ b/arch/x86/include/asm/hypervisor.h
@@ -53,7 +53,8 @@ extern const struct hypervisor_x86 *x86_hyper;
 /* Recognized hypervisors */
 extern const struct hypervisor_x86 x86_hyper_vmware;
 extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
-extern const struct hypervisor_x86 x86_hyper_xen;
+extern const struct hypervisor_x86 x86_hyper_xen_pv;
+extern const struct hypervisor_x86 x86_hyper_xen_hvm;
 extern const struct hypervisor_x86 x86_hyper_kvm;
 
 extern void init_hypervisor(struct cpuinfo_x86 *c);
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index 35691a6..a77f18d 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -29,7 +29,8 @@
 static const __initconst struct hypervisor_x86 * const hypervisors[] =
 {
 #ifdef CONFIG_XEN
-	&x86_hyper_xen,
+	&x86_hyper_xen_pv,
+	&x86_hyper_xen_hvm,
 #endif
 	&x86_hyper_vmware,
 	&x86_hyper_ms_hyperv,
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index ec1d5c4..4c1a582 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -139,9 +139,11 @@ void *xen_initial_gdt;
 
 RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
 
-static int xen_cpu_up_prepare(unsigned int cpu);
+static int xen_cpu_up_prepare_pv(unsigned int cpu);
+static int xen_cpu_up_prepare_hvm(unsigned int cpu);
 static int xen_cpu_up_online(unsigned int cpu);
-static int xen_cpu_dead(unsigned int cpu);
+static int xen_cpu_dead_pv(unsigned int cpu);
+static int xen_cpu_dead_hvm(unsigned int cpu);
 
 /*
  * Point at some empty memory to start with. We map the real shared_info
@@ -1447,13 +1449,14 @@ static void __init xen_dom0_set_legacy_features(void)
 	x86_platform.legacy.rtc = 1;
 }
 
-static int xen_cpuhp_setup(void)
+static int xen_cpuhp_setup(int (*cpu_up_prepare_cb)(unsigned int),
+			   int (*cpu_dead_cb)(unsigned int))
 {
 	int rc;
 
 	rc = cpuhp_setup_state_nocalls(CPUHP_XEN_PREPARE,
 				       "x86/xen/hvm_guest:prepare",
-				       xen_cpu_up_prepare, xen_cpu_dead);
+				       cpu_up_prepare_cb, cpu_dead_cb);
 	if (rc >= 0) {
 		rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
 					       "x86/xen/hvm_guest:online",
@@ -1559,7 +1562,7 @@ 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());
+	WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_pv, xen_cpu_dead_pv));
 
 	local_irq_disable();
 	early_boot_irqs_disabled = true;
@@ -1840,28 +1843,41 @@ static void __init init_hvm_pv_info(void)
 }
 #endif
 
-static int xen_cpu_up_prepare(unsigned int cpu)
+static int xen_cpu_up_prepare_pv(unsigned int cpu)
 {
 	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);
-		}
+	xen_setup_timer(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);
+	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 int xen_cpu_up_prepare_hvm(unsigned int cpu)
+{
+	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);
 	}
 
-	if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
+	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_feature(XENFEAT_hvm_safe_pvclock))
 		xen_setup_timer(cpu);
 
 	rc = xen_smp_intr_init(cpu);
@@ -1873,16 +1889,25 @@ static int xen_cpu_up_prepare(unsigned int cpu)
 	return 0;
 }
 
-static int xen_cpu_dead(unsigned int cpu)
+static int xen_cpu_dead_pv(unsigned int cpu)
 {
 	xen_smp_intr_free(cpu);
 
-	if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
-		xen_teardown_timer(cpu);
+	xen_teardown_timer(cpu);
 
 	return 0;
 }
 
+static int xen_cpu_dead_hvm(unsigned int cpu)
+{
+	xen_smp_intr_free(cpu);
+
+	if (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);
@@ -1919,7 +1944,7 @@ static void __init xen_hvm_guest_init(void)
 	BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector));
 
 	xen_hvm_smp_init();
-	WARN_ON(xen_cpuhp_setup());
+	WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_hvm, xen_cpu_dead_hvm));
 	xen_unplug_emulated_devices();
 	x86_init.irqs.intr_init = xen_init_IRQ;
 	xen_hvm_init_time_ops();
@@ -1942,9 +1967,17 @@ static __init int xen_parse_nopv(char *arg)
 }
 early_param("xen_nopv", xen_parse_nopv);
 
-static uint32_t __init xen_platform(void)
+static uint32_t __init xen_platform_pv(void)
 {
-	if (xen_nopv)
+	if (xen_pv_domain())
+		return xen_cpuid_base();
+
+	return 0;
+}
+
+static uint32_t __init xen_platform_hvm(void)
+{
+	if (xen_pv_domain() || xen_nopv)
 		return 0;
 
 	return xen_cpuid_base();
@@ -1966,10 +1999,8 @@ EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
 
 static void xen_set_cpu_features(struct cpuinfo_x86 *c)
 {
-	if (xen_pv_domain()) {
-		clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
-		set_cpu_cap(c, X86_FEATURE_XENPV);
-	}
+	clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+	set_cpu_cap(c, X86_FEATURE_XENPV);
 }
 
 static void xen_pin_vcpu(int cpu)
@@ -2011,17 +2042,21 @@ static void xen_pin_vcpu(int cpu)
 	}
 }
 
-const struct hypervisor_x86 x86_hyper_xen = {
-	.name			= "Xen",
-	.detect			= xen_platform,
-#ifdef CONFIG_XEN_PVHVM
-	.init_platform		= xen_hvm_guest_init,
-#endif
-	.x2apic_available	= xen_x2apic_para_available,
+const struct hypervisor_x86 x86_hyper_xen_pv = {
+	.name                   = "Xen PV",
+	.detect                 = xen_platform_pv,
 	.set_cpu_features       = xen_set_cpu_features,
 	.pin_vcpu               = xen_pin_vcpu,
 };
-EXPORT_SYMBOL(x86_hyper_xen);
+EXPORT_SYMBOL(x86_hyper_xen_pv);
+
+const struct hypervisor_x86 x86_hyper_xen_hvm = {
+	.name                   = "Xen HVM",
+	.detect                 = xen_platform_hvm,
+	.init_platform          = xen_hvm_guest_init,
+	.x2apic_available       = xen_x2apic_para_available,
+};
+EXPORT_SYMBOL(x86_hyper_xen_hvm);
 
 #ifdef CONFIG_HOTPLUG_CPU
 void xen_arch_register_cpu(int num)
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1595240 — Re: [PATCH v2 01/21] x86/xen: separate PV and HVM hypervisors

FromJuergen Gross <jgross@suse.com>
Date2017-03-08 16:10 +0100
SubjectRe: [PATCH v2 01/21] x86/xen: separate PV and HVM hypervisors
Message-ID<tiLnX-8jK-5@gated-at.bofh.it>
In reply to#1591502
On 02/03/17 18:53, Vitaly Kuznetsov wrote:
> As a preparation to splitting the code we need to untangle it:
> 
> x86_hyper_xen -> x86_hyper_xen_hvm and x86_hyper_xen_pv
> xen_platform() -> xen_platform_hvm() and xen_platform_pv()
> xen_cpu_up_prepare() -> xen_cpu_up_prepare_pv() and xen_cpu_up_prepare_hvm()
> xen_cpu_dead() -> xen_cpu_dead_pv() and xen_cpu_dead_pv_hvm()
> 
> Add two parameters to xen_cpuhp_setup() to pass proper cpu_up_prepare and
> cpu_dead hooks. xen_set_cpu_features() is now PV-only so the redundant
> xen_pv_domain() check can be dropped.
> 
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
> ---
>  arch/x86/include/asm/hypervisor.h |   3 +-
>  arch/x86/kernel/cpu/hypervisor.c  |   3 +-
>  arch/x86/xen/enlighten.c          | 113 +++++++++++++++++++++++++-------------
>  3 files changed, 78 insertions(+), 41 deletions(-)
> 
> diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h
> index 67942b6..6f7545c6 100644
> --- a/arch/x86/include/asm/hypervisor.h
> +++ b/arch/x86/include/asm/hypervisor.h
> @@ -53,7 +53,8 @@ extern const struct hypervisor_x86 *x86_hyper;
>  /* Recognized hypervisors */
>  extern const struct hypervisor_x86 x86_hyper_vmware;
>  extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
> -extern const struct hypervisor_x86 x86_hyper_xen;
> +extern const struct hypervisor_x86 x86_hyper_xen_pv;
> +extern const struct hypervisor_x86 x86_hyper_xen_hvm;
>  extern const struct hypervisor_x86 x86_hyper_kvm;
>  
>  extern void init_hypervisor(struct cpuinfo_x86 *c);
> diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
> index 35691a6..a77f18d 100644
> --- a/arch/x86/kernel/cpu/hypervisor.c
> +++ b/arch/x86/kernel/cpu/hypervisor.c
> @@ -29,7 +29,8 @@
>  static const __initconst struct hypervisor_x86 * const hypervisors[] =
>  {
>  #ifdef CONFIG_XEN
> -	&x86_hyper_xen,
> +	&x86_hyper_xen_pv,
> +	&x86_hyper_xen_hvm,
>  #endif
>  	&x86_hyper_vmware,
>  	&x86_hyper_ms_hyperv,
> diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
> index ec1d5c4..4c1a582 100644
> --- a/arch/x86/xen/enlighten.c
> +++ b/arch/x86/xen/enlighten.c
> @@ -139,9 +139,11 @@ void *xen_initial_gdt;
>  
>  RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
>  
> -static int xen_cpu_up_prepare(unsigned int cpu);
> +static int xen_cpu_up_prepare_pv(unsigned int cpu);
> +static int xen_cpu_up_prepare_hvm(unsigned int cpu);
>  static int xen_cpu_up_online(unsigned int cpu);
> -static int xen_cpu_dead(unsigned int cpu);
> +static int xen_cpu_dead_pv(unsigned int cpu);
> +static int xen_cpu_dead_hvm(unsigned int cpu);
>  
>  /*
>   * Point at some empty memory to start with. We map the real shared_info
> @@ -1447,13 +1449,14 @@ static void __init xen_dom0_set_legacy_features(void)
>  	x86_platform.legacy.rtc = 1;
>  }
>  
> -static int xen_cpuhp_setup(void)
> +static int xen_cpuhp_setup(int (*cpu_up_prepare_cb)(unsigned int),
> +			   int (*cpu_dead_cb)(unsigned int))
>  {
>  	int rc;
>  
>  	rc = cpuhp_setup_state_nocalls(CPUHP_XEN_PREPARE,
>  				       "x86/xen/hvm_guest:prepare",
> -				       xen_cpu_up_prepare, xen_cpu_dead);
> +				       cpu_up_prepare_cb, cpu_dead_cb);
>  	if (rc >= 0) {
>  		rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
>  					       "x86/xen/hvm_guest:online",
> @@ -1559,7 +1562,7 @@ 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());
> +	WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_pv, xen_cpu_dead_pv));
>  
>  	local_irq_disable();
>  	early_boot_irqs_disabled = true;
> @@ -1840,28 +1843,41 @@ static void __init init_hvm_pv_info(void)
>  }
>  #endif
>  
> -static int xen_cpu_up_prepare(unsigned int cpu)
> +static int xen_cpu_up_prepare_pv(unsigned int cpu)
>  {
>  	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);
> -		}
> +	xen_setup_timer(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);
> +	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 int xen_cpu_up_prepare_hvm(unsigned int cpu)
> +{
> +	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);
>  	}
>  
> -	if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
> +	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_feature(XENFEAT_hvm_safe_pvclock))
>  		xen_setup_timer(cpu);
>  
>  	rc = xen_smp_intr_init(cpu);
> @@ -1873,16 +1889,25 @@ static int xen_cpu_up_prepare(unsigned int cpu)
>  	return 0;
>  }
>  
> -static int xen_cpu_dead(unsigned int cpu)
> +static int xen_cpu_dead_pv(unsigned int cpu)
>  {
>  	xen_smp_intr_free(cpu);
>  
> -	if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
> -		xen_teardown_timer(cpu);
> +	xen_teardown_timer(cpu);
>  
>  	return 0;
>  }
>  
> +static int xen_cpu_dead_hvm(unsigned int cpu)
> +{
> +	xen_smp_intr_free(cpu);
> +
> +	if (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);
> @@ -1919,7 +1944,7 @@ static void __init xen_hvm_guest_init(void)
>  	BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector));
>  
>  	xen_hvm_smp_init();
> -	WARN_ON(xen_cpuhp_setup());
> +	WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_hvm, xen_cpu_dead_hvm));
>  	xen_unplug_emulated_devices();
>  	x86_init.irqs.intr_init = xen_init_IRQ;
>  	xen_hvm_init_time_ops();
> @@ -1942,9 +1967,17 @@ static __init int xen_parse_nopv(char *arg)
>  }
>  early_param("xen_nopv", xen_parse_nopv);
>  
> -static uint32_t __init xen_platform(void)
> +static uint32_t __init xen_platform_pv(void)
>  {
> -	if (xen_nopv)
> +	if (xen_pv_domain())
> +		return xen_cpuid_base();
> +
> +	return 0;
> +}
> +
> +static uint32_t __init xen_platform_hvm(void)
> +{
> +	if (xen_pv_domain() || xen_nopv)
>  		return 0;
>  
>  	return xen_cpuid_base();
> @@ -1966,10 +1999,8 @@ EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
>  
>  static void xen_set_cpu_features(struct cpuinfo_x86 *c)
>  {
> -	if (xen_pv_domain()) {
> -		clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
> -		set_cpu_cap(c, X86_FEATURE_XENPV);
> -	}
> +	clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
> +	set_cpu_cap(c, X86_FEATURE_XENPV);
>  }
>  
>  static void xen_pin_vcpu(int cpu)
> @@ -2011,17 +2042,21 @@ static void xen_pin_vcpu(int cpu)
>  	}
>  }
>  
> -const struct hypervisor_x86 x86_hyper_xen = {
> -	.name			= "Xen",
> -	.detect			= xen_platform,
> -#ifdef CONFIG_XEN_PVHVM
> -	.init_platform		= xen_hvm_guest_init,
> -#endif
> -	.x2apic_available	= xen_x2apic_para_available,
> +const struct hypervisor_x86 x86_hyper_xen_pv = {
> +	.name                   = "Xen PV",
> +	.detect                 = xen_platform_pv,
>  	.set_cpu_features       = xen_set_cpu_features,
>  	.pin_vcpu               = xen_pin_vcpu,
>  };
> -EXPORT_SYMBOL(x86_hyper_xen);
> +EXPORT_SYMBOL(x86_hyper_xen_pv);
> +
> +const struct hypervisor_x86 x86_hyper_xen_hvm = {
> +	.name                   = "Xen HVM",
> +	.detect                 = xen_platform_hvm,
> +	.init_platform          = xen_hvm_guest_init,
> +	.x2apic_available       = xen_x2apic_para_available,

Please keep the .pin_vcpu member. It will be needed for a PVH dom0.


Juergen

[toc] | [prev] | [next] | [standalone]


#1591503 — [PATCH v2 05/21] x86/xen: split off enlighten_hvm.c

FromVitaly Kuznetsov <vkuznets@redhat.com>
Date2017-03-02 23:10 +0100
Subject[PATCH v2 05/21] x86/xen: split off enlighten_hvm.c
Message-ID<tgH58-85-11@gated-at.bofh.it>
In reply to#1591381
Move PVHVM related code to enlighten_hvm.c. Three functions:
xen_cpuhp_setup(), xen_reboot(), xen_emergency_restart() are shared, drop
static qualifier from them. These functions will go to common code once
it is split from enlighten.c.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 arch/x86/xen/Makefile        |   1 +
 arch/x86/xen/enlighten.c     | 209 +-----------------------------------------
 arch/x86/xen/enlighten_hvm.c | 210 +++++++++++++++++++++++++++++++++++++++++++
 arch/x86/xen/xen-ops.h       |   6 ++
 4 files changed, 221 insertions(+), 205 deletions(-)
 create mode 100644 arch/x86/xen/enlighten_hvm.c

diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index 348128b..1bca75b 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -15,6 +15,7 @@ obj-y		:= enlighten.o setup.o multicalls.o mmu.o irq.o \
 			grant-table.o suspend.o platform-pci-unplug.o \
 			p2m.o apic.o pmu.o
 
+obj-$(CONFIG_XEN_PVHVM)		+= enlighten_hvm.o
 obj-$(CONFIG_XEN_PVH)			+= enlighten_pvh.o
 
 obj-$(CONFIG_EVENT_TRACING) += trace.o
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index d66debd..0cd99ad 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -45,10 +45,8 @@
 #include <xen/interface/memory.h>
 #include <xen/interface/nmi.h>
 #include <xen/interface/xen-mca.h>
-#include <xen/interface/hvm/start_info.h>
 #include <xen/features.h>
 #include <xen/page.h>
-#include <xen/hvm.h>
 #include <xen/hvc-console.h>
 #include <xen/acpi.h>
 
@@ -140,10 +138,8 @@ void *xen_initial_gdt;
 RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
 
 static int xen_cpu_up_prepare_pv(unsigned int cpu);
-static int xen_cpu_up_prepare_hvm(unsigned int cpu);
 static int xen_cpu_up_online(unsigned int cpu);
 static int xen_cpu_dead_pv(unsigned int cpu);
-static int xen_cpu_dead_hvm(unsigned int cpu);
 
 /*
  * Point at some empty memory to start with. We map the real shared_info
@@ -1282,7 +1278,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
 	.end_context_switch = xen_end_context_switch,
 };
 
-static void xen_reboot(int reason)
+void xen_reboot(int reason)
 {
 	struct sched_shutdown r = { .reason = reason };
 	int cpu;
@@ -1299,7 +1295,7 @@ static void xen_restart(char *msg)
 	xen_reboot(SHUTDOWN_reboot);
 }
 
-static void xen_emergency_restart(void)
+void xen_emergency_restart(void)
 {
 	xen_reboot(SHUTDOWN_reboot);
 }
@@ -1435,8 +1431,8 @@ static void __init xen_dom0_set_legacy_features(void)
 	x86_platform.legacy.rtc = 1;
 }
 
-static int xen_cpuhp_setup(int (*cpu_up_prepare_cb)(unsigned int),
-			   int (*cpu_dead_cb)(unsigned int))
+int xen_cpuhp_setup(int (*cpu_up_prepare_cb)(unsigned int),
+		    int (*cpu_dead_cb)(unsigned int))
 {
 	int rc;
 
@@ -1660,79 +1656,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
 #endif
 }
 
-void __ref xen_hvm_init_shared_info(void)
-{
-	int cpu;
-	struct xen_add_to_physmap xatp;
-	static struct shared_info *shared_info_page = 0;
-
-	if (!shared_info_page)
-		shared_info_page = (struct shared_info *)
-			extend_brk(PAGE_SIZE, PAGE_SIZE);
-	xatp.domid = DOMID_SELF;
-	xatp.idx = 0;
-	xatp.space = XENMAPSPACE_shared_info;
-	xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
-	if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
-		BUG();
-
-	HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
-
-	/* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
-	 * page, we use it in the event channel upcall and in some pvclock
-	 * related functions. We don't need the vcpu_info placement
-	 * optimizations because we don't use any pv_mmu or pv_irq op on
-	 * HVM.
-	 * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
-	 * online but xen_hvm_init_shared_info is run at resume time too and
-	 * in that case multiple vcpus might be online. */
-	for_each_online_cpu(cpu) {
-		/* Leave it to be NULL. */
-		if (xen_vcpu_nr(cpu) >= MAX_VIRT_CPUS)
-			continue;
-		per_cpu(xen_vcpu, cpu) =
-			&HYPERVISOR_shared_info->vcpu_info[xen_vcpu_nr(cpu)];
-	}
-}
-
-#ifdef CONFIG_XEN_PVHVM
-static void __init init_hvm_pv_info(void)
-{
-	int major, minor;
-	uint32_t eax, ebx, ecx, edx, base;
-
-	base = xen_cpuid_base();
-	eax = cpuid_eax(base + 1);
-
-	major = eax >> 16;
-	minor = eax & 0xffff;
-	printk(KERN_INFO "Xen version %d.%d.\n", major, minor);
-
-	xen_domain_type = XEN_HVM_DOMAIN;
-
-	/* PVH set up hypercall page in xen_prepare_pvh(). */
-	if (xen_pvh_domain())
-		pv_info.name = "Xen PVH";
-	else {
-		u64 pfn;
-		uint32_t msr;
-
-		pv_info.name = "Xen HVM";
-		msr = cpuid_ebx(base + 2);
-		pfn = __pa(hypercall_page);
-		wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
-	}
-
-	xen_setup_features();
-
-	cpuid(base + 4, &eax, &ebx, &ecx, &edx);
-	if (eax & XEN_HVM_CPUID_VCPU_ID_PRESENT)
-		this_cpu_write(xen_vcpu_id, ebx);
-	else
-		this_cpu_write(xen_vcpu_id, smp_processor_id());
-}
-#endif
-
 static int xen_cpu_up_prepare_pv(unsigned int cpu)
 {
 	int rc;
@@ -1748,37 +1671,6 @@ static int xen_cpu_up_prepare_pv(unsigned int cpu)
 	return 0;
 }
 
-static int xen_cpu_up_prepare_hvm(unsigned int cpu)
-{
-	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);
-	}
-
-	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_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 int xen_cpu_dead_pv(unsigned int cpu)
 {
 	xen_smp_intr_free(cpu);
@@ -1788,75 +1680,12 @@ static int xen_cpu_dead_pv(unsigned int cpu)
 	return 0;
 }
 
-static int xen_cpu_dead_hvm(unsigned int cpu)
-{
-	xen_smp_intr_free(cpu);
-
-	if (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_XEN_PVHVM
-#ifdef CONFIG_KEXEC_CORE
-static void xen_hvm_shutdown(void)
-{
-	native_machine_shutdown();
-	if (kexec_in_progress)
-		xen_reboot(SHUTDOWN_soft_reset);
-}
-
-static void xen_hvm_crash_shutdown(struct pt_regs *regs)
-{
-	native_machine_crash_shutdown(regs);
-	xen_reboot(SHUTDOWN_soft_reset);
-}
-#endif
-
-static void __init xen_hvm_guest_init(void)
-{
-	if (xen_pv_domain())
-		return;
-
-	init_hvm_pv_info();
-
-	xen_hvm_init_shared_info();
-
-	xen_panic_handler_init();
-
-	BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector));
-
-	xen_hvm_smp_init();
-	WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_hvm, xen_cpu_dead_hvm));
-	xen_unplug_emulated_devices();
-	x86_init.irqs.intr_init = xen_init_IRQ;
-	xen_hvm_init_time_ops();
-	xen_hvm_init_mmu_ops();
-
-	if (xen_pvh_domain())
-		machine_ops.emergency_restart = xen_emergency_restart;
-#ifdef CONFIG_KEXEC_CORE
-	machine_ops.shutdown = xen_hvm_shutdown;
-	machine_ops.crash_shutdown = xen_hvm_crash_shutdown;
-#endif
-}
-#endif
-
-static bool xen_nopv = false;
-static __init int xen_parse_nopv(char *arg)
-{
-       xen_nopv = true;
-       return 0;
-}
-early_param("xen_nopv", xen_parse_nopv);
-
 static uint32_t __init xen_platform_pv(void)
 {
 	if (xen_pv_domain())
@@ -1865,28 +1694,6 @@ static uint32_t __init xen_platform_pv(void)
 	return 0;
 }
 
-static uint32_t __init xen_platform_hvm(void)
-{
-	if (xen_pv_domain() || xen_nopv)
-		return 0;
-
-	return xen_cpuid_base();
-}
-
-bool xen_hvm_need_lapic(void)
-{
-	if (xen_nopv)
-		return false;
-	if (xen_pv_domain())
-		return false;
-	if (!xen_hvm_domain())
-		return false;
-	if (xen_feature(XENFEAT_hvm_pirqs))
-		return false;
-	return true;
-}
-EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
-
 static void xen_set_cpu_features(struct cpuinfo_x86 *c)
 {
 	clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
@@ -1940,14 +1747,6 @@ const struct hypervisor_x86 x86_hyper_xen_pv = {
 };
 EXPORT_SYMBOL(x86_hyper_xen_pv);
 
-const struct hypervisor_x86 x86_hyper_xen_hvm = {
-	.name                   = "Xen HVM",
-	.detect                 = xen_platform_hvm,
-	.init_platform          = xen_hvm_guest_init,
-	.x2apic_available       = xen_x2apic_para_available,
-};
-EXPORT_SYMBOL(x86_hyper_xen_hvm);
-
 #ifdef CONFIG_HOTPLUG_CPU
 void xen_arch_register_cpu(int num)
 {
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
new file mode 100644
index 0000000..a8f4d7e
--- /dev/null
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -0,0 +1,210 @@
+#include <linux/cpu.h>
+#include <linux/kexec.h>
+
+#include <xen/features.h>
+#include <xen/events.h>
+#include <xen/interface/memory.h>
+
+#include <asm/reboot.h>
+#include <asm/setup.h>
+#include <asm/hypervisor.h>
+
+#include <asm/xen/cpuid.h>
+#include <asm/xen/hypervisor.h>
+
+#include "xen-ops.h"
+#include "mmu.h"
+#include "smp.h"
+
+void __ref xen_hvm_init_shared_info(void)
+{
+	int cpu;
+	struct xen_add_to_physmap xatp;
+	static struct shared_info *shared_info_page;
+
+	if (!shared_info_page)
+		shared_info_page = (struct shared_info *)
+			extend_brk(PAGE_SIZE, PAGE_SIZE);
+	xatp.domid = DOMID_SELF;
+	xatp.idx = 0;
+	xatp.space = XENMAPSPACE_shared_info;
+	xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
+	if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
+		BUG();
+
+	HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
+
+	/* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
+	 * page, we use it in the event channel upcall and in some pvclock
+	 * related functions. We don't need the vcpu_info placement
+	 * optimizations because we don't use any pv_mmu or pv_irq op on
+	 * HVM.
+	 * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
+	 * online but xen_hvm_init_shared_info is run at resume time too and
+	 * in that case multiple vcpus might be online. */
+	for_each_online_cpu(cpu) {
+		/* Leave it to be NULL. */
+		if (xen_vcpu_nr(cpu) >= MAX_VIRT_CPUS)
+			continue;
+		per_cpu(xen_vcpu, cpu) =
+			&HYPERVISOR_shared_info->vcpu_info[xen_vcpu_nr(cpu)];
+	}
+}
+
+static void __init init_hvm_pv_info(void)
+{
+	int major, minor;
+	uint32_t eax, ebx, ecx, edx, base;
+
+	base = xen_cpuid_base();
+	eax = cpuid_eax(base + 1);
+
+	major = eax >> 16;
+	minor = eax & 0xffff;
+	printk(KERN_INFO "Xen version %d.%d.\n", major, minor);
+
+	xen_domain_type = XEN_HVM_DOMAIN;
+
+	/* PVH set up hypercall page in xen_prepare_pvh(). */
+	if (xen_pvh_domain())
+		pv_info.name = "Xen PVH";
+	else {
+		u64 pfn;
+		uint32_t msr;
+
+		pv_info.name = "Xen HVM";
+		msr = cpuid_ebx(base + 2);
+		pfn = __pa(hypercall_page);
+		wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
+	}
+
+	xen_setup_features();
+
+	cpuid(base + 4, &eax, &ebx, &ecx, &edx);
+	if (eax & XEN_HVM_CPUID_VCPU_ID_PRESENT)
+		this_cpu_write(xen_vcpu_id, ebx);
+	else
+		this_cpu_write(xen_vcpu_id, smp_processor_id());
+}
+
+#ifdef CONFIG_KEXEC_CORE
+static void xen_hvm_shutdown(void)
+{
+	native_machine_shutdown();
+	if (kexec_in_progress)
+		xen_reboot(SHUTDOWN_soft_reset);
+}
+
+static void xen_hvm_crash_shutdown(struct pt_regs *regs)
+{
+	native_machine_crash_shutdown(regs);
+	xen_reboot(SHUTDOWN_soft_reset);
+}
+#endif
+
+static int xen_cpu_up_prepare_hvm(unsigned int cpu)
+{
+	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);
+	}
+
+	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_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 int xen_cpu_dead_hvm(unsigned int cpu)
+{
+	xen_smp_intr_free(cpu);
+
+	if (xen_feature(XENFEAT_hvm_safe_pvclock))
+		xen_teardown_timer(cpu);
+
+       return 0;
+}
+
+static void __init xen_hvm_guest_init(void)
+{
+	if (xen_pv_domain())
+		return;
+
+	init_hvm_pv_info();
+
+	xen_hvm_init_shared_info();
+
+	xen_panic_handler_init();
+
+	BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector));
+
+	xen_hvm_smp_init();
+	WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_hvm, xen_cpu_dead_hvm));
+	xen_unplug_emulated_devices();
+	x86_init.irqs.intr_init = xen_init_IRQ;
+	xen_hvm_init_time_ops();
+	xen_hvm_init_mmu_ops();
+
+	if (xen_pvh_domain())
+		machine_ops.emergency_restart = xen_emergency_restart;
+#ifdef CONFIG_KEXEC_CORE
+	machine_ops.shutdown = xen_hvm_shutdown;
+	machine_ops.crash_shutdown = xen_hvm_crash_shutdown;
+#endif
+}
+
+static bool xen_nopv;
+static __init int xen_parse_nopv(char *arg)
+{
+       xen_nopv = true;
+       return 0;
+}
+early_param("xen_nopv", xen_parse_nopv);
+
+bool xen_hvm_need_lapic(void)
+{
+	if (xen_nopv)
+		return false;
+	if (xen_pv_domain())
+		return false;
+	if (!xen_hvm_domain())
+		return false;
+	if (xen_feature(XENFEAT_hvm_pirqs))
+		return false;
+	return true;
+}
+EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
+
+static uint32_t __init xen_platform_hvm(void)
+{
+	if (xen_pv_domain() || xen_nopv)
+		return 0;
+
+	return xen_cpuid_base();
+}
+
+const struct hypervisor_x86 x86_hyper_xen_hvm = {
+	.name                   = "Xen HVM",
+	.detect                 = xen_platform_hvm,
+	.init_platform          = xen_hvm_guest_init,
+	.x2apic_available       = xen_x2apic_para_available,
+};
+EXPORT_SYMBOL(x86_hyper_xen_hvm);
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 2b162f6..7baeb04 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -148,4 +148,10 @@ __visible void xen_adjust_exception_frame(void);
 
 extern int xen_panic_handler_init(void);
 
+extern int xen_cpuhp_setup(int (*cpu_up_prepare_cb)(unsigned int),
+			   int (*cpu_dead_cb)(unsigned int));
+
+extern void xen_reboot(int reason);
+extern void xen_emergency_restart(void);
+
 #endif /* XEN_OPS_H */
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1595290 — Re: [PATCH v2 05/21] x86/xen: split off enlighten_hvm.c

FromJuergen Gross <jgross@suse.com>
Date2017-03-08 16:40 +0100
SubjectRe: [PATCH v2 05/21] x86/xen: split off enlighten_hvm.c
Message-ID<tiLR0-8we-29@gated-at.bofh.it>
In reply to#1591503
On 02/03/17 18:53, Vitaly Kuznetsov wrote:
> Move PVHVM related code to enlighten_hvm.c. Three functions:
> xen_cpuhp_setup(), xen_reboot(), xen_emergency_restart() are shared, drop
> static qualifier from them. These functions will go to common code once
> it is split from enlighten.c.
> 
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>

Reviewed-by: Juergen Gross <jgross@suse.com>


Juergen

[toc] | [prev] | [next] | [standalone]


#1591505 — [PATCH v2 10/21] x86/xen: split off smp_hvm.c

FromVitaly Kuznetsov <vkuznets@redhat.com>
Date2017-03-02 23:10 +0100
Subject[PATCH v2 10/21] x86/xen: split off smp_hvm.c
Message-ID<tgH58-85-15@gated-at.bofh.it>
In reply to#1591381
Move PVHVM related code to smp_hvm.c. Drop 'static' qualifier from
xen_smp_send_reschedule(), xen_smp_send_call_function_ipi(),
xen_smp_send_call_function_single_ipi(), these functions will be moved to
common smp code when smp_pv.c is split.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 arch/x86/xen/Kconfig   |  4 ++++
 arch/x86/xen/Makefile  |  1 +
 arch/x86/xen/smp.c     | 57 +++----------------------------------------------
 arch/x86/xen/smp.h     |  3 +++
 arch/x86/xen/smp_hvm.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 69 insertions(+), 54 deletions(-)
 create mode 100644 arch/x86/xen/smp_hvm.c

diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index c387560..dae8dc6 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -37,6 +37,10 @@ config XEN_PVHVM
 	help
 	  Support running as a Xen PVHVM guest.
 
+config XEN_PVHVM_SMP
+	def_bool y
+	depends on XEN_PVHVM && SMP
+
 config XEN_512GB
 	bool "Limit Xen pv-domain memory to 512GB"
 	depends on XEN_PV && X86_64
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index 5ca8d3eb..bc7df8c 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_XEN_PVH)			+= enlighten_pvh.o
 obj-$(CONFIG_EVENT_TRACING) += trace.o
 
 obj-$(CONFIG_SMP)		+= smp.o
+obj-$(CONFIG_XEN_PVHVM_SMP)  	+= smp_hvm.o
 obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
 obj-$(CONFIG_XEN_DEBUG_FS)	+= debugfs.o
 obj-$(CONFIG_XEN_DOM0)		+= vga.o
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 6c4b415..c692336 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -327,25 +327,6 @@ static void __init xen_pv_smp_prepare_boot_cpu(void)
 	xen_init_spinlocks();
 }
 
-static void __init xen_hvm_smp_prepare_boot_cpu(void)
-{
-	BUG_ON(smp_processor_id() != 0);
-	native_smp_prepare_boot_cpu();
-
-	/*
-	 * Setup vcpu_info for boot CPU.
-	 */
-	xen_vcpu_setup(0);
-
-	/*
-	 * The alternative logic (which patches the unlock/lock) runs before
-	 * the smp bootup up code is activated. Hence we need to set this up
-	 * the core kernel is being patched. Otherwise we will have only
-	 * modules patched but not core code.
-	 */
-	xen_init_spinlocks();
-}
-
 static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
 {
 	unsigned cpu;
@@ -529,15 +510,6 @@ static void xen_pv_cpu_die(unsigned int cpu)
 	}
 }
 
-static void xen_hvm_cpu_die(unsigned int cpu)
-{
-	if (common_cpu_die(cpu) == 0) {
-		xen_smp_intr_free(cpu);
-		xen_uninit_lock_cpu(cpu);
-		xen_teardown_timer(cpu);
-	}
-}
-
 static void xen_play_dead(void) /* used only with HOTPLUG_CPU */
 {
 	play_dead_common();
@@ -565,11 +537,6 @@ static void xen_pv_cpu_die(unsigned int cpu)
 	BUG();
 }
 
-static void xen_hvm_cpu_die(unsigned int cpu)
-{
-	BUG();
-}
-
 static void xen_play_dead(void)
 {
 	BUG();
@@ -595,7 +562,7 @@ static void xen_stop_other_cpus(int wait)
 	smp_call_function(stop_self, NULL, wait);
 }
 
-static void xen_smp_send_reschedule(int cpu)
+void xen_smp_send_reschedule(int cpu)
 {
 	xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR);
 }
@@ -609,7 +576,7 @@ static void __xen_send_IPI_mask(const struct cpumask *mask,
 		xen_send_IPI_one(cpu, vector);
 }
 
-static void xen_smp_send_call_function_ipi(const struct cpumask *mask)
+void xen_smp_send_call_function_ipi(const struct cpumask *mask)
 {
 	int cpu;
 
@@ -624,7 +591,7 @@ static void xen_smp_send_call_function_ipi(const struct cpumask *mask)
 	}
 }
 
-static void xen_smp_send_call_function_single_ipi(int cpu)
+void xen_smp_send_call_function_single_ipi(int cpu)
 {
 	__xen_send_IPI_mask(cpumask_of(cpu),
 			  XEN_CALL_FUNCTION_SINGLE_VECTOR);
@@ -762,21 +729,3 @@ void __init xen_smp_init(void)
 	smp_ops = xen_smp_ops;
 	xen_fill_possible_map();
 }
-
-static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
-{
-	native_smp_prepare_cpus(max_cpus);
-	WARN_ON(xen_smp_intr_init(0));
-
-	xen_init_lock_cpu(0);
-}
-
-void __init xen_hvm_smp_init(void)
-{
-	smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
-	smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
-	smp_ops.cpu_die = xen_hvm_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;
-	smp_ops.smp_prepare_boot_cpu = xen_hvm_smp_prepare_boot_cpu;
-}
diff --git a/arch/x86/xen/smp.h b/arch/x86/xen/smp.h
index a059adb..bf36e79 100644
--- a/arch/x86/xen/smp.h
+++ b/arch/x86/xen/smp.h
@@ -14,6 +14,9 @@ extern void xen_smp_intr_free(unsigned int cpu);
 extern int xen_smp_intr_init_pv(unsigned int cpu);
 extern void xen_smp_intr_free_pv(unsigned int cpu);
 
+extern void xen_smp_send_reschedule(int cpu);
+extern void xen_smp_send_call_function_ipi(const struct cpumask *mask);
+extern void xen_smp_send_call_function_single_ipi(int cpu);
 #else /* CONFIG_SMP */
 
 static inline int xen_smp_intr_init(unsigned int cpu)
diff --git a/arch/x86/xen/smp_hvm.c b/arch/x86/xen/smp_hvm.c
new file mode 100644
index 0000000..8bed434
--- /dev/null
+++ b/arch/x86/xen/smp_hvm.c
@@ -0,0 +1,58 @@
+#include <asm/smp.h>
+
+#include "xen-ops.h"
+#include "smp.h"
+
+
+static void __init xen_hvm_smp_prepare_boot_cpu(void)
+{
+	BUG_ON(smp_processor_id() != 0);
+	native_smp_prepare_boot_cpu();
+
+	/*
+	 * Setup vcpu_info for boot CPU.
+	 */
+	xen_vcpu_setup(0);
+
+	/*
+	 * The alternative logic (which patches the unlock/lock) runs before
+	 * the smp bootup up code is activated. Hence we need to set this up
+	 * the core kernel is being patched. Otherwise we will have only
+	 * modules patched but not core code.
+	 */
+	xen_init_spinlocks();
+}
+
+static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
+{
+	native_smp_prepare_cpus(max_cpus);
+	WARN_ON(xen_smp_intr_init(0));
+
+	xen_init_lock_cpu(0);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void xen_hvm_cpu_die(unsigned int cpu)
+{
+	if (common_cpu_die(cpu) == 0) {
+		xen_smp_intr_free(cpu);
+		xen_uninit_lock_cpu(cpu);
+		xen_teardown_timer(cpu);
+	}
+}
+#else
+static void xen_hvm_cpu_die(unsigned int cpu)
+{
+	BUG();
+}
+#endif
+
+void __init xen_hvm_smp_init(void)
+{
+	smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
+	smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
+	smp_ops.cpu_die = xen_hvm_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;
+	smp_ops.smp_prepare_boot_cpu = xen_hvm_smp_prepare_boot_cpu;
+}
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1598915 — Re: [PATCH v2 10/21] x86/xen: split off smp_hvm.c

FromJuergen Gross <jgross@suse.com>
Date2017-03-13 08:40 +0100
SubjectRe: [PATCH v2 10/21] x86/xen: split off smp_hvm.c
Message-ID<tksKd-5zs-1@gated-at.bofh.it>
In reply to#1591505
On 02/03/17 18:53, Vitaly Kuznetsov wrote:
> Move PVHVM related code to smp_hvm.c. Drop 'static' qualifier from
> xen_smp_send_reschedule(), xen_smp_send_call_function_ipi(),
> xen_smp_send_call_function_single_ipi(), these functions will be moved to
> common smp code when smp_pv.c is split.
> 
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>

One nit below, with this addressed:

Reviewed-by: Juergen Gross <jgross@suse.com>

> ---
>  arch/x86/xen/Kconfig   |  4 ++++
>  arch/x86/xen/Makefile  |  1 +
>  arch/x86/xen/smp.c     | 57 +++----------------------------------------------
>  arch/x86/xen/smp.h     |  3 +++
>  arch/x86/xen/smp_hvm.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 69 insertions(+), 54 deletions(-)
>  create mode 100644 arch/x86/xen/smp_hvm.c
> 

> diff --git a/arch/x86/xen/smp.h b/arch/x86/xen/smp.h
> index a059adb..bf36e79 100644
> --- a/arch/x86/xen/smp.h
> +++ b/arch/x86/xen/smp.h
> @@ -14,6 +14,9 @@ extern void xen_smp_intr_free(unsigned int cpu);
>  extern int xen_smp_intr_init_pv(unsigned int cpu);
>  extern void xen_smp_intr_free_pv(unsigned int cpu);
>  
> +extern void xen_smp_send_reschedule(int cpu);
> +extern void xen_smp_send_call_function_ipi(const struct cpumask *mask);
> +extern void xen_smp_send_call_function_single_ipi(int cpu);

Could you please drop the "extern" qualifier when adding new function
prototypes? I know this just follows the style of the file, but I'd
prefer not to add new instances.


Juergen

[toc] | [prev] | [next] | [standalone]


#1591511 — [PATCH v2 03/21] x86/xen: add CONFIG_XEN_PV to Kconfig

FromVitaly Kuznetsov <vkuznets@redhat.com>
Date2017-03-02 23:20 +0100
Subject[PATCH v2 03/21] x86/xen: add CONFIG_XEN_PV to Kconfig
Message-ID<tgHeO-eg-21@gated-at.bofh.it>
In reply to#1591381
All code to supprot Xen PV will get under this new option. For the
beginning, check for it in the common code.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 arch/x86/kernel/cpu/hypervisor.c |  4 +++-
 arch/x86/kernel/process_64.c     |  2 +-
 arch/x86/xen/Kconfig             | 23 ++++++++++++++++++-----
 3 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index a77f18d..ce6fcc3 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -28,8 +28,10 @@
 
 static const __initconst struct hypervisor_x86 * const hypervisors[] =
 {
-#ifdef CONFIG_XEN
+#ifdef CONFIG_XEN_PV
 	&x86_hyper_xen_pv,
+#endif
+#ifdef CONFIG_XEN_PVHVM
 	&x86_hyper_xen_hvm,
 #endif
 	&x86_hyper_vmware,
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index a61e141..5e8d129 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -438,7 +438,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 		     task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
 		__switch_to_xtra(prev_p, next_p, tss);
 
-#ifdef CONFIG_XEN
+#ifdef CONFIG_XEN_PV
 	/*
 	 * On Xen PV, IOPL bits in pt_regs->flags have no effect, and
 	 * current_pt_regs()->flags may not match the current task's
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index 76b6dbd..c387560 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -6,7 +6,6 @@ config XEN
 	bool "Xen guest support"
 	depends on PARAVIRT
 	select PARAVIRT_CLOCK
-	select XEN_HAVE_PVMMU
 	select XEN_HAVE_VPMU
 	depends on X86_64 || (X86_32 && X86_PAE)
 	depends on X86_LOCAL_APIC && X86_TSC
@@ -15,18 +14,32 @@ config XEN
 	  kernel to boot in a paravirtualized environment under the
 	  Xen hypervisor.
 
+config XEN_PV
+	bool "Xen PV guest support"
+	default y
+	depends on XEN
+	help
+	  Support running as a Xen PV guest.
+
 config XEN_DOM0
-	def_bool y
-	depends on XEN && PCI_XEN && SWIOTLB_XEN
+	bool "Xen PV Dom0 support"
+	default y
+	depends on XEN_PV && PCI_XEN && SWIOTLB_XEN
 	depends on X86_IO_APIC && ACPI && PCI
+	select XEN_HAVE_PVMMU
+	help
+	  Support running as a Xen PV Dom0 guest.
 
 config XEN_PVHVM
-	def_bool y
+	bool "Xen PVHVM guest support"
+	default y
 	depends on XEN && PCI && X86_LOCAL_APIC
+	help
+	  Support running as a Xen PVHVM guest.
 
 config XEN_512GB
 	bool "Limit Xen pv-domain memory to 512GB"
-	depends on XEN && X86_64
+	depends on XEN_PV && X86_64
 	default y
 	help
 	  Limit paravirtualized user domains to 512GB of RAM.
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1595253 — Re: [PATCH v2 03/21] x86/xen: add CONFIG_XEN_PV to Kconfig

FromJuergen Gross <jgross@suse.com>
Date2017-03-08 16:20 +0100
SubjectRe: [PATCH v2 03/21] x86/xen: add CONFIG_XEN_PV to Kconfig
Message-ID<tiLxE-8ng-11@gated-at.bofh.it>
In reply to#1591511
On 02/03/17 18:53, Vitaly Kuznetsov wrote:
> All code to supprot Xen PV will get under this new option. For the

s/supprot/support/

> beginning, check for it in the common code.
> 
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
> ---
>  arch/x86/kernel/cpu/hypervisor.c |  4 +++-
>  arch/x86/kernel/process_64.c     |  2 +-
>  arch/x86/xen/Kconfig             | 23 ++++++++++++++++++-----
>  3 files changed, 22 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
> index a77f18d..ce6fcc3 100644
> --- a/arch/x86/kernel/cpu/hypervisor.c
> +++ b/arch/x86/kernel/cpu/hypervisor.c
> @@ -28,8 +28,10 @@
>  
>  static const __initconst struct hypervisor_x86 * const hypervisors[] =
>  {
> -#ifdef CONFIG_XEN
> +#ifdef CONFIG_XEN_PV
>  	&x86_hyper_xen_pv,
> +#endif
> +#ifdef CONFIG_XEN_PVHVM
>  	&x86_hyper_xen_hvm,
>  #endif
>  	&x86_hyper_vmware,
> diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
> index a61e141..5e8d129 100644
> --- a/arch/x86/kernel/process_64.c
> +++ b/arch/x86/kernel/process_64.c
> @@ -438,7 +438,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
>  		     task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
>  		__switch_to_xtra(prev_p, next_p, tss);
>  
> -#ifdef CONFIG_XEN
> +#ifdef CONFIG_XEN_PV
>  	/*
>  	 * On Xen PV, IOPL bits in pt_regs->flags have no effect, and
>  	 * current_pt_regs()->flags may not match the current task's
> diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
> index 76b6dbd..c387560 100644
> --- a/arch/x86/xen/Kconfig
> +++ b/arch/x86/xen/Kconfig
> @@ -6,7 +6,6 @@ config XEN
>  	bool "Xen guest support"
>  	depends on PARAVIRT
>  	select PARAVIRT_CLOCK
> -	select XEN_HAVE_PVMMU
>  	select XEN_HAVE_VPMU
>  	depends on X86_64 || (X86_32 && X86_PAE)
>  	depends on X86_LOCAL_APIC && X86_TSC
> @@ -15,18 +14,32 @@ config XEN
>  	  kernel to boot in a paravirtualized environment under the
>  	  Xen hypervisor.
>  
> +config XEN_PV
> +	bool "Xen PV guest support"
> +	default y
> +	depends on XEN

select XEN_HAVE_PVMMU is missing ...

> +	help
> +	  Support running as a Xen PV guest.
> +
>  config XEN_DOM0
> -	def_bool y
> -	depends on XEN && PCI_XEN && SWIOTLB_XEN
> +	bool "Xen PV Dom0 support"
> +	default y
> +	depends on XEN_PV && PCI_XEN && SWIOTLB_XEN
>  	depends on X86_IO_APIC && ACPI && PCI
> +	select XEN_HAVE_PVMMU

... and can be dropped here


Juergen

[toc] | [prev] | [next] | [standalone]


#1592820 — Re: [Xen-devel] [PATCH v2 00/21] x86/xen: untangle PV and PVHVM guest support code

FromBoris Ostrovsky <boris.ostrovsky@oracle.com>
Date2017-03-05 19:10 +0100
SubjectRe: [Xen-devel] [PATCH v2 00/21] x86/xen: untangle PV and PVHVM guest support code
Message-ID<thILw-46d-5@gated-at.bofh.it>
In reply to#1591381

On 03/02/2017 12:53 PM, Vitaly Kuznetsov wrote:
> Changes since v1:
> - Patches 1,2 and 3 were split and reordered to avoid adding temporary
>    #ifdefs [Juergen Gross]
> - Juergen's R-b added to what is now patches 14 and 15 (patches 4 and 5
>    in v1). Due to re-ordering there are some tiny diffrences but I opted
>    for keeping the tag.
>
> Some patches are known to produce checkpatch.pl WARNINGS and a couple of
> ERRORs, I fixed a few (mostly in _hvm* code I split) and I refrained from
> fixing the rest to make it easier to review. I think that we may leave PV
> code as it is as sooner or later it will go away.
>
> Original description:
>
> I have a long-standing idea to separate PV and PVHVM code in kernel and
> introduce Kconfig options to make it possible to enable the required
> parts only breaking the current 'all or nothing' approach.

I tried applying this to mainline and it failed at some point. Is there 
a branch i can pull from?

Thanks.
-boris

[toc] | [prev] | [next] | [standalone]


#1599338 — Re: [Xen-devel] [PATCH v2 00/21] x86/xen: untangle PV and PVHVM guest support code

FromVitaly Kuznetsov <vkuznets@redhat.com>
Date2017-03-13 14:10 +0100
SubjectRe: [Xen-devel] [PATCH v2 00/21] x86/xen: untangle PV and PVHVM guest support code
Message-ID<tkxTA-XV-19@gated-at.bofh.it>
In reply to#1592820
Boris Ostrovsky <boris.ostrovsky@oracle.com> writes:

> On 03/02/2017 12:53 PM, Vitaly Kuznetsov wrote:
>> Changes since v1:
>> - Patches 1,2 and 3 were split and reordered to avoid adding temporary
>>    #ifdefs [Juergen Gross]
>> - Juergen's R-b added to what is now patches 14 and 15 (patches 4 and 5
>>    in v1). Due to re-ordering there are some tiny diffrences but I opted
>>    for keeping the tag.
>>
>> Some patches are known to produce checkpatch.pl WARNINGS and a couple of
>> ERRORs, I fixed a few (mostly in _hvm* code I split) and I refrained from
>> fixing the rest to make it easier to review. I think that we may leave PV
>> code as it is as sooner or later it will go away.
>>
>> Original description:
>>
>> I have a long-standing idea to separate PV and PVHVM code in kernel and
>> introduce Kconfig options to make it possible to enable the required
>> parts only breaking the current 'all or nothing' approach.
>
> I tried applying this to mainline and it failed at some point. Is
> there a branch i can pull from?
>

Sorry for the delayed response, I was on vacation last week.

Just pushed this series to github, you can pull it from

https://github.com/vittyvk/linux.git (xen_pv_hvm_split_v2 branch)

I'll be rebasing and addressing Juergen's and kbuild's comments this
week.

-- 
  Vitaly

[toc] | [prev] | [next] | [standalone]


#1595250 — Re: [PATCH v2 06/21] x86/xen: split off enlighten_pv.c

FromJuergen Gross <jgross@suse.com>
Date2017-03-08 16:20 +0100
SubjectRe: [PATCH v2 06/21] x86/xen: split off enlighten_pv.c
Message-ID<tiLxD-8ng-7@gated-at.bofh.it>
In reply to#1591381
On 02/03/17 18:53, Vitaly Kuznetsov wrote:
> Basically, enlighten.c is renamed to enlighten_pv.c and some code moved
> out to common enlighten.c.
> 
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>

Reviewed-by: Juergen Gross <jgross@suse.com>


Juergen

[toc] | [prev] | [next] | [standalone]


#1599142 — Re: [PATCH v2 13/21] x86/xen: split off mmu_pv.c

FromJuergen Gross <jgross@suse.com>
Date2017-03-13 10:40 +0100
SubjectRe: [PATCH v2 13/21] x86/xen: split off mmu_pv.c
Message-ID<tkuCm-6Ws-21@gated-at.bofh.it>
In reply to#1591381
On 02/03/17 18:53, Vitaly Kuznetsov wrote:
> Basically, mmu.c is renamed to mmu_pv.c and some code moved out to common
> mmu.c.
> 
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>

Reviewed-by: Juergen Gross <jgross@suse.com>


Juergen

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web