983 lines
29 KiB

diff -Naur linux-2.4.20/Documentation/Configure.help linux-2.4.20-rtai/Documentation/Configure.help
--- linux-2.4.20/Documentation/Configure.help Fri Nov 29 19:01:31 2002
+++ linux-2.4.20-rtai/Documentation/Configure.help Mon Dec 2 16:11:55 2002
@@ -254,6 +254,13 @@
You will need a new lynxer.elf file to flash your firmware with - send
email to Martin.Bligh@us.ibm.com
+Real-Time Harware Abstraction
+CONFIG_RTHAL
+ The Real-Time Hardware Abstraction Layer (RTHAL) is used by
+ the Real-Time Application Interface (RTAI) to provide a
+ hard real-time environment as part of Linux. This feature
+ cannot be turned off, so say Y.
+
Support for IBM Summit (EXA) systems
CONFIG_X86_SUMMIT
This option is needed for IBM systems that use the Summit/EXA chipset.
diff -Naur linux-2.4.20/arch/i386/config.in linux-2.4.20-rtai/arch/i386/config.in
--- linux-2.4.20/arch/i386/config.in Fri Nov 29 19:01:34 2002
+++ linux-2.4.20-rtai/arch/i386/config.in Mon Dec 2 16:11:55 2002
@@ -256,6 +256,8 @@
if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
define_bool CONFIG_HAVE_DEC_LOCK y
fi
+comment 'CONFIG_RTHAL must be yes'
+bool 'Real-Time Hardware Abstraction Layer' CONFIG_RTHAL
endmenu
mainmenu_option next_comment
diff -Naur linux-2.4.20/arch/i386/defconfig linux-2.4.20-rtai/arch/i386/defconfig
--- linux-2.4.20/arch/i386/defconfig Fri Nov 29 19:01:34 2002
+++ linux-2.4.20-rtai/arch/i386/defconfig Mon Dec 2 16:11:55 2002
@@ -66,6 +66,7 @@
# CONFIG_MULTIQUAD is not set
CONFIG_HAVE_DEC_LOCK=y
CONFIG_NR_CPUS=32
+CONFIG_RTHAL=y
#
# General setup
diff -Naur linux-2.4.20/arch/i386/kernel/entry.S linux-2.4.20-rtai/arch/i386/kernel/entry.S
--- linux-2.4.20/arch/i386/kernel/entry.S Fri Nov 29 19:01:34 2002
+++ linux-2.4.20-rtai/arch/i386/kernel/entry.S Mon Dec 2 16:11:55 2002
@@ -184,6 +184,7 @@
ENTRY(ret_from_fork)
+ sti
pushl %ebx
call SYMBOL_NAME(schedule_tail)
addl $4, %esp
@@ -210,17 +211,20 @@
call *SYMBOL_NAME(sys_call_table)(,%eax,4)
movl %eax,EAX(%esp) # save the return value
ENTRY(ret_from_sys_call)
- cli # need_resched and signals atomic test
+ call *(SYMBOL_NAME(rthal) + 12) # cli
cmpl $0,need_resched(%ebx)
jne reschedule
cmpl $0,sigpending(%ebx)
jne signal_return
+ sti
+ call *(SYMBOL_NAME(rthal) + 16) # sti
restore_all:
RESTORE_ALL
ALIGN
signal_return:
- sti # we can get here from an interrupt handler
+ sti # we can get here from an interrupt handler
+ call *(SYMBOL_NAME(rthal) + 16) # sti
testl $(VM_MASK),EFLAGS(%esp)
movl %esp,%eax
jne v86_signal_return
diff -Naur linux-2.4.20/arch/i386/kernel/i386_ksyms.c linux-2.4.20-rtai/arch/i386/kernel/i386_ksyms.c
--- linux-2.4.20/arch/i386/kernel/i386_ksyms.c Sat Aug 3 02:39:42 2002
+++ linux-2.4.20-rtai/arch/i386/kernel/i386_ksyms.c Mon Dec 2 16:11:55 2002
@@ -32,6 +32,18 @@
extern void dump_thread(struct pt_regs *, struct user *);
extern spinlock_t rtc_lock;
+EXPORT_SYMBOL_NOVERS(rthal);
+
+#ifdef CONFIG_VT
+ #include <linux/vt_kern.h>
+ EXPORT_SYMBOL(kd_mksound);
+#endif
+
+#include <linux/console.h>
+EXPORT_SYMBOL(console_drivers);
+extern unsigned long cpu_khz;
+EXPORT_SYMBOL(cpu_khz);
+
#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
extern void machine_real_restart(unsigned char *, int);
EXPORT_SYMBOL(machine_real_restart);
@@ -172,6 +184,13 @@
#ifdef CONFIG_HAVE_DEC_LOCK
EXPORT_SYMBOL(atomic_dec_and_lock);
+#endif
+
+#ifdef CONFIG_X86_REMOTE_DEBUG
+#include <linux/gdb.h>
+EXPORT_SYMBOL(linux_debug_hook);
+EXPORT_SYMBOL(gdb_irq);
+EXPORT_SYMBOL(gdb_interrupt);
#endif
extern int is_sony_vaio_laptop;
diff -Naur linux-2.4.20/arch/i386/kernel/i8259.c linux-2.4.20-rtai/arch/i386/kernel/i8259.c
--- linux-2.4.20/arch/i386/kernel/i8259.c Tue Sep 18 08:03:09 2001
+++ linux-2.4.20-rtai/arch/i386/kernel/i8259.c Mon Dec 2 16:11:55 2002
@@ -290,12 +290,12 @@
handle_real_irq:
if (irq & 8) {
- inb(0xA1); /* DUMMY - (do we need this?) */
+// inb(0xA1); /* DUMMY - (do we need this?) */
outb(cached_A1,0xA1);
outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */
} else {
- inb(0x21); /* DUMMY - (do we need this?) */
+// inb(0x21); /* DUMMY - (do we need this?) */
outb(cached_21,0x21);
outb(0x60+irq,0x20); /* 'Specific EOI' to master */
}
@@ -508,3 +508,17 @@
if (boot_cpu_data.hard_math && !cpu_has_fpu)
setup_irq(13, &irq13);
}
+
+void ack_8259_irq(unsigned int irq)
+{
+ spin_lock(&i8259A_lock);
+ if (irq & 8) {
+ outb(0x62,0x20);
+ outb(0x20,0xA0);
+ } else {
+ outb(0x20,0x20);
+ }
+ spin_unlock(&i8259A_lock);
+ return;
+}
+
diff -Naur linux-2.4.20/arch/i386/kernel/io_apic.c linux-2.4.20-rtai/arch/i386/kernel/io_apic.c
--- linux-2.4.20/arch/i386/kernel/io_apic.c Fri Nov 29 19:01:34 2002
+++ linux-2.4.20-rtai/arch/i386/kernel/io_apic.c Mon Dec 2 16:11:55 2002
@@ -38,7 +38,7 @@
#undef APIC_LOCKUP_DEBUG
-#define APIC_LOCKUP_DEBUG
+//#define APIC_LOCKUP_DEBUG
static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;
@@ -1282,11 +1282,10 @@
#define enable_level_ioapic_irq unmask_IO_APIC_irq
#define disable_level_ioapic_irq mask_IO_APIC_irq
+static unsigned long strange_level;
+
static void end_level_ioapic_irq (unsigned int irq)
{
- unsigned long v;
- int i;
-
/*
* It appears there is an erratum which affects at least version 0x11
* of I/O APIC (that's the 82093AA and cores integrated into various
@@ -1306,12 +1305,8 @@
* operation to prevent an edge-triggered interrupt escaping meanwhile.
* The idea is from Manfred Spraul. --macro
*/
- i = IO_APIC_VECTOR(irq);
- v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
-
- ack_APIC_irq();
- if (!(v & (1 << (i & 0x1f)))) {
+ if (test_and_clear_bit(irq, &strange_level)) {
#ifdef APIC_LOCKUP_DEBUG
struct irq_pin_list *entry;
#endif
@@ -1320,7 +1315,6 @@
atomic_inc(&irq_mis_count);
#endif
spin_lock(&ioapic_lock);
- __mask_and_edge_IO_APIC_irq(irq);
#ifdef APIC_LOCKUP_DEBUG
for (entry = irq_2_pin + irq;;) {
unsigned int reg;
@@ -1338,10 +1332,30 @@
#endif
__unmask_and_level_IO_APIC_irq(irq);
spin_unlock(&ioapic_lock);
+ } else {
+ spin_lock(&ioapic_lock);
+ __unmask_IO_APIC_irq(irq);
+ spin_unlock(&ioapic_lock);
}
}
-static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ }
+static void mask_and_ack_level_ioapic_irq (unsigned int irq)
+{
+ unsigned long i;
+
+ i = IO_APIC_VECTOR(irq);
+ if (!(apic_read(APIC_TMR + ((i & ~0x1f) >> 1)) & (1 << (i & 0x1f)))) {
+ test_and_set_bit(irq, &strange_level);
+ spin_lock(&ioapic_lock);
+ __mask_and_edge_IO_APIC_irq(irq);
+ spin_unlock(&ioapic_lock);
+ } else {
+ spin_lock(&ioapic_lock);
+ __mask_IO_APIC_irq(irq);
+ spin_unlock(&ioapic_lock);
+ }
+ ack_APIC_irq();
+}
#ifndef CONFIG_SMP
diff -Naur linux-2.4.20/arch/i386/kernel/irq.c linux-2.4.20-rtai/arch/i386/kernel/irq.c
--- linux-2.4.20/arch/i386/kernel/irq.c Fri Nov 29 19:01:34 2002
+++ linux-2.4.20-rtai/arch/i386/kernel/irq.c Mon Dec 2 16:11:55 2002
@@ -1212,3 +1212,71 @@
register_irq_proc(i);
}
+static void linux_cli(void)
+{
+ hard_cli();
+}
+
+static void linux_sti(void)
+{
+ hard_sti();
+}
+
+static unsigned int linux_save_flags(void)
+{
+ int flags;
+ hard_save_flags(flags);
+ return flags;
+}
+
+static void linux_restore_flags(unsigned int flags)
+{
+ hard_restore_flags(flags);
+}
+
+static unsigned int linux_save_flags_and_cli(void)
+{
+ int flags;
+ hard_save_flags_and_cli(flags);
+ return flags;
+}
+
+#include <asm/mmu_context.h>
+
+#ifndef CONFIG_X86_IO_APIC
+int irq_vector[];
+#endif
+#ifndef CONFIG_SMP
+void smp_invalidate_interrupt(void) { }
+static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
+static volatile int physical_apicid_2_cpu[1];
+#endif
+
+extern void *ret_from_intr;
+extern struct desc_struct idt_table[];
+extern void ack_8259_irq(unsigned int);
+extern int idle_weight;
+extern void smp_invalidate_interrupt(void);
+extern void switch_mem(struct task_struct *, struct task_struct *, int);
+extern volatile int physical_apicid_2_cpu[];
+
+struct rt_hal rthal = {
+ ret_from_intr: &ret_from_intr,
+ __switch_to: __switch_to,
+ idt_table: idt_table,
+ disint: linux_cli,
+ enint: linux_sti,
+ getflags: linux_save_flags,
+ setflags: linux_restore_flags,
+ getflags_and_cli: linux_save_flags_and_cli,
+ irq_desc: irq_desc,
+ irq_vector: irq_vector,
+ irq_affinity: irq_affinity,
+ smp_invalidate_interrupt: smp_invalidate_interrupt,
+ ack_8259_irq: ack_8259_irq,
+ idle_weight: &idle_weight,
+ lxrt_global_cli: NULL,
+ switch_mem: switch_mem,
+ init_tasks: init_tasks,
+ apicmap: physical_apicid_2_cpu,
+};
diff -Naur linux-2.4.20/arch/i386/kernel/smp.c linux-2.4.20-rtai/arch/i386/kernel/smp.c
--- linux-2.4.20/arch/i386/kernel/smp.c Fri Nov 29 19:01:34 2002
+++ linux-2.4.20-rtai/arch/i386/kernel/smp.c Mon Dec 2 16:11:55 2002
@@ -160,8 +160,7 @@
unsigned long cfg;
unsigned long flags;
- __save_flags(flags);
- __cli();
+ hard_save_flags_and_cli(flags);
/*
@@ -185,7 +184,7 @@
*/
apic_write_around(APIC_ICR, cfg);
- __restore_flags(flags);
+ hard_restore_flags(flags);
}
static inline void send_IPI_mask_sequence(int mask, int vector)
diff -Naur linux-2.4.20/arch/i386/kernel/time.c linux-2.4.20-rtai/arch/i386/kernel/time.c
--- linux-2.4.20/arch/i386/kernel/time.c Fri Nov 29 19:01:34 2002
+++ linux-2.4.20-rtai/arch/i386/kernel/time.c Mon Dec 2 16:11:55 2002
@@ -673,6 +673,7 @@
rdtscl(last_tsc_low);
+#if 0
spin_lock(&i8253_lock);
outb_p(0x00, 0x43); /* latch the count ASAP */
@@ -704,6 +705,7 @@
count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
+#endif
}
do_timer_interrupt(irq, NULL, regs);
diff -Naur linux-2.4.20/arch/i386/mm/fault.c linux-2.4.20-rtai/arch/i386/mm/fault.c
--- linux-2.4.20/arch/i386/mm/fault.c Fri Nov 29 19:01:34 2002
+++ linux-2.4.20-rtai/arch/i386/mm/fault.c Mon Dec 2 16:11:55 2002
@@ -153,7 +153,7 @@
/* It's safe to allow irq's after cr2 has been saved */
if (regs->eflags & X86_EFLAGS_IF)
- local_irq_enable();
+ hard_sti();
tsk = current;
diff -Naur linux-2.4.20/arch/i386/mm/ioremap.c linux-2.4.20-rtai/arch/i386/mm/ioremap.c
--- linux-2.4.20/arch/i386/mm/ioremap.c Sat Aug 3 02:39:42 2002
+++ linux-2.4.20-rtai/arch/i386/mm/ioremap.c Mon Dec 2 16:11:55 2002
@@ -81,6 +81,7 @@
if (remap_area_pmd(pmd, address, end - address,
phys_addr + address, flags))
break;
+ set_pgdir(address, *dir);
error = 0;
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
diff -Naur linux-2.4.20/arch/ppc/config.in linux-2.4.20-rtai/arch/ppc/config.in
--- linux-2.4.20/arch/ppc/config.in Fri Nov 29 19:01:45 2002
+++ linux-2.4.20-rtai/arch/ppc/config.in Mon Dec 2 16:11:55 2002
@@ -125,6 +125,9 @@
bool ' Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS
fi
+#bool 'Real-Time Hardware Abstraction Layer' CONFIG_RTHAL
+define_bool CONFIG_RTHAL y
+
if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then
bool 'AltiVec Support' CONFIG_ALTIVEC
bool 'Thermal Management Support' CONFIG_TAU
diff -Naur linux-2.4.20/arch/ppc/kernel/entry.S linux-2.4.20-rtai/arch/ppc/kernel/entry.S
--- linux-2.4.20/arch/ppc/kernel/entry.S Fri Nov 29 19:01:45 2002
+++ linux-2.4.20-rtai/arch/ppc/kernel/entry.S Mon Dec 2 16:11:55 2002
@@ -291,6 +291,7 @@
bl do_signal
.globl do_signal_ret
do_signal_ret:
+ bl do_soft_sti
.globl ret_to_user_hook
ret_to_user_hook:
nop
diff -Naur linux-2.4.20/arch/ppc/kernel/irq.c linux-2.4.20-rtai/arch/ppc/kernel/irq.c
--- linux-2.4.20/arch/ppc/kernel/irq.c Fri Nov 29 19:01:45 2002
+++ linux-2.4.20-rtai/arch/ppc/kernel/irq.c Mon Dec 2 16:11:55 2002
@@ -510,6 +510,17 @@
spin_unlock(&desc->lock);
}
+void do_soft_cli(void)
+{
+}
+
+void (*rtai_soft_sti)(void);
+
+void do_soft_sti(void)
+{
+ if(rtai_soft_sti)rtai_soft_sti();
+}
+
int do_IRQ(struct pt_regs *regs)
{
int cpu = smp_processor_id();
diff -Naur linux-2.4.20/arch/ppc/kernel/traps.c linux-2.4.20-rtai/arch/ppc/kernel/traps.c
--- linux-2.4.20/arch/ppc/kernel/traps.c Sat Nov 3 02:43:54 2001
+++ linux-2.4.20-rtai/arch/ppc/kernel/traps.c Mon Dec 2 16:11:55 2002
@@ -320,9 +320,15 @@
return retval;
}
+int (*rtai_srq_bckdr)(struct pt_regs *regs) = NULL;
+
void
ProgramCheckException(struct pt_regs *regs)
{
+ if (rtai_srq_bckdr && !rtai_srq_bckdr(regs)) {
+ return;
+ }
+{
unsigned int reason = get_reason(regs);
extern int do_mathemu(struct pt_regs *regs);
@@ -378,6 +384,7 @@
}
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+}
}
void
diff -Naur linux-2.4.20/arch/ppc/kernel/ppc_ksyms.c linux-2.4.20-rtai/arch/ppc/kernel/ppc_ksyms.c
--- linux-2.4.20/arch/ppc/kernel/ppc_ksyms.c Fri Nov 29 19:01:46 2002
+++ linux-2.4.20-rtai/arch/ppc/kernel/ppc_ksyms.c Mon Dec 2 16:11:55 2002
@@ -220,6 +220,12 @@
EXPORT_SYMBOL(synchronize_irq);
#endif
+extern int (*rtai_srq_bckdr)(struct pt_regs *);
+EXPORT_SYMBOL(rtai_srq_bckdr);
+
+extern void (*rtai_soft_sti)(void);
+EXPORT_SYMBOL(rtai_soft_sti);
+
EXPORT_SYMBOL(ppc_md);
#ifdef CONFIG_ADB
diff -Naur linux-2.4.20/include/asm-i386/hw_irq.h linux-2.4.20-rtai/include/asm-i386/hw_irq.h
--- linux-2.4.20/include/asm-i386/hw_irq.h Thu Nov 22 20:46:18 2001
+++ linux-2.4.20-rtai/include/asm-i386/hw_irq.h Mon Dec 2 16:16:00 2002
@@ -37,18 +37,31 @@
*
* Vectors 0xf0-0xfa are free (reserved for future Linux use).
*/
+#ifdef CONFIG_RTHAL
+/* the standard definitions conflict with LXRT */
+#define SPURIOUS_APIC_VECTOR 0xdf
+#define ERROR_APIC_VECTOR 0xde
+#define INVALIDATE_TLB_VECTOR 0xdd
+#define RESCHEDULE_VECTOR 0xdc
+#define CALL_FUNCTION_VECTOR 0xdb
+#else
#define SPURIOUS_APIC_VECTOR 0xff
#define ERROR_APIC_VECTOR 0xfe
#define INVALIDATE_TLB_VECTOR 0xfd
#define RESCHEDULE_VECTOR 0xfc
#define CALL_FUNCTION_VECTOR 0xfb
+#endif
/*
* Local APIC timer IRQ vector is on a different priority level,
* to work around the 'lost local interrupt if more than 2 IRQ
* sources per level' errata.
*/
+#ifdef CONFIG_RTHAL
+#define LOCAL_TIMER_VECTOR 0xcf
+#else
#define LOCAL_TIMER_VECTOR 0xef
+#endif
/*
* First APIC vector available to drivers: (vectors 0x30-0xee)
@@ -56,7 +69,11 @@
* levels. (0x80 is the syscall vector)
*/
#define FIRST_DEVICE_VECTOR 0x31
+#ifdef CONFIG_RTHAL
+#define FIRST_SYSTEM_VECTOR 0xcf
+#else
#define FIRST_SYSTEM_VECTOR 0xef
+#endif
extern int irq_vector[NR_IRQS];
#define IO_APIC_VECTOR(irq) irq_vector[irq]
diff -Naur linux-2.4.20/include/asm-i386/irq.h linux-2.4.20-rtai/include/asm-i386/irq.h
--- linux-2.4.20/include/asm-i386/irq.h Sat Aug 3 02:39:45 2002
+++ linux-2.4.20-rtai/include/asm-i386/irq.h Mon Dec 2 16:11:55 2002
@@ -26,7 +26,7 @@
#ifdef CONFIG_X86_IO_APIC
#define NR_IRQS 224
#else
-#define NR_IRQS 16
+#define NR_IRQS 32 /* 2.4.19 vanilla has 16, this is rtai back compatibility */
#endif
static __inline__ int irq_cannonicalize(int irq)
diff -Naur linux-2.4.20/include/asm-i386/pgalloc.h linux-2.4.20-rtai/include/asm-i386/pgalloc.h
--- linux-2.4.20/include/asm-i386/pgalloc.h Sat Aug 3 02:39:45 2002
+++ linux-2.4.20-rtai/include/asm-i386/pgalloc.h Mon Dec 2 16:16:00 2002
@@ -158,6 +158,33 @@
extern int do_check_pgt_cache(int, int);
+extern inline void set_pgdir(unsigned long address, pgd_t entry)
+{
+ struct task_struct * p;
+ pgd_t *pgd;
+#ifdef CONFIG_SMP
+ int i;
+#endif
+
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (!p->mm)
+ continue;
+ *pgd_offset(p->mm,address) = entry;
+ }
+ read_unlock(&tasklist_lock);
+#ifndef CONFIG_SMP
+ for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
+ pgd[address >> PGDIR_SHIFT] = entry;
+#else
+ /* To pgd_alloc/pgd_free, one holds master kernel lock and so does our callee, so we can
+ modify pgd caches of other CPUs as well. -jj */
+ for (i = 0; i < NR_CPUS; i++)
+ for (pgd = (pgd_t *)cpu_data[i].pgd_quick; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
+ pgd[address >> PGDIR_SHIFT] = entry;
+#endif
+}
+
/*
* TLB flushing:
*
diff -Naur linux-2.4.20/include/asm-i386/system.h linux-2.4.20-rtai/include/asm-i386/system.h
--- linux-2.4.20/include/asm-i386/system.h Fri Nov 29 19:02:50 2002
+++ linux-2.4.20-rtai/include/asm-i386/system.h Mon Dec 2 16:16:00 2002
@@ -12,7 +12,12 @@
struct task_struct; /* one of the stranger aspects of C forward declarations.. */
extern void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
-#define prepare_to_switch() do { } while(0)
+#define prepare_to_switch() do { \
+ if (rthal.lxrt_global_cli) { \
+ rthal.lxrt_global_cli(); \
+ } \
+} while(0)
+
#define switch_to(prev,next,last) do { \
asm volatile("pushl %%esi\n\t" \
"pushl %%edi\n\t" \
@@ -23,6 +28,7 @@
"pushl %4\n\t" /* restore EIP */ \
"jmp __switch_to\n" \
"1:\t" \
+ "sti\n\t" \
"popl %%ebp\n\t" \
"popl %%edi\n\t" \
"popl %%esi\n\t" \
@@ -315,29 +321,59 @@
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+struct rt_hal {
+ void *ret_from_intr;
+ void *__switch_to;
+ struct desc_struct *idt_table;
+ void (*disint)(void);
+ void (*enint)(void);
+ unsigned int (*getflags)(void);
+ void (*setflags)(unsigned int flags);
+ unsigned int (*getflags_and_cli)(void);
+ void *irq_desc;
+ int *irq_vector;
+ unsigned long *irq_affinity;
+ void (*smp_invalidate_interrupt)(void);
+ void (*ack_8259_irq)(unsigned int);
+ int *idle_weight;
+ void (*lxrt_global_cli)(void);
+ void (*switch_mem)(struct task_struct *, struct task_struct *, int);
+ struct task_struct **init_tasks;
+ unsigned int *apicmap;
+};
+
+extern struct rt_hal rthal;
+
/* interrupt control.. */
-#define __save_flags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
-#define __restore_flags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc")
-#define __cli() __asm__ __volatile__("cli": : :"memory")
-#define __sti() __asm__ __volatile__("sti": : :"memory")
-/* used in the idle loop; sti takes one instruction cycle to complete */
-#define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory")
+#define hard_save_flags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
+#define hard_restore_flags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc")
+#define hard_cli() __asm__ __volatile__("cli": : :"memory")
+#define hard_sti() __asm__ __volatile__("sti": : :"memory")
+#define hard_save_flags_and_cli(x) __asm__ __volatile__("pushfl; popl %0; cli":"=g" (x): /* no input */)
+
+#define __cli() do { rthal.disint(); } while (0)
+#define __sti() do { rthal.enint(); } while (0)
+#define __save_flags(x) do { x = rthal.getflags(); } while (0)
+#define __restore_flags(x) do { rthal.setflags(x); } while (0)
+
+#define __save_and_cli(x) do { x = rthal.getflags_and_cli(); } while (0)
+#define __save_and_sti(x) do { x = rthal.getflags(); rthal.enint(); } while (0)
-#define __save_and_cli(x) do { __save_flags(x); __cli(); } while(0);
-#define __save_and_sti(x) do { __save_flags(x); __sti(); } while(0);
+/* used in the idle loop; sti takes one instruction cycle to complete */
+#define safe_halt() __asm__ __volatile__("call *"SYMBOL_NAME_STR(rthal + 16)"; hlt": : :"memory")
/* For spinlocks etc */
#if 0
#define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
#define local_irq_set(x) __asm__ __volatile__("pushfl ; popl %0 ; sti":"=g" (x): /* no input */ :"memory")
#else
-#define local_irq_save(x) __save_and_cli(x)
-#define local_irq_set(x) __save_and_sti(x)
+#define local_irq_save(x) do { x = rthal.getflags_and_cli(); } while (0)
+#define local_irq_set(x) do { x = rthal.getflags(); rthal.enint(); } while (0)
#endif
-#define local_irq_restore(x) __restore_flags(x)
-#define local_irq_disable() __cli()
-#define local_irq_enable() __sti()
+#define local_irq_restore(x) do { rthal.setflags(x); } while (0)
+#define local_irq_disable() do { rthal.disint(); } while (0)
+#define local_irq_enable() do { rthal.enint(); } while (0)
#ifdef CONFIG_SMP
diff -Naur linux-2.4.20/include/asm-ppc/system.h linux-2.4.20-rtai/include/asm-ppc/system.h
--- linux-2.4.20/include/asm-ppc/system.h Sat Aug 3 02:39:45 2002
+++ linux-2.4.20-rtai/include/asm-ppc/system.h Mon Dec 2 16:11:55 2002
@@ -82,6 +82,7 @@
struct task_struct;
#define prepare_to_switch() do { } while(0)
+#define end_switch() do { } while(0)
#define switch_to(prev,next,last) _switch_to((prev),(next),&(last))
extern void _switch_to(struct task_struct *, struct task_struct *,
struct task_struct **);
diff -Naur linux-2.4.20/include/linux/sched.h linux-2.4.20-rtai/include/linux/sched.h
--- linux-2.4.20/include/linux/sched.h Fri Nov 29 19:03:06 2002
+++ linux-2.4.20-rtai/include/linux/sched.h Mon Dec 2 16:16:00 2002
@@ -415,6 +415,8 @@
/* journalling filesystem info */
void *journal_info;
+
+ void *this_rt_task[2];
};
/*
@@ -509,6 +511,7 @@
blocked: {{0}}, \
alloc_lock: SPIN_LOCK_UNLOCKED, \
journal_info: NULL, \
+ this_rt_task: {0,0}, \
}
diff -Naur linux-2.4.20/kernel/exit.c linux-2.4.20-rtai/kernel/exit.c
--- linux-2.4.20/kernel/exit.c Fri Nov 29 19:03:07 2002
+++ linux-2.4.20-rtai/kernel/exit.c Mon Dec 2 16:11:55 2002
@@ -422,6 +422,71 @@
write_unlock_irq(&tasklist_lock);
}
+//
+// PGGC added these lines to callback rtai when a task dies.
+// A list of functions allows different rt_modules to be informed.
+//
+static struct t_callback {
+ void (*rtai_callback)(struct task_struct *tsk);
+ struct t_callback *next;
+ } *rtai_callback_list;
+
+extern int set_rtai_callback( void (*fun)(struct task_struct *tsk));
+extern void remove_rtai_callback( void (*fun)(struct task_struct *tsk));
+
+void inform_rtai(void)
+{
+ struct t_callback *pt;
+
+ pt = rtai_callback_list;
+ while (pt) {
+ (*(pt->rtai_callback))(current);
+ pt = pt->next;
+ }
+//printk( "Task pid %d going down\n", current->pid);
+}
+
+int set_rtai_callback( void (*pt)(struct task_struct *tsk))
+{
+ struct t_callback *ptn;
+
+ ptn = kmalloc(sizeof(struct t_callback), GFP_KERNEL);
+ if (!ptn) {
+ return -ENOMEM;
+ }
+ ptn->rtai_callback = pt;
+ ptn->next = rtai_callback_list ? rtai_callback_list : 0;
+ rtai_callback_list = ptn;
+ return 0;
+}
+
+void remove_rtai_callback(void (*pt)(struct task_struct *tsk))
+{
+ struct t_callback *pto, *ptoo, *ptd;
+
+ pto = rtai_callback_list;
+ ptoo = 0;
+ while (pto) {
+ if (pto->rtai_callback == pt) {
+ if (!ptoo) {
+ rtai_callback_list = pto->next;
+ } else {
+ ptoo->next = pto->next;
+ }
+ ptd = pto;
+ pto = pto->next;
+ kfree(ptd);
+ } else {
+ ptoo = pto;
+ pto = pto->next;
+ }
+ }
+//printk("rtai_callback_list %X\n", rtai_callback_list);
+}
+//
+//
+//
+
NORET_TYPE void do_exit(long code)
{
struct task_struct *tsk = current;
@@ -439,6 +504,18 @@
#ifdef CONFIG_BSD_PROCESS_ACCT
acct_process(code);
#endif
+
+/*
+ * PGGC added these lines to callback rtai when a task dies.
+ * This assumes that a LXRT task should/will always set its
+ * scheduling police to SCHED_FIFO or SCHED_RR.
+ * We may want to enforce this in rt_task_init(...).
+ * (For the moment it is not so, thus let's inform LXRT anyhow (Paolo))
+ */
+ if(tsk->this_rt_task[0]) {
+ inform_rtai();
+ }
+
__exit_mm(tsk);
lock_kernel();
diff -Naur linux-2.4.20/kernel/fork.c linux-2.4.20-rtai/kernel/fork.c
--- linux-2.4.20/kernel/fork.c Fri Nov 29 19:03:07 2002
+++ linux-2.4.20-rtai/kernel/fork.c Mon Dec 2 16:11:55 2002
@@ -233,7 +233,9 @@
atomic_set(&mm->mm_count, 1);
init_rwsem(&mm->mmap_sem);
mm->page_table_lock = SPIN_LOCK_UNLOCKED;
+ lock_kernel();
mm->pgd = pgd_alloc(mm);
+ unlock_kernel();
mm->def_flags = 0;
if (mm->pgd)
return mm;
@@ -265,7 +267,9 @@
inline void __mmdrop(struct mm_struct *mm)
{
BUG_ON(mm == &init_mm);
+ lock_kernel();
pgd_free(mm->pgd);
+ unlock_kernel();
check_pgt_cache();
destroy_context(mm);
free_mm(mm);
diff -Naur linux-2.4.20/kernel/ksyms.c linux-2.4.20-rtai/kernel/ksyms.c
--- linux-2.4.20/kernel/ksyms.c Fri Nov 29 19:03:07 2002
+++ linux-2.4.20-rtai/kernel/ksyms.c Mon Dec 2 16:11:55 2002
@@ -600,3 +600,44 @@
/* To match ksyms with System.map */
extern const char _end[];
EXPORT_SYMBOL(_end);
+
+/*
+ * used to inform rtai a task is about to die.
+ */
+extern int set_rtai_callback( void (*fun)(struct task_struct *tsk));
+extern void remove_rtai_callback(void (*fun)(struct task_struct *tsk));
+extern NORET_TYPE void do_exit(long code);
+EXPORT_SYMBOL(set_rtai_callback);
+EXPORT_SYMBOL(remove_rtai_callback);
+EXPORT_SYMBOL(do_exit);
+
+/*
+ * used to inform RTAI LXRT a task should deal with a Linux signal, and for rt_lxrt_fork()
+ */
+extern int (*rtai_signal_handler)(struct task_struct *lnxt, int sig);
+EXPORT_SYMBOL(rtai_signal_handler);
+extern int do_fork(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size);
+EXPORT_SYMBOL(do_fork);
+
+/*
+ * used to provide async io support (aio) to RTAI LXRT.
+ */
+extern ssize_t sys_read(unsigned int fd, char * buf, size_t count);
+extern ssize_t sys_write(unsigned int fd, const char * buf, size_t count);
+extern ssize_t sys_pread(unsigned int fd, char * buf,
+ size_t count, loff_t pos);
+extern ssize_t sys_pwrite(unsigned int fd, const char * buf,
+ size_t count, loff_t pos);
+extern long sys_fsync(unsigned int fd);
+extern long sys_fdatasync(unsigned int fd);
+extern long sys_open(const char * filename, int flags, int mode);
+extern long sys_close(unsigned int fd);
+
+EXPORT_SYMBOL(sys_read);
+EXPORT_SYMBOL(sys_write);
+EXPORT_SYMBOL(sys_open);
+//EXPORT_SYMBOL(sys_close);
+EXPORT_SYMBOL(sys_pread);
+EXPORT_SYMBOL(sys_pwrite);
+EXPORT_SYMBOL(sys_fsync);
+EXPORT_SYMBOL(sys_fdatasync);
diff -Naur linux-2.4.20/kernel/sched.c linux-2.4.20-rtai/kernel/sched.c
--- linux-2.4.20/kernel/sched.c Fri Nov 29 19:03:07 2002
+++ linux-2.4.20-rtai/kernel/sched.c Mon Dec 2 16:11:55 2002
@@ -544,6 +544,43 @@
* tasks can run. It can not be killed, and it cannot sleep. The 'state'
* information in task[0] is never used.
*/
+
+int idle_weight = -1000;
+#define MAX_MM 1024 // How large should it be?
+static struct smm_t { int in, out; struct mm_struct *mm[MAX_MM]; } smm[NR_CPUS];
+#define incpnd(x) do { x = (x + 1) & (MAX_MM - 1); } while(0)
+
+static inline void pend_mm(struct mm_struct *mm, int cpu)
+{
+ if (rthal.lxrt_global_cli) {
+ struct smm_t *p = smm + cpu;
+ p->mm[p->in] = mm;
+ incpnd(p->in);
+ } else {
+ mmdrop(mm);
+ }
+}
+
+static inline void drop_mm(void)
+{
+ if (rthal.lxrt_global_cli) {
+ struct smm_t *p = smm + smp_processor_id();
+ while (p->out != p->in) {
+ mmdrop(p->mm[p->out]);
+ incpnd(p->out);
+ }
+ }
+}
+
+void switch_mem(struct task_struct *prevp, struct task_struct *nextp, int cpuid)
+{
+ struct mm_struct *oldmm = prevp->active_mm;
+ switch_mm(oldmm, nextp->active_mm, nextp, cpuid & 0x0FFFFFFF);
+ if (!nextp->mm) {
+ enter_lazy_tlb(oldmm, nextp, cpuid & 0x0FFFFFFF);
+ }
+}
+
asmlinkage void schedule(void)
{
struct schedule_data * sched_data;
@@ -602,7 +639,7 @@
* Default process to select..
*/
next = idle_task(this_cpu);
- c = -1000;
+ c = idle_weight;
list_for_each(tmp, &runqueue_head) {
p = list_entry(tmp, struct task_struct, run_list);
if (can_schedule(p, this_cpu)) {
@@ -684,7 +721,7 @@
if (!prev->mm) {
prev->active_mm = NULL;
- mmdrop(oldmm);
+ pend_mm(oldmm, this_cpu);
}
}
@@ -693,6 +730,7 @@
* stack.
*/
switch_to(prev, next, prev);
+ drop_mm();
__schedule_tail(prev);
same_process:
diff -Naur linux-2.4.20/kernel/signal.c linux-2.4.20-rtai/kernel/signal.c
--- linux-2.4.20/kernel/signal.c Fri Nov 29 19:03:07 2002
+++ linux-2.4.20-rtai/kernel/signal.c Mon Dec 2 16:11:55 2002
@@ -1010,9 +1010,30 @@
return ret;
}
+//
+// Add this pointer to the RTAI signal handler.
+//
+int (*rtai_signal_handler)(struct task_struct *lnxt, int sig);
+
asmlinkage long
sys_kill(int pid, int sig)
{
+// Add this section to call the RTAI signal handler.
+//
+ {
+ struct task_struct *p;
+ int ret;
+
+ if (rtai_signal_handler) {
+ p = find_task_by_pid(pid);
+ if(p && (p->policy == SCHED_FIFO || p->policy == SCHED_RR) && p->this_rt_task[0]) {
+ ret = rtai_signal_handler(p, sig);
+ if(!ret) return 0; //let Linux deal with it.
+ }
+ }
+ }
+
+ {
struct siginfo info;
info.si_signo = sig;
@@ -1022,6 +1043,7 @@
info.si_uid = current->uid;
return kill_something_info(sig, &info, pid);
+ }
}
/*
diff -Naur linux-2.4.20/mm/vmalloc.c linux-2.4.20-rtai/mm/vmalloc.c
--- linux-2.4.20/mm/vmalloc.c Fri Nov 29 19:03:09 2002
+++ linux-2.4.20-rtai/mm/vmalloc.c Mon Dec 2 16:11:55 2002
@@ -166,6 +166,9 @@
spin_lock(&init_mm.page_table_lock);
do {
pmd_t *pmd;
+#ifdef CONFIG_X86
+ pgd_t olddir = *dir;
+#endif
pmd = pmd_alloc(&init_mm, dir, address);
ret = -ENOMEM;
@@ -175,6 +178,10 @@
ret = -ENOMEM;
if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot, pages))
break;
+#ifdef CONFIG_X86
+ if (pgd_val(olddir) != pgd_val(*dir))
+ set_pgdir(address, *dir);
+#endif
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;