Message ID | 20181102231320.29164-16-jarkko.sakkinen@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Intel SGX1 | expand |
On Sat, Nov 3, 2018 at 1:18 AM Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> wrote: > > ENCLS is an umbrella instruction for a variety of cpl0 SGX functions. > The ENCLS function that is executed is specified in EAX, with each > function potentially having more leaf-specific operands beyond EAX. > ENCLS introduces its own (positive value) error codes that (some) > leafs use to return failure information in EAX. Leafs that return > an error code also modify RFLAGS. And finally, ENCLS generates > ENCLS-specific non-fatal #GPs and #PFs, i.e. a bug-free kernel may > encounter faults on ENCLS that must be handled gracefully. > > Because of the complexity involved in encoding ENCLS and handling its > assortment of failure paths, executing any given leaf is not a simple > matter of emitting ENCLS. > > To enable adding support for ENCLS leafs with minimal fuss, add a > two-layer macro system along with an encoding scheme to allow wrappers > to return trap numbers along ENCLS-specific error codes. The bottom > layer of the macro system splits between the leafs that return an > error code and those that do not. The second layer generates the > correct input/output annotations based on the number of operands for > each leaf function. > +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ > +/** I dunno if kernel-doc script still complains about this. > + * Copyright(c) 2016-18 Intel Corporation. > + */
On Sat, Nov 03, 2018 at 03:17:35PM +0200, Andy Shevchenko wrote: > On Sat, Nov 3, 2018 at 1:18 AM Jarkko Sakkinen > <jarkko.sakkinen@linux.intel.com> wrote: > > > > ENCLS is an umbrella instruction for a variety of cpl0 SGX functions. > > The ENCLS function that is executed is specified in EAX, with each > > function potentially having more leaf-specific operands beyond EAX. > > ENCLS introduces its own (positive value) error codes that (some) > > leafs use to return failure information in EAX. Leafs that return > > an error code also modify RFLAGS. And finally, ENCLS generates > > ENCLS-specific non-fatal #GPs and #PFs, i.e. a bug-free kernel may > > encounter faults on ENCLS that must be handled gracefully. > > > > Because of the complexity involved in encoding ENCLS and handling its > > assortment of failure paths, executing any given leaf is not a simple > > matter of emitting ENCLS. > > > > To enable adding support for ENCLS leafs with minimal fuss, add a > > two-layer macro system along with an encoding scheme to allow wrappers > > to return trap numbers along ENCLS-specific error codes. The bottom > > layer of the macro system splits between the leafs that return an > > error code and those that do not. The second layer generates the > > correct input/output annotations based on the number of operands for > > each leaf function. > > > +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ > > > +/** > > I dunno if kernel-doc script still complains about this. Is there a way to ask for make htmldocs to do only a subset of docs? Still kind of trying to figure out what would be a good flow for working with Sphinx. /Jarkko
On Mon, Nov 5, 2018 at 7:30 PM Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> wrote: > > On Sat, Nov 03, 2018 at 03:17:35PM +0200, Andy Shevchenko wrote: > > On Sat, Nov 3, 2018 at 1:18 AM Jarkko Sakkinen > > <jarkko.sakkinen@linux.intel.com> wrote: > > > > > > ENCLS is an umbrella instruction for a variety of cpl0 SGX functions. > > > The ENCLS function that is executed is specified in EAX, with each > > > function potentially having more leaf-specific operands beyond EAX. > > > ENCLS introduces its own (positive value) error codes that (some) > > > leafs use to return failure information in EAX. Leafs that return > > > an error code also modify RFLAGS. And finally, ENCLS generates > > > ENCLS-specific non-fatal #GPs and #PFs, i.e. a bug-free kernel may > > > encounter faults on ENCLS that must be handled gracefully. > > > > > > Because of the complexity involved in encoding ENCLS and handling its > > > assortment of failure paths, executing any given leaf is not a simple > > > matter of emitting ENCLS. > > > > > > To enable adding support for ENCLS leafs with minimal fuss, add a > > > two-layer macro system along with an encoding scheme to allow wrappers > > > to return trap numbers along ENCLS-specific error codes. The bottom > > > layer of the macro system splits between the leafs that return an > > > error code and those that do not. The second layer generates the > > > correct input/output annotations based on the number of operands for > > > each leaf function. > > > > > +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ > > > > > +/** > > > > I dunno if kernel-doc script still complains about this. > > Is there a way to ask for make htmldocs to do only a subset of docs? > Still kind of trying to figure out what would be a good flow for > working with Sphinx. What I'm telling here is about Copyright notice, which in my understanding is not a part of kernel-doc formatting. Though I might be mistaken. I remember some USB code has that and I saw a warning.
On Mon, Nov 05, 2018 at 10:39:46PM +0200, Andy Shevchenko wrote: > On Mon, Nov 5, 2018 at 7:30 PM Jarkko Sakkinen > <jarkko.sakkinen@linux.intel.com> wrote: > > > > On Sat, Nov 03, 2018 at 03:17:35PM +0200, Andy Shevchenko wrote: > > > On Sat, Nov 3, 2018 at 1:18 AM Jarkko Sakkinen > > > <jarkko.sakkinen@linux.intel.com> wrote: > > > > > > > > ENCLS is an umbrella instruction for a variety of cpl0 SGX functions. > > > > The ENCLS function that is executed is specified in EAX, with each > > > > function potentially having more leaf-specific operands beyond EAX. > > > > ENCLS introduces its own (positive value) error codes that (some) > > > > leafs use to return failure information in EAX. Leafs that return > > > > an error code also modify RFLAGS. And finally, ENCLS generates > > > > ENCLS-specific non-fatal #GPs and #PFs, i.e. a bug-free kernel may > > > > encounter faults on ENCLS that must be handled gracefully. > > > > > > > > Because of the complexity involved in encoding ENCLS and handling its > > > > assortment of failure paths, executing any given leaf is not a simple > > > > matter of emitting ENCLS. > > > > > > > > To enable adding support for ENCLS leafs with minimal fuss, add a > > > > two-layer macro system along with an encoding scheme to allow wrappers > > > > to return trap numbers along ENCLS-specific error codes. The bottom > > > > layer of the macro system splits between the leafs that return an > > > > error code and those that do not. The second layer generates the > > > > correct input/output annotations based on the number of operands for > > > > each leaf function. > > > > > > > +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ > > > > > > > +/** > > > > > > I dunno if kernel-doc script still complains about this. > > > > Is there a way to ask for make htmldocs to do only a subset of docs? > > Still kind of trying to figure out what would be a good flow for > > working with Sphinx. > > What I'm telling here is about Copyright notice, which in my > understanding is not a part of kernel-doc formatting. Though I might > be mistaken. > I remember some USB code has that and I saw a warning. > > -- > With Best Regards, > Andy Shevchenko I'll remove it because I don't find it in other headers under arch/x86. /Jarkko
diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h new file mode 100644 index 000000000000..23361d508348 --- /dev/null +++ b/arch/x86/include/asm/sgx.h @@ -0,0 +1,255 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/** + * Copyright(c) 2016-18 Intel Corporation. + */ +#ifndef _ASM_X86_SGX_H +#define _ASM_X86_SGX_H + +#include <asm/asm.h> +#include <asm/sgx_arch.h> + +/** + * ENCLS_FAULT_FLAG - flag signifying an ENCLS return code is a trapnr + * + * ENCLS has its own (positive value) error codes and also generates + * ENCLS specific #GP and #PF faults. And the ENCLS values get munged + * with system error codes as everything percolates back up the stack. + * Unfortunately (for us), we need to precisely identify each unique + * error code, e.g. the action taken if EWB fails varies based on the + * type of fault and on the exact SGX error code, i.e. we can't simply + * convert all faults to -EFAULT. + * + * To make all three error types coexist, we set bit 30 to identify an + * ENCLS fault. Bit 31 (technically bits N:31) is used to differentiate + * between positive (faults and SGX error codes) and negative (system + * error codes) values. + */ +#define ENCLS_FAULT_FLAG 0x40000000 + +/** + * Check for a fault by looking for a postive value with the fault + * flag set. The postive value check is needed to filter out system + * error codes since negative values will have all higher order bits + * set, including ENCLS_FAULT_FLAG. + */ +#define IS_ENCLS_FAULT(r) ((int)(r) > 0 && ((r) & ENCLS_FAULT_FLAG)) + +/** + * Retrieve the encoded trapnr from the specified return code. + */ +#define ENCLS_TRAPNR(r) ((r) & ~ENCLS_FAULT_FLAG) + +/** + * encls_to_err - translate an ENCLS fault or SGX code into a system error code + * @ret: positive value return code + * + * Translate a postive return code, e.g. from ENCLS, into a system error + * code. Primarily used by functions that cannot return a non-negative + * error code, e.g. kernel callbacks. + * + * Return: + * 0 on success, + * -errno on failure + */ +static inline int encls_to_err(int ret) +{ + if (IS_ENCLS_FAULT(ret)) + return -EFAULT; + + switch (ret) { + case SGX_UNMASKED_EVENT: + return -EINTR; + case SGX_INVALID_SIG_STRUCT: + case SGX_INVALID_ATTRIBUTE: + case SGX_INVALID_MEASUREMENT: + case SGX_INVALID_EINITTOKEN: + case SGX_INVALID_CPUSVN: + case SGX_INVALID_ISVSVN: + case SGX_INVALID_KEYNAME: + return -EINVAL; + case SGX_ENCLAVE_ACT: + case SGX_CHILD_PRESENT: + case SGX_ENTRYEPOCH_LOCKED: + case SGX_PREV_TRK_INCMPL: + case SGX_PAGE_NOT_MODIFIABLE: + case SGX_PAGE_NOT_DEBUGGABLE: + return -EBUSY; + default: + return -EIO; + }; +} + +/** + * __encls_ret_N - encode an ENCLS leaf that returns an error code in EAX + * @rax: leaf number + * @inputs: asm inputs for the leaf + * + * Emit assembly for an ENCLS leaf that returns an error code, e.g. EREMOVE. + * And because SGX isn't complex enough as it is, leafs that return an error + * code also modify flags. + * + * Return: + * 0 on success, + * SGX error code on failure + */ +#define __encls_ret_N(rax, inputs...) \ + ({ \ + int ret; \ + asm volatile( \ + "1: .byte 0x0f, 0x01, 0xcf;\n\t" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: orl $"__stringify(ENCLS_FAULT_FLAG)",%%eax\n" \ + " jmp 2b\n" \ + ".previous\n" \ + _ASM_EXTABLE_FAULT(1b, 3b) \ + : "=a"(ret) \ + : "a"(rax), inputs \ + : "memory", "cc"); \ + ret; \ + }) + +#define __encls_ret_1(rax, rcx) \ + ({ \ + __encls_ret_N(rax, "c"(rcx)); \ + }) + +#define __encls_ret_2(rax, rbx, rcx) \ + ({ \ + __encls_ret_N(rax, "b"(rbx), "c"(rcx)); \ + }) + +#define __encls_ret_3(rax, rbx, rcx, rdx) \ + ({ \ + __encls_ret_N(rax, "b"(rbx), "c"(rcx), "d"(rdx)); \ + }) + +/** + * __encls_N - encode an ENCLS leaf that doesn't return an error code + * @rax: leaf number + * @rbx_out: optional output variable + * @inputs: asm inputs for the leaf + * + * Emit assembly for an ENCLS leaf that does not return an error code, + * e.g. ECREATE. Leaves without error codes either succeed or fault. + * @rbx_out is an optional parameter for use by EDGBRD, which returns + * the the requested value in RBX. + * + * Return: + * 0 on success, + * trapnr with ENCLS_FAULT_FLAG set on fault + */ +#define __encls_N(rax, rbx_out, inputs...) \ + ({ \ + int ret; \ + asm volatile( \ + "1: .byte 0x0f, 0x01, 0xcf;\n\t" \ + " xor %%eax,%%eax;\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: orl $"__stringify(ENCLS_FAULT_FLAG)",%%eax\n" \ + " jmp 2b\n" \ + ".previous\n" \ + _ASM_EXTABLE_FAULT(1b, 3b) \ + : "=a"(ret), "=b"(rbx_out) \ + : "a"(rax), inputs \ + : "memory"); \ + ret; \ + }) + +#define __encls_2(rax, rbx, rcx) \ + ({ \ + unsigned long ign_rbx_out; \ + __encls_N(rax, ign_rbx_out, "b"(rbx), "c"(rcx)); \ + }) + +#define __encls_1_1(rax, data, rcx) \ + ({ \ + unsigned long rbx_out; \ + int ret = __encls_N(rax, rbx_out, "c"(rcx)); \ + if (!ret) \ + data = rbx_out; \ + ret; \ + }) + +static inline int __ecreate(struct sgx_pageinfo *pginfo, void __iomem *secs) +{ + return __encls_2(SGX_ECREATE, pginfo, secs); +} + +static inline int __eextend(void __iomem *secs, void __iomem *addr) +{ + return __encls_2(SGX_EEXTEND, secs, addr); +} + +static inline int __eadd(struct sgx_pageinfo *pginfo, void __iomem *addr) +{ + return __encls_2(SGX_EADD, pginfo, addr); +} + +static inline int __einit(void *sigstruct, struct sgx_einittoken *einittoken, + void __iomem *secs) +{ + return __encls_ret_3(SGX_EINIT, sigstruct, secs, einittoken); +} + +static inline int __eremove(void __iomem *addr) +{ + return __encls_ret_1(SGX_EREMOVE, addr); +} + +static inline int __edbgwr(void __iomem *addr, unsigned long *data) +{ + return __encls_2(SGX_EDGBWR, *data, addr); +} + +static inline int __edbgrd(void __iomem *addr, unsigned long *data) +{ + return __encls_1_1(SGX_EDGBRD, *data, addr); +} + +static inline int __etrack(void __iomem *addr) +{ + return __encls_ret_1(SGX_ETRACK, addr); +} + +static inline int __eldu(struct sgx_pageinfo *pginfo, void __iomem *addr, + void *va) +{ + return __encls_ret_3(SGX_ELDU, pginfo, addr, va); +} + +static inline int __eblock(void __iomem *addr) +{ + return __encls_ret_1(SGX_EBLOCK, addr); +} + +static inline int __epa(void __iomem *addr) +{ + unsigned long rbx = SGX_PAGE_TYPE_VA; + + return __encls_2(SGX_EPA, rbx, addr); +} + +static inline int __ewb(struct sgx_pageinfo *pginfo, void __iomem *addr, + void __iomem *va) +{ + return __encls_ret_3(SGX_EWB, pginfo, addr, va); +} + +static inline int __eaug(struct sgx_pageinfo *pginfo, void __iomem *addr) +{ + return __encls_2(SGX_EAUG, pginfo, addr); +} + +static inline int __emodpr(struct sgx_secinfo *secinfo, void __iomem *addr) +{ + return __encls_ret_2(SGX_EMODPR, secinfo, addr); +} + +static inline int __emodt(struct sgx_secinfo *secinfo, void __iomem *addr) +{ + return __encls_ret_2(SGX_EMODT, secinfo, addr); +} + +#endif /* _ASM_X86_SGX_H */