Apply patch from Jed Davis, posted to port-xen:
In pmap_remap_pages() new mappings are created (PG_RW|PG_M). When saving a domain, the hypervisor will refuse to map the foreing pages RW. As a temporary measure, retry the mapping read-only if PG_RW fails, so that domain save will work. Also fix the PTP's wire_count if the MMU update fails (prevent a kernel panic).
This commit is contained in:
parent
7558bd0a7c
commit
8dfe5bc813
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: pmap.c,v 1.12 2005/05/29 15:57:02 chs Exp $ */
|
/* $NetBSD: pmap.c,v 1.13 2005/09/10 15:46:04 bouyer Exp $ */
|
||||||
/* NetBSD: pmap.c,v 1.179 2004/10/10 09:55:24 yamt Exp */
|
/* NetBSD: pmap.c,v 1.179 2004/10/10 09:55:24 yamt Exp */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.12 2005/05/29 15:57:02 chs Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.13 2005/09/10 15:46:04 bouyer Exp $");
|
||||||
|
|
||||||
#include "opt_cputype.h"
|
#include "opt_cputype.h"
|
||||||
#include "opt_user_ldt.h"
|
#include "opt_user_ldt.h"
|
||||||
|
@ -4064,7 +4064,9 @@ pmap_remap_pages(pmap, va, pa, npages, flags, dom)
|
||||||
struct vm_page_md *mdpg;
|
struct vm_page_md *mdpg;
|
||||||
struct pv_head *old_pvh;
|
struct pv_head *old_pvh;
|
||||||
struct pv_entry *pve = NULL; /* XXX gcc */
|
struct pv_entry *pve = NULL; /* XXX gcc */
|
||||||
int error;
|
int error, dptpwire;
|
||||||
|
|
||||||
|
dptpwire = 0;
|
||||||
|
|
||||||
XENPRINTK(("pmap_remap_pages(%p, %p, %p, %d, %08x, %d)\n",
|
XENPRINTK(("pmap_remap_pages(%p, %p, %p, %d, %08x, %d)\n",
|
||||||
pmap, (void *)va, (void *)pa, npages, flags, dom));
|
pmap, (void *)va, (void *)pa, npages, flags, dom));
|
||||||
|
@ -4230,13 +4232,36 @@ pmap_remap_pages(pmap, va, pa, npages, flags, dom)
|
||||||
} else {
|
} else {
|
||||||
pmap->pm_stats.resident_count++;
|
pmap->pm_stats.resident_count++;
|
||||||
pmap->pm_stats.wired_count++;
|
pmap->pm_stats.wired_count++;
|
||||||
if (ptp)
|
if (ptp) {
|
||||||
|
dptpwire = 1;
|
||||||
ptp->wire_count++;
|
ptp->wire_count++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//printf("pmap initial setup");
|
//printf("pmap initial setup");
|
||||||
maptp = (pt_entry_t *)vtomach((vaddr_t)&ptes[x86_btop(va)]);
|
maptp = (pt_entry_t *)vtomach((vaddr_t)&ptes[x86_btop(va)]);
|
||||||
|
change_pte:
|
||||||
error = xpq_update_foreign(maptp, npte, dom);
|
error = xpq_update_foreign(maptp, npte, dom);
|
||||||
|
if (error) {
|
||||||
|
if (npte & PG_RW) {
|
||||||
|
/*
|
||||||
|
* XXXjld@panix.com: Some things cannot be
|
||||||
|
* mapped read/write, even by a privileged
|
||||||
|
* domain. This wouldn't be necessary if
|
||||||
|
* pmap_remap_pages had a "prot" parameter
|
||||||
|
* like pmap_enter does.
|
||||||
|
*/
|
||||||
|
npte &= ~(PG_RW | PG_M);
|
||||||
|
//printf("pmap_remap_pages: losing write bit npte=%lx\n", (unsigned long)npte);
|
||||||
|
goto change_pte;
|
||||||
|
}
|
||||||
|
printf("pmap_remap_pages: xpq_update_foreign failed va=%lx"
|
||||||
|
" npte=%lx error=%d dptpwire=%d\n",
|
||||||
|
va, (unsigned long)npte, error, dptpwire);
|
||||||
|
ptp->wire_count -= dptpwire;
|
||||||
|
/* XXX fix other stats? */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
shootdown_test:
|
shootdown_test:
|
||||||
/* Update page attributes if needed */
|
/* Update page attributes if needed */
|
||||||
|
|
Loading…
Reference in New Issue