linux/arch/e2k/boot/romloader.S

283 lines
7.6 KiB
ArmAsm

//
// rom_loader.S, written by <karbo@lab.sun.mcst.ru>
// secondary kernel startup module
//
#ifdef _E2K_SIMULATION_MODE_
#include <asm/simul.h>
#endif /* _E2K_SIMULATION_MODE_ */
#include <asm/head.h>
#include <asm/cpu_regs_types.h>
#ifdef CONFIG_E2K_LEGACY_SIC
#include <asm/hb_regs.h>
#endif /* CONFIG_E2K_LEGACY_SIC */
#ifdef CONFIG_SMP
#include <asm/apicdef.h>
#include <asm/epicdef.h>
#include <asm/mas.h>
#endif /* CONFIG_SMP */
#define MMU_TRAP_CELLAR_MAX_SIZE 64 /* double-words */
#define RW 0x1800000000000000
#define R 0x0800000000000000
#define RW_NONP 0x1800000000000000
#define RBS 0x10 /* 10 quadwords */
#define NMIE_PSR 0x20 /* enable nm-interrupts */
.text
.global loader
.global _data
.global __bios_size_ld
.global __bios_fsize_ld
.global __bios_entry_ld
.global __bios_start_data
.global __bios_size_data
.global __bios_size_data_plus_bss
// loader will call jump() to continue. See jumpstart.c
.global jump
.global free_memory_p
#ifdef CONFIG_SMP
.global cpu_count
.global phys_cpu_count
.global all_pic_ids
#endif /* CONFIG_SMP */
loader:
// [OS]{CUD|GD} setup
addd 0, [__bios_size_ld], %r8 // EOS size
addd 0, [EOS_RAM_BASE_LABEL+R], %r2
addd %r2,1<<58 , %r2 // set CUD.c flag
rwd %r2, %oscud.lo
addd 0, [EOS_RAM_BASE_LABEL+RW], %r6
// shld %r8, 32, %r10
addd 0, 0x01f0000000000000, %r10 // *D size (all space 1M upward)
rwd %r2, %cud.lo
rwd %r6, %osgd.lo
rwd %r6, %gd.lo
rwd %r10, %oscud.hi
rwd %r10, %osgd.hi
rwd %r10, %cud.hi
rwd %r10, %gd.hi
#ifdef CONFIG_SMP
#ifdef CONFIG_BOOT_EPIC
// read CEPIC_CTRL register
addd,1 CEPIC_CTRL, EPIC_DEFAULT_PHYS_BASE, %dr0
ldw,2 [%dr0] MAS_IOADDR, %r0 // read CEPIC_CTRL
disp %ctpr1, cpu_is_BSP
ands,0 %r0, CEPIC_CTRL_BSP_CORE, %r0 // is CPU BSP?
#else /* CONFIG_BOOT_EPIC */
// read APIC_BSP register
addd,1 APIC_BSP, APIC_DEFAULT_PHYS_BASE, %dr0 // APIC_BSP reg addr
ldw,2 [%dr0] MAS_IOADDR, %r0 // read APIC_BSP
disp %ctpr1, cpu_is_BSP
ands,0 %r0, APIC_BSP_IS_BSP, %r0 // is CPU BSP?
#endif /* CONFIG_BOOT_EPIC */
cmpesb %r0, 0, %pred0
ct %ctpr1 ? ~%pred0
addd,0 0, [cpu_count], %dr1
#ifdef CONFIG_BOOT_EPIC
addd,1 0, (CEPIC_ID + EPIC_DEFAULT_PHYS_BASE), %dr0
ldw,2 [%dr0] MAS_IOADDR, %r0 // read CEPIC_ID
ands,0 %r0, CEPIC_ID_BIT_MASK, %r0
shrs,0 %r0, 8, %r3 // calculate prepicn
ands,0 %r0, 0xf, %r0 // calculate cepicn
shls,0 %r3, 4, %r3
ors %r0, %r3, %r0 // ignore 4 bits in CEPIC_ID
#else /* CONFIG_BOOT_EPIC */
addd,1 0, (APIC_ID + APIC_DEFAULT_PHYS_BASE), %dr0 // APIC_ID reg addr
ldw,2 [%dr0] MAS_IOADDR, %r0 // read APIC_ID
shrs,0 %r0, APIC_ID_SHIFT, %r0
ands,0 %r0, APIC_ID_BIT_MASK, %r0
#endif /* CONFIG_BOOT_EPIC */
#ifdef CONFIG_E2K_SIC
ldw,0 [%dr1], %r2 // load cpu_count
adds,0 %r2, 1, %r2 // cpu_count ++
stw,2 %r2, [%dr1] // save cpu_count
sxt,0 6, %r2, %dr2 // ES2 AP CPU #
#endif /* CONFIG_E2K_SIC */
shld,0 %dr2, 2, %dr2
stw,2 %r0, [%dr2 + all_pic_ids]
addd,0 0, [phys_cpu_count], %dr1
waiting_for_cpus_startup:
ldw,0 [%dr1], %r0 // load phys_cpu_count
disp %ctpr1, waiting_for_cpus_startup
cmpesb %r0, 0, %pred0 // phys_cpu_count != 0 ?
ct %ctpr1 ? %pred0 // go waiting_for_cpus_startup
#ifndef CONFIG_BOOT_EPIC
// reset APIC_NM register
addd,1 0, APIC_DEFAULT_PHYS_BASE, %dr0 // APIC_NM reg addr
addd %dr0, APIC_NM, %dr0 //
ors 0, APIC_NM_BIT_MASK, %r1 // initial state of APIC_NM
stw,2 %r1, [%dr0] MAS_IOADDR // reset APIC_BSP
addd,1 0, APIC_DEFAULT_PHYS_BASE, %dr0 // APIC_EOI reg addr
addd %dr0, APIC_EOI, %dr0 // end of interrupt
ors 0, APIC_EOI_ACK, %r1
stw,2 %r1, [%dr0] MAS_IOADDR
#endif /* CONFIG_BOOT_EPIC */
rrs %psr, %r1
ors %r1, NMIE_PSR, %r1
rws %r1, %psr
waiting_for_apic_startup:
nop 4
disp %ctpr1, waiting_for_apic_startup
ct %ctpr1
cpu_is_BSP:
#endif /* CONFIG_SMP */
// copy BIOS .data segment from ROM to RAM
#ifdef CONFIG_E2K_LEGACY_SIC
#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
#define CONFIG_CMD(bus, devfn, where) \
((bus & 0xff) << 20) | ((devfn & 0xff) << 12) | (where & 0xfff)
#define HB_REG_ADDR(reg_offset) \
CONFIG_CMD(HB_PCI_BUS_NUM, \
PCI_DEVFN(HB_PCI_SLOT, HB_PCI_FUNC), \
reg_offset)
#define E1CP_BIOS_DATA_RAM_SIZE 0x1000000 /* 16M */
// Set low memory size to enable copiing data segment to RAM
addd 0, E1CP_PCICFG_AREA_PHYS_BASE, %dr4
addd 0, E1CP_BIOS_DATA_RAM_SIZE, %dr0
stw %dr0, [%dr4 + HB_REG_ADDR(HB_PCI_TOM)] MAS_IOADDR
#endif /* CONFIG_E2K_LEGACY_SIC */
disp %ctpr1,looper
addd 0, EOS_RAM_BASE, %r4
addd 0, [__bios_start_data], %r6 // BIOS RW data segment address
// in ROM
addd 0, [__bios_size_data], %r8 // BIOS RW data segment size
subd %r8, 16, %r8 // size-=16 due to ROM copying
// cycle organization
addd 0, [__bios_size_data_plus_bss], %r0 // BIOS RW data+BSS size
subd %r0, 32, %r0 // size-=32 due to BSS clearing
// cycle organization (ct after
// move completed - 16,
// ct evaluates %pred on next
// iteration only - 16
addd %r6, %r8, %r2 // EOS ending point in ROM
addd %r4, %r0, %r8 // EOS+BSS ending point in RAM
looper:
cmpbesb %r2,%r6, %pred0
ldd [%r6], %r0
ldd [%r6+8], %r12
addd %r6, 16, %r6
std %r0, [%r4]
std %r12, [%r4+8]
addd %r4, 16, %r4
ct %ctpr1 ? ~%pred0
// clear BSS
disp %ctpr1, looper_bss
addd 0, 0, %r0
looper_bss:
cmpbesb %r8, %r4, %pred0
std %r0, [%r4]
std %r0, [%r4+8]
addd %r4, 16, %r4
ct %ctpr1 ? ~%pred0
// PSP - procedure stack pointer
// 'E2K_ALIGN_PSTACK' kernel loader procedure stack align
addd %r4, E2K_ALIGN_PSTACK_MASK, %r4
andd %r4, (~(E2K_ALIGN_PSTACK_MASK)),%r4
// 'E2K_KERNEL_PS_PAGE_SIZE' kernel loader procedure stack align
addd %r4, (E2K_KERNEL_PS_PAGE_SIZE - 1), %r4
andd %r4, (~(E2K_KERNEL_PS_PAGE_SIZE - 1)),%r4
rwd E2K_BOOT_KERNEL_PS_SIZE << 32, %psp.hi
addd %r4, RW, %r6
rwd %r6, %psp.lo
addd %r4, (E2K_BOOT_KERNEL_PS_SIZE + E2K_KERNEL_PS_PAGE_SIZE), %r4
// 'E2K_KERNEL_PS_PAGE_SIZE' kernel loader procedure stack align
addd %r4, (E2K_KERNEL_PS_PAGE_SIZE - 1), %r4
andd %r4, (~(E2K_KERNEL_PS_PAGE_SIZE - 1)),%r4
// PCSP - procedure chain stack pointer
// 'E2K_ALIGN_PCSTACK' kernel loader procedure chain stack align
addd %r4, E2K_ALIGN_PCSTACK_MASK, %r4
andd %r4, (~(E2K_ALIGN_PCSTACK_MASK)),%r4
// 'E2K_KERNEL_PCS_PAGE_SIZE' kernel loader procedure chain stack align
addd %r4, (E2K_KERNEL_PCS_PAGE_SIZE - 1), %r4
andd %r4, (~(E2K_KERNEL_PCS_PAGE_SIZE - 1)),%r4
rwd E2K_BOOT_KERNEL_PCS_SIZE << 32, %pcsp.hi
addd %r4, RW, %r6
rwd %r6, %pcsp.lo
addd %r4, (E2K_BOOT_KERNEL_PCS_SIZE + E2K_KERNEL_PCS_PAGE_SIZE), %r4
// 'E2K_KERNEL_PCS_PAGE_SIZE' kernel loader procedure chain stack align
addd %r4, (E2K_KERNEL_PCS_PAGE_SIZE - 1), %r4
andd %r4, (~(E2K_KERNEL_PCS_PAGE_SIZE - 1)),%r4
// US - user (kernel loader) stack pointer
// 'E2K_ALIGN_USTACK' kernel loader stack align
addd %r4, E2K_ALIGN_USTACK_MASK, %r4
andd %r4, (~(E2K_ALIGN_USTACK_MASK)),%r4
// 'E2K_KERNEL_US_PAGE_SIZE' kernel loader stack align
// User Stack is supposed to grow from higher memory addresses to lower ones
// Switch to higher memory addresses of stack
addd %r4, E2K_BOOT_KERNEL_US_SIZE, %r4
addd %r4, (E2K_KERNEL_US_PAGE_SIZE - 1), %r4
andd %r4, (~(E2K_KERNEL_US_PAGE_SIZE - 1)),%r4
rwd E2K_BOOT_KERNEL_US_SIZE << 32, %usd.hi
addd %r4, E2K_ALIGN_STACKS_BASE_MASK, %r4
andd %r4, (~(E2K_ALIGN_STACKS_BASE_MASK)), %r4
rwd %r4, %sbr
addd %r4, RW_NONP, %r6
rwd %r6, %usd.lo
// Trap Cellar
std %r0, [0x0] 71
std %r4, [0x00000050] 71
addd %dr4, MMU_TRAP_CELLAR_MAX_SIZE * 8, %dr4
std %dr4, [free_memory_p]
// Jump to the rtc0 (preparation)
addd 0, [jump], %r2
movtd %r2, %ctpr1
setwd wsz=RBS+4
// Call jump() and fly away
call %ctpr1, wbs=RBS
.size loader, . - loader