Print this page
8620 pcplusmp shouldn't support x2APIC mode
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
        
*** 219,228 ****
--- 219,231 ----
   * Maximum number of vectors in a CPU that can be used for interrupt
   * allocation (including IPIs and the reserved vectors).
   */
  int apix_cpu_nvectors = APIX_NVECTOR;
  
+ /* number of CPUs in power-on transition state */
+ static int apic_poweron_cnt = 0;
+ 
  /* gcpu.h */
  
  extern void apic_do_interrupt(struct regs *rp, trap_trace_rec_t *ttp);
  extern void apic_change_eoi();
  
*** 2558,2567 ****
--- 2561,2609 ----
          vecp = apix_intx_get_vector(irqno);
  
          return (vecp);
  }
  
+ /*
+  * Switch between safe and x2APIC IPI sending method.
+  * The CPU may power on in xapic mode or x2apic mode. If the CPU needs to send
+  * an IPI to other CPUs before entering x2APIC mode, it still needs to use the
+  * xAPIC method. Before sending a StartIPI to the target CPU, psm_send_ipi will
+  * be changed to apic_common_send_ipi, which detects current local APIC mode and
+  * use the right method to send an IPI. If some CPUs fail to start up,
+  * apic_poweron_cnt won't return to zero, so apic_common_send_ipi will always be
+  * used. psm_send_ipi can't be simply changed back to x2apic_send_ipi if some
+  * CPUs failed to start up because those failed CPUs may recover itself later at
+  * unpredictable time.
+  */
+ void
+ apic_switch_ipi_callback(boolean_t enter)
+ {
+         ulong_t iflag;
+         struct psm_ops *pops = psmops;
+ 
+         iflag = intr_clear();
+         lock_set(&apic_mode_switch_lock);
+         if (enter) {
+                 ASSERT(apic_poweron_cnt >= 0);
+                 if (apic_poweron_cnt == 0) {
+                         pops->psm_send_ipi = apic_common_send_ipi;
+                         send_dirintf = pops->psm_send_ipi;
+                 }
+                 apic_poweron_cnt++;
+         } else {
+                 ASSERT(apic_poweron_cnt > 0);
+                 apic_poweron_cnt--;
+                 if (apic_poweron_cnt == 0) {
+                         pops->psm_send_ipi = x2apic_send_ipi;
+                         send_dirintf = pops->psm_send_ipi;
+                 }
+         }
+         lock_clear(&apic_mode_switch_lock);
+         intr_restore(iflag);
+ }
+ 
  /* stub function */
  int
  apix_loaded(void)
  {
          return (apix_is_enabled);