mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
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:
@@ -10,25 +10,19 @@
|
||||
#include "psr.h"
|
||||
#include "asm/asi.h"
|
||||
#include "asm/crs.h"
|
||||
#define __ASSEMBLY__
|
||||
#include "openbios/firmware_abi.h"
|
||||
#define NO_QEMU_PROTOS
|
||||
#include "openbios/fw_cfg.h"
|
||||
|
||||
#define CFG_ADDR 0x00000510
|
||||
#define CFG_ASI 0x2d
|
||||
|
||||
#define PHYS_JJ_EEPROM 0x71200000 /* [2000] MK48T08 */
|
||||
#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */
|
||||
|
||||
#define PHYS_SS10_EEPROM 0xf1200000
|
||||
#define PHYS_SS10_INTR0 0xf1400000
|
||||
|
||||
#define PHYS_SS2_EEPROM 0xf2000000
|
||||
#define PHYS_SS2_INTR0 0xf5000000
|
||||
#define SER_ADDR2 0xf1000004
|
||||
|
||||
#define PHYS_SS1000_EEPROM 0x00280000
|
||||
#define PHYS_SS1000_SBI 0x02800000
|
||||
#define SER_ADDR1000 0x00200004
|
||||
|
||||
@@ -39,6 +33,40 @@
|
||||
.section ".text", "ax"
|
||||
.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
|
||||
* We start execution from here.
|
||||
@@ -92,6 +120,16 @@ entry:
|
||||
or %g3, %g4, %g1
|
||||
! %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
|
||||
mov FW_CFG_MACHINE_ID, %g2
|
||||
sub %g5, 2, %g5
|
||||
@@ -113,20 +151,12 @@ entry:
|
||||
nop
|
||||
|
||||
! Ok, this is SS-5
|
||||
! Find architecture specific part
|
||||
set PHYS_JJ_EEPROM + OHW_ARCH_PTR, %g5
|
||||
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
|
||||
|
||||
tst %g7
|
||||
bz first_cpu
|
||||
nop
|
||||
|
||||
! SMP init, jump to user specified address
|
||||
! Clear softints used for SMP CPU startup
|
||||
set PHYS_JJ_INTR0 + 0x04, %g1
|
||||
sll %g2, 12, %g2
|
||||
add %g1, %g2, %g2
|
||||
@@ -134,62 +164,41 @@ entry:
|
||||
sta %g1, [%g2] ASI_M_BYPASS ! clear softints
|
||||
add %g2, 4, %g2
|
||||
sta %g0, [%g2] ASI_M_BYPASS ! clear softints
|
||||
add %g3, SPARC_SMP_CTXTBL, %g1
|
||||
lda [%g1] ASI_M_BYPASS, %g2
|
||||
sta %g0, [%g1] ASI_M_BYPASS
|
||||
|
||||
load_ctx:
|
||||
! 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
|
||||
sta %g2, [%g1] ASI_M_MMUREGS ! set ctx table ptr
|
||||
add %g3, SPARC_SMP_CTX, %g1
|
||||
lda [%g1] ASI_M_BYPASS, %g2
|
||||
sta %g0, [%g1] ASI_M_BYPASS
|
||||
add %g6, 0xf00, %g5 ! ctx
|
||||
lda [%g5] ASI_M_BYPASS, %g2
|
||||
sta %g0, [%g5] ASI_M_BYPASS
|
||||
set AC_M_CXR, %g1
|
||||
sta %g2, [%g1] ASI_M_MMUREGS ! set context
|
||||
add %g3, SPARC_SMP_ENTRY, %g1
|
||||
lda [%g1] ASI_M_BYPASS, %g2
|
||||
sta %g0, [%g1] ASI_M_BYPASS
|
||||
add %g6, 0xf08, %g5 ! entry
|
||||
lda [%g5] ASI_M_BYPASS, %g2
|
||||
sta %g0, [%g5] ASI_M_BYPASS
|
||||
set 1, %g1
|
||||
jmp %g2 ! jump to kernel
|
||||
sta %g1, [%g0] ASI_M_MMUREGS ! enable mmu
|
||||
|
||||
ss10:
|
||||
! Ok, this is SS-10 or SS-600MP
|
||||
! Find architecture specific part
|
||||
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
|
||||
tst %g7
|
||||
bz first_cpu
|
||||
nop
|
||||
|
||||
! SMP init, jump to user specified address
|
||||
! Clear softints used for SMP CPU startup
|
||||
set PHYS_SS10_INTR0 + 0x04, %g1
|
||||
sll %g2, 12, %g2
|
||||
add %g1, %g2, %g2
|
||||
set 0xffffffff, %g1
|
||||
sta %g1, [%g2] ASI_M_CTL ! clear softints
|
||||
add %g2, 4, %g2
|
||||
b load_ctx
|
||||
sta %g0, [%g2] ASI_M_CTL ! clear softints
|
||||
add %g3, SPARC_SMP_CTXTBL, %g1
|
||||
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:
|
||||
! Ok, this is SS-2
|
||||
@@ -206,16 +215,11 @@ ss1000:
|
||||
first_cpu:
|
||||
/* Create temporary page tables and map the ROM area to end of
|
||||
RAM. This will be done properly in iommu.c later. */
|
||||
set _end, %g3
|
||||
set 0xfff, %g2
|
||||
add %g3, %g2, %g3
|
||||
andn %g3, %g2, %g3
|
||||
set _start, %g2
|
||||
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
|
||||
! Calculate start of page tables etc. to %g6
|
||||
set 0x1000, %g4
|
||||
sub %g1, %g4, %g6 ! start of private memory
|
||||
|
||||
mov %g6, %g2 ! ctx table at s+0x0
|
||||
add %g2, 0x400, %g3 ! l1 table at s+0x400
|
||||
srl %g3, 0x4, %g3
|
||||
or %g3, 0x1, %g3
|
||||
@@ -264,7 +268,7 @@ first_cpu:
|
||||
or %g3, 0x1, %g3
|
||||
sta %g3, [%g2] ASI_M_BYPASS
|
||||
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
|
||||
or %g3, 0x1, %g3
|
||||
sta %g3, [%g2] ASI_M_BYPASS
|
||||
@@ -275,10 +279,11 @@ first_cpu:
|
||||
set _end, %g6
|
||||
set _start, %g4
|
||||
sub %g6, %g4, %g6
|
||||
srl %g6, 12, %g6 ! # of all pages
|
||||
sub %g1, %g6, %g3
|
||||
set 0x1000, %g5
|
||||
sll %g7, 0x4, %g3
|
||||
add %g5, %g3, %g3 ! ctx table + 0x1000
|
||||
sub %g3, %g5, %g3 ! start of ROM copy
|
||||
mov %g3, %g7 ! save in %g7
|
||||
srl %g6, 12, %g6 ! # of all pages
|
||||
1: srl %g3, 0x4, %g4
|
||||
or %g4, ((7 << 2) | 2), %g4 ! 7 = U: --- S: RWX
|
||||
sta %g4, [%g2] ASI_M_BYPASS
|
||||
@@ -291,10 +296,8 @@ first_cpu:
|
||||
mov %g1, %g6 ! %g6 = memory size
|
||||
|
||||
/* Copy the code, rodata and data sections from ROM. */
|
||||
set 0x1000 - 4, %g4
|
||||
sll %g7, 0x4, %g3
|
||||
add %g4, %g3, %g3 ! ctx table + 0x1000 - 4
|
||||
set _start - 4, %g4 ! First address of TEXT
|
||||
sub %g7, 4, %g3
|
||||
set _start - 4, %g4 ! First address of TEXT - 4
|
||||
set _bss, %g5 ! Last address of DATA
|
||||
ba 2f
|
||||
nop
|
||||
@@ -307,8 +310,10 @@ first_cpu:
|
||||
bl 1b
|
||||
add %g4, 0x4, %g4
|
||||
|
||||
|
||||
set 0x1000, %g3
|
||||
sub %g6, %g3, %g7 ! ctx table at s+0x0
|
||||
set AC_M_CTPR, %g2
|
||||
srl %g7, 4, %g7
|
||||
sta %g7, [%g2] ASI_M_MMUREGS ! set ctx table ptr
|
||||
set AC_M_CXR, %g2
|
||||
sta %g0, [%g2] ASI_M_MMUREGS ! context 0
|
||||
@@ -350,11 +355,15 @@ highmem:
|
||||
set qemu_mem_size, %g1
|
||||
st %g6, [%g1]
|
||||
|
||||
sll %g7, 4, %g7 ! Store va->pa conversion factor
|
||||
set _start - 0x1000, %g1
|
||||
sub %g1, %g7, %g7
|
||||
set _end, %o0 ! Store va->pa conversion factor
|
||||
set _start, %o2
|
||||
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
|
||||
st %g7, [%g1]
|
||||
st %o0, [%g1]
|
||||
|
||||
set qemu_machine_type, %g1
|
||||
mov %y, %g2
|
||||
|
||||
@@ -1132,27 +1132,44 @@ ob_interrupt_init(uint64_t base, unsigned long offset)
|
||||
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
|
||||
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)
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
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_smp_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user