Print this page
9709 Remove support for BZIP2 from dump
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
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>
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 67 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 ↓ |
796 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