traceoff    - Have the tracing instance tracing disabled after it is created.
                            traceprintk - Have trace_printk() write into this trace instance
                                          (note, "printk" and "trace_printk" can also be used)
-                                         Currently, traceprintk flag cannot be used for memory
-                                         mapped ring buffers as described below.
 
                                trace_instance=foo^traceoff^traceprintk,sched,irq
 
                        mix with events of the current boot (unless you are debugging a random crash
                        at boot up).
 
-                               reserve_mem=12M:4096:trace trace_instance=boot_map^traceoff@trace,sched,irq
+                               reserve_mem=12M:4096:trace trace_instance=boot_map^traceoff^traceprintk@trace,sched,irq
 
 
        trace_options=[option-list]
 
 
 static struct trace_array *printk_trace = &global_trace;
 
+static __always_inline bool printk_binsafe(struct trace_array *tr)
+{
+       /*
+        * The binary format of traceprintk can cause a crash if used
+        * by a buffer from another boot. Force the use of the
+        * non binary version of trace_printk if the trace_printk
+        * buffer is a boot mapped ring buffer.
+        */
+       return !(tr->flags & TRACE_ARRAY_FL_BOOT);
+}
+
 void trace_set_ring_buffer_expanded(struct trace_array *tr)
 {
        if (!tr)
  */
 int __trace_bputs(unsigned long ip, const char *str)
 {
-       struct trace_array *tr = printk_trace;
+       struct trace_array *tr = READ_ONCE(printk_trace);
        struct ring_buffer_event *event;
        struct trace_buffer *buffer;
        struct bputs_entry *entry;
        int size = sizeof(struct bputs_entry);
        int ret = 0;
 
+       if (!printk_binsafe(tr))
+               return __trace_puts(ip, str, strlen(str));
+
        if (!(tr->trace_flags & TRACE_ITER_PRINTK))
                return 0;
 
        struct trace_event_call *call = &event_bprint;
        struct ring_buffer_event *event;
        struct trace_buffer *buffer;
-       struct trace_array *tr = printk_trace;
+       struct trace_array *tr = READ_ONCE(printk_trace);
        struct bprint_entry *entry;
        unsigned int trace_ctx;
        char *tbuffer;
        int len = 0, size;
 
+       if (!printk_binsafe(tr))
+               return trace_vprintk(ip, fmt, args);
+
        if (unlikely(tracing_selftest_running || tracing_disabled))
                return 0;
 
                if (traceoff)
                        tracer_tracing_off(tr);
 
-               if (traceprintk) {
-                       /*
-                        * The binary format of traceprintk can cause a crash if used
-                        * by a buffer from another boot. Do not allow it for the
-                        * memory mapped ring buffers.
-                        */
-                       if (start)
-                               pr_warn("Tracing: WARNING: memory mapped ring buffers cannot be used for trace_printk\n");
-                       else
-                               printk_trace = tr;
-               }
+               if (traceprintk)
+                       printk_trace = tr;
 
-               /* Only allow non mapped buffers to be deleted */
-               if (!start)
+               /*
+                * If start is set, then this is a mapped buffer, and
+                * cannot be deleted by user space, so keep the reference
+                * to it.
+                */
+               if (start)
+                       tr->flags |= TRACE_ARRAY_FL_BOOT;
+               else
                        trace_array_put(tr);
 
                while ((tok = strsep(&curr_str, ","))) {
 
 {
        struct print_entry *field;
        struct trace_seq *s = &iter->seq;
+       unsigned long ip;
 
        trace_assign_type(field, iter->ent);
 
-       seq_print_ip_sym(s, field->ip, flags);
+       ip = field->ip + iter->tr->text_delta;
+
+       seq_print_ip_sym(s, ip, flags);
        trace_seq_printf(s, ": %s", field->buf);
 
        return trace_handle_return(s);