mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Re-indent libxc to avoid hard tabs. Also, fix the PAE
domain builder to correctly write PTEs that map pages above 4GB. Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
d847ecf971
commit
e701d05c8a
13 files changed
+1149
-996
No files matched your search
+92
-82
@@ -11,10 +11,10 @@
|
||||
|
||||
static int
|
||||
copy_from_domain_page(int xc_handle,
|
||||
u32 domid,
|
||||
unsigned long *page_array,
|
||||
unsigned long src_pfn,
|
||||
void *dst_page)
|
||||
u32 domid,
|
||||
unsigned long *page_array,
|
||||
unsigned long src_pfn,
|
||||
void *dst_page)
|
||||
{
|
||||
void *vaddr = xc_map_foreign_range(
|
||||
xc_handle, domid, PAGE_SIZE, PROT_READ, page_array[src_pfn]);
|
||||
@@ -27,90 +27,100 @@ copy_from_domain_page(int xc_handle,
|
||||
|
||||
int
|
||||
xc_domain_dumpcore(int xc_handle,
|
||||
u32 domid,
|
||||
const char *corename)
|
||||
u32 domid,
|
||||
const char *corename)
|
||||
{
|
||||
unsigned long nr_pages;
|
||||
unsigned long *page_array;
|
||||
xc_dominfo_t info;
|
||||
int i, j, vcpu_map_size, dump_fd;
|
||||
char *dump_mem, *dump_mem_start = NULL;
|
||||
struct xc_core_header header;
|
||||
vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
|
||||
unsigned long nr_pages;
|
||||
unsigned long *page_array;
|
||||
xc_dominfo_t info;
|
||||
int i, j, vcpu_map_size, dump_fd;
|
||||
char *dump_mem, *dump_mem_start = NULL;
|
||||
struct xc_core_header header;
|
||||
vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
|
||||
|
||||
|
||||
if ((dump_fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0) {
|
||||
PERROR("Could not open corefile %s: %s", corename, strerror(errno));
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ((dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL) {
|
||||
PERROR("Could not allocate dump_mem");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (xc_domain_getinfo(xc_handle, domid, 1, &info) != 1) {
|
||||
PERROR("Could not get info for domain");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
vcpu_map_size = sizeof(info.vcpu_to_cpu) / sizeof(info.vcpu_to_cpu[0]);
|
||||
|
||||
if ((dump_fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0) {
|
||||
PERROR("Could not open corefile %s: %s", corename, strerror(errno));
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ((dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL) {
|
||||
PERROR("Could not allocate dump_mem");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (xc_domain_getinfo(xc_handle, domid, 1, &info) != 1) {
|
||||
PERROR("Could not get info for domain");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
vcpu_map_size = sizeof(info.vcpu_to_cpu) / sizeof(info.vcpu_to_cpu[0]);
|
||||
|
||||
for (i = 0, j = 0; i < vcpu_map_size; i++) {
|
||||
if (info.vcpu_to_cpu[i] == -1) {
|
||||
continue;
|
||||
}
|
||||
if (xc_domain_get_vcpu_context(xc_handle, domid, i, &ctxt[j])) {
|
||||
PERROR("Could not get all vcpu contexts for domain");
|
||||
goto error_out;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
nr_pages = info.nr_pages;
|
||||
for (i = 0, j = 0; i < vcpu_map_size; i++) {
|
||||
if (info.vcpu_to_cpu[i] == -1) {
|
||||
continue;
|
||||
}
|
||||
if (xc_domain_get_vcpu_context(xc_handle, domid, i, &ctxt[j])) {
|
||||
PERROR("Could not get all vcpu contexts for domain");
|
||||
goto error_out;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
nr_pages = info.nr_pages;
|
||||
|
||||
header.xch_magic = 0xF00FEBED;
|
||||
header.xch_nr_vcpus = info.vcpus;
|
||||
header.xch_nr_pages = nr_pages;
|
||||
header.xch_ctxt_offset = sizeof(struct xc_core_header);
|
||||
header.xch_index_offset = sizeof(struct xc_core_header) +
|
||||
sizeof(vcpu_guest_context_t)*info.vcpus;
|
||||
header.xch_pages_offset = round_pgup(sizeof(struct xc_core_header) +
|
||||
(sizeof(vcpu_guest_context_t) * info.vcpus) +
|
||||
(nr_pages * sizeof(unsigned long)));
|
||||
header.xch_magic = 0xF00FEBED;
|
||||
header.xch_nr_vcpus = info.vcpus;
|
||||
header.xch_nr_pages = nr_pages;
|
||||
header.xch_ctxt_offset = sizeof(struct xc_core_header);
|
||||
header.xch_index_offset = sizeof(struct xc_core_header) +
|
||||
sizeof(vcpu_guest_context_t)*info.vcpus;
|
||||
header.xch_pages_offset = round_pgup(sizeof(struct xc_core_header) +
|
||||
(sizeof(vcpu_guest_context_t) * info.vcpus) +
|
||||
(nr_pages * sizeof(unsigned long)));
|
||||
|
||||
write(dump_fd, &header, sizeof(struct xc_core_header));
|
||||
write(dump_fd, &ctxt, sizeof(ctxt[0]) * info.vcpus);
|
||||
write(dump_fd, &header, sizeof(struct xc_core_header));
|
||||
write(dump_fd, &ctxt, sizeof(ctxt[0]) * info.vcpus);
|
||||
|
||||
if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
|
||||
printf("Could not allocate memory\n");
|
||||
goto error_out;
|
||||
}
|
||||
if (xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages) {
|
||||
printf("Could not get the page frame list\n");
|
||||
goto error_out;
|
||||
}
|
||||
write(dump_fd, page_array, nr_pages * sizeof(unsigned long));
|
||||
lseek(dump_fd, header.xch_pages_offset, SEEK_SET);
|
||||
for (dump_mem = dump_mem_start, i = 0; i < nr_pages; i++) {
|
||||
copy_from_domain_page(xc_handle, domid, page_array, i, dump_mem);
|
||||
dump_mem += PAGE_SIZE;
|
||||
if (((i + 1) % DUMP_INCREMENT == 0) || (i + 1) == nr_pages) {
|
||||
if (write(dump_fd, dump_mem_start, dump_mem - dump_mem_start) <
|
||||
dump_mem - dump_mem_start) {
|
||||
PERROR("Partial write, file system full?");
|
||||
goto error_out;
|
||||
}
|
||||
dump_mem = dump_mem_start;
|
||||
}
|
||||
}
|
||||
if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
|
||||
printf("Could not allocate memory\n");
|
||||
goto error_out;
|
||||
}
|
||||
if (xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages) {
|
||||
printf("Could not get the page frame list\n");
|
||||
goto error_out;
|
||||
}
|
||||
write(dump_fd, page_array, nr_pages * sizeof(unsigned long));
|
||||
lseek(dump_fd, header.xch_pages_offset, SEEK_SET);
|
||||
for (dump_mem = dump_mem_start, i = 0; i < nr_pages; i++) {
|
||||
copy_from_domain_page(xc_handle, domid, page_array, i, dump_mem);
|
||||
dump_mem += PAGE_SIZE;
|
||||
if (((i + 1) % DUMP_INCREMENT == 0) || (i + 1) == nr_pages) {
|
||||
if (write(dump_fd, dump_mem_start, dump_mem - dump_mem_start) <
|
||||
dump_mem - dump_mem_start) {
|
||||
PERROR("Partial write, file system full?");
|
||||
goto error_out;
|
||||
}
|
||||
dump_mem = dump_mem_start;
|
||||
}
|
||||
}
|
||||
|
||||
close(dump_fd);
|
||||
free(dump_mem_start);
|
||||
return 0;
|
||||
close(dump_fd);
|
||||
free(dump_mem_start);
|
||||
return 0;
|
||||
error_out:
|
||||
if (dump_fd != -1)
|
||||
close(dump_fd);
|
||||
free(dump_mem_start);
|
||||
return -1;
|
||||
if (dump_fd != -1)
|
||||
close(dump_fd);
|
||||
free(dump_mem_start);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
+12
-2
@@ -265,7 +265,7 @@ int xc_domain_memory_increase_reservation(int xc_handle,
|
||||
unsigned long nr_extents,
|
||||
unsigned int extent_order,
|
||||
unsigned int address_bits,
|
||||
unsigned long *extent_start)
|
||||
unsigned long *extent_start)
|
||||
{
|
||||
int err;
|
||||
struct xen_memory_reservation reservation = {
|
||||
@@ -296,7 +296,7 @@ int xc_domain_memory_decrease_reservation(int xc_handle,
|
||||
u32 domid,
|
||||
unsigned long nr_extents,
|
||||
unsigned int extent_order,
|
||||
unsigned long *extent_start)
|
||||
unsigned long *extent_start)
|
||||
{
|
||||
int err;
|
||||
struct xen_memory_reservation reservation = {
|
||||
@@ -328,3 +328,13 @@ int xc_domain_memory_decrease_reservation(int xc_handle,
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -9,8 +9,8 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
}
|
||||
|
||||
int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
|
||||
unsigned int store_evtchn, unsigned long *store_mfn,
|
||||
unsigned int console_evtchn, unsigned long *console_mfn)
|
||||
unsigned int store_evtchn, unsigned long *store_mfn,
|
||||
unsigned int console_evtchn, unsigned long *console_mfn)
|
||||
{
|
||||
PERROR("xc_linux_restore not implemented\n");
|
||||
return -1;
|
||||
@@ -44,3 +44,12 @@ xc_plan9_build(int xc_handle,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
+166
-168
@@ -13,7 +13,6 @@
|
||||
#define ELFSIZE 64
|
||||
#endif
|
||||
|
||||
|
||||
#include "xc_elf.h"
|
||||
#include "xc_aout9.h"
|
||||
#include <stdlib.h>
|
||||
@@ -33,6 +32,13 @@
|
||||
#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
|
||||
#endif
|
||||
|
||||
#ifdef __ia64__
|
||||
#define already_built(ctxt) (0)
|
||||
#define get_tot_pages xc_get_max_pages
|
||||
#else
|
||||
#define already_built(ctxt) ((ctxt)->ctrlreg[3] != 0)
|
||||
#define get_tot_pages xc_get_tot_pages
|
||||
#endif
|
||||
|
||||
#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
|
||||
#define round_pgdown(_p) ((_p)&PAGE_MASK)
|
||||
@@ -47,7 +53,7 @@ static int probeimageformat(char *image,
|
||||
{
|
||||
if ( probe_elf(image, image_size, load_funcs) &&
|
||||
probe_bin(image, image_size, load_funcs) &&
|
||||
probe_aout9(image, image_size, load_funcs) )
|
||||
probe_aout9(image, image_size, load_funcs) )
|
||||
{
|
||||
ERROR( "Unrecognized image format" );
|
||||
return -EINVAL;
|
||||
@@ -56,27 +62,27 @@ static int probeimageformat(char *image,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define alloc_pt(ltab, vltab) \
|
||||
ltab = (unsigned long long)(page_array[ppt_alloc++]) << PAGE_SHIFT; \
|
||||
if (vltab != NULL) { \
|
||||
munmap(vltab, PAGE_SIZE); \
|
||||
} \
|
||||
if ((vltab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, \
|
||||
PROT_READ|PROT_WRITE, \
|
||||
ltab >> PAGE_SHIFT)) == NULL) { \
|
||||
goto error_out; \
|
||||
} \
|
||||
memset(vltab, 0, PAGE_SIZE);
|
||||
#define alloc_pt(ltab, vltab) \
|
||||
do { \
|
||||
ltab = (u64)page_array[ppt_alloc++] << PAGE_SHIFT; \
|
||||
if ( vltab != NULL ) \
|
||||
munmap(vltab, PAGE_SIZE); \
|
||||
if ( (vltab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, \
|
||||
PROT_READ|PROT_WRITE, \
|
||||
ltab >> PAGE_SHIFT)) == NULL ) \
|
||||
goto error_out; \
|
||||
memset(vltab, 0, PAGE_SIZE); \
|
||||
} while ( 0 )
|
||||
|
||||
#if defined(__i386__)
|
||||
|
||||
static int setup_pg_tables(int xc_handle, u32 dom,
|
||||
vcpu_guest_context_t *ctxt,
|
||||
unsigned long dsi_v_start,
|
||||
unsigned long v_end,
|
||||
unsigned long *page_array,
|
||||
unsigned long vpt_start,
|
||||
unsigned long vpt_end)
|
||||
vcpu_guest_context_t *ctxt,
|
||||
unsigned long dsi_v_start,
|
||||
unsigned long v_end,
|
||||
unsigned long *page_array,
|
||||
unsigned long vpt_start,
|
||||
unsigned long vpt_end)
|
||||
{
|
||||
l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
|
||||
l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
|
||||
@@ -90,11 +96,11 @@ static int setup_pg_tables(int xc_handle, u32 dom,
|
||||
vl2e = &vl2tab[l2_table_offset(dsi_v_start)];
|
||||
ctxt->ctrlreg[3] = l2tab;
|
||||
|
||||
for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++ )
|
||||
for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++ )
|
||||
{
|
||||
if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
|
||||
{
|
||||
alloc_pt(l1tab, vl1tab);
|
||||
alloc_pt(l1tab, vl1tab);
|
||||
vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
|
||||
*vl2e++ = l1tab | L2_PROT;
|
||||
}
|
||||
@@ -111,79 +117,67 @@ static int setup_pg_tables(int xc_handle, u32 dom,
|
||||
|
||||
error_out:
|
||||
if (vl1tab)
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
if (vl2tab)
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int setup_pg_tables_pae(int xc_handle, u32 dom,
|
||||
vcpu_guest_context_t *ctxt,
|
||||
unsigned long dsi_v_start,
|
||||
unsigned long v_end,
|
||||
unsigned long *page_array,
|
||||
unsigned long vpt_start,
|
||||
unsigned long vpt_end)
|
||||
vcpu_guest_context_t *ctxt,
|
||||
unsigned long dsi_v_start,
|
||||
unsigned long v_end,
|
||||
unsigned long *page_array,
|
||||
unsigned long vpt_start,
|
||||
unsigned long vpt_end)
|
||||
{
|
||||
l1_pgentry_64_t *vl1tab=NULL, *vl1e=NULL;
|
||||
l2_pgentry_64_t *vl2tab=NULL, *vl2e=NULL;
|
||||
l3_pgentry_64_t *vl3tab=NULL, *vl3e=NULL;
|
||||
unsigned long long l1tab = 0;
|
||||
unsigned long long l2tab = 0;
|
||||
unsigned long long l3tab = 0;
|
||||
unsigned long ppt_alloc;
|
||||
unsigned long count;
|
||||
l1_pgentry_64_t *vl1tab = NULL, *vl1e = NULL;
|
||||
l2_pgentry_64_t *vl2tab = NULL, *vl2e = NULL;
|
||||
l3_pgentry_64_t *vl3tab = NULL, *vl3e = NULL;
|
||||
u64 l1tab, l2tab, l3tab;
|
||||
unsigned long ppt_alloc, count, nmfn;
|
||||
|
||||
/* First allocate page for page dir. */
|
||||
ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
|
||||
|
||||
if ( page_array[ppt_alloc] > 0xfffff )
|
||||
{
|
||||
unsigned long nmfn;
|
||||
nmfn = xc_make_page_below_4G( xc_handle, dom, page_array[ppt_alloc] );
|
||||
if ( nmfn == 0 )
|
||||
{
|
||||
fprintf(stderr, "Couldn't get a page below 4GB :-(\n");
|
||||
goto error_out;
|
||||
}
|
||||
page_array[ppt_alloc] = nmfn;
|
||||
nmfn = xc_make_page_below_4G(xc_handle, dom, page_array[ppt_alloc]);
|
||||
if ( nmfn == 0 )
|
||||
{
|
||||
fprintf(stderr, "Couldn't get a page below 4GB :-(\n");
|
||||
goto error_out;
|
||||
}
|
||||
page_array[ppt_alloc] = nmfn;
|
||||
}
|
||||
|
||||
alloc_pt(l3tab, vl3tab);
|
||||
vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)];
|
||||
ctxt->ctrlreg[3] = l3tab;
|
||||
|
||||
if(l3tab>0xfffff000ULL)
|
||||
{
|
||||
fprintf(stderr,"L3TAB = %llx above 4GB!\n",l3tab);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++)
|
||||
for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++)
|
||||
{
|
||||
if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
|
||||
{
|
||||
if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
|
||||
{
|
||||
alloc_pt(l2tab, vl2tab);
|
||||
vl2e = &vl2tab[l2_table_offset_pae(
|
||||
dsi_v_start + (count << PAGE_SHIFT))];
|
||||
*vl3e++ = l2tab | L3_PROT;
|
||||
}
|
||||
|
||||
alloc_pt(l1tab, vl1tab);
|
||||
|
||||
if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
|
||||
{
|
||||
alloc_pt(l2tab, vl2tab);
|
||||
vl2e = &vl2tab[l2_table_offset_pae(dsi_v_start + (count<<PAGE_SHIFT))];
|
||||
*vl3e = l2tab | L3_PROT;
|
||||
vl3e++;
|
||||
}
|
||||
vl1e = &vl1tab[l1_table_offset_pae(dsi_v_start + (count<<PAGE_SHIFT))];
|
||||
*vl2e = l1tab | L2_PROT;
|
||||
vl2e++;
|
||||
vl1e = &vl1tab[l1_table_offset_pae(
|
||||
dsi_v_start + (count << PAGE_SHIFT))];
|
||||
*vl2e++ = l1tab | L2_PROT;
|
||||
}
|
||||
|
||||
*vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
|
||||
*vl1e = ((u64)page_array[count] << PAGE_SHIFT) | L1_PROT;
|
||||
if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
|
||||
(count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
|
||||
{
|
||||
*vl1e &= ~_PAGE_RW;
|
||||
}
|
||||
vl1e++;
|
||||
(count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
|
||||
*vl1e &= ~_PAGE_RW;
|
||||
vl1e++;
|
||||
}
|
||||
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
@@ -193,11 +187,11 @@ static int setup_pg_tables_pae(int xc_handle, u32 dom,
|
||||
|
||||
error_out:
|
||||
if (vl1tab)
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
if (vl2tab)
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
if (vl3tab)
|
||||
munmap(vl3tab, PAGE_SIZE);
|
||||
munmap(vl3tab, PAGE_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -206,12 +200,12 @@ static int setup_pg_tables_pae(int xc_handle, u32 dom,
|
||||
#if defined(__x86_64__)
|
||||
|
||||
static int setup_pg_tables_64(int xc_handle, u32 dom,
|
||||
vcpu_guest_context_t *ctxt,
|
||||
unsigned long dsi_v_start,
|
||||
unsigned long v_end,
|
||||
unsigned long *page_array,
|
||||
unsigned long vpt_start,
|
||||
unsigned long vpt_end)
|
||||
vcpu_guest_context_t *ctxt,
|
||||
unsigned long dsi_v_start,
|
||||
unsigned long v_end,
|
||||
unsigned long *page_array,
|
||||
unsigned long vpt_start,
|
||||
unsigned long vpt_end)
|
||||
{
|
||||
l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
|
||||
l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
|
||||
@@ -236,20 +230,20 @@ static int setup_pg_tables_64(int xc_handle, u32 dom,
|
||||
{
|
||||
alloc_pt(l1tab, vl1tab);
|
||||
|
||||
if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
|
||||
if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
|
||||
{
|
||||
alloc_pt(l2tab, vl2tab);
|
||||
if ( !((unsigned long)vl3e & (PAGE_SIZE-1)) )
|
||||
{
|
||||
alloc_pt(l2tab, vl2tab);
|
||||
if ( !((unsigned long)vl3e & (PAGE_SIZE-1)) )
|
||||
{
|
||||
alloc_pt(l3tab, vl3tab);
|
||||
vl3e = &vl3tab[l3_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
|
||||
*vl4e = l3tab | L4_PROT;
|
||||
vl4e++;
|
||||
}
|
||||
vl2e = &vl2tab[l2_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
|
||||
*vl3e = l2tab | L3_PROT;
|
||||
vl3e++;
|
||||
alloc_pt(l3tab, vl3tab);
|
||||
vl3e = &vl3tab[l3_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
|
||||
*vl4e = l3tab | L4_PROT;
|
||||
vl4e++;
|
||||
}
|
||||
vl2e = &vl2tab[l2_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
|
||||
*vl3e = l2tab | L3_PROT;
|
||||
vl3e++;
|
||||
}
|
||||
vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
|
||||
*vl2e = l1tab | L2_PROT;
|
||||
vl2e++;
|
||||
@@ -257,11 +251,11 @@ static int setup_pg_tables_64(int xc_handle, u32 dom,
|
||||
|
||||
*vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
|
||||
if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
|
||||
(count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
|
||||
(count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
|
||||
{
|
||||
*vl1e &= ~_PAGE_RW;
|
||||
*vl1e &= ~_PAGE_RW;
|
||||
}
|
||||
vl1e++;
|
||||
vl1e++;
|
||||
}
|
||||
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
@@ -272,13 +266,13 @@ static int setup_pg_tables_64(int xc_handle, u32 dom,
|
||||
|
||||
error_out:
|
||||
if (vl1tab)
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
if (vl2tab)
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
if (vl3tab)
|
||||
munmap(vl3tab, PAGE_SIZE);
|
||||
munmap(vl3tab, PAGE_SIZE);
|
||||
if (vl4tab)
|
||||
munmap(vl4tab, PAGE_SIZE);
|
||||
munmap(vl4tab, PAGE_SIZE);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -286,18 +280,18 @@ static int setup_pg_tables_64(int xc_handle, u32 dom,
|
||||
#ifdef __ia64__
|
||||
#include <asm/fpu.h> /* for FPSR_DEFAULT */
|
||||
static int setup_guest(int xc_handle,
|
||||
u32 dom,
|
||||
char *image, unsigned long image_size,
|
||||
gzFile initrd_gfd, unsigned long initrd_len,
|
||||
unsigned long nr_pages,
|
||||
unsigned long *pvsi, unsigned long *pvke,
|
||||
unsigned long *pvss, vcpu_guest_context_t *ctxt,
|
||||
const char *cmdline,
|
||||
unsigned long shared_info_frame,
|
||||
unsigned long flags,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn, unsigned long *store_mfn,
|
||||
unsigned int console_evtchn, unsigned long *console_mfn)
|
||||
u32 dom,
|
||||
char *image, unsigned long image_size,
|
||||
gzFile initrd_gfd, unsigned long initrd_len,
|
||||
unsigned long nr_pages,
|
||||
unsigned long *pvsi, unsigned long *pvke,
|
||||
unsigned long *pvss, vcpu_guest_context_t *ctxt,
|
||||
const char *cmdline,
|
||||
unsigned long shared_info_frame,
|
||||
unsigned long flags,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn, unsigned long *store_mfn,
|
||||
unsigned int console_evtchn, unsigned long *console_mfn)
|
||||
{
|
||||
unsigned long *page_array = NULL;
|
||||
struct load_funcs load_funcs;
|
||||
@@ -339,19 +333,20 @@ static int setup_guest(int xc_handle,
|
||||
*pvke = dsi.v_kernentry;
|
||||
|
||||
/* Now need to retrieve machine pfn for system pages:
|
||||
* start_info/store/console
|
||||
* start_info/store/console
|
||||
*/
|
||||
pgnr = 3;
|
||||
if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array, nr_pages - 3, pgnr) != pgnr)
|
||||
if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array,
|
||||
nr_pages - 3, pgnr) != pgnr )
|
||||
{
|
||||
PERROR("Could not get page frame for xenstore");
|
||||
goto error_out;
|
||||
PERROR("Could not get page frame for xenstore");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
*store_mfn = page_array[1];
|
||||
*console_mfn = page_array[2];
|
||||
printf("store_mfn: 0x%lx, console_mfn: 0x%lx\n",
|
||||
(u64)store_mfn, (u64)console_mfn);
|
||||
(u64)store_mfn, (u64)console_mfn);
|
||||
|
||||
start_info = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, page_array[0]);
|
||||
@@ -382,8 +377,8 @@ static int setup_guest(int xc_handle,
|
||||
unsigned long shared_info_frame,
|
||||
unsigned long flags,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn, unsigned long *store_mfn,
|
||||
unsigned int console_evtchn, unsigned long *console_mfn)
|
||||
unsigned int store_evtchn, unsigned long *store_mfn,
|
||||
unsigned int console_evtchn, unsigned long *console_mfn)
|
||||
{
|
||||
unsigned long *page_array = NULL;
|
||||
unsigned long count, i;
|
||||
@@ -458,26 +453,26 @@ static int setup_guest(int xc_handle,
|
||||
if ( (v_end - vstack_end) < (512UL << 10) )
|
||||
v_end += 1UL << 22; /* Add extra 4MB to get >= 512kB padding. */
|
||||
#if defined(__i386__)
|
||||
if (dsi.pae_kernel) {
|
||||
/* FIXME: assumes one L2 pgtable @ 0xc0000000 */
|
||||
if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT_PAE)-1)) >>
|
||||
L2_PAGETABLE_SHIFT_PAE) + 2) <= nr_pt_pages )
|
||||
break;
|
||||
} else {
|
||||
if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >>
|
||||
L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
|
||||
break;
|
||||
}
|
||||
if (dsi.pae_kernel) {
|
||||
/* FIXME: assumes one L2 pgtable @ 0xc0000000 */
|
||||
if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT_PAE)-1)) >>
|
||||
L2_PAGETABLE_SHIFT_PAE) + 2) <= nr_pt_pages )
|
||||
break;
|
||||
} else {
|
||||
if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >>
|
||||
L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(__x86_64__)
|
||||
#define NR(_l,_h,_s) \
|
||||
(((((_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \
|
||||
((_l) & ~((1UL<<(_s))-1))) >> (_s))
|
||||
if ( (1 + /* # L4 */
|
||||
NR(dsi.v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */
|
||||
NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) + /* # L2 */
|
||||
NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */
|
||||
<= nr_pt_pages )
|
||||
if ( (1 + /* # L4 */
|
||||
NR(dsi.v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */
|
||||
NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) + /* # L2 */
|
||||
NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */
|
||||
<= nr_pt_pages )
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@@ -541,7 +536,7 @@ static int setup_guest(int xc_handle,
|
||||
goto error_out;
|
||||
}
|
||||
xc_copy_to_domain_page(xc_handle, dom,
|
||||
page_array[i>>PAGE_SHIFT], page);
|
||||
page_array[i>>PAGE_SHIFT], page);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,22 +546,22 @@ static int setup_guest(int xc_handle,
|
||||
/* setup page tables */
|
||||
#if defined(__i386__)
|
||||
if (dsi.pae_kernel)
|
||||
rc = setup_pg_tables_pae(xc_handle, dom, ctxt,
|
||||
dsi.v_start, v_end,
|
||||
page_array, vpt_start, vpt_end);
|
||||
rc = setup_pg_tables_pae(xc_handle, dom, ctxt,
|
||||
dsi.v_start, v_end,
|
||||
page_array, vpt_start, vpt_end);
|
||||
else {
|
||||
rc = setup_pg_tables(xc_handle, dom, ctxt,
|
||||
dsi.v_start, v_end,
|
||||
page_array, vpt_start, vpt_end);
|
||||
rc = setup_pg_tables(xc_handle, dom, ctxt,
|
||||
dsi.v_start, v_end,
|
||||
page_array, vpt_start, vpt_end);
|
||||
}
|
||||
#endif
|
||||
#if defined(__x86_64__)
|
||||
rc = setup_pg_tables_64(xc_handle, dom, ctxt,
|
||||
dsi.v_start, v_end,
|
||||
page_array, vpt_start, vpt_end);
|
||||
dsi.v_start, v_end,
|
||||
page_array, vpt_start, vpt_end);
|
||||
#endif
|
||||
if (0 != rc)
|
||||
goto error_out;
|
||||
goto error_out;
|
||||
|
||||
/* Write the phys->machine and machine->phys table entries. */
|
||||
physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT;
|
||||
@@ -576,11 +571,13 @@ static int setup_guest(int xc_handle,
|
||||
|
||||
for ( count = 0; count < nr_pages; count++ )
|
||||
{
|
||||
if ( xc_add_mmu_update(xc_handle, mmu,
|
||||
((unsigned long long)page_array[count] << PAGE_SHIFT) |
|
||||
MMU_MACHPHYS_UPDATE, count) )
|
||||
if ( xc_add_mmu_update(
|
||||
xc_handle, mmu,
|
||||
((u64)page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE,
|
||||
count) )
|
||||
{
|
||||
fprintf(stderr,"m2p update failure p=%lx m=%lx\n",count,page_array[count] );
|
||||
fprintf(stderr,"m2p update failure p=%lx m=%lx\n",
|
||||
count, page_array[count]);
|
||||
munmap(physmap, PAGE_SIZE);
|
||||
goto error_out;
|
||||
}
|
||||
@@ -601,13 +598,13 @@ static int setup_guest(int xc_handle,
|
||||
* correct protection for the page
|
||||
*/
|
||||
if (dsi.pae_kernel) {
|
||||
if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE,
|
||||
ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
|
||||
goto error_out;
|
||||
if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE,
|
||||
ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
|
||||
goto error_out;
|
||||
} else {
|
||||
if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE,
|
||||
ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
|
||||
goto error_out;
|
||||
if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE,
|
||||
ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
|
||||
goto error_out;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -616,8 +613,8 @@ static int setup_guest(int xc_handle,
|
||||
* Pin down l4tab addr as page dir page - causes hypervisor to provide
|
||||
* correct protection for the page
|
||||
*/
|
||||
if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE,
|
||||
ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
|
||||
if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE,
|
||||
ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
|
||||
goto error_out;
|
||||
#endif
|
||||
|
||||
@@ -703,12 +700,7 @@ int xc_linux_build(int xc_handle,
|
||||
unsigned long image_size, initrd_size=0;
|
||||
unsigned long vstartinfo_start, vkern_entry, vstack_start;
|
||||
|
||||
#ifdef __ia64__
|
||||
/* Current xen/ia64 allocates domU pages on demand */
|
||||
if ( (nr_pages = xc_get_max_pages(xc_handle, domid)) < 0 )
|
||||
#else
|
||||
if ( (nr_pages = xc_get_tot_pages(xc_handle, domid)) < 0 )
|
||||
#endif
|
||||
if ( (nr_pages = get_tot_pages(xc_handle, domid)) < 0 )
|
||||
{
|
||||
PERROR("Could not find total pages for domain");
|
||||
goto error_out;
|
||||
@@ -755,12 +747,7 @@ int xc_linux_build(int xc_handle,
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ||
|
||||
#ifdef __ia64__
|
||||
0 )
|
||||
#else
|
||||
(ctxt->ctrlreg[3] != 0) )
|
||||
#endif
|
||||
if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) || already_built(ctxt) )
|
||||
{
|
||||
ERROR("Domain is already constructed");
|
||||
goto error_out;
|
||||
@@ -773,7 +760,7 @@ int xc_linux_build(int xc_handle,
|
||||
op.u.getdomaininfo.shared_info_frame,
|
||||
flags, vcpus,
|
||||
store_evtchn, store_mfn,
|
||||
console_evtchn, console_mfn) < 0 )
|
||||
console_evtchn, console_mfn) < 0 )
|
||||
{
|
||||
ERROR("Error constructing guest OS");
|
||||
goto error_out;
|
||||
@@ -789,12 +776,13 @@ int xc_linux_build(int xc_handle,
|
||||
/* based on new_thread in xen/arch/ia64/domain.c */
|
||||
ctxt->flags = 0;
|
||||
ctxt->shared.flags = flags;
|
||||
ctxt->shared.start_info_pfn = nr_pages - 3; // metaphysical
|
||||
ctxt->shared.start_info_pfn = nr_pages - 3; /* metaphysical */
|
||||
ctxt->regs.cr_ipsr = 0; /* all necessary bits filled by hypervisor */
|
||||
ctxt->regs.cr_iip = vkern_entry;
|
||||
ctxt->regs.cr_ifs = 1UL << 63;
|
||||
ctxt->regs.ar_fpsr = FPSR_DEFAULT;
|
||||
/* ctxt->regs.r28 = dom_fw_setup(); currently done by hypervisor, should move here */
|
||||
/* currently done by hypervisor, should move here */
|
||||
/* ctxt->regs.r28 = dom_fw_setup(); */
|
||||
ctxt->vcpu.privregs = 0;
|
||||
ctxt->sys_pgnr = nr_pages - 3;
|
||||
i = 0; /* silence unused variable warning */
|
||||
@@ -875,3 +863,13 @@ int xc_linux_build(int xc_handle,
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
+267
-217
@@ -18,7 +18,6 @@
|
||||
|
||||
#define MAX_MBIT_RATE 500
|
||||
|
||||
|
||||
/*
|
||||
** Default values for important tuning parameters. Can override by passing
|
||||
** non-zero replacement values to xc_linux_save().
|
||||
@@ -29,13 +28,10 @@
|
||||
#define DEF_MAX_ITERS 29 /* limit us to 30 times round loop */
|
||||
#define DEF_MAX_FACTOR 3 /* never send more than 3x nr_pfns */
|
||||
|
||||
|
||||
|
||||
/* Flags to control behaviour of xc_linux_save */
|
||||
#define XCFLAGS_LIVE 1
|
||||
#define XCFLAGS_DEBUG 2
|
||||
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
#if 1
|
||||
@@ -115,8 +111,8 @@ static inline int count_bits ( int nr, volatile void *addr)
|
||||
int i, count = 0;
|
||||
unsigned long *p = (unsigned long *)addr;
|
||||
/* We know that the array is padded to unsigned long. */
|
||||
for(i=0;i<nr/(sizeof(unsigned long)*8);i++,p++)
|
||||
count += hweight32( *p );
|
||||
for( i = 0; i < (nr / (sizeof(unsigned long)*8)); i++, p++ )
|
||||
count += hweight32(*p);
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -201,42 +197,50 @@ ratewrite(int io_fd, void *buf, int n)
|
||||
struct timespec delay;
|
||||
long long delta;
|
||||
|
||||
if (START_MBIT_RATE == 0)
|
||||
return write(io_fd, buf, n);
|
||||
if ( START_MBIT_RATE == 0 )
|
||||
return write(io_fd, buf, n);
|
||||
|
||||
budget -= n;
|
||||
if (budget < 0) {
|
||||
if (MBIT_RATE != ombit_rate) {
|
||||
BURST_TIME_US = RATE_TO_BTU / MBIT_RATE;
|
||||
ombit_rate = MBIT_RATE;
|
||||
DPRINTF("rate limit: %d mbit/s burst budget %d slot time %d\n",
|
||||
MBIT_RATE, BURST_BUDGET, BURST_TIME_US);
|
||||
}
|
||||
if (last_put.tv_sec == 0) {
|
||||
budget += BURST_BUDGET;
|
||||
gettimeofday(&last_put, NULL);
|
||||
} else {
|
||||
while (budget < 0) {
|
||||
gettimeofday(&now, NULL);
|
||||
delta = tv_delta(&now, &last_put);
|
||||
while (delta > BURST_TIME_US) {
|
||||
budget += BURST_BUDGET;
|
||||
last_put.tv_usec += BURST_TIME_US;
|
||||
if (last_put.tv_usec > 1000000) {
|
||||
last_put.tv_usec -= 1000000;
|
||||
last_put.tv_sec++;
|
||||
}
|
||||
delta -= BURST_TIME_US;
|
||||
}
|
||||
if (budget > 0)
|
||||
break;
|
||||
delay.tv_sec = 0;
|
||||
delay.tv_nsec = 1000 * (BURST_TIME_US - delta);
|
||||
while (delay.tv_nsec > 0)
|
||||
if (nanosleep(&delay, &delay) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( budget < 0 )
|
||||
{
|
||||
if ( MBIT_RATE != ombit_rate )
|
||||
{
|
||||
BURST_TIME_US = RATE_TO_BTU / MBIT_RATE;
|
||||
ombit_rate = MBIT_RATE;
|
||||
DPRINTF("rate limit: %d mbit/s burst budget %d slot time %d\n",
|
||||
MBIT_RATE, BURST_BUDGET, BURST_TIME_US);
|
||||
}
|
||||
if ( last_put.tv_sec == 0 )
|
||||
{
|
||||
budget += BURST_BUDGET;
|
||||
gettimeofday(&last_put, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ( budget < 0 )
|
||||
{
|
||||
gettimeofday(&now, NULL);
|
||||
delta = tv_delta(&now, &last_put);
|
||||
while ( delta > BURST_TIME_US )
|
||||
{
|
||||
budget += BURST_BUDGET;
|
||||
last_put.tv_usec += BURST_TIME_US;
|
||||
if ( last_put.tv_usec > 1000000 )
|
||||
{
|
||||
last_put.tv_usec -= 1000000;
|
||||
last_put.tv_sec++;
|
||||
}
|
||||
delta -= BURST_TIME_US;
|
||||
}
|
||||
if ( budget > 0 )
|
||||
break;
|
||||
delay.tv_sec = 0;
|
||||
delay.tv_nsec = 1000 * (BURST_TIME_US - delta);
|
||||
while ( delay.tv_nsec > 0 )
|
||||
if ( nanosleep(&delay, &delay) == 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return write(io_fd, buf, n);
|
||||
}
|
||||
@@ -271,20 +275,21 @@ static int print_stats( int xc_handle, u32 domid,
|
||||
|
||||
if ( print )
|
||||
fprintf(stderr,
|
||||
"delta %lldms, dom0 %d%%, target %d%%, sent %dMb/s, "
|
||||
"dirtied %dMb/s %" PRId32 " pages\n",
|
||||
wall_delta,
|
||||
(int)((d0_cpu_delta*100)/wall_delta),
|
||||
(int)((d1_cpu_delta*100)/wall_delta),
|
||||
(int)((pages_sent*PAGE_SIZE)/(wall_delta*(1000/8))),
|
||||
(int)((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8))),
|
||||
stats->dirty_count);
|
||||
"delta %lldms, dom0 %d%%, target %d%%, sent %dMb/s, "
|
||||
"dirtied %dMb/s %" PRId32 " pages\n",
|
||||
wall_delta,
|
||||
(int)((d0_cpu_delta*100)/wall_delta),
|
||||
(int)((d1_cpu_delta*100)/wall_delta),
|
||||
(int)((pages_sent*PAGE_SIZE)/(wall_delta*(1000/8))),
|
||||
(int)((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8))),
|
||||
stats->dirty_count);
|
||||
|
||||
if (((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8))) > mbit_rate) {
|
||||
mbit_rate = (int)((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8)))
|
||||
+ 50;
|
||||
if (mbit_rate > MAX_MBIT_RATE)
|
||||
mbit_rate = MAX_MBIT_RATE;
|
||||
if ( ((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8))) > mbit_rate )
|
||||
{
|
||||
mbit_rate = (int)((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8)))
|
||||
+ 50;
|
||||
if (mbit_rate > MAX_MBIT_RATE)
|
||||
mbit_rate = MAX_MBIT_RATE;
|
||||
}
|
||||
|
||||
d0_cpu_last = d0_cpu_now;
|
||||
@@ -303,7 +308,7 @@ static int analysis_phase( int xc_handle, u32 domid,
|
||||
|
||||
start = llgettimeofday();
|
||||
|
||||
for (j = 0; j < runs; j++)
|
||||
for ( j = 0; j < runs; j++ )
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -320,10 +325,10 @@ static int analysis_phase( int xc_handle, u32 domid,
|
||||
NULL, 0, &stats);
|
||||
|
||||
fprintf(stderr, "now= %lld faults= %" PRId32 " dirty= %" PRId32
|
||||
" dirty_net= %" PRId32 " dirty_block= %" PRId32"\n",
|
||||
((now-start)+500)/1000,
|
||||
stats.fault_count, stats.dirty_count,
|
||||
stats.dirty_net_count, stats.dirty_block_count);
|
||||
" dirty_net= %" PRId32 " dirty_block= %" PRId32"\n",
|
||||
((now-start)+500)/1000,
|
||||
stats.fault_count, stats.dirty_count,
|
||||
stats.dirty_net_count, stats.dirty_block_count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,7 +336,7 @@ static int analysis_phase( int xc_handle, u32 domid,
|
||||
}
|
||||
|
||||
|
||||
static int suspend_and_state(int xc_handle, int io_fd, int dom,
|
||||
static int suspend_and_state(int xc_handle, int io_fd, int dom,
|
||||
xc_dominfo_t *info,
|
||||
vcpu_guest_context_t *ctxt)
|
||||
{
|
||||
@@ -340,51 +345,53 @@ static int suspend_and_state(int xc_handle, int io_fd, int dom,
|
||||
|
||||
printf("suspend\n");
|
||||
fflush(stdout);
|
||||
if (fgets(ans, sizeof(ans), stdin) == NULL) {
|
||||
if ( fgets(ans, sizeof(ans), stdin) == NULL )
|
||||
{
|
||||
ERR("failed reading suspend reply");
|
||||
return -1;
|
||||
}
|
||||
if (strncmp(ans, "done\n", 5)) {
|
||||
if ( strncmp(ans, "done\n", 5) )
|
||||
{
|
||||
ERR("suspend reply incorrect: %s", ans);
|
||||
return -1;
|
||||
}
|
||||
|
||||
retry:
|
||||
retry:
|
||||
|
||||
if ( xc_domain_getinfo(xc_handle, dom, 1, info) != 1)
|
||||
{
|
||||
ERR("Could not get domain info");
|
||||
return -1;
|
||||
ERR("Could not get domain info");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( xc_domain_get_vcpu_context(xc_handle, dom, 0 /* XXX */,
|
||||
ctxt) )
|
||||
ctxt) )
|
||||
{
|
||||
ERR("Could not get vcpu context");
|
||||
}
|
||||
|
||||
if ( info->shutdown && info->shutdown_reason == SHUTDOWN_suspend )
|
||||
{
|
||||
return 0; // success
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
if ( info->paused )
|
||||
{
|
||||
// try unpausing domain, wait, and retest
|
||||
xc_domain_unpause( xc_handle, dom );
|
||||
// try unpausing domain, wait, and retest
|
||||
xc_domain_unpause( xc_handle, dom );
|
||||
|
||||
ERR("Domain was paused. Wait and re-test.");
|
||||
usleep(10000); // 10ms
|
||||
ERR("Domain was paused. Wait and re-test.");
|
||||
usleep(10000); // 10ms
|
||||
|
||||
goto retry;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
|
||||
if( ++i < 100 )
|
||||
{
|
||||
ERR("Retry suspend domain.");
|
||||
usleep(10000); // 10ms
|
||||
goto retry;
|
||||
ERR("Retry suspend domain.");
|
||||
usleep(10000); // 10ms
|
||||
goto retry;
|
||||
}
|
||||
|
||||
ERR("Unable to suspend domain.");
|
||||
@@ -454,26 +461,26 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
|
||||
|
||||
/* If no explicit control parameters given, use defaults */
|
||||
if(!max_iters)
|
||||
if( !max_iters )
|
||||
max_iters = DEF_MAX_ITERS;
|
||||
if(!max_factor)
|
||||
if( !max_factor )
|
||||
max_factor = DEF_MAX_FACTOR;
|
||||
|
||||
|
||||
DPRINTF("xc_linux_save start DOM%u live=%s\n", dom, live?"true":"false");
|
||||
|
||||
if (mlock(&ctxt, sizeof(ctxt))) {
|
||||
if ( mlock(&ctxt, sizeof(ctxt)) )
|
||||
{
|
||||
ERR("Unable to mlock ctxt");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( xc_domain_getinfo(xc_handle, dom, 1, &info) != 1)
|
||||
if ( xc_domain_getinfo(xc_handle, dom, 1, &info) != 1 )
|
||||
{
|
||||
ERR("Could not get domain info");
|
||||
goto out;
|
||||
}
|
||||
if ( xc_domain_get_vcpu_context( xc_handle, dom, /* FIXME */ 0,
|
||||
&ctxt) )
|
||||
if ( xc_domain_get_vcpu_context(xc_handle, dom, /* FIXME */ 0, &ctxt) )
|
||||
{
|
||||
ERR("Could not get vcpu context");
|
||||
goto out;
|
||||
@@ -481,7 +488,8 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
shared_info_frame = info.shared_info_frame;
|
||||
|
||||
/* A cheesy test to see whether the domain contains valid state. */
|
||||
if ( ctxt.ctrlreg[3] == 0 ){
|
||||
if ( ctxt.ctrlreg[3] == 0 )
|
||||
{
|
||||
ERR("Domain is not in a valid Linux guest OS state");
|
||||
goto out;
|
||||
}
|
||||
@@ -496,18 +504,17 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
}
|
||||
|
||||
/* Map the shared info frame */
|
||||
live_shinfo = xc_map_foreign_range(xc_handle, dom,
|
||||
PAGE_SIZE, PROT_READ,
|
||||
shared_info_frame);
|
||||
|
||||
if (!live_shinfo){
|
||||
live_shinfo = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ, shared_info_frame);
|
||||
if ( !live_shinfo )
|
||||
{
|
||||
ERR("Couldn't map live_shinfo");
|
||||
goto out;
|
||||
}
|
||||
|
||||
live_pfn_to_mfn_frame_list_list = xc_map_foreign_range(xc_handle, dom,
|
||||
PAGE_SIZE, PROT_READ,
|
||||
live_shinfo->arch.pfn_to_mfn_frame_list_list);
|
||||
live_pfn_to_mfn_frame_list_list = xc_map_foreign_range(
|
||||
xc_handle, dom,
|
||||
PAGE_SIZE, PROT_READ, live_shinfo->arch.pfn_to_mfn_frame_list_list);
|
||||
|
||||
if (!live_pfn_to_mfn_frame_list_list){
|
||||
ERR("Couldn't map pfn_to_mfn_frame_list_list");
|
||||
@@ -515,12 +522,13 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
}
|
||||
|
||||
live_pfn_to_mfn_frame_list =
|
||||
xc_map_foreign_batch(xc_handle, dom,
|
||||
PROT_READ,
|
||||
live_pfn_to_mfn_frame_list_list,
|
||||
(nr_pfns+(1024*1024)-1)/(1024*1024) );
|
||||
xc_map_foreign_batch(xc_handle, dom,
|
||||
PROT_READ,
|
||||
live_pfn_to_mfn_frame_list_list,
|
||||
(nr_pfns+(1024*1024)-1)/(1024*1024) );
|
||||
|
||||
if (!live_pfn_to_mfn_frame_list){
|
||||
if ( !live_pfn_to_mfn_frame_list)
|
||||
{
|
||||
ERR("Couldn't map pfn_to_mfn_frame_list");
|
||||
goto out;
|
||||
}
|
||||
@@ -535,7 +543,8 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
PROT_READ,
|
||||
live_pfn_to_mfn_frame_list,
|
||||
(nr_pfns+1023)/1024 );
|
||||
if( !live_pfn_to_mfn_table ){
|
||||
if ( !live_pfn_to_mfn_table )
|
||||
{
|
||||
ERR("Couldn't map pfn_to_mfn table");
|
||||
goto out;
|
||||
}
|
||||
@@ -544,15 +553,17 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
mfn_to_pfn_table_start_mfn = xc_get_m2p_start_mfn( xc_handle );
|
||||
|
||||
live_mfn_to_pfn_table =
|
||||
xc_map_foreign_range(xc_handle, DOMID_XEN,
|
||||
PAGE_SIZE*1024, PROT_READ,
|
||||
mfn_to_pfn_table_start_mfn );
|
||||
xc_map_foreign_range(xc_handle, DOMID_XEN,
|
||||
PAGE_SIZE*1024, PROT_READ,
|
||||
mfn_to_pfn_table_start_mfn );
|
||||
|
||||
/* 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 < nr_pfns; i += 1024 ){
|
||||
if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ){
|
||||
for ( i = 0; i < nr_pfns; i += 1024 )
|
||||
{
|
||||
if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
|
||||
{
|
||||
ERR("Frame# in pfn-to-mfn frame list is not in pseudophys");
|
||||
goto out;
|
||||
}
|
||||
@@ -561,40 +572,44 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
|
||||
/* Domain is still running at this point */
|
||||
|
||||
if( live )
|
||||
if ( live )
|
||||
{
|
||||
if ( xc_shadow_control( xc_handle, dom,
|
||||
DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY,
|
||||
NULL, 0, NULL ) < 0 ) {
|
||||
NULL, 0, NULL ) < 0 )
|
||||
{
|
||||
ERR("Couldn't enable shadow mode");
|
||||
goto out;
|
||||
}
|
||||
|
||||
last_iter = 0;
|
||||
} else{
|
||||
/* This is a non-live suspend. Issue the call back to get the
|
||||
domain suspended */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a non-live suspend. Issue the call back to get the
|
||||
domain suspended */
|
||||
|
||||
last_iter = 1;
|
||||
|
||||
if ( suspend_and_state( xc_handle, io_fd, dom, &info, &ctxt) )
|
||||
{
|
||||
ERR("Domain appears not to have suspended");
|
||||
goto out;
|
||||
}
|
||||
if ( suspend_and_state( xc_handle, io_fd, dom, &info, &ctxt) )
|
||||
{
|
||||
ERR("Domain appears not to have suspended");
|
||||
goto out;
|
||||
}
|
||||
|
||||
}
|
||||
sent_last_iter = 1<<20; /* 4GB of pages */
|
||||
|
||||
/* calculate the power of 2 order of nr_pfns, e.g.
|
||||
15->4 16->4 17->5 */
|
||||
for( i=nr_pfns-1, order_nr=0; i ; i>>=1, order_nr++ );
|
||||
for ( i = nr_pfns-1, order_nr = 0; i ; i >>= 1, order_nr++ )
|
||||
continue;
|
||||
|
||||
/* Setup to_send bitmap */
|
||||
{
|
||||
/* size these for a maximal 4GB domain, to make interaction
|
||||
with balloon driver easier. It's only user space memory,
|
||||
ater all... (3x 128KB) */
|
||||
/* size these for a maximal 4GB domain, to make interaction
|
||||
with balloon driver easier. It's only user space memory,
|
||||
ater all... (3x 128KB) */
|
||||
|
||||
int sz = ( 1<<20 ) / 8;
|
||||
|
||||
@@ -602,21 +617,24 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
to_fix = calloc( 1, sz );
|
||||
to_skip = malloc( sz );
|
||||
|
||||
if (!to_send || !to_fix || !to_skip){
|
||||
if ( !to_send || !to_fix || !to_skip )
|
||||
{
|
||||
ERR("Couldn't allocate to_send array");
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset( to_send, 0xff, sz );
|
||||
memset(to_send, 0xff, sz);
|
||||
|
||||
if ( mlock( to_send, sz ) ){
|
||||
if ( mlock(to_send, sz) )
|
||||
{
|
||||
ERR("Unable to mlock to_send");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* (to fix is local only) */
|
||||
|
||||
if ( mlock( to_skip, sz ) ){
|
||||
if ( mlock(to_skip, sz) )
|
||||
{
|
||||
ERR("Unable to mlock to_skip");
|
||||
return 1;
|
||||
}
|
||||
@@ -629,12 +647,14 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
pfn_type = calloc(BATCH_SIZE, sizeof(unsigned long));
|
||||
pfn_batch = calloc(BATCH_SIZE, sizeof(unsigned long));
|
||||
|
||||
if ( (pfn_type == NULL) || (pfn_batch == NULL) ){
|
||||
if ( (pfn_type == NULL) || (pfn_batch == NULL) )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) ){
|
||||
if ( mlock(pfn_type, BATCH_SIZE * sizeof(unsigned long)) )
|
||||
{
|
||||
ERR("Unable to mlock");
|
||||
goto out;
|
||||
}
|
||||
@@ -645,31 +665,34 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
*/
|
||||
#if DEBUG
|
||||
{
|
||||
int err=0;
|
||||
for ( i = 0; i < nr_pfns; i++ )
|
||||
{
|
||||
mfn = live_pfn_to_mfn_table[i];
|
||||
|
||||
if( (live_mfn_to_pfn_table[mfn] != i) && (mfn != 0xffffffffUL) )
|
||||
{
|
||||
fprintf(stderr, "i=0x%x mfn=%lx live_mfn_to_pfn_table=%lx\n",
|
||||
i,mfn,live_mfn_to_pfn_table[mfn]);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Had %d unexplained entries in p2m table\n",err);
|
||||
int err=0;
|
||||
for ( i = 0; i < nr_pfns; i++ )
|
||||
{
|
||||
mfn = live_pfn_to_mfn_table[i];
|
||||
|
||||
if( (live_mfn_to_pfn_table[mfn] != i) && (mfn != 0xffffffffUL) )
|
||||
{
|
||||
fprintf(stderr, "i=0x%x mfn=%lx live_mfn_to_pfn_table=%lx\n",
|
||||
i,mfn,live_mfn_to_pfn_table[mfn]);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Had %d unexplained entries in p2m table\n",err);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Start writing out the saved-domain record. */
|
||||
|
||||
if (write(io_fd, &nr_pfns, sizeof(unsigned long)) !=
|
||||
sizeof(unsigned long)) {
|
||||
ERR("write: nr_pfns");
|
||||
goto out;
|
||||
if ( write(io_fd, &nr_pfns, sizeof(unsigned long)) !=
|
||||
sizeof(unsigned long) )
|
||||
{
|
||||
ERR("write: nr_pfns");
|
||||
goto out;
|
||||
}
|
||||
if (write(io_fd, pfn_to_mfn_frame_list, PAGE_SIZE) != PAGE_SIZE) {
|
||||
|
||||
if ( write(io_fd, pfn_to_mfn_frame_list, PAGE_SIZE) != PAGE_SIZE )
|
||||
{
|
||||
ERR("write: pfn_to_mfn_frame_list");
|
||||
goto out;
|
||||
}
|
||||
@@ -678,7 +701,8 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
|
||||
/* Now write out each data page, canonicalising page tables as we go... */
|
||||
|
||||
while(1){
|
||||
for ( ; ; )
|
||||
{
|
||||
unsigned int prev_pc, sent_this_iter, N, batch;
|
||||
|
||||
iter++;
|
||||
@@ -689,10 +713,12 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
|
||||
DPRINTF("Saving memory pages: iter %d 0%%", iter);
|
||||
|
||||
while( N < nr_pfns ){
|
||||
while ( N < nr_pfns )
|
||||
{
|
||||
unsigned int this_pc = (N * 100) / nr_pfns;
|
||||
|
||||
if ( (this_pc - prev_pc) >= 5 ){
|
||||
if ( (this_pc - prev_pc) >= 5 )
|
||||
{
|
||||
DPRINTF("\b\b\b\b%3d%%", this_pc);
|
||||
prev_pc = this_pc;
|
||||
}
|
||||
@@ -701,10 +727,10 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
but this is fast enough for the moment. */
|
||||
|
||||
if ( !last_iter &&
|
||||
xc_shadow_control(xc_handle, dom,
|
||||
xc_shadow_control(xc_handle, dom,
|
||||
DOM0_SHADOW_CONTROL_OP_PEEK,
|
||||
to_skip, nr_pfns, NULL) != nr_pfns )
|
||||
{
|
||||
{
|
||||
ERR("Error peeking shadow bitmap");
|
||||
goto out;
|
||||
}
|
||||
@@ -748,7 +774,7 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
pfn_type[batch] = live_pfn_to_mfn_table[n];
|
||||
|
||||
if( ! is_mapped(pfn_type[batch]) )
|
||||
{
|
||||
{
|
||||
/* not currently in pusedo-physical map -- set bit
|
||||
in to_fix that we must send this page in last_iter
|
||||
unless its sent sooner anyhow */
|
||||
@@ -756,7 +782,7 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
set_bit( n, to_fix );
|
||||
if( iter>1 )
|
||||
DPRINTF("netbuf race: iter %d, pfn %x. mfn %lx\n",
|
||||
iter,n,pfn_type[batch]);
|
||||
iter,n,pfn_type[batch]);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -790,8 +816,10 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
goto out;
|
||||
}
|
||||
|
||||
for ( j = 0; j < batch; j++ ){
|
||||
if ( (pfn_type[j] & LTAB_MASK) == XTAB ){
|
||||
for ( j = 0; j < batch; j++ )
|
||||
{
|
||||
if ( (pfn_type[j] & LTAB_MASK) == XTAB )
|
||||
{
|
||||
DPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]);
|
||||
continue;
|
||||
}
|
||||
@@ -809,21 +837,25 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
pfn_type[j] = (pfn_type[j] & LTAB_MASK) | pfn_batch[j];
|
||||
}
|
||||
|
||||
if (write(io_fd, &batch, sizeof(int)) != sizeof(int)) {
|
||||
if ( write(io_fd, &batch, sizeof(int)) != sizeof(int) )
|
||||
{
|
||||
ERR("Error when writing to state file (2)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (write(io_fd, pfn_type, sizeof(unsigned long)*j) !=
|
||||
sizeof(unsigned long)*j) {
|
||||
if ( write(io_fd, pfn_type, sizeof(unsigned long)*j) !=
|
||||
(sizeof(unsigned long) * j) )
|
||||
{
|
||||
ERR("Error when writing to state file (3)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* entering this loop, pfn_type is now in pfns (Not mfns) */
|
||||
for( j = 0; j < batch; j++ ){
|
||||
for ( j = 0; j < batch; j++ )
|
||||
{
|
||||
/* write out pages in batch */
|
||||
if( (pfn_type[j] & LTAB_MASK) == XTAB){
|
||||
if ( (pfn_type[j] & LTAB_MASK) == XTAB )
|
||||
{
|
||||
DPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]);
|
||||
continue;
|
||||
}
|
||||
@@ -836,7 +868,8 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
k < (((pfn_type[j] & LTABTYPE_MASK) == L2TAB) ?
|
||||
(HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) :
|
||||
1024);
|
||||
k++ ){
|
||||
k++ )
|
||||
{
|
||||
unsigned long pfn;
|
||||
|
||||
if ( !(page[k] & _PAGE_PRESENT) )
|
||||
@@ -849,13 +882,13 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
{
|
||||
/* I don't think this should ever happen */
|
||||
fprintf(stderr, "FNI %d : [%08lx,%d] pte=%08lx, "
|
||||
"mfn=%08lx, pfn=%08lx [mfn]=%08lx\n",
|
||||
j, pfn_type[j], k,
|
||||
page[k], mfn, live_mfn_to_pfn_table[mfn],
|
||||
(live_mfn_to_pfn_table[mfn]<nr_pfns)?
|
||||
live_pfn_to_mfn_table[
|
||||
live_mfn_to_pfn_table[mfn]] :
|
||||
0xdeadbeef);
|
||||
"mfn=%08lx, pfn=%08lx [mfn]=%08lx\n",
|
||||
j, pfn_type[j], k,
|
||||
page[k], mfn, live_mfn_to_pfn_table[mfn],
|
||||
(live_mfn_to_pfn_table[mfn]<nr_pfns)?
|
||||
live_pfn_to_mfn_table[
|
||||
live_mfn_to_pfn_table[mfn]] :
|
||||
0xdeadbeef);
|
||||
|
||||
pfn = 0; /* be suspicious */
|
||||
}
|
||||
@@ -865,12 +898,12 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
|
||||
#if 0
|
||||
fprintf(stderr,
|
||||
"L%d i=%d pfn=%d mfn=%d k=%d pte=%08lx "
|
||||
"xpfn=%d\n",
|
||||
pfn_type[j]>>28,
|
||||
j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT);
|
||||
"L%d i=%d pfn=%d mfn=%d k=%d pte=%08lx "
|
||||
"xpfn=%d\n",
|
||||
pfn_type[j]>>28,
|
||||
j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT);
|
||||
#endif
|
||||
|
||||
|
||||
} /* end of page table rewrite for loop */
|
||||
|
||||
if (ratewrite(io_fd, page, PAGE_SIZE) != PAGE_SIZE) {
|
||||
@@ -880,8 +913,9 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
|
||||
} /* end of it's a PT page */ else { /* normal page */
|
||||
|
||||
if (ratewrite(io_fd, region_base + (PAGE_SIZE*j),
|
||||
PAGE_SIZE) != PAGE_SIZE) {
|
||||
if ( ratewrite(io_fd, region_base + (PAGE_SIZE*j),
|
||||
PAGE_SIZE) != PAGE_SIZE )
|
||||
{
|
||||
ERR("Error when writing to state file (5)");
|
||||
goto out;
|
||||
}
|
||||
@@ -899,13 +933,13 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
total_sent += sent_this_iter;
|
||||
|
||||
DPRINTF("\r %d: sent %d, skipped %d, ",
|
||||
iter, sent_this_iter, skip_this_iter );
|
||||
iter, sent_this_iter, skip_this_iter );
|
||||
|
||||
if ( last_iter ) {
|
||||
print_stats( xc_handle, dom, sent_this_iter, &stats, 1);
|
||||
|
||||
DPRINTF("Total pages sent= %d (%.2fx)\n",
|
||||
total_sent, ((float)total_sent)/nr_pfns );
|
||||
total_sent, ((float)total_sent)/nr_pfns );
|
||||
DPRINTF("(of which %d were fixups)\n", needed_to_fix );
|
||||
}
|
||||
|
||||
@@ -930,7 +964,7 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
{
|
||||
if (
|
||||
( ( sent_this_iter > sent_last_iter ) &&
|
||||
(mbit_rate == MAX_MBIT_RATE ) ) ||
|
||||
(mbit_rate == MAX_MBIT_RATE ) ) ||
|
||||
(iter >= max_iters) ||
|
||||
(sent_this_iter+skip_this_iter < 50) ||
|
||||
(total_sent > nr_pfns*max_factor) )
|
||||
@@ -938,15 +972,15 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
DPRINTF("Start last iteration\n");
|
||||
last_iter = 1;
|
||||
|
||||
if ( suspend_and_state( xc_handle, io_fd, dom, &info, &ctxt) )
|
||||
{
|
||||
ERR("Domain appears not to have suspended");
|
||||
goto out;
|
||||
}
|
||||
if ( suspend_and_state( xc_handle, io_fd, dom, &info, &ctxt) )
|
||||
{
|
||||
ERR("Domain appears not to have suspended");
|
||||
goto out;
|
||||
}
|
||||
|
||||
DPRINTF("SUSPEND shinfo %08lx eip %08u esi %08u\n",
|
||||
info.shared_info_frame,
|
||||
ctxt.user_regs.eip, ctxt.user_regs.esi);
|
||||
DPRINTF("SUSPEND shinfo %08lx eip %08u esi %08u\n",
|
||||
info.shared_info_frame,
|
||||
ctxt.user_regs.eip, ctxt.user_regs.esi);
|
||||
}
|
||||
|
||||
if ( xc_shadow_control( xc_handle, dom,
|
||||
@@ -972,86 +1006,92 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
rc = 0;
|
||||
|
||||
/* Zero terminate */
|
||||
if (write(io_fd, &rc, sizeof(int)) != sizeof(int)) {
|
||||
if ( write(io_fd, &rc, sizeof(int)) != sizeof(int) )
|
||||
{
|
||||
ERR("Error when writing to state file (6)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Send through a list of all the PFNs that were not in map at the close */
|
||||
{
|
||||
unsigned int i,j;
|
||||
unsigned int pfntab[1024];
|
||||
unsigned int i,j;
|
||||
unsigned int pfntab[1024];
|
||||
|
||||
for ( i = 0, j = 0; i < nr_pfns; i++ )
|
||||
{
|
||||
if ( ! is_mapped(live_pfn_to_mfn_table[i]) )
|
||||
j++;
|
||||
}
|
||||
for ( i = 0, j = 0; i < nr_pfns; i++ )
|
||||
if ( !is_mapped(live_pfn_to_mfn_table[i]) )
|
||||
j++;
|
||||
|
||||
if (write(io_fd, &j, sizeof(unsigned int)) != sizeof(unsigned int)) {
|
||||
ERR("Error when writing to state file (6a)");
|
||||
goto out;
|
||||
}
|
||||
if ( write(io_fd, &j, sizeof(unsigned int)) != sizeof(unsigned int) )
|
||||
{
|
||||
ERR("Error when writing to state file (6a)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for ( i = 0, j = 0; i < nr_pfns; )
|
||||
{
|
||||
if ( ! is_mapped(live_pfn_to_mfn_table[i]) )
|
||||
{
|
||||
pfntab[j++] = i;
|
||||
}
|
||||
i++;
|
||||
if ( j == 1024 || i == nr_pfns )
|
||||
{
|
||||
if (write(io_fd, &pfntab, sizeof(unsigned long)*j) !=
|
||||
sizeof(unsigned long)*j) {
|
||||
ERR("Error when writing to state file (6b)");
|
||||
goto out;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
for ( i = 0, j = 0; i < nr_pfns; )
|
||||
{
|
||||
if ( !is_mapped(live_pfn_to_mfn_table[i]) )
|
||||
{
|
||||
pfntab[j++] = i;
|
||||
}
|
||||
i++;
|
||||
if ( j == 1024 || i == nr_pfns )
|
||||
{
|
||||
if ( write(io_fd, &pfntab, sizeof(unsigned long)*j) !=
|
||||
(sizeof(unsigned long) * j) )
|
||||
{
|
||||
ERR("Error when writing to state file (6b)");
|
||||
goto out;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Canonicalise the suspend-record frame number. */
|
||||
if ( !translate_mfn_to_pfn(&ctxt.user_regs.esi) ){
|
||||
if ( !translate_mfn_to_pfn(&ctxt.user_regs.esi) )
|
||||
{
|
||||
ERR("Suspend record is not in range of pseudophys map");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Canonicalise each GDT frame number. */
|
||||
for ( i = 0; i < ctxt.gdt_ents; i += 512 ) {
|
||||
if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) {
|
||||
for ( i = 0; i < ctxt.gdt_ents; i += 512 )
|
||||
{
|
||||
if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) )
|
||||
{
|
||||
ERR("GDT frame is not in range of pseudophys map");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Canonicalise the page table base pointer. */
|
||||
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.ctrlreg[3] >> PAGE_SHIFT) ) {
|
||||
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.ctrlreg[3] >> PAGE_SHIFT) )
|
||||
{
|
||||
ERR("PT base is not in range of pseudophys map");
|
||||
goto out;
|
||||
}
|
||||
ctxt.ctrlreg[3] = live_mfn_to_pfn_table[ctxt.ctrlreg[3] >> PAGE_SHIFT] <<
|
||||
PAGE_SHIFT;
|
||||
|
||||
if (write(io_fd, &ctxt, sizeof(ctxt)) != sizeof(ctxt) ||
|
||||
write(io_fd, live_shinfo, PAGE_SIZE) != PAGE_SIZE) {
|
||||
if ( write(io_fd, &ctxt, sizeof(ctxt)) != sizeof(ctxt) ||
|
||||
write(io_fd, live_shinfo, PAGE_SIZE) != PAGE_SIZE)
|
||||
{
|
||||
ERR("Error when writing to state file (1)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
if(live_shinfo)
|
||||
if ( live_shinfo )
|
||||
munmap(live_shinfo, PAGE_SIZE);
|
||||
|
||||
if(live_pfn_to_mfn_frame_list)
|
||||
if ( live_pfn_to_mfn_frame_list )
|
||||
munmap(live_pfn_to_mfn_frame_list, PAGE_SIZE);
|
||||
|
||||
if(live_pfn_to_mfn_table)
|
||||
if ( live_pfn_to_mfn_table )
|
||||
munmap(live_pfn_to_mfn_table, nr_pfns*4);
|
||||
|
||||
if(live_mfn_to_pfn_table)
|
||||
if ( live_mfn_to_pfn_table )
|
||||
munmap(live_mfn_to_pfn_table, PAGE_SIZE*1024);
|
||||
|
||||
free(pfn_type);
|
||||
@@ -1063,3 +1103,13 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
|
||||
DPRINTF("Save exit rc=%d\n",rc);
|
||||
return !!rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -64,11 +64,11 @@ parseaout9image(
|
||||
dstart = round_pgup(start + ehdr.text);
|
||||
end = dstart + ehdr.data + ehdr.bss;
|
||||
|
||||
dsi->v_start = KZERO;
|
||||
dsi->v_kernstart = start;
|
||||
dsi->v_kernend = end;
|
||||
dsi->v_kernentry = ehdr.entry;
|
||||
dsi->v_end = end;
|
||||
dsi->v_start = KZERO;
|
||||
dsi->v_kernstart = start;
|
||||
dsi->v_kernend = end;
|
||||
dsi->v_kernentry = ehdr.entry;
|
||||
dsi->v_end = end;
|
||||
|
||||
/* XXX load symbols */
|
||||
|
||||
@@ -168,3 +168,12 @@ get_header(
|
||||
return ehdr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -109,8 +109,8 @@ loadbinimage(
|
||||
unsigned long *parray, struct domain_setup_info *dsi);
|
||||
|
||||
int probe_bin(char *image,
|
||||
unsigned long image_size,
|
||||
struct load_funcs *load_funcs)
|
||||
unsigned long image_size,
|
||||
struct load_funcs *load_funcs)
|
||||
{
|
||||
if ( NULL == findtable(image, image_size) )
|
||||
{
|
||||
@@ -297,3 +297,13 @@ loadbinimage(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -30,8 +30,8 @@ loadelfsymtab(
|
||||
struct domain_setup_info *dsi);
|
||||
|
||||
int probe_elf(char *image,
|
||||
unsigned long image_size,
|
||||
struct load_funcs *load_funcs)
|
||||
unsigned long image_size,
|
||||
struct load_funcs *load_funcs)
|
||||
{
|
||||
Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
|
||||
|
||||
@@ -116,7 +116,7 @@ static int parseelfimage(char *image,
|
||||
return -EINVAL;
|
||||
}
|
||||
if ( (strstr(guestinfo, "PAE=yes") != NULL) )
|
||||
dsi->pae_kernel = 1;
|
||||
dsi->pae_kernel = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -313,3 +313,13 @@ loadelfsymtab(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
+11
-1
@@ -133,5 +133,15 @@ int xc_msr_write(int xc_handle, int cpu_mask, int msr, unsigned int low,
|
||||
|
||||
long xc_init_store(int xc_handle, int remote_port)
|
||||
{
|
||||
return ioctl(xc_handle, IOCTL_PRIVCMD_INITDOMAIN_STORE, remote_port);
|
||||
return ioctl(xc_handle, IOCTL_PRIVCMD_INITDOMAIN_STORE, remote_port);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
+51
-41
@@ -15,7 +15,7 @@ void *xc_map_foreign_batch(int xc_handle, u32 dom, int prot,
|
||||
void *addr;
|
||||
addr = mmap(NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0);
|
||||
if ( addr == MAP_FAILED )
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
ioctlx.num=num;
|
||||
ioctlx.dom=dom;
|
||||
@@ -24,10 +24,10 @@ void *xc_map_foreign_batch(int xc_handle, u32 dom, int prot,
|
||||
if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx ) < 0 )
|
||||
{
|
||||
int saved_errno = errno;
|
||||
perror("XXXXXXXX");
|
||||
(void)munmap(addr, num*PAGE_SIZE);
|
||||
perror("XXXXXXXX");
|
||||
(void)munmap(addr, num*PAGE_SIZE);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
return addr;
|
||||
|
||||
@@ -36,15 +36,15 @@ void *xc_map_foreign_batch(int xc_handle, u32 dom, int prot,
|
||||
/*******************/
|
||||
|
||||
void *xc_map_foreign_range(int xc_handle, u32 dom,
|
||||
int size, int prot,
|
||||
unsigned long mfn )
|
||||
int size, int prot,
|
||||
unsigned long mfn )
|
||||
{
|
||||
privcmd_mmap_t ioctlx;
|
||||
privcmd_mmap_entry_t entry;
|
||||
void *addr;
|
||||
addr = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
|
||||
if ( addr == MAP_FAILED )
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
ioctlx.num=1;
|
||||
ioctlx.dom=dom;
|
||||
@@ -55,9 +55,9 @@ void *xc_map_foreign_range(int xc_handle, u32 dom,
|
||||
if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) < 0 )
|
||||
{
|
||||
int saved_errno = errno;
|
||||
(void)munmap(addr, size);
|
||||
(void)munmap(addr, size);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ void *xc_map_foreign_range(int xc_handle, u32 dom,
|
||||
|
||||
/* NB: arr must be mlock'ed */
|
||||
int xc_get_pfn_type_batch(int xc_handle,
|
||||
u32 dom, int num, unsigned long *arr)
|
||||
u32 dom, int num, unsigned long *arr)
|
||||
{
|
||||
dom0_op_t op;
|
||||
op.cmd = DOM0_GETPAGEFRAMEINFO2;
|
||||
@@ -116,8 +116,8 @@ int xc_mmuext_op(
|
||||
|
||||
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
|
||||
{
|
||||
fprintf(stderr, "Dom_mmuext operation failed (rc=%ld errno=%d)-- need to"
|
||||
" rebuild the user-space tool set?\n",ret,errno);
|
||||
fprintf(stderr, "Dom_mmuext operation failed (rc=%ld errno=%d)-- need to"
|
||||
" rebuild the user-space tool set?\n",ret,errno);
|
||||
}
|
||||
|
||||
safe_munlock(op, nr_ops*sizeof(*op));
|
||||
@@ -172,7 +172,7 @@ xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom)
|
||||
}
|
||||
|
||||
int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
|
||||
unsigned long long ptr, unsigned long long val)
|
||||
unsigned long long ptr, unsigned long long val)
|
||||
{
|
||||
mmu->updates[mmu->idx].ptr = ptr;
|
||||
mmu->updates[mmu->idx].val = val;
|
||||
@@ -229,7 +229,7 @@ int xc_memory_op(int xc_handle,
|
||||
|
||||
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
|
||||
{
|
||||
fprintf(stderr, "hypercall failed (rc=%ld errno=%d)-- need to"
|
||||
fprintf(stderr, "hypercall failed (rc=%ld errno=%d)-- need to"
|
||||
" rebuild the user-space tool set?\n",ret,errno);
|
||||
}
|
||||
|
||||
@@ -275,16 +275,16 @@ unsigned long xc_get_m2p_start_mfn ( int xc_handle )
|
||||
|
||||
if ( ioctl( xc_handle, IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN, &mfn ) < 0 )
|
||||
{
|
||||
perror("xc_get_m2p_start_mfn:");
|
||||
return 0;
|
||||
perror("xc_get_m2p_start_mfn:");
|
||||
return 0;
|
||||
}
|
||||
return mfn;
|
||||
}
|
||||
|
||||
int xc_get_pfn_list(int xc_handle,
|
||||
u32 domid,
|
||||
unsigned long *pfn_buf,
|
||||
unsigned long max_pfns)
|
||||
u32 domid,
|
||||
unsigned long *pfn_buf,
|
||||
unsigned long max_pfns)
|
||||
{
|
||||
dom0_op_t op;
|
||||
int ret;
|
||||
@@ -306,16 +306,16 @@ int xc_get_pfn_list(int xc_handle,
|
||||
|
||||
#if 0
|
||||
#ifdef DEBUG
|
||||
DPRINTF(("Ret for xc_get_pfn_list is %d\n", ret));
|
||||
if (ret >= 0) {
|
||||
int i, j;
|
||||
for (i = 0; i < op.u.getmemlist.num_pfns; i += 16) {
|
||||
fprintf(stderr, "0x%x: ", i);
|
||||
for (j = 0; j < 16; j++)
|
||||
fprintf(stderr, "0x%lx ", pfn_buf[i + j]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
DPRINTF(("Ret for xc_get_pfn_list is %d\n", ret));
|
||||
if (ret >= 0) {
|
||||
int i, j;
|
||||
for (i = 0; i < op.u.getmemlist.num_pfns; i += 16) {
|
||||
fprintf(stderr, "0x%x: ", i);
|
||||
for (j = 0; j < 16; j++)
|
||||
fprintf(stderr, "0x%lx ", pfn_buf[i + j]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -324,10 +324,10 @@ int xc_get_pfn_list(int xc_handle,
|
||||
|
||||
#ifdef __ia64__
|
||||
int xc_ia64_get_pfn_list(int xc_handle,
|
||||
u32 domid,
|
||||
unsigned long *pfn_buf,
|
||||
unsigned int start_page,
|
||||
unsigned int nr_pages)
|
||||
u32 domid,
|
||||
unsigned long *pfn_buf,
|
||||
unsigned int start_page,
|
||||
unsigned int nr_pages)
|
||||
{
|
||||
dom0_op_t op;
|
||||
int ret;
|
||||
@@ -372,9 +372,9 @@ long xc_get_tot_pages(int xc_handle, u32 domid)
|
||||
}
|
||||
|
||||
int xc_copy_to_domain_page(int xc_handle,
|
||||
u32 domid,
|
||||
unsigned long dst_pfn,
|
||||
void *src_page)
|
||||
u32 domid,
|
||||
unsigned long dst_pfn,
|
||||
void *src_page)
|
||||
{
|
||||
void *vaddr = xc_map_foreign_range(
|
||||
xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
|
||||
@@ -465,18 +465,28 @@ unsigned long xc_make_page_below_4G(
|
||||
unsigned long new_mfn;
|
||||
|
||||
if ( xc_domain_memory_decrease_reservation(
|
||||
xc_handle, domid, 1, 0, &mfn) != 0 )
|
||||
xc_handle, domid, 1, 0, &mfn) != 0 )
|
||||
{
|
||||
fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
|
||||
return 0;
|
||||
fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( xc_domain_memory_increase_reservation(
|
||||
xc_handle, domid, 1, 0, 32, &new_mfn) != 0 )
|
||||
{
|
||||
fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn);
|
||||
return 0;
|
||||
fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new_mfn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
+201
-195
@@ -5,12 +5,9 @@
|
||||
|
||||
#define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */
|
||||
#define X86_CR0_PG 0x80000000 /* Paging (RW) */
|
||||
|
||||
#define BSD_PAGE_MASK (PAGE_SIZE-1)
|
||||
#define PG_FRAME (~((unsigned long)BSD_PAGE_MASK)
|
||||
#define BSD_PAGE_MASK (PAGE_SIZE-1)
|
||||
#define PDRSHIFT 22
|
||||
#define PSL_T 0x00000100 /* trace enable bit */
|
||||
|
||||
#define PSL_T 0x00000100 /* trace enable bit */
|
||||
#define VCPU 0 /* XXX */
|
||||
|
||||
/*
|
||||
@@ -69,67 +66,66 @@ struct gdb_regs {
|
||||
int xss; /* 64 */
|
||||
};
|
||||
|
||||
#define FETCH_REGS(cpu) \
|
||||
if (!regs_valid[cpu]) \
|
||||
{ \
|
||||
int retval = xc_domain_get_vcpu_context(xc_handle, domid, cpu, &ctxt[cpu]); \
|
||||
if (retval) \
|
||||
goto error_out; \
|
||||
cr3[cpu] = ctxt[cpu].ctrlreg[3]; /* physical address */ \
|
||||
regs_valid[cpu] = 1; \
|
||||
} \
|
||||
#define FETCH_REGS(cpu) \
|
||||
if (!regs_valid[cpu]) \
|
||||
{ \
|
||||
int retval = xc_domain_get_vcpu_context( \
|
||||
xc_handle, domid, cpu, &ctxt[cpu]); \
|
||||
if (retval) \
|
||||
goto error_out; \
|
||||
cr3[cpu] = ctxt[cpu].ctrlreg[3]; /* physical address */ \
|
||||
regs_valid[cpu] = 1; \
|
||||
}
|
||||
|
||||
#define printval(x) printf("%s = %lx\n", #x, (long)x);
|
||||
#define SET_PT_REGS(pt, xc) \
|
||||
{ \
|
||||
pt.ebx = xc.ebx; \
|
||||
pt.ecx = xc.ecx; \
|
||||
pt.edx = xc.edx; \
|
||||
pt.esi = xc.esi; \
|
||||
pt.edi = xc.edi; \
|
||||
pt.ebp = xc.ebp; \
|
||||
pt.eax = xc.eax; \
|
||||
pt.eip = xc.eip; \
|
||||
pt.xcs = xc.cs; \
|
||||
pt.eflags = xc.eflags; \
|
||||
pt.esp = xc.esp; \
|
||||
pt.xss = xc.ss; \
|
||||
pt.xes = xc.es; \
|
||||
pt.xds = xc.ds; \
|
||||
pt.xfs = xc.fs; \
|
||||
pt.xgs = xc.gs; \
|
||||
#define SET_PT_REGS(pt, xc) \
|
||||
{ \
|
||||
pt.ebx = xc.ebx; \
|
||||
pt.ecx = xc.ecx; \
|
||||
pt.edx = xc.edx; \
|
||||
pt.esi = xc.esi; \
|
||||
pt.edi = xc.edi; \
|
||||
pt.ebp = xc.ebp; \
|
||||
pt.eax = xc.eax; \
|
||||
pt.eip = xc.eip; \
|
||||
pt.xcs = xc.cs; \
|
||||
pt.eflags = xc.eflags; \
|
||||
pt.esp = xc.esp; \
|
||||
pt.xss = xc.ss; \
|
||||
pt.xes = xc.es; \
|
||||
pt.xds = xc.ds; \
|
||||
pt.xfs = xc.fs; \
|
||||
pt.xgs = xc.gs; \
|
||||
}
|
||||
|
||||
#define SET_XC_REGS(pt, xc) \
|
||||
{ \
|
||||
xc.ebx = pt->ebx; \
|
||||
xc.ecx = pt->ecx; \
|
||||
xc.edx = pt->edx; \
|
||||
xc.esi = pt->esi; \
|
||||
xc.edi = pt->edi; \
|
||||
xc.ebp = pt->ebp; \
|
||||
xc.eax = pt->eax; \
|
||||
xc.eip = pt->eip; \
|
||||
xc.cs = pt->xcs; \
|
||||
xc.eflags = pt->eflags; \
|
||||
xc.esp = pt->esp; \
|
||||
xc.ss = pt->xss; \
|
||||
xc.es = pt->xes; \
|
||||
xc.ds = pt->xds; \
|
||||
xc.fs = pt->xfs; \
|
||||
xc.gs = pt->xgs; \
|
||||
#define SET_XC_REGS(pt, xc) \
|
||||
{ \
|
||||
xc.ebx = pt->ebx; \
|
||||
xc.ecx = pt->ecx; \
|
||||
xc.edx = pt->edx; \
|
||||
xc.esi = pt->esi; \
|
||||
xc.edi = pt->edi; \
|
||||
xc.ebp = pt->ebp; \
|
||||
xc.eax = pt->eax; \
|
||||
xc.eip = pt->eip; \
|
||||
xc.cs = pt->xcs; \
|
||||
xc.eflags = pt->eflags; \
|
||||
xc.esp = pt->esp; \
|
||||
xc.ss = pt->xss; \
|
||||
xc.es = pt->xes; \
|
||||
xc.ds = pt->xds; \
|
||||
xc.fs = pt->xfs; \
|
||||
xc.gs = pt->xgs; \
|
||||
}
|
||||
|
||||
|
||||
#define vtopdi(va) ((va) >> PDRSHIFT)
|
||||
#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff)
|
||||
|
||||
/* XXX application state */
|
||||
|
||||
|
||||
static int xc_handle;
|
||||
static long nr_pages = 0;
|
||||
unsigned long *page_array = NULL;
|
||||
static long nr_pages = 0;
|
||||
unsigned long *page_array = NULL;
|
||||
static int regs_valid[MAX_VIRT_CPUS];
|
||||
static unsigned long cr3[MAX_VIRT_CPUS];
|
||||
static vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
|
||||
@@ -160,64 +156,64 @@ map_domain_va(unsigned long domid, int cpu, void * guest_va, int perm)
|
||||
static int prev_perm[MAX_VIRT_CPUS];
|
||||
|
||||
if (nr_pages != npgs) {
|
||||
if (nr_pages > 0)
|
||||
free(page_array);
|
||||
nr_pages = npgs;
|
||||
if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
|
||||
printf("Could not allocate memory\n");
|
||||
goto error_out;
|
||||
}
|
||||
if (nr_pages > 0)
|
||||
free(page_array);
|
||||
nr_pages = npgs;
|
||||
if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
|
||||
printf("Could not allocate memory\n");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages) {
|
||||
printf("Could not get the page frame list\n");
|
||||
goto error_out;
|
||||
}
|
||||
if (xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages) {
|
||||
printf("Could not get the page frame list\n");
|
||||
goto error_out;
|
||||
}
|
||||
}
|
||||
|
||||
FETCH_REGS(cpu);
|
||||
|
||||
if (cr3[cpu] != cr3_phys[cpu])
|
||||
{
|
||||
cr3_phys[cpu] = cr3[cpu];
|
||||
if (cr3_virt[cpu])
|
||||
munmap(cr3_virt[cpu], PAGE_SIZE);
|
||||
if ((cr3_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
|
||||
PROT_READ,
|
||||
cr3_phys[cpu] >> PAGE_SHIFT)) == NULL)
|
||||
goto error_out;
|
||||
cr3_phys[cpu] = cr3[cpu];
|
||||
if (cr3_virt[cpu])
|
||||
munmap(cr3_virt[cpu], PAGE_SIZE);
|
||||
if ((cr3_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
|
||||
PROT_READ,
|
||||
cr3_phys[cpu] >> PAGE_SHIFT)) == NULL)
|
||||
goto error_out;
|
||||
}
|
||||
if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) /* logical address */
|
||||
goto error_out;
|
||||
goto error_out;
|
||||
if ((ctxt[cpu].flags & VGCF_VMX_GUEST) && paging_enabled(&ctxt[cpu]))
|
||||
pde = page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
|
||||
if (pde != pde_phys[cpu])
|
||||
{
|
||||
pde_phys[cpu] = pde;
|
||||
if (pde_virt[cpu])
|
||||
munmap(pde_virt[cpu], PAGE_SIZE);
|
||||
if ((pde_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
|
||||
PROT_READ,
|
||||
pde_phys[cpu] >> PAGE_SHIFT)) == NULL)
|
||||
goto error_out;
|
||||
pde_phys[cpu] = pde;
|
||||
if (pde_virt[cpu])
|
||||
munmap(pde_virt[cpu], PAGE_SIZE);
|
||||
if ((pde_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
|
||||
PROT_READ,
|
||||
pde_phys[cpu] >> PAGE_SHIFT)) == NULL)
|
||||
goto error_out;
|
||||
}
|
||||
if ((page = pde_virt[cpu][vtopti(va)]) == 0) /* logical address */
|
||||
goto error_out;
|
||||
goto error_out;
|
||||
if (ctxt[cpu].flags & VGCF_VMX_GUEST && paging_enabled(&ctxt[cpu]))
|
||||
page = page_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
|
||||
if (page != page_phys[cpu] || perm != prev_perm[cpu])
|
||||
{
|
||||
page_phys[cpu] = page;
|
||||
if (page_virt[cpu])
|
||||
munmap(page_virt[cpu], PAGE_SIZE);
|
||||
if ((page_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
|
||||
perm,
|
||||
page_phys[cpu] >> PAGE_SHIFT)) == NULL) {
|
||||
printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, vtopti(va));
|
||||
page_phys[cpu] = 0;
|
||||
goto error_out;
|
||||
}
|
||||
prev_perm[cpu] = perm;
|
||||
}
|
||||
page_phys[cpu] = page;
|
||||
if (page_virt[cpu])
|
||||
munmap(page_virt[cpu], PAGE_SIZE);
|
||||
if ((page_virt[cpu] = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
|
||||
perm,
|
||||
page_phys[cpu] >> PAGE_SHIFT)) == NULL) {
|
||||
printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, vtopti(va));
|
||||
page_phys[cpu] = 0;
|
||||
goto error_out;
|
||||
}
|
||||
prev_perm[cpu] = perm;
|
||||
}
|
||||
return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
|
||||
|
||||
error_out:
|
||||
@@ -234,29 +230,29 @@ xc_waitdomain(int domain, int *status, int options)
|
||||
ts.tv_nsec = 10*1000*1000;
|
||||
|
||||
if (!xc_handle)
|
||||
if ((xc_handle = xc_interface_open()) < 0)
|
||||
{
|
||||
printf("xc_interface_open failed\n");
|
||||
return -1;
|
||||
}
|
||||
if ((xc_handle = xc_interface_open()) < 0)
|
||||
{
|
||||
printf("xc_interface_open failed\n");
|
||||
return -1;
|
||||
}
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = domain;
|
||||
retry:
|
||||
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
if (retval || op.u.getdomaininfo.domain != domain) {
|
||||
printf("getdomaininfo failed\n");
|
||||
goto done;
|
||||
printf("getdomaininfo failed\n");
|
||||
goto done;
|
||||
}
|
||||
*status = op.u.getdomaininfo.flags;
|
||||
|
||||
if (options & WNOHANG)
|
||||
goto done;
|
||||
|
||||
goto done;
|
||||
|
||||
|
||||
if (!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED)) {
|
||||
nanosleep(&ts,NULL);
|
||||
goto retry;
|
||||
if (!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED)) {
|
||||
nanosleep(&ts,NULL);
|
||||
goto retry;
|
||||
}
|
||||
done:
|
||||
return retval;
|
||||
@@ -278,107 +274,107 @@ xc_ptrace(enum __ptrace_request request, u32 domid, long eaddr, long edata)
|
||||
op.interface_version = DOM0_INTERFACE_VERSION;
|
||||
|
||||
if (!xc_handle)
|
||||
if ((xc_handle = xc_interface_open()) < 0)
|
||||
return -1;
|
||||
if ((xc_handle = xc_interface_open()) < 0)
|
||||
return -1;
|
||||
#if 0
|
||||
printf("%20s %d, %p, %p \n", ptrace_names[request], domid, addr, data);
|
||||
#endif
|
||||
switch (request) {
|
||||
switch (request) {
|
||||
case PTRACE_PEEKTEXT:
|
||||
case PTRACE_PEEKDATA:
|
||||
if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ)) == NULL) {
|
||||
status = EFAULT;
|
||||
goto error_out;
|
||||
}
|
||||
if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ)) == NULL) {
|
||||
status = EFAULT;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
retval = *guest_va;
|
||||
break;
|
||||
retval = *guest_va;
|
||||
break;
|
||||
case PTRACE_POKETEXT:
|
||||
case PTRACE_POKEDATA:
|
||||
if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ|PROT_WRITE)) == NULL) {
|
||||
status = EFAULT;
|
||||
goto error_out;
|
||||
}
|
||||
if ((guest_va = (unsigned long *)map_domain_va(domid, cpu, addr, PROT_READ|PROT_WRITE)) == NULL) {
|
||||
status = EFAULT;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
*guest_va = (unsigned long)data;
|
||||
break;
|
||||
*guest_va = (unsigned long)data;
|
||||
break;
|
||||
case PTRACE_GETREGS:
|
||||
case PTRACE_GETFPREGS:
|
||||
case PTRACE_GETFPXREGS:
|
||||
FETCH_REGS(cpu);
|
||||
FETCH_REGS(cpu);
|
||||
|
||||
if (request == PTRACE_GETREGS) {
|
||||
SET_PT_REGS(pt, ctxt[cpu].user_regs);
|
||||
memcpy(data, &pt, sizeof(struct gdb_regs));
|
||||
} else if (request == PTRACE_GETFPREGS)
|
||||
memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
|
||||
else /*if (request == PTRACE_GETFPXREGS)*/
|
||||
memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
|
||||
break;
|
||||
if (request == PTRACE_GETREGS) {
|
||||
SET_PT_REGS(pt, ctxt[cpu].user_regs);
|
||||
memcpy(data, &pt, sizeof(struct gdb_regs));
|
||||
} else if (request == PTRACE_GETFPREGS)
|
||||
memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
|
||||
else /*if (request == PTRACE_GETFPXREGS)*/
|
||||
memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
|
||||
break;
|
||||
case PTRACE_SETREGS:
|
||||
op.cmd = DOM0_SETDOMAININFO;
|
||||
SET_XC_REGS(((struct gdb_regs *)data), ctxt[VCPU].user_regs);
|
||||
op.u.setdomaininfo.domain = domid;
|
||||
/* XXX need to understand multiple vcpus */
|
||||
op.u.setdomaininfo.vcpu = cpu;
|
||||
op.u.setdomaininfo.ctxt = &ctxt[cpu];
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
if (retval)
|
||||
goto error_out;
|
||||
op.cmd = DOM0_SETDOMAININFO;
|
||||
SET_XC_REGS(((struct gdb_regs *)data), ctxt[VCPU].user_regs);
|
||||
op.u.setdomaininfo.domain = domid;
|
||||
/* XXX need to understand multiple vcpus */
|
||||
op.u.setdomaininfo.vcpu = cpu;
|
||||
op.u.setdomaininfo.ctxt = &ctxt[cpu];
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
if (retval)
|
||||
goto error_out;
|
||||
|
||||
break;
|
||||
break;
|
||||
case PTRACE_ATTACH:
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = domid;
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
if (retval || op.u.getdomaininfo.domain != domid) {
|
||||
perror("dom0 op failed");
|
||||
goto error_out;
|
||||
}
|
||||
if (op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) {
|
||||
printf("domain currently paused\n");
|
||||
goto error_out;
|
||||
}
|
||||
printf("domain not currently paused\n");
|
||||
op.cmd = DOM0_PAUSEDOMAIN;
|
||||
op.u.pausedomain.domain = domid;
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
break;
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = domid;
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
if (retval || op.u.getdomaininfo.domain != domid) {
|
||||
perror("dom0 op failed");
|
||||
goto error_out;
|
||||
}
|
||||
if (op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) {
|
||||
printf("domain currently paused\n");
|
||||
goto error_out;
|
||||
}
|
||||
printf("domain not currently paused\n");
|
||||
op.cmd = DOM0_PAUSEDOMAIN;
|
||||
op.u.pausedomain.domain = domid;
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
break;
|
||||
case PTRACE_SINGLESTEP:
|
||||
ctxt[VCPU].user_regs.eflags |= PSL_T;
|
||||
op.cmd = DOM0_SETDOMAININFO;
|
||||
op.u.setdomaininfo.domain = domid;
|
||||
op.u.setdomaininfo.vcpu = 0;
|
||||
op.u.setdomaininfo.ctxt = &ctxt[cpu];
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
if (retval) {
|
||||
perror("dom0 op failed");
|
||||
goto error_out;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
ctxt[VCPU].user_regs.eflags |= PSL_T;
|
||||
op.cmd = DOM0_SETDOMAININFO;
|
||||
op.u.setdomaininfo.domain = domid;
|
||||
op.u.setdomaininfo.vcpu = 0;
|
||||
op.u.setdomaininfo.ctxt = &ctxt[cpu];
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
if (retval) {
|
||||
perror("dom0 op failed");
|
||||
goto error_out;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case PTRACE_CONT:
|
||||
case PTRACE_DETACH:
|
||||
if (request != PTRACE_SINGLESTEP) {
|
||||
FETCH_REGS(cpu);
|
||||
/* Clear trace flag */
|
||||
if (ctxt[cpu].user_regs.eflags & PSL_T) {
|
||||
ctxt[cpu].user_regs.eflags &= ~PSL_T;
|
||||
op.cmd = DOM0_SETDOMAININFO;
|
||||
op.u.setdomaininfo.domain = domid;
|
||||
op.u.setdomaininfo.vcpu = cpu;
|
||||
op.u.setdomaininfo.ctxt = &ctxt[cpu];
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
if (retval) {
|
||||
perror("dom0 op failed");
|
||||
goto error_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
regs_valid[cpu] = 0;
|
||||
op.cmd = DOM0_UNPAUSEDOMAIN;
|
||||
op.u.unpausedomain.domain = domid > 0 ? domid : -domid;
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
break;
|
||||
if (request != PTRACE_SINGLESTEP) {
|
||||
FETCH_REGS(cpu);
|
||||
/* Clear trace flag */
|
||||
if (ctxt[cpu].user_regs.eflags & PSL_T) {
|
||||
ctxt[cpu].user_regs.eflags &= ~PSL_T;
|
||||
op.cmd = DOM0_SETDOMAININFO;
|
||||
op.u.setdomaininfo.domain = domid;
|
||||
op.u.setdomaininfo.vcpu = cpu;
|
||||
op.u.setdomaininfo.ctxt = &ctxt[cpu];
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
if (retval) {
|
||||
perror("dom0 op failed");
|
||||
goto error_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
regs_valid[cpu] = 0;
|
||||
op.cmd = DOM0_UNPAUSEDOMAIN;
|
||||
op.u.unpausedomain.domain = domid > 0 ? domid : -domid;
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
break;
|
||||
case PTRACE_SETFPREGS:
|
||||
case PTRACE_SETFPXREGS:
|
||||
case PTRACE_PEEKUSER:
|
||||
@@ -386,20 +382,30 @@ xc_ptrace(enum __ptrace_request request, u32 domid, long eaddr, long edata)
|
||||
case PTRACE_SYSCALL:
|
||||
case PTRACE_KILL:
|
||||
#ifdef DEBUG
|
||||
printf("unsupported xc_ptrace request %s\n", ptrace_names[request]);
|
||||
printf("unsupported xc_ptrace request %s\n", ptrace_names[request]);
|
||||
#endif
|
||||
/* XXX not yet supported */
|
||||
status = ENOSYS;
|
||||
break;
|
||||
/* XXX not yet supported */
|
||||
status = ENOSYS;
|
||||
break;
|
||||
case PTRACE_TRACEME:
|
||||
printf("PTRACE_TRACEME is an invalid request under Xen\n");
|
||||
status = EINVAL;
|
||||
printf("PTRACE_TRACEME is an invalid request under Xen\n");
|
||||
status = EINVAL;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
errno = status;
|
||||
retval = -1;
|
||||
errno = status;
|
||||
retval = -1;
|
||||
}
|
||||
error_out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
+132
-128
@@ -3,12 +3,8 @@
|
||||
#include "xc_private.h"
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#define BSD_PAGE_MASK (PAGE_SIZE-1)
|
||||
#define PG_FRAME (~((unsigned long)BSD_PAGE_MASK)
|
||||
#define BSD_PAGE_MASK (PAGE_SIZE-1)
|
||||
#define PDRSHIFT 22
|
||||
#define PSL_T 0x00000100 /* trace enable bit */
|
||||
|
||||
#define VCPU 0 /* XXX */
|
||||
|
||||
/*
|
||||
@@ -16,7 +12,6 @@
|
||||
* ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
|
||||
*/
|
||||
|
||||
|
||||
struct gdb_regs {
|
||||
long ebx; /* 0 */
|
||||
long ecx; /* 4 */
|
||||
@@ -38,44 +33,44 @@ struct gdb_regs {
|
||||
};
|
||||
|
||||
#define printval(x) printf("%s = %lx\n", #x, (long)x);
|
||||
#define SET_PT_REGS(pt, xc) \
|
||||
{ \
|
||||
pt.ebx = xc.ebx; \
|
||||
pt.ecx = xc.ecx; \
|
||||
pt.edx = xc.edx; \
|
||||
pt.esi = xc.esi; \
|
||||
pt.edi = xc.edi; \
|
||||
pt.ebp = xc.ebp; \
|
||||
pt.eax = xc.eax; \
|
||||
pt.eip = xc.eip; \
|
||||
pt.xcs = xc.cs; \
|
||||
pt.eflags = xc.eflags; \
|
||||
pt.esp = xc.esp; \
|
||||
pt.xss = xc.ss; \
|
||||
pt.xes = xc.es; \
|
||||
pt.xds = xc.ds; \
|
||||
pt.xfs = xc.fs; \
|
||||
pt.xgs = xc.gs; \
|
||||
#define SET_PT_REGS(pt, xc) \
|
||||
{ \
|
||||
pt.ebx = xc.ebx; \
|
||||
pt.ecx = xc.ecx; \
|
||||
pt.edx = xc.edx; \
|
||||
pt.esi = xc.esi; \
|
||||
pt.edi = xc.edi; \
|
||||
pt.ebp = xc.ebp; \
|
||||
pt.eax = xc.eax; \
|
||||
pt.eip = xc.eip; \
|
||||
pt.xcs = xc.cs; \
|
||||
pt.eflags = xc.eflags; \
|
||||
pt.esp = xc.esp; \
|
||||
pt.xss = xc.ss; \
|
||||
pt.xes = xc.es; \
|
||||
pt.xds = xc.ds; \
|
||||
pt.xfs = xc.fs; \
|
||||
pt.xgs = xc.gs; \
|
||||
}
|
||||
|
||||
#define SET_XC_REGS(pt, xc) \
|
||||
{ \
|
||||
xc.ebx = pt->ebx; \
|
||||
xc.ecx = pt->ecx; \
|
||||
xc.edx = pt->edx; \
|
||||
xc.esi = pt->esi; \
|
||||
xc.edi = pt->edi; \
|
||||
xc.ebp = pt->ebp; \
|
||||
xc.eax = pt->eax; \
|
||||
xc.eip = pt->eip; \
|
||||
xc.cs = pt->xcs; \
|
||||
xc.eflags = pt->eflags; \
|
||||
xc.esp = pt->esp; \
|
||||
xc.ss = pt->xss; \
|
||||
xc.es = pt->xes; \
|
||||
xc.ds = pt->xds; \
|
||||
xc.fs = pt->xfs; \
|
||||
xc.gs = pt->xgs; \
|
||||
#define SET_XC_REGS(pt, xc) \
|
||||
{ \
|
||||
xc.ebx = pt->ebx; \
|
||||
xc.ecx = pt->ecx; \
|
||||
xc.edx = pt->edx; \
|
||||
xc.esi = pt->esi; \
|
||||
xc.edi = pt->edi; \
|
||||
xc.ebp = pt->ebp; \
|
||||
xc.eax = pt->eax; \
|
||||
xc.eip = pt->eip; \
|
||||
xc.cs = pt->xcs; \
|
||||
xc.eflags = pt->eflags; \
|
||||
xc.esp = pt->esp; \
|
||||
xc.ss = pt->xss; \
|
||||
xc.es = pt->xes; \
|
||||
xc.ds = pt->xds; \
|
||||
xc.fs = pt->xfs; \
|
||||
xc.gs = pt->xgs; \
|
||||
}
|
||||
|
||||
|
||||
@@ -84,10 +79,9 @@ struct gdb_regs {
|
||||
|
||||
/* XXX application state */
|
||||
|
||||
|
||||
static long nr_pages = 0;
|
||||
static unsigned long *p2m_array = NULL;
|
||||
static unsigned long *m2p_array = NULL;
|
||||
static long nr_pages = 0;
|
||||
static unsigned long *p2m_array = NULL;
|
||||
static unsigned long *m2p_array = NULL;
|
||||
static unsigned long pages_offset;
|
||||
static unsigned long cr3[MAX_VIRT_CPUS];
|
||||
static vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
|
||||
@@ -117,54 +111,54 @@ map_domain_va(unsigned long domfd, int cpu, void * guest_va)
|
||||
|
||||
if (cr3[cpu] != cr3_phys[cpu])
|
||||
{
|
||||
cr3_phys[cpu] = cr3[cpu];
|
||||
if (cr3_virt[cpu])
|
||||
munmap(cr3_virt[cpu], PAGE_SIZE);
|
||||
v = mmap(
|
||||
cr3_phys[cpu] = cr3[cpu];
|
||||
if (cr3_virt[cpu])
|
||||
munmap(cr3_virt[cpu], PAGE_SIZE);
|
||||
v = mmap(
|
||||
NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd,
|
||||
map_mtop_offset(cr3_phys[cpu]));
|
||||
if (v == MAP_FAILED)
|
||||
{
|
||||
perror("mmap failed");
|
||||
goto error_out;
|
||||
}
|
||||
{
|
||||
perror("mmap failed");
|
||||
goto error_out;
|
||||
}
|
||||
cr3_virt[cpu] = v;
|
||||
}
|
||||
if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) /* logical address */
|
||||
goto error_out;
|
||||
goto error_out;
|
||||
if (ctxt[cpu].flags & VGCF_VMX_GUEST)
|
||||
pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
|
||||
pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
|
||||
if (pde != pde_phys[cpu])
|
||||
{
|
||||
pde_phys[cpu] = pde;
|
||||
if (pde_virt[cpu])
|
||||
munmap(pde_virt[cpu], PAGE_SIZE);
|
||||
v = mmap(
|
||||
pde_phys[cpu] = pde;
|
||||
if (pde_virt[cpu])
|
||||
munmap(pde_virt[cpu], PAGE_SIZE);
|
||||
v = mmap(
|
||||
NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd,
|
||||
map_mtop_offset(pde_phys[cpu]));
|
||||
if (v == MAP_FAILED)
|
||||
goto error_out;
|
||||
goto error_out;
|
||||
pde_virt[cpu] = v;
|
||||
}
|
||||
if ((page = pde_virt[cpu][vtopti(va)]) == 0) /* logical address */
|
||||
goto error_out;
|
||||
goto error_out;
|
||||
if (ctxt[cpu].flags & VGCF_VMX_GUEST)
|
||||
page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
|
||||
page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
|
||||
if (page != page_phys[cpu])
|
||||
{
|
||||
page_phys[cpu] = page;
|
||||
if (page_virt[cpu])
|
||||
munmap(page_virt[cpu], PAGE_SIZE);
|
||||
v = mmap(
|
||||
page_phys[cpu] = page;
|
||||
if (page_virt[cpu])
|
||||
munmap(page_virt[cpu], PAGE_SIZE);
|
||||
v = mmap(
|
||||
NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd,
|
||||
map_mtop_offset(page_phys[cpu]));
|
||||
if (v == MAP_FAILED) {
|
||||
printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, vtopti(va));
|
||||
page_phys[cpu] = 0;
|
||||
goto error_out;
|
||||
}
|
||||
printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, vtopti(va));
|
||||
page_phys[cpu] = 0;
|
||||
goto error_out;
|
||||
}
|
||||
page_virt[cpu] = v;
|
||||
}
|
||||
}
|
||||
return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
|
||||
|
||||
error_out:
|
||||
@@ -181,37 +175,37 @@ xc_waitdomain_core(int domfd, int *status, int options)
|
||||
|
||||
if (nr_pages == 0) {
|
||||
|
||||
if (read(domfd, &header, sizeof(header)) != sizeof(header))
|
||||
return -1;
|
||||
if (read(domfd, &header, sizeof(header)) != sizeof(header))
|
||||
return -1;
|
||||
|
||||
nr_pages = header.xch_nr_pages;
|
||||
nr_vcpus = header.xch_nr_vcpus;
|
||||
pages_offset = header.xch_pages_offset;
|
||||
nr_pages = header.xch_nr_pages;
|
||||
nr_vcpus = header.xch_nr_vcpus;
|
||||
pages_offset = header.xch_pages_offset;
|
||||
|
||||
if (read(domfd, ctxt, sizeof(vcpu_guest_context_t)*nr_vcpus) !=
|
||||
sizeof(vcpu_guest_context_t)*nr_vcpus)
|
||||
return -1;
|
||||
if (read(domfd, ctxt, sizeof(vcpu_guest_context_t)*nr_vcpus) !=
|
||||
sizeof(vcpu_guest_context_t)*nr_vcpus)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < nr_vcpus; i++) {
|
||||
cr3[i] = ctxt[i].ctrlreg[3];
|
||||
}
|
||||
if ((p2m_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
|
||||
printf("Could not allocate p2m_array\n");
|
||||
goto error_out;
|
||||
}
|
||||
if (read(domfd, p2m_array, sizeof(unsigned long)*nr_pages) !=
|
||||
sizeof(unsigned long)*nr_pages)
|
||||
return -1;
|
||||
for (i = 0; i < nr_vcpus; i++) {
|
||||
cr3[i] = ctxt[i].ctrlreg[3];
|
||||
}
|
||||
if ((p2m_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
|
||||
printf("Could not allocate p2m_array\n");
|
||||
goto error_out;
|
||||
}
|
||||
if (read(domfd, p2m_array, sizeof(unsigned long)*nr_pages) !=
|
||||
sizeof(unsigned long)*nr_pages)
|
||||
return -1;
|
||||
|
||||
if ((m2p_array = malloc((1<<20) * sizeof(unsigned long))) == NULL) {
|
||||
printf("Could not allocate m2p array\n");
|
||||
goto error_out;
|
||||
}
|
||||
bzero(m2p_array, sizeof(unsigned long)* 1 << 20);
|
||||
if ((m2p_array = malloc((1<<20) * sizeof(unsigned long))) == NULL) {
|
||||
printf("Could not allocate m2p array\n");
|
||||
goto error_out;
|
||||
}
|
||||
bzero(m2p_array, sizeof(unsigned long)* 1 << 20);
|
||||
|
||||
for (i = 0; i < nr_pages; i++) {
|
||||
m2p_array[p2m_array[i]] = i;
|
||||
}
|
||||
for (i = 0; i < nr_pages; i++) {
|
||||
m2p_array[p2m_array[i]] = i;
|
||||
}
|
||||
|
||||
}
|
||||
retval = 0;
|
||||
@@ -234,38 +228,38 @@ xc_ptrace_core(enum __ptrace_request request, u32 domfd, long eaddr, long edata)
|
||||
#if 0
|
||||
printf("%20s %d, %p, %p \n", ptrace_names[request], domid, addr, data);
|
||||
#endif
|
||||
switch (request) {
|
||||
switch (request) {
|
||||
case PTRACE_PEEKTEXT:
|
||||
case PTRACE_PEEKDATA:
|
||||
if ((guest_va = (unsigned long *)map_domain_va(domfd, cpu, addr)) == NULL) {
|
||||
status = EFAULT;
|
||||
goto error_out;
|
||||
}
|
||||
if ((guest_va = (unsigned long *)map_domain_va(domfd, cpu, addr)) == NULL) {
|
||||
status = EFAULT;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
retval = *guest_va;
|
||||
break;
|
||||
retval = *guest_va;
|
||||
break;
|
||||
case PTRACE_POKETEXT:
|
||||
case PTRACE_POKEDATA:
|
||||
if ((guest_va = (unsigned long *)map_domain_va(domfd, cpu, addr)) == NULL) {
|
||||
status = EFAULT;
|
||||
goto error_out;
|
||||
}
|
||||
*guest_va = (unsigned long)data;
|
||||
break;
|
||||
if ((guest_va = (unsigned long *)map_domain_va(domfd, cpu, addr)) == NULL) {
|
||||
status = EFAULT;
|
||||
goto error_out;
|
||||
}
|
||||
*guest_va = (unsigned long)data;
|
||||
break;
|
||||
case PTRACE_GETREGS:
|
||||
case PTRACE_GETFPREGS:
|
||||
case PTRACE_GETFPXREGS:
|
||||
if (request == PTRACE_GETREGS) {
|
||||
SET_PT_REGS(pt, ctxt[cpu].user_regs);
|
||||
memcpy(data, &pt, sizeof(struct gdb_regs));
|
||||
} else if (request == PTRACE_GETFPREGS)
|
||||
memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
|
||||
else /*if (request == PTRACE_GETFPXREGS)*/
|
||||
memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
|
||||
break;
|
||||
if (request == PTRACE_GETREGS) {
|
||||
SET_PT_REGS(pt, ctxt[cpu].user_regs);
|
||||
memcpy(data, &pt, sizeof(struct gdb_regs));
|
||||
} else if (request == PTRACE_GETFPREGS)
|
||||
memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
|
||||
else /*if (request == PTRACE_GETFPXREGS)*/
|
||||
memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
|
||||
break;
|
||||
case PTRACE_ATTACH:
|
||||
retval = 0;
|
||||
break;
|
||||
retval = 0;
|
||||
break;
|
||||
case PTRACE_SETREGS:
|
||||
case PTRACE_SINGLESTEP:
|
||||
case PTRACE_CONT:
|
||||
@@ -277,19 +271,29 @@ xc_ptrace_core(enum __ptrace_request request, u32 domfd, long eaddr, long edata)
|
||||
case PTRACE_SYSCALL:
|
||||
case PTRACE_KILL:
|
||||
#ifdef DEBUG
|
||||
printf("unsupported xc_ptrace request %s\n", ptrace_names[request]);
|
||||
printf("unsupported xc_ptrace request %s\n", ptrace_names[request]);
|
||||
#endif
|
||||
status = ENOSYS;
|
||||
break;
|
||||
status = ENOSYS;
|
||||
break;
|
||||
case PTRACE_TRACEME:
|
||||
printf("PTRACE_TRACEME is an invalid request under Xen\n");
|
||||
status = EINVAL;
|
||||
printf("PTRACE_TRACEME is an invalid request under Xen\n");
|
||||
status = EINVAL;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
errno = status;
|
||||
retval = -1;
|
||||
errno = status;
|
||||
retval = -1;
|
||||
}
|
||||
error_out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
+167
-150
@@ -109,9 +109,9 @@ static void build_e820map(struct mem_map *mem_mapp, unsigned long mem_size)
|
||||
|
||||
#ifdef __i386__
|
||||
static int zap_mmio_range(int xc_handle, u32 dom,
|
||||
l2_pgentry_32_t *vl2tab,
|
||||
unsigned long mmio_range_start,
|
||||
unsigned long mmio_range_size)
|
||||
l2_pgentry_32_t *vl2tab,
|
||||
unsigned long mmio_range_start,
|
||||
unsigned long mmio_range_size)
|
||||
{
|
||||
unsigned long mmio_addr;
|
||||
unsigned long mmio_range_end = mmio_range_start + mmio_range_size;
|
||||
@@ -123,12 +123,14 @@ static int zap_mmio_range(int xc_handle, u32 dom,
|
||||
vl2e = vl2tab[l2_table_offset(mmio_addr)];
|
||||
if (vl2e == 0)
|
||||
continue;
|
||||
vl1tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE, vl2e >> PAGE_SHIFT);
|
||||
if (vl1tab == 0) {
|
||||
PERROR("Failed zap MMIO range");
|
||||
return -1;
|
||||
}
|
||||
vl1tab = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE, vl2e >> PAGE_SHIFT);
|
||||
if ( vl1tab == 0 )
|
||||
{
|
||||
PERROR("Failed zap MMIO range");
|
||||
return -1;
|
||||
}
|
||||
vl1tab[l1_table_offset(mmio_addr)] = 0;
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
}
|
||||
@@ -136,114 +138,118 @@ static int zap_mmio_range(int xc_handle, u32 dom,
|
||||
}
|
||||
|
||||
static int zap_mmio_ranges(int xc_handle, u32 dom,
|
||||
unsigned long l2tab,
|
||||
struct mem_map *mem_mapp)
|
||||
unsigned long l2tab,
|
||||
struct mem_map *mem_mapp)
|
||||
{
|
||||
int i;
|
||||
l2_pgentry_32_t *vl2tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
l2tab >> PAGE_SHIFT);
|
||||
if (vl2tab == 0)
|
||||
return -1;
|
||||
for (i = 0; i < mem_mapp->nr_map; i++) {
|
||||
if ((mem_mapp->map[i].type == E820_IO)
|
||||
&& (mem_mapp->map[i].caching_attr == MEMMAP_UC))
|
||||
if (zap_mmio_range(xc_handle, dom, vl2tab,
|
||||
mem_mapp->map[i].addr, mem_mapp->map[i].size) == -1)
|
||||
return -1;
|
||||
PROT_READ|PROT_WRITE,
|
||||
l2tab >> PAGE_SHIFT);
|
||||
if ( vl2tab == 0 )
|
||||
return -1;
|
||||
|
||||
for ( i = 0; i < mem_mapp->nr_map; i++ )
|
||||
{
|
||||
if ( (mem_mapp->map[i].type == E820_IO) &&
|
||||
(mem_mapp->map[i].caching_attr == MEMMAP_UC) &&
|
||||
(zap_mmio_range(xc_handle, dom, vl2tab,
|
||||
mem_mapp->map[i].addr,
|
||||
mem_mapp->map[i].size) == -1) )
|
||||
return -1;
|
||||
}
|
||||
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int zap_mmio_range(int xc_handle, u32 dom,
|
||||
l3_pgentry_t *vl3tab,
|
||||
unsigned long mmio_range_start,
|
||||
unsigned long mmio_range_size)
|
||||
l3_pgentry_t *vl3tab,
|
||||
unsigned long mmio_range_start,
|
||||
unsigned long mmio_range_size)
|
||||
{
|
||||
unsigned long mmio_addr;
|
||||
unsigned long mmio_range_end = mmio_range_start + mmio_range_size;
|
||||
unsigned long vl2e = 0;
|
||||
unsigned long vl3e;
|
||||
l1_pgentry_t *vl1tab;
|
||||
l2_pgentry_t *vl2tab;
|
||||
unsigned long mmio_addr;
|
||||
unsigned long mmio_range_end = mmio_range_start + mmio_range_size;
|
||||
unsigned long vl2e = 0;
|
||||
unsigned long vl3e;
|
||||
l1_pgentry_t *vl1tab;
|
||||
l2_pgentry_t *vl2tab;
|
||||
|
||||
mmio_addr = mmio_range_start & PAGE_MASK;
|
||||
for ( ; mmio_addr < mmio_range_end; mmio_addr += PAGE_SIZE )
|
||||
{
|
||||
vl3e = vl3tab[l3_table_offset(mmio_addr)];
|
||||
if ( vl3e == 0 )
|
||||
continue;
|
||||
mmio_addr = mmio_range_start & PAGE_MASK;
|
||||
for ( ; mmio_addr < mmio_range_end; mmio_addr += PAGE_SIZE )
|
||||
{
|
||||
vl3e = vl3tab[l3_table_offset(mmio_addr)];
|
||||
if ( vl3e == 0 )
|
||||
continue;
|
||||
|
||||
vl2tab = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, vl3e>>PAGE_SHIFT);
|
||||
if ( vl2tab == NULL )
|
||||
{
|
||||
PERROR("Failed zap MMIO range");
|
||||
return -1;
|
||||
}
|
||||
vl2tab = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, vl3e>>PAGE_SHIFT);
|
||||
if ( vl2tab == NULL )
|
||||
{
|
||||
PERROR("Failed zap MMIO range");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vl2e = vl2tab[l2_table_offset(mmio_addr)];
|
||||
if ( vl2e == 0 )
|
||||
{
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
continue;
|
||||
}
|
||||
vl2e = vl2tab[l2_table_offset(mmio_addr)];
|
||||
if ( vl2e == 0 )
|
||||
{
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
continue;
|
||||
}
|
||||
|
||||
vl1tab = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, vl2e>>PAGE_SHIFT);
|
||||
if ( vl1tab == NULL )
|
||||
{
|
||||
PERROR("Failed zap MMIO range");
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
return -1;
|
||||
}
|
||||
vl1tab = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, vl2e>>PAGE_SHIFT);
|
||||
if ( vl1tab == NULL )
|
||||
{
|
||||
PERROR("Failed zap MMIO range");
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vl1tab[l1_table_offset(mmio_addr)] = 0;
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
}
|
||||
return 0;
|
||||
vl1tab[l1_table_offset(mmio_addr)] = 0;
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zap_mmio_ranges(int xc_handle, u32 dom,
|
||||
unsigned long l3tab,
|
||||
struct mem_map *mem_mapp)
|
||||
{
|
||||
int i;
|
||||
l3_pgentry_t *vl3tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
l3tab >> PAGE_SHIFT);
|
||||
if (vl3tab == 0)
|
||||
return -1;
|
||||
for (i = 0; i < mem_mapp->nr_map; i++) {
|
||||
if ((mem_mapp->map[i].type == E820_IO)
|
||||
&& (mem_mapp->map[i].caching_attr == MEMMAP_UC))
|
||||
if (zap_mmio_range(xc_handle, dom, vl3tab,
|
||||
mem_mapp->map[i].addr, mem_mapp->map[i].size) == -1)
|
||||
return -1;
|
||||
}
|
||||
munmap(vl3tab, PAGE_SIZE);
|
||||
return 0;
|
||||
int i;
|
||||
l3_pgentry_t *vl3tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
l3tab >> PAGE_SHIFT);
|
||||
if (vl3tab == 0)
|
||||
return -1;
|
||||
for (i = 0; i < mem_mapp->nr_map; i++) {
|
||||
if ((mem_mapp->map[i].type == E820_IO)
|
||||
&& (mem_mapp->map[i].caching_attr == MEMMAP_UC))
|
||||
if (zap_mmio_range(xc_handle, dom, vl3tab,
|
||||
mem_mapp->map[i].addr, mem_mapp->map[i].size) == -1)
|
||||
return -1;
|
||||
}
|
||||
munmap(vl3tab, PAGE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int setup_guest(int xc_handle,
|
||||
u32 dom, int memsize,
|
||||
char *image, unsigned long image_size,
|
||||
gzFile initrd_gfd, unsigned long initrd_len,
|
||||
unsigned long nr_pages,
|
||||
vcpu_guest_context_t *ctxt,
|
||||
const char *cmdline,
|
||||
unsigned long shared_info_frame,
|
||||
unsigned int control_evtchn,
|
||||
unsigned long flags,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn,
|
||||
struct mem_map *mem_mapp
|
||||
)
|
||||
u32 dom, int memsize,
|
||||
char *image, unsigned long image_size,
|
||||
gzFile initrd_gfd, unsigned long initrd_len,
|
||||
unsigned long nr_pages,
|
||||
vcpu_guest_context_t *ctxt,
|
||||
const char *cmdline,
|
||||
unsigned long shared_info_frame,
|
||||
unsigned int control_evtchn,
|
||||
unsigned long flags,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn,
|
||||
struct mem_map *mem_mapp
|
||||
)
|
||||
{
|
||||
l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
|
||||
l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
|
||||
@@ -303,7 +309,8 @@ static int setup_guest(int xc_handle,
|
||||
|
||||
/* memsize is in megabytes */
|
||||
v_end = memsize << 20;
|
||||
vinitrd_end = v_end - PAGE_SIZE; /* leaving the top 4k untouched for IO requests page use */
|
||||
/* leaving the top 4k untouched for IO requests page use */
|
||||
vinitrd_end = v_end - PAGE_SIZE;
|
||||
vinitrd_start = vinitrd_end - initrd_len;
|
||||
vinitrd_start = vinitrd_start & (~(PAGE_SIZE - 1));
|
||||
|
||||
@@ -369,7 +376,7 @@ static int setup_guest(int xc_handle,
|
||||
goto error_out;
|
||||
}
|
||||
xc_copy_to_domain_page(xc_handle, dom,
|
||||
page_array[i>>PAGE_SHIFT], page);
|
||||
page_array[i>>PAGE_SHIFT], page);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,14 +387,14 @@ static int setup_guest(int xc_handle,
|
||||
ppt_alloc = (vpt_start - dsi.v_start) >> PAGE_SHIFT;
|
||||
if ( page_array[ppt_alloc] > 0xfffff )
|
||||
{
|
||||
unsigned long nmfn;
|
||||
nmfn = xc_make_page_below_4G( xc_handle, dom, page_array[ppt_alloc] );
|
||||
if ( nmfn == 0 )
|
||||
{
|
||||
fprintf(stderr, "Couldn't get a page below 4GB :-(\n");
|
||||
goto error_out;
|
||||
}
|
||||
page_array[ppt_alloc] = nmfn;
|
||||
unsigned long nmfn;
|
||||
nmfn = xc_make_page_below_4G( xc_handle, dom, page_array[ppt_alloc] );
|
||||
if ( nmfn == 0 )
|
||||
{
|
||||
fprintf(stderr, "Couldn't get a page below 4GB :-(\n");
|
||||
goto error_out;
|
||||
}
|
||||
page_array[ppt_alloc] = nmfn;
|
||||
}
|
||||
|
||||
#ifdef __i386__
|
||||
@@ -448,8 +455,8 @@ static int setup_guest(int xc_handle,
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
|
||||
if ( (vl2tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
l2tab >> PAGE_SHIFT)) == NULL )
|
||||
PROT_READ|PROT_WRITE,
|
||||
l2tab >> PAGE_SHIFT)) == NULL )
|
||||
goto error_out;
|
||||
|
||||
memset(vl2tab, 0, PAGE_SIZE);
|
||||
@@ -462,8 +469,8 @@ static int setup_guest(int xc_handle,
|
||||
if ( vl1tab != NULL )
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
if ( (vl1tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
l1tab >> PAGE_SHIFT)) == NULL )
|
||||
PROT_READ|PROT_WRITE,
|
||||
l1tab >> PAGE_SHIFT)) == NULL )
|
||||
{
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
goto error_out;
|
||||
@@ -485,15 +492,15 @@ static int setup_guest(int xc_handle,
|
||||
for ( count = 0; count < nr_pages; count++ )
|
||||
{
|
||||
if ( xc_add_mmu_update(xc_handle, mmu,
|
||||
(page_array[count] << PAGE_SHIFT) |
|
||||
MMU_MACHPHYS_UPDATE, count) )
|
||||
goto error_out;
|
||||
(page_array[count] << PAGE_SHIFT) |
|
||||
MMU_MACHPHYS_UPDATE, count) )
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
|
||||
if ((boot_paramsp = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[(vboot_params_start-dsi.v_start)>>PAGE_SHIFT])) == 0)
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[(vboot_params_start-dsi.v_start)>>PAGE_SHIFT])) == 0)
|
||||
goto error_out;
|
||||
|
||||
memset(boot_paramsp, 0, sizeof(*boot_paramsp));
|
||||
@@ -558,9 +565,9 @@ static int setup_guest(int xc_handle,
|
||||
#if defined (__i386__)
|
||||
if (zap_mmio_ranges(xc_handle, dom, l2tab, mem_mapp) == -1)
|
||||
#else
|
||||
if (zap_mmio_ranges(xc_handle, dom, l3tab, mem_mapp) == -1)
|
||||
if (zap_mmio_ranges(xc_handle, dom, l3tab, mem_mapp) == -1)
|
||||
#endif
|
||||
goto error_out;
|
||||
goto error_out;
|
||||
boot_paramsp->e820_map_nr = mem_mapp->nr_map;
|
||||
for (i=0; i<mem_mapp->nr_map; i++) {
|
||||
boot_paramsp->e820_map[i].addr = mem_mapp->map[i].addr;
|
||||
@@ -572,9 +579,9 @@ static int setup_guest(int xc_handle,
|
||||
munmap(boot_paramsp, PAGE_SIZE);
|
||||
|
||||
if ((boot_gdtp = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[(vboot_gdt_start-dsi.v_start)>>PAGE_SHIFT])) == 0)
|
||||
goto error_out;
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[(vboot_gdt_start-dsi.v_start)>>PAGE_SHIFT])) == 0)
|
||||
goto error_out;
|
||||
memset(boot_gdtp, 0, PAGE_SIZE);
|
||||
boot_gdtp[12*4 + 0] = boot_gdtp[13*4 + 0] = 0xffff; /* limit */
|
||||
boot_gdtp[12*4 + 1] = boot_gdtp[13*4 + 1] = 0x0000; /* base */
|
||||
@@ -584,9 +591,9 @@ static int setup_guest(int xc_handle,
|
||||
|
||||
/* shared_info page starts its life empty. */
|
||||
if ((shared_info = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
shared_info_frame)) == 0)
|
||||
goto error_out;
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
shared_info_frame)) == 0)
|
||||
goto error_out;
|
||||
memset(shared_info, 0, sizeof(shared_info_t));
|
||||
/* Mask all upcalls... */
|
||||
for ( i = 0; i < MAX_VIRT_CPUS; i++ )
|
||||
@@ -595,9 +602,9 @@ static int setup_guest(int xc_handle,
|
||||
|
||||
/* Populate the event channel port in the shared page */
|
||||
if ((sp = (shared_iopage_t *) xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[shared_page_frame])) == 0)
|
||||
goto error_out;
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[shared_page_frame])) == 0)
|
||||
goto error_out;
|
||||
memset(sp, 0, PAGE_SIZE);
|
||||
sp->sp_global.eport = control_evtchn;
|
||||
munmap(sp, PAGE_SIZE);
|
||||
@@ -622,7 +629,7 @@ static int setup_guest(int xc_handle,
|
||||
ctxt->user_regs.edx = vboot_gdt_start;
|
||||
ctxt->user_regs.eax = 0x800;
|
||||
ctxt->user_regs.esp = vboot_gdt_end;
|
||||
ctxt->user_regs.ebx = 0; /* startup_32 expects this to be 0 to signal boot cpu */
|
||||
ctxt->user_regs.ebx = 0; /* startup_32 expects this to be 0 to signal boot cpu */
|
||||
ctxt->user_regs.ecx = mem_mapp->nr_map;
|
||||
ctxt->user_regs.esi = vboot_params_start;
|
||||
ctxt->user_regs.edi = vboot_params_start + 0x2d0;
|
||||
@@ -646,9 +653,9 @@ static int vmx_identify(void)
|
||||
|
||||
#ifdef __i386__
|
||||
__asm__ __volatile__ ("pushl %%ebx; cpuid; popl %%ebx"
|
||||
: "=a" (eax), "=c" (ecx)
|
||||
: "0" (1)
|
||||
: "dx");
|
||||
: "=a" (eax), "=c" (ecx)
|
||||
: "0" (1)
|
||||
: "dx");
|
||||
#elif defined __x86_64__
|
||||
__asm__ __volatile__ ("pushq %%rbx; cpuid; popq %%rbx"
|
||||
: "=a" (eax), "=c" (ecx)
|
||||
@@ -663,17 +670,17 @@ static int vmx_identify(void)
|
||||
}
|
||||
|
||||
int xc_vmx_build(int xc_handle,
|
||||
u32 domid,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
struct mem_map *mem_mapp,
|
||||
const char *ramdisk_name,
|
||||
const char *cmdline,
|
||||
unsigned int control_evtchn,
|
||||
unsigned long flags,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
u32 domid,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
struct mem_map *mem_mapp,
|
||||
const char *ramdisk_name,
|
||||
const char *cmdline,
|
||||
unsigned int control_evtchn,
|
||||
unsigned long flags,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
{
|
||||
dom0_op_t launch_op, op;
|
||||
int initrd_fd = -1;
|
||||
@@ -745,11 +752,11 @@ int xc_vmx_build(int xc_handle,
|
||||
}
|
||||
|
||||
if ( setup_guest(xc_handle, domid, memsize, image, image_size,
|
||||
initrd_gfd, initrd_size, nr_pages,
|
||||
ctxt, cmdline,
|
||||
op.u.getdomaininfo.shared_info_frame,
|
||||
control_evtchn, flags, vcpus, store_evtchn, store_mfn,
|
||||
mem_mapp) < 0 )
|
||||
initrd_gfd, initrd_size, nr_pages,
|
||||
ctxt, cmdline,
|
||||
op.u.getdomaininfo.shared_info_frame,
|
||||
control_evtchn, flags, vcpus, store_evtchn, store_mfn,
|
||||
mem_mapp) < 0 )
|
||||
{
|
||||
ERROR("Error constructing guest OS");
|
||||
goto error_out;
|
||||
@@ -780,8 +787,8 @@ int xc_vmx_build(int xc_handle,
|
||||
|
||||
/* Ring 1 stack is the initial stack. */
|
||||
/*
|
||||
ctxt->kernel_ss = FLAT_KERNEL_DS;
|
||||
ctxt->kernel_sp = vstartinfo_start;
|
||||
ctxt->kernel_ss = FLAT_KERNEL_DS;
|
||||
ctxt->kernel_sp = vstartinfo_start;
|
||||
*/
|
||||
/* No debugging. */
|
||||
memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
|
||||
@@ -861,7 +868,7 @@ static int parseelfimage(char *elfbase,
|
||||
return -EINVAL;
|
||||
}
|
||||
shdr = (Elf32_Shdr *)(elfbase + ehdr->e_shoff +
|
||||
(ehdr->e_shstrndx*ehdr->e_shentsize));
|
||||
(ehdr->e_shstrndx*ehdr->e_shentsize));
|
||||
shstrtab = elfbase + shdr->sh_offset;
|
||||
|
||||
for ( h = 0; h < ehdr->e_phnum; h++ )
|
||||
@@ -916,9 +923,9 @@ loadelfimage(
|
||||
{
|
||||
pa = (phdr->p_paddr + done) - dsi->v_start - LINUX_PAGE_OFFSET;
|
||||
if ((va = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_WRITE,
|
||||
parray[pa>>PAGE_SHIFT])) == 0)
|
||||
return -1;
|
||||
xch, dom, PAGE_SIZE, PROT_WRITE,
|
||||
parray[pa>>PAGE_SHIFT])) == 0)
|
||||
return -1;
|
||||
chunksz = phdr->p_filesz - done;
|
||||
if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
|
||||
chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
|
||||
@@ -931,9 +938,9 @@ loadelfimage(
|
||||
{
|
||||
pa = (phdr->p_paddr + done) - dsi->v_start - LINUX_PAGE_OFFSET;
|
||||
if ((va = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_WRITE,
|
||||
parray[pa>>PAGE_SHIFT])) == 0)
|
||||
return -1;
|
||||
xch, dom, PAGE_SIZE, PROT_WRITE,
|
||||
parray[pa>>PAGE_SHIFT])) == 0)
|
||||
return -1;
|
||||
chunksz = phdr->p_memsz - done;
|
||||
if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
|
||||
chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
|
||||
@@ -944,3 +951,13 @@ loadelfimage(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||