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:
sos22@labyrinth.cl.cam.ac.uk committed 2003-07-09 10:58:27 +00:00
1 parent c5ef748c89
commit f05b0dd80e
5 files changed
+131 -266

No files matched your search

+1 -1
View File
@@ -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
View File
@@ -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) {
+15 -8
View File
@@ -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(&current->mm->context.direct_list, addr);
if(entry != &current->mm->context.direct_list){
list_add_tail(&dmmap->list, entry);
list_add_tail(&dmmap->list, entry);
} else {
list_add_tail(&dmmap->list, &current->mm->context.direct_list);
list_add_tail(&dmmap->list, &current->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;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.