mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
bitkeeper revision 1.310 (3f0bf553kbldKc8vu6lujXO6BTBWpg)
Misc. tidy ups. Continue moving bits of teh /proc interface from stupidly overloaded calls to read and write to using a slightly less awful ioctl interface.
This commit is contained in:
1 parent
c5ef748c89
commit
f05b0dd80e
5 files changed
+131
-266
No files matched your search
@@ -42,4 +42,4 @@ typedef struct { unsigned long l2_lo; } l2_pgentry_t;
|
||||
|
||||
/* local definitions */
|
||||
|
||||
#define nr_2_page(x) (x << PAGE_SHIFT)
|
||||
#define nr_2_page(x) ((x) << PAGE_SHIFT)
|
||||
+27
-87
@@ -8,13 +8,11 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asm-i386/types.h"
|
||||
#include "hypervisor-ifs/hypervisor-if.h"
|
||||
#include "dom0_ops.h"
|
||||
#include "dom0_defs.h"
|
||||
@@ -51,7 +49,7 @@ static void dom_mem_cleanup(dom_mem_t * dom_mem)
|
||||
{
|
||||
int fd;
|
||||
struct dom0_unmapdommem_args argbuf;
|
||||
|
||||
|
||||
fd = open("/proc/xeno/dom0_cmd", O_WRONLY);
|
||||
if(fd < 0){
|
||||
perror(PERR_STRING);
|
||||
@@ -68,85 +66,33 @@ static void dom_mem_cleanup(dom_mem_t * dom_mem)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* ask dom0 to export domains memory through /proc */
|
||||
static int setup_dom_memmap(unsigned long pfn, int pages, int dom)
|
||||
{
|
||||
char cmd_path[MAX_PATH];
|
||||
dom0_op_t dop;
|
||||
int cmd_fd;
|
||||
|
||||
dop.cmd = MAP_DOM_MEM;
|
||||
dop.u.dommem.start_pfn = pfn;
|
||||
dop.u.dommem.tot_pages = pages;
|
||||
dop.u.dommem.domain = dom;
|
||||
|
||||
/* open the /proc command interface */
|
||||
sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
|
||||
cmd_fd = open(cmd_path, O_WRONLY);
|
||||
if ( cmd_fd < 0 )
|
||||
{
|
||||
perror(PERR_STRING);
|
||||
return -1;
|
||||
}
|
||||
|
||||
write(cmd_fd, &dop, sizeof(dom0_op_t));
|
||||
close(cmd_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* request the actual mapping from dom0 */
|
||||
static unsigned long get_vaddr(unsigned int dom)
|
||||
{
|
||||
char mem_path[MAX_PATH];
|
||||
unsigned long addr;
|
||||
int mem_fd;
|
||||
|
||||
/* open the domain's /proc mem interface */
|
||||
sprintf(mem_path, "%s%s%s%s%d%s%s", "/proc/", PROC_XENO_ROOT, "/",
|
||||
PROC_DOM_PREFIX, dom, "/", PROC_DOM_MEM);
|
||||
|
||||
mem_fd = open(mem_path, O_RDONLY);
|
||||
if(mem_fd < 0){
|
||||
perror(PERR_STRING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get virtual address of mapped region */
|
||||
read(mem_fd, &addr, sizeof(addr));
|
||||
|
||||
close(mem_fd);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static int map_dom_mem(unsigned long pfn, int pages, int dom,
|
||||
dom_mem_t * dom_mem)
|
||||
{
|
||||
struct dom0_mapdommem_args argbuf;
|
||||
int fd;
|
||||
struct dom0_mapdommem_args argbuf;
|
||||
int fd;
|
||||
|
||||
argbuf.domain = dom;
|
||||
argbuf.start_pfn = pfn;
|
||||
argbuf.tot_pages = pages;
|
||||
argbuf.domain = dom;
|
||||
argbuf.start_pfn = pfn;
|
||||
argbuf.tot_pages = pages;
|
||||
|
||||
fd = open("/proc/xeno/dom0_cmd", O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("openning /proc/xeno/dom0_cmd");
|
||||
return -1;
|
||||
}
|
||||
fd = open("/proc/xeno/dom0_cmd", O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("openning /proc/xeno/dom0_cmd");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dom_mem->domain = dom;
|
||||
dom_mem->start_pfn = pfn;
|
||||
dom_mem->tot_pages = pages;
|
||||
dom_mem->vaddr = ioctl(fd, IOCTL_DOM0_MAPDOMMEM, &argbuf);
|
||||
dom_mem->domain = dom;
|
||||
dom_mem->start_pfn = pfn;
|
||||
dom_mem->tot_pages = pages;
|
||||
dom_mem->vaddr = ioctl(fd, IOCTL_DOM0_MAPDOMMEM, &argbuf);
|
||||
|
||||
if (dom_mem->vaddr == -1) {
|
||||
perror("mapping domain memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dom_mem->vaddr == -1) {
|
||||
perror("mapping domain memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* open kernel image and do some sanity checks */
|
||||
@@ -215,14 +161,13 @@ static dom_meminfo_t *setup_guestos(int dom, int kernel_fd, int initrd_fd,
|
||||
dom_meminfo_t *meminfo;
|
||||
unsigned long *page_array;
|
||||
page_update_request_t *pgt_updates;
|
||||
dom_mem_t mem_map;
|
||||
dom_meminfo_t *ret = NULL;
|
||||
int alloc_index, num_pt_pages;
|
||||
unsigned long l2tab;
|
||||
unsigned long l1tab = 0;
|
||||
unsigned long num_pgt_updates = 0;
|
||||
unsigned long count, pt_start;
|
||||
dom0_op_t pgupdate_req;
|
||||
struct dom0_dopgupdates_args pgupdate_req;
|
||||
char cmd_path[MAX_PATH];
|
||||
int cmd_fd;
|
||||
|
||||
@@ -324,10 +269,9 @@ static dom_meminfo_t *setup_guestos(int dom, int kernel_fd, int initrd_fd,
|
||||
*/
|
||||
sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
|
||||
if ( (cmd_fd = open(cmd_path, O_WRONLY)) < 0 ) goto out;
|
||||
pgupdate_req.cmd = DO_PGUPDATES;
|
||||
pgupdate_req.u.pgupdate.pgt_update_arr = (unsigned long)dom_mem->vaddr;
|
||||
pgupdate_req.u.pgupdate.num_pgt_updates = num_pgt_updates;
|
||||
write(cmd_fd, &pgupdate_req, sizeof(dom0_op_t));
|
||||
pgupdate_req.pgt_update_arr = (unsigned long)dom_mem->vaddr;
|
||||
pgupdate_req.num_pgt_updates = num_pgt_updates;
|
||||
if (ioctl(cmd_fd, IOCTL_DOM0_DOPGUPDATES, &pgupdate_req) < 0) goto out;
|
||||
close(cmd_fd);
|
||||
|
||||
/* Load the guest OS image. */
|
||||
@@ -435,11 +379,9 @@ int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
dom_mem_t dom_os_image;
|
||||
dom_mem_t dom_pgt;
|
||||
dom_meminfo_t * meminfo;
|
||||
size_t ksize;
|
||||
unsigned long load_addr;
|
||||
char status[1024];
|
||||
int kernel_fd, initrd_fd = 0;
|
||||
int count;
|
||||
int cmd_len;
|
||||
@@ -450,8 +392,6 @@ int main(int argc, char **argv)
|
||||
int pg_head;
|
||||
int tot_pages;
|
||||
|
||||
unsigned long addr;
|
||||
|
||||
/**** this argument parsing code is really _gross_. rewrite me! ****/
|
||||
|
||||
if(argc < 4) {
|
||||
|
||||
@@ -118,25 +118,32 @@ typedef struct dom0_op_st
|
||||
#define IOCTL_DOM0_CREATEDOMAIN _IOC(_IOC_READ, 'x', 0, sizeof(struct dom0_createdomain_args))
|
||||
#define IOCTL_DOM0_MAPDOMMEM _IOC(_IOC_READ, 'x', 1, sizeof(struct dom0_mapdommem_args))
|
||||
#define IOCTL_DOM0_UNMAPDOMMEM _IOC(_IOC_READ, 'x', 2, sizeof(struct dom0_unmapdommem_args))
|
||||
#define IOCTL_DOM0_DOPGUPDATES _IOC(_IOC_READ, 'x', 3, sizeof(struct dom0_dopgupdates_args))
|
||||
|
||||
struct dom0_createdomain_args
|
||||
{
|
||||
unsigned int kb_mem;
|
||||
const char *name;
|
||||
unsigned int kb_mem;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct dom0_mapdommem_args
|
||||
{
|
||||
unsigned int domain;
|
||||
unsigned start_pfn;
|
||||
unsigned tot_pages;
|
||||
unsigned int domain;
|
||||
unsigned start_pfn;
|
||||
unsigned tot_pages;
|
||||
};
|
||||
|
||||
struct dom0_unmapdommem_args
|
||||
{
|
||||
unsigned long vaddr;
|
||||
unsigned long start_pfn;
|
||||
unsigned long tot_pages;
|
||||
unsigned long vaddr;
|
||||
unsigned long start_pfn;
|
||||
unsigned long tot_pages;
|
||||
};
|
||||
|
||||
struct dom0_dopgupdates_args
|
||||
{
|
||||
unsigned long pgt_update_arr;
|
||||
unsigned long num_pgt_updates;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -162,8 +162,8 @@ static int dom0_cmd_write(struct file *file, const char *buffer, size_t size,
|
||||
}
|
||||
else if ( op.cmd == DO_PGUPDATES )
|
||||
{
|
||||
ret = HYPERVISOR_pt_update((void *)op.u.pgupdate.pgt_update_arr,
|
||||
op.u.pgupdate.num_pgt_updates);
|
||||
/* Now an ioctl. */
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
else if (op.cmd == DOM0_CREATEDOMAIN)
|
||||
{
|
||||
@@ -274,6 +274,8 @@ static struct file_operations proc_xeno_domains_operations = {
|
||||
release: seq_release,
|
||||
};
|
||||
|
||||
/* END OF /proc/xeno/domains */
|
||||
|
||||
static int handle_dom0_cmd_createdomain(unsigned long data)
|
||||
{
|
||||
struct dom0_createdomain_args argbuf;
|
||||
@@ -344,6 +346,18 @@ static int handle_dom0_cmd_unmapdommem(unsigned long data)
|
||||
argbuf.tot_pages << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
static int handle_dom0_cmd_dopgupdates(unsigned long data)
|
||||
{
|
||||
struct dom0_dopgupdates_args argbuf;
|
||||
|
||||
if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf)))
|
||||
return -EFAULT;
|
||||
|
||||
/* argbuf.pgt_update_arr had better be direct mapped... */
|
||||
return HYPERVISOR_pt_update(argbuf.pgt_update_arr,
|
||||
argbuf.num_pgt_updates);
|
||||
}
|
||||
|
||||
static int dom0_cmd_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long data)
|
||||
{
|
||||
@@ -355,6 +369,8 @@ static int dom0_cmd_ioctl(struct inode *inode, struct file *file,
|
||||
return handle_dom0_cmd_mapdommem(data);
|
||||
case IOCTL_DOM0_UNMAPDOMMEM:
|
||||
return handle_dom0_cmd_unmapdommem(data);
|
||||
case IOCTL_DOM0_DOPGUPDATES:
|
||||
return handle_dom0_cmd_dopgupdates(data);
|
||||
default:
|
||||
printk("Unknown dom0_cmd ioctl!\n");
|
||||
return -EINVAL;
|
||||
|
||||
@@ -32,88 +32,43 @@ extern struct list_head * find_direct(struct list_head *, unsigned long);
|
||||
#define __direct_mk_pte(page_nr,pgprot) __direct_pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
|
||||
#define direct_mk_pte_phys(physpage, pgprot) __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot)
|
||||
|
||||
static inline void forget_pte(pte_t page)
|
||||
/* Note: this is only safe if the mm semaphore is held when called. */
|
||||
|
||||
static int direct_remap_page(unsigned long from, unsigned long phys_addr, pgprot_t prot)
|
||||
{
|
||||
if (!pte_none(page)) {
|
||||
printk("forget_pte: old mapping existed!\n");
|
||||
struct mm_struct *mm = current->mm;
|
||||
pgd_t * dir;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
|
||||
pte_t oldpage;
|
||||
|
||||
dir = pgd_offset(mm, from);
|
||||
flush_cache_range(mm, from, from + PAGE_SIZE);
|
||||
|
||||
spin_lock(&mm->page_table_lock);
|
||||
pmd = pmd_alloc(mm, dir, from);
|
||||
if (!pmd)
|
||||
return -ENOMEM;
|
||||
pte = pte_alloc(mm, pmd, address);
|
||||
if (!pte) {
|
||||
/* XXX free pmd? */
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
oldpage = ptep_get_and_clear(pte);
|
||||
if (!pte_none(oldpage)) {
|
||||
printk("Page already in use!\n");
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
direct_set_pte(pte, direct_mk_pte_phys(phys_addr, prot));
|
||||
|
||||
static inline void direct_remappte_range(pte_t * pte, unsigned long address, unsigned long size,
|
||||
unsigned long phys_addr, pgprot_t prot)
|
||||
{
|
||||
unsigned long end;
|
||||
|
||||
address &= ~PMD_MASK;
|
||||
end = address + size;
|
||||
if (end > PMD_SIZE)
|
||||
end = PMD_SIZE;
|
||||
do {
|
||||
pte_t oldpage;
|
||||
oldpage = ptep_get_and_clear(pte);
|
||||
|
||||
direct_set_pte(pte, direct_mk_pte_phys(phys_addr, prot));
|
||||
|
||||
forget_pte(oldpage);
|
||||
address += PAGE_SIZE;
|
||||
phys_addr += PAGE_SIZE;
|
||||
pte++;
|
||||
} while (address && (address < end));
|
||||
|
||||
}
|
||||
|
||||
static inline int direct_remappmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
|
||||
unsigned long phys_addr, pgprot_t prot)
|
||||
{
|
||||
unsigned long end;
|
||||
|
||||
address &= ~PGDIR_MASK;
|
||||
end = address + size;
|
||||
if (end > PGDIR_SIZE)
|
||||
end = PGDIR_SIZE;
|
||||
phys_addr -= address;
|
||||
do {
|
||||
pte_t * pte = pte_alloc(mm, pmd, address);
|
||||
if (!pte)
|
||||
return -ENOMEM;
|
||||
direct_remappte_range(pte, address, end - address, address + phys_addr, prot);
|
||||
address = (address + PMD_SIZE) & PMD_MASK;
|
||||
pmd++;
|
||||
} while (address && (address < end));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Note: this is only safe if the mm semaphore is held when called. */
|
||||
static int direct_remap_page_range(unsigned long from, unsigned long phys_addr, unsigned long size, pgprot_t prot)
|
||||
{
|
||||
int error = 0;
|
||||
pgd_t * dir;
|
||||
unsigned long beg = from;
|
||||
unsigned long end = from + size;
|
||||
struct mm_struct *mm = current->mm;
|
||||
|
||||
phys_addr -= from;
|
||||
dir = pgd_offset(mm, from);
|
||||
flush_cache_range(mm, beg, end);
|
||||
if (from >= end)
|
||||
BUG();
|
||||
|
||||
spin_lock(&mm->page_table_lock);
|
||||
do {
|
||||
pmd_t *pmd = pmd_alloc(mm, dir, from);
|
||||
error = -ENOMEM;
|
||||
if (!pmd)
|
||||
break;
|
||||
error = direct_remappmd_range(mm, pmd, from, end - from, phys_addr + from, prot);
|
||||
if (error)
|
||||
break;
|
||||
from = (from + PGDIR_SIZE) & PGDIR_MASK;
|
||||
dir++;
|
||||
} while (from && (from < end));
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
flush_tlb_range(mm, beg, end);
|
||||
return error;
|
||||
|
||||
flush_tlb_range(mm, from, from + PAGE_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -142,8 +97,8 @@ static int direct_remap_disc_page_range(unsigned long from,
|
||||
|
||||
for ( i = 0; i < pages; i++ )
|
||||
{
|
||||
if(direct_remap_page_range(start, pfns[i] << PAGE_SHIFT,
|
||||
PAGE_SIZE, prot))
|
||||
if(direct_remap_page(start, pfns[i] << PAGE_SHIFT,
|
||||
prot))
|
||||
goto out;
|
||||
start += PAGE_SIZE;
|
||||
tot_pages--;
|
||||
@@ -155,10 +110,10 @@ static int direct_remap_disc_page_range(unsigned long from,
|
||||
return tot_pages;
|
||||
}
|
||||
|
||||
/* below functions replace standard sys_mmap and sys_munmap which are absolutely useless
|
||||
* for direct memory mapping. direct_zap* functions are minor ammendments to the
|
||||
* original versions in mm/memory.c. the changes are to enable unmapping of real physical
|
||||
* addresses.
|
||||
/* below functions replace standard sys_mmap and sys_munmap which are
|
||||
* absolutely useless for direct memory mapping. direct_zap* functions
|
||||
* are minor ammendments to the original versions in mm/memory.c. the
|
||||
* changes are to enable unmapping of real physical addresses.
|
||||
*/
|
||||
|
||||
unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
|
||||
@@ -169,6 +124,9 @@ unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
|
||||
unsigned long addr;
|
||||
int ret = 0;
|
||||
|
||||
if(!(size & ~PAGE_MASK))
|
||||
return -EINVAL;
|
||||
|
||||
if(!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
@@ -185,16 +143,16 @@ unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
|
||||
dmmap->vm_end = addr + size;
|
||||
entry = find_direct(¤t->mm->context.direct_list, addr);
|
||||
if(entry != ¤t->mm->context.direct_list){
|
||||
list_add_tail(&dmmap->list, entry);
|
||||
list_add_tail(&dmmap->list, entry);
|
||||
} else {
|
||||
list_add_tail(&dmmap->list, ¤t->mm->context.direct_list);
|
||||
list_add_tail(&dmmap->list, ¤t->mm->context.direct_list);
|
||||
}
|
||||
|
||||
/* XXX kfree(dmmap)? */
|
||||
|
||||
/* Acquire mm sem? */
|
||||
/* and perform the mapping */
|
||||
ret = direct_remap_disc_page_range(addr, phys_addr >> PAGE_SHIFT,
|
||||
tot_pages, prot);
|
||||
/* Drop mm sem? */
|
||||
|
||||
if(ret == 0)
|
||||
return addr;
|
||||
@@ -202,75 +160,19 @@ unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* most of the checks, refcnt updates, cache stuff have been thrown out as they are not
|
||||
* needed
|
||||
*/
|
||||
static inline int direct_zap_pte_range(mmu_gather_t *tlb, pmd_t * pmd, unsigned long address,
|
||||
unsigned long size)
|
||||
{
|
||||
unsigned long offset;
|
||||
pte_t * ptep;
|
||||
int freed = 0;
|
||||
|
||||
if (pmd_none(*pmd))
|
||||
return 0;
|
||||
if (pmd_bad(*pmd)) {
|
||||
pmd_ERROR(*pmd);
|
||||
pmd_clear(pmd);
|
||||
return 0;
|
||||
}
|
||||
ptep = pte_offset(pmd, address);
|
||||
offset = address & ~PMD_MASK;
|
||||
if (offset + size > PMD_SIZE)
|
||||
size = PMD_SIZE - offset;
|
||||
size &= PAGE_MASK;
|
||||
for (offset=0; offset < size; ptep++, offset += PAGE_SIZE) {
|
||||
pte_t pte = *ptep;
|
||||
if (pte_none(pte))
|
||||
continue;
|
||||
freed ++;
|
||||
direct_pte_clear(ptep);
|
||||
}
|
||||
|
||||
return freed;
|
||||
}
|
||||
|
||||
static inline int direct_zap_pmd_range(mmu_gather_t *tlb, pgd_t * dir,
|
||||
unsigned long address, unsigned long size)
|
||||
{
|
||||
pmd_t * pmd;
|
||||
unsigned long end;
|
||||
int freed;
|
||||
|
||||
if (pgd_none(*dir))
|
||||
return 0;
|
||||
if (pgd_bad(*dir)) {
|
||||
pgd_ERROR(*dir);
|
||||
pgd_clear(dir);
|
||||
return 0;
|
||||
}
|
||||
pmd = pmd_offset(dir, address);
|
||||
end = address + size;
|
||||
if (end > ((address + PGDIR_SIZE) & PGDIR_MASK))
|
||||
end = ((address + PGDIR_SIZE) & PGDIR_MASK);
|
||||
freed = 0;
|
||||
do {
|
||||
freed += direct_zap_pte_range(tlb, pmd, address, end - address);
|
||||
address = (address + PMD_SIZE) & PMD_MASK;
|
||||
pmd++;
|
||||
} while (address < end);
|
||||
return freed;
|
||||
}
|
||||
|
||||
/*
|
||||
* remove user pages in a given range.
|
||||
* remove a user page
|
||||
*
|
||||
* There used to be a function here which could remove a whole range
|
||||
* of pages, but it was only ever called with that range equal to a
|
||||
* single page, so I simplified it a bit -- sos22.
|
||||
*/
|
||||
static void direct_zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size)
|
||||
static void direct_zap_page(struct mm_struct *mm, unsigned long address)
|
||||
{
|
||||
mmu_gather_t *tlb;
|
||||
pgd_t * dir;
|
||||
unsigned long start = address, end = address + size;
|
||||
int freed = 0;
|
||||
pmd_t * pmd;
|
||||
pte_t * pte;
|
||||
|
||||
dir = pgd_offset(mm, address);
|
||||
|
||||
@@ -281,20 +183,14 @@ static void direct_zap_page_range(struct mm_struct *mm, unsigned long address, u
|
||||
* even if kswapd happened to be looking at this
|
||||
* process we _want_ it to get stuck.
|
||||
*/
|
||||
if (address >= end)
|
||||
BUG();
|
||||
spin_lock(&mm->page_table_lock);
|
||||
flush_cache_range(mm, address, end);
|
||||
flush_cache_range(mm, address, address + PAGE_SIZE);
|
||||
|
||||
tlb = tlb_gather_mmu(mm);
|
||||
|
||||
do {
|
||||
freed += direct_zap_pmd_range(tlb, dir, address, end - address);
|
||||
address = (address + PGDIR_SIZE) & PGDIR_MASK;
|
||||
dir++;
|
||||
} while (address && (address < end));
|
||||
|
||||
/* this will flush any remaining tlb entries */
|
||||
tlb_finish_mmu(tlb, start, end);
|
||||
pmd = pmd_offset(dir, address);
|
||||
pte = pte_offset(pmd, address);
|
||||
direct_pte_clear(pte);
|
||||
tlb_finish_mmu(tlb, address, address + PAGE_SIZE);
|
||||
|
||||
/* decrementing rss removed */
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
@@ -303,16 +199,16 @@ static void direct_zap_page_range(struct mm_struct *mm, unsigned long address, u
|
||||
|
||||
int direct_unmap(struct mm_struct *mm, unsigned long addr, unsigned long size)
|
||||
{
|
||||
int count = 0, tot_pages = (size+PAGE_SIZE-1) >> PAGE_SHIFT;
|
||||
direct_mmap_node_t * node;
|
||||
struct list_head * curr;
|
||||
struct list_head * direct_list = &mm->context.direct_list;
|
||||
unsigned long end;
|
||||
|
||||
curr = direct_list->next;
|
||||
while ( curr != direct_list )
|
||||
{
|
||||
node = list_entry(curr, direct_mmap_node_t, list);
|
||||
if ( node->vm_start == addr )
|
||||
if ( node->vm_start == addr && node->vm_end == addr + size)
|
||||
break;
|
||||
curr = curr->next;
|
||||
}
|
||||
@@ -323,11 +219,17 @@ int direct_unmap(struct mm_struct *mm, unsigned long addr, unsigned long size)
|
||||
list_del(&node->list);
|
||||
kfree(node);
|
||||
|
||||
while ( count < tot_pages )
|
||||
if (size & ~PAGE_MASK) {
|
||||
printk("Managed to map something which isn\'t a multiple of a page size...\n");
|
||||
BUG();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
end = addr + size;
|
||||
while ( addr < end )
|
||||
{
|
||||
direct_zap_page_range(mm, addr, PAGE_SIZE);
|
||||
direct_zap_page(mm, addr);
|
||||
addr += PAGE_SIZE;
|
||||
count++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||