Loading arch/s390/include/asm/entry-common.h +10 −0 Original line number Diff line number Diff line Loading @@ -59,4 +59,14 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs, #define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare static __always_inline bool arch_in_rcu_eqs(void) { if (IS_ENABLED(CONFIG_KVM)) return current->flags & PF_VCPU; return false; } #define arch_in_rcu_eqs arch_in_rcu_eqs #endif arch/s390/include/asm/kvm_host.h +3 −0 Original line number Diff line number Diff line Loading @@ -716,6 +716,9 @@ extern char sie_exit; bool kvm_s390_pv_is_protected(struct kvm *kvm); bool kvm_s390_pv_cpu_is_protected(struct kvm_vcpu *vcpu); extern int kvm_s390_enter_exit_sie(struct kvm_s390_sie_block *scb, u64 *gprs, unsigned long gasce); extern int kvm_s390_gisc_register(struct kvm *kvm, u32 gisc); extern int kvm_s390_gisc_unregister(struct kvm *kvm, u32 gisc); Loading arch/s390/kvm/kvm-s390.c +39 −12 Original line number Diff line number Diff line Loading @@ -5062,6 +5062,30 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) return vcpu_post_run_handle_fault(vcpu); } int noinstr kvm_s390_enter_exit_sie(struct kvm_s390_sie_block *scb, u64 *gprs, unsigned long gasce) { int ret; guest_state_enter_irqoff(); /* * The guest_state_{enter,exit}_irqoff() functions inform lockdep and * tracing that entry to the guest will enable host IRQs, and exit from * the guest will disable host IRQs. * * We must not use lockdep/tracing/RCU in this critical section, so we * use the low-level arch_local_irq_*() helpers to enable/disable IRQs. */ arch_local_irq_enable(); ret = sie64a(scb, gprs, gasce); arch_local_irq_disable(); guest_state_exit_irqoff(); return ret; } #define PSW_INT_MASK (PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_MCHECK) static int __vcpu_run(struct kvm_vcpu *vcpu) { Loading @@ -5082,20 +5106,27 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) kvm_vcpu_srcu_read_unlock(vcpu); /* * As PF_VCPU will be used in fault handler, between * guest_enter and guest_exit should be no uaccess. * guest_timing_enter_irqoff and guest_timing_exit_irqoff * should be no uaccess. */ local_irq_disable(); guest_enter_irqoff(); __disable_cpu_timer_accounting(vcpu); local_irq_enable(); if (kvm_s390_pv_cpu_is_protected(vcpu)) { memcpy(sie_page->pv_grregs, vcpu->run->s.regs.gprs, sizeof(sie_page->pv_grregs)); } exit_reason = sie64a(vcpu->arch.sie_block, local_irq_disable(); guest_timing_enter_irqoff(); __disable_cpu_timer_accounting(vcpu); exit_reason = kvm_s390_enter_exit_sie(vcpu->arch.sie_block, vcpu->run->s.regs.gprs, vcpu->arch.gmap->asce); __enable_cpu_timer_accounting(vcpu); guest_timing_exit_irqoff(); local_irq_enable(); if (kvm_s390_pv_cpu_is_protected(vcpu)) { memcpy(vcpu->run->s.regs.gprs, sie_page->pv_grregs, Loading @@ -5111,10 +5142,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) vcpu->arch.sie_block->gpsw.mask &= ~PSW_INT_MASK; } } local_irq_disable(); __enable_cpu_timer_accounting(vcpu); guest_exit_irqoff(); local_irq_enable(); kvm_vcpu_srcu_read_lock(vcpu); rc = vcpu_post_run(vcpu, exit_reason); Loading arch/s390/kvm/vsie.c +7 −10 Original line number Diff line number Diff line Loading @@ -1170,10 +1170,6 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) vcpu->arch.sie_block->fpf & FPF_BPBC) set_thread_flag(TIF_ISOLATE_BP_GUEST); local_irq_disable(); guest_enter_irqoff(); local_irq_enable(); /* * Simulate a SIE entry of the VCPU (see sie64a), so VCPU blocking * and VCPU requests also hinder the vSIE from running and lead Loading @@ -1183,14 +1179,15 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) vcpu->arch.sie_block->prog0c |= PROG_IN_SIE; current->thread.gmap_int_code = 0; barrier(); if (!kvm_s390_vcpu_sie_inhibited(vcpu)) rc = sie64a(scb_s, vcpu->run->s.regs.gprs, vsie_page->gmap->asce); barrier(); vcpu->arch.sie_block->prog0c &= ~PROG_IN_SIE; if (!kvm_s390_vcpu_sie_inhibited(vcpu)) { local_irq_disable(); guest_exit_irqoff(); guest_timing_enter_irqoff(); rc = kvm_s390_enter_exit_sie(scb_s, vcpu->run->s.regs.gprs, vsie_page->gmap->asce); guest_timing_exit_irqoff(); local_irq_enable(); } barrier(); vcpu->arch.sie_block->prog0c &= ~PROG_IN_SIE; /* restore guest state for bp isolation override */ if (!guest_bp_isolation) Loading include/linux/entry-common.h +16 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,22 @@ static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs); static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs) {} #endif /** * arch_in_rcu_eqs - Architecture specific check for RCU extended quiescent * states. * * Returns: true if the CPU is potentially in an RCU EQS, false otherwise. * * Architectures only need to define this if threads other than the idle thread * may have an interruptible EQS. This does not need to handle idle threads. It * is safe to over-estimate at the cost of redundant RCU management work. * * Invoked from irqentry_enter() */ #ifndef arch_in_rcu_eqs static __always_inline bool arch_in_rcu_eqs(void) { return false; } #endif /** * enter_from_user_mode - Establish state when coming from user mode * Loading Loading
arch/s390/include/asm/entry-common.h +10 −0 Original line number Diff line number Diff line Loading @@ -59,4 +59,14 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs, #define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare static __always_inline bool arch_in_rcu_eqs(void) { if (IS_ENABLED(CONFIG_KVM)) return current->flags & PF_VCPU; return false; } #define arch_in_rcu_eqs arch_in_rcu_eqs #endif
arch/s390/include/asm/kvm_host.h +3 −0 Original line number Diff line number Diff line Loading @@ -716,6 +716,9 @@ extern char sie_exit; bool kvm_s390_pv_is_protected(struct kvm *kvm); bool kvm_s390_pv_cpu_is_protected(struct kvm_vcpu *vcpu); extern int kvm_s390_enter_exit_sie(struct kvm_s390_sie_block *scb, u64 *gprs, unsigned long gasce); extern int kvm_s390_gisc_register(struct kvm *kvm, u32 gisc); extern int kvm_s390_gisc_unregister(struct kvm *kvm, u32 gisc); Loading
arch/s390/kvm/kvm-s390.c +39 −12 Original line number Diff line number Diff line Loading @@ -5062,6 +5062,30 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) return vcpu_post_run_handle_fault(vcpu); } int noinstr kvm_s390_enter_exit_sie(struct kvm_s390_sie_block *scb, u64 *gprs, unsigned long gasce) { int ret; guest_state_enter_irqoff(); /* * The guest_state_{enter,exit}_irqoff() functions inform lockdep and * tracing that entry to the guest will enable host IRQs, and exit from * the guest will disable host IRQs. * * We must not use lockdep/tracing/RCU in this critical section, so we * use the low-level arch_local_irq_*() helpers to enable/disable IRQs. */ arch_local_irq_enable(); ret = sie64a(scb, gprs, gasce); arch_local_irq_disable(); guest_state_exit_irqoff(); return ret; } #define PSW_INT_MASK (PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_MCHECK) static int __vcpu_run(struct kvm_vcpu *vcpu) { Loading @@ -5082,20 +5106,27 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) kvm_vcpu_srcu_read_unlock(vcpu); /* * As PF_VCPU will be used in fault handler, between * guest_enter and guest_exit should be no uaccess. * guest_timing_enter_irqoff and guest_timing_exit_irqoff * should be no uaccess. */ local_irq_disable(); guest_enter_irqoff(); __disable_cpu_timer_accounting(vcpu); local_irq_enable(); if (kvm_s390_pv_cpu_is_protected(vcpu)) { memcpy(sie_page->pv_grregs, vcpu->run->s.regs.gprs, sizeof(sie_page->pv_grregs)); } exit_reason = sie64a(vcpu->arch.sie_block, local_irq_disable(); guest_timing_enter_irqoff(); __disable_cpu_timer_accounting(vcpu); exit_reason = kvm_s390_enter_exit_sie(vcpu->arch.sie_block, vcpu->run->s.regs.gprs, vcpu->arch.gmap->asce); __enable_cpu_timer_accounting(vcpu); guest_timing_exit_irqoff(); local_irq_enable(); if (kvm_s390_pv_cpu_is_protected(vcpu)) { memcpy(vcpu->run->s.regs.gprs, sie_page->pv_grregs, Loading @@ -5111,10 +5142,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) vcpu->arch.sie_block->gpsw.mask &= ~PSW_INT_MASK; } } local_irq_disable(); __enable_cpu_timer_accounting(vcpu); guest_exit_irqoff(); local_irq_enable(); kvm_vcpu_srcu_read_lock(vcpu); rc = vcpu_post_run(vcpu, exit_reason); Loading
arch/s390/kvm/vsie.c +7 −10 Original line number Diff line number Diff line Loading @@ -1170,10 +1170,6 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) vcpu->arch.sie_block->fpf & FPF_BPBC) set_thread_flag(TIF_ISOLATE_BP_GUEST); local_irq_disable(); guest_enter_irqoff(); local_irq_enable(); /* * Simulate a SIE entry of the VCPU (see sie64a), so VCPU blocking * and VCPU requests also hinder the vSIE from running and lead Loading @@ -1183,14 +1179,15 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) vcpu->arch.sie_block->prog0c |= PROG_IN_SIE; current->thread.gmap_int_code = 0; barrier(); if (!kvm_s390_vcpu_sie_inhibited(vcpu)) rc = sie64a(scb_s, vcpu->run->s.regs.gprs, vsie_page->gmap->asce); barrier(); vcpu->arch.sie_block->prog0c &= ~PROG_IN_SIE; if (!kvm_s390_vcpu_sie_inhibited(vcpu)) { local_irq_disable(); guest_exit_irqoff(); guest_timing_enter_irqoff(); rc = kvm_s390_enter_exit_sie(scb_s, vcpu->run->s.regs.gprs, vsie_page->gmap->asce); guest_timing_exit_irqoff(); local_irq_enable(); } barrier(); vcpu->arch.sie_block->prog0c &= ~PROG_IN_SIE; /* restore guest state for bp isolation override */ if (!guest_bp_isolation) Loading
include/linux/entry-common.h +16 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,22 @@ static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs); static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs) {} #endif /** * arch_in_rcu_eqs - Architecture specific check for RCU extended quiescent * states. * * Returns: true if the CPU is potentially in an RCU EQS, false otherwise. * * Architectures only need to define this if threads other than the idle thread * may have an interruptible EQS. This does not need to handle idle threads. It * is safe to over-estimate at the cost of redundant RCU management work. * * Invoked from irqentry_enter() */ #ifndef arch_in_rcu_eqs static __always_inline bool arch_in_rcu_eqs(void) { return false; } #endif /** * enter_from_user_mode - Establish state when coming from user mode * Loading