diff options
author | Ingo Molnar <mingo@elte.hu> | 2012-02-28 04:28:24 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2012-02-28 04:28:24 -0500 |
commit | e24b90b282d73c0654c716d449d91a07ebb8ecaf (patch) | |
tree | ad27a95e66d2968d6d89242f955c0cd7401aab4b | |
parent | 458ce2910aa83d8a2cafb489d727f7da839e73c6 (diff) | |
parent | 79fb4ad63e8266ffac1f69bbb45a6f86570493e7 (diff) |
Merge branch 'tip/x86/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace into x86/asm
-rw-r--r-- | arch/x86/kernel/entry_64.S | 64 |
1 files changed, 35 insertions, 29 deletions
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 94c636aa7e1d..a63dabe153ca 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -1529,6 +1529,7 @@ ENTRY(nmi) | |||
1529 | 1529 | ||
1530 | /* Use %rdx as out temp variable throughout */ | 1530 | /* Use %rdx as out temp variable throughout */ |
1531 | pushq_cfi %rdx | 1531 | pushq_cfi %rdx |
1532 | CFI_REL_OFFSET rdx, 0 | ||
1532 | 1533 | ||
1533 | /* | 1534 | /* |
1534 | * If %cs was not the kernel segment, then the NMI triggered in user | 1535 | * If %cs was not the kernel segment, then the NMI triggered in user |
@@ -1553,6 +1554,7 @@ ENTRY(nmi) | |||
1553 | */ | 1554 | */ |
1554 | lea 6*8(%rsp), %rdx | 1555 | lea 6*8(%rsp), %rdx |
1555 | test_in_nmi rdx, 4*8(%rsp), nested_nmi, first_nmi | 1556 | test_in_nmi rdx, 4*8(%rsp), nested_nmi, first_nmi |
1557 | CFI_REMEMBER_STATE | ||
1556 | 1558 | ||
1557 | nested_nmi: | 1559 | nested_nmi: |
1558 | /* | 1560 | /* |
@@ -1584,10 +1586,12 @@ nested_nmi: | |||
1584 | 1586 | ||
1585 | nested_nmi_out: | 1587 | nested_nmi_out: |
1586 | popq_cfi %rdx | 1588 | popq_cfi %rdx |
1589 | CFI_RESTORE rdx | ||
1587 | 1590 | ||
1588 | /* No need to check faults here */ | 1591 | /* No need to check faults here */ |
1589 | INTERRUPT_RETURN | 1592 | INTERRUPT_RETURN |
1590 | 1593 | ||
1594 | CFI_RESTORE_STATE | ||
1591 | first_nmi: | 1595 | first_nmi: |
1592 | /* | 1596 | /* |
1593 | * Because nested NMIs will use the pushed location that we | 1597 | * Because nested NMIs will use the pushed location that we |
@@ -1619,10 +1623,15 @@ first_nmi: | |||
1619 | * | pt_regs | | 1623 | * | pt_regs | |
1620 | * +-------------------------+ | 1624 | * +-------------------------+ |
1621 | * | 1625 | * |
1622 | * The saved RIP is used to fix up the copied RIP that a nested | 1626 | * The saved stack frame is used to fix up the copied stack frame |
1623 | * NMI may zero out. The original stack frame and the temp storage | 1627 | * that a nested NMI may change to make the interrupted NMI iret jump |
1628 | * to the repeat_nmi. The original stack frame and the temp storage | ||
1624 | * is also used by nested NMIs and can not be trusted on exit. | 1629 | * is also used by nested NMIs and can not be trusted on exit. |
1625 | */ | 1630 | */ |
1631 | /* Do not pop rdx, nested NMIs will corrupt that part of the stack */ | ||
1632 | movq (%rsp), %rdx | ||
1633 | CFI_RESTORE rdx | ||
1634 | |||
1626 | /* Set the NMI executing variable on the stack. */ | 1635 | /* Set the NMI executing variable on the stack. */ |
1627 | pushq_cfi $1 | 1636 | pushq_cfi $1 |
1628 | 1637 | ||
@@ -1630,22 +1639,39 @@ first_nmi: | |||
1630 | .rept 5 | 1639 | .rept 5 |
1631 | pushq_cfi 6*8(%rsp) | 1640 | pushq_cfi 6*8(%rsp) |
1632 | .endr | 1641 | .endr |
1642 | CFI_DEF_CFA_OFFSET SS+8-RIP | ||
1643 | |||
1644 | /* Everything up to here is safe from nested NMIs */ | ||
1645 | |||
1646 | /* | ||
1647 | * If there was a nested NMI, the first NMI's iret will return | ||
1648 | * here. But NMIs are still enabled and we can take another | ||
1649 | * nested NMI. The nested NMI checks the interrupted RIP to see | ||
1650 | * if it is between repeat_nmi and end_repeat_nmi, and if so | ||
1651 | * it will just return, as we are about to repeat an NMI anyway. | ||
1652 | * This makes it safe to copy to the stack frame that a nested | ||
1653 | * NMI will update. | ||
1654 | */ | ||
1655 | repeat_nmi: | ||
1656 | /* | ||
1657 | * Update the stack variable to say we are still in NMI (the update | ||
1658 | * is benign for the non-repeat case, where 1 was pushed just above | ||
1659 | * to this very stack slot). | ||
1660 | */ | ||
1661 | movq $1, 5*8(%rsp) | ||
1633 | 1662 | ||
1634 | /* Make another copy, this one may be modified by nested NMIs */ | 1663 | /* Make another copy, this one may be modified by nested NMIs */ |
1635 | .rept 5 | 1664 | .rept 5 |
1636 | pushq_cfi 4*8(%rsp) | 1665 | pushq_cfi 4*8(%rsp) |
1637 | .endr | 1666 | .endr |
1638 | 1667 | CFI_DEF_CFA_OFFSET SS+8-RIP | |
1639 | /* Do not pop rdx, nested NMIs will corrupt it */ | 1668 | end_repeat_nmi: |
1640 | movq 11*8(%rsp), %rdx | ||
1641 | 1669 | ||
1642 | /* | 1670 | /* |
1643 | * Everything below this point can be preempted by a nested | 1671 | * Everything below this point can be preempted by a nested |
1644 | * NMI if the first NMI took an exception. Repeated NMIs | 1672 | * NMI if the first NMI took an exception and reset our iret stack |
1645 | * caused by an exception and nested NMI will start here, and | 1673 | * so that we repeat another NMI. |
1646 | * can still be preempted by another NMI. | ||
1647 | */ | 1674 | */ |
1648 | restart_nmi: | ||
1649 | pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */ | 1675 | pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */ |
1650 | subq $ORIG_RAX-R15, %rsp | 1676 | subq $ORIG_RAX-R15, %rsp |
1651 | CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 | 1677 | CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 |
@@ -1674,26 +1700,6 @@ nmi_restore: | |||
1674 | CFI_ENDPROC | 1700 | CFI_ENDPROC |
1675 | END(nmi) | 1701 | END(nmi) |
1676 | 1702 | ||
1677 | /* | ||
1678 | * If an NMI hit an iret because of an exception or breakpoint, | ||
1679 | * it can lose its NMI context, and a nested NMI may come in. | ||
1680 | * In that case, the nested NMI will change the preempted NMI's | ||
1681 | * stack to jump to here when it does the final iret. | ||
1682 | */ | ||
1683 | repeat_nmi: | ||
1684 | INTR_FRAME | ||
1685 | /* Update the stack variable to say we are still in NMI */ | ||
1686 | movq $1, 5*8(%rsp) | ||
1687 | |||
1688 | /* copy the saved stack back to copy stack */ | ||
1689 | .rept 5 | ||
1690 | pushq_cfi 4*8(%rsp) | ||
1691 | .endr | ||
1692 | |||
1693 | jmp restart_nmi | ||
1694 | CFI_ENDPROC | ||
1695 | end_repeat_nmi: | ||
1696 | |||
1697 | ENTRY(ignore_sysret) | 1703 | ENTRY(ignore_sysret) |
1698 | CFI_STARTPROC | 1704 | CFI_STARTPROC |
1699 | mov $-ENOSYS,%eax | 1705 | mov $-ENOSYS,%eax |