diff --git a/sys/mips/cheri/ccall.S b/sys/mips/cheri/ccall.S index 0c81493..3f2fa8c 100644 --- a/sys/mips/cheri/ccall.S +++ b/sys/mips/cheri/ccall.S @@ -111,6 +111,9 @@ CHERICCall: .set push .set noat + /* Increment the exception counter for ccall, if enabled. */ + INC_EXCEPTION_CNTR(CHERI_CCALL_CNT) + /* * The effective ABI requires that the code capability be in $c0, and * the data capability be in $c1. Throw an exception if this isn't @@ -369,8 +372,12 @@ CHERICReturn: .set push .set noat + /* Increment the exception counter for creturn, if enabled. */ + INC_EXCEPTION_CNTR(CHERI_CRETURN_CNT) + /* Retrieve current PCB pointer. */ - GET_CPU_PCPU(k1) + GET_CPU_PCPU(k1) /* XXXss Redundant if + INC_EXCEPTION_CNTR is enabled. */ PTR_L k1, PC_CURPCB(k1) /* diff --git a/sys/mips/include/asm.h b/sys/mips/include/asm.h index ebb3727..4c53958 100644 --- a/sys/mips/include/asm.h +++ b/sys/mips/include/asm.h @@ -639,6 +639,20 @@ _C_LABEL(x): #define GET_CPU_PCPU(reg) \ PTR_L reg, _C_LABEL(pcpup); +#if 1 /* defined(MIPS_EXC_CNTRS) */ + +#define INC_EXCEPTION_CNTR(name) \ + PTR_L k1, _C_LABEL(pcpup); \ + PTR_L k0, PC_ ## name ## (k1); \ + PTR_ADDIU k0, k0, 1; \ + PTR_S k0, PC_ ## name ## (k1) + +#else /* ! defined(MIPS_EXC_CNTRS) */ + +#define INC_EXCEPTION_CNTR(name) + +#endif /* ! defined(MIPS_EXC_CNTRS) */ + /* * Description of the setjmp buffer * diff --git a/sys/mips/include/pcpu.h b/sys/mips/include/pcpu.h index 89b6525..4cb1aaa 100644 --- a/sys/mips/include/pcpu.h +++ b/sys/mips/include/pcpu.h @@ -33,21 +33,55 @@ #include +#if 1 /* defined(MIPS_EXC_CNTRS) && defined(CPU_CHERI) */ #define PCPU_MD_COMMON_FIELDS \ pd_entry_t *pc_segbase; /* curthread segbase */ \ struct pmap *pc_curpmap; /* pmap of curthread */ \ + register_t pc_tlb_miss_cnt; /* TLB miss count */ \ + register_t pc_tlb_invalid_cnt; /* TLB invalid count */ \ + register_t pc_tlb_mod_cnt; /* TLB modification count */ \ + register_t pc_cheri_ccall_cnt; /* Cheri ccall count */ \ + register_t pc_cheri_creturn_cnt; /* Cheri ccall count */ \ u_int32_t pc_next_asid; /* next ASID to alloc */ \ u_int32_t pc_asid_generation; /* current ASID generation */ \ u_int pc_pending_ipis; /* IPIs pending to this CPU */ +#define PCPU_NUM_EXC_CNTRS 5 + +#elif 0 /* defined(MIPS_EXC_CNTRS) && !defined(CPU_CHERI) */ +#define PCPU_MD_COMMON_FIELDS \ + pd_entry_t *pc_segbase; /* curthread segbase */ \ + struct pmap *pc_curpmap; /* pmap of curthread */ \ + register_t pc_tlb_miss_cnt; /* TLB miss count */ \ + register_t pc_tlb_invalid_cnt; /* TLB invalid count */ \ + register_t pc_tlb_mod_cnt; /* TLB modification count */ \ + u_int32_t pc_next_asid; /* next ASID to alloc */ \ + u_int32_t pc_asid_generation; /* current ASID generation */ \ + u_int pc_pending_ipis; /* IPIs pending to this CPU */ + +#define PCPU_NUM_EXC_CNTRS 3 + +#else /* ! defined(MIPS_EXC_CNTRS) */ + +#define PCPU_MD_COMMON_FIELDS \ + pd_entry_t *pc_segbase; /* curthread segbase */ \ + struct pmap *pc_curpmap; /* pmap of curthread */ \ + u_int32_t pc_next_asid; /* next ASID to alloc */ \ + u_int32_t pc_asid_generation; /* current ASID generation */ \ + u_int pc_pending_ipis; /* IPIs pending to this CPU */ + +#define PCPU_NUM_EXC_CNTRS 0 + +#endif /* ! defined(MIPS_EXC_CNTRS) */ + #ifdef __mips_n64 #define PCPU_MD_MIPS64_FIELDS \ PCPU_MD_COMMON_FIELDS \ - char __pad[61] + char __pad[(61 - (PCPU_NUM_EXC_CNTRS * 8))] #else #define PCPU_MD_MIPS32_FIELDS \ PCPU_MD_COMMON_FIELDS \ - char __pad[133] + char __pad[(133 - (PCPU_NUM_EXC_CNTRS * 4))] #endif #ifdef __mips_n64 diff --git a/sys/mips/include/trap.h b/sys/mips/include/trap.h index 32bf1a8..ad398dc 100644 --- a/sys/mips/include/trap.h +++ b/sys/mips/include/trap.h @@ -113,6 +113,9 @@ void MipsKernGenException(void); void MipsKernIntr(void); void MipsTLBInvalidException(void); void MipsTLBMissException(void); +#if 1 /* defined(MIPS_EXC_CNTRS) */ +void MipsTLBModException(void); +#endif void MipsUserGenException(void); void MipsUserIntr(void); diff --git a/sys/mips/mips/exception.S b/sys/mips/mips/exception.S index fb764b9..00aca46 100644 --- a/sys/mips/mips/exception.S +++ b/sys/mips/mips/exception.S @@ -114,6 +114,9 @@ dtrace_invop_calltrap_addr: VECTOR(MipsTLBMiss, unknown) .set push .set noat + + # Increment exception counter, if enabled. + INC_EXCEPTION_CNTR(TLB_MISS_CNT) #ifdef CPU_CHERI CHERI_EXCEPTION_ENTER(k0) #endif @@ -950,11 +953,27 @@ NESTED_NOPROFILE(MipsUserIntr, CALLFRAME_SIZ, ra) .set at END(MipsUserIntr) +#if 1 /* defined(MIPS_EXC_CNTRS) */ +/* A stub for counting TLB modification exceptions. */ +LEAF_NOPROFILE(MipsTLBModException) + .set push + .set noat + + # Increment exception counter, if enabled. + INC_EXCEPTION_CNTR(TLB_MOD_CNT) + j MipsKernGenException + nop + .set pop +END(MipsTLBModException) +#endif /* defined(MIPS_EXC_CNTRS) */ + LEAF_NOPROFILE(MipsTLBInvalidException) .set push .set noat .set noreorder + # Increment exception counter, if enabled. + INC_EXCEPTION_CNTR(TLB_INVALID_CNT) MFC0 k0, MIPS_COP_0_BAD_VADDR PTR_LI k1, VM_MAXUSER_ADDRESS sltu k1, k0, k1 diff --git a/sys/mips/mips/genassym.c b/sys/mips/mips/genassym.c index 15296b9..1617c0b 100644 --- a/sys/mips/mips/genassym.c +++ b/sys/mips/mips/genassym.c @@ -91,6 +91,15 @@ ASSYM(PC_SEGBASE, offsetof(struct pcpu, pc_segbase)); ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread)); ASSYM(PC_FPCURTHREAD, offsetof(struct pcpu, pc_fpcurthread)); ASSYM(PC_CPUID, offsetof(struct pcpu, pc_cpuid)); +#if 1 /* defined(MIPS_EXC_CNTRS) */ +ASSYM(PC_TLB_MISS_CNT, offsetof(struct pcpu, pc_tlb_miss_cnt)); +ASSYM(PC_TLB_INVALID_CNT, offsetof(struct pcpu, pc_tlb_invalid_cnt)); +ASSYM(PC_TLB_MOD_CNT, offsetof(struct pcpu, pc_tlb_mod_cnt)); +#ifdef CPU_CHERI +ASSYM(PC_CHERI_CCALL_CNT, offsetof(struct pcpu, pc_cheri_ccall_cnt)); +ASSYM(PC_CHERI_CRETURN_CNT, offsetof(struct pcpu, pc_cheri_creturn_cnt)); +#endif /* CPU_CHERI */ +#endif /* defined(MIPS_EXC_CNTRS) */ ASSYM(VM_MAX_KERNEL_ADDRESS, VM_MAX_KERNEL_ADDRESS); ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS); diff --git a/sys/mips/mips/machdep.c b/sys/mips/mips/machdep.c index 87bb2f1..39c28a1 100644 --- a/sys/mips/mips/machdep.c +++ b/sys/mips/mips/machdep.c @@ -486,6 +486,16 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) pcpu->pc_next_asid = 1; pcpu->pc_asid_generation = 1; +#if 1 /* defined(MIPS_EXC_CNTRS) */ + pcpu->pc_tlb_miss_cnt = 0; + pcpu->pc_tlb_invalid_cnt = 0; + pcpu->pc_tlb_mod_cnt = 0; +#ifdef CPU_CHERI + pcpu->pc_cheri_ccall_cnt = 0; + pcpu->pc_cheri_creturn_cnt = 0; +#endif /* CPU_CHERI */ +#endif /* defined(MIPS_EXC_CNTRS) */ + #ifdef SMP if ((vm_offset_t)pcpup >= VM_MIN_KERNEL_ADDRESS && (vm_offset_t)pcpup <= VM_MAX_KERNEL_ADDRESS) { @@ -581,3 +591,96 @@ is_cacheable_mem(vm_paddr_t pa) return (0); } + +#if 1 /* defined((MIPS_EXC_CNTRS) */ +extern int mp_ncpus; +static struct sysctl_ctx_list ctx; + +#if defined(__mips_n64) +static int +sysctl_handler_exc_cnts(SYSCTL_HANDLER_ARGS) +{ + uint64_t tmpout = *((uint64_t *)arg1); + + /* If there is an attempt to write just reset the counter. */ + if (req->newptr) + *((uint64_t *)arg1) = 0; + + return (SYSCTL_OUT(req, &tmpout, sizeof(uint64_t))); +} + +#define SYSCTL_ADD_CNTR(ptr, cpu, name, descr) \ + (void)SYSCTL_ADD_PROC(&ctx, cpuN_tree, OID_AUTO, name, \ + CTLTYPE_U64 | CTLFLAG_RW, ptr, cpu, \ + sysctl_handler_exc_cnts, "QU", descr) + +#else /* ! defined(__mips_n64) */ + +static int +sysctl_handler_exc_cnts(SYSCTL_HANDLER_ARGS) +{ + uint32_t tmpout = *((uint32_t *)arg1); + + /* If there is an attempt to write just reset the counter. */ + if (req->newptr) + *((uint32_t *)arg1) = 0; + + return (SYSCTL_OUT(req, &tmpout, sizeof(uint32_t))); +} + +#define SYSCTL_ADD_CNTR(ptr, cpu, name, descr) \ + (void)SYSCTL_ADD_PROC(&ctx, cpuN_tree, OID_AUTO, name, \ + CTLTYPE_UINT | CTLFLAG_RD, ptr, cpu, \ + sysctl_handler_exc_cnts, "IU", descr) +#endif /* ! defined(__mips_n64) */ + +static void +mips_sysctl_register(void *arg) +{ + /* static uint64_t value = 1234; */ + struct sysctl_oid *cpu_node, *cpuN_node; + struct sysctl_oid_list *cpu_tree, *cpuN_tree; + char cpubuf[5]; + int cpu; + int error = sysctl_ctx_init(&ctx); + + if (error) { + printf("mips_sysctl_register() failed (error = %d)\n", error); + return; + } + + cpu_node = SYSCTL_ADD_NODE(&ctx, SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, + "cpu", CTLFLAG_RD, NULL, "CPU or Core"); + cpu_tree = SYSCTL_CHILDREN(cpu_node); + + /* Foreach CPU... */ + for (cpu = 0; cpu < mp_ncpus; cpu++) { + struct pcpu *pcpupg = (struct pcpu *)pcpu_space[cpu]; + + snprintf(cpubuf, sizeof(cpubuf),"%d", cpu); + cpuN_node = SYSCTL_ADD_NODE(&ctx, cpu_tree, OID_AUTO, cpubuf, + CTLFLAG_RD, NULL, "CPU Number"); + cpuN_tree = SYSCTL_CHILDREN(cpuN_node); + + SYSCTL_ADD_CNTR(&pcpupg->pc_tlb_invalid_cnt, cpu, + "tlb_invalid_cnt", + "TLB invalid exception count for cpu N"); + SYSCTL_ADD_CNTR(&pcpupg->pc_tlb_miss_cnt, cpu, + "tlb_miss_cnt", + "TLB miss exception count for cpu N"); + SYSCTL_ADD_CNTR(&pcpupg->pc_tlb_mod_cnt, cpu, + "tlb_mod_cnt", + "TLB modification exception count for cpu N"); +#ifdef CPU_CHERI + SYSCTL_ADD_CNTR(&pcpupg->pc_cheri_ccall_cnt, cpu, + "cheri_ccall_cnt", + "Cheri ccall exception count for cpu N"); + SYSCTL_ADD_CNTR(&pcpupg->pc_cheri_creturn_cnt, cpu, + "cheri_creturn_cnt", + "Cheri creturn exception count for cpu N"); +#endif /* CPU_CHERI */ + } +} + +SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, mips_sysctl_register, 0); +#endif /* defined((MIPS_EXC_CNTRS) */ diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c index e93644b..6a892d1 100644 --- a/sys/mips/mips/trap.c +++ b/sys/mips/mips/trap.c @@ -186,7 +186,11 @@ void (*machExceptionTable[]) (void)= { * The kernel exception handlers. */ MipsKernIntr, /* external interrupt */ +#if 1 /* defined(MIPS_EXC_CNTRS) */ + MipsTLBModException, /* TLB modification */ +#else MipsKernGenException, /* TLB modification */ +#endif MipsTLBInvalidException,/* TLB miss (load or instr. fetch) */ MipsTLBInvalidException,/* TLB miss (store) */ MipsKernGenException, /* address error (load or I-fetch) */