]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ppc/cpu.c
xnu-517.7.7.tar.gz
[apple/xnu.git] / osfmk / ppc / cpu.c
index a7d32465ba3fe10797c6af900f7d6f3926dc44aa..3e66ab9c0e59fce009bcb82c144310a39ff68b45 100644 (file)
 #include <ppc/machine_routines.h>
 #include <ppc/machine_cpu.h>
 #include <ppc/exception.h>
+#include <ppc/asm.h>
+#include <ppc/hw_perfmon.h>
 #include <pexpert/pexpert.h>
-//#include <pexpert/ppc/powermac.h>
+#include <kern/cpu_data.h>
+#include <ppc/mappings.h>
+#include <ppc/Diagnostics.h>
+#include <ppc/trap.h>
 
 /* TODO: BOGUS TO BE REMOVED */
 int real_ncpus = 1;
@@ -62,6 +67,8 @@ struct SIGtimebase {
        uint64_t        abstime;
 };
 
+struct per_proc_info   *pper_proc_info = per_proc_info; 
 extern struct SIGtimebase syncClkSpot;
 
 void cpu_sync_timebase(void);
@@ -89,20 +96,15 @@ cpu_control(
             cpu_subtype != cmd->cmd_cpu_subtype)
          return(KERN_FAILURE);
 
+       if (perfmon_acquire_facility(current_task()) != KERN_SUCCESS) {
+               return(KERN_RESOURCE_SHORTAGE); /* cpu performance facility in use by another task */
+       }
+
        switch (cmd->cmd_op)
          {
          case PROCESSOR_PM_CLR_PMC:       /* Clear Performance Monitor Counters */
            switch (cpu_subtype)
              {
-             case CPU_SUBTYPE_POWERPC_604:
-               {
-                 oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
-                 mtpmc1(0x0);
-                 mtpmc2(0x0);
-                 ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
-                 return(KERN_SUCCESS);
-               }
-             case CPU_SUBTYPE_POWERPC_604e:
              case CPU_SUBTYPE_POWERPC_750:
              case CPU_SUBTYPE_POWERPC_7400:
              case CPU_SUBTYPE_POWERPC_7450:
@@ -121,21 +123,6 @@ cpu_control(
          case PROCESSOR_PM_SET_REGS:      /* Set Performance Monitor Registors */
            switch (cpu_subtype)
              {
-             case CPU_SUBTYPE_POWERPC_604:
-               if (count <  (PROCESSOR_CONTROL_CMD_COUNT 
-                              + PROCESSOR_PM_REGS_COUNT_POWERPC_604))
-                 return(KERN_FAILURE);
-               else
-                 {
-                   perf_regs = (processor_pm_regs_t)cmd->cmd_pm_regs;
-                   oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
-                   mtmmcr0(PERFMON_MMCR0(perf_regs) & MMCR0_SUPPORT_MASK);
-                   mtpmc1(PERFMON_PMC1(perf_regs));
-                   mtpmc2(PERFMON_PMC2(perf_regs));
-                   ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
-                   return(KERN_SUCCESS);
-                 }
-             case CPU_SUBTYPE_POWERPC_604e:
              case CPU_SUBTYPE_POWERPC_750:
                if (count <  (PROCESSOR_CONTROL_CMD_COUNT +
                       PROCESSOR_PM_REGS_COUNT_POWERPC_750))
@@ -178,17 +165,6 @@ cpu_control(
          case PROCESSOR_PM_SET_MMCR:
            switch (cpu_subtype)
              {
-             case CPU_SUBTYPE_POWERPC_604:
-               if (count < (PROCESSOR_CONTROL_CMD_COUNT +
-                      PROCESSOR_PM_REGS_COUNT_POWERPC_604))
-                 return(KERN_FAILURE);
-               else
-                 {
-                   perf_regs = (processor_pm_regs_t)cmd->cmd_pm_regs;
-                   mtmmcr0(PERFMON_MMCR0(perf_regs) & MMCR0_SUPPORT_MASK);
-                   return(KERN_SUCCESS);
-                 }
-             case CPU_SUBTYPE_POWERPC_604e:
              case CPU_SUBTYPE_POWERPC_750:
                if (count < (PROCESSOR_CONTROL_CMD_COUNT +
                      PROCESSOR_PM_REGS_COUNT_POWERPC_750))
@@ -239,11 +215,6 @@ cpu_info_count(
        switch (flavor) {
                case PROCESSOR_PM_REGS_INFO:
                        switch (cpu_subtype) {
-                               case CPU_SUBTYPE_POWERPC_604:
-                                       *count = PROCESSOR_PM_REGS_COUNT_POWERPC_604;
-                                       return(KERN_SUCCESS);
-
-                               case CPU_SUBTYPE_POWERPC_604e:
                                case CPU_SUBTYPE_POWERPC_750:
                
                                        *count = PROCESSOR_PM_REGS_COUNT_POWERPC_750;
@@ -291,21 +262,6 @@ cpu_info(
                        perf_regs = (processor_pm_regs_t) info;
 
                        switch (cpu_subtype) {
-                               case CPU_SUBTYPE_POWERPC_604:
-
-                                       if (*count < PROCESSOR_PM_REGS_COUNT_POWERPC_604)
-                                         return(KERN_FAILURE);
-                                 
-                                       oldlevel = ml_set_interrupts_enabled(FALSE);    /* disable interrupts */
-                                       PERFMON_MMCR0(perf_regs) = mfmmcr0();
-                                       PERFMON_PMC1(perf_regs)  = mfpmc1();
-                                       PERFMON_PMC2(perf_regs)  = mfpmc2();
-                                       ml_set_interrupts_enabled(oldlevel);     /* enable interrupts */
-               
-                                       *count = PROCESSOR_PM_REGS_COUNT_POWERPC_604;
-                                       return(KERN_SUCCESS);
-
-                               case CPU_SUBTYPE_POWERPC_604e:
                                case CPU_SUBTYPE_POWERPC_750:
 
                                        if (*count < PROCESSOR_PM_REGS_COUNT_POWERPC_750)
@@ -442,8 +398,8 @@ cpu_start(
 {
        struct per_proc_info    *proc_info;
        kern_return_t           ret;
+       mapping *mp;
 
-       extern void (*exception_handlers[])(void);
        extern vm_offset_t      intstack;
        extern vm_offset_t      debstack;
 
@@ -460,29 +416,27 @@ cpu_start(
 
                proc_info->cpu_number = cpu;
                proc_info->cpu_flags &= BootDone;
-               proc_info->istackptr = (vm_offset_t)&intstack + (INTSTACK_SIZE*(cpu+1)) - sizeof (struct ppc_saved_state);
+               proc_info->istackptr = (vm_offset_t)&intstack + (INTSTACK_SIZE*(cpu+1)) - FM_SIZE;
                proc_info->intstack_top_ss = proc_info->istackptr;
 #if     MACH_KDP || MACH_KDB
-               proc_info->debstackptr = (vm_offset_t)&debstack + (KERNEL_STACK_SIZE*(cpu+1)) - sizeof (struct ppc_saved_state);
+               proc_info->debstackptr = (vm_offset_t)&debstack + (KERNEL_STACK_SIZE*(cpu+1)) - FM_SIZE;
                proc_info->debstack_top_ss = proc_info->debstackptr;
 #endif  /* MACH_KDP || MACH_KDB */
                proc_info->interrupts_enabled = 0;
-               proc_info->active_kloaded = (unsigned int)&active_kloaded[cpu];
-               proc_info->cpu_data = (unsigned int)&cpu_data[cpu];
-               proc_info->active_stacks = (unsigned int)&active_stacks[cpu];
                proc_info->need_ast = (unsigned int)&need_ast[cpu];
-               proc_info->FPU_thread = 0;
-               proc_info->FPU_vmmCtx = 0;
-               proc_info->VMX_thread = 0;
-               proc_info->VMX_vmmCtx = 0;
+               proc_info->FPU_owner = 0;
+               proc_info->VMX_owner = 0;
+               mp = (mapping *)(&proc_info->ppCIOmp);
+               mp->mpFlags = 0x01000000 | mpSpecial | 1;
+               mp->mpSpace = invalSpace;
 
                if (proc_info->start_paddr == EXCEPTION_VECTOR(T_RESET)) {
 
                        /* TODO: get mutex lock reset_handler_lock */
 
                        resethandler_target.type = RESET_HANDLER_START;
-                       resethandler_target.call_paddr = kvtophys((vm_offset_t)_start_cpu); 
-                       resethandler_target.arg__paddr = kvtophys((vm_offset_t)proc_info);
+                       resethandler_target.call_paddr = (vm_offset_t)_start_cpu;       /* Note: these routines are always V=R */
+                       resethandler_target.arg__paddr = (vm_offset_t)proc_info;        /* Note: these routines are always V=R */
                        
                        ml_phys_write((vm_offset_t)&ResetHandler + 0,
                                      resethandler_target.type);
@@ -499,7 +453,7 @@ cpu_start(
  *             that all processors are the same.  This is just to get close.
  */
 
-               ml_get_timebase(&proc_info->ruptStamp); /* Pass our current time to the other guy */
+               ml_get_timebase((unsigned long long *)&proc_info->ruptStamp);   /* Pass our current time to the other guy */
                
                __asm__ volatile("sync");                               /* Commit to storage */
                __asm__ volatile("isync");                              /* Wait a second */
@@ -515,6 +469,8 @@ cpu_start(
        }
 }
 
+perfTrap perfCpuSigHook = 0;            /* Pointer to CHUD cpu signal hook routine */
+
 /*
  *     Here is where we implement the receiver of the signaling protocol.
  *     We wait for the signal status area to be passed to us. Then we snarf
@@ -538,10 +494,10 @@ cpu_signal_handler(
        pproc = &per_proc_info[cpu];                                    /* Point to our block */
 
 /*
- *     Since we've been signaled, wait just under 1ms for the signal lock to pass
+ *     Since we've been signaled, wait about 31 ms for the signal lock to pass
  */
-       if(!hw_lock_mbits(&pproc->MPsigpStat, MPsigpMsgp, (MPsigpBusy | MPsigpPass),
-         (MPsigpBusy | MPsigpPass), (gPEClockFrequencyInfo.bus_clock_rate_hz >> 7))) {
+       if(!hw_lock_mbits(&pproc->MPsigpStat, (MPsigpMsgp | MPsigpAck), (MPsigpBusy | MPsigpPass),
+         (MPsigpBusy | MPsigpPass | MPsigpAck), (gPEClockFrequencyInfo.timebase_frequency_hz >> 5))) {
                panic("cpu_signal_handler: Lock pass timed out\n");
        }
        
@@ -552,7 +508,7 @@ cpu_signal_handler(
        
        __asm__ volatile("isync");                                              /* Make sure we don't unlock until memory is in */
 
-       pproc->MPsigpStat = holdStat & ~(MPsigpMsgp | MPsigpFunc);      /* Release lock */
+       pproc->MPsigpStat = holdStat & ~(MPsigpMsgp | MPsigpAck | MPsigpFunc);  /* Release lock */
 
        switch ((holdStat & MPsigpFunc) >> 8) {                 /* Decode function code */
 
@@ -564,18 +520,16 @@ cpu_signal_handler(
                        switch (holdParm0) {                                    /* Decode SIGP message order */
 
                                case SIGPast:                                           /* Should we do an AST? */
-                                       pproc->numSIGPast++;                    /* Count this one */
+                                       pproc->hwCtr.numSIGPast++;              /* Count this one */
 #if 0
                                        kprintf("cpu_signal_handler: AST check on cpu %x\n", cpu_number());
 #endif
-                                       ast_check();                                    /* Yes, do it */
-                                       /* XXX: Should check if AST_URGENT is needed */
-                                       ast_on(AST_URGENT);
+                                       ast_check(cpu_to_processor(cpu));
                                        return;                                                 /* All done... */
                                        
                                case SIGPcpureq:                                        /* CPU specific function? */
                                
-                                       pproc->numSIGPcpureq++;                 /* Count this one */
+                                       pproc->hwCtr.numSIGPcpureq++;   /* Count this one */
                                        switch (holdParm1) {                    /* Select specific function */
                                        
                                                case CPRQtemp:                          /* Get the temperature */
@@ -616,6 +570,25 @@ cpu_signal_handler(
 
                                                        return;
 
+                                               case CPRQsegload:
+                                                       return;
+                                               
+                                               case CPRQchud:
+                                                       parmAddr = (unsigned int *)holdParm2;   /* Get the destination address */
+                                                       if(perfCpuSigHook) {
+                                                               struct savearea *ssp = current_act()->mact.pcb;
+                                                               if(ssp) {
+                                                                       (perfCpuSigHook)(parmAddr[1] /* request */, ssp, 0, 0);
+                                                               }
+                                                       }
+                                                       parmAddr[1] = 0;
+                                                       parmAddr[0] = 0;                /* Show we're done */
+                                                       return;
+                                               
+                                               case CPRQscom:
+                                                       fwSCOM((scomcomm *)holdParm2);  /* Do the function */
+                                                       return;
+
                                                default:
                                                        panic("cpu_signal_handler: unknown CPU request - %08X\n", holdParm1);
                                                        return;
@@ -624,14 +597,14 @@ cpu_signal_handler(
        
                                case SIGPdebug:                                         /* Enter the debugger? */               
 
-                                       pproc->numSIGPdebug++;                  /* Count this one */
+                                       pproc->hwCtr.numSIGPdebug++;    /* Count this one */
                                        debugger_is_slave[cpu]++;               /* Bump up the count to show we're here */
                                        hw_atomic_sub(&debugger_sync, 1);       /* Show we've received the 'rupt */
                                        __asm__ volatile("tw 4,r3,r3"); /* Enter the debugger */
                                        return;                                                 /* All done now... */
                                        
                                case SIGPwake:                                          /* Wake up CPU */
-                                       pproc->numSIGPwake++;                   /* Count this one */
+                                       pproc->hwCtr.numSIGPwake++;             /* Count this one */
                                        return;                                                 /* No need to do anything, the interrupt does it all... */
                                        
                                default:
@@ -673,6 +646,7 @@ cpu_signal(
        unsigned int holdStat, holdParm0, holdParm1, holdParm2, mtype;
        struct per_proc_info *tpproc, *mpproc;                  /* Area for per_proc addresses */
        int cpu;
+       int busybitset =0;
 
 #if DEBUG
        if(target > NCPUS) panic("cpu_signal: invalid target CPU - %08X\n", target);
@@ -686,18 +660,32 @@ cpu_signal(
        tpproc = &per_proc_info[target];                                /* Point to the target's block */
 
        if (!(tpproc->cpu_flags & SignalReady)) return KERN_FAILURE;
-       
+               
        if((tpproc->MPsigpStat & MPsigpMsgp) == MPsigpMsgp) {   /* Is there an unreceived message already pending? */
 
-               if(signal == SIGPwake) return KERN_SUCCESS;                     /* SIGPwake can merge into all others... */
+               if(signal == SIGPwake) {                                        /* SIGPwake can merge into all others... */
+                       mpproc->hwCtr.numSIGPmwake++;                   /* Account for merged wakes */
+                       return KERN_SUCCESS;
+               }
 
                if((signal == SIGPast) && (tpproc->MPsigpParm0 == SIGPast)) {   /* We can merge ASTs */
+                       mpproc->hwCtr.numSIGPmast++;                    /* Account for merged ASTs */
                        return KERN_SUCCESS;                                    /* Don't bother to send this one... */
                }
+
+               if (tpproc->MPsigpParm0 == SIGPwake) {
+                       if (hw_lock_mbits(&tpproc->MPsigpStat, (MPsigpMsgp | MPsigpAck), 
+                                         (MPsigpBusy | MPsigpPass ), MPsigpBusy, 0)) {
+                               busybitset = 1;
+                               mpproc->hwCtr.numSIGPmwake++;   
+                       }
+               }
        }       
        
-       if(!hw_lock_mbits(&tpproc->MPsigpStat, MPsigpMsgp, 0, MPsigpBusy, 
-         (gPEClockFrequencyInfo.bus_clock_rate_hz >> 13))) {   /* Try to lock the message block with a .5ms timeout */
+       if((busybitset == 0) && 
+          (!hw_lock_mbits(&tpproc->MPsigpStat, MPsigpMsgp, 0, MPsigpBusy, 
+          (gPEClockFrequencyInfo.timebase_frequency_hz >> 11)))) {     /* Try to lock the message block with a .5ms timeout */
+               mpproc->hwCtr.numSIGPtimo++;                            /* Account for timeouts */
                return KERN_FAILURE;                                            /* Timed out, take your ball and go home... */
        }
 
@@ -711,7 +699,8 @@ cpu_signal(
        tpproc->MPsigpStat = holdStat;                                  /* Set status and pass the lock */
        __asm__ volatile("eieio");                                              /* I'm a paraniod freak */
        
-       PE_cpu_signal(mpproc->cpu_id, tpproc->cpu_id);  /* Kick the other processor */
+       if (busybitset == 0)
+               PE_cpu_signal(mpproc->cpu_id, tpproc->cpu_id);  /* Kick the other processor */
 
        return KERN_SUCCESS;                                                    /* All is goodness and rainbows... */
 }
@@ -720,7 +709,8 @@ void
 cpu_doshutdown(
        void)
 {
-       processor_doshutdown(current_processor());
+       enable_preemption();
+       processor_offline(current_processor());
 }
 
 void
@@ -728,31 +718,31 @@ cpu_sleep(
        void)
 {
        struct per_proc_info    *proc_info;
-       unsigned int    cpu;
-       extern void (*exception_handlers[])(void);
+       unsigned int    cpu, i;
+       unsigned int    wait_ncpus_sleep, ncpus_sleep;
+       facility_context *fowner;
        extern vm_offset_t      intstack;
        extern vm_offset_t      debstack;
        extern void _restart_cpu(void);
 
        cpu = cpu_number();
-#if 0
-       kprintf("******* About to sleep cpu %d\n", cpu);
-#endif
 
        proc_info = &per_proc_info[cpu];
 
-       if(proc_info->FPU_thread) fpu_save(proc_info->FPU_thread);      /* If anyone owns FPU, save it */
-       proc_info->FPU_thread = 0;                                              /* Set no fpu owner now */
+       fowner = proc_info->FPU_owner;                                  /* Cache this */
+       if(fowner) fpu_save(fowner);                                    /* If anyone owns FPU, save it */
+       proc_info->FPU_owner = 0;                                               /* Set no fpu owner now */
 
-       if(proc_info->VMX_thread) vec_save(proc_info->VMX_thread);      /* If anyone owns vectors, save it */
-       proc_info->VMX_thread = 0;                                              /* Set no vector owner now */
+       fowner = proc_info->VMX_owner;                                  /* Cache this */
+       if(fowner) vec_save(fowner);                                    /* If anyone owns vectors, save it */
+       proc_info->VMX_owner = 0;                                               /* Set no vector owner now */
 
        if (proc_info->cpu_number == 0)  {
                proc_info->cpu_flags &= BootDone;
-               proc_info->istackptr = (vm_offset_t)&intstack + (INTSTACK_SIZE*(cpu+1)) - sizeof (struct ppc_saved_state);
+               proc_info->istackptr = (vm_offset_t)&intstack + (INTSTACK_SIZE*(cpu+1)) - FM_SIZE;
                proc_info->intstack_top_ss = proc_info->istackptr;
 #if     MACH_KDP || MACH_KDB
-               proc_info->debstackptr = (vm_offset_t)&debstack + (KERNEL_STACK_SIZE*(cpu+1)) - sizeof (struct ppc_saved_state);
+               proc_info->debstackptr = (vm_offset_t)&debstack + (KERNEL_STACK_SIZE*(cpu+1)) - FM_SIZE;
                proc_info->debstack_top_ss = proc_info->debstackptr;
 #endif  /* MACH_KDP || MACH_KDB */
                proc_info->interrupts_enabled = 0;
@@ -761,8 +751,8 @@ cpu_sleep(
                        extern void _start_cpu(void);
        
                        resethandler_target.type = RESET_HANDLER_START;
-                       resethandler_target.call_paddr = kvtophys((vm_offset_t)_start_cpu); 
-                       resethandler_target.arg__paddr = kvtophys((vm_offset_t)proc_info);
+                       resethandler_target.call_paddr = (vm_offset_t)_start_cpu;       /* Note: these routines are always V=R */
+                       resethandler_target.arg__paddr = (vm_offset_t)proc_info;        /* Note: these routines are always V=R */
        
                        ml_phys_write((vm_offset_t)&ResetHandler + 0,
                                          resethandler_target.type);
@@ -774,6 +764,16 @@ cpu_sleep(
                        __asm__ volatile("sync");
                        __asm__ volatile("isync");
                }
+
+               wait_ncpus_sleep = real_ncpus-1; 
+               ncpus_sleep = 0;
+               while (wait_ncpus_sleep != ncpus_sleep) {
+                       ncpus_sleep = 0;
+                       for(i=1; i < real_ncpus ; i++) {
+                               if ((*(volatile short *)&per_proc_info[i].cpu_flags) & SleepState)
+                                       ncpus_sleep++;
+                       }
+               }
        }
 
        PE_cpu_machine_quiesce(proc_info->cpu_id);