mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	KVM: arm64: uapi: Add kvm_debug_exit_arch.hsr_high
When userspace is debugging a VM, the kvm_debug_exit_arch part of the kvm_run struct contains arm64 specific debug information: the ESR_EL2 value, encoded in the field "hsr", and the address of the instruction that caused the exception, encoded in the field "far". Linux has moved to treating ESR_EL2 as a 64-bit register, but unfortunately kvm_debug_exit_arch.hsr cannot be changed because that would change the memory layout of the struct on big endian machines: Current layout: | Layout with "hsr" extended to 64 bits: | offset 0: ESR_EL2[31:0] (hsr) | offset 0: ESR_EL2[61:32] (hsr[61:32]) offset 4: padding | offset 4: ESR_EL2[31:0] (hsr[31:0]) offset 8: FAR_EL2[61:0] (far) | offset 8: FAR_EL2[61:0] (far) which breaks existing code. The padding is inserted by the compiler because the "far" field must be aligned to 8 bytes (each field must be naturally aligned - aapcs64 [1], page 18), and the struct itself must be aligned to 8 bytes (the struct must be aligned to the maximum alignment of its fields - aapcs64, page 18), which means that "hsr" must be aligned to 8 bytes as it is the first field in the struct. To avoid changing the struct size and layout for the existing fields, add a new field, "hsr_high", which replaces the existing padding. "hsr_high" will be used to hold the ESR_EL2[61:32] bits of the register. The memory layout, both on big and little endian machine, becomes: offset 0: ESR_EL2[31:0] (hsr) offset 4: ESR_EL2[61:32] (hsr_high) offset 8: FAR_EL2[61:0] (far) The padding that the compiler inserts for the current struct layout is unitialized. To prevent an updated userspace running on an old kernel mistaking the padding for a valid "hsr_high" value, add a new flag, KVM_DEBUG_ARCH_HSR_HIGH_VALID, to kvm_run->flags to let userspace know that "hsr_high" holds a valid ESR_EL2[61:32] value. [1] https://github.com/ARM-software/abi-aa/releases/download/2021Q3/aapcs64.pdf Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> Reviewed-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20220425114444.368693-6-alexandru.elisei@arm.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
		
							parent
							
								
									0b12620fdd
								
							
						
					
					
						commit
						18f3976fdb
					
				
					 4 changed files with 7 additions and 0 deletions
				
			
		| 
						 | 
					@ -5713,6 +5713,8 @@ affect the device's behavior. Current defined flags::
 | 
				
			||||||
  #define KVM_RUN_X86_SMM     (1 << 0)
 | 
					  #define KVM_RUN_X86_SMM     (1 << 0)
 | 
				
			||||||
  /* x86, set if bus lock detected in VM */
 | 
					  /* x86, set if bus lock detected in VM */
 | 
				
			||||||
  #define KVM_RUN_BUS_LOCK    (1 << 1)
 | 
					  #define KVM_RUN_BUS_LOCK    (1 << 1)
 | 
				
			||||||
 | 
					  /* arm64, set for KVM_EXIT_DEBUG */
 | 
				
			||||||
 | 
					  #define KVM_DEBUG_ARCH_HSR_HIGH_VALID  (1 << 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
::
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,8 +139,10 @@ struct kvm_guest_debug_arch {
 | 
				
			||||||
	__u64 dbg_wvr[KVM_ARM_MAX_DBG_REGS];
 | 
						__u64 dbg_wvr[KVM_ARM_MAX_DBG_REGS];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KVM_DEBUG_ARCH_HSR_HIGH_VALID	(1 << 0)
 | 
				
			||||||
struct kvm_debug_exit_arch {
 | 
					struct kvm_debug_exit_arch {
 | 
				
			||||||
	__u32 hsr;
 | 
						__u32 hsr;
 | 
				
			||||||
 | 
						__u32 hsr_high;	/* ESR_EL2[61:32] */
 | 
				
			||||||
	__u64 far;	/* used for watchpoints */
 | 
						__u64 far;	/* used for watchpoints */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -783,6 +783,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = 1;
 | 
						ret = 1;
 | 
				
			||||||
	run->exit_reason = KVM_EXIT_UNKNOWN;
 | 
						run->exit_reason = KVM_EXIT_UNKNOWN;
 | 
				
			||||||
 | 
						run->flags = 0;
 | 
				
			||||||
	while (ret > 0) {
 | 
						while (ret > 0) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Check conditions before entering the guest
 | 
							 * Check conditions before entering the guest
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,6 +121,8 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	run->exit_reason = KVM_EXIT_DEBUG;
 | 
						run->exit_reason = KVM_EXIT_DEBUG;
 | 
				
			||||||
	run->debug.arch.hsr = lower_32_bits(esr);
 | 
						run->debug.arch.hsr = lower_32_bits(esr);
 | 
				
			||||||
 | 
						run->debug.arch.hsr_high = upper_32_bits(esr);
 | 
				
			||||||
 | 
						run->flags = KVM_DEBUG_ARCH_HSR_HIGH_VALID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ESR_ELx_EC(esr) == ESR_ELx_EC_WATCHPT_LOW)
 | 
						if (ESR_ELx_EC(esr) == ESR_ELx_EC_WATCHPT_LOW)
 | 
				
			||||||
		run->debug.arch.far = vcpu->arch.fault.far_el2;
 | 
							run->debug.arch.far = vcpu->arch.fault.far_el2;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue