2005-02-07 02:54:29 +00:00
/*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
2006-10-07 19:44:33 +01:00
* Copyright ( C ) 2004 , 05 , 06 by Ralf Baechle
2005-02-07 02:54:29 +00:00
* Copyright ( C ) 2005 by MIPS Technologies , Inc .
*/
2007-12-06 09:12:28 +00:00
# include <linux/cpumask.h>
2005-02-07 02:54:29 +00:00
# include <linux/oprofile.h>
# include <linux/interrupt.h>
# include <linux/smp.h>
2006-10-07 19:44:33 +01:00
# include <asm/irq_regs.h>
2014-09-18 14:47:12 -07:00
# include <asm/time.h>
2005-02-07 02:54:29 +00:00
# include "op_impl.h"
2017-02-06 12:37:45 +00:00
# define M_PERFCTL_EVENT(event) (((event) << MIPS_PERFCTRL_EVENT_S) & \
MIPS_PERFCTRL_EVENT )
# define M_PERFCTL_VPEID(vpe) ((vpe) << MIPS_PERFCTRL_VPEID_S)
2006-06-23 18:39:00 +01:00
2013-01-22 12:59:30 +01:00
# define M_COUNTER_OVERFLOW (1UL << 31)
2006-06-23 18:39:00 +01:00
2008-04-02 03:58:38 +04:00
static int ( * save_perf_irq ) ( void ) ;
2014-09-18 14:47:12 -07:00
static int perfcount_irq ;
2008-04-02 03:58:38 +04:00
2012-10-31 12:01:27 +00:00
/*
* XLR has only one set of counters per core . Designate the
* first hardware thread in the core for setup and init .
* Skip CPUs with non - zero hardware thread id ( 4 hwt per core )
*/
2013-03-25 06:51:52 +00:00
# if defined(CONFIG_CPU_XLR) && defined(CONFIG_SMP)
2012-10-31 12:01:27 +00:00
# define oprofile_skip_cpu(c) ((cpu_logical_map(c) & 0x3) != 0)
# else
# define oprofile_skip_cpu(c) 0
# endif
2006-06-23 18:39:00 +01:00
# ifdef CONFIG_MIPS_MT_SMP
2017-02-06 12:37:45 +00:00
# define WHAT (MIPS_PERFCTRL_MT_EN_VPE | \
2017-08-12 19:49:35 -07:00
M_PERFCTL_VPEID ( cpu_vpe_id ( & current_cpu_data ) ) )
2008-04-28 17:14:26 +01:00
# define vpe_id() (cpu_has_mipsmt_pertccounters ? \
2017-08-12 19:49:35 -07:00
0 : cpu_vpe_id ( & current_cpu_data ) )
2007-12-06 09:12:28 +00:00
/*
* The number of bits to shift to convert between counters per core and
* counters per VPE . There is no reasonable interface atm to obtain the
* number of VPEs used by Linux and in the 34 K this number is fixed to two
* anyways so we hardcore a few things here for the moment . The way it ' s
* done here will ensure that oprofile VSMP kernel will run right on a lesser
* core like a 24 K also or with maxcpus = 1.
*/
static inline unsigned int vpe_shift ( void )
{
if ( num_possible_cpus ( ) > 1 )
return 1 ;
return 0 ;
}
2006-06-23 18:39:00 +01:00
# else
2007-12-06 09:12:28 +00:00
2006-10-23 13:22:06 +01:00
# define WHAT 0
2007-04-24 21:42:20 +01:00
# define vpe_id() 0
2007-12-06 09:12:28 +00:00
static inline unsigned int vpe_shift ( void )
{
return 0 ;
}
2006-06-23 18:39:00 +01:00
# endif
2005-02-07 02:54:29 +00:00
2007-12-06 09:12:28 +00:00
static inline unsigned int counters_total_to_per_cpu ( unsigned int counters )
{
return counters > > vpe_shift ( ) ;
}
static inline unsigned int counters_per_cpu_to_total ( unsigned int counters )
{
return counters < < vpe_shift ( ) ;
}
2006-06-23 18:39:00 +01:00
# define __define_perf_accessors(r, n, np) \
\
static inline unsigned int r_c0_ # # r # # n ( void ) \
{ \
2006-10-23 13:22:06 +01:00
unsigned int cpu = vpe_id ( ) ; \
2006-06-23 18:39:00 +01:00
\
switch ( cpu ) { \
case 0 : \
return read_c0_ # # r # # n ( ) ; \
case 1 : \
return read_c0_ # # r # # np ( ) ; \
default : \
BUG ( ) ; \
} \
2006-07-07 10:38:51 +01:00
return 0 ; \
2006-06-23 18:39:00 +01:00
} \
\
static inline void w_c0_ # # r # # n ( unsigned int value ) \
{ \
2006-10-23 13:22:06 +01:00
unsigned int cpu = vpe_id ( ) ; \
2006-06-23 18:39:00 +01:00
\
switch ( cpu ) { \
case 0 : \
write_c0_ # # r # # n ( value ) ; \
return ; \
case 1 : \
write_c0_ # # r # # np ( value ) ; \
return ; \
default : \
BUG ( ) ; \
} \
2006-07-07 10:38:51 +01:00
return ; \
2006-06-23 18:39:00 +01:00
} \
__define_perf_accessors ( perfcntr , 0 , 2 )
__define_perf_accessors ( perfcntr , 1 , 3 )
2007-03-01 17:58:24 +00:00
__define_perf_accessors ( perfcntr , 2 , 0 )
__define_perf_accessors ( perfcntr , 3 , 1 )
2006-06-23 18:39:00 +01:00
__define_perf_accessors ( perfctrl , 0 , 2 )
__define_perf_accessors ( perfctrl , 1 , 3 )
2007-03-01 17:58:24 +00:00
__define_perf_accessors ( perfctrl , 2 , 0 )
__define_perf_accessors ( perfctrl , 3 , 1 )
2005-02-07 02:54:29 +00:00
2006-05-23 16:42:38 +09:00
struct op_mips_model op_model_mipsxx_ops ;
2005-02-07 02:54:29 +00:00
static struct mipsxx_register_config {
unsigned int control [ 4 ] ;
unsigned int counter [ 4 ] ;
} reg ;
2013-01-22 12:59:30 +01:00
/* Compute all of the registers in preparation for enabling profiling. */
2005-02-07 02:54:29 +00:00
static void mipsxx_reg_setup ( struct op_counter_config * ctr )
{
2006-05-23 16:42:38 +09:00
unsigned int counters = op_model_mipsxx_ops . num_counters ;
2005-02-07 02:54:29 +00:00
int i ;
/* Compute the performance counter control word. */
for ( i = 0 ; i < counters ; i + + ) {
reg . control [ i ] = 0 ;
reg . counter [ i ] = 0 ;
if ( ! ctr [ i ] . enabled )
continue ;
reg . control [ i ] = M_PERFCTL_EVENT ( ctr [ i ] . event ) |
2017-02-06 12:37:45 +00:00
MIPS_PERFCTRL_IE ;
2005-02-07 02:54:29 +00:00
if ( ctr [ i ] . kernel )
2017-02-06 12:37:45 +00:00
reg . control [ i ] | = MIPS_PERFCTRL_K ;
2005-02-07 02:54:29 +00:00
if ( ctr [ i ] . user )
2017-02-06 12:37:45 +00:00
reg . control [ i ] | = MIPS_PERFCTRL_U ;
2005-02-07 02:54:29 +00:00
if ( ctr [ i ] . exl )
2017-02-06 12:37:45 +00:00
reg . control [ i ] | = MIPS_PERFCTRL_EXL ;
2013-08-01 18:31:05 +02:00
if ( boot_cpu_type ( ) = = CPU_XLR )
2017-02-06 12:37:45 +00:00
reg . control [ i ] | = XLR_PERFCTRL_ALLTHREADS ;
2005-02-07 02:54:29 +00:00
reg . counter [ i ] = 0x80000000 - ctr [ i ] . count ;
}
}
2013-01-22 12:59:30 +01:00
/* Program all of the registers in preparation for enabling profiling. */
2005-02-07 02:54:29 +00:00
2007-10-11 23:46:15 +01:00
static void mipsxx_cpu_setup ( void * args )
2005-02-07 02:54:29 +00:00
{
2006-05-23 16:42:38 +09:00
unsigned int counters = op_model_mipsxx_ops . num_counters ;
2005-02-07 02:54:29 +00:00
2012-10-31 12:01:27 +00:00
if ( oprofile_skip_cpu ( smp_processor_id ( ) ) )
return ;
2005-02-07 02:54:29 +00:00
switch ( counters ) {
case 4 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl3 ( 0 ) ;
w_c0_perfcntr3 ( reg . counter [ 3 ] ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 3 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl2 ( 0 ) ;
w_c0_perfcntr2 ( reg . counter [ 2 ] ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 2 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl1 ( 0 ) ;
w_c0_perfcntr1 ( reg . counter [ 1 ] ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 1 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl0 ( 0 ) ;
w_c0_perfcntr0 ( reg . counter [ 0 ] ) ;
2005-02-07 02:54:29 +00:00
}
}
/* Start all counters on current CPU */
static void mipsxx_cpu_start ( void * args )
{
2006-05-23 16:42:38 +09:00
unsigned int counters = op_model_mipsxx_ops . num_counters ;
2005-02-07 02:54:29 +00:00
2012-10-31 12:01:27 +00:00
if ( oprofile_skip_cpu ( smp_processor_id ( ) ) )
return ;
2005-02-07 02:54:29 +00:00
switch ( counters ) {
case 4 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl3 ( WHAT | reg . control [ 3 ] ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 3 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl2 ( WHAT | reg . control [ 2 ] ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 2 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl1 ( WHAT | reg . control [ 1 ] ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 1 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl0 ( WHAT | reg . control [ 0 ] ) ;
2005-02-07 02:54:29 +00:00
}
}
/* Stop all counters on current CPU */
static void mipsxx_cpu_stop ( void * args )
{
2006-05-23 16:42:38 +09:00
unsigned int counters = op_model_mipsxx_ops . num_counters ;
2005-02-07 02:54:29 +00:00
2012-10-31 12:01:27 +00:00
if ( oprofile_skip_cpu ( smp_processor_id ( ) ) )
return ;
2005-02-07 02:54:29 +00:00
switch ( counters ) {
case 4 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl3 ( 0 ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 3 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl2 ( 0 ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 2 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl1 ( 0 ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 1 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl0 ( 0 ) ;
2005-02-07 02:54:29 +00:00
}
}
2006-10-07 19:44:33 +01:00
static int mipsxx_perfcount_handler ( void )
2005-02-07 02:54:29 +00:00
{
2006-05-23 16:42:38 +09:00
unsigned int counters = op_model_mipsxx_ops . num_counters ;
2005-02-07 02:54:29 +00:00
unsigned int control ;
unsigned int counter ;
2007-05-24 22:24:20 +01:00
int handled = IRQ_NONE ;
2015-01-27 21:45:48 +00:00
if ( cpu_has_mips_r2 & & ! ( read_c0_cause ( ) & CAUSEF_PCI ) )
2007-05-24 22:24:20 +01:00
return handled ;
2005-02-07 02:54:29 +00:00
switch ( counters ) {
# define HANDLE_COUNTER(n) \
2019-07-29 18:32:10 -05:00
/* fall through */ \
2005-02-07 02:54:29 +00:00
case n + 1 : \
2006-06-23 18:39:00 +01:00
control = r_c0_perfctrl # # n ( ) ; \
counter = r_c0_perfcntr # # n ( ) ; \
2017-02-06 12:37:45 +00:00
if ( ( control & MIPS_PERFCTRL_IE ) & & \
2005-02-07 02:54:29 +00:00
( counter & M_COUNTER_OVERFLOW ) ) { \
2006-10-07 19:44:33 +01:00
oprofile_add_sample ( get_irq_regs ( ) , n ) ; \
2006-06-23 18:39:00 +01:00
w_c0_perfcntr # # n ( reg . counter [ n ] ) ; \
2007-05-24 22:24:20 +01:00
handled = IRQ_HANDLED ; \
2005-02-07 02:54:29 +00:00
}
HANDLE_COUNTER ( 3 )
HANDLE_COUNTER ( 2 )
HANDLE_COUNTER ( 1 )
HANDLE_COUNTER ( 0 )
}
2005-12-09 12:29:38 +00:00
return handled ;
2005-02-07 02:54:29 +00:00
}
2006-06-23 18:39:00 +01:00
static inline int __n_counters ( void )
2005-02-07 02:54:29 +00:00
{
2016-05-11 13:50:53 +01:00
if ( ! cpu_has_perf )
2005-02-07 02:54:29 +00:00
return 0 ;
2017-02-06 12:37:45 +00:00
if ( ! ( read_c0_perfctrl0 ( ) & MIPS_PERFCTRL_M ) )
2005-02-07 02:54:29 +00:00
return 1 ;
2017-02-06 12:37:45 +00:00
if ( ! ( read_c0_perfctrl1 ( ) & MIPS_PERFCTRL_M ) )
2005-02-07 02:54:29 +00:00
return 2 ;
2017-02-06 12:37:45 +00:00
if ( ! ( read_c0_perfctrl2 ( ) & MIPS_PERFCTRL_M ) )
2005-02-07 02:54:29 +00:00
return 3 ;
return 4 ;
}
2006-06-23 18:39:00 +01:00
static inline int n_counters ( void )
{
2006-10-23 00:44:02 +01:00
int counters ;
2007-10-11 23:46:15 +01:00
switch ( current_cpu_type ( ) ) {
2006-10-23 00:44:02 +01:00
case CPU_R10000 :
counters = 2 ;
2007-02-28 15:34:22 +00:00
break ;
2006-10-23 00:44:02 +01:00
case CPU_R12000 :
case CPU_R14000 :
2015-01-21 07:59:45 -05:00
case CPU_R16000 :
2006-10-23 00:44:02 +01:00
counters = 4 ;
2007-02-28 15:34:22 +00:00
break ;
2006-10-23 00:44:02 +01:00
default :
counters = __n_counters ( ) ;
}
2006-06-23 18:39:00 +01:00
return counters ;
}
2008-04-28 17:14:26 +01:00
static void reset_counters ( void * arg )
2005-02-07 02:54:29 +00:00
{
2008-05-06 11:23:33 +01:00
int counters = ( int ) ( long ) arg ;
2005-02-07 02:54:29 +00:00
switch ( counters ) {
case 4 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl3 ( 0 ) ;
w_c0_perfcntr3 ( 0 ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 3 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl2 ( 0 ) ;
w_c0_perfcntr2 ( 0 ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 2 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl1 ( 0 ) ;
w_c0_perfcntr1 ( 0 ) ;
2019-07-29 18:32:10 -05:00
/* fall through */
2005-02-07 02:54:29 +00:00
case 1 :
2006-06-23 18:39:00 +01:00
w_c0_perfctrl0 ( 0 ) ;
w_c0_perfcntr0 ( 0 ) ;
2005-02-07 02:54:29 +00:00
}
}
2012-05-02 17:33:04 +02:00
static irqreturn_t mipsxx_perfcount_int ( int irq , void * dev_id )
{
return mipsxx_perfcount_handler ( ) ;
}
2005-02-07 02:54:29 +00:00
static int __init mipsxx_init ( void )
{
int counters ;
counters = n_counters ( ) ;
2005-12-09 12:34:45 +00:00
if ( counters = = 0 ) {
printk ( KERN_ERR " Oprofile: CPU has no performance counters \n " ) ;
2005-02-07 02:54:29 +00:00
return - ENODEV ;
2005-12-09 12:34:45 +00:00
}
2005-02-07 02:54:29 +00:00
2008-04-28 17:14:26 +01:00
# ifdef CONFIG_MIPS_MT_SMP
if ( ! cpu_has_mipsmt_pertccounters )
counters = counters_total_to_per_cpu ( counters ) ;
# endif
2008-07-15 22:08:52 +02:00
on_each_cpu ( reset_counters , ( void * ) ( long ) counters , 1 ) ;
2007-03-01 17:58:24 +00:00
2006-05-23 16:42:38 +09:00
op_model_mipsxx_ops . num_counters = counters ;
2007-10-11 23:46:15 +01:00
switch ( current_cpu_type ( ) ) {
2012-07-06 23:56:00 +02:00
case CPU_M14KC :
op_model_mipsxx_ops . cpu_type = " mips/M14Kc " ;
break ;
2012-12-07 03:51:35 +00:00
case CPU_M14KEC :
op_model_mipsxx_ops . cpu_type = " mips/M14KEc " ;
break ;
2005-12-09 12:42:13 +00:00
case CPU_20KC :
2006-05-23 16:42:38 +09:00
op_model_mipsxx_ops . cpu_type = " mips/20K " ;
2005-12-09 12:42:13 +00:00
break ;
2005-02-07 02:54:29 +00:00
case CPU_24K :
2006-05-23 16:42:38 +09:00
op_model_mipsxx_ops . cpu_type = " mips/24K " ;
2005-02-07 02:54:29 +00:00
break ;
2005-12-09 12:42:13 +00:00
case CPU_25KF :
2006-05-23 16:42:38 +09:00
op_model_mipsxx_ops . cpu_type = " mips/25K " ;
2005-12-09 12:42:13 +00:00
break ;
2008-04-28 17:14:26 +01:00
case CPU_1004K :
2006-02-01 17:54:30 +00:00
case CPU_34K :
2006-05-23 16:42:38 +09:00
op_model_mipsxx_ops . cpu_type = " mips/34K " ;
2006-02-01 17:54:30 +00:00
break ;
2006-05-02 14:08:46 +01:00
2014-01-17 15:03:50 -06:00
case CPU_1074K :
2006-05-02 14:08:46 +01:00
case CPU_74K :
2006-05-23 16:42:38 +09:00
op_model_mipsxx_ops . cpu_type = " mips/74K " ;
2006-05-02 14:08:46 +01:00
break ;
2006-02-01 17:54:30 +00:00
2013-11-27 10:07:53 +00:00
case CPU_INTERAPTIV :
op_model_mipsxx_ops . cpu_type = " mips/interAptiv " ;
break ;
2013-11-14 16:12:27 +00:00
case CPU_PROAPTIV :
op_model_mipsxx_ops . cpu_type = " mips/proAptiv " ;
break ;
2014-01-22 16:19:41 +00:00
case CPU_P5600 :
op_model_mipsxx_ops . cpu_type = " mips/P5600 " ;
break ;
2015-07-09 10:40:36 +01:00
case CPU_I6400 :
op_model_mipsxx_ops . cpu_type = " mips/I6400 " ;
break ;
2014-03-04 13:34:43 +00:00
case CPU_M5150 :
op_model_mipsxx_ops . cpu_type = " mips/M5150 " ;
break ;
2005-12-09 12:42:13 +00:00
case CPU_5KC :
2006-05-23 16:42:38 +09:00
op_model_mipsxx_ops . cpu_type = " mips/5K " ;
2005-12-09 12:42:13 +00:00
break ;
2006-10-23 00:44:02 +01:00
case CPU_R10000 :
if ( ( current_cpu_data . processor_id & 0xff ) = = 0x20 )
op_model_mipsxx_ops . cpu_type = " mips/r10000-v2.x " ;
else
op_model_mipsxx_ops . cpu_type = " mips/r10000 " ;
break ;
case CPU_R12000 :
case CPU_R14000 :
op_model_mipsxx_ops . cpu_type = " mips/r12000 " ;
break ;
2015-01-21 07:59:45 -05:00
case CPU_R16000 :
op_model_mipsxx_ops . cpu_type = " mips/r16000 " ;
break ;
2006-01-17 12:06:32 -08:00
case CPU_SB1 :
case CPU_SB1A :
2006-05-23 16:42:38 +09:00
op_model_mipsxx_ops . cpu_type = " mips/sb1 " ;
2006-01-17 12:06:32 -08:00
break ;
2012-06-20 20:05:32 +01:00
case CPU_LOONGSON1 :
op_model_mipsxx_ops . cpu_type = " mips/loongson1 " ;
break ;
2012-10-31 12:01:27 +00:00
case CPU_XLR :
op_model_mipsxx_ops . cpu_type = " mips/xlr " ;
break ;
2005-02-07 02:54:29 +00:00
default :
printk ( KERN_ERR " Profiling unsupported for this CPU \n " ) ;
return - ENODEV ;
}
2008-04-02 03:58:38 +04:00
save_perf_irq = perf_irq ;
2005-02-07 02:54:29 +00:00
perf_irq = mipsxx_perfcount_handler ;
2014-09-18 14:47:12 -07:00
if ( get_c0_perfcount_int )
perfcount_irq = get_c0_perfcount_int ( ) ;
2015-01-27 21:45:49 +00:00
else if ( cp0_perfcount_irq > = 0 )
2014-09-18 14:47:12 -07:00
perfcount_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq ;
else
perfcount_irq = - 1 ;
if ( perfcount_irq > = 0 )
return request_irq ( perfcount_irq , mipsxx_perfcount_int ,
2015-01-27 21:45:54 +00:00
IRQF_PERCPU | IRQF_NOBALANCING |
IRQF_NO_THREAD | IRQF_NO_SUSPEND |
IRQF_SHARED ,
" Perfcounter " , save_perf_irq ) ;
2012-05-02 17:33:04 +02:00
2005-02-07 02:54:29 +00:00
return 0 ;
}
static void mipsxx_exit ( void )
{
2007-03-01 17:58:24 +00:00
int counters = op_model_mipsxx_ops . num_counters ;
2007-12-06 09:12:28 +00:00
2014-09-18 14:47:12 -07:00
if ( perfcount_irq > = 0 )
free_irq ( perfcount_irq , save_perf_irq ) ;
2012-05-02 17:33:04 +02:00
2007-12-06 09:12:28 +00:00
counters = counters_per_cpu_to_total ( counters ) ;
2008-07-15 22:08:52 +02:00
on_each_cpu ( reset_counters , ( void * ) ( long ) counters , 1 ) ;
2005-02-07 02:54:29 +00:00
2008-04-02 03:58:38 +04:00
perf_irq = save_perf_irq ;
2005-02-07 02:54:29 +00:00
}
2006-05-23 16:42:38 +09:00
struct op_mips_model op_model_mipsxx_ops = {
2005-02-07 02:54:29 +00:00
. reg_setup = mipsxx_reg_setup ,
. cpu_setup = mipsxx_cpu_setup ,
. init = mipsxx_init ,
. exit = mipsxx_exit ,
. cpu_start = mipsxx_cpu_start ,
. cpu_stop = mipsxx_cpu_stop ,
} ;