03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
c39996a7c853f35e9cf2fc40b30e0d2eec0e9996stevel * Common Development and Distribution License (the "License").
c39996a7c853f35e9cf2fc40b30e0d2eec0e9996stevel * 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 */
c39996a7c853f35e9cf2fc40b30e0d2eec0e9996stevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/time.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cpuvar.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/dditypes.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddipropdefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi_impldefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/esunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunndi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/platform_module.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/errno.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/promif.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/promimpl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/prom_plat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cmn_err.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sysmacros.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/mem_cage.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kobj.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/utsname.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cpu_sgnblk_defs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/atomic.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kdi_impl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgsbbc.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgsbbc_iosram.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgsbbc_iosram_priv.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgsbbc_mailbox.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgsgn.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgcn.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/serengeti.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgfrutypes.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/machsystm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sbd_ioctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sbd.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sbdp_mem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/memnode.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <vm/vm_dep.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <vm/page.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cheetahregs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/plat_ecc_unum.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/plat_ecc_dimm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/lgrp.h>
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni#include <sys/clock_impl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sg_debug = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DCMNERR if (sg_debug) cmn_err
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DCMNERR
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* local functions */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void cpu_sgn_update(ushort_t sgn, uchar_t state,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t sub_state, int cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Local data.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_write_ptr is a pointer to iosram_write(). Because of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kernel dynamic linking, we can't get to the function by name,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * but we can look up its address, and store it in this variable
03831d35f7499c87d51205817c93e9a8d42c4baestevel * instead.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We include the extern for iosram_write() here not because we call
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it, but to force compilation errors if its prototype doesn't
03831d35f7499c87d51205817c93e9a8d42c4baestevel * match the prototype of iosram_write_ptr.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The same issues apply to iosram_read() and iosram_read_ptr.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*CSTYLED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int iosram_write (int, uint32_t, caddr_t, uint32_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int (*iosram_write_ptr)(int, uint32_t, caddr_t, uint32_t) = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*CSTYLED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int iosram_read (int, uint32_t, caddr_t, uint32_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int (*iosram_read_ptr)(int, uint32_t, caddr_t, uint32_t) = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Variable to indicate if the date should be obtained from the SC or not.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint todsg_use_sc = FALSE; /* set the false at the beginning */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Preallocation of spare tsb's for DR
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We don't allocate spares for Wildcat since TSBs should come
03831d35f7499c87d51205817c93e9a8d42c4baestevel * out of memory local to the node.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define IOMMU_PER_SCHIZO 2
03831d35f7499c87d51205817c93e9a8d42c4baestevelint serengeti_tsb_spares = (SG_MAX_IO_BDS * SG_SCHIZO_PER_IO_BD *
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOMMU_PER_SCHIZO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah * sg_max_ncpus is the maximum number of CPUs supported on Serengeti.
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah * sg_max_ncpus is set to be smaller than NCPU to reduce the amount of
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah * memory the logs take up until we have a dynamic log memory allocation
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah * solution.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuahint sg_max_ncpus = (24 * 2); /* (max # of processors * # of cores/proc) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * variables to control mailbox message timeouts.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These can be patched via /etc/system or mdb.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint sbbc_mbox_default_timeout = MBOX_DEFAULT_TIMEOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevelint sbbc_mbox_min_timeout = MBOX_MIN_TIMEOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* cached 'chosen' node_id */
03831d35f7499c87d51205817c93e9a8d42c4baestevelpnode_t chosen_nodeid = (pnode_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void (*sg_ecc_taskq_func)(sbbc_ecc_mbox_t *) = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int (*sg_ecc_mbox_func)(sbbc_ecc_mbox_t *) = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Table that maps memory slices to a specific memnode.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint slice_to_memnode[SG_MAX_SLICE];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_dimm_sid_board_t domain_dimm_sids[SG_MAX_CPU_BDS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelset_platform_tsb_spares()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (MIN(serengeti_tsb_spares, MAX_UPA));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#pragma weak mmu_init_large_pages
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelset_platform_defaults(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern int watchdog_enable;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern uint64_t xc_tick_limit_scale;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern void mmu_init_large_pages(size_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *todsg_name = "todsg";
03831d35f7499c87d51205817c93e9a8d42c4baestevel ce_verbose_memory = 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ce_verbose_other = 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel watchdog_enable = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel watchdog_available = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_sgn_func = cpu_sgn_update;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* tod_module_name should be set to "todsg" from OBP property */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tod_module_name && (strcmp(tod_module_name, todsg_name) == 0))
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("Using todsg driver\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("Force using todsg driver\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel tod_module_name = todsg_name;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Serengeti does not support forthdebug */
03831d35f7499c87d51205817c93e9a8d42c4baestevel forthdebug_supported = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Some DR operations require the system to be sync paused.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sync pause on Serengeti could potentially take up to 4
03831d35f7499c87d51205817c93e9a8d42c4baestevel * seconds to complete depending on the load on the SC. To
03831d35f7499c87d51205817c93e9a8d42c4baestevel * avoid send_mond panics during such operations, we need to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * increase xc_tick_limit to a larger value on Serengeti by
03831d35f7499c87d51205817c93e9a8d42c4baestevel * setting xc_tick_limit_scale to 5.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel xc_tick_limit_scale = 5;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mmu_page_sizes == max_mmu_page_sizes) &&
e12a8a13c5492eeed938960ff7c68a46f982288bsusans (mmu_ism_pagesize != DEFAULT_ISM_PAGESIZE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (&mmu_init_large_pages)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mmu_init_large_pages(mmu_ism_pagesize);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelload_platform_modules(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (modload("misc", "pcihp") < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "pcihp driver failed to load");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_cpu_poweron(struct cpu *cp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*serengeti_cpu_poweron)(struct cpu *) = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel serengeti_cpu_poweron =
03831d35f7499c87d51205817c93e9a8d42c4baestevel (int (*)(struct cpu *))modgetsymvalue("sbdp_cpu_poweron", 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (serengeti_cpu_poweron == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOTSUP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((serengeti_cpu_poweron)(cp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_cpu_poweroff(struct cpu *cp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*serengeti_cpu_poweroff)(struct cpu *) = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel serengeti_cpu_poweroff =
03831d35f7499c87d51205817c93e9a8d42c4baestevel (int (*)(struct cpu *))modgetsymvalue("sbdp_cpu_poweroff", 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (serengeti_cpu_poweroff == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOTSUP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((serengeti_cpu_poweroff)(cp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevelpgcnt_t serengeti_cage_size_limit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* Preferred minimum cage size (expressed in pages)... for DR */
03831d35f7499c87d51205817c93e9a8d42c4baestevelpgcnt_t serengeti_minimum_cage_size = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelset_platform_cage_params(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern pgcnt_t total_pages;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern struct memlist *phys_avail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (kernel_cage_enable) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pgcnt_t preferred_cage_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel preferred_cage_size =
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAX(serengeti_minimum_cage_size, total_pages / 256);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (serengeti_cage_size_limit)
03831d35f7499c87d51205817c93e9a8d42c4baestevel preferred_cage_size = serengeti_cage_size_limit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Post copies obp into the lowest slice. This requires the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cage to grow upwards
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
85f5803819bea86c07827a9544494e4ad327d95ddp kcage_range_init(phys_avail, KCAGE_UP, preferred_cage_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
5832075c3d504be66f389f3bc46573d7c21ee3fasetje kcage_startup_dir = KCAGE_UP;
5832075c3d504be66f389f3bc46573d7c21ee3fasetje
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Only note when the cage is off since it should always be on. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!kcage_on)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!DR Kernel Cage is DISABLED");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define ALIGN(x, a) ((a) == 0 ? (uint64_t)(x) : \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (((uint64_t)(x) + (uint64_t)(a) - 1l) & ~((uint64_t)(a) - 1l)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelupdate_mem_bounds(int brd, uint64_t base, uint64_t sz)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t end;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int mnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel end = base + sz - 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * First see if this board already has a memnode associated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with it. If not, see if this slice has a memnode. This
03831d35f7499c87d51205817c93e9a8d42c4baestevel * covers the cases where a single slice covers multiple
03831d35f7499c87d51205817c93e9a8d42c4baestevel * boards (cross-board interleaving) and where a single
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board has multiple slices (1+GB DIMMs).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mnode = plat_lgrphand_to_mem_node(brd)) == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mnode = slice_to_memnode[PA_2_SLICE(base)]) == -1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mnode = mem_node_alloc();
03831d35f7499c87d51205817c93e9a8d42c4baestevel plat_assign_lgrphand_to_mem_node(brd, mnode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Align base at 16GB boundary
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel base = ALIGN(base, (1ul << PA_SLICE_SHIFT));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (base < end) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel slice_to_memnode[PA_2_SLICE(base)] = mnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel base += (1ul << PA_SLICE_SHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Dynamically detect memory slices in the system by decoding
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the cpu memory decoder registers at boot time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_fill_mc(pnode_t nodeid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t mc_addr, mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t mc_decode[SG_MAX_BANKS_PER_MC];
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t base, size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t regs[4];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int local_mc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int boardid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) < 0) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (portid == -1))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Decode the board number from the MC portid
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel boardid = SG_PORTID_TO_BOARD_NUM(portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The "reg" property returns 4 32-bit values. The first two are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * combined to form a 64-bit address. The second two are for a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 64-bit size, but we don't actually need to look at that value.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = prom_getproplen(nodeid, "reg");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != (sizeof (uint32_t) * 4)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("Warning: malformed 'reg' property\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_getprop(nodeid, "reg", (caddr_t)regs) < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_addr = ((uint64_t)regs[0]) << 32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_addr |= (uint64_t)regs[1];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Figure out whether the memory controller we are examining
03831d35f7499c87d51205817c93e9a8d42c4baestevel * belongs to this CPU or a different one.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
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_decode[i] = lddmcdecode(mask & MC_OFFSET_MASK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel mc_decode[i] = lddphysio((mc_addr | mask));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mc_decode[i] >> MC_VALID_SHIFT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The memory decode register is a bitmask field,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so we can decode that into both a base and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a span.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel base = MC_BASE(mc_decode[i]) << PHYS2UM_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel size = MC_UK2SPAN(mc_decode[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel update_mem_bounds(boardid, base, size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This routine is run midway through the boot process. By the time we get
03831d35f7499c87d51205817c93e9a8d42c4baestevel * here, we know about all the active CPU boards in the system, and we have
03831d35f7499c87d51205817c93e9a8d42c4baestevel * extracted information about each board's memory from the memory
03831d35f7499c87d51205817c93e9a8d42c4baestevel * controllers. We have also figured out which ranges of memory will be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * assigned to which memnodes, so we walk the slice table to build the table
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of memnodes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjeplat_build_mem_nodes(prom_memlist_t *list, size_t nelems)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slice;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pfn_t basepfn;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pgcnt_t npgs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mem_node_pfn_shift = PFN_SLICE_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mem_node_physalign = (1ull << PA_SLICE_SHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (slice = 0; slice < SG_MAX_SLICE; slice++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slice_to_memnode[slice] == -1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel basepfn = (uint64_t)slice << PFN_SLICE_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel npgs = 1ull << PFN_SLICE_SHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mem_node_add_slice(basepfn, basepfn + npgs - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_pfn_to_mem_node(pfn_t pfn)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = slice_to_memnode[PFN_2_SLICE(pfn)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Serengeti support for lgroups.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * On Serengeti, an lgroup platform handle == board number.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Mappings between lgroup handles and memnodes are managed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in addition to mappings between memory slices and memnodes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to support cross-board interleaving as well as multiple
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slices per board (e.g. >1GB DIMMs). The initial mapping
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of memnodes to lgroup handles is determined at boot time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A DR addition of memory adds a new mapping. A DR copy-rename
03831d35f7499c87d51205817c93e9a8d42c4baestevel * swaps mappings.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Macro for extracting the board number from the CPU id
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define CPUID_TO_BOARD(id) (((id) >> 2) & 0x7)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return the platform handle for the lgroup containing the given CPU
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For Serengeti, lgroup platform handle == board number
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevellgrp_handle_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_lgrp_cpu_to_hand(processorid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (CPUID_TO_BOARD(id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Platform specific lgroup initialization
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_lgrp_init(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern uint32_t lgrp_expand_proc_thresh;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern uint32_t lgrp_expand_proc_diff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize lookup tables to invalid values so we catch
03831d35f7499c87d51205817c93e9a8d42c4baestevel * any illegal use of them.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SG_MAX_SLICE; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel slice_to_memnode[i] = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set tuneables for Serengeti architecture
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * lgrp_expand_proc_thresh is the minimum load on the lgroups
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this process is currently running on before considering
03831d35f7499c87d51205817c93e9a8d42c4baestevel * expanding threads to another lgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * lgrp_expand_proc_diff determines how much less the remote lgroup
03831d35f7499c87d51205817c93e9a8d42c4baestevel * must be loaded before expanding to it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Bandwidth is maximized on Serengeti by spreading load across
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the machine. The impact to inter-thread communication isn't
03831d35f7499c87d51205817c93e9a8d42c4baestevel * too costly since remote latencies are relatively low. These
03831d35f7499c87d51205817c93e9a8d42c4baestevel * values equate to one CPU's load and so attempt to spread the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * load out across as many lgroups as possible one CPU at a time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel lgrp_expand_proc_thresh = LGRP_LOADAVG_THREAD_MAX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel lgrp_expand_proc_diff = LGRP_LOADAVG_THREAD_MAX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Platform notification of lgroup (re)configuration changes
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_lgrp_config(lgrp_config_flag_t evt, uintptr_t arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel update_membounds_t *umb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel lgrp_config_mem_rename_t lmr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel lgrp_handle_t shand, thand;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int snode, tnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (evt) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case LGRP_CONFIG_MEM_ADD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel umb = (update_membounds_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel update_mem_bounds(umb->u_board, umb->u_base, umb->u_len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case LGRP_CONFIG_MEM_DEL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* We don't have to do anything */
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case LGRP_CONFIG_MEM_RENAME:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * During a DR copy-rename operation, all of the memory
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on one board is moved to another board -- but the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * addresses/pfns and memnodes don't change. This means
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the memory has changed locations without changing identity.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Source is where we are copying from and target is where we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * are copying to. After source memnode is copied to target
03831d35f7499c87d51205817c93e9a8d42c4baestevel * memnode, the physical addresses of the target memnode are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * renamed to match what the source memnode had. Then target
03831d35f7499c87d51205817c93e9a8d42c4baestevel * memnode can be removed and source memnode can take its
03831d35f7499c87d51205817c93e9a8d42c4baestevel * place.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To do this, swap the lgroup handle to memnode mappings for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the boards, so target lgroup will have source memnode and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * source lgroup will have empty target memnode which is where
03831d35f7499c87d51205817c93e9a8d42c4baestevel * its memory will go (if any is added to it later).
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Then source memnode needs to be removed from its lgroup
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and added to the target lgroup where the memory was living
03831d35f7499c87d51205817c93e9a8d42c4baestevel * but under a different name/memnode. The memory was in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * target memnode and now lives in the source memnode with
03831d35f7499c87d51205817c93e9a8d42c4baestevel * different physical addresses even though it is the same
03831d35f7499c87d51205817c93e9a8d42c4baestevel * memory.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel shand = arg & 0xffff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel thand = (arg & 0xffff0000) >> 16;
03831d35f7499c87d51205817c93e9a8d42c4baestevel snode = plat_lgrphand_to_mem_node(shand);
03831d35f7499c87d51205817c93e9a8d42c4baestevel tnode = plat_lgrphand_to_mem_node(thand);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel plat_assign_lgrphand_to_mem_node(thand, snode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel plat_assign_lgrphand_to_mem_node(shand, tnode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove source memnode of copy rename from its lgroup
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and add it to its new target lgroup
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel lmr.lmem_rename_from = shand;
03831d35f7499c87d51205817c93e9a8d42c4baestevel lmr.lmem_rename_to = thand;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel lgrp_config(LGRP_CONFIG_MEM_RENAME, (uintptr_t)snode,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uintptr_t)&lmr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return latency between "from" and "to" lgroups
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This latency number can only be used for relative comparison
03831d35f7499c87d51205817c93e9a8d42c4baestevel * between lgroups on the running system, cannot be used across platforms,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and may not reflect the actual latency. It is platform and implementation
03831d35f7499c87d51205817c93e9a8d42c4baestevel * specific, so platform gets to decide its value. It would be nice if the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * number was at least proportional to make comparisons more meaningful though.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: The numbers below are supposed to be load latencies for uncached
03831d35f7499c87d51205817c93e9a8d42c4baestevel * memory divided by 10.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_lgrp_latency(lgrp_handle_t from, lgrp_handle_t to)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return min remote latency when there are more than two lgroups
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (root and child) and getting latency between two different lgroups
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or root is involved
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (lgrp_optimizations() && (from != to ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel from == LGRP_DEFAULT_HANDLE || to == LGRP_DEFAULT_HANDLE))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (28);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (23);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_freelist_process(int mnode)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find dip for chosen IOSRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_info_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelfind_chosen_dip(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char master_sbbc[MAXNAMELEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t tunnel;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * find the /chosen SBBC node, prom interface will handle errors
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodeid = prom_chosennode();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the 'iosram' property from the /chosen node
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_getprop(nodeid, IOSRAM_CHOSEN_PROP, (caddr_t)&tunnel) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBBC_ERR(CE_PANIC, "No iosram property found! \n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_phandle_to_path((phandle_t)tunnel, master_sbbc,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (master_sbbc)) < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBBC_ERR1(CE_PANIC, "prom_phandle_to_path(%d) failed\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel tunnel);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel chosen_nodeid = nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * load and attach the sgsbbc driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This will also attach all the sgsbbc driver instances
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i_ddi_attach_hw_nodes("sgsbbc") != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sgsbbc failed to load\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* translate a path name to a dev_info_t */
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip = e_ddi_hold_devi_by_path(master_sbbc, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((dip == NULL) || (ddi_get_nodeid(dip) != tunnel)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_PANIC, "i_ddi_path_to_devi(%x) failed for SBBC\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel tunnel);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* make sure devi_ref is ZERO */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DCMNERR(CE_CONT, "Chosen IOSRAM is at %s \n", master_sbbc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelload_platform_drivers(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int ret;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Load and attach the mc-us3 memory driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i_ddi_attach_hw_nodes("mc-us3") != DDI_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "mc-us3 failed to load");
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_hold_driver(ddi_name_to_major("mc-us3"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize the chosen IOSRAM before its clients
03831d35f7499c87d51205817c93e9a8d42c4baestevel * are loaded.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) find_chosen_dip();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Ideally, we'd do this in set_platform_defaults(), but
03831d35f7499c87d51205817c93e9a8d42c4baestevel * at that point it's too early to look up symbols.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_write_ptr = (int (*)(int, uint32_t, caddr_t, uint32_t))
03831d35f7499c87d51205817c93e9a8d42c4baestevel modgetsymvalue("iosram_write", 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_write_ptr == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DCMNERR(CE_WARN, "load_platform_defaults: iosram_write()"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " not found; signatures will not be updated\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The iosram read ptr is only needed if we can actually
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write CPU signatures, so only bother setting it if we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * set a valid write pointer, above.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_read_ptr = (int (*)(int, uint32_t, caddr_t, uint32_t))
03831d35f7499c87d51205817c93e9a8d42c4baestevel modgetsymvalue("iosram_read", 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_read_ptr == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DCMNERR(CE_WARN, "load_platform_defaults: iosram_read()"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " not found\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set todsg_use_sc to TRUE so that we will be getting date
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from the SC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel todsg_use_sc = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now is a good time to activate hardware watchdog (if one exists).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&tod_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (watchdog_enable)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret = tod_ops.tod_set_watchdog_timer(watchdog_timeout_seconds);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&tod_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ret != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel printf("Hardware watchdog enabled\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Load and attach the schizo pci bus nexus driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i_ddi_attach_hw_nodes("pcisch") != DDI_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "pcisch failed to load");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel plat_ecc_init();
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * No platform drivers on this platform
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelchar *platform_module_list[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (char *)0
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_tod_fault(enum tod_fault_type tod_bad)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_max_boards()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SG_MAX_BDS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_max_io_units_per_board()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SG_MAX_IO_PER_BD);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_max_cmp_units_per_board()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SG_MAX_CMPS_PER_BD);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_max_cpu_units_per_board()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SG_MAX_CPUS_PER_BD);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_max_mc_units_per_board()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SG_MAX_CMPS_PER_BD); /* each CPU die has a memory controller */
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_max_mem_units_per_board()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SG_MAX_MEM_PER_BD);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_max_cpumem_boards(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SG_MAX_CPU_BDS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelset_platform_max_ncpus(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (sg_max_ncpus);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_dmv_params(uint_t *hwint, uint_t *swint)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel *hwint = MAX_UPA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *swint = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Our nodename has been set, pass it along to the SC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_nodename_set(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_msg_t req; /* request */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_msg_t resp; /* response */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv; /* return value from call to mbox */
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct nodename_info {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int32_t namelen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char nodename[_SYS_NMLN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel } nni;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*sg_mbox)(sbbc_msg_t *, sbbc_msg_t *, time_t) = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * find the symbol for the mailbox routine
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sg_mbox = (int (*)(sbbc_msg_t *, sbbc_msg_t *, time_t))
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje modgetsymvalue("sbbc_mbox_request_response", 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sg_mbox == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!plat_nodename_set: sg_mbox not found\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * construct the message telling the SC our nodename
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) strcpy(nni.nodename, utsname.nodename);
03831d35f7499c87d51205817c93e9a8d42c4baestevel nni.namelen = (int32_t)strlen(nni.nodename);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_type.type = INFO_MBOX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_type.sub_type = INFO_MBOX_NODENAME;
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_len = (int)(nni.namelen + sizeof (nni.namelen));
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_bytes = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_buf = (caddr_t)&nni;
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_data[0] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_data[1] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialize the response back from the SC
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp.msg_type.type = INFO_MBOX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp.msg_type.sub_type = INFO_MBOX_NODENAME;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp.msg_status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp.msg_len = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp.msg_bytes = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp.msg_buf = (caddr_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp.msg_data[0] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp.msg_data[1] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ship it and check for success
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = (sg_mbox)(&req, &resp, sbbc_mbox_default_timeout);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!plat_nodename_set: sg_mbox retval %d\n", rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (resp.msg_status != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!plat_nodename_set: msg_status %d\n",
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje resp.msg_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DCMNERR(CE_NOTE, "!plat_nodename_set was successful\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It is necessary to exchange the capability bitmap
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with SC before sending any ecc error information and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * indictment. We are calling the plat_ecc_capability_send()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * here just after sending the nodename successfully.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = plat_ecc_capability_send();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DCMNERR(CE_NOTE, "!plat_ecc_capability_send was"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " successful\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flag to allow users switch between using OBP's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * prom_get_unum() and mc-us3 driver's p2get_mem_unum()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (for main memory errors only).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint sg_use_prom_get_unum = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Debugging flag: set to 1 to call into obp for get_unum, or set it to 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to call into the unum cache system. This is the E$ equivalent of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sg_use_prom_get_unum.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint sg_use_prom_ecache_unum = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* used for logging ECC errors to the SC */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SG_MEMORY_ECC 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SG_ECACHE_ECC 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SG_UNKNOWN_ECC (-1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * plat_get_mem_unum() generates a string identifying either the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * memory or E$ DIMM(s) during error logging. Depending on whether
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the error is E$ or memory related, the appropriate support
03831d35f7499c87d51205817c93e9a8d42c4baestevel * routine is called to assist in the string generation.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - For main memory errors we can use the mc-us3 drivers p2getunum()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (or prom_get_unum() for debugging purposes).
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - For E$ errors we call sg_get_ecacheunum() to generate the unum (or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * prom_serengeti_get_ecacheunum() for debugging purposes).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsg_prom_get_unum(int synd_code, uint64_t paddr, char *buf, int buflen,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *lenp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((prom_get_unum(synd_code, (unsigned long long)paddr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, buflen, lenp)) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else if (*lenp <= 1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unum_func will either point to the memory drivers p2get_mem_unum()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or to prom_get_unum() for memory errors.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*unum_func)(int synd_code, uint64_t paddr, char *buf,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int buflen, int *lenp) = p2get_mem_unum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check if it's a Memory or an Ecache error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (flt_in_memory) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It's a main memory error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For debugging we allow the user to switch between
03831d35f7499c87d51205817c93e9a8d42c4baestevel * using OBP's get_unum and the memory driver's get_unum
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so we create a pointer to the functions and switch
03831d35f7499c87d51205817c93e9a8d42c4baestevel * depending on the sg_use_prom_get_unum flag.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sg_use_prom_get_unum) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DCMNERR(CE_NOTE, "Using prom_get_unum from OBP");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (sg_prom_get_unum(synd_code,
03831d35f7499c87d51205817c93e9a8d42c4baestevel P2ALIGN(flt_addr, 8), buf, buflen, lenp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (unum_func != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (unum_func(synd_code, P2ALIGN(flt_addr, 8),
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, buflen, lenp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOTSUP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (flt_status & ECC_ECACHE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It's an E$ error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sg_use_prom_ecache_unum) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We call to OBP to handle this.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DCMNERR(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Using prom_serengeti_get_ecacheunum from OBP");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_serengeti_get_ecacheunum(flt_bus_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel P2ALIGN(flt_addr, 8), buf, buflen, lenp) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (sg_get_ecacheunum(flt_bus_id, flt_addr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, buflen, lenp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOTSUP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This platform hook gets called from mc_add_mem_unum_label() in the mc-us3
03831d35f7499c87d51205817c93e9a8d42c4baestevel * driver giving each platform the opportunity to add platform
03831d35f7499c87d51205817c93e9a8d42c4baestevel * specific label information to the unum for ECC error logging purposes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_add_mem_unum_label(char *unum, int mcid, int bank, int dimm)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char new_unum[UNUM_NAMLEN] = "";
03831d35f7499c87d51205817c93e9a8d42c4baestevel int node = SG_PORTID_TO_NODEID(mcid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int board = SG_CPU_BD_PORTID_TO_BD_NUM(mcid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int position = SG_PORTID_TO_CPU_POSN(mcid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The mc-us3 driver deals with logical banks but for unum
03831d35f7499c87d51205817c93e9a8d42c4baestevel * purposes we need to use physical banks so that the correct
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dimm can be physically located. Logical banks 0 and 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel * make up physical bank 0. Logical banks 1 and 3 make up
03831d35f7499c87d51205817c93e9a8d42c4baestevel * physical bank 1. Here we do the necessary conversion.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bank = (bank % 2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dimm == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_SET_FRU_NAME_NODE(new_unum, node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_SET_FRU_NAME_CPU_BOARD(new_unum, board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_SET_FRU_NAME_MODULE(new_unum, position);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_SET_FRU_NAME_BANK(new_unum, bank);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_SET_FRU_NAME_NODE(new_unum, node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_SET_FRU_NAME_CPU_BOARD(new_unum, board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_SET_FRU_NAME_MODULE(new_unum, position);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_SET_FRU_NAME_BANK(new_unum, bank);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_SET_FRU_NAME_DIMM(new_unum, dimm);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strcat(new_unum, " ");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strcat(new_unum, unum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strcpy(unum, new_unum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int node = SG_PORTID_TO_NODEID(cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int board = SG_CPU_BD_PORTID_TO_BD_NUM(cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (snprintf(buf, buflen, "/N%d/%s%d", node,
03831d35f7499c87d51205817c93e9a8d42c4baestevel SG_HPU_TYPE_CPU_BOARD_ID, board) >= buflen) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOSPC);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *lenp = strlen(buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We log all ECC events to the SC so we send a mailbox
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message to the SC passing it the relevant data.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ECC mailbox messages are sent via a taskq mechanism to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * prevent impaired system performance during ECC floods.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Indictments have already passed through a taskq, so they
03831d35f7499c87d51205817c93e9a8d42c4baestevel * are not queued here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_send_ecc_mailbox_msg(plat_ecc_message_type_t msg_type, void *datap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_ecc_mbox_t *msgp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel size_t msg_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t msg_subtype;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int sleep_flag, log_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sg_ecc_taskq_func == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sg_ecc_taskq_func = (void (*)(sbbc_ecc_mbox_t *))
03831d35f7499c87d51205817c93e9a8d42c4baestevel modgetsymvalue("sbbc_mbox_queue_ecc_event", 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sg_ecc_taskq_func == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sbbc_mbox_queue_ecc_event not found");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENODEV);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sg_ecc_mbox_func == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sg_ecc_mbox_func = (int (*)(sbbc_ecc_mbox_t *))
03831d35f7499c87d51205817c93e9a8d42c4baestevel modgetsymvalue("sbbc_mbox_ecc_output", 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sg_ecc_mbox_func == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sbbc_mbox_ecc_output not found");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENODEV);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize the request and response structures
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (msg_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_ERROR_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_subtype = INFO_MBOX_ERROR_ECC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_size = sizeof (plat_ecc_error_data_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag = KM_NOSLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel log_error = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_ERROR2_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_subtype = INFO_MBOX_ECC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_size = sizeof (plat_ecc_error2_data_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag = KM_NOSLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel log_error = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_INDICTMENT_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_subtype = INFO_MBOX_ERROR_INDICT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_size = sizeof (plat_ecc_indictment_data_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag = KM_SLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel log_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_INDICTMENT2_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_subtype = INFO_MBOX_ECC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_size = sizeof (plat_ecc_indictment2_data_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag = KM_SLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel log_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_CAPABILITY_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_subtype = INFO_MBOX_ECC_CAP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_size = sizeof (plat_capability_data_t) +
03831d35f7499c87d51205817c93e9a8d42c4baestevel strlen(utsname.release) + strlen(utsname.version) + 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag = KM_SLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel log_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_DIMM_SID_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_subtype = INFO_MBOX_ECC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_size = sizeof (plat_dimm_sid_request_data_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag = KM_SLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel log_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp = (sbbc_ecc_mbox_t *)kmem_zalloc(sizeof (sbbc_ecc_mbox_t),
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje sleep_flag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msgp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: "
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje "unable to allocate sbbc_ecc_mbox");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_log_error = log_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_req.msg_type.type = INFO_MBOX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_req.msg_type.sub_type = msg_subtype;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_req.msg_status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_req.msg_len = (int)msg_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_req.msg_bytes = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_req.msg_buf = (caddr_t)kmem_zalloc(msg_size, sleep_flag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_req.msg_data[0] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_req.msg_data[1] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msgp->ecc_req.msg_buf == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: "
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje "unable to allocate request msg_buf");
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free((void *)msgp, sizeof (sbbc_ecc_mbox_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(datap, (void *)msgp->ecc_req.msg_buf, msg_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialize the response back from the SC
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_type.type = INFO_MBOX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_type.sub_type = msg_subtype;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_len = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_bytes = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_buf = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_data[0] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_data[1] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (msg_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_ERROR_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_ERROR2_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For Error Messages, we go through a taskq.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Queue up the message for processing
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (*sg_ecc_taskq_func)(msgp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_CAPABILITY_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For indictment and capability messages, we've already gone
03831d35f7499c87d51205817c93e9a8d42c4baestevel * through the taskq, so we can call the mailbox routine
03831d35f7499c87d51205817c93e9a8d42c4baestevel * directly. Find the symbol for the routine that sends
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the mailbox msg
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_len = (int)msg_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_buf = (caddr_t)kmem_zalloc(msg_size,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* FALLTHRU */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_INDICTMENT_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_INDICTMENT2_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((*sg_ecc_mbox_func)(msgp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_DIMM_SID_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_len = sizeof (plat_dimm_sid_board_data_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgp->ecc_resp.msg_buf = (caddr_t)kmem_zalloc(
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (plat_dimm_sid_board_data_t), sleep_flag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((*sg_ecc_mbox_func)(msgp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * m is redundant on serengeti as the multiplier is always 4
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_make_fru_cpuid(int sb, int m, int proc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (MAKE_CPUID(sb, proc));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board number for a given proc
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_make_fru_boardnum(int proc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (SG_CPU_BD_PORTID_TO_BD_NUM(proc));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelcpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t signature = CPU_SIG_BLD(sig, state, sub_state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sig_state_t current_sgn;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_write_ptr == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the IOSRAM write pointer isn't set, we won't be able
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to write signatures to ANYTHING, so we may as well just
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write out an error message (if desired) and exit this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * routine now...
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DCMNERR(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cpu_sgn_update: iosram_write() not found;"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " cannot write signature 0x%x for CPU(s) or domain\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel signature);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Differentiate a panic reboot from a non-panic reboot in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * setting of the substate of the signature.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the new substate is REBOOT and we're rebooting due to a panic,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then set the new substate to a special value indicating a panic
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reboot, SIGSUBST_PANIC_REBOOT.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A panic reboot is detected by a current (previous) domain signature
03831d35f7499c87d51205817c93e9a8d42c4baestevel * state of SIGST_EXIT, and a new signature substate of SIGSUBST_REBOOT.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The domain signature state SIGST_EXIT is used as the panic flow
03831d35f7499c87d51205817c93e9a8d42c4baestevel * progresses.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * At the end of the panic flow, the reboot occurs but we should now
03831d35f7499c87d51205817c93e9a8d42c4baestevel * one that was involuntary, something that may be quite useful to know
03831d35f7499c87d51205817c93e9a8d42c4baestevel * at OBP level.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sub_state == SIGSUBST_REBOOT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_read_ptr == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DCMNERR(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cpu_sgn_update: iosram_read() not found;"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " could not check current domain signature\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) (*iosram_read_ptr)(SBBC_SIGBLCK_KEY,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje SG_SGNBLK_DOMAINSIG_OFFSET,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje (char *)&current_sgn, sizeof (current_sgn));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (current_sgn.state_t.state == SIGST_EXIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel signature = CPU_SIG_BLD(sig, state,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje SIGSUBST_PANIC_REBOOT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cpuid == -1 indicates that the operation applies to all cpus.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpuid >= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje SG_SGNBLK_CPUSIG_OFFSET(cpuid), (char *)&signature,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje sizeof (signature));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < NCPU; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[i] == NULL || !(cpu[i]->cpu_flags &
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje (CPU_EXISTS|CPU_QUIESCED))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje SG_SGNBLK_CPUSIG_OFFSET(i), (char *)&signature,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje sizeof (signature));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (state == SIGST_OFFLINE || state == SIGST_DETACHED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje SG_SGNBLK_DOMAINSIG_OFFSET, (char *)&signature,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje sizeof (signature));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelstartup_platform(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
575a742678105d588b7c8e1653b57a7e3d78440bpt /* set per-platform constants for mutex backoff */
575a742678105d588b7c8e1653b57a7e3d78440bpt mutex_backoff_base = 1;
575a742678105d588b7c8e1653b57a7e3d78440bpt mutex_cap_factor = 32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A routine to convert a number (represented as a string) to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the integer value it represents.
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
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelstrtoi(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
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the three parts of the Serengeti PROM version.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Used for feature readiness tests.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return 0 if version extracted successfully, -1 otherwise.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsg_get_prom_version(int *sysp, int *intfp, int *bldp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int plen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char vers[512];
03831d35f7499c87d51205817c93e9a8d42c4baestevel static pnode_t node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static char version[] = "version";
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *verp, *ep;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = prom_finddevice("/openprom");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (node == OBP_BADNODE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel plen = prom_getproplen(node, version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (plen <= 0 || plen >= sizeof (vers))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) prom_getprop(node, version, vers);
03831d35f7499c87d51205817c93e9a8d42c4baestevel vers[plen] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Make sure it's an OBP flashprom */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (vers[0] != 'O' && vers[1] != 'B' && vers[2] != 'P') {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sg_get_prom_version: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "unknown <version> string in </openprom>\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel verp = &vers[4];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *sysp = strtoi(verp, &ep);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ep == verp || *ep != '.')
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel verp = ep + 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *intfp = strtoi(verp, &ep);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ep == verp || *ep != '.')
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel verp = ep + 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *bldp = strtoi(verp, &ep);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ep == verp || (*ep != '\0' && !isspace(*ep)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return 0 if system board Dynamic Reconfiguration
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is supported by the firmware, -1 otherwise.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsg_prom_sb_dr_check(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel static int prom_res = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_res == 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int sys, intf, bld;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = sg_get_prom_version(&sys, &intf, &bld);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == 0 && sys == 5 &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (intf >= 12 || (intf == 11 && bld >= 200))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_res = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_res = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (prom_res);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return 0 if cPCI Dynamic Reconfiguration
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is supported by the firmware, -1 otherwise.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsg_prom_cpci_dr_check(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The version check is currently the same as for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * system boards. Since the two DR sub-systems are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * independent, this could change.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (sg_prom_sb_dr_check());
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * KDI functions - used by the in-situ kernel debugger (kmdb) to perform
03831d35f7499c87d51205817c93e9a8d42c4baestevel * platform-specific operations. These functions execute when the world is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * stopped, and as such cannot make any blocking calls, hold locks, etc.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * promif functions are a special case, and may be used.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Our implementation of this KDI op updates the CPU signature in the system
03831d35f7499c87d51205817c93e9a8d42c4baestevel * controller. Note that we set the signature to OBP_SIG, rather than DBG_SIG.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The Forth words we execute will, among other things, transform our OBP_SIG
03831d35f7499c87d51205817c93e9a8d42c4baestevel * into DBG_SIG. They won't function properly if we try to use DBG_SIG.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsg_system_claim(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni lbolt_debug_entry();
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_interpret("sigb-sig! my-sigb-sig!", OBP_SIG, OBP_SIG, 0, 0, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsg_system_release(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_interpret("sigb-sig! my-sigb-sig!", OS_SIG, OS_SIG, 0, 0, 0);
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni lbolt_debug_return();
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsg_console_claim(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) prom_serengeti_set_console_input(SGCN_OBP_STR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsg_console_release(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) prom_serengeti_set_console_input(SGCN_CLNT_STR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelplat_kdi_init(kdi_t *kdi)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel kdi->pkdi_system_claim = sg_system_claim;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kdi->pkdi_system_release = sg_system_release;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kdi->pkdi_console_claim = sg_console_claim;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kdi->pkdi_console_release = sg_console_release;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}