diff options
| author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2006-09-11 04:50:29 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2006-11-29 20:14:44 -0500 |
| commit | 5b10496b6e6577f65b032a5c4c97d0d3a841273c (patch) | |
| tree | 996de253070623043619f893afe8aa244ae88e8a /arch | |
| parent | 656be92f9ae194ed62bc81310a4589a7cd765f13 (diff) | |
[MIPS] Fast path for rdhwr emulation for TLS
Add special short path for emulationg RDHWR which is used to support TLS.
Add an extra prologue for cpu_has_vtag_icache case.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/mips/kernel/genex.S | 63 | ||||
| -rw-r--r-- | arch/mips/kernel/traps.c | 15 |
2 files changed, 77 insertions, 1 deletions
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 5baca16993d0..aacd4a005c5f 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <asm/mipsregs.h> | 19 | #include <asm/mipsregs.h> |
| 20 | #include <asm/stackframe.h> | 20 | #include <asm/stackframe.h> |
| 21 | #include <asm/war.h> | 21 | #include <asm/war.h> |
| 22 | #include <asm/page.h> | ||
| 22 | 23 | ||
| 23 | #define PANIC_PIC(msg) \ | 24 | #define PANIC_PIC(msg) \ |
| 24 | .set push; \ | 25 | .set push; \ |
| @@ -378,6 +379,68 @@ NESTED(nmi_handler, PT_SIZE, sp) | |||
| 378 | BUILD_HANDLER dsp dsp sti silent /* #26 */ | 379 | BUILD_HANDLER dsp dsp sti silent /* #26 */ |
| 379 | BUILD_HANDLER reserved reserved sti verbose /* others */ | 380 | BUILD_HANDLER reserved reserved sti verbose /* others */ |
| 380 | 381 | ||
| 382 | .align 5 | ||
| 383 | LEAF(handle_ri_rdhwr_vivt) | ||
| 384 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 385 | PANIC_PIC("handle_ri_rdhwr_vivt called") | ||
| 386 | #else | ||
| 387 | .set push | ||
| 388 | .set noat | ||
| 389 | .set noreorder | ||
| 390 | /* check if TLB contains a entry for EPC */ | ||
| 391 | MFC0 k1, CP0_ENTRYHI | ||
| 392 | andi k1, 0xff /* ASID_MASK */ | ||
| 393 | MFC0 k0, CP0_EPC | ||
| 394 | PTR_SRL k0, PAGE_SHIFT + 1 | ||
| 395 | PTR_SLL k0, PAGE_SHIFT + 1 | ||
| 396 | or k1, k0 | ||
| 397 | MTC0 k1, CP0_ENTRYHI | ||
| 398 | mtc0_tlbw_hazard | ||
| 399 | tlbp | ||
| 400 | tlb_probe_hazard | ||
| 401 | mfc0 k1, CP0_INDEX | ||
| 402 | .set pop | ||
| 403 | bltz k1, handle_ri /* slow path */ | ||
| 404 | /* fall thru */ | ||
| 405 | #endif | ||
| 406 | END(handle_ri_rdhwr_vivt) | ||
| 407 | |||
| 408 | LEAF(handle_ri_rdhwr) | ||
| 409 | .set push | ||
| 410 | .set noat | ||
| 411 | .set noreorder | ||
| 412 | /* 0x7c03e83b: rdhwr v1,$29 */ | ||
| 413 | MFC0 k1, CP0_EPC | ||
| 414 | lui k0, 0x7c03 | ||
| 415 | lw k1, (k1) | ||
| 416 | ori k0, 0xe83b | ||
| 417 | .set reorder | ||
| 418 | bne k0, k1, handle_ri /* if not ours */ | ||
| 419 | /* The insn is rdhwr. No need to check CAUSE.BD here. */ | ||
| 420 | get_saved_sp /* k1 := current_thread_info */ | ||
| 421 | .set noreorder | ||
| 422 | MFC0 k0, CP0_EPC | ||
| 423 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) | ||
| 424 | ori k1, _THREAD_MASK | ||
| 425 | xori k1, _THREAD_MASK | ||
| 426 | LONG_L v1, TI_TP_VALUE(k1) | ||
| 427 | LONG_ADDIU k0, 4 | ||
| 428 | jr k0 | ||
| 429 | rfe | ||
| 430 | #else | ||
| 431 | LONG_ADDIU k0, 4 /* stall on $k0 */ | ||
| 432 | MTC0 k0, CP0_EPC | ||
| 433 | /* I hope three instructions between MTC0 and ERET are enough... */ | ||
| 434 | ori k1, _THREAD_MASK | ||
| 435 | xori k1, _THREAD_MASK | ||
| 436 | LONG_L v1, TI_TP_VALUE(k1) | ||
| 437 | .set mips3 | ||
| 438 | eret | ||
| 439 | .set mips0 | ||
| 440 | #endif | ||
| 441 | .set pop | ||
| 442 | END(handle_ri_rdhwr) | ||
| 443 | |||
| 381 | #ifdef CONFIG_64BIT | 444 | #ifdef CONFIG_64BIT |
| 382 | /* A temporary overflow handler used by check_daddi(). */ | 445 | /* A temporary overflow handler used by check_daddi(). */ |
| 383 | 446 | ||
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 9fda1b8be3a7..6eccfb49ae68 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
| @@ -54,6 +54,8 @@ extern asmlinkage void handle_dbe(void); | |||
| 54 | extern asmlinkage void handle_sys(void); | 54 | extern asmlinkage void handle_sys(void); |
| 55 | extern asmlinkage void handle_bp(void); | 55 | extern asmlinkage void handle_bp(void); |
| 56 | extern asmlinkage void handle_ri(void); | 56 | extern asmlinkage void handle_ri(void); |
| 57 | extern asmlinkage void handle_ri_rdhwr_vivt(void); | ||
| 58 | extern asmlinkage void handle_ri_rdhwr(void); | ||
| 57 | extern asmlinkage void handle_cpu(void); | 59 | extern asmlinkage void handle_cpu(void); |
| 58 | extern asmlinkage void handle_ov(void); | 60 | extern asmlinkage void handle_ov(void); |
| 59 | extern asmlinkage void handle_tr(void); | 61 | extern asmlinkage void handle_tr(void); |
| @@ -1423,6 +1425,15 @@ void __init set_uncached_handler (unsigned long offset, void *addr, unsigned lon | |||
| 1423 | memcpy((void *)(uncached_ebase + offset), addr, size); | 1425 | memcpy((void *)(uncached_ebase + offset), addr, size); |
| 1424 | } | 1426 | } |
| 1425 | 1427 | ||
| 1428 | static int __initdata rdhwr_noopt; | ||
| 1429 | static int __init set_rdhwr_noopt(char *str) | ||
| 1430 | { | ||
| 1431 | rdhwr_noopt = 1; | ||
| 1432 | return 1; | ||
| 1433 | } | ||
| 1434 | |||
| 1435 | __setup("rdhwr_noopt", set_rdhwr_noopt); | ||
| 1436 | |||
| 1426 | void __init trap_init(void) | 1437 | void __init trap_init(void) |
| 1427 | { | 1438 | { |
| 1428 | extern char except_vec3_generic, except_vec3_r4000; | 1439 | extern char except_vec3_generic, except_vec3_r4000; |
| @@ -1502,7 +1513,9 @@ void __init trap_init(void) | |||
| 1502 | 1513 | ||
| 1503 | set_except_vector(8, handle_sys); | 1514 | set_except_vector(8, handle_sys); |
| 1504 | set_except_vector(9, handle_bp); | 1515 | set_except_vector(9, handle_bp); |
| 1505 | set_except_vector(10, handle_ri); | 1516 | set_except_vector(10, rdhwr_noopt ? handle_ri : |
| 1517 | (cpu_has_vtag_icache ? | ||
| 1518 | handle_ri_rdhwr_vivt : handle_ri_rdhwr)); | ||
| 1506 | set_except_vector(11, handle_cpu); | 1519 | set_except_vector(11, handle_cpu); |
| 1507 | set_except_vector(12, handle_ov); | 1520 | set_except_vector(12, handle_ov); |
| 1508 | set_except_vector(13, handle_tr); | 1521 | set_except_vector(13, handle_tr); |
