VxKernel - 0.1.0 : Base
@add <> board/fx9860g/board : board description for the fx9860G device <> board/fx9860g/fx9860g.ld : linker script for the fx9860G device <> board/fx9860g/initialize : device-specific entry for the fx9860g device <> board/fxcg50/_Exit : define our own _Exit() function for the fxlibc <> board/fxcg50/board : board description for the fxcg50 device <> board/fxcg50/fxcg50.ld : linker script for the fxcg50 device <> board/fxcg50/hardware : hardware detection for the fxcg50 device <> board/fxcg50/initialize : device-specific entry for the fxcg50 device <> config : configuration script for the vxKernel build system <> make/Makefile : initial Makefile (must be used with the vxsdk) <> include/vhex/arch/fxcg50/hardware : hardware definition for the fxcg50 device <> include/vhex/defs/attributes : define common attributes macros <> include/vhex/defs/types : define all types information <> include/vhex/hardware : expose hardware "module" API <> include/vhex/kernel : expose kernel "module" API <> include/vhex/mmu : expose MMU "module" API <> include/vhex/mpu/sh7305/mmu : MMU hardware definition <> include/vhex/mpu/sh7305/pfc : PFC hardware definition <> src/drivers/mpu/sh/sh7305/mmu : MMU driver definition <> src/kernel/kernel : kinit() and kquit() definition
This commit is contained in:
commit
f38bea7024
|
@ -0,0 +1,11 @@
|
|||
[meta]
|
||||
description=Casio's Fx9860g calculator board description
|
||||
|
||||
[drivers]
|
||||
screen=T6K73A,ML9801
|
||||
mpu=sh7305
|
||||
|
||||
[toolchain]
|
||||
prefix=sh-elf-vhex-
|
||||
cflags=-DFX9860G,-m4-nofpu,-mb
|
||||
libs=-lgcc
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
Linker script for the fxcg50 platform.
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT(elf32-sh)
|
||||
OUTPUT_ARCH(sh3)
|
||||
ENTRY(_initilize)
|
||||
|
||||
/*
|
||||
** Linker script for user executables.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
/* virtual memory, read-write segment */
|
||||
userram (WX) : o = 0x00000000, l = 256k
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Code */
|
||||
.text : {
|
||||
*(.text);
|
||||
*(.text.*);
|
||||
|
||||
} > userram
|
||||
|
||||
/* Read-only sections */
|
||||
.rodata : {
|
||||
/* Read-Only data */
|
||||
*(.rodata);
|
||||
*(.rodata.*);
|
||||
|
||||
/* Dynamic symbols */
|
||||
*(.hash)
|
||||
*(.dynsym)
|
||||
*(.dynstr)
|
||||
*(.dynbss)
|
||||
*(.dynamic)
|
||||
|
||||
/* Procedure Linkage Table */
|
||||
*(.plt)
|
||||
|
||||
/* GLobal Offset Table */
|
||||
*(.got.plt)
|
||||
*(.got.*)
|
||||
*(.got)
|
||||
} > userram
|
||||
|
||||
/* Relocatable sections */
|
||||
.rela.dyn : {
|
||||
*(.rela.plt)
|
||||
*(.rela.got)
|
||||
*(.rela.got.*)
|
||||
*(.rela.*)
|
||||
*(.rela.text)
|
||||
*(.real.data)
|
||||
} > userram
|
||||
|
||||
/* readable / writable data */
|
||||
.data ALIGN(4) : {
|
||||
|
||||
/* Data sections */
|
||||
*(.data);
|
||||
*(.data.*);
|
||||
|
||||
/* bss section included to avoid missaligned segment */
|
||||
*(.bss);
|
||||
*(.bss.*);
|
||||
*(COMMON);
|
||||
} > userram
|
||||
|
||||
/* unwanted section */
|
||||
/DISCARD/ : {
|
||||
*(.gnu.*)
|
||||
*(.debug_info)
|
||||
*(.debug_abbrev)
|
||||
*(.debug_loc)
|
||||
*(.debug_aranges)
|
||||
*(.debug_ranges)
|
||||
*(.debug_line)
|
||||
*(.debug_str)
|
||||
*(.jcr)
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame)
|
||||
*(.comment)
|
||||
*(.interp)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#include <stdint.h>
|
||||
|
||||
/* for now, just involve the main routine */
|
||||
void initialize(void)
|
||||
{
|
||||
extern int main(void);
|
||||
|
||||
main();
|
||||
while(1) { __asm__ volatile ("sleep"::); }
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#include <setjmp.h>
|
||||
|
||||
/* Jumping there will properly unwind and leave the kernel */
|
||||
extern jmp_buf vhex_exitbuf;
|
||||
/* Return value of main() */
|
||||
extern int vhex_exitcode;
|
||||
|
||||
/* Standard _Exit, used by the fxlibc exit() to leave control */
|
||||
void _Exit(int rc)
|
||||
{
|
||||
vhex_exitcode = rc;
|
||||
longjmp(vhex_exitbuf, 1);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
[meta]
|
||||
description=Casio's Fxcg50 calculator board description
|
||||
|
||||
[drivers]
|
||||
screen=R61524
|
||||
mpu=sh7305
|
||||
|
||||
[toolchain]
|
||||
prefix=sh-elf-vhex-
|
||||
cflags=-DFXCG50,-m4-nofpu,-mb
|
||||
libs=-lgcc
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
Linker script for the fxcg50 platform.
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT(elf32-sh)
|
||||
OUTPUT_ARCH(sh4)
|
||||
ENTRY(_initialize)
|
||||
|
||||
/*
|
||||
** Linker script for user executables.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
/* virtual memory, read-write segment */
|
||||
userram (WX) : o = 0x00000000, l = 256k
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Code */
|
||||
.text : {
|
||||
*(.text);
|
||||
*(.text.*);
|
||||
|
||||
_bctors = . ;
|
||||
*(.ctors .ctors.*)
|
||||
_ectors = . ;
|
||||
|
||||
_bdtors = . ;
|
||||
*(.dtors .dtors.*)
|
||||
_edtors = . ;
|
||||
} > userram
|
||||
|
||||
/* Read-only sections */
|
||||
.rodata : {
|
||||
/* Read-Only data */
|
||||
*(.rodata);
|
||||
*(.rodata.*);
|
||||
|
||||
/* Dynamic symbols */
|
||||
*(.hash)
|
||||
*(.dynsym)
|
||||
*(.dynstr)
|
||||
*(.dynbss)
|
||||
*(.dynamic)
|
||||
|
||||
/* Procedure Linkage Table */
|
||||
*(.plt)
|
||||
|
||||
/* GLobal Offset Table */
|
||||
*(.got.plt)
|
||||
*(.got.*)
|
||||
*(.got)
|
||||
} > userram
|
||||
|
||||
/* Relocatable sections */
|
||||
.rela.dyn : {
|
||||
*(.rela.init)
|
||||
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
|
||||
*(.rela.fini)
|
||||
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
|
||||
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
|
||||
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
|
||||
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
|
||||
*(.rela.ctors)
|
||||
*(.rela.dtors)
|
||||
*(.rela.got)
|
||||
*(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
|
||||
*(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
|
||||
*(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
|
||||
*(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
|
||||
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
|
||||
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||
*(.rela.iplt)
|
||||
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||
} > userram
|
||||
.rela.plt : {
|
||||
*(.rela.plt)
|
||||
} > userram
|
||||
|
||||
.plt : { *(.plt) } > userram
|
||||
.iplt : { *(.iplt) } > userram
|
||||
|
||||
/* readable / writable data */
|
||||
.data ALIGN(4) : {
|
||||
|
||||
/* Data sections */
|
||||
*(.data);
|
||||
*(.data.*);
|
||||
|
||||
/* bss section included to avoid missaligned segment */
|
||||
*(.bss);
|
||||
*(.bss.*);
|
||||
*(COMMON);
|
||||
} > userram
|
||||
|
||||
/* unwanted section */
|
||||
/DISCARD/ : {
|
||||
*(.gnu.*)
|
||||
*(.debug_info)
|
||||
*(.debug_abbrev)
|
||||
*(.debug_loc)
|
||||
*(.debug_aranges)
|
||||
*(.debug_ranges)
|
||||
*(.debug_line)
|
||||
*(.debug_str)
|
||||
*(.jcr)
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame)
|
||||
*(.comment)
|
||||
*(.interp)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
//---
|
||||
// vhex:core:hardware - Platform information and hardware detection
|
||||
//---
|
||||
#include "vhex/mpu/sh7305/pfc.h"
|
||||
#include "vhex/arch/fxcg50/hardware.h"
|
||||
#include "vhex/hardware.h"
|
||||
#include "vhex/mmu.h"
|
||||
|
||||
|
||||
/* Holds information about the current platform */
|
||||
uintptr_t vhex[HW_KEYS];
|
||||
|
||||
/* Processor Version Register */
|
||||
#define PVR (*((volatile uint32_t *)0xff000030))
|
||||
/* Product Register */
|
||||
#define PRR (*((volatile uint32_t *)0xff000044))
|
||||
|
||||
|
||||
|
||||
/* ram_get_size() : try to determine the RAM size */
|
||||
static ptrdiff_t ram_get_size(uintptr_t start_ram)
|
||||
{
|
||||
volatile uint32_t *ptr = (void*)start_ram;
|
||||
volatile uint32_t *tst = (void*)start_ram;
|
||||
uintptr_t backup;
|
||||
|
||||
//TODO: use UTLB page size information to walk through each pages
|
||||
while (1) {
|
||||
ptr = &ptr[4096];
|
||||
backup = ptr[0];
|
||||
ptr[0] = 0xdeadbeef;
|
||||
if (ptr[0] != 0xdeadbeef || ptr[0] == tst[0]) break;
|
||||
ptr[0] = backup;
|
||||
}
|
||||
ptr[0] = backup;
|
||||
return ((ptrdiff_t)((uintptr_t)ptr - (uintptr_t)tst));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* hw_detect(): Basic hardware detection */
|
||||
void hw_detect(void)
|
||||
{
|
||||
/* get MPU and CPU information */
|
||||
vhex[HWMPU] = HWMPU_SH7305;
|
||||
vhex[HWCPUVR] = PVR;
|
||||
vhex[HWCPUPR] = PRR;
|
||||
|
||||
/* We can differentiate the Prizm device from the fxcg50 device by
|
||||
checking its stack */
|
||||
uintptr_t stack;
|
||||
__asm__("mov r15, %0" : "=r"(stack));
|
||||
|
||||
/* detect the device type */
|
||||
vhex[HWDEVICE] = HWDEVICE_FXCG50;
|
||||
if (stack < 0x8c000000)
|
||||
vhex[HWDEVICE] = HWDEVICE_PRIZM;
|
||||
if (PVR == 0x00000000)
|
||||
vhex[HWDEVICE] = HWDEVICE_FXCG_MANAGER;
|
||||
|
||||
/* detect the RAM geometry */
|
||||
uintptr_t uram = mmu_translate(0x08100000, NULL);
|
||||
vhex[HWRAM_PHY_USER] = uram;
|
||||
vhex[HWRAM_PHY_ORIGIN] = uram & 0xff000000;
|
||||
vhex[HWRAM_PHY_SIZE] = ram_get_size(uram | 0xa0000000);
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
//---
|
||||
// fxcg50:initialize - Kernel initialization and C runtime
|
||||
//---
|
||||
|
||||
#include "vhex/hardware.h"
|
||||
#include "vhex/kernel.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
|
||||
|
||||
/* Constructor and destructor arrays */
|
||||
extern void (*bctors)(void), (*ectors)(void);
|
||||
extern void (*bdtors)(void), (*edtors)(void);
|
||||
|
||||
/* User-provided main() function */
|
||||
extern int main(void);
|
||||
|
||||
/* Jumping there will properly unwind and leave the kernel */
|
||||
jmp_buf vhex_exitbuf;
|
||||
/* Return value of main() */
|
||||
int vhex_exitcode;
|
||||
|
||||
|
||||
|
||||
/* callarray(): Call an array of functions (constructors or destructors) */
|
||||
static void callarray(void (**f)(void), void (**l)(void))
|
||||
{
|
||||
while(f < l) (*(*f++))();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* initialize() : Where it all starts
|
||||
|
||||
We are currently in a RAM location at a non-constant address due to the
|
||||
relocalization performed by the bootloader. Moreover, we are in privileged
|
||||
mode with one golden rule:
|
||||
|
||||
Do not disturb the operating system
|
||||
|
||||
Why we should keep this rule in mind? Because, on this particular device,
|
||||
none of all hardware and software information are documented. Vhex will
|
||||
therefore involve Casio's syscall to perform some interaction, especially
|
||||
concerning file manipulation.
|
||||
|
||||
Note that we don't need to change the stack, the kernel will use the one
|
||||
given by Casio because it's big enough to store the user-application
|
||||
(mainly the vxOS) and the kernel code. However, we need to keep in mind
|
||||
that for this device, a lot of hardware supposition will be performed here,
|
||||
chiefly concerning the memory discovery.
|
||||
|
||||
+---------------+
|
||||
| |
|
||||
| |
|
||||
| Reserved Area |
|
||||
| |
|
||||
| |
|
||||
+ - - - - - - - + <-- virtually mapped at 0x0810000
|
||||
| _vxKernel |
|
||||
| + |
|
||||
| _vxOS |
|
||||
+ - - - - - - - + <-- Provided by the vxKernel (variable)
|
||||
| |
|
||||
| Stack |
|
||||
| |
|
||||
+ - - - - - - - + <-- end of the TLB information (variable)
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| kmalloc() |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
+---------------+ <-- variable
|
||||
|
||||
We know that the "user RAM" is *constantly* mapped at 0x08100000 and all the
|
||||
memory reserved for the user is completely loaded and all of this information
|
||||
is stored at the end of the UTLB. Moreover, the stack provided by Casio start
|
||||
at the end of the "user RAM". So, the memory layout is a bit exotic and look
|
||||
like above. */
|
||||
void initialize(void)
|
||||
{
|
||||
/* Detect hardware information : This part is important because it will
|
||||
tell us if we are running in an emulator or on a real device. */
|
||||
hw_detect();
|
||||
|
||||
/* Install Vhex, switch VBR and initialize drivers */
|
||||
kinit();
|
||||
|
||||
//TODO: add area for the kmalloc() ?
|
||||
|
||||
/* We are now running on our own in kernel mode. Since we have taken
|
||||
control of interrupts, pretty much any interaction with the system
|
||||
will break it. We'll limit our use of syscalls and do device driving
|
||||
ourselves. (Hopefully we can add cool features in the process!) */
|
||||
|
||||
/* Now that we have initialized the kernel, we are ready to start the
|
||||
hosted user application, which has its own constructors and
|
||||
destructors to work with. */
|
||||
|
||||
/* Here, we use exit() to allow the standard library to do
|
||||
what it wants in exit() after main() finishes executing */
|
||||
if(!setjmp(vhex_exitbuf)) {
|
||||
callarray(&bctors, &ectors);
|
||||
exit(main());
|
||||
}
|
||||
else {
|
||||
callarray(&bdtors, &edtors);
|
||||
}
|
||||
|
||||
/* Before leaving the kernel (which will return to the bootloader menu),
|
||||
we need to clean everything we changed to hardware settings and
|
||||
peripheral modules. The OS is bound to be confused (and hang, or
|
||||
crash, or any other kind of giving up) if we don't restore them. */
|
||||
|
||||
/* Unload vhex and give back control to the system. Driver settings
|
||||
will be restored while interrupts are disabled */
|
||||
kquit();
|
||||
|
||||
|
||||
//TODO: involve manualy the Casio's OS-menu
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
#! /bin/python3
|
||||
import sys
|
||||
import configparser
|
||||
import os.path
|
||||
import os
|
||||
import shutil
|
||||
|
||||
|
||||
help_string = f"""
|
||||
usage: config [options...]
|
||||
|
||||
Configuration script for the Vhex unikernel. You should build out-of-tree by
|
||||
creating a build directory and configuring from there.
|
||||
|
||||
Options:
|
||||
-h,--help
|
||||
display this message
|
||||
|
||||
--verbose
|
||||
display more information during the compilation step
|
||||
|
||||
--format=FORMAT[,format[,...]]
|
||||
select the format of the library generation. You can use two format:
|
||||
<> static - generate a static library
|
||||
<> dynamic - generate a dynamic library
|
||||
<> all - same behaviour as "--format=static,dynamic"
|
||||
By default, only "dynamic" is used.
|
||||
|
||||
--board[=BOARD,board[,...]]
|
||||
select boards. If no board name is given, a list of all available board
|
||||
will be printed.
|
||||
|
||||
--prefix=PATH
|
||||
installation path for all generated libraries
|
||||
""".strip()
|
||||
|
||||
#
|
||||
# create and apply the arguments parser
|
||||
#
|
||||
|
||||
def parse_arguments():
|
||||
"""
|
||||
The objectif of this function is to generate the "arguments object" with
|
||||
all arguments passed throuth this script correctly isolated.
|
||||
"""
|
||||
args = {
|
||||
'board' : [],
|
||||
'format' : [],
|
||||
'verbose': False,
|
||||
'prefix': ''
|
||||
}
|
||||
arg_name = [
|
||||
"-h",
|
||||
"--help",
|
||||
"--format",
|
||||
"--verbose",
|
||||
"--board",
|
||||
"--prefix"
|
||||
]
|
||||
for arg in sys.argv[1:]:
|
||||
info = arg.split("=")
|
||||
if (info[0] in arg_name) == False:
|
||||
print("%s: unreconized option '%s'" % (sys.argv[0],info[0]))
|
||||
print("Try '%s --help' for more information" % sys.argv[0])
|
||||
exit(84)
|
||||
if (info[0] in ["-h", "--help"]) == True:
|
||||
print(help_string)
|
||||
exit(0)
|
||||
if info[0] == "--verbose":
|
||||
args["verbose"] = True
|
||||
continue
|
||||
if info[0] == "--prefix":
|
||||
args["prefix"] = info[1]
|
||||
continue
|
||||
if len(info) > 1:
|
||||
args[info[0][2:]] = info[1].split(",")
|
||||
return args
|
||||
|
||||
|
||||
#
|
||||
# part handlers
|
||||
#
|
||||
|
||||
def board_check(file, board_list):
|
||||
(boards,_,_) = os.walk('../board')
|
||||
(archs,_,_) = os.walk('../src/drivers/mpu')
|
||||
boards = boards[1]
|
||||
archs = archs[1]
|
||||
|
||||
if not board_list:
|
||||
print('board available:')
|
||||
for board in boards:
|
||||
path = '../board/%s/board.ini' % board
|
||||
if not os.path.exists(path):
|
||||
print('board \'%s\' does not exists' % board)
|
||||
continue
|
||||
conf = configparser.ConfigParser()
|
||||
conf.read(path)
|
||||
if not ('meta' in conf) or not ('description' in conf['meta']):
|
||||
print('<> %s\t\tNo description available' % board)
|
||||
continue
|
||||
print('<> %s\t\t%s' % (board, conf['meta']['description']))
|
||||
exit(0)
|
||||
|
||||
|
||||
valid_board_list = []
|
||||
for board in board_list:
|
||||
if not (board in boards):
|
||||
print("board '%s' does not exist" % board)
|
||||
continue
|
||||
path = '../board/%s/board.ini' % board
|
||||
if not os.path.exists(path):
|
||||
print("board '%s' does not have INI descriptor file" % board)
|
||||
continue
|
||||
conf = configparser.ConfigParser()
|
||||
conf.read(path)
|
||||
if not ('drivers' in conf) or not ('mpu' in conf['drivers']):
|
||||
print("board '%s' does not have MPU information" % board)
|
||||
continue
|
||||
arch = ''
|
||||
mpu = conf['drivers']['mpu']
|
||||
for _arch in archs:
|
||||
if not os.path.exists('../src/drivers/mpu/%s/%s' % (_arch,mpu)):
|
||||
continue
|
||||
arch = _arch
|
||||
break
|
||||
if not arch:
|
||||
print("board '%s': unreconized MPU '%s'" % (board,mpu))
|
||||
continue
|
||||
|
||||
pathlist = [
|
||||
'../board/%s' % board,
|
||||
'../src/drivers/mpu/%s/%s' % (_arch,mpu)
|
||||
]
|
||||
for driver in conf['drivers']:
|
||||
if driver == 'mpu':
|
||||
continue
|
||||
dpath = '../src/drivers/%s' % driver
|
||||
if not os.path.exists(dpath):
|
||||
print("board '%s': unreconized driver \'%s\'" % (board, dpath))
|
||||
continue
|
||||
for t in conf['drivers'][driver].split(','):
|
||||
tpath = dpath + '/' + t
|
||||
if not os.path.exists(tpath):
|
||||
print("board '%s': unreconized driver \'%s\'" % (board, t))
|
||||
continue
|
||||
pathlist.append(tpath)
|
||||
tpath = tpath + '/target/' + arch
|
||||
if os.path.exists(tpath):
|
||||
pathlist.append(tpath)
|
||||
for dirent in os.listdir('../src'):
|
||||
if not (dirent in ['drivers', 'arch']):
|
||||
pathlist.append('../src/' + dirent)
|
||||
|
||||
ldflags,cflags,prefix,libs = [],[],[],[]
|
||||
if 'toolchain' in conf:
|
||||
if 'prefix' in conf['toolchain']:
|
||||
prefix = conf['toolchain']['prefix']
|
||||
if 'cflags' in conf['toolchain']:
|
||||
cflags = conf['toolchain']['cflags'].split(',')
|
||||
if 'libs' in conf['toolchain']:
|
||||
libs = conf['toolchain']['libs'].split(',')
|
||||
|
||||
confstr = 'CONFIG.' + board;
|
||||
file.write(
|
||||
confstr + '.SRC-MODULE-PATH :=' + ' '.join(pathlist) + '\n'
|
||||
+ confstr + '.TOOLCHAIN.LDFLAGS :=' + ' '.join(ldflags) + '\n'
|
||||
+ confstr + '.TOOLCHAIN.CFLAGS :=' + ' '.join(cflags) + '\n'
|
||||
+ confstr + '.TOOLCHAIN.PREFIX :=' + prefix + '\n'
|
||||
+ confstr + '.LIBS :=' + ' '.join(libs) + '\n'
|
||||
)
|
||||
|
||||
if not os.path.exists(board):
|
||||
os.mkdir(board)
|
||||
os.symlink(
|
||||
'../../board/%s/%s.ld' % (board,board),
|
||||
'%s/%s.ld' % (board,board)
|
||||
)
|
||||
|
||||
valid_board_list.append(board)
|
||||
|
||||
file.write('CONFIG.BOARD-LIST := ' + ' '.join(valid_board_list) + '\n')
|
||||
|
||||
def format_check(file, format_list):
|
||||
file.write('CONFIG.FORMAT-LIST :=')
|
||||
for _format in format_list:
|
||||
if not (_format in ["static", "dynamic", "all"]):
|
||||
print("%s: unreconized format '%s'" % (sys.argv[0], _format))
|
||||
exit(84)
|
||||
if _format == 'all':
|
||||
file.write(' dynamic static\n')
|
||||
return
|
||||
file.write(' ' + _format)
|
||||
if not format_list:
|
||||
file.write(' dynamic')
|
||||
file.write('\n')
|
||||
|
||||
def prefix_check(file, prefix):
|
||||
file.write('CONFIG.INSTALL-PREFIX :=' + prefix + '\n')
|
||||
|
||||
def verbose_check(file, verbose):
|
||||
file.write('CONFIG.VERBOSE :=\n')
|
||||
|
||||
#
|
||||
# "real" entry of the script
|
||||
#
|
||||
|
||||
def main():
|
||||
args = parse_arguments()
|
||||
|
||||
if os.path.exists('../src') == False:
|
||||
print('error: you should configure from a build directory, like this:')
|
||||
print(' mkdir build && cd build && ../configure [options..]')
|
||||
exit(84)
|
||||
|
||||
file = open('kernel.cfg', 'w')
|
||||
|
||||
board_check(file, args['board'])
|
||||
format_check(file, args['format'])
|
||||
prefix_check(file, args['prefix'])
|
||||
verbose_check(file, args['prefix'])
|
||||
|
||||
if os.path.exists('Makefile'):
|
||||
os.remove('Makefile')
|
||||
os.symlink('../make/Makefile', 'Makefile')
|
||||
|
||||
main()
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef __VHEX_ARCH_FXCG50_HARDWARE__
|
||||
# define __VHEX_ARCH_FXCG50_HARDWARE__
|
||||
|
||||
/* define devices list */
|
||||
#define HWDEVICE_FXCG50 0
|
||||
#define HWDEVICE_PRIZM 1
|
||||
#define HWDEVICE_FXCG_MANAGER 2
|
||||
|
||||
/* define MPU list */
|
||||
#define HWMPU_SH7305 0
|
||||
|
||||
#endif /*__VHEX_ARCH_FXCG50_HARDWARE__*/
|
|
@ -0,0 +1,37 @@
|
|||
//---
|
||||
// vhex:defs:attributes - Macros for compiler-specific attributes
|
||||
//---
|
||||
|
||||
#ifndef __VHEX_DEFS_ATTRIBUTES__
|
||||
# define __VHEX_DEFS_ATTRIBUTES__
|
||||
|
||||
/* Objects from specific sections */
|
||||
#define VSECTION(x) __attribute__((section(x)))
|
||||
|
||||
/* Unused parameters or variables */
|
||||
#define VUNUSED __attribute__((unused))
|
||||
/* Functions that *must* be inlined */
|
||||
#define VINLINE __attribute__((always_inline)) inline
|
||||
|
||||
/* Aligned variables */
|
||||
#define VALIGNED(x) __attribute__((aligned(x)))
|
||||
/* Packed structures. I require explicit alignment because if it's unspecified,
|
||||
GCC cannot optimize access size, and reads to memory-mapped I/O with invalid
|
||||
access sizes silently fail - honestly you don't want this to happen */
|
||||
#define VPACKED(x) __attribute__((packed, aligned(x)))
|
||||
/* Packed enumerations */
|
||||
#define VPACKEDENUM __attribute__((packed))
|
||||
/* Transparent unions */
|
||||
#define VTRANSPARENT __attribute__((transparent_union))
|
||||
|
||||
/* Weak symbols */
|
||||
#define VWEAK __attribute__((weak))
|
||||
|
||||
/* Constructors */
|
||||
#define VCONSTRUCTOR __attribute__((constructor))
|
||||
#define VDESTRUCTOR __attribute__((destructor))
|
||||
|
||||
/* Functions that do not return */
|
||||
#define VNORETURN __attribute__((noreturn))
|
||||
|
||||
#endif /*__VHEX_DEFS_ATTRIBUTES__*/
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef __VHEX_DEFS_TYPES__
|
||||
# define __VHEX_DEFS_TYPES__
|
||||
|
||||
#include <vhex/defs/attributes.h>
|
||||
|
||||
/* For size_t, mainly */
|
||||
#include <stddef.h>
|
||||
/* For all fixed-width integer types */
|
||||
#include <stdint.h>
|
||||
/* For human-readable boolean types */
|
||||
#include <stdbool.h>
|
||||
/* Common system types: ssize_t, off_t, etc. */
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Fixed-width types for bit fields are quite meaningless */
|
||||
typedef unsigned int uint;
|
||||
|
||||
//---
|
||||
// Structure elements
|
||||
//----
|
||||
|
||||
/* Giving a type to padding bytes is misguiding, let's hide it in a macro */
|
||||
#define pad_nam2(c) _ ## c
|
||||
#define pad_name(c) pad_nam2(c)
|
||||
#define pad(bytes) uint8_t pad_name(__COUNTER__)[bytes]
|
||||
|
||||
/* byte_union() - union between an uint8_t 'byte' element and a bit field */
|
||||
#define byte_union(name, fields) \
|
||||
union { \
|
||||
uint8_t byte; \
|
||||
struct { fields } VPACKED(1); \
|
||||
} VPACKED(1) name
|
||||
|
||||
/* word_union() - union between an uint16_t 'word' element and a bit field */
|
||||
#define word_union(name, fields) \
|
||||
union { \
|
||||
uint16_t word; \
|
||||
struct { fields } VPACKED(2); \
|
||||
} VPACKED(2) name
|
||||
|
||||
/* lword_union() - union between an uint32_t 'lword' element and a bit field */
|
||||
#define lword_union(name, fields) \
|
||||
union { \
|
||||
uint32_t lword; \
|
||||
struct { fields } VPACKED(4); \
|
||||
} VPACKED(4) name
|
||||
|
||||
|
||||
|
||||
#endif /*__VHEX_DEFS_TYPES__*/
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef __VHEX_HARDWARE_H__
|
||||
# define __VHEX_HARDWARE_H__
|
||||
|
||||
#include <vhex/defs/types.h>
|
||||
|
||||
/* hw_detect(): Basic hardware detection */
|
||||
extern void hw_detect(void);
|
||||
|
||||
/* Most of the information here is going to be stored in (key, value) pairs for
|
||||
predetermined keys and 32-bits values that are often integers or a set of
|
||||
flags. The data will be filled by vhex or its drivers. */
|
||||
#define HW_KEYS 16
|
||||
extern uintptr_t vhex[HW_KEYS];
|
||||
|
||||
/*
|
||||
** Key list
|
||||
*/
|
||||
|
||||
#define HWMPU 0 /* MPU type */
|
||||
#define HWCPUVR 1 /* CPU Version Register */
|
||||
#define HWCPUPR 2 /* CPU Product Register */
|
||||
#define HWDEVICE 3 /* Device model */
|
||||
#define HWRAM_PHY_USER 4 /* Physical RAM address (user) */
|
||||
#define HWRAM_PHY_ORIGIN 5 /* Physical RAM address (origin) */
|
||||
#define HWRAM_PHY_SIZE 6 /* Physical RAM size */
|
||||
|
||||
#endif /*__VHEX_HARDWARE_H__*/
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef __VHEX_KERNEL_H__
|
||||
# define __VHEX_KERNEL_H__
|
||||
|
||||
/* kinit(): Install and start vhex */
|
||||
void kinit(void);
|
||||
|
||||
/* kquit(): Quit vhex and give back control to the system */
|
||||
void kquit(void);
|
||||
|
||||
#endif /*__VHEX_KERNEL_H__*/
|
|
@ -0,0 +1,16 @@
|
|||
//---
|
||||
// vhex:mmu - Memory Management Unit
|
||||
//---
|
||||
|
||||
#ifndef __VHEX_MMU__
|
||||
# define __VHEX_MMU__
|
||||
|
||||
#include <vhex/defs/types.h>
|
||||
|
||||
/* mmu_translate(): Get the physical address for a virtual page
|
||||
Looks for a translation with the specified virtual address as start, and
|
||||
returns the corresponding physical address. Only works if the argument is
|
||||
page-aligned. */
|
||||
extern uintptr_t mmu_translate(uintptr_t page, size_t *size);
|
||||
|
||||
#endif /*__VHEX_MMU__*/
|
|
@ -0,0 +1,123 @@
|
|||
//---
|
||||
// vhex:mpu:mmu - Memory Management Unit
|
||||
//
|
||||
// The MMU mainly exposes the contents of the TLB for us to inspect.
|
||||
// Functions to manipulate these are exposed by <vhex/mmu.h>.
|
||||
//---
|
||||
|
||||
|
||||
#ifndef __VHEX_MPU_SH7305_MMU__
|
||||
# define __VHEX_MPU_SH7305_MMU__
|
||||
|
||||
#include <vhex/defs/attributes.h>
|
||||
|
||||
//---
|
||||
// SH7305 TLB. Refer to:
|
||||
// "Renesas SH7724 User's Manual: Hardware"
|
||||
// Section 7: "Memory Management Unit (MMU)"
|
||||
//---
|
||||
|
||||
/* utlb_addr - address part of a UTLB entry */
|
||||
struct utlb_addr
|
||||
{
|
||||
uint VPN :22;
|
||||
uint D :1;
|
||||
uint V :1;
|
||||
uint ASID :8;
|
||||
|
||||
} VPACKED(4);
|
||||
|
||||
/* utlb_data - data part of a UTLB entry */
|
||||
struct utlb_data
|
||||
{
|
||||
uint :3;
|
||||
uint PPN :19;
|
||||
uint :1;
|
||||
uint V :1;
|
||||
uint SZ1 :1;
|
||||
uint PR :2;
|
||||
uint SZ2 :1;
|
||||
uint C :1;
|
||||
uint D :1;
|
||||
uint SH :1;
|
||||
uint WT :1;
|
||||
|
||||
} VPACKED(4);
|
||||
|
||||
/* sh7305_mmu - MMU definition */
|
||||
struct sh7305_mmu
|
||||
{
|
||||
lword_union(PTEH,
|
||||
uint32_t VPN :22; /* Virtual Page Number */
|
||||
uint32_t :2;
|
||||
uint32_t ASID :8; /* Address Space Identifier */
|
||||
);
|
||||
|
||||
lword_union(PTEL,
|
||||
uint32_t :3;
|
||||
uint32_t PPN :19; /* Phusical Page Number */
|
||||
uint32_t :1;
|
||||
uint32_t V :1; /* Valid */
|
||||
uint32_t SZ1 :1; /* Size (bit 1) */
|
||||
uint32_t PR :2; /* Protection */
|
||||
uint32_t SZ0 :1; /* Size (bit 0) */
|
||||
uint32_t C :1; /* Cacheable */
|
||||
uint32_t D :1; /* Dirty */
|
||||
uint32_t SH :1; /* Shared */
|
||||
uint32_t WT :1; /* Write-through */
|
||||
);
|
||||
|
||||
uint32_t TTB;
|
||||
uint32_t TEA;
|
||||
|
||||
lword_union(MMUCR,
|
||||
uint32_t LRUI :6; /* Least-Recently Used ITLB */
|
||||
uint32_t :2;
|
||||
uint32_t URB :6; /* UTLB Replace Boundary */
|
||||
uint32_t :2;
|
||||
uint32_t URC :6; /* UTLB Replace Counter */
|
||||
uint32_t :1;
|
||||
uint32_t SV :1; /* Single Virtual Memory Mode */
|
||||
uint32_t ME :1; /* TLB Extended Mode */
|
||||
uint32_t :4;
|
||||
uint32_t TI :1; /* TLB Invalidate */
|
||||
uint32_t :1;
|
||||
uint32_t AT :1; /* Address Translation */
|
||||
);
|
||||
pad(0x20);
|
||||
|
||||
lword_union(PTEA,
|
||||
uint32_t :18;
|
||||
uint32_t EPR :6;
|
||||
uint32_t ESZ :4;
|
||||
uint32_t :4;
|
||||
);
|
||||
pad(0x38);
|
||||
|
||||
lword_union(PASCR,
|
||||
uint32_t :24;
|
||||
uint32_t UBC :1; /* Control register area */
|
||||
uint32_t UB6 :1; /* Area 6 */
|
||||
uint32_t UB5 :1; /* Area 5 */
|
||||
uint32_t UB4 :1; /* Area 4 */
|
||||
uint32_t UB3 :1; /* Area 3 */
|
||||
uint32_t UB2 :1; /* Area 2 */
|
||||
uint32_t UB1 :1; /* Area 1 */
|
||||
uint32_t UB0 :1; /* Area 0 */
|
||||
);
|
||||
pad(4);
|
||||
|
||||
lword_union(IRMCR,
|
||||
uint32_t :27;
|
||||
uint32_t R2 :1; /* Re-fetch after Register 2 change */
|
||||
uint32_t R1 :1; /* Re-fetch after Register 1 change */
|
||||
uint32_t LT :1; /* Re-fetch after LDTLB */
|
||||
uint32_t MT :1; /* Re-fetch after writing TLB */
|
||||
uint32_t MC :1; /* Re-fetch after writing insn cache */
|
||||
);
|
||||
|
||||
} VPACKED(4);
|
||||
|
||||
#define SH7305_MMU (*(volatile struct sh7305_mmu *)0xff000000)
|
||||
|
||||
#endif /*__VHEX_MPU_SH7305_MMU__*/
|
|
@ -0,0 +1,78 @@
|
|||
//---
|
||||
// vhex:mpu:pfc - Pin Function Controller
|
||||
//
|
||||
// The Pin Function Controller has a simple register interface, the main
|
||||
// difficulty is still understanding the role of its pins.
|
||||
//---
|
||||
|
||||
#ifndef __VHEX_MPU_SH7305_PFC__
|
||||
# define __VHEX_MPU_SH7305_PFC__
|
||||
|
||||
#include <vhex/defs/attributes.h>
|
||||
#include <vhex/defs/types.h>
|
||||
|
||||
//---
|
||||
// SH7305 Pin Function Controller. Refer to:
|
||||
// "Renesas SH7705 Group Hardware Manual"
|
||||
// Section 19: "Pin Function Controller"
|
||||
//
|
||||
// Note that we don't have any reliable information concerning this module, this
|
||||
// is why we don't havec any bitfields here.
|
||||
//---
|
||||
|
||||
struct sh7305_pfc
|
||||
{
|
||||
/* Control registers */
|
||||
uint16_t PACR;
|
||||
uint16_t PBCR;
|
||||
uint16_t PCCR;
|
||||
uint16_t PDCR;
|
||||
uint16_t PECR;
|
||||
uint16_t PFCR;
|
||||
uint16_t PGCR;
|
||||
uint16_t PHCR;
|
||||
uint16_t PJCR;
|
||||
uint16_t PKCR;
|
||||
uint16_t PLCR;
|
||||
uint16_t SCPCR; /* Port SC control register */
|
||||
uint16_t PMCR;
|
||||
uint16_t PNCR;
|
||||
|
||||
pad(4);
|
||||
|
||||
/* Data registers */
|
||||
uint8_t PADR;
|
||||
pad(1);
|
||||
uint8_t PBDR;
|
||||
pad(1);
|
||||
uint8_t PCDR;
|
||||
pad(1);
|
||||
uint8_t PDDR;
|
||||
pad(1);
|
||||
uint8_t PEDR;
|
||||
pad(1);
|
||||
uint8_t PFDR;
|
||||
pad(1);
|
||||
uint8_t PGDR;
|
||||
pad(1);
|
||||
uint8_t PHDR;
|
||||
pad(1);
|
||||
uint8_t PJDR;
|
||||
pad(1);
|
||||
uint8_t PKDR;
|
||||
pad(1);
|
||||
uint8_t PLDR;
|
||||
pad(1);
|
||||
uint8_t SCPDR; /* Port SC data register */
|
||||
pad(1);
|
||||
uint8_t PMDR;
|
||||
pad(1);
|
||||
uint8_t PNDR;
|
||||
pad(1);
|
||||
|
||||
} VPACKED(4);
|
||||
|
||||
#define SH7305_PFC (*((volatile struct sh7305_pfc *)0xa4000100))
|
||||
|
||||
|
||||
#endif /*__VHEX_MPU_SH7305_PFC__*/
|
|
@ -0,0 +1,336 @@
|
|||
#!/usr/bin/make -f
|
||||
# ---
|
||||
# Project: vxKernek - Vhex project kernel
|
||||
# Author: yann.magnin@epitech.eu
|
||||
#
|
||||
# TODO:
|
||||
# <> support header modification detection
|
||||
# <> remove "target" folder on any directory
|
||||
# <> installation rule
|
||||
# <> uninstall rule
|
||||
# ---
|
||||
|
||||
|
||||
#---
|
||||
# Build rules
|
||||
#---
|
||||
|
||||
# Make selects the first rule set when you type "make" but, in our case, we are
|
||||
# going to generate most of the rules. So, we set a placeholder to force the
|
||||
# "all" rule to be the "first" rule
|
||||
first: all
|
||||
|
||||
# display the library version
|
||||
version:
|
||||
@echo "$(VXSDK_PKG_VERSION)"
|
||||
|
||||
# Display helper
|
||||
help:
|
||||
@ echo 'Rules listing:'
|
||||
@ echo '... all the default, if no target is provided'
|
||||
@ echo '... clean remove build object'
|
||||
@ echo '... fclean remove all generated object'
|
||||
@ echo '... re same as `make fclean all`'
|
||||
@ echo '... version display version'
|
||||
@ echo '... install install the library'
|
||||
@ echo '... uninstall uninstall the library'
|
||||
|
||||
.PHONY: help version first
|
||||
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Check config step validity
|
||||
#---
|
||||
|
||||
# Require configuration file
|
||||
CONFIG := kernel.cfg
|
||||
ifeq "$(wildcard $(CONFIG))" ""
|
||||
$(error "config file $(CONFIG) does not exist (you should use `../configure`")
|
||||
endif
|
||||
include $(CONFIG)
|
||||
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Variables definition
|
||||
#---
|
||||
|
||||
# Many variables will be provided by the "kernel.cfg" file (generated during
|
||||
# the configuration path). It will defines:
|
||||
# <> BOARD - indicate the target board list
|
||||
# <> {BOARD}-SRC-MODULE-PATH - list of all sources path for a specific board
|
||||
# <> {BOARD}-TOOLCHAIN-PREFIX - toolchain prefix for a board (sh-elf, ...)
|
||||
# <> FORMAT - format for the kernel (static, dynamic)
|
||||
|
||||
# color definition, for swagg :D
|
||||
red := \033[1;31m
|
||||
green := \033[1;32m
|
||||
blue := \033[1;34m
|
||||
white := \033[1;37m
|
||||
nocolor := \033[1;0m
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Rules definition
|
||||
#---
|
||||
|
||||
# The objectif is to generate a building this build tree:
|
||||
#
|
||||
# build/:
|
||||
# |-- kernel.cfg
|
||||
# |-- <board_name>/:
|
||||
# | |-- <format>/:
|
||||
# | | |-- obj/:
|
||||
# | | | |-- main.o
|
||||
# ...
|
||||
# | | | `-- initialize.o
|
||||
# | | `-- map
|
||||
# | |-- <board_name>.ld
|
||||
# | `-- libvxkernel-<format>.[so/a]
|
||||
# `-- Makefile
|
||||
|
||||
# Function that will generate a rule for one object file
|
||||
# @param
|
||||
# *1 - GCC name (with specific prefix if needed)
|
||||
# *2 - CFLAGS list
|
||||
# *3 - source file path
|
||||
# *4 - build root directory path
|
||||
# *5 - object file compilation rule list
|
||||
# *6 - unique id (used to generate unique variable name (workaround))
|
||||
define generate-compile-file-rule
|
||||
|
||||
# generate the object file path
|
||||
# @note
|
||||
# <> This is alse the generated rule name
|
||||
# <> step:
|
||||
# 1) ../board/path/file.c -> ../board/path/file
|
||||
# 2) .._board_path_file -> board_path_file
|
||||
# 3) board_path_file.o -> {build path}/board_path_file.o
|
||||
tname := $(strip $6)
|
||||
obj-$(tname)-name := $$(basename $3)
|
||||
obj-$(tname)-name := $$(subst /,_,$$(obj-$(tname)-name))
|
||||
obj-$(tname)-name := $$(patsubst .._%,$4/%.o,$$(obj-$(tname)-name))
|
||||
|
||||
# generate the building rule
|
||||
|
||||
$$(obj-$(tname)-name): $3
|
||||
@ mkdir -p $$(dir $$@)
|
||||
ifeq ($(CONFIG.VERBOSE),)
|
||||
@ printf "$(green)>$(nocolor) $(white)$$@$(nocolor)\n"
|
||||
@ $1 $2 -o $$@ -c $$<
|
||||
else
|
||||
$1 $2 -o $$@ -c $$<
|
||||
endif
|
||||
|
||||
# register the buildinf rule
|
||||
|
||||
$5 += $$(obj-$(tname)-name)
|
||||
|
||||
endef
|
||||
|
||||
|
||||
|
||||
# Function that will generate all rules for a specific board and format
|
||||
# @params
|
||||
# *1 - board name
|
||||
# *2 - format name (static or dynamic)
|
||||
# *3 - rules list variable name
|
||||
define generate-target-lib
|
||||
|
||||
# generate common information
|
||||
# @note:
|
||||
# Because we generate rule "on-the-fly" we need to create unique variable
|
||||
# definition because make is not a "scoped" language. (therefore, when a
|
||||
# variable is created, it will never be destroyed until the end of the script)
|
||||
t-$1-$2-build := $(VXSDK_BUILD_PREFIX)/$1/$2
|
||||
|
||||
# generate compilation flags
|
||||
|
||||
t-$1-$2-ar := $$(CONFIG.$1.TOOLCHAIN.PREFIX)ar
|
||||
t-$1-$2-ld := $$(CONFIG.$1.TOOLCHAIN.PREFIX)ld
|
||||
t-$1-$2-gcc := $$(CONFIG.$1.TOOLCHAIN.PREFIX)gcc
|
||||
t-$1-$2-ldflags := $$(CONFIG.$1.TOOLCHAIN.LDFLAGS)
|
||||
t-$1-$2-cflags := $$(CONFIG.$1.TOOLCHAIN.CFLAGS)
|
||||
t-$1-$2-cflags += -fpic -ffreestanding -nostdlib -fstrict-volatile-bitfields
|
||||
|
||||
# generate compiler information (used to find some library like libgcc.a)
|
||||
t-$1-$2-gcc-base := $$(shell $$(CONFIG.$1.TOOLCHAIN.PREFIX)gcc --print-search-dirs | grep install | sed 's/install: //')
|
||||
t-$1-$2-gcc-header := $$(t-$1-$2-gcc-base)/include
|
||||
t-$1-$2-cflags += -I../include -I.. -I$$(t-$1-$2-gcc-header)
|
||||
t-$1-$2-cflags += -L../lib -L.. -L$$(t-$1-$2-gcc-base)
|
||||
|
||||
|
||||
# generate format-specific flags
|
||||
|
||||
t-$1-$2-exec :=
|
||||
ifeq ($2,static)
|
||||
t-$1-$2-exec := $1/libvhex-$1.a
|
||||
endif
|
||||
ifeq ($2,dynamic)
|
||||
t-$1-$2-ldflags += -shared -T $1/$1.ld
|
||||
t-$1-$2-ldflags += -soname=libvxkernel-$1-$(VXSDK_PKG_VERSION).so
|
||||
t-$1-$2-ldflags += -Map=$$(t-$1-$2-build)/map
|
||||
t-$1-$2-exec := $1/libvxkernel-$1.so
|
||||
endif
|
||||
|
||||
# generate file's sources list, based on the configuration step
|
||||
|
||||
t-$1-$2-dir := $$(foreach module,$$(CONFIG.$1.SRC-MODULE-PATH),\
|
||||
$$(shell find $$(module) -type d))
|
||||
t-$1-$2-src := $$(foreach path,$$(t-$1-$2-dir),\
|
||||
$$(wildcard $$(path)/*.c) \
|
||||
$$(wildcard $$(path)/*.S) \
|
||||
$$(wildcard $$(path)/*.s))
|
||||
|
||||
# generate file's compilation rules and all object filename into an object
|
||||
# list variable, this will be used by the `main` rule
|
||||
|
||||
t-$1-$2-obj :=
|
||||
$$(foreach source,$$(t-$1-$2-src),$$(eval \
|
||||
$$(call generate-compile-file-rule,\
|
||||
$$(t-$1-$2-gcc),\
|
||||
$$(t-$1-$2-cflags),\
|
||||
$$(source),\
|
||||
$$(t-$1-$2-build),\
|
||||
t-$1-$2-obj,\
|
||||
$1-$2\
|
||||
))\
|
||||
)
|
||||
|
||||
|
||||
# generate the "main" rule for this lib
|
||||
|
||||
$$(t-$1-$2-exec): $$(t-$1-$2-obj)
|
||||
@ mkdir -p $$(dir $$@)
|
||||
@ printf "$(blue)Create the library $(red)$$@$(nocolor)\n"
|
||||
ifeq ($2,dynamic)
|
||||
$$(t-$1-$2-gcc) -shared $$(t-$1-$2-gcc-libs) -o $$@ $$^
|
||||
else
|
||||
$$(t-$1-$2-ar) crs $$@ $$^
|
||||
endif
|
||||
|
||||
# register the "main" building rule for the lib
|
||||
|
||||
$3 += $$(t-$1-$2-exec)
|
||||
|
||||
endef
|
||||
|
||||
|
||||
# Generate the "main" rules list
|
||||
target-lib-list :=
|
||||
$(foreach board,$(CONFIG.BOARD-LIST),\
|
||||
$(foreach format,$(CONFIG.FORMAT-LIST),$(eval\
|
||||
$(call generate-target-lib,$(board),$(format),target-lib-list)\
|
||||
))\
|
||||
)
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Build rules
|
||||
#---
|
||||
all: $(target-lib-list)
|
||||
|
||||
.PHONY: all
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Generate installation rules
|
||||
#---
|
||||
# Common rules generated for the installation of each libraries.
|
||||
# Basically, it will generate <libname>-install and <libname>-uninstall rules
|
||||
# @note:
|
||||
# *1 - library pathname
|
||||
# *2 - variable name (installation rules list)
|
||||
# *3 - variable name (uninstallation rules list)
|
||||
define generate-install-rule
|
||||
|
||||
# Generate the installation rule
|
||||
$(basename $(notdir $1))-install:
|
||||
install -d $(VXSDK_LIB_PREFIX)
|
||||
install $1 -m 644 $(VXSDK_LIB_PREFIX)
|
||||
|
||||
# Generate the uninstallation rule
|
||||
$(basename $(notdir $1))-uninstall:
|
||||
rm -f $(VXSDK_LIB_PREFIX)/$(notdir $1)
|
||||
|
||||
# Register generated rules into their appropriate list
|
||||
$2 += $(basename $(notdir $1))-install
|
||||
$3 += $(basename $(notdir $1))-uninstall
|
||||
endef
|
||||
|
||||
# Common rules generated for the installation of board-specific linker script
|
||||
# @note:
|
||||
# $1 - board name
|
||||
# $2 - variable name (installation rules list)
|
||||
# $3 - variable name (uninstallation rules list)
|
||||
define generate-board-install-rule
|
||||
|
||||
$1-install:
|
||||
install -d $(VXSDK_LIB_PREFIX)
|
||||
install ../board/$(strip $1)/$(strip $1).ld -m 644 $(VXSDK_LIB_PREFIX)
|
||||
|
||||
$1-uninstall:
|
||||
rm -f $(VXSDK_LIB_PREFIX)/$(strip $1).ld
|
||||
|
||||
$2 += $1-install
|
||||
$3 += $1-uninstall
|
||||
|
||||
endef
|
||||
|
||||
# Generate all installation/uninstallation rules
|
||||
|
||||
target-install-rules :=
|
||||
target-uninstall-rules :=
|
||||
$(foreach target,$(target-lib-list),$(eval \
|
||||
$(call generate-install-rule, \
|
||||
$(target), \
|
||||
target-install-rules, \
|
||||
target-uninstall-rules \
|
||||
) \
|
||||
))
|
||||
$(foreach board,$(CONFIG.BOARD-LIST),$(eval \
|
||||
$(call generate-board-install-rule, \
|
||||
$(board), \
|
||||
target-install-rules, \
|
||||
target-uninstall-rules \
|
||||
) \
|
||||
))
|
||||
|
||||
# Generate the path where include directory will be installed.
|
||||
target-install-hdr-dir := $(VXSDK_LIB_PREFIX)/include/
|
||||
ifeq ($(wildcard $(target-install-header-dir)vhex/.*),)
|
||||
target-install-hdr-dir := $(target-install-hdr-dir)vhex
|
||||
endif
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Installation rules
|
||||
#---
|
||||
install: $(target-install-rules)
|
||||
cp -r ../include/vhex $(target-install-hdr-dir)
|
||||
|
||||
unsintall: $(target-uninstall_rules)
|
||||
rm -rf $(VXSDK_LIB_PREFIX)/include/vhex
|
||||
|
||||
.PHONY: install uninstall
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# cleaning rules
|
||||
#---
|
||||
#clean: TODO: generate clean rule list
|
||||
|
||||
|
||||
fclean: clean
|
||||
rm -rf $(target-lib-list)
|
||||
re: fclean all
|
||||
|
||||
.PHONY: clean fclean re all
|
|
@ -0,0 +1,43 @@
|
|||
//---
|
||||
// vhex:mmu:mmu - MMU driver definition and context management
|
||||
//---
|
||||
#include <vhex/mmu.h>
|
||||
#include <vhex/mpu/sh7305/mmu.h>
|
||||
#include <vhex/defs/attributes.h>
|
||||
|
||||
/* utlb_addr() - get the P4 address of a UTLB address entry */
|
||||
VINLINE const struct utlb_addr *utlb_addr(uint E)
|
||||
{
|
||||
uintptr_t addr = 0xf6000000 | ((E & 0x3f) << 8);
|
||||
return (void *)addr;
|
||||
}
|
||||
|
||||
/* utlb_data() - get the P4 address of a UTLB data entry */
|
||||
VINLINE const struct utlb_data *utlb_data(uint E)
|
||||
{
|
||||
uintptr_t addr = 0xf7000000 | ((E & 0x3f) << 8);
|
||||
return (void *)addr;
|
||||
}
|
||||
|
||||
/* mmu_translate(): Get the physical address for a virtual page */
|
||||
uintptr_t mmu_translate(uintptr_t page, size_t *size)
|
||||
{
|
||||
for(int E = 0; E < 64; E++)
|
||||
{
|
||||
const struct utlb_addr *addr = utlb_addr(E);
|
||||
const struct utlb_data *data = utlb_data(E);
|
||||
if(!addr->V || !data->V) continue;
|
||||
|
||||
if((uintptr_t)addr->VPN << 10 == page)
|
||||
{
|
||||
/* Magic formula to get the size without using an array
|
||||
since this code is used even before global data is
|
||||
posibly initialized */
|
||||
int sz = ((data->SZ1 << 1) | data->SZ2) << 3;
|
||||
if(size) *size = 1 << ((0x14100c0a >> sz) & 0xff);
|
||||
|
||||
return data->PPN << 10;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#include <vhex/kernel.h>
|
||||
|
||||
//---
|
||||
// Initialization and unloading
|
||||
//---
|
||||
|
||||
/* kinit(): Install and start vhex */
|
||||
void kinit(void)
|
||||
{
|
||||
//TODO: initialize kmalloc()
|
||||
//TODO: initialize hypervisor
|
||||
//TODO: perform a world-switch "in"
|
||||
}
|
||||
|
||||
/* kquit(): Quit vhex and give back control to the system */
|
||||
void kquit(void)
|
||||
{
|
||||
//TODO: perform a world-switch "out"
|
||||
//TODO: free'd allocated world information
|
||||
}
|
Loading…
Reference in New Issue