apic.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/init.h>
  3. #include <linux/thread_info.h>
  4. #include <asm/x86_init.h>
  5. #include <asm/apic.h>
  6. #include <asm/io_apic.h>
  7. #include <asm/xen/hypercall.h>
  8. #include <xen/xen.h>
  9. #include <xen/interface/physdev.h>
  10. #include "xen-ops.h"
  11. static unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
  12. {
  13. struct physdev_apic apic_op;
  14. int ret;
  15. apic_op.apic_physbase = mpc_ioapic_addr(apic);
  16. apic_op.reg = reg;
  17. ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
  18. if (!ret)
  19. return apic_op.value;
  20. /* fallback to return an emulated IO_APIC values */
  21. if (reg == 0x1)
  22. return 0x00170020;
  23. else if (reg == 0x0)
  24. return apic << 24;
  25. return 0xfd;
  26. }
  27. static u32 xen_get_apic_id(u32 x)
  28. {
  29. return ((x)>>24) & 0xFFu;
  30. }
  31. static u32 xen_apic_read(u32 reg)
  32. {
  33. struct xen_platform_op op = {
  34. .cmd = XENPF_get_cpuinfo,
  35. .interface_version = XENPF_INTERFACE_VERSION,
  36. };
  37. int ret, cpu;
  38. if (reg == APIC_LVR)
  39. return 0x14;
  40. if (reg != APIC_ID)
  41. return 0;
  42. cpu = smp_processor_id();
  43. if (!xen_initial_domain())
  44. return cpu ? cpuid_to_apicid[cpu] << 24 : 0;
  45. op.u.pcpu_info.xen_cpuid = cpu;
  46. ret = HYPERVISOR_platform_op(&op);
  47. if (ret)
  48. op.u.pcpu_info.apic_id = BAD_APICID;
  49. return op.u.pcpu_info.apic_id << 24;
  50. }
  51. static void xen_apic_write(u32 reg, u32 val)
  52. {
  53. if (reg == APIC_LVTPC) {
  54. (void)pmu_apic_update(reg);
  55. return;
  56. }
  57. /* Warn to see if there's any stray references */
  58. WARN(1,"register: %x, value: %x\n", reg, val);
  59. }
  60. static void xen_apic_eoi(void)
  61. {
  62. WARN_ON_ONCE(1);
  63. }
  64. static u64 xen_apic_icr_read(void)
  65. {
  66. return 0;
  67. }
  68. static void xen_apic_icr_write(u32 low, u32 id)
  69. {
  70. /* Warn to see if there's any stray references */
  71. WARN_ON(1);
  72. }
  73. static int xen_apic_probe_pv(void)
  74. {
  75. if (xen_pv_domain())
  76. return 1;
  77. return 0;
  78. }
  79. static int xen_madt_oem_check(char *oem_id, char *oem_table_id)
  80. {
  81. return xen_pv_domain();
  82. }
  83. static u32 xen_cpu_present_to_apicid(int cpu)
  84. {
  85. if (cpu_present(cpu))
  86. return cpu_data(cpu).topo.apicid;
  87. else
  88. return BAD_APICID;
  89. }
  90. static struct apic xen_pv_apic __ro_after_init = {
  91. .name = "Xen PV",
  92. .probe = xen_apic_probe_pv,
  93. .acpi_madt_oem_check = xen_madt_oem_check,
  94. /* .delivery_mode and .dest_mode_logical not used by XENPV */
  95. .disable_esr = 0,
  96. .cpu_present_to_apicid = xen_cpu_present_to_apicid,
  97. .max_apic_id = UINT_MAX,
  98. .get_apic_id = xen_get_apic_id,
  99. .calc_dest_apicid = apic_flat_calc_apicid,
  100. #ifdef CONFIG_SMP
  101. .send_IPI_mask = xen_send_IPI_mask,
  102. .send_IPI_mask_allbutself = xen_send_IPI_mask_allbutself,
  103. .send_IPI_allbutself = xen_send_IPI_allbutself,
  104. .send_IPI_all = xen_send_IPI_all,
  105. .send_IPI_self = xen_send_IPI_self,
  106. #endif
  107. .read = xen_apic_read,
  108. .write = xen_apic_write,
  109. .eoi = xen_apic_eoi,
  110. .icr_read = xen_apic_icr_read,
  111. .icr_write = xen_apic_icr_write,
  112. };
  113. apic_driver(xen_pv_apic);
  114. void __init xen_init_apic(void)
  115. {
  116. x86_apic_ops.io_apic_read = xen_io_apic_read;
  117. }