• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10 extern char kvm_heap_begin[];
11 
12 static struct tst_kvm_result *const test_result =
13 	(struct tst_kvm_result *)KVM_RESULT_BASEADDR;
14 
15 static char *heap_end = kvm_heap_begin;
16 
17 static struct tst_intr_handler {
18 	tst_interrupt_callback callback;
19 	void *userdata;
20 } intr_handlers[INTERRUPT_COUNT];
21 
memset(void * dest,int val,size_t size)22 void *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 
memzero(void * dest,size_t size)32 void *memzero(void *dest, size_t size)
33 {
34 	return memset(dest, 0, size);
35 }
36 
memcpy(void * dest,const void * src,size_t size)37 void *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 
strcpy(char * dest,const char * src)48 char *strcpy(char *dest, const char *src)
49 {
50 	char *ret = dest;
51 
52 	while ((*dest++ = *src++))
53 		;
54 
55 	return ret;
56 }
57 
strcat(char * dest,const char * src)58 char *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 
strlen(const char * str)69 size_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 
ptr2hex(char * dest,uintptr_t val)79 char *ptr2hex(char *dest, uintptr_t val)
80 {
81 	unsigned int i;
82 	uintptr_t tmp;
83 	char *ret = dest;
84 
85 	for (i = 4; val >> i; i += 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 
tst_heap_alloc_aligned(size_t size,size_t align)98 void *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 
tst_heap_alloc(size_t size)110 void *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 
tst_set_interrupt_callback(unsigned int vector,tst_interrupt_callback func,void * userdata)118 void 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 
tst_fatal_error(const char * file,const int lineno,const char * message,uintptr_t ip)128 static 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 
tst_res_(const char * file,const int lineno,int result,const char * message)141 void 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 
tst_brk_(const char * file,const int lineno,int result,const char * message)151 void 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 
tst_handle_interrupt(struct kvm_interrupt_frame * ifrm,long vector,unsigned long errcode)158 void tst_handle_interrupt(struct kvm_interrupt_frame *ifrm, long vector,
159 	unsigned long errcode)
160 {
161 	uintptr_t ip = kvm_get_interrupt_ip(ifrm);
162 	const char *iname;
163 	tst_interrupt_callback callback;
164 	int ret = 0;
165 
166 	if (vector < 0 || vector >= INTERRUPT_COUNT)
167 		tst_fatal_error(__FILE__, __LINE__, "Unexpected interrupt", ip);
168 
169 	callback = intr_handlers[vector].callback;
170 
171 	if (callback)
172 		ret = callback(intr_handlers[vector].userdata, ifrm, errcode);
173 
174 	iname = tst_interrupt_names[vector];
175 	iname = iname ? iname : "Unexpected interrupt";
176 
177 	if (!ret)
178 		tst_fatal_error(__FILE__, __LINE__, iname, ip);
179 }
180