/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <vm/pmap.h>
#include <vm/vm_pager.h>
#include <mach/memory_object_types.h>
+#include <kern/debug.h>
#include <miscfs/devfs/devfs.h>
static int mdevbioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p);
static int mdevcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p);
static int mdevrw(dev_t dev, struct uio *uio, int ioflag);
+
+#ifdef CONFIG_MEMDEV_INSECURE
static char * nonspace(char *pos, char *end);
static char * getspace(char *pos, char *end);
-static char * cvtnum(char *pos, char *end, unsigned int *num);
+static char * cvtnum(char *pos, char *end, uint64_t *num);
+#endif /* CONFIG_MEMDEV_INSECURE */
extern void bcopy_phys(addr64_t from, addr64_t to, vm_size_t bytes);
extern void mapping_set_mod(ppnum_t pn);
extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
+/*
+ * Maximal number of memory devices.
+ */
+#define NB_MAX_MDEVICES (16)
/*
* cdevsw
/* ioctl */ mdevcioctl,
/* stop */ eno_stop,
/* reset */ eno_reset,
- /* ttys */ 0,
+ /* ttys */ NULL,
/* select */ eno_select,
/* mmap */ eno_mmap,
/* strategy */ eno_strat,
};
struct mdev {
- vm_offset_t mdBase; /* file size in bytes */
+ uint64_t mdBase; /* file size in bytes */
uint32_t mdSize; /* file size in bytes */
int mdFlags; /* flags */
int mdSecsize; /* sector size */
int mdCDev; /* Character device number */
void * mdbdevb;
void * mdcdevb;
-} mdev[16];
+} mdev[NB_MAX_MDEVICES];
/* mdFlags */
#define mdInited 0x01 /* This device defined */
int mdevBMajor = -1;
int mdevCMajor = -1;
-static int mdevioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p, int is_char);
-dev_t mdevadd(int devid, ppnum_t base, unsigned int size, int phys);
-dev_t mdevlookup(int devid);
+static int mdevioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p, int is_char);
+dev_t mdevadd(int devid, uint64_t base, unsigned int size, int phys);
+dev_t mdevlookup(int devid);
+void mdevremoveall(void);
+int mdevgetrange(int devid, uint64_t *base, uint64_t *size);
static int mdevclose(__unused dev_t dev, __unused int flags,
__unused int devtype, __unused struct proc *p) {
devid = minor(dev); /* Get minor device number */
- if (devid > 16) return (ENXIO); /* Not valid */
+ if (devid >= NB_MAX_MDEVICES) return (ENXIO); /* Not valid */
if ((flags & FWRITE) && (mdev[devid].mdFlags & mdRO)) return (EACCES); /* Currently mounted RO */
devid = minor(dev); /* Get minor device number */
- if (devid > 16) return (ENXIO); /* Not valid */
+ if (devid >= NB_MAX_MDEVICES) return (ENXIO); /* Not valid */
if (!(mdev[devid].mdFlags & mdInited)) return (ENXIO); /* Have we actually been defined yet? */
mdata = ((addr64_t)mdev[devid].mdBase << 12) + uio->uio_offset; /* Point to the area in "file" */
saveflag = uio->uio_segflg; /* Remember what the request is */
#if LP64_DEBUG
- if (IS_VALID_UIO_SEGFLG(uio->uio_segflg) == 0) {
+ if (UIO_IS_USER_SPACE(uio) == 0 && UIO_IS_SYS_SPACE(uio) == 0) {
panic("mdevrw - invalid uio_segflg\n");
}
#endif /* LP64_DEBUG */
lop = min((4096 - (vaddr & 4095)), (4096 - (fvaddr & 4095))); /* Get smallest amount left on sink and source */
csize = min(lop, left); /* Don't move more than we need to */
- pp = pmap_find_phys(kernel_pmap, (addr64_t)((unsigned int)vaddr)); /* Get the sink physical address */
+ pp = pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)vaddr)); /* Get the sink physical address */
if(!pp) { /* Not found, what gives? */
- panic("mdevstrategy: sink address %016llX not mapped\n", (addr64_t)((unsigned int)vaddr));
+ panic("mdevstrategy: sink address %016llX not mapped\n", (addr64_t)((uintptr_t)vaddr));
}
paddr = (addr64_t)(((addr64_t)pp << 12) | (addr64_t)(vaddr & 4095)); /* Get actual address */
bcopy_phys(fvaddr, paddr, csize); /* Copy this on in */
lop = min((4096 - (vaddr & 4095)), (4096 - (fvaddr & 4095))); /* Get smallest amount left on sink and source */
csize = min(lop, left); /* Don't move more than we need to */
- pp = pmap_find_phys(kernel_pmap, (addr64_t)((unsigned int)vaddr)); /* Get the source physical address */
+ pp = pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)vaddr)); /* Get the source physical address */
if(!pp) { /* Not found, what gives? */
- panic("mdevstrategy: source address %016llX not mapped\n", (addr64_t)((unsigned int)vaddr));
+ panic("mdevstrategy: source address %016llX not mapped\n", (addr64_t)((uintptr_t)vaddr));
}
paddr = (addr64_t)(((addr64_t)pp << 12) | (addr64_t)(vaddr & 4095)); /* Get actual address */
static int mdevioctl(dev_t dev, u_long cmd, caddr_t data, __unused int flag,
struct proc *p, int is_char) {
int error;
- u_long *f;
+ u_int32_t *f;
u_int64_t *o;
int devid;
+ dk_memdev_info_t * memdev_info;
devid = minor(dev); /* Get minor device number */
- if (devid > 16) return (ENXIO); /* Not valid */
+ if (devid >= NB_MAX_MDEVICES) return (ENXIO); /* Not valid */
error = proc_suser(p); /* Are we superman? */
if (error) return (error); /* Nope... */
- f = (u_long*)data;
+ f = (u_int32_t*)data;
o = (u_int64_t *)data;
+ memdev_info = (dk_memdev_info_t *) data;
switch (cmd) {
*f = 1;
break;
- case DKIOCGETBLOCKCOUNT32:
- if(!(mdev[devid].mdFlags & mdInited)) return (ENXIO);
- *f = ((mdev[devid].mdSize << 12) + mdev[devid].mdSecsize - 1) / mdev[devid].mdSecsize;
- break;
-
case DKIOCGETBLOCKCOUNT:
if(!(mdev[devid].mdFlags & mdInited)) return (ENXIO);
*o = ((mdev[devid].mdSize << 12) + mdev[devid].mdSecsize - 1) / mdev[devid].mdSecsize;
break;
-
+
+ /*
+ * We're interested in the following bits of information:
+ * Are you a memory-backed device (always yes, in this case)?
+ * Physical memory (mdPhys)?
+ * What is your base page?
+ * What is your size?
+ */
+ case DKIOCGETMEMDEVINFO:
+ if (!(mdev[devid].mdFlags & mdInited)) return (ENXIO);
+ memdev_info->mi_mdev = TRUE;
+ memdev_info->mi_phys = (mdev[devid].mdFlags & mdPhys) ? TRUE : FALSE;
+ memdev_info->mi_base = mdev[devid].mdBase;
+ memdev_info->mi_size = mdev[devid].mdSize;
+ break;
+
default:
error = ENOTTY;
break;
int devid;
devid = minor(dev); /* Get minor device number */
- if (devid > 16) return (ENXIO); /* Not valid */
+ if (devid >= NB_MAX_MDEVICES) return (ENXIO); /* Not valid */
if ((mdev[devid].mdFlags & mdInited) == 0) return(-1); /* Not inited yet */
void mdevinit(__unused int the_cnt) {
+#ifdef CONFIG_MEMDEV_INSECURE
+
int devid, phys;
- ppnum_t base;
- unsigned int size;
+ uint64_t base;
+ uint64_t size;
char *ba, *lp;
dev_t dev;
if((ba[0] != ' ') && (ba[0] != 0)) continue; /* End must be null or space */
}
- dev = mdevadd(devid, base >> 12, size >> 12, phys); /* Go add the device */
+ dev = mdevadd(devid, base >> 12, (unsigned)size >> 12, phys); /* Go add the device */
}
+#endif /* CONFIG_MEMDEV_INSECURE */
+
return;
}
+#ifdef CONFIG_MEMDEV_INSECURE
+
char *nonspace(char *pos, char *end) { /* Find next non-space in string */
if(pos >= end) return end; /* Don't go past end */
}
}
-char *cvtnum(char *pos, char *end, unsigned int *num) { /* Convert to a number */
+char *cvtnum(char *pos, char *end, uint64_t *num) { /* Convert to a number */
int rad, dig;
}
}
-dev_t mdevadd(int devid, ppnum_t base, unsigned int size, int phys) {
+#endif /* CONFIG_MEMDEV_INSECURE */
+
+dev_t mdevadd(int devid, uint64_t base, unsigned int size, int phys) {
int i;
if(devid < 0) {
devid = -1;
- for(i = 0; i < 16; i++) { /* Search all known memory devices */
+ for(i = 0; i < NB_MAX_MDEVICES; i++) { /* Search all known memory devices */
if(!(mdev[i].mdFlags & mdInited)) { /* Is this a free one? */
if(devid < 0)devid = i; /* Remember first free one */
continue; /* Skip check */
}
if(!(((base + size -1 ) < mdev[i].mdBase) || ((mdev[i].mdBase + mdev[i].mdSize - 1) < base))) { /* Is there any overlap? */
- panic("mdevadd: attempt to add overlapping memory device at %08X-%08X\n", mdev[i].mdBase, mdev[i].mdBase + mdev[i].mdSize - 1);
+ panic("mdevadd: attempt to add overlapping memory device at %016llX-%016llX\n", mdev[i].mdBase, mdev[i].mdBase + mdev[i].mdSize - 1);
}
}
if(devid < 0) { /* Do we have free slots? */
- panic("mdevadd: attempt to add more than 16 memory devices\n");
+ panic("mdevadd: attempt to add more than %d memory devices\n", NB_MAX_MDEVICES);
}
}
else {
- if(devid >= 16) { /* Giving us something bogus? */
- panic("mdevadd: attempt to explicitly add a bogus memory device: &08X\n", devid);
+ if(devid >= NB_MAX_MDEVICES) { /* Giving us something bogus? */
+ panic("mdevadd: attempt to explicitly add a bogus memory device: %08X\n", devid);
}
- if(mdev[devid].mdFlags &mdInited) { /* Already there? */
- panic("mdevadd: attempt to explicitly add a previously defined memory device: &08X\n", devid);
+ if(mdev[devid].mdFlags & mdInited) { /* Already there? */
+ panic("mdevadd: attempt to explicitly add a previously defined memory device: %08X\n", devid);
}
}
mdev[devid].mdSecsize = DEV_BSIZE; /* Set starting block size */
if(phys) mdev[devid].mdFlags |= mdPhys; /* Show that we are in physical memory */
mdev[devid].mdFlags |= mdInited; /* Show we are all set up */
- printf("Added memory device md%x/rmd%x (%08X/%08X) at %08X for %08X\n",
- devid, devid, mdev[devid].mdBDev, mdev[devid].mdCDev, base << 12, size << 12);
+ printf("Added memory device md%x/rmd%x (%08X/%08X) at %016llX for %016llX\n",
+ devid, devid, mdev[devid].mdBDev, mdev[devid].mdCDev, base << 12, (uint64_t)size << 12);
return mdev[devid].mdBDev;
}
dev_t mdevlookup(int devid) {
- if((devid < 0) || (devid > 15)) return -1; /* Filter any bogus requests */
+ if((devid < 0) || (devid >= NB_MAX_MDEVICES)) return -1; /* Filter any bogus requests */
if(!(mdev[devid].mdFlags & mdInited)) return -1; /* This one hasn't been defined */
return mdev[devid].mdBDev; /* Return the device number */
}
+
+void mdevremoveall(void) {
+
+ int i;
+
+ for(i = 0; i < NB_MAX_MDEVICES; i++) {
+ if(!(mdev[i].mdFlags & mdInited)) continue; /* Ignore unused mdevs */
+
+ devfs_remove(mdev[i].mdbdevb); /* Remove the block device */
+ devfs_remove(mdev[i].mdcdevb); /* Remove the character device */
+
+ mdev[i].mdBase = 0; /* Clear the mdev's storage */
+ mdev[i].mdSize = 0;
+ mdev[i].mdSecsize = 0;
+ mdev[i].mdFlags = 0;
+ mdev[i].mdBDev = 0;
+ mdev[i].mdCDev = 0;
+ mdev[i].mdbdevb = 0;
+ mdev[i].mdcdevb = 0;
+ }
+}
+
+int
+mdevgetrange(int devid, uint64_t *base, uint64_t *size)
+{
+ assert(base);
+ assert(size);
+
+ /* filter invalid request */
+ if ((devid < 0) || (devid >= NB_MAX_MDEVICES)) {
+ return -1;
+ }
+
+ /* filter non-initialized memory devices */
+ if ((mdev[devid].mdFlags & mdInited) == 0) {
+ return -1;
+ }
+
+ *base = mdev[devid].mdBase << 12;
+ *size = mdev[devid].mdSize << 12;
+
+ /* make sure (base, size) is a valid range and will not overflow */
+ assert(*size < (UINT64_MAX - *base));
+
+ return 0;
+}
+