1/* 2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <autoconf.h> 8#include <stdio.h> 9#include <stdlib.h> 10 11#include <sel4/sel4.h> 12#include <sel4/messages.h> 13#include <utils/util.h> 14 15#include <sel4vm/guest_vm_util.h> 16#include <sel4vm/guest_memory.h> 17 18#include "vm.h" 19#include "syscalls.h" 20 21static void sys_pa_to_ipa(vm_t *vm, seL4_UserContext *regs) 22{ 23 uint32_t pa; 24#ifdef CONFIG_ARCH_AARCH64 25#else 26 pa = regs->r0; 27#endif 28 29 ZF_LOGD("PA translation syscall from [%s]: 0x%08x->?\n", vm->vm_name, pa); 30#ifdef CONFIG_ARCH_AARCH64 31#else 32 regs->r0 = pa; 33#endif 34} 35 36#if 0 37/* sys_ipa_to_pa currently not supported 38 * TODO: Re-enable or re-evaluate support for syscall 39 */ 40static void sys_ipa_to_pa(vm_t *vm, seL4_UserContext *regs) 41{ 42 seL4_ARM_Page_GetAddress_t ret; 43 long ipa; 44 int err; 45 seL4_CPtr cap; 46#ifdef CONFIG_ARCH_AARCH64 47#else 48 ipa = regs->r0; 49#endif 50 cap = vspace_get_cap(vm_get_vspace(vm), (void *)ipa); 51 if (cap == seL4_CapNull) { 52 err = vm_alloc_guest_ram_at(vm, ipa, 0x1000); 53 if (err) { 54 printf("Could not map address for IPA translation\n"); 55 return; 56 } 57 cap = vspace_get_cap(vm_get_vspace(vm), (void *)ipa); 58 assert(cap != seL4_CapNull); 59 } 60 61 ret = seL4_ARM_Page_GetAddress(cap); 62 assert(!ret.error); 63 ZF_LOGD("IPA translation syscall from [%s]: 0x%08x->0x%08x\n", 64 vm->vm_name, ipa, ret.paddr); 65#ifdef CONFIG_ARCH_AARCH64 66#else 67 regs->r0 = ret.paddr; 68#endif 69} 70#endif 71 72static void sys_nop(vm_t *vm, seL4_UserContext *regs) 73{ 74 ZF_LOGD("NOP syscall from [%s]\n", vm->vm_name); 75} 76 77static int handle_syscall(vm_vcpu_t *vcpu) 78{ 79 seL4_Word syscall, ip; 80 seL4_UserContext regs; 81 seL4_CPtr tcb; 82 vm_t *vm; 83 int err; 84 85 vm = vcpu->vm; 86 syscall = seL4_GetMR(seL4_UnknownSyscall_Syscall); 87 ip = seL4_GetMR(seL4_UnknownSyscall_FaultIP); 88 89 tcb = vm_get_vcpu_tcb(vcpu); 90 err = seL4_TCB_ReadRegisters(tcb, false, 0, sizeof(regs) / sizeof(regs.pc), ®s); 91 assert(!err); 92 regs.pc += 4; 93 94 ZF_LOGI("Syscall %d from [%s]\n", syscall, vm->vm_name); 95 switch (syscall) { 96 case SYS_PA_TO_IPA: 97 sys_pa_to_ipa(vm, ®s); 98 break; 99#if 0 100 case SYS_IPA_TO_PA: 101 /* sys_ipa_to_pa currently not supported 102 * TODO: Re-enable or re-evaluate support for syscall 103 */ 104 sys_ipa_to_pa(vcpu->vm, ®s); 105 break; 106#endif 107 case SYS_NOP: 108 sys_nop(vm, ®s); 109 break; 110 default: 111 ZF_LOGE("%sBad syscall from [%s]: scno %zd at PC: %p%s\n", 112 ANSI_COLOR(RED, BOLD), vm->vm_name, syscall, (void *) ip, ANSI_COLOR(RESET)); 113 return -1; 114 } 115 err = seL4_TCB_WriteRegisters(tcb, false, 0, sizeof(regs) / sizeof(regs.pc), ®s); 116 assert(!err); 117 return VM_EXIT_HANDLED; 118} 119 120int vm_syscall_handler(vm_vcpu_t *vcpu) 121{ 122 int err; 123 err = handle_syscall(vcpu); 124 if (!err) { 125 seL4_MessageInfo_t reply; 126 reply = seL4_MessageInfo_new(0, 0, 0, 0); 127 seL4_Reply(reply); 128 } 129 return err; 130} 131