1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2020 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 #include "spdk/env.h" 8 #include "spdk/log.h" 9 10 struct sigbus_handler { 11 spdk_pci_error_handler func; 12 void *ctx; 13 14 TAILQ_ENTRY(sigbus_handler) tailq; 15 }; 16 17 static pthread_mutex_t g_sighandler_mutex = PTHREAD_MUTEX_INITIALIZER; 18 static TAILQ_HEAD(, sigbus_handler) g_sigbus_handler = 19 TAILQ_HEAD_INITIALIZER(g_sigbus_handler); 20 21 static void 22 sigbus_fault_sighandler(int signum, siginfo_t *info, void *ctx) 23 { 24 struct sigbus_handler *sigbus_handler; 25 26 pthread_mutex_lock(&g_sighandler_mutex); 27 TAILQ_FOREACH(sigbus_handler, &g_sigbus_handler, tailq) { 28 sigbus_handler->func(info->si_addr, sigbus_handler->ctx); 29 } 30 pthread_mutex_unlock(&g_sighandler_mutex); 31 } 32 33 __attribute__((constructor)) static void 34 device_set_signal(void) 35 { 36 struct sigaction sa; 37 38 sa.sa_sigaction = sigbus_fault_sighandler; 39 sigemptyset(&sa.sa_mask); 40 sa.sa_flags = SA_SIGINFO; 41 sigaction(SIGBUS, &sa, NULL); 42 } 43 44 __attribute__((destructor)) static void 45 device_destroy_signal(void) 46 { 47 struct sigbus_handler *sigbus_handler, *tmp; 48 49 TAILQ_FOREACH_SAFE(sigbus_handler, &g_sigbus_handler, tailq, tmp) { 50 free(sigbus_handler); 51 } 52 } 53 54 int 55 spdk_pci_register_error_handler(spdk_pci_error_handler sighandler, void *ctx) 56 { 57 struct sigbus_handler *sigbus_handler; 58 59 if (!sighandler) { 60 SPDK_ERRLOG("Error handler is NULL\n"); 61 return -EINVAL; 62 } 63 64 pthread_mutex_lock(&g_sighandler_mutex); 65 TAILQ_FOREACH(sigbus_handler, &g_sigbus_handler, tailq) { 66 if (sigbus_handler->func == sighandler) { 67 pthread_mutex_unlock(&g_sighandler_mutex); 68 SPDK_ERRLOG("Error handler has been registered\n"); 69 return -EINVAL; 70 } 71 } 72 pthread_mutex_unlock(&g_sighandler_mutex); 73 74 sigbus_handler = calloc(1, sizeof(*sigbus_handler)); 75 if (!sigbus_handler) { 76 SPDK_ERRLOG("Failed to allocate sigbus handler\n"); 77 return -ENOMEM; 78 } 79 80 sigbus_handler->func = sighandler; 81 sigbus_handler->ctx = ctx; 82 83 pthread_mutex_lock(&g_sighandler_mutex); 84 TAILQ_INSERT_TAIL(&g_sigbus_handler, sigbus_handler, tailq); 85 pthread_mutex_unlock(&g_sighandler_mutex); 86 87 return 0; 88 } 89 90 void 91 spdk_pci_unregister_error_handler(spdk_pci_error_handler sighandler) 92 { 93 struct sigbus_handler *sigbus_handler; 94 95 if (!sighandler) { 96 return; 97 } 98 99 pthread_mutex_lock(&g_sighandler_mutex); 100 TAILQ_FOREACH(sigbus_handler, &g_sigbus_handler, tailq) { 101 if (sigbus_handler->func == sighandler) { 102 TAILQ_REMOVE(&g_sigbus_handler, sigbus_handler, tailq); 103 free(sigbus_handler); 104 pthread_mutex_unlock(&g_sighandler_mutex); 105 return; 106 } 107 } 108 pthread_mutex_unlock(&g_sighandler_mutex); 109 } 110