1843e1988Sjohnlev /* 2843e1988Sjohnlev * CDDL HEADER START 3843e1988Sjohnlev * 4843e1988Sjohnlev * The contents of this file are subject to the terms of the 5843e1988Sjohnlev * Common Development and Distribution License (the "License"). 6843e1988Sjohnlev * You may not use this file except in compliance with the License. 7843e1988Sjohnlev * 8843e1988Sjohnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9843e1988Sjohnlev * or http://www.opensolaris.org/os/licensing. 10843e1988Sjohnlev * See the License for the specific language governing permissions 11843e1988Sjohnlev * and limitations under the License. 12843e1988Sjohnlev * 13843e1988Sjohnlev * When distributing Covered Code, include this CDDL HEADER in each 14843e1988Sjohnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15843e1988Sjohnlev * If applicable, add the following below this CDDL HEADER, with the 16843e1988Sjohnlev * fields enclosed by brackets "[]" replaced with your own identifying 17843e1988Sjohnlev * information: Portions Copyright [yyyy] [name of copyright owner] 18843e1988Sjohnlev * 19843e1988Sjohnlev * CDDL HEADER END 20843e1988Sjohnlev */ 21843e1988Sjohnlev /* 22843e1988Sjohnlev * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23843e1988Sjohnlev * Use is subject to license terms. 24843e1988Sjohnlev */ 25*0a47c91cSRobert Mustacchi /* 26*0a47c91cSRobert Mustacchi * Copyright (c) 2012, Joyent, Inc. All rights reserved. 27*0a47c91cSRobert Mustacchi */ 28843e1988Sjohnlev 29843e1988Sjohnlev /* 30843e1988Sjohnlev * Libkvm Kernel Target Intel component 31843e1988Sjohnlev * 32843e1988Sjohnlev * This file provides the Intel-dependent portion of the libkvm kernel target. 33843e1988Sjohnlev * For more details on the implementation refer to mdb_kvm.c. 34843e1988Sjohnlev */ 35843e1988Sjohnlev 36843e1988Sjohnlev #include <mdb/mdb_target_impl.h> 37843e1988Sjohnlev #include <mdb/mdb_kreg_impl.h> 38843e1988Sjohnlev #include <mdb/mdb_errno.h> 39843e1988Sjohnlev #include <mdb/mdb_err.h> 40843e1988Sjohnlev #include <mdb/mdb_kvm.h> 41843e1988Sjohnlev #include <mdb/mdb_ks.h> 42843e1988Sjohnlev #include <mdb/mdb.h> 43843e1988Sjohnlev #include <mdb/kvm_isadep.h> 44843e1988Sjohnlev 45843e1988Sjohnlev #include <sys/cpuvar.h> 46843e1988Sjohnlev #include <sys/privmregs.h> 47843e1988Sjohnlev 48843e1988Sjohnlev int 49843e1988Sjohnlev kt_getareg(mdb_tgt_t *t, mdb_tgt_tid_t tid, 50843e1988Sjohnlev const char *rname, mdb_tgt_reg_t *rp) 51843e1988Sjohnlev { 52843e1988Sjohnlev const mdb_tgt_regdesc_t *rdp; 53843e1988Sjohnlev kt_data_t *kt = t->t_data; 54843e1988Sjohnlev 55843e1988Sjohnlev if (tid != kt->k_tid) 56843e1988Sjohnlev return (set_errno(EMDB_NOREGS)); 57843e1988Sjohnlev 58843e1988Sjohnlev for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) { 59843e1988Sjohnlev if (strcmp(rname, rdp->rd_name) == 0) { 60843e1988Sjohnlev *rp = kt->k_regs->kregs[rdp->rd_num]; 61*0a47c91cSRobert Mustacchi if (rdp->rd_flags & MDB_TGT_R_32) 62*0a47c91cSRobert Mustacchi *rp &= 0xffffffffULL; 63*0a47c91cSRobert Mustacchi else if (rdp->rd_flags & MDB_TGT_R_16) 64*0a47c91cSRobert Mustacchi *rp &= 0xffffULL; 65*0a47c91cSRobert Mustacchi else if (rdp->rd_flags & MDB_TGT_R_8H) 66*0a47c91cSRobert Mustacchi *rp = (*rp & 0xff00ULL) >> 8; 67*0a47c91cSRobert Mustacchi else if (rdp->rd_flags & MDB_TGT_R_8L) 68*0a47c91cSRobert Mustacchi *rp &= 0xffULL; 69843e1988Sjohnlev return (0); 70843e1988Sjohnlev } 71843e1988Sjohnlev } 72843e1988Sjohnlev 73843e1988Sjohnlev return (set_errno(EMDB_BADREG)); 74843e1988Sjohnlev } 75843e1988Sjohnlev 76843e1988Sjohnlev int 77843e1988Sjohnlev kt_putareg(mdb_tgt_t *t, mdb_tgt_tid_t tid, const char *rname, mdb_tgt_reg_t r) 78843e1988Sjohnlev { 79843e1988Sjohnlev const mdb_tgt_regdesc_t *rdp; 80843e1988Sjohnlev kt_data_t *kt = t->t_data; 81843e1988Sjohnlev 82843e1988Sjohnlev if (tid != kt->k_tid) 83843e1988Sjohnlev return (set_errno(EMDB_NOREGS)); 84843e1988Sjohnlev 85843e1988Sjohnlev for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) { 86843e1988Sjohnlev if (strcmp(rname, rdp->rd_name) == 0) { 87*0a47c91cSRobert Mustacchi if (rdp->rd_flags & MDB_TGT_R_32) 88*0a47c91cSRobert Mustacchi r &= 0xffffffffULL; 89*0a47c91cSRobert Mustacchi else if (rdp->rd_flags & MDB_TGT_R_16) 90*0a47c91cSRobert Mustacchi r &= 0xffffULL; 91*0a47c91cSRobert Mustacchi else if (rdp->rd_flags & MDB_TGT_R_8H) 92*0a47c91cSRobert Mustacchi r = (r & 0xffULL) << 8; 93*0a47c91cSRobert Mustacchi else if (rdp->rd_flags & MDB_TGT_R_8L) 94*0a47c91cSRobert Mustacchi r &= 0xffULL; 95*0a47c91cSRobert Mustacchi 96843e1988Sjohnlev kt->k_regs->kregs[rdp->rd_num] = (kreg_t)r; 97843e1988Sjohnlev return (0); 98843e1988Sjohnlev } 99843e1988Sjohnlev } 100843e1988Sjohnlev 101843e1988Sjohnlev return (set_errno(EMDB_BADREG)); 102843e1988Sjohnlev } 103843e1988Sjohnlev 104843e1988Sjohnlev int 105843e1988Sjohnlev kt_kvmregs(mdb_tgt_t *t, uint_t cpuid, mdb_tgt_gregset_t *kregs) 106843e1988Sjohnlev { 107843e1988Sjohnlev kt_data_t *kt = t->t_data; 108843e1988Sjohnlev privmregs_t mregs; 109843e1988Sjohnlev int ret; 110843e1988Sjohnlev 111843e1988Sjohnlev if ((ret = kt->k_kb_ops->kb_getmregs(kt->k_cookie, cpuid, &mregs)) != 0) 112843e1988Sjohnlev return (ret); 113843e1988Sjohnlev 114843e1988Sjohnlev kt_regs_to_kregs(&mregs.pm_gregs, kregs); 115843e1988Sjohnlev return (0); 116843e1988Sjohnlev } 117843e1988Sjohnlev 118843e1988Sjohnlev static int 119843e1988Sjohnlev kt_cpu2cpuid(uintptr_t cpup) 120843e1988Sjohnlev { 121843e1988Sjohnlev cpu_t cpu; 122843e1988Sjohnlev 123843e1988Sjohnlev if (mdb_vread(&cpu, sizeof (cpu_t), cpup) != sizeof (cpu_t)) 124843e1988Sjohnlev return (-1); 125843e1988Sjohnlev 126843e1988Sjohnlev return (cpu.cpu_id); 127843e1988Sjohnlev } 128843e1988Sjohnlev 129843e1988Sjohnlev int 130843e1988Sjohnlev kt_cpustack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 131843e1988Sjohnlev { 132843e1988Sjohnlev mdb_tgt_t *t = mdb.m_target; 133843e1988Sjohnlev mdb_tgt_gregset_t regs; 134843e1988Sjohnlev intptr_t cpuid = 0; 135843e1988Sjohnlev uint_t verbose = 0; 136843e1988Sjohnlev int i; 137843e1988Sjohnlev 138843e1988Sjohnlev if (flags & DCMD_ADDRSPEC) { 139843e1988Sjohnlev if ((cpuid = kt_cpu2cpuid(addr)) < 0) { 140843e1988Sjohnlev (void) set_errno(EMDB_NOMAP); 141843e1988Sjohnlev mdb_warn("failed to find cpuid for cpu at %p", addr); 142843e1988Sjohnlev return (DCMD_ERR); 143843e1988Sjohnlev } 144843e1988Sjohnlev flags &= ~DCMD_ADDRSPEC; 145843e1988Sjohnlev } 146843e1988Sjohnlev 147843e1988Sjohnlev 148843e1988Sjohnlev i = mdb_getopts(argc, argv, 149843e1988Sjohnlev 'c', MDB_OPT_UINTPTR, &cpuid, 150843e1988Sjohnlev 'v', MDB_OPT_SETBITS, 1, &verbose, 151843e1988Sjohnlev NULL); 152843e1988Sjohnlev 153843e1988Sjohnlev argc -= i; 154843e1988Sjohnlev argv += i; 155843e1988Sjohnlev 156843e1988Sjohnlev if (kt_kvmregs(t, cpuid, ®s) != 0) { 157843e1988Sjohnlev mdb_warn("failed to get regs for cpu %d\n", cpuid); 158843e1988Sjohnlev return (DCMD_ERR); 159843e1988Sjohnlev } 160843e1988Sjohnlev 161843e1988Sjohnlev /* 162843e1988Sjohnlev * Tell the stack walker that we have regs. 163843e1988Sjohnlev */ 164843e1988Sjohnlev flags |= DCMD_ADDRSPEC; 165843e1988Sjohnlev addr = regs.kregs[KREG_FP]; 166843e1988Sjohnlev 167843e1988Sjohnlev if (verbose) 168843e1988Sjohnlev return (kt_stackv(addr, flags, argc, argv)); 169843e1988Sjohnlev else 170843e1988Sjohnlev return (kt_stack(addr, flags, argc, argv)); 171843e1988Sjohnlev } 172843e1988Sjohnlev 173843e1988Sjohnlev /*ARGSUSED*/ 174843e1988Sjohnlev int 175843e1988Sjohnlev kt_cpuregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 176843e1988Sjohnlev { 177843e1988Sjohnlev mdb_tgt_t *t = mdb.m_target; 178843e1988Sjohnlev mdb_tgt_gregset_t regs; 179843e1988Sjohnlev intptr_t cpuid = 0; 180843e1988Sjohnlev int i; 181843e1988Sjohnlev 182843e1988Sjohnlev if (flags & DCMD_ADDRSPEC) { 183843e1988Sjohnlev if (argc != 0) 184843e1988Sjohnlev return (DCMD_USAGE); 185843e1988Sjohnlev if ((cpuid = kt_cpu2cpuid(addr)) < 0) { 186843e1988Sjohnlev (void) set_errno(EMDB_NOMAP); 187843e1988Sjohnlev mdb_warn("failed to find cpuid for cpu at %p", addr); 188843e1988Sjohnlev return (DCMD_ERR); 189843e1988Sjohnlev } 190843e1988Sjohnlev } 191843e1988Sjohnlev 192843e1988Sjohnlev 193843e1988Sjohnlev i = mdb_getopts(argc, argv, 194843e1988Sjohnlev 'c', MDB_OPT_UINTPTR, &cpuid, 195843e1988Sjohnlev NULL); 196843e1988Sjohnlev 197843e1988Sjohnlev argc -= i; 198843e1988Sjohnlev argv += i; 199843e1988Sjohnlev 200843e1988Sjohnlev if (argc != 0) 201843e1988Sjohnlev return (DCMD_USAGE); 202843e1988Sjohnlev 203843e1988Sjohnlev if (kt_kvmregs(t, cpuid, ®s) != 0) { 204843e1988Sjohnlev mdb_warn("failed to get regs for cpu %d\n", cpuid); 205843e1988Sjohnlev return (DCMD_ERR); 206843e1988Sjohnlev } 207843e1988Sjohnlev 208843e1988Sjohnlev return (kt_regs((uintptr_t)®s, flags, argc, argv)); 209843e1988Sjohnlev } 210