Print this page
8956 Implement KPTI
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
9210 remove KMDB branch debugging support
9211 ::crregs could do with cr2/cr3 support
9209 ::ttrace should be able to filter by thread
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>
9207 kdi_idt: Cast GATESEG_GETOFFSET through uintptr_t
Reviewed by: Yuri Pankov <yuripv@yuripv.net>

*** 19,28 **** --- 19,30 ---- * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2018 Joyent, Inc. */ /* * Management of KMDB's IDT, which is installed upon KMDB activation. *
*** 74,83 **** --- 76,86 ---- #include <sys/sunddi.h> #include <sys/archsystm.h> #include <sys/kdi_impl.h> #include <sys/x_call.h> #include <ia32/sys/psw.h> + #include <vm/hat_i86.h> #define KDI_GATE_NVECS 3 #define KDI_IDT_NOSAVE 0 #define KDI_IDT_SAVE 1
*** 98,110 **** uint32_t kdi_ds; uint32_t kdi_fs; uint32_t kdi_gs; #endif - uint_t kdi_msr_wrexit_msr; - uint64_t *kdi_msr_wrexit_valp; - uintptr_t kdi_kernel_handler; int kdi_trap_switch; #define KDI_MEMRANGES_MAX 2 --- 101,110 ----
*** 115,129 **** typedef void idt_hdlr_f(void); extern idt_hdlr_f kdi_trap0, kdi_trap1, kdi_int2, kdi_trap3, kdi_trap4; extern idt_hdlr_f kdi_trap5, kdi_trap6, kdi_trap7, kdi_trap9; extern idt_hdlr_f kdi_traperr10, kdi_traperr11, kdi_traperr12; ! extern idt_hdlr_f kdi_traperr13, kdi_traperr14, kdi_trap16, kdi_trap17; extern idt_hdlr_f kdi_trap18, kdi_trap19, kdi_trap20, kdi_ivct32; extern idt_hdlr_f kdi_invaltrap; extern size_t kdi_ivct_size; - extern char kdi_slave_entry_patch; typedef struct kdi_gate_spec { uint_t kgs_vec; uint_t kgs_dpl; } kdi_gate_spec_t; --- 115,128 ---- typedef void idt_hdlr_f(void); extern idt_hdlr_f kdi_trap0, kdi_trap1, kdi_int2, kdi_trap3, kdi_trap4; extern idt_hdlr_f kdi_trap5, kdi_trap6, kdi_trap7, kdi_trap9; extern idt_hdlr_f kdi_traperr10, kdi_traperr11, kdi_traperr12; ! extern idt_hdlr_f kdi_traperr13, kdi_traperr14, kdi_trap16, kdi_traperr17; extern idt_hdlr_f kdi_trap18, kdi_trap19, kdi_trap20, kdi_ivct32; extern idt_hdlr_f kdi_invaltrap; extern size_t kdi_ivct_size; typedef struct kdi_gate_spec { uint_t kgs_vec; uint_t kgs_dpl; } kdi_gate_spec_t;
*** 137,147 **** { T_DBGENTR, TRP_KPL } }; static gate_desc_t kdi_kgates[KDI_GATE_NVECS]; ! gate_desc_t kdi_idt[NIDT]; struct idt_description { uint_t id_low; uint_t id_high; idt_hdlr_f *id_basehdlr; --- 136,146 ---- { T_DBGENTR, TRP_KPL } }; static gate_desc_t kdi_kgates[KDI_GATE_NVECS]; ! extern gate_desc_t kdi_idt[NIDT]; struct idt_description { uint_t id_low; uint_t id_high; idt_hdlr_f *id_basehdlr;
*** 164,174 **** { T_STKFLT, 0, kdi_traperr12, NULL }, { T_GPFLT, 0, kdi_traperr13, NULL }, { T_PGFLT, 0, kdi_traperr14, NULL }, { 15, 0, kdi_invaltrap, NULL }, { T_EXTERRFLT, 0, kdi_trap16, NULL }, ! { T_ALIGNMENT, 0, kdi_trap17, NULL }, { T_MCE, 0, kdi_trap18, NULL }, { T_SIMDFPE, 0, kdi_trap19, NULL }, { T_DBGENTR, 0, kdi_trap20, NULL }, { 21, 31, kdi_invaltrap, NULL }, { 32, 255, kdi_ivct32, &kdi_ivct_size }, --- 163,173 ---- { T_STKFLT, 0, kdi_traperr12, NULL }, { T_GPFLT, 0, kdi_traperr13, NULL }, { T_PGFLT, 0, kdi_traperr14, NULL }, { 15, 0, kdi_invaltrap, NULL }, { T_EXTERRFLT, 0, kdi_trap16, NULL }, ! { T_ALIGNMENT, 0, kdi_traperr17, NULL }, { T_MCE, 0, kdi_trap18, NULL }, { T_SIMDFPE, 0, kdi_trap19, NULL }, { T_DBGENTR, 0, kdi_trap20, NULL }, { 21, 31, kdi_invaltrap, NULL }, { 32, 255, kdi_ivct32, &kdi_ivct_size },
*** 183,240 **** for (id = idt_description; id->id_basehdlr != NULL; id++) { uint_t high = id->id_high != 0 ? id->id_high : id->id_low; size_t incr = id->id_incrp != NULL ? *id->id_incrp : 0; for (i = id->id_low; i <= high; i++) { caddr_t hdlr = (caddr_t)id->id_basehdlr + incr * (i - id->id_low); set_gatesegd(&kdi_idt[i], (void (*)())hdlr, sel, ! SDT_SYSIGT, TRP_KPL, i); } } } - /* - * Patch caller-provided code into the debugger's IDT handlers. This code is - * used to save MSRs that must be saved before the first branch. All handlers - * are essentially the same, and end with a branch to kdi_cmnint. To save the - * MSR, we need to patch in before the branch. The handlers have the following - * structure: KDI_MSR_PATCHOFF bytes of code, KDI_MSR_PATCHSZ bytes of - * patchable space, followed by more code. - */ - void - kdi_idt_patch(caddr_t code, size_t sz) - { - int i; - - ASSERT(sz <= KDI_MSR_PATCHSZ); - - for (i = 0; i < sizeof (kdi_idt) / sizeof (struct gate_desc); i++) { - gate_desc_t *gd; - uchar_t *patch; - - if (i == T_DBLFLT) - continue; /* uses kernel's handler */ - - gd = &kdi_idt[i]; - patch = (uchar_t *)GATESEG_GETOFFSET(gd) + KDI_MSR_PATCHOFF; - - /* - * We can't ASSERT that there's a nop here, because this may be - * a debugger restart. In that case, we're copying the new - * patch point over the old one. - */ - /* FIXME: dtrace fbt ... */ - bcopy(code, patch, sz); - - /* Fill the rest with nops to be sure */ - while (sz < KDI_MSR_PATCHSZ) - patch[sz++] = 0x90; /* nop */ - } - } - static void kdi_idt_gates_install(selector_t sel, int saveold) { gate_desc_t gates[KDI_GATE_NVECS]; int i; --- 182,205 ---- for (id = idt_description; id->id_basehdlr != NULL; id++) { uint_t high = id->id_high != 0 ? id->id_high : id->id_low; size_t incr = id->id_incrp != NULL ? *id->id_incrp : 0; + #if !defined(__xpv) + if (kpti_enable && sel == KCS_SEL && id->id_low == T_DBLFLT) + id->id_basehdlr = tr_syserrtrap; + #endif + for (i = id->id_low; i <= high; i++) { caddr_t hdlr = (caddr_t)id->id_basehdlr + incr * (i - id->id_low); set_gatesegd(&kdi_idt[i], (void (*)())hdlr, sel, ! SDT_SYSIGT, TRP_KPL, IST_DBG); } } } static void kdi_idt_gates_install(selector_t sel, int saveold) { gate_desc_t gates[KDI_GATE_NVECS]; int i;
*** 243,253 **** for (i = 0; i < KDI_GATE_NVECS; i++) { const kdi_gate_spec_t *gs = &kdi_gate_specs[i]; uintptr_t func = GATESEG_GETOFFSET(&kdi_idt[gs->kgs_vec]); set_gatesegd(&gates[i], (void (*)())func, sel, SDT_SYSIGT, ! gs->kgs_dpl, gs->kgs_vec); } for (i = 0; i < KDI_GATE_NVECS; i++) { uint_t vec = kdi_gate_specs[i].kgs_vec; --- 208,218 ---- for (i = 0; i < KDI_GATE_NVECS; i++) { const kdi_gate_spec_t *gs = &kdi_gate_specs[i]; uintptr_t func = GATESEG_GETOFFSET(&kdi_idt[gs->kgs_vec]); set_gatesegd(&gates[i], (void (*)())func, sel, SDT_SYSIGT, ! gs->kgs_dpl, IST_DBG); } for (i = 0; i < KDI_GATE_NVECS; i++) { uint_t vec = kdi_gate_specs[i].kgs_vec;
*** 276,359 **** { kdi_idt_init(KCS_SEL); kdi_idt_gates_install(KCS_SEL, KDI_IDT_SAVE); } - /* - * On some processors, we'll need to clear a certain MSR before proceeding into - * the debugger. Complicating matters, this MSR must be cleared before we take - * any branches. We have patch points in every trap handler, which will cover - * all entry paths for master CPUs. We also have a patch point in the slave - * entry code. - */ - static void - kdi_msr_add_clrentry(uint_t msr) - { - #ifdef __amd64 - uchar_t code[] = { - 0x51, 0x50, 0x52, /* pushq %rcx, %rax, %rdx */ - 0xb9, 0x00, 0x00, 0x00, 0x00, /* movl $MSRNUM, %ecx */ - 0x31, 0xc0, /* clr %eax */ - 0x31, 0xd2, /* clr %edx */ - 0x0f, 0x30, /* wrmsr */ - 0x5a, 0x58, 0x59 /* popq %rdx, %rax, %rcx */ - }; - uchar_t *patch = &code[4]; - #else - uchar_t code[] = { - 0x60, /* pushal */ - 0xb9, 0x00, 0x00, 0x00, 0x00, /* movl $MSRNUM, %ecx */ - 0x31, 0xc0, /* clr %eax */ - 0x31, 0xd2, /* clr %edx */ - 0x0f, 0x30, /* wrmsr */ - 0x61 /* popal */ - }; - uchar_t *patch = &code[2]; - #endif - - bcopy(&msr, patch, sizeof (uint32_t)); - - kdi_idt_patch((caddr_t)code, sizeof (code)); - - bcopy(code, &kdi_slave_entry_patch, sizeof (code)); - } - - static void - kdi_msr_add_wrexit(uint_t msr, uint64_t *valp) - { - kdi_msr_wrexit_msr = msr; - kdi_msr_wrexit_valp = valp; - } - void - kdi_set_debug_msrs(kdi_msr_t *msrs) - { - int nmsrs, i; - - ASSERT(kdi_cpusave[0].krs_msr == NULL); - - /* Look in CPU0's MSRs for any special MSRs. */ - for (nmsrs = 0; msrs[nmsrs].msr_num != 0; nmsrs++) { - switch (msrs[nmsrs].msr_type) { - case KDI_MSR_CLEARENTRY: - kdi_msr_add_clrentry(msrs[nmsrs].msr_num); - break; - - case KDI_MSR_WRITEDELAY: - kdi_msr_add_wrexit(msrs[nmsrs].msr_num, - msrs[nmsrs].kdi_msr_valp); - break; - } - } - - nmsrs++; - - for (i = 0; i < kdi_ncpusave; i++) - kdi_cpusave[i].krs_msr = &msrs[nmsrs * i]; - } - - void kdi_update_drreg(kdi_drreg_t *drreg) { kdi_drreg = *drreg; } --- 241,251 ----
*** 392,402 **** */ void kdi_cpu_init(void) { kdi_idt_gates_install(KCS_SEL, KDI_IDT_NOSAVE); ! /* Load the debug registers and MSRs */ kdi_cpu_debug_init(&kdi_cpusave[CPU->cpu_id]); } /* * Activation for all CPUs for mod-loaded kmdb, i.e. a kmdb that wasn't --- 284,294 ---- */ void kdi_cpu_init(void) { kdi_idt_gates_install(KCS_SEL, KDI_IDT_NOSAVE); ! /* Load the debug registers. */ kdi_cpu_debug_init(&kdi_cpusave[CPU->cpu_id]); } /* * Activation for all CPUs for mod-loaded kmdb, i.e. a kmdb that wasn't
*** 446,458 **** kdi_nmemranges = 1; kdi_drreg.dr_ctl = KDIREG_DRCTL_RESERVED; kdi_drreg.dr_stat = KDIREG_DRSTAT_RESERVED; - kdi_msr_wrexit_msr = 0; - kdi_msr_wrexit_valp = NULL; - if (boothowto & RB_KMDB) { kdi_idt_gates_install(KMDBCODE_SEL, KDI_IDT_NOSAVE); } else { xc_call(0, 0, 0, CPUSET2BV(cpuset), (xc_func_t)kdi_cpu_activate); --- 338,347 ----
*** 505,517 **** /* * See the comments in the kernel's T_SGLSTP handler for why we need to * do this. */ if (tt == T_SGLSTP && ! (pc == (greg_t)sys_sysenter || pc == (greg_t)brand_sys_sysenter)) return (1); return (0); } /* --- 394,414 ---- /* * See the comments in the kernel's T_SGLSTP handler for why we need to * do this. */ + #if !defined(__xpv) if (tt == T_SGLSTP && ! (pc == (greg_t)sys_sysenter || pc == (greg_t)brand_sys_sysenter || ! pc == (greg_t)tr_sys_sysenter || ! pc == (greg_t)tr_brand_sys_sysenter)) { ! #else ! if (tt == T_SGLSTP && ! (pc == (greg_t)sys_sysenter || pc == (greg_t)brand_sys_sysenter)) { ! #endif return (1); + } return (0); } /*