Handle rdtscp
[akaros.git] / kern / arch / sparc / arch.h
index e2575cd..e9c12ba 100644 (file)
@@ -1,9 +1,11 @@
 #ifndef ROS_INC_ARCH_H
 #define ROS_INC_ARCH_H
 
+#include <ros/arch/arch.h>
+
 /* Arch Constants */
-#define MAX_NUM_CPUS           64
-#define IOAPIC_BASE            0xFEC00000 // max virtual address
+#define HW_CACHE_ALIGN         64
+#define KERN_VMAP_TOP          0xFEC00000 // max virtual address
 
 #include <arch/mmu.h>
 #include <arch/sparc.h>
@@ -11,7 +13,7 @@
 #ifndef __ASSEMBLER__
 
 #include <ros/common.h>
-#include <arch/timer.h>
+#include <arch/time.h>
 
 static __inline void breakpoint(void) __attribute__((always_inline));
 static __inline void invlpg(void *addr) __attribute__((always_inline));
@@ -23,6 +25,8 @@ static __inline void enable_irqsave(int8_t* state) __attribute__((always_inline)
 static __inline void disable_irqsave(int8_t* state) __attribute__((always_inline));
 static __inline void cpu_relax(void) __attribute__((always_inline));
 static __inline void cpu_halt(void) __attribute__((always_inline));
+static __inline void tlbflush(void) __attribute__((always_inline));
+static __inline void icache_flush_page(void* va, void* pa)__attribute__((always_inline));
 static __inline void clflush(uintptr_t* addr) __attribute__((always_inline));
 static __inline int irq_is_enabled(void) __attribute__((always_inline));
 static __inline uint32_t core_id(void) __attribute__((always_inline));
@@ -33,36 +37,47 @@ static __inline uint32_t rcr3(void) __attribute__((always_inline));
 
 void print_cpuinfo(void);
 void show_mapping(uintptr_t start, size_t size);
-void backtrace(void);
+void __cpu_halt(void);
 
 extern uintptr_t mmu_context_tables[MAX_NUM_CPUS][NCONTEXTS+CONTEXT_TABLE_PAD];
 
 static __inline void
 breakpoint(void)
 {
-       __asm __volatile("ta 0x7f");
+       asm volatile ("ta 0x7f");
 }
 
 static __inline void 
 invlpg(void *addr)
 { 
-       store_alternate(((intptr_t)addr) & ~0xFFF,3,0);
+       store_alternate(((uintptr_t)addr) & ~0xFFF,3,0);
 }  
 
 static __inline void
 tlbflush(void)
 {
-       // unsure if we'll support this yet...
-       // may have to just do invlpg() in a loop
        store_alternate(0x400,3,0);
 }
 
+static __inline void
+icache_flush_page(void* va, void* kva)
+{
+       for(int i = 0; i < PGSIZE; i+=32) // functional pipeline line size
+               clflush((uintptr_t*)((char*)kva+i));
+}
+
 static __inline uint64_t
 read_tsc(void)
 {
        return read_perfctr(0,0);
 }
 
+static __inline uint64_t
+read_tscp(void)
+{
+       return read_tsc();
+}
+
 static __inline uint64_t 
 read_tsc_serialized(void)
 {
@@ -72,13 +87,13 @@ read_tsc_serialized(void)
 static __inline void
 enable_irq(void)
 {
-       write_psr(read_psr() & ~0xF00);
+       write_psr(read_psr() & ~PSR_PIL);
 }
 
 static __inline void
 disable_irq(void)
 {
-       write_psr(read_psr() | 0xF00);
+       write_psr(read_psr() | PSR_PIL);
 }
 
 static __inline void
@@ -110,6 +125,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");
+       uintptr_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)
 {
@@ -121,7 +156,9 @@ cpu_relax(void)
 static __inline void
 cpu_halt(void)
 {
-       asm volatile("1: ba 1b; nop" : : : "memory");
+       /* TODO: this isn't atomic, but we want it to be. */
+       enable_irq();
+       __cpu_halt();
 }
 
 static __inline void
@@ -133,14 +170,14 @@ clflush(uintptr_t* addr)
 static __inline int
 irq_is_enabled(void)
 {
-       return (read_psr() & 0xF00) == 0;
+       return (read_psr() & PSR_PIL) == 0;
 }
 
 static __inline uint32_t
 core_id(void)
 {
        uint32_t reg;
-       __asm__ __volatile__("mov %" XSTR(CORE_ID_REG) ",%0" : "=r"(reg));
+       asm ("mov %" XSTR(CORE_ID_REG) ",%0" : "=r"(reg));
        return reg;
 }
 
@@ -152,7 +189,7 @@ cache_flush(void)
 static __inline void
 reboot(void)
 {
-       extern void appserver_die(int code);
+       extern void appserver_die(uintptr_t code);
        appserver_die(0);
        while(1);
 }