mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-11-04 08:37:49 +08:00
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:
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user