[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] 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 <jbeulich@xxxxxxxx>

--- 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).


Attachment: preempt-EAGAIN-ERESTART.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.