[BACK]Return to vm_nommu.c CVS log [TXT][DIR] Up to [local] / prex-old / sys / mem

Annotation of prex-old/sys/mem/vm_nommu.c, Revision 1.1.1.1

1.1       nbrk        1: /*-
                      2:  * Copyright (c) 2005-2006, Kohsuke Ohtani
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. Neither the name of the author nor the names of any co-contributors
                     14:  *    may be used to endorse or promote products derived from this software
                     15:  *    without specific prior written permission.
                     16:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     27:  * SUCH DAMAGE.
                     28:  */
                     29:
                     30: /*
                     31:  * vm_nommu.c - virtual memory functions for no MMU systems
                     32:  */
                     33:
                     34: /*
                     35:  * When the platform does not support memory management unit (MMU)
                     36:  * all virtual memories are mapped to the physical memory. So, the
                     37:  * memory space is shared among all tasks and kernel.
                     38:  *
                     39:  * Important: The lists of regions are not sorted by address.
                     40:  */
                     41:
                     42: #include <kernel.h>
                     43: #include <kmem.h>
                     44: #include <thread.h>
                     45: #include <page.h>
                     46: #include <task.h>
                     47: #include <sched.h>
                     48: #include <vm.h>
                     49:
                     50: #ifdef CONFIG_VMTRACE
                     51: static void vm_error(const char *, int);
                     52: #define LOG(x)         printk x
                     53: #define CHK(fn,x)      do { if (x) vm_error(fn, x); } while (0)
                     54: #else
                     55: #define LOG(x)
                     56: #define CHK(fn,x)
                     57: #endif
                     58:
                     59: /* forward declarations */
                     60: static struct region *region_create(struct region *, u_long, size_t);
                     61: static void region_delete(struct region *, struct region *);
                     62: static struct region *region_find(struct region *, u_long, size_t);
                     63: static void region_free(struct region *, struct region *);
                     64: static void region_init(struct region *);
                     65: static int do_allocate(vm_map_t, void **, size_t, int);
                     66: static int do_free(vm_map_t, void *);
                     67: static int do_attribute(vm_map_t, void *, int);
                     68: static int do_map(vm_map_t, void *, size_t, void **);
                     69:
                     70: /* vm mapping for kernel task */
                     71: static struct vm_map kern_map;
                     72:
                     73: /**
                     74:  * vm_allocate - allocate zero-filled memory for specified address
                     75:  * @task:     task id to allocate memory
                     76:  * @addr:     required address. set an allocated address in return.
                     77:  * @size:     allocation size
                     78:  * @anywhere: if it is true, the "addr" argument will be ignored.
                     79:  *            In this case, the address of free space will be found
                     80:  *            automatically.
                     81:  *
                     82:  * The allocated area has writable, user-access attribute by default.
                     83:  * The "addr" and "size" argument will be adjusted to page boundary.
                     84:  */
                     85: int
                     86: vm_allocate(task_t task, void **addr, size_t size, int anywhere)
                     87: {
                     88:        int err;
                     89:        void *uaddr;
                     90:
                     91:        LOG(("vm_aloc: task=%s addr=%x size=%x anywhere=%d\n",
                     92:             task->name ? task->name : "no name", *addr, size, anywhere));
                     93:
                     94:        sched_lock();
                     95:
                     96:        if (!task_valid(task)) {
                     97:                err = ESRCH;
                     98:        } else if (task != cur_task() && !task_capable(CAP_MEMORY)) {
                     99:                err = EPERM;
                    100:        } else if (umem_copyin(addr, &uaddr, sizeof(void *))) {
                    101:                err = EFAULT;
                    102:        } else if (anywhere == 0 && !user_area(*addr)) {
                    103:                err = EACCES;
                    104:        } else {
                    105:                err = do_allocate(task->map, &uaddr, size, anywhere);
                    106:                if (err == 0) {
                    107:                        if (umem_copyout(&uaddr, addr, sizeof(void *)))
                    108:                                err = EFAULT;
                    109:                }
                    110:        }
                    111:        sched_unlock();
                    112:        CHK("vm_allocate", err);
                    113:        return err;
                    114: }
                    115:
                    116: static int
                    117: do_allocate(vm_map_t map, void **addr, size_t size, int anywhere)
                    118: {
                    119:        struct region *reg;
                    120:        u_long start, end;
                    121:
                    122:        if (size == 0)
                    123:                return EINVAL;
                    124:
                    125:        /*
                    126:         * Allocate region, and reserve pages for it.
                    127:         */
                    128:        if (anywhere) {
                    129:                size = (size_t)PAGE_ALIGN(size);
                    130:                if ((start = (u_long)page_alloc(size)) == 0)
                    131:                        return ENOMEM;
                    132:        } else {
                    133:                start = PAGE_TRUNC(*addr);
                    134:                end = PAGE_ALIGN(start + size);
                    135:                size = (size_t)(end - start);
                    136:
                    137:                if (page_reserve((void *)start, size))
                    138:                        return EINVAL;
                    139:        }
                    140:        reg = region_create(&map->head, start, size);
                    141:        if (reg == NULL) {
                    142:                page_free((void *)start, size);
                    143:                return ENOMEM;
                    144:        }
                    145:        reg->flags = REG_READ | REG_WRITE;
                    146:
                    147:        /* Zero fill */
                    148:        memset((void *)start, 0, size);
                    149:        *addr = (void *)reg->addr;
                    150:        return 0;
                    151: }
                    152:
                    153: /*
                    154:  * Deallocate memory region for specified address.
                    155:  *
                    156:  * The "addr" argument points to a memory region previously
                    157:  * allocated through a call to vm_allocate() or vm_map(). The number
                    158:  * of bytes freed is the number of bytes of the allocated region.
                    159:  * If one of the region of previous and next are free, it combines
                    160:  * with them, and larger free region is created.
                    161:  */
                    162: int
                    163: vm_free(task_t task, void *addr)
                    164: {
                    165:        int err;
                    166:
                    167:        LOG(("vm_free: task=%s addr=%x\n",
                    168:             task->name ? task->name : "no name", addr));
                    169:
                    170:        sched_lock();
                    171:        if (!task_valid(task)) {
                    172:                err = ESRCH;
                    173:        } else if (task != cur_task() && !task_capable(CAP_MEMORY)) {
                    174:                err = EPERM;
                    175:        } else if (!user_area(addr)) {
                    176:                err = EFAULT;
                    177:        } else {
                    178:                err = do_free(task->map, addr);
                    179:        }
                    180:        sched_unlock();
                    181:        CHK("vm_free", err);
                    182:        return err;
                    183: }
                    184:
                    185: static int
                    186: do_free(vm_map_t map, void *addr)
                    187: {
                    188:        struct region *reg;
                    189:
                    190:        addr = (void *)PAGE_TRUNC(addr);
                    191:
                    192:        /*
                    193:         * Find the target region.
                    194:         */
                    195:        reg = region_find(&map->head, (u_long)addr, 1);
                    196:        if (reg == NULL || reg->addr != (u_long)addr ||
                    197:            (reg->flags & REG_FREE))
                    198:                return EINVAL;  /* not allocated */
                    199:
                    200:        /*
                    201:         * Free pages if it is not shared and mapped.
                    202:         */
                    203:        if (!(reg->flags & REG_SHARED) && !(reg->flags & REG_MAPPED))
                    204:                page_free((void *)reg->addr, reg->size);
                    205:
                    206:        region_free(&map->head, reg);
                    207:        return 0;
                    208: }
                    209:
                    210: /*
                    211:  * Change attribute of specified virtual address.
                    212:  *
                    213:  * The "addr" argument points to a memory region previously allocated
                    214:  * through a call to vm_allocate(). The attribute type can be chosen
                    215:  * a combination of VMA_READ, VMA_WRITE.
                    216:  * Note: VMA_EXEC is not supported, yet.
                    217:  */
                    218: int
                    219: vm_attribute(task_t task, void *addr, int attr)
                    220: {
                    221:        int err;
                    222:
                    223:        LOG(("vm_attr: task=%s addr=%x attr=%x\n",
                    224:             task->name ? task->name : "no name", addr, attr));
                    225:
                    226:        sched_lock();
                    227:        if (attr == 0 || attr & ~(VMA_READ | VMA_WRITE)) {
                    228:                err = EINVAL;
                    229:        } else if (!task_valid(task)) {
                    230:                err = ESRCH;
                    231:        } else if (task != cur_task() && !task_capable(CAP_MEMORY)) {
                    232:                err = EPERM;
                    233:        } else if (!user_area(addr)) {
                    234:                err = EFAULT;
                    235:        } else {
                    236:                err = do_attribute(task->map, addr, attr);
                    237:        }
                    238:        sched_unlock();
                    239:        CHK("vm_attribute", err);
                    240:        return err;
                    241: }
                    242:
                    243: static int
                    244: do_attribute(vm_map_t map, void *addr, int attr)
                    245: {
                    246:        struct region *reg;
                    247:        int new_flags = 0;
                    248:
                    249:        addr = (void *)PAGE_TRUNC(addr);
                    250:
                    251:        /*
                    252:         * Find the target region.
                    253:         */
                    254:        reg = region_find(&map->head, (u_long)addr, 1);
                    255:        if (reg == NULL || reg->addr != (u_long)addr ||
                    256:            (reg->flags & REG_FREE)) {
                    257:                return EINVAL;  /* not allocated */
                    258:        }
                    259:        /*
                    260:         * The attribute of the mapped or shared region can not be changed.
                    261:         */
                    262:        if ((reg->flags & REG_MAPPED) || (reg->flags & REG_SHARED))
                    263:                return EINVAL;
                    264:
                    265:        /*
                    266:         * Check new and old flag.
                    267:         */
                    268:        if (reg->flags & REG_WRITE) {
                    269:                if (!(attr & VMA_WRITE))
                    270:                        new_flags = REG_READ;
                    271:        } else {
                    272:                if (attr & VMA_WRITE)
                    273:                        new_flags = REG_READ | REG_WRITE;
                    274:        }
                    275:        if (new_flags == 0)
                    276:                return 0;       /* same attribute */
                    277:        reg->flags = new_flags;
                    278:        return 0;
                    279: }
                    280:
                    281: /**
                    282:  * vm_map - map another task's memory to current task.
                    283:  * @target: memory owner
                    284:  * @addr:   target address
                    285:  * @size:   map size
                    286:  * @alloc:  map address returned
                    287:  *
                    288:  * Note: This routine does not support mapping to the specific address.
                    289:  */
                    290: int
                    291: vm_map(task_t target, void *addr, size_t size, void **alloc)
                    292: {
                    293:        int err;
                    294:
                    295:        LOG(("vm_map : task=%s addr=%x size=%x\n",
                    296:             target->name ? target->name : "no name", addr, size));
                    297:
                    298:        sched_lock();
                    299:        if (!task_valid(target)) {
                    300:                err = ESRCH;
                    301:        } else if (target == cur_task()) {
                    302:                err = EINVAL;
                    303:        } else if (!task_capable(CAP_MEMORY)) {
                    304:                err = EPERM;
                    305:        } else if (!user_area(addr)) {
                    306:                err = EFAULT;
                    307:        } else {
                    308:                err = do_map(target->map, addr, size, alloc);
                    309:        }
                    310:        sched_unlock();
                    311:        CHK("vm_map", err);
                    312:        return err;
                    313: }
                    314:
                    315: static int
                    316: do_map(vm_map_t map, void *addr, size_t size, void **alloc)
                    317: {
                    318:        vm_map_t curmap;
                    319:        u_long start, end;
                    320:        struct region *reg, *tgt;
                    321:        void *tmp;
                    322:
                    323:        if (size == 0)
                    324:                return EINVAL;
                    325:
                    326:        /* check fault */
                    327:        tmp = NULL;
                    328:        if (umem_copyout(&tmp, alloc, sizeof(void *)))
                    329:                return EFAULT;
                    330:
                    331:        start = PAGE_TRUNC(addr);
                    332:        end = PAGE_ALIGN((u_long)addr + size);
                    333:        size = (size_t)(end - start);
                    334:
                    335:        /*
                    336:         * Find the region that includes target address
                    337:         */
                    338:        reg = region_find(&map->head, start, size);
                    339:        if (reg == NULL || (reg->flags & REG_FREE))
                    340:                return EINVAL;  /* not allocated */
                    341:        tgt = reg;
                    342:
                    343:        /*
                    344:         * Create new region to map
                    345:         */
                    346:        curmap = cur_task()->map;
                    347:        reg = region_create(&curmap->head, start, size);
                    348:        if (reg == NULL)
                    349:                return ENOMEM;
                    350:        reg->flags = tgt->flags | REG_MAPPED;
                    351:
                    352:        umem_copyout(&addr, alloc, sizeof(void *));
                    353:        return 0;
                    354: }
                    355:
                    356: /*
                    357:  * Create new virtual memory space.
                    358:  * No memory is inherited.
                    359:  * Must be called with scheduler locked.
                    360:  */
                    361: vm_map_t
                    362: vm_create(void)
                    363: {
                    364:        vm_map_t map;
                    365:
                    366:        /* Allocate new map structure */
                    367:        if ((map = kmem_alloc(sizeof(struct vm_map))) == NULL)
                    368:                return NULL;
                    369:
                    370:        map->ref_count = 1;
                    371:        region_init(&map->head);
                    372:        return map;
                    373: }
                    374:
                    375: /*
                    376:  * Terminate specified virtual memory space.
                    377:  * This is called when task is terminated.
                    378:  */
                    379: void
                    380: vm_terminate(vm_map_t map)
                    381: {
                    382:        struct region *reg, *tmp;
                    383:
                    384:        if (--map->ref_count >= 1)
                    385:                return;
                    386:
                    387:        sched_lock();
                    388:        reg = &map->head;
                    389:        do {
                    390:                if (reg->flags != REG_FREE) {
                    391:                        /* Free region if it is not shared and mapped */
                    392:                        if (!(reg->flags & REG_SHARED) &&
                    393:                            !(reg->flags & REG_MAPPED)) {
                    394:                                page_free((void *)reg->addr, reg->size);
                    395:                        }
                    396:                }
                    397:                tmp = reg;
                    398:                reg = reg->next;
                    399:                region_delete(&map->head, tmp);
                    400:        } while (reg != &map->head);
                    401:
                    402:        kmem_free(map);
                    403:        sched_unlock();
                    404: }
                    405:
                    406: /*
                    407:  * Duplicate specified virtual memory space.
                    408:  */
                    409: vm_map_t
                    410: vm_fork(vm_map_t org_map)
                    411: {
                    412:        /*
                    413:         * This function is not supported with no MMU system.
                    414:         */
                    415:        return NULL;
                    416: }
                    417:
                    418: /*
                    419:  * Switch VM mapping.
                    420:  */
                    421: void
                    422: vm_switch(vm_map_t map)
                    423: {
                    424: }
                    425:
                    426: /*
                    427:  * Increment reference count of VM mapping.
                    428:  */
                    429: int
                    430: vm_reference(vm_map_t map)
                    431: {
                    432:
                    433:        map->ref_count++;
                    434:        return 0;
                    435: }
                    436:
                    437: /*
                    438:  * Translate virtual address of current task to physical address.
                    439:  * Returns physical address on success, or NULL if no mapped memory.
                    440:  */
                    441: void *
                    442: vm_translate(void *addr, size_t size)
                    443: {
                    444:        return addr;
                    445: }
                    446:
                    447: /*
                    448:  * Check if specified access can be allowed.
                    449:  * return 0 on success, or EFAULT on failure.
                    450:  */
                    451: int
                    452: vm_access(void *addr, size_t size, int type)
                    453: {
                    454:        u_long start, end;
                    455:        int err;
                    456:        char tmp;
                    457:
                    458:        ASSERT(size);
                    459:        start = (u_long)addr;
                    460:        end = (u_long)addr + size - 1;
                    461:        if ((err = umem_copyin((void *)start, &tmp, 1)))
                    462:                return EFAULT;
                    463:        if (type == VMA_WRITE) {
                    464:                if ((err = umem_copyout(&tmp, (void *)start, 1)))
                    465:                        return EFAULT;
                    466:        }
                    467:        if ((err = umem_copyin((void *)end, &tmp, 1)))
                    468:                return EFAULT;
                    469:        if (type == VMA_WRITE) {
                    470:                if ((err = umem_copyout(&tmp, (void *)end, 1)))
                    471:                        return EFAULT;
                    472:        }
                    473:        return 0;
                    474: }
                    475:
                    476: /*
                    477:  * Reserve specific area for boot tasks.
                    478:  */
                    479: static int
                    480: do_reserve(vm_map_t map, void **addr, size_t size)
                    481: {
                    482:        struct region *reg;
                    483:        u_long start, end;
                    484:
                    485:        if (size == 0)
                    486:                return EINVAL;
                    487:
                    488:        start = PAGE_TRUNC(*addr);
                    489:        end = PAGE_ALIGN(start + size);
                    490:        size = (size_t)(end - start);
                    491:
                    492:        reg = region_create(&map->head, start, size);
                    493:        if (reg == NULL)
                    494:                return ENOMEM;
                    495:        reg->flags = REG_READ | REG_WRITE;
                    496:        *addr = (void *)reg->addr;
                    497:        return 0;
                    498: }
                    499:
                    500: /*
                    501:  * Setup task image for boot task. (NOMMU version)
                    502:  * Return 0 on success, -1 on failure.
                    503:  *
                    504:  * Note: We assume that the task images are already copied to
                    505:  * the proper address by a boot loader.
                    506:  */
                    507: int
                    508: vm_load(vm_map_t map, struct module *m, void **stack)
                    509: {
                    510:        void *base;
                    511:        size_t size;
                    512:
                    513:        printk("Loading task:\'%s\'\n", m->name);
                    514:
                    515:        /*
                    516:         * Reserve text & data area
                    517:         */
                    518:        base = (void *)m->text;
                    519:        size = m->textsz + m->datasz + m->bsssz;
                    520:        if (do_reserve(map, &base, size))
                    521:                return -1;
                    522:        if (m->bsssz != 0)
                    523:                memset((void *)(m->data + m->datasz), 0, m->bsssz);
                    524:
                    525:        /*
                    526:         * Create stack
                    527:         */
                    528:        if (do_allocate(map, stack, USTACK_SIZE, 1))
                    529:                return -1;
                    530:        return 0;
                    531: }
                    532:
                    533: /*
                    534:  * Create new free region after the specified region.
                    535:  * Returns region on success, or NULL on failure.
                    536:  */
                    537: static struct region *
                    538: region_create(struct region *prev, u_long addr, size_t size)
                    539: {
                    540:        struct region *reg;
                    541:
                    542:        if ((reg = kmem_alloc(sizeof(struct region))) == NULL)
                    543:                return NULL;
                    544:
                    545:        reg->addr = addr;
                    546:        reg->size = size;
                    547:        reg->flags = REG_FREE;
                    548:        reg->sh_next = reg->sh_prev = reg;
                    549:
                    550:        reg->next = prev->next;
                    551:        reg->prev = prev;
                    552:        prev->next->prev = reg;
                    553:        prev->next = reg;
                    554:        return reg;
                    555: }
                    556:
                    557: /*
                    558:  * Delete specified region
                    559:  */
                    560: static void
                    561: region_delete(struct region *head, struct region *reg)
                    562: {
                    563:
                    564:        /*
                    565:         * If it is shared region, unlink from shared list.
                    566:         */
                    567:        if (reg->flags & REG_SHARED) {
                    568:                reg->sh_prev->sh_next = reg->sh_next;
                    569:                reg->sh_next->sh_prev = reg->sh_prev;
                    570:                if (reg->sh_prev == reg->sh_next)
                    571:                        reg->sh_prev->flags &= ~REG_SHARED;
                    572:        }
                    573:        if (head != reg)
                    574:                kmem_free(reg);
                    575: }
                    576:
                    577: /*
                    578:  * Find the region at the specified area.
                    579:  */
                    580: static struct region *
                    581: region_find(struct region *head, u_long addr, size_t size)
                    582: {
                    583:        struct region *reg;
                    584:
                    585:        reg = head;
                    586:        do {
                    587:                if (reg->addr <= addr &&
                    588:                    reg->addr + reg->size >= addr + size) {
                    589:                        return reg;
                    590:                }
                    591:                reg = reg->next;
                    592:        } while (reg != head);
                    593:        return NULL;
                    594: }
                    595:
                    596: /*
                    597:  * Free specified region
                    598:  */
                    599: static void
                    600: region_free(struct region *head, struct region *reg)
                    601: {
                    602:        ASSERT(reg->flags != REG_FREE);
                    603:
                    604:        /*
                    605:         * If it is shared region, unlink from shared list.
                    606:         */
                    607:        if (reg->flags & REG_SHARED) {
                    608:                reg->sh_prev->sh_next = reg->sh_next;
                    609:                reg->sh_next->sh_prev = reg->sh_prev;
                    610:                if (reg->sh_prev == reg->sh_next)
                    611:                        reg->sh_prev->flags &= ~REG_SHARED;
                    612:        }
                    613:        reg->prev->next = reg->next;
                    614:        reg->next->prev = reg->prev;
                    615:        kmem_free(reg);
                    616: }
                    617:
                    618: /*
                    619:  * Initialize region
                    620:  */
                    621: static void
                    622: region_init(struct region *reg)
                    623: {
                    624:
                    625:        reg->next = reg->prev = reg;
                    626:        reg->sh_next = reg->sh_prev = reg;
                    627:        reg->addr = 0;
                    628:        reg->size = 0;
                    629:        reg->flags = REG_FREE;
                    630: }
                    631:
                    632: #if defined(DEBUG) && defined(CONFIG_KDUMP)
                    633: void
                    634: vm_dump_one(task_t task)
                    635: {
                    636:        vm_map_t map;
                    637:        struct region *reg;
                    638:        char flags[6];
                    639:        u_long total = 0;
                    640:
                    641:        printk("task=%x map=%x name=%s\n", task, task->map,
                    642:               task->name ? task->name : "no name");
                    643:        printk(" region   virtual  size     flags\n");
                    644:        printk(" -------- -------- -------- -----\n");
                    645:
                    646:        map = task->map;
                    647:        reg = &map->head;
                    648:        do {
                    649:                if (reg->flags != REG_FREE) {
                    650:                        strlcpy(flags, "-----", 6);
                    651:                        if (reg->flags & REG_READ)
                    652:                                flags[0] = 'R';
                    653:                        if (reg->flags & REG_WRITE)
                    654:                                flags[1] = 'W';
                    655:                        if (reg->flags & REG_EXEC)
                    656:                                flags[2] = 'E';
                    657:                        if (reg->flags & REG_SHARED)
                    658:                                flags[3] = 'S';
                    659:                        if (reg->flags & REG_MAPPED)
                    660:                                flags[4] = 'M';
                    661:
                    662:                        printk(" %08x %08x %08x %s\n", reg,
                    663:                               reg->addr, reg->size, flags);
                    664:                        if ((reg->flags & REG_MAPPED) == 0)
                    665:                                total += reg->size;
                    666:                }
                    667:                reg = reg->next;
                    668:        } while (reg != &map->head);    /* Process all regions */
                    669:        printk(" *total=%dK bytes\n\n", total / 1024);
                    670: }
                    671:
                    672: void
                    673: vm_dump(void)
                    674: {
                    675:        list_t n;
                    676:        task_t task;
                    677:
                    678:        printk("\nVM dump:\n");
                    679:        n = &kern_task.link;
                    680:        do {
                    681:                task = list_entry(n, struct task, link);
                    682:                ASSERT(task_valid(task));
                    683:                vm_dump_one(task);
                    684:                n = list_next(n);
                    685:        } while (n != &kern_task.link);
                    686: }
                    687: #endif
                    688:
                    689:
                    690: #ifdef CONFIG_VMTRACE
                    691: static void
                    692: vm_error(const char *func, int err)
                    693: {
                    694:        printk("Error!!: %s returns err=%x\n", func, err);
                    695: }
                    696: #endif
                    697:
                    698: void
                    699: vm_init(void)
                    700: {
                    701:
                    702:        region_init(&kern_map.head);
                    703:        kern_task.map = &kern_map;
                    704: }

CVSweb