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;
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 */
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;
}
}
+ /* 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
(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 */