Print this page
    
NEX-17845 Remove support for BZIP2 from dump
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
re #13613 rb4516 Tunables needs volatile keyword
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/sun4/os/machdep.c
          +++ new/usr/src/uts/sun4/os/machdep.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  23   24   * Copyright (c) 2017, Joyent, Inc.  All rights reserved.
  24   25   */
  25   26  
  26   27  #include <sys/types.h>
  27   28  #include <sys/kstat.h>
  28   29  #include <sys/param.h>
  29   30  #include <sys/stack.h>
  30   31  #include <sys/regset.h>
  31   32  #include <sys/thread.h>
  32   33  #include <sys/proc.h>
  33   34  #include <sys/procfs_isa.h>
  34   35  #include <sys/kmem.h>
  35   36  #include <sys/cpuvar.h>
  36   37  #include <sys/systm.h>
  37   38  #include <sys/machpcb.h>
  38   39  #include <sys/machasi.h>
  39   40  #include <sys/vis.h>
  40   41  #include <sys/fpu/fpusystm.h>
  41   42  #include <sys/cpu_module.h>
  42   43  #include <sys/privregs.h>
  43   44  #include <sys/archsystm.h>
  44   45  #include <sys/atomic.h>
  45   46  #include <sys/cmn_err.h>
  46   47  #include <sys/time.h>
  47   48  #include <sys/clock.h>
  48   49  #include <sys/cmp.h>
  49   50  #include <sys/platform_module.h>
  50   51  #include <sys/bl.h>
  51   52  #include <sys/nvpair.h>
  52   53  #include <sys/kdi_impl.h>
  53   54  #include <sys/machsystm.h>
  54   55  #include <sys/sysmacros.h>
  55   56  #include <sys/promif.h>
  
    | 
      ↓ open down ↓ | 
    23 lines elided | 
    
      ↑ open up ↑ | 
  
  56   57  #include <sys/pool_pset.h>
  57   58  #include <sys/mem.h>
  58   59  #include <sys/dumphdr.h>
  59   60  #include <vm/seg_kmem.h>
  60   61  #include <sys/hold_page.h>
  61   62  #include <sys/cpu.h>
  62   63  #include <sys/ivintr.h>
  63   64  #include <sys/clock_impl.h>
  64   65  #include <sys/machclock.h>
  65   66  
  66      -int maxphys = MMU_PAGESIZE * 16;        /* 128k */
       67 +volatile int maxphys = MMU_PAGESIZE * 16; /* 128k */
  67   68  int klustsize = MMU_PAGESIZE * 16;      /* 128k */
  68   69  
  69   70  /*
  70   71   * Initialize kernel thread's stack.
  71   72   */
  72   73  caddr_t
  73   74  thread_stk_init(caddr_t stk)
  74   75  {
  75   76          kfpu_t *fp;
  76   77          ulong_t align;
  77   78  
  78   79          /* allocate extra space for floating point state */
  79   80          stk -= SA(sizeof (kfpu_t) + GSR_SIZE);
  80   81          align = (uintptr_t)stk & 0x3f;
  81   82          stk -= align;           /* force v9_fpu to be 16 byte aligned */
  82   83          fp = (kfpu_t *)stk;
  83   84          fp->fpu_fprs = 0;
  84   85  
  85   86          stk -= SA(MINFRAME);
  86   87          return (stk);
  87   88  }
  88   89  
  89   90  #define WIN32_SIZE      (MAXWIN * sizeof (struct rwindow32))
  90   91  #define WIN64_SIZE      (MAXWIN * sizeof (struct rwindow64))
  91   92  
  92   93  kmem_cache_t    *wbuf32_cache;
  93   94  kmem_cache_t    *wbuf64_cache;
  94   95  
  95   96  void
  96   97  lwp_stk_cache_init(void)
  97   98  {
  98   99          /*
  99  100           * Window buffers are allocated from the static arena
 100  101           * because they are accessed at TL>0. We also must use
 101  102           * KMC_NOHASH to prevent them from straddling page
 102  103           * boundaries as they are accessed by physical address.
 103  104           */
 104  105          wbuf32_cache = kmem_cache_create("wbuf32_cache", WIN32_SIZE,
 105  106              0, NULL, NULL, NULL, NULL, static_arena, KMC_NOHASH);
 106  107          wbuf64_cache = kmem_cache_create("wbuf64_cache", WIN64_SIZE,
 107  108              0, NULL, NULL, NULL, NULL, static_arena, KMC_NOHASH);
 108  109  }
 109  110  
 110  111  /*
 111  112   * Initialize lwp's kernel stack.
 112  113   * Note that now that the floating point register save area (kfpu_t)
 113  114   * has been broken out from machpcb and aligned on a 64 byte boundary so that
 114  115   * we can do block load/stores to/from it, there are a couple of potential
 115  116   * optimizations to save stack space. 1. The floating point register save
 116  117   * area could be aligned on a 16 byte boundary, and the floating point code
 117  118   * changed to (a) check the alignment and (b) use different save/restore
 118  119   * macros depending upon the alignment. 2. The lwp_stk_init code below
 119  120   * could be changed to calculate if less space would be wasted if machpcb
 120  121   * was first instead of second. However there is a REGOFF macro used in
 121  122   * locore, syscall_trap, machdep and mlsetup that assumes that the saved
 122  123   * register area is a fixed distance from the %sp, and would have to be
 123  124   * changed to a pointer or something...JJ said later.
 124  125   */
 125  126  caddr_t
 126  127  lwp_stk_init(klwp_t *lwp, caddr_t stk)
 127  128  {
 128  129          struct machpcb *mpcb;
 129  130          kfpu_t *fp;
 130  131          uintptr_t aln;
 131  132  
 132  133          stk -= SA(sizeof (kfpu_t) + GSR_SIZE);
 133  134          aln = (uintptr_t)stk & 0x3F;
 134  135          stk -= aln;
 135  136          fp = (kfpu_t *)stk;
 136  137          stk -= SA(sizeof (struct machpcb));
 137  138          mpcb = (struct machpcb *)stk;
 138  139          bzero(mpcb, sizeof (struct machpcb));
 139  140          bzero(fp, sizeof (kfpu_t) + GSR_SIZE);
 140  141          lwp->lwp_regs = (void *)&mpcb->mpcb_regs;
 141  142          lwp->lwp_fpu = (void *)fp;
 142  143          mpcb->mpcb_fpu = fp;
 143  144          mpcb->mpcb_fpu->fpu_q = mpcb->mpcb_fpu_q;
 144  145          mpcb->mpcb_thread = lwp->lwp_thread;
 145  146          mpcb->mpcb_wbcnt = 0;
 146  147          if (lwp->lwp_procp->p_model == DATAMODEL_ILP32) {
 147  148                  mpcb->mpcb_wstate = WSTATE_USER32;
 148  149                  mpcb->mpcb_wbuf = kmem_cache_alloc(wbuf32_cache, KM_SLEEP);
 149  150          } else {
 150  151                  mpcb->mpcb_wstate = WSTATE_USER64;
 151  152                  mpcb->mpcb_wbuf = kmem_cache_alloc(wbuf64_cache, KM_SLEEP);
 152  153          }
 153  154          ASSERT(((uintptr_t)mpcb->mpcb_wbuf & 7) == 0);
 154  155          mpcb->mpcb_wbuf_pa = va_to_pa(mpcb->mpcb_wbuf);
 155  156          mpcb->mpcb_pa = va_to_pa(mpcb);
 156  157          return (stk);
 157  158  }
 158  159  
 159  160  void
 160  161  lwp_stk_fini(klwp_t *lwp)
 161  162  {
 162  163          struct machpcb *mpcb = lwptompcb(lwp);
 163  164  
 164  165          /*
 165  166           * there might be windows still in the wbuf due to unmapped
 166  167           * stack, misaligned stack pointer, etc.  We just free it.
 167  168           */
 168  169          mpcb->mpcb_wbcnt = 0;
 169  170          if (mpcb->mpcb_wstate == WSTATE_USER32)
 170  171                  kmem_cache_free(wbuf32_cache, mpcb->mpcb_wbuf);
 171  172          else
 172  173                  kmem_cache_free(wbuf64_cache, mpcb->mpcb_wbuf);
 173  174          mpcb->mpcb_wbuf = NULL;
 174  175          mpcb->mpcb_wbuf_pa = -1;
 175  176  }
 176  177  
 177  178  /*ARGSUSED*/
 178  179  void
 179  180  lwp_fp_init(klwp_t *lwp)
 180  181  {
 181  182  }
 182  183  
 183  184  /*
 184  185   * Copy regs from parent to child.
 185  186   */
 186  187  void
 187  188  lwp_forkregs(klwp_t *lwp, klwp_t *clwp)
 188  189  {
 189  190          kthread_t *t, *pt = lwptot(lwp);
 190  191          struct machpcb *mpcb = lwptompcb(clwp);
 191  192          struct machpcb *pmpcb = lwptompcb(lwp);
 192  193          kfpu_t *fp, *pfp = lwptofpu(lwp);
 193  194          caddr_t wbuf;
 194  195          uint_t wstate;
 195  196  
 196  197          t = mpcb->mpcb_thread;
 197  198          /*
 198  199           * remember child's fp and wbuf since they will get erased during
 199  200           * the bcopy.
 200  201           */
 201  202          fp = mpcb->mpcb_fpu;
 202  203          wbuf = mpcb->mpcb_wbuf;
 203  204          wstate = mpcb->mpcb_wstate;
 204  205          /*
 205  206           * Don't copy mpcb_frame since we hand-crafted it
 206  207           * in thread_load().
 207  208           */
 208  209          bcopy(lwp->lwp_regs, clwp->lwp_regs, sizeof (struct machpcb) - REGOFF);
 209  210          mpcb->mpcb_thread = t;
 210  211          mpcb->mpcb_fpu = fp;
 211  212          fp->fpu_q = mpcb->mpcb_fpu_q;
 212  213  
 213  214          /*
 214  215           * It is theoretically possibly for the lwp's wstate to
 215  216           * be different from its value assigned in lwp_stk_init,
 216  217           * since lwp_stk_init assumed the data model of the process.
 217  218           * Here, we took on the data model of the cloned lwp.
 218  219           */
 219  220          if (mpcb->mpcb_wstate != wstate) {
 220  221                  if (wstate == WSTATE_USER32) {
 221  222                          kmem_cache_free(wbuf32_cache, wbuf);
 222  223                          wbuf = kmem_cache_alloc(wbuf64_cache, KM_SLEEP);
 223  224                          wstate = WSTATE_USER64;
 224  225                  } else {
 225  226                          kmem_cache_free(wbuf64_cache, wbuf);
 226  227                          wbuf = kmem_cache_alloc(wbuf32_cache, KM_SLEEP);
 227  228                          wstate = WSTATE_USER32;
 228  229                  }
 229  230          }
 230  231  
 231  232          mpcb->mpcb_pa = va_to_pa(mpcb);
 232  233          mpcb->mpcb_wbuf = wbuf;
 233  234          mpcb->mpcb_wbuf_pa = va_to_pa(wbuf);
 234  235  
 235  236          ASSERT(mpcb->mpcb_wstate == wstate);
 236  237  
 237  238          if (mpcb->mpcb_wbcnt != 0) {
 238  239                  bcopy(pmpcb->mpcb_wbuf, mpcb->mpcb_wbuf,
 239  240                      mpcb->mpcb_wbcnt * ((mpcb->mpcb_wstate == WSTATE_USER32) ?
 240  241                      sizeof (struct rwindow32) : sizeof (struct rwindow64)));
 241  242          }
 242  243  
 243  244          if (pt == curthread)
 244  245                  pfp->fpu_fprs = _fp_read_fprs();
 245  246          if ((pfp->fpu_en) || (pfp->fpu_fprs & FPRS_FEF)) {
 246  247                  if (pt == curthread && fpu_exists) {
 247  248                          save_gsr(clwp->lwp_fpu);
 248  249                  } else {
 249  250                          uint64_t gsr;
 250  251                          gsr = get_gsr(lwp->lwp_fpu);
 251  252                          set_gsr(gsr, clwp->lwp_fpu);
 252  253                  }
 253  254                  fp_fork(lwp, clwp);
 254  255          }
 255  256  }
 256  257  
 257  258  /*
 258  259   * Free lwp fpu regs.
 259  260   */
 260  261  void
 261  262  lwp_freeregs(klwp_t *lwp, int isexec)
 262  263  {
 263  264          kfpu_t *fp = lwptofpu(lwp);
 264  265  
 265  266          if (lwptot(lwp) == curthread)
 266  267                  fp->fpu_fprs = _fp_read_fprs();
 267  268          if ((fp->fpu_en) || (fp->fpu_fprs & FPRS_FEF))
 268  269                  fp_free(fp, isexec);
 269  270  }
 270  271  
 271  272  /*
 272  273   * These function are currently unused on sparc.
 273  274   */
 274  275  /*ARGSUSED*/
 275  276  void
 276  277  lwp_attach_brand_hdlrs(klwp_t *lwp)
 277  278  {}
 278  279  
 279  280  /*ARGSUSED*/
 280  281  void
 281  282  lwp_detach_brand_hdlrs(klwp_t *lwp)
 282  283  {}
 283  284  
 284  285  /*
 285  286   * fill in the extra register state area specified with the
 286  287   * specified lwp's platform-dependent non-floating-point extra
 287  288   * register state information
 288  289   */
 289  290  /* ARGSUSED */
 290  291  void
 291  292  xregs_getgfiller(klwp_id_t lwp, caddr_t xrp)
 292  293  {
 293  294          /* for sun4u nothing to do here, added for symmetry */
 294  295  }
 295  296  
 296  297  /*
 297  298   * fill in the extra register state area specified with the specified lwp's
 298  299   * platform-dependent floating-point extra register state information.
 299  300   * NOTE:  'lwp' might not correspond to 'curthread' since this is
 300  301   * called from code in /proc to get the registers of another lwp.
 301  302   */
 302  303  void
 303  304  xregs_getfpfiller(klwp_id_t lwp, caddr_t xrp)
 304  305  {
 305  306          prxregset_t *xregs = (prxregset_t *)xrp;
 306  307          kfpu_t *fp = lwptofpu(lwp);
 307  308          uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL);
 308  309          uint64_t gsr;
 309  310  
 310  311          /*
 311  312           * fp_fksave() does not flush the GSR register into
 312  313           * the lwp area, so do it now
 313  314           */
 314  315          kpreempt_disable();
 315  316          if (ttolwp(curthread) == lwp && fpu_exists) {
 316  317                  fp->fpu_fprs = _fp_read_fprs();
 317  318                  if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) {
 318  319                          _fp_write_fprs(fprs);
 319  320                          fp->fpu_fprs = (V9_FPU_FPRS_TYPE)fprs;
 320  321                  }
 321  322                  save_gsr(fp);
 322  323          }
 323  324          gsr = get_gsr(fp);
 324  325          kpreempt_enable();
 325  326          PRXREG_GSR(xregs) = gsr;
 326  327  }
 327  328  
 328  329  /*
 329  330   * set the specified lwp's platform-dependent non-floating-point
 330  331   * extra register state based on the specified input
 331  332   */
 332  333  /* ARGSUSED */
 333  334  void
 334  335  xregs_setgfiller(klwp_id_t lwp, caddr_t xrp)
 335  336  {
 336  337          /* for sun4u nothing to do here, added for symmetry */
 337  338  }
 338  339  
 339  340  /*
 340  341   * set the specified lwp's platform-dependent floating-point
 341  342   * extra register state based on the specified input
 342  343   */
 343  344  void
 344  345  xregs_setfpfiller(klwp_id_t lwp, caddr_t xrp)
 345  346  {
 346  347          prxregset_t *xregs = (prxregset_t *)xrp;
 347  348          kfpu_t *fp = lwptofpu(lwp);
 348  349          uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL);
 349  350          uint64_t gsr = PRXREG_GSR(xregs);
 350  351  
 351  352          kpreempt_disable();
 352  353          set_gsr(gsr, lwptofpu(lwp));
 353  354  
 354  355          if ((lwp == ttolwp(curthread)) && fpu_exists) {
 355  356                  fp->fpu_fprs = _fp_read_fprs();
 356  357                  if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) {
 357  358                          _fp_write_fprs(fprs);
 358  359                          fp->fpu_fprs = (V9_FPU_FPRS_TYPE)fprs;
 359  360                  }
 360  361                  restore_gsr(lwptofpu(lwp));
 361  362          }
 362  363          kpreempt_enable();
 363  364  }
 364  365  
 365  366  /*
 366  367   * fill in the sun4u asrs, ie, the lwp's platform-dependent
 367  368   * non-floating-point extra register state information
 368  369   */
 369  370  /* ARGSUSED */
 370  371  void
 371  372  getasrs(klwp_t *lwp, asrset_t asr)
 372  373  {
 373  374          /* for sun4u nothing to do here, added for symmetry */
 374  375  }
 375  376  
 376  377  /*
 377  378   * fill in the sun4u asrs, ie, the lwp's platform-dependent
 378  379   * floating-point extra register state information
 379  380   */
 380  381  void
 381  382  getfpasrs(klwp_t *lwp, asrset_t asr)
 382  383  {
 383  384          kfpu_t *fp = lwptofpu(lwp);
 384  385          uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL);
 385  386  
 386  387          kpreempt_disable();
 387  388          if (ttolwp(curthread) == lwp)
 388  389                  fp->fpu_fprs = _fp_read_fprs();
 389  390          if ((fp->fpu_en) || (fp->fpu_fprs & FPRS_FEF)) {
 390  391                  if (fpu_exists && ttolwp(curthread) == lwp) {
 391  392                          if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) {
 392  393                                  _fp_write_fprs(fprs);
 393  394                                  fp->fpu_fprs = (V9_FPU_FPRS_TYPE)fprs;
 394  395                          }
 395  396                          save_gsr(fp);
 396  397                  }
 397  398                  asr[ASR_GSR] = (int64_t)get_gsr(fp);
 398  399          }
 399  400          kpreempt_enable();
 400  401  }
 401  402  
 402  403  /*
 403  404   * set the sun4u asrs, ie, the lwp's platform-dependent
 404  405   * non-floating-point extra register state information
 405  406   */
 406  407  /* ARGSUSED */
 407  408  void
 408  409  setasrs(klwp_t *lwp, asrset_t asr)
 409  410  {
 410  411          /* for sun4u nothing to do here, added for symmetry */
 411  412  }
 412  413  
 413  414  void
 414  415  setfpasrs(klwp_t *lwp, asrset_t asr)
 415  416  {
 416  417          kfpu_t *fp = lwptofpu(lwp);
 417  418          uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL);
 418  419  
 419  420          kpreempt_disable();
 420  421          if (ttolwp(curthread) == lwp)
 421  422                  fp->fpu_fprs = _fp_read_fprs();
 422  423          if ((fp->fpu_en) || (fp->fpu_fprs & FPRS_FEF)) {
 423  424                  set_gsr(asr[ASR_GSR], fp);
 424  425                  if (fpu_exists && ttolwp(curthread) == lwp) {
 425  426                          if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) {
 426  427                                  _fp_write_fprs(fprs);
 427  428                                  fp->fpu_fprs = (V9_FPU_FPRS_TYPE)fprs;
 428  429                          }
 429  430                          restore_gsr(fp);
 430  431                  }
 431  432          }
 432  433          kpreempt_enable();
 433  434  }
 434  435  
 435  436  /*
 436  437   * Create interrupt kstats for this CPU.
 437  438   */
 438  439  void
 439  440  cpu_create_intrstat(cpu_t *cp)
 440  441  {
 441  442          int             i;
 442  443          kstat_t         *intr_ksp;
 443  444          kstat_named_t   *knp;
 444  445          char            name[KSTAT_STRLEN];
 445  446          zoneid_t        zoneid;
 446  447  
 447  448          ASSERT(MUTEX_HELD(&cpu_lock));
 448  449  
 449  450          if (pool_pset_enabled())
 450  451                  zoneid = GLOBAL_ZONEID;
 451  452          else
 452  453                  zoneid = ALL_ZONES;
 453  454  
 454  455          intr_ksp = kstat_create_zone("cpu", cp->cpu_id, "intrstat", "misc",
 455  456              KSTAT_TYPE_NAMED, PIL_MAX * 2, NULL, zoneid);
 456  457  
 457  458          /*
 458  459           * Initialize each PIL's named kstat
 459  460           */
 460  461          if (intr_ksp != NULL) {
 461  462                  intr_ksp->ks_update = cpu_kstat_intrstat_update;
 462  463                  knp = (kstat_named_t *)intr_ksp->ks_data;
 463  464                  intr_ksp->ks_private = cp;
 464  465                  for (i = 0; i < PIL_MAX; i++) {
 465  466                          (void) snprintf(name, KSTAT_STRLEN, "level-%d-time",
 466  467                              i + 1);
 467  468                          kstat_named_init(&knp[i * 2], name, KSTAT_DATA_UINT64);
 468  469                          (void) snprintf(name, KSTAT_STRLEN, "level-%d-count",
 469  470                              i + 1);
 470  471                          kstat_named_init(&knp[(i * 2) + 1], name,
 471  472                              KSTAT_DATA_UINT64);
 472  473                  }
 473  474                  kstat_install(intr_ksp);
 474  475          }
 475  476  }
 476  477  
 477  478  /*
 478  479   * Delete interrupt kstats for this CPU.
 479  480   */
 480  481  void
 481  482  cpu_delete_intrstat(cpu_t *cp)
 482  483  {
 483  484          kstat_delete_byname_zone("cpu", cp->cpu_id, "intrstat", ALL_ZONES);
 484  485  }
 485  486  
 486  487  /*
 487  488   * Convert interrupt statistics from CPU ticks to nanoseconds and
 488  489   * update kstat.
 489  490   */
 490  491  int
 491  492  cpu_kstat_intrstat_update(kstat_t *ksp, int rw)
 492  493  {
 493  494          kstat_named_t   *knp = ksp->ks_data;
 494  495          cpu_t           *cpup = (cpu_t *)ksp->ks_private;
 495  496          int             i;
 496  497  
 497  498          if (rw == KSTAT_WRITE)
 498  499                  return (EACCES);
 499  500  
 500  501          /*
 501  502           * We use separate passes to copy and convert the statistics to
 502  503           * nanoseconds. This assures that the snapshot of the data is as
 503  504           * self-consistent as possible.
 504  505           */
 505  506  
 506  507          for (i = 0; i < PIL_MAX; i++) {
 507  508                  knp[i * 2].value.ui64 = cpup->cpu_m.intrstat[i + 1][0];
 508  509                  knp[(i * 2) + 1].value.ui64 = cpup->cpu_stats.sys.intr[i];
 509  510          }
 510  511  
 511  512          for (i = 0; i < PIL_MAX; i++) {
 512  513                  knp[i * 2].value.ui64 =
 513  514                      (uint64_t)tick2ns((hrtime_t)knp[i * 2].value.ui64,
 514  515                      cpup->cpu_id);
 515  516          }
 516  517  
 517  518          return (0);
 518  519  }
 519  520  
 520  521  /*
 521  522   * Called by common/os/cpu.c for psrinfo(1m) kstats
 522  523   */
 523  524  char *
 524  525  cpu_fru_fmri(cpu_t *cp)
 525  526  {
 526  527          return (cpunodes[cp->cpu_id].fru_fmri);
 527  528  }
 528  529  
 529  530  /*
 530  531   * An interrupt thread is ending a time slice, so compute the interval it
 531  532   * ran for and update the statistic for its PIL.
 532  533   */
 533  534  void
 534  535  cpu_intr_swtch_enter(kthread_id_t t)
 535  536  {
 536  537          uint64_t        interval;
 537  538          uint64_t        start;
 538  539          cpu_t           *cpu;
 539  540  
 540  541          ASSERT((t->t_flag & T_INTR_THREAD) != 0);
 541  542          ASSERT(t->t_pil > 0 && t->t_pil <= LOCK_LEVEL);
 542  543  
 543  544          /*
 544  545           * We could be here with a zero timestamp. This could happen if:
 545  546           * an interrupt thread which no longer has a pinned thread underneath
 546  547           * it (i.e. it blocked at some point in its past) has finished running
 547  548           * its handler. intr_thread() updated the interrupt statistic for its
 548  549           * PIL and zeroed its timestamp. Since there was no pinned thread to
 549  550           * return to, swtch() gets called and we end up here.
 550  551           *
 551  552           * It can also happen if an interrupt thread in intr_thread() calls
 552  553           * preempt. It will have already taken care of updating stats. In
 553  554           * this event, the interrupt thread will be runnable.
 554  555           */
 555  556          if (t->t_intr_start) {
 556  557                  do {
 557  558                          start = t->t_intr_start;
 558  559                          interval = CLOCK_TICK_COUNTER() - start;
 559  560                  } while (atomic_cas_64(&t->t_intr_start, start, 0) != start);
 560  561                  cpu = CPU;
 561  562                  if (cpu->cpu_m.divisor > 1)
 562  563                          interval *= cpu->cpu_m.divisor;
 563  564                  cpu->cpu_m.intrstat[t->t_pil][0] += interval;
 564  565  
 565  566                  atomic_add_64((uint64_t *)&cpu->cpu_intracct[cpu->cpu_mstate],
 566  567                      interval);
 567  568          } else
 568  569                  ASSERT(t->t_intr == NULL || t->t_state == TS_RUN);
 569  570  }
 570  571  
 571  572  
 572  573  /*
 573  574   * An interrupt thread is returning from swtch(). Place a starting timestamp
 574  575   * in its thread structure.
 575  576   */
 576  577  void
 577  578  cpu_intr_swtch_exit(kthread_id_t t)
 578  579  {
 579  580          uint64_t ts;
 580  581  
 581  582          ASSERT((t->t_flag & T_INTR_THREAD) != 0);
 582  583          ASSERT(t->t_pil > 0 && t->t_pil <= LOCK_LEVEL);
 583  584  
 584  585          do {
 585  586                  ts = t->t_intr_start;
 586  587          } while (atomic_cas_64(&t->t_intr_start, ts, CLOCK_TICK_COUNTER()) !=
 587  588              ts);
 588  589  }
 589  590  
 590  591  
 591  592  int
 592  593  blacklist(int cmd, const char *scheme, nvlist_t *fmri, const char *class)
 593  594  {
 594  595          if (&plat_blacklist)
 595  596                  return (plat_blacklist(cmd, scheme, fmri, class));
 596  597  
 597  598          return (ENOTSUP);
 598  599  }
 599  600  
 600  601  int
 601  602  kdi_pread(caddr_t buf, size_t nbytes, uint64_t addr, size_t *ncopiedp)
 602  603  {
 603  604          extern void kdi_flush_caches(void);
 604  605          size_t nread = 0;
 605  606          uint32_t word;
 606  607          int slop, i;
 607  608  
 608  609          kdi_flush_caches();
 609  610          membar_enter();
 610  611  
 611  612          /* We might not begin on a word boundary. */
 612  613          if ((slop = addr & 3) != 0) {
 613  614                  word = ldphys(addr & ~3);
 614  615                  for (i = slop; i < 4 && nbytes > 0; i++, nbytes--, nread++)
 615  616                          *buf++ = ((uchar_t *)&word)[i];
 616  617                  addr = roundup(addr, 4);
 617  618          }
 618  619  
 619  620          while (nbytes > 0) {
 620  621                  word = ldphys(addr);
 621  622                  for (i = 0; i < 4 && nbytes > 0; i++, nbytes--, nread++, addr++)
 622  623                          *buf++ = ((uchar_t *)&word)[i];
 623  624          }
 624  625  
 625  626          kdi_flush_caches();
 626  627  
 627  628          *ncopiedp = nread;
 628  629          return (0);
 629  630  }
 630  631  
 631  632  int
 632  633  kdi_pwrite(caddr_t buf, size_t nbytes, uint64_t addr, size_t *ncopiedp)
 633  634  {
 634  635          extern void kdi_flush_caches(void);
 635  636          size_t nwritten = 0;
 636  637          uint32_t word;
 637  638          int slop, i;
 638  639  
 639  640          kdi_flush_caches();
 640  641  
 641  642          /* We might not begin on a word boundary. */
 642  643          if ((slop = addr & 3) != 0) {
 643  644                  word = ldphys(addr & ~3);
 644  645                  for (i = slop; i < 4 && nbytes > 0; i++, nbytes--, nwritten++)
 645  646                          ((uchar_t *)&word)[i] = *buf++;
 646  647                  stphys(addr & ~3, word);
 647  648                  addr = roundup(addr, 4);
 648  649          }
 649  650  
 650  651          while (nbytes > 3) {
 651  652                  for (word = 0, i = 0; i < 4; i++, nbytes--, nwritten++)
 652  653                          ((uchar_t *)&word)[i] = *buf++;
 653  654                  stphys(addr, word);
 654  655                  addr += 4;
 655  656          }
 656  657  
 657  658          /* We might not end with a whole word. */
 658  659          if (nbytes > 0) {
 659  660                  word = ldphys(addr);
 660  661                  for (i = 0; nbytes > 0; i++, nbytes--, nwritten++)
 661  662                          ((uchar_t *)&word)[i] = *buf++;
 662  663                  stphys(addr, word);
 663  664          }
 664  665  
 665  666          membar_enter();
 666  667          kdi_flush_caches();
 667  668  
 668  669          *ncopiedp = nwritten;
 669  670          return (0);
 670  671  }
 671  672  
 672  673  static void
 673  674  kdi_kernpanic(struct regs *regs, uint_t tt)
 674  675  {
 675  676          sync_reg_buf = *regs;
 676  677          sync_tt = tt;
 677  678  
 678  679          sync_handler();
 679  680  }
 680  681  
 681  682  static void
 682  683  kdi_plat_call(void (*platfn)(void))
 683  684  {
 684  685          if (platfn != NULL) {
 685  686                  prom_suspend_prepost();
 686  687                  platfn();
 687  688                  prom_resume_prepost();
 688  689          }
 689  690  }
 690  691  
 691  692  /*
 692  693   * kdi_system_claim and release are defined here for all sun4 platforms and
 693  694   * pointed to by mach_kdi_init() to provide default callbacks for such systems.
 694  695   * Specific sun4u or sun4v platforms may implement their own claim and release
 695  696   * routines, at which point their respective callbacks will be updated.
 696  697   */
 697  698  static void
 698  699  kdi_system_claim(void)
 699  700  {
 700  701          lbolt_debug_entry();
 701  702  }
 702  703  
 703  704  static void
 704  705  kdi_system_release(void)
 705  706  {
 706  707          lbolt_debug_return();
 707  708  }
 708  709  
 709  710  void
 710  711  mach_kdi_init(kdi_t *kdi)
 711  712  {
 712  713          kdi->kdi_plat_call = kdi_plat_call;
 713  714          kdi->kdi_kmdb_enter = kmdb_enter;
 714  715          kdi->pkdi_system_claim = kdi_system_claim;
 715  716          kdi->pkdi_system_release = kdi_system_release;
 716  717          kdi->mkdi_cpu_index = kdi_cpu_index;
 717  718          kdi->mkdi_trap_vatotte = kdi_trap_vatotte;
 718  719          kdi->mkdi_kernpanic = kdi_kernpanic;
 719  720  }
 720  721  
 721  722  
 722  723  /*
 723  724   * get_cpu_mstate() is passed an array of timestamps, NCMSTATES
 724  725   * long, and it fills in the array with the time spent on cpu in
 725  726   * each of the mstates, where time is returned in nsec.
 726  727   *
 727  728   * No guarantee is made that the returned values in times[] will
 728  729   * monotonically increase on sequential calls, although this will
 729  730   * be true in the long run. Any such guarantee must be handled by
 730  731   * the caller, if needed. This can happen if we fail to account
 731  732   * for elapsed time due to a generation counter conflict, yet we
 732  733   * did account for it on a prior call (see below).
 733  734   *
 734  735   * The complication is that the cpu in question may be updating
 735  736   * its microstate at the same time that we are reading it.
 736  737   * Because the microstate is only updated when the CPU's state
 737  738   * changes, the values in cpu_intracct[] can be indefinitely out
 738  739   * of date. To determine true current values, it is necessary to
 739  740   * compare the current time with cpu_mstate_start, and add the
 740  741   * difference to times[cpu_mstate].
 741  742   *
 742  743   * This can be a problem if those values are changing out from
 743  744   * under us. Because the code path in new_cpu_mstate() is
 744  745   * performance critical, we have not added a lock to it. Instead,
 745  746   * we have added a generation counter. Before beginning
 746  747   * modifications, the counter is set to 0. After modifications,
 747  748   * it is set to the old value plus one.
 748  749   *
 749  750   * get_cpu_mstate() will not consider the values of cpu_mstate
 750  751   * and cpu_mstate_start to be usable unless the value of
 751  752   * cpu_mstate_gen is both non-zero and unchanged, both before and
 752  753   * after reading the mstate information. Note that we must
 753  754   * protect against out-of-order loads around accesses to the
 754  755   * generation counter. Also, this is a best effort approach in
 755  756   * that we do not retry should the counter be found to have
 756  757   * changed.
 757  758   *
 758  759   * cpu_intracct[] is used to identify time spent in each CPU
 759  760   * mstate while handling interrupts. Such time should be reported
 760  761   * against system time, and so is subtracted out from its
 761  762   * corresponding cpu_acct[] time and added to
 762  763   * cpu_acct[CMS_SYSTEM]. Additionally, intracct time is stored in
 763  764   * %ticks, but acct time may be stored as %sticks, thus requiring
 764  765   * different conversions before they can be compared.
 765  766   */
 766  767  
 767  768  void
 768  769  get_cpu_mstate(cpu_t *cpu, hrtime_t *times)
 769  770  {
 770  771          int i;
 771  772          hrtime_t now, start;
 772  773          uint16_t gen;
 773  774          uint16_t state;
 774  775          hrtime_t intracct[NCMSTATES];
 775  776  
 776  777          /*
 777  778           * Load all volatile state under the protection of membar.
 778  779           * cpu_acct[cpu_mstate] must be loaded to avoid double counting
 779  780           * of (now - cpu_mstate_start) by a change in CPU mstate that
 780  781           * arrives after we make our last check of cpu_mstate_gen.
 781  782           */
 782  783  
 783  784          now = gethrtime_unscaled();
 784  785          gen = cpu->cpu_mstate_gen;
 785  786  
 786  787          membar_consumer();      /* guarantee load ordering */
 787  788          start = cpu->cpu_mstate_start;
 788  789          state = cpu->cpu_mstate;
 789  790          for (i = 0; i < NCMSTATES; i++) {
 790  791                  intracct[i] = cpu->cpu_intracct[i];
 791  792                  times[i] = cpu->cpu_acct[i];
 792  793          }
 793  794          membar_consumer();      /* guarantee load ordering */
 794  795  
 795  796          if (gen != 0 && gen == cpu->cpu_mstate_gen && now > start)
 796  797                  times[state] += now - start;
 797  798  
 798  799          for (i = 0; i < NCMSTATES; i++) {
 799  800                  scalehrtime(×[i]);
 800  801                  intracct[i] = tick2ns((hrtime_t)intracct[i], cpu->cpu_id);
 801  802          }
 802  803  
 803  804          for (i = 0; i < NCMSTATES; i++) {
 804  805                  if (i == CMS_SYSTEM)
 805  806                          continue;
 806  807                  times[i] -= intracct[i];
 807  808                  if (times[i] < 0) {
 808  809                          intracct[i] += times[i];
 809  810                          times[i] = 0;
 810  811                  }
 811  812                  times[CMS_SYSTEM] += intracct[i];
 812  813          }
 813  814  }
 814  815  
 815  816  void
 816  817  mach_cpu_pause(volatile char *safe)
 817  818  {
 818  819          /*
 819  820           * This cpu is now safe.
 820  821           */
 821  822          *safe = PAUSE_WAIT;
 822  823          membar_enter(); /* make sure stores are flushed */
 823  824  
 824  825          /*
 825  826           * Now we wait.  When we are allowed to continue, safe
 826  827           * will be set to PAUSE_IDLE.
 827  828           */
 828  829          while (*safe != PAUSE_IDLE)
  
    | 
      ↓ open down ↓ | 
    752 lines elided | 
    
      ↑ open up ↑ | 
  
 829  830                  SMT_PAUSE();
 830  831  }
 831  832  
 832  833  /*ARGSUSED*/
 833  834  int
 834  835  plat_mem_do_mmio(struct uio *uio, enum uio_rw rw)
 835  836  {
 836  837          return (ENOTSUP);
 837  838  }
 838  839  
 839      -/* cpu threshold for compressed dumps */
 840      -#ifdef sun4v
 841      -uint_t dump_plat_mincpu_default = DUMP_PLAT_SUN4V_MINCPU;
 842      -#else
 843      -uint_t dump_plat_mincpu_default = DUMP_PLAT_SUN4U_MINCPU;
 844      -#endif
 845      -
 846  840  int
 847  841  dump_plat_addr()
 848  842  {
 849  843          return (0);
 850  844  }
 851  845  
 852  846  void
 853  847  dump_plat_pfn()
 854  848  {
 855  849  }
 856  850  
 857  851  /* ARGSUSED */
 858  852  int
 859  853  dump_plat_data(void *dump_cdata)
 860  854  {
 861  855          return (0);
 862  856  }
 863  857  
 864  858  /* ARGSUSED */
 865  859  int
 866  860  plat_hold_page(pfn_t pfn, int lock, page_t **pp_ret)
 867  861  {
 868  862          return (PLAT_HOLD_OK);
 869  863  }
 870  864  
 871  865  /* ARGSUSED */
 872  866  void
 873  867  plat_release_page(page_t *pp)
 874  868  {
 875  869  }
 876  870  
 877  871  /* ARGSUSED */
 878  872  void
 879  873  progressbar_key_abort(ldi_ident_t li)
 880  874  {
 881  875  }
 882  876  
 883  877  /*
 884  878   * We need to post a soft interrupt to reprogram the lbolt cyclic when
 885  879   * switching from event to cyclic driven lbolt. The following code adds
 886  880   * and posts the softint for sun4 platforms.
 887  881   */
 888  882  static uint64_t lbolt_softint_inum;
 889  883  
 890  884  void
 891  885  lbolt_softint_add(void)
 892  886  {
 893  887          lbolt_softint_inum = add_softintr(LOCK_LEVEL,
 894  888              (softintrfunc)lbolt_ev_to_cyclic, NULL, SOFTINT_MT);
 895  889  }
 896  890  
 897  891  void
 898  892  lbolt_softint_post(void)
 899  893  {
 900  894          setsoftint(lbolt_softint_inum);
 901  895  }
  
    | 
      ↓ open down ↓ | 
    46 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX