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 /*
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <sys/types.h>
30 #include <sys/conf.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/ddi_impldefs.h>
34 #include <sys/obpdefs.h>
35 #include <sys/cmn_err.h>
36 #include <sys/errno.h>
37 #include <sys/kmem.h>
38 #include <sys/vmem.h>
39 #include <sys/debug.h>
40 #include <sys/sysmacros.h>
41 #include <sys/machsystm.h>
42 #include <sys/machparam.h>
43 #include <sys/modctl.h>
44 #include <sys/atomic.h>
45 #include <sys/fhc.h>
46 #include <sys/ac.h>
47 #include <sys/jtag.h>
48 #include <sys/cpu_module.h>
175 return (EFAULT); /* !broken user app */
176 }
177 mutex_exit(&test_mutex);
178 fhc_bdlist_unlock();
179 AC_ERR_SET(pkt, AC_ERR_MEM_BK);
180 return (EBUSY); /* signal bank in use */
181 }
182
183 /*
184 * at this point, we have an available bank to test.
185 * create a test buffer
186 */
187 test = kmem_zalloc(sizeof (struct test_info), KM_SLEEP);
188 test->va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
189
190 /* fill in all the test info details now */
191 test->mem_info = mem_info;
192 test->board = softsp->board;
193 test->bank = pkt->bank;
194 test->bufp = kmem_alloc(TEST_PAGESIZE, KM_SLEEP);
195 test->info.handle = atomic_add_32_nv(&mem_test_sequence_id, 1);
196 (void) drv_getparm(PPID, (ulong_t *)(&(test->info.tester_pid)));
197 test->info.prev_condition = mem_info->condition;
198 test->info.page_size = TEST_PAGESIZE;
199 /* If Blackbird ever gets a variable line size, this will change. */
200 test->info.line_size = cpunodes[CPU->cpu_id].ecache_linesize;
201 decode = (pkt->bank == Bank0) ?
202 *softsp->ac_memdecode0 : *softsp->ac_memdecode1;
203 test->info.afar_base = GRP_REALBASE(decode);
204 test->info.bank_size = GRP_UK2SPAN(decode);
205
206 /* return the information to the user */
207 if (ddi_copyout(&test->info, pkt->cmd_cfga.private,
208 sizeof (ac_mem_test_start_t), flag) != 0) {
209
210 /* oh well, tear down the test now */
211 kmem_free(test->bufp, TEST_PAGESIZE);
212 vmem_free(heap_arena, test->va, PAGESIZE);
213 kmem_free(test, sizeof (struct test_info));
214
215 fhc_bdlist_unlock();
387 }
388 #else /* _MULTI_DATAMODEL */
389 if (ddi_copyin(pkt->cmd_cfga.private, &t_read,
390 sizeof (ac_mem_test_read_t), flag) != 0)
391 return (EFAULT);
392 #endif /* _MULTI_DATAMODEL */
393
394 /* verify the handle */
395 mutex_enter(&test_mutex);
396 for (test = test_base; test != NULL; test = test->next) {
397 if (test->info.handle == t_read.handle)
398 break;
399 }
400 if (test == NULL) {
401 mutex_exit(&test_mutex);
402 AC_ERR_SET(pkt, AC_ERR_MEM_TEST);
403 return (EINVAL);
404 }
405
406 /* bump the busy bit */
407 atomic_add_32(&test->in_test, 1);
408 mutex_exit(&test_mutex);
409
410 /* verify the remaining parameters */
411 if ((t_read.address.page_num >=
412 test->info.bank_size / test->info.page_size) ||
413 (t_read.address.line_count == 0) ||
414 (t_read.address.line_count >
415 test->info.page_size / test->info.line_size) ||
416 (t_read.address.line_offset >=
417 test->info.page_size / test->info.line_size) ||
418 ((t_read.address.line_offset + t_read.address.line_count) >
419 test->info.page_size / test->info.line_size)) {
420 AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
421 retval = EINVAL;
422 goto read_done;
423 }
424
425 page_offset = t_read.address.line_offset * test->info.line_size;
426 page_pa = test->info.afar_base +
427 t_read.address.page_num * test->info.page_size;
481 * If there was a data error, attempt to return the error_buf
482 * to the user.
483 */
484 if (error_found) {
485 if (ddi_copyout(&error_buf, t_read.error_buf,
486 sizeof (sunfire_processor_error_regs_t), flag) != 0) {
487 retval = EFAULT;
488 /* Keep going */
489 }
490 }
491
492 /*
493 * Then, return the page to the user (always)
494 */
495 if (ddi_copyout(dst_va, (caddr_t)(t_read.page_buf) + page_offset,
496 t_read.address.line_count * test->info.line_size, flag) != 0) {
497 retval = EFAULT;
498 }
499
500 read_done:
501 atomic_add_32(&test->in_test, -1);
502 return (retval);
503 }
504
505 int
506 ac_mem_test_write(ac_cfga_pkt_t *pkt, int flag)
507 {
508 struct test_info *test;
509 uint_t page_offset;
510 uint64_t page_pa;
511 uint_t pstate_save;
512 caddr_t src_va, dst_va;
513 int retval = DDI_SUCCESS;
514 ac_mem_test_write_t t_write;
515
516 #ifdef _MULTI_DATAMODEL
517 switch (ddi_model_convert_from(flag & FMODELS)) {
518 case DDI_MODEL_ILP32: {
519 ac_mem_test_write32_t t_write32;
520
521 if (ddi_copyin(pkt->cmd_cfga.private, &t_write32,
533 break;
534 }
535 #else /* _MULTI_DATAMODEL */
536 if (ddi_copyin(pkt->cmd_cfga.private, &t_write,
537 sizeof (ac_mem_test_write_t), flag) != 0)
538 return (EFAULT);
539 #endif /* _MULTI_DATAMODEL */
540
541 /* verify the handle */
542 mutex_enter(&test_mutex);
543 for (test = test_base; test != NULL; test = test->next) {
544 if (test->info.handle == t_write.handle)
545 break;
546 }
547 if (test == NULL) {
548 mutex_exit(&test_mutex);
549 return (EINVAL);
550 }
551
552 /* bump the busy bit */
553 atomic_add_32(&test->in_test, 1);
554 mutex_exit(&test_mutex);
555
556 /* verify the remaining parameters */
557 if ((t_write.address.page_num >=
558 test->info.bank_size / test->info.page_size) ||
559 (t_write.address.line_count == 0) ||
560 (t_write.address.line_count >
561 test->info.page_size / test->info.line_size) ||
562 (t_write.address.line_offset >=
563 test->info.page_size / test->info.line_size) ||
564 ((t_write.address.line_offset + t_write.address.line_count) >
565 test->info.page_size / test->info.line_size)) {
566 AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
567 retval = EINVAL;
568 goto write_done;
569 }
570
571 page_offset = t_write.address.line_offset * test->info.line_size;
572 page_pa = test->info.afar_base +
573 t_write.address.page_num * test->info.page_size;
585 kpreempt_disable();
586
587 /* we need a va for the block instructions */
588 ac_mapin(page_pa, test->va);
589
590 pstate_save = disable_vec_intr();
591
592 /* copy the data again (using our very special copy) */
593 ac_blkcopy(src_va, dst_va, t_write.address.line_count,
594 test->info.line_size);
595
596 enable_vec_intr(pstate_save);
597
598 /* tear down translation (who needs an mmu) */
599 ac_unmap(test->va);
600
601 /* we're back! */
602 kpreempt_enable();
603
604 write_done:
605 atomic_add_32(&test->in_test, -1);
606 return (retval);
607 }
|
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 /*
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/types.h>
28 #include <sys/conf.h>
29 #include <sys/ddi.h>
30 #include <sys/sunddi.h>
31 #include <sys/ddi_impldefs.h>
32 #include <sys/obpdefs.h>
33 #include <sys/cmn_err.h>
34 #include <sys/errno.h>
35 #include <sys/kmem.h>
36 #include <sys/vmem.h>
37 #include <sys/debug.h>
38 #include <sys/sysmacros.h>
39 #include <sys/machsystm.h>
40 #include <sys/machparam.h>
41 #include <sys/modctl.h>
42 #include <sys/atomic.h>
43 #include <sys/fhc.h>
44 #include <sys/ac.h>
45 #include <sys/jtag.h>
46 #include <sys/cpu_module.h>
173 return (EFAULT); /* !broken user app */
174 }
175 mutex_exit(&test_mutex);
176 fhc_bdlist_unlock();
177 AC_ERR_SET(pkt, AC_ERR_MEM_BK);
178 return (EBUSY); /* signal bank in use */
179 }
180
181 /*
182 * at this point, we have an available bank to test.
183 * create a test buffer
184 */
185 test = kmem_zalloc(sizeof (struct test_info), KM_SLEEP);
186 test->va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
187
188 /* fill in all the test info details now */
189 test->mem_info = mem_info;
190 test->board = softsp->board;
191 test->bank = pkt->bank;
192 test->bufp = kmem_alloc(TEST_PAGESIZE, KM_SLEEP);
193 test->info.handle = atomic_inc_32_nv(&mem_test_sequence_id);
194 (void) drv_getparm(PPID, (ulong_t *)(&(test->info.tester_pid)));
195 test->info.prev_condition = mem_info->condition;
196 test->info.page_size = TEST_PAGESIZE;
197 /* If Blackbird ever gets a variable line size, this will change. */
198 test->info.line_size = cpunodes[CPU->cpu_id].ecache_linesize;
199 decode = (pkt->bank == Bank0) ?
200 *softsp->ac_memdecode0 : *softsp->ac_memdecode1;
201 test->info.afar_base = GRP_REALBASE(decode);
202 test->info.bank_size = GRP_UK2SPAN(decode);
203
204 /* return the information to the user */
205 if (ddi_copyout(&test->info, pkt->cmd_cfga.private,
206 sizeof (ac_mem_test_start_t), flag) != 0) {
207
208 /* oh well, tear down the test now */
209 kmem_free(test->bufp, TEST_PAGESIZE);
210 vmem_free(heap_arena, test->va, PAGESIZE);
211 kmem_free(test, sizeof (struct test_info));
212
213 fhc_bdlist_unlock();
385 }
386 #else /* _MULTI_DATAMODEL */
387 if (ddi_copyin(pkt->cmd_cfga.private, &t_read,
388 sizeof (ac_mem_test_read_t), flag) != 0)
389 return (EFAULT);
390 #endif /* _MULTI_DATAMODEL */
391
392 /* verify the handle */
393 mutex_enter(&test_mutex);
394 for (test = test_base; test != NULL; test = test->next) {
395 if (test->info.handle == t_read.handle)
396 break;
397 }
398 if (test == NULL) {
399 mutex_exit(&test_mutex);
400 AC_ERR_SET(pkt, AC_ERR_MEM_TEST);
401 return (EINVAL);
402 }
403
404 /* bump the busy bit */
405 atomic_inc_32(&test->in_test);
406 mutex_exit(&test_mutex);
407
408 /* verify the remaining parameters */
409 if ((t_read.address.page_num >=
410 test->info.bank_size / test->info.page_size) ||
411 (t_read.address.line_count == 0) ||
412 (t_read.address.line_count >
413 test->info.page_size / test->info.line_size) ||
414 (t_read.address.line_offset >=
415 test->info.page_size / test->info.line_size) ||
416 ((t_read.address.line_offset + t_read.address.line_count) >
417 test->info.page_size / test->info.line_size)) {
418 AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
419 retval = EINVAL;
420 goto read_done;
421 }
422
423 page_offset = t_read.address.line_offset * test->info.line_size;
424 page_pa = test->info.afar_base +
425 t_read.address.page_num * test->info.page_size;
479 * If there was a data error, attempt to return the error_buf
480 * to the user.
481 */
482 if (error_found) {
483 if (ddi_copyout(&error_buf, t_read.error_buf,
484 sizeof (sunfire_processor_error_regs_t), flag) != 0) {
485 retval = EFAULT;
486 /* Keep going */
487 }
488 }
489
490 /*
491 * Then, return the page to the user (always)
492 */
493 if (ddi_copyout(dst_va, (caddr_t)(t_read.page_buf) + page_offset,
494 t_read.address.line_count * test->info.line_size, flag) != 0) {
495 retval = EFAULT;
496 }
497
498 read_done:
499 atomic_dec_32(&test->in_test);
500 return (retval);
501 }
502
503 int
504 ac_mem_test_write(ac_cfga_pkt_t *pkt, int flag)
505 {
506 struct test_info *test;
507 uint_t page_offset;
508 uint64_t page_pa;
509 uint_t pstate_save;
510 caddr_t src_va, dst_va;
511 int retval = DDI_SUCCESS;
512 ac_mem_test_write_t t_write;
513
514 #ifdef _MULTI_DATAMODEL
515 switch (ddi_model_convert_from(flag & FMODELS)) {
516 case DDI_MODEL_ILP32: {
517 ac_mem_test_write32_t t_write32;
518
519 if (ddi_copyin(pkt->cmd_cfga.private, &t_write32,
531 break;
532 }
533 #else /* _MULTI_DATAMODEL */
534 if (ddi_copyin(pkt->cmd_cfga.private, &t_write,
535 sizeof (ac_mem_test_write_t), flag) != 0)
536 return (EFAULT);
537 #endif /* _MULTI_DATAMODEL */
538
539 /* verify the handle */
540 mutex_enter(&test_mutex);
541 for (test = test_base; test != NULL; test = test->next) {
542 if (test->info.handle == t_write.handle)
543 break;
544 }
545 if (test == NULL) {
546 mutex_exit(&test_mutex);
547 return (EINVAL);
548 }
549
550 /* bump the busy bit */
551 atomic_inc_32(&test->in_test);
552 mutex_exit(&test_mutex);
553
554 /* verify the remaining parameters */
555 if ((t_write.address.page_num >=
556 test->info.bank_size / test->info.page_size) ||
557 (t_write.address.line_count == 0) ||
558 (t_write.address.line_count >
559 test->info.page_size / test->info.line_size) ||
560 (t_write.address.line_offset >=
561 test->info.page_size / test->info.line_size) ||
562 ((t_write.address.line_offset + t_write.address.line_count) >
563 test->info.page_size / test->info.line_size)) {
564 AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
565 retval = EINVAL;
566 goto write_done;
567 }
568
569 page_offset = t_write.address.line_offset * test->info.line_size;
570 page_pa = test->info.afar_base +
571 t_write.address.page_num * test->info.page_size;
583 kpreempt_disable();
584
585 /* we need a va for the block instructions */
586 ac_mapin(page_pa, test->va);
587
588 pstate_save = disable_vec_intr();
589
590 /* copy the data again (using our very special copy) */
591 ac_blkcopy(src_va, dst_va, t_write.address.line_count,
592 test->info.line_size);
593
594 enable_vec_intr(pstate_save);
595
596 /* tear down translation (who needs an mmu) */
597 ac_unmap(test->va);
598
599 /* we're back! */
600 kpreempt_enable();
601
602 write_done:
603 atomic_dec_32(&test->in_test);
604 return (retval);
605 }
|