#include <sys/kdi_impl.h>
#include <kmdb/kmdb_kdi.h>
#include <kmdb/kmdb_dpi.h>
#include <kmdb/kmdb_kvm.h>
#include <kmdb/kmdb_promif.h>
#include <mdb/mdb_debug.h>
#include <mdb/mdb_err.h>
#include <mdb/mdb.h>
static int kdi_unload_request;
typedef struct mod_interp_data {
int (*mid_usercb)(struct modctl *, void *);
void *mid_userarg;
jmp_buf mid_pcb;
jmp_buf *mid_oldpcb;
} mod_interp_data_t;
static kmdb_auxv_t *kdi_auxv;
int
kmdb_kdi_mods_changed(void)
{
return (mdb.m_kdi->kdi_mods_changed());
}
static int
kmdb_kdi_mod_interp(struct modctl *mp, void *arg)
{
mod_interp_data_t *mid = arg;
int rc;
kmdb_dpi_restore_fault_hdlr(mid->mid_oldpcb);
rc = mid->mid_usercb(mp, mid->mid_userarg);
mid->mid_oldpcb = kmdb_dpi_set_fault_hdlr(&mid->mid_pcb);
return (rc);
}
int
kmdb_kdi_mod_iter(int (*cb)(struct modctl *, void *), void *arg)
{
mod_interp_data_t mid;
int rc;
if (setjmp(mid.mid_pcb) != 0) {
kmdb_dpi_restore_fault_hdlr(mid.mid_oldpcb);
return (-1);
}
mid.mid_usercb = cb;
mid.mid_userarg = arg;
mid.mid_oldpcb = kmdb_dpi_set_fault_hdlr(&mid.mid_pcb);
rc = mdb.m_kdi->kdi_mod_iter(kmdb_kdi_mod_interp, &mid);
kmdb_dpi_restore_fault_hdlr(mid.mid_oldpcb);
return (rc);
}
int
kmdb_kdi_mod_isloaded(struct modctl *modp)
{
return (mdb.m_kdi->kdi_mod_isloaded(modp));
}
int
kmdb_kdi_mod_haschanged(struct modctl *mc1, struct module *mp1,
struct modctl *mc2, struct module *mp2)
{
return (mdb.m_kdi->kdi_mod_haschanged(mc1, mp1, mc2, mp2));
}
static ssize_t
kdi_prw(void *buf, size_t nbytes, physaddr_t addr, int (*rw)(caddr_t, size_t,
physaddr_t, size_t *))
{
size_t sz;
int rc;
kmdb_dpi_flush_slave_caches();
if ((rc = rw(buf, nbytes, addr, &sz)) != 0)
return (set_errno(rc));
return (sz);
}
ssize_t
kmdb_kdi_pread(void *buf, size_t nbytes, physaddr_t addr)
{
return (kdi_prw(buf, nbytes, addr, mdb.m_kdi->kdi_pread));
}
ssize_t
kmdb_kdi_pwrite(void *buf, size_t nbytes, physaddr_t addr)
{
return (kdi_prw(buf, nbytes, addr, mdb.m_kdi->kdi_pwrite));
}
void
kmdb_kdi_flush_caches(void)
{
mdb.m_kdi->kdi_flush_caches();
}
int
kmdb_kdi_get_unload_request(void)
{
return (kdi_unload_request);
}
void
kmdb_kdi_set_unload_request(void)
{
kdi_unload_request = 1;
}
int
kmdb_kdi_get_flags(void)
{
uint_t flags = 0;
if (mdb.m_flags & MDB_FL_NOCTF)
flags |= KMDB_KDI_FL_NOCTF;
if (mdb.m_flags & MDB_FL_NOMODS)
flags |= KMDB_KDI_FL_NOMODS;
return (flags);
}
size_t
kmdb_kdi_range_is_nontoxic(uintptr_t va, size_t sz, int write)
{
return (mdb.m_kdi->kdi_range_is_nontoxic(va, sz, write));
}
void
kmdb_kdi_system_claim(void)
{
(void) kmdb_dpi_call((uintptr_t)mdb.m_kdi->kdi_system_claim, 0, NULL);
kmdb_prom_debugger_entry();
}
void
kmdb_kdi_system_release(void)
{
kmdb_prom_debugger_exit();
if (mdb.m_kdi->kdi_system_release != NULL) {
(void) kmdb_dpi_call((uintptr_t)mdb.m_kdi->kdi_system_release,
0, NULL);
}
}
struct cons_polledio *
kmdb_kdi_get_polled_io(void)
{
return (mdb.m_kdi->kdi_get_polled_io());
}
void
kmdb_kdi_kmdb_enter(void)
{
mdb.m_kdi->kdi_kmdb_enter();
}
int
kmdb_kdi_vtop(uintptr_t va, physaddr_t *pap)
{
jmp_buf pcb, *oldpcb;
int rc = 0;
if (setjmp(pcb) == 0) {
int err;
oldpcb = kmdb_dpi_set_fault_hdlr(&pcb);
if ((err = mdb.m_kdi->kdi_vtop(va, pap)) != 0)
rc = set_errno(err == ENOENT ? EMDB_NOMAP : err);
} else {
rc = set_errno(EMDB_NOMAP);
}
kmdb_dpi_restore_fault_hdlr(oldpcb);
return (rc);
}
kdi_dtrace_state_t
kmdb_kdi_dtrace_get_state(void)
{
return (mdb.m_kdi->kdi_dtrace_get_state());
}
int
kmdb_kdi_dtrace_set(int state)
{
int err;
if ((err = mdb.m_kdi->kdi_dtrace_set(state)) != 0)
return (set_errno(err));
return (0);
}
uintptr_t
kmdb_kdi_lookup_by_name(char *modname, char *symname)
{
ASSERT(kmdb_dpi_get_state(NULL) == DPI_STATE_INIT);
return (kdi_auxv->kav_lookup_by_name(modname, symname));
}
void
kmdb_kdi_init(kdi_t *kdi, kmdb_auxv_t *kav)
{
mdb.m_kdi = kdi;
mdb.m_pagesize = kav->kav_pagesize;
kdi_unload_request = 0;
kdi_auxv = kav;
kmdb_kdi_init_isadep(kdi, kav);
}
void
kmdb_kdi_end_init(void)
{
kdi_auxv = NULL;
}