Author: blueswirl Date: Sun Jan 30 14:07:31 2011 New Revision: 1015 URL: http://tracker.coreboot.org/trac/openbios/changeset/1015
Log: sparc32: avoid runtime relocations
The Forth dictionary was relocated at run time, incurring also a copy operation. The source dictionary remained in memory. It was not possible to run forthstrap without any input files besides the base dictionary.
Make forthstrap generate a hex dump which can be included in C, but also contains relocations, so that relocations are performed by the linker at compile time. Allow dictionary compilation with no source files.
Don't allocate the dictionary dynamically; reduce ofmem supply accordingly.
Signed-off-by: Blue Swirl blauwirbel@gmail.com
Modified: trunk/openbios-devel/arch/sparc32/build.xml trunk/openbios-devel/arch/sparc32/builtin.c trunk/openbios-devel/arch/sparc32/ofmem_sparc32.c trunk/openbios-devel/arch/sparc32/openbios.c trunk/openbios-devel/include/libopenbios/sys_info.h trunk/openbios-devel/kernel/bootstrap.c
Modified: trunk/openbios-devel/arch/sparc32/build.xml ============================================================================== --- trunk/openbios-devel/arch/sparc32/build.xml Sat Jan 8 20:44:38 2011 (r1014) +++ trunk/openbios-devel/arch/sparc32/build.xml Sun Jan 30 14:07:31 2011 (r1015) @@ -42,11 +42,7 @@
<executable name="target/include/static-dict.h" target="target" condition="IMAGE_ELF_EMBEDDED"> <rule><![CDATA[ - $(call quiet-command,true, " GEN $(TARGET_DIR)$@") - @echo "static const char forth_dictionary[] = {" > $@ - @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ - | sed 's/0x ,//g' >> $@ - @echo "};" >> $@]]></rule> + $(call quiet-command,$(ODIR)/forthstrap -x -D $@ -d $< </dev/null, " GEN $(TARGET_DIR)$@")]]></rule> <external-object source="openbios-sparc32.dict"/> </executable>
Modified: trunk/openbios-devel/arch/sparc32/builtin.c ============================================================================== --- trunk/openbios-devel/arch/sparc32/builtin.c Sat Jan 8 20:44:38 2011 (r1014) +++ trunk/openbios-devel/arch/sparc32/builtin.c Sun Jan 30 14:07:31 2011 (r1015) @@ -14,12 +14,20 @@ * wrap an array around the hex'ed dictionary file */
+/* 256K for the dictionary */ +#define DICTIONARY_SIZE (256 * 1024 / sizeof(ucell)) +#define DICTIONARY_BASE ((ucell)((char *)&forth_dictionary)) + +static ucell forth_dictionary[DICTIONARY_SIZE] = { #include "static-dict.h" +};
void collect_multiboot_info(struct sys_info *info); void collect_multiboot_info(struct sys_info *info) { info->dict_start=(unsigned long *)forth_dictionary; - info->dict_end=(unsigned long *)((ucell)forth_dictionary + - sizeof(forth_dictionary)); + info->dict_end = (unsigned long *)FORTH_DICTIONARY_END; + info->dict_last = (ucell *)((unsigned char *)forth_dictionary + + FORTH_DICTIONARY_LAST); + info->dict_limit = sizeof(forth_dictionary); }
Modified: trunk/openbios-devel/arch/sparc32/ofmem_sparc32.c ============================================================================== --- trunk/openbios-devel/arch/sparc32/ofmem_sparc32.c Sat Jan 8 20:44:38 2011 (r1014) +++ trunk/openbios-devel/arch/sparc32/ofmem_sparc32.c Sun Jan 30 14:07:31 2011 (r1015) @@ -21,7 +21,7 @@
#define OF_MALLOC_BASE ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8))
-#define MEMSIZE (512 * 1024) +#define MEMSIZE (256 * 1024) static union { char memory[MEMSIZE]; ofmem_t ofmem;
Modified: trunk/openbios-devel/arch/sparc32/openbios.c ============================================================================== --- trunk/openbios-devel/arch/sparc32/openbios.c Sat Jan 8 20:44:38 2011 (r1014) +++ trunk/openbios-devel/arch/sparc32/openbios.c Sun Jan 30 14:07:31 2011 (r1015) @@ -28,7 +28,6 @@ #include "libopenbios/ofmem.h"
#define MEMORY_SIZE (16*1024) /* 16K ram for hosted system */ -#define DICTIONARY_SIZE (256*1024) /* 256K for the dictionary */ #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" #define FW_CFG_SUN4M_DEPTH (FW_CFG_ARCH_LOCAL + 0x00)
@@ -968,12 +967,11 @@
collect_sys_info(&sys_info);
- dict = malloc(DICTIONARY_SIZE); - dictlimit = DICTIONARY_SIZE; + dict = (unsigned char *)sys_info.dict_start; + dicthead = (cell)sys_info.dict_end; + last = sys_info.dict_last; + dictlimit = sys_info.dict_limit;
- load_dictionary((char *)sys_info.dict_start, - (unsigned long)sys_info.dict_end - - (unsigned long)sys_info.dict_start); forth_init();
#ifdef CONFIG_DEBUG_BOOT
Modified: trunk/openbios-devel/include/libopenbios/sys_info.h ============================================================================== --- trunk/openbios-devel/include/libopenbios/sys_info.h Sat Jan 8 20:44:38 2011 (r1014) +++ trunk/openbios-devel/include/libopenbios/sys_info.h Sun Jan 30 14:07:31 2011 (r1015) @@ -20,6 +20,8 @@ } *memrange; unsigned long *dict_start; unsigned long *dict_end; + cell dict_limit; + ucell *dict_last; };
extern void *elf_boot_notes;
Modified: trunk/openbios-devel/kernel/bootstrap.c ============================================================================== --- trunk/openbios-devel/kernel/bootstrap.c Sat Jan 8 20:44:38 2011 (r1014) +++ trunk/openbios-devel/kernel/bootstrap.c Sun Jan 30 14:07:31 2011 (r1015) @@ -96,6 +96,11 @@ * dictionary related functions. */
+/* + * Compare two dictionaries constructed at different addresses. When + * the cells don't match, a need for relocation is detected and the + * corresponding bit in reloc_table bitmap is set. + */ static void relocation_table(unsigned char * dict_one, unsigned char *dict_two, int length) { ucell *d1=(ucell *)dict_one, *d2=(ucell *)dict_two; @@ -237,6 +242,54 @@ #endif }
+/* + * Write dictionary as a list of ucell hex values to filename. Array + * header and end lines are not generated. + * + * Cells with relocations are output using the expression + * DICTIONARY_BASE + value. + * + * Define some helpful constants. + */ +static void write_dictionary_hex(const char *filename) +{ + FILE *f; + ucell *walk; + + f = fopen(filename, "w"); + if (!f) { + printk("panic: can't write to dictionary '%s'.\n", filename); + exit(1); + } + + for (walk = (ucell *)dict; walk < (ucell *)(dict + dicthead); walk++) { + int pos, bit, l; + ucell val; + + l = (walk - (ucell *)dict); + pos = l / BITS; + bit = l & ~(-BITS); + + val = read_ucell(walk); + if (relocation_address[pos] & target_ucell((ucell)1ULL << bit)) { + fprintf(f, "DICTIONARY_BASE + 0x%" FMT_CELL_x + ",\n", val); + } else { + fprintf(f, "0x%" FMT_CELL_x",\n", val); + } + } + + fprintf(f, "#define FORTH_DICTIONARY_LAST 0x%" FMT_CELL_x"\n", + (ucell)((unsigned long)last - (unsigned long)dict)); + fprintf(f, "#define FORTH_DICTIONARY_END 0x%" FMT_CELL_x"\n", + (ucell)dicthead); + fclose(f); + +#ifdef CONFIG_DEBUG_DICTIONARY + printk("wrote dictionary to file %s.\n", filename); +#endif +} + static ucell read_dictionary(char *fil) { int ilen; @@ -1032,7 +1085,8 @@ " write kernel console output to log file\n" \ " -s|--segfault install segfault handler\n" \ " -M|--dependency-dump file\n" \ - " dump dependencies in Makefile format\n\n" + " dump dependencies in Makefile format\n\n" \ + " -x|--hexdump output format is C language hex dump\n" #else #define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \ " -h show this help\n" \ @@ -1045,8 +1099,9 @@ " write to output.dict\n" \ " -c output.log\n" \ " write kernel console output to log file\n" \ - " -s install segfault handler\n\n" - " -M file dump dependencies in Makefile format\n\n" + " -s install segfault handler\n\n" \ + " -M file dump dependencies in Makefile format\n\n" \ + " -x output format is C language hex dump\n" #endif
int main(int argc, char *argv[]) @@ -1054,15 +1109,15 @@ struct sigaction sa;
unsigned char *ressources=NULL; /* All memory used by us */ - char *dictname = NULL; + const char *dictname = NULL; char *basedict = NULL; char *consolefile = NULL; char *depfilename = NULL;
unsigned char *bootstrapdict[2]; - int c, cnt; + int c, cnt, hexdump = 0;
- const char *optstring = "VvhsI:d:D:c:M:?"; + const char *optstring = "VvhsI:d:D:c:M:x?";
while (1) { #ifdef __GLIBC__ @@ -1077,6 +1132,7 @@ {"target-dictionary", 1, NULL, 'D'}, {"console", 1, NULL, 'c'}, {"dependency-dump", 1, NULL, 'M'}, + {"hexdump", 0, NULL, 'x'}, };
/* @@ -1132,11 +1188,17 @@ depfilename = optarg; } break; + case 'x': + hexdump = 1; + break; default: return 1; } }
+ if (!dictname) { + dictname = "bootstrap.dict"; + } if (verbose) { printk(BANNER); printk("Using source dictionary '%s'\n", basedict); @@ -1144,7 +1206,7 @@ printk("Dumping dependencies to '%s'\n", depfilename); }
- if (argc < optind + 1) { + if (argc < optind) { printk(USAGE, argv[0]); return 1; } @@ -1243,7 +1305,11 @@ #endif { relocation_table( bootstrapdict[0], bootstrapdict[1], dicthead); - write_dictionary( dictname ? dictname : "bootstrap.dict"); + if (hexdump) { + write_dictionary_hex(dictname); + } else { + write_dictionary(dictname); + } }
free(ressources);