Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: PPC: Book3S HV: XIVE: Add support for automatic save-restore

On P10, the feature doing an automatic "save & restore" of a VCPU
interrupt context is set by default in OPAL. When a VP context is
pulled out, the state of the interrupt registers are saved by the XIVE
interrupt controller under the internal NVP structure representing the
VP. This saves a costly store/load in guest entries and exits.

If OPAL advertises the "save & restore" feature in the device tree,
it should also have set the 'H' bit in the CAM line. Check that when
vCPUs are connected to their ICP in KVM before going any further.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210720134209.256133-3-clg@kaod.org

authored by

Cédric Le Goater and committed by
Michael Ellerman
f5af0a97 b68c6646

+57 -2
+3
arch/powerpc/include/asm/xive-regs.h
··· 80 80 #define TM_QW0W2_VU PPC_BIT32(0) 81 81 #define TM_QW0W2_LOGIC_SERV PPC_BITMASK32(1,31) // XX 2,31 ? 82 82 #define TM_QW1W2_VO PPC_BIT32(0) 83 + #define TM_QW1W2_HO PPC_BIT32(1) /* P10 XIVE2 */ 83 84 #define TM_QW1W2_OS_CAM PPC_BITMASK32(8,31) 84 85 #define TM_QW2W2_VP PPC_BIT32(0) 86 + #define TM_QW2W2_HP PPC_BIT32(1) /* P10 XIVE2 */ 85 87 #define TM_QW2W2_POOL_CAM PPC_BITMASK32(8,31) 86 88 #define TM_QW3W2_VT PPC_BIT32(0) 89 + #define TM_QW3W2_HT PPC_BIT32(1) /* P10 XIVE2 */ 87 90 #define TM_QW3W2_LP PPC_BIT32(6) 88 91 #define TM_QW3W2_LE PPC_BIT32(7) 89 92 #define TM_QW3W2_T PPC_BIT32(31)
+1
arch/powerpc/include/asm/xive.h
··· 126 126 int xive_native_disable_vp(u32 vp_id); 127 127 int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id); 128 128 bool xive_native_has_single_escalation(void); 129 + bool xive_native_has_save_restore(void); 129 130 130 131 int xive_native_get_queue_info(u32 vp_id, uint32_t prio, 131 132 u64 *out_qpage,
+32 -2
arch/powerpc/kvm/book3s_xive.c
··· 59 59 */ 60 60 #define XIVE_Q_GAP 2 61 61 62 + static bool kvmppc_xive_vcpu_has_save_restore(struct kvm_vcpu *vcpu) 63 + { 64 + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; 65 + 66 + /* Check enablement at VP level */ 67 + return xc->vp_cam & TM_QW1W2_HO; 68 + } 69 + 70 + bool kvmppc_xive_check_save_restore(struct kvm_vcpu *vcpu) 71 + { 72 + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; 73 + struct kvmppc_xive *xive = xc->xive; 74 + 75 + if (xive->flags & KVMPPC_XIVE_FLAG_SAVE_RESTORE) 76 + return kvmppc_xive_vcpu_has_save_restore(vcpu); 77 + 78 + return true; 79 + } 80 + 62 81 /* 63 82 * Push a vcpu's context to the XIVE on guest entry. 64 83 * This assumes we are in virtual mode (MMU on) ··· 96 77 return; 97 78 98 79 eieio(); 99 - __raw_writeq(vcpu->arch.xive_saved_state.w01, tima + TM_QW1_OS); 80 + if (!kvmppc_xive_vcpu_has_save_restore(vcpu)) 81 + __raw_writeq(vcpu->arch.xive_saved_state.w01, tima + TM_QW1_OS); 100 82 __raw_writel(vcpu->arch.xive_cam_word, tima + TM_QW1_OS + TM_WORD2); 101 83 vcpu->arch.xive_pushed = 1; 102 84 eieio(); ··· 169 149 /* First load to pull the context, we ignore the value */ 170 150 __raw_readl(tima + TM_SPC_PULL_OS_CTX); 171 151 /* Second load to recover the context state (Words 0 and 1) */ 172 - vcpu->arch.xive_saved_state.w01 = __raw_readq(tima + TM_QW1_OS); 152 + if (!kvmppc_xive_vcpu_has_save_restore(vcpu)) 153 + vcpu->arch.xive_saved_state.w01 = __raw_readq(tima + TM_QW1_OS); 173 154 174 155 /* Fixup some of the state for the next load */ 175 156 vcpu->arch.xive_saved_state.lsmfb = 0; ··· 1340 1319 if (r) 1341 1320 goto bail; 1342 1321 1322 + if (!kvmppc_xive_check_save_restore(vcpu)) { 1323 + pr_err("inconsistent save-restore setup for VCPU %d\n", cpu); 1324 + r = -EIO; 1325 + goto bail; 1326 + } 1327 + 1343 1328 /* Configure VCPU fields for use by assembly push/pull */ 1344 1329 vcpu->arch.xive_saved_state.w01 = cpu_to_be64(0xff000000); 1345 1330 vcpu->arch.xive_cam_word = cpu_to_be32(xc->vp_cam | TM_QW1W2_VO); ··· 2164 2137 2165 2138 if (xive_native_has_single_escalation()) 2166 2139 xive->flags |= KVMPPC_XIVE_FLAG_SINGLE_ESCALATION; 2140 + 2141 + if (xive_native_has_save_restore()) 2142 + xive->flags |= KVMPPC_XIVE_FLAG_SAVE_RESTORE; 2167 2143 2168 2144 kvm->arch.xive = xive; 2169 2145 return 0;
+2
arch/powerpc/kvm/book3s_xive.h
··· 98 98 }; 99 99 100 100 #define KVMPPC_XIVE_FLAG_SINGLE_ESCALATION 0x1 101 + #define KVMPPC_XIVE_FLAG_SAVE_RESTORE 0x2 101 102 102 103 struct kvmppc_xive { 103 104 struct kvm *kvm; ··· 310 309 struct kvmppc_xive_vcpu *xc, int irq); 311 310 int kvmppc_xive_compute_vp_id(struct kvmppc_xive *xive, u32 cpu, u32 *vp); 312 311 int kvmppc_xive_set_nr_servers(struct kvmppc_xive *xive, u64 addr); 312 + bool kvmppc_xive_check_save_restore(struct kvm_vcpu *vcpu); 313 313 314 314 static inline bool kvmppc_xive_has_single_escalation(struct kvmppc_xive *xive) 315 315 {
+9
arch/powerpc/kvm/book3s_xive_native.c
··· 168 168 goto bail; 169 169 } 170 170 171 + if (!kvmppc_xive_check_save_restore(vcpu)) { 172 + pr_err("inconsistent save-restore setup for VCPU %d\n", server_num); 173 + rc = -EIO; 174 + goto bail; 175 + } 176 + 171 177 /* 172 178 * Enable the VP first as the single escalation mode will 173 179 * affect escalation interrupts numbering ··· 1119 1113 1120 1114 if (xive_native_has_single_escalation()) 1121 1115 xive->flags |= KVMPPC_XIVE_FLAG_SINGLE_ESCALATION; 1116 + 1117 + if (xive_native_has_save_restore()) 1118 + xive->flags |= KVMPPC_XIVE_FLAG_SAVE_RESTORE; 1122 1119 1123 1120 xive->ops = &kvmppc_xive_native_ops; 1124 1121
+10
arch/powerpc/sysdev/xive/native.c
··· 41 41 static u32 xive_pool_vps = XIVE_INVALID_VP; 42 42 static struct kmem_cache *xive_provision_cache; 43 43 static bool xive_has_single_esc; 44 + static bool xive_has_save_restore; 44 45 45 46 int xive_native_populate_irq_data(u32 hw_irq, struct xive_irq_data *data) 46 47 { ··· 589 588 if (of_get_property(np, "single-escalation-support", NULL) != NULL) 590 589 xive_has_single_esc = true; 591 590 591 + if (of_get_property(np, "vp-save-restore", NULL)) 592 + xive_has_save_restore = true; 593 + 592 594 /* Configure Thread Management areas for KVM */ 593 595 for_each_possible_cpu(cpu) 594 596 kvmppc_set_xive_tima(cpu, r.start, tima); ··· 755 751 return xive_has_single_esc; 756 752 } 757 753 EXPORT_SYMBOL_GPL(xive_native_has_single_escalation); 754 + 755 + bool xive_native_has_save_restore(void) 756 + { 757 + return xive_has_save_restore; 758 + } 759 + EXPORT_SYMBOL_GPL(xive_native_has_save_restore); 758 760 759 761 int xive_native_get_queue_info(u32 vp_id, u32 prio, 760 762 u64 *out_qpage,