cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

encls.h (4784B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef _X86_ENCLS_H
      3#define _X86_ENCLS_H
      4
      5#include <linux/bitops.h>
      6#include <linux/err.h>
      7#include <linux/io.h>
      8#include <linux/rwsem.h>
      9#include <linux/types.h>
     10#include <asm/asm.h>
     11#include <asm/traps.h>
     12#include "sgx.h"
     13
     14/* Retrieve the encoded trapnr from the specified return code. */
     15#define ENCLS_TRAPNR(r) ((r) & ~SGX_ENCLS_FAULT_FLAG)
     16
     17/* Issue a WARN() about an ENCLS function. */
     18#define ENCLS_WARN(r, name) {						  \
     19	do {								  \
     20		int _r = (r);						  \
     21		WARN_ONCE(_r, "%s returned %d (0x%x)\n", (name), _r, _r); \
     22	} while (0);							  \
     23}
     24
     25/*
     26 * encls_faulted() - Check if an ENCLS leaf faulted given an error code
     27 * @ret:	the return value of an ENCLS leaf function call
     28 *
     29 * Return:
     30 * - true:	ENCLS leaf faulted.
     31 * - false:	Otherwise.
     32 */
     33static inline bool encls_faulted(int ret)
     34{
     35	return ret & SGX_ENCLS_FAULT_FLAG;
     36}
     37
     38/**
     39 * encls_failed() - Check if an ENCLS function failed
     40 * @ret:	the return value of an ENCLS function call
     41 *
     42 * Check if an ENCLS function failed. This happens when the function causes a
     43 * fault that is not caused by an EPCM conflict or when the function returns a
     44 * non-zero value.
     45 */
     46static inline bool encls_failed(int ret)
     47{
     48	if (encls_faulted(ret))
     49		return ENCLS_TRAPNR(ret) != X86_TRAP_PF;
     50
     51	return !!ret;
     52}
     53
     54/**
     55 * __encls_ret_N - encode an ENCLS function that returns an error code in EAX
     56 * @rax:	function number
     57 * @inputs:	asm inputs for the function
     58 *
     59 * Emit assembly for an ENCLS function that returns an error code, e.g. EREMOVE.
     60 * And because SGX isn't complex enough as it is, function that return an error
     61 * code also modify flags.
     62 *
     63 * Return:
     64 *	0 on success,
     65 *	SGX error code on failure
     66 */
     67#define __encls_ret_N(rax, inputs...)				\
     68	({							\
     69	int ret;						\
     70	asm volatile(						\
     71	"1: .byte 0x0f, 0x01, 0xcf;\n\t"			\
     72	"2:\n"							\
     73	_ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FAULT_SGX)		\
     74	: "=a"(ret)						\
     75	: "a"(rax), inputs					\
     76	: "memory", "cc");					\
     77	ret;							\
     78	})
     79
     80#define __encls_ret_1(rax, rcx)		\
     81	({				\
     82	__encls_ret_N(rax, "c"(rcx));	\
     83	})
     84
     85#define __encls_ret_2(rax, rbx, rcx)		\
     86	({					\
     87	__encls_ret_N(rax, "b"(rbx), "c"(rcx));	\
     88	})
     89
     90#define __encls_ret_3(rax, rbx, rcx, rdx)			\
     91	({							\
     92	__encls_ret_N(rax, "b"(rbx), "c"(rcx), "d"(rdx));	\
     93	})
     94
     95/**
     96 * __encls_N - encode an ENCLS function that doesn't return an error code
     97 * @rax:	function number
     98 * @rbx_out:	optional output variable
     99 * @inputs:	asm inputs for the function
    100 *
    101 * Emit assembly for an ENCLS function that does not return an error code, e.g.
    102 * ECREATE.  Leaves without error codes either succeed or fault.  @rbx_out is an
    103 * optional parameter for use by EDGBRD, which returns the requested value in
    104 * RBX.
    105 *
    106 * Return:
    107 *   0 on success,
    108 *   trapnr with SGX_ENCLS_FAULT_FLAG set on fault
    109 */
    110#define __encls_N(rax, rbx_out, inputs...)			\
    111	({							\
    112	int ret;						\
    113	asm volatile(						\
    114	"1: .byte 0x0f, 0x01, 0xcf;\n\t"			\
    115	"   xor %%eax,%%eax;\n"					\
    116	"2:\n"							\
    117	_ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FAULT_SGX)		\
    118	: "=a"(ret), "=b"(rbx_out)				\
    119	: "a"(rax), inputs					\
    120	: "memory");						\
    121	ret;							\
    122	})
    123
    124#define __encls_2(rax, rbx, rcx)				\
    125	({							\
    126	unsigned long ign_rbx_out;				\
    127	__encls_N(rax, ign_rbx_out, "b"(rbx), "c"(rcx));	\
    128	})
    129
    130#define __encls_1_1(rax, data, rcx)			\
    131	({						\
    132	unsigned long rbx_out;				\
    133	int ret = __encls_N(rax, rbx_out, "c"(rcx));	\
    134	if (!ret)					\
    135		data = rbx_out;				\
    136	ret;						\
    137	})
    138
    139static inline int __ecreate(struct sgx_pageinfo *pginfo, void *secs)
    140{
    141	return __encls_2(ECREATE, pginfo, secs);
    142}
    143
    144static inline int __eextend(void *secs, void *addr)
    145{
    146	return __encls_2(EEXTEND, secs, addr);
    147}
    148
    149static inline int __eadd(struct sgx_pageinfo *pginfo, void *addr)
    150{
    151	return __encls_2(EADD, pginfo, addr);
    152}
    153
    154static inline int __einit(void *sigstruct, void *token, void *secs)
    155{
    156	return __encls_ret_3(EINIT, sigstruct, secs, token);
    157}
    158
    159static inline int __eremove(void *addr)
    160{
    161	return __encls_ret_1(EREMOVE, addr);
    162}
    163
    164static inline int __edbgwr(void *addr, unsigned long *data)
    165{
    166	return __encls_2(EDGBWR, *data, addr);
    167}
    168
    169static inline int __edbgrd(void *addr, unsigned long *data)
    170{
    171	return __encls_1_1(EDGBRD, *data, addr);
    172}
    173
    174static inline int __etrack(void *addr)
    175{
    176	return __encls_ret_1(ETRACK, addr);
    177}
    178
    179static inline int __eldu(struct sgx_pageinfo *pginfo, void *addr,
    180			 void *va)
    181{
    182	return __encls_ret_3(ELDU, pginfo, addr, va);
    183}
    184
    185static inline int __eblock(void *addr)
    186{
    187	return __encls_ret_1(EBLOCK, addr);
    188}
    189
    190static inline int __epa(void *addr)
    191{
    192	unsigned long rbx = SGX_PAGE_TYPE_VA;
    193
    194	return __encls_2(EPA, rbx, addr);
    195}
    196
    197static inline int __ewb(struct sgx_pageinfo *pginfo, void *addr,
    198			void *va)
    199{
    200	return __encls_ret_3(EWB, pginfo, addr, va);
    201}
    202
    203#endif /* _X86_ENCLS_H */