diff --git a/.vscode/settings.json b/.vscode/settings.json index bd128e451..7b24d33f3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,16 @@ { "files.associations": { "utils.h": "c", - "algorithm": "c" + "algorithm": "c", + "thread.h": "c", + "array": "c", + "string_view": "c", + "initializer_list": "c", + "utility": "c", + "*.tcc": "cpp", + "functional": "cpp", + "fstream": "cpp", + "istream": "cpp", + "streambuf": "cpp" } } \ No newline at end of file diff --git a/Makefile b/Makefile index 8dd400a04..7be4e558d 100644 --- a/Makefile +++ b/Makefile @@ -21,8 +21,8 @@ clean: rm kernel8.elf kernel8.img src/*.o *.o>/dev/null 2>/dev/null || true run: - qemu-system-aarch64 -M raspi3 -kernel kernel8.img --display none -serial null -serial stdio -s -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb - + # qemu-system-aarch64 -M raspi3 -kernel kernel8.img --display none -serial null -serial stdio -s -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial null -serial stdio -s -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb flash: sudo dd if=kernel8.img of=/dev/sdb diff --git a/a.S b/a.S index cb6b7e4f7..94c19c846 100644 --- a/a.S +++ b/a.S @@ -50,7 +50,7 @@ main_loop: b busy_loop .macro save_all - sub sp, sp, 32 * 9 + sub sp, sp, 16 * 17 stp x0, x1, [sp ,16 * 0] stp x2, x3, [sp ,16 * 1] stp x4, x5, [sp ,16 * 2] @@ -66,20 +66,30 @@ main_loop: stp x24, x25, [sp ,16 * 12] stp x26, x27, [sp ,16 * 13] stp x28, x29, [sp ,16 * 14] - str x30, [sp, 16 * 15] + + mrs x9, sp_el0 + stp x30,x9, [sp, 16 * 15] // for nested interrupt - mrs x0, spsr_el1 - mrs x1, elr_el1 - stp x0,x1, [sp, 16 * 16] - ldp x0, x1, [sp ,16 * 0] + mrs x9, spsr_el1 + mrs x10, elr_el1 + stp x9,x10, [sp, 16 * 16] + + // ldp x0, x1, [sp ,16 * 0] + + // for el0 user stack pointer + .endm // load general registers from stack .macro load_all - ldp x0,x1,[sp, 16 * 16] - msr spsr_el1,x0 - msr elr_el1,x1 + + ldp x30,x9, [sp, 16 * 15] + msr sp_el0,x9 + + ldp x9,x10,[sp, 16 * 16] + msr spsr_el1,x9 + msr elr_el1,x10 ldp x0, x1, [sp ,16 * 0] ldp x2, x3, [sp ,16 * 1] @@ -96,19 +106,26 @@ main_loop: ldp x24, x25, [sp ,16 * 12] ldp x26, x27, [sp ,16 * 13] ldp x28, x29, [sp ,16 * 14] - ldr x30, [sp, 16 * 15] + // ldr x30, [sp, 16 * 15] - add sp, sp, 32 * 9 + add sp, sp, 16 * 17 .endm +.global load_eret +load_eret: + load_all + eret + exception_handler: save_all + mov x0,sp bl exception_entry load_all eret irq_handler: save_all + mov x0,sp bl irq_entry load_all eret @@ -188,4 +205,55 @@ core_timer_handler: add x0,x0,x0 // add x0,x0,x1 msr cntp_tval_el0, x0 - ret \ No newline at end of file + ret + +.global switch_to +switch_to: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + + ldp x19, x20, [x1, 16 * 0] + ldp x21, x22, [x1, 16 * 1] + ldp x23, x24, [x1, 16 * 2] + ldp x25, x26, [x1, 16 * 3] + ldp x27, x28, [x1, 16 * 4] + ldp fp, lr, [x1, 16 * 5] + ldr x9, [x1, 16 * 6] + mov sp, x9 + msr tpidr_el1, x1 + ret + +.global get_current +get_current: + mrs x0, tpidr_el1 + ret + +.global save_cpu_context +save_cpu_context: + stp x19, x20, [x0, 16 * 0] + stp x21, x22, [x0, 16 * 1] + stp x23, x24, [x0, 16 * 2] + stp x25, x26, [x0, 16 * 3] + stp x27, x28, [x0, 16 * 4] + stp fp, lr, [x0, 16 * 5] + mov x9, sp + str x9, [x0, 16 * 6] + ret + +.global load_cpu_context +load_cpu_context: + ldp x19, x20, [x0, 16 * 0] + ldp x21, x22, [x0, 16 * 1] + ldp x23, x24, [x0, 16 * 2] + ldp x25, x26, [x0, 16 * 3] + ldp x27, x28, [x0, 16 * 4] + ldp fp, lr, [x0, 16 * 5] + ldr x9, [x0, 16 * 6] + mov sp, x9 + ret \ No newline at end of file diff --git a/include/cpio.h b/include/cpio.h index bc53ee991..ddc8c9c6f 100644 --- a/include/cpio.h +++ b/include/cpio.h @@ -5,7 +5,7 @@ extern uint32_t* cpio_addr; void cpio_ls(); void cpio_cat(); -unsigned long long cpio_get_addr(); +unsigned long cpio_get_addr(char** filedata,unsigned long* filesize); //void* initramfs_callback(fdt_prop* prop,char * name,uint32_t len_prop); void* initramfs_start_callback(fdt_prop* prop,char * name,uint32_t len_prop); void* initramfs_end_callback(fdt_prop* prop,char * name,uint32_t len_prop); diff --git a/include/filesys.h b/include/filesys.h new file mode 100644 index 000000000..e69de29bb diff --git a/include/mini_uart.h b/include/mini_uart.h index ff7e53ade..d43580458 100644 --- a/include/mini_uart.h +++ b/include/mini_uart.h @@ -59,6 +59,7 @@ char uart_buf_write_pop(); void busy_wait_writes(char *s,bool newline); void busy_wait_writec(char s); void busy_wait_writeint(int i,bool newline); +void busy_wait_writehex(unsigned long long h,bool newline); int is_empty_write(); int is_empty_read(); diff --git a/include/sched.h b/include/sched.h new file mode 100644 index 000000000..5ec0edc5d --- /dev/null +++ b/include/sched.h @@ -0,0 +1,69 @@ +#ifndef _SCHEDULE_HEADER_ +#define _SCHEDULE_HEADER_ +#define THREAD_STACK_SIZE 4096//4096 +#include "signal.h" +enum task_state +{ + EMPTY, + RUNNABLE, + WAITING, + RUNNING, + FINISHED, + ZOMBIE, +}; +typedef struct cpu_context +{ + unsigned long x19; + unsigned long x20; + unsigned long x21; + unsigned long x22; + unsigned long x23; + unsigned long x24; + unsigned long x25; + unsigned long x26; + unsigned long x27; + unsigned long x28; + unsigned long fp; + unsigned long lr; + unsigned long sp; +}cpu_context; +typedef struct Thread_struct +{ + cpu_context cpu_context; + enum task_state state; + unsigned int id; + void* user_stack; + void* kernel_stack; + struct Thread_struct *next,*prev; + // void (*singal_handler[10])(); + void (*signal_handler[20])(); + unsigned int signal_count[20]; + void* signal_ustack; + void (*run_handler)(); + cpu_context saved_context; + +}Thread_struct; +typedef struct task_queue +{ + Thread_struct* task; + struct task_queue *next,*prev; +}task_queue; + +int thread_create(void (*f)()); +Thread_struct current_thread(); +void schedule(); +void idle(); +void kill_zombie(); +void init_sched(); +void push_thread(Thread_struct*); +void iter_runqueue(); +void exec_thread(); +void context_switch(Thread_struct* next); +Thread_struct* pop_thread(); +void thread_exit(); +void thread_exec(); +Thread_struct* get_thread(int); +void kill_thread(int); +extern Thread_struct* get_current(); +void raise_signal(int pid,int signal); +#endif \ No newline at end of file diff --git a/include/signal.h b/include/signal.h new file mode 100644 index 000000000..04e5041fd --- /dev/null +++ b/include/signal.h @@ -0,0 +1,9 @@ +#ifndef _SIGNAL_HEADER_ +#define _SIGNAL_HEADER_ +#include "syscall.h" + +void run_signal(trap_frame*); +void signal_default_handler(int); +void sigreturn(); +void signal_registed_handler(void (*handler)()); +#endif \ No newline at end of file diff --git a/include/syscall.h b/include/syscall.h new file mode 100644 index 000000000..05914ea28 --- /dev/null +++ b/include/syscall.h @@ -0,0 +1,30 @@ +#ifndef _SYSCALL_HEADER_ +#define _SYSCALL_HEADER_ + +#define SYS_GETPID 0 +#define SYS_UART_READ 1 +#define SYS_UART_WRITE 2 +#define SYS_EXEC 3 +#define SYS_FORK 4 +#define SYS_EXIT 5 +#define SYS_MBOX_CALL 6 +#define SYS_KILL 7 + +typedef struct trap_frame{ + unsigned long long x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, + x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, + x21, x22, x23, x24, x25, x26, x27, x28, x29, x30; + unsigned long long sp_el0, spsr_el1, elr_el1; +}trap_frame; + +int sys_getpid(trap_frame*); +unsigned int sys_uart_read(trap_frame*,char buf[],unsigned long long size); +unsigned int sys_uart_write(trap_frame*,const char* name,unsigned long long size); +int sys_exec(trap_frame*,const char* name, char *const argv[]); +int sys_fork(trap_frame*); +void sys_exit(trap_frame*); +int sys_mbox_call(trap_frame*,unsigned char ch, unsigned int *mbox); +void sys_kill(trap_frame*,int pid); +void signal_register(int signal,void (*handler)()); +void signal_kill(int pid,int signal); +#endif \ No newline at end of file diff --git a/include/utils.h b/include/utils.h index be320f56d..8f9fad65f 100644 --- a/include/utils.h +++ b/include/utils.h @@ -54,5 +54,14 @@ static inline unsigned int powOf2ToExponent(int n){ } return exp; } +static inline void * +memcpy (void *dest, const void *src, size_t len) +{ + char *d = dest; + const char *s = src; + while (len--) + *d++ = *s++; + return dest; +} #endif \ No newline at end of file diff --git a/initramfs.cpio b/initramfs.cpio index 8f5c6ab59..c32da6749 100644 Binary files a/initramfs.cpio and b/initramfs.cpio differ diff --git a/src/allocator.c b/src/allocator.c index b71a442b6..47fc172b5 100644 --- a/src/allocator.c +++ b/src/allocator.c @@ -104,10 +104,10 @@ void* get_freeframe_addr(unsigned int size){ for (i = 0; i <= MAX_CONTIBLOCK_SIZE; i++) { if(frame_freelist[i]!=nullptr && BLOCK_SIZE*power(2,i)>=size){ - writes_uart("Require "); - write_int_uart(size,FALSE); - writes_uart(" ,Min free block size: "); - write_int_uart(BLOCK_SIZE *power(2,i),TRUE); + // writes_uart("Require "); + // write_int_uart(size,FALSE); + // writes_uart(" ,Min free block size: "); + // write_int_uart(BLOCK_SIZE *power(2,i),TRUE); break; } } @@ -154,8 +154,8 @@ void* get_freeframe_addr(unsigned int size){ // frame_freelist[i] = frame_freelist[i]->next; - writes_uart("Got block size: "); - write_int_uart(-frame_array[node->_index]->size,TRUE); + // writes_uart("Got block size: "); + // write_int_uart(-frame_array[node->_index]->size,TRUE); unsigned long long freeframe_addr = ALLOCATOR_START + node->_index*BLOCK_SIZE; return (void*)freeframe_addr; @@ -406,10 +406,10 @@ void* get_freechunk_addr(int size){ void* my_malloc(unsigned int size){ void* malloc_addr = nullptr; if(size<=chunk_size_arr[chunk_arr_len-1]){ - writes_uart("Chunk malloc "); + // writes_uart("Chunk malloc "); int chunk_size = getBestChunkSize(size); - write_int_uart(chunk_size,TRUE); + // write_int_uart(chunk_size,TRUE); malloc_addr = get_freechunk_addr(chunk_size); // unsigned int chunk_frame_idx = frameAddrToIdx(malloc_addr); diff --git a/src/cpio.c b/src/cpio.c index cfb46a1d5..57770a2b4 100644 --- a/src/cpio.c +++ b/src/cpio.c @@ -4,6 +4,7 @@ #include "shell.h" #include "utils.h" #include "dtb.h" +#include "exception.h" #define CPIO_HEADER_MAGIC "070701" #define CPIO_FOOTER_MAGIC "TRAILER!!!" #define CPIO_ALIGNMENT 4 @@ -108,7 +109,7 @@ void cpio_cat(){ writes_uart("Filename: "); char* read_name; read_string(&read_name); - + while(1){ int parse_result = cpio_parse_header(cnh,&filename,&filesize,&filedata,&next_header); if(parse_result!=0){ @@ -132,28 +133,31 @@ void cpio_cat(){ } } -unsigned long long cpio_get_addr(){ +unsigned long cpio_get_addr(char** filedata,unsigned long* filesize){ cpio_newc_header* cnh = (cpio_newc_header*)cpio_addr; cpio_newc_header* next_header; char *filename; - char *filedata; - unsigned long filesize; + // char *filedata; + // unsigned long filesize; writes_uart("Filename: "); char* read_name; read_string(&read_name); while(1){ - if(cpio_parse_header(cnh,&filename,&filesize,&filedata,&next_header)!=0){ + if(cpio_parse_header(cnh,&filename,filesize,filedata,&next_header)!=0){ writes_uart("File not found!\r\n"); + *filesize=0; break; } if(strncmp(read_name,".",strlen(read_name))==0){ writes_uart(".: Is a directory\r\n"); + *filesize=0; break; } else if(strncmp(read_name,filename,strlen(read_name))==0){ // writes_n_uart(filedata,parse_hex_str(cnh->c_filesize,sizeof(cnh->c_filesize))); // writes_uart("\r\n"); + return (unsigned long long)filedata; break; } diff --git a/src/exception.c b/src/exception.c index 4b4926754..b9356ad9c 100644 --- a/src/exception.c +++ b/src/exception.c @@ -3,7 +3,9 @@ #include "string.h" #include "timer.h" #include "task.h" - +#include "syscall.h" +#include "sched.h" +#include "signal.h" void enable_interrupt(){ asm volatile( "msr DAIFClr, 0xf" @@ -17,8 +19,8 @@ void disable_interrupt(){ } -void exception_entry(){ - busy_wait_writes("EXCEPTION ENTRY",TRUE); +void exception_entry(trap_frame* tf){ + // busy_wait_writes("EXCEPTION ENTRY",TRUE); // spsr_el1, elr_el1, and esr_el1 unsigned long long reg_spsr_el1, reg_elr_el1,reg_esr_el1; asm volatile( @@ -29,18 +31,66 @@ void exception_entry(){ "=r" (reg_elr_el1), "=r" (reg_esr_el1) ); - writes_uart("Exception\r\n"); - writes_uart("spsr_el1: "); - writehex_uart(reg_spsr_el1,1); - writes_uart("reg_elr_el1: "); - writehex_uart(reg_elr_el1,1); - writes_uart("reg_esr_el1: "); - writehex_uart(reg_esr_el1,1); + /* + https://developer.arm.com/documentation/ddi0601/2021-12/AArch64-Registers/ESR-EL1--Exception-Syndrome-Register--EL1-?lang=en + EC, bits [31:26], 0b010101: SVC instruction execution in AArch64 state. + */ + unsigned long long ec = reg_esr_el1>>26; + if(ec == 0b010101){ + switch (tf->x8) + { + case 0: // getpid + sys_getpid(tf); + break; + case 1: // uart_read + sys_uart_read(tf,(char*)tf->x0,tf->x1); + break; + case 2: // uart_write + sys_uart_write(tf,(char*)tf->x0,tf->x1); + break; + case 3: // exec + sys_exec(tf,(char*)tf->x0,(char**)tf->x1); + break; + case 4: // fork + sys_fork(tf); + break; + case 5: // exit + sys_exit(tf); + break; + case 6: // mbox_call + sys_mbox_call(tf,(unsigned char)tf->x0,(unsigned int*)tf->x1); + break; + case 7: // kill + sys_kill(tf,(int)tf->x0); + break; + case 8: + signal_register(tf->x0, (void (*)())(tf->x1)); + break; + case 9: + signal_kill(tf->x0,tf->x1); + break; + case 21: + sigreturn(); + default: + break; + } + } + else{ + disable_timer_interrupt(); + writes_uart("Exception\r\n"); + writes_uart("spsr_el1: "); + writehex_uart(reg_spsr_el1,1); + writes_uart("reg_elr_el1: "); + writehex_uart(reg_elr_el1,1); + writes_uart("reg_esr_el1: "); + writehex_uart(reg_esr_el1,1); + enable_timer_interrupt(); + } return; } int curr_task_privilege = 100; -void irq_entry(){ +void irq_entry(trap_frame* tf){ // writes_uart("IRQ entry\r\n"); // writes_uart("Interrupt Source:"); @@ -92,14 +142,14 @@ void irq_entry(){ add_task(Timer_interrupt_handler,INTERRUPT_PRIVILEGE_TIMER); if(curr_task_privilegespsr_el1 & 0b1111) == 0) + { + run_signal(tf); + } return; } @@ -141,35 +196,42 @@ void Timer_interrupt_handler(){ ); //itr_timer_queue(); // busy_wait_writes("TIMER INT",TRUE); - if(is_timerq_empty()){ - write_int_uart((int)(time_count/time_freq),0); - writes_uart(" seconds After booting\r\n"); - // set_expired_time(0x0fffffff); - disable_timer_interrupt(); - return; - } - else{ - writes_uart("Current time is: "); - write_int_uart((int)(time_count/time_freq),1); - timer* h = get_head_timer(); - h->callback(h->message); - // writes_uart("DEBUG:"); - // writes_nl_uart(h->message); - if(h->next==nullptr){ - writes_uart("next timer is not exist.\r\n"); - h = to_next_timer(); - disable_timer_interrupt(); - } - else{ - h = to_next_timer(); - writes_uart("Found next timer in "); - write_int_uart(h->value,TRUE); - unsigned long long time_count=0; - unsigned long long time_freq=0; - get_current_time(&time_count,&time_freq); - set_expired_time(h->value - time_count/time_freq); - enable_timer_interrupt(); - } - } + // for schedule timer interrupt + asm volatile( + "msr cntp_tval_el0, %0\n\t" + ::"r" (time_freq>>5) + ); + // schedule(); + + // if(is_timerq_empty()){ + // // write_int_uart((int)(time_count/time_freq),0); + // // writes_uart(" seconds After booting\r\n"); + // // set_expired_time(0x0fffffff); + // disable_timer_interrupt(); + // return; + // } + // else{ + // writes_uart("Current time is: "); + // write_int_uart((int)(time_count/time_freq),1); + // timer* h = get_head_timer(); + // h->callback(h->message); + // // writes_uart("DEBUG:"); + // // writes_nl_uart(h->message); + // if(h->next==nullptr){ + // writes_uart("next timer is not exist.\r\n"); + // h = to_next_timer(); + // disable_timer_interrupt(); + // } + // else{ + // h = to_next_timer(); + // writes_uart("Found next timer in "); + // write_int_uart(h->value,TRUE); + // unsigned long long time_count=0; + // unsigned long long time_freq=0; + // get_current_time(&time_count,&time_freq); + // set_expired_time(h->value - time_count/time_freq); + // enable_timer_interrupt(); + // } + // } } \ No newline at end of file diff --git a/src/filesys.c b/src/filesys.c new file mode 100644 index 000000000..e69de29bb diff --git a/src/main.c b/src/main.c index f74aee944..e7254a781 100644 --- a/src/main.c +++ b/src/main.c @@ -8,98 +8,70 @@ #include "timer.h" #include "task.h" #include "allocator.h" +#include "sched.h" extern unsigned long _head_start_brk; +extern Thread_struct* get_current(); +void foo() +{ + for(int i = 0; i < 10; ++i) { + unsigned long long reg_sp_el0; + asm volatile( + "mrs %0,sp_el0\n\t" + : "=r" (reg_sp_el0) + ); + writes_uart("Thread id: "); + write_int_uart(get_current()->id,FALSE); + writes_uart(" "); + write_int_uart(i,TRUE); + // delay(1000000); + // unsigned long long time_count=0; + // unsigned long long time_freq=0; + // get_current_time(&time_count,&time_freq); + // unsigned long long time_target = time_count + time_freq*0.01; + // while(time_count < time_target){ + // get_current_time(&time_count,&time_freq); + // } + schedule(); + } + thread_exit(); + // get_current()->state = FINISHED; +} -// uint32_t* cpio_addr; -// bool initramfs_callback(fdt_prop* prop,char * name,uint32_t len_prop){ -// if(strncmp(name,"linux,initrd-start",18)==0){ // start address of initrd -// writes_uart("Found target: \""); -// writes_n_uart(name,18); -// writes_uart("\" at address "); -// cpio_addr = (unsigned int*)((unsigned long)big2little(*((uint32_t*)(prop+1)))); -// writehex_uart((unsigned long)cpio_addr,TRUE); -// return TRUE; -// } -// else if(strncmp(name,"linux,initrd-end",18)==0) -// { -// writes_uart("Found target: \""); -// writes_n_uart(name,18); -// writes_uart("\" at address "); -// cpio_addr = (unsigned int*)((unsigned long)big2little(*((uint32_t*)(prop+1)))); -// writehex_uart((unsigned long)cpio_addr,TRUE); -// return TRUE; -// } -// return FALSE; -// } int main(){ // register unsigned long dtb_reg asm ("x15"); //init_frame_freelist(); + uint64_t tmp; + asm volatile("mrs %0, cntkctl_el1" : "=r"(tmp)); + tmp |= 1; + asm volatile("msr cntkctl_el1, %0" : : "r"(tmp)); init_uart(); init_uart_buf(); init_taskq(); init_memory(); init_timer(); - + init_sched(); *AUX_MU_IER_REG = 1; // 3 for RX, TX interrupt enable *IRQ_ENABLE1 = 1<<29; writes_uart("\r\n"); - writes_uart("██╗ ██╗███████╗██╗ ██████╗ ██████╗ ███╗ ███╗███████╗\r\n"); - writes_uart("██║ ██║██╔════╝██║ ██╔════╝██╔═══██╗████╗ ████║██╔════╝\r\n"); - writes_uart("██║ █╗ ██║█████╗ ██║ ██║ ██║ ██║██╔████╔██║█████╗ \r\n"); - writes_uart("██║███╗██║██╔══╝ ██║ ██║ ██║ ██║██║╚██╔╝██║██╔══╝ \r\n"); - writes_uart("╚███╔███╔╝███████╗███████╗╚██████╗╚██████╔╝██║ ╚═╝ ██║███████╗\r\n"); - writes_uart("╚══╝╚══╝ ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝\r\n"); - - // writes_uart("Hello World!\r\n"); + // writes_uart("██╗ ██╗███████╗██╗ ██████╗ ██████╗ ███╗ ███╗███████╗\r\n"); + // writes_uart("██║ ██║██╔════╝██║ ██╔════╝██╔═══██╗████╗ ████║██╔════╝\r\n"); + // writes_uart("██║ █╗ ██║█████╗ ██║ ██║ ██║ ██║██╔████╔██║█████╗ \r\n"); + // writes_uart("██║███╗██║██╔══╝ ██║ ██║ ██║ ██║██║╚██╔╝██║██╔══╝ \r\n"); + // writes_uart("╚███╔███╔╝███████╗███████╗╚██████╗╚██████╔╝██║ ╚═╝ ██║███████╗\r\n"); + // writes_uart("╚══╝╚══╝ ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝\r\n"); - // unsigned long long cur_excep_lvl; - // asm volatile( - // "mrs x0, CurrentEL\n\t" - // "mov %0,x0\n\t" - // :"=r" (cur_excep_lvl) - // ); - // writes_uart("Current exceotion level:"); - // writehex_uart(cur_excep_lvl>>2,1); - - // writes_uart("Loaded dtb address: "); - // writehex_uart(dtb_reg); - // writes_uart("\r\n"); - - // fdt_traverse(initramfs_start_callback); - // fdt_traverse(initramfs_end_callback); - - // list_freeChunkNode(); - // list_freeFrameNode(); + writes_uart("Hello World!\r\n"); - // unsigned long long got_freeaddr[16]; - // for (int i = 0; i < 16; i++) + // for (int i = 0; i < 10; i++) // { - // unsigned int* f_addr; - // writes_uart("Mallocing "); - // write_int_uart(power(2,i),TRUE); - // f_addr = my_malloc(power(2,i)); - - // got_freeaddr[i]=f_addr; - // writes_uart("Got address "); - // writehex_uart((unsigned int)f_addr,TRUE); - // // list_freeFrameNode(); + // thread_create(foo); // } - // list_freeChunkNode(); - // list_freeFrameNode(); - - // for (int i = 0; i < 16; i++) - // { - // writes_uart("Free address "); - // writehex_uart(got_freeaddr[i],TRUE); - // free(got_freeaddr[i]); - // } - // list_freeChunkNode(); - // list_freeFrameNode(); - + // idle(); + // disable_timer_interrupt(); while(1) { // writes_uart("main\r\n"); diff --git a/src/mini_uart.c b/src/mini_uart.c index 9c074dd94..907b251b0 100644 --- a/src/mini_uart.c +++ b/src/mini_uart.c @@ -314,4 +314,20 @@ void busy_wait_writeint(int s,bool newline){ if(newline) busy_wait_writes("\r\n",FALSE); +} +void busy_wait_writehex(unsigned long long h,bool newline) +{ + busy_wait_writes("0x",FALSE); + unsigned int n; + int c; + for(c=28;c>=0;c-=4) { + + n=(h>>c)&(0xF); // n = 1,2,3....th byte of h from left to right. + + n+=n>9?0x37:0x30; // int 0~9 -> char '0'~'9', 10~15 -> 'A'~'F' + busy_wait_writec(n); + } + if(newline==1){ + busy_wait_writes("\r\n",FALSE); + } } \ No newline at end of file diff --git a/src/sched.c b/src/sched.c new file mode 100644 index 000000000..1b68b3827 --- /dev/null +++ b/src/sched.c @@ -0,0 +1,192 @@ + +#include "mini_uart.h" +#include "allocator.h" +#include "sched.h" +#include "exception.h" +#include "cpio.h" +#include "timer.h" +#include "syscall.h" +#include "signal.h" +#define TASK_POOL_SIZE 20 + +extern void switch_to(Thread_struct* prev, Thread_struct* next); + +Thread_struct* thread_pool; +Thread_struct* run_queue; +Thread_struct* wait_queue; + +int thread_create(void (*f)()){ + int i; + for (i = 0; i < TASK_POOL_SIZE; i++) + { + if(thread_pool[i].state == EMPTY){ + break; + } + } + thread_pool[i].state = RUNNING; + thread_pool[i].user_stack = my_malloc(THREAD_STACK_SIZE); + thread_pool[i].kernel_stack = my_malloc(THREAD_STACK_SIZE); + thread_pool[i].cpu_context.lr = (unsigned long)f; + thread_pool[i].cpu_context.fp = (unsigned long)(thread_pool[i].kernel_stack + THREAD_STACK_SIZE); + thread_pool[i].cpu_context.sp = (unsigned long)(thread_pool[i].kernel_stack + THREAD_STACK_SIZE); + for(int j=0;j<20;j++) + { + thread_pool[i].signal_handler[j] = signal_default_handler; + thread_pool[i].signal_count[j] = 0; + } + thread_pool[i].signal_ustack = nullptr; + thread_pool[i].run_handler = nullptr; + writes_uart("Create Thread "); + write_int_uart(i,TRUE); + push_thread(&thread_pool[i]); + return i; +} +void schedule() +{ + disable_interrupt(); + if(run_queue != nullptr) + { + Thread_struct* next = pop_thread(run_queue); + // context_switch(next); + Thread_struct* cur = get_current(); + if (cur->state == RUNNING && cur->id !=0) + { + push_thread(cur); + } + // busy_wait_writes("From ",FALSE); + // busy_wait_writeint(cur->id,FALSE); + // busy_wait_writes(" schedule to ",FALSE); + // busy_wait_writeint(next->id,TRUE); + // iter_runqueue(); + enable_interrupt(); + // enable_timer_interrupt(); + switch_to(cur,next); + } + enable_interrupt(); + return; +} +void context_switch(Thread_struct* next) { + + // Thread_struct *current = get_current(); + // asm volatile("msr sp_el0, %0" : : "r"(&ustack_pool[current->id][USTACK_TOP_IDX])); + // asm volatile("msr elr_el1, %0": : "r"(func)); + // asm volatile("msr spsr_el1, %0" : : "r"(SPSR_EL1_VALUE)); + // asm volatile("eret"); +} +void init_sched() +{ + run_queue = nullptr; + thread_pool = my_malloc(TASK_POOL_SIZE * sizeof(Thread_struct)); + for (int i = 0; i < TASK_POOL_SIZE; i++) + { + thread_pool[i].state = EMPTY; + thread_pool[i].id = i; + thread_pool[i].cpu_context.sp = (unsigned long)nullptr; + } + thread_pool[0].state = RUNNING; // idle task; + asm volatile( + "msr tpidr_el1, %0" + :: "r" (&thread_pool[0]) + ); +} +void idle() +{ + // iter_runqueue(); + while(TRUE) + { + kill_zombie(); + schedule(); + } +} +void kill_zombie() +{ + +} +void thread_exit() +{ + get_current()->state = ZOMBIE; + schedule(); +} +void iter_runqueue() +{ + Thread_struct* node = run_queue; + while(node != nullptr){ + busy_wait_writeint(node->id,FALSE); + busy_wait_writes("->",FALSE); + node = node->next; + } + busy_wait_writes("\r\n",FALSE); +} +void push_thread(Thread_struct* t) +{ + if(run_queue == nullptr){ + // run_queue = my_malloc(sizeof(Thread_struct)); + run_queue = t; + run_queue->next = nullptr; + run_queue->prev = nullptr; + + } + else{ + Thread_struct* node; + node = run_queue; + while(node->next != nullptr){ + node = node->next; + } + node->next = t; + t->prev = node; + t->next = nullptr; + // writes_uart("Pushed in to queue: "); + // write_int_uart(t->id,TRUE); + } +} +Thread_struct* pop_thread() +{ + Thread_struct* q = run_queue; + if(run_queue!=nullptr){ + if(q->next){ + q->next->prev = nullptr; + } + run_queue = run_queue->next; + } + return q; +} +void thread_exec() +{ + + char **file_start = my_malloc(sizeof(char*)); + unsigned long *filesize = my_malloc(sizeof(unsigned long)); + // cpio_get_addr(file_start,&filesize); + cpio_get_addr(file_start,filesize); + + char *new_start = my_malloc(*filesize); + memcpy(new_start,*file_start,*filesize); + Thread_struct* cur_thread = get_current(); + asm volatile( + "mov x0, 0\n\t" // + "msr spsr_el1, x0\n\t" + "msr elr_el1, %0\n\t" + "msr sp_el0,%1\n\t" + "mov sp, %2\n\t" + "msr tpidr_el1, %3\n\t" + ::"r" (new_start), + "r" ((char*)(cur_thread->user_stack+THREAD_STACK_SIZE)), + "r" ((char*)(cur_thread->kernel_stack+THREAD_STACK_SIZE)), + "r" ((char*)cur_thread) + : "x0" + ); + + asm volatile( + "eret\n\t" // + ); +} +Thread_struct* get_thread(int id){ + return &(thread_pool[id]); +} +void kill_thread(int id) +{ + thread_pool[id].state = ZOMBIE; +} +void raise_signal(int pid,int signal) +{ + thread_pool[pid].signal_count[signal]++; +} \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index c7a21e5d8..d2e5d73c5 100644 --- a/src/shell.c +++ b/src/shell.c @@ -6,6 +6,7 @@ #include "stdlib.h" #include "timer.h" #include "allocator.h" +#include "sched.h" int match_command(char *buffer){ if(strcmp(buffer,"help")==0){ @@ -209,7 +210,7 @@ void handle_command(enum Action action, char *buffer){ writes_uart("ccreboot : cancel reboot the device\r\n"); writes_uart("ls : print the files in rootfs.\r\n"); writes_uart("cat : print the file information\r\n"); - writes_uart("usrprog : load user program and run it\r\n"); + writes_uart("prog : load user program and run it\r\n"); writes_uart("timeout : set timer timeout events\r\n"); writes_uart("mmalloc : test the malloc function\r\n"); writes_uart("mfree : free testing malloc address\r\n"); @@ -244,27 +245,36 @@ void handle_command(enum Action action, char *buffer){ break; case prog: { - unsigned long long prog_addr = cpio_get_addr(); - unsigned long *e0_stack = (unsigned long*)simple_malloc(2000); - writehex_uart(prog_addr,1); - // writehex_uart(e0_stack); - // writes_uart("\r\n"); + // // origin + // char *filedata = nullptr; + // unsigned long filesize; + + // unsigned long long prog_addr = cpio_get_addr(filedata,&filesize); + + // // unsigned long long prog_addr = (unsigned long long)filedata; + // unsigned long *e0_stack = (unsigned long*)simple_malloc(2000); + // writehex_uart(prog_addr,1); + // // writehex_uart(e0_stack); + // // writes_uart("\r\n"); + // // asm volatile( + // // "bl core_timer_enable\n\t" + // // // "bl core_timer_handler\n\t" + // // ); // asm volatile( - // "bl core_timer_enable\n\t" - // // "bl core_timer_handler\n\t" - // ); - asm volatile( - "mov x0, 0\n\t" // - "msr spsr_el1, x0\n\t" - "msr elr_el1, %0\n\t" - "msr sp_el0,%1\n\t" + // "mov x0, 0\n\t" // + // "msr spsr_el1, x0\n\t" + // "msr elr_el1, %0\n\t" + // "msr sp_el0,%1\n\t" - "eret\n\t" // - ::"r" (prog_addr), - "r" (e0_stack) - : "x0" - ); - writes_nl_uart("Run userprogram done"); + // "eret\n\t" // + // ::"r" (prog_addr), + // "r" (e0_stack) + // : "x0" + // ); + // writes_nl_uart("Run userprogram done"); + + thread_create(&thread_exec); + idle(); break; } case timeout: diff --git a/src/signal.c b/src/signal.c new file mode 100644 index 000000000..e5dc437c2 --- /dev/null +++ b/src/signal.c @@ -0,0 +1,59 @@ +#include "signal.h" +#include "sched.h" +#include "syscall.h" +#include "allocator.h" +#include "exception.h" +#include "mini_uart.h" +void signal_default_handler(int pid) +{ + sys_kill(0,pid); +} +void signal_registed_handler(void (*handler)()) +{ + Thread_struct* cur_thread = get_current(); + cur_thread->run_handler(); + asm volatile + ( + "mov x8,21\n\t" + "svc 0\n\t" + ); +} +extern void save_cpu_context(cpu_context* ctx); +void run_signal(trap_frame* tf) +{ + Thread_struct* cur_thread = get_current(); + save_cpu_context(&(cur_thread->saved_context)); + for(int j=0;j<20;j++) + { + if(cur_thread->signal_count[j] >0 ) + { + cur_thread->signal_count[j]--; + void* sig_func = cur_thread->signal_handler[j]; + if(sig_func == signal_default_handler) // if it is default function, + { + signal_default_handler(cur_thread->id); + } + else + { + cur_thread->signal_ustack = my_malloc(THREAD_STACK_SIZE); + cur_thread->run_handler = sig_func; + asm volatile("mov x0, %0": : "r"(sig_func)); + asm volatile("msr sp_el0, %0" : : "r"(cur_thread->signal_ustack + THREAD_STACK_SIZE)); + asm volatile("msr elr_el1, %0": : "r"(signal_registed_handler)); + // asm volatile("msr spsr_el1, %0" : : "r"(0)); + asm volatile("eret"); + } + + } + } + +} +extern void load_cpu_context(cpu_context* ctx); +void sigreturn() +{ + disable_interrupt(); + Thread_struct* cur_thread = get_current(); + free(cur_thread->signal_ustack); + load_cpu_context(&(cur_thread->saved_context)); + enable_interrupt(); +} \ No newline at end of file diff --git a/src/syscall.c b/src/syscall.c new file mode 100644 index 000000000..87463e754 --- /dev/null +++ b/src/syscall.c @@ -0,0 +1,153 @@ +#include "syscall.h" +#include "sched.h" +#include "mini_uart.h" +#include "cpio.h" +#include "allocator.h" +#include "utils.h" +#include "exception.h" +#include "mailbox.h" +#include "timer.h" +extern Thread_struct* get_current(); +int sys_getpid(trap_frame* tf){ + disable_interrupt(); + int pid = get_current()->id; + tf->x0 = pid; + // unsigned long long reg_sp_el0; + // asm volatile( + // "mrs %0,sp_el0\n\t" + // : "=r" (reg_sp_el0) + // ); + // busy_wait_writehex(reg_sp_el0,TRUE); + enable_interrupt(); + return pid; +} +unsigned int sys_uart_read(trap_frame* tf,char buf[],unsigned long long size) +{ + enable_interrupt(); + for (int i = 0; i < size; i++) + { + // buf[i] = read_uart(); + do{asm volatile("nop");}while(is_empty_read()); + buf[i] = uart_buf_read_pop(); + } + disable_interrupt(); + tf->x0 = size; + enable_interrupt(); + return size; +} +unsigned int sys_uart_write(trap_frame* tf,const char* name,unsigned long long size) +{ + enable_interrupt(); + for (int i = 0; i < size; i++) + { + busy_wait_writec(name[i]); + // writec_uart(name[i]); + } + disable_interrupt(); + tf->x0 = size; + enable_interrupt(); + return size; +} +int kernel_exec(trap_frame* tf,const char* name, char *const argv[]) +{ + // char *file_start = nullptr; + // unsigned long filesize; + // cpio_get_addr(file_start,&filesize); + // char *new_start = my_malloc(filesize); + // memcpy(new_start,file_start,filesize); + // thread_exec(new_start); + + + // if(filesize!=0){ // file not found if filesize == 0 + // tf->sp_el0 = (unsigned long)(get_current()->user_stack + THREAD_STACK_SIZE); + // tf->elr_el1 = (unsigned long)new_start; + // tf->spsr_el1 = 0; + // // asm volatile("msr sp_el0, %0" : : "r"(get_current()->user_stack + THREAD_STACK_SIZE)); + // // asm volatile("msr elr_el1, %0": : "r"(file_start)); + // // asm volatile("msr spsr_el1, %0" : : "r"(SPSR_EL1_VALUE)); + // // asm volatile("eret"); + // } + return 0; +} +int sys_exec(trap_frame* tf,const char* name, char *const argv[]) +{ + char **file_start = my_malloc(sizeof(char*)); + unsigned long* filesize = my_malloc(sizeof(unsigned long)); + cpio_get_addr(file_start,filesize); + char *new_start = my_malloc(*filesize); + memcpy(new_start,*file_start,*filesize); + if(filesize!=0){ // file not found if filesize == 0 + tf->sp_el0 = (unsigned long)(get_current()->user_stack + THREAD_STACK_SIZE); + tf->elr_el1 = (unsigned long)new_start; + tf->spsr_el1 = 0; + } + return 0; +} +extern void load_eret(); +int sys_fork(trap_frame* tf) +{ + disable_interrupt(); + // busy_wait_writehex(tf->sp_el0,TRUE); + Thread_struct* cur_thread = get_current(); + + int child_id = thread_create((void*)cur_thread->cpu_context.lr); + + Thread_struct* child_thread = get_thread(child_id); + + for(int i=0;i<20;i++) + { + child_thread->signal_handler[i] = cur_thread->signal_handler[i]; + } + // // copy parent's cpu context to child + memcpy(&(child_thread->cpu_context),&(cur_thread->cpu_context),sizeof(cpu_context)); + // // copy parent's user stack to child + memcpy(child_thread->user_stack,cur_thread->user_stack,THREAD_STACK_SIZE); + // // copy trap frame to child sp + trap_frame* child_tf = (trap_frame*)(child_thread->kernel_stack + THREAD_STACK_SIZE-sizeof(trap_frame)); + memcpy((void*)(child_tf),(void*)tf,sizeof(trap_frame)); + child_tf->x0 = 0; + child_tf->sp_el0 = (unsigned long long)(child_thread->user_stack+THREAD_STACK_SIZE) - (unsigned long long)((unsigned long long)cur_thread->user_stack+THREAD_STACK_SIZE-tf->sp_el0); + + child_thread->cpu_context.sp = (unsigned long long)child_tf; + child_thread->cpu_context.lr = (unsigned long long)(&load_eret); + tf->x0 = child_id; + + enable_interrupt(); + return child_id; +} +void sys_exit(trap_frame* tf) +{ + disable_interrupt(); + get_current()->state = ZOMBIE; + enable_interrupt(); + schedule(); +} +int sys_mbox_call(trap_frame* tf, unsigned char ch, unsigned int *mbox) +{ + disable_interrupt(); + + int res = mailbox_call(mbox,ch); + tf->x0 = res; + return res; + enable_interrupt(); +} +void sys_kill(trap_frame* tf, int pid) +{ + disable_interrupt(); + kill_thread(pid); + enable_interrupt(); +} + +void signal_register(int signal,void (*handler)()) +{ + disable_interrupt(); + if(!(signal<0 || signal>20)) + get_current()->signal_handler[signal]=handler; + enable_interrupt(); +} +void signal_kill(int pid,int signal) +{ + disable_interrupt(); + raise_signal( pid, signal); + enable_interrupt(); +} \ No newline at end of file diff --git a/src/timer.c b/src/timer.c index 0fa74a870..3d9f5543d 100644 --- a/src/timer.c +++ b/src/timer.c @@ -9,7 +9,7 @@ void init_timer(){ // head->value = null; head = nullptr; - disable_timer_interrupt(); + // disable_timer_interrupt(); // writes_uart("Core timer: "); //writehex_uart(*CORE0_TIMER_IRQ_CTRL,1); } @@ -88,7 +88,7 @@ void add_timer(void (*callback)(char* s),char *message,int after){ } } //callback(message); - itr_timer_queue(); + // itr_timer_queue(); return; } diff --git a/user/Makefile b/user/Makefile new file mode 100644 index 000000000..4b4c99913 --- /dev/null +++ b/user/Makefile @@ -0,0 +1,43 @@ +SRCS = $(wildcard src/*.c) +OBJS = $(SRCS:.c=.o) +INCLUDE = -I ./include/ +ASMS = a +LINK = linker +CFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles + +all: clean usr1.img run + +%.o: %.S + aarch64-linux-gnu-gcc $(CFLAGS) $(INCLUDE) -c $(ASMS).S -o $(ASMS).o -g + +%.o: %.c + aarch64-linux-gnu-gcc $(CFLAGS) $(INCLUDE) -c $< -o $@ -g + +usr1.img: $(ASMS).o $(OBJS) + aarch64-linux-gnu-ld -nostdlib -nostartfiles $(ASMS).o $(OBJS) -T $(LINK).ld -o usr1.elf + aarch64-linux-gnu-objcopy -O binary usr1.elf usr1.img + +clean: + rm usr1.elf usr1.img src/*.o *.o>/dev/null 2>/dev/null || true + +run: + qemu-system-aarch64 -M raspi3 -kernel usr1.img --display none -serial null -serial stdio -s -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + + +flash: + sudo dd if=usr1.img of=/dev/sdb + +screen: + sudo screen /dev/ttyUSB0 115200 + +ptty: + qemu-system-aarch64 -M raspi3 -kernel usr1.img -s -display none -serial null -serial pty -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + +boot: + python3 uart_boot.py +screenb: + sudo screen /dev/pts/4 115200 +cpio: + cd rootfs + find . | cpio -o -H newc > ../initramfs.cpio + cd .. \ No newline at end of file diff --git a/user/a.S b/user/a.S new file mode 100644 index 000000000..628c966da --- /dev/null +++ b/user/a.S @@ -0,0 +1,54 @@ +.section ".text" +.global _start +_start: + bl main + +.global get_pid +get_pid: + mov x8,0 + svc #0 + ret + +.global uart_read +uart_read: + mov x8,1 + svc #0 + ret + +.global uart_write +uart_write: + mov x8,2 + svc #0 + ret + +.global exec +exec: + mov x8,3 + svc #0 + ret + +.global fork +fork: + mov x8,4 + svc #0 + ret + +.global exit +exit: + mov x8,5 + svc #0 + ret + +.global mbox_call +mbox_call: + mov x8,6 + svc #0 + ret + +.global kill +kill: + mov x8,7 + svc #0 + ret + +// b exit diff --git a/user/bcm2710-rpi-3-b-plus.dtb b/user/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 000000000..3934b3a26 Binary files /dev/null and b/user/bcm2710-rpi-3-b-plus.dtb differ diff --git a/user/include/allocator.h b/user/include/allocator.h new file mode 100644 index 000000000..1d4835b53 --- /dev/null +++ b/user/include/allocator.h @@ -0,0 +1,62 @@ +// #include "list.h" +#ifndef __ALLCATOR_H +#define __ALLCATOR_H + +#define ALLOCATOR_BASE 0x00000000 +#define ALLOCATOR_START ALLOCATOR_BASE +#define ALLOCATOR_END ALLOCATOR_BASE+ 0x3C000000 +#define BLOCK_SIZE 0x1000 +#define MAX_CONTIBLOCK_SIZE 12 + +typedef struct _frame_node +{ + int _block_exponent; + int _index; + struct _frame_node* next; + struct _frame_node* prev; + //struct list_head list; +}_frame_node; +//_frame_node* frame_freelist[MAX_CONTIBLOCK_SIZE+1]; +enum _frame_status{ + _R=-1, + _F=-2, + _X=-3 +}; +#define FRAME_ARRAY_SIZE (ALLOCATOR_END-ALLOCATOR_START)/BLOCK_SIZE +//int frame_array[FRAME_ARRAY_SIZE]; +void init_frame_freelist(); +void* get_freeframe_addr(unsigned int); +_frame_node* create_frame_node(int idx,int exp,_frame_node* next,_frame_node* prev); +void frame_list_addtail(int i,_frame_node *element); +void free(void* frame_addr); +int find_buddy(int,int); +void merge_buddy(); +void _F_frame_array(int idx, int exp); +void _X_frame_array(int idx, int exp); + + +typedef struct _frame_chunk_node +{ + void* addr; + struct _frame_chunk_node* next; + +}_frame_chunk_node; + +typedef struct _frame_array_node +{ + int size; + struct _frame_node* node; +}_frame_array_node; + +void* my_malloc(unsigned int); +void* get_freechunk_addr(int size); +void chunkNode_append(void* addr); +int getBestChunkSize(int require_size); +unsigned int frameAddrToIdx(void* frame_addr); +void list_freeChunkNode(); +void list_freeFrameNode(); +void memory_reserve(unsigned long long start, unsigned long long end); +void init_memory(); +void pop_frame(int idx); + +#endif diff --git a/user/include/cpio.h b/user/include/cpio.h new file mode 100644 index 000000000..faa71bb04 --- /dev/null +++ b/user/include/cpio.h @@ -0,0 +1,13 @@ +#ifndef _CPIO_HEADER_ +#define _CPIO_HEADER_ +#include "utils.h" +#include "dtb.h" +extern uint32_t* cpio_addr; +void cpio_ls(); +void cpio_cat(); +void cpio_get_addr(char* filedata,unsigned long* filesize); +//void* initramfs_callback(fdt_prop* prop,char * name,uint32_t len_prop); +void* initramfs_start_callback(fdt_prop* prop,char * name,uint32_t len_prop); +void* initramfs_end_callback(fdt_prop* prop,char * name,uint32_t len_prop); + +#endif \ No newline at end of file diff --git a/user/include/dtb.h b/user/include/dtb.h new file mode 100644 index 000000000..b3531056f --- /dev/null +++ b/user/include/dtb.h @@ -0,0 +1,39 @@ +#ifndef _DTB_HEADER +#define _DTB_HEADER + +#include "utils.h" +void* fdt_traverse(void* (*f)()); + +#define FDT_HEADER_MAGIC 0xd00dfeed + +#define FDT_BEGIN_NODE (0x00000001) +#define FDT_END_NODE (0x00000002) +#define FDT_PROPERTY (0x00000003) +#define FDT_NOP (0x00000004) +#define FDT_END (0x00000009) + + + +typedef struct fdt_header { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +}fdt_header; +typedef struct fdt_reserve_entry{ + uint64_t address; + uint64_t size; +}fdt_reserve_entry; +typedef struct fdt_prop +{ + uint32_t len; + uint32_t nameoff; +}fdt_prop; + +#endif \ No newline at end of file diff --git a/user/include/exception.h b/user/include/exception.h new file mode 100644 index 000000000..1c241eb88 --- /dev/null +++ b/user/include/exception.h @@ -0,0 +1,16 @@ +#define GPU_INTERRUPTS_ROUTING ((volatile uint32_t *)(0x4000000C)) +#define core0_interrupt_source ((volatile unsigned int*)(0x40000060)) + +#define INTERRUPT_PRIVILEGE_TIMER 1 +#define INTERRUPT_PRIVILEGE_READ 2 +#define INTERRUPT_PRIVILEGE_WRITE 3 + +void enable_interrupt(); +void disable_interrupt(); +void exception_entry(); +void irq_entry(); +void GPU_interrupt_handler(); +void Timer_interrupt_handler(); +void rx_interrupt_handler(); +void tx_interrupt_handler(); + diff --git a/user/include/list.h b/user/include/list.h new file mode 100644 index 000000000..d81475f9c --- /dev/null +++ b/user/include/list.h @@ -0,0 +1,45 @@ +#ifndef __TOOLS_LINUX_LIST_H +#define __TOOLS_LINUX_LIST_H +struct list_head { + struct list_head *next, *prev; +}; +#define WRITE_ONCE(var, val) \ + (*((volatile typeof(val) *)(&(var))) = (val)) +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + WRITE_ONCE(list->next, list); + list->prev = list; +} +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} +static inline void list_add(struct list_head *new, struct list_head *head){ + __list_add(new, head, head->next); +} + +static inline void list_add_tail(struct list_head *new, struct list_head *head){ + __list_add(new, head->prev, head); +} + +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + // in include/linux/kernel.h + +/** +* container_of – cast a member of a structure out to the containing structure +* @ptr: the pointer to the member. +* @type: the type of the container struct this is embedded in. +* @member: the name of the member within the struct. +* +*/ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr – offsetof(type,member) );}) + +#endif \ No newline at end of file diff --git a/user/include/mailbox.h b/user/include/mailbox.h new file mode 100644 index 000000000..bcac0f93b --- /dev/null +++ b/user/include/mailbox.h @@ -0,0 +1,16 @@ +#include "mini_uart.h" + +/* channels */ +#define MBOX_CH_POWER 0 +#define MBOX_CH_FB 1 +#define MBOX_CH_VUART 2 +#define MBOX_CH_VCHIQ 3 +#define MBOX_CH_LEDS 4 +#define MBOX_CH_BTNS 5 +#define MBOX_CH_TOUCH 6 +#define MBOX_CH_COUNT 7 +#define MBOX_CH_PROP 8 + +void get_board_revision(); +void get_ARM_memory(); +int mailbox_call(volatile unsigned int*,unsigned char); diff --git a/user/include/mini_uart.h b/user/include/mini_uart.h new file mode 100644 index 000000000..90f6cb7c6 --- /dev/null +++ b/user/include/mini_uart.h @@ -0,0 +1,75 @@ +#include "utils.h" +#define MMIO_BASE 0x3F000000 + +#define AUXENB ((volatile unsigned int*)(MMIO_BASE+0x00215004)) +#define AUX_MU_IO_REG ((volatile unsigned int*)(MMIO_BASE+0x00215040)) +#define AUX_MU_IER_REG ((volatile unsigned int*)(MMIO_BASE+0x00215044)) +#define AUX_MU_IIR_REG ((volatile unsigned int*)(MMIO_BASE+0x00215048)) +#define AUX_MU_LCR_REG ((volatile unsigned int*)(MMIO_BASE+0x0021504C)) +#define AUX_MU_MCR_REG ((volatile unsigned int*)(MMIO_BASE+0x00215050)) +#define AUX_MU_LSR_REG ((volatile unsigned int*)(MMIO_BASE+0x00215054)) +#define AUX_MU_MSR_REG ((volatile unsigned int*)(MMIO_BASE+0x00215058)) +#define AUX_MU_SCRATCH_REG ((volatile unsigned int*)(MMIO_BASE+0x0021505C)) +#define AUX_MU_CNTL_REG ((volatile unsigned int*)(MMIO_BASE+0x00215060)) +#define AUX_MU_STAT_REG ((volatile unsigned int*)(MMIO_BASE+0x00215064)) +#define AUX_MU_BAUD_REG ((volatile unsigned int*)(MMIO_BASE+0x00215068)) +void init_uart(); +char read_uart(); +int read_int(); +void writec_uart(unsigned int s); +void writes_uart(char *s); +void writes_n_uart(char *s, unsigned int size); +void writes_nl_uart(char *s); +void writehex_uart(unsigned int h,int newline); +void write_int_uart(unsigned int,bool newline); +void busy_wait_writehex(unsigned long long h,bool newline); +//void writeaddr_uart(unsigned int*); +#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000)) +#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004)) +#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008)) +#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C)) +#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010)) +#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014)) +#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C)) +#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020)) +#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028)) +#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034)) +#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038)) +#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040)) +#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044)) +#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064)) +#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068)) +#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094)) +#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098)) +#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C)) + +#define IRQ_ENABLE1 ((volatile unsigned *)(0x3F00B210)) +char uart_buf_read[1024]; +char uart_buf_write[1024]; +int uart_read_i_l; +int uart_read_i_r; +int uart_write_i_l; +int uart_write_i_r; +void init_uart_buf(); +void uart_buf_read_push(char c); +void uart_buf_write_push(char c); +void uart_buf_writes_push(char *s); +char uart_buf_read_pop(); +char uart_buf_write_pop(); +void busy_wait_writes(char *s,bool newline); +void busy_wait_writec(char s); +void busy_wait_writeint(int i,bool newline); +int is_empty_write(); +int is_empty_read(); + +#ifdef __DEBUG_LOG + static inline void writes_uart_debug(char* s, bool newline){ + while(*s){ + if(*s=='\n') + writec_uart('\r'); + writec_uart(*s++); + } + if(newline) + writes_uart("\r\n"); + } +#endif \ No newline at end of file diff --git a/user/include/reboot.h b/user/include/reboot.h new file mode 100644 index 000000000..59eb24fbf --- /dev/null +++ b/user/include/reboot.h @@ -0,0 +1,3 @@ +void set(long addr, unsigned int value); +void reset(int tick); +void cancel_reset(); \ No newline at end of file diff --git a/user/include/shell.h b/user/include/shell.h new file mode 100644 index 000000000..7a25b85b5 --- /dev/null +++ b/user/include/shell.h @@ -0,0 +1,29 @@ +#include "mini_uart.h" +enum Action{ + help, + hello, + revision, + memory, + reboot, + ccreboot, + bootload, + version, + ls, + cat, + prog, + timeout, + mmalloc, + mfree, + mlistc, + mlistf, + mtest, + unknown +}; + +void read_command(); +void read_string(char**); +void handle_command(enum Action action, char *buffer); +int match_command(char *buffer); +int get_para_num(char* s); +char* get_para_by_num(int num,char *buffer); +void read_uart_buf(); \ No newline at end of file diff --git a/user/include/stdlib.h b/user/include/stdlib.h new file mode 100644 index 000000000..aed4fc27a --- /dev/null +++ b/user/include/stdlib.h @@ -0,0 +1,8 @@ +#ifndef __STDLIB_H +#define __STDLIB_H + +#include "utils.h" +void* simple_malloc(size_t size); + +void* get_smalloc_end(); +#endif \ No newline at end of file diff --git a/user/include/string.h b/user/include/string.h new file mode 100644 index 000000000..4ab34b4e0 --- /dev/null +++ b/user/include/string.h @@ -0,0 +1,5 @@ +#include "mini_uart.h" +int strcmp (const char *p1, const char *p2); +int strncmp(const char *s1, const char *s2, unsigned int n); +int strlen(char *s); +unsigned int str2int(char *s); \ No newline at end of file diff --git a/user/include/task.h b/user/include/task.h new file mode 100644 index 000000000..630ac14e3 --- /dev/null +++ b/user/include/task.h @@ -0,0 +1,16 @@ +#include "utils.h" +#include "mini_uart.h" +#include "stdlib.h" +struct taskq +{ + struct taskq *next; + void (*handler)(); + int privilege; +}; +typedef struct taskq taskq; +taskq *taskq_head; + +void init_taskq(); +void add_task(void (*handler)(),int privilege); +bool is_taskq_empty(); +void do_task(int* last_privilege); \ No newline at end of file diff --git a/user/include/timer.h b/user/include/timer.h new file mode 100644 index 000000000..a6cac5890 --- /dev/null +++ b/user/include/timer.h @@ -0,0 +1,22 @@ +#include "utils.h" +struct timer +{ + struct timer *next; + void (*callback)(char* s); + char *message; + unsigned int value; +}; +typedef struct timer timer; +timer *head; + +void init_timer(); +void add_timer(void (*callback)(char* s),char *message,int after); +bool timer_is_empty(); +void itr_timer_queue(); +void disable_timer_interrupt(); +void enable_timer_interrupt(); +bool is_timerq_empty(); +void set_expired_time(int ); +void get_current_time(unsigned long long *time_count,unsigned long long *time_freq); +timer* to_next_timer(); +timer* get_head_timer(); \ No newline at end of file diff --git a/user/include/usr_syscall.h b/user/include/usr_syscall.h new file mode 100644 index 000000000..ebf780eae --- /dev/null +++ b/user/include/usr_syscall.h @@ -0,0 +1,8 @@ +extern int getpid(); +extern unsigned int uart_read(char buf[],unsigned int size); +extern unsigned int uart_write(const char* name,unsigned int size); +extern int exec(const char* name, char *const argv[]); +extern int fork(); +extern void exit(); +extern int mbox_call(unsigned char ch, unsigned int *mbox); +extern void kill(int pid); \ No newline at end of file diff --git a/user/include/utils.h b/user/include/utils.h new file mode 100644 index 000000000..be320f56d --- /dev/null +++ b/user/include/utils.h @@ -0,0 +1,58 @@ +#ifndef __UTILS_H_ +#define __UTILS_H_ +#ifndef uint32_t + #define uint32_t unsigned int +#endif +#ifndef size_t + #define size_t unsigned long +#endif +#ifndef uint64_t + #define uint64_t unsigned long long +#endif + +#define TRUE (1==1) +#define FALSE (!TRUE) +#define null 0 +#define nullptr ((void *)0) +typedef int bool; + + + +uint32_t big2little(uint32_t); +unsigned long align_up(unsigned long n, unsigned long align); +/* Function to calculate x raised to the power y in O(logn)*/ +static inline int power(int x, unsigned int y) +{ + int temp; + if( y == 0) + return 1; + temp = power(x, y/2); + if (y%2 == 0) + return temp*temp; + else + return x*temp*temp; +} +static inline unsigned int findPreviousPowerOf2(unsigned int n) +{ + unsigned int x=n; + // do till only one bit is left + while (x & (x - 1)) { + + //writehex_uart(x&(x-1)); + x = x & (x - 1); // unset rightmost bit + } + + // `n` is now a power of two (less than or equal to `n`) + return x; +} +static inline unsigned int powOf2ToExponent(int n){ + int num = n; + int exp = -1; + while(num>0){ + num = num >> 1; + ++ exp; + } + return exp; +} + +#endif \ No newline at end of file diff --git a/user/initramfs.cpio b/user/initramfs.cpio new file mode 100644 index 000000000..8f5c6ab59 Binary files /dev/null and b/user/initramfs.cpio differ diff --git a/user/linker.ld b/user/linker.ld new file mode 100644 index 000000000..301372b6c --- /dev/null +++ b/user/linker.ld @@ -0,0 +1,19 @@ +SECTIONS +{ + . = 0x80000; + .text : { *(.text) } + + .rodata : { *(.rodata) } + .data : { *(.data) } + . = ALIGN(8); + bss_begin = .; + .bss : { *(.bss*) } + bss_end = .; + _end = .; + + _head_start_brk = .; + +} + +_boot_size = _end - _start; +_head_start_brk = _head_start_brk + 0x00100; \ No newline at end of file diff --git a/user/src/allocator.c b/user/src/allocator.c new file mode 100644 index 000000000..47fc172b5 --- /dev/null +++ b/user/src/allocator.c @@ -0,0 +1,469 @@ +#include "allocator.h" +#include "stdlib.h" +#include "mini_uart.h" +#include "cpio.h" +#ifndef __DEBUG_LOG +#define __DEBUG_LOG +#endif +int chunk_size_arr[] = { + // 0x1, //2^0 + // 0x2, //2^1 + 0x4, //2^2 + 0x8, //2^3 + 0x10, //2^4 + 0x20, //2^5 + 0x40, //2^6 + 0x80, //2^7 + 0x100, //2^8 + 0x200, //2^9 + 0x400, //2^10 + 0x800 //2^11 + }; +int chunk_arr_len = 10; +_frame_node* frame_freelist[MAX_CONTIBLOCK_SIZE+1]; +_frame_chunk_node* chunk_freelist[10]; + +// int frame_array[FRAME_ARRAY_SIZE] = {_F}; +_frame_array_node** frame_array;//[FRAME_ARRAY_SIZE]; +void init_frame_freelist(){ + for (int i = 0; i <= MAX_CONTIBLOCK_SIZE; i++) + { + frame_freelist[i]=nullptr; + } + // _F_frame_array(0,MAX_CONTIBLOCK_SIZE); + // frame_freelist[MAX_CONTIBLOCK_SIZE] = simple_malloc(sizeof(struct _frame_node)); + // frame_freelist[MAX_CONTIBLOCK_SIZE]->next = nullptr; + // frame_freelist[MAX_CONTIBLOCK_SIZE]->_block_exponent = MAX_CONTIBLOCK_SIZE; + // frame_freelist[MAX_CONTIBLOCK_SIZE]->_index = 0; + + for (int i = 0; i < chunk_arr_len; i++) + { + chunk_freelist[i] = nullptr; + } + + +} +void frame_list_addtail(int i,_frame_node *element){ + _frame_node* node = frame_freelist[i]; + if(node==nullptr){ + frame_freelist[i]=element; + } + else{ + while(node->next!=nullptr){ + node = node->next; + } + node->next = element; + element->prev=node; + } +} +void frame_list_addhead(int i,_frame_node *element){ + _frame_node* node = frame_freelist[i]; + if(node==nullptr){ + element->next=nullptr; + element->prev=nullptr; + frame_freelist[i]=element; + } + else{ + node->prev = element; + element->next = node; + element->prev = nullptr; + frame_freelist[i] = element; + } +} +_frame_node* create_frame_node(int idx,int exp,_frame_node* next,_frame_node* prev){ + _frame_node* new_node = simple_malloc(sizeof(_frame_node)); + new_node->next = next; + new_node->prev = prev; + new_node->_block_exponent = exp; + new_node->_index=idx; + frame_array[idx]->node = new_node; + return new_node; +} + +void _F_frame_array(int idx, int exp){ + frame_array[idx]->size = power(2,exp)*BLOCK_SIZE; + frame_array[idx]->node->_block_exponent = exp; + frame_array[idx]->node->_index=idx; + for (int i = idx + 1; i < idx+power(2,exp); i++) + { + frame_array[i]->size = _F; + } + +} + +void _X_frame_array(int idx, int exp){ + frame_array[idx]->size = -power(2,exp)*BLOCK_SIZE; + for (int i = idx+1; i < idx + power(2,exp); i++) + { + frame_array[i]->size = _X; + } +} + +void* get_freeframe_addr(unsigned int size){ + int i; + for (i = 0; i <= MAX_CONTIBLOCK_SIZE; i++) + { + if(frame_freelist[i]!=nullptr && BLOCK_SIZE*power(2,i)>=size){ + // writes_uart("Require "); + // write_int_uart(size,FALSE); + // writes_uart(" ,Min free block size: "); + // write_int_uart(BLOCK_SIZE *power(2,i),TRUE); + break; + } + } + if(frame_freelist[i]==nullptr) + { + // writes_uart("ALL FULL\r\n"); + return nullptr; + } + _frame_node* node; + while(BLOCK_SIZE*power(2,i)/2>=size && i>0){ + node = frame_freelist[i]; + // writes_uart("From "); + // write_int_uart(node->_index,FALSE); + // writes_uart(" - "); + // write_int_uart(node->_index+frame_array[node->_index]->size/BLOCK_SIZE-1,FALSE); + pop_frame(node->_index); + //frame_freelist[i] = frame_freelist[i]->next; + + i-=1; + + //_frame_node* new_node1 = create_frame_node(node->_index,i,nullptr,nullptr); + _frame_node* new_node1 = frame_array[node->_index]->node; + _F_frame_array(new_node1->_index,i); + frame_list_addtail(i,new_node1); + _frame_node* new_node2 = frame_array[node->_index+power(2,i)]->node; + //_frame_node* new_node2 = create_frame_node(node->_index+power(2,i),i,nullptr,nullptr); + _F_frame_array(new_node2->_index,i); + frame_list_addtail(i,new_node2); + + // writes_uart(" To "); + // write_int_uart(new_node1->_index,FALSE); + // writes_uart(" - "); + // write_int_uart(new_node1->_index+frame_array[new_node1->_index]->size/BLOCK_SIZE-1,FALSE); + // writes_uart(" And "); + // write_int_uart(new_node2->_index,FALSE); + // writes_uart(" - "); + // write_int_uart(new_node2->_index+frame_array[new_node2->_index]->size/BLOCK_SIZE-1,TRUE); + + } + node = frame_freelist[i]; + pop_frame(node->_index); + _X_frame_array(node->_index,node->_block_exponent); + + + // frame_freelist[i] = frame_freelist[i]->next; + + // writes_uart("Got block size: "); + // write_int_uart(-frame_array[node->_index]->size,TRUE); + unsigned long long freeframe_addr = ALLOCATOR_START + node->_index*BLOCK_SIZE; + return (void*)freeframe_addr; + +} + + +void pop_frame(int idx){ + int exp = powOf2ToExponent(frame_array[idx]->size / BLOCK_SIZE); + _frame_node* node = frame_array[idx]->node; + _frame_node** head = &frame_freelist[exp]; + if(*head==nullptr || node==nullptr) return; + + if(*head==node) *head = node->next; + if(node->next!=nullptr) node->next->prev = node->prev; + if(node->prev!=nullptr) node->prev->next = node->next; + + node->next=nullptr; + node->prev=nullptr; + + return; + + // if(node != nullptr){ + // if(node->prev!=nullptr){ + // node->prev->next = node->next; + // if(node->next != nullptr){ + // node->next->prev = node->prev; + // } + // } + // else{ + // if(frame_freelist[exp]->next!=nullptr){ + // frame_freelist[exp]->next->prev = nullptr; + // } + // frame_freelist[exp] = frame_freelist[exp]->next; + // } + // node->next=nullptr; + // node->prev=nullptr; + // } + +} +int find_buddy(int frame_idx, int frame_exp){ + // if(frame_exp==MAX_CONTIBLOCK_SIZE) + // return frame_idx; + int buddy_frame_idx = frame_idx^(power(2,frame_exp)); + return buddy_frame_idx; +} +void merge_buddy(int frame_idx, int buddy_idx){ + if( frame_idx == buddy_idx || + frame_array[frame_idx]->size != frame_array[buddy_idx]->size || + frame_array[frame_idx]->sizesizesize>= BLOCK_SIZE* power(2,MAX_CONTIBLOCK_SIZE) || + frame_array[buddy_idx]->size>= BLOCK_SIZE* power(2,MAX_CONTIBLOCK_SIZE)) + { + + // busy_wait_writes("Can't merge",TRUE); + // writes_uart("[*] No buddy can be merged. \r\n"); + // if( frame_array[frame_idx]->size >=BLOCK_SIZE && + // frame_array[frame_idx]->size <=power(2,MAX_CONTIBLOCK_SIZE)){ + + // int exp = powOf2ToExponent(frame_array[frame_idx]->size/BLOCK_SIZE); + // frame_array[frame_idx]->node->_block_exponent = exp; + // frame_array[frame_idx]->node->_index = frame_idx; + // frame_list_addhead(exp,frame_array[frame_idx]->node); + // } + + return; + } + else{ + int smaller_idx_frame = (frame_idx < buddy_idx)?frame_idx : buddy_idx; + int larger_idx_frame = (smaller_idx_frame == frame_idx)?buddy_idx : frame_idx; + // writes_uart("From "); + // write_int_uart(smaller_idx_frame,FALSE); + // writes_uart(" - "); + // write_int_uart(smaller_idx_frame+frame_array[smaller_idx_frame]->size/BLOCK_SIZE-1,FALSE); + // writes_uart(" And "); + // write_int_uart(larger_idx_frame,FALSE); + // writes_uart(" - "); + // write_int_uart(larger_idx_frame+frame_array[larger_idx_frame]->size/BLOCK_SIZE-1,FALSE); + + frame_array[smaller_idx_frame]->size+=frame_array[larger_idx_frame]->size; + frame_array[smaller_idx_frame]->node->_block_exponent+=1; + + pop_frame(larger_idx_frame); + frame_array[larger_idx_frame]->size = _F; + // _F_frame_array(larger_idx_frame,frame_array[larger_idx_frame]->node->_block_exponent); + + + // writes_uart(" To "); + // write_int_uart(smaller_idx_frame,FALSE); + // writes_uart(" - "); + // write_int_uart(smaller_idx_frame+frame_array[smaller_idx_frame]->size/BLOCK_SIZE-1,TRUE); + int new_buddy_idx = find_buddy(smaller_idx_frame,powOf2ToExponent(frame_array[smaller_idx_frame]->size/BLOCK_SIZE)); + // writes_uart("[*] merging "); + // write_int_uart(smaller_idx_frame,FALSE); + // writes_uart(" and "); + // write_int_uart(new_buddy_idx,TRUE); + merge_buddy(smaller_idx_frame,new_buddy_idx); + + } +} +void free(void* frame_addr){ + + int frame_idx = frameAddrToIdx(frame_addr);//(frame_addr-ALLOCATOR_START)/BLOCK_SIZE; + if(frame_array[frame_idx]->size>_X) + return; + else if( -frame_array[frame_idx]->size <= chunk_size_arr[chunk_arr_len-1]){ + chunkNode_append(frame_addr); + } + else{ + int frame_exp = powOf2ToExponent((-frame_array[frame_idx]->size)/BLOCK_SIZE); + // write_int_uart(frame_idx,TRUE); + // write_int_uart(frame_exp,TRUE); + _F_frame_array(frame_idx,frame_exp); + // write_int_uart(frame_idx,TRUE); + // write_int_uart(frame_exp,TRUE); + int buddy_frame_idx = find_buddy(frame_idx,frame_exp); + // write_int_uart(frame_idx,TRUE); + // write_int_uart(buddy_frame_idx,TRUE); + + merge_buddy(frame_idx,buddy_frame_idx); + frame_idx = (frame_idx > 0)?frame_idx : buddy_frame_idx; + //busy_wait_writeint(frame_array[buddy_frame_idx]->size,TRUE); + // while(frame_array[frame_idx]->size==_F) + // frame_idx--; + frame_exp = frame_array[frame_idx]->node->_block_exponent;//powOf2ToExponent(frame_array[frame_idx]->size/BLOCK_SIZE); + + // _frame_node* new_node = frame_array[frame_idx]->node; //create_frame_node(frame_idx,frame_exp,nullptr,nullptr); + // new_node->_index = frame_idx; + // new_node->_block_exponent = frame_exp; + // busy_wait_writeint(frame_idx,FALSE); + // busy_wait_writes(" ",FALSE); + + frame_list_addhead(frame_exp,frame_array[frame_idx]->node); + //list_freeFrameNode(); + } + +} + +unsigned int frameAddrToIdx(void* frame_addr){ + if(frame_addr < ALLOCATOR_START) + { + // writes_uart("Address not in the range of frame array\r\n"); + return null; + } + + return (unsigned int)((unsigned long long)frame_addr-ALLOCATOR_START)/BLOCK_SIZE; +} + +int getBestChunkSize(int require_size){ + for (int i = 0 ; i size; + int chunk_exp = powOf2ToExponent(chunk_size); + // _frame_chunk_node** headChunkNode = &chunk_freelist[chunk_exp-2]; + _frame_chunk_node* newChunkNode = simple_malloc(sizeof(_frame_chunk_node)); + newChunkNode->addr = addr; + newChunkNode->next = chunk_freelist[chunk_exp-2]; + chunk_freelist[chunk_exp-2] = newChunkNode; + // while(*headChunkNode) + // headChunkNode = &((*headChunkNode)->next); + // *headChunkNode = newChunkNode; +} +void list_freeChunkNode() +{ + for (int i = 0; i < chunk_arr_len; i++) + { + writes_uart("[>] Chunk "); + write_int_uart(chunk_size_arr[i],FALSE); + if(i<10) + writes_uart(" "); + writes_uart(" "); + _frame_chunk_node *node = chunk_freelist[i]; + int count=0; + while(node != nullptr){ + //writes_uart("["); + count++; + // writehex_uart((unsigned long long)node->addr,FALSE); + // writes_uart("]"); + node = node->next; + } + write_int_uart(count,TRUE); + //writes_uart("\r\n"); + } + +} +void list_freeFrameNode() +{ + for (int i = 0; i <= MAX_CONTIBLOCK_SIZE; i++) + { + // writes_uart("[>] Frame "); + // write_int_uart(BLOCK_SIZE*power(2,i),FALSE); + // writes_uart(" "); + busy_wait_writes("[>] Frame ",FALSE); + busy_wait_writeint(BLOCK_SIZE*power(2,i),FALSE); + busy_wait_writes(" ",FALSE); + _frame_node *node = frame_freelist[i]; + int count=0; + while(node != nullptr){ + //writes_uart("["); + count++; + // writehex_uart((unsigned long long)node->addr,FALSE); + // writes_uart("]"); + node = node->next; + } + busy_wait_writeint(count,TRUE); + // write_int_uart(count,TRUE); + } + +} +void* get_freechunk_addr(int size){ + //int chunk_size = getBestChunkSize(size); + int chunk_exp = powOf2ToExponent(size); + if(chunk_freelist[chunk_exp-2]==nullptr){ + // if no free chunk exist, cut a frame into chunks and return first chunk. + void* freeframe_addr = get_freeframe_addr(BLOCK_SIZE); + int frame_idx = frameAddrToIdx(freeframe_addr); + frame_array[frame_idx]->size = -size; + int chunk_count = BLOCK_SIZE / size; + + for (int i = 1; i < chunk_count; i++) + { + // _frame_chunk_node* newChunkNode= simple_malloc(sizeof(_frame_chunk_node)); + // newChunkNode->addr = freeframe_addr + i*size; + chunkNode_append(freeframe_addr + i*size); + // headChunkNode->next = newChunkNode; + // headChunkNode = headChunkNode->next; + } + // headChunkNode->next = nullptr; + return freeframe_addr; + } + else{ + void* chunk_addr = chunk_freelist[chunk_exp-2]->addr; + chunk_freelist[chunk_exp-2] = chunk_freelist[chunk_exp-2]->next; + return chunk_addr; + } + return nullptr; +} + +void* my_malloc(unsigned int size){ + void* malloc_addr = nullptr; + if(size<=chunk_size_arr[chunk_arr_len-1]){ + // writes_uart("Chunk malloc "); + + int chunk_size = getBestChunkSize(size); + // write_int_uart(chunk_size,TRUE); + malloc_addr = get_freechunk_addr(chunk_size); + + // unsigned int chunk_frame_idx = frameAddrToIdx(malloc_addr); + // frame_array[chunk_frame_idx] = chunk_size; + } + else{ + malloc_addr = get_freeframe_addr(size); + } + return malloc_addr; +} + +void memory_reserve(unsigned long long start, unsigned long long end){ + unsigned int start_idx = frameAddrToIdx((void*)start); + unsigned int end_idx = frameAddrToIdx((void*)end); + for (unsigned int i = start_idx; i <= end_idx; i++) + { + frame_array[i]->size = _R; + } + +} +void free_unreserved_memory(){ + for (long long i = FRAME_ARRAY_SIZE-1; i >=0 ; i--) + { + if(frame_array[i]->size!=_R) + { + + frame_array[i]->node = simple_malloc(sizeof(_frame_node)); + frame_array[i]->node->_block_exponent=0; + frame_array[i]->node->_index=i; + frame_array[i]->node->next=nullptr; + frame_array[i]->node->prev=nullptr; + free((void*)(ALLOCATOR_START+BLOCK_SIZE*i)); + } + } +} +void init_memory(){ + // writes_uart("Initializing memory...\r\n"); + init_frame_freelist(); + frame_array = (_frame_array_node**)simple_malloc(FRAME_ARRAY_SIZE*sizeof(_frame_array_node*)); + + for (unsigned int i = 0; i < FRAME_ARRAY_SIZE; i++) + { + frame_array[i] = (_frame_array_node*)simple_malloc(sizeof(_frame_array_node)); + frame_array[i]->size = -BLOCK_SIZE; + // frame_array[i]->node = simple_malloc(sizeof(_frame_node)); + // frame_array[i]->node->_block_exponent=0; + // frame_array[i]->node->_index=i; + // frame_array[i]->node->next=nullptr; + // frame_array[i]->node->prev=nullptr; + } + + memory_reserve(0,0x1000); //Spin tables for multicore boot + memory_reserve(0x80000,(unsigned long long)get_smalloc_end()); + memory_reserve((unsigned long long)fdt_traverse(initramfs_start_callback),(unsigned long long)fdt_traverse(initramfs_end_callback)); + free_unreserved_memory(); + +} \ No newline at end of file diff --git a/user/src/cpio.c b/user/src/cpio.c new file mode 100644 index 000000000..46099c8d4 --- /dev/null +++ b/user/src/cpio.c @@ -0,0 +1,193 @@ +#include "mini_uart.h" +#include "cpio.h" +#include "string.h" +#include "shell.h" +#include "utils.h" +#include "dtb.h" +#define CPIO_HEADER_MAGIC "070701" +#define CPIO_FOOTER_MAGIC "TRAILER!!!" +#define CPIO_ALIGNMENT 4 +uint32_t* cpio_addr; + //((volatile unsigned int*)(0x8000000)) +typedef struct { + char c_magic[6]; /* Magic header '070701'. */ + char c_ino[8]; /* "i-node" number. */ + char c_mode[8]; /* Permisions. */ + char c_uid[8]; /* User ID. */ + char c_gid[8]; /* Group ID. */ + char c_nlink[8]; /* Number of hard links. */ + char c_mtime[8]; /* Modification time. */ + char c_filesize[8]; /* File size. */ + char c_devmajor[8]; /* Major dev number. */ + char c_devminor[8]; /* Minor dev number. */ + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; /* Length of filename in bytes. */ + char c_check[8]; /* Checksum. */ +}cpio_newc_header; + +/* Transform the string type hex to unsigned long. */ +static unsigned long parse_hex_str(char *s, unsigned int max_len) +{ + unsigned long r = 0; + unsigned long i; + + for (i = 0; i < max_len; i++) { + r *= 16; + if (s[i] >= '0' && s[i] <= '9') { + r += s[i] - '0'; + } else if (s[i] >= 'a' && s[i] <= 'f') { + r += s[i] - 'a' + 10; + } else if (s[i] >= 'A' && s[i] <= 'F') { + r += s[i] - 'A' + 10; + } else { + return r; + } + continue; + } + return r; +} + +int cpio_parse_header(cpio_newc_header *archive, + char **filename, unsigned long *_filesize, char **data, + cpio_newc_header **next) +{ + unsigned long file_size; + unsigned long file_namesize; + char *file_data; + /* Ensure magic header exists. */ + if (strncmp(archive->c_magic, CPIO_HEADER_MAGIC, + sizeof(archive->c_magic)) != 0) + return -1; + + /* Get filename and file size. */ + file_size = parse_hex_str(archive->c_filesize, sizeof(archive->c_filesize)); + file_namesize = parse_hex_str(archive->c_namesize, sizeof(archive->c_namesize)); + + /* filename is in after header. */ + *filename = ((char *)archive) + sizeof(cpio_newc_header); + + /* Ensure filename is not the trailer indicating EOF. */ + if (strncmp(*filename, CPIO_FOOTER_MAGIC, sizeof(CPIO_FOOTER_MAGIC)) == 0) + return 1; + + file_data = (char *)align_up(((unsigned long)archive) + + sizeof(cpio_newc_header) + file_namesize, CPIO_ALIGNMENT); + *next = (cpio_newc_header *)align_up(((unsigned long)file_data) + file_size, CPIO_ALIGNMENT); + *data = file_data; + *_filesize = file_size; + return 0; +} +void cpio_ls(){ + //writehex_uart(cpio_addr); + cpio_newc_header* cnh = (cpio_newc_header*)cpio_addr; + cpio_newc_header* next_header; + char *filename; + char *filedata; + unsigned long filesize; + + while(1){ + if(cpio_parse_header(cnh,&filename,&filesize,&filedata,&next_header)!=0) + break; + writes_n_uart(filename,parse_hex_str(cnh->c_namesize,sizeof(cnh->c_namesize))); + writes_uart("\r\n"); + //writes_n_uart(filedata,parse_hex_str(cnh->c_filesize,sizeof(cnh->c_filesize))); + //writes_uart("\r\n"); + cnh = next_header; + + } + +} + +void cpio_cat(){ + cpio_newc_header* cnh = (cpio_newc_header*)cpio_addr; + cpio_newc_header* next_header; + char *filename; + char *filedata; + unsigned long filesize; + writes_uart("Filename: "); + char* read_name; + read_string(&read_name); + + while(1){ + int parse_result = cpio_parse_header(cnh,&filename,&filesize,&filedata,&next_header); + if(parse_result!=0){ + writes_uart("[!] File not found!\r\n"); + break; + } + if(strncmp(read_name,".",strlen(read_name))==0){ + writes_uart("[!] .: Is a directory\r\n"); + break; + } + else if(strncmp(read_name,filename,strlen(read_name))==0){ + writes_n_uart(filedata,parse_hex_str(cnh->c_filesize,sizeof(cnh->c_filesize))); + writes_uart("\r\n"); + break; + } + //writes_n_uart(filename,parse_hex_str(cnh->c_namesize,sizeof(cnh->c_namesize))); + //writes_uart("\r\n"); + // writes_n_uart(filedata,parse_hex_str(cnh->c_filesize,sizeof(cnh->c_filesize))); + // writes_uart("\r\n"); + cnh = next_header; + } +} + +void cpio_get_addr(char* filedata,unsigned long* filesize){ + cpio_newc_header* cnh = (cpio_newc_header*)cpio_addr; + cpio_newc_header* next_header; + char *filename; + // char *filedata; + // unsigned long filesize; + writes_uart("Filename: "); + char* read_name; + read_string(&read_name); + + while(1){ + if(cpio_parse_header(cnh,&filename,filesize,&filedata,&next_header)!=0){ + writes_uart("File not found!\r\n"); + *filesize=0; + break; + } + if(strncmp(read_name,".",strlen(read_name))==0){ + writes_uart(".: Is a directory\r\n"); + *filesize=0; + break; + } + else if(strncmp(read_name,filename,strlen(read_name))==0){ + // writes_n_uart(filedata,parse_hex_str(cnh->c_filesize,sizeof(cnh->c_filesize))); + // writes_uart("\r\n"); + // return (unsigned long long)filedata; + break; + } + //writes_n_uart(filename,parse_hex_str(cnh->c_namesize,sizeof(cnh->c_namesize))); + //writes_uart("\r\n"); + // writes_n_uart(filedata,parse_hex_str(cnh->c_filesize,sizeof(cnh->c_filesize))); + // writes_uart("\r\n"); + cnh = next_header; + } + // return 0; +} + +void* initramfs_start_callback(fdt_prop* prop,char * name,uint32_t len_prop){ + if(strncmp(name,"linux,initrd-start",18)==0){ // start address of initrd + writes_uart("Found target: \""); + writes_n_uart(name,18); + writes_uart("\" at target_cpio_addraddress "); + cpio_addr = (unsigned int*)((unsigned long)big2little(*((uint32_t*)(prop+1)))); + writehex_uart((unsigned long)cpio_addr,TRUE); + return (void*)cpio_addr; + } + return nullptr; +} +void* initramfs_end_callback(fdt_prop* prop,char * name,uint32_t len_prop){ + if(strncmp(name,"linux,initrd-end",16)==0) + { + writes_uart("Found target: \""); + writes_n_uart(name,18); + writes_uart("\" at address "); + void* target_cpio_addr = (void*)((unsigned long)big2little(*((uint32_t*)(prop+1)))); + writehex_uart((unsigned long)target_cpio_addr,TRUE); + return (void*)target_cpio_addr; + } + return nullptr; +} \ No newline at end of file diff --git a/user/src/dtb.c b/user/src/dtb.c new file mode 100644 index 000000000..c3f770ce6 --- /dev/null +++ b/user/src/dtb.c @@ -0,0 +1,78 @@ +#include "dtb.h" +#include "mini_uart.h" +#include "utils.h" +#include "string.h" +#include "cpio.h" + +void* fdt_traverse(void* (*f)()){ + register unsigned long dtb_reg asm ("x15"); + // writes_uart("Loaded dtb address: "); + // writehex_uart(dtb_reg,1); + fdt_header* header = (fdt_header*)dtb_reg; + + if(big2little(header->magic) != FDT_HEADER_MAGIC){ + writes_uart("Header magic failed\r\n"); + return nullptr; + } + + uint32_t* struct_start = (uint32_t*)((char*)header+ big2little(header->off_dt_struct)); + //uint32_t* string_start = (uint32_t*)((char*)header+ big2little(header->off_dt_strings)); + fdt_prop* prop; + char *name; + // writehex_uart(struct_start); + // writes_uart("\r\n"); + // writehex_uart(big2little(header->totalsize)); + // writes_uart("\r\n"); + + + while(1){ + + uint32_t tok = big2little(*struct_start); + switch (tok) + { + case FDT_BEGIN_NODE: + //writes_uart("Begin node\r\n"); + + name = (char*)(struct_start+1); + // followed node name + + uint32_t name_size = strlen(name); + + struct_start+=align_up(name_size+1,4)/sizeof(uint32_t); + // name have zero padding, aligned up to multiple of 4. + + break; + case FDT_END_NODE: + // writes_uart("End node\r\n"); + break; + case FDT_PROPERTY: + // // writes_uart("PROP\r\n"); + prop = (fdt_prop*)(struct_start+1); + // // followed property information + + name = ((char*)header+big2little(header->off_dt_strings)+ big2little(prop->nameoff)); + + void* result = f(prop,name,big2little(prop->len)); + if(result != nullptr) + return result; + struct_start+=(sizeof(fdt_prop)+align_up(big2little(prop->len),4))/sizeof(uint32_t); + // add size of property name length and name. + // property name have zero padding, up to multiple of 4. + break; + case FDT_END: + //writes_uart("End\r\n"); + return nullptr; + break; + case FDT_NOP: + //writes_uart("NOP\r\n"); + //struct_start+= 1; + break; + default: + //struct_start+= 1; + //writehex_uart(tok); + break; + } + struct_start+=1; + } + return nullptr; +} \ No newline at end of file diff --git a/user/src/exception.c b/user/src/exception.c new file mode 100644 index 000000000..4b4926754 --- /dev/null +++ b/user/src/exception.c @@ -0,0 +1,175 @@ +#include "mini_uart.h" +#include "exception.h" +#include "string.h" +#include "timer.h" +#include "task.h" + +void enable_interrupt(){ + asm volatile( + "msr DAIFClr, 0xf" + ); +} + +void disable_interrupt(){ + asm volatile( + "msr DAIFSet, 0xf" + ); +} + + +void exception_entry(){ + busy_wait_writes("EXCEPTION ENTRY",TRUE); + // spsr_el1, elr_el1, and esr_el1 + unsigned long long reg_spsr_el1, reg_elr_el1,reg_esr_el1; + asm volatile( + "mrs %0,spsr_el1\n\t" + "mrs %1,elr_el1\n\t" + "mrs %2,esr_el1\n\t" + : "=r" (reg_spsr_el1), + "=r" (reg_elr_el1), + "=r" (reg_esr_el1) + ); + writes_uart("Exception\r\n"); + writes_uart("spsr_el1: "); + writehex_uart(reg_spsr_el1,1); + writes_uart("reg_elr_el1: "); + writehex_uart(reg_elr_el1,1); + writes_uart("reg_esr_el1: "); + writehex_uart(reg_esr_el1,1); + return; +} + +int curr_task_privilege = 100; +void irq_entry(){ + + // writes_uart("IRQ entry\r\n"); + // writes_uart("Interrupt Source:"); + // writehex_uart(*core0_interrupt_source,1); + if(*core0_interrupt_source & (1<<8)){ //GPU interrupt + //*AUX_MU_IER_REG = 0; + // add_task(GPU_interrupt_handler,0); + /* AUX_MU_IIR_REG bits 2:1 + 00 : No interrupts + 01 : Transmit holding register empty + 10 : Receiver holds valid byte + 11 : */ + + if((*AUX_MU_IIR_REG & 0b0010)) //write interrupt + { + // disable_interrupt(); + *AUX_MU_IER_REG &= ~2; //disable write interrupt + add_task(tx_interrupt_handler,INTERRUPT_PRIVILEGE_WRITE); + if(curr_task_privilegecallback(h->message); + // writes_uart("DEBUG:"); + // writes_nl_uart(h->message); + if(h->next==nullptr){ + writes_uart("next timer is not exist.\r\n"); + h = to_next_timer(); + disable_timer_interrupt(); + } + else{ + h = to_next_timer(); + writes_uart("Found next timer in "); + write_int_uart(h->value,TRUE); + unsigned long long time_count=0; + unsigned long long time_freq=0; + get_current_time(&time_count,&time_freq); + set_expired_time(h->value - time_count/time_freq); + enable_timer_interrupt(); + } + } + +} \ No newline at end of file diff --git a/user/src/mailbox.c b/user/src/mailbox.c new file mode 100644 index 000000000..4c0e27891 --- /dev/null +++ b/user/src/mailbox.c @@ -0,0 +1,125 @@ +/* +The mailbox mechanism consists of three components mailbox registers, channels, and messages. +mailbox0: CPU(ARM) read from GPU(VideoCoreIV), +mailbox0 status: check GPU status. +mailbox1: CPU write to GPU. + +Mailbox 0 defines the following channels: + +0: Power management +1: Framebuffer +2: Virtual UART +3: VCHIQ +4: LEDs +5: Buttons +6: Touch screen +7: +8: Property tags (ARM -> VC) +9: Property tags (VC -> ARM) +*/ +#include "mailbox.h" +// mailbox address and flags + +//#define MMIO_BASE 0x3F000000 +#define MAILBOX_BASE MMIO_BASE + 0xb880 +// mailbox0: CPU read from GPU +#define MAILBOX0_RW ((volatile unsigned int*)(MAILBOX_BASE+0x0)) //read write register. +#define MAILBOX0_POLL ((volatile unsigned int*)(MAILBOX_BASE+0x10)) +#define MAILBOX0_SENDER ((volatile unsigned int*)(MAILBOX_BASE+0x14)) +#define MAILBOX0_STATUS ((volatile unsigned int*)(MAILBOX_BASE+0x18)) +#define MAILBOX0_CONFIG ((volatile unsigned int*)(MAILBOX_BASE+0x1C)) +// mailbox1: CPU write to GPU +#define MAILBOX1_RW ((volatile unsigned int*)(MAILBOX_BASE+0x20)) +#define MAILBOX1_POLL ((volatile unsigned int*)(MAILBOX_BASE+0x30)) +#define MAILBOX1_SENDER ((volatile unsigned int*)(MAILBOX_BASE+0x34)) +#define MAILBOX1_STATUS ((volatile unsigned int*)(MAILBOX_BASE+0x38)) +#define MAILBOX1_CONFIG ((volatile unsigned int*)(MAILBOX_BASE+0x3C)) + + +#define MBOX_REQUEST 0 + +#define MAILBOX_RESPONSE 0x80000000 +#define MAILBOX_FULL 0x80000000 +#define MAILBOX_EMPTY 0x40000000 +#define TAG_REQUEST_CODE 0x00000000 +#define GET_BOARD_REVISION 0x00010002 +#define GET_ARM_MEMORY 0x00010005 + +#define END_TAG 0x00000000 + +int mailbox_call(volatile unsigned int* mailbox,unsigned char ch){ + // combine mailbox message address(upper 28 bits) and channel number(4bits). + unsigned int r = (unsigned int)(((unsigned long)mailbox) & (~0xF)) | ch;//(ch & 0xF); + // wait for the mailbox1 not full. + do{asm volatile("nop");}while(*MAILBOX1_STATUS & MAILBOX_FULL); + + // write the message address(28 bits) and channel number (4bits) to mailbox write register. + *MAILBOX1_RW = r; + + while(1) { + // is there any response in mailbox + while(*MAILBOX0_STATUS & MAILBOX_EMPTY){asm volatile("nop");}; + if(r == *MAILBOX0_RW) + { + return mailbox[1]==MAILBOX_RESPONSE; // check if it is the response, if failed: 0x80000001 + } + } + return 0; + +} + +//board revision number: identify what model of pi it is. +void get_board_revision(){ + //unsigned int mailbox[7]; + volatile unsigned int __attribute__((aligned(16))) mailbox[7]; + mailbox[0] = 7 * 4; // buffer size in bytes + mailbox[1] = MBOX_REQUEST; + // tags begin + mailbox[2] = GET_BOARD_REVISION; // tag identifier + mailbox[3] = 4; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + // tags end + mailbox[6] = END_TAG; + + if(mailbox_call(mailbox,MBOX_CH_PROP)) // message passing procedure call, you should implement it following the 6 steps provided above. + { + writes_uart("Get Board revision: "); + writehex_uart(mailbox[5],1); // it should be 0xa020d3 for rpi3 b+ + } + else{ + writes_uart("Get Board revision failed!\r\n"); + } + +} + +/*Get ARM memory +Tag: 0x00010005 +Request: +Length: 0 +Response: +Length: 8 +Value: +u32: base address in bytes +u32: size in bytes +Future formats may specify multiple base+size combinations.*/ + +void get_ARM_memory(){ + volatile unsigned int __attribute__((aligned(16))) mailbox[8]; + mailbox[0] = 8 * 4; // buffer size in bytes + mailbox[1] = MBOX_REQUEST; + // tags begin + mailbox[2] = GET_ARM_MEMORY; // tag identifier + mailbox[3] = 8; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + mailbox[6] = 0; // value buffer + // tags end + mailbox[7] = END_TAG; + + mailbox_call(mailbox,MBOX_CH_PROP); // message passing procedure call, you should implement it following the 6 steps provided above. + writes_uart("Get ARM Memory address: "); + writehex_uart(mailbox[5],1); + writes_uart("Get ARM Memory size: "); + writehex_uart(mailbox[6],1); +} diff --git a/user/src/main.c b/user/src/main.c new file mode 100644 index 000000000..f89962276 --- /dev/null +++ b/user/src/main.c @@ -0,0 +1,88 @@ +#include "mini_uart.h" +extern int get_pid(); +extern unsigned int uart_read(char buf[],unsigned int size); +extern unsigned int uart_write(const char* name,unsigned int size); +extern int exec(const char* name, char *const argv[]); +extern int fork(); +extern void exit(); +extern int mbox_call(unsigned char ch, unsigned int *mbox); +extern void kill(int pid); +void delay(int time) +{ + unsigned long long delay_time = time*0x1000; + while(delay_time>1){ + delay_time--; + } +} +void fork_test(){ + // printf("\nFork Test, pid %d\n", get_pid()); + busy_wait_writes("\nFork Test, pid ",FALSE); + busy_wait_writeint(get_pid(),TRUE); + int cnt = 1; + int ret = 0; + if ((ret = fork())== 0) { // child + long long cur_sp; + + asm volatile("mov %0, sp" : "=r"(cur_sp)); + // printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + busy_wait_writes("first child pid: ",FALSE); + busy_wait_writeint(get_pid(),FALSE); + busy_wait_writes(", cnt: ",FALSE); + busy_wait_writeint(cnt,FALSE); + busy_wait_writes(", ptr: ",FALSE); + busy_wait_writehex((unsigned long long )(&cnt),FALSE); + busy_wait_writes(", sp: ",FALSE); + busy_wait_writehex((unsigned long long)cur_sp,TRUE); + ++cnt; + + if ((ret = fork()) != 0){ + asm volatile("mov %0, sp" : "=r"(cur_sp)); + // printf("first child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + busy_wait_writes("first child pid: ",FALSE); + busy_wait_writeint(get_pid(),FALSE); + busy_wait_writes(", cnt: ",FALSE); + busy_wait_writeint(cnt,FALSE); + busy_wait_writes(", ptr: ",FALSE); + busy_wait_writehex((unsigned long long )(&cnt),FALSE); + busy_wait_writes(", sp: ",FALSE); + busy_wait_writehex((unsigned long long)cur_sp,TRUE); + } + else{ + while (cnt < 5) { + asm volatile("mov %0, sp" : "=r"(cur_sp)); + // printf("second child pid: %d, cnt: %d, ptr: %x, sp : %x\n", get_pid(), cnt, &cnt, cur_sp); + busy_wait_writes("second child pid: ",FALSE); + busy_wait_writeint(get_pid(),FALSE); + busy_wait_writes(", cnt: ",FALSE); + busy_wait_writeint(cnt,FALSE); + busy_wait_writes(", ptr: ",FALSE); + busy_wait_writehex((unsigned long long )(&cnt),FALSE); + busy_wait_writes(", sp: ",FALSE); + busy_wait_writehex((unsigned long long)cur_sp,TRUE); + delay(1000000); + ++cnt; + } + } + exit(); + } + else { + // printf("parent here, pid %d, child %d\n", get_pid(), ret); + busy_wait_writes("parent here, pid ",FALSE); + busy_wait_writeint(get_pid(),FALSE); + busy_wait_writes(", child ",FALSE); + busy_wait_writeint(ret,TRUE); + + } + exit(); + // while(1){asm volatile("nop");} +} +int main(){ + // while(1) + // { + // busy_wait_writes("HI, here is user ",FALSE); + // busy_wait_writeint(get_pid(),TRUE); + // } + fork_test(); + exit(); + return 0; +} \ No newline at end of file diff --git a/user/src/mini_uart.c b/user/src/mini_uart.c new file mode 100644 index 000000000..907b251b0 --- /dev/null +++ b/user/src/mini_uart.c @@ -0,0 +1,333 @@ +#include "mini_uart.h" +#include "stdlib.h" +#include "exception.h" +#include "string.h" +void init_uart(){ + *AUXENB |=1; // enable mini UART, then mini uart register can be accessed. + *AUX_MU_CNTL_REG = 0; // Disable transmitter and receiver during configuration. + *AUX_MU_IER_REG = 0; // 0: Disable interrupt, 1: enable interrupt + *AUX_MU_LCR_REG = 3; // set data size to 8 bits. + *AUX_MU_MCR_REG = 0; // no flow control + *AUX_MU_BAUD_REG = 270; // 250MHz / (115200 + 1)*8 + *AUX_MU_IIR_REG = 6; // No FIFO + *AUX_MU_CNTL_REG = 3; // Enable the transmitter and receiver. + + + + /* configure gpio*/ + + register unsigned int tmp_reg; // hope the register can be stored in CPU register. + // GPFSELn: define the operation of the GPIO pins + // GPFSEL1: FSEL10(0~2) ~ FSEL19(27~29) + 30,31 reserved + /* FSEL: 3bits, in GPFSELn + + 000 = GPIO Pin 9 is an input + 001 = GPIO Pin 9 is an output + 100 = GPIO Pin 9 takes alternate function 0 + 101 = GPIO Pin 9 takes alternate function 1 + 110 = GPIO Pin 9 takes alternate function 2 + 111 = GPIO Pin 9 takes alternate function 3 + 011 = GPIO Pin 9 takes alternate function 4 + 010 = GPIO Pin 9 takes alternate function 5 + */ + tmp_reg = *GPFSEL1; // load the GPIO Function Select Registers SEL1 to tmp_reg. + tmp_reg &= 0xfffc0fff; // use a mask to clear the 12~17 bits(FSEL14 & FSEL15) of the register. + // FSEL14: 12~14bits. + // FSEL15: 15~17bits. + tmp_reg |= (0b010 << 12) | (0b010 << 15); // to make the 12~14bits and 15~17 bits of the register to b010, takes alternate function 5. + *GPFSEL1 = tmp_reg; + /* + 1. Write to GPPUD to set the required control signal (i.e. Pull-up or Pull-Down or neither + to remove the current Pull-up/down) + 2. Wait 150 cycles – this provides the required set-up time for the control signal + 3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to + modify – NOTE only the pads which receive a clock will be modified, all others will + retain their previous state. + 4. Wait 150 cycles – this provides the required hold time for the control signal + 5. Write to GPPUD to remove the control signal + 6. Write to GPPUDCLK0/1 to remove the clock + */ + *GPPUD = 0; // disable pull-up/down tmp_regregister, allow gpio pins use alternate function, not only basic input-output. + tmp_reg = 150; + while(tmp_reg--){ + asm volatile("nop"); // wait 150 cycles. + } + *GPPUDCLK0 = (1<<14)|(1<<15); // assert clock on 14 and 15, because the gpio state would be modified. + tmp_reg = 150; + while(tmp_reg--){ + asm volatile("nop"); // wait 150 cycles. + } + + *GPPUDCLK0 = 0; // remove the clock. + *AUX_MU_CNTL_REG = 3; // enable tx and rx after configuration. + +} +char read_uart(){ + char r; + while(!(*AUX_MU_LSR_REG & 0x01)){ + asm volatile("nop"); + } + r = (char)(*AUX_MU_IO_REG); + return r=='\r'?'\n':r; +} + +void write_int_uart(unsigned int s, bool newline){ + if(s==0){ + writec_uart('0'); + if(newline) + writes_uart("\r\n"); + return; + } + char a[128]; + int i=0,n=s; + while(n!=0){ + a[i] = '0' + n%10; + n/=10; + i++; + } + a[i]='\0'; + for (int j = i-1; j>=0; j--) + { + writec_uart(a[j]); + /* code */ + } + + if(newline) + writes_uart("\r\n"); +} + +void writec_uart(unsigned int s){ + // unsigned int c = s; + // while(!(*AUX_MU_LSR_REG & 0x20)) asm volatile("nop"); + // *AUX_MU_IO_REG = c; + uart_buf_write_push(s); +} + +void writes_n_uart(char *s, unsigned int size){ + for(int i=0;i=0;c-=4) { + + n=(h>>c)&(0xF); // n = 1,2,3....th byte of h from left to right. + + n+=n>9?0x37:0x30; // int 0~9 -> char '0'~'9', 10~15 -> 'A'~'F' + writec_uart(n); + } + if(newline==1){ + writes_uart("\r\n"); + } +} +void writeint_uart(unsigned int i){ + int iter=0; + char buffer[100]; + int k=i; + while(1){ + if(k==0) + { + buffer[iter]=k%10; + break; + }else{ + buffer[iter++] = k%10; + k = k/10; + } + } + writes_uart(buffer); + writes_uart("\r\n"); +} +// void writeaddr_uart(unsigned int* addrh){ + +// writes_uart("0x"); +// unsigned int n; +// int c; +// for(c=28;c>=0;c-=4) { + +// n=(h>>c)&(0xF); // n = 1,2,3....th byte of h from left to right. + +// n+=n>9?0x37:0x30; // int 0~9 -> char '0'~'9', 10~15 -> 'A'~'F' +// writec_uart(n); +// } +// } +void init_uart_buf(){ + uart_read_i_l=0; + uart_read_i_r=0; + uart_write_i_l=0; + uart_write_i_r=0; + //uart_buf_read = simple_malloc(2560); + uart_buf_read[0]='\0'; + // uart_buf_write = simple_malloc(2560); + uart_buf_write[0] = '\0'; +} +void uart_buf_read_push(char c){ + disable_interrupt(); + if(uart_read_i_r<1024) + { + uart_buf_read[uart_read_i_r++] = c; + uart_read_i_r= uart_read_i_r % 1024; + // uart_buf_read[uart_read_i_r] = '\0'; + } + enable_interrupt(); +} +void uart_buf_write_push(char c){ + disable_interrupt(); + if(uart_write_i_r<1024) + { + uart_buf_write[uart_write_i_r++] = c; + uart_write_i_r = uart_write_i_r % 1024; + // uart_buf_write[uart_write_i_r] = '\0'; + + // if(*AUX_MU_IER_REG != 3) + // *AUX_MU_IER_REG = 3; + if(!(*AUX_MU_IER_REG & 2)) + *AUX_MU_IER_REG |= 2; + } + enable_interrupt(); +} +void uart_buf_writes_push(char *s){ + // writehex_uart(strlen(s),1); + // writes_uart(s); + // *AUX_MU_IER_REG = 1; + + for (int i = 0; i < strlen(s); i++) + { + /* code */ + if(s[i]=='\n') + uart_buf_write_push('\r'); + uart_buf_write_push(s[i]); + } + + // while(*s){ + // if(*s=='\n') + // uart_buf_write_push('\r'); + // uart_buf_write_push(*s++); + // } + // *AUX_MU_IER_REG = 3; + +} + +char uart_buf_read_pop(){ + char c='0'; + if(uart_read_i_l != uart_read_i_r){ + + c = uart_buf_read[uart_read_i_l++]; + uart_read_i_l=uart_read_i_l%1024; + + } + return c; +} +char uart_buf_write_pop(){ + char c='0'; + if(uart_write_i_l != uart_write_i_r){ + + c = uart_buf_write[uart_write_i_l++]; + uart_write_i_l= uart_write_i_l % 1024; + + } + return c; +} + +int is_empty_write(){ + if(uart_write_i_l==uart_write_i_r){ + return 1; // return 1 if empty. + }else{ + return 0; // return 0 if not empty. + } +} +int is_empty_read(){ + if(uart_read_i_l==uart_read_i_r){ + return 1; // return 1 if empty. + }else{ + return 0; // return 0 if not empty. + } +} +void busy_wait_writec(char s){ + unsigned int c = s; + while(!(*AUX_MU_LSR_REG & 0x20)) asm volatile("nop"); + *AUX_MU_IO_REG = c; +} +void busy_wait_writes(char *s,bool newline){ + while(*s){ + if(*s=='\n') + busy_wait_writec('\r'); + busy_wait_writec(*s++); + } + if(newline){ + busy_wait_writec('\r'); + busy_wait_writec('\n'); + } + +} +void busy_wait_writeint(int s,bool newline){ + if(s==0){ + busy_wait_writec('0'); + if(newline) + busy_wait_writes("\r\n",FALSE); + return; + } + char a[128]; + int i=0,n=s; + while(n!=0){ + a[i] = '0' + n%10; + n/=10; + i++; + } + a[i]='\0'; + for (int j = i-1; j>=0; j--) + { + busy_wait_writec(a[j]); + /* code */ + } + + if(newline) + busy_wait_writes("\r\n",FALSE); +} +void busy_wait_writehex(unsigned long long h,bool newline) +{ + busy_wait_writes("0x",FALSE); + unsigned int n; + int c; + for(c=28;c>=0;c-=4) { + + n=(h>>c)&(0xF); // n = 1,2,3....th byte of h from left to right. + + n+=n>9?0x37:0x30; // int 0~9 -> char '0'~'9', 10~15 -> 'A'~'F' + busy_wait_writec(n); + } + if(newline==1){ + busy_wait_writes("\r\n",FALSE); + } +} \ No newline at end of file diff --git a/user/src/reboot.c b/user/src/reboot.c new file mode 100644 index 000000000..0346e57c1 --- /dev/null +++ b/user/src/reboot.c @@ -0,0 +1,20 @@ +#include "reboot.h" +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC 0x3F10001c +#define PM_WDOG 0x3F100024 + +void set(long addr, unsigned int value) { + volatile unsigned int* point = (unsigned int*)addr; + *point = value; +} +//500 ms =2000 ticks. + +void reset(int tick) { // reboot after watchdog timer expire + set(PM_RSTC, PM_PASSWORD | 0x20); // full reset + set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick +} + +void cancel_reset() { + set(PM_RSTC, PM_PASSWORD | 0); // full reset + set(PM_WDOG, PM_PASSWORD | 0); // number of watchdog tick +} \ No newline at end of file diff --git a/user/src/shell.c b/user/src/shell.c new file mode 100644 index 000000000..5e307df2c --- /dev/null +++ b/user/src/shell.c @@ -0,0 +1,420 @@ +#include "shell.h" +#include "string.h" +#include "mailbox.h" +#include "reboot.h" +#include "cpio.h" +#include "stdlib.h" +#include "timer.h" +#include "allocator.h" +int match_command(char *buffer){ + + if(strcmp(buffer,"help")==0){ + return help; + } + else if(strcmp(buffer,"hello")==0){ + return hello; + }else if(strcmp(buffer,"revision")==0){ + return revision; + }else if(strcmp(buffer,"memory")==0){ + return memory; + } + else if(strcmp(buffer,"reboot")==0){ + return reboot; + } + else if(strcmp(buffer,"ccreboot")==0){ + return ccreboot; + } + else if(strcmp(buffer,"version")==0){ + return version; + } + else if(strcmp(buffer,"ls")==0){ + return ls; + } + else if(strcmp(buffer,"cat")==0){ + return cat; + } + else if(strcmp(buffer,"prog")==0){ + return prog; + } + else if(strncmp(buffer,"timeout",strlen("timeout"))==0){ + return timeout; + } + else if(strncmp(buffer,"mmalloc",strlen("mmalloc"))==0){ + return mmalloc; + } + else if(strncmp(buffer,"mfree",strlen("mfree"))==0){ + return mfree; + } + else if(strncmp(buffer,"mlistc",strlen("mlistc"))==0){ + return mlistc; + } + else if(strncmp(buffer,"mlistf",strlen("mlistf"))==0){ + return mlistf; + } + else if(strncmp(buffer,"mtest",strlen("mtest"))==0){ + return mtest; + } + else{ + return unknown; + } +} + + +void read_command(){ + char buffer[512]; + int count=0; + int action = 0; + writes_uart("# "); + while(1){ + do{asm volatile("nop");}while(is_empty_read()); + char c = uart_buf_read_pop(); + // writehex_uart(uart_write_i_l,0); + // writehex_uart(uart_write_i_r,1); + if(c!='\n' && count<256){ + if(c=='\x7f'){ + if(count >0 ){ + uart_buf_write_push('\b'); + uart_buf_write_push(' '); + uart_buf_write_push('\b'); + buffer[--count]='\0'; + } + + } + else if(c>=0 && c<=127){ // only accept the value is inside 0~127(ASCII). + uart_buf_write_push(c); + buffer[count++] = c; + buffer[count] = '\0'; + } + + }else{ + uart_buf_write_push('\r'); + uart_buf_write_push('\n'); + buffer[count]='\0'; + if(buffer[0] != '\0'){ + action = match_command(buffer); + handle_command(action, buffer); + } + break; + } + + } + return; +} + +void read_string(char **s){ + char *buffer= simple_malloc(256); + int count=0; + while(1){ + do{asm volatile("nop");}while(is_empty_read()); + char c = uart_buf_read_pop(); + if(c!='\n' && count<256){ + if(c=='\x7f'){ + if(count >0 ){ + writec_uart('\b'); + writec_uart(' '); + writec_uart('\b'); + buffer[--count]='\0'; + } + + } + else if(c>=0 && c<=127){ // only accept the value is inside 0~127(ASCII). + writec_uart(c); + buffer[count++] = c; + } + + }else{ + writec_uart('\r'); + writec_uart('\n'); + + buffer[count]='\0'; + if(buffer[0] != '\0'){ + *s = buffer; + return; + } + break; + } + + } + return; +} +int read_int(){ + char* s; + read_string(&s); + int n=0; + for (int i = 0; i < strlen(s); i++) + { + char c = s[i]; + n = n *10; + n += c-'0'; + /* code */ + } + return n; + +} + +int get_para_num(char *s){ + int n=0; + for (int i = 0; i < strlen(s); i++) + { + if(s[i]==' ') n++; + } + return n; +} + +char* get_para_by_num(int num,char *buffer){ + int space_num=0; + int start=0,end=0; + for (int i = 0; i < strlen(buffer); i++) + { + if(buffer[i]==' ') + { + space_num++; + if(space_num==num){ + start = i+1; + } + else if(space_num==num+1){ + end = i; + } + } + } + if(space_num 0) + { + u1 = (unsigned char) *s1++; + u2 = (unsigned char) *s2++; + if (u1 != u2) + return u1 - u2; + if (u1 == '\0') + return 0; + } + return 0; +} + + +int strlen(char *s){ + unsigned int count = 0; + char *tmps = s; + while(*tmps!='\0') + { + count++; + tmps++; + } + return count; +} + +unsigned int str2int(char *s){ + unsigned int n=0; + //busy_wait_writes("Enter str2int",TRUE); + for (int i = 0; i < strlen(s); i++) + { + if(s[i]<'0' || s[i]>'9') + return n; + //busy_wait_writes("Lopping str2int",TRUE); + n*=10; + n+=s[i]-'0'; + } + //busy_wait_writes("Return str2int",TRUE); + return n; +} \ No newline at end of file diff --git a/user/src/syscall.S b/user/src/syscall.S new file mode 100644 index 000000000..e69de29bb diff --git a/user/src/task.c b/user/src/task.c new file mode 100644 index 000000000..6ef02e953 --- /dev/null +++ b/user/src/task.c @@ -0,0 +1,61 @@ +#include "task.h" +#include "exception.h" +#include "timer.h" +void init_taskq(){ + taskq_head = nullptr; + return; +} +void add_task(void (*handler)(),int privilege){ + taskq *node = (taskq*)simple_malloc(sizeof(taskq)); + node->handler = handler; + node->privilege = privilege; + node->next = nullptr; + if(taskq_head==nullptr){ + taskq_head = node; + } + else{ + // taskq* newNode = (taskq*)simple_malloc(sizeof(taskq)); + + if(privilege < taskq_head->privilege){ + node->next = taskq_head; + taskq_head = node; + // set_expired_time(after); + } + else{ + taskq *itr_node = taskq_head; + while(itr_node->next!=null){ + if(itr_node->next->privilege>=privilege){ + break; + } + itr_node = itr_node->next; + } + node->next = itr_node->next; + itr_node->next = node; + } + } + return; +} +void do_task(int* curr_task_privilege){ + while(!is_taskq_empty()){ + disable_interrupt(); + + taskq *node = taskq_head; + int last_task_privilege = *curr_task_privilege; + *curr_task_privilege = node->privilege; + taskq_head = taskq_head->next; + + enable_interrupt(); + + node->handler(); + disable_interrupt(); + *curr_task_privilege = last_task_privilege; + enable_interrupt(); + } +} + +bool is_taskq_empty(){ + if(taskq_head == nullptr) + return TRUE; + else + return FALSE; +} \ No newline at end of file diff --git a/user/src/timer.c b/user/src/timer.c new file mode 100644 index 000000000..0fa74a870 --- /dev/null +++ b/user/src/timer.c @@ -0,0 +1,156 @@ +#include "timer.h" +#include "mini_uart.h" +#include "stdlib.h" +#include "shell.h" +#include "string.h" +#define CORE0_TIMER_IRQ_CTRL ((volatile unsigned int*)(0x40000040)) +void init_timer(){ + // head->next = nullptr; + // head->value = null; + + head = nullptr; + disable_timer_interrupt(); + // writes_uart("Core timer: "); + //writehex_uart(*CORE0_TIMER_IRQ_CTRL,1); +} +void get_current_time(unsigned long long *time_count,unsigned long long *time_freq){ + unsigned long long _time_count=0; + unsigned long long _time_freq=0; + asm volatile( + "mrs %0,cntpct_el0\n\t" + "mrs %1,cntfrq_el0\n\t" + :"=r" (_time_count), + "=r" (_time_freq) + ); + *time_count = _time_count; + *time_freq = _time_freq; +} +void set_expired_time(int after){ + unsigned long long time_count=0; + unsigned long long time_freq=0; + get_current_time(&time_count,&time_freq); + // write_int_uart((int)(time_count/time_freq),1); + unsigned long long time_expired = time_freq*after; + // write_int_uart(time_expired,1); + asm volatile( + "msr cntp_tval_el0, %0\n\t" + ::"r" (time_expired) + ); + return; +} + +void add_timer(void (*callback)(char* s),char *message,int after){ + //busy_wait_writes("Enter add timer",TRUE); + timer* node ; + unsigned long long time_count=0; + unsigned long long time_freq=0; + // char* tmp_message = simple_malloc(strlen(message)); + // for (int i = 0; i < strlen(message); i++) + // { + // tmp_message[i] = message[i]; + // } + + if(head==nullptr){ + writes_nl_uart("Adding new timer to empty timer queue"); + node = (timer*)simple_malloc(sizeof(timer)); + node->next=nullptr; + get_current_time(&time_count,&time_freq); + node->value=(time_count/time_freq) + after; + node->message = message; + node->callback = callback; + head = node; + set_expired_time(after); + enable_timer_interrupt(); + }else{ + // busy_wait_writes("ADDing new timer busy2",TRUE); + writes_nl_uart("Adding new timer to non-empty queue"); + timer* newNode = (timer*)simple_malloc(sizeof(timer)); + get_current_time(&time_count,&time_freq); + newNode->value=(time_count/time_freq) + after; + newNode->message=message; + newNode->callback = callback; + if((time_count/time_freq + after) < head->value){ + newNode->next = head; + head = newNode; + set_expired_time(after); + } + else{ + timer *node = head; + get_current_time(&time_count,&time_freq); + while(node->next!=null){ + if(node->next->value>=(time_count/time_freq + after)){ + break; + } + node = node->next; + } + newNode->next = node->next; + node->next = newNode; + } + } + //callback(message); + itr_timer_queue(); + return; +} + +void itr_timer_queue(){ + timer *node = head; + while(node!=nullptr){ + writes_uart(node->message); + writes_uart(" "); + write_int_uart(node->value,TRUE); + node = node->next; + } + return; +} + +bool timer_is_empty(){ + if(head==null){ + return TRUE; + } + else{ + return FALSE; + } +} + +void disable_timer_interrupt(){ + // head = nullptr; + *CORE0_TIMER_IRQ_CTRL = 0; + // asm volatile( + // "mrs x0, cntfrq_el0\n\t" + // "mov x1,0x00000fff\n\t" + // "mul x0,x0,x1\n\t" + // "msr cntp_tval_el0, x0\n\t" + // //"mov x0, 0\n\t" + // //"msr cntp_ctl_el0, x0\n\t" + // :::"x0","x1" + // ); + + //*CORE0_TIMER_IRQ_CTRL &= ~(1 << 2); + +} +void enable_timer_interrupt(){ + *CORE0_TIMER_IRQ_CTRL = 2; + // asm volatile( + // "mov x0,1\n\t" + // "msr cntp_ctl_el0, x0\n\t" + // :: + // : "x0" + // ); + // asm volatile( + // "bl core_timer_enable" + // ); +} +bool is_timerq_empty(){ + if(head==nullptr) + return TRUE; + else + return FALSE; +} + +timer* to_next_timer(){ + head = head->next; + return head; +} +timer* get_head_timer(){ + return head; +} \ No newline at end of file diff --git a/user/src/utils.c b/user/src/utils.c new file mode 100644 index 000000000..4cbfe3e94 --- /dev/null +++ b/user/src/utils.c @@ -0,0 +1,16 @@ +#include "utils.h" + +/* transfer big endian to little endian */ +uint32_t big2little(uint32_t big){ + // use instruction + uint32_t little = (0x000000ff & (big >> 24)) | + (0x0000ff00 & (big >> 8)) | + (0x00ff0000 & (big << 8)) | + (0xff000000 & (big << 24)); + return little; +} + +unsigned long align_up(unsigned long n, unsigned long align) +{ + return (n + align - 1) & (~(align - 1)); +} \ No newline at end of file