diff options
author | Will Deacon <will.deacon@arm.com> | 2012-01-20 06:01:13 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-03-24 05:38:51 -0400 |
commit | f9d4861fc32b995b1616775614459b8f266c803c (patch) | |
tree | 187d7bfa7ff0418f2762d38c9c553331e602faf1 /arch/arm/kernel/process.c | |
parent | 195864cf3d6f5b6b743793bda3aaa2ff65d322ae (diff) |
ARM: 7294/1: vectors: use gate_vma for vectors user mapping
The current user mapping for the vectors page is inserted as a `horrible
hack vma' into each task via arch_setup_additional_pages. This causes
problems with the MM subsystem and vm_normal_page, as described here:
https://lkml.org/lkml/2012/1/14/55
Following the suggestion from Hugh in the above thread, this patch uses
the gate_vma for the vectors user mapping, therefore consolidating
the horrible hack VMAs into one.
Acked-and-Tested-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel/process.c')
-rw-r--r-- | arch/arm/kernel/process.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 971d65c253a9..e11b523db332 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -526,22 +526,40 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) | |||
526 | #ifdef CONFIG_MMU | 526 | #ifdef CONFIG_MMU |
527 | /* | 527 | /* |
528 | * The vectors page is always readable from user space for the | 528 | * The vectors page is always readable from user space for the |
529 | * atomic helpers and the signal restart code. Let's declare a mapping | 529 | * atomic helpers and the signal restart code. Insert it into the |
530 | * for it so it is visible through ptrace and /proc/<pid>/mem. | 530 | * gate_vma so that it is visible through ptrace and /proc/<pid>/mem. |
531 | */ | 531 | */ |
532 | static struct vm_area_struct gate_vma; | ||
532 | 533 | ||
533 | int vectors_user_mapping(void) | 534 | static int __init gate_vma_init(void) |
534 | { | 535 | { |
535 | struct mm_struct *mm = current->mm; | 536 | gate_vma.vm_start = 0xffff0000; |
536 | return install_special_mapping(mm, 0xffff0000, PAGE_SIZE, | 537 | gate_vma.vm_end = 0xffff0000 + PAGE_SIZE; |
537 | VM_READ | VM_EXEC | | 538 | gate_vma.vm_page_prot = PAGE_READONLY_EXEC; |
538 | VM_MAYREAD | VM_MAYEXEC | | 539 | gate_vma.vm_flags = VM_READ | VM_EXEC | |
539 | VM_ALWAYSDUMP | VM_RESERVED, | 540 | VM_MAYREAD | VM_MAYEXEC | |
540 | NULL); | 541 | VM_ALWAYSDUMP; |
542 | return 0; | ||
543 | } | ||
544 | arch_initcall(gate_vma_init); | ||
545 | |||
546 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
547 | { | ||
548 | return &gate_vma; | ||
549 | } | ||
550 | |||
551 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
552 | { | ||
553 | return (addr >= gate_vma.vm_start) && (addr < gate_vma.vm_end); | ||
554 | } | ||
555 | |||
556 | int in_gate_area_no_mm(unsigned long addr) | ||
557 | { | ||
558 | return in_gate_area(NULL, addr); | ||
541 | } | 559 | } |
542 | 560 | ||
543 | const char *arch_vma_name(struct vm_area_struct *vma) | 561 | const char *arch_vma_name(struct vm_area_struct *vma) |
544 | { | 562 | { |
545 | return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL; | 563 | return (vma == &gate_vma) ? "[vectors]" : NULL; |
546 | } | 564 | } |
547 | #endif | 565 | #endif |