From 8235703e103579bdcedadcaf63bc1896f82b191b Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Sat, 1 Jun 2013 12:55:42 +0530 Subject: ARC: Use kconfig helper IS_ENABLED() to get rid of defines.h Signed-off-by: Vineet Gupta --- arch/arc/mm/cache_arc700.c | 6 ++++-- arch/arc/mm/tlb.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index aedce1905441..28007d25066e 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -89,8 +89,10 @@ char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len) enb ? "" : "DISABLED (kernel-build)"); \ } - PR_CACHE(&cpuinfo_arc700[c].icache, __CONFIG_ARC_HAS_ICACHE, "I-Cache"); - PR_CACHE(&cpuinfo_arc700[c].dcache, __CONFIG_ARC_HAS_DCACHE, "D-Cache"); + PR_CACHE(&cpuinfo_arc700[c].icache, IS_ENABLED(CONFIG_ARC_HAS_ICACHE), + "I-Cache"); + PR_CACHE(&cpuinfo_arc700[c].dcache, IS_ENABLED(CONFIG_ARC_HAS_DCACHE), + "D-Cache"); return buf; } diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index fe1c5a073afe..1ced5f18e6b3 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -505,7 +505,7 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len) "J-TLB %d (%dx%d), uDTLB %d, uITLB %d, %s\n", p_mmu->num_tlb, p_mmu->sets, p_mmu->ways, p_mmu->u_dtlb, p_mmu->u_itlb, - __CONFIG_ARC_MMU_SASID_VAL ? "SASID" : ""); + IS_ENABLED(CONFIG_ARC_MMU_SASID) ? "SASID" : ""); return buf; } -- cgit From da1677b02d3ef674dfd8a4ba1ed32153dc717fa2 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Tue, 14 May 2013 13:28:17 +0530 Subject: ARC: Disintegrate arcregs.h * Move the various sub-system defines/types into relevant files/functions (reduces compilation time) * move CPU specific stuff out of asm/tlb.h into asm/mmu.h Signed-off-by: Vineet Gupta --- arch/arc/mm/cache_arc700.c | 39 +++++++++++++++++++++++++++++++++++---- arch/arc/mm/fault.c | 1 + arch/arc/mm/tlb.c | 24 ++++++++++++++++++++---- arch/arc/mm/tlbex.S | 2 +- 4 files changed, 57 insertions(+), 9 deletions(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 28007d25066e..e9c7a66817ca 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -73,6 +73,33 @@ #include #include +/* Instruction cache related Auxiliary registers */ +#define ARC_REG_IC_BCR 0x77 /* Build Config reg */ +#define ARC_REG_IC_IVIC 0x10 +#define ARC_REG_IC_CTRL 0x11 +#define ARC_REG_IC_IVIL 0x19 +#if (CONFIG_ARC_MMU_VER > 2) +#define ARC_REG_IC_PTAG 0x1E +#endif + +/* Bit val in IC_CTRL */ +#define IC_CTRL_CACHE_DISABLE 0x1 + +/* Data cache related Auxiliary registers */ +#define ARC_REG_DC_BCR 0x72 /* Build Config reg */ +#define ARC_REG_DC_IVDC 0x47 +#define ARC_REG_DC_CTRL 0x48 +#define ARC_REG_DC_IVDL 0x4A +#define ARC_REG_DC_FLSH 0x4B +#define ARC_REG_DC_FLDL 0x4C +#if (CONFIG_ARC_MMU_VER > 2) +#define ARC_REG_DC_PTAG 0x5C +#endif + +/* Bit val in DC_CTRL */ +#define DC_CTRL_INV_MODE_FLUSH 0x40 +#define DC_CTRL_FLUSH_STATUS 0x100 + char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len) { int n = 0; @@ -104,9 +131,15 @@ char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len) */ void __cpuinit read_decode_cache_bcr(void) { - struct bcr_cache ibcr, dbcr; struct cpuinfo_arc_cache *p_ic, *p_dc; unsigned int cpu = smp_processor_id(); + struct bcr_cache { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; +#else + unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; +#endif + } ibcr, dbcr; p_ic = &cpuinfo_arc700[cpu].icache; READ_BCR(ARC_REG_IC_BCR, ibcr); @@ -136,12 +169,10 @@ void __cpuinit read_decode_cache_bcr(void) */ void __cpuinit arc_cache_init(void) { - unsigned int temp; unsigned int cpu = smp_processor_id(); struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache; struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache; - int way_pg_ratio = way_pg_ratio; - int dcache_does_alias; + unsigned int dcache_does_alias, temp; char str[256]; printk(arc_cache_mumbojumbo(0, str, sizeof(str))); diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index 689ffd86d5e9..c0decc1f8d22 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -15,6 +15,7 @@ #include #include #include +#include static int handle_vmalloc_fault(struct mm_struct *mm, unsigned long address) { diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 1ced5f18e6b3..f60807c2683d 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -55,7 +55,7 @@ #include #include #include -#include +#include /* Need for ARC MMU v2 * @@ -97,6 +97,7 @@ * J-TLB entry got evicted/replaced. */ + /* A copy of the ASID from the PID reg is kept in asid_cache */ int asid_cache = FIRST_ASID; @@ -466,10 +467,25 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned, */ void __cpuinit read_decode_mmu_bcr(void) { - unsigned int tmp; - struct bcr_mmu_1_2 *mmu2; /* encoded MMU2 attr */ - struct bcr_mmu_3 *mmu3; /* encoded MMU3 attr */ struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; + unsigned int tmp; + struct bcr_mmu_1_2 { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int ver:8, ways:4, sets:4, u_itlb:8, u_dtlb:8; +#else + unsigned int u_dtlb:8, u_itlb:8, sets:4, ways:4, ver:8; +#endif + } *mmu2; + + struct bcr_mmu_3 { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int ver:8, ways:4, sets:4, osm:1, reserv:3, pg_sz:4, + u_itlb:4, u_dtlb:4; +#else + unsigned int u_dtlb:4, u_itlb:4, pg_sz:4, reserv:3, osm:1, sets:4, + ways:4, ver:8; +#endif + } *mmu3; tmp = read_aux_reg(ARC_REG_MMU_BCR); mmu->ver = (tmp >> 24); diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S index 3357d26ffe54..7bf811d51af8 100644 --- a/arch/arc/mm/tlbex.S +++ b/arch/arc/mm/tlbex.S @@ -39,7 +39,7 @@ #include #include -#include +#include #include #include #include -- cgit From 30499186602afa1d62c2e5d354d02214a0ee00b7 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Sat, 15 Jun 2013 10:21:51 +0530 Subject: ARC: cache detection code bitrot * Number of (i|d)cache ways can be retrieved from BCRs and hence no need to cross check with with built-in constants * Use of IS_ENABLED() to check for a Kconfig option * is_not_cache_aligned() not used anymore Signed-off-by: Vineet Gupta --- arch/arc/mm/cache_arc700.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index e9c7a66817ca..0a56682e0c94 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -144,8 +144,8 @@ void __cpuinit read_decode_cache_bcr(void) p_ic = &cpuinfo_arc700[cpu].icache; READ_BCR(ARC_REG_IC_BCR, ibcr); - if (ibcr.config == 0x3) - p_ic->assoc = 2; + BUG_ON(ibcr.config != 3); + p_ic->assoc = 2; /* Fixed to 2w set assoc */ p_ic->line_len = 8 << ibcr.line_len; p_ic->sz = 0x200 << ibcr.sz; p_ic->ver = ibcr.ver; @@ -153,8 +153,8 @@ void __cpuinit read_decode_cache_bcr(void) p_dc = &cpuinfo_arc700[cpu].dcache; READ_BCR(ARC_REG_DC_BCR, dbcr); - if (dbcr.config == 0x2) - p_dc->assoc = 4; + BUG_ON(dbcr.config != 2); + p_dc->assoc = 4; /* Fixed to 4w set assoc */ p_dc->line_len = 16 << dbcr.line_len; p_dc->sz = 0x200 << dbcr.sz; p_dc->ver = dbcr.ver; @@ -182,20 +182,11 @@ void __cpuinit arc_cache_init(void) #ifdef CONFIG_ARC_HAS_ICACHE /* 1. Confirm some of I-cache params which Linux assumes */ - if ((ic->assoc != ARC_ICACHE_WAYS) || - (ic->line_len != ARC_ICACHE_LINE_LEN)) { + if (ic->line_len != ARC_ICACHE_LINE_LEN) panic("Cache H/W doesn't match kernel Config"); - } -#if (CONFIG_ARC_MMU_VER > 2) - if (ic->ver != 3) { - if (running_on_hw) - panic("Cache ver doesn't match MMU ver\n"); - /* For ISS - suggest the toggles to use */ - pr_err("Use -prop=icache_version=3,-prop=dcache_version=3\n"); - - } -#endif + if (ic->ver != CONFIG_ARC_MMU_VER) + panic("Cache ver doesn't match MMU ver\n"); #endif /* Enable/disable I-Cache */ @@ -214,14 +205,12 @@ chk_dc: return; #ifdef CONFIG_ARC_HAS_DCACHE - if ((dc->assoc != ARC_DCACHE_WAYS) || - (dc->line_len != ARC_DCACHE_LINE_LEN)) { + if (dc->line_len != ARC_DCACHE_LINE_LEN) panic("Cache H/W doesn't match kernel Config"); - } - - dcache_does_alias = (dc->sz / ARC_DCACHE_WAYS) > PAGE_SIZE; /* check for D-Cache aliasing */ + dcache_does_alias = (dc->sz / dc->assoc) > PAGE_SIZE; + if (dcache_does_alias && !cache_is_vipt_aliasing()) panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); else if (!dcache_does_alias && cache_is_vipt_aliasing()) -- cgit From 336e199e9c812e2f20f028d7825f4342c9ec0cc3 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Sat, 22 Jun 2013 19:22:42 +0530 Subject: ARC: No-op full icache flush if !CONFIG_ARC_HAS_ICACHE Also remove extraneous irq disabling in flush_cache_all() callstack Signed-off-by: Vineet Gupta --- arch/arc/mm/cache_arc700.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 0a56682e0c94..03012a27d590 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -261,11 +261,9 @@ static inline void wait_for_flush(void) */ static inline void __dc_entire_op(const int cacheop) { - unsigned long flags, tmp = tmp; + unsigned int tmp = tmp; int aux; - local_irq_save(flags); - if (cacheop == OP_FLUSH_N_INV) { /* Dcache provides 2 cmd: FLUSH or INV * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE @@ -289,8 +287,6 @@ static inline void __dc_entire_op(const int cacheop) /* Switch back the DISCARD ONLY Invalidate mode */ if (cacheop == OP_FLUSH_N_INV) write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH); - - local_irq_restore(flags); } /* @@ -481,8 +477,15 @@ static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr, local_irq_restore(flags); } +static inline void __ic_entire_inv(void) +{ + write_aux_reg(ARC_REG_IC_IVIC, 1); + read_aux_reg(ARC_REG_IC_CTRL); /* blocks */ +} + #else +#define __ic_entire_inv() #define __ic_line_inv_vaddr(pstart, vstart, sz) #endif /* CONFIG_ARC_HAS_ICACHE */ @@ -651,26 +654,13 @@ void ___flush_dcache_page(unsigned long paddr, unsigned long vaddr) __dc_line_op(paddr, vaddr & PAGE_MASK, PAGE_SIZE, OP_FLUSH_N_INV); } -void flush_icache_all(void) -{ - unsigned long flags; - - local_irq_save(flags); - - write_aux_reg(ARC_REG_IC_IVIC, 1); - - /* lr will not complete till the icache inv operation is not over */ - read_aux_reg(ARC_REG_IC_CTRL); - local_irq_restore(flags); -} - noinline void flush_cache_all(void) { unsigned long flags; local_irq_save(flags); - flush_icache_all(); + __ic_entire_inv(); __dc_entire_op(OP_FLUSH_N_INV); local_irq_restore(flags); -- cgit From 29b93c68bf81d2aad1030e989d844cff9f3ba99a Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Sun, 19 May 2013 15:51:03 +0530 Subject: ARC: [mm] Zero page optimization Signed-off-by: Vineet Gupta --- arch/arc/mm/tlb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index f60807c2683d..1c91dbc8ddd8 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -433,9 +433,14 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned, { unsigned long vaddr = vaddr_unaligned & PAGE_MASK; unsigned long paddr = pte_val(*ptep) & PAGE_MASK; + struct page *page = pfn_to_page(pte_pfn(*ptep)); create_tlb(vma, vaddr, ptep); + if (page == ZERO_PAGE(0)) { + return; + } + /* * Exec page : Independent of aliasing/page-color considerations, * since icache doesn't snoop dcache on ARC, any dirty @@ -447,7 +452,6 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned, */ if ((vma->vm_flags & VM_EXEC) || addr_not_cache_congruent(paddr, vaddr)) { - struct page *page = pfn_to_page(pte_pfn(*ptep)); int dirty = test_and_clear_bit(PG_arch_1, &page->flags); if (dirty) { -- cgit From 5971bc719d1e329401412ae03ab83c2e4768cd2e Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 16 May 2013 12:23:31 +0530 Subject: ARC: [mm] optimise VIPT dcache aliasing 1/x flush_cache_page() - kills icache only if page is executable Signed-off-by: Vineet Gupta --- arch/arc/mm/cache_arc700.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 03012a27d590..4e54ef5b4c2a 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -679,7 +679,12 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long u_vaddr, { unsigned int paddr = pfn << PAGE_SHIFT; - __sync_icache_dcache(paddr, u_vaddr, PAGE_SIZE); + u_vaddr &= PAGE_MASK; + + ___flush_dcache_page(paddr, u_vaddr); + + if (vma->vm_flags & VM_EXEC) + __inv_icache_page(paddr, u_vaddr); } void flush_cache_range(struct vm_area_struct *vma, unsigned long start, -- cgit From fedf5b9bafca5cd8af99993d1b9cfd13c1dc2c5b Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 23 May 2013 12:02:00 +0530 Subject: ARC: [mm] optimise VIPT dcache aliasing 2/x Non-congruent SRC page in copy_user_page() is dcache clean in the end - so record that fact, to avoid a subsequent extraneous flush. Signed-off-by: Vineet Gupta --- arch/arc/mm/cache_arc700.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 4e54ef5b4c2a..074658704d86 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -742,6 +742,7 @@ void copy_user_highpage(struct page *to, struct page *from, */ if (clean_src_k_mappings) { __flush_dcache_page(kfrom, kfrom); + clear_bit(PG_arch_1, &from->flags); } else { set_bit(PG_arch_1, &from->flags); } -- cgit From 2ed21dae021db1f9f988494ceee519290217520d Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Mon, 13 May 2013 17:23:58 +0530 Subject: ARC: [mm] Assume pagecache page dirty by default Similar to ARM/SH Signed-off-by: Vineet Gupta --- arch/arc/mm/cache_arc700.c | 12 ++++++------ arch/arc/mm/tlb.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 074658704d86..66c75ee16e50 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -512,7 +512,7 @@ void flush_dcache_page(struct page *page) struct address_space *mapping; if (!cache_is_vipt_aliasing()) { - set_bit(PG_arch_1, &page->flags); + clear_bit(PG_dc_clean, &page->flags); return; } @@ -526,7 +526,7 @@ void flush_dcache_page(struct page *page) * Make a note that K-mapping is dirty */ if (!mapping_mapped(mapping)) { - set_bit(PG_arch_1, &page->flags); + clear_bit(PG_dc_clean, &page->flags); } else if (page_mapped(page)) { /* kernel reading from page with U-mapping */ @@ -734,7 +734,7 @@ void copy_user_highpage(struct page *to, struct page *from, * non copied user pages (e.g. read faults which wire in pagecache page * directly). */ - set_bit(PG_arch_1, &to->flags); + clear_bit(PG_dc_clean, &to->flags); /* * if SRC was already usermapped and non-congruent to kernel mapping @@ -742,16 +742,16 @@ void copy_user_highpage(struct page *to, struct page *from, */ if (clean_src_k_mappings) { __flush_dcache_page(kfrom, kfrom); - clear_bit(PG_arch_1, &from->flags); + set_bit(PG_dc_clean, &from->flags); } else { - set_bit(PG_arch_1, &from->flags); + clear_bit(PG_dc_clean, &from->flags); } } void clear_user_page(void *to, unsigned long u_vaddr, struct page *page) { clear_page(to); - set_bit(PG_arch_1, &page->flags); + clear_bit(PG_dc_clean, &page->flags); } diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 1c91dbc8ddd8..d44ae33c2d1e 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -453,7 +453,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned, if ((vma->vm_flags & VM_EXEC) || addr_not_cache_congruent(paddr, vaddr)) { - int dirty = test_and_clear_bit(PG_arch_1, &page->flags); + int dirty = !test_and_set_bit(PG_dc_clean, &page->flags); if (dirty) { /* wback + inv dcache lines */ __flush_dcache_page(paddr, paddr); -- cgit From 3e1ae441886b82fbf605f37ac0756b811d55f3d5 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 12 Jun 2013 13:49:02 +0530 Subject: ARC: [mm] Remove @write argument to do_page_fault() This can be ascertained within do_page_fault() since it gets the full ECR (Exception Cause Register). Further, for both the callers of do_page_fault(): Prot-V / D-TLB-Miss, the cause sub-fields in ECR are same for same type of access, making the code much more simpler. D-TLB-Miss [LD] 0x00_21_01_00 Prot-V [LD] 0x00_23_01_00 ^^ D-TLB-Miss [ST] 0x00_21_02_00 Prot-V [ST] 0x00_23_02_00 ^^ D-TLB-Miss [EX] 0x00_21_03_00 Prot-V [EX] 0x00_23_03_00 ^^ This helps code consolidation, which is even better when moving code from assembler to "C". Signed-off-by: Vineet Gupta --- arch/arc/mm/fault.c | 3 ++- arch/arc/mm/tlbex.S | 14 ++------------ 2 files changed, 4 insertions(+), 13 deletions(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index c0decc1f8d22..fdafeb1917cc 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -52,7 +52,7 @@ bad_area: return 1; } -void do_page_fault(struct pt_regs *regs, int write, unsigned long address, +void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long cause_code) { struct vm_area_struct *vma = NULL; @@ -60,6 +60,7 @@ void do_page_fault(struct pt_regs *regs, int write, unsigned long address, struct mm_struct *mm = tsk->mm; siginfo_t info; int fault, ret; + int write = cause_code & (1 << ECR_C_BIT_DTLB_ST_MISS); /* ST/EX */ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | (write ? FAULT_FLAG_WRITE : 0); diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S index 7bf811d51af8..bd8bc90f61d3 100644 --- a/arch/arc/mm/tlbex.S +++ b/arch/arc/mm/tlbex.S @@ -381,18 +381,8 @@ do_slow_path_pf: ; ------- setup args for Linux Page fault Hanlder --------- mov_s r0, sp - lr r2, [efa] - lr r3, [ecr] - - ; Both st and ex imply WRITE access of some sort, hence do_page_fault( ) - ; invoked with write=1 for DTLB-st/ex Miss and write=0 for ITLB miss or - ; DTLB-ld Miss - ; DTLB Miss Cause code is ld = 0x01 , st = 0x02, ex = 0x03 - ; Following code uses that fact that st/ex have one bit in common - - btst_s r3, ECR_C_BIT_DTLB_ST_MISS - mov.z r1, 0 - mov.nz r1, 1 + lr r1, [efa] + lr r2, [ecr] ; We don't want exceptions to be disabled while the fault is handled. ; Now that we have saved the context we return from exception hence -- cgit From 38a9ff6d247cf9afcbe55ea245b650b8955029fd Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 12 Jun 2013 15:13:40 +0530 Subject: ARC: Remove explicit passing around of ECR With ECR now part of pt_regs * No need to propagate from lowest asm handlers as arg * No need to save it in tsk->thread.cause_code * Avoid bit chopping to access the bit-fields More code consolidation, cleanup Signed-off-by: Vineet Gupta --- arch/arc/mm/fault.c | 12 +++++------- arch/arc/mm/tlbex.S | 1 - 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index fdafeb1917cc..318164cabdfc 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -52,15 +52,14 @@ bad_area: return 1; } -void do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long cause_code) +void do_page_fault(struct pt_regs *regs, unsigned long address) { struct vm_area_struct *vma = NULL; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; siginfo_t info; int fault, ret; - int write = cause_code & (1 << ECR_C_BIT_DTLB_ST_MISS); /* ST/EX */ + int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | (write ? FAULT_FLAG_WRITE : 0); @@ -111,7 +110,8 @@ good_area: /* Handle protection violation, execute on heap or stack */ - if (cause_code == ((ECR_V_PROTV << 16) | ECR_C_PROTV_INST_FETCH)) + if ((regs->ecr_vec == ECR_V_PROTV) && + (regs->ecr_cause == ECR_C_PROTV_INST_FETCH)) goto bad_area; if (write) { @@ -178,7 +178,6 @@ bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { tsk->thread.fault_address = address; - tsk->thread.cause_code = cause_code; info.si_signo = SIGSEGV; info.si_errno = 0; /* info.si_code has been set above */ @@ -199,7 +198,7 @@ no_context: if (fixup_exception(regs)) return; - die("Oops", regs, address, cause_code); + die("Oops", regs, address); out_of_memory: if (is_global_init(tsk)) { @@ -220,7 +219,6 @@ do_sigbus: goto no_context; tsk->thread.fault_address = address; - tsk->thread.cause_code = cause_code; info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = BUS_ADRERR; diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S index bd8bc90f61d3..8d61fdf7a43b 100644 --- a/arch/arc/mm/tlbex.S +++ b/arch/arc/mm/tlbex.S @@ -382,7 +382,6 @@ do_slow_path_pf: ; ------- setup args for Linux Page fault Hanlder --------- mov_s r0, sp lr r1, [efa] - lr r2, [ecr] ; We don't want exceptions to be disabled while the fault is handled. ; Now that we have saved the context we return from exception hence -- cgit From c3e757a77cab461d11cd3e365d700e8c8fb3fae0 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Mon, 17 Jun 2013 11:35:15 +0530 Subject: ARC: [tlb-miss] Extraneous PTE bit testing/setting * No need to check for READ access in I-TLB Miss handler * Redundant PAGE_PRESENT update in PTE Post TLB entry installation, in updating PTE for software accessed/dity bits, no need to update PAGE_PRESENT since it will already be set. Infact the entry won't have installed if !PAGE_PRESENT. Signed-off-by: Vineet Gupta --- arch/arc/mm/tlbex.S | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S index 8d61fdf7a43b..fcdc19ff6da7 100644 --- a/arch/arc/mm/tlbex.S +++ b/arch/arc/mm/tlbex.S @@ -277,16 +277,16 @@ ARC_ENTRY EV_TLBMissI ;---------------------------------------------------------------- ; VERIFY_PTE: Check if PTE permissions approp for executing code cmp_s r2, VMALLOC_START - mov.lo r2, (_PAGE_PRESENT | _PAGE_U_READ | _PAGE_U_EXECUTE) - mov.hs r2, (_PAGE_PRESENT | _PAGE_K_READ | _PAGE_K_EXECUTE) + mov.lo r2, (_PAGE_PRESENT | _PAGE_U_EXECUTE) + mov.hs r2, (_PAGE_PRESENT | _PAGE_K_EXECUTE) and r3, r0, r2 ; Mask out NON Flag bits from PTE xor.f r3, r3, r2 ; check ( ( pte & flags_test ) == flags_test ) bnz do_slow_path_pf ; Let Linux VM know that the page was accessed - or r0, r0, (_PAGE_PRESENT | _PAGE_ACCESSED) ; set Accessed Bit - st_s r0, [r1] ; Write back PTE + or r0, r0, _PAGE_ACCESSED ; set Accessed Bit + st_s r0, [r1] ; Write back PTE CONV_PTE_TO_TLB COMMIT_ENTRY_TO_MMU @@ -345,7 +345,7 @@ ARC_ENTRY EV_TLBMissD ;---------------------------------------------------------------- ; UPDATE_PTE: Let Linux VM know that page was accessed/dirty lr r3, [ecr] - or r0, r0, (_PAGE_PRESENT | _PAGE_ACCESSED) ; Accessed bit always + or r0, r0, _PAGE_ACCESSED ; Accessed bit always btst_s r3, ECR_C_BIT_DTLB_ST_MISS ; See if it was a Write Access ? or.nz r0, r0, _PAGE_MODIFIED ; if Write, set Dirty bit as well st_s r0, [r1] ; Write back PTE -- cgit From dc81df244028e0d07c8723e3f7ebd1a35e848293 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Mon, 17 Jun 2013 14:33:15 +0530 Subject: ARC: [tlb-miss] Fix bug with CONFIG_ARC_DBG_TLB_MISS_COUNT LOAD_FAULT_PTE macro is expected to set r2 with faulting vaddr. However in case of CONFIG_ARC_DBG_TLB_MISS_COUNT, it was getting clobbered with statistics collection code. Fix latter by using a different register. Note that only I-TLB Miss handler was potentially affected. Signed-off-by: Vineet Gupta --- arch/arc/mm/tlbex.S | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S index fcdc19ff6da7..5c5bb23001b0 100644 --- a/arch/arc/mm/tlbex.S +++ b/arch/arc/mm/tlbex.S @@ -147,9 +147,9 @@ ex_saved_reg1: #ifdef CONFIG_ARC_DBG_TLB_MISS_COUNT and.f 0, r0, _PAGE_PRESENT bz 1f - ld r2, [num_pte_not_present] - add r2, r2, 1 - st r2, [num_pte_not_present] + ld r3, [num_pte_not_present] + add r3, r3, 1 + st r3, [num_pte_not_present] 1: #endif @@ -271,7 +271,7 @@ ARC_ENTRY EV_TLBMissI #endif ;---------------------------------------------------------------- - ; Get the PTE corresponding to V-addr accessed + ; Get the PTE corresponding to V-addr accessed, r2 is setup with EFA LOAD_FAULT_PTE ;---------------------------------------------------------------- @@ -311,7 +311,7 @@ ARC_ENTRY EV_TLBMissD ;---------------------------------------------------------------- ; Get the PTE corresponding to V-addr accessed - ; If PTE exists, it will setup, r0 = PTE, r1 = Ptr to PTE + ; If PTE exists, it will setup, r0 = PTE, r1 = Ptr to PTE, r2 = EFA LOAD_FAULT_PTE ;---------------------------------------------------------------- -- cgit From ce7599567e27eabc1003e35b6f05579268dafecd Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 24 Jun 2013 15:30:15 -0400 Subject: arc: delete __cpuinit usage from all arc files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/arc uses of the __cpuinit macros from all C files. Currently arc does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Vineet Gupta Signed-off-by: Paul Gortmaker Signed-off-by: Vineet Gupta --- arch/arc/mm/cache_arc700.c | 4 ++-- arch/arc/mm/tlb.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/arc/mm') diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 66c75ee16e50..f415d851b765 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -129,7 +129,7 @@ char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len) * the cpuinfo structure for later use. * No Validation done here, simply read/convert the BCRs */ -void __cpuinit read_decode_cache_bcr(void) +void read_decode_cache_bcr(void) { struct cpuinfo_arc_cache *p_ic, *p_dc; unsigned int cpu = smp_processor_id(); @@ -167,7 +167,7 @@ void __cpuinit read_decode_cache_bcr(void) * 3. Enable the Caches, setup default flush mode for D-Cache * 3. Calculate the SHMLBA used by user space */ -void __cpuinit arc_cache_init(void) +void arc_cache_init(void) { unsigned int cpu = smp_processor_id(); struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache; diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index d44ae33c2d1e..7957dc4e4d4a 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -469,7 +469,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned, * the cpuinfo structure for later use. * No Validation is done here, simply read/convert the BCRs */ -void __cpuinit read_decode_mmu_bcr(void) +void read_decode_mmu_bcr(void) { struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; unsigned int tmp; @@ -530,7 +530,7 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len) return buf; } -void __cpuinit arc_mmu_init(void) +void arc_mmu_init(void) { char str[256]; struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; -- cgit