[RFC PATCH v7 2/6] lib: sbi: Introduce memory class for memory type hart protection

Anup Patel anup at brainfault.org
Tue Nov 10 03:24:28 PST 2026


On Mon, Nov 2, 2026 at 10:04 AM Rahul Pathak
<rahul.pathak at oss.qualcomm.com> wrote:
>
> In TYPE_MEMORY type mechanisms, some of the hart protection
> mechanisms can be exclusive and other can work as an addon
> with the other TYPE_MEMORY type mechanisms. For example, in
> PMP, SMEPMP and SMSD which are currently the TYPE_MEMORY
> type protection mechanisms, the PMP and SMEPMP are exclusive
> to each other and the SMSD if present will work together with
> PMP or SMEPMP. So it will be either PMP+SMSD or SMEPMP+SMSD.

This memory class attribute in hart_protection does not really
help us reduce PMP regions when SMSD is present.

PMP+SMSD or SMEPMP + SMSD is supposed to be composite
hart_protection which programs both PMP and SMSD such that
it only programs PMP for M-only and M+S regions and enforcement
of S-only regions is only through MPT.

I suggest dropping this patch and extending your SMSD hart
protection to use PMP at appropriate places for M-only and M+S
regions whereas use MPT for other regions.

>
> For such configurations selection, add memory class in which
> types within same memory class are exclusive but other types
> in different memory class selected will work together.
>
> Signed-off-by: Rahul Pathak <rahul.pathak at oss.qualcomm.com>
> ---
>  include/sbi/sbi_hart_protection.h | 20 ++++++++
>  lib/sbi/sbi_hart_pmp.c            |  2 +
>  lib/sbi/sbi_hart_protection.c     | 84 ++++++++++++-------------------
>  3 files changed, 53 insertions(+), 53 deletions(-)
>
> diff --git a/include/sbi/sbi_hart_protection.h b/include/sbi/sbi_hart_protection.h
> index bdcad0080baf..fee5063ca167 100644
> --- a/include/sbi/sbi_hart_protection.h
> +++ b/include/sbi/sbi_hart_protection.h
> @@ -20,6 +20,23 @@ enum sbi_hart_protection_type {
>         SBI_HART_PROTECTION_TYPE_MAX
>  };
>
> +/**
> + * Hart protection class for memory protection.
> + *
> + * Memory protection mechanisms of the same class use the same
> + * hardware for memory access which makes them mutually exclusive and
> + * among those the rating will choose which one is active.
> + * Mechanisms of different classes can work together so a hart can have
> + * PMP + MPT or ePMP + MPT.
> + */
> +enum sbi_hart_protection_memory_class {
> +       /** PMP CSRs: pmp, epmp */
> +       SBI_HART_PROTECTION_MEMORY_CLASS_PMP = 0,
> +       /** mmpt CSR: MPT (Smsd) */
> +       SBI_HART_PROTECTION_MEMORY_CLASS_MPT,
> +       SBI_HART_PROTECTION_MEMORY_CLASS_MAX
> +};
> +
>  /** Representation of hart protection mechanism */
>  struct sbi_hart_protection {
>         /** List head */
> @@ -31,6 +48,9 @@ struct sbi_hart_protection {
>         /** Type of the hart protection mechanism */
>         enum sbi_hart_protection_type type;
>
> +       /** Hardware programmed by the mechanism */
> +       enum sbi_hart_protection_memory_class memory_class;
> +
>         /** Ratings of the hart protection mechanism (higher is better) */
>         unsigned long rating;
>
> diff --git a/lib/sbi/sbi_hart_pmp.c b/lib/sbi/sbi_hart_pmp.c
> index c530739f8c46..e60dbdcfca0a 100644
> --- a/lib/sbi/sbi_hart_pmp.c
> +++ b/lib/sbi/sbi_hart_pmp.c
> @@ -426,6 +426,7 @@ static struct sbi_hart_protection pmp_protection = {
>         .name = "pmp",
>         .rating = 100,
>         .type = SBI_HART_PROTECTION_TYPE_MEMORY,
> +       .memory_class = SBI_HART_PROTECTION_MEMORY_CLASS_PMP,
>         .configure = sbi_hart_oldpmp_configure,
>         .unconfigure = sbi_hart_pmp_unconfigure,
>  };
> @@ -434,6 +435,7 @@ static struct sbi_hart_protection epmp_protection = {
>         .name = "epmp",
>         .rating = 200,
>         .type = SBI_HART_PROTECTION_TYPE_MEMORY,
> +       .memory_class = SBI_HART_PROTECTION_MEMORY_CLASS_PMP,
>         .configure = sbi_hart_smepmp_configure,
>         .unconfigure = sbi_hart_pmp_unconfigure,
>         .temp_map_range = sbi_hart_smepmp_temp_map_range,
> diff --git a/lib/sbi/sbi_hart_protection.c b/lib/sbi/sbi_hart_protection.c
> index ee4d4beb9087..72ce4e9899cc 100644
> --- a/lib/sbi/sbi_hart_protection.c
> +++ b/lib/sbi/sbi_hart_protection.c
> @@ -12,21 +12,37 @@
>
>  static SBI_LIST_HEAD(hart_protection_list);
>
> -static struct sbi_hart_protection *__hart_memory_protection_best(void)
> +static struct sbi_hart_protection *
> +__hart_memory_protection_best(enum sbi_hart_protection_memory_class memclass)
>  {
>         struct sbi_hart_protection *pos;
>
>         sbi_list_for_each_entry(pos, &hart_protection_list, head) {
> -               if (pos->type == SBI_HART_PROTECTION_TYPE_MEMORY)
> +               if (pos->type == SBI_HART_PROTECTION_TYPE_MEMORY &&
> +                   pos->memory_class == memclass)
>                         return pos;
>         }
>
>         return NULL;
>  }
>
> +/*
> + * Select the highest rating protection mechanism from each class
> + */
> +static bool __hart_protection_selected(struct sbi_hart_protection *hprot)
> +{
> +       switch (hprot->type) {
> +       case SBI_HART_PROTECTION_TYPE_MEMORY:
> +               return hprot == __hart_memory_protection_best(hprot->memory_class);
> +       case SBI_HART_PROTECTION_TYPE_ID:
> +               return true;
> +       default:
> +               return false;
> +       }
> +}
> +
>  void sbi_hart_protection_get_str(char *out_str, int out_str_size)
>  {
> -       bool memory_protect_done = false;
>         struct sbi_hart_protection *pos;
>         int offset = 0;
>
> @@ -35,11 +51,8 @@ void sbi_hart_protection_get_str(char *out_str, int out_str_size)
>         sbi_memset(out_str, 0, out_str_size);
>
>         sbi_list_for_each_entry(pos, &hart_protection_list, head) {
> -               if (pos->type == SBI_HART_PROTECTION_TYPE_MEMORY) {
> -                       if (memory_protect_done)
> -                               continue;
> -                       memory_protect_done = true;
> -               }
> +               if (!__hart_protection_selected(pos))
> +                       continue;
>                 sbi_snprintf(out_str + offset, out_str_size - offset, "%s,", pos->name);
>                 offset = offset + sbi_strlen(pos->name) + 1;
>         }
> @@ -59,6 +72,9 @@ int sbi_hart_protection_register(struct sbi_hart_protection *hprot)
>                 return SBI_EINVAL;
>         if (hprot->type >= SBI_HART_PROTECTION_TYPE_MAX)
>                 return SBI_EINVAL;
> +       if (hprot->type == SBI_HART_PROTECTION_TYPE_MEMORY &&
> +           hprot->memory_class >= SBI_HART_PROTECTION_MEMORY_CLASS_MAX)
> +               return SBI_EINVAL;
>
>         sbi_list_for_each_entry(pos, &hart_protection_list, head) {
>                 if (hprot->rating > pos->rating) {
> @@ -108,24 +124,11 @@ static void __hart_protection_unconfigure(struct sbi_scratch *scratch,
>  int sbi_hart_protection_configure(struct sbi_scratch *scratch,
>                                   struct sbi_domain *dom)
>  {
> -       bool do_configure, memory_protect_done = false;
>         struct sbi_hart_protection *hprot;
>         int ret;
>
>         sbi_list_for_each_entry(hprot, &hart_protection_list, head) {
> -               do_configure = false;
> -               switch (hprot->type) {
> -               case SBI_HART_PROTECTION_TYPE_MEMORY:
> -                       do_configure = !memory_protect_done;
> -                       memory_protect_done = true;
> -                       break;
> -               case SBI_HART_PROTECTION_TYPE_ID:
> -                       do_configure = true;
> -                       break;
> -               default:
> -                       break;
> -               }
> -               if (!do_configure)
> +               if (!__hart_protection_selected(hprot))
>                         continue;
>
>                 ret = __hart_protection_configure(scratch, hprot, dom);
> @@ -139,24 +142,10 @@ int sbi_hart_protection_configure(struct sbi_scratch *scratch,
>  void sbi_hart_protection_unconfigure(struct sbi_scratch *scratch,
>                                      struct sbi_domain *dom)
>  {
> -
> -       bool do_unconfigure, memory_protect_done = false;
>         struct sbi_hart_protection *hprot;
>
>         sbi_list_for_each_entry(hprot, &hart_protection_list, head) {
> -               do_unconfigure = false;
> -               switch (hprot->type) {
> -               case SBI_HART_PROTECTION_TYPE_MEMORY:
> -                       do_unconfigure = !memory_protect_done;
> -                       memory_protect_done = true;
> -                       break;
> -               case SBI_HART_PROTECTION_TYPE_ID:
> -                       do_unconfigure = true;
> -                       break;
> -               default:
> -                       break;
> -               }
> -               if (!do_unconfigure)
> +               if (!__hart_protection_selected(hprot))
>                         continue;
>
>                 __hart_protection_unconfigure(scratch, hprot, dom);
> @@ -167,24 +156,11 @@ int sbi_hart_protection_reconfigure(struct sbi_scratch *scratch,
>                                     struct sbi_domain *current_dom,
>                                     struct sbi_domain *next_dom)
>  {
> -       bool do_reconfigure, memory_protect_done = false;
>         struct sbi_hart_protection *hprot;
>         int ret;
>
>         sbi_list_for_each_entry(hprot, &hart_protection_list, head) {
> -               do_reconfigure = false;
> -               switch (hprot->type) {
> -               case SBI_HART_PROTECTION_TYPE_MEMORY:
> -                       do_reconfigure = !memory_protect_done;
> -                       memory_protect_done = true;
> -                       break;
> -               case SBI_HART_PROTECTION_TYPE_ID:
> -                       do_reconfigure = true;
> -                       break;
> -               default:
> -                       break;
> -               }
> -               if (!do_reconfigure)
> +               if (!__hart_protection_selected(hprot))
>                         continue;
>
>                 __hart_protection_unconfigure(scratch, hprot, current_dom);
> @@ -198,7 +174,8 @@ int sbi_hart_protection_reconfigure(struct sbi_scratch *scratch,
>
>  int sbi_hart_protection_temp_map_range(unsigned long base, unsigned long size)
>  {
> -       struct sbi_hart_protection *hprot = __hart_memory_protection_best();
> +       struct sbi_hart_protection *hprot =
> +               __hart_memory_protection_best(SBI_HART_PROTECTION_MEMORY_CLASS_PMP);
>
>         if (!hprot || !hprot->temp_map_range)
>                 return 0;
> @@ -208,7 +185,8 @@ int sbi_hart_protection_temp_map_range(unsigned long base, unsigned long size)
>
>  int sbi_hart_protection_temp_unmap_range(unsigned long base, unsigned long size)
>  {
> -       struct sbi_hart_protection *hprot = __hart_memory_protection_best();
> +       struct sbi_hart_protection *hprot =
> +               __hart_memory_protection_best(SBI_HART_PROTECTION_MEMORY_CLASS_PMP);
>
>         if (!hprot || !hprot->temp_unmap_range)
>                 return 0;
> --
> 2.53.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

Regards,
Anup



More information about the opensbi mailing list