1 /* 2 * Xen stolen ticks accounting. 3 */ 4 #include <linux/kernel.h> 5 #include <linux/kernel_stat.h> 6 #include <linux/math64.h> 7 #include <linux/gfp.h> 8 9 #include <asm/paravirt.h> 10 #include <asm/xen/hypervisor.h> 11 #include <asm/xen/hypercall.h> 12 13 #include <xen/events.h> 14 #include <xen/features.h> 15 #include <xen/interface/xen.h> 16 #include <xen/interface/vcpu.h> 17 #include <xen/xen-ops.h> 18 19 /* runstate info updated by Xen */ 20 static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate); 21 22 /* return an consistent snapshot of 64-bit time/counter value */ 23 static u64 get64(const u64 *p) 24 { 25 u64 ret; 26 27 if (BITS_PER_LONG < 64) { 28 u32 *p32 = (u32 *)p; 29 u32 h, l, h2; 30 31 /* 32 * Read high then low, and then make sure high is 33 * still the same; this will only loop if low wraps 34 * and carries into high. 35 * XXX some clean way to make this endian-proof? 36 */ 37 do { 38 h = READ_ONCE(p32[1]); 39 l = READ_ONCE(p32[0]); 40 h2 = READ_ONCE(p32[1]); 41 } while(h2 != h); 42 43 ret = (((u64)h) << 32) | l; 44 } else 45 ret = READ_ONCE(*p); 46 47 return ret; 48 } 49 50 static void xen_get_runstate_snapshot_cpu(struct vcpu_runstate_info *res, 51 unsigned int cpu) 52 { 53 u64 state_time; 54 struct vcpu_runstate_info *state; 55 56 BUG_ON(preemptible()); 57 58 state = per_cpu_ptr(&xen_runstate, cpu); 59 60 do { 61 state_time = get64(&state->state_entry_time); 62 rmb(); /* Hypervisor might update data. */ 63 *res = READ_ONCE(*state); 64 rmb(); /* Hypervisor might update data. */ 65 } while (get64(&state->state_entry_time) != state_time || 66 (state_time & XEN_RUNSTATE_UPDATE)); 67 } 68 69 /* 70 * Runstate accounting 71 */ 72 void xen_get_runstate_snapshot(struct vcpu_runstate_info *res) 73 { 74 xen_get_runstate_snapshot_cpu(res, smp_processor_id()); 75 } 76 77 /* return true when a vcpu could run but has no real cpu to run on */ 78 bool xen_vcpu_stolen(int vcpu) 79 { 80 return per_cpu(xen_runstate, vcpu).state == RUNSTATE_runnable; 81 } 82 83 u64 xen_steal_clock(int cpu) 84 { 85 struct vcpu_runstate_info state; 86 87 xen_get_runstate_snapshot_cpu(&state, cpu); 88 return state.time[RUNSTATE_runnable] + state.time[RUNSTATE_offline]; 89 } 90 91 void xen_setup_runstate_info(int cpu) 92 { 93 struct vcpu_register_runstate_memory_area area; 94 95 area.addr.v = &per_cpu(xen_runstate, cpu); 96 97 if (HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, 98 xen_vcpu_nr(cpu), &area)) 99 BUG(); 100 } 101 102 void __init xen_time_setup_guest(void) 103 { 104 bool xen_runstate_remote; 105 106 xen_runstate_remote = !HYPERVISOR_vm_assist(VMASST_CMD_enable, 107 VMASST_TYPE_runstate_update_flag); 108 109 pv_time_ops.steal_clock = xen_steal_clock; 110 111 static_key_slow_inc(¶virt_steal_enabled); 112 if (xen_runstate_remote) 113 static_key_slow_inc(¶virt_steal_rq_enabled); 114 } 115