Use RAM for SMP init instead of NVRAM

git-svn-id: svn://coreboot.org/openbios/openbios-devel@426 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
Blue Swirl
2009-01-25 12:20:12 +00:00
parent 3fae06cd81
commit eea3589cb9
2 changed files with 115 additions and 87 deletions

View File

@@ -10,25 +10,19 @@
#include "psr.h" #include "psr.h"
#include "asm/asi.h" #include "asm/asi.h"
#include "asm/crs.h" #include "asm/crs.h"
#define __ASSEMBLY__
#include "openbios/firmware_abi.h"
#define NO_QEMU_PROTOS #define NO_QEMU_PROTOS
#include "openbios/fw_cfg.h" #include "openbios/fw_cfg.h"
#define CFG_ADDR 0x00000510 #define CFG_ADDR 0x00000510
#define CFG_ASI 0x2d #define CFG_ASI 0x2d
#define PHYS_JJ_EEPROM 0x71200000 /* [2000] MK48T08 */
#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */ #define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */
#define PHYS_SS10_EEPROM 0xf1200000
#define PHYS_SS10_INTR0 0xf1400000 #define PHYS_SS10_INTR0 0xf1400000
#define PHYS_SS2_EEPROM 0xf2000000
#define PHYS_SS2_INTR0 0xf5000000 #define PHYS_SS2_INTR0 0xf5000000
#define SER_ADDR2 0xf1000004 #define SER_ADDR2 0xf1000004
#define PHYS_SS1000_EEPROM 0x00280000
#define PHYS_SS1000_SBI 0x02800000 #define PHYS_SS1000_SBI 0x02800000
#define SER_ADDR1000 0x00200004 #define SER_ADDR1000 0x00200004
@@ -39,6 +33,40 @@
.section ".text", "ax" .section ".text", "ax"
.align 8 .align 8
/* Memory map:
*
* Top +-------------------------+
* | SMP CPU table |
* | s + 0xf00 ... 0xf0f |
* | s + 0xf0c valid |
* | s + 0xf08 entry |
* | s + 0xf04 ctxtbl |
* | s + 0xf00 ctx |
* +-------------------------+
* | Bootstrap |
* | MMU L3 tables 5 * 0x100 |
* | s + 0xa00 ... 0xeff |
* +-------------------------+
* | Bootstrap |
* | MMU L2 tables 2 * 0x100 |
* | s + 0x800 ... 0x9ff |
* +-------------------------+
* | Bootstrap |
* | MMU L1 table 0x400 |
* | s + 0x400 ... 0x7ff |
* +-------------------------+
* | Bootstrap |
* | MMU L0/ctx table 0x400 |
* | s + 0x000 ... 0x3ff |
* +-------------------------+
* | |
* | ROM into RAM |
* | |
* +-------------------------+
* : :
* Bottom
*/
/* /*
* Entry point * Entry point
* We start execution from here. * We start execution from here.
@@ -92,6 +120,16 @@ entry:
or %g3, %g4, %g1 or %g3, %g4, %g1
! %g1 contains end of memory ! %g1 contains end of memory
! Start of private memory in %g6
set 0x1000, %g3
sub %g1, %g3, %g6
! Calculate SMP table location
add %g6, 0xf0c, %g2 ! valid?
lda [%g2] ASI_M_BYPASS, %g7
sta %g0, [%g2] ASI_M_BYPASS
! Get machine ID from configuration device ! Get machine ID from configuration device
mov FW_CFG_MACHINE_ID, %g2 mov FW_CFG_MACHINE_ID, %g2
sub %g5, 2, %g5 sub %g5, 2, %g5
@@ -113,20 +151,12 @@ entry:
nop nop
! Ok, this is SS-5 ! Ok, this is SS-5
! Find architecture specific part
set PHYS_JJ_EEPROM + OHW_ARCH_PTR, %g5 tst %g7
lduha [%g5] ASI_M_BYPASS, %g2
set PHYS_JJ_EEPROM, %g5
add %g5, %g2, %g3
! Check if this not the first SMP CPU, if so, bypass PROM entirely
add %g3, SPARC_SMP_VALID, %g5
lduba [%g5] ASI_M_BYPASS, %g2
stba %g0, [%g5] ASI_M_BYPASS
tst %g2
bz first_cpu bz first_cpu
nop nop
! SMP init, jump to user specified address ! Clear softints used for SMP CPU startup
set PHYS_JJ_INTR0 + 0x04, %g1 set PHYS_JJ_INTR0 + 0x04, %g1
sll %g2, 12, %g2 sll %g2, 12, %g2
add %g1, %g2, %g2 add %g1, %g2, %g2
@@ -134,62 +164,41 @@ entry:
sta %g1, [%g2] ASI_M_BYPASS ! clear softints sta %g1, [%g2] ASI_M_BYPASS ! clear softints
add %g2, 4, %g2 add %g2, 4, %g2
sta %g0, [%g2] ASI_M_BYPASS ! clear softints sta %g0, [%g2] ASI_M_BYPASS ! clear softints
add %g3, SPARC_SMP_CTXTBL, %g1
lda [%g1] ASI_M_BYPASS, %g2 load_ctx:
sta %g0, [%g1] ASI_M_BYPASS ! SMP init, jump to user specified address
add %g6, 0xf04, %g5 ! ctxtbl
lda [%g5] ASI_M_BYPASS, %g2
sta %g0, [%g5] ASI_M_BYPASS
set AC_M_CTPR, %g1 set AC_M_CTPR, %g1
sta %g2, [%g1] ASI_M_MMUREGS ! set ctx table ptr sta %g2, [%g1] ASI_M_MMUREGS ! set ctx table ptr
add %g3, SPARC_SMP_CTX, %g1 add %g6, 0xf00, %g5 ! ctx
lda [%g1] ASI_M_BYPASS, %g2 lda [%g5] ASI_M_BYPASS, %g2
sta %g0, [%g1] ASI_M_BYPASS sta %g0, [%g5] ASI_M_BYPASS
set AC_M_CXR, %g1 set AC_M_CXR, %g1
sta %g2, [%g1] ASI_M_MMUREGS ! set context sta %g2, [%g1] ASI_M_MMUREGS ! set context
add %g3, SPARC_SMP_ENTRY, %g1 add %g6, 0xf08, %g5 ! entry
lda [%g1] ASI_M_BYPASS, %g2 lda [%g5] ASI_M_BYPASS, %g2
sta %g0, [%g1] ASI_M_BYPASS sta %g0, [%g5] ASI_M_BYPASS
set 1, %g1 set 1, %g1
jmp %g2 ! jump to kernel jmp %g2 ! jump to kernel
sta %g1, [%g0] ASI_M_MMUREGS ! enable mmu sta %g1, [%g0] ASI_M_MMUREGS ! enable mmu
ss10: ss10:
! Ok, this is SS-10 or SS-600MP ! Ok, this is SS-10 or SS-600MP
! Find architecture specific part tst %g7
set PHYS_SS10_EEPROM + OHW_ARCH_PTR, %g5
lduha [%g5] ASI_M_CTL, %g2
set PHYS_SS10_EEPROM, %g5
add %g5, %g2, %g3
! Check if this not the first SMP CPU, if so, bypass PROM entirely
add %g3, SPARC_SMP_VALID, %g5
lduba [%g5] ASI_M_CTL, %g2
stba %g0, [%g5] ASI_M_CTL
tst %g2
bz first_cpu bz first_cpu
nop nop
! SMP init, jump to user specified address ! Clear softints used for SMP CPU startup
set PHYS_SS10_INTR0 + 0x04, %g1 set PHYS_SS10_INTR0 + 0x04, %g1
sll %g2, 12, %g2 sll %g2, 12, %g2
add %g1, %g2, %g2 add %g1, %g2, %g2
set 0xffffffff, %g1 set 0xffffffff, %g1
sta %g1, [%g2] ASI_M_CTL ! clear softints sta %g1, [%g2] ASI_M_CTL ! clear softints
add %g2, 4, %g2 add %g2, 4, %g2
sta %g0, [%g2] ASI_M_CTL ! clear softints b load_ctx
add %g3, SPARC_SMP_CTXTBL, %g1 sta %g0, [%g2] ASI_M_CTL ! clear softints
lda [%g1] ASI_M_CTL, %g2
sta %g0, [%g1] ASI_M_CTL
set AC_M_CTPR, %g1
sta %g2, [%g1] ASI_M_MMUREGS ! set ctx table ptr
add %g3, SPARC_SMP_CTX, %g1
lda [%g1] ASI_M_CTL, %g2
sta %g0, [%g1] ASI_M_CTL
set AC_M_CXR, %g1
sta %g2, [%g1] ASI_M_MMUREGS ! set context
add %g3, SPARC_SMP_ENTRY, %g1
lda [%g1] ASI_M_CTL, %g2
sta %g0, [%g1] ASI_M_CTL
set 1, %g1
jmp %g2 ! jump to kernel
sta %g1, [%g0] ASI_M_MMUREGS ! enable mmu
ss2: ss2:
! Ok, this is SS-2 ! Ok, this is SS-2
@@ -206,16 +215,11 @@ ss1000:
first_cpu: first_cpu:
/* Create temporary page tables and map the ROM area to end of /* Create temporary page tables and map the ROM area to end of
RAM. This will be done properly in iommu.c later. */ RAM. This will be done properly in iommu.c later. */
set _end, %g3 ! Calculate start of page tables etc. to %g6
set 0xfff, %g2 set 0x1000, %g4
add %g3, %g2, %g3 sub %g1, %g4, %g6 ! start of private memory
andn %g3, %g2, %g3
set _start, %g2 mov %g6, %g2 ! ctx table at s+0x0
sub %g3, %g2, %g3
set 0x1000, %g4 ! add 0x1000 for page tables
add %g4, %g3, %g2
sub %g1, %g2, %g2 ! start of private memory
srl %g2, 0x4, %g7 ! ctx table at s+0x0
add %g2, 0x400, %g3 ! l1 table at s+0x400 add %g2, 0x400, %g3 ! l1 table at s+0x400
srl %g3, 0x4, %g3 srl %g3, 0x4, %g3
or %g3, 0x1, %g3 or %g3, 0x1, %g3
@@ -264,7 +268,7 @@ first_cpu:
or %g3, 0x1, %g3 or %g3, 0x1, %g3
sta %g3, [%g2] ASI_M_BYPASS sta %g3, [%g2] ASI_M_BYPASS
add %g2, 4, %g2 ! s+0x9e0 add %g2, 4, %g2 ! s+0x9e0
add %g2, 0xd00 - 0x9e0, %g3 ! 5th l3 table for rom at s+0xe00 add %g2, 0xe00 - 0x9e0, %g3 ! 5th l3 table for rom at s+0xe00
srl %g3, 0x4, %g3 srl %g3, 0x4, %g3
or %g3, 0x1, %g3 or %g3, 0x1, %g3
sta %g3, [%g2] ASI_M_BYPASS sta %g3, [%g2] ASI_M_BYPASS
@@ -275,10 +279,11 @@ first_cpu:
set _end, %g6 set _end, %g6
set _start, %g4 set _start, %g4
sub %g6, %g4, %g6 sub %g6, %g4, %g6
srl %g6, 12, %g6 ! # of all pages sub %g1, %g6, %g3
set 0x1000, %g5 set 0x1000, %g5
sll %g7, 0x4, %g3 sub %g3, %g5, %g3 ! start of ROM copy
add %g5, %g3, %g3 ! ctx table + 0x1000 mov %g3, %g7 ! save in %g7
srl %g6, 12, %g6 ! # of all pages
1: srl %g3, 0x4, %g4 1: srl %g3, 0x4, %g4
or %g4, ((7 << 2) | 2), %g4 ! 7 = U: --- S: RWX or %g4, ((7 << 2) | 2), %g4 ! 7 = U: --- S: RWX
sta %g4, [%g2] ASI_M_BYPASS sta %g4, [%g2] ASI_M_BYPASS
@@ -291,10 +296,8 @@ first_cpu:
mov %g1, %g6 ! %g6 = memory size mov %g1, %g6 ! %g6 = memory size
/* Copy the code, rodata and data sections from ROM. */ /* Copy the code, rodata and data sections from ROM. */
set 0x1000 - 4, %g4 sub %g7, 4, %g3
sll %g7, 0x4, %g3 set _start - 4, %g4 ! First address of TEXT - 4
add %g4, %g3, %g3 ! ctx table + 0x1000 - 4
set _start - 4, %g4 ! First address of TEXT
set _bss, %g5 ! Last address of DATA set _bss, %g5 ! Last address of DATA
ba 2f ba 2f
nop nop
@@ -307,8 +310,10 @@ first_cpu:
bl 1b bl 1b
add %g4, 0x4, %g4 add %g4, 0x4, %g4
set 0x1000, %g3
sub %g6, %g3, %g7 ! ctx table at s+0x0
set AC_M_CTPR, %g2 set AC_M_CTPR, %g2
srl %g7, 4, %g7
sta %g7, [%g2] ASI_M_MMUREGS ! set ctx table ptr sta %g7, [%g2] ASI_M_MMUREGS ! set ctx table ptr
set AC_M_CXR, %g2 set AC_M_CXR, %g2
sta %g0, [%g2] ASI_M_MMUREGS ! context 0 sta %g0, [%g2] ASI_M_MMUREGS ! context 0
@@ -350,11 +355,15 @@ highmem:
set qemu_mem_size, %g1 set qemu_mem_size, %g1
st %g6, [%g1] st %g6, [%g1]
sll %g7, 4, %g7 ! Store va->pa conversion factor set _end, %o0 ! Store va->pa conversion factor
set _start - 0x1000, %g1 set _start, %o2
sub %g1, %g7, %g7 sub %o0, %o2, %o0
sub %g6, %o0, %o0
set 0x1000, %o1
sub %o0, %o1, %o0 ! start of ROM copy
sub %o2, %o0, %o0 ! start of ROM copy
set va_shift, %g1 set va_shift, %g1
st %g7, [%g1] st %o0, [%g1]
set qemu_machine_type, %g1 set qemu_machine_type, %g1
mov %y, %g2 mov %y, %g2

View File

@@ -1132,27 +1132,44 @@ ob_interrupt_init(uint64_t base, unsigned long offset)
fword("finish-device"); fword("finish-device");
} }
/* SMP CPU boot structure */
struct smp_cfg {
uint32_t smp_ctx;
uint32_t smp_ctxtbl;
uint32_t smp_entry;
uint32_t valid;
};
static struct smp_cfg *smp_header;
int int
start_cpu(unsigned int pc, unsigned int context_ptr, unsigned int context, int cpu) start_cpu(unsigned int pc, unsigned int context_ptr, unsigned int context, int cpu)
{ {
ohwcfg_v3_t *header = (ohwcfg_v3_t *)nvram;
struct sparc_arch_cfg *sparc_header;
if (!cpu) if (!cpu)
return -1; return -1;
sparc_header = (struct sparc_arch_cfg *)&nvram[header->nvram_arch_ptr];
sparc_header->smp_entry = pc;
sparc_header->smp_ctxtbl = context_ptr;
sparc_header->smp_ctx = context;
sparc_header->valid = 1;
cpu &= 7; cpu &= 7;
smp_header->smp_entry = pc;
smp_header->smp_ctxtbl = context_ptr;
smp_header->smp_ctx = context;
smp_header->valid = cpu;
intregs->cpu_intregs[cpu].set = SUN4M_SOFT_INT(14); intregs->cpu_intregs[cpu].set = SUN4M_SOFT_INT(14);
return 0; return 0;
} }
static void
ob_smp_init(void)
{
unsigned long mem_size;
// See arch/sparc32/entry.S for memory layout
mem_size = fw_cfg_read_i32(FW_CFG_RAM_SIZE);
smp_header = (struct smp_cfg *)map_io((uint64_t)(mem_size - 0x100),
sizeof(struct smp_cfg));
}
static void static void
ob_obio_open(__attribute__((unused))int *idx) ob_obio_open(__attribute__((unused))int *idx)
@@ -1276,5 +1293,7 @@ ob_obio_init(uint64_t slavio_base, unsigned long fd_offset,
ob_interrupt_init(slavio_base, intr_offset); ob_interrupt_init(slavio_base, intr_offset);
ob_smp_init();
return 0; return 0;
} }