Commit 1aa940d9 authored by Michael Ellerman's avatar Michael Ellerman
Browse files

Merge branch 'topic/ppc-kvm' into next

Merge some more commits from our KVM topic branch. In particular this
brings in some commits that depend on a new capability that was merged
via the KVM tree for v5.18.
parents f82da161 f771b557
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -28,11 +28,13 @@ void setup_panic(void);
#define ARCH_PANIC_TIMEOUT 180

#ifdef CONFIG_PPC_PSERIES
extern bool pseries_reloc_on_exception(void);
extern bool pseries_enable_reloc_on_exc(void);
extern void pseries_disable_reloc_on_exc(void);
extern void pseries_big_endian_exceptions(void);
void __init pseries_little_endian_exceptions(void);
#else
static inline bool pseries_reloc_on_exception(void) { return false; }
static inline bool pseries_enable_reloc_on_exc(void) { return false; }
static inline void pseries_disable_reloc_on_exc(void) {}
static inline void pseries_big_endian_exceptions(void) {}
+4 −0
Original line number Diff line number Diff line
@@ -809,6 +809,10 @@ __start_interrupts:
 * - MSR_EE|MSR_RI is clear (no reentrant exceptions)
 * - Standard kernel environment is set up (stack, paca, etc)
 *
 * KVM:
 * These interrupts do not elevate HV 0->1, so HV is not involved. PR KVM
 * ensures that FSCR[SCV] is disabled whenever it has to force AIL off.
 *
 * Call convention:
 *
 * syscall register convention is in Documentation/powerpc/syscall64-abi.rst
+28 −0
Original line number Diff line number Diff line
@@ -196,6 +196,34 @@ static void __init configure_exceptions(void)

	/* Under a PAPR hypervisor, we need hypercalls */
	if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
		/*
		 * - PR KVM does not support AIL mode interrupts in the host
		 *   while a PR guest is running.
		 *
		 * - SCV system call interrupt vectors are only implemented for
		 *   AIL mode interrupts.
		 *
		 * - On pseries, AIL mode can only be enabled and disabled
		 *   system-wide so when a PR VM is created on a pseries host,
		 *   all CPUs of the host are set to AIL=0 mode.
		 *
		 * - Therefore host CPUs must not execute scv while a PR VM
		 *   exists.
		 *
		 * - SCV support can not be disabled dynamically because the
		 *   feature is advertised to host userspace. Disabling the
		 *   facility and emulating it would be possible but is not
		 *   implemented.
		 *
		 * - So SCV support is blanket disabled if PR KVM could possibly
		 *   run. That is, PR support compiled in, booting on pseries
		 *   with hash MMU.
		 */
		if (IS_ENABLED(CONFIG_KVM_BOOK3S_PR_POSSIBLE) && !radix_enabled()) {
			init_task.thread.fscr &= ~FSCR_SCV;
			cur_cpu_spec->cpu_user_features2 &= ~PPC_FEATURE2_SCV;
		}

		/* Enable AIL if possible */
		if (!pseries_enable_reloc_on_exc()) {
			init_task.thread.fscr &= ~FSCR_SCV;
+9 −0
Original line number Diff line number Diff line
@@ -112,12 +112,21 @@ config KVM_BOOK3S_64_PR
	  guest in user mode (problem state) and emulating all
	  privileged instructions and registers.

	  This is only available for hash MMU mode and only supports
	  guests that use hash MMU mode.

	  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.

	  Selecting this option will cause the SCV facility to be
	  disabled when the kernel is booted on the pseries platform in
	  hash MMU mode (regardless of PR VMs running). When any PR VMs
	  are running, "AIL" mode is disabled which may slow interrupts
	  and system calls on the host.

config KVM_BOOK3S_HV_EXIT_TIMING
	bool "Detailed timing for hypervisor real-mode code"
	depends on KVM_BOOK3S_HV_POSSIBLE && DEBUG_FS
+33 −8
Original line number Diff line number Diff line
@@ -225,6 +225,13 @@ static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
	int cpu;
	struct rcuwait *waitp;

	/*
	 * rcuwait_wake_up contains smp_mb() which orders prior stores that
	 * create pending work vs below loads of cpu fields. The other side
	 * is the barrier in vcpu run that orders setting the cpu fields vs
	 * testing for pending work.
	 */

	waitp = kvm_arch_vcpu_get_wait(vcpu);
	if (rcuwait_wake_up(waitp))
		++vcpu->stat.generic.halt_wakeup;
@@ -1089,7 +1096,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
			break;
		}
		tvcpu->arch.prodded = 1;
		smp_mb();
		smp_mb(); /* This orders prodded store vs ceded load */
		if (tvcpu->arch.ceded)
			kvmppc_fast_vcpu_kick_hv(tvcpu);
		break;
@@ -3766,6 +3773,14 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
		pvc = core_info.vc[sub];
		pvc->pcpu = pcpu + thr;
		for_each_runnable_thread(i, vcpu, pvc) {
			/*
			 * XXX: is kvmppc_start_thread called too late here?
			 * It updates vcpu->cpu and vcpu->arch.thread_cpu
			 * which are used by kvmppc_fast_vcpu_kick_hv(), but
			 * kick is called after new exceptions become available
			 * and exceptions are checked earlier than here, by
			 * kvmppc_core_prepare_to_enter.
			 */
			kvmppc_start_thread(vcpu, pvc);
			kvmppc_create_dtl_entry(vcpu, pvc);
			trace_kvm_guest_enter(vcpu);
@@ -4487,6 +4502,21 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
	if (need_resched() || !kvm->arch.mmu_ready)
		goto out;

	vcpu->cpu = pcpu;
	vcpu->arch.thread_cpu = pcpu;
	vc->pcpu = pcpu;
	local_paca->kvm_hstate.kvm_vcpu = vcpu;
	local_paca->kvm_hstate.ptid = 0;
	local_paca->kvm_hstate.fake_suspend = 0;

	/*
	 * Orders set cpu/thread_cpu vs testing for pending interrupts and
	 * doorbells below. The other side is when these fields are set vs
	 * kvmppc_fast_vcpu_kick_hv reading the cpu/thread_cpu fields to
	 * kick a vCPU to notice the pending interrupt.
	 */
	smp_mb();

	if (!nested) {
		kvmppc_core_prepare_to_enter(vcpu);
		if (test_bit(BOOK3S_IRQPRIO_EXTERNAL,
@@ -4506,13 +4536,6 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,

	tb = mftb();

	vcpu->cpu = pcpu;
	vcpu->arch.thread_cpu = pcpu;
	vc->pcpu = pcpu;
	local_paca->kvm_hstate.kvm_vcpu = vcpu;
	local_paca->kvm_hstate.ptid = 0;
	local_paca->kvm_hstate.fake_suspend = 0;

	__kvmppc_create_dtl_entry(vcpu, pcpu, tb + vc->tb_offset, 0);

	trace_kvm_guest_enter(vcpu);
@@ -4614,6 +4637,8 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
	run->exit_reason = KVM_EXIT_INTR;
	vcpu->arch.ret = -EINTR;
 out:
	vcpu->cpu = -1;
	vcpu->arch.thread_cpu = -1;
	powerpc_local_irq_pmu_restore(flags);
	preempt_enable();
	goto done;
Loading