Skip to content

Commit bc6e8dc

Browse files
xen0ntsbogend
authored andcommitted
MIPS: handle Loongson-specific GSExc exception
Newer Loongson cores (Loongson-3A R2 and newer) use the implementation-dependent ExcCode 16 to signal Loongson-specific exceptions. The extended cause is put in the non-standard CP0.Diag1 register which is CP0 Register 22 Select 1, called GSCause in Loongson manuals. Inside is an exception code bitfield called GSExcCode, only codes 0 to 6 inclusive are documented (so far, in the Loongson 3A3000 User Manual, Volume 2). During experiments, it was found that some undocumented unprivileged instructions can trigger the also-undocumented GSExcCode 8 on Loongson 3A4000. Processor state is not corrupted, but we cannot continue without further knowledge, and Loongson is not providing that information as of this writing. So we send SIGILL on seeing this exception code to thwart easy local DoS attacks. Other exception codes are made fatal, partly because of insufficient knowledge, also partly because they are not as easily reproduced. None of them are encountered in the wild with upstream kernels and userspace so far. Some older cores (Loongson-3A1000 and Loongson-3B1500) have ExcCode 16 too, but the semantic is equivalent to GSExcCode 0. Because the respective manuals did not mention the CP0.Diag1 register or its read behavior, these cores are not covered in this patch, as MFC0 from non-existent CP0 registers is UNDEFINED according to the MIPS architecture spec. Reviewed-by: Huacai Chen <[email protected]> Signed-off-by: WANG Xuerui <[email protected]> Cc: Huacai Chen <[email protected]> Cc: Jiaxun Yang <[email protected]> Cc: Tiezhu Yang <[email protected]> Signed-off-by: Thomas Bogendoerfer <[email protected]>
1 parent 2480c91 commit bc6e8dc

File tree

6 files changed

+60
-0
lines changed

6 files changed

+60
-0
lines changed

arch/mips/include/asm/cpu-features.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,10 @@
572572
# define cpu_has_ftlbparex __opt(MIPS_CPU_FTLBPAREX)
573573
#endif
574574

575+
#ifndef cpu_has_gsexcex
576+
# define cpu_has_gsexcex __opt(MIPS_CPU_GSEXCEX)
577+
#endif
578+
575579
#ifdef CONFIG_SMP
576580
/*
577581
* Some systems share FTLB RAMs between threads within a core (siblings in

arch/mips/include/asm/cpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ enum cpu_type_enum {
428428
#define MIPS_CPU_MM_FULL BIT_ULL(59) /* CPU supports write-through full merge */
429429
#define MIPS_CPU_MAC_2008_ONLY BIT_ULL(60) /* CPU Only support MAC2008 Fused multiply-add instruction */
430430
#define MIPS_CPU_FTLBPAREX BIT_ULL(61) /* CPU has FTLB parity exception */
431+
#define MIPS_CPU_GSEXCEX BIT_ULL(62) /* CPU has GSExc exception */
431432

432433
/*
433434
* CPU ASE encodings

arch/mips/include/asm/mipsregs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,9 @@
474474
/* Implementation specific trap codes used by MIPS cores */
475475
#define MIPS_EXCCODE_TLBPAR 16 /* TLB parity error exception */
476476

477+
/* Implementation specific trap codes used by Loongson cores */
478+
#define LOONGSON_EXCCODE_GSEXC 16 /* Loongson-specific exception */
479+
477480
/*
478481
* Bits in the coprocessor 0 config register.
479482
*/

arch/mips/kernel/cpu-probe.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2043,6 +2043,9 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
20432043
{
20442044
decode_configs(c);
20452045

2046+
/* All Loongson processors covered here define ExcCode 16 as GSExc. */
2047+
c->options |= MIPS_CPU_GSEXCEX;
2048+
20462049
switch (c->processor_id & PRID_IMP_MASK) {
20472050
case PRID_IMP_LOONGSON_64R: /* Loongson-64 Reduced */
20482051
switch (c->processor_id & PRID_REV_MASK) {

arch/mips/kernel/genex.S

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,19 @@ NESTED(nmi_handler, PT_SIZE, sp)
498498
KMODE
499499
.endm
500500

501+
.macro __build_clear_gsexc
502+
.set push
503+
/*
504+
* We need to specify a selector to access the CP0.Diag1 (GSCause)
505+
* register. All GSExc-equipped processors have MIPS32.
506+
*/
507+
.set mips32
508+
mfc0 a1, CP0_DIAGNOSTIC1
509+
.set pop
510+
TRACE_IRQS_ON
511+
STI
512+
.endm
513+
501514
.macro __BUILD_silent exception
502515
.endm
503516

@@ -556,6 +569,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
556569
BUILD_HANDLER fpe fpe fpe silent /* #15 */
557570
#endif
558571
BUILD_HANDLER ftlb ftlb none silent /* #16 */
572+
BUILD_HANDLER gsexc gsexc gsexc silent /* #16 */
559573
BUILD_HANDLER msa msa sti silent /* #21 */
560574
BUILD_HANDLER mdmx mdmx sti silent /* #22 */
561575
#ifdef CONFIG_HARDWARE_WATCHPOINTS

arch/mips/kernel/traps.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ extern asmlinkage void handle_tr(void);
9090
extern asmlinkage void handle_msa_fpe(void);
9191
extern asmlinkage void handle_fpe(void);
9292
extern asmlinkage void handle_ftlb(void);
93+
extern asmlinkage void handle_gsexc(void);
9394
extern asmlinkage void handle_msa(void);
9495
extern asmlinkage void handle_mdmx(void);
9596
extern asmlinkage void handle_watch(void);
@@ -1900,6 +1901,37 @@ asmlinkage void do_ftlb(void)
19001901
cache_parity_error();
19011902
}
19021903

1904+
asmlinkage void do_gsexc(struct pt_regs *regs, u32 diag1)
1905+
{
1906+
u32 exccode = (diag1 & LOONGSON_DIAG1_EXCCODE) >>
1907+
LOONGSON_DIAG1_EXCCODE_SHIFT;
1908+
enum ctx_state prev_state;
1909+
1910+
prev_state = exception_enter();
1911+
1912+
switch (exccode) {
1913+
case 0x08:
1914+
/* Undocumented exception, will trigger on certain
1915+
* also-undocumented instructions accessible from userspace.
1916+
* Processor state is not otherwise corrupted, but currently
1917+
* we don't know how to proceed. Maybe there is some
1918+
* undocumented control flag to enable the instructions?
1919+
*/
1920+
force_sig(SIGILL);
1921+
break;
1922+
1923+
default:
1924+
/* None of the other exceptions, documented or not, have
1925+
* further details given; none are encountered in the wild
1926+
* either. Panic in case some of them turn out to be fatal.
1927+
*/
1928+
show_regs(regs);
1929+
panic("Unhandled Loongson exception - GSCause = %08x", diag1);
1930+
}
1931+
1932+
exception_exit(prev_state);
1933+
}
1934+
19031935
/*
19041936
* SDBBP EJTAG debug exception handler.
19051937
* We skip the instruction and return to the next instruction.
@@ -2457,6 +2489,9 @@ void __init trap_init(void)
24572489
if (cpu_has_ftlbparex)
24582490
set_except_vector(MIPS_EXCCODE_TLBPAR, handle_ftlb);
24592491

2492+
if (cpu_has_gsexcex)
2493+
set_except_vector(LOONGSON_EXCCODE_GSEXC, handle_gsexc);
2494+
24602495
if (cpu_has_rixiex) {
24612496
set_except_vector(EXCCODE_TLBRI, tlb_do_page_fault_0);
24622497
set_except_vector(EXCCODE_TLBXI, tlb_do_page_fault_0);

0 commit comments

Comments
 (0)