Loading arch/powerpc/include/asm/setup.h +2 −0 Original line number Diff line number Diff line Loading @@ -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) {} Loading arch/powerpc/kernel/exceptions-64s.S +4 −0 Original line number Diff line number Diff line Loading @@ -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 Loading arch/powerpc/kernel/setup_64.c +28 −0 Original line number Diff line number Diff line Loading @@ -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; Loading arch/powerpc/kvm/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -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 Loading arch/powerpc/kvm/book3s_hv.c +33 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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, Loading @@ -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); Loading Loading @@ -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 Loading
arch/powerpc/include/asm/setup.h +2 −0 Original line number Diff line number Diff line Loading @@ -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) {} Loading
arch/powerpc/kernel/exceptions-64s.S +4 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
arch/powerpc/kernel/setup_64.c +28 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
arch/powerpc/kvm/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
arch/powerpc/kvm/book3s_hv.c +33 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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, Loading @@ -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); Loading Loading @@ -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