#define KFACTOR 1024
size = atol(argv[1])*KFACTOR;
- if(size <= 0) {
- fprintf(stderr, "size should be positive.\n");
+ if(size < 0) {
+ fprintf(stderr, "size should be non-negative.\n");
return 1;
}
local defines and declarations
*/
-extern unsigned char _binary_imgrd_mfs_start[], *_binary_imgrd_mfs_end;
+extern unsigned char _binary_imgrd_mfs_start, _binary_imgrd_mfs_end;
-#define imgrd _binary_imgrd_mfs_start
+#define imgrd &_binary_imgrd_mfs_start
#define imgrd_size \
- ((size_t)(_binary_imgrd_mfs_end - _binary_imgrd_mfs_start))
+ (((size_t) &_binary_imgrd_mfs_end - (size_t)&_binary_imgrd_mfs_start))
* Apr 20, 1992 device dependent/independent split (Kees J. Bot)
*/
+#include <assert.h>
#include <minix/drivers.h>
#include <minix/chardriver.h>
#include <minix/blockdriver.h>
static void sef_local_startup(void);
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
+
/*===========================================================================*
* main *
*===========================================================================*/
}
openct[minor]--;
-#if 0
- /* Special case: free initial ramdisk after it's been unmounted once. */
- if(minor == IMGRD_DEV && openct[minor] == 0 && m_vaddrs[IMGRD_DEV]) {
- vir_bytes vaddr, vlen;
- vaddr = m_vaddrs[IMGRD_DEV];
- vlen = imgrd_size;
- /* Align `inwards' so as to not unmap more than the initial
- * ramdisk image.
- */
- if(vaddr % PAGE_SIZE) {
- vir_bytes o = PAGE_SIZE - (vaddr % PAGE_SIZE);
- vlen -= o;
- vaddr += o;
- }
- if(vlen % PAGE_SIZE) {
- vlen -= vlen % PAGE_SIZE;
- }
- minix_munmap((void *) vaddr, vlen);
- m_geom[IMGRD_DEV].dv_base= cvul64(0);
- m_geom[IMGRD_DEV].dv_size= cvul64(0);
- m_vaddrs[IMGRD_DEV] = 0;
- }
-#endif
-
return(OK);
}
u32_t ramdev_size;
int s;
void *mem;
+ int is_imgrd = 0;
if (request != MIOCRAMSIZE)
return EINVAL;
+ if(minor == IMGRD_DEV)
+ is_imgrd = 1;
+
/* Someone wants to create a new RAM disk with the given size.
* A ramdisk can be created only once, and only on RAM disk device.
*/
if ((dv = m_block_part(minor)) == NULL) return ENXIO;
- if((minor < RAM_DEV_FIRST || minor > RAM_DEV_LAST) && minor != RAM_DEV_OLD) {
+ if((minor < RAM_DEV_FIRST || minor > RAM_DEV_LAST) &&
+ minor != RAM_DEV_OLD && !is_imgrd) {
printf("MEM: MIOCRAMSIZE: %d not a ramdisk\n", minor);
return EINVAL;
}
sizeof(ramdev_size));
if (s != OK)
return s;
+ if(is_imgrd)
+ ramdev_size = 0;
if(m_vaddrs[minor] && !cmp64(dv->dv_size, cvul64(ramdev_size))) {
return(OK);
}
return(EBUSY);
}
if(m_vaddrs[minor]) {
- u32_t size;
+ u32_t a, o;
+ u64_t size;
+ int r;
if(ex64hi(dv->dv_size)) {
panic("huge old ramdisk");
}
- size = ex64lo(dv->dv_size);
- minix_munmap((void *) m_vaddrs[minor], size);
+ size = dv->dv_size;
+ a = m_vaddrs[minor];
+ if((o = a % PAGE_SIZE)) {
+ vir_bytes l = PAGE_SIZE - o;
+ a += l;
+ size -= l;
+ }
+ size = rounddown(size, PAGE_SIZE);
+ r = minix_munmap((void *) a, size);
+ if(r != OK) {
+ printf("memory: WARNING: munmap failed: %d\n", r);
+ }
m_vaddrs[minor] = (vir_bytes) NULL;
+ dv->dv_size = 0;
}
#if DEBUG
printf("MEM:%d: allocating ramdisk of size 0x%x\n", minor, ramdev_size);
#endif
+ mem = NULL;
+
/* Try to allocate a piece of memory for the RAM disk. */
- if((mem = minix_mmap(NULL, ramdev_size, PROT_READ|PROT_WRITE,
+ if(ramdev_size > 0 &&
+ (mem = minix_mmap(NULL, ramdev_size, PROT_READ|PROT_WRITE,
MAP_PREALLOC|MAP_ANON, -1, 0)) == MAP_FAILED) {
printf("MEM: failed to get memory for ramdisk\n");
return(ENOMEM);
printroot >/etc/mtab # /etc/mtab keeps track of mounts
>/etc/utmp # /etc/utmp keeps track of logins
- # Unmount now defunct ramdisk
- umount /dev/imgrd > /dev/null || echo "Failed to unmount boot ramdisk"
-
# Use MFS binary only from kernel image?
if [ "`sysenv bin_img`" = 1 ]
then
fi
fi
+ # Unmount and free now defunct ramdisk
+ umount /dev/imgrd > /dev/null || echo "Failed to unmount boot ramdisk"
+ ramdisk 0 /dev/imgrd || echo "Failed to free boot ramdisk"
+
# Edit settings for boot system services
if [ "`sysenv skip_boot_config`" != 1 ]
then
# define VMUM_ADDR m1_p1
# define VMUM_LEN m1_i1
-#define VM_MUNMAP_TEXT (VM_RQ_BASE+19)
-
/* To VM: forget all my yielded blocks. */
#define VM_FORGETBLOCKS (VM_RQ_BASE+22)
/* Basic vm calls allowed to every process. */
#define VM_BASIC_CALLS \
- VM_MMAP, VM_MUNMAP, VM_MUNMAP_TEXT, VM_MAP_PHYS, VM_UNMAP_PHYS, \
+ VM_MMAP, VM_MUNMAP, VM_MAP_PHYS, VM_UNMAP_PHYS, \
VM_FORGETBLOCKS, VM_FORGETBLOCK, VM_YIELDBLOCKGETBLOCK, VM_INFO
/*===========================================================================*
void * minix_mmap(void *, size_t, int, int, int, off_t);
void * minix_mmap_for(endpoint_t, void *, size_t, int, int, int, off_t);
int minix_munmap(void *, size_t);
-int minix_munmap_text(void *, size_t);
void * vm_remap(int d, int s, void *da, void *sa, size_t si);
void * vm_remap_ro(int d, int s, void *da, void *sa, size_t si);
int vm_unmap(int endpt, void *addr);
#define writev _writev
#define minix_mmap _minix_mmap
#define minix_munmap _minix_munmap
-#define minix_munmap_text _minix_munmap_text
#define vfork __vfork14
#endif /* __minix */
__weak_alias(vm_getrefcount, _vm_getrefcount)
__weak_alias(minix_mmap, _minix_mmap)
__weak_alias(minix_munmap, _minix_munmap)
-__weak_alias(minix_munmap_text, _minix_munmap_text)
#endif
}
-int minix_munmap_text(void *addr, size_t len)
-{
- message m;
-
- m.VMUM_ADDR = addr;
- m.VMUM_LEN = len;
-
- return _syscall(VM_PROC_NR, VM_MUNMAP_TEXT, &m);
-}
-
void *vm_remap(endpoint_t d,
endpoint_t s,
void *da,
#include "inc.h"
#define minix_munmap _minix_munmap
-#define minix_munmap_text _minix_munmap_text
#include <sys/mman.h>
#undef minix_munmap
-#undef minix_munmap_text
int unmap_ok = 0;
return _minix_munmap(addrstart, len);
}
-
-/*===========================================================================*
- * minix_munmap_text *
- *===========================================================================*/
-int minix_munmap_text(void *addrstart, vir_bytes len)
-{
- if(!unmap_ok)
- return ENOSYS;
-
- return _minix_munmap_text(addrstart, len);
-}
/* Basic VM calls. */
CALLMAP(VM_MMAP, do_mmap);
CALLMAP(VM_MUNMAP, do_munmap);
- CALLMAP(VM_MUNMAP_TEXT, do_munmap);
CALLMAP(VM_MAP_PHYS, do_map_phys);
CALLMAP(VM_UNMAP_PHYS, do_unmap_phys);
#include <minix/debug.h>
#include <sys/mman.h>
+#include <sys/param.h>
#include <errno.h>
#include <assert.h>
return EINVAL;
}
- if(map_unmap_region(vmp, region, region->length) != OK) {
+ if(map_unmap_region(vmp, region, 0, region->length) != OK) {
return EINVAL;
}
return EFAULT;
}
- if(map_unmap_region(vmp, vr, vr->length) != OK)
+ if(map_unmap_region(vmp, vr, 0, vr->length) != OK)
panic("do_shared_unmap: map_unmap_region failed");
return OK;
{
int r, n;
struct vmproc *vmp;
- vir_bytes addr, len;
+ vir_bytes addr, len, offset;
struct vir_region *vr;
-
+
if((r=vm_isokendpt(m->m_source, &n)) != OK) {
panic("do_mmap: message from strange source: %d", m->m_source);
}
vmp = &vmproc[n];
- if(m->m_type == VM_MUNMAP) {
- addr = (vir_bytes) (vir_bytes) m->VMUM_ADDR;
- } else if(m->m_type == VM_MUNMAP_TEXT) {
- addr = (vir_bytes) (vir_bytes) m->VMUM_ADDR;
- } else {
- panic("do_munmap: strange type");
- }
+ assert(m->m_type == VM_MUNMAP);
+ addr = (vir_bytes) (vir_bytes) m->VMUM_ADDR;
if(!(vr = map_lookup(vmp, addr))) {
printf("VM: unmap: virtual address %p not found in %d\n",
m->VMUM_ADDR, vmp->vm_endpoint);
return EFAULT;
}
+
+ if(addr % VM_PAGE_SIZE)
+ return EFAULT;
- len = m->VMUM_LEN;
- if (len % VM_PAGE_SIZE)
- len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);
+ len = roundup(m->VMUM_LEN, VM_PAGE_SIZE);
- if(addr != vr->vaddr || len > vr->length || len < VM_PAGE_SIZE) {
- return EFAULT;
- }
+ offset = addr - vr->vaddr;
+
+ if(offset + len > vr->length) {
+ printf("munmap: addr 0x%lx len 0x%lx spills out of region\n",
+ addr, len);
+ return EFAULT;
+ }
- if(map_unmap_region(vmp, vr, len) != OK)
+ if(map_unmap_region(vmp, vr, offset, len) != OK)
panic("do_munmap: map_unmap_region failed");
return OK;
return munmap_lin(laddr, len);
}
-/*===========================================================================*
- * munmap_text (override for VM) *
- *===========================================================================*/
-int minix_munmap_text(void *addr, size_t len)
-{
- vir_bytes laddr;
- if(!unmap_ok)
- return ENOSYS;
- laddr = (vir_bytes) addr;
- return munmap_lin(laddr, len);
-}
-
/*===========================================================================*
* pb_unreferenced *
*===========================================================================*/
-void pb_unreferenced(struct vir_region *region, struct phys_region *pr)
+void pb_unreferenced(struct vir_region *region, struct phys_region *pr, int rm)
{
struct phys_block *pb;
SLABFREE(pb);
}
- physr_remove(region->phys, pr->offset);
+ if(rm) physr_remove(region->phys, pr->offset);
}
int map_region_extend_upto_v(struct vmproc *vmp, vir_bytes vir);
int map_region_shrink(struct vir_region *vr, vir_bytes delta);
int map_unmap_region(struct vmproc *vmp, struct vir_region *vr,
- vir_bytes len);
+ vir_bytes offset, vir_bytes len);
int map_free_proc(struct vmproc *vmp);
int map_proc_copy(struct vmproc *dst, struct vmproc *src);
int map_proc_copy_from(struct vmproc *dst, struct vmproc *src, struct
int map_get_phys(struct vmproc *vmp, vir_bytes addr, phys_bytes *r);
int map_get_ref(struct vmproc *vmp, vir_bytes addr, u8_t *cnt);
-void pb_unreferenced(struct vir_region *region, struct phys_region *pr);
void get_stats_info(struct vm_stats_info *vsi);
void get_usage_info(struct vmproc *vmp, struct vm_usage_info *vui);
int get_region_info(struct vmproc *vmp, struct vm_region_info *vri, int
struct phys_block *pb_new(phys_bytes phys);
struct phys_region *pb_reference(struct phys_block *newpb,
vir_bytes offset, struct vir_region *region);
-void pb_unreferenced(struct vir_region *region, struct phys_region *pr);
+void pb_unreferenced(struct vir_region *region, struct phys_region *pr, int rm);
printf("VM: 1 minv: 0x%lx maxv: 0x%lx length: 0x%lx\n",
minv, maxv, length);
}
+
assert(minv < maxv);
- assert(minv + length <= maxv);
+
+ if(minv + length > maxv)
+ return SLOT_FAIL;
#define FREEVRANGE_TRY(rangestart, rangeend) { \
vir_bytes frstart = (rangestart), frend = (rangeend); \
/*===========================================================================*
* map_subfree *
*===========================================================================*/
-static int map_subfree(struct vir_region *region, vir_bytes len)
+static int map_subfree(struct vir_region *region,
+ vir_bytes start, vir_bytes len)
{
struct phys_region *pr;
physr_iter iter;
+ vir_bytes end = start+len;
+ int full = 0;
#if SANITYCHECKS
{
}
#endif
- physr_start_iter_least(region->phys, &iter);
+ if(start == 0 && len == region->length)
+ full = 1;
+
+ physr_start_iter(region->phys, &iter, start, AVL_GREATER_EQUAL);
while((pr = physr_get_iter(&iter))) {
physr_incr_iter(&iter);
- if(pr->offset >= len)
+ if(pr->offset >= end)
break;
- if(pr->offset + VM_PAGE_SIZE <= len) {
- pb_unreferenced(region, pr);
- physr_start_iter_least(region->phys, &iter);
- SLABFREE(pr);
+ pb_unreferenced(region, pr, !full);
+ if(!full) {
+ physr_start_iter(region->phys, &iter,
+ pr->offset, AVL_GREATER_EQUAL);
}
+ SLABFREE(pr);
}
+ if(full)
+ physr_init(region->phys);
+
return OK;
}
{
int r;
- if((r=map_subfree(region, region->length)) != OK) {
+ if((r=map_subfree(region, 0, region->length)) != OK) {
printf("%d\n", __LINE__);
return r;
}
if((physr = physr_search(region->phys, offset,
AVL_EQUAL))) {
assert(physr->ph->refcount == 1);
- pb_unreferenced(region, physr);
+ pb_unreferenced(region, physr, 1);
SLABFREE(physr);
}
offset += VM_PAGE_SIZE;
SLABSANE(ph);
SLABSANE(ph->ph);
assert(ph->ph->refcount > 1);
- pb_unreferenced(region, ph);
+ pb_unreferenced(region, ph, 1);
assert(ph->ph->refcount >= 1);
SLABFREE(ph);
* map_unmap_region *
*========================================================================*/
int map_unmap_region(struct vmproc *vmp, struct vir_region *r,
- vir_bytes len)
+ vir_bytes offset, vir_bytes len)
{
/* Shrink the region by 'len' bytes, from the start. Unreference
* memory it used to reference if any.
SANITYCHECK(SCL_FUNCTIONS);
- if(len > r->length || (len % VM_PAGE_SIZE)) {
+ if(offset+len > r->length || (len % VM_PAGE_SIZE)) {
printf("VM: bogus length 0x%lx\n", len);
return EINVAL;
}
return EINVAL;
}
- regionstart = r->vaddr;
+ regionstart = r->vaddr + offset;
- if(len == r->length) {
- SANITYCHECK(SCL_DETAIL);
- /* Whole region disappears. Unlink and free it. */
- region_remove(&vmp->vm_regions_avl, r->vaddr);
- map_free(r);
- } else {
+ /* unreference its memory */
+ map_subfree(r, offset, len);
+
+ /* if unmap was at start/end of this region, it actually shrinks */
+ if(offset == 0) {
struct phys_region *pr;
physr_iter iter;
- /* Region shrinks. First unreference its memory
- * and then shrink the region.
- */
- SANITYCHECK(SCL_DETAIL);
- map_subfree(r, len);
+
+ region_remove(&vmp->vm_regions_avl, r->vaddr);
+
USE(r,
r->vaddr += len;
r->length -= len;);
- physr_start_iter_least(r->phys, &iter);
+
+ region_insert(&vmp->vm_regions_avl, r);
/* vaddr has increased; to make all the phys_regions
* point to the same addresses, make them shrink by the
* same amount.
*/
+ physr_start_iter(r->phys, &iter, offset, AVL_GREATER_EQUAL);
+
while((pr = physr_get_iter(&iter))) {
- assert(pr->offset >= len);
+ assert(pr->offset >= offset);
USE(pr, pr->offset -= len;);
physr_incr_iter(&iter);
}
+ } else if(offset + len == r->length) {
+ assert(len <= r->length);
+ r->length -= len;
+ }
+
+ if(r->length == 0) {
+ /* Whole region disappears. Unlink and free it. */
+ region_remove(&vmp->vm_regions_avl, r->vaddr);
+ map_free(r);
}
SANITYCHECK(SCL_DETAIL);
physr_start_iter(region->phys, &iter, begin, AVL_GREATER_EQUAL);
while((pr = physr_get_iter(&iter)) && pr->offset < begin + length) {
- pb_unreferenced(region, pr);
+ pb_unreferenced(region, pr, 1);
physr_start_iter(region->phys, &iter, begin,
AVL_GREATER_EQUAL);
SLABFREE(pr);
MYASSERT(n->sdh.magic1 == MAGIC1);
MYASSERT(n->sdh.magic2 == MAGIC2);
#endif
- MYASSERT(n->sdh.list == l);
MYASSERT(usedpages_add(n->sdh.phys, VM_PAGE_SIZE) == OK);
if(n->sdh.prev)
MYASSERT(n->sdh.prev->sdh.next == n);
else
- MYASSERT(s->list_head[l] == n);
+ MYASSERT(s->list_head == n);
if(n->sdh.next) MYASSERT(n->sdh.next->sdh.prev == n);
for(i = 0; i < USEELEMENTS*8; i++)
if(i >= ITEMSPERPAGE(bytes))
{
int s;
for(s = 0; s < SLABSIZES; s++) {
- int l;
checklist(file, line, &slabs[s], s + MINSIZE);
}
}
struct slabdata *f;
int i;
+ bytes = roundup(bytes, OBJALIGN);
+
return (objstats(mem, bytes, &s, &f, &i) == OK);
}
#endif
n++;
if(n%1000) return;
for(s = 0; s < SLABSIZES; s++) {
- int l;
int b, t;
b = s + MINSIZE;
t = checklist(__FILE__, __LINE__, &slabs[s], b);