diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mm/mm-armv.c | 60 |
1 files changed, 47 insertions, 13 deletions
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index 64db10e806b3..61bc2fa0511e 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c | |||
@@ -478,20 +478,20 @@ void __init create_mapping(struct map_desc *md) | |||
478 | unsigned long virt, length; | 478 | unsigned long virt, length; |
479 | int prot_sect, prot_l1, domain; | 479 | int prot_sect, prot_l1, domain; |
480 | pgprot_t prot_pte; | 480 | pgprot_t prot_pte; |
481 | long off; | 481 | unsigned long off = (u32)__pfn_to_phys(md->pfn); |
482 | 482 | ||
483 | if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { | 483 | if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { |
484 | printk(KERN_WARNING "BUG: not creating mapping for " | 484 | printk(KERN_WARNING "BUG: not creating mapping for " |
485 | "0x%08lx at 0x%08lx in user region\n", | 485 | "0x%016llx at 0x%08lx in user region\n", |
486 | __pfn_to_phys(md->pfn), md->virtual); | 486 | __pfn_to_phys((u64)md->pfn), md->virtual); |
487 | return; | 487 | return; |
488 | } | 488 | } |
489 | 489 | ||
490 | if ((md->type == MT_DEVICE || md->type == MT_ROM) && | 490 | if ((md->type == MT_DEVICE || md->type == MT_ROM) && |
491 | md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { | 491 | md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { |
492 | printk(KERN_WARNING "BUG: mapping for 0x%08lx at 0x%08lx " | 492 | printk(KERN_WARNING "BUG: mapping for 0x%016llx at 0x%08lx " |
493 | "overlaps vmalloc space\n", | 493 | "overlaps vmalloc space\n", |
494 | __pfn_to_phys(md->pfn), md->virtual); | 494 | __pfn_to_phys((u64)md->pfn), md->virtual); |
495 | } | 495 | } |
496 | 496 | ||
497 | domain = mem_types[md->type].domain; | 497 | domain = mem_types[md->type].domain; |
@@ -499,8 +499,33 @@ void __init create_mapping(struct map_desc *md) | |||
499 | prot_l1 = mem_types[md->type].prot_l1 | PMD_DOMAIN(domain); | 499 | prot_l1 = mem_types[md->type].prot_l1 | PMD_DOMAIN(domain); |
500 | prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain); | 500 | prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain); |
501 | 501 | ||
502 | /* | ||
503 | * Catch 36-bit addresses | ||
504 | */ | ||
505 | if(md->pfn >= 0x100000) { | ||
506 | if(domain) { | ||
507 | printk(KERN_ERR "MM: invalid domain in supersection " | ||
508 | "mapping for 0x%016llx at 0x%08lx\n", | ||
509 | __pfn_to_phys((u64)md->pfn), md->virtual); | ||
510 | return; | ||
511 | } | ||
512 | if((md->virtual | md->length | __pfn_to_phys(md->pfn)) | ||
513 | & ~SUPERSECTION_MASK) { | ||
514 | printk(KERN_ERR "MM: cannot create mapping for " | ||
515 | "0x%016llx at 0x%08lx invalid alignment\n", | ||
516 | __pfn_to_phys((u64)md->pfn), md->virtual); | ||
517 | return; | ||
518 | } | ||
519 | |||
520 | /* | ||
521 | * Shift bits [35:32] of address into bits [23:20] of PMD | ||
522 | * (See ARMv6 spec). | ||
523 | */ | ||
524 | off |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20); | ||
525 | } | ||
526 | |||
502 | virt = md->virtual; | 527 | virt = md->virtual; |
503 | off = __pfn_to_phys(md->pfn) - virt; | 528 | off -= virt; |
504 | length = md->length; | 529 | length = md->length; |
505 | 530 | ||
506 | if (mem_types[md->type].prot_l1 == 0 && | 531 | if (mem_types[md->type].prot_l1 == 0 && |
@@ -525,13 +550,22 @@ void __init create_mapping(struct map_desc *md) | |||
525 | * of the actual domain assignments in use. | 550 | * of the actual domain assignments in use. |
526 | */ | 551 | */ |
527 | if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) { | 552 | if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) { |
528 | /* Align to supersection boundary */ | 553 | /* |
529 | while ((virt & ~SUPERSECTION_MASK || (virt + off) & | 554 | * Align to supersection boundary if !high pages. |
530 | ~SUPERSECTION_MASK) && length >= (PGDIR_SIZE / 2)) { | 555 | * High pages have already been checked for proper |
531 | alloc_init_section(virt, virt + off, prot_sect); | 556 | * alignment above and they will fail the SUPSERSECTION_MASK |
532 | 557 | * check because of the way the address is encoded into | |
533 | virt += (PGDIR_SIZE / 2); | 558 | * offset. |
534 | length -= (PGDIR_SIZE / 2); | 559 | */ |
560 | if (md->pfn <= 0x100000) { | ||
561 | while ((virt & ~SUPERSECTION_MASK || | ||
562 | (virt + off) & ~SUPERSECTION_MASK) && | ||
563 | length >= (PGDIR_SIZE / 2)) { | ||
564 | alloc_init_section(virt, virt + off, prot_sect); | ||
565 | |||
566 | virt += (PGDIR_SIZE / 2); | ||
567 | length -= (PGDIR_SIZE / 2); | ||
568 | } | ||
535 | } | 569 | } |
536 | 570 | ||
537 | while (length >= SUPERSECTION_SIZE) { | 571 | while (length >= SUPERSECTION_SIZE) { |