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,10 +219,13 @@
* 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,10 +2561,49 @@
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);