@@ -1073,7 +1073,10 @@ static int livepatch_quiesce(struct livepatch_func *funcs, unsigned int nfuncs)
if ( livepatch_vmap.text || livepatch_vmap.funcs )
return -EINVAL;
- text_mfn = _mfn(virt_to_mfn(_start));
+ text_mfn = arch_livepatch_lookup_mfn((unsigned long)_start);
+ if ( mfn_eq(text_mfn, INVALID_MFN) )
+ return -EINVAL;
+
text_order = get_order_from_bytes(_end - _start);
/*
@@ -1093,7 +1096,14 @@ static int livepatch_quiesce(struct livepatch_func *funcs, unsigned int nfuncs)
livepatch_vmap.text = vmap_addr;
livepatch_vmap.offset = offs;
- rodata_mfn = _mfn(virt_to_mfn(va & PAGE_MASK));
+ rodata_mfn = arch_livepatch_lookup_mfn(va & PAGE_MASK);
+ if ( mfn_eq(rodata_mfn, INVALID_MFN) )
+ {
+ vunmap(livepatch_vmap.text);
+ livepatch_vmap.text = NULL;
+ return -EINVAL;
+ }
+
vmap_addr = __vmap(&rodata_mfn, size, 1, 1, PAGE_HYPERVISOR, VMAP_DEFAULT);
if ( !vmap_addr )
{
Without this patch on x86 we would get a DOUBLE FAULT as the virt_to_mfn does not lookup virtual addresses that are in vmap region. This means that the livepatch_vmap.funcs would point to an incorrect MFN (with either garbage or all zeros). We only use the livepatch_vmap.funcs to save the old contents of the instruction (f->opaque) so during patching all works fine. But when we revert and copy the contents of f->opaque we would either get the right values, or zeros (again, depending on where the MFN is) - and then starting instructions in the unpatched function would end up with 00000000 .. causing a double fault. Using the arch_livepatch_lookup_mfn solves the problem and the applying/reverting works on all platforms properly. Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- xen/common/livepatch.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)