View of xos/mm/memory.c


XOS | Parent Directory | View | Download

/* Operations sur l'espace d'adressage lineaire du processus courant. */
/* Copyright (C) 2008  Emmanuel Varoquaux
 
   This file is part of XOS.
 
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
#include "page_fault.h"
#include "maps.h"
#include "map.h"
#include "pages.h"
#include "page.h"
 
#include <errno.h>
#include <enums.h>
#include <i386.h>
 
static int verify_page(const struct maps_struct *maps, unsigned long laddr, int access)
{
  int rw;
 
  if (!get_page_rw(laddr, &rw))
    return _handle_page_fault(laddr, PF_NOT_PRESENT, access, 0, maps) == PF_SUCCESS;
  if (access == PF_WRITE && !rw)
    return _handle_page_fault(laddr, PF_PROTECTION_VIOLATION, PF_WRITE, 0, maps) == PF_SUCCESS;
  return 1;
}
 
/* Copie la memoire du processus courant.
 * start doit etre aligne sur une frontiere de page.
 * length doit etre non nul et multiple de PAGE_SIZE.
 * [start, start + length[ doit etre inclus dans l'espace d'adressage lineaire.
 */
int copy_memory(const struct maps_struct *maps, struct maps_struct *dest_maps, unsigned long *dest_page_directory, unsigned long start, unsigned long length)
{
  int rv;
 
  if ((rv = copy_pages(start, length, dest_page_directory)) < 0)
    return rv;
  if ((rv = clone_maps(maps, dest_maps, start, length)) < 0)
    return rv;
  return 0;
}
 
/* Libere la memoire du processus courant.
 * start doit etre aligne sur une frontiere de page.
 * length doit etre non nul et multiple de PAGE_SIZE.
 * [start, start + length[ doit etre inclus dans l'espace d'adressage lineaire.
 */
int free_memory(struct maps_struct *maps, unsigned long start, unsigned long length)
{
  int rv;
 
  free_pages(start, length, maps);
  if ((rv = clear_maps(maps, start, length)) < 0)
    return rv;
  return 0;
}
 
/* Change la protection de la memoire du processus courant.
 * start doit etre aligne sur une frontiere de page.
 * length doit etre non nul et multiple de PAGE_SIZE.
 * [start, start + length[ doit etre inclus dans l'espace d'adressage lineaire.
 */
int protect_memory(struct maps_struct *maps, unsigned long start, unsigned long length, int prot)
{
  int rv;
 
  if ((rv = protect_maps(maps, start, length, prot)) < 0)
    return rv;
  return 0;
}
 
/* Verifie la validite d'un acces a un intervalle d'adresses lineaires du
 * processus courant, et peuple les pages en vue de cet acces.
 * start doit etre aligne sur une frontiere de page.
 * length doit etre non nul et multiple de PAGE_SIZE.
 * [start, start + length[ doit etre inclus dans l'espace d'adressage lineaire.
 */
int verify_memory(const struct maps_struct *maps, unsigned long start, unsigned long length, int access)
{
  while (1) {
    if (!verify_page(maps, start, access))
      return 0;
    length -= PAGE_SIZE;
    if (!length)
      break;
    start += PAGE_SIZE;
  }
  return 1;
}
 
/* Cree une projection de memoire. Utilise pour projetter la memoire du noyau
 * dans l'espace lineaire de init().
 * start doit etre aligne sur une frontiere de page.
 * length doit etre non nul et multiple de PAGE_SIZE.
 * [start, start + length[ doit etre inclus dans l'espace d'adressage lineaire.
 */
int map_mem(struct maps_struct *maps, unsigned long start, unsigned long length, int prot, void *mem_start)
{
  struct map_struct *map;
  int retval;
 
  if ((retval = alloc_mem_map(start, length, prot, mem_start, &map)) < 0)
    goto error;
  clear_maps(maps, start, length);
  if (!insert_map(maps, map)) {
    retval = -EINVAL;
    goto error_free_map;
  }
  return 0;
 
 error_free_map:
  free_map(map);
 error:
  return retval;
}
 
/* Cree une projection anonyme.
 * start doit etre aligne sur une frontiere de page.
 * length doit etre non nul et multiple de PAGE_SIZE.
 * [start, start + length[ doit etre inclus dans l'espace d'adressage lineaire.
 * name peut etre nul. */
int map_anon(struct maps_struct *maps, unsigned long start, unsigned long length, int prot, int grows_down, const char *name)
{
  struct map_struct *map;
  int retval;
 
  if ((retval = alloc_anon_map(start, length, prot, grows_down, name, &map)) < 0)
    goto error;
  clear_maps(maps, start, length);
  if (!insert_map(maps, map)) {
    retval = -EINVAL;
    goto error_free_map;
  }
  return 0;
 
 error_free_map:
  free_map(map);
 error:
  return retval;
}
 
/* Cree une projection de fichier.
 * start et offset doivent etre alignes sur une frontiere de page.
 * length doit etre non nul et multiple de PAGE_SIZE.
 * [start, start + length[ doit etre inclus dans l'espace d'adressage lineaire.
 * file doit etre un fichier regulier ou un fichier special. */
int map_file(struct maps_struct *maps, unsigned long start, unsigned long length, int prot, struct file_struct *file, unsigned long offset)
{
  struct map_struct *map;
  int retval;
 
  if ((retval = alloc_file_map(start, length, prot, file, offset, &map)) < 0)
    goto error;
  clear_maps(maps, start, length);
  if (!insert_map(maps, map)) {
    retval = -EINVAL;
    goto error_free_map;
  }
  return 0;
 
 error_free_map:
  free_map(map);
 error:
  return retval;
}