aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorChris Dearman <chris@mips.com>2006-05-08 13:02:16 -0400
committerRalf Baechle <ralf@linux-mips.org>2008-03-12 10:14:40 -0400
commit1f5826bd0ed6c0abec3da28dfffb8d12f0c2cb81 (patch)
tree734b934e846b902faf7d10d4ae104b27956eaeb0 /arch
parent0ec734c2b8b005667ffdaef8610d1024630683b0 (diff)
[MIPS] Added missing cases for rdhwr emulation
Some of these are architecturally required for R2 processors so lets try to be bit closer to the real thing. This also provides access to the CPU cycle timer, even on multiprocessors. In that aspect its currently bug compatible to what would happen on a R2-based SMP. Signed-off-by: Chris Dearman <chris@mips.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/kernel/traps.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index fcae66752972..79cf7e913b99 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -534,8 +534,7 @@ static int simulate_llsc(struct pt_regs *regs, unsigned int opcode)
534 534
535/* 535/*
536 * Simulate trapping 'rdhwr' instructions to provide user accessible 536 * Simulate trapping 'rdhwr' instructions to provide user accessible
537 * registers not implemented in hardware. The only current use of this 537 * registers not implemented in hardware.
538 * is the thread area pointer.
539 */ 538 */
540static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode) 539static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)
541{ 540{
@@ -545,11 +544,31 @@ static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)
545 int rd = (opcode & RD) >> 11; 544 int rd = (opcode & RD) >> 11;
546 int rt = (opcode & RT) >> 16; 545 int rt = (opcode & RT) >> 16;
547 switch (rd) { 546 switch (rd) {
548 case 29: 547 case 0: /* CPU number */
549 regs->regs[rt] = ti->tp_value; 548 regs->regs[rt] = smp_processor_id();
550 return 0; 549 return 0;
550 case 1: /* SYNCI length */
551 regs->regs[rt] = min(current_cpu_data.dcache.linesz,
552 current_cpu_data.icache.linesz);
553 return 0;
554 case 2: /* Read count register */
555 regs->regs[rt] = read_c0_count();
556 return 0;
557 case 3: /* Count register resolution */
558 switch (current_cpu_data.cputype) {
559 case CPU_20KC:
560 case CPU_25KF:
561 regs->regs[rt] = 1;
562 break;
551 default: 563 default:
552 return -1; 564 regs->regs[rt] = 2;
565 }
566 return 0;
567 case 29:
568 regs->regs[rt] = ti->tp_value;
569 return 0;
570 default:
571 return -1;
553 } 572 }
554 } 573 }
555 574