03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Common Development and Distribution License (the "License").
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or http://www.opensolaris.org/os/licensing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * memory management for serengeti dr memory
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/obpdefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cpuvar.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/memlist_impl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/machsystm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/promif.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/mem_cage.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/note.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/lgrp.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sbd_ioctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sbd.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sbdp_priv.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sbdp_mem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sun4asi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cheetahregs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cpu_module.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/esunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <vm/page.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sbdp_get_meminfo(pnode_t, int, uint64_t *, uint64_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelint mc_read_regs(pnode_t, mc_regs_t *);
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint64_t mc_get_addr(pnode_t, int, uint_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic pnode_t mc_get_sibling_cpu(pnode_t nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int mc_get_sibling_cpu_impl(pnode_t nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_cond_t mc_check_sibling_cpu(pnode_t nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void _sbdp_copy_rename_end(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sbdp_copy_rename__relocatable(sbdp_cr_handle_t *,
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *, sbdp_rename_script_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sbdp_prep_rename_script(sbdp_cr_handle_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sbdp_get_lowest_addr_in_node(pnode_t, uint64_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void bcopy32_il(uint64_t, uint64_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void flush_ecache_il(uint64_t physaddr, size_t size, size_t linesize);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern uint64_t lddphys_il(uint64_t physaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern uint64_t ldxasi_il(uint64_t physaddr, uint_t asi);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void sbdp_exec_script_il(sbdp_rename_script_t *rsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid sbdp_fill_bank_info(uint64_t, sbdp_bank_t **);
03831d35f7499c87d51205817c93e9a8d42c4baestevelint sbdp_add_nodes_banks(pnode_t node, sbdp_bank_t **banks);
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid sbdp_add_bank_to_seg(sbdp_bank_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid sbdp_remove_bank_from_seg(sbdp_bank_t *);
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint64_t sbdp_determine_slice(sbdp_handle_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_seg_t *sbdp_get_seg(uint64_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid sbdp_print_seg(sbdp_seg_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Head to the system segments link list
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_seg_t *sys_seg = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint64_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_determine_slice(sbdp_handle_t *hp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel size = sbdp_get_mem_size(hp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (size <= SG_SLICE_16G_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SG_SLICE_16G_SIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (size <= SG_SLICE_32G_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SG_SLICE_32G_SIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SG_SLICE_64G_SIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_get_mem_alignment(sbdp_handle_t *hp, dev_info_t *dip, uint64_t *align)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel *align = sbdp_determine_slice(hp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_memlist_dump(struct memlist *mlist)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register struct memlist *ml;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mlist == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("memlist> EMPTY\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = mlist; ml; ml = ml->ml_next)
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("memlist> 0x%" PRIx64", 0x%" PRIx64"\n",
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams ml->ml_address, ml->ml_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct mem_arg {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int ndips;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t **list;
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns mem dip held
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_get_mem_dip(pnode_t node, void *arg, uint_t flags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(flags))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mem_op_t mem = {0};
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct mem_arg *ap = arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (node == OBP_BADNODE || node == OBP_NONODE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mem.nodes = &nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mem.board = ap->board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mem.nmem = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sbdp_is_mem(node, &mem);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mem.nmem == 0 || mem.nmem == 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mem.nmem == 0 || nodeid != node)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip = e_ddi_nodeid_to_dip(nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(ap->ndips < SBDP_MAX_MEM_NODES_PER_BOARD);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ap->list[ap->ndips++] = dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct memlist *
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_get_memlist(sbdp_handle_t *hp, dev_info_t *dip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(dip))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, j, skip = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *list[SBDP_MAX_MEM_NODES_PER_BOARD];
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct mem_arg arg = {0};
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t base_pa, size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *mlist = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel list[0] = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel arg.board = hp->h_board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel arg.list = list;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_walk_prom_tree(prom_rootnode(), sbdp_get_mem_dip, &arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < arg.ndips; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (list[i] == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel size = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j < SBDP_MAX_MCS_PER_NODE; j++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_get_meminfo(ddi_get_nodeid(list[i]), j,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &size, &base_pa)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel skip++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (size == -1 || size == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) memlist_add_span(base_pa, size, &mlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Release hold acquired in sbdp_get_mem_dip()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_release_devi(list[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX - The following two lines are from existing code.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * However, this appears to be incorrect - this check should be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * made for each dip in list i.e within the for(i) loop.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (skip == SBDP_MAX_MCS_PER_NODE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, ESGT_INTERNAL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("memlist for board %d\n", hp->h_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_memlist_dump(mlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct memlist *
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_memlist_dup(struct memlist *mlist)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *hl, *prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mlist == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel hl = NULL;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (; mlist; mlist = mlist->ml_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = memlist_get_one();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hl != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel memlist_free_list(hl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel hl = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams mp->ml_address = mlist->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams mp->ml_size = mlist->ml_size;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams mp->ml_next = NULL;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams mp->ml_prev = prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prev == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel hl = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams prev->ml_next = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_del_memlist(sbdp_handle_t *hp, struct memlist *mlist)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(hp))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel memlist_free_list(mlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_flush_ecache(uint64_t a, uint64_t b)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_flush_ecache();
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef enum {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_CR_OK,
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_CR_MC_IDLE_ERR
03831d35f7499c87d51205817c93e9a8d42c4baestevel} sbdp_cr_err_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_move_memory(sbdp_handle_t *hp, int t_bd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bd_t *s_bdp, *t_bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t mempage;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ulong_t data_area, index_area;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ulong_t e_area, e_page;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int availlen, indexlen, funclen, scriptlen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *indexp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel time_t copytime;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*funcp)();
03831d35f7499c87d51205817c93e9a8d42c4baestevel size_t size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *mlist;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_sr_handle_t *srhp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_rename_script_t *rsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_rename_script_t *rsbuffer;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_cr_handle_t *cph;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int linesize;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t neer;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_cr_err_t cr_err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cph = kmem_zalloc(sizeof (sbdp_cr_handle_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("moving memory from memory board %d to board %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel hp->h_board, t_bd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_bdp = sbdp_get_bd_info(hp->h_wnode, hp->h_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_bdp = sbdp_get_bd_info(hp->h_wnode, t_bd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((s_bdp == NULL) || (t_bdp == NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, ESGT_INTERNAL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel funclen = (int)((ulong_t)_sbdp_copy_rename_end -
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (ulong_t)sbdp_copy_rename__relocatable);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (funclen > PAGESIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sbdp: copy-rename funclen (%d) > PAGESIZE (%d)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel funclen, PAGESIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, ESGT_INTERNAL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mempage will be page aligned, since we're calling
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kmem_alloc() with an exact multiple of PAGESIZE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mempage = kmem_alloc(PAGESIZE, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki SBDP_DBG_MEM("mempage = 0x%p\n", (void *)mempage);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copy the code for the copy-rename routine into
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a page aligned piece of memory. We do this to guarantee
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that we're executing within the same page and thus reduce
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the possibility of cache collisions between different
03831d35f7499c87d51205817c93e9a8d42c4baestevel * pages.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy((caddr_t)sbdp_copy_rename__relocatable, mempage, funclen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel funcp = (int (*)())mempage;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki SBDP_DBG_MEM("copy-rename funcp = 0x%p (len = 0x%x)\n", (void *)funcp,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki funclen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Prepare data page that will contain script of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * operations to perform during copy-rename.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate temporary buffer to hold script.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel size = sizeof (sbdp_rename_script_t) * SBDP_RENAME_MAXOP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsbuffer = kmem_zalloc(size, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cph->s_bdp = s_bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cph->t_bdp = t_bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cph->script = rsbuffer;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We need to make sure we don't switch cpus since we depend on the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * correct cpu processing
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_set(CPU_CURRENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scriptlen = sbdp_prep_rename_script(cph);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scriptlen <= 0) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cmn_err(CE_WARN, "sbdp failed to prep for copy-rename");
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, ESGT_INTERNAL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto cleanup;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("copy-rename script length = 0x%x\n", scriptlen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel indexlen = sizeof (*indexp) << 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((funclen + scriptlen + indexlen) > PAGESIZE) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cmn_err(CE_WARN, "sbdp: func len (%d) + script len (%d) "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "+ index len (%d) > PAGESIZE (%d)", funclen, scriptlen,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni indexlen, PAGESIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, ESGT_INTERNAL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto cleanup;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel linesize = cpunodes[CPU->cpu_id].ecache_linesize;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find aligned area within data page to maintain script.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel data_area = (ulong_t)mempage;
03831d35f7499c87d51205817c93e9a8d42c4baestevel data_area += (ulong_t)funclen + (ulong_t)(linesize - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel data_area &= ~((ulong_t)(linesize - 1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel availlen = PAGESIZE - indexlen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel availlen -= (int)(data_area - (ulong_t)mempage);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (availlen < scriptlen) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cmn_err(CE_WARN, "sbdp: available len (%d) < script len (%d)",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni availlen, scriptlen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, ESGT_INTERNAL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto cleanup;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("copy-rename script data area = 0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni data_area);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy((caddr_t)rsbuffer, (caddr_t)data_area, scriptlen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp = (sbdp_rename_script_t *)data_area;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni index_area = data_area + (ulong_t)scriptlen + (ulong_t)(linesize - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index_area &= ~((ulong_t)(linesize - 1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel indexp = (int *)index_area;
03831d35f7499c87d51205817c93e9a8d42c4baestevel indexp[0] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel indexp[1] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel e_area = index_area + (ulong_t)indexlen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel e_page = (ulong_t)mempage + PAGESIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (e_area > e_page) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "sbdp: index area size (%d) > available (%d)\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni indexlen, (int)(e_page - index_area));
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, ESGT_INTERNAL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto cleanup;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki SBDP_DBG_MEM("copy-rename index area = 0x%p\n", (void *)indexp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("cpu %d\n", CPU->cpu_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel srhp = sbdp_get_sr_handle();
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(srhp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel srhp->sr_flags = hp->h_flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni copytime = ddi_get_lbolt();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&s_bdp->bd_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mlist = sbdp_memlist_dup(s_bdp->ml);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&s_bdp->bd_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mlist == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("Didn't find memory list\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("src\n\tbd\t%d\n\tnode\t%d\n\tbpa 0x%lx\n\tnodes\t%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki s_bdp->bd, s_bdp->wnode, s_bdp->bpa, (void *)s_bdp->nodes);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_memlist_dump(s_bdp->ml);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("tgt\n\tbd\t%d\n\tnode\t%d\n\tbpa 0x%lx\n\tnodes\t%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki t_bdp->bd, t_bdp->wnode, t_bdp->bpa, (void *)t_bdp->nodes);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_memlist_dump(t_bdp->ml);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Quiesce the OS.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_suspend(srhp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *sep;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cmn_err(CE_WARN, "sbdp: failed to quiesce OS for copy-rename");
03831d35f7499c87d51205817c93e9a8d42c4baestevel sep = &srhp->sep;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, sep->e_code, sep->e_rsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_release_sr_handle(srhp);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sbdp_del_memlist(hp, mlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto cleanup;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * =================================
03831d35f7499c87d51205817c93e9a8d42c4baestevel * COPY-RENAME BEGIN.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * =================================
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("s_base 0x%lx t_base 0x%lx\n", cph->s_bdp->bpa,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cph->t_bdp->bpa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cph->ret = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("cph return 0x%lx\n", cph->ret);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("Flushing all of the cpu caches\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel xc_all(sbdp_flush_ecache, 0, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* disable CE reporting */
03831d35f7499c87d51205817c93e9a8d42c4baestevel neer = get_error_enable();
03831d35f7499c87d51205817c93e9a8d42c4baestevel set_error_enable(neer & ~EN_REG_CEEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr_err = (*funcp)(cph, mlist, rsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* enable CE reporting */
03831d35f7499c87d51205817c93e9a8d42c4baestevel set_error_enable(neer);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("s_base 0x%lx t_base 0x%lx\n", cph->s_bdp->bpa,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cph->t_bdp->bpa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("cph return 0x%lx\n", cph->ret);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("after execking the function\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * =================================
03831d35f7499c87d51205817c93e9a8d42c4baestevel * COPY-RENAME END.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * =================================
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("err is 0x%d\n", err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Resume the OS.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_resume(srhp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (srhp->sep.e_code) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *sep;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sbdp: failed to resume OS for copy-rename");
03831d35f7499c87d51205817c93e9a8d42c4baestevel sep = &srhp->sep;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, sep->e_code, sep->e_rsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni copytime = ddi_get_lbolt() - copytime;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_release_sr_handle(srhp);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sbdp_del_memlist(hp, mlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("copy-rename elapsed time = %ld ticks (%ld secs)\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni copytime, copytime / hz);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cr_err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SBDP_CR_OK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SBDP_CR_MC_IDLE_ERR: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t nodeid = cph->busy_mc->node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip = e_ddi_nodeid_to_dip(nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(dip != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_pathname(dip, path);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_release_devi(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to idle memory controller %s: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "copy-rename aborted", path);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(path, MAXPATHLEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, ESBD_MEMFAIL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, ESGT_INTERNAL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "unknown copy-rename error code (%d)", cr_err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto cleanup;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Rename memory for lgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Source and target board numbers are packaged in arg.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel lgrp_plat_config(LGRP_CONFIG_MEM_RENAME,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (uintptr_t)(s_bdp->bd | (t_bdp->bd << 16)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * swap list of banks
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_swap_list_of_banks(s_bdp, t_bdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Update the cached board info for both the source and the target
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_update_bd_info(s_bdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_update_bd_info(t_bdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Tell the sc that we have swapped slices.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_swap_slices(s_bdp->bd, t_bdp->bd) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* This is dangerous. The in use slice could be re-used! */
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("swaping slices failed\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelcleanup:
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(rsbuffer, size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(mempage, PAGESIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(cph, sizeof (sbdp_cr_handle_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_clear();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err ? -1 : 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_copy_regs(pnode_t node, uint64_t bpa, uint64_t new_base, int inval,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_rename_script_t *rsp, int *index)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, m;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_regs_t regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t *mc_decode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mc_read_regs(node, &regs)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("sbdp_copy_regs: failed to read source Decode "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Regs");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_decode = regs.mc_decode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel m = *index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SBDP_MAX_MCS_PER_NODE; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t offset, seg_pa, tmp_base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Skip invalid banks
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mc_decode[i] & SG_DECODE_VALID) != SG_DECODE_VALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp_base = new_base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!inval) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We need to calculate the offset from the base pa
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to add it appropriately to the new_base.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The offset needs to be in UM relative to the mc
03831d35f7499c87d51205817c93e9a8d42c4baestevel * decode register. Since we are going from physical
03831d35f7499c87d51205817c93e9a8d42c4baestevel * address to UM, we need to shift it by PHYS2UM_SHIFT.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To get it ready to OR it with the MC decode reg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we need to shift it left MC_UM_SHIFT
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel seg_pa = MC_BASE(mc_decode[i]) << PHYS2UM_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = (seg_pa - bpa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Convert tmp_base into a physical address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp_base = (tmp_base >> MC_UM_SHIFT) << PHYS2UM_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp_base += offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Convert tmp_base to be MC reg ready */
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp_base = (tmp_base >> PHYS2UM_SHIFT) << MC_UM_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_decode[i] &= ~SG_DECODE_UM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_decode[i] |= tmp_base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_decode[i] |= SG_DECODE_VALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Step 1: Write source base address to the MC
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with present bit off.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[m].masr_addr = mc_get_addr(node, i, &rsp[m].asi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[m].masr = mc_decode[i] & ~SG_DECODE_VALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel m++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Step 2: Now rewrite the mc reg with present bit on.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[m].masr_addr = rsp[m-1].masr_addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[m].masr = mc_decode[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[m].asi = rsp[m-1].asi;
03831d35f7499c87d51205817c93e9a8d42c4baestevel m++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *index = m;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_get_reg_addr(pnode_t nodeid, uint64_t *pa)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_regspace reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = prom_getproplen(nodeid, "reg");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != sizeof (mc_regspace))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_getprop(nodeid, "reg", (caddr_t)&reg) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(pa != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *pa = ((uint64_t)reg.regspec_addr_hi) << 32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *pa |= (uint64_t)reg.regspec_addr_lo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelmc_get_sibling_cpu_impl(pnode_t mc_node)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len, impl;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t cpu_node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char namebuf[OBP_MAXPROPNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_node = mc_get_sibling_cpu(mc_node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu_node == OBP_NONODE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("mc_get_sibling_cpu failed: dnode=0x%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = prom_getproplen(cpu_node, "name");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("invalid prom_getproplen for name prop: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "len=%d, dnode=0x%x\n", len, cpu_node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_getprop(cpu_node, "name", (caddr_t)namebuf) == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("failed to read name property for dnode=0x%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If this is a CMP node, the child has the implementation
03831d35f7499c87d51205817c93e9a8d42c4baestevel * property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(namebuf, "cmp") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_node = prom_childnode(cpu_node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(cpu_node != OBP_NONODE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_getprop(cpu_node, "implementation#", (caddr_t)&impl) == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("failed to read implementation# property for "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "dnode=0x%x\n", cpu_node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("mc_get_sibling_cpu_impl: found impl=0x%x, dnode=0x%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel impl, cpu_node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (impl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Provide EMU Activity Status register ASI and address. Only valid for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Panther processors.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelmc_get_idle_reg(pnode_t nodeid, uint64_t *addr, uint_t *asi)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t reg_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(nodeid != OBP_NONODE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mc_get_sibling_cpu_impl(nodeid) == PANTHER_IMPL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_getprop(nodeid, "portid", (caddr_t)&portid) < 0 ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel portid == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("mc_get_idle_reg: failed to read portid prop "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "for dnode=0x%x\n", nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_get_reg_addr(nodeid, &reg_pa) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("mc_get_idle_reg: failed to read reg prop "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "for dnode=0x%x\n", nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Local access will be via ASI 0x4a, otherwise via Safari PIO.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This assumes the copy-rename will later run on the same proc,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hence there is an assumption we are already bound.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(curthread->t_bound_cpu == CPU);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (SG_CPUID_TO_PORTID(CPU->cpu_id) == portid) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *addr = ASI_EMU_ACT_STATUS_VA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *asi = ASI_SAFARI_CONFIG;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *addr = MC_ACTIVITY_STATUS(reg_pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *asi = ASI_IO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If non-Panther board, add phys_banks entry for each physical bank.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If Panther board, add mc_idle_regs entry for each EMU Activity Status
03831d35f7499c87d51205817c93e9a8d42c4baestevel * register. Increment the array indices b_idx and r_idx for each entry
03831d35f7499c87d51205817c93e9a8d42c4baestevel * populated by this routine.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The caller is responsible for allocating sufficient array entries.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_prep_mc_idle_one(sbdp_bd_t *bp, sbdp_rename_script_t phys_banks[],
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *b_idx, sbdp_mc_idle_script_t mc_idle_regs[], int *r_idx)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, j;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t *memnodes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_regs_t regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t asi;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_cond_t sibling_cpu_cond;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int impl = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel memnodes = bp->nodes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SBDP_MAX_MEM_NODES_PER_BOARD; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (memnodes[i] == OBP_NONODE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* MC should not be accessed if cpu has failed */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sibling_cpu_cond = mc_check_sibling_cpu(memnodes[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sibling_cpu_cond == SBD_COND_FAILED ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel sibling_cpu_cond == SBD_COND_UNUSABLE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("sbdp: skipping MC with failed cpu: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "board=%d, mem node=%d, condition=%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->bd, i, sibling_cpu_cond);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize the board cpu type, assuming all board cpus are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the same type. This is true of all Cheetah-based processors.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Failure to read the cpu type is considered a fatal error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (impl == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel impl = mc_get_sibling_cpu_impl(memnodes[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (impl == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("sbdp: failed to get cpu impl "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "for MC dnode=0x%x\n", memnodes[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (impl) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CHEETAH_IMPL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CHEETAH_PLUS_IMPL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case JAGUAR_IMPL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mc_read_regs(memnodes[i], &regs)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("sbdp: failed to read source "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Decode Regs of board %d", bp->bd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j < SBDP_MAX_MCS_PER_NODE; j++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t mc_decode = regs.mc_decode[j];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mc_decode & SG_DECODE_VALID) !=
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_DECODE_VALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel addr = (MC_BASE(mc_decode) << PHYS2UM_SHIFT) |
03831d35f7499c87d51205817c93e9a8d42c4baestevel (MC_LM(mc_decode) << MC_LM_SHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_banks[*b_idx].masr_addr = addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_banks[*b_idx].masr = 0; /* unused */
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_banks[*b_idx].asi = ASI_MEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (*b_idx)++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PANTHER_IMPL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mc_get_idle_reg(memnodes[i], &addr, &asi)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_idle_regs[*r_idx].addr = addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_idle_regs[*r_idx].asi = asi;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_idle_regs[*r_idx].node = memnodes[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_idle_regs[*r_idx].bd_id = bp->bd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (*r_idx)++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Unknown cpu implementation=0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel impl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For non-Panther MCs that do not support read-bypass-write, we do a read
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to each physical bank, relying on the reads to block until all outstanding
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write requests have completed. This mechanism is referred to as the bus
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sync list and is used for Cheetah, Cheetah+, and Jaguar processors. The
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bus sync list PAs for the source and target are kept together and comprise
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Section 1 of the rename script.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For Panther processors that support the EMU Activity Status register,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we ensure the writes have completed by polling the MCU_ACT_STATUS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * field several times to make sure the MC queues are empty. The
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EMU Activity Status register PAs for the source and target are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kept together and comprise Section 2 of the rename script.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_prep_mc_idle_script(sbdp_bd_t *s_bp, sbdp_bd_t *t_bp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_rename_script_t *rsp, int *rsp_idx)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_rename_script_t *phys_banks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_mc_idle_script_t *mc_idle_regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int max_banks, max_regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel size_t bsize, msize;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int nbanks = 0, nregs = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* CONSTCOND */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(sizeof (sbdp_rename_script_t) ==
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (sbdp_mc_idle_script_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* allocate space for both source and target */
03831d35f7499c87d51205817c93e9a8d42c4baestevel max_banks = SBDP_MAX_MEM_NODES_PER_BOARD *
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_MAX_BANKS_PER_MC * 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel max_regs = SBDP_MAX_MEM_NODES_PER_BOARD * 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bsize = sizeof (sbdp_rename_script_t) * max_banks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msize = sizeof (sbdp_mc_idle_script_t) * max_regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_banks = kmem_zalloc(bsize, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_idle_regs = kmem_zalloc(msize, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_prep_mc_idle_one(t_bp, phys_banks, &nbanks,
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_idle_regs, &nregs) != 0 ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_prep_mc_idle_one(s_bp, phys_banks, &nbanks,
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_idle_regs, &nregs) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(phys_banks, bsize);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(mc_idle_regs, msize);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* section 1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < nbanks; i++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[(*rsp_idx)++] = phys_banks[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* section 2 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < nregs; i++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[(*rsp_idx)++] = *(sbdp_rename_script_t *)&mc_idle_regs[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(phys_banks, bsize);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(mc_idle_regs, msize);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * code assumes single mem-unit.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_prep_rename_script(sbdp_cr_handle_t *cph)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t *s_nodes, *t_nodes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int m = 0, i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bd_t s_bd, t_bd, *s_bdp, *t_bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_rename_script_t *rsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t new_base, old_base, temp_base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int s_num, t_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cph->s_bdp->bd_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_bd = *cph->s_bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cph->s_bdp->bd_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cph->t_bdp->bd_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_bd = *cph->t_bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cph->t_bdp->bd_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_bdp = &s_bd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_bdp = &t_bd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_nodes = s_bdp->nodes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_nodes = t_bdp->nodes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_num = s_bdp->nnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_num = t_bdp->nnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp = cph->script;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Calculate the new base address for the target bd
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_base = (s_bdp->bpa >> PHYS2UM_SHIFT) << MC_UM_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Calculate the old base address for the source bd
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel old_base = (t_bdp->bpa >> PHYS2UM_SHIFT) << MC_UM_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel temp_base = SG_INVAL_UM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("new 0x%lx old_base ox%lx temp_base 0x%lx\n", new_base,
03831d35f7499c87d51205817c93e9a8d42c4baestevel old_base, temp_base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel m = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Ensure the MC queues have been idled on the source and target
03831d35f7499c87d51205817c93e9a8d42c4baestevel * following the copy.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_prep_mc_idle_script(s_bdp, t_bdp, rsp, &m) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Script section terminator
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[m].masr_addr = 0ull;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[m].masr = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[m].asi = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel m++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Invalidate the base in the target mc registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < t_num; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_copy_regs(t_nodes[i], t_bdp->bpa, temp_base, 1, rsp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &m) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Invalidate the base in the source mc registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < s_num; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_copy_regs(s_nodes[i], s_bdp->bpa, temp_base, 1, rsp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &m) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copy the new base into the targets mc registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < t_num; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_copy_regs(t_nodes[i], t_bdp->bpa, new_base, 0, rsp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &m) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copy the old base into the source mc registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < s_num; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_copy_regs(s_nodes[i], s_bdp->bpa, old_base, 0, rsp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &m) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Zero masr_addr value indicates the END.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[m].masr_addr = 0ull;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[m].masr = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp[m].asi = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel m++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("dumping copy-rename script:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < m; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("0x%lx = 0x%lx, asi 0x%x\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni rsp[i].masr_addr, rsp[i].masr, rsp[i].asi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DELAY(1000000);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (m * sizeof (sbdp_rename_script_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EMU Activity Status Register needs to be read idle several times.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See Panther PRM 12.5.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SBDP_MCU_IDLE_RETRIES 10
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SBDP_MCU_IDLE_READS 3
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Using the "__relocatable" suffix informs DTrace providers (and anything
03831d35f7499c87d51205817c93e9a8d42c4baestevel * else, for that matter) that this function's text may be manually relocated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * elsewhere before it is executed. That is, it cannot be safely instrumented
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with any methodology that is PC-relative.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_copy_rename__relocatable(sbdp_cr_handle_t *hp, struct memlist *mlist,
03831d35f7499c87d51205817c93e9a8d42c4baestevel register sbdp_rename_script_t *rsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_cr_err_t err = SBDP_CR_OK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel size_t csize;
03831d35f7499c87d51205817c93e9a8d42c4baestevel size_t linesize;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t caddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t s_base, t_base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bd_t *s_sbp, *t_sbp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *ml;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_mc_idle_script_t *isp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr = ecache_flushaddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel csize = (size_t)(cpunodes[CPU->cpu_id].ecache_size * 2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel linesize = (size_t)(cpunodes[CPU->cpu_id].ecache_linesize);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel size = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_sbp = hp->s_bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_sbp = hp->t_bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_base = (uint64_t)s_sbp->bpa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_base = (uint64_t)t_sbp->bpa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel hp->ret = s_base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DO COPY.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = mlist; ml; ml = ml->ml_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t s_pa, t_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t nbytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams s_pa = ml->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams t_pa = t_base + (ml->ml_address - s_base);
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nbytes = ml->ml_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel size += nbytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (nbytes != 0ull) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This copy does NOT use an ASI
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that avoids the Ecache, therefore
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the dst_pa addresses may remain
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in our Ecache after the dst_pa
03831d35f7499c87d51205817c93e9a8d42c4baestevel * has been removed from the system.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A subsequent write-back to memory
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will cause an ARB-stop because the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * physical address no longer exists
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the system. Therefore we must
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flush out local Ecache after we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * finish the copy.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* copy 32 bytes at src_pa to dst_pa */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy32_il(s_pa, t_pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* increment by 32 bytes */
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_pa += (4 * sizeof (uint64_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_pa += (4 * sizeof (uint64_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* decrement by 32 bytes */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nbytes -= (4 * sizeof (uint64_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since bcopy32_il() does NOT use an ASI to bypass
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the Ecache, we need to flush our Ecache after
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the copy is complete.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel flush_ecache_il(caddr, csize, linesize); /* inline version */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Non-Panther MCs are idled by reading each physical bank.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; rsp[i].asi == ASI_MEM; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) lddphys_il(rsp[i].masr_addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel isp = (sbdp_mc_idle_script_t *)&rsp[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Panther MCs are idled by polling until the MCU idle state
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is read SBDP_MCU_IDLE_READS times in succession.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (isp->addr != 0ull) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SBDP_MCU_IDLE_RETRIES; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel register uint64_t v;
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int n_idle = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel v = ldxasi_il(isp->addr, isp->asi) &
03831d35f7499c87d51205817c93e9a8d42c4baestevel MCU_ACT_STATUS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (v != MCU_ACT_STATUS &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++n_idle < SBDP_MCU_IDLE_READS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (n_idle == SBDP_MCU_IDLE_READS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i == SBDP_MCU_IDLE_RETRIES) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* bailout */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hp->busy_mc = isp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SBDP_CR_MC_IDLE_ERR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel isp++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* skip terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel isp++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The following inline assembly routine caches
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the rename script and then caches the code that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will do the rename. This is necessary
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so that we don't have any memory references during
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the reprogramming. We accomplish this by first
03831d35f7499c87d51205817c93e9a8d42c4baestevel * jumping through the code to guarantee it's cached
03831d35f7499c87d51205817c93e9a8d42c4baestevel * before we actually execute it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_exec_script_il((sbdp_rename_script_t *)isp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevel_sbdp_copy_rename_end(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IMPORTANT: This function's location MUST be located immediately
03831d35f7499c87d51205817c93e9a8d42c4baestevel * following sbdp_copy_rename__relocatable to accurately
03831d35f7499c87d51205817c93e9a8d42c4baestevel * estimate its size. Note that this assumes (!)the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * compiler keeps these functions in the order in which
03831d35f7499c87d51205817c93e9a8d42c4baestevel * they appear :-o
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_memory_rename(sbdp_handle_t *hp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef lint
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Delete when implemented
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hp = hp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In Serengeti this is a nop
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_post_configure_mem(sbdp_handle_t *hp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef lint
03831d35f7499c87d51205817c93e9a8d42c4baestevel hp = hp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In Serengeti this is a nop
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_post_unconfigure_mem(sbdp_handle_t *hp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef lint
03831d35f7499c87d51205817c93e9a8d42c4baestevel hp = hp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdphw_disable_memctrl(sbdp_handle_t *hp, dev_info_t *dip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdphw_enable_memctrl(sbdp_handle_t *hp, dev_info_t *dip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We are assuming one memory node therefore the base address is the lowest
03831d35f7499c87d51205817c93e9a8d42c4baestevel * segment possible
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define PA_ABOVE_MAX (0x8000000000000000ull)
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdphw_get_base_physaddr(sbdp_handle_t *hp, dev_info_t *dip, uint64_t *pa)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(hp))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, board = -1, wnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct mem_arg arg = {0};
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t seg_pa, tmp_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *list[SBDP_MAX_MEM_NODES_PER_BOARD];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dip == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodeid = ddi_get_nodeid(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_get_bd_and_wnode_num(nodeid, &board, &wnode) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel list[0] = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel arg.board = board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel arg.list = list;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sbdp_walk_prom_tree(prom_rootnode(), sbdp_get_mem_dip, &arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (arg.ndips <= 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel seg_pa = PA_ABOVE_MAX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < arg.ndips; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (list[i] == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_get_lowest_addr_in_node(ddi_get_nodeid(list[i]),
03831d35f7499c87d51205817c93e9a8d42c4baestevel &tmp_pa) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tmp_pa < seg_pa)
03831d35f7499c87d51205817c93e9a8d42c4baestevel seg_pa = tmp_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Release hold acquired in sbdp_get_mem_dip()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_release_devi(list[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *pa = seg_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Record the fact that an error has occurred
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, ESGT_INTERNAL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_get_lowest_addr_in_node(pnode_t node, uint64_t *pa)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t mc_decode, seg_pa, tmp_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_regs_t mc_regs, *mc_regsp = &mc_regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel seg_pa = PA_ABOVE_MAX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mc_read_regs(node, mc_regsp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("sbdp_get_lowest_addr_in_node: failed to "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "read source Decode Regs\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SBDP_MAX_MCS_PER_NODE; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_decode = mc_regsp->mc_decode[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel valid = mc_decode >> MC_VALID_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp_pa = MC_BASE(mc_decode) << PHYS2UM_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (valid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (valid && (tmp_pa < seg_pa))
03831d35f7499c87d51205817c93e9a8d42c4baestevel seg_pa = tmp_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *pa = seg_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_is_mem(pnode_t node, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mem_op_t *memp = (mem_op_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char type[OBP_MAXPROPNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t *list;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char name[OBP_MAXDRVNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(memp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel list = memp->nodes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel board = memp->board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make sure that this node doesn't have its status
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as failed
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_get_comp_status(node) != SBD_COND_OK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = prom_getproplen(node, "device_type");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((len > 0) && (len < OBP_MAXPROPNAME))
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) prom_getprop(node, "device_type", (caddr_t)type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel type[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(type, "memory-controller") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int wnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_get_bd_and_wnode_num(node, &bd, &wnode) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bd == board) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make sure we don't overwrite the array
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (memp->nmem >= SBDP_MAX_MEM_NODES_PER_BOARD)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) prom_getprop(node, OBP_NAME, (caddr_t)name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("name %s boot bd %d board %d\n", name,
03831d35f7499c87d51205817c93e9a8d42c4baestevel board, bd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel list[memp->nmem++] = node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_get_meminfo(pnode_t nodeid, int mc, uint64_t *size, uint64_t *base_pa)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int board, wnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_regs_t mc_regs, *mc_regsp = &mc_regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t mc_decode = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_get_bd_and_wnode_num(nodeid, &board, &wnode) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mc_read_regs(nodeid, mc_regsp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("sbdp_get_meminfo: failed to read source "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Decode Regs");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Calculate memory size
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_decode = mc_regsp->mc_decode[mc];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check the valid bit to see if bank is there
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel valid = mc_decode >> MC_VALID_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (valid) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *size = MC_UK2SPAN(mc_decode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *base_pa = MC_BASE(mc_decode) << PHYS2UM_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Luckily for us mem nodes and cpu/CMP nodes are siblings. All we need to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * do is search in the same branch as the mem node for its sibling cpu or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CMP node.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelpnode_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelmc_get_sibling_cpu(pnode_t nodeid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_getprop(nodeid, OBP_PORTID, (caddr_t)&portid) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (OBP_NONODE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cpus and memory are siblings so we don't need to traverse
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the whole tree, just a branch
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (sbdp_find_nearby_cpu_by_portid(nodeid, portid));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Given a memory node, check it's sibling cpu or CMP to see if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * access to mem will be ok. We need to search for the node and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if found get its condition.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_cond_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelmc_check_sibling_cpu(pnode_t nodeid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t cpu_node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_cond_t cond;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_node = mc_get_sibling_cpu(nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cond = sbdp_get_comp_status(cpu_node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cond == SBD_COND_OK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int wnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_get_bd_and_wnode_num(nodeid, &bd, &wnode) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SBD_COND_UNKNOWN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) prom_getprop(nodeid, OBP_PORTID, (caddr_t)&portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Access to the memory controller should not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * be attempted if any of the cores are marked
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as being in reset.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < SBDP_MAX_CORES_PER_CMP; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unit = SG_PORTID_TO_CPU_UNIT(portid, i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbdp_is_cpu_present(wnode, bd, unit) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_is_cpu_in_reset(wnode, bd, unit)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cond = SBD_COND_UNUSABLE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (cond);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelmc_read_regs(pnode_t nodeid, mc_regs_t *mc_regsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t mc_addr, mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_regspace reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_cond_t sibling_cpu_cond;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int local_mc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) < 0) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (portid == -1))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mc should not be accessed if their corresponding cpu
03831d35f7499c87d51205817c93e9a8d42c4baestevel * has failed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sibling_cpu_cond = mc_check_sibling_cpu(nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((sibling_cpu_cond == SBD_COND_FAILED) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (sibling_cpu_cond == SBD_COND_UNUSABLE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = prom_getproplen(nodeid, "reg");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != sizeof (mc_regspace))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_getprop(nodeid, "reg", (caddr_t)&reg) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_addr = ((uint64_t)reg.regspec_addr_hi) << 32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_addr |= (uint64_t)reg.regspec_addr_lo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make sure we don't switch cpus
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_set(CPU_CURRENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (portid == cpunodes[CPU->cpu_id].portid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel local_mc = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel local_mc = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SG_MAX_BANKS_PER_MC; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask = SG_REG_2_OFFSET(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the memory controller is local to this CPU, we use
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the special ASI to read the decode registers.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Otherwise, we load the values from a magic address in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * I/O space.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (local_mc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_regsp->mc_decode[i] = lddmcdecode(
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask & MC_OFFSET_MASK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_regsp->mc_decode[i] = lddphysio(
03831d35f7499c87d51205817c93e9a8d42c4baestevel (mc_addr | mask));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_clear();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint64_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelmc_get_addr(pnode_t nodeid, int mc, uint_t *asi)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t mc_addr, addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_regspace reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int local_mc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) < 0) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (portid == -1))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = prom_getproplen(nodeid, "reg");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != sizeof (mc_regspace))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_getprop(nodeid, "reg", (caddr_t)&reg) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_addr = ((uint64_t)reg.regspec_addr_hi) << 32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_addr |= (uint64_t)reg.regspec_addr_lo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make sure we don't switch cpus
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_set(CPU_CURRENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (portid == cpunodes[CPU->cpu_id].portid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel local_mc = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel local_mc = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (local_mc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *asi = ASI_MC_DECODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel addr = SG_REG_2_OFFSET(mc) & MC_OFFSET_MASK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *asi = ASI_IO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel addr = SG_REG_2_OFFSET(mc) | mc_addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_clear();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_mem_add_span(sbdp_handle_t *hp, uint64_t address, uint64_t size)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_mem_del_span(sbdp_handle_t *hp, uint64_t address, uint64_t size)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel pfn_t basepfn = (pfn_t)(address >> PAGESHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pgcnt_t npages = (pgcnt_t)(size >> PAGESHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (size > 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = kcage_range_delete_post_mem_del(basepfn, npages);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "unexpected kcage_range_delete_post_mem_del"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " return value %d", rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_set_err(hp->h_err, ESGT_INTERNAL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This routine gets the size including the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bad banks
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_get_mem_size(sbdp_handle_t *hp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t size = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *mlist, *ml;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mlist = sbdp_get_memlist(hp, (dev_info_t *)NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = mlist; ml; ml = ml->ml_next)
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams size += ml->ml_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sbdp_del_memlist(hp, mlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("sbdp_get_mem_size: size 0x%" PRIx64 "\n", size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (btop(size));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function compares the list of banks passed with the banks
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the segment
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_check_seg_with_banks(sbdp_seg_t *seg, sbdp_bank_t *banks)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bank_t *cur_bank, *bank;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (cur_bank = seg->banks; cur_bank; cur_bank = cur_bank->seg_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (bank = banks; bank; bank = bank->bd_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!bank->valid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cur_bank == bank) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("banks found = %d total banks = %d\n", i, seg->nbanks);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we find the same num of banks that are equal, then this segment
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is not interleaved across boards
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i == seg->nbanks)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This routine determines if any of the memory banks on the board
03831d35f7499c87d51205817c93e9a8d42c4baestevel * participate in across board memory interleaving
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_isinterleaved(sbdp_handle_t *hp, dev_info_t *dip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(dip))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bank_t *bankp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int wnode, board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int is_interleave = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bd_t *bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_seg_t *seg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel board = hp->h_board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wnode = hp->h_wnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_print_all_segs();
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the banks for this board
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bdp = sbdp_get_bd_info(wnode, board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bdp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Search for the first bank with valid memory
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (bankp = bdp->banks; bankp; bankp = bankp->bd_next)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bankp->valid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If there are no banks in the board, then the board is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * not interleaved across boards
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bankp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel base = bankp->um & ~(bankp->uk);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find the segment for the first bank
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((seg = sbdp_get_seg(base)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Something bad has happened.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make sure that this segment is only composed of the banks
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in this board. If one is missing or we have an extra one
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the board is interleaved across boards
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel is_interleave = sbdp_check_seg_with_banks(seg, bdp->banks);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("interleave is %d\n", is_interleave);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (is_interleave);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Each node has 4 logical banks. This routine adds all the banks (including
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the invalid ones to the passed list. Note that we use the bd list and not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the seg list
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_add_nodes_banks(pnode_t node, sbdp_bank_t **banks)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_regs_t regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t *mc_decode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bank_t *bank;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mc_read_regs(node, &regs) == -1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_decode = regs.mc_decode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SBDP_MAX_MCS_PER_NODE; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This creates the mem for the new member of the list
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_fill_bank_info(mc_decode[i], &bank);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("adding bank %d\n", bank->id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Insert bank into the beginning of the list
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bank->bd_next = *banks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *banks = bank;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add this bank into its corresponding
03831d35f7499c87d51205817c93e9a8d42c4baestevel * segment
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_add_bank_to_seg(bank);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * given the info, create a new bank node and set the info
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as appropriate. We allocate the memory for the bank. It is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * up to the caller to ensure the mem is freed
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_fill_bank_info(uint64_t mc_decode, sbdp_bank_t **bank)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel static int id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bank_t *new;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel new = kmem_zalloc(sizeof (sbdp_bank_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->id = id++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->valid = (mc_decode >> MC_VALID_SHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->uk = MC_UK(mc_decode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->um = MC_UM(mc_decode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->lk = MC_LK(mc_decode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->lm = MC_LM(mc_decode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->bd_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->seg_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *bank = new;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Each bd has the potential of having mem banks on it. The banks
03831d35f7499c87d51205817c93e9a8d42c4baestevel * may be empty or not. This routine gets all the mem banks
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for this bd
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_init_bd_banks(sbdp_bd_t *bdp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, nmem;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t *lists;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel lists = bdp->nodes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nmem = bdp->nnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bdp->banks != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bdp->banks = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < nmem; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sbdp_add_nodes_banks(lists[i], &bdp->banks);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * swap the list of banks for the 2 boards
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_swap_list_of_banks(sbdp_bd_t *bdp1, sbdp_bd_t *bdp2)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bank_t *tmp_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((bdp1 == NULL) || (bdp2 == NULL))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp_ptr = bdp1->banks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bdp1->banks = bdp2->banks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bdp2->banks = tmp_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * free all the banks on the board. Note that a bank node belongs
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to 2 lists. The first list is the board list. The second one is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the seg list. We only need to remove the bank from both lists but only
03831d35f7499c87d51205817c93e9a8d42c4baestevel * free the node once.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_fini_bd_banks(sbdp_bd_t *bdp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bank_t *bkp, *nbkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (bkp = bdp->banks; bkp; ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove the bank from the seg list first
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("Removing bank %d\n", bkp->id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_remove_bank_from_seg(bkp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel nbkp = bkp->bd_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bkp->bd_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(bkp, sizeof (sbdp_bank_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bkp = nbkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel bdp->banks = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_print_bd_banks(sbdp_bd_t *bdp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bank_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("BOARD %d\n", bdp->bd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (bp = bdp->banks, i = 0; bp; bp = bp->bd_next, i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("BANK [%d]:\n", bp->id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("\tvalid %d\tuk 0x%x\tum 0x%x\tlk 0x%x"
03831d35f7499c87d51205817c93e9a8d42c4baestevel "\tlm 0x%x\n", bp->valid, bp->uk, bp->um,
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->lk, bp->lm);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_print_all_segs(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_seg_t *cur_seg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (cur_seg = sys_seg; cur_seg; cur_seg = cur_seg->next)
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_print_seg(cur_seg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_print_seg(sbdp_seg_t *seg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bank_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("SEG %d\n", seg->id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (bp = seg->banks, i = 0; bp; bp = bp->seg_next, i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("BANK [%d]:\n", bp->id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("\tvalid %d\tuk 0x%x\tum 0x%x\tlk 0x%x"
03831d35f7499c87d51205817c93e9a8d42c4baestevel "\tlm 0x%x\n", bp->valid, bp->uk, bp->um,
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->lk, bp->lm);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_add_bank_to_seg(sbdp_bank_t *bank)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_seg_t *cur_seg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static int id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if we got an invalid bank just skip it
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bank == NULL || !bank->valid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel base = bank->um & ~(bank->uk);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cur_seg = sbdp_get_seg(base)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This bank is part of a new segment, so create
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a struct for it and added to the list of segments
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cur_seg = kmem_zalloc(sizeof (sbdp_seg_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cur_seg->id = id++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cur_seg->base = base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cur_seg->size = ((bank->uk +1) << PHYS2UM_SHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cur_seg->intlv = ((bank->lk ^ 0xF) + 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * add to the seg list
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cur_seg->next = sys_seg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sys_seg = cur_seg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cur_seg->nbanks++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * add bank into segs bank list. Note we add at the head
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bank->seg_next = cur_seg->banks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cur_seg->banks = bank;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove this segment from the seg list
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_rm_seg(sbdp_seg_t *seg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_seg_t **curpp, *curp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel curpp = &sys_seg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((curp = *curpp) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (curp == seg) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *curpp = curp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel curpp = &curp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (curp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(curp, sizeof (sbdp_seg_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel curp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remove this bank from its seg list
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_remove_bank_from_seg(sbdp_bank_t *bank)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_seg_t *cur_seg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bank_t **curpp, *curp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if we got an invalid bank just skip it
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bank == NULL || !bank->valid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel base = bank->um & ~(bank->uk);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the bank doesn't belong to any seg just return
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cur_seg = sbdp_get_seg(base)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("bank %d with no segment\n", bank->id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find bank in the seg
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel curpp = &cur_seg->banks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((curp = *curpp) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (curp->id == bank->id) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * found node, remove it
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *curpp = curp->seg_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel curpp = &curp->seg_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (curp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cur_seg->nbanks--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cur_seg->nbanks == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * No banks left on this segment, remove the segment
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBDP_DBG_MEM("No banks left in this segment, removing it\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_rm_seg(cur_seg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_seg_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_get_seg(uint64_t base)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_seg_t *cur_seg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (cur_seg = sys_seg; cur_seg; cur_seg = cur_seg->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cur_seg-> base == base)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (cur_seg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_passthru_readmem(sbdp_handle_t *hp, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(hp))
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(arg))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *ml;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t src_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t dst_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t dst;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dst_pa = va_to_pa(&dst);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel memlist_read_lock();
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = phys_install; ml; ml = ml->ml_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t nbytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams src_pa = ml->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nbytes = ml->ml_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (nbytes != 0ull) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* copy 32 bytes at src_pa to dst_pa */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy32_il(src_pa, dst_pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* increment by 32 bytes */
03831d35f7499c87d51205817c93e9a8d42c4baestevel src_pa += (4 * sizeof (uint64_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* decrement by 32 bytes */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nbytes -= (4 * sizeof (uint64_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel memlist_read_unlock();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelisdigit(int ch)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ch >= '0' && ch <= '9');
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_strtoi(char *p, char **pos)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int n;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int c, neg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!isdigit(c = *p)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (isspace(c))
03831d35f7499c87d51205817c93e9a8d42c4baestevel c = *++p;
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (c) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case '-':
03831d35f7499c87d51205817c93e9a8d42c4baestevel neg++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* FALLTHROUGH */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case '+':
03831d35f7499c87d51205817c93e9a8d42c4baestevel c = *++p;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!isdigit(c)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pos != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *pos = p;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (n = '0' - c; isdigit(c = *++p); ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel n *= 10; /* two steps to avoid unnecessary overflow */
03831d35f7499c87d51205817c93e9a8d42c4baestevel n += '0' - c; /* accum neg to avoid surprises at MAX */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pos != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *pos = p;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (neg ? n : -n);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbdp_passthru_prep_script(sbdp_handle_t *hp, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int board, i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_bd_t *t_bdp, *s_bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *opts;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int t_board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_rename_script_t *rsbuffer;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_cr_handle_t *cph;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int scriptlen, size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel opts = (char *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel board = hp->h_board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel opts += strlen("prep-script=");
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_board = sbdp_strtoi(opts, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cph = kmem_zalloc(sizeof (sbdp_cr_handle_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel size = sizeof (sbdp_rename_script_t) * SBDP_RENAME_MAXOP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsbuffer = kmem_zalloc(size, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_bdp = sbdp_get_bd_info(hp->h_wnode, board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_bdp = sbdp_get_bd_info(hp->h_wnode, t_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cph->s_bdp = s_bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cph->t_bdp = t_bdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cph->script = rsbuffer;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_set(CPU_CURRENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scriptlen = sbdp_prep_rename_script(cph);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scriptlen <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sbdp failed to prep for copy-rename");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("SCRIPT from board %d to board %d ->\n", board, t_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < (scriptlen / (sizeof (sbdp_rename_script_t))); i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("0x%lx = 0x%lx, asi 0x%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsbuffer[i].masr_addr, rsbuffer[i].masr, rsbuffer[i].asi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_clear();
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(rsbuffer, size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(cph, sizeof (sbdp_cr_handle_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif