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"),
|
||||
("WITH_GPROF", "Include gprof profiling (0 or 1).", "0"),
|
||||
("PREFIX", "Installation target directory.", "#pxelinux"),
|
||||
("ARCH", "Target Architecture", "amd64"),
|
||||
("ARCH", "Target Architecture", "arm64"),
|
||||
("BOOTDISK", "Build boot disk (0 or 1)", "1"),
|
||||
("BOOTDISK_SIZE", "Boot disk size", "128")
|
||||
)
|
||||
@ -51,8 +51,16 @@ if 'LDFLAGS' in os.environ:
|
||||
toolenv = env.Clone()
|
||||
|
||||
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" ])
|
||||
#env.Append(LINKFLAGS = [ "-no-pie" ])
|
||||
|
||||
@ -78,10 +86,6 @@ else:
|
||||
print("Error BUILDTYPE must be RELEASE or DEBUG")
|
||||
sys.exit(-1)
|
||||
|
||||
if env["ARCH"] != "amd64":
|
||||
print("Unsupported architecture: " + env["ARCH"])
|
||||
sys.exit(-1)
|
||||
|
||||
try:
|
||||
hf = open(".git/HEAD", 'r')
|
||||
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 3;
|
||||
#elif defined(__aarch64__)
|
||||
if (pagesize) {
|
||||
pagesize[0] = PGSIZE;
|
||||
}
|
||||
return 1;
|
||||
#else
|
||||
#error "Unsupported Architecture!"
|
||||
#endif
|
||||
|
@ -36,6 +36,27 @@ src_amd64 = [
|
||||
"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 = [
|
||||
"kern/copy.c",
|
||||
"kern/critical.c",
|
||||
@ -75,14 +96,22 @@ src_common = [
|
||||
if (env["ARCH"] == "amd64"):
|
||||
src.append(src_amd64)
|
||||
ldscript = "#sys/amd64/kernel.lds"
|
||||
elif (env["ARCH"] == "arm64"):
|
||||
src.append(src_arm64)
|
||||
ldscript = "#sys/arm64/kernel.lds"
|
||||
src.append(src_common)
|
||||
|
||||
kern_env.Append(LINKFLAGS = ['-T', ldscript[1:], '-nostdlib'])
|
||||
kern_env.Append(CPPFLAGS = ['-D_KERNEL'])
|
||||
kern_env.Append(CPPFLAGS = ['-ffreestanding', '-fno-builtin', '-nostdinc',
|
||||
'-mno-red-zone', '-mno-mmx', '-mno-sse',
|
||||
'-mcmodel=large'])
|
||||
# '-target', 'amd64-orion-eabi'
|
||||
'-mno-red-zone'])
|
||||
|
||||
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'])
|
||||
|
||||
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__
|
||||
#define __MP_H__
|
||||
|
||||
#if defined(__x86_64__)
|
||||
uint32_t LAPIC_CPU();
|
||||
|
||||
#define CPU LAPIC_CPU
|
||||
#elif defined(__aarch64__)
|
||||
static inline int ARM_CPU()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#define CPU ARM_CPU
|
||||
#endif
|
||||
|
||||
#endif /* __MP_H__ */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user