Towards making KEEP_IT_REAL work again.
authorMichael Brown <mcb30@etherboot.org>
Thu, 24 Aug 2006 13:18:05 +0000 (13:18 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 24 Aug 2006 13:18:05 +0000 (13:18 +0000)
Fix bug that caused over-allocation of .text16 and .data16 memory areas
by a factor of 16.

src/arch/i386/include/libkir.h
src/arch/i386/include/librm.h
src/arch/i386/kir-Makefile
src/arch/i386/prefix/libprefix.S
src/arch/i386/scripts/i386-kir.lds [new file with mode: 0644]
src/arch/i386/scripts/i386.lds
src/arch/i386/transitions/libkir.S

index 82df822..a54c343 100644 (file)
@@ -213,6 +213,15 @@ virt_to_user ( void * virtual ) {
 #define BASEMEM_PARAMETER_INIT BASEMEM_PARAMETER_INIT_LIBKIR
 #define BASEMEM_PARAMETER_DONE BASEMEM_PARAMETER_DONE_LIBKIR
 
+/* TEXT16_CODE: declare a fragment of code that resides in .text16 */
+#define TEXT16_CODE( asm_code_str )                    \
+       ".section \".text16\", \"ax\", @progbits\n\t"   \
+       ".code16\n\t"                                   \
+       ".arch i386\n\t"                                \
+       asm_code_str "\n\t"                             \
+       ".code16gcc\n\t"                                \
+       ".previous\n\t"
+
 /* REAL_CODE: declare a fragment of code that executes in real mode */
 #define REAL_CODE( asm_code_str )      \
        ".code16\n\t"                   \
index 8b0169e..3f2dbd5 100644 (file)
@@ -177,20 +177,25 @@ extern void remove_from_rm_stack ( void *data, size_t size );
 #define BASEMEM_PARAMETER_INIT BASEMEM_PARAMETER_INIT_LIBRM
 #define BASEMEM_PARAMETER_DONE BASEMEM_PARAMETER_DONE_LIBRM
 
-/* REAL_CODE: declare a fragment of code that executes in real mode */
-#define REAL_CODE( asm_code_str )                      \
-       "pushl $1f\n\t"                                 \
-       "call real_call\n\t"                            \
-       "addl $4, %%esp\n\t"                            \
+/* TEXT16_CODE: declare a fragment of code that resides in .text16 */
+#define TEXT16_CODE( asm_code_str )                    \
        ".section \".text16\", \"ax\", @progbits\n\t"   \
        ".code16\n\t"                                   \
        ".arch i386\n\t"                                \
-       "\n1:\n\t"                                      \
        asm_code_str "\n\t"                             \
-       "ret\n\t"                                       \
        ".code32\n\t"                                   \
        ".previous\n\t"
 
+/* REAL_CODE: declare a fragment of code that executes in real mode */
+#define REAL_CODE( asm_code_str )                      \
+       "pushl $1f\n\t"                                 \
+       "call real_call\n\t"                            \
+       "addl $4, %%esp\n\t"                            \
+       TEXT16_CODE ( "\n1:\n\t"                        \
+                     asm_code_str                      \
+                     "\n\t"                            \
+                     "ret\n\t" )
+
 #endif /* ASSEMBLY */
 
 #endif /* LIBRM_H */
index cc37a91..bbfc1a3 100644 (file)
@@ -21,9 +21,6 @@ BIN           = bin-kir
 #
 CFLAGS         += -DKEEP_IT_REAL -include kir.h
 
-# Link with _data_link_addr = 0; data symbols are relative to the data
-# segment.
-#
-LDFLAGS                += --defsym _data_link_addr=0
-
 include Makefile
+
+LDSCRIPT       = arch/i386/scripts/i386-kir.lds
index f0f7682..1c471aa 100644 (file)
@@ -99,11 +99,11 @@ alloc_basemem:
        shlw    $6, %ax
 
        /* .data16 segment address */
-       subw    $_data16_size, %ax
+       subw    $_data16_size_pgh, %ax
        pushw   %ax
 
        /* .text16 segment address */
-       subw    $_text16_size, %ax
+       subw    $_text16_size_pgh, %ax
        pushw   %ax
 
        /* Update FBMS */
@@ -322,7 +322,14 @@ install_prealloc:
        /* Install .text16 and .data16 */
        call    install_basemem
 
-#ifndef KEEP_IT_REAL
+#ifdef KEEP_IT_REAL
+       /* Preserve %ds, call init_libkir, restore registers */
+       pushw   %ds
+       movw    %bx, %ds
+       movw    %ax, (init_libkir_vector+2)
+       lcall   *init_libkir_vector
+       popw    %ds
+#else
        /* Preserve registers and interrupt status, and disable interrupts */
        pushfw
        pushw   %ds
@@ -379,9 +386,14 @@ install_prealloc:
        ret
        .size install_prealloc, . - install_prealloc
 
-#ifndef KEEP_IT_REAL
        /* Vectors for far calls to .text16 functions */
        .section ".data16"
+#ifdef KEEP_IT_REAL
+init_libkir_vector:
+       .word init_libkir
+       .word 0
+       .size init_libkir_vector, . - init_libkir_vector
+#else
 init_librm_vector:
        .word init_librm
        .word 0
diff --git a/src/arch/i386/scripts/i386-kir.lds b/src/arch/i386/scripts/i386-kir.lds
new file mode 100644 (file)
index 0000000..3095b31
--- /dev/null
@@ -0,0 +1,192 @@
+/* -*- sh -*- */
+
+/*
+ * Linker script for i386 images
+ *
+ */
+
+OUTPUT_FORMAT ( "elf32-i386", "elf32-i386", "elf32-i386" )
+OUTPUT_ARCH ( i386 )
+ENTRY ( _entry )
+
+SECTIONS {
+
+    /* All sections in the resulting file have consecutive load
+     * addresses, but may have individual link addresses depending on
+     * the memory model being used.
+     *
+     * The linker symbols _prefix_link_addr, load_addr, and
+     * _max_align may be specified explicitly.  If not specified, they
+     * will default to:
+     *
+     *   _prefix_link_addr     = 0
+     *   _load_addr            = 0
+     *   _max_align            = 16
+     * 
+     * We guarantee alignment of virtual addresses to any alignment
+     * specified by the constituent object files (e.g. via
+     * __attribute__((aligned(x)))).  Load addresses are guaranteed
+     * only up to _max_align.  Provided that all loader and relocation
+     * code honours _max_align, this means that physical addresses are
+     * also guaranteed up to _max_align.
+     *
+     * Note that when using -DKEEP_IT_REAL, the UNDI segments are only
+     * guaranteed to be loaded on a paragraph boundary (i.e. 16-byte
+     * alignment).  Using _max_align>16 will therefore not guarantee
+     * >16-byte alignment of physical addresses when -DKEEP_IT_REAL is
+     * used (though virtual addresses will still be fully aligned).
+     *
+     */
+
+    /*
+     * The prefix
+     */
+
+    _prefix_link_addr = DEFINED ( _prefix_link_addr ) ? _prefix_link_addr : 0;
+    . = _prefix_link_addr;
+    _prefix = .;
+
+    .prefix : AT ( _prefix_load_offset + __prefix ) {
+       __prefix = .;
+       _entry = .;
+       *(.prefix)
+       *(.prefix.*)
+       _eprefix_progbits = .;
+    }
+    
+    _eprefix = .;
+
+    /*
+     * The 16-bit sections
+     */
+
+    _text16_link_addr = 0;
+    . = _text16_link_addr;
+    _text16 = .;
+
+    .text16 : AT ( _text16_load_offset + __text16 ) {
+       __text16 = .;
+       *(.text.null_trap)
+       *(.text16)
+       *(.text16.*)
+       *(.text)
+       *(.text.*)
+       _etext16_progbits = .;
+    } = 0x9090
+
+    _etext16 = .;
+
+    _data16_link_addr = 0;
+    . = _data16_link_addr;
+    _data16 = .;
+
+    .rodata16 : AT ( _data16_load_offset + __rodata16 ) {
+       __rodata16 = .;
+       *(.rodata16)
+       *(.rodata16.*)
+       *(.rodata)
+       *(.rodata.*)
+    }
+    .data16 : AT ( _data16_load_offset + __data16 ) {
+       __data16 = .;
+       *(.data16)
+       *(.data16.*)
+       *(.data)
+       *(.data.*)
+       *(SORT(.tbl.*))         /* Various tables.  See include/tables.h */
+       _edata16_progbits = .;
+    }
+    .bss16 : AT ( _data16_load_offset + __bss16 ) {
+       __bss16 = .;
+       _bss16 = .;
+       *(.bss16)
+       *(.bss16.*)
+       *(.bss)
+       *(.bss.*)
+       *(COMMON)
+       _ebss16 = .;
+    }
+    .stack16 : AT ( _data16_load_offset + __stack16 ) {
+       __stack16 = .;
+       *(.stack16)
+       *(.stack16.*)
+       *(.stack)
+       *(.stack.*)
+    }
+
+    _edata16 = .;
+
+    _end = .;
+
+    /*
+     * Dispose of the comment and note sections to make the link map
+     * easier to read
+     */
+
+    /DISCARD/ : {
+       *(.comment)
+       *(.note)
+    }
+
+    /*
+     * Load address calculations.  The slightly obscure nature of the
+     * calculations is because ALIGN(x) can only operate on the
+     * location counter.
+     */
+
+    _max_align             = DEFINED ( _max_align ) ? _max_align : 16;
+    _load_addr             = DEFINED ( _load_addr ) ? _load_addr : 0;
+
+    .                      = _load_addr;
+
+    .                     -= _prefix_link_addr;
+    _prefix_load_offset            = ALIGN ( _max_align );
+    _prefix_load_addr      = _prefix_link_addr + _prefix_load_offset;
+    _prefix_size           = _eprefix - _prefix;
+    _prefix_progbits_size   = _eprefix_progbits - _prefix;
+    .                      = _prefix_load_addr + _prefix_progbits_size;
+
+    .                     -= _text16_link_addr;
+    _text16_load_offset            = ALIGN ( _max_align );
+    _text16_load_addr      = _text16_link_addr + _text16_load_offset;
+    _text16_size           = _etext16 - _text16;
+    _text16_progbits_size   = _etext16_progbits - _text16;
+    .                      = _text16_load_addr + _text16_progbits_size;
+
+    .                     -= _data16_link_addr;
+    _data16_load_offset            = ALIGN ( _max_align );
+    _data16_load_addr      = _data16_link_addr + _data16_load_offset;
+    _data16_size           = _edata16 - _data16;
+    _data16_progbits_size   = _edata16_progbits - _data16;
+    .                      = _data16_load_addr + _data16_progbits_size;
+
+    .                      = ALIGN ( _max_align );
+
+    _load_size             = . - _load_addr;
+
+    /*
+     * Alignment checks.  ALIGN() can only operate on the location
+     * counter, so we set the location counter to each value we want
+     * to check.
+     */
+
+    . = _prefix_load_addr - _prefix_link_addr;
+    _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
+                      "_prefix is badly aligned" );
+
+    . = _text16_load_addr - _text16_link_addr;
+    _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
+                      "_text16 is badly aligned" );
+
+    . = _data16_load_addr - _data16_link_addr;
+    _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
+                      "_data16 is badly aligned" );
+
+    /*
+     * Values calculated to save code from doing it
+     */
+    _text16_size_pgh   = ( ( _text16_size + 15 ) / 16 );
+    _data16_size_pgh   = ( ( _data16_size + 15 ) / 16 );
+    _load_size_pgh     = ( ( _load_size + 15 ) / 16 );
+    _rom_size          = ( ( _load_size + 511 ) / 512 );
+}
index 48dd777..3077609 100644 (file)
@@ -15,7 +15,7 @@ SECTIONS {
      * addresses, but may have individual link addresses depending on
      * the memory model being used.
      *
-     * The linker symbols {prefix,text}_link_addr, load_addr, and
+     * The linker symbols _{prefix,textdata}_link_addr, load_addr, and
      * _max_align may be specified explicitly.  If not specified, they
      * will default to:
      *
@@ -236,6 +236,8 @@ SECTIONS {
     /*
      * Values calculated to save code from doing it
      */
-    _load_size_pgh     = ( _load_size / 16 );
+    _text16_size_pgh   = ( ( _text16_size + 15 ) / 16 );
+    _data16_size_pgh   = ( ( _data16_size + 15 ) / 16 );
+    _load_size_pgh     = ( ( _load_size + 15 ) / 16 );
     _rom_size          = ( ( _load_size + 511 ) / 512 );
 }
index e0d6c57..1023ddd 100644 (file)
        .section ".text16", "awx", @progbits
        .code16
        
+/****************************************************************************
+ * init_libkir (real-mode or 16:xx protected-mode far call)
+ *
+ * Initialise libkir ready for transitions to the kir environment
+ *
+ * Parameters:
+ *   %cs : .text16 segment
+ *   %ds : .data16 segment
+ ****************************************************************************
+ */
+       .globl  init_libkir
+init_libkir:
+       /* Record segment registers */
+       pushw   %ds
+       popw    %cs:kir_ds
+       lret
+       
 /****************************************************************************
  * ext_to_kir (real-mode or 16:xx protected-mode near call)
  *
  * %cs:0000 must point to the start of the runtime image code segment
  * on entry.
  *
- * Note that this routine can be called *without* having first set up
- * a stored kir_ds and kir_sp.  If you do this, ext_to_kir will return
- * without altering the segment registers or stack pointer.
- *
  * Parameters: none
  ****************************************************************************
  */
@@ -73,10 +86,8 @@ ext_to_kir:
        movw    %ss, %ds:ext_ss
        movl    %esp, %ds:ext_esp
 
-       /* Load internal segment registers and stack pointer, if available */
+       /* Load internal segment registers and stack pointer */
        movw    %ds:kir_ds, %ax
-       testw   %ax, %ax
-       jz      1f
        movw    %ax, %ss
        movzwl  %ds:kir_sp, %esp
        movw    %ax, %ds
@@ -144,12 +155,12 @@ kir_to_ext:
  * will also be preserved.
  *
  * Parameters:
- *   function : (16-bit) virtual address of protected-mode function to call
+ *   function : (32-bit) virtual address of C function to call
  *
  * Example usage:
- *     pushw   $pxe_api_call
+ *     pushl   $pxe_api_call
  *     lcall   $UNDI_CS, $kir_call
- *     addw    $2, %sp
+ *     addw    $4, %sp
  * to call in to the C function
  *      void pxe_api_call ( struct i386_all_regs *ix86 );
  ****************************************************************************
@@ -157,7 +168,6 @@ kir_to_ext:
 
        .globl  kir_call
 kir_call:
-
        /* Preserve flags.  Must do this before any operation that may
         * affect flags.
         */
@@ -174,8 +184,8 @@ kir_call:
         * either a 16-bit or a 32-bit stack segment.
         */
        popl    %cs:save_retaddr        /* Scratch location */
-       popw    %cs:save_function
-       subl    $6, %esp                /* Restore %esp */
+       popl    %cs:save_function
+       subl    $8, %esp                /* Restore %esp */
        
        /* Switch to internal stack.  Note that the external stack is
         * inaccessible once we're running internally (since we have
@@ -191,6 +201,7 @@ kir_call:
        pushl   %cs:ext_cs_and_ss
 
        /* Push &ix86 on stack and call function */
+       sti
        pushl   %esp
        data32 call *%cs:save_function
        popl    %eax /* discard */
@@ -231,13 +242,13 @@ ext_esp:  .long 0
                .globl kir_ds
 kir_ds:                .word 0
                .globl kir_sp
-kir_sp:                .word 0
+kir_sp:                .word _estack
 
 /****************************************************************************
  * Temporary variables
  ****************************************************************************
  */
 save_ax:       .word 0
-save_retaddr:  .word 0
+save_retaddr:  .long 0
 save_flags:    .long 0
 save_function: .long 0