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/xen/hypervisor.h> 10 #include <asm/xen/hypercall.h> 11 12 #include <xen/events.h> 13 #include <xen/features.h> 14 #include <xen/interface/xen.h> 15 #include <xen/interface/vcpu.h> 16 #include <xen/xen-ops.h> 17 18 /* runstate info updated by Xen */ 19 static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate); 20 21 /* return an consistent snapshot of 64-bit time/counter value */ 22 static u64 get64(const u64 *p) 23 { 24 u64 ret; 25 26 if (BITS_PER_LONG < 64) { 27 u32 *p32 = (u32 *)p; 28 u32 h, l, h2; 29 30 /* 31 * Read high then low, and then make sure high is 32 * still the same; this will only loop if low wraps 33 * and carries into high. 34 * XXX some clean way to make this endian-proof? 35 */ 36 do { 37 h = READ_ONCE(p32[1]); 38 l = READ_ONCE(p32[0]); 39 h2 = READ_ONCE(p32[1]); 40 } while(h2 != h); 41 42 ret = (((u64)h) << 32) | l; 43 } else 44 ret = READ_ONCE(*p); 45 46 return ret; 47 } 48 49 /* 50 * Runstate accounting 51 */ 52 void xen_get_runstate_snapshot(struct vcpu_runstate_info *res) 53 { 54 u64 state_time; 55 struct vcpu_runstate_info *state; 56 57 BUG_ON(preemptible()); 58 59 state = this_cpu_ptr(&xen_runstate); 60 61 /* 62 * The runstate info is always updated by the hypervisor on 63 * the current CPU, so there's no need to use anything 64 * stronger than a compiler barrier when fetching it. 65 */ 66 do { 67 state_time = get64(&state->state_entry_time); 68 *res = READ_ONCE(*state); 69 } while (get64(&state->state_entry_time) != state_time); 70 } 71 72 /* return true when a vcpu could run but has no real cpu to run on */ 73 bool xen_vcpu_stolen(int vcpu) 74 { 75 return per_cpu(xen_runstate, vcpu).state == RUNSTATE_runnable; 76 } 77 78 void xen_setup_runstate_info(int cpu) 79 { 80 struct vcpu_register_runstate_memory_area area; 81 82 area.addr.v = &per_cpu(xen_runstate, cpu); 83 84 if (HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, 85 cpu, &area)) 86 BUG(); 87 } 88 89