Add RAM memory managment
This commit is contained in:
parent
df00142f07
commit
145e75088c
|
@ -48,6 +48,16 @@ typedef struct fx9860_context_s
|
|||
uint32_t vbr;
|
||||
} fx9860_context_t;
|
||||
|
||||
typedef struct common_context_s
|
||||
{
|
||||
uint32_t reg[16];
|
||||
uint32_t gbr;
|
||||
uint32_t macl;
|
||||
uint32_t mach;
|
||||
uint32_t ssr;
|
||||
uint32_t spc;
|
||||
} common_context_t;
|
||||
|
||||
// Context primitive.
|
||||
extern void fx9860_context_save(fx9860_context_t *context);
|
||||
extern void fx9860_context_restore(fx9860_context_t *context);
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef __KERNEL_MEMORY_H__
|
||||
# define __KERNEL_MEMORY_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PM_BLOCK_SIZE (64)
|
||||
|
||||
struct pm_block_cache_s
|
||||
{
|
||||
// Block status
|
||||
enum {
|
||||
UNUSED,
|
||||
USED
|
||||
} status;
|
||||
|
||||
// Space informations.
|
||||
uint16_t start;
|
||||
uint32_t end;
|
||||
|
||||
// Linked list
|
||||
struct pm_block_cache_s *next;
|
||||
};
|
||||
|
||||
struct memory_info_s
|
||||
{
|
||||
// Cache informations.
|
||||
struct pm_block_cache_s *cache;
|
||||
struct pm_block_cache_s *head;
|
||||
|
||||
// RAM informations.
|
||||
uint32_t start;
|
||||
uint32_t blocks;
|
||||
};
|
||||
|
||||
// Function
|
||||
extern void *pm_alloc(size_t size);
|
||||
extern void pm_free(void *ptr);
|
||||
|
||||
#endif /*__KERNEL_MEMORY_H__*/
|
|
@ -0,0 +1,49 @@
|
|||
#ifndef __KERNEL_PROCESS_H__
|
||||
# define __KERNEL_PROCESS_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <kernel/context.h>
|
||||
#include <kernel/types.h>
|
||||
|
||||
#define PROCESS_NAME_LENGHT (16)
|
||||
#define PROCESS_MAX (3)
|
||||
|
||||
#define PROC_IDLE (0)
|
||||
|
||||
// define process struct.
|
||||
//TODO: signal !
|
||||
typedef struct process_s
|
||||
{
|
||||
// Process name.
|
||||
char name[PROCESS_NAME_LENGHT];
|
||||
|
||||
// Context management
|
||||
common_context_t context;
|
||||
|
||||
// Signals management.
|
||||
//sighandler_t signal[NSIG];
|
||||
|
||||
// Other process management.
|
||||
struct process_s *parent;
|
||||
struct process_s *child;
|
||||
struct process_s *next;
|
||||
} process_t;
|
||||
|
||||
// Internal struct used by the
|
||||
// static process stack
|
||||
struct process_stack_s
|
||||
{
|
||||
struct process_s process;
|
||||
int status;
|
||||
};
|
||||
|
||||
// Functions.
|
||||
extern pid_t process_create(const char *name);
|
||||
extern process_t *process_get(pid_t pid);
|
||||
extern int process_switch(pid_t pid);
|
||||
|
||||
// Internal function.
|
||||
extern pid_t process_alloc(process_t **process);
|
||||
|
||||
#endif /*__KERNEL_PROCESS_H__*/
|
|
@ -3,6 +3,26 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <kernel/types.h>
|
||||
|
||||
//---
|
||||
//
|
||||
// Vhex part !!
|
||||
//
|
||||
//---
|
||||
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);
|
||||
|
||||
|
||||
//---
|
||||
//
|
||||
// CASIO PART !!
|
||||
// TODO: remove me ?
|
||||
//
|
||||
//----
|
||||
|
||||
|
||||
// Internal Casio datat structure
|
||||
struct rect
|
||||
|
|
|
@ -26,6 +26,8 @@ typedef enum mpu_e
|
|||
MPU_UNKNOWN,
|
||||
} mpu_t;
|
||||
|
||||
typedef int pid_t;
|
||||
|
||||
// Force inline function.
|
||||
#define INLINE __attribute__((always_inline)) inline
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef __KERNEL_UNISTD_32_H__
|
||||
# define __KERNEL_UNISTD_32_H__
|
||||
|
||||
#define __NR_restart_syscall 0
|
||||
#define __NR_exit 1
|
||||
#define __NR_fork 2
|
||||
#define __NR_read 3
|
||||
#define __NR_write 4
|
||||
#define __NR_open 5
|
||||
#define __NR_close 6
|
||||
#define __NR_waitpid 7
|
||||
|
||||
#endif /*__KERNEL_UNISTD_32_H__*/
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef __LIB_UNISTD_H__
|
||||
# define __LIB_UNISTD_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <kernel/types.h>
|
||||
|
||||
// Define syscall LIST
|
||||
#include <kernel/unistd_32.h>
|
||||
|
||||
extern pid_t fork(void);
|
||||
|
||||
//TODO: move me
|
||||
#define WNOHANG 0
|
||||
#define WUNTRACED 1
|
||||
#define WCONTINUED 2
|
||||
extern pid_t waitpid(pid_t pid, int *wstatus, int options);
|
||||
|
||||
#endif /*__LIB_UNISTD_H__*/
|
|
@ -0,0 +1,56 @@
|
|||
.text
|
||||
|
||||
.global _kernel_switch
|
||||
.type _kernel_switch, @function
|
||||
|
||||
.align 2
|
||||
_kernel_switch:
|
||||
! Save process context into unbakable register
|
||||
! @note:
|
||||
! I do not save r8 ~ r14 because we will
|
||||
! never return into the bootstrap part.
|
||||
mov r4, r8
|
||||
|
||||
! Update SR register to block
|
||||
! interrupt / exception and
|
||||
! switch register bank to simalate
|
||||
! system call.
|
||||
mov.l .sr_msk, r1 ! get mask for SR.BL = 1, SR.RB = 1 and SR.IMASK = 0b1111
|
||||
stc sr, r0 ! get SR register
|
||||
or r1, r0 ! set mask for BL and IMASK
|
||||
ldc r0, sr ! update SR regsiter
|
||||
|
||||
! set process context into bankable register
|
||||
! because unbankable register will be over-written.
|
||||
mov r8, r0
|
||||
|
||||
! Load first process
|
||||
ldc.l @r0+, R0_BANK ! set "process" r0 regsiter
|
||||
ldc.l @r0+, R1_BANK ! set "process" r1 regsiter
|
||||
ldc.l @r0+, R2_BANK ! set "process" r2 regsiter
|
||||
ldc.l @r0+, R3_BANK ! set "process" r3 regsiter
|
||||
ldc.l @r0+, R4_BANK ! set "process" r4 regsiter
|
||||
ldc.l @r0+, R5_BANK ! set "process" r5 regsiter
|
||||
ldc.l @r0+, R6_BANK ! set "process" r6 regsiter
|
||||
ldc.l @r0+, R7_BANK ! set "process" r7 regsiter
|
||||
mov.l @r0+, r8 ! set r8 regsiter
|
||||
mov.l @r0+, r9 ! set r9 regsiter
|
||||
mov.l @r0+, r10 ! set r10 regsiter
|
||||
mov.l @r0+, r11 ! set r11 regsiter
|
||||
mov.l @r0+, r12 ! set r12 regsiter
|
||||
mov.l @r0+, r13 ! set r13 regsiter
|
||||
mov.l @r0+, r14 ! set r14 regsiter
|
||||
mov.l @r0+, r2 ! Stack not handled for now
|
||||
ldc.l @r0+, gbr ! set gbr regsiter
|
||||
lds.l @r0+, macl ! set macl regsiter
|
||||
lds.l @r0+, mach ! set mach regsiter
|
||||
ldc.l @r0+, ssr ! set ssr regsiter
|
||||
ldc.l @r0+, spc ! set spc regsiter
|
||||
|
||||
! Process switch
|
||||
rte
|
||||
nop
|
||||
|
||||
.align 4
|
||||
.sr_msk: .long 0x300000f0
|
||||
.end
|
|
@ -3,8 +3,8 @@
|
|||
#include <kernel/context.h>
|
||||
#include <kernel/atomic.h>
|
||||
#include <kernel/types.h>
|
||||
#include <kernel/process.h>
|
||||
#include <lib/display.h>
|
||||
#include <kernel/syscall.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
// Internal symbols
|
||||
|
@ -35,6 +35,7 @@ extern uint32_t edtors;
|
|||
|
||||
// Internal functions.
|
||||
extern void vhex_context_set(void);
|
||||
extern void kernel_switch(common_context_t *context);
|
||||
extern mpu_t mpu_get(void);
|
||||
extern int main(void);
|
||||
|
||||
|
@ -116,18 +117,20 @@ int start(void)
|
|||
vhex_context_set();
|
||||
atomic_end();
|
||||
|
||||
// Call high level abstraction
|
||||
error = main();
|
||||
// Create first process: Vhex.
|
||||
uint32_t ssr = atomic_start();
|
||||
pid_t vhex_pid = process_create("Vhex");
|
||||
process_t *vhex_process = process_get(vhex_pid);
|
||||
vhex_process->context.spc = (uint32_t)&main;
|
||||
vhex_process->context.ssr = ssr;
|
||||
|
||||
// Restore Casio's context.
|
||||
atomic_start();
|
||||
fx9860_context_restore(&casio_context);
|
||||
atomic_end();
|
||||
// Switch to first process.
|
||||
kernel_switch(&vhex_process->context);
|
||||
|
||||
// Execute destructor.
|
||||
section_execute(&bdtors, &edtors);
|
||||
|
||||
// Return properly
|
||||
// TODO: involve main menu ?
|
||||
return (error);
|
||||
// normally the kernel SHOULD not
|
||||
// arrive here.
|
||||
while (1)
|
||||
{
|
||||
__asm__ volatile ("sleep");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include <lib/display.h>
|
||||
|
||||
__attribute__((section(".vhex.exception"), interrupt_handler))
|
||||
void exception_handler(void)
|
||||
{
|
||||
uint32_t spc;
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
.section ".vhex.exception", "awx", @progbits
|
||||
|
||||
.global _exception_handler_pre
|
||||
.type _exception_handler_pre, @function
|
||||
|
||||
.extern _exception_handler
|
||||
.extern _syscall_pre
|
||||
|
||||
.align 2
|
||||
_exception_handler_pre:
|
||||
! Save critical regsiter.
|
||||
stc.l spc, @-r15 ! save SPC register.
|
||||
stc.l ssr, @-r15 ! save SSR register.
|
||||
sts.l pr, @-r15 ! save pr register.
|
||||
|
||||
! Check syscall (trapa)
|
||||
mov.l .expevt, r0 ! r0 = EXPEVT address.
|
||||
mov.l .trapa_code, r1 ! r1 = trapa exception code
|
||||
mov.l @r0, r0 ! r0 = excecption code
|
||||
cmp/eq r1, r0 ! if exception code == TRAPA CODE...
|
||||
bt _trapa_entry ! ...if yes, jump at <trapa_entry>
|
||||
|
||||
! Call high-level abstraction
|
||||
mov.l .exception_handler, r0 ! get high-level aception abstraction
|
||||
jsr @r0 ! call abstraction
|
||||
nop ! (db) nop
|
||||
bra _exception_handler_exit ! jump at <_exception_handler_exit>
|
||||
nop ! (db) nop.
|
||||
|
||||
_trapa_entry:
|
||||
! Call syscall pre handler
|
||||
mov.l .syscall_pre, r0 ! get syscall pre handler address
|
||||
jsr @r0 ! call pre handler
|
||||
nop ! (db) nop
|
||||
|
||||
|
||||
_exception_handler_exit:
|
||||
! Restore critical regsiter
|
||||
lds.l @r15+, pr ! restore PR register.
|
||||
ldc.l @r15+, ssr ! restore SSR regsiter.
|
||||
ldc.l @r15+, spc ! restore SPC regsiter.
|
||||
|
||||
! Exit properly
|
||||
rte ! exit
|
||||
nop ! (db) nop
|
||||
|
||||
.align 4
|
||||
.expevt: .long 0xff000024
|
||||
.trapa_code: .long 0x00000160
|
||||
.exception_handler: .long _exception_handler
|
||||
.syscall_pre: .long _syscall_pre
|
||||
.end
|
|
@ -0,0 +1,59 @@
|
|||
#include <kernel/memory.h>
|
||||
#include <lib/display.h>
|
||||
|
||||
// Internal data.
|
||||
struct memory_info_s pmemory;
|
||||
|
||||
__attribute__((constructor(101)))
|
||||
void memory_init(void)
|
||||
{
|
||||
extern uint32_t ram_start;
|
||||
uint32_t ram_end;
|
||||
uint32_t ram_size;
|
||||
|
||||
// TODO: determine RAM's end.
|
||||
ram_end = 0x88080000;
|
||||
ram_size = ram_end - (uint32_t)&ram_start;
|
||||
|
||||
// DEBUG
|
||||
/*dclear();
|
||||
dprint(0, 0, "RAM diagnostic");
|
||||
dprint(0, 1, "start = %p", &ram_start);
|
||||
dprint(0, 2, "end = %p", ram_end);
|
||||
dprint(0, 3, "size = %dko", ram_size / 1024);
|
||||
dupdate();*/
|
||||
//for (int i = 0 ; i < 9000000 ; i = i + 1);
|
||||
|
||||
// Get the number of block available
|
||||
// and calculate the real numer of block with
|
||||
// the cache.
|
||||
// TODO: check if RAM can be used ? (block == 0)
|
||||
// @note: try to avoid too long search part.
|
||||
pmemory.cache = (void*)&ram_start;
|
||||
pmemory.blocks = (ram_size / PM_BLOCK_SIZE) >> 1;
|
||||
ram_end = ram_end - (PM_BLOCK_SIZE * pmemory.blocks);
|
||||
while ((uint32_t)&pmemory.cache[pmemory.blocks] < ram_end - PM_BLOCK_SIZE)
|
||||
{
|
||||
pmemory.blocks = pmemory.blocks + 1;
|
||||
ram_end = ram_end - PM_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
// Get "real" physical memory start
|
||||
pmemory.start = ram_end;
|
||||
|
||||
// DEBUG
|
||||
/*dclear();
|
||||
dprint(0, 0, "Cache diagnostic");
|
||||
dprint(0, 1, "Bloks = %d (%do)", pmemory.blocks, PM_BLOCK_SIZE);
|
||||
dprint(0, 2, "Start = %p", pmemory.cache);
|
||||
dprint(0, 3, "PRAM = %p", pmemory.start);
|
||||
dupdate();
|
||||
for (int i = 0 ; i < 9000000 ; i = i + 1);*/
|
||||
|
||||
// Initialize cache
|
||||
for (uint32_t i = 0 ; i < pmemory.blocks ; i = i + 1)
|
||||
{
|
||||
pmemory.cache[i].status = UNUSED;
|
||||
pmemory.cache[i].next = NULL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
#include <kernel/memory.h>
|
||||
|
||||
static struct pm_block_cache_s *block_alloc(void)
|
||||
{
|
||||
extern struct memory_info_s pmemory;
|
||||
uint32_t i;
|
||||
|
||||
i = -1;
|
||||
while (++i < pmemory.blocks)
|
||||
{
|
||||
// Check if the block are used
|
||||
if (pmemory.cache[i].status == USED)
|
||||
continue;
|
||||
|
||||
// Initialize block and return address
|
||||
pmemory.cache[i].status = USED;
|
||||
pmemory.cache[i].next = NULL;
|
||||
return (&pmemory.cache[i]);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void *pm_alloc(size_t size)
|
||||
{
|
||||
extern struct memory_info_s pmemory;
|
||||
struct pm_block_cache_s **head;
|
||||
struct pm_block_cache_s *block;
|
||||
uint32_t block_entry;
|
||||
uint32_t nb_blocks;
|
||||
|
||||
// Check obvious error.
|
||||
if (size == 0)
|
||||
return (NULL);
|
||||
|
||||
// Get the number of blocks we need.
|
||||
nb_blocks = (size + PM_BLOCK_SIZE - 1) / PM_BLOCK_SIZE;
|
||||
|
||||
// Find block entry.
|
||||
block_entry = 0;
|
||||
head = &pmemory.head;
|
||||
while (*head != NULL)
|
||||
{
|
||||
// Check is it is the last allocated
|
||||
// object.
|
||||
if ((*head)->next == NULL)
|
||||
{
|
||||
// Check memory space.
|
||||
if ((*head)->end + 1 + nb_blocks >= pmemory.blocks)
|
||||
return (NULL);
|
||||
|
||||
// Get cache entry.
|
||||
block_entry = (*head)->end + 1;
|
||||
head = &(*head)->next;
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate the gap between current
|
||||
// allocated object and the next object.
|
||||
if (((*head)->next->start) - ((*head)->end + 1) >= nb_blocks)
|
||||
{
|
||||
block_entry = (*head)->end + 1;
|
||||
head = &(*head)->next;
|
||||
break;
|
||||
}
|
||||
|
||||
// Get next allocated block.
|
||||
head = &(*head)->next;
|
||||
}
|
||||
|
||||
// Setup new allocated block
|
||||
block = block_alloc();
|
||||
if (block == NULL)
|
||||
return (NULL);
|
||||
|
||||
// Initialize new block
|
||||
block->start = block_entry;
|
||||
block->end = block_entry + nb_blocks - 1;
|
||||
|
||||
// Insert new block.
|
||||
block->next = *head;
|
||||
*head = block;
|
||||
|
||||
// Generate physical memory address
|
||||
return ((void*)((block_entry * PM_BLOCK_SIZE) + pmemory.start));
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#include <kernel/memory.h>
|
||||
#include <kernel/devices/tty.h>
|
||||
|
||||
void pm_free(void *ptr)
|
||||
{
|
||||
extern struct memory_info_s pmemory;
|
||||
struct pm_block_cache_s **head;
|
||||
uint32_t block_entry;
|
||||
uint32_t sptr;
|
||||
|
||||
// Save address for error message.
|
||||
sptr = (uint32_t)ptr;
|
||||
|
||||
// Get the "real" physical space.
|
||||
ptr = (void*)(ptr - pmemory.start);
|
||||
|
||||
// Check misaligned pointer.
|
||||
if (((uint32_t)ptr % PM_BLOCK_SIZE) != 0)
|
||||
{
|
||||
tty_write(
|
||||
"pm_free: Warning, you try to free misaligned"
|
||||
"pointer address (%p)\n", sptr
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get block entry.
|
||||
block_entry = (uint32_t)ptr / PM_BLOCK_SIZE;
|
||||
|
||||
// Walk into "head" cache and try to find
|
||||
// the allocated block.
|
||||
head = &pmemory.head;
|
||||
while (*head != NULL)
|
||||
{
|
||||
// Check the allocated block.
|
||||
if ((*head)->start != block_entry)
|
||||
{
|
||||
head = &(*head)->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Free the block and return
|
||||
(*head)->status = UNUSED;
|
||||
*head = (*head)->next;
|
||||
return;
|
||||
}
|
||||
|
||||
// No block found, display error.
|
||||
tty_write(
|
||||
"pm_free: Warning, you try to free unused"
|
||||
"allocated memory (%p)", sptr
|
||||
);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#include <kernel/process.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
// This function SHOULD not be called
|
||||
// without atomic operation !!
|
||||
pid_t process_alloc(process_t **process)
|
||||
{
|
||||
extern struct process_stack_s process_stack[PROCESS_MAX];
|
||||
|
||||
for (int i = 0 ; i < PROCESS_MAX ; i = i + 1)
|
||||
{
|
||||
if (process_stack[i].status == PROC_IDLE)
|
||||
{
|
||||
*process = &process_stack[i].process;
|
||||
return (i);
|
||||
}
|
||||
}
|
||||
return (-1);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#include <kernel/process.h>
|
||||
|
||||
// Create all internal global
|
||||
// used to handle process.
|
||||
struct process_stack_s process_stack[PROCESS_MAX];
|
||||
process_t *process_current;
|
||||
|
||||
__attribute__((constructor))
|
||||
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;
|
||||
}
|
||||
|
||||
// No process is currently running.
|
||||
process_current = NULL;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#include <kernel/process.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
pid_t process_create(const char *name)
|
||||
{
|
||||
extern process_t *process_current;
|
||||
process_t *process;
|
||||
pid_t process_pid;
|
||||
|
||||
// Check error
|
||||
if (name == NULL)
|
||||
return (-1);
|
||||
|
||||
// Try to find free slot.
|
||||
process_pid = process_alloc(&process);
|
||||
if (process == NULL)
|
||||
return (-1);
|
||||
|
||||
// Set process name.
|
||||
strncpy(process->name, name, PROCESS_NAME_LENGHT);
|
||||
|
||||
// Initialize context.
|
||||
for (int i = 0 ; i < 16 ; i = i + 1)
|
||||
process->context.reg[i] = 0x00000000;
|
||||
process->context.gbr = 0x00000000;
|
||||
process->context.macl = 0x00000000;
|
||||
process->context.mach = 0x00000000;
|
||||
process->context.ssr = 0x00000000;
|
||||
process->context.spc = 0x00000000;
|
||||
|
||||
// Initialize processes.
|
||||
process->parent = process_current;
|
||||
process->child = NULL;
|
||||
process->next = NULL;
|
||||
return (process_pid);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#include <kernel/process.h>
|
||||
|
||||
process_t *process_get(pid_t pid)
|
||||
{
|
||||
extern struct process_stack_s process_stack[PROCESS_MAX];
|
||||
|
||||
// Check error
|
||||
if (pid < 0 || pid >= PROCESS_MAX)
|
||||
return (NULL);
|
||||
|
||||
// Return process.
|
||||
return (&process_stack[pid].process);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#include <kernel/process.h>
|
||||
|
||||
//FIXME: atomic operation !!
|
||||
int process_switch(pid_t pid)
|
||||
{
|
||||
extern process_t *process_current;
|
||||
common_context_t *context_current;
|
||||
common_context_t *context_next;
|
||||
process_t *process;
|
||||
|
||||
// Get current context
|
||||
context_current =
|
||||
(process_current != NULL)
|
||||
? &process_current->context
|
||||
: NULL;
|
||||
|
||||
// Get next context.
|
||||
process = process_get(pid);
|
||||
if (process == NULL)
|
||||
return (-1);
|
||||
context_next = &process->context;
|
||||
|
||||
// Context switch
|
||||
// TODO: SYSCALL !!!!!
|
||||
//context_switch(context_current, context_next);
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#include <kernel/process.h>
|
||||
|
||||
pid_t sys_fork(void)
|
||||
{
|
||||
extern process_t *process_current;
|
||||
process_t **process_new;
|
||||
pid_t process_pid;
|
||||
|
||||
// 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)
|
||||
return (-1);
|
||||
|
||||
// Initialize context.
|
||||
return (-1);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#include <kernel/process.h>
|
||||
|
||||
pid_t sys_waitpid(pid_t pid, int *wstatus, int options)
|
||||
{
|
||||
return (-1);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#include <kernel/syscall.h>
|
||||
#include <lib/display.h>
|
||||
|
||||
static const void *sys_handler[] = {
|
||||
NULL, //restart
|
||||
NULL, //exit
|
||||
sys_fork, //fork
|
||||
NULL, //read
|
||||
NULL, //write
|
||||
NULL, //open
|
||||
NULL, //close
|
||||
sys_waitpid, //waitpid
|
||||
};
|
||||
|
||||
void *sys_get_handler(int sysno)
|
||||
{
|
||||
//FIXME: Check sysno validity
|
||||
return ((void *)sys_handler[sysno]);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
.text
|
||||
.global _syscall_pre
|
||||
.type _syscall_pre, @function
|
||||
|
||||
.extern _sys_get_handler
|
||||
|
||||
.align 2
|
||||
_syscall_pre:
|
||||
! save some used register.
|
||||
mov.l r8, @-r15 ! save r8 register
|
||||
mov.l r9, @-r15 ! save r9 register
|
||||
sts.l pr, @-r15 ! save PR register
|
||||
|
||||
! Call syscall high-level abstraction
|
||||
! to get appropriate system handler
|
||||
mov.l .tra, r4 ! r4 = TRA regsiter address (trapa exception code)
|
||||
mov.l .sys_get_handler, r0 ! r0 = high-level abstration handler
|
||||
mov.l @r4, r4 ! r4 = trapa exception code
|
||||
jsr @r0 ! call abstraction
|
||||
shlr2 r4 ! (db) r4 = syscall number
|
||||
cmp/eq #0, r0 ! if r0 == NULL...
|
||||
bt.s syscall_pre_exit ! ...if yes, jump at <syscall_pre_exit>
|
||||
mov r0, r9 ! save kernel handler into unbankable register
|
||||
|
||||
! Get and save SR register
|
||||
stc sr, r0 ! get SR register
|
||||
mov r0, r8 ! save SR register
|
||||
|
||||
! Switch register bank and allow interrupt
|
||||
! @note: user context has been saved
|
||||
! during the `exception_handler_pre`
|
||||
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
|
||||
|
||||
! Call kernel abstraction
|
||||
jsr @r9 ! call system handler
|
||||
nop ! (db) nop.
|
||||
|
||||
! Restore SR regsiter
|
||||
ldc r8, sr ! SR.BL = 1, SR.RB = 1 and SR.IMASK = old mask.
|
||||
|
||||
syscall_pre_exit:
|
||||
! Restore used regsiter.
|
||||
lds.l @r15+, pr ! restore PR register
|
||||
mov.l @r15+, r9 ! restore r9 register
|
||||
mov.l @r15+, r8 ! restore r8 register
|
||||
|
||||
! Exit properly
|
||||
rts ! exit
|
||||
nop ! (db) nop
|
||||
|
||||
.align 4
|
||||
.tra: .long 0xff000020
|
||||
.sr_mask: .long ~(0x300000f0)
|
||||
.sys_get_handler: .long _sys_get_handler
|
||||
.end
|
|
@ -0,0 +1,12 @@
|
|||
.text
|
||||
.global _fork
|
||||
.type _fork, @function
|
||||
|
||||
#include "kernel/unistd_32.h"
|
||||
|
||||
.align 2
|
||||
_fork:
|
||||
trapa #__NR_fork
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -0,0 +1,12 @@
|
|||
.text
|
||||
.global _waitpid
|
||||
.type _waitpid, @function
|
||||
|
||||
#include "kernel/unistd_32.h"
|
||||
|
||||
.align 2
|
||||
_waitpid:
|
||||
trapa #__NR_waitpid
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -1,6 +1,7 @@
|
|||
#include "builtin.h"
|
||||
#include <kernel/devices/ubc.h>
|
||||
#include <lib/display.h>
|
||||
#include <lib/unistd.h>
|
||||
|
||||
// TODO: remove me !!
|
||||
extern void test(void);
|
||||
|
@ -15,6 +16,14 @@ VHEX_BUILTIN(fxdb)
|
|||
dprint(0, 0, "FXDB - entry !!");
|
||||
dupdate();
|
||||
for (int i = 0 ; i < 9000000 ; i = i + 1);
|
||||
|
||||
int fion = fork();
|
||||
dclear();
|
||||
dprint(0, 0, "FXDB - entry !!");
|
||||
dprint(0, 1, "fork test = %d", fion);
|
||||
dupdate();
|
||||
for (int i = 0 ; i < 9000000 ; i = i + 1);
|
||||
|
||||
return (0);
|
||||
|
||||
// Open User Break Controller.
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
#include "builtin.h"
|
||||
#include <kernel/memory.h>
|
||||
#include <lib/display.h>
|
||||
|
||||
VHEX_BUILTIN(ram)
|
||||
{
|
||||
extern struct memory_info_s pmemory;
|
||||
extern uint32_t ram_start;
|
||||
uint32_t ram_end;
|
||||
uint32_t ram_size;
|
||||
|
||||
// TODO: determine RAM's end.
|
||||
ram_end = 0x88080000;
|
||||
ram_size = ram_end - (uint32_t)&ram_start;
|
||||
|
||||
//dprint(0, 0, "RAM diagnostic");
|
||||
//dprint(0, 1, "start = %p", &ram_start);
|
||||
//dprint(0, 2, "end = %p", 0x88080000);
|
||||
//dprint(0, 3, "size = %dko", ram_size / 1024);
|
||||
|
||||
//dprint(0, 5, "Cache diagnostic");
|
||||
//dprint(0, 0, "Bloks = %d (%do)", pmemory.blocks, PM_BLOCK_SIZE);
|
||||
//dprint(0, 1, "Start = %p", pmemory.cache);
|
||||
//dprint(0, 2, "PRAM = %p", pmemory.start);
|
||||
//dupdate();
|
||||
|
||||
//TODO: GetKey
|
||||
//for (int i = 0 ; i < 9000000 ; i = i + 1);
|
||||
|
||||
// Try to alloc.
|
||||
void *test0 = pm_alloc(129);
|
||||
void *test1 = pm_alloc(1024);
|
||||
void *test2 = pm_alloc(129);
|
||||
|
||||
// Display address
|
||||
dclear();
|
||||
dprint(0, 0, "test0 = %p (129o)", test0);
|
||||
dprint(0, 1, "test1 = %p (1024o)", test1);
|
||||
dprint(0, 2, "test2 = %p (129o)", test2);
|
||||
|
||||
// Try to free allocated space.
|
||||
pm_free(test1);
|
||||
|
||||
// Try to alloc again.
|
||||
test1 = pm_alloc(64);
|
||||
|
||||
// Display RAM abstract cache
|
||||
int i = 0;
|
||||
struct pm_block_cache_s *head = pmemory.head;
|
||||
while (head != NULL && i < 7)
|
||||
{
|
||||
dprint(0, 3 + i, "s:%d-e:%d-n:%p", head->start, head->end, head->next);
|
||||
head = head->next;
|
||||
i = i + 1;
|
||||
}
|
||||
dupdate();
|
||||
for (int i = 0 ; i < 9000000 ; i = i + 1);
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
#include "builtin.h"
|
||||
#include <lib/string.h>
|
||||
#include <lib/display.h>
|
||||
#include <lib/unistd.h>
|
||||
|
||||
//TODO: use agc, argv.
|
||||
int check_builtin(char *cmd)
|
||||
|
@ -9,23 +10,38 @@ 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)
|
||||
{
|
||||
dclear();
|
||||
dprint(0, 0, "builtin - %s", list[i].name);
|
||||
dupdate();
|
||||
for (int i = 0 ; i < 9000000 ; i = i + 1);
|
||||
if (strcmp(list[i].name, cmd) != 0)
|
||||
continue;
|
||||
|
||||
// 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();*/
|
||||
|
||||
|
||||
if (strcmp(list[i].name, cmd) == 0)
|
||||
{
|
||||
list[i].entry(0, NULL);
|
||||
return (0);
|
||||
}
|
||||
// } else {
|
||||
// waitpid(pid, &wstatus, WCONTINUED);
|
||||
//TODO: signal handling.
|
||||
// }
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue