The current approach to propagate root hardware interrupts from the I-pipe layer fails to set the timer IRQ register context correctly and comes with an extra function call indirection. This patch addresses both, specifically repairing Linux profiling and processing time accounting abilities.
To save the latter also when Xenomai is enabled, it takes an additional Xenomai fix that will be posted to the related list. Jan
---
arch/x86_64/kernel/entry.S | 22 -------------------
arch/x86_64/kernel/ipipe.c | 20 ++++++++++++-----
include/asm-x86_64/ipipe.h | 51 +++++++++++++++++++++++++++++++++++++--------
3 files changed, 57 insertions(+), 36 deletions(-)
Index: linux-2.6.23.12-xeno_64/arch/x86_64/kernel/entry.S
===================================================================
--- linux-2.6.23.12-xeno_64.orig/arch/x86_64/kernel/entry.S
+++ linux-2.6.23.12-xeno_64/arch/x86_64/kernel/entry.S
@@ -582,26 +582,6 @@ END(stub_rt_sigreturn)
#ifdef CONFIG_IPIPE
- /* %rdi=negated _vector_ number, %rsi=handler */
-ENTRY(__ipipe_root_xirq_thunk)
- movq %rsp, %rax
- pushq $0
- pushq %rax
- pushfq
- pushq $__KERNEL_CS
- pushq $1f
- pushq %rdi
- XCPT_FRAME
- SAVE_ARGS
- leaq -ARGOFFSET(%rsp),%rdi # regs for handler
- call *%rsi
- jmp exit_intr
- CFI_ENDPROC
-1:
- cli
- ret
-END(__ipipe_root_xirq_thunk)
-
/* %rdi=virq number, %rsi=cookie, %rdx=handler */
ENTRY(__ipipe_root_virq_thunk)
movq %rsp, %rax
@@ -647,7 +627,7 @@ ret_from_intr:
leaveq
CFI_DEF_CFA_REGISTER rsp
CFI_ADJUST_CFA_OFFSET -8
-exit_intr:
+ENTRY(exit_intr)
GET_THREAD_INFO(%rcx)
testl $3,CS-ARGOFFSET(%rsp)
je retint_kernel
Index: linux-2.6.23.12-xeno_64/arch/x86_64/kernel/ipipe.c
===================================================================
--- linux-2.6.23.12-xeno_64.orig/arch/x86_64/kernel/ipipe.c
+++ linux-2.6.23.12-xeno_64/arch/x86_64/kernel/ipipe.c
@@ -750,13 +750,21 @@ int __ipipe_handle_irq(struct pt_regs *r
finalize:
+ /*
+ * Given our deferred dispatching model for regular IRQs, we only
+ * record relevant registers for the last timer interrupt, so that the
+ * timer handler charges CPU times properly. It is assumed that other
+ * interrupt handlers don't actually care for such information.
+ */
if (irq == __ipipe_tick_irq) {
- __raw_get_cpu_var(__ipipe_tick_regs).rip = regs->rip;
- __raw_get_cpu_var(__ipipe_tick_regs).cs = regs->cs;
- __raw_get_cpu_var(__ipipe_tick_regs).eflags = regs->eflags;
- __raw_get_cpu_var(__ipipe_tick_regs).rbp = regs->rbp;
- __raw_get_cpu_var(__ipipe_tick_regs).rsp = regs->rsp;
- __raw_get_cpu_var(__ipipe_tick_regs).ss = regs->ss;
+ struct pt_regs *tick_regs =
+ &__raw_get_cpu_var(__ipipe_tick_regs);
+ tick_regs->ss = regs->ss;
+ tick_regs->rsp = regs->rsp;
+ tick_regs->eflags = regs->eflags;
+ tick_regs->cs = regs->cs;
+ tick_regs->rip = regs->rip;
+ tick_regs->rbp = regs->rbp;
}
/*
Index: linux-2.6.23.12-xeno_64/include/asm-x86_64/ipipe.h
===================================================================
--- linux-2.6.23.12-xeno_64.orig/include/asm-x86_64/ipipe.h
+++ linux-2.6.23.12-xeno_64/include/asm-x86_64/ipipe.h
@@ -123,9 +123,6 @@ DECLARE_PER_CPU(struct pt_regs, __ipipe_
unsigned __ipipe_get_irq_vector(int irq);
-asmlinkage void __ipipe_root_xirq_thunk(unsigned irq,
- void (*handler)(unsigned irq, void *cookie));
-
asmlinkage void __ipipe_root_virq_thunk(unsigned irq,
void *cookie,
void (*handler)(unsigned irq, void *cookie));
@@ -142,6 +139,44 @@ void __ipipe_ack_edge_irq(unsigned irq,
void __ipipe_end_edge_irq(unsigned irq, struct irq_desc *desc);
+static inline void
+__ipipe_call_root_xirq_handler(unsigned irq,
+ void (*handler)(unsigned irq, void *cookie))
+{
+ struct pt_regs *regs = &__raw_get_cpu_var(__ipipe_tick_regs);
+
+ regs->orig_rax = ~__ipipe_get_irq_vector(irq);
+
+ __asm__ __volatile__ (
+ "movq %%rsp, %%rdx\n\t"
+ "pushq $0\n\t"
+ "pushq %%rdx\n\t"
+ "pushfq\n\t"
+ "pushq %[kernel_cs]\n\t"
+ "pushq $xirq_end\n\t"
+ "pushq %%rax # dummy value\n\t"
+ "movq %%rdi,8*8(%%rsp) # are these required?\n\t"
+ "movq %%rsi,7*8(%%rsp)\n\t"
+ "movq %%rdx,6*8(%%rsp)\n\t"
+ "movq %%rcx,5*8(%%rsp)\n\t"
+ "movq %%rax,4*8(%%rsp)\n\t"
+ "movq %%r8,3*8(%%rsp)\n\t"
+ "movq %%r9,2*8(%%rsp)\n\t"
+ "movq %%r10,1*8(%%rsp)\n\t"
+ "movq %%r11,(%%rsp)\n\t"
+
+ "movq %[regs],%%rdi # always pass tick regs\n\t"
+ "call *%[handler]\n\t"
+
+ "jmp exit_intr # Linux IRQ epilogue\n\t"
+
+ "xirq_end: cli\n\t"
+ : /* no output */
+ : [kernel_cs] "i" (__KERNEL_CS), [regs] "rm" (regs),
+ [handler] "rm" (handler)
+ : "rdx", "rdi");
+}
+
/*
* When running handlers, enable hw interrupts for all domains but the
* one heading the pipeline, so that IRQs can never be significantly
@@ -151,12 +186,10 @@ void __ipipe_end_edge_irq(unsigned irq,
do { \
local_irq_enable_nohead(ipd); \
if (ipd == ipipe_root_domain) { \
- if (likely(!ipipe_virtual_irq_p(irq))) { \
- struct pt_regs *old_regs; \
- old_regs = set_irq_regs(&__raw_get_cpu_var(__ipipe_tick_regs)); \
- __ipipe_root_xirq_thunk(~__ipipe_get_irq_vector(irq), (ipd)->irqs[irq].handler); \
- set_irq_regs(old_regs); \
- } else { \
+ if (likely(!ipipe_virtual_irq_p(irq))) \
+ __ipipe_call_root_xirq_handler( \
+ irq, (ipd)->irqs[irq].handler); \
+ else { \
irq_enter(); \
__ipipe_root_virq_thunk( \
irq, (ipd)->irqs[irq].cookie, (ipd)->irqs[irq].handler); \
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Adeos-main mailing list [email protected] https://mail.gna.org/listinfo/adeos-main
