diff -uNr xen-unstable.hg-orig/xen/arch/x86/mm/shadow/multi.c xen-unstable.hg-umptw/xen/arch/x86/mm/shadow/multi.c --- xen-unstable.hg-orig/xen/arch/x86/mm/shadow/multi.c 2008-07-22 18:37:51.000000000 +0100 +++ xen-unstable.hg-umptw/xen/arch/x86/mm/shadow/multi.c 2008-07-29 11:29:39.080673303 +0100 @@ -3359,7 +3359,7 @@ gdprintk(XENLOG_DEBUG, "guest attempted write to read-only memory" " page. va page=%#lx, mfn=%#lx\n", va & PAGE_MASK, mfn_x(gmfn)); - goto emulate; /* skip over the instruction */ + goto emulate_readonly; /* skip over the instruction */ } /* In HVM guests, we force CR0.WP always to be set, so that the @@ -3404,6 +3404,9 @@ goto done; } + /* Write from userspace to ro-mem needs to jump here to avoid getting + caught by user-mode page-table check above. */ + emulate_readonly: /* * We don't need to hold the lock for the whole emulation; we will * take it again when we write to the pagetables. @@ -4644,11 +4647,6 @@ unsigned long offset; void *map = NULL; - /* We don't emulate user-mode writes to page tables */ - sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt); - if ( sreg->attr.fields.dpl == 3 ) - return MAPPING_UNHANDLEABLE; - sh_ctxt->mfn1 = emulate_gva_to_mfn(v, vaddr, sh_ctxt); if ( !mfn_valid(sh_ctxt->mfn1) ) return ((mfn_x(sh_ctxt->mfn1) == BAD_GVA_TO_GFN) ? @@ -4656,6 +4654,16 @@ (mfn_x(sh_ctxt->mfn1) == READONLY_GFN) ? MAPPING_SILENT_FAIL : MAPPING_UNHANDLEABLE); +#ifndef NDEBUG + /* We don't emulate user-mode writes to page tables */ + sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt); + if ( sreg->attr.fields.dpl == 3 ) + { + gdprintk(XENLOG_DEBUG, "User-mode write to pagetable reached emulate_map_dest(). This should never happen!\n"); + return MAPPING_UNHANDLEABLE; + } +#endif + /* Unaligned writes mean probably this isn't a pagetable */ if ( vaddr & (bytes - 1) ) sh_remove_shadows(v, sh_ctxt->mfn1, 0, 0 /* Slow, can fail */ );