Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Import rdmsr_safe(msr, *value) for x86 world. It al...



details:   https://anonhg.NetBSD.org/src/rev/40a13079c290
branches:  trunk
changeset: 769809:40a13079c290
user:      jym <jym%NetBSD.org@localhost>
date:      Sat Sep 24 10:32:52 2011 +0000

description:
Import rdmsr_safe(msr, *value) for x86 world. It allows reading MSRs
in a safe way by handling the fault that might trigger for certain
register <> CPU/arch combos.

Requested by Jukka. Patch adapted from one found in DragonflyBSD.

diffstat:

 sys/arch/amd64/amd64/cpufunc.S |  35 ++++++++++++++++++++++++++++++++++-
 sys/arch/i386/i386/cpufunc.S   |  40 ++++++++++++++++++++++++++++++++++++++--
 sys/arch/x86/include/cpufunc.h |   3 ++-
 3 files changed, 74 insertions(+), 4 deletions(-)

diffs (135 lines):

diff -r 49049017758b -r 40a13079c290 sys/arch/amd64/amd64/cpufunc.S
--- a/sys/arch/amd64/amd64/cpufunc.S    Sat Sep 24 08:39:39 2011 +0000
+++ b/sys/arch/amd64/amd64/cpufunc.S    Sat Sep 24 10:32:52 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cpufunc.S,v 1.19 2011/06/12 03:35:37 rmind Exp $       */
+/*     $NetBSD: cpufunc.S,v 1.20 2011/09/24 10:32:52 jym Exp $ */
 
 /*-
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -33,6 +33,8 @@
  * Functions to provide access to i386-specific instructions.
  */
 
+#include <sys/errno.h>
+
 #include <machine/asm.h>
 #include <machine/frameasm.h>
 #include <machine/specialreg.h>
@@ -221,6 +223,37 @@
        wrmsr
        ret
 
+/*
+ * Support for reading MSRs in the safe manner (returns EFAULT on fault)
+ */
+/* int rdmsr_safe(u_int msr, uint64_t *data) */
+ENTRY(rdmsr_safe)
+       movq    CPUVAR(CURLWP), %r8
+       movq    L_PCB(%r8), %r8
+       movq    $_C_LABEL(msr_onfault), PCB_ONFAULT(%r8)
+
+       movl    %edi, %ecx /* u_int msr */
+       rdmsr                   /* Read MSR pointed by %ecx. Returns
+                                  hi byte in edx, lo in %eax */
+       salq    $32, %rdx       /* sign-shift %rdx left */
+       movl    %eax, %eax      /* zero-extend %eax -> %rax */
+       orq     %rdx, %rax
+       movq    %rax, (%rsi)  /* *data */
+       xorq    %rax, %rax    /* "no error" */
+
+       movq    %rax, PCB_ONFAULT(%r8)
+       ret
+
+/*
+ * MSR operations fault handler
+ */
+NENTRY(msr_onfault)
+       movq    CPUVAR(CURLWP), %r8
+       movq    L_PCB(%r8), %r8
+       movq    $0, PCB_ONFAULT(%r8)
+       movl    $EFAULT, %eax
+        ret
+
 #ifndef XEN
 ENTRY(wbinvd)
        wbinvd
diff -r 49049017758b -r 40a13079c290 sys/arch/i386/i386/cpufunc.S
--- a/sys/arch/i386/i386/cpufunc.S      Sat Sep 24 08:39:39 2011 +0000
+++ b/sys/arch/i386/i386/cpufunc.S      Sat Sep 24 10:32:52 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cpufunc.S,v 1.15 2011/03/18 15:32:02 joerg Exp $       */
+/*     $NetBSD: cpufunc.S,v 1.16 2011/09/24 10:32:52 jym Exp $ */
 
 /*-
  * Copyright (c) 1998, 2007 The NetBSD Foundation, Inc.
@@ -35,8 +35,10 @@
  * These are shared with NetBSD/xen.
  */
 
+#include <sys/errno.h>
+
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: cpufunc.S,v 1.15 2011/03/18 15:32:02 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpufunc.S,v 1.16 2011/09/24 10:32:52 jym Exp $");
 
 #include "opt_xen.h"
 
@@ -137,6 +139,40 @@
        ret
 END(wrmsr_locked)
 
+/*
+ * Support for reading MSRs in the safe manner (returns EFAULT on fault)
+ */
+/* int rdmsr_safe(u_int msr, uint64_t *data) */
+ENTRY(rdmsr_safe)
+       movl    CPUVAR(CURLWP), %ecx
+       movl    L_PCB(%ecx), %ecx
+       movl    $_C_LABEL(msr_onfault), PCB_ONFAULT(%ecx)
+
+       movl    4(%esp), %ecx /* u_int msr */
+       rdmsr
+       movl    8(%esp), %ecx /* *data */
+       movl    %eax, (%ecx)  /* low-order bits */
+       movl    %edx, 4(%ecx) /* high-order bits */
+       xorl    %eax, %eax    /* "no error" */
+
+       movl    CPUVAR(CURLWP), %ecx
+       movl    L_PCB(%ecx), %ecx
+       movl    %eax, PCB_ONFAULT(%ecx)
+
+       ret
+
+/*
+ * MSR operations fault handler
+ */
+NENTRY(msr_onfault)
+               movl    CPUVAR(CURLWP), %ecx
+       movl    L_PCB(%ecx), %ecx
+       movl    $0, PCB_ONFAULT(%ecx)
+       movl    $EFAULT, %eax
+        ret
+
+END(rdmsr_safe)
+
 ENTRY(cpu_counter)
        rdtsc
        addl    CPUVAR(CC_SKEW), %eax
diff -r 49049017758b -r 40a13079c290 sys/arch/x86/include/cpufunc.h
--- a/sys/arch/x86/include/cpufunc.h    Sat Sep 24 08:39:39 2011 +0000
+++ b/sys/arch/x86/include/cpufunc.h    Sat Sep 24 10:32:52 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cpufunc.h,v 1.12 2010/07/07 01:14:53 chs Exp $ */
+/*     $NetBSD: cpufunc.h,v 1.13 2011/09/24 10:32:52 jym Exp $ */
 
 /*-
  * Copyright (c) 1998, 2007 The NetBSD Foundation, Inc.
@@ -118,6 +118,7 @@
 
 uint64_t       rdmsr(u_int);
 uint64_t       rdmsr_locked(u_int, u_int);
+int            rdmsr_safe(u_int, uint64_t *);
 uint64_t       rdtsc(void);
 uint64_t       rdpmc(u_int);
 void           wrmsr(u_int, uint64_t);



Home | Main Index | Thread Index | Old Index