Re: [PATCH v4 08/10] riscv: Introduce HEST SSE notification handlers

Anup Patel <[email protected]>
Newsgroups org.kernel.vger.linux-efi,dev.linux.lists.acpica-devel,org.infradead.lists.linux-riscv,org.kernel.vger.linux-acpi,org.kernel.vger.linux-kernel
Message-ID <CAAhSdy2LkwC_FBFWP3M66X-mY8WwpSHiOCOKf=e4Fri=gkt27Q@mail.gmail.com>
On Wed, May 13, 2026 at 2:18 PM Himanshu Chauhan
<[email protected]> wrote:
>
> Add config option to enable SSE in APEI. When it is enabled, functions
> to register/unregister a ghes entry with SSE are avilable along with
> low and high priority event handers. If a SSE notification type is
> determined, a ghes common handler to handle an error event is registered.
>
> Signed-off-by: Himanshu Chauhan <[email protected]>
> ---
>  drivers/acpi/apei/Kconfig |  5 ++
>  drivers/acpi/apei/ghes.c  | 99 ++++++++++++++++++++++++++++++++++-----
>  2 files changed, 93 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
> index 428458c623f0..895a843d0e36 100644
> --- a/drivers/acpi/apei/Kconfig
> +++ b/drivers/acpi/apei/Kconfig
> @@ -46,6 +46,11 @@ config ACPI_APEI_SEA
>         depends on ARM64 && ACPI_APEI_GHES
>         default y
>
> +config ACPI_APEI_SSE
> +       bool
> +       depends on RISCV && RISCV_SBI_SSE && ACPI_APEI_GHES
> +       default y
> +
>  config ACPI_APEI_MEMORY_FAILURE
>         bool "APEI memory error recovering support"
>         depends on ACPI_APEI && MEMORY_FAILURE
> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
> index 8edc2c8db1bb..1baa8ddd10ea 100644
> --- a/drivers/acpi/apei/ghes.c
> +++ b/drivers/acpi/apei/ghes.c
> @@ -17,6 +17,8 @@
>   *   Author: Huang Ying <[email protected]>
>   */
>
> +#include <linux/err.h>
> +#include <linux/riscv_sbi_sse.h>
>  #include <linux/arm_sdei.h>
>  #include <linux/kernel.h>
>  #include <linux/moduleparam.h>
> @@ -100,6 +102,11 @@
>  #define FIX_APEI_GHES_SDEI_CRITICAL    __end_of_fixed_addresses
>  #endif
>
> +#ifndef CONFIG_RISCV_SBI_SSE
> +#define FIX_APEI_GHES_SSE_LOW_PRIORITY __end_of_fixed_addresses
> +#define FIX_APEI_GHES_SSE_HIGH_PRIORITY        __end_of_fixed_addresses
> +#endif
> +
>  static ATOMIC_NOTIFIER_HEAD(ghes_report_chain);
>
>  static inline bool is_hest_type_generic_v2(struct ghes *ghes)
> @@ -1662,6 +1669,63 @@ static int apei_sdei_unregister_ghes(struct ghes *ghes)
>         return sdei_unregister_ghes(ghes);
>  }
>
> +#if defined(CONFIG_ACPI_APEI_SSE)
> +/* SSE Handlers */
> +static int __ghes_sse_callback(struct ghes *ghes,
> +                              enum fixed_addresses fixmap_idx)
> +{
> +       if (!ghes_in_nmi_queue_one_entry(ghes, fixmap_idx)) {
> +               irq_work_queue(&ghes_proc_irq_work);
> +
> +               return 0;
> +       }
> +
> +       return -ENOENT;
> +}
> +
> +/* Low priority */
> +static int ghes_sse_lo_callback(u32 event_num, void *arg, struct pt_regs *regs)
> +{
> +       static DEFINE_RAW_SPINLOCK(ghes_notify_lock_sse_lo);
> +       struct ghes *ghes = arg;
> +       int err;
> +
> +       raw_spin_lock(&ghes_notify_lock_sse_lo);
> +       err = __ghes_sse_callback(ghes, FIX_APEI_GHES_SSE_LOW_PRIORITY);
> +       raw_spin_unlock(&ghes_notify_lock_sse_lo);
> +
> +       return err;
> +}
> +
> +/* High priority */
> +static int ghes_sse_hi_callback(u32 event_num, void *arg, struct pt_regs *regs)
> +{
> +       static DEFINE_RAW_SPINLOCK(ghes_notify_lock_sse_hi);
> +       struct ghes *ghes = arg;
> +       int err;
> +
> +       raw_spin_lock(&ghes_notify_lock_sse_hi);
> +       err = __ghes_sse_callback(ghes, FIX_APEI_GHES_SSE_HIGH_PRIORITY);
> +       raw_spin_unlock(&ghes_notify_lock_sse_hi);
> +
> +       return err;
> +}
> +
> +static int apei_sse_register_ghes(struct ghes *ghes)
> +{
> +       return sse_register_ghes(ghes, ghes_sse_lo_callback,
> +                                ghes_sse_hi_callback);
> +}
> +
> +static int apei_sse_unregister_ghes(struct ghes *ghes)
> +{
> +       return sse_unregister_ghes(ghes);
> +}
> +#else /* CONFIG_ACPI_APEI_SSE */
> +static int apei_sse_register_ghes(struct ghes *ghes) { return -EOPNOTSUPP; }
> +static int apei_sse_unregister_ghes(struct ghes *ghes) { return -EOPNOTSUPP; }
> +#endif
> +
>  static int ghes_probe(struct platform_device *ghes_dev)
>  {
>         struct acpi_hest_generic *generic;
> @@ -1708,6 +1772,14 @@ static int ghes_probe(struct platform_device *ghes_dev)
>                 pr_warn(GHES_PFX "Generic hardware error source: %d notified via local interrupt is not supported!\n",
>                         generic->header.source_id);
>                 goto err;
> +       case ACPI_HEST_NOTIFY_SSE:
> +               if (!IS_ENABLED(CONFIG_ACPI_APEI_SSE)) {
> +                       pr_warn(GHES_PFX "Generic hardware error source: %d notified via SSE is not supported\n",
> +                               generic->header.source_id);
> +                       rc = -EOPNOTSUPP;
> +                       goto err;
> +               }
> +               break;
>         default:
>                 pr_warn(FW_WARN GHES_PFX "Unknown notification type: %u for generic hardware error source: %d\n",
>                         generic->notify.type, generic->header.source_id);
> @@ -1775,6 +1847,17 @@ static int ghes_probe(struct platform_device *ghes_dev)
>                 if (rc)
>                         goto err;
>                 break;
> +
> +       case ACPI_HEST_NOTIFY_SSE:
> +               rc = apei_sse_register_ghes(ghes);
> +               if (rc) {
> +                       pr_err(GHES_PFX "Failed to register for SSE notification on vector %d\n",
> +                              generic->notify.vector);
> +                       goto err;
> +               }
> +               pr_err(GHES_PFX "Registered SSE notification on vector %d\n",
> +                      generic->notify.vector);

This needs to be pr_info() instead of pr_err().

> +               break;
>         default:
>                 BUG();
>         }
> @@ -1804,7 +1887,6 @@ static int ghes_probe(struct platform_device *ghes_dev)
>
>  static void ghes_remove(struct platform_device *ghes_dev)
>  {
> -       int rc;
>         struct ghes *ghes;
>         struct acpi_hest_generic *generic;
>
> @@ -1838,16 +1920,11 @@ static void ghes_remove(struct platform_device *ghes_dev)
>                 ghes_nmi_remove(ghes);
>                 break;
>         case ACPI_HEST_NOTIFY_SOFTWARE_DELEGATED:
> -               rc = apei_sdei_unregister_ghes(ghes);
> -               if (rc) {
> -                       /*
> -                        * Returning early results in a resource leak, but we're
> -                        * only here if stopping the hardware failed.
> -                        */
> -                       dev_err(&ghes_dev->dev, "Failed to unregister ghes (%pe)\n",
> -                               ERR_PTR(rc));
> -                       return;
> -               }
> +               apei_sdei_unregister_ghes(ghes);
> +               break;
> +
> +       case ACPI_HEST_NOTIFY_SSE:
> +               apei_sse_unregister_ghes(ghes);
>                 break;
>         default:
>                 BUG();
> --
> 2.43.0
>
>

Regards,
Anup
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.