All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paul Mackerras <paulus@samba.org>
To: Alexander Graf <agraf@suse.de>,
	Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org
Subject: [PATCH 18/23] KVM: PPC: Book3S: Allow both PR and HV KVM to be selected
Date: Tue, 6 Aug 2013 14:25:39 +1000	[thread overview]
Message-ID: <20130806042539.GX19254@iris.ozlabs.ibm.com> (raw)
In-Reply-To: <20130806041259.GF19254@iris.ozlabs.ibm.com>

This makes the config options for PR and HV KVM independently selectable,
making it possible to compile a KVM module with both PR and HV code in
it.  This adds fields to struct kvm_arch and struct kvm_vcpu_arch to
indicate whether the guest is using PR or HV KVM, though at this stage
all guests in a given kernel instance are of the same type: HV KVM if
HV is enabled and the machine supports it (i.e. has suitable CPUs and
has a working hypervisor mode available), otherwise PR.

Since the code in book3s_64_vio_hv.c is called from real mode with HV
KVM, and therefore has to be built into the main kernel binary, this
makes it always built-in rather than part of the KVM module.  It gets
called from the KVM module by PR KVM, so this adds an EXPORT_SYMBOL_GPL().

If both HV and PR KVM are included, interrupts come in to the HV version
of the kvmppc_interrupt code, which then jumps to the PR handler,
renamed to kvmppc_interrupt_pr, if the guest is a PR guest.

Allowing both PR and HV in the same kernel required some changes to
kvm_dev_ioctl_check_extension(), since the values returned now can't
be selected with #ifdefs as much as previously.  For capabilities that
are only provided by HV KVM (for example, KVM_PPC_ALLOCATE_HTAB), we
return the HV value only if HV KVM is possible on the current machine.
For capabilities provided by PR KVM but not HV, we return the PR
value unless only HV KVM has been configured.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
 arch/powerpc/include/asm/kvm_book3s.h   | 67 +++++++++++++++++++++------------
 arch/powerpc/include/asm/kvm_host.h     |  6 +++
 arch/powerpc/include/asm/kvm_ppc.h      |  5 ++-
 arch/powerpc/kvm/Kconfig                | 15 +++++++-
 arch/powerpc/kvm/Makefile               | 11 +++---
 arch/powerpc/kvm/book3s.c               | 56 +++++++++++++++++++++++----
 arch/powerpc/kvm/book3s_64_vio_hv.c     |  1 +
 arch/powerpc/kvm/book3s_emulate.c       |  9 +++++
 arch/powerpc/kvm/book3s_exports.c       |  3 +-
 arch/powerpc/kvm/book3s_hv.c            |  3 ++
 arch/powerpc/kvm/book3s_hv_rmhandlers.S |  4 ++
 arch/powerpc/kvm/book3s_segment.S       |  7 ++++
 arch/powerpc/kvm/book3s_xics.c          |  2 +-
 arch/powerpc/kvm/powerpc.c              | 57 ++++++++++++++++++----------
 14 files changed, 184 insertions(+), 62 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index 476d862..f6af43f 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -272,6 +272,29 @@ static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
 #include <asm/kvm_book3s_64.h>
 #endif
 
+#if defined(CONFIG_KVM_BOOK3S_PR) && defined(CONFIG_KVM_BOOK3S_64_HV)
+static inline int kvmppc_vcpu_pr(struct kvm_vcpu *vcpu)
+{
+	return !vcpu->arch.use_hv;
+}
+
+static inline int kvmppc_vcpu_hv(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.use_hv;
+}
+
+#else
+static inline int kvmppc_vcpu_pr(struct kvm_vcpu *vcpu)
+{
+	return IS_ENABLED(CONFIG_KVM_BOOK3S_PR);
+}
+
+static inline int kvmppc_vcpu_hv(struct kvm_vcpu *vcpu)
+{
+	return IS_ENABLED(CONFIG_KVM_BOOK3S_64_HV);
+}
+#endif
+
 static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
 {
 	vcpu->arch.gpr[num] = val;
@@ -366,28 +389,38 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
 	return vcpu->arch.fault_dar;
 }
 
-#ifdef CONFIG_KVM_BOOK3S_PR
+#ifdef CONFIG_KVM_BOOK3S_HANDLER
 
 static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
 {
-	return to_book3s(vcpu)->hior;
+	if (kvmppc_vcpu_pr(vcpu))
+		return to_book3s(vcpu)->hior;
+	return 0;
 }
 
 static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
 			unsigned long pending_now, unsigned long old_pending)
 {
-	if (pending_now)
-		vcpu->arch.shared->int_pending = 1;
-	else if (old_pending)
-		vcpu->arch.shared->int_pending = 0;
+	if (kvmppc_vcpu_pr(vcpu)) {
+		if (pending_now)
+			vcpu->arch.shared->int_pending = 1;
+		else if (old_pending)
+			vcpu->arch.shared->int_pending = 0;
+	}
 }
 
 static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
 {
-	ulong crit_raw = vcpu->arch.shared->critical;
-	ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+	ulong crit_raw;
+	ulong crit_r1;
 	bool crit;
 
+	if (!kvmppc_vcpu_pr(vcpu))
+		return false;
+
+	crit_raw = vcpu->arch.shared->critical;
+	crit_r1 = kvmppc_get_gpr(vcpu, 1);
+
 	/* Truncate crit indicators in 32 bit mode */
 	if (!(vcpu->arch.shared->msr & MSR_SF)) {
 		crit_raw &= 0xffffffff;
@@ -401,23 +434,7 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
 
 	return crit;
 }
-#else /* CONFIG_KVM_BOOK3S_PR */
-
-static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
-{
-	return 0;
-}
-
-static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
-			unsigned long pending_now, unsigned long old_pending)
-{
-}
-
-static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
-{
-	return false;
-}
-#endif
+#endif /* CONFIG_KVM_BOOK3S_HANDLER */
 
 /* Magic register values loaded into r3 and r4 before the 'sc' assembly
  * instruction for the OSI hypercalls */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index c012db2..647e064 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -237,6 +237,7 @@ struct kvm_arch_memory_slot {
 
 struct kvm_arch {
 	unsigned int lpid;
+	int kvm_mode;
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	unsigned long hpt_virt;
 	struct revmap_entry *revmap;
@@ -278,6 +279,10 @@ struct kvm_arch {
 #endif
 };
 
+/* Values for kvm_mode */
+#define KVM_MODE_PR		1
+#define KVM_MODE_HV		2
+
 /*
  * Struct for a virtual core.
  * Note: entry_exit_count combines an entry count in the bottom 8 bits
@@ -409,6 +414,7 @@ struct kvm_vcpu_arch {
 	ulong host_stack;
 	u32 host_pid;
 #ifdef CONFIG_PPC_BOOK3S
+	bool use_hv;
 	struct kvmppc_slb slb[64];
 	int slb_max;		/* 1 + index of last valid entry in slb[] */
 	int slb_nr;		/* total number of entries in SLB */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index af7fe62..7408e2b 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -283,7 +283,8 @@ static inline void kvmppc_set_host_ipi(int cpu, u8 host_ipi)
 
 extern void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu);
 
-static inline int kvm_book3s_hv_possible(void)	{ return 1; }
+extern int kvm_book3s_hv_possible(void);
+extern int kvm_is_book3s_hv(struct kvm *kvm);
 
 #else
 static inline void __init kvm_cma_reserve(void)
@@ -306,6 +307,8 @@ static inline void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu)
 }
 
 static inline int kvm_book3s_hv_possible(void)		{ return 0; }
+static inline int kvm_is_book3s_hv(struct kvm *kvm)	{ return 0; }
+
 #endif
 
 #ifdef CONFIG_KVM_XICS
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index ffaef2c..2eeb2ae 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -89,9 +89,20 @@ config KVM_BOOK3S_64_HV
 	  If unsure, say N.
 
 config KVM_BOOK3S_64_PR
-	def_bool y
-	depends on KVM_BOOK3S_64 && !KVM_BOOK3S_64_HV
+	bool "KVM support without using hypervisor mode in host"
+	depends on KVM_BOOK3S_64
 	select KVM_BOOK3S_PR
+	---help---
+	  Support running guest kernels in virtual machines on processors
+	  without using hypervisor mode in the host, by running the
+	  guest in user mode (problem state) and emulating all
+	  privileged instructions and registers.
+
+	  This is not as fast as using hypervisor mode, but works on
+	  machines where hypervisor mode is not available or not usable,
+	  and can emulate processors that are different from the host
+	  processor, including emulating 32-bit processors on a 64-bit
+	  host.
 
 config KVM_BOOKE_HV
 	bool
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 6646c95..5d63d7f 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -53,32 +53,33 @@ kvm-e500mc-objs := \
 	e500_emulate.o
 kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs)
 
+kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) := \
+	book3s_64_vio_hv.o
+
 kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \
 	$(KVM)/coalesced_mmio.o \
 	fpu.o \
 	book3s_paired_singles.o \
 	book3s_pr.o \
 	book3s_pr_papr.o \
-	book3s_64_vio_hv.o \
 	book3s_emulate.o \
 	book3s_interrupts.o \
 	book3s_mmu_hpte.o \
 	book3s_64_mmu_host.o \
 	book3s_64_mmu.o \
 	book3s_32_mmu.o
-kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \
+kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_PR) += \
 	book3s_rmhandlers.o
 
-kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
+kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) += \
 	book3s_hv.o \
 	book3s_hv_interrupts.o \
 	book3s_64_mmu_hv.o
 kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \
 	book3s_hv_rm_xics.o
-kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
+kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) += \
 	book3s_hv_rmhandlers.o \
 	book3s_hv_rm_mmu.o \
-	book3s_64_vio_hv.o \
 	book3s_hv_ras.o \
 	book3s_hv_builtin.o \
 	book3s_hv_cma.o \
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 06abd84..f22b3af 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -61,19 +61,54 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ NULL }
 };
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+static int hv_ok;
+
+int kvm_book3s_hv_possible(void)
+{
+	return hv_ok;
+}
+
+int kvm_is_book3s_hv(struct kvm *kvm)
+{
+	return kvm->arch.kvm_mode == KVM_MODE_HV;
+}
+#endif
+
 #ifdef CONFIG_KVM_BOOK3S_PR
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+/* Do x if the VM mode is PR */
+#define DO_IF_PR(kvm, x)	if ((kvm)->arch.kvm_mode == KVM_MODE_PR) { x; }
+/* Do x if the VM mode is HV */
+#define DO_IF_HV(kvm, x)	if ((kvm)->arch.kvm_mode == KVM_MODE_HV) { x; }
+
+/* Do x for PR vcpus */
+#define VCPU_DO_PR(vcpu, x)	if (!(vcpu)->arch.use_hv) { x; }
+/* Do x for HV vcpus */
+#define VCPU_DO_HV(vcpu, x)	if ((vcpu)->arch.use_hv) { x; }
+
+#else
 #define DO_IF_PR(kvm, x)	x
 #define DO_IF_HV(kvm, x)	
 #define VCPU_DO_PR(vcpu, x)	x
 #define VCPU_DO_HV(vcpu, x)
 #endif
 
+#else
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 #define DO_IF_PR(kvm, x)
 #define DO_IF_HV(kvm, x)	x
 #define VCPU_DO_PR(vcpu, x)
 #define VCPU_DO_HV(vcpu, x)	x
+
+#else
+#define DO_IF_PR(kvm, x)
+#define DO_IF_HV(kvm, x)
+#define VCPU_DO_PR(vcpu, x)
+#define VCPU_DO_HV(vcpu, x)
 #endif
+#endif /* CONFIG_KVM_BOOK3S_PR */
+
 
 void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu)
 {
@@ -867,11 +902,16 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 	INIT_LIST_HEAD(&kvm->arch.rtas_tokens);
 #endif
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	if (hv_ok) {
+		err = kvmppc_core_init_vm_hv(kvm);
+		kvm->arch.kvm_mode = KVM_MODE_HV;
+		return err;
+	}
+#endif
 #ifdef CONFIG_KVM_BOOK3S_PR
 	err = kvmppc_core_init_vm_pr(kvm);
-#endif
-#ifdef CONFIG_KVM_BOOK3S_64_HV
-	err = kvmppc_core_init_vm_hv(kvm);
+	kvm->arch.kvm_mode = KVM_MODE_PR;
 #endif
 
 	return err;
@@ -890,7 +930,7 @@ void kvmppc_core_destroy_vm(struct kvm *kvm)
 
 int kvmppc_core_check_processor_compat(void)
 {
-#if defined(CONFIG_KVM_BOOK3S_64_HV)
+#if defined(CONFIG_KVM_BOOK3S_64_HV) && !defined(CONFIG_KVM_BOOK3S_PR)
 	if (!cpu_has_feature(CPU_FTR_HVMODE))
 		return -EIO;
 #endif
@@ -905,11 +945,13 @@ static int kvmppc_book3s_init(void)
 	if (r)
 		return r;
 
-#ifdef CONFIG_KVM_BOOK3S_PR
-	r = kvmppc_mmu_hpte_sysinit();
-#endif
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	r = kvmppc_mmu_hv_init();
+	if (!r)
+		hv_ok = 1;
+#endif
+#ifdef CONFIG_KVM_BOOK3S_PR
+	r = kvmppc_mmu_hpte_sysinit();
 #endif
 
 	return r;
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c
index 30c2f3b..2c25f54 100644
--- a/arch/powerpc/kvm/book3s_64_vio_hv.c
+++ b/arch/powerpc/kvm/book3s_64_vio_hv.c
@@ -74,3 +74,4 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
 	/* Didn't find the liobn, punt it to userspace */
 	return H_TOO_HARD;
 }
+EXPORT_SYMBOL_GPL(kvmppc_h_put_tce);
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 34044b1..fe958e1 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -95,6 +95,9 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	int ra = get_ra(inst);
 	int rb = get_rb(inst);
 
+	if (kvmppc_vcpu_hv(vcpu))
+		return EMULATE_FAIL;
+
 	switch (get_op(inst)) {
 	case 19:
 		switch (get_xop(inst)) {
@@ -349,6 +352,9 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 {
 	int emulated = EMULATE_DONE;
 
+	if (kvmppc_vcpu_hv(vcpu))
+		return EMULATE_FAIL;
+
 	switch (sprn) {
 	case SPRN_SDR1:
 		if (!spr_allowed(vcpu, PRIV_HYPER))
@@ -472,6 +478,9 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
 {
 	int emulated = EMULATE_DONE;
 
+	if (kvmppc_vcpu_hv(vcpu))
+		return EMULATE_FAIL;
+
 	switch (sprn) {
 	case SPRN_IBAT0U ... SPRN_IBAT3L:
 	case SPRN_IBAT4U ... SPRN_IBAT7L:
diff --git a/arch/powerpc/kvm/book3s_exports.c b/arch/powerpc/kvm/book3s_exports.c
index 7057a02..0730d98 100644
--- a/arch/powerpc/kvm/book3s_exports.c
+++ b/arch/powerpc/kvm/book3s_exports.c
@@ -22,7 +22,8 @@
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 EXPORT_SYMBOL_GPL(kvmppc_hv_entry_trampoline);
-#else
+#endif
+#ifdef CONFIG_KVM_BOOK3S_PR
 EXPORT_SYMBOL_GPL(kvmppc_entry_trampoline);
 EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu);
 #ifdef CONFIG_ALTIVEC
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index c524d6b..956318b 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -959,6 +959,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, unsigned int id)
 	vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
 	if (!vcpu)
 		goto out;
+	vcpu->arch.use_hv = true;
 
 	err = kvm_vcpu_init(vcpu, kvm, id);
 	if (err)
@@ -1921,6 +1922,7 @@ void kvmppc_core_destroy_vm_hv(struct kvm *kvm)
 	kvmppc_free_hpt(kvm);
 }
 
+#ifndef CONFIG_KVM_BOOK3S_PR
 /* We don't need to emulate any privileged instructions or dcbz */
 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                            unsigned int inst, int *advance)
@@ -1937,3 +1939,4 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
 {
 	return EMULATE_FAIL;
 }
+#endif
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index af9ba85..467b24d 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -569,6 +569,10 @@ kvmppc_interrupt:
 	lbz	r9, HSTATE_IN_GUEST(r13)
 	cmpwi	r9, KVM_GUEST_MODE_HOST_HV
 	beq	kvmppc_bad_host_intr
+#ifdef CONFIG_KVM_BOOK3S_PR
+	cmpwi	r9, KVM_GUEST_MODE_GUEST
+	beq	kvmppc_interrupt_pr
+#endif
 	/* We're now back in the host but in guest MMU context */
 	li	r9, KVM_GUEST_MODE_HOST_HV
 	stb	r9, HSTATE_IN_GUEST(r13)
diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S
index 1abe478..13cfc59 100644
--- a/arch/powerpc/kvm/book3s_segment.S
+++ b/arch/powerpc/kvm/book3s_segment.S
@@ -161,8 +161,15 @@ kvmppc_handler_trampoline_enter_end:
 .global kvmppc_handler_trampoline_exit
 kvmppc_handler_trampoline_exit:
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+.global kvmppc_interrupt_pr
+kvmppc_interrupt_pr:
+	ld	r9, HSTATE_SCRATCH2(r13)
+
+#else
 .global kvmppc_interrupt
 kvmppc_interrupt:
+#endif
 
 	/* Register usage at this point:
 	 *
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index a3a5cb8..d28d2f7 100644
--- a/arch/powerpc/kvm/book3s_xics.c
+++ b/arch/powerpc/kvm/book3s_xics.c
@@ -818,7 +818,7 @@ int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 req)
 	}
 
 	/* Check for real mode returning too hard */
-	if (xics->real_mode)
+	if (xics->real_mode && kvmppc_vcpu_hv(vcpu))
 		return kvmppc_xics_rm_complete(vcpu, req);
 
 	switch (req) {
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 4e05f8c..49bbc9e 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -50,7 +50,6 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
-#ifndef CONFIG_KVM_BOOK3S_64_HV
 /*
  * Common checks before entering the guest world.  Call with interrupts
  * disabled.
@@ -125,7 +124,6 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
 
 	return r;
 }
-#endif /* CONFIG_KVM_BOOK3S_64_HV */
 
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 {
@@ -193,8 +191,8 @@ int kvmppc_sanity_check(struct kvm_vcpu *vcpu)
 		goto out;
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
-	/* HV KVM can only do PAPR mode for now */
-	if (!vcpu->arch.papr_enabled)
+	/* HV KVM can only do PAPR mode */
+	if (!vcpu->arch.papr_enabled && kvmppc_vcpu_hv(vcpu))
 		goto out;
 #endif
 
@@ -298,6 +296,12 @@ void kvm_arch_sync_events(struct kvm *kvm)
 {
 }
 
+#if defined(CONFIG_KVM_BOOK3S_64_HV) && !defined(CONFIG_KVM_BOOK3S_PR)
+#define KVM_IS_BOOK3S_HV_ONLY	1
+#else
+#define KVM_IS_BOOK3S_HV_ONLY	0
+#endif
+
 int kvm_dev_ioctl_check_extension(long ext)
 {
 	int r;
@@ -320,22 +324,24 @@ int kvm_dev_ioctl_check_extension(long ext)
 	case KVM_CAP_DEVICE_CTRL:
 		r = 1;
 		break;
-#ifndef CONFIG_KVM_BOOK3S_64_HV
 	case KVM_CAP_PPC_PAIRED_SINGLES:
 	case KVM_CAP_PPC_OSI:
 	case KVM_CAP_PPC_GET_PVINFO:
 #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
 	case KVM_CAP_SW_TLB:
 #endif
-#ifdef CONFIG_KVM_MPIC
-	case KVM_CAP_IRQ_MPIC:
-#endif
-		r = 1;
+		r = !KVM_IS_BOOK3S_HV_ONLY;
 		break;
+#ifdef CONFIG_KVM_MMIO
 	case KVM_CAP_COALESCED_MMIO:
 		r = KVM_COALESCED_MMIO_PAGE_OFFSET;
 		break;
 #endif
+#ifdef CONFIG_KVM_MPIC
+	case KVM_CAP_IRQ_MPIC:
+		r = 1;
+		break;
+#endif
 #ifdef CONFIG_PPC_BOOK3S_64
 	case KVM_CAP_SPAPR_TCE:
 	case KVM_CAP_PPC_ALLOC_HTAB:
@@ -348,30 +354,32 @@ int kvm_dev_ioctl_check_extension(long ext)
 #endif /* CONFIG_PPC_BOOK3S_64 */
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	case KVM_CAP_PPC_SMT:
-		r = threads_per_core;
+		r = 0;
+		if (kvm_book3s_hv_possible())
+			r = threads_per_core;
 		break;
 	case KVM_CAP_PPC_RMA:
-		r = 1;
-		/* PPC970 requires an RMA */
-		if (cpu_has_feature(CPU_FTR_ARCH_201))
+		r = kvm_book3s_hv_possible();
+		/* PPC970 requires an RMA for HV KVM */
+		if (r && cpu_has_feature(CPU_FTR_ARCH_201))
 			r = 2;
 		break;
 #endif
 	case KVM_CAP_SYNC_MMU:
 #ifdef CONFIG_KVM_BOOK3S_64_HV
-		r = cpu_has_feature(CPU_FTR_ARCH_206) ? 1 : 0;
+		r = !KVM_IS_BOOK3S_HV_ONLY ||
+			cpu_has_feature(CPU_FTR_ARCH_206);
 #elif defined(KVM_ARCH_WANT_MMU_NOTIFIER)
 		r = 1;
 #else
 		r = 0;
-		break;
 #endif
+		break;
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	case KVM_CAP_PPC_HTAB_FD:
-		r = 1;
+		r = kvm_book3s_hv_possible();
 		break;
 #endif
-		break;
 	case KVM_CAP_NR_VCPUS:
 		/*
 		 * Recommending a number of CPUs is somewhat arbitrary; we
@@ -379,10 +387,10 @@ int kvm_dev_ioctl_check_extension(long ext)
 		 * will have secondary threads "offline"), and for other KVM
 		 * implementations just count online CPUs.
 		 */
-#ifdef CONFIG_KVM_BOOK3S_64_HV
-		r = num_present_cpus();
-#else
 		r = num_online_cpus();
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+		if (kvm_book3s_hv_possible())
+			r = num_present_cpus();
 #endif
 		break;
 	case KVM_CAP_MAX_VCPUS:
@@ -1027,6 +1035,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		struct kvm_allocate_rma rma;
 		struct kvm *kvm = filp->private_data;
 
+		r = -ENOTTY;
+		if (!kvm_is_book3s_hv(kvm))
+			break;
 		r = kvm_vm_ioctl_allocate_rma(kvm, &rma);
 		if (r >= 0 && copy_to_user(argp, &rma, sizeof(rma)))
 			r = -EFAULT;
@@ -1036,6 +1047,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
 	case KVM_PPC_ALLOCATE_HTAB: {
 		u32 htab_order;
 
+		r = -ENOTTY;
+		if (!kvm_is_book3s_hv(kvm))
+			break;
 		r = -EFAULT;
 		if (get_user(htab_order, (u32 __user *)argp))
 			break;
@@ -1052,6 +1066,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
 	case KVM_PPC_GET_HTAB_FD: {
 		struct kvm_get_htab_fd ghf;
 
+		r = -ENOTTY;
+		if (!kvm_is_book3s_hv(kvm))
+			break;
 		r = -EFAULT;
 		if (copy_from_user(&ghf, argp, sizeof(ghf)))
 			break;
-- 
1.8.3.1


WARNING: multiple messages have this Message-ID (diff)
From: Paul Mackerras <paulus@samba.org>
To: Alexander Graf <agraf@suse.de>,
	Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org
Subject: [PATCH 18/23] KVM: PPC: Book3S: Allow both PR and HV KVM to be selected
Date: Tue, 06 Aug 2013 04:25:39 +0000	[thread overview]
Message-ID: <20130806042539.GX19254@iris.ozlabs.ibm.com> (raw)
In-Reply-To: <20130806041259.GF19254@iris.ozlabs.ibm.com>

This makes the config options for PR and HV KVM independently selectable,
making it possible to compile a KVM module with both PR and HV code in
it.  This adds fields to struct kvm_arch and struct kvm_vcpu_arch to
indicate whether the guest is using PR or HV KVM, though at this stage
all guests in a given kernel instance are of the same type: HV KVM if
HV is enabled and the machine supports it (i.e. has suitable CPUs and
has a working hypervisor mode available), otherwise PR.

Since the code in book3s_64_vio_hv.c is called from real mode with HV
KVM, and therefore has to be built into the main kernel binary, this
makes it always built-in rather than part of the KVM module.  It gets
called from the KVM module by PR KVM, so this adds an EXPORT_SYMBOL_GPL().

If both HV and PR KVM are included, interrupts come in to the HV version
of the kvmppc_interrupt code, which then jumps to the PR handler,
renamed to kvmppc_interrupt_pr, if the guest is a PR guest.

Allowing both PR and HV in the same kernel required some changes to
kvm_dev_ioctl_check_extension(), since the values returned now can't
be selected with #ifdefs as much as previously.  For capabilities that
are only provided by HV KVM (for example, KVM_PPC_ALLOCATE_HTAB), we
return the HV value only if HV KVM is possible on the current machine.
For capabilities provided by PR KVM but not HV, we return the PR
value unless only HV KVM has been configured.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
 arch/powerpc/include/asm/kvm_book3s.h   | 67 +++++++++++++++++++++------------
 arch/powerpc/include/asm/kvm_host.h     |  6 +++
 arch/powerpc/include/asm/kvm_ppc.h      |  5 ++-
 arch/powerpc/kvm/Kconfig                | 15 +++++++-
 arch/powerpc/kvm/Makefile               | 11 +++---
 arch/powerpc/kvm/book3s.c               | 56 +++++++++++++++++++++++----
 arch/powerpc/kvm/book3s_64_vio_hv.c     |  1 +
 arch/powerpc/kvm/book3s_emulate.c       |  9 +++++
 arch/powerpc/kvm/book3s_exports.c       |  3 +-
 arch/powerpc/kvm/book3s_hv.c            |  3 ++
 arch/powerpc/kvm/book3s_hv_rmhandlers.S |  4 ++
 arch/powerpc/kvm/book3s_segment.S       |  7 ++++
 arch/powerpc/kvm/book3s_xics.c          |  2 +-
 arch/powerpc/kvm/powerpc.c              | 57 ++++++++++++++++++----------
 14 files changed, 184 insertions(+), 62 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index 476d862..f6af43f 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -272,6 +272,29 @@ static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
 #include <asm/kvm_book3s_64.h>
 #endif
 
+#if defined(CONFIG_KVM_BOOK3S_PR) && defined(CONFIG_KVM_BOOK3S_64_HV)
+static inline int kvmppc_vcpu_pr(struct kvm_vcpu *vcpu)
+{
+	return !vcpu->arch.use_hv;
+}
+
+static inline int kvmppc_vcpu_hv(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.use_hv;
+}
+
+#else
+static inline int kvmppc_vcpu_pr(struct kvm_vcpu *vcpu)
+{
+	return IS_ENABLED(CONFIG_KVM_BOOK3S_PR);
+}
+
+static inline int kvmppc_vcpu_hv(struct kvm_vcpu *vcpu)
+{
+	return IS_ENABLED(CONFIG_KVM_BOOK3S_64_HV);
+}
+#endif
+
 static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
 {
 	vcpu->arch.gpr[num] = val;
@@ -366,28 +389,38 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
 	return vcpu->arch.fault_dar;
 }
 
-#ifdef CONFIG_KVM_BOOK3S_PR
+#ifdef CONFIG_KVM_BOOK3S_HANDLER
 
 static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
 {
-	return to_book3s(vcpu)->hior;
+	if (kvmppc_vcpu_pr(vcpu))
+		return to_book3s(vcpu)->hior;
+	return 0;
 }
 
 static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
 			unsigned long pending_now, unsigned long old_pending)
 {
-	if (pending_now)
-		vcpu->arch.shared->int_pending = 1;
-	else if (old_pending)
-		vcpu->arch.shared->int_pending = 0;
+	if (kvmppc_vcpu_pr(vcpu)) {
+		if (pending_now)
+			vcpu->arch.shared->int_pending = 1;
+		else if (old_pending)
+			vcpu->arch.shared->int_pending = 0;
+	}
 }
 
 static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
 {
-	ulong crit_raw = vcpu->arch.shared->critical;
-	ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+	ulong crit_raw;
+	ulong crit_r1;
 	bool crit;
 
+	if (!kvmppc_vcpu_pr(vcpu))
+		return false;
+
+	crit_raw = vcpu->arch.shared->critical;
+	crit_r1 = kvmppc_get_gpr(vcpu, 1);
+
 	/* Truncate crit indicators in 32 bit mode */
 	if (!(vcpu->arch.shared->msr & MSR_SF)) {
 		crit_raw &= 0xffffffff;
@@ -401,23 +434,7 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
 
 	return crit;
 }
-#else /* CONFIG_KVM_BOOK3S_PR */
-
-static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
-{
-	return 0;
-}
-
-static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
-			unsigned long pending_now, unsigned long old_pending)
-{
-}
-
-static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
-{
-	return false;
-}
-#endif
+#endif /* CONFIG_KVM_BOOK3S_HANDLER */
 
 /* Magic register values loaded into r3 and r4 before the 'sc' assembly
  * instruction for the OSI hypercalls */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index c012db2..647e064 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -237,6 +237,7 @@ struct kvm_arch_memory_slot {
 
 struct kvm_arch {
 	unsigned int lpid;
+	int kvm_mode;
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	unsigned long hpt_virt;
 	struct revmap_entry *revmap;
@@ -278,6 +279,10 @@ struct kvm_arch {
 #endif
 };
 
+/* Values for kvm_mode */
+#define KVM_MODE_PR		1
+#define KVM_MODE_HV		2
+
 /*
  * Struct for a virtual core.
  * Note: entry_exit_count combines an entry count in the bottom 8 bits
@@ -409,6 +414,7 @@ struct kvm_vcpu_arch {
 	ulong host_stack;
 	u32 host_pid;
 #ifdef CONFIG_PPC_BOOK3S
+	bool use_hv;
 	struct kvmppc_slb slb[64];
 	int slb_max;		/* 1 + index of last valid entry in slb[] */
 	int slb_nr;		/* total number of entries in SLB */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index af7fe62..7408e2b 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -283,7 +283,8 @@ static inline void kvmppc_set_host_ipi(int cpu, u8 host_ipi)
 
 extern void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu);
 
-static inline int kvm_book3s_hv_possible(void)	{ return 1; }
+extern int kvm_book3s_hv_possible(void);
+extern int kvm_is_book3s_hv(struct kvm *kvm);
 
 #else
 static inline void __init kvm_cma_reserve(void)
@@ -306,6 +307,8 @@ static inline void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu)
 }
 
 static inline int kvm_book3s_hv_possible(void)		{ return 0; }
+static inline int kvm_is_book3s_hv(struct kvm *kvm)	{ return 0; }
+
 #endif
 
 #ifdef CONFIG_KVM_XICS
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index ffaef2c..2eeb2ae 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -89,9 +89,20 @@ config KVM_BOOK3S_64_HV
 	  If unsure, say N.
 
 config KVM_BOOK3S_64_PR
-	def_bool y
-	depends on KVM_BOOK3S_64 && !KVM_BOOK3S_64_HV
+	bool "KVM support without using hypervisor mode in host"
+	depends on KVM_BOOK3S_64
 	select KVM_BOOK3S_PR
+	---help---
+	  Support running guest kernels in virtual machines on processors
+	  without using hypervisor mode in the host, by running the
+	  guest in user mode (problem state) and emulating all
+	  privileged instructions and registers.
+
+	  This is not as fast as using hypervisor mode, but works on
+	  machines where hypervisor mode is not available or not usable,
+	  and can emulate processors that are different from the host
+	  processor, including emulating 32-bit processors on a 64-bit
+	  host.
 
 config KVM_BOOKE_HV
 	bool
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 6646c95..5d63d7f 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -53,32 +53,33 @@ kvm-e500mc-objs := \
 	e500_emulate.o
 kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs)
 
+kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) := \
+	book3s_64_vio_hv.o
+
 kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \
 	$(KVM)/coalesced_mmio.o \
 	fpu.o \
 	book3s_paired_singles.o \
 	book3s_pr.o \
 	book3s_pr_papr.o \
-	book3s_64_vio_hv.o \
 	book3s_emulate.o \
 	book3s_interrupts.o \
 	book3s_mmu_hpte.o \
 	book3s_64_mmu_host.o \
 	book3s_64_mmu.o \
 	book3s_32_mmu.o
-kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \
+kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_PR) += \
 	book3s_rmhandlers.o
 
-kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
+kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) += \
 	book3s_hv.o \
 	book3s_hv_interrupts.o \
 	book3s_64_mmu_hv.o
 kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \
 	book3s_hv_rm_xics.o
-kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
+kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) += \
 	book3s_hv_rmhandlers.o \
 	book3s_hv_rm_mmu.o \
-	book3s_64_vio_hv.o \
 	book3s_hv_ras.o \
 	book3s_hv_builtin.o \
 	book3s_hv_cma.o \
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 06abd84..f22b3af 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -61,19 +61,54 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ NULL }
 };
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+static int hv_ok;
+
+int kvm_book3s_hv_possible(void)
+{
+	return hv_ok;
+}
+
+int kvm_is_book3s_hv(struct kvm *kvm)
+{
+	return kvm->arch.kvm_mode = KVM_MODE_HV;
+}
+#endif
+
 #ifdef CONFIG_KVM_BOOK3S_PR
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+/* Do x if the VM mode is PR */
+#define DO_IF_PR(kvm, x)	if ((kvm)->arch.kvm_mode = KVM_MODE_PR) { x; }
+/* Do x if the VM mode is HV */
+#define DO_IF_HV(kvm, x)	if ((kvm)->arch.kvm_mode = KVM_MODE_HV) { x; }
+
+/* Do x for PR vcpus */
+#define VCPU_DO_PR(vcpu, x)	if (!(vcpu)->arch.use_hv) { x; }
+/* Do x for HV vcpus */
+#define VCPU_DO_HV(vcpu, x)	if ((vcpu)->arch.use_hv) { x; }
+
+#else
 #define DO_IF_PR(kvm, x)	x
 #define DO_IF_HV(kvm, x)	
 #define VCPU_DO_PR(vcpu, x)	x
 #define VCPU_DO_HV(vcpu, x)
 #endif
 
+#else
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 #define DO_IF_PR(kvm, x)
 #define DO_IF_HV(kvm, x)	x
 #define VCPU_DO_PR(vcpu, x)
 #define VCPU_DO_HV(vcpu, x)	x
+
+#else
+#define DO_IF_PR(kvm, x)
+#define DO_IF_HV(kvm, x)
+#define VCPU_DO_PR(vcpu, x)
+#define VCPU_DO_HV(vcpu, x)
 #endif
+#endif /* CONFIG_KVM_BOOK3S_PR */
+
 
 void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu)
 {
@@ -867,11 +902,16 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 	INIT_LIST_HEAD(&kvm->arch.rtas_tokens);
 #endif
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	if (hv_ok) {
+		err = kvmppc_core_init_vm_hv(kvm);
+		kvm->arch.kvm_mode = KVM_MODE_HV;
+		return err;
+	}
+#endif
 #ifdef CONFIG_KVM_BOOK3S_PR
 	err = kvmppc_core_init_vm_pr(kvm);
-#endif
-#ifdef CONFIG_KVM_BOOK3S_64_HV
-	err = kvmppc_core_init_vm_hv(kvm);
+	kvm->arch.kvm_mode = KVM_MODE_PR;
 #endif
 
 	return err;
@@ -890,7 +930,7 @@ void kvmppc_core_destroy_vm(struct kvm *kvm)
 
 int kvmppc_core_check_processor_compat(void)
 {
-#if defined(CONFIG_KVM_BOOK3S_64_HV)
+#if defined(CONFIG_KVM_BOOK3S_64_HV) && !defined(CONFIG_KVM_BOOK3S_PR)
 	if (!cpu_has_feature(CPU_FTR_HVMODE))
 		return -EIO;
 #endif
@@ -905,11 +945,13 @@ static int kvmppc_book3s_init(void)
 	if (r)
 		return r;
 
-#ifdef CONFIG_KVM_BOOK3S_PR
-	r = kvmppc_mmu_hpte_sysinit();
-#endif
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	r = kvmppc_mmu_hv_init();
+	if (!r)
+		hv_ok = 1;
+#endif
+#ifdef CONFIG_KVM_BOOK3S_PR
+	r = kvmppc_mmu_hpte_sysinit();
 #endif
 
 	return r;
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c
index 30c2f3b..2c25f54 100644
--- a/arch/powerpc/kvm/book3s_64_vio_hv.c
+++ b/arch/powerpc/kvm/book3s_64_vio_hv.c
@@ -74,3 +74,4 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
 	/* Didn't find the liobn, punt it to userspace */
 	return H_TOO_HARD;
 }
+EXPORT_SYMBOL_GPL(kvmppc_h_put_tce);
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 34044b1..fe958e1 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -95,6 +95,9 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	int ra = get_ra(inst);
 	int rb = get_rb(inst);
 
+	if (kvmppc_vcpu_hv(vcpu))
+		return EMULATE_FAIL;
+
 	switch (get_op(inst)) {
 	case 19:
 		switch (get_xop(inst)) {
@@ -349,6 +352,9 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 {
 	int emulated = EMULATE_DONE;
 
+	if (kvmppc_vcpu_hv(vcpu))
+		return EMULATE_FAIL;
+
 	switch (sprn) {
 	case SPRN_SDR1:
 		if (!spr_allowed(vcpu, PRIV_HYPER))
@@ -472,6 +478,9 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
 {
 	int emulated = EMULATE_DONE;
 
+	if (kvmppc_vcpu_hv(vcpu))
+		return EMULATE_FAIL;
+
 	switch (sprn) {
 	case SPRN_IBAT0U ... SPRN_IBAT3L:
 	case SPRN_IBAT4U ... SPRN_IBAT7L:
diff --git a/arch/powerpc/kvm/book3s_exports.c b/arch/powerpc/kvm/book3s_exports.c
index 7057a02..0730d98 100644
--- a/arch/powerpc/kvm/book3s_exports.c
+++ b/arch/powerpc/kvm/book3s_exports.c
@@ -22,7 +22,8 @@
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 EXPORT_SYMBOL_GPL(kvmppc_hv_entry_trampoline);
-#else
+#endif
+#ifdef CONFIG_KVM_BOOK3S_PR
 EXPORT_SYMBOL_GPL(kvmppc_entry_trampoline);
 EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu);
 #ifdef CONFIG_ALTIVEC
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index c524d6b..956318b 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -959,6 +959,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, unsigned int id)
 	vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
 	if (!vcpu)
 		goto out;
+	vcpu->arch.use_hv = true;
 
 	err = kvm_vcpu_init(vcpu, kvm, id);
 	if (err)
@@ -1921,6 +1922,7 @@ void kvmppc_core_destroy_vm_hv(struct kvm *kvm)
 	kvmppc_free_hpt(kvm);
 }
 
+#ifndef CONFIG_KVM_BOOK3S_PR
 /* We don't need to emulate any privileged instructions or dcbz */
 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                            unsigned int inst, int *advance)
@@ -1937,3 +1939,4 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
 {
 	return EMULATE_FAIL;
 }
+#endif
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index af9ba85..467b24d 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -569,6 +569,10 @@ kvmppc_interrupt:
 	lbz	r9, HSTATE_IN_GUEST(r13)
 	cmpwi	r9, KVM_GUEST_MODE_HOST_HV
 	beq	kvmppc_bad_host_intr
+#ifdef CONFIG_KVM_BOOK3S_PR
+	cmpwi	r9, KVM_GUEST_MODE_GUEST
+	beq	kvmppc_interrupt_pr
+#endif
 	/* We're now back in the host but in guest MMU context */
 	li	r9, KVM_GUEST_MODE_HOST_HV
 	stb	r9, HSTATE_IN_GUEST(r13)
diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S
index 1abe478..13cfc59 100644
--- a/arch/powerpc/kvm/book3s_segment.S
+++ b/arch/powerpc/kvm/book3s_segment.S
@@ -161,8 +161,15 @@ kvmppc_handler_trampoline_enter_end:
 .global kvmppc_handler_trampoline_exit
 kvmppc_handler_trampoline_exit:
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+.global kvmppc_interrupt_pr
+kvmppc_interrupt_pr:
+	ld	r9, HSTATE_SCRATCH2(r13)
+
+#else
 .global kvmppc_interrupt
 kvmppc_interrupt:
+#endif
 
 	/* Register usage at this point:
 	 *
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index a3a5cb8..d28d2f7 100644
--- a/arch/powerpc/kvm/book3s_xics.c
+++ b/arch/powerpc/kvm/book3s_xics.c
@@ -818,7 +818,7 @@ int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 req)
 	}
 
 	/* Check for real mode returning too hard */
-	if (xics->real_mode)
+	if (xics->real_mode && kvmppc_vcpu_hv(vcpu))
 		return kvmppc_xics_rm_complete(vcpu, req);
 
 	switch (req) {
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 4e05f8c..49bbc9e 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -50,7 +50,6 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
-#ifndef CONFIG_KVM_BOOK3S_64_HV
 /*
  * Common checks before entering the guest world.  Call with interrupts
  * disabled.
@@ -125,7 +124,6 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
 
 	return r;
 }
-#endif /* CONFIG_KVM_BOOK3S_64_HV */
 
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 {
@@ -193,8 +191,8 @@ int kvmppc_sanity_check(struct kvm_vcpu *vcpu)
 		goto out;
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
-	/* HV KVM can only do PAPR mode for now */
-	if (!vcpu->arch.papr_enabled)
+	/* HV KVM can only do PAPR mode */
+	if (!vcpu->arch.papr_enabled && kvmppc_vcpu_hv(vcpu))
 		goto out;
 #endif
 
@@ -298,6 +296,12 @@ void kvm_arch_sync_events(struct kvm *kvm)
 {
 }
 
+#if defined(CONFIG_KVM_BOOK3S_64_HV) && !defined(CONFIG_KVM_BOOK3S_PR)
+#define KVM_IS_BOOK3S_HV_ONLY	1
+#else
+#define KVM_IS_BOOK3S_HV_ONLY	0
+#endif
+
 int kvm_dev_ioctl_check_extension(long ext)
 {
 	int r;
@@ -320,22 +324,24 @@ int kvm_dev_ioctl_check_extension(long ext)
 	case KVM_CAP_DEVICE_CTRL:
 		r = 1;
 		break;
-#ifndef CONFIG_KVM_BOOK3S_64_HV
 	case KVM_CAP_PPC_PAIRED_SINGLES:
 	case KVM_CAP_PPC_OSI:
 	case KVM_CAP_PPC_GET_PVINFO:
 #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
 	case KVM_CAP_SW_TLB:
 #endif
-#ifdef CONFIG_KVM_MPIC
-	case KVM_CAP_IRQ_MPIC:
-#endif
-		r = 1;
+		r = !KVM_IS_BOOK3S_HV_ONLY;
 		break;
+#ifdef CONFIG_KVM_MMIO
 	case KVM_CAP_COALESCED_MMIO:
 		r = KVM_COALESCED_MMIO_PAGE_OFFSET;
 		break;
 #endif
+#ifdef CONFIG_KVM_MPIC
+	case KVM_CAP_IRQ_MPIC:
+		r = 1;
+		break;
+#endif
 #ifdef CONFIG_PPC_BOOK3S_64
 	case KVM_CAP_SPAPR_TCE:
 	case KVM_CAP_PPC_ALLOC_HTAB:
@@ -348,30 +354,32 @@ int kvm_dev_ioctl_check_extension(long ext)
 #endif /* CONFIG_PPC_BOOK3S_64 */
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	case KVM_CAP_PPC_SMT:
-		r = threads_per_core;
+		r = 0;
+		if (kvm_book3s_hv_possible())
+			r = threads_per_core;
 		break;
 	case KVM_CAP_PPC_RMA:
-		r = 1;
-		/* PPC970 requires an RMA */
-		if (cpu_has_feature(CPU_FTR_ARCH_201))
+		r = kvm_book3s_hv_possible();
+		/* PPC970 requires an RMA for HV KVM */
+		if (r && cpu_has_feature(CPU_FTR_ARCH_201))
 			r = 2;
 		break;
 #endif
 	case KVM_CAP_SYNC_MMU:
 #ifdef CONFIG_KVM_BOOK3S_64_HV
-		r = cpu_has_feature(CPU_FTR_ARCH_206) ? 1 : 0;
+		r = !KVM_IS_BOOK3S_HV_ONLY ||
+			cpu_has_feature(CPU_FTR_ARCH_206);
 #elif defined(KVM_ARCH_WANT_MMU_NOTIFIER)
 		r = 1;
 #else
 		r = 0;
-		break;
 #endif
+		break;
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	case KVM_CAP_PPC_HTAB_FD:
-		r = 1;
+		r = kvm_book3s_hv_possible();
 		break;
 #endif
-		break;
 	case KVM_CAP_NR_VCPUS:
 		/*
 		 * Recommending a number of CPUs is somewhat arbitrary; we
@@ -379,10 +387,10 @@ int kvm_dev_ioctl_check_extension(long ext)
 		 * will have secondary threads "offline"), and for other KVM
 		 * implementations just count online CPUs.
 		 */
-#ifdef CONFIG_KVM_BOOK3S_64_HV
-		r = num_present_cpus();
-#else
 		r = num_online_cpus();
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+		if (kvm_book3s_hv_possible())
+			r = num_present_cpus();
 #endif
 		break;
 	case KVM_CAP_MAX_VCPUS:
@@ -1027,6 +1035,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		struct kvm_allocate_rma rma;
 		struct kvm *kvm = filp->private_data;
 
+		r = -ENOTTY;
+		if (!kvm_is_book3s_hv(kvm))
+			break;
 		r = kvm_vm_ioctl_allocate_rma(kvm, &rma);
 		if (r >= 0 && copy_to_user(argp, &rma, sizeof(rma)))
 			r = -EFAULT;
@@ -1036,6 +1047,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
 	case KVM_PPC_ALLOCATE_HTAB: {
 		u32 htab_order;
 
+		r = -ENOTTY;
+		if (!kvm_is_book3s_hv(kvm))
+			break;
 		r = -EFAULT;
 		if (get_user(htab_order, (u32 __user *)argp))
 			break;
@@ -1052,6 +1066,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
 	case KVM_PPC_GET_HTAB_FD: {
 		struct kvm_get_htab_fd ghf;
 
+		r = -ENOTTY;
+		if (!kvm_is_book3s_hv(kvm))
+			break;
 		r = -EFAULT;
 		if (copy_from_user(&ghf, argp, sizeof(ghf)))
 			break;
-- 
1.8.3.1


  parent reply	other threads:[~2013-08-06  4:28 UTC|newest]

Thread overview: 136+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-06  4:12 [PATCH 00/23] Allow PR and HV KVM to coexist in one kernel Paul Mackerras
2013-08-06  4:12 ` Paul Mackerras
2013-08-06  4:13 ` [PATCH 01/23] KVM: PPC: Book3S: Fix compile error in XICS emulation Paul Mackerras
2013-08-06  4:13   ` Paul Mackerras
2013-08-28 22:51   ` Alexander Graf
2013-08-28 22:51     ` Alexander Graf
2013-08-06  4:14 ` [PATCH 02/23] KVM: PPC: Book3S PR: Don't corrupt guest state when kernel uses VMX Paul Mackerras
2013-08-06  4:14   ` Paul Mackerras
2013-08-08 15:49   ` Aneesh Kumar K.V
2013-08-08 15:49     ` Aneesh Kumar K.V
2013-08-28 22:51   ` Alexander Graf
2013-08-28 22:51     ` Alexander Graf
2013-08-06  4:15 ` [PATCH 03/23] KVM: PPC: Book3S PR: Make instruction fetch fallback work for system calls Paul Mackerras
2013-08-06  4:15   ` Paul Mackerras
2013-08-28 22:51   ` Alexander Graf
2013-08-28 22:51     ` Alexander Graf
2013-08-06  4:16 ` [PATCH 04/23] KVM: PPC: Book3S PR: Keep volatile reg values in vcpu rather than shadow_vcpu Paul Mackerras
2013-08-06  4:16   ` Paul Mackerras
2013-08-11 11:06   ` Aneesh Kumar K.V
2013-08-11 11:18     ` Aneesh Kumar K.V
2013-08-28 22:00   ` Alexander Graf
2013-08-28 22:00     ` Alexander Graf
2013-08-29  5:04     ` Paul Mackerras
2013-08-29  5:04       ` Paul Mackerras
2013-08-29 12:46       ` Alexander Graf
2013-08-29 12:46         ` Alexander Graf
2013-08-06  4:18 ` [PATCH 05/23] KVM: PPC: Book3S PR: Rework kvmppc_mmu_book3s_64_xlate() Paul Mackerras
2013-08-06  4:18   ` Paul Mackerras
2013-08-28 22:51   ` Alexander Graf
2013-08-28 22:51     ` Alexander Graf
2013-08-06  4:18 ` [PATCH 06/23] KVM: PPC: Book3S PR: Allow guest to use 64k pages Paul Mackerras
2013-08-06  4:18   ` Paul Mackerras
2013-08-28 22:56   ` Alexander Graf
2013-08-28 22:56     ` Alexander Graf
2013-08-29  5:17     ` Paul Mackerras
2013-08-29  5:17       ` Paul Mackerras
2013-08-29 12:48       ` Alexander Graf
2013-08-29 12:48         ` Alexander Graf
2013-08-06  4:19 ` [PATCH 07/23] KVM: PPC: Book3S PR: Use 64k host pages where possible Paul Mackerras
2013-08-06  4:19   ` Paul Mackerras
2013-08-28 23:24   ` Alexander Graf
2013-08-28 23:24     ` Alexander Graf
2013-08-29  5:23     ` Paul Mackerras
2013-08-29  5:23       ` Paul Mackerras
2013-08-29 12:43       ` Alexander Graf
2013-08-29 12:43         ` Alexander Graf
2013-08-06  4:20 ` [PATCH 08/23] KVM: PPC: Book3S PR: Handle PP0 page-protection bit in guest HPTEs Paul Mackerras
2013-08-06  4:20   ` Paul Mackerras
2013-08-06  4:20 ` [PATCH 09/23] KVM: PPC: Book3S PR: Correct errors in H_ENTER implementation Paul Mackerras
2013-08-06  4:20   ` Paul Mackerras
2013-08-06  4:21 ` [PATCH 10/23] KVM: PPC: Book3S PR: Make HPT accesses and updates SMP-safe Paul Mackerras
2013-08-06  4:21   ` Paul Mackerras
2013-08-06  4:21 ` [PATCH 11/23] KVM: PPC: Book3S PR: Allocate kvm_vcpu structs from kvm_vcpu_cache Paul Mackerras
2013-08-06  4:21   ` Paul Mackerras
2013-08-12 10:03   ` Aneesh Kumar K.V
2013-08-12 10:15     ` Aneesh Kumar K.V
2013-08-06  4:22 ` [PATCH 12/23] KVM: PPC: Book3S HV: Better handling of exceptions that happen in real mode Paul Mackerras
2013-08-06  4:22   ` Paul Mackerras
2013-08-06  4:22 ` [PATCH 13/23] KVM: PPC: Book3S: Move skip-interrupt handlers to common code Paul Mackerras
2013-08-06  4:22   ` Paul Mackerras
2013-08-06  4:23 ` [PATCH 14/23] KVM: PPC: Book3S PR: Delay disabling relocation-on interrupts Paul Mackerras
2013-08-06  4:23   ` Paul Mackerras
2013-08-30 16:30   ` Alexander Graf
2013-08-30 16:30     ` Alexander Graf
2013-08-30 22:55     ` Paul Mackerras
2013-08-30 22:55       ` Paul Mackerras
2013-08-30 23:13       ` Alexander Graf
2013-08-30 23:13         ` Alexander Graf
2013-08-31  5:42         ` Paul Mackerras
2013-08-31  5:42           ` Paul Mackerras
2013-08-06  4:24 ` [PATCH 15/23] KVM: PPC: Book3S: Rename symbols that exist in both PR and HV KVM Paul Mackerras
2013-08-06  4:24   ` Paul Mackerras
2013-08-06  4:24 ` [PATCH 16/23] KVM: PPC: Book3S: Merge implementations of KVM_PPC_GET_SMMU_INFO ioctl Paul Mackerras
2013-08-06  4:24   ` Paul Mackerras
2013-08-06  4:25 ` [PATCH 17/23] KVM: PPC: Book3S HV: Factorize kvmppc_core_vcpu_create_hv() Paul Mackerras
2013-08-06  4:25   ` Paul Mackerras
2013-08-06  4:25 ` Paul Mackerras [this message]
2013-08-06  4:25   ` [PATCH 18/23] KVM: PPC: Book3S: Allow both PR and HV KVM to be selected Paul Mackerras
2013-08-06  4:26 ` [PATCH 19/23] KVM: PPC: Book3S: Select PR vs HV separately for each guest Paul Mackerras
2013-08-06  4:26   ` Paul Mackerras
2013-09-12 22:56   ` Alexander Graf
2013-09-12 22:56     ` Alexander Graf
2013-09-13  0:17     ` Paul Mackerras
2013-09-13  0:17       ` Paul Mackerras
2013-09-13  1:31       ` Benjamin Herrenschmidt
2013-09-13  1:31         ` Benjamin Herrenschmidt
2013-09-13  4:18         ` Alexander Graf
2013-09-13  4:18           ` Alexander Graf
2013-09-14 18:33         ` Aneesh Kumar K.V
2013-09-14 18:45           ` Aneesh Kumar K.V
2013-09-14 20:22           ` Alexander Graf
2013-09-14 20:22             ` Alexander Graf
2013-09-15  9:16             ` Aneesh Kumar K.V
2013-09-15  9:28               ` Aneesh Kumar K.V
2013-09-15 11:55               ` Alexander Graf
2013-09-15 11:55                 ` Alexander Graf
2013-09-13  4:17       ` Alexander Graf
2013-09-13  4:17         ` Alexander Graf
2013-09-18 12:05         ` Paul Mackerras
2013-09-18 12:05           ` Paul Mackerras
2013-09-19  7:31           ` Alexander Graf
2013-09-19  7:31             ` Alexander Graf
2013-08-06  4:27 ` [PATCH 20/23] KVM: PPC: Book3S PR: Better handling of host-side read-only pages Paul Mackerras
2013-08-06  4:27   ` Paul Mackerras
2013-09-12 23:01   ` Alexander Graf
2013-09-12 23:01     ` Alexander Graf
2013-09-13  0:23     ` Paul Mackerras
2013-09-13  0:23       ` Paul Mackerras
2013-09-14  5:24     ` Paul Mackerras
2013-09-14  5:24       ` Paul Mackerras
2013-09-14 20:23       ` Alexander Graf
2013-09-14 20:23         ` Alexander Graf
2013-09-16  4:12         ` Paul Mackerras
2013-09-16  4:12           ` Paul Mackerras
2013-09-16 12:47           ` Alexander Graf
2013-09-16 12:47             ` Alexander Graf
2013-08-06  4:27 ` [PATCH 21/23] KVM: PPC: Book3S PR: Use mmu_notifier_retry() in kvmppc_mmu_map_page() Paul Mackerras
2013-08-06  4:27   ` Paul Mackerras
2013-08-07  4:13   ` Bhushan Bharat-R65777
2013-08-07  4:13     ` Bhushan Bharat-R65777
2013-08-07  4:28     ` Paul Mackerras
2013-08-07  4:28       ` Paul Mackerras
2013-08-07  5:18       ` Bhushan Bharat-R65777
2013-08-07  5:18         ` Bhushan Bharat-R65777
2013-08-07  5:17   ` Bhushan Bharat-R65777
2013-08-07  5:17     ` Bhushan Bharat-R65777
2013-08-07  8:27     ` Paul Mackerras
2013-08-07  8:27       ` Paul Mackerras
2013-08-07  8:31       ` Bhushan Bharat-R65777
2013-08-07  8:31         ` Bhushan Bharat-R65777
2013-08-08 12:06         ` Paul Mackerras
2013-08-08 12:06           ` Paul Mackerras
2013-08-06  4:27 ` [PATCH 22/23] KVM: PPC: Book3S PR: Mark pages accessed, and dirty if being written Paul Mackerras
2013-08-06  4:27   ` Paul Mackerras
2013-08-06  4:28 ` [PATCH 23/23] KVM: PPC: Book3S PR: Reduce number of shadow PTEs invalidated by MMU notifiers Paul Mackerras
2013-08-06  4:28   ` Paul Mackerras

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130806042539.GX19254@iris.ozlabs.ibm.com \
    --to=paulus@samba.org \
    --cc=agraf@suse.de \
    --cc=benh@kernel.crashing.org \
    --cc=kvm-ppc@vger.kernel.org \
    --cc=kvm@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.