Subject: Some ASM code to C
To: None <port-i386@netbsd.org>
From: Julio M. Merino Vidal <jmmv84@gmail.com>
List: port-i386
Date: 02/12/2006 12:51:34
--Boundary-00=_GFy7Dmr/9gngB7L
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Hi,
I've converted the code in locore.S that fetches the parameters passed in
by the boot loader from ASM to C. It may look longer, but I believe it is
easier to understand. It took me a while to understand what was going on
the first time I looked there (specially the part that deals with bootinfo).
Patch attached. Comments?
--
Julio M. Merino Vidal <jmmv84@gmail.com>
The Julipedia - http://julipedia.blogspot.com/
--Boundary-00=_GFy7Dmr/9gngB7L
Content-Type: text/x-diff;
charset="us-ascii";
name="patch.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="patch.diff"
Index: locore.S
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/locore.S,v
retrieving revision 1.37
diff -u -p -r1.37 locore.S
--- locore.S 3 Feb 2006 11:08:24 -0000 1.37
+++ locore.S 12 Feb 2006 11:46:47 -0000
@@ -95,7 +95,6 @@
#include <machine/segments.h>
#include <machine/specialreg.h>
#include <machine/trap.h>
-#include <machine/bootinfo.h>
#if NLAPIC > 0
#include <machine/i82489reg.h>
@@ -158,13 +157,9 @@
.data
.globl _C_LABEL(cpu)
- .globl _C_LABEL(esym),_C_LABEL(boothowto)
- .globl _C_LABEL(bootinfo),_C_LABEL(atdevbase)
-#ifdef COMPAT_OLDBOOT
- .globl _C_LABEL(bootdev)
-#endif
+ .globl _C_LABEL(esym)
+ .globl _C_LABEL(atdevbase)
.globl _C_LABEL(proc0paddr),_C_LABEL(PDPpaddr)
- .globl _C_LABEL(biosbasemem),_C_LABEL(biosextmem)
.globl _C_LABEL(gdt)
#ifdef I586_CPU
.globl _C_LABEL(idt)
@@ -197,20 +192,9 @@ _C_LABEL(lapic_tpr):
_C_LABEL(cpu): .long 0 # are we 386, 386sx, or 486,
# or Pentium, or..
-_C_LABEL(esym): .long 0 # ptr to end of syms
_C_LABEL(atdevbase): .long 0 # location of start of iomem in virtual
_C_LABEL(proc0paddr): .long 0
_C_LABEL(PDPpaddr): .long 0 # paddr of PDP, for libkvm
-#ifndef REALBASEMEM
-_C_LABEL(biosbasemem): .long 0 # base memory reported by BIOS
-#else
-_C_LABEL(biosbasemem): .long REALBASEMEM
-#endif
-#ifndef REALEXTMEM
-_C_LABEL(biosextmem): .long 0 # extended memory reported by BIOS
-#else
-_C_LABEL(biosextmem): .long REALEXTMEM
-#endif
.space 512
tmpstk:
@@ -256,71 +240,21 @@ _C_LABEL(Multiboot_Header):
pushl %ebx # Address of Multiboot information
call _C_LABEL(multiboot_pre_reloc)
addl $4,%esp
- jmp 3f
+ jmp 2f
#endif
1:
/*
- * Load parameters from stack
- * (howto, [bootdev], bootinfo, esym, basemem, extmem).
+ * At this point, we know that a NetBSD-specific boot loader
+ * booted this kernel. The stack carries the following parameters:
+ * (boothowto, [bootdev], bootinfo, esym, biosbasemem, biosextmem),
+ * 4 bytes each.
*/
- movl 4(%esp),%eax
- movl %eax,RELOC(boothowto)
-#ifdef COMPAT_OLDBOOT
- movl 8(%esp),%eax
- movl %eax,RELOC(bootdev)
-#endif
- movl 12(%esp),%eax
+ addl $4,%esp # Discard return address to boot loader
+ call _C_LABEL(native_loader)
+ addl $24,%esp
- testl %eax, %eax
- jz 1f
- movl (%eax), %ebx /* number of entries */
- movl $RELOC(bootinfo), %edi
- movl %ebx, (%edi)
- addl $4, %edi
2:
- testl %ebx, %ebx
- jz 1f
- addl $4, %eax
- movl (%eax), %ecx /* address of entry */
- pushl %eax
- pushl (%ecx) /* len */
- pushl %ecx
- pushl %edi
- addl (%ecx), %edi /* update dest pointer */
- cmpl $_RELOC(_C_LABEL(bootinfo) + BOOTINFO_MAXSIZE), %edi
- jg 2f
- call _C_LABEL(memcpy)
- addl $12, %esp
- popl %eax
- subl $1, %ebx
- jmp 2b
-2: /* cleanup for overflow case */
- addl $16, %esp
- movl $RELOC(bootinfo), %edi
- subl %ebx, (%edi) /* correct number of entries */
-1:
-
- movl 16(%esp),%eax
- testl %eax,%eax
- jz 1f
- addl $KERNBASE,%eax
-1: movl %eax,RELOC(esym)
-
- movl RELOC(biosextmem),%eax
- testl %eax,%eax
- jnz 1f
- movl 20(%esp),%eax
- movl %eax,RELOC(biosextmem)
-1:
- movl RELOC(biosbasemem),%eax
- testl %eax,%eax
- jnz 1f
- movl 24(%esp),%eax
- movl %eax,RELOC(biosbasemem)
-1:
-
-3:
/* First, reset the PSL. */
pushl $PSL_MBO
popfl
Index: machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.570
diff -u -p -r1.570 machdep.c
--- machdep.c 3 Feb 2006 11:08:24 -0000 1.570
+++ machdep.c 12 Feb 2006 11:46:48 -0000
@@ -1,12 +1,12 @@
/* $NetBSD: machdep.c,v 1.570 2006/02/03 11:08:24 jmmv Exp $ */
/*-
- * Copyright (c) 1996, 1997, 1998, 2000, 2004 The NetBSD Foundation, Inc.
+ * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
- * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
- * Simulation Facility, NASA Ames Research Center.
+ * by Charles M. Hannum, by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center and by Julio M. Merino Vidal.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -276,6 +276,114 @@ void add_mem_cluster(uint64_t, uint64_t,
extern int time_adjusted;
+struct bootinfo bootinfo;
+int *esym;
+extern int boothowto;
+
+/* Base memory reported by BIOS. */
+#ifndef REALBASEMEM
+int biosbasemem = 0;
+#else
+int biosbasemem = REALBASEMEM;
+#endif
+
+/* Extended memory reported by BIOS. */
+#ifndef REALEXTMEM
+int biosextmem = 0;
+#else
+int biosextmem = REALEXTMEM;
+#endif
+
+/* Representation of the bootinfo structure constructed by a NetBSD native
+ * boot loader. Only be used by native_loader(). */
+struct bootinfo_source {
+ uint32_t bs_naddrs;
+ paddr_t bs_addrs[1]; /* Actually longer. */
+};
+
+/* Only called by locore.h; no need to be in a header file. */
+void native_loader(int, int, struct bootinfo_source *, paddr_t, int, int);
+
+/*
+ * Called as one of the very first things during system startup (just after
+ * the boot loader gave control to the kernel image), this routine is in
+ * charge of retrieving the parameters passed in by the boot loader and
+ * storing them in the appropriate kernel variables.
+ *
+ * WARNING: Because the kernel has not yet relocated itself to KERNBASE,
+ * special care has to be taken when accessing memory because absolute
+ * addresses (referring to kernel symbols) do not work. So:
+ *
+ * 1) Avoid jumps to absolute addresses (such as gotos and switches).
+ * 2) To access global variables use their physical address, which
+ * can be obtained using the RELOC macro.
+ */
+void
+native_loader(int bl_boothowto, int bl_bootdev,
+ struct bootinfo_source *bl_bootinfo, paddr_t bl_esym,
+ int bl_biosbasemem, int bl_biosextmem)
+{
+#define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
+
+ *RELOC(int *, &boothowto) = bl_boothowto;
+
+#ifdef COMPAT_OLDBOOT
+ /*
+ * Pre-1.3 boot loaders gave the boot device as a parameter
+ * (instead of a bootinfo entry).
+ */
+ *RELOC(int *, &bootdev) = bl_bootdev;
+#endif
+
+ /*
+ * The boot loader provides a physical, non-relocated address
+ * for the symbols table's end. We need to convert it to a
+ * virtual address.
+ */
+ if (bl_esym != 0)
+ *RELOC(int **, &esym) = (int *)((vaddr_t)bl_esym + KERNBASE);
+ else
+ *RELOC(int **, &esym) = 0;
+
+ /*
+ * Copy bootinfo entries (if any) from the boot loader's
+ * representation to the kernel's bootinfo space.
+ */
+ if (bl_bootinfo != NULL) {
+ size_t i;
+ uint8_t *data;
+ struct bootinfo *bidest;
+
+ bidest = RELOC(struct bootinfo *, &bootinfo);
+
+ data = &bidest->bi_data[0];
+
+ for (i = 0; i < bl_bootinfo->bs_naddrs; i++) {
+ struct btinfo_common *bc;
+
+ bc = (struct btinfo_common *)(bl_bootinfo->bs_addrs[i]);
+
+ if ((paddr_t)(data + bc->len) >
+ (paddr_t)(&bidest->bi_data[0] + BOOTINFO_MAXSIZE))
+ break;
+
+ memcpy(data, bc, bc->len);
+ data += bc->len;
+ }
+ bidest->bi_nentries = i;
+ }
+
+ /*
+ * Configure biosbasemem and biosextmem only if they were not
+ * explicitly given during the kernel's build.
+ */
+ if (*RELOC(int *, &biosbasemem) == 0)
+ *RELOC(int *, &biosbasemem) = bl_biosbasemem;
+ if (*RELOC(int *, &biosextmem) == 0)
+ *RELOC(int *, &biosextmem) = bl_biosextmem;
+#undef RELOC
+}
+
/*
* Machine-dependent startup code
*/
@@ -1869,7 +1977,6 @@ init386(paddr_t first_avail)
#if NKSYMS || defined(DDB) || defined(LKM)
{
extern int end;
- extern int *esym;
struct btinfo_symtab *symtab;
#ifdef DDB
--Boundary-00=_GFy7Dmr/9gngB7L--