Print this page
9685 KPTI %cr3 handling needs fixes

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/intel/kdi/kdi_asm.s
          +++ new/usr/src/uts/intel/kdi/kdi_asm.s
↓ open down ↓ 444 lines elided ↑ open up ↑
 445  445   * machine for debugger entry, and enter the debugger.
 446  446   */
 447  447  
 448  448          ENTRY_NP(kdi_save_common_state)
 449  449  
 450  450          popq    %rdi                    /* the cpusave area */
 451  451          movq    %rsp, KRS_GREGS(%rdi)   /* save ptr to current saved regs */
 452  452  
 453  453          pushq   %rdi
 454  454          call    kdi_trap_pass
 455      -        cmpq    $1, %rax
 456      -        je      kdi_pass_to_kernel
      455 +        testq   %rax, %rax
      456 +        jnz     kdi_pass_to_kernel
 457  457          popq    %rax /* cpusave in %rax */
 458  458  
 459  459          SAVE_IDTGDT
 460  460  
 461  461  #if !defined(__xpv)
 462  462          /* Save off %cr0, and clear write protect */
 463  463          movq    %cr0, %rcx
 464  464          movq    %rcx, KRS_CR0(%rax)
 465  465          andq    $_BITNOT(CR0_WP), %rcx
 466  466          movq    %rcx, %cr0
↓ open down ↓ 95 lines elided ↑ open up ↑
 562  562           * for either kernel or userland.
 563  563           */
 564  564  #if !defined(__xpv)
 565  565          jmp     tr_iret_kdi
 566  566  #else
 567  567          IRET
 568  568  #endif
 569  569          /*NOTREACHED*/
 570  570          SET_SIZE(kdi_resume)
 571  571  
 572      -        ENTRY_NP(kdi_pass_to_kernel)
 573  572  
 574      -        popq    %rdi /* cpusave */
 575      -
 576      -        movq    $KDI_CPU_STATE_NONE, KRS_CPU_STATE(%rdi)
 577      -
 578  573          /*
 579      -         * Find the trap and vector off the right kernel handler.  The trap
 580      -         * handler will expect the stack to be in trap order, with %rip being
 581      -         * the last entry, so we'll need to restore all our regs.  On i86xpv
 582      -         * we'll need to compensate for XPV_TRAP_POP.
      574 +         * We took a trap that should be handled by the kernel, not KMDB.
 583  575           *
 584  576           * We're hard-coding the three cases where KMDB has installed permanent
 585  577           * handlers, since after we KDI_RESTORE_REGS(), we don't have registers
 586  578           * to work with; we can't use a global since other CPUs can easily pass
 587  579           * through here at the same time.
 588  580           *
 589  581           * Note that we handle T_DBGENTR since userspace might have tried it.
      582 +         *
      583 +         * The trap handler will expect the stack to be in trap order, with %rip
      584 +         * being the last entry, so we'll need to restore all our regs.  On
      585 +         * i86xpv we'll need to compensate for XPV_TRAP_POP.
      586 +         *
      587 +         * %rax on entry is either 1 or 2, which is from kdi_trap_pass().
      588 +         * kdi_cmnint stashed the original %cr3 into KDIREG_CR3, then (probably)
      589 +         * switched us to the CPU's kf_kernel_cr3. But we're about to call, for
      590 +         * example:
      591 +         *
      592 +         * dbgtrap->trap()->tr_iret_kernel
      593 +         *
      594 +         * which, unlike, tr_iret_kdi, doesn't restore the original %cr3, so
      595 +         * we'll do so here if needed.
      596 +         *
      597 +         * This isn't just a matter of tidiness: for example, consider:
      598 +         *
      599 +         * hat_switch(oldhat=kas.a_hat, newhat=prochat)
      600 +         *  setcr3()
      601 +         *  reset_kpti()
      602 +         *   *brktrap* due to fbt on reset_kpti:entry
      603 +         *
      604 +         * Here, we have the new hat's %cr3, but we haven't yet updated
      605 +         * kf_kernel_cr3 (so its currently kas's). So if we don't restore here,
      606 +         * we'll stay on kas's cr3 value on returning from the trap: not good if
      607 +         * we fault on a userspace address.
 590  608           */
      609 +        ENTRY_NP(kdi_pass_to_kernel)
      610 +
      611 +        popq    %rdi /* cpusave */
      612 +        movq    $KDI_CPU_STATE_NONE, KRS_CPU_STATE(%rdi)
 591  613          movq    KRS_GREGS(%rdi), %rsp
      614 +
      615 +        cmpq    $2, %rax
      616 +        jne     no_restore_cr3
      617 +        movq    REG_OFF(KDIREG_CR3)(%rsp), %r11
      618 +        movq    %r11, %cr3
      619 +
      620 +no_restore_cr3:
 592  621          movq    REG_OFF(KDIREG_TRAPNO)(%rsp), %rdi
      622 +
 593  623          cmpq    $T_SGLSTP, %rdi
 594      -        je      1f
      624 +        je      kdi_pass_dbgtrap
 595  625          cmpq    $T_BPTFLT, %rdi
 596      -        je      2f
      626 +        je      kdi_pass_brktrap
 597  627          cmpq    $T_DBGENTR, %rdi
 598      -        je      3f
      628 +        je      kdi_pass_invaltrap
 599  629          /*
 600  630           * Hmm, unknown handler.  Somebody forgot to update this when they
 601  631           * added a new trap interposition... try to drop back into kmdb.
 602  632           */
 603  633          int     $T_DBGENTR
 604  634  
 605  635  #define CALL_TRAP_HANDLER(name) \
 606  636          KDI_RESTORE_REGS(%rsp); \
 607  637          /* Discard state, trapno, err */ \
 608  638          addq    $REG_OFF(KDIREG_RIP), %rsp; \
 609  639          XPV_TRAP_PUSH; \
 610  640          jmp     %cs:name
 611  641  
 612      -1:
      642 +kdi_pass_dbgtrap:
 613  643          CALL_TRAP_HANDLER(dbgtrap)
 614  644          /*NOTREACHED*/
 615      -2:
      645 +kdi_pass_brktrap:
 616  646          CALL_TRAP_HANDLER(brktrap)
 617  647          /*NOTREACHED*/
 618      -3:
      648 +kdi_pass_invaltrap:
 619  649          CALL_TRAP_HANDLER(invaltrap)
 620  650          /*NOTREACHED*/
 621  651  
 622  652          SET_SIZE(kdi_pass_to_kernel)
 623  653  
 624  654          /*
 625  655           * A minimal version of mdboot(), to be used by the master CPU only.
 626  656           */
 627  657          ENTRY_NP(kdi_reboot)
 628  658  
↓ open down ↓ 52 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX