summaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
authorChris Dearman <chris@mips.com>2006-05-08 21:02:16 +0400
committerRalf Baechle <ralf@linux-mips.org>2008-03-12 17:14:40 +0300
commit1f5826bd0ed6c0abec3da28dfffb8d12f0c2cb81 (patch)
tree734b934e846b902faf7d10d4ae104b27956eaeb0 /arch/mips
parent0ec734c2b8b005667ffdaef8610d1024630683b0 (diff)
downloadlinux-1f5826bd0ed6c0abec3da28dfffb8d12f0c2cb81.tar.xz
[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/mips')
-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)
/*
* Simulate trapping 'rdhwr' instructions to provide user accessible
- * registers not implemented in hardware. The only current use of this
- * is the thread area pointer.
+ * registers not implemented in hardware.
*/
static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)
{
@@ -545,11 +544,31 @@ static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)
int rd = (opcode & RD) >> 11;
int rt = (opcode & RT) >> 16;
switch (rd) {
- case 29:
- regs->regs[rt] = ti->tp_value;
- return 0;
+ case 0: /* CPU number */
+ regs->regs[rt] = smp_processor_id();
+ return 0;
+ case 1: /* SYNCI length */
+ regs->regs[rt] = min(current_cpu_data.dcache.linesz,
+ current_cpu_data.icache.linesz);
+ return 0;
+ case 2: /* Read count register */
+ regs->regs[rt] = read_c0_count();
+ return 0;
+ case 3: /* Count register resolution */
+ switch (current_cpu_data.cputype) {
+ case CPU_20KC:
+ case CPU_25KF:
+ regs->regs[rt] = 1;
+ break;
default:
- return -1;
+ regs->regs[rt] = 2;
+ }
+ return 0;
+ case 29:
+ regs->regs[rt] = ti->tp_value;
+ return 0;
+ default:
+ return -1;
}
}