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));
}
}