aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>2004-04-30 16:56:08 +0000
committeriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>2004-04-30 16:56:08 +0000
commit0780b0730b169a1ef80c7308cffc760ddc03268e (patch)
treed10f790fdb7ea8e1de43546daf43cf15e265a406
parent33e4a0c224e38eefd0654f8627363d928247b3a6 (diff)
downloadxen-0780b0730b169a1ef80c7308cffc760ddc03268e.tar.gz
xen-0780b0730b169a1ef80c7308cffc760ddc03268e.tar.bz2
xen-0780b0730b169a1ef80c7308cffc760ddc03268e.zip
bitkeeper revision 1.881 (409285285QhBEC23wsKBevdQUow-YA)
faster suspend
-rw-r--r--tools/Makefile4
-rwxr-xr-xtools/examples/xc_dom_control.py1
-rw-r--r--tools/xc/lib/Makefile2
-rw-r--r--tools/xc/lib/xc_linux_restore.c2
-rw-r--r--tools/xc/lib/xc_linux_save.c220
-rw-r--r--tools/xc/lib/xc_private.c126
-rw-r--r--tools/xc/lib/xc_private.h14
-rw-r--r--xen/common/kernel.c3
-rw-r--r--xen/common/memory.c18
-rw-r--r--xen/include/xen/sched.h3
-rw-r--r--xen/net/dev.c5
-rw-r--r--xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c9
-rw-r--r--xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c24
-rw-r--r--xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h1
14 files changed, 303 insertions, 129 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 0d4c43fb24..9ddf5f25a2 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -17,6 +17,10 @@ install: all
$(MAKE) -C xenctl install
$(MAKE) -C xend install
+dist: $(TARGET)
+ $(MAKE) prefix=`pwd`/../../install dist=yes install
+
+
clean:
$(MAKE) -C balloon clean
$(MAKE) -C xc clean
diff --git a/tools/examples/xc_dom_control.py b/tools/examples/xc_dom_control.py
index ea97a45f0e..080af6f366 100755
--- a/tools/examples/xc_dom_control.py
+++ b/tools/examples/xc_dom_control.py
@@ -137,6 +137,7 @@ elif cmd == 'suspend':
os.kill(pid, signal.SIGTERM)
xc.domain_stop( dom=dom )
+ time.sleep(0.1);
rc = xc.linux_save( dom=dom, state_file=file, progress=1)
if rc == 0 : xc.domain_destroy( dom=dom, force=1 )
diff --git a/tools/xc/lib/Makefile b/tools/xc/lib/Makefile
index 79dce046df..f542935167 100644
--- a/tools/xc/lib/Makefile
+++ b/tools/xc/lib/Makefile
@@ -4,7 +4,7 @@ MINOR = 0
SONAME = libxc.so.$(MAJOR)
CC = gcc
-CFLAGS = -c -Wall -O3 -fno-strict-aliasing
+CFLAGS = -c -Werror -O3 -fno-strict-aliasing
CFLAGS += -I../../../xen/include/hypervisor-ifs
CFLAGS += -I../../xend/lib
CFLAGS += -I../../../xenolinux-sparse/include
diff --git a/tools/xc/lib/xc_linux_restore.c b/tools/xc/lib/xc_linux_restore.c
index 239df65984..893cd0cef4 100644
--- a/tools/xc/lib/xc_linux_restore.c
+++ b/tools/xc/lib/xc_linux_restore.c
@@ -246,7 +246,7 @@ int xc_linux_restore(int xc_handle,
{
if ( (pfn = ppage[j] >> PAGE_SHIFT) >= nr_pfns )
{
- ERROR("Frame number in page table is out of range");
+ ERROR("Frame number in type %d page table is out of range. i=%d j=%d pfn=%d nr_pfns=%d",pfn_type[i],i,j,pfn,nr_pfns);
goto out;
}
if ( (pfn_type[pfn] != NONE) && (ppage[j] & _PAGE_RW) )
diff --git a/tools/xc/lib/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c
index e6e8f8864d..0a367234de 100644
--- a/tools/xc/lib/xc_linux_save.c
+++ b/tools/xc/lib/xc_linux_save.c
@@ -24,7 +24,7 @@
*/
#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \
(((_mfn) < (1024*1024)) && \
- (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn)))
+ (live_pfn_to_mfn_table[live_mfn_to_pfn_table[_mfn]] == (_mfn)))
/* Returns TRUE if MFN is successfully converted to a PFN. */
#define translate_mfn_to_pfn(_pmfn) \
@@ -34,7 +34,7 @@
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) \
_res = 0; \
else \
- *(_pmfn) = mfn_to_pfn_table[mfn]; \
+ *(_pmfn) = live_mfn_to_pfn_table[mfn]; \
_res; \
})
@@ -80,7 +80,7 @@ int xc_linux_save(int xc_handle,
int verbose)
{
dom0_op_t op;
- int rc = 1, i, j;
+ int rc = 1, i, j, k, n;
unsigned long mfn;
unsigned int prev_pc, this_pc;
@@ -103,25 +103,25 @@ int xc_linux_save(int xc_handle,
unsigned long *pfn_type = NULL;
/* A temporary mapping, and a copy, of one frame of guest memory. */
- unsigned long *ppage, page[1024];
+ unsigned long page[1024];
/* A copy of the pfn-to-mfn table frame list. */
- unsigned long *pfn_to_mfn_frame_list;
- /* A live mapping of the pfn-to-mfn table frame list. */
unsigned long *live_pfn_to_mfn_frame_list;
+ unsigned long pfn_to_mfn_frame_list[1024];
- /* A table translating each PFN to its current MFN. */
- unsigned long *pfn_to_mfn_table = NULL;
/* Live mapping of the table mapping each PFN to its current MFN. */
unsigned long *live_pfn_to_mfn_table = NULL;
- /* A table translating each current MFN to its canonical PFN. */
- unsigned long *mfn_to_pfn_table = NULL;
+ /* Live mapping of system MFN to PFN table. */
+ unsigned long *live_mfn_to_pfn_table = NULL;
/* Live mapping of shared info structure */
unsigned long *live_shinfo;
+ /* base of the region in which domain memory is mapped */
+ unsigned char *region_base;
+
/* A temporary mapping, and a copy, of the guest's suspend record. */
- suspend_record_t *srec;
+ suspend_record_t *p_srec, srec;
/* The name and descriptor of the file that we are writing to. */
int fd;
@@ -187,118 +187,126 @@ int xc_linux_save(int xc_handle,
}
- /* Map the suspend-record MFN to pin it */
- srec = mfn_mapper_map_single(xc_handle, PROT_READ,
- ctxt.cpu_ctxt.esi, sizeof(*srec));
+ /* Map the suspend-record MFN to pin it. The page must be owned by
+ domid for this to succeed. */
+ p_srec = mfn_mapper_map_single(xc_handle, domid,
+ sizeof(srec), PROT_READ,
+ ctxt.cpu_ctxt.esi );
- /* Is the suspend-record MFN actually valid for this domain? */
- if ( !check_pfn_ownership(xc_handle, ctxt.cpu_ctxt.esi, domid) )
+ if (!p_srec)
{
- ERROR("Invalid state record pointer");
+ ERROR("Couldn't map state record");
goto out;
}
+ memcpy( &srec, p_srec, sizeof(srec) );
+
/* cheesy sanity check */
- if ( srec->nr_pfns > 1024*1024 )
+ if ( srec.nr_pfns > 1024*1024 )
{
ERROR("Invalid state record -- pfn count out of range");
goto out;
}
-
/* the pfn_to_mfn_frame_list fits in a single page */
live_pfn_to_mfn_frame_list =
- mfn_mapper_map_single(xc_handle, PROT_WRITE,
- srec->pfn_to_mfn_frame_list,
- PAGE_SIZE);
+ mfn_mapper_map_single(xc_handle, domid,
+ PAGE_SIZE, PROT_READ,
+ srec.pfn_to_mfn_frame_list );
- if ( !check_pfn_ownership(xc_handle,
- srec->pfn_to_mfn_frame_list, domid) )
+ if (!live_pfn_to_mfn_frame_list)
{
- ERROR("Invalid pfn-to-mfn frame list pointer");
- goto out;
+ ERROR("Couldn't map pfn_to_mfn_frame_list");
+ goto out;
}
+
- memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE );
-
- if ( (mapper_handle1 = mfn_mapper_init(xc_handle, 1024*1024, PROT_READ ))
+ if ( (mapper_handle1 = mfn_mapper_init(xc_handle, domid,
+ 1024*1024, PROT_READ ))
== NULL )
goto out;
- for ( i = 0; i < (srec->nr_pfns+1023)/1024; i++ )
+ for ( i = 0; i < (srec.nr_pfns+1023)/1024; i++ )
{
/* Grab a copy of the pfn-to-mfn table frame list.
This has the effect of preventing the page from being freed and
given to another domain. (though the domain is stopped anyway...) */
mfn_mapper_queue_entry( mapper_handle1, i<<PAGE_SHIFT,
- pfn_to_mfn_frame_list[i],
+ live_pfn_to_mfn_frame_list[i],
PAGE_SIZE );
}
- mfn_mapper_flush_queue(mapper_handle1);
-
- /* Now they're pined, check they're the right dom. We assume
- they're not going to change, otherwise the suspend is going to fail,
- with only itself to blame. */
-
- for ( i = 0; i < (srec->nr_pfns+1023)/1024; i++ )
+ if ( mfn_mapper_flush_queue(mapper_handle1) )
{
- if ( !check_pfn_ownership(xc_handle,
- pfn_to_mfn_frame_list[i], domid) )
- {
- ERROR("Invalid pfn-to-mfn frame list pointer");
- goto out;
- }
+ ERROR("Couldn't map pfn_to_mfn table");
+ goto out;
}
live_pfn_to_mfn_table = mfn_mapper_base( mapper_handle1 );
+
+
/* We want zeroed memory so use calloc rather than malloc. */
- mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024);
- pfn_to_mfn_table = calloc(1, 4 * srec->nr_pfns);
- pfn_type = calloc(1, 4 * srec->nr_pfns);
+ pfn_type = calloc(1, 4 * srec.nr_pfns);
- if ( (mfn_to_pfn_table == NULL) ||
- (pfn_to_mfn_table == NULL) ||
- (pfn_type == NULL) )
+ if ( (pfn_type == NULL) )
{
errno = ENOMEM;
goto out;
}
+
+ /* Track the mfn_to_pfn table down from the domains PT */
+ {
+ unsigned long *pgd;
+ unsigned long mfn_to_pfn_table_start_mfn;
+
+ pgd = mfn_mapper_map_single(xc_handle, domid,
+ PAGE_SIZE, PROT_READ,
+ ctxt.pt_base>>PAGE_SHIFT);
+/*
+ printf("pt mfn=%d pfn=%d type=%08x pte=%08x\n",ctxt.pt_base>>PAGE_SHIFT,
+ mfn_to_pfn_table[ctxt.pt_base>>PAGE_SHIFT],
+ pfn_type[mfn_to_pfn_table[ctxt.pt_base>>PAGE_SHIFT]],
+ pgd[HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT] );
+*/
+ mfn_to_pfn_table_start_mfn = pgd[HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT]>>PAGE_SHIFT;
+
+ live_mfn_to_pfn_table =
+ mfn_mapper_map_single(xc_handle, ~0ULL,
+ PAGE_SIZE*1024, PROT_READ,
+ mfn_to_pfn_table_start_mfn );
+ }
+
+
/*
* Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
* loop we have each MFN mapped at most once. Note that there may be MFNs
* that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
*/
- for ( i = 0; i < srec->nr_pfns; i++ )
+ for ( i = 0; i < srec.nr_pfns; i++ )
{
mfn = live_pfn_to_mfn_table[i];
- if ( !check_pfn_ownership(xc_handle, mfn, domid) )
- {
- ERROR("Invalid frame specified with pfn-to-mfn table");
- goto out;
- }
+#if 1 /* XXX use the master mfn_to_pfn table???? */
- /* Did we map this MFN already? That would be invalid! */
- if ( mfn_to_pfn_table[mfn] )
- {
- ERROR("A machine frame appears twice in pseudophys space");
- goto out;
- }
- mfn_to_pfn_table[mfn] = i;
- pfn_to_mfn_table[i] = live_pfn_to_mfn_table[i];
+ if( live_mfn_to_pfn_table[mfn] != i )
+ printf("i=%d mfn=%d live_mfn_to_pfn_table=%d\n",
+ i,mfn,live_mfn_to_pfn_table[mfn]);
/* Query page type by MFN, but store it by PFN. */
if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn, domid)) ==
GETPFN_ERR )
goto out;
+#endif
+
}
+
+
/* Canonicalise the suspend-record frame number. */
if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) )
{
@@ -322,9 +330,10 @@ int xc_linux_save(int xc_handle,
ERROR("PT base is not in range of pseudophys map");
goto out;
}
- ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
+ ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
/* Canonicalise the pfn-to-mfn table frame-number list. */
+ memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE );
for ( i = 0; i < srec.nr_pfns; i += 1024 )
{
if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
@@ -335,8 +344,15 @@ int xc_linux_save(int xc_handle,
}
/* Start writing out the saved-domain record. */
- live_shinfo = mfn_mapper_map_single(xc_handle, PROT_READ,
- shared_info_frame, PAGE_SIZE);
+ live_shinfo = mfn_mapper_map_single(xc_handle, domid,
+ PAGE_SIZE, PROT_READ,
+ shared_info_frame);
+
+ if (!live_shinfo)
+ {
+ ERROR("Couldn't map live_shinfo");
+ goto out;
+ }
/* Belts and braces safety check on the shared info record */
if ( !check_pfn_ownership(xc_handle, shared_info_frame, domid) )
@@ -360,7 +376,9 @@ int xc_linux_save(int xc_handle,
verbose_printf("Saving memory pages: 0%%");
- if ( (mapper_handle2 = mfn_mapper_init(xc_handle,
+#define BATCH_SIZE 1024 /* 1024 pages (4MB) at a time */
+
+ if ( (mapper_handle2 = mfn_mapper_init(xc_handle, domid,
BATCH_SIZE*4096, PROT_READ ))
== NULL )
goto out;
@@ -383,12 +401,19 @@ int xc_linux_save(int xc_handle,
{
/* queue up mappings for all of the pages in this batch */
+//printf("region n=%d j=%d i=%d mfn=%d\n",n,j,i,live_pfn_to_mfn_table[i]);
mfn_mapper_queue_entry( mapper_handle2, j<<PAGE_SHIFT,
- pfn_to_mfn_frame_list[i],
+ live_pfn_to_mfn_table[i],
PAGE_SIZE );
}
- mfn_mapper_flush_queue(mapper_handle2);
-
+
+ if( mfn_mapper_flush_queue(mapper_handle2) )
+ {
+ ERROR("Couldn't map page region");
+ goto out;
+ }
+
+#if 0
typer_handle = get_type_init( xc_handle, BATCH_SIZE )
for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
@@ -399,42 +424,51 @@ int xc_linux_save(int xc_handle,
pfn_to_mfn_frame_list[i] );
}
-
region_type = get_type;
+#endif
+
for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
{
/* write out pages in batch */
- mfn = pfn_to_mfn_table[i];
-
- ppage = map_pfn_readonly(pm_handle, mfn);
- memcpy(page, ppage, PAGE_SIZE);
- unmap_pfn(pm_handle, ppage);
-
if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
{
- for ( j = 0;
- j < ((pfn_type[i] == L2TAB) ?
+
+ memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE);
+
+ for ( k = 0;
+ k < ((pfn_type[i] == L2TAB) ?
(HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024);
- j++ )
+ k++ )
{
- if ( !(page[j] & _PAGE_PRESENT) ) continue;
- mfn = page[j] >> PAGE_SHIFT;
+ if ( !(page[k] & _PAGE_PRESENT) ) continue;
+ mfn = page[k] >> PAGE_SHIFT;
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
{
ERROR("Frame number in pagetable page is invalid");
goto out;
}
- page[j] &= PAGE_SIZE - 1;
- page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
+ page[k] &= PAGE_SIZE - 1;
+ page[k] |= live_mfn_to_pfn_table[mfn] << PAGE_SHIFT;
+
+ }
+
+ if ( !checked_write(gfd, page, PAGE_SIZE) )
+ {
+ ERROR("Error when writing to state file");
+ goto out;
}
- }
- if ( !checked_write(gfd, page, PAGE_SIZE) )
+
+ }
+ else
{
- ERROR("Error when writing to state file");
- goto out;
+ if ( !checked_write(gfd, region_base + (PAGE_SIZE*j), PAGE_SIZE) )
+ {
+ ERROR("Error when writing to state file");
+ goto out;
+ }
}
}
@@ -450,6 +484,7 @@ out:
/* Restart the domain if we had to stop it to save its state. */
if ( we_stopped_it )
{
+ printf("Restart domain\n");
op.cmd = DOM0_STARTDOMAIN;
op.u.startdomain.domain = (domid_t)domid;
(void)do_dom0_op(xc_handle, &op);
@@ -457,13 +492,6 @@ out:
gzclose(gfd);
- if ( pm_handle >= 0 )
- (void)close_pfn_mapper(pm_handle);
-
- if ( pfn_to_mfn_table != NULL )
- free(pfn_to_mfn_table);
- if ( mfn_to_pfn_table != NULL )
- free(mfn_to_pfn_table);
if ( pfn_type != NULL )
free(pfn_type);
diff --git a/tools/xc/lib/xc_private.c b/tools/xc/lib/xc_private.c
index 796da64ad7..0c9092b607 100644
--- a/tools/xc/lib/xc_private.c
+++ b/tools/xc/lib/xc_private.c
@@ -47,8 +47,9 @@ void unmap_pfn(int pm_handle, void *vaddr)
/*******************/
-void * mfn_mapper_map_single(int xc_handle, int prot,
- unsigned long mfn, int size)
+void * mfn_mapper_map_single(int xc_handle, domid_t dom,
+ int size, int prot,
+ unsigned long mfn )
{
privcmd_mmap_t ioctlx;
privcmd_mmap_entry_t entry;
@@ -57,6 +58,7 @@ void * mfn_mapper_map_single(int xc_handle, int prot,
if (addr)
{
ioctlx.num=1;
+ ioctlx.dom=dom;
ioctlx.entry=&entry;
entry.va=(unsigned long) addr;
entry.mfn=mfn;
@@ -67,7 +69,7 @@ void * mfn_mapper_map_single(int xc_handle, int prot,
return addr;
}
-mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot)
+mfn_mapper_t * mfn_mapper_init(int xc_handle, domid_t dom, int size, int prot)
{
mfn_mapper_t * t;
t = calloc( 1, sizeof(mfn_mapper_t)+
@@ -76,6 +78,7 @@ mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot)
t->xc_handle = xc_handle;
t->size = size;
t->prot = prot;
+ t->error = 0;
t->max_queue_size = mfn_mapper_queue_size;
t->addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 );
if (!t->addr)
@@ -84,6 +87,7 @@ mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot)
return NULL;
}
t->ioctl.num = 0;
+ t->ioctl.dom = dom;
t->ioctl.entry = (privcmd_mmap_entry_t *) &t[1];
return t;
}
@@ -99,14 +103,29 @@ void mfn_mapper_close(mfn_mapper_t *t)
free(t);
}
+static int __mfn_mapper_flush_queue(mfn_mapper_t *t)
+{
+ int rc;
+ rc = ioctl( t->xc_handle, IOCTL_PRIVCMD_MMAP, &t->ioctl );
+ t->ioctl.num = 0;
+ if(rc && !t->error)
+ t->error = rc;
+ return rc;
+}
+
int mfn_mapper_flush_queue(mfn_mapper_t *t)
{
int rc;
+
+ rc = __mfn_mapper_flush_queue(t);
- rc = ioctl( t->xc_handle, IOCTL_PRIVCMD_MMAP, &t->ioctl );
- if (rc<0) return rc;
- t->ioctl.num = 0;
- return 0;
+ if ( t->error )
+ {
+ rc = t->error;
+ }
+
+ t->error = 0;
+ return rc;
}
void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset,
@@ -123,30 +142,113 @@ void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset,
{
prev = &t->ioctl.entry[t->ioctl.num-1];
- if ( (prev->va+(prev->npages*PAGE_SIZE)) == (t->addr+offset) &&
+ if ( (prev->va+(prev->npages*PAGE_SIZE)) ==
+ ((unsigned long)t->addr+offset) &&
(prev->mfn+prev->npages) == mfn )
{
prev->npages += pages;
-printf("merge\n");
return t->addr+offset;
}
}
- entry->va = t->addr+offset;
+ entry->va = (unsigned long)t->addr+offset;
entry->mfn = mfn;
entry->npages = pages;
t->ioctl.num++;
if(t->ioctl.num == t->max_queue_size)
{
- if ( mfn_mapper_flush_queue(t) )
- return 0;
+ if ( __mfn_mapper_flush_queue(t) )
+ return 0;
}
return t->addr+offset;
}
+/*******************/
+
+typedef struct dom0_op_compact_getpageframeinfo {
+ unsigned long cmd;
+ unsigned long interface_version; /* DOM0_INTERFACE_VERSION */
+ dom0_getpageframeinfo_t getpageframeinfo;
+} dom0_op_compact_getpageframeinfo_t;
+
+
+typedef struct mfn_typer {
+ domid_t dom;
+ int max;
+ int nr_multicall_ents;
+ multicall_entry_t *multicall_list;
+ dom0_op_compact_getpageframeinfo_t *gpf_list;
+} mfn_typer_t;
+
+
+mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num );
+
+void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn );
+
+int mfn_typer_flush_queue(mfn_typer_t *t);
+
+unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx);
+
+mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num )
+{
+ mfn_typer_t *t;
+ multicall_entry_t *m;
+ dom0_op_compact_getpageframeinfo_t *d;
+
+ t = calloc(1, sizeof(mfn_typer_t) );
+ m = calloc(1, sizeof(multicall_entry_t)*num );
+ d = calloc(1, sizeof(dom0_op_compact_getpageframeinfo_t)*num );
+
+ if (!t || !m || !d)
+ {
+ if(t) free(t);
+ if(m) free(m);
+ if(d) free(d);
+ return NULL;
+ }
+
+ t->max = num;
+ t->nr_multicall_ents=0;
+ t->multicall_list=m;
+ t->gpf_list=d;
+ t->dom = dom;
+
+ return t;
+}
+
+void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn )
+{
+ int i = t->nr_multicall_ents;
+ multicall_entry_t *m = &t->multicall_list[i];
+ dom0_op_compact_getpageframeinfo_t *d = &t->gpf_list[i];
+
+ d->cmd = DOM0_GETPAGEFRAMEINFO;
+ d->interface_version = DOM0_INTERFACE_VERSION;
+ d->getpageframeinfo.pfn = mfn;
+ d->getpageframeinfo.domain = t->dom;
+ d->getpageframeinfo.type = ~0UL;
+
+ m->op = __HYPERVISOR_dom0_op;
+ m->args[0] = (unsigned long)d;
+
+ t->nr_multicall_ents++;
+}
+
+int mfn_typer_flush_queue(mfn_typer_t *t)
+{
+ if (t->nr_multicall_ents == 0) return 0;
+ (void)HYPERVISOR_multicall(t->multicall_list, t->nr_multicall_ents);
+ t->nr_multicall_ents = 0;
+}
+
+unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx)
+{
+ return t->gpf_list[idx].getpageframeinfo.type;
+}
+
/*******************/
diff --git a/tools/xc/lib/xc_private.h b/tools/xc/lib/xc_private.h
index d173e58e46..198c703eaf 100644
--- a/tools/xc/lib/xc_private.h
+++ b/tools/xc/lib/xc_private.h
@@ -16,8 +16,6 @@
#include "xc.h"
-#include <asm-xen/proc_cmd.h>
-
/* from xen/include/hypervisor-ifs */
#include <hypervisor-if.h>
#include <dom0_ops.h>
@@ -25,6 +23,10 @@
#include <event_channel.h>
#include <sched_ctl.h>
+#include <asm-xen/proc_cmd.h>
+
+
+
/* from xend/lib */
#include <domain_controller.h>
@@ -188,6 +190,7 @@ typedef struct privcmd_mmap_entry {
typedef struct privcmd_mmap {
int num;
+ domid_t dom;
privcmd_mmap_entry_t *entry;
} privcmd_mmap_t;
*/
@@ -198,16 +201,17 @@ typedef struct mfn_mapper {
int xc_handle;
int size;
int prot;
+ int error;
int max_queue_size;
void * addr;
privcmd_mmap_t ioctl;
} mfn_mapper_t;
-void * mfn_mapper_map_single(int xc_handle, int prot,
- unsigned long mfn, int size);
+void * mfn_mapper_map_single(int xc_handle, domid_t dom, int size, int prot,
+ unsigned long mfn );
-mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot);
+mfn_mapper_t * mfn_mapper_init(int xc_handle, domid_t dom, int size, int prot);
void * mfn_mapper_base(mfn_mapper_t *t);
diff --git a/xen/common/kernel.c b/xen/common/kernel.c
index 3c10cf3ca2..d8d5d03251 100644
--- a/xen/common/kernel.c
+++ b/xen/common/kernel.c
@@ -255,6 +255,9 @@ void cmain(unsigned long magic, multiboot_info_t *mbi)
start_of_day();
+ /* Add CPU0 idle task to the task hash list */
+ task_hash[TASK_HASH(IDLE_DOMAIN_ID)] = &idle0_task;
+
/* Create initial domain 0. */
dom0_params.memory_kb = opt_dom0_mem;
new_dom = do_createdomain(0, 0);
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 1ffc207bdf..ed2e5b6e17 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -194,6 +194,9 @@ static struct {
*/
void __init init_frametable(unsigned long nr_pages)
{
+ int i;
+ unsigned long mfn;
+
memset(percpu_info, 0, sizeof(percpu_info));
max_page = nr_pages;
@@ -206,8 +209,20 @@ void __init init_frametable(unsigned long nr_pages)
INIT_LIST_HEAD(&free_list);
free_pfns = 0;
+ /* so that we can map them latter, set the ownership of pages
+ belonging to the machine_to_phys_mapping to CPU0 idle task */
+
+ mfn = virt_to_phys((void *)RDWR_MPT_VIRT_START)>>PAGE_SHIFT;
+// for(i=0;i<nr_pages;i+=1024,mfn++)
+ for(i=0;i<1024*1024;i+=1024,mfn++)
+ {
+ frame_table[mfn].count_and_flags = 1 | PGC_allocated;
+ frame_table[mfn].type_and_flags = 1 | PGT_gdt_page; // anything non RW
+ frame_table[mfn].u.domain = &idle0_task;
+ }
}
+
void add_to_domain_alloc_list(unsigned long ps, unsigned long pe)
{
struct pfn_info *pf;
@@ -895,7 +910,8 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
break;
case MMUEXT_SET_SUBJECTDOM_H:
- percpu_info[cpu].subject_id |= (domid_t)((ptr&~0xFFFF)|(val>>16))<<32;
+ percpu_info[cpu].subject_id |= ((domid_t)((ptr&~0xFFFF)|(val>>16)))<<32;
+
if ( !IS_PRIV(current) )
{
MEM_LOG("Dom %llu has no privilege to set subject domain",
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 14f4019ac1..c9b072aaa0 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -209,7 +209,8 @@ struct task_struct
mm: IDLE0_MM, \
addr_limit: KERNEL_DS, \
thread: INIT_THREAD, \
- flags: 1<<PF_IDLETASK \
+ flags: 1<<PF_IDLETASK, \
+ refcnt: ATOMIC_INIT(1) \
}
extern struct task_struct idle0_task;
diff --git a/xen/net/dev.c b/xen/net/dev.c
index e4e1092840..5ab01092f0 100644
--- a/xen/net/dev.c
+++ b/xen/net/dev.c
@@ -2156,8 +2156,9 @@ static void get_rx_bufs(net_vif_t *vif)
0) !=
(PGC_allocated | PGC_tlb_flush_on_type_change | 2)) )
{
- DPRINTK("Page held more than once %08x\n",
- buf_page->count_and_flags);
+ DPRINTK("Page held more than once %08x %s\n",
+ buf_page->count_and_flags,
+ (buf_page->u.domain)?buf_page->u.domain->name:"None");
if ( !get_page_type(buf_page, PGT_writeable_page) )
put_page(buf_page);
else if ( cmpxchg(ptep, pte & ~_PAGE_PRESENT, pte) !=
diff --git a/xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c b/xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c
index a94b016fb7..4e507081be 100644
--- a/xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c
+++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c
@@ -67,7 +67,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
#define PRIVCMD_MMAP_SZ 32
privcmd_mmap_t mmapcmd;
privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p;
- int i;
+ int i, rc;
if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) )
return -EFAULT;
@@ -95,12 +95,13 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
if (msg[j].va + (msg[j].npages<<PAGE_SHIFT) > vma->vm_end)
return -EINVAL;
- if (direct_remap_area_pages(vma->vm_mm,
+ if (rc = direct_remap_area_pages(vma->vm_mm,
msg[j].va&PAGE_MASK,
msg[j].mfn<<PAGE_SHIFT,
msg[j].npages<<PAGE_SHIFT,
- vma->vm_page_prot))
- return -EINVAL;
+ vma->vm_page_prot,
+ mmapcmd.dom))
+ return rc;
}
}
ret = 0;
diff --git a/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c b/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c
index 6474d4c6ed..7b4d1ff0a9 100644
--- a/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c
+++ b/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c
@@ -27,7 +27,7 @@
#define direct_mk_pte_phys(physpage, pgprot) \
__direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot)
-static inline void direct_remap_area_pte(pte_t *pte,
+static inline int direct_remap_area_pte(pte_t *pte,
unsigned long address,
unsigned long size,
unsigned long machine_addr,
@@ -39,6 +39,9 @@ static inline void direct_remap_area_pte(pte_t *pte,
mmu_update_t *u, *v;
u = v = vmalloc(3*PAGE_SIZE); /* plenty */
+ if (!u)
+ return -ENOMEM;
+
/* If not I/O mapping then specify General-Purpose Subject Domain (GPS). */
if ( domid != 0 )
{
@@ -74,10 +77,15 @@ static inline void direct_remap_area_pte(pte_t *pte,
pte++;
} while (address && (address < end));
- if ( ((v-u) != 0) && (HYPERVISOR_mmu_update(u, v-u) < 0) )
+ if ( ((v-u) > 2) && (HYPERVISOR_mmu_update(u, v-u) < 0) )
+ {
printk(KERN_WARNING "Failed to ioremap %08lx->%08lx (%08lx)\n",
end-size, end, machine_addr-size);
+ return -EINVAL;
+ }
+
vfree(u);
+ return 0;
}
static inline int direct_remap_area_pmd(struct mm_struct *mm,
@@ -89,6 +97,7 @@ static inline int direct_remap_area_pmd(struct mm_struct *mm,
domid_t domid)
{
unsigned long end;
+ int rc;
address &= ~PGDIR_MASK;
end = address + size;
@@ -101,8 +110,11 @@ static inline int direct_remap_area_pmd(struct mm_struct *mm,
pte_t * pte = pte_alloc(mm, pmd, address);
if (!pte)
return -ENOMEM;
- direct_remap_area_pte(pte, address, end - address,
- address + machine_addr, prot, domid);
+
+ if ( rc = direct_remap_area_pte(pte, address, end - address,
+ address + machine_addr, prot, domid) )
+ return rc;
+
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address && (address < end));
@@ -120,8 +132,8 @@ int direct_remap_area_pages(struct mm_struct *mm,
pgd_t * dir;
unsigned long end = address + size;
-printk("direct_remap_area_pages va=%08lx ma=%08lx size=%d\n",
- address, machine_addr, size);
+/*printk("direct_remap_area_pages va=%08lx ma=%08lx size=%d\n",
+ address, machine_addr, size);*/
machine_addr -= address;
dir = pgd_offset(mm, address);
diff --git a/xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h b/xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h
index 205355fa9c..30cec9aff5 100644
--- a/xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h
+++ b/xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h
@@ -21,6 +21,7 @@ typedef struct privcmd_mmap_entry {
typedef struct privcmd_mmap {
int num;
+ domid_t dom; /* target domain */
privcmd_mmap_entry_t *entry;
} privcmd_mmap_t;