[OpenBIOS] [PATCH 1/4] sparc32: avoid runtime relocations

Blue Swirl blauwirbel at gmail.com
Sun Jan 23 12:56:00 CET 2011


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 at gmail.com>
---
 arch/sparc32/build.xml         |    6 +--
 arch/sparc32/builtin.c         |   12 +++++-
 arch/sparc32/ofmem_sparc32.c   |    2 +-
 arch/sparc32/openbios.c        |   10 ++---
 include/libopenbios/sys_info.h |    2 +
 kernel/bootstrap.c             |   82 ++++++++++++++++++++++++++++++++++++----
 6 files changed, 92 insertions(+), 22 deletions(-)

diff --git a/arch/sparc32/build.xml b/arch/sparc32/build.xml
index 3d2f71d..47ad01a 100644
--- a/arch/sparc32/build.xml
+++ b/arch/sparc32/build.xml
@@ -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>

diff --git a/arch/sparc32/builtin.c b/arch/sparc32/builtin.c
index 8bcce4c..971a400 100644
--- a/arch/sparc32/builtin.c
+++ b/arch/sparc32/builtin.c
@@ -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);
 }
diff --git a/arch/sparc32/ofmem_sparc32.c b/arch/sparc32/ofmem_sparc32.c
index 6815349..72079b2 100644
--- a/arch/sparc32/ofmem_sparc32.c
+++ b/arch/sparc32/ofmem_sparc32.c
@@ -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;
diff --git a/arch/sparc32/openbios.c b/arch/sparc32/openbios.c
index c940a5f..1d8842a 100644
--- a/arch/sparc32/openbios.c
+++ b/arch/sparc32/openbios.c
@@ -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 @@ int openbios(void)

         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
diff --git a/include/libopenbios/sys_info.h b/include/libopenbios/sys_info.h
index 2eea9af..a8b3cce 100644
--- a/include/libopenbios/sys_info.h
+++ b/include/libopenbios/sys_info.h
@@ -20,6 +20,8 @@ struct sys_info {
     } *memrange;
     unsigned long *dict_start;
     unsigned long *dict_end;
+    cell dict_limit;
+    ucell *dict_last;
 };

 extern void *elf_boot_notes;
diff --git a/kernel/bootstrap.c b/kernel/bootstrap.c
index 94aaeb8..546ffee 100644
--- a/kernel/bootstrap.c
+++ b/kernel/bootstrap.c
@@ -96,6 +96,11 @@ static const char *wordnames[] = {
  * 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 @@ static void write_dictionary(const char *filename)
 #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 @@ static void new_dictionary(const char *source)
 		"			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 @@ static void new_dictionary(const char *source)
 		"		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 @@ int main(int argc, char *argv[])
 	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 @@ int main(int argc, char *argv[])
 			{"target-dictionary", 1, NULL, 'D'},
 			{"console", 1, NULL, 'c'},
                         {"dependency-dump", 1, NULL, 'M'},
+                        {"hexdump", 0, NULL, 'x'},
 		};

 		/*
@@ -1132,11 +1188,17 @@ int main(int argc, char *argv[])
                                 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 @@ int main(int argc, char *argv[])
                 printk("Dumping dependencies to '%s'\n", depfilename);
         }

-	if (argc < optind + 1) {
+        if (argc < optind) {
 		printk(USAGE, argv[0]);
 		return 1;
 	}
@@ -1243,7 +1305,11 @@ int main(int argc, char *argv[])
 #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);
-- 
1.6.2.4
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-sparc32-avoid-runtime-relocations.patch
Type: application/mbox
Size: 9735 bytes
Desc: not available
URL: <http://lists.openbios.org/pipermail/openbios/attachments/20110123/b18a55c8/attachment.bin>


More information about the OpenBIOS mailing list