summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/vm/page.h
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/vm/page.h')
-rw-r--r--usr/src/uts/common/vm/page.h110
1 files changed, 70 insertions, 40 deletions
diff --git a/usr/src/uts/common/vm/page.h b/usr/src/uts/common/vm/page.h
index 2e4183bdc0..c1db6f1391 100644
--- a/usr/src/uts/common/vm/page.h
+++ b/usr/src/uts/common/vm/page.h
@@ -76,6 +76,12 @@ typedef enum {
*/
#define SE_EXCL_WANTED 0x02
+/*
+ * All page_*lock() requests will be denied unless this flag is set in
+ * the 'es' parameter.
+ */
+#define SE_RETIRED 0x04
+
#endif /* _KERNEL | _KMEMUSER */
typedef int selock_t;
@@ -630,37 +636,6 @@ struct lgrp;
#define PG_LIST_ISCAGE 0x2000
/*
- * Flags for setting the p_toxic flag when a page has errors
- * These flags may be OR'ed into the p_toxic page flag to
- * indicate that error(s) have occurred on a page,
- * (see page_settoxic()). If both PAGE_IS_TOXIC and
- * PAGE_IS_FAILING are set, PAGE_IS_FAILING takes precedence.
- *
- * When an error happens on a page, the trap handler sets
- * PAGE_IS_FAULTY on the page to indicate that an error has been
- * seen on the page. The error could be really a memory error or
- * something else (like a datapath error). When it is determined
- * that it is a memory error, the page is marked as PAGE_IS_TOXIC
- * or PAGE_IS_FAILING depending on the type of error and then
- * retired.
- *
- * We use the page's 'toxic' flag to determine whether the page
- * has just got a single error - PAGE_IS_TOXIC - or is being
- * retired due to multiple soft errors - PAGE_IS_FAILING. In
- * page_free(), a page that has been marked PAGE_IS_FAILING will
- * not be cleaned, it will always be retired. A page marked
- * PAGE_IS_TOXIC is cleaned and is retired only if this attempt at
- * cleaning fails.
- *
- * When a page has been successfully retired, we set PAGE_IS_RETIRED.
- */
-#define PAGE_IS_OK 0x0
-#define PAGE_IS_TOXIC 0x1
-#define PAGE_IS_FAILING 0x2
-#define PAGE_IS_RETIRED 0x4
-#define PAGE_IS_FAULTY 0x8
-
-/*
* Page frame operations.
*/
page_t *page_lookup(struct vnode *, u_offset_t, se_t);
@@ -707,6 +682,7 @@ void page_boot_demote(page_t *);
void page_promote_size(page_t *, uint_t);
void page_list_add_pages(page_t *, int);
void page_list_sub(page_t *, int);
+void page_list_sub_pages(page_t *, uint_t);
void page_list_xfer(page_t *, int, int);
void page_list_break(page_t **, page_t **, size_t);
void page_list_concat(page_t **, page_t **);
@@ -720,6 +696,7 @@ int page_try_reclaim_lock(page_t *, se_t, int);
int page_tryupgrade(page_t *);
void page_downgrade(page_t *);
void page_unlock(page_t *);
+void page_unlock_noretire(page_t *);
void page_lock_delete(page_t *);
int page_pp_lock(page_t *, int, int);
void page_pp_unlock(page_t *, int, int);
@@ -759,19 +736,22 @@ int page_isfree(page_t *);
int page_isref(page_t *);
int page_ismod(page_t *);
int page_release(page_t *, int);
-int page_retire(page_t *, uchar_t);
-int page_istoxic(page_t *);
-int page_isfailing(page_t *);
-int page_isretired(page_t *);
-int page_deteriorating(page_t *);
+void page_retire_init(void);
+int page_retire(uint64_t, uchar_t);
+int page_retire_check(uint64_t, uint64_t *);
+int page_unretire(uint64_t);
+int page_unretire_pp(page_t *, int);
+void page_tryretire(page_t *);
+void page_retire_hunt(void (*)(page_t *));
+void page_retire_mdboot_cb(page_t *);
+void page_clrtoxic(page_t *, uchar_t);
void page_settoxic(page_t *, uchar_t);
-void page_clrtoxic(page_t *);
-void page_clrtoxic_flag(page_t *, uchar_t);
-int page_isfaulty(page_t *);
+
int page_mem_avail(pgcnt_t);
void page_set_props(page_t *, uint_t);
void page_clr_all_props(page_t *);
+int page_clear_lck_cow(page_t *, int);
kmutex_t *page_vnode_mutex(struct vnode *);
kmutex_t *page_se_mutex(struct page *);
@@ -792,6 +772,7 @@ void page_free_replacement_page(page_t *);
int page_relocate_cage(page_t **, page_t **);
int page_try_demote_pages(page_t *);
+int page_try_demote_free_pages(page_t *);
void page_demote_free_pages(page_t *);
struct anon_map;
@@ -879,7 +860,56 @@ int page_szc_user_filtered(size_t);
#define PP_CLRMIGRATE(pp) ((pp)->p_state &= ~P_MIGRATE)
#define PP_CLRSWAP(pp) ((pp)->p_state &= ~P_SWAP)
-
+/*
+ * Flags for page_t p_toxic, for tracking memory hardware errors.
+ *
+ * These flags are OR'ed into p_toxic with page_settoxic() to track which
+ * error(s) have occurred on a given page. The flags are cleared with
+ * page_clrtoxic(). Both page_settoxic() and page_cleartoxic use atomic
+ * primitives to manipulate the p_toxic field so no other locking is needed.
+ *
+ * When an error occurs on a page, p_toxic is set to record the error. The
+ * error could be a memory error or something else (i.e. a datapath). The Page
+ * Retire mechanism does not try to determine the exact cause of the error;
+ * Page Retire rightly leaves that sort of determination to FMA's Diagnostic
+ * Engine (DE).
+ *
+ * Note that, while p_toxic bits can be set without holding any locks, they
+ * should only be cleared while holding the page exclusively locked.
+ *
+ * Pages with PR_UE or PR_FMA flags are retired unconditionally, while pages
+ * with PR_MCE are retired if the system has not retired too many of them.
+ *
+ * A page must be exclusively locked to be retired. Pages can be retired if
+ * they are mapped, modified, or both, as long as they are not marked PR_UE,
+ * since pages with uncorrectable errors cannot be relocated in memory.
+ * Once a page has been successfully retired it is zeroed, attached to the
+ * retired_pages vnode and, finally, PR_RETIRED is set in p_toxic. The other
+ * p_toxic bits are NOT cleared. Pages are not left locked after retiring them
+ * to avoid special case code throughout the kernel; rather, page_*lock() will
+ * fail to lock the page, unless SE_RETIRED is passed as an argument.
+ *
+ * While we have your attention, go take a look at the comments at the
+ * beginning of page_retire.c too.
+ */
+#define PR_OK 0x00 /* no problem */
+#define PR_MCE 0x01 /* page has seen two or more CEs */
+#define PR_UE 0x02 /* page has an unhandled UE */
+#define PR_UE_SCRUBBED 0x04 /* page has seen a UE but was cleaned */
+#define PR_FMA 0x08 /* A DE wants this page retired */
+#define PR_RESV 0x10 /* Reserved for future use */
+#define PR_BUSY 0x20 /* Page retire is in progress */
+#define PR_MSG 0x40 /* message(s) already printed for this page */
+#define PR_RETIRED 0x80 /* This page has been retired */
+
+#define PR_REASONS (PR_UE | PR_MCE | PR_FMA)
+#define PR_TOXIC (PR_UE)
+#define PR_ERRMASK (PR_UE | PR_UE_SCRUBBED | PR_MCE | PR_FMA)
+#define PR_ALLFLAGS (0xFF)
+
+#define PP_RETIRED(pp) ((pp)->p_toxic & PR_RETIRED)
+#define PP_TOXIC(pp) ((pp)->p_toxic & PR_TOXIC)
+#define PP_PR_REQ(pp) (((pp)->p_toxic & PR_REASONS) && !PP_RETIRED(pp))
/*
* kpm large page description.