aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2017-02-09 10:20:06 -0500
committerJames Hogan <james.hogan@imgtec.com>2017-02-13 13:57:31 -0500
commitf700a420088624671ed955bf818c17012bb57bca (patch)
treeedb0148c355db8c8f02b550181a250e94e8c93db
parent98e58b01e1671e5784c67972ec1b58a8997f784e (diff)
parent7170bdc777556dad87f92e6a73a6cc557bf3290e (diff)
Merge tag 'mips_kvm_4.11_1' into mips-for-linux-next
MIPS dependencies for KVM Miscellaneous MIPS architecture changes depended on by the MIPS KVM changes in the KVM tree. - Move pgd_alloc() out of header. - Exports so KVM can access page table management and TLBEX functions. - Add return errors to protected cache ops.
-rw-r--r--arch/mips/include/asm/pgalloc.h16
-rw-r--r--arch/mips/include/asm/r4kcache.h55
-rw-r--r--arch/mips/include/asm/tlbex.h26
-rw-r--r--arch/mips/include/asm/uasm.h5
-rw-r--r--arch/mips/mm/Makefile2
-rw-r--r--arch/mips/mm/init.c1
-rw-r--r--arch/mips/mm/pgtable-64.c2
-rw-r--r--arch/mips/mm/pgtable.c25
-rw-r--r--arch/mips/mm/tlbex.c38
9 files changed, 116 insertions, 54 deletions
diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h
index a03e86969f78..a8705f6c8180 100644
--- a/arch/mips/include/asm/pgalloc.h
+++ b/arch/mips/include/asm/pgalloc.h
@@ -43,21 +43,7 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
43 * Initialize a new pgd / pmd table with invalid pointers. 43 * Initialize a new pgd / pmd table with invalid pointers.
44 */ 44 */
45extern void pgd_init(unsigned long page); 45extern void pgd_init(unsigned long page);
46 46extern pgd_t *pgd_alloc(struct mm_struct *mm);
47static inline pgd_t *pgd_alloc(struct mm_struct *mm)
48{
49 pgd_t *ret, *init;
50
51 ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER);
52 if (ret) {
53 init = pgd_offset(&init_mm, 0UL);
54 pgd_init((unsigned long)ret);
55 memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
56 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
57 }
58
59 return ret;
60}
61 47
62static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) 48static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
63{ 49{
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index b42b513007a2..7227c158cbf8 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -147,49 +147,64 @@ static inline void flush_scache_line(unsigned long addr)
147} 147}
148 148
149#define protected_cache_op(op,addr) \ 149#define protected_cache_op(op,addr) \
150({ \
151 int __err = 0; \
150 __asm__ __volatile__( \ 152 __asm__ __volatile__( \
151 " .set push \n" \ 153 " .set push \n" \
152 " .set noreorder \n" \ 154 " .set noreorder \n" \
153 " .set "MIPS_ISA_ARCH_LEVEL" \n" \ 155 " .set "MIPS_ISA_ARCH_LEVEL" \n" \
154 "1: cache %0, (%1) \n" \ 156 "1: cache %1, (%2) \n" \
155 "2: .set pop \n" \ 157 "2: .set pop \n" \
158 " .section .fixup,\"ax\" \n" \
159 "3: li %0, %3 \n" \
160 " j 2b \n" \
161 " .previous \n" \
156 " .section __ex_table,\"a\" \n" \ 162 " .section __ex_table,\"a\" \n" \
157 " "STR(PTR)" 1b, 2b \n" \ 163 " "STR(PTR)" 1b, 3b \n" \
158 " .previous" \ 164 " .previous" \
159 : \ 165 : "+r" (__err) \
160 : "i" (op), "r" (addr)) 166 : "i" (op), "r" (addr), "i" (-EFAULT)); \
167 __err; \
168})
169
161 170
162#define protected_cachee_op(op,addr) \ 171#define protected_cachee_op(op,addr) \
172({ \
173 int __err = 0; \
163 __asm__ __volatile__( \ 174 __asm__ __volatile__( \
164 " .set push \n" \ 175 " .set push \n" \
165 " .set noreorder \n" \ 176 " .set noreorder \n" \
166 " .set mips0 \n" \ 177 " .set mips0 \n" \
167 " .set eva \n" \ 178 " .set eva \n" \
168 "1: cachee %0, (%1) \n" \ 179 "1: cachee %1, (%2) \n" \
169 "2: .set pop \n" \ 180 "2: .set pop \n" \
181 " .section .fixup,\"ax\" \n" \
182 "3: li %0, %3 \n" \
183 " j 2b \n" \
184 " .previous \n" \
170 " .section __ex_table,\"a\" \n" \ 185 " .section __ex_table,\"a\" \n" \
171 " "STR(PTR)" 1b, 2b \n" \ 186 " "STR(PTR)" 1b, 3b \n" \
172 " .previous" \ 187 " .previous" \
173 : \ 188 : "+r" (__err) \
174 : "i" (op), "r" (addr)) 189 : "i" (op), "r" (addr), "i" (-EFAULT)); \
190 __err; \
191})
175 192
176/* 193/*
177 * The next two are for badland addresses like signal trampolines. 194 * The next two are for badland addresses like signal trampolines.
178 */ 195 */
179static inline void protected_flush_icache_line(unsigned long addr) 196static inline int protected_flush_icache_line(unsigned long addr)
180{ 197{
181 switch (boot_cpu_type()) { 198 switch (boot_cpu_type()) {
182 case CPU_LOONGSON2: 199 case CPU_LOONGSON2:
183 protected_cache_op(Hit_Invalidate_I_Loongson2, addr); 200 return protected_cache_op(Hit_Invalidate_I_Loongson2, addr);
184 break;
185 201
186 default: 202 default:
187#ifdef CONFIG_EVA 203#ifdef CONFIG_EVA
188 protected_cachee_op(Hit_Invalidate_I, addr); 204 return protected_cachee_op(Hit_Invalidate_I, addr);
189#else 205#else
190 protected_cache_op(Hit_Invalidate_I, addr); 206 return protected_cache_op(Hit_Invalidate_I, addr);
191#endif 207#endif
192 break;
193 } 208 }
194} 209}
195 210
@@ -199,21 +214,21 @@ static inline void protected_flush_icache_line(unsigned long addr)
199 * caches. We're talking about one cacheline unnecessarily getting invalidated 214 * caches. We're talking about one cacheline unnecessarily getting invalidated
200 * here so the penalty isn't overly hard. 215 * here so the penalty isn't overly hard.
201 */ 216 */
202static inline void protected_writeback_dcache_line(unsigned long addr) 217static inline int protected_writeback_dcache_line(unsigned long addr)
203{ 218{
204#ifdef CONFIG_EVA 219#ifdef CONFIG_EVA
205 protected_cachee_op(Hit_Writeback_Inv_D, addr); 220 return protected_cachee_op(Hit_Writeback_Inv_D, addr);
206#else 221#else
207 protected_cache_op(Hit_Writeback_Inv_D, addr); 222 return protected_cache_op(Hit_Writeback_Inv_D, addr);
208#endif 223#endif
209} 224}
210 225
211static inline void protected_writeback_scache_line(unsigned long addr) 226static inline int protected_writeback_scache_line(unsigned long addr)
212{ 227{
213#ifdef CONFIG_EVA 228#ifdef CONFIG_EVA
214 protected_cachee_op(Hit_Writeback_Inv_SD, addr); 229 return protected_cachee_op(Hit_Writeback_Inv_SD, addr);
215#else 230#else
216 protected_cache_op(Hit_Writeback_Inv_SD, addr); 231 return protected_cache_op(Hit_Writeback_Inv_SD, addr);
217#endif 232#endif
218} 233}
219 234
diff --git a/arch/mips/include/asm/tlbex.h b/arch/mips/include/asm/tlbex.h
new file mode 100644
index 000000000000..53050e9dd2c9
--- /dev/null
+++ b/arch/mips/include/asm/tlbex.h
@@ -0,0 +1,26 @@
1#ifndef __ASM_TLBEX_H
2#define __ASM_TLBEX_H
3
4#include <asm/uasm.h>
5
6/*
7 * Write random or indexed TLB entry, and care about the hazards from
8 * the preceding mtc0 and for the following eret.
9 */
10enum tlb_write_entry {
11 tlb_random,
12 tlb_indexed
13};
14
15extern int pgd_reg;
16
17void build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
18 unsigned int tmp, unsigned int ptr);
19void build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr);
20void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr);
21void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep);
22void build_tlb_write_entry(u32 **p, struct uasm_label **l,
23 struct uasm_reloc **r,
24 enum tlb_write_entry wmode);
25
26#endif /* __ASM_TLBEX_H */
diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h
index f7929f65f7ca..e9a9e2ade1d2 100644
--- a/arch/mips/include/asm/uasm.h
+++ b/arch/mips/include/asm/uasm.h
@@ -9,6 +9,9 @@
9 * Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved. 9 * Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved.
10 */ 10 */
11 11
12#ifndef __ASM_UASM_H
13#define __ASM_UASM_H
14
12#include <linux/types.h> 15#include <linux/types.h>
13 16
14#ifdef CONFIG_EXPORT_UASM 17#ifdef CONFIG_EXPORT_UASM
@@ -309,3 +312,5 @@ void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
309void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1, 312void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1,
310 unsigned int reg2, int lid); 313 unsigned int reg2, int lid);
311void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); 314void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
315
316#endif /* __ASM_UASM_H */
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index b4c64bd3f723..b4cc8811a664 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -4,7 +4,7 @@
4 4
5obj-y += cache.o dma-default.o extable.o fault.o \ 5obj-y += cache.o dma-default.o extable.o fault.o \
6 gup.o init.o mmap.o page.o page-funcs.o \ 6 gup.o init.o mmap.o page.o page-funcs.o \
7 tlbex.o tlbex-fault.o tlb-funcs.o 7 pgtable.o tlbex.o tlbex-fault.o tlb-funcs.o
8 8
9ifdef CONFIG_CPU_MICROMIPS 9ifdef CONFIG_CPU_MICROMIPS
10obj-y += uasm-micromips.o 10obj-y += uasm-micromips.o
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 9d1d54b8e1e8..aa75849c36bc 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -539,6 +539,7 @@ unsigned long pgd_current[NR_CPUS];
539pgd_t swapper_pg_dir[_PTRS_PER_PGD] __section(.bss..swapper_pg_dir); 539pgd_t swapper_pg_dir[_PTRS_PER_PGD] __section(.bss..swapper_pg_dir);
540#ifndef __PAGETABLE_PMD_FOLDED 540#ifndef __PAGETABLE_PMD_FOLDED
541pmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned_bss; 541pmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned_bss;
542EXPORT_SYMBOL_GPL(invalid_pmd_table);
542#endif 543#endif
543pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss; 544pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss;
544EXPORT_SYMBOL(invalid_pte_table); 545EXPORT_SYMBOL(invalid_pte_table);
diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c
index ce4473e7c0d2..0ae7b28b4db5 100644
--- a/arch/mips/mm/pgtable-64.c
+++ b/arch/mips/mm/pgtable-64.c
@@ -6,6 +6,7 @@
6 * Copyright (C) 1999, 2000 by Silicon Graphics 6 * Copyright (C) 1999, 2000 by Silicon Graphics
7 * Copyright (C) 2003 by Ralf Baechle 7 * Copyright (C) 2003 by Ralf Baechle
8 */ 8 */
9#include <linux/export.h>
9#include <linux/init.h> 10#include <linux/init.h>
10#include <linux/mm.h> 11#include <linux/mm.h>
11#include <asm/fixmap.h> 12#include <asm/fixmap.h>
@@ -60,6 +61,7 @@ void pmd_init(unsigned long addr, unsigned long pagetable)
60 p[-1] = pagetable; 61 p[-1] = pagetable;
61 } while (p != end); 62 } while (p != end);
62} 63}
64EXPORT_SYMBOL_GPL(pmd_init);
63#endif 65#endif
64 66
65pmd_t mk_pmd(struct page *page, pgprot_t prot) 67pmd_t mk_pmd(struct page *page, pgprot_t prot)
diff --git a/arch/mips/mm/pgtable.c b/arch/mips/mm/pgtable.c
new file mode 100644
index 000000000000..05560b042d82
--- /dev/null
+++ b/arch/mips/mm/pgtable.c
@@ -0,0 +1,25 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 */
6#include <linux/export.h>
7#include <linux/mm.h>
8#include <linux/string.h>
9#include <asm/pgalloc.h>
10
11pgd_t *pgd_alloc(struct mm_struct *mm)
12{
13 pgd_t *ret, *init;
14
15 ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER);
16 if (ret) {
17 init = pgd_offset(&init_mm, 0UL);
18 pgd_init((unsigned long)ret);
19 memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
20 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
21 }
22
23 return ret;
24}
25EXPORT_SYMBOL_GPL(pgd_alloc);
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 87eed65660f5..9bfee8988eaf 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -22,6 +22,7 @@
22 */ 22 */
23 23
24#include <linux/bug.h> 24#include <linux/bug.h>
25#include <linux/export.h>
25#include <linux/kernel.h> 26#include <linux/kernel.h>
26#include <linux/types.h> 27#include <linux/types.h>
27#include <linux/smp.h> 28#include <linux/smp.h>
@@ -34,6 +35,7 @@
34#include <asm/war.h> 35#include <asm/war.h>
35#include <asm/uasm.h> 36#include <asm/uasm.h>
36#include <asm/setup.h> 37#include <asm/setup.h>
38#include <asm/tlbex.h>
37 39
38static int mips_xpa_disabled; 40static int mips_xpa_disabled;
39 41
@@ -344,7 +346,8 @@ static int allocate_kscratch(void)
344} 346}
345 347
346static int scratch_reg; 348static int scratch_reg;
347static int pgd_reg; 349int pgd_reg;
350EXPORT_SYMBOL_GPL(pgd_reg);
348enum vmalloc64_mode {not_refill, refill_scratch, refill_noscratch}; 351enum vmalloc64_mode {not_refill, refill_scratch, refill_noscratch};
349 352
350static struct work_registers build_get_work_registers(u32 **p) 353static struct work_registers build_get_work_registers(u32 **p)
@@ -496,15 +499,9 @@ static void __maybe_unused build_tlb_probe_entry(u32 **p)
496 } 499 }
497} 500}
498 501
499/* 502void build_tlb_write_entry(u32 **p, struct uasm_label **l,
500 * Write random or indexed TLB entry, and care about the hazards from 503 struct uasm_reloc **r,
501 * the preceding mtc0 and for the following eret. 504 enum tlb_write_entry wmode)
502 */
503enum tlb_write_entry { tlb_random, tlb_indexed };
504
505static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
506 struct uasm_reloc **r,
507 enum tlb_write_entry wmode)
508{ 505{
509 void(*tlbw)(u32 **) = NULL; 506 void(*tlbw)(u32 **) = NULL;
510 507
@@ -627,6 +624,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
627 break; 624 break;
628 } 625 }
629} 626}
627EXPORT_SYMBOL_GPL(build_tlb_write_entry);
630 628
631static __maybe_unused void build_convert_pte_to_entrylo(u32 **p, 629static __maybe_unused void build_convert_pte_to_entrylo(u32 **p,
632 unsigned int reg) 630 unsigned int reg)
@@ -781,9 +779,8 @@ static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r,
781 * TMP and PTR are scratch. 779 * TMP and PTR are scratch.
782 * TMP will be clobbered, PTR will hold the pmd entry. 780 * TMP will be clobbered, PTR will hold the pmd entry.
783 */ 781 */
784static void 782void build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
785build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, 783 unsigned int tmp, unsigned int ptr)
786 unsigned int tmp, unsigned int ptr)
787{ 784{
788#ifndef CONFIG_MIPS_PGD_C0_CONTEXT 785#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
789 long pgdc = (long)pgd_current; 786 long pgdc = (long)pgd_current;
@@ -859,6 +856,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
859 uasm_i_daddu(p, ptr, ptr, tmp); /* add in pmd offset */ 856 uasm_i_daddu(p, ptr, ptr, tmp); /* add in pmd offset */
860#endif 857#endif
861} 858}
859EXPORT_SYMBOL_GPL(build_get_pmde64);
862 860
863/* 861/*
864 * BVADDR is the faulting address, PTR is scratch. 862 * BVADDR is the faulting address, PTR is scratch.
@@ -934,8 +932,7 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
934 * TMP and PTR are scratch. 932 * TMP and PTR are scratch.
935 * TMP will be clobbered, PTR will hold the pgd entry. 933 * TMP will be clobbered, PTR will hold the pgd entry.
936 */ 934 */
937static void __maybe_unused 935void build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
938build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
939{ 936{
940 if (pgd_reg != -1) { 937 if (pgd_reg != -1) {
941 /* pgd is in pgd_reg */ 938 /* pgd is in pgd_reg */
@@ -960,6 +957,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
960 uasm_i_sll(p, tmp, tmp, PGD_T_LOG2); 957 uasm_i_sll(p, tmp, tmp, PGD_T_LOG2);
961 uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */ 958 uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
962} 959}
960EXPORT_SYMBOL_GPL(build_get_pgde32);
963 961
964#endif /* !CONFIG_64BIT */ 962#endif /* !CONFIG_64BIT */
965 963
@@ -989,7 +987,7 @@ static void build_adjust_context(u32 **p, unsigned int ctx)
989 uasm_i_andi(p, ctx, ctx, mask); 987 uasm_i_andi(p, ctx, ctx, mask);
990} 988}
991 989
992static void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) 990void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr)
993{ 991{
994 /* 992 /*
995 * Bug workaround for the Nevada. It seems as if under certain 993 * Bug workaround for the Nevada. It seems as if under certain
@@ -1013,8 +1011,9 @@ static void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr)
1013 build_adjust_context(p, tmp); 1011 build_adjust_context(p, tmp);
1014 UASM_i_ADDU(p, ptr, ptr, tmp); /* add in offset */ 1012 UASM_i_ADDU(p, ptr, ptr, tmp); /* add in offset */
1015} 1013}
1014EXPORT_SYMBOL_GPL(build_get_ptep);
1016 1015
1017static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) 1016void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
1018{ 1017{
1019 int pte_off_even = 0; 1018 int pte_off_even = 0;
1020 int pte_off_odd = sizeof(pte_t); 1019 int pte_off_odd = sizeof(pte_t);
@@ -1063,6 +1062,7 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
1063 UASM_i_MTC0(p, 0, C0_ENTRYLO1); 1062 UASM_i_MTC0(p, 0, C0_ENTRYLO1);
1064 UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */ 1063 UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
1065} 1064}
1065EXPORT_SYMBOL_GPL(build_update_entries);
1066 1066
1067struct mips_huge_tlb_info { 1067struct mips_huge_tlb_info {
1068 int huge_pte; 1068 int huge_pte;
@@ -1536,7 +1536,9 @@ static void build_loongson3_tlb_refill_handler(void)
1536extern u32 handle_tlbl[], handle_tlbl_end[]; 1536extern u32 handle_tlbl[], handle_tlbl_end[];
1537extern u32 handle_tlbs[], handle_tlbs_end[]; 1537extern u32 handle_tlbs[], handle_tlbs_end[];
1538extern u32 handle_tlbm[], handle_tlbm_end[]; 1538extern u32 handle_tlbm[], handle_tlbm_end[];
1539extern u32 tlbmiss_handler_setup_pgd_start[], tlbmiss_handler_setup_pgd[]; 1539extern u32 tlbmiss_handler_setup_pgd_start[];
1540extern u32 tlbmiss_handler_setup_pgd[];
1541EXPORT_SYMBOL_GPL(tlbmiss_handler_setup_pgd);
1540extern u32 tlbmiss_handler_setup_pgd_end[]; 1542extern u32 tlbmiss_handler_setup_pgd_end[];
1541 1543
1542static void build_setup_pgd(void) 1544static void build_setup_pgd(void)