166f67c6aSlogin #pragma once
266f67c6aSlogin
30e0c1874Slogin #include <DragonOS/stdint.h>
446e234aeSLoGin #include <stdbool.h>
546e234aeSLoGin #include <common/stddef.h>
646e234aeSLoGin
7*4fda81ceSLoGin
866f67c6aSlogin
966f67c6aSlogin #define sti() __asm__ __volatile__("sti\n\t" :: \
1066f67c6aSlogin : "memory") // 开启外部中断
1166f67c6aSlogin #define cli() __asm__ __volatile__("cli\n\t" :: \
1266f67c6aSlogin : "memory") // 关闭外部中断
1366f67c6aSlogin #define nop() __asm__ __volatile__("nop\n\t")
1466f67c6aSlogin #define hlt() __asm__ __volatile__("hlt\n\t")
1566f67c6aSlogin #define pause() asm volatile("pause\n\t"); // 处理器等待一段时间
1666f67c6aSlogin
1766f67c6aSlogin // 内存屏障
1866f67c6aSlogin #define io_mfence() __asm__ __volatile__("mfence\n\t" :: \
1966f67c6aSlogin : "memory") // 在mfence指令前的读写操作必须在mfence指令后的读写操作前完成。
2066f67c6aSlogin #define io_sfence() __asm__ __volatile__("sfence\n\t" :: \
2166f67c6aSlogin : "memory") // 在sfence指令前的写操作必须在sfence指令后的写操作前完成
2266f67c6aSlogin #define io_lfence() __asm__ __volatile__("lfence\n\t" :: \
2366f67c6aSlogin : "memory") // 在lfence指令前的读操作必须在lfence指令后的读操作前完成。
2466f67c6aSlogin
2566f67c6aSlogin /*
2666f67c6aSlogin * Macros to generate condition code outputs from inline assembly,
2766f67c6aSlogin * The output operand must be type "bool".
2866f67c6aSlogin */
2966f67c6aSlogin // 如果编译器支持输出标志寄存器值到变量的话,则会定义__GCC_ASM_FLAG_OUTPUTS__
3066f67c6aSlogin #ifdef __GCC_ASM_FLAG_OUTPUTS__
3166f67c6aSlogin // CC_SET(c)则是用于设置标志寄存器中的某一位
3266f67c6aSlogin #define CC_SET(c) "\n\t/* output condition code " #c "*/\n"
3366f67c6aSlogin // "=@cccond"的用法是,将标志寄存器中的cond(也就是指令集定义的标准条件)的值输出到变量中
3466f67c6aSlogin #define CC_OUT(c) "=@cc" #c
3566f67c6aSlogin #else
3666f67c6aSlogin #define CC_SET(c) "\n\tset" #c " %[_cc_" #c "]\n"
3766f67c6aSlogin #define CC_OUT(c) [_cc_##c] "=qm"
3866f67c6aSlogin #endif
3966f67c6aSlogin
4066f67c6aSlogin #define rdtsc() ({ \
4166f67c6aSlogin uint64_t tmp1 = 0, tmp2 = 0; \
4266f67c6aSlogin asm volatile("rdtsc" \
4366f67c6aSlogin : "=d"(tmp1), "=a"(tmp2)::"memory"); \
4466f67c6aSlogin (tmp1 << 32 | tmp2); \
4566f67c6aSlogin })
4666f67c6aSlogin
4766f67c6aSlogin /**
4866f67c6aSlogin * @brief 读取rsp寄存器的值(存储了页目录的基地址)
4966f67c6aSlogin *
5066f67c6aSlogin * @return unsigned* rsp的值的指针
5166f67c6aSlogin */
get_rsp()5266f67c6aSlogin unsigned long *get_rsp()
5366f67c6aSlogin {
5466f67c6aSlogin uint64_t *tmp;
5566f67c6aSlogin __asm__ __volatile__(
5666f67c6aSlogin "movq %%rsp, %0\n\t"
5766f67c6aSlogin : "=r"(tmp)::"memory");
5866f67c6aSlogin return tmp;
5966f67c6aSlogin }
6066f67c6aSlogin
6166f67c6aSlogin /**
6246e234aeSLoGin * @brief 验证地址空间是否为用户地址空间
6346e234aeSLoGin *
6446e234aeSLoGin * @param addr_start 地址起始值
6546e234aeSLoGin * @param length 地址长度
6646e234aeSLoGin * @return true
6746e234aeSLoGin * @return false
6846e234aeSLoGin */
verify_area(uint64_t addr_start,uint64_t length)6946e234aeSLoGin bool verify_area(uint64_t addr_start, uint64_t length)
7046e234aeSLoGin {
7146e234aeSLoGin if ((addr_start + length) <= 0x00007fffffffffffUL) // 用户程序可用的的地址空间应<= 0x00007fffffffffffUL
7246e234aeSLoGin return true;
7346e234aeSLoGin else
7446e234aeSLoGin return false;
7546e234aeSLoGin }
7646e234aeSLoGin
7746e234aeSLoGin /**
7866f67c6aSlogin * @brief 读取rbp寄存器的值(存储了页目录的基地址)
7966f67c6aSlogin *
8066f67c6aSlogin * @return unsigned* rbp的值的指针
8166f67c6aSlogin */
get_rbp()8266f67c6aSlogin unsigned long *get_rbp()
8366f67c6aSlogin {
8466f67c6aSlogin uint64_t *tmp;
8566f67c6aSlogin __asm__ __volatile__(
8666f67c6aSlogin "movq %%rbp, %0\n\t"
8766f67c6aSlogin : "=r"(tmp)::"memory");
8866f67c6aSlogin return tmp;
8966f67c6aSlogin }
9066f67c6aSlogin
9166f67c6aSlogin /**
9266f67c6aSlogin * @brief 读取ds寄存器的值(存储了页目录的基地址)
9366f67c6aSlogin *
9466f67c6aSlogin * @return unsigned* ds的值的指针
9566f67c6aSlogin */
get_ds()9666f67c6aSlogin unsigned long *get_ds()
9766f67c6aSlogin {
9866f67c6aSlogin uint64_t *tmp;
9966f67c6aSlogin __asm__ __volatile__(
10066f67c6aSlogin "movq %%ds, %0\n\t"
10166f67c6aSlogin : "=r"(tmp)::"memory");
10266f67c6aSlogin return tmp;
10366f67c6aSlogin }
10466f67c6aSlogin
10566f67c6aSlogin /**
10666f67c6aSlogin * @brief 读取rax寄存器的值(存储了页目录的基地址)
10766f67c6aSlogin *
10866f67c6aSlogin * @return unsigned* rax的值的指针
10966f67c6aSlogin */
get_rax()11066f67c6aSlogin unsigned long *get_rax()
11166f67c6aSlogin {
11266f67c6aSlogin uint64_t *tmp;
11366f67c6aSlogin __asm__ __volatile__(
11466f67c6aSlogin "movq %%rax, %0\n\t"
11566f67c6aSlogin : "=r"(tmp)::"memory");
11666f67c6aSlogin return tmp;
11766f67c6aSlogin }
11866f67c6aSlogin /**
11966f67c6aSlogin * @brief 读取rbx寄存器的值(存储了页目录的基地址)
12066f67c6aSlogin *
12166f67c6aSlogin * @return unsigned* rbx的值的指针
12266f67c6aSlogin */
get_rbx()12366f67c6aSlogin unsigned long *get_rbx()
12466f67c6aSlogin {
12566f67c6aSlogin uint64_t *tmp;
12666f67c6aSlogin __asm__ __volatile__(
12766f67c6aSlogin "movq %%rbx, %0\n\t"
12866f67c6aSlogin : "=r"(tmp)::"memory");
12966f67c6aSlogin return tmp;
13066f67c6aSlogin }
13166f67c6aSlogin
get_rflags()13266f67c6aSlogin uint64_t get_rflags()
13366f67c6aSlogin {
13466f67c6aSlogin unsigned long tmp = 0;
13566f67c6aSlogin __asm__ __volatile__("pushfq \n\t"
13666f67c6aSlogin "movq (%%rsp), %0 \n\t"
13766f67c6aSlogin "popfq \n\t"
13866f67c6aSlogin : "=r"(tmp)::"memory");
13966f67c6aSlogin return tmp;
14066f67c6aSlogin }
14146e234aeSLoGin
memset(void * dst,unsigned char C,ul size)14246e234aeSLoGin void *memset(void *dst, unsigned char C, ul size)
14346e234aeSLoGin {
14446e234aeSLoGin
14546e234aeSLoGin int d0, d1;
14646e234aeSLoGin unsigned long tmp = C * 0x0101010101010101UL;
14746e234aeSLoGin __asm__ __volatile__("cld \n\t"
14846e234aeSLoGin "rep \n\t"
14946e234aeSLoGin "stosq \n\t"
15046e234aeSLoGin "testb $4, %b3 \n\t"
15146e234aeSLoGin "je 1f \n\t"
15246e234aeSLoGin "stosl \n\t"
15346e234aeSLoGin "1:\ttestb $2, %b3 \n\t"
15446e234aeSLoGin "je 2f\n\t"
15546e234aeSLoGin "stosw \n\t"
15646e234aeSLoGin "2:\ttestb $1, %b3 \n\t"
15746e234aeSLoGin "je 3f \n\t"
15846e234aeSLoGin "stosb \n\t"
15946e234aeSLoGin "3: \n\t"
16046e234aeSLoGin : "=&c"(d0), "=&D"(d1)
16146e234aeSLoGin : "a"(tmp), "q"(size), "0"(size / 8), "1"(dst)
16246e234aeSLoGin : "memory");
16346e234aeSLoGin return dst;
16446e234aeSLoGin }
16546e234aeSLoGin
memset_c(void * dst,uint8_t c,size_t count)16646e234aeSLoGin void *memset_c(void *dst, uint8_t c, size_t count)
16746e234aeSLoGin {
16846e234aeSLoGin uint8_t *xs = (uint8_t *)dst;
16946e234aeSLoGin
17046e234aeSLoGin while (count--)
17146e234aeSLoGin *xs++ = c;
17246e234aeSLoGin
17346e234aeSLoGin return dst;
17446e234aeSLoGin }
17546e234aeSLoGin
17646e234aeSLoGin /**
17746e234aeSLoGin * @brief 内存拷贝函数
17846e234aeSLoGin *
17946e234aeSLoGin * @param dst 目标数组
18046e234aeSLoGin * @param src 源数组
18146e234aeSLoGin * @param Num 字节数
18246e234aeSLoGin * @return void*
18346e234aeSLoGin */
memcpy(void * dst,const void * src,long Num)18446e234aeSLoGin static void *memcpy(void *dst, const void *src, long Num)
18546e234aeSLoGin {
18646e234aeSLoGin int d0 = 0, d1 = 0, d2 = 0;
18746e234aeSLoGin __asm__ __volatile__("cld \n\t"
18846e234aeSLoGin "rep \n\t"
18946e234aeSLoGin "movsq \n\t"
19046e234aeSLoGin "testb $4,%b4 \n\t"
19146e234aeSLoGin "je 1f \n\t"
19246e234aeSLoGin "movsl \n\t"
19346e234aeSLoGin "1:\ttestb $2,%b4 \n\t"
19446e234aeSLoGin "je 2f \n\t"
19546e234aeSLoGin "movsw \n\t"
19646e234aeSLoGin "2:\ttestb $1,%b4 \n\t"
19746e234aeSLoGin "je 3f \n\t"
19846e234aeSLoGin "movsb \n\t"
19946e234aeSLoGin "3: \n\t"
20046e234aeSLoGin : "=&c"(d0), "=&D"(d1), "=&S"(d2)
20146e234aeSLoGin : "0"(Num / 8), "q"(Num), "1"(dst), "2"(src)
20246e234aeSLoGin : "memory");
20346e234aeSLoGin return dst;
20446e234aeSLoGin }
20546e234aeSLoGin
20646e234aeSLoGin // 从io口读入8个bit
io_in8(unsigned short port)20746e234aeSLoGin unsigned char io_in8(unsigned short port)
20846e234aeSLoGin {
20946e234aeSLoGin unsigned char ret = 0;
21046e234aeSLoGin __asm__ __volatile__("inb %%dx, %0 \n\t"
21146e234aeSLoGin "mfence \n\t"
21246e234aeSLoGin : "=a"(ret)
21346e234aeSLoGin : "d"(port)
21446e234aeSLoGin : "memory");
21546e234aeSLoGin return ret;
21646e234aeSLoGin }
21746e234aeSLoGin
21846e234aeSLoGin // 从io口读入32个bit
io_in32(unsigned short port)21946e234aeSLoGin unsigned int io_in32(unsigned short port)
22046e234aeSLoGin {
22146e234aeSLoGin unsigned int ret = 0;
22246e234aeSLoGin __asm__ __volatile__("inl %%dx, %0 \n\t"
22346e234aeSLoGin "mfence \n\t"
22446e234aeSLoGin : "=a"(ret)
22546e234aeSLoGin : "d"(port)
22646e234aeSLoGin : "memory");
22746e234aeSLoGin return ret;
22846e234aeSLoGin }
22946e234aeSLoGin
23046e234aeSLoGin // 输出8个bit到输出端口
io_out8(unsigned short port,unsigned char value)23146e234aeSLoGin void io_out8(unsigned short port, unsigned char value)
23246e234aeSLoGin {
23346e234aeSLoGin __asm__ __volatile__("outb %0, %%dx \n\t"
23446e234aeSLoGin "mfence \n\t"
23546e234aeSLoGin :
23646e234aeSLoGin : "a"(value), "d"(port)
23746e234aeSLoGin : "memory");
23846e234aeSLoGin }
23946e234aeSLoGin
24046e234aeSLoGin // 输出32个bit到输出端口
io_out32(unsigned short port,unsigned int value)24146e234aeSLoGin void io_out32(unsigned short port, unsigned int value)
24246e234aeSLoGin {
24346e234aeSLoGin __asm__ __volatile__("outl %0, %%dx \n\t"
24446e234aeSLoGin "mfence \n\t"
24546e234aeSLoGin :
24646e234aeSLoGin : "a"(value), "d"(port)
24746e234aeSLoGin : "memory");
24846e234aeSLoGin }
24946e234aeSLoGin
25046e234aeSLoGin /**
25146e234aeSLoGin * @brief 从端口读入n个word到buffer
25246e234aeSLoGin *
25346e234aeSLoGin */
25446e234aeSLoGin #define io_insw(port, buffer, nr) \
25546e234aeSLoGin __asm__ __volatile__("cld;rep;insw;mfence;" ::"d"(port), "D"(buffer), "c"(nr) \
25646e234aeSLoGin : "memory")
25746e234aeSLoGin
25846e234aeSLoGin /**
25946e234aeSLoGin * @brief 从输出buffer中的n个word到端口
26046e234aeSLoGin *
26146e234aeSLoGin */
26246e234aeSLoGin #define io_outsw(port, buffer, nr) \
26346e234aeSLoGin __asm__ __volatile__("cld;rep;outsw;mfence;" ::"d"(port), "S"(buffer), "c"(nr) \
26446e234aeSLoGin : "memory")
26546e234aeSLoGin
26646e234aeSLoGin /**
26746e234aeSLoGin * @brief 从用户空间搬运数据到内核空间
26846e234aeSLoGin *
26946e234aeSLoGin * @param dst 目的地址
27046e234aeSLoGin * @param src 源地址
27146e234aeSLoGin * @param size 搬运的大小
27246e234aeSLoGin * @return uint64_t
27346e234aeSLoGin */
copy_from_user(void * dst,void * src,uint64_t size)27446e234aeSLoGin static inline uint64_t copy_from_user(void *dst, void *src, uint64_t size)
27546e234aeSLoGin {
27646e234aeSLoGin uint64_t tmp0, tmp1;
27746e234aeSLoGin if (!verify_area((uint64_t)src, size))
27846e234aeSLoGin return 0;
27946e234aeSLoGin
28046e234aeSLoGin /**
28146e234aeSLoGin * @brief 先每次搬运8 bytes,剩余就直接一个个byte搬运
28246e234aeSLoGin *
28346e234aeSLoGin */
28446e234aeSLoGin asm volatile("rep \n\t"
28546e234aeSLoGin "movsq \n\t"
28646e234aeSLoGin "movq %3, %0 \n\t"
28746e234aeSLoGin "rep \n\t"
28846e234aeSLoGin "movsb \n\t"
28946e234aeSLoGin : "=&c"(size), "=&D"(tmp0), "=&S"(tmp1)
29046e234aeSLoGin : "r"(size & 7), "0"(size >> 3), "1"(dst), "2"(src)
29146e234aeSLoGin : "memory");
29246e234aeSLoGin return size;
29346e234aeSLoGin }
29446e234aeSLoGin
29546e234aeSLoGin /**
29646e234aeSLoGin * @brief 从内核空间搬运数据到用户空间
29746e234aeSLoGin *
29846e234aeSLoGin * @param dst 目的地址
29946e234aeSLoGin * @param src 源地址
30046e234aeSLoGin * @param size 搬运的大小
30146e234aeSLoGin * @return uint64_t
30246e234aeSLoGin */
copy_to_user(void * dst,void * src,uint64_t size)30346e234aeSLoGin static inline uint64_t copy_to_user(void *dst, void *src, uint64_t size)
30446e234aeSLoGin {
30546e234aeSLoGin if (verify_area((uint64_t)src, size))
30646e234aeSLoGin return 0;
30746e234aeSLoGin
30846e234aeSLoGin /**
30946e234aeSLoGin * @brief 先每次搬运8 bytes,剩余就直接一个个byte搬运
31046e234aeSLoGin *
31146e234aeSLoGin */
31246e234aeSLoGin // todo:编译有bug
31346e234aeSLoGin // asm volatile("rep \n\t"
31446e234aeSLoGin // "movsq \n\t"
31546e234aeSLoGin // "movq %3, %0 \n\t"
31646e234aeSLoGin // "rep \n\t"
31746e234aeSLoGin // "movsb \n\t"
31846e234aeSLoGin // : "=&c"(size), "=&D"(tmp0), "=&S"(tmp1)
31946e234aeSLoGin // : "r"(size & 7), "0"(size >> 3), "1"(dst), "2"(src)
32046e234aeSLoGin // : "memory");
32146e234aeSLoGin memcpy(dst, src, size);
32246e234aeSLoGin
32346e234aeSLoGin return size;
32446e234aeSLoGin }
32546e234aeSLoGin
32646e234aeSLoGin /**
32746e234aeSLoGin * @brief 往指定地址写入8字节
32846e234aeSLoGin * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候)
32946e234aeSLoGin *
33046e234aeSLoGin * @param vaddr 虚拟地址
33146e234aeSLoGin * @param value 要写入的值
33246e234aeSLoGin */
__write8b(uint64_t vaddr,uint64_t value)33346e234aeSLoGin static __always_inline void __write8b(uint64_t vaddr, uint64_t value)
33446e234aeSLoGin {
33546e234aeSLoGin asm volatile("movq %%rdx, 0(%%rax)" ::"a"(vaddr), "d"(value)
33646e234aeSLoGin : "memory");
33746e234aeSLoGin }
33846e234aeSLoGin
33946e234aeSLoGin /**
34046e234aeSLoGin * @brief 往指定地址写入4字节
34146e234aeSLoGin * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候)
34246e234aeSLoGin *
34346e234aeSLoGin * @param vaddr 虚拟地址
34446e234aeSLoGin * @param value 要写入的值
34546e234aeSLoGin */
__write4b(uint64_t vaddr,uint32_t value)34646e234aeSLoGin static __always_inline void __write4b(uint64_t vaddr, uint32_t value)
34746e234aeSLoGin {
34846e234aeSLoGin asm volatile("movl %%edx, 0(%%rax)" ::"a"(vaddr), "d"(value)
34946e234aeSLoGin : "memory");
35046e234aeSLoGin }
35146e234aeSLoGin
35246e234aeSLoGin /**
35346e234aeSLoGin * @brief 从指定地址读取8字节
35446e234aeSLoGin * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候)
35546e234aeSLoGin *
35646e234aeSLoGin * @param vaddr 虚拟地址
35746e234aeSLoGin * @return uint64_t 读取到的值
35846e234aeSLoGin */
__read8b(uint64_t vaddr)35946e234aeSLoGin static __always_inline uint64_t __read8b(uint64_t vaddr)
36046e234aeSLoGin {
36146e234aeSLoGin uint64_t retval;
36246e234aeSLoGin asm volatile("movq 0(%%rax), %0"
36346e234aeSLoGin : "=r"(retval)
36446e234aeSLoGin : "a"(vaddr)
36546e234aeSLoGin : "memory");
36646e234aeSLoGin return retval;
36746e234aeSLoGin }
36846e234aeSLoGin
36946e234aeSLoGin /**
37046e234aeSLoGin * @brief 从指定地址读取4字节
37146e234aeSLoGin * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候)
37246e234aeSLoGin *
37346e234aeSLoGin * @param vaddr 虚拟地址
37446e234aeSLoGin * @return uint64_t 读取到的值
37546e234aeSLoGin */
__read4b(uint64_t vaddr)37646e234aeSLoGin static __always_inline uint32_t __read4b(uint64_t vaddr)
37746e234aeSLoGin {
37846e234aeSLoGin uint32_t retval;
37946e234aeSLoGin asm volatile("movl 0(%%rax), %0"
38046e234aeSLoGin : "=d"(retval)
38146e234aeSLoGin : "a"(vaddr)
38246e234aeSLoGin : "memory");
38346e234aeSLoGin return retval;
38446e234aeSLoGin }
385*4fda81ceSLoGin
386*4fda81ceSLoGin
387*4fda81ceSLoGin /**
388*4fda81ceSLoGin * @brief 逐字节比较指定内存区域的值,并返回s1、s2的第一个不相等的字节i处的差值(s1[i]-s2[i])。
389*4fda81ceSLoGin * 若两块内存区域的内容相同,则返回0
390*4fda81ceSLoGin *
391*4fda81ceSLoGin * @param s1 内存区域1
392*4fda81ceSLoGin * @param s2 内存区域2
393*4fda81ceSLoGin * @param len 要比较的内存区域长度
394*4fda81ceSLoGin * @return int s1、s2的第一个不相等的字节i处的差值(s1[i]-s2[i])。若两块内存区域的内容相同,则返回0
395*4fda81ceSLoGin */
memcmp(const void * s1,const void * s2,size_t len)396*4fda81ceSLoGin static inline int memcmp(const void *s1, const void *s2, size_t len)
397*4fda81ceSLoGin {
398*4fda81ceSLoGin int diff;
399*4fda81ceSLoGin
400*4fda81ceSLoGin asm("cld \n\t" // 复位DF,确保s1、s2指针是自增的
401*4fda81ceSLoGin "repz; cmpsb\n\t" CC_SET(nz)
402*4fda81ceSLoGin : CC_OUT(nz)(diff), "+D"(s1), "+S"(s2)
403*4fda81ceSLoGin : "c"(len)
404*4fda81ceSLoGin : "memory");
405*4fda81ceSLoGin
406*4fda81ceSLoGin if (diff)
407*4fda81ceSLoGin diff = *(const unsigned char *)(s1 - 1) - *(const unsigned char *)(s2 - 1);
408*4fda81ceSLoGin
409*4fda81ceSLoGin return diff;
410*4fda81ceSLoGin }
411