[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