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

Merge tag 'kvm-arm64/for-3.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into kvm-next

A handful of fixes for KVM/arm64:

- A couple a basic fixes for running BE guests on a LE host
- A performance improvement for overcommitted VMs (same as the equivalent
patch for ARM)

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Conflicts:
arch/arm/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_emulate.h

+201 -18
+46
arch/arm/include/asm/kvm_emulate.h
··· 162 162 return vcpu->arch.cp15[c0_MPIDR]; 163 163 } 164 164 165 + static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu) 166 + { 167 + *vcpu_cpsr(vcpu) |= PSR_E_BIT; 168 + } 169 + 170 + static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu) 171 + { 172 + return !!(*vcpu_cpsr(vcpu) & PSR_E_BIT); 173 + } 174 + 175 + static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu, 176 + unsigned long data, 177 + unsigned int len) 178 + { 179 + if (kvm_vcpu_is_be(vcpu)) { 180 + switch (len) { 181 + case 1: 182 + return data & 0xff; 183 + case 2: 184 + return be16_to_cpu(data & 0xffff); 185 + default: 186 + return be32_to_cpu(data); 187 + } 188 + } 189 + 190 + return data; /* Leave LE untouched */ 191 + } 192 + 193 + static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu, 194 + unsigned long data, 195 + unsigned int len) 196 + { 197 + if (kvm_vcpu_is_be(vcpu)) { 198 + switch (len) { 199 + case 1: 200 + return data & 0xff; 201 + case 2: 202 + return cpu_to_be16(data & 0xffff); 203 + default: 204 + return cpu_to_be32(data); 205 + } 206 + } 207 + 208 + return data; /* Leave LE untouched */ 209 + } 210 + 165 211 #endif /* __ARM_KVM_EMULATE_H__ */
+75 -11
arch/arm/kvm/mmio.c
··· 23 23 24 24 #include "trace.h" 25 25 26 + static void mmio_write_buf(char *buf, unsigned int len, unsigned long data) 27 + { 28 + void *datap = NULL; 29 + union { 30 + u8 byte; 31 + u16 hword; 32 + u32 word; 33 + u64 dword; 34 + } tmp; 35 + 36 + switch (len) { 37 + case 1: 38 + tmp.byte = data; 39 + datap = &tmp.byte; 40 + break; 41 + case 2: 42 + tmp.hword = data; 43 + datap = &tmp.hword; 44 + break; 45 + case 4: 46 + tmp.word = data; 47 + datap = &tmp.word; 48 + break; 49 + case 8: 50 + tmp.dword = data; 51 + datap = &tmp.dword; 52 + break; 53 + } 54 + 55 + memcpy(buf, datap, len); 56 + } 57 + 58 + static unsigned long mmio_read_buf(char *buf, unsigned int len) 59 + { 60 + unsigned long data = 0; 61 + union { 62 + u16 hword; 63 + u32 word; 64 + u64 dword; 65 + } tmp; 66 + 67 + switch (len) { 68 + case 1: 69 + data = buf[0]; 70 + break; 71 + case 2: 72 + memcpy(&tmp.hword, buf, len); 73 + data = tmp.hword; 74 + break; 75 + case 4: 76 + memcpy(&tmp.word, buf, len); 77 + data = tmp.word; 78 + break; 79 + case 8: 80 + memcpy(&tmp.dword, buf, len); 81 + data = tmp.dword; 82 + break; 83 + } 84 + 85 + return data; 86 + } 87 + 26 88 /** 27 89 * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation 28 90 * @vcpu: The VCPU pointer ··· 95 33 */ 96 34 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) 97 35 { 98 - unsigned long *dest; 36 + unsigned long data; 99 37 unsigned int len; 100 38 int mask; 101 39 102 40 if (!run->mmio.is_write) { 103 - dest = vcpu_reg(vcpu, vcpu->arch.mmio_decode.rt); 104 - *dest = 0; 105 - 106 41 len = run->mmio.len; 107 42 if (len > sizeof(unsigned long)) 108 43 return -EINVAL; 109 44 110 - memcpy(dest, run->mmio.data, len); 111 - 112 - trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr, 113 - *((u64 *)run->mmio.data)); 45 + data = mmio_read_buf(run->mmio.data, len); 114 46 115 47 if (vcpu->arch.mmio_decode.sign_extend && 116 48 len < sizeof(unsigned long)) { 117 49 mask = 1U << ((len * 8) - 1); 118 - *dest = (*dest ^ mask) - mask; 50 + data = (data ^ mask) - mask; 119 51 } 52 + 53 + trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr, 54 + data); 55 + data = vcpu_data_host_to_guest(vcpu, data, len); 56 + *vcpu_reg(vcpu, vcpu->arch.mmio_decode.rt) = data; 120 57 } 121 58 122 59 return 0; ··· 166 105 phys_addr_t fault_ipa) 167 106 { 168 107 struct kvm_exit_mmio mmio; 108 + unsigned long data; 169 109 unsigned long rt; 170 110 int ret; 171 111 ··· 187 125 } 188 126 189 127 rt = vcpu->arch.mmio_decode.rt; 128 + data = vcpu_data_guest_to_host(vcpu, *vcpu_reg(vcpu, rt), mmio.len); 129 + 190 130 trace_kvm_mmio((mmio.is_write) ? KVM_TRACE_MMIO_WRITE : 191 131 KVM_TRACE_MMIO_READ_UNSATISFIED, 192 132 mmio.len, fault_ipa, 193 - (mmio.is_write) ? *vcpu_reg(vcpu, rt) : 0); 133 + (mmio.is_write) ? data : 0); 194 134 195 135 if (mmio.is_write) 196 - memcpy(mmio.data, vcpu_reg(vcpu, rt), mmio.len); 136 + mmio_write_buf(mmio.data, mmio.len, data); 197 137 198 138 if (vgic_handle_mmio(vcpu, run, &mmio)) 199 139 return 1;
+4
arch/arm/kvm/psci.c
··· 71 71 vcpu_set_thumb(vcpu); 72 72 } 73 73 74 + /* Propagate caller endianness */ 75 + if (kvm_vcpu_is_be(source_vcpu)) 76 + kvm_vcpu_set_be(vcpu); 77 + 74 78 *vcpu_pc(vcpu) = target_pc; 75 79 vcpu->arch.pause = false; 76 80 smp_mb(); /* Make sure the above is visible */
+6 -2
arch/arm64/include/asm/kvm_arm.h
··· 63 63 * TAC: Trap ACTLR 64 64 * TSC: Trap SMC 65 65 * TSW: Trap cache operations by set/way 66 + * TWE: Trap WFE 66 67 * TWI: Trap WFI 67 68 * TIDCP: Trap L2CTLR/L2ECTLR 68 69 * BSU_IS: Upgrade barriers to the inner shareable domain ··· 73 72 * FMO: Override CPSR.F and enable signaling with VF 74 73 * SWIO: Turn set/way invalidates into set/way clean+invalidate 75 74 */ 76 - #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWI | HCR_VM | HCR_BSU_IS | \ 77 - HCR_FB | HCR_TAC | HCR_AMO | HCR_IMO | HCR_FMO | \ 75 + #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \ 76 + HCR_BSU_IS | HCR_FB | HCR_TAC | \ 77 + HCR_AMO | HCR_IMO | HCR_FMO | \ 78 78 HCR_SWIO | HCR_TIDCP | HCR_RW) 79 79 #define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF) 80 80 ··· 243 241 #define ESR_EL2_EC_BRK64 (0x3C) 244 242 245 243 #define ESR_EL2_EC_xABT_xFSR_EXTABT 0x10 244 + 245 + #define ESR_EL2_EC_WFI_ISS_WFE (1 << 0) 246 246 247 247 #endif /* __ARM64_KVM_ARM_H__ */
+56
arch/arm64/include/asm/kvm_emulate.h
··· 182 182 return vcpu_sys_reg(vcpu, MPIDR_EL1); 183 183 } 184 184 185 + static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu) 186 + { 187 + if (vcpu_mode_is_32bit(vcpu)) 188 + *vcpu_cpsr(vcpu) |= COMPAT_PSR_E_BIT; 189 + else 190 + vcpu_sys_reg(vcpu, SCTLR_EL1) |= (1 << 25); 191 + } 192 + 193 + static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu) 194 + { 195 + if (vcpu_mode_is_32bit(vcpu)) 196 + return !!(*vcpu_cpsr(vcpu) & COMPAT_PSR_E_BIT); 197 + 198 + return !!(vcpu_sys_reg(vcpu, SCTLR_EL1) & (1 << 25)); 199 + } 200 + 201 + static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu, 202 + unsigned long data, 203 + unsigned int len) 204 + { 205 + if (kvm_vcpu_is_be(vcpu)) { 206 + switch (len) { 207 + case 1: 208 + return data & 0xff; 209 + case 2: 210 + return be16_to_cpu(data & 0xffff); 211 + case 4: 212 + return be32_to_cpu(data & 0xffffffff); 213 + default: 214 + return be64_to_cpu(data); 215 + } 216 + } 217 + 218 + return data; /* Leave LE untouched */ 219 + } 220 + 221 + static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu, 222 + unsigned long data, 223 + unsigned int len) 224 + { 225 + if (kvm_vcpu_is_be(vcpu)) { 226 + switch (len) { 227 + case 1: 228 + return data & 0xff; 229 + case 2: 230 + return cpu_to_be16(data & 0xffff); 231 + case 4: 232 + return cpu_to_be32(data & 0xffffffff); 233 + default: 234 + return cpu_to_be64(data); 235 + } 236 + } 237 + 238 + return data; /* Leave LE untouched */ 239 + } 240 + 185 241 #endif /* __ARM64_KVM_EMULATE_H__ */
+1
arch/arm64/kvm/Kconfig
··· 21 21 select MMU_NOTIFIER 22 22 select PREEMPT_NOTIFIERS 23 23 select ANON_INODES 24 + select HAVE_KVM_CPU_RELAX_INTERCEPT 24 25 select KVM_MMIO 25 26 select KVM_ARM_HOST 26 27 select KVM_ARM_VGIC
+13 -5
arch/arm64/kvm/handle_exit.c
··· 47 47 } 48 48 49 49 /** 50 - * kvm_handle_wfi - handle a wait-for-interrupts instruction executed by a guest 50 + * kvm_handle_wfx - handle a wait-for-interrupts or wait-for-event 51 + * instruction executed by a guest 52 + * 51 53 * @vcpu: the vcpu pointer 52 54 * 53 - * Simply call kvm_vcpu_block(), which will halt execution of 55 + * WFE: Yield the CPU and come back to this vcpu when the scheduler 56 + * decides to. 57 + * WFI: Simply call kvm_vcpu_block(), which will halt execution of 54 58 * world-switches and schedule other host processes until there is an 55 59 * incoming IRQ or FIQ to the VM. 56 60 */ 57 - static int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run) 61 + static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run) 58 62 { 59 - kvm_vcpu_block(vcpu); 63 + if (kvm_vcpu_get_hsr(vcpu) & ESR_EL2_EC_WFI_ISS_WFE) 64 + kvm_vcpu_on_spin(vcpu); 65 + else 66 + kvm_vcpu_block(vcpu); 67 + 60 68 return 1; 61 69 } 62 70 63 71 static exit_handle_fn arm_exit_handlers[] = { 64 - [ESR_EL2_EC_WFI] = kvm_handle_wfi, 72 + [ESR_EL2_EC_WFI] = kvm_handle_wfx, 65 73 [ESR_EL2_EC_CP15_32] = kvm_handle_cp15_32, 66 74 [ESR_EL2_EC_CP15_64] = kvm_handle_cp15_64, 67 75 [ESR_EL2_EC_CP14_MR] = kvm_handle_cp14_access,