Re: [PATCH v3 02/18] x86/reboot: Harden virtualization hooks for emergency reboot

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2023-05-12 at 16:50 -0700, Sean Christopherson wrote:
> Provide dedicated helpers to (un)register virt hooks used during an
> emergency crash/reboot, and WARN if there is an attempt to overwrite
> the registered callback, or an attempt to do an unpaired unregister.
> 
> Opportunsitically use rcu_assign_pointer() instead of RCU_INIT_POINTER(),
> mainly so that the set/unset paths are more symmetrical, but also because
> any performance gains from using RCU_INIT_POINTER() are meaningless for
> this code.
> 
> Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>

Reviewed-by: Kai Huang <kai.huang@xxxxxxxxx>

> ---
>  arch/x86/include/asm/reboot.h |  5 +++--
>  arch/x86/kernel/reboot.c      | 30 ++++++++++++++++++++++++------
>  arch/x86/kvm/vmx/vmx.c        |  6 ++----
>  3 files changed, 29 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h
> index 2551baec927d..d9a38d379d18 100644
> --- a/arch/x86/include/asm/reboot.h
> +++ b/arch/x86/include/asm/reboot.h
> @@ -25,8 +25,9 @@ void __noreturn machine_real_restart(unsigned int type);
>  #define MRR_BIOS	0
>  #define MRR_APM		1
>  
> -typedef void crash_vmclear_fn(void);
> -extern crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss;
> +typedef void (cpu_emergency_virt_cb)(void);
> +void cpu_emergency_register_virt_callback(cpu_emergency_virt_cb *callback);
> +void cpu_emergency_unregister_virt_callback(cpu_emergency_virt_cb *callback);
>  void cpu_emergency_disable_virtualization(void);
>  
>  typedef void (*nmi_shootdown_cb)(int, struct pt_regs*);
> diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
> index 299b970e5f82..739e09527dbb 100644
> --- a/arch/x86/kernel/reboot.c
> +++ b/arch/x86/kernel/reboot.c
> @@ -794,17 +794,35 @@ void machine_crash_shutdown(struct pt_regs *regs)
>   *
>   * protected by rcu.
>   */
> -crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss;
> -EXPORT_SYMBOL_GPL(crash_vmclear_loaded_vmcss);
> +static cpu_emergency_virt_cb __rcu *cpu_emergency_virt_callback;
> +
> +void cpu_emergency_register_virt_callback(cpu_emergency_virt_cb *callback)
> +{
> +	if (WARN_ON_ONCE(rcu_access_pointer(cpu_emergency_virt_callback)))
> +		return;
> +
> +	rcu_assign_pointer(cpu_emergency_virt_callback, callback);
> +}
> +EXPORT_SYMBOL_GPL(cpu_emergency_register_virt_callback);
> +
> +void cpu_emergency_unregister_virt_callback(cpu_emergency_virt_cb *callback)
> +{
> +	if (WARN_ON_ONCE(rcu_access_pointer(cpu_emergency_virt_callback) != callback))
> +		return;
> +
> +	rcu_assign_pointer(cpu_emergency_virt_callback, NULL);
> +	synchronize_rcu();
> +}
> +EXPORT_SYMBOL_GPL(cpu_emergency_unregister_virt_callback);
>  
>  static inline void cpu_crash_vmclear_loaded_vmcss(void)
>  {
> -	crash_vmclear_fn *do_vmclear_operation = NULL;
> +	cpu_emergency_virt_cb *callback;
>  
>  	rcu_read_lock();
> -	do_vmclear_operation = rcu_dereference(crash_vmclear_loaded_vmcss);
> -	if (do_vmclear_operation)
> -		do_vmclear_operation();
> +	callback = rcu_dereference(cpu_emergency_virt_callback);
> +	if (callback)
> +		callback();
>  	rcu_read_unlock();
>  }
>  
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 317f72baf0c3..fc9cdb4114cc 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -8547,8 +8547,7 @@ static void __vmx_exit(void)
>  {
>  	allow_smaller_maxphyaddr = false;
>  
> -	RCU_INIT_POINTER(crash_vmclear_loaded_vmcss, NULL);
> -	synchronize_rcu();
> +	cpu_emergency_unregister_virt_callback(crash_vmclear_local_loaded_vmcss);
>  
>  	vmx_cleanup_l1d_flush();
>  }
> @@ -8598,8 +8597,7 @@ static int __init vmx_init(void)
>  		pi_init_cpu(cpu);
>  	}
>  
> -	rcu_assign_pointer(crash_vmclear_loaded_vmcss,
> -			   crash_vmclear_local_loaded_vmcss);
> +	cpu_emergency_register_virt_callback(crash_vmclear_local_loaded_vmcss);
>  
>  	vmx_check_vmcs12_offsets();
>  
> -- 
> 2.40.1.606.ga4b1b128d6-goog
> 





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux