#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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}