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.
This commit is contained in:
Sebastian Huber committed 2018-01-22 07:21:19 +01:00
1 parent 5ce2dfaf4e
commit 9ec5ff4e57
2 files changed
+188 -38

No files matched your search

@@ -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);
}
+71 -27
View File
@@ -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);