List Info

Thread: CP0 count register




CP0 count register
user name
2007-05-14 19:18:36
I would like to be able to measure the number of clock
cycles a routine
takes in user-space when running on a MIPS in order to
measure the
performance of a routine as accurately as possible.

It seems that the count register on CP0 is what I want to
use, but that
it cannot be accessed from user-space unless the appropriate
bit in
the CP0 status register is set to one.  That is:

mips_cp0_status_write(mips_cp0_status_read() |
MIPS_SR_COP_0_BIT);

Is it possible, at all, to access CP0 in userspace if the
kernel is
modified to allow access to CP0 by user-space? 
documentation such as
http://6004.csail.mit.edu/6.371/handouts/mips6371.pdf
suggests it is,
but that is all I have to work with, and I am not intimately
familiar
with NetBSD on the MIPS CPU.

If it is, I was thinking of modifying
sys/arch/mips/mips/vm_machdep.c 
cpu_lwp_fork() and cpu_setfunc() as follows:

--- vm_machdep.c.orig   2007-05-15 12:07:43.000000000 +1200
+++ vm_machdep.c        2007-05-15 12:14:01.000000000 +1200
 -171,7
+171,12  cpu_lwp_fork(struct lwp *l1, struct lwp 
        pcb->pcb_context[1] = (intptr_t)arg;           
/* S1 */
        pcb->pcb_context[8] = (intptr_t)f;             
/* SP */
        pcb->pcb_context[10] = (intptr_t)proc_trampoline;
      /* RA */
-       pcb->pcb_context[11] |= PSL_LOWIPL;            
/* SR */
+
+       if(kauth_cred_getuid(l2->l_cred) == 0)
+               pcb->pcb_context[11] |= (PSL_LOWIPL |
MIPS_SR_COP_0_BIT);
+       else
+               pcb->pcb_context[11] |= PSL_LOWIPL;      
      /* SR */
+
 #ifdef IPL_ICU_MASK
        pcb->pcb_ppl = 0;       /* machine dependent
interrupt mask */
 #endif
 -195,7
+200,12  cpu_setfunc(struct lwp *l, void (*func)(
        pcb->pcb_context[1] = (intptr_t)arg;             
      /* S1 */
        pcb->pcb_context[8] = (intptr_t)f;               
      /* SP */
        pcb->pcb_context[10] = (intptr_t)proc_trampoline;
      /* RA */
-       pcb->pcb_context[11] |= PSL_LOWIPL;              
      /* SR */
+
+       if(kauth_cred_getuid(l2->l_cred) == 0)
+               pcb->pcb_context[11] |= (PSL_LOWIPL |
MIPS_SR_COP_0_BIT);
+       else
+               pcb->pcb_context[11] |= PSL_LOWIPL;      
      /* SR */
+
 #ifdef IPL_ICU_MASK
        pcb->pcb_ppl = 0;       /* machine depenedend
interrupt mask */
 #endif

Is this likely to work, or am I trying to do something that
the MIPS
CPU working with NetBSD is not able to support?  The
hardware I'm
using is NetBSD/cobalt running 4.0_BETA2 200703090002Z

cpu0 at mainbus0: QED RM5200 CPU (0x28a0) Rev. 10.0 with
built-in FPU Rev. 10.0
cpu0: 32KB/32B 2-way set-associative L1 Instruction cache,
48 TLB entries
cpu0: 32KB/32B 2-way set-associative write-back L1 Data
cache

Thanks

Matthew

Re: CP0 count register
country flaguser name
Australia
2007-05-14 20:55:18
Matthew Luckie wrote:

> I would like to be able to measure the number of clock
cycles a routine
> takes in user-space when running on a MIPS in order to
measure the
> performance of a routine as accurately as possible.
> 
> It seems that the count register on CP0 is what I want
to use, but that
> it cannot be accessed from user-space unless the
appropriate bit in
> the CP0 status register is set to one.  That is:
> 
> mips_cp0_status_write(mips_cp0_status_read() |
MIPS_SR_COP_0_BIT);
> 
> Is it possible, at all, to access CP0 in userspace if
the kernel is
> modified to allow access to CP0 by user-space? 
documentation such as
> http://6004.csail.mit.edu/6.371/handouts/mips6371.pdf
suggests it is,
> but that is all I have to work with, and I am not
intimately familiar
> with NetBSD on the MIPS CPU.
> 
> If it is, I was thinking of modifying
sys/arch/mips/mips/vm_machdep.c 
> cpu_lwp_fork() and cpu_setfunc() as follows:
> 
>   [ ... patch deleted ... ]
> 
> Is this likely to work, or am I trying to do something
that the MIPS
> CPU working with NetBSD is not able to support?  The
hardware I'm
> using is NetBSD/cobalt running 4.0_BETA2 200703090002Z

I'd never have thought to allow CP0 access to user programs.
 Certainly
from a general standpoint you couldn't do this, since then
any user
process can completely corrupt the machine state and
security would be
pretty much non-existant.  That said, it seems like what you
suggest
might work.  Just be _really_ careful which registers you
touch 

I'm guessing the overhead of a gettimeofday(2) system call
is either
too high, or not granular enough?  The way I'd probably go
about this
if I really needed access to CP0 Count would be to add some
sort of
fast path handling.  Perhaps add a new system call number
and check for
it explicitly in MIPSX(SystemCall) before you set up the
kernel stack
frame.  You could do that in a handful of instructions, and
the impact
on normal system calls should be quite minimal.

Interestingly the Release 2 versions of the MIPS32 and
MIPS64 specs
which have only been out a few years do allow for user
programs
reading the CP0 Count register (through a new "read
hardware register"
instruction), but I'm not sure if there are any Release 2
CPUs supported
by NetBSD.  But that doesn't help you right now :-(

Cheers,
Simon.

[1-2]

about | contact  Other archives ( Real Estate discussion Medical topics )