On Mon, 2010-10-18 at 11:19 +0800, Li Zefan wrote:

> This is a dead loop:
> 
> trace_hcall_entry() -> trace_clock_global() -> trace_hcall_entry() ..
> 
> And this is a PPC specific bug. Hope some ppc guys will fix it?
> Or we kill trace_clock_global() if no one actually uses it..

trace_clock_global() is used by many. I use it (and recommend using it)
on boxes where the TSC is horribly out of sync, and the trace needs
synchronization between CPUs.

The trace_hcall_entry and exit has wrappers already. Just add recursion
protection there.

Perhaps something like this:

(Not compiled nor ran)

+static DEFINE_PER_CPU(hcall_trace_disable);
+
 void hcall_tracepoint_regfunc(void)
 {
        hcall_tracepoint_refcount++;
 }

 void hcall_tracepoint_unregfunc(void)
 {
        hcall_tracepoint_refcount--;
 }

+int __trace_disable_check(void)
+{
+       if (!hcall_tracepoint_refcount)
+               return 1;
+
+       if (get_cpu_var(hcall_trace_disable)) {
+               put_cpu_var(hcall_trace_disable);
+               return 1;
+       }
+
+       __get_cpu_var(hcall_trace_disable)++;
+
+       return 0;
+}
+
+void __trace_disable_put(void)
+{
+       __get_cpu_var(hcall_trace_disable)--;
+       put_cpu_var(hcall_trace_disable);
+}
+
 void __trace_hcall_entry(unsigned long opcode, unsigned long *args)
 {
+       int trace_disable;
+
+       if (__trace_disable_check())
+               return;
+
        trace_hcall_entry(opcode, args);
+       __trace_disable_put();
 }

 void __trace_hcall_exit(long opcode, unsigned long retval,
                        unsigned long *retbuf)
 {
+       if (__trace_disable_check())
+               return;
+
        trace_hcall_exit(opcode, retval, retbuf);
+       __trace_disable_put();
 }

-- Steve


_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to