Unverified Commit 12359685 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!4807 [OLK-6.6] Intel: backport KVM LAM from v6.8 to OLK-6.6

Merge Pull Request from: @zhiquan1-li 
 
**KVM x86 support for virtualizing Linear Address Masking (LAM)** 

Add KVM support for Linear Address Masking (LAM).  LAM tweaks the canonicality
checks for most virtual address usage in 64-bit mode, such that only the most
significant bit of the untranslated address bits must match the polarity of the
last translated address bit.  This allows software to use ignored, untranslated
address bits for metadata, e.g. to efficiently tag pointers for address
sanitization.

**Intel-Kernel Issue**
[#I94GWL](https://gitee.com/openeuler/intel-kernel/issues/I94GWL)

**About the patche**
The content of the patches are the same as upstream.
There are 12 patches, this is the commit list from upstream:
```
183bdd161c2b KVM: x86: Use KVM-governed feature framework to track "LAM enabled"
703d794cb8cb KVM: x86: Advertise and enable LAM (user and supervisor)
3098e6eca88e KVM: x86: Virtualize LAM for user pointer
93d1c9f498a7 KVM: x86: Virtualize LAM for supervisor pointer
b39bd520a60c KVM: x86: Untag addresses for LAM emulation where applicable
37a41847b770 KVM: x86: Introduce get_untagged_addr() in kvm_x86_ops and call it in emulator
9c8021d4ae85 KVM: x86: Remove kvm_vcpu_is_illegal_gpa()
2c49db455ee2 KVM: x86: Add & use kvm_vcpu_is_legal_cr3() to check CR3's legality
a130066f7400 KVM: x86/mmu: Drop non-PA bits when getting GFN for guest's PGD
538ac9a92d66 KVM: x86: Add X86EMUL_F_INVLPG and pass it in em_invlpg()
3963c52df422 KVM: x86: Add an emulation flag for implicit system access
7b0dd9430cf0 KVM: x86: Consolidate flags for __linearize()
```

**Test**
Test on SRF Platform
- Built and run the kernel successfully
- Kernel kselftest - LAM in host: PASS
- Kernel kselftest - LAM in guest: PASS
- kvm-unit-tests in host: PASS
- kvm-unit-tests in guest: PASS

**Known Issue**
N/A

**Default config change**
N/A

**References** 
[[GIT PULL] KVM: x86: LAM support for 6.8](https://lore.kernel.org/kvm/20240104193303.3175844-4-seanjc@google.com/) 
 
Link:https://gitee.com/openeuler/kernel/pulls/4807

 

Reviewed-by: default avatarJason Zeng <jason.zeng@intel.com>
Reviewed-by: default avatarAichun Shi <aichun.shi@intel.com>
Reviewed-by: default avatarKevin Zhu <zhukeqian1@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents 3016126e e3563584
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ KVM_X86_OP(msr_filter_changed)
KVM_X86_OP(complete_emulated_msr)
KVM_X86_OP(vcpu_deliver_sipi_vector)
KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons);
KVM_X86_OP_OPTIONAL(get_untagged_addr)

#undef KVM_X86_OP
#undef KVM_X86_OP_OPTIONAL
+4 −1
Original line number Diff line number Diff line
@@ -125,7 +125,8 @@
			  | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR | X86_CR4_PCIDE \
			  | X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_FSGSBASE \
			  | X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_VMXE \
			  | X86_CR4_SMAP | X86_CR4_PKE | X86_CR4_UMIP))
			  | X86_CR4_SMAP | X86_CR4_PKE | X86_CR4_UMIP \
			  | X86_CR4_LAM_SUP))

#define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)

@@ -1767,6 +1768,8 @@ struct kvm_x86_ops {
	 * Returns vCPU specific APICv inhibit reasons
	 */
	unsigned long (*vcpu_get_apicv_inhibit_reasons)(struct kvm_vcpu *vcpu);

	gva_t (*get_untagged_addr)(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags);
};

struct kvm_x86_nested_ops {
+1 −1
Original line number Diff line number Diff line
@@ -669,7 +669,7 @@ void kvm_set_cpu_caps(void)
	kvm_cpu_cap_mask(CPUID_7_1_EAX,
		F(AVX_VNNI) | F(AVX512_BF16) | F(CMPCCXADD) |
		F(FZRM) | F(FSRS) | F(FSRC) |
		F(AMX_FP16) | F(AVX_IFMA)
		F(AMX_FP16) | F(AVX_IFMA) | F(LAM)
	);

	kvm_cpu_cap_init_kvm_defined(CPUID_7_1_EDX,
+8 −5
Original line number Diff line number Diff line
@@ -47,11 +47,6 @@ static inline bool kvm_vcpu_is_legal_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
	return !(gpa & vcpu->arch.reserved_gpa_bits);
}

static inline bool kvm_vcpu_is_illegal_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
{
	return !kvm_vcpu_is_legal_gpa(vcpu, gpa);
}

static inline bool kvm_vcpu_is_legal_aligned_gpa(struct kvm_vcpu *vcpu,
						 gpa_t gpa, gpa_t alignment)
{
@@ -278,4 +273,12 @@ static __always_inline bool guest_can_use(struct kvm_vcpu *vcpu,
			vcpu->arch.governed_features.enabled);
}

static inline bool kvm_vcpu_is_legal_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
{
	if (guest_can_use(vcpu, X86_FEATURE_LAM))
		cr3 &= ~(X86_CR3_LAM_U48 | X86_CR3_LAM_U57);

	return kvm_vcpu_is_legal_gpa(vcpu, cr3);
}

#endif
+15 −12
Original line number Diff line number Diff line
@@ -687,8 +687,8 @@ static unsigned insn_alignment(struct x86_emulate_ctxt *ctxt, unsigned size)
static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
				       struct segmented_address addr,
				       unsigned *max_size, unsigned size,
				       bool write, bool fetch,
				       enum x86emul_mode mode, ulong *linear)
				       enum x86emul_mode mode, ulong *linear,
				       unsigned int flags)
{
	struct desc_struct desc;
	bool usable;
@@ -701,7 +701,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
	*max_size = 0;
	switch (mode) {
	case X86EMUL_MODE_PROT64:
		*linear = la;
		*linear = la = ctxt->ops->get_untagged_addr(ctxt, la, flags);
		va_bits = ctxt_virt_addr_bits(ctxt);
		if (!__is_canonical_address(la, va_bits))
			goto bad;
@@ -717,11 +717,11 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
		if (!usable)
			goto bad;
		/* code segment in protected mode or read-only data segment */
		if ((((ctxt->mode != X86EMUL_MODE_REAL) && (desc.type & 8))
					|| !(desc.type & 2)) && write)
		if ((((ctxt->mode != X86EMUL_MODE_REAL) && (desc.type & 8)) || !(desc.type & 2)) &&
		    (flags & X86EMUL_F_WRITE))
			goto bad;
		/* unreadable code segment */
		if (!fetch && (desc.type & 8) && !(desc.type & 2))
		if (!(flags & X86EMUL_F_FETCH) && (desc.type & 8) && !(desc.type & 2))
			goto bad;
		lim = desc_limit_scaled(&desc);
		if (!(desc.type & 8) && (desc.type & 4)) {
@@ -757,8 +757,8 @@ static int linearize(struct x86_emulate_ctxt *ctxt,
		     ulong *linear)
{
	unsigned max_size;
	return __linearize(ctxt, addr, &max_size, size, write, false,
			   ctxt->mode, linear);
	return __linearize(ctxt, addr, &max_size, size, ctxt->mode, linear,
			   write ? X86EMUL_F_WRITE : 0);
}

static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst)
@@ -771,7 +771,8 @@ static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst)

	if (ctxt->op_bytes != sizeof(unsigned long))
		addr.ea = dst & ((1UL << (ctxt->op_bytes << 3)) - 1);
	rc = __linearize(ctxt, addr, &max_size, 1, false, true, ctxt->mode, &linear);
	rc = __linearize(ctxt, addr, &max_size, 1, ctxt->mode, &linear,
			 X86EMUL_F_FETCH);
	if (rc == X86EMUL_CONTINUE)
		ctxt->_eip = addr.ea;
	return rc;
@@ -907,8 +908,8 @@ static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
	 * boundary check itself.  Instead, we use max_size to check
	 * against op_size.
	 */
	rc = __linearize(ctxt, addr, &max_size, 0, false, true, ctxt->mode,
			 &linear);
	rc = __linearize(ctxt, addr, &max_size, 0, ctxt->mode, &linear,
			 X86EMUL_F_FETCH);
	if (unlikely(rc != X86EMUL_CONTINUE))
		return rc;

@@ -3439,8 +3440,10 @@ static int em_invlpg(struct x86_emulate_ctxt *ctxt)
{
	int rc;
	ulong linear;
	unsigned int max_size;

	rc = linearize(ctxt, ctxt->src.addr.mem, 1, false, &linear);
	rc = __linearize(ctxt, ctxt->src.addr.mem, &max_size, 1, ctxt->mode,
			 &linear, X86EMUL_F_INVLPG);
	if (rc == X86EMUL_CONTINUE)
		ctxt->ops->invlpg(ctxt, linear);
	/* Disable writeback. */
Loading