diff options
author | sos22@labyrinth.cl.cam.ac.uk <sos22@labyrinth.cl.cam.ac.uk> | 2003-07-09 10:58:27 +0000 |
---|---|---|
committer | sos22@labyrinth.cl.cam.ac.uk <sos22@labyrinth.cl.cam.ac.uk> | 2003-07-09 10:58:27 +0000 |
commit | f05b0dd80e2aca10ac47ee07d629d09bd3a707cd (patch) | |
tree | 2d674c18e5e266b568766143e902bbddfe47c998 | |
parent | c5ef748c89912ef97ebf9e218fa303e2ab11d101 (diff) | |
download | xen-f05b0dd80e2aca10ac47ee07d629d09bd3a707cd.tar.gz xen-f05b0dd80e2aca10ac47ee07d629d09bd3a707cd.tar.bz2 xen-f05b0dd80e2aca10ac47ee07d629d09bd3a707cd.zip |
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.
-rw-r--r-- | tools/internal/mem_defs.h | 2 | ||||
-rw-r--r-- | tools/internal/xi_build.c | 114 | ||||
-rw-r--r-- | xen/include/hypervisor-ifs/dom0_ops.h | 23 | ||||
-rw-r--r-- | xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c | 20 | ||||
-rw-r--r-- | xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c | 230 |
5 files changed, 127 insertions, 262 deletions
diff --git a/tools/internal/mem_defs.h b/tools/internal/mem_defs.h index a9a1441d61..4ba84ffaee 100644 --- a/tools/internal/mem_defs.h +++ b/tools/internal/mem_defs.h @@ -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) diff --git a/tools/internal/xi_build.c b/tools/internal/xi_build.c index 1457281f74..c8dfc78786 100644 --- a/tools/internal/xi_build.c +++ b/tools/internal/xi_build.c @@ -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); - - if (dom_mem->vaddr == -1) { - perror("mapping domain memory"); - 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); + + 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) { diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index 6286f11b98..b6df8bee46 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -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 diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c index 496a8ce279..7570982fee 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c @@ -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; diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c index 3e3ff19fca..e2f14db03f 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c @@ -32,90 +32,45 @@ 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) -{ - if (!pte_none(page)) { - printk("forget_pte: old mapping existed!\n"); - BUG(); - } -} +/* Note: this is only safe if the mm semaphore is held when called. */ -static inline void direct_remappte_range(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, pgprot_t prot) +static int direct_remap_page(unsigned long from, unsigned long phys_addr, pgprot_t prot) { - unsigned long end; + struct mm_struct *mm = current->mm; + pgd_t * dir; + pmd_t *pmd; + pte_t *pte; - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - do { - pte_t oldpage; - oldpage = ptep_get_and_clear(pte); + pte_t oldpage; - direct_set_pte(pte, direct_mk_pte_phys(phys_addr, prot)); + 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; + } - forget_pte(oldpage); - address += PAGE_SIZE; - phys_addr += PAGE_SIZE; - pte++; - } while (address && (address < end)); + /* 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)); -} + spin_unlock(&mm->page_table_lock); -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; + flush_tlb_range(mm, from, from + PAGE_SIZE); - 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; -} - /* * used for remapping discontiguous bits of domain's memory, pages to map are * found from frame table beginning at the given first_pg index @@ -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; |