Module Name: src
Committed By: uebayasi
Date: Wed Jul 7 14:29:39 UTC 2010
Modified Files:
src/sys/miscfs/genfs [uebayasi-xip]: genfs_io.c
src/sys/uvm [uebayasi-xip]: uvm_fault.c uvm_page.c uvm_page.h
Log Message:
To simplify things, revert global vm_page_md hash and allocate struct
vm_page [] for XIP physical segments.
To generate a diff of this commit:
cvs rdiff -u -r1.36.2.11 -r1.36.2.12 src/sys/miscfs/genfs/genfs_io.c
cvs rdiff -u -r1.166.2.7 -r1.166.2.8 src/sys/uvm/uvm_fault.c
cvs rdiff -u -r1.153.2.39 -r1.153.2.40 src/sys/uvm/uvm_page.c
cvs rdiff -u -r1.59.2.22 -r1.59.2.23 src/sys/uvm/uvm_page.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/miscfs/genfs/genfs_io.c
diff -u src/sys/miscfs/genfs/genfs_io.c:1.36.2.11 src/sys/miscfs/genfs/genfs_io.c:1.36.2.12
--- src/sys/miscfs/genfs/genfs_io.c:1.36.2.11 Tue Jul 6 07:20:27 2010
+++ src/sys/miscfs/genfs/genfs_io.c Wed Jul 7 14:29:39 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: genfs_io.c,v 1.36.2.11 2010/07/06 07:20:27 uebayasi Exp $ */
+/* $NetBSD: genfs_io.c,v 1.36.2.12 2010/07/07 14:29:39 uebayasi Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.36.2.11 2010/07/06 07:20:27 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.36.2.12 2010/07/07 14:29:39 uebayasi Exp $");
#include "opt_direct_page.h"
#include "opt_xip.h"
@@ -828,11 +828,18 @@
KASSERT(error == 0);
UVMHIST_LOG(ubchist, "xip VOP_BMAP: lbn=%ld blkno=%ld run=%d", (long)lbn, (long)blkno, run, 0);
+ /*
+ * XIP page metadata assignment
+ * - Unallocated block is redirected to the dedicated zero'ed
+ * page.
+ * - Assume that struct vm_page *[] array of this segment is
+ * allocated and linearly ordered by physical address.
+ */
if (blkno < 0) {
static ONCE_DECL(xip_zero_page_inited);
RUN_ONCE(&xip_zero_page_inited, xip_zero_page_init);
- phys_addr = xip_zero_page->phys_addr;
+ pps[i] = xip_zero_page;
} else {
struct vm_physseg *seg;
@@ -842,10 +849,12 @@
phys_addr = pmap_phys_address(seg->start) +
(blkno << dev_bshift) +
(off - (lbn << fs_bshift));
+ pps[i] = seg->pgs +
+ ((phys_addr >> PAGE_SHIFT) - seg->start);
+ KASSERT(pps[i]->phys_addr == phys_addr);
+ KASSERT((pps[i]->flags & PG_DIRECT) != 0);
}
- pps[i] = uvm_phys_to_vm_page_direct(phys_addr);
-
UVMHIST_LOG(ubchist, "xip pgs %d => phys_addr=0x%lx (%p)",
i,
(long)phys_addr,
Index: src/sys/uvm/uvm_fault.c
diff -u src/sys/uvm/uvm_fault.c:1.166.2.7 src/sys/uvm/uvm_fault.c:1.166.2.8
--- src/sys/uvm/uvm_fault.c:1.166.2.7 Wed Jun 9 15:29:58 2010
+++ src/sys/uvm/uvm_fault.c Wed Jul 7 14:29:37 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_fault.c,v 1.166.2.7 2010/06/09 15:29:58 uebayasi Exp $ */
+/* $NetBSD: uvm_fault.c,v 1.166.2.8 2010/07/07 14:29:37 uebayasi Exp $ */
/*
*
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.166.2.7 2010/06/09 15:29:58 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.166.2.8 2010/07/07 14:29:37 uebayasi Exp $");
#include "opt_uvmhist.h"
#include "opt_direct_page.h"
@@ -1657,9 +1657,9 @@
* - at this point uobjpage could be PG_WANTED (handle later)
*/
- KASSERT(uvm_pageisdirect_p(uobjpage) || uobj == NULL ||
+ KASSERT(uobj == NULL || uvm_pageisdirect_p(uobjpage) ||
uobj == uobjpage->uobject);
- KASSERT(uvm_pageisdirect_p(uobjpage) || uobj == NULL ||
+ KASSERT(uobj == NULL || uvm_pageisdirect_p(uobjpage) ||
!UVM_OBJ_IS_CLEAN(uobjpage->uobject) ||
(uobjpage->flags & PG_CLEAN) != 0);
Index: src/sys/uvm/uvm_page.c
diff -u src/sys/uvm/uvm_page.c:1.153.2.39 src/sys/uvm/uvm_page.c:1.153.2.40
--- src/sys/uvm/uvm_page.c:1.153.2.39 Mon May 31 13:26:38 2010
+++ src/sys/uvm/uvm_page.c Wed Jul 7 14:29:38 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_page.c,v 1.153.2.39 2010/05/31 13:26:38 uebayasi Exp $ */
+/* $NetBSD: uvm_page.c,v 1.153.2.40 2010/07/07 14:29:38 uebayasi Exp $ */
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.153.2.39 2010/05/31 13:26:38 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.153.2.40 2010/07/07 14:29:38 uebayasi Exp $");
#include "opt_ddb.h"
#include "opt_uvmhist.h"
@@ -195,10 +195,6 @@
static void uvm_pageinsert(struct uvm_object *, struct vm_page *);
static void uvm_pageremove(struct uvm_object *, struct vm_page *);
-#ifdef DIRECT_PAGE
-static void vm_page_direct_mdpage_insert(paddr_t);
-static void vm_page_direct_mdpage_remove(paddr_t);
-#endif
/*
* per-object tree of pages
@@ -780,7 +776,7 @@
static struct vm_physseg *
uvm_page_physload_common(struct vm_physseg_freelist * const,
struct vm_physseg **, int,
- const paddr_t, const paddr_t, const paddr_t, const paddr_t);
+ const paddr_t, const paddr_t);
static void
uvm_page_physunload_common(struct vm_physseg_freelist *,
struct vm_physseg **, struct vm_physseg *);
@@ -804,7 +800,7 @@
panic("uvm_page_physload: bad free list %d", free_list);
seg = uvm_page_physload_common(&vm_physmem_freelist, vm_physmem_ptrs,
- vm_nphysmem, start, end, avail_start, avail_end);
+ vm_nphysmem, start, end);
KASSERT(seg != NULL);
seg->avail_start = avail_start;
@@ -848,15 +844,38 @@
paddr_t avail_end, int prot, int flags)
{
struct vm_physseg *seg;
+ int i;
seg = uvm_page_physload_common(&vm_physdev_freelist, vm_physdev_ptrs,
- vm_nphysdev, start, end, avail_start, avail_end);
+ vm_nphysdev, start, end);
KASSERT(seg != NULL);
seg->prot = prot;
seg->flags = flags; /* XXXUEBS BUS_SPACE_MAP_* */
- for (paddr_t pf = start; pf < end; pf++)
- vm_page_direct_mdpage_insert(pf);
+
+ /*
+ * XIP page metadata
+ * - Only "phys_addr" and "vm_page_md" (== "PV" management) are used.
+ * - No "pageq" operation is done.
+ */
+ seg->pgs = kmem_zalloc(sizeof(struct vm_page) * (end - start),
+ KM_SLEEP);
+ KASSERT(seg->pgs != NULL);
+ seg->endpg = seg->pgs + (end - start);
+ seg->start = start;
+ seg->end = end;
+
+ for (i = 0; i < end - start; i++) {
+ struct vm_page *pg = seg->pgs + i;
+ paddr_t paddr = (start + i) << PAGE_SHIFT;
+
+ pg->phys_addr = paddr;
+ pg->flags |= PG_DIRECT;
+#ifdef __HAVE_VM_PAGE_MD
+ VM_MDPAGE_INIT(&pg->mdpage, paddr);
+#endif
+ }
+
vm_nphysdev++;
return seg;
}
@@ -866,8 +885,7 @@
{
struct vm_physseg *seg = cookie;
- for (paddr_t pf = seg->start; pf < seg->end; pf++)
- vm_page_direct_mdpage_remove(pf);
+ kmem_free(seg->pgs, sizeof(struct vm_page) * (seg->end - seg->start));
uvm_page_physunload_common(&vm_physdev_freelist, vm_physdev_ptrs, seg);
vm_nphysdev--;
}
@@ -876,8 +894,7 @@
static struct vm_physseg *
uvm_page_physload_common(struct vm_physseg_freelist *freelist,
struct vm_physseg **segs, int nsegs,
- const paddr_t start, const paddr_t end,
- const paddr_t avail_start, const paddr_t avail_end)
+ const paddr_t start, const paddr_t end)
{
struct vm_physseg *ps;
static int uvm_page_physseg_inited;
@@ -1156,52 +1173,13 @@
}
}
-
-#ifdef DIRECT_PAGE
-/*
- * Device pages don't have struct vm_page objects for various reasons:
- *
- * - Device pages are volatile; not paging involved. Which means we have
- * much less state information to keep for each page.
- *
- * - Volatile, directly memory-mappable devices (framebuffers, audio devices,
- * etc.) only need physical address and attribute (protection and some
- * accelaration specific to physical bus) common to all the pages.
- * Allocating vm_page objects to keep such informations is wasteful.
- *
- * - Per-page MD information is only used for XIP vnodes' copy-on-write from
- * a device page to anon.
- */
-
-/* Assume struct vm_page * is aligned to 4 bytes. */
-/* XXXUEBS Consider to improve this. */
-#define VM_PAGE_DIRECT_MAGIC 0x2
-#define VM_PAGE_DIRECT_MAGIC_MASK 0x3
-#define VM_PAGE_DIRECT_MAGIC_SHIFT 2
-
-struct vm_page *
-uvm_phys_to_vm_page_direct(paddr_t pa)
-{
- paddr_t pf = pa >> PAGE_SHIFT;
- uintptr_t cookie = pf << VM_PAGE_DIRECT_MAGIC_SHIFT;
- return (void *)(cookie | VM_PAGE_DIRECT_MAGIC);
-}
-
-static inline paddr_t
-VM_PAGE_DIRECT_TO_PHYS(const struct vm_page *pg)
-{
- uintptr_t cookie = (uintptr_t)pg & ~VM_PAGE_DIRECT_MAGIC_MASK;
- paddr_t pf = cookie >> VM_PAGE_DIRECT_MAGIC_SHIFT;
- return pf << PAGE_SHIFT;
-}
-
bool
uvm_pageisdirect_p(const struct vm_page *pg)
{
- return ((uintptr_t)pg & VM_PAGE_DIRECT_MAGIC_MASK) == VM_PAGE_DIRECT_MAGIC;
+ KASSERT(pg != NULL);
+ return (pg->flags & PG_DIRECT) != 0;
}
-#endif
/*
@@ -1219,7 +1197,7 @@
#ifdef DIRECT_PAGE
psi = vm_physseg_find_direct(pf, &off);
if (psi != -1)
- return(uvm_phys_to_vm_page_direct(pa));
+ return(&vm_physdev_ptrs[psi]->pgs[off]);
#endif
psi = vm_physseg_find(pf, &off);
if (psi != -1)
@@ -1231,142 +1209,9 @@
uvm_vm_page_to_phys(const struct vm_page *pg)
{
-#ifdef DIRECT_PAGE
- if (uvm_pageisdirect_p(pg)) {
- return VM_PAGE_DIRECT_TO_PHYS(pg);
- }
-#endif
return pg->phys_addr;
}
-
-#ifdef __HAVE_VM_PAGE_MD
-#ifdef XIP
-/*
- * Device page's mdpage lookup.
- *
- * - Needed when promoting an XIP vnode page and invalidating its old mapping.
- *
- * - Hashing code is based on sys/arch/x86/x86/pmap.c.
- *
- * XXX Consider to allocate slots on-demand.
- */
-
-static struct vm_page_md *vm_page_direct_mdpage_lookup(struct vm_page *);
-
-struct vm_page_md *
-uvm_vm_page_to_md(struct vm_page *pg)
-{
-
- return uvm_pageisdirect_p(pg) ?
- vm_page_direct_mdpage_lookup(pg) : &pg->mdpage;
-}
-
-struct vm_page_direct_mdpage_entry {
- struct vm_page_md mde_mdpage;
- SLIST_ENTRY(vm_page_direct_mdpage_entry) mde_hash;
- paddr_t mde_pf;
-};
-
-/*
- * These can be optimized depending on the size of XIP'ed executables' .data
- * segments. If page size is 4K and .data is 1M, .data spans across 256
- * pages. Considering these pages' physical addresses are continuous, linear
- * hash should suffice.
- */
-#define MDPG_HASH_SIZE 256 /* XXX */
-#define MDPG_HASH_LOCK_CNT 4 /* XXX */
-
-struct vm_page_direct_mdpage {
- kmutex_t locks[MDPG_HASH_LOCK_CNT];
- struct vm_page_direct_mdpage_head {
- SLIST_HEAD(, vm_page_direct_mdpage_entry) list;
- } heads[MDPG_HASH_SIZE];
-};
-
-/* Global for now. Consider to make this per-vm_physseg. */
-struct vm_page_direct_mdpage vm_page_direct_mdpage;
-
-static struct vm_page_direct_mdpage_head *
-vm_page_direct_mdpage_head(u_int hash)
-{
-
- return &vm_page_direct_mdpage.heads[hash % MDPG_HASH_SIZE];
-}
-
-static kmutex_t *
-vm_page_direct_mdpage_lock(u_int hash)
-{
-
- return &vm_page_direct_mdpage.locks[hash % MDPG_HASH_LOCK_CNT];
-}
-
-static void
-vm_page_direct_mdpage_insert(paddr_t pf)
-{
- u_int hash = (u_int)pf;
- kmutex_t *lock = vm_page_direct_mdpage_lock(hash);
- struct vm_page_direct_mdpage_head *head = vm_page_direct_mdpage_head(hash);
-
- struct vm_page_direct_mdpage_entry *mde = kmem_zalloc(sizeof(*mde), KM_SLEEP);
-
- VM_MDPAGE_INIT(&mde->mde_mdpage, pf << PAGE_SHIFT);
- mde->mde_pf = pf;
-
- mutex_spin_enter(lock);
- SLIST_INSERT_HEAD(&head->list, mde, mde_hash);
- mutex_spin_exit(lock);
-}
-
-static void
-vm_page_direct_mdpage_remove(paddr_t pf)
-{
- u_int hash = (u_int)pf;
- kmutex_t *lock = vm_page_direct_mdpage_lock(hash);
- struct vm_page_direct_mdpage_head *head = vm_page_direct_mdpage_head(hash);
-
- struct vm_page_direct_mdpage_entry *mde;
- struct vm_page_direct_mdpage_entry *prev = NULL;
-
- mutex_spin_enter(lock);
- SLIST_FOREACH(mde, &head->list, mde_hash) {
- if (mde->mde_pf == pf) {
- if (prev != NULL) {
- SLIST_REMOVE_AFTER(prev, mde_hash);
- } else {
- SLIST_REMOVE_HEAD(&head->list, mde_hash);
- }
- break;
- }
- prev = mde;
- }
- mutex_spin_exit(lock);
- KASSERT(mde != NULL);
- kmem_free(mde, sizeof(*mde));
-}
-
-static struct vm_page_md *
-vm_page_direct_mdpage_lookup(struct vm_page *pg)
-{
- paddr_t pf = VM_PAGE_DIRECT_TO_PHYS(pg) >> PAGE_SHIFT;
- u_int hash = (u_int)pf;
- kmutex_t *lock = vm_page_direct_mdpage_lock(hash);
- struct vm_page_direct_mdpage_head *head = vm_page_direct_mdpage_head(hash);
-
- struct vm_page_direct_mdpage_entry *mde = NULL;
-
- mutex_spin_enter(lock);
- SLIST_FOREACH(mde, &head->list, mde_hash)
- if (mde->mde_pf == pf)
- break;
- mutex_spin_exit(lock);
- KASSERT(mde != NULL);
- return &mde->mde_mdpage;
-}
-#endif
-#endif
-
-
/*
* uvm_page_recolor: Recolor the pages if the new bucket count is
* larger than the old one.
Index: src/sys/uvm/uvm_page.h
diff -u src/sys/uvm/uvm_page.h:1.59.2.22 src/sys/uvm/uvm_page.h:1.59.2.23
--- src/sys/uvm/uvm_page.h:1.59.2.22 Mon May 31 13:26:38 2010
+++ src/sys/uvm/uvm_page.h Wed Jul 7 14:29:38 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_page.h,v 1.59.2.22 2010/05/31 13:26:38 uebayasi Exp $ */
+/* $NetBSD: uvm_page.h,v 1.59.2.23 2010/07/07 14:29:38 uebayasi Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -181,12 +181,13 @@
#define PG_FAKE 0x0040 /* page is not yet initialized */
#define PG_RDONLY 0x0080 /* page must be mapped read-only */
#define PG_ZERO 0x0100 /* page is pre-zero'd */
+#define PG_DIRECT 0x0200 /* page is direct vnode data */
#define PG_PAGER1 0x1000 /* pager-specific flag */
#define UVM_PGFLAGBITS \
"\20\1BUSY\2WANTED\3TABLED\4CLEAN\5PAGEOUT\6RELEASED\7FAKE\10RDONLY" \
- "\11ZERO\15PAGER1"
+ "\11ZERO\12DIRECT\15PAGER1"
#define PQ_FREE 0x0001 /* page is on free list */
#define PQ_ANON 0x0002 /* page is part of an anon, rather
@@ -304,11 +305,7 @@
void uvm_pagewire(struct vm_page *);
void uvm_pagezero(struct vm_page *);
bool uvm_pageismanaged(paddr_t);
-#ifdef DIRECT_PAGE
bool uvm_pageisdirect_p(const struct vm_page *);
-#else
-#define uvm_pageisdirect_p(x) false
-#endif
int uvm_page_lookup_freelist(struct vm_page *);
@@ -317,8 +314,6 @@
paddr_t uvm_vm_page_to_phys(const struct vm_page *);
#ifdef XIP
int vm_physseg_find_direct(paddr_t, int *);
-struct vm_page *uvm_phys_to_vm_page_direct(paddr_t);
-paddr_t uvm_vm_page_to_phys_direct(const struct vm_page *);
#endif
/*
@@ -330,12 +325,7 @@
#define VM_PAGE_TO_PHYS(entry) uvm_vm_page_to_phys(entry)
#ifdef __HAVE_VM_PAGE_MD
-#ifndef XIP
#define VM_PAGE_TO_MD(pg) (&(pg)->mdpage)
-#else
-struct vm_page_md *uvm_vm_page_to_md(struct vm_page *);
-#define VM_PAGE_TO_MD(pg) uvm_vm_page_to_md(pg)
-#endif
#endif
/*