Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 1057 → Rev 1058

/boot/trunk/arch/ppc32/loader/asm.S
26,6 → 26,7
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
#include "asm.h"
#include "regname.h"
 
.data
35,198 → 36,106
 
.text
 
.global memsetb
.global memcpy
.global flush_instruction_cache
.global halt
.global jump_to_kernel
 
memsetb:
rlwimi r5, r5, 8, 16, 23
rlwimi r5, r5, 16, 0, 15
addi r14, r3, -4
cmplwi 0, r4, 4
blt 7f
stwu r5, 4(r14)
beqlr
andi. r15, r14, 3
add r4, r15, r4
subf r14, r15, r14
srwi r15, r4, 2
mtctr r15
bdz 6f
1:
stwu r5, 4(r14)
bdnz 1b
6:
andi. r4, r4, 3
7:
cmpwi 0, r4, 0
beqlr
mtctr r4
addi r6, r6, 3
8:
stbu r5, 1(r14)
bdnz 8b
blr
halt:
b halt
 
memcpy:
srwi. r7, r5, 3
addi r6, r3, -4
addi r4, r4, -4
beq 2f
andi. r0, r6, 3
mtctr r7
bne 5f
1:
lwz r7, 4(r4)
lwzu r8, 8(r4)
stw r7, 4(r6)
stwu r8, 8(r6)
bdnz 1b
andi. r5, r5, 7
2:
cmplwi 0, r5, 4
blt 3f
lwzu r0, 4(r4)
addi r5, r5, -4
stwu r0, 4(r6)
3:
cmpwi 0, r5, 0
beqlr
mtctr r5
addi r4, r4, 3
addi r6, r6, 3
4:
lbzu r0, 1(r4)
stbu r0, 1(r6)
bdnz 4b
blr
5:
subfic r0, r0, 4
mtctr r0
6:
lbz r7, 4(r4)
addi r4, r4, 1
stb r7, 4(r6)
addi r6, r6, 1
bdnz 6b
subf r5, r0, r5
rlwinm. r7, r5, 32-3, 3, 31
beq 2b
mtctr r7
b 1b
flush_instruction_cache:
 
# Flush data cache
lis r3, flush_buffer@h
ori r3, r3, flush_buffer@l
li r4, L1_CACHE_LINES
mtctr r4
0:
lwz r4, 0(r3)
addi r3, r3, L1_CACHE_BYTES
bdnz 0b
# Invalidate instruction cache
li r3, 0
ori r3, r3, (hid0_ice | hid0_dce | hid0_icfi | hid0_dci)
mfspr r4, hid0
or r5, r4, r3
isync
mtspr hid0, r5
sync
isync
# Enable instruction cache
ori r5, r4, hid0_ice
mtspr hid0, r5
sync
isync
blr
 
jump_to_kernel:
# r3 = kernel_start (va)
# r4 = memmap (pa)
# r5 = real_mode (pa)
# r3 = memmap (pa)
# r4 = trans (pa)
# r5 = number of kernel pages
# r6 = real_mode (pa)
mtspr srr0, r5
mtspr srr0, r6
# jumps to real_mode
mfmsr r5
lis r6, ~0@h
ori r6, r6, ~(msr_ir | msr_dr)@l
and r5, r5, r6
mtspr srr1, r5
mfmsr r31
lis r30, ~0@h
ori r30, r30, ~(msr_ir | msr_dr)@l
and r31, r31, r30
mtspr srr1, r31
rfi
 
.section REALMODE
.align 12
.align PAGE_WIDTH
.global real_mode
 
real_mode:
 
# copy kernel to proper location
#
# r4 = trans (pa)
# r5 = number of kernel pages
li r31, PAGE_SIZE >> 3
li r30, 0
page_copy:
cmpwi r5, 0
beq copy_end
# copy single page
mtctr r31
lwz r29, 0(r4)
copy_loop:
lwz r28, 0(r29)
stw r28, 0(r30)
addi r29, r29, 4
addi r30, r30, 4
bdnz copy_loop
subi r5, r5, 1
addi r4, r4, 4
b page_copy
copy_end:
# fill segment registers
 
li r5, 16
mtctr r5
li r5, 0
li r6, 0
li r31, 16
mtctr r31
li r31, 0
li r30, 0x2000
seg_fill:
mtsrin r6, r5
addis r5, r5, 0x1000 # move to next SR
addis r6, r6, 0x10 # add 256 MB, move to next SR
mtsrin r30, r31
addis r31, r31, 0x1000 # add 256 MB
addi r30, r30, 0x111 # move to next SR
bdnz seg_fill
# bootstrap kernel
# create identity mapping
tlbia
# start the kernel
#
# r3 = kernel_start (va)
# r4 = memmap (pa) -> r10
# r3 = memmap (pa)
mtspr srr0, r3
lis r31, KERNEL_START_ADDR@ha
addi r31, r31, KERNEL_START_ADDR@l
mfmsr r5
ori r5, r5, (msr_ir | msr_dr)@l
mtspr srr1, r5
mtspr srr0, r31
mr r10, r4
mfmsr r31
ori r31, r31, (msr_ir | msr_dr)@l
mtspr srr1, r31
rfi
 
.align PAGE_WIDTH
.global trans
trans:
.space (TRANS_SIZE * TRANS_ITEM_SIZE)
/boot/trunk/arch/ppc32/loader/ofw.h
53,12 → 53,9
 
 
extern void init(void);
extern void halt(void);
 
extern void ofw_write(const char *str, const int len);
 
extern void *ofw_translate(const void *virt);
extern int ofw_map(const void *phys, const void *virt, const int size, const int mode);
extern int ofw_memmap(memmap_t *map);
 
#endif
/boot/trunk/arch/ppc32/loader/regname.h
181,6 → 181,7
#define lr 8
#define ctr 9
#define dec 22
#define sdr1 25
#define srr0 26
#define srr1 27
#define sprg0 272
/boot/trunk/arch/ppc32/loader/main.c
30,44 → 30,57
#include "printf.h"
#include "asm.h"
 
#define KERNEL_PHYSICAL_ADDRESS 0x0000
#define KERNEL_VIRTUAL_ADDRESS 0x80000000
#define KERNEL_BOOT_OFFSET 0x2000
#define KERNEL_START &_binary_____________kernel_kernel_bin_start
#define KERNEL_END &_binary_____________kernel_kernel_bin_end
#define KERNEL_START ((void *) &_binary_____________kernel_kernel_bin_start)
#define KERNEL_END ((void *) &_binary_____________kernel_kernel_bin_end)
#define KERNEL_SIZE ((unsigned int) KERNEL_END - (unsigned int) KERNEL_START)
 
memmap_t memmap;
 
 
static void check_align(const void *addr, const char *desc)
{
if ((unsigned int) addr % PAGE_SIZE != 0) {
printf("Error: %s not on page boundary\n", desc);
halt();
}
}
 
 
void bootstrap(void)
{
printf("\nHelenOS PPC Bootloader\n");
void *phys = ofw_translate(&start);
printf("loaded at %L (physical %L)\n", &start, phys);
check_align(KERNEL_START, "Kernel image");
check_align(&real_mode, "Bootstrap trampoline");
check_align(&trans, "Translation table");
void *real_mode_pa = ofw_translate(&real_mode);
void *trans_pa = ofw_translate(&trans);
void *memmap_pa = ofw_translate(&memmap);
printf("Memory statistics\n");
printf(" kernel image at %L (size %d bytes)\n", KERNEL_START, KERNEL_SIZE);
printf(" memory map at %L (physical %L)\n", &memmap, memmap_pa);
printf(" bootstrap trampoline at %L (physical %L)\n", &real_mode, real_mode_pa);
printf(" translation table at %L (physical %L)\n", &trans, trans_pa);
if (!ofw_memmap(&memmap)) {
printf("Unable to get memory map\n");
halt();
}
printf("total memory %d MB\n", memmap.total >> 20);
printf("Total memory %d MB\n", memmap.total >> 20);
if (ofw_map((void *) KERNEL_PHYSICAL_ADDRESS, (void *) KERNEL_VIRTUAL_ADDRESS, KERNEL_SIZE + KERNEL_BOOT_OFFSET, 0) != 0) {
printf("Unable to map kernel memory at %L (physical %L)\n", KERNEL_VIRTUAL_ADDRESS, KERNEL_PHYSICAL_ADDRESS);
halt();
unsigned int addr;
unsigned int pages;
for (addr = 0, pages = 0; addr < KERNEL_SIZE; addr += PAGE_SIZE, pages++) {
void *pa = ofw_translate(KERNEL_START + addr);
if ((unsigned int) pa < KERNEL_SIZE) {
printf("Error: Kernel image overlaps kernel physical area\n");
halt();
}
trans[addr >> PAGE_WIDTH] = pa;
}
printf("kernel memory mapped at %L (physical %L, size %d bytes)\n", KERNEL_VIRTUAL_ADDRESS, KERNEL_PHYSICAL_ADDRESS, KERNEL_SIZE);
// FIXME: relocate the kernel in real mode
memcpy((void *) KERNEL_VIRTUAL_ADDRESS, KERNEL_START, KERNEL_SIZE);
// FIXME: proper hardware detection & mapping
ofw_map((void *) 0x84000000, (void *) 0xf0000000, 0x01000000, 0);
ofw_map((void *) 0x80816000, (void *) 0xf2000000, 0x00018000, 0);
void *tramp = ofw_translate(&real_mode);
printf("bootstrap trampoline at %L (physical %L)\n", &real_mode, tramp);
printf("Booting the kernel...\n");
flush_instruction_cache();
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS + KERNEL_BOOT_OFFSET, ofw_translate(&memmap), tramp);
jump_to_kernel(memmap_pa, trans_pa, pages, real_mode_pa);
}
/boot/trunk/arch/ppc32/loader/asm.h
29,10 → 29,22
#ifndef __ASM_H__
#define __ASM_H__
 
void flush_instruction_cache(void);
void jump_to_kernel(void *code, void *memmap, void *real_mode) __attribute__((noreturn));
void real_mode(void *code, void *memmap);
#define PAGE_SIZE 4096
#define PAGE_WIDTH 12
 
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt))
#define TRANS_SIZE 1024
#define TRANS_ITEM_SIZE 4
 
#define KERNEL_START_ADDR 0x80002000
 
#ifndef __ASM__
 
extern void *trans[TRANS_SIZE];
 
extern void halt();
extern void jump_to_kernel(void *memmap, void *trans, unsigned int cnt, void *real_mode) __attribute__((noreturn));
extern void real_mode();
 
#endif
 
#endif
/boot/trunk/arch/ppc32/loader/_link.ld
7,9 → 7,9
ENTRY(start)
 
SECTIONS {
.image 0x10000000: AT (0) {
*(BOOTSTRAP)
*(REALMODE)
.boot 0x10000000: AT (0) {
*(BOOTSTRAP);
*(REALMODE);
*(.text);
*(.rodata);
21,4 → 21,8
*(.bss); /* uninitialized static variables */
*(COMMON); /* global variables */
}
.image 0x10000000+SIZEOF(.boot): AT (SIZEOF(.boot)) SUBALIGN(4096) {
*(.image);
}
}
/boot/trunk/arch/ppc32/loader/ofw.c
27,6 → 27,7
*/
#include "ofw.h"
#include "asm.h"
#include "printf.h"
 
#define MAX_OFW_ARGS 10
113,12 → 114,6
}
 
 
void halt(void)
{
ofw_call("exit", 0, 0);
}
 
 
void ofw_write(const char *str, const int len)
{
if (ofw_stdout == 0)
134,12 → 129,6
}
 
 
int ofw_map(const void *phys, const void *virt, const int size, const int mode)
{
return ofw_call("call-method", 6, 1, "map", ofw_mmu, mode, size, virt, phys);
}
 
 
int ofw_memmap(memmap_t *map)
{
int i;
/boot/trunk/arch/ppc32/loader/Makefile
65,7 → 65,7
-include Makefile.depend
 
image.boot: depend $(OBJECTS) kernel.o
$(LD) -no-check-sections -N -T _link.ld -Map map $(OBJECTS) kernel.o -o $@
$(LD) -no-check-sections -N -T _link.ld $(OBJECTS) kernel.o -o $@
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
74,7 → 74,7
-rm -f $(OBJECTS) image.boot kernel.o Makefile.depend
 
kernel.o: $(KERNEL)
$(OBJCOPY) -I binary -O elf32-powerpc -B powerpc $(KERNEL) $@
$(OBJCOPY) -I binary -O elf32-powerpc -B powerpc --rename-section .data=.image $(KERNEL) $@
 
%.o: %.S
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@