Module: xenomai-forge
Branch: next
Commit: b29d078a6f47a3bcfd432680e90a055a49ae29c4
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=b29d078a6f47a3bcfd432680e90a055a49ae29c4

Author: Philippe Gerum <r...@xenomai.org>
Date:   Fri Sep  6 11:59:36 2013 +0200

lib/cobalt, cobalt/shadow: allow user-space to issue serial debug output

In desperate cases, it may be convenient to write raw debug output
directly to the console UART from the current domain, without any
intermediate buffering.

This internal debug service is available from the inner Cobalt
interface as __cobalt_serial_debug(const char *fmt, ...). The
formatted output is directed to __ipipe_serial_debug().

NOTE: for the output to take place, the support for serial console and
CONFIG_IPIPE_DEBUG must be enabled in the kernel.

---

 include/cobalt/uapi/asm-generic/syscall.h |    1 +
 kernel/cobalt/shadow.c                    |   22 +++++++++++++++++++++-
 lib/cobalt/internal.c                     |   20 ++++++++++++++++++++
 lib/cobalt/internal.h                     |    2 ++
 4 files changed, 44 insertions(+), 1 deletions(-)

diff --git a/include/cobalt/uapi/asm-generic/syscall.h 
b/include/cobalt/uapi/asm-generic/syscall.h
index 4eb95d9..056fc6c 100644
--- a/include/cobalt/uapi/asm-generic/syscall.h
+++ b/include/cobalt/uapi/asm-generic/syscall.h
@@ -34,6 +34,7 @@
 #define sc_nucleus_current_info  7     /* r = xnshadow_current_info(&info) */
 #define sc_nucleus_mayday        8     /* request mayday fixup */
 #define sc_nucleus_backtrace     9     /* collect backtrace (relax tracing) */
+#define sc_nucleus_serialdbg     10    /* output to serial console 
(__ipipe_serial_debug()) */
 
 struct xnbindreq {
        int feat_req;           /* Features userland requires. */
diff --git a/kernel/cobalt/shadow.c b/kernel/cobalt/shadow.c
index ab72f70..2fb0b42 100644
--- a/kernel/cobalt/shadow.c
+++ b/kernel/cobalt/shadow.c
@@ -1587,13 +1587,32 @@ static int xnshadow_sys_current_info(struct 
xnthread_info __user *u_info)
        return __xn_safe_copy_to_user(u_info, &info, sizeof(*u_info));
 }
 
-static int xnshadow_sys_backtrace(int nr, unsigned long *u_backtrace,
+static int xnshadow_sys_backtrace(int nr, unsigned long __user *u_backtrace,
                                  int reason)
 {
        xndebug_trace_relax(nr, u_backtrace, reason);
        return 0;
 }
 
+static int xnshadow_sys_serialdbg(const char __user *u_msg, int len)
+{
+       char buf[128];
+       int n;
+
+       while (len > 0) {
+               n = len;
+               if (n > sizeof(buf))
+                       n = sizeof(buf);
+               if (__xn_safe_copy_from_user(buf, u_msg, n))
+                       return -EFAULT;
+               __ipipe_serial_debug("%.*s", n, buf);
+               u_msg += n;
+               len -= n;
+       }
+
+       return 0;
+}
+
 static void post_ppd_release(struct xnheap *h)
 {
        struct xnsys_ppd *p = container_of(h, struct xnsys_ppd, sem_heap);
@@ -1712,6 +1731,7 @@ static struct xnsyscall user_syscalls[] = {
        SKINCALL_DEF(sc_nucleus_current_info, xnshadow_sys_current_info, 
shadow),
        SKINCALL_DEF(sc_nucleus_mayday, xnshadow_sys_mayday, oneway),
        SKINCALL_DEF(sc_nucleus_backtrace, xnshadow_sys_backtrace, current),
+       SKINCALL_DEF(sc_nucleus_serialdbg, xnshadow_sys_serialdbg, any),
 };
 
 static struct xnpersonality user_personality = {
diff --git a/lib/cobalt/internal.c b/lib/cobalt/internal.c
index 10b2ce1..603791b 100644
--- a/lib/cobalt/internal.c
+++ b/lib/cobalt/internal.c
@@ -28,6 +28,7 @@
 #include <unistd.h>
 #include <signal.h>
 #include <errno.h>
+#include <stdarg.h>
 #include <pthread.h>
 #include <asm/xenomai/syscall.h>
 #include "current.h"
@@ -60,6 +61,25 @@ void ___cobalt_prefault(void *p, size_t len)
        } while (_p < end);
 }
 
+int __cobalt_serial_debug(const char *fmt, ...)
+{
+       char msg[128];
+       va_list ap;
+       int n, ret;
+
+       /*
+        * The serial debug output handler disables hw IRQs while
+        * writing to the UART console port, so the message ought to
+        * be reasonably short.
+        */
+       va_start(ap, fmt);
+       n = vsnprintf(msg, sizeof(msg), fmt, ap);
+       ret = XENOMAI_SYSCALL2(sc_nucleus_serialdbg, msg, n);
+       va_end(ap);
+
+       return ret;
+}
+
 size_t cobalt_get_stacksize(size_t size)
 {
        static const size_t default_size = PTHREAD_STACK_MIN * 4;
diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
index 75ce011..6a32f3f 100644
--- a/lib/cobalt/internal.h
+++ b/lib/cobalt/internal.h
@@ -65,6 +65,8 @@ void __cobalt_thread_harden(void);
 int __cobalt_thread_stat(pid_t pid,
                         struct cobalt_threadstat *stat);
 
+int __cobalt_serial_debug(const char *fmt, ...);
+
 int cobalt_monitor_init(cobalt_monitor_t *mon, int flags);
 
 int cobalt_monitor_destroy(cobalt_monitor_t *mon);


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to