Message ID | e9a350fac5b18ca69496d07fe25a7a2408d1a73a.1610935432.git.kai.huang@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM SGX virtualization support | expand |
On Mon, Jan 18, 2021 at 04:28:06PM +1300, Kai Huang wrote: > From: Sean Christopherson <sean.j.christopherson@intel.com> > > The bare-metal kernel must intercept ECREATE to be able to impose policies > on guests. When it does this, the bare-metal kernel runs ECREATE against > the userspace mapping of the virtualized EPC. > > Provide wrappers around __ecreate() and __einit() to hide the ugliness > of overloading the ENCLS return value to encode multiple error formats > in a single int. KVM will trap-and-execute ECREATE and EINIT as part > of SGX virtualization, and on an exception, KVM needs the trapnr so that > it can inject the correct fault into the guest. > > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> > [Kai: Use sgx_update_lepubkeyhash() to update pubkey hash MSRs.] If you have to go to this, please instead use co-developed-by. > Signed-off-by: Kai Huang <kai.huang@intel.com> > --- > v1->v2: > > - Refined commit msg based on Dave's comment. > - Added comment to explain why to use __uaccess_xxx(). > --- > arch/x86/include/asm/sgx.h | 16 +++++++++ > arch/x86/kernel/cpu/sgx/virt.c | 61 ++++++++++++++++++++++++++++++++++ > 2 files changed, 77 insertions(+) > create mode 100644 arch/x86/include/asm/sgx.h > > diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h > new file mode 100644 > index 000000000000..0d643b985085 > --- /dev/null > +++ b/arch/x86/include/asm/sgx.h > @@ -0,0 +1,16 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +#ifndef _ASM_X86_SGX_H > +#define _ASM_X86_SGX_H > + > +#include <linux/types.h> > + > +#ifdef CONFIG_X86_SGX_VIRTUALIZATION > +struct sgx_pageinfo; > + > +int sgx_virt_ecreate(struct sgx_pageinfo *pageinfo, void __user *secs, > + int *trapnr); > +int sgx_virt_einit(void __user *sigstruct, void __user *token, > + void __user *secs, u64 *lepubkeyhash, int *trapnr); > +#endif > + > +#endif /* _ASM_X86_SGX_H */ > diff --git a/arch/x86/kernel/cpu/sgx/virt.c b/arch/x86/kernel/cpu/sgx/virt.c > index 1e8620f20651..97f02e5235ca 100644 > --- a/arch/x86/kernel/cpu/sgx/virt.c > +++ b/arch/x86/kernel/cpu/sgx/virt.c > @@ -253,3 +253,64 @@ int __init sgx_virt_epc_init(void) > > return misc_register(&sgx_virt_epc_dev); > } > + > +int sgx_virt_ecreate(struct sgx_pageinfo *pageinfo, void __user *secs, > + int *trapnr) > +{ > + int ret; > + > + /* > + * @secs is userspace address, and it's not guaranteed @secs points at > + * an actual EPC page. It's also possible to generate a kernel mapping > + * to physical EPC page by resolving PFN but using __uaccess_xx() is > + * simpler. > + */ > + __uaccess_begin(); > + ret = __ecreate(pageinfo, (void *)secs); > + __uaccess_end(); > + > + if (encls_faulted(ret)) { > + *trapnr = ENCLS_TRAPNR(ret); > + return -EFAULT; > + } > + > + /* ECREATE doesn't return an error code, it faults or succeeds. */ > + WARN_ON_ONCE(ret); > + return 0; > +} > +EXPORT_SYMBOL_GPL(sgx_virt_ecreate); > + > +static int __sgx_virt_einit(void __user *sigstruct, void __user *token, > + void __user *secs) > +{ > + int ret; > + > + __uaccess_begin(); > + ret = __einit((void *)sigstruct, (void *)token, (void *)secs); > + __uaccess_end(); > + return ret; > +} > + > +int sgx_virt_einit(void __user *sigstruct, void __user *token, > + void __user *secs, u64 *lepubkeyhash, int *trapnr) kdoc missing. > +{ > + int ret; > + > + if (!boot_cpu_has(X86_FEATURE_SGX_LC)) { > + ret = __sgx_virt_einit(sigstruct, token, secs); > + } else { > + preempt_disable(); > + > + sgx_update_lepubkeyhash(lepubkeyhash); > + > + ret = __sgx_virt_einit(sigstruct, token, secs); > + preempt_enable(); > + } > + > + if (encls_faulted(ret)) { > + *trapnr = ENCLS_TRAPNR(ret); > + return -EFAULT; > + } > + return ret; > +} > +EXPORT_SYMBOL_GPL(sgx_virt_einit); > -- > 2.29.2 > > /Jarkko
On Wed, 20 Jan 2021 14:04:36 +0200 Jarkko Sakkinen wrote: > On Mon, Jan 18, 2021 at 04:28:06PM +1300, Kai Huang wrote: > > From: Sean Christopherson <sean.j.christopherson@intel.com> > > > > The bare-metal kernel must intercept ECREATE to be able to impose policies > > on guests. When it does this, the bare-metal kernel runs ECREATE against > > the userspace mapping of the virtualized EPC. > > > > Provide wrappers around __ecreate() and __einit() to hide the ugliness > > of overloading the ENCLS return value to encode multiple error formats > > in a single int. KVM will trap-and-execute ECREATE and EINIT as part > > of SGX virtualization, and on an exception, KVM needs the trapnr so that > > it can inject the correct fault into the guest. > > > > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> > > [Kai: Use sgx_update_lepubkeyhash() to update pubkey hash MSRs.] > > If you have to go to this, please instead use co-developed-by. I'll remove it. I don't want to use co-developed-by here. > > > Signed-off-by: Kai Huang <kai.huang@intel.com> > > --- > > v1->v2: > > > > - Refined commit msg based on Dave's comment. > > - Added comment to explain why to use __uaccess_xxx(). > > --- > > arch/x86/include/asm/sgx.h | 16 +++++++++ > > arch/x86/kernel/cpu/sgx/virt.c | 61 ++++++++++++++++++++++++++++++++++ > > 2 files changed, 77 insertions(+) > > create mode 100644 arch/x86/include/asm/sgx.h > > > > diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h > > new file mode 100644 > > index 000000000000..0d643b985085 > > --- /dev/null > > +++ b/arch/x86/include/asm/sgx.h > > @@ -0,0 +1,16 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +#ifndef _ASM_X86_SGX_H > > +#define _ASM_X86_SGX_H > > + > > +#include <linux/types.h> > > + > > +#ifdef CONFIG_X86_SGX_VIRTUALIZATION > > +struct sgx_pageinfo; > > + > > +int sgx_virt_ecreate(struct sgx_pageinfo *pageinfo, void __user *secs, > > + int *trapnr); > > +int sgx_virt_einit(void __user *sigstruct, void __user *token, > > + void __user *secs, u64 *lepubkeyhash, int *trapnr); > > +#endif > > + > > +#endif /* _ASM_X86_SGX_H */ > > diff --git a/arch/x86/kernel/cpu/sgx/virt.c b/arch/x86/kernel/cpu/sgx/virt.c > > index 1e8620f20651..97f02e5235ca 100644 > > --- a/arch/x86/kernel/cpu/sgx/virt.c > > +++ b/arch/x86/kernel/cpu/sgx/virt.c > > @@ -253,3 +253,64 @@ int __init sgx_virt_epc_init(void) > > > > return misc_register(&sgx_virt_epc_dev); > > } > > + > > +int sgx_virt_ecreate(struct sgx_pageinfo *pageinfo, void __user *secs, > > + int *trapnr) > > +{ > > + int ret; > > + > > + /* > > + * @secs is userspace address, and it's not guaranteed @secs points at > > + * an actual EPC page. It's also possible to generate a kernel mapping > > + * to physical EPC page by resolving PFN but using __uaccess_xx() is > > + * simpler. > > + */ > > + __uaccess_begin(); > > + ret = __ecreate(pageinfo, (void *)secs); > > + __uaccess_end(); > > + > > + if (encls_faulted(ret)) { > > + *trapnr = ENCLS_TRAPNR(ret); > > + return -EFAULT; > > + } > > + > > + /* ECREATE doesn't return an error code, it faults or succeeds. */ > > + WARN_ON_ONCE(ret); > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL(sgx_virt_ecreate); > > + > > +static int __sgx_virt_einit(void __user *sigstruct, void __user *token, > > + void __user *secs) > > +{ > > + int ret; > > + > > + __uaccess_begin(); > > + ret = __einit((void *)sigstruct, (void *)token, (void *)secs); > > + __uaccess_end(); > > + return ret; > > +} > > + > > +int sgx_virt_einit(void __user *sigstruct, void __user *token, > > + void __user *secs, u64 *lepubkeyhash, int *trapnr) > > kdoc missing. OK. Will add for both sgx_virt_create() and sgx_virt_init(). > > > +{ > > + int ret; > > + > > + if (!boot_cpu_has(X86_FEATURE_SGX_LC)) { > > + ret = __sgx_virt_einit(sigstruct, token, secs); > > + } else { > > + preempt_disable(); > > + > > + sgx_update_lepubkeyhash(lepubkeyhash); > > + > > + ret = __sgx_virt_einit(sigstruct, token, secs); > > + preempt_enable(); > > + } > > + > > + if (encls_faulted(ret)) { > > + *trapnr = ENCLS_TRAPNR(ret); > > + return -EFAULT; > > + } > > + return ret; > > +} > > +EXPORT_SYMBOL_GPL(sgx_virt_einit); > > -- > > 2.29.2 > > > > > > /Jarkko
diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h new file mode 100644 index 000000000000..0d643b985085 --- /dev/null +++ b/arch/x86/include/asm/sgx.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_SGX_H +#define _ASM_X86_SGX_H + +#include <linux/types.h> + +#ifdef CONFIG_X86_SGX_VIRTUALIZATION +struct sgx_pageinfo; + +int sgx_virt_ecreate(struct sgx_pageinfo *pageinfo, void __user *secs, + int *trapnr); +int sgx_virt_einit(void __user *sigstruct, void __user *token, + void __user *secs, u64 *lepubkeyhash, int *trapnr); +#endif + +#endif /* _ASM_X86_SGX_H */ diff --git a/arch/x86/kernel/cpu/sgx/virt.c b/arch/x86/kernel/cpu/sgx/virt.c index 1e8620f20651..97f02e5235ca 100644 --- a/arch/x86/kernel/cpu/sgx/virt.c +++ b/arch/x86/kernel/cpu/sgx/virt.c @@ -253,3 +253,64 @@ int __init sgx_virt_epc_init(void) return misc_register(&sgx_virt_epc_dev); } + +int sgx_virt_ecreate(struct sgx_pageinfo *pageinfo, void __user *secs, + int *trapnr) +{ + int ret; + + /* + * @secs is userspace address, and it's not guaranteed @secs points at + * an actual EPC page. It's also possible to generate a kernel mapping + * to physical EPC page by resolving PFN but using __uaccess_xx() is + * simpler. + */ + __uaccess_begin(); + ret = __ecreate(pageinfo, (void *)secs); + __uaccess_end(); + + if (encls_faulted(ret)) { + *trapnr = ENCLS_TRAPNR(ret); + return -EFAULT; + } + + /* ECREATE doesn't return an error code, it faults or succeeds. */ + WARN_ON_ONCE(ret); + return 0; +} +EXPORT_SYMBOL_GPL(sgx_virt_ecreate); + +static int __sgx_virt_einit(void __user *sigstruct, void __user *token, + void __user *secs) +{ + int ret; + + __uaccess_begin(); + ret = __einit((void *)sigstruct, (void *)token, (void *)secs); + __uaccess_end(); + return ret; +} + +int sgx_virt_einit(void __user *sigstruct, void __user *token, + void __user *secs, u64 *lepubkeyhash, int *trapnr) +{ + int ret; + + if (!boot_cpu_has(X86_FEATURE_SGX_LC)) { + ret = __sgx_virt_einit(sigstruct, token, secs); + } else { + preempt_disable(); + + sgx_update_lepubkeyhash(lepubkeyhash); + + ret = __sgx_virt_einit(sigstruct, token, secs); + preempt_enable(); + } + + if (encls_faulted(ret)) { + *trapnr = ENCLS_TRAPNR(ret); + return -EFAULT; + } + return ret; +} +EXPORT_SYMBOL_GPL(sgx_virt_einit);