Re: [RFC PATCH v2 2/5] mpt: Add Smsdid and Smmpt supervisor domain core

Rahul Pathak <[email protected]>
Newsgroups org.infradead.lists.opensbi
Message-ID <CAFR3w34PZq2jCg2vZcZKm8OY3jtSHkXgz0o+c5CTZw4tMm6PNA@mail.gmail.com>
On Fri, Aug 14, 2026 at 11:58 PM Pawandeep Oza
<[email protected]> wrote:
>
> On Mon, Jul 27, 2026 at 6:56 AM Rahul Pathak
> <[email protected]> wrote:
> >
> > Introduce the supervisord omain memory-protection (Smmpt) table
> Oza: typo: "supervisord omain"

Rahul: Sure, will update

> > management core. This adds the mode agnostic core layer and the
> > per mode table walkers/builder.
> >
> > Add defines for the mmpt CSR encoding, MPTE bit layout, permission flags,
> > structures, fence helpers and the public interfaces.
> >
> > It implements the RV64 supported modes (Smmpt43/52/64) and
> > the RV32 mode (Smmpt34), its MPT table support.
> >
> > Also implements mpt core which integrates Smmpt with SBI domains and
> > other core layers.
> >
> > Signed-off-by: Rahul Pathak <[email protected]>
> > ---
> >  include/sbi/sbi_mpt.h  | 334 ++++++++++++++
> >  lib/sbi/objects.mk     |   2 +
> >  lib/sbi/sbi_mpt.c      | 926 ++++++++++++++++++++++++++++++++++++++
> >  lib/sbi/sbi_mpt_mode.c | 997 +++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 2259 insertions(+)
> >  create mode 100644 include/sbi/sbi_mpt.h
> >  create mode 100644 lib/sbi/sbi_mpt.c
> >  create mode 100644 lib/sbi/sbi_mpt_mode.c
> >
> > +       return xwr;
> > +}
> > +
> > +/*
> > + * sbi_mpt_domain_create(): Create a Supervisor Domain
> Oza: "Create a Supervisor Domain" ?  You probably meant "Create an mpt domain" !

Rahul: Yes, will change

>
> > + */
> > +int sbi_mpt_domain_create(const struct sbi_mpt_domain_config *cfg,
> > +                          u32 *out_sdid)
> > +{
> > +       int rc;
> > +       u32 sdid, i;
> > +       unsigned long root_pa;
> > +       struct sbi_mpt_mode *sch;
> > +       struct sbi_mpt_domain *dom;
> > +       const struct sbi_domain_memregion *mr;
> > +       struct sbi_mpt_ctrl *ctrl = &mpt_ctrl;
> > +       u8 base_xwr = SBI_MPT_PERM_NONE;
> > +
> > +       if (!ctrl->ready)
> > +               return SBI_ENODEV;
> > +
> > +       if (cfg->sbi_dom && cfg->nregions) {
> > +               sbi_printf("sbi_mpt: sbi_dom and explicit regions are mutually exclusive\n");
> > +               return SBI_EINVAL;
> > +       }
> > +
> > +       /*
> > +        * sdid_bitmap empty means every available SDID is
> > +        * currently in use and no domain can be created.
> > +        */
> > +       if (bitmap_empty(ctrl->sdid_bitmap, ctrl->max_domains))
> > +               return SBI_ENOMEM;
> > +
> > +       sch = ctrl->mode;
> > +
> > +       root_pa = sbi_mpt_pool_alloc(sch->root_table_size(),
> > +                                    sch->root_table_align());
> > +       if (!root_pa) {
        rv64_write_mpte(grp_base + i * RV64_MPTE_SIZE, leaf);
> > +}
> > +
> > +/*
> > + * MPT table best-level selection
> > + *
> > + * Returns the highest level at which the range [pa, pa+size] can be
> > + * covered by a single leaf MPTE. Level 0 is always valid because thats
> > + * the last resort.
> > + */
> > +static u32 rv64_best_level(unsigned long pa, unsigned long size,
> > +                          u32 top_level)
> > +{
> > +       u32 lvl;
> > +       unsigned long range;
> Oza: need to validate ?? or trust top_level her ?
> if (!top_level) return 0;

Rahul: This if condition will be redundant since below for
loop will not enter if top_level == 0

> > +
> > +       for (lvl = top_level; lvl >= 1; lvl--) {
> > +               range = rv64_mpte_range(lvl);
> > +
> > +               if (size >= range && (pa & (range - 1)) == 0)
> > +                       return lvl;
> > +       }
> > +       return 0;
> > +}
> > +
> > +/*
> > + * Generic N-level walk with lazy table allocation
> > + */
> > +static unsigned long rv64_split_leaf(unsigned long parent_ep)
> > +{
> > +       u64 parent = rv64_read_mpte(parent_ep);
> > +       unsigned long sub;
> > +       u32 j, pg, sh;
> > +       u8 xwr;
> > +       u64 child;
> > +
> > +       sub = sbi_mpt_pool_alloc(RV64_TABLE_SIZE, SBI_MPT_PAGE_SIZE);
> > +       if (!sub)
> > +               return 0;
> > +
> > +       for (j = 0; j < RV64_INNER_ENTRIES; j++) {
> > +               sh = sbi_mpte_xwr_shift(j >> 5);
> Oza: can we define 5 ?

Rahul: Sure, will define a macro for it

> > +               xwr = (((unsigned long)parent >> sh) & SBI_MPTE_XWR_MASK);
> > +               child = SBI_MPTE_V | SBI_MPTE_L; /* N=0 uniform leaf */
> > +
> > +               for (pg = 0; pg < RV64_PAGES_PER_MPTE; pg++)
> > +                       child = sbi_mpte_leaf_set_xwr(child, pg, xwr);
> > +
> > +               rv64_write_mpte(sub + j * RV64_MPTE_SIZE, child);
> > +       }
> > +
> > +       /* parent leaf -> non-leaf pointer to MPT sub table. */
> > +       rv64_write_mpte(parent_ep, sbi_mpte_nonleaf(sub));
> > +
> > +       return sub;
> > +}
> > +
> > +/*
> > + * Walk a MPT table and return MPTE PA and its suitable level
> > + */
> > +static unsigned long rv64_walk_alloc(struct sbi_mpt_domain *dom,
> > +                                    unsigned long pa,
> > +                                    unsigned long size,
> > +                                    u32 *out_level,
> > +                                    u32 top_level)
> > +{
> > +       u32 lvl, idx;
> > +       u64 mpte;
> > +       unsigned long ep, sub, new_pa;
> > +       const struct sbi_mpt_mode *sch = dom->mode;
> > +       unsigned long table_pa = dom->root_pa;
> > +       u32 best_lvl = rv64_best_level(pa, size, top_level);
> > +
> > +
> > +       for (lvl = top_level; lvl >= 1; lvl--) {
> > +               idx = rv64_table_idx(pa, lvl, sch);
> > +               ep = rv64_mpte_pa(table_pa, idx);
> > +               mpte = rv64_read_mpte(ep);
> > +
> > +               if (mpte & SBI_MPTE_L) {
> > +                       if (lvl > best_lvl) {
> > +                               sub = rv64_split_leaf(ep);
> > +                               if (!sub)
> > +                                       return 0;
> > +
> > +                               table_pa = sub;
> Oza: do you need to decrement lvl here since you are splitting ?  e.g. lvl--

Rahul: below continue make sure that lvl is decremented in next pass of for loop
Do you mean I have to decrement lvl again here though due to below continue,
it will be decremented twice?

>
> > +                               continue;
> > +                       }
> > +
> > +                       *out_level = lvl;
> > +                       return ep;
> > +               }
> > +
> > +               if (!(mpte & SBI_MPTE_V)) {
> > +                       if (lvl <= best_lvl) {
> > +                               *out_level = lvl;
> > +                               return ep;
> > +                       }
> > +                       /* Allocate inner table (always 4KiB, all levels, all modes) */
> > +                       new_pa = sbi_mpt_pool_alloc(RV64_TABLE_SIZE,
> > +                                                   SBI_MPT_PAGE_SIZE);
> > +                       if (!new_pa)
> > +                               return 0;
> > +
> > +                       rv64_write_mpte(ep, (u64)sbi_mpte_nonleaf(new_pa));
> > +                       table_pa = new_pa;
> > +               }
> > +               else {
> > +                       table_pa = rv64_next_table_pa(mpte);
> > +               }
> > +       }
> > +
> > +       *out_level = 0;
> > +
> > +       return rv64_mpte_pa(table_pa, rv64_table_idx(pa, 0, sch));
> > +}
> > +

-- 
opensbi mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/opensbi
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.