qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.0-pull-request' into staging

Implement TARGET_SO_PEERSEC
Fix rt signals management

# gpg: Signature made Thu 13 Feb 2020 12:20:50 GMT
# gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg: issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C

* remotes/vivier2/tags/linux-user-for-5.0-pull-request:
linux-user: implement TARGET_SO_PEERSEC
linux-user: fix use of SIGRTMIN
linux-user: fix TARGET_NSIG and _NSIG uses
linux-user: cleanup signal.c
linux-user: add missing TARGET_SIGRTMIN for hppa

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

# Conflicts:
# linux-user/signal.c

+128 -32
+1
linux-user/hppa/target_signal.h
··· 34 34 #define TARGET_SIGURG 29 35 35 #define TARGET_SIGXFSZ 30 36 36 #define TARGET_SIGSYS 31 37 + #define TARGET_SIGRTMIN 32 37 38 38 39 #define TARGET_SIG_BLOCK 0 39 40 #define TARGET_SIG_UNBLOCK 1
+102 -32
linux-user/signal.c
··· 30 30 static void host_signal_handler(int host_signum, siginfo_t *info, 31 31 void *puc); 32 32 33 + 34 + /* 35 + * System includes define _NSIG as SIGRTMAX + 1, 36 + * but qemu (like the kernel) defines TARGET_NSIG as TARGET_SIGRTMAX 37 + * and the first signal is SIGHUP defined as 1 38 + * Signal number 0 is reserved for use as kill(pid, 0), to test whether 39 + * a process exists without sending it a signal. 40 + */ 41 + QEMU_BUILD_BUG_ON(__SIGRTMAX + 1 != _NSIG); 33 42 static uint8_t host_to_target_signal_table[_NSIG] = { 34 43 [SIGHUP] = TARGET_SIGHUP, 35 44 [SIGINT] = TARGET_SIGINT, ··· 66 75 [SIGPWR] = TARGET_SIGPWR, 67 76 [SIGSYS] = TARGET_SIGSYS, 68 77 /* next signals stay the same */ 69 - /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with 70 - host libpthread signals. This assumes no one actually uses SIGRTMAX :-/ 71 - To fix this properly we need to do manual signal delivery multiplexed 72 - over a single host signal. */ 73 - [__SIGRTMIN] = __SIGRTMAX, 74 - [__SIGRTMAX] = __SIGRTMIN, 75 78 }; 76 - static uint8_t target_to_host_signal_table[_NSIG]; 77 79 80 + static uint8_t target_to_host_signal_table[TARGET_NSIG + 1]; 81 + 82 + /* valid sig is between 1 and _NSIG - 1 */ 78 83 int host_to_target_signal(int sig) 79 84 { 80 - if (sig < 0 || sig >= _NSIG) 85 + if (sig < 1 || sig >= _NSIG) { 81 86 return sig; 87 + } 82 88 return host_to_target_signal_table[sig]; 83 89 } 84 90 91 + /* valid sig is between 1 and TARGET_NSIG */ 85 92 int target_to_host_signal(int sig) 86 93 { 87 - if (sig < 0 || sig >= _NSIG) 94 + if (sig < 1 || sig > TARGET_NSIG) { 88 95 return sig; 96 + } 89 97 return target_to_host_signal_table[sig]; 90 98 } 91 99 ··· 106 114 void host_to_target_sigset_internal(target_sigset_t *d, 107 115 const sigset_t *s) 108 116 { 109 - int i; 117 + int host_sig, target_sig; 110 118 target_sigemptyset(d); 111 - for (i = 1; i <= TARGET_NSIG; i++) { 112 - if (sigismember(s, i)) { 113 - target_sigaddset(d, host_to_target_signal(i)); 119 + for (host_sig = 1; host_sig < _NSIG; host_sig++) { 120 + target_sig = host_to_target_signal(host_sig); 121 + if (target_sig < 1 || target_sig > TARGET_NSIG) { 122 + continue; 123 + } 124 + if (sigismember(s, host_sig)) { 125 + target_sigaddset(d, target_sig); 114 126 } 115 127 } 116 128 } ··· 128 140 void target_to_host_sigset_internal(sigset_t *d, 129 141 const target_sigset_t *s) 130 142 { 131 - int i; 143 + int host_sig, target_sig; 132 144 sigemptyset(d); 133 - for (i = 1; i <= TARGET_NSIG; i++) { 134 - if (target_sigismember(s, i)) { 135 - sigaddset(d, target_to_host_signal(i)); 145 + for (target_sig = 1; target_sig <= TARGET_NSIG; target_sig++) { 146 + host_sig = target_to_host_signal(target_sig); 147 + if (host_sig < 1 || host_sig >= _NSIG) { 148 + continue; 149 + } 150 + if (target_sigismember(s, target_sig)) { 151 + sigaddset(d, host_sig); 136 152 } 137 153 } 138 154 } ··· 480 496 } 481 497 } 482 498 499 + static void signal_table_init(void) 500 + { 501 + int host_sig, target_sig, count; 502 + 503 + /* 504 + * Signals are supported starting from TARGET_SIGRTMIN and going up 505 + * until we run out of host realtime signals. 506 + * glibc at least uses only the lower 2 rt signals and probably 507 + * nobody's using the upper ones. 508 + * it's why SIGRTMIN (34) is generally greater than __SIGRTMIN (32) 509 + * To fix this properly we need to do manual signal delivery multiplexed 510 + * over a single host signal. 511 + * Attempts for configure "missing" signals via sigaction will be 512 + * silently ignored. 513 + */ 514 + for (host_sig = SIGRTMIN; host_sig <= SIGRTMAX; host_sig++) { 515 + target_sig = host_sig - SIGRTMIN + TARGET_SIGRTMIN; 516 + if (target_sig <= TARGET_NSIG) { 517 + host_to_target_signal_table[host_sig] = target_sig; 518 + } 519 + } 520 + 521 + /* generate signal conversion tables */ 522 + for (target_sig = 1; target_sig <= TARGET_NSIG; target_sig++) { 523 + target_to_host_signal_table[target_sig] = _NSIG; /* poison */ 524 + } 525 + for (host_sig = 1; host_sig < _NSIG; host_sig++) { 526 + if (host_to_target_signal_table[host_sig] == 0) { 527 + host_to_target_signal_table[host_sig] = host_sig; 528 + } 529 + target_sig = host_to_target_signal_table[host_sig]; 530 + if (target_sig <= TARGET_NSIG) { 531 + target_to_host_signal_table[target_sig] = host_sig; 532 + } 533 + } 534 + 535 + if (trace_event_get_state_backends(TRACE_SIGNAL_TABLE_INIT)) { 536 + for (target_sig = 1, count = 0; target_sig <= TARGET_NSIG; target_sig++) { 537 + if (target_to_host_signal_table[target_sig] == _NSIG) { 538 + count++; 539 + } 540 + } 541 + trace_signal_table_init(count); 542 + } 543 + } 544 + 483 545 void signal_init(void) 484 546 { 485 547 TaskState *ts = (TaskState *)thread_cpu->opaque; 486 548 struct sigaction act; 487 549 struct sigaction oact; 488 - int i, j; 550 + int i; 489 551 int host_sig; 490 552 491 - /* generate signal conversion tables */ 492 - for(i = 1; i < _NSIG; i++) { 493 - if (host_to_target_signal_table[i] == 0) 494 - host_to_target_signal_table[i] = i; 495 - } 496 - for(i = 1; i < _NSIG; i++) { 497 - j = host_to_target_signal_table[i]; 498 - target_to_host_signal_table[j] = i; 499 - } 553 + /* initialize signal conversion tables */ 554 + signal_table_init(); 500 555 501 556 /* Set the signal mask from the host mask. */ 502 557 sigprocmask(0, 0, &ts->signal_mask); 503 558 504 - /* set all host signal handlers. ALL signals are blocked during 505 - the handlers to serialize them. */ 506 - memset(sigact_table, 0, sizeof(sigact_table)); 507 - 508 559 sigfillset(&act.sa_mask); 509 560 act.sa_flags = SA_SIGINFO; 510 561 act.sa_sigaction = host_signal_handler; 511 562 for(i = 1; i <= TARGET_NSIG; i++) { 512 563 #ifdef CONFIG_GPROF 513 - if (i == SIGPROF) { 564 + if (i == TARGET_SIGPROF) { 514 565 continue; 515 566 } 516 567 #endif ··· 787 838 int host_sig; 788 839 int ret = 0; 789 840 841 + trace_signal_do_sigaction_guest(sig, TARGET_NSIG); 842 + 790 843 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) { 791 844 return -TARGET_EINVAL; 792 845 } ··· 817 870 818 871 /* we update the host linux signal state */ 819 872 host_sig = target_to_host_signal(sig); 873 + trace_signal_do_sigaction_host(host_sig, TARGET_NSIG); 874 + if (host_sig > SIGRTMAX) { 875 + /* we don't have enough host signals to map all target signals */ 876 + qemu_log_mask(LOG_UNIMP, "Unsupported target signal #%d, ignored\n", 877 + sig); 878 + /* 879 + * we don't return an error here because some programs try to 880 + * register an handler for all possible rt signals even if they 881 + * don't need it. 882 + * An error here can abort them whereas there can be no problem 883 + * to not have the signal available later. 884 + * This is the case for golang, 885 + * See https://github.com/golang/go/issues/33746 886 + * So we silently ignore the error. 887 + */ 888 + return 0; 889 + } 820 890 if (host_sig != SIGSEGV && host_sig != SIGBUS) { 821 891 sigfillset(&act1.sa_mask); 822 892 act1.sa_flags = SA_SIGINFO;
+22
linux-user/syscall.c
··· 2344 2344 } 2345 2345 break; 2346 2346 } 2347 + case TARGET_SO_PEERSEC: { 2348 + char *name; 2349 + 2350 + if (get_user_u32(len, optlen)) { 2351 + return -TARGET_EFAULT; 2352 + } 2353 + if (len < 0) { 2354 + return -TARGET_EINVAL; 2355 + } 2356 + name = lock_user(VERIFY_WRITE, optval_addr, len, 0); 2357 + if (!name) { 2358 + return -TARGET_EFAULT; 2359 + } 2360 + lv = len; 2361 + ret = get_errno(getsockopt(sockfd, level, SO_PEERSEC, 2362 + name, &lv)); 2363 + if (put_user_u32(lv, optlen)) { 2364 + ret = -TARGET_EFAULT; 2365 + } 2366 + unlock_user(name, optval_addr, lv); 2367 + break; 2368 + } 2347 2369 case TARGET_SO_LINGER: 2348 2370 { 2349 2371 struct linger lg;
+3
linux-user/trace-events
··· 1 1 # See docs/devel/tracing.txt for syntax documentation. 2 2 3 3 # signal.c 4 + signal_table_init(int i) "number of unavailable signals: %d" 5 + signal_do_sigaction_guest(int sig, int max) "target signal %d (MAX %d)" 6 + signal_do_sigaction_host(int sig, int max) "host signal %d (MAX %d)" 4 7 # */signal.c 5 8 user_setup_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64 6 9 user_setup_rt_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64