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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Support routines for managing per-page state.
36 #include <cmd_dp_page.h>
41 #include <fm/fmd_api.h>
42 #include <sys/fm/protocol.h>
45 page_write(fmd_hdl_t
*hdl
, cmd_page_t
*page
)
47 fmd_buf_write(hdl
, NULL
, page
->page_bufname
, page
,
48 sizeof (cmd_page_pers_t
));
52 cmd_page_free(fmd_hdl_t
*hdl
, cmd_page_t
*page
, int destroy
)
54 cmd_case_t
*cc
= &page
->page_case
;
56 if (cc
->cc_cp
!= NULL
)
57 cmd_case_fini(hdl
, cc
->cc_cp
, destroy
);
59 if (cc
->cc_serdnm
!= NULL
) {
60 if (fmd_serd_exists(hdl
, cc
->cc_serdnm
) && destroy
)
61 fmd_serd_destroy(hdl
, cc
->cc_serdnm
);
62 fmd_hdl_strfree(hdl
, cc
->cc_serdnm
);
66 fmd_buf_destroy(hdl
, NULL
, page
->page_bufname
);
68 cmd_fmri_fini(hdl
, &page
->page_asru
, destroy
);
70 cmd_list_delete(&cmd
.cmd_pages
, page
);
71 fmd_hdl_free(hdl
, page
, sizeof (cmd_page_t
));
75 cmd_page_destroy(fmd_hdl_t
*hdl
, cmd_page_t
*page
)
77 cmd_page_free(hdl
, page
, FMD_B_TRUE
);
81 page_lookup_by_physaddr(uint64_t pa
)
85 for (page
= cmd_list_next(&cmd
.cmd_pages
); page
!= NULL
;
86 page
= cmd_list_next(page
)) {
87 if (page
->page_physbase
== pa
)
95 cmd_page_create(fmd_hdl_t
*hdl
, nvlist_t
*modasru
, uint64_t pa
)
100 pa
= pa
& cmd
.cmd_pagemask
;
102 fmd_hdl_debug(hdl
, "page_lookup: creating new page for %llx\n",
104 CMD_STAT_BUMP(page_creat
);
106 page
= fmd_hdl_zalloc(hdl
, sizeof (cmd_page_t
), FMD_SLEEP
);
107 page
->page_nodetype
= CMD_NT_PAGE
;
108 page
->page_version
= CMD_PAGE_VERSION
;
109 page
->page_physbase
= pa
;
111 cmd_bufname(page
->page_bufname
, sizeof (page
->page_bufname
),
112 "page_%llx", (u_longlong_t
)pa
);
114 if ((errno
= nvlist_dup(modasru
, &asru
, 0)) != 0 ||
115 (errno
= nvlist_add_uint64(asru
, FM_FMRI_MEM_PHYSADDR
,
116 page
->page_physbase
)) != 0 ||
117 (errno
= fmd_nvl_fmri_expand(hdl
, asru
)) != 0)
118 fmd_hdl_abort(hdl
, "failed to build page fmri");
120 cmd_fmri_init(hdl
, &page
->page_asru
, asru
, "page_asru_%llx",
125 cmd_list_append(&cmd
.cmd_pages
, page
);
126 page_write(hdl
, page
);
132 cmd_page_lookup(uint64_t pa
)
134 pa
= pa
& cmd
.cmd_pagemask
;
136 return (page_lookup_by_physaddr(pa
));
140 page_v0tov1(fmd_hdl_t
*hdl
, cmd_page_0_t
*old
, size_t oldsz
)
144 if (oldsz
!= sizeof (cmd_page_0_t
)) {
145 fmd_hdl_abort(hdl
, "size of state doesn't match size of "
146 "version 0 state (%u bytes).\n", sizeof (cmd_page_0_t
));
149 new = fmd_hdl_zalloc(hdl
, sizeof (cmd_page_t
), FMD_SLEEP
);
150 new->page_header
= old
->page0_header
;
151 new->page_version
= CMD_PAGE_VERSION
;
152 new->page_asru
= old
->page0_asru
;
154 fmd_hdl_free(hdl
, old
, oldsz
);
159 page_wrapv1(fmd_hdl_t
*hdl
, cmd_page_pers_t
*pers
, size_t psz
)
163 if (psz
!= sizeof (cmd_page_pers_t
)) {
164 fmd_hdl_abort(hdl
, "size of state doesn't match size of "
165 "version 1 state (%u bytes).\n", sizeof (cmd_page_pers_t
));
168 page
= fmd_hdl_zalloc(hdl
, sizeof (cmd_page_t
), FMD_SLEEP
);
169 bcopy(pers
, page
, sizeof (cmd_page_pers_t
));
170 fmd_hdl_free(hdl
, pers
, psz
);
175 cmd_page_restore(fmd_hdl_t
*hdl
, fmd_case_t
*cp
, cmd_case_ptr_t
*ptr
)
179 for (page
= cmd_list_next(&cmd
.cmd_pages
); page
!= NULL
;
180 page
= cmd_list_next(page
)) {
181 if (strcmp(page
->page_bufname
, ptr
->ptr_name
) == 0)
189 fmd_hdl_debug(hdl
, "restoring page from %s\n", ptr
->ptr_name
);
191 if ((pagesz
= fmd_buf_size(hdl
, NULL
, ptr
->ptr_name
)) == 0) {
192 if (fmd_case_solved(hdl
, cp
) ||
193 fmd_case_closed(hdl
, cp
)) {
194 fmd_hdl_debug(hdl
, "page %s from case %s not "
195 "found. Case is already solved or closed\n",
196 ptr
->ptr_name
, fmd_case_uuid(hdl
, cp
));
199 fmd_hdl_abort(hdl
, "page referenced by case %s "
200 "does not exist in saved state\n",
201 fmd_case_uuid(hdl
, cp
));
203 } else if (pagesz
> CMD_PAGE_MAXSIZE
||
204 pagesz
< CMD_PAGE_MINSIZE
) {
205 fmd_hdl_abort(hdl
, "page buffer referenced by case %s "
206 "is out of bounds (is %u bytes, max %u, min %u)\n",
207 fmd_case_uuid(hdl
, cp
), pagesz
,
208 CMD_PAGE_MAXSIZE
, CMD_PAGE_MINSIZE
);
211 if ((page
= cmd_buf_read(hdl
, NULL
, ptr
->ptr_name
,
213 fmd_hdl_abort(hdl
, "failed to read page buf %s",
217 fmd_hdl_debug(hdl
, "found %d in version field\n",
220 if (CMD_PAGE_VERSIONED(page
)) {
221 switch (page
->page_version
) {
222 case CMD_PAGE_VERSION_1
:
223 page
= page_wrapv1(hdl
, (cmd_page_pers_t
*)page
,
227 fmd_hdl_abort(hdl
, "unknown version (found %d) "
228 "for page state referenced by case %s.\n",
229 page
->page_version
, fmd_case_uuid(hdl
, cp
));
233 page
= page_v0tov1(hdl
, (cmd_page_0_t
*)page
, pagesz
);
238 /* CMD_STAT_BUMP(page_migrat); */
239 cmd_page_dirty(hdl
, page
);
242 cmd_fmri_restore(hdl
, &page
->page_asru
);
244 cmd_list_append(&cmd
.cmd_pages
, page
);
247 switch (ptr
->ptr_subtype
) {
248 case BUG_PTR_PAGE_CASE
:
249 fmd_hdl_debug(hdl
, "recovering from out of order page ptr\n");
250 cmd_case_redirect(hdl
, cp
, CMD_PTR_PAGE_CASE
);
252 case CMD_PTR_PAGE_CASE
:
253 cmd_case_restore(hdl
, &page
->page_case
, cp
,
254 cmd_page_serdnm_create(hdl
, "page", page
->page_physbase
));
258 case CMD_PTR_DP_PAGE_DEFER
:
259 page
->page_case
.cc_cp
= cp
;
260 cmd_dp_page_restore(hdl
, page
);
264 fmd_hdl_abort(hdl
, "invalid %s subtype %d\n",
265 ptr
->ptr_name
, ptr
->ptr_subtype
);
274 cmd_page_validate(fmd_hdl_t
*hdl
)
276 cmd_page_t
*page
, *next
;
278 for (page
= cmd_list_next(&cmd
.cmd_pages
); page
!= NULL
; page
= next
) {
279 next
= cmd_list_next(page
);
281 if (fmd_nvl_fmri_unusable(hdl
, page
->page_asru_nvl
)) {
283 if (cmd_dp_page_isdeferred(hdl
, page
) &&
284 fmd_nvl_fmri_present(hdl
, page
->page_asru_nvl
))
287 cmd_page_destroy(hdl
, page
);
293 cmd_page_dirty(fmd_hdl_t
*hdl
, cmd_page_t
*page
)
295 if (fmd_buf_size(hdl
, NULL
, page
->page_bufname
) !=
296 sizeof (cmd_page_pers_t
))
297 fmd_buf_destroy(hdl
, NULL
, page
->page_bufname
);
299 /* No need to rewrite the FMRIs in the page - they don't change */
300 fmd_buf_write(hdl
, NULL
, page
->page_bufname
, &page
->page_pers
,
301 sizeof (cmd_page_pers_t
));
305 cmd_page_fini(fmd_hdl_t
*hdl
)
309 while ((page
= cmd_list_next(&cmd
.cmd_pages
)) != NULL
)
310 cmd_page_free(hdl
, page
, FMD_B_FALSE
);