Implemented casuword for vkernel64. Fix two typos in casuword for pc64.
authorImre Vadasz <imre@vdsz.com>
Fri, 14 Mar 2014 22:56:40 +0000 (23:56 +0100)
committerAlex Hornung <alex@alexhornung.com>
Sat, 15 Mar 2014 09:12:02 +0000 (09:12 +0000)
sys/platform/pc64/x86_64/support.s
sys/platform/vkernel64/platform/copyio.c

index dec0c98..9c1dbd5 100644 (file)
@@ -361,7 +361,7 @@ ENTRY(casuword)
        movq    $fusufault,PCB_ONFAULT(%rcx)
        movq    %rsp,PCB_ONFAULT_SP(%rcx)
 
-       movq    $VM_MAX_USER_ADDRESS-4,%rax
+       movq    $VM_MAX_USER_ADDRESS-8,%rax
        cmpq    %rax,%rdi                       /* verify address is valid */
        ja      fusufault
 
@@ -370,7 +370,7 @@ ENTRY(casuword)
        cmpxchgq %rdx,(%rdi)                    /* new = %rdx */
 
        /*
-        * The old value is in %eax.  If the store succeeded it will be the
+        * The old value is in %rax.  If the store succeeded it will be the
         * value we expected (old) from before the store, otherwise it will
         * be the current value.
         */
index 3e366ce..475941d 100644 (file)
@@ -57,6 +57,41 @@ bcopyi(const void *src, void *dst, size_t len)
        bcopy(src, dst, len);
 }
 
+u_long
+casuword(volatile u_long *p, u_long oldval, u_long newval)
+{
+       struct vmspace *vm = curproc->p_vmspace;
+       vm_offset_t kva;
+       vm_page_t m;
+       volatile u_long *dest;
+       u_long res;
+       int error;
+
+       /* XXX No idea how to handle this case in a simple way, just abort */
+       if (PAGE_SIZE - ((vm_offset_t)p & PAGE_MASK) < sizeof(u_long))
+               return -1;
+
+       m = vm_fault_page(&vm->vm_map, trunc_page((vm_offset_t)p),
+                         VM_PROT_READ|VM_PROT_WRITE,
+                         VM_FAULT_NORMAL, &error);
+       if (error)
+               return -1;
+
+       kva = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
+       dest = (u_long *)(kva + ((vm_offset_t)p & PAGE_MASK));
+       res = oldval;
+       __asm __volatile(MPLOCKED "cmpxchgq %2,%1; " \
+                        : "+a" (res), "=m" (*dest) \
+                        : "r" (newval), "m" (*dest) \
+                        : "memory");
+
+       if (res == oldval)
+               vm_page_dirty(m);
+       vm_page_unhold(m);
+
+       return res;
+}
+
 int
 copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *lencopied)
 {