/* Registered with Xen-bound event channel for incoming notifications. */ static void mem_paging_notification(struct vcpu *v, unsigned int port) { if ( likely(v->domain->mem_event->paging.ring_page != NULL) ) p2m_mem_paging_resume(v->domain); }
/* * Pull all responses from the given ring and unpause the corresponding vCPU * if required. Based on the response type, here we can also call custom * handlers. * * Note: responses are handled the same way regardless of which ring they * arrive on. */ void vm_event_resume(struct domain *d, struct vm_event_domain *ved) { vm_event_response_t rsp; /* Pull all responses off the ring. */ while ( vm_event_get_response(d, ved, &rsp) ) { struct vcpu *v; if ( rsp.version != VM_EVENT_INTERFACE_VERSION ) { printk(XENLOG_G_WARNING "vm_event interface version mismatch\n"); continue; } /* Validate the vcpu_id in the response. */ if ( (rsp.vcpu_id >= d->max_vcpus) || !d->vcpu[rsp.vcpu_id] ) continue; v = d->vcpu[rsp.vcpu_id]; /* * In some cases the response type needs extra handling, so here * we call the appropriate handlers. */ switch ( rsp.reason ) { case VM_EVENT_REASON_MOV_TO_MSR: case VM_EVENT_REASON_WRITE_CTRLREG: vm_event_register_write_resume(v, &rsp); break; #ifdef CONFIG_HAS_MEM_ACCESS case VM_EVENT_REASON_MEM_ACCESS: mem_access_resume(v, &rsp); break; #endif #ifdef CONFIG_HAS_MEM_PAGING case VM_EVENT_REASON_MEM_PAGING: p2m_mem_paging_resume(d, &rsp); break; #endif }; /* Check for altp2m switch */ if ( rsp.flags & VM_EVENT_FLAG_ALTERNATE_P2M ) p2m_altp2m_check(v, rsp.altp2m_idx); if ( rsp.flags & VM_EVENT_FLAG_VCPU_PAUSED ) { if ( rsp.flags & VM_EVENT_FLAG_SET_REGISTERS ) vm_event_set_registers(v, &rsp); if ( rsp.flags & VM_EVENT_FLAG_TOGGLE_SINGLESTEP ) vm_event_toggle_singlestep(d, v); vm_event_vcpu_unpause(v); } } }