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