Message ID | 20221124132906.257732-4-apatel@ventanamicro.com |
---|---|
State | Superseded |
Headers | show |
Series | OpenSBI debug console support | expand |
在 2022-11-24星期四的 18:59 +0530,Anup Patel写道: > We add sbi_domain_check_addr_range() helper function to check > whether a given address range is accessible under a particular > domain. > > Signed-off-by: Anup Patel <apatel@ventanamicro.com> Look good to me Reviewed-by: Xiang W <wxjstz@126.com> > --- > include/sbi/sbi_domain.h | 15 +++++++++ > lib/sbi/sbi_domain.c | 69 ++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 84 insertions(+) > > diff --git a/include/sbi/sbi_domain.h b/include/sbi/sbi_domain.h > index 5553d21..4afcc37 100644 > --- a/include/sbi/sbi_domain.h > +++ b/include/sbi/sbi_domain.h > @@ -154,6 +154,21 @@ bool sbi_domain_check_addr(const struct sbi_domain *dom, > unsigned long addr, unsigned long mode, > unsigned long access_flags); > > +/** > + * Check whether we can access specified address range for given mode and > + * memory region flags under a domain > + * @param dom pointer to domain > + * @param addr the start of the address range to be checked > + * @param size the size of the address range to be checked > + * @param mode the privilege mode of access > + * @param access_flags bitmask of domain access types (enum sbi_domain_access) > + * @return TRUE if access allowed otherwise FALSE > + */ > +bool sbi_domain_check_addr_range(const struct sbi_domain *dom, > + unsigned long addr, unsigned long size, > + unsigned long mode, > + unsigned long access_flags); > + > /** Dump domain details on the console */ > void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix); > > diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c > index f24a8e5..11a547c 100644 > --- a/lib/sbi/sbi_domain.c > +++ b/lib/sbi/sbi_domain.c > @@ -195,6 +195,44 @@ static bool is_region_before(const struct sbi_domain_memregion *regA, > return FALSE; > } > > +static const struct sbi_domain_memregion *find_region( > + const struct sbi_domain *dom, > + unsigned long addr) > +{ > + unsigned long rstart, rend; > + struct sbi_domain_memregion *reg; > + > + sbi_domain_for_each_memregion(dom, reg) { > + rstart = reg->base; > + rend = (reg->order < __riscv_xlen) ? > + rstart + ((1UL << reg->order) - 1) : -1UL; > + if (rstart <= addr && addr <= rend) > + return reg; > + } > + > + return NULL; > +} > + > +static const struct sbi_domain_memregion *find_next_subset_region( > + const struct sbi_domain *dom, > + const struct sbi_domain_memregion *reg, > + unsigned long addr) > +{ > + struct sbi_domain_memregion *sreg, *ret = NULL; > + > + sbi_domain_for_each_memregion(dom, sreg) { > + if (sreg == reg || (sreg->base <= addr) || > + !is_region_subset(sreg, reg)) > + continue; > + > + if (!ret || (sreg->base < ret->base) || > + ((sreg->base == ret->base) && (sreg->order < ret->order))) > + ret = sreg; > + } > + > + return ret; > +} > + > static int sanitize_domain(const struct sbi_platform *plat, > struct sbi_domain *dom) > { > @@ -303,6 +341,37 @@ static int sanitize_domain(const struct sbi_platform *plat, > return 0; > } > > +bool sbi_domain_check_addr_range(const struct sbi_domain *dom, > + unsigned long addr, unsigned long size, > + unsigned long mode, > + unsigned long access_flags) > +{ > + unsigned long max = addr + size; > + const struct sbi_domain_memregion *reg, *sreg; > + > + if (!dom) > + return FALSE; > + > + while (addr < max) { > + reg = find_region(dom, addr); > + if (!reg) > + return FALSE; > + > + if (!sbi_domain_check_addr(dom, addr, mode, access_flags)) > + return FALSE; > + > + sreg = find_next_subset_region(dom, reg, addr); > + if (sreg) > + addr = sreg->base; > + else if (reg->order < __riscv_xlen) > + addr = reg->base + (1UL << reg->order); > + else > + break; > + } > + > + return TRUE; > +} > + > void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix) > { > u32 i, k; > -- > 2.34.1 > >
On Thu, Nov 24, 2022 at 9:32 PM Anup Patel <apatel@ventanamicro.com> wrote: > > We add sbi_domain_check_addr_range() helper function to check > whether a given address range is accessible under a particular > domain. > > Signed-off-by: Anup Patel <apatel@ventanamicro.com> > --- > include/sbi/sbi_domain.h | 15 +++++++++ > lib/sbi/sbi_domain.c | 69 ++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 84 insertions(+) > > diff --git a/include/sbi/sbi_domain.h b/include/sbi/sbi_domain.h > index 5553d21..4afcc37 100644 > --- a/include/sbi/sbi_domain.h > +++ b/include/sbi/sbi_domain.h > @@ -154,6 +154,21 @@ bool sbi_domain_check_addr(const struct sbi_domain *dom, > unsigned long addr, unsigned long mode, > unsigned long access_flags); > > +/** > + * Check whether we can access specified address range for given mode and > + * memory region flags under a domain > + * @param dom pointer to domain > + * @param addr the start of the address range to be checked > + * @param size the size of the address range to be checked > + * @param mode the privilege mode of access > + * @param access_flags bitmask of domain access types (enum sbi_domain_access) > + * @return TRUE if access allowed otherwise FALSE > + */ > +bool sbi_domain_check_addr_range(const struct sbi_domain *dom, > + unsigned long addr, unsigned long size, > + unsigned long mode, > + unsigned long access_flags); > + > /** Dump domain details on the console */ > void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix); > > diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c > index f24a8e5..11a547c 100644 > --- a/lib/sbi/sbi_domain.c > +++ b/lib/sbi/sbi_domain.c > @@ -195,6 +195,44 @@ static bool is_region_before(const struct sbi_domain_memregion *regA, > return FALSE; > } > > +static const struct sbi_domain_memregion *find_region( > + const struct sbi_domain *dom, > + unsigned long addr) > +{ > + unsigned long rstart, rend; > + struct sbi_domain_memregion *reg; > + > + sbi_domain_for_each_memregion(dom, reg) { > + rstart = reg->base; > + rend = (reg->order < __riscv_xlen) ? > + rstart + ((1UL << reg->order) - 1) : -1UL; > + if (rstart <= addr && addr <= rend) addr < rend? > + return reg; > + } > + > + return NULL; > +} > + > +static const struct sbi_domain_memregion *find_next_subset_region( > + const struct sbi_domain *dom, > + const struct sbi_domain_memregion *reg, > + unsigned long addr) > +{ > + struct sbi_domain_memregion *sreg, *ret = NULL; > + > + sbi_domain_for_each_memregion(dom, sreg) { > + if (sreg == reg || (sreg->base <= addr) || > + !is_region_subset(sreg, reg)) > + continue; > + > + if (!ret || (sreg->base < ret->base) || > + ((sreg->base == ret->base) && (sreg->order < ret->order))) > + ret = sreg; > + } > + > + return ret; > +} > + > static int sanitize_domain(const struct sbi_platform *plat, > struct sbi_domain *dom) > { > @@ -303,6 +341,37 @@ static int sanitize_domain(const struct sbi_platform *plat, > return 0; > } > > +bool sbi_domain_check_addr_range(const struct sbi_domain *dom, > + unsigned long addr, unsigned long size, > + unsigned long mode, > + unsigned long access_flags) > +{ > + unsigned long max = addr + size; > + const struct sbi_domain_memregion *reg, *sreg; > + > + if (!dom) > + return FALSE; > + > + while (addr < max) { > + reg = find_region(dom, addr); > + if (!reg) > + return FALSE; > + > + if (!sbi_domain_check_addr(dom, addr, mode, access_flags)) > + return FALSE; > + > + sreg = find_next_subset_region(dom, reg, addr); > + if (sreg) > + addr = sreg->base; > + else if (reg->order < __riscv_xlen) > + addr = reg->base + (1UL << reg->order); > + else > + break; > + } > + > + return TRUE; > +} > + > void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix) > { > u32 i, k; Regards, Bin
On Wed, Dec 21, 2022 at 5:30 PM Bin Meng <bmeng.cn@gmail.com> wrote: > > On Thu, Nov 24, 2022 at 9:32 PM Anup Patel <apatel@ventanamicro.com> wrote: > > > > We add sbi_domain_check_addr_range() helper function to check > > whether a given address range is accessible under a particular > > domain. > > > > Signed-off-by: Anup Patel <apatel@ventanamicro.com> > > --- > > include/sbi/sbi_domain.h | 15 +++++++++ > > lib/sbi/sbi_domain.c | 69 ++++++++++++++++++++++++++++++++++++++++ > > 2 files changed, 84 insertions(+) > > > > diff --git a/include/sbi/sbi_domain.h b/include/sbi/sbi_domain.h > > index 5553d21..4afcc37 100644 > > --- a/include/sbi/sbi_domain.h > > +++ b/include/sbi/sbi_domain.h > > @@ -154,6 +154,21 @@ bool sbi_domain_check_addr(const struct sbi_domain *dom, > > unsigned long addr, unsigned long mode, > > unsigned long access_flags); > > > > +/** > > + * Check whether we can access specified address range for given mode and > > + * memory region flags under a domain > > + * @param dom pointer to domain > > + * @param addr the start of the address range to be checked > > + * @param size the size of the address range to be checked > > + * @param mode the privilege mode of access > > + * @param access_flags bitmask of domain access types (enum sbi_domain_access) > > + * @return TRUE if access allowed otherwise FALSE > > + */ > > +bool sbi_domain_check_addr_range(const struct sbi_domain *dom, > > + unsigned long addr, unsigned long size, > > + unsigned long mode, > > + unsigned long access_flags); > > + > > /** Dump domain details on the console */ > > void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix); > > > > diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c > > index f24a8e5..11a547c 100644 > > --- a/lib/sbi/sbi_domain.c > > +++ b/lib/sbi/sbi_domain.c > > @@ -195,6 +195,44 @@ static bool is_region_before(const struct sbi_domain_memregion *regA, > > return FALSE; > > } > > > > +static const struct sbi_domain_memregion *find_region( > > + const struct sbi_domain *dom, > > + unsigned long addr) > > +{ > > + unsigned long rstart, rend; > > + struct sbi_domain_memregion *reg; > > + > > + sbi_domain_for_each_memregion(dom, reg) { > > + rstart = reg->base; > > + rend = (reg->order < __riscv_xlen) ? > > + rstart + ((1UL << reg->order) - 1) : -1UL; > > + if (rstart <= addr && addr <= rend) > > addr < rend? Never mind. Looks good. > > > + return reg; > > + } > > + > > + return NULL; > > +} > > + > > +static const struct sbi_domain_memregion *find_next_subset_region( > > + const struct sbi_domain *dom, > > + const struct sbi_domain_memregion *reg, > > + unsigned long addr) > > +{ > > + struct sbi_domain_memregion *sreg, *ret = NULL; > > + > > + sbi_domain_for_each_memregion(dom, sreg) { > > + if (sreg == reg || (sreg->base <= addr) || > > + !is_region_subset(sreg, reg)) > > + continue; > > + > > + if (!ret || (sreg->base < ret->base) || > > + ((sreg->base == ret->base) && (sreg->order < ret->order))) > > + ret = sreg; > > + } > > + > > + return ret; > > +} > > + > > static int sanitize_domain(const struct sbi_platform *plat, > > struct sbi_domain *dom) > > { > > @@ -303,6 +341,37 @@ static int sanitize_domain(const struct sbi_platform *plat, > > return 0; > > } > > > > +bool sbi_domain_check_addr_range(const struct sbi_domain *dom, > > + unsigned long addr, unsigned long size, > > + unsigned long mode, > > + unsigned long access_flags) > > +{ > > + unsigned long max = addr + size; > > + const struct sbi_domain_memregion *reg, *sreg; > > + > > + if (!dom) > > + return FALSE; > > + > > + while (addr < max) { > > + reg = find_region(dom, addr); > > + if (!reg) > > + return FALSE; > > + > > + if (!sbi_domain_check_addr(dom, addr, mode, access_flags)) > > + return FALSE; > > + > > + sreg = find_next_subset_region(dom, reg, addr); > > + if (sreg) > > + addr = sreg->base; > > + else if (reg->order < __riscv_xlen) > > + addr = reg->base + (1UL << reg->order); > > + else > > + break; > > + } > > + > > + return TRUE; > > +} > > + > > void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix) > > { > > u32 i, k; > Reviewed-by: Bin Meng <bmeng@tinylab.org>
diff --git a/include/sbi/sbi_domain.h b/include/sbi/sbi_domain.h index 5553d21..4afcc37 100644 --- a/include/sbi/sbi_domain.h +++ b/include/sbi/sbi_domain.h @@ -154,6 +154,21 @@ bool sbi_domain_check_addr(const struct sbi_domain *dom, unsigned long addr, unsigned long mode, unsigned long access_flags); +/** + * Check whether we can access specified address range for given mode and + * memory region flags under a domain + * @param dom pointer to domain + * @param addr the start of the address range to be checked + * @param size the size of the address range to be checked + * @param mode the privilege mode of access + * @param access_flags bitmask of domain access types (enum sbi_domain_access) + * @return TRUE if access allowed otherwise FALSE + */ +bool sbi_domain_check_addr_range(const struct sbi_domain *dom, + unsigned long addr, unsigned long size, + unsigned long mode, + unsigned long access_flags); + /** Dump domain details on the console */ void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix); diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c index f24a8e5..11a547c 100644 --- a/lib/sbi/sbi_domain.c +++ b/lib/sbi/sbi_domain.c @@ -195,6 +195,44 @@ static bool is_region_before(const struct sbi_domain_memregion *regA, return FALSE; } +static const struct sbi_domain_memregion *find_region( + const struct sbi_domain *dom, + unsigned long addr) +{ + unsigned long rstart, rend; + struct sbi_domain_memregion *reg; + + sbi_domain_for_each_memregion(dom, reg) { + rstart = reg->base; + rend = (reg->order < __riscv_xlen) ? + rstart + ((1UL << reg->order) - 1) : -1UL; + if (rstart <= addr && addr <= rend) + return reg; + } + + return NULL; +} + +static const struct sbi_domain_memregion *find_next_subset_region( + const struct sbi_domain *dom, + const struct sbi_domain_memregion *reg, + unsigned long addr) +{ + struct sbi_domain_memregion *sreg, *ret = NULL; + + sbi_domain_for_each_memregion(dom, sreg) { + if (sreg == reg || (sreg->base <= addr) || + !is_region_subset(sreg, reg)) + continue; + + if (!ret || (sreg->base < ret->base) || + ((sreg->base == ret->base) && (sreg->order < ret->order))) + ret = sreg; + } + + return ret; +} + static int sanitize_domain(const struct sbi_platform *plat, struct sbi_domain *dom) { @@ -303,6 +341,37 @@ static int sanitize_domain(const struct sbi_platform *plat, return 0; } +bool sbi_domain_check_addr_range(const struct sbi_domain *dom, + unsigned long addr, unsigned long size, + unsigned long mode, + unsigned long access_flags) +{ + unsigned long max = addr + size; + const struct sbi_domain_memregion *reg, *sreg; + + if (!dom) + return FALSE; + + while (addr < max) { + reg = find_region(dom, addr); + if (!reg) + return FALSE; + + if (!sbi_domain_check_addr(dom, addr, mode, access_flags)) + return FALSE; + + sreg = find_next_subset_region(dom, reg, addr); + if (sreg) + addr = sreg->base; + else if (reg->order < __riscv_xlen) + addr = reg->base + (1UL << reg->order); + else + break; + } + + return TRUE; +} + void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix) { u32 i, k;
We add sbi_domain_check_addr_range() helper function to check whether a given address range is accessible under a particular domain. Signed-off-by: Anup Patel <apatel@ventanamicro.com> --- include/sbi/sbi_domain.h | 15 +++++++++ lib/sbi/sbi_domain.c | 69 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+)