summaryrefslogtreecommitdiff
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2019-08-23 13:16:23 +0200
committerRichard Weinberger <richard@nod.at>2019-09-15 21:37:11 +0200
commit0dafcbe128d2af48919619f79332ef219b5e5514 (patch)
tree2f95274135b2485bb13dea1dcbe6d86c31b206e7 /arch/um/os-Linux
parent276d75c4aff3ade04f0f78769dd895a78f03edd9 (diff)
um: Implement TRACE_IRQFLAGS_SUPPORT
UML enables TRACE_IRQFLAGS_SUPPORT but doesn't actually implement it. It seems to have been added for lockdep support, but that can't actually really work well without IRQ flags tracing, as is also very noisily reported when enabling CONFIG_DEBUG_LOCKDEP. Implement it now. Fixes: 711553efa5b8 ("[PATCH] uml: declare in Kconfig our partial LOCKDEP support") Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/main.c2
-rw-r--r--arch/um/os-Linux/sigio.c6
-rw-r--r--arch/um/os-Linux/signal.c44
-rw-r--r--arch/um/os-Linux/skas/process.c12
4 files changed, 42 insertions, 22 deletions
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index f1fee2b91239..6d098e712839 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -170,7 +170,7 @@ int __init main(int argc, char **argv, char **envp)
* that they won't be delivered after the exec, when
* they are definitely not expected.
*/
- unblock_signals();
+ unblock_signals_trace();
os_info("\n");
/* Reboot */
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 46e762f926eb..21b226aa1041 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -132,7 +132,7 @@ static void update_thread(void)
int n;
char c;
- flags = set_signals(0);
+ flags = set_signals_trace(0);
CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c)));
if (n != sizeof(c)) {
printk(UM_KERN_ERR "update_thread : write failed, err = %d\n",
@@ -147,7 +147,7 @@ static void update_thread(void)
goto fail;
}
- set_signals(flags);
+ set_signals_trace(flags);
return;
fail:
/* Critical section start */
@@ -161,7 +161,7 @@ static void update_thread(void)
close(write_sigio_fds[0]);
close(write_sigio_fds[1]);
/* Critical section end */
- set_signals(flags);
+ set_signals_trace(flags);
}
int add_sigio_fd(int fd)
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 4cd88b5b9006..bde54c4a27da 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -43,7 +43,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
/* enable signals if sig isn't IRQ signal */
if ((sig != SIGIO) && (sig != SIGWINCH))
- unblock_signals();
+ unblock_signals_trace();
(*sig_info[sig])(sig, si, &r);
@@ -76,11 +76,11 @@ void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
return;
}
- block_signals();
+ block_signals_trace();
sig_handler_common(sig, si, mc);
- set_signals(enabled);
+ set_signals_trace(enabled);
}
static void timer_real_alarm_handler(mcontext_t *mc)
@@ -104,7 +104,7 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
return;
}
- block_signals();
+ block_signals_trace();
signals_active |= SIGALRM_MASK;
@@ -112,7 +112,7 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
signals_active &= ~SIGALRM_MASK;
- set_signals(enabled);
+ set_signals_trace(enabled);
}
void deliver_alarm(void) {
@@ -253,6 +253,8 @@ void unblock_signals(void)
if (signals_enabled == 1)
return;
+ signals_enabled = 1;
+
/*
* We loop because the IRQ handler returns with interrupts off. So,
* interrupts may have arrived and we need to re-enable them and
@@ -262,12 +264,9 @@ void unblock_signals(void)
/*
* Save and reset save_pending after enabling signals. This
* way, signals_pending won't be changed while we're reading it.
- */
- signals_enabled = 1;
-
- /*
+ *
* Setting signals_enabled and reading signals_pending must
- * happen in this order.
+ * happen in this order, so have the barrier here.
*/
barrier();
@@ -280,10 +279,13 @@ void unblock_signals(void)
/*
* We have pending interrupts, so disable signals, as the
* handlers expect them off when they are called. They will
- * be enabled again above.
+ * be enabled again above. We need to trace this, as we're
+ * expected to be enabling interrupts already, but any more
+ * tracing that happens inside the handlers we call for the
+ * pending signals will mess up the tracing state.
*/
-
signals_enabled = 0;
+ um_trace_signals_off();
/*
* Deal with SIGIO first because the alarm handler might
@@ -306,6 +308,9 @@ void unblock_signals(void)
if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
return;
+ /* Re-enable signals and trace that we're doing so. */
+ um_trace_signals_on();
+ signals_enabled = 1;
}
}
@@ -328,6 +333,21 @@ int set_signals(int enable)
return ret;
}
+int set_signals_trace(int enable)
+{
+ int ret;
+ if (signals_enabled == enable)
+ return enable;
+
+ ret = signals_enabled;
+ if (enable)
+ unblock_signals_trace();
+ else
+ block_signals_trace();
+
+ return ret;
+}
+
int os_is_signal_stack(void)
{
stack_t ss;
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index df4a985716eb..095bff707bb3 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -425,9 +425,9 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
case SIGBUS:
case SIGFPE:
case SIGWINCH:
- block_signals();
+ block_signals_trace();
(*sig_info[sig])(sig, (struct siginfo *)&si, regs);
- unblock_signals();
+ unblock_signals_trace();
break;
default:
printk(UM_KERN_ERR "userspace - child stopped "
@@ -625,10 +625,10 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
cb_arg = arg;
cb_back = &here;
- block_signals();
+ block_signals_trace();
if (UML_SETJMP(&here) == 0)
UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
- unblock_signals();
+ unblock_signals_trace();
cb_proc = NULL;
cb_arg = NULL;
@@ -637,13 +637,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
void halt_skas(void)
{
- block_signals();
+ block_signals_trace();
UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
}
void reboot_skas(void)
{
- block_signals();
+ block_signals_trace();
UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
}