summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/sbi/sbi_domain.c60
1 files changed, 38 insertions, 22 deletions
diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c
index 71cb381f..88d25deb 100644
--- a/lib/sbi/sbi_domain.c
+++ b/lib/sbi/sbi_domain.c
@@ -193,12 +193,11 @@ static bool is_region_subset(const struct sbi_domain_memregion *regA,
return false;
}
-/** Check if regionA conflicts regionB */
-static bool is_region_conflict(const struct sbi_domain_memregion *regA,
- const struct sbi_domain_memregion *regB)
+/** Check if regionA can be replaced by regionB */
+static bool is_region_compatible(const struct sbi_domain_memregion *regA,
+ const struct sbi_domain_memregion *regB)
{
- if ((is_region_subset(regA, regB) || is_region_subset(regB, regA)) &&
- regA->flags == regB->flags)
+ if (is_region_subset(regA, regB) && regA->flags == regB->flags)
return true;
return false;
@@ -266,9 +265,15 @@ static void swap_region(struct sbi_domain_memregion* reg1,
sbi_memcpy(reg2, &treg, sizeof(treg));
}
+static void clear_region(struct sbi_domain_memregion* reg)
+{
+ sbi_memset(reg, 0x0, sizeof(*reg));
+}
+
static int sanitize_domain(struct sbi_domain *dom)
{
u32 i, j, count;
+ bool is_covered;
struct sbi_domain_memregion *reg, *reg1;
/* Check possible HARTs */
@@ -320,16 +325,6 @@ static int sanitize_domain(struct sbi_domain *dom)
for (j = i + 1; j < count; j++) {
reg1 = &dom->regions[j];
- if (is_region_conflict(reg1, reg)) {
- sbi_printf("%s: %s conflict between regions "
- "(base=0x%lx order=%lu flags=0x%lx) and "
- "(base=0x%lx order=%lu flags=0x%lx)\n",
- __func__, dom->name,
- reg->base, reg->order, reg->flags,
- reg1->base, reg1->order, reg1->flags);
- return SBI_EINVAL;
- }
-
if (!is_region_before(reg1, reg))
continue;
@@ -337,6 +332,31 @@ static int sanitize_domain(struct sbi_domain *dom)
}
}
+ /* Remove covered regions */
+ while(i < (count - 1)) {
+ is_covered = false;
+ reg = &dom->regions[i];
+
+ for (j = i + 1; j < count; j++) {
+ reg1 = &dom->regions[j];
+
+ if (is_region_compatible(reg, reg1)) {
+ is_covered = true;
+ break;
+ }
+ }
+
+ /* find a region is superset of reg, remove reg */
+ if (is_covered) {
+ for (j = i; j < (count - 1); j++)
+ swap_region(&dom->regions[j],
+ &dom->regions[j + 1]);
+ clear_region(&dom->regions[count - 1]);
+ count--;
+ } else
+ i++;
+ }
+
/*
* We don't need to check boot HART id of domain because if boot
* HART id is not possible/assigned to this domain then it won't
@@ -576,14 +596,10 @@ int sbi_domain_root_add_memregion(const struct sbi_domain_memregion *reg)
(ROOT_REGION_MAX <= root_memregs_count))
return SBI_EINVAL;
- /* Check for conflicts */
+ /* Check whether compatible region exists for the new one */
sbi_domain_for_each_memregion(&root, nreg) {
- if (is_region_conflict(reg, nreg)) {
- sbi_printf("%s: is_region_conflict check failed"
- " 0x%lx conflicts existing 0x%lx\n", __func__,
- reg->base, nreg->base);
- return SBI_EALREADY;
- }
+ if (is_region_compatible(reg, nreg))
+ return 0;
}
/* Append the memregion to root memregions */