1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <cma.h> 27 #include <fcntl.h> 28 #include <strings.h> 29 #include <unistd.h> 30 #include <errno.h> 31 #include <fm/fmd_api.h> 32 #include <sys/fm/protocol.h> 33 #include <sys/mem_cache.h> 34 35 int 36 /* ARGSUSED 4 */ 37 cma_cache_way_retire(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *asru, 38 const char *uuid, boolean_t repair) 39 { 40 uint_t cpuid; 41 uint32_t way; 42 uint32_t index; 43 uint16_t bit = 0; 44 uint8_t type; 45 cache_info_t cache_info; 46 int ret, fd; 47 int err; 48 49 fmd_hdl_debug(hdl, "cpu cache *line* fault processing\n"); 50 fmd_hdl_debug(hdl, "asru %lx\n", asru); 51 52 /* 53 * This added expansion is needed to cover the situation where a 54 * cpu fault from the resource cache is replayed at fmd restart, 55 * and the cpu resource has been remapped or replaced. The stored 56 * FMRI is expanded, but may have stale data. 57 */ 58 59 if (fmd_nvl_fmri_expand(hdl, asru) < 0) { 60 fmd_hdl_debug(hdl, "failed to expand cpu asru\n"); 61 cma_stats.bad_flts.fmds_value.ui64++; 62 return (CMA_RA_FAILURE); 63 } 64 65 if (nvlist_lookup_uint32(asru, FM_FMRI_CPU_ID, &cpuid) != 0) { 66 fmd_hdl_debug(hdl, "cpu cache fault missing '%s'\n", 67 FM_FMRI_CPU_ID); 68 cma_stats.bad_flts.fmds_value.ui64++; 69 return (CMA_RA_FAILURE); 70 } 71 72 if (nvlist_lookup_uint32(asru, FM_FMRI_CPU_CACHE_INDEX, &index) != 0) { 73 fmd_hdl_debug(hdl, "cpu cache fault missing '%s'\n", 74 FM_FMRI_CPU_CACHE_INDEX); 75 cma_stats.bad_flts.fmds_value.ui64++; 76 return (CMA_RA_FAILURE); 77 } 78 79 if (nvlist_lookup_uint32(asru, FM_FMRI_CPU_CACHE_WAY, &way) != 0) { 80 fmd_hdl_debug(hdl, "cpu cache fault missing '%s'\n", 81 FM_FMRI_CPU_CACHE_WAY); 82 cma_stats.bad_flts.fmds_value.ui64++; 83 return (CMA_RA_FAILURE); 84 } 85 86 if (nvlist_lookup_uint8(asru, FM_FMRI_CPU_CACHE_TYPE, &type) != 0) { 87 fmd_hdl_debug(hdl, "cpu cache fault missing '%s'\n", 88 FM_FMRI_CPU_CACHE_TYPE); 89 cma_stats.bad_flts.fmds_value.ui64++; 90 return (CMA_RA_FAILURE); 91 } 92 93 /* 94 * Tag faults will use it to set the bit to a stable state 95 */ 96 97 if (nvlist_lookup_uint16(asru, FM_FMRI_CPU_CACHE_BIT, &bit) != 0) { 98 fmd_hdl_debug(hdl, "cpu cache fault missing '%s'\n", 99 FM_FMRI_CPU_CACHE_BIT); 100 cma_stats.bad_flts.fmds_value.ui64++; 101 return (CMA_RA_FAILURE); 102 } 103 if (repair) { 104 fmd_hdl_debug(hdl, 105 "cpu %d: Unretire for index %d, way %d\n bit %d" 106 " type 0x%02x is being called now. We will not unretire" 107 " cacheline. This message is for information.\n", 108 cpuid, index, way, bit, type); 109 /* 110 * The DE will do the actual unretire. 111 * The agent is called because the DE informs the fmd 112 * that the resource is repaired. 113 */ 114 return (CMA_RA_SUCCESS); 115 } 116 fmd_hdl_debug(hdl, 117 "cpu %d: Retiring index %d, way %d\n bit %d" 118 " type 0x%02x", cpuid, index, way, bit, type); 119 fd = open(mem_cache_device, O_RDWR); 120 if (fd == -1) { 121 fmd_hdl_debug(hdl, "Driver open failed\n"); 122 return (CMA_RA_FAILURE); 123 } 124 cache_info.cpu_id = cpuid; 125 cache_info.way = way; 126 cache_info.bit = bit; 127 cache_info.index = index; 128 cache_info.cache = type == FM_FMRI_CPU_CACHE_TYPE_L3 ? 129 L3_CACHE_DATA : L2_CACHE_DATA; 130 131 ret = ioctl(fd, MEM_CACHE_RETIRE, &cache_info); 132 /* 133 * save errno before we call close. 134 * Need errno to display the error if ioctl fails. 135 */ 136 err = errno; 137 (void) close(fd); 138 if (ret == -1) { 139 fmd_hdl_debug(hdl, "Driver call failed errno = %d\n", err); 140 return (CMA_RA_FAILURE); 141 } 142 return (CMA_RA_SUCCESS); 143 } 144