cma_page.c revision 24db46411fd54f70c35b94bb952eb7ba040e43b4
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CDDL HEADER START
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The contents of this file are subject to the terms of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Common Development and Distribution License (the "License").
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * You may not use this file except in compliance with the License.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * See the License for the specific language governing permissions
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and limitations under the License.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * When distributing Covered Code, include this CDDL HEADER in each
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If applicable, add the following below this CDDL HEADER, with the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fields enclosed by brackets "[]" replaced with your own identifying
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information: Portions Copyright [yyyy] [name of copyright owner]
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CDDL HEADER END
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Use is subject to license terms.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#pragma ident "%Z%%M% %I% %E% SMI"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Page retirement can be an extended process due to the fact that a retirement
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * may not be possible when the original request is made. The kernel will
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * repeatedly attempt to retire a given page, but will not let us know when the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * page has been retired. We therefore have to poll to see if the retirement
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * has been completed. This poll is implemented with a bounded exponential
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * backoff to reduce the burden which we impose upon the system.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * To reduce the burden on fmd in the face of retirement storms, we schedule
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * all retries as a group. In the simplest case, we attempt to retire a single
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * page. When forced to retry, we initially schedule a retry at a configurable
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * interval t. If the retry fails, we schedule another at 2 * t, and so on,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * until t reaches the maximum interval (also configurable). Future retries
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * for that page will occur with t equal to the maximum interval value. We
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * will never give up on a retirement.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * With multiple retirements, the situation gets slightly more complicated. As
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * indicated above, we schedule retries as a group. We don't want to deny new
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * pages their short retry intervals, so we'll (re)set the retry interval to the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * value appropriate for the newest page.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorcma_page_cmd(fmd_hdl_t *hdl, int cmd, nvlist_t *nvl)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((errno = nvlist_size(nvl, &fmrisz, NV_ENCODE_NATIVE)) != 0 ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (fmribuf = fmd_hdl_alloc(hdl, fmrisz, FMD_SLEEP)) == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((errno = nvlist_pack(nvl, &fmribuf, &fmrisz,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (-1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Retire the specified ASRU, referring to a memory page by PA or by DIMM
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * offset (i.e. the encoded coordinates internal bank, row, and column).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * In the initial FMA implementation, fault.memory.page exported an ASRU
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * with an explicit physical address, which is valid at the initial time of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * diagnosis but may not be later following DR, DIMM removal, or interleave
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * changes. On SPARC, this issue was solved by exporting the DIMM offset
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and pushing the entire FMRI to the platform memory controller through
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * /dev/mem so it can derive the current PA from the DIMM and offset.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * On x64, we also use DIMM and offset, but the mem:/// unum string is an
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * encoded hc:/// FMRI that is then used by the x64 memory controller driver.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * At some point these three approaches need to be rationalized: all platforms
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * should use the same scheme, either with decoding in the kernel or decoding
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * in userland (i.e. with a libtopo method to compute and update the PA).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorcma_page_retire(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *asru, const char *uuid)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* It should already be expanded, but we'll do it again anyway */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fmd_hdl_debug(hdl, "failed to expand page asru\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (nvlist_lookup_uint64(asru, FM_FMRI_MEM_PHYSADDR, &pageaddr) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fmd_hdl_debug(hdl, "suppressed retire of page %llx\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fmd_hdl_debug(hdl, "page retire overtaken by events\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the unum is an hc fmri string expand it to an fmri and include
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that in a modified asru nvlist.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (nvlist_lookup_string(asru, FM_FMRI_MEM_UNUM, &unumstr) == 0 &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor struct topo_hdl *thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (topo_fmri_str2nvl(thp, unumstr, &unumfmri, &err) != 0) {
return (CMA_RA_FAILURE);
return (CMA_RA_FAILURE);
unumfmri) != 0) {
return (CMA_RA_FAILURE);
if (asrucp)
return (CMA_RA_SUCCESS);
if (asrucp)
return (CMA_RA_SUCCESS);
return (CMA_RA_FAILURE);
if (asrucp) {
return (CMA_RA_FAILURE);