1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2016-20 Intel Corporation. */
8 * Data buffer spanning two pages that will be placed first in the .data
9 * segment via the linker script. Even if not used internally the second page
10 * is needed by external test manipulating page permissions, so mark
11 * encl_buffer as "used" to make sure it is entirely preserved by the compiler.
13 static uint8_t __used
__section(".data.encl_buffer") encl_buffer
[8192] = { 1 };
15 enum sgx_enclu_function
{
20 static void do_encl_emodpe(void *_op
)
22 struct sgx_secinfo secinfo
__aligned(sizeof(struct sgx_secinfo
)) = {0};
23 struct encl_op_emodpe
*op
= _op
;
25 secinfo
.flags
= op
->flags
;
27 asm volatile(".byte 0x0f, 0x01, 0xd7"
32 : "memory" /* read from secinfo pointer */);
35 static void do_encl_eaccept(void *_op
)
37 struct sgx_secinfo secinfo
__aligned(sizeof(struct sgx_secinfo
)) = {0};
38 struct encl_op_eaccept
*op
= _op
;
41 secinfo
.flags
= op
->flags
;
43 asm volatile(".byte 0x0f, 0x01, 0xd7"
48 : "memory" /* read from secinfo pointer */);
53 static void *memcpy(void *dest
, const void *src
, size_t n
)
57 for (i
= 0; i
< n
; i
++)
58 ((char *)dest
)[i
] = ((char *)src
)[i
];
63 static void *memset(void *dest
, int c
, size_t n
)
67 for (i
= 0; i
< n
; i
++)
68 ((char *)dest
)[i
] = c
;
73 static void do_encl_init_tcs_page(void *_op
)
75 struct encl_op_init_tcs_page
*op
= _op
;
76 void *tcs
= (void *)op
->tcs_page
;
79 memset(tcs
, 0, 16); /* STATE and FLAGS */
80 memcpy(tcs
+ 16, &op
->ssa
, 8); /* OSSA */
81 memset(tcs
+ 24, 0, 4); /* CSSA */
83 memcpy(tcs
+ 28, &val_32
, 4); /* NSSA */
84 memcpy(tcs
+ 32, &op
->entry
, 8); /* OENTRY */
85 memset(tcs
+ 40, 0, 24); /* AEP, OFSBASE, OGSBASE */
87 memcpy(tcs
+ 64, &val_32
, 4); /* FSLIMIT */
88 memcpy(tcs
+ 68, &val_32
, 4); /* GSLIMIT */
89 memset(tcs
+ 72, 0, 4024); /* Reserved */
92 static void do_encl_op_put_to_buf(void *op
)
94 struct encl_op_put_to_buf
*op2
= op
;
96 memcpy(&encl_buffer
[0], &op2
->value
, 8);
99 static void do_encl_op_get_from_buf(void *op
)
101 struct encl_op_get_from_buf
*op2
= op
;
103 memcpy(&op2
->value
, &encl_buffer
[0], 8);
106 static void do_encl_op_put_to_addr(void *_op
)
108 struct encl_op_put_to_addr
*op
= _op
;
110 memcpy((void *)op
->addr
, &op
->value
, 8);
113 static void do_encl_op_get_from_addr(void *_op
)
115 struct encl_op_get_from_addr
*op
= _op
;
117 memcpy(&op
->value
, (void *)op
->addr
, 8);
120 static void do_encl_op_nop(void *_op
)
126 * Symbol placed at the start of the enclave image by the linker script.
127 * Declare this extern symbol with visibility "hidden" to ensure the compiler
128 * does not access it through the GOT and generates position-independent
129 * addressing as __encl_base(%rip), so we can get the actual enclave base
132 extern const uint8_t __attribute__((visibility("hidden"))) __encl_base
;
134 typedef void (*encl_op_t
)(void *);
135 static const encl_op_t encl_op_array
[ENCL_OP_MAX
] = {
136 do_encl_op_put_to_buf
,
137 do_encl_op_get_from_buf
,
138 do_encl_op_put_to_addr
,
139 do_encl_op_get_from_addr
,
143 do_encl_init_tcs_page
,
146 void encl_body(void *rdi
, void *rsi
)
148 struct encl_op_header
*header
= (struct encl_op_header
*)rdi
;
151 if (header
->type
>= ENCL_OP_MAX
)
155 * The enclave base address needs to be added, as this call site
156 * *cannot be* made rip-relative by the compiler, or fixed up by
157 * any other possible means.
159 op
= ((uint64_t)&__encl_base
) + encl_op_array
[header
->type
];