Browse Source

Merge pull request #538 from sandrine-bailleux-arm/sb/extend-memory-types

Extend memory attributes to map non-cacheable memory
pull/547/head
danh-arm 9 years ago
parent
commit
a34f3bf213
  1. 4
      include/lib/aarch64/arch.h
  2. 42
      include/lib/aarch64/xlat_tables.h
  3. 28
      lib/aarch64/xlat_tables.c

4
include/lib/aarch64/arch.h

@ -419,11 +419,11 @@
#define AP_RW (0x0 << 5)
#define NS (0x1 << 3)
#define ATTR_SO_INDEX 0x2
#define ATTR_NON_CACHEABLE_INDEX 0x2
#define ATTR_DEVICE_INDEX 0x1
#define ATTR_IWBWA_OWBWA_NTR_INDEX 0x0
#define LOWER_ATTRS(x) (((x) & 0xfff) << 2)
#define ATTR_SO (0x0)
#define ATTR_NON_CACHEABLE (0x44)
#define ATTR_DEVICE (0x4)
#define ATTR_IWBWA_OWBWA_NTR (0xff)
#define MAIR_ATTR_SET(attr, index) (attr << (index << 3))

42
include/lib/aarch64/xlat_tables.h

@ -52,21 +52,41 @@
#define MAP_REGION(pa, va, sz, attr) {(pa), (va), (sz), (attr)}
/*
* Flags for building up memory mapping attributes.
* These are organised so that a clear bit gives a more restrictive mapping
* that a set bit, that way a bitwise-and two sets of attributes will never give
* an attribute which has greater access rights that any of the original
* attributes.
* Shifts and masks to access fields of an mmap_attr_t
*/
#define MT_TYPE_MASK 0x7
#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK)
/* Access permissions (RO/RW) */
#define MT_PERM_SHIFT 3
/* Security state (SECURE/NS) */
#define MT_SEC_SHIFT 4
/*
* Memory mapping attributes
*/
typedef enum {
MT_DEVICE = 0 << 0,
MT_MEMORY = 1 << 0,
/*
* Memory types supported.
* These are organised so that, going down the list, the memory types
* are getting weaker; conversely going up the list the memory types are
* getting stronger.
*/
MT_DEVICE,
MT_NON_CACHEABLE,
MT_MEMORY,
/* Values up to 7 are reserved to add new memory types in the future */
MT_RO = 0 << 1,
MT_RW = 1 << 1,
/*
* The following values are organised so that a clear bit gives a more
* restrictive mapping than a set bit, that way a bitwise-and of two
* sets of attributes will never give an attribute which has greater
* access rights than any of the original attributes.
*/
MT_RO = 0 << MT_PERM_SHIFT,
MT_RW = 1 << MT_PERM_SHIFT,
MT_SECURE = 0 << 2,
MT_NS = 1 << 2
MT_SECURE = 0 << MT_SEC_SHIFT,
MT_NS = 1 << MT_SEC_SHIFT,
} mmap_attr_t;
/*

28
lib/aarch64/xlat_tables.c

@ -138,6 +138,7 @@ static unsigned long mmap_desc(unsigned attr, unsigned long addr_pa,
unsigned level)
{
unsigned long desc = addr_pa;
int mem_type;
desc |= level == 3 ? TABLE_DESC : BLOCK_DESC;
@ -147,16 +148,23 @@ static unsigned long mmap_desc(unsigned attr, unsigned long addr_pa,
desc |= LOWER_ATTRS(ACCESS_FLAG);
if (attr & MT_MEMORY) {
mem_type = MT_TYPE(attr);
if (mem_type == MT_MEMORY) {
desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH);
if (attr & MT_RW)
desc |= UPPER_ATTRS(XN);
} else if (mem_type == MT_NON_CACHEABLE) {
desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH);
if (attr & MT_RW)
desc |= UPPER_ATTRS(XN);
} else {
assert(mem_type == MT_DEVICE);
desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH);
desc |= UPPER_ATTRS(XN);
}
debug_print(attr & MT_MEMORY ? "MEM" : "DEV");
debug_print((mem_type == MT_MEMORY) ? "MEM" :
((mem_type == MT_NON_CACHEABLE) ? "NC" : "DEV"));
debug_print(attr & MT_RW ? "-RW" : "-RO");
debug_print(attr & MT_NS ? "-NS" : "-S");
@ -167,6 +175,7 @@ static int mmap_region_attr(mmap_region_t *mm, unsigned long base_va,
unsigned long size)
{
int attr = mm->attr;
int old_mem_type, new_mem_type;
for (;;) {
++mm;
@ -183,7 +192,20 @@ static int mmap_region_attr(mmap_region_t *mm, unsigned long base_va,
if ((mm->attr & attr) == attr)
continue; /* Region doesn't override attribs so skip */
/*
* Update memory mapping attributes in 2 steps:
* 1) Update access permissions and security state flags
* 2) Update memory type.
*
* See xlat_tables.h for details about the attributes priority
* system and the rules dictating whether attributes should be
* updated.
*/
old_mem_type = MT_TYPE(attr);
new_mem_type = MT_TYPE(mm->attr);
attr &= mm->attr;
if (new_mem_type < old_mem_type)
attr = (attr & ~MT_TYPE_MASK) | new_mem_type;
if (mm->base_va > base_va ||
mm->base_va + mm->size < base_va + size)
@ -309,6 +331,8 @@ void init_xlat_tables(void)
mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); \
mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, \
ATTR_IWBWA_OWBWA_NTR_INDEX); \
mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, \
ATTR_NON_CACHEABLE_INDEX); \
write_mair_el##_el(mair); \
\
/* Invalidate TLBs at the current exception level */ \

Loading…
Cancel
Save