#include <sys/types.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/cred.h>
#include <sys/kmem.h>
#include <sys/lgrp.h>
#include <sys/mman.h>
#include <vm/hat.h>
#include <vm/as.h>
#include <vm/seg.h>
#include <vm/seg_hole.h>
static int seghole_dup(struct seg *, struct seg *);
static int seghole_unmap(struct seg *, caddr_t, size_t);
static void seghole_free(struct seg *);
static faultcode_t seghole_fault(struct hat *, struct seg *, caddr_t, size_t,
enum fault_type, enum seg_rw);
static faultcode_t seghole_faulta(struct seg *, caddr_t);
static int seghole_setprot(struct seg *, caddr_t, size_t, uint_t);
static int seghole_checkprot(struct seg *, caddr_t, size_t, uint_t);
static int seghole_sync(struct seg *, caddr_t, size_t, int, uint_t);
static size_t seghole_incore(struct seg *, caddr_t, size_t, char *);
static int seghole_lockop(struct seg *, caddr_t, size_t, int, int, ulong_t *,
size_t);
static int seghole_getprot(struct seg *, caddr_t, size_t, uint_t *);
static u_offset_t seghole_getoffset(struct seg *, caddr_t);
static int seghole_gettype(struct seg *, caddr_t);
static int seghole_getvp(struct seg *, caddr_t, struct vnode **);
static int seghole_advise(struct seg *, caddr_t, size_t, uint_t);
static void seghole_dump(struct seg *);
static int seghole_pagelock(struct seg *, caddr_t, size_t, struct page ***,
enum lock_type, enum seg_rw);
static int seghole_setpagesize(struct seg *, caddr_t, size_t, uint_t);
static int seghole_capable(struct seg *, segcapability_t);
static struct seg_ops seghole_ops = {
seghole_dup,
seghole_unmap,
seghole_free,
seghole_fault,
seghole_faulta,
seghole_setprot,
seghole_checkprot,
NULL,
NULL,
seghole_sync,
seghole_incore,
seghole_lockop,
seghole_getprot,
seghole_getoffset,
seghole_gettype,
seghole_getvp,
seghole_advise,
seghole_dump,
seghole_pagelock,
seghole_setpagesize,
NULL,
NULL,
seghole_capable,
seg_inherit_notsup
};
int
seghole_create(struct seg **segpp, void *argsp)
{
struct seg *seg = *segpp;
seghole_crargs_t *crargs = argsp;
seghole_data_t *data;
data = kmem_alloc(sizeof (seghole_data_t), KM_SLEEP);
data->shd_name = crargs->name;
seg->s_ops = &seghole_ops;
seg->s_data = data;
seg->s_flags = S_HOLE;
return (0);
}
static int
seghole_dup(struct seg *seg, struct seg *newseg)
{
seghole_data_t *shd = (seghole_data_t *)seg->s_data;
seghole_data_t *newshd;
ASSERT(seg->s_as && AS_WRITE_HELD(seg->s_as));
newshd = kmem_zalloc(sizeof (seghole_data_t), KM_SLEEP);
newshd->shd_name = shd->shd_name;
newseg->s_ops = seg->s_ops;
newseg->s_data = newshd;
newseg->s_flags = S_HOLE;
return (0);
}
static int
seghole_unmap(struct seg *seg, caddr_t addr, size_t len)
{
ASSERT(seg->s_as && AS_WRITE_HELD(seg->s_as));
if (addr == seg->s_base && len == seg->s_size) {
seg_free(seg);
return (0);
}
if (addr == seg->s_base) {
seg->s_base += len;
seg->s_size -= len;
return (0);
}
if ((addr + len) == (seg->s_base + seg->s_size)) {
seg->s_size -= len;
return (0);
}
return (EINVAL);
}
static void
seghole_free(struct seg *seg)
{
seghole_data_t *data = (seghole_data_t *)seg->s_data;
ASSERT(data != NULL);
kmem_free(data, sizeof (*data));
seg->s_data = NULL;
}
static faultcode_t
seghole_fault(struct hat *hat, struct seg *seg, caddr_t addr, size_t len,
enum fault_type type, enum seg_rw tw)
{
ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
return (FC_NOMAP);
}
static faultcode_t
seghole_faulta(struct seg *seg, caddr_t addr)
{
return (FC_NOMAP);
}
static int
seghole_setprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot)
{
ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
return (ENOMEM);
}
static int
seghole_checkprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot)
{
ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
return (ENOMEM);
}
static int
seghole_sync(struct seg *seg, caddr_t addr, size_t len, int attr, uint_t flags)
{
return (0);
}
static size_t
seghole_incore(struct seg *seg, caddr_t addr, size_t len, char *vec)
{
ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
return (0);
}
static int
seghole_lockop(struct seg *seg, caddr_t addr, size_t len, int attr, int op,
ulong_t *lockmap, size_t pos)
{
return (ENOMEM);
}
static int
seghole_getprot(struct seg *seg, caddr_t addr, size_t len, uint_t *protv)
{
size_t pgno;
ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
pgno = seg_page(seg, addr + len) - seg_page(seg, addr) + 1;
while (pgno > 0) {
protv[--pgno] = 0;
}
return (ENOMEM);
}
static u_offset_t
seghole_getoffset(struct seg *seg, caddr_t addr)
{
return (0);
}
static int
seghole_gettype(struct seg *seg, caddr_t addr)
{
return (MAP_PRIVATE);
}
static int
seghole_getvp(struct seg *seg, caddr_t addr, struct vnode **vpp)
{
ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as));
return (ENOMEM);
}
static int
seghole_advise(struct seg *seg, caddr_t addr, size_t len, uint_t behav)
{
return (ENOMEM);
}
static void
seghole_dump(struct seg *seg)
{
}
static int
seghole_pagelock(struct seg *seg, caddr_t addr, size_t len, struct page ***ppp,
enum lock_type type, enum seg_rw rw)
{
return (EFAULT);
}
static int
seghole_setpagesize(struct seg *seg, caddr_t addr, size_t len, uint_t szc)
{
return (ENOMEM);
}
static int
seghole_capable(struct seg *seg, segcapability_t capability)
{
return (0);
}