Example #1
0
File: pdir.c Project: HarryR/sanos
int mem_access(void *vaddr, int size, pte_t access) {
  unsigned long addr;
  unsigned long next;
  pte_t pte;
  
  addr = (unsigned long) vaddr;
  next = (addr & ~PAGESIZE) + PAGESIZE;
  while (1) {
    if ((GET_PDE(addr) & PT_PRESENT) == 0) return 0;
    pte = GET_PTE(addr);
    if ((pte & access) != access) {
      if (pte & PT_FILE) {
        if (fetch_page((void *) PAGEADDR(addr)) < 0) return 0;
        if ((GET_PTE(addr) & access) != access) return 0;
      } else {
        return 0;
      }
    }

    size -= next - addr;
    if (size <= 0) break;
    addr = next;
    next += PAGESIZE;
  }

  return 1;
}
Example #2
0
int vmfree(void *addr, unsigned long size, int type) {
    struct filemap *fm = NULL;
    int pages = PAGES(size);
    int i, rc;
    char *vaddr;

    if (size == 0) return 0;
    addr = (void *) PAGEADDR(addr);
    if (!valid_range(addr, size)) return -EINVAL;

    if (type & (MEM_DECOMMIT | MEM_RELEASE)) {
        vaddr = (char *) addr;
        for (i = 0; i < pages; i++) {
            if (page_directory_mapped(vaddr)) {
                pte_t flags = get_page_flags(vaddr);
                unsigned long pfn = BTOP(virt2phys(vaddr));

                if (flags & PT_FILE) {
                    handle_t h = (flags & PT_PRESENT) ? pfdb[pfn].owner : pfn;
                    struct filemap *newfm = (struct filemap *) hlookup(h);
                    if (newfm != fm) {
                        if (fm) {
                            if (fm->pages == 0) {
                                rc = free_filemap(fm);
                            } else {
                                rc = unlock_filemap(fm);
                            }
                            if (rc < 0) return rc;
                        }
                        fm = newfm;
                        rc = wait_for_object(fm, INFINITE);
                        if (rc < 0) return rc;
                    }
                    fm->pages--;
                    unmap_page(vaddr);
                    if (flags & PT_PRESENT) free_pageframe(pfn);
                } else  if (flags & PT_PRESENT) {
                    unmap_page(vaddr);
                    free_pageframe(pfn);
                }
            }

            vaddr += PAGESIZE;
        }
    }

    if (fm) {
        if (fm->pages == 0) {
            rc = free_filemap(fm);
        } else {
            rc = unlock_filemap(fm);
        }
        if (rc < 0) return rc;
    } else if (type & MEM_RELEASE) {
        rmap_free(vmap, BTOP(addr), pages);
    }

    return 0;
}
Example #3
0
void *vmmap(void *addr, unsigned long size, int protect, struct file *filp, off64_t offset, int *rc) {
    int pages = PAGES(size);
    unsigned long flags = pte_flags_from_protect(protect);
    struct filemap *fm;
    int i;
    char *vaddr;

    if (rc) *rc = 0;
    if (size == 0 || flags == 0xFFFFFFFF) {
        if (rc) *rc = -EINVAL;
        return NULL;
    }
    addr = (void *) PAGEADDR(addr);
    if (addr == NULL) {
        addr = (void *) PTOB(rmap_alloc(vmap, pages));
        if (addr == NULL) {
            if (rc) *rc = -ENOMEM;
            return NULL;
        }
    } else {
        if (rmap_reserve(vmap, BTOP(addr), pages)) {
            if (rc) *rc = -ENOMEM;
            return NULL;
        }
    }

    fm = (struct filemap *) kmalloc(sizeof(struct filemap));
    if (!fm) {
        rmap_free(vmap, BTOP(addr), pages);
        if (rc) *rc = -ENOMEM;
        return NULL;
    }
    init_object(&fm->object, OBJECT_FILEMAP);
    fm->self = halloc(&fm->object);
    fm->file = halloc(&filp->iob.object);
    if (fm->self < 0 || fm->file < 0) {
        if (rc) *rc = -ENFILE;
        return NULL;
    }
    hprotect(fm->self);
    hprotect(fm->file);
    fm->offset = offset;
    fm->pages = pages;
    fm->object.signaled = 1;
    fm->addr = addr;
    fm->size = size;
    fm->protect = flags | PT_FILE;

    vaddr = (char *) addr;
    flags = (flags & ~PT_USER) | PT_FILE;
    for (i = 0; i < pages; i++) {
        map_page(vaddr, fm->self, flags);
        vaddr += PAGESIZE;
    }

    return addr;
}
Example #4
0
int vmsync(void *addr, unsigned long size) {
    struct filemap *fm = NULL;
    int pages = PAGES(size);
    int i, rc;
    char *vaddr;

    if (size == 0) return 0;
    addr = (void *) PAGEADDR(addr);
    if (!valid_range(addr, size)) return -EINVAL;

    vaddr = (char *) addr;
    for (i = 0; i < pages; i++) {
        if (page_directory_mapped(vaddr)) {
            pte_t flags = get_page_flags(vaddr);
            if ((flags & (PT_FILE | PT_PRESENT | PT_DIRTY)) == (PT_FILE | PT_PRESENT | PT_DIRTY)) {
                unsigned long pfn = BTOP(virt2phys(vaddr));
                struct filemap *newfm = (struct filemap *) hlookup(pfdb[pfn].owner);
                if (newfm != fm) {
                    if (fm) {
                        rc = unlock_filemap(fm);
                        if (rc < 0) return rc;
                    }
                    fm = newfm;
                    rc = wait_for_object(fm, INFINITE);
                    if (rc < 0) return rc;
                }

                rc = save_file_page(fm, vaddr);
                if (rc < 0) return rc;
            }
        }
        vaddr += PAGESIZE;
    }

    if (fm) {
        rc = unlock_filemap(fm);
        if (rc < 0) return rc;
    }

    return 0;
}
Example #5
0
File: pdir.c Project: HarryR/sanos
int str_access(char *s, pte_t access) {
  pte_t pte;

  while (1) {
    if ((GET_PDE(s) & PT_PRESENT) == 0) return 0;
    pte = GET_PTE(s);
    if ((pte & access) != access) {
      if (pte & PT_FILE) {
        if (fetch_page((void *) PAGEADDR(s)) < 0) return 0;
        if ((GET_PTE(s) & access) != access) return 0;
      } else {
        return 0;
      }
    }

    while (1) {
      if (!*s) return 1;
      s++;
      if (PGOFF(s) == 0) break;
    }
  }
}
Example #6
0
int vmprotect(void *addr, unsigned long size, int protect) {
    int pages = PAGES(size);
    int i;
    char *vaddr;
    unsigned long flags;

    if (size == 0) return 0;
    addr = (void *) PAGEADDR(addr);
    if (!valid_range(addr, size)) return -EINVAL;
    flags = pte_flags_from_protect(protect);
    if (flags == 0xFFFFFFFF) return -EINVAL;

    vaddr = (char *) addr;
    for (i = 0; i < pages; i++) {
        if (page_mapped(vaddr)) {
            set_page_flags(vaddr, (get_page_flags(vaddr) & ~PT_PROTECTMASK) | flags);
        }
        vaddr += PAGESIZE;
    }

    return 0;
}
Example #7
0
File: pdir.c Project: HarryR/sanos
int pdir_proc(struct proc_file *pf, void *arg) {
  char *vaddr;
  pte_t pte;
  int lines = 0;

  int ma = 0;
  int us = 0;
  int su = 0;
  int ro = 0;
  int rw = 0;
  int ac = 0;
  int dt = 0;
  int gd = 0;
  int fi = 0;

  pprintf(pf, "virtaddr physaddr flags\n");
  pprintf(pf, "-------- -------- ------\n");

  vaddr = NULL;
  while (1) {
    if ((GET_PDE(vaddr) & PT_PRESENT) == 0) {
      vaddr += PTES_PER_PAGE * PAGESIZE;
    } else {
      pte = GET_PTE(vaddr);
      if (pte & PT_PRESENT) {
        ma++;
        
        if (pte & PT_WRITABLE) {
          rw++;
        } else {
          ro++;
        }

        if (pte & PT_USER) {
          us++;
        } else {
          su++;
        }

        if (pte & PT_ACCESSED) ac++;
        if (pte & PT_DIRTY) dt++;
        if (pte & PT_GUARD) gd++;
        if (pte & PT_FILE) fi++;

        pprintf(pf, "%08x %08x %c%c%c%c%c%c\n", 
                vaddr, PAGEADDR(pte), 
                (pte & PT_WRITABLE) ? 'w' : 'r',
                (pte & PT_USER) ? 'u' : 's',
                (pte & PT_ACCESSED) ? 'a' : ' ',
                (pte & PT_DIRTY) ? 'd' : ' ',
                (pte & PT_GUARD) ? 'g' : ' ',
                (pte & PT_FILE) ? 'f' : ' ');
      }

      vaddr += PAGESIZE;
    }

    if (!vaddr) break;
  }

  pprintf(pf, "\ntotal:%d usr:%d sys:%d rw: %d ro: %d acc: %d dirty: %d guard:%d file:%d\n", ma, us, su, rw, ro, ac, dt, gd, fi);
  return 0;
}
Example #8
0
void *vmalloc(void *addr, unsigned long size, int type, int protect, unsigned long tag, int *rc) {
    int pages = PAGES(size);
    unsigned long flags = pte_flags_from_protect(protect);
    int i;

    if (rc) *rc = 0;
    if (size == 0) {
        if (rc) *rc = -EINVAL;
        return NULL;
    }
    if ((type & MEM_COMMIT) != 0 && flags == 0xFFFFFFFF) {
        if (rc) *rc = -EINVAL;
        return NULL;
    }
    addr = (void *) PAGEADDR(addr);
    if (!addr && (type & MEM_COMMIT) != 0) type |= MEM_RESERVE;
    if (!tag) tag = 'VM';

    if (type & MEM_RESERVE) {
        if (addr == NULL) {
            if (type & MEM_ALIGN64K) {
                addr = (void *) PTOB(rmap_alloc_align(vmap, pages, 64 * 1024 / PAGESIZE));
            } else {
                addr = (void *) PTOB(rmap_alloc(vmap, pages));
            }

            if (addr == NULL) {
                if (rc) *rc = -ENOMEM;
                return NULL;
            }
        } else {
            if (rmap_reserve(vmap, BTOP(addr), pages)) {
                if (rc) *rc = -ENOMEM;
                return NULL;
            }
        }
    } else {
        if (!valid_range(addr, size)) {
            if (rc) *rc = -EFAULT;
            return NULL;
        }
    }

    if (type & MEM_COMMIT) {
        char *vaddr;
        unsigned long pfn;

        vaddr = (char *) addr;
        for (i = 0; i < pages; i++) {
            if (page_mapped(vaddr)) {
                set_page_flags(vaddr, flags | PT_PRESENT);
            } else {
                pfn = alloc_pageframe(tag);
                if (pfn == 0xFFFFFFFF) {
                    if (rc) *rc = -ENOMEM;
                    return NULL;
                }

                map_page(vaddr, pfn, flags | PT_PRESENT);
                memset(vaddr, 0, PAGESIZE);
            }
            vaddr += PAGESIZE;
        }
    }

    return addr;
}