⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arch.h

📁 fsmlabs的real time linux的内核
💻 H
📖 第 1 页 / 共 2 页
字号:
/* * (C) Finite State Machine Labs Inc. 1999 <business@fsmlabs.com> * * Released under the terms of GPL 2. * Open RTLinux makes use of a patented process described in * US Patent 5,995,745. Use of this process is governed * by the Open RTLinux Patent License which can be obtained from * www.fsmlabs.com/PATENT or by sending email to * licensequestions@fsmlabs.com */#include <linux/config.h>#include <linux/irq.h>#include <asm/irq.h>#include <asm/hw_irq.h>#include <asm/apic.h>#include <arch/constants.h>#include <rtl_core.h>extern struct irq_control_s  irq_control;static struct irq_control_s pre_patch_control;#define RTL_NR_IRQS NR_IRQS/* interface to the hardware controller handlers */struct hw_interrupt_type *rtl_irq_desc[NR_IRQS];static struct hw_interrupt_type *save_linux_irq_desc[NR_IRQS];static inline int rtl_irq_controller_get_irq(struct pt_regs r){	return r.orig_eax & 0xff;}static inline void rtl_irq_controller_ack(unsigned int irq) {	if(rtl_irq_desc[irq]) rtl_irq_desc[irq]->ack(irq);}static inline void rtl_irq_controller_enable(unsigned int irq){	if(rtl_irq_desc[irq]) 		rtl_irq_desc[irq]->enable(irq);}static inline void rtl_irq_controller_disable(unsigned int irq){	if(rtl_irq_desc[irq]) rtl_irq_desc[irq]->disable(irq);}void rtl_soft_cli(void);void rtl_soft_sti(void);void rtl_soft_save_flags(unsigned long *);void rtl_soft_restore_flags(unsigned long );void rtl_soft_local_irq_save(unsigned long *);void rtl_soft_local_irq_restore(unsigned long );/* dispatching rt and linux handlers */asmlinkage void (*xdo_IRQ)(struct pt_regs);struct rtl_global_handlers;static inline void dispatch_linux_irq(struct pt_regs *regs,unsigned int irq){	xdo_IRQ(*regs);}#ifdef CONFIG_X86_LOCAL_APICstatic void rtl_local_intercept(MACHDEPREGS );static inline void dispatch_rtl_local_handler(int pnd, struct pt_regs *r){	rtl_local[rtl_getcpuid()].rt_handlers[pnd](r);}struct {        void (*smp_reschedule_interrupt)(void);        void (*smp_invalidate_interrupt)(void);        void (*smp_error_interrupt)(void);        void (*smp_apic_timer_interrupt)(struct pt_regs *);        void (*smp_call_function_interrupt)(void);	void (*rtl_reschedule)(int cpu);        void (*smp_spurious_interrupt)(void); }local_code;#endif#define FAKE_REGS { 0, 0, 0, 0, 0, 0, 0, __KERNEL_DS, 0, 0, (long)rtl_soft_sti, __KERNEL_CS, ARCH_DEFINED_ENABLE, 0, 0 }	/* Called with soft disable set */inline void soft_dispatch_global(unsigned int irq){	struct pt_regs r = FAKE_REGS;	DeclareAndInit(cpu_id);		r.orig_eax = irq;		L_CLEAR(l_ienable);		xdo_IRQ(r);}#ifdef CONFIG_X86_LOCAL_APICvoid dispatch_local_linux_irq(struct pt_regs *r, int pnd){/*  soft_dispatch_local(VECTOR_TO_LOCAL_PND(r->orig_eax)); */ soft_dispatch_local(r->orig_eax);/*  __sti(); */}/* #define localdbg() do { if (test_bit(rtl_getcpuid(), &rtl_reserved_cpumask)) rtl_printf("l%x\n", vector); } while (0) */#define localdbg() do {;} while (0)void soft_dispatch_local(unsigned int vector){/* 	unsigned int vector = LOCAL_PND_TO_VECTOR(pnd); */	rtl_soft_cli();/* 		conpr("d"); conprn(vector); */	switch(vector){	/* IPI for rescheduling */		case RESCHEDULE_VECTOR:			localdbg();			local_code.smp_reschedule_interrupt();			break;		case INVALIDATE_TLB_VECTOR:			/* IPI for invalidation */			localdbg();			local_code.smp_invalidate_interrupt();			break;		case CALL_FUNCTION_VECTOR:			localdbg();			local_code.smp_call_function_interrupt();			break;		case SPURIOUS_APIC_VECTOR:			localdbg();			local_code.smp_spurious_interrupt();			break;		case ERROR_APIC_VECTOR:			localdbg();			local_code.smp_error_interrupt();			break;		case LOCAL_TIMER_VECTOR:			{			struct pt_regs r=  FAKE_REGS;			localdbg();			local_code.smp_apic_timer_interrupt(&r);			}			break;		default:			printk("RTL: bad local vector %x\n",vector);			break;	}}#endif/* Virtual functions for soft irq descriptor table */void rtl_virt_shutdown(unsigned int irq) {	G_DISABLE(irq) ;	rtl_irq_desc[irq]->shutdown(irq);}unsigned int rtl_virt_startup (unsigned int irq){ 	G_ENABLED(irq) ; 	return (rtl_irq_desc[irq]->startup(irq));}#if LINUX_VERSION_CODE < 0x020300void rtl_virt_handle (unsigned int irq, struct pt_regs * regs){ 	rtl_irq_desc[irq]->handle(irq, regs);}#endifstatic void rtl_virt_ack (unsigned int irq){ return;}#ifdef CONFIG_SMPstatic void rtl_virt_set_affinity(unsigned int irq, unsigned long mask){	if(rtl_irq_desc[irq] && rtl_irq_desc[irq]->set_affinity) {		rtl_irq_desc[irq]->set_affinity(irq, mask);	}}extern unsigned long irq_affinity [NR_IRQS];int rtl_irq_set_affinity (unsigned int irq, const unsigned long *mask, unsigned long *oldmask){	rtl_irqstate_t flags;	if (irq >= RTL_RESCHEDULE_VECTOR - 0x20) {		return -1;	}	if (!rtl_irq_desc[irq] || !rtl_irq_desc[irq]->set_affinity) {		return -1;	}	if (oldmask) {		*oldmask = irq_affinity[irq];	}	if (! mask) {		return 0;	}	if (!(*mask & cpu_online_map))		return -EINVAL;	rtl_no_interrupts (flags);	rtl_spin_lock (&rtl_global.hard_irq_controller_lock);	irq_affinity[irq] = *mask;	rtl_irq_desc[irq]->set_affinity(irq, *mask);	rtl_spin_unlock (&rtl_global.hard_irq_controller_lock);	rtl_restore_interrupts (flags);	return 0;}#elsestatic void rtl_virt_set_affinity(unsigned int irq, unsigned long mask){;}int rtl_irq_set_affinity (unsigned int irq, const unsigned long *mask, unsigned long *oldmask){ return -1;}#endifvoid rtl_virt_enable(unsigned int);void rtl_virt_disable(unsigned int);struct hw_interrupt_type rtl_generic_type =  {\	"RTLinux virtual irq",	rtl_virt_startup,	rtl_virt_shutdown,	rtl_virt_enable,	rtl_virt_disable,	rtl_virt_ack,	rtl_virt_enable,	rtl_virt_set_affinity,#if LINUX_VERSION_CODE < 0x020300	rtl_virt_handle#endif};#ifdef CONFIG_SMP/* Michael's reschedule interrupt hack (use a global interrupt for it) */static void rtl_ack_apic(unsigned int irq) {	ack_APIC_irq();}static void rtl_null_enable(unsigned int irq) {}struct hw_interrupt_type rtl_resched_irq_type =  {\	"RTLinux reschedule irq",	rtl_virt_startup,	rtl_virt_shutdown,	rtl_null_enable,	rtl_virt_disable,	rtl_ack_apic,	rtl_virt_enable,	rtl_virt_set_affinity,#if LINUX_VERSION_CODE < 0x020300	rtl_virt_handle /* nothing */#endif};#endifvoid (*local_ret_from_intr)(void);enum pfunctions {pf___start_rtlinux_patch,pf___stop_rtlinux_patch,pf_rtl_emulate_iret,pf_irq_desc,pf_do_IRQ,pf_ret_from_intr,pf_rtl_exception_intercept,#ifdef CONFIG_X86_LOCAL_APICpf_smp_spurious_interrupt,#define PF_LOCAL_START pf_smp_spurious_interruptpf_smp_error_interrupt,pf_smp_apic_timer_interrupt,#ifdef CONFIG_SMPpf_smp_reschedule_interrupt,pf_smp_invalidate_interrupt,pf_smp_call_function_interrupt,pf_rtl_reschedule,#define PF_LOCAL_END pf_smp_call_function_interrupt#else#define PF_LOCAL_END pf_smp_apic_timer_interrupt#endif /* CONFIG_SMP */#endif};/* #define DEBUG_RTLINUX 1 */#ifdef DEBUG_RTLINUX_PATCH_TABLEstatic void print_patch_table(void){	const struct func_table *p = &__start_rtlinux_funcs;	struct patch_table *start_rtlinux_patch = p[0].address;	struct patch_table *stop_rtlinux_patch = p[1].address;	struct patch_table *pt;;	printk("RTLinux table print start=%x stop=%x\n",p,&__stop_rtlinux_funcs);        for(; p <= &__stop_rtlinux_funcs;p++) {		printk("RTLinux function table %x => %x\n",p,p->address);        }	for(pt = start_rtlinux_patch; pt < stop_rtlinux_patch; pt++)		printk("RTLinux patch table %x => %x %x\n",pt,pt->address,pt->magic);        return;}#endif#define JUMP_SIZE 5#define MAX_JUMPS 20/* TODO patch_failure should do a recovery */#define patch_failure(x) {printk(x); return; }static char saved_jumps[MAX_JUMPS][JUMP_SIZE];static void save_jump(char *p, enum pfunctions pf){	int i;	if(pf > MAX_JUMPS){		patch_failure("RTLinux FATAL ERROR; too many jumps\n");	}else for(i=0;i<5;i++)saved_jumps[pf][i] = p[i];}static void unpatch_jump(char *p, enum pfunctions pf){	int i;	if(pf > MAX_JUMPS){		patch_failure("RTLinux FATAL ERROR; too many jumps in unpatch\n");	}else for(i=0;i<5;i++)p[i] = saved_jumps[pf][i];}static void patch_jump(char *code_to_patch,char *target){	int distance;        distance = (int)target - ((int)code_to_patch +5) ;        *code_to_patch++= 0xe9; /* jump */        *code_to_patch++ = ((char *)&distance)[0];        *code_to_patch++ = ((char *)&distance)[1];        *code_to_patch++ = ((char *)&distance)[2];        *code_to_patch = ((char *)&distance)[3];}/* IF THIS IS EVER CHANGED IN linux/arch/i386/rtlinux.h   IT MUST BE CHANGED HERE TOO   */#define ACK_MAGIC 0x12344321struct patch_table { char * address; unsigned long magic;};struct func_table { char * address;};extern const struct func_table *__start_rtlinux_funcs;extern const struct func_table *__stop_rtlinux_funcs;#ifdef CONFIG_X86_IO_APIC/* our version of level-triggered IO APIC irq controller */#if LINUX_VERSION_CODE >= 0x020300static struct hw_interrupt_type *linux_ioapic_level_irq_type_ptr = 0;static struct hw_interrupt_type rtl_ioapic_level_irq_type;void static rtl_mask_and_ack_level_ioapic_irq(unsigned int i){	linux_ioapic_level_irq_type_ptr->disable(i); /* mask */	linux_ioapic_level_irq_type_ptr->end(i);	/* ack */}void static rtl_end_level_io_apic_irq(unsigned int i){	linux_ioapic_level_irq_type_ptr->enable(i); /* unmask */}#endif#endif /* CONFIG_X86_IO_APIC */#ifdef CONFIG_X86_LOCAL_APICvoid start_apic_ack(void);void end_apic_ack(void);static void rtl_local_irq_controller_ack(void){	asm __volatile__("start_apic_ack:\t\n");        ack_APIC_irq();	asm __volatile__("end_apic_ack:\t\n");}static inline char * match_ack(char *caller){	const struct func_table *pfunc = (struct func_table *)&__start_rtlinux_funcs;	struct patch_table *p = (struct patch_table *)pfunc[pf___start_rtlinux_patch].address;	char *closest=0;	unsigned dis=0x7fffffff; /* distance *//* 	printk("searching %x\n", (unsigned) caller); */       	for(; (ulong)p < (ulong)pfunc[pf___stop_rtlinux_patch].address;p++) {		if (p->magic != ACK_MAGIC) {			continue;		} else {/* 			printk("%x, %x, %d\n", p->address, caller, dis); */			if ((unsigned) p->address >= (unsigned) caller &&				dis > ((unsigned)p->address - (unsigned)caller)) {			dis = (ulong)p->address - (ulong)caller;			closest = p->address;			}		}	}	return closest;}static void zap_ack_apic(char *apic_caller){	int i;	int ack_len = (int) end_apic_ack  - (int)start_apic_ack;	char *call_point = match_ack(apic_caller);	if(call_point){#ifdef DEBUG_RTLINUX		printk("RTLinux debug zapping %x at %x\n",(unsigned int)apic_caller,(unsigned int)call_point);#endif		for(i=0; i<ack_len; i++)			call_point[i]= 0x90;	}}static void unzap_ack_apic(char *apic_caller){	int i;	int ack_len = (int) end_apic_ack  - (int)start_apic_ack;	char *call_point = match_ack(apic_caller);	if(call_point){#ifdef DEBUG_RTLINUX		printk("RTLinux debug unzapping %x at %x\n",(unsigned int)apic_caller,(unsigned int)call_point);#endif		for(i=0; i<ack_len; i++)			call_point[i]= ((char *)start_apic_ack)[i];	}}/* i8259.cBUILD_SMP_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -