switch hypercall restart indication from -EAGAIN to -ERESTART -EAGAIN being a return value we want to return to the actual caller in a couple of cases makes this unsuitable for restart indication, and x86 already developed two cases where -EAGAIN could not be returned as intended due to this (which is being fixed here at once). Signed-off-by: Jan Beulich --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -675,7 +675,7 @@ static int relinquish_memory(struct doma if ( hypercall_preempt_check() ) { - ret = -EAGAIN; + ret = -ERESTART; goto out; } } --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -439,7 +439,7 @@ static int apply_p2m_changes(struct doma if ( hypercall_preempt_check() ) { p2m->lowest_mapped_gfn = addr >> PAGE_SHIFT; - rc = -EAGAIN; + rc = -ERESTART; goto out; } count = 0; --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -929,8 +929,8 @@ int arch_set_info_guest( switch ( rc ) { case -EINTR: - rc = -EAGAIN; - case -EAGAIN: + rc = -ERESTART; + case -ERESTART: case 0: break; default: @@ -957,8 +957,8 @@ int arch_set_info_guest( switch ( rc ) { case -EINTR: - rc = -EAGAIN; - case -EAGAIN: + rc = -ERESTART; + case -ERESTART: v->arch.old_guest_table = pagetable_get_page(v->arch.guest_table); v->arch.guest_table = pagetable_null(); @@ -1808,9 +1808,9 @@ static int relinquish_memory( { case 0: break; - case -EAGAIN: + case -ERESTART: case -EINTR: - ret = -EAGAIN; + ret = -ERESTART; page_list_add(page, list); set_bit(_PGT_pinned, &page->u.inuse.type_info); put_page(page); @@ -1855,9 +1855,9 @@ static int relinquish_memory( if ( x & PGT_partial ) put_page(page); put_page(page); - ret = -EAGAIN; + ret = -ERESTART; goto out; - case -EAGAIN: + case -ERESTART: page_list_add(page, list); page->u.inuse.type_info |= PGT_partial; if ( x & PGT_partial ) @@ -1881,7 +1881,7 @@ static int relinquish_memory( if ( hypercall_preempt_check() ) { - ret = -EAGAIN; + ret = -ERESTART; goto out; } } --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -4446,7 +4446,7 @@ static int hvmop_flush_tlb_all(void) /* Avoid deadlock if more than one vcpu tries this at the same time. */ if ( !spin_trylock(&d->hypercall_deadlock_mutex) ) - return -EAGAIN; + return -ERESTART; /* Pause all other vcpus. */ for_each_vcpu ( d, v ) @@ -4554,7 +4554,7 @@ long do_hvm_op(unsigned long op, XEN_GUE * All foreign updates to guest state must synchronise on * the domctl_lock. */ - rc = -EAGAIN; + rc = -ERESTART; if ( !domctl_lock_acquire() ) break; @@ -4816,7 +4816,7 @@ long do_hvm_op(unsigned long op, XEN_GUE if ( a.nr > ++start_iter && !(start_iter & HVMOP_op_mask) && hypercall_preempt_check() ) { - rc = -EAGAIN; + rc = -ERESTART; break; } } @@ -4916,13 +4916,13 @@ long do_hvm_op(unsigned long op, XEN_GUE { put_gfn(d, pfn); p2m_mem_paging_populate(d, pfn); - rc = -EINVAL; /* XXX EAGAIN */ + rc = -EAGAIN; goto param_fail4; } if ( p2m_is_shared(t) ) { put_gfn(d, pfn); - rc = -EINVAL; /* XXX EAGAIN */ + rc = -EAGAIN; goto param_fail4; } if ( !p2m_is_ram(t) && @@ -4941,7 +4941,7 @@ long do_hvm_op(unsigned long op, XEN_GUE if ( a.nr > ++start_iter && !(start_iter & HVMOP_op_mask) && hypercall_preempt_check() ) { - rc = -EAGAIN; + rc = -ERESTART; goto param_fail4; } } @@ -5056,7 +5056,7 @@ long do_hvm_op(unsigned long op, XEN_GUE } } - if ( rc == -EAGAIN ) + if ( rc == -ERESTART ) { ASSERT(!(start_iter & HVMOP_op_mask)); rc = hypercall_create_continuation(__HYPERVISOR_hvm_op, "lh", --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -1827,7 +1827,7 @@ static int svm_msr_write_intercept(unsig switch ( wrmsr_hypervisor_regs(msr, msr_content) ) { - case -EAGAIN: + case -ERESTART: result = X86EMUL_RETRY; break; case 0: --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -2289,7 +2289,7 @@ static int vmx_msr_write_intercept(unsig !is_last_branch_msr(msr) ) switch ( wrmsr_hypervisor_regs(msr, msr_content) ) { - case -EAGAIN: + case -ERESTART: return X86EMUL_RETRY; case 0: case 1: --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1285,7 +1285,7 @@ static int alloc_l2_table(struct page_in && hypercall_preempt_check() ) { page->nr_validated_ptes = i; - rc = -EAGAIN; + rc = -ERESTART; break; } @@ -1356,7 +1356,7 @@ static int alloc_l3_table(struct page_in (rc = get_page_from_l3e(pl3e[i], pfn, d, partial)) > 0 ) continue; - if ( rc == -EAGAIN ) + if ( rc == -ERESTART ) { page->nr_validated_ptes = i; page->partial_pte = partial ?: 1; @@ -1365,7 +1365,7 @@ static int alloc_l3_table(struct page_in { page->nr_validated_ptes = i; page->partial_pte = 0; - rc = -EAGAIN; + rc = -ERESTART; } if ( rc < 0 ) break; @@ -1375,7 +1375,7 @@ static int alloc_l3_table(struct page_in if ( rc >= 0 && !create_pae_xen_mappings(d, pl3e) ) rc = -EINVAL; - if ( rc < 0 && rc != -EAGAIN && rc != -EINTR ) + if ( rc < 0 && rc != -ERESTART && rc != -EINTR ) { MEM_LOG("Failure in alloc_l3_table: entry %d", i); if ( i ) @@ -1428,7 +1428,7 @@ static int alloc_l4_table(struct page_in (rc = get_page_from_l4e(pl4e[i], pfn, d, partial)) > 0 ) continue; - if ( rc == -EAGAIN ) + if ( rc == -ERESTART ) { page->nr_validated_ptes = i; page->partial_pte = partial ?: 1; @@ -1442,7 +1442,7 @@ static int alloc_l4_table(struct page_in page->nr_validated_ptes = i; page->partial_pte = 0; if ( rc == -EINTR ) - rc = -EAGAIN; + rc = -ERESTART; else { if ( current->arch.old_guest_table ) @@ -1500,7 +1500,7 @@ static int free_l2_table(struct page_inf preemptible && i && hypercall_preempt_check() ) { page->nr_validated_ptes = i; - err = -EAGAIN; + err = -ERESTART; } } while ( !err && i-- ); @@ -1537,7 +1537,7 @@ static int free_l3_table(struct page_inf unmap_domain_page(pl3e); - if ( rc == -EAGAIN ) + if ( rc == -ERESTART ) { page->nr_validated_ptes = i; page->partial_pte = partial ?: -1; @@ -1546,7 +1546,7 @@ static int free_l3_table(struct page_inf { page->nr_validated_ptes = i + 1; page->partial_pte = 0; - rc = -EAGAIN; + rc = -ERESTART; } return rc > 0 ? 0 : rc; } @@ -1567,7 +1567,7 @@ static int free_l4_table(struct page_inf partial = 0; } while ( i-- ); - if ( rc == -EAGAIN ) + if ( rc == -ERESTART ) { page->nr_validated_ptes = i; page->partial_pte = partial ?: -1; @@ -1576,7 +1576,7 @@ static int free_l4_table(struct page_inf { page->nr_validated_ptes = i + 1; page->partial_pte = 0; - rc = -EAGAIN; + rc = -ERESTART; } unmap_domain_page(pl4e); @@ -2104,7 +2104,7 @@ static int alloc_page_type(struct page_i { ASSERT((page->u.inuse.type_info & (PGT_count_mask | PGT_validated)) == 1); - case -EAGAIN: + case -ERESTART: get_page_light(page); page->u.inuse.type_info |= PGT_partial; } @@ -2203,7 +2203,7 @@ static int __put_final_page_type( } else { - BUG_ON(rc != -EAGAIN); + BUG_ON(rc != -ERESTART); wmb(); get_page_light(page); page->u.inuse.type_info |= PGT_partial; @@ -2421,7 +2421,7 @@ int get_page_type(struct page_info *page int rc = __get_page_type(page, type, 0); if ( likely(rc == 0) ) return 1; - ASSERT(rc != -EINTR && rc != -EAGAIN); + ASSERT(rc != -EINTR && rc != -ERESTART); return 0; } @@ -2633,8 +2633,8 @@ int put_old_guest_table(struct vcpu *v) switch ( rc = put_page_and_type_preemptible(v->arch.old_guest_table) ) { case -EINTR: - case -EAGAIN: - return -EAGAIN; + case -ERESTART: + return -ERESTART; } v->arch.old_guest_table = NULL; @@ -2722,8 +2722,8 @@ int new_guest_cr3(unsigned long mfn) case 0: break; case -EINTR: - case -EAGAIN: - return -EAGAIN; + case -ERESTART: + return -ERESTART; default: MEM_LOG("Error while installing new compat baseptr %lx", mfn); return rc; @@ -2758,8 +2758,8 @@ int new_guest_cr3(unsigned long mfn) case 0: break; case -EINTR: - case -EAGAIN: - return -EAGAIN; + case -ERESTART: + return -ERESTART; default: MEM_LOG("Error while installing new baseptr %lx", mfn); return rc; @@ -2782,8 +2782,8 @@ int new_guest_cr3(unsigned long mfn) switch ( rc = put_page_and_type_preemptible(page) ) { case -EINTR: - rc = -EAGAIN; - case -EAGAIN: + rc = -ERESTART; + case -ERESTART: curr->arch.old_guest_table = page; break; default: @@ -2896,7 +2896,7 @@ long do_mmuext_op( if ( unlikely(rc) ) { - if ( likely(rc == -EAGAIN) ) + if ( likely(rc == -ERESTART) ) rc = hypercall_create_continuation( __HYPERVISOR_mmuext_op, "hihi", uops, count, pdone, foreigndom); @@ -2937,7 +2937,7 @@ long do_mmuext_op( { if ( curr->arch.old_guest_table || (i && hypercall_preempt_check()) ) { - rc = -EAGAIN; + rc = -ERESTART; break; } @@ -2991,8 +2991,8 @@ long do_mmuext_op( if ( unlikely(!okay) ) { if ( rc == -EINTR ) - rc = -EAGAIN; - else if ( rc != -EAGAIN ) + rc = -ERESTART; + else if ( rc != -ERESTART ) MEM_LOG("Error while pinning mfn %lx", page_to_mfn(page)); if ( page != curr->arch.old_guest_table ) put_page(page); @@ -3061,7 +3061,7 @@ long do_mmuext_op( switch ( rc = put_page_and_type_preemptible(page) ) { case -EINTR: - case -EAGAIN: + case -ERESTART: curr->arch.old_guest_table = page; rc = 0; break; @@ -3117,8 +3117,8 @@ long do_mmuext_op( if ( unlikely(!okay) ) { if ( rc == -EINTR ) - rc = -EAGAIN; - else if ( rc != -EAGAIN ) + rc = -ERESTART; + else if ( rc != -ERESTART ) MEM_LOG("Error while installing new mfn %lx", op.arg1.mfn); break; @@ -3137,8 +3137,8 @@ long do_mmuext_op( switch ( rc = put_page_and_type_preemptible(page) ) { case -EINTR: - rc = -EAGAIN; - case -EAGAIN: + rc = -ERESTART; + case -ERESTART: curr->arch.old_guest_table = page; okay = 0; break; @@ -3373,7 +3373,7 @@ long do_mmuext_op( guest_handle_add_offset(uops, 1); } - if ( rc == -EAGAIN ) + if ( rc == -ERESTART ) { ASSERT(i < count); rc = hypercall_create_continuation( @@ -3430,7 +3430,7 @@ long do_mmu_update( if ( unlikely(rc) ) { - if ( likely(rc == -EAGAIN) ) + if ( likely(rc == -ERESTART) ) rc = hypercall_create_continuation( __HYPERVISOR_mmu_update, "hihi", ureqs, count, pdone, foreigndom); @@ -3484,7 +3484,7 @@ long do_mmu_update( { if ( curr->arch.old_guest_table || (i && hypercall_preempt_check()) ) { - rc = -EAGAIN; + rc = -ERESTART; break; } @@ -3614,7 +3614,7 @@ long do_mmu_update( } page_unlock(page); if ( rc == -EINTR ) - rc = -EAGAIN; + rc = -ERESTART; } else if ( get_page_type(page, PGT_writable_page) ) { @@ -3676,7 +3676,7 @@ long do_mmu_update( guest_handle_add_offset(ureqs, 1); } - if ( rc == -EAGAIN ) + if ( rc == -ERESTART ) { ASSERT(i < count); rc = hypercall_create_continuation( @@ -4830,7 +4830,7 @@ long arch_memory_op(unsigned long cmd, X rc = p2m_pod_set_mem_target(d, target.target_pages); } - if ( rc == -EAGAIN ) + if ( rc == -ERESTART ) { rc = hypercall_create_continuation( __HYPERVISOR_memory_op, "lh", op, arg); --- a/xen/arch/x86/mm/mem_sharing.c +++ b/xen/arch/x86/mm/mem_sharing.c @@ -1297,7 +1297,7 @@ int relinquish_shared_pages(struct domai if ( hypercall_preempt_check() ) { p2m->next_shared_gfn_to_relinquish = gfn + 1; - rc = -EAGAIN; + rc = -ERESTART; break; } count = 0; --- a/xen/arch/x86/mm/p2m-pod.c +++ b/xen/arch/x86/mm/p2m-pod.c @@ -245,7 +245,7 @@ p2m_pod_set_cache_target(struct p2m_doma if ( preemptible && pod_target != p2m->pod.count && hypercall_preempt_check() ) { - ret = -EAGAIN; + ret = -ERESTART; goto out; } } @@ -290,7 +290,7 @@ p2m_pod_set_cache_target(struct p2m_doma if ( preemptible && pod_target != p2m->pod.count && hypercall_preempt_check() ) { - ret = -EAGAIN; + ret = -ERESTART; goto out; } } --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -650,7 +650,7 @@ int wrmsr_hypervisor_regs(uint32_t idx, if ( p2m_is_paging(t) ) { p2m_mem_paging_populate(d, gmfn); - return -EAGAIN; + return -ERESTART; } gdprintk(XENLOG_WARNING, @@ -2354,7 +2354,7 @@ static int emulate_privileged_op(struct { case 0: break; - case -EAGAIN: /* retry after preemption */ + case -ERESTART: /* retry after preemption */ goto skip; default: /* not okay */ goto fail; --- a/xen/common/compat/domain.c +++ b/xen/common/compat/domain.c @@ -58,7 +58,7 @@ int compat_vcpu_op(int cmd, int vcpuid, rc = v->is_initialised ? -EEXIST : arch_set_info_guest(v, cmp_ctxt); domain_unlock(d); - if ( rc == -EAGAIN ) + if ( rc == -ERESTART ) rc = hypercall_create_continuation(__HYPERVISOR_vcpu_op, "iih", cmd, vcpuid, arg); --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -590,6 +590,8 @@ int domain_kill(struct domain *d) rc = domain_relinquish_resources(d); if ( rc != 0 ) { + if ( rc == -ERESTART ) + rc = -EAGAIN; BUG_ON(rc != -EAGAIN); break; } @@ -1067,7 +1069,7 @@ long do_vcpu_op(int cmd, int vcpuid, XEN free_vcpu_guest_context(ctxt); - if ( rc == -EAGAIN ) + if ( rc == -ERESTART ) rc = hypercall_create_continuation(__HYPERVISOR_vcpu_op, "iih", cmd, vcpuid, arg); --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -342,7 +342,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe if ( guest_handle_is_null(op->u.vcpucontext.ctxt) ) { ret = vcpu_reset(v); - if ( ret == -EAGAIN ) + if ( ret == -ERESTART ) ret = hypercall_create_continuation( __HYPERVISOR_domctl, "h", u_domctl); break; @@ -374,7 +374,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe ret = arch_set_info_guest(v, c); domain_unpause(d); - if ( ret == -EAGAIN ) + if ( ret == -ERESTART ) ret = hypercall_create_continuation( __HYPERVISOR_domctl, "h", u_domctl); } --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -125,7 +125,7 @@ struct page_info * PGT_partial gets set, and it must be dropped when the flag gets * cleared. This is so that a get() leaving a page in partially * validated state (where the caller would drop the reference acquired - * due to the getting of the type [apparently] failing [-EAGAIN]) + * due to the getting of the type [apparently] failing [-ERESTART]) * would not accidentally result in a page left with zero general * reference count, but non-zero type reference count (possible when * the partial get() is followed immediately by domain destruction).