* Handle an IPI_SUSPEND by saving our current context and spinning until we * are resumed. */
| 1535 | * are resumed. |
| 1536 | */ |
| 1537 | void |
| 1538 | cpususpend_handler(void) |
| 1539 | { |
| 1540 | u_int cpu; |
| 1541 | |
| 1542 | mtx_assert(&smp_ipi_mtx, MA_NOTOWNED); |
| 1543 | |
| 1544 | cpu = PCPU_GET(cpuid); |
| 1545 | if (savectx(&susppcbs[cpu]->sp_pcb)) { |
| 1546 | #ifdef __amd64__ |
| 1547 | fpususpend(susppcbs[cpu]->sp_fpususpend); |
| 1548 | #else |
| 1549 | npxsuspend(susppcbs[cpu]->sp_fpususpend); |
| 1550 | #endif |
| 1551 | /* |
| 1552 | * suspended_cpus is cleared shortly after each AP is restarted |
| 1553 | * by a Startup IPI, so that the BSP can proceed to restarting |
| 1554 | * the next AP. |
| 1555 | * |
| 1556 | * resuming_cpus gets cleared when the AP completes |
| 1557 | * initialization after having been released by the BSP. |
| 1558 | * resuming_cpus is probably not the best name for the |
| 1559 | * variable, because it is actually a set of processors that |
| 1560 | * haven't resumed yet and haven't necessarily started resuming. |
| 1561 | * |
| 1562 | * Note that suspended_cpus is meaningful only for ACPI suspend |
| 1563 | * as it's not really used for Xen suspend since the APs are |
| 1564 | * automatically restored to the running state and the correct |
| 1565 | * context. For the same reason resumectx is never called in |
| 1566 | * that case. |
| 1567 | */ |
| 1568 | CPU_SET_ATOMIC(cpu, &suspended_cpus); |
| 1569 | CPU_SET_ATOMIC(cpu, &resuming_cpus); |
| 1570 | |
| 1571 | /* |
| 1572 | * Invalidate the cache after setting the global status bits. |
| 1573 | * The last AP to set its bit may end up being an Owner of the |
| 1574 | * corresponding cache line in MOESI protocol. The AP may be |
| 1575 | * stopped before the cache line is written to the main memory. |
| 1576 | */ |
| 1577 | wbinvd(); |
| 1578 | } else { |
| 1579 | #ifdef __amd64__ |
| 1580 | fpuresume(susppcbs[cpu]->sp_fpususpend); |
| 1581 | #else |
| 1582 | npxresume(susppcbs[cpu]->sp_fpususpend); |
| 1583 | #endif |
| 1584 | pmap_init_pat(); |
| 1585 | initializecpu(); |
| 1586 | PCPU_SET(switchtime, 0); |
| 1587 | PCPU_SET(switchticks, ticks); |
| 1588 | |
| 1589 | /* Indicate that we have restarted and restored the context. */ |
| 1590 | CPU_CLR_ATOMIC(cpu, &suspended_cpus); |
| 1591 | } |
| 1592 | |
| 1593 | /* Wait for resume directive */ |
| 1594 | while (!CPU_ISSET(cpu, &toresume_cpus)) |
no test coverage detected