]> git.buserror.net Git - polintos/scott/priv.git/blobdiff - kernel/include/arch-x86/usercopy.h
update
[polintos/scott/priv.git] / kernel / include / arch-x86 / usercopy.h
index f220cd9963867b43e76b5e356b7a8bc338bfcb00..2b72f42c59c5c55b5e0415bca6085b9e72b8917a 100644 (file)
@@ -6,38 +6,79 @@
 
 namespace Arch {
        template <typename T>
-       static inline T copyin(T *ptr)
+       static inline void copyin(T *uptr, T *kdata, int count)
        {
-               // FIXME
-               return *ptr;
+               // OPT: use alignof for movsw and movsl versions
+               ulong bytes = sizeof(*kdata) * count;
+               int cause;
+               
+               if ((ulong)uptr + bytes >= PHYSMEM_START ||
+                   (ulong)uptr + bytes < (ulong)uptr) {
+                       cause = 1;
+                       goto bad;
+               }
+               
+               asm("1: rep; movsb\n"
+                   "2:\n"
+                   ".section .extable,\"a\"\n"
+                   ".align 4\n"
+                   ".long 1b\n"
+                   ".long 2b\n"
+                   ".previous\n" : "+c" (bytes), "+D" (kdata), "+S" (uptr), "=d" (cause));
+       
+               if (bytes != 0) {
+               bad:
+                       throw_idl(MemoryFault, reinterpret_cast<ulong>(uptr),
+                                 0, NULL, NULL, cause);
+               }
        }
 
        template <typename T>
-       static inline void copyin(T *ptr, T &data)
+       static inline void copyin(T *uptr, T &kdata)
        {
-               // FIXME
-               data = *ptr;
+               // OPT: special versions for common small sizes
+               copyin(uptr, &kdata, 1);
        }
        
        template <typename T>
-       static inline void copyin(T *ptr, T *data, int count)
+       static inline T copyin(T *uptr)
        {
-               // FIXME
-               memcpy(data, ptr, count * sizeof(T));
+               T kdata;
+               copyin(uptr, kdata);
+               return kdata;
        }
 
        template <typename T>
-       static inline void copyout(T *ptr, T &data)
+       static inline void copyout(T *uptr, T *kdata, int count)
        {
-               // FIXME
-               *ptr = data;
+               // OPT: use alignof for movsw and movsl versions
+               ulong bytes = sizeof(*kdata) * count;
+               int cause;
+
+               if ((ulong)uptr + bytes >= PHYSMEM_START ||
+                   (ulong)uptr + bytes < (ulong)uptr) {
+                       cause = 1;
+                       goto bad;
+               }
+               
+               asm("1: rep; movsb\n"
+                   "2:\n"
+                   ".section .extable,\"a\"\n"
+                   ".long 1b\n"
+                   ".long 2b\n"
+                   ".previous\n" : "+c" (bytes), "+S" (kdata), "+D" (uptr), "=d" (cause));
+       
+               if (bytes != 0) {
+               bad:
+                       throw_idl(MemoryFault, reinterpret_cast<ulong>(uptr),
+                                 0, NULL, NULL, cause);
+               }
        }
 
        template <typename T>
-       static inline void copyout(T *ptr, T *data, int count)
+       static inline void copyout(T *uptr, T &kdata)
        {
-               // FIXME
-               memcpy(ptr, data, count * sizeof(T));
+               copyout(uptr, &kdata, sizeof(kdata));
        }
 }