#include <kern/misc_protos.h>
#include <kern/assert.h>
#include <kern/thread.h>
#include <kern/counters.h>
#include <ppc/misc_protos.h>
#include <ppc/trap.h>
#include <ppc/proc_reg.h>
#include <ppc/exception.h>
#include <ppc/savearea.h>
#include <pexpert/pexpert.h>
#include <sys/kdebug.h>
perfTrap perfIntHook = 0;
struct savearea * interrupt(
int type,
struct savearea *ssp,
unsigned int dsisr,
unsigned int dar)
{
int current_cpu, tmpr, targtemp;
unsigned int throttle;
uint64_t now;
thread_act_t act;
disable_preemption();
if(perfIntHook) {
if(perfIntHook(type, ssp, dsisr, dar) == KERN_SUCCESS) return ssp;
}
#if 0
{
extern void fctx_text(void);
fctx_test();
}
#endif
current_cpu = cpu_number();
switch (type) {
case T_THERMAL:
tmpr = ml_read_temp();
targtemp = (dar >> 23) & 0x7F;
if(dar & 4) {
#if 1
kprintf("THERMAL below (cpu %d) target = %d; actual = %d; thrm = %08X\n", current_cpu, targtemp, tmpr, dar);
#endif
#if 0
throttle = ml_throttle(0);
#if 1
kprintf("THERMAL (cpu %d) throttle set off; last = %d\n", current_cpu, throttle);
#endif
#endif
ml_thrm_set(0, per_proc_info[current_cpu].thrm.throttleTemp);
#if 1
kprintf("THERMAL (cpu %d) temp set to: off min, %d max\n", current_cpu, per_proc_info[current_cpu].thrm.throttleTemp);
#endif
}
else {
#if 1
kprintf("THERMAL above (cpu %d) target = %d; actual = %d; thrm = %08X\n", current_cpu, targtemp, tmpr, dar);
#endif
#if 0
throttle = ml_throttle(32);
#if 1
kprintf("THERMAL (cpu %d) throttle set to 32; last = %d\n", current_cpu, throttle);
#endif
#endif
ml_thrm_set(per_proc_info[current_cpu].thrm.throttleTemp - 4, 0);
#if 1
kprintf("THERMAL (cpu %d) temp set to: %d min, off max\n", current_cpu, per_proc_info[current_cpu].thrm.throttleTemp - 4);
#endif
}
break;
case T_DECREMENTER:
KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI, 0) | DBG_FUNC_NONE,
isync_mfdec(), (unsigned int)ssp->save_srr0, 0, 0, 0);
#if 0
if (pcsample_enable) {
if (find_user_regs(current_act()))
add_pcsamples (user_pc(current_act()));
}
#endif
act = current_act();
if(act->mact.qactTimer != 0) {
clock_get_uptime(&now);
if (act->mact.qactTimer <= now) {
act->mact.qactTimer = 0;
if((unsigned int)act->mact.vmmControl & 0xFFFFFFFE) {
vmm_timer_pop(act);
}
}
}
rtclock_intr(0, ssp, 0);
break;
case T_INTERRUPT:
counter_always(c_incoming_interrupts++);
KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_INTR, 0) | DBG_FUNC_START,
current_cpu, (unsigned int)ssp->save_srr0, 0, 0, 0);
per_proc_info[current_cpu].interrupt_handler(
per_proc_info[current_cpu].interrupt_target,
per_proc_info[current_cpu].interrupt_refCon,
per_proc_info[current_cpu].interrupt_nub,
per_proc_info[current_cpu].interrupt_source);
KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_INTR, 0) | DBG_FUNC_END,
0, 0, 0, 0, 0);
break;
case T_SIGP:
cpu_signal_handler();
break;
case T_SHUTDOWN:
cpu_doshutdown();
panic("returning from cpu_doshutdown()\n");
break;
default:
#if MACH_KDP || MACH_KDB
(void)Call_Debugger(type, ssp);
#else
panic("Invalid interrupt type %x\n", type);
#endif
break;
}
enable_preemption();
return ssp;
}