[MAJOR] Updated early ARM bootstrap

There are no unmapped code in kernel now.

_kern_phys_base is determed in run-time.
NOTE! It doesn't work on the RPI3 now. Fix it later.
This commit is contained in:
Korobov Nikita
2017-05-12 06:06:51 +03:00
parent cecc3c0d18
commit cde275c049
10 changed files with 257 additions and 124 deletions

View File

@@ -4,49 +4,6 @@
HERE=${.CURDIR}/arch/${MACHINE_ARCH}
.PATH: ${HERE}
# objects we want unpaged from -lc
MINLIB_OBJS_UNPAGED= get_bp.o
get_bp.o: ${NETBSDSRCDIR}/minix/lib/libc/arch/arm/get_bp.S
# objects we want unpaged from -lsys
SYS_OBJS_UNPAGED=assert.o stacktrace.o
assert.o: ${NETBSDSRCDIR}/minix/lib/libsys/assert.c
stacktrace.o: ${NETBSDSRCDIR}/minix/lib/libsys/stacktrace.c
# objects we want unpaged from -lminc
MINC_OBJS_UNPAGED= atoi.o \
printf.o subr_prf.o \
strcmp.o strcpy.o strlen.o strncmp.o \
memcpy.o memmove.o memset.o
MINC_OBJS_UNPAGED+= divmodsi4.o divsi3.o udivsi3.o umodsi3.o \
umoddi3.o udivmoddi4.o __aeabi_idiv0.o aeabi_idivmod.o aeabi_uidivmod.o \
udivmodsi4.o aeabi_uldivmod.o
atoi.o: ${NETBSDSRCDIR}/minix/lib/libminc/atoi.c
printf.o: ${NETBSDSRCDIR}/sys/lib/libsa/printf.c
subr_prf.o: ${NETBSDSRCDIR}/sys/lib/libsa/subr_prf.c
memcpy.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/memcpy.S
memmove.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/memmove.S
memset.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/memset.S
strlen.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/strlen.S
strcpy.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/strcpy.S
strcmp.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/string/strcmp.S
__aeabi_idiv0.o: ${NETBSDSRCDIR}/common/lib/libc/arch/arm/gen/__aeabi_idiv0.c
CPPFLAGS.__aeabi_idiv0.c+= -D_STANDALONE -I${NETBSDSRCDIR}/sys
divsi3.o: ${NETBSDSRCDIR}/sys/external/bsd/compiler_rt/dist/lib/builtins/divsi3.c
udivsi3.o: ${NETBSDSRCDIR}/sys/external/bsd/compiler_rt/dist/lib/builtins/udivsi3.c
umodsi3.o: ${NETBSDSRCDIR}/sys/external/bsd/compiler_rt/dist/lib/builtins/umodsi3.c
umoddi3.o: ${NETBSDSRCDIR}/sys/external/bsd/compiler_rt/dist/lib/builtins/umoddi3.c
udivmoddi4.o: ${NETBSDSRCDIR}/sys/external/bsd/compiler_rt/dist/lib/builtins/udivmoddi4.c
divmodsi4.o: ${NETBSDSRCDIR}/sys/external/bsd/compiler_rt/dist/lib/builtins/arm/divmodsi4.S
udivmodsi4.o: ${NETBSDSRCDIR}/sys/external/bsd/compiler_rt/dist/lib/builtins/arm/udivmodsi4.S
aeabi_idivmod.o: ${NETBSDSRCDIR}/sys/external/bsd/compiler_rt/dist/lib/builtins/arm/aeabi_idivmod.S
aeabi_uidivmod.o: ${NETBSDSRCDIR}/sys/external/bsd/compiler_rt/dist/lib/builtins/arm/aeabi_uidivmod.S
aeabi_uldivmod.o: ${NETBSDSRCDIR}/sys/external/bsd/compiler_rt/dist/lib/builtins/arm/aeabi_uldivmod.S
# the following is required by pre_init.c
strncmp.o: ${NETBSDSRCDIR}/common/lib/libc/string/strncmp.c
# LSC: putchar and kputc have the same signature. A bit hackish.
CPPFLAGS.subr_prf.c+= -Dputchar=kputc
@@ -58,9 +15,7 @@ CPPFLAGS.subr_prf.c+= -DLIBSA_PRINTF_LONGLONG_SUPPORT -DLIBSA_PRINTF_WIDTH_SUPPO
# some object files we give a symbol prefix (or namespace) of __k_unpaged_
# that must live in their own unique namespace.
#
.for unpaged_obj in head.o pre_init.o direct_tty_utils.o \
pg_utils.o klib.o utility.o arch_reset.o \
${MINLIB_OBJS_UNPAGED} ${MINC_OBJS_UNPAGED} ${SYS_OBJS_UNPAGED} ${BSP_OBJS_UNPAGED}
.for unpaged_obj in head.o
unpaged_${unpaged_obj}: ${unpaged_obj}
${OBJCOPY} --prefix-symbols=__k_unpaged_ ${.OBJDIR}/${unpaged_obj} $@
UNPAGED_OBJS += unpaged_${unpaged_obj}
@@ -71,7 +26,7 @@ ORIG_UNPAGED_OBJS += ${unpaged_obj}
CLEANFILES+= ${ORIG_UNPAGED_OBJS}
SRCS+= mpx.S arch_clock.c arch_do_vmctl.c arch_system.c do_padconf.c \
exception.c hw_intr.c klib.S memory.c \
exception.c hw_intr.c klib.S memory.c pre_init.c \
protect.c direct_tty_utils.c arch_reset.c \
pg_utils.c phys_copy.S phys_memset.S exc.S

View File

@@ -1,3 +1,4 @@
#include "kernel/kernel.h" /* configures the kernel */
/* sections */
@@ -19,9 +20,9 @@
#include "arch_proto.h" /* K_STACK_SIZE */
.section .startup
/*===========================================================================*/
/* MINIX */
/*===========================================================================*/
/*==================================================*/
/* MINIX */
/*==================================================*/
.global MINIX
MINIX:
/* this is the entry point for the MINIX kernel */
@@ -29,9 +30,212 @@ MINIX:
.text
multiboot_init:
ldr sp, =load_stack_start /* make usable stack */
/*
* We enable paging on early stage of booting in this file.
* Only the head.o contains __k_unpaged code.
*
* To make platform-independent boot system we should not keep _kern_phys_base
* as a constant. We should know it at run-time from program counter
* and create page table relatively it.
*
* NOTE!
* We should not use r0 and r1 here, because they contain external parametrs.
*
* in r0 - argc
* in r1 - argv
*
* r4 - pg_table
* r9 - _kern_phys_base
*
* out r0 - argc
* out r1 - argv
*/
ldr r6, =0xFFF00000
and r9, pc, r6
mov r6, #0
/* Clean cache */
mcr p15, 0, r6, c7, c14, 2
ldr r4, =pg_table
mov r6, #0
/****************************************************/
/* Clear kernel bss section */
/****************************************************/
ldr r2, =_edata
ldr r3, =_end
sub r3, r3, r2
mov r6, #0
mov r5, #0
b check1
1:
str r6, [r2], #4
add r5, r5, #1
check1:
cmp r5, r3
bne 1b
/****************************************************/
/* Clear kernel unpaged bss section */
/****************************************************/
ldr r2, =_kern_unpaged_edata
ldr r3, =_kern_unpaged_end
sub r3, r3, r2
mov r6, #0
mov r5, #0
b check2
1:
str r6, [r2], #4
add r5, r5, #1
check2:
cmp r5, r3
bne 1b
/****************************************************/
/* Clear the page table */
/****************************************************/
/* The page table is initialized by zeroes */
/* (the page table are not in the bss section). */
/****************************************************/
mov r2, r4
mov r3, #0
add r6, r2, #0x4000
1:
str r3, [r2], #4
str r3, [r2], #4
str r3, [r2], #4
str r3, [r2], #4
teq r2, r6
bne 1b
/****************************************************/
/* Page identify */
/****************************************************/
/* Page table is filled by cahced or device memory */
/* It requires, because it will be better, if all */
/* entries are initialized. */
/****************************************************/
mov r6, #0
mov r7, #0
mov r3, #0
orr r3, r3, #ARM_VM_SECTION
orr r3, r3, #ARM_VM_SECTION_USER
orr r3, r3, #ARM_VM_SECTION_DOMAIN
1:
ldr r5, =0x3effffff //FIXME
cmp r7, r5
blo cached
ldr r2, =#ARM_VM_SECTION_DEVICE
b setup
cached:
ldr r2, =#ARM_VM_SECTION_CACHED
setup:
orr r3, r3, r2
orr r2, r3, r7
add r7, r7, #ARM_SECTION_SIZE
str r2, [r4, r6, lsl #2]
add r6, r6, #1
cmp r6, #ARM_VM_DIR_ENTRIES
blo 1b
/****************************************************/
/* Map kernel */
/****************************************************/
/* Kernel maps from _kern_phys_base, which locates */
/* in r9, to _kern_vir_base (0xf0400000). */
/* The first free entry in the page table is placed */
/* in freepde. */
/****************************************************/
ldr r6, =0xf0400000 //FIXME
mov r7, r9
add r5, r4, r6, lsr #18
mov r8, #0
orr r8, r8, #ARM_VM_SECTION
orr r8, r8, #ARM_VM_SECTION_SUPER
orr r8, r8, #ARM_VM_SECTION_DOMAIN
ldr r2, =#ARM_VM_SECTION_CACHED
orr r8, r8, r2
ldr r3, =#ARM_VM_SECTION_MASK
1:
and r2, r7, r3
orr r2, r2, r8
str r2, [r5], #4
add r7, r7, #ARM_SECTION_SIZE
cmp r7, r6
blo 1b
ldr r3, =freepde
sub r5, r5, r4
lsr r5, #3
str r5, [r3]
/****************************************************/
/* Load the page table */
/****************************************************/
dsb
isb
ldr r2, =#ARM_TTBR_ADDR_MASK
and r2, r4, r2
orr r2, r2, #ARM_TTBR_FLAGS_CACHED
/* Write page table base */
mcr p15, 0, r2, c2, c0, 0
dsb
mov r2, #0
/* Invalidate unified TLB register */
mcr p15, 0, r2, c8, c7, 0
/* Invalidate entire instruction cache register */
mcr p15, 0, r2, c7, c5, 0
/* Flush entire branch target cache register */
mcr p15, 0, r2, c7, c5, 6
dsb
isb
/****************************************************/
/* Enable paging */
/****************************************************/
/* Read translation table base control register */
mcr p15, 0, r2, c2, c0, 2
ldr r2, =0x55555555
/* Read domain access control register */
mcr p15, 0, r2, c3, c0, 0
isb
/* Read control register */
mrc p15, 0, r3, c1, c0, 0
isb
orr r3, r3, #CPU_CONTROL_32BD_ENABLE
orr r3, r3, #CPU_CONTROL_MMU_ENABLE
orr r3, r3, #CPU_CONTROL_DC_ENABLE
orr r3, r3, #CPU_CONTROL_IC_ENABLE
orr r3, r3, #CPU_CONTROL_BPRD_ENABLE
/* Read auxiliary control register */
mrc p15, 0, r2, c1, c0, 1
orr r2, r2, #2
/* Write auxiliary control register */
mcr p15, 0, r2, c1, c0, 1
isb
/* Write control register */
mcr p15, 0, r3, c1, c0, 0
isb
ldr sp, =k_initial_stktop /* make usable stack */
/* Terminate stack */
mov fp, #0
bl _C_LABEL(pre_init)
mov r2, #0
push {r2}
bl _C_LABEL(pre_init)
ldr r4, =1384 // FIXME
add r3, r0, r4
ldr r5, =freepde
ldr r5, [r5]
str r5, [r3]
/* Kernel is mapped high now and ready to go, with
* the boot info pointer returned by pre_init in r0.
@@ -39,9 +243,6 @@ multiboot_init:
*
* Afther that call kmain with r0 still pointing to boot info
*/
ldr sp, =k_initial_stktop
mov r1, #0
push {r1} /* Terminate stack */
ldr r2, =_C_LABEL(kmain) /* r0 holds kinfo_t ptr */
bx r2
@@ -50,6 +251,9 @@ hang:
b hang
.data
load_stack:
.space 4096
load_stack_start:
.balign 16384
pg_table:
.space 16384
freepde:
.word 0

View File

@@ -12,13 +12,14 @@ __k_unpaged__kern_phys_base = _kern_phys_base;
SECTIONS
{
. = _kern_phys_base;
__k_unpaged__kern_unpaged_start = .;
_kern_unpaged_start = .;
.unpaged_text ALIGN(4096) : { unpaged_*.o(.startup); unpaged_*.o(.text) }
.unpaged_data ALIGN(4096) : { unpaged_*.o(.data .rodata*) }
_kern_unpaged_edata = .;
__k_unpaged__kern_unpaged_edata = .;
.unpaged_bss ALIGN(4096) : { unpaged_*.o(.bss COMMON) }
_kern_unpaged_end = .;
__k_unpaged__kern_unpaged_end = .;
. += _kern_offset;
@@ -41,10 +42,10 @@ SECTIONS
. += 4096;
}
_end = .;
__k_unpaged__end = . - _kern_offset;
__k_unpaged__end = . - _kern_offset;
/DISCARD/ :
{
*(.ARM.exidx*)
}
/DISCARD/ :
{
*(.ARM.exidx*)
}
}

View File

@@ -2,7 +2,7 @@ OUTPUT_ARCH("arm")
ENTRY(__k_unpaged_MINIX)
_kern_phys_base = 0x00200000; /* phys 4MB aligned for convenient remapping */
_kern_vir_base = 0xF0400000; /* map kernel high for max. user vir space */
_kern_vir_base = 0xF0400000; /* map kernel high for max. user vir space */
_kern_offset = (_kern_vir_base - _kern_phys_base);
__k_unpaged__kern_offset = _kern_offset;
@@ -12,13 +12,14 @@ __k_unpaged__kern_phys_base = _kern_phys_base;
SECTIONS
{
. = _kern_phys_base;
__k_unpaged__kern_unpaged_start = .;
_kern_unpaged_start = .;
.unpaged_text ALIGN(4096) : { unpaged_*.o(.startup); unpaged_*.o(.text) }
.unpaged_data ALIGN(4096) : { unpaged_*.o(.data .rodata*) }
_kern_unpaged_edata = .;
__k_unpaged__kern_unpaged_edata = .;
.unpaged_bss ALIGN(4096) : { unpaged_*.o(.bss COMMON) }
_kern_unpaged_end = .;
__k_unpaged__kern_unpaged_end = .;
. += _kern_offset;
@@ -33,7 +34,7 @@ SECTIONS
.data ALIGN(4096) : AT(ADDR(.data) - _kern_offset) { *(.data .rodata* ) }
. = ALIGN(4096);
_edata = .;
__k_unpaged__edata = . - _kern_offset;
__k_unpaged__edata = . - _kern_offset;
.bss ALIGN(4096) : AT(ADDR(.bss) - _kern_offset) { *(.bss* COMMON)
__k_unpaged__kern_size = . - _kern_vir_base;
_kern_size = __k_unpaged__kern_size;
@@ -41,10 +42,10 @@ SECTIONS
. += 4096;
}
_end = .;
__k_unpaged__end = . - _kern_offset;
__k_unpaged__end = . - _kern_offset;
/DISCARD/ :
{
*(.ARM.exidx*)
}
/DISCARD/ :
{
*(.ARM.exidx*)
}
}

View File

@@ -1,5 +1,3 @@
#define UNPAGED 1 /* for proper kmain() prototype */
#include "kernel/kernel.h"
#include <assert.h>
#include <stdlib.h>
@@ -26,9 +24,6 @@
kinfo_t kinfo;
struct kmessages kmessages;
/* pg_utils.c uses this; in this phase, there is a 1:1 mapping. */
phys_bytes vir2phys(void *addr) { return (phys_bytes) addr; }
static void setup_mbi(multiboot_info_t *mbi, char *bootargs);
/* String length used for mb_itoa */
@@ -41,10 +36,6 @@ int kernel_may_alloc = 1;
extern u32_t _edata;
extern u32_t _end;
/* kernel unpaged bss */
extern char _kern_unpaged_edata;
extern char _kern_unpaged_end;
/*
* During low level init many things are not supposed to work
* serial being one of them. We therefore can't rely on the
@@ -176,7 +167,7 @@ int overlaps(multiboot_module_t *mod, int n, int cmp_mod)
#define INRANGE(mod, v) ((v) >= mod->mod_start && (v) <= thismod->mod_end)
#define OVERLAP(mod1, mod2) (INRANGE(mod1, mod2->mod_start) || \
INRANGE(mod1, mod2->mod_end))
INRANGE(mod1, mod2->mod_end))
for(m = 0; m < n; m++) {
multiboot_module_t *thismod = &mod[m];
if(m == cmp_mod) continue;
@@ -223,7 +214,7 @@ void setup_mbi(multiboot_info_t *mbi, char *bootargs)
for (i = 0; i < MB_MODS_NR; ++i) {
mb_modlist[i].mod_start = mb_mods_base + i * mb_mods_align;
mb_modlist[i].mod_end = mb_modlist[i].mod_start + mb_mods_align
- ARM_PAGE_SIZE;
- ARM_PAGE_SIZE;
mb_modlist[i].cmdline = 0;
}
@@ -246,9 +237,9 @@ void get_parameters(kinfo_t *cbi, char *bootargs)
int var_i,value_i, m, k;
char *p;
extern char _kern_phys_base, _kern_vir_base, _kern_size,
_kern_unpaged_start, _kern_unpaged_end;
_kern_unpaged_start, _kern_unpaged_end;
phys_bytes kernbase = (phys_bytes) &_kern_phys_base,
kernsize = (phys_bytes) &_kern_size;
kernsize = (phys_bytes) &_kern_size;
#define BUF 1024
static char cmdline[BUF];
@@ -324,10 +315,10 @@ void get_parameters(kinfo_t *cbi, char *bootargs)
/* mem_map has a variable layout */
if(mbi->flags & MULTIBOOT_INFO_MEM_MAP) {
cbi->mmap_size = 0;
for (mmap = (multiboot_memory_map_t *) mbi->mmap_addr;
(unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
mmap = (multiboot_memory_map_t *)
((unsigned long) mmap + mmap->size + sizeof(mmap->size))) {
for (mmap = (multiboot_memory_map_t *) mbi->mmap_addr;
(unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
mmap = (multiboot_memory_map_t *)
((unsigned long) mmap + mmap->size + sizeof(mmap->size))) {
if(mmap->type != MULTIBOOT_MEMORY_AVAILABLE) continue;
add_memmap(cbi, mmap->mm_base_addr, mmap->mm_length);
}
@@ -387,16 +378,13 @@ void set_machine_id(char *cmdline)
kinfo_t *pre_init(int argc, char **argv)
{
char *bootargs;
/* This is the main "c" entry point into the kernel. It gets called
from head.S */
/* Clear BSS */
memset(&_edata, 0, (u32_t)&_end - (u32_t)&_edata);
memset(&_kern_unpaged_edata, 0, (u32_t)&_kern_unpaged_end - (u32_t)&_kern_unpaged_edata);
char* bootargs;
/* This is the main "c" entry point into the kernel. It gets called
from head.S */
/* we get called in a c like fashion where the first arg
* is the program name (load address) and the rest are
* is the program name (load address) and the rest are
* arguments. by convention the second argument is the
* command line */
if (argc != 2) {
@@ -405,24 +393,12 @@ kinfo_t *pre_init(int argc, char **argv)
bootargs = argv[1];
set_machine_id(bootargs);
bsp_ser_init();
/* Get our own copy boot params pointed to by ebx.
/* Get our own copy boot params pointed to by r1.
* Here we find out whether we should do serial output.
*/
get_parameters(&kinfo, bootargs);
/* Make and load a pagetable that will map the kernel
* to where it should be; but first a 1:1 mapping so
* this code stays where it should be.
*/
dcache_clean(); /* clean the caches */
pg_clear();
pg_identity(&kinfo);
kinfo.freepde_start = pg_mapkernel();
pg_load();
vm_enable_paging();
/* Done, return boot info so it can be passed to kmain(). */
return &kinfo;
}
@@ -431,10 +407,4 @@ kinfo_t *pre_init(int argc, char **argv)
* ensure this). The following methods are used in that context. Once we jump to kmain they are no
* longer used and the "real" implementations are visible
*/
void send_diag_sig(void) { }
void minix_shutdown(minix_timer_t *t) { arch_shutdown(0); }
void busy_delay_ms(int x) { }
int raise(int n) { panic("raise(%d)\n", n); }
int kern_phys_map_ptr( phys_bytes base_address, vir_bytes io_size, int vm_flags,
struct kern_phys_map * priv, vir_bytes ptr) { return -1; };
struct machine machine; /* pre init stage machine */

View File

@@ -76,6 +76,7 @@ int booting_cpu = 0;
void prot_init(void)
{
/* tell the HW where we stored our vector table */
write_vbar((reg_t)&exc_vector_table);
@@ -84,9 +85,10 @@ void prot_init(void)
* data.
*/
dcache_clean(); /* clean the caches */
pg_clear();
pg_identity(&kinfo); /* Still need 1:1 for device memory . */
pg_mapkernel();
kinfo.freepde_start = pg_mapkernel();
pg_load();
prot_init_done = 1;

View File

@@ -410,9 +410,8 @@ void cstart(void)
*/
register char *value; /* value in key=value pair */
/* low-level initialization */
prot_init();
/* determine verbosity */
if ((value = env_get(VERBOSEBOOTVARNAME)))
verboseboot = atoi(value);

View File

@@ -48,6 +48,7 @@ void fpu_sigcontext(struct proc *, struct sigframe_sigcontext *fr, struct
/* main.c */
#ifndef UNPAGED
#define kmain __k_unpaged_kmain
#define pre_init __k_unpaged_pre_init
#endif
void kmain(kinfo_t *cbi);
void prepare_shutdown(int how);

View File

@@ -129,4 +129,4 @@ echo ""
echo "Disk image at `pwd`/${IMG}"
echo ""
echo "To boot this image on kvm:"
echo "qemu-system-arm -M raspi2 -drive if=sd,cache=writeback,format=raw,file=$(pwd)/${IMG} -bios ${ROOT_DIR}/minix_rpi.bin"
echo "qemu-system-arm -M raspi2 -drive if=sd,cache=writeback,format=raw,file=$(pwd)/${IMG} -bios ${ROOT_DIR}/minix_rpi.bin -serial stdio"

View File

@@ -10,7 +10,7 @@ argv:
argv0:
.asciz "0x00200000"
argv1:
.asciz ""
.asciz "board_name=RPI_2_B console=tty00"
.data
.align 4
.space 256