diff options
-rw-r--r-- | projects/hsm/Makefile | 7 | ||||
-rw-r--r-- | projects/hsm/hsm.c | 115 | ||||
-rw-r--r-- | projects/hsm/mgmt-cli.c | 3 | ||||
-rw-r--r-- | projects/hsm/mgmt-fpga.c | 3 | ||||
-rw-r--r-- | projects/hsm/mgmt-thread.c | 97 | ||||
-rw-r--r-- | projects/hsm/mgmt-thread.h | 42 |
6 files changed, 207 insertions, 60 deletions
diff --git a/projects/hsm/Makefile b/projects/hsm/Makefile index 0ab4bff..b92390a 100644 --- a/projects/hsm/Makefile +++ b/projects/hsm/Makefile @@ -8,7 +8,8 @@ OBJS = crc32.o \ mgmt-fpga.c \ mgmt-keystore.c \ mgmt-masterkey.c \ - mgmt-misc.c + mgmt-misc.c \ + mgmt-thread.c BOARD_OBJS = \ $(TOPLEVEL)/stm-init.o \ @@ -26,9 +27,7 @@ BOARD_OBJS = \ $(BOARD_DIR)/stm32f4xx_hal_msp.o \ $(BOARD_DIR)/stm32f4xx_it_rtos.o -ifndef CRYPTECH_ROOT - CRYPTECH_ROOT := $(abspath ../../../..) -endif +CFLAGS += -DNUM_RPC_TASK=4 CFLAGS += -I$(LIBHAL_SRC) CFLAGS += -I$(LIBCLI_SRC) diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c index adce889..862e718 100644 --- a/projects/hsm/hsm.c +++ b/projects/hsm/hsm.c @@ -91,28 +91,21 @@ typedef struct { uint8_t buf[MAX_PKT_SIZE]; } rpc_buffer_t; +/* A mail queue (memory pool + message queue) for RPC request messages. + */ +osMailQId ibuf_queue; +osMailQDef(ibuf_queue, NUM_RPC_TASK, rpc_buffer_t); + #if NUM_RPC_TASK > 1 /* A mutex to arbitrate concurrent UART transmits, from RPC responses. */ osMutexId uart_mutex; osMutexDef(uart_mutex); - -/* A mutex so only one dispatch thread can receive requests. - */ -osMutexId dispatch_mutex; -osMutexDef(dispatch_mutex); #endif -/* Semaphore to inform the dispatch thread that there's a new RPC request. - */ -osSemaphoreId rpc_sem; -osSemaphoreDef(rpc_sem); - static volatile uint8_t uart_rx; /* current character received from UART */ -static rpc_buffer_t * volatile rbuf; /* current RPC input buffer */ -static volatile int reenable_recv = 1; -/* Callback for HAL_UART_Receive_IT(). +/* Callback for HAL_UART_Receive_DMA(). * With multiple worker threads, we can't do a blocking receive, because * that prevents other threads from sending RPC responses (because they * both want to lock the UART - see stm32f4xx_hal_uart.c). So we have to @@ -122,25 +115,35 @@ static volatile int reenable_recv = 1; */ void HAL_UART2_RxCpltCallback(UART_HandleTypeDef *huart) { + /* current RPC input buffer */ + static rpc_buffer_t *ibuf = NULL; int complete; - if (hal_slip_recv_char(rbuf->buf, &rbuf->len, sizeof(rbuf->buf), &complete) != LIBHAL_OK) + if (ibuf == NULL) { + if ((ibuf = (rpc_buffer_t *)osMailAlloc(ibuf_queue, 0)) == NULL) + Error_Handler(); + ibuf->len = 0; + } + + if (hal_slip_recv_char(ibuf->buf, &ibuf->len, sizeof(ibuf->buf), &complete) != LIBHAL_OK) Error_Handler(); - if (complete) - if (osSemaphoreRelease(rpc_sem) != osOK) + if (complete) { + if (osMailPut(ibuf_queue, (void *)ibuf) != osOK) Error_Handler(); + ibuf = NULL; + } +} - if (HAL_UART_Receive_IT(huart, (uint8_t *)&uart_rx, 1) != CMSIS_HAL_OK) - /* We may have collided with a transmit. - * Signal the dispatch_thread to try again. - */ - reenable_recv = 1; +void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) +{ + /* I dunno, just trap it for now */ + Error_Handler(); } hal_error_t hal_serial_recv_char(uint8_t *cp) { - /* return the character from HAL_UART_Receive_IT */ + /* return the character from HAL_UART_Receive_DMA */ *cp = uart_rx; return LIBHAL_OK; } @@ -154,49 +157,35 @@ hal_error_t hal_serial_send_char(uint8_t c) */ void dispatch_thread(void const *args) { - rpc_buffer_t ibuf, obuf; + rpc_buffer_t obuf_s, *obuf = &obuf_s, *ibuf; while (1) { - memset(&ibuf, 0, sizeof(ibuf)); - memset(&obuf, 0, sizeof(obuf)); - obuf.len = sizeof(obuf.buf); + memset(obuf, 0, sizeof(*obuf)); + obuf->len = sizeof(obuf->buf); -#if NUM_RPC_TASK > 1 - /* Wait for access to the uart */ - osMutexWait(dispatch_mutex, osWaitForever); -#endif - - /* Start receiving, or re-enable after failing in the callback. */ - if (reenable_recv) { - if (HAL_UART_Receive_IT(&huart_user, (uint8_t *)&uart_rx, 1) != CMSIS_HAL_OK) - Error_Handler(); - reenable_recv = 0; - } - - /* Wait for the complete rpc request */ - rbuf = &ibuf; - osSemaphoreWait(rpc_sem, osWaitForever); - -#if NUM_RPC_TASK > 1 - /* Let the next thread handle the next request */ - osMutexRelease(dispatch_mutex); - /* Let the next thread take the mutex */ - osThreadYield(); -#endif + /* Wait for a complete RPC request */ + osEvent evt = osMailGet(ibuf_queue, osWaitForever); + if (evt.status != osEventMail) + continue; + ibuf = (rpc_buffer_t *)evt.value.p; /* Process the request */ - if (hal_rpc_server_dispatch(ibuf.buf, ibuf.len, obuf.buf, &obuf.len) != LIBHAL_OK) + hal_error_t ret = hal_rpc_server_dispatch(ibuf->buf, ibuf->len, obuf->buf, &obuf->len); + osMailFree(ibuf_queue, (void *)ibuf); + if (ret != LIBHAL_OK) { + Error_Handler(); /* If hal_rpc_server_dispatch failed with an XDR error, it * probably means the request packet was garbage. In any case, we * have nothing to transmit. */ continue; + } /* Send the response */ #if NUM_RPC_TASK > 1 osMutexWait(uart_mutex, osWaitForever); #endif - hal_error_t ret = hal_rpc_sendto(obuf.buf, obuf.len, NULL); + ret = hal_rpc_sendto(obuf->buf, obuf->len, NULL); #if NUM_RPC_TASK > 1 osMutexRelease(uart_mutex); #endif @@ -228,6 +217,20 @@ static uint8_t *sdram_malloc(size_t size) return p; } +#if NUM_RPC_TASK > 1 +/* Critical section start/end, currently used just for hal_core_alloc/_free. + */ +void hal_critical_section_start(void) +{ + __disable_irq(); +} + +void hal_critical_section_end(void) +{ + __enable_irq(); +} +#endif + /* The main thread. This does all the setup, and the worker threads handle * the rest. */ @@ -241,13 +244,13 @@ int main() fmc_init(); sdram_init(); + if ((ibuf_queue = osMailCreate(osMailQ(ibuf_queue), NULL)) == NULL) + Error_Handler(); + #if NUM_RPC_TASK > 1 - if ((uart_mutex = osMutexCreate(osMutex(uart_mutex))) == NULL || - (dispatch_mutex = osMutexCreate(osMutex(dispatch_mutex)) == NULL) + if ((uart_mutex = osMutexCreate(osMutex(uart_mutex))) == NULL) Error_Handler(); #endif - if ((rpc_sem = osSemaphoreCreate(osSemaphore(rpc_sem), 0)) == NULL) - Error_Handler(); if (hal_rpc_server_init() != LIBHAL_OK) Error_Handler(); @@ -265,6 +268,10 @@ int main() Error_Handler(); } + /* Start the UART receiver. */ + if (HAL_UART_Receive_DMA(&huart_user, (uint8_t *)&uart_rx, 1) != CMSIS_HAL_OK) + Error_Handler(); + /* Launch other threads (csprng warm-up thread?) * Wait for FPGA_DONE interrupt. */ diff --git a/projects/hsm/mgmt-cli.c b/projects/hsm/mgmt-cli.c index 539ba4c..ee1b31b 100644 --- a/projects/hsm/mgmt-cli.c +++ b/projects/hsm/mgmt-cli.c @@ -49,6 +49,7 @@ #include "mgmt-misc.h" #include "mgmt-keystore.h" #include "mgmt-masterkey.h" +#include "mgmt-thread.h" #undef HAL_OK #define HAL_OK LIBHAL_OK @@ -106,7 +107,6 @@ void HAL_UART1_RxCpltCallback(UART_HandleTypeDef *huart) { ringbuf_write_char(&uart_ringbuf, uart_rx); osSemaphoreRelease(uart_sem); - HAL_UART_Receive_DMA(huart, &uart_rx, 1); } static void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf) @@ -196,6 +196,7 @@ int cli_main(void) configure_cli_firmware(cli); configure_cli_bootloader(cli); configure_cli_misc(cli); + configure_cli_thread(cli); while (1) { control_mgmt_uart_dma_rx(DMA_RX_START); diff --git a/projects/hsm/mgmt-fpga.c b/projects/hsm/mgmt-fpga.c index 778ded9..d76315e 100644 --- a/projects/hsm/mgmt-fpga.c +++ b/projects/hsm/mgmt-fpga.c @@ -119,6 +119,7 @@ static int cmd_fpga_reset(struct cli_def *cli, const char *command, char *argv[] { fpgacfg_access_control(ALLOW_FPGA); fpgacfg_reset_fpga(RESET_FULL); + hal_core_reset_table(); cli_print(cli, "FPGA has been reset"); return CLI_OK; @@ -126,7 +127,7 @@ static int cmd_fpga_reset(struct cli_def *cli, const char *command, char *argv[] static int cmd_fpga_show_cores(struct cli_def *cli, const char *command, char *argv[], int argc) { - const hal_core_t *core; + hal_core_t *core; const hal_core_info_t *info; if (! fpgacfg_check_done()) { diff --git a/projects/hsm/mgmt-thread.c b/projects/hsm/mgmt-thread.c new file mode 100644 index 0000000..82b8e72 --- /dev/null +++ b/projects/hsm/mgmt-thread.c @@ -0,0 +1,97 @@ +/* + * mgmt-thread.c + * ----------- + * CLI 'thread' functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Show the active threads. This is mostly for debugging, and looks deeply + * into OS-level structures, but sometimes you just need to know... + */ + +#include "mgmt-cli.h" +#include "mgmt-thread.h" + +/* rt_TypeDef.h redefines NULL (previously defined in stddef.h, via libcli.h) */ +#undef NULL + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" + +static char *task_state[] = { + "INACTIVE", + "READY", + "RUNNING", + "WAIT_DLY", + "WAIT_ITV", + "WAIT_OR", + "WAIT_AND", + "WAIT_SEM", + "WAIT_MBX", + "WAIT_MUT", +}; + +static int cmd_thread_show(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + OS_TID task_id; + P_TCB task; + char *name; + extern void main(void); + extern void dispatch_thread(void); + extern void osTimerThread(void); + + for (task_id = 1; task_id <= os_maxtaskrun; ++ task_id) { + if ((task = os_active_TCB[task_id-1]) != NULL) { + if (task->ptask == main) + name = "main"; + else if (task->ptask == dispatch_thread) + name = "dispatch_thread"; + else if (task->ptask == osTimerThread) + name = "osTimerThread"; + else + name = "unknown"; + + cli_print(cli, "%d:\tptask\t%p\t%s", task_id, task->ptask, name); + cli_print(cli, "\tstate\t%d\t\t%s", (int)task->state, task_state[task->state]); + cli_print(cli, "\tprio\t%d", (int)task->prio); + cli_print(cli, "\tstack\t%p", task->stack); + } + } + return CLI_OK; +} + +void configure_cli_thread(struct cli_def *cli) +{ + struct cli_command *c = cli_register_command(cli, NULL, "thread", NULL, 0, 0, NULL); + + /* thread show */ + cli_register_command(cli, c, "show", cmd_thread_show, 0, 0, "Show the active threads"); +} diff --git a/projects/hsm/mgmt-thread.h b/projects/hsm/mgmt-thread.h new file mode 100644 index 0000000..f72695e --- /dev/null +++ b/projects/hsm/mgmt-thread.h @@ -0,0 +1,42 @@ +/* + * mgmt-thread.h + * ----------- + * Management CLI 'thread' functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STM32_CLI_MGMT_THREAD_H +#define __STM32_CLI_MGMT_THREAD_H + +#include <libcli.h> + +extern void configure_cli_thread(struct cli_def *cli); + +#endif /* __STM32_CLI_MGMT_THREAD_H */ |