metal gic

This commit is contained in:
oscar 2024-09-26 04:07:50 +08:00
parent a7bafe607f
commit e96e5b0278
27 changed files with 1149 additions and 110 deletions

View File

@ -22,7 +22,7 @@ opts.AddVariables(
("PREFIX", "Installation target directory.", "#pxelinux"), ("PREFIX", "Installation target directory.", "#pxelinux"),
("ARCH", "Target Architecture", "arm64"), ("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"),
) )
env = Environment(options = opts, env = Environment(options = opts,
@ -75,7 +75,7 @@ if env["WITH_GPROF"] == "1":
env.Append(CPPFLAGS = "-DBUILDTYPE=" + env["BUILDTYPE"]) env.Append(CPPFLAGS = "-DBUILDTYPE=" + env["BUILDTYPE"])
if env["BUILDTYPE"] == "DEBUG": if env["BUILDTYPE"] == "DEBUG":
env.Append(CPPFLAGS = [ "-g", "-DDEBUG", "-Wall", env.Append(CPPFLAGS = [ "-g", "-DDEBUG", "-Wall", "-O2",
"-Wno-deprecated-declarations" ]) "-Wno-deprecated-declarations" ])
env.Append(LINKFLAGS = [ "-g" ]) env.Append(LINKFLAGS = [ "-g" ])
elif env["BUILDTYPE"] == "PERF": elif env["BUILDTYPE"] == "PERF":

View File

@ -57,6 +57,11 @@ src_arm64 = [
"arm64/gic.c", "arm64/gic.c",
# Devices # Devices
"dev/arm64/uart.c", "dev/arm64/uart.c",
# Metal
"arm64/metal.c",
"arm64/paging.c",
"arm64/mrt/init.c",
"arm64/mrt/paging.c",
] ]
src_common = [ src_common = [
@ -106,7 +111,7 @@ 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-red-zone', '-std=c11', "-Wno-c2x-extensions"])
if env["ARCH"] == "amd64": if env["ARCH"] == "amd64":
kern_env.Append(CPPFLAGS = ['-mno-mmx', '-mno-sse', '-mcmodel=large']) kern_env.Append(CPPFLAGS = ['-mno-mmx', '-mno-sse', '-mcmodel=large'])

View File

@ -5,7 +5,7 @@
static INLINE uint64_t static INLINE uint64_t
atomic_swap_uint32(volatile uint32_t *dst, uint32_t newval) atomic_swap_uint32(volatile uint32_t *dst, uint32_t newval)
{ {
asm volatile("lock; xchgl %0, %1;" __asm__ volatile("lock; xchgl %0, %1;"
: "+m" (*dst), "+r" (newval)); : "+m" (*dst), "+r" (newval));
return newval; return newval;
@ -14,7 +14,7 @@ atomic_swap_uint32(volatile uint32_t *dst, uint32_t newval)
static INLINE uint64_t static INLINE uint64_t
atomic_swap_uint64(volatile uint64_t *dst, uint64_t newval) atomic_swap_uint64(volatile uint64_t *dst, uint64_t newval)
{ {
asm volatile("lock; xchgq %0, %1;" __asm__ volatile("lock; xchgq %0, %1;"
: "+m" (*dst), "+r" (newval)); : "+m" (*dst), "+r" (newval));
return newval; return newval;

View File

@ -8,39 +8,39 @@
static INLINE void enable_interrupts() static INLINE void enable_interrupts()
{ {
asm volatile("sti"); __asm__ volatile("sti");
} }
static INLINE void disable_interrupts() static INLINE void disable_interrupts()
{ {
asm volatile("cli"); __asm__ volatile("cli");
} }
static INLINE void hlt() static INLINE void hlt()
{ {
asm volatile("hlt"); __asm__ volatile("hlt");
} }
static INLINE void pause() static INLINE void pause()
{ {
asm volatile("pause"); __asm__ volatile("pause");
} }
static INLINE void breakpoint() static INLINE void breakpoint()
{ {
asm volatile("int3"); __asm__ volatile("int3");
} }
static INLINE void icebp() static INLINE void icebp()
{ {
asm volatile(".byte 0xf1"); __asm__ volatile(".byte 0xf1");
} }
static INLINE uint64_t rdtsc() static INLINE uint64_t rdtsc()
{ {
uint32_t lo, hi; uint32_t lo, hi;
asm volatile("rdtsc" __asm__ volatile("rdtsc"
: "=a" (lo), "=d" (hi)); : "=a" (lo), "=d" (hi));
return ((uint64_t)hi << 32) | (uint64_t)lo; return ((uint64_t)hi << 32) | (uint64_t)lo;
@ -50,7 +50,7 @@ static INLINE uint64_t rdtscp(uint32_t *procno)
{ {
uint32_t lo, hi, proc; uint32_t lo, hi, proc;
asm volatile("rdtsc" __asm__ volatile("rdtsc"
: "=a" (lo), "=d" (hi), "=c" (proc)); : "=a" (lo), "=d" (hi), "=c" (proc));
if (procno) if (procno)
@ -61,7 +61,7 @@ static INLINE uint64_t rdtscp(uint32_t *procno)
static INLINE void lidt(PseudoDescriptor *idt) static INLINE void lidt(PseudoDescriptor *idt)
{ {
asm volatile("lidt (%0)" __asm__ volatile("lidt (%0)"
: :
: "r" (idt) : "r" (idt)
: "memory"); : "memory");
@ -69,7 +69,7 @@ static INLINE void lidt(PseudoDescriptor *idt)
static INLINE void lgdt(PseudoDescriptor *gdt) static INLINE void lgdt(PseudoDescriptor *gdt)
{ {
asm volatile("lgdt (%0)" __asm__ volatile("lgdt (%0)"
: :
: "r" (gdt) : "r" (gdt)
: "memory"); : "memory");
@ -77,7 +77,7 @@ static INLINE void lgdt(PseudoDescriptor *gdt)
static INLINE void ltr(uint16_t tss) static INLINE void ltr(uint16_t tss)
{ {
asm volatile("ltr %0" __asm__ volatile("ltr %0"
: :
: "r" (tss)); : "r" (tss));
} }
@ -87,7 +87,7 @@ static INLINE void cpuid(uint32_t info, uint32_t *eax, uint32_t *ebx,
{ {
uint32_t a, b, c, d; uint32_t a, b, c, d;
asm volatile("cpuid" __asm__ volatile("cpuid"
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "=a" (a), "=b" (b), "=c" (c), "=d" (d)
: "a" (info)); : "a" (info));
@ -106,7 +106,7 @@ static INLINE void wrmsr(uint32_t addr, uint64_t val)
uint32_t eax = val & 0xFFFFFFFF; uint32_t eax = val & 0xFFFFFFFF;
uint32_t edx = val >> 32; uint32_t edx = val >> 32;
asm volatile("wrmsr" __asm__ volatile("wrmsr"
: :
: "a" (eax), "c" (addr), "d" (edx)); : "a" (eax), "c" (addr), "d" (edx));
} }
@ -115,7 +115,7 @@ static INLINE uint64_t rdmsr(uint32_t addr)
{ {
uint64_t eax, edx; uint64_t eax, edx;
asm volatile("rdmsr" __asm__ volatile("rdmsr"
: "=a" (eax), "=d" (edx) : "=a" (eax), "=d" (edx)
: "c" (addr)); : "c" (addr));
@ -130,7 +130,7 @@ static INLINE uint64_t read_cr0()
{ {
uint64_t val; uint64_t val;
asm volatile("movq %%cr0, %0" __asm__ volatile("movq %%cr0, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -138,7 +138,7 @@ static INLINE uint64_t read_cr0()
static INLINE void write_cr0(uint64_t val) static INLINE void write_cr0(uint64_t val)
{ {
asm volatile("movq %0, %%cr0" __asm__ volatile("movq %0, %%cr0"
: :
: "r" (val)); : "r" (val));
} }
@ -147,7 +147,7 @@ static INLINE uint64_t read_cr2()
{ {
uint64_t val; uint64_t val;
asm volatile("movq %%cr2, %0" __asm__ volatile("movq %%cr2, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -157,7 +157,7 @@ static INLINE uint64_t read_cr3()
{ {
uint64_t val; uint64_t val;
asm volatile("movq %%cr3, %0" __asm__ volatile("movq %%cr3, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -165,7 +165,7 @@ static INLINE uint64_t read_cr3()
static INLINE void write_cr3(uint64_t val) static INLINE void write_cr3(uint64_t val)
{ {
asm volatile("movq %0, %%cr3" __asm__ volatile("movq %0, %%cr3"
: :
: "r" (val)); : "r" (val));
} }
@ -174,7 +174,7 @@ static INLINE uint64_t read_cr4()
{ {
uint64_t val; uint64_t val;
asm volatile("movq %%cr4, %0" __asm__ volatile("movq %%cr4, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -182,7 +182,7 @@ static INLINE uint64_t read_cr4()
static INLINE void write_cr4(uint64_t val) static INLINE void write_cr4(uint64_t val)
{ {
asm volatile("movq %0, %%cr4" __asm__ volatile("movq %0, %%cr4"
: :
: "r" (val)); : "r" (val));
} }
@ -195,7 +195,7 @@ static INLINE uint64_t read_dr0()
{ {
uint64_t val; uint64_t val;
asm volatile("movq %%dr0, %0" __asm__ volatile("movq %%dr0, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -203,7 +203,7 @@ static INLINE uint64_t read_dr0()
static INLINE void write_dr0(uint64_t val) static INLINE void write_dr0(uint64_t val)
{ {
asm volatile("movq %0, %%dr0" __asm__ volatile("movq %0, %%dr0"
: :
: "r" (val)); : "r" (val));
} }
@ -212,7 +212,7 @@ static INLINE uint64_t read_dr1()
{ {
uint64_t val; uint64_t val;
asm volatile("movq %%dr1, %0" __asm__ volatile("movq %%dr1, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -220,7 +220,7 @@ static INLINE uint64_t read_dr1()
static INLINE void write_dr1(uint64_t val) static INLINE void write_dr1(uint64_t val)
{ {
asm volatile("movq %0, %%dr1" __asm__ volatile("movq %0, %%dr1"
: :
: "r" (val)); : "r" (val));
} }
@ -229,7 +229,7 @@ static INLINE uint64_t read_dr2()
{ {
uint64_t val; uint64_t val;
asm volatile("movq %%dr2, %0" __asm__ volatile("movq %%dr2, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -237,7 +237,7 @@ static INLINE uint64_t read_dr2()
static INLINE void write_dr2(uint64_t val) static INLINE void write_dr2(uint64_t val)
{ {
asm volatile("movq %0, %%dr2" __asm__ volatile("movq %0, %%dr2"
: :
: "r" (val)); : "r" (val));
} }
@ -246,7 +246,7 @@ static INLINE uint64_t read_dr3()
{ {
uint64_t val; uint64_t val;
asm volatile("movq %%dr3, %0" __asm__ volatile("movq %%dr3, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -254,7 +254,7 @@ static INLINE uint64_t read_dr3()
static INLINE void write_dr3(uint64_t val) static INLINE void write_dr3(uint64_t val)
{ {
asm volatile("movq %0, %%dr3" __asm__ volatile("movq %0, %%dr3"
: :
: "r" (val)); : "r" (val));
} }
@ -263,7 +263,7 @@ static INLINE uint64_t read_dr6()
{ {
uint64_t val; uint64_t val;
asm volatile("movq %%dr6, %0" __asm__ volatile("movq %%dr6, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -271,7 +271,7 @@ static INLINE uint64_t read_dr6()
static INLINE void write_dr6(uint64_t val) static INLINE void write_dr6(uint64_t val)
{ {
asm volatile("movq %0, %%dr6" __asm__ volatile("movq %0, %%dr6"
: :
: "r" (val)); : "r" (val));
} }
@ -280,7 +280,7 @@ static INLINE uint64_t read_dr7()
{ {
uint64_t val; uint64_t val;
asm volatile("movq %%dr7, %0" __asm__ volatile("movq %%dr7, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -288,7 +288,7 @@ static INLINE uint64_t read_dr7()
static INLINE void write_dr7(uint64_t val) static INLINE void write_dr7(uint64_t val)
{ {
asm volatile("movq %0, %%dr7" __asm__ volatile("movq %0, %%dr7"
: :
: "r" (val)); : "r" (val));
} }
@ -301,7 +301,7 @@ static INLINE uint16_t read_ds()
{ {
uint16_t val; uint16_t val;
asm volatile("movw %%ds, %0" __asm__ volatile("movw %%ds, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -309,7 +309,7 @@ static INLINE uint16_t read_ds()
static INLINE void write_ds(uint16_t val) static INLINE void write_ds(uint16_t val)
{ {
asm volatile("movw %0, %%ds" __asm__ volatile("movw %0, %%ds"
: :
: "r" (val)); : "r" (val));
} }
@ -318,7 +318,7 @@ static INLINE uint16_t read_es()
{ {
uint16_t val; uint16_t val;
asm volatile("movw %%es, %0" __asm__ volatile("movw %%es, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -326,7 +326,7 @@ static INLINE uint16_t read_es()
static INLINE void write_es(uint16_t val) static INLINE void write_es(uint16_t val)
{ {
asm volatile("movw %0, %%es" __asm__ volatile("movw %0, %%es"
: :
: "r" (val)); : "r" (val));
} }
@ -335,7 +335,7 @@ static INLINE uint16_t read_fs()
{ {
uint16_t val; uint16_t val;
asm volatile("movw %%fs, %0" __asm__ volatile("movw %%fs, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -343,7 +343,7 @@ static INLINE uint16_t read_fs()
static INLINE void write_fs(uint16_t val) static INLINE void write_fs(uint16_t val)
{ {
asm volatile("movw %0, %%fs" __asm__ volatile("movw %0, %%fs"
: :
: "r" (val)); : "r" (val));
} }
@ -352,7 +352,7 @@ static INLINE uint16_t read_gs()
{ {
uint16_t val; uint16_t val;
asm volatile("movw %%gs, %0" __asm__ volatile("movw %%gs, %0"
: "=r" (val)); : "=r" (val));
return val; return val;
@ -360,7 +360,7 @@ static INLINE uint16_t read_gs()
static INLINE void write_gs(uint16_t val) static INLINE void write_gs(uint16_t val)
{ {
asm volatile("movw %0, %%gs" __asm__ volatile("movw %0, %%gs"
: :
: "r" (val)); : "r" (val));
} }
@ -371,12 +371,12 @@ static INLINE void write_gs(uint16_t val)
static INLINE void clts() static INLINE void clts()
{ {
asm volatile("clts"); __asm__ volatile("clts");
} }
static INLINE void fxsave(struct XSAVEArea *xsa) static INLINE void fxsave(struct XSAVEArea *xsa)
{ {
asm volatile("fxsave %0" __asm__ volatile("fxsave %0"
: "=m" (*xsa) : "=m" (*xsa)
: :
: "memory"); : "memory");
@ -385,7 +385,7 @@ static INLINE void fxsave(struct XSAVEArea *xsa)
// XXX: Need to fix AMD Bug // XXX: Need to fix AMD Bug
static INLINE void fxrstor(struct XSAVEArea *xsa) static INLINE void fxrstor(struct XSAVEArea *xsa)
{ {
asm volatile("fxrstor %0" __asm__ volatile("fxrstor %0"
: :
: "m" (*xsa) : "m" (*xsa)
: "memory"); : "memory");
@ -396,7 +396,7 @@ static INLINE void xsave(struct XSAVEArea *xsa, uint64_t mask)
uint32_t lo = (uint32_t)mask; uint32_t lo = (uint32_t)mask;
uint32_t hi = (uint32_t)(mask >> 32); uint32_t hi = (uint32_t)(mask >> 32);
asm volatile("xsave %0" __asm__ volatile("xsave %0"
: "=m" (*xsa) : "=m" (*xsa)
: "a" (lo), "d" (hi) : "a" (lo), "d" (hi)
: "memory"); : "memory");
@ -407,7 +407,7 @@ static INLINE void xsaveopt(struct XSAVEArea *xsa, uint64_t mask)
uint32_t lo = (uint32_t)mask; uint32_t lo = (uint32_t)mask;
uint32_t hi = (uint32_t)(mask >> 32); uint32_t hi = (uint32_t)(mask >> 32);
asm volatile("xsaveopt %0" __asm__ volatile("xsaveopt %0"
: "=m" (*xsa) : "=m" (*xsa)
: "a" (lo), "d" (hi) : "a" (lo), "d" (hi)
: "memory"); : "memory");
@ -418,7 +418,7 @@ static INLINE void xrstor(struct XSAVEArea *xsa, uint64_t mask)
uint32_t lo = (uint32_t)mask; uint32_t lo = (uint32_t)mask;
uint32_t hi = (uint32_t)(mask >> 32); uint32_t hi = (uint32_t)(mask >> 32);
asm volatile("xrstor %0" __asm__ volatile("xrstor %0"
: :
: "m" (*xsa), "a" (lo), "d" (hi) : "m" (*xsa), "a" (lo), "d" (hi)
: "memory"); : "memory");
@ -430,21 +430,21 @@ static INLINE void xrstor(struct XSAVEArea *xsa, uint64_t mask)
static INLINE void outb(uint16_t port, uint8_t data) static INLINE void outb(uint16_t port, uint8_t data)
{ {
asm volatile("outb %0, %1" __asm__ volatile("outb %0, %1"
: :
: "a" (data), "d" (port)); : "a" (data), "d" (port));
} }
static INLINE void outw(uint16_t port, uint16_t data) static INLINE void outw(uint16_t port, uint16_t data)
{ {
asm volatile("outw %0, %1" __asm__ volatile("outw %0, %1"
: :
: "a" (data), "d" (port)); : "a" (data), "d" (port));
} }
static INLINE void outl(uint16_t port, uint32_t data) static INLINE void outl(uint16_t port, uint32_t data)
{ {
asm volatile("outl %0, %1" __asm__ volatile("outl %0, %1"
: :
: "a" (data), "d" (port)); : "a" (data), "d" (port));
} }
@ -453,7 +453,7 @@ static INLINE uint8_t inb(uint16_t port)
{ {
uint8_t data; uint8_t data;
asm volatile("inb %1, %0" __asm__ volatile("inb %1, %0"
: "=a" (data) : "=a" (data)
:"d" (port)); :"d" (port));
@ -464,7 +464,7 @@ static INLINE uint16_t inw(uint16_t port)
{ {
uint16_t data; uint16_t data;
asm volatile("inw %1, %0" __asm__ volatile("inw %1, %0"
: "=a" (data) : "=a" (data)
:"d" (port)); :"d" (port));
@ -475,7 +475,7 @@ static INLINE uint32_t inl(uint16_t port)
{ {
uint32_t data; uint32_t data;
asm volatile("inl %1, %0" __asm__ volatile("inl %1, %0"
: "=a" (data) : "=a" (data)
:"d" (port)); :"d" (port));

View File

@ -1,4 +1,5 @@
#include <machine/gic.h> #include <machine/gic.h>
#include "include/pmap.h"
#include "sys/cdefs.h" #include "sys/cdefs.h"
#include "errno.h" #include "errno.h"
#include <sys/kassert.h> #include <sys/kassert.h>
@ -220,8 +221,8 @@ gic_addr_init(void)
{ {
uint32_t index = 0; uint32_t index = 0;
gic.gic_dist = (void*)DIST_BASE_ADDR; gic.gic_dist = (void*)DEVPA2VA(DIST_BASE_ADDR);
gic.gic_rdist = (void*)REDIST_BASE_ADDR; gic.gic_rdist = (void*)DEVPA2VA(REDIST_BASE_ADDR);
while((gic.gic_rdist[index].lpis.GICR_TYPER & (1<<4)) == 0) // Keep incrementing until GICR_TYPER.Last reports no more RDs in block while((gic.gic_rdist[index].lpis.GICR_TYPER & (1<<4)) == 0) // Keep incrementing until GICR_TYPER.Last reports no more RDs in block
{ {

View File

@ -7,7 +7,7 @@ atomic_swap_uint32(volatile uint32_t *dst, uint32_t newval)
{ {
uint32_t retval; uint32_t retval;
asm volatile(".arch_extension lse; swp %w2, %w0, [%w1]; .arch_extension nolse;" __asm__ volatile(".arch_extension lse; swp %w2, %w0, [%w1]; .arch_extension nolse;"
: "=r" (retval) : "=r" (retval)
: "r" (dst), "r" (newval) : "r" (dst), "r" (newval)
: "memory"); : "memory");
@ -20,7 +20,7 @@ atomic_swap_uint64(volatile uint64_t *dst, uint64_t newval)
{ {
uint64_t retval; uint64_t retval;
asm volatile(".arch_extension lse; swp %2, %0, [%1]; .arch_extension nolse;" __asm__ volatile(".arch_extension lse; swp %2, %0, [%1]; .arch_extension nolse;"
: "=r" (retval) : "=r" (retval)
: "r" (dst), "r" (newval) : "r" (dst), "r" (newval)
: "memory"); : "memory");

View File

@ -3,8 +3,8 @@
* All rights reserved. * All rights reserved.
*/ */
#ifndef __AMD64_H__ #ifndef __ARM64_H__
#define __AMD64_H__ #define __ARM64_H__
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -12,23 +12,19 @@
* Page Tables * Page Tables
*/ */
#define PGNUMMASK 0xFFFFFFFFFFFFF000ULL // #define PGNUMMASK 0xFFFFFFFFFFFFF000ULL
#define PGIDXSHIFT 9 // #define PGIDXSHIFT 9
#define PGIDXMASK (512 - 1) // #define PGIDXMASK (512 - 1)
#define PGSHIFT 12 #define PGSHIFT 14
#define PGSIZE (1 << PGSHIFT) #define PGSIZE (1 << PGSHIFT)
#define PGMASK (PGSIZE - 1) #define PGMASK (PGSIZE - 1)
#define LARGE_PGSHIFT 21 #define LARGE_PGSHIFT 26
#define LARGE_PGSIZE (1 << LARGE_PGSHIFT) #define LARGE_PGSIZE (1 << LARGE_PGSHIFT)
#define LARGE_PGMASK (LARGE_PGSIZE - 1) #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 ROUNDUP_PGSIZE(x) (((x) + LARGE_PGSIZE - 1) & ~LARGE_PGMASK)
#define ROUNDDOWN_PGSIZE(x) ((x) & ~LARGE_PGMASK) #define ROUNDDOWN_PGSIZE(x) ((x) & ~LARGE_PGMASK)

View File

@ -8,27 +8,27 @@
static INLINE void enable_interrupts() static INLINE void enable_interrupts()
{ {
asm volatile("msr daifclr, #(0x0002)\n"); __asm__ volatile("msr daifclr, #(0x0002)\n");
} }
static INLINE void disable_interrupts() static INLINE void disable_interrupts()
{ {
asm volatile("msr daifset, #(0x0002)\n"); __asm__ volatile("msr daifset, #(0x0002)\n");
} }
static INLINE void hlt() static INLINE void hlt()
{ {
asm volatile("wfi"); __asm__ volatile("wfi");
} }
static INLINE void pause() static INLINE void pause()
{ {
asm volatile("yield"); __asm__ volatile("yield");
} }
static INLINE void breakpoint() static INLINE void breakpoint()
{ {
asm volatile("brk #0"); __asm__ volatile("brk #0");
} }
#endif /* __ARM64OP_H__ */ #endif /* __ARM64OP_H__ */

56
sys/arm64/include/metal.h Normal file
View File

@ -0,0 +1,56 @@
#pragma once
#include <machine/metalp.h>
#include <sys/cdefs.h>
#define MCODE ALIGNED(16) __attribute__((section("mcode")))
#define MDATA __attribute__((section("mdata")))
#define METAL_REG_MSTK (METAL_REG_MG8)
#if defined(DECL_MROUTINE)
#undef DECL_MROUTINE
#define DECL_MROUTINE(name) void MCODE name(void)
#endif
#if defined(IMPL_MROUTINE)
#undef IMPL_MROUTINE
#define IMPL_MROUTINE(name, exit_flag) void MCODE _ ## name ## _impl(void); \
__asm__ ( \
".section \"mcode\";" \
".globl " _METAL_STR(name) ";" \
".balign 16;" \
_METAL_STR(name) ":;" \
METAL_RMR_GAS(METAL_REG_MSTK, AARCH_REG_X0) \
"mov x1, sp;" \
"str x1, [x0, #-16]!;" \
"mov sp, x0;" \
"mov x0, xzr;" \
"ldr x0,=_" _METAL_STR(name) "_impl;" \
"blr x0;" \
"ldr x0, [sp], #16;" \
"mov sp, x0;" \
METAL_MEXIT_GAS(exit_flag) \
); \
void MCODE _ ## name ## _impl(void)
#endif
#define IMPL_SHORT_MROUTINE(name, exit_flag) void MCODE _ ## name ## _impl(void); \
__asm__ ( \
".section \"mcode\";" \
".globl " _METAL_STR(name) ";" \
".balign 16;" \
_METAL_STR(name) ":;" \
"mov x0, xzr;" \
"ldr x0,=_" _METAL_STR(name) "_impl;" \
"blr x0;" \
METAL_MEXIT_GAS(exit_flag) \
); \
void MCODE _ ## name ## _impl(void)
#define DECL_MVAR(type, name) type MDATA name
#define DECL_MVAR_ALIGNED(type, name, align) type ALIGNED(align) MDATA name
#define METAL_REG_MPTB_DMAP (METAL_REG_MG6)
#define METAL_REG_MPTB_XMEM (METAL_REG_MG7)
#define METAL_REG_MPTB_USER (METAL_REG_MG5)

384
sys/arm64/include/metalp.h Normal file
View File

@ -0,0 +1,384 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#define AARCH_REG_X0 (0)
#define AARCH_REG_X1 (1)
#define AARCH_REG_X2 (2)
#define AARCH_REG_X3 (3)
#define AARCH_REG_X4 (4)
#define AARCH_REG_X5 (5)
#define AARCH_REG_X6 (6)
#define AARCH_REG_X7 (7)
#define AARCH_REG_X8 (8)
#define AARCH_REG_X9 (9)
#define AARCH_REG_X10 (10)
#define AARCH_REG_X11 (11)
#define AARCH_REG_X12 (12)
#define AARCH_REG_X13 (13)
#define AARCH_REG_X14 (14)
#define AARCH_REG_X15 (15)
#define AARCH_REG_X16 (16)
#define AARCH_REG_X17 (17)
#define AARCH_REG_X18 (18)
#define AARCH_REG_X19 (19)
#define AARCH_REG_X20 (20)
#define AARCH_REG_X21 (21)
#define AARCH_REG_X22 (22)
#define AARCH_REG_X23 (23)
#define AARCH_REG_X24 (24)
#define AARCH_REG_X25 (25)
#define AARCH_REG_X26 (26)
#define AARCH_REG_X27 (27)
#define AARCH_REG_X28 (28)
#define AARCH_REG_X29 (29)
#define AARCH_REG_X30 (30)
#define AARCH_REG_X31 (31)
#define METAL_REG_MO0 (0)
#define METAL_REG_MO1 (1)
#define METAL_REG_MO2 (2)
#define METAL_REG_MO3 (3)
#define METAL_REG_MO4 (4)
#define METAL_REG_MO5 (5)
#define METAL_REG_MR0 (6)
#define METAL_REG_MR1 (7)
#define METAL_REG_MR2 (8)
#define METAL_REG_MR3 (9)
#define METAL_REG_MI0 (10)
#define METAL_REG_MI1 (11)
#define METAL_REG_MI2 (12)
#define METAL_REG_MI3 (13)
#define METAL_REG_MI4 (14)
#define METAL_REG_MI5 (15)
#define METAL_REG_MLR (METAL_REG_MI5)
#define METAL_REG_MIR0 (METAL_REG_MI0)
#define METAL_REG_MIR1 (METAL_REG_MI1)
#define METAL_REG_MIR2 (METAL_REG_MI2)
#define METAL_REG_MER0 (METAL_REG_MI0)
#define METAL_REG_MER1 (METAL_REG_MI1)
#define METAL_REG_MER2 (METAL_REG_MI2)
#define METAL_REG_MSPSR (METAL_REG_MI3)
#define METAL_REG_MSR (16)
#define METAL_REG_MBR (17)
#define METAL_REG_MIB (18)
#define METAL_REG_MEB (19)
#define METAL_REG_MTP (20)
#define METAL_REG_MG5 (21)
#define METAL_REG_MG6 (22)
#define METAL_REG_MG7 (23)
#define METAL_REG_MG8 (24)
#define METAL_REG_MG9 (25)
#define METAL_REG_MG10 (26)
#define METAL_REG_MG11 (27)
#define METAL_REG_MG12 (28)
#define METAL_REG_MG13 (29)
#define METAL_REG_MG14 (30)
#define METAL_REG_MG15 (31)
#define _METAL_STR(x) #x
#define METAL_STR(x) _METAL_STR(x)
#define _METAL_GAS_ENCODE(x) ".word " METAL_STR(x) ";"
#define METAL_GAS_ENCODE(x) _METAL_GAS_ENCODE(x)
// metal insts defs
#define METAL_WMR_ENCODING(mreg, greg) (0xd61f2C00 | ((mreg) << 5) | ((greg) << 0))
#define METAL_WMR_GAS(mreg, greg) METAL_GAS_ENCODE(METAL_WMR_ENCODING(mreg, greg))
#define METAL_WMR(reg, var) do { __asm__ volatile (\
"mov x0, %x0;" \
METAL_WMR_GAS(reg, AARCH_REG_X0)\
: \
: "r" (var)\
: "x0" \
); } while(0)
#define METAL_RMR_ENCODING(mreg, greg) (0xd61f2800 | ((mreg) << 5) | ((greg) << 0))
#define METAL_RMR_GAS(mreg, greg) METAL_GAS_ENCODE(METAL_RMR_ENCODING(mreg,greg))
#define METAL_RMR(reg, var) do { \
__asm__ volatile ( \
METAL_RMR_GAS(reg, AARCH_REG_X0) \
"mov %x0, x0;"\
: "=r" (var) \
: \
: "x0" \
); } while(0)
//
// we need to preserve the stack pointer between mroutine calls
// mroutines never return values using stacks
// and since "mexit"s always occur before "return"s
// the function epilogue is not run before returning
// which may destroy the stack if local variables are defined
//
// we do this using the mroutine stub function to wrap mroutine calls
//
#define METAL_MENTER_ENCODING(mroutine) (0xd61f2000 | ((mroutine) << 0))
#define METAL_MENTER_GAS(mroutine) METAL_GAS_ENCODE(METAL_MENTER_ENCODING(mroutine))
#define METAL_MENTER(mroutine) do { \
__asm__ volatile ( \
METAL_MENTER_GAS(mroutine) \
: \
: \
: \
); \
} while(0)
#define METAL_MEXIT_ENCODING(flags) (0xd61f2400 | ((flags) << 0))
#define METAL_MEXIT_GAS(flags) METAL_GAS_ENCODE(METAL_MEXIT_ENCODING(flags))
#define METAL_MEXIT(flags) do { \
__asm__ volatile ( \
METAL_MEXIT_GAS(flags) \
: \
: \
: \
); } while(0)
#define MEXIT_FLAG_IIM (1 << 1) // this mexit masks instruction intercept for the instruction returned to
#define MEXIT_FLAG_RFI (1 << 0) // this mexit is a return from intercept (also restores CPSR from MSPSR)
// do not provide C version of RAR/WAR for the current bank
// can't decide which GP register to use as temp
#define METAL_RAR_ENCODING(idxmreg, dstmreg) (0xd61f3000 | ((idxmreg) << 5) | ((dstmreg) << 0))
#define METAL_RAR_GAS(idxmreg, dstmreg) METAL_GAS_ENCODE(METAL_RAR_ENCODING(idxmreg, dstmreg))
#define METAL_WAR_ENCODING(idxmreg, srcmreg) (0xd61f3400 | ((idxmreg) << 5) | ((srcmreg) << 0))
#define METAL_WAR_GAS(idxmreg, dstmreg) METAL_GAS_ENCODE(METAL_WAR_ENCODING(idxmreg, dstmreg))
#define METAL_RPR_ENCODING(idxmreg, dstmreg) (0xd61f4000 | ((idxmreg) << 5) | ((dstmreg) << 0))
#define METAL_RPR_GAS(idxmreg, dstmreg) METAL_GAS_ENCODE(METAL_RPR_ENCODING(idxmreg, dstmreg))
#define METAL_RPR(idxvar, var) do { __asm__ volatile (\
METAL_RMR_GAS(METAL_REG_MR0, AARCH_REG_X1) \
METAL_RMR_GAS(METAL_REG_MR1, AARCH_REG_X2) \
\
"mov x0, %x1;" \
METAL_WMR_GAS(METAL_REG_MR0, AARCH_REG_X0) \
METAL_RPR_GAS(METAL_REG_MR0, METAL_REG_MR1) \
METAL_RMR_GAS(METAL_REG_MR1, AARCH_REG_X0) \
"mov %x0, x0;" \
\
METAL_WMR_GAS(METAL_REG_MR0, AARCH_REG_X1) \
METAL_WMR_GAS(METAL_REG_MR1, AARCH_REG_X2) \
: "=r" (var) \
: "r" (idxvar)\
: "x0", "x1", "x2" \
); } while(0)
#define METAL_WPR_ENCODING(idxmreg, srcmreg) (0xd61f4400 | ((idxmreg) << 5) | ((srcmreg) << 0))
#define METAL_WPR_GAS(idxmreg, srcmreg) METAL_GAS_ENCODE(METAL_WPR_ENCODING(idxmreg, srcmreg))
#define METAL_WPR(idxvar, var) do { __asm__ volatile (\
METAL_RMR_GAS(METAL_REG_MR0, AARCH_REG_X1) \
METAL_RMR_GAS(METAL_REG_MR1, AARCH_REG_X2) \
\
"mov x0, %x0;" \
METAL_WMR_GAS(METAL_REG_MR0, AARCH_REG_X0) \
"mov x0, %x1;" \
METAL_WMR_GAS(METAL_REG_MR1, AARCH_REG_X0) \
\
METAL_WPR_GAS(METAL_REG_MR0, METAL_REG_MR1) \
\
METAL_WMR_GAS(METAL_REG_MR0, AARCH_REG_X1) \
METAL_WMR_GAS(METAL_REG_MR1, AARCH_REG_X2) \
: \
: "r" (idxvar), "r" (var) \
: "x0", "x1", "x2" \
); } while(0)
#define METAL_MCLI_ENCODING (0xd61f3800)
#define METAL_MCLI_GAS METAL_GAS_ENCODE(METAL_MCLI_ENCODING)
#define METAL_MCLI do { \
__asm__ volatile ( \
METAL_MCLI_GAS \
: \
: \
: \
); } while(0)
#define METAL_MSTI_ENCODING (0xd61f3C00)
#define METAL_MSTI_GAS METAL_GAS_ENCODE(METAL_MSTI_ENCODING)
#define METAL_MSTI do { \
__asm__ volatile ( \
METAL_MSTI_GAS \
: \
: \
: \
); } while(0)
#define _METAL_WTLB_SHIFT_RM (0)
#define _METAL_WTLB_SHIFT_RN (5)
#define _METAL_WTLB_SHIFT_RL (10)
#define _METAL_WTLB_ENCODING(rl, rn, rm) ".word " METAL_STR(0xd63f8000 | (rl << _METAL_WTLB_SHIFT_RL) | (rn << _METAL_WTLB_SHIFT_RN) | (rm << _METAL_WTLB_SHIFT_RM))
#define METAL_WTLB(descreg, inforeg, vaddrreg) do { __asm__ volatile (\
_METAL_WTLB_ENCODING(descreg, vaddrreg, inforeg)); \
} while (0)
#define _METAL_RTLB_SHIFT_RM (0)
#define _METAL_RTLB_SHIFT_RN (5)
#define _METAL_RTLB_SHIFT_RL (10)
#define _METAL_RTLB_ENCODING(rl, rn, rm) ".word " METAL_STR(0xd61f8000 | (rl << _METAL_RTLB_SHIFT_RL) | (rn << _METAL_RTLB_SHIFT_RN) | (rm << _METAL_RTLB_SHIFT_RM))
#define METAL_RTLB(descreg, inforeg, vaddrreg) do { __asm__ volatile (\
_METAL_RTLB_ENCODING(descreg, vaddrreg, inforeg)); \
} while (0)
#define METAL_PMEMOP_MODE_NORMAL (0)
#define METAL_PMEMOP_MODE_PRE (1)
#define METAL_PMEMOP_MODE_POST (2)
// PSTR
#define _METAL_PSTR_TEMPLATE(var, paddr, cmd) do { __asm__ volatile (\
"mov x0, %x0;" \
"mov x1, %x1;" \
"mov x2, #0;" \
cmd \
: \
: "r" (var), "r" (paddr) \
: "x0", "x1", "x2" \
); } while (0)
#define METAL_PSTRR8_ENCODING(dReg, bReg, oReg) (0x8c400000 | ((dReg) << 0) | ((bReg) << 5) | ((oReg) << 10))
#define METAL_PSTRR8_GAS(dReg, bReg, oReg) METAL_GAS_ENCODE(METAL_PSTRR8_ENCODING(dReg, bReg, oReg))
#define METAL_PSTR8(var, paddr) _METAL_PSTR_TEMPLATE(var, paddr, METAL_PSTRR8_GAS(AARCH_REG_X0, AARCH_REG_X1, AARCH_REG_X2))
#define METAL_PSTRR16_ENCODING(dReg, bReg, oReg) (0x8cc00000 | ((dReg) << 0) | ((bReg) << 5) | ((oReg) << 10))
#define METAL_PSTRR16_GAS(dReg, bReg, oReg) METAL_GAS_ENCODE(METAL_PSTRR16_ENCODING(dReg, bReg, oReg))
#define METAL_PSTR16(var, paddr) _METAL_PSTR_TEMPLATE(var, paddr, METAL_PSTRR16_GAS(AARCH_REG_X0, AARCH_REG_X1, AARCH_REG_X2))
#define METAL_PSTRR32_ENCODING(dReg, bReg, oReg) (0x8d400000 | ((dReg) << 0) | ((bReg) << 5) | ((oReg) << 10))
#define METAL_PSTRR32_GAS(dReg, bReg, oReg) METAL_GAS_ENCODE(METAL_PSTRR32_ENCODING(dReg, bReg, oReg))
#define METAL_PSTR32(var, paddr) _METAL_PSTR_TEMPLATE(var, paddr, METAL_PSTRR32_GAS(AARCH_REG_X0, AARCH_REG_X1, AARCH_REG_X2))
#define METAL_PSTRR64_ENCODING(dReg, bReg, oReg) (0x8dc00000 | ((dReg) << 0) | ((bReg) << 5) | ((oReg) << 10))
#define METAL_PSTRR64_GAS(dReg, bReg, oReg) METAL_GAS_ENCODE(METAL_PSTRR64_ENCODING(dReg, bReg, oReg))
#define METAL_PSTR64(var, paddr) _METAL_PSTR_TEMPLATE(var, paddr, METAL_PSTRR64_GAS(AARCH_REG_X0, AARCH_REG_X1, AARCH_REG_X2))
// PLDR
#define _METAL_PLDR_TEMPLATE(var, paddr, cmd) do { __asm__ volatile (\
"mov x1, %x1;" \
"mov x2, #0;" \
cmd \
"mov %x0, x0;" \
: "=r" (var) \
: "r" (paddr) \
: "x0", "x1", "x2" \
); } while (0)
#define METAL_PLDRR8_ENCODING(dReg, bReg, oReg) (0x8c000000 | ((dReg) << 0) | ((bReg) << 5) | ((oReg) << 10))
#define METAL_PLDRR8_GAS(dReg, bReg, oReg) METAL_GAS_ENCODE(METAL_PLDRR8_ENCODING(dReg, bReg, oReg))
#define METAL_PLDR8(var, paddr) _METAL_PLDR_TEMPLATE(var, paddr, METAL_PLDRR8_GAS(AARCH_REG_X0, AARCH_REG_X1, AARCH_REG_X2))
#define METAL_PLDRR16_ENCODING(dReg, bReg, oReg) (0x8c800000 | ((dReg) << 0) | ((bReg) << 5) | ((oReg) << 10))
#define METAL_PLDRR16_GAS(dReg, bReg, oReg) METAL_GAS_ENCODE(METAL_PLDRR16_ENCODING(dReg, bReg, oReg))
#define METAL_PLDR16(var, paddr) _METAL_PLDR_TEMPLATE(var, paddr, METAL_PLDRR16_GAS(AARCH_REG_X0, AARCH_REG_X1, AARCH_REG_X2))
#define METAL_PLDRR32_ENCODING(dReg, bReg, oReg) (0x8d000000 | ((dReg) << 0) | ((bReg) << 5) | ((oReg) << 10))
#define METAL_PLDRR32_GAS(dReg, bReg, oReg) METAL_GAS_ENCODE(METAL_PLDRR32_ENCODING(dReg, bReg, oReg))
#define METAL_PLDR32(var, paddr) _METAL_PLDR_TEMPLATE(var, paddr, METAL_PLDRR32_GAS(AARCH_REG_X0, AARCH_REG_X1, AARCH_REG_X2))
#define METAL_PLDRR64_ENCODING(dReg, bReg, oReg) (0x8d800000 | ((dReg) << 0) | ((bReg) << 5) | ((oReg) << 10))
#define METAL_PLDRR64_GAS(dReg, bReg, oReg) METAL_GAS_ENCODE(METAL_PLDRR64_ENCODING(dReg, bReg, oReg))
#define METAL_PLDR64(var, paddr) _METAL_PLDR_TEMPLATE(var, paddr, METAL_PLDRR64_GAS(AARCH_REG_X0, AARCH_REG_X1, AARCH_REG_X2))
// Mroutine helpers
// can get MI0-MI4, MI5 is link reg
// MR23 = link register
#define METAL_MROUTINE_GETARG(idx, var) do { \
_Static_assert(idx < (METAL_REG_MI4 - METAL_REG_MI0)); \
METAL_RMR(METAL_REG_MI0 + idx, var); \
} while(0)
// can set MO0-MO4, MO5 is Link Reg
// MR7 is link register
#define METAL_MROUTINE_SETARG(idx, var) do { \
_Static_assert(idx < (METAL_REG_MO4 - METAL_REG_MO0)); \
METAL_WMR(METAL_REG_MO0 + idx, var); \
} while(0)
// mroutine defs
#define METAL_MROUTINE_SETRET(idx, var) do { \
_Static_assert(idx < (METAL_REG_MI4 - METAL_REG_MI0)); \
METAL_WMR(METAL_REG_MI0 + idx, var); \
} while(0)
#define METAL_MROUTINE_GETRET(idx, var) do { \
_Static_assert(idx < (METAL_REG_MO4 - METAL_REG_MO0)); \
METAL_RMR(METAL_REG_MO0 + idx, var); \
} while(0)
#define DECL_MROUTINE(name) void __attribute__((aligned(16))) name(void)
#define IMPL_MROUTINE(name, exit_flag) void _ ## name ## _impl(void); \
__asm__ ( \
".globl " _METAL_STR(name) ";" \
".balign 16;" \
_METAL_STR(name) ":;" \
"bl _" _METAL_STR(name) "_impl;" \
METAL_MEXIT_GAS(exit_flag) \
); \
void _ ## name ## _impl(void)
// mroutine table defs
#define _MROUTINE_ENTRY_CTRL_MASK_VALID (1ul)
#define _MROUTINE_ENTRY_CTRL_MASK_ADDR (~((1ul << 4) - 1))
#define MROUTINE_ENTRY_MAKE(addr, valid) (((uintptr_t)addr & _MROUTINE_ENTRY_CTRL_MASK_ADDR) | (valid & _MROUTINE_ENTRY_CTRL_MASK_VALID))
typedef uint64_t mroutine_entry;
#define MROUTINE_TABLE_MAX_ENTRY_NUM (256)
struct mroutine_table {
mroutine_entry entries[MROUTINE_TABLE_MAX_ENTRY_NUM];
};
// inst intercept defs
#define INST_INTERCEPT_TABLE_MAX_ENTRY_NUM (64)
struct inst_intercept_entry {
uint32_t inst;
uint32_t opmask;
uint32_t ctrl;
uint32_t mask0;
uint32_t mask1;
uint32_t mask2;
};
//_Static_assert(sizeof(struct inst_intercept_entry) == 6 * sizeof(uint32_t));
#define INST_INTERCEPT_MAKE_CTRL(mroutine, post, valid) ((mroutine) & 0xff | ((post) & 1) << 30 | ((valid) & 1) << 31)
struct inst_intercept_table {
struct inst_intercept_entry entries[INST_INTERCEPT_TABLE_MAX_ENTRY_NUM];
};
// exc intercept defs
#define EXC_INTERCEPT_TABLE_MAX_ENTRY_NUM (64)
struct exc_intercept_entry {
uint32_t esrbits;
uint32_t esrmask;
uint32_t ctrl;
};
#define EXC_INTERCEPT_MODE_SYNC (0)
#define EXC_INTERCEPT_MODE_IRQ (1)
#define EXC_INTERCEPT_MODE_FIQ (2)
#define EXC_INTERCEPT_MODE_SERROR (3)
#define EXC_INTERCEPT_MAKE_CTRL(mroutine, mode, valid) ((mroutine) & 0xff | ((mode) & 0b11) << 8 | ((valid) & 1) << 31)
struct exc_intercept_table {
struct exc_intercept_entry entries[EXC_INTERCEPT_TABLE_MAX_ENTRY_NUM];
};
// metal register defs
typedef uint64_t regval_t;
typedef regval_t msr_t;
#define METAL_MSR_MASK_INIT (1ul << 63)
#define METAL_MSR_MASK_II (1ul << 62)
#define METAL_MSR_MASK_IM (1ul << 61)
#define METAL_MSR_MASK_LV (0xfful)
#define METAL_MSR_MASK_EI (1ul << 60)
#define METAL_MSR_MASK_PD (1ul << 59)
#ifdef __cplusplus
}
#endif

36
sys/arm64/include/mrt.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include <machine/metal.h>
DECL_MROUTINE(mrt_init);
#define MRT_INIT_IDX (1)
DECL_MROUTINE(mrt_pf_handler);
#define MRT_PF_HANDLER_IDX (2)
DECL_MROUTINE(mrt_dummy);
//
// int mrt_set_mptb(int ptbidx, regval_t val);
//
DECL_MROUTINE(mrt_set_mptb);
#define MRT_SET_MPTB_IDX (3)
#define MRT_SET_MPTB_USER (0)
#define MRT_SET_MPTB_DMAP (1)
#define MRT_SET_MPTB_XMEM (2)
#define MRT_SET_MPTB_ARG_IDX (0)
#define MRT_SET_MPTB_ARG_PTB (1)
#define MRT_SET_MPTB_RET_STATUS (0)
//
// void mrt_set_mtp(regval_t mtp);
//
DECL_MROUTINE(mrt_set_mtp);
#define MRT_SET_MTP_IDX (4)
#define MRT_SET_MTP_ARG_MTP (0)
extern DECL_MVAR(struct mroutine_table, mtl_mrt_tbl);
extern DECL_MVAR(struct exc_intercept_table, mtl_exc_tbl);
void mtl_init(void);

107
sys/arm64/include/paging.h Normal file
View File

@ -0,0 +1,107 @@
#pragma once
#include <machine/pmap.h>
#include <sys/types.h>
// 2048 buckets * 8 bytes / bucket = 16KB per page tbl = smallest page size
#define VM_PTBUCKETS (2048)
// 1GB page ident map region
#define REGION_DMAP_PGSHIFT (30)
// 16K page userspace
#define REGION_USER_PGSHIFT (14)
// 16K page XMEM region
#define REGION_XMEM_PGSHIFT (14)
//
// Page Table Pointer (points to a list of struct vmpd)
//
struct vmpte {
paddr_t first;
};
_Static_assert(sizeof(struct vmpte) == 8);
struct vmpt {
struct vmpte entries[VM_PTBUCKETS];
};
_Static_assert(sizeof(struct vmpt) == VM_PTBUCKETS * sizeof(struct vmpte));
//
// Page Table Entry (must be 8 bytes aligned)
//
#define VMPD_ATTR_P (0x1ul)
#define VMPD_ATTR_DEV (0x2ul)
#define VMPD_ATTR_AO_MASK (0xFul)
#define VMPD_ATTR_AO_SHIFT (0x4ul)
//
// AP with 2 ELs:
// EL1 EL0
// - 00 RW /
// - 01 RW RW
// - 10 RO /
// - 11 RO RO
//
// MTP:
// 0-1: ap
// 2: xn
// 3: rn
//
// AO REG for Kernel:
// entry 0 (kernel RO): RO 0b0011
// entry 1 (kernel RW): RW 0b0001
// entry 2 (user RO): RW 0b0001
// entry 3 (user RW): RW 0b0001
//
// AO REG for User:
// entry 0 (kernel RO): NA 0b0010
// entry 1 (kernel RW): NA 0b0000
// entry 2 (user RO): RO 0b0011
// entry 3 (user RW): RW 0b0010
//
#define VMPD_ATTR_AO_MAKE(x) (((x) & VMPD_ATTR_AO_MASK) << VMPD_ATTR_AO_SHIFT)
#define VMPD_ATTR_AO_GET(x) (((x) >> VMPD_ATTR_AO_SHIFT) & VMPD_ATTR_AO_MASK)
#define VMPD_ATTR_AO_KRO (VMPD_ATTR_AO_MAKE(0ull))
#define VMPD_ATTR_AO_KRW (VMPD_ATTR_AO_MAKE(1ull))
#define VMPD_ATTR_AO_URO (VMPD_ATTR_AO_MAKE(2ull))
#define VMPD_ATTR_AO_URW (VMPD_ATTR_AO_MAKE(3ull))
// #define VMPD_ATTR_CA_MAKE(x) (((x) & VMPD_ATTR_CA_MASK) << VMPD_ATTR_CA_SHIFT)
// #define VMPD_ATTR_CA_GET(x) (((x) >> VMPD_ATTR_CA_SHIFT) & VMPD_ATTR_CA_MASK)
// #define VMPD_ATTR_CA_NORMAL (VMPD_ATTR_CA_MAKE(0ull))
// #define VMPD_ATTR_CA_DEVICE (VMPD_ATTR_CA_MAKE(1ull))
#define MTP_KERNEL (0b0011 | (0b0001 << 4) | (0b0001 << 8) | (0b0001 << 12))
#define MTP_USER (0b0010 | (0b0000 << 4) | (0b0011 << 8) | (0b0010 << 12))
struct vmpd {
paddr_t next; // the next hppte in the list
paddr_t paddr; // the physical address of the VA
vaddr_t vaddr; // the corresponding virtual address
uint64_t attr; // the attributes of the page
};
_Static_assert(sizeof(struct vmpd) == 32);
static ALWAYS_INLINE inline uint64_t
vm_vahash(vaddr_t va)
{
return ((va) * (va+3)) % VM_PTBUCKETS;
}
static ALWAYS_INLINE inline uint64_t
vm_get_pfn(vaddr_t va, unsigned int pgshift)
{
return va >> pgshift;
}
static ALWAYS_INLINE inline uint64_t
vm_get_pgbase(vaddr_t va, unsigned int pgshift)
{
return va & ~((1ull << pgshift) - 1);
}
void paging_init();

View File

@ -2,6 +2,7 @@
#ifndef __PMAP_H__ #ifndef __PMAP_H__
#define __PMAP_H__ #define __PMAP_H__
#include <sys/types.h>
#include <machine/cpu.h> #include <machine/cpu.h>
/* /*
@ -38,14 +39,20 @@
#define MEM_USERSPACE_STKTOP (MEM_USERSPACE_STKBASE + MEM_USERSPACE_STKLEN) #define MEM_USERSPACE_STKTOP (MEM_USERSPACE_STKBASE + MEM_USERSPACE_STKLEN)
#define MEM_DIRECTMAP_BASE 0xFFFF800000000000ULL #define MEM_DIRECTMAP_BASE 0xFFFF800000000000ULL
#define MEM_DIRECTMAP_DEV_BASE (MEM_DIRECTMAP_BASE + MEM_DIRECTMAP_LEN / 2)
#define MEM_DIRECTMAP_LEN 0x0000010000000000ULL #define MEM_DIRECTMAP_LEN 0x0000010000000000ULL
#define MEM_DIRECTMAP_TOP (MEM_DIRECTMAP_BASE + MEM_DIRECTMAP_LEN)
#define MEM_XMAP_BASE 0xFFFF810000000000ULL #define MEM_XMAP_BASE 0xFFFF810000000000ULL
#define MEM_XMAP_LEN 0x0000002000000000ULL #define MEM_XMAP_LEN 0x0000002000000000ULL
#define MEM_XMAP_TOP (MEM_XMAP_BASE + MEM_XMAP_LEN)
#define PPN2DMVA(ppn) (((ppn) << PGSIZE) + MEM_DIRECTMAP_BASE) #define PPN2DMVA(ppn) (((ppn) << PGSIZE) + MEM_DIRECTMAP_BASE)
#define DMVA2PPN(dmva) (((dmva) - MEM_DIRECTMAP_BASE) >> PGSIZE) #define DMVA2PPN(dmva) (((uintptr_t)(dmva) - MEM_DIRECTMAP_BASE) >> PGSIZE)
#define DMVA2PA(dmva) ((dmva) - MEM_DIRECTMAP_BASE) #define DMVA2PA(dmva) ((uintptr_t)(dmva) - MEM_DIRECTMAP_BASE)
#define DMPA2VA(pa) ((pa) + MEM_DIRECTMAP_BASE) #define DMPA2VA(pa) ((uintptr_t)(pa) + MEM_DIRECTMAP_BASE)
#define DEVVA2PA(devva) ((uintptr_t)(devva) - MEM_DIRECTMAP_DEV_BASE)
#define DEVPA2VA(pa) ((uintptr_t)(pa) + MEM_DIRECTMAP_DEV_BASE)
#define VA2PA(va) PMap_Translate(PMap_CurrentAS(), va) #define VA2PA(va) PMap_Translate(PMap_CurrentAS(), va)
typedef struct AS typedef struct AS

View File

@ -21,8 +21,8 @@ SECTIONS
/* Read-only sections, merged into text segment: */ /* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", PROVIDE (__executable_start = SEGMENT_START("text-segment",
0xFFFF800000400000)); 0xFFFF800000400000));
. = SEGMENT_START("text-segment", 0xFFFF800080400000); . = SEGMENT_START("text-segment", 0xFFFF800000400000);
.text : AT(SEGMENT_START("text-segment", 0xFFFF800080400000) - 0xFFFF800000000000) .text : AT(SEGMENT_START("text-segment", 0xFFFF800000400000) - 0xFFFF800000000000)
{ {
*(.boot) *(.boot)
*(.text .stub .text.* .gnu.linkonce.t.*) *(.text .stub .text.* .gnu.linkonce.t.*)
@ -236,5 +236,17 @@ SECTIONS
/* DWARF Extension. */ /* DWARF Extension. */
.debug_macro 0 : { *(.debug_macro) } .debug_macro 0 : { *(.debug_macro) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/* Metal RAM */
. = 0xC0000000;
.mdata : AT(0xC0000000)
{
*(mdata)
}
.mcode :
{
*(mcode)
}
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
} }

View File

@ -120,27 +120,22 @@ _el1_entry:
#define BOOT_PGD_ATTR (PD_TABLE) #define BOOT_PGD_ATTR (PD_TABLE)
#define BOOT_PUD_ATTR (PD_ACCESS | (MAIR_IDX_NORMAL_CACHEABLE << 2) | PD_BLOCK) #define BOOT_PUD_ATTR (PD_ACCESS | (MAIR_IDX_NORMAL_CACHEABLE << 2) | PD_BLOCK)
#define BOOT_PUD_DEV_ATTR (PD_ACCESS | (MAIR_IDX_DEVICE << 2) | PD_BLOCK) #define BOOT_PUD_DEV_ATTR (PD_ACCESS | (MAIR_IDX_DEVICE << 2) | PD_BLOCK)
// ident map 0x80000000 -> 0x80000000 Size: 1G // ident map 0x00000000 -> 0x00000000 Size: 1G
ldr x0, =LOWMEM(_boot_ptl0lo) + 0x8 * 0 // x0 = L0 entry for vaddr 0x80000000 ldr x0, =LOWMEM(_boot_ptl0lo) + 0x8 * 0 // x0 = L0 entry for vaddr 0x00000000
ldr x1, =LOWMEM(_boot_ptl1lo) + BOOT_PGD_ATTR ldr x1, =LOWMEM(_boot_ptl1lo) + BOOT_PGD_ATTR
str x1, [x0] str x1, [x0]
ldr x0, =LOWMEM(_boot_ptl1lo) + 0x8 * 2 // x0 = L1 entry for vaddr 0x80000000 ldr x0, =LOWMEM(_boot_ptl1lo) + 0x8 * 0 // x0 = L1 entry for vaddr 0x00000000
ldr x1, =0x80000000 | BOOT_PUD_ATTR // map to 0x80000000 ldr x1, =0x00000000 | BOOT_PUD_ATTR // map to 0x80000000
str x1, [x0] str x1, [x0]
// ident map 0x00000000 -> 0x00000000 Size: 1G as device memory // map 0x00000000 -> 0xFFFF800000000000 Size: 1G
ldr x0, =LOWMEM(_boot_ptl1lo) + 0x8 * 0 // x0 - L1 entry for vaddr 0x00000000 ldr x0, =LOWMEM(_boot_ptl0hi) + 0x8 * 256 // x0 = L0 entry for vaddr 0xFFFF800000000000
ldr x1, =0x00000000 | BOOT_PUD_DEV_ATTR
str x1, [x0]
// map 0x80000000 -> 0xFFFF800080000000 Size: 1G
ldr x0, =LOWMEM(_boot_ptl0hi) + 0x8 * 256 // x0 = L0 entry for vaddr 0xFFFF800080000000
ldr x1, =LOWMEM(_boot_ptl1hi) + BOOT_PGD_ATTR ldr x1, =LOWMEM(_boot_ptl1hi) + BOOT_PGD_ATTR
str x1, [x0] str x1, [x0]
ldr x0, =LOWMEM(_boot_ptl1hi) + 0x8 * 2 // x0 = L1 entry for vaddr 0xFFFF800080000000 ldr x0, =LOWMEM(_boot_ptl1hi) + 0x8 * 0 // x0 = L1 entry for vaddr 0xFFFF800000000000
ldr x1, =0x80000000 | BOOT_PUD_ATTR ldr x1, =0x00000000 | BOOT_PUD_ATTR
str x1, [x0] str x1, [x0]
// enable MMU // enable MMU

View File

@ -21,6 +21,7 @@
#include <sys/elf64.h> #include <sys/elf64.h>
#include "../dev/console.h" #include "../dev/console.h"
#include "machine/cpuop.h"
extern void KTime_Init(); extern void KTime_Init();
extern void KTimer_Init(); extern void KTimer_Init();
@ -101,15 +102,15 @@ void Machine_Init()
); );
while(1) { while(1) {
__asm__ volatile ("wfi"); hlt();
}; };
Machine_SyscallInit(); //Machine_SyscallInit();
/* /*
* Initialize Memory Allocation and Virtual Memory * Initialize Memory Allocation and Virtual Memory
*/ */
//PAlloc_AddRegion(DMPA2VA(16*1024*1024), 16*1024*1024); PAlloc_AddRegion(DMPA2VA(16*1024*1024), 16*1024*1024);
PMap_Init(); PMap_Init();
XMem_Init(); XMem_Init();
PAlloc_LateInit(); PAlloc_LateInit();

View File

@ -10,7 +10,9 @@
#include "../dev/console.h" #include "../dev/console.h"
#include <machine/mrt.h>
#include <machine/pmap.h> #include <machine/pmap.h>
#include <machine/paging.h>
void MachineBoot_Entry(unsigned long magic, unsigned long addr); void MachineBoot_Entry(unsigned long magic, unsigned long addr);
@ -29,6 +31,10 @@ static int memRegionIdx;
void void
MachineBoot_Entry(unsigned long magic, unsigned long addr) MachineBoot_Entry(unsigned long magic, unsigned long addr)
{ {
// initialize metal mode
mtl_init();
paging_init();
// Main initialization // Main initialization
Machine_Init(); Machine_Init();

21
sys/arm64/metal.c Normal file
View File

@ -0,0 +1,21 @@
#include <machine/mrt.h>
#include <string.h>
#include <machine/pmap.h>
// early metal init
void mtl_init(void)
{
// initialize metal mode
memset(&mtl_mrt_tbl, 0, sizeof(mtl_mrt_tbl));
mtl_mrt_tbl.entries[MRT_INIT_IDX] = MROUTINE_ENTRY_MAKE(mrt_init, 1);
// load mroutine table
METAL_WMR(METAL_REG_MBR, &mtl_mrt_tbl);
// toggle metal mode
METAL_MENTER(MRT_INIT_IDX);
// call dummy mroutine to cache the entries
METAL_MENTER(0);
}

97
sys/arm64/mrt/init.c Normal file
View File

@ -0,0 +1,97 @@
#include "machine/metalp.h"
#include <machine/mrt.h>
#include <string.h>
DECL_MVAR(struct mroutine_table, mtl_mrt_tbl);
DECL_MVAR(struct exc_intercept_table, mtl_exc_tbl);
DECL_MVAR(struct inst_intercept_table, mtl_inst_tbl);
#define METAL_BOOTSTACK_SZ (4096)
DECL_MVAR_ALIGNED(static char, mtl_bootstack[METAL_BOOTSTACK_SZ], METAL_BOOTSTACK_SZ);
IMPL_SHORT_MROUTINE(mrt_dummy, 0)
{
}
IMPL_SHORT_MROUTINE(mrt_init, 0)
{
memset(&mtl_mrt_tbl, 0, sizeof(mtl_mrt_tbl));
memset(&mtl_exc_tbl, 0, sizeof(mtl_exc_tbl));
memset(&mtl_inst_tbl, 0, sizeof(mtl_inst_tbl));
// mroutine 0 - 8
mtl_mrt_tbl.entries[0] = MROUTINE_ENTRY_MAKE(mrt_dummy, 1);
mtl_mrt_tbl.entries[MRT_INIT_IDX] = MROUTINE_ENTRY_MAKE(mrt_init, 1);
mtl_mrt_tbl.entries[MRT_PF_HANDLER_IDX] = MROUTINE_ENTRY_MAKE(mrt_pf_handler, 1);
mtl_mrt_tbl.entries[MRT_SET_MPTB_IDX] = MROUTINE_ENTRY_MAKE(mrt_set_mptb, 1);
mtl_mrt_tbl.entries[MRT_SET_MTP_IDX] = MROUTINE_ENTRY_MAKE(mrt_set_mtp, 1);
mtl_exc_tbl.entries[0].esrbits = (0b100100 << 26) | (0b00100); // data abort, lv0 translation
mtl_exc_tbl.entries[0].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[0].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
mtl_exc_tbl.entries[1].esrbits = (0b100100 << 26) | (0b00101); // data abort, lv1 translation
mtl_exc_tbl.entries[1].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[1].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
mtl_exc_tbl.entries[2].esrbits = (0b100100 << 26) | (0b00110); // data abort, lv2 translation
mtl_exc_tbl.entries[2].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[2].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
mtl_exc_tbl.entries[3].esrbits = (0b100100 << 26) | (0b00111); // data abort, lv3 translation
mtl_exc_tbl.entries[3].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[3].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
mtl_exc_tbl.entries[4].esrbits = (0b100001 << 26) | (0b00100); // inst abort, lv0 translation
mtl_exc_tbl.entries[4].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[4].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
mtl_exc_tbl.entries[5].esrbits = (0b100001 << 26) | (0b00101); // inst abort, lv1 translation
mtl_exc_tbl.entries[5].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[5].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
mtl_exc_tbl.entries[6].esrbits = (0b100001 << 26) | (0b00110); // inst abort, lv2 translation
mtl_exc_tbl.entries[6].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[6].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
mtl_exc_tbl.entries[7].esrbits = (0b100001 << 26) | (0b00111); // inst abort, lv3 translation
mtl_exc_tbl.entries[7].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[7].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
mtl_exc_tbl.entries[8].esrbits = (0b100101 << 26) | (0b00100); // data abort, lv0 translation
mtl_exc_tbl.entries[8].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[8].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
mtl_exc_tbl.entries[9].esrbits = (0b100101 << 26) | (0b00101); // data abort, lv1 translation
mtl_exc_tbl.entries[9].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[9].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
mtl_exc_tbl.entries[10].esrbits = (0b100101 << 26) | (0b00110); // data abort, lv2 translation
mtl_exc_tbl.entries[10].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[10].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
mtl_exc_tbl.entries[11].esrbits = (0b100101 << 26) | (0b00111); // data abort, lv3 translation
mtl_exc_tbl.entries[11].esrmask = (0b111111 << 26) | (0b11111);
mtl_exc_tbl.entries[11].ctrl = EXC_INTERCEPT_MAKE_CTRL(MRT_PF_HANDLER_IDX, EXC_INTERCEPT_MODE_SYNC, 1);
// load mroutine table
void* tbl_addr = &mtl_mrt_tbl;
METAL_WMR(METAL_REG_MBR, tbl_addr);
// reset inst intercept table
tbl_addr = &mtl_inst_tbl;
METAL_WMR(METAL_REG_MIB, tbl_addr);
// load exc intercept table
tbl_addr = &mtl_exc_tbl;
METAL_WMR(METAL_REG_MEB, tbl_addr);
// enable exc intercept
regval_t msr;
METAL_RMR(METAL_REG_MSR, msr);
msr |= (1ull << 60);
METAL_WMR(METAL_REG_MSR, msr);
// temporary metal stack
regval_t mstk = (regval_t)&mtl_bootstack[METAL_BOOTSTACK_SZ];
METAL_WMR(METAL_REG_MSTK, mstk);
}

210
sys/arm64/mrt/paging.c Normal file
View File

@ -0,0 +1,210 @@
#include <machine/metal.h>
#include <machine/mrt.h>
#include <machine/paging.h>
#include <sys/kassert.h>
#include <sys/types.h>
#include <sys/cdefs.h>
#include <errno.h>
#define VM_MAP_PAGE_SHIFT (12)
//
// finds the page table base for the corresponding uva
// uva: untained virtual address
//
static MCODE int
vmm_get_ptb(vaddr_t uva, paddr_t * paddr, unsigned int * pgshift)
{
paddr_t addr = 0;
if (uva >= MEM_USERSPACE_BASE && uva < MEM_USERSPACE_TOP) {
METAL_RMR(METAL_REG_MPTB_USER, addr);
*pgshift = REGION_USER_PGSHIFT;
} else if (uva >= MEM_DIRECTMAP_BASE && uva < MEM_DIRECTMAP_TOP) {
METAL_RMR(METAL_REG_MPTB_DMAP, addr);
*pgshift = REGION_DMAP_PGSHIFT;
} else if (uva >= MEM_XMAP_BASE && uva < MEM_XMAP_TOP) {
METAL_RMR(METAL_REG_MPTB_XMEM, addr);
*pgshift = REGION_XMEM_PGSHIFT;
} else {
return EINVAL;
}
*paddr = addr;
return 0;
}
//
// finds the corresponding pte to va given the page table base
// uva: untained virtual address
//
static MCODE int
vmm_get_pd(paddr_t ptb, unsigned int pgshift, vaddr_t uva, paddr_t * out)
{
const uint64_t pfn = vm_get_pfn(uva, pgshift);
const uint64_t vahash = vm_vahash(pfn);
ASSERT(vahash < VM_PTBUCKETS);
const paddr_t pte = ptb + vahash * sizeof(struct vmpte);
paddr_t cur;
METAL_PLDR64(cur, pte + offsetof(struct vmpte, first));
vaddr_t curvaddr;
while (cur != (paddr_t)NULL) {
METAL_PLDR64(curvaddr, cur + offsetof(struct vmpd, vaddr));
if (vm_get_pfn(curvaddr, pgshift) == pfn) {
*out = cur;
return 0;
}
METAL_PLDR64(cur, cur + offsetof(struct vmpd, next));
}
return ENOENT;
}
//
// populates the tlb of a corresponding page
//
// uva: untainted virtual address
//
// returns: EINVAL if translation failure
// 0 if success
//
static MCODE int
vmm_map_page(vaddr_t uva)
{
int status;
paddr_t ptb;
unsigned int pgshift;
status = vmm_get_ptb(uva, &ptb, &pgshift);
if (status != 0) {
return status;
}
paddr_t pd;
status = vmm_get_pd(ptb, pgshift, uva, &pd);
if (status != 0) {
return status;
}
struct vmpd vmpd;
METAL_PLDR64(vmpd.attr, pd + offsetof(struct vmpd, attr));
METAL_PLDR64(vmpd.paddr, pd + offsetof(struct vmpd, paddr));
// access override bits
//AO REG for Kernel:
// entry 0 (kernel RO): RO
// entry 1 (kernel RW): RW
// entry 2 (user RO): RW
// entry 3 (user RW): RW
// AO REG for User:
// entry 0 (kernel RO): NA
// entry 1 (kernel RW): NA
// entry 2 (user RO): RO
// entry 3 (user RW): RW
const unsigned int aoid = VMPD_ATTR_AO_GET(vmpd.attr);
const unsigned int dev = vmpd.attr & VMPD_ATTR_DEV;
const vaddr_t pgvaddr = vm_get_pgbase(uva, VM_MAP_PAGE_SHIFT);
const vaddr_t pgvoffset = pgvaddr - vm_get_pgbase(pgvaddr, pgshift);
const paddr_t pgpaddr = vm_get_pgbase(vmpd.paddr + pgvoffset, VM_MAP_PAGE_SHIFT);
// type Page, grainSize 12
const regval_t desc = ((0ull << 54) | // xn
(0ull << 53) | // pxn
(pgpaddr) | // pfn (bits 47:12)
(0 << 11) | // global page
((dev ? 0b00 : 0b11) << 8) | // inner-shareable for normal memory
(0b00 << 6) | // ap - AP[2:1] = b00, r/w for privileged, will be overriden by AO
(0b0 << 5) | // secure
(0b0 << 2) | // mair index = 0 (dummy)
(0b11)); // block/page desc + valid
#define MAIR_NORMAL (0b11111111ul)
#define MAIR_DEV (0b0ul)
const regval_t extIAttrs =
(1 << 0) | // itlb
(0b01 << 1) | // el1
(0b11 << 3) | // translv = 3
(0b00 << 5) | // 4k page
(0x0 << 7) | // asid = 0
(0 << 23) | // hyp = 0
(0 << 24) | // vmid
(1ul << 40) | // ao = 1
((regval_t)aoid << 41) | // aoid
((dev ? MAIR_DEV : MAIR_NORMAL) << 43) | // mair
(1ul << 51) | // ns = 0
(1ul << 52); // nstid = 1
METAL_WMR(METAL_REG_MR0, desc);
METAL_WMR(METAL_REG_MR1, extIAttrs);
METAL_WMR(METAL_REG_MR2, pgvaddr);
METAL_WTLB(METAL_REG_MR0, METAL_REG_MR1, METAL_REG_MR2);
const regval_t extDAttrs =
(0 << 0) | // dtlb
(0b01 << 1) | // el1
(0b11 << 3) | // translv = 3
(0b00 << 5) | // 4k page
(0x0 << 7) | // asid = 0
(0 << 23) | // hyp = 0
(0 << 24) | // vmid
(1ul << 40) | // ao = 1
((regval_t)aoid << 41) | // aoid
((dev ? MAIR_DEV : MAIR_NORMAL) << 43) | // mair
(1ul << 51) | // ns = 0
(1ul << 52); // nstid = 1
METAL_WMR(METAL_REG_MR1, extDAttrs);
METAL_WTLB(METAL_REG_MR0, METAL_REG_MR1, METAL_REG_MR2);
return 0;
}
// flag: skip exception intercept on the next instruction upon mreturn
IMPL_MROUTINE(mrt_pf_handler, 1)
{
vaddr_t vaddr;
METAL_RMR(METAL_REG_MER2, vaddr);
vmm_map_page(vaddr);
}
IMPL_MROUTINE(mrt_set_mptb, 0)
{
unsigned int idx;
int ret = 0;
METAL_MROUTINE_GETARG(0, idx);
regval_t mptb;
METAL_MROUTINE_GETARG(1, mptb);
switch (idx) {
case MRT_SET_MPTB_USER: {
METAL_WMR(METAL_REG_MPTB_USER, mptb);
break;
}
case MRT_SET_MPTB_DMAP: {
METAL_WMR(METAL_REG_MPTB_DMAP, mptb);
break;
}
case MRT_SET_MPTB_XMEM: {
METAL_WMR(METAL_REG_MPTB_XMEM, mptb);
break;
}
default: {
ret = EINVAL;
}
}
METAL_MROUTINE_SETRET(0, ret);
}
IMPL_MROUTINE(mrt_set_mtp, 0)
{
uint64_t mtp;
METAL_MROUTINE_GETARG(0, mtp);
METAL_WMR(METAL_REG_MTP, mtp);
}

94
sys/arm64/paging.c Normal file
View File

@ -0,0 +1,94 @@
#include "include/pmap.h"
#include <machine/metalp.h>
#include <machine/paging.h>
#include <machine/pmap.h>
#include <machine/mrt.h>
#include <sys/types.h>
#include <string.h>
// page table for boot
static struct vmpt boot_pt;
#define BOOT_PD_NUM (4)
static struct vmpd boot_pd[BOOT_PD_NUM];
static struct vmpd boot_dev_pd[BOOT_PD_NUM];
void
vm_insert_pd(struct vmpt * pt, struct vmpd * pd, unsigned int pgshift, paddr_t paddr)
{
const uint64_t pfn = vm_get_pfn(pd->vaddr, pgshift);
int hash = vm_vahash(pfn);
struct vmpte * vmpte = &pt->entries[hash];
pd->next = vmpte->first;
vmpte->first = paddr;
}
void paging_init()
{
int ret;
memset(&boot_pd, 0, sizeof(boot_pd));
memset(&boot_pt, 0, sizeof(boot_pt));
// ident map the first 4GB
paddr_t cur = 0;
for (int i = 0; i < BOOT_PD_NUM; i++) {
boot_pd[i].attr = VMPD_ATTR_P | VMPD_ATTR_AO_KRW;
boot_pd[i].paddr = cur;
boot_pd[i].vaddr = MEM_DIRECTMAP_BASE + cur;
cur += (1 << REGION_DMAP_PGSHIFT);
vm_insert_pd(&boot_pt, &boot_pd[i], REGION_DMAP_PGSHIFT, (paddr_t)DMVA2PA(&boot_pd[i]));
}
// ident map the first 4GB to device memory space
cur = 0;
for (int i = 0; i < BOOT_PD_NUM; i++) {
boot_dev_pd[i].attr = VMPD_ATTR_P | VMPD_ATTR_DEV | VMPD_ATTR_AO_KRW;
boot_dev_pd[i].paddr = cur;
boot_dev_pd[i].vaddr = MEM_DIRECTMAP_DEV_BASE + cur;
cur += (1 << REGION_DMAP_PGSHIFT);
vm_insert_pd(&boot_pt, &boot_dev_pd[i], REGION_DMAP_PGSHIFT, (paddr_t)DMVA2PA(&boot_dev_pd[i]));
}
// set page table base
paddr_t ptb = (paddr_t)DMVA2PA(&boot_pt);
int idx = MRT_SET_MPTB_DMAP;
METAL_MROUTINE_SETARG(MRT_SET_MPTB_ARG_IDX, idx);
METAL_MROUTINE_SETARG(MRT_SET_MPTB_ARG_PTB, ptb);
METAL_MENTER(MRT_SET_MPTB_IDX);
METAL_MROUTINE_GETRET(MRT_SET_MPTB_RET_STATUS, ret);
if (ret != 0) {
hlt();
}
// set page table attribute override bits
uint64_t mtp = MTP_KERNEL;
METAL_MROUTINE_SETARG(MRT_SET_MTP_ARG_MTP, mtp);
METAL_MENTER(MRT_SET_MTP_IDX);
// // set MAIR
// #define MAIR_VAL ((0b11111111) | (0b00000000 << 8))
// // 0 = b11111111 = Normal, Inner/Outer WB/WA/RA
// // 1 = b00000000 = Device-nGnRnE
// __asm__ volatile (
// "ldr x0, =(" METAL_STR(MAIR_VAL) ");"
// "msr mair_el1, x0;"
// :
// :
// : "x0"
// );
// reset page tables
uint64_t zero = 0;
__asm__ volatile (
"msr ttbr0_el1, %x0;"
"msr ttbr1_el1, %x0;"
"TLBI VMALLE1;"
:
: "r" (zero)
:
);
}

View File

@ -249,7 +249,7 @@ PMap_SystemLookup(uint64_t va, PageEntry **entry, int size)
/** /**
* PMap_SystemLMap -- * PMap_SystemLMap --
* *
* Map a range of large (2MB) physical pages to virtual pages in the kernel * Map a range of large (64MB) physical pages to virtual pages in the kernel
* address space that is shared by all processes. * address space that is shared by all processes.
* *
* @param [in] phys Physical address. * @param [in] phys Physical address.
@ -263,7 +263,7 @@ PMap_SystemLookup(uint64_t va, PageEntry **entry, int size)
bool bool
PMap_SystemLMap(uint64_t phys, uint64_t virt, uint64_t lpages, uint64_t flags) PMap_SystemLMap(uint64_t phys, uint64_t virt, uint64_t lpages, uint64_t flags)
{ {
NOT_IMPLEMENTED();
return true; return true;
} }
@ -300,11 +300,11 @@ PMap_SystemUnmap(uint64_t virt, uint64_t pages)
return false; return false;
} }
static uint64_t // static uint64_t
AddrFromIJKL(uint64_t i, uint64_t j, uint64_t k, uint64_t l) // AddrFromIJKL(uint64_t i, uint64_t j, uint64_t k, uint64_t l)
{ // {
return (i << 39) | (j << HUGE_PGSHIFT) | (k << LARGE_PGSHIFT) | (l << PGSHIFT); // return (i << 39) | (j << HUGE_PGSHIFT) | (k << LARGE_PGSHIFT) | (l << PGSHIFT);
} // }
void void
PMap_Dump(AS *space) PMap_Dump(AS *space)

View File

@ -49,7 +49,7 @@ ThreadEnterUserLevelCB(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
memset(&tf, 0, sizeof(tf)); memset(&tf, 0, sizeof(tf));
Trap_Pop(&tf); //Trap_Pop(&tf);
} }
void void

View File

@ -13,7 +13,7 @@ uint64_t
Time_GetTSC() Time_GetTSC()
{ {
uint64_t ui; uint64_t ui;
asm volatile("mrs %0, CNTVCT_EL0" : "=&r" (ui)); __asm__ volatile("mrs %0, CNTVCT_EL0" : "=&r" (ui));
return ui; return ui;
} }
@ -21,7 +21,7 @@ uint64_t
Time_GetTSCFreq() Time_GetTSCFreq()
{ {
uint64_t ui; uint64_t ui;
asm volatile("mrs %0, CNTFRQ_EL0" : "=&r" (ui)); __asm__ volatile("mrs %0, CNTFRQ_EL0" : "=&r" (ui));
return ui; return ui;
} }

View File

@ -1,6 +1,7 @@
#include "uart.h" #include "uart.h"
#include "sys/kassert.h" #include "sys/kassert.h"
#include <stdint.h> #include <stdint.h>
#include "machine/pmap.h"
#define UART_DR_OFFSET (0x000) #define UART_DR_OFFSET (0x000)
#define UART_FR_OFFSET (0x018) #define UART_FR_OFFSET (0x018)
@ -26,7 +27,7 @@ struct uart {
}; };
static struct uart g_uart0 = { static struct uart g_uart0 = {
.base = 0x1c090000, .base = DEVPA2VA(0x1c090000),
.baud = 115200, .baud = 115200,
.clock = 24000000, .clock = 24000000,
.dbits = 8, .dbits = 8,

View File

@ -10,6 +10,8 @@
#define INLINE inline #define INLINE inline
#define ALWAYS_INLINE __attribute__((__always_inline__)) #define ALWAYS_INLINE __attribute__((__always_inline__))
#define ALIGNED(x) __attribute__((aligned(x)))
#define NO_RETURN __attribute__((noreturn)) #define NO_RETURN __attribute__((noreturn))
#define UNREACHABLE __builtin_unreachable #define UNREACHABLE __builtin_unreachable
@ -41,5 +43,8 @@
#define __printflike(_fmt, _var) __attribute__((__format__(__printf__, _fmt, _var))) #define __printflike(_fmt, _var) __attribute__((__format__(__printf__, _fmt, _var)))
#define offsetof(st, m) \
((size_t)((char *)&((st *)0)->m - (char *)0))
#endif /* __CDEFS_H__ */ #endif /* __CDEFS_H__ */

View File

@ -2,6 +2,8 @@
#ifndef __SYS_TYPES_H__ #ifndef __SYS_TYPES_H__
#define __SYS_TYPES_H__ #define __SYS_TYPES_H__
#include <stdbool.h>
typedef signed char int8_t; typedef signed char int8_t;
typedef signed short int16_t; typedef signed short int16_t;
typedef signed int int32_t; typedef signed int int32_t;
@ -27,6 +29,9 @@ typedef uint64_t suseconds_t;
typedef uint16_t pid_t; typedef uint16_t pid_t;
typedef uintptr_t paddr_t;
typedef uintptr_t vaddr_t;
#define NULL ((void *)0) #define NULL ((void *)0)
#endif /* __SYS_TYPES_H__ */ #endif /* __SYS_TYPES_H__ */