summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-01-09 10:09:57 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-01-22 07:21:19 +0100
commit9ec5ff4e577c2c06b8a839f090761f55fa70fab8 (patch)
tree383c873c958f0ec6ea5cfd8aeea176f15ebd889e
parentpowerpc: Add FSL_EIS_EPR (diff)
downloadrtems-9ec5ff4e577c2c06b8a839f090761f55fa70fab8.tar.bz2
bsp/qoriq: Fix hypervisor guest MMU config
Account for DPAA resources defined in the device tree. Prevent merging of areas with incompatible MAS2. Update #3085.
-rw-r--r--c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c128
-rw-r--r--c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c98
2 files changed, 188 insertions, 38 deletions
diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c
index 90b0534fa3..91a6240e10 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (c) 2011, 2017 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2011, 2018 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -150,9 +150,103 @@ static entry DATA config[] = {
static DATA char memory_path[] = "/memory";
-static void TEXT config_fdt_adjust(void)
+#ifdef QORIQ_IS_HYPERVISOR_GUEST
+static void TEXT add_dpaa_bqman_portals(
+ qoriq_mmu_context *context,
+ const void *fdt,
+ const char *compatible
+)
+{
+ int node;
+
+ node = -1;
+
+ while (true) {
+ const void *val;
+ int len;
+ uintptr_t paddr;
+ uintptr_t size;
+
+ node = fdt_node_offset_by_compatible(fdt, node, compatible);
+ if (node < 0) {
+ break;
+ }
+
+ val = fdt_getprop(fdt, node, "reg", &len);
+ if (len != 32) {
+ continue;
+ }
+
+ paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[0]);
+ size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[1]);
+
+ qoriq_mmu_add(
+ context,
+ paddr,
+ paddr + size - 1,
+ 0,
+ FSL_EIS_MAS2_M | FSL_EIS_MAS2_G,
+ FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW,
+ QORIQ_MMU_DEVICE_MAS7
+ );
+
+ paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[2]);
+ size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[3]);
+
+ qoriq_mmu_add(
+ context,
+ paddr,
+ paddr + size - 1,
+ 0,
+ FSL_EIS_MAS2_I | FSL_EIS_MAS2_G,
+ FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW,
+ QORIQ_MMU_DEVICE_MAS7
+ );
+ }
+}
+
+static void TEXT add_dpaa_bpool(qoriq_mmu_context *context, const void *fdt)
+{
+ int node;
+
+ node = -1;
+
+ while (true) {
+ const void *val;
+ int len;
+ uintptr_t config_count;
+ uintptr_t size;
+ uintptr_t paddr;
+
+ node = fdt_node_offset_by_compatible(fdt, node, "fsl,bpool");
+ if (node < 0) {
+ break;
+ }
+
+ val = fdt_getprop(fdt, node, "fsl,bpool-ethernet-cfg", &len);
+ if (len != 24) {
+ continue;
+ }
+
+ config_count = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[0]);
+ size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[1]);
+ paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[2]);
+
+ qoriq_mmu_add(
+ context,
+ paddr,
+ paddr + config_count * size - 1,
+ 0,
+ FSL_EIS_MAS2_M,
+ FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW,
+ 0
+ );
+ }
+}
+#endif
+
+static void TEXT config_fdt_adjust(const void *fdt)
{
- const void *fdt = bsp_fdt_get();
int node;
node = fdt_path_offset_namelen(
@@ -198,13 +292,9 @@ static void TEXT config_fdt_adjust(void)
void TEXT qoriq_mmu_config(bool boot_processor, int first_tlb, int scratch_tlb)
{
qoriq_mmu_context context;
- int i = 0;
-
- if (boot_processor) {
- config_fdt_adjust();
- }
-
- qoriq_mmu_context_init(&context);
+ const void *fdt;
+ int max_count;
+ int i;
for (i = 0; i < QORIQ_TLB1_ENTRY_COUNT; ++i) {
if (i != scratch_tlb) {
@@ -212,6 +302,22 @@ void TEXT qoriq_mmu_config(bool boot_processor, int first_tlb, int scratch_tlb)
}
}
+ fdt = bsp_fdt_get();
+ qoriq_mmu_context_init(&context);
+
+#ifdef QORIQ_IS_HYPERVISOR_GUEST
+ add_dpaa_bqman_portals(&context, fdt, "fsl,bman-portal");
+ add_dpaa_bqman_portals(&context, fdt, "fsl,qman-portal");
+ add_dpaa_bpool(&context, fdt);
+ max_count = QORIQ_TLB1_ENTRY_COUNT - 1;
+#else
+ max_count = (3 * QORIQ_TLB1_ENTRY_COUNT) / 4;
+#endif
+
+ if (boot_processor) {
+ config_fdt_adjust(fdt);
+ }
+
for (i = 0; i < (int) (sizeof(config) / sizeof(config [0])); ++i) {
const entry *cur = &config [i];
if (cur->size > 0) {
@@ -227,7 +333,7 @@ void TEXT qoriq_mmu_config(bool boot_processor, int first_tlb, int scratch_tlb)
}
}
- qoriq_mmu_partition(&context, (3 * QORIQ_TLB1_ENTRY_COUNT) / 4);
+ qoriq_mmu_partition(&context, max_count);
qoriq_mmu_write_to_tlb1(&context, first_tlb);
}
diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c
index 12dcc71f50..2629c9f999 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (c) 2011-2015 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2011, 2018 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -84,31 +84,17 @@ static void TEXT sort(qoriq_mmu_context *self)
}
}
-static bool TEXT mas_equal(const qoriq_mmu_entry *a, const qoriq_mmu_entry *b)
+static bool TEXT mas_compatible(const qoriq_mmu_entry *a, const qoriq_mmu_entry *b)
{
- return a->mas1 == b->mas1 && a->mas2 == b->mas2 && a->mas3 == b->mas3;
+ uint32_t m = FSL_EIS_MAS2_M;
+
+ return (a->mas2 & ~m) == (b->mas2 & ~m);
}
static bool TEXT can_merge(const qoriq_mmu_entry *prev, const qoriq_mmu_entry *cur)
{
- bool can = false;
-
- if (prev->begin == cur->begin || prev->last >= cur->begin - 1) {
- /*
- * Here we can technically merge. We need a heuristic to
- * prevent merges in case the MAS values differ and the boarder
- * is reasonably well aligned.
- */
- if (
- mas_equal(prev, cur)
- || prev->last != cur->begin - 1
- || power_of_two(cur->begin) < 24
- ) {
- can = true;
- }
- }
-
- return can;
+ return mas_compatible(prev, cur)
+ && (prev->begin == cur->begin || prev->last >= cur->begin - 1);
}
static void TEXT merge(qoriq_mmu_context *self)
@@ -130,7 +116,7 @@ static void TEXT merge(qoriq_mmu_context *self)
if (cur->last > prev->last) {
prev->last = cur->last;
- }
+ }
for (j = i + 1; j < n; ++j) {
entries [j - 1] = entries [j];
@@ -150,16 +136,72 @@ static void TEXT compact(qoriq_mmu_context *self)
merge(self);
}
+static bool TEXT can_expand_down(
+ const qoriq_mmu_context *self,
+ const qoriq_mmu_entry *cur,
+ int i,
+ uintptr_t new_begin
+)
+{
+ int j;
+
+ for (j = 0; j < i; ++j) {
+ const qoriq_mmu_entry *before = &self->entries[j];
+
+ if (
+ before->begin <= new_begin
+ && new_begin <= before->last
+ && !mas_compatible(before, cur)
+ ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool TEXT can_expand_up(
+ const qoriq_mmu_context *self,
+ const qoriq_mmu_entry *cur,
+ int i,
+ int n,
+ uintptr_t new_last
+)
+{
+ int j;
+
+ for (j = i + 1; j < n; ++j) {
+ const qoriq_mmu_entry *after = &self->entries[j];
+
+ if (
+ after->begin <= new_last
+ && new_last <= after->last
+ && !mas_compatible(after, cur)
+ ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
static void TEXT align(qoriq_mmu_context *self, uintptr_t alignment)
{
- qoriq_mmu_entry *entries = self->entries;
int n = self->count;
- int i = 0;
+ int i;
for (i = 0; i < n; ++i) {
- qoriq_mmu_entry *cur = &entries [i];
- cur->begin &= ~(alignment - 1);
- cur->last = alignment + (cur->last & ~(alignment - 1)) - 1;
+ qoriq_mmu_entry *cur = &self->entries[i];
+ uintptr_t new_begin = cur->begin & ~(alignment - 1);
+ uintptr_t new_last = alignment + (cur->last & ~(alignment - 1)) - 1;
+
+ if (
+ can_expand_down(self, cur, i, new_begin)
+ && can_expand_up(self, cur, i, n, new_last)
+ ) {
+ cur->begin = new_begin;
+ cur->last = new_last;
+ }
}
}
@@ -265,6 +307,8 @@ void TEXT qoriq_mmu_partition(qoriq_mmu_context *self, int max_count)
{
uintptr_t alignment = 4096;
+ sort(self);
+
do {
align(self, alignment);
partition(self);