diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index 32f39b2213..a8dd434329 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 4a28a24b4c..cb9187ce92 100644 --- a/xen/common/random.c +++ b/xen/common/random.c @@ -1,9 +1,11 @@ +#include #include #include #include #include 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 5c57615819..3e340b4148 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 7c43d87f59..b950f03c0c 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__ */