[OpenBIOS] [PATCH 4/4] ppc: avoid runtime relocations

Blue Swirl blauwirbel at gmail.com
Fri Jan 21 21:18:15 CET 2011


Because the sizes of cells and pointers do not match on PPC64,
relocations can't be computed in an ucell array by the linker.

Introduce a method to relocate the dictionary to a fixed address
by forthstrap.

Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
---
 arch/ppc/build.xml       |    6 +-----
 arch/ppc/qemu/kernel.c   |   18 +++++++++++++-----
 arch/ppc/qemu/ldscript   |    7 +++++++
 arch/ppc/qemu/ofmem.c    |    2 +-
 arch/ppc64/qemu/ldscript |    7 +++++++
 kernel/bootstrap.c       |   44 ++++++++++++++++++++++++++++++++++++--------
 6 files changed, 65 insertions(+), 19 deletions(-)

diff --git a/arch/ppc/build.xml b/arch/ppc/build.xml
index 4aec62f..2b7b605 100644
--- a/arch/ppc/build.xml
+++ b/arch/ppc/build.xml
@@ -60,11 +60,7 @@

  <executable name="target/include/qemu-dict.h" target="target"
condition="QEMU">
   <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 -a 0xfff08000 -D $@ -d $<
</dev/null, "  GEN   $(TARGET_DIR)$@")]]></rule>
   <external-object source="openbios-qemu.dict"/>
  </executable>

diff --git a/arch/ppc/qemu/kernel.c b/arch/ppc/qemu/kernel.c
index 4cae525..fbb5925 100644
--- a/arch/ppc/qemu/kernel.c
+++ b/arch/ppc/qemu/kernel.c
@@ -17,7 +17,6 @@
  *
  */

-#include "qemu-dict.h"
 #include "config.h"
 #include "dict.h"
 #include "libopenbios/bindings.h"
@@ -27,7 +26,14 @@
 #include "kernel.h"

 #define MEMORY_SIZE	(256*1024)	/* 256K ram for hosted system */
-#define DICTIONARY_SIZE	(512*1024)	/* 512K for the dictionary   */
+/* 512K for the dictionary  */
+#define DICTIONARY_SIZE (512 * 1024 / sizeof(ucell))
+
+/*
+ * wrap an array around the hex'ed dictionary file
+ */
+
+#include "qemu-dict.h"

 static ucell 		*memory;

@@ -82,10 +88,12 @@ init_memory( void )
 int
 initialize_forth( void )
 {
-	dict = malloc(DICTIONARY_SIZE);
-	dictlimit = DICTIONARY_SIZE;
+        dict = (unsigned char *)forth_dictionary;
+        dicthead = (ucell)FORTH_DICTIONARY_END;
+        last = (ucell *)((unsigned char *)forth_dictionary +
+                         FORTH_DICTIONARY_LAST);
+        dictlimit = sizeof(forth_dictionary);

-	load_dictionary( forth_dictionary, sizeof(forth_dictionary) );
 	forth_init();

 	PUSH_xt( bind_noname_func(arch_of_init) );
diff --git a/arch/ppc/qemu/ldscript b/arch/ppc/qemu/ldscript
index 840b498..3b1855a 100644
--- a/arch/ppc/qemu/ldscript
+++ b/arch/ppc/qemu/ldscript
@@ -6,6 +6,7 @@ OUTPUT_ARCH(powerpc)
 BASE_ADDR = 0xfff00000;

 /* As NVRAM is at 0xfff04000, the .text needs to be after that
+ * The value in arch/ppc/build.xml must match this value!
  */
 TEXT_ADDR = 0xfff08000;

@@ -26,6 +27,12 @@ SECTIONS

     . = TEXT_ADDR;
     /* Normal sections */
+    .data.dict ALIGN(4096): {
+        _dict_start = .;
+        *(.data.dict)
+        _dict_end = .;
+    }
+
     .text ALIGN(4096): {
         *(.text)
         *(.text.*)
diff --git a/arch/ppc/qemu/ofmem.c b/arch/ppc/qemu/ofmem.c
index 4c6825e..f6cf8cd 100644
--- a/arch/ppc/qemu/ofmem.c
+++ b/arch/ppc/qemu/ofmem.c
@@ -55,7 +55,7 @@ extern void setup_mmu(unsigned long code_base);
 #define HASH_BITS		15
 #endif
 #define HASH_SIZE		(2 << HASH_BITS)
-#define OFMEM_SIZE		(2 * 1024 * 1024)
+#define OFMEM_SIZE		(1 * 1024 * 1024 + 512 * 1024)

 #define	SEGR_USER		BIT(2)
 #define SEGR_BASE		0x0400
diff --git a/arch/ppc64/qemu/ldscript b/arch/ppc64/qemu/ldscript
index 7a22903..0bb2157 100644
--- a/arch/ppc64/qemu/ldscript
+++ b/arch/ppc64/qemu/ldscript
@@ -6,6 +6,7 @@ OUTPUT_ARCH(powerpc:common64)
 BASE_ADDR = 0xfff00000;

 /* As NVRAM is at 0xfff04000, the .text needs to be after that
+ * The value in arch/ppc/build.xml must match this value!
  */
 TEXT_ADDR = 0xfff08000;

@@ -26,6 +27,12 @@ SECTIONS

     . = TEXT_ADDR;
     /* Normal sections */
+    .data.dict ALIGN(4096): {
+        _dict_start = .;
+        *(.data.dict)
+        _dict_end = .;
+    }
+
     .text ALIGN(4096): {
         *(.text)
         *(.text.*)
diff --git a/kernel/bootstrap.c b/kernel/bootstrap.c
index 68fe5dd..b19c5c4 100644
--- a/kernel/bootstrap.c
+++ b/kernel/bootstrap.c
@@ -96,7 +96,15 @@ static const char *wordnames[] = {
  * dictionary related functions.
  */

-static void relocation_table(unsigned char * dict_one, unsigned char
*dict_two, int length)
+/*
+ * 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.
+ *
+ * If offset is nonzero, add the offset to the cell instead.
+ */
+static void relocation_table(unsigned char * dict_one, unsigned char *dict_two,
+                             int length, ucell offset)
 {
 	ucell *d1=(ucell *)dict_one, *d2=(ucell *)dict_two;
 	ucell *reloc_table;
@@ -122,8 +130,12 @@ static void relocation_table(unsigned char *
dict_one, unsigned char *dict_two,
 			//	printk("\nWARNING: inconsistent relocation (%x:%x)!\n", d1[i], d2[i]);
 		} else {
 			/* This is a pointer, it needs relocation, d2==dict */
-                        reloc_table[pos] |= target_ucell((ucell)1ULL << bit);
-			d2[i] = target_ucell(target_ucell(d2[i]) - pointer2cell(d2));
+                        if (!offset) {
+                            reloc_table[pos] |= target_ucell((ucell)1ULL
+                                                             << bit);
+                        }
+                        d2[i] = target_ucell(target_ucell(d2[i]) -
+                                             pointer2cell(d2) + offset);
 		}
 	}

@@ -237,6 +249,11 @@ static void write_dictionary(const char *filename)
 #endif
 }

+/*
+ * Write dictionary as a C array of ucells to filename.
+ * Put the array to special section so that its address can be fixed.
+ * Define some helpful constants.
+ */
 static void write_dictionary_hex(const char *filename)
 {
     FILE *f;
@@ -248,7 +265,8 @@ static void write_dictionary_hex(const char *filename)
         exit(1);
     }

-    fprintf(f, "static ucell forth_dictionary[DICTIONARY_SIZE] = {\n");
+    fprintf(f, "static ucell forth_dictionary[DICTIONARY_SIZE] "
+            "__attribute__((section(\".data.dict\"))) = {\n");
     for (walk = (ucell *)dict; walk < (ucell *)(dict + dicthead); walk++) {
         int pos, bit, l;
         ucell val;
@@ -1075,7 +1093,10 @@ static void new_dictionary(const char *source)
 		"   -s|--segfault	install segfault handler\n"     \
                 "   -M|--dependency-dump file\n"                         \
                 "                       dump dependencies in Makefile
format\n\n" \
-                "   -x|--hexdump        output format is C language hex dump\n"
+                "   -x|--hexdump        output format is C language
hex dump\n" \
+                "   -a|--fixed-address base\n" \
+                "                       relocate output to base\n"
+
 #else
 #define USAGE   "Usage: %s [options] [dictionary file|source file]\n\n" \
 		"   -h		show this help\n"		\
@@ -1090,7 +1111,8 @@ static void new_dictionary(const char *source)
 		"		write kernel console output to log file\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"
+                "   -x          output format is C language hex dump\n" \
+                "   -a base     relocate output to base\n"
 #endif

 int main(int argc, char *argv[])
@@ -1105,8 +1127,9 @@ int main(int argc, char *argv[])

 	unsigned char *bootstrapdict[2];
         int c, cnt, hexdump = 0;
+        ucell relocation_offset = 0;

-        const char *optstring = "VvhsI:d:D:c:M:x?";
+        const char *optstring = "a:VvhsI:d:D:c:M:x?";

 	while (1) {
 #ifdef __GLIBC__
@@ -1122,6 +1145,7 @@ int main(int argc, char *argv[])
 			{"console", 1, NULL, 'c'},
                         {"dependency-dump", 1, NULL, 'M'},
                         {"hexdump", 0, NULL, 'x'},
+                        {"fixed-address", 1, NULL, 'a'},
 		};

 		/*
@@ -1180,6 +1204,9 @@ int main(int argc, char *argv[])
                 case 'x':
                         hexdump = 1;
                         break;
+                case 'a':
+                        relocation_offset = strtoll(optarg, NULL, 0);
+                        break;
 		default:
 			return 1;
 		}
@@ -1293,7 +1320,8 @@ int main(int argc, char *argv[])
 	else
 #endif
 	{
-		relocation_table( bootstrapdict[0], bootstrapdict[1], dicthead);
+                relocation_table(bootstrapdict[0], bootstrapdict[1], dicthead,
+                                 relocation_offset);
                 if (hexdump) {
                     write_dictionary_hex(dictname);
                 } else {
-- 
1.6.2.4
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0004-ppc-avoid-runtime-relocations.patch
Type: application/mbox
Size: 9136 bytes
Desc: not available
URL: <http://lists.openbios.org/pipermail/openbios/attachments/20110121/15273065/attachment-0001.bin>


More information about the OpenBIOS mailing list