Change the location of the shared_info page for auto_translated_physmap guests.

Instead of putting the page outside of the guests pseudo-physical address
space, we put it next to the other pages filled by the domain builder,
such that the page is already mapped in the initial pagetables and/or a
lowmem-type memory mapping.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
This commit is contained in:
cl349@firebug.cl.cam.ac.uk committed 2006-03-09 16:24:57 +00:00
1 parent fd5de61bb8
commit e2b8c75165
9 files changed
+201 -106

No files matched your search

+9 -4
View File
@@ -556,10 +556,15 @@ void __init paging_init(void)
kmap_init();
/* Switch to the real shared_info page, and clear the dummy page. */
set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
memset(empty_zero_page, 0, sizeof(empty_zero_page));
if (!xen_feature(XENFEAT_auto_translated_physmap) ||
xen_start_info->shared_info >= xen_start_info->nr_pages) {
/* Switch to the real shared_info page, and clear the
* dummy page. */
set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
HYPERVISOR_shared_info =
(shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
memset(empty_zero_page, 0, sizeof(empty_zero_page));
}
/* Setup mapping of lower 1st MB */
for (i = 0; i < NR_FIX_ISAMAPS; i++)
@@ -664,6 +664,13 @@ void __init setup_arch(char **cmdline_p)
setup_xen_features();
if (xen_feature(XENFEAT_auto_translated_physmap) &&
xen_start_info->shared_info < xen_start_info->nr_pages) {
HYPERVISOR_shared_info =
(shared_info_t *)__va(xen_start_info->shared_info);
memset(empty_zero_page, 0, sizeof(empty_zero_page));
}
HYPERVISOR_vm_assist(VMASST_CMD_enable,
VMASST_TYPE_writable_pagetables);
@@ -757,10 +757,16 @@ void __init paging_init(void)
free_area_init_node(0, NODE_DATA(0), zones,
__pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
if (!xen_feature(XENFEAT_auto_translated_physmap) ||
xen_start_info->shared_info >= xen_start_info->nr_pages) {
/* Switch to the real shared_info page, and clear the
* dummy page. */
set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
HYPERVISOR_shared_info =
(shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
memset(empty_zero_page, 0, sizeof(empty_zero_page));
}
memset(empty_zero_page, 0, sizeof(empty_zero_page));
init_mm.context.pinned = 1;
/* Setup mapping of lower 1st MB */
@@ -37,6 +37,13 @@ static void __init machine_specific_arch_setup(void)
struct xen_platform_parameters pp;
struct xennmi_callback cb;
if (xen_feature(XENFEAT_auto_translated_physmap) &&
xen_start_info->shared_info < xen_start_info->nr_pages) {
HYPERVISOR_shared_info =
(shared_info_t *)__va(xen_start_info->shared_info);
memset(empty_zero_page, 0, sizeof(empty_zero_page));
}
HYPERVISOR_set_callbacks(
__KERNEL_CS, (unsigned long)hypervisor_callback,
__KERNEL_CS, (unsigned long)failsafe_callback);
+72 -67
View File
@@ -606,15 +606,11 @@ static int setup_guest(int xc_handle,
struct load_funcs load_funcs;
struct domain_setup_info dsi;
unsigned long vinitrd_start;
unsigned long vinitrd_end;
unsigned long vphysmap_start;
unsigned long vphysmap_end;
unsigned long vstartinfo_start;
unsigned long vstartinfo_end;
unsigned long vstoreinfo_start;
unsigned long vstoreinfo_end;
unsigned long vconsole_start;
unsigned long vconsole_end;
unsigned long vsharedinfo_start = 0; /* XXX gcc */
unsigned long vstack_start;
unsigned long vstack_end;
unsigned long vpt_start;
@@ -640,6 +636,34 @@ static int setup_guest(int xc_handle,
goto error_out;
}
/* Parse and validate kernel features. */
p = strstr(dsi.xen_guest_string, "FEATURES=");
if ( p != NULL )
{
if ( !parse_features(p + strlen("FEATURES="),
supported_features,
required_features) )
{
ERROR("Failed to parse guest kernel features.\n");
goto error_out;
}
printf("Supported features = { %08x }.\n", supported_features[0]);
printf("Required features = { %08x }.\n", required_features[0]);
}
for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ )
{
if ( (supported_features[i]&required_features[i]) != required_features[i] )
{
ERROR("Guest kernel does not support a required feature.\n");
goto error_out;
}
}
shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap,
required_features);
/*
* Why do we need this? The number of page-table frames depends on the
* size of the bootstrap address space. But the size of the address space
@@ -647,17 +671,22 @@ static int setup_guest(int xc_handle,
* read-only). We have a pair of simultaneous equations in two unknowns,
* which we solve by exhaustive search.
*/
vinitrd_start = round_pgup(dsi.v_end);
vinitrd_end = vinitrd_start + initrd->len;
vphysmap_start = round_pgup(vinitrd_end);
vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long));
vstartinfo_start = round_pgup(vphysmap_end);
vstartinfo_end = vstartinfo_start + PAGE_SIZE;
vstoreinfo_start = vstartinfo_end;
vstoreinfo_end = vstoreinfo_start + PAGE_SIZE;
vconsole_start = vstoreinfo_end;
vconsole_end = vconsole_start + PAGE_SIZE;
vpt_start = vconsole_end;
v_end = round_pgup(dsi.v_end);
vinitrd_start = v_end;
v_end += round_pgup(initrd->len);
vphysmap_start = v_end;
v_end += round_pgup(nr_pages * sizeof(unsigned long));
vstartinfo_start = v_end;
v_end += PAGE_SIZE;
vstoreinfo_start = v_end;
v_end += PAGE_SIZE;
vconsole_start = v_end;
v_end += PAGE_SIZE;
if ( shadow_mode_enabled ) {
vsharedinfo_start = v_end;
v_end += PAGE_SIZE;
}
vpt_start = v_end;
for ( nr_pt_pages = 2; ; nr_pt_pages++ )
{
@@ -697,26 +726,22 @@ static int setup_guest(int xc_handle,
#define _p(a) ((void *) (a))
printf("VIRTUAL MEMORY ARRANGEMENT:\n"
" Loaded kernel: %p->%p\n"
" Init. ramdisk: %p->%p\n"
" Phys-Mach map: %p->%p\n"
" Start info: %p->%p\n"
" Store page: %p->%p\n"
" Console page: %p->%p\n"
" Page tables: %p->%p\n"
" Boot stack: %p->%p\n"
" TOTAL: %p->%p\n",
_p(dsi.v_kernstart), _p(dsi.v_kernend),
_p(vinitrd_start), _p(vinitrd_end),
_p(vphysmap_start), _p(vphysmap_end),
_p(vstartinfo_start), _p(vstartinfo_end),
_p(vstoreinfo_start), _p(vstoreinfo_end),
_p(vconsole_start), _p(vconsole_end),
_p(vpt_start), _p(vpt_end),
_p(vstack_start), _p(vstack_end),
_p(dsi.v_start), _p(v_end));
printf(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
printf("VIRTUAL MEMORY ARRANGEMENT:\n");
printf(" Loaded kernel: %p->%p\n", _p(dsi.v_kernstart),
_p(dsi.v_kernend));
if ( initrd->len )
printf(" Initial ramdisk: %p->%p\n", _p(vinitrd_start),
_p(vinitrd_start + initrd->len));
printf(" Phys-Mach map: %p\n", _p(vphysmap_start));
printf(" Start info: %p\n", _p(vstartinfo_start));
printf(" Store page: %p\n", _p(vstoreinfo_start));
printf(" Console page: %p\n", _p(vconsole_start));
if ( shadow_mode_enabled )
printf(" Shared Info page: %p\n", _p(vsharedinfo_start));
printf(" Page tables: %p\n", _p(vpt_start));
printf(" Boot stack: %p\n", _p(vstack_start));
printf(" TOTAL: %p->%p\n", _p(dsi.v_start), _p(v_end));
printf(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
if ( ((v_end - dsi.v_start)>>PAGE_SHIFT) > nr_pages )
{
@@ -742,36 +767,6 @@ static int setup_guest(int xc_handle,
xc_handle, dom, page_array,
&dsi);
/* Parse and validate kernel features. */
p = strstr(dsi.xen_guest_string, "FEATURES=");
if ( p != NULL )
{
if ( !parse_features(p + strlen("FEATURES="),
supported_features,
required_features) )
{
ERROR("Failed to parse guest kernel features.\n");
goto error_out;
}
fprintf(stderr, "Supported features = { %08x }.\n",
supported_features[0]);
fprintf(stderr, "Required features = { %08x }.\n",
required_features[0]);
}
for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ )
{
if ( (supported_features[i]&required_features[i]) != required_features[i] )
{
ERROR("Guest kernel does not support a required feature.\n");
goto error_out;
}
}
shadow_mode_enabled = test_feature_bit(
XENFEAT_auto_translated_physmap, required_features);
if ( load_initrd(xc_handle, dom, initrd,
vinitrd_start - dsi.v_start, page_array) )
goto error_out;
@@ -869,6 +864,7 @@ static int setup_guest(int xc_handle,
if ( shadow_mode_enabled )
{
struct xen_reserved_phys_area xrpa;
struct xen_map_shared_info xmsi;
/* Enable shadow translate mode */
if ( xc_shadow_control(xc_handle, dom,
@@ -889,7 +885,16 @@ static int setup_guest(int xc_handle,
PERROR("Cannot find shared info pfn");
goto error_out;
}
guest_shared_info_mfn = xrpa.first_gpfn;
guest_shared_info_mfn = (vsharedinfo_start-dsi.v_start) >> PAGE_SHIFT;
xmsi.domid = dom;
xmsi.pfn = guest_shared_info_mfn;
rc = xc_memory_op(xc_handle, XENMEM_map_shared_info, &xmsi);
if ( rc != 0 )
{
PERROR("Cannot map shared info pfn");
goto error_out;
}
}
else
{
+41 -6
View File
@@ -2817,14 +2817,15 @@ long do_update_descriptor(u64 pa, u64 desc)
long arch_memory_op(int op, GUEST_HANDLE(void) arg)
{
struct xen_reserved_phys_area xrpa;
unsigned long pfn;
struct domain *d;
unsigned int i;
switch ( op )
{
case XENMEM_reserved_phys_area:
case XENMEM_reserved_phys_area: {
struct xen_reserved_phys_area xrpa;
if ( copy_from_guest(&xrpa, arg, 1) )
return -EFAULT;
@@ -2846,16 +2847,14 @@ long arch_memory_op(int op, GUEST_HANDLE(void) arg)
if ( d->arch.first_reserved_pfn == 0 )
{
d->arch.first_reserved_pfn = pfn = d->max_pages;
guest_physmap_add_page(
d, pfn + 0, virt_to_maddr(d->shared_info) >> PAGE_SHIFT);
for ( i = 0; i < NR_GRANT_FRAMES; i++ )
guest_physmap_add_page(
d, pfn + 1 + i, gnttab_shared_mfn(d, d->grant_table, i));
d, pfn + i, gnttab_shared_mfn(d, d->grant_table, i));
}
UNLOCK_BIGLOCK(d);
xrpa.first_gpfn = d->arch.first_reserved_pfn;
xrpa.nr_gpfns = 32;
xrpa.nr_gpfns = NR_GRANT_FRAMES;
put_domain(d);
@@ -2863,6 +2862,42 @@ long arch_memory_op(int op, GUEST_HANDLE(void) arg)
return -EFAULT;
break;
}
case XENMEM_map_shared_info: {
struct xen_map_shared_info xmsi;
if ( copy_from_guest(&xmsi, arg, 1) )
return -EFAULT;
if ( (d = find_domain_by_id(xmsi.domid)) == NULL )
return -ESRCH;
/* Only initialised translated guests can set the shared_info
* mapping. */
if ( !shadow_mode_translate(d) || (d->max_pages == 0) )
{
put_domain(d);
return -ESRCH;
}
if ( xmsi.pfn > d->max_pages ) {
put_domain(d);
return -EINVAL;
}
LOCK_BIGLOCK(d);
/* Remove previously mapped page if it was present. */
if ( mfn_valid(gmfn_to_mfn(d, xmsi.pfn)) )
guest_remove_page(d, xmsi.pfn);
guest_physmap_add_page(d, xmsi.pfn,
virt_to_maddr(d->shared_info) >> PAGE_SHIFT);
UNLOCK_BIGLOCK(d);
put_domain(d);
break;
}
default:
return subarch_memory_op(op, arg);
+39 -26
View File
@@ -137,7 +137,43 @@ populate_physmap(
out:
return i;
}
int
guest_remove_page(
struct domain *d,
unsigned long gmfn)
{
struct page_info *page;
unsigned long mfn;
mfn = gmfn_to_mfn(d, gmfn);
if ( unlikely(!mfn_valid(mfn)) )
{
DPRINTK("Domain %u page number %lx invalid\n",
d->domain_id, mfn);
return 0;
}
page = mfn_to_page(mfn);
if ( unlikely(!get_page(page, d)) )
{
DPRINTK("Bad page free for domain %u\n", d->domain_id);
return 0;
}
if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
put_page_and_type(page);
if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
put_page(page);
guest_physmap_remove_page(d, gmfn, mfn);
put_page(page);
return 1;
}
static long
decrease_reservation(
struct domain *d,
@@ -147,8 +183,7 @@ decrease_reservation(
unsigned int flags,
int *preempted)
{
struct page_info *page;
unsigned long i, j, gmfn, mfn;
unsigned long i, j, gmfn;
if ( !guest_handle_okay(extent_list, nr_extents) )
return 0;
@@ -166,30 +201,8 @@ decrease_reservation(
for ( j = 0; j < (1 << extent_order); j++ )
{
mfn = gmfn_to_mfn(d, gmfn + j);
if ( unlikely(!mfn_valid(mfn)) )
{
DPRINTK("Domain %u page number %lx invalid\n",
d->domain_id, mfn);
if ( !guest_remove_page(d, gmfn + j) )
return i;
}
page = mfn_to_page(mfn);
if ( unlikely(!get_page(page, d)) )
{
DPRINTK("Bad page free for domain %u\n", d->domain_id);
return i;
}
if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
put_page_and_type(page);
if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
put_page(page);
guest_physmap_remove_page(d, gmfn + j, mfn);
put_page(page);
}
}
+15
View File
@@ -140,6 +140,21 @@ typedef struct xen_translate_gpfn_list {
} xen_translate_gpfn_list_t;
DEFINE_GUEST_HANDLE(xen_translate_gpfn_list_t);
/*
* Sets the GPFN at which the shared_info_page appears in the specified
* guest's pseudophysical address space.
* arg == addr of xen_map_shared_info_t.
*/
#define XENMEM_map_shared_info 9
typedef struct xen_map_shared_info {
/* Which domain to change the mapping for. */
domid_t domid;
/* GPFN where the shared_info_page should appear. */
unsigned long pfn;
} xen_map_shared_info_t;
DEFINE_GUEST_HANDLE(xen_map_shared_info_t);
#endif /* __XEN_PUBLIC_MEMORY_H__ */
/*
+2
View File
@@ -82,4 +82,6 @@ extern struct list_head page_scrub_list;
#define sync_pagetable_state(d) ((void)0)
#endif
int guest_remove_page(struct domain *d, unsigned long gmfn);
#endif /* __XEN_MM_H__ */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.