Buildable skeleton for ARM64 architecture specific code.
This commit is contained in:
parent
3cf6f55b95
commit
ae669bfa83
18
SConstruct
18
SConstruct
@ -20,7 +20,7 @@ opts.AddVariables(
|
|||||||
("NUMCPUS", "Number of CPUs to use for build (0 means auto).", "0"),
|
("NUMCPUS", "Number of CPUs to use for build (0 means auto).", "0"),
|
||||||
("WITH_GPROF", "Include gprof profiling (0 or 1).", "0"),
|
("WITH_GPROF", "Include gprof profiling (0 or 1).", "0"),
|
||||||
("PREFIX", "Installation target directory.", "#pxelinux"),
|
("PREFIX", "Installation target directory.", "#pxelinux"),
|
||||||
("ARCH", "Target Architecture", "amd64"),
|
("ARCH", "Target Architecture", "arm64"),
|
||||||
("BOOTDISK", "Build boot disk (0 or 1)", "1"),
|
("BOOTDISK", "Build boot disk (0 or 1)", "1"),
|
||||||
("BOOTDISK_SIZE", "Boot disk size", "128")
|
("BOOTDISK_SIZE", "Boot disk size", "128")
|
||||||
)
|
)
|
||||||
@ -51,8 +51,16 @@ if 'LDFLAGS' in os.environ:
|
|||||||
toolenv = env.Clone()
|
toolenv = env.Clone()
|
||||||
|
|
||||||
env.Append(CFLAGS = [ "-Wshadow", "-Wno-typedef-redefinition" ])
|
env.Append(CFLAGS = [ "-Wshadow", "-Wno-typedef-redefinition" ])
|
||||||
env.Append(CPPFLAGS = [ "-target", "x86_64-freebsd-freebsd-elf",
|
|
||||||
"-fno-builtin", "-fno-stack-protector",
|
if env["ARCH"] == "amd64":
|
||||||
|
env.Append(CPPFLAGS = [ "-target", "x86_64-freebsd-freebsd-elf" ])
|
||||||
|
elif env["ARCH"] == "arm64":
|
||||||
|
env.Append(CPPFLAGS = [ "-target", "arm64-freebsd-freebsd-elf" ])
|
||||||
|
else:
|
||||||
|
print("Unsupported architecture: " + env["ARCH"])
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
env.Append(CPPFLAGS = [ "-fno-builtin", "-fno-stack-protector",
|
||||||
"-fno-optimize-sibling-calls" ])
|
"-fno-optimize-sibling-calls" ])
|
||||||
#env.Append(LINKFLAGS = [ "-no-pie" ])
|
#env.Append(LINKFLAGS = [ "-no-pie" ])
|
||||||
|
|
||||||
@ -78,10 +86,6 @@ else:
|
|||||||
print("Error BUILDTYPE must be RELEASE or DEBUG")
|
print("Error BUILDTYPE must be RELEASE or DEBUG")
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
if env["ARCH"] != "amd64":
|
|
||||||
print("Unsupported architecture: " + env["ARCH"])
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hf = open(".git/HEAD", 'r')
|
hf = open(".git/HEAD", 'r')
|
||||||
head = hf.read()
|
head = hf.read()
|
||||||
|
47
lib/libc/arm64/crti.S
Normal file
47
lib/libc/arm64/crti.S
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright 2001 David E. O'Brien
|
||||||
|
* Copyright 2014 The FreeBSD Foundation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Portions of this software were developed by Andrew Turner
|
||||||
|
* under sponsorship from the FreeBSD Foundation.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <machine/asm.h>
|
||||||
|
|
||||||
|
.section .init,"ax",@progbits
|
||||||
|
.align 4
|
||||||
|
.globl _init
|
||||||
|
.type _init,@function
|
||||||
|
_init:
|
||||||
|
sub sp, sp, #16
|
||||||
|
str lr, [sp]
|
||||||
|
|
||||||
|
.section .fini,"ax",@progbits
|
||||||
|
.align 4
|
||||||
|
.globl _fini
|
||||||
|
.type _fini,@function
|
||||||
|
_fini:
|
||||||
|
sub sp, sp, #16
|
||||||
|
str lr, [sp]
|
||||||
|
|
43
lib/libc/arm64/crtn.S
Normal file
43
lib/libc/arm64/crtn.S
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright 2001 David E. O'Brien
|
||||||
|
* Copyright 2014 The FreeBSD Foundation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Portions of this software were developed by Andrew Turner
|
||||||
|
* under sponsorship from the FreeBSD Foundation.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <machine/asm.h>
|
||||||
|
|
||||||
|
.section .init,"ax",@progbits
|
||||||
|
ldr lr, [sp]
|
||||||
|
add sp, sp, #16
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.section .fini,"ax",@progbits
|
||||||
|
ldr lr, [sp]
|
||||||
|
add sp, sp, #16
|
||||||
|
ret
|
||||||
|
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
13
lib/libc/arm64/syscall.S
Normal file
13
lib/libc/arm64/syscall.S
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* System Call
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <machine/asm.h>
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
FUNC_BEGIN(syscall)
|
||||||
|
svc 0
|
||||||
|
ret
|
||||||
|
FUNC_END(syscall)
|
||||||
|
|
@ -22,6 +22,11 @@ getpagesizes(size_t *pagesize, int nelem)
|
|||||||
return (nelem > 3 ? 3 : nelem);
|
return (nelem > 3 ? 3 : nelem);
|
||||||
}
|
}
|
||||||
return 3;
|
return 3;
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
if (pagesize) {
|
||||||
|
pagesize[0] = PGSIZE;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
#else
|
#else
|
||||||
#error "Unsupported Architecture!"
|
#error "Unsupported Architecture!"
|
||||||
#endif
|
#endif
|
||||||
|
@ -36,6 +36,27 @@ src_amd64 = [
|
|||||||
"dev/x86/vgacons.c",
|
"dev/x86/vgacons.c",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
src_arm64 = [
|
||||||
|
# Multiboot requires multiboot.S to be the first file
|
||||||
|
"arm64/multiboot.S",
|
||||||
|
"arm64/mbentry.c",
|
||||||
|
# AMD64
|
||||||
|
"arm64/debug.c",
|
||||||
|
"arm64/disasm.c",
|
||||||
|
"arm64/irq.c",
|
||||||
|
"arm64/machine.c",
|
||||||
|
"arm64/mp.c",
|
||||||
|
"arm64/pci.c",
|
||||||
|
"arm64/pmap.c",
|
||||||
|
"arm64/support.S",
|
||||||
|
"arm64/switch.S",
|
||||||
|
"arm64/thread.c",
|
||||||
|
"arm64/time.c",
|
||||||
|
"arm64/trap.c",
|
||||||
|
"arm64/trapentry.S",
|
||||||
|
# Devices
|
||||||
|
]
|
||||||
|
|
||||||
src_common = [
|
src_common = [
|
||||||
"kern/copy.c",
|
"kern/copy.c",
|
||||||
"kern/critical.c",
|
"kern/critical.c",
|
||||||
@ -75,14 +96,22 @@ src_common = [
|
|||||||
if (env["ARCH"] == "amd64"):
|
if (env["ARCH"] == "amd64"):
|
||||||
src.append(src_amd64)
|
src.append(src_amd64)
|
||||||
ldscript = "#sys/amd64/kernel.lds"
|
ldscript = "#sys/amd64/kernel.lds"
|
||||||
|
elif (env["ARCH"] == "arm64"):
|
||||||
|
src.append(src_arm64)
|
||||||
|
ldscript = "#sys/arm64/kernel.lds"
|
||||||
src.append(src_common)
|
src.append(src_common)
|
||||||
|
|
||||||
kern_env.Append(LINKFLAGS = ['-T', ldscript[1:], '-nostdlib'])
|
kern_env.Append(LINKFLAGS = ['-T', ldscript[1:], '-nostdlib'])
|
||||||
kern_env.Append(CPPFLAGS = ['-D_KERNEL'])
|
kern_env.Append(CPPFLAGS = ['-D_KERNEL'])
|
||||||
kern_env.Append(CPPFLAGS = ['-ffreestanding', '-fno-builtin', '-nostdinc',
|
kern_env.Append(CPPFLAGS = ['-ffreestanding', '-fno-builtin', '-nostdinc',
|
||||||
'-mno-red-zone', '-mno-mmx', '-mno-sse',
|
'-mno-red-zone'])
|
||||||
'-mcmodel=large'])
|
|
||||||
# '-target', 'amd64-orion-eabi'
|
if env["ARCH"] == "amd64":
|
||||||
|
kern_env.Append(CPPFLAGS = ['-mno-mmx', '-mno-sse', '-mcmodel=large'])
|
||||||
|
# '-target', 'amd64-orion-eabi'
|
||||||
|
elif env["ARCH"] == "arm64":
|
||||||
|
kern_env.Append(CPPFLAGS = ['-mcmodel=large'])
|
||||||
|
|
||||||
kern_env.Append(CPPPATH = ['#build/include'])
|
kern_env.Append(CPPPATH = ['#build/include'])
|
||||||
|
|
||||||
kernel = kern_env.Program("castor", src)
|
kernel = kern_env.Program("castor", src)
|
||||||
|
181
sys/arm64/debug.c
Normal file
181
sys/arm64/debug.c
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <sys/kassert.h>
|
||||||
|
#include <sys/kconfig.h>
|
||||||
|
#include <sys/kdebug.h>
|
||||||
|
#include <sys/mp.h>
|
||||||
|
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <machine/cpuop.h>
|
||||||
|
#include <machine/atomic.h>
|
||||||
|
#include <machine/trap.h>
|
||||||
|
#include <machine/mp.h>
|
||||||
|
|
||||||
|
TrapFrame *frames[MAX_CPUS];
|
||||||
|
|
||||||
|
volatile static uint64_t debugLock = 0;
|
||||||
|
volatile static uint64_t debugCmd = 0;
|
||||||
|
volatile static uint64_t debugHalted = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
Debug_HaltCPUs()
|
||||||
|
{
|
||||||
|
debugCmd = 0;
|
||||||
|
|
||||||
|
//if (MP_GetCPUs() == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//LAPIC_BroadcastNMI(T_DEBUGIPI);
|
||||||
|
|
||||||
|
// Wait for processors to enter
|
||||||
|
/*while (debugHalted < (MP_GetCPUs() - 1)) {
|
||||||
|
pause();
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Debug_ResumeCPUs()
|
||||||
|
{
|
||||||
|
debugCmd = 1;
|
||||||
|
|
||||||
|
// Wait for processors to resume
|
||||||
|
while (debugHalted > 0) {
|
||||||
|
pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Debug_HaltIPI(TrapFrame *tf)
|
||||||
|
{
|
||||||
|
MP_SetState(CPUSTATE_HALTED);
|
||||||
|
__sync_fetch_and_add(&debugHalted, 1);
|
||||||
|
|
||||||
|
frames[CPU()] = tf;
|
||||||
|
|
||||||
|
while (debugCmd == 0) {
|
||||||
|
pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
__sync_fetch_and_sub(&debugHalted, 1);
|
||||||
|
MP_SetState(CPUSTATE_BOOTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Debug_Breakpoint(TrapFrame *tf)
|
||||||
|
{
|
||||||
|
frames[CPU()] = tf;
|
||||||
|
|
||||||
|
// Should probably force all cores into the debugger
|
||||||
|
while(atomic_swap_uint64(&debugLock, 1) == 1) {
|
||||||
|
// Wait to acquire debugger lock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop all processors
|
||||||
|
Debug_HaltCPUs();
|
||||||
|
|
||||||
|
// Enter prompt
|
||||||
|
Debug_Prompt();
|
||||||
|
|
||||||
|
// Resume all processors
|
||||||
|
Debug_ResumeCPUs();
|
||||||
|
atomic_set_uint64(&debugLock, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_Registers(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
TrapFrame *tf = frames[CPU()];
|
||||||
|
|
||||||
|
if (argc == 2) {
|
||||||
|
int cpuNo = Debug_StrToInt(argv[1]);
|
||||||
|
if (cpuNo >= MAX_CPUS) {
|
||||||
|
kprintf("Invalid CPU number\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tf = frames[cpuNo];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(registers, "Show CPU registers", Debug_Registers);
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_Backtrace(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
TrapFrame *tf = frames[CPU()];
|
||||||
|
uint64_t *ptr;
|
||||||
|
uint64_t rip;
|
||||||
|
uint64_t rbp;
|
||||||
|
|
||||||
|
if (argc == 2) {
|
||||||
|
int cpuNo = Debug_StrToInt(argv[1]);
|
||||||
|
if (cpuNo >= MAX_CPUS) {
|
||||||
|
kprintf("Invalid CPU number\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tf = frames[cpuNo];
|
||||||
|
}
|
||||||
|
|
||||||
|
rip = 0; //tf->rip;
|
||||||
|
rbp = 0; //tf->rbp;
|
||||||
|
|
||||||
|
kprintf("%-16s %-16s\n", "IP Pointer", "Base Pointer");
|
||||||
|
while (3) {
|
||||||
|
kprintf("%016llx %016llx\n", rip, rbp);
|
||||||
|
ptr = (uint64_t *)rbp;
|
||||||
|
if (rbp == 0ULL || rip == 0ULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rbp = ptr[0];
|
||||||
|
rip = ptr[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(backtrace, "Print backtrace", Debug_Backtrace);
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_SetBreakpoint(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
kprintf("bkpt [ADDR]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t addr = Debug_StrToInt(argv[1]);
|
||||||
|
|
||||||
|
kprintf("NOT IMPLEMENTED\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(bkpt, "Set breakpoint", Debug_SetBreakpoint);
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_ClearBreakpoint(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
kprintf("clrbkpt [0-3]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
kprintf("NOT IMPLEMENTED\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(clrbkpt, "Clear breakpoint", Debug_ClearBreakpoint);
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_ListBreakpoints(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
kprintf("NOT IMPLEMENTED\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(bkpts, "List breakpoint", Debug_ListBreakpoints);
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_Reboot(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
kprintf("NOT IMPLEMENTED\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(reboot, "Reboot computer", Debug_Reboot);
|
||||||
|
|
1627
sys/arm64/disasm.c
Normal file
1627
sys/arm64/disasm.c
Normal file
File diff suppressed because it is too large
Load Diff
10
sys/arm64/include/asm.h
Normal file
10
sys/arm64/include/asm.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Assembly Macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FUNC_BEGIN(fname) .p2align 4, 0x90; .global fname; \
|
||||||
|
.type fname, @function; \
|
||||||
|
fname:
|
||||||
|
|
||||||
|
#define FUNC_END(fname) .size fname, . - fname
|
||||||
|
|
38
sys/arm64/include/atomic.h
Normal file
38
sys/arm64/include/atomic.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
#ifndef __ATOMIC_H__
|
||||||
|
#define __ATOMIC_H__
|
||||||
|
|
||||||
|
static INLINE uint64_t
|
||||||
|
atomic_swap_uint32(volatile uint32_t *dst, uint32_t newval)
|
||||||
|
{
|
||||||
|
uint32_t retval;
|
||||||
|
|
||||||
|
asm volatile(".arch_extension lse; swp %w2, %w0, [%w1]; .arch_extension nolse;"
|
||||||
|
: "=r" (retval)
|
||||||
|
: "r" (dst), "r" (newval)
|
||||||
|
: "memory");
|
||||||
|
|
||||||
|
return newval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE uint64_t
|
||||||
|
atomic_swap_uint64(volatile uint64_t *dst, uint64_t newval)
|
||||||
|
{
|
||||||
|
uint64_t retval;
|
||||||
|
|
||||||
|
asm volatile(".arch_extension lse; swp %2, %0, [%1]; .arch_extension nolse;"
|
||||||
|
: "=r" (retval)
|
||||||
|
: "r" (dst), "r" (newval)
|
||||||
|
: "memory");
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
atomic_set_uint64(volatile uint64_t *dst, uint64_t newval)
|
||||||
|
{
|
||||||
|
*dst = newval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __ATOMIC_H__ */
|
||||||
|
|
46
sys/arm64/include/cpu.h
Normal file
46
sys/arm64/include/cpu.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2018 Ali Mashtizadeh
|
||||||
|
* All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AMD64_H__
|
||||||
|
#define __AMD64_H__
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Page Tables
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PGNUMMASK 0xFFFFFFFFFFFFF000ULL
|
||||||
|
|
||||||
|
#define PGIDXSHIFT 9
|
||||||
|
#define PGIDXMASK (512 - 1)
|
||||||
|
|
||||||
|
#define PGSHIFT 12
|
||||||
|
#define PGSIZE (1 << PGSHIFT)
|
||||||
|
#define PGMASK (PGSIZE - 1)
|
||||||
|
|
||||||
|
#define LARGE_PGSHIFT 21
|
||||||
|
#define LARGE_PGSIZE (1 << LARGE_PGSHIFT)
|
||||||
|
#define LARGE_PGMASK (LARGE_PGSIZE - 1)
|
||||||
|
|
||||||
|
#define HUGE_PGSHIFT 30
|
||||||
|
#define HUGE_PGSIZE (1 << HUGE_PGSHIFT)
|
||||||
|
#define HUGE_PGMASK (HUGE_PGSIZE - 1)
|
||||||
|
|
||||||
|
#define ROUNDUP_PGSIZE(x) (((x) + LARGE_PGSIZE - 1) & ~LARGE_PGMASK)
|
||||||
|
#define ROUNDDOWN_PGSIZE(x) ((x) & ~LARGE_PGMASK)
|
||||||
|
|
||||||
|
#define PAGETABLE_ENTRIES 512
|
||||||
|
|
||||||
|
typedef uint64_t PageEntry;
|
||||||
|
|
||||||
|
typedef struct PageTable {
|
||||||
|
PageEntry entries[PAGETABLE_ENTRIES];
|
||||||
|
} PageTable;
|
||||||
|
|
||||||
|
#include "cpuop.h"
|
||||||
|
|
||||||
|
#endif /* __AMD64_H__ */
|
||||||
|
|
35
sys/arm64/include/cpuop.h
Normal file
35
sys/arm64/include/cpuop.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2023 Ali Mashtizadeh
|
||||||
|
* All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARM64OP_H__
|
||||||
|
#define __ARM64OP_H__
|
||||||
|
|
||||||
|
static INLINE void enable_interrupts()
|
||||||
|
{
|
||||||
|
asm volatile("msr daifclr, #(0x0002)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void disable_interrupts()
|
||||||
|
{
|
||||||
|
asm volatile("msr daifset, #(0x0002)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void hlt()
|
||||||
|
{
|
||||||
|
asm volatile("");
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void pause()
|
||||||
|
{
|
||||||
|
asm volatile("");
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void breakpoint()
|
||||||
|
{
|
||||||
|
asm volatile("brk #0");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __ARM64OP_H__ */
|
||||||
|
|
13
sys/arm64/include/ioapic.h
Normal file
13
sys/arm64/include/ioapic.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* IOAPIC Header
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __IOAPIC_H__
|
||||||
|
#define __IOAPIC_H__
|
||||||
|
|
||||||
|
void IOAPIC_Init();
|
||||||
|
void IOAPIC_Enable(int irq);
|
||||||
|
void IOAPIC_Disable(int irq);
|
||||||
|
|
||||||
|
#endif /* __IOAPIC_H__ */
|
||||||
|
|
23
sys/arm64/include/mp.h
Normal file
23
sys/arm64/include/mp.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
#ifndef __MACHINE_MP_H__
|
||||||
|
#define __MACHINE_MP_H__
|
||||||
|
|
||||||
|
#define CPUSTATE_NOT_PRESENT 0
|
||||||
|
#define CPUSTATE_BOOTED 1
|
||||||
|
#define CPUSTATE_HALTED 2
|
||||||
|
#define CPUSTATE_MAX 2
|
||||||
|
|
||||||
|
void MP_Init();
|
||||||
|
void MP_InitAP();
|
||||||
|
void MP_SetState(int state);
|
||||||
|
int MP_GetCPUs();
|
||||||
|
|
||||||
|
/* Cross Calls */
|
||||||
|
typedef int (*CrossCallCB)(void *);
|
||||||
|
void MP_CrossCallTrap();
|
||||||
|
int MP_CrossCall(CrossCallCB cb, void *arg);
|
||||||
|
|
||||||
|
uint32_t LAPIC_CPU();
|
||||||
|
|
||||||
|
#endif /* __MACHINE_MP__ */
|
||||||
|
|
81
sys/arm64/include/pmap.h
Normal file
81
sys/arm64/include/pmap.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
|
||||||
|
#ifndef __PMAP_H__
|
||||||
|
#define __PMAP_H__
|
||||||
|
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* +----------------------+
|
||||||
|
* | Zero Page (Unmapped) |
|
||||||
|
* +----------------------+ 0x00000000_00000100 User Space Start
|
||||||
|
* | |
|
||||||
|
* | User Space |
|
||||||
|
* .
|
||||||
|
* .
|
||||||
|
* .
|
||||||
|
* | |
|
||||||
|
* +----------------------+ 0x00008000_00000000 User Space End
|
||||||
|
* | |
|
||||||
|
* | Non-canonical |
|
||||||
|
* .
|
||||||
|
* .
|
||||||
|
* .
|
||||||
|
* | |
|
||||||
|
* +----------------------+ 0xFFFF8000_00000000 Direct Map
|
||||||
|
* | Direct Map |
|
||||||
|
* +----------------------+ 0xFFFF8100_00000000 XMap Start
|
||||||
|
* | XMap |
|
||||||
|
* +----------------------+ 0xFFFF8120_00000000 XMap Top
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define MEM_USERSPACE_BASE 0x0000000000000000ULL
|
||||||
|
#define MEM_USERSPACE_LEN 0x0000800000000000ULL
|
||||||
|
#define MEM_USERSPACE_TOP (MEM_USERSPACE_BASE + MEM_USERSPACE_LEN)
|
||||||
|
|
||||||
|
#define MEM_USERSPACE_STKBASE 0x0000000070000000ULL
|
||||||
|
#define MEM_USERSPACE_STKLEN 0x0000000000010000ULL
|
||||||
|
#define MEM_USERSPACE_STKTOP (MEM_USERSPACE_STKBASE + MEM_USERSPACE_STKLEN)
|
||||||
|
|
||||||
|
#define MEM_DIRECTMAP_BASE 0xFFFF800000000000ULL
|
||||||
|
#define MEM_DIRECTMAP_LEN 0x0000010000000000ULL
|
||||||
|
#define MEM_XMAP_BASE 0xFFFF810000000000ULL
|
||||||
|
#define MEM_XMAP_LEN 0x0000002000000000ULL
|
||||||
|
|
||||||
|
#define PPN2DMVA(ppn) (((ppn) << PGSIZE) + MEM_DIRECTMAP_BASE)
|
||||||
|
#define DMVA2PPN(dmva) (((dmva) - MEM_DIRECTMAP_BASE) >> PGSIZE)
|
||||||
|
#define DMVA2PA(dmva) ((dmva) - MEM_DIRECTMAP_BASE)
|
||||||
|
#define DMPA2VA(pa) ((pa) + MEM_DIRECTMAP_BASE)
|
||||||
|
#define VA2PA(va) PMap_Translate(PMap_CurrentAS(), va)
|
||||||
|
|
||||||
|
typedef struct AS
|
||||||
|
{
|
||||||
|
PageTable *root;
|
||||||
|
uint64_t tables;
|
||||||
|
uint64_t mappings;
|
||||||
|
} AS;
|
||||||
|
|
||||||
|
void PMap_Init();
|
||||||
|
void PMap_InitAP();
|
||||||
|
|
||||||
|
AS* PMap_NewAS();
|
||||||
|
void PMap_DestroyAS(AS *space);
|
||||||
|
AS* PMap_CurrentAS();
|
||||||
|
void PMap_LoadAS(AS *space);
|
||||||
|
void PMap_Dump(AS *space);
|
||||||
|
|
||||||
|
uintptr_t PMap_Translate(AS *space, uintptr_t va);
|
||||||
|
|
||||||
|
// Manipulate User Memory
|
||||||
|
bool PMap_Map(AS *as, uint64_t phys, uint64_t virt, uint64_t pages, uint64_t flags);
|
||||||
|
bool PMap_AllocMap(AS *as, uint64_t virt, uint64_t len, uint64_t flags);
|
||||||
|
bool PMap_Unmap(AS *as, uint64_t virt, uint64_t pages);
|
||||||
|
|
||||||
|
// Manipulate Kernel Memory
|
||||||
|
void PMap_SystemLookup(uint64_t va, PageEntry **entry, int size);
|
||||||
|
bool PMap_SystemLMap(uint64_t phys, uint64_t virt, uint64_t lpages, uint64_t flags);
|
||||||
|
bool PMap_SystemMap(uint64_t phys, uint64_t virt, uint64_t pages, uint64_t flags);
|
||||||
|
bool PMap_SystemUnmap(uint64_t virt, uint64_t pages);
|
||||||
|
|
||||||
|
#endif /* __PMAP_H__ */
|
||||||
|
|
17
sys/arm64/include/thread.h
Normal file
17
sys/arm64/include/thread.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
#ifndef __MACHINE_THREAD_H__
|
||||||
|
#define __MACHINE_THREAD_H__
|
||||||
|
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <machine/cpuop.h>
|
||||||
|
|
||||||
|
typedef struct ThreadArchStackFrame {
|
||||||
|
} ThreadArchStackFrame;
|
||||||
|
|
||||||
|
typedef struct ThreadArch {
|
||||||
|
bool useFP;
|
||||||
|
uint64_t rsp;
|
||||||
|
} ThreadArch;
|
||||||
|
|
||||||
|
#endif /* __MACHINE_THREAD_H__ */
|
||||||
|
|
91
sys/arm64/include/trap.h
Normal file
91
sys/arm64/include/trap.h
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
#ifndef __TRAP_H__
|
||||||
|
#define __TRAP_H__
|
||||||
|
|
||||||
|
#define T_DE 0 /* Divide Error Exception */
|
||||||
|
#define T_DB 1 /* Debug Exception */
|
||||||
|
#define T_NMI 2 /* NMI Interrupt */
|
||||||
|
#define T_BP 3 /* Breakpoint Exception */
|
||||||
|
#define T_OF 4 /* Overflow Exception */
|
||||||
|
#define T_BR 5 /* BOUND Range Exceeded Exception */
|
||||||
|
#define T_UD 6 /* Invalid Opcode Exception */
|
||||||
|
#define T_NM 7 /* Device Not Available Exception */
|
||||||
|
#define T_DF 8 /* Double Fault Exception */
|
||||||
|
#define T_TS 10 /* Invalid TSS Exception */
|
||||||
|
#define T_NP 11 /* Segment Not Present */
|
||||||
|
#define T_SS 12 /* Stack Fault Exception */
|
||||||
|
#define T_GP 13 /* General Protection Exception */
|
||||||
|
#define T_PF 14 /* Page-Fault Exception */
|
||||||
|
#define T_MF 16 /* x87 FPU Floating-Point Error */
|
||||||
|
#define T_AC 17 /* Alignment Check Exception */
|
||||||
|
#define T_MC 18 /* Machine-Check Exception */
|
||||||
|
#define T_XF 19 /* SIMB Floating-Point Exception */
|
||||||
|
#define T_VE 20 /* Virtualization Exception */
|
||||||
|
|
||||||
|
#define T_CPU_LAST T_VE
|
||||||
|
|
||||||
|
// IRQs
|
||||||
|
#define T_IRQ_BASE 32
|
||||||
|
#define T_IRQ_LEN 24
|
||||||
|
#define T_IRQ_MAX (T_IRQ_BASE + T_IRQ_LEN - 1)
|
||||||
|
|
||||||
|
#define T_IRQ_TIMER (T_IRQ_BASE + 0)
|
||||||
|
#define T_IRQ_KBD (T_IRQ_BASE + 1)
|
||||||
|
#define T_IRQ_COM1 (T_IRQ_BASE + 4)
|
||||||
|
#define T_IRQ_MOUSE (T_IRQ_BASE + 12)
|
||||||
|
|
||||||
|
// LAPIC Special Vectors
|
||||||
|
#define T_IRQ_SPURIOUS (T_IRQ_BASE + 24)
|
||||||
|
#define T_IRQ_ERROR (T_IRQ_BASE + 25)
|
||||||
|
#define T_IRQ_THERMAL (T_IRQ_BASE + 26)
|
||||||
|
|
||||||
|
#define T_SYSCALL 60 /* System Call */
|
||||||
|
#define T_CROSSCALL 61 /* Cross Call (IPI) */
|
||||||
|
#define T_DEBUGIPI 62 /* Kernel Debugger Halt (IPI) */
|
||||||
|
|
||||||
|
#define T_UNKNOWN 63 /* Unknown Trap */
|
||||||
|
|
||||||
|
#define T_MAX 64
|
||||||
|
|
||||||
|
typedef struct TrapFrame
|
||||||
|
{
|
||||||
|
uint64_t r15;
|
||||||
|
uint64_t r14;
|
||||||
|
uint64_t r13;
|
||||||
|
uint64_t r12;
|
||||||
|
uint64_t r11;
|
||||||
|
uint64_t r10;
|
||||||
|
uint64_t r9;
|
||||||
|
uint64_t r8;
|
||||||
|
uint64_t rbp;
|
||||||
|
uint64_t rdi;
|
||||||
|
uint64_t rsi;
|
||||||
|
uint64_t rdx;
|
||||||
|
uint64_t rcx;
|
||||||
|
uint64_t rbx;
|
||||||
|
uint64_t ds;
|
||||||
|
uint64_t rax;
|
||||||
|
|
||||||
|
uint64_t vector;
|
||||||
|
uint32_t errcode;
|
||||||
|
uint32_t _unused0;
|
||||||
|
uint64_t rip;
|
||||||
|
uint16_t cs;
|
||||||
|
uint16_t _unused1;
|
||||||
|
uint16_t _unused2;
|
||||||
|
uint16_t _unused3;
|
||||||
|
uint64_t rflags;
|
||||||
|
uint64_t rsp;
|
||||||
|
uint16_t ss;
|
||||||
|
uint16_t _unused4;
|
||||||
|
uint16_t _unused5;
|
||||||
|
uint16_t _unused6;
|
||||||
|
} TrapFrame;
|
||||||
|
|
||||||
|
void Trap_Init();
|
||||||
|
void Trap_InitAP();
|
||||||
|
void Trap_Dump(TrapFrame *tf);
|
||||||
|
void Trap_Pop(TrapFrame *tf);
|
||||||
|
|
||||||
|
#endif /* __TRAP_H__ */
|
||||||
|
|
53
sys/arm64/irq.c
Normal file
53
sys/arm64/irq.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <sys/kassert.h>
|
||||||
|
#include <sys/irq.h>
|
||||||
|
|
||||||
|
#include <machine/trap.h>
|
||||||
|
#include <machine/ioapic.h>
|
||||||
|
|
||||||
|
LIST_HEAD(IRQHandlerList, IRQHandler);
|
||||||
|
struct IRQHandlerList handlers[T_IRQ_LEN];
|
||||||
|
|
||||||
|
void
|
||||||
|
IRQ_Init()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < T_IRQ_LEN; i++)
|
||||||
|
{
|
||||||
|
LIST_INIT(&handlers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IRQ_Handler(int irq)
|
||||||
|
{
|
||||||
|
struct IRQHandler *h;
|
||||||
|
LIST_FOREACH(h, &handlers[irq], link)
|
||||||
|
{
|
||||||
|
h->cb(h->arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IRQ_Register(int irq, struct IRQHandler *h)
|
||||||
|
{
|
||||||
|
ASSERT(irq < T_IRQ_LEN);
|
||||||
|
|
||||||
|
LIST_INSERT_HEAD(&handlers[irq], h, link);
|
||||||
|
|
||||||
|
//IOAPIC_Enable(irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IRQ_Unregister(int irq, struct IRQHandler *h)
|
||||||
|
{
|
||||||
|
LIST_REMOVE(h, link);
|
||||||
|
|
||||||
|
if (LIST_EMPTY(&handlers[irq])) {
|
||||||
|
//IOAPIC_Disable(irq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
227
sys/arm64/kernel.lds
Normal file
227
sys/arm64/kernel.lds
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
/*OUTPUT_FORMAT("elf64-arm64-freebsd",
|
||||||
|
"elf64-arm64-freebsd",
|
||||||
|
"elf64-arm64-freebsd")*/
|
||||||
|
|
||||||
|
OUTPUT_ARCH(arm:arm64)
|
||||||
|
ENTRY(_start)
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Read-only sections, merged into text segment: */
|
||||||
|
PROVIDE (__executable_start = SEGMENT_START("text-segment",
|
||||||
|
0xFFFF800000400000));
|
||||||
|
. = SEGMENT_START("text-segment", 0xFFFF800000400000) + SIZEOF_HEADERS;
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
*(.text.exit .text.exit.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text.hot .text.hot.*)
|
||||||
|
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
}
|
||||||
|
.plt : { *(.plt) *(.iplt) }
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
KEEP (*(.init))
|
||||||
|
}
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(.fini))
|
||||||
|
}
|
||||||
|
PROVIDE (__etext = .);
|
||||||
|
PROVIDE (_etext = .);
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||||
|
.rodata1 : { *(.rodata1) }
|
||||||
|
.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.init : { *(.rela.init) }
|
||||||
|
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||||
|
.rela.fini : { *(.rela.fini) }
|
||||||
|
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
|
||||||
|
.rela.data.rel.ro : { *(.rela.data.rel.ro .rela.data.rel.ro.* .rela.gnu.linkonce.d.rel.ro.*) }
|
||||||
|
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
|
||||||
|
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
|
||||||
|
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
|
||||||
|
.rela.ctors : { *(.rela.ctors) }
|
||||||
|
.rela.dtors : { *(.rela.dtors) }
|
||||||
|
.rela.got : { *(.rela.got) }
|
||||||
|
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
|
||||||
|
.rela.ldata : { *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) }
|
||||||
|
.rela.lbss : { *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) }
|
||||||
|
.rela.lrodata : { *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) }
|
||||||
|
.rela.ifunc : { *(.rela.ifunc) }
|
||||||
|
.rela.plt :
|
||||||
|
{
|
||||||
|
*(.rela.plt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||||
|
*(.rela.iplt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||||
|
}
|
||||||
|
.eh_frame_hdr : { *(.eh_frame_hdr) }
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
|
||||||
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table
|
||||||
|
.gcc_except_table.*) }
|
||||||
|
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||||
|
.exception_ranges : ONLY_IF_RO { *(.exception_ranges
|
||||||
|
.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. */
|
||||||
|
. = .;
|
||||||
|
/* Exception handling */
|
||||||
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
|
||||||
|
/* Thread Local Storage sections */
|
||||||
|
.tdata : { *(.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 (*(.init_array.* .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 (*(.fini_array.* .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) }
|
||||||
|
.got : { *(.got) *(.igot) }
|
||||||
|
.got.plt : { *(.got.plt) *(.igot.plt) }
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
}
|
||||||
|
.data1 : { *(.data1) }
|
||||||
|
/* Kernel Debugger */
|
||||||
|
.kdbgcmd ALIGN(CONSTANT(COMMONPAGESIZE)) :
|
||||||
|
{
|
||||||
|
__kdbgcmd_start = .;
|
||||||
|
*(.kdbgcmd)
|
||||||
|
__kdbgcmd_end = .;
|
||||||
|
}
|
||||||
|
_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 don't
|
||||||
|
pad the .data section. */
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
.lbss :
|
||||||
|
{
|
||||||
|
*(.dynlbss)
|
||||||
|
*(.lbss .lbss.* .gnu.linkonce.lb.*)
|
||||||
|
*(LARGE_COMMON)
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
. = SEGMENT_START("ldata-segment", .);
|
||||||
|
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
|
||||||
|
}
|
||||||
|
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.ldata .ldata.* .gnu.linkonce.l.*)
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
_end = .; PROVIDE (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) }
|
||||||
|
/* 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 Extension. */
|
||||||
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
|
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||||
|
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
|
||||||
|
}
|
170
sys/arm64/machine.c
Normal file
170
sys/arm64/machine.c
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <sys/kconfig.h>
|
||||||
|
#include <sys/kassert.h>
|
||||||
|
#include <sys/kmem.h>
|
||||||
|
#include <sys/mp.h>
|
||||||
|
#include <sys/irq.h>
|
||||||
|
#include <sys/spinlock.h>
|
||||||
|
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <machine/trap.h>
|
||||||
|
#include <machine/pmap.h>
|
||||||
|
#include <machine/mp.h>
|
||||||
|
|
||||||
|
#include <sys/thread.h>
|
||||||
|
#include <sys/disk.h>
|
||||||
|
#include <sys/bufcache.h>
|
||||||
|
#include <sys/vfs.h>
|
||||||
|
#include <sys/elf64.h>
|
||||||
|
|
||||||
|
#include "../dev/console.h"
|
||||||
|
|
||||||
|
extern void KTime_Init();
|
||||||
|
extern void KTimer_Init();
|
||||||
|
extern void RTC_Init();
|
||||||
|
extern void PCI_Init();
|
||||||
|
extern void MachineBoot_AddMem();
|
||||||
|
extern void Loader_LoadInit();
|
||||||
|
extern void PAlloc_LateInit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Machine_SyscallInit --
|
||||||
|
*
|
||||||
|
* Configure the model specific registers (MSRs) that specify how to transfer
|
||||||
|
* control to the operating system when the system call instruction is invoked.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
Machine_SyscallInit()
|
||||||
|
{
|
||||||
|
kprintf("Initializing Syscall... ");
|
||||||
|
|
||||||
|
NOT_IMPLEMENTED();
|
||||||
|
|
||||||
|
kprintf("Done!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Machine_EarlyInit --
|
||||||
|
*
|
||||||
|
* Initializes early kernel state.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Machine_EarlyInit()
|
||||||
|
{
|
||||||
|
Spinlock_EarlyInit();
|
||||||
|
Critical_Init();
|
||||||
|
Critical_Enter();
|
||||||
|
WaitChannel_EarlyInit();
|
||||||
|
Console_Init();
|
||||||
|
PAlloc_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Machine_IdleThread(void *test)
|
||||||
|
{
|
||||||
|
while (1) { enable_interrupts(); hlt(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Machine_Init --
|
||||||
|
*
|
||||||
|
* At this point the assembly startup code has setup temporary processor data
|
||||||
|
* structures sufficient to execute C code and make it through this
|
||||||
|
* initialization routine.
|
||||||
|
*/
|
||||||
|
void Machine_Init()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Initialize Processor State
|
||||||
|
*/
|
||||||
|
//Trap_Init();
|
||||||
|
Machine_SyscallInit();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize Memory Allocation and Virtual Memory
|
||||||
|
*/
|
||||||
|
//PAlloc_AddRegion(DMPA2VA(16*1024*1024), 16*1024*1024);
|
||||||
|
PMap_Init();
|
||||||
|
XMem_Init();
|
||||||
|
PAlloc_LateInit();
|
||||||
|
MachineBoot_AddMem();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize Time Keeping
|
||||||
|
*/
|
||||||
|
KTime_Init();
|
||||||
|
RTC_Init(); // Finishes initializing KTime
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize Interrupts
|
||||||
|
*/
|
||||||
|
IRQ_Init();
|
||||||
|
// GICv3
|
||||||
|
Thread_Init();
|
||||||
|
|
||||||
|
KTimer_Init(); // Depends on RTC and KTime
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize Additional Processors
|
||||||
|
*/
|
||||||
|
MP_Init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize Basic Devices
|
||||||
|
*/
|
||||||
|
PCI_Init(); // PCI BUS
|
||||||
|
BufCache_Init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open the primary disk and mount the root file system
|
||||||
|
*/
|
||||||
|
Disk *root = Disk_GetByID(0, 0);
|
||||||
|
if (!root)
|
||||||
|
Panic("No boot disk!");
|
||||||
|
VFS_MountRoot(root);
|
||||||
|
|
||||||
|
Critical_Exit();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the idle thread
|
||||||
|
*/
|
||||||
|
Thread *thr = Thread_KThreadCreate(&Machine_IdleThread, NULL);
|
||||||
|
if (thr == NULL) {
|
||||||
|
kprintf("Couldn't create idle thread!\n");
|
||||||
|
}
|
||||||
|
Sched_SetRunnable(thr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load the init processor
|
||||||
|
*/
|
||||||
|
Loader_LoadInit();
|
||||||
|
|
||||||
|
breakpoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Machine_InitAP --
|
||||||
|
*
|
||||||
|
* Shorter initialization routine for co-processors.
|
||||||
|
*/
|
||||||
|
void Machine_InitAP()
|
||||||
|
{
|
||||||
|
Critical_Enter();
|
||||||
|
|
||||||
|
// Setup CPU state
|
||||||
|
Trap_InitAP();
|
||||||
|
PMap_InitAP();
|
||||||
|
Machine_SyscallInit();
|
||||||
|
|
||||||
|
// Setup LAPIC
|
||||||
|
|
||||||
|
// Boot processor
|
||||||
|
MP_InitAP();
|
||||||
|
Thread_InitAP();
|
||||||
|
Critical_Exit();
|
||||||
|
|
||||||
|
Machine_IdleThread(NULL);
|
||||||
|
}
|
||||||
|
|
61
sys/arm64/mbentry.c
Normal file
61
sys/arm64/mbentry.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Multiboot C Entry
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <sys/kassert.h>
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#include "../dev/console.h"
|
||||||
|
|
||||||
|
#include <machine/pmap.h>
|
||||||
|
|
||||||
|
void MachineBoot_Entry(unsigned long magic, unsigned long addr);
|
||||||
|
|
||||||
|
#define PAGE_ALIGN __attribute__((aligned(PGSIZE)))
|
||||||
|
#define DATA_SECTION __attribute__((section(".data")))
|
||||||
|
|
||||||
|
extern void Machine_EarlyInit();
|
||||||
|
extern void Machine_Init();
|
||||||
|
extern void PAlloc_AddRegion(uintptr_t start, uintptr_t len);
|
||||||
|
|
||||||
|
#define MAX_REGIONS 16
|
||||||
|
static uintptr_t memRegionStart[MAX_REGIONS];
|
||||||
|
static uintptr_t memRegionLen[MAX_REGIONS];
|
||||||
|
static int memRegionIdx;
|
||||||
|
|
||||||
|
void
|
||||||
|
MachineBoot_Entry(unsigned long magic, unsigned long addr)
|
||||||
|
{
|
||||||
|
// Main initialization
|
||||||
|
Machine_Init();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MachineBoot_AddMem()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uintptr_t initRamEnd = 32*1024*1024;
|
||||||
|
|
||||||
|
for (i = 0; i < memRegionIdx; i++)
|
||||||
|
{
|
||||||
|
uintptr_t start = memRegionStart[i];
|
||||||
|
uintptr_t len = memRegionLen[i];
|
||||||
|
|
||||||
|
if (start + len < initRamEnd)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (start < initRamEnd) {
|
||||||
|
len = initRamEnd - start;
|
||||||
|
start = initRamEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
kprintf("AddRegion: %08llx %08llx\n", start, len);
|
||||||
|
PAlloc_AddRegion(start + MEM_DIRECTMAP_BASE, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
213
sys/arm64/mp.c
Normal file
213
sys/arm64/mp.c
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/kassert.h>
|
||||||
|
#include <sys/kconfig.h>
|
||||||
|
#include <sys/kdebug.h>
|
||||||
|
#include <sys/kmem.h>
|
||||||
|
#include <sys/ktime.h>
|
||||||
|
#include <sys/mp.h>
|
||||||
|
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <machine/cpuop.h>
|
||||||
|
#include <machine/pmap.h>
|
||||||
|
#include <machine/mp.h>
|
||||||
|
#include <machine/trap.h>
|
||||||
|
|
||||||
|
extern uint8_t mpstart_begin[];
|
||||||
|
extern uint8_t mpstart_end[];
|
||||||
|
|
||||||
|
extern AS systemAS;
|
||||||
|
|
||||||
|
#define MP_WAITTIME 250000000ULL
|
||||||
|
|
||||||
|
typedef struct CrossCallFrame {
|
||||||
|
CrossCallCB cb;
|
||||||
|
void *arg;
|
||||||
|
volatile int count;
|
||||||
|
volatile int done[MAX_CPUS];
|
||||||
|
volatile int status[MAX_CPUS];
|
||||||
|
} CrossCallFrame;
|
||||||
|
|
||||||
|
const char *CPUStateToString[] = {
|
||||||
|
"NOT PRESENT",
|
||||||
|
"BOOTED",
|
||||||
|
"HALTED",
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct CPUState {
|
||||||
|
int state;
|
||||||
|
UnixEpochNS heartbeat;
|
||||||
|
CrossCallFrame *frame;
|
||||||
|
} CPUState;
|
||||||
|
|
||||||
|
volatile static bool booted;
|
||||||
|
volatile static int lastCPU;
|
||||||
|
volatile static CPUState cpus[MAX_CPUS];
|
||||||
|
|
||||||
|
void
|
||||||
|
MP_Init()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
kprintf("Booting on CPU %u\n", CPU());
|
||||||
|
|
||||||
|
cpus[CPU()].state = CPUSTATE_BOOTED;
|
||||||
|
cpus[CPU()].frame = NULL;
|
||||||
|
|
||||||
|
for (i = 1; i < MAX_CPUS; i++) {
|
||||||
|
cpus[i].state = CPUSTATE_NOT_PRESENT;
|
||||||
|
cpus[i].frame = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: We really should read from the MP Table, but this appears to be
|
||||||
|
* reliable for now.
|
||||||
|
*/
|
||||||
|
lastCPU = 0;
|
||||||
|
/*
|
||||||
|
for (i = 1; i < MAX_CPUS; i++) {
|
||||||
|
if (MPBootAP(i) < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
lastCPU = i;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
lastCPU++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MP_InitAP()
|
||||||
|
{
|
||||||
|
kprintf("AP %d booted!\n", CPU());
|
||||||
|
cpus[CPU()].state = CPUSTATE_BOOTED;
|
||||||
|
booted = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MP_SetState(int state)
|
||||||
|
{
|
||||||
|
ASSERT(state > 0 && state <= CPUSTATE_MAX);
|
||||||
|
cpus[CPU()].state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
MP_GetCPUs()
|
||||||
|
{
|
||||||
|
return lastCPU;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MP_CrossCallTrap()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
Critical_Enter();
|
||||||
|
|
||||||
|
for (c = 0; c <= lastCPU; c++) {
|
||||||
|
CrossCallFrame *frame = cpus[c].frame;
|
||||||
|
if (frame == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (frame->done[CPU()] == 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
frame->status[CPU()] = (frame->cb)(frame->arg);
|
||||||
|
frame->done[CPU()] = 1;
|
||||||
|
|
||||||
|
// Increment
|
||||||
|
__sync_add_and_fetch(&frame->count, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Critical_Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: The thread should not be migrated in the middle of this call.
|
||||||
|
int
|
||||||
|
MP_CrossCall(CrossCallCB cb, void *arg)
|
||||||
|
{
|
||||||
|
volatile CrossCallFrame frame;
|
||||||
|
|
||||||
|
// Setup frame
|
||||||
|
memset((void *)&frame, 0, sizeof(frame));
|
||||||
|
frame.cb = cb;
|
||||||
|
frame.arg = arg;
|
||||||
|
frame.count = 1;
|
||||||
|
|
||||||
|
Critical_Enter();
|
||||||
|
|
||||||
|
cpus[CPU()].frame = (CrossCallFrame *)&frame;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (LAPIC_Broadcast(T_CROSSCALL) < 0)
|
||||||
|
return -1;
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Run on the local CPU
|
||||||
|
frame.status[CPU()] = cb(arg);
|
||||||
|
frame.done[CPU()] = 1;
|
||||||
|
|
||||||
|
// Wait for all to respond
|
||||||
|
while (frame.count < lastCPU) {
|
||||||
|
// Check for timeout
|
||||||
|
|
||||||
|
// XXX: Should dump the crosscall frame
|
||||||
|
}
|
||||||
|
cpus[CPU()].frame = NULL;
|
||||||
|
|
||||||
|
Critical_Exit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
MPPing(void *arg)
|
||||||
|
{
|
||||||
|
//kprintf("CPU %d Ack\n", CPU());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_CrossCall(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
UnixEpochNS startTS, stopTS;
|
||||||
|
|
||||||
|
startTS = KTime_GetEpochNS();
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
MP_CrossCall(&MPPing, NULL);
|
||||||
|
}
|
||||||
|
stopTS = KTime_GetEpochNS();
|
||||||
|
|
||||||
|
// XXX: Print min and max
|
||||||
|
kprintf("Average CrossCall Latency: %llu ns\n",
|
||||||
|
(stopTS - startTS) / 32ULL);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(crosscall, "Ping crosscall", Debug_CrossCall);
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_CPUS(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (c = 0; c < MAX_CPUS; c++) {
|
||||||
|
if (cpus[c].state != CPUSTATE_NOT_PRESENT) {
|
||||||
|
kprintf("CPU %d: %s\n", c, CPUStateToString[cpus[c].state]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(cpus, "Show MP information", Debug_CPUS);
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_CPU(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
kprintf("CPU %d\n", CPU());
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(cpu, "Current CPU number", Debug_CPU);
|
||||||
|
|
30
sys/arm64/multiboot.S
Normal file
30
sys/arm64/multiboot.S
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Multiboot Entry
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define STACK_SIZE 0x4000
|
||||||
|
|
||||||
|
#define KERNEL_BASE 0xFFFF800000000000
|
||||||
|
#define LOWMEM(_x) (_x - KERNEL_BASE)
|
||||||
|
|
||||||
|
.extern mb_entry
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _start --
|
||||||
|
*
|
||||||
|
* ELF entry point.
|
||||||
|
*/
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
#call MachineBoot_Entry
|
||||||
|
loop:
|
||||||
|
#hlt
|
||||||
|
#jmp loop
|
||||||
|
|
||||||
|
// Boot stack
|
||||||
|
.p2align 12
|
||||||
|
.globl stack
|
||||||
|
.comm stack, STACK_SIZE
|
||||||
|
|
77
sys/arm64/pci.c
Normal file
77
sys/arm64/pci.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <sys/kassert.h>
|
||||||
|
#include <sys/pci.h>
|
||||||
|
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <machine/cpuop.h>
|
||||||
|
|
||||||
|
#define PCI_PORT_ADDR 0xCF8
|
||||||
|
#define PCI_PORT_DATABASE 0xCFC
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
PCIGetAddr(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
|
||||||
|
{
|
||||||
|
ASSERT(bus < 256 && slot < 64 && func < 8 && reg < 256);
|
||||||
|
return (1 << 31) | (bus << 16) | (slot << 11) | (func << 8) | (reg & 0x00fc);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
PCICfgRead8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
|
||||||
|
{
|
||||||
|
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
|
||||||
|
uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
PCICfgRead16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
|
||||||
|
{
|
||||||
|
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
|
||||||
|
uint16_t port = PCI_PORT_DATABASE + (reg & 0x2);
|
||||||
|
|
||||||
|
ASSERT((reg & 0x1) == 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
PCICfgRead32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
|
||||||
|
{
|
||||||
|
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
|
||||||
|
uint16_t port = PCI_PORT_DATABASE;
|
||||||
|
|
||||||
|
ASSERT((reg & 0x3) == 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PCICfgWrite8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
|
||||||
|
uint8_t data)
|
||||||
|
{
|
||||||
|
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
|
||||||
|
uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PCICfgWrite16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
|
||||||
|
uint16_t data)
|
||||||
|
{
|
||||||
|
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
|
||||||
|
uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PCICfgWrite32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
|
||||||
|
uint32_t data)
|
||||||
|
{
|
||||||
|
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
|
||||||
|
uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
323
sys/arm64/pmap.c
Normal file
323
sys/arm64/pmap.c
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <sys/kconfig.h>
|
||||||
|
#include <sys/kassert.h>
|
||||||
|
#include <sys/kdebug.h>
|
||||||
|
#include <sys/kmem.h>
|
||||||
|
#include <sys/mp.h>
|
||||||
|
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <machine/cpuop.h>
|
||||||
|
|
||||||
|
#include <machine/pmap.h>
|
||||||
|
|
||||||
|
AS systemAS;
|
||||||
|
AS *currentAS[MAX_CPUS];
|
||||||
|
|
||||||
|
void
|
||||||
|
PMap_Init()
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
kprintf("Initializing PMAP ... ");
|
||||||
|
|
||||||
|
// Setup global state
|
||||||
|
for (i = 0; i < MAX_CPUS; i++) {
|
||||||
|
currentAS[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate system page table
|
||||||
|
systemAS.root = PAlloc_AllocPage();
|
||||||
|
systemAS.tables = PAGETABLE_ENTRIES / 2 + 1;
|
||||||
|
systemAS.mappings = 0;
|
||||||
|
|
||||||
|
if (!systemAS.root)
|
||||||
|
PANIC("Cannot allocate system page table");
|
||||||
|
|
||||||
|
// Setup system mappings
|
||||||
|
PMap_SystemLMap(0x0, MEM_DIRECTMAP_BASE + 0x0,
|
||||||
|
3*512, 0); // 3GB RWX
|
||||||
|
PMap_SystemLMap(0xC0000000, MEM_DIRECTMAP_BASE + 0xC0000000,
|
||||||
|
512, 0); // 1GB RW + PCD
|
||||||
|
PMap_SystemLMap(0x100000000, MEM_DIRECTMAP_BASE + 0x100000000,
|
||||||
|
60*512, 0); // 60GB RWX
|
||||||
|
|
||||||
|
PMap_LoadAS(&systemAS);
|
||||||
|
|
||||||
|
kprintf("Done!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PMap_InitAP()
|
||||||
|
{
|
||||||
|
PMap_LoadAS(&systemAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_NewAS --
|
||||||
|
*
|
||||||
|
* Create a new address space.
|
||||||
|
*
|
||||||
|
* @return Newly created address space.
|
||||||
|
*/
|
||||||
|
AS*
|
||||||
|
PMap_NewAS()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
AS *as = PAlloc_AllocPage();
|
||||||
|
|
||||||
|
if (!as)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
as->root = PAlloc_AllocPage();
|
||||||
|
as->tables = 1;
|
||||||
|
as->mappings = 0;
|
||||||
|
|
||||||
|
// NOT IMPLEMENTED
|
||||||
|
|
||||||
|
return as;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_DestroyAS --
|
||||||
|
*
|
||||||
|
* Destroys an address space and releases the physical pages.
|
||||||
|
*
|
||||||
|
* @param [in] space Address space to destroy.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
PMap_DestroyAS(AS *space)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_CurrentAS --
|
||||||
|
*
|
||||||
|
* Get the current address space on this CPU.
|
||||||
|
*
|
||||||
|
* @return Current address space.
|
||||||
|
*/
|
||||||
|
AS *
|
||||||
|
PMap_CurrentAS()
|
||||||
|
{
|
||||||
|
return currentAS[CPU()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_LoadAS --
|
||||||
|
*
|
||||||
|
* Load an address space into the CPU. Reloads the CR3 register in x86-64 that
|
||||||
|
* points the physical page tables and flushes the TLB entries.
|
||||||
|
*
|
||||||
|
* @param [in] space Address space to load.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
PMap_LoadAS(AS *space)
|
||||||
|
{
|
||||||
|
// Flush TLB
|
||||||
|
currentAS[CPU()] = space;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMapAllocPageTable --
|
||||||
|
*
|
||||||
|
* Allocates and initializes a page table.
|
||||||
|
*
|
||||||
|
* @return Newly created PageTable.
|
||||||
|
*/
|
||||||
|
static PageTable *
|
||||||
|
PMapAllocPageTable()
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_Translate --
|
||||||
|
*
|
||||||
|
* Translates a virtual address to physical address for a given address space.
|
||||||
|
*
|
||||||
|
* @param [in] space Address space we wish to lookup a mapping in.
|
||||||
|
* @param [in] va Virtual address we wish to translate.
|
||||||
|
*/
|
||||||
|
uintptr_t
|
||||||
|
PMap_Translate(AS *space, uintptr_t va)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMapLookupEntry --
|
||||||
|
*
|
||||||
|
* Lookup a virtual address in a page table and return a pointer to the page
|
||||||
|
* entry. This function allocates page tables as necessary to fill in the
|
||||||
|
* 4-level heirarchy.
|
||||||
|
*
|
||||||
|
* @param [in] space Address space to search.
|
||||||
|
* @param [in] va Virtual address to lookup.
|
||||||
|
* @param [out] entry Pointer will point to the PageEntry.
|
||||||
|
* @param [in] size Page size we want to use.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
PMapLookupEntry(AS *space, uint64_t va, PageEntry **entry, int size)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_Map --
|
||||||
|
*
|
||||||
|
* Map a physical to virtual mapping in an address space.
|
||||||
|
*
|
||||||
|
* @param [in] as Address space.
|
||||||
|
* @param [in] phys Physical address.
|
||||||
|
* @param [in] virt Virtual address.
|
||||||
|
* @param [in] pages Pages to map in.
|
||||||
|
* @param [in] flags Flags to apply to the mapping.
|
||||||
|
*
|
||||||
|
* @retval true On success
|
||||||
|
* @retval false On failure
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
PMap_Map(AS *as, uint64_t phys, uint64_t virt, uint64_t pages, uint64_t flags)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_Unmap --
|
||||||
|
*
|
||||||
|
* Unmap a range of addresses.
|
||||||
|
*
|
||||||
|
* @param [in] as Address space.
|
||||||
|
* @param [in] va Virtual address.
|
||||||
|
* @param [in] pages Pages to map in.
|
||||||
|
*
|
||||||
|
* @retval true On success
|
||||||
|
* @retval false On failure
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
PMap_Unmap(AS *as, uint64_t va, uint64_t pages)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_AllocMap --
|
||||||
|
*
|
||||||
|
* Map a virtual mapping in an address space and back it by newly allocated
|
||||||
|
* memory.
|
||||||
|
*
|
||||||
|
* @param [in] as Address space.
|
||||||
|
* @param [in] virt Virtual address.
|
||||||
|
* @param [in] pages Pages to map in.
|
||||||
|
* @param [in] flags Flags to apply to the mapping.
|
||||||
|
*
|
||||||
|
* @retval true On success
|
||||||
|
* @retval false On failure
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
PMap_AllocMap(AS *as, uint64_t virt, uint64_t len, uint64_t flags)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_SystemLookup --
|
||||||
|
*
|
||||||
|
* Lookup a kernel virtual address in a page table and return a pointer to the
|
||||||
|
* page entry. This function allocates page tables as necessary to fill in the
|
||||||
|
* 4-level heirarchy.
|
||||||
|
*
|
||||||
|
* @param [in] va Virtual address to lookup.
|
||||||
|
* @param [out] entry Pointer will point to the PageEntry.
|
||||||
|
* @param [in] size Page size we want to use.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
PMap_SystemLookup(uint64_t va, PageEntry **entry, int size)
|
||||||
|
{
|
||||||
|
PMapLookupEntry(&systemAS, va, entry, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_SystemLMap --
|
||||||
|
*
|
||||||
|
* Map a range of large (2MB) physical pages to virtual pages in the kernel
|
||||||
|
* address space that is shared by all processes.
|
||||||
|
*
|
||||||
|
* @param [in] phys Physical address.
|
||||||
|
* @param [in] virt Virtual address.
|
||||||
|
* @param [in] lpages Large pages to map in.
|
||||||
|
* @param [in] flags Flags to apply to the mapping.
|
||||||
|
*
|
||||||
|
* @retval true On success
|
||||||
|
* @retval false On failure
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
PMap_SystemLMap(uint64_t phys, uint64_t virt, uint64_t lpages, uint64_t flags)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_SystemLMap --
|
||||||
|
*
|
||||||
|
* Map a range of physical pages to virtual pages in the kernel address space
|
||||||
|
* that is shared by all processes.
|
||||||
|
*
|
||||||
|
* @param [in] phys Physical address.
|
||||||
|
* @param [in] virt Virtual address.
|
||||||
|
* @param [in] pages Pages to map in.
|
||||||
|
* @param [in] flags Flags to apply to the mapping.
|
||||||
|
*
|
||||||
|
* @retval true On success
|
||||||
|
* @retval false On failure
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
PMap_SystemMap(uint64_t phys, uint64_t virt, uint64_t pages, uint64_t flags)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PMap_SystemUnmap --
|
||||||
|
*
|
||||||
|
* We do not currently use this!
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
PMap_SystemUnmap(uint64_t virt, uint64_t pages)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t
|
||||||
|
AddrFromIJKL(uint64_t i, uint64_t j, uint64_t k, uint64_t l)
|
||||||
|
{
|
||||||
|
return (i << 39) | (j << HUGE_PGSHIFT) | (k << LARGE_PGSHIFT) | (l << PGSHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PMap_Dump(AS *space)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_PMapDump(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
PMap_Dump(currentAS[CPU()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(pmapdump, "Dump memory mappings", Debug_PMapDump);
|
||||||
|
|
||||||
|
|
26
sys/arm64/support.S
Normal file
26
sys/arm64/support.S
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Support Functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <machine/asm.h>
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
// copy_unsafe(to, from, len)
|
||||||
|
FUNC_BEGIN(copy_unsafe)
|
||||||
|
.globl copy_unsafe_done
|
||||||
|
copy_unsafe_done:
|
||||||
|
.globl copy_unsafe_fault
|
||||||
|
copy_unsafe_fault:
|
||||||
|
FUNC_END(copy_unsafe)
|
||||||
|
|
||||||
|
// copystr_unsafe(to, from, len)
|
||||||
|
FUNC_BEGIN(copystr_unsafe)
|
||||||
|
.globl copystr_unsafe_done
|
||||||
|
copystr_unsafe_done:
|
||||||
|
.globl copystr_unsafe_fault
|
||||||
|
copystr_unsafe_fault:
|
||||||
|
.globl copystr_unsafe_toolong
|
||||||
|
FUNC_END(copystr_unsafe)
|
||||||
|
|
19
sys/arm64/switch.S
Normal file
19
sys/arm64/switch.S
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Trap Handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <machine/asm.h>
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
# switch(uint64_t *oldsp, uint64_t newsp)
|
||||||
|
# %rdi: oldsp
|
||||||
|
# %rsi: newsp
|
||||||
|
FUNC_BEGIN(switchstack)
|
||||||
|
# Save callee saved registers of old thread
|
||||||
|
|
||||||
|
# Switch stack from old to new thread
|
||||||
|
|
||||||
|
# Restore callee saved registers of new thread
|
||||||
|
FUNC_END(switchstack)
|
||||||
|
|
68
sys/arm64/thread.c
Normal file
68
sys/arm64/thread.c
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/kconfig.h>
|
||||||
|
#include <sys/kassert.h>
|
||||||
|
#include <sys/kmem.h>
|
||||||
|
#include <sys/mp.h>
|
||||||
|
#include <sys/thread.h>
|
||||||
|
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <machine/cpuop.h>
|
||||||
|
#include <machine/trap.h>
|
||||||
|
#include <machine/pmap.h>
|
||||||
|
|
||||||
|
extern void ThreadKThreadEntry(TrapFrame *tf);
|
||||||
|
extern void switchstack(uint64_t *oldrsp, uint64_t rsp);
|
||||||
|
|
||||||
|
void
|
||||||
|
Thread_InitArch(Thread *thr)
|
||||||
|
{
|
||||||
|
thr->arch.useFP = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Thread_SetupKThread(Thread *thr, void (*f)(),
|
||||||
|
uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
|
||||||
|
{
|
||||||
|
// Initialize stack
|
||||||
|
uint64_t stacktop = thr->kstack + PGSIZE;
|
||||||
|
ThreadArchStackFrame *sf;
|
||||||
|
TrapFrame *tf;
|
||||||
|
|
||||||
|
tf = (TrapFrame *)(stacktop - sizeof(*tf));
|
||||||
|
sf = (ThreadArchStackFrame *)(stacktop - sizeof(*tf) - sizeof(*sf));
|
||||||
|
|
||||||
|
memset(tf, 0, sizeof(*tf));
|
||||||
|
memset(sf, 0, sizeof(*sf));
|
||||||
|
|
||||||
|
// Setup thread exit function on stack
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ThreadEnterUserLevelCB(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
|
||||||
|
{
|
||||||
|
TrapFrame tf;
|
||||||
|
|
||||||
|
memset(&tf, 0, sizeof(tf));
|
||||||
|
|
||||||
|
Trap_Pop(&tf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Thread_SetupUThread(Thread *thr, uintptr_t rip, uintptr_t arg)
|
||||||
|
{
|
||||||
|
Thread_SetupKThread(thr, ThreadEnterUserLevelCB, rip,
|
||||||
|
thr->ustack, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Thread_SwitchArch(Thread *oldthr, Thread *newthr)
|
||||||
|
{
|
||||||
|
// Jump to trapframe
|
||||||
|
switchstack(&oldthr->arch.rsp, newthr->arch.rsp);
|
||||||
|
}
|
||||||
|
|
25
sys/arm64/time.c
Normal file
25
sys/arm64/time.c
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <sys/kassert.h>
|
||||||
|
#include <sys/kdebug.h>
|
||||||
|
#include <sys/ktime.h>
|
||||||
|
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <machine/cpuop.h>
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
Time_GetTSC()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_ReadTSC(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
kprintf("RDTSC: %lld\n", Time_GetTSC());
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(readtsc, "Print current timestamp", Debug_ReadTSC);
|
||||||
|
|
121
sys/arm64/trap.c
Normal file
121
sys/arm64/trap.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <sys/kconfig.h>
|
||||||
|
#include <sys/kassert.h>
|
||||||
|
#include <sys/kdebug.h>
|
||||||
|
#include <sys/kmem.h>
|
||||||
|
#include <sys/ktime.h>
|
||||||
|
#include <sys/spinlock.h>
|
||||||
|
#include <sys/irq.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/mp.h>
|
||||||
|
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <machine/trap.h>
|
||||||
|
#include <machine/mp.h>
|
||||||
|
|
||||||
|
#include <sys/thread.h>
|
||||||
|
|
||||||
|
extern uint64_t trap_table[T_MAX];
|
||||||
|
extern void trap_pop(TrapFrame *tf);
|
||||||
|
extern void Debug_Breakpoint(TrapFrame *tf);
|
||||||
|
extern void Debug_HaltIPI(TrapFrame *tf);
|
||||||
|
extern void KTimer_Process();
|
||||||
|
|
||||||
|
static uint64_t intStats[256];
|
||||||
|
|
||||||
|
void
|
||||||
|
Trap_Init()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
kprintf("Initializing IDT... ");
|
||||||
|
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
intStats[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
kprintf("Done!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Trap_InitAP()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Trap_Dump(TrapFrame *tf)
|
||||||
|
{
|
||||||
|
kprintf("CPU %d\n", CPU());
|
||||||
|
kprintf("Interrupt %d Error Code: %016llx\n",
|
||||||
|
tf->vector, tf->errcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Trap_StackDump(TrapFrame *tf)
|
||||||
|
{
|
||||||
|
uint64_t rsp;
|
||||||
|
uint64_t *data;
|
||||||
|
|
||||||
|
// XXX: This should use safe copy
|
||||||
|
for (rsp = tf->rsp; (rsp & 0xFFF) != 0; rsp += 8) {
|
||||||
|
data = (uint64_t *)rsp;
|
||||||
|
kprintf("%016llx: %016llx\n", rsp, *data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int copy_unsafe(void *to, void *from, uintptr_t len);
|
||||||
|
extern void copy_unsafe_done(void);
|
||||||
|
extern void copy_unsafe_fault(void);
|
||||||
|
|
||||||
|
extern int copystr_unsafe(void *to, void *from, uintptr_t len);
|
||||||
|
extern void copystr_unsafe_done(void);
|
||||||
|
extern void copystr_unsafe_fault(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
trap_entry(TrapFrame *tf)
|
||||||
|
{
|
||||||
|
// XXX: USE ATOMIC!
|
||||||
|
intStats[tf->vector]++;
|
||||||
|
|
||||||
|
// Debug NMI
|
||||||
|
|
||||||
|
// Kernel
|
||||||
|
// Kernel Debugger
|
||||||
|
|
||||||
|
// User IO
|
||||||
|
|
||||||
|
// Halt on kernel errors
|
||||||
|
|
||||||
|
// User space exceptions
|
||||||
|
|
||||||
|
// IRQs
|
||||||
|
|
||||||
|
// Debug IPI
|
||||||
|
|
||||||
|
// Cross calls
|
||||||
|
|
||||||
|
kprintf("Unhandled Interrupt 0x%x!\n", tf->vector);
|
||||||
|
Trap_Dump(tf);
|
||||||
|
while (1)
|
||||||
|
hlt();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Debug_Traps(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
kprintf("Trap Interrupts Trap Interrupts\n");
|
||||||
|
for (i = 0; i < T_MAX / 2; i++)
|
||||||
|
{
|
||||||
|
kprintf("%-4d %-12d %-4d %-12d\n",
|
||||||
|
i, intStats[i],
|
||||||
|
T_MAX / 2 + i, intStats[T_MAX / 2 + i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_DBGCMD(traps, "Print trap statistics", Debug_Traps);
|
||||||
|
|
38
sys/arm64/trapentry.S
Normal file
38
sys/arm64/trapentry.S
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Trap Handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
.extern trap_entry
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
.macro TRAP_NOEC TRAPNUM
|
||||||
|
trap\TRAPNUM:
|
||||||
|
# Push top of the trap frame
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro TRAP_EC TRAPNUM
|
||||||
|
trap\TRAPNUM:
|
||||||
|
# Push top of the trap frame
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.globl trap_table
|
||||||
|
trap_table:
|
||||||
|
.quad trap0
|
||||||
|
|
||||||
|
TRAP_NOEC 0 // DE
|
||||||
|
|
||||||
|
trap_common:
|
||||||
|
# Create the rest of the trap frame
|
||||||
|
|
||||||
|
# Pass the trap frame as an argument to trap_entry
|
||||||
|
.globl trap_return
|
||||||
|
trap_return:
|
||||||
|
|
||||||
|
# Skip error code and vector number
|
||||||
|
|
||||||
|
# Return to userspace
|
||||||
|
|
||||||
|
.globl Trap_Pop
|
||||||
|
Trap_Pop:
|
||||||
|
|
@ -2,9 +2,17 @@
|
|||||||
#ifndef __MP_H__
|
#ifndef __MP_H__
|
||||||
#define __MP_H__
|
#define __MP_H__
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
uint32_t LAPIC_CPU();
|
uint32_t LAPIC_CPU();
|
||||||
|
|
||||||
#define CPU LAPIC_CPU
|
#define CPU LAPIC_CPU
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
static inline int ARM_CPU()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define CPU ARM_CPU
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __MP_H__ */
|
#endif /* __MP_H__ */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user