trace kprot patch
Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index 2d14ae4..c9b97ac 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -96,6 +96,7 @@
{
long ret;
+ trace_printk("syscall: Enter from user\n");
enter_from_user_mode(regs, HT_PROTECT_SYSCALL);
instrumentation_begin();
@@ -299,11 +300,14 @@
local_irq_disable_exit_to_user();
exit_to_user_mode_prepare(regs, HT_PROTECT_SYSCALL);
instrumentation_end();
+ trace_printk("syscall: Entering exit_to_user_mode\n");
exit_to_user_mode();
+ trace_printk("syscall: Leaving exit_to_user_mode\n");
}
noinstr void irqentry_enter_from_user_mode(struct pt_regs *regs)
{
+ trace_printk("irq: Enter from user\n");
enter_from_user_mode(regs, HT_PROTECT_IRQ);
}
@@ -312,7 +316,9 @@
instrumentation_begin();
exit_to_user_mode_prepare(regs, HT_PROTECT_IRQ);
instrumentation_end();
+ trace_printk("irq: Entering exit_to_user_mode\n");
exit_to_user_mode();
+ trace_printk("irq: Entering exit_to_user_mode\n");
}
noinstr irqentry_state_t irqentry_enter(struct pt_regs *regs)
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index fbff25a..cd18de2 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -102,8 +102,10 @@
if (cpu != smp_processor_id()) {
/* Arch remote IPI send/receive backend aren't NMI safe */
WARN_ON_ONCE(in_nmi());
+ trace_printk("Queuing on cpu %d\n", cpu);
__smp_call_single_queue(cpu, &work->node.llist);
} else {
+ trace_printk("Queuing local\n");
__irq_work_queue_local(work);
}
preempt_enable();
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 508dbce..8ebb894 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5194,6 +5194,17 @@
*/
static void sched_core_irq_work(struct irq_work *work)
{
+ struct rq *rq;
+ int cpu;
+ cpu = smp_processor_id();
+ rq = cpu_rq(cpu);
+
+ WARN_ON_ONCE(!rq->pause_pending);
+
+ trace_printk("Entering irq work hnd\n");
+ trace_printk("Exit irq work hnd\n");
+
+ rq->pause_pending = false;
}
static inline void init_sched_core_irq_work(struct rq *rq)
@@ -5217,6 +5228,7 @@
bool restart = false;
struct rq *rq;
int cpu;
+ int loops = 0;
/* If arch doesn't define the TIF flag, don't do anything. */
if (!TIF_UNSAFE_RET)
@@ -5235,12 +5247,13 @@
preempt_disable();
local_irq_enable();
+ trace_printk("Enter wait\n");
/*
* Wait till the core of this HT is not in an unsafe state.
*
* Pair with raw_spin_lock/unlock() in sched_core_unsafe_enter/exit().
*/
- while (smp_load_acquire(&rq->core->core_unsafe_nest) > 0) {
+ while (smp_load_acquire(&rq->core->core_unsafe_nest) > 0 && loops++ < 100000000) {
cpu_relax();
if (READ_ONCE(current_thread_info()->flags) & ti_check) {
restart = true;
@@ -5252,6 +5265,11 @@
local_irq_disable();
preempt_enable();
+ trace_printk("Exit wait\n");
+
+ if (WARN_ON_ONCE(loops >= 100000000))
+ panic("excessive spinning\n");
+
ret:
if (!restart)
clear_tsk_thread_flag(current, TIF_UNSAFE_RET);
@@ -5303,6 +5321,11 @@
/* Count unsafe_enter() calls received without unsafe_exit() on this CPU. */
rq->core_this_unsafe_nest++;
+ trace_printk("enter: unsafe this nest now: %d\n", rq->core_this_unsafe_nest);
+ if (rq->core_this_unsafe_nest < 0) {
+ trace_printk("issue stop\n");
+ tracing_stop();
+ }
/*
* Should not nest: enter() should only pair with exit(). Both are done
@@ -5322,16 +5345,23 @@
* counter's smp_load_acquire() in sched_core_wait_till_safe().
*/
WRITE_ONCE(rq->core->core_unsafe_nest, rq->core->core_unsafe_nest + 1);
+ trace_printk("enter: unsafe nest now: %d\n", rq->core->core_unsafe_nest);
+ if (rq->core->core_unsafe_nest < 0) {
+ trace_printk("issue stop core-wide\n");
+ tracing_stop();
+ }
if (WARN_ON_ONCE(rq->core->core_unsafe_nest == UINT_MAX))
goto unlock;
if (irq_work_is_busy(&rq->core_irq_work)) {
+ WARN_ON_ONCE(!rq->pause_pending);
/*
* Do nothing more since we are in an IPI sent from another
* sibling to enforce safety. That sibling would have sent IPIs
* to all of the HTs.
*/
+ trace_printk("We are in IPI, do nothing more.\n");
goto unlock;
}
@@ -5339,8 +5369,10 @@
* If we are not the first ones on the core to enter core-wide unsafe
* state, do nothing.
*/
- if (rq->core->core_unsafe_nest > 1)
+ if (rq->core->core_unsafe_nest > 1) {
+ trace_printk("Inner core-wide nest.\n");
goto unlock;
+ }
/* Do nothing more if the core is not tagged. */
if (!rq->core->core_cookie)
@@ -5364,6 +5396,8 @@
* pending, no new IPIs are sent. This is Ok since the receiver
* would already be in the kernel, or on its way to it.
*/
+ trace_printk("Queuing irq_work on %d\n", i);
+ srq->pause_pending = true;
irq_work_queue_on(&srq->core_irq_work, i);
}
unlock:
@@ -5404,6 +5438,11 @@
goto ret;
rq->core_this_unsafe_nest--;
+ trace_printk("exit: unsafe this nest now: %d\n", rq->core_this_unsafe_nest);
+ if (rq->core_this_unsafe_nest < 0) {
+ trace_printk("issue stop\n");
+ tracing_stop();
+ }
/* enter() should be paired with exit() only. */
if (WARN_ON_ONCE(rq->core_this_unsafe_nest != 0))
@@ -5418,6 +5457,7 @@
WARN_ON_ONCE(!nest);
WRITE_ONCE(rq->core->core_unsafe_nest, nest - 1);
+ trace_printk("exit: unsafe nest now: %d\n", rq->core->core_unsafe_nest);
/*
* The raw_spin_unlock release semantics pairs with the nest counter's
* smp_load_acquire() in sched_core_wait_till_safe().
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 225654a..f97b91f 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1085,6 +1085,7 @@
struct rb_root core_tree;
struct irq_work core_irq_work; /* To force HT into kernel */
unsigned int core_this_unsafe_nest;
+ bool pause_pending;
/* shared state */
unsigned int core_task_seq;