17bebe46jc/*
27bebe46jc * CDDL HEADER START
37bebe46jc *
47bebe46jc * The contents of this file are subject to the terms of the
57bebe46jc * Common Development and Distribution License (the "License").
67bebe46jc * You may not use this file except in compliance with the License.
77bebe46jc *
87bebe46jc * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97bebe46jc * or http://www.opensolaris.org/os/licensing.
107bebe46jc * See the License for the specific language governing permissions
117bebe46jc * and limitations under the License.
127bebe46jc *
137bebe46jc * When distributing Covered Code, include this CDDL HEADER in each
147bebe46jc * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157bebe46jc * If applicable, add the following below this CDDL HEADER, with the
167bebe46jc * fields enclosed by brackets "[]" replaced with your own identifying
177bebe46jc * information: Portions Copyright [yyyy] [name of copyright owner]
187bebe46jc *
197bebe46jc * CDDL HEADER END
207bebe46jc */
217bebe46jc/*
22a62774dSinanallur Balasubramanian * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237bebe46jc * Use is subject to license terms.
247bebe46jc */
257bebe46jc
267bebe46jc#include <cma.h>
277bebe46jc#include <fcntl.h>
287bebe46jc#include <strings.h>
297bebe46jc#include <unistd.h>
30a62774dSinanallur Balasubramanian#include <errno.h>
317bebe46jc#include <fm/fmd_api.h>
327bebe46jc#include <sys/fm/protocol.h>
337bebe46jc#include <sys/mem_cache.h>
347bebe46jc
357bebe46jcint
367bebe46jc/* ARGSUSED 4 */
377bebe46jccma_cache_way_retire(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *asru,
387bebe46jc    const char *uuid, boolean_t repair)
397bebe46jc{
407bebe46jc	uint_t 		cpuid;
41a62774dSinanallur Balasubramanian	uint32_t 	way;
42a62774dSinanallur Balasubramanian	uint32_t	index;
437bebe46jc	uint16_t	bit = 0;
447bebe46jc	uint8_t		type;
457bebe46jc	cache_info_t    cache_info;
467bebe46jc	int ret, fd;
47a62774dSinanallur Balasubramanian	int	err;
487bebe46jc
497bebe46jc	fmd_hdl_debug(hdl, "cpu cache *line* fault processing\n");
50d69c255jc	fmd_hdl_debug(hdl, "asru %lx\n", asru);
517bebe46jc
527bebe46jc	/*
537bebe46jc	 * This added expansion is needed to cover the situation where a
547bebe46jc	 * cpu fault from the resource cache is replayed at fmd restart,
557bebe46jc	 * and the cpu resource has been remapped or replaced.  The stored
567bebe46jc	 * FMRI is expanded, but may have stale data.
577bebe46jc	 */
587bebe46jc
597bebe46jc	if (fmd_nvl_fmri_expand(hdl, asru) < 0) {
607bebe46jc		fmd_hdl_debug(hdl, "failed to expand cpu asru\n");
617bebe46jc		cma_stats.bad_flts.fmds_value.ui64++;
627bebe46jc		return (CMA_RA_FAILURE);
637bebe46jc	}
647bebe46jc
657bebe46jc	if (nvlist_lookup_uint32(asru, FM_FMRI_CPU_ID, &cpuid) != 0) {
667bebe46jc		fmd_hdl_debug(hdl, "cpu cache fault missing '%s'\n",
677bebe46jc		    FM_FMRI_CPU_ID);
687bebe46jc		cma_stats.bad_flts.fmds_value.ui64++;
697bebe46jc		return (CMA_RA_FAILURE);
707bebe46jc	}
717bebe46jc
727bebe46jc	if (nvlist_lookup_uint32(asru, FM_FMRI_CPU_CACHE_INDEX, &index) != 0) {
737bebe46jc		fmd_hdl_debug(hdl, "cpu cache fault missing '%s'\n",
74a62774dSinanallur Balasubramanian		    FM_FMRI_CPU_CACHE_INDEX);
757bebe46jc		cma_stats.bad_flts.fmds_value.ui64++;
767bebe46jc		return (CMA_RA_FAILURE);
777bebe46jc	}
787bebe46jc
797bebe46jc	if (nvlist_lookup_uint32(asru, FM_FMRI_CPU_CACHE_WAY, &way) != 0) {
807bebe46jc		fmd_hdl_debug(hdl, "cpu cache fault missing '%s'\n",
817bebe46jc		    FM_FMRI_CPU_CACHE_WAY);
827bebe46jc		cma_stats.bad_flts.fmds_value.ui64++;
837bebe46jc		return (CMA_RA_FAILURE);
847bebe46jc	}
857bebe46jc
867bebe46jc	if (nvlist_lookup_uint8(asru, FM_FMRI_CPU_CACHE_TYPE, &type) != 0) {
877bebe46jc		fmd_hdl_debug(hdl, "cpu cache fault missing '%s'\n",
887bebe46jc		    FM_FMRI_CPU_CACHE_TYPE);
897bebe46jc		cma_stats.bad_flts.fmds_value.ui64++;
907bebe46jc		return (CMA_RA_FAILURE);
917bebe46jc	}
927bebe46jc
937bebe46jc	/*
947bebe46jc	 * Tag faults will use it to set the bit to a stable state
957bebe46jc	 */
967bebe46jc
97a62774dSinanallur Balasubramanian	if (nvlist_lookup_uint16(asru, FM_FMRI_CPU_CACHE_BIT, &bit) != 0) {
98a62774dSinanallur Balasubramanian		fmd_hdl_debug(hdl, "cpu cache fault missing '%s'\n",
99a62774dSinanallur Balasubramanian		    FM_FMRI_CPU_CACHE_BIT);
100a62774dSinanallur Balasubramanian		cma_stats.bad_flts.fmds_value.ui64++;
101a62774dSinanallur Balasubramanian		return (CMA_RA_FAILURE);
102a62774dSinanallur Balasubramanian	}
103a62774dSinanallur Balasubramanian	if (repair) {
104a62774dSinanallur Balasubramanian		fmd_hdl_debug(hdl,
105a62774dSinanallur Balasubramanian		    "cpu %d: Unretire for index %d, way %d\n bit %d"
106a62774dSinanallur Balasubramanian		    " type 0x%02x is being called now. We will not unretire"
107a62774dSinanallur Balasubramanian		    " cacheline. This message is for information.\n",
108a62774dSinanallur Balasubramanian		    cpuid, index, way, bit, type);
109a62774dSinanallur Balasubramanian		/*
110a62774dSinanallur Balasubramanian		 * The DE will do the actual unretire.
111a62774dSinanallur Balasubramanian		 * The agent is called because the DE informs the fmd
112a62774dSinanallur Balasubramanian		 * that the resource is repaired.
113a62774dSinanallur Balasubramanian		 */
114a62774dSinanallur Balasubramanian		return (CMA_RA_SUCCESS);
115a62774dSinanallur Balasubramanian	}
116a62774dSinanallur Balasubramanian	fmd_hdl_debug(hdl,
117a62774dSinanallur Balasubramanian	    "cpu %d: Retiring index %d, way %d\n bit %d"
118a62774dSinanallur Balasubramanian	    " type 0x%02x", cpuid, index, way, bit, type);
1197bebe46jc	fd = open(mem_cache_device, O_RDWR);
1207bebe46jc	if (fd == -1) {
1217bebe46jc		fmd_hdl_debug(hdl, "Driver open failed\n");
1227bebe46jc		return (CMA_RA_FAILURE);
1237bebe46jc	}
1247bebe46jc	cache_info.cpu_id = cpuid;
1257bebe46jc	cache_info.way = way;
1267bebe46jc	cache_info.bit = bit;
1277bebe46jc	cache_info.index = index;
1287bebe46jc	cache_info.cache = type == FM_FMRI_CPU_CACHE_TYPE_L3 ?
1297bebe46jc	    L3_CACHE_DATA : L2_CACHE_DATA;
1307bebe46jc
131a62774dSinanallur Balasubramanian	ret = ioctl(fd, MEM_CACHE_RETIRE, &cache_info);
132a62774dSinanallur Balasubramanian	/*
133a62774dSinanallur Balasubramanian	 * save errno before we call close.
134a62774dSinanallur Balasubramanian	 * Need errno to display the error if ioctl fails.
135a62774dSinanallur Balasubramanian	 */
136a62774dSinanallur Balasubramanian	err = errno;
137a62774dSinanallur Balasubramanian	(void) close(fd);
1387bebe46jc	if (ret == -1) {
139a62774dSinanallur Balasubramanian		fmd_hdl_debug(hdl, "Driver call failed errno = %d\n", err);
1407bebe46jc		return (CMA_RA_FAILURE);
1417bebe46jc	}
1427bebe46jc	return (CMA_RA_SUCCESS);
1437bebe46jc}
144