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

linux-user: fix use of SIGRTMIN

Some RT signals can be in use by glibc,
it's why SIGRTMIN (34) is generally greater than __SIGRTMIN (32).

So SIGRTMIN cannot be mapped to TARGET_SIGRTMIN.

Instead of swapping only SIGRTMIN and SIGRTMAX, map all the
range [TARGET_SIGRTMIN ... TARGET_SIGRTMAX - X] to
[__SIGRTMIN + X ... SIGRTMAX ]
(SIGRTMIN is __SIGRTMIN + X).

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Taylor Simson <tsimpson@quicinc.com>
Tested-by: Taylor Simpson <tsimpson@quicinc.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20200212125658.644558-5-laurent@vivier.eu>

+48 -5
+45 -5
linux-user/signal.c
··· 498 498 499 499 static void signal_table_init(void) 500 500 { 501 - int host_sig, target_sig; 501 + int host_sig, target_sig, count; 502 502 503 503 /* 504 - * Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with 505 - * host libpthread signals. This assumes no one actually uses SIGRTMAX :-/ 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) 506 509 * To fix this properly we need to do manual signal delivery multiplexed 507 510 * over a single host signal. 511 + * Attempts for configure "missing" signals via sigaction will be 512 + * silently ignored. 508 513 */ 509 - host_to_target_signal_table[__SIGRTMIN] = __SIGRTMAX; 510 - host_to_target_signal_table[__SIGRTMAX] = __SIGRTMIN; 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 + } 511 520 512 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 + } 513 525 for (host_sig = 1; host_sig < _NSIG; host_sig++) { 514 526 if (host_to_target_signal_table[host_sig] == 0) { 515 527 host_to_target_signal_table[host_sig] = host_sig; ··· 518 530 if (target_sig <= TARGET_NSIG) { 519 531 target_to_host_signal_table[target_sig] = host_sig; 520 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); 521 542 } 522 543 } 523 544 ··· 817 838 int host_sig; 818 839 int ret = 0; 819 840 841 + trace_signal_do_sigaction_guest(sig, TARGET_NSIG); 842 + 820 843 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) { 821 844 return -TARGET_EINVAL; 822 845 } ··· 847 870 848 871 /* we update the host linux signal state */ 849 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 + } 850 890 if (host_sig != SIGSEGV && host_sig != SIGBUS) { 851 891 sigfillset(&act1.sa_mask); 852 892 act1.sa_flags = SA_SIGINFO;
+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