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

[Xen-changelog] [xen master] x86: allow reading MSR_IA32_TSC with XENPF_resource_op



commit f6c9698d7f65eca5c1ef5ed325e12252a2fb89fd
Author:     Chao Peng <chao.p.peng@xxxxxxxxxxxxxxx>
AuthorDate: Wed Jan 28 16:33:01 2015 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Wed Jan 28 16:36:36 2015 +0100

    x86: allow reading MSR_IA32_TSC with XENPF_resource_op
    
    Memory bandwidth monitoring requires system time information returned
    along with the monitoring counter to verify the correctness of the
    counter value and to calculate the time elapsed between two samplings.
    
    Add MSR_IA32_TSC to the read path and it returns scaled system time(ns)
    instead of raw timestamp to elimanate the needs to convert. The return
    time is obfuscated with booting random to eliminate the potential abuse
    of it. RESOURCE_ACCESS_MAX_ENTRIES is also increased to 3 so MSR_IA32_TSC
    can be used together with an MSR write/read operation pair.
    
    Signed-off-by: Chao Peng <chao.p.peng@xxxxxxxxxxxxxxx>
    
    Fix uninitialized variable build error.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/x86/platform_hypercall.c |   38 ++++++++++++++++++++++++++++++++++--
 xen/common/random.c               |    9 ++++++++
 xen/include/public/platform.h     |   10 +++++++++
 xen/include/xen/random.h          |    3 ++
 4 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/platform_hypercall.c 
b/xen/arch/x86/platform_hypercall.c
index 32f39b2..a8dd434 100644
--- a/xen/arch/x86/platform_hypercall.c
+++ b/xen/arch/x86/platform_hypercall.c
@@ -61,7 +61,7 @@ long cpu_down_helper(void *data);
 long core_parking_helper(void *data);
 uint32_t get_cur_idle_nums(void);
 
-#define RESOURCE_ACCESS_MAX_ENTRIES 2
+#define RESOURCE_ACCESS_MAX_ENTRIES 3
 struct xen_resource_access {
     unsigned int nr_done;
     unsigned int nr_entries;
@@ -75,6 +75,7 @@ static bool_t allow_access_msr(unsigned int msr)
     /* MSR for CMT, refer to chapter 17.14 of Intel SDM. */
     case MSR_IA32_CMT_EVTSEL:
     case MSR_IA32_CMT_CTR:
+    case MSR_IA32_TSC:
         return 1;
     }
 
@@ -124,6 +125,7 @@ static void resource_access(void *info)
 {
     struct xen_resource_access *ra = info;
     unsigned int i;
+    u64 tsc = 0;
 
     for ( i = 0; i < ra->nr_done; i++ )
     {
@@ -133,10 +135,40 @@ static void resource_access(void *info)
         switch ( entry->u.cmd )
         {
         case XEN_RESOURCE_OP_MSR_READ:
-            ret = rdmsr_safe(entry->idx, entry->val);
+            if ( unlikely(entry->idx == MSR_IA32_TSC) )
+            {
+                /* Return obfuscated scaled time instead of raw timestamp */
+                entry->val = get_s_time_fixed(tsc)
+                             + SECONDS(boot_random) - boot_random;
+                ret = 0;
+            }
+            else
+            {
+                unsigned long flags = 0;
+                /*
+                 * If next entry is MSR_IA32_TSC read, then the actual rdtscll
+                 * is performed together with current entry, with IRQ disabled.
+                 */
+                bool_t read_tsc = (i < ra->nr_done - 1 &&
+                                   unlikely(entry[1].idx == MSR_IA32_TSC));
+
+                if ( unlikely(read_tsc) )
+                    local_irq_save(flags);
+
+                ret = rdmsr_safe(entry->idx, entry->val);
+
+                if ( unlikely(read_tsc) )
+                {
+                    rdtscll(tsc);
+                    local_irq_restore(flags);
+                }
+            }
             break;
         case XEN_RESOURCE_OP_MSR_WRITE:
-            ret = wrmsr_safe(entry->idx, entry->val);
+            if ( unlikely(entry->idx == MSR_IA32_TSC) )
+                ret = -EPERM;
+            else
+                ret = wrmsr_safe(entry->idx, entry->val);
             break;
         default:
             BUG();
diff --git a/xen/common/random.c b/xen/common/random.c
index 4a28a24..cb9187c 100644
--- a/xen/common/random.c
+++ b/xen/common/random.c
@@ -1,9 +1,11 @@
+#include <xen/init.h>
 #include <xen/percpu.h>
 #include <xen/random.h>
 #include <xen/time.h>
 #include <asm/random.h>
 
 static DEFINE_PER_CPU(unsigned int, seed);
+unsigned int __read_mostly boot_random;
 
 unsigned int get_random(void)
 {
@@ -27,3 +29,10 @@ unsigned int get_random(void)
 
     return val;
 }
+
+static int __init init_boot_random(void)
+{
+    boot_random = get_random();
+    return 0;
+}
+__initcall(init_boot_random);
diff --git a/xen/include/public/platform.h b/xen/include/public/platform.h
index 5c57615..3e340b4 100644
--- a/xen/include/public/platform.h
+++ b/xen/include/public/platform.h
@@ -540,6 +540,16 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_core_parking_t);
 #define XEN_RESOURCE_OP_MSR_READ  0
 #define XEN_RESOURCE_OP_MSR_WRITE 1
 
+/*
+ * Specially handled MSRs:
+ * - MSR_IA32_TSC
+ * READ: Returns the scaled system time(ns) instead of raw timestamp. In
+ *       multiple entry case, if other MSR read is followed by a MSR_IA32_TSC
+ *       read, then both reads are guaranteed to be performed atomically (with
+ *       IRQ disabled). The return time indicates the point of reading that 
MSR.
+ * WRITE: Not supported.
+ */
+
 struct xenpf_resource_entry {
     union {
         uint32_t cmd;   /* IN: XEN_RESOURCE_OP_* */
diff --git a/xen/include/xen/random.h b/xen/include/xen/random.h
index 7c43d87..b950f03 100644
--- a/xen/include/xen/random.h
+++ b/xen/include/xen/random.h
@@ -3,4 +3,7 @@
 
 unsigned int get_random(void);
 
+/* The value keeps unchange once initialized for each booting */
+extern unsigned int boot_random;
+
 #endif /* __XEN_RANDOM_H__ */
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.