1 #pragma once 2 3 #include <DragonOS/stdint.h> 4 #include <stdbool.h> 5 #include <common/stddef.h> 6 7 // 定义类型的缩写 8 typedef unsigned char uchar; 9 typedef unsigned short ushort; 10 typedef unsigned int uint; 11 typedef unsigned long ul; 12 typedef unsigned long long int ull; 13 typedef long long int ll; 14 15 #define sti() __asm__ __volatile__("sti\n\t" :: \ 16 : "memory") // 开启外部中断 17 #define cli() __asm__ __volatile__("cli\n\t" :: \ 18 : "memory") // 关闭外部中断 19 #define nop() __asm__ __volatile__("nop\n\t") 20 #define hlt() __asm__ __volatile__("hlt\n\t") 21 #define pause() asm volatile("pause\n\t"); // 处理器等待一段时间 22 23 // 内存屏障 24 #define io_mfence() __asm__ __volatile__("mfence\n\t" :: \ 25 : "memory") // 在mfence指令前的读写操作必须在mfence指令后的读写操作前完成。 26 #define io_sfence() __asm__ __volatile__("sfence\n\t" :: \ 27 : "memory") // 在sfence指令前的写操作必须在sfence指令后的写操作前完成 28 #define io_lfence() __asm__ __volatile__("lfence\n\t" :: \ 29 : "memory") // 在lfence指令前的读操作必须在lfence指令后的读操作前完成。 30 31 /* 32 * Macros to generate condition code outputs from inline assembly, 33 * The output operand must be type "bool". 34 */ 35 // 如果编译器支持输出标志寄存器值到变量的话,则会定义__GCC_ASM_FLAG_OUTPUTS__ 36 #ifdef __GCC_ASM_FLAG_OUTPUTS__ 37 // CC_SET(c)则是用于设置标志寄存器中的某一位 38 #define CC_SET(c) "\n\t/* output condition code " #c "*/\n" 39 // "=@cccond"的用法是,将标志寄存器中的cond(也就是指令集定义的标准条件)的值输出到变量中 40 #define CC_OUT(c) "=@cc" #c 41 #else 42 #define CC_SET(c) "\n\tset" #c " %[_cc_" #c "]\n" 43 #define CC_OUT(c) [_cc_##c] "=qm" 44 #endif 45 46 #define rdtsc() ({ \ 47 uint64_t tmp1 = 0, tmp2 = 0; \ 48 asm volatile("rdtsc" \ 49 : "=d"(tmp1), "=a"(tmp2)::"memory"); \ 50 (tmp1 << 32 | tmp2); \ 51 }) 52 53 /** 54 * @brief 读取rsp寄存器的值(存储了页目录的基地址) 55 * 56 * @return unsigned* rsp的值的指针 57 */ 58 unsigned long *get_rsp() 59 { 60 uint64_t *tmp; 61 __asm__ __volatile__( 62 "movq %%rsp, %0\n\t" 63 : "=r"(tmp)::"memory"); 64 return tmp; 65 } 66 67 /** 68 * @brief 验证地址空间是否为用户地址空间 69 * 70 * @param addr_start 地址起始值 71 * @param length 地址长度 72 * @return true 73 * @return false 74 */ 75 bool verify_area(uint64_t addr_start, uint64_t length) 76 { 77 if ((addr_start + length) <= 0x00007fffffffffffUL) // 用户程序可用的的地址空间应<= 0x00007fffffffffffUL 78 return true; 79 else 80 return false; 81 } 82 83 /** 84 * @brief 读取rbp寄存器的值(存储了页目录的基地址) 85 * 86 * @return unsigned* rbp的值的指针 87 */ 88 unsigned long *get_rbp() 89 { 90 uint64_t *tmp; 91 __asm__ __volatile__( 92 "movq %%rbp, %0\n\t" 93 : "=r"(tmp)::"memory"); 94 return tmp; 95 } 96 97 /** 98 * @brief 读取ds寄存器的值(存储了页目录的基地址) 99 * 100 * @return unsigned* ds的值的指针 101 */ 102 unsigned long *get_ds() 103 { 104 uint64_t *tmp; 105 __asm__ __volatile__( 106 "movq %%ds, %0\n\t" 107 : "=r"(tmp)::"memory"); 108 return tmp; 109 } 110 111 /** 112 * @brief 读取rax寄存器的值(存储了页目录的基地址) 113 * 114 * @return unsigned* rax的值的指针 115 */ 116 unsigned long *get_rax() 117 { 118 uint64_t *tmp; 119 __asm__ __volatile__( 120 "movq %%rax, %0\n\t" 121 : "=r"(tmp)::"memory"); 122 return tmp; 123 } 124 /** 125 * @brief 读取rbx寄存器的值(存储了页目录的基地址) 126 * 127 * @return unsigned* rbx的值的指针 128 */ 129 unsigned long *get_rbx() 130 { 131 uint64_t *tmp; 132 __asm__ __volatile__( 133 "movq %%rbx, %0\n\t" 134 : "=r"(tmp)::"memory"); 135 return tmp; 136 } 137 138 // ========= MSR寄存器组操作 ============= 139 /** 140 * @brief 向msr寄存器组的address处的寄存器写入值value 141 * 142 * @param address 地址 143 * @param value 要写入的值 144 */ 145 void wrmsr(uint64_t address, uint64_t value) 146 { 147 __asm__ __volatile__("wrmsr \n\t" ::"d"(value >> 32), "a"(value & 0xffffffff), "c"(address) 148 : "memory"); 149 } 150 151 /** 152 * @brief 从msr寄存器组的address地址处读取值 153 * rdmsr返回高32bits在edx,低32bits在eax 154 * @param address 地址 155 * @return uint64_t address处的寄存器的值 156 */ 157 uint64_t rdmsr(uint64_t address) 158 { 159 unsigned int tmp0, tmp1; 160 __asm__ __volatile__("rdmsr \n\t" 161 : "=d"(tmp0), "=a"(tmp1) 162 : "c"(address) 163 : "memory"); 164 return ((uint64_t)tmp0 << 32) | tmp1; 165 } 166 167 uint64_t get_rflags() 168 { 169 unsigned long tmp = 0; 170 __asm__ __volatile__("pushfq \n\t" 171 "movq (%%rsp), %0 \n\t" 172 "popfq \n\t" 173 : "=r"(tmp)::"memory"); 174 return tmp; 175 } 176 177 void *memset(void *dst, unsigned char C, ul size) 178 { 179 180 int d0, d1; 181 unsigned long tmp = C * 0x0101010101010101UL; 182 __asm__ __volatile__("cld \n\t" 183 "rep \n\t" 184 "stosq \n\t" 185 "testb $4, %b3 \n\t" 186 "je 1f \n\t" 187 "stosl \n\t" 188 "1:\ttestb $2, %b3 \n\t" 189 "je 2f\n\t" 190 "stosw \n\t" 191 "2:\ttestb $1, %b3 \n\t" 192 "je 3f \n\t" 193 "stosb \n\t" 194 "3: \n\t" 195 : "=&c"(d0), "=&D"(d1) 196 : "a"(tmp), "q"(size), "0"(size / 8), "1"(dst) 197 : "memory"); 198 return dst; 199 } 200 201 void *memset_c(void *dst, uint8_t c, size_t count) 202 { 203 uint8_t *xs = (uint8_t *)dst; 204 205 while (count--) 206 *xs++ = c; 207 208 return dst; 209 } 210 211 /** 212 * @brief 内存拷贝函数 213 * 214 * @param dst 目标数组 215 * @param src 源数组 216 * @param Num 字节数 217 * @return void* 218 */ 219 static void *memcpy(void *dst, const void *src, long Num) 220 { 221 int d0 = 0, d1 = 0, d2 = 0; 222 __asm__ __volatile__("cld \n\t" 223 "rep \n\t" 224 "movsq \n\t" 225 "testb $4,%b4 \n\t" 226 "je 1f \n\t" 227 "movsl \n\t" 228 "1:\ttestb $2,%b4 \n\t" 229 "je 2f \n\t" 230 "movsw \n\t" 231 "2:\ttestb $1,%b4 \n\t" 232 "je 3f \n\t" 233 "movsb \n\t" 234 "3: \n\t" 235 : "=&c"(d0), "=&D"(d1), "=&S"(d2) 236 : "0"(Num / 8), "q"(Num), "1"(dst), "2"(src) 237 : "memory"); 238 return dst; 239 } 240 241 // 从io口读入8个bit 242 unsigned char io_in8(unsigned short port) 243 { 244 unsigned char ret = 0; 245 __asm__ __volatile__("inb %%dx, %0 \n\t" 246 "mfence \n\t" 247 : "=a"(ret) 248 : "d"(port) 249 : "memory"); 250 return ret; 251 } 252 253 // 从io口读入32个bit 254 unsigned int io_in32(unsigned short port) 255 { 256 unsigned int ret = 0; 257 __asm__ __volatile__("inl %%dx, %0 \n\t" 258 "mfence \n\t" 259 : "=a"(ret) 260 : "d"(port) 261 : "memory"); 262 return ret; 263 } 264 265 // 输出8个bit到输出端口 266 void io_out8(unsigned short port, unsigned char value) 267 { 268 __asm__ __volatile__("outb %0, %%dx \n\t" 269 "mfence \n\t" 270 : 271 : "a"(value), "d"(port) 272 : "memory"); 273 } 274 275 // 输出32个bit到输出端口 276 void io_out32(unsigned short port, unsigned int value) 277 { 278 __asm__ __volatile__("outl %0, %%dx \n\t" 279 "mfence \n\t" 280 : 281 : "a"(value), "d"(port) 282 : "memory"); 283 } 284 285 /** 286 * @brief 从端口读入n个word到buffer 287 * 288 */ 289 #define io_insw(port, buffer, nr) \ 290 __asm__ __volatile__("cld;rep;insw;mfence;" ::"d"(port), "D"(buffer), "c"(nr) \ 291 : "memory") 292 293 /** 294 * @brief 从输出buffer中的n个word到端口 295 * 296 */ 297 #define io_outsw(port, buffer, nr) \ 298 __asm__ __volatile__("cld;rep;outsw;mfence;" ::"d"(port), "S"(buffer), "c"(nr) \ 299 : "memory") 300 301 /** 302 * @brief 从用户空间搬运数据到内核空间 303 * 304 * @param dst 目的地址 305 * @param src 源地址 306 * @param size 搬运的大小 307 * @return uint64_t 308 */ 309 static inline uint64_t copy_from_user(void *dst, void *src, uint64_t size) 310 { 311 uint64_t tmp0, tmp1; 312 if (!verify_area((uint64_t)src, size)) 313 return 0; 314 315 /** 316 * @brief 先每次搬运8 bytes,剩余就直接一个个byte搬运 317 * 318 */ 319 asm volatile("rep \n\t" 320 "movsq \n\t" 321 "movq %3, %0 \n\t" 322 "rep \n\t" 323 "movsb \n\t" 324 : "=&c"(size), "=&D"(tmp0), "=&S"(tmp1) 325 : "r"(size & 7), "0"(size >> 3), "1"(dst), "2"(src) 326 : "memory"); 327 return size; 328 } 329 330 /** 331 * @brief 从内核空间搬运数据到用户空间 332 * 333 * @param dst 目的地址 334 * @param src 源地址 335 * @param size 搬运的大小 336 * @return uint64_t 337 */ 338 static inline uint64_t copy_to_user(void *dst, void *src, uint64_t size) 339 { 340 if (verify_area((uint64_t)src, size)) 341 return 0; 342 343 /** 344 * @brief 先每次搬运8 bytes,剩余就直接一个个byte搬运 345 * 346 */ 347 // todo:编译有bug 348 // asm volatile("rep \n\t" 349 // "movsq \n\t" 350 // "movq %3, %0 \n\t" 351 // "rep \n\t" 352 // "movsb \n\t" 353 // : "=&c"(size), "=&D"(tmp0), "=&S"(tmp1) 354 // : "r"(size & 7), "0"(size >> 3), "1"(dst), "2"(src) 355 // : "memory"); 356 memcpy(dst, src, size); 357 358 return size; 359 } 360 361 /** 362 * @brief 往指定地址写入8字节 363 * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候) 364 * 365 * @param vaddr 虚拟地址 366 * @param value 要写入的值 367 */ 368 static __always_inline void __write8b(uint64_t vaddr, uint64_t value) 369 { 370 asm volatile("movq %%rdx, 0(%%rax)" ::"a"(vaddr), "d"(value) 371 : "memory"); 372 } 373 374 /** 375 * @brief 往指定地址写入4字节 376 * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候) 377 * 378 * @param vaddr 虚拟地址 379 * @param value 要写入的值 380 */ 381 static __always_inline void __write4b(uint64_t vaddr, uint32_t value) 382 { 383 asm volatile("movl %%edx, 0(%%rax)" ::"a"(vaddr), "d"(value) 384 : "memory"); 385 } 386 387 /** 388 * @brief 从指定地址读取8字节 389 * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候) 390 * 391 * @param vaddr 虚拟地址 392 * @return uint64_t 读取到的值 393 */ 394 static __always_inline uint64_t __read8b(uint64_t vaddr) 395 { 396 uint64_t retval; 397 asm volatile("movq 0(%%rax), %0" 398 : "=r"(retval) 399 : "a"(vaddr) 400 : "memory"); 401 return retval; 402 } 403 404 /** 405 * @brief 从指定地址读取4字节 406 * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候) 407 * 408 * @param vaddr 虚拟地址 409 * @return uint64_t 读取到的值 410 */ 411 static __always_inline uint32_t __read4b(uint64_t vaddr) 412 { 413 uint32_t retval; 414 asm volatile("movl 0(%%rax), %0" 415 : "=d"(retval) 416 : "a"(vaddr) 417 : "memory"); 418 return retval; 419 }