Re: [Xenomai-core] More on Shared interrupts

2006-02-16 Thread Anders Blomdell

Anders Blomdell wrote:
For the last few days, I have tried to figure out a good way to share 
interrupts between RT and non-RT domains. This has included looking 
through Dmitry's patch, correcting bugs and testing what is possible in 
my specific case. I'll therefore try to summarize at least a few of my 
thoughts.


1. When looking through Dmitry's patch I get the impression that the 
iack handler has very little to do with each interrupt (the test 
'prev->iack != intr->iack' is a dead giveaway), but is more of a 
domain-specific function (or perhaps even just a placeholder for the 
hijacked Linux ack-function).



2. Somewhat inspired by the figure in "Life with Adeos", I have 
identified the following cases:


  irq K  | --- | ---o|   // Linux only
  ...
  irq L  | ---o| |   // RT-only
  ...
  irq M  | ---o--- | ---o|   // Shared between domains
  ...
  irq N  | ---o---o--- | |   // Shared inside single domain
  ...
  irq O  | ---o---o--- | ---o|   // Shared between and inside single 
domain


Xenomai currently handles the K & L cases, Dmitrys patch addresses the N 
case, with edge triggered interrupts the M (and O after Dmitry's patch) 
case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE 
from the interrupt handler, for level triggered interrupt the M and O 
cases can't be handled.


If one looks more closely at the K case (Linux only interrupt), it works 
by when an interrupt occurs, the call to irq_end is postponed until the 
Linux interrupt handler has run, i.e. further interrupts are disabled. 
This can be seen as a lazy version of Philippe's idea of disabling all 
non-RT interrupts until the RT-domain is idle, i.e. the interrupt is 
disabled only if it indeed occurs.


If this idea should be generalized to the M (and O) case(s), one can't 
rely on postponing the irq_end call (since the interrupt is still needed 
in the RT-domain), but has to rely on some function that disables all 
non-RT hardware that generates interrupts on that irq-line; such a 
function naturally has to have intimate knowledge of all hardware that 
can generate interrupts in order to be able to disable those interrupt 
sources that are non-RT.


If we then take Jan's observation about the many (Linux-only) interrupts 
present in an ordinary PC and add it to Philippe's idea of disabling all 
non-RT interrupts while executing in the RT-domain, I think that the 
following is a workable (and fairly efficient) way of handling this:


Add hardware dependent enable/disable functions, where the enable is 
called just before normal execution in a domain starts (i.e. when 
playing back interrupts, the disable is still in effect), and disable is 
called when normal domain execution end. This does effectively handle 
the K case above, with the added benefit that NO non-RT interrupts will 
occur during RT execution.


In the 8259 case, the disable function could look something like:

  domain_irq_disable(uint irqmask) {
if (irqmask & 0xff00 != 0xff00) {
  irqmask &= ~0x0004; // Cascaded interrupt is still needed
  outb(irqmask >> 8, PIC_SLAVE_IMR);
}
outb(irqmask, PIC_MASTER_IMR);
  }

If we should extend this to handle the M (and O) case(s), the disable 
function could look like:


  domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
int i;

for (i = 0 ; i < MAX_IRQ ; i++) {
  if (shared[i]) {
shared_irq_t *next = shared[i];
irqmask &= ~(1next;
}
  }
}
if (irqmask & 0xff00 != 0xff00) {
  irqmask &= ~0x0004; // Cascaded interrupt is still needed
  outb(irqmask >> 8, PIC_SLAVE_IMR);
}
outb(irqmask, PIC_MASTER_IMR);
  }

An obvious optimization of the above scheme, is to never call the 
disable (or enable) function for the RT-domain, since there all 
interrupt processing is protected by the hardware.


Comments, anyone?


OK, I have finally got around to do some interrupt timing tests on a PrPMC800 
(450 MHz PowerPC/G4)  with the following interrupt sources:


  3: 10 Khz watchdog interrupt (Linux)
 10: 100 Mbit/s ethernet (Linux)
 16: mailbox interrupt (RT) + UART (Linux)

I have measured interrupt latency, task latency (time from interrupt until a 
task signalled from interrupt handler has started) and the semaphore latency 
(time from task semaphore is signalled until task has started).


I have tested 4 different ways of handling shared Linux/RT interrupts:

  1. When UART interrupt occurs, disable further UART interrupts, signal low
 priority UART reenable task, return XN_ISR_ENABLE | XN_ISR_CHAINED.
 In low priority UART reenable task, reenable UART when Linux has handled
 the interrupt.

  2. Disable UART interrupts, and poll them at 1kHz from low priority RT task,
 and rthal_irq_host_pend them as they occur.

  3. Modified Xenomai, where non-RT interrupts are disabled when entering
 the RT domain, and enabled when entering th

Re: [Xenomai-core] More on Shared interrupts

2006-02-16 Thread Anders Blomdell

Anders Blomdell wrote:
For the last few days, I have tried to figure out a good way to share 
interrupts between RT and non-RT domains. This has included looking 
through Dmitry's patch, correcting bugs and testing what is possible in 
my specific case. I'll therefore try to summarize at least a few of my 
thoughts.


1. When looking through Dmitry's patch I get the impression that the 
iack handler has very little to do with each interrupt (the test 
'prev->iack != intr->iack' is a dead giveaway), but is more of a 
domain-specific function (or perhaps even just a placeholder for the 
hijacked Linux ack-function).



2. Somewhat inspired by the figure in "Life with Adeos", I have 
identified the following cases:


  irq K  | --- | ---o|   // Linux only
  ...
  irq L  | ---o| |   // RT-only
  ...
  irq M  | ---o--- | ---o|   // Shared between domains
  ...
  irq N  | ---o---o--- | |   // Shared inside single domain
  ...
  irq O  | ---o---o--- | ---o|   // Shared between and inside single 
domain


Xenomai currently handles the K & L cases, Dmitrys patch addresses the N 
case, with edge triggered interrupts the M (and O after Dmitry's patch) 
case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE 
from the interrupt handler, for level triggered interrupt the M and O 
cases can't be handled.


If one looks more closely at the K case (Linux only interrupt), it works 
by when an interrupt occurs, the call to irq_end is postponed until the 
Linux interrupt handler has run, i.e. further interrupts are disabled. 
This can be seen as a lazy version of Philippe's idea of disabling all 
non-RT interrupts until the RT-domain is idle, i.e. the interrupt is 
disabled only if it indeed occurs.


If this idea should be generalized to the M (and O) case(s), one can't 
rely on postponing the irq_end call (since the interrupt is still needed 
in the RT-domain), but has to rely on some function that disables all 
non-RT hardware that generates interrupts on that irq-line; such a 
function naturally has to have intimate knowledge of all hardware that 
can generate interrupts in order to be able to disable those interrupt 
sources that are non-RT.


If we then take Jan's observation about the many (Linux-only) interrupts 
present in an ordinary PC and add it to Philippe's idea of disabling all 
non-RT interrupts while executing in the RT-domain, I think that the 
following is a workable (and fairly efficient) way of handling this:


Add hardware dependent enable/disable functions, where the enable is 
called just before normal execution in a domain starts (i.e. when 
playing back interrupts, the disable is still in effect), and disable is 
called when normal domain execution end. This does effectively handle 
the K case above, with the added benefit that NO non-RT interrupts will 
occur during RT execution.


In the 8259 case, the disable function could look something like:

  domain_irq_disable(uint irqmask) {
if (irqmask & 0xff00 != 0xff00) {
  irqmask &= ~0x0004; // Cascaded interrupt is still needed
  outb(irqmask >> 8, PIC_SLAVE_IMR);
}
outb(irqmask, PIC_MASTER_IMR);
  }

If we should extend this to handle the M (and O) case(s), the disable 
function could look like:


  domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
int i;

for (i = 0 ; i < MAX_IRQ ; i++) {
  if (shared[i]) {
shared_irq_t *next = shared[i];
irqmask &= ~(1next;
}
  }
}
if (irqmask & 0xff00 != 0xff00) {
  irqmask &= ~0x0004; // Cascaded interrupt is still needed
  outb(irqmask >> 8, PIC_SLAVE_IMR);
}
outb(irqmask, PIC_MASTER_IMR);
  }

An obvious optimization of the above scheme, is to never call the 
disable (or enable) function for the RT-domain, since there all 
interrupt processing is protected by the hardware.


Comments, anyone?


OK, I have finally got around to do some interrupt timing tests on a PrPMC800 
(450 MHz PowerPC/G4)  with the following interrupt sources:


  3: 10 Khz watchdog interrupt (Linux)
 10: 100 Mbit/s ethernet (Linux)
 16: mailbox interrupt (RT) + UART (Linux)

I have measured interrupt latency, task latency (time from interrupt until a 
task signalled from interrupt handler has started) and the semaphore latency 
(time from task semaphore is signalled until task has started).


I have tested 4 different ways of handling shared Linux/RT interrupts:

  1. When UART interrupt occurs, disable further UART interrupts, signal low
 priority UART reenable task, return XN_ISR_ENABLE | XN_ISR_CHAINED.
 In low priority UART reenable task, reenable UART when Linux has handled
 the interrupt.

  2. Disable UART interrupts, and poll them at 1kHz from low priority RT task,
 and rthal_irq_host_pend them as they occur.

  3. Modified Xenomai, where non-RT interrupts are disabled when entering
 the RT domain, and enabled when entering th

Re: [Xenomai-core] More on Shared interrupts

2006-02-10 Thread Anders Blomdell

Jan Kiszka wrote:

Anders Blomdell wrote:


For the last few days, I have tried to figure out a good way to share
interrupts between RT and non-RT domains. This has included looking
through Dmitry's patch, correcting bugs and testing what is possible in
my specific case. I'll therefore try to summarize at least a few of my
thoughts.

1. When looking through Dmitry's patch I get the impression that the
iack handler has very little to do with each interrupt (the test
'prev->iack != intr->iack' is a dead giveaway), but is more of a
domain-specific function (or perhaps even just a placeholder for the
hijacked Linux ack-function).


2. Somewhat inspired by the figure in "Life with Adeos", I have
identified the following cases:

 irq K  | --- | ---o|   // Linux only
 ...
 irq L  | ---o| |   // RT-only
 ...
 irq M  | ---o--- | ---o|   // Shared between domains
 ...
 irq N  | ---o---o--- | |   // Shared inside single domain
 ...
 irq O  | ---o---o--- | ---o|   // Shared between and inside single
domain

Xenomai currently handles the K & L cases, Dmitrys patch addresses the N
case, with edge triggered interrupts the M (and O after Dmitry's patch)
case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE
from the interrupt handler, for level triggered interrupt the M and O
cases can't be handled.



I guess you mean it the other way around: for the edge-triggered
cross-domain case we would actually have to loop over both the RT and
the Linux handlers until we are sure, that the IRQ line was released once.

I obviously has misunderstood edge triggered :-(


Luckily, I never saw such a scenario which were unavoidable (it hits you
with ISA hardware which tend to have nice IRQ jumpers or other means -
it's just that you often cannot divide several controllers on the same
extension card IRQ-wise apart).



If one looks more closely at the K case (Linux only interrupt), it works
by when an interrupt occurs, the call to irq_end is postponed until the
Linux interrupt handler has run, i.e. further interrupts are disabled.
This can be seen as a lazy version of Philippe's idea of disabling all
non-RT interrupts until the RT-domain is idle, i.e. the interrupt is
disabled only if it indeed occurs.

If this idea should be generalized to the M (and O) case(s), one can't
rely on postponing the irq_end call (since the interrupt is still needed
in the RT-domain), but has to rely on some function that disables all
non-RT hardware that generates interrupts on that irq-line; such a
function naturally has to have intimate knowledge of all hardware that
can generate interrupts in order to be able to disable those interrupt
sources that are non-RT.

If we then take Jan's observation about the many (Linux-only) interrupts
present in an ordinary PC and add it to Philippe's idea of disabling all
non-RT interrupts while executing in the RT-domain, I think that the
following is a workable (and fairly efficient) way of handling this:

Add hardware dependent enable/disable functions, where the enable is
called just before normal execution in a domain starts (i.e. when
playing back interrupts, the disable is still in effect), and disable is
called when normal domain execution end. This does effectively handle
the K case above, with the added benefit that NO non-RT interrupts will
occur during RT execution.

In the 8259 case, the disable function could look something like:

 domain_irq_disable(uint irqmask) {
   if (irqmask & 0xff00 != 0xff00) {
 irqmask &= ~0x0004; // Cascaded interrupt is still needed
 outb(irqmask >> 8, PIC_SLAVE_IMR);
   }
   outb(irqmask, PIC_MASTER_IMR);
 }

If we should extend this to handle the M (and O) case(s), the disable
function could look like:

 domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
   int i;

   for (i = 0 ; i < MAX_IRQ ; i++) {
 if (shared[i]) {
   shared_irq_t *next = shared[i];
   irqmask &= ~(1next;
   }



This obviously means that all non-RT IRQ handlers sharing a line with
the RT domain would have to be registered in that shared[]-list. This
gets close to my old suggestion. Just raises the question how to
organise these interface, both on the RT and the Linux side.



 }
   }
   if (irqmask & 0xff00 != 0xff00) {
 irqmask &= ~0x0004; // Cascaded interrupt is still needed
 outb(irqmask >> 8, PIC_SLAVE_IMR);
   }
   outb(irqmask, PIC_MASTER_IMR);
 }

An obvious optimization of the above scheme, is to never call the
disable (or enable) function for the RT-domain, since there all
interrupt processing is protected by the hardware.



Another point is to avoid that looping over disable handlers for IRQs of
the K case. Otherwise, too many device-specific disable handlers had to
be implemented even if only a single Linux device hogs a RT IRQ.
You only have to spin over those IRQ that are actually shared across domains 
(probably just a few in most cases), those IRQ that s

Re: [Xenomai-core] More on Shared interrupts

2006-02-10 Thread Anders Blomdell

Jan Kiszka wrote:

Anders Blomdell wrote:


For the last few days, I have tried to figure out a good way to share
interrupts between RT and non-RT domains. This has included looking
through Dmitry's patch, correcting bugs and testing what is possible in
my specific case. I'll therefore try to summarize at least a few of my
thoughts.

1. When looking through Dmitry's patch I get the impression that the
iack handler has very little to do with each interrupt (the test
'prev->iack != intr->iack' is a dead giveaway), but is more of a
domain-specific function (or perhaps even just a placeholder for the
hijacked Linux ack-function).


2. Somewhat inspired by the figure in "Life with Adeos", I have
identified the following cases:

 irq K  | --- | ---o|   // Linux only
 ...
 irq L  | ---o| |   // RT-only
 ...
 irq M  | ---o--- | ---o|   // Shared between domains
 ...
 irq N  | ---o---o--- | |   // Shared inside single domain
 ...
 irq O  | ---o---o--- | ---o|   // Shared between and inside single
domain

Xenomai currently handles the K & L cases, Dmitrys patch addresses the N
case, with edge triggered interrupts the M (and O after Dmitry's patch)
case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE
from the interrupt handler, for level triggered interrupt the M and O
cases can't be handled.



I guess you mean it the other way around: for the edge-triggered
cross-domain case we would actually have to loop over both the RT and
the Linux handlers until we are sure, that the IRQ line was released once.

I obviously has misunderstood edge triggered :-(


Luckily, I never saw such a scenario which were unavoidable (it hits you
with ISA hardware which tend to have nice IRQ jumpers or other means -
it's just that you often cannot divide several controllers on the same
extension card IRQ-wise apart).



If one looks more closely at the K case (Linux only interrupt), it works
by when an interrupt occurs, the call to irq_end is postponed until the
Linux interrupt handler has run, i.e. further interrupts are disabled.
This can be seen as a lazy version of Philippe's idea of disabling all
non-RT interrupts until the RT-domain is idle, i.e. the interrupt is
disabled only if it indeed occurs.

If this idea should be generalized to the M (and O) case(s), one can't
rely on postponing the irq_end call (since the interrupt is still needed
in the RT-domain), but has to rely on some function that disables all
non-RT hardware that generates interrupts on that irq-line; such a
function naturally has to have intimate knowledge of all hardware that
can generate interrupts in order to be able to disable those interrupt
sources that are non-RT.

If we then take Jan's observation about the many (Linux-only) interrupts
present in an ordinary PC and add it to Philippe's idea of disabling all
non-RT interrupts while executing in the RT-domain, I think that the
following is a workable (and fairly efficient) way of handling this:

Add hardware dependent enable/disable functions, where the enable is
called just before normal execution in a domain starts (i.e. when
playing back interrupts, the disable is still in effect), and disable is
called when normal domain execution end. This does effectively handle
the K case above, with the added benefit that NO non-RT interrupts will
occur during RT execution.

In the 8259 case, the disable function could look something like:

 domain_irq_disable(uint irqmask) {
   if (irqmask & 0xff00 != 0xff00) {
 irqmask &= ~0x0004; // Cascaded interrupt is still needed
 outb(irqmask >> 8, PIC_SLAVE_IMR);
   }
   outb(irqmask, PIC_MASTER_IMR);
 }

If we should extend this to handle the M (and O) case(s), the disable
function could look like:

 domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
   int i;

   for (i = 0 ; i < MAX_IRQ ; i++) {
 if (shared[i]) {
   shared_irq_t *next = shared[i];
   irqmask &= ~(1next;
   }



This obviously means that all non-RT IRQ handlers sharing a line with
the RT domain would have to be registered in that shared[]-list. This
gets close to my old suggestion. Just raises the question how to
organise these interface, both on the RT and the Linux side.



 }
   }
   if (irqmask & 0xff00 != 0xff00) {
 irqmask &= ~0x0004; // Cascaded interrupt is still needed
 outb(irqmask >> 8, PIC_SLAVE_IMR);
   }
   outb(irqmask, PIC_MASTER_IMR);
 }

An obvious optimization of the above scheme, is to never call the
disable (or enable) function for the RT-domain, since there all
interrupt processing is protected by the hardware.



Another point is to avoid that looping over disable handlers for IRQs of
the K case. Otherwise, too many device-specific disable handlers had to
be implemented even if only a single Linux device hogs a RT IRQ.
You only have to spin over those IRQ that are actually shared across domains 
(probably just a few in most cases), those IRQ that s

Re: [Xenomai-core] More on Shared interrupts

2006-02-09 Thread Jan Kiszka
Anders Blomdell wrote:
> For the last few days, I have tried to figure out a good way to share
> interrupts between RT and non-RT domains. This has included looking
> through Dmitry's patch, correcting bugs and testing what is possible in
> my specific case. I'll therefore try to summarize at least a few of my
> thoughts.
> 
> 1. When looking through Dmitry's patch I get the impression that the
> iack handler has very little to do with each interrupt (the test
> 'prev->iack != intr->iack' is a dead giveaway), but is more of a
> domain-specific function (or perhaps even just a placeholder for the
> hijacked Linux ack-function).
> 
> 
> 2. Somewhat inspired by the figure in "Life with Adeos", I have
> identified the following cases:
> 
>   irq K  | --- | ---o|   // Linux only
>   ...
>   irq L  | ---o| |   // RT-only
>   ...
>   irq M  | ---o--- | ---o|   // Shared between domains
>   ...
>   irq N  | ---o---o--- | |   // Shared inside single domain
>   ...
>   irq O  | ---o---o--- | ---o|   // Shared between and inside single
> domain
> 
> Xenomai currently handles the K & L cases, Dmitrys patch addresses the N
> case, with edge triggered interrupts the M (and O after Dmitry's patch)
> case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE
> from the interrupt handler, for level triggered interrupt the M and O
> cases can't be handled.

I guess you mean it the other way around: for the edge-triggered
cross-domain case we would actually have to loop over both the RT and
the Linux handlers until we are sure, that the IRQ line was released once.

Luckily, I never saw such a scenario which were unavoidable (it hits you
with ISA hardware which tend to have nice IRQ jumpers or other means -
it's just that you often cannot divide several controllers on the same
extension card IRQ-wise apart).

> 
> If one looks more closely at the K case (Linux only interrupt), it works
> by when an interrupt occurs, the call to irq_end is postponed until the
> Linux interrupt handler has run, i.e. further interrupts are disabled.
> This can be seen as a lazy version of Philippe's idea of disabling all
> non-RT interrupts until the RT-domain is idle, i.e. the interrupt is
> disabled only if it indeed occurs.
> 
> If this idea should be generalized to the M (and O) case(s), one can't
> rely on postponing the irq_end call (since the interrupt is still needed
> in the RT-domain), but has to rely on some function that disables all
> non-RT hardware that generates interrupts on that irq-line; such a
> function naturally has to have intimate knowledge of all hardware that
> can generate interrupts in order to be able to disable those interrupt
> sources that are non-RT.
> 
> If we then take Jan's observation about the many (Linux-only) interrupts
> present in an ordinary PC and add it to Philippe's idea of disabling all
> non-RT interrupts while executing in the RT-domain, I think that the
> following is a workable (and fairly efficient) way of handling this:
> 
> Add hardware dependent enable/disable functions, where the enable is
> called just before normal execution in a domain starts (i.e. when
> playing back interrupts, the disable is still in effect), and disable is
> called when normal domain execution end. This does effectively handle
> the K case above, with the added benefit that NO non-RT interrupts will
> occur during RT execution.
> 
> In the 8259 case, the disable function could look something like:
> 
>   domain_irq_disable(uint irqmask) {
> if (irqmask & 0xff00 != 0xff00) {
>   irqmask &= ~0x0004; // Cascaded interrupt is still needed
>   outb(irqmask >> 8, PIC_SLAVE_IMR);
> }
> outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> If we should extend this to handle the M (and O) case(s), the disable
> function could look like:
> 
>   domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
> int i;
> 
> for (i = 0 ; i < MAX_IRQ ; i++) {
>   if (shared[i]) {
> shared_irq_t *next = shared[i];
> irqmask &= ~(1< while (next) {
>   next->disable();
>   next = next->next;
> }

This obviously means that all non-RT IRQ handlers sharing a line with
the RT domain would have to be registered in that shared[]-list. This
gets close to my old suggestion. Just raises the question how to
organise these interface, both on the RT and the Linux side.

>   }
> }
> if (irqmask & 0xff00 != 0xff00) {
>   irqmask &= ~0x0004; // Cascaded interrupt is still needed
>   outb(irqmask >> 8, PIC_SLAVE_IMR);
> }
> outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> An obvious optimization of the above scheme, is to never call the
> disable (or enable) function for the RT-domain, since there all
> interrupt processing is protected by the hardware.

Another point is to avoid that looping over disable handlers for IRQs of
the K case. Otherwise, too many device-specific disable handlers had to
be implemented e

Re: [Xenomai-core] More on Shared interrupts

2006-02-09 Thread Jan Kiszka
Anders Blomdell wrote:
> For the last few days, I have tried to figure out a good way to share
> interrupts between RT and non-RT domains. This has included looking
> through Dmitry's patch, correcting bugs and testing what is possible in
> my specific case. I'll therefore try to summarize at least a few of my
> thoughts.
> 
> 1. When looking through Dmitry's patch I get the impression that the
> iack handler has very little to do with each interrupt (the test
> 'prev->iack != intr->iack' is a dead giveaway), but is more of a
> domain-specific function (or perhaps even just a placeholder for the
> hijacked Linux ack-function).
> 
> 
> 2. Somewhat inspired by the figure in "Life with Adeos", I have
> identified the following cases:
> 
>   irq K  | --- | ---o|   // Linux only
>   ...
>   irq L  | ---o| |   // RT-only
>   ...
>   irq M  | ---o--- | ---o|   // Shared between domains
>   ...
>   irq N  | ---o---o--- | |   // Shared inside single domain
>   ...
>   irq O  | ---o---o--- | ---o|   // Shared between and inside single
> domain
> 
> Xenomai currently handles the K & L cases, Dmitrys patch addresses the N
> case, with edge triggered interrupts the M (and O after Dmitry's patch)
> case(s) might be handled by returning RT_INTR_CHAINED | RT_INTR_ENABLE
> from the interrupt handler, for level triggered interrupt the M and O
> cases can't be handled.

I guess you mean it the other way around: for the edge-triggered
cross-domain case we would actually have to loop over both the RT and
the Linux handlers until we are sure, that the IRQ line was released once.

Luckily, I never saw such a scenario which were unavoidable (it hits you
with ISA hardware which tend to have nice IRQ jumpers or other means -
it's just that you often cannot divide several controllers on the same
extension card IRQ-wise apart).

> 
> If one looks more closely at the K case (Linux only interrupt), it works
> by when an interrupt occurs, the call to irq_end is postponed until the
> Linux interrupt handler has run, i.e. further interrupts are disabled.
> This can be seen as a lazy version of Philippe's idea of disabling all
> non-RT interrupts until the RT-domain is idle, i.e. the interrupt is
> disabled only if it indeed occurs.
> 
> If this idea should be generalized to the M (and O) case(s), one can't
> rely on postponing the irq_end call (since the interrupt is still needed
> in the RT-domain), but has to rely on some function that disables all
> non-RT hardware that generates interrupts on that irq-line; such a
> function naturally has to have intimate knowledge of all hardware that
> can generate interrupts in order to be able to disable those interrupt
> sources that are non-RT.
> 
> If we then take Jan's observation about the many (Linux-only) interrupts
> present in an ordinary PC and add it to Philippe's idea of disabling all
> non-RT interrupts while executing in the RT-domain, I think that the
> following is a workable (and fairly efficient) way of handling this:
> 
> Add hardware dependent enable/disable functions, where the enable is
> called just before normal execution in a domain starts (i.e. when
> playing back interrupts, the disable is still in effect), and disable is
> called when normal domain execution end. This does effectively handle
> the K case above, with the added benefit that NO non-RT interrupts will
> occur during RT execution.
> 
> In the 8259 case, the disable function could look something like:
> 
>   domain_irq_disable(uint irqmask) {
> if (irqmask & 0xff00 != 0xff00) {
>   irqmask &= ~0x0004; // Cascaded interrupt is still needed
>   outb(irqmask >> 8, PIC_SLAVE_IMR);
> }
> outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> If we should extend this to handle the M (and O) case(s), the disable
> function could look like:
> 
>   domain_irq_disable(uint irqmask, shared_irq_t *shared[]) {
> int i;
> 
> for (i = 0 ; i < MAX_IRQ ; i++) {
>   if (shared[i]) {
> shared_irq_t *next = shared[i];
> irqmask &= ~(1< while (next) {
>   next->disable();
>   next = next->next;
> }

This obviously means that all non-RT IRQ handlers sharing a line with
the RT domain would have to be registered in that shared[]-list. This
gets close to my old suggestion. Just raises the question how to
organise these interface, both on the RT and the Linux side.

>   }
> }
> if (irqmask & 0xff00 != 0xff00) {
>   irqmask &= ~0x0004; // Cascaded interrupt is still needed
>   outb(irqmask >> 8, PIC_SLAVE_IMR);
> }
> outb(irqmask, PIC_MASTER_IMR);
>   }
> 
> An obvious optimization of the above scheme, is to never call the
> disable (or enable) function for the RT-domain, since there all
> interrupt processing is protected by the hardware.

Another point is to avoid that looping over disable handlers for IRQs of
the K case. Otherwise, too many device-specific disable handlers had to
be implemented e