/*
* 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"
/*
* isa-dependent portions of the kmdb target
*/
#include <kmdb/kmdb_kdi.h>
#include <kmdb/kmdb_asmutil.h>
#include <mdb/mdb_debug.h>
#include <mdb/mdb_list.h>
#include <mdb/mdb_target_impl.h>
#include <mdb/mdb_isautil.h>
#include <mdb/mdb_kreg_impl.h>
#include <sys/pci_impl.h>
/* Higher than the highest trap number for which we have a defined specifier */
const char *
kmt_def_dismode(void)
{
#ifdef __amd64
return ("amd64");
#else
return ("ia32");
#endif
}
int
{
int i;
return (0);
}
return (1);
}
/*
* Determine the return address for the current frame.
*/
int
{
sizeof (mdb_instr_t))
return (-1); /* errno is set for us */
if (!kmt_step_out_validate(t, pc))
return (set_errno(EMDB_TGTNOTSUP));
}
int
{
}
/*
* Return the address of the next instruction following a call, or return -1
* and set errno to EAGAIN if the target should just single-step.
*/
int
{
sizeof (mdb_instr_t))
return (-1); /* errno is set for us */
}
/*ARGSUSED*/
static int
{
if (flags & DCMD_ADDRSPEC) {
} else
return (DCMD_ERR);
}
if (argc != 0) {
return (DCMD_USAGE);
else
}
return (DCMD_OK);
}
int
{
}
int
{
}
int
{
}
int
{
}
/*ARGSUSED*/
void
{
}
#define IOCHECK_NOWARN 0
static int
{
if (addr > IOPORTLIMIT) {
if (dowarn)
}
if (dowarn)
warn("port access must be 1, 2, or 4 bytes\n");
}
if (dowarn) {
warn("address for %llu-byte access must be %llu-byte "
}
}
return (0);
}
/*ARGSUSED1*/
int
{
return (DCMD_USAGE);
if (len == 0)
return (DCMD_ERR);
return (DCMD_ERR);
}
return (DCMD_OK);
}
static uint64_t
{
else
}
/*ARGSUSED1*/
int
{
return (DCMD_USAGE);
if (len == 0)
return (DCMD_ERR);
warn("value is out of range for port size\n");
return (DCMD_ERR);
}
return (DCMD_ERR);
}
return (DCMD_OK);
}
static int
{
return (-1); /* errno is set for us */
}
return (0);
}
/*ARGSUSED*/
int
{
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
warn("rdmsr failed");
return (DCMD_ERR);
}
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
return (DCMD_USAGE);
warn("wrmsr failed");
return (DCMD_ERR);
}
return (DCMD_OK);
}
int
{
return (0);
}
return (1);
}
/*ARGSUSED*/
{
if (!(t->t_flags & MDB_TGT_F_ALLOWIO) &&
return (set_errno(EMDB_NOMAP));
/*
* No writes to user space are allowed. If we were to allow it, we'd
* be in the unfortunate situation where kmdb could place a breakpoint
* on a userspace executable page; this dirty page would end up being
* flushed back to disk, incurring sadness when it's next executed.
* Besides, we can't allow trapping in from userspace anyway.
*/
if (addr < kmdb_kdi_get_userlimit())
return (set_errno(EMDB_TGTNOTSUP));
}
/*ARGSUSED*/
static ssize_t
{
return (-1); /* errno is set for us */
return (-1); /* errno is set for us */
}
return (nbytes);
}
/*ARGSUSED*/
{
}
/*ARGSUSED*/
{
}
static int
{
warn("invalid bus number (must be 0-0xffff)\n");
return (DCMD_ERR);
}
warn("invalid device number (must be 0-0x1f)\n");
return (DCMD_ERR);
}
warn("invalid function number (must be 0-7)\n");
return (DCMD_ERR);
}
warn("invalid register number (must be 0-0xff, and 4-byte "
"aligned\n");
return (DCMD_ERR);
}
sizeof (addr)) {
warn("write of PCI_CONFADD failed");
return (DCMD_ERR);
}
sizeof (*valp)) {
warn("access to PCI_CONFDATA failed");
return (DCMD_ERR);
}
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
return (DCMD_USAGE);
return (DCMD_ERR);
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
return (DCMD_USAGE);
return (DCMD_ERR);
return (DCMD_OK);
}
const char *
{
switch (trapnum) {
case T_ZERODIV:
return ("division by zero (#de) trap");
case T_SGLSTP:
return ("single-step (#db) trap");
case T_NMIFLT:
return ("NMI");
case T_BPTFLT:
return ("breakpoint (#bp) trap");
case T_ILLINST:
return ("illegal instruction (#ud) trap");
case T_SEGFLT:
return ("segment not present (#np) trap");
case T_STKFLT:
return ("stack (#ss) trap");
case T_GPFLT:
return ("general protection (#gp) trap");
case T_PGFLT:
return ("page fault (#pf) trap");
case T_ALIGNMENT:
return ("alignment check (#ac) trap");
case T_MCE:
return ("machine check (#mc) trap");
case T_SIMDFPE:
case T_DBGENTR:
return ("debugger entry trap");
default:
trapnum);
return (trapname);
}
}
void
{
/* Traps for which we want to provide an explicit message */
/*
* Traps which will be handled elsewhere, and which therefore don't
* need the trap-based message.
*/
/* Catch-all for traps not explicitly listed here */
}
void
{
/*
* The stack trace and ::step out code need to detect "interrupt"
* frames. The heuristic they use to detect said frames requires the
* addresses of routines that can generate them.
*/
(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
#if defined(__amd64)
(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
#endif
}