/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Management of KMDB's IDT, which is installed upon KMDB activation.
*
* Debugger activation has two flavors, which cover the cases where KMDB is
* loaded at boot, and when it is loaded after boot. In brief, in both cases,
* the KDI needs to interpose upon several handlers in the IDT. When
* mod-loaded KMDB is deactivated, we undo the IDT interposition, restoring the
* handlers to what they were before we started.
*
* We also take over the entirety of IDT (except the double-fault handler) on
* the active CPU when we're in kmdb so we can handle things like page faults
* sensibly.
*
* Boot-loaded KMDB
*
* When we're first activated, we're running on boot's IDT. We need to be able
* to function in this world, so we'll install our handlers into boot's IDT.
* This is a little complicated: we're using the fake cpu_t set up by
* boot_kdi_tmpinit(), so we can't access cpu_idt directly. Instead,
* kdi_idt_write() notices that cpu_idt is NULL, and works around this problem.
*
* Later, when we're about to switch to the kernel's IDT, it'll call us via
* kdi_idt_sync(), allowing us to add our handlers to the new IDT. While
* boot-loaded KMDB can't be unloaded, we still need to save the descriptors we
* replace so we can pass traps back to the kernel as necessary.
*
* The last phase of boot-loaded KMDB activation occurs at non-boot CPU
* startup. We will be called on each non-boot CPU, thus allowing us to set up
* any watchpoints that may have been configured on the boot CPU and interpose
* on the given CPU's IDT. We don't save the interposed descriptors in this
* case -- see kdi_cpu_init() for details.
*
* Mod-loaded KMDB
*
* This style of activation is much simpler, as the CPUs are already running,
* and are using their own copy of the kernel's IDT. We simply interpose upon
* each CPU's IDT. We save the handlers we replace, both for deactivation and
* for passing traps back to the kernel. Note that for the hypervisors'
* benefit, we need to xcall to the other CPUs to do this, since we need to
* actively set the trap entries in its virtual IDT from that vcpu's context
* rather than just modifying the IDT table from the CPU running kdi_activate().
*/
#include <sys/segments.h>
#include <sys/archsystm.h>
#include <sys/kdi_impl.h>
#define KDI_IDT_NOSAVE 0
#define KDI_IDT_DTYPE_KERNEL 0
int kdi_ncpusave;
#ifndef __amd64
/* Used to track the current set of valid kernel selectors. */
#endif
int kdi_trap_switch;
int kdi_nmemranges;
typedef void idt_hdlr_f(void);
extern idt_hdlr_f kdi_invaltrap;
extern size_t kdi_ivct_size;
extern char kdi_slave_entry_patch;
typedef struct kdi_gate_spec {
/*
* Beware: kdi_pass_to_kernel() has unpleasant knowledge of this list.
*/
};
struct idt_description {
} idt_description[] = {
#if !defined(__xpv)
#endif
{ 0, 0, NULL },
};
void
{
int i;
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
{
int i;
if (i == T_DBLFLT)
continue; /* uses kernel's handler */
/*
* 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 ... */
/* Fill the rest with nops to be sure */
while (sz < KDI_MSR_PATCHSZ)
}
}
static void
{
int i;
for (i = 0; i < KDI_GATE_NVECS; i++) {
}
for (i = 0; i < KDI_GATE_NVECS; i++) {
if (saveold)
}
}
static void
kdi_idt_gates_restore(void)
{
int i;
for (i = 0; i < KDI_GATE_NVECS; i++)
}
/*
* Called when we switch to the kernel's IDT. We need to interpose on the
* kernel's IDT entries and stop using KMDBCODE_SEL.
*/
void
kdi_idt_sync(void)
{
}
/*
* 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
{
#ifdef __amd64
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 */
};
#else
0x60, /* pushal */
0xb9, 0x00, 0x00, 0x00, 0x00, /* movl $MSRNUM, %ecx */
0x31, 0xc0, /* clr %eax */
0x31, 0xd2, /* clr %edx */
0x0f, 0x30, /* wrmsr */
0x61 /* popal */
};
#endif
}
static void
{
}
void
{
int nmsrs, i;
/* Look in CPU0's MSRs for any special MSRs. */
case KDI_MSR_CLEARENTRY:
break;
case KDI_MSR_WRITEDELAY:
break;
}
}
nmsrs++;
for (i = 0; i < kdi_ncpusave; i++)
}
void
{
}
void
{
}
void
{
else
}
/*
* Activation for CPUs other than the boot CPU, called from that CPU's
* mp_startup(). We saved the kernel's descriptors when we initialized the
* boot CPU, so we don't want to do it again. Saving the handlers from this
* CPU's IDT would actually be dangerous with the CPU initialization method in
* use at the time of this writing. With that method, the startup code creates
* the IDTs for slave CPUs by copying the one used by the boot CPU, which has
* already been interposed upon by KMDB. Were we to interpose again, we'd
* replace the kernel's descriptors with our own in the save area. By not
* saving, but still overwriting, we'll work in the current world, and in any
* future world where the IDT is generated from scratch.
*/
void
kdi_cpu_init(void)
{
/* Load the debug registers and MSRs */
}
/*
* Activation for all CPUs for mod-loaded kmdb, i.e. a kmdb that wasn't
* loaded at boot.
*/
static int
kdi_cpu_activate(void)
{
return (0);
}
void
{
int i;
for (i = 0; i < kdi_ncpusave; i++) {
kdi_cpusave[i].krs_cpu_id = i;
kdi_cpusave[i].krs_curcrumb =
}
else
/* The initial selector set. Updated by the debugger-entry code */
#ifndef __amd64
#endif
kdi_nmemranges = 1;
kdi_msr_wrexit_msr = 0;
} else {
}
}
static int
kdi_cpu_deactivate(void)
{
return (0);
}
void
kdi_deactivate(void)
{
kdi_nmemranges = 0;
}
/*
* We receive all breakpoints and single step traps. Some of them,
* including those from userland and those induced by DTrace providers,
* are intended for the kernel, and must be processed there. We adopt
* this ours-until-proven-otherwise position due to the painful
* consequences of sending the kernel an unexpected breakpoint or
* single step. Unless someone can prove to us that the kernel is
* prepared to handle the trap, we'll assume there's a problem and will
* give the user a chance to debug it.
*/
int
{
return (1);
return (0);
return (1);
/*
* See the comments in the kernel's T_SGLSTP handler for why we need to
* do this.
*/
return (1);
return (0);
}
/*
* State has been saved, and all CPUs are on the CPU-specific stacks. All
* CPUs enter here, and head off into the debugger proper.
*/
void
{
/*
* BPTFLT gives us control with %eip set to the instruction *after*
* the int 3. Back it off, so we're looking at the instruction that
* triggered the fault.
*/
}