From d704fb0cc0cce474ac959adca6c3d1f606fcfa2a Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> Date: Mon, 14 Jan 2008 21:42:56 +0100 Subject: avr32: Kill special exception handler sections Kill the special exception handler sections .tlbx.ex.text, .tlbr.ex.text, tlbw.ex.text and .scall.text. Use .org instead to place the handlers at the required offsets from EVBA. Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> --- arch/avr32/kernel/entry-avr32b.S | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch/avr32/kernel/entry-avr32b.S') diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index 5f31702d6b1c..050c006a7f0c 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S @@ -83,22 +83,23 @@ exception_vectors: #define tlbmiss_save pushm r0-r3 #define tlbmiss_restore popm r0-r3 - .section .tlbx.ex.text,"ax",@progbits + .org 0x50 .global itlb_miss itlb_miss: tlbmiss_save rjmp tlb_miss_common - .section .tlbr.ex.text,"ax",@progbits + .org 0x60 dtlb_miss_read: tlbmiss_save rjmp tlb_miss_common - .section .tlbw.ex.text,"ax",@progbits + .org 0x70 dtlb_miss_write: tlbmiss_save .global tlb_miss_common + .align 2 tlb_miss_common: mfsr r0, SYSREG_TLBEAR mfsr r1, SYSREG_PTBR @@ -157,7 +158,7 @@ handle_vmalloc_miss: /* --- System Call --- */ - .section .scall.text,"ax",@progbits + .org 0x100 system_call: #ifdef CONFIG_PREEMPT mask_interrupts -- cgit v1.2.2 From cfd23e93a0289cf6711fd3877c5226658d87240a Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> Date: Mon, 14 Jan 2008 22:15:05 +0100 Subject: avr32: Store virtual addresses in the PGD Instead of storing physical addresses along with page flags in the PGD, store virtual addresses and use NULL to indicate a not present second-level page table. A non-page-aligned page table indicates a bad PMD. This simplifies the TLB miss handler since it no longer has to check the Present bit and no longer has to convert the PGD entry from physical to virtual address. Instead, it has to check for a NULL entry, which is slightly cheaper than either. Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> --- arch/avr32/kernel/entry-avr32b.S | 45 ++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 25 deletions(-) (limited to 'arch/avr32/kernel/entry-avr32b.S') diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index 050c006a7f0c..3cdd7071f35e 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S @@ -74,12 +74,6 @@ exception_vectors: .align 2 bral do_dtlb_modified - /* - * r0 : PGD/PT/PTE - * r1 : Offending address - * r2 : Scratch register - * r3 : Cause (5, 12 or 13) - */ #define tlbmiss_save pushm r0-r3 #define tlbmiss_restore popm r0-r3 @@ -108,17 +102,17 @@ tlb_miss_common: bld r0, 31 brcs handle_vmalloc_miss - /* First level lookup */ + /* + * First level lookup: The PGD contains virtual pointers to + * the second-level page tables, but they may be NULL if not + * present. + */ pgtbl_lookup: lsr r2, r0, PGDIR_SHIFT ld.w r3, r1[r2 << 2] bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT - bld r3, _PAGE_BIT_PRESENT - brcc page_table_not_present - - /* Translate to virtual address in P1. */ - andl r3, 0xf000 - sbr r3, 31 + cp.w r3, 0 + breq page_table_not_present /* Second level lookup */ ld.w r2, r3[r1 << 2] @@ -155,6 +149,19 @@ handle_vmalloc_miss: orh r1, hi(swapper_pg_dir) rjmp pgtbl_lookup + /* The slow path of the TLB miss handler */ + .align 2 +page_table_not_present: +page_not_present: + tlbmiss_restore + sub sp, 4 + stmts --sp, r0-lr + rcall save_full_context_ex + mfsr r12, SYSREG_ECR + mov r11, sp + rcall do_page_fault + rjmp ret_from_exception + /* --- System Call --- */ @@ -267,18 +274,6 @@ syscall_exit_work: brcc syscall_exit_cont rjmp enter_monitor_mode - /* The slow path of the TLB miss handler */ -page_table_not_present: -page_not_present: - tlbmiss_restore - sub sp, 4 - stmts --sp, r0-lr - rcall save_full_context_ex - mfsr r12, SYSREG_ECR - mov r11, sp - rcall do_page_fault - rjmp ret_from_exception - /* This function expects to find offending PC in SYSREG_RAR_EX */ .type save_full_context_ex, @function .align 2 -- cgit v1.2.2 From a9a934f278613885816aa9f177968c1dac557240 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> Date: Mon, 14 Jan 2008 23:11:26 +0100 Subject: avr32: Cover the kernel page tables in the user PGDs Expand the per-process PGDs so that they cover the kernel virtual memory area as well. This simplifies the TLB miss handler fastpath since it doesn't have to check for kernel addresses anymore. If a TLB miss happens on a kernel address and a second-level page table can't be found, we check swapper_pg_dir and copy the PGD entry into the user PGD if it can be found there. Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> --- arch/avr32/kernel/entry-avr32b.S | 42 ++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) (limited to 'arch/avr32/kernel/entry-avr32b.S') diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index 3cdd7071f35e..2b398cae110c 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S @@ -98,10 +98,6 @@ tlb_miss_common: mfsr r0, SYSREG_TLBEAR mfsr r1, SYSREG_PTBR - /* Is it the vmalloc space? */ - bld r0, 31 - brcs handle_vmalloc_miss - /* * First level lookup: The PGD contains virtual pointers to * the second-level page tables, but they may be NULL if not @@ -143,15 +139,13 @@ pgtbl_lookup: tlbmiss_restore rete -handle_vmalloc_miss: - /* Simply do the lookup in init's page table */ - mov r1, lo(swapper_pg_dir) - orh r1, hi(swapper_pg_dir) - rjmp pgtbl_lookup - /* The slow path of the TLB miss handler */ .align 2 page_table_not_present: + /* Do we need to synchronize with swapper_pg_dir? */ + bld r0, 31 + brcs sync_with_swapper_pg_dir + page_not_present: tlbmiss_restore sub sp, 4 @@ -162,6 +156,34 @@ page_not_present: rcall do_page_fault rjmp ret_from_exception + .align 2 +sync_with_swapper_pg_dir: + /* + * If swapper_pg_dir contains a non-NULL second-level page + * table pointer, copy it into the current PGD. If not, we + * must handle it as a full-blown page fault. + * + * Jumping back to pgtbl_lookup causes an unnecessary lookup, + * but it is guaranteed to be a cache hit, it won't happen + * very often, and we absolutely do not want to sacrifice any + * performance in the fast path in order to improve this. + */ + mov r1, lo(swapper_pg_dir) + orh r1, hi(swapper_pg_dir) + ld.w r3, r1[r2 << 2] + cp.w r3, 0 + breq page_not_present + mfsr r1, SYSREG_PTBR + st.w r1[r2 << 2], r3 + rjmp pgtbl_lookup + + /* + * We currently have two bytes left at this point until we + * crash into the system call handler... + * + * Don't worry, the assembler will let us know. + */ + /* --- System Call --- */ -- cgit v1.2.2