1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <sys/cpuvar.h>
  27 #include <sys/kdi_impl.h>
  28 #include <sys/reboot.h>
  29 #include <sys/errno.h>
  30 #include <sys/atomic.h>
  31 #include <sys/kmem.h>
  32 
  33 kdi_debugvec_t  *kdi_dvec;
  34 struct modctl   *kdi_dmods;
  35 
  36 static kdi_dtrace_state_t kdi_dtrace_state = KDI_DTSTATE_IDLE;
  37 
  38 void
  39 kdi_dvec_vmready(void)
  40 {
  41         kdi_dvec->dv_kctl_vmready();
  42         kdi_dvec->dv_vmready();
  43 }
  44 
  45 void
  46 kdi_dvec_memavail(void)
  47 {
  48         /*
  49          * The driver will allocate more memory (if requested), and will call
  50          * dv_memavail itself.
  51          */
  52         kdi_dvec->dv_kctl_memavail();
  53 }
  54 
  55 #if defined(__x86)
  56 void
  57 kdi_dvec_handle_fault(greg_t trapno, greg_t pc, greg_t sp, int cpuid)
  58 {
  59         kdi_dvec->dv_handle_fault(trapno, pc, sp, cpuid);
  60 }
  61 #endif
  62 
  63 #if defined(__sparc)
  64 /*
  65  * Called on the CPU being initialized
  66  */
  67 void
  68 kdi_dvec_cpu_init(struct cpu *cp)
  69 {
  70         kdi_dvec->dv_kctl_cpu_init();
  71         kdi_dvec->dv_cpu_init(cp);
  72 }
  73 
  74 void
  75 kdi_dvec_cpr_restart(void)
  76 {
  77         kdi_dvec->dv_kctl_cpu_init();
  78         kdi_dvec->dv_cpr_restart();
  79 }
  80 #endif  /* __sparc */
  81 
  82 void
  83 kdi_dvec_modavail(void)
  84 {
  85         kdi_dvec->dv_kctl_modavail();
  86 }
  87 
  88 void
  89 kdi_dvec_thravail(void)
  90 {
  91         kdi_dvec->dv_kctl_thravail();
  92 }
  93 
  94 void
  95 kdi_dvec_mod_loaded(struct modctl *modp)
  96 {
  97         kdi_dvec->dv_mod_loaded(modp);
  98 }
  99 
 100 void
 101 kdi_dvec_mod_unloading(struct modctl *modp)
 102 {
 103         kdi_dvec->dv_mod_unloading(modp);
 104 }
 105 
 106 kdi_dtrace_state_t
 107 kdi_dtrace_get_state(void)
 108 {
 109         return (kdi_dtrace_state);
 110 }
 111 
 112 int
 113 kdi_dtrace_set(kdi_dtrace_set_t transition)
 114 {
 115         kdi_dtrace_state_t new, cur;
 116 
 117         do {
 118                 cur = kdi_dtrace_state;
 119 
 120                 switch (transition) {
 121                 case KDI_DTSET_DTRACE_ACTIVATE:
 122                         if (cur == KDI_DTSTATE_KMDB_BPT_ACTIVE)
 123                                 return (EBUSY);
 124                         if (cur == KDI_DTSTATE_DTRACE_ACTIVE)
 125                                 return (0);
 126                         new = KDI_DTSTATE_DTRACE_ACTIVE;
 127                         break;
 128                 case KDI_DTSET_DTRACE_DEACTIVATE:
 129                         if (cur == KDI_DTSTATE_KMDB_BPT_ACTIVE)
 130                                 return (EBUSY);
 131                         if (cur == KDI_DTSTATE_IDLE)
 132                                 return (0);
 133                         new = KDI_DTSTATE_IDLE;
 134                         break;
 135                 case KDI_DTSET_KMDB_BPT_ACTIVATE:
 136                         if (cur == KDI_DTSTATE_DTRACE_ACTIVE)
 137                                 return (EBUSY);
 138                         if (cur == KDI_DTSTATE_KMDB_BPT_ACTIVE)
 139                                 return (0);
 140                         new = KDI_DTSTATE_KMDB_BPT_ACTIVE;
 141                         break;
 142                 case KDI_DTSET_KMDB_BPT_DEACTIVATE:
 143                         if (cur == KDI_DTSTATE_DTRACE_ACTIVE)
 144                                 return (EBUSY);
 145                         if (cur == KDI_DTSTATE_IDLE)
 146                                 return (0);
 147                         new = KDI_DTSTATE_IDLE;
 148                         break;
 149                 default:
 150                         return (EINVAL);
 151                 }
 152         } while (atomic_cas_32((uint_t *)&kdi_dtrace_state, cur, new) != cur);
 153 
 154         return (0);
 155 }