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

📄 vpe.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*	 * Ok, we're done with the HI16 relocs.  Now deal with the LO16.	 */	val = v + vallo;	insnlo = (insnlo & ~0xffff) | (val & 0xffff);	*location = insnlo;	return 0;}static int (*reloc_handlers[]) (struct module *me, uint32_t *location,				Elf32_Addr v) = {	[R_MIPS_NONE]	= apply_r_mips_none,	[R_MIPS_32]	= apply_r_mips_32,	[R_MIPS_26]	= apply_r_mips_26,	[R_MIPS_HI16]	= apply_r_mips_hi16,	[R_MIPS_LO16]	= apply_r_mips_lo16,	[R_MIPS_GPREL16] = apply_r_mips_gprel16,	[R_MIPS_PC16] = apply_r_mips_pc16};static char *rstrs[] = {    	[R_MIPS_NONE]	= "MIPS_NONE",	[R_MIPS_32]	= "MIPS_32",	[R_MIPS_26]	= "MIPS_26",	[R_MIPS_HI16]	= "MIPS_HI16",	[R_MIPS_LO16]	= "MIPS_LO16",	[R_MIPS_GPREL16] = "MIPS_GPREL16",	[R_MIPS_PC16] = "MIPS_PC16"};int apply_relocations(Elf32_Shdr *sechdrs,		      const char *strtab,		      unsigned int symindex,		      unsigned int relsec,		      struct module *me){	Elf32_Rel *rel = (void *) sechdrs[relsec].sh_addr;	Elf32_Sym *sym;	uint32_t *location;	unsigned int i;	Elf32_Addr v;	int res;	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {		Elf32_Word r_info = rel[i].r_info;		/* This is where to make the change */		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr			+ rel[i].r_offset;		/* This is the symbol it is referring to */		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr			+ ELF32_R_SYM(r_info);		if (!sym->st_value) {			printk(KERN_DEBUG "%s: undefined weak symbol %s\n",			       me->name, strtab + sym->st_name);			/* just print the warning, dont barf */		}		v = sym->st_value;		res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v);		if( res ) {			char *r = rstrs[ELF32_R_TYPE(r_info)];		    	printk(KERN_WARNING "VPE loader: .text+0x%x "			       "relocation type %s for symbol \"%s\" failed\n",			       rel[i].r_offset, r ? r : "UNKNOWN",			       strtab + sym->st_name);			return res;		}	}	return 0;}void save_gp_address(unsigned int secbase, unsigned int rel){	gp_addr = secbase + rel;	gp_offs = gp_addr - (secbase & 0xffff0000);}/* end module-elf32.c *//* Change all symbols so that sh_value encodes the pointer directly. */static void simplify_symbols(Elf_Shdr * sechdrs,			    unsigned int symindex,			    const char *strtab,			    const char *secstrings,			    unsigned int nsecs, struct module *mod){	Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;	unsigned long secbase, bssbase = 0;	unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);	int size;	/* find the .bss section for COMMON symbols */	for (i = 0; i < nsecs; i++) {		if (strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) == 0) {			bssbase = sechdrs[i].sh_addr;			break;		}	}	for (i = 1; i < n; i++) {		switch (sym[i].st_shndx) {		case SHN_COMMON:			/* Allocate space for the symbol in the .bss section.			   st_value is currently size.			   We want it to have the address of the symbol. */			size = sym[i].st_value;			sym[i].st_value = bssbase;			bssbase += size;			break;		case SHN_ABS:			/* Don't need to do anything */			break;		case SHN_UNDEF:			/* ret = -ENOENT; */			break;		case SHN_MIPS_SCOMMON:			printk(KERN_DEBUG "simplify_symbols: ignoring SHN_MIPS_SCOMMON"			       "symbol <%s> st_shndx %d\n", strtab + sym[i].st_name,			       sym[i].st_shndx);			// .sbss section			break;		default:			secbase = sechdrs[sym[i].st_shndx].sh_addr;			if (strncmp(strtab + sym[i].st_name, "_gp", 3) == 0) {				save_gp_address(secbase, sym[i].st_value);			}			sym[i].st_value += secbase;			break;		}	}}#ifdef DEBUG_ELFLOADERstatic void dump_elfsymbols(Elf_Shdr * sechdrs, unsigned int symindex,			    const char *strtab, struct module *mod){	Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;	unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);	printk(KERN_DEBUG "dump_elfsymbols: n %d\n", n);	for (i = 1; i < n; i++) {		printk(KERN_DEBUG " i %d name <%s> 0x%x\n", i,		       strtab + sym[i].st_name, sym[i].st_value);	}}#endifstatic void dump_tc(struct tc *t){  	unsigned long val;  	settc(t->index); 	printk(KERN_DEBUG "VPE loader: TC index %d targtc %ld " 	       "TCStatus 0x%lx halt 0x%lx\n",  	       t->index, read_c0_vpecontrol() & VPECONTROL_TARGTC,  	       read_tc_c0_tcstatus(), read_tc_c0_tchalt()); 	printk(KERN_DEBUG " tcrestart 0x%lx\n", read_tc_c0_tcrestart()); 	printk(KERN_DEBUG " tcbind 0x%lx\n", read_tc_c0_tcbind());  	val = read_c0_vpeconf0(); 	printk(KERN_DEBUG " VPEConf0 0x%lx MVP %ld\n", val,  	       (val & VPECONF0_MVP) >> VPECONF0_MVP_SHIFT); 	printk(KERN_DEBUG " c0 status 0x%lx\n", read_vpe_c0_status()); 	printk(KERN_DEBUG " c0 cause 0x%lx\n", read_vpe_c0_cause()); 	printk(KERN_DEBUG " c0 badvaddr 0x%lx\n", read_vpe_c0_badvaddr()); 	printk(KERN_DEBUG " c0 epc 0x%lx\n", read_vpe_c0_epc());}static void dump_tclist(void){	struct tc *t;	list_for_each_entry(t, &vpecontrol.tc_list, list) {		dump_tc(t);	}}/* We are prepared so configure and start the VPE... */int vpe_run(struct vpe * v){	struct vpe_notifications *n;	unsigned long val, dmt_flag;	struct tc *t;	/* check we are the Master VPE */	val = read_c0_vpeconf0();	if (!(val & VPECONF0_MVP)) {		printk(KERN_WARNING		       "VPE loader: only Master VPE's are allowed to configure MT\n");		return -1;	}	/* disable MT (using dvpe) */	dvpe();	if (!list_empty(&v->tc)) {                if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {                        printk(KERN_WARNING "VPE loader: TC %d is already in use.\n",                               t->index);                        return -ENOEXEC;                }        } else {                printk(KERN_WARNING "VPE loader: No TC's associated with VPE %d\n",                       v->minor);                return -ENOEXEC;        }	/* Put MVPE's into 'configuration state' */	set_c0_mvpcontrol(MVPCONTROL_VPC);	settc(t->index);	/* should check it is halted, and not activated */	if ((read_tc_c0_tcstatus() & TCSTATUS_A) || !(read_tc_c0_tchalt() & TCHALT_H)) {		printk(KERN_WARNING "VPE loader: TC %d is already doing something!\n",		       t->index);		dump_tclist();		return -ENOEXEC;	}	/*	 * Disable multi-threaded execution whilst we activate, clear the	 * halt bit and bound the tc to the other VPE...	 */	dmt_flag = dmt();	/* Write the address we want it to start running from in the TCPC register. */	write_tc_c0_tcrestart((unsigned long)v->__start);	write_tc_c0_tccontext((unsigned long)0);	/*	 * Mark the TC as activated, not interrupt exempt and not dynamically	 * allocatable	 */	val = read_tc_c0_tcstatus();	val = (val & ~(TCSTATUS_DA | TCSTATUS_IXMT)) | TCSTATUS_A;	write_tc_c0_tcstatus(val);	write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);	/*	 * The sde-kit passes 'memsize' to __start in $a3, so set something	 * here...  Or set $a3 to zero and define DFLT_STACK_SIZE and	 * DFLT_HEAP_SIZE when you compile your program	 */ 	mttgpr(7, physical_memsize);	/* set up VPE1 */	/*	 * bind the TC to VPE 1 as late as possible so we only have the final	 * VPE registers to set up, and so an EJTAG probe can trigger on it	 */ 	write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | v->minor);        /* Set up the XTC bit in vpeconf0 to point at our tc */        write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))                               | (t->index << VPECONF0_XTC_SHIFT));        /* enable this VPE */        write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);	/* clear out any left overs from a previous program */	write_vpe_c0_status(0);	write_vpe_c0_cause(0);	/* take system out of configuration state */	clear_c0_mvpcontrol(MVPCONTROL_VPC);	/* now safe to re-enable multi-threading */	emt(dmt_flag);	/* set it running */	evpe(EVPE_ENABLE);	list_for_each_entry(n, &v->notify, list) {		n->start(v->minor);	}	return 0;}static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,				      unsigned int symindex, const char *strtab,				      struct module *mod){	Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;	unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);	for (i = 1; i < n; i++) {		if (strcmp(strtab + sym[i].st_name, "__start") == 0) {			v->__start = sym[i].st_value;		}		if (strcmp(strtab + sym[i].st_name, "vpe_shared") == 0) {			v->shared_ptr = (void *)sym[i].st_value;		}	}	if ( (v->__start == 0) || (v->shared_ptr == NULL))		return -1;	return 0;}/* * Allocates a VPE with some program code space(the load address), copies the * contents of the program (p)buffer performing relocatations/etc, free's it * when finished. */int vpe_elfload(struct vpe * v){	Elf_Ehdr *hdr;	Elf_Shdr *sechdrs;	long err = 0;	char *secstrings, *strtab = NULL;	unsigned int len, i, symindex = 0, strindex = 0, relocate = 0;	struct module mod;	// so we can re-use the relocations code	memset(&mod, 0, sizeof(struct module));	strcpy(mod.name, "VPE loader");	hdr = (Elf_Ehdr *) v->pbuffer;	len = v->plen;	/* Sanity checks against insmoding binaries or wrong arch,	   weird elf version */	if (memcmp(hdr->e_ident, ELFMAG, 4) != 0	    || (hdr->e_type != ET_REL && hdr->e_type != ET_EXEC)	    || !elf_check_arch(hdr)	    || hdr->e_shentsize != sizeof(*sechdrs)) {		printk(KERN_WARNING		       "VPE loader: program wrong arch or weird elf version\n");		return -ENOEXEC;	}	if (hdr->e_type == ET_REL)		relocate = 1;	if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) {		printk(KERN_ERR "VPE loader: program length %u truncated\n",		       len);		return -ENOEXEC;	}	/* Convenience variables */	sechdrs = (void *)hdr + hdr->e_shoff;	secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;	sechdrs[0].sh_addr = 0;	/* And these should exist, but gcc whinges if we don't init them */	symindex = strindex = 0;	if (relocate) {		for (i = 1; i < hdr->e_shnum; i++) {			if (sechdrs[i].sh_type != SHT_NOBITS			    && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {				printk(KERN_ERR "VPE program length %u truncated\n",				       len);				return -ENOEXEC;			}			/* Mark all sections sh_addr with their address in the			   temporary image. */			sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;			/* Internal symbols and strings. */			if (sechdrs[i].sh_type == SHT_SYMTAB) {				symindex = i;				strindex = sechdrs[i].sh_link;				strtab = (char *)hdr + sechdrs[strindex].sh_offset;			}		}		layout_sections(&mod, hdr, sechdrs, secstrings);	}	v->load_addr = alloc_progmem(mod.core_size);	memset(v->load_addr, 0, mod.core_size);	printk("VPE loader: loading to %p\n", v->load_addr);	if (relocate) {		for (i = 0; i < hdr->e_shnum; i++) {			void *dest;			if (!(sechdrs[i].sh_flags & SHF_ALLOC))				continue;			dest = v->load_addr + sechdrs[i].sh_entsize;			if (sechdrs[i].sh_type != SHT_NOBITS)				memcpy(dest, (void *)sechdrs[i].sh_addr,				       sechdrs[i].sh_size);			/* Update sh_addr to point to copy in image. */			sechdrs[i].sh_addr = (unsigned long)dest;			printk(KERN_DEBUG " section sh_name %s sh_addr 0x%x\n",			       secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr);		} 		/* Fix up syms, so that st_value is a pointer to location. */ 		simplify_symbols(sechdrs, symindex, strtab, secstrings, 				 hdr->e_shnum, &mod); 		/* Now do relocations. */ 		for (i = 1; i < hdr->e_shnum; i++) { 			const char *strtab = (char *)sechdrs[strindex].sh_addr; 			unsigned int info = sechdrs[i].sh_info; 			/* Not a valid relocation section? */ 			if (info >= hdr->e_shnum) 				continue; 			/* Don't bother with non-allocated sections */ 			if (!(sechdrs[info].sh_flags & SHF_ALLOC)) 				continue; 			if (sechdrs[i].sh_type == SHT_REL) 				err = apply_relocations(sechdrs, strtab, symindex, i, 							&mod); 			else if (sechdrs[i].sh_type == SHT_RELA) 				err = apply_relocate_add(sechdrs, strtab, symindex, i, 							 &mod); 			if (err < 0) 				return err;  		}  	} else {  		for (i = 0; i < hdr->e_shnum; i++) { 			/* Internal symbols and strings. */ 			if (sechdrs[i].sh_type == SHT_SYMTAB) { 				symindex = i; 				strindex = sechdrs[i].sh_link; 				strtab = (char *)hdr + sechdrs[strindex].sh_offset; 				/* mark the symtab's address for when we try to find the 				   magic symbols */ 				sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset; 			} 			/* filter sections we dont want in the final image */ 			if (!(sechdrs[i].sh_flags & SHF_ALLOC) || 			    (sechdrs[i].sh_type == SHT_MIPS_REGINFO)) { 				printk( KERN_DEBUG " ignoring section, " 					"name %s type %x address 0x%x \n", 					secstrings + sechdrs[i].sh_name, 					sechdrs[i].sh_type, sechdrs[i].sh_addr); 				continue; 			}  			if (sechdrs[i].sh_addr < (unsigned int)v->load_addr) { 				printk( KERN_WARNING "VPE loader: " 					"fully linked image has invalid section, " 					"name %s type %x address 0x%x, before load " 					"address of 0x%x\n", 					secstrings + sechdrs[i].sh_name, 					sechdrs[i].sh_type, sechdrs[i].sh_addr, 					(unsigned int)v->load_addr);  				return -ENOEXEC;  			} 			printk(KERN_DEBUG " copying section sh_name %s, sh_addr 0x%x "			       "size 0x%x0 from x%p\n",			       secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr,			       sechdrs[i].sh_size, hdr + sechdrs[i].sh_offset);  			if (sechdrs[i].sh_type != SHT_NOBITS)				memcpy((void *)sechdrs[i].sh_addr,				       (char *)hdr + sechdrs[i].sh_offset, 				       sechdrs[i].sh_size);			else				memset((void *)sechdrs[i].sh_addr, 0, sechdrs[i].sh_size);		}	}	/* make sure it's physically written out */	flush_icache_range((unsigned long)v->load_addr,			   (unsigned long)v->load_addr + v->len);

⌨️ 快捷键说明

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