29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * CDDL HEADER START
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * The contents of this file are subject to the terms of the
29949e866e40b95795203f3ee46f44a197c946e4stevel * Common Development and Distribution License (the "License").
29949e866e40b95795203f3ee46f44a197c946e4stevel * You may not use this file except in compliance with the License.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
29949e866e40b95795203f3ee46f44a197c946e4stevel * or http://www.opensolaris.org/os/licensing.
29949e866e40b95795203f3ee46f44a197c946e4stevel * See the License for the specific language governing permissions
29949e866e40b95795203f3ee46f44a197c946e4stevel * and limitations under the License.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * When distributing Covered Code, include this CDDL HEADER in each
29949e866e40b95795203f3ee46f44a197c946e4stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
29949e866e40b95795203f3ee46f44a197c946e4stevel * If applicable, add the following below this CDDL HEADER, with the
29949e866e40b95795203f3ee46f44a197c946e4stevel * fields enclosed by brackets "[]" replaced with your own identifying
29949e866e40b95795203f3ee46f44a197c946e4stevel * information: Portions Copyright [yyyy] [name of copyright owner]
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * CDDL HEADER END
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Use is subject to license terms.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/types.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/conf.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ddi.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/sunddi.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ddi_impldefs.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/obpdefs.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/cmn_err.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/errno.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/kmem.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/vmem.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/debug.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/sysmacros.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/machsystm.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/machparam.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/modctl.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/atomic.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/fhc.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ac.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/jtag.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/cpu_module.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/spitregs.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/vm.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <vm/seg_kmem.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <vm/hat_sfmmu.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* memory setup parameters */
29949e866e40b95795203f3ee46f44a197c946e4stevel#define TEST_PAGESIZE MMU_PAGESIZE
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstruct test_info {
29949e866e40b95795203f3ee46f44a197c946e4stevel struct test_info *next; /* linked list of tests */
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_mem_info *mem_info;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t board;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t bank;
29949e866e40b95795203f3ee46f44a197c946e4stevel caddr_t bufp; /* pointer to buffer page */
29949e866e40b95795203f3ee46f44a197c946e4stevel caddr_t va; /* test target VA */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_mem_test_start_t info;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t in_test; /* count of threads in test */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* list of tests in progress (list protected test_mutex) */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct test_info *test_base = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic kmutex_t test_mutex;
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int test_mutex_initialized = FALSE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic mem_test_handle_t mem_test_sequence_id = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelac_mapin(uint64_t pa, caddr_t va)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel pfn_t pfn;
29949e866e40b95795203f3ee46f44a197c946e4stevel tte_t tte;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel pfn = pa >> MMU_PAGESHIFT;
29949e866e40b95795203f3ee46f44a197c946e4stevel tte.tte_inthi = TTE_VALID_INT | TTE_SZ_INT(TTE8K) |
29949e866e40b95795203f3ee46f44a197c946e4stevel TTE_PFN_INTHI(pfn);
29949e866e40b95795203f3ee46f44a197c946e4stevel tte.tte_intlo = TTE_PFN_INTLO(pfn) | TTE_CP_INT |
29949e866e40b95795203f3ee46f44a197c946e4stevel TTE_PRIV_INT | TTE_LCK_INT | TTE_HWWR_INT;
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah sfmmu_dtlb_ld_kva(va, &tte);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelac_unmap(caddr_t va)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah vtag_flushpage(va, (uint64_t)ksfmmup);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevelac_mem_test_start(ac_cfga_pkt_t *pkt, int flag)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_mem_info *mem_info;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct bd_list *board;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct test_info *test;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t decode;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* XXX if ac ever detaches... */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (test_mutex_initialized == FALSE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_init(&test_mutex, NULL, MUTEX_DEFAULT, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel test_mutex_initialized = TRUE;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Is the specified bank testable?
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel board = fhc_bdlist_lock(pkt->softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (board == NULL || board->ac_softsp == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_BD);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(pkt->softsp == board->ac_softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* verify the board is of the correct type */
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (board->sc.type) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case CPU_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case MEM_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_BD_TYPE);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Memory must be in the spare state to be testable.
29949e866e40b95795203f3ee46f44a197c946e4stevel * However, spare memory that is testing can't be tested
29949e866e40b95795203f3ee46f44a197c946e4stevel * again, instead return the current test info.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = pkt->softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info = &softsp->bank[pkt->bank];
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!MEM_BOARD_VISIBLE(board) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_busy(softsp->board) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info->rstate != SYSC_CFGA_RSTATE_CONNECTED ||
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info->ostate != SYSC_CFGA_OSTATE_UNCONFIGURED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_BD_STATE);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (mem_info->busy) { /* oops, testing? */
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * find the test entry
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(test_mutex_initialized);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel for (test = test_base; test != NULL; test = test->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (test->board == softsp->board &&
29949e866e40b95795203f3ee46f44a197c946e4stevel test->bank == pkt->bank)
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (test == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Not busy testing. */
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_BD_STATE);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * return the current test information to the new caller
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyout(&test->info, pkt->cmd_cfga.private,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (ac_mem_test_start_t), flag) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT); /* !broken user app */
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_MEM_BK);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EBUSY); /* signal bank in use */
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * at this point, we have an available bank to test.
29949e866e40b95795203f3ee46f44a197c946e4stevel * create a test buffer
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel test = kmem_zalloc(sizeof (struct test_info), KM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel test->va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* fill in all the test info details now */
29949e866e40b95795203f3ee46f44a197c946e4stevel test->mem_info = mem_info;
29949e866e40b95795203f3ee46f44a197c946e4stevel test->board = softsp->board;
29949e866e40b95795203f3ee46f44a197c946e4stevel test->bank = pkt->bank;
29949e866e40b95795203f3ee46f44a197c946e4stevel test->bufp = kmem_alloc(TEST_PAGESIZE, KM_SLEEP);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek test->info.handle = atomic_inc_32_nv(&mem_test_sequence_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) drv_getparm(PPID, (ulong_t *)(&(test->info.tester_pid)));
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.prev_condition = mem_info->condition;
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.page_size = TEST_PAGESIZE;
29949e866e40b95795203f3ee46f44a197c946e4stevel /* If Blackbird ever gets a variable line size, this will change. */
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.line_size = cpunodes[CPU->cpu_id].ecache_linesize;
29949e866e40b95795203f3ee46f44a197c946e4stevel decode = (pkt->bank == Bank0) ?
29949e866e40b95795203f3ee46f44a197c946e4stevel *softsp->ac_memdecode0 : *softsp->ac_memdecode1;
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.afar_base = GRP_REALBASE(decode);
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.bank_size = GRP_UK2SPAN(decode);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* return the information to the user */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyout(&test->info, pkt->cmd_cfga.private,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (ac_mem_test_start_t), flag) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* oh well, tear down the test now */
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(test->bufp, TEST_PAGESIZE);
29949e866e40b95795203f3ee46f44a197c946e4stevel vmem_free(heap_arena, test->va, PAGESIZE);
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(test, sizeof (struct test_info));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info->busy = TRUE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* finally link us into the test database */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel test->next = test_base;
29949e866e40b95795203f3ee46f44a197c946e4stevel test_base = test;
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "!memtest: start test[%u]: board %d, bank %d",
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.handle, test->board, test->bank);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG */
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevelac_mem_test_stop(ac_cfga_pkt_t *pkt, int flag)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct test_info *test, **prev;
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_mem_test_stop_t stop;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get test result information */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyin(pkt->cmd_cfga.private, &stop,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (ac_mem_test_stop_t), flag) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* bdlist protects all state changes... */
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) fhc_bdlist_lock(-1);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* find the test */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel prev = &test_base;
29949e866e40b95795203f3ee46f44a197c946e4stevel for (test = test_base; test != NULL; test = test->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (test->info.handle == stop.handle)
29949e866e40b95795203f3ee46f44a197c946e4stevel break; /* found the test */
29949e866e40b95795203f3ee46f44a197c946e4stevel prev = &test->next;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (test == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_MEM_TEST);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE,
29949e866e40b95795203f3ee46f44a197c946e4stevel "!memtest: stop test[%u]: board %d, bank %d,"
29949e866e40b95795203f3ee46f44a197c946e4stevel " condition %d",
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.handle, test->board,
29949e866e40b95795203f3ee46f44a197c946e4stevel test->bank, stop.condition);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* first unlink us from the test list (to allow no more entries) */
29949e866e40b95795203f3ee46f44a197c946e4stevel *prev = test->next;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* then, wait for current tests to complete */
29949e866e40b95795203f3ee46f44a197c946e4stevel while (test->in_test != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel delay(1);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* clean up the test related allocations */
29949e866e40b95795203f3ee46f44a197c946e4stevel vmem_free(heap_arena, test->va, PAGESIZE);
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(test->bufp, TEST_PAGESIZE);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* update the bank condition accordingly */
29949e866e40b95795203f3ee46f44a197c946e4stevel test->mem_info->condition = stop.condition;
29949e866e40b95795203f3ee46f44a197c946e4stevel test->mem_info->status_change = ddi_get_time();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel test->mem_info->busy = FALSE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* finally, delete the test element */
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(test, sizeof (struct test_info));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelac_mem_test_stop_on_close(uint_t board, uint_t bank)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct test_info *test, **prev;
29949e866e40b95795203f3ee46f44a197c946e4stevel sysc_cfga_cond_t condition = SYSC_CFGA_COND_UNKNOWN;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* bdlist protects all state changes... */
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) fhc_bdlist_lock(-1);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* find the test */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel prev = &test_base;
29949e866e40b95795203f3ee46f44a197c946e4stevel for (test = test_base; test != NULL; test = test->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (test->board == board && test->bank == bank)
29949e866e40b95795203f3ee46f44a197c946e4stevel break; /* found the test */
29949e866e40b95795203f3ee46f44a197c946e4stevel prev = &test->next;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (test == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* No test running, nothing to do. */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel return;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "!memtest: stop test[%u] on close: "
29949e866e40b95795203f3ee46f44a197c946e4stevel "board %d, bank %d, condition %d", test->info.handle,
29949e866e40b95795203f3ee46f44a197c946e4stevel test->board, test->bank, condition);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* first unlink us from the test list (to allow no more entries) */
29949e866e40b95795203f3ee46f44a197c946e4stevel *prev = test->next;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(test->in_test == 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* clean up the test related allocations */
29949e866e40b95795203f3ee46f44a197c946e4stevel vmem_free(heap_arena, test->va, PAGESIZE);
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(test->bufp, TEST_PAGESIZE);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* update the bank condition accordingly */
29949e866e40b95795203f3ee46f44a197c946e4stevel test->mem_info->condition = condition;
29949e866e40b95795203f3ee46f44a197c946e4stevel test->mem_info->status_change = ddi_get_time();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel test->mem_info->busy = FALSE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* finally, delete the test element */
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(test, sizeof (struct test_info));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevelac_mem_test_read(ac_cfga_pkt_t *pkt, int flag)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct test_info *test;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t page_offset;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t page_pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t pstate_save;
29949e866e40b95795203f3ee46f44a197c946e4stevel caddr_t src_va, dst_va;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t orig_err;
29949e866e40b95795203f3ee46f44a197c946e4stevel int retval = DDI_SUCCESS;
29949e866e40b95795203f3ee46f44a197c946e4stevel sunfire_processor_error_regs_t error_buf;
29949e866e40b95795203f3ee46f44a197c946e4stevel int error_found;
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_mem_test_read_t t_read;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef _MULTI_DATAMODEL
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (ddi_model_convert_from(flag & FMODELS)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_MODEL_ILP32: {
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_mem_test_read32_t t_read32;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyin(pkt->cmd_cfga.private, &t_read32,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (ac_mem_test_read32_t), flag) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel t_read.handle = t_read32.handle;
29949e866e40b95795203f3ee46f44a197c946e4stevel t_read.page_buf = (void *)(uintptr_t)t_read32.page_buf;
29949e866e40b95795203f3ee46f44a197c946e4stevel t_read.address = t_read32.address;
29949e866e40b95795203f3ee46f44a197c946e4stevel t_read.error_buf = (sunfire_processor_error_regs_t *)
29949e866e40b95795203f3ee46f44a197c946e4stevel (uintptr_t)t_read32.error_buf;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_MODEL_NONE:
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyin(pkt->cmd_cfga.private, &t_read,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (ac_mem_test_read_t), flag) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel#else /* _MULTI_DATAMODEL */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyin(pkt->cmd_cfga.private, &t_read,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (ac_mem_test_read_t), flag) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* _MULTI_DATAMODEL */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* verify the handle */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel for (test = test_base; test != NULL; test = test->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (test->info.handle == t_read.handle)
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (test == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_MEM_TEST);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* bump the busy bit */
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&test->in_test);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* verify the remaining parameters */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((t_read.address.page_num >=
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.bank_size / test->info.page_size) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel (t_read.address.line_count == 0) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel (t_read.address.line_count >
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.page_size / test->info.line_size) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel (t_read.address.line_offset >=
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.page_size / test->info.line_size) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel ((t_read.address.line_offset + t_read.address.line_count) >
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.page_size / test->info.line_size)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EINVAL;
29949e866e40b95795203f3ee46f44a197c946e4stevel goto read_done;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel page_offset = t_read.address.line_offset * test->info.line_size;
29949e866e40b95795203f3ee46f44a197c946e4stevel page_pa = test->info.afar_base +
29949e866e40b95795203f3ee46f44a197c946e4stevel t_read.address.page_num * test->info.page_size;
29949e866e40b95795203f3ee46f44a197c946e4stevel dst_va = test->bufp + page_offset;
29949e866e40b95795203f3ee46f44a197c946e4stevel src_va = test->va + page_offset;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* time to go quiet */
29949e866e40b95795203f3ee46f44a197c946e4stevel kpreempt_disable();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* we need a va for the block instructions */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_mapin(page_pa, test->va);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel pstate_save = disable_vec_intr();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* disable errors */
29949e866e40b95795203f3ee46f44a197c946e4stevel orig_err = get_error_enable();
29949e866e40b95795203f3ee46f44a197c946e4stevel set_error_enable(orig_err & ~(EER_CEEN | EER_NCEEN));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* copy the data again (using our very special copy) */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_blkcopy(src_va, dst_va, t_read.address.line_count,
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.line_size);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* process errors (if any) */
29949e866e40b95795203f3ee46f44a197c946e4stevel error_buf.module_id = CPU->cpu_id;
29949e866e40b95795203f3ee46f44a197c946e4stevel get_asyncflt(&(error_buf.afsr));
29949e866e40b95795203f3ee46f44a197c946e4stevel get_asyncaddr(&(error_buf.afar));
29949e866e40b95795203f3ee46f44a197c946e4stevel get_udb_errors(&(error_buf.udbh_error_reg),
29949e866e40b95795203f3ee46f44a197c946e4stevel &(error_buf.udbl_error_reg));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * clean up after our no-error copy but before enabling ints.
29949e866e40b95795203f3ee46f44a197c946e4stevel * XXX what to do about other error types?
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (error_buf.afsr & (P_AFSR_CE | P_AFSR_UE)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel extern void clr_datapath(void); /* XXX */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel clr_datapath();
29949e866e40b95795203f3ee46f44a197c946e4stevel set_asyncflt(error_buf.afsr);
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EIO;
29949e866e40b95795203f3ee46f44a197c946e4stevel error_found = TRUE;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel error_found = FALSE;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* errors back on */
29949e866e40b95795203f3ee46f44a197c946e4stevel set_error_enable(orig_err);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel enable_vec_intr(pstate_save);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* tear down translation (who needs an mmu) */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_unmap(test->va);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* we're back! */
29949e866e40b95795203f3ee46f44a197c946e4stevel kpreempt_enable();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If there was a data error, attempt to return the error_buf
29949e866e40b95795203f3ee46f44a197c946e4stevel * to the user.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (error_found) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyout(&error_buf, t_read.error_buf,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (sunfire_processor_error_regs_t), flag) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EFAULT;
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Keep going */
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Then, return the page to the user (always)
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyout(dst_va, (caddr_t)(t_read.page_buf) + page_offset,
29949e866e40b95795203f3ee46f44a197c946e4stevel t_read.address.line_count * test->info.line_size, flag) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EFAULT;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelread_done:
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_32(&test->in_test);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (retval);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevelac_mem_test_write(ac_cfga_pkt_t *pkt, int flag)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct test_info *test;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t page_offset;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t page_pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t pstate_save;
29949e866e40b95795203f3ee46f44a197c946e4stevel caddr_t src_va, dst_va;
29949e866e40b95795203f3ee46f44a197c946e4stevel int retval = DDI_SUCCESS;
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_mem_test_write_t t_write;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef _MULTI_DATAMODEL
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (ddi_model_convert_from(flag & FMODELS)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_MODEL_ILP32: {
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_mem_test_write32_t t_write32;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyin(pkt->cmd_cfga.private, &t_write32,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (ac_mem_test_write32_t), flag) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel t_write.handle = t_write32.handle;
29949e866e40b95795203f3ee46f44a197c946e4stevel t_write.page_buf = (void *)(uintptr_t)t_write32.page_buf;
29949e866e40b95795203f3ee46f44a197c946e4stevel t_write.address = t_write32.address;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_MODEL_NONE:
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyin(pkt->cmd_cfga.private, &t_write,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (ac_mem_test_write_t), flag) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel#else /* _MULTI_DATAMODEL */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyin(pkt->cmd_cfga.private, &t_write,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (ac_mem_test_write_t), flag) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* _MULTI_DATAMODEL */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* verify the handle */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel for (test = test_base; test != NULL; test = test->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (test->info.handle == t_write.handle)
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (test == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* bump the busy bit */
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&test->in_test);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&test_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* verify the remaining parameters */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((t_write.address.page_num >=
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.bank_size / test->info.page_size) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel (t_write.address.line_count == 0) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel (t_write.address.line_count >
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.page_size / test->info.line_size) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel (t_write.address.line_offset >=
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.page_size / test->info.line_size) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel ((t_write.address.line_offset + t_write.address.line_count) >
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.page_size / test->info.line_size)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EINVAL;
29949e866e40b95795203f3ee46f44a197c946e4stevel goto write_done;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel page_offset = t_write.address.line_offset * test->info.line_size;
29949e866e40b95795203f3ee46f44a197c946e4stevel page_pa = test->info.afar_base +
29949e866e40b95795203f3ee46f44a197c946e4stevel t_write.address.page_num * test->info.page_size;
29949e866e40b95795203f3ee46f44a197c946e4stevel src_va = test->bufp + page_offset;
29949e866e40b95795203f3ee46f44a197c946e4stevel dst_va = test->va + page_offset;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* copy in the specified user data */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyin((caddr_t)(t_write.page_buf) + page_offset, src_va,
29949e866e40b95795203f3ee46f44a197c946e4stevel t_write.address.line_count * test->info.line_size, flag) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EFAULT;
29949e866e40b95795203f3ee46f44a197c946e4stevel goto write_done;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* time to go quiet */
29949e866e40b95795203f3ee46f44a197c946e4stevel kpreempt_disable();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* we need a va for the block instructions */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_mapin(page_pa, test->va);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel pstate_save = disable_vec_intr();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* copy the data again (using our very special copy) */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_blkcopy(src_va, dst_va, t_write.address.line_count,
29949e866e40b95795203f3ee46f44a197c946e4stevel test->info.line_size);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel enable_vec_intr(pstate_save);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* tear down translation (who needs an mmu) */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_unmap(test->va);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* we're back! */
29949e866e40b95795203f3ee46f44a197c946e4stevel kpreempt_enable();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelwrite_done:
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_32(&test->in_test);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (retval);
29949e866e40b95795203f3ee46f44a197c946e4stevel}