You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							982 lines
						
					
					
						
							29 KiB
						
					
					
				
			
		
		
	
	
							982 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 [email protected] | |
|   | |
| +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++;
 | |
| 
 |