| /* | |
| * Copyright 2014, NICTA | |
| * | |
| * This software may be distributed and modified according to the terms of | |
| * the GNU General Public License version 2. Note that NO WARRANTY is provided. | |
| * See "LICENSE_GPLv2.txt" for details. | |
| * | |
| * @TAG(NICTA_GPL) | |
| */ | |
| #include "vmm/vmm.h" | |
| #include "vmm/debug.h" | |
| #include "vmm/vmcall.h" | |
| static vmcall_handler_t *get_handle(vmm_t *vmm, int token); | |
| static vmcall_handler_t *get_handle(vmm_t *vmm, int token) { | |
| int i; | |
| for(i = 0; i < vmm->vmcall_num_handlers; i++) { | |
| if(vmm->vmcall_handlers[i].token == token) { | |
| return &vmm->vmcall_handlers[i]; | |
| } | |
| } | |
| return NULL; | |
| } | |
| int reg_new_handler(vmm_t *vmm, vmcall_handler func, int token) { | |
| unsigned int *hnum = &(vmm->vmcall_num_handlers); | |
| if(get_handle(vmm, token) != NULL) { | |
| return -1; | |
| } | |
| vmm->vmcall_handlers = realloc(vmm->vmcall_handlers, sizeof(vmcall_handler_t) * (*hnum + 1)); | |
| if(vmm->vmcall_handlers == NULL) { | |
| return -1; | |
| } | |
| vmm->vmcall_handlers[*hnum].func = func; | |
| vmm->vmcall_handlers[*hnum].token = token; | |
| vmm->vmcall_num_handlers++; | |
| DPRINTF(4, "Reg. handler %u for vmm, total = %u\n", *hnum - 1, *hnum); | |
| return 0; | |
| } | |
| int vmm_vmcall_handler(vmm_vcpu_t *vcpu) { | |
| int res; | |
| vmcall_handler_t *h; | |
| int token = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EAX); | |
| h = get_handle(vcpu->vmm, token); | |
| if(h == NULL) { | |
| DPRINTF(2, "Failed to find handler for token:%x\n", token); | |
| return -1; | |
| } | |
| res = h->func(vcpu); | |
| if(res == 0) { | |
| vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); | |
| } | |
| return res; | |
| } |