Added exception table based safe MSR access APIs
authorDavide Libenzi <dlibenzi@google.com>
Tue, 24 Nov 2015 14:30:46 +0000 (06:30 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 24 Nov 2015 20:38:22 +0000 (15:38 -0500)
Added exception table based safe MSR access APIs.

Signed-off-by: Davide Libenzi <dlibenzi@google.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/uaccess.h

index 17d284f..cba0ef5 100644 (file)
@@ -40,6 +40,33 @@ struct extable_ip_fixup {
        " .quad (" #to ") - .\n"                                                                        \
        " .popsection\n"
 
+#define __read_msr_asm(eax, edx, addr, err, errret)                                            \
+       asm volatile(ASM_STAC "\n"                                                                                      \
+                                "1:            rdmsr\n"                                                                        \
+                                "                      mfence\n"                                                                       \
+                                "2: " ASM_CLAC "\n"                                                                    \
+                                ".section .fixup,\"ax\"\n"                                                             \
+                                "3:            mov %4,%0\n"                                                            \
+                                "      jmp 2b\n"                                                                                       \
+                                ".previous\n"                                                                                  \
+                                _ASM_EXTABLE(1b, 3b)                                                                   \
+                                : "=r" (err), "=d" (edx), "=a" (eax)                                   \
+                                : "c" (addr), "i" (errret), "0" (err))
+
+#define __write_msr_asm(val, addr, err, errret)                                                        \
+       asm volatile(ASM_STAC "\n"                                                                                      \
+                                "1:            wrmsr\n"                                                                        \
+                                "2: " ASM_CLAC "\n"                                                                    \
+                                ".section .fixup,\"ax\"\n"                                                             \
+                                "3:            mov %4,%0\n"                                                            \
+                                "      jmp 2b\n"                                                                                       \
+                                ".previous\n"                                                                                  \
+                                _ASM_EXTABLE(1b, 3b)                                                                   \
+                                : "=r" (err)                                                                                   \
+                                : "d" ((uint32_t) (val >> 32)),                                                \
+                                  "a" ((uint32_t) (val & 0xffffffff)), "c" (addr),             \
+                                  "i" (errret), "0" (err))
+
 #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret)              \
        asm volatile(ASM_STAC "\n"                                                                                      \
                                 "1:            mov"itype" %"rtype"1,%2\n"                                      \
@@ -165,6 +192,27 @@ static inline int copy_from_user(void *dst, const void *src,
        return err;
 }
 
+static inline int safe_read_msr(uint32_t addr, uint64_t *value)
+{
+       int err = 0;
+       uint32_t edx, eax;
+
+       __read_msr_asm(eax, edx, addr, err, -EFAULT);
+       if (likely(err == 0))
+               *value = ((uint64_t) edx << 32) | eax;
+
+       return err;
+}
+
+static inline int safe_write_msr(uint32_t addr, uint64_t value)
+{
+       int err = 0;
+
+       __write_msr_asm(value, addr, err, -EFAULT);
+
+       return err;
+}
+
 static inline uintptr_t ex_insn_addr(const struct extable_ip_fixup *x)
 {
        return (uintptr_t) &x->insn + x->insn;