aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsos22@labyrinth.cl.cam.ac.uk <sos22@labyrinth.cl.cam.ac.uk>2003-07-09 10:58:27 +0000
committersos22@labyrinth.cl.cam.ac.uk <sos22@labyrinth.cl.cam.ac.uk>2003-07-09 10:58:27 +0000
commitf05b0dd80e2aca10ac47ee07d629d09bd3a707cd (patch)
tree2d674c18e5e266b568766143e902bbddfe47c998
parentc5ef748c89912ef97ebf9e218fa303e2ab11d101 (diff)
downloadxen-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.h2
-rw-r--r--tools/internal/xi_build.c114
-rw-r--r--xen/include/hypervisor-ifs/dom0_ops.h23
-rw-r--r--xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c20
-rw-r--r--xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c230
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(&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;