Re: [PATCH Part2 v5 04/45] x86/sev: Add RMP entry lookup helpers
From: Borislav Petkov <bp@alien8.de>
Date: 2021-09-24 09:50:07
Also in:
kvm, linux-coco, linux-mm, lkml
On Fri, Aug 20, 2021 at 10:58:37AM -0500, Brijesh Singh wrote:
+struct __packed rmpentry {
+ union {
+ struct {
+ u64 assigned : 1,
+ pagesize : 1,
+ immutable : 1,
+ rsvd1 : 9,
+ gpa : 39,
+ asid : 10,
+ vmsa : 1,
+ validated : 1,
+ rsvd2 : 1;
+ } info;
+ u64 low;
+ };
+ u64 high;
+};__packed goes at the end of the struct definition.
+ +#define rmpentry_assigned(x) ((x)->info.assigned) +#define rmpentry_pagesize(x) ((x)->info.pagesize)
Inline functions pls so that you can get typechecking too.
quoted hunk ↗ jump to hunk
#define RMPADJUST_VMSA_PAGE_BIT BIT(16)diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c index 7936c8139c74..f383d2a89263 100644 --- a/arch/x86/kernel/sev.c +++ b/arch/x86/kernel/sev.c@@ -54,6 +54,8 @@ * bookkeeping, the range need to be added during the RMP entry lookup. */ #define RMPTABLE_CPU_BOOKKEEPING_SZ 0x4000 +#define RMPENTRY_SHIFT 8 +#define rmptable_page_offset(x) (RMPTABLE_CPU_BOOKKEEPING_SZ + (((unsigned long)x) >> RMPENTRY_SHIFT)) /* For early boot hypervisor communication in SEV-ES enabled guests */ static struct ghcb boot_ghcb_page __bss_decrypted __aligned(PAGE_SIZE);@@ -2376,3 +2378,44 @@ static int __init snp_rmptable_init(void) * available after subsys_initcall(). */ fs_initcall(snp_rmptable_init); + +static struct rmpentry *__snp_lookup_rmpentry(u64 pfn, int *level) +{ + unsigned long vaddr, paddr = pfn << PAGE_SHIFT; + struct rmpentry *entry, *large_entry; + + if (!pfn_valid(pfn)) + return ERR_PTR(-EINVAL); + + if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP)) + return ERR_PTR(-ENXIO);
I think that check should happen first.
+ + vaddr = rmptable_start + rmptable_page_offset(paddr); + if (unlikely(vaddr > rmptable_end)) + return ERR_PTR(-ENXIO);
Maybe the above -E should be -ENOENT instead so that you have unique error types for each check to facilitate debugging.
+ + entry = (struct rmpentry *)vaddr; + + /* Read a large RMP entry to get the correct page level used in RMP entry. */
That comment needs rewriting.
+ vaddr = rmptable_start + rmptable_page_offset(paddr & PMD_MASK); + large_entry = (struct rmpentry *)vaddr; + *level = RMP_TO_X86_PG_LEVEL(rmpentry_pagesize(large_entry)); + + return entry; +} + +/* + * Return 1 if the RMP entry is assigned, 0 if it exists but is not assigned, + * and -errno if there is no corresponding RMP entry. + */
kernel-doc format since it is being exported.
+int snp_lookup_rmpentry(u64 pfn, int *level)
+{
+ struct rmpentry *e;
+
+ e = __snp_lookup_rmpentry(pfn, level);
+ if (IS_ERR(e))
+ return PTR_ERR(e);
+
+ return !!rmpentry_assigned(e);
+}
+EXPORT_SYMBOL_GPL(snp_lookup_rmpentry);This export is for kvm, I presume?
quoted hunk ↗ jump to hunk
diff --git a/include/linux/sev.h b/include/linux/sev.h new file mode 100644 index 000000000000..1a68842789e1 --- /dev/null +++ b/include/linux/sev.h@@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * AMD Secure Encrypted Virtualization + * + * Author: Brijesh Singh <brijesh.singh@amd.com> + */ + +#ifndef __LINUX_SEV_H +#define __LINUX_SEV_H + +/* RMUPDATE detected 4K page and 2MB page overlap. */ +#define RMPUPDATE_FAIL_OVERLAP 7 + +#ifdef CONFIG_AMD_MEM_ENCRYPT +int snp_lookup_rmpentry(u64 pfn, int *level); +int psmash(u64 pfn); +int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, int asid, bool immutable); +int rmp_make_shared(u64 pfn, enum pg_level level); +#else +static inline int snp_lookup_rmpentry(u64 pfn, int *level) { return 0; } +static inline int psmash(u64 pfn) { return -ENXIO; } +static inline int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, int asid, + bool immutable) +{ + return -ENODEV; +} +static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV; } + +#endif /* CONFIG_AMD_MEM_ENCRYPT */ +#endif /* __LINUX_SEV_H */--
What is going to use this linux/ namespace header?
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette