[v7,2/3] powerpc/powernv: Introduce a machine check hook for Guest MCEs.

Message ID 149142524189.28284.14876788789820474952.stgit@jupiter.in.ibm.com
State Superseded
Headers show

Commit Message

Mahesh J Salgaonkar April 5, 2017, 8:47 p.m.
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>

This patch introduces a mce hook which is invoked at the time of guest
exit to facilitate the host-side handling of machine check exception
before the exception is passed on to the guest. This hook will be invoked
from host virtual mode from KVM (before exiting the guest with
KVM_EXIT_NMI reason) for machine check exception that occurs in the guest.

Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/machdep.h     |    7 +++++++
 arch/powerpc/include/asm/opal.h        |    4 ++++
 arch/powerpc/platforms/powernv/opal.c  |   26 ++++++++++++++++++++++++++
 arch/powerpc/platforms/powernv/setup.c |    3 +++
 4 files changed, 40 insertions(+)


--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

David Gibson April 6, 2017, 5:22 a.m. | #1
On Thu, Apr 06, 2017 at 02:17:22AM +0530, Mahesh J Salgaonkar wrote:
> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
> 
> This patch introduces a mce hook which is invoked at the time of guest
> exit to facilitate the host-side handling of machine check exception
> before the exception is passed on to the guest. This hook will be invoked
> from host virtual mode from KVM (before exiting the guest with
> KVM_EXIT_NMI reason) for machine check exception that occurs in the guest.
> 
> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>

Um.. this introduces the hook, and puts in an implementation of it,
but AFAICT, nothing calls it, either here or in the next patch.  That
seems a bit pointless.

> ---
>  arch/powerpc/include/asm/machdep.h     |    7 +++++++
>  arch/powerpc/include/asm/opal.h        |    4 ++++
>  arch/powerpc/platforms/powernv/opal.c  |   26 ++++++++++++++++++++++++++
>  arch/powerpc/platforms/powernv/setup.c |    3 +++
>  4 files changed, 40 insertions(+)
> 
> diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
> index 5011b69..9d74e7a 100644
> --- a/arch/powerpc/include/asm/machdep.h
> +++ b/arch/powerpc/include/asm/machdep.h
> @@ -15,6 +15,7 @@
>  #include <linux/export.h>
>  
>  #include <asm/setup.h>
> +#include <asm/mce.h>
>  
>  /* We export this macro for external modules like Alsa to know if
>   * ppc_md.feature_call is implemented or not
> @@ -112,6 +113,12 @@ struct machdep_calls {
>  	/* Called during machine check exception to retrive fixup address. */
>  	bool		(*mce_check_early_recovery)(struct pt_regs *regs);
>  
> +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
> +	/* Called after KVM interrupt handler finishes handling MCE for guest */
> +	int		(*machine_check_exception_guest)
> +					(struct machine_check_event *evt);
> +#endif
> +
>  	/* Motherboard/chipset features. This is a kind of general purpose
>  	 * hook used to control some machine specific features (like reset
>  	 * lines, chip power control, etc...).
> diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
> index 1ff03a6..9b1fcbf 100644
> --- a/arch/powerpc/include/asm/opal.h
> +++ b/arch/powerpc/include/asm/opal.h
> @@ -17,6 +17,7 @@
>  #ifndef __ASSEMBLY__
>  
>  #include <linux/notifier.h>
> +#include <asm/mce.h>
>  
>  /* We calculate number of sg entries based on PAGE_SIZE */
>  #define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
> @@ -273,6 +274,9 @@ extern int opal_hmi_handler_init(void);
>  extern int opal_event_init(void);
>  
>  extern int opal_machine_check(struct pt_regs *regs);
> +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
> +extern int opal_machine_check_guest(struct machine_check_event *evt);
> +#endif
>  extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
>  extern int opal_hmi_exception_early(struct pt_regs *regs);
>  extern int opal_handle_hmi_exception(struct pt_regs *regs);
> diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
> index e0f856b..5e633a4 100644
> --- a/arch/powerpc/platforms/powernv/opal.c
> +++ b/arch/powerpc/platforms/powernv/opal.c
> @@ -479,6 +479,32 @@ int opal_machine_check(struct pt_regs *regs)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
> +/*
> + * opal_machine_check_guest() is a hook which is invoked at the time
> + * of guest exit to facilitate the host-side handling of machine check
> + * exception before the exception is passed on to the guest. This hook
> + * is invoked from host virtual mode from KVM (before exiting the guest
> + * with KVM_EXIT_NMI reason) for machine check exception that occurs in
> + * the guest.
> + *
> + * Currently no action is performed in the host other than printing the
> + * event information. The machine check exception is passed on to the
> + * guest kernel and the guest kernel will attempt for recovery.
> + */
> +int opal_machine_check_guest(struct machine_check_event *evt)
> +{
> +	/* Print things out */
> +	if (evt->version != MCE_V1) {
> +		pr_err("Machine Check Exception, Unknown event version %d !\n",
> +		       evt->version);
> +		return 0;
> +	}
> +	machine_check_print_event_info(evt);
> +	return 0;
> +}
> +#endif
> +
>  /* Early hmi handler called in real mode. */
>  int opal_hmi_exception_early(struct pt_regs *regs)
>  {
> diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
> index d50c7d9..333ee09 100644
> --- a/arch/powerpc/platforms/powernv/setup.c
> +++ b/arch/powerpc/platforms/powernv/setup.c
> @@ -264,6 +264,9 @@ static void __init pnv_setup_machdep_opal(void)
>  	ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery;
>  	ppc_md.hmi_exception_early = opal_hmi_exception_early;
>  	ppc_md.handle_hmi_exception = opal_handle_hmi_exception;
> +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
> +	ppc_md.machine_check_exception_guest = opal_machine_check_guest;
> +#endif
>  }
>  
>  static int __init pnv_probe(void)
>
Michael Ellerman April 6, 2017, 5:53 a.m. | #2
Mahesh J Salgaonkar <mahesh@linux.vnet.ibm.com> writes:

> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>
> This patch introduces a mce hook which is invoked at the time of guest
> exit to facilitate the host-side handling of machine check exception
> before the exception is passed on to the guest. This hook will be invoked
> from host virtual mode from KVM (before exiting the guest with
> KVM_EXIT_NMI reason) for machine check exception that occurs in the guest.

Hi Mahesh,

This patch doesn't meaningfully abstract anything.

opal_machine_check_guest() doesn't call opal, or do anything opal
specific. It just passes the evt struct back to code in mce.c, which is
where the struct came from in the first place.

> --- a/arch/powerpc/platforms/powernv/opal.c
> +++ b/arch/powerpc/platforms/powernv/opal.c
> @@ -479,6 +479,32 @@ int opal_machine_check(struct pt_regs *regs)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
> +/*
> + * opal_machine_check_guest() is a hook which is invoked at the time
> + * of guest exit to facilitate the host-side handling of machine check
> + * exception before the exception is passed on to the guest. This hook
> + * is invoked from host virtual mode from KVM (before exiting the guest
> + * with KVM_EXIT_NMI reason) for machine check exception that occurs in
> + * the guest.
> + *
> + * Currently no action is performed in the host other than printing the
> + * event information. The machine check exception is passed on to the
> + * guest kernel and the guest kernel will attempt for recovery.
> + */
> +int opal_machine_check_guest(struct machine_check_event *evt)
> +{
> +	/* Print things out */
> +	if (evt->version != MCE_V1) {
> +		pr_err("Machine Check Exception, Unknown event version %d !\n",
> +		       evt->version);
> +		return 0;
> +	}
> +	machine_check_print_event_info(evt);
> +	return 0;
> +}
> +#endif

Called from kvmppc_handle_exit_hv():

+		if (ppc_md.machine_check_exception_guest)
+			ppc_md.machine_check_exception_guest(
+							&vcpu->arch.mce_evt);
 		break;

Just call machine_check_print_event_info() directly from
kvmppc_handle_exit_hv().

You'll need to export symbol it, but that's all AFAICS, I don't think it
even needs any #ifdefs.

If we ever want to do anything different we can change the code then.

cheers
--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mahesh J Salgaonkar April 6, 2017, 7:04 a.m. | #3
On 04/06/2017 10:52 AM, David Gibson wrote:
> On Thu, Apr 06, 2017 at 02:17:22AM +0530, Mahesh J Salgaonkar wrote:
>> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>>
>> This patch introduces a mce hook which is invoked at the time of guest
>> exit to facilitate the host-side handling of machine check exception
>> before the exception is passed on to the guest. This hook will be invoked
>> from host virtual mode from KVM (before exiting the guest with
>> KVM_EXIT_NMI reason) for machine check exception that occurs in the guest.
>>
>> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
> 
> Um.. this introduces the hook, and puts in an implementation of it,
> but AFAICT, nothing calls it, either here or in the next patch.  That
> seems a bit pointless.

It gets called in the next patch [3/3] through
ppc_md.machine_check_exception_guest(). See the hunk for file
arch/powerpc/kvm/book3s_hv.c in next patch.

> 
>> ---
>>  arch/powerpc/include/asm/machdep.h     |    7 +++++++
>>  arch/powerpc/include/asm/opal.h        |    4 ++++
>>  arch/powerpc/platforms/powernv/opal.c  |   26 ++++++++++++++++++++++++++
>>  arch/powerpc/platforms/powernv/setup.c |    3 +++
>>  4 files changed, 40 insertions(+)
>>
>> diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
>> index 5011b69..9d74e7a 100644
>> --- a/arch/powerpc/include/asm/machdep.h
>> +++ b/arch/powerpc/include/asm/machdep.h
>> @@ -15,6 +15,7 @@
>>  #include <linux/export.h>
>>  
>>  #include <asm/setup.h>
>> +#include <asm/mce.h>
>>  
>>  /* We export this macro for external modules like Alsa to know if
>>   * ppc_md.feature_call is implemented or not
>> @@ -112,6 +113,12 @@ struct machdep_calls {
>>  	/* Called during machine check exception to retrive fixup address. */
>>  	bool		(*mce_check_early_recovery)(struct pt_regs *regs);
>>  
>> +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
>> +	/* Called after KVM interrupt handler finishes handling MCE for guest */
>> +	int		(*machine_check_exception_guest)
>> +					(struct machine_check_event *evt);
>> +#endif
>> +
>>  	/* Motherboard/chipset features. This is a kind of general purpose
>>  	 * hook used to control some machine specific features (like reset
>>  	 * lines, chip power control, etc...).
>> diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
>> index 1ff03a6..9b1fcbf 100644
>> --- a/arch/powerpc/include/asm/opal.h
>> +++ b/arch/powerpc/include/asm/opal.h
>> @@ -17,6 +17,7 @@
>>  #ifndef __ASSEMBLY__
>>  
>>  #include <linux/notifier.h>
>> +#include <asm/mce.h>
>>  
>>  /* We calculate number of sg entries based on PAGE_SIZE */
>>  #define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
>> @@ -273,6 +274,9 @@ extern int opal_hmi_handler_init(void);
>>  extern int opal_event_init(void);
>>  
>>  extern int opal_machine_check(struct pt_regs *regs);
>> +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
>> +extern int opal_machine_check_guest(struct machine_check_event *evt);
>> +#endif
>>  extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
>>  extern int opal_hmi_exception_early(struct pt_regs *regs);
>>  extern int opal_handle_hmi_exception(struct pt_regs *regs);
>> diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
>> index e0f856b..5e633a4 100644
>> --- a/arch/powerpc/platforms/powernv/opal.c
>> +++ b/arch/powerpc/platforms/powernv/opal.c
>> @@ -479,6 +479,32 @@ int opal_machine_check(struct pt_regs *regs)
>>  	return 0;
>>  }
>>  
>> +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
>> +/*
>> + * opal_machine_check_guest() is a hook which is invoked at the time
>> + * of guest exit to facilitate the host-side handling of machine check
>> + * exception before the exception is passed on to the guest. This hook
>> + * is invoked from host virtual mode from KVM (before exiting the guest
>> + * with KVM_EXIT_NMI reason) for machine check exception that occurs in
>> + * the guest.
>> + *
>> + * Currently no action is performed in the host other than printing the
>> + * event information. The machine check exception is passed on to the
>> + * guest kernel and the guest kernel will attempt for recovery.
>> + */
>> +int opal_machine_check_guest(struct machine_check_event *evt)
>> +{
>> +	/* Print things out */
>> +	if (evt->version != MCE_V1) {
>> +		pr_err("Machine Check Exception, Unknown event version %d !\n",
>> +		       evt->version);
>> +		return 0;
>> +	}
>> +	machine_check_print_event_info(evt);
>> +	return 0;
>> +}
>> +#endif
>> +
>>  /* Early hmi handler called in real mode. */
>>  int opal_hmi_exception_early(struct pt_regs *regs)
>>  {
>> diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
>> index d50c7d9..333ee09 100644
>> --- a/arch/powerpc/platforms/powernv/setup.c
>> +++ b/arch/powerpc/platforms/powernv/setup.c
>> @@ -264,6 +264,9 @@ static void __init pnv_setup_machdep_opal(void)
>>  	ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery;
>>  	ppc_md.hmi_exception_early = opal_hmi_exception_early;
>>  	ppc_md.handle_hmi_exception = opal_handle_hmi_exception;
>> +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
>> +	ppc_md.machine_check_exception_guest = opal_machine_check_guest;
>> +#endif
>>  }
>>  
>>  static int __init pnv_probe(void)
>>
> 

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 5011b69..9d74e7a 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -15,6 +15,7 @@ 
 #include <linux/export.h>
 
 #include <asm/setup.h>
+#include <asm/mce.h>
 
 /* We export this macro for external modules like Alsa to know if
  * ppc_md.feature_call is implemented or not
@@ -112,6 +113,12 @@  struct machdep_calls {
 	/* Called during machine check exception to retrive fixup address. */
 	bool		(*mce_check_early_recovery)(struct pt_regs *regs);
 
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+	/* Called after KVM interrupt handler finishes handling MCE for guest */
+	int		(*machine_check_exception_guest)
+					(struct machine_check_event *evt);
+#endif
+
 	/* Motherboard/chipset features. This is a kind of general purpose
 	 * hook used to control some machine specific features (like reset
 	 * lines, chip power control, etc...).
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 1ff03a6..9b1fcbf 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -17,6 +17,7 @@ 
 #ifndef __ASSEMBLY__
 
 #include <linux/notifier.h>
+#include <asm/mce.h>
 
 /* We calculate number of sg entries based on PAGE_SIZE */
 #define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
@@ -273,6 +274,9 @@  extern int opal_hmi_handler_init(void);
 extern int opal_event_init(void);
 
 extern int opal_machine_check(struct pt_regs *regs);
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+extern int opal_machine_check_guest(struct machine_check_event *evt);
+#endif
 extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
 extern int opal_hmi_exception_early(struct pt_regs *regs);
 extern int opal_handle_hmi_exception(struct pt_regs *regs);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index e0f856b..5e633a4 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -479,6 +479,32 @@  int opal_machine_check(struct pt_regs *regs)
 	return 0;
 }
 
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+/*
+ * opal_machine_check_guest() is a hook which is invoked at the time
+ * of guest exit to facilitate the host-side handling of machine check
+ * exception before the exception is passed on to the guest. This hook
+ * is invoked from host virtual mode from KVM (before exiting the guest
+ * with KVM_EXIT_NMI reason) for machine check exception that occurs in
+ * the guest.
+ *
+ * Currently no action is performed in the host other than printing the
+ * event information. The machine check exception is passed on to the
+ * guest kernel and the guest kernel will attempt for recovery.
+ */
+int opal_machine_check_guest(struct machine_check_event *evt)
+{
+	/* Print things out */
+	if (evt->version != MCE_V1) {
+		pr_err("Machine Check Exception, Unknown event version %d !\n",
+		       evt->version);
+		return 0;
+	}
+	machine_check_print_event_info(evt);
+	return 0;
+}
+#endif
+
 /* Early hmi handler called in real mode. */
 int opal_hmi_exception_early(struct pt_regs *regs)
 {
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index d50c7d9..333ee09 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -264,6 +264,9 @@  static void __init pnv_setup_machdep_opal(void)
 	ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery;
 	ppc_md.hmi_exception_early = opal_hmi_exception_early;
 	ppc_md.handle_hmi_exception = opal_handle_hmi_exception;
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+	ppc_md.machine_check_exception_guest = opal_machine_check_guest;
+#endif
 }
 
 static int __init pnv_probe(void)