qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio
at jcs-hda-dma 136 lines 3.8 kB view raw
1/* 2 * QEMU System Emulator - managing I/O handler 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25#include "qemu/osdep.h" 26#include "qapi/error.h" 27#include "qemu-common.h" 28#include "qemu/queue.h" 29#include "block/aio.h" 30#include "qemu/main-loop.h" 31 32#ifndef _WIN32 33#include <sys/wait.h> 34#endif 35 36/* This context runs on top of main loop. We can't reuse qemu_aio_context 37 * because iohandlers mustn't be polled by aio_poll(qemu_aio_context). */ 38static AioContext *iohandler_ctx; 39 40static void iohandler_init(void) 41{ 42 if (!iohandler_ctx) { 43 iohandler_ctx = aio_context_new(&error_abort); 44 } 45} 46 47AioContext *iohandler_get_aio_context(void) 48{ 49 iohandler_init(); 50 return iohandler_ctx; 51} 52 53GSource *iohandler_get_g_source(void) 54{ 55 iohandler_init(); 56 return aio_get_g_source(iohandler_ctx); 57} 58 59void qemu_set_fd_handler(int fd, 60 IOHandler *fd_read, 61 IOHandler *fd_write, 62 void *opaque) 63{ 64 iohandler_init(); 65 aio_set_fd_handler(iohandler_ctx, fd, false, 66 fd_read, fd_write, NULL, opaque); 67} 68 69void event_notifier_set_handler(EventNotifier *e, 70 EventNotifierHandler *handler) 71{ 72 iohandler_init(); 73 aio_set_event_notifier(iohandler_ctx, e, false, 74 handler, NULL); 75} 76 77/* reaping of zombies. right now we're not passing the status to 78 anyone, but it would be possible to add a callback. */ 79#ifndef _WIN32 80typedef struct ChildProcessRecord { 81 int pid; 82 QLIST_ENTRY(ChildProcessRecord) next; 83} ChildProcessRecord; 84 85static QLIST_HEAD(, ChildProcessRecord) child_watches = 86 QLIST_HEAD_INITIALIZER(child_watches); 87 88static QEMUBH *sigchld_bh; 89 90static void sigchld_handler(int signal) 91{ 92 qemu_bh_schedule(sigchld_bh); 93} 94 95static void sigchld_bh_handler(void *opaque) 96{ 97 ChildProcessRecord *rec, *next; 98 99 QLIST_FOREACH_SAFE(rec, &child_watches, next, next) { 100 if (waitpid(rec->pid, NULL, WNOHANG) == rec->pid) { 101 QLIST_REMOVE(rec, next); 102 g_free(rec); 103 } 104 } 105} 106 107static void qemu_init_child_watch(void) 108{ 109 struct sigaction act; 110 sigchld_bh = qemu_bh_new(sigchld_bh_handler, NULL); 111 112 memset(&act, 0, sizeof(act)); 113 act.sa_handler = sigchld_handler; 114 act.sa_flags = SA_NOCLDSTOP; 115 sigaction(SIGCHLD, &act, NULL); 116} 117 118int qemu_add_child_watch(pid_t pid) 119{ 120 ChildProcessRecord *rec; 121 122 if (!sigchld_bh) { 123 qemu_init_child_watch(); 124 } 125 126 QLIST_FOREACH(rec, &child_watches, next) { 127 if (rec->pid == pid) { 128 return 1; 129 } 130 } 131 rec = g_malloc0(sizeof(ChildProcessRecord)); 132 rec->pid = pid; 133 QLIST_INSERT_HEAD(&child_watches, rec, next); 134 return 0; 135} 136#endif