time.c 1.9 KB

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