Exposed SPARC iobus to userspace
authorAndrew Waterman <waterman@parcad.millennium.berkeley.edu>
Wed, 24 Feb 2010 22:22:53 +0000 (14:22 -0800)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:36 +0000 (17:35 -0700)
users can now load_iobus and store_iobus.

kern/arch/sparc/arch.h
kern/arch/sparc/ros/hart.h
kern/arch/sparc/sparc.h
kern/arch/sparc/trap_table.S

index ded8484..7d7ac16 100644 (file)
@@ -111,6 +111,26 @@ disable_irqsave(int8_t* state)
                (*state)--;
 }
 
+static __inline uint64_t
+read_perfctr(uint32_t cpu, uint32_t which)
+{
+       register uint32_t hi asm("o0"), lo asm("o1");
+       intptr_t addr = cpu<<10 | which<<3;
+
+       #ifdef ROS_KERNEL
+               int8_t state = 0;
+               disable_irqsave(&state);
+               hi = load_iobus(0,addr);
+               lo = load_iobus(0,addr+4);
+               enable_irqsave(&state);
+       #else
+               // can't use two load_iobuses in userspace because of atomicity
+               asm volatile("mov %2,%%o0; ta 9"
+                            : "=r"(hi),"=r"(lo) : "r"(addr));
+       #endif
+       return (((uint64_t)hi) << 32) | lo;
+}
+
 static __inline void
 cpu_relax(void)
 {
index 4af5595..f24f79c 100644 (file)
@@ -36,4 +36,39 @@ __hart_swap(int* addr, int val)
        return val;
 }
 
+extern int __hart_atomic_hash_locks[HART_CL_SIZE*HART_ATOMIC_HASHTABLE_SIZE];
+static inline int*
+__hart_atomic_hash(int* addr)
+{
+       int hash = ((unsigned int)addr/sizeof(int*))/HART_ATOMIC_HASHTABLE_SIZE;
+       return __hart_atomic_hash_locks[HART_CL_SIZE/sizeof(int)*hash];
+}
+
+static inline int
+__hart_fetch_and_add(int* addr, int addend)
+{
+       int * lock = __hart_atomic_hash_lock(addr);
+       while(__hart_swap(lock,1));
+
+       int old = *addr;
+       *addr = old+addend;
+
+       *lock = 0;
+       return old;
+}
+
+static inline int
+__hart_compare_and_swap(int* addr, int testval, int newval)
+{
+       int * lock = __hart_atomic_hash_lock(addr);
+       while(__hart_swap(lock,1));
+
+       int old = *addr;
+       if(old == testval)
+               *word = newval;
+
+       *lock = 0;
+       return old;
+}
+
 #endif
index eeb10c4..d8c8212 100644 (file)
@@ -92,21 +92,6 @@ read_fsr(void)
        return reg;
 }
 
-static __inline uint64_t
-read_perfctr(uint32_t cpu, uint32_t which)
-{
-       register uint32_t hi asm("o0"), lo asm("o1");
-       intptr_t addr = cpu<<10 | which<<3;
-       #ifdef ROS_KERNEL
-               hi = load_alternate(addr,2);
-               lo = load_alternate(addr+4,2);
-       #else
-               asm volatile("mov %2,%%o0; ta 9"
-                            : "=r"(hi),"=r"(lo) : "r"(addr));
-       #endif
-       return (((uint64_t)hi) << 32) | lo;
-}
-
 static __inline void
 write_psr(uint32_t val)
 {
@@ -168,7 +153,25 @@ mmu_probe(uint32_t va)
 static __inline void
 store_iobus(uint32_t device, uint32_t addr, uint32_t data)
 {
-       store_alternate(device << 16 | addr, 2, data);
+       #ifdef ROS_KERNEL
+               store_alternate(device << 16 | addr, 2, data);
+       #else
+               register uint32_t __my_addr asm("o0") = (addr);
+               register uint32_t __my_data asm("o1") = (data);
+               __asm__ __volatile__ ("ta 11" : : "r"(__my_addr),"r"(__my_data));
+       #endif
+}
+
+static __inline uint32_t
+load_iobus(uint32_t device, uint32_t addr)
+{
+       #ifdef ROS_KERNEL
+               return load_alternate(device << 16 | addr, 2);
+       #else
+               register uint32_t __my_addr asm("o0") = (addr);
+               __asm__ __volatile__ ("ta 10" : "=r"(__my_addr) : "0"(__my_addr));
+               return __my_addr;
+       #endif
 }
 
 static __inline uint32_t
index b9a6df2..ce191a8 100644 (file)
@@ -146,8 +146,8 @@ trap_table:
        UNHANDLED_TRAP                          ! 0x87
        TRAP_TABLE_ENTRY(handle_syscall)        ! 0x88
        JMP(handle_perfctr)                     ! 0x89
-       UNHANDLED_TRAP                          ! 0x8A
-       UNHANDLED_TRAP                          ! 0x8B
+       andn %i0,3,%i0; lda [%i0] 2,%i0; jmp %l2; rett %l2+4 ! 0x8A
+       andn %i0,3,%i0; sta %i1,[%i0] 2; jmp %l2; rett %l2+4 ! 0x8A
        UNHANDLED_TRAP                          ! 0x8C
        UNHANDLED_TRAP                          ! 0x8D
        UNHANDLED_TRAP                          ! 0x8E