Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

310551115 Lab6 & Lab7 #172

Open
wants to merge 26 commits into
base: 310551115
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Lab6/.vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/include"
],
"defines": [],
"compilerPath": "/usr/bin/clang",
"cStandard": "c11",
"cppStandard": "c++14",
"intelliSenseMode": "linux-clang-x64"
}
],
"version": 4
}
16 changes: 16 additions & 0 deletions Lab6/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"files.associations": {
"stdint.h": "c",
"memory.h": "c",
"array": "c",
"hash_map": "c",
"string_view": "c",
"initializer_list": "c",
"utility": "c",
"task.h": "c",
"allocator.h": "c",
"mini_uart.h": "c",
"exception.h": "c",
"mail_box.h": "c"
}
}
45 changes: 45 additions & 0 deletions Lab6/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.PHONY: all clean qemu-kernel on-board

ARMGNU ?= aarch64-linux-gnu

FLAGS = -O0 -Wall -nostartfiles -ffreestanding -mgeneral-regs-only -g -fPIC
INC = include
LIB = lib
CPIO = archive/initramfs.cpio
USER_PROG = timer_test

all: kernel8.img $(CPIO) $(USER_PROG).img

kernel8.img: kernel/*.S kernel/*.c $(LIB)/*.S $(LIB)/*.c rd.o
$(ARMGNU)-gcc $(FLAGS) -Tkernel/linker.ld $^ -o kernel8.elf -I$(INC)
$(ARMGNU)-objcopy -O binary kernel8.elf kernel8.img

$(USER_PROG).img: user/$(USER_PROG).c user/$(LIB)/*.c
$(ARMGNU)-gcc $(FLAGS) -Tuser/linker.ld $^ -o $(USER_PROG).elf -Iuser/$(INC)
$(ARMGNU)-objcopy -O binary $(USER_PROG).elf $(USER_PROG).img

$(CPIO): $(USER_PROG).img
cd archive/rootfs && find . | cpio -o -H newc > ../initramfs.cpio

rd.o:$(CPIO)
aarch64-linux-gnu-ld -r -b binary -o rd.o $(CPIO)

qemu-kernel:
qemu-system-aarch64 -M raspi3 -kernel kernel8.img -display none -serial null -serial stdio -initrd archive/initramfs.cpio

qemu-debug:
aarch64-linux-gnu-objdump -d kernel8.elf > kernel8.S
qemu-system-aarch64 -M raspi3 -kernel kernel8.img -display none -serial null -serial stdio -initrd archive/initramfs.cpio -d in_asm

# qemu-kernel:
# qemu-system-aarch64 -M raspi3 -kernel kernel8.img -display none -serial null -serial stdio -initrd $(CPIO)

# qemu-debug:
# aarch64-linux-gnu-objdump -d kernel8.elf > kernel8.S
# qemu-system-aarch64 -M raspi3 -kernel kernel8.img -display none -serial null -serial stdio -initrd $(CPIO) -d in_asm

on-board:
sudo screen /dev/ttyUSB0 115200

clean:
rm -f *.elf *.img *.cpio *.o *.S *.s
Binary file added Lab6/archive/initramfs.cpio
Binary file not shown.
Binary file added Lab6/archive/rootfs/dummy_test.img
Binary file not shown.
Binary file added Lab6/archive/rootfs/exec_test.img
Binary file not shown.
Binary file added Lab6/archive/rootfs/fork_test.img
Binary file not shown.
Binary file added Lab6/archive/rootfs/mbox_test.img
Binary file not shown.
Binary file added Lab6/archive/rootfs/timer_test.img
Binary file not shown.
Binary file added Lab6/archive/rootfs/vm.img
Binary file not shown.
40 changes: 40 additions & 0 deletions Lab6/bootloader/boot.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.section ".text.relo"
.globl _start
# need to relocate the bootloader from 0x80000 to 0x60000
_start:
adr x10, . //x10=0x80000
ldr x11, =_blsize
add x11, x11, x10
ldr x12, =_stext // x12=0x60000

moving_relo:
cmp x10, x11 //without bootloader
b.eq end_relo
ldr x13, [x10]
str x13, [x12] //move 0x80000 data to 0x60000
add x12, x12, #8
add x10, x10, #8
b moving_relo
end_relo:
ldr x14, =_bl_entry //jump to boot part
br x14


.section ".text.boot"
.globl _start_bl
mrs x0, mpidr_el1
and x0, x0,#0xFF // Check processor id
cbz x0, master // Hang for all non-primary CPU

hang:
b hang

master:
adr x0, _sbss
adr x1, _ebss
sub x1, x1, x0
bl memzero

mov sp, #0x400000 // 4MB
bl main

28 changes: 28 additions & 0 deletions Lab6/bootloader/linker.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
ENTRY(_start)
SECTIONS
{
. = 0x60000;
_stext = .;
.text : {
*(.text.relo)
_bl_entry = .;
*(.text.boot)
*(.text)
*(.rodata)
}
. = ALIGN(0x1000);
_etext = .;

_sdata = .;
.data : { *(.data) }
. = ALIGN(0x1000);
_edata = .;


_sbss = .;
.bss : { *(.bss*) }
. = ALIGN(0x1000);
_ebss = .;

_blsize = _ebss - _stext;
}
36 changes: 36 additions & 0 deletions Lab6/bootloader/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "mini_uart.h"
#include "utils.h"

void load_kernel() {
char buffer[MAX_BUFFER_SIZE];

while (compare_string(buffer, "[Load Kernel]") != 0) {
uart_recv_string(buffer);
}

unsigned long k_addr=0,k_size=0;
uart_send_string("Please enter kernel load address (Hex): ");

uart_recv_string(buffer);
k_addr = getHexFromString(buffer);
uart_send_string("Please enter kernel size (Dec): ");
uart_recv_string(buffer);
k_size = getIntegerFromString(buffer);

uart_send_string("Please send kernel image now...\n");
unsigned char* target=(unsigned char*)k_addr;
while(k_size--){
*target=uart_getb();
target++;
uart_send('.');
}

uart_send_string("loading...\n");
asm volatile("br %0\n"::"r"(k_addr)); // GCC inline assembly
}

int main() {
uart_init();
load_kernel();
return 0; // should not reach here
}
40 changes: 40 additions & 0 deletions Lab6/include/allocator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#ifndef _ALLOCATOR_H
#define _ALLOCATOR_H

#include "memory.h"
#include <stddef.h>

/*
Partition of a 4K page: (size, amount)
(32, 32) (64, 15) (128, 8) (256, 4)

First 64 byte is used to record usage of each slot, shown below:
uint32_t usage32;
uint16_t usage64; // upper 1 bit is not used
uint8_t usage128;
uint8_t usage258; // upper 4 bits reserve for future use

[Future use] 4 bits of record of 256-bytes slot can be used to represent fused mode to get larger slot
*/

void *kmalloc(size_t size);
void kfree(void *addr);
uint64_t get_slot_record(frame_free_node *page, int size);
void set_slot_record(frame_free_node *page, int size, int which_slot, int value);
int is_full(frame_free_node *page, int size);
int is_empty(frame_free_node *page, int size);
int round_to_smallest(size_t size);
frame_free_node *get_page_with_slot(int size);
void *allocate_slot(frame_free_node *page, int size);
frame_free_node *find_page(void *addr);
void clear_page(frame_free_node *page);
void print_slot_record(frame_free_node *page);
void free_page_if_empty(frame_free_node *page);

/*
memory reservation
*/
void memory_reserve(uint64_t start, uint64_t end);
void init_reserve();

#endif
43 changes: 43 additions & 0 deletions Lab6/include/cpio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef __CPIO__
#define __CPIO__

#include "peripherals/base.h"

#define __USE_QEMU__

#ifdef __USE_QEMU__
#define CPIO_ADDR ((char *)(KVA + 0x8000000)) // qemu
#else
#define CPIO_ADDR ((char *)(KVA + 0x20000000)) // raspi3
#endif
#define MAX_INITRAMFS_SIZE 0x100000 // 1M

#define USER_PROGRAM_VA 0x0
#define MAX_USER_PROGRAM_SIZE 0x100000 // 1M


typedef struct
{
// uses 8-byte hexadecimal fields for all numbers
char magic[6]; //determine whether this archive is written with little-endian or big-endian integers.
char ino[8]; //determine when two entries refer to the same file.
char mode[8]; //specifies both the regular permissions and the file type.
char uid[8]; // numeric user id
char gid[8]; // numeric group id
char nlink[8]; // number of links to this file.
char mtime[8]; // Modification time of the file
char filesize[8]; // size of the file
char devmajor[8];
char devminor[8];
char rdevmajor[8];
char rdevminor[8];
char namesize[8]; // number of bytes in the pathname
char check[8]; // always set to zero by writers and ignored by readers.
} __attribute__((packed)) cpio_header;

void cpio_list();
void cpio_cat(char *filename);
char * findFile(char *name);
void load_program(char *name, void *page_table);

#endif
34 changes: 34 additions & 0 deletions Lab6/include/exception.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef _EXCEPTION_H
#define _EXCEPTION_H

#include "task.h"
#include <stddef.h>

void enable_interrupt();
void disable_interrupt();
void dumpState();
void lower_sync_handler();
void lower_iqr_handler();
void curr_sync_handler();
void curr_iqr_handler();
void error_handler();
void child_return_from_fork();

/* Implement system calls */
int sys_getpid();
size_t sys_uartread(char buf[], size_t size);
size_t sys_uartwrite(const char buf[], size_t size);
int sys_exec(trap_frame *tf, const char *name, char *const argv[]);
void sys_fork(trap_frame *tf);
void sys_exit();
int sys_mbox_call(unsigned char ch, volatile unsigned int *mbox);
void sys_kill(int pid);
void sys_signal(int SIGNAL, void (*handler)());
void sys_signal_kill(int pid, int SIGNAL);

/* helper functions */
extern void (*_handler)();
extern int _pid;
void signal_handler_wrapper();

#endif
45 changes: 45 additions & 0 deletions Lab6/include/mail_box.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#ifndef _MAIL_BOX_H
#define _MAIL_BOX_H

/* a properly aligned buffer */
extern volatile unsigned int mailbox[36];

#define MBOX_REQUEST 0

/* 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

/* tags */
#define MBOX_TAG_GETSERIAL 0x10004
#define MBOX_TAG_LAST 0
#define GET_BOARD_REVISION 0x00010002
#define GET_ARM_EMEORY 0x00010005

int mailbox_call(unsigned char ch, volatile unsigned int *mailbox, volatile unsigned int *mailbox_va);


/* old macros from lab1 */
// #define GET_BOARD_REVISION 0x00010002
// #define GET_ARM_EMEORY 0x00010005
// #define REQUEST_CODE 0x00000000
// #define REQUEST_SUCCEED 0x80000000
// #define REQUEST_FAILED 0x80000001
// #define TAG_REQUEST_CODE 0x00000000
// #define END_TAG 0x00000000

// extern volatile unsigned int mailbox[8];

// int mailbox_call(unsigned char ch, volatile unsigned int *mbox);
void get_board_revision();
void get_arm_memory();
void get_serial_number();

#endif
Loading