1 /******************************************************************************
2  * vm_event.c
3  *
4  * VM event support.
5  *
6  * Copyright (c) 2009 Citrix Systems, Inc. (Patrick Colp)
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 
23 #include <xen/sched.h>
24 #include <xen/event.h>
25 #include <xen/wait.h>
26 #include <xen/vm_event.h>
27 #include <xen/mem_access.h>
28 #include <asm/p2m.h>
29 #include <asm/monitor.h>
30 #include <asm/vm_event.h>
31 #include <xsm/xsm.h>
32 #include <public/hvm/params.h>
33 
34 /* for public/io/ring.h macros */
35 #define xen_mb()   smp_mb()
36 #define xen_rmb()  smp_rmb()
37 #define xen_wmb()  smp_wmb()
38 
vm_event_enable(struct domain * d,struct xen_domctl_vm_event_op * vec,struct vm_event_domain ** p_ved,int pause_flag,int param,xen_event_channel_notification_t notification_fn)39 static int vm_event_enable(
40     struct domain *d,
41     struct xen_domctl_vm_event_op *vec,
42     struct vm_event_domain **p_ved,
43     int pause_flag,
44     int param,
45     xen_event_channel_notification_t notification_fn)
46 {
47     int rc;
48     unsigned long ring_gfn = d->arch.hvm.params[param];
49     struct vm_event_domain *ved;
50 
51     /*
52      * Only one connected agent at a time.  If the helper crashed, the ring is
53      * in an undefined state, and the guest is most likely unrecoverable.
54      */
55     if ( *p_ved != NULL )
56         return -EBUSY;
57 
58     /* No chosen ring GFN?  Nothing we can do. */
59     if ( ring_gfn == 0 )
60         return -EOPNOTSUPP;
61 
62     ved = xzalloc(struct vm_event_domain);
63     if ( !ved )
64         return -ENOMEM;
65 
66     /* Trivial setup. */
67     spin_lock_init(&ved->lock);
68     init_waitqueue_head(&ved->wq);
69     ved->pause_flag = pause_flag;
70 
71     rc = vm_event_init_domain(d);
72     if ( rc < 0 )
73         goto err;
74 
75     rc = prepare_ring_for_helper(d, ring_gfn, &ved->ring_pg_struct,
76                                  &ved->ring_page);
77     if ( rc < 0 )
78         goto err;
79 
80     FRONT_RING_INIT(&ved->front_ring,
81                     (vm_event_sring_t *)ved->ring_page,
82                     PAGE_SIZE);
83 
84     rc = alloc_unbound_xen_event_channel(d, 0, current->domain->domain_id,
85                                          notification_fn);
86     if ( rc < 0 )
87         goto err;
88 
89     ved->xen_port = vec->u.enable.port = rc;
90 
91     /* Success.  Fill in the domain's appropriate ved. */
92     *p_ved = ved;
93 
94     return 0;
95 
96  err:
97     destroy_ring_for_helper(&ved->ring_page, ved->ring_pg_struct);
98     xfree(ved);
99 
100     return rc;
101 }
102 
vm_event_ring_available(struct vm_event_domain * ved)103 static unsigned int vm_event_ring_available(struct vm_event_domain *ved)
104 {
105     int avail_req = RING_FREE_REQUESTS(&ved->front_ring);
106 
107     avail_req -= ved->target_producers;
108     avail_req -= ved->foreign_producers;
109 
110     BUG_ON(avail_req < 0);
111 
112     return avail_req;
113 }
114 
115 /*
116  * vm_event_wake_blocked() will wakeup vcpus waiting for room in the
117  * ring. These vCPUs were paused on their way out after placing an event,
118  * but need to be resumed where the ring is capable of processing at least
119  * one event from them.
120  */
vm_event_wake_blocked(struct domain * d,struct vm_event_domain * ved)121 static void vm_event_wake_blocked(struct domain *d, struct vm_event_domain *ved)
122 {
123     struct vcpu *v;
124     unsigned int i, j, k, avail_req = vm_event_ring_available(ved);
125 
126     if ( avail_req == 0 || ved->blocked == 0 )
127         return;
128 
129     /* We remember which vcpu last woke up to avoid scanning always linearly
130      * from zero and starving higher-numbered vcpus under high load */
131     for ( i = ved->last_vcpu_wake_up + 1, j = 0; j < d->max_vcpus; i++, j++ )
132     {
133         k = i % d->max_vcpus;
134         v = d->vcpu[k];
135         if ( !v )
136             continue;
137 
138         if ( !ved->blocked || avail_req == 0 )
139             break;
140 
141         if ( test_and_clear_bit(ved->pause_flag, &v->pause_flags) )
142         {
143             vcpu_unpause(v);
144             avail_req--;
145             ved->blocked--;
146             ved->last_vcpu_wake_up = k;
147         }
148     }
149 }
150 
151 /*
152  * In the event that a vCPU attempted to place an event in the ring and
153  * was unable to do so, it is queued on a wait queue.  These are woken as
154  * needed, and take precedence over the blocked vCPUs.
155  */
vm_event_wake_queued(struct domain * d,struct vm_event_domain * ved)156 static void vm_event_wake_queued(struct domain *d, struct vm_event_domain *ved)
157 {
158     unsigned int avail_req = vm_event_ring_available(ved);
159 
160     if ( avail_req > 0 )
161         wake_up_nr(&ved->wq, avail_req);
162 }
163 
164 /*
165  * vm_event_wake() will wakeup all vcpus waiting for the ring to
166  * become available.  If we have queued vCPUs, they get top priority. We
167  * are guaranteed that they will go through code paths that will eventually
168  * call vm_event_wake() again, ensuring that any blocked vCPUs will get
169  * unpaused once all the queued vCPUs have made it through.
170  */
vm_event_wake(struct domain * d,struct vm_event_domain * ved)171 void vm_event_wake(struct domain *d, struct vm_event_domain *ved)
172 {
173     if ( !list_empty(&ved->wq.list) )
174         vm_event_wake_queued(d, ved);
175     else
176         vm_event_wake_blocked(d, ved);
177 }
178 
vm_event_disable(struct domain * d,struct vm_event_domain ** p_ved)179 static int vm_event_disable(struct domain *d, struct vm_event_domain **p_ved)
180 {
181     struct vm_event_domain *ved = *p_ved;
182 
183     if ( vm_event_check_ring(ved) )
184     {
185         struct vcpu *v;
186 
187         spin_lock(&ved->lock);
188 
189         if ( !list_empty(&ved->wq.list) )
190         {
191             spin_unlock(&ved->lock);
192             return -EBUSY;
193         }
194 
195         /* Free domU's event channel and leave the other one unbound */
196         free_xen_event_channel(d, ved->xen_port);
197 
198         /* Unblock all vCPUs */
199         for_each_vcpu ( d, v )
200         {
201             if ( test_and_clear_bit(ved->pause_flag, &v->pause_flags) )
202             {
203                 vcpu_unpause(v);
204                 ved->blocked--;
205             }
206         }
207 
208         destroy_ring_for_helper(&ved->ring_page, ved->ring_pg_struct);
209 
210         vm_event_cleanup_domain(d);
211 
212         spin_unlock(&ved->lock);
213     }
214 
215     xfree(ved);
216     *p_ved = NULL;
217 
218     return 0;
219 }
220 
vm_event_release_slot(struct domain * d,struct vm_event_domain * ved)221 static void vm_event_release_slot(struct domain *d,
222                                   struct vm_event_domain *ved)
223 {
224     /* Update the accounting */
225     if ( current->domain == d )
226         ved->target_producers--;
227     else
228         ved->foreign_producers--;
229 
230     /* Kick any waiters */
231     vm_event_wake(d, ved);
232 }
233 
234 /*
235  * vm_event_mark_and_pause() tags vcpu and put it to sleep.
236  * The vcpu will resume execution in vm_event_wake_blocked().
237  */
vm_event_mark_and_pause(struct vcpu * v,struct vm_event_domain * ved)238 static void vm_event_mark_and_pause(struct vcpu *v, struct vm_event_domain *ved)
239 {
240     if ( !test_and_set_bit(ved->pause_flag, &v->pause_flags) )
241     {
242         vcpu_pause_nosync(v);
243         ved->blocked++;
244     }
245 }
246 
247 /*
248  * This must be preceded by a call to claim_slot(), and is guaranteed to
249  * succeed.  As a side-effect however, the vCPU may be paused if the ring is
250  * overly full and its continued execution would cause stalling and excessive
251  * waiting.  The vCPU will be automatically unpaused when the ring clears.
252  */
vm_event_put_request(struct domain * d,struct vm_event_domain * ved,vm_event_request_t * req)253 void vm_event_put_request(struct domain *d,
254                           struct vm_event_domain *ved,
255                           vm_event_request_t *req)
256 {
257     vm_event_front_ring_t *front_ring;
258     int free_req;
259     unsigned int avail_req;
260     RING_IDX req_prod;
261     struct vcpu *curr = current;
262 
263     if( !vm_event_check_ring(ved) )
264         return;
265 
266     if ( curr->domain != d )
267     {
268         req->flags |= VM_EVENT_FLAG_FOREIGN;
269 
270         if ( !(req->flags & VM_EVENT_FLAG_VCPU_PAUSED) )
271             gdprintk(XENLOG_WARNING, "d%dv%d was not paused.\n",
272                      d->domain_id, req->vcpu_id);
273     }
274 
275     req->version = VM_EVENT_INTERFACE_VERSION;
276 
277     spin_lock(&ved->lock);
278 
279     /* Due to the reservations, this step must succeed. */
280     front_ring = &ved->front_ring;
281     free_req = RING_FREE_REQUESTS(front_ring);
282     ASSERT(free_req > 0);
283 
284     /* Copy request */
285     req_prod = front_ring->req_prod_pvt;
286     memcpy(RING_GET_REQUEST(front_ring, req_prod), req, sizeof(*req));
287     req_prod++;
288 
289     /* Update ring */
290     front_ring->req_prod_pvt = req_prod;
291     RING_PUSH_REQUESTS(front_ring);
292 
293     /* We've actually *used* our reservation, so release the slot. */
294     vm_event_release_slot(d, ved);
295 
296     /* Give this vCPU a black eye if necessary, on the way out.
297      * See the comments above wake_blocked() for more information
298      * on how this mechanism works to avoid waiting. */
299     avail_req = vm_event_ring_available(ved);
300     if( curr->domain == d && avail_req < d->max_vcpus &&
301         !atomic_read(&curr->vm_event_pause_count) )
302         vm_event_mark_and_pause(curr, ved);
303 
304     spin_unlock(&ved->lock);
305 
306     notify_via_xen_event_channel(d, ved->xen_port);
307 }
308 
vm_event_get_response(struct domain * d,struct vm_event_domain * ved,vm_event_response_t * rsp)309 static int vm_event_get_response(struct domain *d, struct vm_event_domain *ved,
310                                  vm_event_response_t *rsp)
311 {
312     vm_event_front_ring_t *front_ring;
313     RING_IDX rsp_cons;
314     int rc = 0;
315 
316     spin_lock(&ved->lock);
317 
318     front_ring = &ved->front_ring;
319     rsp_cons = front_ring->rsp_cons;
320 
321     if ( !RING_HAS_UNCONSUMED_RESPONSES(front_ring) )
322         goto out;
323 
324     /* Copy response */
325     memcpy(rsp, RING_GET_RESPONSE(front_ring, rsp_cons), sizeof(*rsp));
326     rsp_cons++;
327 
328     /* Update ring */
329     front_ring->rsp_cons = rsp_cons;
330     front_ring->sring->rsp_event = rsp_cons + 1;
331 
332     /* Kick any waiters -- since we've just consumed an event,
333      * there may be additional space available in the ring. */
334     vm_event_wake(d, ved);
335 
336     rc = 1;
337 
338  out:
339     spin_unlock(&ved->lock);
340 
341     return rc;
342 }
343 
344 /*
345  * Pull all responses from the given ring and unpause the corresponding vCPU
346  * if required. Based on the response type, here we can also call custom
347  * handlers.
348  *
349  * Note: responses are handled the same way regardless of which ring they
350  * arrive on.
351  */
vm_event_resume(struct domain * d,struct vm_event_domain * ved)352 static int vm_event_resume(struct domain *d, struct vm_event_domain *ved)
353 {
354     vm_event_response_t rsp;
355 
356     /*
357      * vm_event_resume() runs in either XEN_DOMCTL_VM_EVENT_OP_*, or
358      * EVTCHN_send context from the introspection consumer. Both contexts
359      * are guaranteed not to be the subject of vm_event responses.
360      * While we could ASSERT(v != current) for each VCPU in d in the loop
361      * below, this covers the case where we would need to iterate over all
362      * of them more succintly.
363      */
364     ASSERT(d != current->domain);
365 
366     if ( unlikely(!vm_event_check_ring(ved)) )
367          return -ENODEV;
368 
369     /* Pull all responses off the ring. */
370     while ( vm_event_get_response(d, ved, &rsp) )
371     {
372         struct vcpu *v;
373 
374         if ( rsp.version != VM_EVENT_INTERFACE_VERSION )
375         {
376             printk(XENLOG_G_WARNING "vm_event interface version mismatch\n");
377             continue;
378         }
379 
380         /* Validate the vcpu_id in the response. */
381         v = domain_vcpu(d, rsp.vcpu_id);
382         if ( !v )
383             continue;
384 
385         /*
386          * In some cases the response type needs extra handling, so here
387          * we call the appropriate handlers.
388          */
389 
390         /* Check flags which apply only when the vCPU is paused */
391         if ( atomic_read(&v->vm_event_pause_count) )
392         {
393 #ifdef CONFIG_HAS_MEM_PAGING
394             if ( rsp.reason == VM_EVENT_REASON_MEM_PAGING )
395                 p2m_mem_paging_resume(d, &rsp);
396 #endif
397 
398             /*
399              * Check emulation flags in the arch-specific handler only, as it
400              * has to set arch-specific flags when supported, and to avoid
401              * bitmask overhead when it isn't supported.
402              */
403             vm_event_emulate_check(v, &rsp);
404 
405             /*
406              * Check in arch-specific handler to avoid bitmask overhead when
407              * not supported.
408              */
409             vm_event_register_write_resume(v, &rsp);
410 
411             /*
412              * Check in arch-specific handler to avoid bitmask overhead when
413              * not supported.
414              */
415             vm_event_toggle_singlestep(d, v, &rsp);
416 
417             /* Check for altp2m switch */
418             if ( rsp.flags & VM_EVENT_FLAG_ALTERNATE_P2M )
419                 p2m_altp2m_check(v, rsp.altp2m_idx);
420 
421             if ( rsp.flags & VM_EVENT_FLAG_SET_REGISTERS )
422                 vm_event_set_registers(v, &rsp);
423 
424             if ( rsp.flags & VM_EVENT_FLAG_GET_NEXT_INTERRUPT )
425                 vm_event_monitor_next_interrupt(v);
426 
427             if ( rsp.flags & VM_EVENT_FLAG_VCPU_PAUSED )
428                 vm_event_vcpu_unpause(v);
429         }
430     }
431 
432     return 0;
433 }
434 
vm_event_cancel_slot(struct domain * d,struct vm_event_domain * ved)435 void vm_event_cancel_slot(struct domain *d, struct vm_event_domain *ved)
436 {
437     if( !vm_event_check_ring(ved) )
438         return;
439 
440     spin_lock(&ved->lock);
441     vm_event_release_slot(d, ved);
442     spin_unlock(&ved->lock);
443 }
444 
vm_event_grab_slot(struct vm_event_domain * ved,int foreign)445 static int vm_event_grab_slot(struct vm_event_domain *ved, int foreign)
446 {
447     unsigned int avail_req;
448     int rc;
449 
450     if ( !ved->ring_page )
451         return -EOPNOTSUPP;
452 
453     spin_lock(&ved->lock);
454 
455     avail_req = vm_event_ring_available(ved);
456 
457     rc = -EBUSY;
458     if ( avail_req == 0 )
459         goto out;
460 
461     if ( !foreign )
462         ved->target_producers++;
463     else
464         ved->foreign_producers++;
465 
466     rc = 0;
467 
468  out:
469     spin_unlock(&ved->lock);
470 
471     return rc;
472 }
473 
474 /* Simple try_grab wrapper for use in the wait_event() macro. */
vm_event_wait_try_grab(struct vm_event_domain * ved,int * rc)475 static int vm_event_wait_try_grab(struct vm_event_domain *ved, int *rc)
476 {
477     *rc = vm_event_grab_slot(ved, 0);
478 
479     return *rc;
480 }
481 
482 /* Call vm_event_grab_slot() until the ring doesn't exist, or is available. */
vm_event_wait_slot(struct vm_event_domain * ved)483 static int vm_event_wait_slot(struct vm_event_domain *ved)
484 {
485     int rc = -EBUSY;
486 
487     wait_event(ved->wq, vm_event_wait_try_grab(ved, &rc) != -EBUSY);
488 
489     return rc;
490 }
491 
vm_event_check_ring(struct vm_event_domain * ved)492 bool vm_event_check_ring(struct vm_event_domain *ved)
493 {
494     return ved && ved->ring_page;
495 }
496 
497 /*
498  * Determines whether or not the current vCPU belongs to the target domain,
499  * and calls the appropriate wait function.  If it is a guest vCPU, then we
500  * use vm_event_wait_slot() to reserve a slot.  As long as there is a ring,
501  * this function will always return 0 for a guest.  For a non-guest, we check
502  * for space and return -EBUSY if the ring is not available.
503  *
504  * Return codes: -EOPNOTSUPP: the ring is not yet configured
505  *               -EBUSY: the ring is busy
506  *               0: a spot has been reserved
507  *
508  */
__vm_event_claim_slot(struct domain * d,struct vm_event_domain * ved,bool allow_sleep)509 int __vm_event_claim_slot(struct domain *d, struct vm_event_domain *ved,
510                           bool allow_sleep)
511 {
512     if ( !vm_event_check_ring(ved) )
513         return -EOPNOTSUPP;
514 
515     if ( (current->domain == d) && allow_sleep )
516         return vm_event_wait_slot(ved);
517     else
518         return vm_event_grab_slot(ved, current->domain != d);
519 }
520 
521 #ifdef CONFIG_HAS_MEM_PAGING
522 /* Registered with Xen-bound event channel for incoming notifications. */
mem_paging_notification(struct vcpu * v,unsigned int port)523 static void mem_paging_notification(struct vcpu *v, unsigned int port)
524 {
525     vm_event_resume(v->domain, v->domain->vm_event_paging);
526 }
527 #endif
528 
529 /* Registered with Xen-bound event channel for incoming notifications. */
monitor_notification(struct vcpu * v,unsigned int port)530 static void monitor_notification(struct vcpu *v, unsigned int port)
531 {
532     vm_event_resume(v->domain, v->domain->vm_event_monitor);
533 }
534 
535 #ifdef CONFIG_MEM_SHARING
536 /* Registered with Xen-bound event channel for incoming notifications. */
mem_sharing_notification(struct vcpu * v,unsigned int port)537 static void mem_sharing_notification(struct vcpu *v, unsigned int port)
538 {
539     vm_event_resume(v->domain, v->domain->vm_event_share);
540 }
541 #endif
542 
543 /* Clean up on domain destruction */
vm_event_cleanup(struct domain * d)544 void vm_event_cleanup(struct domain *d)
545 {
546 #ifdef CONFIG_HAS_MEM_PAGING
547     if ( vm_event_check_ring(d->vm_event_paging) )
548     {
549         /* Destroying the wait queue head means waking up all
550          * queued vcpus. This will drain the list, allowing
551          * the disable routine to complete. It will also drop
552          * all domain refs the wait-queued vcpus are holding.
553          * Finally, because this code path involves previously
554          * pausing the domain (domain_kill), unpausing the
555          * vcpus causes no harm. */
556         destroy_waitqueue_head(&d->vm_event_paging->wq);
557         (void)vm_event_disable(d, &d->vm_event_paging);
558     }
559 #endif
560     if ( vm_event_check_ring(d->vm_event_monitor) )
561     {
562         destroy_waitqueue_head(&d->vm_event_monitor->wq);
563         (void)vm_event_disable(d, &d->vm_event_monitor);
564     }
565 #ifdef CONFIG_MEM_SHARING
566     if ( vm_event_check_ring(d->vm_event_share) )
567     {
568         destroy_waitqueue_head(&d->vm_event_share->wq);
569         (void)vm_event_disable(d, &d->vm_event_share);
570     }
571 #endif
572 }
573 
vm_event_domctl(struct domain * d,struct xen_domctl_vm_event_op * vec)574 int vm_event_domctl(struct domain *d, struct xen_domctl_vm_event_op *vec)
575 {
576     int rc;
577 
578     if ( vec->op == XEN_VM_EVENT_GET_VERSION )
579     {
580         vec->u.version = VM_EVENT_INTERFACE_VERSION;
581         return 0;
582     }
583 
584     rc = xsm_vm_event_control(XSM_PRIV, d, vec->mode, vec->op);
585     if ( rc )
586         return rc;
587 
588     if ( unlikely(d == current->domain) ) /* no domain_pause() */
589     {
590         gdprintk(XENLOG_INFO, "Tried to do a memory event op on itself.\n");
591         return -EINVAL;
592     }
593 
594     if ( unlikely(d->is_dying) )
595     {
596         gdprintk(XENLOG_INFO, "Ignoring memory event op on dying domain %u\n",
597                  d->domain_id);
598         return 0;
599     }
600 
601     if ( unlikely(d->vcpu == NULL) || unlikely(d->vcpu[0] == NULL) )
602     {
603         gdprintk(XENLOG_INFO,
604                  "Memory event op on a domain (%u) with no vcpus\n",
605                  d->domain_id);
606         return -EINVAL;
607     }
608 
609     rc = -ENOSYS;
610 
611     switch ( vec->mode )
612     {
613 #ifdef CONFIG_HAS_MEM_PAGING
614     case XEN_DOMCTL_VM_EVENT_OP_PAGING:
615     {
616         rc = -EINVAL;
617 
618         switch( vec->op )
619         {
620         case XEN_VM_EVENT_ENABLE:
621         {
622             rc = -EOPNOTSUPP;
623             /* hvm fixme: p2m_is_foreign types need addressing */
624             if ( is_hvm_domain(hardware_domain) )
625                 break;
626 
627             rc = -ENODEV;
628             /* Only HAP is supported */
629             if ( !hap_enabled(d) )
630                 break;
631 
632             /* No paging if iommu is used */
633             rc = -EMLINK;
634             if ( unlikely(is_iommu_enabled(d)) )
635                 break;
636 
637             rc = -EXDEV;
638             /* Disallow paging in a PoD guest */
639             if ( p2m_pod_entry_count(p2m_get_hostp2m(d)) )
640                 break;
641 
642             /* domain_pause() not required here, see XSA-99 */
643             rc = vm_event_enable(d, vec, &d->vm_event_paging, _VPF_mem_paging,
644                                  HVM_PARAM_PAGING_RING_PFN,
645                                  mem_paging_notification);
646         }
647         break;
648 
649         case XEN_VM_EVENT_DISABLE:
650             if ( vm_event_check_ring(d->vm_event_paging) )
651             {
652                 domain_pause(d);
653                 rc = vm_event_disable(d, &d->vm_event_paging);
654                 domain_unpause(d);
655             }
656             break;
657 
658         case XEN_VM_EVENT_RESUME:
659             rc = vm_event_resume(d, d->vm_event_paging);
660             break;
661 
662         default:
663             rc = -ENOSYS;
664             break;
665         }
666     }
667     break;
668 #endif
669 
670     case XEN_DOMCTL_VM_EVENT_OP_MONITOR:
671     {
672         rc = -EINVAL;
673 
674         switch( vec->op )
675         {
676         case XEN_VM_EVENT_ENABLE:
677             /* domain_pause() not required here, see XSA-99 */
678             rc = arch_monitor_init_domain(d);
679             if ( rc )
680                 break;
681             rc = vm_event_enable(d, vec, &d->vm_event_monitor, _VPF_mem_access,
682                                  HVM_PARAM_MONITOR_RING_PFN,
683                                  monitor_notification);
684             break;
685 
686         case XEN_VM_EVENT_DISABLE:
687             if ( vm_event_check_ring(d->vm_event_monitor) )
688             {
689                 domain_pause(d);
690                 rc = vm_event_disable(d, &d->vm_event_monitor);
691                 arch_monitor_cleanup_domain(d);
692                 domain_unpause(d);
693             }
694             break;
695 
696         case XEN_VM_EVENT_RESUME:
697             rc = vm_event_resume(d, d->vm_event_monitor);
698             break;
699 
700         default:
701             rc = -ENOSYS;
702             break;
703         }
704     }
705     break;
706 
707 #ifdef CONFIG_MEM_SHARING
708     case XEN_DOMCTL_VM_EVENT_OP_SHARING:
709     {
710         rc = -EINVAL;
711 
712         switch( vec->op )
713         {
714         case XEN_VM_EVENT_ENABLE:
715             rc = -EOPNOTSUPP;
716             /* hvm fixme: p2m_is_foreign types need addressing */
717             if ( is_hvm_domain(hardware_domain) )
718                 break;
719 
720             rc = -ENODEV;
721             /* Only HAP is supported */
722             if ( !hap_enabled(d) )
723                 break;
724 
725             /* domain_pause() not required here, see XSA-99 */
726             rc = vm_event_enable(d, vec, &d->vm_event_share, _VPF_mem_sharing,
727                                  HVM_PARAM_SHARING_RING_PFN,
728                                  mem_sharing_notification);
729             break;
730 
731         case XEN_VM_EVENT_DISABLE:
732             if ( vm_event_check_ring(d->vm_event_share) )
733             {
734                 domain_pause(d);
735                 rc = vm_event_disable(d, &d->vm_event_share);
736                 domain_unpause(d);
737             }
738             break;
739 
740         case XEN_VM_EVENT_RESUME:
741             rc = vm_event_resume(d, d->vm_event_share);
742             break;
743 
744         default:
745             rc = -ENOSYS;
746             break;
747         }
748     }
749     break;
750 #endif
751 
752     default:
753         rc = -ENOSYS;
754     }
755 
756     return rc;
757 }
758 
vm_event_vcpu_pause(struct vcpu * v)759 void vm_event_vcpu_pause(struct vcpu *v)
760 {
761     ASSERT(v == current);
762 
763     atomic_inc(&v->vm_event_pause_count);
764     vcpu_pause_nosync(v);
765 }
766 
vm_event_vcpu_unpause(struct vcpu * v)767 void vm_event_vcpu_unpause(struct vcpu *v)
768 {
769     int old, new, prev = v->vm_event_pause_count.counter;
770 
771     /*
772      * All unpause requests as a result of toolstack responses.
773      * Prevent underflow of the vcpu pause count.
774      */
775     do
776     {
777         old = prev;
778         new = old - 1;
779 
780         if ( new < 0 )
781         {
782             printk(XENLOG_G_WARNING
783                    "%pv vm_event: Too many unpause attempts\n", v);
784             return;
785         }
786 
787         prev = cmpxchg(&v->vm_event_pause_count.counter, old, new);
788     } while ( prev != old );
789 
790     vcpu_unpause(v);
791 }
792 
793 /*
794  * Local variables:
795  * mode: C
796  * c-file-style: "BSD"
797  * c-basic-offset: 4
798  * indent-tabs-mode: nil
799  * End:
800  */
801