mirror of
https://github.com/Fishwaldo/opensbi.git
synced 2025-03-15 19:31:32 +00:00
lib: sbi: Add sbi_domain_check_addr_range() function
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> Reviewed-by: Atish Patra <atishp@rivosinc.com> Reviewed-by: Xiang W <wxjstz@126.com> Reviewed-by: Bin Meng <bmeng@tinylab.org> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
This commit is contained in:
parent
4e0572f57b
commit
eab48c33a1
2 changed files with 84 additions and 0 deletions
|
@ -196,6 +196,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);
|
||||
|
||||
|
|
|
@ -212,6 +212,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)
|
||||
{
|
||||
|
@ -320,6 +358,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;
|
||||
|
|
Loading…
Add table
Reference in a new issue