- Updates for the supermicro p4dc6 motherboard

- Code to initialize sdram from C on the l440gx
- cache as ram code fro the p6 it works except conflict misses occur
  with addresses that are not cached so writing to ram does not work.
  Which makes it to brittle to count on.
- Initial implementation of a fallback booting scheme where we can
  have two copies of linuxbios in rom at once.
- Movement of 32 bit entry code from entry16.inc to entry32.inc
- Update of all config files so they now also include entry32.inc
- Fix for start_stop.c & entry16.inc so I can fairly arbitrarily relocate
  the 16bit entry code in SMP.
- A small number of fixes for warnings
This commit is contained in:
Eric W. Biederman 2001-11-27 19:29:59 +00:00
commit 2beb0a1bcc
97 changed files with 2517 additions and 291 deletions

View file

@ -25,8 +25,6 @@ it with the version available from LANL.
* protected mode.
*/
#include <arch/cache_ram.h>
.text
.code16
.globl EXT(_start)
@ -41,8 +39,8 @@ EXT(_start):
/* any further code. Even though paging is disabled we could still get*/
/*false address translations due to the TLB if we didn't invalidate it.*/
/**/
xor %eax, %eax
mov %eax, %cr3 /* Invalidate TLB*/
xorl %eax, %eax
movl %eax, %cr3 /* Invalidate TLB*/
/* invalidate the cache */
invd
@ -66,18 +64,28 @@ EXT(_start):
* So while this code is relocateable it isn't arbitrarily
* relocatable.
*
* In particular this code can be run with the base address of
* the code segment at either 0xffff0000 or 0xf0000.
* The first is what is initiallly loaded when the processor
* powers on. The second is normal real mode segment 0xf000.
* The criteria for relocation have been relaxed to their
* utmost, so that we can use the same code for both
* our initial entry point and startup of the second cpu.
* The code assumes when executing at _start that:
* (((cs & 0xfff) == 0) and (ip == _start & 0xffff))
* or
* ((cs == anything) and (ip == 0)).
*
* At this point all the linker script does when calculating
* gdtptr_offset is return the low 16 bits so your segment
* must be 64K aligned. So it wouldn't be too much work
* to support other segments, I just don't see the point
* right now.
* The restrictions in reset16.inc mean that _start initially
* must be loaded at or above 0xffff0000 or below 0x100000.
*
* The linker scripts computs gdtptr16_offset by simply returning
* the low 16 bits. This means that the intial segment used
* when start is called must be 64K aligned. This should not
* restrict the address as the ip address can be anything.
*/
data32 lgdt %cs:EXT(gdtptr_offset)
movw %cs, %ax
shlw $4, %ax
movw $EXT(gdtptr16_offset), %bx
subw %ax, %bx
data32 lgdt %cs:(%bx)
movl %cr0, %eax
andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
@ -85,62 +93,19 @@ EXT(_start):
movl %eax, %cr0
/* Now that we are in protected mode jump to a 32 bit code segment. */
data32 ljmp $0x10, $_protected_start
data32 ljmp $0x10, $__protected_start
/** This gdt has a 4 Gb code segment at 0x10, and a 4 GB data segment
/** The gdt has a 4 Gb code segment at 0x10, and a 4 GB data segment
* at 0x18; these are Linux-compatible.
*/
/** GDT. we have modified this from the original freebios to make it
* compatible with linux. This puts text at seg 0x10 and data at 0x18
*/
.align 4
.globl EXT(gdtptr)
EXT(gdtptr):
.globl EXT(gdtptr16)
EXT(gdtptr16):
.word 4*8-1
.long gdt /* we know the offset */
.globl EXT(_estart)
EXT(_estart):
gdt:
.word 0x0000, 0x0000 /* dummy */
.byte 0x00, 0x00, 0x00, 0x00
.word 0xffff, (CACHE_RAM_SEG_BASE & 0xffff) /* flat offset data segment */
.byte ((CACHE_RAM_SEG_BASE >> 16)& 0xff), 0x93, 0xcf
.byte ((CACHE_RAM_SEG_BASE >> 24) & 0xff)
.word 0xffff, 0x0000 /* flat code segment */
.byte 0x00, 0x9b, 0xcf, 0x00
.word 0xffff, 0x0000 /* flat data segment */
.byte 0x00, 0x93, 0xcf, 0x00
/*
* When we come here we are in protected mode. We expand
* the stack and copies the data segment from ROM to the
* memory.
*
* After that, we call the chipset bootstrap routine that
* does what is left of the chipset initialization.
*
* NOTE aligned to 4 so that we are sure that the prefetch
* cache will be reloaded.
*/
.align 4
_protected_start:
.code32
intel_chip_post_macro(0x10) /* post 10 */
movw $0x18, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs

View file

@ -1,2 +1,2 @@
gdtptr_offset = gdtptr & 0xffff;
gdtptr16_offset = gdtptr16 & 0xffff;
_start_offset = _start & 0xffff;

View file

@ -1,5 +1,63 @@
/* For starting linuxBIOS in protected mode */
/* For starting linuxBIOS in protected mode */
#include <arch/cache_ram.h>
.text
.align 4
.code32
/** This gdt has a 4 Gb code segment at 0x10, and a 4 GB data segment
* at 0x18; these are Linux-compatible.
*/
/** GDT. we have modified this from the original freebios to make it
* compatible with linux. This puts text at seg 0x10 and data at 0x18
*/
.align 4
.globl EXT(gdtptr)
EXT(gdtptr):
.word 4*8-1
.long gdt /* we know the offset */
gdt:
.word 0x0000, 0x0000 /* dummy */
.byte 0x00, 0x00, 0x00, 0x00
.word 0xffff, (CACHE_RAM_SEG_BASE & 0xffff) /* flat offset data segment */
.byte ((CACHE_RAM_SEG_BASE >> 16)& 0xff), 0x93, 0xcf
.byte ((CACHE_RAM_SEG_BASE >> 24) & 0xff)
.word 0xffff, 0x0000 /* flat code segment */
.byte 0x00, 0x9b, 0xcf, 0x00
.word 0xffff, 0x0000 /* flat data segment */
.byte 0x00, 0x93, 0xcf, 0x00
/*
* When we come here we are in protected mode. We expand
* the stack and copies the data segment from ROM to the
* memory.
*
* After that, we call the chipset bootstrap routine that
* does what is left of the chipset initialization.
*
* NOTE aligned to 4 so that we are sure that the prefetch
* cache will be reloaded.
*/
.align 4
.globl EXT(protected_start)
EXT(protected_start):
lgdt %cs:gdtptr
ljmp $0x10, $__protected_start
__protected_start:
intel_chip_post_macro(0x10) /* post 10 */
movw $0x18, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs

View file

@ -20,5 +20,8 @@ EXT(reset_vector):
#error _ROMBASE is an unsupported value
#endif
. = 0x8;
.code32
jmp EXT(protected_start)
.previous

10
src/cpu/i386/reset32.inc Normal file
View file

@ -0,0 +1,10 @@
.section ".reset"
.code16
.globl EXT(reset_vector)
EXT(reset_vector):
. = 0x8;
.code32
jmp EXT(protected_start)
.previous

14
src/cpu/i386/reset32.lds Normal file
View file

@ -0,0 +1,14 @@
/*
* _ROMTOP : The top of the rom used where we
* need to put the reset vector.
*/
SECTIONS {
_ROMTOP = _ROMBASE + ROM_IMAGE_SIZE - 0x10;
. = _ROMTOP;
.reset (.): {
*(.reset)
. = 15 ;
BYTE(0x00);
}
}

View file

@ -44,4 +44,4 @@
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
#endif
#endif

View file

@ -0,0 +1,40 @@
#if defined(CACHE_RAM_BASE) && defined(CACHE_RAM_SIZE)
/* Note: We cannot be running from simulated ram in
* this code. If we are evil things will happen.
*/
/* Disable the cache */
movl %cr0, %eax
orl $0x40000000, %eax
movl %eax, %cr0
/* Flush everything that is left in the cache,
* We don't want random writes to memory to occur later on.
*/
invd
/* Disable the cache ram mtrr */
movl $0x204, %ecx
xorl %eax, %eax
xorl %edx, %edx
wrmsr
movl $0x205, %ecx
xorl %eax, %eax
xorl %edx, %edx
wrmsr
/* Reenable the cache now that the mtrr is cleared */
movl %cr0, %eax
andl $0x9fffffff, %eax
movl %eax, %cr0
/* Reload the normal data segments */
movw $0x18, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs
#endif

View file

@ -0,0 +1,48 @@
#if defined(CACHE_RAM_BASE) && defined(CACHE_RAM_SIZE)
/* Disable the cache while we set up the cache ram MTRR */
movl %cr0, %eax
orl $0x40000000, %eax
movl %eax, %cr0
/* Set up an mtrr in write-back mode over some arbitrary
* location. As long as we do not get a capacity miss,
* or a multiprocessor conflict miss this should allow us to
* function as if we have memory even when it hasn't been
* enabled yet.
*/
movl $0x204, %ecx /* mtrr[0] physical base register */
xorl %edx, %edx
movl $(CACHE_RAM_BASE | 0x006), %eax
wrmsr
movl $0x205, %ecx /* mtrr[0] physical mask register */
movl $0x0000000f, %edx
movl $(~(CACHE_RAM_SIZE - 1) | 0x800), %eax
wrmsr
/* Reenable the cache now that the mtrr is set up */
movl %cr0, %eax
andl $0x9fffffff, %eax
movl %eax, %cr0
/* Force cache ram area into cache
* Note: Some versions of the P4 don't allocate a cache
* line on write immediately after a mtrr change, so
* we make certain we read the address before we write
* to it.
*/
movl $CACHE_RAM_BASE, %esi
movl $(CACHE_RAM_BASE + CACHE_RAM_SIZE), %edi
1:
movl (%esi), %eax
addl $4, %esi
movl %eax, -4(%esi)
cmpl %esi, %edi
jnz 1b
/* Load a different set of data segments */
movw $0x08, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
#endif

View file

@ -0,0 +1,27 @@
#include <arch/cache_ram.h>
/* copy data segment from FLASH ROM to CACHE */
movl $(EXT(_ldata) - CACHE_RAM_SEG_BASE), %esi
movl $EXT(_data), %edi
movl $(EXT(_eldata) - CACHE_RAM_SEG_BASE), %ecx
subl %esi, %ecx
jz 1f /* should not happen */
rep
movsb
1:
/** clear bss */
movl $EXT(_bss), %edi
movl $EXT(_ebss), %ecx
subl %edi, %ecx
jz 1f
xorl %eax, %eax
rep
stosb
1:
/* set new stack */
movl $(_stack + STACK_SIZE), %esp
call cache_ram_start

View file

@ -225,6 +225,42 @@ static void intel_set_var_mtrr(unsigned int reg, unsigned long base, unsigned lo
}
/* setting variable mtrr, comes from linux kernel source */
void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsigned char type)
{
unsigned int tmp;
if (reg >= 8)
return;
// it is recommended that we disable and enable cache when we
// do this.
/* Disable cache */
/* Write back the cache and flush TLB */
asm volatile (
"movl %%cr0, %0\n\t"
"orl $0x40000000, %0\n\t"
"movl %0, %%cr0\n\t"
:"=r" (tmp)
::"memory");
if (size == 0) {
/* The invalid bit is kept in the mask, so we simply clear the
relevant mask register to disable a range. */
wrmsr (MTRRphysMask_MSR (reg), 0, 0);
} else {
/* Bit 32-35 of MTRRphysMask should be set to 1 */
wrmsr (MTRRphysBase_MSR (reg), base | type, 0);
wrmsr (MTRRphysMask_MSR (reg), ~(size - 1) | 0x800, 0x0F);
}
// turn cache back on.
asm volatile ("movl %%cr0, %0\n\t"
"andl $0x9fffffff, %0\n\t"
"movl %0, %%cr0\n\t":"=r" (tmp)::"memory");
}
/* fms: find most sigificant bit set, stolen from Linux Kernel Source. */
static __inline__ unsigned int fms(unsigned int x)
{