From 41802e2c869ef8b626b1815870a3f7ede579e53f Mon Sep 17 00:00:00 2001 From: kib Date: Sat, 9 Aug 2014 05:00:34 +0000 Subject: [PATCH] Adapt vm_page_aflag_set(PGA_WRITEABLE) to the locking of pmap_enter(PMAP_ENTER_NOSLEEP). The PGA_WRITEABLE flag can be set when either the page is busied, or the owner object is locked. Update comments, move all assertions about page state when PGA_WRITEABLE flag is set, into new helper vm_page_assert_pga_writeable(). Reviewed by: alc Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/vm/vm_page.c | 18 ++++++++++++++++++ sys/vm/vm_page.h | 20 +++++++++----------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 4e30a3f5aded..7ce12d63de48 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -3134,6 +3134,24 @@ vm_page_object_lock_assert(vm_page_t m) if (m->object != NULL && !vm_page_xbusied(m)) VM_OBJECT_ASSERT_WLOCKED(m->object); } + +void +vm_page_assert_pga_writeable(vm_page_t m, uint8_t bits) +{ + + if ((bits & PGA_WRITEABLE) == 0) + return; + + /* + * The PGA_WRITEABLE flag can only be set if the page is + * managed, is exclusively busied or the object is locked. + * Currently, this flag is only set by pmap_enter(). + */ + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("PGA_WRITEABLE on unmanaged page")); + if (!vm_page_xbusied(m)) + VM_OBJECT_ASSERT_LOCKED(m->object); +} #endif #include "opt_ddb.h" diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h index ff61e06adfe5..f12b76c34280 100644 --- a/sys/vm/vm_page.h +++ b/sys/vm/vm_page.h @@ -305,10 +305,10 @@ extern struct mtx_padalign pa_lock[]; * both the MI and MD VM layers. However, kernel loadable modules should not * directly set this flag. They should call vm_page_reference() instead. * - * PGA_WRITEABLE is set exclusively on managed pages by pmap_enter(). When it - * does so, the page must be exclusive busied. The MI VM layer must never - * access this flag directly. Instead, it should call - * pmap_page_is_write_mapped(). + * PGA_WRITEABLE is set exclusively on managed pages by pmap_enter(). + * When it does so, the object must be locked, or the page must be + * exclusive busied. The MI VM layer must never access this flag + * directly. Instead, it should call pmap_page_is_write_mapped(). * * PGA_EXECUTABLE may be set by pmap routines, and indicates that a page has * at least one executable mapping. It is not consumed by the MI VM layer. @@ -533,8 +533,12 @@ void vm_page_lock_assert_KBI(vm_page_t m, int a, const char *file, int line); #ifdef INVARIANTS void vm_page_object_lock_assert(vm_page_t m); #define VM_PAGE_OBJECT_LOCK_ASSERT(m) vm_page_object_lock_assert(m) +void vm_page_assert_pga_writeable(vm_page_t m, uint8_t bits); +#define VM_PAGE_ASSERT_PGA_WRITEABLE(m, bits) \ + vm_page_assert_pga_writeable(m, bits) #else #define VM_PAGE_OBJECT_LOCK_ASSERT(m) (void)0 +#define VM_PAGE_ASSERT_PGA_WRITEABLE(m, bits) (void)0 #endif /* @@ -582,13 +586,7 @@ vm_page_aflag_set(vm_page_t m, uint8_t bits) { uint32_t *addr, val; - /* - * The PGA_WRITEABLE flag can only be set if the page is managed and - * exclusive busied. Currently, this flag is only set by pmap_enter(). - */ - KASSERT((bits & PGA_WRITEABLE) == 0 || - ((m->oflags & VPO_UNMANAGED) == 0 && vm_page_xbusied(m)), - ("vm_page_aflag_set: PGA_WRITEABLE and not exclusive busy")); + VM_PAGE_ASSERT_PGA_WRITEABLE(m, bits); /* * Access the whole 32-bit word containing the aflags field with an