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

Diff for /prex-old/sys/mem/vm.c between version 1.1.1.1 and 1.1.1.1.2.1

version 1.1.1.1, 2008/06/03 10:38:46 version 1.1.1.1.2.1, 2008/08/13 17:12:32
Line 28 
Line 28 
  */   */
   
 /*  /*
  * vm.c - virtual memory manager   * vm.c - virtual memory allocator
  */   */
   
 /*  /*
Line 52 
Line 52 
 #include <sched.h>  #include <sched.h>
 #include <vm.h>  #include <vm.h>
   
 #ifdef CONFIG_VMTRACE  
 static void vm_error(const char *, int);  
 #define LOG(x)          printk x  
 #define CHK(fn,x)       do { if (x) vm_error(fn, x); } while (0)  
 #else  
 #define LOG(x)  
 #define CHK(fn,x)  
 #endif  
   
 /* forward declarations */  /* forward declarations */
 static struct region *region_create(struct region *, u_long, size_t);  static struct region *region_create(struct region *, void *, size_t);
 static void region_delete(struct region *, struct region *);  static void region_delete(struct region *, struct region *);
 static struct region *region_find(struct region *, u_long, size_t);  static struct region *region_find(struct region *, void *, size_t);
 static struct region *region_alloc(struct region *, size_t);  static struct region *region_alloc(struct region *, size_t);
 static void region_free(struct region *, struct region *);  static void region_free(struct region *, struct region *);
 static struct region *region_split(struct region *, struct region *,  static struct region *region_split(struct region *, struct region *,
                                    u_long, size_t);                                     void *, size_t);
 static void region_init(struct region *);  static void region_init(struct region *);
 static int do_allocate(vm_map_t, void **, size_t, int);  static int do_allocate(vm_map_t, void **, size_t, int);
 static int do_free(vm_map_t, void *);  static int do_free(vm_map_t, void *);
 static int do_attribute(vm_map_t, void *, int);  static int do_attribute(vm_map_t, void *, int);
 static int do_map(vm_map_t, void *, size_t, void **);  static int do_map(vm_map_t, void *, size_t, void **);
 static vm_map_t do_fork(vm_map_t);  static vm_map_t do_fork(vm_map_t);
   
   
 /* vm mapping for kernel task */  /* vm mapping for kernel task */
 static struct vm_map kern_map;  static struct vm_map kern_map;
   
 /**  /**
  * vm_allocate - allocate zero-filled memory for specified address   * vm_allocate - allocate zero-filled memory for specified address
  * @task:     task id to allocate memory  
  * @addr:     required address. set an allocated address in return.  
  * @size:     allocation size  
  * @anywhere: if it is true, the "addr" argument will be ignored.  
  *            In this case, the address of free space will be found  
  *            automatically.  
  *   *
  * The allocated area has writable, user-access attribute by default.   * If "anywhere" argument is true, the "addr" argument will be
  * The "addr" and "size" argument will be adjusted to page boundary.   * ignored.  In this case, the address of free space will be
    * found automatically.
    *
    * The allocated area has writable, user-access attribute by
    * default.  The "addr" and "size" argument will be adjusted
    * to page boundary.
  */   */
 int  int
 vm_allocate(task_t task, void **addr, size_t size, int anywhere)  vm_allocate(task_t task, void **addr, size_t size, int anywhere)
Line 97 
Line 88 
         int err;          int err;
         void *uaddr;          void *uaddr;
   
         LOG(("vm_aloc: task=%s addr=%x size=%x anywhere=%d\n",  
              task->name ? task->name : "no name", *addr, size, anywhere));  
   
         sched_lock();          sched_lock();
   
         if (!task_valid(task)) {          if (!task_valid(task)) {
                 err = ESRCH;                  err = ESRCH;
         } else if (task != cur_task() && !task_capable(CAP_MEMORY)) {                  goto out;
           }
           if (task != cur_task() && !task_capable(CAP_MEMORY)) {
                 err = EPERM;                  err = EPERM;
         } else if (umem_copyin(addr, &uaddr, sizeof(void *))) {                  goto out;
           }
           if (umem_copyin(addr, &uaddr, sizeof(void *))) {
                 err = EFAULT;                  err = EFAULT;
         } else if (anywhere == 0 && !user_area(*addr)) {                  goto out;
           }
           if (anywhere == 0 && !user_area(*addr)) {
                 err = EACCES;                  err = EACCES;
         } else {                  goto out;
                 err = do_allocate(task->map, &uaddr, size, anywhere);  
                 if (err == 0) {  
                         if (umem_copyout(&uaddr, addr, sizeof(void *)))  
                                 err = EFAULT;  
                 }  
         }          }
   
           err = do_allocate(task->map, &uaddr, size, anywhere);
           if (err == 0) {
                   if (umem_copyout(&uaddr, addr, sizeof(void *)))
                           err = EFAULT;
           }
    out:
         sched_unlock();          sched_unlock();
         CHK("vm_allocate", err);  
         return err;          return err;
 }  }
   
Line 126 
Line 121 
 do_allocate(vm_map_t map, void **addr, size_t size, int anywhere)  do_allocate(vm_map_t map, void **addr, size_t size, int anywhere)
 {  {
         struct region *reg;          struct region *reg;
         u_long start, end, phys;          char *start, *end, *phys;
   
         if (size == 0)          if (size == 0)
                 return EINVAL;                  return EINVAL;
Line 139 
Line 134 
                 if ((reg = region_alloc(&map->head, size)) == NULL)                  if ((reg = region_alloc(&map->head, size)) == NULL)
                         return ENOMEM;                          return ENOMEM;
         } else {          } else {
                 start = PAGE_TRUNC(*addr);                  start = (char *)PAGE_TRUNC(*addr);
                 end = PAGE_ALIGN(start + size);                  end = (char *)PAGE_ALIGN(start + size);
                 size = (size_t)(end - start);                  size = (size_t)(end - start);
   
                 reg = region_find(&map->head, start, size);                  reg = region_find(&map->head, start, size);
Line 151 
Line 146 
                 if (reg == NULL)                  if (reg == NULL)
                         return ENOMEM;                          return ENOMEM;
         }          }
   
         reg->flags = REG_READ | REG_WRITE;          reg->flags = REG_READ | REG_WRITE;
   
         /*          /*
          * Allocate physical pages, and map them into virtual address           * Allocate physical pages, and map them into virtual address
          */           */
         if ((phys = (u_long)page_alloc(size)) == 0)          if ((phys = page_alloc(size)) == 0)
                 goto err1;                  goto err1;
   
         if (mmu_map(map->pgd, (void *)phys, (void *)reg->addr,          if (mmu_map(map->pgd, phys, reg->addr, size, PG_WRITE))
                     size, PG_WRITE))  
                 goto err2;                  goto err2;
   
         reg->phys = phys;          reg->phys = phys;
   
         /* Zero fill */          /* Zero fill */
         memset(phys_to_virt(phys), 0, reg->size);          memset(phys_to_virt(phys), 0, reg->size);
         *addr = (void *)reg->addr;          *addr = reg->addr;
         return 0;          return 0;
   
  err2:   err2:
         page_free((void *)phys, size);          page_free(phys, size);
  err1:   err1:
         region_free(&map->head, reg);          region_free(&map->head, reg);
         return ENOMEM;          return ENOMEM;
Line 182 
Line 175 
  * Deallocate memory region for specified address.   * Deallocate memory region for specified address.
  *   *
  * The "addr" argument points to a memory region previously   * The "addr" argument points to a memory region previously
  * allocated through a call to vm_allocate() or vm_map(). The number   * allocated through a call to vm_allocate() or vm_map(). The
  * of bytes freed is the number of bytes of the allocated region.   * number of bytes freed is the number of bytes of the
  * If one of the region of previous and next are free, it combines   * allocated region. If one of the region of previous and next
  * with them, and larger free region is created.   * are free, it combines with them, and larger free region is
    * created.
  */   */
 int  int
 vm_free(task_t task, void *addr)  vm_free(task_t task, void *addr)
 {  {
         int err;          int err;
   
         LOG(("vm_free: task=%s addr=%x\n",  
              task->name ? task->name : "no name", addr));  
   
         sched_lock();          sched_lock();
         if (!task_valid(task)) {          if (!task_valid(task)) {
                 err = ESRCH;                  err = ESRCH;
         } else if (task != cur_task() && !task_capable(CAP_MEMORY)) {                  goto out;
           }
           if (task != cur_task() && !task_capable(CAP_MEMORY)) {
                 err = EPERM;                  err = EPERM;
         } else if (!user_area(addr)) {                  goto out;
           }
           if (!user_area(addr)) {
                 err = EFAULT;                  err = EFAULT;
         } else {                  goto out;
                 err = do_free(task->map, addr);  
         }          }
   
           err = do_free(task->map, addr);
    out:
         sched_unlock();          sched_unlock();
         CHK("vm_free", err);  
         return err;          return err;
 }  }
   
Line 220 
Line 216 
         /*          /*
          * Find the target region.           * Find the target region.
          */           */
         reg = region_find(&map->head, (u_long)addr, 1);          reg = region_find(&map->head, addr, 1);
         if (reg == NULL || reg->addr != (u_long)addr ||          if (reg == NULL || reg->addr != addr || (reg->flags & REG_FREE))
             (reg->flags & REG_FREE))  
                 return EINVAL;                  return EINVAL;
   
         /*          /*
          * Unmap pages of the region.           * Unmap pages of the region.
          */           */
         mmu_map(map->pgd, (void *)reg->phys, (void *)reg->addr,          mmu_map(map->pgd, reg->phys, reg->addr, reg->size, PG_UNMAP);
                 reg->size, PG_UNMAP);  
   
         /*          /*
          * Free pages if it is not shared and mapped.           * Relinquish use of the page if it is not shared and mapped.
          */           */
         if (!(reg->flags & REG_SHARED) && !(reg->flags & REG_MAPPED))          if (!(reg->flags & REG_SHARED) && !(reg->flags & REG_MAPPED))
                 page_free((void *)reg->phys, reg->size);                  page_free(reg->phys, reg->size);
   
         region_free(&map->head, reg);          region_free(&map->head, reg);
         return 0;          return 0;
Line 244 
Line 238 
 /*  /*
  * Change attribute of specified virtual address.   * Change attribute of specified virtual address.
  *   *
  * The "addr" argument points to a memory region previously allocated   * The "addr" argument points to a memory region previously
  * through a call to vm_allocate(). The attribute type can be chosen   * allocated through a call to vm_allocate(). The attribute
  * a combination of VMA_READ, VMA_WRITE.   * type can be chosen a combination of VMA_READ, VMA_WRITE.
  * Note: VMA_EXEC is not supported, yet.   * Note: VMA_EXEC is not supported, yet.
  */   */
 int  int
Line 254 
Line 248 
 {  {
         int err;          int err;
   
         LOG(("vm_attribute: task=%s addr=%x attr=%x\n",  
              task->name ? task->name : "no name", addr, attr));  
   
         sched_lock();          sched_lock();
         if (attr == 0 || attr & ~(VMA_READ | VMA_WRITE)) {          if (attr == 0 || attr & ~(VMA_READ | VMA_WRITE)) {
                 err = EINVAL;                  err = EINVAL;
         } else if (!task_valid(task)) {                  goto out;
           }
           if (!task_valid(task)) {
                 err = ESRCH;                  err = ESRCH;
         } else if (task != cur_task() && !task_capable(CAP_MEMORY)) {                  goto out;
           }
           if (task != cur_task() && !task_capable(CAP_MEMORY)) {
                 err = EPERM;                  err = EPERM;
         } else if (!user_area(addr)) {                  goto out;
           }
           if (!user_area(addr)) {
                 err = EFAULT;                  err = EFAULT;
         } else {                  goto out;
                 err = do_attribute(task->map, addr, attr);  
         }          }
   
           err = do_attribute(task->map, addr, attr);
    out:
         sched_unlock();          sched_unlock();
         CHK("vm_attribute", err);  
         return err;          return err;
 }  }
   
Line 279 
Line 277 
 {  {
         struct region *reg;          struct region *reg;
         int new_flags = 0;          int new_flags = 0;
         u_long old_addr, new_addr = 0;          void *old_addr, *new_addr = NULL;
         int map_type;          int map_type;
   
         addr = (void *)PAGE_TRUNC(addr);          addr = (void *)PAGE_TRUNC(addr);
Line 287 
Line 285 
         /*          /*
          * Find the target region.           * Find the target region.
          */           */
         reg = region_find(&map->head, (u_long)addr, 1);          reg = region_find(&map->head, addr, 1);
         if (reg == NULL || reg->addr != (u_long)addr ||          if (reg == NULL || reg->addr != addr || (reg->flags & REG_FREE)) {
             (reg->flags & REG_FREE)) {  
                 return EINVAL;  /* not allocated */                  return EINVAL;  /* not allocated */
         }          }
         /*          /*
Line 321 
Line 318 
                 old_addr = reg->phys;                  old_addr = reg->phys;
   
                 /* Allocate new physical page. */                  /* Allocate new physical page. */
                 if ((new_addr = (u_long)page_alloc(reg->size)) == 0)                  if ((new_addr = page_alloc(reg->size)) == 0)
                         return ENOMEM;                          return ENOMEM;
   
                 /* Copy source page */                  /* Copy source page */
Line 329 
Line 326 
                        reg->size);                         reg->size);
   
                 /* Map new region */                  /* Map new region */
                 if (mmu_map(map->pgd, (void *)new_addr, (void *)reg->addr,                  if (mmu_map(map->pgd, new_addr, reg->addr, reg->size,
                             reg->size, map_type)) {                              map_type)) {
                         page_free((void *)new_addr, reg->size);                          page_free(new_addr, reg->size);
                         return ENOMEM;                          return ENOMEM;
                 }                  }
                 reg->phys = new_addr;                  reg->phys = new_addr;
Line 343 
Line 340 
                         reg->sh_prev->flags &= ~REG_SHARED;                          reg->sh_prev->flags &= ~REG_SHARED;
                 reg->sh_next = reg->sh_prev = reg;                  reg->sh_next = reg->sh_prev = reg;
         } else {          } else {
                 if (mmu_map(map->pgd, (void *)reg->phys, (void *)reg->addr,                  if (mmu_map(map->pgd, reg->phys, reg->addr, reg->size,
                             reg->size, map_type))                              map_type))
                         return ENOMEM;                          return ENOMEM;
         }          }
         reg->flags = new_flags;          reg->flags = new_flags;
Line 353 
Line 350 
   
 /**  /**
  * vm_map - map another task's memory to current task.   * vm_map - map another task's memory to current task.
  * @target: memory owner  
  * @addr:   target address  
  * @size:   map size  
  * @alloc:  map address returned  
  *   *
  * Note: This routine does not support mapping to the specific address.   * Note: This routine does not support mapping to the specific address.
  */   */
Line 365 
Line 358 
 {  {
         int err;          int err;
   
         LOG(("vm_map : task=%s addr=%x size=%x\n",  
              target->name ? target->name : "no name", addr, size));  
   
         sched_lock();          sched_lock();
         if (!task_valid(target)) {          if (!task_valid(target)) {
                 err = ESRCH;                  err = ESRCH;
         } else if (target == cur_task()) {                  goto out;
           }
           if (target == cur_task()) {
                 err = EINVAL;                  err = EINVAL;
         } else if (!task_capable(CAP_MEMORY)) {                  goto out;
           }
           if (!task_capable(CAP_MEMORY)) {
                 err = EPERM;                  err = EPERM;
         } else if (!user_area(addr)) {                  goto out;
           }
           if (!user_area(addr)) {
                 err = EFAULT;                  err = EFAULT;
         } else {                  goto out;
                 err = do_map(target->map, addr, size, alloc);  
         }          }
           err = do_map(target->map, addr, size, alloc);
    out:
         sched_unlock();          sched_unlock();
         CHK("vm_map", err);  
         return err;          return err;
 }  }
   
Line 389 
Line 385 
 do_map(vm_map_t map, void *addr, size_t size, void **alloc)  do_map(vm_map_t map, void *addr, size_t size, void **alloc)
 {  {
         vm_map_t curmap;          vm_map_t curmap;
         u_long start, end, offset, phys;          char *start, *end, *phys;
           size_t offset;
         struct region *reg, *cur, *tgt;          struct region *reg, *cur, *tgt;
           task_t self;
         int map_type;          int map_type;
         void *tmp;          void *tmp;
   
Line 402 
Line 400 
         if (umem_copyout(&tmp, alloc, sizeof(void *)))          if (umem_copyout(&tmp, alloc, sizeof(void *)))
                 return EFAULT;                  return EFAULT;
   
         start = PAGE_TRUNC(addr);          start = (char *)PAGE_TRUNC(addr);
         end = PAGE_ALIGN((u_long)addr + size);          end = (char *)PAGE_ALIGN((char *)addr + size);
         size = (size_t)(end - start);          size = (size_t)(end - start);
         offset = (u_long)addr - start;          offset = (size_t)((char *)addr - start);
   
         /*          /*
          * Find the region that includes target address           * Find the region that includes target address
Line 418 
Line 416 
         /*          /*
          * Find the free region in current task           * Find the free region in current task
          */           */
         curmap = cur_task()->map;          self = cur_task();
           curmap = self->map;
         if ((reg = region_alloc(&curmap->head, size)) == NULL)          if ((reg = region_alloc(&curmap->head, size)) == NULL)
                 return ENOMEM;                  return ENOMEM;
         cur = reg;          cur = reg;
Line 431 
Line 430 
         else          else
                 map_type = PG_READ;                  map_type = PG_READ;
   
         phys = tgt->phys + (start - tgt->addr);          phys = (char *)tgt->phys + (start - (char *)tgt->addr);
         if (mmu_map(curmap->pgd, (void *)phys, (void *)cur->addr,          if (mmu_map(curmap->pgd, phys, cur->addr, size, map_type)) {
                     size, map_type)) {  
                 region_free(&curmap->head, reg);                  region_free(&curmap->head, reg);
                 return ENOMEM;                  return ENOMEM;
         }          }
Line 441 
Line 439 
         cur->flags = tgt->flags | REG_MAPPED;          cur->flags = tgt->flags | REG_MAPPED;
         cur->phys = phys;          cur->phys = phys;
   
         tmp = (void *)((u_long)cur->addr + offset);          tmp = (char *)cur->addr + offset;
         umem_copyout(&tmp, alloc, sizeof(void *));          umem_copyout(&tmp, alloc, sizeof(void *));
         return 0;          return 0;
 }  }
Line 461 
Line 459 
         if ((map = kmem_alloc(sizeof(struct vm_map))) == NULL)          if ((map = kmem_alloc(sizeof(struct vm_map))) == NULL)
                 return NULL;                  return NULL;
   
         map->ref_count = 1;          map->refcnt = 1;
   
         /* Allocate new page directory */          /* Allocate new page directory */
         if ((map->pgd = mmu_newmap()) == NULL) {          if ((map->pgd = mmu_newmap()) == NULL) {
Line 481 
Line 479 
 {  {
         struct region *reg, *tmp;          struct region *reg, *tmp;
   
         if (--map->ref_count >= 1)          if (--map->refcnt >= 1)
                 return;                  return;
   
         sched_lock();          sched_lock();
Line 489 
Line 487 
         do {          do {
                 if (reg->flags != REG_FREE) {                  if (reg->flags != REG_FREE) {
                         /* Unmap region */                          /* Unmap region */
                         mmu_map(map->pgd, (void *)reg->phys,                          mmu_map(map->pgd, reg->phys, reg->addr,
                                 (void *)reg->addr, reg->size, PG_UNMAP);                                  reg->size, PG_UNMAP);
   
                         /* Free region if it is not shared and mapped */                          /* Free region if it is not shared and mapped */
                         if (!(reg->flags & REG_SHARED) &&                          if (!(reg->flags & REG_SHARED) &&
                             !(reg->flags & REG_MAPPED)) {                              !(reg->flags & REG_MAPPED)) {
                                 page_free((void *)reg->phys, reg->size);                                  page_free(reg->phys, reg->size);
                         }                          }
                 }                  }
                 tmp = reg;                  tmp = reg;
Line 574 
Line 572 
                         tmp->next = dest;                          tmp->next = dest;
                         tmp = dest;                          tmp = dest;
                 }                  }
                 /* Skip free region */  
                 if (src->flags == REG_FREE) {                  if (src->flags == REG_FREE) {
                         src = src->next;                          /*
                         continue;                           * Skip free region
                 }                           */
                 /* Check if the region can be shared */                  } else {
                 if (!(src->flags & REG_WRITE) && !(src->flags & REG_MAPPED))                          /* Check if the region can be shared */
                         dest->flags |= REG_SHARED;                          if (!(src->flags & REG_WRITE) &&
                               !(src->flags & REG_MAPPED)) {
                                   dest->flags |= REG_SHARED;
                           }
   
                 if (!(dest->flags & REG_SHARED)) {                          if (!(dest->flags & REG_SHARED)) {
                         /* Allocate new physical page. */                                  /* Allocate new physical page. */
                         dest->phys = (u_long)page_alloc(src->size);                                  dest->phys = page_alloc(src->size);
                         if (dest->phys == 0)                                  if (dest->phys == 0)
                                 return NULL;                                          return NULL;
   
                         /* Copy source page */                                  /* Copy source page */
                         memcpy(phys_to_virt(dest->phys),                                  memcpy(phys_to_virt(dest->phys),
                                phys_to_virt(src->phys), src->size);                                         phys_to_virt(src->phys), src->size);
                 }                          }
                 /* Map the region to virtual address */                          /* Map the region to virtual address */
                 if (dest->flags & REG_WRITE)                          if (dest->flags & REG_WRITE)
                         map_type = PG_WRITE;                                  map_type = PG_WRITE;
                 else                          else
                         map_type = PG_READ;                                  map_type = PG_READ;
   
                 if (mmu_map(new_map->pgd, (void *)dest->phys,                          if (mmu_map(new_map->pgd, dest->phys, dest->addr,
                             (void *)dest->addr, dest->size, map_type))                                      dest->size, map_type))
                         return NULL;                                  return NULL;
                   }
                 src = src->next;                  src = src->next;
         } while (src != &org_map->head);          } while (src != &org_map->head);
   
Line 626 
Line 626 
 }  }
   
 /*  /*
  * SWitch VM mapping.   * Switch VM mapping.
  *   *
  * Since a kernel task does not have user mode memory image, we   * Since a kernel task does not have user mode memory image, we
  * don't have to setup the page directory for it. Thus, an idle   * don't have to setup the page directory for it. Thus, an idle
Line 647 
Line 647 
 vm_reference(vm_map_t map)  vm_reference(vm_map_t map)
 {  {
   
         map->ref_count++;          map->refcnt++;
         return 0;          return 0;
 }  }
   
Line 656 
Line 656 
  * Return 0 on success, -1 on failure.   * Return 0 on success, -1 on failure.
  */   */
 int  int
 vm_load(vm_map_t map, struct module *m, void **stack)  vm_load(vm_map_t map, struct module *mod, void **stack)
 {  {
         u_long src;          char *src;
         void *text, *data;          void *text, *data;
   
         printk("Loading task: %s\n", m->name);          DPRINTF(("Loading task: %s\n", mod->name));
   
         /*          /*
          * We have to switch VM mapping to touch the virtual           * We have to switch VM mapping to touch the virtual
Line 669 
Line 669 
          */           */
         vm_switch(map);          vm_switch(map);
   
         src = (u_long)phys_to_virt(m->phys);          src = phys_to_virt(mod->phys);
         text = (void *)m->text;          text = (void *)mod->text;
         data = (void *)m->data;          data = (void *)mod->data;
   
         /*          /*
          * Create text segment           * Create text segment
          */           */
         if (do_allocate(map, &text, m->textsz, 0))          if (do_allocate(map, &text, mod->textsz, 0))
                 return -1;                  return -1;
         memcpy(text, (void *)src, m->textsz);          memcpy(text, src, mod->textsz);
         if (do_attribute(map, text, VMA_READ))          if (do_attribute(map, text, VMA_READ))
                 return -1;                  return -1;
   
         /*          /*
          * Create data & BSS segment           * Create data & BSS segment
          */           */
         if (m->datasz + m->bsssz != 0) {          if (mod->datasz + mod->bsssz != 0) {
                 if (do_allocate(map, &data, m->datasz + m->bsssz, 0))                  if (do_allocate(map, &data, mod->datasz + mod->bsssz, 0))
                         return -1;                          return -1;
                 src = src + (m->data - m->text);                  src = src + (mod->data - mod->text);
                 memcpy(data, (void *)src, m->datasz);                  memcpy(data, src, mod->datasz);
         }          }
         /*          /*
          * Create stack           * Create stack
Line 699 
Line 699 
                 return -1;                  return -1;
   
         /* Free original pages */          /* Free original pages */
         page_free((void *)m->phys, m->size);          page_free((void *)mod->phys, mod->size);
         return 0;          return 0;
 }  }
   
Line 710 
Line 710 
 void *  void *
 vm_translate(void *addr, size_t size)  vm_translate(void *addr, size_t size)
 {  {
           task_t self = cur_task();
   
         return mmu_extract(cur_task()->map->pgd, addr, size);          return mmu_extract(self->map->pgd, addr, size);
 }  }
   
 /*  /*
  * Check if specified access can be allowed.  
  * return 0 on success, or EFAULT on failure.  
  */  
 int  
 vm_access(void *addr, size_t size, int type)  
 {  
         u_long pg, end;  
         int err;  
         char tmp;  
   
         ASSERT(size);  
         pg = PAGE_TRUNC(addr);  
         end = PAGE_TRUNC((u_long)addr + size - 1);  
         do {  
                 if ((err = umem_copyin((void *)pg, &tmp, 1)))  
                         return EFAULT;  
                 if (type == VMA_WRITE) {  
                         if ((err = umem_copyout(&tmp, (void *)pg, 1)))  
                                 return EFAULT;  
                 }  
                 pg += PAGE_SIZE;  
         } while (pg <= end);  
         return 0;  
 }  
   
 /*  
  * Initialize region   * Initialize region
  */   */
 static void  static void
Line 749 
Line 724 
   
         reg->next = reg->prev = reg;          reg->next = reg->prev = reg;
         reg->sh_next = reg->sh_prev = reg;          reg->sh_next = reg->sh_prev = reg;
         reg->addr = PAGE_SIZE;          reg->addr = (void *)PAGE_SIZE;
         reg->phys = 0;          reg->phys = 0;
         reg->size = USER_MAX - PAGE_SIZE;          reg->size = USER_MAX - PAGE_SIZE;
         reg->flags = REG_FREE;          reg->flags = REG_FREE;
Line 760 
Line 735 
  * Returns region on success, or NULL on failure.   * Returns region on success, or NULL on failure.
  */   */
 static struct region *  static struct region *
 region_create(struct region *prev, u_long addr, size_t size)  region_create(struct region *prev, void *addr, size_t size)
 {  {
         struct region *reg;          struct region *reg;
   
Line 802 
Line 777 
  * Find the region at the specified area.   * Find the region at the specified area.
  */   */
 static struct region *  static struct region *
 region_find(struct region *head, u_long addr, size_t size)  region_find(struct region *head, void *addr, size_t size)
 {  {
         struct region *reg;          struct region *reg;
   
         reg = head;          reg = head;
         do {          do {
                 if (reg->addr <= addr &&                  if (reg->addr <= addr &&
                     reg->addr + reg->size >= addr + size) {                      (char *)reg->addr + reg->size >= (char *)addr + size) {
                         return reg;                          return reg;
                 }                  }
                 reg = reg->next;                  reg = reg->next;
Line 830 
Line 805 
                 if ((reg->flags & REG_FREE) && reg->size >= size) {                  if ((reg->flags & REG_FREE) && reg->size >= size) {
                         if (reg->size != size) {                          if (reg->size != size) {
                                 /* Split this region and return its head */                                  /* Split this region and return its head */
                                 if (region_create(reg, reg->addr + size,                                  if (region_create(reg,
                                                     (char *)reg->addr + size,
                                                   reg->size - size) == NULL)                                                    reg->size - size) == NULL)
                                         return NULL;                                          return NULL;
                         }                          }
Line 885 
Line 861 
  * Sprit region for the specified address/size.   * Sprit region for the specified address/size.
  */   */
 static struct region *  static struct region *
 region_split(struct region *head, struct region *reg, u_long addr,  region_split(struct region *head, struct region *reg, void *addr,
              size_t size)               size_t size)
 {  {
         struct region *prev, *next;          struct region *prev, *next;
Line 897 
Line 873 
         prev = NULL;          prev = NULL;
         if (reg->addr != addr) {          if (reg->addr != addr) {
                 prev = reg;                  prev = reg;
                 diff = (size_t)(addr - reg->addr);                  diff = (size_t)((char *)addr - (char *)reg->addr);
                 reg = region_create(prev, addr, prev->size - diff);                  reg = region_create(prev, addr, prev->size - diff);
                 if (reg == NULL)                  if (reg == NULL)
                         return NULL;                          return NULL;
Line 908 
Line 884 
          * Check next region to split region.           * Check next region to split region.
          */           */
         if (reg->size != size) {          if (reg->size != size) {
                 next = region_create(reg, reg->addr + size,                  next = region_create(reg, (char *)reg->addr + size,
                                      reg->size - size);                                       reg->size - size);
                 if (next == NULL) {                  if (next == NULL) {
                         if (prev) {                          if (prev) {
Line 923 
Line 899 
         return reg;          return reg;
 }  }
   
 #if defined(DEBUG) && defined(CONFIG_KDUMP)  #ifdef DEBUG
 void  static void
 vm_dump_one(task_t task)  vm_dump_one(task_t task)
 {  {
         vm_map_t map;          vm_map_t map;
         struct region *reg;          struct region *reg;
         char flags[6];          char flags[6];
         u_long total = 0;          size_t total = 0;
   
         printk("task=%x map=%x name=%s\n", task, task->map,          printf("task=%x map=%x name=%s\n", task, task->map,
                task->name ? task->name : "no name");                 task->name != NULL ? task->name : "no name");
         printk(" region   virtual  physical size     flags\n");          printf(" region   virtual  physical size     flags\n");
         printk(" -------- -------- -------- -------- -----\n");          printf(" -------- -------- -------- -------- -----\n");
   
         map = task->map;          map = task->map;
         reg = &map->head;          reg = &map->head;
Line 953 
Line 929 
                         if (reg->flags & REG_MAPPED)                          if (reg->flags & REG_MAPPED)
                                 flags[4] = 'M';                                  flags[4] = 'M';
   
                         printk(" %08x %08x %08x %8x %s\n", reg,                          printf(" %08x %08x %08x %8x %s\n", reg,
                                reg->addr, reg->phys, reg->size, flags);                                 reg->addr, reg->phys, reg->size, flags);
                         total += reg->size;                          total += reg->size;
                 }                  }
                 reg = reg->next;                  reg = reg->next;
         } while (reg != &map->head);    /* Process all regions */          } while (reg != &map->head);    /* Process all regions */
         printk(" *total=%dK bytes\n\n", total / 1024);          printf(" *total=%dK bytes\n\n", total / 1024);
 }  }
   
 void  void
Line 968 
Line 944 
         list_t n;          list_t n;
         task_t task;          task_t task;
   
         printk("\nVM dump:\n");          printf("\nVM dump:\n");
         n = list_first(&kern_task.link);          n = list_first(&kern_task.link);
         while (n != &kern_task.link) {          while (n != &kern_task.link) {
                 task = list_entry(n, struct task, link);                  task = list_entry(n, struct task, link);
                 vm_dump_one(task);                  vm_dump_one(task);
                 n = list_next(n);                  n = list_next(n);
         }          }
 }  
 #endif  
   
 #ifdef CONFIG_VMTRACE  
 static void  
 vm_error(const char *func, int err)  
 {  
   
         printk("VM error: %s returns err=%x\n", func, err);  
 }  }
 #endif  #endif
   

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.1.2.1

CVSweb