aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2012-02-28 04:28:24 -0500
committerIngo Molnar <mingo@elte.hu>2012-02-28 04:28:24 -0500
commite24b90b282d73c0654c716d449d91a07ebb8ecaf (patch)
treead27a95e66d2968d6d89242f955c0cd7401aab4b
parent458ce2910aa83d8a2cafb489d727f7da839e73c6 (diff)
parent79fb4ad63e8266ffac1f69bbb45a6f86570493e7 (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.S64
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
1557nested_nmi: 1559nested_nmi:
1558 /* 1560 /*
@@ -1584,10 +1586,12 @@ nested_nmi:
1584 1586
1585nested_nmi_out: 1587nested_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
1591first_nmi: 1595first_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 */
1655repeat_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 */ 1668end_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 */
1648restart_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
1675END(nmi) 1701END(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 */
1683repeat_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
1695end_repeat_nmi:
1696
1697ENTRY(ignore_sysret) 1703ENTRY(ignore_sysret)
1698 CFI_STARTPROC 1704 CFI_STARTPROC
1699 mov $-ENOSYS,%eax 1705 mov $-ENOSYS,%eax