Browse Source

:new: 用户/内核内存拷贝函数

fslongjin 2 years ago
parent
commit
59cbd6c4fc
2 changed files with 122 additions and 42 deletions
  1. 8 0
      kernel/common/errno.h
  2. 114 42
      kernel/common/glib.h

+ 8 - 0
kernel/common/errno.h

@@ -19,6 +19,7 @@
 #define EALREADY 7         /* 连接已经在处理 Connection already in progress. */
 #define EBADF 8            /* 错误的文件描述符 Bad file descriptor. */
 #define EBADMSG 9          /* 错误的消息 Bad message. */
+
 #define EBUSY 10           /* 设备或资源忙 Device or resource busy. */
 #define ECANCELED 11       /* 操作被取消 Operation canceled. */
 #define ECHILD 12          /* 没有子进程 No child processes. */
@@ -29,6 +30,7 @@
 #define EDESTADDRREQ 17    /* 需要目标地址 Destination address required.*/
 #define EDOM 18            /* 数学参数超出作用域 Mathematics argument out of domain of function. */
 #define EDQUOT 19          /* 保留使用 Reserved */
+
 #define EEXIST 20          /* 文件已存在 File exists. */
 #define EFAULT 21          /* 错误的地址 Bad address */
 #define EFBIG 22           /* 文件太大 File too large. */
@@ -39,6 +41,7 @@
 #define EINTR 27           /* 被中断的函数 Interrupted function. */
 #define EINVAL 28          /* 不可用的参数 Invalid argument. */
 #define EIO 29             /* I/O错误 I/O error. */
+
 #define EISCONN 30         /* 套接字已连接 Socket is connected. */
 #define EISDIR 31          /* 是一个目录 Is a directory */
 #define ELOOP 32           /* 符号链接级别过多 Too many levels of symbolic links. */
@@ -49,6 +52,7 @@
 #define ENAMETOOLONG 37    /* 文件名过长 Filename too long. */
 #define ENETDOWN 38        /* 网络已关闭 Network is down. */
 #define ENETRESET 39       /* 网络连接已断开 Connection aborted by network. */
+
 #define ENETUNREACH 40     /* 网络不可达 Network unreachable. */
 #define ENFILE 41          /* 系统中打开的文件过多 Too many files open in system.*/
 #define ENOBUFS 42         /* 缓冲区空间不足 No buffer space available. */
@@ -59,6 +63,7 @@
 #define ENOLCK 47          /* 没有可用的锁 No locks available. */
 #define ENOLINK 48         /* 保留 Reserved. */
 #define ENOMEM 49          /* 没有足够的空间 Not enough space. */
+
 #define ENOMSG 50          /* 没有期待类型的消息 No message of the desired type. */
 #define ENOPROTOOPT 51     /* 协议不可用 Protocol not available. */
 #define ENOSPC 52          /* 设备上没有空间 No space left on device. */
@@ -69,6 +74,7 @@
 #define ENOTDIR 57         /* 不是目录 Not a directory. */
 #define ENOTEMPTY 58       /* 目录非空 Directory not empty. */
 #define ENOTRECOVERABLE 59 /* 状态不可覆盖 State not recoverable. */
+
 #define ENOTSOCK 60        /* 不是一个套接字 Not a socket.*/
 #define ENOTSUP 61         /* 不被支持 Not supported (may be the same value as [EOPNOTSUPP]). */
 #define ENOTTY 62          /* 不正确的I/O控制操作 Inappropriate I/O control operation. */
@@ -79,6 +85,7 @@
 #define EPERM 67           /* 操作不被允许 Operation not permitted. */
 #define EPIPE 68           /* 断开的管道 Broken pipe. */
 #define EPROTO 69          /* 协议错误 Protocol error. */
+
 #define EPROTONOSUPPORT 70 /* 协议不被支持 Protocol not supported. */
 #define EPROTOTYPE 71      /* 对于套接字而言,错误的协议 Protocol wrong type for socket. */
 #define ERANGE 72          /* 结果过大 Result too large. */
@@ -89,5 +96,6 @@
 #define ETIME 77           /* 流式ioctl()超时 Stream ioctl() timeout */
 #define ETIMEDOUT 78       /* 连接超时 Connection timed out.*/
 #define ETXTBSY 79         /* 文本文件忙 Text file busy. */
+
 #define EWOULDBLOCK 80     /* 操作将被禁止 Operation would block (may be the same value as [EAGAIN]). */
 #define EXDEV 81           /* 跨设备连接 Cross-device link. */

+ 114 - 42
kernel/common/glib.h

@@ -17,7 +17,7 @@
                                        : "memory") //关闭外部中断
 #define nop() __asm__ __volatile__("nop\n\t")
 #define hlt() __asm__ __volatile__("hlt\n\t")
-#define pause() asm volatile ("pause\n\t"); // 处理器等待一段时间
+#define pause() asm volatile("pause\n\t"); // 处理器等待一段时间
 
 //内存屏障
 #define io_mfence() __asm__ __volatile__("mfence\n\t" :: \
@@ -123,7 +123,7 @@ static inline void list_del(struct List *entry)
      */
 
     entry->next->prev = entry->prev;
-	entry->prev->next = entry->next;
+    entry->prev->next = entry->next;
 }
 
 static inline bool list_empty(struct List *entry)
@@ -133,7 +133,7 @@ static inline bool list_empty(struct List *entry)
      * @param entry 入口
      */
 
-    if(entry == entry->next && entry->prev == entry)
+    if (entry == entry->next && entry->prev == entry)
         return true;
     else
         return false;
@@ -210,7 +210,7 @@ void *memset(void *dst, unsigned char C, ul size)
  * @param Num 字节数
  * @return void*
  */
-void *memcpy(void *dst, void *src, long Num)
+static inline void *memcpy(void *dst, void *src, long Num)
 {
     int d0, d1, d2;
     __asm__ __volatile__("cld	\n\t"
@@ -233,34 +233,33 @@ void *memcpy(void *dst, void *src, long Num)
 }
 
 /*
-		比较字符串 FirstPart and SecondPart
-		FirstPart = SecondPart =>  0
-		FirstPart > SecondPart =>  1
-		FirstPart < SecondPart => -1
+        比较字符串 FirstPart and SecondPart
+        FirstPart = SecondPart =>  0
+        FirstPart > SecondPart =>  1
+        FirstPart < SecondPart => -1
 */
 
-int strcmp(char * FirstPart,char * SecondPart)
+int strcmp(char *FirstPart, char *SecondPart)
 {
-	register int __res;
-	__asm__	__volatile__	(	"cld	\n\t"
-					"1:	\n\t"
-					"lodsb	\n\t"
-					"scasb	\n\t"
-					"jne	2f	\n\t"
-					"testb	%%al,	%%al	\n\t"
-					"jne	1b	\n\t"
-					"xorl	%%eax,	%%eax	\n\t"
-					"jmp	3f	\n\t"
-					"2:	\n\t"
-					"movl	$1,	%%eax	\n\t"
-					"jl	3f	\n\t"
-					"negl	%%eax	\n\t"
-					"3:	\n\t"
-					:"=a"(__res)
-					:"D"(FirstPart),"S"(SecondPart)
-					:					
-				);
-	return __res;
+    register int __res;
+    __asm__ __volatile__("cld	\n\t"
+                         "1:	\n\t"
+                         "lodsb	\n\t"
+                         "scasb	\n\t"
+                         "jne	2f	\n\t"
+                         "testb	%%al,	%%al	\n\t"
+                         "jne	1b	\n\t"
+                         "xorl	%%eax,	%%eax	\n\t"
+                         "jmp	3f	\n\t"
+                         "2:	\n\t"
+                         "movl	$1,	%%eax	\n\t"
+                         "jl	3f	\n\t"
+                         "negl	%%eax	\n\t"
+                         "3:	\n\t"
+                         : "=a"(__res)
+                         : "D"(FirstPart), "S"(SecondPart)
+                         :);
+    return __res;
 }
 
 void *memset_c(void *dst, unsigned char c, ul n)
@@ -317,17 +316,19 @@ void io_out32(unsigned short port, unsigned int value)
 
 /**
  * @brief 从端口读入n个word到buffer
- * 
+ *
  */
-#define io_insw(port,buffer,nr)	\
-__asm__ __volatile__("cld;rep;insw;mfence;"::"d"(port),"D"(buffer),"c"(nr):"memory")
+#define io_insw(port, buffer, nr)                                                 \
+    __asm__ __volatile__("cld;rep;insw;mfence;" ::"d"(port), "D"(buffer), "c"(nr) \
+                         : "memory")
 
 /**
  * @brief 从输出buffer中的n个word到端口
- * 
+ *
  */
-#define io_outsw(port,buffer,nr)	\
-__asm__ __volatile__("cld;rep;outsw;mfence;"::"d"(port),"S"(buffer),"c"(nr):"memory")
+#define io_outsw(port, buffer, nr)                                                 \
+    __asm__ __volatile__("cld;rep;outsw;mfence;" ::"d"(port), "S"(buffer), "c"(nr) \
+                         : "memory")
 
 /**
  * @brief 读取rsp寄存器的值(存储了页目录的基地址)
@@ -427,13 +428,84 @@ ul rdmsr(ul address)
     return ((ul)tmp0 << 32) | tmp1;
 }
 
-
 uint64_t get_rflags()
 {
-	unsigned long tmp = 0;
-	__asm__ __volatile__	("pushfq	\n\t"
-				 "movq	(%%rsp), %0	\n\t"
-				 "popfq	\n\t"
-				:"=r"(tmp)::"memory");
-	return tmp;
+    unsigned long tmp = 0;
+    __asm__ __volatile__("pushfq	\n\t"
+                         "movq	(%%rsp), %0	\n\t"
+                         "popfq	\n\t"
+                         : "=r"(tmp)::"memory");
+    return tmp;
+}
+
+/**
+ * @brief 验证地址空间是否为用户地址空间
+ *
+ * @param addr_start 地址起始值
+ * @param length 地址长度
+ * @return true
+ * @return false
+ */
+bool verify_area(uint64_t addr_start, uint64_t length)
+{
+    if ((addr_start + length) <= 0x00007fffffffffffUL) // 用户程序可用的的地址空间应<= 0x00007fffffffffffUL
+        return true;
+    else
+        return false;
+}
+
+/**
+ * @brief 从用户空间搬运数据到内核空间
+ * 
+ * @param dst 目的地址
+ * @param src 源地址
+ * @param size 搬运的大小
+ * @return uint64_t 
+ */
+static inline uint64_t copy_from_user(void *dst, void *src, uint64_t size)
+{
+    uint64_t tmp0, tmp1;
+    if (!verify_area((uint64_t)src, size))
+        return 0;
+
+    /**
+     * @brief 先每次搬运8 bytes,剩余就直接一个个byte搬运
+     * 
+     */
+    asm volatile("rep   \n\t"
+                 "movsq  \n\t"
+                 "movq %3, %0   \n\t"
+                 "rep   \n\t"
+                 "movsb \n\t"
+                 : "=&c"(size), "=&D"(tmp0), "=&S"(tmp1)
+                 : "r"(size & 7), "0"(size >> 3), "1"(dst), "2"(src));
+    return size;
+}
+
+/**
+ * @brief 从内核空间搬运数据到用户空间
+ * 
+ * @param dst 目的地址
+ * @param src 源地址
+ * @param size 搬运的大小
+ * @return uint64_t 
+ */
+static inline uint64_t copy_to_user(void *dst, void *src, uint64_t size)
+{
+    uint64_t tmp0, tmp1;
+    if (verify_area((uint64_t)src, size))
+        return 0;
+
+    /**
+     * @brief 先每次搬运8 bytes,剩余就直接一个个byte搬运
+     * 
+     */
+    asm volatile("rep   \n\t"
+                 "movsq  \n\t"
+                 "movq %3, %0   \n\t"
+                 "rep   \n\t"
+                 "movsb \n\t"
+                 : "=&c"(size), "=&D"(tmp0), "=&S"(tmp1)
+                 : "r"(size & 7), "0"(size >> 3), "1"(dst), "2"(src));
+    return size;
 }