perf: Use a user_data blob for perf_event (XCC)
[akaros.git] / kern / arch / x86 / arch.h
index edff711..20efdf9 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef ROS_INC_ARCH_H
-#define ROS_INC_ARCH_H
+#pragma once
 
 #include <ros/arch/arch.h>
 #include <ros/common.h>
@@ -14,8 +13,6 @@
 #define __always_inline inline __attribute__((always_inline))
 
 static inline void breakpoint(void) __attribute__((always_inline));
-static inline void invlpg(void *addr) __attribute__((always_inline));  
-static inline void tlbflush(void) __attribute__((always_inline));
 static inline void icache_flush_page(void *va, void *kva)
               __attribute__((always_inline));
 static inline uint64_t read_tsc(void) __attribute__((always_inline));
@@ -33,31 +30,26 @@ static inline int irq_is_enabled(void) __attribute__((always_inline));
 static inline void cache_flush(void) __attribute__((always_inline));
 static inline void reboot(void)
               __attribute__((always_inline)) __attribute__((noreturn));
+static inline void prefetch(void *addr);
+static inline void prefetchw(void *addr);
+static inline void swap_gs(void);
 
 /* in trap.c */
 void send_ipi(uint32_t os_coreid, uint8_t vector);
 /* in cpuinfo.c */
 void print_cpuinfo(void);
-void show_mapping(pde_t *pgdir, uintptr_t start, size_t size);
+void show_mapping(pgdir_t pgdir, uintptr_t start, size_t size);
 int vendor_id(char *);
+/* pmap.c */
+void invlpg(void *addr);
+void tlbflush(void);
+void tlb_flush_global(void);
 
 static inline void breakpoint(void)
 {
        asm volatile("int3");
 }
 
-static inline void invlpg(void *addr)
-{ 
-       asm volatile("invlpg (%0)" : : "r" (addr) : "memory");
-}  
-
-static inline void tlbflush(void)
-{
-       unsigned long cr3;
-       asm volatile("mov %%cr3,%0" : "=r" (cr3));
-       asm volatile("mov %0,%%cr3" : : "r" (cr3));
-}
-
 static inline void icache_flush_page(void *va, void *kva)
 {
        // x86 handles self-modifying code (mostly) without SW support
@@ -78,6 +70,17 @@ static inline uint64_t read_tscp(void)
        return (uint64_t)edx << 32 | eax;
 }
 
+static inline void mwait(void *eax)
+{
+       asm volatile("xorq %%rcx, %%rcx;"
+                    "xorq %%rdx, %%rdx;"
+                    "monitor;"
+                                /* this is racy, generically.  we never check if the write to
+                                 * the monitored address happened already. */
+                    "movq $0, %%rax;"  /* c-state hint.  this is C1 */
+                    "mwait;"
+                    : : "a"(eax));
+}
 /* Check out k/a/x86/rdtsc_test.c for more info */
 static inline uint64_t read_tsc_serialized(void)
 {
@@ -118,7 +121,7 @@ static inline void disable_irqsave(int8_t *state)
 {
        if ((*state == 0) && irq_is_enabled())
                disable_irq();
-       else 
+       else
                (*state)--;
 }
 
@@ -127,8 +130,8 @@ static inline void cpu_relax(void)
        __cpu_relax();
 }
 
-/* This doesn't atomically enable interrupts and then halt, like we want, so
- * x86 needs to use a custom helper in the irq handler in trap.c. */
+/* This atomically enables interrupts and halts.  sti does not take effect until
+ * after the *next* instruction */
 static inline void cpu_halt(void)
 {
        asm volatile("sti; hlt" : : : "memory");
@@ -159,4 +162,34 @@ static inline void reboot(void)
        while (1);
 }
 
-#endif /* !ROS_INC_ARCH_H */
+static inline void prefetch(void *addr)
+{
+       asm volatile("prefetchnta (%0)" : : "r"(addr));
+}
+
+static inline void prefetchw(void *addr)
+{
+       asm volatile("prefetchw (%0)" : : "r"(addr));
+}
+
+/* Guest VMs have a maximum physical address they can use.  Guest
+ * physical addresses are mapped into this MCP 1:1, but limited to
+ * this max address *in hardware*.  I.e., the MCP process can address
+ * more memory than the VMMCP can.  This is great; it means that
+ * keeping VM management stuff separate from the VM is trivial: just
+ * map it above max_vm_address. There's no need, as in other systems,
+ * to tweak the page table or root pointer to protect management
+ * memory from VM memory.
+ *
+ * TODO: read a register the first time this is called and save it
+ * away.  But this is more than enough for now.
+ */
+static inline uint64_t max_guest_pa(void)
+{
+       return (1ULL<<40) - 1;
+}
+
+static inline void swap_gs(void)
+{
+       asm volatile ("swapgs");
+}