# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Date 1163136126 -32400 # Node ID f3e97d467b6f7e36c95d4deb3ed3bc955710f8e7 # Parent 5470cadfeb22e33e7abb86193224984140732361 fix xenmem hypercall for non-trivial xencomm arch(i.e. ia64, and powerpc) On ia64 and powerpc, guest_handle_add_offset() effect persists over hypercall continuation because its consumed offset is recorced in guest domains memory space. On the other hand, x86 guest_handle_add_offset() effect is volatile over hypercall continuation. So xenmem hypercall(more specifically increase_reservation, decrease_reservaton, populate_memory and exchange) is broken on ia64 and powerpc. #ifdef/ifndef CONFIG_X86 is used to solve this issue without breaking the existing ABI. #ifdef is ugly, but it would be difficult to solve this issue without #ifdef and to preserve the existing ABI simaltaneously. I checked other users of both guest_handle_add_offset() and hypercall continuation. Fortunately other users records restart points by hypercall argument so that this isn't an issue. PATCHNAME: xencomm_and_xenmem_hypercall Signed-off-by: Isaku Yamahata diff -r 5470cadfeb22 -r f3e97d467b6f xen/common/memory.c --- a/xen/common/memory.c Fri Nov 10 14:22:05 2006 +0900 +++ b/xen/common/memory.c Fri Nov 10 14:22:06 2006 +0900 @@ -341,23 +341,29 @@ memory_exchange(XEN_GUEST_HANDLE(xen_mem memflags = MEMF_dma; } +#ifdef CONFIG_X86 guest_handle_add_offset(exch.in.extent_start, exch.nr_exchanged); +#endif exch.in.nr_extents -= exch.nr_exchanged; if ( exch.in.extent_order <= exch.out.extent_order ) { in_chunk_order = exch.out.extent_order - exch.in.extent_order; out_chunk_order = 0; +#ifdef CONFIG_X86 guest_handle_add_offset( exch.out.extent_start, exch.nr_exchanged >> in_chunk_order); +#endif exch.out.nr_extents -= exch.nr_exchanged >> in_chunk_order; } else { in_chunk_order = 0; out_chunk_order = exch.in.extent_order - exch.out.extent_order; +#ifdef CONFIG_X86 guest_handle_add_offset( exch.out.extent_start, exch.nr_exchanged << out_chunk_order); +#endif exch.out.nr_extents -= exch.nr_exchanged << out_chunk_order; } @@ -379,6 +385,15 @@ memory_exchange(XEN_GUEST_HANDLE(xen_mem { if ( hypercall_preempt_check() ) { +#ifndef CONFIG_X86 + guest_handle_add_offset(exch.in.extent_start, i); + if ( exch.in.extent_order <= exch.out.extent_order ) + guest_handle_add_offset( + exch.out.extent_start, i >> in_chunk_order); + else + guest_handle_add_offset( + exch.out.extent_start, i << out_chunk_order); +#endif exch.nr_exchanged += i << in_chunk_order; if ( copy_field_to_guest(arg, &exch, nr_exchanged) ) return -EFAULT; @@ -543,8 +558,10 @@ long do_memory_op(unsigned long cmd, XEN if ( unlikely(start_extent > reservation.nr_extents) ) return start_extent; +#ifdef CONFIG_X86 if ( !guest_handle_is_null(reservation.extent_start) ) guest_handle_add_offset(reservation.extent_start, start_extent); +#endif reservation.nr_extents -= start_extent; if ( (reservation.address_bits != 0) && @@ -596,6 +613,10 @@ long do_memory_op(unsigned long cmd, XEN if ( unlikely(reservation.domid != DOMID_SELF) ) put_domain(d); +#ifndef CONFIG_X86 + if (rc > 0 && !guest_handle_is_null(reservation.extent_start)) + guest_handle_add_offset(reservation.extent_start, rc); +#endif rc += start_extent; if ( preempted )