add zeroobj for private anonymous mappings
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
IHKDIR=$(IHKBASE)/$(TARGETDIR)
|
||||
OBJS = init.o mem.o debug.o mikc.o listeners.o ap.o syscall.o cls.o host.o
|
||||
OBJS += process.o copy.o waitq.o futex.o timer.o plist.o fileobj.o shmobj.o
|
||||
OBJS += zeroobj.o
|
||||
DEPSRCS=$(wildcard $(SRC)/*.c)
|
||||
|
||||
CFLAGS += -I$(SRC)/include -mcmodel=kernel -D__KERNEL__
|
||||
|
||||
@ -103,5 +103,6 @@ static inline int memobj_has_pager(struct memobj *obj)
|
||||
|
||||
int fileobj_create(int fd, struct memobj **objp, int *maxprotp);
|
||||
int shmobj_create(struct shmid_ds *ds, struct memobj **objp);
|
||||
int zeroobj_create(struct memobj **objp);
|
||||
|
||||
#endif /* HEADER_MEMOBJ_H */
|
||||
|
||||
@ -795,6 +795,13 @@ SYSCALL_DECLARE(mmap)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else {
|
||||
error = zeroobj_create(&memobj);
|
||||
if (error) {
|
||||
ekprintf("sys_mmap:zeroobj_create failed. %d\n", error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & MAP_PRIVATE) && (maxprot & PROT_READ)) {
|
||||
maxprot |= PROT_WRITE;
|
||||
|
||||
206
kernel/zeroobj.c
Normal file
206
kernel/zeroobj.c
Normal file
@ -0,0 +1,206 @@
|
||||
/**
|
||||
* \file zeroobj.c
|
||||
* License details are found in the file LICENSE.
|
||||
* \brief
|
||||
* read-only zeroed page object
|
||||
* \author Gou Nakamura <go.nakamura.yw@hitachi-solutions.com>
|
||||
*/
|
||||
/*
|
||||
* HISTORY:
|
||||
*/
|
||||
|
||||
#include <ihk/atomic.h>
|
||||
#include <ihk/debug.h>
|
||||
#include <ihk/lock.h>
|
||||
#include <ihk/mm.h>
|
||||
#include <errno.h>
|
||||
#include <kmalloc.h>
|
||||
#include <list.h>
|
||||
#include <memobj.h>
|
||||
#include <memory.h>
|
||||
#include <page.h>
|
||||
#include <string.h>
|
||||
|
||||
#define dkprintf(...) do { if (0) kprintf(__VA_ARGS__); } while (0)
|
||||
#define ekprintf(...) kprintf(__VA_ARGS__)
|
||||
#define fkprintf(...) kprintf(__VA_ARGS__)
|
||||
|
||||
struct zeroobj {
|
||||
struct memobj memobj; /* must be first */
|
||||
struct list_head page_list;
|
||||
};
|
||||
|
||||
static ihk_spinlock_t the_zeroobj_lock = SPIN_LOCK_UNLOCKED;
|
||||
static struct zeroobj *the_zeroobj = NULL; /* singleton */
|
||||
|
||||
static memobj_get_page_func_t zeroobj_get_page;
|
||||
|
||||
static struct memobj_ops zeroobj_ops = {
|
||||
.get_page = &zeroobj_get_page,
|
||||
};
|
||||
|
||||
static struct zeroobj *to_zeroobj(struct memobj *memobj)
|
||||
{
|
||||
return (struct zeroobj *)memobj;
|
||||
}
|
||||
|
||||
static struct memobj *to_memobj(struct zeroobj *zeroobj)
|
||||
{
|
||||
return &zeroobj->memobj;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* page_list
|
||||
*/
|
||||
static void page_list_init(struct zeroobj *obj)
|
||||
{
|
||||
INIT_LIST_HEAD(&obj->page_list);
|
||||
return;
|
||||
}
|
||||
|
||||
static void page_list_insert(struct zeroobj *obj, struct page *page)
|
||||
{
|
||||
list_add(&page->list, &obj->page_list);
|
||||
return;
|
||||
}
|
||||
|
||||
static struct page *page_list_first(struct zeroobj *obj)
|
||||
{
|
||||
if (list_empty(&obj->page_list)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return list_first_entry(&obj->page_list, struct page, list);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* zeroobj
|
||||
*/
|
||||
static int alloc_zeroobj(void)
|
||||
{
|
||||
int error;
|
||||
struct zeroobj *obj = NULL;
|
||||
void *virt = NULL;
|
||||
uintptr_t phys;
|
||||
struct page *page;
|
||||
|
||||
dkprintf("alloc_zeroobj()\n");
|
||||
ihk_mc_spinlock_lock_noirq(&the_zeroobj_lock);
|
||||
if (the_zeroobj) {
|
||||
error = 0;
|
||||
dkprintf("alloc_zeroobj():already. %d\n", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
obj = kmalloc(sizeof(*obj), IHK_MC_AP_NOWAIT);
|
||||
if (!obj) {
|
||||
error = -ENOMEM;
|
||||
ekprintf("alloc_zeroobj():kmalloc failed. %d\n", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(obj, 0, sizeof(*obj));
|
||||
obj->memobj.ops = &zeroobj_ops;
|
||||
page_list_init(obj);
|
||||
ihk_mc_spinlock_init(&obj->memobj.lock);
|
||||
|
||||
virt = ihk_mc_alloc_pages(1, IHK_MC_AP_NOWAIT); /* XXX:NYI:large page */
|
||||
if (!virt) {
|
||||
error = -ENOMEM;
|
||||
ekprintf("alloc_zeroobj():alloc pages failed. %d\n", error);
|
||||
goto out;
|
||||
}
|
||||
phys = virt_to_phys(virt);
|
||||
page = phys_to_page(phys);
|
||||
|
||||
if (page->mode != PM_NONE) {
|
||||
fkprintf("alloc_zeroobj():"
|
||||
"page %p %#lx %d %d %#lx\n",
|
||||
page, page_to_phys(page), page->mode,
|
||||
page->count, page->offset);
|
||||
panic("alloc_zeroobj:dup alloc");
|
||||
}
|
||||
|
||||
memset(virt, 0, PAGE_SIZE);
|
||||
page->mode = PM_MAPPED;
|
||||
page->offset = 0;
|
||||
ihk_atomic_set(&page->count, 1);
|
||||
page_list_insert(obj, page);
|
||||
virt = NULL;
|
||||
|
||||
error = 0;
|
||||
the_zeroobj = obj;
|
||||
obj = NULL;
|
||||
|
||||
out:
|
||||
ihk_mc_spinlock_unlock_noirq(&the_zeroobj_lock);
|
||||
if (virt) {
|
||||
ihk_mc_free_pages(virt, 1);
|
||||
}
|
||||
if (obj) {
|
||||
kfree(obj);
|
||||
}
|
||||
dkprintf("alloc_zeroobj():%d %p\n", error, the_zeroobj);
|
||||
return error;
|
||||
}
|
||||
|
||||
int zeroobj_create(struct memobj **objp)
|
||||
{
|
||||
int error;
|
||||
|
||||
dkprintf("zeroobj_create(%p)\n", objp);
|
||||
if (!the_zeroobj) {
|
||||
error = alloc_zeroobj();
|
||||
if (error) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
error = 0;
|
||||
*objp = to_memobj(the_zeroobj);
|
||||
|
||||
out:
|
||||
dkprintf("zeroobj_create(%p):%d %p\n", objp, error, *objp);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int zeroobj_get_page(struct memobj *memobj, off_t off, int p2align,
|
||||
uintptr_t *physp)
|
||||
{
|
||||
int error;
|
||||
struct zeroobj *obj = to_zeroobj(memobj);
|
||||
struct page *page;
|
||||
|
||||
dkprintf("zeroobj_get_page(%p,%#lx,%d,%p)\n",
|
||||
memobj, off, p2align, physp);
|
||||
if (off & ~PAGE_MASK) {
|
||||
error = -EINVAL;
|
||||
ekprintf("zeroobj_get_page(%p,%#lx,%d,%p):invalid argument. %d\n",
|
||||
memobj, off, p2align, physp, error);
|
||||
goto out;
|
||||
}
|
||||
if (p2align != PAGE_P2ALIGN) { /* XXX:NYI:large pages */
|
||||
error = -ENOMEM;
|
||||
ekprintf("zeroobj_get_page(%p,%#lx,%d,%p):large page. %d\n",
|
||||
memobj, off, p2align, physp, error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
page = page_list_first(obj);
|
||||
if (!page) {
|
||||
error = -ENOMEM;
|
||||
ekprintf("zeroobj_get_page(%p,%#lx,%d,%p):page not found. %d\n",
|
||||
memobj, off, p2align, physp, error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ihk_atomic_inc(&page->count);
|
||||
|
||||
error = 0;
|
||||
*physp = page_to_phys(page);
|
||||
|
||||
out:
|
||||
dkprintf("zeroobj_get_page(%p,%#lx,%d,%p):%d\n",
|
||||
memobj, off, p2align, physp, error);
|
||||
return error;
|
||||
}
|
||||
Reference in New Issue
Block a user