Exemple #1
0
/*ARGSUSED*/
static int
fm_ioctl_page_retire(int cmd, nvlist_t *invl, nvlist_t **onvlp)
{
	uint64_t pa;
	nvlist_t *fmri;
	int err;

	if (is_i86xpv)
		return (ENOTSUP);

	if ((err = nvlist_lookup_nvlist(invl, FM_PAGE_RETIRE_FMRI, &fmri))
	    != 0)
		return (err);

	if ((err = fm_get_paddr(fmri, &pa)) != 0)
		return (err);

	switch (cmd) {
	case FM_IOC_PAGE_STATUS:
		return (page_retire_check(pa, NULL));

	case FM_IOC_PAGE_RETIRE:
		return (page_retire(pa, PR_FMA));

	case FM_IOC_PAGE_UNRETIRE:
		return (page_unretire(pa));
	}

	return (ENOTTY);
}
Exemple #2
0
/*
 * Given a PA, execute the given page retire command on it.
 */
static int
mmioctl_page_retire(int cmd, intptr_t data)
{
	extern int page_retire_test(void);
	uint64_t pa;

	if (copyin((void *)data, &pa, sizeof (uint64_t))) {
		return (EFAULT);
	}

	switch (cmd) {
	case MEM_PAGE_ISRETIRED:
		return (page_retire_check(pa, NULL));

	case MEM_PAGE_UNRETIRE:
		return (page_unretire(pa));

	case MEM_PAGE_RETIRE:
		return (page_retire(pa, PR_FMA));

	case MEM_PAGE_RETIRE_MCE:
		return (page_retire(pa, PR_MCE));

	case MEM_PAGE_RETIRE_UE:
		return (page_retire(pa, PR_UE));

	case MEM_PAGE_GETERRORS:
		{
			uint64_t page_errors;
			int rc = page_retire_check(pa, &page_errors);
			if (copyout(&page_errors, (void *)data,
			    sizeof (uint64_t))) {
				return (EFAULT);
			}
			return (rc);
		}

	case MEM_PAGE_RETIRE_TEST:
		return (page_retire_test());

	}

	return (EINVAL);
}
Exemple #3
0
/*
 * Page retire self-test. For now, it always returns 0.
 */
int
page_retire_test(void)
{
	page_t *first, *pp, *cpp, *cpp2, *lpp;

	/*
	 * Tests the corner case where a large page can't be retired
	 * because one of the constituent pages is locked. We mark
	 * one page to be retired and try to retire it, and mark the
	 * other page to be retired but don't try to retire it, so
	 * that page_unlock() in the failure path will recurse and try
	 * to retire THAT page. This is the worst possible situation
	 * we can get ourselves into.
	 */
	memsegs_lock(0);
	pp = first = page_first();
	do {
		if (pp->p_szc && PP_PAGEROOT(pp) == pp) {
			cpp = pp + 1;
			lpp = PP_ISFREE(pp)? pp : pp + 2;
			cpp2 = pp + 3;
			if (!page_trylock(lpp, pp == lpp? SE_EXCL : SE_SHARED))
				continue;
			if (!page_trylock(cpp, SE_EXCL)) {
				page_unlock(lpp);
				continue;
			}
			page_settoxic(cpp, PR_FMA | PR_BUSY);
			page_settoxic(cpp2, PR_FMA);
			page_tryretire(cpp);	/* will fail */
			page_unlock(lpp);
			(void) page_retire(cpp->p_pagenum, PR_FMA);
			(void) page_retire(cpp2->p_pagenum, PR_FMA);
		}
	} while ((pp = page_next(pp)) != first);
	memsegs_unlock(0);

	return (0);
}