[rtems commit] bsp/qoriq: Fix hypervisor guest MMU config

Sebastian Huber sebh at rtems.org
Mon Jan 22 09:38:48 UTC 2018


Module:    rtems
Branch:    master
Commit:    9ec5ff4e577c2c06b8a839f090761f55fa70fab8
Changeset: http://git.rtems.org/rtems/commit/?id=9ec5ff4e577c2c06b8a839f090761f55fa70fab8

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Tue Jan  9 10:09:57 2018 +0100

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.

---

 .../lib/libbsp/powerpc/qoriq/startup/mmu-config.c  | 128 +++++++++++++++++++--
 c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c       |  98 +++++++++++-----
 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 90b0534..91a6240 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 12dcc71..2629c9f 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);



More information about the vc mailing list