[OpenBIOS] Running client with MMU off

BALATON Zoltan balaton at eik.bme.hu
Thu Jun 19 23:19:04 CEST 2014


On Tue, 17 Jun 2014, BALATON Zoltan wrote:
> From the test results it seems that Apple puts the stack after the image (and 
> probably clears it or otherwise adds a mapping in the TLB for it so accessing 
> it will not generate exceptions). How could this be implemented in OpenBIOS? 
> I've tried to look at the code to find a good place but there seems to be 
> different cases for different architectures and using preloaded kernel image 
> seems to be an additional complication. Could the file-size stored in 
> saved-program-state be used as a base to place the stack in call_elf? (this 
> would need adding an additional parameter to it in the ppc/qemu case because 
> accessing Forth from assembly is not something I'd try).
>
> Or are my conclusions wrong or you have a better idea? (Also what about my 
> other patches on the list? This place seemed abandoned for the last week.)

With the patch below I don't get DSI-s but it crashes in an ISI while 
trying to replace the sr registers. How could this possibly work on real 
hardware without getting any exceptions during replacing the vectors? Is 
there a way to preload the TLB with code addresses too so we can avoid the 
crash? How? (For data accessing it before calling the boot code is enough 
to preload translations but how to avoid ISI-s?)

Regards,
BALATON Zoltan

diff --git a/openbios-devel/arch/ppc/qemu/init.c b/openbios-devel/arch/ppc/qemu/init.c
index 8d5ef8e..2872c7b 100644
--- a/openbios-devel/arch/ppc/qemu/init.c
+++ b/openbios-devel/arch/ppc/qemu/init.c
@@ -594,12 +594,20 @@ static void go(void);
  static void
  go(void)
  {
-    ucell addr;
+    ucell addr, end;

      feval("saved-program-state >sps.entry @");
      addr = POP();
+    feval("saved-program-state >sps.end @");
+    end = POP();

-    call_elf(0, 0, addr);
+    if (end) {
+        ofmem_claim(end, 64 * 1024, 0);
+        memset((void *)end, 0, 64 * 1024);
+        end += 64 * 1024;
+    }
+
+    call_elf(0, 0, addr, end);
  }

  static void kvm_of_init(void)
diff --git a/openbios-devel/arch/ppc/qemu/kernel.h b/openbios-devel/arch/ppc/qemu/kernel.h
index fe9be83..464aa14 100644
--- a/openbios-devel/arch/ppc/qemu/kernel.h
+++ b/openbios-devel/arch/ppc/qemu/kernel.h
@@ -22,7 +22,8 @@ extern void		exit( int status ) __attribute__ ((noreturn));
  /* start.S */
  extern void 		flush_icache_range( char *start, char *stop );
  extern char		of_rtas_start[], of_rtas_end[];
-extern void             call_elf( unsigned long arg1, unsigned long arg2, unsigned long elf_entry );
+extern void		call_elf( unsigned long arg1, unsigned long arg2,
+				  unsigned long elf_entry, unsigned long stack_addr );

  /* methods.c */
  extern void		node_methods_init( const char *cpuname );
diff --git a/openbios-devel/arch/ppc/qemu/main.c b/openbios-devel/arch/ppc/qemu/main.c
index 44b1666..ac45c6c 100644
--- a/openbios-devel/arch/ppc/qemu/main.c
+++ b/openbios-devel/arch/ppc/qemu/main.c
@@ -61,7 +61,7 @@ static void check_preloaded_kernel(void)
  	       ph = find_dev("/chosen");
                 set_property(ph, "bootargs", strdup(kernel_cmdline), strlen(kernel_cmdline) + 1);
          }
-        call_elf(initrd_image, initrd_size, kernel_image);
+        call_elf(initrd_image, initrd_size, kernel_image, 0);
      }
  }

diff --git a/openbios-devel/arch/ppc/qemu/start.S b/openbios-devel/arch/ppc/qemu/start.S
index ae2fd53..2edf7ba 100644
--- a/openbios-devel/arch/ppc/qemu/start.S
+++ b/openbios-devel/arch/ppc/qemu/start.S
@@ -501,7 +501,7 @@ real_entry:
  saved_stack:
      DATA_LONG(0)
          .previous
-	/* void call_elf( arg1, arg2, entry ) */
+	/* void call_elf( arg1, arg2, entry, stack_addr ) */
  _GLOBAL(call_elf):
  	mflr	r0
  	PPC_STLU r1, -STACKFRAME_MINSIZE(r1)
@@ -512,6 +512,13 @@ _GLOBAL(call_elf):
  	mfsdr1	r1
  	addi	r1, r1, -32768		/* - 32 KiB exception stack */
  	addis	r1, r1, -1			/* - 64 KiB stack */
+	cmpwi	r6,0
+	beq	1f
+	mr	r1,r6				// use stack_addr if not NULL
+1:	LOAD_REG_IMMEDIATE(r8, __vectors)	// access 0x1000 to preload TLB
+	li	r9,0
+	lwz	r10,4096(r8)
+	stw	r10,4096(r9)
  	LOAD_REG_IMMEDIATE(r5, of_client_callback)	// r5 = callback
  	li	r6,0			// r6 = address of client program arguments (unused)
  	li	r7,0			// r7 = length of client program arguments (unused)
diff --git a/openbios-devel/forth/debugging/client.fs b/openbios-devel/forth/debugging/client.fs
index f374404..f06d2d3 100644
--- a/openbios-devel/forth/debugging/client.fs
+++ b/openbios-devel/forth/debugging/client.fs
@@ -21,6 +21,7 @@ struct ( saved-program-state )
    /n field >sps.entry
    /n field >sps.file-size
    /n field >sps.file-type
+  /n field >sps.end
  constant saved-program-state.size
  create saved-program-state saved-program-state.size allot

diff --git a/openbios-devel/libopenbios/aout_load.c b/openbios-devel/libopenbios/aout_load.c
index e9d2002..01edb88 100644
--- a/openbios-devel/libopenbios/aout_load.c
+++ b/openbios-devel/libopenbios/aout_load.c
@@ -160,6 +160,8 @@ aout_load(struct sys_info *info, ihandle_t dev)
      PUSH(size);
      feval("saved-program-state >sps.file-size !");
      feval("aout saved-program-state >sps.file-type !");
+    PUSH(entry + size);
+    feval("saved-program-state >sps.end !");

      feval("-1 state-valid !");

diff --git a/openbios-devel/libopenbios/bootcode_load.c b/openbios-devel/libopenbios/bootcode_load.c
index 0fabf55..5c09c87 100644
--- a/openbios-devel/libopenbios/bootcode_load.c
+++ b/openbios-devel/libopenbios/bootcode_load.c
@@ -89,6 +89,8 @@ bootcode_load(ihandle_t dev)
      PUSH(size);
      feval("saved-program-state >sps.file-size !");
      feval("bootcode saved-program-state >sps.file-type !");
+    PUSH(bootcode);
+    feval("saved-program-state >sps.end !");

      feval("-1 state-valid !");

diff --git a/openbios-devel/libopenbios/elf_load.c b/openbios-devel/libopenbios/elf_load.c
index 9c7850e..236b893 100644
--- a/openbios-devel/libopenbios/elf_load.c
+++ b/openbios-devel/libopenbios/elf_load.c
@@ -478,6 +478,7 @@ elf_init_program(void)
  	Elf_phdr *phdr;
  	size_t size, total_size = 0;
  	char *addr;
+	char *end = NULL;
  	uintptr_t tmp;

  	/* TODO: manage ELF notes section */
@@ -519,6 +520,8 @@ elf_init_program(void)

  		memcpy(addr, base + phdr[i].p_offset, size);

+		if (addr + phdr[i].p_memsz > end)
+			end = addr + phdr[i].p_memsz;
  		total_size += size;

  #ifdef CONFIG_PPC
@@ -532,6 +535,8 @@ elf_init_program(void)
  	PUSH(total_size);
  	feval("saved-program-state >sps.file-size !");
  	feval("elf saved-program-state >sps.file-type !");
+	PUSH((ucell)end);
+	feval("saved-program-state >sps.end !");

  	feval("-1 state-valid !");
  }
diff --git a/openbios-devel/libopenbios/fcode_load.c b/openbios-devel/libopenbios/fcode_load.c
index f4eb7bf..3f3fbbf 100644
--- a/openbios-devel/libopenbios/fcode_load.c
+++ b/openbios-devel/libopenbios/fcode_load.c
@@ -81,6 +81,8 @@ fcode_load(ihandle_t dev)
      PUSH(size);
      feval("saved-program-state >sps.file-size !");
      feval("fcode saved-program-state >sps.file-type !");
+    PUSH(start + size);
+    feval("saved-program-state >sps.end !");

      feval("-1 state-valid !");

diff --git a/openbios-devel/libopenbios/forth_load.c b/openbios-devel/libopenbios/forth_load.c
index c3a1929..403f1e5 100644
--- a/openbios-devel/libopenbios/forth_load.c
+++ b/openbios-devel/libopenbios/forth_load.c
@@ -69,6 +69,8 @@ int forth_load(ihandle_t dev)
      PUSH((ucell)forthsize);
      feval("saved-program-state >sps.file-size !");
      feval("forth saved-program-state >sps.file-type !");
+    PUSH(0);
+    feval("saved-program-state >sps.end !");

      feval("-1 state-valid !");

diff --git a/openbios-devel/libopenbios/xcoff_load.c b/openbios-devel/libopenbios/xcoff_load.c
index 0dcb28c..3eb8574 100644
--- a/openbios-devel/libopenbios/xcoff_load.c
+++ b/openbios-devel/libopenbios/xcoff_load.c
@@ -60,6 +60,7 @@ xcoff_init_program(void)
  	uint32_t offset;
  	size_t total_size = 0;
  	int i;
+	ucell end = 0;

  	feval("0 state-valid !");

@@ -113,6 +114,8 @@ xcoff_init_program(void)

  			memcpy((char*)(uintptr_t)shdr->s_vaddr, base + shdr->s_scnptr,
  			       shdr->s_size);
+			if (shdr->s_vaddr + shdr->s_size > end)
+				end = shdr->s_vaddr + shdr->s_size;
  			total_size += shdr->s_size;
  #ifdef CONFIG_PPC
  			flush_icache_range((char*)(uintptr_t)shdr->s_vaddr,
@@ -122,11 +125,15 @@ xcoff_init_program(void)

  			memcpy((char*)(uintptr_t)shdr->s_vaddr, base + shdr->s_scnptr,
  			       shdr->s_size);
+			if (shdr->s_vaddr + shdr->s_size > end)
+				end = shdr->s_vaddr + shdr->s_size;
  			total_size += shdr->s_size;

  		} else if (strcmp(shdr->s_name, ".bss") == 0) {

  			memset((void *)(uintptr_t)shdr->s_vaddr, 0, shdr->s_size);
+			if (shdr->s_vaddr + shdr->s_size > end)
+				end = shdr->s_vaddr + shdr->s_size;
  			total_size += shdr->s_size;
  		} else {
  			DPRINTF("    Skip '%s' section\n", shdr->s_name);
@@ -142,6 +149,8 @@ xcoff_init_program(void)
  	PUSH(total_size);
  	feval("saved-program-state >sps.file-size !");
  	feval("xcoff saved-program-state >sps.file-type !");
+	PUSH(end);
+	feval("saved-program-state >sps.end !");

  	feval("-1 state-valid !");
  }



More information about the OpenBIOS mailing list