]> xenbits.xensource.com Git - xen.git/commitdiff
x86: allow calling {shadow/hap}_set_allocation with the idle domain
authorRoger Pau Monné <roger.pau@citrix.com>
Fri, 2 Dec 2016 17:07:58 +0000 (18:07 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 2 Dec 2016 17:07:58 +0000 (18:07 +0100)
... and using the "preempted" parameter. Introduce a new helper that can
be used from both hypercall or idle vcpu context (ie: during Dom0
creation) in order to check if preemption is needed. If such preemption
happens, the caller should then call process_pending_softirqs in order to
drain the pending softirqs, and then call *_set_allocation again to continue
with it's execution.

This allows us to call *_set_allocation() when building domain 0.

While there also document hypercall_preempt_check and add an assert to
local_events_need_delivery in order to be sure it's not called by the idle
domain, which doesn't receive any events (and that in turn
hypercall_preempt_check is also not called by the idle domain).

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: George Dunlap <george.dunlap@citrix.com>
Acked-by: Tim Deegan <tim@xen.org>
xen/arch/x86/mm/hap/hap.c
xen/arch/x86/mm/shadow/common.c
xen/include/asm-x86/event.h
xen/include/xen/sched.h

index f099e9412fd490124f2c624a4dea2e9790dcc18f..b9faba68345724d0b0eddf74ebdabdb990bfb986 100644 (file)
@@ -379,7 +379,7 @@ hap_set_allocation(struct domain *d, unsigned int pages, int *preempted)
             break;
 
         /* Check to see if we need to yield and try again */
-        if ( preempted && hypercall_preempt_check() )
+        if ( preempted && general_preempt_check() )
         {
             *preempted = 1;
             return 0;
index 756c2760c45dc1f7fe6763ed86e44554acd50c88..ddbdb735fa54660e50d15cad29094b5f1fc3b972 100644 (file)
@@ -1681,7 +1681,7 @@ static int sh_set_allocation(struct domain *d,
             break;
 
         /* Check to see if we need to yield and try again */
-        if ( preempted && hypercall_preempt_check() )
+        if ( preempted && general_preempt_check() )
         {
             *preempted = 1;
             return 0;
index a82062e339d5be03441a3e5837a087b04499179f..d589d6f86c71ed3434726299e878de61b5ce1ea2 100644 (file)
@@ -23,6 +23,9 @@ int hvm_local_events_need_delivery(struct vcpu *v);
 static inline int local_events_need_delivery(void)
 {
     struct vcpu *v = current;
+
+    ASSERT(!is_idle_vcpu(v));
+
     return (has_hvm_container_vcpu(v) ? hvm_local_events_need_delivery(v) :
             (vcpu_info(v, evtchn_upcall_pending) &&
              !vcpu_info(v, evtchn_upcall_mask)));
index 1fbda87813e1a91dc7a9162c8524411e25cc58f2..063efe610f400f12448aa5512e8a22029c573138 100644 (file)
@@ -708,11 +708,26 @@ unsigned long hypercall_create_continuation(
     unsigned int op, const char *format, ...);
 void hypercall_cancel_continuation(void);
 
+/*
+ * For long-running operations that must be in hypercall context, check
+ * if there is background work to be done that should interrupt this
+ * operation.
+ */
 #define hypercall_preempt_check() (unlikely(    \
         softirq_pending(smp_processor_id()) |   \
         local_events_need_delivery()            \
     ))
 
+/*
+ * For long-running operations that may be in hypercall context or on
+ * the idle vcpu (e.g. during dom0 construction), check if there is
+ * background work to be done that should interrupt this operation.
+ */
+#define general_preempt_check() (unlikely(                          \
+        softirq_pending(smp_processor_id()) ||                      \
+        (!is_idle_vcpu(current) && local_events_need_delivery())    \
+    ))
+
 extern struct domain *domain_list;
 
 /* Caller must hold the domlist_read_lock or domlist_update_lock. */