1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2021 SUSE LLC <mdoucha@suse.cz> 4 * 5 * Minimal testing library for KVM tests 6 */ 7 8#include "kvm_test.h" 9 10extern char kvm_heap_begin[]; 11 12static struct tst_kvm_result *const test_result = 13 (struct tst_kvm_result *)KVM_RESULT_BASEADDR; 14 15static char *heap_end = kvm_heap_begin; 16 17static struct tst_intr_handler { 18 tst_interrupt_callback callback; 19 void *userdata; 20} intr_handlers[INTERRUPT_COUNT]; 21 22void *memset(void *dest, int val, size_t size) 23{ 24 char *ptr = dest; 25 26 while (size--) 27 *ptr++ = val; 28 29 return dest; 30} 31 32void *memzero(void *dest, size_t size) 33{ 34 return memset(dest, 0, size); 35} 36 37void *memcpy(void *dest, const void *src, size_t size) 38{ 39 char *dptr = dest; 40 const char *sptr = src; 41 42 while (size--) 43 *dptr++ = *sptr++; 44 45 return dest; 46} 47 48char *strcpy(char *dest, const char *src) 49{ 50 char *ret = dest; 51 52 while ((*dest++ = *src++)) 53 ; 54 55 return ret; 56} 57 58char *strcat(char *dest, const char *src) 59{ 60 char *ret = dest; 61 62 for (; *dest; dest++) 63 ; 64 65 strcpy(dest, src); 66 return ret; 67} 68 69size_t strlen(const char *str) 70{ 71 size_t ret; 72 73 for (ret = 0; str[ret]; ret++) 74 ; 75 76 return ret; 77} 78 79char *ptr2hex(char *dest, uintptr_t val) 80{ 81 unsigned int i; 82 uintptr_t tmp; 83 char *ret = dest; 84 85 for (i = 4, tmp = val >> 4; tmp; i += 4, tmp >>= 4) 86 ; 87 88 do { 89 i -= 4; 90 tmp = (val >> i) & 0xf; 91 *dest++ = tmp + (tmp >= 10 ? 'A' - 10 : '0'); 92 } while (i); 93 94 *dest = '\0'; 95 return ret; 96} 97 98void *tst_heap_alloc_aligned(size_t size, size_t align) 99{ 100 uintptr_t addr = (uintptr_t)heap_end; 101 void *ret; 102 103 addr += align - 1; 104 addr -= addr % align; 105 ret = (void *)addr; 106 heap_end = (char *)LTP_ALIGN(addr + size, 4); 107 return ret; 108} 109 110void *tst_heap_alloc(size_t size) 111{ 112 void *ret = heap_end; 113 114 heap_end += LTP_ALIGN(size, 4); 115 return ret; 116} 117 118void tst_set_interrupt_callback(unsigned int vector, 119 tst_interrupt_callback func, void *userdata) 120{ 121 if (vector >= INTERRUPT_COUNT) 122 tst_brk(TBROK, "Set interrupt callback: vector out of range"); 123 124 intr_handlers[vector].callback = func; 125 intr_handlers[vector].userdata = userdata; 126} 127 128static void tst_fatal_error(const char *file, const int lineno, 129 const char *message, uintptr_t ip) 130{ 131 test_result->result = TBROK; 132 test_result->lineno = lineno; 133 test_result->file_addr = (uintptr_t)file; 134 strcpy(test_result->message, message); 135 strcat(test_result->message, " at address 0x"); 136 ptr2hex(test_result->message + strlen(test_result->message), ip); 137 kvm_yield(); 138 kvm_exit(); 139} 140 141void tst_res_(const char *file, const int lineno, int result, 142 const char *message) 143{ 144 test_result->result = result; 145 test_result->lineno = lineno; 146 test_result->file_addr = (uintptr_t)file; 147 strcpy(test_result->message, message); 148 kvm_yield(); 149} 150 151void tst_brk_(const char *file, const int lineno, int result, 152 const char *message) 153{ 154 tst_res_(file, lineno, result, message); 155 kvm_exit(); 156} 157 158void tst_signal_host(void *data) 159{ 160 test_result->file_addr = (uintptr_t)data; 161 test_result->result = KVM_TSYNC; 162} 163 164void tst_wait_host(void *data) 165{ 166 volatile int32_t *vres = &test_result->result; 167 168 tst_signal_host(data); 169 170 while (*vres != KVM_TNONE) 171 ; 172} 173 174void tst_handle_interrupt(struct kvm_interrupt_frame *ifrm, long vector, 175 unsigned long errcode) 176{ 177 uintptr_t ip = kvm_get_interrupt_ip(ifrm); 178 const char *iname; 179 tst_interrupt_callback callback; 180 int ret = 0; 181 182 if (vector < 0 || vector >= INTERRUPT_COUNT) 183 tst_fatal_error(__FILE__, __LINE__, "Unexpected interrupt", ip); 184 185 callback = intr_handlers[vector].callback; 186 187 if (callback) 188 ret = callback(intr_handlers[vector].userdata, ifrm, errcode); 189 190 iname = tst_interrupt_names[vector]; 191 iname = iname ? iname : "Unexpected interrupt"; 192 193 if (!ret) 194 tst_fatal_error(__FILE__, __LINE__, iname, ip); 195} 196