diff options
Diffstat (limited to 'arch/mips/kernel/vpe.c')
-rw-r--r-- | arch/mips/kernel/vpe.c | 113 |
1 files changed, 52 insertions, 61 deletions
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 29933652ff4a..1765bab000a0 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c | |||
@@ -254,7 +254,7 @@ static void __maybe_unused dump_mtregs(void) | |||
254 | val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT); | 254 | val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT); |
255 | } | 255 | } |
256 | 256 | ||
257 | /* Find some VPE program space */ | 257 | /* Find some VPE program space */ |
258 | static void *alloc_progmem(unsigned long len) | 258 | static void *alloc_progmem(unsigned long len) |
259 | { | 259 | { |
260 | void *addr; | 260 | void *addr; |
@@ -292,7 +292,7 @@ static long get_offset(unsigned long *size, Elf_Shdr * sechdr) | |||
292 | } | 292 | } |
293 | 293 | ||
294 | /* Lay out the SHF_ALLOC sections in a way not dissimilar to how ld | 294 | /* Lay out the SHF_ALLOC sections in a way not dissimilar to how ld |
295 | might -- code, read-only data, read-write data, small data. Tally | 295 | might -- code, read-only data, read-write data, small data. Tally |
296 | sizes, and place the offsets into sh_entsize fields: high bit means it | 296 | sizes, and place the offsets into sh_entsize fields: high bit means it |
297 | belongs in init. */ | 297 | belongs in init. */ |
298 | static void layout_sections(struct module *mod, const Elf_Ehdr * hdr, | 298 | static void layout_sections(struct module *mod, const Elf_Ehdr * hdr, |
@@ -386,7 +386,7 @@ static int apply_r_mips_pc16(struct module *me, uint32_t *location, | |||
386 | 386 | ||
387 | if( (rel > 32768) || (rel < -32768) ) { | 387 | if( (rel > 32768) || (rel < -32768) ) { |
388 | printk(KERN_DEBUG "VPE loader: " | 388 | printk(KERN_DEBUG "VPE loader: " |
389 | "apply_r_mips_pc16: relative address out of range 0x%x\n", rel); | 389 | "apply_r_mips_pc16: relative address out of range 0x%x\n", rel); |
390 | return -ENOEXEC; | 390 | return -ENOEXEC; |
391 | } | 391 | } |
392 | 392 | ||
@@ -458,7 +458,7 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location, | |||
458 | Elf32_Addr val, vallo; | 458 | Elf32_Addr val, vallo; |
459 | struct mips_hi16 *l, *next; | 459 | struct mips_hi16 *l, *next; |
460 | 460 | ||
461 | /* Sign extend the addend we extract from the lo insn. */ | 461 | /* Sign extend the addend we extract from the lo insn. */ |
462 | vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; | 462 | vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; |
463 | 463 | ||
464 | if (mips_hi16_list != NULL) { | 464 | if (mips_hi16_list != NULL) { |
@@ -470,7 +470,7 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location, | |||
470 | /* | 470 | /* |
471 | * The value for the HI16 had best be the same. | 471 | * The value for the HI16 had best be the same. |
472 | */ | 472 | */ |
473 | if (v != l->value) { | 473 | if (v != l->value) { |
474 | printk(KERN_DEBUG "VPE loader: " | 474 | printk(KERN_DEBUG "VPE loader: " |
475 | "apply_r_mips_lo16/hi16: \t" | 475 | "apply_r_mips_lo16/hi16: \t" |
476 | "inconsistent value information\n"); | 476 | "inconsistent value information\n"); |
@@ -505,7 +505,7 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location, | |||
505 | } | 505 | } |
506 | 506 | ||
507 | /* | 507 | /* |
508 | * Ok, we're done with the HI16 relocs. Now deal with the LO16. | 508 | * Ok, we're done with the HI16 relocs. Now deal with the LO16. |
509 | */ | 509 | */ |
510 | val = v + vallo; | 510 | val = v + vallo; |
511 | insnlo = (insnlo & ~0xffff) | (val & 0xffff); | 511 | insnlo = (insnlo & ~0xffff) | (val & 0xffff); |
@@ -579,7 +579,7 @@ static int apply_relocations(Elf32_Shdr *sechdrs, | |||
579 | res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v); | 579 | res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v); |
580 | if( res ) { | 580 | if( res ) { |
581 | char *r = rstrs[ELF32_R_TYPE(r_info)]; | 581 | char *r = rstrs[ELF32_R_TYPE(r_info)]; |
582 | printk(KERN_WARNING "VPE loader: .text+0x%x " | 582 | printk(KERN_WARNING "VPE loader: .text+0x%x " |
583 | "relocation type %s for symbol \"%s\" failed\n", | 583 | "relocation type %s for symbol \"%s\" failed\n", |
584 | rel[i].r_offset, r ? r : "UNKNOWN", | 584 | rel[i].r_offset, r ? r : "UNKNOWN", |
585 | strtab + sym->st_name); | 585 | strtab + sym->st_name); |
@@ -697,18 +697,7 @@ static int vpe_run(struct vpe * v) | |||
697 | dmt_flag = dmt(); | 697 | dmt_flag = dmt(); |
698 | vpeflags = dvpe(); | 698 | vpeflags = dvpe(); |
699 | 699 | ||
700 | if (!list_empty(&v->tc)) { | 700 | if (list_empty(&v->tc)) { |
701 | if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) { | ||
702 | evpe(vpeflags); | ||
703 | emt(dmt_flag); | ||
704 | local_irq_restore(flags); | ||
705 | |||
706 | printk(KERN_WARNING | ||
707 | "VPE loader: TC %d is already in use.\n", | ||
708 | v->tc->index); | ||
709 | return -ENOEXEC; | ||
710 | } | ||
711 | } else { | ||
712 | evpe(vpeflags); | 701 | evpe(vpeflags); |
713 | emt(dmt_flag); | 702 | emt(dmt_flag); |
714 | local_irq_restore(flags); | 703 | local_irq_restore(flags); |
@@ -720,6 +709,8 @@ static int vpe_run(struct vpe * v) | |||
720 | return -ENOEXEC; | 709 | return -ENOEXEC; |
721 | } | 710 | } |
722 | 711 | ||
712 | t = list_first_entry(&v->tc, struct tc, tc); | ||
713 | |||
723 | /* Put MVPE's into 'configuration state' */ | 714 | /* Put MVPE's into 'configuration state' */ |
724 | set_c0_mvpcontrol(MVPCONTROL_VPC); | 715 | set_c0_mvpcontrol(MVPCONTROL_VPC); |
725 | 716 | ||
@@ -772,7 +763,7 @@ static int vpe_run(struct vpe * v) | |||
772 | 763 | ||
773 | /* Set up the XTC bit in vpeconf0 to point at our tc */ | 764 | /* Set up the XTC bit in vpeconf0 to point at our tc */ |
774 | write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC)) | 765 | write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC)) |
775 | | (t->index << VPECONF0_XTC_SHIFT)); | 766 | | (t->index << VPECONF0_XTC_SHIFT)); |
776 | 767 | ||
777 | back_to_back_c0_hazard(); | 768 | back_to_back_c0_hazard(); |
778 | 769 | ||
@@ -926,34 +917,34 @@ static int vpe_elfload(struct vpe * v) | |||
926 | secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr); | 917 | secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr); |
927 | } | 918 | } |
928 | 919 | ||
929 | /* Fix up syms, so that st_value is a pointer to location. */ | 920 | /* Fix up syms, so that st_value is a pointer to location. */ |
930 | simplify_symbols(sechdrs, symindex, strtab, secstrings, | 921 | simplify_symbols(sechdrs, symindex, strtab, secstrings, |
931 | hdr->e_shnum, &mod); | 922 | hdr->e_shnum, &mod); |
932 | 923 | ||
933 | /* Now do relocations. */ | 924 | /* Now do relocations. */ |
934 | for (i = 1; i < hdr->e_shnum; i++) { | 925 | for (i = 1; i < hdr->e_shnum; i++) { |
935 | const char *strtab = (char *)sechdrs[strindex].sh_addr; | 926 | const char *strtab = (char *)sechdrs[strindex].sh_addr; |
936 | unsigned int info = sechdrs[i].sh_info; | 927 | unsigned int info = sechdrs[i].sh_info; |
937 | 928 | ||
938 | /* Not a valid relocation section? */ | 929 | /* Not a valid relocation section? */ |
939 | if (info >= hdr->e_shnum) | 930 | if (info >= hdr->e_shnum) |
940 | continue; | 931 | continue; |
941 | 932 | ||
942 | /* Don't bother with non-allocated sections */ | 933 | /* Don't bother with non-allocated sections */ |
943 | if (!(sechdrs[info].sh_flags & SHF_ALLOC)) | 934 | if (!(sechdrs[info].sh_flags & SHF_ALLOC)) |
944 | continue; | 935 | continue; |
945 | 936 | ||
946 | if (sechdrs[i].sh_type == SHT_REL) | 937 | if (sechdrs[i].sh_type == SHT_REL) |
947 | err = apply_relocations(sechdrs, strtab, symindex, i, | 938 | err = apply_relocations(sechdrs, strtab, symindex, i, |
948 | &mod); | 939 | &mod); |
949 | else if (sechdrs[i].sh_type == SHT_RELA) | 940 | else if (sechdrs[i].sh_type == SHT_RELA) |
950 | err = apply_relocate_add(sechdrs, strtab, symindex, i, | 941 | err = apply_relocate_add(sechdrs, strtab, symindex, i, |
951 | &mod); | 942 | &mod); |
952 | if (err < 0) | 943 | if (err < 0) |
953 | return err; | 944 | return err; |
954 | 945 | ||
955 | } | 946 | } |
956 | } else { | 947 | } else { |
957 | struct elf_phdr *phdr = (struct elf_phdr *) ((char *)hdr + hdr->e_phoff); | 948 | struct elf_phdr *phdr = (struct elf_phdr *) ((char *)hdr + hdr->e_phoff); |
958 | 949 | ||
959 | for (i = 0; i < hdr->e_phnum; i++) { | 950 | for (i = 0; i < hdr->e_phnum; i++) { |
@@ -968,16 +959,16 @@ static int vpe_elfload(struct vpe * v) | |||
968 | } | 959 | } |
969 | 960 | ||
970 | for (i = 0; i < hdr->e_shnum; i++) { | 961 | for (i = 0; i < hdr->e_shnum; i++) { |
971 | /* Internal symbols and strings. */ | 962 | /* Internal symbols and strings. */ |
972 | if (sechdrs[i].sh_type == SHT_SYMTAB) { | 963 | if (sechdrs[i].sh_type == SHT_SYMTAB) { |
973 | symindex = i; | 964 | symindex = i; |
974 | strindex = sechdrs[i].sh_link; | 965 | strindex = sechdrs[i].sh_link; |
975 | strtab = (char *)hdr + sechdrs[strindex].sh_offset; | 966 | strtab = (char *)hdr + sechdrs[strindex].sh_offset; |
976 | 967 | ||
977 | /* mark the symtab's address for when we try to find the | 968 | /* mark the symtab's address for when we try to find the |
978 | magic symbols */ | 969 | magic symbols */ |
979 | sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset; | 970 | sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset; |
980 | } | 971 | } |
981 | } | 972 | } |
982 | } | 973 | } |
983 | 974 | ||
@@ -1049,7 +1040,7 @@ static int getcwd(char *buff, int size) | |||
1049 | return ret; | 1040 | return ret; |
1050 | } | 1041 | } |
1051 | 1042 | ||
1052 | /* checks VPE is unused and gets ready to load program */ | 1043 | /* checks VPE is unused and gets ready to load program */ |
1053 | static int vpe_open(struct inode *inode, struct file *filp) | 1044 | static int vpe_open(struct inode *inode, struct file *filp) |
1054 | { | 1045 | { |
1055 | enum vpe_state state; | 1046 | enum vpe_state state; |
@@ -1121,11 +1112,11 @@ static int vpe_release(struct inode *inode, struct file *filp) | |||
1121 | if (vpe_elfload(v) >= 0) { | 1112 | if (vpe_elfload(v) >= 0) { |
1122 | vpe_run(v); | 1113 | vpe_run(v); |
1123 | } else { | 1114 | } else { |
1124 | printk(KERN_WARNING "VPE loader: ELF load failed.\n"); | 1115 | printk(KERN_WARNING "VPE loader: ELF load failed.\n"); |
1125 | ret = -ENOEXEC; | 1116 | ret = -ENOEXEC; |
1126 | } | 1117 | } |
1127 | } else { | 1118 | } else { |
1128 | printk(KERN_WARNING "VPE loader: only elf files are supported\n"); | 1119 | printk(KERN_WARNING "VPE loader: only elf files are supported\n"); |
1129 | ret = -ENOEXEC; | 1120 | ret = -ENOEXEC; |
1130 | } | 1121 | } |
1131 | 1122 | ||