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 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*853a57a4SJo Van Bulck : /* no outputs */ 2820404a80SReinette Chatre : "a" (EMODPE), 2920404a80SReinette Chatre "b" (&secinfo), 30*853a57a4SJo Van Bulck "c" (op->epc_addr) 31*853a57a4SJo Van Bulck : "memory" /* read from secinfo pointer */); 3220404a80SReinette Chatre } 3320404a80SReinette Chatre 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*853a57a4SJo Van Bulck "c" (op->epc_addr) 47*853a57a4SJo Van Bulck : "memory" /* read from secinfo pointer */); 4820404a80SReinette Chatre 4920404a80SReinette Chatre op->ret = rax; 5020404a80SReinette Chatre } 5120404a80SReinette Chatre 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 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 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 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 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 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 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 119688542e2SReinette Chatre static void do_encl_op_nop(void *_op) 120688542e2SReinette Chatre { 121688542e2SReinette Chatre 122688542e2SReinette Chatre } 123688542e2SReinette Chatre 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