Kernel runs in the higher address space
This commit is contained in:
27
kboot/Makefile
Normal file
27
kboot/Makefile
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
DEST=$(O)/kboot
|
||||||
|
OBJS=$(DEST)/main.o $(DEST)/data.o
|
||||||
|
CFLAGS=-mno-sse -mno-mmx -mno-sse2 -mno-3dnow
|
||||||
|
|
||||||
|
$(if $(O),,$(error Specify the target directory))
|
||||||
|
|
||||||
|
$(DEST)/kboot.elf: $(DEST) $(DEST)/kernel.lds $(OBJS)
|
||||||
|
@$(LD) $(LDFLAGS) -o $@ -T $(DEST)/kernel.lds -nostdlib $(OBJS)
|
||||||
|
|
||||||
|
$(DEST)/%.o: %.c
|
||||||
|
@$(CC) $(CFLAGS) -c -o $@ -O3 $<
|
||||||
|
|
||||||
|
$(DEST)/data.o: data.S
|
||||||
|
@$(CC) -c -o $@ -O3 -DKIMAGE='"$(KIMAGE)"' $^
|
||||||
|
|
||||||
|
$(DEST)/kernel.lds: kernel.lds.S
|
||||||
|
$(if $(LOAD_PA),,$(error Specify the loading physical address))
|
||||||
|
@$(CC) -E -P -DLOAD_PA=$(LOAD_PA) -o $@ $<
|
||||||
|
|
||||||
|
$(DEST):
|
||||||
|
@mkdir -p $(DEST)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@$(RM) $(DEST)/*
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
|
||||||
9
kboot/data.S
Normal file
9
kboot/data.S
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef KIMAGE
|
||||||
|
#error "No kernel image is specified"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.data
|
||||||
|
.globl data_start
|
||||||
|
data_start:
|
||||||
|
.incbin KIMAGE
|
||||||
|
|
||||||
34
kboot/kernel.lds.S
Normal file
34
kboot/kernel.lds.S
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
ENTRY(main)
|
||||||
|
PHDRS
|
||||||
|
{
|
||||||
|
text PT_LOAD FLAGS(5);
|
||||||
|
data PT_LOAD FLAGS(7);
|
||||||
|
}
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = LOAD_PA;
|
||||||
|
_head = .;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
*(.text);
|
||||||
|
} : text
|
||||||
|
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.data : {
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
} :data
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata .rodata.*)
|
||||||
|
} :data
|
||||||
|
.bss : {
|
||||||
|
*(.bss .bss.*)
|
||||||
|
}
|
||||||
|
. = ALIGN(4096);
|
||||||
|
data_end = .;
|
||||||
|
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.eh_frame)
|
||||||
|
*(.note.gnu.build-id)
|
||||||
|
}
|
||||||
|
}
|
||||||
132
kboot/main.c
Normal file
132
kboot/main.c
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
#include <elf.h>
|
||||||
|
|
||||||
|
extern char data_start[], data_end[];
|
||||||
|
|
||||||
|
#define LARGE_PAGE_SIZE (1UL << 21)
|
||||||
|
#define LARGE_PAGE_MASK (~((unsigned long)LARGE_PAGE_SIZE - 1))
|
||||||
|
|
||||||
|
#define MAP_ST_START 0xffff800000000000UL
|
||||||
|
#define MAP_KERNEL_START 0xffffffff80000000UL
|
||||||
|
|
||||||
|
#define PTL4_SHIFT 39
|
||||||
|
#define PTL3_SHIFT 30
|
||||||
|
#define PTL2_SHIFT 21
|
||||||
|
|
||||||
|
unsigned long page_tables[3][512] __attribute__((aligned(4096)));
|
||||||
|
|
||||||
|
static void *memcpy(void *dest, void *src, unsigned long len)
|
||||||
|
{
|
||||||
|
char *d = dest, *s = src;
|
||||||
|
|
||||||
|
for ( ; len ; len--) {
|
||||||
|
*(d++) = *(s++);
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
static void *memset(void *dest, int v, unsigned long len)
|
||||||
|
{
|
||||||
|
char *d = dest;
|
||||||
|
|
||||||
|
for ( ; len ; len--) {
|
||||||
|
*(d++) = (char)v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void memzerol(unsigned long *p, unsigned long size)
|
||||||
|
{
|
||||||
|
unsigned long i;
|
||||||
|
|
||||||
|
size /= sizeof(unsigned long);
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
p[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long load_programs(unsigned char *image, Elf64_Phdr *hdrs,
|
||||||
|
int nhdr, unsigned long offset)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned long end = MAP_KERNEL_START;
|
||||||
|
|
||||||
|
for (i = 0; i < nhdr; i++) {
|
||||||
|
if (hdrs[i].p_type == PT_LOAD) {
|
||||||
|
memcpy((void *)(hdrs[i].p_vaddr - offset),
|
||||||
|
image + hdrs[i].p_offset,
|
||||||
|
hdrs[i].p_filesz);
|
||||||
|
if (hdrs[i].p_filesz < hdrs[i].p_memsz) {
|
||||||
|
memset((void *)(hdrs[i].p_vaddr +
|
||||||
|
hdrs[i].p_filesz - offset), 0,
|
||||||
|
hdrs[i].p_memsz - hdrs[i].p_filesz);
|
||||||
|
}
|
||||||
|
if (end < hdrs[i].p_vaddr + hdrs[i].p_memsz) {
|
||||||
|
end = hdrs[i].p_vaddr + hdrs[i].p_memsz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return value: If success, the entry point address. Otherwise, 0.
|
||||||
|
*/
|
||||||
|
unsigned long load_elf(unsigned char *image, unsigned long offset)
|
||||||
|
{
|
||||||
|
Elf64_Ehdr *hdr = (Elf64_Ehdr *)image;
|
||||||
|
|
||||||
|
if (hdr->e_ident[0] != 0x7f || hdr->e_ident[1] != 'E'
|
||||||
|
|| hdr->e_ident[2] != 'L' || hdr->e_ident[3] != 'F') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* TODO: We may overlap. So copying should be more sophisticated */
|
||||||
|
if (!hdr->e_phoff || hdr->e_phentsize != sizeof(Elf64_Phdr)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return load_programs(image,
|
||||||
|
(Elf64_Phdr *)(image + hdr->e_phoff), hdr->e_phnum,
|
||||||
|
offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(unsigned long param)
|
||||||
|
{
|
||||||
|
/* Assume phys == virt */
|
||||||
|
unsigned long load_address, end, *org_cr3;
|
||||||
|
unsigned long i, n;
|
||||||
|
Elf64_Ehdr *hdr;
|
||||||
|
void (*entry)(unsigned long param, unsigned long load_address);
|
||||||
|
|
||||||
|
load_address = (unsigned long)data_end;
|
||||||
|
load_address = (load_address + LARGE_PAGE_SIZE - 1) & LARGE_PAGE_MASK;
|
||||||
|
|
||||||
|
asm volatile("movq %%cr3, %0" : "=r"(org_cr3));
|
||||||
|
|
||||||
|
memzerol((unsigned long *)page_tables, sizeof(page_tables));
|
||||||
|
|
||||||
|
page_tables[0][0] = org_cr3[0];
|
||||||
|
page_tables[0][(MAP_ST_START >> PTL4_SHIFT) & 511] = org_cr3[0];
|
||||||
|
page_tables[0][(MAP_KERNEL_START >> PTL4_SHIFT) & 511] =
|
||||||
|
((unsigned long)page_tables[1]) | 3;
|
||||||
|
page_tables[1][(MAP_KERNEL_START >> PTL3_SHIFT) & 511] =
|
||||||
|
((unsigned long)page_tables[2]) | 3;
|
||||||
|
|
||||||
|
end = load_elf(data_start, MAP_KERNEL_START - load_address);
|
||||||
|
|
||||||
|
/* map 4MB more in case */
|
||||||
|
n = (end - MAP_KERNEL_START + (1 << PTL2_SHIFT) - 1) >> PTL2_SHIFT;
|
||||||
|
n += 2;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
page_tables[2][i] = (load_address + (i << PTL2_SHIFT)) | 0x83;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr = (Elf64_Ehdr *)data_start;
|
||||||
|
|
||||||
|
asm volatile("movq %0, %%cr3" : : "r"(page_tables) : "memory");
|
||||||
|
|
||||||
|
entry = (void *)hdr->e_entry;
|
||||||
|
entry(param, load_address);
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ AALOBJ = aal/aal.o
|
|||||||
SUBCMD_OPTS = TARGET=$(TARGET) O=$(CURDIR)/aal CC=$(CC) LD=$(LD)
|
SUBCMD_OPTS = TARGET=$(TARGET) O=$(CURDIR)/aal CC=$(CC) LD=$(LD)
|
||||||
|
|
||||||
ld_kern_cmd_base = $(LD) $(LDFLAGS) -o $@.elf $^
|
ld_kern_cmd_base = $(LD) $(LDFLAGS) -o $@.elf $^
|
||||||
mkimage_cmd_base = [ -f $(SRC)/scripts/mkimage.$(TARGET) ] && sh $(SRC)/scripts/mkimage.$(TARGET) '$@.elf' '$@' '$(SRC)' || cp $@.elf $@
|
mkimage_cmd_base = [ -f $(SRC)/scripts/mkimage.$(TARGET) ] && CC=$(CC) LD=$(LD) LDFLAGS="$(LDFLAGS_MKIMAGE)" sh $(SRC)/scripts/mkimage.$(TARGET) '$@.elf' '$@' '$(SRC)' || cp $@.elf $@
|
||||||
|
|
||||||
ld_kern_cmd = $(call echo_cmd,LDKERN,$@)$(ld_kern_cmd_base)
|
ld_kern_cmd = $(call echo_cmd,LDKERN,$@)$(ld_kern_cmd_base)
|
||||||
mkimage_cmd = $(call echo_cmd,MKIMAGE,$@)$(mkimage_cmd_base)
|
mkimage_cmd = $(call echo_cmd,MKIMAGE,$@)$(mkimage_cmd_base)
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ static volatile int ap_stop = 1;
|
|||||||
|
|
||||||
void ap_idle(void)
|
void ap_idle(void)
|
||||||
{
|
{
|
||||||
int id = aal_mc_get_hardware_processor_id();
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
cpu_halt();
|
cpu_halt();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ LD = /home/shimosawa/cross.knf/bin/x86_64-l1om-linux-ld
|
|||||||
|
|
||||||
CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow
|
CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow
|
||||||
LDFLAGS += -m elf_l1om -T $(SRC)/knf.lds
|
LDFLAGS += -m elf_l1om -T $(SRC)/knf.lds
|
||||||
|
LDFLAGS_MKIMAGE = -m elf_l1om
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ PHDRS
|
|||||||
}
|
}
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x401000;
|
. = 0xffffffff80001000;
|
||||||
_head = .;
|
_head = .;
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ PHDRS
|
|||||||
}
|
}
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x40001000;
|
. = 0xffffffff80001000;
|
||||||
_head = .;
|
_head = .;
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
|
|||||||
10
kernel/scripts/mkimage.knf
Normal file
10
kernel/scripts/mkimage.knf
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
O=`pwd`
|
||||||
|
|
||||||
|
make -C $3/../kboot O=$O clean
|
||||||
|
make -C $3/../kboot O=$O KIMAGE="$O/$1" LOAD_PA=0x401000 CC=${CC} LD=${LD} LDFLAGS="${LDFLAGS}"
|
||||||
|
|
||||||
|
cp kboot/kboot.elf $2
|
||||||
@@ -1,3 +1,10 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
cat $3/../elfboot/elfboot $1 > $2
|
set -e
|
||||||
|
|
||||||
|
O=`pwd`
|
||||||
|
|
||||||
|
make -C $3/../kboot O=$O clean
|
||||||
|
make -C $3/../kboot O=$O KIMAGE="$O/$1" LOAD_PA=0x3a001000
|
||||||
|
|
||||||
|
cat $3/../elfboot/elfboot kboot/kboot.elf > $2
|
||||||
|
|||||||
Reference in New Issue
Block a user