Change to a higher-half kernel

This commit is contained in:
pjht 2023-03-24 08:09:51 -05:00
parent 62c803b36a
commit 4836f3e5ca
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
6 changed files with 148 additions and 229 deletions

View File

@ -1,5 +1,5 @@
.gitignore
LDFLAGS = -z max-page-size=1
LDFLAGS = -z max-page-size=4096
ASFLAGS = -m68010 --register-prefix-optional
!as = |> m68k-elf-as $(ASFLAGS) -o %o %f |> %B.o

View File

@ -14,7 +14,7 @@ bsr.w find_first_card
move.l #PHDR_BUF_START, a1 | Set the destination address to PHDR_BUF_START
move.l #0x2, d0 | Set the starting sector number to 2
move.l #PHDR_BUF_SEC_SIZE, d1 | Set the sector count
bsr.b read_sectors
bsr.w read_sectors
move.l (PHDR_BUF_START + 0x1C), d0 | Load the offset of the program headers in the file
move.l #PHDR_BUF_START, a1 | Put the address of the program headers in a1
adda.w d0, a1
@ -27,25 +27,29 @@ bne.b next_seg
| Zero the destination memory
move.l (20, a1), d1 | Put the memory size - 1 in d1
subq.l #0x1, d1
move.l (8, a1), a2 | Put the starting memory address in a2
move.l (12, a1), a2 | Put the starting memory address in a2
zero_loop:
move.b #0, (a2)+ | Zero a byte of the destination memory
dbra d1, zero_loop | Loop back if there is more to zero
| Load the segment data off disk
move.l (16, a1), d1 | Put the file size in d1
beq.b next_seg | If the file size is 0, skip the copy (ex, .bss section)
move.l a1,a6 | Save a1 in a6
move.l a1,a5 | Save a1 in a5
move.l d0,d4 | Save d0 in d4
move.l (4, a1), d0 | Put the starting byte number in d0
addi.l #0x400, d0 | Add the 2 sector offset in the disk for the kernel file
move.l (8, a1), a1 | Put the destination memory address in a1
move.l (12, a1), a1 | Put the destination memory address in a1
bsr.b read_bytes
move.l a6,a1 | Restore a1 from a6
move.l a5,a1 | Restore a1 from a5
move.l d4,d0 | Restore d0 from d4
next_seg:
lea (0x20, a1), a1 | Advance a1 to point to the next program header
dbra d0, phead_loop | If there are more program headers, loop back
move.l (PHDR_BUF_START + 0x18), a1 | Load the entry point of the program into a1
move.l (PHDR_BUF_START + 0x1C), d0 | Load the offset of the program headers in the file
move.l #PHDR_BUF_START, a0 | Put the address of the program headers in a0
adda.w d0, a0
move.w (PHDR_BUF_START + 0x2C), d0 | Put the number of program headers in d0
jmp (a1) | Jump to the entry point of the program

View File

@ -1,4 +1,4 @@
symbol_tables = ["boot/boot.elf"]
symbol_tables = ["kernel/kernel.elf"]
[[cards]]
type = "rom"
@ -9,11 +9,11 @@ type = "term"
[[cards]]
type = "ram"
size = 65536
size = 16777216 # 16 MiB
[[cards]]
type = "storage"
image = "os.dsk"
# [[cards]]
# type = "mmu"
[[cards]]
type = "mmu"

View File

@ -1,220 +1,43 @@
/* Script for -z combreloc */
/* Copyright (C) 2014-2022 Free Software Foundation, Inc.
Copying and distribution of this script, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. */
OUTPUT_FORMAT("elf32-m68k", "elf32-m68k",
"elf32-m68k")
OUTPUT_ARCH(m68k)
ENTRY(_start)
SEARCH_DIR("/usr/m68k-elf/lib");
ENTRY (_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x1000)); . = SEGMENT_START("text-segment", 0x1000) + SIZEOF_HEADERS;
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rela.dyn :
{
*(.rela.init)
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.fini)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
*(.rela.ctors)
*(.rela.dtors)
*(.rela.got)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
PROVIDE_HIDDEN (__rela_iplt_start = .);
*(.rela.iplt)
PROVIDE_HIDDEN (__rela_iplt_end = .);
}
.rela.plt :
{
*(.rela.plt)
}
.init :
{
KEEP (*(SORT_NONE(.init)))
} =0x4e714e71
.plt : { *(.plt) }
.iplt : { *(.iplt) }
.text :
{
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(SORT(.text.sorted.*))
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf.em. */
*(.gnu.warning)
} =0x4e714e71
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} =0x4e714e71
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
/* These sections are generated by the Sun/Oracle C++ compiler. */
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
/* Thread Local Storage sections */
.tdata :
{
PROVIDE_HIDDEN (__tdata_start = .);
*(.tdata .tdata.* .gnu.linkonce.td.*)
}
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) }
. = DATA_SEGMENT_RELRO_END (0, .);
.got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
_edata = .; PROVIDE (edata = .);
. = .;
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we do not
pad the .data section. */
. = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
. = SEGMENT_START("ldata-segment", .);
. = ALIGN(32 / 8);
_end = .; PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1. */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions. */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2. */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2. */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions. */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3. */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
/* DWARF 5. */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.debug_sup 0 : { *(.debug_sup) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
. = 0x1000;
/* The kernel will live at 12MB in the virtual address space, */
/* which will be mapped to 0 in the physical address space. */
/* Note that we page-align the sections. */
.early.text ALIGN (4K) : {
*(.early.text)
}
.early.rodata ALIGN (4K) : {
*(.early.rodata)
}
.early.data ALIGN (4K) : {
*(.early.data)
}
.early.bss ALIGN (4K) : {
*(.early.bss)
}
. += 0xC00000;
/* Add a symbol that indicates the start address of the kernel. */
.text ALIGN (4K) : AT (ADDR (.text) - 0xC00000)
{
*(.text)
}
.rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC00000)
{
*(.rodata)
}
.data ALIGN (4K) : AT (ADDR (.data) - 0xC00000)
{
*(.data)
}
.bss ALIGN (4K) : AT (ADDR (.bss) - 0xC00000)
{
*(COMMON)
*(.bss)
}
}

View File

@ -1,5 +1,5 @@
.global _start
_start:
.global main
main:
move.b #'H', 0xFF0200
move.b #'i', 0xFF0200
move.b #0xA, 0xFF0200

92
kernel/start.68k Normal file
View File

@ -0,0 +1,92 @@
.section .early.text, "ax"
.global _start
| Receives pointer to program headers in a0 and number of program headers in d0
_start:
move.l d0, d2
move.l a0, a1
move.b #0x5, d0
bsr.w find_first_card_early
cmpa.l #0, a0
beq.w no_mmu
subq.w #0x1, d2
phead_loop:
move.l (a1), d1 | If the type of the program header isn't 1 (LOAD), skip the header
cmpi.l #0x1, d1
bne.b next_phead
| move.b (9, a1), d1 | If the program header is not in the upper quarter, skip it
| cmpi.b #0xc0, d1
| bgt.b next_phead
move.l (20, a1), d4 | Put the memory size in d4
move.l d4, d3
lsr #8, d3
lsr #4, d3
andi.l #0xFFF, d4
cmp.l #0x0, d4
beq.b even_page
addq.l #1, d3
even_page:
subq.b #1, d3
move.l (12, a1), d1
ori.l #3, d1
move.l (8, a1), d0
lsr.l #8, d0
lsr.l #4, d0
andi.l #0x3ff, d0
lsl #2, d0
move.l #kernel_map, a2
adda d0, a2
| d3 contains number of pages - 1
| d1 initial map entry
| a2 pointer to initial map entry location
map_loop:
move.l d1, (a2)+
addi.l #0x1000, d1
dbra d3, map_loop
next_phead:
lea (0x20, a1), a1 | Advance a1 to point to the next program header
dbra d2, phead_loop | If there are more program headers, loop back
io_map:
move.l #15, d0
move.l #(kernel_map + 0x3f0 * 4), a1
move.l #0xffff0003, d1
io_map_loop:
move.l d1, (a1)+
addi.l #0x1000, d1
dbra d0, io_map_loop
map_done:
move.l #kernel_map, d0
ori.l #0x1, d0
move.l d0, (0x0, a0)
move.l d0, (0xC, a0)
move.w #1, (0x14, a0)
move.w #0, 0xff0000
move.l #bootstrap_stack, a7
jmp main
no_mmu:
stop #2700
| Finds the first card with the type in d0.b, and returns it's IO base address in a0, or 0 if not found
| Clobbers d1
find_first_card_early:
move.l #0xff0000, a0 | a0 holds the address of the current card
ffc_early_loop:
lea (0x100, a0), a0 | Move to the next card
move.b (0xff, a0), d1 | Load the type of the card into d1
beq.b ffc_early_notfound | If the type is 0 (empty slot), we have scanned all cards, so exit the loop
cmp.b d0, d1 | If the card is the type we want, return with the address in a0
beq.b ffc_early_done
bra.b ffc_early_loop | Loop back and check the next card
ffc_early_notfound:
move.l #0x0, a0
ffc_early_done:
rts
.section .early.bss, "aw", @nobits
kernel_map:
.balign 4096
.ds.b 4096
kernel_map_end:
.bss
.ds.b 16384
bootstrap_stack: