12adcba79SJarkko Sakkinen // SPDX-License-Identifier: GPL-2.0
22adcba79SJarkko Sakkinen /* Copyright(c) 2016-20 Intel Corporation. */
32adcba79SJarkko Sakkinen
42adcba79SJarkko Sakkinen #include <stddef.h>
52adcba79SJarkko Sakkinen #include "defines.h"
62adcba79SJarkko Sakkinen
7abc5cec4SReinette Chatre /*
8abc5cec4SReinette Chatre * Data buffer spanning two pages that will be placed first in .data
9abc5cec4SReinette Chatre * segment. Even if not used internally the second page is needed by
10abc5cec4SReinette Chatre * external test manipulating page permissions.
11abc5cec4SReinette Chatre */
1222118ce1SJarkko Sakkinen static uint8_t encl_buffer[8192] = { 1 };
1322118ce1SJarkko Sakkinen
1420404a80SReinette Chatre enum sgx_enclu_function {
1520404a80SReinette Chatre EACCEPT = 0x5,
1620404a80SReinette Chatre EMODPE = 0x6,
1720404a80SReinette Chatre };
1820404a80SReinette Chatre
do_encl_emodpe(void * _op)1920404a80SReinette Chatre static void do_encl_emodpe(void *_op)
2020404a80SReinette Chatre {
2120404a80SReinette Chatre struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0};
2220404a80SReinette Chatre struct encl_op_emodpe *op = _op;
2320404a80SReinette Chatre
2420404a80SReinette Chatre secinfo.flags = op->flags;
2520404a80SReinette Chatre
2620404a80SReinette Chatre asm volatile(".byte 0x0f, 0x01, 0xd7"
27*88fe67d4SJo Van Bulck : /* no outputs */
2820404a80SReinette Chatre : "a" (EMODPE),
2920404a80SReinette Chatre "b" (&secinfo),
30*88fe67d4SJo Van Bulck "c" (op->epc_addr)
31*88fe67d4SJo Van Bulck : "memory" /* read from secinfo pointer */);
3220404a80SReinette Chatre }
3320404a80SReinette Chatre
do_encl_eaccept(void * _op)3420404a80SReinette Chatre static void do_encl_eaccept(void *_op)
3520404a80SReinette Chatre {
3620404a80SReinette Chatre struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0};
3720404a80SReinette Chatre struct encl_op_eaccept *op = _op;
3820404a80SReinette Chatre int rax;
3920404a80SReinette Chatre
4020404a80SReinette Chatre secinfo.flags = op->flags;
4120404a80SReinette Chatre
4220404a80SReinette Chatre asm volatile(".byte 0x0f, 0x01, 0xd7"
4320404a80SReinette Chatre : "=a" (rax)
4420404a80SReinette Chatre : "a" (EACCEPT),
4520404a80SReinette Chatre "b" (&secinfo),
46*88fe67d4SJo Van Bulck "c" (op->epc_addr)
47*88fe67d4SJo Van Bulck : "memory" /* read from secinfo pointer */);
4820404a80SReinette Chatre
4920404a80SReinette Chatre op->ret = rax;
5020404a80SReinette Chatre }
5120404a80SReinette Chatre
memcpy(void * dest,const void * src,size_t n)522adcba79SJarkko Sakkinen static void *memcpy(void *dest, const void *src, size_t n)
532adcba79SJarkko Sakkinen {
542adcba79SJarkko Sakkinen size_t i;
552adcba79SJarkko Sakkinen
562adcba79SJarkko Sakkinen for (i = 0; i < n; i++)
572adcba79SJarkko Sakkinen ((char *)dest)[i] = ((char *)src)[i];
582adcba79SJarkko Sakkinen
592adcba79SJarkko Sakkinen return dest;
602adcba79SJarkko Sakkinen }
612adcba79SJarkko Sakkinen
memset(void * dest,int c,size_t n)62b564982fSReinette Chatre static void *memset(void *dest, int c, size_t n)
63b564982fSReinette Chatre {
64b564982fSReinette Chatre size_t i;
65b564982fSReinette Chatre
66b564982fSReinette Chatre for (i = 0; i < n; i++)
67b564982fSReinette Chatre ((char *)dest)[i] = c;
68b564982fSReinette Chatre
69b564982fSReinette Chatre return dest;
70b564982fSReinette Chatre }
71b564982fSReinette Chatre
do_encl_init_tcs_page(void * _op)72b564982fSReinette Chatre static void do_encl_init_tcs_page(void *_op)
73b564982fSReinette Chatre {
74b564982fSReinette Chatre struct encl_op_init_tcs_page *op = _op;
75b564982fSReinette Chatre void *tcs = (void *)op->tcs_page;
76b564982fSReinette Chatre uint32_t val_32;
77b564982fSReinette Chatre
78b564982fSReinette Chatre memset(tcs, 0, 16); /* STATE and FLAGS */
79b564982fSReinette Chatre memcpy(tcs + 16, &op->ssa, 8); /* OSSA */
80b564982fSReinette Chatre memset(tcs + 24, 0, 4); /* CSSA */
81b564982fSReinette Chatre val_32 = 1;
82b564982fSReinette Chatre memcpy(tcs + 28, &val_32, 4); /* NSSA */
83b564982fSReinette Chatre memcpy(tcs + 32, &op->entry, 8); /* OENTRY */
84b564982fSReinette Chatre memset(tcs + 40, 0, 24); /* AEP, OFSBASE, OGSBASE */
85b564982fSReinette Chatre val_32 = 0xFFFFFFFF;
86b564982fSReinette Chatre memcpy(tcs + 64, &val_32, 4); /* FSLIMIT */
87b564982fSReinette Chatre memcpy(tcs + 68, &val_32, 4); /* GSLIMIT */
88b564982fSReinette Chatre memset(tcs + 72, 0, 4024); /* Reserved */
89b564982fSReinette Chatre }
90b564982fSReinette Chatre
do_encl_op_put_to_buf(void * op)91c085dfc7SReinette Chatre static void do_encl_op_put_to_buf(void *op)
9241493a09SJarkko Sakkinen {
93c085dfc7SReinette Chatre struct encl_op_put_to_buf *op2 = op;
9441493a09SJarkko Sakkinen
9541493a09SJarkko Sakkinen memcpy(&encl_buffer[0], &op2->value, 8);
9641493a09SJarkko Sakkinen }
9741493a09SJarkko Sakkinen
do_encl_op_get_from_buf(void * op)98c085dfc7SReinette Chatre static void do_encl_op_get_from_buf(void *op)
9941493a09SJarkko Sakkinen {
100c085dfc7SReinette Chatre struct encl_op_get_from_buf *op2 = op;
10141493a09SJarkko Sakkinen
10241493a09SJarkko Sakkinen memcpy(&op2->value, &encl_buffer[0], 8);
10341493a09SJarkko Sakkinen }
10441493a09SJarkko Sakkinen
do_encl_op_put_to_addr(void * _op)105abc5cec4SReinette Chatre static void do_encl_op_put_to_addr(void *_op)
106abc5cec4SReinette Chatre {
107abc5cec4SReinette Chatre struct encl_op_put_to_addr *op = _op;
108abc5cec4SReinette Chatre
109abc5cec4SReinette Chatre memcpy((void *)op->addr, &op->value, 8);
110abc5cec4SReinette Chatre }
111abc5cec4SReinette Chatre
do_encl_op_get_from_addr(void * _op)112abc5cec4SReinette Chatre static void do_encl_op_get_from_addr(void *_op)
113abc5cec4SReinette Chatre {
114abc5cec4SReinette Chatre struct encl_op_get_from_addr *op = _op;
115abc5cec4SReinette Chatre
116abc5cec4SReinette Chatre memcpy(&op->value, (void *)op->addr, 8);
117abc5cec4SReinette Chatre }
118abc5cec4SReinette Chatre
do_encl_op_nop(void * _op)119688542e2SReinette Chatre static void do_encl_op_nop(void *_op)
120688542e2SReinette Chatre {
121688542e2SReinette Chatre
122688542e2SReinette Chatre }
123688542e2SReinette Chatre
encl_body(void * rdi,void * rsi)1242adcba79SJarkko Sakkinen void encl_body(void *rdi, void *rsi)
1252adcba79SJarkko Sakkinen {
12641493a09SJarkko Sakkinen const void (*encl_op_array[ENCL_OP_MAX])(void *) = {
127c085dfc7SReinette Chatre do_encl_op_put_to_buf,
128c085dfc7SReinette Chatre do_encl_op_get_from_buf,
129abc5cec4SReinette Chatre do_encl_op_put_to_addr,
130abc5cec4SReinette Chatre do_encl_op_get_from_addr,
131688542e2SReinette Chatre do_encl_op_nop,
13220404a80SReinette Chatre do_encl_eaccept,
13320404a80SReinette Chatre do_encl_emodpe,
134b564982fSReinette Chatre do_encl_init_tcs_page,
13541493a09SJarkko Sakkinen };
13622118ce1SJarkko Sakkinen
13741493a09SJarkko Sakkinen struct encl_op_header *op = (struct encl_op_header *)rdi;
13822118ce1SJarkko Sakkinen
13941493a09SJarkko Sakkinen if (op->type < ENCL_OP_MAX)
14041493a09SJarkko Sakkinen (*encl_op_array[op->type])(op);
1412adcba79SJarkko Sakkinen }
142