Add scheduler first release + fix process stack crash

This commit is contained in:
Yann MAGNIN 2020-02-05 21:09:39 +01:00
parent 223f92b6b2
commit 105eb7c482
48 changed files with 1168 additions and 253 deletions

View File

@ -7,6 +7,7 @@
KERNEL := output/vhex.g1a
USER := output/shell.elf
TEST := output/test.elf
##---
@ -15,11 +16,13 @@ USER := output/shell.elf
all:
@ make --no-print-directory -C src/lib
@ make --no-print-directory -C src/kernel
@ make --no-print-directory -C src/user
@ make --no-print-directory -C src/user/shell
@ make --no-print-directory -C src/user/test
install: all
sudo p7 send --force --no-term $(KERNEL)
sudo p7 send --force --directory=VHEX $(USER)
sudo p7 send --force --no-term --directory=VHEX $(USER)
sudo p7 send --force --directory=VHEX $(TEST)
@ -30,12 +33,15 @@ install: all
clean:
make clean --no-print-directory -C src/lib
make clean --no-print-directory -C src/kernel
make clean --no-print-directory -C src/user
make clean --no-print-directory -C src/user/shell
make clean --no-print-directory -C src/user/test
fclean: clean
make fclean --no-print-directory -C src/lib
make fclean --no-print-directory -C src/kernel
make fclean --no-print-directory -C src/user
make fclean --no-print-directory -C src/user/shell
make fclean --no-print-directory -C src/user/test
rm -rf build
re: fclean all

View File

@ -1,18 +0,0 @@
#ifndef __KERNEL_DEVICES_TIMER_H__
# define __KERNEL_DEVICES_TIMER_H__
#include <stddef.h>
#include <stdint.h>
// TODO: MOVE ME !!!!!!!!
#define TIMER_NUMBER 3
#define TIMER_UNUSED 0xff
struct timer_cache_s
{
void *callback;
volatile void *arg;
uint8_t status;
};
#endif /*__KERNEL_DEVICES_TIMER_H__*/

View File

@ -0,0 +1,80 @@
#ifndef __KERNEL_HARDWARE_CPG_H__
# define __KERNEL_HARDWARE_CPG_H__
#include <stddef.h>
#include <stdint.h>
#include <kernel/def/union_types.h>
#include <kernel/def/attributes.h>
struct SH7305_cpg_s
{
volatile long_union(FRQCRA, /* Casio's configuration: 0x0f212213 */
uint32_t KICK : 1; /* Kick bits */
uint32_t const : 1; /* All 0 */
uint32_t STC : 6; /* PLL circuit multiplication ratio */
uint32_t IFC : 4; /* CPU clock frequency division ratio */
uint32_t const : 4; /* All 0 */
uint32_t SFC : 4; /* S clock frequency division ratio */
uint32_t BFC : 4; /* Bus clock frequency division ration */
uint32_t const : 4; /* All 0 */
uint32_t PFC : 4; /* Peripheral clock frequency division ratio */
);
volatile uint32_t FRQCRB; /* Undocumented (0x00000000) */
volatile long_union(FCLKACR, /* Casio's configuration: 0x00000157 */
uint32_t const : 16; /* All 0 */
uint32_t unknown : 16; /* Unknown (default 0x0157) */
);
volatile long_union(FCLKBCR, /* Casio's configuration: 0x0000003f */
uint32_t const : 16; /* All 0 */
uint32_t unknown : 16; /* Unknown (default 0x003f) */
);
GAPS(0x08);
volatile long_union(IRDACLKCR, /* Casio's configuration: 0x0000003f */
uint32_t const : 16; /* All 0 */
uint32_t unknown : 16; /* Unknown (default 0x003f) */
);
GAPS(0x08);
volatile long_union(PLLCR, /* Casio's configuration: 0x00005000 */
uint32_t const : 16; /* All 0 */
uint32_t unknown0 : 1; /* Unknown (default 0) */
uint32_t PLLE : 1; /* PLL enable (?) */
uint32_t const : 1; /* All 0 */
uint32_t FLLE : 1; /* FLL enable (?) */
uint32_t const : 8; /* All 0 */
uint32_t unknown1 : 4; /* Unknown (default 0b0000) */
);
GAPS(0x14);
volatile long_union(SPUCLKCR, /* Casio's configuration: 0x00000103 */
uint32_t const : 16; /* All 0 */
uint32_t unknown : 16; /* Unknown (default 0x0103) */
);
GAPS(0x08);
volatile long_union(VCLKCR, /* Casio's configuration: 0x0000003f */
uint32_t const : 16; /* All 0 */
uint32_t unknown : 16; /* Unknown (default 0x003f) */
);
GAPS(0x04);
volatile long_union(FLLFRQ, /* Casio's configuration: 0x00004384 */
uint32_t const : 16; /* All 0 */
uint32_t SELXM : 2; /* FLL output division */
uint32_t unknown : 3; /* Unknown */
uint32_t FLF : 11; /* FLL Multiplication Ratio */
);
GAPS(0x0c);
volatile long_union(LSTATS,
uint32_t const : 31; /* All 0 */
uint32_t const FQRF : 1; /* Frequency change status */
);
};
#define SH7305_CPG (*(volatile struct SH7305_cpg_s *)0xa4150000)
#endif /*__KERNEL_HARDWARE_CPG_H__*/

View File

@ -8,29 +8,29 @@
struct timer_s
{
volatile uint32_t TCOR; /* Timer Constant register */
volatile uint32_t TCNT; /* Timer Counter */
volatile word_union(TCR, /* Timer Control Register */
uint16_t const : 7; /* All 0 */
uint16_t UNF : 1; /* Underflow flags */
uint16_t const : 2; /* All 0 */
uint16_t UNIE : 1; /* Underflow interrup control */
uint16_t const : 2; /* All 0 */
uint16_t TPSC : 3; /* Time prescaler */
volatile uint32_t TCOR; /* Timer Constant register */
volatile uint32_t TCNT; /* Timer Counter */
volatile word_union(TCR, /* Timer Control Register */
uint16_t const : 7; /* All 0 */
uint16_t UNF : 1; /* Underflow flags */
uint16_t const : 2; /* All 0 */
uint16_t UNIE : 1; /* Underflow interrup control */
uint16_t CKREG : 2; /* Input Clock edge */
uint16_t TPSC : 3; /* Time prescaler */
);
GAPS(2);
};
struct __sh7305_tmu_s
{
volatile byte_union(TSTR, /* Timer Start Register */
uint8_t const : 5; /* All 0 */
uint8_t STR2 : 1; /* Counter start 2 */
uint8_t STR1 : 1; /* Counter start 1 */
uint8_t STR0 : 1; /* Counter start 0 */
volatile byte_union(TSTR, /* Timer Start Register */
uint8_t const : 5; /* All 0 */
uint8_t STR2 : 1; /* Counter start 2 */
uint8_t STR1 : 1; /* Counter start 1 */
uint8_t STR0 : 1; /* Counter start 0 */
);
GAPS(3);
volatile struct timer_s TIMER[3];
volatile struct timer_s TIMER[3]; /* Timers */
};
#define SH7305_TMU (*(volatile struct __sh7305_tmu_s *)0xa4490004)

View File

@ -15,7 +15,7 @@ struct pm_block_cache_s
} status;
// Space informations.
uint16_t start;
uint32_t start;
uint32_t end;
// Linked list

View File

@ -14,8 +14,6 @@
#define PROCESS_NAME_LENGHT (16)
#define PROCESS_MAX (4)
#define PROC_IDLE (0)
// define process struct.
//TODO: signal !
struct process
@ -93,6 +91,7 @@ struct process_stack
// Functions.
extern struct process *process_create(const char *name);
extern struct process *process_get(pid_t pid);
extern pid_t process_get_pid(struct process *process);
extern int process_switch(pid_t pid);
// Internal function.

View File

@ -59,10 +59,10 @@ extern int sched_add_task(struct process *process);
extern void sched_start(void);
/*
** Save current context of the current task and run the
** next one based on internal task priority.
** Get the current task context and the next one
** based on internal task priority / status.
*/
extern void sched_schedule(void);
extern int sched_schedule(common_context_t **current, common_context_t **next);
/*
** Internal function wich will switch current process

View File

@ -14,6 +14,8 @@ extern pid_t sys_fork(void);
extern pid_t sys_getpid(void);
extern pid_t sys_getppid(void);
extern pid_t sys_waitpid(pid_t pid, int *wstatus, int options);
extern pid_t sys_fexecve(const char *pathname);
extern void sys_exit(int status);
extern int sys_open(const char *pathname, int flags, ...);
extern ssize_t sys_write(int fd, const void *buf, size_t count);

View File

@ -6,7 +6,7 @@
// Process
#define __NR_exit 1
#define __NR_exec 2
#define __NR_fexecve 2
#define __NR_waitpid 3
// VFS
@ -27,6 +27,7 @@
#define __NR_kvram_ascii 12
#define __NR_kvram_reverse 13
#define __NR_kvram_scroll 14
#define __NR_kvram_clr_str_area 15
//TODO: keyboard

View File

@ -18,9 +18,9 @@ extern size_t strlen(char const *str);
extern void kvram_clear(void);
extern void kvram_display(void);
extern void kvram_scroll(int lines);
extern void kvram_reverse(int x, int y, int width, int height);
extern void kvram_print(int x, int y, char const *str);
extern void kvram_ascii(int x, int y, char const c);
extern void kvram_reverse(int x, int y, int width, int height);
extern void kvram_clr_str_area(int x, int y, int width, int height);
// Kernel printf-wrapper
extern void printk(int x, int y, char const *str, ...);
@ -28,9 +28,21 @@ extern void printk(int x, int y, char const *str, ...);
// Hardware specific function (do not use !)
extern void t6k11_display(void *vram);
// Timer functions.
//---
// Timer functions.
//---
#define TIMER_NUMBER 3
#define TIMER_UNUSED 0xff
struct timer_cache_s
{
void *callback;
volatile void *arg;
uint8_t status;
};
extern int timer_uninstall(int timer_ID);
extern int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode);
extern int timer_install(void *callback, void *arg, uint32_t ticks, uint8_t mode);
extern int timer_start(int timer_ID);
// Debug wait
#define DBG_WAIT for(int i = 0 ; i < 3000000 ; i++)

View File

@ -6,7 +6,8 @@
// Draw primtives
extern void dclear(void);
extern void dprint(int x, int y, char const *str);
extern void dclr_str_area(int x, int y, int with, int height);
extern void dprint(int x, int y, char const *str, ...);
extern void dascii(int x, int y, char const c);
extern void dreverse(int x, int y, int width, int height);
extern void dscroll(int line);

View File

@ -14,6 +14,7 @@
#define WUNTRACED 1
#define WCONTINUED 2
extern pid_t waitpid(pid_t pid, int *wstatus, int options);
extern pid_t fexecve(const char *pathname);
// File syscall
#define O_DIRECT 0

View File

@ -4,14 +4,6 @@
#include <stddef.h>
#include <stdint.h>
#define VHEX_BUILTIN(bname) \
static int bname(int argc, char **argv); \
__attribute__((section(".builtin"))) \
struct builtin_s _##bname = { \
.name = #bname, \
.entry = &bname \
}; \
static int bname(int argc, char **argv)
// Define builtin struct.
struct builtin_s
@ -20,5 +12,9 @@ struct builtin_s
int (*entry)(int argc, char **argv);
};
// Builtin list
extern int builtin_proc(void);
extern int builtin_ram(void);
#endif /*__USER_BUILTIN_H__*/

View File

@ -174,9 +174,9 @@ int start(void)
if (vhex_process == NULL)
{
kvram_clear();
kvram_print(0, 0, "Vhex fatal error !");
kvram_print(0, 1, "First process error !");
kvram_print(0, 2, "Wait manual reset...");
printk(0, 0, "Vhex fatal error !");
printk(0, 1, "First process error !");
printk(0, 2, "Wait manual reset...");
kvram_display();
while (1) { __asm__ volatile ("sleep"); }
}
@ -188,9 +188,9 @@ int start(void)
{
// Display message.
kvram_clear();
kvram_print(0, 0, "Vhex fatal error !");
kvram_print(0, 1, "File \"VHEX/shell.elf\" not found !");
kvram_print(0, 2, "Press [MENU key]...");
printk(0, 0, "Vhex fatal error !");
printk(0, 1, "File \"VHEX/shell.elf\" not found !");
printk(0, 2, "Press [MENU key]...");
kvram_display();
// Restore Casio context.
@ -225,7 +225,7 @@ int start(void)
// normally the kernel SHOULD / CAN not arrive here.
kvram_clear();
kvram_print(0, 0, "Kernel job fini !");
printk(0, 0, "Kernel job fini !");
kvram_display();
while (1)
{

View File

@ -42,7 +42,8 @@ ssize_t tty_read(void *inode, void *buffer, size_t count)
keyboard.saved.tty.cursor.y = tty.cursor.y;
// Initialize timer for cursor.
timer_fd = timer_install(&cursor_callback, &keyboard, 500, 1);
// FIXME: find real ticks value !!
timer_fd = timer_install(&cursor_callback, &keyboard, 500 * 500 * 2, 1);
if (timer_fd == -1)
return (0);

View File

@ -19,7 +19,7 @@ void *gladfs_mount(void)
if (gladfs_superblock.root_inode == NULL)
{
kvram_clear();
kvram_print(0, 0, "GladFS: ROOT inode alloc error !");
printk(0, 0, "GladFS: ROOT inode alloc error !");
kvram_display();
DBG_WAIT;
}

View File

@ -24,7 +24,7 @@ static int get_name(int *name_lenght, const char *path, char *name)
return (0);
}
//TODO add '..' handling.
//TODO: update ?
struct dentry *vfs_dentry_resolve(const char *path, int mode)
{
extern struct process *process_current;
@ -114,7 +114,6 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
printk(0, 3, "name: %s$", name);
kvram_display();
DBG_WAIT;
while (1);
return (NULL);
}
}
@ -138,7 +137,7 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
// Try to find first child
next = vfs_dentry_find_first_child(next);
if (next != NULL)
/*if (next != NULL)
{
// Debug !
kvram_clear();
@ -148,7 +147,7 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
printk(0, 3, "name: %s$", name);
kvram_display();
DBG_WAIT;
}
}*/
// Update name lenght to skip '/' char
name_lenght = name_lenght + 1;

View File

@ -62,7 +62,7 @@ int vfs_mknod(const char *pathname, mode_t mode, dev_t dev)
// Debug !
kvram_clear();
/*kvram_clear();
printk(0, 0, "New mknod device !");
printk(0, 1, "dentry: %p$", file);
printk(0, 2, "inode: %p$", file->inode);
@ -70,7 +70,7 @@ int vfs_mknod(const char *pathname, mode_t mode, dev_t dev)
printk(0, 4, "dev->file_op: %p$", &device->file_op);
kvram_display();
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;*/
// Set file operations
file->dentry_op.file_op = &device->file_op;

View File

@ -67,13 +67,13 @@ int vfs_mount(const char *source, const char *target,
vfs_root_node->dentry_op.inode_op = &filesystem->inode_operations;
// Debug !
kvram_clear();
/*kvram_clear();
printk(0, 0, "vfs_root_node = %p", vfs_root_node);
printk(0, 1, "vfs_root_node = %s$", vfs_root_node->name);
printk(0, 2, "vfs_root_node = %p", vfs_root_node->child);
printk(0, 3, "vfs_root_node = %p", vfs_root_node->next);
kvram_display();
DBG_WAIT;
DBG_WAIT;*/
return (0);
}

View File

@ -1,16 +0,0 @@
#include <kernel/hardware/tmu.h>
#include <kernel/devices/timer.h>
// Internal timer "cache".
struct timer_cache_s timercache[TIMER_NUMBER];
__attribute__((constructor))
void timer_constructor(void)
{
for (int i = 0 ; i < TIMER_NUMBER ; i = i + 1)
{
timercache[i].status = TIMER_UNUSED;
timercache[i].callback = NULL;
timercache[i].arg = NULL;
}
}

View File

@ -1,9 +1,10 @@
#include <kernel/hardware/tmu.h>
#include <kernel/devices/timer.h>
#include <kernel/util.h>
void timer_handler(void)
{
extern struct timer_cache_s timercache[TIMER_NUMBER];
static uint32_t counter = 0;
uint32_t intevt;
int timer_ID;
@ -11,10 +12,18 @@ void timer_handler(void)
// @note: tricky way to get timer ID
// TODO: find better way !
intevt = *(uint32_t*)0xff000028;
timer_ID = (intevt - 0x400) >> 9;
timer_ID = (intevt - 0x400) / 0x20;
// Stop timer flag and clear interrupt flags.
SH7305_TMU.TSTR.BYTE &= ~(1 << timer_ID);
/*if (intevt != 0x400)
{
kvram_clear();
printk(0, 0, "Timer ID: %d\n", timer_ID);
printk(0, 1, "Interrupt: %#x\n", intevt);
printk(0, 2, "counter: %d\n", counter++);
kvram_display();
}*/
// Clear interrupt flags.
SH7305_TMU.TIMER[timer_ID].TCR.UNF = 0;
// Execute callback if possible.
@ -24,6 +33,4 @@ void timer_handler(void)
((void (*)(volatile void *))timercache[timer_ID].callback)(timercache[timer_ID].arg);
}
// Re-start timer.
SH7305_TMU.TSTR.BYTE |= 1 << timer_ID;
}

View File

@ -4,7 +4,6 @@
extern void keysc_handler(void);
extern void timer_handler(void);
__attribute__((section(".vhex.interrupt"), interrupt_handler))
void interrupt_handler(void)
{
uint32_t intevt = *(uint32_t*)0xff000028;

View File

@ -0,0 +1,52 @@
.section ".vhex.interrupt", "awx", @progbits
.global _interrupt_handler_pre
.type _interrupt_handler_pre, @function
.extern _sched_timer_intevt
.extern _sched_handler
.extern _interrupt_handler
_interrupt_handler_pre:
! Due to PR register used to switch process
! context, we SHOULD catch scheduler timer
! interrupt before the interrupt handler because
! we need to save / restore pr register before
! context swtich.
mov.l .sched_timer_intevt, r0 ! get the precalculate scheduler timer event
mov.l .intevt_register, r1 ! get INTEVT register address
mov.l @r0, r0 ! get the scheduler event code
mov.l @r1, r1 ! get the interrupt event
cmp/eq r0, r1 ! if scheduler timer event == INTEVT...
bf general_interrupt ! ...if not, jump at <general_interrupt>
scheduler_interrupt:
mov.l .scheduler_handler, r0 ! get scheduler handler address
jmp @r0 ! jump into scheduler handler
nop ! (db) nop
general_interrupt:
! Save critical regsiter.
stc.l spc, @-r15 ! save SPC register.
stc.l ssr, @-r15 ! save SSR register.
sts.l pr, @-r15 ! save pr register.
! Call interrupt handler
mov.l .interrupt_handler, r0 ! get interrupt handler address
jsr @r0 ! call interurpt handler
nop ! (db) nop
! Restore critical regsiter
lds.l @r15+, pr ! restore PR register.
ldc.l @r15+, ssr ! restore SSR regsiter.
ldc.l @r15+, spc ! restore SPC regsiter.
! Return
rte ! exit
nop ! (db) nop
.align 4
.sched_timer_intevt: .long _sched_timer_intevt
.scheduler_handler: .long _sched_handler
.interrupt_handler: .long _interrupt_handler
.intevt_register: .long 0xff000028

View File

@ -44,10 +44,10 @@ save_current_context:
! @note: current process can be NULL !
tst r4, r4 ! if current task == NULL...
bt context_load ! ...if yes, jump at <context_switch>
add #88, r4 ! get &process->context (end)
add #84, r4 ! get &process->context (end)
! save current context
sts.l pr, @-r4 ! get pr regsiter
!sts.l pr, @-r4 ! get pr regsiter
stc.l spc, @-r4 ! get spc regsiter
stc.l ssr, @-r4 ! get ssr regsiter
sts.l mach, @-r4 ! get mach regsiter
@ -95,7 +95,7 @@ context_load:
lds.l @r5+, mach ! set mach regsiter
ldc.l @r5+, ssr ! set ssr regsiter
ldc.l @r5+, spc ! set spc regsiter
lds.l @r5+, pr ! set pr regsiter
!lds.l @r5+, pr ! set pr regsiter
! Process switch

View File

@ -0,0 +1,37 @@
#include <kernel/context.h>
#include <kernel/hardware/tmu.h>
#include <kernel/util.h>
// Test
uint32_t counter = 0;
void sched_debug(common_context_t *context_current, common_context_t *context_next)
{
extern uint32_t sched_timer_id;
extern uint32_t sched_timer_address;
uint32_t tstr = SH7305_TMU.TSTR.BYTE;
uint32_t tcr = *(uint16_t*)sched_timer_address;
uint32_t tcor = *(uint32_t*)(sched_timer_address - 4);
uint32_t tcnt = *(uint32_t*)(sched_timer_address - 8);
//SH7305_TMU.TSTR.STR2 = 0;
//SH7305_TMU.TSTR.STR1 = 0;
//SH7305_TMU.TSTR.STR0 = 0;
//SH7305_TMU.TIMER[0].TCR.UNF = 0;
//SH7305_TMU.TIMER[1].TCR.UNF = 0;
//SH7305_TMU.TIMER[2].TCR.UNF = 0;
kvram_clear();
printk(0, 0, "Scheduler_schudele !");
printk(0, 1, "context current = %p", context_current);
printk(0, 2, "context next = %p", context_next);
printk(0, 3, "counter = %#x", counter++);
printk(0, 4, "TSTR: %#x", tstr);
printk(0, 5, "TCOR: %#x", tcor);
printk(0, 6, "TCNT: %#x", tcnt);
printk(0, 7, "TCR: %#x", tcr);
kvram_display();
}

View File

@ -0,0 +1,204 @@
.text
.global _sched_handler
.type _sched_handler, @function
.extern _sched_timer_id
.extern _sched_timer_address
.extern _sched_schedule
.align 2
/*
** @note
** We can use only r0 - r7 register because
** we SHOULD not modify the current process context.
*/
_sched_handler:
/*
** Stop scheduler timer and clear interrupt flags
*/
stop_clear_sched_timer:
! Clear scheduler timer interrupt
mov.l .sched_timer_address, r0 ! get precalculated scheduler timer address
mov.l .timer_unf_field, r1 ! get TIMER.TCR.UNF byte field
mov.l @r0, r0 ! get scheduler timer TCR register
mov.w @r0, r2 ! get scheduler timer TCR register
not r1, r1 ! get interrupt flags bit mask (to remove)
and r1, r2 ! clear timer interrupt flags
mov.w r2, @r0 ! update timer TCR
! Stop scheduler timer
mov.l .sched_timer_tstr_bit, r0 ! get precalculated scheduler timer ID
mov.l .timer_tstr_register, r1 ! get TMU0.TSTR base address
mov.l @r0, r0 ! get scheduler timer ID
mov.b @r1, r2 ! get TMU0.TSTR data
not r0, r0 ! get TSTR scheduler timer ID mask (to remove)
and r0, r2 ! stop scheduler timer
mov.b r2, @r1 ! update TMU0.TSTR
#ifdef __SCHED_DEBUG__
sts.l pr, @-r15 ! save pr register
mov #0, r4 ! save r4 register (current context)
mov #0, r5 ! save r5 register (next context)
mov.l .sched_debug, r0 ! get sched_debug() absraction
jsr @r0 ! call abstraction
nop ! (db) nop
lds.l @r15+, pr ! restore pr register
bra restart_sched_timer
nop
#endif
/*
** Get current and next context
*/
get_contexts:
! prologue
mov.l r9, @-r15 ! save r9 register
mov.l r8, @-r15 ! save r8 register
sts.l pr, @-r15 ! save pr register
! Create to context_common_t **ptr
add #-4, r15 ! create first context pointer
mov r15, r8 ! save first context pointer
add #-4, r15 ! create second context pointer
mov r15, r9 ! save second context pointer
add #-4, r15 ! create context pointer
mov.l r15, @r8 ! save context pointer
add #-4, r15 ! create context pointer
mov.l r15, @r9 ! save context pointer
! call high level abstraction
mov r8, r4 ! send current contexts pointer
mov r9, r5 ! send next context pointer
mov.l .sched_schedule, r0 ! get sched_scheduler() abstraction address
jsr @r0 ! call sched_schedule() abstract
nop ! (db) nop
! Restore stack and register (epilogue)
mov.l @r8, r4 ! save current context
mov.l @r9, r5 ! save next context
add #16, r15 ! restore stack
lds.l @r15+, pr ! restore pr register
mov.l @r15+, r8 ! restore r8 register
mov.l @r15+, r9 ! restore r9 register
! Check context error
tst r0, r0 ! check if returned value == 0...
bt debug ! if yes, jump at <debug>
bra restart_sched_timer ! jump at <restart_sched_timer>
nop ! (db) nop
/*
** Debug part, used to debug the contexts
*/
debug:
#ifdef __SCHED_DEBUG__
sts.l pr, @-r15 ! save pr register
mov.l r4, @-r15 ! save r4 register (current context)
mov.l r5, @-r15 ! save r5 register (next context)
mov.l .sched_debug, r0 ! get sched_debug() absraction
jsr @r0 ! call abstraction
nop ! (db) nop
mov.l @r15+, r5 ! restore r5 register
mov.l @r15+, r4 ! restore r4 register
lds.l @r15+, pr ! restore pr register
#endif
/*
** Context switch
*/
save_current_context:
! Check current process
! @note: current process can be NULL !
tst r4, r4 ! if current task == NULL...
bt next_context_load ! ...if yes, jump at <context_switch>
add #88, r4 ! get &process->context (end)
! save current context
sts.l pr, @-r4 ! get pr regsiter
stc.l spc, @-r4 ! get spc regsiter
stc.l ssr, @-r4 ! get ssr regsiter
sts.l mach, @-r4 ! get mach regsiter
sts.l macl, @-r4 ! get macl regsiter
stc.l gbr, @-r4 ! get gbr regsiter
mov.l r15, @-r4 ! get r15 register
mov.l r14, @-r4 ! get r14 regsiter
mov.l r13, @-r4 ! get r13 regsiter
mov.l r12, @-r4 ! get r12 regsiter
mov.l r11, @-r4 ! get r11 regsiter
mov.l r10, @-r4 ! get r10 regsiter
mov.l r9, @-r4 ! get r9 regsiter
mov.l r8, @-r4 ! get r8 regsiter
stc.l R7_BANK, @-r4 ! get "process" r7 regsiter
stc.l R6_BANK, @-r4 ! get "process" r6 regsiter
stc.l R5_BANK, @-r4 ! get "process" r5 regsiter
stc.l R4_BANK, @-r4 ! get "process" r4 regsiter
stc.l R3_BANK, @-r4 ! get "process" r3 regsiter
stc.l R2_BANK, @-r4 ! get "process" r2 regsiter
stc.l R1_BANK, @-r4 ! get "process" r1 regsiter
stc.l R0_BANK, @-r4 ! get "process" r0 regsiter
next_context_load:
! Load next process
! @note: next process can not be NULL !
ldc.l @r5+, R0_BANK ! set "process" r0 regsiter
ldc.l @r5+, R1_BANK ! set "process" r1 regsiter
ldc.l @r5+, R2_BANK ! set "process" r2 regsiter
ldc.l @r5+, R3_BANK ! set "process" r3 regsiter
ldc.l @r5+, R4_BANK ! set "process" r4 regsiter
ldc.l @r5+, R5_BANK ! set "process" r5 regsiter
ldc.l @r5+, R6_BANK ! set "process" r6 regsiter
ldc.l @r5+, R7_BANK ! set "process" r7 regsiter
mov.l @r5+, r8 ! set r8 regsiter
mov.l @r5+, r9 ! set r9 regsiter
mov.l @r5+, r10 ! set r10 regsiter
mov.l @r5+, r11 ! set r11 regsiter
mov.l @r5+, r12 ! set r12 regsiter
mov.l @r5+, r13 ! set r13 regsiter
mov.l @r5+, r14 ! set r14 regsiter
mov.l @r5+, r15 ! set r15 register
ldc.l @r5+, gbr ! set gbr regsiter
lds.l @r5+, macl ! set macl regsiter
lds.l @r5+, mach ! set mach regsiter
ldc.l @r5+, ssr ! set ssr regsiter
ldc.l @r5+, spc ! set spc regsiter
lds.l @r5+, pr ! set pr regsiter
/*
** Restart timer
*/
restart_sched_timer:
mov.l .sched_timer_tstr_bit, r0 ! get precalculated scheduler timer ID
mov.l .timer_tstr_register, r1 ! get TMU0.TSTR base address
mov.l @r0, r0 ! get scheduler timer ID
mov.b @r1, r2 ! get TMU0.TSTR data
or r0, r2 ! start scheduler timer
mov.b r2, @r1 ! update TMU0.TSTR
/*
** Process switch
*/
process_switch:
rte ! use RTE to switch process
nop ! (db) nop
.align 4
.sched_timer_tstr_bit: .long _sched_timer_tstr_bit
.sched_timer_address: .long _sched_timer_address
.sched_schedule: .long _sched_schedule
.timer_tstr_register: .long 0xa4490004
.timer_unf_field: .long 0x00000100
#ifndef __SCHED_DEBUG__
.sched_debug: .long _sched_debug
#endif
.end

View File

@ -2,14 +2,16 @@
// This function SHOULD NOT be called
// without atomic operation !!
// TODO: dynamic allocation ?
pid_t process_alloc(struct process **process)
{
extern struct process_stack process_stack[PROCESS_MAX];
for (int i = 0 ; i < PROCESS_MAX ; i = i + 1)
{
if (process_stack[i].status == PROC_IDLE)
if (process_stack[i].status == PROC_UNUSED)
{
process_stack[i].status = PROC_USED;
*process = &process_stack[i].process;
return (i);
}

View File

@ -1,6 +1,6 @@
#include <kernel/process.h>
struct process *process_get(pid_t pid)
struct process *process_get_proc(pid_t pid)
{
extern struct process_stack process_stack[PROCESS_MAX];
@ -11,3 +11,17 @@ struct process *process_get(pid_t pid)
// Return process.
return (&process_stack[pid].process);
}
pid_t process_get_pid(struct process *target)
{
extern struct process_stack process_stack[PROCESS_MAX];
int i;
i = -1;
while (++i < PROCESS_MAX)
{
if (&process_stack[i].process == target)
return (i);
}
return (-1);
}

View File

@ -10,6 +10,6 @@ void process_constructor(void)
// Set all process to idle state.
for (int i = 0 ; i < PROCESS_MAX ; i = i + 1)
{
process_stack[i].status = PROC_IDLE;
process_stack[i].status = PROC_UNUSED;
}
}

View File

@ -3,26 +3,20 @@
#include <kernel/util.h>
//TODO: assembly !
void sched_schedule(void)
// @note: This part *SHOULD* be exeption safe !
int sched_schedule(common_context_t **context_current, common_context_t **context_next)
{
extern struct sched_task *sched_task_current;
extern struct sched_task *sched_task_queue;
struct sched_task *task_current;
struct sched_task *task_next;
common_context_t *context_current;
common_context_t *context_next;
// Start atomic operation
atomic_start();
// Check current task
// TODO: check process status !!
if (sched_task_current == NULL)
{
task_current = NULL;
task_next = (sched_task_queue != NULL)
? sched_task_queue
: NULL;
task_next = (sched_task_queue != NULL) ? sched_task_queue : NULL;
} else {
task_current = sched_task_current;
task_next = (sched_task_current->next != NULL)
@ -32,39 +26,23 @@ void sched_schedule(void)
// Check potantial error
if (task_next == NULL || task_next == sched_task_current)
{
atomic_stop();
return;
}
//TODO: check process status !!!
return (-1);
// Update internal scheduler task cursor
sched_task_current = task_next;
// Get context
context_current =
(task_current != NULL)
? &task_current->process->context
: NULL;
context_next =
(task_next != NULL)
? &task_next->process->context
: NULL;
*context_current = (task_current != NULL) ? &task_current->process->context : NULL;
*context_next = &task_next->process->context;
// DEBUG !
kvram_clear();
/*kvram_clear();
printk(0, 0, "Scheduler_schudele !");
printk(0, 1, "task current = %p", task_current);
printk(0, 2, "task next = %p", task_next);
printk(0, 3, "context current = %p", context_current);
printk(0, 4, "context next = %p", context_next);
printk(0, 3, "context current = %p", *context_current);
printk(0, 4, "context next = %p", *context_next);
kvram_display();
DBG_WAIT;
printk(0, 5, "context switch !");
kvram_display();
// Context switch
sched_context_switch(context_current, context_next);
DBG_WAIT;*/
return (0);
}

View File

@ -1,12 +1,114 @@
#include <kernel/scheduler.h>
#include <kernel/hardware/cpg.h>
#include <kernel/hardware/tmu.h>
#include <kernel/util.h>
// Internal data used by the scheduler handler
uint32_t sched_timer_id = 0;
uint32_t sched_timer_address = 0;
uint32_t sched_timer_intevt = 0;
uint32_t sched_timer_tstr_bit = 0;
// Internal private function
//void sched_handler(void);
//FIXME: remove me and wrap timer interrupt when occur !!
static void scheduler_timer_callback(void)
{
common_context_t *context_current;
common_context_t *context_next;
//TODO: quantum handling !!
//TODO: scheduler block / unblock options !!
//FIXME: Get SPC, SSR, ... !!
// Get current context and
if (sched_schedule(&context_current, &context_next) != 0)
return;
// Debug
//kvram_clear();
//printk(0, 0, "Scheduler_schudele !");
//printk(0, 1, "context current = %p", context_current);
//printk(0, 2, "context next = %p", context_next);
//kvram_display();
//printk(0, 3, "context switch !");
//kvram_display();
//DBG_WAIT;
// Context switch
sched_context_switch(context_current, context_next);
}
void sched_start(void)
{
extern struct sched_task *sched_task_queue;
extern struct process *process_current;
uint32_t fll_freq;
uint32_t pll_freq;
uint32_t cpu_freq;
uint32_t bus_freq;
uint32_t per_freq;
//TODO: get CPU frequency !
//TODO: setup TMU0 interrupt !
// Calculate FLL frequency (Khz)
// @note: RCLK = 32 768 Hz
fll_freq = SH7305_CPG.FLLFRQ.FLF * 32768; // Hz
fll_freq = fll_freq / (1 << SH7305_CPG.FLLFRQ.SELXM); // Check FLL output division
// Calculate PLL frequency (Khz)
pll_freq = fll_freq * (SH7305_CPG.FRQCRA.STC + 1);
// Calculate CPU clock frequency !
cpu_freq = pll_freq / (1 << (SH7305_CPG.FRQCRA.IFC + 1));
// Calculate BUS clock frequency !
bus_freq = pll_freq / (1 << (SH7305_CPG.FRQCRA.BFC + 1));
// Calculate Peripheral clock frequency !
per_freq = pll_freq / (1 << (SH7305_CPG.FRQCRA.PFC + 1));
// Debug
kvram_clear();
printk(0, 0,
"FLL freq: %d.%d Mhz\n"
"PLL freq: %d.%d Mhz\n"
"CPU freq: %d.%d Mhz\n"
"BUS freq: %d.%d Mhz\n"
"Per freq: %d.%d Mhz",
fll_freq / 1000000, (((fll_freq - ((fll_freq / 1000000)) * 1000000)) + 999) / 1000,
pll_freq / 1000000, (((pll_freq - ((pll_freq / 1000000)) * 1000000)) + 999) / 1000,
cpu_freq / 1000000, (((cpu_freq - ((cpu_freq / 1000000)) * 1000000)) + 999) / 1000,
bus_freq / 1000000, (((bus_freq - ((bus_freq / 1000000)) * 1000000)) + 999) / 1000,
per_freq / 1000000, (((per_freq - ((per_freq / 1000000)) * 1000000)) + 999) / 1000
);
kvram_display();
DBG_WAIT;
// Register first process !
process_current = sched_task_queue->process;
sched_schedule();
// Setup TMU0 (scheduler) interrupt !
// @note: I use Po/4 on TMU prescaler
// TODO: generate quantum and quantum counter for preemption !
uint32_t ticks = (per_freq / 4) / 16;
//sched_timer_id = timer_install(scheduler_timer_callback, NULL, ticks, 0);
sched_timer_id = timer_install(NULL, NULL, ticks, 0);
sched_timer_address = (uint32_t)&SH7305_TMU.TIMER[sched_timer_id].TCR;
sched_timer_intevt = 0x400 + (0x20 * sched_timer_id);
sched_timer_tstr_bit = 1 << sched_timer_id;
// Debug
kvram_clear();
printk(0, 0, "timer ID: %d", sched_timer_id);
printk(0, 1, "timer addr: %#x", sched_timer_address);
printk(0, 2, "timer event: %#x", sched_timer_intevt);
printk(0, 3, "timer TSTR: %#x", sched_timer_tstr_bit);
kvram_display();
DBG_WAIT;
// Start scheduler timer
timer_start(sched_timer_id);
}

View File

@ -0,0 +1,11 @@
#include <kernel/scheduler.h>
#include <kernel/util.h>
void sys_exit(int status)
{
kvram_clear();
printk(0, 0, "PROCESS EXIT SYSCALL !!!!");
printk(0, 0, "Wait manual reset...");
kvram_display();
while (1);
}

View File

@ -0,0 +1,77 @@
#include <kernel/process.h>
#include <kernel/scheduler.h>
#include <kernel/loader.h>
#include <kernel/atomic.h>
#include <kernel/util.h>
pid_t sys_fexecve(const char *pathname)
{
struct process *proc;
pid_t child_pid;
FILE *bin;
int error;
// Start atomic operation
atomic_start();
// Try create new process
proc = process_create(pathname);
if (proc == NULL)
{
kvram_clear();
printk(0, 0, "sys_fexecve: alloc error !");
kvram_display();
DBG_WAIT;
atomic_stop();
return (-1);
}
// Try to load binary into physical memory
proc->context.spc = (uint32_t)loader(pathname, proc);
if (proc->context.spc == 0x00000000)
{
kvram_clear();
printk(0, 0, "sys_fexecve: loader error !");
kvram_display();
DBG_WAIT;
process_free(proc);
atomic_stop();
return (-1);
}
// Debug
kvram_clear();
printk(0, 0, "New proc loaded !");
kvram_display();
DBG_WAIT;
// Add new process into task queue
error = sched_add_task(proc);
if (error != 0)
{
kvram_clear();
printk(0, 0, "sys_fexecve: scheduler error !");
kvram_display();
DBG_WAIT;
process_free(proc);
atomic_stop();
return (-1);
}
// Debug
printk(0, 1, "New proc sched added !");
kvram_display();
DBG_WAIT;
// Get child process PID
child_pid = process_get_pid(proc);
// Debug
printk(0, 2, "New proc PID = %#x !", child_pid);
kvram_display();
DBG_WAIT;
// Stop atomic operations
atomic_stop();
return (child_pid);
}

View File

@ -2,20 +2,41 @@
pid_t sys_fork(void)
{
extern process_t *process_current;
process_t **process_new;
pid_t process_pid;
extern struct process *process_current;
struct process *process_new;
pid_t process_new_pid;
// Check error
if (process_current == NULL)
return (-1);
// Get the new process slot.
process_new = &process_current->child;
while (*process_new != NULL)
process_new = &(*process_new)->next;
// Try to find new sheduler place.
process_pid = process_alloc(&(*process_new));
if (*process_new == NULL)
new_pid = process_alloc(&process_new);
if (new_pid != 0)
return (-1);
// Initialize context.
// Try to create user stack
process_new->memory.stack.size.user = process_current->;
process_new->memory.stack.user = (uint32_t)pm_alloc(process_new->memory.stack.size.user);
if (process_new->memory.stack.user == 0x00000000)
{
process_free(process_new);
return (-1);
}
// Try to create kernel stack
process_new->memory.stack.size.kernel = process_current->memory.stack.size.kernel;
process_new->memory.stack.kernel = (uint32_t)pm_alloc(process_new->memory.stack.size.kernel);
if (process_new->memory.stack.kernel == 0x00000000)
{
pm_free(process_new->memory.stack.user);
process_free(process_new);
return (-1);
}
//TODO: dump stack data
//TODO: dump code data
//TODO: Initialize context.
return (-1);
}*/

View File

@ -12,35 +12,36 @@ static void sys_test(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
DBG_WAIT;
}
static const void *sys_handler[15] = {
static const void *sys_handler[16] = {
// Kernel Test
sys_test, //restart
sys_test, // test
// Process
NULL, //exit
sys_waitpid, //waitpid
NULL, //exec
sys_exit, // exit
sys_fexecve, // fexecve
sys_waitpid, // waitpid
// VFS
sys_read, //read
sys_write, //write
sys_open, //open
sys_close, //close
sys_lseek, //lseek
sys_read, // read
sys_write, // write
sys_open, // open
sys_close, // close
sys_lseek, // lseek
// Display
kvram_display, //kvram_display
kvram_clear, //kvram_clear
kvram_print, //kvram_print
kvram_ascii, //kvram_ascii
kvram_reverse, //kvram_reverse
kvram_scroll //kvram_scroll
kvram_display, // kvram_display
kvram_clear, // kvram_clear
printk, // printk
kvram_ascii, // kvram_ascii
kvram_reverse, // kvram_reverse
kvram_scroll, // kvram_scroll
kvram_clr_str_area // kvram_clr_str_area
};
void *sys_get_handler(int sysno)
{
// Check sysno validity
if (sysno < 0 || sysno >= 14)
if (sysno < 0 || sysno >= 16)
return (0);
// DEBUG

View File

@ -31,6 +31,7 @@ _syscall_pre:
! Switch register bank and allow interrupt
! @note: user context has been saved
! during the `exception_handler_pre`
! TODO: do not allow interrupt ?
mov.l .sr_mask, r1 ! get SR mask for BL and IMASK
and r1, r0 ! set SR.BL = 0, SR.RB = 0 and SR.IMASK = 0b0000
ldc r0, sr ! update SR regsiter

View File

@ -133,42 +133,49 @@ void kvram_reverse(int x, int y, int width, int height)
atomic_stop();
}
/* kvram_print() - Print string on Video RAM */
void kvram_print(int x, int y, char const *str)
/* kvram_clr_str_area() - Clear area based on kernel font size on Video RAM */
//FIXME: secure
void kvram_clr_str_area(int x, int y, int width, int height)
{
int default_pos_x;
int starting_x;
int i;
uint32_t vram_offset_y;
int cur_x;
int cur_y;
// Initialize part
i = -1;
starting_x = x;
x = x * (KERNEL_FONT_REAL_WIDTH + 1);
y = y * (KERNEL_FONT_REAL_HEIGHT + 1);
default_pos_x = x;
width = width * (KERNEL_FONT_REAL_WIDTH + 1);
height = height * (KERNEL_FONT_REAL_HEIGHT + 1);
// Walk into string and display character by character
while (str[++i] != '\0')
// Get VRAM offset
vram_offset_y = y << 2;
//DEbug
/*kvram_clear();
printk(0, 0, "kvram_clr_str_area debug !");
printk(0, 1, "x = %d", x);
printk(0, 2, "y = %d", y);
printk(0, 3, "width = %d", width);
printk(0, 4, "height = %d", height);
kvram_display();
DBG_WAIT;*/
// Clear area, pixel per pixel x____x
// TODO: update me !!!!
cur_y = -1;
while (++cur_y < height)
{
// New line
if (str[i] == '\n')
cur_x = -1;
while (++cur_x < width)
{
y = y + KERNEL_FONT_REAL_HEIGHT + 1;
x = default_pos_x;
continue;
}
// Horizontal tab
if (str[i] == '\t')
{
x = x / (KERNEL_FONT_REAL_WIDTH + 1);
x = (x + (4 - ((x - starting_x) & 3))) * (KERNEL_FONT_REAL_WIDTH + 1);
continue;
vram[((x + cur_x) >> 5) + vram_offset_y] &=
~(0x80000000 >> ((x + cur_x) & 31));
}
// Default, display character
font_draw(x, y, str[i]);
x = x + KERNEL_FONT_REAL_WIDTH + 1;
// update internal counter
vram_offset_y = vram_offset_y + 4;
}
}
/* kvram_ascii() - Draw ASCII character into Video RAM */

View File

@ -1,10 +1,39 @@
#include <kernel/util.h>
#include <kernel/hardware/tmu.h>
#include <kernel/devices/timer.h>
#include <kernel/atomic.h>
//TODO: update !
int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode)
// Internal timer "cache".
struct timer_cache_s timercache[TIMER_NUMBER];
__attribute__((constructor))
void timer_constructor(void)
{
// Initialise internal cache
for (int i = 0 ; i < TIMER_NUMBER ; i = i + 1)
{
timercache[i].status = TIMER_UNUSED;
timercache[i].callback = NULL;
timercache[i].arg = NULL;
}
// Configure TMU
SH7305_TMU.TSTR.STR0 = 0; // Stop timer 0
SH7305_TMU.TSTR.STR1 = 0; // Stop timer 1
SH7305_TMU.TSTR.STR2 = 0; // Stop timer 2
// Configure TMU timers
for (int i = 0 ; i < 3 ; ++i)
{
SH7305_TMU.TIMER[i].TCOR = 0xffffffff; // Reset timer constant register
SH7305_TMU.TIMER[i].TCNT = 0xffffffff; // Reset timer counter
SH7305_TMU.TIMER[i].TCR.UNF = 0; // Clear interrupt flags
SH7305_TMU.TIMER[i].TCR.UNIE = 0; // Disable timerinterrupt
SH7305_TMU.TIMER[i].TCR.CKREG = 0b00; // Count on rising edge
SH7305_TMU.TIMER[i].TCR.TPSC = 0b000; // Select P/4 prescaler
}
}
int timer_install(void *callback, void *arg, uint32_t ticks, uint8_t mode)
{
extern struct timer_cache_s timercache[TIMER_NUMBER];
int timer_ID;
@ -20,6 +49,12 @@ int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode)
if (timer_ID >= TIMER_NUMBER)
return (-1);
// Debug !!
/*kvram_clear();
printk(0, 0, "Timer find: %d\n", timer_ID);
printk(0, 1, "TMU = %p\n", &SH7305_TMU.TIMER[timer_ID]);
kvram_display();
DBG_WAIT;*/
// Initialise internal timer data.
timercache[timer_ID].callback = callback;
@ -29,12 +64,11 @@ int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode)
// Initialise hardware module.
SH7305_TMU.TSTR.BYTE &= ~(1 << timer_ID); // Stop timer.
// Convert delay in millisecond into timer tick.
// TODO !!
SH7305_TMU.TIMER[timer_ID].TCOR = delay_ms * 2000;
SH7305_TMU.TIMER[timer_ID].TCNT = delay_ms * 2000;
SH7305_TMU.TIMER[timer_ID].TCR.TPSC = 0b000; // TODO use appropriate divisor !
// Setup Timer
SH7305_TMU.TIMER[timer_ID].TCOR = ticks;
SH7305_TMU.TIMER[timer_ID].TCNT = ticks;
// Configure timer
SH7305_TMU.TIMER[timer_ID].TCR.UNF = 0; // Clear interrupt flag.
SH7305_TMU.TIMER[timer_ID].TCR.UNIE = 1; // Enable interrupt.
@ -48,7 +82,6 @@ int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode)
return (timer_ID);
}
//TODO: update !
int timer_uninstall(int timer_ID)
{
extern struct timer_cache_s timercache[TIMER_NUMBER];
@ -71,6 +104,27 @@ int timer_uninstall(int timer_ID)
// Free'd timer cache.
timercache[timer_ID].status = TIMER_UNUSED;
timercache[timer_ID].callback = NULL;
timercache[timer_ID].arg = NULL;
// Stop atomic operation and return.
atomic_stop();
return (0);
}
int timer_start(int timer_ID)
{
extern struct timer_cache_s timercache[TIMER_NUMBER];
// Check bad ID
if (timer_ID < 0 || timer_ID >= TIMER_NUMBER)
return (-1);
// Start Atomic operation.
atomic_start();
// Start hardware timer.
SH7305_TMU.TSTR.BYTE |= 1 << timer_ID;
// Stop atomic operation and return.
atomic_stop();

View File

@ -0,0 +1,12 @@
.text
.global _dclr_str_area
.type _dclr_str_area, @function
#include "kernel/unistd_32.h"
.align 2
_dclr_str_area:
trapa #__NR_kvram_clr_str_area
rts
nop
.end

12
src/lib/unistd/fexecve.S Normal file
View File

@ -0,0 +1,12 @@
.text
.global _fexecve
.type _fexecve, @function
#include "kernel/unistd_32.h"
.align 2
_fexecve:
trapa #__NR_fexecve
rts
nop
.end

View File

@ -3,16 +3,16 @@
## Project: Vhex - On-calc debugger
## Author: yann.magnin@epitech.eu
## ---
include ../../global.mk
include ../../../global.mk
##---
## Static variables
##--
HEADER := -I../../include -I../../include/user
LIBS := -L../lib/ -l_unistd -l_stdio -l_string -l_display
BUILD := ../../build/user
DEBUG := ../../debug
OUTPUT := ../../output
HEADER := -I../../../include -I../../../include/user
LIBS := -L../../lib/ -l_unistd -l_stdio -l_string -l_display
BUILD := ../../../build/user/shell
DEBUG := ../../../debug
OUTPUT := ../../../output
NAME := shell
EXEC := $(OUTPUT)/$(NAME).elf
@ -26,7 +26,7 @@ MEMORY_MAP := $(DEBUG)/$(NAME).map
## Automated variables
##---
SRC :=
DIRECTORY := $(shell find shell -not -path "*/\.*" -type d)
DIRECTORY := $(shell find . -not -path "*/\.*" -type d)
# Get all source files
$(foreach path,$(DIRECTORY),$(eval \
SRC += $(wildcard $(path)/*.c) \
@ -34,7 +34,7 @@ $(foreach path,$(DIRECTORY),$(eval \
$(wildcard $(path)/*.s) \
))
# Geneate all object files
OBJ := $(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))))
OBJ := $(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))))
@ -75,7 +75,7 @@ sec:
## Automated rules
##---
define rule-src
$(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1
$(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) -fPIC $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
@ printf "$(green)[ok]$(nocolor)\n"

View File

@ -0,0 +1,43 @@
#include <lib/unistd.h>
#include <lib/display.h>
#include <builtin.h>
int builtin_proc(void)
{
pid_t child;
// Debug
dclear();
dprint(0, 0, "Proc builtin !");
dupdate();
for (int i = 0 ; i < 3000000 ; i++);
// Try to create first child
/*child = fork();
if (child == -1)
{
dprint(0, 1, "fork() fail !");
dupdate();
for (int i = 0 ; i < 3000000 ; i++);
return (0);
}
// Check parent
if (child_pid != 0)
{
int counter = 0;
while (1)
{
dprint(0, 1, "parent: %d", counter++);
for (int i = 0 ; i < 3000000 ; i++);
}
} else {
int counter = 0;
while (1)
{
dprint(0, 2, "child: %d", counter++);
for (int i = 0 ; i < 9000000 ; i++);
}
}*/
return (0);
}

View File

@ -27,11 +27,6 @@ SECTIONS
.rodata : {
*(.rodata);
*(.rodata.*);
/* Builtin */
_bbuiltin_section = ALIGN(4) ;
*(.builtin);
_ebuiltin_section = . ;
}
.data ALIGN(4) : {

View File

@ -1,48 +1,88 @@
#include "util.h"
#include "builtin.h"
#include <lib/string.h>
#include <lib/display.h>
#include <lib/unistd.h>
// Internal builtin list
// FIXME: due to PIE binary format, we can not
// FIXME: use address of builtin_proc !!
/*struct builtin_s list[1] = {
{
.name = "proc",
.entry = (void*)&builtin_proc
},
//{
// .name = "ram",
// .entry = (void *)&builtin_ram
//}
};*/
//TODO: use agc, argv.
int check_builtin(char *cmd)
{
extern uint32_t bbuiltin_section;
extern uint32_t ebuiltin_section;
struct builtin_s *list;
int wstatus;
//pid_t pid;
int i;
i = -1;
list = (void*)&bbuiltin_section;
while ((uint32_t)&list[++i] < (uint32_t)&ebuiltin_section)
// Process test
dclear();
dprint(0, 0, "Process Load Test !");
// Load process test
pid_t pid = fexecve("/mnt/smemfs/VHEX/test.elf");
if (pid < 0)
{
dprint(0, 1, "Process error !");
dupdate();
for(int i = 0 ; i < 3000000 ; ++i);
return (-1);
}
int counter = 0;
dclear();
dprint(0, 0, "Process Test !");;
while (1)
{
dclr_str_area(0, 1, 20, 1);
dprint(0, 1, "P process: %d", counter);
dupdate();
counter = counter + 1;
for (int i = 0 ; i < 30000 ; ++i);
}
//int wstatus;
//pid_t pid;
//int i;
// Try to find builtin
/* for (int i = 0 ; i < 1 ; i++)
{
if (strcmp(list[i].name, cmd) != 0)
continue;
// Execute builtin
list[i].entry(0, NULL);
return (0);
}
}*/
return (-1);
// Create subprocess
//pid = fork();
//if (pid < 0)
// return (1);
// If we are the child execute
// the builtins.
//if (pid == 0)
// //{
// dclear();
// dprint(0, 0, "Child process !!");
// dprint(0, 1, "PID = %d", getpid());
// dprint(0, 2, "PPID = %d", getppid());
// dupdate();
// Create subprocess
//pid = fork();
//if (pid < 0)
// return (1);
// If we are the child execute
// the builtins.
//if (pid == 0)
// //{
// dclear();
// dprint(0, 0, "Child process !!");
// dprint(0, 1, "PID = %d", getpid());
// dprint(0, 2, "PPID = %d", getppid());
// dupdate();
// } else {
// waitpid(pid, &wstatus, WCONTINUED);
//TODO: signal handling.
//TODO: signal handling.
// }
// }
// return (1);
}
// }
// return (1);
}

106
src/user/test/Makefile Normal file
View File

@ -0,0 +1,106 @@
#!/usr/bin/make -f
## ---
## Project: Vhex - On-calc debugger
## Author: yann.magnin@epitech.eu
## ---
include ../../../global.mk
##---
## Static variables
##--
HEADER := -I../../../include -I../../../include/user
LIBS := -L../../lib/ -l_unistd -l_stdio -l_string -l_display
BUILD := ../../../build/user/test
DEBUG := ../../../debug
OUTPUT := ../../../output
NAME := test
EXEC := $(OUTPUT)/$(NAME).elf
LDFLAG := -T $(NAME).ld
MEMORY_MAP := $(DEBUG)/$(NAME).map
##---
## Automated variables
##---
SRC :=
DIRECTORY := $(shell find . -not -path "*/\.*" -type d)
# Get all source files
$(foreach path,$(DIRECTORY),$(eval \
SRC += $(wildcard $(path)/*.c) \
$(wildcard $(path)/*.S) \
$(wildcard $(path)/*.s) \
))
# Geneate all object files
OBJ := $(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))))
##---
## General rules
##---
all: | $(BUILD) $(DEBUG) $(EXEC)
$(EXEC): $(OBJ)
$(CC) -fPIC -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf.big $(OBJ) $(HEADER) $(LIBS) -lgcc > $(MEMORY_MAP)
$(OBJCOPY) -S $(DEBUG)/$(NAME).elf.big $@
rm -f $(DEBUG)/$(NAME).elf.big
$(BUILD) $(DEBUG):
@ printf "Create $(blue)$@$(nocolor) directory\n"
@ mkdir -p $@
install: $(EXEC)
sudo p7 send --force -d VHEX $^
check:
@ echo 'src: $(SRC)'
@ echo 'obj: $(OBJ)'
@ echo 'directory: $(DIRECTORY)'
asm:
@ $(OBJDUMP) -D $(EXEC) | less
map:
@ cat $(MEMORY_MAP) | less
sec:
@ $(OBJDUMP) -h $(EXEC)
##---
## Automated rules
##---
define rule-src
$(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) -fPIC $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
@ printf "$(green)[ok]$(nocolor)\n"
endef
$(foreach source,$(SRC),$(eval \
$(call rule-src,$(source))) \
)
##---
## Cleaning rules
##---
clean:
rm -rf $(BUILD)
rm -rf $(DEBUG)
fclean: clean
rm -f $(EXEC)
re: fclean all
.PHONY: re fclean clean all install

View File

@ -1,8 +1,19 @@
/*#include <kernel/syscall.h>
#include <lib/display.h>
void test(void)
int main(void)
{
uint8_t *vram;
uint32_t counter = 0;
while (1)
{
// Display data
dclr_str_area(0, 2, 20, 1);
dprint(0, 2, "C process: %d", counter);
dupdate();
vram = casio_Bdisp_GetVRAM();
}*/
// Update counter and "wait"
counter = counter + 1;
if (counter >= 100)
counter = 0;
for (int i = 0 ; i < 300000 ; ++i);
}
}

65
src/user/test/test.ld Normal file
View File

@ -0,0 +1,65 @@
OUTPUT_ARCH(sh3)
OUTPUT_FORMAT(elf32-sh)
ENTRY(_main)
/*
** Linker script for user executables.
*/
MEMORY
{
/* virtual memory, read-write segment */
userram (WX) : o = 0x00000000, l = 256k
}
PHDRS
{
text PT_LOAD ;
data PT_LOAD ;
}
SECTIONS
{
.text : {
*(.text);
*(.text.*);
} : text
.rodata : {
*(.rodata);
*(.rodata.*);
}
.data ALIGN(4) : {
*(.plt);
*(.data);
*(.data.*);
/* bss section included to avoid missaligned segment */
*(.bss);
*(.bss.*);
*(COMMON);
} : data
.relocgot : {
BRELOC_GOT = . ;
*(.got.plt)
*(.got)
ERELOC_GOT = . ;
}
/* unwanted section */
/DISCARD/ : {
*(.debug_info)
*(.debug_abbrev)
*(.debug_loc)
*(.debug_aranges)
*(.debug_ranges)
*(.debug_line)
*(.debug_str)
*(.jcr)
*(.eh_frame_hdr)
*(.eh_frame)
*(.comment)
}
}

View File

@ -1,4 +1,4 @@
.global _test
/*.global _test
.type _test, @function
.align 2
@ -20,4 +20,4 @@ _test:
.align 4
.syscall_entry: .long 0xa0010070
.syscall_vram: .long 0x00000135
.end
.end*/