kvm_isadep.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* isa-dependent portions of the kmdb target
*/
#include <mdb/mdb_kreg_impl.h>
#include <mdb/mdb_debug.h>
#include <mdb/mdb_modapi.h>
#include <mdb/mdb_v9util.h>
#include <mdb/mdb_target_impl.h>
#include <mdb/mdb_umem.h>
#include <kmdb/kmdb_kdi.h>
#include <kmdb/kmdb_dpi.h>
#include <kmdb/kmdb_promif.h>
#include <kmdb/kmdb_asmutil.h>
#include <sys/sysmacros.h>
#include <sys/machtrap.h>
/* Higher than the highest trap number for which we have a specific specifier */
#define KMT_MAXTRAPNO 0x1ff
#define OP(x) ((x) >> 30)
#define RS2(x) ((x) & 0x1f)
#define OP_ARITH 0x2
#define OP3_OR 0x02
#define OP3_SAVE 0x3c
#define OP3_RESTORE 0x3d
static int
{
long argv[6];
/*
* If gsp isn't null, we were asked to dump a trace from a
* specific location. The normal iterator can handle that.
*/
if (cpu != DPI_MASTER_CPUID)
warn("register set provided - ignoring cpu argument\n");
}
if (kmdb_dpi_get_cpu_state(cpu) < 0) {
return (DCMD_ERR);
}
/*
* We're being asked to dump the trace for the current CPU.
* To do that, we need to iterate first through the saved
* register windors. If there's more to the trace than that,
* we'll hand off to the normal iterator.
*/
for (;;) {
for (i = 0; i < 6; i++)
return (0);
return (0); /* Stop if we're at the end of stack */
return (set_errno(EMDB_STKALIGN));
break;
return (-1);
}
for (i = 0; i < 8; i++)
for (i = 0; i < 8; i++)
}
/*
* hack - if we null out pc here, iterator won't print the frame
* that corresponds to the current set of registers. That's what we
* want because we just printed them above.
*/
}
void
{
}
static int
{
if (flags & DCMD_ADDRSPEC) {
}
if (argc != 0) {
return (DCMD_USAGE);
else
}
return (DCMD_OK);
}
int
{
}
int
{
mdb_kvm_v9frame, 0));
}
int
{
mdb_kvm_v9framev, 0));
}
int
{
/*
* Force printing of the first register window by setting the saved
* pc (%i7) to PC_FAKE.
*/
}
{
/*
* Can we write to this page?
*/
if (!(t->t_flags & MDB_TGT_F_ALLOWIO) &&
return (set_errno(EMDB_NOMAP));
/*
* The OBP va>pa call returns a protection value that's right only some
* of the time. We can, however, tell if we failed a write due to a
* protection violation. If we get such an error, we'll retry the
* write using pwrite.
*/
/* We failed the write */
return (-1); /* errno is set for us */
}
return (nbytes);
}
/*ARGSUSED*/
{
int rc;
if (nbytes == 0)
return (0);
/*
* Break the writes up into page-sized chunks. First, the leading page
* fragment (if any), then the subsequent pages.
*/
return (rc);
}
while (nbytes > 0) {
}
return (rc);
}
/*ARGSUSED*/
{
return (set_errno(EMDB_TGTHWNOTSUP));
}
/*ARGSUSED*/
{
return (set_errno(EMDB_TGTHWNOTSUP));
}
const char *
kmt_def_dismode(void)
{
#ifdef __sparcv9
return ("v9plus");
#else
return ("v8");
#endif
}
/*
* If we are stopped on a save instruction or at the first instruction of a
* known function, return %o7 as the step-out address; otherwise return the
* current frame's return address (%i7). Significantly better handling of
* step out in leaf routines could be accomplished by implementing more
* complex decoding of the current function and our current state.
*/
int
{
else {
sizeof (instr)) {
warn("failed to read instruction at %p for step out",
(void *)pc);
return (-1);
}
else
}
return (0);
}
/*ARGSUSED*/
int
{
return (set_errno(EMDB_TGTHWNOTSUP));
}
static const char *
regno2name(int idx)
{
const mdb_tgt_regdesc_t *rd;
}
return ("unknown");
}
/*
* Step over call and jmpl by returning the address of the position where a
* temporary breakpoint can be set to catch return from the control transfer.
* This function does not currently provide advanced decoding of DCTI couples
* or any other complex special case; we just fall back to single-step.
*/
int
{
return (-1);
/*
* We're about to transfer control outside this function, so we
* want to stop when control returns from the other function.
* Normally the return address will be in %o7, tail-calls being
* the exception. We try to discover if this is a tail-call and
* compute the return address in that case.
*/
sizeof (instr)) {
warn("failed to read instruction at %p for next",
(void *)pc);
return (-1);
}
®);
} else
return (0);
}
}
const char *
kmt_trapname(int trapnum)
{
static char trapname[11];
switch (trapnum) {
case T_INSTR_EXCEPTION:
return ("instruction access error trap");
case T_ALIGNMENT:
return ("improper alignment trap");
case T_UNIMP_INSTR:
return ("illegal instruction trap");
case T_IDIV0:
return ("division by zero trap");
case T_FAST_INSTR_MMU_MISS:
return ("instruction access MMU miss trap");
case T_FAST_DATA_MMU_MISS:
return ("data access MMU miss trap");
case ST_KMDB_TRAP|T_SOFTWARE_TRAP:
return ("debugger entry trap");
return ("breakpoint trap");
default:
trapnum);
return (trapname);
}
}
void
{
/* Traps for which we want to provide an explicit message */
(void) mdb_tgt_add_fault(t, T_FAST_INSTR_MMU_MISS,
/*
* Traps which will be handled elsewhere, and which therefore don't
* need the trap-based message.
*/
/* Catch-all for traps not explicitly listed here */
}
/*ARGSUSED*/
void
{
}