Commit 49ee1b77 authored by George G. Davis's avatar George G. Davis Committed by Russell King

[ARM PATCH] 2459/1: ARMv6 supersections for static kernel direct mapped memory regions [updated]

Patch from George G. Davis

Use ARMv6 supersections for 16MiB static kernel direct mapped memory
regions when possible.
Based on comments received for the first version of this patch, this
version has added a comment to clarify that ARMv6 supersections are
only valid for the domain == 0 case and moved the supersection address
mask and size macros before the hardware page table definitions.

Signed-off-by: George G. Davis
Signed-off-by: Russell King
parent 5f2849e4
...@@ -255,6 +255,23 @@ alloc_init_section(unsigned long virt, unsigned long phys, int prot) ...@@ -255,6 +255,23 @@ alloc_init_section(unsigned long virt, unsigned long phys, int prot)
set_pmd(pmdp, __pmd(phys | prot)); set_pmd(pmdp, __pmd(phys | prot));
} }
/*
* Create a SUPER SECTION PGD between VIRT and PHYS with protection PROT
*/
static inline void
alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
{
int i;
for (i = 0; i < 16; i += 1) {
alloc_init_section(virt, phys & SUPERSECTION_MASK,
prot | PMD_SECT_SUPER);
virt += (PGDIR_SIZE / 2);
phys += (PGDIR_SIZE / 2);
}
}
/* /*
* Add a PAGE mapping between VIRT and PHYS in domain * Add a PAGE mapping between VIRT and PHYS in domain
* DOMAIN with protection PROT. Note that due to the * DOMAIN with protection PROT. Note that due to the
...@@ -436,7 +453,8 @@ static void __init build_mem_type_table(void) ...@@ -436,7 +453,8 @@ static void __init build_mem_type_table(void)
* Create the page directory entries and any necessary * Create the page directory entries and any necessary
* page tables for the mapping specified by `md'. We * page tables for the mapping specified by `md'. We
* are able to cope here with varying sizes and address * are able to cope here with varying sizes and address
* offsets, and we take full advantage of sections. * offsets, and we take full advantage of sections and
* supersections.
*/ */
static void __init create_mapping(struct map_desc *md) static void __init create_mapping(struct map_desc *md)
{ {
...@@ -483,6 +501,30 @@ static void __init create_mapping(struct map_desc *md) ...@@ -483,6 +501,30 @@ static void __init create_mapping(struct map_desc *md)
length -= PAGE_SIZE; length -= PAGE_SIZE;
} }
/* N.B. ARMv6 supersections are only defined to work with domain 0.
* Since domain assignments can in fact be arbitrary, the
* 'domain == 0' check below is required to insure that ARMv6
* supersections are only allocated for domain 0 regardless
* of the actual domain assignments in use.
*/
if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) {
/* Align to supersection boundary */
while ((virt & ~SUPERSECTION_MASK || (virt + off) &
~SUPERSECTION_MASK) && length >= (PGDIR_SIZE / 2)) {
alloc_init_section(virt, virt + off, prot_sect);
virt += (PGDIR_SIZE / 2);
length -= (PGDIR_SIZE / 2);
}
while (length >= SUPERSECTION_SIZE) {
alloc_init_supersection(virt, virt + off, prot_sect);
virt += SUPERSECTION_SIZE;
length -= SUPERSECTION_SIZE;
}
}
/* /*
* A section mapping covers half a "pgdir" entry. * A section mapping covers half a "pgdir" entry.
*/ */
......
...@@ -105,6 +105,13 @@ extern void __pgd_error(const char *file, int line, unsigned long val); ...@@ -105,6 +105,13 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define FIRST_USER_PGD_NR 1 #define FIRST_USER_PGD_NR 1
#define USER_PTRS_PER_PGD ((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR) #define USER_PTRS_PER_PGD ((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR)
/*
* ARMv6 supersection address mask and size definitions.
*/
#define SUPERSECTION_SHIFT 24
#define SUPERSECTION_SIZE (1UL << SUPERSECTION_SHIFT)
#define SUPERSECTION_MASK (~(SUPERSECTION_SIZE-1))
/* /*
* Hardware page table definitions. * Hardware page table definitions.
* *
...@@ -129,6 +136,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val); ...@@ -129,6 +136,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define PMD_SECT_APX (1 << 15) /* v6 */ #define PMD_SECT_APX (1 << 15) /* v6 */
#define PMD_SECT_S (1 << 16) /* v6 */ #define PMD_SECT_S (1 << 16) /* v6 */
#define PMD_SECT_nG (1 << 17) /* v6 */ #define PMD_SECT_nG (1 << 17) /* v6 */
#define PMD_SECT_SUPER (1 << 18) /* v6 */
#define PMD_SECT_UNCACHED (0) #define PMD_SECT_UNCACHED (0)
#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE) #define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment