From e03ac9f0c3f5f2e79c41fd02d9b90831dfd78a2e Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Tue, 8 Dec 2015 13:27:02 -0500 Subject: mips: Fix CPC_BASE_ADDR mask to match datasheet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to 'MIPS32® interAptivTM Multiprocessing System Programmer’s Guide' CPC_BASE_ADDR takes bits [31:15]. This change is tested ith mt7621 which wasn't working without it. Signed-off-by: Nikolay Martynov Reviewed-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11766/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index d4635391c36a..4ac8e4b69fb5 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -290,8 +290,8 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) #define CM_GCR_GIC_BASE_GICEN_MSK (_ULCAST_(0x1) << 0) /* GCR_CPC_BASE register fields */ -#define CM_GCR_CPC_BASE_CPCBASE_SHF 17 -#define CM_GCR_CPC_BASE_CPCBASE_MSK (_ULCAST_(0x7fff) << 17) +#define CM_GCR_CPC_BASE_CPCBASE_SHF 15 +#define CM_GCR_CPC_BASE_CPCBASE_MSK (_ULCAST_(0x1ffff) << 15) #define CM_GCR_CPC_BASE_CPCEN_SHF 0 #define CM_GCR_CPC_BASE_CPCEN_MSK (_ULCAST_(0x1) << 0) -- cgit v1.2.3 From a7e89326b415b5d81c4b1016fd4a40db861eb58d Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 1 Mar 2016 22:19:36 +0000 Subject: MIPS: Fix watchpoint restoration Commit f51246efee2b ("MIPS: Get rid of finish_arch_switch().") moved the __restore_watch() call from finish_arch_switch() (i.e. after resume() returns) to before the resume() call in switch_to(). This results in watchpoints only being restored when a task is descheduled, preventing the watchpoints from being effective most of the time, except due to chance before the watchpoints are lazily removed. Fix the call sequence from switch_to() through to mips_install_watch_registers() to pass the task_struct pointer of the next task, instead of using current. This allows the watchpoints for the next (non-current) task to be restored without reintroducing finish_arch_switch(). Fixes: f51246efee2b ("MIPS: Get rid of finish_arch_switch().") Signed-off-by: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: # 4.3.x- Patchwork: https://patchwork.linux-mips.org/patch/12726/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/switch_to.h | 2 +- arch/mips/include/asm/watch.h | 10 +++++----- arch/mips/kernel/pm.c | 2 +- arch/mips/kernel/watch.c | 5 ++--- 4 files changed, 9 insertions(+), 10 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h index 28b5d84a5022..ebb5c0f2f90d 100644 --- a/arch/mips/include/asm/switch_to.h +++ b/arch/mips/include/asm/switch_to.h @@ -105,7 +105,7 @@ do { \ __clear_software_ll_bit(); \ if (cpu_has_userlocal) \ write_c0_userlocal(task_thread_info(next)->tp_value); \ - __restore_watch(); \ + __restore_watch(next); \ (last) = resume(prev, next, task_thread_info(next)); \ } while (0) diff --git a/arch/mips/include/asm/watch.h b/arch/mips/include/asm/watch.h index 20126ec79359..6ffe3eadf105 100644 --- a/arch/mips/include/asm/watch.h +++ b/arch/mips/include/asm/watch.h @@ -12,21 +12,21 @@ #include -void mips_install_watch_registers(void); +void mips_install_watch_registers(struct task_struct *t); void mips_read_watch_registers(void); void mips_clear_watch_registers(void); void mips_probe_watch_registers(struct cpuinfo_mips *c); #ifdef CONFIG_HARDWARE_WATCHPOINTS -#define __restore_watch() do { \ +#define __restore_watch(task) do { \ if (unlikely(test_bit(TIF_LOAD_WATCH, \ - ¤t_thread_info()->flags))) { \ - mips_install_watch_registers(); \ + &task_thread_info(task)->flags))) { \ + mips_install_watch_registers(task); \ } \ } while (0) #else -#define __restore_watch() do {} while (0) +#define __restore_watch(task) do {} while (0) #endif #endif /* _ASM_WATCH_H */ diff --git a/arch/mips/kernel/pm.c b/arch/mips/kernel/pm.c index fefdf39d3df3..dc814892133c 100644 --- a/arch/mips/kernel/pm.c +++ b/arch/mips/kernel/pm.c @@ -56,7 +56,7 @@ static void mips_cpu_restore(void) write_c0_userlocal(current_thread_info()->tp_value); /* Restore watch registers */ - __restore_watch(); + __restore_watch(current); } /** diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c index 2a03abb5bd2c..9b78e375118e 100644 --- a/arch/mips/kernel/watch.c +++ b/arch/mips/kernel/watch.c @@ -15,10 +15,9 @@ * Install the watch registers for the current thread. A maximum of * four registers are installed although the machine may have more. */ -void mips_install_watch_registers(void) +void mips_install_watch_registers(struct task_struct *t) { - struct mips3264_watch_reg_state *watches = - ¤t->thread.watch.mips3264; + struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264; switch (current_cpu_data.watch_reg_use_cnt) { default: BUG(); -- cgit v1.2.3 From 8a3c8b48aca8771bff3536e40aa26ffb311699d1 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 15 Apr 2016 10:07:23 +0100 Subject: MIPS: Use copy_s.fmt rather than copy_u.fmt In revision 1.12 of the MSA specification, the copy_u.w instruction has been removed for MIPS32 & the copy_u.d instruction has been removed for MIPS64. Newer toolchains (eg. Codescape SDK essentials 2015.10) will complain about this like so: arch/mips/kernel/r4k_fpu.S:290: Error: opcode not supported on this processor: mips32r2 (mips32r2) `copy_u.w $1,$w26[3]' Since we always copy to the width of a GPR, simply use copy_s instead of copy_u to fix this. Signed-off-by: Paul Burton Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Cc: # 4.3.x+ Patchwork: https://patchwork.linux-mips.org/patch/13061/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/asmmacro.h | 24 ++++++++++++------------ arch/mips/kernel/r4k_fpu.S | 10 +++++----- 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index 867f924b05c7..b99b38862fcb 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -298,21 +298,21 @@ .set pop .endm - .macro copy_u_w ws, n + .macro copy_s_w ws, n .set push .set mips32r2 .set fp=64 .set msa - copy_u.w $1, $w\ws[\n] + copy_s.w $1, $w\ws[\n] .set pop .endm - .macro copy_u_d ws, n + .macro copy_s_d ws, n .set push .set mips64r2 .set fp=64 .set msa - copy_u.d $1, $w\ws[\n] + copy_s.d $1, $w\ws[\n] .set pop .endm @@ -346,8 +346,8 @@ #define STH_MSA_INSN 0x5800081f #define STW_MSA_INSN 0x5800082f #define STD_MSA_INSN 0x5800083f -#define COPY_UW_MSA_INSN 0x58f00056 -#define COPY_UD_MSA_INSN 0x58f80056 +#define COPY_SW_MSA_INSN 0x58b00056 +#define COPY_SD_MSA_INSN 0x58b80056 #define INSERT_W_MSA_INSN 0x59300816 #define INSERT_D_MSA_INSN 0x59380816 #else @@ -361,8 +361,8 @@ #define STH_MSA_INSN 0x78000825 #define STW_MSA_INSN 0x78000826 #define STD_MSA_INSN 0x78000827 -#define COPY_UW_MSA_INSN 0x78f00059 -#define COPY_UD_MSA_INSN 0x78f80059 +#define COPY_SW_MSA_INSN 0x78b00059 +#define COPY_SD_MSA_INSN 0x78b80059 #define INSERT_W_MSA_INSN 0x79300819 #define INSERT_D_MSA_INSN 0x79380819 #endif @@ -461,21 +461,21 @@ .set pop .endm - .macro copy_u_w ws, n + .macro copy_s_w ws, n .set push .set noat SET_HARDFLOAT .insn - .word COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11) + .word COPY_SW_MSA_INSN | (\n << 16) | (\ws << 11) .set pop .endm - .macro copy_u_d ws, n + .macro copy_s_d ws, n .set push .set noat SET_HARDFLOAT .insn - .word COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11) + .word COPY_SD_MSA_INSN | (\n << 16) | (\ws << 11) .set pop .endm diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S index 17732f876eff..56d86b09c917 100644 --- a/arch/mips/kernel/r4k_fpu.S +++ b/arch/mips/kernel/r4k_fpu.S @@ -244,17 +244,17 @@ LEAF(\name) .set push .set noat #ifdef CONFIG_64BIT - copy_u_d \wr, 1 + copy_s_d \wr, 1 EX sd $1, \off(\base) #elif defined(CONFIG_CPU_LITTLE_ENDIAN) - copy_u_w \wr, 2 + copy_s_w \wr, 2 EX sw $1, \off(\base) - copy_u_w \wr, 3 + copy_s_w \wr, 3 EX sw $1, (\off+4)(\base) #else /* CONFIG_CPU_BIG_ENDIAN */ - copy_u_w \wr, 2 + copy_s_w \wr, 2 EX sw $1, (\off+4)(\base) - copy_u_w \wr, 3 + copy_s_w \wr, 3 EX sw $1, \off(\base) #endif .set pop -- cgit v1.2.3 From ea1688573426adc2587ed52d086b51c7c62eaca3 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 15 Apr 2016 10:07:24 +0100 Subject: MIPS: Fix MSA ld_*/st_* asm macros to use PTR_ADDU The MSA ld_*/st_* assembler macros for when the toolchain doesn't support MSA use addu to offset the base address. However it is a virtual memory pointer so fix it to use PTR_ADDU which expands to daddu for 64-bit kernels. Signed-off-by: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: # 4.3.y- Patchwork: https://patchwork.linux-mips.org/patch/13062/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/asmmacro.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index b99b38862fcb..e689b894353c 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -393,7 +393,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word LDB_MSA_INSN | (\wd << 6) .set pop .endm @@ -402,7 +402,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word LDH_MSA_INSN | (\wd << 6) .set pop .endm @@ -411,7 +411,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word LDW_MSA_INSN | (\wd << 6) .set pop .endm @@ -420,7 +420,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word LDD_MSA_INSN | (\wd << 6) .set pop .endm @@ -429,7 +429,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word STB_MSA_INSN | (\wd << 6) .set pop .endm @@ -438,7 +438,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word STH_MSA_INSN | (\wd << 6) .set pop .endm @@ -447,7 +447,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word STW_MSA_INSN | (\wd << 6) .set pop .endm @@ -456,7 +456,7 @@ .set push .set noat SET_HARDFLOAT - addu $1, \base, \off + PTR_ADDU $1, \base, \off .word STD_MSA_INSN | (\wd << 6) .set pop .endm -- cgit v1.2.3 From 143e93d74e19febd491792cdd3aec3054883b776 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 15 Apr 2016 10:07:25 +0100 Subject: MIPS: Fix MSA assembly with big thread offsets When lockdep is enabled on a 64-bit kernel the FPR offset into the thread structure exceeds the maximum range of the MSA ld.d/st.d instructions. For example THREAD_FPR31 = 4644 (instead of 2448), while the signed immediate field is only 10 bits with an implicit multiply by 8, giving a maximum offset of 511*8 = 4088. This isn't a problem when the toolchain doesn't support MSA as the ld_*/st_* macros perform the addition separately into $1 with [d]addui which has a 16bit signed immediate field. Fix the case where the toolchain does support MSA by doing a single addition of THREAD_FPR0 into $1 with [d]addui, and doing the ld_*/st_* relative to that. Signed-off-by: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13064/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/asmmacro.h | 149 ++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 66 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index e689b894353c..637fccab5604 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -496,41 +496,52 @@ .endm #endif +#ifdef TOOLCHAIN_SUPPORTS_MSA +#define FPR_BASE_OFFS THREAD_FPR0 +#define FPR_BASE $1 +#else +#define FPR_BASE_OFFS 0 +#define FPR_BASE \thread +#endif + .macro msa_save_all thread - st_d 0, THREAD_FPR0, \thread - st_d 1, THREAD_FPR1, \thread - st_d 2, THREAD_FPR2, \thread - st_d 3, THREAD_FPR3, \thread - st_d 4, THREAD_FPR4, \thread - st_d 5, THREAD_FPR5, \thread - st_d 6, THREAD_FPR6, \thread - st_d 7, THREAD_FPR7, \thread - st_d 8, THREAD_FPR8, \thread - st_d 9, THREAD_FPR9, \thread - st_d 10, THREAD_FPR10, \thread - st_d 11, THREAD_FPR11, \thread - st_d 12, THREAD_FPR12, \thread - st_d 13, THREAD_FPR13, \thread - st_d 14, THREAD_FPR14, \thread - st_d 15, THREAD_FPR15, \thread - st_d 16, THREAD_FPR16, \thread - st_d 17, THREAD_FPR17, \thread - st_d 18, THREAD_FPR18, \thread - st_d 19, THREAD_FPR19, \thread - st_d 20, THREAD_FPR20, \thread - st_d 21, THREAD_FPR21, \thread - st_d 22, THREAD_FPR22, \thread - st_d 23, THREAD_FPR23, \thread - st_d 24, THREAD_FPR24, \thread - st_d 25, THREAD_FPR25, \thread - st_d 26, THREAD_FPR26, \thread - st_d 27, THREAD_FPR27, \thread - st_d 28, THREAD_FPR28, \thread - st_d 29, THREAD_FPR29, \thread - st_d 30, THREAD_FPR30, \thread - st_d 31, THREAD_FPR31, \thread .set push .set noat +#ifdef TOOLCHAIN_SUPPORTS_MSA + PTR_ADDU FPR_BASE, \thread, FPR_BASE_OFFS +#endif + st_d 0, THREAD_FPR0 - FPR_BASE_OFFS, FPR_BASE + st_d 1, THREAD_FPR1 - FPR_BASE_OFFS, FPR_BASE + st_d 2, THREAD_FPR2 - FPR_BASE_OFFS, FPR_BASE + st_d 3, THREAD_FPR3 - FPR_BASE_OFFS, FPR_BASE + st_d 4, THREAD_FPR4 - FPR_BASE_OFFS, FPR_BASE + st_d 5, THREAD_FPR5 - FPR_BASE_OFFS, FPR_BASE + st_d 6, THREAD_FPR6 - FPR_BASE_OFFS, FPR_BASE + st_d 7, THREAD_FPR7 - FPR_BASE_OFFS, FPR_BASE + st_d 8, THREAD_FPR8 - FPR_BASE_OFFS, FPR_BASE + st_d 9, THREAD_FPR9 - FPR_BASE_OFFS, FPR_BASE + st_d 10, THREAD_FPR10 - FPR_BASE_OFFS, FPR_BASE + st_d 11, THREAD_FPR11 - FPR_BASE_OFFS, FPR_BASE + st_d 12, THREAD_FPR12 - FPR_BASE_OFFS, FPR_BASE + st_d 13, THREAD_FPR13 - FPR_BASE_OFFS, FPR_BASE + st_d 14, THREAD_FPR14 - FPR_BASE_OFFS, FPR_BASE + st_d 15, THREAD_FPR15 - FPR_BASE_OFFS, FPR_BASE + st_d 16, THREAD_FPR16 - FPR_BASE_OFFS, FPR_BASE + st_d 17, THREAD_FPR17 - FPR_BASE_OFFS, FPR_BASE + st_d 18, THREAD_FPR18 - FPR_BASE_OFFS, FPR_BASE + st_d 19, THREAD_FPR19 - FPR_BASE_OFFS, FPR_BASE + st_d 20, THREAD_FPR20 - FPR_BASE_OFFS, FPR_BASE + st_d 21, THREAD_FPR21 - FPR_BASE_OFFS, FPR_BASE + st_d 22, THREAD_FPR22 - FPR_BASE_OFFS, FPR_BASE + st_d 23, THREAD_FPR23 - FPR_BASE_OFFS, FPR_BASE + st_d 24, THREAD_FPR24 - FPR_BASE_OFFS, FPR_BASE + st_d 25, THREAD_FPR25 - FPR_BASE_OFFS, FPR_BASE + st_d 26, THREAD_FPR26 - FPR_BASE_OFFS, FPR_BASE + st_d 27, THREAD_FPR27 - FPR_BASE_OFFS, FPR_BASE + st_d 28, THREAD_FPR28 - FPR_BASE_OFFS, FPR_BASE + st_d 29, THREAD_FPR29 - FPR_BASE_OFFS, FPR_BASE + st_d 30, THREAD_FPR30 - FPR_BASE_OFFS, FPR_BASE + st_d 31, THREAD_FPR31 - FPR_BASE_OFFS, FPR_BASE SET_HARDFLOAT _cfcmsa $1, MSA_CSR sw $1, THREAD_MSA_CSR(\thread) @@ -543,40 +554,46 @@ SET_HARDFLOAT lw $1, THREAD_MSA_CSR(\thread) _ctcmsa MSA_CSR, $1 - .set pop - ld_d 0, THREAD_FPR0, \thread - ld_d 1, THREAD_FPR1, \thread - ld_d 2, THREAD_FPR2, \thread - ld_d 3, THREAD_FPR3, \thread - ld_d 4, THREAD_FPR4, \thread - ld_d 5, THREAD_FPR5, \thread - ld_d 6, THREAD_FPR6, \thread - ld_d 7, THREAD_FPR7, \thread - ld_d 8, THREAD_FPR8, \thread - ld_d 9, THREAD_FPR9, \thread - ld_d 10, THREAD_FPR10, \thread - ld_d 11, THREAD_FPR11, \thread - ld_d 12, THREAD_FPR12, \thread - ld_d 13, THREAD_FPR13, \thread - ld_d 14, THREAD_FPR14, \thread - ld_d 15, THREAD_FPR15, \thread - ld_d 16, THREAD_FPR16, \thread - ld_d 17, THREAD_FPR17, \thread - ld_d 18, THREAD_FPR18, \thread - ld_d 19, THREAD_FPR19, \thread - ld_d 20, THREAD_FPR20, \thread - ld_d 21, THREAD_FPR21, \thread - ld_d 22, THREAD_FPR22, \thread - ld_d 23, THREAD_FPR23, \thread - ld_d 24, THREAD_FPR24, \thread - ld_d 25, THREAD_FPR25, \thread - ld_d 26, THREAD_FPR26, \thread - ld_d 27, THREAD_FPR27, \thread - ld_d 28, THREAD_FPR28, \thread - ld_d 29, THREAD_FPR29, \thread - ld_d 30, THREAD_FPR30, \thread - ld_d 31, THREAD_FPR31, \thread - .endm +#ifdef TOOLCHAIN_SUPPORTS_MSA + PTR_ADDU FPR_BASE, \thread, FPR_BASE_OFFS +#endif + ld_d 0, THREAD_FPR0 - FPR_BASE_OFFS, FPR_BASE + ld_d 1, THREAD_FPR1 - FPR_BASE_OFFS, FPR_BASE + ld_d 2, THREAD_FPR2 - FPR_BASE_OFFS, FPR_BASE + ld_d 3, THREAD_FPR3 - FPR_BASE_OFFS, FPR_BASE + ld_d 4, THREAD_FPR4 - FPR_BASE_OFFS, FPR_BASE + ld_d 5, THREAD_FPR5 - FPR_BASE_OFFS, FPR_BASE + ld_d 6, THREAD_FPR6 - FPR_BASE_OFFS, FPR_BASE + ld_d 7, THREAD_FPR7 - FPR_BASE_OFFS, FPR_BASE + ld_d 8, THREAD_FPR8 - FPR_BASE_OFFS, FPR_BASE + ld_d 9, THREAD_FPR9 - FPR_BASE_OFFS, FPR_BASE + ld_d 10, THREAD_FPR10 - FPR_BASE_OFFS, FPR_BASE + ld_d 11, THREAD_FPR11 - FPR_BASE_OFFS, FPR_BASE + ld_d 12, THREAD_FPR12 - FPR_BASE_OFFS, FPR_BASE + ld_d 13, THREAD_FPR13 - FPR_BASE_OFFS, FPR_BASE + ld_d 14, THREAD_FPR14 - FPR_BASE_OFFS, FPR_BASE + ld_d 15, THREAD_FPR15 - FPR_BASE_OFFS, FPR_BASE + ld_d 16, THREAD_FPR16 - FPR_BASE_OFFS, FPR_BASE + ld_d 17, THREAD_FPR17 - FPR_BASE_OFFS, FPR_BASE + ld_d 18, THREAD_FPR18 - FPR_BASE_OFFS, FPR_BASE + ld_d 19, THREAD_FPR19 - FPR_BASE_OFFS, FPR_BASE + ld_d 20, THREAD_FPR20 - FPR_BASE_OFFS, FPR_BASE + ld_d 21, THREAD_FPR21 - FPR_BASE_OFFS, FPR_BASE + ld_d 22, THREAD_FPR22 - FPR_BASE_OFFS, FPR_BASE + ld_d 23, THREAD_FPR23 - FPR_BASE_OFFS, FPR_BASE + ld_d 24, THREAD_FPR24 - FPR_BASE_OFFS, FPR_BASE + ld_d 25, THREAD_FPR25 - FPR_BASE_OFFS, FPR_BASE + ld_d 26, THREAD_FPR26 - FPR_BASE_OFFS, FPR_BASE + ld_d 27, THREAD_FPR27 - FPR_BASE_OFFS, FPR_BASE + ld_d 28, THREAD_FPR28 - FPR_BASE_OFFS, FPR_BASE + ld_d 29, THREAD_FPR29 - FPR_BASE_OFFS, FPR_BASE + ld_d 30, THREAD_FPR30 - FPR_BASE_OFFS, FPR_BASE + ld_d 31, THREAD_FPR31 - FPR_BASE_OFFS, FPR_BASE + .set pop + .endm + +#undef FPR_BASE_OFFS +#undef FPR_BASE .macro msa_init_upper wd #ifdef CONFIG_64BIT -- cgit v1.2.3 From 92e9953c5865b47281d74d43f08d7cecde11e58a Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 15 Apr 2016 10:07:26 +0100 Subject: MIPS: Fix MSA assembly warnings Building an MSA capable kernel with a toolchain that supports MSA produces warnings such as this: arch/mips/kernel/r4k_fpu.S:229: Warning: the `msa' extension requires 64-bit FPRs This is due to ".set msa" without ".set fp=64" in the non doubleword MSA load/store macros, since MSA requires the 64-bit FPU registers (FR=1). Add the missing fp=64 in these macros to silence the warnings. Signed-off-by: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13063/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/asmmacro.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index 637fccab5604..6741673c92ca 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -235,6 +235,7 @@ .macro ld_b wd, off, base .set push .set mips32r2 + .set fp=64 .set msa ld.b $w\wd, \off(\base) .set pop @@ -243,6 +244,7 @@ .macro ld_h wd, off, base .set push .set mips32r2 + .set fp=64 .set msa ld.h $w\wd, \off(\base) .set pop @@ -251,6 +253,7 @@ .macro ld_w wd, off, base .set push .set mips32r2 + .set fp=64 .set msa ld.w $w\wd, \off(\base) .set pop @@ -268,6 +271,7 @@ .macro st_b wd, off, base .set push .set mips32r2 + .set fp=64 .set msa st.b $w\wd, \off(\base) .set pop @@ -276,6 +280,7 @@ .macro st_h wd, off, base .set push .set mips32r2 + .set fp=64 .set msa st.h $w\wd, \off(\base) .set pop @@ -284,6 +289,7 @@ .macro st_w wd, off, base .set push .set mips32r2 + .set fp=64 .set msa st.w $w\wd, \off(\base) .set pop -- cgit v1.2.3 From 05490626d5f535baaaec60cdd37167f1a8031a9b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 15 Apr 2016 10:25:33 +0200 Subject: MIPS: Move definitions for 32/64-bit agonstic inline assembler to new file. Inspired by Markos Chandras' patch. I just didn't want do pull bitsops.h into pgtable.h. Signed-off-by: Ralf Baechle References: https://patchwork.linux-mips.org/patch/11052/ --- arch/mips/include/asm/bitops.h | 17 +---------------- arch/mips/include/asm/llsc.h | 28 ++++++++++++++++++++++++++++ arch/mips/include/asm/pgtable.h | 11 ++--------- 3 files changed, 31 insertions(+), 25 deletions(-) create mode 100644 arch/mips/include/asm/llsc.h (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index ce9666cf1499..fa57cef12a46 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h @@ -19,25 +19,10 @@ #include /* sigh ... */ #include #include +#include #include #include -#if _MIPS_SZLONG == 32 -#define SZLONG_LOG 5 -#define SZLONG_MASK 31UL -#define __LL "ll " -#define __SC "sc " -#define __INS "ins " -#define __EXT "ext " -#elif _MIPS_SZLONG == 64 -#define SZLONG_LOG 6 -#define SZLONG_MASK 63UL -#define __LL "lld " -#define __SC "scd " -#define __INS "dins " -#define __EXT "dext " -#endif - /* * These are the "slower" versions of the functions and are in bitops.c. * These functions call raw_local_irq_{save,restore}(). diff --git a/arch/mips/include/asm/llsc.h b/arch/mips/include/asm/llsc.h new file mode 100644 index 000000000000..c6d17d171147 --- /dev/null +++ b/arch/mips/include/asm/llsc.h @@ -0,0 +1,28 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Macros for 32/64-bit neutral inline assembler + */ + +#ifndef __ASM_LLSC_H +#define __ASM_LLSC_H + +#if _MIPS_SZLONG == 32 +#define SZLONG_LOG 5 +#define SZLONG_MASK 31UL +#define __LL "ll " +#define __SC "sc " +#define __INS "ins " +#define __EXT "ext " +#elif _MIPS_SZLONG == 64 +#define SZLONG_LOG 6 +#define SZLONG_MASK 63UL +#define __LL "lld " +#define __SC "scd " +#define __INS "dins " +#define __EXT "dext " +#endif + +#endif /* __ASM_LLSC_H */ diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 9a4fe0133ff1..25b1c1c08cbc 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -187,23 +187,16 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) * For SMP, multiple CPUs can race, so we need to do * this atomically. */ -#ifdef CONFIG_64BIT -#define LL_INSN "lld" -#define SC_INSN "scd" -#else /* CONFIG_32BIT */ -#define LL_INSN "ll" -#define SC_INSN "sc" -#endif unsigned long page_global = _PAGE_GLOBAL; unsigned long tmp; __asm__ __volatile__ ( " .set push\n" " .set noreorder\n" - "1: " LL_INSN " %[tmp], %[buddy]\n" + "1: " __LL " %[tmp], %[buddy]\n" " bnez %[tmp], 2f\n" " or %[tmp], %[tmp], %[global]\n" - " " SC_INSN " %[tmp], %[buddy]\n" + " " __SC " %[tmp], %[buddy]\n" " beqz %[tmp], 1b\n" " nop\n" "2:\n" -- cgit v1.2.3 From 128639395b2ceacc6a56a0141d0261012bfe04d3 Mon Sep 17 00:00:00 2001 From: Joshua Kinard Date: Mon, 7 Sep 2015 06:42:30 -0400 Subject: MIPS: Adjust set_pte() SMP fix to handle R10000_LLSC_WAR Update the recent changes to set_pte() that were added in 46011e6ea392 to handle R10000_LLSC_WAR, and format the assembly to match other areas of the MIPS tree using the same WAR. This also incorporates a patch recently sent in my Markos Chandras, "Remove local LL/SC preprocessor variants", so that patch doesn't need to be applied if this one is accepted. Signed-off-by: Joshua Kinard Fixes: 46011e6ea392 ("MIPS: Make set_pte() SMP safe.) Cc: David Daney Cc: Linux/MIPS Patchwork: https://patchwork.linux-mips.org/patch/11103/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable.h | 45 +++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 13 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 25b1c1c08cbc..75c29cff0f99 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -190,20 +190,39 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) unsigned long page_global = _PAGE_GLOBAL; unsigned long tmp; - __asm__ __volatile__ ( - " .set push\n" - " .set noreorder\n" - "1: " __LL " %[tmp], %[buddy]\n" - " bnez %[tmp], 2f\n" - " or %[tmp], %[tmp], %[global]\n" - " " __SC " %[tmp], %[buddy]\n" - " beqz %[tmp], 1b\n" - " nop\n" - "2:\n" - " .set pop" - : [buddy] "+m" (buddy->pte), - [tmp] "=&r" (tmp) + if (kernel_uses_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__ ( + " .set arch=r4000 \n" + " .set push \n" + " .set noreorder \n" + "1:" __LL "%[tmp], %[buddy] \n" + " bnez %[tmp], 2f \n" + " or %[tmp], %[tmp], %[global] \n" + __SC "%[tmp], %[buddy] \n" + " beqzl %[tmp], 1b \n" + " nop \n" + "2: \n" + " .set pop \n" + " .set mips0 \n" + : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp) : [global] "r" (page_global)); + } else if (kernel_uses_llsc) { + __asm__ __volatile__ ( + " .set "MIPS_ISA_ARCH_LEVEL" \n" + " .set push \n" + " .set noreorder \n" + "1:" __LL "%[tmp], %[buddy] \n" + " bnez %[tmp], 2f \n" + " or %[tmp], %[tmp], %[global] \n" + __SC "%[tmp], %[buddy] \n" + " beqz %[tmp], 1b \n" + " nop \n" + "2: \n" + " .set pop \n" + " .set mips0 \n" + : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp) + : [global] "r" (page_global)); + } #else /* !CONFIG_SMP */ if (pte_none(*buddy)) pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL; -- cgit v1.2.3 From 34ae8e3688fb8af2afaf52b78c6f20c74c6ae650 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 28 Jan 2016 14:26:00 +0100 Subject: MIPS: highmem: Turn flush_cache_kmaps into a no-op. It was calling flush_cache_all() which is a no-op since a long time anyway and which was overkill in the old days when it was actually doing something because only the D-cache needs to be flushed, never the I-cache, never the S-cache. Since however highmem on MIPS is still only supported on processors that don't suffer from cache aliases, we could turn flush_cache_kmaps() into a no-op - but for paranoia's sake we rather make it BUG_ON(cpu_has_dc_aliases()). Signed-off-by: Ralf Baechle --- arch/mips/include/asm/highmem.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h index 01880b34a209..64f2500d891b 100644 --- a/arch/mips/include/asm/highmem.h +++ b/arch/mips/include/asm/highmem.h @@ -19,8 +19,10 @@ #ifdef __KERNEL__ +#include #include #include +#include #include /* undef for production */ @@ -50,7 +52,7 @@ extern void *kmap_atomic(struct page *page); extern void __kunmap_atomic(void *kvaddr); extern void *kmap_atomic_pfn(unsigned long pfn); -#define flush_cache_kmaps() flush_cache_all() +#define flush_cache_kmaps() BUG_ON(cpu_has_dc_aliases) extern void kmap_init(void); -- cgit v1.2.3 From b8c8f665076604762fd15eb815f2fd75eb511b2e Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 1 Feb 2016 14:43:41 -0800 Subject: MIPS: Add CPU identifiers and probing for Cavium CN73xx and CNF75xx processors. Add new processor identifiers for Cavium CN73xx and CNF75xx processors, and probe for them in cpu-probe.c Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12311/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 2 ++ arch/mips/kernel/cpu-probe.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index a97ca97285ec..7bea0f3bf9ee 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -169,6 +169,8 @@ #define PRID_IMP_CAVIUM_CNF71XX 0x9400 #define PRID_IMP_CAVIUM_CN78XX 0x9500 #define PRID_IMP_CAVIUM_CN70XX 0x9600 +#define PRID_IMP_CAVIUM_CN73XX 0x9700 +#define PRID_IMP_CAVIUM_CNF75XX 0x9800 /* * These are the PRID's for when 23:16 == PRID_COMP_INGENIC_* diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index b725b713b9f8..9ad6157e23de 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1481,6 +1481,8 @@ platform: set_elf_platform(cpu, "octeon2"); break; case PRID_IMP_CAVIUM_CN70XX: + case PRID_IMP_CAVIUM_CN73XX: + case PRID_IMP_CAVIUM_CNF75XX: case PRID_IMP_CAVIUM_CN78XX: c->cputype = CPU_CAVIUM_OCTEON3; __cpu_name[cpu] = "Cavium Octeon III"; -- cgit v1.2.3 From 58546e3b735cc9f695bba1559be76a68b072761f Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 1 Feb 2016 17:46:53 -0800 Subject: MIPS: OCTEON: Remove dead code from cvmx-sysinfo. Get rid of the long unused code. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12318/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/executive/cvmx-sysinfo.c | 72 ++---------------------- arch/mips/include/asm/octeon/cvmx-sysinfo.h | 30 +--------- 2 files changed, 5 insertions(+), 97 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c b/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c index 3d17fac29359..cc1b1d2a6fa1 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c +++ b/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c @@ -32,86 +32,22 @@ #include #include -#include #include -/** +/* * This structure defines the private state maintained by sysinfo module. - * */ -static struct { - struct cvmx_sysinfo sysinfo; /* system information */ - cvmx_spinlock_t lock; /* mutex spinlock */ - -} state = { - .lock = CVMX_SPINLOCK_UNLOCKED_INITIALIZER -}; - +static struct cvmx_sysinfo sysinfo; /* system information */ /* - * Global variables that define the min/max of the memory region set - * up for 32 bit userspace access. - */ -uint64_t linux_mem32_min; -uint64_t linux_mem32_max; -uint64_t linux_mem32_wired; -uint64_t linux_mem32_offset; - -/** - * This function returns the application information as obtained + * Returns the application information as obtained * by the bootloader. This provides the core mask of the cores * running the same application image, as well as the physical * memory regions available to the core. - * - * Returns Pointer to the boot information structure - * */ struct cvmx_sysinfo *cvmx_sysinfo_get(void) { - return &(state.sysinfo); + return &sysinfo; } EXPORT_SYMBOL(cvmx_sysinfo_get); -/** - * This function is used in non-simple executive environments (such as - * Linux kernel, u-boot, etc.) to configure the minimal fields that - * are required to use simple executive files directly. - * - * Locking (if required) must be handled outside of this - * function - * - * @phy_mem_desc_ptr: - * Pointer to global physical memory descriptor - * (bootmem descriptor) @board_type: Octeon board - * type enumeration - * - * @board_rev_major: - * Board major revision - * @board_rev_minor: - * Board minor revision - * @cpu_clock_hz: - * CPU clock freqency in hertz - * - * Returns 0: Failure - * 1: success - */ -int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr, - uint16_t board_type, - uint8_t board_rev_major, - uint8_t board_rev_minor, - uint32_t cpu_clock_hz) -{ - - /* The sysinfo structure was already initialized */ - if (state.sysinfo.board_type) - return 0; - - memset(&(state.sysinfo), 0x0, sizeof(state.sysinfo)); - state.sysinfo.phy_mem_desc_ptr = phy_mem_desc_ptr; - state.sysinfo.board_type = board_type; - state.sysinfo.board_rev_major = board_rev_major; - state.sysinfo.board_rev_minor = board_rev_minor; - state.sysinfo.cpu_clock_hz = cpu_clock_hz; - - return 1; -} diff --git a/arch/mips/include/asm/octeon/cvmx-sysinfo.h b/arch/mips/include/asm/octeon/cvmx-sysinfo.h index 2131197422e5..78cd64ad79c7 100644 --- a/arch/mips/include/asm/octeon/cvmx-sysinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-sysinfo.h @@ -4,7 +4,7 @@ * Contact: support@caviumnetworks.com * This file is part of the OCTEON SDK * - * Copyright (c) 2003-2008 Cavium Networks + * Copyright (c) 2003-2016 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as @@ -121,32 +121,4 @@ struct cvmx_sysinfo { extern struct cvmx_sysinfo *cvmx_sysinfo_get(void); -/** - * This function is used in non-simple executive environments (such as - * Linux kernel, u-boot, etc.) to configure the minimal fields that - * are required to use simple executive files directly. - * - * Locking (if required) must be handled outside of this - * function - * - * @phy_mem_desc_ptr: Pointer to global physical memory descriptor - * (bootmem descriptor) @board_type: Octeon board - * type enumeration - * - * @board_rev_major: - * Board major revision - * @board_rev_minor: - * Board minor revision - * @cpu_clock_hz: - * CPU clock freqency in hertz - * - * Returns 0: Failure - * 1: success - */ -extern int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr, - uint16_t board_type, - uint8_t board_rev_major, - uint8_t board_rev_minor, - uint32_t cpu_clock_hz); - #endif /* __CVMX_SYSINFO_H__ */ -- cgit v1.2.3 From 7d52ab163c75bb830185f7ea12bae1db87f12b56 Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 1 Feb 2016 17:46:54 -0800 Subject: MIPS: OCTEON: Extend number of supported CPUs past 32 To support more than 48 CPUs, the bootinfo structure grows a new coremask structure. Add the definition of the structure and add it to struct cvmx_bootinfo. In prom_init(), copy the new coremask data into the sysinfo structure, and use it in smp_setup(). Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12319/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 19 +++++- arch/mips/cavium-octeon/smp.c | 4 +- arch/mips/include/asm/octeon/cvmx-bootinfo.h | 14 ++++- arch/mips/include/asm/octeon/cvmx-coremask.h | 89 ++++++++++++++++++++++++++++ arch/mips/include/asm/octeon/cvmx-sysinfo.h | 7 ++- 5 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 arch/mips/include/asm/octeon/cvmx-coremask.h (limited to 'arch/mips/include/asm') diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index cd7101fb6227..9c6ad2fab344 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -637,9 +637,22 @@ void __init prom_init(void) sysinfo = cvmx_sysinfo_get(); memset(sysinfo, 0, sizeof(*sysinfo)); sysinfo->system_dram_size = octeon_bootinfo->dram_size << 20; - sysinfo->phy_mem_desc_ptr = - cvmx_phys_to_ptr(octeon_bootinfo->phy_mem_desc_addr); - sysinfo->core_mask = octeon_bootinfo->core_mask; + sysinfo->phy_mem_desc_addr = (u64)phys_to_virt(octeon_bootinfo->phy_mem_desc_addr); + + if ((octeon_bootinfo->major_version > 1) || + (octeon_bootinfo->major_version == 1 && + octeon_bootinfo->minor_version >= 4)) + cvmx_coremask_copy(&sysinfo->core_mask, + &octeon_bootinfo->ext_core_mask); + else + cvmx_coremask_set64(&sysinfo->core_mask, + octeon_bootinfo->core_mask); + + /* Some broken u-boot pass garbage in upper bits, clear them out */ + if (!OCTEON_IS_MODEL(OCTEON_CN78XX)) + for (i = 512; i < 1024; i++) + cvmx_coremask_clear_core(&sysinfo->core_mask, i); + sysinfo->exception_base_addr = octeon_bootinfo->exception_base_addr; sysinfo->cpu_clock_hz = octeon_bootinfo->eclock_hz; sysinfo->dram_data_rate_hz = octeon_bootinfo->dclock_hz * 2; diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 61a60e424424..42395c561aa5 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -103,6 +103,8 @@ static void octeon_smp_setup(void) int cpus; int id; int core_mask = octeon_get_boot_coremask(); + struct cvmx_sysinfo *sysinfo = cvmx_sysinfo_get(); + #ifdef CONFIG_HOTPLUG_CPU unsigned int num_cores = cvmx_octeon_num_cores(); #endif @@ -119,7 +121,7 @@ static void octeon_smp_setup(void) /* The present CPUs get the lowest CPU numbers. */ cpus = 1; for (id = 0; id < NR_CPUS; id++) { - if ((id != coreid) && (core_mask & (1 << id))) { + if ((id != coreid) && cvmx_coremask_is_core_set(&sysinfo->core_mask, id)) { set_cpu_possible(cpus, true); set_cpu_present(cpus, true); __cpu_number_map[id] = cpus; diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h index d92cf59bdae6..c455d34f5a4f 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h @@ -32,6 +32,8 @@ #ifndef __CVMX_BOOTINFO_H__ #define __CVMX_BOOTINFO_H__ +#include "cvmx-coremask.h" + /* * Current major and minor versions of the CVMX bootinfo block that is * passed from the bootloader to the application. This is versioned @@ -39,7 +41,7 @@ * versions. */ #define CVMX_BOOTINFO_MAJ_VER 1 -#define CVMX_BOOTINFO_MIN_VER 3 +#define CVMX_BOOTINFO_MIN_VER 4 #if (CVMX_BOOTINFO_MAJ_VER == 1) #define CVMX_BOOTINFO_OCTEON_SERIAL_LEN 20 @@ -124,6 +126,13 @@ struct cvmx_bootinfo { */ uint64_t fdt_addr; #endif +#if (CVMX_BOOTINFO_MIN_VER >= 4) + /* + * Coremask used for processors with more than 32 cores + * or with OCI. This replaces core_mask. + */ + struct cvmx_coremask ext_core_mask; +#endif #else /* __BIG_ENDIAN */ /* * Little-Endian: When the CPU mode is switched to @@ -177,6 +186,9 @@ struct cvmx_bootinfo { #if (CVMX_BOOTINFO_MIN_VER >= 3) uint64_t fdt_addr; #endif +#if (CVMX_BOOTINFO_MIN_VER >= 4) + struct cvmx_coremask ext_core_mask; +#endif #endif }; diff --git a/arch/mips/include/asm/octeon/cvmx-coremask.h b/arch/mips/include/asm/octeon/cvmx-coremask.h new file mode 100644 index 000000000000..097dc096db84 --- /dev/null +++ b/arch/mips/include/asm/octeon/cvmx-coremask.h @@ -0,0 +1,89 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2016 Cavium Inc. (support@cavium.com). + * + */ + +/* + * Module to support operations on bitmap of cores. Coremask can be used to + * select a specific core, a group of cores, or all available cores, for + * initialization and differentiation of roles within a single shared binary + * executable image. + * + * The core numbers used in this file are the same value as what is found in + * the COP0_EBASE register and the rdhwr 0 instruction. + * + * For the CN78XX and other multi-node environments the core numbers are not + * contiguous. The core numbers for the CN78XX are as follows: + * + * Node 0: Cores 0 - 47 + * Node 1: Cores 128 - 175 + * Node 2: Cores 256 - 303 + * Node 3: Cores 384 - 431 + * + */ + +#ifndef __CVMX_COREMASK_H__ +#define __CVMX_COREMASK_H__ + +#define CVMX_MIPS_MAX_CORES 1024 +/* bits per holder */ +#define CVMX_COREMASK_ELTSZ 64 + +/* cvmx_coremask_t's size in u64 */ +#define CVMX_COREMASK_BMPSZ (CVMX_MIPS_MAX_CORES / CVMX_COREMASK_ELTSZ) + + +/* cvmx_coremask_t */ +struct cvmx_coremask { + u64 coremask_bitmap[CVMX_COREMASK_BMPSZ]; +}; + +/* + * Is ``core'' set in the coremask? + */ +static inline bool cvmx_coremask_is_core_set(const struct cvmx_coremask *pcm, + int core) +{ + int n, i; + + n = core % CVMX_COREMASK_ELTSZ; + i = core / CVMX_COREMASK_ELTSZ; + + return (pcm->coremask_bitmap[i] & ((u64)1 << n)) != 0; +} + +/* + * Make a copy of a coremask + */ +static inline void cvmx_coremask_copy(struct cvmx_coremask *dest, + const struct cvmx_coremask *src) +{ + memcpy(dest, src, sizeof(*dest)); +} + +/* + * Set the lower 64-bit of the coremask. + */ +static inline void cvmx_coremask_set64(struct cvmx_coremask *pcm, + uint64_t coremask_64) +{ + pcm->coremask_bitmap[0] = coremask_64; +} + +/* + * Clear ``core'' from the coremask. + */ +static inline void cvmx_coremask_clear_core(struct cvmx_coremask *pcm, int core) +{ + int n, i; + + n = core % CVMX_COREMASK_ELTSZ; + i = core / CVMX_COREMASK_ELTSZ; + pcm->coremask_bitmap[i] &= ~(1ull << n); +} + +#endif /* __CVMX_COREMASK_H__ */ diff --git a/arch/mips/include/asm/octeon/cvmx-sysinfo.h b/arch/mips/include/asm/octeon/cvmx-sysinfo.h index 78cd64ad79c7..c6c3ee39c69d 100644 --- a/arch/mips/include/asm/octeon/cvmx-sysinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-sysinfo.h @@ -32,6 +32,8 @@ #ifndef __CVMX_SYSINFO_H__ #define __CVMX_SYSINFO_H__ +#include "cvmx-coremask.h" + #define OCTEON_SERIAL_LEN 20 /** * Structure describing application specific information. @@ -50,8 +52,7 @@ struct cvmx_sysinfo { uint64_t system_dram_size; /* ptr to memory descriptor block */ - void *phy_mem_desc_ptr; - + uint64_t phy_mem_desc_addr; /* Application image specific variables */ /* stack top address (virtual) */ @@ -63,7 +64,7 @@ struct cvmx_sysinfo { /* heap size in bytes */ uint32_t heap_size; /* coremask defining cores running application */ - uint32_t core_mask; + struct cvmx_coremask core_mask; /* Deprecated, use cvmx_coremask_first_core() to select init core */ uint32_t init_core; -- cgit v1.2.3 From 1d2753a66acbb101a0ec495cd13b9031ac1b171f Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:07 -0800 Subject: MIPS: Select CONFIG_HANDLE_DOMAIN_IRQ and make it work. Per the subject, always select HANDLE_DOMAIN_IRQ, and implement set_irq_regs() so that it actually works. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12496/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/include/asm/irq_regs.h | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c049c0667559..2352917a47a1 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -62,6 +62,7 @@ config MIPS select HAVE_IRQ_TIME_ACCOUNTING select GENERIC_TIME_VSYSCALL select ARCH_CLOCKSOURCE_DATA + select HANDLE_DOMAIN_IRQ menu "Machine selection" diff --git a/arch/mips/include/asm/irq_regs.h b/arch/mips/include/asm/irq_regs.h index 33bd2a06de57..8c48d6dd1d78 100644 --- a/arch/mips/include/asm/irq_regs.h +++ b/arch/mips/include/asm/irq_regs.h @@ -18,4 +18,14 @@ static inline struct pt_regs *get_irq_regs(void) return current_thread_info()->regs; } +static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs) +{ + struct pt_regs *old_regs; + + old_regs = get_irq_regs(); + current_thread_info()->regs = new_regs; + + return old_regs; +} + #endif /* __ASM_IRQ_REGS_H */ -- cgit v1.2.3 From 2df11221bdc32f62ff1d8b6b945a8b19bf2a681c Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:08 -0800 Subject: MIPS: OCTEON: Add register definitions for cn73xx, cnf75xx and cn78xx. These new members of the OCTEON III family have some new registers, update some of the definitions for use in follow on patches. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12497/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/octeon/cvmx-ciu3-defs.h | 353 ++++++++++++++++++++++ arch/mips/include/asm/octeon/cvmx-fpa-defs.h | 1 + arch/mips/include/asm/octeon/cvmx-mio-defs.h | 410 +++++++++++++++++++++++++- 3 files changed, 748 insertions(+), 16 deletions(-) create mode 100644 arch/mips/include/asm/octeon/cvmx-ciu3-defs.h (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h b/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h new file mode 100644 index 000000000000..547f778f5b05 --- /dev/null +++ b/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2003-2016 Cavium Inc. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, but + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or + * NONINFRINGEMENT. See the GNU General Public License for more + * details. + * + */ + +#ifndef __CVMX_CIU3_DEFS_H__ +#define __CVMX_CIU3_DEFS_H__ + +#define CVMX_CIU3_FUSE CVMX_ADD_IO_SEG(0x00010100000001A0ull) +#define CVMX_CIU3_BIST CVMX_ADD_IO_SEG(0x00010100000001C0ull) +#define CVMX_CIU3_CONST CVMX_ADD_IO_SEG(0x0001010000000220ull) +#define CVMX_CIU3_CTL CVMX_ADD_IO_SEG(0x00010100000000E0ull) +#define CVMX_CIU3_DESTX_IO_INT(offset) (CVMX_ADD_IO_SEG(0x0001010000210000ull) + ((offset) & 7) * 8) +#define CVMX_CIU3_DESTX_PP_INT(offset) (CVMX_ADD_IO_SEG(0x0001010000200000ull) + ((offset) & 255) * 8) +#define CVMX_CIU3_GSTOP CVMX_ADD_IO_SEG(0x0001010000000140ull) +#define CVMX_CIU3_IDTX_CTL(offset) (CVMX_ADD_IO_SEG(0x0001010000110000ull) + ((offset) & 255) * 8) +#define CVMX_CIU3_IDTX_IO(offset) (CVMX_ADD_IO_SEG(0x0001010000130000ull) + ((offset) & 255) * 8) +#define CVMX_CIU3_IDTX_PPX(offset, block_id) (CVMX_ADD_IO_SEG(0x0001010000120000ull) + ((block_id) & 255) * 0x20ull) +#define CVMX_CIU3_INTR_RAM_ECC_CTL CVMX_ADD_IO_SEG(0x0001010000000260ull) +#define CVMX_CIU3_INTR_RAM_ECC_ST CVMX_ADD_IO_SEG(0x0001010000000280ull) +#define CVMX_CIU3_INTR_READY CVMX_ADD_IO_SEG(0x00010100000002A0ull) +#define CVMX_CIU3_INTR_SLOWDOWN CVMX_ADD_IO_SEG(0x0001010000000240ull) +#define CVMX_CIU3_ISCX_CTL(offset) (CVMX_ADD_IO_SEG(0x0001010080000000ull) + ((offset) & 1048575) * 8) +#define CVMX_CIU3_ISCX_W1C(offset) (CVMX_ADD_IO_SEG(0x0001010090000000ull) + ((offset) & 1048575) * 8) +#define CVMX_CIU3_ISCX_W1S(offset) (CVMX_ADD_IO_SEG(0x00010100A0000000ull) + ((offset) & 1048575) * 8) +#define CVMX_CIU3_NMI CVMX_ADD_IO_SEG(0x0001010000000160ull) +#define CVMX_CIU3_SISCX(offset) (CVMX_ADD_IO_SEG(0x0001010000220000ull) + ((offset) & 255) * 8) +#define CVMX_CIU3_TIMX(offset) (CVMX_ADD_IO_SEG(0x0001010000010000ull) + ((offset) & 15) * 8) + +union cvmx_ciu3_bist { + uint64_t u64; + struct cvmx_ciu3_bist_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_9_63 : 55; + uint64_t bist : 9; +#else + uint64_t bist : 9; + uint64_t reserved_9_63 : 55; +#endif + } s; +}; + +union cvmx_ciu3_const { + uint64_t u64; + struct cvmx_ciu3_const_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t dests_io : 16; + uint64_t pintsn : 16; + uint64_t dests_pp : 16; + uint64_t idt : 16; +#else + uint64_t idt : 16; + uint64_t dests_pp : 16; + uint64_t pintsn : 16; + uint64_t dests_io : 16; +#endif + } s; +}; + +union cvmx_ciu3_ctl { + uint64_t u64; + struct cvmx_ciu3_ctl_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_5_63 : 59; + uint64_t mcd_sel : 2; + uint64_t iscmem_le : 1; + uint64_t seq_dis : 1; + uint64_t cclk_dis : 1; +#else + uint64_t cclk_dis : 1; + uint64_t seq_dis : 1; + uint64_t iscmem_le : 1; + uint64_t mcd_sel : 2; + uint64_t reserved_5_63 : 59; +#endif + } s; +}; + +union cvmx_ciu3_destx_io_int { + uint64_t u64; + struct cvmx_ciu3_destx_io_int_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_52_63 : 12; + uint64_t intsn : 20; + uint64_t reserved_10_31 : 22; + uint64_t intidt : 8; + uint64_t newint : 1; + uint64_t intr : 1; +#else + uint64_t intr : 1; + uint64_t newint : 1; + uint64_t intidt : 8; + uint64_t reserved_10_31 : 22; + uint64_t intsn : 20; + uint64_t reserved_52_63 : 12; +#endif + } s; +}; + +union cvmx_ciu3_destx_pp_int { + uint64_t u64; + struct cvmx_ciu3_destx_pp_int_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_52_63 : 12; + uint64_t intsn : 20; + uint64_t reserved_10_31 : 22; + uint64_t intidt : 8; + uint64_t newint : 1; + uint64_t intr : 1; +#else + uint64_t intr : 1; + uint64_t newint : 1; + uint64_t intidt : 8; + uint64_t reserved_10_31 : 22; + uint64_t intsn : 20; + uint64_t reserved_52_63 : 12; +#endif + } s; +}; + +union cvmx_ciu3_gstop { + uint64_t u64; + struct cvmx_ciu3_gstop_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_1_63 : 63; + uint64_t gstop : 1; +#else + uint64_t gstop : 1; + uint64_t reserved_1_63 : 63; +#endif + } s; +}; + +union cvmx_ciu3_idtx_ctl { + uint64_t u64; + struct cvmx_ciu3_idtx_ctl_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_52_63 : 12; + uint64_t intsn : 20; + uint64_t reserved_4_31 : 28; + uint64_t intr : 1; + uint64_t newint : 1; + uint64_t ip_num : 2; +#else + uint64_t ip_num : 2; + uint64_t newint : 1; + uint64_t intr : 1; + uint64_t reserved_4_31 : 28; + uint64_t intsn : 20; + uint64_t reserved_52_63 : 12; +#endif + } s; +}; + +union cvmx_ciu3_idtx_io { + uint64_t u64; + struct cvmx_ciu3_idtx_io_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_5_63 : 59; + uint64_t io : 5; +#else + uint64_t io : 5; + uint64_t reserved_5_63 : 59; +#endif + } s; +}; + +union cvmx_ciu3_idtx_ppx { + uint64_t u64; + struct cvmx_ciu3_idtx_ppx_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_48_63 : 16; + uint64_t pp : 48; +#else + uint64_t pp : 48; + uint64_t reserved_48_63 : 16; +#endif + } s; +}; + +union cvmx_ciu3_intr_ram_ecc_ctl { + uint64_t u64; + struct cvmx_ciu3_intr_ram_ecc_ctl_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_3_63 : 61; + uint64_t flip_synd : 2; + uint64_t ecc_ena : 1; +#else + uint64_t ecc_ena : 1; + uint64_t flip_synd : 2; + uint64_t reserved_3_63 : 61; +#endif + } s; +}; + +union cvmx_ciu3_intr_ram_ecc_st { + uint64_t u64; + struct cvmx_ciu3_intr_ram_ecc_st_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_52_63 : 12; + uint64_t addr : 20; + uint64_t reserved_6_31 : 26; + uint64_t sisc_dbe : 1; + uint64_t sisc_sbe : 1; + uint64_t idt_dbe : 1; + uint64_t idt_sbe : 1; + uint64_t isc_dbe : 1; + uint64_t isc_sbe : 1; +#else + uint64_t isc_sbe : 1; + uint64_t isc_dbe : 1; + uint64_t idt_sbe : 1; + uint64_t idt_dbe : 1; + uint64_t sisc_sbe : 1; + uint64_t sisc_dbe : 1; + uint64_t reserved_6_31 : 26; + uint64_t addr : 20; + uint64_t reserved_52_63 : 12; +#endif + } s; +}; + +union cvmx_ciu3_intr_ready { + uint64_t u64; + struct cvmx_ciu3_intr_ready_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_46_63 : 18; + uint64_t index : 14; + uint64_t reserved_1_31 : 31; + uint64_t ready : 1; +#else + uint64_t ready : 1; + uint64_t reserved_1_31 : 31; + uint64_t index : 14; + uint64_t reserved_46_63 : 18; +#endif + } s; +}; + +union cvmx_ciu3_intr_slowdown { + uint64_t u64; + struct cvmx_ciu3_intr_slowdown_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_3_63 : 61; + uint64_t ctl : 3; +#else + uint64_t ctl : 3; + uint64_t reserved_3_63 : 61; +#endif + } s; +}; + +union cvmx_ciu3_iscx_ctl { + uint64_t u64; + struct cvmx_ciu3_iscx_ctl_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_24_63 : 40; + uint64_t idt : 8; + uint64_t imp : 1; + uint64_t reserved_2_14 : 13; + uint64_t en : 1; + uint64_t raw : 1; +#else + uint64_t raw : 1; + uint64_t en : 1; + uint64_t reserved_2_14 : 13; + uint64_t imp : 1; + uint64_t idt : 8; + uint64_t reserved_24_63 : 40; +#endif + } s; +}; + +union cvmx_ciu3_iscx_w1c { + uint64_t u64; + struct cvmx_ciu3_iscx_w1c_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_2_63 : 62; + uint64_t en : 1; + uint64_t raw : 1; +#else + uint64_t raw : 1; + uint64_t en : 1; + uint64_t reserved_2_63 : 62; +#endif + } s; +}; + +union cvmx_ciu3_iscx_w1s { + uint64_t u64; + struct cvmx_ciu3_iscx_w1s_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_2_63 : 62; + uint64_t en : 1; + uint64_t raw : 1; +#else + uint64_t raw : 1; + uint64_t en : 1; + uint64_t reserved_2_63 : 62; +#endif + } s; +}; + +union cvmx_ciu3_nmi { + uint64_t u64; + struct cvmx_ciu3_nmi_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_48_63 : 16; + uint64_t nmi : 48; +#else + uint64_t nmi : 48; + uint64_t reserved_48_63 : 16; +#endif + } s; +}; + +union cvmx_ciu3_siscx { + uint64_t u64; + struct cvmx_ciu3_siscx_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t en : 64; +#else + uint64_t en : 64; +#endif + } s; +}; + +union cvmx_ciu3_timx { + uint64_t u64; + struct cvmx_ciu3_timx_s { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_37_63 : 27; + uint64_t one_shot : 1; + uint64_t len : 36; +#else + uint64_t len : 36; + uint64_t one_shot : 1; + uint64_t reserved_37_63 : 27; +#endif + } s; +}; + +#endif diff --git a/arch/mips/include/asm/octeon/cvmx-fpa-defs.h b/arch/mips/include/asm/octeon/cvmx-fpa-defs.h index 1d79e3c7040d..887ff8e1f715 100644 --- a/arch/mips/include/asm/octeon/cvmx-fpa-defs.h +++ b/arch/mips/include/asm/octeon/cvmx-fpa-defs.h @@ -66,6 +66,7 @@ #define CVMX_FPA_WART_CTL (CVMX_ADD_IO_SEG(0x00011800280000D8ull)) #define CVMX_FPA_WART_STATUS (CVMX_ADD_IO_SEG(0x00011800280000E0ull)) #define CVMX_FPA_WQE_THRESHOLD (CVMX_ADD_IO_SEG(0x0001180028000468ull)) +#define CVMX_FPA_CLK_COUNT (CVMX_ADD_IO_SEG(0x00012800000000F0ull)) union cvmx_fpa_addr_range_error { uint64_t u64; diff --git a/arch/mips/include/asm/octeon/cvmx-mio-defs.h b/arch/mips/include/asm/octeon/cvmx-mio-defs.h index bb0ae338a460..5196c04eee41 100644 --- a/arch/mips/include/asm/octeon/cvmx-mio-defs.h +++ b/arch/mips/include/asm/octeon/cvmx-mio-defs.h @@ -1481,7 +1481,9 @@ union cvmx_mio_fus_dat2 { uint64_t u64; struct cvmx_mio_fus_dat2_s { #ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_48_63:16; + uint64_t reserved_59_63:5; + uint64_t run_platform:3; + uint64_t gbl_pwr_throttle:8; uint64_t fus118:1; uint64_t rom_info:10; uint64_t power_limit:2; @@ -1513,7 +1515,9 @@ union cvmx_mio_fus_dat2 { uint64_t power_limit:2; uint64_t rom_info:10; uint64_t fus118:1; - uint64_t reserved_48_63:16; + uint64_t gbl_pwr_throttle:8; + uint64_t run_platform:3; + uint64_t reserved_59_63:5; #endif } s; struct cvmx_mio_fus_dat2_cn30xx { @@ -1837,50 +1841,192 @@ union cvmx_mio_fus_dat2 { #endif } cn68xx; struct cvmx_mio_fus_dat2_cn68xx cn68xxp1; + struct cvmx_mio_fus_dat2_cn70xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_48_63:16; + uint64_t fus118:1; + uint64_t rom_info:10; + uint64_t power_limit:2; + uint64_t dorm_crypto:1; + uint64_t fus318:1; + uint64_t raid_en:1; + uint64_t reserved_31_29:3; + uint64_t nodfa_cp2:1; + uint64_t nomul:1; + uint64_t nocrypto:1; + uint64_t reserved_25_24:2; + uint64_t chip_id:8; + uint64_t reserved_15_0:16; +#else + uint64_t reserved_15_0:16; + uint64_t chip_id:8; + uint64_t reserved_25_24:2; + uint64_t nocrypto:1; + uint64_t nomul:1; + uint64_t nodfa_cp2:1; + uint64_t reserved_31_29:3; + uint64_t raid_en:1; + uint64_t fus318:1; + uint64_t dorm_crypto:1; + uint64_t power_limit:2; + uint64_t rom_info:10; + uint64_t fus118:1; + uint64_t reserved_48_63:16; +#endif + } cn70xx; + struct cvmx_mio_fus_dat2_cn70xx cn70xxp1; + struct cvmx_mio_fus_dat2_cn73xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_59_63:5; + uint64_t run_platform:3; + uint64_t gbl_pwr_throttle:8; + uint64_t fus118:1; + uint64_t rom_info:10; + uint64_t power_limit:2; + uint64_t dorm_crypto:1; + uint64_t fus318:1; + uint64_t raid_en:1; + uint64_t reserved_31_29:3; + uint64_t nodfa_cp2:1; + uint64_t nomul:1; + uint64_t nocrypto:1; + uint64_t reserved_25_24:2; + uint64_t chip_id:8; + uint64_t reserved_15_0:16; +#else + uint64_t reserved_15_0:16; + uint64_t chip_id:8; + uint64_t reserved_25_24:2; + uint64_t nocrypto:1; + uint64_t nomul:1; + uint64_t nodfa_cp2:1; + uint64_t reserved_31_29:3; + uint64_t raid_en:1; + uint64_t fus318:1; + uint64_t dorm_crypto:1; + uint64_t power_limit:2; + uint64_t rom_info:10; + uint64_t fus118:1; + uint64_t gbl_pwr_throttle:8; + uint64_t run_platform:3; + uint64_t reserved_59_63:5; +#endif + } cn73xx; + struct cvmx_mio_fus_dat2_cn78xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_59_63:5; + uint64_t run_platform:3; + uint64_t reserved_48_55:8; + uint64_t fus118:1; + uint64_t rom_info:10; + uint64_t power_limit:2; + uint64_t dorm_crypto:1; + uint64_t fus318:1; + uint64_t raid_en:1; + uint64_t reserved_31_29:3; + uint64_t nodfa_cp2:1; + uint64_t nomul:1; + uint64_t nocrypto:1; + uint64_t reserved_25_24:2; + uint64_t chip_id:8; + uint64_t reserved_0_15:16; +#else + uint64_t reserved_0_15:16; + uint64_t chip_id:8; + uint64_t reserved_25_24:2; + uint64_t nocrypto:1; + uint64_t nomul:1; + uint64_t nodfa_cp2:1; + uint64_t reserved_31_29:3; + uint64_t raid_en:1; + uint64_t fus318:1; + uint64_t dorm_crypto:1; + uint64_t power_limit:2; + uint64_t rom_info:10; + uint64_t fus118:1; + uint64_t reserved_48_55:8; + uint64_t run_platform:3; + uint64_t reserved_59_63:5; +#endif + } cn78xx; + struct cvmx_mio_fus_dat2_cn78xxp2 { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t reserved_59_63:5; + uint64_t run_platform:3; + uint64_t gbl_pwr_throttle:8; + uint64_t fus118:1; + uint64_t rom_info:10; + uint64_t power_limit:2; + uint64_t dorm_crypto:1; + uint64_t fus318:1; + uint64_t raid_en:1; + uint64_t reserved_31_29:3; + uint64_t nodfa_cp2:1; + uint64_t nomul:1; + uint64_t nocrypto:1; + uint64_t reserved_25_24:2; + uint64_t chip_id:8; + uint64_t reserved_0_15:16; +#else + uint64_t reserved_0_15:16; + uint64_t chip_id:8; + uint64_t reserved_25_24:2; + uint64_t nocrypto:1; + uint64_t nomul:1; + uint64_t nodfa_cp2:1; + uint64_t reserved_31_29:3; + uint64_t raid_en:1; + uint64_t fus318:1; + uint64_t dorm_crypto:1; + uint64_t power_limit:2; + uint64_t rom_info:10; + uint64_t fus118:1; + uint64_t gbl_pwr_throttle:8; + uint64_t run_platform:3; + uint64_t reserved_59_63:5; +#endif + } cn78xxp2; struct cvmx_mio_fus_dat2_cn61xx cnf71xx; + struct cvmx_mio_fus_dat2_cn73xx cnf75xx; }; union cvmx_mio_fus_dat3 { uint64_t u64; struct cvmx_mio_fus_dat3_s { #ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_58_63:6; + uint64_t ema0:6; uint64_t pll_ctl:10; uint64_t dfa_info_dte:3; uint64_t dfa_info_clm:4; - uint64_t reserved_40_40:1; - uint64_t ema:2; + uint64_t pll_alt_matrix:1; + uint64_t reserved_38_39:2; uint64_t efus_lck_rsv:1; uint64_t efus_lck_man:1; uint64_t pll_half_dis:1; uint64_t l2c_crip:3; - uint64_t pll_div4:1; - uint64_t reserved_29_30:2; - uint64_t bar2_en:1; + uint64_t reserved_28_31:4; uint64_t efus_lck:1; uint64_t efus_ign:1; uint64_t nozip:1; uint64_t nodfa_dte:1; - uint64_t icache:24; + uint64_t reserved_0_23:24; #else - uint64_t icache:24; + uint64_t reserved_0_23:24; uint64_t nodfa_dte:1; uint64_t nozip:1; uint64_t efus_ign:1; uint64_t efus_lck:1; - uint64_t bar2_en:1; - uint64_t reserved_29_30:2; - uint64_t pll_div4:1; + uint64_t reserved_28_31:4; uint64_t l2c_crip:3; uint64_t pll_half_dis:1; uint64_t efus_lck_man:1; uint64_t efus_lck_rsv:1; - uint64_t ema:2; - uint64_t reserved_40_40:1; + uint64_t reserved_38_39:2; + uint64_t pll_alt_matrix:1; uint64_t dfa_info_clm:4; uint64_t dfa_info_dte:3; uint64_t pll_ctl:10; - uint64_t reserved_58_63:6; + uint64_t ema0:6; #endif } s; struct cvmx_mio_fus_dat3_cn30xx { @@ -2022,7 +2168,239 @@ union cvmx_mio_fus_dat3 { struct cvmx_mio_fus_dat3_cn61xx cn66xx; struct cvmx_mio_fus_dat3_cn61xx cn68xx; struct cvmx_mio_fus_dat3_cn61xx cn68xxp1; + struct cvmx_mio_fus_dat3_cn70xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t ema0:6; + uint64_t pll_ctl:10; + uint64_t dfa_info_dte:3; + uint64_t dfa_info_clm:4; + uint64_t pll_alt_matrix:1; + uint64_t pll_bwadj_denom:2; + uint64_t efus_lck_rsv:1; + uint64_t efus_lck_man:1; + uint64_t pll_half_dis:1; + uint64_t l2c_crip:3; + uint64_t use_int_refclk:1; + uint64_t zip_info:2; + uint64_t bar2_sz_conf:1; + uint64_t efus_lck:1; + uint64_t efus_ign:1; + uint64_t nozip:1; + uint64_t nodfa_dte:1; + uint64_t ema1:6; + uint64_t reserved_0_17:18; +#else + uint64_t reserved_0_17:18; + uint64_t ema1:6; + uint64_t nodfa_dte:1; + uint64_t nozip:1; + uint64_t efus_ign:1; + uint64_t efus_lck:1; + uint64_t bar2_sz_conf:1; + uint64_t zip_info:2; + uint64_t use_int_refclk:1; + uint64_t l2c_crip:3; + uint64_t pll_half_dis:1; + uint64_t efus_lck_man:1; + uint64_t efus_lck_rsv:1; + uint64_t pll_bwadj_denom:2; + uint64_t pll_alt_matrix:1; + uint64_t dfa_info_clm:4; + uint64_t dfa_info_dte:3; + uint64_t pll_ctl:10; + uint64_t ema0:6; +#endif + } cn70xx; + struct cvmx_mio_fus_dat3_cn70xxp1 { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t ema0:6; + uint64_t pll_ctl:10; + uint64_t dfa_info_dte:3; + uint64_t dfa_info_clm:4; + uint64_t reserved_38_40:3; + uint64_t efus_lck_rsv:1; + uint64_t efus_lck_man:1; + uint64_t pll_half_dis:1; + uint64_t l2c_crip:3; + uint64_t reserved_31_31:1; + uint64_t zip_info:2; + uint64_t bar2_sz_conf:1; + uint64_t efus_lck:1; + uint64_t efus_ign:1; + uint64_t nozip:1; + uint64_t nodfa_dte:1; + uint64_t ema1:6; + uint64_t reserved_0_17:18; +#else + uint64_t reserved_0_17:18; + uint64_t ema1:6; + uint64_t nodfa_dte:1; + uint64_t nozip:1; + uint64_t efus_ign:1; + uint64_t efus_lck:1; + uint64_t bar2_sz_conf:1; + uint64_t zip_info:2; + uint64_t reserved_31_31:1; + uint64_t l2c_crip:3; + uint64_t pll_half_dis:1; + uint64_t efus_lck_man:1; + uint64_t efus_lck_rsv:1; + uint64_t reserved_38_40:3; + uint64_t dfa_info_clm:4; + uint64_t dfa_info_dte:3; + uint64_t pll_ctl:10; + uint64_t ema0:6; +#endif + } cn70xxp1; + struct cvmx_mio_fus_dat3_cn73xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t ema0:6; + uint64_t pll_ctl:10; + uint64_t dfa_info_dte:3; + uint64_t dfa_info_clm:4; + uint64_t pll_alt_matrix:1; + uint64_t pll_bwadj_denom:2; + uint64_t efus_lck_rsv:1; + uint64_t efus_lck_man:1; + uint64_t pll_half_dis:1; + uint64_t l2c_crip:3; + uint64_t use_int_refclk:1; + uint64_t zip_info:2; + uint64_t bar2_sz_conf:1; + uint64_t efus_lck:1; + uint64_t efus_ign:1; + uint64_t nozip:1; + uint64_t nodfa_dte:1; + uint64_t ema1:6; + uint64_t nohna_dte:1; + uint64_t hna_info_dte:3; + uint64_t hna_info_clm:4; + uint64_t reserved_9_9:1; + uint64_t core_pll_mul:5; + uint64_t pnr_pll_mul:4; +#else + uint64_t pnr_pll_mul:4; + uint64_t core_pll_mul:5; + uint64_t reserved_9_9:1; + uint64_t hna_info_clm:4; + uint64_t hna_info_dte:3; + uint64_t nohna_dte:1; + uint64_t ema1:6; + uint64_t nodfa_dte:1; + uint64_t nozip:1; + uint64_t efus_ign:1; + uint64_t efus_lck:1; + uint64_t bar2_sz_conf:1; + uint64_t zip_info:2; + uint64_t use_int_refclk:1; + uint64_t l2c_crip:3; + uint64_t pll_half_dis:1; + uint64_t efus_lck_man:1; + uint64_t efus_lck_rsv:1; + uint64_t pll_bwadj_denom:2; + uint64_t pll_alt_matrix:1; + uint64_t dfa_info_clm:4; + uint64_t dfa_info_dte:3; + uint64_t pll_ctl:10; + uint64_t ema0:6; +#endif + } cn73xx; + struct cvmx_mio_fus_dat3_cn78xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t ema0:6; + uint64_t pll_ctl:10; + uint64_t dfa_info_dte:3; + uint64_t dfa_info_clm:4; + uint64_t reserved_38_40:3; + uint64_t efus_lck_rsv:1; + uint64_t efus_lck_man:1; + uint64_t pll_half_dis:1; + uint64_t l2c_crip:3; + uint64_t reserved_31_31:1; + uint64_t zip_info:2; + uint64_t bar2_sz_conf:1; + uint64_t efus_lck:1; + uint64_t efus_ign:1; + uint64_t nozip:1; + uint64_t nodfa_dte:1; + uint64_t ema1:6; + uint64_t nohna_dte:1; + uint64_t hna_info_dte:3; + uint64_t hna_info_clm:4; + uint64_t reserved_0_9:10; +#else + uint64_t reserved_0_9:10; + uint64_t hna_info_clm:4; + uint64_t hna_info_dte:3; + uint64_t nohna_dte:1; + uint64_t ema1:6; + uint64_t nodfa_dte:1; + uint64_t nozip:1; + uint64_t efus_ign:1; + uint64_t efus_lck:1; + uint64_t bar2_sz_conf:1; + uint64_t zip_info:2; + uint64_t reserved_31_31:1; + uint64_t l2c_crip:3; + uint64_t pll_half_dis:1; + uint64_t efus_lck_man:1; + uint64_t efus_lck_rsv:1; + uint64_t reserved_38_40:3; + uint64_t dfa_info_clm:4; + uint64_t dfa_info_dte:3; + uint64_t pll_ctl:10; + uint64_t ema0:6; +#endif + } cn78xx; + struct cvmx_mio_fus_dat3_cn73xx cn78xxp2; struct cvmx_mio_fus_dat3_cn61xx cnf71xx; + struct cvmx_mio_fus_dat3_cnf75xx { +#ifdef __BIG_ENDIAN_BITFIELD + uint64_t ema0:6; + uint64_t pll_ctl:10; + uint64_t dfa_info_dte:3; + uint64_t dfa_info_clm:4; + uint64_t pll_alt_matrix:1; + uint64_t pll_bwadj_denom:2; + uint64_t efus_lck_rsv:1; + uint64_t efus_lck_man:1; + uint64_t pll_half_dis:1; + uint64_t l2c_crip:3; + uint64_t use_int_refclk:1; + uint64_t zip_info:2; + uint64_t bar2_sz_conf:1; + uint64_t efus_lck:1; + uint64_t efus_ign:1; + uint64_t nozip:1; + uint64_t nodfa_dte:1; + uint64_t ema1:6; + uint64_t reserved_9_17:9; + uint64_t core_pll_mul:5; + uint64_t pnr_pll_mul:4; +#else + uint64_t pnr_pll_mul:4; + uint64_t core_pll_mul:5; + uint64_t reserved_9_17:9; + uint64_t ema1:6; + uint64_t nodfa_dte:1; + uint64_t nozip:1; + uint64_t efus_ign:1; + uint64_t efus_lck:1; + uint64_t bar2_sz_conf:1; + uint64_t zip_info:2; + uint64_t use_int_refclk:1; + uint64_t l2c_crip:3; + uint64_t pll_half_dis:1; + uint64_t efus_lck_man:1; + uint64_t efus_lck_rsv:1; + uint64_t pll_bwadj_denom:2; + uint64_t pll_alt_matrix:1; + uint64_t dfa_info_clm:4; + uint64_t dfa_info_dte:3; + uint64_t pll_ctl:10; + uint64_t ema0:6; +#endif + } cnf75xx; }; union cvmx_mio_fus_ema { -- cgit v1.2.3 From 182a6d1cd393226350ec22d973d2139adb194daa Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:09 -0800 Subject: MIPS: OCTEON: Add model checking support for cn73xx, cnf75xx and cn78xx Follow on patchs need to be able to distinguish the new models. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12498/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/executive/octeon-model.c | 82 +++++++++++++++++++++++- arch/mips/include/asm/octeon/cvmx.h | 27 +++++++- arch/mips/include/asm/octeon/octeon-feature.h | 19 +++++- arch/mips/include/asm/octeon/octeon-model.h | 5 ++ 4 files changed, 125 insertions(+), 8 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/cavium-octeon/executive/octeon-model.c b/arch/mips/cavium-octeon/executive/octeon-model.c index b2104bd9ab3b..d08a2bce653c 100644 --- a/arch/mips/cavium-octeon/executive/octeon-model.c +++ b/arch/mips/cavium-octeon/executive/octeon-model.c @@ -71,11 +71,11 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, uint32_t fuse_data = 0; fus3.u64 = 0; - if (!OCTEON_IS_MODEL(OCTEON_CN6XXX)) + if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3); fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2); fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3); - num_cores = cvmx_pop(cvmx_read_csr(CVMX_CIU_FUSE)); + num_cores = cvmx_octeon_num_cores(); /* Make sure the non existent devices look disabled */ switch ((chip_id >> 8) & 0xff) { @@ -121,6 +121,15 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, * later. */ switch (num_cores) { + case 48: + core_model = "90"; + break; + case 44: + core_model = "88"; + break; + case 40: + core_model = "85"; + break; case 32: core_model = "80"; break; @@ -297,7 +306,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, if (fus_dat3.s.nozip) suffix = "SCP"; - if (fus_dat3.s.bar2_en) + if (fus_dat3.cn56xx.bar2_en) suffix = "NSPB2"; } if (fus3.cn56xx.crip_1024k) @@ -369,6 +378,73 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, else suffix = "AAP"; break; + case 0x94: /* CNF71XX */ + family = "F71"; + if (fus_dat3.cnf71xx.nozip) + suffix = "SCP"; + else + suffix = "AAP"; + break; + case 0x95: /* CN78XX */ + if (num_cores == 6) /* Other core counts match generic */ + core_model = "35"; + if (OCTEON_IS_MODEL(OCTEON_CN76XX)) + family = "76"; + else + family = "78"; + if (fus_dat3.cn78xx.l2c_crip == 2) + family = "77"; + if (fus_dat3.cn78xx.nozip + && fus_dat3.cn78xx.nodfa_dte + && fus_dat3.cn78xx.nohna_dte) { + if (fus_dat3.cn78xx.nozip && + !fus_dat2.cn78xx.raid_en && + fus_dat3.cn78xx.nohna_dte) { + suffix = "CP"; + } else { + suffix = "SCP"; + } + } else if (fus_dat2.cn78xx.raid_en == 0) + suffix = "HCP"; + else + suffix = "AAP"; + break; + case 0x96: /* CN70XX */ + family = "70"; + if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32)) + family = "71"; + if (fus_dat2.cn70xx.nocrypto) + suffix = "CP"; + else if (fus_dat3.cn70xx.nodfa_dte) + suffix = "SCP"; + else + suffix = "AAP"; + break; + case 0x97: /* CN73XX */ + if (num_cores == 6) /* Other core counts match generic */ + core_model = "35"; + family = "73"; + if (fus_dat3.cn73xx.l2c_crip == 2) + family = "72"; + if (fus_dat3.cn73xx.nozip + && fus_dat3.cn73xx.nodfa_dte + && fus_dat3.cn73xx.nohna_dte) { + if (!fus_dat2.cn73xx.raid_en) + suffix = "CP"; + else + suffix = "SCP"; + } else + suffix = "AAP"; + break; + case 0x98: /* CN75XX */ + family = "F75"; + if (fus_dat3.cn78xx.nozip + && fus_dat3.cn78xx.nodfa_dte + && fus_dat3.cn78xx.nohna_dte) + suffix = "SCP"; + else + suffix = "AAP"; + break; default: family = "XX"; core_model = "XX"; diff --git a/arch/mips/include/asm/octeon/cvmx.h b/arch/mips/include/asm/octeon/cvmx.h index 3e982e0c397e..2530e8731c8a 100644 --- a/arch/mips/include/asm/octeon/cvmx.h +++ b/arch/mips/include/asm/octeon/cvmx.h @@ -57,6 +57,7 @@ enum cvmx_mips_space { #include #include +#include #include #include #include @@ -341,6 +342,21 @@ static inline unsigned int cvmx_get_core_num(void) return core_num; } +/* Maximum # of bits to define core in node */ +#define CVMX_NODE_NO_SHIFT 7 +#define CVMX_NODE_MASK 0x3 +static inline unsigned int cvmx_get_node_num(void) +{ + unsigned int core_num = cvmx_get_core_num(); + + return (core_num >> CVMX_NODE_NO_SHIFT) & CVMX_NODE_MASK; +} + +static inline unsigned int cvmx_get_local_core_num(void) +{ + return cvmx_get_core_num() & ((1 << CVMX_NODE_NO_SHIFT) - 1); +} + /** * Returns the number of bits set in the provided value. * Simple wrapper for POP instruction. @@ -448,8 +464,15 @@ static inline uint64_t cvmx_get_cycle_global(void) /* Return the number of cores available in the chip */ static inline uint32_t cvmx_octeon_num_cores(void) { - uint32_t ciu_fuse = (uint32_t) cvmx_read_csr(CVMX_CIU_FUSE) & 0xffff; - return cvmx_pop(ciu_fuse); + u64 ciu_fuse_reg; + u64 ciu_fuse; + + if (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX)) + ciu_fuse_reg = CVMX_CIU3_FUSE; + else + ciu_fuse_reg = CVMX_CIU_FUSE; + ciu_fuse = cvmx_read_csr(ciu_fuse_reg); + return cvmx_dpop(ciu_fuse); } #endif /* __CVMX_H__ */ diff --git a/arch/mips/include/asm/octeon/octeon-feature.h b/arch/mips/include/asm/octeon/octeon-feature.h index 3ed10a8d7865..a19ca3b2775c 100644 --- a/arch/mips/include/asm/octeon/octeon-feature.h +++ b/arch/mips/include/asm/octeon/octeon-feature.h @@ -81,6 +81,10 @@ enum octeon_feature { OCTEON_FEATURE_HFA, OCTEON_FEATURE_DFM, OCTEON_FEATURE_CIU2, + OCTEON_FEATURE_CIU3, + /* Octeon has FPA first seen on 78XX */ + OCTEON_FEATURE_FPA3, + OCTEON_FEATURE_FAU, OCTEON_MAX_FEATURE }; @@ -110,7 +114,7 @@ static inline int octeon_has_crypto(void) * Returns Non zero if the feature exists. Zero if the feature does not * exist. */ -static inline int octeon_has_feature(enum octeon_feature feature) +static inline bool octeon_has_feature(enum octeon_feature feature) { switch (feature) { case OCTEON_FEATURE_SAAD: @@ -122,7 +126,7 @@ static inline int octeon_has_feature(enum octeon_feature feature) fus_2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2); return !fus_2.s.nocrypto && !fus_2.s.nomul && fus_2.s.dorm_crypto; } else { - return 0; + return false; } case OCTEON_FEATURE_PCIE: @@ -190,11 +194,20 @@ static inline int octeon_has_feature(enum octeon_feature feature) case OCTEON_FEATURE_CIU2: return OCTEON_IS_MODEL(OCTEON_CN68XX); + case OCTEON_FEATURE_CIU3: + case OCTEON_FEATURE_FPA3: + return OCTEON_IS_MODEL(OCTEON_CN78XX) + || OCTEON_IS_MODEL(OCTEON_CNF75XX) + || OCTEON_IS_MODEL(OCTEON_CN73XX); + case OCTEON_FEATURE_FAU: + return !(OCTEON_IS_MODEL(OCTEON_CN78XX) + || OCTEON_IS_MODEL(OCTEON_CNF75XX) + || OCTEON_IS_MODEL(OCTEON_CN73XX)); default: break; } - return 0; + return false; } #endif /* __OCTEON_FEATURE_H__ */ diff --git a/arch/mips/include/asm/octeon/octeon-model.h b/arch/mips/include/asm/octeon/octeon-model.h index 92b377e36dac..6c68517c2770 100644 --- a/arch/mips/include/asm/octeon/octeon-model.h +++ b/arch/mips/include/asm/octeon/octeon-model.h @@ -74,7 +74,12 @@ * CN7XXX models with new revision encoding */ +#define OCTEON_CNF75XX_PASS1_0 0x000d9800 +#define OCTEON_CNF75XX (OCTEON_CNF75XX_PASS1_0 | OM_IGNORE_REVISION) +#define OCTEON_CNF75XX_PASS1_X (OCTEON_CNF75XX_PASS1_0 | OM_IGNORE_MINOR_REVISION) + #define OCTEON_CN73XX_PASS1_0 0x000d9700 +#define OCTEON_CN73XX_PASS1_1 0x000d9701 #define OCTEON_CN73XX (OCTEON_CN73XX_PASS1_0 | OM_IGNORE_REVISION) #define OCTEON_CN73XX_PASS1_X (OCTEON_CN73XX_PASS1_0 | \ OM_IGNORE_MINOR_REVISION) -- cgit v1.2.3 From ce210d35bb93c2c5c8857878123275ecdcfd7018 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:11 -0800 Subject: MIPS: OCTEON: Add support for OCTEON III interrupt controller. Add irq_chip support for both IPI and "normal" interrupts of the CIU3 controller. Document the device tree binding for the CIU3. Some functions are non-static as they will be used by follow-on support for MSI-X. Signed-off-by: David Daney Acked-by: Rob Herring Cc: Rob Herring Cc: Pawel Moll Cc: Mark Rutland Cc: Ian Campbell Cc: Kumar Gala Cc: devicetree@vger.kernel.org Cc: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12500/ Signed-off-by: Ralf Baechle --- .../devicetree/bindings/mips/cavium/ciu3.txt | 27 + arch/mips/cavium-octeon/octeon-irq.c | 650 ++++++++++++++++++++- arch/mips/include/asm/octeon/octeon.h | 19 + 3 files changed, 695 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/mips/cavium/ciu3.txt (limited to 'arch/mips/include/asm') diff --git a/Documentation/devicetree/bindings/mips/cavium/ciu3.txt b/Documentation/devicetree/bindings/mips/cavium/ciu3.txt new file mode 100644 index 000000000000..616862ad2b71 --- /dev/null +++ b/Documentation/devicetree/bindings/mips/cavium/ciu3.txt @@ -0,0 +1,27 @@ +* Central Interrupt Unit v3 + +Properties: +- compatible: "cavium,octeon-7890-ciu3" + + Compatibility with 78XX and 73XX SOCs. + +- interrupt-controller: This is an interrupt controller. + +- reg: The base address of the CIU's register bank. + +- #interrupt-cells: Must be <2>. The first cell is source number. + The second cell indicates the triggering semantics, and may have a + value of either 4 for level semantics, or 1 for edge semantics. + +Example: + interrupt-controller@1010000000000 { + compatible = "cavium,octeon-7890-ciu3"; + interrupt-controller; + /* Interrupts are specified by two parts: + * 1) Source number (20 significant bits) + * 2) Trigger type: (4 == level, 1 == edge) + */ + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <0x10100 0x00000000 0x0 0xb0000000>; + }; diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index bc30d3a90b2f..9b6a65b959f9 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -19,15 +19,52 @@ #include #include +#include static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu0_en_mirror); static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu1_en_mirror); static DEFINE_PER_CPU(raw_spinlock_t, octeon_irq_ciu_spinlock); +static DEFINE_PER_CPU(unsigned int, octeon_irq_ciu3_idt_ip2); + +static DEFINE_PER_CPU(unsigned int, octeon_irq_ciu3_idt_ip3); +static DEFINE_PER_CPU(struct octeon_ciu3_info *, octeon_ciu3_info); +#define CIU3_MBOX_PER_CORE 10 + +/* + * The 8 most significant bits of the intsn identify the interrupt major block. + * Each major block might use its own interrupt domain. Thus 256 domains are + * needed. + */ +#define MAX_CIU3_DOMAINS 256 + +typedef irq_hw_number_t (*octeon_ciu3_intsn2hw_t)(struct irq_domain *, unsigned int); + +/* Information for each ciu3 in the system */ +struct octeon_ciu3_info { + u64 ciu3_addr; + int node; + struct irq_domain *domain[MAX_CIU3_DOMAINS]; + octeon_ciu3_intsn2hw_t intsn2hw[MAX_CIU3_DOMAINS]; +}; + +/* Each ciu3 in the system uses its own data (one ciu3 per node) */ +static struct octeon_ciu3_info *octeon_ciu3_info_per_node[4]; struct octeon_irq_ciu_domain_data { int num_sum; /* number of sum registers (2 or 3). */ }; +/* Register offsets from ciu3_addr */ +#define CIU3_CONST 0x220 +#define CIU3_IDT_CTL(_idt) ((_idt) * 8 + 0x110000) +#define CIU3_IDT_PP(_idt, _idx) ((_idt) * 32 + (_idx) * 8 + 0x120000) +#define CIU3_IDT_IO(_idt) ((_idt) * 8 + 0x130000) +#define CIU3_DEST_PP_INT(_pp_ip) ((_pp_ip) * 8 + 0x200000) +#define CIU3_DEST_IO_INT(_io) ((_io) * 8 + 0x210000) +#define CIU3_ISC_CTL(_intsn) ((_intsn) * 8 + 0x80000000) +#define CIU3_ISC_W1C(_intsn) ((_intsn) * 8 + 0x90000000) +#define CIU3_ISC_W1S(_intsn) ((_intsn) * 8 + 0xa0000000) + static __read_mostly int octeon_irq_ciu_to_irq[8][64]; struct octeon_ciu_chip_data { @@ -39,10 +76,11 @@ struct octeon_ciu_chip_data { struct { /* only used for ciu/ciu2 */ u8 line; u8 bit; - u8 gpio_line; }; }; + int gpio_line; int current_cpu; /* Next CPU expected to take this irq */ + int ciu_node; /* NUMA node number of the CIU */ }; struct octeon_core_chip_data { @@ -626,6 +664,18 @@ static void octeon_irq_ciu_enable_all_v2(struct irq_data *data) } } +static int octeon_irq_ciu_set_type(struct irq_data *data, unsigned int t) +{ + irqd_set_trigger_type(data, t); + + if (t & IRQ_TYPE_EDGE_BOTH) + irq_set_handler_locked(data, handle_edge_irq); + else + irq_set_handler_locked(data, handle_level_irq); + + return IRQ_SET_MASK_OK; +} + static void octeon_irq_gpio_setup(struct irq_data *data) { union cvmx_gpio_bit_cfgx cfg; @@ -863,6 +913,16 @@ static int octeon_irq_ciu_set_affinity_sum2(struct irq_data *data, } #endif +static unsigned int edge_startup(struct irq_data *data) +{ + /* ack any pending edge-irq at startup, so there is + * an _edge_ to fire on when the event reappears. + */ + data->chip->irq_ack(data); + data->chip->irq_enable(data); + return 0; +} + /* * Newer octeon chips have support for lockless CIU operation. */ @@ -2271,10 +2331,598 @@ static int __init octeon_irq_init_cib(struct device_node *ciu_node, return 0; } +int octeon_irq_ciu3_xlat(struct irq_domain *d, + struct device_node *node, + const u32 *intspec, + unsigned int intsize, + unsigned long *out_hwirq, + unsigned int *out_type) +{ + struct octeon_ciu3_info *ciu3_info = d->host_data; + unsigned int hwirq, type, intsn_major; + union cvmx_ciu3_iscx_ctl isc; + + if (intsize < 2) + return -EINVAL; + hwirq = intspec[0]; + type = intspec[1]; + + if (hwirq >= (1 << 20)) + return -EINVAL; + + intsn_major = hwirq >> 12; + switch (intsn_major) { + case 0x04: /* Software handled separately. */ + return -EINVAL; + default: + break; + } + + isc.u64 = cvmx_read_csr(ciu3_info->ciu3_addr + CIU3_ISC_CTL(hwirq)); + if (!isc.s.imp) + return -EINVAL; + + switch (type) { + case 4: /* official value for level triggering. */ + *out_type = IRQ_TYPE_LEVEL_HIGH; + break; + case 0: /* unofficial value, but we might as well let it work. */ + case 1: /* official value for edge triggering. */ + *out_type = IRQ_TYPE_EDGE_RISING; + break; + default: /* Nothing else is acceptable. */ + return -EINVAL; + } + + *out_hwirq = hwirq; + + return 0; +} + +void octeon_irq_ciu3_enable(struct irq_data *data) +{ + int cpu; + union cvmx_ciu3_iscx_ctl isc_ctl; + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_ctl_addr; + + struct octeon_ciu_chip_data *cd; + + cpu = next_cpu_for_irq(data); + + cd = irq_data_get_irq_chip_data(data); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64); + + isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn); + isc_ctl.u64 = 0; + isc_ctl.s.en = 1; + isc_ctl.s.idt = per_cpu(octeon_irq_ciu3_idt_ip2, cpu); + cvmx_write_csr(isc_ctl_addr, isc_ctl.u64); + cvmx_read_csr(isc_ctl_addr); +} + +void octeon_irq_ciu3_disable(struct irq_data *data) +{ + u64 isc_ctl_addr; + union cvmx_ciu3_iscx_w1c isc_w1c; + + struct octeon_ciu_chip_data *cd; + + cd = irq_data_get_irq_chip_data(data); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + + isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn); + cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64); + cvmx_write_csr(isc_ctl_addr, 0); + cvmx_read_csr(isc_ctl_addr); +} + +void octeon_irq_ciu3_ack(struct irq_data *data) +{ + u64 isc_w1c_addr; + union cvmx_ciu3_iscx_w1c isc_w1c; + struct octeon_ciu_chip_data *cd; + u32 trigger_type = irqd_get_trigger_type(data); + + /* + * We use a single irq_chip, so we have to do nothing to ack a + * level interrupt. + */ + if (!(trigger_type & IRQ_TYPE_EDGE_BOTH)) + return; + + cd = irq_data_get_irq_chip_data(data); + + isc_w1c.u64 = 0; + isc_w1c.s.raw = 1; + + isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn); + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); +} + +void octeon_irq_ciu3_mask(struct irq_data *data) +{ + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_w1c_addr; + struct octeon_ciu_chip_data *cd; + + cd = irq_data_get_irq_chip_data(data); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + + isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn); + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); +} + +void octeon_irq_ciu3_mask_ack(struct irq_data *data) +{ + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_w1c_addr; + struct octeon_ciu_chip_data *cd; + u32 trigger_type = irqd_get_trigger_type(data); + + cd = irq_data_get_irq_chip_data(data); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + + /* + * We use a single irq_chip, so only ack an edge (!level) + * interrupt. + */ + if (trigger_type & IRQ_TYPE_EDGE_BOTH) + isc_w1c.s.raw = 1; + + isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn); + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); +} + +#ifdef CONFIG_SMP +int octeon_irq_ciu3_set_affinity(struct irq_data *data, + const struct cpumask *dest, bool force) +{ + union cvmx_ciu3_iscx_ctl isc_ctl; + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_ctl_addr; + int cpu; + bool enable_one = !irqd_irq_disabled(data) && !irqd_irq_masked(data); + struct octeon_ciu_chip_data *cd = irq_data_get_irq_chip_data(data); + + if (!cpumask_subset(dest, cpumask_of_node(cd->ciu_node))) + return -EINVAL; + + if (!enable_one) + return IRQ_SET_MASK_OK; + + cd = irq_data_get_irq_chip_data(data); + cpu = cpumask_first(dest); + if (cpu >= nr_cpu_ids) + cpu = smp_processor_id(); + cd->current_cpu = cpu; + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64); + + isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn); + isc_ctl.u64 = 0; + isc_ctl.s.en = 1; + isc_ctl.s.idt = per_cpu(octeon_irq_ciu3_idt_ip2, cpu); + cvmx_write_csr(isc_ctl_addr, isc_ctl.u64); + cvmx_read_csr(isc_ctl_addr); + + return IRQ_SET_MASK_OK; +} +#endif + +static struct irq_chip octeon_irq_chip_ciu3 = { + .name = "CIU3", + .irq_startup = edge_startup, + .irq_enable = octeon_irq_ciu3_enable, + .irq_disable = octeon_irq_ciu3_disable, + .irq_ack = octeon_irq_ciu3_ack, + .irq_mask = octeon_irq_ciu3_mask, + .irq_mask_ack = octeon_irq_ciu3_mask_ack, + .irq_unmask = octeon_irq_ciu3_enable, + .irq_set_type = octeon_irq_ciu_set_type, +#ifdef CONFIG_SMP + .irq_set_affinity = octeon_irq_ciu3_set_affinity, + .irq_cpu_offline = octeon_irq_cpu_offline_ciu, +#endif +}; + +int octeon_irq_ciu3_mapx(struct irq_domain *d, unsigned int virq, + irq_hw_number_t hw, struct irq_chip *chip) +{ + struct octeon_ciu3_info *ciu3_info = d->host_data; + struct octeon_ciu_chip_data *cd = kzalloc_node(sizeof(*cd), GFP_KERNEL, + ciu3_info->node); + if (!cd) + return -ENOMEM; + cd->intsn = hw; + cd->current_cpu = -1; + cd->ciu3_addr = ciu3_info->ciu3_addr; + cd->ciu_node = ciu3_info->node; + irq_set_chip_and_handler(virq, chip, handle_edge_irq); + irq_set_chip_data(virq, cd); + + return 0; +} + +static int octeon_irq_ciu3_map(struct irq_domain *d, + unsigned int virq, irq_hw_number_t hw) +{ + return octeon_irq_ciu3_mapx(d, virq, hw, &octeon_irq_chip_ciu3); +} + +static struct irq_domain_ops octeon_dflt_domain_ciu3_ops = { + .map = octeon_irq_ciu3_map, + .unmap = octeon_irq_free_cd, + .xlate = octeon_irq_ciu3_xlat, +}; + +static void octeon_irq_ciu3_ip2(void) +{ + union cvmx_ciu3_destx_pp_int dest_pp_int; + struct octeon_ciu3_info *ciu3_info; + u64 ciu3_addr; + + ciu3_info = __this_cpu_read(octeon_ciu3_info); + ciu3_addr = ciu3_info->ciu3_addr; + + dest_pp_int.u64 = cvmx_read_csr(ciu3_addr + CIU3_DEST_PP_INT(3 * cvmx_get_local_core_num())); + + if (likely(dest_pp_int.s.intr)) { + irq_hw_number_t intsn = dest_pp_int.s.intsn; + irq_hw_number_t hw; + struct irq_domain *domain; + /* Get the domain to use from the major block */ + int block = intsn >> 12; + int ret; + + domain = ciu3_info->domain[block]; + if (ciu3_info->intsn2hw[block]) + hw = ciu3_info->intsn2hw[block](domain, intsn); + else + hw = intsn; + + ret = handle_domain_irq(domain, hw, NULL); + if (ret < 0) { + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_w1c_addr = ciu3_addr + CIU3_ISC_W1C(intsn); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); + spurious_interrupt(); + } + } else { + spurious_interrupt(); + } +} + +/* + * 10 mbox per core starting from zero. + * Base mbox is core * 10 + */ +static unsigned int octeon_irq_ciu3_base_mbox_intsn(int core) +{ + /* SW (mbox) are 0x04 in bits 12..19 */ + return 0x04000 + CIU3_MBOX_PER_CORE * core; +} + +static unsigned int octeon_irq_ciu3_mbox_intsn_for_core(int core, unsigned int mbox) +{ + return octeon_irq_ciu3_base_mbox_intsn(core) + mbox; +} + +static unsigned int octeon_irq_ciu3_mbox_intsn_for_cpu(int cpu, unsigned int mbox) +{ + int local_core = octeon_coreid_for_cpu(cpu) & 0x3f; + + return octeon_irq_ciu3_mbox_intsn_for_core(local_core, mbox); +} + +static void octeon_irq_ciu3_mbox(void) +{ + union cvmx_ciu3_destx_pp_int dest_pp_int; + struct octeon_ciu3_info *ciu3_info; + u64 ciu3_addr; + int core = cvmx_get_local_core_num(); + + ciu3_info = __this_cpu_read(octeon_ciu3_info); + ciu3_addr = ciu3_info->ciu3_addr; + + dest_pp_int.u64 = cvmx_read_csr(ciu3_addr + CIU3_DEST_PP_INT(1 + 3 * core)); + + if (likely(dest_pp_int.s.intr)) { + irq_hw_number_t intsn = dest_pp_int.s.intsn; + int mbox = intsn - octeon_irq_ciu3_base_mbox_intsn(core); + + if (likely(mbox >= 0 && mbox < CIU3_MBOX_PER_CORE)) { + do_IRQ(mbox + OCTEON_IRQ_MBOX0); + } else { + union cvmx_ciu3_iscx_w1c isc_w1c; + u64 isc_w1c_addr = ciu3_addr + CIU3_ISC_W1C(intsn); + + isc_w1c.u64 = 0; + isc_w1c.s.en = 1; + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); + spurious_interrupt(); + } + } else { + spurious_interrupt(); + } +} + +void octeon_ciu3_mbox_send(int cpu, unsigned int mbox) +{ + struct octeon_ciu3_info *ciu3_info; + unsigned int intsn; + union cvmx_ciu3_iscx_w1s isc_w1s; + u64 isc_w1s_addr; + + if (WARN_ON_ONCE(mbox >= CIU3_MBOX_PER_CORE)) + return; + + intsn = octeon_irq_ciu3_mbox_intsn_for_cpu(cpu, mbox); + ciu3_info = per_cpu(octeon_ciu3_info, cpu); + isc_w1s_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1S(intsn); + + isc_w1s.u64 = 0; + isc_w1s.s.raw = 1; + + cvmx_write_csr(isc_w1s_addr, isc_w1s.u64); + cvmx_read_csr(isc_w1s_addr); +} + +static void octeon_irq_ciu3_mbox_set_enable(struct irq_data *data, int cpu, bool en) +{ + struct octeon_ciu3_info *ciu3_info; + unsigned int intsn; + u64 isc_ctl_addr, isc_w1c_addr; + union cvmx_ciu3_iscx_ctl isc_ctl; + unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0; + + intsn = octeon_irq_ciu3_mbox_intsn_for_cpu(cpu, mbox); + ciu3_info = per_cpu(octeon_ciu3_info, cpu); + isc_w1c_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1C(intsn); + isc_ctl_addr = ciu3_info->ciu3_addr + CIU3_ISC_CTL(intsn); + + isc_ctl.u64 = 0; + isc_ctl.s.en = 1; + + cvmx_write_csr(isc_w1c_addr, isc_ctl.u64); + cvmx_write_csr(isc_ctl_addr, 0); + if (en) { + unsigned int idt = per_cpu(octeon_irq_ciu3_idt_ip3, cpu); + + isc_ctl.u64 = 0; + isc_ctl.s.en = 1; + isc_ctl.s.idt = idt; + cvmx_write_csr(isc_ctl_addr, isc_ctl.u64); + } + cvmx_read_csr(isc_ctl_addr); +} + +static void octeon_irq_ciu3_mbox_enable(struct irq_data *data) +{ + int cpu; + unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0; + + WARN_ON(mbox >= CIU3_MBOX_PER_CORE); + + for_each_online_cpu(cpu) + octeon_irq_ciu3_mbox_set_enable(data, cpu, true); +} + +static void octeon_irq_ciu3_mbox_disable(struct irq_data *data) +{ + int cpu; + unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0; + + WARN_ON(mbox >= CIU3_MBOX_PER_CORE); + + for_each_online_cpu(cpu) + octeon_irq_ciu3_mbox_set_enable(data, cpu, false); +} + +static void octeon_irq_ciu3_mbox_ack(struct irq_data *data) +{ + struct octeon_ciu3_info *ciu3_info; + unsigned int intsn; + u64 isc_w1c_addr; + union cvmx_ciu3_iscx_w1c isc_w1c; + unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0; + + intsn = octeon_irq_ciu3_mbox_intsn_for_core(cvmx_get_local_core_num(), mbox); + + isc_w1c.u64 = 0; + isc_w1c.s.raw = 1; + + ciu3_info = __this_cpu_read(octeon_ciu3_info); + isc_w1c_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1C(intsn); + cvmx_write_csr(isc_w1c_addr, isc_w1c.u64); + cvmx_read_csr(isc_w1c_addr); +} + +static void octeon_irq_ciu3_mbox_cpu_online(struct irq_data *data) +{ + octeon_irq_ciu3_mbox_set_enable(data, smp_processor_id(), true); +} + +static void octeon_irq_ciu3_mbox_cpu_offline(struct irq_data *data) +{ + octeon_irq_ciu3_mbox_set_enable(data, smp_processor_id(), false); +} + +static int octeon_irq_ciu3_alloc_resources(struct octeon_ciu3_info *ciu3_info) +{ + u64 b = ciu3_info->ciu3_addr; + int idt_ip2, idt_ip3, idt_ip4; + int unused_idt2; + int core = cvmx_get_local_core_num(); + int i; + + __this_cpu_write(octeon_ciu3_info, ciu3_info); + + /* + * 4 idt per core starting from 1 because zero is reserved. + * Base idt per core is 4 * core + 1 + */ + idt_ip2 = core * 4 + 1; + idt_ip3 = core * 4 + 2; + idt_ip4 = core * 4 + 3; + unused_idt2 = core * 4 + 4; + __this_cpu_write(octeon_irq_ciu3_idt_ip2, idt_ip2); + __this_cpu_write(octeon_irq_ciu3_idt_ip3, idt_ip3); + + /* ip2 interrupts for this CPU */ + cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip2), 0); + cvmx_write_csr(b + CIU3_IDT_PP(idt_ip2, 0), 1ull << core); + cvmx_write_csr(b + CIU3_IDT_IO(idt_ip2), 0); + + /* ip3 interrupts for this CPU */ + cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip3), 1); + cvmx_write_csr(b + CIU3_IDT_PP(idt_ip3, 0), 1ull << core); + cvmx_write_csr(b + CIU3_IDT_IO(idt_ip3), 0); + + /* ip4 interrupts for this CPU */ + cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip4), 2); + cvmx_write_csr(b + CIU3_IDT_PP(idt_ip4, 0), 0); + cvmx_write_csr(b + CIU3_IDT_IO(idt_ip4), 0); + + cvmx_write_csr(b + CIU3_IDT_CTL(unused_idt2), 0); + cvmx_write_csr(b + CIU3_IDT_PP(unused_idt2, 0), 0); + cvmx_write_csr(b + CIU3_IDT_IO(unused_idt2), 0); + + for (i = 0; i < CIU3_MBOX_PER_CORE; i++) { + unsigned int intsn = octeon_irq_ciu3_mbox_intsn_for_core(core, i); + + cvmx_write_csr(b + CIU3_ISC_W1C(intsn), 2); + cvmx_write_csr(b + CIU3_ISC_CTL(intsn), 0); + } + + return 0; +} + +static void octeon_irq_setup_secondary_ciu3(void) +{ + struct octeon_ciu3_info *ciu3_info; + + ciu3_info = octeon_ciu3_info_per_node[cvmx_get_node_num()]; + octeon_irq_ciu3_alloc_resources(ciu3_info); + irq_cpu_online(); + + /* Enable the CIU lines */ + set_c0_status(STATUSF_IP3 | STATUSF_IP2); + if (octeon_irq_use_ip4) + set_c0_status(STATUSF_IP4); + else + clear_c0_status(STATUSF_IP4); +} + +static struct irq_chip octeon_irq_chip_ciu3_mbox = { + .name = "CIU3-M", + .irq_enable = octeon_irq_ciu3_mbox_enable, + .irq_disable = octeon_irq_ciu3_mbox_disable, + .irq_ack = octeon_irq_ciu3_mbox_ack, + + .irq_cpu_online = octeon_irq_ciu3_mbox_cpu_online, + .irq_cpu_offline = octeon_irq_ciu3_mbox_cpu_offline, + .flags = IRQCHIP_ONOFFLINE_ENABLED, +}; + +static int __init octeon_irq_init_ciu3(struct device_node *ciu_node, + struct device_node *parent) +{ + int i; + int node; + struct irq_domain *domain; + struct octeon_ciu3_info *ciu3_info; + const __be32 *zero_addr; + u64 base_addr; + union cvmx_ciu3_const consts; + + node = 0; /* of_node_to_nid(ciu_node); */ + ciu3_info = kzalloc_node(sizeof(*ciu3_info), GFP_KERNEL, node); + + if (!ciu3_info) + return -ENOMEM; + + zero_addr = of_get_address(ciu_node, 0, NULL, NULL); + if (WARN_ON(!zero_addr)) + return -EINVAL; + + base_addr = of_translate_address(ciu_node, zero_addr); + base_addr = (u64)phys_to_virt(base_addr); + + ciu3_info->ciu3_addr = base_addr; + ciu3_info->node = node; + + consts.u64 = cvmx_read_csr(base_addr + CIU3_CONST); + + octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu3; + + octeon_irq_ip2 = octeon_irq_ciu3_ip2; + octeon_irq_ip3 = octeon_irq_ciu3_mbox; + octeon_irq_ip4 = octeon_irq_ip4_mask; + + if (node == cvmx_get_node_num()) { + /* Mips internal */ + octeon_irq_init_core(); + + /* Only do per CPU things if it is the CIU of the boot node. */ + i = irq_alloc_descs_from(OCTEON_IRQ_MBOX0, 8, node); + WARN_ON(i < 0); + + for (i = 0; i < 8; i++) + irq_set_chip_and_handler(i + OCTEON_IRQ_MBOX0, + &octeon_irq_chip_ciu3_mbox, handle_percpu_irq); + } + + /* + * Initialize all domains to use the default domain. Specific major + * blocks will overwrite the default domain as needed. + */ + domain = irq_domain_add_tree(ciu_node, &octeon_dflt_domain_ciu3_ops, + ciu3_info); + for (i = 0; i < MAX_CIU3_DOMAINS; i++) + ciu3_info->domain[i] = domain; + + octeon_ciu3_info_per_node[node] = ciu3_info; + + if (node == cvmx_get_node_num()) { + /* Only do per CPU things if it is the CIU of the boot node. */ + octeon_irq_ciu3_alloc_resources(ciu3_info); + if (node == 0) + irq_set_default_host(domain); + + octeon_irq_use_ip4 = false; + /* Enable the CIU lines */ + set_c0_status(STATUSF_IP2 | STATUSF_IP3); + clear_c0_status(STATUSF_IP4); + } + + return 0; +} + static struct of_device_id ciu_types[] __initdata = { {.compatible = "cavium,octeon-3860-ciu", .data = octeon_irq_init_ciu}, {.compatible = "cavium,octeon-3860-gpio", .data = octeon_irq_init_gpio}, {.compatible = "cavium,octeon-6880-ciu2", .data = octeon_irq_init_ciu2}, + {.compatible = "cavium,octeon-7890-ciu3", .data = octeon_irq_init_ciu3}, {.compatible = "cavium,octeon-7130-cib", .data = octeon_irq_init_cib}, {} }; diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index de9f74ee5dd0..53d51aeb9140 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -299,6 +299,25 @@ static inline void octeon_npi_write32(uint64_t address, uint32_t val) cvmx_read64_uint32(address ^ 4); } +struct irq_domain; +struct device_node; +struct irq_data; +struct irq_chip; +void octeon_ciu3_mbox_send(int cpu, unsigned int mbox); +int octeon_irq_ciu3_xlat(struct irq_domain *d, + struct device_node *node, + const u32 *intspec, + unsigned int intsize, + unsigned long *out_hwirq, + unsigned int *out_type); +void octeon_irq_ciu3_enable(struct irq_data *data); +void octeon_irq_ciu3_disable(struct irq_data *data); +void octeon_irq_ciu3_ack(struct irq_data *data); +void octeon_irq_ciu3_mask(struct irq_data *data); +void octeon_irq_ciu3_mask_ack(struct irq_data *data); +int octeon_irq_ciu3_mapx(struct irq_domain *d, unsigned int virq, + irq_hw_number_t hw, struct irq_chip *chip); + /* Octeon multiplier save/restore routines from octeon_switch.S */ void octeon_mult_save(void); void octeon_mult_restore(void); -- cgit v1.2.3 From c6d2b22eb5211e96e932428bc1183c6ad57d5e54 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 9 Feb 2016 11:00:12 -0800 Subject: MIPS: OCTEON: Add SMP support for OCTEON cn78xx et al. OCTEON chips with the CIU3 interrupt controller use a different IPI mechanism that previous models. Add plat_smp_ops for the cn78xx and probing code to choose between the two types of ops. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12499/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 4 +- arch/mips/cavium-octeon/smp.c | 145 +++++++++++++++++++++++++++++++--- arch/mips/include/asm/octeon/octeon.h | 6 ++ 3 files changed, 139 insertions(+), 16 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 54a214ec33d3..8ffc1f108239 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -43,8 +43,6 @@ #include #include -extern struct plat_smp_ops octeon_smp_ops; - #ifdef CONFIG_PCI extern void pci_console_init(const char *arg); #endif @@ -888,7 +886,7 @@ void __init prom_init(void) #endif octeon_user_io_init(); - register_smp_ops(&octeon_smp_ops); + octeon_setup_smp(); } /* Exclude a single page from the regions obtained in plat_mem_setup. */ diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 42395c561aa5..32c0cce73ed7 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -30,25 +30,55 @@ uint64_t octeon_bootloader_entry_addr; EXPORT_SYMBOL(octeon_bootloader_entry_addr); #endif +static void octeon_icache_flush(void) +{ + asm volatile ("synci 0($0)\n"); +} + +static void (*octeon_message_functions[8])(void) = { + scheduler_ipi, + generic_smp_call_function_interrupt, + octeon_icache_flush, +}; + static irqreturn_t mailbox_interrupt(int irq, void *dev_id) { - const int coreid = cvmx_get_core_num(); - uint64_t action; + u64 mbox_clrx = CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()); + u64 action; + int i; + + /* + * Make sure the function array initialization remains + * correct. + */ + BUILD_BUG_ON(SMP_RESCHEDULE_YOURSELF != (1 << 0)); + BUILD_BUG_ON(SMP_CALL_FUNCTION != (1 << 1)); + BUILD_BUG_ON(SMP_ICACHE_FLUSH != (1 << 2)); + + /* + * Load the mailbox register to figure out what we're supposed + * to do. + */ + action = cvmx_read_csr(mbox_clrx); - /* Load the mailbox register to figure out what we're supposed to do */ - action = cvmx_read_csr(CVMX_CIU_MBOX_CLRX(coreid)) & 0xffff; + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + action &= 0xff; + else + action &= 0xffff; /* Clear the mailbox to clear the interrupt */ - cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), action); + cvmx_write_csr(mbox_clrx, action); - if (action & SMP_CALL_FUNCTION) - generic_smp_call_function_interrupt(); - if (action & SMP_RESCHEDULE_YOURSELF) - scheduler_ipi(); + for (i = 0; i < ARRAY_SIZE(octeon_message_functions) && action;) { + if (action & 1) { + void (*fn)(void) = octeon_message_functions[i]; - /* Check if we've been told to flush the icache */ - if (action & SMP_ICACHE_FLUSH) - asm volatile ("synci 0($0)\n"); + if (fn) + fn(); + } + action >>= 1; + i++; + } return IRQ_HANDLED; } @@ -102,10 +132,10 @@ static void octeon_smp_setup(void) const int coreid = cvmx_get_core_num(); int cpus; int id; - int core_mask = octeon_get_boot_coremask(); struct cvmx_sysinfo *sysinfo = cvmx_sysinfo_get(); #ifdef CONFIG_HOTPLUG_CPU + int core_mask = octeon_get_boot_coremask(); unsigned int num_cores = cvmx_octeon_num_cores(); #endif @@ -390,3 +420,92 @@ struct plat_smp_ops octeon_smp_ops = { .cpu_die = octeon_cpu_die, #endif }; + +static irqreturn_t octeon_78xx_reched_interrupt(int irq, void *dev_id) +{ + scheduler_ipi(); + return IRQ_HANDLED; +} + +static irqreturn_t octeon_78xx_call_function_interrupt(int irq, void *dev_id) +{ + generic_smp_call_function_interrupt(); + return IRQ_HANDLED; +} + +static irqreturn_t octeon_78xx_icache_flush_interrupt(int irq, void *dev_id) +{ + octeon_icache_flush(); + return IRQ_HANDLED; +} + +/* + * Callout to firmware before smp_init + */ +static void octeon_78xx_prepare_cpus(unsigned int max_cpus) +{ + if (request_irq(OCTEON_IRQ_MBOX0 + 0, + octeon_78xx_reched_interrupt, + IRQF_PERCPU | IRQF_NO_THREAD, "Scheduler", + octeon_78xx_reched_interrupt)) { + panic("Cannot request_irq for SchedulerIPI"); + } + if (request_irq(OCTEON_IRQ_MBOX0 + 1, + octeon_78xx_call_function_interrupt, + IRQF_PERCPU | IRQF_NO_THREAD, "SMP-Call", + octeon_78xx_call_function_interrupt)) { + panic("Cannot request_irq for SMP-Call"); + } + if (request_irq(OCTEON_IRQ_MBOX0 + 2, + octeon_78xx_icache_flush_interrupt, + IRQF_PERCPU | IRQF_NO_THREAD, "ICache-Flush", + octeon_78xx_icache_flush_interrupt)) { + panic("Cannot request_irq for ICache-Flush"); + } +} + +static void octeon_78xx_send_ipi_single(int cpu, unsigned int action) +{ + int i; + + for (i = 0; i < 8; i++) { + if (action & 1) + octeon_ciu3_mbox_send(cpu, i); + action >>= 1; + } +} + +static void octeon_78xx_send_ipi_mask(const struct cpumask *mask, + unsigned int action) +{ + unsigned int cpu; + + for_each_cpu(cpu, mask) + octeon_78xx_send_ipi_single(cpu, action); +} + +static struct plat_smp_ops octeon_78xx_smp_ops = { + .send_ipi_single = octeon_78xx_send_ipi_single, + .send_ipi_mask = octeon_78xx_send_ipi_mask, + .init_secondary = octeon_init_secondary, + .smp_finish = octeon_smp_finish, + .boot_secondary = octeon_boot_secondary, + .smp_setup = octeon_smp_setup, + .prepare_cpus = octeon_78xx_prepare_cpus, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_disable = octeon_cpu_disable, + .cpu_die = octeon_cpu_die, +#endif +}; + +void __init octeon_setup_smp(void) +{ + struct plat_smp_ops *ops; + + if (octeon_has_feature(OCTEON_FEATURE_CIU3)) + ops = &octeon_78xx_smp_ops; + else + ops = &octeon_smp_ops; + + register_smp_ops(ops); +} diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index 53d51aeb9140..07c0516ef4d5 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -299,6 +299,12 @@ static inline void octeon_npi_write32(uint64_t address, uint32_t val) cvmx_read64_uint32(address ^ 4); } +#ifdef CONFIG_SMP +void octeon_setup_smp(void); +#else +static inline void octeon_setup_smp(void) {} +#endif + struct irq_domain; struct device_node; struct irq_data; -- cgit v1.2.3 From 6ecffafe242ec6d2789631499452c54177f0bb4c Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 23 Feb 2016 00:22:55 +0200 Subject: MIPS: Octeon: board_type_to_string: return NULL for unsupported board Return NULL for unsupported board. Signed-off-by: Aaro Koskinen Cc: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12581/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 9 +++++++-- arch/mips/include/asm/octeon/cvmx-bootinfo.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 8ffc1f108239..4759494c3ff4 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -466,9 +466,14 @@ static char __read_mostly octeon_system_type[80]; static int __init init_octeon_system_type(void) { + char const *board_type; + + board_type = cvmx_board_type_to_string(octeon_bootinfo->board_type); + if (board_type == NULL) + board_type = "Unsupported Board"; + snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)", - cvmx_board_type_to_string(octeon_bootinfo->board_type), - octeon_model_get_string(read_c0_prid())); + board_type, octeon_model_get_string(read_c0_prid())); return 0; } diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h index c455d34f5a4f..62787765575e 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h @@ -400,7 +400,7 @@ static inline const char *cvmx_board_type_to_string(enum ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KONTRON_S1901) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX) } - return "Unsupported Board"; + return NULL; } #define ENUM_CHIP_TYPE_CASE(x) \ -- cgit v1.2.3 From f270d881fa552c9c21c37417af2bf95da9a74347 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:21 +0000 Subject: MIPS: Detect MIPSr6 Virtual Processor support MIPSr6 introduces support for "Virtual Processors", which are conceptually similar to VPEs from the now-deprecated MT ASE. Detect whether the system supports VPs using the VP bit in Config5, adding cpu_has_vp for use by later patches. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Maciej W. Rozycki Cc: Joshua Kinard Cc: Steven J. Hill Cc: Leonid Yegoshin Cc: James Hogan Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12327/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 4 ++++ arch/mips/include/asm/cpu.h | 1 + arch/mips/include/asm/mipsregs.h | 1 + arch/mips/kernel/cpu-probe.c | 2 ++ 4 files changed, 8 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index eeec8c8e2da2..57cdc5be9545 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -311,6 +311,10 @@ #define cpu_has_mipsmt (cpu_data[0].ases & MIPS_ASE_MIPSMT) #endif +#ifndef cpu_has_vp +#define cpu_has_vp (cpu_data[0].options & MIPS_CPU_VP) +#endif + #ifndef cpu_has_userlocal #define cpu_has_userlocal (cpu_data[0].options & MIPS_CPU_ULRI) #endif diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 7bea0f3bf9ee..631aa10fdebe 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -390,6 +390,7 @@ enum cpu_type_enum { #define MIPS_CPU_FTLB 0x20000000000ull /* CPU has Fixed-page-size TLB */ #define MIPS_CPU_NAN_LEGACY 0x40000000000ull /* Legacy NaN implemented */ #define MIPS_CPU_NAN_2008 0x80000000000ull /* 2008 NaN implemented */ +#define MIPS_CPU_VP 0x100000000000ull /* MIPSr6 Virtual Processors (multi-threading) */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 3ad19ad04d8a..ca251f6fea8e 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -623,6 +623,7 @@ #define MIPS_CONF5_MRP (_ULCAST_(1) << 3) #define MIPS_CONF5_LLB (_ULCAST_(1) << 4) #define MIPS_CONF5_MVH (_ULCAST_(1) << 5) +#define MIPS_CONF5_VP (_ULCAST_(1) << 7) #define MIPS_CONF5_FRE (_ULCAST_(1) << 8) #define MIPS_CONF5_UFE (_ULCAST_(1) << 9) #define MIPS_CONF5_MSAEN (_ULCAST_(1) << 27) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 9ad6157e23de..e0cfa3b85bca 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -796,6 +796,8 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c) if (config5 & MIPS_CONF5_MVH) c->options |= MIPS_CPU_XPA; #endif + if (cpu_has_mips_r6 && (config5 & MIPS_CONF5_VP)) + c->options |= MIPS_CPU_VP; return config5 & MIPS_CONF_M; } -- cgit v1.2.3 From 88036557bac3c831a564dcd6c860da48ae55756f Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 3 Feb 2016 03:15:24 +0000 Subject: MIPS: CPC: Add start, stop and running CM3 CPC registers Add the new CM3 registers for controlling bringing up and powering down VPs on MIPSR6 cores. Signed-off-by: Markos Chandras Signed-off-by: Paul Burton Cc: Bjorn Helgaas Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12330/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cpc.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mips-cpc.h b/arch/mips/include/asm/mips-cpc.h index e09035239e53..8c519f9827a3 100644 --- a/arch/mips/include/asm/mips-cpc.h +++ b/arch/mips/include/asm/mips-cpc.h @@ -106,6 +106,9 @@ BUILD_CPC_R_(revision, MIPS_CPC_GCB_OFS + 0x20) BUILD_CPC_Cx_RW(cmd, 0x00) BUILD_CPC_Cx_RW(stat_conf, 0x08) BUILD_CPC_Cx_RW(other, 0x10) +BUILD_CPC_Cx_RW(vp_stop, 0x20) +BUILD_CPC_Cx_RW(vp_run, 0x28) +BUILD_CPC_Cx_RW(vp_running, 0x30) /* CPC_Cx_CMD register fields */ #define CPC_Cx_CMD_SHF 0 -- cgit v1.2.3 From db8e00af7b4a09ef5924140c1c42494fc88204ef Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:25 +0000 Subject: MIPS: CM: Add CM GCR_BEV_BASE accessors Generate accessor functions for the GCR_BEV_BASE register introduced by CM3, for use by a later patch. Signed-off-by: Paul Burton Cc: Matt Redfearn Cc: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12331/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 4ac8e4b69fb5..b79433f19b77 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -208,6 +208,7 @@ BUILD_CM_RW(l2_config, MIPS_CM_GCB_OFS + 0x130) BUILD_CM_RW(sys_config2, MIPS_CM_GCB_OFS + 0x150) BUILD_CM_RW(l2_pft_control, MIPS_CM_GCB_OFS + 0x300) BUILD_CM_RW(l2_pft_control_b, MIPS_CM_GCB_OFS + 0x308) +BUILD_CM_RW(bev_base, MIPS_CM_GCB_OFS + 0x680) /* Core Local & Core Other register accessor functions */ BUILD_CM_Cx_RW(reset_release, 0x00) -- cgit v1.2.3 From a60ae81e5e5918138703f22427dd8f2445985b55 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:26 +0000 Subject: MIPS: CM: Fix mips_cm_max_vp_width for UP kernels Fix mips_cm_max_vp_width for UP kernels where it previously referenced smp_num_siblings, which is not declared for UP kernels. This led to build errors such as the following: drivers/built-in.o: In function `$L446': irq-mips-gic.c:(.text+0x1994): undefined reference to `smp_num_siblings' drivers/built-in.o:irq-mips-gic.c:(.text+0x199c): more undefined references to `smp_num_siblings' follow On UP kernels simply return 1, leaving the reference to smp_num_siblings in place only for SMP kernels. Signed-off-by: Paul Burton Cc: Matt Redfearn Cc: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12332/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index b79433f19b77..3fea29e50c46 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -462,7 +462,10 @@ static inline unsigned int mips_cm_max_vp_width(void) if (mips_cm_revision() >= CM_REV_CM3) return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW_MSK; - return smp_num_siblings; + if (config_enabled(CONFIG_SMP)) + return smp_num_siblings; + + return 1; } /** -- cgit v1.2.3 From f12401d7219f5a1e361ded834016e5777a10262b Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:31 +0000 Subject: MIPS: smp-cps: Pull boot config retrieval out of mips_cps_boot_vpes The mips_cps_boot_vpes function previously included code to retrieve pointers to the core & VPE boot configuration structs. These structures were used both by mips_cps_boot_vpes and by its mips_cps_core_entry callsite. In preparation for skipping the call to mips_cps_boot_vpes on some invocations of mips_cps_core_entry, pull the calculation of those pointers out into a separate function such that it can continue to be shared. Signed-off-by: Paul Burton Cc: Rusty Russell Cc: Matt Redfearn Cc: Niklas Cassel Cc: Ezequiel Garcia Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12337/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/smp-cps.h | 2 +- arch/mips/kernel/cps-vec.S | 74 +++++++++++++++++++++++++---------------- arch/mips/kernel/smp-cps.c | 7 ++-- 3 files changed, 52 insertions(+), 31 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/smp-cps.h b/arch/mips/include/asm/smp-cps.h index 326c16ebd589..2ae1f61a4a95 100644 --- a/arch/mips/include/asm/smp-cps.h +++ b/arch/mips/include/asm/smp-cps.h @@ -29,7 +29,7 @@ extern struct core_boot_config *mips_cps_core_bootcfg; extern void mips_cps_core_entry(void); extern void mips_cps_core_init(void); -extern struct vpe_boot_config *mips_cps_boot_vpes(void); +extern void mips_cps_boot_vpes(struct core_boot_config *cfg, unsigned vpe); extern void mips_cps_pm_save(void); extern void mips_cps_pm_restore(void); diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 8d5ea4b778f9..2613de9bcb2d 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -60,6 +60,17 @@ nop .endm + /* Calculate an uncached address for the CM GCRs */ + .macro cmgcrb dest + .set push + .set noat + MFC0 $1, CP0_CMGCRBASE + PTR_SLL $1, $1, 4 + PTR_LI \dest, UNCAC_BASE + PTR_ADDU \dest, \dest, $1 + .set pop + .endm + .section .text.cps-vec .balign 0x1000 @@ -102,13 +113,8 @@ not_nmi: mtc0 t0, CP0_CONFIG ehb - /* Calculate an uncached address for the CM GCRs */ - MFC0 v1, CP0_CMGCRBASE - PTR_SLL v1, v1, 4 - PTR_LI t0, UNCAC_BASE - PTR_ADDU v1, v1, t0 - /* Enter the coherent domain */ + cmgcrb v1 li t0, 0xff sw t0, GCR_CL_COHERENCE_OFS(v1) ehb @@ -128,17 +134,22 @@ not_nmi: /* Do any EVA initialization if necessary */ eva_init + /* Retrieve boot configuration pointers */ + jal mips_cps_get_bootcfg + nop + /* * Boot any other VPEs within this core that should be online, and * deactivate this VPE if it should be offline. */ + move a1, t9 jal mips_cps_boot_vpes - nop + move a0, v0 /* Off we go! */ - PTR_L t1, VPEBOOTCFG_PC(v0) - PTR_L gp, VPEBOOTCFG_GP(v0) - PTR_L sp, VPEBOOTCFG_SP(v0) + PTR_L t1, VPEBOOTCFG_PC(v1) + PTR_L gp, VPEBOOTCFG_GP(v1) + PTR_L sp, VPEBOOTCFG_SP(v1) jr t1 nop END(mips_cps_core_entry) @@ -258,18 +269,21 @@ LEAF(mips_cps_core_init) nop END(mips_cps_core_init) -LEAF(mips_cps_boot_vpes) - /* Retrieve CM base address */ - PTR_LA t0, mips_cm_base - PTR_L t0, 0(t0) - +/** + * mips_cps_get_bootcfg() - retrieve boot configuration pointers + * + * Returns: pointer to struct core_boot_config in v0, pointer to + * struct vpe_boot_config in v1, VPE ID in t9 + */ +LEAF(mips_cps_get_bootcfg) /* Calculate a pointer to this cores struct core_boot_config */ + cmgcrb t0 lw t0, GCR_CL_ID_OFS(t0) li t1, COREBOOTCFG_SIZE mul t0, t0, t1 PTR_LA t1, mips_cps_core_bootcfg PTR_L t1, 0(t1) - PTR_ADDU t0, t0, t1 + PTR_ADDU v0, t0, t1 /* Calculate this VPEs ID. If the core doesn't support MT use 0 */ li t9, 0 @@ -297,22 +311,27 @@ LEAF(mips_cps_boot_vpes) 1: /* Calculate a pointer to this VPEs struct vpe_boot_config */ li t1, VPEBOOTCFG_SIZE - mul v0, t9, t1 - PTR_L ta3, COREBOOTCFG_VPECONFIG(t0) - PTR_ADDU v0, v0, ta3 - -#ifdef CONFIG_MIPS_MT_SMP + mul v1, t9, t1 + PTR_L ta3, COREBOOTCFG_VPECONFIG(v0) + PTR_ADDU v1, v1, ta3 - /* If the core doesn't support MT then return */ - bnez ta2, 1f - nop jr ra nop + END(mips_cps_get_bootcfg) + +LEAF(mips_cps_boot_vpes) + PTR_L ta2, COREBOOTCFG_VPEMASK(a0) + PTR_L ta3, COREBOOTCFG_VPECONFIG(a0) + +#ifdef CONFIG_MIPS_MT .set push .set mt -1: /* Enter VPE configuration state */ + /* If the core doesn't support MT then return */ + has_mt t0, 5f + + /* Enter VPE configuration state */ dvpe PTR_LA t1, 1f jr.hb t1 @@ -323,7 +342,6 @@ LEAF(mips_cps_boot_vpes) ehb /* Loop through each VPE */ - PTR_L ta2, COREBOOTCFG_VPEMASK(t0) move t8, ta2 li ta1, 0 @@ -400,7 +418,7 @@ LEAF(mips_cps_boot_vpes) /* Check whether this VPE is meant to be running */ li t0, 1 - sll t0, t0, t9 + sll t0, t0, a1 and t0, t0, t8 bnez t0, 2f nop @@ -417,7 +435,7 @@ LEAF(mips_cps_boot_vpes) #endif /* CONFIG_MIPS_MT_SMP */ /* Return */ - jr ra +5: jr ra nop END(mips_cps_boot_vpes) diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 9d9c7ff61d4d..1a289db642cf 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -250,7 +250,10 @@ static void boot_core(unsigned core) static void remote_vpe_boot(void *dummy) { - mips_cps_boot_vpes(); + unsigned core = current_cpu_data.core; + struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core]; + + mips_cps_boot_vpes(core_cfg, cpu_vpe_id(¤t_cpu_data)); } static void cps_boot_secondary(int cpu, struct task_struct *idle) @@ -296,7 +299,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) BUG_ON(!cpu_has_mipsmt); /* Boot a VPE on this core */ - mips_cps_boot_vpes(); + mips_cps_boot_vpes(core_cfg, vpe_id); out: preempt_enable(); } -- cgit v1.2.3 From 5a3e7c02d84fd31e6a2b1b242612363b6131a09e Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:15:33 +0000 Subject: MIPS: smp-cps: Support MIPSr6 Virtual Processors Introduce support for bringing up Virtual Processors in MIPSr6 systems as CPUs, much like their VPE parallel from the now-deprecated MT ASE. The existing mips_cps_boot_vpes function fits the MIPSr6 architecture pretty well - it can now simply write the mask of running VPs to the VC_RUN register, rather than looping through each & starting or stopping as appropriate as is done for VPEs from the MT ASE. Thus the VP support is in general an extension & simplification of the existing MT ASE VPE (aka SMVP) support. Signed-off-by: Paul Burton Cc: Matt Redfearn Cc: Rusty Russell Cc: Maciej W. Rozycki Cc: Niklas Cassel Cc: Ezequiel Garcia Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12339/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- arch/mips/include/asm/cpu-info.h | 4 +-- arch/mips/kernel/cps-vec.S | 53 ++++++++++++++++++++++++++++++++++++++-- arch/mips/kernel/smp-cps.c | 35 +++++++++++++++++++++++--- 4 files changed, 85 insertions(+), 9 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 882e73c3334e..e77a439c1932 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2282,7 +2282,7 @@ config MIPS_CMP config MIPS_CPS bool "MIPS Coherent Processing System support" - depends on SYS_SUPPORTS_MIPS_CPS && !CPU_MIPSR6 + depends on SYS_SUPPORTS_MIPS_CPS select MIPS_CM select MIPS_CPC select MIPS_CPS_PM if HOTPLUG_CPU diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index af12c1f9f1a8..9ec81684b1b8 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -68,7 +68,7 @@ struct cpuinfo_mips { #ifdef CONFIG_64BIT int vmbits; /* Virtual memory size in bits */ #endif -#ifdef CONFIG_MIPS_MT_SMP +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6) /* * There is not necessarily a 1:1 mapping of VPE num to CPU number * in particular on multi-core systems. @@ -125,7 +125,7 @@ struct proc_cpuinfo_notifier_args { unsigned long n; }; -#ifdef CONFIG_MIPS_MT_SMP +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6) # define cpu_vpe_id(cpuinfo) ((cpuinfo)->vpe_id) #else # define cpu_vpe_id(cpuinfo) ({ (void)cpuinfo; 0; }) diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 4849cbd47ccc..c28138d53d32 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -18,9 +18,12 @@ #include #include +#define GCR_CPC_BASE_OFS 0x0088 #define GCR_CL_COHERENCE_OFS 0x2008 #define GCR_CL_ID_OFS 0x2028 +#define CPC_CL_VC_RUN_OFS 0x2028 + .extern mips_cm_base .set noreorder @@ -60,6 +63,26 @@ nop .endm + /* + * Set dest to non-zero if the core supports MIPSr6 multithreading + * (ie. VPs), else zero. If MIPSr6 multithreading is not supported then + * branch to nomt. + */ + .macro has_vp dest, nomt + mfc0 \dest, CP0_CONFIG, 1 + bgez \dest, \nomt + mfc0 \dest, CP0_CONFIG, 2 + bgez \dest, \nomt + mfc0 \dest, CP0_CONFIG, 3 + bgez \dest, \nomt + mfc0 \dest, CP0_CONFIG, 4 + bgez \dest, \nomt + mfc0 \dest, CP0_CONFIG, 5 + andi \dest, \dest, MIPS_CONF5_VP + beqz \dest, \nomt + nop + .endm + /* Calculate an uncached address for the CM GCRs */ .macro cmgcrb dest .set push @@ -296,7 +319,17 @@ LEAF(mips_cps_get_bootcfg) /* Calculate this VPEs ID. If the core doesn't support MT use 0 */ li t9, 0 -#ifdef CONFIG_MIPS_MT_SMP +#if defined(CONFIG_CPU_MIPSR6) + has_vp ta2, 1f + + /* + * Assume non-contiguous numbering. Perhaps some day we'll need + * to handle contiguous VP numbering, but no such systems yet + * exist. + */ + mfc0 t9, $3, 1 + andi t9, t9, 0xff +#elif defined(CONFIG_MIPS_MT_SMP) has_mt ta2, 1f /* Find the number of VPEs present in the core */ @@ -332,7 +365,23 @@ LEAF(mips_cps_boot_vpes) PTR_L ta2, COREBOOTCFG_VPEMASK(a0) PTR_L ta3, COREBOOTCFG_VPECONFIG(a0) -#ifdef CONFIG_MIPS_MT +#if defined(CONFIG_CPU_MIPSR6) + + has_vp t0, 5f + + /* Find base address of CPC */ + cmgcrb t3 + PTR_L t1, GCR_CPC_BASE_OFS(t3) + PTR_LI t2, ~0x7fff + and t1, t1, t2 + PTR_LI t2, UNCAC_BASE + PTR_ADD t1, t1, t2 + + /* Set VC_RUN to the VPE mask */ + PTR_S ta2, CPC_CL_VC_RUN_OFS(t1) + ehb + +#elif defined(CONFIG_MIPS_MT) .set push .set mt diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 1a289db642cf..06512171fd19 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -35,7 +35,8 @@ static unsigned core_vpe_count(unsigned core) { unsigned cfg; - if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt) + if ((!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt) + && (!config_enabled(CONFIG_CPU_MIPSR6) || !cpu_has_vp)) return 1; mips_cm_lock_other(core, 0); @@ -47,11 +48,12 @@ static unsigned core_vpe_count(unsigned core) static void __init cps_smp_setup(void) { unsigned int ncores, nvpes, core_vpes; + unsigned long core_entry; int c, v; /* Detect & record VPE topology */ ncores = mips_cm_numcores(); - pr_info("VPE topology "); + pr_info("%s topology ", cpu_has_mips_r6 ? "VP" : "VPE"); for (c = nvpes = 0; c < ncores; c++) { core_vpes = core_vpe_count(c); pr_cont("%c%u", c ? ',' : '{', core_vpes); @@ -62,7 +64,7 @@ static void __init cps_smp_setup(void) for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) { cpu_data[nvpes + v].core = c; -#ifdef CONFIG_MIPS_MT_SMP +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6) cpu_data[nvpes + v].vpe_id = v; #endif } @@ -91,6 +93,11 @@ static void __init cps_smp_setup(void) /* Make core 0 coherent with everything */ write_gcr_cl_coherence(0xff); + if (mips_cm_revision() >= CM_REV_CM3) { + core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry); + write_gcr_bev_base(core_entry); + } + #ifdef CONFIG_MIPS_MT_FPAFF /* If we have an FPU, enroll ourselves in the FPU-full mask */ if (cpu_has_fpu) @@ -213,6 +220,18 @@ static void boot_core(unsigned core) if (mips_cpc_present()) { /* Reset the core */ mips_cpc_lock_other(core); + + if (mips_cm_revision() >= CM_REV_CM3) { + /* Run VP0 following the reset */ + write_cpc_co_vp_run(0x1); + + /* + * Ensure that the VP_RUN register is written before the + * core leaves reset. + */ + wmb(); + } + write_cpc_co_cmd(CPC_Cx_CMD_RESET); timeout = 100; @@ -262,6 +281,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]); struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core]; struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id]; + unsigned long core_entry; unsigned int remote; int err; @@ -279,6 +299,13 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) goto out; } + if (cpu_has_vp) { + mips_cm_lock_other(core, vpe_id); + core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry); + write_gcr_co_reset_base(core_entry); + mips_cm_unlock_other(); + } + if (core != current_cpu_data.core) { /* Boot a VPE on another powered up core */ for (remote = 0; remote < NR_CPUS; remote++) { @@ -296,7 +323,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) goto out; } - BUG_ON(!cpu_has_mipsmt); + BUG_ON(!cpu_has_mipsmt && !cpu_has_vp); /* Boot a VPE on this core */ mips_cps_boot_vpes(core_cfg, vpe_id); -- cgit v1.2.3 From bff3d472b82300274cac16007d76a70d67c7a643 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 25 Mar 2016 00:41:58 +0100 Subject: MIPS: : Reformat to 80 columns. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 631aa10fdebe..59b46feb37b1 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -309,8 +309,8 @@ enum cpu_type_enum { CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K, CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350, CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC, - CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, CPU_M5150, - CPU_I6400, + CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, + CPU_M5150, CPU_I6400, /* * MIPS64 class processors -- cgit v1.2.3 From 5cd0d5beef2bf34e3ec850aa75637e73fd8f5f82 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:26:37 +0000 Subject: MIPS: Add P6600 PRID & cpu_type_enum values Define the processor ID for the P6600 core and add a value to the enum cpu_type_enum for the core. [ralf@linux-mips.org: Fix merge conflict.] Signed-off-by: Paul Burton Cc: Joshua Kinard Cc: Leonid Yegoshin Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12342/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 59b46feb37b1..7773b8e0de1e 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -118,6 +118,7 @@ #define PRID_IMP_INTERAPTIV_MP 0xa100 #define PRID_IMP_PROAPTIV_UP 0xa200 #define PRID_IMP_PROAPTIV_MP 0xa300 +#define PRID_IMP_P6600 0xa400 #define PRID_IMP_M5150 0xa700 #define PRID_IMP_P5600 0xa800 #define PRID_IMP_I6400 0xa900 @@ -310,7 +311,7 @@ enum cpu_type_enum { CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350, CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC, CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, - CPU_M5150, CPU_I6400, + CPU_M5150, CPU_I6400, CPU_P6600, /* * MIPS64 class processors -- cgit v1.2.3 From 1091bfa20b94ba14a3c8a3eaf3a5b9d3df975da2 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 03:26:38 +0000 Subject: MIPS: Add P6600 cases to CPU switch statements Add cases supporting the P6600 CPU to various switch statements in core MIPS kernel code that define behaviour dependent upon the CPU. Signed-off-by: Paul Burton Cc: Maciej W. Rozycki Cc: Peter Zijlstra Cc: Joshua Kinard Cc: Andrzej Hajda Cc: Leonid Yegoshin Cc: Paul Gortmaker Cc: James Hogan Cc: Arnaldo Carvalho de Melo Cc: Ingo Molnar Cc: Petri Gynther Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12343/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-type.h | 1 + arch/mips/kernel/cpu-probe.c | 1 + arch/mips/kernel/perf_event_mipsxx.c | 6 ++++++ arch/mips/kernel/spram.c | 1 + arch/mips/kernel/traps.c | 1 + arch/mips/mm/c-r4k.c | 1 + arch/mips/mm/sc-mips.c | 1 + 7 files changed, 12 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h index abee2bfd10dc..2cb0979b5dc5 100644 --- a/arch/mips/include/asm/cpu-type.h +++ b/arch/mips/include/asm/cpu-type.h @@ -79,6 +79,7 @@ static inline int __pure __get_cpu_type(const int cpu_type) #ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6 case CPU_I6400: + case CPU_P6600: #endif #ifdef CONFIG_SYS_HAS_CPU_R3000 diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index e0cfa3b85bca..388503867657 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -539,6 +539,7 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable) switch (c->cputype) { case CPU_PROAPTIV: case CPU_P5600: + case CPU_P6600: /* proAptiv & related cores use Config6 to enable the FTLB */ config = read_c0_config6(); /* Clear the old probability value */ diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 9bc1191b1ab0..656769c166fc 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -1556,6 +1556,7 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config) #endif break; case CPU_P5600: + case CPU_P6600: case CPU_I6400: /* 8-bit event numbers */ raw_id = config & 0x1ff; @@ -1718,6 +1719,11 @@ init_hw_perf_events(void) mipspmu.general_event_map = &mipsxxcore_event_map2; mipspmu.cache_event_map = &mipsxxcore_cache_map2; break; + case CPU_P6600: + mipspmu.name = "mips/P6600"; + mipspmu.general_event_map = &mipsxxcore_event_map2; + mipspmu.cache_event_map = &mipsxxcore_cache_map2; + break; case CPU_I6400: mipspmu.name = "mips/I6400"; mipspmu.general_event_map = &mipsxxcore_event_map2; diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c index 8489c88f9932..d6e6cf75114d 100644 --- a/arch/mips/kernel/spram.c +++ b/arch/mips/kernel/spram.c @@ -210,6 +210,7 @@ void spram_config(void) case CPU_P5600: case CPU_QEMU_GENERIC: case CPU_I6400: + case CPU_P6600: config0 = read_c0_config(); /* FIXME: addresses are Malta specific */ if (config0 & (1<<24)) { diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index bd4893feffa6..4358f025b752 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1644,6 +1644,7 @@ static inline void parity_protection_init(void) case CPU_P5600: case CPU_QEMU_GENERIC: case CPU_I6400: + case CPU_P6600: { #define ERRCTL_PE 0x80000000 #define ERRCTL_L2P 0x00800000 diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 69e7e5873af3..729a7d48ceee 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1285,6 +1285,7 @@ static void probe_pcache(void) case CPU_M5150: case CPU_QEMU_GENERIC: case CPU_I6400: + case CPU_P6600: if (!(read_c0_config7() & MIPS_CONF7_IAR) && (c->icache.waysize > PAGE_SIZE)) c->icache.flags |= MIPS_CACHE_ALIASES; diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index 91dec32c77b7..286a4d5a1884 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -141,6 +141,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c) case CPU_P5600: case CPU_BMIPS5000: case CPU_QEMU_GENERIC: + case CPU_P6600: if (config2 & (1 << 12)) return 0; } -- cgit v1.2.3 From df8b1a5ee9f7f5fbb5e8f0df9537c648481019ea Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 16:17:28 +0000 Subject: MIPS: Add M6250 PRID & cpu_type_enum values Define the processor ID for the M6250 CPU and add a value to the enum cpu_type_enum for the core. [ralf@linux-mips.org: Fix merge conflict.] Signed-off-by: Paul Burton Cc: Joshua Kinard Cc: Leonid Yegoshin Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12373/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 7773b8e0de1e..a7a91857950c 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -122,6 +122,7 @@ #define PRID_IMP_M5150 0xa700 #define PRID_IMP_P5600 0xa800 #define PRID_IMP_I6400 0xa900 +#define PRID_IMP_M6250 0xab00 /* * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE @@ -311,7 +312,7 @@ enum cpu_type_enum { CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350, CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC, CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, - CPU_M5150, CPU_I6400, CPU_P6600, + CPU_M5150, CPU_I6400, CPU_P6600, CPU_M6250, /* * MIPS64 class processors -- cgit v1.2.3 From 1dbf6a81c845a748e46b4bcaf25d958038624ad8 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 3 Feb 2016 16:17:29 +0000 Subject: MIPS: Add M6250 cases to CPU switch statements Add casses supporting the M6250 CPU to various switch statements in the core MIPS kernel code that define behaviour dependent upon the CPU. Signed-off-by: Paul Burton Cc: Joshua Kinard Cc: Leonid Yegoshin Cc: Paul Gortmaker Cc: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12374/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-type.h | 4 ++++ arch/mips/mm/c-r4k.c | 1 + 2 files changed, 5 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h index 2cb0979b5dc5..fbe1881f28fc 100644 --- a/arch/mips/include/asm/cpu-type.h +++ b/arch/mips/include/asm/cpu-type.h @@ -77,6 +77,10 @@ static inline int __pure __get_cpu_type(const int cpu_type) */ #endif +#ifdef CONFIG_SYS_HAS_CPU_MIPS32_R6 + case CPU_M6250: +#endif + #ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6 case CPU_I6400: case CPU_P6600: diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 729a7d48ceee..e64d595fdcf2 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1286,6 +1286,7 @@ static void probe_pcache(void) case CPU_QEMU_GENERIC: case CPU_I6400: case CPU_P6600: + case CPU_M6250: if (!(read_c0_config7() & MIPS_CONF7_IAR) && (c->icache.waysize > PAGE_SIZE)) c->icache.flags |= MIPS_CACHE_ALIASES; -- cgit v1.2.3 From ad8319ea4647c897c837643a611714a83d8f6a0f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 4 Feb 2016 13:05:04 +0000 Subject: MIPS: Support R_MIPS_PC{21,26} rela-style relocs MIPS64 code uses rela-style relocs, and MIPS64r6 modules may include the new R_MIPS_PC21 & R_MIPS_PC26 relocations. We thus need to support these relocations in order to load MIPS64r6 kernel modules. They are similar to the existing R_MIPS_PC16 relocation but applying to a wider field. Implement support for them by genericising the existing R_MIPS_PC16 implementation such that it can be used for different field widths, and calling it for all 3 reloc types. Signed-off-by: Paul Burton Cc: Maciej W. Rozycki Cc: Kees Cook Cc: James Hogan Cc: Alex Smith Cc: Steven J. Hill Cc: Andrew Morton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12434/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 5 +++++ arch/mips/kernel/module-rela.c | 48 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index e090fc388e02..1bcbadb445fb 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -110,6 +110,11 @@ */ #define R_MIPS_CALLHI16 30 #define R_MIPS_CALLLO16 31 +/* + * Introduced for MIPSr6. + */ +#define R_MIPS_PC21_S2 60 +#define R_MIPS_PC26_S2 61 /* * This range is reserved for vendor specific relocations. */ diff --git a/arch/mips/kernel/module-rela.c b/arch/mips/kernel/module-rela.c index 0570676b10e2..b3611426b128 100644 --- a/arch/mips/kernel/module-rela.c +++ b/arch/mips/kernel/module-rela.c @@ -16,6 +16,7 @@ * Copyright (C) 2001 Rusty Russell. * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2005 Thiemo Seufer + * Copyright (C) 2015 Imagination Technologies Ltd. */ #include @@ -65,6 +66,48 @@ static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v) return 0; } +static int apply_r_mips_pc_rela(struct module *me, u32 *location, Elf_Addr v, + unsigned bits) +{ + unsigned long mask = GENMASK(bits - 1, 0); + unsigned long se_bits; + long offset; + + if (v % 4) { + pr_err("module %s: dangerous R_MIPS_PC%u RELA relocation\n", + me->name, bits); + return -ENOEXEC; + } + + offset = ((long)v - (long)location) >> 2; + + /* check the sign bit onwards are identical - ie. we didn't overflow */ + se_bits = (offset & BIT(bits - 1)) ? ~0ul : 0; + if ((offset & ~mask) != (se_bits & ~mask)) { + pr_err("module %s: relocation overflow\n", me->name); + return -ENOEXEC; + } + + *location = (*location & ~mask) | (offset & mask); + + return 0; +} + +static int apply_r_mips_pc16_rela(struct module *me, u32 *location, Elf_Addr v) +{ + return apply_r_mips_pc_rela(me, location, v, 16); +} + +static int apply_r_mips_pc21_rela(struct module *me, u32 *location, Elf_Addr v) +{ + return apply_r_mips_pc_rela(me, location, v, 21); +} + +static int apply_r_mips_pc26_rela(struct module *me, u32 *location, Elf_Addr v) +{ + return apply_r_mips_pc_rela(me, location, v, 26); +} + static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v) { *(Elf_Addr *)location = v; @@ -97,9 +140,12 @@ static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, [R_MIPS_26] = apply_r_mips_26_rela, [R_MIPS_HI16] = apply_r_mips_hi16_rela, [R_MIPS_LO16] = apply_r_mips_lo16_rela, + [R_MIPS_PC16] = apply_r_mips_pc16_rela, [R_MIPS_64] = apply_r_mips_64_rela, [R_MIPS_HIGHER] = apply_r_mips_higher_rela, - [R_MIPS_HIGHEST] = apply_r_mips_highest_rela + [R_MIPS_HIGHEST] = apply_r_mips_highest_rela, + [R_MIPS_PC21_S2] = apply_r_mips_pc21_rela, + [R_MIPS_PC26_S2] = apply_r_mips_pc26_rela, }; int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, -- cgit v1.2.3 From 04cc89d120f94131de89a6e20da27016db4782ce Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 27 Mar 2016 00:07:14 +0100 Subject: MIPS: Make flush_thread Avoids function calls to an empty function. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/processor.h | 4 ++++ arch/mips/kernel/process.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 041153f5cf93..cfa15bad43af 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -355,6 +355,10 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); */ extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp); +static inline void flush_thread(void) +{ +} + unsigned long get_wchan(struct task_struct *p); #define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \ diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 3f5aa3bc191e..f57891616357 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -77,10 +77,6 @@ void exit_thread(void) { } -void flush_thread(void) -{ -} - int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { /* -- cgit v1.2.3 From 738a3f79027bef44b0bd3bfcc325f53b518749d4 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 9 Feb 2016 12:55:50 -0800 Subject: MIPS: BMIPS: Add early CPU initialization code Port the stblinux-3.3 code to perform a bunch of CPU-specific initialization, make it compatible with run-time detection of the CPU, and unroll the brcmstb-specific macros: BDEV_RB(), BDEV_UNSET. The "pref 30" disabling is done as a quirk. This is a preliminary change to allow the use of the "rotr" instruction gated by cpu_has_rixi. Signed-off-by: Florian Fainelli Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jon.fraser@broadcom.com Cc: pgynther@google.com Cc: paul.burton@imgtec.com Cc: ddaney.cavm@gmail.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12504/ Signed-off-by: Ralf Baechle --- arch/mips/bmips/setup.c | 1 + arch/mips/include/asm/bmips.h | 1 + arch/mips/kernel/smp-bmips.c | 87 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c index 35535284b39e..b764995343c1 100644 --- a/arch/mips/bmips/setup.c +++ b/arch/mips/bmips/setup.c @@ -111,6 +111,7 @@ static const struct bmips_quirk bmips_quirk_list[] = { void __init prom_init(void) { + bmips_cpu_setup(); register_bmips_smp_ops(); } diff --git a/arch/mips/include/asm/bmips.h b/arch/mips/include/asm/bmips.h index 6d25ad33ec78..a92aee7b977a 100644 --- a/arch/mips/include/asm/bmips.h +++ b/arch/mips/include/asm/bmips.h @@ -88,6 +88,7 @@ extern unsigned long bmips_tp1_irqs; extern void bmips_ebase_setup(void); extern asmlinkage void plat_wired_tlb_setup(void); +extern void bmips_cpu_setup(void); static inline unsigned long bmips_read_zscm_reg(unsigned int offset) { diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 6d11788b4502..e02addc0307f 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -566,3 +566,90 @@ asmlinkage void __weak plat_wired_tlb_setup(void) * once the wired entries are present. */ } + +void __init bmips_cpu_setup(void) +{ + void __iomem __maybe_unused *cbr = BMIPS_GET_CBR(); + u32 __maybe_unused cfg; + + switch (current_cpu_type()) { + case CPU_BMIPS3300: + /* Set BIU to async mode */ + set_c0_brcm_bus_pll(BIT(22)); + __sync(); + + /* put the BIU back in sync mode */ + clear_c0_brcm_bus_pll(BIT(22)); + + /* clear BHTD to enable branch history table */ + clear_c0_brcm_reset(BIT(16)); + + /* Flush and enable RAC */ + cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG); + __raw_writel(cfg | 0x100, BMIPS_RAC_CONFIG); + __raw_readl(cbr + BMIPS_RAC_CONFIG); + + cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG); + __raw_writel(cfg | 0xf, BMIPS_RAC_CONFIG); + __raw_readl(cbr + BMIPS_RAC_CONFIG); + + cfg = __raw_readl(cbr + BMIPS_RAC_ADDRESS_RANGE); + __raw_writel(cfg | 0x0fff0000, cbr + BMIPS_RAC_ADDRESS_RANGE); + __raw_readl(cbr + BMIPS_RAC_ADDRESS_RANGE); + break; + + case CPU_BMIPS4380: + /* CBG workaround for early BMIPS4380 CPUs */ + switch (read_c0_prid()) { + case 0x2a040: + case 0x2a042: + case 0x2a044: + case 0x2a060: + cfg = __raw_readl(cbr + BMIPS_L2_CONFIG); + __raw_writel(cfg & ~0x07000000, cbr + BMIPS_L2_CONFIG); + __raw_readl(cbr + BMIPS_L2_CONFIG); + } + + /* clear BHTD to enable branch history table */ + clear_c0_brcm_config_0(BIT(21)); + + /* XI/ROTR enable */ + set_c0_brcm_config_0(BIT(23)); + set_c0_brcm_cmt_ctrl(BIT(15)); + break; + + case CPU_BMIPS5000: + /* enable RDHWR, BRDHWR */ + set_c0_brcm_config(BIT(17) | BIT(21)); + + /* Disable JTB */ + __asm__ __volatile__( + " .set noreorder\n" + " li $8, 0x5a455048\n" + " .word 0x4088b00f\n" /* mtc0 t0, $22, 15 */ + " .word 0x4008b008\n" /* mfc0 t0, $22, 8 */ + " li $9, 0x00008000\n" + " or $8, $8, $9\n" + " .word 0x4088b008\n" /* mtc0 t0, $22, 8 */ + " sync\n" + " li $8, 0x0\n" + " .word 0x4088b00f\n" /* mtc0 t0, $22, 15 */ + " .set reorder\n" + : : : "$8", "$9"); + + /* XI enable */ + set_c0_brcm_config(BIT(27)); + + /* enable MIPS32R2 ROR instruction for XI TLB handlers */ + __asm__ __volatile__( + " li $8, 0x5a455048\n" + " .word 0x4088b00f\n" /* mtc0 $8, $22, 15 */ + " nop; nop; nop\n" + " .word 0x4008b008\n" /* mfc0 $8, $22, 8 */ + " lui $9, 0x0100\n" + " or $8, $9\n" + " .word 0x4088b008\n" /* mtc0 $8, $22, 8 */ + : : : "$8", "$9"); + break; + } +} -- cgit v1.2.3 From c0291f7c735941f2cf5c8d5264c2cc2402b77869 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 13 May 2015 16:17:13 +0100 Subject: MIPS: cpu: Alter MIPS_CPU_* definitions to fill gap The MIPS_CPU_* definitions accidentally missed bits 27..30 when MIPS_CPU_EVA was added, and further definitions have continued from there. Shift all the definitions since MIPS_CPU_EVA right by 4 so there are no gaps. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/10044/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index a7a91857950c..a9a5aa75a863 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -379,14 +379,14 @@ enum cpu_type_enum { #define MIPS_CPU_MICROMIPS 0x01000000ull /* CPU has microMIPS capability */ #define MIPS_CPU_TLBINV 0x02000000ull /* CPU supports TLBINV/F */ #define MIPS_CPU_SEGMENTS 0x04000000ull /* CPU supports Segmentation Control registers */ -#define MIPS_CPU_EVA 0x80000000ull /* CPU supports Enhanced Virtual Addressing */ -#define MIPS_CPU_HTW 0x100000000ull /* CPU support Hardware Page Table Walker */ -#define MIPS_CPU_RIXIEX 0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */ -#define MIPS_CPU_MAAR 0x400000000ull /* MAAR(I) registers are present */ -#define MIPS_CPU_FRE 0x800000000ull /* FRE & UFE bits implemented */ -#define MIPS_CPU_RW_LLB 0x1000000000ull /* LLADDR/LLB writes are allowed */ -#define MIPS_CPU_XPA 0x2000000000ull /* CPU supports Extended Physical Addressing */ -#define MIPS_CPU_CDMM 0x4000000000ull /* CPU has Common Device Memory Map */ +#define MIPS_CPU_EVA 0x08000000ull /* CPU supports Enhanced Virtual Addressing */ +#define MIPS_CPU_HTW 0x10000000ull /* CPU support Hardware Page Table Walker */ +#define MIPS_CPU_RIXIEX 0x20000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */ +#define MIPS_CPU_MAAR 0x40000000ull /* MAAR(I) registers are present */ +#define MIPS_CPU_FRE 0x80000000ull /* FRE & UFE bits implemented */ +#define MIPS_CPU_RW_LLB 0x100000000ull /* LLADDR/LLB writes are allowed */ +#define MIPS_CPU_XPA 0x200000000ull /* CPU supports Extended Physical Addressing */ +#define MIPS_CPU_CDMM 0x400000000ull /* CPU has Common Device Memory Map */ #define MIPS_CPU_BP_GHIST 0x8000000000ull /* R12K+ Branch Prediction Global History */ #define MIPS_CPU_SP 0x10000000000ull /* Small (1KB) page support */ #define MIPS_CPU_FTLB 0x20000000000ull /* CPU has Fixed-page-size TLB */ -- cgit v1.2.3 From 0c94fa33b4de55a0dcb60519ba04a0fd49da124d Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 13 May 2015 16:17:14 +0100 Subject: MIPS: cpu: Convert MIPS_CPU_* defs to (1ull << x) The MIPS_CPU_* definitions have now filled the first 32-bits, and are getting longer since they're written in hex without zero padding. Adding my 8 extra MIPS_CPU_* definitions which I haven't upstreamed yet this is getting increasingly ugly as the comments get shifted progressively to the right. Its also error prone, and I've seen this cause mistakes on 3 separate occasions now, not helped by it being a conflict hotspot. Convert all the MIPS_CPU_* definitions to the form (1ull << x). Humans are better at incrementing than shifting. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/10045/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu.h | 89 ++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 41 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index a9a5aa75a863..cc579a6c8016 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -349,50 +349,57 @@ enum cpu_type_enum { MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2 | \ MIPS_CPU_ISA_M64R6) +/* + * Private version of BIT_ULL() to escape include file recursion hell. + * We soon will have to switch to another mechanism that will work with + * more than 64 bits anyway. + */ +#define MBIT_ULL(bit) (1ULL << (bit)) + /* * CPU Option encodings */ -#define MIPS_CPU_TLB 0x00000001ull /* CPU has TLB */ -#define MIPS_CPU_4KEX 0x00000002ull /* "R4K" exception model */ -#define MIPS_CPU_3K_CACHE 0x00000004ull /* R3000-style caches */ -#define MIPS_CPU_4K_CACHE 0x00000008ull /* R4000-style caches */ -#define MIPS_CPU_TX39_CACHE 0x00000010ull /* TX3900-style caches */ -#define MIPS_CPU_FPU 0x00000020ull /* CPU has FPU */ -#define MIPS_CPU_32FPR 0x00000040ull /* 32 dbl. prec. FP registers */ -#define MIPS_CPU_COUNTER 0x00000080ull /* Cycle count/compare */ -#define MIPS_CPU_WATCH 0x00000100ull /* watchpoint registers */ -#define MIPS_CPU_DIVEC 0x00000200ull /* dedicated interrupt vector */ -#define MIPS_CPU_VCE 0x00000400ull /* virt. coherence conflict possible */ -#define MIPS_CPU_CACHE_CDEX_P 0x00000800ull /* Create_Dirty_Exclusive CACHE op */ -#define MIPS_CPU_CACHE_CDEX_S 0x00001000ull /* ... same for seconary cache ... */ -#define MIPS_CPU_MCHECK 0x00002000ull /* Machine check exception */ -#define MIPS_CPU_EJTAG 0x00004000ull /* EJTAG exception */ -#define MIPS_CPU_NOFPUEX 0x00008000ull /* no FPU exception */ -#define MIPS_CPU_LLSC 0x00010000ull /* CPU has ll/sc instructions */ -#define MIPS_CPU_INCLUSIVE_CACHES 0x00020000ull /* P-cache subset enforced */ -#define MIPS_CPU_PREFETCH 0x00040000ull /* CPU has usable prefetch */ -#define MIPS_CPU_VINT 0x00080000ull /* CPU supports MIPSR2 vectored interrupts */ -#define MIPS_CPU_VEIC 0x00100000ull /* CPU supports MIPSR2 external interrupt controller mode */ -#define MIPS_CPU_ULRI 0x00200000ull /* CPU has ULRI feature */ -#define MIPS_CPU_PCI 0x00400000ull /* CPU has Perf Ctr Int indicator */ -#define MIPS_CPU_RIXI 0x00800000ull /* CPU has TLB Read/eXec Inhibit */ -#define MIPS_CPU_MICROMIPS 0x01000000ull /* CPU has microMIPS capability */ -#define MIPS_CPU_TLBINV 0x02000000ull /* CPU supports TLBINV/F */ -#define MIPS_CPU_SEGMENTS 0x04000000ull /* CPU supports Segmentation Control registers */ -#define MIPS_CPU_EVA 0x08000000ull /* CPU supports Enhanced Virtual Addressing */ -#define MIPS_CPU_HTW 0x10000000ull /* CPU support Hardware Page Table Walker */ -#define MIPS_CPU_RIXIEX 0x20000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */ -#define MIPS_CPU_MAAR 0x40000000ull /* MAAR(I) registers are present */ -#define MIPS_CPU_FRE 0x80000000ull /* FRE & UFE bits implemented */ -#define MIPS_CPU_RW_LLB 0x100000000ull /* LLADDR/LLB writes are allowed */ -#define MIPS_CPU_XPA 0x200000000ull /* CPU supports Extended Physical Addressing */ -#define MIPS_CPU_CDMM 0x400000000ull /* CPU has Common Device Memory Map */ -#define MIPS_CPU_BP_GHIST 0x8000000000ull /* R12K+ Branch Prediction Global History */ -#define MIPS_CPU_SP 0x10000000000ull /* Small (1KB) page support */ -#define MIPS_CPU_FTLB 0x20000000000ull /* CPU has Fixed-page-size TLB */ -#define MIPS_CPU_NAN_LEGACY 0x40000000000ull /* Legacy NaN implemented */ -#define MIPS_CPU_NAN_2008 0x80000000000ull /* 2008 NaN implemented */ -#define MIPS_CPU_VP 0x100000000000ull /* MIPSr6 Virtual Processors (multi-threading) */ +#define MIPS_CPU_TLB MBIT_ULL( 0) /* CPU has TLB */ +#define MIPS_CPU_4KEX MBIT_ULL( 1) /* "R4K" exception model */ +#define MIPS_CPU_3K_CACHE MBIT_ULL( 2) /* R3000-style caches */ +#define MIPS_CPU_4K_CACHE MBIT_ULL( 3) /* R4000-style caches */ +#define MIPS_CPU_TX39_CACHE MBIT_ULL( 4) /* TX3900-style caches */ +#define MIPS_CPU_FPU MBIT_ULL( 5) /* CPU has FPU */ +#define MIPS_CPU_32FPR MBIT_ULL( 6) /* 32 dbl. prec. FP registers */ +#define MIPS_CPU_COUNTER MBIT_ULL( 7) /* Cycle count/compare */ +#define MIPS_CPU_WATCH MBIT_ULL( 8) /* watchpoint registers */ +#define MIPS_CPU_DIVEC MBIT_ULL( 9) /* dedicated interrupt vector */ +#define MIPS_CPU_VCE MBIT_ULL(10) /* virt. coherence conflict possible */ +#define MIPS_CPU_CACHE_CDEX_P MBIT_ULL(11) /* Create_Dirty_Exclusive CACHE op */ +#define MIPS_CPU_CACHE_CDEX_S MBIT_ULL(12) /* ... same for seconary cache ... */ +#define MIPS_CPU_MCHECK MBIT_ULL(13) /* Machine check exception */ +#define MIPS_CPU_EJTAG MBIT_ULL(14) /* EJTAG exception */ +#define MIPS_CPU_NOFPUEX MBIT_ULL(15) /* no FPU exception */ +#define MIPS_CPU_LLSC MBIT_ULL(16) /* CPU has ll/sc instructions */ +#define MIPS_CPU_INCLUSIVE_CACHES MBIT_ULL(17) /* P-cache subset enforced */ +#define MIPS_CPU_PREFETCH MBIT_ULL(18) /* CPU has usable prefetch */ +#define MIPS_CPU_VINT MBIT_ULL(19) /* CPU supports MIPSR2 vectored interrupts */ +#define MIPS_CPU_VEIC MBIT_ULL(20) /* CPU supports MIPSR2 external interrupt controller mode */ +#define MIPS_CPU_ULRI MBIT_ULL(21) /* CPU has ULRI feature */ +#define MIPS_CPU_PCI MBIT_ULL(22) /* CPU has Perf Ctr Int indicator */ +#define MIPS_CPU_RIXI MBIT_ULL(23) /* CPU has TLB Read/eXec Inhibit */ +#define MIPS_CPU_MICROMIPS MBIT_ULL(24) /* CPU has microMIPS capability */ +#define MIPS_CPU_TLBINV MBIT_ULL(25) /* CPU supports TLBINV/F */ +#define MIPS_CPU_SEGMENTS MBIT_ULL(26) /* CPU supports Segmentation Control registers */ +#define MIPS_CPU_EVA MBIT_ULL(27) /* CPU supports Enhanced Virtual Addressing */ +#define MIPS_CPU_HTW MBIT_ULL(28) /* CPU support Hardware Page Table Walker */ +#define MIPS_CPU_RIXIEX MBIT_ULL(29) /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */ +#define MIPS_CPU_MAAR MBIT_ULL(30) /* MAAR(I) registers are present */ +#define MIPS_CPU_FRE MBIT_ULL(31) /* FRE & UFE bits implemented */ +#define MIPS_CPU_RW_LLB MBIT_ULL(32) /* LLADDR/LLB writes are allowed */ +#define MIPS_CPU_XPA MBIT_ULL(33) /* CPU supports Extended Physical Addressing */ +#define MIPS_CPU_CDMM MBIT_ULL(34) /* CPU has Common Device Memory Map */ +#define MIPS_CPU_BP_GHIST MBIT_ULL(35) /* R12K+ Branch Prediction Global History */ +#define MIPS_CPU_SP MBIT_ULL(36) /* Small (1KB) page support */ +#define MIPS_CPU_FTLB MBIT_ULL(37) /* CPU has Fixed-page-size TLB */ +#define MIPS_CPU_NAN_LEGACY MBIT_ULL(38) /* Legacy NaN implemented */ +#define MIPS_CPU_NAN_2008 MBIT_ULL(39) /* 2008 NaN implemented */ +#define MIPS_CPU_VP MBIT_ULL(40) /* MIPSr6 Virtual Processors (multi-threading) */ /* * CPU ASE encodings -- cgit v1.2.3 From b5a6455cde3d63466ac31bacdb42afcf30932f75 Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Kakakhel Date: Tue, 29 Mar 2016 15:50:25 +0100 Subject: MIPS: Detect DSP v3 support DSPv3 is supported on all MIPSr6 systems which indicate support for DSPv2. This doesn't require any changes to the kernel's handling of DSP resources. The patch is to detect support and indicate it in /proc/cpuinfo DSP v3 introduces a new instruction BPOSGE32C Signed-off-by: Zubair Lutfullah Kakakhel Reviewed-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12918/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 4 ++++ arch/mips/include/asm/cpu.h | 1 + arch/mips/kernel/cpu-probe.c | 5 ++++- arch/mips/kernel/proc.c | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 57cdc5be9545..6ff0504d090d 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -307,6 +307,10 @@ #define cpu_has_dsp2 (cpu_data[0].ases & MIPS_ASE_DSP2P) #endif +#ifndef cpu_has_dsp3 +#define cpu_has_dsp3 (cpu_data[0].ases & MIPS_ASE_DSP3) +#endif + #ifndef cpu_has_mipsmt #define cpu_has_mipsmt (cpu_data[0].ases & MIPS_ASE_MIPSMT) #endif diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index cc579a6c8016..9127a583d1f1 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -413,5 +413,6 @@ enum cpu_type_enum { #define MIPS_ASE_DSP2P 0x00000040 /* Signal Processing ASE Rev 2 */ #define MIPS_ASE_VZ 0x00000080 /* Virtualization ASE */ #define MIPS_ASE_MSA 0x00000100 /* MIPS SIMD Architecture */ +#define MIPS_ASE_DSP3 0x00000200 /* Signal Processing ASE Rev 3*/ #endif /* _ASM_CPU_H */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 785e9a11c721..d0818aab00e2 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -680,8 +680,11 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->options |= MIPS_CPU_RIXI; if (config3 & MIPS_CONF3_DSP) c->ases |= MIPS_ASE_DSP; - if (config3 & MIPS_CONF3_DSP2P) + if (config3 & MIPS_CONF3_DSP2P) { c->ases |= MIPS_ASE_DSP2P; + if (cpu_has_mips_r6) + c->ases |= MIPS_ASE_DSP3; + } if (config3 & MIPS_CONF3_VINT) c->options |= MIPS_CPU_VINT; if (config3 & MIPS_CONF3_VEIC) diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 298b2b773d12..97dc01b03631 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -114,6 +114,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (cpu_has_smartmips) seq_printf(m, "%s", " smartmips"); if (cpu_has_dsp) seq_printf(m, "%s", " dsp"); if (cpu_has_dsp2) seq_printf(m, "%s", " dsp2"); + if (cpu_has_dsp3) seq_printf(m, "%s", " dsp3"); if (cpu_has_mipsmt) seq_printf(m, "%s", " mt"); if (cpu_has_mmips) seq_printf(m, "%s", " micromips"); if (cpu_has_vz) seq_printf(m, "%s", " vz"); -- cgit v1.2.3 From 763fee97e743acb4f6e683a00fd2e7f5ad2484fb Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 1 Mar 2016 02:37:56 +0000 Subject: MIPS: Flush dcache for flush_kernel_dcache_page The flush_kernel_dcache_page function was previously essentially a nop. This is incorrect for MIPS, where if a page has been modified & either it aliases or it's executable & the icache doesn't fill from dcache then the content needs to be written back from dcache to the next level of the cache hierarchy (which is shared with the icache). Implement this by simply calling flush_dcache_page, treating this kmapped cache flush function (flush_kernel_dcache_page) exactly the same as its non-kmapped counterpart (flush_dcache_page). Signed-off-by: Paul Burton Cc: Lars Persson Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12719/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cacheflush.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h index 723229f4cf27..7e9f46818eba 100644 --- a/arch/mips/include/asm/cacheflush.h +++ b/arch/mips/include/asm/cacheflush.h @@ -132,6 +132,7 @@ static inline void kunmap_noncoherent(void) static inline void flush_kernel_dcache_page(struct page *page) { BUG_ON(cpu_has_dc_aliases && PageHighMem(page)); + flush_dcache_page(page); } /* -- cgit v1.2.3 From 37d22a0d798b5c938b277d32cfd86dc231381342 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 1 Mar 2016 02:37:59 +0000 Subject: MIPS: Sync icache & dcache in set_pte_at It's possible for pages to become visible prior to update_mmu_cache running if a thread within the same address space preempts the current thread or runs simultaneously on another CPU. That is, the following scenario is possible: CPU0 CPU1 write to page flush_dcache_page flush_icache_page set_pte_at map page update_mmu_cache If CPU1 maps the page in between CPU0's set_pte_at, which marks it valid & visible, and update_mmu_cache where the dcache flush occurs then CPU1s icache will fill from stale data (unless it fills from the dcache, in which case all is good, but most MIPS CPUs don't have this property). Commit 4d46a67a3eb8 ("MIPS: Fix race condition in lazy cache flushing.") attempted to fix that by performing the dcache flush in flush_icache_page such that it occurs before the set_pte_at call makes the page visible. However it has the problem that not all code that writes to pages exposed to userland call flush_icache_page. There are many callers of set_pte_at under mm/ and only 2 of them do call flush_icache_page. Thus the race window between a page becoming visible & being coherent between the icache & dcache remains open in some cases. To illustrate some of the cases, a WARN was added to __update_cache with this patch applied that triggered in cases where a page about to be flushed from the dcache was not the last page provided to flush_icache_page. That is, backtraces were obtained for cases in which the race window is left open without this patch. The 2 standout examples follow. When forking a process: [ 15.271842] [<80417630>] __update_cache+0xcc/0x188 [ 15.277274] [<80530394>] copy_page_range+0x56c/0x6ac [ 15.282861] [<8042936c>] copy_process.part.54+0xd40/0x17ac [ 15.289028] [<80429f80>] do_fork+0xe4/0x420 [ 15.293747] [<80413808>] handle_sys+0x128/0x14c When exec'ing an ELF binary: [ 14.445964] [<80417630>] __update_cache+0xcc/0x188 [ 14.451369] [<80538d88>] move_page_tables+0x414/0x498 [ 14.457075] [<8055d848>] setup_arg_pages+0x220/0x318 [ 14.462685] [<805b0f38>] load_elf_binary+0x530/0x12a0 [ 14.468374] [<8055ec3c>] search_binary_handler+0xbc/0x214 [ 14.474444] [<8055f6c0>] do_execveat_common+0x43c/0x67c [ 14.480324] [<8055f938>] do_execve+0x38/0x44 [ 14.485137] [<80413808>] handle_sys+0x128/0x14c These code paths write into a page, call flush_dcache_page then call set_pte_at without flush_icache_page inbetween. The end result is that the icache can become corrupted & userland processes may execute unexpected or invalid code, typically resulting in a reserved instruction exception, a trap or a segfault. Fix this race condition fully by performing any cache maintenance required to keep the icache & dcache in sync in set_pte_at, before the page is made valid. This has the added bonus of ensuring the cache maintenance always happens in one location, rather than being duplicated in flush_icache_page & update_mmu_cache. It also matches the way other architectures solve the same problem (see arm, ia64 & powerpc). Signed-off-by: Paul Burton Reported-by: Ionela Voinescu Cc: Lars Persson Fixes: 4d46a67a3eb8 ("MIPS: Fix race condition in lazy cache flushing.") Cc: Steven J. Hill Cc: David Daney Cc: Huacai Chen Cc: Aneesh Kumar K.V Cc: Andrew Morton Cc: Jerome Marchand Cc: Kirill A. Shutemov Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: stable # v4.1+ Patchwork: https://patchwork.linux-mips.org/patch/12722/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cacheflush.h | 6 ------ arch/mips/include/asm/pgtable.h | 26 +++++++++++++++++++++----- arch/mips/mm/cache.c | 19 +++---------------- 3 files changed, 24 insertions(+), 27 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h index 7e9f46818eba..34ed22ec6c33 100644 --- a/arch/mips/include/asm/cacheflush.h +++ b/arch/mips/include/asm/cacheflush.h @@ -51,7 +51,6 @@ extern void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); extern void __flush_dcache_page(struct page *page); -extern void __flush_icache_page(struct vm_area_struct *vma, struct page *page); #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 static inline void flush_dcache_page(struct page *page) @@ -77,11 +76,6 @@ static inline void flush_anon_page(struct vm_area_struct *vma, static inline void flush_icache_page(struct vm_area_struct *vma, struct page *page) { - if (!cpu_has_ic_fills_f_dc && (vma->vm_flags & VM_EXEC) && - Page_dcache_dirty(page)) { - __flush_icache_page(vma, page); - ClearPageDcacheDirty(page); - } } extern void (*flush_icache_range)(unsigned long start, unsigned long end); diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 75c29cff0f99..45de57651619 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -127,10 +127,14 @@ do { \ } \ } while(0) +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pteval); + #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) #define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) +#define pte_no_exec(pte) ((pte).pte_low & _PAGE_NO_EXEC) static inline void set_pte(pte_t *ptep, pte_t pte) { @@ -148,7 +152,6 @@ static inline void set_pte(pte_t *ptep, pte_t pte) buddy->pte_high |= _PAGE_GLOBAL; } } -#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -166,6 +169,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt #define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL)) #define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) +#define pte_no_exec(pte) (pte_val(pte) & _PAGE_NO_EXEC) /* * Certain architectures need to do special things when pte's @@ -230,7 +234,6 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) } #endif } -#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -246,6 +249,22 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt } #endif +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pteval) +{ + extern void __update_cache(unsigned long address, pte_t pte); + + if (!pte_present(pteval)) + goto cache_sync_done; + + if (pte_present(*ptep) && (pte_pfn(*ptep) == pte_pfn(pteval))) + goto cache_sync_done; + + __update_cache(addr, pteval); +cache_sync_done: + set_pte(ptep, pteval); +} + /* * (pmds are folded into puds so this doesn't get actually called, * but the define is needed for a generic inline function.) @@ -442,15 +461,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) extern void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte); -extern void __update_cache(struct vm_area_struct *vma, unsigned long address, - pte_t pte); static inline void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) { pte_t pte = *ptep; __update_tlb(vma, address, pte); - __update_cache(vma, address, pte); } static inline void update_mmu_cache_pmd(struct vm_area_struct *vma, diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 8befa55234df..bf04c6c479a4 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -125,30 +125,17 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr) EXPORT_SYMBOL(__flush_anon_page); -void __flush_icache_page(struct vm_area_struct *vma, struct page *page) -{ - unsigned long addr; - - if (PageHighMem(page)) - return; - - addr = (unsigned long) page_address(page); - flush_data_cache_page(addr); -} -EXPORT_SYMBOL_GPL(__flush_icache_page); - -void __update_cache(struct vm_area_struct *vma, unsigned long address, - pte_t pte) +void __update_cache(unsigned long address, pte_t pte) { struct page *page; unsigned long pfn, addr; - int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc; + int exec = !pte_no_exec(pte) && !cpu_has_ic_fills_f_dc; pfn = pte_pfn(pte); if (unlikely(!pfn_valid(pfn))) return; page = pfn_to_page(pfn); - if (page_mapping(page) && Page_dcache_dirty(page)) { + if (Page_dcache_dirty(page)) { if (PageHighMem(page)) addr = (unsigned long)kmap_atomic(page); else -- cgit v1.2.3 From 3d2ca73af4eb4a33ae021e37b5f395ac5631cb3f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 27 Jan 2016 14:23:36 -0800 Subject: MIPS: Use generic clkdev.h header The generic header file is equivalent to the MIPS one, so use the generic one instead. Signed-off-by: Stephen Boyd Cc: linux-kernel@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12261/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/Kbuild | 1 + arch/mips/include/asm/clkdev.h | 27 --------------------------- 2 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 arch/mips/include/asm/clkdev.h (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild index c7fe4d01e79c..9740066cc631 100644 --- a/arch/mips/include/asm/Kbuild +++ b/arch/mips/include/asm/Kbuild @@ -1,5 +1,6 @@ # MIPS headers generic-(CONFIG_GENERIC_CSUM) += checksum.h +generic-y += clkdev.h generic-y += cputime.h generic-y += current.h generic-y += dma-contiguous.h diff --git a/arch/mips/include/asm/clkdev.h b/arch/mips/include/asm/clkdev.h deleted file mode 100644 index 1b3ad7b09dc1..000000000000 --- a/arch/mips/include/asm/clkdev.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * based on arch/arm/include/asm/clkdev.h - * - * Copyright (C) 2008 Russell King. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Helper for the clk API to assist looking up a struct clk. - */ -#ifndef __ASM_CLKDEV_H -#define __ASM_CLKDEV_H - -#include - -#ifndef CONFIG_COMMON_CLK -#define __clk_get(clk) ({ 1; }) -#define __clk_put(clk) do { } while (0) -#endif - -static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) -{ - return kzalloc(size, GFP_KERNEL); -} - -#endif -- cgit v1.2.3 From b1b4fad5cc678442c8184a7b91b6cfb0b8b461a5 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Tue, 29 Mar 2016 09:35:33 +0100 Subject: MIPS: seccomp: Support compat with both O32 and N32 Previously the seccomp would only support strict mode on O32 userland programs when the kernel had support for both O32 and N32 ABIs. Remove kludge and support both ABIs. With this patch in place, the seccomp_bpf self test now passes global.mode_strict_support with N32 userland. Suggested-by: Paul Burton Signed-off-by: Matt Redfearn Acked-by: Kees Cook Cc: Andrew Morton Cc: IMG-MIPSLinuxKerneldevelopers@imgtec.com Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12917/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/seccomp.h | 47 +++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/seccomp.h b/arch/mips/include/asm/seccomp.h index 1d8a2e2c75c1..684fb3a12ed3 100644 --- a/arch/mips/include/asm/seccomp.h +++ b/arch/mips/include/asm/seccomp.h @@ -2,27 +2,32 @@ #include -/* - * Kludge alert: - * - * The generic seccomp code currently allows only a single compat ABI. Until - * this is fixed we priorize O32 as the compat ABI over N32. - */ -#ifdef CONFIG_MIPS32_O32 - -#define __NR_seccomp_read_32 4003 -#define __NR_seccomp_write_32 4004 -#define __NR_seccomp_exit_32 4001 -#define __NR_seccomp_sigreturn_32 4193 /* rt_sigreturn */ - -#elif defined(CONFIG_MIPS32_N32) - -#define __NR_seccomp_read_32 6000 -#define __NR_seccomp_write_32 6001 -#define __NR_seccomp_exit_32 6058 -#define __NR_seccomp_sigreturn_32 6211 /* rt_sigreturn */ - -#endif /* CONFIG_MIPS32_O32 */ +#ifdef CONFIG_COMPAT +static inline const int *get_compat_mode1_syscalls(void) +{ + static const int syscalls_O32[] = { + __NR_O32_Linux + 3, __NR_O32_Linux + 4, + __NR_O32_Linux + 1, __NR_O32_Linux + 193, + 0, /* null terminated */ + }; + static const int syscalls_N32[] = { + __NR_N32_Linux + 0, __NR_N32_Linux + 1, + __NR_N32_Linux + 58, __NR_N32_Linux + 211, + 0, /* null terminated */ + }; + + if (config_enabled(CONFIG_MIPS32_O32) && test_thread_flag(TIF_32BIT_REGS)) + return syscalls_O32; + + if (config_enabled(CONFIG_MIPS32_N32)) + return syscalls_N32; + + BUG(); +} + +#define get_compat_mode1_syscalls get_compat_mode1_syscalls + +#endif /* CONFIG_COMPAT */ #include -- cgit v1.2.3 From 5e7c1c918a4433c5dd1844d99f5648e17425fa16 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 31 Mar 2016 10:05:40 +0100 Subject: MIPS: Introduce plat_get_fdt a platform API to retrieve the FDT Early access to the kernel command line requires early access to the FDT for platforms which pass the command line within the device tree. There was no common way to retrieve the location of the FDT without incurring side effects, such as plat_mem_setup which, on Malta at least, initializes a bunch of other stuff. This patch adds plat_get_ftd() for IMG platforms. Signed-off-by: Matt Redfearn Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12988/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/bootinfo.h | 18 ++++++++++++++++++ arch/mips/mti-malta/malta-setup.c | 7 ++++++- arch/mips/mti-sead3/sead3-setup.c | 5 +++++ 3 files changed, 29 insertions(+), 1 deletion(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h index b603804caac5..9f67033961a6 100644 --- a/arch/mips/include/asm/bootinfo.h +++ b/arch/mips/include/asm/bootinfo.h @@ -144,4 +144,22 @@ static inline void plat_swiotlb_setup(void) {} #endif /* CONFIG_SWIOTLB */ +#ifdef CONFIG_USE_OF +/** + * plat_get_fdt() - Return a pointer to the platform's device tree blob + * + * This function provides a platform independent API to get a pointer to the + * flattened device tree blob. The interface between bootloader and kernel + * is not consistent across platforms so it is necessary to provide this + * API such that common startup code can locate the FDT. + * + * This is used by the KASLR code to get command line arguments and random + * seed from the device tree. Any platform wishing to use KASLR should + * provide this API and select SYS_SUPPORTS_RELOCATABLE. + * + * Return: Pointer to the flattened device tree blob. + */ +extern void *plat_get_fdt(void); +#endif /* CONFIG_USE_OF */ + #endif /* _ASM_BOOTINFO_H */ diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c index 4740c82fb97a..33d5ff5069e5 100644 --- a/arch/mips/mti-malta/malta-setup.c +++ b/arch/mips/mti-malta/malta-setup.c @@ -248,10 +248,15 @@ static void __init bonito_quirks_setup(void) #endif } +void __init *plat_get_fdt(void) +{ + return (void *)__dtb_start; +} + void __init plat_mem_setup(void) { unsigned int i; - void *fdt = __dtb_start; + void *fdt = plat_get_fdt(); fdt = malta_dt_shim(fdt); __dt_setup_arch(fdt); diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c index e43f4801a245..9f2f9b2b23ce 100644 --- a/arch/mips/mti-sead3/sead3-setup.c +++ b/arch/mips/mti-sead3/sead3-setup.c @@ -83,6 +83,11 @@ static void __init parse_memsize_param(void) } } +void __init *plat_get_fdt(void) +{ + return (void *)__dtb_start; +} + void __init plat_mem_setup(void) { /* allow command line/bootloader env to override memory size in DT */ -- cgit v1.2.3 From 9ec88b60cb481a6862dc98a78400a6945d9675ba Mon Sep 17 00:00:00 2001 From: Kelvin Cheung Date: Wed, 6 Apr 2016 20:34:54 +0800 Subject: MIPS: Loongson1B: Some updates/fixes for LS1B - Add DMA device - Add NAND device - Add GPIO device - Add LED device - Update the defconfig and rename it to loongson1b_defconfig - Fix ioremap size - Other minor fixes Signed-off-by: Kelvin Cheung Cc: Michael Turquette Cc: Stephen Boyd Cc: Rafael J. Wysocki Cc: Viresh Kumar Cc: Vinod Koul Cc: Dan Williams Cc: Linus Walleij Cc: Alexandre Courbot Cc: Boris Brezillon Cc: Richard Weinberger Cc: David Woodhouse Cc: Brian Norris Cc: linux-mips@linux-mips.org Cc: linux-clk@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: dmaengine@vger.kernel.org Cc: linux-gpio@vger.kernel.org Cc: linux-mtd@lists.infradead.org Patchwork: https://patchwork.linux-mips.org/patch/13033/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 + arch/mips/configs/loongson1b_defconfig | 125 ++++++++++++++++++++++ arch/mips/configs/ls1b_defconfig | 110 ------------------- arch/mips/include/asm/mach-loongson32/cpufreq.h | 1 - arch/mips/include/asm/mach-loongson32/dma.h | 25 +++++ arch/mips/include/asm/mach-loongson32/irq.h | 1 - arch/mips/include/asm/mach-loongson32/loongson1.h | 4 +- arch/mips/include/asm/mach-loongson32/nand.h | 30 ++++++ arch/mips/include/asm/mach-loongson32/platform.h | 14 ++- arch/mips/include/asm/mach-loongson32/regs-clk.h | 24 ++--- arch/mips/include/asm/mach-loongson32/regs-mux.h | 84 +++++++-------- arch/mips/include/asm/mach-loongson32/regs-pwm.h | 12 +-- arch/mips/loongson32/common/platform.c | 105 +++++++++++++++++- arch/mips/loongson32/common/reset.c | 13 +-- arch/mips/loongson32/common/time.c | 27 ++--- arch/mips/loongson32/ls1b/board.c | 67 +++++++++++- 16 files changed, 440 insertions(+), 204 deletions(-) create mode 100644 arch/mips/configs/loongson1b_defconfig delete mode 100644 arch/mips/configs/ls1b_defconfig create mode 100644 arch/mips/include/asm/mach-loongson32/dma.h create mode 100644 arch/mips/include/asm/mach-loongson32/nand.h (limited to 'arch/mips/include/asm') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 79a1c6991c08..fbd63ff8eba4 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1387,6 +1387,8 @@ config CPU_LOONGSON1B bool "Loongson 1B" depends on SYS_HAS_CPU_LOONGSON1B select CPU_LOONGSON1 + select ARCH_WANT_OPTIONAL_GPIOLIB + select LEDS_GPIO_REGISTER help The Loongson 1B is a 32-bit SoC, which implements the MIPS32 release 2 instruction set. diff --git a/arch/mips/configs/loongson1b_defconfig b/arch/mips/configs/loongson1b_defconfig new file mode 100644 index 000000000000..c442f27685f4 --- /dev/null +++ b/arch/mips/configs/loongson1b_defconfig @@ -0,0 +1,125 @@ +CONFIG_MACH_LOONGSON32=y +CONFIG_PREEMPT=y +# CONFIG_SECCOMP is not set +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_KERNEL_XZ=y +CONFIG_SYSVIPC=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_NAMESPACES=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EXPERT=y +CONFIG_PERF_EVENTS=y +# CONFIG_COMPAT_BRK is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_LOONGSON1=y +CONFIG_MTD_UBI=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_SCSI=m +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=m +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +CONFIG_STMMAC_ETH=y +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_LEGACY_PTY_COUNT=8 +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_GPIOLIB=y +CONFIG_GPIO_LOONGSON1=y +# CONFIG_HWMON is not set +# CONFIG_VGA_CONSOLE is not set +CONFIG_HID_GENERIC=m +CONFIG_USB_HID=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_STORAGE=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_LOONGSON1=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_DNOTIFY is not set +CONFIG_VFAT_FS=y +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_ATIME_SUPPORT=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_ISO8859_1=m +CONFIG_DYNAMIC_DEBUG=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_DEBUG_FS=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_FTRACE is not set +# CONFIG_EARLY_PRINTK is not set +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_HW is not set diff --git a/arch/mips/configs/ls1b_defconfig b/arch/mips/configs/ls1b_defconfig deleted file mode 100644 index 1b2cc1fb26a1..000000000000 --- a/arch/mips/configs/ls1b_defconfig +++ /dev/null @@ -1,110 +0,0 @@ -CONFIG_MACH_LOONGSON32=y -CONFIG_PREEMPT=y -# CONFIG_SECCOMP is not set -CONFIG_EXPERIMENTAL=y -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=16 -CONFIG_NAMESPACES=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_RD_BZIP2=y -CONFIG_RD_LZMA=y -CONFIG_EXPERT=y -CONFIG_PERF_EVENTS=y -# CONFIG_COMPAT_BRK is not set -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODVERSIONS=y -# CONFIG_LBDAF is not set -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -# CONFIG_SUSPEND is not set -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_SYN_COOKIES=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -# CONFIG_WIRELESS is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -# CONFIG_STANDALONE is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_SCSI=m -# CONFIG_SCSI_PROC_FS is not set -CONFIG_BLK_DEV_SD=m -# CONFIG_SCSI_LOWLEVEL is not set -CONFIG_NETDEVICES=y -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_CHELSIO is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SMSC is not set -CONFIG_STMMAC_ETH=y -CONFIG_STMMAC_DA=y -# CONFIG_NET_VENDOR_WIZNET is not set -# CONFIG_WLAN is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO is not set -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_LEGACY_PTY_COUNT=8 -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_HW_RANDOM is not set -# CONFIG_HWMON is not set -# CONFIG_VGA_CONSOLE is not set -CONFIG_USB_HID=m -CONFIG_HID_GENERIC=m -CONFIG_USB=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_HCD_PLATFORM=y -# CONFIG_USB_EHCI_TT_NEWSCHED is not set -CONFIG_USB_STORAGE=m -CONFIG_USB_SERIAL=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_LOONGSON1=y -# CONFIG_IOMMU_SUPPORT is not set -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -# CONFIG_DNOTIFY is not set -CONFIG_VFAT_FS=y -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_ISO8859_1=m -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_SCHED_DEBUG is not set -# CONFIG_DEBUG_PREEMPT is not set -# CONFIG_FTRACE is not set -# CONFIG_EARLY_PRINTK is not set diff --git a/arch/mips/include/asm/mach-loongson32/cpufreq.h b/arch/mips/include/asm/mach-loongson32/cpufreq.h index 6843fa1a608d..2f1ecb081223 100644 --- a/arch/mips/include/asm/mach-loongson32/cpufreq.h +++ b/arch/mips/include/asm/mach-loongson32/cpufreq.h @@ -9,7 +9,6 @@ * option) any later version. */ - #ifndef __ASM_MACH_LOONGSON32_CPUFREQ_H #define __ASM_MACH_LOONGSON32_CPUFREQ_H diff --git a/arch/mips/include/asm/mach-loongson32/dma.h b/arch/mips/include/asm/mach-loongson32/dma.h new file mode 100644 index 000000000000..ad1dec743ccc --- /dev/null +++ b/arch/mips/include/asm/mach-loongson32/dma.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 Zhang, Keguang + * + * Loongson 1 NAND platform support. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __ASM_MACH_LOONGSON32_DMA_H +#define __ASM_MACH_LOONGSON32_DMA_H + +#define LS1X_DMA_CHANNEL0 0 +#define LS1X_DMA_CHANNEL1 1 +#define LS1X_DMA_CHANNEL2 2 + +struct plat_ls1x_dma { + int nr_channels; +}; + +extern struct plat_ls1x_dma ls1b_dma_pdata; + +#endif /* __ASM_MACH_LOONGSON32_DMA_H */ diff --git a/arch/mips/include/asm/mach-loongson32/irq.h b/arch/mips/include/asm/mach-loongson32/irq.h index 0d35b994e8d2..c1c744197de4 100644 --- a/arch/mips/include/asm/mach-loongson32/irq.h +++ b/arch/mips/include/asm/mach-loongson32/irq.h @@ -9,7 +9,6 @@ * option) any later version. */ - #ifndef __ASM_MACH_LOONGSON32_IRQ_H #define __ASM_MACH_LOONGSON32_IRQ_H diff --git a/arch/mips/include/asm/mach-loongson32/loongson1.h b/arch/mips/include/asm/mach-loongson32/loongson1.h index 12aa129aad80..978f6df8970a 100644 --- a/arch/mips/include/asm/mach-loongson32/loongson1.h +++ b/arch/mips/include/asm/mach-loongson32/loongson1.h @@ -9,7 +9,6 @@ * option) any later version. */ - #ifndef __ASM_MACH_LOONGSON32_LOONGSON1_H #define __ASM_MACH_LOONGSON32_LOONGSON1_H @@ -18,6 +17,9 @@ /* Loongson 1 Register Bases */ #define LS1X_MUX_BASE 0x1fd00420 #define LS1X_INTC_BASE 0x1fd01040 +#define LS1X_GPIO0_BASE 0x1fd010c0 +#define LS1X_GPIO1_BASE 0x1fd010c4 +#define LS1X_DMAC_BASE 0x1fd01160 #define LS1X_EHCI_BASE 0x1fe00000 #define LS1X_OHCI_BASE 0x1fe08000 #define LS1X_GMAC0_BASE 0x1fe10000 diff --git a/arch/mips/include/asm/mach-loongson32/nand.h b/arch/mips/include/asm/mach-loongson32/nand.h new file mode 100644 index 000000000000..e274912e9de1 --- /dev/null +++ b/arch/mips/include/asm/mach-loongson32/nand.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 Zhang, Keguang + * + * Loongson 1 NAND platform support. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __ASM_MACH_LOONGSON32_NAND_H +#define __ASM_MACH_LOONGSON32_NAND_H + +#include +#include + +struct plat_ls1x_nand { + struct mtd_partition *parts; + unsigned int nr_parts; + + int hold_cycle; + int wait_cycle; +}; + +extern struct plat_ls1x_nand ls1b_nand_pdata; + +bool ls1x_dma_filter_fn(struct dma_chan *chan, void *param); + +#endif /* __ASM_MACH_LOONGSON32_NAND_H */ diff --git a/arch/mips/include/asm/mach-loongson32/platform.h b/arch/mips/include/asm/mach-loongson32/platform.h index c32f03f3f72c..672531aa9bef 100644 --- a/arch/mips/include/asm/mach-loongson32/platform.h +++ b/arch/mips/include/asm/mach-loongson32/platform.h @@ -7,20 +7,28 @@ * option) any later version. */ - #ifndef __ASM_MACH_LOONGSON32_PLATFORM_H #define __ASM_MACH_LOONGSON32_PLATFORM_H #include +#include +#include + extern struct platform_device ls1x_uart_pdev; extern struct platform_device ls1x_cpufreq_pdev; +extern struct platform_device ls1x_dma_pdev; extern struct platform_device ls1x_eth0_pdev; extern struct platform_device ls1x_eth1_pdev; extern struct platform_device ls1x_ehci_pdev; +extern struct platform_device ls1x_gpio0_pdev; +extern struct platform_device ls1x_gpio1_pdev; +extern struct platform_device ls1x_nand_pdev; extern struct platform_device ls1x_rtc_pdev; -extern void __init ls1x_clk_init(void); -extern void __init ls1x_serial_setup(struct platform_device *pdev); +void __init ls1x_clk_init(void); +void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata); +void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata); +void __init ls1x_serial_set_uartclk(struct platform_device *pdev); #endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */ diff --git a/arch/mips/include/asm/mach-loongson32/regs-clk.h b/arch/mips/include/asm/mach-loongson32/regs-clk.h index 1f5a715ac841..4d56fc38f0c4 100644 --- a/arch/mips/include/asm/mach-loongson32/regs-clk.h +++ b/arch/mips/include/asm/mach-loongson32/regs-clk.h @@ -19,18 +19,18 @@ #define LS1X_CLK_PLL_DIV LS1X_CLK_REG(0x4) /* Clock PLL Divisor Register Bits */ -#define DIV_DC_EN (0x1 << 31) -#define DIV_DC_RST (0x1 << 30) -#define DIV_CPU_EN (0x1 << 25) -#define DIV_CPU_RST (0x1 << 24) -#define DIV_DDR_EN (0x1 << 19) -#define DIV_DDR_RST (0x1 << 18) -#define RST_DC_EN (0x1 << 5) -#define RST_DC (0x1 << 4) -#define RST_DDR_EN (0x1 << 3) -#define RST_DDR (0x1 << 2) -#define RST_CPU_EN (0x1 << 1) -#define RST_CPU 0x1 +#define DIV_DC_EN BIT(31) +#define DIV_DC_RST BIT(30) +#define DIV_CPU_EN BIT(25) +#define DIV_CPU_RST BIT(24) +#define DIV_DDR_EN BIT(19) +#define DIV_DDR_RST BIT(18) +#define RST_DC_EN BIT(5) +#define RST_DC BIT(4) +#define RST_DDR_EN BIT(3) +#define RST_DDR BIT(2) +#define RST_CPU_EN BIT(1) +#define RST_CPU BIT(0) #define DIV_DC_SHIFT 26 #define DIV_CPU_SHIFT 20 diff --git a/arch/mips/include/asm/mach-loongson32/regs-mux.h b/arch/mips/include/asm/mach-loongson32/regs-mux.h index 8302d92f2da2..7c394f93cb9e 100644 --- a/arch/mips/include/asm/mach-loongson32/regs-mux.h +++ b/arch/mips/include/asm/mach-loongson32/regs-mux.h @@ -19,49 +19,49 @@ #define LS1X_MUX_CTRL1 LS1X_MUX_REG(0x4) /* MUX CTRL0 Register Bits */ -#define UART0_USE_PWM23 (0x1 << 28) -#define UART0_USE_PWM01 (0x1 << 27) -#define UART1_USE_LCD0_5_6_11 (0x1 << 26) -#define I2C2_USE_CAN1 (0x1 << 25) -#define I2C1_USE_CAN0 (0x1 << 24) -#define NAND3_USE_UART5 (0x1 << 23) -#define NAND3_USE_UART4 (0x1 << 22) -#define NAND3_USE_UART1_DAT (0x1 << 21) -#define NAND3_USE_UART1_CTS (0x1 << 20) -#define NAND3_USE_PWM23 (0x1 << 19) -#define NAND3_USE_PWM01 (0x1 << 18) -#define NAND2_USE_UART5 (0x1 << 17) -#define NAND2_USE_UART4 (0x1 << 16) -#define NAND2_USE_UART1_DAT (0x1 << 15) -#define NAND2_USE_UART1_CTS (0x1 << 14) -#define NAND2_USE_PWM23 (0x1 << 13) -#define NAND2_USE_PWM01 (0x1 << 12) -#define NAND1_USE_UART5 (0x1 << 11) -#define NAND1_USE_UART4 (0x1 << 10) -#define NAND1_USE_UART1_DAT (0x1 << 9) -#define NAND1_USE_UART1_CTS (0x1 << 8) -#define NAND1_USE_PWM23 (0x1 << 7) -#define NAND1_USE_PWM01 (0x1 << 6) -#define GMAC1_USE_UART1 (0x1 << 4) -#define GMAC1_USE_UART0 (0x1 << 3) -#define LCD_USE_UART0_DAT (0x1 << 2) -#define LCD_USE_UART15 (0x1 << 1) -#define LCD_USE_UART0 0x1 +#define UART0_USE_PWM23 BIT(28) +#define UART0_USE_PWM01 BIT(27) +#define UART1_USE_LCD0_5_6_11 BIT(26) +#define I2C2_USE_CAN1 BIT(25) +#define I2C1_USE_CAN0 BIT(24) +#define NAND3_USE_UART5 BIT(23) +#define NAND3_USE_UART4 BIT(22) +#define NAND3_USE_UART1_DAT BIT(21) +#define NAND3_USE_UART1_CTS BIT(20) +#define NAND3_USE_PWM23 BIT(19) +#define NAND3_USE_PWM01 BIT(18) +#define NAND2_USE_UART5 BIT(17) +#define NAND2_USE_UART4 BIT(16) +#define NAND2_USE_UART1_DAT BIT(15) +#define NAND2_USE_UART1_CTS BIT(14) +#define NAND2_USE_PWM23 BIT(13) +#define NAND2_USE_PWM01 BIT(12) +#define NAND1_USE_UART5 BIT(11) +#define NAND1_USE_UART4 BIT(10) +#define NAND1_USE_UART1_DAT BIT(9) +#define NAND1_USE_UART1_CTS BIT(8) +#define NAND1_USE_PWM23 BIT(7) +#define NAND1_USE_PWM01 BIT(6) +#define GMAC1_USE_UART1 BIT(4) +#define GMAC1_USE_UART0 BIT(3) +#define LCD_USE_UART0_DAT BIT(2) +#define LCD_USE_UART15 BIT(1) +#define LCD_USE_UART0 BIT(0) /* MUX CTRL1 Register Bits */ -#define USB_RESET (0x1 << 31) -#define SPI1_CS_USE_PWM01 (0x1 << 24) -#define SPI1_USE_CAN (0x1 << 23) -#define DISABLE_DDR_CONFSPACE (0x1 << 20) -#define DDR32TO16EN (0x1 << 16) -#define GMAC1_SHUT (0x1 << 13) -#define GMAC0_SHUT (0x1 << 12) -#define USB_SHUT (0x1 << 11) -#define UART1_3_USE_CAN1 (0x1 << 5) -#define UART1_2_USE_CAN0 (0x1 << 4) -#define GMAC1_USE_TXCLK (0x1 << 3) -#define GMAC0_USE_TXCLK (0x1 << 2) -#define GMAC1_USE_PWM23 (0x1 << 1) -#define GMAC0_USE_PWM01 0x1 +#define USB_RESET BIT(31) +#define SPI1_CS_USE_PWM01 BIT(24) +#define SPI1_USE_CAN BIT(23) +#define DISABLE_DDR_CONFSPACE BIT(20) +#define DDR32TO16EN BIT(16) +#define GMAC1_SHUT BIT(13) +#define GMAC0_SHUT BIT(12) +#define USB_SHUT BIT(11) +#define UART1_3_USE_CAN1 BIT(5) +#define UART1_2_USE_CAN0 BIT(4) +#define GMAC1_USE_TXCLK BIT(3) +#define GMAC0_USE_TXCLK BIT(2) +#define GMAC1_USE_PWM23 BIT(1) +#define GMAC0_USE_PWM01 BIT(0) #endif /* __ASM_MACH_LOONGSON32_REGS_MUX_H */ diff --git a/arch/mips/include/asm/mach-loongson32/regs-pwm.h b/arch/mips/include/asm/mach-loongson32/regs-pwm.h index 69f174ed13a4..4119600ce79a 100644 --- a/arch/mips/include/asm/mach-loongson32/regs-pwm.h +++ b/arch/mips/include/asm/mach-loongson32/regs-pwm.h @@ -19,11 +19,11 @@ #define PWM_CTRL 0xc /* PWM Control Register Bits */ -#define CNT_RST (0x1 << 7) -#define INT_SR (0x1 << 6) -#define INT_EN (0x1 << 5) -#define PWM_SINGLE (0x1 << 4) -#define PWM_OE (0x1 << 3) -#define CNT_EN 0x1 +#define CNT_RST BIT(7) +#define INT_SR BIT(6) +#define INT_EN BIT(5) +#define PWM_SINGLE BIT(4) +#define PWM_OE BIT(3) +#define CNT_EN BIT(0) #endif /* __ASM_MACH_LOONGSON32_REGS_PWM_H */ diff --git a/arch/mips/loongson32/common/platform.c b/arch/mips/loongson32/common/platform.c index ddf1d4cbf31e..f2c714d8fb60 100644 --- a/arch/mips/loongson32/common/platform.c +++ b/arch/mips/loongson32/common/platform.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Zhang, Keguang + * Copyright (c) 2011-2016 Zhang, Keguang * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -10,14 +10,17 @@ #include #include #include +#include +#include #include #include #include #include -#include -#include #include +#include +#include +#include /* 8250/16550 compatible UART */ #define LS1X_UART(_id) \ @@ -45,7 +48,7 @@ struct platform_device ls1x_uart_pdev = { }, }; -void __init ls1x_serial_setup(struct platform_device *pdev) +void __init ls1x_serial_set_uartclk(struct platform_device *pdev) { struct clk *clk; struct plat_serial8250_port *p; @@ -77,6 +80,42 @@ struct platform_device ls1x_cpufreq_pdev = { }, }; +/* DMA */ +static struct resource ls1x_dma_resources[] = { + [0] = { + .start = LS1X_DMAC_BASE, + .end = LS1X_DMAC_BASE + SZ_4 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = LS1X_DMA0_IRQ, + .end = LS1X_DMA0_IRQ, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = LS1X_DMA1_IRQ, + .end = LS1X_DMA1_IRQ, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = LS1X_DMA2_IRQ, + .end = LS1X_DMA2_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device ls1x_dma_pdev = { + .name = "ls1x-dma", + .id = -1, + .num_resources = ARRAY_SIZE(ls1x_dma_resources), + .resource = ls1x_dma_resources, +}; + +void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata) +{ + ls1x_dma_pdev.dev.platform_data = pdata; +} + /* Synopsys Ethernet GMAC */ static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = { .phy_mask = 0, @@ -198,6 +237,64 @@ struct platform_device ls1x_eth1_pdev = { }, }; +/* GPIO */ +static struct resource ls1x_gpio0_resources[] = { + [0] = { + .start = LS1X_GPIO0_BASE, + .end = LS1X_GPIO0_BASE + SZ_4 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device ls1x_gpio0_pdev = { + .name = "ls1x-gpio", + .id = 0, + .num_resources = ARRAY_SIZE(ls1x_gpio0_resources), + .resource = ls1x_gpio0_resources, +}; + +static struct resource ls1x_gpio1_resources[] = { + [0] = { + .start = LS1X_GPIO1_BASE, + .end = LS1X_GPIO1_BASE + SZ_4 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device ls1x_gpio1_pdev = { + .name = "ls1x-gpio", + .id = 1, + .num_resources = ARRAY_SIZE(ls1x_gpio1_resources), + .resource = ls1x_gpio1_resources, +}; + +/* NAND Flash */ +static struct resource ls1x_nand_resources[] = { + [0] = { + .start = LS1X_NAND_BASE, + .end = LS1X_NAND_BASE + SZ_32 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + /* DMA channel 0 is dedicated to NAND */ + .start = LS1X_DMA_CHANNEL0, + .end = LS1X_DMA_CHANNEL0, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device ls1x_nand_pdev = { + .name = "ls1x-nand", + .id = -1, + .num_resources = ARRAY_SIZE(ls1x_nand_resources), + .resource = ls1x_nand_resources, +}; + +void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata) +{ + ls1x_nand_pdev.dev.platform_data = pdata; +} + /* USB EHCI */ static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32); diff --git a/arch/mips/loongson32/common/reset.c b/arch/mips/loongson32/common/reset.c index c41e4ca56ab4..8a1d9cc5a134 100644 --- a/arch/mips/loongson32/common/reset.c +++ b/arch/mips/loongson32/common/reset.c @@ -9,12 +9,13 @@ #include #include +#include #include #include #include -static void __iomem *wdt_base; +static void __iomem *wdt_reg_base; static void ls1x_halt(void) { @@ -26,9 +27,9 @@ static void ls1x_halt(void) static void ls1x_restart(char *command) { - __raw_writel(0x1, wdt_base + WDT_EN); - __raw_writel(0x1, wdt_base + WDT_TIMER); - __raw_writel(0x1, wdt_base + WDT_SET); + __raw_writel(0x1, wdt_reg_base + WDT_EN); + __raw_writel(0x1, wdt_reg_base + WDT_TIMER); + __raw_writel(0x1, wdt_reg_base + WDT_SET); ls1x_halt(); } @@ -40,8 +41,8 @@ static void ls1x_power_off(void) static int __init ls1x_reboot_setup(void) { - wdt_base = ioremap_nocache(LS1X_WDT_BASE, 0x0f); - if (!wdt_base) + wdt_reg_base = ioremap_nocache(LS1X_WDT_BASE, (SZ_4 + SZ_8)); + if (!wdt_reg_base) panic("Failed to remap watchdog registers"); _machine_restart = ls1x_restart; diff --git a/arch/mips/loongson32/common/time.c b/arch/mips/loongson32/common/time.c index 0996b025eeef..ff224f0020e5 100644 --- a/arch/mips/loongson32/common/time.c +++ b/arch/mips/loongson32/common/time.c @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -35,25 +36,25 @@ DEFINE_RAW_SPINLOCK(ls1x_timer_lock); -static void __iomem *timer_base; +static void __iomem *timer_reg_base; static uint32_t ls1x_jiffies_per_tick; static inline void ls1x_pwmtimer_set_period(uint32_t period) { - __raw_writel(period, timer_base + PWM_HRC); - __raw_writel(period, timer_base + PWM_LRC); + __raw_writel(period, timer_reg_base + PWM_HRC); + __raw_writel(period, timer_reg_base + PWM_LRC); } static inline void ls1x_pwmtimer_restart(void) { - __raw_writel(0x0, timer_base + PWM_CNT); - __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL); + __raw_writel(0x0, timer_reg_base + PWM_CNT); + __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); } void __init ls1x_pwmtimer_init(void) { - timer_base = ioremap(LS1X_TIMER_BASE, 0xf); - if (!timer_base) + timer_reg_base = ioremap_nocache(LS1X_TIMER_BASE, SZ_16); + if (!timer_reg_base) panic("Failed to remap timer registers"); ls1x_jiffies_per_tick = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ); @@ -86,7 +87,7 @@ static cycle_t ls1x_clocksource_read(struct clocksource *cs) */ jifs = jiffies; /* read the count */ - count = __raw_readl(timer_base + PWM_CNT); + count = __raw_readl(timer_reg_base + PWM_CNT); /* * It's possible for count to appear to go the wrong way for this @@ -131,7 +132,7 @@ static int ls1x_clockevent_set_state_periodic(struct clock_event_device *cd) raw_spin_lock(&ls1x_timer_lock); ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick); ls1x_pwmtimer_restart(); - __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL); + __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); raw_spin_unlock(&ls1x_timer_lock); return 0; @@ -140,7 +141,7 @@ static int ls1x_clockevent_set_state_periodic(struct clock_event_device *cd) static int ls1x_clockevent_tick_resume(struct clock_event_device *cd) { raw_spin_lock(&ls1x_timer_lock); - __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL); + __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); raw_spin_unlock(&ls1x_timer_lock); return 0; @@ -149,8 +150,8 @@ static int ls1x_clockevent_tick_resume(struct clock_event_device *cd) static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *cd) { raw_spin_lock(&ls1x_timer_lock); - __raw_writel(__raw_readl(timer_base + PWM_CTRL) & ~CNT_EN, - timer_base + PWM_CTRL); + __raw_writel(__raw_readl(timer_reg_base + PWM_CTRL) & ~CNT_EN, + timer_reg_base + PWM_CTRL); raw_spin_unlock(&ls1x_timer_lock); return 0; @@ -220,7 +221,7 @@ void __init plat_time_init(void) #ifdef CONFIG_CEVT_CSRC_LS1X /* setup LS1X PWM timer */ - clk = clk_get(NULL, "ls1x_pwmtimer"); + clk = clk_get(NULL, "ls1x-pwmtimer"); if (IS_ERR(clk)) panic("unable to get timer clock, err=%ld", PTR_ERR(clk)); diff --git a/arch/mips/loongson32/ls1b/board.c b/arch/mips/loongson32/ls1b/board.c index 58daeea25739..38a1d404be1b 100644 --- a/arch/mips/loongson32/ls1b/board.c +++ b/arch/mips/loongson32/ls1b/board.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Zhang, Keguang + * Copyright (c) 2011-2016 Zhang, Keguang * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -7,26 +7,83 @@ * option) any later version. */ +#include +#include +#include + +#include +#include +#include #include +struct plat_ls1x_dma ls1x_dma_pdata = { + .nr_channels = 3, +}; + +static struct mtd_partition ls1x_nand_parts[] = { + { + .name = "kernel", + .offset = 0, + .size = SZ_16M, + }, + { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +struct plat_ls1x_nand ls1x_nand_pdata = { + .parts = ls1x_nand_parts, + .nr_parts = ARRAY_SIZE(ls1x_nand_parts), + .hold_cycle = 0x2, + .wait_cycle = 0xc, +}; + +static const struct gpio_led ls1x_gpio_leds[] __initconst = { + { + .name = "LED9", + .default_trigger = "heartbeat", + .gpio = 38, + .active_low = 1, + .default_state = LEDS_GPIO_DEFSTATE_OFF, + }, { + .name = "LED6", + .default_trigger = "nand-disk", + .gpio = 39, + .active_low = 1, + .default_state = LEDS_GPIO_DEFSTATE_OFF, + }, +}; + +static const struct gpio_led_platform_data ls1x_led_pdata __initconst = { + .num_leds = ARRAY_SIZE(ls1x_gpio_leds), + .leds = ls1x_gpio_leds, +}; + static struct platform_device *ls1b_platform_devices[] __initdata = { &ls1x_uart_pdev, &ls1x_cpufreq_pdev, + &ls1x_dma_pdev, &ls1x_eth0_pdev, &ls1x_eth1_pdev, &ls1x_ehci_pdev, + &ls1x_gpio0_pdev, + &ls1x_gpio1_pdev, + &ls1x_nand_pdev, &ls1x_rtc_pdev, }; static int __init ls1b_platform_init(void) { - int err; + ls1x_serial_set_uartclk(&ls1x_uart_pdev); + ls1x_dma_set_platdata(&ls1x_dma_pdata); + ls1x_nand_set_platdata(&ls1x_nand_pdata); - ls1x_serial_setup(&ls1x_uart_pdev); + gpio_led_register_device(-1, &ls1x_led_pdata); - err = platform_add_devices(ls1b_platform_devices, + return platform_add_devices(ls1b_platform_devices, ARRAY_SIZE(ls1b_platform_devices)); - return err; } arch_initcall(ls1b_platform_init); -- cgit v1.2.3 From f337967d6d87da39f6e59d90430f3bec0909edf5 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 4 Apr 2016 10:55:37 -0700 Subject: MIPS: BMIPS: Add cpu-feature-overrides.h BMIPS_GENERIC being multiplatform and intended to support BMIPS3200, BMIPS3300, BMIPS4350, BMIPS4380 and BMIPS5000-class processors, there is not much more we can put in there since they do not share the same I and D cache line sizes at all (doubled for every new generation essentially), some processors have a S-cache, some don't, some have a FPU, some don't. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13013/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h b/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h new file mode 100644 index 000000000000..fa0583e1ce0d --- /dev/null +++ b/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h @@ -0,0 +1,14 @@ +#ifndef __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H + +/* Invariants across all BMIPS processors */ +#define cpu_has_vtag_icache 0 +#define cpu_icache_snoops_remote_store 1 + +/* Processor ISA compatibility is MIPS32R1 */ +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#endif /* __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H */ -- cgit v1.2.3 From 3604b4510c17c16271b3446528807227dfb02b04 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sat, 9 Apr 2016 12:56:47 +0200 Subject: MIPS: BMIPS: Add BCM6358 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM6358 has a shared TLB which conflicts with current SMP support, so it must be disabled for now. BCM6358 uses >= 0xfffe0000 addresses for internal registers, which need to be remapped (by using a simplified version of BRCM63xx ioremap.h). However, 0xfff80000 is a better address, since it also covers BCM3368, leaving the possibility to add it in the future. Signed-off-by: Álvaro Fernández Rojas Cc: f.fainelli@gmail.com Cc: jogo@openwrt.org Cc: cernekee@gmail.com Cc: robh@kernel.org Cc: simon@fire.lp0.eu Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13040/ Signed-off-by: Ralf Baechle --- arch/mips/bmips/setup.c | 10 +++++++++ arch/mips/include/asm/mach-bmips/ioremap.h | 33 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 arch/mips/include/asm/mach-bmips/ioremap.h (limited to 'arch/mips/include/asm') diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c index b764995343c1..c63bc0af61fc 100644 --- a/arch/mips/bmips/setup.c +++ b/arch/mips/bmips/setup.c @@ -95,6 +95,15 @@ static void bcm6328_quirks(void) bcm63xx_fixup_cpu1(); } +static void bcm6358_quirks(void) +{ + /* + * BCM6358 needs special handling for its shared TLB, so + * disable SMP for now + */ + bmips_smp_enabled = 0; +} + static void bcm6368_quirks(void) { bcm63xx_fixup_cpu1(); @@ -104,6 +113,7 @@ static const struct bmips_quirk bmips_quirk_list[] = { { "brcm,bcm3384-viper", &bcm3384_viper_quirks }, { "brcm,bcm33843-viper", &bcm3384_viper_quirks }, { "brcm,bcm6328", &bcm6328_quirks }, + { "brcm,bcm6358", &bcm6358_quirks }, { "brcm,bcm6368", &bcm6368_quirks }, { "brcm,bcm63168", &bcm6368_quirks }, { }, diff --git a/arch/mips/include/asm/mach-bmips/ioremap.h b/arch/mips/include/asm/mach-bmips/ioremap.h new file mode 100644 index 000000000000..29c7a7bb7080 --- /dev/null +++ b/arch/mips/include/asm/mach-bmips/ioremap.h @@ -0,0 +1,33 @@ +#ifndef __ASM_MACH_BMIPS_IOREMAP_H +#define __ASM_MACH_BMIPS_IOREMAP_H + +#include + +static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) +{ + return phys_addr; +} + +static inline int is_bmips_internal_registers(phys_addr_t offset) +{ + if (offset >= 0xfff80000) + return 1; + + return 0; +} + +static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size, + unsigned long flags) +{ + if (is_bmips_internal_registers(offset)) + return (void __iomem *)offset; + + return NULL; +} + +static inline int plat_iounmap(const volatile void __iomem *addr) +{ + return is_bmips_internal_registers((unsigned long)addr); +} + +#endif /* __ASM_MACH_BMIPS_IOREMAP_H */ -- cgit v1.2.3 From 2e5832ab589459265e70163a7dea3abdc1429eb7 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 Nov 2015 00:48:39 +0000 Subject: MIPS: ELF: Restructure personality macros Update the ELF personality macros used for individual ABIs to make actions in the same order across all of them and match formatting too. Signed-off-by: Maciej W. Rozycki Cc: Andrew Morton Cc: Matthew Fortune Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 1bcbadb445fb..1fba19747fa9 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -305,17 +305,16 @@ extern struct mips_abi mips_abi_n32; #define SET_PERSONALITY2(ex, state) \ do { \ - if (personality(current->personality) != PER_LINUX) \ - set_personality(PER_LINUX); \ - \ clear_thread_flag(TIF_HYBRID_FPREGS); \ set_thread_flag(TIF_32BIT_FPREGS); \ \ - mips_set_personality_fp(state); \ - \ current->thread.abi = &mips_abi; \ \ + mips_set_personality_fp(state); \ mips_set_personality_nan(state); \ + \ + if (personality(current->personality) != PER_LINUX) \ + set_personality(PER_LINUX); \ } while (0) #endif /* CONFIG_32BIT */ @@ -326,6 +325,7 @@ do { \ #define __SET_PERSONALITY32_N32() \ do { \ set_thread_flag(TIF_32BIT_ADDR); \ + \ current->thread.abi = &mips_abi_n32; \ } while (0) #else @@ -341,9 +341,9 @@ do { \ clear_thread_flag(TIF_HYBRID_FPREGS); \ set_thread_flag(TIF_32BIT_FPREGS); \ \ - mips_set_personality_fp(state); \ - \ current->thread.abi = &mips_abi_32; \ + \ + mips_set_personality_fp(state); \ } while (0) #else #define __SET_PERSONALITY32_O32(ex, state) \ -- cgit v1.2.3 From e233c733786a8ca70cd12cc30aeb80e5b390ad71 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 1 Mar 2016 22:19:38 +0000 Subject: MIPS: Add and use CAUSEF_WP definition do_watch() clears bit 22 of cause without using a CAUSEF_* definition from mipsregs.h. Add a definition for this bit (CAUSEF_WP) and make use of it. Also use clear_c0_cause() instead of manual read/modify/write. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12728/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 2 ++ arch/mips/kernel/traps.c | 5 +---- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index ca251f6fea8e..c08b6f798f8f 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -390,6 +390,8 @@ #define CAUSEF_IP7 (_ULCAST_(1) << 15) #define CAUSEB_FDCI 21 #define CAUSEF_FDCI (_ULCAST_(1) << 21) +#define CAUSEB_WP 22 +#define CAUSEF_WP (_ULCAST_(1) << 22) #define CAUSEB_IV 23 #define CAUSEF_IV (_ULCAST_(1) << 23) #define CAUSEB_PCI 26 diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 4358f025b752..dcda63e65854 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1498,16 +1498,13 @@ asmlinkage void do_watch(struct pt_regs *regs) { siginfo_t info = { .si_signo = SIGTRAP, .si_code = TRAP_HWBKPT }; enum ctx_state prev_state; - u32 cause; prev_state = exception_enter(); /* * Clear WP (bit 22) bit of cause register so we don't loop * forever. */ - cause = read_c0_cause(); - cause &= ~(1 << 22); - write_c0_cause(cause); + clear_c0_cause(CAUSEF_WP); /* * If the current thread has the watch registers loaded, save -- cgit v1.2.3 From 50af501cd84b4e005fd54c351184ec89cfc940e4 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 1 Mar 2016 22:19:39 +0000 Subject: MIPS: Add and use watch register field definitions The files watch.c and ptrace.c contain various magic masks for WatchLo/WatchHi register fields. Add some definitions to mipsregs.h for these registers and make use of them in both watch.c and ptrace.c, hopefully making them more readable. Signed-off-by: James Hogan Reviewed-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12729/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 18 ++++++++++ arch/mips/kernel/ptrace.c | 7 ++-- arch/mips/kernel/watch.c | 74 ++++++++++++++++++++++------------------ 3 files changed, 63 insertions(+), 36 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index c08b6f798f8f..aea90631a301 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -648,6 +648,24 @@ /* FTLB probability bits for R6 */ #define MIPS_CONF7_FTLBP_SHIFT (18) +/* WatchLo* register definitions */ +#define MIPS_WATCHLO_IRW (_ULCAST_(0x7) << 0) + +/* WatchHi* register definitions */ +#define MIPS_WATCHHI_M (_ULCAST_(1) << 31) +#define MIPS_WATCHHI_G (_ULCAST_(1) << 30) +#define MIPS_WATCHHI_WM (_ULCAST_(0x3) << 28) +#define MIPS_WATCHHI_WM_R_RVA (_ULCAST_(0) << 28) +#define MIPS_WATCHHI_WM_R_GPA (_ULCAST_(1) << 28) +#define MIPS_WATCHHI_WM_G_GVA (_ULCAST_(2) << 28) +#define MIPS_WATCHHI_EAS (_ULCAST_(0x3) << 24) +#define MIPS_WATCHHI_ASID (_ULCAST_(0xff) << 16) +#define MIPS_WATCHHI_MASK (_ULCAST_(0x1ff) << 3) +#define MIPS_WATCHHI_I (_ULCAST_(1) << 2) +#define MIPS_WATCHHI_R (_ULCAST_(1) << 1) +#define MIPS_WATCHHI_W (_ULCAST_(1) << 0) +#define MIPS_WATCHHI_IRW (_ULCAST_(0x7) << 0) + /* MAAR bit definitions */ #define MIPS_MAAR_ADDR ((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12) #define MIPS_MAAR_ADDR_SHIFT 12 diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index a5279b2f3198..48c0534c4d15 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -210,7 +210,8 @@ int ptrace_get_watch_regs(struct task_struct *child, for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { __put_user(child->thread.watch.mips3264.watchlo[i], &addr->WATCH_STYLE.watchlo[i]); - __put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff, + __put_user(child->thread.watch.mips3264.watchhi[i] & + (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW), &addr->WATCH_STYLE.watchhi[i]); __put_user(boot_cpu_data.watch_reg_masks[i], &addr->WATCH_STYLE.watch_masks[i]); @@ -252,12 +253,12 @@ int ptrace_set_watch_regs(struct task_struct *child, } #endif __get_user(ht[i], &addr->WATCH_STYLE.watchhi[i]); - if (ht[i] & ~0xff8) + if (ht[i] & ~MIPS_WATCHHI_MASK) return -EINVAL; } /* Install them. */ for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { - if (lt[i] & 7) + if (lt[i] & MIPS_WATCHLO_IRW) watch_active = 1; child->thread.watch.mips3264.watchlo[i] = lt[i]; /* Set the G bit. */ diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c index 9b78e375118e..19fcab7348b1 100644 --- a/arch/mips/kernel/watch.c +++ b/arch/mips/kernel/watch.c @@ -25,16 +25,20 @@ void mips_install_watch_registers(struct task_struct *t) write_c0_watchlo3(watches->watchlo[3]); /* Write 1 to the I, R, and W bits to clear them, and 1 to G so all ASIDs are trapped. */ - write_c0_watchhi3(0x40000007 | watches->watchhi[3]); + write_c0_watchhi3(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW | + watches->watchhi[3]); case 3: write_c0_watchlo2(watches->watchlo[2]); - write_c0_watchhi2(0x40000007 | watches->watchhi[2]); + write_c0_watchhi2(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW | + watches->watchhi[2]); case 2: write_c0_watchlo1(watches->watchlo[1]); - write_c0_watchhi1(0x40000007 | watches->watchhi[1]); + write_c0_watchhi1(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW | + watches->watchhi[1]); case 1: write_c0_watchlo0(watches->watchlo[0]); - write_c0_watchhi0(0x40000007 | watches->watchhi[0]); + write_c0_watchhi0(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW | + watches->watchhi[0]); } } @@ -51,22 +55,26 @@ void mips_read_watch_registers(void) default: BUG(); case 4: - watches->watchhi[3] = (read_c0_watchhi3() & 0x0fff); + watches->watchhi[3] = (read_c0_watchhi3() & + (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW)); case 3: - watches->watchhi[2] = (read_c0_watchhi2() & 0x0fff); + watches->watchhi[2] = (read_c0_watchhi2() & + (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW)); case 2: - watches->watchhi[1] = (read_c0_watchhi1() & 0x0fff); + watches->watchhi[1] = (read_c0_watchhi1() & + (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW)); case 1: - watches->watchhi[0] = (read_c0_watchhi0() & 0x0fff); + watches->watchhi[0] = (read_c0_watchhi0() & + (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW)); } if (current_cpu_data.watch_reg_use_cnt == 1 && - (watches->watchhi[0] & 7) == 0) { + (watches->watchhi[0] & MIPS_WATCHHI_IRW) == 0) { /* Pathological case of release 1 architecture that * doesn't set the condition bits. We assume that * since we got here, the watch condition was met and * signal that the conditions requested in watchlo * were met. */ - watches->watchhi[0] |= (watches->watchlo[0] & 7); + watches->watchhi[0] |= (watches->watchlo[0] & MIPS_WATCHHI_IRW); } } @@ -109,86 +117,86 @@ void mips_probe_watch_registers(struct cpuinfo_mips *c) * Check which of the I,R and W bits are supported, then * disable the register. */ - write_c0_watchlo0(7); + write_c0_watchlo0(MIPS_WATCHLO_IRW); back_to_back_c0_hazard(); t = read_c0_watchlo0(); write_c0_watchlo0(0); - c->watch_reg_masks[0] = t & 7; + c->watch_reg_masks[0] = t & MIPS_WATCHLO_IRW; /* Write the mask bits and read them back to determine which * can be used. */ c->watch_reg_count = 1; c->watch_reg_use_cnt = 1; t = read_c0_watchhi0(); - write_c0_watchhi0(t | 0xff8); + write_c0_watchhi0(t | MIPS_WATCHHI_MASK); back_to_back_c0_hazard(); t = read_c0_watchhi0(); - c->watch_reg_masks[0] |= (t & 0xff8); - if ((t & 0x80000000) == 0) + c->watch_reg_masks[0] |= (t & MIPS_WATCHHI_MASK); + if ((t & MIPS_WATCHHI_M) == 0) return; - write_c0_watchlo1(7); + write_c0_watchlo1(MIPS_WATCHLO_IRW); back_to_back_c0_hazard(); t = read_c0_watchlo1(); write_c0_watchlo1(0); - c->watch_reg_masks[1] = t & 7; + c->watch_reg_masks[1] = t & MIPS_WATCHLO_IRW; c->watch_reg_count = 2; c->watch_reg_use_cnt = 2; t = read_c0_watchhi1(); - write_c0_watchhi1(t | 0xff8); + write_c0_watchhi1(t | MIPS_WATCHHI_MASK); back_to_back_c0_hazard(); t = read_c0_watchhi1(); - c->watch_reg_masks[1] |= (t & 0xff8); - if ((t & 0x80000000) == 0) + c->watch_reg_masks[1] |= (t & MIPS_WATCHHI_MASK); + if ((t & MIPS_WATCHHI_M) == 0) return; - write_c0_watchlo2(7); + write_c0_watchlo2(MIPS_WATCHLO_IRW); back_to_back_c0_hazard(); t = read_c0_watchlo2(); write_c0_watchlo2(0); - c->watch_reg_masks[2] = t & 7; + c->watch_reg_masks[2] = t & MIPS_WATCHLO_IRW; c->watch_reg_count = 3; c->watch_reg_use_cnt = 3; t = read_c0_watchhi2(); - write_c0_watchhi2(t | 0xff8); + write_c0_watchhi2(t | MIPS_WATCHHI_MASK); back_to_back_c0_hazard(); t = read_c0_watchhi2(); - c->watch_reg_masks[2] |= (t & 0xff8); - if ((t & 0x80000000) == 0) + c->watch_reg_masks[2] |= (t & MIPS_WATCHHI_MASK); + if ((t & MIPS_WATCHHI_M) == 0) return; - write_c0_watchlo3(7); + write_c0_watchlo3(MIPS_WATCHLO_IRW); back_to_back_c0_hazard(); t = read_c0_watchlo3(); write_c0_watchlo3(0); - c->watch_reg_masks[3] = t & 7; + c->watch_reg_masks[3] = t & MIPS_WATCHLO_IRW; c->watch_reg_count = 4; c->watch_reg_use_cnt = 4; t = read_c0_watchhi3(); - write_c0_watchhi3(t | 0xff8); + write_c0_watchhi3(t | MIPS_WATCHHI_MASK); back_to_back_c0_hazard(); t = read_c0_watchhi3(); - c->watch_reg_masks[3] |= (t & 0xff8); - if ((t & 0x80000000) == 0) + c->watch_reg_masks[3] |= (t & MIPS_WATCHHI_MASK); + if ((t & MIPS_WATCHHI_M) == 0) return; /* We use at most 4, but probe and report up to 8. */ c->watch_reg_count = 5; t = read_c0_watchhi4(); - if ((t & 0x80000000) == 0) + if ((t & MIPS_WATCHHI_M) == 0) return; c->watch_reg_count = 6; t = read_c0_watchhi5(); - if ((t & 0x80000000) == 0) + if ((t & MIPS_WATCHHI_M) == 0) return; c->watch_reg_count = 7; t = read_c0_watchhi6(); - if ((t & 0x80000000) == 0) + if ((t & MIPS_WATCHHI_M) == 0) return; c->watch_reg_count = 8; -- cgit v1.2.3 From 44896afe214e780e172f1bbbea7a2e6d087c908d Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Wed, 27 Jan 2016 14:56:06 +0100 Subject: MIPS: BCM1480: bcm1480_regs.h: strip redundant comments Strip some comments which probably meant to repeat the same value of the define; they also contained a confusing 0x0x prefix. Signed-off-by: Antonio Ospite Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12254/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/sibyte/bcm1480_regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/sibyte/bcm1480_regs.h b/arch/mips/include/asm/sibyte/bcm1480_regs.h index ec0dacf6f0cb..32a84837b8fa 100644 --- a/arch/mips/include/asm/sibyte/bcm1480_regs.h +++ b/arch/mips/include/asm/sibyte/bcm1480_regs.h @@ -415,8 +415,8 @@ (cpu)*BCM1480_IMR_ALIAS_MAILBOX_SPACING) #define A_BCM1480_IMR_ALIAS_MAILBOX_REGISTER(cpu, reg) (A_BCM1480_IMR_ALIAS_MAILBOX(cpu)+(reg)) -#define R_BCM1480_IMR_ALIAS_MAILBOX_0 0x0000 /* 0x0x0 */ -#define R_BCM1480_IMR_ALIAS_MAILBOX_0_SET 0x0008 /* 0x0x8 */ +#define R_BCM1480_IMR_ALIAS_MAILBOX_0 0x0000 +#define R_BCM1480_IMR_ALIAS_MAILBOX_0_SET 0x0008 /* * these macros work together to build the address of a mailbox -- cgit v1.2.3 From b2edcfc814017eb278e29bfdc72844f0434dd8b1 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 3 Mar 2016 09:45:09 +0800 Subject: MIPS: Loongson: Add Loongson-3A R2 basic support Loongson-3 CPU family: Code-name Brand-name PRId Loongson-3A R1 Loongson-3A1000 0x6305 Loongson-3A R2 Loongson-3A2000 0x6308 Loongson-3B R1 Loongson-3B1000 0x6306 Loongson-3B R2 Loongson-3B1500 0x6307 Features of R2 revision of Loongson-3A: - Primary cache includes I-Cache, D-Cache and V-Cache (Victim Cache). - I-Cache, D-Cache and V-Cache are 16-way set-associative, linesize is 64 bytes. - 64 entries of VTLB (classic TLB), 1024 entries of FTLB (8-way set-associative). - Supports DSP/DSPv2 instructions, UserLocal register and Read-Inhibit/ Execute-Inhibit. [ralf@linux-mips.org: Resolved merge conflicts.] Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12751/ Patchwork: https://patchwork.linux-mips.org/patch/13136/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 + arch/mips/include/asm/cacheops.h | 6 ++ arch/mips/include/asm/cpu-info.h | 1 + arch/mips/include/asm/cpu.h | 4 +- .../asm/mach-loongson64/cpu-feature-overrides.h | 18 +--- .../asm/mach-loongson64/kernel-entry-init.h | 6 +- arch/mips/include/asm/mipsregs.h | 2 + arch/mips/include/asm/pgtable.h | 4 +- arch/mips/kernel/cpu-probe.c | 38 +++++++- arch/mips/kernel/idle.c | 5 + arch/mips/kernel/traps.c | 3 +- arch/mips/loongson64/common/env.c | 7 +- arch/mips/loongson64/loongson-3/smp.c | 106 +++++++++++++++++++-- arch/mips/mm/c-r4k.c | 27 ++++++ drivers/platform/mips/cpu_hwmon.c | 4 +- 15 files changed, 201 insertions(+), 32 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index fbd63ff8eba4..adcc97ea4392 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1354,6 +1354,7 @@ config CPU_LOONGSON3 select CPU_SUPPORTS_HUGEPAGES select WEAK_ORDERING select WEAK_REORDERING_BEYOND_LLSC + select MIPS_PGD_C0_CONTEXT select ARCH_REQUIRE_GPIOLIB help The Loongson 3 processor implements the MIPS64R2 instruction @@ -1823,6 +1824,7 @@ config CPU_BMIPS5000 config SYS_HAS_CPU_LOONGSON3 bool select CPU_SUPPORTS_CPUFREQ + select CPU_HAS_RIXI config SYS_HAS_CPU_LOONGSON2E bool diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h index c3212ff26723..8031fbc6b69a 100644 --- a/arch/mips/include/asm/cacheops.h +++ b/arch/mips/include/asm/cacheops.h @@ -21,6 +21,7 @@ #define Cache_I 0x00 #define Cache_D 0x01 #define Cache_T 0x02 +#define Cache_V 0x02 /* Loongson-3 */ #define Cache_S 0x03 #define Index_Writeback_Inv 0x00 @@ -107,4 +108,9 @@ */ #define Hit_Invalidate_I_Loongson2 (Cache_I | 0x00) +/* + * Loongson3-specific cacheops + */ +#define Index_Writeback_Inv_V (Cache_V | Index_Writeback_Inv) + #endif /* __ASM_CACHEOPS_H */ diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index 9ec81684b1b8..b090aa51d644 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -60,6 +60,7 @@ struct cpuinfo_mips { int tlbsizeftlbways; struct cache_desc icache; /* Primary I-cache */ struct cache_desc dcache; /* Primary D or combined I/D cache */ + struct cache_desc vcache; /* Victim cache, between pcache and scache */ struct cache_desc scache; /* Secondary cache */ struct cache_desc tcache; /* Tertiary/split secondary cache */ int srsets; /* Shadow register sets */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 9127a583d1f1..810536b6900c 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -42,6 +42,7 @@ #define PRID_COMP_LEXRA 0x0b0000 #define PRID_COMP_NETLOGIC 0x0c0000 #define PRID_COMP_CAVIUM 0x0d0000 +#define PRID_COMP_LOONGSON 0x140000 #define PRID_COMP_INGENIC_D0 0xd00000 /* JZ4740, JZ4750 */ #define PRID_COMP_INGENIC_D1 0xd10000 /* JZ4770, JZ4775 */ #define PRID_COMP_INGENIC_E1 0xe10000 /* JZ4780 */ @@ -241,9 +242,10 @@ #define PRID_REV_LOONGSON1B 0x0020 #define PRID_REV_LOONGSON2E 0x0002 #define PRID_REV_LOONGSON2F 0x0003 -#define PRID_REV_LOONGSON3A 0x0005 +#define PRID_REV_LOONGSON3A_R1 0x0005 #define PRID_REV_LOONGSON3B_R1 0x0006 #define PRID_REV_LOONGSON3B_R2 0x0007 +#define PRID_REV_LOONGSON3A_R2 0x0008 /* * Older processors used to encode processor version and revision in two diff --git a/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h b/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h index 98963c2c7be4..89328a3d44d8 100644 --- a/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h @@ -16,11 +16,6 @@ #ifndef __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H #define __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H -#define cpu_dcache_line_size() 32 -#define cpu_icache_line_size() 32 -#define cpu_scache_line_size() 32 - - #define cpu_has_32fpr 1 #define cpu_has_3k_cache 0 #define cpu_has_4k_cache 1 @@ -31,24 +26,17 @@ #define cpu_has_counter 1 #define cpu_has_dc_aliases (PAGE_SIZE < 0x4000) #define cpu_has_divec 0 -#define cpu_has_dsp 0 -#define cpu_has_dsp2 0 #define cpu_has_ejtag 0 -#define cpu_has_ic_fills_f_dc 0 #define cpu_has_inclusive_pcaches 1 #define cpu_has_llsc 1 #define cpu_has_mcheck 0 #define cpu_has_mdmx 0 #define cpu_has_mips16 0 -#define cpu_has_mips32r2 0 #define cpu_has_mips3d 0 -#define cpu_has_mips64r2 0 #define cpu_has_mipsmt 0 -#define cpu_has_prefetch 0 #define cpu_has_smartmips 0 #define cpu_has_tlb 1 #define cpu_has_tx39_cache 0 -#define cpu_has_userlocal 0 #define cpu_has_vce 0 #define cpu_has_veic 0 #define cpu_has_vint 0 @@ -56,6 +44,10 @@ #define cpu_has_watch 1 #define cpu_has_local_ebase 0 -#define cpu_has_wsbh IS_ENABLED(CONFIG_CPU_LOONGSON3) +#ifdef CONFIG_CPU_LOONGSON3 +#define cpu_has_wsbh 1 +#define cpu_has_ic_fills_f_dc 1 +#define cpu_hwrena_impl_bits 0xc0000000 +#endif #endif /* __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h index 3f2f84f6c401..da83482ff0b9 100644 --- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h @@ -23,7 +23,8 @@ or t0, (0x1 << 7) mtc0 t0, $16, 3 /* Set ELPA on LOONGSON3 pagegrain */ - li t0, (0x1 << 29) + mfc0 t0, $5, 1 + or t0, (0x1 << 29) mtc0 t0, $5, 1 _ehb .set pop @@ -42,7 +43,8 @@ or t0, (0x1 << 7) mtc0 t0, $16, 3 /* Set ELPA on LOONGSON3 pagegrain */ - li t0, (0x1 << 29) + mfc0 t0, $5, 1 + or t0, (0x1 << 29) mtc0 t0, $5, 1 _ehb .set pop diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index aea90631a301..28ded49d25c6 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -636,6 +636,8 @@ #define MIPS_CONF6_SYND (_ULCAST_(1) << 13) /* proAptiv FTLB on/off bit */ #define MIPS_CONF6_FTLBEN (_ULCAST_(1) << 15) +/* Loongson-3 FTLB on/off bit */ +#define MIPS_CONF6_FTLBDIS (_ULCAST_(1) << 22) /* FTLB probability bits */ #define MIPS_CONF6_FTLBP_SHIFT (16) diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 45de57651619..7f422500b65d 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -384,7 +384,7 @@ static inline pte_t pte_mkdirty(pte_t pte) static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_CPU_LOONGSON3) if (!(pte_val(pte) & _PAGE_NO_READ)) pte_val(pte) |= _PAGE_SILENT_READ; else @@ -570,7 +570,7 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd) { pmd_val(pmd) |= _PAGE_ACCESSED; -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_CPU_LOONGSON3) if (!(pmd_val(pmd) & _PAGE_NO_READ)) pmd_val(pmd) |= _PAGE_SILENT_READ; else diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index d72bd7eb8bce..2bfd48375b46 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -562,6 +562,16 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable) write_c0_config7(config | (calculate_ftlb_probability(c) << MIPS_CONF7_FTLBP_SHIFT)); break; + case CPU_LOONGSON3: + /* Loongson-3 cores use Config6 to enable the FTLB */ + config = read_c0_config6(); + if (enable) + /* Enable FTLB */ + write_c0_config6(config & ~MIPS_CONF6_FTLBDIS); + else + /* Disable FTLB */ + write_c0_config6(config | MIPS_CONF6_FTLBDIS); + break; default: return 1; } @@ -1178,7 +1188,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) set_isa(c, MIPS_CPU_ISA_III); c->fpu_msk31 |= FPU_CSR_CONDX; break; - case PRID_REV_LOONGSON3A: + case PRID_REV_LOONGSON3A_R1: c->cputype = CPU_LOONGSON3; __cpu_name[cpu] = "ICT Loongson-3"; set_elf_platform(cpu, "loongson3a"); @@ -1512,6 +1522,29 @@ platform: } } +static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) +{ + switch (c->processor_id & PRID_IMP_MASK) { + case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */ + switch (c->processor_id & PRID_REV_MASK) { + case PRID_REV_LOONGSON3A_R2: + c->cputype = CPU_LOONGSON3; + __cpu_name[cpu] = "ICT Loongson-3"; + set_elf_platform(cpu, "loongson3a"); + set_isa(c, MIPS_CPU_ISA_M64R2); + break; + } + + decode_configs(c); + c->options |= MIPS_CPU_TLBINV; + c->writecombine = _CACHE_UNCACHED_ACCELERATED; + break; + default: + panic("Unknown Loongson Processor ID!"); + break; + } +} + static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu) { decode_configs(c); @@ -1659,6 +1692,9 @@ void cpu_probe(void) case PRID_COMP_CAVIUM: cpu_probe_cavium(c, cpu); break; + case PRID_COMP_LOONGSON: + cpu_probe_loongson(c, cpu); + break; case PRID_COMP_INGENIC_D0: case PRID_COMP_INGENIC_D1: case PRID_COMP_INGENIC_E1: diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index 46794d64c0bf..60ab4c44d305 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -181,6 +181,11 @@ void __init check_wait(void) case CPU_XLP: cpu_wait = r4k_wait; break; + case CPU_LOONGSON3: + if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2) + cpu_wait = r4k_wait; + break; + case CPU_BMIPS5000: cpu_wait = r4k_wait_irqoff; break; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index dcda63e65854..38864dc179ff 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1772,7 +1772,8 @@ asmlinkage void do_ftlb(void) /* For the moment, report the problem and hang. */ if ((cpu_has_mips_r2_r6) && - ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) { + (((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS) || + ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_LOONGSON))) { pr_err("FTLB error exception, cp0_ecc=0x%08x:\n", read_c0_ecc()); pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc()); diff --git a/arch/mips/loongson64/common/env.c b/arch/mips/loongson64/common/env.c index d6d07ad56180..57d590ac8004 100644 --- a/arch/mips/loongson64/common/env.c +++ b/arch/mips/loongson64/common/env.c @@ -105,6 +105,10 @@ void __init prom_init_env(void) loongson_chiptemp[1] = 0x900010001fe0019c; loongson_chiptemp[2] = 0x900020001fe0019c; loongson_chiptemp[3] = 0x900030001fe0019c; + loongson_freqctrl[0] = 0x900000001fe001d0; + loongson_freqctrl[1] = 0x900010001fe001d0; + loongson_freqctrl[2] = 0x900020001fe001d0; + loongson_freqctrl[3] = 0x900030001fe001d0; loongson_sysconf.ht_control_base = 0x90000EFDFB000000; loongson_sysconf.workarounds = WORKAROUND_CPUFREQ; } else if (ecpu->cputype == Loongson_3B) { @@ -187,7 +191,8 @@ void __init prom_init_env(void) case PRID_REV_LOONGSON2F: cpu_clock_freq = 797000000; break; - case PRID_REV_LOONGSON3A: + case PRID_REV_LOONGSON3A_R1: + case PRID_REV_LOONGSON3A_R2: cpu_clock_freq = 900000000; break; case PRID_REV_LOONGSON3B_R1: diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c index b913cd240d77..e59759af63d9 100644 --- a/arch/mips/loongson64/loongson-3/smp.c +++ b/arch/mips/loongson64/loongson-3/smp.c @@ -439,7 +439,7 @@ static void loongson3_cpu_die(unsigned int cpu) * flush all L1 entries at first. Then, another core (usually Core 0) can * safely disable the clock of the target core. loongson3_play_dead() is * called via CKSEG1 (uncached and unmmaped) */ -static void loongson3a_play_dead(int *state_addr) +static void loongson3a_r1_play_dead(int *state_addr) { register int val; register long cpuid, core, node, count; @@ -501,6 +501,89 @@ static void loongson3a_play_dead(int *state_addr) : "a1"); } +static void loongson3a_r2_play_dead(int *state_addr) +{ + register int val; + register long cpuid, core, node, count; + register void *addr, *base, *initfunc; + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " li %[addr], 0x80000000 \n" /* KSEG0 */ + "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */ + " cache 0, 1(%[addr]) \n" + " cache 0, 2(%[addr]) \n" + " cache 0, 3(%[addr]) \n" + " cache 1, 0(%[addr]) \n" /* flush L1 DCache */ + " cache 1, 1(%[addr]) \n" + " cache 1, 2(%[addr]) \n" + " cache 1, 3(%[addr]) \n" + " addiu %[sets], %[sets], -1 \n" + " bnez %[sets], 1b \n" + " addiu %[addr], %[addr], 0x40 \n" + " li %[addr], 0x80000000 \n" /* KSEG0 */ + "2: cache 2, 0(%[addr]) \n" /* flush L1 VCache */ + " cache 2, 1(%[addr]) \n" + " cache 2, 2(%[addr]) \n" + " cache 2, 3(%[addr]) \n" + " cache 2, 4(%[addr]) \n" + " cache 2, 5(%[addr]) \n" + " cache 2, 6(%[addr]) \n" + " cache 2, 7(%[addr]) \n" + " cache 2, 8(%[addr]) \n" + " cache 2, 9(%[addr]) \n" + " cache 2, 10(%[addr]) \n" + " cache 2, 11(%[addr]) \n" + " cache 2, 12(%[addr]) \n" + " cache 2, 13(%[addr]) \n" + " cache 2, 14(%[addr]) \n" + " cache 2, 15(%[addr]) \n" + " addiu %[vsets], %[vsets], -1 \n" + " bnez %[vsets], 2b \n" + " addiu %[addr], %[addr], 0x40 \n" + " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */ + " sw %[val], (%[state_addr]) \n" + " sync \n" + " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */ + " .set pop \n" + : [addr] "=&r" (addr), [val] "=&r" (val) + : [state_addr] "r" (state_addr), + [sets] "r" (cpu_data[smp_processor_id()].dcache.sets), + [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets)); + + __asm__ __volatile__( + " .set push \n" + " .set noreorder \n" + " .set mips64 \n" + " mfc0 %[cpuid], $15, 1 \n" + " andi %[cpuid], 0x3ff \n" + " dli %[base], 0x900000003ff01000 \n" + " andi %[core], %[cpuid], 0x3 \n" + " sll %[core], 8 \n" /* get core id */ + " or %[base], %[base], %[core] \n" + " andi %[node], %[cpuid], 0xc \n" + " dsll %[node], 42 \n" /* get node id */ + " or %[base], %[base], %[node] \n" + "1: li %[count], 0x100 \n" /* wait for init loop */ + "2: bnez %[count], 2b \n" /* limit mailbox access */ + " addiu %[count], -1 \n" + " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */ + " beqz %[initfunc], 1b \n" + " nop \n" + " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */ + " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */ + " ld $a1, 0x38(%[base]) \n" + " jr %[initfunc] \n" /* jump to initial PC */ + " nop \n" + " .set pop \n" + : [core] "=&r" (core), [node] "=&r" (node), + [base] "=&r" (base), [cpuid] "=&r" (cpuid), + [count] "=&r" (count), [initfunc] "=&r" (initfunc) + : /* No Input */ + : "a1"); +} + static void loongson3b_play_dead(int *state_addr) { register int val; @@ -572,13 +655,18 @@ void play_dead(void) void (*play_dead_at_ckseg1)(int *); idle_task_exit(); - switch (loongson_sysconf.cputype) { - case Loongson_3A: + switch (read_c0_prid() & PRID_REV_MASK) { + case PRID_REV_LOONGSON3A_R1: default: play_dead_at_ckseg1 = - (void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead); + (void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead); + break; + case PRID_REV_LOONGSON3A_R2: + play_dead_at_ckseg1 = + (void *)CKSEG1ADDR((unsigned long)loongson3a_r2_play_dead); break; - case Loongson_3B: + case PRID_REV_LOONGSON3B_R1: + case PRID_REV_LOONGSON3B_R2: play_dead_at_ckseg1 = (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead); break; @@ -593,9 +681,9 @@ void loongson3_disable_clock(int cpu) uint64_t core_id = cpu_data[cpu].core; uint64_t package_id = cpu_data[cpu].package; - if (loongson_sysconf.cputype == Loongson_3A) { + if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) { LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id)); - } else if (loongson_sysconf.cputype == Loongson_3B) { + } else { if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG)) LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3)); } @@ -606,9 +694,9 @@ void loongson3_enable_clock(int cpu) uint64_t core_id = cpu_data[cpu].core; uint64_t package_id = cpu_data[cpu].package; - if (loongson_sysconf.cputype == Loongson_3A) { + if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) { LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id); - } else if (loongson_sysconf.cputype == Loongson_3B) { + } else { if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG)) LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3); } diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 6f43bdf9a679..77fbaf1cdfd6 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -77,6 +77,7 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info) */ static unsigned long icache_size __read_mostly; static unsigned long dcache_size __read_mostly; +static unsigned long vcache_size __read_mostly; static unsigned long scache_size __read_mostly; /* @@ -1349,6 +1350,31 @@ static void probe_pcache(void) c->dcache.linesz); } +static void probe_vcache(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int config2, lsize; + + if (current_cpu_type() != CPU_LOONGSON3) + return; + + config2 = read_c0_config2(); + if ((lsize = ((config2 >> 20) & 15))) + c->vcache.linesz = 2 << lsize; + else + c->vcache.linesz = lsize; + + c->vcache.sets = 64 << ((config2 >> 24) & 15); + c->vcache.ways = 1 + ((config2 >> 16) & 15); + + vcache_size = c->vcache.sets * c->vcache.ways * c->vcache.linesz; + + c->vcache.waybit = 0; + + pr_info("Unified victim cache %ldkB %s, linesize %d bytes.\n", + vcache_size >> 10, way_string[c->vcache.ways], c->vcache.linesz); +} + /* * If you even _breathe_ on this function, look at the gcc output and make sure * it does not pop things on and off the stack for the cache sizing loop that @@ -1671,6 +1697,7 @@ void r4k_cache_init(void) struct cpuinfo_mips *c = ¤t_cpu_data; probe_pcache(); + probe_vcache(); setup_scache(); r4k_blast_dcache_page_setup(); diff --git a/drivers/platform/mips/cpu_hwmon.c b/drivers/platform/mips/cpu_hwmon.c index 0f6c63e17049..8c5072b7ad4f 100644 --- a/drivers/platform/mips/cpu_hwmon.c +++ b/drivers/platform/mips/cpu_hwmon.c @@ -20,9 +20,9 @@ int loongson3_cpu_temp(int cpu) u32 reg; reg = LOONGSON_CHIPTEMP(cpu); - if (loongson_sysconf.cputype == Loongson_3A) + if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) reg = (reg >> 8) & 0xff; - else if (loongson_sysconf.cputype == Loongson_3B) + else reg = ((reg >> 8) & 0xff) - 100; return (int)reg * 1000; -- cgit v1.2.3 From 06e4814eec988f7ee01c29762f945b3ff59355fb Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 3 Mar 2016 09:45:11 +0800 Subject: MIPS: Loongson: Invalidate special TLBs when needed Loongson-2 has a 4 entry itlb which is a subset of jtlb, Loongson-3 has a 4 entry itlb and a 4 entry dtlb which are subsets of jtlb. We should write diag register to invalidate itlb/dtlb when flushing jtlb because itlb/dtlb are not totally transparent to software. For Loongson-3A R2 (and newer), we should invalidate ITLB, DTLB, VTLB and FTLB before we enable/disable FTLB. Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12753/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 9 +++++++++ arch/mips/kernel/cpu-probe.c | 3 +++ arch/mips/mm/tlb-r4k.c | 27 +++++++++++++++------------ 3 files changed, 27 insertions(+), 12 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 28ded49d25c6..0d0bd161fc10 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -780,6 +780,15 @@ /* Disable Branch Return Cache */ #define R10K_DIAG_D_BRC (_ULCAST_(1) << 22) +/* Flush ITLB */ +#define LOONGSON_DIAG_ITLB (_ULCAST_(1) << 2) +/* Flush DTLB */ +#define LOONGSON_DIAG_DTLB (_ULCAST_(1) << 3) +/* Flush VTLB */ +#define LOONGSON_DIAG_VTLB (_ULCAST_(1) << 12) +/* Flush FTLB */ +#define LOONGSON_DIAG_FTLB (_ULCAST_(1) << 13) + /* * Coprocessor 1 (FPU) register names */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 2bfd48375b46..515dd1f8901e 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -563,6 +563,9 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable) << MIPS_CONF7_FTLBP_SHIFT)); break; case CPU_LOONGSON3: + /* Flush ITLB, DTLB, VTLB and FTLB */ + write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB | + LOONGSON_DIAG_VTLB | LOONGSON_DIAG_FTLB); /* Loongson-3 cores use Config6 to enable the FTLB */ config = read_c0_config6(); if (enable) diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index c17d7627f872..4c3362b46066 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -28,25 +28,28 @@ extern void build_tlb_refill_handler(void); /* - * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb, - * unfortunately, itlb is not totally transparent to software. + * LOONGSON-2 has a 4 entry itlb which is a subset of jtlb, LOONGSON-3 has + * a 4 entry itlb and a 4 entry dtlb which are subsets of jtlb. Unfortunately, + * itlb/dtlb are not totally transparent to software. */ -static inline void flush_itlb(void) +static inline void flush_micro_tlb(void) { switch (current_cpu_type()) { case CPU_LOONGSON2: + write_c0_diag(LOONGSON_DIAG_ITLB); + break; case CPU_LOONGSON3: - write_c0_diag(4); + write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB); break; default: break; } } -static inline void flush_itlb_vm(struct vm_area_struct *vma) +static inline void flush_micro_tlb_vm(struct vm_area_struct *vma) { if (vma->vm_flags & VM_EXEC) - flush_itlb(); + flush_micro_tlb(); } void local_flush_tlb_all(void) @@ -93,7 +96,7 @@ void local_flush_tlb_all(void) tlbw_use_hazard(); write_c0_entryhi(old_ctx); htw_start(); - flush_itlb(); + flush_micro_tlb(); local_irq_restore(flags); } EXPORT_SYMBOL(local_flush_tlb_all); @@ -159,7 +162,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, } else { drop_mmu_context(mm, cpu); } - flush_itlb(); + flush_micro_tlb(); local_irq_restore(flags); } } @@ -205,7 +208,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) } else { local_flush_tlb_all(); } - flush_itlb(); + flush_micro_tlb(); local_irq_restore(flags); } @@ -240,7 +243,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) finish: write_c0_entryhi(oldpid); htw_start(); - flush_itlb_vm(vma); + flush_micro_tlb_vm(vma); local_irq_restore(flags); } } @@ -274,7 +277,7 @@ void local_flush_tlb_one(unsigned long page) } write_c0_entryhi(oldpid); htw_start(); - flush_itlb(); + flush_micro_tlb(); local_irq_restore(flags); } @@ -357,7 +360,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) } tlbw_use_hazard(); htw_start(); - flush_itlb_vm(vma); + flush_micro_tlb_vm(vma); local_irq_restore(flags); } -- cgit v1.2.3 From 380cd582c08831217ae693c86411902e6300ba6b Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 3 Mar 2016 09:45:12 +0800 Subject: MIPS: Loongson-3: Fast TLB refill handler Loongson-3A R2 has pwbase/pwfield/pwsize/pwctl registers in CP0 (this is very similar to HTW) and lwdir/lwpte/lddir/ldpte instructions which can be used for fast TLB refill. [ralf@linux-mips.org: Resolve conflict.] Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12754/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 3 + arch/mips/include/asm/cpu.h | 1 + arch/mips/include/asm/mipsregs.h | 6 ++ arch/mips/include/asm/uasm.h | 3 +- arch/mips/include/uapi/asm/inst.h | 10 +++ arch/mips/kernel/cpu-probe.c | 2 +- arch/mips/mm/tlbex.c | 124 ++++++++++++++++++++++++++++++++++- arch/mips/mm/uasm-mips.c | 2 + arch/mips/mm/uasm.c | 3 + 9 files changed, 149 insertions(+), 5 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 6ff0504d090d..da92d513a395 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -35,6 +35,9 @@ #ifndef cpu_has_htw #define cpu_has_htw (cpu_data[0].options & MIPS_CPU_HTW) #endif +#ifndef cpu_has_ldpte +#define cpu_has_ldpte (cpu_data[0].options & MIPS_CPU_LDPTE) +#endif #ifndef cpu_has_rixiex #define cpu_has_rixiex (cpu_data[0].options & MIPS_CPU_RIXIEX) #endif diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 810536b6900c..d9150a210df6 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -402,6 +402,7 @@ enum cpu_type_enum { #define MIPS_CPU_NAN_LEGACY MBIT_ULL(38) /* Legacy NaN implemented */ #define MIPS_CPU_NAN_2008 MBIT_ULL(39) /* 2008 NaN implemented */ #define MIPS_CPU_VP MBIT_ULL(40) /* MIPSr6 Virtual Processors (multi-threading) */ +#define MIPS_CPU_LDPTE MBIT_ULL(41) /* CPU has ldpte/lddir instructions */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 0d0bd161fc10..1e9d337fb077 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1474,6 +1474,12 @@ do { \ #define read_c0_pwctl() __read_32bit_c0_register($6, 6) #define write_c0_pwctl(val) __write_32bit_c0_register($6, 6, val) +#define read_c0_pgd() __read_64bit_c0_register($9, 7) +#define write_c0_pgd(val) __write_64bit_c0_register($9, 7, val) + +#define read_c0_kpgd() __read_64bit_c0_register($31, 7) +#define write_c0_kpgd(val) __write_64bit_c0_register($31, 7, val) + /* Cavium OCTEON (cnMIPS) */ #define read_c0_cvmcount() __read_ulong_c0_register($9, 6) #define write_c0_cvmcount(val) __write_ulong_c0_register($9, 6, val) diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index fc1cdd25fcda..b6ecfeee4dbe 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -171,7 +171,8 @@ Ip_u2u1(_wsbh); Ip_u3u1u2(_xor); Ip_u2u1u3(_xori); Ip_u2u1(_yield); - +Ip_u1u2(_ldpte); +Ip_u2u1u3(_lddir); /* Handle labels. */ struct uasm_label { diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index ddea53e3a9bb..3bb8cd957e81 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -203,6 +203,16 @@ enum mad_func { nmadd_fp_op = 0x0c, nmsub_fp_op = 0x0e }; +/* + * func field for page table walker (Loongson-3). + */ +enum ptw_func { + lwdir_op = 0x00, + lwpte_op = 0x01, + lddir_op = 0x02, + ldpte_op = 0x03, +}; + /* * func field for special3 lx opcodes (Cavium Octeon). */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 515dd1f8901e..064ab389e964 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1539,7 +1539,7 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) } decode_configs(c); - c->options |= MIPS_CPU_TLBINV; + c->options |= MIPS_CPU_TLBINV | MIPS_CPU_LDPTE; c->writecombine = _CACHE_UNCACHED_ACCELERATED; break; default: diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 84c6e3fda84a..7153e1fb0cd4 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -284,7 +284,12 @@ static inline void dump_handler(const char *symbol, const u32 *handler, int coun #define C0_ENTRYLO1 3, 0 #define C0_CONTEXT 4, 0 #define C0_PAGEMASK 5, 0 +#define C0_PWBASE 5, 5 +#define C0_PWFIELD 5, 6 +#define C0_PWSIZE 5, 7 +#define C0_PWCTL 6, 6 #define C0_BADVADDR 8, 0 +#define C0_PGD 9, 7 #define C0_ENTRYHI 10, 0 #define C0_EPC 14, 0 #define C0_XCONTEXT 20, 0 @@ -808,7 +813,10 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, if (pgd_reg != -1) { /* pgd is in pgd_reg */ - UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); + if (cpu_has_ldpte) + UASM_i_MFC0(p, ptr, C0_PWBASE); + else + UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); } else { #if defined(CONFIG_MIPS_PGD_C0_CONTEXT) /* @@ -1421,6 +1429,108 @@ static void build_r4000_tlb_refill_handler(void) dump_handler("r4000_tlb_refill", (u32 *)ebase, 64); } +static void setup_pw(void) +{ + unsigned long pgd_i, pgd_w; +#ifndef __PAGETABLE_PMD_FOLDED + unsigned long pmd_i, pmd_w; +#endif + unsigned long pt_i, pt_w; + unsigned long pte_i, pte_w; +#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT + unsigned long psn; + + psn = ilog2(_PAGE_HUGE); /* bit used to indicate huge page */ +#endif + pgd_i = PGDIR_SHIFT; /* 1st level PGD */ +#ifndef __PAGETABLE_PMD_FOLDED + pgd_w = PGDIR_SHIFT - PMD_SHIFT + PGD_ORDER; + + pmd_i = PMD_SHIFT; /* 2nd level PMD */ + pmd_w = PMD_SHIFT - PAGE_SHIFT; +#else + pgd_w = PGDIR_SHIFT - PAGE_SHIFT + PGD_ORDER; +#endif + + pt_i = PAGE_SHIFT; /* 3rd level PTE */ + pt_w = PAGE_SHIFT - 3; + + pte_i = ilog2(_PAGE_GLOBAL); + pte_w = 0; + +#ifndef __PAGETABLE_PMD_FOLDED + write_c0_pwfield(pgd_i << 24 | pmd_i << 12 | pt_i << 6 | pte_i); + write_c0_pwsize(1 << 30 | pgd_w << 24 | pmd_w << 12 | pt_w << 6 | pte_w); +#else + write_c0_pwfield(pgd_i << 24 | pt_i << 6 | pte_i); + write_c0_pwsize(1 << 30 | pgd_w << 24 | pt_w << 6 | pte_w); +#endif + +#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT + write_c0_pwctl(1 << 6 | psn); +#endif + write_c0_kpgd(swapper_pg_dir); + kscratch_used_mask |= (1 << 7); /* KScratch6 is used for KPGD */ +} + +static void build_loongson3_tlb_refill_handler(void) +{ + u32 *p = tlb_handler; + struct uasm_label *l = labels; + struct uasm_reloc *r = relocs; + + memset(labels, 0, sizeof(labels)); + memset(relocs, 0, sizeof(relocs)); + memset(tlb_handler, 0, sizeof(tlb_handler)); + + if (check_for_high_segbits) { + uasm_i_dmfc0(&p, K0, C0_BADVADDR); + uasm_i_dsrl_safe(&p, K1, K0, PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3); + uasm_il_beqz(&p, &r, K1, label_vmalloc); + uasm_i_nop(&p); + + uasm_il_bgez(&p, &r, K0, label_large_segbits_fault); + uasm_i_nop(&p); + uasm_l_vmalloc(&l, p); + } + + uasm_i_dmfc0(&p, K1, C0_PGD); + + uasm_i_lddir(&p, K0, K1, 3); /* global page dir */ +#ifndef __PAGETABLE_PMD_FOLDED + uasm_i_lddir(&p, K1, K0, 1); /* middle page dir */ +#endif + uasm_i_ldpte(&p, K1, 0); /* even */ + uasm_i_ldpte(&p, K1, 1); /* odd */ + uasm_i_tlbwr(&p); + + /* restore page mask */ + if (PM_DEFAULT_MASK >> 16) { + uasm_i_lui(&p, K0, PM_DEFAULT_MASK >> 16); + uasm_i_ori(&p, K0, K0, PM_DEFAULT_MASK & 0xffff); + uasm_i_mtc0(&p, K0, C0_PAGEMASK); + } else if (PM_DEFAULT_MASK) { + uasm_i_ori(&p, K0, 0, PM_DEFAULT_MASK); + uasm_i_mtc0(&p, K0, C0_PAGEMASK); + } else { + uasm_i_mtc0(&p, 0, C0_PAGEMASK); + } + + uasm_i_eret(&p); + + if (check_for_high_segbits) { + uasm_l_large_segbits_fault(&l, p); + UASM_i_LA(&p, K1, (unsigned long)tlb_do_page_fault_0); + uasm_i_jr(&p, K1); + uasm_i_nop(&p); + } + + uasm_resolve_relocs(relocs, labels); + memcpy((void *)(ebase + 0x80), tlb_handler, 0x80); + local_flush_icache_range(ebase + 0x80, ebase + 0x100); + dump_handler("loongson3_tlb_refill", (u32 *)(ebase + 0x80), 32); +} + extern u32 handle_tlbl[], handle_tlbl_end[]; extern u32 handle_tlbs[], handle_tlbs_end[]; extern u32 handle_tlbm[], handle_tlbm_end[]; @@ -1468,7 +1578,10 @@ static void build_setup_pgd(void) } else { /* PGD in c0_KScratch */ uasm_i_jr(&p, 31); - UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg); + if (cpu_has_ldpte) + UASM_i_MTC0(&p, a0, C0_PWBASE); + else + UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg); } #else #ifdef CONFIG_SMP @@ -2437,13 +2550,18 @@ void build_tlb_refill_handler(void) break; default: + if (cpu_has_ldpte) + setup_pw(); + if (!run_once) { scratch_reg = allocate_kscratch(); build_setup_pgd(); build_r4000_tlb_load_handler(); build_r4000_tlb_store_handler(); build_r4000_tlb_modify_handler(); - if (!cpu_has_local_ebase) + if (cpu_has_ldpte) + build_loongson3_tlb_refill_handler(); + else if (!cpu_has_local_ebase) build_r4000_tlb_refill_handler(); flush_tlb_handlers(); run_once++; diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index b4a837893562..9c2220a45189 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -153,6 +153,8 @@ static struct insn insn_table[] = { { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, { insn_yield, M(spec3_op, 0, 0, 0, 0, yield_op), RS | RD }, + { insn_ldpte, M(lwc2_op, 0, 0, 0, ldpte_op, mult_op), RS | RD }, + { insn_lddir, M(lwc2_op, 0, 0, 0, lddir_op, mult_op), RS | RT | RD }, { insn_invalid, 0, 0 } }; diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 319051c34343..ad718debc35a 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -60,6 +60,7 @@ enum opcode { insn_sltiu, insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh, insn_xor, insn_xori, insn_yield, + insn_lddir, insn_ldpte, }; struct insn { @@ -335,6 +336,8 @@ I_u1u2s3(_bbit0); I_u1u2s3(_bbit1); I_u3u1u2(_lwx) I_u3u1u2(_ldx) +I_u1u2(_ldpte) +I_u2u1u3(_lddir) #ifdef CONFIG_CPU_CAVIUM_OCTEON #include -- cgit v1.2.3 From 1e820da3c9af4f5771d2ad47099919429b906ac6 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 3 Mar 2016 09:45:13 +0800 Subject: MIPS: Loongson-3: Introduce CONFIG_LOONGSON3_ENHANCEMENT New Loongson 3 CPU (since Loongson-3A R2, as opposed to Loongson-3A R1, Loongson-3B R1 and Loongson-3B R2) has many enhancements, such as FTLB, L1-VCache, EI/DI/Wait/Prefetch instruction, DSP/DSPv2 ASE, User Local register, Read-Inhibit/Execute-Inhibit, SFB (Store Fill Buffer), Fast TLB refill support, etc. This patch introduce a config option, CONFIG_LOONGSON3_ENHANCEMENT, to enable those enhancements which are not probed at run time. If you want a generic kernel to run on all Loongson 3 machines, please say 'N' here. If you want a high-performance kernel to run on new Loongson 3 machines only, please say 'Y' here. Some additional explanations: 1) SFB locates between core and L1 cache, it causes memory access out of order, so writel/outl (and other similar functions) need a I/O reorder barrier. 2) Loongson 3 has a bug that di instruction can not save the irqflag, so arch_local_irq_save() is modified. Since CPU_MIPSR2 is selected by CONFIG_LOONGSON3_ENHANCEMENT, generic kernel doesn't use ei/di at all. 3) CPU_HAS_PREFETCH is selected by CONFIG_LOONGSON3_ENHANCEMENT, so MIPS_CPU_PREFETCH (used by uasm) probing is also put in this patch. Signed-off-by: Huacai Chen Cc: Aurelien Jarno Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12755/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 18 ++++++++++++++++++ arch/mips/include/asm/hazards.h | 7 ++++--- arch/mips/include/asm/io.h | 10 +++++----- arch/mips/include/asm/irqflags.h | 5 +++++ .../include/asm/mach-loongson64/kernel-entry-init.h | 12 ++++++++++++ arch/mips/mm/c-r4k.c | 2 ++ arch/mips/mm/page.c | 9 +++++++++ 7 files changed, 55 insertions(+), 8 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index adcc97ea4392..d5c3621f0dd1 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1360,6 +1360,24 @@ config CPU_LOONGSON3 The Loongson 3 processor implements the MIPS64R2 instruction set with many extensions. +config LOONGSON3_ENHANCEMENT + bool "New Loongson 3 CPU Enhancements" + default n + select CPU_MIPSR2 + select CPU_HAS_PREFETCH + depends on CPU_LOONGSON3 + help + New Loongson 3 CPU (since Loongson-3A R2, as opposed to Loongson-3A + R1, Loongson-3B R1 and Loongson-3B R2) has many enhancements, such as + FTLB, L1-VCache, EI/DI/Wait/Prefetch instruction, DSP/DSPv2 ASE, User + Local register, Read-Inhibit/Execute-Inhibit, SFB (Store Fill Buffer), + Fast TLB refill support, etc. + + This option enable those enhancements which are not probed at run + time. If you want a generic kernel to run on all Loongson 3 machines, + please say 'N' here. If you want a high-performance kernel to run on + new Loongson 3 machines only, please say 'Y' here. + config CPU_LOONGSON2E bool "Loongson 2E" depends on SYS_HAS_CPU_LOONGSON2E diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h index 7b99efd31074..dbb1eb6e284f 100644 --- a/arch/mips/include/asm/hazards.h +++ b/arch/mips/include/asm/hazards.h @@ -22,7 +22,8 @@ /* * TLB hazards */ -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) && !defined(CONFIG_CPU_CAVIUM_OCTEON) +#if (defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)) && \ + !defined(CONFIG_CPU_CAVIUM_OCTEON) && !defined(CONFIG_LOONGSON3_ENHANCEMENT) /* * MIPSR2 defines ehb for hazard avoidance @@ -155,8 +156,8 @@ do { \ } while (0) #elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \ - defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_CPU_R10000) || \ - defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR) + defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_LOONGSON3_ENHANCEMENT) || \ + defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR) /* * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer. diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 2b4dc7ad53b8..ecabc00c1e66 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -304,10 +304,10 @@ static inline void iounmap(const volatile void __iomem *addr) #undef __IS_KSEG1 } -#ifdef CONFIG_CPU_CAVIUM_OCTEON -#define war_octeon_io_reorder_wmb() wmb() +#if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_LOONGSON3_ENHANCEMENT) +#define war_io_reorder_wmb() wmb() #else -#define war_octeon_io_reorder_wmb() do { } while (0) +#define war_io_reorder_wmb() do { } while (0) #endif #define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq) \ @@ -318,7 +318,7 @@ static inline void pfx##write##bwlq(type val, \ volatile type *__mem; \ type __val; \ \ - war_octeon_io_reorder_wmb(); \ + war_io_reorder_wmb(); \ \ __mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \ \ @@ -387,7 +387,7 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \ volatile type *__addr; \ type __val; \ \ - war_octeon_io_reorder_wmb(); \ + war_io_reorder_wmb(); \ \ __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ \ diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h index 65c351e328cc..9d3610be2323 100644 --- a/arch/mips/include/asm/irqflags.h +++ b/arch/mips/include/asm/irqflags.h @@ -41,7 +41,12 @@ static inline unsigned long arch_local_irq_save(void) " .set push \n" " .set reorder \n" " .set noat \n" +#if defined(CONFIG_CPU_LOONGSON3) + " mfc0 %[flags], $12 \n" + " di \n" +#else " di %[flags] \n" +#endif " andi %[flags], 1 \n" " " __stringify(__irq_disable_hazard) " \n" " .set pop \n" diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h index da83482ff0b9..8393bc548987 100644 --- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h @@ -26,6 +26,12 @@ mfc0 t0, $5, 1 or t0, (0x1 << 29) mtc0 t0, $5, 1 +#ifdef CONFIG_LOONGSON3_ENHANCEMENT + /* Enable STFill Buffer */ + mfc0 t0, $16, 6 + or t0, 0x100 + mtc0 t0, $16, 6 +#endif _ehb .set pop #endif @@ -46,6 +52,12 @@ mfc0 t0, $5, 1 or t0, (0x1 << 29) mtc0 t0, $5, 1 +#ifdef CONFIG_LOONGSON3_ENHANCEMENT + /* Enable STFill Buffer */ + mfc0 t0, $16, 6 + or t0, 0x100 + mtc0 t0, $16, 6 +#endif _ehb .set pop #endif diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 3415d3e2a63b..d73b304cfe8a 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1161,6 +1161,8 @@ static void probe_pcache(void) c->dcache.ways * c->dcache.linesz; c->dcache.waybit = 0; + if ((prid & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2) + c->options |= MIPS_CPU_PREFETCH; break; case CPU_CAVIUM_OCTEON3: diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index 885d73ffd6fb..c41953ca6605 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -188,6 +188,15 @@ static void set_prefetch_parameters(void) } break; + case CPU_LOONGSON3: + /* Loongson-3 only support the Pref_Load/Pref_Store. */ + pref_bias_clear_store = 128; + pref_bias_copy_load = 128; + pref_bias_copy_store = 128; + pref_src_mode = Pref_Load; + pref_dst_mode = Pref_Store; + break; + default: pref_bias_clear_store = 128; pref_bias_copy_load = 256; -- cgit v1.2.3 From 7939469da29a8dfa3947e5d9648d0f0501bc4ba0 Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Mon, 19 Oct 2015 11:39:55 -0700 Subject: MIPS64: signal: Fix o32 sigaction syscall MIPS32 o32 ABI sigaction() processing on MIPS64 n64 kernel was incorrectly set to processing aka rt_sigaction() variant only. Signed-off-by: Leonid Yegoshin Cc: paul.burton@imgtec.com Cc: richard@nod.at Cc: luto@amacapital.net Cc: alex.smith@imgtec.com Cc: Maciej W. Rozycki Cc: mpe@ellerman.id.au Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11321/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/signal.h | 12 +++++++++--- arch/mips/kernel/signal.c | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/signal.h b/arch/mips/include/asm/signal.h index 003e273eff4c..2292373ff11a 100644 --- a/arch/mips/include/asm/signal.h +++ b/arch/mips/include/asm/signal.h @@ -11,11 +11,17 @@ #include +#ifdef CONFIG_MIPS32_COMPAT +extern struct mips_abi mips_abi_32; -#ifdef CONFIG_TRAD_SIGNALS -#define sig_uses_siginfo(ka) ((ka)->sa.sa_flags & SA_SIGINFO) +#define sig_uses_siginfo(ka, abi) \ + ((abi != &mips_abi_32) ? 1 : \ + ((ka)->sa.sa_flags & SA_SIGINFO)) #else -#define sig_uses_siginfo(ka) (1) +#define sig_uses_siginfo(ka, abi) \ + (config_enabled(CONFIG_64BIT) ? 1 : \ + (config_enabled(CONFIG_TRAD_SIGNALS) ? \ + ((ka)->sa.sa_flags & SA_SIGINFO) : 1) ) #endif #include diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index bf792e2839a6..5f18d0b879e0 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -798,7 +798,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) regs->regs[0] = 0; /* Don't deal with this again. */ } - if (sig_uses_siginfo(&ksig->ka)) + if (sig_uses_siginfo(&ksig->ka, abi)) ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn, ksig, regs, oldset); else -- cgit v1.2.3 From 1e321fa917fb2d30d39ff1c6ea89d6f1cf4f34a5 Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Thu, 14 May 2015 18:34:43 -0700 Subject: MIPS64: Support of at least 48 bits of SEGBITS SEGBITS is 40 bits or more, depending on CPU type. Introduces optional support for 48 bits of application virtual address space. Only 16K and 64K pages are supported. Enabling will result in a memory overhead of a small number of pages for small applications. For 64K pages a 3rd level of page tables is required which has some impact during software TLB refill. [ralf@linux-mips.org: Fixed things raised in the review of the version posted and changed kconfig to be a bit more userfriendly.] Signed-off-by: Leonid Yegoshin Cc: aleksey.makarov@auriga.com Cc: james.hogan@imgtec.com Cc: paul.burton@imgtec.com Cc: david.daney@cavium.com Cc: peterz@infradead.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: davidlohr@hp.com Cc: kirill@shutemov.name Cc: akpm@linux-foundation.org Cc: mingo@kernel.org Patchwork: https://patchwork.linux-mips.org/patch/10051/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 13 +++++++++++++ arch/mips/include/asm/pgtable-64.h | 18 +++++++++++------- arch/mips/include/asm/processor.h | 6 +++++- 3 files changed, 29 insertions(+), 8 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index d5c3621f0dd1..2b7af9014cce 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2076,6 +2076,16 @@ config KVM_GUEST_TIMER_FREQ emulation when determining guest CPU Frequency. Instead, the guest's timer frequency is specified directly. +config MIPS_VA_BITS_48 + bool "48 bits virtual memory" + depends on 64BIT + help + Support a maximum at least 48 bits of application virtual memory. + Default is 40 bits or less, depending on the CPU. + This option result in a small memory overhead for page tables. + This option is only supported with 16k and 64k page sizes. + If unsure, say N. + choice prompt "Kernel page size" default PAGE_SIZE_4KB @@ -2083,6 +2093,7 @@ choice config PAGE_SIZE_4KB bool "4kB" depends on !CPU_LOONGSON2 && !CPU_LOONGSON3 + depends on !MIPS_VA_BITS_48 help This option select the standard 4kB Linux page size. On some R3000-family processors this is the only available page size. Using @@ -2092,6 +2103,7 @@ config PAGE_SIZE_4KB config PAGE_SIZE_8KB bool "8kB" depends on CPU_R8000 || CPU_CAVIUM_OCTEON + depends on !MIPS_VA_BITS_48 help Using 8kB page size will result in higher performance kernel at the price of higher memory consumption. This option is available @@ -2110,6 +2122,7 @@ config PAGE_SIZE_16KB config PAGE_SIZE_32KB bool "32kB" depends on CPU_CAVIUM_OCTEON + depends on !MIPS_VA_BITS_48 help Using 32kB page size will result in higher performance kernel at the price of higher memory consumption. This option is available diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h index cf661a2fb141..514cbc0a6a67 100644 --- a/arch/mips/include/asm/pgtable-64.h +++ b/arch/mips/include/asm/pgtable-64.h @@ -17,7 +17,7 @@ #include #include -#ifdef CONFIG_PAGE_SIZE_64KB +#if defined(CONFIG_PAGE_SIZE_64KB) && !defined(CONFIG_MIPS_VA_BITS_48) #include #else #include @@ -90,7 +90,11 @@ #define PTE_ORDER 0 #endif #ifdef CONFIG_PAGE_SIZE_16KB -#define PGD_ORDER 0 +#ifdef CONFIG_MIPS_VA_BITS_48 +#define PGD_ORDER 1 +#else +#define PGD_ORDER 0 +#endif #define PUD_ORDER aieeee_attempt_to_allocate_pud #define PMD_ORDER 0 #define PTE_ORDER 0 @@ -104,7 +108,11 @@ #ifdef CONFIG_PAGE_SIZE_64KB #define PGD_ORDER 0 #define PUD_ORDER aieeee_attempt_to_allocate_pud +#ifdef CONFIG_MIPS_VA_BITS_48 +#define PMD_ORDER 0 +#else #define PMD_ORDER aieeee_attempt_to_allocate_pmd +#endif #define PTE_ORDER 0 #endif @@ -114,11 +122,7 @@ #endif #define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t)) -#if PGDIR_SIZE >= TASK_SIZE64 -#define USER_PTRS_PER_PGD (1) -#else -#define USER_PTRS_PER_PGD (TASK_SIZE64 / PGDIR_SIZE) -#endif +#define USER_PTRS_PER_PGD ((TASK_SIZE64 / PGDIR_SIZE)?(TASK_SIZE64 / PGDIR_SIZE):1) #define FIRST_USER_ADDRESS 0UL /* diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index cfa15bad43af..7e78b6208d7d 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -63,7 +63,11 @@ extern unsigned int vced_count, vcei_count; * 8192EB ... */ #define TASK_SIZE32 0x7fff8000UL -#define TASK_SIZE64 0x10000000000UL +#ifdef CONFIG_MIPS_VA_BITS_48 +#define TASK_SIZE64 (0x1UL << ((cpu_data[0].vmbits>48)?48:cpu_data[0].vmbits)) +#else +#define TASK_SIZE64 0x10000000000UL +#endif #define TASK_SIZE (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64) #define STACK_TOP_MAX TASK_SIZE64 -- cgit v1.2.3 From e8b5325ca3d01c512be6f04d587869a01e0ea59f Mon Sep 17 00:00:00 2001 From: Sergey Ryazanov Date: Sat, 30 Aug 2014 06:06:28 +0400 Subject: MIPS: make PCI_DMA_BUS_IS_PHYS=1 constant No one of supported MIPS machines has an IOMMU unit, so we can safely define PCI_DMA_BUS_IS_PHYS = 1. Also remove iommu flag from the pci controller structure, since it is useless. Signed-off-by: Sergey Ryazanov Cc: Linux MIPS Patchwork: https://patchwork.linux-mips.org/patch/7604/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pci.h | 10 ++++------ arch/mips/kernel/setup.c | 7 ------- arch/mips/pci/pci-ip32.c | 1 - arch/mips/pci/pci.c | 3 --- arch/mips/pnx833x/common/setup.c | 3 --- 5 files changed, 4 insertions(+), 20 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 8c16fb7b8fdb..86b239d9d75d 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -43,8 +43,6 @@ struct pci_controller { and XFree86. Eventually will be removed. */ unsigned int need_domain_info; - int iommu; - /* Optional access methods for reading/writing the bus number of the PCI controller */ int (*get_busno)(void); @@ -106,11 +104,11 @@ static inline void pci_resource_to_user(const struct pci_dev *dev, int bar, struct pci_dev; /* - * The PCI address space does equal the physical memory address space. The - * networking and block device layers use this boolean for bounce buffer - * decisions. This is set if any hose does not have an IOMMU. + * The PCI address space does equal the physical memory address space. + * The networking and block device layers use this boolean for bounce + * buffer decisions. */ -extern unsigned int PCI_DMA_BUS_IS_PHYS; +#define PCI_DMA_BUS_IS_PHYS (1) #ifdef CONFIG_PCI_DOMAINS #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 9b20a0f89812..693e8d1a174c 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -51,13 +51,6 @@ EXPORT_SYMBOL(cpu_data); struct screen_info screen_info; #endif -/* - * Despite it's name this variable is even if we don't have PCI - */ -unsigned int PCI_DMA_BUS_IS_PHYS; - -EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS); - /* * Setup information * diff --git a/arch/mips/pci/pci-ip32.c b/arch/mips/pci/pci-ip32.c index b1e061f7fdc7..7ae89d0c7099 100644 --- a/arch/mips/pci/pci-ip32.c +++ b/arch/mips/pci/pci-ip32.c @@ -116,7 +116,6 @@ static struct pci_controller mace_pci_controller = { .pci_ops = &mace_pci_ops, .mem_resource = &mace_pci_mem_resource, .io_resource = &mace_pci_io_resource, - .iommu = 0, .mem_offset = MACE_PCI_MEM_OFFSET, .io_offset = 0, .io_map_base = CKSEG1ADDR(MACEPCI_LOW_IO), diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index b8a0bf5766f2..f1b11f0dea2d 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -83,9 +83,6 @@ static void pcibios_scanbus(struct pci_controller *hose) LIST_HEAD(resources); struct pci_bus *bus; - if (!hose->iommu) - PCI_DMA_BUS_IS_PHYS = 1; - if (hose->get_busno && pci_has_flag(PCI_PROBE_ONLY)) next_busno = (*hose->get_busno)(); diff --git a/arch/mips/pnx833x/common/setup.c b/arch/mips/pnx833x/common/setup.c index 99b4d94236cc..8a7443b2535e 100644 --- a/arch/mips/pnx833x/common/setup.c +++ b/arch/mips/pnx833x/common/setup.c @@ -38,9 +38,6 @@ extern void pnx833x_machine_power_off(void); int __init plat_mem_setup(void) { - /* fake pci bus to avoid bounce buffers */ - PCI_DMA_BUS_IS_PHYS = 1; - /* set mips clock to 320MHz */ #if defined(CONFIG_SOC_PNX8335) PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ); -- cgit v1.2.3 From 87321fddaeb8706a91293dc244408697a0a24ece Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 6 May 2016 13:35:03 +0100 Subject: MIPS: Implement __arch_bitrev* using bitswap for MIPSr6 Release 6 of the MIPS architecture introduced the bitswap instruction, which reverses the bits within each byte of a word. Make use of this instruction to implement the __arch_bitrev* functions, which should be faster for most MIPSr6 CPUs, reduces code size slightly and allows us to avoid the lookup table used by the generic implementation, saving 256 bytes in the kernel binary by dropping that. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13204/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/include/asm/bitrev.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 arch/mips/include/asm/bitrev.h (limited to 'arch/mips/include/asm') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2b7af9014cce..95f05826a16f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2000,6 +2000,7 @@ config CPU_MIPSR2 config CPU_MIPSR6 bool default y if CPU_MIPS32_R6 || CPU_MIPS64_R6 + select HAVE_ARCH_BITREVERSE select MIPS_SPRAM config EVA diff --git a/arch/mips/include/asm/bitrev.h b/arch/mips/include/asm/bitrev.h new file mode 100644 index 000000000000..bc739a404ae3 --- /dev/null +++ b/arch/mips/include/asm/bitrev.h @@ -0,0 +1,30 @@ +#ifndef __MIPS_ASM_BITREV_H__ +#define __MIPS_ASM_BITREV_H__ + +#include + +static __always_inline __attribute_const__ u32 __arch_bitrev32(u32 x) +{ + u32 ret; + + asm("bitswap %0, %1" : "=r"(ret) : "r"(__swab32(x))); + return ret; +} + +static __always_inline __attribute_const__ u16 __arch_bitrev16(u16 x) +{ + u16 ret; + + asm("bitswap %0, %1" : "=r"(ret) : "r"(__swab16(x))); + return ret; +} + +static __always_inline __attribute_const__ u8 __arch_bitrev8(u8 x) +{ + u8 ret; + + asm("bitswap %0, %1" : "=r"(ret) : "r"(x)); + return ret; +} + +#endif /* __MIPS_ASM_BITREV_H__ */ -- cgit v1.2.3 From 97b921087fa76b1b0b2a20ae70d0e8b6d394c4ea Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 5 May 2016 09:57:56 +0200 Subject: MIPS: Change my email address The old address is no longer valid. Use the my new one instead. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13201/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h | 2 +- arch/mips/include/asm/mach-lantiq/lantiq.h | 2 +- arch/mips/include/asm/mach-lantiq/lantiq_platform.h | 2 +- arch/mips/include/asm/mach-lantiq/xway/irq.h | 2 +- arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h | 2 +- arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 2 +- arch/mips/include/asm/mach-lantiq/xway/xway_dma.h | 2 +- arch/mips/include/asm/mach-ralink/mt7620.h | 2 +- arch/mips/include/asm/mach-ralink/mt7621.h | 2 +- arch/mips/include/asm/mach-ralink/pinmux.h | 2 +- arch/mips/include/asm/mach-ralink/ralink_regs.h | 2 +- arch/mips/include/asm/mach-ralink/rt288x.h | 2 +- arch/mips/include/asm/mach-ralink/rt305x.h | 2 +- arch/mips/lantiq/Makefile | 2 +- arch/mips/lantiq/clk.c | 2 +- arch/mips/lantiq/clk.h | 2 +- arch/mips/lantiq/early_printk.c | 2 +- arch/mips/lantiq/falcon/prom.c | 2 +- arch/mips/lantiq/falcon/reset.c | 2 +- arch/mips/lantiq/falcon/sysctrl.c | 2 +- arch/mips/lantiq/irq.c | 2 +- arch/mips/lantiq/prom.c | 2 +- arch/mips/lantiq/prom.h | 2 +- arch/mips/lantiq/xway/clk.c | 2 +- arch/mips/lantiq/xway/dcdc.c | 2 +- arch/mips/lantiq/xway/dma.c | 2 +- arch/mips/lantiq/xway/gptu.c | 2 +- arch/mips/lantiq/xway/prom.c | 2 +- arch/mips/lantiq/xway/reset.c | 2 +- arch/mips/lantiq/xway/sysctrl.c | 2 +- arch/mips/lantiq/xway/vmmc.c | 2 +- arch/mips/lantiq/xway/xrx200_phy_fw.c | 4 ++-- arch/mips/pci/fixup-lantiq.c | 2 +- arch/mips/pci/ops-lantiq.c | 2 +- arch/mips/pci/pci-lantiq.c | 2 +- arch/mips/pci/pci-lantiq.h | 2 +- arch/mips/pci/pci-mt7620.c | 2 +- arch/mips/pci/pci-rt2880.c | 2 +- arch/mips/ralink/Makefile | 2 +- arch/mips/ralink/bootrom.c | 2 +- arch/mips/ralink/cevt-rt3352.c | 2 +- arch/mips/ralink/clk.c | 2 +- arch/mips/ralink/common.h | 2 +- arch/mips/ralink/ill_acc.c | 2 +- arch/mips/ralink/irq-gic.c | 2 +- arch/mips/ralink/irq.c | 2 +- arch/mips/ralink/mt7620.c | 2 +- arch/mips/ralink/mt7621.c | 2 +- arch/mips/ralink/of.c | 2 +- arch/mips/ralink/prom.c | 2 +- arch/mips/ralink/reset.c | 2 +- arch/mips/ralink/rt288x.c | 2 +- arch/mips/ralink/rt305x.c | 2 +- arch/mips/ralink/rt3883.c | 2 +- arch/mips/ralink/timer-gic.c | 2 +- arch/mips/ralink/timer.c | 4 ++-- 56 files changed, 58 insertions(+), 58 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h index 98d6a2f14aaf..7023883ca50f 100644 --- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h +++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LTQ_FALCON_H__ diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h index 4e5ae6523cb4..8064d7a4b33d 100644 --- a/arch/mips/include/asm/mach-lantiq/lantiq.h +++ b/arch/mips/include/asm/mach-lantiq/lantiq.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LANTIQ_H__ #define _LANTIQ_H__ diff --git a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h index e23bf7c9a2d0..17d2fdcdaef4 100644 --- a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h +++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LANTIQ_PLATFORM_H__ diff --git a/arch/mips/include/asm/mach-lantiq/xway/irq.h b/arch/mips/include/asm/mach-lantiq/xway/irq.h index a1471d2dd0d2..83e5f03cccb5 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/irq.h +++ b/arch/mips/include/asm/mach-lantiq/xway/irq.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef __LANTIQ_IRQ_H diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h index 5eadfe582529..141076325307 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LANTIQ_XWAY_IRQ_H__ diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h index dd6005b75e0c..f87310755319 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LTQ_XWAY_H__ diff --git a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h index 5f8693d5ab12..4901833498f7 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h +++ b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h @@ -12,7 +12,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * - * Copyright (C) 2011 John Crispin + * Copyright (C) 2011 John Crispin */ #ifndef LTQ_DMA_H__ diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h index 455d406e8ddf..ece7420f6562 100644 --- a/arch/mips/include/asm/mach-ralink/mt7620.h +++ b/arch/mips/include/asm/mach-ralink/mt7620.h @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #ifndef _MT7620_REGS_H_ diff --git a/arch/mips/include/asm/mach-ralink/mt7621.h b/arch/mips/include/asm/mach-ralink/mt7621.h index 610b61e3f9df..a672e06fa5fd 100644 --- a/arch/mips/include/asm/mach-ralink/mt7621.h +++ b/arch/mips/include/asm/mach-ralink/mt7621.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2015 John Crispin + * Copyright (C) 2015 John Crispin */ #ifndef _MT7621_REGS_H_ diff --git a/arch/mips/include/asm/mach-ralink/pinmux.h b/arch/mips/include/asm/mach-ralink/pinmux.h index be106cb2e26d..ba8ac331af0c 100644 --- a/arch/mips/include/asm/mach-ralink/pinmux.h +++ b/arch/mips/include/asm/mach-ralink/pinmux.h @@ -3,7 +3,7 @@ * it under the terms of the GNU General Public License version 2 as * publishhed by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #ifndef _RT288X_PINMUX_H__ diff --git a/arch/mips/include/asm/mach-ralink/ralink_regs.h b/arch/mips/include/asm/mach-ralink/ralink_regs.h index 4c9fba68c8b2..9df1a53bcb36 100644 --- a/arch/mips/include/asm/mach-ralink/ralink_regs.h +++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h @@ -1,7 +1,7 @@ /* * Ralink SoC register definitions * - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin * Copyright (C) 2008-2010 Gabor Juhos * Copyright (C) 2008 Imre Kaloz * diff --git a/arch/mips/include/asm/mach-ralink/rt288x.h b/arch/mips/include/asm/mach-ralink/rt288x.h index 03ad716acb42..25ae1042d57b 100644 --- a/arch/mips/include/asm/mach-ralink/rt288x.h +++ b/arch/mips/include/asm/mach-ralink/rt288x.h @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #ifndef _RT288X_REGS_H_ diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h index 2eea79331a14..ac2d65c04b5f 100644 --- a/arch/mips/include/asm/mach-ralink/rt305x.h +++ b/arch/mips/include/asm/mach-ralink/rt305x.h @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #ifndef _RT305X_REGS_H_ diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile index 690257ab86d6..2718652e7466 100644 --- a/arch/mips/lantiq/Makefile +++ b/arch/mips/lantiq/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 2010 John Crispin +# Copyright (C) 2010 John Crispin # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License version 2 as published diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c index a0706fd4ce0a..149f0513c4f5 100644 --- a/arch/mips/lantiq/clk.c +++ b/arch/mips/lantiq/clk.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2010 Thomas Langer - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #include #include diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h index 7376ce817eda..e806e048ffc2 100644 --- a/arch/mips/lantiq/clk.h +++ b/arch/mips/lantiq/clk.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LTQ_CLK_H__ diff --git a/arch/mips/lantiq/early_printk.c b/arch/mips/lantiq/early_printk.c index 9b28d0940ef4..44bccaee822b 100644 --- a/arch/mips/lantiq/early_printk.c +++ b/arch/mips/lantiq/early_printk.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #include diff --git a/arch/mips/lantiq/falcon/prom.c b/arch/mips/lantiq/falcon/prom.c index aa9497947859..75315c0a9fc3 100644 --- a/arch/mips/lantiq/falcon/prom.c +++ b/arch/mips/lantiq/falcon/prom.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2012 Thomas Langer - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #include diff --git a/arch/mips/lantiq/falcon/reset.c b/arch/mips/lantiq/falcon/reset.c index 568248253426..7a535d72f541 100644 --- a/arch/mips/lantiq/falcon/reset.c +++ b/arch/mips/lantiq/falcon/reset.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2012 Thomas Langer - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #include diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c index 7edcd4946fc1..2a1b3021589c 100644 --- a/arch/mips/lantiq/falcon/sysctrl.c +++ b/arch/mips/lantiq/falcon/sysctrl.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2011 Thomas Langer - * Copyright (C) 2011 John Crispin + * Copyright (C) 2011 John Crispin */ #include diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index 2e7f60c9fc5d..ff17669e30a3 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin * Copyright (C) 2010 Thomas Langer */ diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c index a5c7fec92a97..5f693ac77a0d 100644 --- a/arch/mips/lantiq/prom.c +++ b/arch/mips/lantiq/prom.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #include diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h index bfd2d58c1d69..4b6576c50250 100644 --- a/arch/mips/lantiq/prom.h +++ b/arch/mips/lantiq/prom.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LTQ_PROM_H__ diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c index 07f6d5b0b65e..41fc30d8ef89 100644 --- a/arch/mips/lantiq/xway/clk.c +++ b/arch/mips/lantiq/xway/clk.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ diff --git a/arch/mips/lantiq/xway/dcdc.c b/arch/mips/lantiq/xway/dcdc.c index ae8e930f5283..08f7abaadfe5 100644 --- a/arch/mips/lantiq/xway/dcdc.c +++ b/arch/mips/lantiq/xway/dcdc.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin * Copyright (C) 2010 Sameer Ahmad, Lantiq GmbH */ diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c index 34a116e840d8..cef811755123 100644 --- a/arch/mips/lantiq/xway/dma.c +++ b/arch/mips/lantiq/xway/dma.c @@ -12,7 +12,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * - * Copyright (C) 2011 John Crispin + * Copyright (C) 2011 John Crispin */ #include diff --git a/arch/mips/lantiq/xway/gptu.c b/arch/mips/lantiq/xway/gptu.c index f1492b2db017..0f1bbea1a816 100644 --- a/arch/mips/lantiq/xway/gptu.c +++ b/arch/mips/lantiq/xway/gptu.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin * Copyright (C) 2012 Lantiq GmbH */ diff --git a/arch/mips/lantiq/xway/prom.c b/arch/mips/lantiq/xway/prom.c index 8f6e02f1e965..9475b2510adb 100644 --- a/arch/mips/lantiq/xway/prom.c +++ b/arch/mips/lantiq/xway/prom.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index 1f3460877ed5..83fd65d76e81 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 80554e8f6037..236193b5210b 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2011-2012 John Crispin + * Copyright (C) 2011-2012 John Crispin * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG */ diff --git a/arch/mips/lantiq/xway/vmmc.c b/arch/mips/lantiq/xway/vmmc.c index d001bc38908a..4625495f9230 100644 --- a/arch/mips/lantiq/xway/vmmc.c +++ b/arch/mips/lantiq/xway/vmmc.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #include diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c index 199094a40c15..71e518c1e7e7 100644 --- a/arch/mips/lantiq/xway/xrx200_phy_fw.c +++ b/arch/mips/lantiq/xway/xrx200_phy_fw.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #include @@ -112,6 +112,6 @@ static struct platform_driver xway_phy_driver = { module_platform_driver(xway_phy_driver); -MODULE_AUTHOR("John Crispin "); +MODULE_AUTHOR("John Crispin "); MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader"); MODULE_LICENSE("GPL"); diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c index c2ce41ea61d7..2b5427d3f35c 100644 --- a/arch/mips/pci/fixup-lantiq.c +++ b/arch/mips/pci/fixup-lantiq.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2012 John Crispin + * Copyright (C) 2012 John Crispin */ #include diff --git a/arch/mips/pci/ops-lantiq.c b/arch/mips/pci/ops-lantiq.c index e5738ee26f4f..f51e10899cc2 100644 --- a/arch/mips/pci/ops-lantiq.c +++ b/arch/mips/pci/ops-lantiq.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #include diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c index 6a15dbd085aa..b9deab17ccf2 100644 --- a/arch/mips/pci/pci-lantiq.c +++ b/arch/mips/pci/pci-lantiq.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #include diff --git a/arch/mips/pci/pci-lantiq.h b/arch/mips/pci/pci-lantiq.h index 66bf6cd6be3c..0cc71253a497 100644 --- a/arch/mips/pci/pci-lantiq.h +++ b/arch/mips/pci/pci-lantiq.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2010 John Crispin + * Copyright (C) 2010 John Crispin */ #ifndef _LTQ_PCI_H__ diff --git a/arch/mips/pci/pci-mt7620.c b/arch/mips/pci/pci-mt7620.c index 1ae932c2d78b..6ce816201699 100644 --- a/arch/mips/pci/pci-mt7620.c +++ b/arch/mips/pci/pci-mt7620.c @@ -2,7 +2,7 @@ * Ralink MT7620A SoC PCI support * * Copyright (C) 2007-2013 Bruce Chang (Mediatek) - * Copyright (C) 2013-2016 John Crispin + * Copyright (C) 2013-2016 John Crispin * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published diff --git a/arch/mips/pci/pci-rt2880.c b/arch/mips/pci/pci-rt2880.c index a245cad4372a..f2a1050168d9 100644 --- a/arch/mips/pci/pci-rt2880.c +++ b/arch/mips/pci/pci-rt2880.c @@ -1,7 +1,7 @@ /* * Ralink RT288x SoC PCI register definitions * - * Copyright (C) 2009 John Crispin + * Copyright (C) 2009 John Crispin * Copyright (C) 2009 Gabor Juhos * * Parts of this file are based on Ralink's 2.6.21 BSP diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile index 0d1795a0321e..fe3471533820 100644 --- a/arch/mips/ralink/Makefile +++ b/arch/mips/ralink/Makefile @@ -4,7 +4,7 @@ # Makefile for the Ralink common stuff # # Copyright (C) 2009-2011 Gabor Juhos -# Copyright (C) 2013 John Crispin +# Copyright (C) 2013 John Crispin obj-y := prom.o of.o reset.o diff --git a/arch/mips/ralink/bootrom.c b/arch/mips/ralink/bootrom.c index 5403468394fb..e1fa5972a81d 100644 --- a/arch/mips/ralink/bootrom.c +++ b/arch/mips/ralink/bootrom.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/cevt-rt3352.c b/arch/mips/ralink/cevt-rt3352.c index e46f91f971c5..3ad0b0794f7d 100644 --- a/arch/mips/ralink/cevt-rt3352.c +++ b/arch/mips/ralink/cevt-rt3352.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2013 by John Crispin + * Copyright (C) 2013 by John Crispin */ #include diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c index 25c4a61779f1..ebaa7cc0e995 100644 --- a/arch/mips/ralink/clk.c +++ b/arch/mips/ralink/clk.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2011 Gabor Juhos - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h index 8e7d8e618fb9..b8245d0940d6 100644 --- a/arch/mips/ralink/common.h +++ b/arch/mips/ralink/common.h @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #ifndef _RALINK_COMMON_H__ diff --git a/arch/mips/ralink/ill_acc.c b/arch/mips/ralink/ill_acc.c index e10d10b9e82a..765d5ba98fa2 100644 --- a/arch/mips/ralink/ill_acc.c +++ b/arch/mips/ralink/ill_acc.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/irq-gic.c b/arch/mips/ralink/irq-gic.c index 50d6c55ab1de..2058280450b5 100644 --- a/arch/mips/ralink/irq-gic.c +++ b/arch/mips/ralink/irq-gic.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2015 Nikolay Martynov - * Copyright (C) 2015 John Crispin + * Copyright (C) 2015 John Crispin */ #include diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c index 4cf77f358395..4911c1445f1a 100644 --- a/arch/mips/ralink/irq.c +++ b/arch/mips/ralink/irq.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2009 Gabor Juhos - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index 0d3d1a97895f..2c623f6bca08 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c index e9b9fa3e1e51..a45bbbe97ac5 100644 --- a/arch/mips/ralink/mt7621.c +++ b/arch/mips/ralink/mt7621.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2015 Nikolay Martynov - * Copyright (C) 2015 John Crispin + * Copyright (C) 2015 John Crispin */ #include diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c index f9eda5d8f82c..0aa67a2d0ae6 100644 --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c @@ -5,7 +5,7 @@ * * Copyright (C) 2008 Imre Kaloz * Copyright (C) 2008-2009 Gabor Juhos - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/prom.c b/arch/mips/ralink/prom.c index 39a9142f71be..5a73c5e14221 100644 --- a/arch/mips/ralink/prom.c +++ b/arch/mips/ralink/prom.c @@ -5,7 +5,7 @@ * * Copyright (C) 2009 Gabor Juhos * Copyright (C) 2010 Joonas Lahtinen - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c index 09ccdd1b8f4d..64543d66e76b 100644 --- a/arch/mips/ralink/reset.c +++ b/arch/mips/ralink/reset.c @@ -5,7 +5,7 @@ * * Copyright (C) 2008-2009 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c index 3c84166ebcb7..285796e6d75c 100644 --- a/arch/mips/ralink/rt288x.c +++ b/arch/mips/ralink/rt288x.c @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c index d7c4ba43a428..c8a28c4bf29e 100644 --- a/arch/mips/ralink/rt305x.c +++ b/arch/mips/ralink/rt305x.c @@ -7,7 +7,7 @@ * * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c index fafec947b27d..4cef9162bd9b 100644 --- a/arch/mips/ralink/rt3883.c +++ b/arch/mips/ralink/rt3883.c @@ -7,7 +7,7 @@ * * Copyright (C) 2008 Imre Kaloz * Copyright (C) 2008-2011 Gabor Juhos - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include diff --git a/arch/mips/ralink/timer-gic.c b/arch/mips/ralink/timer-gic.c index 5b4f186bcf95..069771dbec42 100644 --- a/arch/mips/ralink/timer-gic.c +++ b/arch/mips/ralink/timer-gic.c @@ -4,7 +4,7 @@ * by the Free Software Foundation. * * Copyright (C) 2015 Nikolay Martynov - * Copyright (C) 2015 John Crispin + * Copyright (C) 2015 John Crispin */ #include diff --git a/arch/mips/ralink/timer.c b/arch/mips/ralink/timer.c index 82c72a15bf75..b0343ff336c5 100644 --- a/arch/mips/ralink/timer.c +++ b/arch/mips/ralink/timer.c @@ -3,7 +3,7 @@ * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * - * Copyright (C) 2013 John Crispin + * Copyright (C) 2013 John Crispin */ #include @@ -180,5 +180,5 @@ static struct platform_driver rt_timer_driver = { module_platform_driver(rt_timer_driver); MODULE_DESCRIPTION("Ralink RT2880 timer"); -MODULE_AUTHOR("John Crispin Date: Fri, 6 May 2016 14:36:19 +0100 Subject: MIPS: Add & use CP0_EntryHi ASID definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add definitions for the ASID field in CP0_EntryHi (along with the soon to be used ASIDX field), and use them in a few previously hardcoded cases. Signed-off-by: James Hogan Cc: Manuel Lauss Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13205/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 2 ++ arch/mips/kernel/genex.S | 2 +- arch/mips/kvm/locore.S | 4 ++-- arch/mips/pci/pci-alchemy.c | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 1e9d337fb077..b7705ef09df2 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -229,6 +229,8 @@ /* MIPS32/64 EntryHI bit definitions */ #define MIPS_ENTRYHI_EHINV (_ULCAST_(1) << 10) +#define MIPS_ENTRYHI_ASIDX (_ULCAST_(0x3) << 8) +#define MIPS_ENTRYHI_ASID (_ULCAST_(0xff) << 0) /* * R4x00 interrupt enable / cause bits diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index baa7b6fc0a60..17374aef6f00 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -455,7 +455,7 @@ NESTED(nmi_handler, PT_SIZE, sp) .set noreorder /* check if TLB contains a entry for EPC */ MFC0 k1, CP0_ENTRYHI - andi k1, 0xff /* ASID_MASK */ + andi k1, MIPS_ENTRYHI_ASID MFC0 k0, CP0_EPC PTR_SRL k0, _PAGE_SHIFT + 1 PTR_SLL k0, _PAGE_SHIFT + 1 diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S index c24facc85357..308706493fd5 100644 --- a/arch/mips/kvm/locore.S +++ b/arch/mips/kvm/locore.S @@ -164,7 +164,7 @@ FEXPORT(__kvm_mips_load_asid) INT_SLL t2, t2, 2 /* x4 */ REG_ADDU t3, t1, t2 LONG_L k0, (t3) - andi k0, k0, 0xff + andi k0, k0, MIPS_ENTRYHI_ASID mtc0 k0, CP0_ENTRYHI ehb @@ -483,7 +483,7 @@ __kvm_mips_return_to_guest: INT_SLL t2, t2, 2 /* x4 */ REG_ADDU t3, t1, t2 LONG_L k0, (t3) - andi k0, k0, 0xff + andi k0, k0, MIPS_ENTRYHI_ASID mtc0 k0, CP0_ENTRYHI ehb diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c index 28952637a862..c8994c156e2d 100644 --- a/arch/mips/pci/pci-alchemy.c +++ b/arch/mips/pci/pci-alchemy.c @@ -76,7 +76,7 @@ static void mod_wired_entry(int entry, unsigned long entrylo0, unsigned long old_ctx; /* Save old context and create impossible VPN2 value */ - old_ctx = read_c0_entryhi() & 0xff; + old_ctx = read_c0_entryhi() & MIPS_ENTRYHI_ASID; old_pagemask = read_c0_pagemask(); write_c0_index(entry); write_c0_pagemask(pagemask); -- cgit v1.2.3 From ca64c2beecd43e9621f5265edf14a76f7a2ffd7b Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 6 May 2016 14:36:20 +0100 Subject: MIPS: KVM: Abstract guest ASID mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for supporting varied widths of ASID mask in the kernel in general, switch KVM's guest ASIDs to a new KVM_ENTRYHI_ASID definition based on the 8-bit MIPS_ENTRYHI_ASID instead of ASID_MASK. It could potentially be used to support extended guest ASIDs in the future. Signed-off-by: Paul Burton Signed-off-by: James Hogan Cc: Paolo Bonzini Cc: Radim Krčmář Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13207/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/kvm_host.h | 5 +++-- arch/mips/kvm/emulate.c | 25 +++++++++++++------------ arch/mips/kvm/tlb.c | 3 ++- 3 files changed, 18 insertions(+), 15 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index f6b12790716c..b76e132c87e4 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -311,17 +311,18 @@ enum emulation_result { #define MIPS3_PG_FRAME 0x3fffffc0 #define VPN2_MASK 0xffffe000 +#define KVM_ENTRYHI_ASID MIPS_ENTRYHI_ASID #define TLB_IS_GLOBAL(x) (((x).tlb_lo0 & MIPS3_PG_G) && \ ((x).tlb_lo1 & MIPS3_PG_G)) #define TLB_VPN2(x) ((x).tlb_hi & VPN2_MASK) -#define TLB_ASID(x) ((x).tlb_hi & ASID_MASK) +#define TLB_ASID(x) ((x).tlb_hi & KVM_ENTRYHI_ASID) #define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) \ ? ((x).tlb_lo1 & MIPS3_PG_V) \ : ((x).tlb_lo0 & MIPS3_PG_V)) #define TLB_HI_VPN2_HIT(x, y) ((TLB_VPN2(x) & ~(x).tlb_mask) == \ ((y) & VPN2_MASK & ~(x).tlb_mask)) #define TLB_HI_ASID_HIT(x, y) (TLB_IS_GLOBAL(x) || \ - TLB_ASID(x) == ((y) & ASID_MASK)) + TLB_ASID(x) == ((y) & KVM_ENTRYHI_ASID)) struct kvm_mips_tlb { long tlb_mask; diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index b37954cc880d..8e945e866a73 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -1068,15 +1068,15 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, kvm_read_c0_guest_ebase(cop0)); } else if (rd == MIPS_CP0_TLB_HI && sel == 0) { uint32_t nasid = - vcpu->arch.gprs[rt] & ASID_MASK; + vcpu->arch.gprs[rt] & KVM_ENTRYHI_ASID; if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0) && ((kvm_read_c0_guest_entryhi(cop0) & - ASID_MASK) != nasid)) { + KVM_ENTRYHI_ASID) != nasid)) { kvm_debug("MTCz, change ASID from %#lx to %#lx\n", kvm_read_c0_guest_entryhi(cop0) - & ASID_MASK, + & KVM_ENTRYHI_ASID, vcpu->arch.gprs[rt] - & ASID_MASK); + & KVM_ENTRYHI_ASID); /* Blow away the shadow host TLBs */ kvm_mips_flush_host_tlb(1); @@ -1620,7 +1620,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, */ index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) | (kvm_read_c0_guest_entryhi - (cop0) & ASID_MASK)); + (cop0) & KVM_ENTRYHI_ASID)); if (index < 0) { vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK); @@ -1786,7 +1786,7 @@ enum emulation_result kvm_mips_emulate_tlbmiss_ld(unsigned long cause, struct mips_coproc *cop0 = vcpu->arch.cop0; struct kvm_vcpu_arch *arch = &vcpu->arch; unsigned long entryhi = (vcpu->arch. host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { /* save old pc */ @@ -1833,7 +1833,7 @@ enum emulation_result kvm_mips_emulate_tlbinv_ld(unsigned long cause, struct kvm_vcpu_arch *arch = &vcpu->arch; unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { /* save old pc */ @@ -1878,7 +1878,7 @@ enum emulation_result kvm_mips_emulate_tlbmiss_st(unsigned long cause, struct mips_coproc *cop0 = vcpu->arch.cop0; struct kvm_vcpu_arch *arch = &vcpu->arch; unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { /* save old pc */ @@ -1922,7 +1922,7 @@ enum emulation_result kvm_mips_emulate_tlbinv_st(unsigned long cause, struct mips_coproc *cop0 = vcpu->arch.cop0; struct kvm_vcpu_arch *arch = &vcpu->arch; unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { /* save old pc */ @@ -1967,7 +1967,7 @@ enum emulation_result kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc, #ifdef DEBUG struct mips_coproc *cop0 = vcpu->arch.cop0; unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); int index; /* If address not in the guest TLB, then we are in trouble */ @@ -1994,7 +1994,7 @@ enum emulation_result kvm_mips_emulate_tlbmod(unsigned long cause, { struct mips_coproc *cop0 = vcpu->arch.cop0; unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID); struct kvm_vcpu_arch *arch = &vcpu->arch; if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { @@ -2569,7 +2569,8 @@ enum emulation_result kvm_mips_handle_tlbmiss(unsigned long cause, */ index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) | - (kvm_read_c0_guest_entryhi(vcpu->arch.cop0) & ASID_MASK)); + (kvm_read_c0_guest_entryhi(vcpu->arch.cop0) & + KVM_ENTRYHI_ASID)); if (index < 0) { if (exccode == EXCCODE_TLBL) { er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu); diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c index e0e1d0a611fc..52d87280f865 100644 --- a/arch/mips/kvm/tlb.c +++ b/arch/mips/kvm/tlb.c @@ -748,7 +748,8 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu) inst = *(opc); } else { vpn2 = (unsigned long) opc & VPN2_MASK; - asid = kvm_read_c0_guest_entryhi(cop0) & ASID_MASK; + asid = kvm_read_c0_guest_entryhi(cop0) & + KVM_ENTRYHI_ASID; index = kvm_mips_guest_tlb_lookup(vcpu, vpn2 | asid); if (index < 0) { kvm_err("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n", -- cgit v1.2.3 From 4edf00a46bee692f62578b5280c5774f9b65a08f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 6 May 2016 14:36:23 +0100 Subject: MIPS: Retrieve ASID masks using function accepting struct cpuinfo_mips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for supporting variable ASID masks, retrieve ASID masks using functions in asm/cpu-info.h which accept struct cpuinfo_mips. This will allow those functions to determine the ASID mask based upon the CPU in a later patch. This also allows for the r3k & r8k cases to be handled in Kconfig, which is arguably cleaner than the previous #ifdefs. Signed-off-by: Paul Burton Signed-off-by: James Hogan Cc: Paolo Bonzini Cc: Radim Krčmář Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13210/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 11 ++++++++++ arch/mips/include/asm/cpu-info.h | 10 +++++++++ arch/mips/include/asm/mmu_context.h | 41 ++++++++++++++++--------------------- arch/mips/kernel/traps.c | 2 +- arch/mips/kvm/tlb.c | 30 +++++++++++++++++---------- arch/mips/lib/dump_tlb.c | 10 +++++---- arch/mips/lib/r3k_dump_tlb.c | 9 ++++---- arch/mips/mm/tlb-r3k.c | 24 +++++++++++++--------- arch/mips/mm/tlb-r4k.c | 2 +- arch/mips/mm/tlb-r8k.c | 2 +- 10 files changed, 86 insertions(+), 55 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 95f05826a16f..0cab0da2ab55 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2449,6 +2449,17 @@ config CPU_R4000_WORKAROUNDS config CPU_R4400_WORKAROUNDS bool +config MIPS_ASID_SHIFT + int + default 6 if CPU_R3000 || CPU_TX39XX + default 4 if CPU_R8000 + default 0 + +config MIPS_ASID_BITS + int + default 6 if CPU_R3000 || CPU_TX39XX + default 8 + # # - Highmem only makes sense for the 32-bit kernel. # - The current highmem code will only work properly on physically indexed diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index b090aa51d644..1ae26a393153 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -132,4 +132,14 @@ struct proc_cpuinfo_notifier_args { # define cpu_vpe_id(cpuinfo) ({ (void)cpuinfo; 0; }) #endif +static inline unsigned long cpu_asid_inc(void) +{ + return 1 << CONFIG_MIPS_ASID_SHIFT; +} + +static inline unsigned long cpu_asid_mask(struct cpuinfo_mips *cpuinfo) +{ + return ((1 << CONFIG_MIPS_ASID_BITS) - 1) << CONFIG_MIPS_ASID_SHIFT; +} + #endif /* __ASM_CPU_INFO_H */ diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h index 45914b59824c..fc57e135cb0a 100644 --- a/arch/mips/include/asm/mmu_context.h +++ b/arch/mips/include/asm/mmu_context.h @@ -65,37 +65,32 @@ extern unsigned long pgd_current[]; back_to_back_c0_hazard(); \ TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) #endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/ -#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) -#define ASID_INC 0x40 -#define ASID_MASK 0xfc0 - -#elif defined(CONFIG_CPU_R8000) - -#define ASID_INC 0x10 -#define ASID_MASK 0xff0 - -#else /* FIXME: not correct for R6000 */ +/* + * All unused by hardware upper bits will be considered + * as a software asid extension. + */ +static unsigned long asid_version_mask(unsigned int cpu) +{ + unsigned long asid_mask = cpu_asid_mask(&cpu_data[cpu]); -#define ASID_INC 0x1 -#define ASID_MASK 0xff + return ~(asid_mask | (asid_mask - 1)); +} -#endif +static unsigned long asid_first_version(unsigned int cpu) +{ + return ~asid_version_mask(cpu) + 1; +} #define cpu_context(cpu, mm) ((mm)->context.asid[cpu]) -#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK) #define asid_cache(cpu) (cpu_data[cpu].asid_cache) +#define cpu_asid(cpu, mm) \ + (cpu_context((cpu), (mm)) & cpu_asid_mask(&cpu_data[cpu])) static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { } -/* - * All unused by hardware upper bits will be considered - * as a software asid extension. - */ -#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1))) -#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1) /* Normal, classic MIPS get_new_mmu_context */ static inline void @@ -104,7 +99,7 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) extern void kvm_local_flush_tlb_all(void); unsigned long asid = asid_cache(cpu); - if (! ((asid += ASID_INC) & ASID_MASK) ) { + if (!((asid += cpu_asid_inc()) & cpu_asid_mask(&cpu_data[cpu]))) { if (cpu_has_vtag_icache) flush_icache_all(); #ifdef CONFIG_KVM @@ -113,7 +108,7 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) local_flush_tlb_all(); /* start new asid cycle */ #endif if (!asid) /* fix version if needed */ - asid = ASID_FIRST_VERSION; + asid = asid_first_version(cpu); } cpu_context(cpu, mm) = asid_cache(cpu) = asid; @@ -145,7 +140,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, htw_stop(); /* Check if our ASID is of an older version and thus invalid */ - if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK) + if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & asid_version_mask(cpu)) get_new_mmu_context(next, cpu); write_c0_entryhi(cpu_asid(cpu, next)); TLBMISS_HANDLER_SETUP_PGD(next->pgd); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index f586b8b23f60..56f4161b98b9 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -2136,7 +2136,7 @@ void per_cpu_trap_init(bool is_boot_cpu) } if (!cpu_data[cpu].asid_cache) - cpu_data[cpu].asid_cache = ASID_FIRST_VERSION; + cpu_data[cpu].asid_cache = asid_first_version(cpu); atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c index 52d87280f865..b9c52c1d35d6 100644 --- a/arch/mips/kvm/tlb.c +++ b/arch/mips/kvm/tlb.c @@ -49,12 +49,18 @@ EXPORT_SYMBOL_GPL(kvm_mips_is_error_pfn); uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu) { - return vcpu->arch.guest_kernel_asid[smp_processor_id()] & ASID_MASK; + int cpu = smp_processor_id(); + + return vcpu->arch.guest_kernel_asid[cpu] & + cpu_asid_mask(&cpu_data[cpu]); } uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu) { - return vcpu->arch.guest_user_asid[smp_processor_id()] & ASID_MASK; + int cpu = smp_processor_id(); + + return vcpu->arch.guest_user_asid[cpu] & + cpu_asid_mask(&cpu_data[cpu]); } inline uint32_t kvm_mips_get_commpage_asid(struct kvm_vcpu *vcpu) @@ -78,7 +84,8 @@ void kvm_mips_dump_host_tlbs(void) old_pagemask = read_c0_pagemask(); kvm_info("HOST TLBs:\n"); - kvm_info("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK); + kvm_info("ASID: %#lx\n", read_c0_entryhi() & + cpu_asid_mask(¤t_cpu_data)); for (i = 0; i < current_cpu_data.tlbsize; i++) { write_c0_index(i); @@ -564,15 +571,15 @@ void kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu, { unsigned long asid = asid_cache(cpu); - asid += ASID_INC; - if (!(asid & ASID_MASK)) { + asid += cpu_asid_inc(); + if (!(asid & cpu_asid_mask(&cpu_data[cpu]))) { if (cpu_has_vtag_icache) flush_icache_all(); kvm_local_flush_tlb_all(); /* start new asid cycle */ if (!asid) /* fix version if needed */ - asid = ASID_FIRST_VERSION; + asid = asid_first_version(cpu); } cpu_context(cpu, mm) = asid_cache(cpu) = asid; @@ -627,6 +634,7 @@ static void kvm_mips_migrate_count(struct kvm_vcpu *vcpu) /* Restore ASID once we are scheduled back after preemption */ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { + unsigned long asid_mask = cpu_asid_mask(&cpu_data[cpu]); unsigned long flags; int newasid = 0; @@ -637,7 +645,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) local_irq_save(flags); if ((vcpu->arch.guest_kernel_asid[cpu] ^ asid_cache(cpu)) & - ASID_VERSION_MASK) { + asid_version_mask(cpu)) { kvm_get_new_mmu_context(&vcpu->arch.guest_kernel_mm, cpu, vcpu); vcpu->arch.guest_kernel_asid[cpu] = vcpu->arch.guest_kernel_mm.context.asid[cpu]; @@ -672,7 +680,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) */ if (current->flags & PF_VCPU) { write_c0_entryhi(vcpu->arch. - preempt_entryhi & ASID_MASK); + preempt_entryhi & asid_mask); ehb(); } } else { @@ -687,11 +695,11 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) if (KVM_GUEST_KERNEL_MODE(vcpu)) write_c0_entryhi(vcpu->arch. guest_kernel_asid[cpu] & - ASID_MASK); + asid_mask); else write_c0_entryhi(vcpu->arch. guest_user_asid[cpu] & - ASID_MASK); + asid_mask); ehb(); } } @@ -721,7 +729,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) kvm_mips_callbacks->vcpu_get_regs(vcpu); if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) & - ASID_VERSION_MASK)) { + asid_version_mask(cpu))) { kvm_debug("%s: Dropping MMU Context: %#lx\n", __func__, cpu_context(cpu, current->mm)); drop_mmu_context(current->mm, cpu); diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c index 92a37319efbe..3283aa7423e4 100644 --- a/arch/mips/lib/dump_tlb.c +++ b/arch/mips/lib/dump_tlb.c @@ -73,6 +73,8 @@ static void dump_tlb(int first, int last) unsigned long s_entryhi, entryhi, asid; unsigned long long entrylo0, entrylo1, pa; unsigned int s_index, s_pagemask, pagemask, c0, c1, i; + unsigned long asidmask = cpu_asid_mask(¤t_cpu_data); + int asidwidth = DIV_ROUND_UP(ilog2(asidmask) + 1, 4); #ifdef CONFIG_32BIT bool xpa = cpu_has_xpa && (read_c0_pagegrain() & PG_ELPA); int pwidth = xpa ? 11 : 8; @@ -86,7 +88,7 @@ static void dump_tlb(int first, int last) s_pagemask = read_c0_pagemask(); s_entryhi = read_c0_entryhi(); s_index = read_c0_index(); - asid = s_entryhi & 0xff; + asid = s_entryhi & asidmask; for (i = first; i <= last; i++) { write_c0_index(i); @@ -115,7 +117,7 @@ static void dump_tlb(int first, int last) * due to duplicate TLB entry. */ if (!((entrylo0 | entrylo1) & ENTRYLO_G) && - (entryhi & 0xff) != asid) + (entryhi & asidmask) != asid) continue; /* @@ -126,9 +128,9 @@ static void dump_tlb(int first, int last) c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT; c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT; - printk("va=%0*lx asid=%02lx\n", + printk("va=%0*lx asid=%0*lx\n", vwidth, (entryhi & ~0x1fffUL), - entryhi & 0xff); + asidwidth, entryhi & asidmask); /* RI/XI are in awkward places, so mask them off separately */ pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI); if (xpa) diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c index cfcbb5218b59..744f4a7bc49d 100644 --- a/arch/mips/lib/r3k_dump_tlb.c +++ b/arch/mips/lib/r3k_dump_tlb.c @@ -29,9 +29,10 @@ static void dump_tlb(int first, int last) { int i; unsigned int asid; - unsigned long entryhi, entrylo0; + unsigned long entryhi, entrylo0, asid_mask; - asid = read_c0_entryhi() & ASID_MASK; + asid_mask = cpu_asid_mask(¤t_cpu_data); + asid = read_c0_entryhi() & asid_mask; for (i = first; i <= last; i++) { write_c0_index(i<<8); @@ -46,7 +47,7 @@ static void dump_tlb(int first, int last) /* Unused entries have a virtual address of KSEG0. */ if ((entryhi & PAGE_MASK) != KSEG0 && (entrylo0 & R3K_ENTRYLO_G || - (entryhi & ASID_MASK) == asid)) { + (entryhi & asid_mask) == asid)) { /* * Only print entries in use */ @@ -55,7 +56,7 @@ static void dump_tlb(int first, int last) printk("va=%08lx asid=%08lx" " [pa=%06lx n=%d d=%d v=%d g=%d]", entryhi & PAGE_MASK, - entryhi & ASID_MASK, + entryhi & asid_mask, entrylo0 & PAGE_MASK, (entrylo0 & R3K_ENTRYLO_N) ? 1 : 0, (entrylo0 & R3K_ENTRYLO_D) ? 1 : 0, diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index b4f366f7c0f5..1290b995695d 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -43,7 +43,7 @@ static void local_flush_tlb_from(int entry) { unsigned long old_ctx; - old_ctx = read_c0_entryhi() & ASID_MASK; + old_ctx = read_c0_entryhi() & cpu_asid_mask(¤t_cpu_data); write_c0_entrylo0(0); while (entry < current_cpu_data.tlbsize) { write_c0_index(entry << 8); @@ -81,6 +81,7 @@ void local_flush_tlb_mm(struct mm_struct *mm) void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { + unsigned long asid_mask = cpu_asid_mask(¤t_cpu_data); struct mm_struct *mm = vma->vm_mm; int cpu = smp_processor_id(); @@ -89,13 +90,13 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, #ifdef DEBUG_TLB printk("[tlbrange<%lu,0x%08lx,0x%08lx>]", - cpu_context(cpu, mm) & ASID_MASK, start, end); + cpu_context(cpu, mm) & asid_mask, start, end); #endif local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; if (size <= current_cpu_data.tlbsize) { - int oldpid = read_c0_entryhi() & ASID_MASK; - int newpid = cpu_context(cpu, mm) & ASID_MASK; + int oldpid = read_c0_entryhi() & asid_mask; + int newpid = cpu_context(cpu, mm) & asid_mask; start &= PAGE_MASK; end += PAGE_SIZE - 1; @@ -159,6 +160,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { + unsigned long asid_mask = cpu_asid_mask(¤t_cpu_data); int cpu = smp_processor_id(); if (cpu_context(cpu, vma->vm_mm) != 0) { @@ -168,10 +170,10 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) #ifdef DEBUG_TLB printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page); #endif - newpid = cpu_context(cpu, vma->vm_mm) & ASID_MASK; + newpid = cpu_context(cpu, vma->vm_mm) & asid_mask; page &= PAGE_MASK; local_irq_save(flags); - oldpid = read_c0_entryhi() & ASID_MASK; + oldpid = read_c0_entryhi() & asid_mask; write_c0_entryhi(page | newpid); BARRIER; tlb_probe(); @@ -190,6 +192,7 @@ finish: void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) { + unsigned long asid_mask = cpu_asid_mask(¤t_cpu_data); unsigned long flags; int idx, pid; @@ -199,10 +202,10 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) if (current->active_mm != vma->vm_mm) return; - pid = read_c0_entryhi() & ASID_MASK; + pid = read_c0_entryhi() & asid_mask; #ifdef DEBUG_TLB - if ((pid != (cpu_context(cpu, vma->vm_mm) & ASID_MASK)) || (cpu_context(cpu, vma->vm_mm) == 0)) { + if ((pid != (cpu_context(cpu, vma->vm_mm) & asid_mask)) || (cpu_context(cpu, vma->vm_mm) == 0)) { printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n", (cpu_context(cpu, vma->vm_mm)), pid); } @@ -228,6 +231,7 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { + unsigned long asid_mask = cpu_asid_mask(¤t_cpu_data); unsigned long flags; unsigned long old_ctx; static unsigned long wired = 0; @@ -243,7 +247,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, local_irq_save(flags); /* Save old context and create impossible VPN2 value */ - old_ctx = read_c0_entryhi() & ASID_MASK; + old_ctx = read_c0_entryhi() & asid_mask; old_pagemask = read_c0_pagemask(); w = read_c0_wired(); write_c0_wired(w + 1); @@ -266,7 +270,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, #endif local_irq_save(flags); - old_ctx = read_c0_entryhi() & ASID_MASK; + old_ctx = read_c0_entryhi() & asid_mask; write_c0_entrylo0(entrylo0); write_c0_entryhi(entryhi); write_c0_index(wired); diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 4c3362b46066..61f1f1ba4a17 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -304,7 +304,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) local_irq_save(flags); htw_stop(); - pid = read_c0_entryhi() & ASID_MASK; + pid = read_c0_entryhi() & cpu_asid_mask(¤t_cpu_data); address &= (PAGE_MASK << 1); write_c0_entryhi(address | pid); pgdp = pgd_offset(vma->vm_mm, address); diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c index 138a2ec7cc6b..e86e2e55ad3e 100644 --- a/arch/mips/mm/tlb-r8k.c +++ b/arch/mips/mm/tlb-r8k.c @@ -194,7 +194,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) if (current->active_mm != vma->vm_mm) return; - pid = read_c0_entryhi() & ASID_MASK; + pid = read_c0_entryhi() & cpu_asid_mask(¤t_cpu_data); local_irq_save(flags); address &= PAGE_MASK; -- cgit v1.2.3 From 2db003a5ddee986d4bc67c069ee3aa1b1b320f1d Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 6 May 2016 14:36:24 +0100 Subject: MIPS: Support extended ASIDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for extended ASIDs as determined by the Config4.AE bit. Since the only supported CPUs known to implement this are Netlogic XLP and MIPS I6400, select this variable ASID support based upon CONFIG_CPU_XLP and CONFIG_CPU_MIPSR6. Signed-off-by: Paul Burton Signed-off-by: James Hogan Cc: Jayachandran C. Cc: Paolo Bonzini Cc: Radim Krčmář Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13211/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 6 ++++++ arch/mips/include/asm/cpu-info.h | 14 ++++++++++++++ arch/mips/kernel/asm-offsets.c | 10 ++++++++++ arch/mips/kernel/cpu-probe.c | 13 +++++++++++++ arch/mips/kernel/genex.S | 2 +- arch/mips/kvm/locore.S | 14 ++++++++++++++ 6 files changed, 58 insertions(+), 1 deletion(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 0cab0da2ab55..5cc5b621ae69 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1706,6 +1706,7 @@ config CPU_XLP select CPU_HAS_PREFETCH select CPU_MIPSR2 select CPU_SUPPORTS_HUGEPAGES + select MIPS_ASID_BITS_VARIABLE help Netlogic Microsystems XLP processors. endchoice @@ -2001,6 +2002,7 @@ config CPU_MIPSR6 bool default y if CPU_MIPS32_R6 || CPU_MIPS64_R6 select HAVE_ARCH_BITREVERSE + select MIPS_ASID_BITS_VARIABLE select MIPS_SPRAM config EVA @@ -2457,9 +2459,13 @@ config MIPS_ASID_SHIFT config MIPS_ASID_BITS int + default 0 if MIPS_ASID_BITS_VARIABLE default 6 if CPU_R3000 || CPU_TX39XX default 8 +config MIPS_ASID_BITS_VARIABLE + bool + # # - Highmem only makes sense for the 32-bit kernel. # - The current highmem code will only work properly on physically indexed diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index 1ae26a393153..392da7e6fc72 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -40,6 +40,9 @@ struct cache_desc { struct cpuinfo_mips { unsigned long asid_cache; +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + unsigned long asid_mask; +#endif /* * Capability and feature descriptor structure for MIPS CPU @@ -139,7 +142,18 @@ static inline unsigned long cpu_asid_inc(void) static inline unsigned long cpu_asid_mask(struct cpuinfo_mips *cpuinfo) { +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + return cpuinfo->asid_mask; +#endif return ((1 << CONFIG_MIPS_ASID_BITS) - 1) << CONFIG_MIPS_ASID_SHIFT; } +static inline void set_cpu_asid_mask(struct cpuinfo_mips *cpuinfo, + unsigned long asid_mask) +{ +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + cpuinfo->asid_mask = asid_mask; +#endif +} + #endif /* __ASM_CPU_INFO_H */ diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 154e2039ea5e..1ea973b2abb1 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -338,6 +339,15 @@ void output_pm_defines(void) } #endif +void output_cpuinfo_defines(void) +{ + COMMENT(" MIPS cpuinfo offsets. "); + DEFINE(CPUINFO_SIZE, sizeof(struct cpuinfo_mips)); +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + OFFSET(CPUINFO_ASID_MASK, cpuinfo_mips, asid_mask); +#endif +} + void output_kvm_defines(void) { COMMENT(" KVM/MIPS Specfic offsets. "); diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 064ab389e964..5ca4fefb1344 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -732,6 +732,7 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c) unsigned int newcf4; unsigned int mmuextdef; unsigned int ftlb_page = MIPS_CONF4_FTLBPAGESIZE; + unsigned long asid_mask; config4 = read_c0_config4(); @@ -792,6 +793,18 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c) c->kscratch_mask = (config4 >> 16) & 0xff; + asid_mask = MIPS_ENTRYHI_ASID; + if (config4 & MIPS_CONF4_AE) + asid_mask |= MIPS_ENTRYHI_ASIDX; + set_cpu_asid_mask(c, asid_mask); + + /* + * Warn if the computed ASID mask doesn't match the mask the kernel + * is built for. This may indicate either a serious problem or an + * easy optimisation opportunity, but either way should be addressed. + */ + WARN_ON(asid_mask != cpu_asid_mask(c)); + return config4 & MIPS_CONF_M; } diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 17374aef6f00..bff9644b9ad1 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -455,7 +455,7 @@ NESTED(nmi_handler, PT_SIZE, sp) .set noreorder /* check if TLB contains a entry for EPC */ MFC0 k1, CP0_ENTRYHI - andi k1, MIPS_ENTRYHI_ASID + andi k1, MIPS_ENTRYHI_ASID | MIPS_ENTRYHI_ASIDX MFC0 k0, CP0_EPC PTR_SRL k0, _PAGE_SHIFT + 1 PTR_SLL k0, _PAGE_SHIFT + 1 diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S index 1f2167bc847d..3ef03009de5f 100644 --- a/arch/mips/kvm/locore.S +++ b/arch/mips/kvm/locore.S @@ -137,7 +137,14 @@ FEXPORT(__kvm_mips_load_asid) INT_SLL t2, t2, 2 /* x4 */ REG_ADDU t3, t1, t2 LONG_L k0, (t3) +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + li t3, CPUINFO_SIZE/4 + mul t2, t2, t3 /* x sizeof(struct cpuinfo_mips)/4 */ + LONG_L t2, (cpu_data + CPUINFO_ASID_MASK)(t2) + and k0, k0, t2 +#else andi k0, k0, MIPS_ENTRYHI_ASID +#endif mtc0 k0, CP0_ENTRYHI ehb @@ -449,7 +456,14 @@ __kvm_mips_return_to_guest: INT_SLL t2, t2, 2 /* x4 */ REG_ADDU t3, t1, t2 LONG_L k0, (t3) +#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE + li t3, CPUINFO_SIZE/4 + mul t2, t2, t3 /* x sizeof(struct cpuinfo_mips)/4 */ + LONG_L t2, (cpu_data + CPUINFO_ASID_MASK)(t2) + and k0, k0, t2 +#else andi k0, k0, MIPS_ENTRYHI_ASID +#endif mtc0 k0, CP0_ENTRYHI ehb -- cgit v1.2.3 From 12822570a29bdc12c69fca2c021753cb5ce319c5 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 19 Apr 2016 09:24:59 +0100 Subject: MIPS: Separate XPA CPU feature into LPA and MVH XPA (eXtended Physical Addressing) should be detected as a combination of two architectural features: - Large Physical Address (as per Config3.LPA). With XPA this will be set on MIPS32r5 cores, but it may also be set for MIPS64r2 cores too. - MTHC0/MFHC0 instructions (as per Config5.MVH). With XPA this will be set, but it may also be set in VZ guest context even when Config3.LPA in the guest context has been cleared by the hypervisor. As such, XPA is only usable if both bits are set. Update CPU features to separate these two features, with cpu_has_xpa requiring both to be set. Signed-off-by: James Hogan Cc: Paul Burton Cc: Maciej W. Rozycki Cc: Joshua Kinard Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13112/ Signed-off-by: Paul Burton Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 8 +++++++- arch/mips/include/asm/cpu.h | 3 ++- arch/mips/kernel/cpu-probe.c | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index da92d513a395..bff73c52b273 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -145,8 +145,14 @@ # endif #endif +#ifndef cpu_has_lpa +#define cpu_has_lpa (cpu_data[0].options & MIPS_CPU_LPA) +#endif +#ifndef cpu_has_mvh +#define cpu_has_mvh (cpu_data[0].options & MIPS_CPU_MVH) +#endif #ifndef cpu_has_xpa -#define cpu_has_xpa (cpu_data[0].options & MIPS_CPU_XPA) +#define cpu_has_xpa (cpu_has_lpa && cpu_has_mvh) #endif #ifndef cpu_has_vtag_icache #define cpu_has_vtag_icache (cpu_data[0].icache.flags & MIPS_CACHE_VTAG) diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index d9150a210df6..f6cecc52a8c6 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -394,7 +394,7 @@ enum cpu_type_enum { #define MIPS_CPU_MAAR MBIT_ULL(30) /* MAAR(I) registers are present */ #define MIPS_CPU_FRE MBIT_ULL(31) /* FRE & UFE bits implemented */ #define MIPS_CPU_RW_LLB MBIT_ULL(32) /* LLADDR/LLB writes are allowed */ -#define MIPS_CPU_XPA MBIT_ULL(33) /* CPU supports Extended Physical Addressing */ +#define MIPS_CPU_LPA MBIT_ULL(33) /* CPU supports Large Physical Addressing */ #define MIPS_CPU_CDMM MBIT_ULL(34) /* CPU has Common Device Memory Map */ #define MIPS_CPU_BP_GHIST MBIT_ULL(35) /* R12K+ Branch Prediction Global History */ #define MIPS_CPU_SP MBIT_ULL(36) /* Small (1KB) page support */ @@ -403,6 +403,7 @@ enum cpu_type_enum { #define MIPS_CPU_NAN_2008 MBIT_ULL(39) /* 2008 NaN implemented */ #define MIPS_CPU_VP MBIT_ULL(40) /* MIPSr6 Virtual Processors (multi-threading) */ #define MIPS_CPU_LDPTE MBIT_ULL(41) /* CPU has ldpte/lddir instructions */ +#define MIPS_CPU_MVH MBIT_ULL(42) /* CPU supports MFHC0/MTHC0 */ /* * CPU ASE encodings diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 5ca4fefb1344..8eda42a9ca59 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -702,6 +702,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->options |= MIPS_CPU_VINT; if (config3 & MIPS_CONF3_VEIC) c->options |= MIPS_CPU_VEIC; + if (config3 & MIPS_CONF3_LPA) + c->options |= MIPS_CPU_LPA; if (config3 & MIPS_CONF3_MT) c->ases |= MIPS_ASE_MIPSMT; if (config3 & MIPS_CONF3_ULRI) -- cgit v1.2.3 From 253f0d4a5fdcba9367b83df7fb504407efc20ec2 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:01 +0100 Subject: MIPS: Remove redundant asm/pgtable-bits.h inclusions asm/pgtable-bits.h is included in 2 assembly files and thus has to ifdef around C code, however nothing defined by the header is used in either of the assembly files that include it. Remove the redundant inclusions such that asm/pgtable-bits.h doesn't need to #ifdef around C code, for cleanliness and in preparation for later patches which will add more C. Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: Maciej W. Rozycki Cc: Jonas Gorski Cc: Alex Smith Cc: Kirill A. Shutemov Cc: Andrew Morton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13114/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable-bits.h | 2 -- arch/mips/kernel/head.S | 1 - arch/mips/kernel/r4k_switch.S | 1 - 3 files changed, 4 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index 97b313882678..2f4031209d54 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h @@ -191,7 +191,6 @@ */ -#ifndef __ASSEMBLY__ /* * pte_to_entrylo converts a page table entry (PTE) into a Mips * entrylo0/1 value. @@ -218,7 +217,6 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val) return pte_val >> _PAGE_GLOBAL_SHIFT; } -#endif /* * Cache attributes diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 7dc043349d66..56e8fede3fd8 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 92cd0516ecf5..2f0a3b223c97 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 694977006a7ba71e33e1f5df4f66ffd5ae19ec84 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:02 +0100 Subject: MIPS: Use enums to make asm/pgtable-bits.h readable asm/pgtable-bits.h has grown to become an unreadable mess of #ifdef directives defining bits conditionally upon other bits all at the preprocessing stage, for no good reason. Instead of having quite so many #ifdef's, simply use enums to provide sequential numbering for bit shifts, without having to keep track manually of what the last bit defined was. Masks are defined separately, after the shifts, which allows for most of their definitions to be reused for all systems rather than duplicated. This patch is not intended to make any behavioural change to the code - all bits should be used in the same way they were before this patch. Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: Maciej W. Rozycki Cc: Alex Smith Cc: Kirill A. Shutemov Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13115/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable-bits.h | 189 +++++++++++++++-------------------- 1 file changed, 81 insertions(+), 108 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index 2f4031209d54..c81fc1703c8a 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h @@ -35,36 +35,25 @@ #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) /* - * The following bits are implemented by the TLB hardware + * Page table bit offsets used for 64 bit physical addressing on MIPS32, + * for example with Alchemy, Netlogic XLP/XLR or XPA. */ -#define _PAGE_NO_EXEC_SHIFT 0 -#define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) -#define _PAGE_NO_READ_SHIFT (_PAGE_NO_EXEC_SHIFT + 1) -#define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) -#define _PAGE_GLOBAL_SHIFT (_PAGE_NO_READ_SHIFT + 1) -#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) -#define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1) -#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) -#define _PAGE_DIRTY_SHIFT (_PAGE_VALID_SHIFT + 1) -#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) -#define _CACHE_SHIFT (_PAGE_DIRTY_SHIFT + 1) -#define _CACHE_MASK (7 << _CACHE_SHIFT) - -/* - * The following bits are implemented in software - */ -#define _PAGE_PRESENT_SHIFT (24) -#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) -#define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1) -#define _PAGE_READ (1 << _PAGE_READ_SHIFT) -#define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) -#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) -#define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) -#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) -#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) -#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) - -#define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) +enum pgtable_bits { + /* Used by TLB hardware (placed in EntryLo*) */ + _PAGE_NO_EXEC_SHIFT, + _PAGE_NO_READ_SHIFT, + _PAGE_GLOBAL_SHIFT, + _PAGE_VALID_SHIFT, + _PAGE_DIRTY_SHIFT, + _CACHE_SHIFT, + + /* Used only by software (masked out before writing EntryLo*) */ + _PAGE_PRESENT_SHIFT = 24, + _PAGE_READ_SHIFT, + _PAGE_WRITE_SHIFT, + _PAGE_ACCESSED_SHIFT, + _PAGE_MODIFIED_SHIFT, +}; /* * Bits for extended EntryLo0/EntryLo1 registers @@ -73,101 +62,85 @@ #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) -/* - * The following bits are implemented in software - */ -#define _PAGE_PRESENT_SHIFT (0) -#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) -#define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1) -#define _PAGE_READ (1 << _PAGE_READ_SHIFT) -#define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) -#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) -#define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) -#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) -#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) -#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) +/* Page table bits used for r3k systems */ +enum pgtable_bits { + /* Used only by software (writes to EntryLo ignored) */ + _PAGE_PRESENT_SHIFT, + _PAGE_READ_SHIFT, + _PAGE_WRITE_SHIFT, + _PAGE_ACCESSED_SHIFT, + _PAGE_MODIFIED_SHIFT, + + /* Used by TLB hardware (placed in EntryLo) */ + _PAGE_GLOBAL_SHIFT = 8, + _PAGE_VALID_SHIFT, + _PAGE_DIRTY_SHIFT, + _CACHE_UNCACHED_SHIFT, +}; -/* - * The following bits are implemented by the TLB hardware - */ -#define _PAGE_GLOBAL_SHIFT (_PAGE_MODIFIED_SHIFT + 4) -#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) -#define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1) -#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) -#define _PAGE_DIRTY_SHIFT (_PAGE_VALID_SHIFT + 1) -#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) -#define _CACHE_UNCACHED_SHIFT (_PAGE_DIRTY_SHIFT + 1) -#define _CACHE_UNCACHED (1 << _CACHE_UNCACHED_SHIFT) -#define _CACHE_MASK _CACHE_UNCACHED +#else -#define _PFN_SHIFT PAGE_SHIFT +/* Page table bits used for r4k systems */ +enum pgtable_bits { + /* Used only by software (masked out before writing EntryLo*) */ + _PAGE_PRESENT_SHIFT, +#if !defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_MIPSR6) + _PAGE_READ_SHIFT, +#endif + _PAGE_WRITE_SHIFT, + _PAGE_ACCESSED_SHIFT, + _PAGE_MODIFIED_SHIFT, +#if defined(CONFIG_64BIT) && defined(CONFIG_MIPS_HUGE_TLB_SUPPORT) + _PAGE_HUGE_SHIFT, +#endif -#else -/* - * Below are the "Normal" R4K cases - */ + /* Used by TLB hardware (placed in EntryLo*) */ +#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) + _PAGE_NO_EXEC_SHIFT, + _PAGE_NO_READ_SHIFT, + _PAGE_READ_SHIFT = _PAGE_NO_READ_SHIFT, +#endif + _PAGE_GLOBAL_SHIFT, + _PAGE_VALID_SHIFT, + _PAGE_DIRTY_SHIFT, + _CACHE_SHIFT, +}; -/* - * The following bits are implemented in software - */ -#define _PAGE_PRESENT_SHIFT 0 +#endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */ + +/* Used only by software */ #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) -/* R2 or later cores check for RI/XI support to determine _PAGE_READ */ #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) -#define _PAGE_WRITE_SHIFT (_PAGE_PRESENT_SHIFT + 1) -#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) +# define _PAGE_READ (cpu_has_rixi ? 0 : (1 << _PAGE_READ_SHIFT)) #else -#define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1) -#define _PAGE_READ (1 << _PAGE_READ_SHIFT) -#define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) -#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) +# define _PAGE_READ (1 << _PAGE_READ_SHIFT) #endif -#define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) +#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) -#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) - #if defined(CONFIG_64BIT) && defined(CONFIG_MIPS_HUGE_TLB_SUPPORT) -/* Huge TLB page */ -#define _PAGE_HUGE_SHIFT (_PAGE_MODIFIED_SHIFT + 1) -#define _PAGE_HUGE (1 << _PAGE_HUGE_SHIFT) -#endif /* CONFIG_64BIT && CONFIG_MIPS_HUGE_TLB_SUPPORT */ - -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) -/* XI - page cannot be executed */ -#ifdef _PAGE_HUGE_SHIFT -#define _PAGE_NO_EXEC_SHIFT (_PAGE_HUGE_SHIFT + 1) -#else -#define _PAGE_NO_EXEC_SHIFT (_PAGE_MODIFIED_SHIFT + 1) +# define _PAGE_HUGE (1 << _PAGE_HUGE_SHIFT) #endif -#define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) - -/* RI - page cannot be read */ -#define _PAGE_READ_SHIFT (_PAGE_NO_EXEC_SHIFT + 1) -#define _PAGE_READ (cpu_has_rixi ? 0 : (1 << _PAGE_READ_SHIFT)) -#define _PAGE_NO_READ_SHIFT _PAGE_READ_SHIFT -#define _PAGE_NO_READ (cpu_has_rixi ? (1 << _PAGE_READ_SHIFT) : 0) -#endif /* defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) */ - -#if defined(_PAGE_NO_READ_SHIFT) -#define _PAGE_GLOBAL_SHIFT (_PAGE_NO_READ_SHIFT + 1) -#elif defined(_PAGE_HUGE_SHIFT) -#define _PAGE_GLOBAL_SHIFT (_PAGE_HUGE_SHIFT + 1) -#else -#define _PAGE_GLOBAL_SHIFT (_PAGE_MODIFIED_SHIFT + 1) + +/* Used by TLB hardware (placed in EntryLo*) */ +#if (defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)) +# define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) +# define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) +#elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +# define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) +# define _PAGE_NO_READ (cpu_has_rixi ? (1 << _PAGE_NO_READ_SHIFT) : 0) #endif #define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) - -#define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1) #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) -#define _PAGE_DIRTY_SHIFT (_PAGE_VALID_SHIFT + 1) #define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) -#define _CACHE_SHIFT (_PAGE_DIRTY_SHIFT + 1) -#define _CACHE_MASK (7 << _CACHE_SHIFT) - -#define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) - -#endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */ +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) +# define _CACHE_UNCACHED (1 << _CACHE_UNCACHED_SHIFT) +# define _CACHE_MASK _CACHE_UNCACHED +# define _PFN_SHIFT PAGE_SHIFT +#else +# define _CACHE_MASK (7 << _CACHE_SHIFT) +# define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) +#endif #ifndef _PAGE_NO_EXEC #define _PAGE_NO_EXEC 0 -- cgit v1.2.3 From 780602d740fc0b723ea3a05bd7f35d2d7f31aa68 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:03 +0100 Subject: MIPS: mm: Standardise on _PAGE_NO_READ, drop _PAGE_READ Ever since support for RI/XI was implemented by commit 6dd9344cfc41 ("MIPS: Implement Read Inhibit/eXecute Inhibit") we've had a mixture of _PAGE_READ & _PAGE_NO_READ bits. Rather than keep both around, switch away from using _PAGE_READ to determine page presence & instead invert the use to _PAGE_NO_READ. Wherever we formerly had no definition for _PAGE_NO_READ, change what was _PAGE_READ to _PAGE_NO_READ. The end result is that we consistently use _PAGE_NO_READ to determine whether a page is readable, regardless of whether RI/XI is implemented. Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: David Daney Cc: Huacai Chen Cc: Maciej W. Rozycki Cc: Paul Gortmaker Cc: Aneesh Kumar K.V Cc: Andrew Morton Cc: Alex Smith Cc: Kirill A. Shutemov Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13116/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable-bits.h | 19 ++++--------------- arch/mips/include/asm/pgtable.h | 23 +++++++---------------- arch/mips/mm/tlbex.c | 13 ++++--------- 3 files changed, 15 insertions(+), 40 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index c81fc1703c8a..5bc663d330d2 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h @@ -49,7 +49,6 @@ enum pgtable_bits { /* Used only by software (masked out before writing EntryLo*) */ _PAGE_PRESENT_SHIFT = 24, - _PAGE_READ_SHIFT, _PAGE_WRITE_SHIFT, _PAGE_ACCESSED_SHIFT, _PAGE_MODIFIED_SHIFT, @@ -66,7 +65,7 @@ enum pgtable_bits { enum pgtable_bits { /* Used only by software (writes to EntryLo ignored) */ _PAGE_PRESENT_SHIFT, - _PAGE_READ_SHIFT, + _PAGE_NO_READ_SHIFT, _PAGE_WRITE_SHIFT, _PAGE_ACCESSED_SHIFT, _PAGE_MODIFIED_SHIFT, @@ -85,7 +84,7 @@ enum pgtable_bits { /* Used only by software (masked out before writing EntryLo*) */ _PAGE_PRESENT_SHIFT, #if !defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_MIPSR6) - _PAGE_READ_SHIFT, + _PAGE_NO_READ_SHIFT, #endif _PAGE_WRITE_SHIFT, _PAGE_ACCESSED_SHIFT, @@ -98,7 +97,6 @@ enum pgtable_bits { #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) _PAGE_NO_EXEC_SHIFT, _PAGE_NO_READ_SHIFT, - _PAGE_READ_SHIFT = _PAGE_NO_READ_SHIFT, #endif _PAGE_GLOBAL_SHIFT, _PAGE_VALID_SHIFT, @@ -110,11 +108,6 @@ enum pgtable_bits { /* Used only by software */ #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) -# define _PAGE_READ (cpu_has_rixi ? 0 : (1 << _PAGE_READ_SHIFT)) -#else -# define _PAGE_READ (1 << _PAGE_READ_SHIFT) -#endif #define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) @@ -125,11 +118,10 @@ enum pgtable_bits { /* Used by TLB hardware (placed in EntryLo*) */ #if (defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)) # define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) -# define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) #elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) # define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) -# define _PAGE_NO_READ (cpu_has_rixi ? (1 << _PAGE_NO_READ_SHIFT) : 0) #endif +#define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) #define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) #define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) @@ -145,9 +137,6 @@ enum pgtable_bits { #ifndef _PAGE_NO_EXEC #define _PAGE_NO_EXEC 0 #endif -#ifndef _PAGE_NO_READ -#define _PAGE_NO_READ 0 -#endif #define _PAGE_SILENT_READ _PAGE_VALID #define _PAGE_SILENT_WRITE _PAGE_DIRTY @@ -245,7 +234,7 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val) #define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT) #endif -#define __READABLE (_PAGE_SILENT_READ | _PAGE_READ | _PAGE_ACCESSED) +#define __READABLE (_PAGE_SILENT_READ | _PAGE_ACCESSED) #define __WRITEABLE (_PAGE_SILENT_WRITE | _PAGE_WRITE | _PAGE_MODIFIED) #define _PAGE_CHG_MASK (_PAGE_ACCESSED | _PAGE_MODIFIED | \ diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 7f422500b65d..f6de4f49b1b2 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -23,18 +23,19 @@ struct mm_struct; struct vm_area_struct; -#define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT) -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | \ +#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_NO_READ | \ + _CACHE_CACHABLE_NONCOHERENT) +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_WRITE | \ _page_cachable_default) -#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_NO_EXEC | \ +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC | \ _page_cachable_default) -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | \ _page_cachable_default) #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ _PAGE_GLOBAL | _page_cachable_default) #define PAGE_KERNEL_NC __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ _PAGE_GLOBAL | _CACHE_CACHABLE_NONCOHERENT) -#define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ +#define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_WRITE | \ _page_cachable_default) #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \ __WRITEABLE | _PAGE_GLOBAL | _CACHE_UNCACHED) @@ -338,7 +339,7 @@ static inline pte_t pte_mkdirty(pte_t pte) static inline pte_t pte_mkyoung(pte_t pte) { pte.pte_low |= _PAGE_ACCESSED; - if (pte.pte_low & _PAGE_READ) + if (!(pte.pte_low & _PAGE_NO_READ)) pte.pte_high |= _PAGE_SILENT_READ; return pte; } @@ -384,13 +385,8 @@ static inline pte_t pte_mkdirty(pte_t pte) static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_CPU_LOONGSON3) if (!(pte_val(pte) & _PAGE_NO_READ)) pte_val(pte) |= _PAGE_SILENT_READ; - else -#endif - if (pte_val(pte) & _PAGE_READ) - pte_val(pte) |= _PAGE_SILENT_READ; return pte; } @@ -570,13 +566,8 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd) { pmd_val(pmd) |= _PAGE_ACCESSED; -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_CPU_LOONGSON3) if (!(pmd_val(pmd) & _PAGE_NO_READ)) pmd_val(pmd) |= _PAGE_SILENT_READ; - else -#endif - if (pmd_val(pmd) & _PAGE_READ) - pmd_val(pmd) |= _PAGE_SILENT_READ; return pmd; } diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index baad605db878..67966f30c522 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -234,20 +234,16 @@ static void output_pgtable_bits_defines(void) pr_debug("\n"); pr_define("_PAGE_PRESENT_SHIFT %d\n", _PAGE_PRESENT_SHIFT); - pr_define("_PAGE_READ_SHIFT %d\n", _PAGE_READ_SHIFT); + pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT); pr_define("_PAGE_WRITE_SHIFT %d\n", _PAGE_WRITE_SHIFT); pr_define("_PAGE_ACCESSED_SHIFT %d\n", _PAGE_ACCESSED_SHIFT); pr_define("_PAGE_MODIFIED_SHIFT %d\n", _PAGE_MODIFIED_SHIFT); #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT); #endif -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) - if (cpu_has_rixi) { #ifdef _PAGE_NO_EXEC_SHIFT + if (cpu_has_rixi) pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT); - pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT); -#endif - } #endif pr_define("_PAGE_GLOBAL_SHIFT %d\n", _PAGE_GLOBAL_SHIFT); pr_define("_PAGE_VALID_SHIFT %d\n", _PAGE_VALID_SHIFT); @@ -1728,9 +1724,8 @@ build_pte_present(u32 **p, struct uasm_reloc **r, cur = t; } uasm_i_andi(p, t, cur, - (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); - uasm_i_xori(p, t, t, - (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); + (_PAGE_PRESENT | _PAGE_NO_READ) >> _PAGE_PRESENT_SHIFT); + uasm_i_xori(p, t, t, _PAGE_PRESENT >> _PAGE_PRESENT_SHIFT); uasm_il_bnez(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ -- cgit v1.2.3 From 745f35587846249b392aa548b4c5f54cd69ed688 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:04 +0100 Subject: MIPS: mm: Unify pte_page definition The same definition for pte_page is duplicated for the MIPS32 PHYS_ADDR_T_64BIT case & the generic case. Unify them by moving a single definition outside of preprocessor conditionals. Signed-off-by: Paul Burton Reviewed-by: James Hogan Cc: Paul Gortmaker Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13117/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable-32.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index 832e2167d00f..181bd8e7db7d 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h @@ -104,7 +104,7 @@ static inline void pmd_clear(pmd_t *pmdp) } #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) -#define pte_page(x) pfn_to_page(pte_pfn(x)) + #define pte_pfn(x) (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT)) static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) @@ -120,8 +120,6 @@ pfn_pte(unsigned long pfn, pgprot_t prot) #else -#define pte_page(x) pfn_to_page(pte_pfn(x)) - #ifdef CONFIG_CPU_VR41XX #define pte_pfn(x) ((unsigned long)((x).pte >> (PAGE_SHIFT + 2))) #define pfn_pte(pfn, prot) __pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot)) @@ -131,6 +129,8 @@ pfn_pte(unsigned long pfn, pgprot_t prot) #endif #endif /* defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) */ +#define pte_page(x) pfn_to_page(pte_pfn(x)) + #define __pgd_offset(address) pgd_index(address) #define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) #define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) -- cgit v1.2.3 From 7b2cb64f91f25a7293b10054e20d1c0734ffab6f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 19 Apr 2016 09:25:05 +0100 Subject: MIPS: mm: Fix MIPS32 36b physical addressing (alchemy, netlogic) There are 2 distinct cases in which a kernel for a MIPS32 CPU (CONFIG_CPU_MIPS32=y) may use 64 bit physical addresses (CONFIG_PHYS_ADDR_T_64BIT=y): - 36 bit physical addressing as used by RMI Alchemy & Netlogic XLP/XLR CPUs. - MIPS32r5 eXtended Physical Addressing (XPA). These 2 cases are distinct in that they require different behaviour from the kernel - the EntryLo registers have different formats. Until Linux v4.1 we only supported the first case, with code conditional upon the 2 aforementioned Kconfig variables being set. Commit c5b367835cfc ("MIPS: Add support for XPA.") added support for the second case, but did so by modifying the code that existed for the first case rather than treating the 2 cases as distinct. Since the EntryLo registers have different formats this breaks the 36 bit Alchemy/XLP/XLR case. Fix this by splitting the 2 cases, with XPA cases now being conditional upon CONFIG_XPA and the non-XPA case matching the code as it existed prior to commit c5b367835cfc ("MIPS: Add support for XPA."). Signed-off-by: Paul Burton Reported-by: Manuel Lauss Tested-by: Manuel Lauss Fixes: c5b367835cfc ("MIPS: Add support for XPA.") Cc: James Hogan Cc: David Daney Cc: Huacai Chen Cc: Maciej W. Rozycki Cc: Paul Gortmaker Cc: Aneesh Kumar K.V Cc: Peter Zijlstra (Intel) Cc: David Hildenbrand Cc: Andrew Morton Cc: Ingo Molnar Cc: Alex Smith Cc: Kirill A. Shutemov Cc: stable@vger.kernel.org # v4.1+ Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13119/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable-32.h | 27 +++++++++++++++-- arch/mips/include/asm/pgtable-bits.h | 29 +++++++++++++++--- arch/mips/include/asm/pgtable.h | 57 +++++++++++++++++++++++++++++++----- arch/mips/mm/init.c | 4 ++- arch/mips/mm/tlbex.c | 35 ++++++++++++++-------- 5 files changed, 125 insertions(+), 27 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index 181bd8e7db7d..d21f3da7bdb6 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h @@ -103,7 +103,7 @@ static inline void pmd_clear(pmd_t *pmdp) pmd_val(*pmdp) = ((unsigned long) invalid_pte_table); } -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +#if defined(CONFIG_XPA) #define pte_pfn(x) (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT)) static inline pte_t @@ -118,6 +118,20 @@ pfn_pte(unsigned long pfn, pgprot_t prot) return pte; } +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) + +#define pte_pfn(x) ((unsigned long)((x).pte_high >> 6)) + +static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) +{ + pte_t pte; + + pte.pte_high = (pfn << 6) | (pgprot_val(prot) & 0x3f); + pte.pte_low = pgprot_val(prot); + + return pte; +} + #else #ifdef CONFIG_CPU_VR41XX @@ -166,7 +180,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot) #else -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +#if defined(CONFIG_XPA) /* Swap entries must have VALID and GLOBAL bits cleared. */ #define __swp_type(x) (((x).val >> 4) & 0x1f) @@ -175,6 +189,15 @@ pfn_pte(unsigned long pfn, pgprot_t prot) #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) #define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) + +/* Swap entries must have VALID and GLOBAL bits cleared. */ +#define __swp_type(x) (((x).val >> 2) & 0x1f) +#define __swp_offset(x) ((x).val >> 7) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 7) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) +#define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) + #else /* * Constraints: diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index 5bc663d330d2..58e8bf815404 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h @@ -32,11 +32,11 @@ * unpredictable things. The code (when it is written) to deal with * this problem will be in the update_mmu_cache() code for the r4k. */ -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +#if defined(CONFIG_XPA) /* - * Page table bit offsets used for 64 bit physical addressing on MIPS32, - * for example with Alchemy, Netlogic XLP/XLR or XPA. + * Page table bit offsets used for 64 bit physical addressing on + * MIPS32r5 with XPA. */ enum pgtable_bits { /* Used by TLB hardware (placed in EntryLo*) */ @@ -59,6 +59,27 @@ enum pgtable_bits { */ #define _PFNX_MASK 0xffffff +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) + +/* + * Page table bit offsets used for 36 bit physical addressing on MIPS32, + * for example with Alchemy or Netlogic XLP/XLR. + */ +enum pgtable_bits { + /* Used by TLB hardware (placed in EntryLo*) */ + _PAGE_GLOBAL_SHIFT, + _PAGE_VALID_SHIFT, + _PAGE_DIRTY_SHIFT, + _CACHE_SHIFT, + + /* Used only by software (masked out before writing EntryLo*) */ + _PAGE_PRESENT_SHIFT = _CACHE_SHIFT + 3, + _PAGE_NO_READ_SHIFT, + _PAGE_WRITE_SHIFT, + _PAGE_ACCESSED_SHIFT, + _PAGE_MODIFIED_SHIFT, +}; + #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) /* Page table bits used for r3k systems */ @@ -116,7 +137,7 @@ enum pgtable_bits { #endif /* Used by TLB hardware (placed in EntryLo*) */ -#if (defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)) +#if defined(CONFIG_XPA) # define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) #elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) # define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index f6de4f49b1b2..e07a105cafc2 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -133,7 +133,12 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) -#define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) +#ifdef CONFIG_XPA +# define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) +#else +# define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL)) +#endif + #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) #define pte_no_exec(pte) ((pte).pte_low & _PAGE_NO_EXEC) @@ -143,14 +148,21 @@ static inline void set_pte(pte_t *ptep, pte_t pte) smp_wmb(); ptep->pte_low = pte.pte_low; +#ifdef CONFIG_XPA if (pte.pte_high & _PAGE_GLOBAL) { +#else + if (pte.pte_low & _PAGE_GLOBAL) { +#endif pte_t *buddy = ptep_buddy(ptep); /* * Make sure the buddy is global too (if it's !none, * it better already be global) */ - if (pte_none(*buddy)) + if (pte_none(*buddy)) { + if (!config_enabled(CONFIG_XPA)) + buddy->pte_low |= _PAGE_GLOBAL; buddy->pte_high |= _PAGE_GLOBAL; + } } } @@ -160,8 +172,13 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt htw_stop(); /* Preserve global status for the pair */ - if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL) - null.pte_high = _PAGE_GLOBAL; + if (config_enabled(CONFIG_XPA)) { + if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL) + null.pte_high = _PAGE_GLOBAL; + } else { + if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL) + null.pte_low = null.pte_high = _PAGE_GLOBAL; + } set_pte_at(mm, addr, ptep, null); htw_start(); @@ -302,6 +319,8 @@ static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; } static inline pte_t pte_wrprotect(pte_t pte) { pte.pte_low &= ~_PAGE_WRITE; + if (!config_enabled(CONFIG_XPA)) + pte.pte_low &= ~_PAGE_SILENT_WRITE; pte.pte_high &= ~_PAGE_SILENT_WRITE; return pte; } @@ -309,6 +328,8 @@ static inline pte_t pte_wrprotect(pte_t pte) static inline pte_t pte_mkclean(pte_t pte) { pte.pte_low &= ~_PAGE_MODIFIED; + if (!config_enabled(CONFIG_XPA)) + pte.pte_low &= ~_PAGE_SILENT_WRITE; pte.pte_high &= ~_PAGE_SILENT_WRITE; return pte; } @@ -316,6 +337,8 @@ static inline pte_t pte_mkclean(pte_t pte) static inline pte_t pte_mkold(pte_t pte) { pte.pte_low &= ~_PAGE_ACCESSED; + if (!config_enabled(CONFIG_XPA)) + pte.pte_low &= ~_PAGE_SILENT_READ; pte.pte_high &= ~_PAGE_SILENT_READ; return pte; } @@ -323,24 +346,33 @@ static inline pte_t pte_mkold(pte_t pte) static inline pte_t pte_mkwrite(pte_t pte) { pte.pte_low |= _PAGE_WRITE; - if (pte.pte_low & _PAGE_MODIFIED) + if (pte.pte_low & _PAGE_MODIFIED) { + if (!config_enabled(CONFIG_XPA)) + pte.pte_low |= _PAGE_SILENT_WRITE; pte.pte_high |= _PAGE_SILENT_WRITE; + } return pte; } static inline pte_t pte_mkdirty(pte_t pte) { pte.pte_low |= _PAGE_MODIFIED; - if (pte.pte_low & _PAGE_WRITE) + if (pte.pte_low & _PAGE_WRITE) { + if (!config_enabled(CONFIG_XPA)) + pte.pte_low |= _PAGE_SILENT_WRITE; pte.pte_high |= _PAGE_SILENT_WRITE; + } return pte; } static inline pte_t pte_mkyoung(pte_t pte) { pte.pte_low |= _PAGE_ACCESSED; - if (!(pte.pte_low & _PAGE_NO_READ)) + if (!(pte.pte_low & _PAGE_NO_READ)) { + if (!config_enabled(CONFIG_XPA)) + pte.pte_low |= _PAGE_SILENT_READ; pte.pte_high |= _PAGE_SILENT_READ; + } return pte; } #else @@ -438,7 +470,7 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _prot) */ #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +#if defined(CONFIG_XPA) static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte.pte_low &= (_PAGE_MODIFIED | _PAGE_ACCESSED | _PFNX_MASK); @@ -447,6 +479,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) pte.pte_high |= pgprot_val(newprot) & ~_PFN_MASK; return pte; } +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + pte.pte_low &= _PAGE_CHG_MASK; + pte.pte_high &= (_PFN_MASK | _CACHE_MASK); + pte.pte_low |= pgprot_val(newprot); + pte.pte_high |= pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK); + return pte; +} #else static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 6c6a843b0d17..134c988bc61f 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -98,8 +98,10 @@ static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot) idx += in_interrupt() ? FIX_N_COLOURS : 0; vaddr = __fix_to_virt(FIX_CMAP_END - idx); pte = mk_pte(page, prot); -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +#if defined(CONFIG_XPA) entrylo = pte_to_entrylo(pte.pte_high); +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) + entrylo = pte.pte_high; #else entrylo = pte_to_entrylo(pte_val(pte)); #endif diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 67966f30c522..db4adf9cc65c 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1011,25 +1011,21 @@ static void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) { - /* - * 64bit address support (36bit on a 32bit CPU) in a 32bit - * Kernel is a special case. Only a few CPUs use it. - */ - if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) { + if (config_enabled(CONFIG_XPA)) { int pte_off_even = sizeof(pte_t) / 2; int pte_off_odd = pte_off_even + sizeof(pte_t); -#ifdef CONFIG_XPA const int scratch = 1; /* Our extra working register */ uasm_i_addu(p, scratch, 0, ptep); -#endif + uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ - uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); - UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); UASM_i_MTC0(p, tmp, C0_ENTRYLO0); + + uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ + UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); UASM_i_MTC0(p, ptep, C0_ENTRYLO1); -#ifdef CONFIG_XPA + uasm_i_lw(p, tmp, 0, scratch); uasm_i_lw(p, ptep, sizeof(pte_t), scratch); uasm_i_lui(p, scratch, 0xff); @@ -1038,7 +1034,22 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) uasm_i_and(p, ptep, scratch, ptep); uasm_i_mthc0(p, tmp, C0_ENTRYLO0); uasm_i_mthc0(p, ptep, C0_ENTRYLO1); -#endif + return; + } + + /* + * 64bit address support (36bit on a 32bit CPU) in a 32bit + * Kernel is a special case. Only a few CPUs use it. + */ + if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) { + int pte_off_even = sizeof(pte_t) / 2; + int pte_off_odd = pte_off_even + sizeof(pte_t); + + uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ + UASM_i_MTC0(p, tmp, C0_ENTRYLO0); + + uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ + UASM_i_MTC0(p, ptep, C0_ENTRYLO1); return; } @@ -1637,7 +1648,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, #ifdef CONFIG_PHYS_ADDR_T_64BIT unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY); - if (!cpu_has_64bits) { + if (config_enabled(CONFIG_XPA) && !cpu_has_64bits) { const int scratch = 1; /* Our extra working register */ uasm_i_lui(p, scratch, (mode >> 16)); -- cgit v1.2.3 From 8256b17ecb028949d80c982d0f28ad46fe4e73d8 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 9 Feb 2016 12:55:51 -0800 Subject: MIPS: Allow RIXI to be used on non-R2 or R6 cores Some processors, like Broadcom's BMIPS4380 and BMIPS5000 support RIXI and the "rotr" instruction, which can be used to get a slightly more efficient page table layout. Introduce a CONFIG_CPU_HAS_RIXI such that those cores can benefit from this feature. Perform the conditional check updates where relevant. Signed-off-by: Florian Fainelli Cc: john@phrozen.org Cc: cernekee@gmail.com Cc: jon.fraser@broadcom.com Cc: pgynther@google.com Cc: paul.burton@imgtec.com Cc: ddaney.cavm@gmail.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12505/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 5 +++++ arch/mips/include/asm/pgtable-bits.h | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index d10ed57ad418..5562ee535db8 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1996,11 +1996,13 @@ config CPU_MIPSR1 config CPU_MIPSR2 bool default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON + select CPU_HAS_RIXI select MIPS_SPRAM config CPU_MIPSR6 bool default y if CPU_MIPS32_R6 || CPU_MIPS64_R6 + select CPU_HAS_RIXI select HAVE_ARCH_BITREVERSE select MIPS_ASID_BITS_VARIABLE select MIPS_SPRAM @@ -2421,6 +2423,9 @@ config CPU_HAS_WB config XKS01 bool +config CPU_HAS_RIXI + bool + # # Vectored interrupt mode is an R2 feature # diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index 58e8bf815404..f88a48cd68b2 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h @@ -104,7 +104,7 @@ enum pgtable_bits { enum pgtable_bits { /* Used only by software (masked out before writing EntryLo*) */ _PAGE_PRESENT_SHIFT, -#if !defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_MIPSR6) +#if !defined(CONFIG_CPU_HAS_RIXI) _PAGE_NO_READ_SHIFT, #endif _PAGE_WRITE_SHIFT, @@ -115,7 +115,7 @@ enum pgtable_bits { #endif /* Used by TLB hardware (placed in EntryLo*) */ -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +#if defined(CONFIG_CPU_HAS_RIXI) _PAGE_NO_EXEC_SHIFT, _PAGE_NO_READ_SHIFT, #endif @@ -139,7 +139,7 @@ enum pgtable_bits { /* Used by TLB hardware (placed in EntryLo*) */ #if defined(CONFIG_XPA) # define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) -#elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +#elif defined(CONFIG_CPU_HAS_RIXI) # define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) #endif #define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) @@ -180,7 +180,7 @@ enum pgtable_bits { */ static inline uint64_t pte_to_entrylo(unsigned long pte_val) { -#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) +#ifdef CONFIG_CPU_HAS_RIXI if (cpu_has_rixi) { int sa; #ifdef CONFIG_32BIT -- cgit v1.2.3 From 37af2f3077d9202f8f8d17f453c91c9d08e11c76 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 13:50:49 +0100 Subject: MIPS: Define & use CP0_EBase bit definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add definitions for the bits & fields in the CP0_EBase register, and use them from a few different places in arch/mips which hardcoded these values. Signed-off-by: James Hogan Cc: Jayachandran C Cc: Paolo Bonzini Cc: Radim Krčmář Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13222/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 10 +++++++++- arch/mips/kvm/trap_emul.c | 3 ++- arch/mips/netlogic/xlp/nlm_hal.c | 2 +- arch/mips/netlogic/xlr/setup.c | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index b7705ef09df2..57d72f2bf745 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -676,6 +676,14 @@ #define MIPS_MAAR_S (_ULCAST_(1) << 1) #define MIPS_MAAR_V (_ULCAST_(1) << 0) +/* EBase bit definitions */ +#define MIPS_EBASE_CPUNUM_SHIFT 0 +#define MIPS_EBASE_CPUNUM (_ULCAST_(0x3ff) << 0) +#define MIPS_EBASE_WG_SHIFT 11 +#define MIPS_EBASE_WG (_ULCAST_(1) << 11) +#define MIPS_EBASE_BASE_SHIFT 12 +#define MIPS_EBASE_BASE (~_ULCAST_((1 << MIPS_EBASE_BASE_SHIFT) - 1)) + /* CMGCRBase bit definitions */ #define MIPS_CMGCRB_BASE 11 #define MIPS_CMGCRF_BASE (~_ULCAST_((1 << MIPS_CMGCRB_BASE) - 1)) @@ -2104,7 +2112,7 @@ __BUILD_SET_C0(brcm_mode) */ static inline unsigned int get_ebase_cpunum(void) { - return read_c0_ebase() & 0x3ff; + return read_c0_ebase() & MIPS_EBASE_CPUNUM; } #endif /* !__ASSEMBLY__ */ diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c index c4038d2a724c..fd43f0afdb9f 100644 --- a/arch/mips/kvm/trap_emul.c +++ b/arch/mips/kvm/trap_emul.c @@ -505,7 +505,8 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu) kvm_write_c0_guest_intctl(cop0, 0xFC000000); /* Put in vcpu id as CPUNum into Ebase Reg to handle SMP Guests */ - kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 | (vcpu_id & 0xFF)); + kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 | + (vcpu_id & MIPS_EBASE_CPUNUM)); return 0; } diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 80ec929747c3..25ee69489e5e 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -58,7 +58,7 @@ void nlm_node_init(int node) nodep->coremask = 1; /* node 0, boot cpu */ nodep->sysbase = nlm_get_sys_regbase(node); nodep->picbase = nlm_get_pic_regbase(node); - nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1)); + nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE; if (cpu_is_xlp9xx()) nodep->socbus = xlp9xx_get_socbus(node); else diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c index d118b9aa7647..72ceddc9a03f 100644 --- a/arch/mips/netlogic/xlr/setup.c +++ b/arch/mips/netlogic/xlr/setup.c @@ -168,7 +168,7 @@ static void nlm_init_node(void) nodep = nlm_current_node(); nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET); - nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1)); + nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE; spin_lock_init(&nodep->piclock); } -- cgit v1.2.3 From 37fb60f8e3f011c25c120081a73886ad8dbc42fd Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 13:50:50 +0100 Subject: MIPS: Add defs & probing of extended CP0_EBase The CP0_EBase register may optionally have a write gate (WG) bit to allow the upper bits to be written, i.e. bits 31:30 on MIPS32 since r3 (to allow for an exception base outside of KSeg0/KSeg1 when segmentation control is in use) and bits 63:30 on MIPS64 (which also implies the extension of CP0_EBase to 64 bits long). The presence of this feature will need to be known about for VZ support in order to correctly save and restore all the bits of the guest CP0_EBase register, so add CPU feature definition and probing for this feature. Probing the WG bit on MIPS64 can be a bit fiddly, since 64-bit COP0 register access instructions were UNDEFINED for 32-bit registers prior to MIPS r6, and it'd be nice to be able to probe without clobbering the existing state, so there are 3 potential paths: - If we do a 32-bit read of CP0_EBase and the WG bit is already set, the register must be 64-bit. - On MIPS r6 we can do a 64-bit read-modify-write to set CP0_EBase.WG, since the upper bits will read 0 and be ignored on write if the register is 32-bit. - On pre-r6 cores, we do a 32-bit read-modify-write of CP0_EBase. This avoids the potentially UNDEFINED behaviour, but will clobber the upper 32-bits of CP0_EBase if it isn't a simple sign extension (which also requires us to ensure BEV=1 or modifying the exception base would be UNDEFINED too). It is hopefully unlikely a bootloader would set up CP0_EBase to a 64-bit segment and leave WG=0. [ralf@linux-mips.org: Resolved merge conflict.] Signed-off-by: James Hogan Tested-by: Matt Redfearn Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13223/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 4 ++++ arch/mips/include/asm/cpu.h | 1 + arch/mips/include/asm/mipsregs.h | 3 +++ arch/mips/kernel/cpu-probe.c | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index bff73c52b273..676a37b9c37e 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -438,4 +438,8 @@ #define cpu_has_nan_2008 (cpu_data[0].options & MIPS_CPU_NAN_2008) #endif +#ifndef cpu_has_ebase_wg +# define cpu_has_ebase_wg (cpu_data[0].options & MIPS_CPU_EBASE_WG) +#endif + #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index f6cecc52a8c6..3108d9b35bf1 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -404,6 +404,7 @@ enum cpu_type_enum { #define MIPS_CPU_VP MBIT_ULL(40) /* MIPSr6 Virtual Processors (multi-threading) */ #define MIPS_CPU_LDPTE MBIT_ULL(41) /* CPU has ldpte/lddir instructions */ #define MIPS_CPU_MVH MBIT_ULL(42) /* CPU supports MFHC0/MTHC0 */ +#define MIPS_CPU_EBASE_WG MBIT_ULL(43) /* CPU has EBase.WG */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 57d72f2bf745..4e8ad9d6038a 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1458,6 +1458,9 @@ do { \ #define read_c0_ebase() __read_32bit_c0_register($15, 1) #define write_c0_ebase(val) __write_32bit_c0_register($15, 1, val) +#define read_c0_ebase_64() __read_64bit_c0_register($15, 1) +#define write_c0_ebase_64(val) __write_64bit_c0_register($15, 1, val) + #define read_c0_cdmmbase() __read_ulong_c0_register($15, 2) #define write_c0_cdmmbase(val) __write_ulong_c0_register($15, 2, val) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 46a24729fbba..6a1a7da4b2d2 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -860,6 +860,41 @@ static void decode_configs(struct cpuinfo_mips *c) if (ok) ok = decode_config5(c); + /* Probe the EBase.WG bit */ + if (cpu_has_mips_r2_r6) { + u64 ebase; + unsigned int status; + + /* {read,write}_c0_ebase_64() may be UNDEFINED prior to r6 */ + ebase = cpu_has_mips64r6 ? read_c0_ebase_64() + : (s32)read_c0_ebase(); + if (ebase & MIPS_EBASE_WG) { + /* WG bit already set, we can avoid the clumsy probe */ + c->options |= MIPS_CPU_EBASE_WG; + } else { + /* Its UNDEFINED to change EBase while BEV=0 */ + status = read_c0_status(); + write_c0_status(status | ST0_BEV); + irq_enable_hazard(); + /* + * On pre-r6 cores, this may well clobber the upper bits + * of EBase. This is hard to avoid without potentially + * hitting UNDEFINED dm*c0 behaviour if EBase is 32-bit. + */ + if (cpu_has_mips64r6) + write_c0_ebase_64(ebase | MIPS_EBASE_WG); + else + write_c0_ebase(ebase | MIPS_EBASE_WG); + back_to_back_c0_hazard(); + /* Restore BEV */ + write_c0_status(status); + if (read_c0_ebase() & MIPS_EBASE_WG) { + c->options |= MIPS_CPU_EBASE_WG; + write_c0_ebase(ebase); + } + } + } + mips_probe_watch_registers(c); #ifndef CONFIG_MIPS_CPS -- cgit v1.2.3 From e06a1548f3043febb658b58ec5ccbc7d03a785af Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 13:50:51 +0100 Subject: MIPS: Add defs & probing of BadInstr[P] registers The optional CP0_BadInstr and CP0_BadInstrP registers are written with the encoding of the instruction that caused a synchronous exception to occur, and the prior branch instruction if in a delay slot. These will be useful for instruction emulation in KVM, and especially for VZ support where reading guest virtual memory is a bit more awkward. Add CPU option numbers and cpu_has_* definitions to indicate the presence of each registers, and add code to probe for them using bits in the CP0_Config3 register. [ralf@linux-mips.org: resolve merge conflict.] Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13224/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 8 ++++++++ arch/mips/include/asm/cpu.h | 2 ++ arch/mips/include/asm/mipsregs.h | 3 +++ arch/mips/kernel/cpu-probe.c | 4 ++++ 4 files changed, 17 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 676a37b9c37e..5d82b01ef8b5 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -442,4 +442,12 @@ # define cpu_has_ebase_wg (cpu_data[0].options & MIPS_CPU_EBASE_WG) #endif +#ifndef cpu_has_badinstr +# define cpu_has_badinstr (cpu_data[0].options & MIPS_CPU_BADINSTR) +#endif + +#ifndef cpu_has_badinstrp +# define cpu_has_badinstrp (cpu_data[0].options & MIPS_CPU_BADINSTRP) +#endif + #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 3108d9b35bf1..0cf90d67c1af 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -405,6 +405,8 @@ enum cpu_type_enum { #define MIPS_CPU_LDPTE MBIT_ULL(41) /* CPU has ldpte/lddir instructions */ #define MIPS_CPU_MVH MBIT_ULL(42) /* CPU supports MFHC0/MTHC0 */ #define MIPS_CPU_EBASE_WG MBIT_ULL(43) /* CPU has EBase.WG */ +#define MIPS_CPU_BADINSTR MBIT_ULL(44) /* CPU has BadInstr register */ +#define MIPS_CPU_BADINSTRP MBIT_ULL(45) /* CPU has BadInstrP register */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 4e8ad9d6038a..b1f8f8436fd1 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1248,6 +1248,9 @@ do { \ #define read_c0_badvaddr() __read_ulong_c0_register($8, 0) #define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val) +#define read_c0_badinstr() __read_32bit_c0_register($8, 1) +#define read_c0_badinstrp() __read_32bit_c0_register($8, 2) + #define read_c0_count() __read_32bit_c0_register($9, 0) #define write_c0_count(val) __write_32bit_c0_register($9, 0, val) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 6a1a7da4b2d2..8e54d51c14bc 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -714,6 +714,10 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->ases |= MIPS_ASE_VZ; if (config3 & MIPS_CONF3_SC) c->options |= MIPS_CPU_SEGMENTS; + if (config3 & MIPS_CONF3_BI) + c->options |= MIPS_CPU_BADINSTR; + if (config3 & MIPS_CONF3_BP) + c->options |= MIPS_CPU_BADINSTRP; if (config3 & MIPS_CONF3_MSA) c->ases |= MIPS_ASE_MSA; if (config3 & MIPS_CONF3_PW) { -- cgit v1.2.3 From f18bdfa191df3947879f93519ce4a4985e5f5fce Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 13:50:52 +0100 Subject: MIPS: Add defs & probing of [X]ContextConfig The CP0_[X]ContextConfig registers are present if CP0_Config3.CTXTC or CP0_Config3.SM are set, and provide more control over which bits of CP0_[X]Context are set to the faulting virtual address on a TLB exception. KVM/VZ will need to be able to save and restore these registers in the guest context, so add the relevant definitions and probing of the ContextConfig feature in the root context first. [ralf@linux-mips.org: resolve merge conflict.] Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13225/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 4 ++++ arch/mips/include/asm/cpu.h | 1 + arch/mips/include/asm/mipsregs.h | 6 ++++++ arch/mips/kernel/cpu-probe.c | 4 +++- 4 files changed, 14 insertions(+), 1 deletion(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 5d82b01ef8b5..7962b257cc16 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -450,4 +450,8 @@ # define cpu_has_badinstrp (cpu_data[0].options & MIPS_CPU_BADINSTRP) #endif +#ifndef cpu_has_contextconfig +# define cpu_has_contextconfig (cpu_data[0].options & MIPS_CPU_CTXTC) +#endif + #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 0cf90d67c1af..ddcb2abd44ba 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -407,6 +407,7 @@ enum cpu_type_enum { #define MIPS_CPU_EBASE_WG MBIT_ULL(43) /* CPU has EBase.WG */ #define MIPS_CPU_BADINSTR MBIT_ULL(44) /* CPU has BadInstr register */ #define MIPS_CPU_BADINSTRP MBIT_ULL(45) /* CPU has BadInstrP register */ +#define MIPS_CPU_CTXTC MBIT_ULL(46) /* CPU has [X]ConfigContext registers */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index b1f8f8436fd1..08864cbbb27b 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1228,9 +1228,15 @@ do { \ #define read_c0_context() __read_ulong_c0_register($4, 0) #define write_c0_context(val) __write_ulong_c0_register($4, 0, val) +#define read_c0_contextconfig() __read_32bit_c0_register($4, 1) +#define write_c0_contextconfig(val) __write_32bit_c0_register($4, 1, val) + #define read_c0_userlocal() __read_ulong_c0_register($4, 2) #define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val) +#define read_c0_xcontextconfig() __read_ulong_c0_register($4, 3) +#define write_c0_xcontextconfig(val) __write_ulong_c0_register($4, 3, val) + #define read_c0_pagemask() __read_32bit_c0_register($5, 0) #define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 8e54d51c14bc..963ce7ef29df 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -687,10 +687,12 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) if (config3 & MIPS_CONF3_SM) { c->ases |= MIPS_ASE_SMARTMIPS; - c->options |= MIPS_CPU_RIXI; + c->options |= MIPS_CPU_RIXI | MIPS_CPU_CTXTC; } if (config3 & MIPS_CONF3_RXI) c->options |= MIPS_CPU_RIXI; + if (config3 & MIPS_CONF3_CTXTC) + c->options |= MIPS_CPU_CTXTC; if (config3 & MIPS_CONF3_DSP) c->ases |= MIPS_ASE_DSP; if (config3 & MIPS_CONF3_DSP2P) { -- cgit v1.2.3 From 30228c40f0c6f0a93910325f120904505a4c39cc Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 13:50:53 +0100 Subject: MIPS: Add perf counter feature Add CPU feature for standard MIPS r2 performance counters, as determined by the Config1.PC bit. Both perf_events and oprofile probe this bit, so lets combine the probing and change both to use cpu_has_perf. This will also be used for VZ support in KVM to know whether performance counters exist which can be exposed to guests. [ralf@linux-mips.org: resolve conflict.] Signed-off-by: James Hogan Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Robert Richter Cc: linux-mips@linux-mips.org Cc: oprofile-list@lists.sf.net Patchwork: https://patchwork.linux-mips.org/patch/13226/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 4 ++++ arch/mips/include/asm/cpu.h | 1 + arch/mips/kernel/cpu-probe.c | 2 ++ arch/mips/kernel/perf_event_mipsxx.c | 4 +--- arch/mips/oprofile/op_model_mipsxx.c | 4 +--- 5 files changed, 9 insertions(+), 6 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 7962b257cc16..232b0377346a 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -454,4 +454,8 @@ # define cpu_has_contextconfig (cpu_data[0].options & MIPS_CPU_CTXTC) #endif +#ifndef cpu_has_perf +# define cpu_has_perf (cpu_data[0].options & MIPS_CPU_PERF) +#endif + #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index ddcb2abd44ba..3971a25e07a6 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -408,6 +408,7 @@ enum cpu_type_enum { #define MIPS_CPU_BADINSTR MBIT_ULL(44) /* CPU has BadInstr register */ #define MIPS_CPU_BADINSTRP MBIT_ULL(45) /* CPU has BadInstrP register */ #define MIPS_CPU_CTXTC MBIT_ULL(46) /* CPU has [X]ConfigContext registers */ +#define MIPS_CPU_PERF MBIT_ULL(47) /* CPU has MIPS performance counters */ /* * CPU ASE encodings diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 963ce7ef29df..45770d83c3f0 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -648,6 +648,8 @@ static inline unsigned int decode_config1(struct cpuinfo_mips *c) if (config1 & MIPS_CONF1_MD) c->ases |= MIPS_ASE_MDMX; + if (config1 & MIPS_CONF1_PC) + c->options |= MIPS_CPU_PERF; if (config1 & MIPS_CONF1_WR) c->options |= MIPS_CPU_WATCH; if (config1 & MIPS_CONF1_CA) diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 656769c166fc..302af8c975df 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -101,8 +101,6 @@ struct mips_pmu { static struct mips_pmu mipspmu; -#define M_CONFIG1_PC (1 << 4) - #define M_PERFCTL_EXL (1 << 0) #define M_PERFCTL_KERNEL (1 << 1) #define M_PERFCTL_SUPERVISOR (1 << 2) @@ -754,7 +752,7 @@ static void handle_associated_event(struct cpu_hw_events *cpuc, static int __n_counters(void) { - if (!(read_c0_config1() & M_CONFIG1_PC)) + if (!cpu_has_perf) return 0; if (!(read_c0_perfctrl0() & M_PERFCTL_MORE)) return 1; diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 8f988a61b7a8..45cb27469fba 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -269,11 +269,9 @@ static int mipsxx_perfcount_handler(void) return handled; } -#define M_CONFIG1_PC (1 << 4) - static inline int __n_counters(void) { - if (!(read_c0_config1() & M_CONFIG1_PC)) + if (!cpu_has_perf) return 0; if (!(read_c0_perfctrl0() & M_PERFCTL_MORE)) return 1; -- cgit v1.2.3 From 9e575f753576d85e83ae0afc27eca9708259a797 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 15:50:27 +0100 Subject: MIPS: Avoid magic numbers probing kscratch_mask The decode_config4() function reads kscratch_mask from CP0_Config4.KScrExist using a hard coded shift and mask. We already have a definition for the mask in mipsregs.h, so add a definition for the shift and make use of them. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13227/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 3 ++- arch/mips/kernel/cpu-probe.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 08864cbbb27b..480d51550dc0 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -615,7 +615,8 @@ #define MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT (_ULCAST_(1) << 14) #define MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT (_ULCAST_(2) << 14) #define MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT (_ULCAST_(3) << 14) -#define MIPS_CONF4_KSCREXIST (_ULCAST_(255) << 16) +#define MIPS_CONF4_KSCREXIST_SHIFT (16) +#define MIPS_CONF4_KSCREXIST (_ULCAST_(255) << MIPS_CONF4_KSCREXIST_SHIFT) #define MIPS_CONF4_VTLBSIZEEXT_SHIFT (24) #define MIPS_CONF4_VTLBSIZEEXT (_ULCAST_(15) << MIPS_CONF4_VTLBSIZEEXT_SHIFT) #define MIPS_CONF4_AE (_ULCAST_(1) << 28) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 45770d83c3f0..31c27576a931 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -801,7 +801,8 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c) } } - c->kscratch_mask = (config4 >> 16) & 0xff; + c->kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST) + >> MIPS_CONF4_KSCREXIST_SHIFT; asid_mask = MIPS_ENTRYHI_ASID; if (config4 & MIPS_CONF4_AE) -- cgit v1.2.3 From f913e9ea3946902f5443e703d70d5daf90f4498a Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 15:50:28 +0100 Subject: MIPS: Add register definitions for VZ ASE registers Add various register definitions to for the coprocessor zero registers in the VZ ASE, namely CP0_GuestCtl0, CP0_GuestCtl0Ext, CP0_GuestCtl1, CP0_GuestCtl2, CP0_GuestCtl3, and CP0_GTOffset. Signed-off-by: James Hogan Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13228/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 117 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 480d51550dc0..951d92e5f771 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -55,8 +55,14 @@ #define CP0_BADINSTR $8, 1 #define CP0_COUNT $9 #define CP0_ENTRYHI $10 +#define CP0_GUESTCTL1 $10, 4 +#define CP0_GUESTCTL2 $10, 5 +#define CP0_GUESTCTL3 $10, 6 #define CP0_COMPARE $11 +#define CP0_GUESTCTL0EXT $11, 4 #define CP0_STATUS $12 +#define CP0_GUESTCTL0 $12, 6 +#define CP0_GTOFFSET $12, 7 #define CP0_CAUSE $13 #define CP0_EPC $14 #define CP0_PRID $15 @@ -740,6 +746,94 @@ #define MIPS_PWCTL_PSN_SHIFT 0 #define MIPS_PWCTL_PSN_MASK 0x0000003f +/* GuestCtl0 fields */ +#define MIPS_GCTL0_GM_SHIFT 31 +#define MIPS_GCTL0_GM (_ULCAST_(1) << MIPS_GCTL0_GM_SHIFT) +#define MIPS_GCTL0_RI_SHIFT 30 +#define MIPS_GCTL0_RI (_ULCAST_(1) << MIPS_GCTL0_RI_SHIFT) +#define MIPS_GCTL0_MC_SHIFT 29 +#define MIPS_GCTL0_MC (_ULCAST_(1) << MIPS_GCTL0_MC_SHIFT) +#define MIPS_GCTL0_CP0_SHIFT 28 +#define MIPS_GCTL0_CP0 (_ULCAST_(1) << MIPS_GCTL0_CP0_SHIFT) +#define MIPS_GCTL0_AT_SHIFT 26 +#define MIPS_GCTL0_AT (_ULCAST_(0x3) << MIPS_GCTL0_AT_SHIFT) +#define MIPS_GCTL0_GT_SHIFT 25 +#define MIPS_GCTL0_GT (_ULCAST_(1) << MIPS_GCTL0_GT_SHIFT) +#define MIPS_GCTL0_CG_SHIFT 24 +#define MIPS_GCTL0_CG (_ULCAST_(1) << MIPS_GCTL0_CG_SHIFT) +#define MIPS_GCTL0_CF_SHIFT 23 +#define MIPS_GCTL0_CF (_ULCAST_(1) << MIPS_GCTL0_CF_SHIFT) +#define MIPS_GCTL0_G1_SHIFT 22 +#define MIPS_GCTL0_G1 (_ULCAST_(1) << MIPS_GCTL0_G1_SHIFT) +#define MIPS_GCTL0_G0E_SHIFT 19 +#define MIPS_GCTL0_G0E (_ULCAST_(1) << MIPS_GCTL0_G0E_SHIFT) +#define MIPS_GCTL0_PT_SHIFT 18 +#define MIPS_GCTL0_PT (_ULCAST_(1) << MIPS_GCTL0_PT_SHIFT) +#define MIPS_GCTL0_RAD_SHIFT 9 +#define MIPS_GCTL0_RAD (_ULCAST_(1) << MIPS_GCTL0_RAD_SHIFT) +#define MIPS_GCTL0_DRG_SHIFT 8 +#define MIPS_GCTL0_DRG (_ULCAST_(1) << MIPS_GCTL0_DRG_SHIFT) +#define MIPS_GCTL0_G2_SHIFT 7 +#define MIPS_GCTL0_G2 (_ULCAST_(1) << MIPS_GCTL0_G2_SHIFT) +#define MIPS_GCTL0_GEXC_SHIFT 2 +#define MIPS_GCTL0_GEXC (_ULCAST_(0x1f) << MIPS_GCTL0_GEXC_SHIFT) +#define MIPS_GCTL0_SFC2_SHIFT 1 +#define MIPS_GCTL0_SFC2 (_ULCAST_(1) << MIPS_GCTL0_SFC2_SHIFT) +#define MIPS_GCTL0_SFC1_SHIFT 0 +#define MIPS_GCTL0_SFC1 (_ULCAST_(1) << MIPS_GCTL0_SFC1_SHIFT) + +/* GuestCtl0.AT Guest address translation control */ +#define MIPS_GCTL0_AT_ROOT 1 /* Guest MMU under Root control */ +#define MIPS_GCTL0_AT_GUEST 3 /* Guest MMU under Guest control */ + +/* GuestCtl0.GExcCode Hypervisor exception cause codes */ +#define MIPS_GCTL0_GEXC_GPSI 0 /* Guest Privileged Sensitive Instruction */ +#define MIPS_GCTL0_GEXC_GSFC 1 /* Guest Software Field Change */ +#define MIPS_GCTL0_GEXC_HC 2 /* Hypercall */ +#define MIPS_GCTL0_GEXC_GRR 3 /* Guest Reserved Instruction Redirect */ +#define MIPS_GCTL0_GEXC_GVA 8 /* Guest Virtual Address available */ +#define MIPS_GCTL0_GEXC_GHFC 9 /* Guest Hardware Field Change */ +#define MIPS_GCTL0_GEXC_GPA 10 /* Guest Physical Address available */ + +/* GuestCtl0Ext fields */ +#define MIPS_GCTL0EXT_RPW_SHIFT 8 +#define MIPS_GCTL0EXT_RPW (_ULCAST_(0x3) << MIPS_GCTL0EXT_RPW_SHIFT) +#define MIPS_GCTL0EXT_NCC_SHIFT 6 +#define MIPS_GCTL0EXT_NCC (_ULCAST_(0x3) << MIPS_GCTL0EXT_NCC_SHIFT) +#define MIPS_GCTL0EXT_CGI_SHIFT 4 +#define MIPS_GCTL0EXT_CGI (_ULCAST_(1) << MIPS_GCTL0EXT_CGI_SHIFT) +#define MIPS_GCTL0EXT_FCD_SHIFT 3 +#define MIPS_GCTL0EXT_FCD (_ULCAST_(1) << MIPS_GCTL0EXT_FCD_SHIFT) +#define MIPS_GCTL0EXT_OG_SHIFT 2 +#define MIPS_GCTL0EXT_OG (_ULCAST_(1) << MIPS_GCTL0EXT_OG_SHIFT) +#define MIPS_GCTL0EXT_BG_SHIFT 1 +#define MIPS_GCTL0EXT_BG (_ULCAST_(1) << MIPS_GCTL0EXT_BG_SHIFT) +#define MIPS_GCTL0EXT_MG_SHIFT 0 +#define MIPS_GCTL0EXT_MG (_ULCAST_(1) << MIPS_GCTL0EXT_MG_SHIFT) + +/* GuestCtl0Ext.RPW Root page walk configuration */ +#define MIPS_GCTL0EXT_RPW_BOTH 0 /* Root PW for GPA->RPA and RVA->RPA */ +#define MIPS_GCTL0EXT_RPW_GPA 2 /* Root PW for GPA->RPA */ +#define MIPS_GCTL0EXT_RPW_RVA 3 /* Root PW for RVA->RPA */ + +/* GuestCtl0Ext.NCC Nested cache coherency attributes */ +#define MIPS_GCTL0EXT_NCC_IND 0 /* Guest CCA independent of Root CCA */ +#define MIPS_GCTL0EXT_NCC_MOD 1 /* Guest CCA modified by Root CCA */ + +/* GuestCtl1 fields */ +#define MIPS_GCTL1_ID_SHIFT 0 +#define MIPS_GCTL1_ID_WIDTH 8 +#define MIPS_GCTL1_ID (_ULCAST_(0xff) << MIPS_GCTL1_ID_SHIFT) +#define MIPS_GCTL1_RID_SHIFT 16 +#define MIPS_GCTL1_RID_WIDTH 8 +#define MIPS_GCTL1_RID (_ULCAST_(0xff) << MIPS_GCTL1_RID_SHIFT) +#define MIPS_GCTL1_EID_SHIFT 24 +#define MIPS_GCTL1_EID_WIDTH 8 +#define MIPS_GCTL1_EID (_ULCAST_(0xff) << MIPS_GCTL1_EID_SHIFT) + +/* GuestID reserved for root context */ +#define MIPS_GCTL1_ROOT_GUESTID 0 + /* CDMMBase register bit definitions */ #define MIPS_CDMMBASE_SIZE_SHIFT 0 #define MIPS_CDMMBASE_SIZE (_ULCAST_(511) << MIPS_CDMMBASE_SIZE_SHIFT) @@ -1270,9 +1364,21 @@ do { \ #define read_c0_entryhi() __read_ulong_c0_register($10, 0) #define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val) +#define read_c0_guestctl1() __read_32bit_c0_register($10, 4) +#define write_c0_guestctl1(val) __write_32bit_c0_register($10, 4, val) + +#define read_c0_guestctl2() __read_32bit_c0_register($10, 5) +#define write_c0_guestctl2(val) __write_32bit_c0_register($10, 5, val) + +#define read_c0_guestctl3() __read_32bit_c0_register($10, 6) +#define write_c0_guestctl3(val) __write_32bit_c0_register($10, 6, val) + #define read_c0_compare() __read_32bit_c0_register($11, 0) #define write_c0_compare(val) __write_32bit_c0_register($11, 0, val) +#define read_c0_guestctl0ext() __read_32bit_c0_register($11, 4) +#define write_c0_guestctl0ext(val) __write_32bit_c0_register($11, 4, val) + #define read_c0_compare2() __read_32bit_c0_register($11, 6) /* pnx8550 */ #define write_c0_compare2(val) __write_32bit_c0_register($11, 6, val) @@ -1283,6 +1389,12 @@ do { \ #define write_c0_status(val) __write_32bit_c0_register($12, 0, val) +#define read_c0_guestctl0() __read_32bit_c0_register($12, 6) +#define write_c0_guestctl0(val) __write_32bit_c0_register($12, 6, val) + +#define read_c0_gtoffset() __read_32bit_c0_register($12, 7) +#define write_c0_gtoffset(val) __write_32bit_c0_register($12, 7, val) + #define read_c0_cause() __read_32bit_c0_register($13, 0) #define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) @@ -2111,6 +2223,11 @@ __BUILD_SET_C0(intcontrol) __BUILD_SET_C0(intctl) __BUILD_SET_C0(srsmap) __BUILD_SET_C0(pagegrain) +__BUILD_SET_C0(guestctl0) +__BUILD_SET_C0(guestctl0ext) +__BUILD_SET_C0(guestctl1) +__BUILD_SET_C0(guestctl2) +__BUILD_SET_C0(guestctl3) __BUILD_SET_C0(brcm_config_0) __BUILD_SET_C0(brcm_bus_pll) __BUILD_SET_C0(brcm_reset) -- cgit v1.2.3 From 7eb91118227d71132ca2da06a9b376ba656171d9 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 15:50:29 +0100 Subject: MIPS: Add guest CP0 accessors Add guest CP0 accessors and guest TLB operations along the same lines as the existing macros and functions for the root CP0. Signed-off-by: James Hogan Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13229/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 341 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 330 insertions(+), 11 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 951d92e5f771..1019de6bb2a8 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1679,6 +1679,253 @@ do { \ #define read_c0_brcm_sleepcount() __read_32bit_c0_register($22, 7) #define write_c0_brcm_sleepcount(val) __write_32bit_c0_register($22, 7, val) +/* + * Macros to access the guest system control coprocessor + */ + +#define __read_32bit_gc0_register(source, sel) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tmips32r2\n\t" \ + ".set\tvirt\n\t" \ + "mfgc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __read_64bit_gc0_register(source, sel) \ +({ unsigned long long __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tmips64r2\n\t" \ + ".set\tvirt\n\t" \ + "dmfgc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __write_32bit_gc0_register(register, sel, value) \ +do { \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tmips32r2\n\t" \ + ".set\tvirt\n\t" \ + "mtgc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tpop" \ + : : "Jr" ((unsigned int)(value))); \ +} while (0) + +#define __write_64bit_gc0_register(register, sel, value) \ +do { \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tmips64r2\n\t" \ + ".set\tvirt\n\t" \ + "dmtgc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tpop" \ + : : "Jr" (value)); \ +} while (0) + +#define __read_ulong_gc0_register(reg, sel) \ + ((sizeof(unsigned long) == 4) ? \ + (unsigned long) __read_32bit_gc0_register(reg, sel) : \ + (unsigned long) __read_64bit_gc0_register(reg, sel)) + +#define __write_ulong_gc0_register(reg, sel, val) \ +do { \ + if (sizeof(unsigned long) == 4) \ + __write_32bit_gc0_register(reg, sel, val); \ + else \ + __write_64bit_gc0_register(reg, sel, val); \ +} while (0) + +#define read_gc0_index() __read_32bit_gc0_register($0, 0) +#define write_gc0_index(val) __write_32bit_gc0_register($0, 0, val) + +#define read_gc0_entrylo0() __read_ulong_gc0_register($2, 0) +#define write_gc0_entrylo0(val) __write_ulong_gc0_register($2, 0, val) + +#define read_gc0_entrylo1() __read_ulong_gc0_register($3, 0) +#define write_gc0_entrylo1(val) __write_ulong_gc0_register($3, 0, val) + +#define read_gc0_context() __read_ulong_gc0_register($4, 0) +#define write_gc0_context(val) __write_ulong_gc0_register($4, 0, val) + +#define read_gc0_contextconfig() __read_32bit_gc0_register($4, 1) +#define write_gc0_contextconfig(val) __write_32bit_gc0_register($4, 1, val) + +#define read_gc0_userlocal() __read_ulong_gc0_register($4, 2) +#define write_gc0_userlocal(val) __write_ulong_gc0_register($4, 2, val) + +#define read_gc0_xcontextconfig() __read_ulong_gc0_register($4, 3) +#define write_gc0_xcontextconfig(val) __write_ulong_gc0_register($4, 3, val) + +#define read_gc0_pagemask() __read_32bit_gc0_register($5, 0) +#define write_gc0_pagemask(val) __write_32bit_gc0_register($5, 0, val) + +#define read_gc0_pagegrain() __read_32bit_gc0_register($5, 1) +#define write_gc0_pagegrain(val) __write_32bit_gc0_register($5, 1, val) + +#define read_gc0_segctl0() __read_ulong_gc0_register($5, 2) +#define write_gc0_segctl0(val) __write_ulong_gc0_register($5, 2, val) + +#define read_gc0_segctl1() __read_ulong_gc0_register($5, 3) +#define write_gc0_segctl1(val) __write_ulong_gc0_register($5, 3, val) + +#define read_gc0_segctl2() __read_ulong_gc0_register($5, 4) +#define write_gc0_segctl2(val) __write_ulong_gc0_register($5, 4, val) + +#define read_gc0_pwbase() __read_ulong_gc0_register($5, 5) +#define write_gc0_pwbase(val) __write_ulong_gc0_register($5, 5, val) + +#define read_gc0_pwfield() __read_ulong_gc0_register($5, 6) +#define write_gc0_pwfield(val) __write_ulong_gc0_register($5, 6, val) + +#define read_gc0_pwsize() __read_ulong_gc0_register($5, 7) +#define write_gc0_pwsize(val) __write_ulong_gc0_register($5, 7, val) + +#define read_gc0_wired() __read_32bit_gc0_register($6, 0) +#define write_gc0_wired(val) __write_32bit_gc0_register($6, 0, val) + +#define read_gc0_pwctl() __read_32bit_gc0_register($6, 6) +#define write_gc0_pwctl(val) __write_32bit_gc0_register($6, 6, val) + +#define read_gc0_hwrena() __read_32bit_gc0_register($7, 0) +#define write_gc0_hwrena(val) __write_32bit_gc0_register($7, 0, val) + +#define read_gc0_badvaddr() __read_ulong_gc0_register($8, 0) +#define write_gc0_badvaddr(val) __write_ulong_gc0_register($8, 0, val) + +#define read_gc0_badinstr() __read_32bit_gc0_register($8, 1) +#define write_gc0_badinstr(val) __write_32bit_gc0_register($8, 1, val) + +#define read_gc0_badinstrp() __read_32bit_gc0_register($8, 2) +#define write_gc0_badinstrp(val) __write_32bit_gc0_register($8, 2, val) + +#define read_gc0_count() __read_32bit_gc0_register($9, 0) + +#define read_gc0_entryhi() __read_ulong_gc0_register($10, 0) +#define write_gc0_entryhi(val) __write_ulong_gc0_register($10, 0, val) + +#define read_gc0_compare() __read_32bit_gc0_register($11, 0) +#define write_gc0_compare(val) __write_32bit_gc0_register($11, 0, val) + +#define read_gc0_status() __read_32bit_gc0_register($12, 0) +#define write_gc0_status(val) __write_32bit_gc0_register($12, 0, val) + +#define read_gc0_intctl() __read_32bit_gc0_register($12, 1) +#define write_gc0_intctl(val) __write_32bit_gc0_register($12, 1, val) + +#define read_gc0_cause() __read_32bit_gc0_register($13, 0) +#define write_gc0_cause(val) __write_32bit_gc0_register($13, 0, val) + +#define read_gc0_epc() __read_ulong_gc0_register($14, 0) +#define write_gc0_epc(val) __write_ulong_gc0_register($14, 0, val) + +#define read_gc0_ebase() __read_32bit_gc0_register($15, 1) +#define write_gc0_ebase(val) __write_32bit_gc0_register($15, 1, val) + +#define read_gc0_ebase_64() __read_64bit_gc0_register($15, 1) +#define write_gc0_ebase_64(val) __write_64bit_gc0_register($15, 1, val) + +#define read_gc0_config() __read_32bit_gc0_register($16, 0) +#define read_gc0_config1() __read_32bit_gc0_register($16, 1) +#define read_gc0_config2() __read_32bit_gc0_register($16, 2) +#define read_gc0_config3() __read_32bit_gc0_register($16, 3) +#define read_gc0_config4() __read_32bit_gc0_register($16, 4) +#define read_gc0_config5() __read_32bit_gc0_register($16, 5) +#define read_gc0_config6() __read_32bit_gc0_register($16, 6) +#define read_gc0_config7() __read_32bit_gc0_register($16, 7) +#define write_gc0_config(val) __write_32bit_gc0_register($16, 0, val) +#define write_gc0_config1(val) __write_32bit_gc0_register($16, 1, val) +#define write_gc0_config2(val) __write_32bit_gc0_register($16, 2, val) +#define write_gc0_config3(val) __write_32bit_gc0_register($16, 3, val) +#define write_gc0_config4(val) __write_32bit_gc0_register($16, 4, val) +#define write_gc0_config5(val) __write_32bit_gc0_register($16, 5, val) +#define write_gc0_config6(val) __write_32bit_gc0_register($16, 6, val) +#define write_gc0_config7(val) __write_32bit_gc0_register($16, 7, val) + +#define read_gc0_watchlo0() __read_ulong_gc0_register($18, 0) +#define read_gc0_watchlo1() __read_ulong_gc0_register($18, 1) +#define read_gc0_watchlo2() __read_ulong_gc0_register($18, 2) +#define read_gc0_watchlo3() __read_ulong_gc0_register($18, 3) +#define read_gc0_watchlo4() __read_ulong_gc0_register($18, 4) +#define read_gc0_watchlo5() __read_ulong_gc0_register($18, 5) +#define read_gc0_watchlo6() __read_ulong_gc0_register($18, 6) +#define read_gc0_watchlo7() __read_ulong_gc0_register($18, 7) +#define write_gc0_watchlo0(val) __write_ulong_gc0_register($18, 0, val) +#define write_gc0_watchlo1(val) __write_ulong_gc0_register($18, 1, val) +#define write_gc0_watchlo2(val) __write_ulong_gc0_register($18, 2, val) +#define write_gc0_watchlo3(val) __write_ulong_gc0_register($18, 3, val) +#define write_gc0_watchlo4(val) __write_ulong_gc0_register($18, 4, val) +#define write_gc0_watchlo5(val) __write_ulong_gc0_register($18, 5, val) +#define write_gc0_watchlo6(val) __write_ulong_gc0_register($18, 6, val) +#define write_gc0_watchlo7(val) __write_ulong_gc0_register($18, 7, val) + +#define read_gc0_watchhi0() __read_32bit_gc0_register($19, 0) +#define read_gc0_watchhi1() __read_32bit_gc0_register($19, 1) +#define read_gc0_watchhi2() __read_32bit_gc0_register($19, 2) +#define read_gc0_watchhi3() __read_32bit_gc0_register($19, 3) +#define read_gc0_watchhi4() __read_32bit_gc0_register($19, 4) +#define read_gc0_watchhi5() __read_32bit_gc0_register($19, 5) +#define read_gc0_watchhi6() __read_32bit_gc0_register($19, 6) +#define read_gc0_watchhi7() __read_32bit_gc0_register($19, 7) +#define write_gc0_watchhi0(val) __write_32bit_gc0_register($19, 0, val) +#define write_gc0_watchhi1(val) __write_32bit_gc0_register($19, 1, val) +#define write_gc0_watchhi2(val) __write_32bit_gc0_register($19, 2, val) +#define write_gc0_watchhi3(val) __write_32bit_gc0_register($19, 3, val) +#define write_gc0_watchhi4(val) __write_32bit_gc0_register($19, 4, val) +#define write_gc0_watchhi5(val) __write_32bit_gc0_register($19, 5, val) +#define write_gc0_watchhi6(val) __write_32bit_gc0_register($19, 6, val) +#define write_gc0_watchhi7(val) __write_32bit_gc0_register($19, 7, val) + +#define read_gc0_xcontext() __read_ulong_gc0_register($20, 0) +#define write_gc0_xcontext(val) __write_ulong_gc0_register($20, 0, val) + +#define read_gc0_perfctrl0() __read_32bit_gc0_register($25, 0) +#define write_gc0_perfctrl0(val) __write_32bit_gc0_register($25, 0, val) +#define read_gc0_perfcntr0() __read_32bit_gc0_register($25, 1) +#define write_gc0_perfcntr0(val) __write_32bit_gc0_register($25, 1, val) +#define read_gc0_perfcntr0_64() __read_64bit_gc0_register($25, 1) +#define write_gc0_perfcntr0_64(val) __write_64bit_gc0_register($25, 1, val) +#define read_gc0_perfctrl1() __read_32bit_gc0_register($25, 2) +#define write_gc0_perfctrl1(val) __write_32bit_gc0_register($25, 2, val) +#define read_gc0_perfcntr1() __read_32bit_gc0_register($25, 3) +#define write_gc0_perfcntr1(val) __write_32bit_gc0_register($25, 3, val) +#define read_gc0_perfcntr1_64() __read_64bit_gc0_register($25, 3) +#define write_gc0_perfcntr1_64(val) __write_64bit_gc0_register($25, 3, val) +#define read_gc0_perfctrl2() __read_32bit_gc0_register($25, 4) +#define write_gc0_perfctrl2(val) __write_32bit_gc0_register($25, 4, val) +#define read_gc0_perfcntr2() __read_32bit_gc0_register($25, 5) +#define write_gc0_perfcntr2(val) __write_32bit_gc0_register($25, 5, val) +#define read_gc0_perfcntr2_64() __read_64bit_gc0_register($25, 5) +#define write_gc0_perfcntr2_64(val) __write_64bit_gc0_register($25, 5, val) +#define read_gc0_perfctrl3() __read_32bit_gc0_register($25, 6) +#define write_gc0_perfctrl3(val) __write_32bit_gc0_register($25, 6, val) +#define read_gc0_perfcntr3() __read_32bit_gc0_register($25, 7) +#define write_gc0_perfcntr3(val) __write_32bit_gc0_register($25, 7, val) +#define read_gc0_perfcntr3_64() __read_64bit_gc0_register($25, 7) +#define write_gc0_perfcntr3_64(val) __write_64bit_gc0_register($25, 7, val) + +#define read_gc0_errorepc() __read_ulong_gc0_register($30, 0) +#define write_gc0_errorepc(val) __write_ulong_gc0_register($30, 0, val) + +#define read_gc0_kscratch1() __read_ulong_gc0_register($31, 2) +#define read_gc0_kscratch2() __read_ulong_gc0_register($31, 3) +#define read_gc0_kscratch3() __read_ulong_gc0_register($31, 4) +#define read_gc0_kscratch4() __read_ulong_gc0_register($31, 5) +#define read_gc0_kscratch5() __read_ulong_gc0_register($31, 6) +#define read_gc0_kscratch6() __read_ulong_gc0_register($31, 7) +#define write_gc0_kscratch1(val) __write_ulong_gc0_register($31, 2, val) +#define write_gc0_kscratch2(val) __write_ulong_gc0_register($31, 3, val) +#define write_gc0_kscratch3(val) __write_ulong_gc0_register($31, 4, val) +#define write_gc0_kscratch4(val) __write_ulong_gc0_register($31, 5, val) +#define write_gc0_kscratch5(val) __write_ulong_gc0_register($31, 6, val) +#define write_gc0_kscratch6(val) __write_ulong_gc0_register($31, 7, val) + /* * Macros to access the floating point coprocessor control registers */ @@ -2175,46 +2422,109 @@ static inline void tlb_write_random(void) } /* - * Manipulate bits in a c0 register. + * Guest TLB operations. + * + * It is responsibility of the caller to take care of any TLB hazards. + */ +static inline void guest_tlb_probe(void) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + ".set virt\n\t" + "tlbgp\n\t" + ".set pop"); +} + +static inline void guest_tlb_read(void) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + ".set virt\n\t" + "tlbgr\n\t" + ".set pop"); +} + +static inline void guest_tlb_write_indexed(void) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + ".set virt\n\t" + "tlbgwi\n\t" + ".set pop"); +} + +static inline void guest_tlb_write_random(void) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + ".set virt\n\t" + "tlbgwr\n\t" + ".set pop"); +} + +/* + * Guest TLB Invalidate Flush */ -#define __BUILD_SET_C0(name) \ +static inline void guest_tlbinvf(void) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + ".set virt\n\t" + "tlbginvf\n\t" + ".set pop"); +} + +/* + * Manipulate bits in a register. + */ +#define __BUILD_SET_COMMON(name) \ static inline unsigned int \ -set_c0_##name(unsigned int set) \ +set_##name(unsigned int set) \ { \ unsigned int res, new; \ \ - res = read_c0_##name(); \ + res = read_##name(); \ new = res | set; \ - write_c0_##name(new); \ + write_##name(new); \ \ return res; \ } \ \ static inline unsigned int \ -clear_c0_##name(unsigned int clear) \ +clear_##name(unsigned int clear) \ { \ unsigned int res, new; \ \ - res = read_c0_##name(); \ + res = read_##name(); \ new = res & ~clear; \ - write_c0_##name(new); \ + write_##name(new); \ \ return res; \ } \ \ static inline unsigned int \ -change_c0_##name(unsigned int change, unsigned int val) \ +change_##name(unsigned int change, unsigned int val) \ { \ unsigned int res, new; \ \ - res = read_c0_##name(); \ + res = read_##name(); \ new = res & ~change; \ new |= (val & change); \ - write_c0_##name(new); \ + write_##name(new); \ \ return res; \ } +/* + * Manipulate bits in a c0 register. + */ +#define __BUILD_SET_C0(name) __BUILD_SET_COMMON(c0_##name) + __BUILD_SET_C0(status) __BUILD_SET_C0(cause) __BUILD_SET_C0(config) @@ -2236,6 +2546,15 @@ __BUILD_SET_C0(brcm_cmt_ctrl) __BUILD_SET_C0(brcm_config) __BUILD_SET_C0(brcm_mode) +/* + * Manipulate bits in a guest c0 register. + */ +#define __BUILD_SET_GC0(name) __BUILD_SET_COMMON(gc0_##name) + +__BUILD_SET_GC0(status) +__BUILD_SET_GC0(cause) +__BUILD_SET_GC0(ebase) + /* * Return low 10 bits of ebase. * Note that under KVM (MIPSVZ) this returns vcpu id. -- cgit v1.2.3 From 6ad816e77ed77538fe729050cf6631328c6113f7 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 11 May 2016 15:50:30 +0100 Subject: MIPS: Add probing & defs for VZ & guest features Add a few new cpu-features.h definitions for VZ sub-features, namely the existence of the CP0_GuestCtl0Ext, CP0_GuestCtl1, and CP0_GuestCtl2 registers, and support for GuestID to dialias TLB entries belonging to different guests. Also add certain features present in the guest, with the naming scheme cpu_guest_has_*. These are added separately to the main options bitfield since they generally parallel similar features in the root context. A few of these (FPU, MSA, watchpoints, perf counters, CP0_[X]ContextConfig registers, MAAR registers, and probably others in future) can be dynamically configured in the guest context, for which the cpu_guest_has_dyn_* macros are added. [ralf@linux-mips.org: Resolve merge conflict.] Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13231/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 98 +++++++++++++++ arch/mips/include/asm/cpu-info.h | 14 +++ arch/mips/include/asm/cpu.h | 5 + arch/mips/kernel/cpu-probe.c | 232 +++++++++++++++++++++++++++++++++++ 4 files changed, 349 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 232b0377346a..e6f19fc61bf2 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -120,6 +120,21 @@ #ifndef kernel_uses_llsc #define kernel_uses_llsc cpu_has_llsc #endif +#ifndef cpu_has_guestctl0ext +#define cpu_has_guestctl0ext (cpu_data[0].options & MIPS_CPU_GUESTCTL0EXT) +#endif +#ifndef cpu_has_guestctl1 +#define cpu_has_guestctl1 (cpu_data[0].options & MIPS_CPU_GUESTCTL1) +#endif +#ifndef cpu_has_guestctl2 +#define cpu_has_guestctl2 (cpu_data[0].options & MIPS_CPU_GUESTCTL2) +#endif +#ifndef cpu_has_guestid +#define cpu_has_guestid (cpu_data[0].options & MIPS_CPU_GUESTID) +#endif +#ifndef cpu_has_drg +#define cpu_has_drg (cpu_data[0].options & MIPS_CPU_DRG) +#endif #ifndef cpu_has_mips16 #define cpu_has_mips16 (cpu_data[0].ases & MIPS_ASE_MIPS16) #endif @@ -458,4 +473,87 @@ # define cpu_has_perf (cpu_data[0].options & MIPS_CPU_PERF) #endif +/* + * Guest capabilities + */ +#ifndef cpu_guest_has_conf1 +#define cpu_guest_has_conf1 (cpu_data[0].guest.conf & (1 << 1)) +#endif +#ifndef cpu_guest_has_conf2 +#define cpu_guest_has_conf2 (cpu_data[0].guest.conf & (1 << 2)) +#endif +#ifndef cpu_guest_has_conf3 +#define cpu_guest_has_conf3 (cpu_data[0].guest.conf & (1 << 3)) +#endif +#ifndef cpu_guest_has_conf4 +#define cpu_guest_has_conf4 (cpu_data[0].guest.conf & (1 << 4)) +#endif +#ifndef cpu_guest_has_conf5 +#define cpu_guest_has_conf5 (cpu_data[0].guest.conf & (1 << 5)) +#endif +#ifndef cpu_guest_has_conf6 +#define cpu_guest_has_conf6 (cpu_data[0].guest.conf & (1 << 6)) +#endif +#ifndef cpu_guest_has_conf7 +#define cpu_guest_has_conf7 (cpu_data[0].guest.conf & (1 << 7)) +#endif +#ifndef cpu_guest_has_fpu +#define cpu_guest_has_fpu (cpu_data[0].guest.options & MIPS_CPU_FPU) +#endif +#ifndef cpu_guest_has_watch +#define cpu_guest_has_watch (cpu_data[0].guest.options & MIPS_CPU_WATCH) +#endif +#ifndef cpu_guest_has_contextconfig +#define cpu_guest_has_contextconfig (cpu_data[0].guest.options & MIPS_CPU_CTXTC) +#endif +#ifndef cpu_guest_has_segments +#define cpu_guest_has_segments (cpu_data[0].guest.options & MIPS_CPU_SEGMENTS) +#endif +#ifndef cpu_guest_has_badinstr +#define cpu_guest_has_badinstr (cpu_data[0].guest.options & MIPS_CPU_BADINSTR) +#endif +#ifndef cpu_guest_has_badinstrp +#define cpu_guest_has_badinstrp (cpu_data[0].guest.options & MIPS_CPU_BADINSTRP) +#endif +#ifndef cpu_guest_has_htw +#define cpu_guest_has_htw (cpu_data[0].guest.options & MIPS_CPU_HTW) +#endif +#ifndef cpu_guest_has_msa +#define cpu_guest_has_msa (cpu_data[0].guest.ases & MIPS_ASE_MSA) +#endif +#ifndef cpu_guest_has_kscr +#define cpu_guest_has_kscr(n) (cpu_data[0].guest.kscratch_mask & (1u << (n))) +#endif +#ifndef cpu_guest_has_rw_llb +#define cpu_guest_has_rw_llb (cpu_has_mips_r6 || (cpu_data[0].guest.options & MIPS_CPU_RW_LLB)) +#endif +#ifndef cpu_guest_has_perf +#define cpu_guest_has_perf (cpu_data[0].guest.options & MIPS_CPU_PERF) +#endif +#ifndef cpu_guest_has_maar +#define cpu_guest_has_maar (cpu_data[0].guest.options & MIPS_CPU_MAAR) +#endif + +/* + * Guest dynamic capabilities + */ +#ifndef cpu_guest_has_dyn_fpu +#define cpu_guest_has_dyn_fpu (cpu_data[0].guest.options_dyn & MIPS_CPU_FPU) +#endif +#ifndef cpu_guest_has_dyn_watch +#define cpu_guest_has_dyn_watch (cpu_data[0].guest.options_dyn & MIPS_CPU_WATCH) +#endif +#ifndef cpu_guest_has_dyn_contextconfig +#define cpu_guest_has_dyn_contextconfig (cpu_data[0].guest.options_dyn & MIPS_CPU_CTXTC) +#endif +#ifndef cpu_guest_has_dyn_perf +#define cpu_guest_has_dyn_perf (cpu_data[0].guest.options_dyn & MIPS_CPU_PERF) +#endif +#ifndef cpu_guest_has_dyn_msa +#define cpu_guest_has_dyn_msa (cpu_data[0].guest.ases_dyn & MIPS_ASE_MSA) +#endif +#ifndef cpu_guest_has_dyn_maar +#define cpu_guest_has_dyn_maar (cpu_data[0].guest.options_dyn & MIPS_CPU_MAAR) +#endif + #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index 392da7e6fc72..edbe2734a1bf 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -28,6 +28,15 @@ struct cache_desc { unsigned char flags; /* Flags describing cache properties */ }; +struct guest_info { + unsigned long ases; + unsigned long ases_dyn; + unsigned long long options; + unsigned long long options_dyn; + u8 conf; + u8 kscratch_mask; +}; + /* * Flag definitions */ @@ -95,6 +104,11 @@ struct cpuinfo_mips { * htw_start/htw_stop calls */ unsigned int htw_seq; + + /* VZ & Guest features */ + struct guest_info guest; + unsigned int gtoffset_mask; + unsigned int guestid_mask; } __attribute__((aligned(SMP_CACHE_BYTES))); extern struct cpuinfo_mips cpu_data[]; diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 3971a25e07a6..f672df8b26d0 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -409,6 +409,11 @@ enum cpu_type_enum { #define MIPS_CPU_BADINSTRP MBIT_ULL(45) /* CPU has BadInstrP register */ #define MIPS_CPU_CTXTC MBIT_ULL(46) /* CPU has [X]ConfigContext registers */ #define MIPS_CPU_PERF MBIT_ULL(47) /* CPU has MIPS performance counters */ +#define MIPS_CPU_GUESTCTL0EXT MBIT_ULL(48) /* CPU has VZ GuestCtl0Ext register */ +#define MIPS_CPU_GUESTCTL1 MBIT_ULL(49) /* CPU has VZ GuestCtl1 register */ +#define MIPS_CPU_GUESTCTL2 MBIT_ULL(50) /* CPU has VZ GuestCtl2 register */ +#define MIPS_CPU_GUESTID MBIT_ULL(51) /* CPU uses VZ ASE GuestID feature */ +#define MIPS_CPU_DRG MBIT_ULL(52) /* CPU has VZ Direct Root to Guest (DRG) */ /* * CPU ASE encodings diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 31c27576a931..5ac5c3e23460 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -915,6 +915,235 @@ static void decode_configs(struct cpuinfo_mips *c) #endif } +/* + * Probe for certain guest capabilities by writing config bits and reading back. + * Finally write back the original value. + */ +#define probe_gc0_config(name, maxconf, bits) \ +do { \ + unsigned int tmp; \ + tmp = read_gc0_##name(); \ + write_gc0_##name(tmp | (bits)); \ + back_to_back_c0_hazard(); \ + maxconf = read_gc0_##name(); \ + write_gc0_##name(tmp); \ +} while (0) + +/* + * Probe for dynamic guest capabilities by changing certain config bits and + * reading back to see if they change. Finally write back the original value. + */ +#define probe_gc0_config_dyn(name, maxconf, dynconf, bits) \ +do { \ + maxconf = read_gc0_##name(); \ + write_gc0_##name(maxconf ^ (bits)); \ + back_to_back_c0_hazard(); \ + dynconf = maxconf ^ read_gc0_##name(); \ + write_gc0_##name(maxconf); \ + maxconf |= dynconf; \ +} while (0) + +static inline unsigned int decode_guest_config0(struct cpuinfo_mips *c) +{ + unsigned int config0; + + probe_gc0_config(config, config0, MIPS_CONF_M); + + if (config0 & MIPS_CONF_M) + c->guest.conf |= BIT(1); + return config0 & MIPS_CONF_M; +} + +static inline unsigned int decode_guest_config1(struct cpuinfo_mips *c) +{ + unsigned int config1, config1_dyn; + + probe_gc0_config_dyn(config1, config1, config1_dyn, + MIPS_CONF_M | MIPS_CONF1_PC | MIPS_CONF1_WR | + MIPS_CONF1_FP); + + if (config1 & MIPS_CONF1_FP) + c->guest.options |= MIPS_CPU_FPU; + if (config1_dyn & MIPS_CONF1_FP) + c->guest.options_dyn |= MIPS_CPU_FPU; + + if (config1 & MIPS_CONF1_WR) + c->guest.options |= MIPS_CPU_WATCH; + if (config1_dyn & MIPS_CONF1_WR) + c->guest.options_dyn |= MIPS_CPU_WATCH; + + if (config1 & MIPS_CONF1_PC) + c->guest.options |= MIPS_CPU_PERF; + if (config1_dyn & MIPS_CONF1_PC) + c->guest.options_dyn |= MIPS_CPU_PERF; + + if (config1 & MIPS_CONF_M) + c->guest.conf |= BIT(2); + return config1 & MIPS_CONF_M; +} + +static inline unsigned int decode_guest_config2(struct cpuinfo_mips *c) +{ + unsigned int config2; + + probe_gc0_config(config2, config2, MIPS_CONF_M); + + if (config2 & MIPS_CONF_M) + c->guest.conf |= BIT(3); + return config2 & MIPS_CONF_M; +} + +static inline unsigned int decode_guest_config3(struct cpuinfo_mips *c) +{ + unsigned int config3, config3_dyn; + + probe_gc0_config_dyn(config3, config3, config3_dyn, + MIPS_CONF_M | MIPS_CONF3_MSA | MIPS_CONF3_CTXTC); + + if (config3 & MIPS_CONF3_CTXTC) + c->guest.options |= MIPS_CPU_CTXTC; + if (config3_dyn & MIPS_CONF3_CTXTC) + c->guest.options_dyn |= MIPS_CPU_CTXTC; + + if (config3 & MIPS_CONF3_PW) + c->guest.options |= MIPS_CPU_HTW; + + if (config3 & MIPS_CONF3_SC) + c->guest.options |= MIPS_CPU_SEGMENTS; + + if (config3 & MIPS_CONF3_BI) + c->guest.options |= MIPS_CPU_BADINSTR; + if (config3 & MIPS_CONF3_BP) + c->guest.options |= MIPS_CPU_BADINSTRP; + + if (config3 & MIPS_CONF3_MSA) + c->guest.ases |= MIPS_ASE_MSA; + if (config3_dyn & MIPS_CONF3_MSA) + c->guest.ases_dyn |= MIPS_ASE_MSA; + + if (config3 & MIPS_CONF_M) + c->guest.conf |= BIT(4); + return config3 & MIPS_CONF_M; +} + +static inline unsigned int decode_guest_config4(struct cpuinfo_mips *c) +{ + unsigned int config4; + + probe_gc0_config(config4, config4, + MIPS_CONF_M | MIPS_CONF4_KSCREXIST); + + c->guest.kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST) + >> MIPS_CONF4_KSCREXIST_SHIFT; + + if (config4 & MIPS_CONF_M) + c->guest.conf |= BIT(5); + return config4 & MIPS_CONF_M; +} + +static inline unsigned int decode_guest_config5(struct cpuinfo_mips *c) +{ + unsigned int config5, config5_dyn; + + probe_gc0_config_dyn(config5, config5, config5_dyn, + MIPS_CONF_M | MIPS_CONF5_MRP); + + if (config5 & MIPS_CONF5_MRP) + c->guest.options |= MIPS_CPU_MAAR; + if (config5_dyn & MIPS_CONF5_MRP) + c->guest.options_dyn |= MIPS_CPU_MAAR; + + if (config5 & MIPS_CONF5_LLB) + c->guest.options |= MIPS_CPU_RW_LLB; + + if (config5 & MIPS_CONF_M) + c->guest.conf |= BIT(6); + return config5 & MIPS_CONF_M; +} + +static inline void decode_guest_configs(struct cpuinfo_mips *c) +{ + unsigned int ok; + + ok = decode_guest_config0(c); + if (ok) + ok = decode_guest_config1(c); + if (ok) + ok = decode_guest_config2(c); + if (ok) + ok = decode_guest_config3(c); + if (ok) + ok = decode_guest_config4(c); + if (ok) + decode_guest_config5(c); +} + +static inline void cpu_probe_guestctl0(struct cpuinfo_mips *c) +{ + unsigned int guestctl0, temp; + + guestctl0 = read_c0_guestctl0(); + + if (guestctl0 & MIPS_GCTL0_G0E) + c->options |= MIPS_CPU_GUESTCTL0EXT; + if (guestctl0 & MIPS_GCTL0_G1) + c->options |= MIPS_CPU_GUESTCTL1; + if (guestctl0 & MIPS_GCTL0_G2) + c->options |= MIPS_CPU_GUESTCTL2; + if (!(guestctl0 & MIPS_GCTL0_RAD)) { + c->options |= MIPS_CPU_GUESTID; + + /* + * Probe for Direct Root to Guest (DRG). Set GuestCtl1.RID = 0 + * first, otherwise all data accesses will be fully virtualised + * as if they were performed by guest mode. + */ + write_c0_guestctl1(0); + tlbw_use_hazard(); + + write_c0_guestctl0(guestctl0 | MIPS_GCTL0_DRG); + back_to_back_c0_hazard(); + temp = read_c0_guestctl0(); + + if (temp & MIPS_GCTL0_DRG) { + write_c0_guestctl0(guestctl0); + c->options |= MIPS_CPU_DRG; + } + } +} + +static inline void cpu_probe_guestctl1(struct cpuinfo_mips *c) +{ + if (cpu_has_guestid) { + /* determine the number of bits of GuestID available */ + write_c0_guestctl1(MIPS_GCTL1_ID); + back_to_back_c0_hazard(); + c->guestid_mask = (read_c0_guestctl1() & MIPS_GCTL1_ID) + >> MIPS_GCTL1_ID_SHIFT; + write_c0_guestctl1(0); + } +} + +static inline void cpu_probe_gtoffset(struct cpuinfo_mips *c) +{ + /* determine the number of bits of GTOffset available */ + write_c0_gtoffset(0xffffffff); + back_to_back_c0_hazard(); + c->gtoffset_mask = read_c0_gtoffset(); + write_c0_gtoffset(0); +} + +static inline void cpu_probe_vz(struct cpuinfo_mips *c) +{ + cpu_probe_guestctl0(c); + if (cpu_has_guestctl1) + cpu_probe_guestctl1(c); + + cpu_probe_gtoffset(c); + + decode_guest_configs(c); +} + #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \ | MIPS_CPU_COUNTER) @@ -1817,6 +2046,9 @@ void cpu_probe(void) elf_hwcap |= HWCAP_MIPS_MSA; } + if (cpu_has_vz) + cpu_probe_vz(c); + cpu_probe_vmbits(c); #ifdef CONFIG_64BIT -- cgit v1.2.3 From de704161aa05a594fcd596cb7f50e231c384355e Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 May 2016 07:20:16 +0100 Subject: MIPS: ELF: Deconditionalise ABI flags definitions Move the `mips_elf_abiflags_v0' structure and FP ABI flag macros outside #ifndef ELF_ARCH. These are public interfaces. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13243/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 1fba19747fa9..94fd11953128 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -175,16 +175,14 @@ #define SHF_MIPS_NAMES 0x02000000 #define SHF_MIPS_NODUPES 0x01000000 -#ifndef ELF_ARCH -/* ELF register definitions */ -#define ELF_NGREG 45 -#define ELF_NFPREG 33 - -typedef unsigned long elf_greg_t; -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef double elf_fpreg_t; -typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; +#define MIPS_ABI_FP_ANY 0 /* FP ABI doesn't matter */ +#define MIPS_ABI_FP_DOUBLE 1 /* -mdouble-float */ +#define MIPS_ABI_FP_SINGLE 2 /* -msingle-float */ +#define MIPS_ABI_FP_SOFT 3 /* -msoft-float */ +#define MIPS_ABI_FP_OLD_64 4 /* -mips32r2 -mfp64 */ +#define MIPS_ABI_FP_XX 5 /* -mfpxx */ +#define MIPS_ABI_FP_64 6 /* -mips32r2 -mfp64 */ +#define MIPS_ABI_FP_64A 7 /* -mips32r2 -mfp64 -mno-odd-spreg */ struct mips_elf_abiflags_v0 { uint16_t version; /* Version of flags structure */ @@ -201,14 +199,16 @@ struct mips_elf_abiflags_v0 { uint32_t flags2; }; -#define MIPS_ABI_FP_ANY 0 /* FP ABI doesn't matter */ -#define MIPS_ABI_FP_DOUBLE 1 /* -mdouble-float */ -#define MIPS_ABI_FP_SINGLE 2 /* -msingle-float */ -#define MIPS_ABI_FP_SOFT 3 /* -msoft-float */ -#define MIPS_ABI_FP_OLD_64 4 /* -mips32r2 -mfp64 */ -#define MIPS_ABI_FP_XX 5 /* -mfpxx */ -#define MIPS_ABI_FP_64 6 /* -mips32r2 -mfp64 */ -#define MIPS_ABI_FP_64A 7 /* -mips32r2 -mfp64 -mno-odd-spreg */ +#ifndef ELF_ARCH +/* ELF register definitions */ +#define ELF_NGREG 45 +#define ELF_NFPREG 33 + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #ifdef CONFIG_32BIT -- cgit v1.2.3 From 4a60ad51d660200adcb8bfecda472f0179ff22ec Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 May 2016 07:20:55 +0100 Subject: MIPS: ELF: Unify __MIPS_O32_FP64_MUST_BE_ZERO definitions Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13244/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 25 ++++++++++++------------- arch/mips/kernel/binfmt_elfo32.c | 12 ------------ 2 files changed, 12 insertions(+), 25 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 94fd11953128..68705a0a8014 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -211,19 +211,6 @@ typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #ifdef CONFIG_32BIT - -/* - * In order to be sure that we don't attempt to execute an O32 binary which - * requires 64 bit FP (FR=1) on a system which does not support it we refuse - * to execute any binary which has bits specified by the following macro set - * in its ELF header flags. - */ -#ifdef CONFIG_MIPS_O32_FP64_SUPPORT -# define __MIPS_O32_FP64_MUST_BE_ZERO 0 -#else -# define __MIPS_O32_FP64_MUST_BE_ZERO EF_MIPS_FP64 -#endif - /* * This is used to ensure we don't load something for the wrong architecture. */ @@ -290,6 +277,18 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #endif /* !defined(ELF_ARCH) */ +/* + * In order to be sure that we don't attempt to execute an O32 binary which + * requires 64 bit FP (FR=1) on a system which does not support it we refuse + * to execute any binary which has bits specified by the following macro set + * in its ELF header flags. + */ +#ifdef CONFIG_MIPS_O32_FP64_SUPPORT +# define __MIPS_O32_FP64_MUST_BE_ZERO 0 +#else +# define __MIPS_O32_FP64_MUST_BE_ZERO EF_MIPS_FP64 +#endif + #define mips_elf_check_machine(x) ((x)->e_machine == EM_MIPS) #define vmcore_elf32_check_arch mips_elf_check_machine diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index abd3affe5fb3..ca43eaf1734b 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -27,18 +27,6 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; -/* - * In order to be sure that we don't attempt to execute an O32 binary which - * requires 64 bit FP (FR=1) on a system which does not support it we refuse - * to execute any binary which has bits specified by the following macro set - * in its ELF header flags. - */ -#ifdef CONFIG_MIPS_O32_FP64_SUPPORT -# define __MIPS_O32_FP64_MUST_BE_ZERO 0 -#else -# define __MIPS_O32_FP64_MUST_BE_ZERO EF_MIPS_FP64 -#endif - /* * This is used to ensure we don't load something for the wrong architecture. */ -- cgit v1.2.3 From c9babb1926852d88ebee3c27f2b8bac848560c0e Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 May 2016 07:21:40 +0100 Subject: MIPS: ELF: Unify ABI classification macros Remove a duplicate o32 `elf_check_arch' implementation, move all macro variants to and define them unconditionally under indvidual names, substituting alias `elf_check_arch' definitions in variant code. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13245/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 91 ++++++++++++++++++++++++++-------------- arch/mips/kernel/binfmt_elfn32.c | 16 +------ arch/mips/kernel/binfmt_elfo32.c | 20 +-------- 3 files changed, 62 insertions(+), 65 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 68705a0a8014..f5f45717968e 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -214,25 +214,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(hdr) \ -({ \ - int __res = 1; \ - struct elfhdr *__h = (hdr); \ - \ - if (!mips_elf_check_machine(__h)) \ - __res = 0; \ - if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ - __res = 0; \ - if ((__h->e_flags & EF_MIPS_ABI2) != 0) \ - __res = 0; \ - if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ - ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ - __res = 0; \ - if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ - __res = 0; \ - \ - __res; \ -}) +#define elf_check_arch elfo32_check_arch /* * These are used to set parameters in the core dumps. @@ -245,18 +227,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(hdr) \ -({ \ - int __res = 1; \ - struct elfhdr *__h = (hdr); \ - \ - if (!mips_elf_check_machine(__h)) \ - __res = 0; \ - if (__h->e_ident[EI_CLASS] != ELFCLASS64) \ - __res = 0; \ - \ - __res; \ -}) +#define elf_check_arch elfn64_check_arch /* * These are used to set parameters in the core dumps. @@ -294,6 +265,64 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #define vmcore_elf32_check_arch mips_elf_check_machine #define vmcore_elf64_check_arch mips_elf_check_machine +/* + * Return non-zero if HDR identifies an o32 ELF binary. + */ +#define elfo32_check_arch(hdr) \ +({ \ + int __res = 1; \ + struct elfhdr *__h = (hdr); \ + \ + if (!mips_elf_check_machine(__h)) \ + __res = 0; \ + if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ + __res = 0; \ + if ((__h->e_flags & EF_MIPS_ABI2) != 0) \ + __res = 0; \ + if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ + ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ + __res = 0; \ + if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ + __res = 0; \ + \ + __res; \ +}) + +/* + * Return non-zero if HDR identifies an n64 ELF binary. + */ +#define elfn64_check_arch(hdr) \ +({ \ + int __res = 1; \ + struct elfhdr *__h = (hdr); \ + \ + if (!mips_elf_check_machine(__h)) \ + __res = 0; \ + if (__h->e_ident[EI_CLASS] != ELFCLASS64) \ + __res = 0; \ + \ + __res; \ +}) + +/* + * Return non-zero if HDR identifies an n32 ELF binary. + */ +#define elfn32_check_arch(hdr) \ +({ \ + int __res = 1; \ + struct elfhdr *__h = (hdr); \ + \ + if (!mips_elf_check_machine(__h)) \ + __res = 0; \ + if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ + __res = 0; \ + if (((__h->e_flags & EF_MIPS_ABI2) == 0) || \ + ((__h->e_flags & EF_MIPS_ABI) != 0)) \ + __res = 0; \ + \ + __res; \ +}) + struct mips_abi; extern struct mips_abi mips_abi; diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c index 1b992c6e3d8e..58ad63d7eb42 100644 --- a/arch/mips/kernel/binfmt_elfn32.c +++ b/arch/mips/kernel/binfmt_elfn32.c @@ -30,21 +30,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(hdr) \ -({ \ - int __res = 1; \ - struct elfhdr *__h = (hdr); \ - \ - if (!mips_elf_check_machine(__h)) \ - __res = 0; \ - if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ - __res = 0; \ - if (((__h->e_flags & EF_MIPS_ABI2) == 0) || \ - ((__h->e_flags & EF_MIPS_ABI) != 0)) \ - __res = 0; \ - \ - __res; \ -}) +#define elf_check_arch elfn32_check_arch #define TASK32_SIZE 0x7fff8000UL #undef ELF_ET_DYN_BASE diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index ca43eaf1734b..49fb881481f7 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -30,25 +30,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(hdr) \ -({ \ - int __res = 1; \ - struct elfhdr *__h = (hdr); \ - \ - if (!mips_elf_check_machine(__h)) \ - __res = 0; \ - if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ - __res = 0; \ - if ((__h->e_flags & EF_MIPS_ABI2) != 0) \ - __res = 0; \ - if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ - ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ - __res = 0; \ - if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ - __res = 0; \ - \ - __res; \ -}) +#define elf_check_arch elfo32_check_arch #ifdef CONFIG_KVM_GUEST #define TASK32_SIZE 0x3fff8000UL -- cgit v1.2.3 From 86ce9a340e38bcba664fb11c7ab9ba03fcf5e55e Mon Sep 17 00:00:00 2001 From: Sashka Nochkin Date: Tue, 19 Apr 2016 23:44:45 -0400 Subject: mips: mt7620: fallback to SDRAM when syscfg0 does not have a valid value for the memory type Mediatek MT7620 SoC has syscfg0 bits where it sets the type of memory being used. However, sometimes those bits are not set properly (reading "11"). In this case, the SoC assumes SDRAM. The patch below reflects that. Signed-off-by: Sashka Nochkin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13135/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-ralink/mt7620.h | 1 + arch/mips/ralink/mt7620.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h index ece7420f6562..a73350b07fdf 100644 --- a/arch/mips/include/asm/mach-ralink/mt7620.h +++ b/arch/mips/include/asm/mach-ralink/mt7620.h @@ -72,6 +72,7 @@ #define SYSCFG0_DRAM_TYPE_SDRAM 0 #define SYSCFG0_DRAM_TYPE_DDR1 1 #define SYSCFG0_DRAM_TYPE_DDR2 2 +#define SYSCFG0_DRAM_TYPE_UNKNOWN 3 #define SYSCFG0_DRAM_TYPE_DDR2_MT7628 0 #define SYSCFG0_DRAM_TYPE_DDR1_MT7628 1 diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index 2c623f6bca08..88b82fe21ae6 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -581,11 +581,14 @@ void prom_soc_init(struct ralink_soc_info *soc_info) (rev & CHIP_REV_ECO_MASK)); cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); - if (is_mt76x8()) + if (is_mt76x8()) { dram_type = cfg0 & DRAM_TYPE_MT7628_MASK; - else + } else { dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; + if (dram_type == SYSCFG0_DRAM_TYPE_UNKNOWN) + dram_type = SYSCFG0_DRAM_TYPE_SDRAM; + } soc_info->mem_base = MT7620_DRAM_BASE; if (is_mt76x8()) -- cgit v1.2.3 From 9d1e7875fafc45dbcbe3d816b022aa1f17219f32 Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Mon, 18 Apr 2016 20:58:52 +0200 Subject: MIPS: JZ4740: Probe OHCI platform device via DT The DT fragment will select the ohci-platform driver, since that can handle the JZ4740 OHCI just fine. While I don't have a JZ4740-based board with anything connected to the USB host controller, I did test the generic OHCI driver successfully on a JZ4770-based board. The device is disabled by default; boards that want to use it can override the "status" property. The mass-production Qi LB60 boards don't use the USB host controller. Signed-off-by: Maarten ter Huurne Cc: Lars-Peter Clausen Cc: Paul Cercueil Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13104/ Signed-off-by: Ralf Baechle --- arch/mips/boot/dts/ingenic/jz4740.dtsi | 14 ++++++++++++++ arch/mips/include/asm/mach-jz4740/platform.h | 1 - arch/mips/jz4740/platform.c | 25 ------------------------- 3 files changed, 14 insertions(+), 26 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi index 8b2437cd019f..4a9c8f2a72d6 100644 --- a/arch/mips/boot/dts/ingenic/jz4740.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi @@ -65,4 +65,18 @@ clocks = <&ext>, <&cgu JZ4740_CLK_UART1>; clock-names = "baud", "module"; }; + + uhc: uhc@13030000 { + compatible = "ingenic,jz4740-ohci", "generic-ohci"; + reg = <0x13030000 0x1000>; + + clocks = <&cgu JZ4740_CLK_UHC>; + assigned-clocks = <&cgu JZ4740_CLK_UHC>; + assigned-clock-rates = <48000000>; + + interrupt-parent = <&intc>; + interrupts = <3>; + + status = "disabled"; + }; }; diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h index 32cfbe6a191b..073b8bfbb3b3 100644 --- a/arch/mips/include/asm/mach-jz4740/platform.h +++ b/arch/mips/include/asm/mach-jz4740/platform.h @@ -19,7 +19,6 @@ #include -extern struct platform_device jz4740_usb_ohci_device; extern struct platform_device jz4740_udc_device; extern struct platform_device jz4740_udc_xceiv_device; extern struct platform_device jz4740_mmc_device; diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index e8a463b9b663..2f1dab35c061 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c @@ -32,31 +32,6 @@ #include "clock.h" -/* OHCI controller */ -static struct resource jz4740_usb_ohci_resources[] = { - { - .start = JZ4740_UHC_BASE_ADDR, - .end = JZ4740_UHC_BASE_ADDR + 0x1000 - 1, - .flags = IORESOURCE_MEM, - }, - { - .start = JZ4740_IRQ_UHC, - .end = JZ4740_IRQ_UHC, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device jz4740_usb_ohci_device = { - .name = "jz4740-ohci", - .id = -1, - .dev = { - .dma_mask = &jz4740_usb_ohci_device.dev.coherent_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .num_resources = ARRAY_SIZE(jz4740_usb_ohci_resources), - .resource = jz4740_usb_ohci_resources, -}; - /* USB Device Controller */ struct platform_device jz4740_udc_xceiv_device = { .name = "usb_phy_generic", -- cgit v1.2.3 From 0868971a8dad52e726711a2a4b161ace9ed011fa Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 4 Dec 2015 19:40:00 +0800 Subject: MIPS: CM: Fix compilation error when !MIPS_CM Fix mips_cm_lock_other compilation error when MIPS_CM is not selected. This was introduced in commit 23d5de8efb9a (MIPS: CM: Introduce core-other locking functions) Signed-off-by: Tony Wu Cc: Paul Burton Cc: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11698/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 3fea29e50c46..9411a4c0bdad 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -509,7 +509,7 @@ extern void mips_cm_unlock_other(void); #else /* !CONFIG_MIPS_CM */ -static inline void mips_cm_lock_other(unsigned int core) { } +static inline void mips_cm_lock_other(unsigned int core, unsigned int vp) { } static inline void mips_cm_unlock_other(void) { } #endif /* !CONFIG_MIPS_CM */ -- cgit v1.2.3 From e49d38488515057dba8f0c2ba4cfde5be4a7281f Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 17 May 2016 06:12:27 +0100 Subject: MIPS: MSA: Fix a link error on `_init_msa_upper' with older GCC Fix a build regression from commit c9017757c532 ("MIPS: init upper 64b of vector registers when MSA is first used"): arch/mips/built-in.o: In function `enable_restore_fp_context': traps.c:(.text+0xbb90): undefined reference to `_init_msa_upper' traps.c:(.text+0xbb90): relocation truncated to fit: R_MIPS_26 against `_init_msa_upper' traps.c:(.text+0xbef0): undefined reference to `_init_msa_upper' traps.c:(.text+0xbef0): relocation truncated to fit: R_MIPS_26 against `_init_msa_upper' to !CONFIG_CPU_HAS_MSA configurations with older GCC versions, which are unable to figure out that calls to `_init_msa_upper' are indeed dead. Of the many ways to tackle this failure choose the approach we have already taken in `thread_msa_context_live'. [ralf@linux-mips.org: Drop patch segment to junk file.] Signed-off-by: Maciej W. Rozycki Cc: stable@vger.kernel.org # v3.16+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13271/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/msa.h | 13 +++++++++++++ arch/mips/kernel/traps.c | 6 +++--- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h index bbb85fe21642..6e4effa6f626 100644 --- a/arch/mips/include/asm/msa.h +++ b/arch/mips/include/asm/msa.h @@ -147,6 +147,19 @@ static inline void restore_msa(struct task_struct *t) _restore_msa(t); } +static inline void init_msa_upper(void) +{ + /* + * Check cpu_has_msa only if it's a constant. This will allow the + * compiler to optimise out code for CPUs without MSA without adding + * an extra redundant check for CPUs with MSA. + */ + if (__builtin_constant_p(cpu_has_msa) && !cpu_has_msa) + return; + + _init_msa_upper(); +} + #ifdef TOOLCHAIN_SUPPORTS_MSA #define __BUILD_MSA_CTL_REG(name, cs) \ diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 56f4161b98b9..4a1712b5abdf 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1246,7 +1246,7 @@ static int enable_restore_fp_context(int msa) err = init_fpu(); if (msa && !err) { enable_msa(); - _init_msa_upper(); + init_msa_upper(); set_thread_flag(TIF_USEDMSA); set_thread_flag(TIF_MSA_CTX_LIVE); } @@ -1309,7 +1309,7 @@ static int enable_restore_fp_context(int msa) */ prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE); if (!prior_msa && was_fpu_owner) { - _init_msa_upper(); + init_msa_upper(); goto out; } @@ -1326,7 +1326,7 @@ static int enable_restore_fp_context(int msa) * of each vector register such that it cannot see data left * behind by another task. */ - _init_msa_upper(); + init_msa_upper(); } else { /* We need to restore the vector context. */ restore_msa(current); -- cgit v1.2.3 From bad50d79255a8a479ea63bea89e859bf08fd0f24 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 16 May 2016 12:50:04 +0100 Subject: MIPS: Fix VZ probe gas errors with binutils <2.24 The VZ guest register & TLB access macros introduced in commit "MIPS: Add guest CP0 accessors" use VZ ASE specific instructions that aren't understood by versions of binutils prior to 2.24. Add a check for whether the toolchain supports the -mvirt option, similar to the MSA toolchain check, and implement the accessors using .word if not. Due to difficulty in converting compiler specified registers (e.g. "$3") to usable numbers (e.g. "3") in inline asm, we need to copy to/from a temporary register, namely the assembler temporary (at/$1), and specify guest CP0 registers numerically in the gc0 macros. Fixes: 7eb91118227d ("MIPS: Add guest CP0 accessors") Signed-off-by: James Hogan Reported-by: Guenter Roeck Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: linux-next@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13255/ Signed-off-by: Ralf Baechle --- arch/mips/Makefile | 2 + arch/mips/include/asm/mipsregs.h | 473 ++++++++++++++++++++++++--------------- 2 files changed, 295 insertions(+), 180 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/Makefile b/arch/mips/Makefile index c0b002a09bef..efd7a9dc93c4 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -200,6 +200,8 @@ ifeq ($(CONFIG_CPU_HAS_MSA),y) toolchain-msa := $(call cc-option-yn,$(mips-cflags) -mhard-float -mfp64 -Wa$(comma)-mmsa) cflags-$(toolchain-msa) += -DTOOLCHAIN_SUPPORTS_MSA endif +toolchain-virt := $(call cc-option-yn,$(mips-cflags) -mvirt) +cflags-$(toolchain-virt) += -DTOOLCHAIN_SUPPORTS_VIRT cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_NEVER) += -mcompact-branches=never cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_OPTIMAL) += -mcompact-branches=optimal diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 1019de6bb2a8..25d01577d0b5 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1683,15 +1683,18 @@ do { \ * Macros to access the guest system control coprocessor */ +#ifdef TOOLCHAIN_SUPPORTS_VIRT + #define __read_32bit_gc0_register(source, sel) \ ({ int __res; \ __asm__ __volatile__( \ ".set\tpush\n\t" \ ".set\tmips32r2\n\t" \ ".set\tvirt\n\t" \ - "mfgc0\t%0, " #source ", " #sel "\n\t" \ + "mfgc0\t%0, $%1, %2\n\t" \ ".set\tpop" \ - : "=r" (__res)); \ + : "=r" (__res) \ + : "i" (source), "i" (sel)); \ __res; \ }) @@ -1701,9 +1704,10 @@ do { \ ".set\tpush\n\t" \ ".set\tmips64r2\n\t" \ ".set\tvirt\n\t" \ - "dmfgc0\t%0, " #source ", " #sel "\n\t" \ + "dmfgc0\t%0, $%1, %2\n\t" \ ".set\tpop" \ - : "=r" (__res)); \ + : "=r" (__res) \ + : "i" (source), "i" (sel)); \ __res; \ }) @@ -1713,9 +1717,10 @@ do { \ ".set\tpush\n\t" \ ".set\tmips32r2\n\t" \ ".set\tvirt\n\t" \ - "mtgc0\t%z0, " #register ", " #sel "\n\t" \ + "mtgc0\t%z0, $%1, %2\n\t" \ ".set\tpop" \ - : : "Jr" ((unsigned int)(value))); \ + : : "Jr" ((unsigned int)(value)), \ + "i" (register), "i" (sel)); \ } while (0) #define __write_64bit_gc0_register(register, sel, value) \ @@ -1724,11 +1729,70 @@ do { \ ".set\tpush\n\t" \ ".set\tmips64r2\n\t" \ ".set\tvirt\n\t" \ - "dmtgc0\t%z0, " #register ", " #sel "\n\t" \ + "dmtgc0\t%z0, $%1, %2\n\t" \ + ".set\tpop" \ + : : "Jr" (value), \ + "i" (register), "i" (sel)); \ +} while (0) + +#else /* TOOLCHAIN_SUPPORTS_VIRT */ + +#define __read_32bit_gc0_register(source, sel) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tnoat\n\t" \ + "# mfgc0\t$1, $%1, %2\n\t" \ + ".word\t(0x40610000 | %1 << 11 | %2)\n\t" \ + "move\t%0, $1\n\t" \ + ".set\tpop" \ + : "=r" (__res) \ + : "i" (source), "i" (sel)); \ + __res; \ +}) + +#define __read_64bit_gc0_register(source, sel) \ +({ unsigned long long __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tnoat\n\t" \ + "# dmfgc0\t$1, $%1, %2\n\t" \ + ".word\t(0x40610100 | %1 << 11 | %2)\n\t" \ + "move\t%0, $1\n\t" \ + ".set\tpop" \ + : "=r" (__res) \ + : "i" (source), "i" (sel)); \ + __res; \ +}) + +#define __write_32bit_gc0_register(register, sel, value) \ +do { \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tnoat\n\t" \ + "move\t$1, %0\n\t" \ + "# mtgc0\t$1, $%1, %2\n\t" \ + ".word\t(0x40610200 | %1 << 11 | %2)\n\t" \ ".set\tpop" \ - : : "Jr" (value)); \ + : : "Jr" ((unsigned int)(value)), \ + "i" (register), "i" (sel)); \ } while (0) +#define __write_64bit_gc0_register(register, sel, value) \ +do { \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\tnoat\n\t" \ + "move\t$1, %0\n\t" \ + "# dmtgc0\t$1, $%1, %2\n\t" \ + ".word\t(0x40610300 | %1 << 11 | %2)\n\t" \ + ".set\tpop" \ + : : "Jr" (value), \ + "i" (register), "i" (sel)); \ +} while (0) + +#endif /* !TOOLCHAIN_SUPPORTS_VIRT */ + #define __read_ulong_gc0_register(reg, sel) \ ((sizeof(unsigned long) == 4) ? \ (unsigned long) __read_32bit_gc0_register(reg, sel) : \ @@ -1742,189 +1806,189 @@ do { \ __write_64bit_gc0_register(reg, sel, val); \ } while (0) -#define read_gc0_index() __read_32bit_gc0_register($0, 0) -#define write_gc0_index(val) __write_32bit_gc0_register($0, 0, val) +#define read_gc0_index() __read_32bit_gc0_register(0, 0) +#define write_gc0_index(val) __write_32bit_gc0_register(0, 0, val) -#define read_gc0_entrylo0() __read_ulong_gc0_register($2, 0) -#define write_gc0_entrylo0(val) __write_ulong_gc0_register($2, 0, val) +#define read_gc0_entrylo0() __read_ulong_gc0_register(2, 0) +#define write_gc0_entrylo0(val) __write_ulong_gc0_register(2, 0, val) -#define read_gc0_entrylo1() __read_ulong_gc0_register($3, 0) -#define write_gc0_entrylo1(val) __write_ulong_gc0_register($3, 0, val) +#define read_gc0_entrylo1() __read_ulong_gc0_register(3, 0) +#define write_gc0_entrylo1(val) __write_ulong_gc0_register(3, 0, val) -#define read_gc0_context() __read_ulong_gc0_register($4, 0) -#define write_gc0_context(val) __write_ulong_gc0_register($4, 0, val) +#define read_gc0_context() __read_ulong_gc0_register(4, 0) +#define write_gc0_context(val) __write_ulong_gc0_register(4, 0, val) -#define read_gc0_contextconfig() __read_32bit_gc0_register($4, 1) -#define write_gc0_contextconfig(val) __write_32bit_gc0_register($4, 1, val) +#define read_gc0_contextconfig() __read_32bit_gc0_register(4, 1) +#define write_gc0_contextconfig(val) __write_32bit_gc0_register(4, 1, val) -#define read_gc0_userlocal() __read_ulong_gc0_register($4, 2) -#define write_gc0_userlocal(val) __write_ulong_gc0_register($4, 2, val) +#define read_gc0_userlocal() __read_ulong_gc0_register(4, 2) +#define write_gc0_userlocal(val) __write_ulong_gc0_register(4, 2, val) -#define read_gc0_xcontextconfig() __read_ulong_gc0_register($4, 3) -#define write_gc0_xcontextconfig(val) __write_ulong_gc0_register($4, 3, val) +#define read_gc0_xcontextconfig() __read_ulong_gc0_register(4, 3) +#define write_gc0_xcontextconfig(val) __write_ulong_gc0_register(4, 3, val) -#define read_gc0_pagemask() __read_32bit_gc0_register($5, 0) -#define write_gc0_pagemask(val) __write_32bit_gc0_register($5, 0, val) +#define read_gc0_pagemask() __read_32bit_gc0_register(5, 0) +#define write_gc0_pagemask(val) __write_32bit_gc0_register(5, 0, val) -#define read_gc0_pagegrain() __read_32bit_gc0_register($5, 1) -#define write_gc0_pagegrain(val) __write_32bit_gc0_register($5, 1, val) +#define read_gc0_pagegrain() __read_32bit_gc0_register(5, 1) +#define write_gc0_pagegrain(val) __write_32bit_gc0_register(5, 1, val) -#define read_gc0_segctl0() __read_ulong_gc0_register($5, 2) -#define write_gc0_segctl0(val) __write_ulong_gc0_register($5, 2, val) +#define read_gc0_segctl0() __read_ulong_gc0_register(5, 2) +#define write_gc0_segctl0(val) __write_ulong_gc0_register(5, 2, val) -#define read_gc0_segctl1() __read_ulong_gc0_register($5, 3) -#define write_gc0_segctl1(val) __write_ulong_gc0_register($5, 3, val) +#define read_gc0_segctl1() __read_ulong_gc0_register(5, 3) +#define write_gc0_segctl1(val) __write_ulong_gc0_register(5, 3, val) -#define read_gc0_segctl2() __read_ulong_gc0_register($5, 4) -#define write_gc0_segctl2(val) __write_ulong_gc0_register($5, 4, val) - -#define read_gc0_pwbase() __read_ulong_gc0_register($5, 5) -#define write_gc0_pwbase(val) __write_ulong_gc0_register($5, 5, val) - -#define read_gc0_pwfield() __read_ulong_gc0_register($5, 6) -#define write_gc0_pwfield(val) __write_ulong_gc0_register($5, 6, val) - -#define read_gc0_pwsize() __read_ulong_gc0_register($5, 7) -#define write_gc0_pwsize(val) __write_ulong_gc0_register($5, 7, val) - -#define read_gc0_wired() __read_32bit_gc0_register($6, 0) -#define write_gc0_wired(val) __write_32bit_gc0_register($6, 0, val) - -#define read_gc0_pwctl() __read_32bit_gc0_register($6, 6) -#define write_gc0_pwctl(val) __write_32bit_gc0_register($6, 6, val) - -#define read_gc0_hwrena() __read_32bit_gc0_register($7, 0) -#define write_gc0_hwrena(val) __write_32bit_gc0_register($7, 0, val) - -#define read_gc0_badvaddr() __read_ulong_gc0_register($8, 0) -#define write_gc0_badvaddr(val) __write_ulong_gc0_register($8, 0, val) - -#define read_gc0_badinstr() __read_32bit_gc0_register($8, 1) -#define write_gc0_badinstr(val) __write_32bit_gc0_register($8, 1, val) - -#define read_gc0_badinstrp() __read_32bit_gc0_register($8, 2) -#define write_gc0_badinstrp(val) __write_32bit_gc0_register($8, 2, val) - -#define read_gc0_count() __read_32bit_gc0_register($9, 0) - -#define read_gc0_entryhi() __read_ulong_gc0_register($10, 0) -#define write_gc0_entryhi(val) __write_ulong_gc0_register($10, 0, val) - -#define read_gc0_compare() __read_32bit_gc0_register($11, 0) -#define write_gc0_compare(val) __write_32bit_gc0_register($11, 0, val) - -#define read_gc0_status() __read_32bit_gc0_register($12, 0) -#define write_gc0_status(val) __write_32bit_gc0_register($12, 0, val) - -#define read_gc0_intctl() __read_32bit_gc0_register($12, 1) -#define write_gc0_intctl(val) __write_32bit_gc0_register($12, 1, val) - -#define read_gc0_cause() __read_32bit_gc0_register($13, 0) -#define write_gc0_cause(val) __write_32bit_gc0_register($13, 0, val) - -#define read_gc0_epc() __read_ulong_gc0_register($14, 0) -#define write_gc0_epc(val) __write_ulong_gc0_register($14, 0, val) - -#define read_gc0_ebase() __read_32bit_gc0_register($15, 1) -#define write_gc0_ebase(val) __write_32bit_gc0_register($15, 1, val) - -#define read_gc0_ebase_64() __read_64bit_gc0_register($15, 1) -#define write_gc0_ebase_64(val) __write_64bit_gc0_register($15, 1, val) - -#define read_gc0_config() __read_32bit_gc0_register($16, 0) -#define read_gc0_config1() __read_32bit_gc0_register($16, 1) -#define read_gc0_config2() __read_32bit_gc0_register($16, 2) -#define read_gc0_config3() __read_32bit_gc0_register($16, 3) -#define read_gc0_config4() __read_32bit_gc0_register($16, 4) -#define read_gc0_config5() __read_32bit_gc0_register($16, 5) -#define read_gc0_config6() __read_32bit_gc0_register($16, 6) -#define read_gc0_config7() __read_32bit_gc0_register($16, 7) -#define write_gc0_config(val) __write_32bit_gc0_register($16, 0, val) -#define write_gc0_config1(val) __write_32bit_gc0_register($16, 1, val) -#define write_gc0_config2(val) __write_32bit_gc0_register($16, 2, val) -#define write_gc0_config3(val) __write_32bit_gc0_register($16, 3, val) -#define write_gc0_config4(val) __write_32bit_gc0_register($16, 4, val) -#define write_gc0_config5(val) __write_32bit_gc0_register($16, 5, val) -#define write_gc0_config6(val) __write_32bit_gc0_register($16, 6, val) -#define write_gc0_config7(val) __write_32bit_gc0_register($16, 7, val) - -#define read_gc0_watchlo0() __read_ulong_gc0_register($18, 0) -#define read_gc0_watchlo1() __read_ulong_gc0_register($18, 1) -#define read_gc0_watchlo2() __read_ulong_gc0_register($18, 2) -#define read_gc0_watchlo3() __read_ulong_gc0_register($18, 3) -#define read_gc0_watchlo4() __read_ulong_gc0_register($18, 4) -#define read_gc0_watchlo5() __read_ulong_gc0_register($18, 5) -#define read_gc0_watchlo6() __read_ulong_gc0_register($18, 6) -#define read_gc0_watchlo7() __read_ulong_gc0_register($18, 7) -#define write_gc0_watchlo0(val) __write_ulong_gc0_register($18, 0, val) -#define write_gc0_watchlo1(val) __write_ulong_gc0_register($18, 1, val) -#define write_gc0_watchlo2(val) __write_ulong_gc0_register($18, 2, val) -#define write_gc0_watchlo3(val) __write_ulong_gc0_register($18, 3, val) -#define write_gc0_watchlo4(val) __write_ulong_gc0_register($18, 4, val) -#define write_gc0_watchlo5(val) __write_ulong_gc0_register($18, 5, val) -#define write_gc0_watchlo6(val) __write_ulong_gc0_register($18, 6, val) -#define write_gc0_watchlo7(val) __write_ulong_gc0_register($18, 7, val) - -#define read_gc0_watchhi0() __read_32bit_gc0_register($19, 0) -#define read_gc0_watchhi1() __read_32bit_gc0_register($19, 1) -#define read_gc0_watchhi2() __read_32bit_gc0_register($19, 2) -#define read_gc0_watchhi3() __read_32bit_gc0_register($19, 3) -#define read_gc0_watchhi4() __read_32bit_gc0_register($19, 4) -#define read_gc0_watchhi5() __read_32bit_gc0_register($19, 5) -#define read_gc0_watchhi6() __read_32bit_gc0_register($19, 6) -#define read_gc0_watchhi7() __read_32bit_gc0_register($19, 7) -#define write_gc0_watchhi0(val) __write_32bit_gc0_register($19, 0, val) -#define write_gc0_watchhi1(val) __write_32bit_gc0_register($19, 1, val) -#define write_gc0_watchhi2(val) __write_32bit_gc0_register($19, 2, val) -#define write_gc0_watchhi3(val) __write_32bit_gc0_register($19, 3, val) -#define write_gc0_watchhi4(val) __write_32bit_gc0_register($19, 4, val) -#define write_gc0_watchhi5(val) __write_32bit_gc0_register($19, 5, val) -#define write_gc0_watchhi6(val) __write_32bit_gc0_register($19, 6, val) -#define write_gc0_watchhi7(val) __write_32bit_gc0_register($19, 7, val) - -#define read_gc0_xcontext() __read_ulong_gc0_register($20, 0) -#define write_gc0_xcontext(val) __write_ulong_gc0_register($20, 0, val) - -#define read_gc0_perfctrl0() __read_32bit_gc0_register($25, 0) -#define write_gc0_perfctrl0(val) __write_32bit_gc0_register($25, 0, val) -#define read_gc0_perfcntr0() __read_32bit_gc0_register($25, 1) -#define write_gc0_perfcntr0(val) __write_32bit_gc0_register($25, 1, val) -#define read_gc0_perfcntr0_64() __read_64bit_gc0_register($25, 1) -#define write_gc0_perfcntr0_64(val) __write_64bit_gc0_register($25, 1, val) -#define read_gc0_perfctrl1() __read_32bit_gc0_register($25, 2) -#define write_gc0_perfctrl1(val) __write_32bit_gc0_register($25, 2, val) -#define read_gc0_perfcntr1() __read_32bit_gc0_register($25, 3) -#define write_gc0_perfcntr1(val) __write_32bit_gc0_register($25, 3, val) -#define read_gc0_perfcntr1_64() __read_64bit_gc0_register($25, 3) -#define write_gc0_perfcntr1_64(val) __write_64bit_gc0_register($25, 3, val) -#define read_gc0_perfctrl2() __read_32bit_gc0_register($25, 4) -#define write_gc0_perfctrl2(val) __write_32bit_gc0_register($25, 4, val) -#define read_gc0_perfcntr2() __read_32bit_gc0_register($25, 5) -#define write_gc0_perfcntr2(val) __write_32bit_gc0_register($25, 5, val) -#define read_gc0_perfcntr2_64() __read_64bit_gc0_register($25, 5) -#define write_gc0_perfcntr2_64(val) __write_64bit_gc0_register($25, 5, val) -#define read_gc0_perfctrl3() __read_32bit_gc0_register($25, 6) -#define write_gc0_perfctrl3(val) __write_32bit_gc0_register($25, 6, val) -#define read_gc0_perfcntr3() __read_32bit_gc0_register($25, 7) -#define write_gc0_perfcntr3(val) __write_32bit_gc0_register($25, 7, val) -#define read_gc0_perfcntr3_64() __read_64bit_gc0_register($25, 7) -#define write_gc0_perfcntr3_64(val) __write_64bit_gc0_register($25, 7, val) - -#define read_gc0_errorepc() __read_ulong_gc0_register($30, 0) -#define write_gc0_errorepc(val) __write_ulong_gc0_register($30, 0, val) - -#define read_gc0_kscratch1() __read_ulong_gc0_register($31, 2) -#define read_gc0_kscratch2() __read_ulong_gc0_register($31, 3) -#define read_gc0_kscratch3() __read_ulong_gc0_register($31, 4) -#define read_gc0_kscratch4() __read_ulong_gc0_register($31, 5) -#define read_gc0_kscratch5() __read_ulong_gc0_register($31, 6) -#define read_gc0_kscratch6() __read_ulong_gc0_register($31, 7) -#define write_gc0_kscratch1(val) __write_ulong_gc0_register($31, 2, val) -#define write_gc0_kscratch2(val) __write_ulong_gc0_register($31, 3, val) -#define write_gc0_kscratch3(val) __write_ulong_gc0_register($31, 4, val) -#define write_gc0_kscratch4(val) __write_ulong_gc0_register($31, 5, val) -#define write_gc0_kscratch5(val) __write_ulong_gc0_register($31, 6, val) -#define write_gc0_kscratch6(val) __write_ulong_gc0_register($31, 7, val) +#define read_gc0_segctl2() __read_ulong_gc0_register(5, 4) +#define write_gc0_segctl2(val) __write_ulong_gc0_register(5, 4, val) + +#define read_gc0_pwbase() __read_ulong_gc0_register(5, 5) +#define write_gc0_pwbase(val) __write_ulong_gc0_register(5, 5, val) + +#define read_gc0_pwfield() __read_ulong_gc0_register(5, 6) +#define write_gc0_pwfield(val) __write_ulong_gc0_register(5, 6, val) + +#define read_gc0_pwsize() __read_ulong_gc0_register(5, 7) +#define write_gc0_pwsize(val) __write_ulong_gc0_register(5, 7, val) + +#define read_gc0_wired() __read_32bit_gc0_register(6, 0) +#define write_gc0_wired(val) __write_32bit_gc0_register(6, 0, val) + +#define read_gc0_pwctl() __read_32bit_gc0_register(6, 6) +#define write_gc0_pwctl(val) __write_32bit_gc0_register(6, 6, val) + +#define read_gc0_hwrena() __read_32bit_gc0_register(7, 0) +#define write_gc0_hwrena(val) __write_32bit_gc0_register(7, 0, val) + +#define read_gc0_badvaddr() __read_ulong_gc0_register(8, 0) +#define write_gc0_badvaddr(val) __write_ulong_gc0_register(8, 0, val) + +#define read_gc0_badinstr() __read_32bit_gc0_register(8, 1) +#define write_gc0_badinstr(val) __write_32bit_gc0_register(8, 1, val) + +#define read_gc0_badinstrp() __read_32bit_gc0_register(8, 2) +#define write_gc0_badinstrp(val) __write_32bit_gc0_register(8, 2, val) + +#define read_gc0_count() __read_32bit_gc0_register(9, 0) + +#define read_gc0_entryhi() __read_ulong_gc0_register(10, 0) +#define write_gc0_entryhi(val) __write_ulong_gc0_register(10, 0, val) + +#define read_gc0_compare() __read_32bit_gc0_register(11, 0) +#define write_gc0_compare(val) __write_32bit_gc0_register(11, 0, val) + +#define read_gc0_status() __read_32bit_gc0_register(12, 0) +#define write_gc0_status(val) __write_32bit_gc0_register(12, 0, val) + +#define read_gc0_intctl() __read_32bit_gc0_register(12, 1) +#define write_gc0_intctl(val) __write_32bit_gc0_register(12, 1, val) + +#define read_gc0_cause() __read_32bit_gc0_register(13, 0) +#define write_gc0_cause(val) __write_32bit_gc0_register(13, 0, val) + +#define read_gc0_epc() __read_ulong_gc0_register(14, 0) +#define write_gc0_epc(val) __write_ulong_gc0_register(14, 0, val) + +#define read_gc0_ebase() __read_32bit_gc0_register(15, 1) +#define write_gc0_ebase(val) __write_32bit_gc0_register(15, 1, val) + +#define read_gc0_ebase_64() __read_64bit_gc0_register(15, 1) +#define write_gc0_ebase_64(val) __write_64bit_gc0_register(15, 1, val) + +#define read_gc0_config() __read_32bit_gc0_register(16, 0) +#define read_gc0_config1() __read_32bit_gc0_register(16, 1) +#define read_gc0_config2() __read_32bit_gc0_register(16, 2) +#define read_gc0_config3() __read_32bit_gc0_register(16, 3) +#define read_gc0_config4() __read_32bit_gc0_register(16, 4) +#define read_gc0_config5() __read_32bit_gc0_register(16, 5) +#define read_gc0_config6() __read_32bit_gc0_register(16, 6) +#define read_gc0_config7() __read_32bit_gc0_register(16, 7) +#define write_gc0_config(val) __write_32bit_gc0_register(16, 0, val) +#define write_gc0_config1(val) __write_32bit_gc0_register(16, 1, val) +#define write_gc0_config2(val) __write_32bit_gc0_register(16, 2, val) +#define write_gc0_config3(val) __write_32bit_gc0_register(16, 3, val) +#define write_gc0_config4(val) __write_32bit_gc0_register(16, 4, val) +#define write_gc0_config5(val) __write_32bit_gc0_register(16, 5, val) +#define write_gc0_config6(val) __write_32bit_gc0_register(16, 6, val) +#define write_gc0_config7(val) __write_32bit_gc0_register(16, 7, val) + +#define read_gc0_watchlo0() __read_ulong_gc0_register(18, 0) +#define read_gc0_watchlo1() __read_ulong_gc0_register(18, 1) +#define read_gc0_watchlo2() __read_ulong_gc0_register(18, 2) +#define read_gc0_watchlo3() __read_ulong_gc0_register(18, 3) +#define read_gc0_watchlo4() __read_ulong_gc0_register(18, 4) +#define read_gc0_watchlo5() __read_ulong_gc0_register(18, 5) +#define read_gc0_watchlo6() __read_ulong_gc0_register(18, 6) +#define read_gc0_watchlo7() __read_ulong_gc0_register(18, 7) +#define write_gc0_watchlo0(val) __write_ulong_gc0_register(18, 0, val) +#define write_gc0_watchlo1(val) __write_ulong_gc0_register(18, 1, val) +#define write_gc0_watchlo2(val) __write_ulong_gc0_register(18, 2, val) +#define write_gc0_watchlo3(val) __write_ulong_gc0_register(18, 3, val) +#define write_gc0_watchlo4(val) __write_ulong_gc0_register(18, 4, val) +#define write_gc0_watchlo5(val) __write_ulong_gc0_register(18, 5, val) +#define write_gc0_watchlo6(val) __write_ulong_gc0_register(18, 6, val) +#define write_gc0_watchlo7(val) __write_ulong_gc0_register(18, 7, val) + +#define read_gc0_watchhi0() __read_32bit_gc0_register(19, 0) +#define read_gc0_watchhi1() __read_32bit_gc0_register(19, 1) +#define read_gc0_watchhi2() __read_32bit_gc0_register(19, 2) +#define read_gc0_watchhi3() __read_32bit_gc0_register(19, 3) +#define read_gc0_watchhi4() __read_32bit_gc0_register(19, 4) +#define read_gc0_watchhi5() __read_32bit_gc0_register(19, 5) +#define read_gc0_watchhi6() __read_32bit_gc0_register(19, 6) +#define read_gc0_watchhi7() __read_32bit_gc0_register(19, 7) +#define write_gc0_watchhi0(val) __write_32bit_gc0_register(19, 0, val) +#define write_gc0_watchhi1(val) __write_32bit_gc0_register(19, 1, val) +#define write_gc0_watchhi2(val) __write_32bit_gc0_register(19, 2, val) +#define write_gc0_watchhi3(val) __write_32bit_gc0_register(19, 3, val) +#define write_gc0_watchhi4(val) __write_32bit_gc0_register(19, 4, val) +#define write_gc0_watchhi5(val) __write_32bit_gc0_register(19, 5, val) +#define write_gc0_watchhi6(val) __write_32bit_gc0_register(19, 6, val) +#define write_gc0_watchhi7(val) __write_32bit_gc0_register(19, 7, val) + +#define read_gc0_xcontext() __read_ulong_gc0_register(20, 0) +#define write_gc0_xcontext(val) __write_ulong_gc0_register(20, 0, val) + +#define read_gc0_perfctrl0() __read_32bit_gc0_register(25, 0) +#define write_gc0_perfctrl0(val) __write_32bit_gc0_register(25, 0, val) +#define read_gc0_perfcntr0() __read_32bit_gc0_register(25, 1) +#define write_gc0_perfcntr0(val) __write_32bit_gc0_register(25, 1, val) +#define read_gc0_perfcntr0_64() __read_64bit_gc0_register(25, 1) +#define write_gc0_perfcntr0_64(val) __write_64bit_gc0_register(25, 1, val) +#define read_gc0_perfctrl1() __read_32bit_gc0_register(25, 2) +#define write_gc0_perfctrl1(val) __write_32bit_gc0_register(25, 2, val) +#define read_gc0_perfcntr1() __read_32bit_gc0_register(25, 3) +#define write_gc0_perfcntr1(val) __write_32bit_gc0_register(25, 3, val) +#define read_gc0_perfcntr1_64() __read_64bit_gc0_register(25, 3) +#define write_gc0_perfcntr1_64(val) __write_64bit_gc0_register(25, 3, val) +#define read_gc0_perfctrl2() __read_32bit_gc0_register(25, 4) +#define write_gc0_perfctrl2(val) __write_32bit_gc0_register(25, 4, val) +#define read_gc0_perfcntr2() __read_32bit_gc0_register(25, 5) +#define write_gc0_perfcntr2(val) __write_32bit_gc0_register(25, 5, val) +#define read_gc0_perfcntr2_64() __read_64bit_gc0_register(25, 5) +#define write_gc0_perfcntr2_64(val) __write_64bit_gc0_register(25, 5, val) +#define read_gc0_perfctrl3() __read_32bit_gc0_register(25, 6) +#define write_gc0_perfctrl3(val) __write_32bit_gc0_register(25, 6, val) +#define read_gc0_perfcntr3() __read_32bit_gc0_register(25, 7) +#define write_gc0_perfcntr3(val) __write_32bit_gc0_register(25, 7, val) +#define read_gc0_perfcntr3_64() __read_64bit_gc0_register(25, 7) +#define write_gc0_perfcntr3_64(val) __write_64bit_gc0_register(25, 7, val) + +#define read_gc0_errorepc() __read_ulong_gc0_register(30, 0) +#define write_gc0_errorepc(val) __write_ulong_gc0_register(30, 0, val) + +#define read_gc0_kscratch1() __read_ulong_gc0_register(31, 2) +#define read_gc0_kscratch2() __read_ulong_gc0_register(31, 3) +#define read_gc0_kscratch3() __read_ulong_gc0_register(31, 4) +#define read_gc0_kscratch4() __read_ulong_gc0_register(31, 5) +#define read_gc0_kscratch5() __read_ulong_gc0_register(31, 6) +#define read_gc0_kscratch6() __read_ulong_gc0_register(31, 7) +#define write_gc0_kscratch1(val) __write_ulong_gc0_register(31, 2, val) +#define write_gc0_kscratch2(val) __write_ulong_gc0_register(31, 3, val) +#define write_gc0_kscratch3(val) __write_ulong_gc0_register(31, 4, val) +#define write_gc0_kscratch4(val) __write_ulong_gc0_register(31, 5, val) +#define write_gc0_kscratch5(val) __write_ulong_gc0_register(31, 6, val) +#define write_gc0_kscratch6(val) __write_ulong_gc0_register(31, 7, val) /* * Macros to access the floating point coprocessor control registers @@ -2421,6 +2485,8 @@ static inline void tlb_write_random(void) ".set reorder"); } +#ifdef TOOLCHAIN_SUPPORTS_VIRT + /* * Guest TLB operations. * @@ -2479,6 +2545,53 @@ static inline void guest_tlbinvf(void) ".set pop"); } +#else /* TOOLCHAIN_SUPPORTS_VIRT */ + +/* + * Guest TLB operations. + * + * It is responsibility of the caller to take care of any TLB hazards. + */ +static inline void guest_tlb_probe(void) +{ + __asm__ __volatile__( + "# tlbgp\n\t" + ".word 0x42000010"); +} + +static inline void guest_tlb_read(void) +{ + __asm__ __volatile__( + "# tlbgr\n\t" + ".word 0x42000009"); +} + +static inline void guest_tlb_write_indexed(void) +{ + __asm__ __volatile__( + "# tlbgwi\n\t" + ".word 0x4200000a"); +} + +static inline void guest_tlb_write_random(void) +{ + __asm__ __volatile__( + "# tlbgwr\n\t" + ".word 0x4200000e"); +} + +/* + * Guest TLB Invalidate Flush + */ +static inline void guest_tlbinvf(void) +{ + __asm__ __volatile__( + "# tlbginvf\n\t" + ".word 0x4200000c"); +} + +#endif /* !TOOLCHAIN_SUPPORTS_VIRT */ + /* * Manipulate bits in a register. */ -- cgit v1.2.3