kaif.c revision ae115bc77f6fcde83175c75b4206dc2e50747966
/*
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
*/
#ifndef sun4v
#include <sys/spitregs.h>
#endif /* sun4v */
#include <sys/machtrap.h>
#include <sys/privregs.h>
#include <kmdb/kaif_regs.h>
#include <kmdb/kmdb_asmutil.h>
#include <kmdb/kmdb_kdi.h>
#include <kmdb/kmdb_promif_isadep.h>
#include <kmdb/kmdb_dpi_impl.h>
#include <mdb/mdb_debug.h>
#include <mdb/mdb_modapi.h>
#include <mdb/mdb_kreg_impl.h>
#include <mdb/mdb_v9util.h>
#define OP(x) ((x) >> 30)
#define RS2(x) ((x) & 0x1f)
#define OP_BRANCH 0x0
#define OP_ARITH 0x2
#define OP2_BPcc 0x1
#define OP2_Bicc 0x2
#define OP2_BPr 0x3
#define OP2_FBPfcc 0x5
#define OP2_FBfcc 0x6
#define OP3_RDPR 0x2a
#define OP3_WRPR 0x32
#define A(x) (((x) >> 29) & 0x01)
#define I(x) (((x) >> 13) & 0x01)
#define DISP22(x) ((x) & 0x3fffff)
#define DISP19(x) ((x) & 0x7ffff)
#define SIMM13(x) ((x) & 0x1fff)
static uint64_t kaif_vwapt_addr;
static uint64_t kaif_pwapt_addr;
#ifndef sun4v
static uint64_t kaif_lsuctl;
#endif /* sun4v */
int kaif_ncpusave;
#ifdef sun4v
#endif /* sun4v */
int *kaif_promexitarmp;
int kaif_trap_switch;
void (*kaif_modchg_cb)(struct modctl *, int);
void (*kaif_ktrap_install)(int, void (*)(void));
void (*kaif_ktrap_restore)(void);
static int
kaif_get_master_cpuid(void)
{
return (kaif_master_cpuid);
}
/*ARGSUSED*/
static int
kaif_get_nwin(int cpuid)
{
return (get_nwin());
}
static kaif_cpusave_t *
kaif_cpuid2save(int cpuid)
{
if (cpuid == DPI_MASTER_CPUID)
return (&kaif_cpusave[kaif_master_cpuid]);
return (NULL);
}
return (NULL);
}
return (save);
}
static int
kaif_get_cpu_state(int cpuid)
{
return (-1); /* errno is set for us */
switch (save->krs_cpu_state) {
case KAIF_CPU_STATE_MASTER:
return (DPI_CPU_STATE_MASTER);
case KAIF_CPU_STATE_SLAVE:
return (DPI_CPU_STATE_SLAVE);
default:
}
}
static const mdb_tgt_gregset_t *
kaif_get_gregs(int cpuid)
{
int wp, i;
return (NULL); /* errno is set for us */
/*
* The DPI startup routine populates the register window portions of
* the kaif_cpusave_t. We copy the current set of ins, outs, and
* locals to the gregs. We also extract %pstate from %tstate.
*/
for (i = 0; i < 8; i++) {
}
wp = 0;
for (i = 0; i < 8; i++)
return (gregs);
}
static kreg_t *
{
int nwin, i;
int win;
regname = "o6";
regname = "i6";
switch (regname[0]) {
case 'o':
win = 0;
/*FALLTHROUGH*/
case 'i':
case 'l':
}
}
}
return (NULL);
}
static int
{
return (0);
}
return (-1);
return (0);
}
static int
{
return (0);
return (0);
}
return (-1);
return (0);
}
static int
{
sizeof (mdb_instr_t))
return (-1); /* errno is set for us */
sizeof (mdb_instr_t))
return (-1); /* errno is set for us */
return (0);
}
static int
{
sizeof (mdb_instr_t))
return (-1); /* errno is set for us */
return (0);
}
/*
* Calculate the watchpoint mask byte (VM or PM, as appropriate). A 1 bit in
* the mask indicates that the corresponding byte in the watchpoint address
* should be used for activation comparison.
*/
/*
* Sun4v doesn't have watchpoint regs
*/
#ifndef sun4v
static uchar_t
{
int pow;
if (len == 8)
return (0xff);
}
#endif
/*
* UltraSPARC processors have one physical and one virtual watchpoint. These
* watchpoints are specified by setting the address in a register, and by
* setting a selector byte in another register to determine which bytes of the
* address are to be used for comparison. For simplicity, we only support
* selector byte values whose bit patterns match the regexp "1+0*". Watchpoint
* addresses must be 8-byte aligned on these chips, so a selector byte of 0xff
* indicates an 8-byte watchpoint. Successive valid sizes are powers of 256,
* starting with 256.
*/
static int
{
warn("execute watchpoints are not supported on this "
"platform\n");
return (set_errno(EMDB_TGTNOTSUP));
}
warn("watchpoint size must be 8 or a power of 256 bytes\n");
}
warn("%lu-byte watchpoints must be %lu-byte aligned\n",
}
warn("requested watchpoint type not supported on this "
"platform\n");
return (set_errno(EMDB_TGTHWNOTSUP));
}
return (0);
}
static int
{
#ifdef sun4v
#ifdef lint
#endif /* !lint */
/* Watchpoints not supported */
return (set_errno(EMDB_TGTHWNOTSUP));
#else
addrp = &kaif_pwapt_addr;
else
addrp = &kaif_vwapt_addr;
return (set_errno(EMDB_WPTOOMANY));
return (0);
#endif
}
static void
{
}
/*ARGSUSED*/
static void
{
/*
* Sun4v doesn't have watch point regs
*/
#ifndef sun4v
kaif_lsuctl |= LSU_PR;
kaif_lsuctl |= LSU_PW;
kaif_lsuctl |= LSU_VR;
kaif_lsuctl |= LSU_VW;
}
#endif /* sun4v */
}
/*ARGSUSED*/
static void
{
/*
* Sun4v doesn't have watch point regs
*/
#ifndef sun4v
} else {
}
#endif
}
/*
* `kaif_wapt_arm' and `kaif_wapt_disarm' modify the global state we keep that
* indicates what the values of the wapt control registers should be. These
* values must be individually set and cleared on each active CPU, a task which
* is performed by `kaif_wapt_clear_regs' and `kaif_wapt_set_regs', invoked as
* the world is stopped and resumed, respectively. `kaif_wapt_set_regs' is also
* used for CPU initialization.
*/
void
kaif_wapt_set_regs(void)
{
/*
* Sun4v doesn't have watch point regs
*/
#ifndef sun4v
lsu &= ~KAIF_LSUCTL_WAPT_MASK;
lsu |= kaif_lsuctl;
#endif /* sun4v */
}
void
kaif_wapt_clear_regs(void)
{
/*
* Sun4v doesn't have watch point regs
*/
#ifndef sun4v
lsu &= ~KAIF_LSUCTL_WAPT_MASK;
#endif /* sun4v */
}
/*
* UltraSPARC has one PA watchpoint and one VA watchpoint. The trap we get will
* tell us which one we hit, but it won't tell us where. We could attempt to
* dissect the instruction at %pc to see where it was reading from or writing
* to, but that gets messy in a hurry. We can, however, make a couple of
* assumptions:
*
* - kaif_set_watchpoint and kaif_delete_watchpoint will enforce the limits as
* to the number of watch points. As such, at most one VA watchpoint and one
* PA watchpoint will be on the active list.
*
* - We'll only be called on watchpoints that are on the active list.
*
* Taking these two assumptions, we can conclude that, if we're stopped due to
* a watchpoint and we're asked to match against a watchpoint, we must have
* stopped due to the watchpoint. This is all very terrifying, but the
* alternative (taking instructions apart) is worse.
*/
/*ARGSUSED*/
static int
{
else
}
static const char *
regno2name(int idx)
{
const mdb_tgt_regdesc_t *rd;
}
return ("unknown");
}
/*
* UltraSPARC doesn't support single-step natively, so we have to do it
* ourselves, by placing breakpoints at the instruction after the current one.
* Note that "after" will be %npc in the simple case, but can be one of
* several places if %pc is a branch.
*
* If %pc is an unconditional annulled branch, we put a breakpoint at the branch
* target. If it is a conditional annulled branch, we put breakpoints at %pc +
* 8 and the branch target. For all other branches, %npc will be set correctly
* as determined by the branch condition, and thus we can step through the
* branch by putting a breakpoint at %npc. If %pc contains a non-branch
* instruction (with the exception of certain rdpr and wrpr instructions,
* described more below), we step over it by placing a breakpoint at %npc.
*/
static int
kaif_step(void)
{
sizeof (instr)) {
return (-1);
}
/*
* If the current instruction is a read or write of PSTATE we need
* to emulate it because we've taken over management of PSTATE and
* we need keep interrupts disabled. If it's a branch, we may need
* to set two breakpoints -- one at the target and one at the
* subsequent instruction.
*/
const char *tgtreg =
return (0);
&rs1);
if (I(instr)) {
imm <<= 19;
imm >>= 19;
} else {
(void) kmdb_dpi_get_register(
}
return (0);
}
bpnpc = 1;
case OP2_BPcc:
case OP2_FBPfcc:
disp <<= 13;
disp >>= 11;
break;
case OP2_Bicc:
case OP2_FBfcc:
disp <<= 10;
disp >>= 8;
break;
case OP2_BPr:
cond = 1;
disp <<= 16;
disp >>= 14;
break;
default:
bpnpc = 1;
}
if (!bpnpc) {
bptgt = 1;
} else {
bpnpc = 1;
bppc8 = 1;
}
}
} else {
bpnpc = 1;
}
/*
* Place the breakpoints and resume this CPU with IE off. We'll come
* back after having encountered either one of the breakpoints we placed
* or a trap.
*/
err = 0;
goto step_done;
}
kmdb_dpi_resume_master(); /* ... there and back again ... */
(void) kmdb_dpi_set_register("pstate",
if (svnpc)
if (svpc8)
if (svtgt)
}
static uintptr_t
{
}
static const mdb_bitmask_t krm_flag_bits[] = {
{ NULL }
};
static void
{
sizeof (kaif_crumb_t)) {
return;
}
mdb_printf(" src: ");
case KAIF_CRUMB_SRC_OBP:
mdb_printf("O");
break;
case KAIF_CRUMB_SRC_IVEC:
mdb_printf("I");
break;
case KAIF_CRUMB_SRC_MAIN:
mdb_printf("M");
break;
case 0:
mdb_printf("-");
break;
default:
}
mdb_printf(" tt %3x pc %8p %-20A <%b>\n",
}
static void
{
int i;
for (i = KAIF_NCRUMBS; i > 0; i--) {
}
}
static void
{
int i;
/* dump_crumb will protect us from bogus addresses */
} else if (cpuid != -1) {
if (cpuid >= kaif_ncpusave)
return;
} else {
for (i = 0; i < kaif_ncpusave; i++) {
continue;
mdb_printf("%sCPU %d crumbs: (curidx %d)\n",
}
}
}
static int
{
return (-1); /* errno is set for us */
return (-1);
return (0);
}
static void
kaif_enter_mon(void)
{
}
static void
{
}
static void
kaif_modchg_cancel(void)
{
}
void
{
if (kaif_modchg_cb != NULL)
}
void
{
if (kaif_modchg_cb != NULL)
kaif_modchg_cb(modp, 0);
}
void
kaif_trap_set_debugger(void)
{
}
void
{
}
static void
kaif_kernpanic(int cpuid)
{
/*
* We're going to try to panic the system by using the same entry point
* used by the PROM when told to `sync'. The kernel wants a
* fully-populated struct regs, which we're going to build using the
* state captured at the time of the debugger fault. Said state lives
* in kaif_cb_save, since we haven't yet copied it over to the cpusave
* structure for the current master.
*/
/*
* The %tba is, as ever, different. We don't want the %tba from the
* time of the fault -- that'll be the debugger's. We want the %tba
* saved when the debugger was initially entered. It'll be saved in
* the cpusave area for the current CPU.
*/
}
static int
{
int i;
kaif_vwapt_addr = kaif_pwapt_addr = 0;
#ifdef sun4v
#endif
/* Allocate the per-CPU save areas */
UM_SLEEP);
UM_SLEEP);
for (i = 0; i < kaif_ncpusave; i++) {
save->krs_cpu_id = i;
}
return (0);
}
};