Commit 5b7e8fdb authored by Catalin Marinas's avatar Catalin Marinas

Only use supersections for high addresses

Because of possible unpredictable behaviour caused by the overlapping
of sections and supersections during the initial memory setup (may
lead to two TLB entries for the same virtual address), this patch
disables the use of supersections for addresses < 4GB.
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent 98cd902c
......@@ -300,7 +300,7 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
addr = (unsigned long)area->addr;
#ifndef CONFIG_SMP
if (DOMAIN_IO == 0 &&
if (DOMAIN_IO == 0 && pfn >= 0x100000 &&
(((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) ||
cpu_is_xsc3()) &&
!((__pfn_to_phys(pfn) | size | addr) & ~SUPERSECTION_MASK)) {
......
......@@ -465,6 +465,12 @@ void __init create_mapping(struct map_desc *md)
* Catch 36-bit addresses
*/
if(md->pfn >= 0x100000) {
if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) {
printk(KERN_ERR "MM: supersection mapping not "
"supported for 0x%08llx at 0x%08lx\n",
__pfn_to_phys((u64)md->pfn), md->virtual);
return;
}
if(domain) {
printk(KERN_ERR "MM: invalid domain in supersection "
"mapping for 0x%08llx at 0x%08lx\n",
......@@ -505,39 +511,17 @@ void __init create_mapping(struct map_desc *md)
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.
/*
* Architecture version, domain 0 and high pages alignment
* have already been checked above.
*/
if ((cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())
&& domain == 0) {
/*
* Align to supersection boundary if !high pages.
* High pages have already been checked for proper
* alignment above and they will fail the SUPSERSECTION_MASK
* check because of the way the address is encoded into
* offset.
*/
if (md->pfn <= 0x100000) {
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);
}
}
if (md->pfn >= 0x100000)
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.
......
......@@ -35,8 +35,10 @@
#ifndef CONFIG_SMP
#define TTB_FLAGS TTB_RGN_WBWA
#define PMD_SECT_SMP 0
#else
#define TTB_FLAGS TTB_RGN_WBWA|TTB_S
#define PMD_SECT_SMP PMD_SECT_S
#endif
ENTRY(cpu_v6_proc_init)
......@@ -266,7 +268,8 @@ __v6_proc_info:
PMD_SECT_BUFFERABLE | \
PMD_SECT_CACHEABLE | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ
PMD_SECT_AP_READ | \
PMD_SECT_SMP
.long PMD_TYPE_SECT | \
PMD_SECT_XN | \
PMD_SECT_AP_WRITE | \
......
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