diff options
author | Ian Moffett <ian@osmora.org> | 2024-12-15 22:57:21 -0500 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-12-15 22:57:21 -0500 |
commit | 0bdb884b331c58d33c3ccf29070e2955095a1acc (patch) | |
tree | 1397186ea6ba20e3addc5b98d072d958500ff3af /sys | |
parent | 5504521882fc4f12dc0c25fea57d53c583789492 (diff) |
kernel: vm: Add objects, page struct and pagers
This commit expands the virtual memory subsystem by providing the
initial implementation of virtual memory objects, pager descriptors and
pagers. This change currently implemenents a minimal vnode pager.
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys')
-rw-r--r-- | sys/include/sys/vnode.h | 2 | ||||
-rw-r--r-- | sys/include/vm/vm_obj.h | 58 | ||||
-rw-r--r-- | sys/include/vm/vm_page.h | 65 | ||||
-rw-r--r-- | sys/include/vm/vm_pager.h | 54 | ||||
-rw-r--r-- | sys/include/vm/vm_vnode.h | 43 | ||||
-rw-r--r-- | sys/vm/vm_obj.c | 51 | ||||
-rw-r--r-- | sys/vm/vm_page.c | 106 | ||||
-rw-r--r-- | sys/vm/vm_pager.c | 45 | ||||
-rw-r--r-- | sys/vm/vm_vnode.c | 185 |
9 files changed, 609 insertions, 0 deletions
diff --git a/sys/include/sys/vnode.h b/sys/include/sys/vnode.h index d9f9afe..dfa6a30 100644 --- a/sys/include/sys/vnode.h +++ b/sys/include/sys/vnode.h @@ -34,6 +34,7 @@ #include <sys/queue.h> #include <sys/atomic.h> #include <sys/sio.h> +#include <vm/vm_obj.h> #if defined(_KERNEL) @@ -44,6 +45,7 @@ struct vnode { int flags; void *data; const struct vops *vops; + struct vm_object vobj; uint32_t refcount; TAILQ_ENTRY(vnode) vcache_link; }; diff --git a/sys/include/vm/vm_obj.h b/sys/include/vm/vm_obj.h new file mode 100644 index 0000000..78a7dbb --- /dev/null +++ b/sys/include/vm/vm_obj.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VM_OBJ_H_ +#define _VM_OBJ_H_ + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/spinlock.h> +#include <sys/cdefs.h> +#include <vm/vm_pager.h> +#include <vm/vm_page.h> +#include <vm/vm.h> + +struct vm_object { + struct spinlock lock; + const struct vm_pagerops *pgops; + RBT_HEAD(vm_objtree, vm_page) objt; + vm_prot_t prot; + void *data; + int refs; + int npages; +}; + +int vm_obj_init(struct vm_object *obp, const struct vm_pagerops *pgops, int refs); +void vm_obj_release(struct vm_object *obp); + +/* Object tree stuff */ +int vm_pagecmp(const struct vm_page *a, const struct vm_page *b); +RBT_PROTOTYPE(vm_objtree, vm_page, objt, vm_pagecmp) + +#endif /* !_VM_OBJ_H_ */ diff --git a/sys/include/vm/vm_page.h b/sys/include/vm/vm_page.h new file mode 100644 index 0000000..665431c --- /dev/null +++ b/sys/include/vm/vm_page.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VM_PAGE_H_ +#define _VM_PAGE_H_ + +#include <sys/types.h> +#include <sys/tree.h> +#include <sys/queue.h> +#include <sys/param.h> +#include <sys/spinlock.h> + +struct vm_object; + +/* + * Represents a single virtual memory page. + */ +struct vm_page { + TAILQ_ENTRY(vm_page) pageq; /* Queue data */ + RBT_ENTRY(vm_page) objt; /* Object tree */ + paddr_t phys_addr; /* Physical address of page */ + struct spinlock lock; /* Page lock */ + uint32_t flags; /* Page flags */ + off_t offset; /* Offset into object */ +}; + +/* Page flags */ +#define PG_VALID BIT(0) /* Has to be set to be valid */ +#define PG_CLEAN BIT(1) /* Page has not be written to */ +#define PG_REQ BIT(2) /* Page has been requested by someone */ + +/* Page alloc flags */ +#define PALLOC_ZERO BIT(0) + +struct vm_page *vm_pagelookup(struct vm_object *obj, off_t off); +struct vm_page *vm_pagealloc(struct vm_object *obj, int flags); +void vm_pagefree(struct vm_object *obj, struct vm_page *pg, int flags); + +#endif /* !_VM_PAGE_H_ */ diff --git a/sys/include/vm/vm_pager.h b/sys/include/vm/vm_pager.h new file mode 100644 index 0000000..80a5a6c --- /dev/null +++ b/sys/include/vm/vm_pager.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VM_PAGER_H_ +#define _VM_PAGER_H_ + +#include <sys/types.h> +#include <vm/vm_page.h> +#include <vm/vm_obj.h> + +struct vm_object; + +/* + * Pager operations. + * + * @init: Init pager + * @get: Read a page. + * @put: Write a page. + */ +struct vm_pagerops { + void(*init)(void); + int(*get)(struct vm_object *obp, struct vm_page **pgs, off_t off, size_t len); + int(*put)(struct vm_object *obp, struct vm_page *pgs, size_t len); +}; + +int vm_pager_get(struct vm_object *obp, struct vm_page **pgs, off_t off, size_t len); + +#endif /* !_VM_PAGER_H_ */ diff --git a/sys/include/vm/vm_vnode.h b/sys/include/vm/vm_vnode.h new file mode 100644 index 0000000..138cfe2 --- /dev/null +++ b/sys/include/vm/vm_vnode.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VM_VNODE_H_ +#define _VM_VNODE_H_ + +#include <sys/types.h> +#include <sys/vnode.h> +#include <vm/vm_pager.h> +#include <vm/vm_obj.h> +#include <vm/pmap.h> + +extern const struct vm_pagerops vm_vnops; + +struct vm_object *vn_attach(struct vnode *vp, vm_prot_t prot); + +#endif /* !_VM_VNODE_H_ */ diff --git a/sys/vm/vm_obj.c b/sys/vm/vm_obj.c new file mode 100644 index 0000000..75545dc --- /dev/null +++ b/sys/vm/vm_obj.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <vm/vm_obj.h> +#include <vm/vm_pager.h> + +int +vm_obj_init(struct vm_object *obp, const struct vm_pagerops *pgops, int refs) +{ + if (obp == NULL || pgops == NULL) + return -1; + + obp->pgops = pgops; + obp->refs = refs; + obp->npages = 0; + RBT_INIT(vm_objtree, &obp->objt); + return 0; +} + +void +vm_obj_release(struct vm_object *obp) +{ + /* STUB */ + (void)obp; +} diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c new file mode 100644 index 0000000..8ada183 --- /dev/null +++ b/sys/vm/vm_page.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <vm/vm_page.h> +#include <vm/vm_obj.h> +#include <vm/physmem.h> +#include <vm/dynalloc.h> +#include <vm/vm.h> +#include <assert.h> +#include <string.h> + +RBT_GENERATE(vm_objtree, vm_page, objt, vm_pagecmp); + +/* + * Insert a page into an object. + */ +static inline void +vm_pageinsert(struct vm_page *pg, struct vm_object *obp) +{ + struct vm_page *tmp; + + tmp = RBT_INSERT(vm_objtree, &obp->objt, pg); + __assert(tmp == NULL); + ++obp->npages; +} + +static inline void +vm_pageremove(struct vm_page *pg, struct vm_object *obp) +{ + RBT_REMOVE(vm_objtree, &obp->objt, pg); + --obp->npages; +} + +struct vm_page * +vm_pagelookup(struct vm_object *obj, off_t off) +{ + struct vm_page tmp; + + tmp.offset = off; + return RBT_FIND(vm_objtree, &obj->objt, &tmp); +} + +struct vm_page * +vm_pagealloc(struct vm_object *obj, int flags) +{ + struct vm_page *tmp; + + tmp = dynalloc(sizeof(*tmp)); + if (tmp == NULL) { + return NULL; + } + + memset(tmp, 0, sizeof(*tmp)); + tmp->phys_addr = vm_alloc_frame(1); + tmp->flags |= (PG_VALID | PG_CLEAN); + __assert(tmp->phys_addr != 0); + + if (ISSET(flags, PALLOC_ZERO)) { + memset(PHYS_TO_VIRT(tmp->phys_addr), 0, DEFAULT_PAGESIZE); + } + + vm_pageinsert(tmp, obj); + return tmp; +} + +void +vm_pagefree(struct vm_object *obj, struct vm_page *pg, int flags) +{ + __assert(pg->phys_addr != 0); + + vm_pageremove(pg, obj); + vm_free_frame(pg->phys_addr, 1); + dynfree(pg); +} + +int +vm_pagecmp(const struct vm_page *a, const struct vm_page *b) +{ + return (a->offset < b->offset) ? -1 : a->offset > b->offset; +} diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c new file mode 100644 index 0000000..2a85d55 --- /dev/null +++ b/sys/vm/vm_pager.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/errno.h> +#include <vm/vm_pager.h> +#include <vm/vm_obj.h> + +int +vm_pager_get(struct vm_object *obp, struct vm_page **pgs, off_t off, size_t len) +{ + const struct vm_pagerops *pgops = obp->pgops; + + if (pgops->get == NULL) { + return -ENOTSUP; + } + + return pgops->get(obp, pgs, off, len); +} diff --git a/sys/vm/vm_vnode.c b/sys/vm/vm_vnode.c new file mode 100644 index 0000000..31e74cc --- /dev/null +++ b/sys/vm/vm_vnode.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/cdefs.h> +#include <sys/errno.h> +#include <sys/syslog.h> +#include <sys/systm.h> +#include <sys/vnode.h> +#include <vm/vm_vnode.h> +#include <vm/vm_page.h> +#include <vm/pmap.h> +#include <vm/vm.h> + +#define VN_TIMEOUT_USEC 200000 + +#define pr_trace(fmt, ...) kprintf("vm_vnode: " fmt, ##__VA_ARGS__) +#define pr_error(...) pr_trace(__VA_ARGS__) + +/* Debug print helper */ +#if defined(PR_DEBUG) +#define pr_debug(...) pr_trace(__VA_ARGS__) +#else +#define pr_debug(...) __nothing +#endif /* PR_DEBUG */ + +const struct vm_pagerops vm_vnops; + +/* + * Perform read/write operation on vnode to/from pages. + * + * Returns number of bytes read. + */ +static int +vn_io(struct vnode *vp, struct vm_page **pgs, unsigned int npages, int rw) +{ + struct vop_getattr_args args; + struct sio_txn sio; + struct vattr vattr; + size_t c, read = 0; + int err; + + /* TODO: Add support for writes */ + if (rw != 0) { + return -ENOTSUP; + } + + args.vp = vp; + args.res = &vattr; + c = MAX(vattr.size / DEFAULT_PAGESIZE, 1); + + if ((err = vfs_vop_getattr(vp, &args)) != 0) { + return err; + } + + if (npages > c) { + npages = c; + } + + /* Prepare SIO constants */ + sio.len = DEFAULT_PAGESIZE; + sio.offset = 0; + + /* Copy in each page */ + for (size_t i = 0; i < npages; ++i) { + sio.buf = PHYS_TO_VIRT(pgs[i]->phys_addr); + read = vfs_vop_read(vp, &sio); + if (read < 0) + pr_debug("vn_io: page-in @ %p failed (err=%d)\n", err); + } + + return read; +} + +/* + * Get pages from backing store. + * + * @obp: Object representing the backing store. + * @pgs: Page descriptors to be filled. + * @off: Offset to read from in backing store. + * @len: Length to read in bytes. + */ +static int +vn_get(struct vm_object *obp, struct vm_page **pgs, off_t off, size_t len) +{ + struct vm_page *pgtmp; + size_t j, pgcnt; + + spinlock_acquire(&obp->lock); + + for (int i = off; i < len; i += DEFAULT_PAGESIZE) { + j = i / DEFAULT_PAGESIZE; + pgtmp = vm_pagelookup(obp, i); + + /* + * If we have no corresponding page in the object + * at this offset, we will need to make our own. + */ + if (pgtmp == NULL) { + pgtmp = vm_pagealloc(obp, PALLOC_ZERO); + if (pgtmp == NULL) { + pgs[j]->flags &= ~PG_VALID; + continue; + } + pgtmp->offset = i; + pgs[j] = pgtmp; + } + + if (spinlock_usleep(&pgtmp->lock, VN_TIMEOUT_USEC) != 0) { + pgs[j]->flags &= ~PG_VALID; + continue; + } + + /* Set the page count and ensure it is valid */ + pgcnt = ALIGN_DOWN(len, DEFAULT_PAGESIZE); + pgcnt = MAX(pgcnt, 1); + + /* Page in and save this pgtmp */ + vn_io(obp->data, &pgtmp, pgcnt, 0); + pgs[j] = pgtmp; + spinlock_release(&pgtmp->lock); + } + + spinlock_release(&obp->lock); + return 0; +} + +/* + * Attach a virtual memory object to a vnode. + * + * @vp: Vnode to attach to. + */ +struct vm_object * +vn_attach(struct vnode *vp, vm_prot_t prot) +{ + struct vm_object *vmobj; + int error; + + if (vp->type != VREG) { + pr_error("vn_attach: vp=%p, prot=%x\n", vp, prot); + pr_error("vn_attach: Special files not supported yet!\n"); + return NULL; + } + + error = vm_obj_init(&vp->vobj, &vm_vnops, 1); + if (error != 0) { + return NULL; + } + + vmobj = &vp->vobj; + vmobj->prot = prot; + vmobj->data = vp; + vmobj->pgops = &vm_vnops; + return vmobj; +} + +const struct vm_pagerops vm_vnops = { + .get = vn_get +}; |