Advertisement
Guest User

Linux-5.5.10-13

a guest
Mar 26th, 2020
417
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 41.31 KB | None | 0 0
  1. diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
  2. index 329d01c689b7..4dffbc10d3f8 100644
  3. --- a/arch/x86/include/asm/kvm_host.h
  4. +++ b/arch/x86/include/asm/kvm_host.h
  5. @@ -78,6 +78,8 @@
  6. #define KVM_REQ_HV_STIMER KVM_ARCH_REQ(22)
  7. #define KVM_REQ_LOAD_EOI_EXITMAP KVM_ARCH_REQ(23)
  8. #define KVM_REQ_GET_VMCS12_PAGES KVM_ARCH_REQ(24)
  9. +#define KVM_REQ_APICV_UPDATE \
  10. + KVM_ARCH_REQ_FLAGS(25, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
  11.  
  12. #define CR0_RESERVED_BITS \
  13. (~(unsigned long)(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS \
  14. @@ -873,6 +875,12 @@ enum kvm_irqchip_mode {
  15. KVM_IRQCHIP_SPLIT, /* created with KVM_CAP_SPLIT_IRQCHIP */
  16. };
  17.  
  18. +#define APICV_INHIBIT_REASON_DISABLE 0
  19. +#define APICV_INHIBIT_REASON_HYPERV 1
  20. +#define APICV_INHIBIT_REASON_NESTED 2
  21. +#define APICV_INHIBIT_REASON_IRQWIN 3
  22. +#define APICV_INHIBIT_REASON_PIT_REINJ 4
  23. +
  24. struct kvm_arch {
  25. unsigned long n_used_mmu_pages;
  26. unsigned long n_requested_mmu_pages;
  27. @@ -904,6 +912,7 @@ struct kvm_arch {
  28. struct kvm_apic_map *apic_map;
  29.  
  30. bool apic_access_page_done;
  31. + unsigned long apicv_inhibit_reasons;
  32.  
  33. gpa_t wall_clock;
  34.  
  35. @@ -1118,7 +1127,8 @@ struct kvm_x86_ops {
  36. void (*enable_nmi_window)(struct kvm_vcpu *vcpu);
  37. void (*enable_irq_window)(struct kvm_vcpu *vcpu);
  38. void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
  39. - bool (*get_enable_apicv)(struct kvm *kvm);
  40. + bool (*check_apicv_inhibit_reasons)(ulong bit);
  41. + void (*pre_update_apicv_exec_ctrl)(struct kvm *kvm, bool activate);
  42. void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
  43. void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
  44. void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr);
  45. @@ -1477,7 +1487,11 @@ gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva,
  46. gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva,
  47. struct x86_exception *exception);
  48.  
  49. -void kvm_vcpu_deactivate_apicv(struct kvm_vcpu *vcpu);
  50. +bool kvm_apicv_activated(struct kvm *kvm);
  51. +void kvm_apicv_init(struct kvm *kvm, bool enable);
  52. +void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu);
  53. +void kvm_request_apicv_update(struct kvm *kvm, bool activate,
  54. + unsigned long bit);
  55.  
  56. int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
  57.  
  58. diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
  59. index 4df1c965bf1a..a86fda7a1d03 100644
  60. --- a/arch/x86/kvm/hyperv.c
  61. +++ b/arch/x86/kvm/hyperv.c
  62. @@ -776,9 +776,10 @@ int kvm_hv_activate_synic(struct kvm_vcpu *vcpu, bool dont_zero_synic_pages)
  63.  
  64. /*
  65. * Hyper-V SynIC auto EOI SINT's are
  66. - * not compatible with APICV, so deactivate APICV
  67. + * not compatible with APICV, so request
  68. + * to deactivate APICV permanently.
  69. */
  70. - kvm_vcpu_deactivate_apicv(vcpu);
  71. + kvm_request_apicv_update(vcpu->kvm, false, APICV_INHIBIT_REASON_HYPERV);
  72. synic->active = true;
  73. synic->dont_zero_synic_pages = dont_zero_synic_pages;
  74. return 0;
  75. diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
  76. index 4a6dc54cc12b..b24c606ac04b 100644
  77. --- a/arch/x86/kvm/i8254.c
  78. +++ b/arch/x86/kvm/i8254.c
  79. @@ -295,12 +295,24 @@ void kvm_pit_set_reinject(struct kvm_pit *pit, bool reinject)
  80. if (atomic_read(&ps->reinject) == reinject)
  81. return;
  82.  
  83. + /*
  84. + * AMD SVM AVIC accelerates EOI write and does not trap.
  85. + * This cause in-kernel PIT re-inject mode to fail
  86. + * since it checks ps->irq_ack before kvm_set_irq()
  87. + * and relies on the ack notifier to timely queue
  88. + * the pt->worker work iterm and reinject the missed tick.
  89. + * So, deactivate APICv when PIT is in reinject mode.
  90. + */
  91. if (reinject) {
  92. + kvm_request_apicv_update(kvm, false,
  93. + APICV_INHIBIT_REASON_PIT_REINJ);
  94. /* The initial state is preserved while ps->reinject == 0. */
  95. kvm_pit_reset_reinject(pit);
  96. kvm_register_irq_ack_notifier(kvm, &ps->irq_ack_notifier);
  97. kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
  98. } else {
  99. + kvm_request_apicv_update(kvm, true,
  100. + APICV_INHIBIT_REASON_PIT_REINJ);
  101. kvm_unregister_irq_ack_notifier(kvm, &ps->irq_ack_notifier);
  102. kvm_unregister_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
  103. }
  104. diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c
  105. index 26aa22cb9b29..7668fed1ce65 100644
  106. --- a/arch/x86/kvm/ioapic.c
  107. +++ b/arch/x86/kvm/ioapic.c
  108. @@ -49,6 +49,11 @@
  109. static int ioapic_service(struct kvm_ioapic *vioapic, int irq,
  110. bool line_status);
  111.  
  112. +static void kvm_ioapic_update_eoi_one(struct kvm_vcpu *vcpu,
  113. + struct kvm_ioapic *ioapic,
  114. + int trigger_mode,
  115. + int pin);
  116. +
  117. static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
  118. unsigned long addr,
  119. unsigned long length)
  120. @@ -154,10 +159,16 @@ static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic)
  121. __rtc_irq_eoi_tracking_restore_one(vcpu);
  122. }
  123.  
  124. -static void rtc_irq_eoi(struct kvm_ioapic *ioapic, struct kvm_vcpu *vcpu)
  125. +static void rtc_irq_eoi(struct kvm_ioapic *ioapic, struct kvm_vcpu *vcpu,
  126. + int vector)
  127. {
  128. - if (test_and_clear_bit(vcpu->vcpu_id,
  129. - ioapic->rtc_status.dest_map.map)) {
  130. + struct dest_map *dest_map = &ioapic->rtc_status.dest_map;
  131. +
  132. + /* RTC special handling */
  133. + if (test_bit(vcpu->vcpu_id, dest_map->map) &&
  134. + (vector == dest_map->vectors[vcpu->vcpu_id]) &&
  135. + (test_and_clear_bit(vcpu->vcpu_id,
  136. + ioapic->rtc_status.dest_map.map))) {
  137. --ioapic->rtc_status.pending_eoi;
  138. rtc_status_pending_eoi_check_valid(ioapic);
  139. }
  140. @@ -171,6 +182,31 @@ static bool rtc_irq_check_coalesced(struct kvm_ioapic *ioapic)
  141. return false;
  142. }
  143.  
  144. +static void ioapic_lazy_update_eoi(struct kvm_ioapic *ioapic, int irq)
  145. +{
  146. + int i;
  147. + struct kvm_vcpu *vcpu;
  148. + union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq];
  149. +
  150. + kvm_for_each_vcpu(i, vcpu, ioapic->kvm) {
  151. + if (!kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
  152. + entry->fields.dest_id,
  153. + entry->fields.dest_mode) ||
  154. + kvm_apic_pending_eoi(vcpu, entry->fields.vector))
  155. + continue;
  156. +
  157. + /*
  158. + * If no longer has pending EOI in LAPICs, update
  159. + * EOI for this vetor.
  160. + */
  161. + rtc_irq_eoi(ioapic, vcpu, entry->fields.vector);
  162. + kvm_ioapic_update_eoi_one(vcpu, ioapic,
  163. + entry->fields.trig_mode,
  164. + irq);
  165. + break;
  166. + }
  167. +}
  168. +
  169. static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq,
  170. int irq_level, bool line_status)
  171. {
  172. @@ -188,6 +224,15 @@ static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq,
  173. goto out;
  174. }
  175.  
  176. + /*
  177. + * AMD SVM AVIC accelerate EOI write and do not trap,
  178. + * in-kernel IOAPIC will not be able to receive the EOI.
  179. + * In this case, we do lazy update of the pending EOI when
  180. + * trying to set IOAPIC irq.
  181. + */
  182. + if (kvm_apicv_activated(ioapic->kvm))
  183. + ioapic_lazy_update_eoi(ioapic, irq);
  184. +
  185. /*
  186. * Return 0 for coalesced interrupts; for edge-triggered interrupts,
  187. * this only happens if a previous edge has not been delivered due
  188. @@ -454,72 +499,68 @@ static void kvm_ioapic_eoi_inject_work(struct work_struct *work)
  189. }
  190.  
  191. #define IOAPIC_SUCCESSIVE_IRQ_MAX_COUNT 10000
  192. -
  193. -static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,
  194. - struct kvm_ioapic *ioapic, int vector, int trigger_mode)
  195. +static void kvm_ioapic_update_eoi_one(struct kvm_vcpu *vcpu,
  196. + struct kvm_ioapic *ioapic,
  197. + int trigger_mode,
  198. + int pin)
  199. {
  200. - struct dest_map *dest_map = &ioapic->rtc_status.dest_map;
  201. struct kvm_lapic *apic = vcpu->arch.apic;
  202. - int i;
  203. -
  204. - /* RTC special handling */
  205. - if (test_bit(vcpu->vcpu_id, dest_map->map) &&
  206. - vector == dest_map->vectors[vcpu->vcpu_id])
  207. - rtc_irq_eoi(ioapic, vcpu);
  208. -
  209. - for (i = 0; i < IOAPIC_NUM_PINS; i++) {
  210. - union kvm_ioapic_redirect_entry *ent = &ioapic->redirtbl[i];
  211. -
  212. - if (ent->fields.vector != vector)
  213. - continue;
  214. + union kvm_ioapic_redirect_entry *ent = &ioapic->redirtbl[pin];
  215.  
  216. - /*
  217. - * We are dropping lock while calling ack notifiers because ack
  218. - * notifier callbacks for assigned devices call into IOAPIC
  219. - * recursively. Since remote_irr is cleared only after call
  220. - * to notifiers if the same vector will be delivered while lock
  221. - * is dropped it will be put into irr and will be delivered
  222. - * after ack notifier returns.
  223. - */
  224. - spin_unlock(&ioapic->lock);
  225. - kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, i);
  226. - spin_lock(&ioapic->lock);
  227. + /*
  228. + * We are dropping lock while calling ack notifiers because ack
  229. + * notifier callbacks for assigned devices call into IOAPIC
  230. + * recursively. Since remote_irr is cleared only after call
  231. + * to notifiers if the same vector will be delivered while lock
  232. + * is dropped it will be put into irr and will be delivered
  233. + * after ack notifier returns.
  234. + */
  235. + spin_unlock(&ioapic->lock);
  236. + kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, pin);
  237. + spin_lock(&ioapic->lock);
  238.  
  239. - if (trigger_mode != IOAPIC_LEVEL_TRIG ||
  240. - kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)
  241. - continue;
  242. + if (trigger_mode != IOAPIC_LEVEL_TRIG ||
  243. + kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)
  244. + return;
  245.  
  246. - ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
  247. - ent->fields.remote_irr = 0;
  248. - if (!ent->fields.mask && (ioapic->irr & (1 << i))) {
  249. - ++ioapic->irq_eoi[i];
  250. - if (ioapic->irq_eoi[i] == IOAPIC_SUCCESSIVE_IRQ_MAX_COUNT) {
  251. - /*
  252. - * Real hardware does not deliver the interrupt
  253. - * immediately during eoi broadcast, and this
  254. - * lets a buggy guest make slow progress
  255. - * even if it does not correctly handle a
  256. - * level-triggered interrupt. Emulate this
  257. - * behavior if we detect an interrupt storm.
  258. - */
  259. - schedule_delayed_work(&ioapic->eoi_inject, HZ / 100);
  260. - ioapic->irq_eoi[i] = 0;
  261. - trace_kvm_ioapic_delayed_eoi_inj(ent->bits);
  262. - } else {
  263. - ioapic_service(ioapic, i, false);
  264. - }
  265. + ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
  266. + ent->fields.remote_irr = 0;
  267. + if (!ent->fields.mask && (ioapic->irr & (1 << pin))) {
  268. + ++ioapic->irq_eoi[pin];
  269. + if (ioapic->irq_eoi[pin] == IOAPIC_SUCCESSIVE_IRQ_MAX_COUNT) {
  270. + /*
  271. + * Real hardware does not deliver the interrupt
  272. + * immediately during eoi broadcast, and this
  273. + * lets a buggy guest make slow progress
  274. + * even if it does not correctly handle a
  275. + * level-triggered interrupt. Emulate this
  276. + * behavior if we detect an interrupt storm.
  277. + */
  278. + schedule_delayed_work(&ioapic->eoi_inject, HZ / 100);
  279. + ioapic->irq_eoi[pin] = 0;
  280. + trace_kvm_ioapic_delayed_eoi_inj(ent->bits);
  281. } else {
  282. - ioapic->irq_eoi[i] = 0;
  283. + ioapic_service(ioapic, pin, false);
  284. }
  285. + } else {
  286. + ioapic->irq_eoi[pin] = 0;
  287. }
  288. }
  289.  
  290. void kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, int vector, int trigger_mode)
  291. {
  292. + int i;
  293. struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;
  294.  
  295. spin_lock(&ioapic->lock);
  296. - __kvm_ioapic_update_eoi(vcpu, ioapic, vector, trigger_mode);
  297. + rtc_irq_eoi(ioapic, vcpu, vector);
  298. + for (i = 0; i < IOAPIC_NUM_PINS; i++) {
  299. + union kvm_ioapic_redirect_entry *ent = &ioapic->redirtbl[i];
  300. +
  301. + if (ent->fields.vector != vector)
  302. + continue;
  303. + kvm_ioapic_update_eoi_one(vcpu, ioapic, trigger_mode, i);
  304. + }
  305. spin_unlock(&ioapic->lock);
  306. }
  307.  
  308. diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
  309. index 9dbb990c319a..bf0556588ad0 100644
  310. --- a/arch/x86/kvm/svm.c
  311. +++ b/arch/x86/kvm/svm.c
  312. @@ -387,6 +387,8 @@ static u8 rsm_ins_bytes[] = "\x0f\xaa";
  313. static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
  314. static void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa);
  315. static void svm_complete_interrupts(struct vcpu_svm *svm);
  316. +static void svm_toggle_avic_for_irq_window(struct kvm_vcpu *vcpu, bool activate);
  317. +static inline void avic_post_state_restore(struct kvm_vcpu *vcpu);
  318.  
  319. static int nested_svm_exit_handled(struct vcpu_svm *svm);
  320. static int nested_svm_intercept(struct vcpu_svm *svm);
  321. @@ -1545,7 +1547,10 @@ static void avic_init_vmcb(struct vcpu_svm *svm)
  322. vmcb->control.avic_logical_id = lpa & AVIC_HPA_MASK;
  323. vmcb->control.avic_physical_id = ppa & AVIC_HPA_MASK;
  324. vmcb->control.avic_physical_id |= AVIC_MAX_PHYSICAL_ID_COUNT;
  325. - vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
  326. + if (kvm_apicv_activated(svm->vcpu.kvm))
  327. + vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
  328. + else
  329. + vmcb->control.int_ctl &= ~AVIC_ENABLE_MASK;
  330. }
  331.  
  332. static void init_vmcb(struct vcpu_svm *svm)
  333. @@ -1729,23 +1734,28 @@ static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu,
  334. * field of the VMCB. Therefore, we set up the
  335. * APIC_ACCESS_PAGE_PRIVATE_MEMSLOT (4KB) here.
  336. */
  337. -static int avic_init_access_page(struct kvm_vcpu *vcpu)
  338. +static int avic_update_access_page(struct kvm *kvm, bool activate)
  339. {
  340. - struct kvm *kvm = vcpu->kvm;
  341. int ret = 0;
  342.  
  343. mutex_lock(&kvm->slots_lock);
  344. - if (kvm->arch.apic_access_page_done)
  345. + /*
  346. + * During kvm_destroy_vm(), kvm_pit_set_reinject() could trigger
  347. + * APICv mode change, which update APIC_ACCESS_PAGE_PRIVATE_MEMSLOT
  348. + * memory region. So, we need to ensure that kvm->mm == current->mm.
  349. + */
  350. + if ((kvm->arch.apic_access_page_done == activate) ||
  351. + (kvm->mm != current->mm))
  352. goto out;
  353.  
  354. ret = __x86_set_memory_region(kvm,
  355. APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
  356. APIC_DEFAULT_PHYS_BASE,
  357. - PAGE_SIZE);
  358. + activate ? PAGE_SIZE : 0);
  359. if (ret)
  360. goto out;
  361.  
  362. - kvm->arch.apic_access_page_done = true;
  363. + kvm->arch.apic_access_page_done = activate;
  364. out:
  365. mutex_unlock(&kvm->slots_lock);
  366. return ret;
  367. @@ -1753,21 +1763,24 @@ static int avic_init_access_page(struct kvm_vcpu *vcpu)
  368.  
  369. static int avic_init_backing_page(struct kvm_vcpu *vcpu)
  370. {
  371. - int ret;
  372. u64 *entry, new_entry;
  373. int id = vcpu->vcpu_id;
  374. struct vcpu_svm *svm = to_svm(vcpu);
  375.  
  376. - ret = avic_init_access_page(vcpu);
  377. - if (ret)
  378. - return ret;
  379. -
  380. if (id >= AVIC_MAX_PHYSICAL_ID_COUNT)
  381. return -EINVAL;
  382.  
  383. if (!svm->vcpu.arch.apic->regs)
  384. return -EINVAL;
  385.  
  386. + if (kvm_apicv_activated(vcpu->kvm)) {
  387. + int ret;
  388. +
  389. + ret = avic_update_access_page(vcpu->kvm, true);
  390. + if (ret)
  391. + return ret;
  392. + }
  393. +
  394. svm->avic_backing_page = virt_to_page(svm->vcpu.arch.apic->regs);
  395.  
  396. /* Setting AVIC backing page address in the phy APIC ID table */
  397. @@ -2052,6 +2065,18 @@ static int avic_vm_init(struct kvm *kvm)
  398. return err;
  399. }
  400.  
  401. +static int svm_vm_init(struct kvm *kvm)
  402. +{
  403. + if (avic) {
  404. + int ret = avic_vm_init(kvm);
  405. + if (ret)
  406. + return ret;
  407. + }
  408. +
  409. + kvm_apicv_init(kvm, avic);
  410. + return 0;
  411. +}
  412. +
  413. static inline int
  414. avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int cpu, bool r)
  415. {
  416. @@ -2223,7 +2248,8 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu)
  417. /* We initialize this flag to true to make sure that the is_running
  418. * bit would be set the first time the vcpu is loaded.
  419. */
  420. - svm->avic_is_running = true;
  421. + if (irqchip_in_kernel(vcpu->kvm) && kvm_apicv_activated(vcpu->kvm))
  422. + svm->avic_is_running = true;
  423.  
  424. svm->nested.hsave = page_address(hsave_page);
  425.  
  426. @@ -2348,6 +2374,8 @@ static void svm_vcpu_blocking(struct kvm_vcpu *vcpu)
  427.  
  428. static void svm_vcpu_unblocking(struct kvm_vcpu *vcpu)
  429. {
  430. + if (kvm_check_request(KVM_REQ_APICV_UPDATE, vcpu))
  431. + kvm_vcpu_update_apicv(vcpu);
  432. avic_set_running(vcpu, true);
  433. }
  434.  
  435. @@ -4440,6 +4468,14 @@ static int interrupt_window_interception(struct vcpu_svm *svm)
  436. {
  437. kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
  438. svm_clear_vintr(svm);
  439. +
  440. + /*
  441. + * For AVIC, the only reason to end up here is ExtINTs.
  442. + * In this case AVIC was temporarily disabled for
  443. + * requesting the IRQ window and we have to re-enable it.
  444. + */
  445. + svm_toggle_avic_for_irq_window(&svm->vcpu, true);
  446. +
  447. svm->vmcb->control.int_ctl &= ~V_IRQ_MASK;
  448. mark_dirty(svm->vmcb, VMCB_INTR);
  449. ++svm->vcpu.stat.irq_window_exits;
  450. @@ -5135,30 +5171,79 @@ static void svm_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
  451. return;
  452. }
  453.  
  454. -static bool svm_get_enable_apicv(struct kvm *kvm)
  455. +static void svm_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)
  456. {
  457. - return avic && irqchip_split(kvm);
  458. }
  459.  
  460. -static void svm_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)
  461. +static void svm_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
  462. {
  463. }
  464.  
  465. -static void svm_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
  466. +static void svm_toggle_avic_for_irq_window(struct kvm_vcpu *vcpu, bool activate)
  467. {
  468. + if (!avic || !lapic_in_kernel(vcpu))
  469. + return;
  470. +
  471. + srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
  472. + kvm_request_apicv_update(vcpu->kvm, activate,
  473. + APICV_INHIBIT_REASON_IRQWIN);
  474. + vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
  475. +}
  476. +
  477. +static int svm_set_pi_irte_mode(struct kvm_vcpu *vcpu, bool activate)
  478. +{
  479. + int ret = 0;
  480. + unsigned long flags;
  481. + struct amd_svm_iommu_ir *ir;
  482. + struct vcpu_svm *svm = to_svm(vcpu);
  483. +
  484. + if (!kvm_arch_has_assigned_device(vcpu->kvm))
  485. + return 0;
  486. +
  487. + /*
  488. + * Here, we go through the per-vcpu ir_list to update all existing
  489. + * interrupt remapping table entry targeting this vcpu.
  490. + */
  491. + spin_lock_irqsave(&svm->ir_list_lock, flags);
  492. +
  493. + if (list_empty(&svm->ir_list))
  494. + goto out;
  495. +
  496. + list_for_each_entry(ir, &svm->ir_list, node) {
  497. + if (activate)
  498. + ret = amd_iommu_activate_guest_mode(ir->data);
  499. + else
  500. + ret = amd_iommu_deactivate_guest_mode(ir->data);
  501. + if (ret)
  502. + break;
  503. + }
  504. +out:
  505. + spin_unlock_irqrestore(&svm->ir_list_lock, flags);
  506. + return ret;
  507. }
  508.  
  509. -/* Note: Currently only used by Hyper-V. */
  510. static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
  511. {
  512. struct vcpu_svm *svm = to_svm(vcpu);
  513. struct vmcb *vmcb = svm->vmcb;
  514. + bool activated = kvm_vcpu_apicv_active(vcpu);
  515.  
  516. - if (kvm_vcpu_apicv_active(vcpu))
  517. + if (activated) {
  518. + /**
  519. + * During AVIC temporary deactivation, guest could update
  520. + * APIC ID, DFR and LDR registers, which would not be trapped
  521. + * by avic_unaccelerated_access_interception(). In this case,
  522. + * we need to check and update the AVIC logical APIC ID table
  523. + * accordingly before re-activating.
  524. + */
  525. + avic_post_state_restore(vcpu);
  526. vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
  527. - else
  528. + } else {
  529. vmcb->control.int_ctl &= ~AVIC_ENABLE_MASK;
  530. + }
  531. mark_dirty(vmcb, VMCB_AVIC);
  532. +
  533. + svm_set_pi_irte_mode(vcpu, activated);
  534. }
  535.  
  536. static void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
  537. @@ -5445,9 +5530,6 @@ static void enable_irq_window(struct kvm_vcpu *vcpu)
  538. {
  539. struct vcpu_svm *svm = to_svm(vcpu);
  540.  
  541. - if (kvm_vcpu_apicv_active(vcpu))
  542. - return;
  543. -
  544. /*
  545. * In case GIF=0 we can't rely on the CPU to tell us when GIF becomes
  546. * 1, because that's a separate STGI/VMRUN intercept. The next time we
  547. @@ -5457,6 +5539,13 @@ static void enable_irq_window(struct kvm_vcpu *vcpu)
  548. * window under the assumption that the hardware will set the GIF.
  549. */
  550. if ((vgif_enabled(svm) || gif_set(svm)) && nested_svm_intr(svm)) {
  551. + /*
  552. + * IRQ window is not needed when AVIC is enabled,
  553. + * unless we have pending ExtINT since it cannot be injected
  554. + * via AVIC. In such case, we need to temporarily disable AVIC,
  555. + * and fallback to injecting IRQ via V_IRQ.
  556. + */
  557. + svm_toggle_avic_for_irq_window(vcpu, false);
  558. svm_set_vintr(svm);
  559. svm_inject_irq(svm, 0x0);
  560. }
  561. @@ -5929,6 +6018,14 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu)
  562. return;
  563.  
  564. guest_cpuid_clear(vcpu, X86_FEATURE_X2APIC);
  565. +
  566. + /*
  567. + * Currently, AVIC does not work with nested virtualization.
  568. + * So, we disable AVIC when cpuid for SVM is set in the L1 guest.
  569. + */
  570. + if (nested && guest_cpuid_has(vcpu, X86_FEATURE_SVM))
  571. + kvm_request_apicv_update(vcpu->kvm, false,
  572. + APICV_INHIBIT_REASON_NESTED);
  573. }
  574.  
  575. #define F feature_bit
  576. @@ -7257,6 +7354,22 @@ static bool svm_apic_init_signal_blocked(struct kvm_vcpu *vcpu)
  577. (svm->vmcb->control.intercept & (1ULL << INTERCEPT_INIT));
  578. }
  579.  
  580. +static bool svm_check_apicv_inhibit_reasons(ulong bit)
  581. +{
  582. + ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) |
  583. + BIT(APICV_INHIBIT_REASON_HYPERV) |
  584. + BIT(APICV_INHIBIT_REASON_NESTED) |
  585. + BIT(APICV_INHIBIT_REASON_IRQWIN) |
  586. + BIT(APICV_INHIBIT_REASON_PIT_REINJ);
  587. +
  588. + return supported & BIT(bit);
  589. +}
  590. +
  591. +static void svm_pre_update_apicv_exec_ctrl(struct kvm *kvm, bool activate)
  592. +{
  593. + avic_update_access_page(kvm, activate);
  594. +}
  595. +
  596. static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
  597. .cpu_has_kvm_support = has_svm,
  598. .disabled_by_bios = is_disabled,
  599. @@ -7274,7 +7387,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
  600.  
  601. .vm_alloc = svm_vm_alloc,
  602. .vm_free = svm_vm_free,
  603. - .vm_init = avic_vm_init,
  604. + .vm_init = svm_vm_init,
  605. .vm_destroy = svm_vm_destroy,
  606.  
  607. .prepare_guest_switch = svm_prepare_guest_switch,
  608. @@ -7331,8 +7444,9 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
  609. .enable_irq_window = enable_irq_window,
  610. .update_cr8_intercept = update_cr8_intercept,
  611. .set_virtual_apic_mode = svm_set_virtual_apic_mode,
  612. - .get_enable_apicv = svm_get_enable_apicv,
  613. .refresh_apicv_exec_ctrl = svm_refresh_apicv_exec_ctrl,
  614. + .check_apicv_inhibit_reasons = svm_check_apicv_inhibit_reasons,
  615. + .pre_update_apicv_exec_ctrl = svm_pre_update_apicv_exec_ctrl,
  616. .load_eoi_exitmap = svm_load_eoi_exitmap,
  617. .hwapic_irr_update = svm_hwapic_irr_update,
  618. .hwapic_isr_update = svm_hwapic_isr_update,
  619. diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
  620. index 7c741a0c5f80..f194dd058470 100644
  621. --- a/arch/x86/kvm/trace.h
  622. +++ b/arch/x86/kvm/trace.h
  623. @@ -1291,6 +1291,25 @@ TRACE_EVENT(kvm_hv_stimer_cleanup,
  624. __entry->vcpu_id, __entry->timer_index)
  625. );
  626.  
  627. +TRACE_EVENT(kvm_apicv_update_request,
  628. + TP_PROTO(bool activate, unsigned long bit),
  629. + TP_ARGS(activate, bit),
  630. +
  631. + TP_STRUCT__entry(
  632. + __field(bool, activate)
  633. + __field(unsigned long, bit)
  634. + ),
  635. +
  636. + TP_fast_assign(
  637. + __entry->activate = activate;
  638. + __entry->bit = bit;
  639. + ),
  640. +
  641. + TP_printk("%s bit=%lu",
  642. + __entry->activate ? "activate" : "deactivate",
  643. + __entry->bit)
  644. +);
  645. +
  646. /*
  647. * Tracepoint for AMD AVIC
  648. */
  649. diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
  650. index c475fa2aaae0..678edbd6e278 100644
  651. --- a/arch/x86/kvm/vmx/vmx.c
  652. +++ b/arch/x86/kvm/vmx/vmx.c
  653. @@ -3719,11 +3719,6 @@ void pt_update_intercept_for_msr(struct vcpu_vmx *vmx)
  654. }
  655. }
  656.  
  657. -static bool vmx_get_enable_apicv(struct kvm *kvm)
  658. -{
  659. - return enable_apicv;
  660. -}
  661. -
  662. static bool vmx_guest_apic_has_interrupt(struct kvm_vcpu *vcpu)
  663. {
  664. struct vcpu_vmx *vmx = to_vmx(vcpu);
  665. @@ -6813,6 +6808,7 @@ static int vmx_vm_init(struct kvm *kvm)
  666. break;
  667. }
  668. }
  669. + kvm_apicv_init(kvm, enable_apicv);
  670. return 0;
  671. }
  672.  
  673. @@ -7714,6 +7710,14 @@ static __exit void hardware_unsetup(void)
  674. free_kvm_area();
  675. }
  676.  
  677. +static bool vmx_check_apicv_inhibit_reasons(ulong bit)
  678. +{
  679. + ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) |
  680. + BIT(APICV_INHIBIT_REASON_HYPERV);
  681. +
  682. + return supported & BIT(bit);
  683. +}
  684. +
  685. static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
  686. .cpu_has_kvm_support = cpu_has_kvm_support,
  687. .disabled_by_bios = vmx_disabled_by_bios,
  688. @@ -7786,10 +7790,10 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
  689. .update_cr8_intercept = update_cr8_intercept,
  690. .set_virtual_apic_mode = vmx_set_virtual_apic_mode,
  691. .set_apic_access_page_addr = vmx_set_apic_access_page_addr,
  692. - .get_enable_apicv = vmx_get_enable_apicv,
  693. .refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,
  694. .load_eoi_exitmap = vmx_load_eoi_exitmap,
  695. .apicv_post_state_restore = vmx_apicv_post_state_restore,
  696. + .check_apicv_inhibit_reasons = vmx_check_apicv_inhibit_reasons,
  697. .hwapic_irr_update = vmx_hwapic_irr_update,
  698. .hwapic_isr_update = vmx_hwapic_isr_update,
  699. .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
  700. diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
  701. index 2d3be7f3ad67..52edf0bb46e5 100644
  702. --- a/arch/x86/kvm/x86.c
  703. +++ b/arch/x86/kvm/x86.c
  704. @@ -26,6 +26,7 @@
  705. #include "cpuid.h"
  706. #include "pmu.h"
  707. #include "hyperv.h"
  708. +#include "lapic.h"
  709.  
  710. #include <linux/clocksource.h>
  711. #include <linux/interrupt.h>
  712. @@ -7456,18 +7457,22 @@ static void kvm_pv_kick_cpu_op(struct kvm *kvm, unsigned long flags, int apicid)
  713. kvm_irq_delivery_to_apic(kvm, NULL, &lapic_irq, NULL);
  714. }
  715.  
  716. -void kvm_vcpu_deactivate_apicv(struct kvm_vcpu *vcpu)
  717. +bool kvm_apicv_activated(struct kvm *kvm)
  718. {
  719. - if (!lapic_in_kernel(vcpu)) {
  720. - WARN_ON_ONCE(vcpu->arch.apicv_active);
  721. - return;
  722. - }
  723. - if (!vcpu->arch.apicv_active)
  724. - return;
  725. + return (READ_ONCE(kvm->arch.apicv_inhibit_reasons) == 0);
  726. +}
  727. +EXPORT_SYMBOL_GPL(kvm_apicv_activated);
  728.  
  729. - vcpu->arch.apicv_active = false;
  730. - kvm_x86_ops->refresh_apicv_exec_ctrl(vcpu);
  731. +void kvm_apicv_init(struct kvm *kvm, bool enable)
  732. +{
  733. + if (enable)
  734. + clear_bit(APICV_INHIBIT_REASON_DISABLE,
  735. + &kvm->arch.apicv_inhibit_reasons);
  736. + else
  737. + set_bit(APICV_INHIBIT_REASON_DISABLE,
  738. + &kvm->arch.apicv_inhibit_reasons);
  739. }
  740. +EXPORT_SYMBOL_GPL(kvm_apicv_init);
  741.  
  742. static void kvm_sched_yield(struct kvm *kvm, unsigned long dest_id)
  743. {
  744. @@ -7996,6 +8001,47 @@ void kvm_make_scan_ioapic_request(struct kvm *kvm)
  745. kvm_make_all_cpus_request(kvm, KVM_REQ_SCAN_IOAPIC);
  746. }
  747.  
  748. +void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu)
  749. +{
  750. + if (!lapic_in_kernel(vcpu))
  751. + return;
  752. +
  753. + vcpu->arch.apicv_active = kvm_apicv_activated(vcpu->kvm);
  754. + kvm_apic_update_apicv(vcpu);
  755. + kvm_x86_ops->refresh_apicv_exec_ctrl(vcpu);
  756. +}
  757. +EXPORT_SYMBOL_GPL(kvm_vcpu_update_apicv);
  758. +
  759. +/*
  760. + * NOTE: Do not hold any lock prior to calling this.
  761. + *
  762. + * In particular, kvm_request_apicv_update() expects kvm->srcu not to be
  763. + * locked, because it calls __x86_set_memory_region() which does
  764. + * synchronize_srcu(&kvm->srcu).
  765. + */
  766. +void kvm_request_apicv_update(struct kvm *kvm, bool activate, ulong bit)
  767. +{
  768. + if (!kvm_x86_ops->check_apicv_inhibit_reasons ||
  769. + !kvm_x86_ops->check_apicv_inhibit_reasons(bit))
  770. + return;
  771. +
  772. + if (activate) {
  773. + if (!test_and_clear_bit(bit, &kvm->arch.apicv_inhibit_reasons) ||
  774. + !kvm_apicv_activated(kvm))
  775. + return;
  776. + } else {
  777. + if (test_and_set_bit(bit, &kvm->arch.apicv_inhibit_reasons) ||
  778. + kvm_apicv_activated(kvm))
  779. + return;
  780. + }
  781. +
  782. + trace_kvm_apicv_update_request(activate, bit);
  783. + if (kvm_x86_ops->pre_update_apicv_exec_ctrl)
  784. + kvm_x86_ops->pre_update_apicv_exec_ctrl(kvm, activate);
  785. + kvm_make_all_cpus_request(kvm, KVM_REQ_APICV_UPDATE);
  786. +}
  787. +EXPORT_SYMBOL_GPL(kvm_request_apicv_update);
  788. +
  789. static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu)
  790. {
  791. if (!kvm_apic_present(vcpu))
  792. @@ -8186,6 +8232,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
  793. */
  794. if (kvm_check_request(KVM_REQ_HV_STIMER, vcpu))
  795. kvm_hv_process_stimers(vcpu);
  796. + if (kvm_check_request(KVM_REQ_APICV_UPDATE, vcpu))
  797. + kvm_vcpu_update_apicv(vcpu);
  798. }
  799.  
  800. if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
  801. @@ -9219,10 +9267,11 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
  802. return r;
  803.  
  804. if (irqchip_in_kernel(vcpu->kvm)) {
  805. - vcpu->arch.apicv_active = kvm_x86_ops->get_enable_apicv(vcpu->kvm);
  806. r = kvm_create_lapic(vcpu, lapic_timer_advance_ns);
  807. if (r < 0)
  808. goto fail_mmu_destroy;
  809. + if (kvm_apicv_activated(vcpu->kvm))
  810. + vcpu->arch.apicv_active = true;
  811. } else
  812. static_key_slow_inc(&kvm_no_apic_vcpu);
  813.  
  814. @@ -10448,3 +10497,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pml_full);
  815. EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pi_irte_update);
  816. EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_unaccelerated_access);
  817. EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_incomplete_ipi);
  818. +EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_apicv_update_request);
  819.  
  820. From patchwork Thu Mar 12 10:39:28 2020
  821. Content-Type: text/plain; charset="utf-8"
  822. MIME-Version: 1.0
  823. Content-Transfer-Encoding: 7bit
  824. X-Patchwork-Submitter: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
  825. X-Patchwork-Id: 1208775
  826. Return-Path: <SRS0=+FT0=45=vger.kernel.org=linux-kernel-owner@kernel.org>
  827. Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
  828. by smtp.lore.kernel.org (Postfix) with ESMTP id B1216C10DCE
  829. for <linux-kernel@archiver.kernel.org>; Thu, 12 Mar 2020 10:39:44 +0000 (UTC)
  830. Received: from vger.kernel.org (vger.kernel.org [209.132.180.67])
  831. by mail.kernel.org (Postfix) with ESMTP id 7C7A9206BE
  832. for <linux-kernel@archiver.kernel.org>; Thu, 12 Mar 2020 10:39:44 +0000 (UTC)
  833. Authentication-Results: mail.kernel.org;
  834. dkim=pass (1024-bit key) header.d=amdcloud.onmicrosoft.com
  835. header.i=@amdcloud.onmicrosoft.com header.b="ArIUjTS2"
  836. Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
  837. id S1726898AbgCLKjn (ORCPT
  838. <rfc822;linux-kernel@archiver.kernel.org>);
  839. Thu, 12 Mar 2020 06:39:43 -0400
  840. Received: from mail-dm6nam11on2042.outbound.protection.outlook.com
  841. ([40.107.223.42]:65504
  842. "EHLO NAM11-DM6-obe.outbound.protection.outlook.com"
  843. rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP
  844. id S1726023AbgCLKjm (ORCPT <rfc822;linux-kernel@vger.kernel.org>);
  845. Thu, 12 Mar 2020 06:39:42 -0400
  846. ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
  847. b=cJ//0OxCNsTuWhvFb4ZnQgHAjrIFoINQgzVEBF93klN4rTvAU+m2yM+JwYFZTrNNy6bfyLgFt6Tb+GvXOh9IZaZZF+Yc2tCK6TyJMbkCWhBQaBAwXH0tpPp8mMkVor0AJ5YaQZVT9LLWqkL1yjuCrslzMSszPNz6/BesWhU5CEPELgd+iQmZa8b8pch8aAp3botQD2aIGeKt1DMDHXD2t0Izt7JHBOQ/HWk1yl0cfecnG1xTFDz638xebdYeeCdD1WGHqBTp4ethgEIvfILIs4INDmUrrHkjVMNUrzkJqDz5vaZTv4b5NEBLnvLBsHtwVGR+9IVhSC+1ndJDMuJ5tA==
  848. ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
  849. s=arcselector9901;
  850. h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
  851. bh=fWlPjNv/NennGkA26zbaVAstC6MS7BJPLzel49z3I1c=;
  852. b=So1Bq24SCM9y7gTaltt8NCl7xLJD6BslokEMRk0CFhk1W1DmIdcTGLvgEuQaSvE7p5qQrvRjSiaV4JIvyzJKpyBfv+vrfmX6S1rJY4i0F60Hgy9PW6yZNxxmV58wwS+/sjxZecnM2lsox+5fYMC0auaXo9si4zS68qAcVdhCAGjwLlpdyqa6zZuRAp4B7jRMiaXHwnT/rKMKDzxTaHrUusj/8FAQyRYDptolqVLkqrAM3WPSNnVYJUOFSoa0VOn+LfvD6dwuZmBefukl+kl1HBB1QZhj/2DxLPtXa+lKtsrKq2/gqyPW4dhoFj46xETNyo6lH6X7Pwlz2hiCpTr7SA==
  853. ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass
  854. smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass
  855. header.d=amd.com; arc=none
  856. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
  857. d=amdcloud.onmicrosoft.com; s=selector2-amdcloud-onmicrosoft-com;
  858. h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
  859. bh=fWlPjNv/NennGkA26zbaVAstC6MS7BJPLzel49z3I1c=;
  860. b=ArIUjTS2LZaV9MH7grOJemnrIWTIb4zMgTY4Qjckm0ek8xUo31didVQpsuMqi0tGVqFbwwRa0TBfPkOCJxgrCijlmb/CLML046k/m+uEh5FW2Sr6Pt5o4a82BQZGTYwULOCBH/1Vpfh8rMFABZ2PJMGZ0HWoeoccZv2ISuK3QQs=
  861. Authentication-Results: spf=none (sender IP is )
  862. smtp.mailfrom=Suravee.Suthikulpanit@amd.com;
  863. Received: from DM6PR12MB3865.namprd12.prod.outlook.com (2603:10b6:5:1c4::14)
  864. by DM6PR12MB2812.namprd12.prod.outlook.com (2603:10b6:5:44::27) with
  865. Microsoft SMTP Server (version=TLS1_2,
  866. cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2793.17; Thu, 12 Mar
  867. 2020 10:39:38 +0000
  868. Received: from DM6PR12MB3865.namprd12.prod.outlook.com
  869. ([fe80::2d84:ed9d:cba4:dcfd]) by DM6PR12MB3865.namprd12.prod.outlook.com
  870. ([fe80::2d84:ed9d:cba4:dcfd%3]) with mapi id 15.20.2793.018; Thu, 12 Mar 2020
  871. 10:39:37 +0000
  872. From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
  873. To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
  874. Cc: pbonzini@redhat.com, joro@8bytes.org, jon.grimm@amd.com,
  875. Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
  876. Subject: [PATCH] kvm: svm: Introduce GA Log tracepoint for AVIC
  877. Date: Thu, 12 Mar 2020 05:39:28 -0500
  878. Message-Id: <1584009568-14089-1-git-send-email-suravee.suthikulpanit@amd.com>
  879. X-Mailer: git-send-email 1.8.3.1
  880. X-ClientProxiedBy: DM5PR2001CA0011.namprd20.prod.outlook.com
  881. (2603:10b6:4:16::21) To DM6PR12MB3865.namprd12.prod.outlook.com
  882. (2603:10b6:5:1c4::14)
  883. MIME-Version: 1.0
  884. X-MS-Exchange-MessageSentRepresentingType: 1
  885. Received: from ssuthiku-rhel7-ssp.amd.com (165.204.78.2) by
  886. DM5PR2001CA0011.namprd20.prod.outlook.com (2603:10b6:4:16::21) with Microsoft
  887. SMTP Server (version=TLS1_2,
  888. cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2793.16 via Frontend
  889. Transport; Thu, 12 Mar 2020 10:39:37 +0000
  890. X-Mailer: git-send-email 1.8.3.1
  891. X-Originating-IP: [165.204.78.2]
  892. X-MS-PublicTrafficType: Email
  893. X-MS-Office365-Filtering-HT: Tenant
  894. X-MS-Office365-Filtering-Correlation-Id: dcb947a3-853e-4140-a1a9-08d7c671a9a2
  895. X-MS-TrafficTypeDiagnostic: DM6PR12MB2812:|DM6PR12MB2812:
  896. X-MS-Exchange-Transport-Forked: True
  897. X-Microsoft-Antispam-PRVS:
  898. <DM6PR12MB28120BDE5B7890772626263EF3FD0@DM6PR12MB2812.namprd12.prod.outlook.com>
  899. X-MS-Oob-TLC-OOBClassifiers: OLM:4502;
  900. X-Forefront-PRVS: 0340850FCD
  901. X-Forefront-Antispam-Report:
  902. SFV:NSPM;SFS:(10009020)(4636009)(136003)(396003)(366004)(346002)(39860400002)(376002)(199004)(478600001)(4326008)(6666004)(86362001)(66556008)(66476007)(7696005)(316002)(81166006)(8676002)(81156014)(52116002)(2906002)(66946007)(5660300002)(6486002)(8936002)(16526019)(44832011)(956004)(2616005)(26005)(36756003)(186003);DIR:OUT;SFP:1101;SCL:1;SRVR:DM6PR12MB2812;H:DM6PR12MB3865.namprd12.prod.outlook.com;FPR:;SPF:None;LANG:en;PTR:InfoNoRecords;A:1;
  903. Received-SPF: None (protection.outlook.com: amd.com does not designate
  904. permitted sender hosts)
  905. X-MS-Exchange-SenderADCheck: 1
  906. X-Microsoft-Antispam: BCL:0;
  907. X-Microsoft-Antispam-Message-Info:
  908. FTBOzwS2IHHTpztPexVQk/N6ATf/++RSt7ztOUaIl6sPxfJgWytBYaqGm7alOHLD7E5KaIltnmdwE2jfR9yT6sbNF6HlTtnARVvc+cqS8RrxUaZGYfpXzhoZM6TtSAGcLnuk4x+u7W8QNvf7u8+do3DYpqC6SR3d8IR8t7vMlVbxmdcZrYF5QvnnwYDsSQZTCh8dZMvZ5JBX6gTvuZcx/KtwfYhBgMxUZO0PhHin6COHQHtv3/JbKFbnVRcAd1ng5T2qrHx+zuLz7dAPSr2WnGJealFA7QE9IoVWhMSTeYE1qWJIuTi/hKf5HTHlCcOzc8QQphIQQSQmsF5a423xUF35V5Cv05RbIx/KM2pcksAVrv0hay3MIu6Nc0PXAu8QEk61mpudCqME8UdkzynfarWMN4iQ3aay3OI0ZsSGXybETmiGypqsp2UHEK3Y39RP
  909. X-MS-Exchange-AntiSpam-MessageData:
  910. R8KUGQeKjOTa73q16Alk48bpW+D3xqx7EtqMUsvyjRv6aPqgVVhJkw6oKKWY16CWKtV1ULzy2OSFszfoVtEJZCQ/onXO2OWgsYKAWBGEXp6fmrMRuVIR51o0FEbed9R5gU/Lo5Kc2Ue2VJlnDbjxXA==
  911. X-OriginatorOrg: amd.com
  912. X-MS-Exchange-CrossTenant-Network-Message-Id:
  913. dcb947a3-853e-4140-a1a9-08d7c671a9a2
  914. X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Mar 2020 10:39:37.8294
  915. (UTC)
  916. X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted
  917. X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d
  918. X-MS-Exchange-CrossTenant-MailboxType: HOSTED
  919. X-MS-Exchange-CrossTenant-UserPrincipalName:
  920. 8T0Dfc4NvYJL51OpFfP7ab+zzKldgvJyD8rkl2NfAfqe7YqXud21D+COqcbQbx2+wS7nISYb8BKkSgXHqPlBtA==
  921. X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB2812
  922. Sender: linux-kernel-owner@vger.kernel.org
  923. Precedence: bulk
  924. List-ID: <linux-kernel.vger.kernel.org>
  925. X-Mailing-List: linux-kernel@vger.kernel.org
  926.  
  927. GA Log tracepoint is useful when debugging AVIC performance
  928. issue as it can be used with perf to count the number of times
  929. IOMMU AVIC injects interrupts through the slow-path instead of
  930. directly inject interrupts to the target vcpu.
  931.  
  932. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
  933. ---
  934. arch/x86/kvm/svm.c | 1 +
  935. arch/x86/kvm/trace.h | 18 ++++++++++++++++++
  936. arch/x86/kvm/x86.c | 1 +
  937. 3 files changed, 20 insertions(+)
  938.  
  939. diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
  940. index 24c0b2b..504f2cb 100644
  941. --- a/arch/x86/kvm/svm.c
  942. +++ b/arch/x86/kvm/svm.c
  943. @@ -1208,6 +1208,7 @@ static int avic_ga_log_notifier(u32 ga_tag)
  944. u32 vcpu_id = AVIC_GATAG_TO_VCPUID(ga_tag);
  945.  
  946. pr_debug("SVM: %s: vm_id=%#x, vcpu_id=%#x\n", __func__, vm_id, vcpu_id);
  947. + trace_kvm_avic_ga_log(vm_id, vcpu_id);
  948.  
  949. spin_lock_irqsave(&svm_vm_data_hash_lock, flags);
  950. hash_for_each_possible(svm_vm_data_hash, kvm_svm, hnode, vm_id) {
  951. diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
  952. index f194dd0..023de6c 100644
  953. --- a/arch/x86/kvm/trace.h
  954. +++ b/arch/x86/kvm/trace.h
  955. @@ -1367,6 +1367,24 @@
  956. __entry->vec)
  957. );
  958.  
  959. +TRACE_EVENT(kvm_avic_ga_log,
  960. + TP_PROTO(u32 vmid, u32 vcpuid),
  961. + TP_ARGS(vmid, vcpuid),
  962. +
  963. + TP_STRUCT__entry(
  964. + __field(u32, vmid)
  965. + __field(u32, vcpuid)
  966. + ),
  967. +
  968. + TP_fast_assign(
  969. + __entry->vmid = vmid;
  970. + __entry->vcpuid = vcpuid;
  971. + ),
  972. +
  973. + TP_printk("vmid=%u, vcpuid=%u",
  974. + __entry->vmid, __entry->vcpuid)
  975. +);
  976. +
  977. TRACE_EVENT(kvm_hv_timer_state,
  978. TP_PROTO(unsigned int vcpu_id, unsigned int hv_timer_in_use),
  979. TP_ARGS(vcpu_id, hv_timer_in_use),
  980. diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
  981. index 5de2006..ef38b82 100644
  982. --- a/arch/x86/kvm/x86.c
  983. +++ b/arch/x86/kvm/x86.c
  984. @@ -10514,4 +10514,5 @@ u64 kvm_spec_ctrl_valid_bits(struct kvm_vcpu *vcpu)
  985. EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pi_irte_update);
  986. EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_unaccelerated_access);
  987. EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_incomplete_ipi);
  988. +EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_ga_log);
  989. EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_apicv_update_request);
  990.  
  991. From 93fd9666c269877fffb74e14f52792d9c000c1f2 Mon Sep 17 00:00:00 2001
  992. From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
  993. Date: Fri, 21 Feb 2020 08:52:17 -0600
  994. Subject: kvm: x86: svm: Fix NULL pointer dereference when AVIC not enabled
  995.  
  996. Launching VM w/ AVIC disabled together with pass-through device
  997. results in NULL pointer dereference bug with the following call trace.
  998.  
  999. RIP: 0010:svm_refresh_apicv_exec_ctrl+0x17e/0x1a0 [kvm_amd]
  1000.  
  1001. Call Trace:
  1002. kvm_vcpu_update_apicv+0x44/0x60 [kvm]
  1003. kvm_arch_vcpu_ioctl_run+0x3f4/0x1c80 [kvm]
  1004. kvm_vcpu_ioctl+0x3d8/0x650 [kvm]
  1005. do_vfs_ioctl+0xaa/0x660
  1006. ? tomoyo_file_ioctl+0x19/0x20
  1007. ksys_ioctl+0x67/0x90
  1008. __x64_sys_ioctl+0x1a/0x20
  1009. do_syscall_64+0x57/0x190
  1010. entry_SYSCALL_64_after_hwframe+0x44/0xa9
  1011.  
  1012. Investigation shows that this is due to the uninitialized usage of
  1013. struct vapu_svm.ir_list in the svm_set_pi_irte_mode(), which is
  1014. called from svm_refresh_apicv_exec_ctrl().
  1015.  
  1016. The ir_list is initialized only if AVIC is enabled. So, fixes by
  1017. adding a check if AVIC is enabled in the svm_refresh_apicv_exec_ctrl().
  1018.  
  1019. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=206579
  1020. Fixes: 8937d762396d ("kvm: x86: svm: Add support to (de)activate posted interrupts.")
  1021. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
  1022. Tested-by: Alex Williamson <alex.williamson@redhat.com>
  1023. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  1024. ---
  1025. arch/x86/kvm/svm.c | 3 +++
  1026. 1 file changed, 3 insertions(+)
  1027.  
  1028. diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
  1029. index bef0ba35f121..a391b29138f0 100644
  1030. --- a/arch/x86/kvm/svm.c
  1031. +++ b/arch/x86/kvm/svm.c
  1032. @@ -5232,6 +5232,9 @@ static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
  1033. struct vmcb *vmcb = svm->vmcb;
  1034. bool activated = kvm_vcpu_apicv_active(vcpu);
  1035.  
  1036. + if (!avic)
  1037. + return;
  1038. +
  1039. if (activated) {
  1040. /**
  1041. * During AVIC temporary deactivation, guest could update
  1042. --
  1043. cgit 1.2-0.3.lf.el7
  1044.  
  1045. From b26a695a1d78cc415fe26d74d0463f5d887980de Mon Sep 17 00:00:00 2001
  1046. From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
  1047. Date: Thu, 14 Nov 2019 14:15:04 -0600
  1048. Subject: kvm: lapic: Introduce APICv update helper function
  1049.  
  1050. Re-factor code into a helper function for setting lapic parameters when
  1051. activate/deactivate APICv, and export the function for subsequent usage.
  1052.  
  1053. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
  1054. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  1055. ---
  1056. arch/x86/kvm/lapic.c | 22 +++++++++++++++++-----
  1057. arch/x86/kvm/lapic.h | 1 +
  1058. 2 files changed, 18 insertions(+), 5 deletions(-)
  1059.  
  1060. diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
  1061. index cce1e6b204c8..eafc631d305c 100644
  1062. --- a/arch/x86/kvm/lapic.c
  1063. +++ b/arch/x86/kvm/lapic.c
  1064. @@ -2187,6 +2187,21 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
  1065. pr_warn_once("APIC base relocation is unsupported by KVM");
  1066. }
  1067.  
  1068. +void kvm_apic_update_apicv(struct kvm_vcpu *vcpu)
  1069. +{
  1070. + struct kvm_lapic *apic = vcpu->arch.apic;
  1071. +
  1072. + if (vcpu->arch.apicv_active) {
  1073. + /* irr_pending is always true when apicv is activated. */
  1074. + apic->irr_pending = true;
  1075. + apic->isr_count = 1;
  1076. + } else {
  1077. + apic->irr_pending = (apic_search_irr(apic) != -1);
  1078. + apic->isr_count = count_vectors(apic->regs + APIC_ISR);
  1079. + }
  1080. +}
  1081. +EXPORT_SYMBOL_GPL(kvm_apic_update_apicv);
  1082. +
  1083. void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
  1084. {
  1085. struct kvm_lapic *apic = vcpu->arch.apic;
  1086. @@ -2229,8 +2244,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
  1087. kvm_lapic_set_reg(apic, APIC_ISR + 0x10 * i, 0);
  1088. kvm_lapic_set_reg(apic, APIC_TMR + 0x10 * i, 0);
  1089. }
  1090. - apic->irr_pending = vcpu->arch.apicv_active;
  1091. - apic->isr_count = vcpu->arch.apicv_active ? 1 : 0;
  1092. + kvm_apic_update_apicv(vcpu);
  1093. apic->highest_isr_cache = -1;
  1094. update_divide_count(apic);
  1095. atomic_set(&apic->lapic_timer.pending, 0);
  1096. @@ -2487,9 +2501,7 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
  1097. apic_manage_nmi_watchdog(apic, kvm_lapic_get_reg(apic, APIC_LVT0));
  1098. update_divide_count(apic);
  1099. start_apic_timer(apic);
  1100. - apic->irr_pending = true;
  1101. - apic->isr_count = vcpu->arch.apicv_active ?
  1102. - 1 : count_vectors(apic->regs + APIC_ISR);
  1103. + kvm_apic_update_apicv(vcpu);
  1104. apic->highest_isr_cache = -1;
  1105. if (vcpu->arch.apicv_active) {
  1106. kvm_x86_ops->apicv_post_state_restore(vcpu);
  1107. diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
  1108. index ec730ce7a344..ec6fbfe325cf 100644
  1109. --- a/arch/x86/kvm/lapic.h
  1110. +++ b/arch/x86/kvm/lapic.h
  1111. @@ -91,6 +91,7 @@ void kvm_apic_update_ppr(struct kvm_vcpu *vcpu);
  1112. int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq,
  1113. struct dest_map *dest_map);
  1114. int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type);
  1115. +void kvm_apic_update_apicv(struct kvm_vcpu *vcpu);
  1116.  
  1117. bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
  1118. struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map);
  1119. --
  1120. cgit 1.2-0.3.lf.el7
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement