[Xenomai] RTDM serial illicit call from head domain 'Xenomai'

Greg Gallagher greg at embeddedgreg.com
Sun May 13 19:37:25 CEST 2018


I can take a look at it this week. I'd like to trace through some of the drivers to get a better understanding of when or if they cause a domain switch.

  Original Message  
From: rpm at xenomai.org
Sent: May 13, 2018 10:16 AM
To: greg at embeddedgreg.com; steve at freyder.net
Cc: xenomai at xenomai.org
Subject: Re: [Xenomai] RTDM serial illicit call from head domain 'Xenomai'

On 05/13/2018 07:02 AM, Greg Gallagher wrote:
> I won't say the driver is improperly written, this ioctl call may not
> be expected to be used in a low latency situation.  Some code maybe
> expected to be called at initialization time and then never again so
> it doesn't impact RT operation.  The rt_imx_uart driver is part of the
> Xenomai code base, I'm not 100% sure if this functions shouldn't be
> called from an RTDM driver or if the author needs to be aware they
> could just introduce latency when used in the rt context.
> These panics aren't kernel or driver errors, we are creating them on
> purpose to try to track down domain switches which could impact
> latency.  So as long as your latency number are acceptable you don't
> need to enable the debug flag to track down domain switches and these
> panics can be ignored for now.
>

I would recommend to fix the situation asap in the RTDM driver though
[1], because this may actually lead to crashes.

Those debug checks trap invalid re-entries of the regular kernel code
from the co-kernel (rt) context. This is an illustration of a possible
scenario involving such a bad re-entry:

   /* regular kernel context */
   spin_lock_irqsave(&lock, flags);
      <IRQx received: rt handler installed>
         handle_rt_event();
            <context_switch>
            /* rt thread context. */
            ioctl(imx_fd, ...);
               /* invalid call of regular kernel code */
               spin_lock_irqsave(&lock, flags);
               <DEADLOCK>

IOW, we have to keep in mind that any IRQ routed to the real-time
co-kernel may preempt most of the regular kernel code, even though the
latter has [only virtually] disabled interrupts: making this event
possible is the purpose of the interrupt pipeline. The restriction which
is paired to this feature is that we may not re-enter the preempted
code, because the logic there still rightfully assumes this may not happen.

As a matter of fact, the interrupt pipeline potentially turns any device
IRQ as a NMI from the standpoint of a Linux kernel. In addition, the
co-kernel has its own scheduler to manage rt threads. In short, rt
activities are not serialized by the regular kernel locking scheme.

[1]
diff --git a/kernel/drivers/serial/rt_imx_uart.c
b/kernel/drivers/serial/rt_imx_uart.c
index 61836ae09..1aec219b7 100644
--- a/kernel/drivers/serial/rt_imx_uart.c
+++ b/kernel/drivers/serial/rt_imx_uart.c
@@ -963,6 +963,13 @@ static int rt_imx_uart_ioctl(struct rtdm_fd *fd,
struct rtser_config config_buf;
uint64_t *hist_buf = NULL;

+	/*
+	* We may call regular kernel services ahead, ask for
+	* re-entering secondary mode if need be.
+	*/
+	if (rtdm_in_rt_context())
+	return -ENOSYS;
+
config = (struct rtser_config *)arg;

if (rtdm_fd_is_user(fd)) {
@@ -984,13 +991,6 @@ static int rt_imx_uart_ioctl(struct rtdm_fd *fd,
return -EINVAL;

if (config->config_mask & RTSER_SET_TIMESTAMP_HISTORY) {
-	/*
-	* Reflect the call to non-RT as we will likely
-	* allocate or free the buffer.
-	*/
-	if (rtdm_in_rt_context())
-	return -ENOSYS;
-
if (config->timestamp_history &
RTSER_RX_TIMESTAMP_HISTORY)
hist_buf = kmalloc(IN_BUFFER_SIZE *
@@ -1000,7 +1000,8 @@ static int rt_imx_uart_ioctl(struct rtdm_fd *fd,

rt_imx_uart_set_config(ctx, config, &hist_buf);

-	kfree(hist_buf);
+	if (hist_buf)
+	kfree(hist_buf);
break;
}

-- 
Philippe.


More information about the Xenomai mailing list