1/* 2 * Copyright (c) 2005-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * @OSF_FREE_COPYRIGHT@ 30 */ 31/* 32 * @APPLE_FREE_COPYRIGHT@ 33 */ 34 35/* 36 * Author: Bill Angell, Apple 37 * Date: 10/auht-five 38 * 39 * Random diagnostics 40 * 41 * Try to keep the x86 selectors in-sync with the ppc selectors. 42 * 43 */ 44 45 46#include <kern/machine.h> 47#include <kern/processor.h> 48#include <mach/machine.h> 49#include <mach/processor_info.h> 50#include <mach/mach_types.h> 51#include <mach/boolean.h> 52#include <kern/thread.h> 53#include <kern/task.h> 54#include <kern/ipc_kobject.h> 55#include <mach/vm_param.h> 56#include <ipc/port.h> 57#include <ipc/ipc_entry.h> 58#include <ipc/ipc_space.h> 59#include <ipc/ipc_object.h> 60#include <ipc/ipc_port.h> 61#include <vm/vm_kern.h> 62#include <vm/vm_map.h> 63#include <vm/vm_page.h> 64#include <vm/pmap.h> 65#include <pexpert/pexpert.h> 66#include <console/video_console.h> 67#include <i386/cpu_data.h> 68#include <i386/Diagnostics.h> 69#include <i386/mp.h> 70#include <i386/pmCPU.h> 71#include <i386/tsc.h> 72#include <mach/i386/syscall_sw.h> 73 74extern uint64_t lastNapClear; 75 76diagWork dgWork; 77uint64_t lastNapClear = 0ULL; 78uint64_t lastRuptClear = 0ULL; 79 80 81int 82diagCall64(x86_saved_state_t * state) 83{ 84 uint64_t curpos, i, j; 85 uint64_t selector, data; 86 uint64_t currNap, durNap; 87 x86_saved_state64_t *regs; 88 89 assert(is_saved_state64(state)); 90 regs = saved_state64(state); 91 92 if (!(dgWork.dgFlags & enaDiagSCs)) 93 return 0; /* If not enabled, cause an exception */ 94 95 selector = regs->rdi; 96 97 switch (selector) { /* Select the routine */ 98 case dgRuptStat: /* Suck Interruption statistics */ 99 data = regs->rsi; /* Get the number of processors */ 100 101 if (data == 0) { /* If no location is specified for data, clear all 102 * counts 103 */ 104 for (i = 0; i < real_ncpus; i++) { /* Cycle through 105 * processors */ 106 for (j = 0; j < 256; j++) 107 cpu_data_ptr[i]->cpu_hwIntCnt[j] = 0; 108 } 109 110 lastRuptClear = mach_absolute_time(); /* Get the time of clear */ 111 return 1; /* Normal return */ 112 } 113 114 (void) copyout((char *) &real_ncpus, data, sizeof(real_ncpus)); /* Copy out number of 115 * processors */ 116 117 currNap = mach_absolute_time(); /* Get the time now */ 118 durNap = currNap - lastRuptClear; /* Get the last interval 119 * duration */ 120 if (durNap == 0) 121 durNap = 1; /* This is a very short time, make it 122 * bigger */ 123 124 curpos = data + sizeof(real_ncpus); /* Point to the next 125 * available spot */ 126 127 for (i = 0; i < real_ncpus; i++) { /* Move 'em all out */ 128 (void) copyout((char *) &durNap, curpos, 8); /* Copy out the time 129 * since last clear */ 130 (void) copyout((char *) &cpu_data_ptr[i]->cpu_hwIntCnt, curpos + 8, 256 * sizeof(uint32_t)); /* Copy out interrupt 131 * data for this 132 * processor */ 133 curpos = curpos + (256 * sizeof(uint32_t) + 8); /* Point to next out put 134 * slot */ 135 } 136 break; 137 138 default: /* Handle invalid ones */ 139 return 0; /* Return an exception */ 140 141 } 142 143 return 1; /* Normal non-ast check return */ 144} 145 146 147int 148diagCall(x86_saved_state_t * state) 149{ 150 uint32_t stk, curpos, i, j; 151 uint32_t selector, data; 152 int err; 153 uint64_t currNap, durNap; 154 x86_saved_state32_t *regs; 155 156 assert(is_saved_state32(state)); 157 regs = saved_state32(state); 158 159 if (!(dgWork.dgFlags & enaDiagSCs)) 160 return 0; /* If not enabled, cause an exception */ 161 162 stk = regs->uesp; /* Point to the stack */ 163 err = copyin((user_addr_t) (stk + 4), (char *) &selector, sizeof(uint32_t)); /* Get the selector */ 164 if (err) { 165 return 0; /* Failed to fetch stack */ 166 } 167 switch (selector) { /* Select the routine */ 168 case dgRuptStat: /* Suck Interruption statistics */ 169 170 err = copyin((user_addr_t) (stk + 8), (char *) &data, sizeof(uint32_t)); /* Get the selector */ 171 172 if (data == 0) {/* If number of processors is 0, clear all 173 * counts */ 174 for (i = 0; i < real_ncpus; i++) { /* Cycle through 175 * processors */ 176 for (j = 0; j < 256; j++) 177 cpu_data_ptr[i]->cpu_hwIntCnt[j] = 0; 178 } 179 180 lastRuptClear = mach_absolute_time(); /* Get the time of clear */ 181 return 1; /* Normal return */ 182 } 183 184 (void) copyout((char *) &real_ncpus, data, sizeof(real_ncpus)); /* Copy out number of 185 * processors */ 186 187 currNap = mach_absolute_time(); /* Get the time now */ 188 durNap = currNap - lastRuptClear; /* Get the last interval 189 * duration */ 190 if (durNap == 0) 191 durNap = 1; /* This is a very short time, make it 192 * bigger */ 193 194 curpos = data + sizeof(real_ncpus); /* Point to the next 195 * available spot */ 196 197 for (i = 0; i < real_ncpus; i++) { /* Move 'em all out */ 198 (void) copyout((char *) &durNap, curpos, 8); /* Copy out the time 199 * since last clear */ 200 (void) copyout((char *) &cpu_data_ptr[i]->cpu_hwIntCnt, curpos + 8, 256 * sizeof(uint32_t)); /* Copy out interrupt 201 * data for this 202 * processor */ 203 curpos = curpos + (256 * sizeof(uint32_t) + 8); /* Point to next out put 204 * slot */ 205 } 206 207 break; 208 209 default: /* Handle invalid ones */ 210 return 0; /* Return an exception */ 211 212 } 213 214 return 1; /* Normal non-ast check return */ 215} 216