diff --git a/.gdb_history b/.gdb_history new file mode 100644 index 000000000..514dac8e1 --- /dev/null +++ b/.gdb_history @@ -0,0 +1,27 @@ +target remote:1234 +file lab3/build/kernel8.elf +x/gx deubg +x/gx debug +b log_kernel_start +c +x/gx 0x87004 +x/gx 0x87004 - 0x10 +x/gx 0x87004 - 0x20 +x/gx 0x87004 - 0x100 +quit +target remote:1234 +file ./lab3/build/kernel8.elf +x/gx 0x87004 +x/gx 0x87004 +watch *0x87004 +c +x/gx 0x87004 +quit +file +ls +file lab5/build/kernel8.elf +file 0x881e4 +x/i 0x881e4 +target remote:1234 +x/i 0x881e4 +quit diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 5ff9f31c3..000000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,25 +0,0 @@ -↓↓↓ **Notice** ↓↓↓ - -- [ ] Check your base repository and branch are belong to you. -- [ ] The PR name need to include student ID and which lab assignment - - template: `${student id} ${which lab}` - - e.g. `0756110 lab0` - -↑↑↑ **Notice** ↑↑↑ - -> If you ensure the notice items is done, you can remove them. - ---- - -> Following section is optional, depend on you. - -## Description -a few message for overall goals of this pull request - -## Todos -- [ ] what feature to do ? -- [ ] what bug to fix ? -- [ ] what enhancement to improve ? - ---- -@GrassLab/ta \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 9cd99afa2..000000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 GRASS 綠色運算與嵌入式系統實驗室  - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 8ffefa7f8..000000000 --- a/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Operating Systems Capstone 2022 - -This repository is homework submission for students - -## How to submit homework - -1. Fork [this repository](https://github.com/oscapstone/osc2022) on GitHub - ![](images/fork_button.png) -2. Write down following info in your `README.md` - - GitHub account name - - Student ID - - Your name -3. Design and implement your kernel in forked repository -4. Create a GitHub pull request - - Choose `oscapstone/osc2022` as base repository and `{your student ID}` as base branch - - Choose branch in your forked repository as compare branch - - Name it with student ID and which lab e.g. `0856085 lab0` - ![](images/pull_request.png) -5. We will accept pull request when lab due date - -repeat 3-5 to submit later homework/lab. - -## Happy Coding ~ diff --git a/images/fork_button.png b/images/fork_button.png deleted file mode 100644 index e6e8fa2de..000000000 Binary files a/images/fork_button.png and /dev/null differ diff --git a/images/pull_request.png b/images/pull_request.png deleted file mode 100755 index b178065b5..000000000 Binary files a/images/pull_request.png and /dev/null differ diff --git a/lab0/Start.S b/lab0/Start.S new file mode 100644 index 000000000..d0181b01c --- /dev/null +++ b/lab0/Start.S @@ -0,0 +1,4 @@ +.section ".text" +_start: + wfe + b _start diff --git a/lab0/Start.o b/lab0/Start.o new file mode 100644 index 000000000..fdcc2b628 Binary files /dev/null and b/lab0/Start.o differ diff --git a/lab0/kernel8.elf b/lab0/kernel8.elf new file mode 100755 index 000000000..7b80a04ac Binary files /dev/null and b/lab0/kernel8.elf differ diff --git a/lab0/kernel8.img b/lab0/kernel8.img new file mode 100755 index 000000000..2276dd4d5 --- /dev/null +++ b/lab0/kernel8.img @@ -0,0 +1 @@ +_  \ No newline at end of file diff --git a/lab0/linker.ld b/lab0/linker.ld new file mode 100644 index 000000000..faee5d7b1 --- /dev/null +++ b/lab0/linker.ld @@ -0,0 +1,5 @@ +SECTIONS +{ + . = 0x80000; + .text : { *(.text) } +} diff --git a/lab1/.gdb_history b/lab1/.gdb_history new file mode 100644 index 000000000..598c43976 --- /dev/null +++ b/lab1/.gdb_history @@ -0,0 +1,67 @@ +file ./build/kernel8.elf +target remote :1234 +ni +quit +file ./build/kernel8.elf +target remote :1234 +ni +ni +ni +ni +target remote :1234 +target remote :1234 +ni +ni +ni +quit +file ./build/kernel8.elf +target remote :1234 +ni +quit +file ./build/kernel8.elf +target remote :1234 +ni +b *0x80028 +c +x/gx 0x81330 +b *0x80028 +quit +quit +file ./build/kernel8.elf +target remote :1234 +c +c +x/gx MBox_buf +x/gx MBox_write +b * 0x80360 +c +mailbox +target remote :1234 +b * 0x80360 +del 1 +c +ni +qquit +quit +file ./build/kernel8..efl +file ./build/kernel8..elf +file ./build/kernel8.elf +target remote :1234 +b MBox_write +c +ni +x/gx 0x3f00b880 + 0x1b +x/gx 0x3f00b880 + 0x10 +x/gx 0x3f00b880 + 0x1b +x/gx 0x3f00b880 + 0x1c +x/gx 0x3f00b880 + 0x1b +x/gx 0x3f00b880 + 0x1e +x/gx 0x3f00b880 + 0x1f +x/gx 0x3f00b880 + 0x1a +x/gx 0x3f00b880 + 0x1b +x/gx 0x3f00b880 + 0x1c +x/gx 0x3f00b880 + 0x1b +disassemble MBox_write +disassemble MBox_write +disassemble MBox_write +ls diff --git a/lab1/Makefile b/lab1/Makefile new file mode 100644 index 000000000..c9acf5625 --- /dev/null +++ b/lab1/Makefile @@ -0,0 +1,78 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +override CFLAGS += \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin \ + +LDFLAGS ?= \ + -nostdlib \ + +CXXFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJDUMP = aarch64-linux-gnu-objdump +QEMU = qemu-system-aarch64 +RASPI_VER = raspi3b + + +LINKER_FILE = ./linker.ld +HEADERS = $(PWD)/include/ +OUTPUT = $(PWD)/build +KNAME = $(OUTPUT)/kernel8 + +LIBS = \ + $(OUTPUT)/print.o \ + $(OUTPUT)/string.o \ + +OBJECTS = \ + $(OUTPUT)/boot.o \ + $(OUTPUT)/mini_uart.o \ + $(OUTPUT)/mailbox.o \ + $(OUTPUT)/main.o \ + $(OUTPUT)/kernel_init.o \ + $(OUTPUT)/reboot.o \ + $(OUTPUT)/shell.o \ + $(OUTPUT)/debug.o \ + $(LIBS) + + +.PHONY: all start objects link kernel end clean dump + + +all: start objects link kernel end + +start: + @echo "Start building kernel8.img" + +objects: + $(MAKE) -C boot OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C peripherals OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C init OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C kernel OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C lib OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C debug OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + +link: $(OBJECTS) + $(LD) -T $(LINKER_FILE) -o $(KNAME).elf $(OBJECTS) $(LDFLAGS) + +kernel: $(KNAME).elf + $(OBJCOPY) -O binary $(KNAME).elf $(KNAME).img + +end: + @echo "Finish building kernel8.img" + +dump: + $(OBJDUMP) -m aarch64 -b binary -D $(KNAME).img + +qemu-run: + sudo $(QEMU) -M $(RASPI_VER) -kernel $(KNAME).img -display none -serial null -serial stdio + +qemu-run-instr: + sudo $(QEMU) -M $(RASPI_VER) -kernel $(KNAME).img -display none -d in_asm + +clean: + rm $(OUTPUT)/* diff --git a/lab1/README.md b/lab1/README.md new file mode 100644 index 000000000..c2590d943 --- /dev/null +++ b/lab1/README.md @@ -0,0 +1,18 @@ +# Requirements + +## Features + +- Basic Exercise 1 + - [x] All it’s data is presented at correct memory address. (In linker.ld) + - [x] The program counter is set to correct memory address. (In linker.ld) + - [x] The bss segment are initialized to 0. (In boot/boot.S) + - [x] The stack pointer is set to a proper address. (In boot/boot.S) +- Basic Exercise 2 + - [x] Mini UART (In peripherals/mini_uart.c) +- Basic Exercise 3 + - [x] Simple Shell (In kernel/shell.c) +- Basic Exercise 4 + - [x] Mailbox (In peripherals/mailbox.c) +- Advanced Exercise 1 + - [x] Reboot (In kernel/reboot.c) + diff --git a/lab1/boot/Makefile b/lab1/boot/Makefile new file mode 100644 index 000000000..9c8b30cba --- /dev/null +++ b/lab1/boot/Makefile @@ -0,0 +1,23 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +OBJECTS = \ + boot.o + +all: $(OBJECTS) + +%.o: %.S + $(CC) -c $^ -o $(OUTPUT)/$@ + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab1/boot/boot.S b/lab1/boot/boot.S new file mode 100644 index 000000000..0b14fd836 --- /dev/null +++ b/lab1/boot/boot.S @@ -0,0 +1,32 @@ +.section ".text.boot" +.global _start +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #0xff + + // cpu id > 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + +// cpu id == 0 +master_core: +// stack + adr x1, _start + mov sp, x1 +// initialize .bss section + ldr x1, =__bss_start + ldr x2, =__bss_end +bss_zero: + sub x3, x2, x1 + cbz x3, end + str xzr, [x1], #8 // store zero to [x1] and add 8 to x1 + b bss_zero + +end: +// jump to kernel_main + bl kernel_main + b proc_hang diff --git a/lab1/build/boot.o b/lab1/build/boot.o new file mode 100644 index 000000000..585b7781c Binary files /dev/null and b/lab1/build/boot.o differ diff --git a/lab1/build/debug.o b/lab1/build/debug.o new file mode 100644 index 000000000..c63273446 Binary files /dev/null and b/lab1/build/debug.o differ diff --git a/lab1/build/kernel8.elf b/lab1/build/kernel8.elf new file mode 100755 index 000000000..beffe2ed6 Binary files /dev/null and b/lab1/build/kernel8.elf differ diff --git a/lab1/build/kernel8.img b/lab1/build/kernel8.img new file mode 100755 index 000000000..0954d7278 Binary files /dev/null and b/lab1/build/kernel8.img differ diff --git a/lab1/build/kernel_init.o b/lab1/build/kernel_init.o new file mode 100644 index 000000000..3fb627104 Binary files /dev/null and b/lab1/build/kernel_init.o differ diff --git a/lab1/build/mailbox.o b/lab1/build/mailbox.o new file mode 100644 index 000000000..d2b06efc3 Binary files /dev/null and b/lab1/build/mailbox.o differ diff --git a/lab1/build/main.o b/lab1/build/main.o new file mode 100644 index 000000000..8726a2bff Binary files /dev/null and b/lab1/build/main.o differ diff --git a/lab1/build/mini_uart.o b/lab1/build/mini_uart.o new file mode 100644 index 000000000..d823b9bb7 Binary files /dev/null and b/lab1/build/mini_uart.o differ diff --git a/lab1/build/print.o b/lab1/build/print.o new file mode 100644 index 000000000..0de04a1fa Binary files /dev/null and b/lab1/build/print.o differ diff --git a/lab1/build/reboot.o b/lab1/build/reboot.o new file mode 100644 index 000000000..b2e138124 Binary files /dev/null and b/lab1/build/reboot.o differ diff --git a/lab1/build/shell.o b/lab1/build/shell.o new file mode 100644 index 000000000..25886191c Binary files /dev/null and b/lab1/build/shell.o differ diff --git a/lab1/build/string.o b/lab1/build/string.o new file mode 100644 index 000000000..89ad5c7da Binary files /dev/null and b/lab1/build/string.o differ diff --git a/lab1/debug.sh b/lab1/debug.sh new file mode 100755 index 000000000..81d573d80 --- /dev/null +++ b/lab1/debug.sh @@ -0,0 +1,3 @@ +#!/bin/sh +make CFLAGS=-DDEBUG >/dev/null +make qemu-run diff --git a/lab1/debug/Makefile b/lab1/debug/Makefile new file mode 100644 index 000000000..22ac23500 --- /dev/null +++ b/lab1/debug/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + debug.o + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab1/debug/debug.c b/lab1/debug/debug.c new file mode 100644 index 000000000..a0cdda203 --- /dev/null +++ b/lab1/debug/debug.c @@ -0,0 +1,42 @@ +#include "types.h" +#include "utils.h" +#include "debug/debug.h" +extern int __bss_start, __bss_end; +extern int __text_start, __text_end; +extern int __rodata_start, __rodata_end; +extern int __data_start, __data_end; + +#ifdef DEBUG +int debug = 1; +#else +int debug = 0; +#endif + +void log_kernel_start(){ + if(debug == 0) return; + printf("text_start=%p, text_end=%p, text_size=%u\r\n", \ + &__text_start, \ + &__text_end, \ + (uint64_t)&__text_end - (uint64_t)&__text_start + ); + + + printf("rodata_start=%p, rodata_end=%p, rodata_size=%u\r\n", \ + &__rodata_start, \ + &__rodata_end, \ + (uint64_t)&__rodata_end - (uint64_t)&__rodata_start + ); + + printf("data_start=%p, data_end=%p, data_size=%u\r\n", \ + &__data_start, \ + &__data_end, \ + (uint64_t)&__data_end - (uint64_t)&__data_start + ); + + printf("bss_start=%p, bss_end=%p, bss_size=%u\r\n", \ + &__bss_start, \ + &__bss_end, \ + (uint64_t)&__bss_end - (uint64_t)&__bss_start + ); + +} diff --git a/lab1/include/debug/debug.h b/lab1/include/debug/debug.h new file mode 100644 index 000000000..5f96a0f1e --- /dev/null +++ b/lab1/include/debug/debug.h @@ -0,0 +1,16 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "utils.h" + +#define DEBUG_KERNEL_START() log_kernel_start() +#define LOG(fmt, ...) \ + if(debug) \ + printf("[%s/%s:%d] " fmt "\r\n" , __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) + + + +extern void log_kernel_start(void); + +extern int debug; +#endif diff --git a/lab1/include/init/kernel_init.h b/lab1/include/init/kernel_init.h new file mode 100644 index 000000000..1f10f2d49 --- /dev/null +++ b/lab1/include/init/kernel_init.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_INIT_H +#define _KERNEL_INIT_H + +extern void kernel_init(); + +#endif diff --git a/lab1/include/kernel/reboot.h b/lab1/include/kernel/reboot.h new file mode 100644 index 000000000..cc8e8730b --- /dev/null +++ b/lab1/include/kernel/reboot.h @@ -0,0 +1,16 @@ +#ifndef _REBOOT_H_ +#define _REBOOT_H_ + +#include "peripherals/iomapping.h" + +#define PM_WDOG_RESET 0000000000 +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +extern void reboot(int tick); + +#endif diff --git a/lab1/include/kernel/shell.h b/lab1/include/kernel/shell.h new file mode 100644 index 000000000..756bd672f --- /dev/null +++ b/lab1/include/kernel/shell.h @@ -0,0 +1,6 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ + +void simple_shell(void); + +#endif diff --git a/lab1/include/lib/print.h b/lab1/include/lib/print.h new file mode 100644 index 000000000..791dab44a --- /dev/null +++ b/lab1/include/lib/print.h @@ -0,0 +1,10 @@ +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#include "types.h" + +int32_t printf(char *, ...); +int32_t putchar(uint8_t); +int32_t getchar(); + +#endif diff --git a/lab1/include/lib/string.h b/lab1/include/lib/string.h new file mode 100644 index 000000000..bead2e26f --- /dev/null +++ b/lab1/include/lib/string.h @@ -0,0 +1,14 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#include "types.h" + +extern char * itoa(int32_t, char*, uint32_t); +extern char * utoa(uint32_t, char*, uint32_t); +extern char * ltoa(int64_t, char*, uint32_t); +extern char * ultoa(uint64_t, char*, uint32_t); +extern int32_t strcmp(char*, char*); +extern void* memcpy(void*, const void*, size_t); +extern void* memset(void*, int, size_t); + +#endif diff --git a/lab1/include/peripherals/iomapping.h b/lab1/include/peripherals/iomapping.h new file mode 100644 index 000000000..b99ae5860 --- /dev/null +++ b/lab1/include/peripherals/iomapping.h @@ -0,0 +1,79 @@ +#ifndef _IOMAPPING_H_ +#define _IOMAPPING_H_ + + +/* Physical addresses range from 0x3F000000 to 0x3FFFFFFF for peripherals */ +#define IO_BASE 0x3F000000 + +/* Register's offset of GPIO */ +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL1 (IO_BASE + 0x200004) +#define GPFSEL2 (IO_BASE + 0x200008) +#define GPFSEL3 (IO_BASE + 0x20000C) +#define GPFSEL4 (IO_BASE + 0x200010) +#define GPFSEL5 (IO_BASE + 0x200014) +#define GPSET0 (IO_BASE + 0x20001C) +#define GPSET1 (IO_BASE + 0x200020) +#define GPCLR0 (IO_BASE + 0x200028) +#define GPCLR1 (IO_BASE + 0x20002C) +#define GPLEV0 (IO_BASE + 0x200034) +#define GPLEV1 (IO_BASE + 0x200038) +#define GPEDS0 (IO_BASE + 0x200040) +#define GPEDS1 (IO_BASE + 0x200044) +#define GPREN0 (IO_BASE + 0x20004C) +#define GPREN1 (IO_BASE + 0x200050) +#define GPFEN0 (IO_BASE + 0x200058) +#define GPFEN1 (IO_BASE + 0x20005C) +#define GPHEN0 (IO_BASE + 0x200064) +#define GPHEN1 (IO_BASE + 0x200068) +#define GPLEN0 (IO_BASE + 0x200070) +#define GPLEN1 (IO_BASE + 0x200074) +#define GPAREN0 (IO_BASE + 0x20007C) +#define GPAREN1 (IO_BASE + 0x200080) +#define GPAFEN0 (IO_BASE + 0x200088) +#define GPAFEN1 (IO_BASE + 0x20008C) +#define GPPUD (IO_BASE + 0x200094) +#define GPPUDCLK0 (IO_BASE + 0x200098) +#define GPPUDCLK1 (IO_BASE + 0x20009C) + + +/* Register's offset of UART and SPI */ +#define AUX_IRQ (IO_BASE + 0x215000) +#define AUX_ENABLES (IO_BASE + 0x215004) +#define AUX_MU_IO_REG (IO_BASE + 0x215040) +#define AUX_MU_IER_REG (IO_BASE + 0x215044) +#define AUX_MU_IIR_REG (IO_BASE + 0x215048) +#define AUX_MU_LCR_REG (IO_BASE + 0x21504C) +#define AUX_MU_MCR_REG (IO_BASE + 0x215050) +#define AUX_MU_LSR_REG (IO_BASE + 0x215054) +#define AUX_MU_MSR_REG (IO_BASE + 0x215058) +#define AUX_MU_SCRATCH (IO_BASE + 0x21505C) +#define AUX_MU_CNTL_REG (IO_BASE + 0x215060) +#define AUX_MU_STAT_REG (IO_BASE + 0x215064) +#define AUX_MU_BAUD_REG (IO_BASE + 0x215068) +#define AUX_SPI0_CNTL0_REG (IO_BASE + 0x215080) +#define AUX_SPI0_CNTL1_REG (IO_BASE + 0x215084) +#define AUX_SPI0_STAT_REG (IO_BASE + 0x215088) +#define AUX_SPI0_IO_REG (IO_BASE + 0x215090) +#define AUX_SPI0_PEEK_REG (IO_BASE + 0x215094) +#define AUX_SPI1_CNTL0_REG (IO_BASE + 0x2150C0) +#define AUX_SPI1_CNTL1_REG (IO_BASE + 0x2150C4) +#define AUX_SPI1_STAT_REG (IO_BASE + 0x2150C8) +#define AUX_SPI1_IO_REG (IO_BASE + 0x2150D0) +#define AUX_SPI1_PEEK_REG (IO_BASE + 0x2150D4) + +// mailbox register base address +#define MBOX_REG (IO_BASE + 0xB880) + +// watch dog +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_RSTC (IO_BASE + 0x10001c) +#define PM_WDOG (IO_BASE + 0x100024) + +#define IO_MMIO_write32(addr, val) *(uint32_t*)addr = val +#define IO_MMIO_read32(addr) *(uint32_t*)addr + + +#endif + diff --git a/lab1/include/peripherals/mailbox.h b/lab1/include/peripherals/mailbox.h new file mode 100644 index 000000000..b37243d21 --- /dev/null +++ b/lab1/include/peripherals/mailbox.h @@ -0,0 +1,172 @@ +#ifndef _MAILBOX_H_ +#define _MAILBOX_H_ + +#include "types.h" + +#define MBOX_CHANNEL_POWER 0 +#define MBOX_CHANNEL_FRAME_BUF 1 +#define MBOX_CHANNEL_VIRTUAL_UART 2 +#define MBOX_CHANNEL_VCHIQ 3 +#define MBOX_CHANNEL_LEDS 4 +#define MBOX_CHANNEL_BUTTONS 5 +#define MBOX_CHANNEL_TOUCH_SCREEN 6 +#define MBOX_CHANNEL_UNKOWN 7 +#define MBOX_CHANNEL_PROPERTY_TAGS 8 + +enum MBOX_PROPERTY_STATUS { + MBOX_STATUS_REQUEST = 0, + MBOX_STATUS_SUCCESS = 0x80000000, + MBOX_STATUS_ERROR = 0x80000001, +}; + +enum MBOX_PROPERTY_TAG{ + MBOX_PROPERTY_END = 0, + MBOX_GET_FIRMWARE_REVISION = 0x00000001, + + MBOX_SET_CURSOR_INFO = 0x00008010, + MBOX_SET_CURSOR_STATE = 0x00008011, + + MBOX_GET_BOARD_MODEL = 0x00010001, + MBOX_GET_BOARD_REVISION = 0x00010002, + MBOX_GET_BOARD_MAC_ADDRESS = 0x00010003, + MBOX_GET_BOARD_SERIAL = 0x00010004, + MBOX_GET_ARM_MEMORY = 0x00010005, + MBOX_GET_VC_MEMORY = 0x00010006, + MBOX_GET_CLOCKS = 0x00010007, + MBOX_GET_POWER_STATE = 0x00020001, + MBOX_GET_TIMING = 0x00020002, + MBOX_SET_POWER_STATE = 0x00028001, + MBOX_GET_CLOCK_STATE = 0x00030001, + MBOX_GET_CLOCK_RATE = 0x00030002, + MBOX_GET_VOLTAGE = 0x00030003, + MBOX_GET_MAX_CLOCK_RATE = 0x00030004, + MBOX_GET_MAX_VOLTAGE = 0x00030005, + MBOX_GET_TEMPERATURE = 0x00030006, + MBOX_GET_MIN_CLOCK_RATE = 0x00030007, + MBOX_GET_MIN_VOLTAGE = 0x00030008, + MBOX_GET_TURBO = 0x00030009, + MBOX_GET_MAX_TEMPERATURE = 0x0003000a, + MBOX_GET_STC = 0x0003000b, + MBOX_ALLOCATE_MEMORY = 0x0003000c, + MBOX_LOCK_MEMORY = 0x0003000d, + MBOX_UNLOCK_MEMORY = 0x0003000e, + MBOX_RELEASE_MEMORY = 0x0003000f, + MBOX_EXECUTE_CODE = 0x00030010, + MBOX_EXECUTE_QPU = 0x00030011, + MBOX_SET_ENABLE_QPU = 0x00030012, + MBOX_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, + MBOX_GET_EDID_BLOCK = 0x00030020, + MBOX_GET_CUSTOMER_OTP = 0x00030021, + MBOX_GET_DOMAIN_STATE = 0x00030030, + MBOX_SET_CLOCK_STATE = 0x00038001, + MBOX_SET_CLOCK_RATE = 0x00038002, + MBOX_SET_VOLTAGE = 0x00038003, + MBOX_SET_TURBO = 0x00038009, + MBOX_SET_CUSTOMER_OTP = 0x00038021, + MBOX_SET_DOMAIN_STATE = 0x00038030, + MBOX_GET_GPIO_STATE = 0x00030041, + MBOX_SET_GPIO_STATE = 0x00038041, + MBOX_SET_SDHOST_CLOCK = 0x00038042, + MBOX_GET_GPIO_CONFIG = 0x00030043, + MBOX_SET_GPIO_CONFIG = 0x00038043, + MBOX_GET_PERIPH_REG = 0x00030045, + MBOX_SET_PERIPH_REG = 0x00038045, + + + /* Dispmanx TAGS */ + MBOX_FRAMEBUFFER_ALLOCATE = 0x00040001, + MBOX_FRAMEBUFFER_BLANK = 0x00040002, + MBOX_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, + MBOX_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, + MBOX_FRAMEBUFFER_GET_DEPTH = 0x00040005, + MBOX_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006, + MBOX_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007, + MBOX_FRAMEBUFFER_GET_PITCH = 0x00040008, + MBOX_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, + MBOX_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, + MBOX_FRAMEBUFFER_GET_PALETTE = 0x0004000b, + MBOX_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, + MBOX_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010, + MBOX_FRAMEBUFFER_RELEASE = 0x00048001, + MBOX_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, + MBOX_FRAMEBUFFER_TEST_DEPTH = 0x00044005, + MBOX_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006, + MBOX_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, + MBOX_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, + MBOX_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, + MBOX_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, + MBOX_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, + MBOX_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, + MBOX_FRAMEBUFFER_SET_DEPTH = 0x00048005, + MBOX_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006, + MBOX_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007, + MBOX_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + MBOX_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + MBOX_FRAMEBUFFER_SET_PALETTE = 0x0004800b, + MBOX_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + MBOX_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, + MBOX_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + MBOX_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + + MBOX_VCHIQ_INIT = 0x00048010, + + MBOX_GET_COMMAND_LINE = 0x00050001, + MBOX_GET_DMA_CHANNELS = 0x00060001, +}; +/* + * Mailbox Read/Write Peek Sender Status Config + * 0 0x00 0x10 0x14 0x18 0x1c + * 1 0x20 0x30 0x34 0x38 0x3c + */ + +#define MBOX_READ_CHANNEL_MASK 15 +#define MBOX_WRITE_CHANNEL_MASK 15 +#define MBOX_WRITE_ADDR_MASK (~15) +#define MBOX_READ_ADDR_MASK (~15) +#define MBOX_STATUS_FULL_MASK 0x80000000 +#define MBOX_STATUS_EMPTY_MASK 0x40000000 +typedef struct{ + uint32_t read; + uint32_t unused[5]; + uint32_t status; + uint32_t config; + uint32_t write; +}__attribute__((packed)) MBox_register; + +/* 0 4 8 12 16 20 24 28 32 + +---------------------------------------------------------------+ +0x00 | Buffer Size | + +---------------------------------------------------------------+ +0x04 | Request/Response Code | + +---------------------------------------------------------------+ +0x08 | Tags | +... \\ \\ +0xXX | Tags | + +---------------------------------------------------------------+ +0xXX+4 | End Tag (0) | + +---------------------------------------------------------------+ +0xXX+8 | Padding | +... \\ \\ +0xXX+16| Padding | + +---------------------------------------------------------------+ +*/ +#define MBOX_TAG_REQUEST 0 +typedef struct{ + uint32_t id; + uint32_t value_size; + uint32_t code; + uint8_t values[0]; +}MBox_tag; + +typedef struct{ + uint32_t buf_size; + uint32_t code; + uint8_t buf[0]; +}MBox_buffer; + +extern void MBox_get_board_revision(uint32_t*); +extern void MBox_get_arm_memory(uint32_t*); + +#endif diff --git a/lab1/include/peripherals/mini_uart.h b/lab1/include/peripherals/mini_uart.h new file mode 100644 index 000000000..f640d0cac --- /dev/null +++ b/lab1/include/peripherals/mini_uart.h @@ -0,0 +1,19 @@ +#ifndef _MINI_UART_H_ +#define _MINI_UART_H_ + +#include "types.h" + +#define SYSTEM_CLOCK_RATE (250000000) +#define BAUD_RATE 115200 +#define BAUD_RATE_REG (SYSTEM_CLOCK_RATE / (8 * BAUD_RATE) - 1) + +extern void mini_uart_init(void); +extern uint8_t mini_uart_read(void); +extern void mini_uart_write(uint8_t); +extern ssize_t write_bytes(uint8_t *, size_t); +extern void write_str(char *); +extern void write_hex(uint8_t); + + + +#endif diff --git a/lab1/include/types.h b/lab1/include/types.h new file mode 100644 index 000000000..74cf56150 --- /dev/null +++ b/lab1/include/types.h @@ -0,0 +1,16 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; +#endif diff --git a/lab1/include/utils.h b/lab1/include/utils.h new file mode 100644 index 000000000..342be57c0 --- /dev/null +++ b/lab1/include/utils.h @@ -0,0 +1,7 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include "lib/print.h" +#include "lib/string.h" + +#endif diff --git a/lab1/init/Makefile b/lab1/init/Makefile new file mode 100644 index 000000000..e5b218aa8 --- /dev/null +++ b/lab1/init/Makefile @@ -0,0 +1,24 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + kernel_init.o + +all: $(OBJECTS) + +%.o: %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab1/init/kernel_init.c b/lab1/init/kernel_init.c new file mode 100644 index 000000000..726d0d868 --- /dev/null +++ b/lab1/init/kernel_init.c @@ -0,0 +1,7 @@ +#include "types.h" +#include "peripherals/mini_uart.h" + +void kernel_init(void){ + mini_uart_init(); + return; +} diff --git a/lab1/kernel/Makefile b/lab1/kernel/Makefile new file mode 100644 index 000000000..939531ce7 --- /dev/null +++ b/lab1/kernel/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + shell.o \ + reboot.o \ + main.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab1/kernel/main.c b/lab1/kernel/main.c new file mode 100644 index 000000000..e5fc6f926 --- /dev/null +++ b/lab1/kernel/main.c @@ -0,0 +1,13 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "init/kernel_init.h" +#include "utils.h" +#include "debug/debug.h" +#include "kernel/shell.h" + +void kernel_main(void){ + kernel_init(); + DEBUG_KERNEL_START(); + + simple_shell(); +} diff --git a/lab1/kernel/reboot.c b/lab1/kernel/reboot.c new file mode 100644 index 000000000..2511cc06e --- /dev/null +++ b/lab1/kernel/reboot.c @@ -0,0 +1,14 @@ +#include "types.h" +#include "peripherals/iomapping.h" +#include "kernel/reboot.h" + +void reboot(int ticks){ + unsigned int pm_rstc,pm_wdog; + pm_rstc = IO_MMIO_read32(PM_RSTC); + + pm_wdog = PM_PASSWORD | (ticks & PM_WDOG_TIME_SET); + pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; + + IO_MMIO_write32(PM_RSTC, pm_rstc); + IO_MMIO_write32(PM_WDOG, pm_wdog); +} diff --git a/lab1/kernel/shell.c b/lab1/kernel/shell.c new file mode 100644 index 000000000..1725bed26 --- /dev/null +++ b/lab1/kernel/shell.c @@ -0,0 +1,52 @@ +#include "types.h" +#include "utils.h" +#include "peripherals/mailbox.h" +#include "kernel/reboot.h" +char *miku_ascii = "⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀\r\n⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁\r\n⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀\r\n⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀\r\n⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀\r\n⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀\r\n⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀\r\n⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀\r\n⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀\r\n⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀\r\n⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀"; +char buf[0x2000]; +void simple_shell(){ + unsigned int i; + char ch; + printf(miku_ascii); + printf("\r\n\r\n"); + while(1){ + i = 0; + buf[0] = '\0'; + printf("# "); + // read command + while(1){ + ch = (char)getchar(); + if(ch == '\r'){ + printf("\r\n"); + buf[i] = '\0'; + break; + }else if(ch != '\n'){ + putchar(ch); + buf[i] = ch; + i++; + } + } + + // match comman + if(strcmp(buf, "help") == 0){ + printf("help : print this help menu\r\n"); + printf("hello : print Hello World!\r\n"); + printf("info : print hardware infomation\r\n"); + printf("reboot : reboot the device\r\n"); + }else if(strcmp(buf, "hello") == 0){ + printf("Hello World!\r\n"); + }else if(strcmp(buf, "info") == 0){ + uint32_t tmp[2]; + MBox_get_board_revision(tmp); + printf("Board revision: 0x%x\r\n", tmp[0]); + + MBox_get_arm_memory(tmp); + printf("Memory base: 0x%x\r\n", tmp[0]); + printf("Memory size: 0x%x\r\n", tmp[1]); + }else if(strcmp(buf, "reboot") == 0){ + printf("Start rebooting...\r\n"); + reboot(100); + while(1); + } + } +} diff --git a/lab1/lib/Makefile b/lab1/lib/Makefile new file mode 100644 index 000000000..d895559ac --- /dev/null +++ b/lab1/lib/Makefile @@ -0,0 +1,28 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + print.o \ + string.o + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab1/lib/print.c b/lab1/lib/print.c new file mode 100644 index 000000000..c315cd642 --- /dev/null +++ b/lab1/lib/print.c @@ -0,0 +1,109 @@ +#include "lib/print.h" +#include "lib/string.h" +#include "types.h" +#include "peripherals/mini_uart.h" +#include + +int32_t printf(char *fmt, ...){ + uint32_t uval; + int32_t val; + int64_t lval; + char str[64], ch; + char* p, *s; + void* addr; + volatile int32_t count = 0; + va_list ap; + + va_start(ap, fmt); + + while(*fmt){ + char c = *fmt++; + if(c == '%'){ + c = *fmt++; + switch(c){ + case 'u': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'd': + val = va_arg(ap, int); + itoa(val, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'l': + lval = va_arg(ap, int64_t); + ltoa(lval, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'c': + ch = va_arg(ap, int); + mini_uart_write(ch); + count++; + break; + case 'p': + addr = va_arg(ap, void*); + utoa((uint64_t)addr, str, 16); + + mini_uart_write('0'); + mini_uart_write('x'); + count += 2; + + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + + break; + case 'x': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 16); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + + break; + case 's': + s = va_arg(ap, char*); + p = s; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + default: + case '%': + mini_uart_write('%'); + count++; + } + }else{ + mini_uart_write(c); + count++; + } + } + va_end(ap); + return count; +} +int32_t putchar(uint8_t ch){ + mini_uart_write(ch); + return ch; +} +int32_t getchar(){ + return mini_uart_read(); +} diff --git a/lab1/lib/string.c b/lab1/lib/string.c new file mode 100644 index 000000000..28d648c63 --- /dev/null +++ b/lab1/lib/string.c @@ -0,0 +1,167 @@ +#include "lib/string.h" +#include "types.h" +char *int_table = "0123456789"; +char *hex_table = "0123456789abcdef"; +char * itoa(int32_t value, char* str, uint32_t base){ + char buf[32]; + uint32_t val; + volatile int i = 0, j = 0; + + switch(base){ + case 16: + val = (uint32_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} + +char * utoa(uint32_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint32_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} +char * ltoa(int64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val; + + switch(base){ + case 16: + val = (uint64_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +char * ultoa(uint64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +int32_t strcmp(char* str1, char* str2){ + do{ + if(*str1 > *str2) return 1; + else if(*str1 < *str2) return -1; + str1++;str2++; + }while(*str1 != '\0' || *str2 != '\0'); + return 0; + +} +void* memcpy(void* dst, const void* src, size_t n){ + const uint8_t* ps = src; + uint8_t*pd = dst; + for(size_t i = 0 ; i < n ; i++) pd[i] = ps[i]; + return dst; +} +void* memset(void* s, int c, size_t n){ + uint8_t* ps = s; + for(size_t i = 0 ; i < n ; i++) ps[i] = c; + return s; +} diff --git a/lab1/linker.ld b/lab1/linker.ld new file mode 100644 index 000000000..87654f5bc --- /dev/null +++ b/lab1/linker.ld @@ -0,0 +1,39 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; +} diff --git a/lab1/peripherals/Makefile b/lab1/peripherals/Makefile new file mode 100644 index 000000000..50b5d0780 --- /dev/null +++ b/lab1/peripherals/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + mini_uart.o \ + mailbox.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab1/peripherals/mailbox.c b/lab1/peripherals/mailbox.c new file mode 100644 index 000000000..f5e84baaa --- /dev/null +++ b/lab1/peripherals/mailbox.c @@ -0,0 +1,117 @@ +#include "types.h" +#include "debug/debug.h" +#include "peripherals/mailbox.h" +#include "peripherals/iomapping.h" + +static uint32_t MBox_buf[4096] __attribute__((aligned(16))); + +static uint32_t MBox_read(int channel){ + int ch, data; + + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_EMPTY_MASK); + + data = mbox_reg->read; + ch = data & MBOX_WRITE_CHANNEL_MASK; + if(ch == channel){ + LOG("MBox read address: %p", data & MBOX_READ_ADDR_MASK); + return (data & MBOX_READ_ADDR_MASK); + } + LOG("Leave"); + return 0; +} + +static void MBox_write(uint32_t data, int channel){ + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_FULL_MASK); + + mbox_reg->write = data | channel; + LOG("Leave"); +} + +static uint32_t MBox_process(uint8_t* tags, size_t tags_size){ + LOG("Enter"); + MBox_buffer* mbuf = (MBox_buffer*)MBox_buf; + // set buffer header + mbuf->buf_size = tags_size + 12; + mbuf->code = MBOX_STATUS_REQUEST; + + // copy tags to buffer + memcpy(mbuf->buf, tags, tags_size); + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + LOG("mbuf->buf: %p", mbuf->buf); + LOG("mbuf->buf + tags_size: %p", mbuf->buf + tags_size); + // end of MBox_buf + memset(mbuf->buf + tags_size, 0, 4); + + pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + // write to mailbox + MBox_write((uint32_t)MBox_buf, MBOX_CHANNEL_PROPERTY_TAGS); + + // read from mailbox + uint32_t result = MBox_read(MBOX_CHANNEL_PROPERTY_TAGS); + + + LOG("Leave"); + return result; +} +void MBox_get_board_revision(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 4]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_BOARD_REVISION; + tag->value_size = 4; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer *)MBox_process(buf, sizeof(MBox_tag) + 4); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + *ret = ((uint32_t*)tag->values)[0]; + LOG("Leave"); +} +void MBox_get_arm_memory(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 8]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_ARM_MEMORY; + tag->value_size = 8; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + ((uint32_t*)tag->values)[1] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer *)MBox_process(buf, sizeof(MBox_tag) + 8); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + ret[0] = ((uint32_t*)tag->values)[0]; + ret[1] = ((uint32_t*)tag->values)[1]; + LOG("Leave"); +} + + diff --git a/lab1/peripherals/mini_uart.c b/lab1/peripherals/mini_uart.c new file mode 100644 index 000000000..a11fee682 --- /dev/null +++ b/lab1/peripherals/mini_uart.c @@ -0,0 +1,85 @@ +#include "types.h" +#include "peripherals/iomapping.h" +#include "peripherals/mini_uart.h" +void delay_cycles(uint64_t n){ + for(register uint64_t i = 0 ; i < n ; i++) asm volatile("nop"); +} + +/** + * @brief Enable UART + */ +void mini_uart_init(void){ + // GPIO 14 & 15 take function 0 + // Read out GPFSEL1 register + uint32_t tmp = IO_MMIO_read32(GPFSEL1); + + // Set GPIO 14 & 15 function bits + tmp &= ~(0b111111 << 12); + tmp |= 0b010010 << 12; + IO_MMIO_write32(GPFSEL1, tmp); + + + // disable pull-up/down of GPIO 14 & 15 + // Write to GPPUD to set the required control signal + IO_MMIO_write32(GPPUD, 0); + + // Wait 150 cycles – this provides the required set-up time for the control signal + delay_cycles(150); + + // Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to modify + IO_MMIO_write32(GPPUDCLK0, (1 << 14) | (1 << 15)); + + // Wait 150 cycles – this provides the required hold time for the control signal + delay_cycles(150); + + // Write to GPPUD to remove the control signa + IO_MMIO_write32(GPPUD, 0); + + // Write to GPPUDCLK0/1 to remove the clock + IO_MMIO_write32(GPPUDCLK0, 0); + + // Initialize Auxiliary peripherals Register + // Mini UART enable + IO_MMIO_write32(AUX_ENABLES, 1); + + // To disable auto flow control and disable receiver and transmitter, set control register to 0 + IO_MMIO_write32(AUX_MU_CNTL_REG, 0); + + // Disable mini UART's interrupt + IO_MMIO_write32(AUX_MU_IER_REG, 0); + + // Set UART to 8-bit mode + IO_MMIO_write32(AUX_MU_LCR_REG, 3); + + // To indicate that our UART is able to receive data, set RTS line to be always high + IO_MMIO_write32(AUX_MU_MCR_REG, 0); + + // Set Baud rate to 115200 + IO_MMIO_write32(AUX_MU_BAUD_REG, BAUD_RATE_REG); + + // Start UART + IO_MMIO_write32(AUX_MU_CNTL_REG, 3); + return; +} + +uint8_t mini_uart_read(void){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & 0x1)); + return IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; +} + +void mini_uart_write(uint8_t val){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & (0x1 << 5))); + IO_MMIO_write32(AUX_MU_IO_REG, val); +} + +ssize_t write_bytes(uint8_t* buf, size_t n){ + for(uint64_t i = 0 ; i < n ; i++) mini_uart_write(buf[i]); + return n; +} + +void write_str(char* buf){ + while(*buf) mini_uart_write((uint8_t)*buf++); + return; +} + + diff --git a/lab1/tools/AUX_PERIPHERALS b/lab1/tools/AUX_PERIPHERALS new file mode 100644 index 000000000..324eb3019 --- /dev/null +++ b/lab1/tools/AUX_PERIPHERALS @@ -0,0 +1,23 @@ +0x7E215000 AUX_IRQ Auxiliary Interrupt status 3 +0x7E215004 AUX_ENABLES Auxiliary enables 3 +0x7E215040 AUX_MU_IO_REG Mini Uart I/O Data 8 +0x7E215044 AUX_MU_IER_REG Mini Uart Interrupt Enable 8 +0x7E215048 AUX_MU_IIR_REG Mini Uart Interrupt Identify 8 +0x7E21504C AUX_MU_LCR_REG Mini Uart Line Control 8 +0x7E215050 AUX_MU_MCR_REG Mini Uart Modem Control 8 +0x7E215054 AUX_MU_LSR_REG Mini Uart Line Status 8 +0x7E215058 AUX_MU_MSR_REG Mini Uart Modem Status 8 +0x7E21505C AUX_MU_SCRATCH Mini Uart Scratch 8 +0x7E215060 AUX_MU_CNTL_REG Mini Uart Extra Control 8 +0x7E215064 AUX_MU_STAT_REG Mini Uart Extra Status 32 +0x7E215068 AUX_MU_BAUD_REG Mini Uart Baudrate 16 +0x7E215080 AUX_SPI0_CNTL0_REG SPI 1 Control register 0 32 +0x7E215084 AUX_SPI0_CNTL1_REG SPI 1 Control register 1 8 +0x7E215088 AUX_SPI0_STAT_REG SPI 1 Status 32 +0x7E215090 AUX_SPI0_IO_REG SPI 1 Data 32 +0x7E215094 AUX_SPI0_PEEK_REG SPI 1 Peek 16 +0x7E2150C0 AUX_SPI1_CNTL0_REG SPI 2 Control register 0 32 +0x7E2150C4 AUX_SPI1_CNTL1_REG SPI 2 Control register 1 8 +0x7E2150C8 AUX_SPI1_STAT_REG SPI 2 Status 32 +0x7E2150D0 AUX_SPI1_IO_REG SPI 2 Data 32 +0x7E2150D4 AUX_SPI1_PEEK_REG SPI 2 Peek 16 diff --git a/lab1/tools/GPIO b/lab1/tools/GPIO new file mode 100644 index 000000000..ad2b10794 --- /dev/null +++ b/lab1/tools/GPIO @@ -0,0 +1,43 @@ +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200004 GPFSEL1 GPIO Function Select 1 32 R/W +0x7E200008 GPFSEL2 GPIO Function Select 2 32 R/W +0x7E20000C GPFSEL3 GPIO Function Select 3 32 R/W +0x7E200010 GPFSEL4 GPIO Function Select 4 32 R/W +0x7E200014 GPFSEL5 GPIO Function Select 5 32 R/W +0x7E200018 - Reserved - - +0x7E20001C GPSET0 GPIO Pin Output Set 0 32 W +0x7E200020 GPSET1 GPIO Pin Output Set 1 32 W +0x7E200024 - Reserved - - +0x7E200028 GPCLR0 GPIO Pin Output Clear 0 32 W +0x7E20002C GPCLR1 GPIO Pin Output Clear 1 32 W +0x7E200030 - Reserved - - +0x7E200034 GPLEV0 GPIO Pin Level 0 32 R +0x7E200038 GPLEV1 GPIO Pin Level 1 32 R +0x7E20003C - Reserved - - +0x7E200040 GPEDS0 GPIO Pin Event Detect Status 0 32 R/W +0x7E200044 GPEDS1 GPIO Pin Event Detect Status 1 32 R/W +0x7E200048 - Reserved - - +0x7E20004C GPREN0 GPIO Pin Rising Edge Detect Enable 0 32 R/W +0x7E200050 GPREN1 GPIO Pin Rising Edge Detect Enable 1 32 R/W +0x7E200054 - Reserved - - +0x7E200058 GPFEN0 GPIO Pin Falling Edge Detect Enable 0 32 R/W +0x7E20005C GPFEN1 GPIO Pin Falling Edge Detect Enable 1 32 R/W +0x7E200060 - Reserved - - +0x7E200064 GPHEN0 GPIO Pin High Detect Enable 0 32 R/W +0x7E200068 GPHEN1 GPIO Pin High Detect Enable 1 32 R/W +0x7E20006C - Reserved - - +0x7E200070 GPLEN0 GPIO Pin Low Detect Enable 0 32 R/W +0x7E200074 GPLEN1 GPIO Pin Low Detect Enable 1 32 R/W +0x7E200078 - Reserved - - +0x7E20007C GPAREN0 GPIO Pin Async. Rising Edge Detect 0 32 R/W +0x7E200080 GPAREN1 GPIO Pin Async. Rising Edge Detect 1 32 R/W +0x7E200084 - Reserved - - +0x7E200088 GPAFEN0 GPIO Pin Async. Falling Edge Detect 0 32 R/W +0x7E20008C GPAFEN1 GPIO Pin Async. Falling Edge Detect 1 32 R/W +0x7E200090 - Reserved - - +0x7E200094 GPPUD GPIO Pin Pull-up/down Enable 32 R/W +0x7E200098 GPPUDCLK0 GPIO Pin Pull-up/down Enable Clock 0 32 R/W +0x7E20009C GPPUDCLK1 GPIO Pin Pull-up/down Enable Clock 1 32 R/W +0x7E2000A0 - Reserved - - +0x7E2000B0 - Test 4 R/W diff --git a/lab1/tools/gen.sh b/lab1/tools/gen.sh new file mode 100755 index 000000000..235b38c28 --- /dev/null +++ b/lab1/tools/gen.sh @@ -0,0 +1,24 @@ +#! /bin/sh +BUS_IO_BASE=0x7E000000 +PHY_IO_BASE=0x3F000000 +echo "/* Register's offset of GPIO */" +grep -v " - " GPIO | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + +echo "" +echo "" +echo "/* Register's offset of UART and SPI */" +grep -v " - " AUX_PERIPHERALS | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + + diff --git a/lab2/.gdb_history b/lab2/.gdb_history new file mode 100644 index 000000000..fdc5919d0 --- /dev/null +++ b/lab2/.gdb_history @@ -0,0 +1,256 @@ +c +c +quit +file ./build/bootloader.elf +target remote:1234 +target remote:1234 +b uart_recv_kernel +c +ni +x/i 0x601d4 +x *0x601f0 +x *0x601f0 +x 0x601f0 +c +target remote:1234 +target remote:1234 +c +ni +x/i 0x601f0 +x/i 0x6009c +x/i 0x601d4 +b* 0x601e4 +c +ni +si +ni +ni +x/i 0x601b0 +b* 0x601b4 +c +0x83000 +0x8300 +0x83000 +x/gx *0x83000 +x/gx *0x81000 +x/gx *0x80000 +ni +ni +target remote:1234 +target remote:1234 +c +c +ni +si +x/i 0x6015c +info reg x30 +x/i 0x601f4 +x/i 0x601f4 +ni +ni +x/i $x30 +info reg x30 +x/i 0x601b0 +ni +x/i 0x60180 +x/i 0x601b0 +b* 0x60180 +c +x/i 0x60180 +x/i 0x601f4 +ni +x/i 0x601b0 +b* 0x601bc +c +ni +info b +dle 5 +dle 5 +del 5 +del 4 +ni +x/i 0x601b0 +b* 0x601c4 +c +ni +x/i 0x601f4 +ni +info reg x30 +x/i 0x601f4 +ni +x/i 0x601f4 +ni +si +x/i write_str +target remote:1234 +target remote:1234 +c +x/i write_str +quit +file ./build/reboot.o +file ./build/bootloader.elf +target remote:1234 +b uart_recv_kernel +c +x/i +x/i $(pc) +x/i $pc +x/i 0x60400 +x/i 0x60000 +x/gx 0x60078 +target remote:1234 +target remote:1234 +ni +x/gx 0x80078 +x/gx 0x60078 +x/gx 0x80078 +file ./build/bootloader.elf +target remote:1234 +target remote:1234 +info b +del 1 +b uart_recv_kernel +c +target remote:1234 +target remote:1234 +mo +ni +file ./build/bootloader.elf +file ./build/bootloader.elf +target remote:1234 +ni +del 2 +b uart_recv_kernel +c +ni +c +target remote:1234 +target remote:1234 +b uart_recv_kernel +del 3 +c +info reg x30 +x/i 0x6002c +ni +x/i 0x6002c +info reg x30 +x/i 0x6002c +x/i 0x601c4 +x/gx 0x601fc +b* 0x601fc +c +ni +file ./build/kernel8.efl +file ./build/kernel8.elf +ni +x/i 0x80030 +b* 0x80034 +c +si +ni +si +ni +ni +quit +file ./build/bootloader.elf +target remote:1234 +ni +ni +ni +x/i 0x80070 +b *0x80074 +c +ni +b* 0x60038 +c +si +ni +x/i 0x601d4 +b* 0x60214 +c +target remote:1234 +target remote:1234 +ni +target remote:1234 +target remote:1234 +ni +c +ni +c +x/i mini_uart_read +ni +x/i 0x601d4 +b* 0x601d4 +c +ni +target remote:1234 +target remote:1234 +ni +x/gx 0x83000 +c +ni +x/gx 0x63000 +x/gx 0x83000 +target remote:1234 +c +x/gx 0x83000 +x/gx 0x63000 +b* 0x80060 +target remote:1234 +b* 0x80060 +c +ni +c +info b +del 5 +c +quit +b main +run +ni +x/gx 0x5555555592a0 +x/3gx 0x5555555592a0 - 0x10 +call malloc(8) +x/gx 0x5555555592c0 - 0x10 +call malloc(9) +x/gx 0x5555555592e0 - 0x10 +call malloc(10) +x/gx 0x555555559300 -0x10 +quit +file ./build/kernel8.img +file ./build/kernel8.elf +target remote:1234 +ni +b kernel_main +c +quit +file build/kernel8.elf +target remote:1234 +ni +ni +quit +file build/kernel8.elf +target remote:1234 +ni +ni +b* 0x80014 +c +ni +quit +target remote:1234 +ni +ni +x/i 0x80038 +b* 0x8003c +c +x regs +info reg +ni +ni +quit +target remote:1234 +b* 0x8003c +c +si +ni +quit diff --git a/lab2/Makefile b/lab2/Makefile new file mode 100644 index 000000000..4486cffb1 --- /dev/null +++ b/lab2/Makefile @@ -0,0 +1,95 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +override CFLAGS += \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin \ + +LDFLAGS ?= \ + -nostdlib \ + +CXXFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJDUMP = aarch64-linux-gnu-objdump +QEMU = qemu-system-aarch64 +RASPI_VER = raspi3b + + +LINKER_FILE = ./linker.ld +HEADERS = $(PWD)/include/ +OUTPUT = $(PWD)/build +KNAME = kernel8 +BNAME = bootloader + +LIBS = \ + $(OUTPUT)/print.o \ + $(OUTPUT)/string.o \ + $(OUTPUT)/list.o \ + $(OUTPUT)/cpio.o \ + $(OUTPUT)/simple_malloc.o \ + $(OUTPUT)/fdt_parse.o \ + +KOBJECTS = \ + $(OUTPUT)/start.o \ + $(OUTPUT)/mini_uart.o \ + $(OUTPUT)/mailbox.o \ + $(OUTPUT)/main.o \ + $(OUTPUT)/kernel_init.o \ + $(OUTPUT)/reboot.o \ + $(OUTPUT)/shell.o \ + $(OUTPUT)/debug.o \ + $(OUTPUT)/initrdfs.o \ + $(LIBS) + +BOBJECTS = \ + $(OUTPUT)/boot.o \ + $(OUTPUT)/uart_boot.o \ + $(OUTPUT)/mini_uart.o \ + $(OUTPUT)/debug.o \ + $(LIBS) + + +.PHONY: all start bootloader kernel end clean dump + + +all: start link bootloader kernel end + +start: + @echo "Start building kernel8.img" + + $(MAKE) -C boot OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C peripherals OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C init OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C kernel OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C lib OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C debug OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C fs OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + +link: $(OBJECTS) + $(LD) -T kernel/$(LINKER_FILE) -o $(OUTPUT)/$(KNAME).elf $(KOBJECTS) $(LDFLAGS) + $(LD) -T boot/$(LINKER_FILE) -o $(OUTPUT)/$(BNAME).elf $(BOBJECTS) $(LDFLAGS) + +bootloader: + $(OBJCOPY) -O binary $(OUTPUT)/$(BNAME).elf $(OUTPUT)/$(BNAME).img + +kernel: $(OUTPUT)/$(KNAME).elf + $(OBJCOPY) -O binary $(OUTPUT)/$(KNAME).elf $(OUTPUT)/$(KNAME).img + +end: + @echo "Finish building kernel8.img" + +dump: + $(OBJDUMP) -m aarch64 -b binary -D $(OUTPUT)/$(KNAME).img + +qemu-run: + sudo $(QEMU) -M $(RASPI_VER) -kernel $(OUTPUT)/$(KNAME).img -display none -serial null -serial stdio -initrd ./initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + +qemu-run-instr: + sudo $(QEMU) -M $(RASPI_VER) -kernel $(OUTPUT)/$(KNAME).img -display none -d in_asm + +clean: + rm $(OUTPUT)/* diff --git a/lab2/README.md b/lab2/README.md new file mode 100644 index 000000000..6e84d3737 --- /dev/null +++ b/lab2/README.md @@ -0,0 +1,15 @@ +# Requirements + +## Features + +- Basic Exercise 1 + - [x] UART Bootloader +- Basic Exercise 2 + - [x] Initial Ramdisk +- Basic Exercise 3 + - [x] Simple Allocator +- Advanced Exercise 1 + - [x] Bootloader Self Relocation +- Advanced Exercise 2 + - [x] Devicetree + diff --git a/lab2/bcm2710-rpi-3-b-plus.dtb b/lab2/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 000000000..6f9ef31cc Binary files /dev/null and b/lab2/bcm2710-rpi-3-b-plus.dtb differ diff --git a/lab2/boot/Makefile b/lab2/boot/Makefile new file mode 100644 index 000000000..b98c365cd --- /dev/null +++ b/lab2/boot/Makefile @@ -0,0 +1,28 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + boot.o \ + uart_boot.o + +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab2/boot/boot.S b/lab2/boot/boot.S new file mode 100644 index 000000000..b28524a42 --- /dev/null +++ b/lab2/boot/boot.S @@ -0,0 +1,84 @@ +.section ".text.boot" +.global _start +_start: +// x1 = current PC + offset to _dtb + adr x1, _dtb + str x0, [x1] + +// stack + adr x1, _start + mov sp, x1 + +// rebase boot loader to specific address +// indicated by linker script + bl rebase_bootloader + +// slave cpu should not sleep before bootloader finishes rebase +// Since if they wake up, there next instruction will be invalid instruction +rebase_entry: + // read cpu id, stop slave cores + // cpu id == 0 + // store pointer to dtb to _dtb + mrs x1, mpidr_el1 + and x1, x1, #0xff + + // cpu id > 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + + +master_core: +// stack + ldr x1, =_start + mov sp, x1 + +// recover dtb to x0 + adr x1, _dtb + ldr x0, [x1] + + +// jump to kernel_main + bl uart_recv_kernel + + b proc_hang + +// rebase our boot loader +rebase_bootloader: + // manipulate our return address ( x30 a.k.a LR ) to the rebased bootloader + // x19 = current PC + offset to _start + // x20 = absolute address ( _start ) that specify by linker script + adr x19, _start + ldr x20, =_start + sub x19, x19, x20 + sub lr , lr, x19 + + // x21 = absolute address ( __bootloader_start ) that specify by linker script + // x22 = current PC + offset to __bootloader_start ( In linker script ) + ldr x21, =__bootloader_start + adr x22, __bootloader_start + ldr x23, =__bootloader_size + // start rebasing bootloader +copy_bootloader: + cbz x23, end_rebase_bootloader + ldr x24, [x22], #8 + str x24, [x21], #8 + sub x23, x23, #8 + b copy_bootloader + +// Since ldr and str memory operation should obey 8 bytes alignment rule, the code here would failed on real device +// cbz x23, end_rebase_bootloader +// ldr x24, [x22], #1 +// str x24, [x21], #1 +// sub x23, x23, #1 +// b copy_bootloader + + + // return to rebased bootloader +end_rebase_bootloader: + ret + +.section ".data" +_dtb: .dword 0 diff --git a/lab2/boot/boot.o b/lab2/boot/boot.o new file mode 100644 index 000000000..3ce9ed4e9 Binary files /dev/null and b/lab2/boot/boot.o differ diff --git a/lab2/boot/linker.ld b/lab2/boot/linker.ld new file mode 100644 index 000000000..740945ab2 --- /dev/null +++ b/lab2/boot/linker.ld @@ -0,0 +1,43 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x60000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __bootloader_start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + __bootloader_end = .; + __bootloader_size = (__bootloader_end - __bootloader_start); +} diff --git a/lab2/boot/uart_boot.c b/lab2/boot/uart_boot.c new file mode 100644 index 000000000..fa0a9564c --- /dev/null +++ b/lab2/boot/uart_boot.c @@ -0,0 +1,47 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "utils.h" + +void recv_boot_header(){ + while('A' != mini_uart_read()); +} + +size_t recv_kernel_base(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +size_t recv_kernel_size(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +void recv_kernel(uint64_t base, size_t size){ + uint8_t *pb; + size_t i; + for(pb = (uint8_t*)base , i = 0 ; i < size ; i++){ + pb[i] = mini_uart_read(); + } +} +uint64_t uart_recv_kernel(uint64_t dtb){ + size_t size; + uint64_t base; + mini_uart_init(); + + recv_boot_header(); + printf("Receive A...\r\n"); + + base = recv_kernel_base(); + printf("Receive kernel base 0x%x...\r\n", base); + + size = recv_kernel_size(); + printf("Receive kernel size 0x%x...\r\n", size); + + recv_kernel(base, size); + printf("Jump to kernel iamge...\r\n"); + + delay_cycles(10000); + ((void (*)(uint64_t))base)(dtb); +} diff --git a/lab2/build/boot.o b/lab2/build/boot.o new file mode 100644 index 000000000..76a165ab4 Binary files /dev/null and b/lab2/build/boot.o differ diff --git a/lab2/build/bootloader.elf b/lab2/build/bootloader.elf new file mode 100755 index 000000000..54c836a88 Binary files /dev/null and b/lab2/build/bootloader.elf differ diff --git a/lab2/build/bootloader.img b/lab2/build/bootloader.img new file mode 100755 index 000000000..241a66b3d Binary files /dev/null and b/lab2/build/bootloader.img differ diff --git a/lab2/build/cpio.o b/lab2/build/cpio.o new file mode 100644 index 000000000..707e51c8b Binary files /dev/null and b/lab2/build/cpio.o differ diff --git a/lab2/build/debug.o b/lab2/build/debug.o new file mode 100644 index 000000000..60b499707 Binary files /dev/null and b/lab2/build/debug.o differ diff --git a/lab2/build/fdt_parse.o b/lab2/build/fdt_parse.o new file mode 100644 index 000000000..7e71e0d8c Binary files /dev/null and b/lab2/build/fdt_parse.o differ diff --git a/lab2/build/initrdfs.o b/lab2/build/initrdfs.o new file mode 100644 index 000000000..123230426 Binary files /dev/null and b/lab2/build/initrdfs.o differ diff --git a/lab2/build/kernel8.elf b/lab2/build/kernel8.elf new file mode 100755 index 000000000..8f328c88f Binary files /dev/null and b/lab2/build/kernel8.elf differ diff --git a/lab2/build/kernel8.img b/lab2/build/kernel8.img new file mode 100755 index 000000000..56ae6c9ad Binary files /dev/null and b/lab2/build/kernel8.img differ diff --git a/lab2/build/kernel_init.o b/lab2/build/kernel_init.o new file mode 100644 index 000000000..1d246756b Binary files /dev/null and b/lab2/build/kernel_init.o differ diff --git a/lab2/build/list.o b/lab2/build/list.o new file mode 100644 index 000000000..203193c42 Binary files /dev/null and b/lab2/build/list.o differ diff --git a/lab2/build/mailbox.o b/lab2/build/mailbox.o new file mode 100644 index 000000000..d2b06efc3 Binary files /dev/null and b/lab2/build/mailbox.o differ diff --git a/lab2/build/main.o b/lab2/build/main.o new file mode 100644 index 000000000..95659f059 Binary files /dev/null and b/lab2/build/main.o differ diff --git a/lab2/build/mini_uart.o b/lab2/build/mini_uart.o new file mode 100644 index 000000000..d823b9bb7 Binary files /dev/null and b/lab2/build/mini_uart.o differ diff --git a/lab2/build/print.o b/lab2/build/print.o new file mode 100644 index 000000000..c02ed0912 Binary files /dev/null and b/lab2/build/print.o differ diff --git a/lab2/build/reboot.o b/lab2/build/reboot.o new file mode 100644 index 000000000..b2e138124 Binary files /dev/null and b/lab2/build/reboot.o differ diff --git a/lab2/build/shell.o b/lab2/build/shell.o new file mode 100644 index 000000000..a5909fd2b Binary files /dev/null and b/lab2/build/shell.o differ diff --git a/lab2/build/simple_malloc.o b/lab2/build/simple_malloc.o new file mode 100644 index 000000000..964124e30 Binary files /dev/null and b/lab2/build/simple_malloc.o differ diff --git a/lab2/build/start.o b/lab2/build/start.o new file mode 100644 index 000000000..585b7781c Binary files /dev/null and b/lab2/build/start.o differ diff --git a/lab2/build/string.o b/lab2/build/string.o new file mode 100644 index 000000000..bbf3c3863 Binary files /dev/null and b/lab2/build/string.o differ diff --git a/lab2/build/uart_boot.o b/lab2/build/uart_boot.o new file mode 100644 index 000000000..4c8ec5293 Binary files /dev/null and b/lab2/build/uart_boot.o differ diff --git a/lab2/debug.sh b/lab2/debug.sh new file mode 100755 index 000000000..81d573d80 --- /dev/null +++ b/lab2/debug.sh @@ -0,0 +1,3 @@ +#!/bin/sh +make CFLAGS=-DDEBUG >/dev/null +make qemu-run diff --git a/lab2/debug/Makefile b/lab2/debug/Makefile new file mode 100644 index 000000000..22ac23500 --- /dev/null +++ b/lab2/debug/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + debug.o + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab2/debug/debug.c b/lab2/debug/debug.c new file mode 100644 index 000000000..233449e66 --- /dev/null +++ b/lab2/debug/debug.c @@ -0,0 +1,44 @@ +#include "types.h" +#include "utils.h" +#include "debug/debug.h" +extern int __bss_start, __bss_end; +extern int __text_start, __text_end; +extern int __rodata_start, __rodata_end; +extern int __data_start, __data_end; +extern int __heap_start; + +#ifdef DEBUG +int debug = 1; +#else +int debug = 0; +#endif + +void log_kernel_start(){ + if(debug == 0) return; + printf("text_start=%p, text_end=%p, text_size=%u\r\n", \ + &__text_start, \ + &__text_end, \ + (uint64_t)&__text_end - (uint64_t)&__text_start + ); + + + printf("rodata_start=%p, rodata_end=%p, rodata_size=%u\r\n", \ + &__rodata_start, \ + &__rodata_end, \ + (uint64_t)&__rodata_end - (uint64_t)&__rodata_start + ); + + printf("data_start=%p, data_end=%p, data_size=%u\r\n", \ + &__data_start, \ + &__data_end, \ + (uint64_t)&__data_end - (uint64_t)&__data_start + ); + + printf("bss_start=%p, bss_end=%p, bss_size=%u\r\n", \ + &__bss_start, \ + &__bss_end, \ + (uint64_t)&__bss_end - (uint64_t)&__bss_start + ); + printf("heap_start=%p\n", &__heap_start); + +} diff --git a/lab2/fs/Makefile b/lab2/fs/Makefile new file mode 100644 index 000000000..15fbb2fa3 --- /dev/null +++ b/lab2/fs/Makefile @@ -0,0 +1,24 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + initrdfs.o +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab2/fs/initrdfs.c b/lab2/fs/initrdfs.c new file mode 100644 index 000000000..7e28ebeb0 --- /dev/null +++ b/lab2/fs/initrdfs.c @@ -0,0 +1,69 @@ +#include "utils.h" +#include "types.h" +#include "debug/debug.h" +#include "peripherals/mini_uart.h" +static struct fentry * root; + +void initrdfs_init(void* addr){ + INFO("Initrd filesystem start address: %p", addr); + LOG("Enter initrdfs_int"); + LOG("initrd start at %p\n", addr); + LOG("initrd first 4 bytes: %x\n", *(uint32_t*)addr); + root = (struct fentry*)simple_malloc(sizeof(struct fentry)); + struct cpio_iter iter; + char *fname = (char*)simple_malloc(2); + strcpy(fname, "/"); + + memset(root, 0, sizeof(struct fentry)); + root->filename = fname; + root->namesize = 1; + root->mode = root->mode & FILE_TYPE_DIR; + + INIT_LIST_HEAD(&root->list); + + // Start parsing initrd in New ASCII Format at addr + LOG("Start parsing new ascii format's cpio"); + cpio_iter_init(&iter, addr); + do{ + struct fentry *f = (struct fentry*)simple_malloc(sizeof(struct fentry)); + cpio_iter_parse(&iter, f); + LOG("FILE: %s", f->filename); + if(cpio_is_tailer(f)) break; + list_add(&f->list, &root->list); + }while(1); + LOG("Leave initrdfs_int"); +} +void* fdt_initrdfs_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(prop != NULL){ + if(strcmp(prop->name, "linux,initrd-start") == 0){ + uint64_t initrd_start = bswap32(*(uint32_t*)prop->value); + LOG("linux,initrd-start: %x", (uint32_t)initrd_start); + initrdfs_init((void*)initrd_start); + } + } +} + +void initrdfs_ls(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + printf("%s\r\n", f->filename); + } +} +void initrdfs_cat(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + printf("Filename : %s\r\n", f->filename); + printf("File size: %u\r\n", f->filesize); + write_bytes(f->data, f->filesize); + printf("\r\n"); + } + } +} + diff --git a/lab2/include/debug/debug.h b/lab2/include/debug/debug.h new file mode 100644 index 000000000..5f96a0f1e --- /dev/null +++ b/lab2/include/debug/debug.h @@ -0,0 +1,16 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "utils.h" + +#define DEBUG_KERNEL_START() log_kernel_start() +#define LOG(fmt, ...) \ + if(debug) \ + printf("[%s/%s:%d] " fmt "\r\n" , __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) + + + +extern void log_kernel_start(void); + +extern int debug; +#endif diff --git a/lab2/include/fs/initrdfs.h b/lab2/include/fs/initrdfs.h new file mode 100644 index 000000000..992575e6e --- /dev/null +++ b/lab2/include/fs/initrdfs.h @@ -0,0 +1,10 @@ +#ifndef _INITRDFS_H_ +#define _INITRDFS_H_ +#include "utils.h" +#include "types.h" + +extern void initrdfs_init(void*); +extern void initrdfs_ls(); +extern void initrdfs_cat(); +extern void* fdt_initrdfs_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +#endif diff --git a/lab2/include/init/kernel_init.h b/lab2/include/init/kernel_init.h new file mode 100644 index 000000000..4e15dd829 --- /dev/null +++ b/lab2/include/init/kernel_init.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_INIT_H +#define _KERNEL_INIT_H + +extern void kernel_init(void *); + +#endif diff --git a/lab2/include/kernel/reboot.h b/lab2/include/kernel/reboot.h new file mode 100644 index 000000000..cc8e8730b --- /dev/null +++ b/lab2/include/kernel/reboot.h @@ -0,0 +1,16 @@ +#ifndef _REBOOT_H_ +#define _REBOOT_H_ + +#include "peripherals/iomapping.h" + +#define PM_WDOG_RESET 0000000000 +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +extern void reboot(int tick); + +#endif diff --git a/lab2/include/kernel/shell.h b/lab2/include/kernel/shell.h new file mode 100644 index 000000000..756bd672f --- /dev/null +++ b/lab2/include/kernel/shell.h @@ -0,0 +1,6 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ + +void simple_shell(void); + +#endif diff --git a/lab2/include/lib/cpio.h b/lab2/include/lib/cpio.h new file mode 100644 index 000000000..1e68b5dd7 --- /dev/null +++ b/lab2/include/lib/cpio.h @@ -0,0 +1,61 @@ +#ifndef _CPIO_H_ +#define _CPIO_H_ + +#include "utils.h" +#include "types.h" + +#define FILE_TYPE_MASK 0170000 +#define FILE_TYPE_SOCKET 0140000 +#define FILE_TYPE_SYMLINK 0120000 +#define FILE_TYPE_REGULAR 0100000 +#define FILE_TYPE_BLKDEV 0060000 +#define FILE_TYPE_DIR 0040000 +#define FILE_TYPE_CHRDEV 0020000 +#define FILE_TYPE_NAMED_PIPE 0010000 +#define FILE_SUID 0004000 +#define FILE_SGID 0002000 +#define FILE_STICKY 0001000 +#define FILE_PERMISSION_MASK 0000777 + +struct cpio_iter{ + uint8_t *cur; +}; +struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} __attribute((packed)); + +struct fentry { + uint32_t ino; + uint32_t mode; + uint32_t uid; + uint32_t gid; + uint32_t nlink; + uint32_t mtime; + uint32_t filesize; + uint32_t devmajor; + uint32_t devminor; + uint32_t rdevmajor; + uint32_t rdevminor; + uint32_t namesize; + uint32_t check; + char *filename; + uint8_t *data; + struct list_head list; +}; +void cpio_iter_parse(struct cpio_iter*, struct fentry*); +extern void cpio_iter_init(struct cpio_iter*, void*); +extern int cpio_is_tailer(struct fentry*); +#endif diff --git a/lab2/include/lib/fdt_parse.h b/lab2/include/lib/fdt_parse.h new file mode 100644 index 000000000..2a1a45d30 --- /dev/null +++ b/lab2/include/lib/fdt_parse.h @@ -0,0 +1,41 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +#endif diff --git a/lab2/include/lib/list.h b/lab2/include/lib/list.h new file mode 100644 index 000000000..20f384940 --- /dev/null +++ b/lab2/include/lib/list.h @@ -0,0 +1,21 @@ +#ifndef _LIST_H_ +#define _LIST_H_ + +#include "types.h" +struct list_head{ + struct list_head* next, *prev; +}__attribute__((packed)); + +#define LIST_HEAD(head) struct list_head head = { &(head), &(head) } +#define list_entry(node, type, member) container_of(node, type, member) +#define list_first_entry(head, type, member) list_entry((head)->next, type, member) +#define list_last_entry(head, type, member) list_entry((head)->prev, type, member) +#define list_for_each(node, head) \ + for(node = (head)->next ; node != (head) ; node = node->next) + +extern void INIT_LIST_HEAD(struct list_head*); +extern void list_add(struct list_head* node, struct list_head*); +extern void list_add_tail(struct list_head*, struct list_head*); +extern void list_del(struct list_head*); +extern int list_empty(struct list_head*); +#endif diff --git a/lab2/include/lib/print.h b/lab2/include/lib/print.h new file mode 100644 index 000000000..8c8aa74d3 --- /dev/null +++ b/lab2/include/lib/print.h @@ -0,0 +1,13 @@ +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#include "types.h" + +int32_t printf(char *, ...); +int32_t putchar(uint8_t); +int32_t getchar(); + +#define INFO(fmt, ...) \ + printf("[%s] " fmt "\r\n" , __FUNCTION__, ##__VA_ARGS__) + +#endif diff --git a/lab2/include/lib/simple_malloc.h b/lab2/include/lib/simple_malloc.h new file mode 100644 index 000000000..37049120d --- /dev/null +++ b/lab2/include/lib/simple_malloc.h @@ -0,0 +1,9 @@ +#ifndef _SIMPLE_MALLOC_H_ +#define _SIMPLE_MALLOC_H_ + +#include "types.h" + +extern void* simple_malloc(size_t); +extern void init_malloc_state(void*); +extern void* get_remainder(); +#endif diff --git a/lab2/include/lib/string.h b/lab2/include/lib/string.h new file mode 100644 index 000000000..62357669c --- /dev/null +++ b/lab2/include/lib/string.h @@ -0,0 +1,17 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#include "types.h" + +extern char * itoa(int32_t, char*, uint32_t); +extern char * utoa(uint32_t, char*, uint32_t); +extern char * ltoa(int64_t, char*, uint32_t); +extern char * ultoa(uint64_t, char*, uint32_t); +extern int32_t strcmp(char*, char*); +extern char *strcpy(char *, const char *); +extern size_t strlen(const char*); +extern void* memcpy(void*, const void*, size_t); +extern void* memset(void*, int, size_t); +extern int32_t memcmp(void*, const void*, size_t); +extern uint8_t hex2dec(char); +#endif diff --git a/lab2/include/peripherals/iomapping.h b/lab2/include/peripherals/iomapping.h new file mode 100644 index 000000000..b99ae5860 --- /dev/null +++ b/lab2/include/peripherals/iomapping.h @@ -0,0 +1,79 @@ +#ifndef _IOMAPPING_H_ +#define _IOMAPPING_H_ + + +/* Physical addresses range from 0x3F000000 to 0x3FFFFFFF for peripherals */ +#define IO_BASE 0x3F000000 + +/* Register's offset of GPIO */ +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL1 (IO_BASE + 0x200004) +#define GPFSEL2 (IO_BASE + 0x200008) +#define GPFSEL3 (IO_BASE + 0x20000C) +#define GPFSEL4 (IO_BASE + 0x200010) +#define GPFSEL5 (IO_BASE + 0x200014) +#define GPSET0 (IO_BASE + 0x20001C) +#define GPSET1 (IO_BASE + 0x200020) +#define GPCLR0 (IO_BASE + 0x200028) +#define GPCLR1 (IO_BASE + 0x20002C) +#define GPLEV0 (IO_BASE + 0x200034) +#define GPLEV1 (IO_BASE + 0x200038) +#define GPEDS0 (IO_BASE + 0x200040) +#define GPEDS1 (IO_BASE + 0x200044) +#define GPREN0 (IO_BASE + 0x20004C) +#define GPREN1 (IO_BASE + 0x200050) +#define GPFEN0 (IO_BASE + 0x200058) +#define GPFEN1 (IO_BASE + 0x20005C) +#define GPHEN0 (IO_BASE + 0x200064) +#define GPHEN1 (IO_BASE + 0x200068) +#define GPLEN0 (IO_BASE + 0x200070) +#define GPLEN1 (IO_BASE + 0x200074) +#define GPAREN0 (IO_BASE + 0x20007C) +#define GPAREN1 (IO_BASE + 0x200080) +#define GPAFEN0 (IO_BASE + 0x200088) +#define GPAFEN1 (IO_BASE + 0x20008C) +#define GPPUD (IO_BASE + 0x200094) +#define GPPUDCLK0 (IO_BASE + 0x200098) +#define GPPUDCLK1 (IO_BASE + 0x20009C) + + +/* Register's offset of UART and SPI */ +#define AUX_IRQ (IO_BASE + 0x215000) +#define AUX_ENABLES (IO_BASE + 0x215004) +#define AUX_MU_IO_REG (IO_BASE + 0x215040) +#define AUX_MU_IER_REG (IO_BASE + 0x215044) +#define AUX_MU_IIR_REG (IO_BASE + 0x215048) +#define AUX_MU_LCR_REG (IO_BASE + 0x21504C) +#define AUX_MU_MCR_REG (IO_BASE + 0x215050) +#define AUX_MU_LSR_REG (IO_BASE + 0x215054) +#define AUX_MU_MSR_REG (IO_BASE + 0x215058) +#define AUX_MU_SCRATCH (IO_BASE + 0x21505C) +#define AUX_MU_CNTL_REG (IO_BASE + 0x215060) +#define AUX_MU_STAT_REG (IO_BASE + 0x215064) +#define AUX_MU_BAUD_REG (IO_BASE + 0x215068) +#define AUX_SPI0_CNTL0_REG (IO_BASE + 0x215080) +#define AUX_SPI0_CNTL1_REG (IO_BASE + 0x215084) +#define AUX_SPI0_STAT_REG (IO_BASE + 0x215088) +#define AUX_SPI0_IO_REG (IO_BASE + 0x215090) +#define AUX_SPI0_PEEK_REG (IO_BASE + 0x215094) +#define AUX_SPI1_CNTL0_REG (IO_BASE + 0x2150C0) +#define AUX_SPI1_CNTL1_REG (IO_BASE + 0x2150C4) +#define AUX_SPI1_STAT_REG (IO_BASE + 0x2150C8) +#define AUX_SPI1_IO_REG (IO_BASE + 0x2150D0) +#define AUX_SPI1_PEEK_REG (IO_BASE + 0x2150D4) + +// mailbox register base address +#define MBOX_REG (IO_BASE + 0xB880) + +// watch dog +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_RSTC (IO_BASE + 0x10001c) +#define PM_WDOG (IO_BASE + 0x100024) + +#define IO_MMIO_write32(addr, val) *(uint32_t*)addr = val +#define IO_MMIO_read32(addr) *(uint32_t*)addr + + +#endif + diff --git a/lab2/include/peripherals/mailbox.h b/lab2/include/peripherals/mailbox.h new file mode 100644 index 000000000..b37243d21 --- /dev/null +++ b/lab2/include/peripherals/mailbox.h @@ -0,0 +1,172 @@ +#ifndef _MAILBOX_H_ +#define _MAILBOX_H_ + +#include "types.h" + +#define MBOX_CHANNEL_POWER 0 +#define MBOX_CHANNEL_FRAME_BUF 1 +#define MBOX_CHANNEL_VIRTUAL_UART 2 +#define MBOX_CHANNEL_VCHIQ 3 +#define MBOX_CHANNEL_LEDS 4 +#define MBOX_CHANNEL_BUTTONS 5 +#define MBOX_CHANNEL_TOUCH_SCREEN 6 +#define MBOX_CHANNEL_UNKOWN 7 +#define MBOX_CHANNEL_PROPERTY_TAGS 8 + +enum MBOX_PROPERTY_STATUS { + MBOX_STATUS_REQUEST = 0, + MBOX_STATUS_SUCCESS = 0x80000000, + MBOX_STATUS_ERROR = 0x80000001, +}; + +enum MBOX_PROPERTY_TAG{ + MBOX_PROPERTY_END = 0, + MBOX_GET_FIRMWARE_REVISION = 0x00000001, + + MBOX_SET_CURSOR_INFO = 0x00008010, + MBOX_SET_CURSOR_STATE = 0x00008011, + + MBOX_GET_BOARD_MODEL = 0x00010001, + MBOX_GET_BOARD_REVISION = 0x00010002, + MBOX_GET_BOARD_MAC_ADDRESS = 0x00010003, + MBOX_GET_BOARD_SERIAL = 0x00010004, + MBOX_GET_ARM_MEMORY = 0x00010005, + MBOX_GET_VC_MEMORY = 0x00010006, + MBOX_GET_CLOCKS = 0x00010007, + MBOX_GET_POWER_STATE = 0x00020001, + MBOX_GET_TIMING = 0x00020002, + MBOX_SET_POWER_STATE = 0x00028001, + MBOX_GET_CLOCK_STATE = 0x00030001, + MBOX_GET_CLOCK_RATE = 0x00030002, + MBOX_GET_VOLTAGE = 0x00030003, + MBOX_GET_MAX_CLOCK_RATE = 0x00030004, + MBOX_GET_MAX_VOLTAGE = 0x00030005, + MBOX_GET_TEMPERATURE = 0x00030006, + MBOX_GET_MIN_CLOCK_RATE = 0x00030007, + MBOX_GET_MIN_VOLTAGE = 0x00030008, + MBOX_GET_TURBO = 0x00030009, + MBOX_GET_MAX_TEMPERATURE = 0x0003000a, + MBOX_GET_STC = 0x0003000b, + MBOX_ALLOCATE_MEMORY = 0x0003000c, + MBOX_LOCK_MEMORY = 0x0003000d, + MBOX_UNLOCK_MEMORY = 0x0003000e, + MBOX_RELEASE_MEMORY = 0x0003000f, + MBOX_EXECUTE_CODE = 0x00030010, + MBOX_EXECUTE_QPU = 0x00030011, + MBOX_SET_ENABLE_QPU = 0x00030012, + MBOX_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, + MBOX_GET_EDID_BLOCK = 0x00030020, + MBOX_GET_CUSTOMER_OTP = 0x00030021, + MBOX_GET_DOMAIN_STATE = 0x00030030, + MBOX_SET_CLOCK_STATE = 0x00038001, + MBOX_SET_CLOCK_RATE = 0x00038002, + MBOX_SET_VOLTAGE = 0x00038003, + MBOX_SET_TURBO = 0x00038009, + MBOX_SET_CUSTOMER_OTP = 0x00038021, + MBOX_SET_DOMAIN_STATE = 0x00038030, + MBOX_GET_GPIO_STATE = 0x00030041, + MBOX_SET_GPIO_STATE = 0x00038041, + MBOX_SET_SDHOST_CLOCK = 0x00038042, + MBOX_GET_GPIO_CONFIG = 0x00030043, + MBOX_SET_GPIO_CONFIG = 0x00038043, + MBOX_GET_PERIPH_REG = 0x00030045, + MBOX_SET_PERIPH_REG = 0x00038045, + + + /* Dispmanx TAGS */ + MBOX_FRAMEBUFFER_ALLOCATE = 0x00040001, + MBOX_FRAMEBUFFER_BLANK = 0x00040002, + MBOX_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, + MBOX_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, + MBOX_FRAMEBUFFER_GET_DEPTH = 0x00040005, + MBOX_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006, + MBOX_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007, + MBOX_FRAMEBUFFER_GET_PITCH = 0x00040008, + MBOX_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, + MBOX_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, + MBOX_FRAMEBUFFER_GET_PALETTE = 0x0004000b, + MBOX_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, + MBOX_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010, + MBOX_FRAMEBUFFER_RELEASE = 0x00048001, + MBOX_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, + MBOX_FRAMEBUFFER_TEST_DEPTH = 0x00044005, + MBOX_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006, + MBOX_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, + MBOX_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, + MBOX_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, + MBOX_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, + MBOX_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, + MBOX_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, + MBOX_FRAMEBUFFER_SET_DEPTH = 0x00048005, + MBOX_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006, + MBOX_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007, + MBOX_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + MBOX_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + MBOX_FRAMEBUFFER_SET_PALETTE = 0x0004800b, + MBOX_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + MBOX_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, + MBOX_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + MBOX_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + + MBOX_VCHIQ_INIT = 0x00048010, + + MBOX_GET_COMMAND_LINE = 0x00050001, + MBOX_GET_DMA_CHANNELS = 0x00060001, +}; +/* + * Mailbox Read/Write Peek Sender Status Config + * 0 0x00 0x10 0x14 0x18 0x1c + * 1 0x20 0x30 0x34 0x38 0x3c + */ + +#define MBOX_READ_CHANNEL_MASK 15 +#define MBOX_WRITE_CHANNEL_MASK 15 +#define MBOX_WRITE_ADDR_MASK (~15) +#define MBOX_READ_ADDR_MASK (~15) +#define MBOX_STATUS_FULL_MASK 0x80000000 +#define MBOX_STATUS_EMPTY_MASK 0x40000000 +typedef struct{ + uint32_t read; + uint32_t unused[5]; + uint32_t status; + uint32_t config; + uint32_t write; +}__attribute__((packed)) MBox_register; + +/* 0 4 8 12 16 20 24 28 32 + +---------------------------------------------------------------+ +0x00 | Buffer Size | + +---------------------------------------------------------------+ +0x04 | Request/Response Code | + +---------------------------------------------------------------+ +0x08 | Tags | +... \\ \\ +0xXX | Tags | + +---------------------------------------------------------------+ +0xXX+4 | End Tag (0) | + +---------------------------------------------------------------+ +0xXX+8 | Padding | +... \\ \\ +0xXX+16| Padding | + +---------------------------------------------------------------+ +*/ +#define MBOX_TAG_REQUEST 0 +typedef struct{ + uint32_t id; + uint32_t value_size; + uint32_t code; + uint8_t values[0]; +}MBox_tag; + +typedef struct{ + uint32_t buf_size; + uint32_t code; + uint8_t buf[0]; +}MBox_buffer; + +extern void MBox_get_board_revision(uint32_t*); +extern void MBox_get_arm_memory(uint32_t*); + +#endif diff --git a/lab2/include/peripherals/mini_uart.h b/lab2/include/peripherals/mini_uart.h new file mode 100644 index 000000000..64de0e7d4 --- /dev/null +++ b/lab2/include/peripherals/mini_uart.h @@ -0,0 +1,20 @@ +#ifndef _MINI_UART_H_ +#define _MINI_UART_H_ + +#include "types.h" + +#define SYSTEM_CLOCK_RATE (250000000) +#define BAUD_RATE 115200 +#define BAUD_RATE_REG (SYSTEM_CLOCK_RATE / (8 * BAUD_RATE) - 1) + +extern void mini_uart_init(void); +extern uint8_t mini_uart_read(void); +extern void mini_uart_write(uint8_t); +extern ssize_t write_bytes(uint8_t *, size_t); +extern void write_str(char *); +extern void write_hex(uint8_t); +extern void delay_cycles(uint64_t); + + + +#endif diff --git a/lab2/include/types.h b/lab2/include/types.h new file mode 100644 index 000000000..8854dd672 --- /dev/null +++ b/lab2/include/types.h @@ -0,0 +1,43 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) + +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + + +#endif diff --git a/lab2/include/utils.h b/lab2/include/utils.h new file mode 100644 index 000000000..baa5852bf --- /dev/null +++ b/lab2/include/utils.h @@ -0,0 +1,11 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include "lib/print.h" +#include "lib/string.h" +#include "lib/list.h" +#include "lib/cpio.h" +#include "lib/simple_malloc.h" +#include "lib/fdt_parse.h" + +#endif diff --git a/lab2/init/Makefile b/lab2/init/Makefile new file mode 100644 index 000000000..e5b218aa8 --- /dev/null +++ b/lab2/init/Makefile @@ -0,0 +1,24 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + kernel_init.o + +all: $(OBJECTS) + +%.o: %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab2/init/kernel_init.c b/lab2/init/kernel_init.c new file mode 100644 index 000000000..7bbb40c81 --- /dev/null +++ b/lab2/init/kernel_init.c @@ -0,0 +1,14 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "fs/initrdfs.h" +#include "utils.h" +extern int __heap_start; +void kernel_init(void *dtb){ + INFO("kernel start initialization..."); + // init_malloc_state should done first!!! + init_malloc_state(&__heap_start); + fdt_parser(dtb, fdt_initrdfs_callback); +// initrdfs_init(&__initrdfs_start); + return; +} + diff --git a/lab2/initramfs.cpio b/lab2/initramfs.cpio new file mode 100644 index 000000000..9f61f2371 Binary files /dev/null and b/lab2/initramfs.cpio differ diff --git a/lab2/kernel/Makefile b/lab2/kernel/Makefile new file mode 100644 index 000000000..4488ea9d5 --- /dev/null +++ b/lab2/kernel/Makefile @@ -0,0 +1,31 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + shell.o \ + reboot.o \ + main.o \ + start.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab2/kernel/linker.ld b/lab2/kernel/linker.ld new file mode 100644 index 000000000..84f7925c6 --- /dev/null +++ b/lab2/kernel/linker.ld @@ -0,0 +1,40 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; +} diff --git a/lab2/kernel/main.c b/lab2/kernel/main.c new file mode 100644 index 000000000..aaf3030dc --- /dev/null +++ b/lab2/kernel/main.c @@ -0,0 +1,13 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "init/kernel_init.h" +#include "utils.h" +#include "debug/debug.h" +#include "kernel/shell.h" + +void kernel_main(void *dtb){ + kernel_init(dtb); + DEBUG_KERNEL_START(); + + simple_shell(); +} diff --git a/lab2/kernel/reboot.c b/lab2/kernel/reboot.c new file mode 100644 index 000000000..2511cc06e --- /dev/null +++ b/lab2/kernel/reboot.c @@ -0,0 +1,14 @@ +#include "types.h" +#include "peripherals/iomapping.h" +#include "kernel/reboot.h" + +void reboot(int ticks){ + unsigned int pm_rstc,pm_wdog; + pm_rstc = IO_MMIO_read32(PM_RSTC); + + pm_wdog = PM_PASSWORD | (ticks & PM_WDOG_TIME_SET); + pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; + + IO_MMIO_write32(PM_RSTC, pm_rstc); + IO_MMIO_write32(PM_WDOG, pm_wdog); +} diff --git a/lab2/kernel/shell.c b/lab2/kernel/shell.c new file mode 100644 index 000000000..1803a5e81 --- /dev/null +++ b/lab2/kernel/shell.c @@ -0,0 +1,59 @@ +#include "types.h" +#include "utils.h" +#include "peripherals/mailbox.h" +#include "kernel/reboot.h" +#include "fs/initrdfs.h" +char *miku_ascii = "⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀\r\n⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁\r\n⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀\r\n⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀\r\n⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀\r\n⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀\r\n⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀\r\n⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀\r\n⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀\r\n⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀\r\n⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀"; +char buf[0x2000]; +void simple_shell(){ + unsigned int i; + char ch; + printf(miku_ascii); + printf("\r\n\r\n"); + while(1){ + i = 0; + buf[0] = '\0'; + printf("# "); + // read command + while(1){ + ch = (char)getchar(); + if(ch == '\r'){ + printf("\r\n"); + buf[i] = '\0'; + break; + }else if(ch != '\n'){ + putchar(ch); + buf[i] = ch; + i++; + } + } + // match comman + if(strcmp(buf, "help") == 0){ + printf("help : print this help menu\r\n"); + printf("hello : print Hello World!\r\n"); + printf("info : print hardware infomation\r\n"); + printf("reboot : reboot the device\r\n"); + printf("ls : list files\r\n"); + printf("cat : cat files\r\n"); + + }else if(strcmp(buf, "hello") == 0){ + printf("Hello World!\r\n"); + }else if(strcmp(buf, "info") == 0){ + uint32_t tmp[2]; + MBox_get_board_revision(tmp); + printf("Board revision: 0x%x\r\n", tmp[0]); + + MBox_get_arm_memory(tmp); + printf("Memory base: 0x%x\r\n", tmp[0]); + printf("Memory size: 0x%x\r\n", tmp[1]); + }else if(strcmp(buf, "reboot") == 0){ + printf("Start rebooting...\r\n"); + reboot(100); + while(1); + }else if(strcmp(buf, "ls") == 0){ + initrdfs_ls(); + }else if(strcmp(buf, "cat") == 0){ + initrdfs_cat(); + } + } +} diff --git a/lab2/kernel/start.S b/lab2/kernel/start.S new file mode 100644 index 000000000..0b14fd836 --- /dev/null +++ b/lab2/kernel/start.S @@ -0,0 +1,32 @@ +.section ".text.boot" +.global _start +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #0xff + + // cpu id > 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + +// cpu id == 0 +master_core: +// stack + adr x1, _start + mov sp, x1 +// initialize .bss section + ldr x1, =__bss_start + ldr x2, =__bss_end +bss_zero: + sub x3, x2, x1 + cbz x3, end + str xzr, [x1], #8 // store zero to [x1] and add 8 to x1 + b bss_zero + +end: +// jump to kernel_main + bl kernel_main + b proc_hang diff --git a/lab2/lib/Makefile b/lab2/lib/Makefile new file mode 100644 index 000000000..816264a1c --- /dev/null +++ b/lab2/lib/Makefile @@ -0,0 +1,33 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + print.o \ + string.o \ + list.o \ + cpio.o \ + simple_malloc.o \ + fdt_parse.o + + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab2/lib/cpio.c b/lab2/lib/cpio.c new file mode 100644 index 000000000..4129ad568 --- /dev/null +++ b/lab2/lib/cpio.c @@ -0,0 +1,63 @@ +#include "types.h" +#include "utils.h" +#include "debug/debug.h" + +uint32_t cpio_hex2dec(const char *s){ + uint32_t ret = 0; + for(uint32_t i = 0 ; i < 8 ; i++){ + ret = ret << 4; + ret = ret + hex2dec(s[i]); + } + return ret; +} + +void cpio_iter_parse(struct cpio_iter* iter, struct fentry* f){ + LOG("Enter cpio_iter_parse"); + size_t count = 0; + struct cpio_newc_header* header = (struct cpio_newc_header* )iter->cur; + + if(!memcpy(header->c_magic, "070701", 6)){ + LOG("CPIO PARSE ERROR!!!!"); + return; + } + + f->ino = cpio_hex2dec(header->c_ino); + f->mode = cpio_hex2dec(header->c_mode); + f->uid = cpio_hex2dec(header->c_uid); + LOG("f->uid: %u", f->uid); + f->gid = cpio_hex2dec(header->c_gid); + f->nlink = cpio_hex2dec(header->c_nlink); + f->mtime = cpio_hex2dec(header->c_mtime); + f->filesize = cpio_hex2dec(header->c_filesize); + LOG("f->filesize: %u", f->filesize); + f->devmajor = cpio_hex2dec(header->c_devmajor); + f->devminor = cpio_hex2dec(header->c_devminor); + f->rdevmajor = cpio_hex2dec(header->c_rdevmajor); + f->rdevminor = cpio_hex2dec(header->c_rdevminor); + f->namesize = cpio_hex2dec(header->c_namesize); + LOG("f->namesize: %u", f->namesize); + f->check = cpio_hex2dec(header->c_check); + count = count + sizeof(struct cpio_newc_header); + + f->filename = (char*)simple_malloc(f->namesize); + memcpy(f->filename, (uint8_t* )header + count, f->namesize); + LOG("get f->filename"); + count = ALIGN_UP(count + f->namesize, 4); + if(f->filesize > 0){ + f->data = (uint8_t*)simple_malloc(f->filesize); + memcpy(f->data, (uint8_t* )header + count, f->filesize); + } + LOG("get f->data"); + count = ALIGN_UP(count + f->filesize, 4); + iter->cur = iter->cur + count; + LOG("count: %u, iter->cur: %p", count, iter->cur); + LOG("Leave cpio_iter_parse"); +} + +void cpio_iter_init(struct cpio_iter* iter, void* addr){ + iter->cur = addr; +} +int cpio_is_tailer(struct fentry* f){ + return (strcmp(f->filename, "TRAILER!!!") == 0); +} + diff --git a/lab2/lib/fdt_parse.c b/lab2/lib/fdt_parse.c new file mode 100644 index 000000000..d70a5c93c --- /dev/null +++ b/lab2/lib/fdt_parse.c @@ -0,0 +1,110 @@ +#include "lib/fdt_parse.h" +#include "utils.h" +#include "types.h" +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } + +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = (fdt_header*)simple_malloc(sizeof(fdt_header)); + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) / 4; + //printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + len += 2; + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + printf("Parsing error!!\n"); + } + } +} + +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab2/lib/list.c b/lab2/lib/list.c new file mode 100644 index 000000000..8cd772b4f --- /dev/null +++ b/lab2/lib/list.c @@ -0,0 +1,37 @@ +#include "lib/list.h" + +void INIT_LIST_HEAD(struct list_head* head){ + head->next = head; + head->prev = head; +} + +void list_add(struct list_head* node, struct list_head* head){ + struct list_head *next = head->next; + + next->prev = node; + head->next = node; + + node->next = next; + node->prev = head; +} + +void list_add_tail(struct list_head* node, struct list_head* head){ + struct list_head* tail = head->prev; + + tail->next = node; + head->prev = node; + + node->next = head; + node->prev = tail; +} + +void list_del(struct list_head* node){ + struct list_head* next = node->next; + struct list_head* prev = node->prev; + + next->prev = prev; + prev->next = next; +} +int list_empty(struct list_head* head){ + return (head->next == head); +} diff --git a/lab2/lib/print.c b/lab2/lib/print.c new file mode 100644 index 000000000..546954f43 --- /dev/null +++ b/lab2/lib/print.c @@ -0,0 +1,112 @@ +#include "lib/print.h" +#include "lib/string.h" +#include "types.h" +#include "peripherals/mini_uart.h" +#include + +int32_t printf(char *fmt, ...){ + uint32_t uval; + int32_t val; + int64_t lval; + char str[64], ch; + char* p, *s; + void* addr; + volatile int32_t count = 0; + va_list ap; + + va_start(ap, fmt); + + while(*fmt){ + char c = *fmt++; + if(c == '%'){ + c = *fmt++; + switch(c){ + case 'u': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'd': + val = va_arg(ap, int); + itoa(val, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'l': + lval = va_arg(ap, int64_t); + ltoa(lval, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'c': + ch = va_arg(ap, int); + mini_uart_write(ch); + count++; + break; + case 'p': + addr = va_arg(ap, void*); + utoa((uint64_t)addr, str, 16); + + mini_uart_write('0'); + mini_uart_write('x'); + count += 2; + + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + + break; + case 'x': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 16); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + + break; + case 's': + s = va_arg(ap, char*); + p = s; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case '%': + mini_uart_write('%'); + count++; + default: + mini_uart_write('%'); + mini_uart_write(c); + count += 2; + } + }else{ + mini_uart_write(c); + count++; + } + } + va_end(ap); + return count; +} +int32_t putchar(uint8_t ch){ + mini_uart_write(ch); + return ch; +} +int32_t getchar(){ + return mini_uart_read(); +} diff --git a/lab2/lib/simple_malloc.c b/lab2/lib/simple_malloc.c new file mode 100644 index 000000000..0a44953e3 --- /dev/null +++ b/lab2/lib/simple_malloc.c @@ -0,0 +1,24 @@ +#include "lib/simple_malloc.h" +#include "debug/debug.h" +#include "types.h" + + +#define req2size(req) ALIGN_UP(req, 16) +struct malloc_state{ + uint8_t* last_remainder; +}mstate; + +void init_malloc_state(void* heap_start){ + INFO("Simple heap start address: %p", heap_start); + mstate.last_remainder = (uint8_t*)heap_start; +} + +void* simple_malloc(size_t size){ + void* chunk = mstate.last_remainder; + size_t nb = req2size(size); + mstate.last_remainder = mstate.last_remainder + nb; + return chunk; +} +void* get_remainder(){ + return mstate.last_remainder; +} diff --git a/lab2/lib/string.c b/lab2/lib/string.c new file mode 100644 index 000000000..b6f56d7fa --- /dev/null +++ b/lab2/lib/string.c @@ -0,0 +1,200 @@ +#include "lib/string.h" +#include "types.h" +char *int_table = "0123456789"; +char *hex_table = "0123456789abcdef"; +char * itoa(int32_t value, char* str, uint32_t base){ + char buf[32]; + uint32_t val; + volatile int i = 0, j = 0; + + switch(base){ + case 16: + val = (uint32_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} + +char * utoa(uint32_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint32_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} +char * ltoa(int64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val; + + switch(base){ + case 16: + val = (uint64_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +char * ultoa(uint64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +int32_t strcmp(char* str1, char* str2){ + do{ + if(*str1 > *str2) return 1; + else if(*str1 < *str2) return -1; + str1++;str2++; + }while(*str1 != '\0' || *str2 != '\0'); + return 0; +} +size_t strlen(const char* s){ + size_t i = 0; + while(s[i++]); + i--; + return i; +} +// Do not maninpulate data by using (uint64*) or it may sometimes trigger alignment issue +// Manipulating data by using (uint8*) is best choice in this homework +void* memcpy(void* dst, const void* src, size_t n){ + const uint8_t* ps = src; + uint8_t *pd = dst; + size_t i; + for(i = 0 ; i < n ; i++) pd[i] = ps[i]; + return dst; +} +char *strcpy(char *dest, const char *src){ + memcpy(dest, src, strlen(src) + 1); +} +void* memset(void* s, int c, size_t n){ + uint8_t* ps = s; + for(size_t i = 0 ; i < n ; i++) ps[i] = c; + return s; +} + +int32_t memcmp(void* m1, const void* m2, size_t n){ + size_t i = 0; + char *s1 = m1; + const char* s2 = m2; + while(i < n){ + if(s1[i] > s2[i]) return 1; + else if(s1[i] < s2[i]) return -1; + i++; + } + return 0; +} + +uint8_t hex2dec(char hex){ + if('0' <= hex && hex <= '9'){ + return (uint8_t)hex - (uint8_t)'0'; + }else if('a' <= hex && hex <= 'f'){ + return (uint8_t)hex - (uint8_t)'a' + 10; + }else{ + return (uint8_t)hex - (uint8_t)'A' + 10; + } +} diff --git a/lab2/peripherals/Makefile b/lab2/peripherals/Makefile new file mode 100644 index 000000000..50b5d0780 --- /dev/null +++ b/lab2/peripherals/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + mini_uart.o \ + mailbox.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab2/peripherals/mailbox.c b/lab2/peripherals/mailbox.c new file mode 100644 index 000000000..1e1021ea2 --- /dev/null +++ b/lab2/peripherals/mailbox.c @@ -0,0 +1,117 @@ +#include "types.h" +#include "debug/debug.h" +#include "peripherals/mailbox.h" +#include "peripherals/iomapping.h" + +static uint32_t MBox_buf[4096] __attribute__((aligned(16))); + +static uint32_t MBox_read(int channel){ + int ch, data; + + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_EMPTY_MASK); + + data = mbox_reg->read; + ch = data & MBOX_WRITE_CHANNEL_MASK; + if(ch == channel){ + LOG("MBox read address: %p", data & MBOX_READ_ADDR_MASK); + return (data & MBOX_READ_ADDR_MASK); + } + LOG("Leave"); + return 0; +} + +static void MBox_write(uint32_t data, int channel){ + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_FULL_MASK); + + mbox_reg->write = data | channel; + LOG("Leave"); +} + +static uint32_t MBox_process(uint8_t* tags, size_t tags_size){ + LOG("Enter"); + MBox_buffer* mbuf = (MBox_buffer*)MBox_buf; + // set buffer header + mbuf->buf_size = tags_size + 12; + mbuf->code = MBOX_STATUS_REQUEST; + + // copy tags to buffer + memcpy(mbuf->buf, tags, tags_size); + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + LOG("mbuf->buf: %p", mbuf->buf); + LOG("mbuf->buf + tags_size: %p", mbuf->buf + tags_size); + // end of MBox_buf + memset(mbuf->buf + tags_size, 0, 4); + + pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + // write to mailbox + MBox_write((uint32_t)(uint64_t)MBox_buf, MBOX_CHANNEL_PROPERTY_TAGS); + + // read from mailbox + uint32_t result = MBox_read(MBOX_CHANNEL_PROPERTY_TAGS); + + + LOG("Leave"); + return result; +} +void MBox_get_board_revision(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 4]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_BOARD_REVISION; + tag->value_size = 4; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer *)(uint64_t)MBox_process(buf, sizeof(MBox_tag) + 4); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + *ret = ((uint32_t*)tag->values)[0]; + LOG("Leave"); +} +void MBox_get_arm_memory(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 8]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_ARM_MEMORY; + tag->value_size = 8; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + ((uint32_t*)tag->values)[1] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer *)(uint64_t)MBox_process(buf, sizeof(MBox_tag) + 8); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + ret[0] = ((uint32_t*)tag->values)[0]; + ret[1] = ((uint32_t*)tag->values)[1]; + LOG("Leave"); +} + + diff --git a/lab2/peripherals/mini_uart.c b/lab2/peripherals/mini_uart.c new file mode 100644 index 000000000..9198e6b15 --- /dev/null +++ b/lab2/peripherals/mini_uart.c @@ -0,0 +1,85 @@ +#include "types.h" +#include "peripherals/iomapping.h" +#include "peripherals/mini_uart.h" +inline void delay_cycles(uint64_t n){ + for(register uint64_t i = 0 ; i < n ; i++) asm volatile("nop"); +} + +/** + * @brief Enable UART + */ +void mini_uart_init(void){ + // GPIO 14 & 15 take function 0 + // Read out GPFSEL1 register + uint32_t tmp = IO_MMIO_read32(GPFSEL1); + + // Set GPIO 14 & 15 function bits + tmp &= ~(0b111111 << 12); + tmp |= 0b010010 << 12; + IO_MMIO_write32(GPFSEL1, tmp); + + + // disable pull-up/down of GPIO 14 & 15 + // Write to GPPUD to set the required control signal + IO_MMIO_write32(GPPUD, 0); + + // Wait 150 cycles – this provides the required set-up time for the control signal + delay_cycles(150); + + // Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to modify + IO_MMIO_write32(GPPUDCLK0, (1 << 14) | (1 << 15)); + + // Wait 150 cycles – this provides the required hold time for the control signal + delay_cycles(150); + + // Write to GPPUD to remove the control signa + IO_MMIO_write32(GPPUD, 0); + + // Write to GPPUDCLK0/1 to remove the clock + IO_MMIO_write32(GPPUDCLK0, 0); + + // Initialize Auxiliary peripherals Register + // Mini UART enable + IO_MMIO_write32(AUX_ENABLES, 1); + + // To disable auto flow control and disable receiver and transmitter, set control register to 0 + IO_MMIO_write32(AUX_MU_CNTL_REG, 0); + + // Disable mini UART's interrupt + IO_MMIO_write32(AUX_MU_IER_REG, 0); + + // Set UART to 8-bit mode + IO_MMIO_write32(AUX_MU_LCR_REG, 3); + + // To indicate that our UART is able to receive data, set RTS line to be always high + IO_MMIO_write32(AUX_MU_MCR_REG, 0); + + // Set Baud rate to 115200 + IO_MMIO_write32(AUX_MU_BAUD_REG, BAUD_RATE_REG); + + // Start UART + IO_MMIO_write32(AUX_MU_CNTL_REG, 3); + return; +} + +uint8_t mini_uart_read(void){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & 0x1)); + return IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; +} + +void mini_uart_write(uint8_t val){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & (0x1 << 5))); + IO_MMIO_write32(AUX_MU_IO_REG, val); +} + +ssize_t write_bytes(uint8_t* buf, size_t n){ + for(uint64_t i = 0 ; i < n ; i++) mini_uart_write(buf[i]); + return n; +} + +void write_str(char* buf){ + while(*buf) mini_uart_write((uint8_t)*buf++); + return; +} + + diff --git a/lab2/test/lib/.gdb_history b/lab2/test/lib/.gdb_history new file mode 100644 index 000000000..58afc787f --- /dev/null +++ b/lab2/test/lib/.gdb_history @@ -0,0 +1,2 @@ +run +quit diff --git a/lab2/test/lib/dtb_parse/.gdb_history b/lab2/test/lib/dtb_parse/.gdb_history new file mode 100644 index 000000000..8ae386791 --- /dev/null +++ b/lab2/test/lib/dtb_parse/.gdb_history @@ -0,0 +1,43 @@ +b main +run +n +quit +run +p fdt +quit +b main +n +run +n +x/gx ptr +quit +b main +run +n +statbuf->size +p statbuf->size +p statbuf->st_size +quit +run +b main +run +n +s +n +p token +p/x pdft_struct +p/x pdt_struct +x/gx 0x7ffff7fb3048 +x/s 0x7ffff7fb3048 +x/dx 0x7ffff7fb3048 +x/wx 0x7ffff7fb3048 +x/4wx 0x7ffff7fb3048 +n +p len +n +quit +quit +run +quit +run +quit diff --git a/lab2/test/lib/dtb_parse/Makefile b/lab2/test/lib/dtb_parse/Makefile new file mode 100644 index 000000000..d6e1a8f08 --- /dev/null +++ b/lab2/test/lib/dtb_parse/Makefile @@ -0,0 +1,2 @@ +all: + gcc main.c fdt_parse.c -o main -g -O0 diff --git a/lab2/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb b/lab2/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 000000000..6f9ef31cc Binary files /dev/null and b/lab2/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb differ diff --git a/lab2/test/lib/dtb_parse/fdt_parse.c b/lab2/test/lib/dtb_parse/fdt_parse.c new file mode 100644 index 000000000..bb8abd2c8 --- /dev/null +++ b/lab2/test/lib/dtb_parse/fdt_parse.c @@ -0,0 +1,113 @@ +#include "fdt_parse.h" +#include +#include +#include + +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } + +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = (fdt_header*)malloc(sizeof(fdt_header)); + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) / 4; + //printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + len += 2; + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + printf("Parsing error!!\n"); + exit(0); + } + } +} + +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab2/test/lib/dtb_parse/fdt_parse.h b/lab2/test/lib/dtb_parse/fdt_parse.h new file mode 100644 index 000000000..876b4087a --- /dev/null +++ b/lab2/test/lib/dtb_parse/fdt_parse.h @@ -0,0 +1,53 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +#endif diff --git a/lab2/test/lib/dtb_parse/main b/lab2/test/lib/dtb_parse/main new file mode 100755 index 000000000..aa43f24f6 Binary files /dev/null and b/lab2/test/lib/dtb_parse/main differ diff --git a/lab2/test/lib/dtb_parse/main.c b/lab2/test/lib/dtb_parse/main.c new file mode 100644 index 000000000..9af1de752 --- /dev/null +++ b/lab2/test/lib/dtb_parse/main.c @@ -0,0 +1,19 @@ +#include "fdt_parse.h" +#include +#include +#include +#include +#include +#include + +int main(void){ + int fd = open("./bcm2710-rpi-3-b-plus.dtb", O_RDONLY); + if(fd < 0){ + printf("failed to open file\n"); + } + struct stat statbuf; + fstat(fd, &statbuf); + char *ptr = mmap(NULL,statbuf.st_size,PROT_READ,MAP_PRIVATE,fd,0); + + fdt_parser(ptr, fdt_print_callback); +} diff --git a/lab2/test/lib/dtb_parse/tmp.dts b/lab2/test/lib/dtb_parse/tmp.dts new file mode 100644 index 000000000..1ceb3539f --- /dev/null +++ b/lab2/test/lib/dtb_parse/tmp.dts @@ -0,0 +1,1515 @@ +/dts-v1/; + +/memreserve/ 0x0000000000000000 0x0000000000001000; +/ { + compatible = "raspberrypi,3-model-b-plus\0brcm,bcm2837"; + model = "Raspberry Pi 3 Model B+"; + #address-cells = <0x01>; + #size-cells = <0x01>; + interrupt-parent = <0x01>; + + aliases { + serial0 = "/soc/serial@7e215040"; + serial1 = "/soc/serial@7e201000"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + aux = "/soc/aux@7e215000"; + sound = "/soc/sound"; + soc = "/soc"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + uart0 = "/soc/serial@7e201000"; + uart1 = "/soc/serial@7e215040"; + sdhost = "/soc/mmc@7e202000"; + mmc = "/soc/mmc@7e300000"; + mmc1 = "/soc/mmcnr@7e300000"; + mmc0 = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c1 = "/soc/i2c@7e804000"; + i2c10 = "/soc/i2c0mux/i2c@1"; + spi0 = "/soc/spi@7e204000"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + usb = "/soc/usb@7e980000"; + leds = "/leds"; + fb = "/soc/fb"; + thermal = "/soc/thermal@7e212000"; + axiperf = "/soc/axiperf"; + i2c2 = "/soc/i2c@7e805000"; + ethernet0 = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + }; + + chosen { + bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; + }; + + reserved-memory { + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges; + phandle = <0x37>; + + linux,cma { + compatible = "shared-dma-pool"; + size = <0x4000000>; + reusable; + linux,cma-default; + phandle = <0x38>; + }; + }; + + thermal-zones { + + cpu-thermal { + polling-delay-passive = <0x00>; + polling-delay = <0x3e8>; + thermal-sensors = <0x02>; + coefficients = <0xfffffde6 0x64960>; + phandle = <0x39>; + + cooling-maps { + }; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x7e000000 0x3f000000 0x1000000 0x40000000 0x40000000 0x1000>; + dma-ranges = <0xc0000000 0x00 0x3f000000>; + phandle = <0x3a>; + + txp@7e004000 { + compatible = "brcm,bcm2835-txp"; + reg = <0x7e004000 0x20>; + interrupts = <0x01 0x0b>; + status = "disabled"; + phandle = <0x3b>; + }; + + cprman@7e101000 { + compatible = "brcm,bcm2835-cprman"; + #clock-cells = <0x01>; + reg = <0x7e101000 0x2000>; + clocks = <0x03 0x04 0x00 0x04 0x01 0x04 0x02 0x05 0x00 0x05 0x01 0x05 0x02>; + firmware = <0x06>; + phandle = <0x08>; + }; + + mailbox@7e00b880 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0x00 0x01>; + #mbox-cells = <0x00>; + phandle = <0x1f>; + }; + + gpio@7e200000 { + compatible = "brcm,bcm2835-gpio"; + reg = <0x7e200000 0xb4>; + interrupts = <0x02 0x11 0x02 0x12>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x07 0x00 0x00 0x36>; + pinctrl-names = "default"; + gpio-line-names = "ID_SDA\0ID_SCL\0SDA1\0SCL1\0GPIO_GCLK\0GPIO5\0GPIO6\0SPI_CE1_N\0SPI_CE0_N\0SPI_MISO\0SPI_MOSI\0SPI_SCLK\0GPIO12\0GPIO13\0TXD1\0RXD1\0GPIO16\0GPIO17\0GPIO18\0GPIO19\0GPIO20\0GPIO21\0GPIO22\0GPIO23\0GPIO24\0GPIO25\0GPIO26\0GPIO27\0HDMI_HPD_N\0STATUS_LED_G\0CTS0\0RTS0\0TXD0\0RXD0\0SD1_CLK\0SD1_CMD\0SD1_DATA0\0SD1_DATA1\0SD1_DATA2\0SD1_DATA3\0PWM0_OUT\0PWM1_OUT\0ETH_CLK\0WIFI_CLK\0SDA0\0SCL0\0SMPS_SCL\0SMPS_SDA\0SD_CLK_R\0SD_CMD_R\0SD_DATA0_R\0SD_DATA1_R\0SD_DATA2_R\0SD_DATA3_R"; + phandle = <0x07>; + + dpi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x06>; + phandle = <0x3c>; + }; + + emmc_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x07>; + phandle = <0x3d>; + }; + + emmc_gpio34 { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x3e>; + }; + + emmc_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x07>; + phandle = <0x17>; + }; + + gpclk0_gpio4 { + brcm,pins = <0x04>; + brcm,function = <0x04>; + phandle = <0x3f>; + }; + + gpclk1_gpio5 { + brcm,pins = <0x05>; + brcm,function = <0x04>; + phandle = <0x40>; + }; + + gpclk1_gpio42 { + brcm,pins = <0x2a>; + brcm,function = <0x04>; + phandle = <0x41>; + }; + + gpclk1_gpio44 { + brcm,pins = <0x2c>; + brcm,function = <0x04>; + phandle = <0x42>; + }; + + gpclk2_gpio6 { + brcm,pins = <0x06>; + brcm,function = <0x04>; + phandle = <0x43>; + }; + + gpclk2_gpio43 { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x44>; + }; + + i2c0_gpio0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x12>; + }; + + i2c0_gpio28 { + brcm,pins = <0x1c 0x1d>; + brcm,function = <0x04>; + phandle = <0x45>; + }; + + i2c0_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x05>; + phandle = <0x13>; + }; + + i2c1_gpio2 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x46>; + }; + + i2c1_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x06>; + phandle = <0x47>; + }; + + jtag_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x03>; + phandle = <0x48>; + }; + + pcm_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x49>; + }; + + pcm_gpio28 { + brcm,pins = <0x1c 0x1d 0x1e 0x1f>; + brcm,function = <0x06>; + phandle = <0x4a>; + }; + + sdhost_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x04>; + phandle = <0x0d>; + }; + + spi0_gpio7 { + brcm,pins = <0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x4b>; + }; + + spi0_gpio35 { + brcm,pins = <0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x04>; + phandle = <0x4c>; + }; + + spi1_gpio16 { + brcm,pins = <0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x03>; + phandle = <0x4d>; + }; + + spi2_gpio40 { + brcm,pins = <0x28 0x29 0x2a 0x2b 0x2c 0x2d>; + brcm,function = <0x03>; + phandle = <0x4e>; + }; + + uart0_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x04>; + phandle = <0x4f>; + }; + + uart0_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x07>; + phandle = <0x50>; + }; + + uart0_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x07>; + brcm,pull = <0x02 0x00>; + phandle = <0x51>; + }; + + uart0_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x52>; + }; + + uart0_gpio36 { + brcm,pins = <0x24 0x25>; + brcm,function = <0x06>; + phandle = <0x53>; + }; + + uart0_ctsrts_gpio38 { + brcm,pins = <0x26 0x27>; + brcm,function = <0x06>; + phandle = <0x54>; + }; + + uart1_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x02>; + phandle = <0x55>; + }; + + uart1_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x02>; + phandle = <0x56>; + }; + + uart1_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x02>; + phandle = <0x57>; + }; + + uart1_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x02>; + phandle = <0x58>; + }; + + uart1_gpio40 { + brcm,pins = <0x28 0x29>; + brcm,function = <0x02>; + phandle = <0x59>; + }; + + uart1_ctsrts_gpio42 { + brcm,pins = <0x2a 0x2b>; + brcm,function = <0x02>; + phandle = <0x5a>; + }; + + i2c_slave_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x07>; + phandle = <0x5b>; + }; + + jtag_gpio4 { + brcm,pins = <0x04 0x05 0x06 0x0c 0x0d>; + brcm,function = <0x02>; + phandle = <0x5c>; + }; + + pwm0_gpio12 { + brcm,pins = <0x0c>; + brcm,function = <0x04>; + phandle = <0x5d>; + }; + + pwm0_gpio18 { + brcm,pins = <0x12>; + brcm,function = <0x02>; + phandle = <0x5e>; + }; + + pwm0_gpio40 { + brcm,pins = <0x28>; + brcm,function = <0x04>; + phandle = <0x5f>; + }; + + pwm1_gpio13 { + brcm,pins = <0x0d>; + brcm,function = <0x04>; + phandle = <0x60>; + }; + + pwm1_gpio19 { + brcm,pins = <0x13>; + brcm,function = <0x02>; + phandle = <0x61>; + }; + + pwm1_gpio41 { + brcm,pins = <0x29>; + brcm,function = <0x04>; + phandle = <0x62>; + }; + + pwm1_gpio45 { + brcm,pins = <0x2d>; + brcm,function = <0x04>; + phandle = <0x63>; + }; + + dpi_18bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + brcm,pull = <0x00>; + phandle = <0x64>; + }; + + dpi_18bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + phandle = <0x65>; + }; + + dpi_18bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x66>; + }; + + dpi_18bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x67>; + }; + + dpi_16bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x68>; + }; + + dpi_16bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x69>; + }; + + dpi_16bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6a>; + }; + + dpi_16bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6b>; + }; + + gpioout { + brcm,pins = <0x06>; + brcm,function = <0x01>; + phandle = <0x6c>; + }; + + alt0 { + brcm,pins = <0x04 0x05 0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x6d>; + }; + + spi0_pins { + brcm,pins = <0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x0f>; + }; + + spi0_cs_pins { + brcm,pins = <0x08 0x07>; + brcm,function = <0x01>; + phandle = <0x10>; + }; + + i2c0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x6e>; + }; + + i2c1 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x18>; + }; + + i2s { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x0e>; + }; + + sdio_pins { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x1e>; + }; + + bt_pins { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x0a>; + }; + + uart0_pins { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x09>; + }; + + uart1_pins { + brcm,pins; + brcm,function; + brcm,pull; + phandle = <0x16>; + }; + + audio_pins { + brcm,pins = <0x28 0x29>; + brcm,function = <0x04>; + phandle = <0x20>; + }; + }; + + serial@7e201000 { + compatible = "arm,pl011\0arm,primecell"; + reg = <0x7e201000 0x200>; + interrupts = <0x02 0x19>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk\0apb_pclk"; + arm,primecell-periphid = <0x241011>; + cts-event-workaround; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x09 0x0a>; + status = "okay"; + phandle = <0x26>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <0x2dc6c0>; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x33>; + }; + }; + + mmc@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <0x02 0x18>; + clocks = <0x08 0x14>; + status = "okay"; + dmas = <0x0c 0x2000000d>; + dma-names = "rx-tx"; + bus-width = <0x04>; + brcm,overclock-50 = <0x00>; + brcm,pio-limit = <0x01>; + firmware = <0x06>; + pinctrl-names = "default"; + pinctrl-0 = <0x0d>; + phandle = <0x2f>; + }; + + i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; + reg = <0x7e203000 0x24>; + clocks = <0x08 0x1f>; + status = "disabled"; + dmas = <0x0c 0x02 0x0c 0x03>; + dma-names = "tx\0rx"; + #sound-dai-cells = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x0e>; + phandle = <0x28>; + }; + + spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x200>; + interrupts = <0x02 0x16>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + dmas = <0x0c 0x06 0x0c 0x07>; + dma-names = "tx\0rx"; + pinctrl-names = "default"; + pinctrl-0 = <0x0f 0x10>; + cs-gpios = <0x07 0x08 0x01 0x07 0x07 0x01>; + phandle = <0x29>; + + spidev@0 { + compatible = "spidev"; + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x6f>; + }; + + spidev@1 { + compatible = "spidev"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x70>; + }; + }; + + i2c@7e205000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e205000 0x200>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x11>; + }; + + i2c0mux { + compatible = "i2c-mux-pinctrl"; + #address-cells = <0x01>; + #size-cells = <0x00>; + i2c-parent = <0x11>; + pinctrl-names = "i2c0\0i2c_csi_dsi"; + status = "disabled"; + pinctrl-0 = <0x12>; + pinctrl-1 = <0x13>; + phandle = <0x2a>; + + i2c@0 { + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x71>; + }; + + i2c@1 { + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x72>; + }; + }; + + dpi@7e208000 { + compatible = "brcm,bcm2835-dpi"; + reg = <0x7e208000 0x8c>; + clocks = <0x08 0x14 0x08 0x2c>; + clock-names = "core\0pixel"; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x73>; + }; + + dsi@7e209000 { + compatible = "brcm,bcm2835-dsi0"; + reg = <0x7e209000 0x78>; + interrupts = <0x02 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x20 0x08 0x2f 0x08 0x31>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi0_byte\0dsi0_ddr2\0dsi0_ddr"; + status = "disabled"; + power-domains = <0x14 0x11>; + phandle = <0x04>; + }; + + aux@7e215000 { + compatible = "brcm,bcm2835-aux"; + #clock-cells = <0x01>; + reg = <0x7e215000 0x08>; + clocks = <0x08 0x14>; + phandle = <0x15>; + }; + + serial@7e215040 { + compatible = "brcm,bcm2835-aux-uart"; + reg = <0x7e215040 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x00>; + status = "okay"; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x16>; + phandle = <0x27>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = "\0\a\b"; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x74>; + }; + }; + + spi@7e215080 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e215080 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x75>; + }; + + spi@7e2150c0 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e2150c0 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x02>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x76>; + }; + + pwm@7e20c000 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x7e20c000 0x28>; + clocks = <0x08 0x1e>; + assigned-clocks = <0x08 0x1e>; + assigned-clock-rates = <0x989680>; + #pwm-cells = <0x02>; + status = "disabled"; + phandle = <0x77>; + }; + + mmc@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + status = "disabled"; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x17>; + bus-width = <0x04>; + phandle = <0x30>; + }; + + hvs@7e400000 { + compatible = "brcm,bcm2835-hvs"; + reg = <0x7e400000 0x6000>; + interrupts = <0x02 0x01>; + status = "disabled"; + phandle = <0x78>; + }; + + dsi@7e700000 { + compatible = "brcm,bcm2835-dsi1"; + reg = <0x7e700000 0x8c>; + interrupts = <0x02 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x23 0x08 0x30 0x08 0x32>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi1_byte\0dsi1_ddr2\0dsi1_ddr"; + status = "disabled"; + power-domains = <0x14 0x12>; + phandle = <0x05>; + }; + + i2c@7e804000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e804000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x18>; + clock-frequency = <0x186a0>; + phandle = <0x2b>; + }; + + usb@7e980000 { + compatible = "brcm,bcm2708-usb"; + reg = <0x7e980000 0x10000 0x7e006000 0x1000>; + interrupts = <0x01 0x09 0x02 0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x19>; + clock-names = "otg"; + phys = <0x1a>; + phy-names = "usb2-phy"; + interrupt-names = "usb\0soft"; + power-domains = <0x14 0x06>; + phandle = <0x79>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet@1 { + compatible = "usb424,7800"; + reg = <0x01>; + phandle = <0x7a>; + + mdio { + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet-phy@1 { + reg = <0x01>; + microchip,led-modes = <0x01 0x06>; + microchip,eee-enabled; + microchip,tx-lpi-timer = <0x258>; + microchip,downshift-after = <0x02>; + phandle = <0x36>; + }; + }; + }; + }; + }; + }; + + dma@7e007000 { + compatible = "brcm,bcm2835-dma"; + reg = <0x7e007000 0xf00>; + interrupts = <0x01 0x10 0x01 0x11 0x01 0x12 0x01 0x13 0x01 0x14 0x01 0x15 0x01 0x16 0x01 0x17 0x01 0x18 0x01 0x19 0x01 0x1a 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1c>; + interrupt-names = "dma0\0dma1\0dma2\0dma3\0dma4\0dma5\0dma6\0dma7\0dma8\0dma9\0dma10\0dma11\0dma12\0dma13\0dma14\0dma-shared-all"; + #dma-cells = <0x01>; + brcm,dma-channel-mask = <0x7f35>; + phandle = <0x0c>; + }; + + interrupt-controller@7e00b200 { + compatible = "brcm,bcm2836-armctrl-ic"; + reg = <0x7e00b200 0x200>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + interrupts = <0x08 0x04>; + phandle = <0x01>; + }; + + watchdog@7e100000 { + compatible = "brcm,bcm2835-pm\0brcm,bcm2835-pm-wdt"; + #power-domain-cells = <0x01>; + #reset-cells = <0x01>; + reg = <0x7e100000 0x114 0x7e00a000 0x24>; + clocks = <0x08 0x15 0x08 0x1d 0x08 0x17 0x08 0x16>; + clock-names = "v3d\0peri_image\0h264\0isp"; + system-power-controller; + phandle = <0x2d>; + }; + + rng@7e104000 { + compatible = "brcm,bcm2835-rng"; + reg = <0x7e104000 0x10>; + interrupts = <0x02 0x1d>; + phandle = <0x2e>; + }; + + pixelvalve@7e206000 { + compatible = "brcm,bcm2835-pixelvalve0"; + reg = <0x7e206000 0x100>; + interrupts = <0x02 0x0d>; + status = "disabled"; + phandle = <0x7b>; + }; + + pixelvalve@7e207000 { + compatible = "brcm,bcm2835-pixelvalve1"; + reg = <0x7e207000 0x100>; + interrupts = <0x02 0x0e>; + status = "disabled"; + phandle = <0x7c>; + }; + + thermal@7e212000 { + compatible = "brcm,bcm2837-thermal"; + reg = <0x7e212000 0x08>; + clocks = <0x08 0x1b>; + #thermal-sensor-cells = <0x00>; + status = "okay"; + phandle = <0x02>; + }; + + i2c@7e805000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e805000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x1d>; + }; + + vec@7e806000 { + compatible = "brcm,bcm2835-vec"; + reg = <0x7e806000 0x1000>; + clocks = <0x1c 0x0f>; + interrupts = <0x02 0x1b>; + status = "disabled"; + power-domains = <0x14 0x07>; + phandle = <0x7d>; + }; + + pixelvalve@7e807000 { + compatible = "brcm,bcm2835-pixelvalve2"; + reg = <0x7e807000 0x100>; + interrupts = <0x02 0x0a>; + status = "disabled"; + phandle = <0x7e>; + }; + + hdmi@7e902000 { + compatible = "brcm,bcm2835-hdmi"; + reg = <0x7e902000 0x600 0x7e808000 0x100>; + reg-names = "hdmi\0hd"; + interrupts = <0x02 0x08 0x02 0x09>; + ddc = <0x1d>; + clocks = <0x1c 0x09 0x1c 0x0d>; + clock-names = "pixel\0hdmi"; + dmas = <0x0c 0x9000011>; + dma-names = "audio-rx"; + status = "disabled"; + power-domains = <0x14 0x05>; + hpd-gpios = <0x07 0x1c 0x01>; + phandle = <0x7f>; + }; + + v3d@7ec00000 { + compatible = "brcm,vc4-v3d"; + reg = <0x7ec00000 0x1000>; + interrupts = <0x01 0x0a>; + power-domains = <0x14 0x0a>; + status = "disabled"; + phandle = <0x80>; + }; + + gpu { + compatible = "brcm,bcm2835-vc4"; + status = "disabled"; + raspberrypi,firmware = <0x06>; + phandle = <0x81>; + }; + + local_intc@40000000 { + compatible = "brcm,bcm2836-l1-intc"; + reg = <0x40000000 0x100>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + phandle = <0x1b>; + }; + + mmcnr@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + non-removable; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x1e>; + bus-width = <0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x31>; + + wifi@1 { + reg = <0x01>; + compatible = "brcm,bcm4329-fmac"; + phandle = <0x82>; + }; + }; + + firmwarekms@7e600000 { + compatible = "raspberrypi,rpi-firmware-kms"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + brcm,firmware = <0x06>; + status = "disabled"; + phandle = <0x83>; + }; + + smi@7e600000 { + compatible = "brcm,bcm2835-smi"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + clocks = <0x08 0x2a>; + assigned-clocks = <0x08 0x2a>; + assigned-clock-rates = <0x7735940>; + dmas = <0x0c 0x04>; + dma-names = "rx-tx"; + status = "disabled"; + phandle = <0x84>; + }; + + csi@7e800000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e800000 0x800 0x7e802000 0x04>; + interrupts = <0x02 0x06>; + clocks = <0x08 0x2d 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + phandle = <0x85>; + }; + + csi@7e801000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e801000 0x800 0x7e802004 0x04>; + interrupts = <0x02 0x07>; + clocks = <0x08 0x2e 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0d>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + brcm,num-data-lanes = <0x02>; + phandle = <0x86>; + }; + + axiperf { + compatible = "brcm,bcm2835-axiperf"; + reg = <0x7e009800 0x100 0x7ee08000 0x100>; + firmware = <0x06>; + status = "disabled"; + phandle = <0x32>; + }; + + firmware { + compatible = "raspberrypi,bcm2835-firmware\0simple-mfd"; + #address-cells = <0x01>; + #size-cells = <0x01>; + mboxes = <0x1f>; + dma-ranges; + phandle = <0x06>; + + clocks { + compatible = "raspberrypi,firmware-clocks"; + #clock-cells = <0x01>; + phandle = <0x1c>; + }; + + vcio { + compatible = "raspberrypi,vcio"; + phandle = <0x87>; + }; + + expgpio { + compatible = "raspberrypi,firmware-gpio"; + gpio-controller; + #gpio-cells = <0x02>; + gpio-line-names = "BT_ON\0WL_ON\0PWR_LED_R\0LAN_RUN\0NC\0CAM_GPIO0\0CAM_GPIO1\0NC"; + status = "okay"; + phandle = <0x0b>; + }; + }; + + power { + compatible = "raspberrypi,bcm2835-power"; + firmware = <0x06>; + #power-domain-cells = <0x01>; + phandle = <0x14>; + }; + + mailbox@7e00b840 { + compatible = "brcm,bcm2836-vchiq\0brcm,bcm2835-vchiq"; + reg = <0x7e00b840 0x3c>; + interrupts = <0x00 0x02>; + phandle = <0x88>; + + bcm2835_audio { + compatible = "brcm,bcm2835-audio"; + brcm,firmware = <0x06>; + brcm,pwm-channels = <0x08>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x20>; + phandle = <0x2c>; + }; + }; + + gpiomem { + compatible = "brcm,bcm2835-gpiomem"; + reg = <0x7e200000 0x1000>; + }; + + fb { + compatible = "brcm,bcm2708-fb"; + firmware = <0x06>; + status = "okay"; + phandle = <0x89>; + }; + + sound { + status = "disabled"; + phandle = <0x8a>; + }; + }; + + clocks { + + clk-osc { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "osc"; + clock-frequency = <0x124f800>; + phandle = <0x03>; + }; + + clk-usb { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "otg"; + clock-frequency = <0x1c9c3800>; + phandle = <0x19>; + }; + }; + + phy { + compatible = "usb-nop-xceiv"; + #phy-cells = <0x00>; + phandle = <0x1a>; + }; + + arm-pmu { + compatible = "arm,cortex-a53-pmu\0arm,cortex-a7-pmu"; + interrupt-parent = <0x1b>; + interrupts = <0x09 0x04>; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupt-parent = <0x1b>; + interrupts = <0x00 0x04 0x01 0x04 0x03 0x04 0x02 0x04>; + always-on; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + enable-method = "brcm,bcm2836-smp"; + phandle = <0x8b>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x00>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xd8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x22>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x01>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x23>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x02>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x24>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x03>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xf0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x25>; + }; + + l2-cache0 { + compatible = "cache"; + cache-size = <0x80000>; + cache-line-size = <0x40>; + cache-sets = <0x200>; + cache-level = <0x02>; + phandle = <0x21>; + }; + }; + + cam1_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam1-reg"; + enable-active-high; + status = "okay"; + gpio = <0x0b 0x05 0x00>; + phandle = <0x8c>; + }; + + cam1_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8d>; + }; + + cam0_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam0-reg"; + enable-active-high; + status = "disabled"; + phandle = <0x8e>; + }; + + cam0_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8f>; + }; + + cam_dummy_reg { + compatible = "regulator-fixed"; + regulator-name = "cam-dummy-reg"; + status = "okay"; + phandle = <0x90>; + }; + + __overrides__ { + cam0-pwdn-ctrl; + cam0-pwdn; + cam0-led-ctrl; + cam0-led; + arm_freq = "\0\0\0\"clock-frequency:0\0\0\0\0#clock-frequency:0\0\0\0\0$clock-frequency:0\0\0\0\0%clock-frequency:0"; + cache_line_size; + uart0 = "\0\0\0&status"; + uart1 = "\0\0\0'status"; + i2s = "\0\0\0(status"; + spi = "\0\0\0)status"; + i2c0 = [00 00 00 11 73 74 61 74 75 73 00 00 00 00 2a 73 74 61 74 75 73 00]; + i2c1 = "\0\0\0+status"; + i2c0_baudrate = [00 00 00 11 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + i2c1_baudrate = "\0\0\0+clock-frequency:0"; + audio = "\0\0\0,status"; + watchdog = "\0\0\0-status"; + random = "\0\0\0.status"; + sd_overclock = "\0\0\0/brcm,overclock-50:0"; + sd_force_pio = "\0\0\0/brcm,force-pio?"; + sd_pio_limit = "\0\0\0/brcm,pio-limit:0"; + sd_debug = "\0\0\0/brcm,debug"; + sdio_overclock = "\0\0\00brcm,overclock-50:0\0\0\0\01brcm,overclock-50:0"; + axiperf = "\0\0\02status"; + i2c2_iknowwhatimdoing = [00 00 00 1d 73 74 61 74 75 73 00]; + i2c2_baudrate = [00 00 00 1d 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + sd_poll_once = "\0\0\0/non-removable?"; + krnbt = "\0\0\03status"; + krnbt_baudrate = "\0\0\03max-speed:0"; + act_led_gpio = "\0\0\04gpios:4"; + act_led_activelow = "\0\0\04gpios:8"; + act_led_trigger = "\0\0\04linux,default-trigger"; + pwr_led_gpio = "\0\0\05gpios:4"; + pwr_led_activelow = "\0\0\05gpios:8"; + pwr_led_trigger = "\0\0\05linux,default-trigger"; + eee = "\0\0\06microchip,eee-enabled?"; + tx_lpi_timer = "\0\0\06microchip,tx-lpi-timer:0"; + eth_led0 = "\0\0\06microchip,led-modes:0"; + eth_led1 = "\0\0\06microchip,led-modes:4"; + eth_downshift_after = "\0\0\06microchip,downshift-after:0"; + eth_max_speed = "\0\0\06max-speed:0"; + }; + + leds { + compatible = "gpio-leds"; + phandle = <0x91>; + + led-act { + label = "led0"; + default-state = "keep"; + linux,default-trigger = "mmc0"; + gpios = <0x07 0x1d 0x00>; + phandle = <0x34>; + }; + + led-pwr { + label = "led1"; + linux,default-trigger = "default-on"; + gpios = <0x0b 0x02 0x01>; + phandle = <0x35>; + }; + }; + + fixedregulator_3v3 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microvolt = <0x325aa0>; + regulator-name = "3v3"; + phandle = <0x92>; + }; + + fixedregulator_5v0 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x4c4b40>; + regulator-min-microvolt = <0x4c4b40>; + regulator-name = "5v0"; + phandle = <0x93>; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00 0x00>; + }; + + __symbols__ { + rmem = "/reserved-memory"; + cma = "/reserved-memory/linux,cma"; + cpu_thermal = "/thermal-zones/cpu-thermal"; + soc = "/soc"; + txp = "/soc/txp@7e004000"; + clocks = "/soc/cprman@7e101000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + dpi_gpio0 = "/soc/gpio@7e200000/dpi_gpio0"; + emmc_gpio22 = "/soc/gpio@7e200000/emmc_gpio22"; + emmc_gpio34 = "/soc/gpio@7e200000/emmc_gpio34"; + emmc_gpio48 = "/soc/gpio@7e200000/emmc_gpio48"; + gpclk0_gpio4 = "/soc/gpio@7e200000/gpclk0_gpio4"; + gpclk1_gpio5 = "/soc/gpio@7e200000/gpclk1_gpio5"; + gpclk1_gpio42 = "/soc/gpio@7e200000/gpclk1_gpio42"; + gpclk1_gpio44 = "/soc/gpio@7e200000/gpclk1_gpio44"; + gpclk2_gpio6 = "/soc/gpio@7e200000/gpclk2_gpio6"; + gpclk2_gpio43 = "/soc/gpio@7e200000/gpclk2_gpio43"; + i2c0_gpio0 = "/soc/gpio@7e200000/i2c0_gpio0"; + i2c0_gpio28 = "/soc/gpio@7e200000/i2c0_gpio28"; + i2c0_gpio44 = "/soc/gpio@7e200000/i2c0_gpio44"; + i2c1_gpio2 = "/soc/gpio@7e200000/i2c1_gpio2"; + i2c1_gpio44 = "/soc/gpio@7e200000/i2c1_gpio44"; + jtag_gpio22 = "/soc/gpio@7e200000/jtag_gpio22"; + pcm_gpio18 = "/soc/gpio@7e200000/pcm_gpio18"; + pcm_gpio28 = "/soc/gpio@7e200000/pcm_gpio28"; + sdhost_gpio48 = "/soc/gpio@7e200000/sdhost_gpio48"; + spi0_gpio7 = "/soc/gpio@7e200000/spi0_gpio7"; + spi0_gpio35 = "/soc/gpio@7e200000/spi0_gpio35"; + spi1_gpio16 = "/soc/gpio@7e200000/spi1_gpio16"; + spi2_gpio40 = "/soc/gpio@7e200000/spi2_gpio40"; + uart0_gpio14 = "/soc/gpio@7e200000/uart0_gpio14"; + uart0_ctsrts_gpio16 = "/soc/gpio@7e200000/uart0_ctsrts_gpio16"; + uart0_ctsrts_gpio30 = "/soc/gpio@7e200000/uart0_ctsrts_gpio30"; + uart0_gpio32 = "/soc/gpio@7e200000/uart0_gpio32"; + uart0_gpio36 = "/soc/gpio@7e200000/uart0_gpio36"; + uart0_ctsrts_gpio38 = "/soc/gpio@7e200000/uart0_ctsrts_gpio38"; + uart1_gpio14 = "/soc/gpio@7e200000/uart1_gpio14"; + uart1_ctsrts_gpio16 = "/soc/gpio@7e200000/uart1_ctsrts_gpio16"; + uart1_gpio32 = "/soc/gpio@7e200000/uart1_gpio32"; + uart1_ctsrts_gpio30 = "/soc/gpio@7e200000/uart1_ctsrts_gpio30"; + uart1_gpio40 = "/soc/gpio@7e200000/uart1_gpio40"; + uart1_ctsrts_gpio42 = "/soc/gpio@7e200000/uart1_ctsrts_gpio42"; + i2c_slave_gpio18 = "/soc/gpio@7e200000/i2c_slave_gpio18"; + jtag_gpio4 = "/soc/gpio@7e200000/jtag_gpio4"; + pwm0_gpio12 = "/soc/gpio@7e200000/pwm0_gpio12"; + pwm0_gpio18 = "/soc/gpio@7e200000/pwm0_gpio18"; + pwm0_gpio40 = "/soc/gpio@7e200000/pwm0_gpio40"; + pwm1_gpio13 = "/soc/gpio@7e200000/pwm1_gpio13"; + pwm1_gpio19 = "/soc/gpio@7e200000/pwm1_gpio19"; + pwm1_gpio41 = "/soc/gpio@7e200000/pwm1_gpio41"; + pwm1_gpio45 = "/soc/gpio@7e200000/pwm1_gpio45"; + dpi_18bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio0"; + dpi_18bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio2"; + dpi_18bit_gpio0 = "/soc/gpio@7e200000/dpi_18bit_gpio0"; + dpi_18bit_gpio2 = "/soc/gpio@7e200000/dpi_18bit_gpio2"; + dpi_16bit_gpio0 = "/soc/gpio@7e200000/dpi_16bit_gpio0"; + dpi_16bit_gpio2 = "/soc/gpio@7e200000/dpi_16bit_gpio2"; + dpi_16bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio0"; + dpi_16bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio2"; + gpioout = "/soc/gpio@7e200000/gpioout"; + alt0 = "/soc/gpio@7e200000/alt0"; + spi0_pins = "/soc/gpio@7e200000/spi0_pins"; + spi0_cs_pins = "/soc/gpio@7e200000/spi0_cs_pins"; + i2c0_pins = "/soc/gpio@7e200000/i2c0"; + i2c1_pins = "/soc/gpio@7e200000/i2c1"; + i2s_pins = "/soc/gpio@7e200000/i2s"; + sdio_pins = "/soc/gpio@7e200000/sdio_pins"; + bt_pins = "/soc/gpio@7e200000/bt_pins"; + uart0_pins = "/soc/gpio@7e200000/uart0_pins"; + uart1_pins = "/soc/gpio@7e200000/uart1_pins"; + audio_pins = "/soc/gpio@7e200000/audio_pins"; + uart0 = "/soc/serial@7e201000"; + bt = "/soc/serial@7e201000/bluetooth"; + sdhost = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + spi0 = "/soc/spi@7e204000"; + spi = "/soc/spi@7e204000"; + spidev0 = "/soc/spi@7e204000/spidev@0"; + spidev1 = "/soc/spi@7e204000/spidev@1"; + i2c0if = "/soc/i2c@7e205000"; + i2c0mux = "/soc/i2c0mux"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c_csi_dsi = "/soc/i2c0mux/i2c@1"; + dpi = "/soc/dpi@7e208000"; + dsi0 = "/soc/dsi@7e209000"; + aux = "/soc/aux@7e215000"; + uart1 = "/soc/serial@7e215040"; + minibt = "/soc/serial@7e215040/bluetooth"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + pwm = "/soc/pwm@7e20c000"; + mmc = "/soc/mmc@7e300000"; + sdhci = "/soc/mmc@7e300000"; + hvs = "/soc/hvs@7e400000"; + dsi1 = "/soc/dsi@7e700000"; + i2c1 = "/soc/i2c@7e804000"; + usb = "/soc/usb@7e980000"; + ethernet = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + eth_phy = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1/mdio/ethernet-phy@1"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + pm = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + pixelvalve0 = "/soc/pixelvalve@7e206000"; + pixelvalve1 = "/soc/pixelvalve@7e207000"; + thermal = "/soc/thermal@7e212000"; + i2c2 = "/soc/i2c@7e805000"; + vec = "/soc/vec@7e806000"; + pixelvalve2 = "/soc/pixelvalve@7e807000"; + hdmi = "/soc/hdmi@7e902000"; + v3d = "/soc/v3d@7ec00000"; + vc4 = "/soc/gpu"; + local_intc = "/soc/local_intc@40000000"; + mmcnr = "/soc/mmcnr@7e300000"; + brcmf = "/soc/mmcnr@7e300000/wifi@1"; + firmwarekms = "/soc/firmwarekms@7e600000"; + smi = "/soc/smi@7e600000"; + csi0 = "/soc/csi@7e800000"; + csi1 = "/soc/csi@7e801000"; + axiperf = "/soc/axiperf"; + firmware = "/soc/firmware"; + firmware_clocks = "/soc/firmware/clocks"; + vcio = "/soc/firmware/vcio"; + expgpio = "/soc/firmware/expgpio"; + power = "/soc/power"; + vchiq = "/soc/mailbox@7e00b840"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + fb = "/soc/fb"; + sound = "/soc/sound"; + clk_osc = "/clocks/clk-osc"; + clk_usb = "/clocks/clk-usb"; + usbphy = "/phy"; + cpus = "/cpus"; + cpu0 = "/cpus/cpu@0"; + cpu1 = "/cpus/cpu@1"; + cpu2 = "/cpus/cpu@2"; + cpu3 = "/cpus/cpu@3"; + l2 = "/cpus/l2-cache0"; + cam1_reg = "/cam1_regulator"; + cam1_clk = "/cam1_clk"; + cam0_regulator = "/cam0_regulator"; + cam0_clk = "/cam0_clk"; + cam0_reg = "/cam_dummy_reg"; + cam_dummy_reg = "/cam_dummy_reg"; + leds = "/leds"; + act_led = "/leds/led-act"; + pwr_led = "/leds/led-pwr"; + vdd_3v3_reg = "/fixedregulator_3v3"; + vdd_5v0_reg = "/fixedregulator_5v0"; + }; +}; diff --git a/lab2/test/lib/dtb_parse/types.h b/lab2/test/lib/dtb_parse/types.h new file mode 100644 index 000000000..94f612c66 --- /dev/null +++ b/lab2/test/lib/dtb_parse/types.h @@ -0,0 +1,26 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#define NULL ((void*)0) + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) +#endif diff --git a/lab2/test/lib/list/Makefile b/lab2/test/lib/list/Makefile new file mode 100644 index 000000000..764af75c6 --- /dev/null +++ b/lab2/test/lib/list/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/list.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab2/test/lib/list/test b/lab2/test/lib/list/test new file mode 100755 index 000000000..dd63c9895 Binary files /dev/null and b/lab2/test/lib/list/test differ diff --git a/lab2/test/lib/list/test.c b/lab2/test/lib/list/test.c new file mode 100644 index 000000000..b568a42a4 --- /dev/null +++ b/lab2/test/lib/list/test.c @@ -0,0 +1,59 @@ +#include "lib/list.h" +#include +#include +#include +struct student{ + int id; + char name[100]; + struct list_head list; +}; + +struct student* create_student(int id, char* name){ + struct student* s = (struct student*)malloc(sizeof(struct student)); + s->id = id; + strcpy(s->name, name); + return s; +} +void print_student(struct student* s){ + printf("------------------------------------------\n"); + printf(" id: %d\n", s->id); + printf(" name: %s\n", s->name); + printf("------------------------------------------\n"); +} +int main(void){ + struct list_head* node, head; + INIT_LIST_HEAD(&head); + + if(list_empty(&head)){ + printf("List is empty\n"); + } + list_add(&create_student(13, "xiaobye")->list, &head); + list_add(&create_student(35, "test01")->list, &head); + list_add(&create_student(34, "test02")->list, &head); + + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + if(!list_empty(&head)){ + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + } + + + return 0; +} + diff --git a/lab2/test/lib/malloc/.gdb_history b/lab2/test/lib/malloc/.gdb_history new file mode 100644 index 000000000..1b332373d --- /dev/null +++ b/lab2/test/lib/malloc/.gdb_history @@ -0,0 +1,9 @@ +b main +run +ni +x/gx $rax +x/gx $rax - 0x10 + call malloc(1) +x/gx $rax - 0x10 +x/gx 0x5555555592c0 +quit diff --git a/lab2/test/lib/malloc/Makefile b/lab2/test/lib/malloc/Makefile new file mode 100644 index 000000000..2aedecaf1 --- /dev/null +++ b/lab2/test/lib/malloc/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/simple_malloc.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab2/test/lib/malloc/test b/lab2/test/lib/malloc/test new file mode 100755 index 000000000..194c23579 Binary files /dev/null and b/lab2/test/lib/malloc/test differ diff --git a/lab2/test/lib/malloc/test.c b/lab2/test/lib/malloc/test.c new file mode 100644 index 000000000..374f6deff --- /dev/null +++ b/lab2/test/lib/malloc/test.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include "lib/simple_malloc.h" + +#define RANGE 1000 +int main(void){ + void* cur,* next; + size_t req_size, real_size; + void* p = mmap( NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 ); + init_malloc_state(p); + srand((unsigned)time(0)); + + for(int i = 0 ; i < 30 ; i++){ + req_size = (uint64_t)rand() % RANGE; + cur = simple_malloc(req_size); + next = get_remainder(); + real_size = (uint64_t)next - (uint64_t)cur; + printf("cur: %p, next: %p, request size: %lu, real size: %lu, legal: %d\n", cur, next , req_size, real_size, (req_size <= real_size) && !(real_size % 16)); + } + + return 0; +} diff --git a/lab2/test/lib/malloc/test.py b/lab2/test/lib/malloc/test.py new file mode 100644 index 000000000..cce0d171c --- /dev/null +++ b/lab2/test/lib/malloc/test.py @@ -0,0 +1,9 @@ +def req2size(val, a): + if val < 16: + print(val,": ", hex(32)) + else: + print(val,": ",hex((val + 16 + (a - 1)) & ~(a-1))) + +for i in range(0, 64): + req2size(i, 16) + diff --git a/lab2/test/lib/string/Makefile b/lab2/test/lib/string/Makefile new file mode 100644 index 000000000..e7e0f12c1 --- /dev/null +++ b/lab2/test/lib/string/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/string.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab2/test/lib/string/test b/lab2/test/lib/string/test new file mode 100755 index 000000000..439093564 Binary files /dev/null and b/lab2/test/lib/string/test differ diff --git a/lab2/test/lib/string/test.c b/lab2/test/lib/string/test.c new file mode 100644 index 000000000..c4c3b6401 --- /dev/null +++ b/lab2/test/lib/string/test.c @@ -0,0 +1,14 @@ +#include "lib/string.h" +#include + +int main(void){ + char *name = ""; + printf("%s, len=%lu\n", name, strlen(name)); + + name = "test"; + printf("%s, len=%lu\n", name, strlen(name)); + + name = "xiaobye"; + printf("%s, len=%lu\n", name, strlen(name)); + return 0; +} diff --git a/lab2/tmp b/lab2/tmp new file mode 100644 index 000000000..e6016bf3e --- /dev/null +++ b/lab2/tmp @@ -0,0 +1,1449 @@ +sudo qemu-system-aarch64 -M raspi3b -kernel /home/xiaobye/Documents/OSDI/osc2022/lab2/build/kernel8.img -display none -serial null -serial stdio -initrd tools/cpio/initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + { + compatible ; + model ; + #address-cells ; + #size-cells ; + interrupt-parent ; + memory@0 { + reg ; + device_type ; + } + aliases { + serial0 ; + serial1 ; + audio ; + aux ; + sound ; + soc ; + dma ; + intc ; + watchdog ; + random ; + mailbox ; + gpio ; + uart0 ; + uart1 ; + sdhost ; + mmc ; + mmc1 ; + mmc0 ; + i2s ; + i2c0 ; + i2c1 ; + i2c10 ; + spi0 ; + spi1 ; + spi2 ; + usb ; + leds ; + fb ; + thermal ; + axiperf ; + i2c2 ; + ethernet0 ; + } + chosen { + linux,initrd-end ; + linux,initrd-start ; + bootargs ; + } + reserved-memory { + #address-cells ; + #size-cells ; + ranges ; + phandle ; + linux,cma { + compatible ; + size ; + reusable ; + linux,cma-default ; + phandle ; + } + } + thermal-zones { + cpu-thermal { + polling-delay-passive ; + polling-delay ; + thermal-sensors ; + coefficients ; + phandle ; + cooling-maps { + } + } + } + soc { + compatible ; + #address-cells ; + #size-cells ; + ranges ; + dma-ranges ; + phandle ; + txp@7e004000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + cprman@7e101000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + firmware ; + phandle ; + } + mailbox@7e00b880 { + compatible ; + reg ; + interrupts ; + #mbox-cells ; + phandle ; + } + gpio@7e200000 { + compatible ; + reg ; + interrupts ; + gpio-controller ; + #gpio-cells ; + interrupt-controller ; + #interrupt-cells ; + gpio-ranges ; + pinctrl-names ; + gpio-line-names ; + phandle ; + dpi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio34 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + emmc_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk0_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio5 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio6 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio43 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + i2c0_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + sdhost_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio7 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio35 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi1_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi2_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio32 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio36 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio38 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio32 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c_slave_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio12 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio13 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio19 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio41 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio45 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + dpi_18bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpioout { + brcm,pins ; + brcm,function ; + phandle ; + } + alt0 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_cs_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2s { + brcm,pins ; + brcm,function ; + phandle ; + } + sdio_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + bt_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart1_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + audio_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + } + serial@7e201000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + arm,primecell-periphid ; + cts-event-workaround ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + status ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + mmc@7e202000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + bus-width ; + brcm,overclock-50 ; + brcm,pio-limit ; + firmware ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + i2s@7e203000 { + compatible ; + reg ; + clocks ; + status ; + dmas ; + dma-names ; + #sound-dai-cells ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + spi@7e204000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + dmas ; + dma-names ; + pinctrl-names ; + pinctrl-0 ; + cs-gpios ; + phandle ; + spidev@0 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + spidev@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + } + i2c@7e205000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + i2c0mux { + compatible ; + #address-cells ; + #size-cells ; + i2c-parent ; + pinctrl-names ; + status ; + pinctrl-0 ; + pinctrl-1 ; + phandle ; + i2c@0 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + i2c@1 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + } + dpi@7e208000 { + compatible ; + reg ; + clocks ; + clock-names ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + dsi@7e209000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + aux@7e215000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + phandle ; + } + serial@7e215040 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + spi@7e215080 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + spi@7e2150c0 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + pwm@7e20c000 { + compatible ; + reg ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + #pwm-cells ; + status ; + phandle ; + } + mmc@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + brcm,overclock-50 ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + phandle ; + } + hvs@7e400000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + dsi@7e700000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + i2c@7e804000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + pinctrl-names ; + pinctrl-0 ; + clock-frequency ; + phandle ; + } + usb@7e980000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + clocks ; + clock-names ; + phys ; + phy-names ; + interrupt-names ; + power-domains ; + phandle ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + ethernet@1 { + compatible ; + reg ; + phandle ; + mdio { + #address-cells ; + #size-cells ; + ethernet-phy@1 { + reg ; + microchip,led-modes ; + microchip,eee-enabled ; + microchip,tx-lpi-timer ; + microchip,downshift-after ; + phandle ; + } + } + } + } + } + } + dma@7e007000 { + compatible ; + reg ; + interrupts ; + interrupt-names ; + #dma-cells ; + brcm,dma-channel-mask ; + phandle ; + } + interrupt-controller@7e00b200 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + interrupts ; + phandle ; + } + watchdog@7e100000 { + compatible ; + #power-domain-cells ; + #reset-cells ; + reg ; + clocks ; + clock-names ; + system-power-controller ; + phandle ; + } + rng@7e104000 { + compatible ; + reg ; + interrupts ; + phandle ; + } + pixelvalve@7e206000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + pixelvalve@7e207000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + thermal@7e212000 { + compatible ; + reg ; + clocks ; + #thermal-sensor-cells ; + status ; + phandle ; + } + i2c@7e805000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + vec@7e806000 { + compatible ; + reg ; + clocks ; + interrupts ; + status ; + power-domains ; + phandle ; + } + pixelvalve@7e807000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + hdmi@7e902000 { + compatible ; + reg ; + reg-names ; + interrupts ; + ddc ; + clocks ; + clock-names ; + dmas ; + dma-names ; + status ; + power-domains ; + hpd-gpios ; + phandle ; + } + v3d@7ec00000 { + compatible ; + reg ; + interrupts ; + power-domains ; + status ; + phandle ; + } + gpu { + compatible ; + status ; + raspberrypi,firmware ; + phandle ; + } + local_intc@40000000 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + phandle ; + } + mmcnr@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + dmas ; + dma-names ; + brcm,overclock-50 ; + non-removable ; + status ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + #address-cells ; + #size-cells ; + phandle ; + wifi@1 { + reg ; + compatible ; + phandle ; + } + } + firmwarekms@7e600000 { + compatible ; + reg ; + interrupts ; + brcm,firmware ; + status ; + phandle ; + } + smi@7e600000 { + compatible ; + reg ; + interrupts ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + dmas ; + dma-names ; + status ; + phandle ; + } + csi@7e800000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + phandle ; + } + csi@7e801000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + brcm,num-data-lanes ; + phandle ; + } + axiperf { + compatible ; + reg ; + firmware ; + status ; + phandle ; + } + firmware { + compatible ; + #address-cells ; + #size-cells ; + mboxes ; + dma-ranges ; + phandle ; + clocks { + compatible ; + #clock-cells ; + phandle ; + } + vcio { + compatible ; + phandle ; + } + expgpio { + compatible ; + gpio-controller ; + #gpio-cells ; + gpio-line-names ; + status ; + phandle ; + } + } + power { + compatible ; + firmware ; + #power-domain-cells ; + phandle ; + } + mailbox@7e00b840 { + compatible ; + reg ; + interrupts ; + phandle ; + bcm2835_audio { + compatible ; + brcm,firmware ; + brcm,pwm-channels ; + status ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + } + gpiomem { + compatible ; + reg ; + } + fb { + compatible ; + firmware ; + status ; + phandle ; + } + sound { + status ; + phandle ; + } + } + clocks { + clk-osc { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + clk-usb { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + } + phy { + compatible ; + #phy-cells ; + phandle ; + } + arm-pmu { + compatible ; + interrupt-parent ; + interrupts ; + } + timer { + compatible ; + interrupt-parent ; + interrupts ; + always-on ; + } + cpus { + #address-cells ; + #size-cells ; + enable-method ; + phandle ; + cpu@0 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@1 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@2 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@3 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + l2-cache0 { + compatible ; + cache-size ; + cache-line-size ; + cache-sets ; + cache-level ; + phandle ; + } + } + cam1_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + gpio ; + phandle ; + } + cam1_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam0_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + phandle ; + } + cam0_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam_dummy_reg { + compatible ; + regulator-name ; + status ; + phandle ; + } + __overrides__ { + cam0-pwdn-ctrl ; + cam0-pwdn ; + cam0-led-ctrl ; + cam0-led ; + arm_freq ; + cache_line_size ; + uart0 ; + uart1 ; + i2s ; + spi ; + i2c0 ; + i2c1 ; + i2c0_baudrate ; + i2c1_baudrate ; + audio ; + watchdog ; + random ; + sd_overclock ; + sd_force_pio ; + sd_pio_limit ; + sd_debug ; + sdio_overclock ; + axiperf ; + i2c2_iknowwhatimdoing ; + i2c2_baudrate ; + sd_poll_once ; + krnbt ; + krnbt_baudrate ; + act_led_gpio ; + act_led_activelow ; + act_led_trigger ; + pwr_led_gpio ; + pwr_led_activelow ; + pwr_led_trigger ; + eee ; + tx_lpi_timer ; + eth_led0 ; + eth_led1 ; + eth_downshift_after ; + eth_max_speed ; + } + leds { + compatible ; + phandle ; + led-act { + label ; + default-state ; + linux,default-trigger ; + gpios ; + phandle ; + } + led-pwr { + label ; + linux,default-trigger ; + gpios ; + phandle ; + } + } + fixedregulator_3v3 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + fixedregulator_5v0 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + __symbols__ { + rmem ; + cma ; + cpu_thermal ; + soc ; + txp ; + clocks ; + mailbox ; + gpio ; + dpi_gpio0 ; + emmc_gpio22 ; + emmc_gpio34 ; + emmc_gpio48 ; + gpclk0_gpio4 ; + gpclk1_gpio5 ; + gpclk1_gpio42 ; + gpclk1_gpio44 ; + gpclk2_gpio6 ; + gpclk2_gpio43 ; + i2c0_gpio0 ; + i2c0_gpio28 ; + i2c0_gpio44 ; + i2c1_gpio2 ; + i2c1_gpio44 ; + jtag_gpio22 ; + pcm_gpio18 ; + pcm_gpio28 ; + sdhost_gpio48 ; + spi0_gpio7 ; + spi0_gpio35 ; + spi1_gpio16 ; + spi2_gpio40 ; + uart0_gpio14 ; + uart0_ctsrts_gpio16 ; + uart0_ctsrts_gpio30 ; + uart0_gpio32 ; + uart0_gpio36 ; + uart0_ctsrts_gpio38 ; + uart1_gpio14 ; + uart1_ctsrts_gpio16 ; + uart1_gpio32 ; + uart1_ctsrts_gpio30 ; + uart1_gpio40 ; + uart1_ctsrts_gpio42 ; + i2c_slave_gpio18 ; + jtag_gpio4 ; + pwm0_gpio12 ; + pwm0_gpio18 ; + pwm0_gpio40 ; + pwm1_gpio13 ; + pwm1_gpio19 ; + pwm1_gpio41 ; + pwm1_gpio45 ; + dpi_18bit_cpadhi_gpio0 ; + dpi_18bit_cpadhi_gpio2 ; + dpi_18bit_gpio0 ; + dpi_18bit_gpio2 ; + dpi_16bit_gpio0 ; + dpi_16bit_gpio2 ; + dpi_16bit_cpadhi_gpio0 ; + dpi_16bit_cpadhi_gpio2 ; + gpioout ; + alt0 ; + spi0_pins ; + spi0_cs_pins ; + i2c0_pins ; + i2c1_pins ; + i2s_pins ; + sdio_pins ; + bt_pins ; + uart0_pins ; + uart1_pins ; + audio_pins ; + uart0 ; + bt ; + sdhost ; + i2s ; + spi0 ; + spi ; + spidev0 ; + spidev1 ; + i2c0if ; + i2c0mux ; + i2c0 ; + i2c_csi_dsi ; + dpi ; + dsi0 ; + aux ; + uart1 ; + minibt ; + spi1 ; + spi2 ; + pwm ; + mmc ; + sdhci ; + hvs ; + dsi1 ; + i2c1 ; + usb ; + ethernet ; + eth_phy ; + dma ; + intc ; + watchdog ; + pm ; + random ; + pixelvalve0 ; + pixelvalve1 ; + thermal ; + i2c2 ; + vec ; + pixelvalve2 ; + hdmi ; + v3d ; + vc4 ; + local_intc ; + mmcnr ; + brcmf ; + firmwarekms ; + smi ; + csi0 ; + csi1 ; + axiperf ; + firmware ; + firmware_clocks ; + vcio ; + expgpio ; + power ; + vchiq ; + audio ; + fb ; + sound ; + clk_osc ; + clk_usb ; + usbphy ; + cpus ; + cpu0 ; + cpu1 ; + cpu2 ; + cpu3 ; + l2 ; + cam1_reg ; + cam1_clk ; + cam0_regulator ; + cam0_clk ; + cam0_reg ; + cam_dummy_reg ; + leds ; + act_led ; + pwr_led ; + vdd_3v3_reg ; + vdd_5v0_reg ; + } +} +[simple_malloc.c/init_malloc_state:12] Simple heap start address: 0x8e000 + +[initrdfs.c/initrdfs_init:7] Enter initrdfs_int +[initrdfs.c/initrdfs_init:8] initrd start at 0x8000000 + +[initrdfs.c/initrdfs_init:9] initrd first 4 bytes: 37303730 + +[initrdfs.c/initrdfs_init:23] Start parsing new ascii format's cpio +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 2 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 112, iter->cur: 0x8000070 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: . +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 21 +[cpio.c/cpio_iter_parse:38] f->namesize: 6 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 140, iter->cur: 0x80000fc +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file1 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 34 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 156, iter->cur: 0x8000198 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file2.txt +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 5 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 116, iter->cur: 0x800020c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 5 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 128, iter->cur: 0x800028c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test/1234 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 0 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 11 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 124, iter->cur: 0x8000308 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: TRAILER!!! +[initrdfs.c/initrdfs_init:32] Leave initrdfs_int +text_start=0x80000, text_end=0x84000, text_size=16384 +rodata_start=0x84000, rodata_end=0x86000, rodata_size=8192 +data_start=0x86000, data_end=0x87000, data_size=4096 +bss_start=0x87000, bss_end=0x8e000, bss_size=28672 +heap_start=0x8e000 +⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀ +⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀ +⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁ +⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀ +⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀ +⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀ +⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀ +⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀ +⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀ +⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀ +⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀ +⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀ +⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀ + +# \ No newline at end of file diff --git a/lab2/tools/AUX_PERIPHERALS b/lab2/tools/AUX_PERIPHERALS new file mode 100644 index 000000000..324eb3019 --- /dev/null +++ b/lab2/tools/AUX_PERIPHERALS @@ -0,0 +1,23 @@ +0x7E215000 AUX_IRQ Auxiliary Interrupt status 3 +0x7E215004 AUX_ENABLES Auxiliary enables 3 +0x7E215040 AUX_MU_IO_REG Mini Uart I/O Data 8 +0x7E215044 AUX_MU_IER_REG Mini Uart Interrupt Enable 8 +0x7E215048 AUX_MU_IIR_REG Mini Uart Interrupt Identify 8 +0x7E21504C AUX_MU_LCR_REG Mini Uart Line Control 8 +0x7E215050 AUX_MU_MCR_REG Mini Uart Modem Control 8 +0x7E215054 AUX_MU_LSR_REG Mini Uart Line Status 8 +0x7E215058 AUX_MU_MSR_REG Mini Uart Modem Status 8 +0x7E21505C AUX_MU_SCRATCH Mini Uart Scratch 8 +0x7E215060 AUX_MU_CNTL_REG Mini Uart Extra Control 8 +0x7E215064 AUX_MU_STAT_REG Mini Uart Extra Status 32 +0x7E215068 AUX_MU_BAUD_REG Mini Uart Baudrate 16 +0x7E215080 AUX_SPI0_CNTL0_REG SPI 1 Control register 0 32 +0x7E215084 AUX_SPI0_CNTL1_REG SPI 1 Control register 1 8 +0x7E215088 AUX_SPI0_STAT_REG SPI 1 Status 32 +0x7E215090 AUX_SPI0_IO_REG SPI 1 Data 32 +0x7E215094 AUX_SPI0_PEEK_REG SPI 1 Peek 16 +0x7E2150C0 AUX_SPI1_CNTL0_REG SPI 2 Control register 0 32 +0x7E2150C4 AUX_SPI1_CNTL1_REG SPI 2 Control register 1 8 +0x7E2150C8 AUX_SPI1_STAT_REG SPI 2 Status 32 +0x7E2150D0 AUX_SPI1_IO_REG SPI 2 Data 32 +0x7E2150D4 AUX_SPI1_PEEK_REG SPI 2 Peek 16 diff --git a/lab2/tools/GPIO b/lab2/tools/GPIO new file mode 100644 index 000000000..ad2b10794 --- /dev/null +++ b/lab2/tools/GPIO @@ -0,0 +1,43 @@ +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200004 GPFSEL1 GPIO Function Select 1 32 R/W +0x7E200008 GPFSEL2 GPIO Function Select 2 32 R/W +0x7E20000C GPFSEL3 GPIO Function Select 3 32 R/W +0x7E200010 GPFSEL4 GPIO Function Select 4 32 R/W +0x7E200014 GPFSEL5 GPIO Function Select 5 32 R/W +0x7E200018 - Reserved - - +0x7E20001C GPSET0 GPIO Pin Output Set 0 32 W +0x7E200020 GPSET1 GPIO Pin Output Set 1 32 W +0x7E200024 - Reserved - - +0x7E200028 GPCLR0 GPIO Pin Output Clear 0 32 W +0x7E20002C GPCLR1 GPIO Pin Output Clear 1 32 W +0x7E200030 - Reserved - - +0x7E200034 GPLEV0 GPIO Pin Level 0 32 R +0x7E200038 GPLEV1 GPIO Pin Level 1 32 R +0x7E20003C - Reserved - - +0x7E200040 GPEDS0 GPIO Pin Event Detect Status 0 32 R/W +0x7E200044 GPEDS1 GPIO Pin Event Detect Status 1 32 R/W +0x7E200048 - Reserved - - +0x7E20004C GPREN0 GPIO Pin Rising Edge Detect Enable 0 32 R/W +0x7E200050 GPREN1 GPIO Pin Rising Edge Detect Enable 1 32 R/W +0x7E200054 - Reserved - - +0x7E200058 GPFEN0 GPIO Pin Falling Edge Detect Enable 0 32 R/W +0x7E20005C GPFEN1 GPIO Pin Falling Edge Detect Enable 1 32 R/W +0x7E200060 - Reserved - - +0x7E200064 GPHEN0 GPIO Pin High Detect Enable 0 32 R/W +0x7E200068 GPHEN1 GPIO Pin High Detect Enable 1 32 R/W +0x7E20006C - Reserved - - +0x7E200070 GPLEN0 GPIO Pin Low Detect Enable 0 32 R/W +0x7E200074 GPLEN1 GPIO Pin Low Detect Enable 1 32 R/W +0x7E200078 - Reserved - - +0x7E20007C GPAREN0 GPIO Pin Async. Rising Edge Detect 0 32 R/W +0x7E200080 GPAREN1 GPIO Pin Async. Rising Edge Detect 1 32 R/W +0x7E200084 - Reserved - - +0x7E200088 GPAFEN0 GPIO Pin Async. Falling Edge Detect 0 32 R/W +0x7E20008C GPAFEN1 GPIO Pin Async. Falling Edge Detect 1 32 R/W +0x7E200090 - Reserved - - +0x7E200094 GPPUD GPIO Pin Pull-up/down Enable 32 R/W +0x7E200098 GPPUDCLK0 GPIO Pin Pull-up/down Enable Clock 0 32 R/W +0x7E20009C GPPUDCLK1 GPIO Pin Pull-up/down Enable Clock 1 32 R/W +0x7E2000A0 - Reserved - - +0x7E2000B0 - Test 4 R/W diff --git a/lab2/tools/cpio/create_initramfs.sh b/lab2/tools/cpio/create_initramfs.sh new file mode 100755 index 000000000..2736e47fe --- /dev/null +++ b/lab2/tools/cpio/create_initramfs.sh @@ -0,0 +1,4 @@ +#! /bin/sh +cd rootfs +find . | cpio -o -H newc > ../initramfs.cpio +cd .. diff --git a/lab2/tools/cpio/initramfs.cpio b/lab2/tools/cpio/initramfs.cpio new file mode 100644 index 000000000..9f61f2371 Binary files /dev/null and b/lab2/tools/cpio/initramfs.cpio differ diff --git a/lab2/tools/cpio/rootfs/file1 b/lab2/tools/cpio/rootfs/file1 new file mode 100644 index 000000000..b7b514317 --- /dev/null +++ b/lab2/tools/cpio/rootfs/file1 @@ -0,0 +1 @@ +This is your flag!!! diff --git a/lab2/tools/cpio/rootfs/file2.txt b/lab2/tools/cpio/rootfs/file2.txt new file mode 100644 index 000000000..367edaf2d --- /dev/null +++ b/lab2/tools/cpio/rootfs/file2.txt @@ -0,0 +1 @@ +FLAG{...........................} diff --git a/lab2/tools/cpio/rootfs/test/1234 b/lab2/tools/cpio/rootfs/test/1234 new file mode 100644 index 000000000..81c545efe --- /dev/null +++ b/lab2/tools/cpio/rootfs/test/1234 @@ -0,0 +1 @@ +1234 diff --git a/lab2/tools/gen.sh b/lab2/tools/gen.sh new file mode 100755 index 000000000..235b38c28 --- /dev/null +++ b/lab2/tools/gen.sh @@ -0,0 +1,24 @@ +#! /bin/sh +BUS_IO_BASE=0x7E000000 +PHY_IO_BASE=0x3F000000 +echo "/* Register's offset of GPIO */" +grep -v " - " GPIO | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + +echo "" +echo "" +echo "/* Register's offset of UART and SPI */" +grep -v " - " AUX_PERIPHERALS | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + + diff --git a/lab2/uart_upload.py b/lab2/uart_upload.py new file mode 100755 index 000000000..9a2a52d80 --- /dev/null +++ b/lab2/uart_upload.py @@ -0,0 +1,69 @@ +#! /usr/bin/python3 + +import sys +import struct +import serial +import os +import time +if len(sys.argv) < 4: + print(sys.argv[0], "", "", "") + sys.exit(-1) + +tty_name = sys.argv[1] +kernel_name = sys.argv[2] +base_addr = int(sys.argv[3], 16) + +ser = None + +def readline(): + os.write(1,b'[From bootloader]: ') + while 1: + c = ser.read(1) + if c == b'\n': + os.write(1, b'\n') + return + elif c != b'\r': + os.write(1, c) + + + +with open(kernel_name, "rb",) as kernel: + kernel_buf = kernel.read() + kernel_size = len(kernel_buf) + + + while(1): + ser = serial.Serial( + # Serial Port to read the data from + port = tty_name, + #Rate at which the information is shared to the communication channel + baudrate = 115200, + timeout = .1 + ) + + # start upload kernel to rasberry pi 3b+ by uart interface + # start header + ser.write(b"A") + ser.flush() + readline() + + # transfer kernel base address and kernel size ( both are 8 bytes ) in little endian + ser.write(struct.pack(" 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + + +master_core: +// stack + ldr x1, =_start + mov sp, x1 + +// recover dtb to x0 + adr x1, _dtb + ldr x0, [x1] + + +// jump to kernel_main + bl uart_recv_kernel + + b proc_hang + +// rebase our boot loader +rebase_bootloader: + // manipulate our return address ( x30 a.k.a LR ) to the rebased bootloader + // x19 = current PC + offset to _start + // x20 = absolute address ( _start ) that specify by linker script + adr x19, _start + ldr x20, =_start + sub x19, x19, x20 + sub lr , lr, x19 + + // x21 = absolute address ( __bootloader_start ) that specify by linker script + // x22 = current PC + offset to __bootloader_start ( In linker script ) + ldr x21, =__bootloader_start + adr x22, __bootloader_start + ldr x23, =__bootloader_size + // start rebasing bootloader +copy_bootloader: + cbz x23, end_rebase_bootloader + ldr x24, [x22], #8 + str x24, [x21], #8 + sub x23, x23, #8 + b copy_bootloader + +// Since ldr and str memory operation should obey 8 bytes alignment rule, the code here would failed on real device +// cbz x23, end_rebase_bootloader +// ldr x24, [x22], #1 +// str x24, [x21], #1 +// sub x23, x23, #1 +// b copy_bootloader + + + // return to rebased bootloader +end_rebase_bootloader: + ret + +.section ".data" +_dtb: .dword 0 diff --git a/lab3/boot/linker.ld b/lab3/boot/linker.ld new file mode 100644 index 000000000..740945ab2 --- /dev/null +++ b/lab3/boot/linker.ld @@ -0,0 +1,43 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x60000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __bootloader_start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + __bootloader_end = .; + __bootloader_size = (__bootloader_end - __bootloader_start); +} diff --git a/lab3/boot/uart_boot.c b/lab3/boot/uart_boot.c new file mode 100644 index 000000000..faec51411 --- /dev/null +++ b/lab3/boot/uart_boot.c @@ -0,0 +1,47 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "lib/print.h" + +void recv_boot_header(){ + while('A' != mini_uart_read()); +} + +size_t recv_kernel_base(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +size_t recv_kernel_size(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +void recv_kernel(uint64_t base, size_t size){ + uint8_t *pb; + size_t i; + for(pb = (uint8_t*)base , i = 0 ; i < size ; i++){ + pb[i] = mini_uart_read(); + } +} +uint64_t uart_recv_kernel(uint64_t dtb){ + size_t size; + uint64_t base; + mini_uart_init(); + + recv_boot_header(); +// printf("Receive A...\r\n"); + + base = recv_kernel_base(); +// printf("Receive kernel base 0x%x...\r\n", base); + + size = recv_kernel_size(); +// printf("Receive kernel size 0x%x...\r\n", size); + + recv_kernel(base, size); +// printf("Jump to kernel iamge...\r\n"); + + delay_cycles(10000); + ((void (*)(uint64_t))base)(dtb); +} diff --git a/lab3/build/asm.o b/lab3/build/asm.o new file mode 100644 index 000000000..e64c4949b Binary files /dev/null and b/lab3/build/asm.o differ diff --git a/lab3/build/bitops.o b/lab3/build/bitops.o new file mode 100644 index 000000000..eeb1f4674 Binary files /dev/null and b/lab3/build/bitops.o differ diff --git a/lab3/build/boot.o b/lab3/build/boot.o new file mode 100644 index 000000000..d9a96fce6 Binary files /dev/null and b/lab3/build/boot.o differ diff --git a/lab3/build/bootloader.elf b/lab3/build/bootloader.elf new file mode 100755 index 000000000..a514a962b Binary files /dev/null and b/lab3/build/bootloader.elf differ diff --git a/lab3/build/bootloader.img b/lab3/build/bootloader.img new file mode 100755 index 000000000..87870709a Binary files /dev/null and b/lab3/build/bootloader.img differ diff --git a/lab3/build/cpio.o b/lab3/build/cpio.o new file mode 100644 index 000000000..d84f1e0af Binary files /dev/null and b/lab3/build/cpio.o differ diff --git a/lab3/build/debug.o b/lab3/build/debug.o new file mode 100644 index 000000000..adcd18597 Binary files /dev/null and b/lab3/build/debug.o differ diff --git a/lab3/build/entry.o b/lab3/build/entry.o new file mode 100644 index 000000000..70396fb6f Binary files /dev/null and b/lab3/build/entry.o differ diff --git a/lab3/build/fdt_parse.o b/lab3/build/fdt_parse.o new file mode 100644 index 000000000..eccd692bd Binary files /dev/null and b/lab3/build/fdt_parse.o differ diff --git a/lab3/build/initrdfs.o b/lab3/build/initrdfs.o new file mode 100644 index 000000000..29b6e9657 Binary files /dev/null and b/lab3/build/initrdfs.o differ diff --git a/lab3/build/irq_handler.o b/lab3/build/irq_handler.o new file mode 100644 index 000000000..6a15a4689 Binary files /dev/null and b/lab3/build/irq_handler.o differ diff --git a/lab3/build/kernel8.elf b/lab3/build/kernel8.elf new file mode 100755 index 000000000..39fb07ba8 Binary files /dev/null and b/lab3/build/kernel8.elf differ diff --git a/lab3/build/kernel8.img b/lab3/build/kernel8.img new file mode 100755 index 000000000..6455eea14 Binary files /dev/null and b/lab3/build/kernel8.img differ diff --git a/lab3/build/kernel_init.o b/lab3/build/kernel_init.o new file mode 100644 index 000000000..35e8fd7c7 Binary files /dev/null and b/lab3/build/kernel_init.o differ diff --git a/lab3/build/list.o b/lab3/build/list.o new file mode 100644 index 000000000..203193c42 Binary files /dev/null and b/lab3/build/list.o differ diff --git a/lab3/build/mailbox.o b/lab3/build/mailbox.o new file mode 100644 index 000000000..288896b9f Binary files /dev/null and b/lab3/build/mailbox.o differ diff --git a/lab3/build/main.o b/lab3/build/main.o new file mode 100644 index 000000000..95659f059 Binary files /dev/null and b/lab3/build/main.o differ diff --git a/lab3/build/mini_uart.o b/lab3/build/mini_uart.o new file mode 100644 index 000000000..703891413 Binary files /dev/null and b/lab3/build/mini_uart.o differ diff --git a/lab3/build/print.o b/lab3/build/print.o new file mode 100644 index 000000000..e944f0a04 Binary files /dev/null and b/lab3/build/print.o differ diff --git a/lab3/build/reboot.o b/lab3/build/reboot.o new file mode 100644 index 000000000..b2e138124 Binary files /dev/null and b/lab3/build/reboot.o differ diff --git a/lab3/build/ring_buffer.o b/lab3/build/ring_buffer.o new file mode 100644 index 000000000..4782eca2f Binary files /dev/null and b/lab3/build/ring_buffer.o differ diff --git a/lab3/build/shell.o b/lab3/build/shell.o new file mode 100644 index 000000000..885e82ca7 Binary files /dev/null and b/lab3/build/shell.o differ diff --git a/lab3/build/simple_malloc.o b/lab3/build/simple_malloc.o new file mode 100644 index 000000000..9341a3bd8 Binary files /dev/null and b/lab3/build/simple_malloc.o differ diff --git a/lab3/build/start.o b/lab3/build/start.o new file mode 100644 index 000000000..9e6af6d11 Binary files /dev/null and b/lab3/build/start.o differ diff --git a/lab3/build/string.o b/lab3/build/string.o new file mode 100644 index 000000000..59c6f1bcd Binary files /dev/null and b/lab3/build/string.o differ diff --git a/lab3/build/syscall_table.o b/lab3/build/syscall_table.o new file mode 100644 index 000000000..ebee7f0ff Binary files /dev/null and b/lab3/build/syscall_table.o differ diff --git a/lab3/build/syscall_test.o b/lab3/build/syscall_test.o new file mode 100644 index 000000000..df2c55619 Binary files /dev/null and b/lab3/build/syscall_test.o differ diff --git a/lab3/build/timer.o b/lab3/build/timer.o new file mode 100644 index 000000000..433a61ccf Binary files /dev/null and b/lab3/build/timer.o differ diff --git a/lab3/build/uart_boot.o b/lab3/build/uart_boot.o new file mode 100644 index 000000000..4b0da3041 Binary files /dev/null and b/lab3/build/uart_boot.o differ diff --git a/lab3/debug.sh b/lab3/debug.sh new file mode 100755 index 000000000..81d573d80 --- /dev/null +++ b/lab3/debug.sh @@ -0,0 +1,3 @@ +#!/bin/sh +make CFLAGS=-DDEBUG >/dev/null +make qemu-run diff --git a/lab3/debug/Makefile b/lab3/debug/Makefile new file mode 100644 index 000000000..22ac23500 --- /dev/null +++ b/lab3/debug/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + debug.o + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab3/debug/debug.c b/lab3/debug/debug.c new file mode 100644 index 000000000..392816bfd --- /dev/null +++ b/lab3/debug/debug.c @@ -0,0 +1,50 @@ +#include "debug/debug.h" + +extern int __bss_start, __bss_end; +extern int __text_start, __text_end; +extern int __rodata_start, __rodata_end; +extern int __data_start, __data_end; +extern int __heap_start; + +#ifdef DEBUG +int debug = 1; +#else +int debug = 0; +#endif + +void log_kernel_start(){ + uint64_t currentEL; + if(debug == 0) return; + printf("text_start=%p, text_end=%p, text_size=%u\r\n", \ + &__text_start, \ + &__text_end, \ + (uint64_t)&__text_end - (uint64_t)&__text_start + ); + + + printf("rodata_start=%p, rodata_end=%p, rodata_size=%u\r\n", \ + &__rodata_start, \ + &__rodata_end, \ + (uint64_t)&__rodata_end - (uint64_t)&__rodata_start + ); + + printf("data_start=%p, data_end=%p, data_size=%u\r\n", \ + &__data_start, \ + &__data_end, \ + (uint64_t)&__data_end - (uint64_t)&__data_start + ); + + printf("bss_start=%p, bss_end=%p, bss_size=%u\r\n", \ + &__bss_start, \ + &__bss_end, \ + (uint64_t)&__bss_end - (uint64_t)&__bss_start + ); + printf("heap_start=%p\n", &__heap_start); + + printf("current exception level: %u\r\n", get_currentEL()); + printf("SP_EL0: 0x%x\r\n", get_SP_ELx(0)); + printf("DAIF: 0x%x\r\n", get_DAIF()); + printf("SPSel: 0x%x\r\n", get_SPSel()); + printf("stack pointer: %p\r\n", ¤tEL); + +} diff --git a/lab3/fs/Makefile b/lab3/fs/Makefile new file mode 100644 index 000000000..15fbb2fa3 --- /dev/null +++ b/lab3/fs/Makefile @@ -0,0 +1,24 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + initrdfs.o +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab3/fs/initrdfs.c b/lab3/fs/initrdfs.c new file mode 100644 index 000000000..964027964 --- /dev/null +++ b/lab3/fs/initrdfs.c @@ -0,0 +1,81 @@ +#include "fs/initrdfs.h" + +static struct fentry * root; + +void initrdfs_init(void* addr){ + INFO("Initrd filesystem start address: %p", addr); + LOG("Enter initrdfs_int"); + LOG("initrd start at %p\n", addr); + LOG("initrd first 4 bytes: %x\n", *(uint32_t*)addr); + root = (struct fentry*)simple_malloc(sizeof(struct fentry)); + struct cpio_iter iter; + char *fname = (char*)simple_malloc(2); + strcpy(fname, "/"); + + memset(root, 0, sizeof(struct fentry)); + root->filename = fname; + root->namesize = 1; + root->mode = root->mode & FILE_TYPE_DIR; + + INIT_LIST_HEAD(&root->list); + + // Start parsing initrd in New ASCII Format at addr + LOG("Start parsing new ascii format's cpio"); + cpio_iter_init(&iter, addr); + do{ + struct fentry *f = (struct fentry*)simple_malloc(sizeof(struct fentry)); + cpio_iter_parse(&iter, f); + LOG("FILE: %s", f->filename); + if(cpio_is_tailer(f)) break; + list_add(&f->list, &root->list); + }while(1); + LOG("Leave initrdfs_int"); +} +void* fdt_initrdfs_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(prop != NULL){ + if(strcmp(prop->name, "linux,initrd-start") == 0){ + uint64_t initrd_start = bswap32(*(uint32_t*)prop->value); + LOG("linux,initrd-start: %x", (uint32_t)initrd_start); + initrdfs_init((void*)initrd_start); + } + } +} + +void initrdfs_ls(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + printf("%s\r\n", f->filename); + } +} +void initrdfs_cat(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + printf("Filename : %s\r\n", f->filename); + printf("File size: %u\r\n", f->filesize); + aio_write_bytes(f->data, f->filesize); + printf("\r\n"); + } + } +} +void initrdfs_loadfile(char* name, uint8_t* addr){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + if(strcmp(name, f->filename) == 0){ + LOG("Load file %s to %p", name, addr); + memcpy(addr, f->data, f->filesize); + break; + } + } + } +} diff --git a/lab3/include/asm.h b/lab3/include/asm.h new file mode 100644 index 000000000..37dbc4cc7 --- /dev/null +++ b/lab3/include/asm.h @@ -0,0 +1,20 @@ +#ifndef _ASM_H_ +#define _ASM_H_ +extern uint32_t get_currentEL(); +extern uint64_t get_SP_ELx(uint32_t); +extern uint64_t get_DAIF(); +extern void set_DAIF(uint64_t); +extern uint64_t get_SPSel(); +extern uint64_t get_ESR_EL1(); +extern uint64_t get_SPSR_EL1(); +extern uint64_t get_ELR_EL1(); +extern uint64_t get_SP(); +extern uint64_t get_CNTP_CTL_EL0(); +extern void set_CNTP_CTL_EL0(uint64_t); +extern uint64_t get_CNTFRQ_EL0(); +extern void set_CNTP_TVAL_EL0(uint64_t); +extern uint64_t get_CNTPCT_EL0(); +extern void local_irq_enable(); +extern void local_irq_disable(); +#endif + diff --git a/lab3/include/debug/debug.h b/lab3/include/debug/debug.h new file mode 100644 index 000000000..098653069 --- /dev/null +++ b/lab3/include/debug/debug.h @@ -0,0 +1,18 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "lib/print.h" +#include "types.h" +#include "asm.h" + +#define DEBUG_KERNEL_START() log_kernel_start() +#define LOG(fmt, ...) \ + if(debug) \ + printf("[%s/%s:%d] " fmt "\r\n" , __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) + + + +extern void log_kernel_start(void); + +extern int debug; +#endif diff --git a/lab3/include/fs/initrdfs.h b/lab3/include/fs/initrdfs.h new file mode 100644 index 000000000..b24e9fc1f --- /dev/null +++ b/lab3/include/fs/initrdfs.h @@ -0,0 +1,17 @@ +#ifndef _INITRDFS_H_ +#define _INITRDFS_H_ +#include "types.h" +#include "lib/cpio.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "lib/list.h" +#include "lib/string.h" +#include "debug/debug.h" +#include "peripherals/mini_uart.h" + +extern void initrdfs_init(void*); +extern void initrdfs_ls(); +extern void initrdfs_cat(); +extern void* fdt_initrdfs_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void initrdfs_loadfile(char* , uint8_t*); +#endif diff --git a/lab3/include/init/kernel_init.h b/lab3/include/init/kernel_init.h new file mode 100644 index 000000000..4e15dd829 --- /dev/null +++ b/lab3/include/init/kernel_init.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_INIT_H +#define _KERNEL_INIT_H + +extern void kernel_init(void *); + +#endif diff --git a/lab3/include/kernel/irq_handler.h b/lab3/include/kernel/irq_handler.h new file mode 100644 index 000000000..9a2f57535 --- /dev/null +++ b/lab3/include/kernel/irq_handler.h @@ -0,0 +1,23 @@ +#ifndef _IRQ_HANDLER_H_ +#define _IRQ_HANDLER_H_ + +#include "types.h" +#include "peripherals/iomapping.h" +#include "peripherals/mini_uart.h" +#include "lib/print.h" +#include "lib/bitops.h" +#include "kernel/timer.h" +#include "debug/debug.h" +#include "asm.h" + +#define MAX_SOFTIRQ_TRY 5 + +enum {CORE0_TIMER = 0, MINI_UART_RX, MINI_UART_TX, END_OF_LIST}; +typedef void (*irq_funcptr)(void); + +struct softirq_status{ + uint16_t pending; // support 16 interrupt + uint8_t in_softirq; +}; +extern uint64_t irq_count[END_OF_LIST]; +#endif diff --git a/lab3/include/kernel/reboot.h b/lab3/include/kernel/reboot.h new file mode 100644 index 000000000..cc8e8730b --- /dev/null +++ b/lab3/include/kernel/reboot.h @@ -0,0 +1,16 @@ +#ifndef _REBOOT_H_ +#define _REBOOT_H_ + +#include "peripherals/iomapping.h" + +#define PM_WDOG_RESET 0000000000 +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +extern void reboot(int tick); + +#endif diff --git a/lab3/include/kernel/shell.h b/lab3/include/kernel/shell.h new file mode 100644 index 000000000..47184f030 --- /dev/null +++ b/lab3/include/kernel/shell.h @@ -0,0 +1,16 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ +#include "types.h" +#include "lib/print.h" +#include "lib/string.h" +#include "lib/simple_malloc.h" +#include "peripherals/mailbox.h" +#include "kernel/reboot.h" +#include "fs/initrdfs.h" +#include "kernel/timer.h" +#include "kernel/irq_handler.h" + +void simple_shell(void); + +#define DELIM " \t\n\r" +#endif diff --git a/lab3/include/kernel/syscall.h b/lab3/include/kernel/syscall.h new file mode 100644 index 000000000..97f303301 --- /dev/null +++ b/lab3/include/kernel/syscall.h @@ -0,0 +1,5 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ +#include "types.h" +extern uint64_t sys_hello(uint64_t); +#endif diff --git a/lab3/include/kernel/syscall_table.h b/lab3/include/kernel/syscall_table.h new file mode 100644 index 000000000..50ab0047e --- /dev/null +++ b/lab3/include/kernel/syscall_table.h @@ -0,0 +1,6 @@ +#ifndef _SYSCALL_TABLE_H_ +#define _SYSCALL_TABLE_H_ + +#include "kernel/syscall.h" +extern void *syscall_table[]; +#endif diff --git a/lab3/include/kernel/timer.h b/lab3/include/kernel/timer.h new file mode 100644 index 000000000..5a1937f46 --- /dev/null +++ b/lab3/include/kernel/timer.h @@ -0,0 +1,31 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ +#include "types.h" +#include "lib/list.h" +#include "lib/simple_malloc.h" +#include "peripherals/iomapping.h" +#include "debug/debug.h" +#include "asm.h" + + +#define HZ 100 + +typedef void (*timer_callback)(void*); + +typedef struct{ + uint64_t ticks; + timer_callback callback; + void *data; + struct list_head list; +}timer_t; + +extern void core_timer_irq_handler(); +extern void init_core_timer(); +extern uint64_t get_jiffies(); +extern void enable_core_timer_irq(); +extern void disable_core_timer_irq(); +extern void init_timer_list(); +extern void add_timer(timer_callback, uint8_t*, uint64_t); +extern void timer_softirq_callback(); + +#endif diff --git a/lab3/include/lib/bitops.h b/lab3/include/lib/bitops.h new file mode 100644 index 000000000..8f5770dc7 --- /dev/null +++ b/lab3/include/lib/bitops.h @@ -0,0 +1,7 @@ +#ifndef _BITOPS_H_ +#define _BITOPS_H_ + +#include "types.h" +extern uint16_t ffs16(uint16_t); + +#endif diff --git a/lab3/include/lib/cpio.h b/lab3/include/lib/cpio.h new file mode 100644 index 000000000..9e9eaf129 --- /dev/null +++ b/lab3/include/lib/cpio.h @@ -0,0 +1,66 @@ +#ifndef _CPIO_H_ +#define _CPIO_H_ + +#include "types.h" +#include "lib/list.h" +#include "lib/fdt_parse.h" +#include "lib/string.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "debug/debug.h" + +#define FILE_TYPE_MASK 0170000 +#define FILE_TYPE_SOCKET 0140000 +#define FILE_TYPE_SYMLINK 0120000 +#define FILE_TYPE_REGULAR 0100000 +#define FILE_TYPE_BLKDEV 0060000 +#define FILE_TYPE_DIR 0040000 +#define FILE_TYPE_CHRDEV 0020000 +#define FILE_TYPE_NAMED_PIPE 0010000 +#define FILE_SUID 0004000 +#define FILE_SGID 0002000 +#define FILE_STICKY 0001000 +#define FILE_PERMISSION_MASK 0000777 + +struct cpio_iter{ + uint8_t *cur; +}; +struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} __attribute((packed)); + +struct fentry { + uint32_t ino; + uint32_t mode; + uint32_t uid; + uint32_t gid; + uint32_t nlink; + uint32_t mtime; + uint32_t filesize; + uint32_t devmajor; + uint32_t devminor; + uint32_t rdevmajor; + uint32_t rdevminor; + uint32_t namesize; + uint32_t check; + char *filename; + uint8_t *data; + struct list_head list; +}; +void cpio_iter_parse(struct cpio_iter*, struct fentry*); +extern void cpio_iter_init(struct cpio_iter*, void*); +extern int cpio_is_tailer(struct fentry*); +#endif diff --git a/lab3/include/lib/fdt_parse.h b/lab3/include/lib/fdt_parse.h new file mode 100644 index 000000000..584ba7d1a --- /dev/null +++ b/lab3/include/lib/fdt_parse.h @@ -0,0 +1,44 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "lib/string.h" + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +#endif diff --git a/lab3/include/lib/list.h b/lab3/include/lib/list.h new file mode 100644 index 000000000..20f384940 --- /dev/null +++ b/lab3/include/lib/list.h @@ -0,0 +1,21 @@ +#ifndef _LIST_H_ +#define _LIST_H_ + +#include "types.h" +struct list_head{ + struct list_head* next, *prev; +}__attribute__((packed)); + +#define LIST_HEAD(head) struct list_head head = { &(head), &(head) } +#define list_entry(node, type, member) container_of(node, type, member) +#define list_first_entry(head, type, member) list_entry((head)->next, type, member) +#define list_last_entry(head, type, member) list_entry((head)->prev, type, member) +#define list_for_each(node, head) \ + for(node = (head)->next ; node != (head) ; node = node->next) + +extern void INIT_LIST_HEAD(struct list_head*); +extern void list_add(struct list_head* node, struct list_head*); +extern void list_add_tail(struct list_head*, struct list_head*); +extern void list_del(struct list_head*); +extern int list_empty(struct list_head*); +#endif diff --git a/lab3/include/lib/print.h b/lab3/include/lib/print.h new file mode 100644 index 000000000..d0cab3e83 --- /dev/null +++ b/lab3/include/lib/print.h @@ -0,0 +1,17 @@ +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#include "types.h" +#include "kernel/timer.h" +#include "lib/string.h" +#include "peripherals/mini_uart.h" +#include + +int32_t printf(char *, ...); +int32_t putchar(uint8_t); +int32_t getchar(); + +#define INFO(fmt, ...) \ + printf("%l: [%s] " fmt "\r\n" , (int64_t)get_jiffies(), __FUNCTION__, ##__VA_ARGS__) + +#endif diff --git a/lab3/include/lib/ring_buffer.h b/lab3/include/lib/ring_buffer.h new file mode 100644 index 000000000..22e0303b6 --- /dev/null +++ b/lab3/include/lib/ring_buffer.h @@ -0,0 +1,20 @@ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ +#include "types.h" +#include "lib/simple_malloc.h" + +typedef struct{ + size_t size; + uint64_t head; + uint64_t tail; + uint8_t* buf; + size_t count; +}ring_buffer; + +extern ring_buffer* create_ring_buf(size_t); +extern size_t ring_buf_write(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read(ring_buffer*, uint8_t*, size_t); +extern uint8_t ring_buf_is_full(ring_buffer*); +extern uint8_t ring_buf_is_empty(ring_buffer*); +extern size_t ring_buf_get_len(ring_buffer*); +#endif diff --git a/lab3/include/lib/simple_malloc.h b/lab3/include/lib/simple_malloc.h new file mode 100644 index 000000000..8f8c0f4dc --- /dev/null +++ b/lab3/include/lib/simple_malloc.h @@ -0,0 +1,15 @@ +#ifndef _SIMPLE_MALLOC_H_ +#define _SIMPLE_MALLOC_H_ + +#include "types.h" +#include "debug/debug.h" + +#define req2size(req) ALIGN_UP(req, 16) + +struct malloc_state{ + uint8_t* last_remainder; +}; + +extern void* simple_malloc(size_t); +extern void* simple_malloc_get_remainder(); +#endif diff --git a/lab3/include/lib/string.h b/lab3/include/lib/string.h new file mode 100644 index 000000000..4a6a30cd7 --- /dev/null +++ b/lab3/include/lib/string.h @@ -0,0 +1,19 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#include "types.h" + +extern char * itoa(int32_t, char*, uint32_t); +extern char * utoa(uint32_t, char*, uint32_t); +extern char * ltoa(int64_t, char*, uint32_t); +extern char * ultoa(uint64_t, char*, uint32_t); +extern int32_t strcmp(char*, char*); +extern char *strcpy(char *, const char *); +extern size_t strlen(const char*); +extern void* memcpy(void*, const void*, size_t); +extern void* memset(void*, int, size_t); +extern int32_t memcmp(void*, const void*, size_t); +extern uint8_t hex2dec(char); +extern char* strtok(char*,const char*); +extern uint64_t atoul(const char*); +#endif diff --git a/lab3/include/peripherals/iomapping.h b/lab3/include/peripherals/iomapping.h new file mode 100644 index 000000000..e06ff517b --- /dev/null +++ b/lab3/include/peripherals/iomapping.h @@ -0,0 +1,94 @@ +#ifndef _IOMAPPING_H_ +#define _IOMAPPING_H_ + + +/* Physical addresses range from 0x3F000000 to 0x3FFFFFFF for peripherals */ +#define IO_BASE 0x3F000000 + +/* Register's offset of GPIO */ +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL1 (IO_BASE + 0x200004) +#define GPFSEL2 (IO_BASE + 0x200008) +#define GPFSEL3 (IO_BASE + 0x20000C) +#define GPFSEL4 (IO_BASE + 0x200010) +#define GPFSEL5 (IO_BASE + 0x200014) +#define GPSET0 (IO_BASE + 0x20001C) +#define GPSET1 (IO_BASE + 0x200020) +#define GPCLR0 (IO_BASE + 0x200028) +#define GPCLR1 (IO_BASE + 0x20002C) +#define GPLEV0 (IO_BASE + 0x200034) +#define GPLEV1 (IO_BASE + 0x200038) +#define GPEDS0 (IO_BASE + 0x200040) +#define GPEDS1 (IO_BASE + 0x200044) +#define GPREN0 (IO_BASE + 0x20004C) +#define GPREN1 (IO_BASE + 0x200050) +#define GPFEN0 (IO_BASE + 0x200058) +#define GPFEN1 (IO_BASE + 0x20005C) +#define GPHEN0 (IO_BASE + 0x200064) +#define GPHEN1 (IO_BASE + 0x200068) +#define GPLEN0 (IO_BASE + 0x200070) +#define GPLEN1 (IO_BASE + 0x200074) +#define GPAREN0 (IO_BASE + 0x20007C) +#define GPAREN1 (IO_BASE + 0x200080) +#define GPAFEN0 (IO_BASE + 0x200088) +#define GPAFEN1 (IO_BASE + 0x20008C) +#define GPPUD (IO_BASE + 0x200094) +#define GPPUDCLK0 (IO_BASE + 0x200098) +#define GPPUDCLK1 (IO_BASE + 0x20009C) + + +/* Register's offset of UART and SPI */ +#define AUX_IRQ (IO_BASE + 0x215000) +#define AUX_ENABLES (IO_BASE + 0x215004) +#define AUX_MU_IO_REG (IO_BASE + 0x215040) +#define AUX_MU_IER_REG (IO_BASE + 0x215044) +#define AUX_MU_IIR_REG (IO_BASE + 0x215048) +#define AUX_MU_LCR_REG (IO_BASE + 0x21504C) +#define AUX_MU_MCR_REG (IO_BASE + 0x215050) +#define AUX_MU_LSR_REG (IO_BASE + 0x215054) +#define AUX_MU_MSR_REG (IO_BASE + 0x215058) +#define AUX_MU_SCRATCH (IO_BASE + 0x21505C) +#define AUX_MU_CNTL_REG (IO_BASE + 0x215060) +#define AUX_MU_STAT_REG (IO_BASE + 0x215064) +#define AUX_MU_BAUD_REG (IO_BASE + 0x215068) +#define AUX_SPI0_CNTL0_REG (IO_BASE + 0x215080) +#define AUX_SPI0_CNTL1_REG (IO_BASE + 0x215084) +#define AUX_SPI0_STAT_REG (IO_BASE + 0x215088) +#define AUX_SPI0_IO_REG (IO_BASE + 0x215090) +#define AUX_SPI0_PEEK_REG (IO_BASE + 0x215094) +#define AUX_SPI1_CNTL0_REG (IO_BASE + 0x2150C0) +#define AUX_SPI1_CNTL1_REG (IO_BASE + 0x2150C4) +#define AUX_SPI1_STAT_REG (IO_BASE + 0x2150C8) +#define AUX_SPI1_IO_REG (IO_BASE + 0x2150D0) +#define AUX_SPI1_PEEK_REG (IO_BASE + 0x2150D4) + +// mailbox register base address +#define MBOX_REG (IO_BASE + 0xB880) + +// interrupt +#define IRQ_BASIC_PENDING (IO_BASE + 0xB200) +#define IRQ_PENDING_1 (IO_BASE + 0xB204) +#define IRQ_PENDING_2 (IO_BASE + 0xB208) +#define CORE0_INTERRUPT_SOURCE (IO_BASE + 0x1000060) +#define ENABLE_IRQS_1 (IO_BASE + 0xB210) + + +// timer +#define CORE0_TIMER_IRQ_CTRL (IO_BASE + 0x1000040) + + +// watch dog +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_RSTC (IO_BASE + 0x10001c) +#define PM_WDOG (IO_BASE + 0x100024) + +#define IO_MMIO_write32(addr, val) *(uint32_t*)addr = val +#define IO_MMIO_read32(addr) *(uint32_t*)addr +#define IO_MMIO_write64(addr, val) *(uint64_t*)addr = val +#define IO_MMIO_read64(addr) *(uint64_t*)addr + + + +#endif + diff --git a/lab3/include/peripherals/mailbox.h b/lab3/include/peripherals/mailbox.h new file mode 100644 index 000000000..0d264f4de --- /dev/null +++ b/lab3/include/peripherals/mailbox.h @@ -0,0 +1,175 @@ +#ifndef _MAILBOX_H_ +#define _MAILBOX_H_ + +#include "types.h" +#include "lib/string.h" +#include "debug/debug.h" +#include "peripherals/iomapping.h" + +#define MBOX_CHANNEL_POWER 0 +#define MBOX_CHANNEL_FRAME_BUF 1 +#define MBOX_CHANNEL_VIRTUAL_UART 2 +#define MBOX_CHANNEL_VCHIQ 3 +#define MBOX_CHANNEL_LEDS 4 +#define MBOX_CHANNEL_BUTTONS 5 +#define MBOX_CHANNEL_TOUCH_SCREEN 6 +#define MBOX_CHANNEL_UNKOWN 7 +#define MBOX_CHANNEL_PROPERTY_TAGS 8 + +enum MBOX_PROPERTY_STATUS { + MBOX_STATUS_REQUEST = 0, + MBOX_STATUS_SUCCESS = 0x80000000, + MBOX_STATUS_ERROR = 0x80000001, +}; + +enum MBOX_PROPERTY_TAG{ + MBOX_PROPERTY_END = 0, + MBOX_GET_FIRMWARE_REVISION = 0x00000001, + + MBOX_SET_CURSOR_INFO = 0x00008010, + MBOX_SET_CURSOR_STATE = 0x00008011, + + MBOX_GET_BOARD_MODEL = 0x00010001, + MBOX_GET_BOARD_REVISION = 0x00010002, + MBOX_GET_BOARD_MAC_ADDRESS = 0x00010003, + MBOX_GET_BOARD_SERIAL = 0x00010004, + MBOX_GET_ARM_MEMORY = 0x00010005, + MBOX_GET_VC_MEMORY = 0x00010006, + MBOX_GET_CLOCKS = 0x00010007, + MBOX_GET_POWER_STATE = 0x00020001, + MBOX_GET_TIMING = 0x00020002, + MBOX_SET_POWER_STATE = 0x00028001, + MBOX_GET_CLOCK_STATE = 0x00030001, + MBOX_GET_CLOCK_RATE = 0x00030002, + MBOX_GET_VOLTAGE = 0x00030003, + MBOX_GET_MAX_CLOCK_RATE = 0x00030004, + MBOX_GET_MAX_VOLTAGE = 0x00030005, + MBOX_GET_TEMPERATURE = 0x00030006, + MBOX_GET_MIN_CLOCK_RATE = 0x00030007, + MBOX_GET_MIN_VOLTAGE = 0x00030008, + MBOX_GET_TURBO = 0x00030009, + MBOX_GET_MAX_TEMPERATURE = 0x0003000a, + MBOX_GET_STC = 0x0003000b, + MBOX_ALLOCATE_MEMORY = 0x0003000c, + MBOX_LOCK_MEMORY = 0x0003000d, + MBOX_UNLOCK_MEMORY = 0x0003000e, + MBOX_RELEASE_MEMORY = 0x0003000f, + MBOX_EXECUTE_CODE = 0x00030010, + MBOX_EXECUTE_QPU = 0x00030011, + MBOX_SET_ENABLE_QPU = 0x00030012, + MBOX_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, + MBOX_GET_EDID_BLOCK = 0x00030020, + MBOX_GET_CUSTOMER_OTP = 0x00030021, + MBOX_GET_DOMAIN_STATE = 0x00030030, + MBOX_SET_CLOCK_STATE = 0x00038001, + MBOX_SET_CLOCK_RATE = 0x00038002, + MBOX_SET_VOLTAGE = 0x00038003, + MBOX_SET_TURBO = 0x00038009, + MBOX_SET_CUSTOMER_OTP = 0x00038021, + MBOX_SET_DOMAIN_STATE = 0x00038030, + MBOX_GET_GPIO_STATE = 0x00030041, + MBOX_SET_GPIO_STATE = 0x00038041, + MBOX_SET_SDHOST_CLOCK = 0x00038042, + MBOX_GET_GPIO_CONFIG = 0x00030043, + MBOX_SET_GPIO_CONFIG = 0x00038043, + MBOX_GET_PERIPH_REG = 0x00030045, + MBOX_SET_PERIPH_REG = 0x00038045, + + + /* Dispmanx TAGS */ + MBOX_FRAMEBUFFER_ALLOCATE = 0x00040001, + MBOX_FRAMEBUFFER_BLANK = 0x00040002, + MBOX_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, + MBOX_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, + MBOX_FRAMEBUFFER_GET_DEPTH = 0x00040005, + MBOX_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006, + MBOX_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007, + MBOX_FRAMEBUFFER_GET_PITCH = 0x00040008, + MBOX_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, + MBOX_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, + MBOX_FRAMEBUFFER_GET_PALETTE = 0x0004000b, + MBOX_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, + MBOX_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010, + MBOX_FRAMEBUFFER_RELEASE = 0x00048001, + MBOX_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, + MBOX_FRAMEBUFFER_TEST_DEPTH = 0x00044005, + MBOX_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006, + MBOX_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, + MBOX_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, + MBOX_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, + MBOX_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, + MBOX_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, + MBOX_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, + MBOX_FRAMEBUFFER_SET_DEPTH = 0x00048005, + MBOX_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006, + MBOX_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007, + MBOX_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + MBOX_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + MBOX_FRAMEBUFFER_SET_PALETTE = 0x0004800b, + MBOX_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + MBOX_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, + MBOX_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + MBOX_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + + MBOX_VCHIQ_INIT = 0x00048010, + + MBOX_GET_COMMAND_LINE = 0x00050001, + MBOX_GET_DMA_CHANNELS = 0x00060001, +}; +/* + * Mailbox Read/Write Peek Sender Status Config + * 0 0x00 0x10 0x14 0x18 0x1c + * 1 0x20 0x30 0x34 0x38 0x3c + */ + +#define MBOX_READ_CHANNEL_MASK 15 +#define MBOX_WRITE_CHANNEL_MASK 15 +#define MBOX_WRITE_ADDR_MASK (~15) +#define MBOX_READ_ADDR_MASK (~15) +#define MBOX_STATUS_FULL_MASK 0x80000000 +#define MBOX_STATUS_EMPTY_MASK 0x40000000 +typedef struct{ + uint32_t read; + uint32_t unused[5]; + uint32_t status; + uint32_t config; + uint32_t write; +}__attribute__((packed)) MBox_register; + +/* 0 4 8 12 16 20 24 28 32 + +---------------------------------------------------------------+ +0x00 | Buffer Size | + +---------------------------------------------------------------+ +0x04 | Request/Response Code | + +---------------------------------------------------------------+ +0x08 | Tags | +... \\ \\ +0xXX | Tags | + +---------------------------------------------------------------+ +0xXX+4 | End Tag (0) | + +---------------------------------------------------------------+ +0xXX+8 | Padding | +... \\ \\ +0xXX+16| Padding | + +---------------------------------------------------------------+ +*/ +#define MBOX_TAG_REQUEST 0 +typedef struct{ + uint32_t id; + uint32_t value_size; + uint32_t code; + uint8_t values[0]; +}MBox_tag; + +typedef struct{ + uint32_t buf_size; + uint32_t code; + uint8_t buf[0]; +}MBox_buffer; + +extern void MBox_get_board_revision(uint32_t*); +extern void MBox_get_arm_memory(uint32_t*); + +#endif diff --git a/lab3/include/peripherals/mini_uart.h b/lab3/include/peripherals/mini_uart.h new file mode 100644 index 000000000..9cec1e688 --- /dev/null +++ b/lab3/include/peripherals/mini_uart.h @@ -0,0 +1,40 @@ +#ifndef _MINI_UART_H_ +#define _MINI_UART_H_ + +#include "types.h" +#include "asm.h" +#include "peripherals/iomapping.h" +#include "debug/debug.h" +#include "lib/print.h" +#include "lib/ring_buffer.h" + +#define SYSTEM_CLOCK_RATE (250000000) +#define BAUD_RATE 115200 +#define BAUD_RATE_REG (SYSTEM_CLOCK_RATE / (8 * BAUD_RATE) - 1) +#define TX 1 +#define RX 2 +extern void mini_uart_init(); +extern uint8_t mini_uart_read(void); +extern void mini_uart_write(uint8_t); +extern ssize_t write_bytes(uint8_t *, size_t); +extern void write_str(char *); +extern void write_hex(uint64_t); +extern void delay_cycles(uint64_t); +extern void disable_mini_uart_irq(uint32_t); +extern void enable_mini_uart_irq(uint32_t); +extern void mini_uart_irq_init(); +extern void mini_uart_irq_read(); +extern size_t mini_uart_get_rx_len(); +extern uint8_t mini_uart_aio_read(void); +extern void mini_uart_irq_write(); +extern size_t mini_uart_get_tx_len(); +extern void mini_uart_aio_write(uint8_t); +extern ssize_t aio_write_bytes(uint8_t *, size_t); +extern void enable_mini_uart_tx_irq(); +extern void enable_mini_uart_rx_irq(); +extern void disable_mini_uart_tx_irq(); +extern void disable_mini_uart_rx_irq(); +extern void mini_uart_tx_softirq_callback(); +extern void mini_uart_rx_softirq_callback(); + +#endif diff --git a/lab3/include/types.h b/lab3/include/types.h new file mode 100644 index 000000000..ca7799fe1 --- /dev/null +++ b/lab3/include/types.h @@ -0,0 +1,42 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) + +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#endif diff --git a/lab3/init/Makefile b/lab3/init/Makefile new file mode 100644 index 000000000..e5b218aa8 --- /dev/null +++ b/lab3/init/Makefile @@ -0,0 +1,24 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + kernel_init.o + +all: $(OBJECTS) + +%.o: %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab3/init/kernel_init.c b/lab3/init/kernel_init.c new file mode 100644 index 000000000..b066f1647 --- /dev/null +++ b/lab3/init/kernel_init.c @@ -0,0 +1,17 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "fs/initrdfs.h" +#include "kernel/timer.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +void kernel_init(void *dtb){ + init_core_timer(); + mini_uart_init(); + mini_uart_irq_init(); + INFO("kernel start initialization..."); + + // init_malloc_state should be executed before simple_malloc is using + fdt_parser(dtb, fdt_initrdfs_callback); + return; +} + diff --git a/lab3/initramfs.cpio b/lab3/initramfs.cpio new file mode 100644 index 000000000..98a9c8fae Binary files /dev/null and b/lab3/initramfs.cpio differ diff --git a/lab3/kernel/.gdb_history b/lab3/kernel/.gdb_history new file mode 100644 index 000000000..0e9b7b5ce --- /dev/null +++ b/lab3/kernel/.gdb_history @@ -0,0 +1,25 @@ +file ./../build/kernel8.elf +target remote:1234 +x/gx simple_shell +disassemble simple_shell +b* 0x0000000000081e1c +c +x/i 0x100000 +ni +x/i 0x100000 +b* 0x100008 +ni +quit +file ./../build/kernel8.elf +target remote:1234 +disassemble simple_shell +b* 0x0000000000081e1c +c +ni +x/i 0x1000000 +x/i 0x100000 +b*0x100008 +ni +ni +ni +quit diff --git a/lab3/kernel/Makefile b/lab3/kernel/Makefile new file mode 100644 index 000000000..809af1319 --- /dev/null +++ b/lab3/kernel/Makefile @@ -0,0 +1,36 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + shell.o \ + reboot.o \ + main.o \ + start.o \ + entry.o \ + syscall_test.o \ + syscall_table.o \ + timer.o \ + irq_handler.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab3/kernel/entry.S b/lab3/kernel/entry.S new file mode 100644 index 000000000..ab8b82607 --- /dev/null +++ b/lab3/kernel/entry.S @@ -0,0 +1,122 @@ + .macro ventry label + .align 7 + b \label + .endm + + + .macro save_all + sub sp, sp, 17 * 16 + stp x0, x1, [sp ,16 * 0] + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + str x30, [sp, 16 * 15] + + mrs x24, spsr_el1 + mrs x25, elr_el1 + stp x24, x25, [sp, 16 * 16] + .endm + + .macro load_all + ldp x24, x25, [sp, 16 * 16] + msr spsr_el1, x24 + msr elr_el1, x25 + + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + ldr x30, [sp, 16 * 15] + add sp, sp, 17 * 16 + .endm + + +// exception vector table + +.align 11 +.global EL1_exception_vector_table +EL1_exception_vector_table: +// Exception from the current EL while using SP_EL0 + ventry invalid_handler // Synchronous EL1t + ventry invalid_handler // IRQ EL1t + ventry invalid_handler // FIQ EL1t + ventry invalid_handler // Error EL1t + +// Exception from the current EL while using SP_ELx + ventry el1_sync_handler // Synchronous EL1h + ventry el1_irq_handler // IRQ EL1h + ventry invalid_handler // FIQ EL1h + ventry invalid_handler // Error EL1h + +// Exception from a lower EL at least one lower EL is AArch64 + ventry el0_sync_handler // Synchronous 64-bit EL0 + ventry el0_irq_handler // IRQ 64-bit EL0 + ventry invalid_handler // FIQ 64-bit EL0 + ventry invalid_handler // Error 64-bit EL0 + +// Exception from a lower EL and all lower ELs are AArch32 + ventry invalid_handler // Synchronous 32-bit EL0 + ventry invalid_handler // IRQ 32-bit EL0 + ventry invalid_handler // FIQ 32-bit EL0 + ventry invalid_handler // Error 32-bit EL0 + + + +invalid_handler: +el1_sync_handler: + save_all + nop + load_all + eret + + +el1_irq_handler: +el0_irq_handler: + save_all + bl irq_handler + load_all + eret + +el0_sync_handler: + save_all + mrs x24, esr_el1 + lsr x24, x24, #26 + cmp x24, #0x15 + + b.eq svc_handler + b nothing + +svc_handler: + ldr x24, [x24] + + blr x24 + + str x0, [sp] + load_all + eret + +nothing: + load_all + eret diff --git a/lab3/kernel/irq_handler.c b/lab3/kernel/irq_handler.c new file mode 100644 index 000000000..0dbc6855c --- /dev/null +++ b/lab3/kernel/irq_handler.c @@ -0,0 +1,110 @@ +#include "kernel/irq_handler.h" + +struct softirq_status softirq_s = { + .pending = 0, + .in_softirq = 0 +}; + +irq_funcptr softirq_vec[END_OF_LIST] = { + timer_softirq_callback, + mini_uart_rx_softirq_callback, + mini_uart_tx_softirq_callback +}; +uint64_t irq_count[END_OF_LIST] = {0, 0, 0}; + +void enter_softirq(){ + softirq_s.in_softirq = 1; +} + +void exit_softirq(){ + softirq_s.in_softirq = 0; +} + +uint8_t in_softirq(){ + return softirq_s.in_softirq; +} + +uint8_t has_softirq_pending(){ + return softirq_s.pending ? 1 : 0; +} + +uint16_t get_softirq_pending(){ + return softirq_s.pending; +} + +void set_softirq_pending(uint16_t val){ + softirq_s.pending = val; +} + + +void add_softirq_task(uint32_t softirq_nr){ + softirq_s.pending |= (1 << softirq_nr); +} + +void do_softirq(){ + uint16_t try = 0; + uint16_t pending; + uint16_t softirq_bit; + irq_funcptr softirq_handler; + + while(try < MAX_SOFTIRQ_TRY){ + pending = get_softirq_pending(); + set_softirq_pending(0); + + local_irq_enable(); + while(pending){ + softirq_bit = ffs16(pending); + softirq_handler = softirq_vec[softirq_bit]; + softirq_handler(); + pending &= ~(1 << softirq_bit); + } + local_irq_disable(); + try++; + } +} + +void do_irq(uint32_t nr, irq_funcptr do_hardirq,irq_funcptr enable_device_irq , irq_funcptr disable_device_irq){ + disable_device_irq(); + irq_count[nr]++; + do_hardirq(); + add_softirq_task(nr); + + if(!in_softirq() && has_softirq_pending()){ + enter_softirq(); + do_softirq(); + exit_softirq(); + } + + enable_device_irq(); +} + +void irq_handler(){ + uint32_t irq_pending_1 = IO_MMIO_read32(IRQ_PENDING_1); + uint32_t core0_irq_source = IO_MMIO_read32(CORE0_INTERRUPT_SOURCE); + uint32_t auxirq, uart_irq_type; + if(core0_irq_source & 2){ + //core timer interrupt + do_irq(CORE0_TIMER, core_timer_irq_handler, enable_core_timer_irq, disable_core_timer_irq); + }else if(irq_pending_1 & (1 << 29)){ + auxirq = IO_MMIO_read32(AUX_IRQ); + if(auxirq & 1){ + uart_irq_type = (IO_MMIO_read32(AUX_MU_IIR_REG) >> 1) & (0b11); + if(uart_irq_type == RX){ + // Receiver holds valid byte + do_irq(MINI_UART_RX, mini_uart_irq_read, enable_mini_uart_rx_irq, disable_mini_uart_rx_irq); + }else if(uart_irq_type == TX){ + // Transmit holding register empty + do_irq(MINI_UART_TX, mini_uart_irq_write, enable_mini_uart_tx_irq, disable_mini_uart_tx_irq); + }else{ + LOG("UART interrupt"); + } + }else{ + LOG("Unkown AUX interrupt, DAIF: %x", get_DAIF()); + } + } + else{ + LOG("Unkown interrupt, DAIF: %x", get_DAIF()); + } +} + + diff --git a/lab3/kernel/linker.ld b/lab3/kernel/linker.ld new file mode 100644 index 000000000..47c848ae8 --- /dev/null +++ b/lab3/kernel/linker.ld @@ -0,0 +1,42 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + + __EL1_stack = 0x200000; +} diff --git a/lab3/kernel/main.c b/lab3/kernel/main.c new file mode 100644 index 000000000..c38cd2970 --- /dev/null +++ b/lab3/kernel/main.c @@ -0,0 +1,13 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "init/kernel_init.h" +#include "debug/debug.h" +#include "kernel/shell.h" + +void kernel_main(void *dtb){ + kernel_init(dtb); + DEBUG_KERNEL_START(); + + simple_shell(); +} + diff --git a/lab3/kernel/reboot.c b/lab3/kernel/reboot.c new file mode 100644 index 000000000..2511cc06e --- /dev/null +++ b/lab3/kernel/reboot.c @@ -0,0 +1,14 @@ +#include "types.h" +#include "peripherals/iomapping.h" +#include "kernel/reboot.h" + +void reboot(int ticks){ + unsigned int pm_rstc,pm_wdog; + pm_rstc = IO_MMIO_read32(PM_RSTC); + + pm_wdog = PM_PASSWORD | (ticks & PM_WDOG_TIME_SET); + pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; + + IO_MMIO_write32(PM_RSTC, pm_rstc); + IO_MMIO_write32(PM_WDOG, pm_wdog); +} diff --git a/lab3/kernel/shell.c b/lab3/kernel/shell.c new file mode 100644 index 000000000..2e5ae02f9 --- /dev/null +++ b/lab3/kernel/shell.c @@ -0,0 +1,114 @@ +#include "kernel/shell.h" + +char *miku_ascii = "⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀\r\n⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁\r\n⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀\r\n⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀\r\n⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀\r\n⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀\r\n⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀\r\n⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀\r\n⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀\r\n⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀\r\n⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀"; +char buf[0x2000]; + +void print_irq_count(void){ + printf("irq_count: "); + for(uint32_t i = 0 ; i < END_OF_LIST ; i++){ + printf("%l ", irq_count[i]); + } + printf("\r\n"); +} + +void setTimeout_callback(void* data){ + uint64_t t = get_jiffies(); + printf("Elapsed time after booting: %l.%l\r\n", t / HZ, t % HZ); + print_irq_count(); + printf("Your message: %s\r\n",(char*) data); +} + + +void simple_shell(){ + unsigned int i; + char ch, *token; + printf(miku_ascii); + printf("\r\n\r\n"); + while(1){ + i = 0; + buf[0] = '\0'; + printf("# "); + // read command + while(1){ + ch = (char)getchar(); + if(ch == '\r'){ + printf("\r\n"); + buf[i] = '\0'; + break; + }else if(ch != '\n'){ + putchar(ch); + buf[i] = ch; + i++; + } + } + + token = strtok(buf, DELIM); + if(token == NULL) continue; + // match comman + if(strcmp(token, "help") == 0){ + printf("help : print this help menu\r\n" \ + "hello : print Hello World!\r\n" \ + "info : print hardware infomation\r\n" \ + "ls : list files\r\n" \ + "cat : cat files\r\n" \ + "laod : load user program\r\n" \ + "time : print time after booting\r\n" \ + "reboot : reboot the device\r\n" \ + "setTimeout : set a N seconds timer task\r\n" \ + " setTimeout \r\n" \ + "irq_count : list irq count\r\n" + ); + + }else if(strcmp(token, "hello") == 0){ + printf("Hello World!\r\n"); + }else if(strcmp(token, "info") == 0){ + uint32_t tmp[2]; + MBox_get_board_revision(tmp); + printf("Board revision: 0x%x\r\n", tmp[0]); + + MBox_get_arm_memory(tmp); + printf("Memory base: 0x%x\r\n", tmp[0]); + printf("Memory size: 0x%x\r\n", tmp[1]); + }else if(strcmp(token, "reboot") == 0){ + printf("Start rebooting...\r\n"); + reboot(100); + while(1); + }else if(strcmp(token, "ls") == 0){ + initrdfs_ls(); + }else if(strcmp(token, "cat") == 0){ + initrdfs_cat(); + }else if(strcmp(token, "load") == 0){ + initrdfs_loadfile("test.img",(uint8_t*) 0x100000); + asm volatile("mov x0, 0x0\n\t" + "msr spsr_el1, x0\n\t" + "mov x0, #0x100000\n\t" + "msr elr_el1, x0\n\t" + "eret\n\t" + ); + }else if(strcmp(token, "time") == 0){ + uint64_t j = get_jiffies(); + printf("Elapsed time after booting: %l.%l\r\n", j / HZ, j % HZ); + }else if(strcmp(token, "setTimeout") == 0){ + uint64_t j = 0, len = 0, timeout = 0; + char *data = NULL; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + len = strlen(token); + data = (char*)simple_malloc(len + 1); + strcpy(data, token); + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + timeout = atoul(token); + + j = get_jiffies(); + add_timer(setTimeout_callback, data, timeout * 1000); + printf("Elapsed time after booting: %l.%l\r\n", j / HZ, j % HZ); + print_irq_count(); + printf("Timer will trigger after %l seconds\r\n", timeout); + }else if(strcmp(token, "irq_count") == 0){ + print_irq_count(); + } + } +} diff --git a/lab3/kernel/start.S b/lab3/kernel/start.S new file mode 100644 index 000000000..168336ea5 --- /dev/null +++ b/lab3/kernel/start.S @@ -0,0 +1,54 @@ +.section ".text.boot" +.global _start +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #0xff + + // cpu id > 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + +// cpu id == 0 +master_core: + adr x1, _dtb + str x0, [x1] +// initialize .bss section + ldr x1, =__bss_start + ldr x2, =__bss_end +bss_zero: + sub x3, x2, x1 + cbz x3, end + str xzr, [x1], #8 // store zero to [x1] and add 8 to x1 + b bss_zero + +end: +// modify vbar_el1 before changing exception level to 1 + adr x0, EL1_exception_vector_table + msr vbar_el1, x0 +// from el2 to el1 + bl from_el2_to_el1 + + adr x1, _dtb + ldr x0, [x1] +// jump to kernel_main + bl kernel_main + b proc_hang +from_el2_to_el1: + ldr x0, =__EL1_stack // Set el1 stack to __EL1_stack + msr sp_el1, x0 + + mov x0, (1 << 31) // Set hcr_el2.RW so EL1 uses aarch64 + msr hcr_el2, x0 + + mov x0, 0x5 // EL1h (SPSel = 1) + msr spsr_el2, x0 + msr elr_el2, lr + eret // return to EL1 + +.section ".data" +_dtb: .dword 0 + diff --git a/lab3/kernel/syscall_table.c b/lab3/kernel/syscall_table.c new file mode 100644 index 000000000..0b8582f1b --- /dev/null +++ b/lab3/kernel/syscall_table.c @@ -0,0 +1,6 @@ +#include "kernel/syscall_table.h" +void *syscall_table[] = { + sys_hello +}; + + diff --git a/lab3/kernel/syscall_test.c b/lab3/kernel/syscall_test.c new file mode 100644 index 000000000..8690295ca --- /dev/null +++ b/lab3/kernel/syscall_test.c @@ -0,0 +1,15 @@ +#include "types.h" +#include "debug/debug.h" +#include "asm.h" +#include "lib/print.h" +uint64_t sys_hello(uint64_t x0){ + LOG("Enter sys_hello"); + printf("CurrentEL: %x\r\n", get_currentEL()); + printf("DAIF: %x\r\n", get_DAIF()); + printf("SPSR_EL1: %p\r\n", (void*)get_SPSR_EL1()); + printf("ELR_EL1: %p\r\n", (void*)get_ELR_EL1()); + printf("ESR_EL1: %p\r\n", (void*)get_ESR_EL1()); + printf("SP : %p\r\n", (void*)get_SP()); + printf("\r\n"); + return x0; +} diff --git a/lab3/kernel/timer.c b/lab3/kernel/timer.c new file mode 100644 index 000000000..cc7539752 --- /dev/null +++ b/lab3/kernel/timer.c @@ -0,0 +1,82 @@ +#include "kernel/timer.h" + +static uint64_t jiffies = 0; +static struct list_head timer_list; + +/* + * We use core timer to update jiffies + */ +void enable_core_timer_irq(){ + IO_MMIO_write32(CORE0_TIMER_IRQ_CTRL, 2); +} +void disable_core_timer_irq(){ + IO_MMIO_write32(CORE0_TIMER_IRQ_CTRL, 0); +} + +void timer_softirq_callback(){ + struct list_head *head = &timer_list; + struct list_head *node; + timer_t* t; + + list_for_each(node, head){ + t = list_entry(node, timer_t, list); + t->ticks--; + if(t->ticks <= 0){ + list_del(node); + t->callback(t->data); + } + } +} + +void init_timer_list(void){ + INIT_LIST_HEAD(&timer_list); +} + +/** + * Timer with 10 microsecond resolution + * + * @param duration in microsecond + */ +void add_timer(timer_callback callback, uint8_t* data, uint64_t duration){ + if(duration == 0){ + callback(data); + return; + } + + timer_t* t = (timer_t*)simple_malloc(sizeof(timer_t)); + + t->ticks = duration / (1000 / HZ); + t->callback = callback; + t->data = data; + + disable_core_timer_irq(); + //critical section + list_add(&t->list, &timer_list); + enable_core_timer_irq(); +} + +void init_core_timer(){ + uint64_t freq; + + init_timer_list(); + set_CNTP_CTL_EL0(1); + freq = get_CNTFRQ_EL0(); + set_CNTP_TVAL_EL0(freq / HZ); + enable_core_timer_irq(); +} +void core_timer_irq_handler(){ + uint64_t freq; + + freq = get_CNTFRQ_EL0(); + set_CNTP_TVAL_EL0(freq / HZ); + + jiffies += 1; +} + +uint64_t inline get_jiffies(){ + return jiffies; +} + + + + diff --git a/lab3/lib/Makefile b/lab3/lib/Makefile new file mode 100644 index 000000000..328a22f1a --- /dev/null +++ b/lab3/lib/Makefile @@ -0,0 +1,36 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + print.o \ + string.o \ + list.o \ + cpio.o \ + simple_malloc.o \ + fdt_parse.o \ + asm.o \ + ring_buffer.o \ + bitops.o + + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab3/lib/asm.c b/lab3/lib/asm.c new file mode 100644 index 000000000..08c2a919a --- /dev/null +++ b/lab3/lib/asm.c @@ -0,0 +1,142 @@ +#include "types.h" +void local_irq_enable(){ + asm volatile("msr DAIFClr, 0xf"); +} + +void local_irq_disable(){ + asm volatile("msr DAIFSet, 0xf"); +} + +uint32_t get_currentEL(){ + uint64_t curEL = 0; + asm volatile("mrs %0, CurrentEL" + : "=&r" (curEL) + : + ); + return curEL >> 2; +} +uint64_t get_SP_ELx(uint32_t x){ + uint64_t sp = 0; + + switch(x){ + case 0: + asm volatile("mrs %0, SP_EL0" + : "=&r" (sp) + : + ); + break; + case 1: + asm volatile("mrs %0, SP_EL1" + : "=&r" (sp) + : + ); + break; + case 2: + asm volatile("mrs %0, SP_EL2" + : "=&r" (sp) + : + ); + break; + default: + break; + } + + + return sp; +} +uint64_t get_DAIF(){ + uint64_t daif = 0; + asm volatile("mrs %0, DAIF" + : "=&r" (daif) + : + ); + return daif >> 6; +} +void set_DAIF(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr daif, x0" + : + :[n] "r" (n) + ); +} + +uint64_t get_SPSel(){ + uint64_t spsel = 0; + asm volatile("mrs %0, spsel" + : "=&r" (spsel) + : + ); + return spsel; +} +uint64_t get_ESR_EL1(){ + uint64_t esr_el1 = 0; + asm volatile("mrs %0, esr_el1" + : "=&r" (esr_el1) + : + ); + return esr_el1; +} +uint64_t get_SPSR_EL1(){ + uint64_t spsr_el1 = 0; + asm volatile("mrs %0, spsr_el1" + : "=&r" (spsr_el1) + : + ); + return spsr_el1; +} +uint64_t get_ELR_EL1(){ + uint64_t elr_el1 = 0; + asm volatile("mrs %0, elr_el1" + : "=&r" (elr_el1) + : + ); + return elr_el1; +} +uint64_t get_SP(){ + uint64_t sp = 0; + asm volatile("mov %0, sp" + : "=&r" (sp) + : + ); + return sp; +} +uint64_t get_CNTP_CTL_EL0(){ + uint64_t cntp_ctl_el0 = 0; + asm volatile("mrs %0, cntp_ctl_el0" + : "=&r" (cntp_ctl_el0) + : + ); + return cntp_ctl_el0; +} +void set_CNTP_CTL_EL0(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr cntp_ctl_el0, x0" + : + :[n] "r" (n) + ); +} +uint64_t get_CNTFRQ_EL0(){ + uint64_t cntfrq_el0 = 0; + asm volatile("mrs %0, cntfrq_el0" + : "=&r" (cntfrq_el0) + : + ); + return cntfrq_el0; +} + +void set_CNTP_TVAL_EL0(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr cntp_tval_el0, x0" + : + :[n] "r" (n) + ); +} +uint64_t get_CNTPCT_EL0(){ + uint64_t cntpct_el0 = 0; + asm volatile("mrs %0, cntpct_el0" + : "=&r" (cntpct_el0) + : + ); + return cntpct_el0; +} + diff --git a/lab3/lib/bitops.c b/lab3/lib/bitops.c new file mode 100644 index 000000000..e4230d762 --- /dev/null +++ b/lab3/lib/bitops.c @@ -0,0 +1,25 @@ +#include "lib/bitops.h" + +uint16_t ffs16(uint16_t val){ +// val should not be zero! +// The behavior is undefined when val is zer! + uint16_t num = 0; + if((val & 0xff) == 0){ + num += 8; + val >>= 8; + } + if((val & 0xf) == 0){ + num += 4; + val >>= 4; + } + if((val & 0x3) == 0){ + num += 2; + val >>= 2; + } + if((val & 0x1) == 0) + num += 1; + + return num; +} + + diff --git a/lab3/lib/cpio.c b/lab3/lib/cpio.c new file mode 100644 index 000000000..4474ac83b --- /dev/null +++ b/lab3/lib/cpio.c @@ -0,0 +1,61 @@ +#include "lib/cpio.h" + +uint32_t cpio_hex2dec(const char *s){ + uint32_t ret = 0; + for(uint32_t i = 0 ; i < 8 ; i++){ + ret = ret << 4; + ret = ret + hex2dec(s[i]); + } + return ret; +} + +void cpio_iter_parse(struct cpio_iter* iter, struct fentry* f){ + LOG("Enter cpio_iter_parse"); + size_t count = 0; + struct cpio_newc_header* header = (struct cpio_newc_header* )iter->cur; + + if(!memcpy(header->c_magic, "070701", 6)){ + LOG("CPIO PARSE ERROR!!!!"); + return; + } + + f->ino = cpio_hex2dec(header->c_ino); + f->mode = cpio_hex2dec(header->c_mode); + f->uid = cpio_hex2dec(header->c_uid); + LOG("f->uid: %u", f->uid); + f->gid = cpio_hex2dec(header->c_gid); + f->nlink = cpio_hex2dec(header->c_nlink); + f->mtime = cpio_hex2dec(header->c_mtime); + f->filesize = cpio_hex2dec(header->c_filesize); + LOG("f->filesize: %u", f->filesize); + f->devmajor = cpio_hex2dec(header->c_devmajor); + f->devminor = cpio_hex2dec(header->c_devminor); + f->rdevmajor = cpio_hex2dec(header->c_rdevmajor); + f->rdevminor = cpio_hex2dec(header->c_rdevminor); + f->namesize = cpio_hex2dec(header->c_namesize); + LOG("f->namesize: %u", f->namesize); + f->check = cpio_hex2dec(header->c_check); + count = count + sizeof(struct cpio_newc_header); + + f->filename = (char*)simple_malloc(f->namesize); + memcpy(f->filename, (uint8_t* )header + count, f->namesize); + LOG("get f->filename"); + count = ALIGN_UP(count + f->namesize, 4); + if(f->filesize > 0){ + f->data = (uint8_t*)simple_malloc(f->filesize); + memcpy(f->data, (uint8_t* )header + count, f->filesize); + } + LOG("get f->data"); + count = ALIGN_UP(count + f->filesize, 4); + iter->cur = iter->cur + count; + LOG("count: %u, iter->cur: %p", count, iter->cur); + LOG("Leave cpio_iter_parse"); +} + +void cpio_iter_init(struct cpio_iter* iter, void* addr){ + iter->cur = addr; +} +int cpio_is_tailer(struct fentry* f){ + return (strcmp(f->filename, "TRAILER!!!") == 0); +} + diff --git a/lab3/lib/fdt_parse.c b/lab3/lib/fdt_parse.c new file mode 100644 index 000000000..81bf87993 --- /dev/null +++ b/lab3/lib/fdt_parse.c @@ -0,0 +1,109 @@ +#include "lib/fdt_parse.h" + +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } + +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = (fdt_header*)simple_malloc(sizeof(fdt_header)); + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) / 4; + //printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + len += 2; + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + //printf("Parsing error!!\n"); + } + } +} + +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab3/lib/list.c b/lab3/lib/list.c new file mode 100644 index 000000000..8cd772b4f --- /dev/null +++ b/lab3/lib/list.c @@ -0,0 +1,37 @@ +#include "lib/list.h" + +void INIT_LIST_HEAD(struct list_head* head){ + head->next = head; + head->prev = head; +} + +void list_add(struct list_head* node, struct list_head* head){ + struct list_head *next = head->next; + + next->prev = node; + head->next = node; + + node->next = next; + node->prev = head; +} + +void list_add_tail(struct list_head* node, struct list_head* head){ + struct list_head* tail = head->prev; + + tail->next = node; + head->prev = node; + + node->next = head; + node->prev = tail; +} + +void list_del(struct list_head* node){ + struct list_head* next = node->next; + struct list_head* prev = node->prev; + + next->prev = prev; + prev->next = next; +} +int list_empty(struct list_head* head){ + return (head->next == head); +} diff --git a/lab3/lib/print.c b/lab3/lib/print.c new file mode 100644 index 000000000..19292e549 --- /dev/null +++ b/lab3/lib/print.c @@ -0,0 +1,111 @@ +#include "lib/print.h" + +int32_t aio_print(char* fmt, ...){ + +} +int32_t printf(char *fmt, ...){ + uint32_t uval; + int32_t val; + int64_t lval; + char str[64], ch; + char* p, *s; + void* addr; + volatile int32_t count = 0; + va_list ap; + + va_start(ap, fmt); + + while(*fmt){ + char c = *fmt++; + if(c == '%'){ + c = *fmt++; + switch(c){ + case 'u': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 10); + p = str; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + break; + case 'd': + val = va_arg(ap, int); + itoa(val, str, 10); + p = str; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + break; + case 'l': + lval = va_arg(ap, int64_t); + ltoa(lval, str, 10); + p = str; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + break; + case 'c': + ch = va_arg(ap, int); + mini_uart_aio_write(ch); + count++; + break; + case 'p': + addr = va_arg(ap, void*); + utoa((uint64_t)addr, str, 16); + + mini_uart_aio_write('0'); + mini_uart_aio_write('x'); + count += 2; + + p = str; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + break; + + break; + case 'x': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 16); + p = str; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + + break; + case 's': + s = va_arg(ap, char*); + p = s; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + break; + case '%': + mini_uart_aio_write('%'); + count++; + default: + mini_uart_aio_write('%'); + mini_uart_aio_write(c); + count += 2; + } + }else{ + mini_uart_aio_write(c); + count++; + } + } + va_end(ap); + return count; +} +int32_t putchar(uint8_t ch){ + mini_uart_aio_write(ch); + return ch; +} +int32_t getchar(){ + return mini_uart_aio_read(); +} diff --git a/lab3/lib/ring_buffer.c b/lab3/lib/ring_buffer.c new file mode 100644 index 000000000..65efeb496 --- /dev/null +++ b/lab3/lib/ring_buffer.c @@ -0,0 +1,46 @@ +#include "lib/ring_buffer.h" +ring_buffer* create_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)simple_malloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)simple_malloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + tmp->count = 0; + return tmp; +} + +uint8_t ring_buf_is_empty(ring_buffer* rbuf){ + if(rbuf->head == rbuf->tail) return 1; + return 0; +} +uint8_t ring_buf_is_full(ring_buffer* rbuf){ + if((rbuf->tail + 1) % (rbuf->size + 1) == rbuf->head) return 1; + return 0; +} +size_t ring_buf_write(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count += count; + return count; +} +size_t ring_buf_read(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count -= count; + return count; +} +size_t ring_buf_get_len(ring_buffer* rbuf){ + return rbuf->count; +} diff --git a/lab3/lib/simple_malloc.c b/lab3/lib/simple_malloc.c new file mode 100644 index 000000000..2887488e1 --- /dev/null +++ b/lab3/lib/simple_malloc.c @@ -0,0 +1,17 @@ +#include "lib/simple_malloc.h" + +extern int __heap_start; +struct malloc_state mstate = { + .last_remainder = (uint8_t*)&__heap_start +}; + + +void* simple_malloc(size_t size){ + void* chunk = mstate.last_remainder; + size_t nb = req2size(size); + mstate.last_remainder = mstate.last_remainder + nb; + return chunk; +} +void* simple_malloc_get_remainder(){ + return mstate.last_remainder; +} diff --git a/lab3/lib/string.c b/lab3/lib/string.c new file mode 100644 index 000000000..3ab9d9ce6 --- /dev/null +++ b/lab3/lib/string.c @@ -0,0 +1,260 @@ +#include "lib/string.h" +#include "types.h" +char *int_table = "0123456789"; +char *hex_table = "0123456789abcdef"; +char * itoa(int32_t value, char* str, uint32_t base){ + char buf[32]; + uint32_t val; + volatile int i = 0, j = 0; + + switch(base){ + case 16: + val = (uint32_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} + +char * utoa(uint32_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint32_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} +char * ltoa(int64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val; + + switch(base){ + case 16: + val = (uint64_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +char * ultoa(uint64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +uint64_t atoul(const char* str){ + uint64_t val = 0; + const char* ps = str; + while(*ps){ + val *= 10; + val += (*ps - '0'); + ps++; + } + return val; +} +int32_t strcmp(char* str1, char* str2){ + do{ + if(*str1 > *str2) return 1; + else if(*str1 < *str2) return -1; + str1++;str2++; + }while(*str1 != '\0' || *str2 != '\0'); + return 0; +} +size_t strlen(const char* s){ + size_t i = 0; + while(s[i++]); + i--; + return i; +} +// Do not maninpulate data by using (uint64*) or it may sometimes trigger alignment issue +// Manipulating data by using (uint8*) is best choice in this homework +void* memcpy(void* dst, const void* src, size_t n){ + const uint8_t* ps = src; + uint8_t *pd = dst; + size_t i; + for(i = 0 ; i < n ; i++) pd[i] = ps[i]; + return dst; +} +char *strcpy(char *dest, const char *src){ + memcpy(dest, src, strlen(src) + 1); +} +void* memset(void* s, int c, size_t n){ + uint8_t* ps = s; + for(size_t i = 0 ; i < n ; i++) ps[i] = c; + return s; +} + +int32_t memcmp(void* m1, const void* m2, size_t n){ + size_t i = 0; + char *s1 = m1; + const char* s2 = m2; + while(i < n){ + if(s1[i] > s2[i]) return 1; + else if(s1[i] < s2[i]) return -1; + i++; + } + return 0; +} + +uint8_t hex2dec(char hex){ + if('0' <= hex && hex <= '9'){ + return (uint8_t)hex - (uint8_t)'0'; + }else if('a' <= hex && hex <= 'f'){ + return (uint8_t)hex - (uint8_t)'a' + 10; + }else{ + return (uint8_t)hex - (uint8_t)'A' + 10; + } +} +uint8_t _is_delim(char c,const char* delim){ + uint32_t i = 0; + while(delim[i]){ + if(c == delim[i++]) return 1; + } + return 0; +} +char* _next_token(char* s,const char* delim){ + char* pos = s; + + do{ + if(*pos == '\0'){ + return NULL; + }else if(_is_delim(*pos, delim)){ + *pos = '\0'; + return pos + 1; + } + pos++; + }while(1); +} +char* _skip_delim(char* s,const char* delim){ + char* pos = s; + while(*pos != '\0' && _is_delim(*pos, delim)) pos++; + return pos; +} +char* strtok(char* s,const char* delim){ + static char *pos = NULL; + char *tmp_pos = NULL; + if(s == NULL){ + if(pos == NULL || *pos =='\0') return NULL; + + tmp_pos = pos = _skip_delim(pos, delim); + if(*pos != '\0'){ + pos = _next_token(pos, delim); + }else{ + pos = tmp_pos = NULL; + } + }else{ + if(*s == '\0') return NULL; + + pos = s; + tmp_pos = pos = _skip_delim(pos, delim); + if(*pos != '\0'){ + pos = _next_token(pos, delim); + }else{ + pos = tmp_pos = NULL; + } + } + return tmp_pos; +} diff --git a/lab3/peripherals/Makefile b/lab3/peripherals/Makefile new file mode 100644 index 000000000..50b5d0780 --- /dev/null +++ b/lab3/peripherals/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + mini_uart.o \ + mailbox.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab3/peripherals/mailbox.c b/lab3/peripherals/mailbox.c new file mode 100644 index 000000000..d8ae82621 --- /dev/null +++ b/lab3/peripherals/mailbox.c @@ -0,0 +1,114 @@ +#include "peripherals/mailbox.h" + +static uint32_t MBox_buf[4096] __attribute__((aligned(16))); + +static uint32_t MBox_read(int channel){ + int ch, data; + + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_EMPTY_MASK); + + data = mbox_reg->read; + ch = data & MBOX_WRITE_CHANNEL_MASK; + if(ch == channel){ + LOG("MBox read address: %p", data & MBOX_READ_ADDR_MASK); + return (data & MBOX_READ_ADDR_MASK); + } + LOG("Leave"); + return 0; +} + +static void MBox_write(uint32_t data, int channel){ + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_FULL_MASK); + + mbox_reg->write = data | channel; + LOG("Leave"); +} + +static uint32_t MBox_process(uint8_t* tags, size_t tags_size){ + LOG("Enter"); + MBox_buffer* mbuf = (MBox_buffer*)MBox_buf; + // set buffer header + mbuf->buf_size = tags_size + 12; + mbuf->code = MBOX_STATUS_REQUEST; + + // copy tags to buffer + memcpy(mbuf->buf, tags, tags_size); + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + LOG("mbuf->buf: %p", mbuf->buf); + LOG("mbuf->buf + tags_size: %p", mbuf->buf + tags_size); + // end of MBox_buf + memset(mbuf->buf + tags_size, 0, 4); + + pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + // write to mailbox + MBox_write((uint32_t)(uint64_t)MBox_buf, MBOX_CHANNEL_PROPERTY_TAGS); + + // read from mailbox + uint32_t result = MBox_read(MBOX_CHANNEL_PROPERTY_TAGS); + + + LOG("Leave"); + return result; +} +void MBox_get_board_revision(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 4]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_BOARD_REVISION; + tag->value_size = 4; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer *)(uint64_t)MBox_process(buf, sizeof(MBox_tag) + 4); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + *ret = ((uint32_t*)tag->values)[0]; + LOG("Leave"); +} +void MBox_get_arm_memory(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 8]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_ARM_MEMORY; + tag->value_size = 8; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + ((uint32_t*)tag->values)[1] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer *)(uint64_t)MBox_process(buf, sizeof(MBox_tag) + 8); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + ret[0] = ((uint32_t*)tag->values)[0]; + ret[1] = ((uint32_t*)tag->values)[1]; + LOG("Leave"); +} + + diff --git a/lab3/peripherals/mini_uart.c b/lab3/peripherals/mini_uart.c new file mode 100644 index 000000000..ce7f2bafe --- /dev/null +++ b/lab3/peripherals/mini_uart.c @@ -0,0 +1,195 @@ +#include "peripherals/mini_uart.h" + +static ring_buffer* rx_rbuf = NULL; +static ring_buffer* tx_rbuf = NULL; + +inline void delay_cycles(uint64_t n){ + for(register uint64_t i = 0 ; i < n ; i++) asm volatile("nop"); +} + +inline void enable_mini_uart_irq(uint32_t tx){ + uint32_t old_ier = IO_MMIO_read32(AUX_MU_IER_REG); + + if(tx == TX) IO_MMIO_write32(AUX_MU_IER_REG, 0b10 | old_ier); + else IO_MMIO_write32(AUX_MU_IER_REG, 0b01 | old_ier); +} + +inline void enable_mini_uart_tx_irq(){ + if(mini_uart_get_tx_len() > 0){ + enable_mini_uart_irq(TX); + } +} + +inline void enable_mini_uart_rx_irq(){ + enable_mini_uart_irq(RX); +} + +inline void disable_mini_uart_irq(uint32_t tx){ + uint32_t old_ier = IO_MMIO_read32(AUX_MU_IER_REG); + + if(tx == TX) IO_MMIO_write32(AUX_MU_IER_REG, 0b01 & old_ier); + else IO_MMIO_write32(AUX_MU_IER_REG, 0b10 & old_ier); +} + +inline void disable_mini_uart_tx_irq(){ + disable_mini_uart_irq(TX); +} + +inline void disable_mini_uart_rx_irq(){ + disable_mini_uart_irq(RX); +} + +void mini_uart_init(){ + // GPIO 14 & 15 take function 0 + // Read out GPFSEL1 register + uint32_t tmp = IO_MMIO_read32(GPFSEL1); + + // Set GPIO 14 & 15 function bits + tmp &= ~(0b111111 << 12); + tmp |= 0b010010 << 12; + IO_MMIO_write32(GPFSEL1, tmp); + + + // disable pull-up/down of GPIO 14 & 15 + // Write to GPPUD to set the required control signal + IO_MMIO_write32(GPPUD, 0); + + // Wait 150 cycles – this provides the required set-up time for the control signal + delay_cycles(150); + + // Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to modify + IO_MMIO_write32(GPPUDCLK0, (1 << 14) | (1 << 15)); + + // Wait 150 cycles – this provides the required hold time for the control signal + delay_cycles(150); + + // Write to GPPUD to remove the control signa + IO_MMIO_write32(GPPUD, 0); + + // Write to GPPUDCLK0/1 to remove the clock + IO_MMIO_write32(GPPUDCLK0, 0); + + // Initialize Auxiliary peripherals Register + // Mini UART enable + IO_MMIO_write32(AUX_ENABLES, 1); + + // To disable auto flow control and disable receiver and transmitter, set control register to 0 + IO_MMIO_write32(AUX_MU_CNTL_REG, 0); + + // Disable mini UART's interrupt + IO_MMIO_write32(AUX_MU_IER_REG, 0); + + // Set UART to 8-bit mode + IO_MMIO_write32(AUX_MU_LCR_REG, 3); + + // To indicate that our UART is able to receive data, set RTS line to be always high + IO_MMIO_write32(AUX_MU_MCR_REG, 0); + + // Set Baud rate to 115200 + IO_MMIO_write32(AUX_MU_BAUD_REG, BAUD_RATE_REG); + + // Start UART + IO_MMIO_write32(AUX_MU_CNTL_REG, 3); + + return; +} + +uint8_t mini_uart_read(void){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & 0x1)); + return IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; +} + +void mini_uart_write(uint8_t val){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & (0x1 << 5))); + IO_MMIO_write32(AUX_MU_IO_REG, val); +} + +ssize_t write_bytes(uint8_t* buf, size_t n){ + for(uint64_t i = 0 ; i < n ; i++) mini_uart_write(buf[i]); + return n; +} + +void write_str(char* buf){ + while(*buf) mini_uart_write((uint8_t)*buf++); + return; +} + +void write_hex(uint64_t n){ + int i = 0; + char buf[16]; + char *hex_table = "0123456789abcdef"; + do{ + buf[i] = hex_table[n & 0xf]; + n = n >> 4; + i++; + }while(n); + do{ + i--; + mini_uart_write(buf[i]); + }while(i > 0); +} + +void mini_uart_irq_init(){ + rx_rbuf = create_ring_buf(4096 * 2 - 1); + tx_rbuf = create_ring_buf(4096 * 2 - 1); + + + IO_MMIO_write32(ENABLE_IRQS_1, 1 << 29); + // only enable receive interrupt. transmit interrupts should be enable when user want to transmit data. + enable_mini_uart_irq(RX); +} + +void mini_uart_tx_softirq_callback(){ +} + +void mini_uart_rx_softirq_callback(){ +} + +void mini_uart_irq_read(){ + while((IO_MMIO_read32(AUX_MU_LSR_REG) & 0x1)){ + uint8_t b[1]; + b[0] = IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; + ring_buf_write(rx_rbuf, b, 1); + } +} +size_t mini_uart_get_rx_len(){ + return ring_buf_get_len(rx_rbuf); +} + +uint8_t mini_uart_aio_read(void){ + uint8_t b[1]; + while(ring_buf_is_empty(rx_rbuf)); + + disable_mini_uart_irq(RX); + ring_buf_read(rx_rbuf, b, 1); + enable_mini_uart_irq(RX); + return b[0]; +} + +void mini_uart_irq_write(){ + uint8_t b[1]; + if(IO_MMIO_read32(AUX_MU_LSR_REG) & (0x1 << 5)){ + if(ring_buf_read(tx_rbuf, b, 1)){ + IO_MMIO_write32(AUX_MU_IO_REG, b[0]); + } + } +} +size_t mini_uart_get_tx_len(){ + return ring_buf_get_len(tx_rbuf); +} + +void mini_uart_aio_write(uint8_t c){ + uint8_t b[1]; + while(ring_buf_is_full(tx_rbuf)); + b[0] = c; +// disable_mini_uart_irq(TX); + local_irq_disable(); + ring_buf_write(tx_rbuf, b, 1); + local_irq_enable(); + enable_mini_uart_irq(TX); +} + +ssize_t aio_write_bytes(uint8_t* buf, size_t n){ + for(uint64_t i = 0 ; i < n ; i++) mini_uart_aio_write(buf[i]); + return n; +} diff --git a/lab3/test/lib/.gdb_history b/lab3/test/lib/.gdb_history new file mode 100644 index 000000000..58afc787f --- /dev/null +++ b/lab3/test/lib/.gdb_history @@ -0,0 +1,2 @@ +run +quit diff --git a/lab3/test/lib/dtb_parse/.gdb_history b/lab3/test/lib/dtb_parse/.gdb_history new file mode 100644 index 000000000..8ae386791 --- /dev/null +++ b/lab3/test/lib/dtb_parse/.gdb_history @@ -0,0 +1,43 @@ +b main +run +n +quit +run +p fdt +quit +b main +n +run +n +x/gx ptr +quit +b main +run +n +statbuf->size +p statbuf->size +p statbuf->st_size +quit +run +b main +run +n +s +n +p token +p/x pdft_struct +p/x pdt_struct +x/gx 0x7ffff7fb3048 +x/s 0x7ffff7fb3048 +x/dx 0x7ffff7fb3048 +x/wx 0x7ffff7fb3048 +x/4wx 0x7ffff7fb3048 +n +p len +n +quit +quit +run +quit +run +quit diff --git a/lab3/test/lib/dtb_parse/Makefile b/lab3/test/lib/dtb_parse/Makefile new file mode 100644 index 000000000..d6e1a8f08 --- /dev/null +++ b/lab3/test/lib/dtb_parse/Makefile @@ -0,0 +1,2 @@ +all: + gcc main.c fdt_parse.c -o main -g -O0 diff --git a/lab3/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb b/lab3/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 000000000..6f9ef31cc Binary files /dev/null and b/lab3/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb differ diff --git a/lab3/test/lib/dtb_parse/fdt_parse.c b/lab3/test/lib/dtb_parse/fdt_parse.c new file mode 100644 index 000000000..bb8abd2c8 --- /dev/null +++ b/lab3/test/lib/dtb_parse/fdt_parse.c @@ -0,0 +1,113 @@ +#include "fdt_parse.h" +#include +#include +#include + +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } + +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = (fdt_header*)malloc(sizeof(fdt_header)); + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) / 4; + //printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + len += 2; + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + printf("Parsing error!!\n"); + exit(0); + } + } +} + +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab3/test/lib/dtb_parse/fdt_parse.h b/lab3/test/lib/dtb_parse/fdt_parse.h new file mode 100644 index 000000000..876b4087a --- /dev/null +++ b/lab3/test/lib/dtb_parse/fdt_parse.h @@ -0,0 +1,53 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +#endif diff --git a/lab3/test/lib/dtb_parse/main b/lab3/test/lib/dtb_parse/main new file mode 100755 index 000000000..aa43f24f6 Binary files /dev/null and b/lab3/test/lib/dtb_parse/main differ diff --git a/lab3/test/lib/dtb_parse/main.c b/lab3/test/lib/dtb_parse/main.c new file mode 100644 index 000000000..9af1de752 --- /dev/null +++ b/lab3/test/lib/dtb_parse/main.c @@ -0,0 +1,19 @@ +#include "fdt_parse.h" +#include +#include +#include +#include +#include +#include + +int main(void){ + int fd = open("./bcm2710-rpi-3-b-plus.dtb", O_RDONLY); + if(fd < 0){ + printf("failed to open file\n"); + } + struct stat statbuf; + fstat(fd, &statbuf); + char *ptr = mmap(NULL,statbuf.st_size,PROT_READ,MAP_PRIVATE,fd,0); + + fdt_parser(ptr, fdt_print_callback); +} diff --git a/lab3/test/lib/dtb_parse/tmp.dts b/lab3/test/lib/dtb_parse/tmp.dts new file mode 100644 index 000000000..1ceb3539f --- /dev/null +++ b/lab3/test/lib/dtb_parse/tmp.dts @@ -0,0 +1,1515 @@ +/dts-v1/; + +/memreserve/ 0x0000000000000000 0x0000000000001000; +/ { + compatible = "raspberrypi,3-model-b-plus\0brcm,bcm2837"; + model = "Raspberry Pi 3 Model B+"; + #address-cells = <0x01>; + #size-cells = <0x01>; + interrupt-parent = <0x01>; + + aliases { + serial0 = "/soc/serial@7e215040"; + serial1 = "/soc/serial@7e201000"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + aux = "/soc/aux@7e215000"; + sound = "/soc/sound"; + soc = "/soc"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + uart0 = "/soc/serial@7e201000"; + uart1 = "/soc/serial@7e215040"; + sdhost = "/soc/mmc@7e202000"; + mmc = "/soc/mmc@7e300000"; + mmc1 = "/soc/mmcnr@7e300000"; + mmc0 = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c1 = "/soc/i2c@7e804000"; + i2c10 = "/soc/i2c0mux/i2c@1"; + spi0 = "/soc/spi@7e204000"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + usb = "/soc/usb@7e980000"; + leds = "/leds"; + fb = "/soc/fb"; + thermal = "/soc/thermal@7e212000"; + axiperf = "/soc/axiperf"; + i2c2 = "/soc/i2c@7e805000"; + ethernet0 = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + }; + + chosen { + bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; + }; + + reserved-memory { + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges; + phandle = <0x37>; + + linux,cma { + compatible = "shared-dma-pool"; + size = <0x4000000>; + reusable; + linux,cma-default; + phandle = <0x38>; + }; + }; + + thermal-zones { + + cpu-thermal { + polling-delay-passive = <0x00>; + polling-delay = <0x3e8>; + thermal-sensors = <0x02>; + coefficients = <0xfffffde6 0x64960>; + phandle = <0x39>; + + cooling-maps { + }; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x7e000000 0x3f000000 0x1000000 0x40000000 0x40000000 0x1000>; + dma-ranges = <0xc0000000 0x00 0x3f000000>; + phandle = <0x3a>; + + txp@7e004000 { + compatible = "brcm,bcm2835-txp"; + reg = <0x7e004000 0x20>; + interrupts = <0x01 0x0b>; + status = "disabled"; + phandle = <0x3b>; + }; + + cprman@7e101000 { + compatible = "brcm,bcm2835-cprman"; + #clock-cells = <0x01>; + reg = <0x7e101000 0x2000>; + clocks = <0x03 0x04 0x00 0x04 0x01 0x04 0x02 0x05 0x00 0x05 0x01 0x05 0x02>; + firmware = <0x06>; + phandle = <0x08>; + }; + + mailbox@7e00b880 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0x00 0x01>; + #mbox-cells = <0x00>; + phandle = <0x1f>; + }; + + gpio@7e200000 { + compatible = "brcm,bcm2835-gpio"; + reg = <0x7e200000 0xb4>; + interrupts = <0x02 0x11 0x02 0x12>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x07 0x00 0x00 0x36>; + pinctrl-names = "default"; + gpio-line-names = "ID_SDA\0ID_SCL\0SDA1\0SCL1\0GPIO_GCLK\0GPIO5\0GPIO6\0SPI_CE1_N\0SPI_CE0_N\0SPI_MISO\0SPI_MOSI\0SPI_SCLK\0GPIO12\0GPIO13\0TXD1\0RXD1\0GPIO16\0GPIO17\0GPIO18\0GPIO19\0GPIO20\0GPIO21\0GPIO22\0GPIO23\0GPIO24\0GPIO25\0GPIO26\0GPIO27\0HDMI_HPD_N\0STATUS_LED_G\0CTS0\0RTS0\0TXD0\0RXD0\0SD1_CLK\0SD1_CMD\0SD1_DATA0\0SD1_DATA1\0SD1_DATA2\0SD1_DATA3\0PWM0_OUT\0PWM1_OUT\0ETH_CLK\0WIFI_CLK\0SDA0\0SCL0\0SMPS_SCL\0SMPS_SDA\0SD_CLK_R\0SD_CMD_R\0SD_DATA0_R\0SD_DATA1_R\0SD_DATA2_R\0SD_DATA3_R"; + phandle = <0x07>; + + dpi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x06>; + phandle = <0x3c>; + }; + + emmc_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x07>; + phandle = <0x3d>; + }; + + emmc_gpio34 { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x3e>; + }; + + emmc_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x07>; + phandle = <0x17>; + }; + + gpclk0_gpio4 { + brcm,pins = <0x04>; + brcm,function = <0x04>; + phandle = <0x3f>; + }; + + gpclk1_gpio5 { + brcm,pins = <0x05>; + brcm,function = <0x04>; + phandle = <0x40>; + }; + + gpclk1_gpio42 { + brcm,pins = <0x2a>; + brcm,function = <0x04>; + phandle = <0x41>; + }; + + gpclk1_gpio44 { + brcm,pins = <0x2c>; + brcm,function = <0x04>; + phandle = <0x42>; + }; + + gpclk2_gpio6 { + brcm,pins = <0x06>; + brcm,function = <0x04>; + phandle = <0x43>; + }; + + gpclk2_gpio43 { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x44>; + }; + + i2c0_gpio0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x12>; + }; + + i2c0_gpio28 { + brcm,pins = <0x1c 0x1d>; + brcm,function = <0x04>; + phandle = <0x45>; + }; + + i2c0_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x05>; + phandle = <0x13>; + }; + + i2c1_gpio2 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x46>; + }; + + i2c1_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x06>; + phandle = <0x47>; + }; + + jtag_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x03>; + phandle = <0x48>; + }; + + pcm_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x49>; + }; + + pcm_gpio28 { + brcm,pins = <0x1c 0x1d 0x1e 0x1f>; + brcm,function = <0x06>; + phandle = <0x4a>; + }; + + sdhost_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x04>; + phandle = <0x0d>; + }; + + spi0_gpio7 { + brcm,pins = <0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x4b>; + }; + + spi0_gpio35 { + brcm,pins = <0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x04>; + phandle = <0x4c>; + }; + + spi1_gpio16 { + brcm,pins = <0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x03>; + phandle = <0x4d>; + }; + + spi2_gpio40 { + brcm,pins = <0x28 0x29 0x2a 0x2b 0x2c 0x2d>; + brcm,function = <0x03>; + phandle = <0x4e>; + }; + + uart0_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x04>; + phandle = <0x4f>; + }; + + uart0_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x07>; + phandle = <0x50>; + }; + + uart0_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x07>; + brcm,pull = <0x02 0x00>; + phandle = <0x51>; + }; + + uart0_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x52>; + }; + + uart0_gpio36 { + brcm,pins = <0x24 0x25>; + brcm,function = <0x06>; + phandle = <0x53>; + }; + + uart0_ctsrts_gpio38 { + brcm,pins = <0x26 0x27>; + brcm,function = <0x06>; + phandle = <0x54>; + }; + + uart1_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x02>; + phandle = <0x55>; + }; + + uart1_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x02>; + phandle = <0x56>; + }; + + uart1_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x02>; + phandle = <0x57>; + }; + + uart1_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x02>; + phandle = <0x58>; + }; + + uart1_gpio40 { + brcm,pins = <0x28 0x29>; + brcm,function = <0x02>; + phandle = <0x59>; + }; + + uart1_ctsrts_gpio42 { + brcm,pins = <0x2a 0x2b>; + brcm,function = <0x02>; + phandle = <0x5a>; + }; + + i2c_slave_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x07>; + phandle = <0x5b>; + }; + + jtag_gpio4 { + brcm,pins = <0x04 0x05 0x06 0x0c 0x0d>; + brcm,function = <0x02>; + phandle = <0x5c>; + }; + + pwm0_gpio12 { + brcm,pins = <0x0c>; + brcm,function = <0x04>; + phandle = <0x5d>; + }; + + pwm0_gpio18 { + brcm,pins = <0x12>; + brcm,function = <0x02>; + phandle = <0x5e>; + }; + + pwm0_gpio40 { + brcm,pins = <0x28>; + brcm,function = <0x04>; + phandle = <0x5f>; + }; + + pwm1_gpio13 { + brcm,pins = <0x0d>; + brcm,function = <0x04>; + phandle = <0x60>; + }; + + pwm1_gpio19 { + brcm,pins = <0x13>; + brcm,function = <0x02>; + phandle = <0x61>; + }; + + pwm1_gpio41 { + brcm,pins = <0x29>; + brcm,function = <0x04>; + phandle = <0x62>; + }; + + pwm1_gpio45 { + brcm,pins = <0x2d>; + brcm,function = <0x04>; + phandle = <0x63>; + }; + + dpi_18bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + brcm,pull = <0x00>; + phandle = <0x64>; + }; + + dpi_18bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + phandle = <0x65>; + }; + + dpi_18bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x66>; + }; + + dpi_18bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x67>; + }; + + dpi_16bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x68>; + }; + + dpi_16bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x69>; + }; + + dpi_16bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6a>; + }; + + dpi_16bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6b>; + }; + + gpioout { + brcm,pins = <0x06>; + brcm,function = <0x01>; + phandle = <0x6c>; + }; + + alt0 { + brcm,pins = <0x04 0x05 0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x6d>; + }; + + spi0_pins { + brcm,pins = <0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x0f>; + }; + + spi0_cs_pins { + brcm,pins = <0x08 0x07>; + brcm,function = <0x01>; + phandle = <0x10>; + }; + + i2c0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x6e>; + }; + + i2c1 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x18>; + }; + + i2s { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x0e>; + }; + + sdio_pins { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x1e>; + }; + + bt_pins { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x0a>; + }; + + uart0_pins { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x09>; + }; + + uart1_pins { + brcm,pins; + brcm,function; + brcm,pull; + phandle = <0x16>; + }; + + audio_pins { + brcm,pins = <0x28 0x29>; + brcm,function = <0x04>; + phandle = <0x20>; + }; + }; + + serial@7e201000 { + compatible = "arm,pl011\0arm,primecell"; + reg = <0x7e201000 0x200>; + interrupts = <0x02 0x19>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk\0apb_pclk"; + arm,primecell-periphid = <0x241011>; + cts-event-workaround; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x09 0x0a>; + status = "okay"; + phandle = <0x26>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <0x2dc6c0>; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x33>; + }; + }; + + mmc@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <0x02 0x18>; + clocks = <0x08 0x14>; + status = "okay"; + dmas = <0x0c 0x2000000d>; + dma-names = "rx-tx"; + bus-width = <0x04>; + brcm,overclock-50 = <0x00>; + brcm,pio-limit = <0x01>; + firmware = <0x06>; + pinctrl-names = "default"; + pinctrl-0 = <0x0d>; + phandle = <0x2f>; + }; + + i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; + reg = <0x7e203000 0x24>; + clocks = <0x08 0x1f>; + status = "disabled"; + dmas = <0x0c 0x02 0x0c 0x03>; + dma-names = "tx\0rx"; + #sound-dai-cells = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x0e>; + phandle = <0x28>; + }; + + spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x200>; + interrupts = <0x02 0x16>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + dmas = <0x0c 0x06 0x0c 0x07>; + dma-names = "tx\0rx"; + pinctrl-names = "default"; + pinctrl-0 = <0x0f 0x10>; + cs-gpios = <0x07 0x08 0x01 0x07 0x07 0x01>; + phandle = <0x29>; + + spidev@0 { + compatible = "spidev"; + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x6f>; + }; + + spidev@1 { + compatible = "spidev"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x70>; + }; + }; + + i2c@7e205000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e205000 0x200>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x11>; + }; + + i2c0mux { + compatible = "i2c-mux-pinctrl"; + #address-cells = <0x01>; + #size-cells = <0x00>; + i2c-parent = <0x11>; + pinctrl-names = "i2c0\0i2c_csi_dsi"; + status = "disabled"; + pinctrl-0 = <0x12>; + pinctrl-1 = <0x13>; + phandle = <0x2a>; + + i2c@0 { + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x71>; + }; + + i2c@1 { + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x72>; + }; + }; + + dpi@7e208000 { + compatible = "brcm,bcm2835-dpi"; + reg = <0x7e208000 0x8c>; + clocks = <0x08 0x14 0x08 0x2c>; + clock-names = "core\0pixel"; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x73>; + }; + + dsi@7e209000 { + compatible = "brcm,bcm2835-dsi0"; + reg = <0x7e209000 0x78>; + interrupts = <0x02 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x20 0x08 0x2f 0x08 0x31>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi0_byte\0dsi0_ddr2\0dsi0_ddr"; + status = "disabled"; + power-domains = <0x14 0x11>; + phandle = <0x04>; + }; + + aux@7e215000 { + compatible = "brcm,bcm2835-aux"; + #clock-cells = <0x01>; + reg = <0x7e215000 0x08>; + clocks = <0x08 0x14>; + phandle = <0x15>; + }; + + serial@7e215040 { + compatible = "brcm,bcm2835-aux-uart"; + reg = <0x7e215040 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x00>; + status = "okay"; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x16>; + phandle = <0x27>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = "\0\a\b"; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x74>; + }; + }; + + spi@7e215080 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e215080 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x75>; + }; + + spi@7e2150c0 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e2150c0 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x02>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x76>; + }; + + pwm@7e20c000 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x7e20c000 0x28>; + clocks = <0x08 0x1e>; + assigned-clocks = <0x08 0x1e>; + assigned-clock-rates = <0x989680>; + #pwm-cells = <0x02>; + status = "disabled"; + phandle = <0x77>; + }; + + mmc@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + status = "disabled"; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x17>; + bus-width = <0x04>; + phandle = <0x30>; + }; + + hvs@7e400000 { + compatible = "brcm,bcm2835-hvs"; + reg = <0x7e400000 0x6000>; + interrupts = <0x02 0x01>; + status = "disabled"; + phandle = <0x78>; + }; + + dsi@7e700000 { + compatible = "brcm,bcm2835-dsi1"; + reg = <0x7e700000 0x8c>; + interrupts = <0x02 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x23 0x08 0x30 0x08 0x32>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi1_byte\0dsi1_ddr2\0dsi1_ddr"; + status = "disabled"; + power-domains = <0x14 0x12>; + phandle = <0x05>; + }; + + i2c@7e804000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e804000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x18>; + clock-frequency = <0x186a0>; + phandle = <0x2b>; + }; + + usb@7e980000 { + compatible = "brcm,bcm2708-usb"; + reg = <0x7e980000 0x10000 0x7e006000 0x1000>; + interrupts = <0x01 0x09 0x02 0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x19>; + clock-names = "otg"; + phys = <0x1a>; + phy-names = "usb2-phy"; + interrupt-names = "usb\0soft"; + power-domains = <0x14 0x06>; + phandle = <0x79>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet@1 { + compatible = "usb424,7800"; + reg = <0x01>; + phandle = <0x7a>; + + mdio { + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet-phy@1 { + reg = <0x01>; + microchip,led-modes = <0x01 0x06>; + microchip,eee-enabled; + microchip,tx-lpi-timer = <0x258>; + microchip,downshift-after = <0x02>; + phandle = <0x36>; + }; + }; + }; + }; + }; + }; + + dma@7e007000 { + compatible = "brcm,bcm2835-dma"; + reg = <0x7e007000 0xf00>; + interrupts = <0x01 0x10 0x01 0x11 0x01 0x12 0x01 0x13 0x01 0x14 0x01 0x15 0x01 0x16 0x01 0x17 0x01 0x18 0x01 0x19 0x01 0x1a 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1c>; + interrupt-names = "dma0\0dma1\0dma2\0dma3\0dma4\0dma5\0dma6\0dma7\0dma8\0dma9\0dma10\0dma11\0dma12\0dma13\0dma14\0dma-shared-all"; + #dma-cells = <0x01>; + brcm,dma-channel-mask = <0x7f35>; + phandle = <0x0c>; + }; + + interrupt-controller@7e00b200 { + compatible = "brcm,bcm2836-armctrl-ic"; + reg = <0x7e00b200 0x200>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + interrupts = <0x08 0x04>; + phandle = <0x01>; + }; + + watchdog@7e100000 { + compatible = "brcm,bcm2835-pm\0brcm,bcm2835-pm-wdt"; + #power-domain-cells = <0x01>; + #reset-cells = <0x01>; + reg = <0x7e100000 0x114 0x7e00a000 0x24>; + clocks = <0x08 0x15 0x08 0x1d 0x08 0x17 0x08 0x16>; + clock-names = "v3d\0peri_image\0h264\0isp"; + system-power-controller; + phandle = <0x2d>; + }; + + rng@7e104000 { + compatible = "brcm,bcm2835-rng"; + reg = <0x7e104000 0x10>; + interrupts = <0x02 0x1d>; + phandle = <0x2e>; + }; + + pixelvalve@7e206000 { + compatible = "brcm,bcm2835-pixelvalve0"; + reg = <0x7e206000 0x100>; + interrupts = <0x02 0x0d>; + status = "disabled"; + phandle = <0x7b>; + }; + + pixelvalve@7e207000 { + compatible = "brcm,bcm2835-pixelvalve1"; + reg = <0x7e207000 0x100>; + interrupts = <0x02 0x0e>; + status = "disabled"; + phandle = <0x7c>; + }; + + thermal@7e212000 { + compatible = "brcm,bcm2837-thermal"; + reg = <0x7e212000 0x08>; + clocks = <0x08 0x1b>; + #thermal-sensor-cells = <0x00>; + status = "okay"; + phandle = <0x02>; + }; + + i2c@7e805000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e805000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x1d>; + }; + + vec@7e806000 { + compatible = "brcm,bcm2835-vec"; + reg = <0x7e806000 0x1000>; + clocks = <0x1c 0x0f>; + interrupts = <0x02 0x1b>; + status = "disabled"; + power-domains = <0x14 0x07>; + phandle = <0x7d>; + }; + + pixelvalve@7e807000 { + compatible = "brcm,bcm2835-pixelvalve2"; + reg = <0x7e807000 0x100>; + interrupts = <0x02 0x0a>; + status = "disabled"; + phandle = <0x7e>; + }; + + hdmi@7e902000 { + compatible = "brcm,bcm2835-hdmi"; + reg = <0x7e902000 0x600 0x7e808000 0x100>; + reg-names = "hdmi\0hd"; + interrupts = <0x02 0x08 0x02 0x09>; + ddc = <0x1d>; + clocks = <0x1c 0x09 0x1c 0x0d>; + clock-names = "pixel\0hdmi"; + dmas = <0x0c 0x9000011>; + dma-names = "audio-rx"; + status = "disabled"; + power-domains = <0x14 0x05>; + hpd-gpios = <0x07 0x1c 0x01>; + phandle = <0x7f>; + }; + + v3d@7ec00000 { + compatible = "brcm,vc4-v3d"; + reg = <0x7ec00000 0x1000>; + interrupts = <0x01 0x0a>; + power-domains = <0x14 0x0a>; + status = "disabled"; + phandle = <0x80>; + }; + + gpu { + compatible = "brcm,bcm2835-vc4"; + status = "disabled"; + raspberrypi,firmware = <0x06>; + phandle = <0x81>; + }; + + local_intc@40000000 { + compatible = "brcm,bcm2836-l1-intc"; + reg = <0x40000000 0x100>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + phandle = <0x1b>; + }; + + mmcnr@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + non-removable; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x1e>; + bus-width = <0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x31>; + + wifi@1 { + reg = <0x01>; + compatible = "brcm,bcm4329-fmac"; + phandle = <0x82>; + }; + }; + + firmwarekms@7e600000 { + compatible = "raspberrypi,rpi-firmware-kms"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + brcm,firmware = <0x06>; + status = "disabled"; + phandle = <0x83>; + }; + + smi@7e600000 { + compatible = "brcm,bcm2835-smi"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + clocks = <0x08 0x2a>; + assigned-clocks = <0x08 0x2a>; + assigned-clock-rates = <0x7735940>; + dmas = <0x0c 0x04>; + dma-names = "rx-tx"; + status = "disabled"; + phandle = <0x84>; + }; + + csi@7e800000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e800000 0x800 0x7e802000 0x04>; + interrupts = <0x02 0x06>; + clocks = <0x08 0x2d 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + phandle = <0x85>; + }; + + csi@7e801000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e801000 0x800 0x7e802004 0x04>; + interrupts = <0x02 0x07>; + clocks = <0x08 0x2e 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0d>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + brcm,num-data-lanes = <0x02>; + phandle = <0x86>; + }; + + axiperf { + compatible = "brcm,bcm2835-axiperf"; + reg = <0x7e009800 0x100 0x7ee08000 0x100>; + firmware = <0x06>; + status = "disabled"; + phandle = <0x32>; + }; + + firmware { + compatible = "raspberrypi,bcm2835-firmware\0simple-mfd"; + #address-cells = <0x01>; + #size-cells = <0x01>; + mboxes = <0x1f>; + dma-ranges; + phandle = <0x06>; + + clocks { + compatible = "raspberrypi,firmware-clocks"; + #clock-cells = <0x01>; + phandle = <0x1c>; + }; + + vcio { + compatible = "raspberrypi,vcio"; + phandle = <0x87>; + }; + + expgpio { + compatible = "raspberrypi,firmware-gpio"; + gpio-controller; + #gpio-cells = <0x02>; + gpio-line-names = "BT_ON\0WL_ON\0PWR_LED_R\0LAN_RUN\0NC\0CAM_GPIO0\0CAM_GPIO1\0NC"; + status = "okay"; + phandle = <0x0b>; + }; + }; + + power { + compatible = "raspberrypi,bcm2835-power"; + firmware = <0x06>; + #power-domain-cells = <0x01>; + phandle = <0x14>; + }; + + mailbox@7e00b840 { + compatible = "brcm,bcm2836-vchiq\0brcm,bcm2835-vchiq"; + reg = <0x7e00b840 0x3c>; + interrupts = <0x00 0x02>; + phandle = <0x88>; + + bcm2835_audio { + compatible = "brcm,bcm2835-audio"; + brcm,firmware = <0x06>; + brcm,pwm-channels = <0x08>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x20>; + phandle = <0x2c>; + }; + }; + + gpiomem { + compatible = "brcm,bcm2835-gpiomem"; + reg = <0x7e200000 0x1000>; + }; + + fb { + compatible = "brcm,bcm2708-fb"; + firmware = <0x06>; + status = "okay"; + phandle = <0x89>; + }; + + sound { + status = "disabled"; + phandle = <0x8a>; + }; + }; + + clocks { + + clk-osc { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "osc"; + clock-frequency = <0x124f800>; + phandle = <0x03>; + }; + + clk-usb { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "otg"; + clock-frequency = <0x1c9c3800>; + phandle = <0x19>; + }; + }; + + phy { + compatible = "usb-nop-xceiv"; + #phy-cells = <0x00>; + phandle = <0x1a>; + }; + + arm-pmu { + compatible = "arm,cortex-a53-pmu\0arm,cortex-a7-pmu"; + interrupt-parent = <0x1b>; + interrupts = <0x09 0x04>; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupt-parent = <0x1b>; + interrupts = <0x00 0x04 0x01 0x04 0x03 0x04 0x02 0x04>; + always-on; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + enable-method = "brcm,bcm2836-smp"; + phandle = <0x8b>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x00>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xd8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x22>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x01>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x23>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x02>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x24>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x03>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xf0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x25>; + }; + + l2-cache0 { + compatible = "cache"; + cache-size = <0x80000>; + cache-line-size = <0x40>; + cache-sets = <0x200>; + cache-level = <0x02>; + phandle = <0x21>; + }; + }; + + cam1_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam1-reg"; + enable-active-high; + status = "okay"; + gpio = <0x0b 0x05 0x00>; + phandle = <0x8c>; + }; + + cam1_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8d>; + }; + + cam0_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam0-reg"; + enable-active-high; + status = "disabled"; + phandle = <0x8e>; + }; + + cam0_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8f>; + }; + + cam_dummy_reg { + compatible = "regulator-fixed"; + regulator-name = "cam-dummy-reg"; + status = "okay"; + phandle = <0x90>; + }; + + __overrides__ { + cam0-pwdn-ctrl; + cam0-pwdn; + cam0-led-ctrl; + cam0-led; + arm_freq = "\0\0\0\"clock-frequency:0\0\0\0\0#clock-frequency:0\0\0\0\0$clock-frequency:0\0\0\0\0%clock-frequency:0"; + cache_line_size; + uart0 = "\0\0\0&status"; + uart1 = "\0\0\0'status"; + i2s = "\0\0\0(status"; + spi = "\0\0\0)status"; + i2c0 = [00 00 00 11 73 74 61 74 75 73 00 00 00 00 2a 73 74 61 74 75 73 00]; + i2c1 = "\0\0\0+status"; + i2c0_baudrate = [00 00 00 11 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + i2c1_baudrate = "\0\0\0+clock-frequency:0"; + audio = "\0\0\0,status"; + watchdog = "\0\0\0-status"; + random = "\0\0\0.status"; + sd_overclock = "\0\0\0/brcm,overclock-50:0"; + sd_force_pio = "\0\0\0/brcm,force-pio?"; + sd_pio_limit = "\0\0\0/brcm,pio-limit:0"; + sd_debug = "\0\0\0/brcm,debug"; + sdio_overclock = "\0\0\00brcm,overclock-50:0\0\0\0\01brcm,overclock-50:0"; + axiperf = "\0\0\02status"; + i2c2_iknowwhatimdoing = [00 00 00 1d 73 74 61 74 75 73 00]; + i2c2_baudrate = [00 00 00 1d 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + sd_poll_once = "\0\0\0/non-removable?"; + krnbt = "\0\0\03status"; + krnbt_baudrate = "\0\0\03max-speed:0"; + act_led_gpio = "\0\0\04gpios:4"; + act_led_activelow = "\0\0\04gpios:8"; + act_led_trigger = "\0\0\04linux,default-trigger"; + pwr_led_gpio = "\0\0\05gpios:4"; + pwr_led_activelow = "\0\0\05gpios:8"; + pwr_led_trigger = "\0\0\05linux,default-trigger"; + eee = "\0\0\06microchip,eee-enabled?"; + tx_lpi_timer = "\0\0\06microchip,tx-lpi-timer:0"; + eth_led0 = "\0\0\06microchip,led-modes:0"; + eth_led1 = "\0\0\06microchip,led-modes:4"; + eth_downshift_after = "\0\0\06microchip,downshift-after:0"; + eth_max_speed = "\0\0\06max-speed:0"; + }; + + leds { + compatible = "gpio-leds"; + phandle = <0x91>; + + led-act { + label = "led0"; + default-state = "keep"; + linux,default-trigger = "mmc0"; + gpios = <0x07 0x1d 0x00>; + phandle = <0x34>; + }; + + led-pwr { + label = "led1"; + linux,default-trigger = "default-on"; + gpios = <0x0b 0x02 0x01>; + phandle = <0x35>; + }; + }; + + fixedregulator_3v3 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microvolt = <0x325aa0>; + regulator-name = "3v3"; + phandle = <0x92>; + }; + + fixedregulator_5v0 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x4c4b40>; + regulator-min-microvolt = <0x4c4b40>; + regulator-name = "5v0"; + phandle = <0x93>; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00 0x00>; + }; + + __symbols__ { + rmem = "/reserved-memory"; + cma = "/reserved-memory/linux,cma"; + cpu_thermal = "/thermal-zones/cpu-thermal"; + soc = "/soc"; + txp = "/soc/txp@7e004000"; + clocks = "/soc/cprman@7e101000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + dpi_gpio0 = "/soc/gpio@7e200000/dpi_gpio0"; + emmc_gpio22 = "/soc/gpio@7e200000/emmc_gpio22"; + emmc_gpio34 = "/soc/gpio@7e200000/emmc_gpio34"; + emmc_gpio48 = "/soc/gpio@7e200000/emmc_gpio48"; + gpclk0_gpio4 = "/soc/gpio@7e200000/gpclk0_gpio4"; + gpclk1_gpio5 = "/soc/gpio@7e200000/gpclk1_gpio5"; + gpclk1_gpio42 = "/soc/gpio@7e200000/gpclk1_gpio42"; + gpclk1_gpio44 = "/soc/gpio@7e200000/gpclk1_gpio44"; + gpclk2_gpio6 = "/soc/gpio@7e200000/gpclk2_gpio6"; + gpclk2_gpio43 = "/soc/gpio@7e200000/gpclk2_gpio43"; + i2c0_gpio0 = "/soc/gpio@7e200000/i2c0_gpio0"; + i2c0_gpio28 = "/soc/gpio@7e200000/i2c0_gpio28"; + i2c0_gpio44 = "/soc/gpio@7e200000/i2c0_gpio44"; + i2c1_gpio2 = "/soc/gpio@7e200000/i2c1_gpio2"; + i2c1_gpio44 = "/soc/gpio@7e200000/i2c1_gpio44"; + jtag_gpio22 = "/soc/gpio@7e200000/jtag_gpio22"; + pcm_gpio18 = "/soc/gpio@7e200000/pcm_gpio18"; + pcm_gpio28 = "/soc/gpio@7e200000/pcm_gpio28"; + sdhost_gpio48 = "/soc/gpio@7e200000/sdhost_gpio48"; + spi0_gpio7 = "/soc/gpio@7e200000/spi0_gpio7"; + spi0_gpio35 = "/soc/gpio@7e200000/spi0_gpio35"; + spi1_gpio16 = "/soc/gpio@7e200000/spi1_gpio16"; + spi2_gpio40 = "/soc/gpio@7e200000/spi2_gpio40"; + uart0_gpio14 = "/soc/gpio@7e200000/uart0_gpio14"; + uart0_ctsrts_gpio16 = "/soc/gpio@7e200000/uart0_ctsrts_gpio16"; + uart0_ctsrts_gpio30 = "/soc/gpio@7e200000/uart0_ctsrts_gpio30"; + uart0_gpio32 = "/soc/gpio@7e200000/uart0_gpio32"; + uart0_gpio36 = "/soc/gpio@7e200000/uart0_gpio36"; + uart0_ctsrts_gpio38 = "/soc/gpio@7e200000/uart0_ctsrts_gpio38"; + uart1_gpio14 = "/soc/gpio@7e200000/uart1_gpio14"; + uart1_ctsrts_gpio16 = "/soc/gpio@7e200000/uart1_ctsrts_gpio16"; + uart1_gpio32 = "/soc/gpio@7e200000/uart1_gpio32"; + uart1_ctsrts_gpio30 = "/soc/gpio@7e200000/uart1_ctsrts_gpio30"; + uart1_gpio40 = "/soc/gpio@7e200000/uart1_gpio40"; + uart1_ctsrts_gpio42 = "/soc/gpio@7e200000/uart1_ctsrts_gpio42"; + i2c_slave_gpio18 = "/soc/gpio@7e200000/i2c_slave_gpio18"; + jtag_gpio4 = "/soc/gpio@7e200000/jtag_gpio4"; + pwm0_gpio12 = "/soc/gpio@7e200000/pwm0_gpio12"; + pwm0_gpio18 = "/soc/gpio@7e200000/pwm0_gpio18"; + pwm0_gpio40 = "/soc/gpio@7e200000/pwm0_gpio40"; + pwm1_gpio13 = "/soc/gpio@7e200000/pwm1_gpio13"; + pwm1_gpio19 = "/soc/gpio@7e200000/pwm1_gpio19"; + pwm1_gpio41 = "/soc/gpio@7e200000/pwm1_gpio41"; + pwm1_gpio45 = "/soc/gpio@7e200000/pwm1_gpio45"; + dpi_18bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio0"; + dpi_18bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio2"; + dpi_18bit_gpio0 = "/soc/gpio@7e200000/dpi_18bit_gpio0"; + dpi_18bit_gpio2 = "/soc/gpio@7e200000/dpi_18bit_gpio2"; + dpi_16bit_gpio0 = "/soc/gpio@7e200000/dpi_16bit_gpio0"; + dpi_16bit_gpio2 = "/soc/gpio@7e200000/dpi_16bit_gpio2"; + dpi_16bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio0"; + dpi_16bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio2"; + gpioout = "/soc/gpio@7e200000/gpioout"; + alt0 = "/soc/gpio@7e200000/alt0"; + spi0_pins = "/soc/gpio@7e200000/spi0_pins"; + spi0_cs_pins = "/soc/gpio@7e200000/spi0_cs_pins"; + i2c0_pins = "/soc/gpio@7e200000/i2c0"; + i2c1_pins = "/soc/gpio@7e200000/i2c1"; + i2s_pins = "/soc/gpio@7e200000/i2s"; + sdio_pins = "/soc/gpio@7e200000/sdio_pins"; + bt_pins = "/soc/gpio@7e200000/bt_pins"; + uart0_pins = "/soc/gpio@7e200000/uart0_pins"; + uart1_pins = "/soc/gpio@7e200000/uart1_pins"; + audio_pins = "/soc/gpio@7e200000/audio_pins"; + uart0 = "/soc/serial@7e201000"; + bt = "/soc/serial@7e201000/bluetooth"; + sdhost = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + spi0 = "/soc/spi@7e204000"; + spi = "/soc/spi@7e204000"; + spidev0 = "/soc/spi@7e204000/spidev@0"; + spidev1 = "/soc/spi@7e204000/spidev@1"; + i2c0if = "/soc/i2c@7e205000"; + i2c0mux = "/soc/i2c0mux"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c_csi_dsi = "/soc/i2c0mux/i2c@1"; + dpi = "/soc/dpi@7e208000"; + dsi0 = "/soc/dsi@7e209000"; + aux = "/soc/aux@7e215000"; + uart1 = "/soc/serial@7e215040"; + minibt = "/soc/serial@7e215040/bluetooth"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + pwm = "/soc/pwm@7e20c000"; + mmc = "/soc/mmc@7e300000"; + sdhci = "/soc/mmc@7e300000"; + hvs = "/soc/hvs@7e400000"; + dsi1 = "/soc/dsi@7e700000"; + i2c1 = "/soc/i2c@7e804000"; + usb = "/soc/usb@7e980000"; + ethernet = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + eth_phy = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1/mdio/ethernet-phy@1"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + pm = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + pixelvalve0 = "/soc/pixelvalve@7e206000"; + pixelvalve1 = "/soc/pixelvalve@7e207000"; + thermal = "/soc/thermal@7e212000"; + i2c2 = "/soc/i2c@7e805000"; + vec = "/soc/vec@7e806000"; + pixelvalve2 = "/soc/pixelvalve@7e807000"; + hdmi = "/soc/hdmi@7e902000"; + v3d = "/soc/v3d@7ec00000"; + vc4 = "/soc/gpu"; + local_intc = "/soc/local_intc@40000000"; + mmcnr = "/soc/mmcnr@7e300000"; + brcmf = "/soc/mmcnr@7e300000/wifi@1"; + firmwarekms = "/soc/firmwarekms@7e600000"; + smi = "/soc/smi@7e600000"; + csi0 = "/soc/csi@7e800000"; + csi1 = "/soc/csi@7e801000"; + axiperf = "/soc/axiperf"; + firmware = "/soc/firmware"; + firmware_clocks = "/soc/firmware/clocks"; + vcio = "/soc/firmware/vcio"; + expgpio = "/soc/firmware/expgpio"; + power = "/soc/power"; + vchiq = "/soc/mailbox@7e00b840"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + fb = "/soc/fb"; + sound = "/soc/sound"; + clk_osc = "/clocks/clk-osc"; + clk_usb = "/clocks/clk-usb"; + usbphy = "/phy"; + cpus = "/cpus"; + cpu0 = "/cpus/cpu@0"; + cpu1 = "/cpus/cpu@1"; + cpu2 = "/cpus/cpu@2"; + cpu3 = "/cpus/cpu@3"; + l2 = "/cpus/l2-cache0"; + cam1_reg = "/cam1_regulator"; + cam1_clk = "/cam1_clk"; + cam0_regulator = "/cam0_regulator"; + cam0_clk = "/cam0_clk"; + cam0_reg = "/cam_dummy_reg"; + cam_dummy_reg = "/cam_dummy_reg"; + leds = "/leds"; + act_led = "/leds/led-act"; + pwr_led = "/leds/led-pwr"; + vdd_3v3_reg = "/fixedregulator_3v3"; + vdd_5v0_reg = "/fixedregulator_5v0"; + }; +}; diff --git a/lab3/test/lib/dtb_parse/types.h b/lab3/test/lib/dtb_parse/types.h new file mode 100644 index 000000000..94f612c66 --- /dev/null +++ b/lab3/test/lib/dtb_parse/types.h @@ -0,0 +1,26 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#define NULL ((void*)0) + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) +#endif diff --git a/lab3/test/lib/list/Makefile b/lab3/test/lib/list/Makefile new file mode 100644 index 000000000..764af75c6 --- /dev/null +++ b/lab3/test/lib/list/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/list.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab3/test/lib/list/test b/lab3/test/lib/list/test new file mode 100755 index 000000000..dd63c9895 Binary files /dev/null and b/lab3/test/lib/list/test differ diff --git a/lab3/test/lib/list/test.c b/lab3/test/lib/list/test.c new file mode 100644 index 000000000..b568a42a4 --- /dev/null +++ b/lab3/test/lib/list/test.c @@ -0,0 +1,59 @@ +#include "lib/list.h" +#include +#include +#include +struct student{ + int id; + char name[100]; + struct list_head list; +}; + +struct student* create_student(int id, char* name){ + struct student* s = (struct student*)malloc(sizeof(struct student)); + s->id = id; + strcpy(s->name, name); + return s; +} +void print_student(struct student* s){ + printf("------------------------------------------\n"); + printf(" id: %d\n", s->id); + printf(" name: %s\n", s->name); + printf("------------------------------------------\n"); +} +int main(void){ + struct list_head* node, head; + INIT_LIST_HEAD(&head); + + if(list_empty(&head)){ + printf("List is empty\n"); + } + list_add(&create_student(13, "xiaobye")->list, &head); + list_add(&create_student(35, "test01")->list, &head); + list_add(&create_student(34, "test02")->list, &head); + + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + if(!list_empty(&head)){ + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + } + + + return 0; +} + diff --git a/lab3/test/lib/malloc/.gdb_history b/lab3/test/lib/malloc/.gdb_history new file mode 100644 index 000000000..1b332373d --- /dev/null +++ b/lab3/test/lib/malloc/.gdb_history @@ -0,0 +1,9 @@ +b main +run +ni +x/gx $rax +x/gx $rax - 0x10 + call malloc(1) +x/gx $rax - 0x10 +x/gx 0x5555555592c0 +quit diff --git a/lab3/test/lib/malloc/Makefile b/lab3/test/lib/malloc/Makefile new file mode 100644 index 000000000..2aedecaf1 --- /dev/null +++ b/lab3/test/lib/malloc/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/simple_malloc.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab3/test/lib/malloc/test b/lab3/test/lib/malloc/test new file mode 100755 index 000000000..194c23579 Binary files /dev/null and b/lab3/test/lib/malloc/test differ diff --git a/lab3/test/lib/malloc/test.c b/lab3/test/lib/malloc/test.c new file mode 100644 index 000000000..374f6deff --- /dev/null +++ b/lab3/test/lib/malloc/test.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include "lib/simple_malloc.h" + +#define RANGE 1000 +int main(void){ + void* cur,* next; + size_t req_size, real_size; + void* p = mmap( NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 ); + init_malloc_state(p); + srand((unsigned)time(0)); + + for(int i = 0 ; i < 30 ; i++){ + req_size = (uint64_t)rand() % RANGE; + cur = simple_malloc(req_size); + next = get_remainder(); + real_size = (uint64_t)next - (uint64_t)cur; + printf("cur: %p, next: %p, request size: %lu, real size: %lu, legal: %d\n", cur, next , req_size, real_size, (req_size <= real_size) && !(real_size % 16)); + } + + return 0; +} diff --git a/lab3/test/lib/malloc/test.py b/lab3/test/lib/malloc/test.py new file mode 100644 index 000000000..cce0d171c --- /dev/null +++ b/lab3/test/lib/malloc/test.py @@ -0,0 +1,9 @@ +def req2size(val, a): + if val < 16: + print(val,": ", hex(32)) + else: + print(val,": ",hex((val + 16 + (a - 1)) & ~(a-1))) + +for i in range(0, 64): + req2size(i, 16) + diff --git a/lab3/test/lib/ring_buffer/.gdb_history b/lab3/test/lib/ring_buffer/.gdb_history new file mode 100644 index 000000000..b7bc3d7af --- /dev/null +++ b/lab3/test/lib/ring_buffer/.gdb_history @@ -0,0 +1,17 @@ +run +quit +file main +run +p rbuf +quit +quit +run +x/gx 0x555555556008 +p rbuf->buf[rbuf->head] +s +ni +quit +b main +run +n +quit diff --git a/lab3/test/lib/ring_buffer/Makefile b/lab3/test/lib/ring_buffer/Makefile new file mode 100644 index 000000000..ec3d806b1 --- /dev/null +++ b/lab3/test/lib/ring_buffer/Makefile @@ -0,0 +1,2 @@ +all: + gcc main.c ring_buffer.c -o main -g -O0 diff --git a/lab3/test/lib/ring_buffer/main b/lab3/test/lib/ring_buffer/main new file mode 100755 index 000000000..bc8cc09fa Binary files /dev/null and b/lab3/test/lib/ring_buffer/main differ diff --git a/lab3/test/lib/ring_buffer/main.c b/lab3/test/lib/ring_buffer/main.c new file mode 100644 index 000000000..ea70d0e9b --- /dev/null +++ b/lab3/test/lib/ring_buffer/main.c @@ -0,0 +1,50 @@ +#include "ring_buffer.h" +#include +#include +char* s = "abcdefghijklmn"; +int main(void){ + char b[10]; + ring_buffer* rbuf = create_ring_buf(10); + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } + + ring_buf_write(rbuf, s, 8); + + if(!ring_buf_is_empty(rbuf)){ + printf("Ring buffer is has some contant now!\n"); + int i = ring_buf_read(rbuf, b, 100); + b[i] = '\0'; + + printf("%d: %s\n", i, b); + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } + } + printf("%lu\n", ring_buf_write(rbuf, s, 16)); + if(ring_buf_is_full(rbuf)){ + printf("Ring buffer is full now!\n"); + } + + int i = ring_buf_read(rbuf, b, 4); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + i = ring_buf_write(rbuf, b, 10); + printf("%d\n", i); + + i = ring_buf_read(rbuf, b, 7); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + i = ring_buf_read(rbuf, b, 10); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + if(ring_buf_is_full(rbuf)){ + printf("Ring buffer is full now!\n"); + } + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } +} diff --git a/lab3/test/lib/ring_buffer/ring_buffer.c b/lab3/test/lib/ring_buffer/ring_buffer.c new file mode 100644 index 000000000..a5e7e3612 --- /dev/null +++ b/lab3/test/lib/ring_buffer/ring_buffer.c @@ -0,0 +1,42 @@ +#include "ring_buffer.h" +#include +ring_buffer* create_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)malloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)malloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + return tmp; +} + +uint8_t ring_buf_is_empty(ring_buffer* rbuf){ + if(rbuf->head == rbuf->tail) return 1; + return 0; +} +uint8_t ring_buf_is_full(ring_buffer* rbuf){ + if((rbuf->tail + 1) % (rbuf->size + 1) == rbuf->head) return 1; + return 0; +} +size_t ring_buf_write(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + return count; +} +size_t ring_buf_read(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + return count; +} + diff --git a/lab3/test/lib/ring_buffer/ring_buffer.h b/lab3/test/lib/ring_buffer/ring_buffer.h new file mode 100644 index 000000000..61c0431d4 --- /dev/null +++ b/lab3/test/lib/ring_buffer/ring_buffer.h @@ -0,0 +1,17 @@ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ +#include "types.h" + +typedef struct{ + size_t size; + uint64_t head; + uint64_t tail; + uint8_t* buf; +}ring_buffer; + +extern ring_buffer* create_ring_buf(size_t); +extern size_t ring_buf_write(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read(ring_buffer*, uint8_t*, size_t); +extern uint8_t ring_buf_is_full(ring_buffer*); +extern uint8_t ring_buf_is_empty(ring_buffer*); +#endif diff --git a/lab3/test/lib/ring_buffer/types.h b/lab3/test/lib/ring_buffer/types.h new file mode 100644 index 000000000..94f612c66 --- /dev/null +++ b/lab3/test/lib/ring_buffer/types.h @@ -0,0 +1,26 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#define NULL ((void*)0) + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) +#endif diff --git a/lab3/test/lib/string/.gdb_history b/lab3/test/lib/string/.gdb_history new file mode 100644 index 000000000..d0d68342a --- /dev/null +++ b/lab3/test/lib/string/.gdb_history @@ -0,0 +1,47 @@ +b main +run +n +quit +run +b main +run +n +quit +b main +run +n +run +n +s +s +n +x/gx rax +x/gx $rax +run +s +n +s +x/bx s +s +p c +n +n +quit +b main +run +s +x/s delim +s +s +ni +n +ni +x/s s +x/s pos +x/b pos +x/bx pos +n +n +s +s +quit diff --git a/lab3/test/lib/string/Makefile b/lab3/test/lib/string/Makefile new file mode 100644 index 000000000..e7e0f12c1 --- /dev/null +++ b/lab3/test/lib/string/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/string.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab3/test/lib/string/test b/lab3/test/lib/string/test new file mode 100755 index 000000000..a0a7ea144 Binary files /dev/null and b/lab3/test/lib/string/test differ diff --git a/lab3/test/lib/string/test.c b/lab3/test/lib/string/test.c new file mode 100644 index 000000000..b23d13172 --- /dev/null +++ b/lab3/test/lib/string/test.c @@ -0,0 +1,31 @@ + +// C code to demonstrate working of +// strtok +#include +#include "string.h" + +// Driver function +int main() +{ + // Declaration of string + char *gfg = "setTimeout 123"; + + // Declaration of delimiter + const char s[4] = "-"; + char* tok; + + // Use of strtok + // get first token + tok = strtok(gfg, s); + + // Checks for delimiter + while (tok != 0) { + printf(" %s\n", tok); + + // Use of strtok + // go through other tokens + tok = strtok(0, s); + } + + return (0); +} diff --git a/lab3/tmp b/lab3/tmp new file mode 100644 index 000000000..e6016bf3e --- /dev/null +++ b/lab3/tmp @@ -0,0 +1,1449 @@ +sudo qemu-system-aarch64 -M raspi3b -kernel /home/xiaobye/Documents/OSDI/osc2022/lab2/build/kernel8.img -display none -serial null -serial stdio -initrd tools/cpio/initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + { + compatible ; + model ; + #address-cells ; + #size-cells ; + interrupt-parent ; + memory@0 { + reg ; + device_type ; + } + aliases { + serial0 ; + serial1 ; + audio ; + aux ; + sound ; + soc ; + dma ; + intc ; + watchdog ; + random ; + mailbox ; + gpio ; + uart0 ; + uart1 ; + sdhost ; + mmc ; + mmc1 ; + mmc0 ; + i2s ; + i2c0 ; + i2c1 ; + i2c10 ; + spi0 ; + spi1 ; + spi2 ; + usb ; + leds ; + fb ; + thermal ; + axiperf ; + i2c2 ; + ethernet0 ; + } + chosen { + linux,initrd-end ; + linux,initrd-start ; + bootargs ; + } + reserved-memory { + #address-cells ; + #size-cells ; + ranges ; + phandle ; + linux,cma { + compatible ; + size ; + reusable ; + linux,cma-default ; + phandle ; + } + } + thermal-zones { + cpu-thermal { + polling-delay-passive ; + polling-delay ; + thermal-sensors ; + coefficients ; + phandle ; + cooling-maps { + } + } + } + soc { + compatible ; + #address-cells ; + #size-cells ; + ranges ; + dma-ranges ; + phandle ; + txp@7e004000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + cprman@7e101000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + firmware ; + phandle ; + } + mailbox@7e00b880 { + compatible ; + reg ; + interrupts ; + #mbox-cells ; + phandle ; + } + gpio@7e200000 { + compatible ; + reg ; + interrupts ; + gpio-controller ; + #gpio-cells ; + interrupt-controller ; + #interrupt-cells ; + gpio-ranges ; + pinctrl-names ; + gpio-line-names ; + phandle ; + dpi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio34 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + emmc_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk0_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio5 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio6 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio43 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + i2c0_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + sdhost_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio7 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio35 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi1_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi2_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio32 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio36 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio38 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio32 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c_slave_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio12 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio13 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio19 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio41 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio45 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + dpi_18bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpioout { + brcm,pins ; + brcm,function ; + phandle ; + } + alt0 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_cs_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2s { + brcm,pins ; + brcm,function ; + phandle ; + } + sdio_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + bt_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart1_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + audio_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + } + serial@7e201000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + arm,primecell-periphid ; + cts-event-workaround ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + status ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + mmc@7e202000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + bus-width ; + brcm,overclock-50 ; + brcm,pio-limit ; + firmware ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + i2s@7e203000 { + compatible ; + reg ; + clocks ; + status ; + dmas ; + dma-names ; + #sound-dai-cells ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + spi@7e204000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + dmas ; + dma-names ; + pinctrl-names ; + pinctrl-0 ; + cs-gpios ; + phandle ; + spidev@0 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + spidev@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + } + i2c@7e205000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + i2c0mux { + compatible ; + #address-cells ; + #size-cells ; + i2c-parent ; + pinctrl-names ; + status ; + pinctrl-0 ; + pinctrl-1 ; + phandle ; + i2c@0 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + i2c@1 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + } + dpi@7e208000 { + compatible ; + reg ; + clocks ; + clock-names ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + dsi@7e209000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + aux@7e215000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + phandle ; + } + serial@7e215040 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + spi@7e215080 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + spi@7e2150c0 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + pwm@7e20c000 { + compatible ; + reg ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + #pwm-cells ; + status ; + phandle ; + } + mmc@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + brcm,overclock-50 ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + phandle ; + } + hvs@7e400000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + dsi@7e700000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + i2c@7e804000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + pinctrl-names ; + pinctrl-0 ; + clock-frequency ; + phandle ; + } + usb@7e980000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + clocks ; + clock-names ; + phys ; + phy-names ; + interrupt-names ; + power-domains ; + phandle ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + ethernet@1 { + compatible ; + reg ; + phandle ; + mdio { + #address-cells ; + #size-cells ; + ethernet-phy@1 { + reg ; + microchip,led-modes ; + microchip,eee-enabled ; + microchip,tx-lpi-timer ; + microchip,downshift-after ; + phandle ; + } + } + } + } + } + } + dma@7e007000 { + compatible ; + reg ; + interrupts ; + interrupt-names ; + #dma-cells ; + brcm,dma-channel-mask ; + phandle ; + } + interrupt-controller@7e00b200 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + interrupts ; + phandle ; + } + watchdog@7e100000 { + compatible ; + #power-domain-cells ; + #reset-cells ; + reg ; + clocks ; + clock-names ; + system-power-controller ; + phandle ; + } + rng@7e104000 { + compatible ; + reg ; + interrupts ; + phandle ; + } + pixelvalve@7e206000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + pixelvalve@7e207000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + thermal@7e212000 { + compatible ; + reg ; + clocks ; + #thermal-sensor-cells ; + status ; + phandle ; + } + i2c@7e805000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + vec@7e806000 { + compatible ; + reg ; + clocks ; + interrupts ; + status ; + power-domains ; + phandle ; + } + pixelvalve@7e807000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + hdmi@7e902000 { + compatible ; + reg ; + reg-names ; + interrupts ; + ddc ; + clocks ; + clock-names ; + dmas ; + dma-names ; + status ; + power-domains ; + hpd-gpios ; + phandle ; + } + v3d@7ec00000 { + compatible ; + reg ; + interrupts ; + power-domains ; + status ; + phandle ; + } + gpu { + compatible ; + status ; + raspberrypi,firmware ; + phandle ; + } + local_intc@40000000 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + phandle ; + } + mmcnr@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + dmas ; + dma-names ; + brcm,overclock-50 ; + non-removable ; + status ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + #address-cells ; + #size-cells ; + phandle ; + wifi@1 { + reg ; + compatible ; + phandle ; + } + } + firmwarekms@7e600000 { + compatible ; + reg ; + interrupts ; + brcm,firmware ; + status ; + phandle ; + } + smi@7e600000 { + compatible ; + reg ; + interrupts ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + dmas ; + dma-names ; + status ; + phandle ; + } + csi@7e800000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + phandle ; + } + csi@7e801000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + brcm,num-data-lanes ; + phandle ; + } + axiperf { + compatible ; + reg ; + firmware ; + status ; + phandle ; + } + firmware { + compatible ; + #address-cells ; + #size-cells ; + mboxes ; + dma-ranges ; + phandle ; + clocks { + compatible ; + #clock-cells ; + phandle ; + } + vcio { + compatible ; + phandle ; + } + expgpio { + compatible ; + gpio-controller ; + #gpio-cells ; + gpio-line-names ; + status ; + phandle ; + } + } + power { + compatible ; + firmware ; + #power-domain-cells ; + phandle ; + } + mailbox@7e00b840 { + compatible ; + reg ; + interrupts ; + phandle ; + bcm2835_audio { + compatible ; + brcm,firmware ; + brcm,pwm-channels ; + status ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + } + gpiomem { + compatible ; + reg ; + } + fb { + compatible ; + firmware ; + status ; + phandle ; + } + sound { + status ; + phandle ; + } + } + clocks { + clk-osc { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + clk-usb { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + } + phy { + compatible ; + #phy-cells ; + phandle ; + } + arm-pmu { + compatible ; + interrupt-parent ; + interrupts ; + } + timer { + compatible ; + interrupt-parent ; + interrupts ; + always-on ; + } + cpus { + #address-cells ; + #size-cells ; + enable-method ; + phandle ; + cpu@0 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@1 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@2 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@3 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + l2-cache0 { + compatible ; + cache-size ; + cache-line-size ; + cache-sets ; + cache-level ; + phandle ; + } + } + cam1_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + gpio ; + phandle ; + } + cam1_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam0_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + phandle ; + } + cam0_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam_dummy_reg { + compatible ; + regulator-name ; + status ; + phandle ; + } + __overrides__ { + cam0-pwdn-ctrl ; + cam0-pwdn ; + cam0-led-ctrl ; + cam0-led ; + arm_freq ; + cache_line_size ; + uart0 ; + uart1 ; + i2s ; + spi ; + i2c0 ; + i2c1 ; + i2c0_baudrate ; + i2c1_baudrate ; + audio ; + watchdog ; + random ; + sd_overclock ; + sd_force_pio ; + sd_pio_limit ; + sd_debug ; + sdio_overclock ; + axiperf ; + i2c2_iknowwhatimdoing ; + i2c2_baudrate ; + sd_poll_once ; + krnbt ; + krnbt_baudrate ; + act_led_gpio ; + act_led_activelow ; + act_led_trigger ; + pwr_led_gpio ; + pwr_led_activelow ; + pwr_led_trigger ; + eee ; + tx_lpi_timer ; + eth_led0 ; + eth_led1 ; + eth_downshift_after ; + eth_max_speed ; + } + leds { + compatible ; + phandle ; + led-act { + label ; + default-state ; + linux,default-trigger ; + gpios ; + phandle ; + } + led-pwr { + label ; + linux,default-trigger ; + gpios ; + phandle ; + } + } + fixedregulator_3v3 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + fixedregulator_5v0 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + __symbols__ { + rmem ; + cma ; + cpu_thermal ; + soc ; + txp ; + clocks ; + mailbox ; + gpio ; + dpi_gpio0 ; + emmc_gpio22 ; + emmc_gpio34 ; + emmc_gpio48 ; + gpclk0_gpio4 ; + gpclk1_gpio5 ; + gpclk1_gpio42 ; + gpclk1_gpio44 ; + gpclk2_gpio6 ; + gpclk2_gpio43 ; + i2c0_gpio0 ; + i2c0_gpio28 ; + i2c0_gpio44 ; + i2c1_gpio2 ; + i2c1_gpio44 ; + jtag_gpio22 ; + pcm_gpio18 ; + pcm_gpio28 ; + sdhost_gpio48 ; + spi0_gpio7 ; + spi0_gpio35 ; + spi1_gpio16 ; + spi2_gpio40 ; + uart0_gpio14 ; + uart0_ctsrts_gpio16 ; + uart0_ctsrts_gpio30 ; + uart0_gpio32 ; + uart0_gpio36 ; + uart0_ctsrts_gpio38 ; + uart1_gpio14 ; + uart1_ctsrts_gpio16 ; + uart1_gpio32 ; + uart1_ctsrts_gpio30 ; + uart1_gpio40 ; + uart1_ctsrts_gpio42 ; + i2c_slave_gpio18 ; + jtag_gpio4 ; + pwm0_gpio12 ; + pwm0_gpio18 ; + pwm0_gpio40 ; + pwm1_gpio13 ; + pwm1_gpio19 ; + pwm1_gpio41 ; + pwm1_gpio45 ; + dpi_18bit_cpadhi_gpio0 ; + dpi_18bit_cpadhi_gpio2 ; + dpi_18bit_gpio0 ; + dpi_18bit_gpio2 ; + dpi_16bit_gpio0 ; + dpi_16bit_gpio2 ; + dpi_16bit_cpadhi_gpio0 ; + dpi_16bit_cpadhi_gpio2 ; + gpioout ; + alt0 ; + spi0_pins ; + spi0_cs_pins ; + i2c0_pins ; + i2c1_pins ; + i2s_pins ; + sdio_pins ; + bt_pins ; + uart0_pins ; + uart1_pins ; + audio_pins ; + uart0 ; + bt ; + sdhost ; + i2s ; + spi0 ; + spi ; + spidev0 ; + spidev1 ; + i2c0if ; + i2c0mux ; + i2c0 ; + i2c_csi_dsi ; + dpi ; + dsi0 ; + aux ; + uart1 ; + minibt ; + spi1 ; + spi2 ; + pwm ; + mmc ; + sdhci ; + hvs ; + dsi1 ; + i2c1 ; + usb ; + ethernet ; + eth_phy ; + dma ; + intc ; + watchdog ; + pm ; + random ; + pixelvalve0 ; + pixelvalve1 ; + thermal ; + i2c2 ; + vec ; + pixelvalve2 ; + hdmi ; + v3d ; + vc4 ; + local_intc ; + mmcnr ; + brcmf ; + firmwarekms ; + smi ; + csi0 ; + csi1 ; + axiperf ; + firmware ; + firmware_clocks ; + vcio ; + expgpio ; + power ; + vchiq ; + audio ; + fb ; + sound ; + clk_osc ; + clk_usb ; + usbphy ; + cpus ; + cpu0 ; + cpu1 ; + cpu2 ; + cpu3 ; + l2 ; + cam1_reg ; + cam1_clk ; + cam0_regulator ; + cam0_clk ; + cam0_reg ; + cam_dummy_reg ; + leds ; + act_led ; + pwr_led ; + vdd_3v3_reg ; + vdd_5v0_reg ; + } +} +[simple_malloc.c/init_malloc_state:12] Simple heap start address: 0x8e000 + +[initrdfs.c/initrdfs_init:7] Enter initrdfs_int +[initrdfs.c/initrdfs_init:8] initrd start at 0x8000000 + +[initrdfs.c/initrdfs_init:9] initrd first 4 bytes: 37303730 + +[initrdfs.c/initrdfs_init:23] Start parsing new ascii format's cpio +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 2 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 112, iter->cur: 0x8000070 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: . +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 21 +[cpio.c/cpio_iter_parse:38] f->namesize: 6 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 140, iter->cur: 0x80000fc +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file1 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 34 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 156, iter->cur: 0x8000198 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file2.txt +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 5 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 116, iter->cur: 0x800020c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 5 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 128, iter->cur: 0x800028c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test/1234 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 0 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 11 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 124, iter->cur: 0x8000308 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: TRAILER!!! +[initrdfs.c/initrdfs_init:32] Leave initrdfs_int +text_start=0x80000, text_end=0x84000, text_size=16384 +rodata_start=0x84000, rodata_end=0x86000, rodata_size=8192 +data_start=0x86000, data_end=0x87000, data_size=4096 +bss_start=0x87000, bss_end=0x8e000, bss_size=28672 +heap_start=0x8e000 +⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀ +⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀ +⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁ +⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀ +⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀ +⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀ +⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀ +⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀ +⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀ +⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀ +⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀ +⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀ +⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀ + +# \ No newline at end of file diff --git a/lab3/tools/AUX_PERIPHERALS b/lab3/tools/AUX_PERIPHERALS new file mode 100644 index 000000000..324eb3019 --- /dev/null +++ b/lab3/tools/AUX_PERIPHERALS @@ -0,0 +1,23 @@ +0x7E215000 AUX_IRQ Auxiliary Interrupt status 3 +0x7E215004 AUX_ENABLES Auxiliary enables 3 +0x7E215040 AUX_MU_IO_REG Mini Uart I/O Data 8 +0x7E215044 AUX_MU_IER_REG Mini Uart Interrupt Enable 8 +0x7E215048 AUX_MU_IIR_REG Mini Uart Interrupt Identify 8 +0x7E21504C AUX_MU_LCR_REG Mini Uart Line Control 8 +0x7E215050 AUX_MU_MCR_REG Mini Uart Modem Control 8 +0x7E215054 AUX_MU_LSR_REG Mini Uart Line Status 8 +0x7E215058 AUX_MU_MSR_REG Mini Uart Modem Status 8 +0x7E21505C AUX_MU_SCRATCH Mini Uart Scratch 8 +0x7E215060 AUX_MU_CNTL_REG Mini Uart Extra Control 8 +0x7E215064 AUX_MU_STAT_REG Mini Uart Extra Status 32 +0x7E215068 AUX_MU_BAUD_REG Mini Uart Baudrate 16 +0x7E215080 AUX_SPI0_CNTL0_REG SPI 1 Control register 0 32 +0x7E215084 AUX_SPI0_CNTL1_REG SPI 1 Control register 1 8 +0x7E215088 AUX_SPI0_STAT_REG SPI 1 Status 32 +0x7E215090 AUX_SPI0_IO_REG SPI 1 Data 32 +0x7E215094 AUX_SPI0_PEEK_REG SPI 1 Peek 16 +0x7E2150C0 AUX_SPI1_CNTL0_REG SPI 2 Control register 0 32 +0x7E2150C4 AUX_SPI1_CNTL1_REG SPI 2 Control register 1 8 +0x7E2150C8 AUX_SPI1_STAT_REG SPI 2 Status 32 +0x7E2150D0 AUX_SPI1_IO_REG SPI 2 Data 32 +0x7E2150D4 AUX_SPI1_PEEK_REG SPI 2 Peek 16 diff --git a/lab3/tools/GPIO b/lab3/tools/GPIO new file mode 100644 index 000000000..ad2b10794 --- /dev/null +++ b/lab3/tools/GPIO @@ -0,0 +1,43 @@ +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200004 GPFSEL1 GPIO Function Select 1 32 R/W +0x7E200008 GPFSEL2 GPIO Function Select 2 32 R/W +0x7E20000C GPFSEL3 GPIO Function Select 3 32 R/W +0x7E200010 GPFSEL4 GPIO Function Select 4 32 R/W +0x7E200014 GPFSEL5 GPIO Function Select 5 32 R/W +0x7E200018 - Reserved - - +0x7E20001C GPSET0 GPIO Pin Output Set 0 32 W +0x7E200020 GPSET1 GPIO Pin Output Set 1 32 W +0x7E200024 - Reserved - - +0x7E200028 GPCLR0 GPIO Pin Output Clear 0 32 W +0x7E20002C GPCLR1 GPIO Pin Output Clear 1 32 W +0x7E200030 - Reserved - - +0x7E200034 GPLEV0 GPIO Pin Level 0 32 R +0x7E200038 GPLEV1 GPIO Pin Level 1 32 R +0x7E20003C - Reserved - - +0x7E200040 GPEDS0 GPIO Pin Event Detect Status 0 32 R/W +0x7E200044 GPEDS1 GPIO Pin Event Detect Status 1 32 R/W +0x7E200048 - Reserved - - +0x7E20004C GPREN0 GPIO Pin Rising Edge Detect Enable 0 32 R/W +0x7E200050 GPREN1 GPIO Pin Rising Edge Detect Enable 1 32 R/W +0x7E200054 - Reserved - - +0x7E200058 GPFEN0 GPIO Pin Falling Edge Detect Enable 0 32 R/W +0x7E20005C GPFEN1 GPIO Pin Falling Edge Detect Enable 1 32 R/W +0x7E200060 - Reserved - - +0x7E200064 GPHEN0 GPIO Pin High Detect Enable 0 32 R/W +0x7E200068 GPHEN1 GPIO Pin High Detect Enable 1 32 R/W +0x7E20006C - Reserved - - +0x7E200070 GPLEN0 GPIO Pin Low Detect Enable 0 32 R/W +0x7E200074 GPLEN1 GPIO Pin Low Detect Enable 1 32 R/W +0x7E200078 - Reserved - - +0x7E20007C GPAREN0 GPIO Pin Async. Rising Edge Detect 0 32 R/W +0x7E200080 GPAREN1 GPIO Pin Async. Rising Edge Detect 1 32 R/W +0x7E200084 - Reserved - - +0x7E200088 GPAFEN0 GPIO Pin Async. Falling Edge Detect 0 32 R/W +0x7E20008C GPAFEN1 GPIO Pin Async. Falling Edge Detect 1 32 R/W +0x7E200090 - Reserved - - +0x7E200094 GPPUD GPIO Pin Pull-up/down Enable 32 R/W +0x7E200098 GPPUDCLK0 GPIO Pin Pull-up/down Enable Clock 0 32 R/W +0x7E20009C GPPUDCLK1 GPIO Pin Pull-up/down Enable Clock 1 32 R/W +0x7E2000A0 - Reserved - - +0x7E2000B0 - Test 4 R/W diff --git a/lab3/tools/cpio/Makefile b/lab3/tools/cpio/Makefile new file mode 100644 index 000000000..1cbe92c74 --- /dev/null +++ b/lab3/tools/cpio/Makefile @@ -0,0 +1,35 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +override CFLAGS += \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin \ + +LDFLAGS ?= \ + -nostdlib \ + +CXXFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJDUMP = aarch64-linux-gnu-objdump +QEMU = qemu-system-aarch64 +RASPI_VER = raspi3b + + +LINKER_FILE = ./linker.ld +HEADERS = $(PWD)/include/ +OUTPUT = $(PWD)/build +KNAME = kernel8 +BNAME = bootloader + +.PHONY: all + + +all: + $(CC) -c -o test.o test.S $(CFLAGS) + $(LD) -T linker.ld -o test.elf test.o $(LDFLAGS) + $(OBJCOPY) -O binary test.elf test.img + diff --git a/lab3/tools/cpio/create_initramfs.sh b/lab3/tools/cpio/create_initramfs.sh new file mode 100755 index 000000000..2736e47fe --- /dev/null +++ b/lab3/tools/cpio/create_initramfs.sh @@ -0,0 +1,4 @@ +#! /bin/sh +cd rootfs +find . | cpio -o -H newc > ../initramfs.cpio +cd .. diff --git a/lab3/tools/cpio/initramfs.cpio b/lab3/tools/cpio/initramfs.cpio new file mode 100644 index 000000000..98a9c8fae Binary files /dev/null and b/lab3/tools/cpio/initramfs.cpio differ diff --git a/lab3/tools/cpio/linker.ld b/lab3/tools/cpio/linker.ld new file mode 100644 index 000000000..a550bf32e --- /dev/null +++ b/lab3/tools/cpio/linker.ld @@ -0,0 +1,41 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + +} diff --git a/lab3/tools/cpio/rootfs/file1 b/lab3/tools/cpio/rootfs/file1 new file mode 100644 index 000000000..b7b514317 --- /dev/null +++ b/lab3/tools/cpio/rootfs/file1 @@ -0,0 +1 @@ +This is your flag!!! diff --git a/lab3/tools/cpio/rootfs/file2.txt b/lab3/tools/cpio/rootfs/file2.txt new file mode 100644 index 000000000..367edaf2d --- /dev/null +++ b/lab3/tools/cpio/rootfs/file2.txt @@ -0,0 +1 @@ +FLAG{...........................} diff --git a/lab3/tools/cpio/rootfs/test.img b/lab3/tools/cpio/rootfs/test.img new file mode 100755 index 000000000..1adf648a4 Binary files /dev/null and b/lab3/tools/cpio/rootfs/test.img differ diff --git a/lab3/tools/cpio/rootfs/test/1234 b/lab3/tools/cpio/rootfs/test/1234 new file mode 100644 index 000000000..81c545efe --- /dev/null +++ b/lab3/tools/cpio/rootfs/test/1234 @@ -0,0 +1 @@ +1234 diff --git a/lab3/tools/cpio/test.S b/lab3/tools/cpio/test.S new file mode 100644 index 000000000..ce7e53908 --- /dev/null +++ b/lab3/tools/cpio/test.S @@ -0,0 +1,11 @@ +.section ".text" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b diff --git a/lab3/tools/cpio/test.elf b/lab3/tools/cpio/test.elf new file mode 100755 index 000000000..fbf6baf3c Binary files /dev/null and b/lab3/tools/cpio/test.elf differ diff --git a/lab3/tools/cpio/test.img b/lab3/tools/cpio/test.img new file mode 100755 index 000000000..1adf648a4 Binary files /dev/null and b/lab3/tools/cpio/test.img differ diff --git a/lab3/tools/cpio/test.o b/lab3/tools/cpio/test.o new file mode 100644 index 000000000..f84f74464 Binary files /dev/null and b/lab3/tools/cpio/test.o differ diff --git a/lab3/tools/gen.sh b/lab3/tools/gen.sh new file mode 100755 index 000000000..235b38c28 --- /dev/null +++ b/lab3/tools/gen.sh @@ -0,0 +1,24 @@ +#! /bin/sh +BUS_IO_BASE=0x7E000000 +PHY_IO_BASE=0x3F000000 +echo "/* Register's offset of GPIO */" +grep -v " - " GPIO | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + +echo "" +echo "" +echo "/* Register's offset of UART and SPI */" +grep -v " - " AUX_PERIPHERALS | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + + diff --git a/lab3/uart_upload.py b/lab3/uart_upload.py new file mode 100755 index 000000000..9a2a52d80 --- /dev/null +++ b/lab3/uart_upload.py @@ -0,0 +1,69 @@ +#! /usr/bin/python3 + +import sys +import struct +import serial +import os +import time +if len(sys.argv) < 4: + print(sys.argv[0], "", "", "") + sys.exit(-1) + +tty_name = sys.argv[1] +kernel_name = sys.argv[2] +base_addr = int(sys.argv[3], 16) + +ser = None + +def readline(): + os.write(1,b'[From bootloader]: ') + while 1: + c = ser.read(1) + if c == b'\n': + os.write(1, b'\n') + return + elif c != b'\r': + os.write(1, c) + + + +with open(kernel_name, "rb",) as kernel: + kernel_buf = kernel.read() + kernel_size = len(kernel_buf) + + + while(1): + ser = serial.Serial( + # Serial Port to read the data from + port = tty_name, + #Rate at which the information is shared to the communication channel + baudrate = 115200, + timeout = .1 + ) + + # start upload kernel to rasberry pi 3b+ by uart interface + # start header + ser.write(b"A") + ser.flush() + readline() + + # transfer kernel base address and kernel size ( both are 8 bytes ) in little endian + ser.write(struct.pack(" 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + + +master_core: +// stack + ldr x1, =_start + mov sp, x1 + +// recover dtb to x0 + adr x1, _dtb + ldr x0, [x1] + + +// jump to kernel_main + bl uart_recv_kernel + + b proc_hang + +// rebase our boot loader +rebase_bootloader: + // manipulate our return address ( x30 a.k.a LR ) to the rebased bootloader + // x19 = current PC + offset to _start + // x20 = absolute address ( _start ) that specify by linker script + adr x19, _start + ldr x20, =_start + sub x19, x19, x20 + sub lr , lr, x19 + + // x21 = absolute address ( __bootloader_start ) that specify by linker script + // x22 = current PC + offset to __bootloader_start ( In linker script ) + ldr x21, =__bootloader_start + adr x22, __bootloader_start + ldr x23, =__bootloader_size + // start rebasing bootloader +copy_bootloader: + cbz x23, end_rebase_bootloader + ldr x24, [x22], #8 + str x24, [x21], #8 + sub x23, x23, #8 + b copy_bootloader + +// Since ldr and str memory operation should obey 8 bytes alignment rule, the code here would failed on real device +// cbz x23, end_rebase_bootloader +// ldr x24, [x22], #1 +// str x24, [x21], #1 +// sub x23, x23, #1 +// b copy_bootloader + + + // return to rebased bootloader +end_rebase_bootloader: + ret + +.section ".data" +_dtb: .dword 0 diff --git a/lab4/boot/linker.ld b/lab4/boot/linker.ld new file mode 100644 index 000000000..740945ab2 --- /dev/null +++ b/lab4/boot/linker.ld @@ -0,0 +1,43 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x60000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __bootloader_start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + __bootloader_end = .; + __bootloader_size = (__bootloader_end - __bootloader_start); +} diff --git a/lab4/boot/uart_boot.c b/lab4/boot/uart_boot.c new file mode 100644 index 000000000..faec51411 --- /dev/null +++ b/lab4/boot/uart_boot.c @@ -0,0 +1,47 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "lib/print.h" + +void recv_boot_header(){ + while('A' != mini_uart_read()); +} + +size_t recv_kernel_base(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +size_t recv_kernel_size(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +void recv_kernel(uint64_t base, size_t size){ + uint8_t *pb; + size_t i; + for(pb = (uint8_t*)base , i = 0 ; i < size ; i++){ + pb[i] = mini_uart_read(); + } +} +uint64_t uart_recv_kernel(uint64_t dtb){ + size_t size; + uint64_t base; + mini_uart_init(); + + recv_boot_header(); +// printf("Receive A...\r\n"); + + base = recv_kernel_base(); +// printf("Receive kernel base 0x%x...\r\n", base); + + size = recv_kernel_size(); +// printf("Receive kernel size 0x%x...\r\n", size); + + recv_kernel(base, size); +// printf("Jump to kernel iamge...\r\n"); + + delay_cycles(10000); + ((void (*)(uint64_t))base)(dtb); +} diff --git a/lab4/build/asm.o b/lab4/build/asm.o new file mode 100644 index 000000000..e64c4949b Binary files /dev/null and b/lab4/build/asm.o differ diff --git a/lab4/build/bitops.o b/lab4/build/bitops.o new file mode 100644 index 000000000..f6889106e Binary files /dev/null and b/lab4/build/bitops.o differ diff --git a/lab4/build/boot.o b/lab4/build/boot.o new file mode 100644 index 000000000..d9a96fce6 Binary files /dev/null and b/lab4/build/boot.o differ diff --git a/lab4/build/bootloader.img b/lab4/build/bootloader.img new file mode 100755 index 000000000..00caf3628 Binary files /dev/null and b/lab4/build/bootloader.img differ diff --git a/lab4/build/cpio.o b/lab4/build/cpio.o new file mode 100644 index 000000000..d84f1e0af Binary files /dev/null and b/lab4/build/cpio.o differ diff --git a/lab4/build/debug.o b/lab4/build/debug.o new file mode 100644 index 000000000..9e8bb5d02 Binary files /dev/null and b/lab4/build/debug.o differ diff --git a/lab4/build/entry.o b/lab4/build/entry.o new file mode 100644 index 000000000..70396fb6f Binary files /dev/null and b/lab4/build/entry.o differ diff --git a/lab4/build/fdt_parse.o b/lab4/build/fdt_parse.o new file mode 100644 index 000000000..887a3f70d Binary files /dev/null and b/lab4/build/fdt_parse.o differ diff --git a/lab4/build/initrdfs.o b/lab4/build/initrdfs.o new file mode 100644 index 000000000..3256684e2 Binary files /dev/null and b/lab4/build/initrdfs.o differ diff --git a/lab4/build/irq_handler.o b/lab4/build/irq_handler.o new file mode 100644 index 000000000..57ee2f829 Binary files /dev/null and b/lab4/build/irq_handler.o differ diff --git a/lab4/build/kernel8.elf b/lab4/build/kernel8.elf new file mode 100755 index 000000000..979a853b5 Binary files /dev/null and b/lab4/build/kernel8.elf differ diff --git a/lab4/build/kernel8.img b/lab4/build/kernel8.img new file mode 100755 index 000000000..f317d0433 Binary files /dev/null and b/lab4/build/kernel8.img differ diff --git a/lab4/build/kernel_init.o b/lab4/build/kernel_init.o new file mode 100644 index 000000000..5ade373e9 Binary files /dev/null and b/lab4/build/kernel_init.o differ diff --git a/lab4/build/list.o b/lab4/build/list.o new file mode 100644 index 000000000..10fcdaee0 Binary files /dev/null and b/lab4/build/list.o differ diff --git a/lab4/build/mailbox.o b/lab4/build/mailbox.o new file mode 100644 index 000000000..288896b9f Binary files /dev/null and b/lab4/build/mailbox.o differ diff --git a/lab4/build/main.o b/lab4/build/main.o new file mode 100644 index 000000000..95659f059 Binary files /dev/null and b/lab4/build/main.o differ diff --git a/lab4/build/mini_uart.o b/lab4/build/mini_uart.o new file mode 100644 index 000000000..4b5dbfcf6 Binary files /dev/null and b/lab4/build/mini_uart.o differ diff --git a/lab4/build/mm.o b/lab4/build/mm.o new file mode 100644 index 000000000..3e84ac050 Binary files /dev/null and b/lab4/build/mm.o differ diff --git a/lab4/build/page_alloc.o b/lab4/build/page_alloc.o new file mode 100644 index 000000000..297353180 Binary files /dev/null and b/lab4/build/page_alloc.o differ diff --git a/lab4/build/print.o b/lab4/build/print.o new file mode 100644 index 000000000..e944f0a04 Binary files /dev/null and b/lab4/build/print.o differ diff --git a/lab4/build/reboot.o b/lab4/build/reboot.o new file mode 100644 index 000000000..b2e138124 Binary files /dev/null and b/lab4/build/reboot.o differ diff --git a/lab4/build/ring_buffer.o b/lab4/build/ring_buffer.o new file mode 100644 index 000000000..d83819fc8 Binary files /dev/null and b/lab4/build/ring_buffer.o differ diff --git a/lab4/build/shell.o b/lab4/build/shell.o new file mode 100644 index 000000000..e67fab55b Binary files /dev/null and b/lab4/build/shell.o differ diff --git a/lab4/build/simple_malloc.o b/lab4/build/simple_malloc.o new file mode 100644 index 000000000..30561a330 Binary files /dev/null and b/lab4/build/simple_malloc.o differ diff --git a/lab4/build/slab.o b/lab4/build/slab.o new file mode 100644 index 000000000..77e4d6750 Binary files /dev/null and b/lab4/build/slab.o differ diff --git a/lab4/build/start.o b/lab4/build/start.o new file mode 100644 index 000000000..9e6af6d11 Binary files /dev/null and b/lab4/build/start.o differ diff --git a/lab4/build/string.o b/lab4/build/string.o new file mode 100644 index 000000000..59c6f1bcd Binary files /dev/null and b/lab4/build/string.o differ diff --git a/lab4/build/syscall_table.o b/lab4/build/syscall_table.o new file mode 100644 index 000000000..ebee7f0ff Binary files /dev/null and b/lab4/build/syscall_table.o differ diff --git a/lab4/build/syscall_test.o b/lab4/build/syscall_test.o new file mode 100644 index 000000000..df2c55619 Binary files /dev/null and b/lab4/build/syscall_test.o differ diff --git a/lab4/build/timer.o b/lab4/build/timer.o new file mode 100644 index 000000000..433a61ccf Binary files /dev/null and b/lab4/build/timer.o differ diff --git a/lab4/build/uart_boot.o b/lab4/build/uart_boot.o new file mode 100644 index 000000000..4b0da3041 Binary files /dev/null and b/lab4/build/uart_boot.o differ diff --git a/lab4/debug.sh b/lab4/debug.sh new file mode 100755 index 000000000..81d573d80 --- /dev/null +++ b/lab4/debug.sh @@ -0,0 +1,3 @@ +#!/bin/sh +make CFLAGS=-DDEBUG >/dev/null +make qemu-run diff --git a/lab4/debug/Makefile b/lab4/debug/Makefile new file mode 100644 index 000000000..22ac23500 --- /dev/null +++ b/lab4/debug/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + debug.o + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab4/debug/debug.c b/lab4/debug/debug.c new file mode 100644 index 000000000..e990517b5 --- /dev/null +++ b/lab4/debug/debug.c @@ -0,0 +1,50 @@ +#include "debug/debug.h" + +extern int __bss_start, __bss_end; +extern int __text_start, __text_end; +extern int __rodata_start, __rodata_end; +extern int __data_start, __data_end; +extern int __heap_start; + +#ifdef DEBUG +int debug = 1; +#else +int debug = 0; +#endif + +void log_kernel_start(){ + uint64_t currentEL; + if(debug == 0) return; + printf("text_start=%p, text_end=%p, text_size=%u\r\n", \ + &__text_start, \ + &__text_end, \ + (uint64_t)&__text_end - (uint64_t)&__text_start + ); + + + printf("rodata_start=%p, rodata_end=%p, rodata_size=%u\r\n", \ + &__rodata_start, \ + &__rodata_end, \ + (uint64_t)&__rodata_end - (uint64_t)&__rodata_start + ); + + printf("data_start=%p, data_end=%p, data_size=%u\r\n", \ + &__data_start, \ + &__data_end, \ + (uint64_t)&__data_end - (uint64_t)&__data_start + ); + + printf("bss_start=%p, bss_end=%p, bss_size=%u\r\n", \ + &__bss_start, \ + &__bss_end, \ + (uint64_t)&__bss_end - (uint64_t)&__bss_start + ); + printf("heap_start=%p\r\n", &__heap_start); + + printf("current exception level: %u\r\n", get_currentEL()); + printf("SP_EL0: 0x%x\r\n", get_SP_ELx(0)); + printf("DAIF: 0x%x\r\n", get_DAIF()); + printf("SPSel: 0x%x\r\n", get_SPSel()); + printf("stack pointer: %p\r\n", ¤tEL); + +} diff --git a/lab4/fs/Makefile b/lab4/fs/Makefile new file mode 100644 index 000000000..15fbb2fa3 --- /dev/null +++ b/lab4/fs/Makefile @@ -0,0 +1,24 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + initrdfs.o +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab4/fs/initrdfs.c b/lab4/fs/initrdfs.c new file mode 100644 index 000000000..8c7c591f3 --- /dev/null +++ b/lab4/fs/initrdfs.c @@ -0,0 +1,81 @@ +#include "fs/initrdfs.h" + +static struct fentry * root; + +void initrdfs_init(void* addr){ + INFO("Initrd filesystem start address: %p", addr); + LOG("Enter initrdfs_int"); + LOG("initrd start at %p\n", addr); + LOG("initrd first 4 bytes: %x\n", *(uint32_t*)addr); + root = (struct fentry*)kmalloc(sizeof(struct fentry)); + struct cpio_iter iter; + char *fname = (char*)kmalloc(2); + strcpy(fname, "/"); + + memset(root, 0, sizeof(struct fentry)); + root->filename = fname; + root->namesize = 1; + root->mode = root->mode & FILE_TYPE_DIR; + + INIT_LIST_HEAD(&root->list); + + // Start parsing initrd in New ASCII Format at addr + LOG("Start parsing new ascii format's cpio"); + cpio_iter_init(&iter, addr); + do{ + struct fentry *f = (struct fentry*)kmalloc(sizeof(struct fentry)); + cpio_iter_parse(&iter, f); + LOG("FILE: %s", f->filename); + if(cpio_is_tailer(f)) break; + list_add(&f->list, &root->list); + }while(1); + LOG("Leave initrdfs_int"); +} +void* fdt_initrdfs_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(prop != NULL){ + if(strcmp(prop->name, "linux,initrd-start") == 0){ + uint64_t initrd_start = bswap32(*(uint32_t*)prop->value); + LOG("linux,initrd-start: %x", (uint32_t)initrd_start); + initrdfs_init((void*)initrd_start); + } + } +} + +void initrdfs_ls(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + printf("%s\r\n", f->filename); + } +} +void initrdfs_cat(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + printf("Filename : %s\r\n", f->filename); + printf("File size: %u\r\n", f->filesize); + aio_write_bytes(f->data, f->filesize); + printf("\r\n"); + } + } +} +void initrdfs_loadfile(char* name, uint8_t* addr){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + if(strcmp(name, f->filename) == 0){ + LOG("Load file %s to %p", name, addr); + memcpy(addr, f->data, f->filesize); + break; + } + } + } +} diff --git a/lab4/include/asm.h b/lab4/include/asm.h new file mode 100644 index 000000000..37dbc4cc7 --- /dev/null +++ b/lab4/include/asm.h @@ -0,0 +1,20 @@ +#ifndef _ASM_H_ +#define _ASM_H_ +extern uint32_t get_currentEL(); +extern uint64_t get_SP_ELx(uint32_t); +extern uint64_t get_DAIF(); +extern void set_DAIF(uint64_t); +extern uint64_t get_SPSel(); +extern uint64_t get_ESR_EL1(); +extern uint64_t get_SPSR_EL1(); +extern uint64_t get_ELR_EL1(); +extern uint64_t get_SP(); +extern uint64_t get_CNTP_CTL_EL0(); +extern void set_CNTP_CTL_EL0(uint64_t); +extern uint64_t get_CNTFRQ_EL0(); +extern void set_CNTP_TVAL_EL0(uint64_t); +extern uint64_t get_CNTPCT_EL0(); +extern void local_irq_enable(); +extern void local_irq_disable(); +#endif + diff --git a/lab4/include/debug/debug.h b/lab4/include/debug/debug.h new file mode 100644 index 000000000..098653069 --- /dev/null +++ b/lab4/include/debug/debug.h @@ -0,0 +1,18 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "lib/print.h" +#include "types.h" +#include "asm.h" + +#define DEBUG_KERNEL_START() log_kernel_start() +#define LOG(fmt, ...) \ + if(debug) \ + printf("[%s/%s:%d] " fmt "\r\n" , __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) + + + +extern void log_kernel_start(void); + +extern int debug; +#endif diff --git a/lab4/include/fs/initrdfs.h b/lab4/include/fs/initrdfs.h new file mode 100644 index 000000000..baa74fe6b --- /dev/null +++ b/lab4/include/fs/initrdfs.h @@ -0,0 +1,18 @@ +#ifndef _INITRDFS_H_ +#define _INITRDFS_H_ +#include "types.h" +#include "lib/cpio.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "mm/slab.h" +#include "lib/list.h" +#include "lib/string.h" +#include "debug/debug.h" +#include "peripherals/mini_uart.h" + +extern void initrdfs_init(void*); +extern void initrdfs_ls(); +extern void initrdfs_cat(); +extern void* fdt_initrdfs_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void initrdfs_loadfile(char* , uint8_t*); +#endif diff --git a/lab4/include/init/kernel_init.h b/lab4/include/init/kernel_init.h new file mode 100644 index 000000000..cdb4c5eb2 --- /dev/null +++ b/lab4/include/init/kernel_init.h @@ -0,0 +1,14 @@ +#ifndef _KERNEL_INIT_H +#define _KERNEL_INIT_H +#include "types.h" +#include "peripherals/mini_uart.h" +#include "fs/initrdfs.h" +#include "kernel/timer.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "mm/mm.h" +#include "asm.h" + +extern void kernel_init(void *); + +#endif diff --git a/lab4/include/kernel/irq_handler.h b/lab4/include/kernel/irq_handler.h new file mode 100644 index 000000000..9a2f57535 --- /dev/null +++ b/lab4/include/kernel/irq_handler.h @@ -0,0 +1,23 @@ +#ifndef _IRQ_HANDLER_H_ +#define _IRQ_HANDLER_H_ + +#include "types.h" +#include "peripherals/iomapping.h" +#include "peripherals/mini_uart.h" +#include "lib/print.h" +#include "lib/bitops.h" +#include "kernel/timer.h" +#include "debug/debug.h" +#include "asm.h" + +#define MAX_SOFTIRQ_TRY 5 + +enum {CORE0_TIMER = 0, MINI_UART_RX, MINI_UART_TX, END_OF_LIST}; +typedef void (*irq_funcptr)(void); + +struct softirq_status{ + uint16_t pending; // support 16 interrupt + uint8_t in_softirq; +}; +extern uint64_t irq_count[END_OF_LIST]; +#endif diff --git a/lab4/include/kernel/reboot.h b/lab4/include/kernel/reboot.h new file mode 100644 index 000000000..cc8e8730b --- /dev/null +++ b/lab4/include/kernel/reboot.h @@ -0,0 +1,16 @@ +#ifndef _REBOOT_H_ +#define _REBOOT_H_ + +#include "peripherals/iomapping.h" + +#define PM_WDOG_RESET 0000000000 +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +extern void reboot(int tick); + +#endif diff --git a/lab4/include/kernel/shell.h b/lab4/include/kernel/shell.h new file mode 100644 index 000000000..6510e6677 --- /dev/null +++ b/lab4/include/kernel/shell.h @@ -0,0 +1,17 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ +#include "types.h" +#include "lib/print.h" +#include "lib/string.h" +#include "lib/simple_malloc.h" +#include "peripherals/mailbox.h" +#include "kernel/reboot.h" +#include "fs/initrdfs.h" +#include "kernel/timer.h" +#include "kernel/irq_handler.h" +#include "mm/slab.h" + +void simple_shell(void); + +#define DELIM " \t\n\r" +#endif diff --git a/lab4/include/kernel/syscall.h b/lab4/include/kernel/syscall.h new file mode 100644 index 000000000..97f303301 --- /dev/null +++ b/lab4/include/kernel/syscall.h @@ -0,0 +1,5 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ +#include "types.h" +extern uint64_t sys_hello(uint64_t); +#endif diff --git a/lab4/include/kernel/syscall_table.h b/lab4/include/kernel/syscall_table.h new file mode 100644 index 000000000..50ab0047e --- /dev/null +++ b/lab4/include/kernel/syscall_table.h @@ -0,0 +1,6 @@ +#ifndef _SYSCALL_TABLE_H_ +#define _SYSCALL_TABLE_H_ + +#include "kernel/syscall.h" +extern void *syscall_table[]; +#endif diff --git a/lab4/include/kernel/timer.h b/lab4/include/kernel/timer.h new file mode 100644 index 000000000..5a1937f46 --- /dev/null +++ b/lab4/include/kernel/timer.h @@ -0,0 +1,31 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ +#include "types.h" +#include "lib/list.h" +#include "lib/simple_malloc.h" +#include "peripherals/iomapping.h" +#include "debug/debug.h" +#include "asm.h" + + +#define HZ 100 + +typedef void (*timer_callback)(void*); + +typedef struct{ + uint64_t ticks; + timer_callback callback; + void *data; + struct list_head list; +}timer_t; + +extern void core_timer_irq_handler(); +extern void init_core_timer(); +extern uint64_t get_jiffies(); +extern void enable_core_timer_irq(); +extern void disable_core_timer_irq(); +extern void init_timer_list(); +extern void add_timer(timer_callback, uint8_t*, uint64_t); +extern void timer_softirq_callback(); + +#endif diff --git a/lab4/include/lib/bitops.h b/lab4/include/lib/bitops.h new file mode 100644 index 000000000..1a22a6136 --- /dev/null +++ b/lab4/include/lib/bitops.h @@ -0,0 +1,8 @@ +#ifndef _BITOPS_H_ +#define _BITOPS_H_ + +#include "types.h" +extern uint16_t ffs16(uint16_t); +extern uint64_t ffs64(uint64_t); + +#endif diff --git a/lab4/include/lib/cpio.h b/lab4/include/lib/cpio.h new file mode 100644 index 000000000..9e9eaf129 --- /dev/null +++ b/lab4/include/lib/cpio.h @@ -0,0 +1,66 @@ +#ifndef _CPIO_H_ +#define _CPIO_H_ + +#include "types.h" +#include "lib/list.h" +#include "lib/fdt_parse.h" +#include "lib/string.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "debug/debug.h" + +#define FILE_TYPE_MASK 0170000 +#define FILE_TYPE_SOCKET 0140000 +#define FILE_TYPE_SYMLINK 0120000 +#define FILE_TYPE_REGULAR 0100000 +#define FILE_TYPE_BLKDEV 0060000 +#define FILE_TYPE_DIR 0040000 +#define FILE_TYPE_CHRDEV 0020000 +#define FILE_TYPE_NAMED_PIPE 0010000 +#define FILE_SUID 0004000 +#define FILE_SGID 0002000 +#define FILE_STICKY 0001000 +#define FILE_PERMISSION_MASK 0000777 + +struct cpio_iter{ + uint8_t *cur; +}; +struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} __attribute((packed)); + +struct fentry { + uint32_t ino; + uint32_t mode; + uint32_t uid; + uint32_t gid; + uint32_t nlink; + uint32_t mtime; + uint32_t filesize; + uint32_t devmajor; + uint32_t devminor; + uint32_t rdevmajor; + uint32_t rdevminor; + uint32_t namesize; + uint32_t check; + char *filename; + uint8_t *data; + struct list_head list; +}; +void cpio_iter_parse(struct cpio_iter*, struct fentry*); +extern void cpio_iter_init(struct cpio_iter*, void*); +extern int cpio_is_tailer(struct fentry*); +#endif diff --git a/lab4/include/lib/fdt_parse.h b/lab4/include/lib/fdt_parse.h new file mode 100644 index 000000000..d01497474 --- /dev/null +++ b/lab4/include/lib/fdt_parse.h @@ -0,0 +1,47 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "lib/string.h" + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +typedef void (*fdt_rsvmap_callback)(uint64_t, uint64_t); +extern void fdt_parse_header(uint8_t*, fdt_header*); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parse_rsvmap(uint8_t*, fdt_rsvmap_callback); +#endif diff --git a/lab4/include/lib/list.h b/lab4/include/lib/list.h new file mode 100644 index 000000000..4987bc697 --- /dev/null +++ b/lab4/include/lib/list.h @@ -0,0 +1,23 @@ +#ifndef _LIST_H_ +#define _LIST_H_ + +#include "types.h" +struct list_head{ + struct list_head* next, *prev; +}__attribute__((packed)); + +#define LIST_HEAD(head) struct list_head head = { &(head), &(head) } +#define list_entry(node, type, member) container_of(node, type, member) +#define list_first_entry(head, type, member) list_entry((head)->next, type, member) +#define list_last_entry(head, type, member) list_entry((head)->prev, type, member) +#define list_for_each(node, head) \ + for(node = (head)->next ; node != (head) ; node = node->next) + +extern void INIT_LIST_HEAD(struct list_head*); +extern void list_add(struct list_head* node, struct list_head*); +extern void list_add_tail(struct list_head*, struct list_head*); +extern void list_del(struct list_head*); +extern int list_empty(struct list_head*); +extern int list_is_last(struct list_head*, struct list_head*); +extern int list_is_head(struct list_head*, struct list_head*); +#endif diff --git a/lab4/include/lib/print.h b/lab4/include/lib/print.h new file mode 100644 index 000000000..d0cab3e83 --- /dev/null +++ b/lab4/include/lib/print.h @@ -0,0 +1,17 @@ +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#include "types.h" +#include "kernel/timer.h" +#include "lib/string.h" +#include "peripherals/mini_uart.h" +#include + +int32_t printf(char *, ...); +int32_t putchar(uint8_t); +int32_t getchar(); + +#define INFO(fmt, ...) \ + printf("%l: [%s] " fmt "\r\n" , (int64_t)get_jiffies(), __FUNCTION__, ##__VA_ARGS__) + +#endif diff --git a/lab4/include/lib/ring_buffer.h b/lab4/include/lib/ring_buffer.h new file mode 100644 index 000000000..3f82d8ef4 --- /dev/null +++ b/lab4/include/lib/ring_buffer.h @@ -0,0 +1,25 @@ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ +#include "types.h" +#include "lib/simple_malloc.h" +#include "mm/slab.h" + +typedef struct{ + size_t size; + uint64_t head; + uint64_t tail; + uint8_t* buf; + size_t count; +}ring_buffer; + +extern ring_buffer* create_simple_ring_buf(size_t); + +extern ring_buffer* create_ring_buf(size_t); +extern void free_ring_buf(ring_buffer*); +extern size_t ring_buf_write(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read(ring_buffer*, uint8_t*, size_t); +extern uint8_t ring_buf_is_full(ring_buffer*); +extern uint8_t ring_buf_is_empty(ring_buffer*); +extern size_t ring_buf_get_len(ring_buffer*); + +#endif diff --git a/lab4/include/lib/simple_malloc.h b/lab4/include/lib/simple_malloc.h new file mode 100644 index 000000000..8f8c0f4dc --- /dev/null +++ b/lab4/include/lib/simple_malloc.h @@ -0,0 +1,15 @@ +#ifndef _SIMPLE_MALLOC_H_ +#define _SIMPLE_MALLOC_H_ + +#include "types.h" +#include "debug/debug.h" + +#define req2size(req) ALIGN_UP(req, 16) + +struct malloc_state{ + uint8_t* last_remainder; +}; + +extern void* simple_malloc(size_t); +extern void* simple_malloc_get_remainder(); +#endif diff --git a/lab4/include/lib/string.h b/lab4/include/lib/string.h new file mode 100644 index 000000000..4a6a30cd7 --- /dev/null +++ b/lab4/include/lib/string.h @@ -0,0 +1,19 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#include "types.h" + +extern char * itoa(int32_t, char*, uint32_t); +extern char * utoa(uint32_t, char*, uint32_t); +extern char * ltoa(int64_t, char*, uint32_t); +extern char * ultoa(uint64_t, char*, uint32_t); +extern int32_t strcmp(char*, char*); +extern char *strcpy(char *, const char *); +extern size_t strlen(const char*); +extern void* memcpy(void*, const void*, size_t); +extern void* memset(void*, int, size_t); +extern int32_t memcmp(void*, const void*, size_t); +extern uint8_t hex2dec(char); +extern char* strtok(char*,const char*); +extern uint64_t atoul(const char*); +#endif diff --git a/lab4/include/mm/mm.h b/lab4/include/mm/mm.h new file mode 100644 index 000000000..52532cce5 --- /dev/null +++ b/lab4/include/mm/mm.h @@ -0,0 +1,35 @@ +#ifndef _MM_H_ +#define _MM_H_ + +#include "types.h" +#include "lib/fdt_parse.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "lib/list.h" +#include "lib/string.h" +#include "mm/page_alloc.h" +#include "mm/slab.h" + + +struct mem_block{ + uint64_t start; + uint64_t end; + struct list_head list; +}; + +struct mem_node{ + uint64_t start; + uint64_t end; + char *name; + struct list_head list; +}; + +extern struct list_head mem_rsvmap; +extern struct list_head mem_unusedmap; +extern struct mem_node memory_node; +extern struct page *mem_map; + +extern void mm_init(void *); + + +#endif diff --git a/lab4/include/mm/page_alloc.h b/lab4/include/mm/page_alloc.h new file mode 100644 index 000000000..20f92a7fd --- /dev/null +++ b/lab4/include/mm/page_alloc.h @@ -0,0 +1,58 @@ +#ifndef _PAGE_ALLOC_H_ +#define _PAGE_ALLOC_H_ + +#include "types.h" +#include "lib/list.h" +#include "lib/print.h" +#include "lib/bitops.h" +#include "mm/mm.h" + +#define BUDDY_GROUP_MEMBER 0x80000000 +#define BUDDY_ALLOCATED 0x40000000 +#define BUDDY_MAX_ORDER 7 + +#define PAGE_TYPE_RESERVED 1 +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1ul << PAGE_SHIFT) + +#define BUDDY_IS_ALLOCATED(x) (((struct page*)x)->order & BUDDY_ALLOCATED) +#define BUDDY_IS_MEMBER(x) (((struct page*)x)->order & BUDDY_GROUP_MEMBER) +#define BUDDY_IS_FREED(x) (!BUDDY_IS_ALLOCATED(x)) +#define PAGE_IS_RESERVED(x) (((struct page*)x)->type & PAGE_TYPE_RESERVED) +#define _buddy_ffs(x) ((x) == 0 ? BUDDY_MAX_ORDER : ffs64(x)) +#define addr_to_pfn(addr) ((uint64_t)(addr) >> PAGE_SHIFT) +#define pfn_to_addr(n) ((void*)(n << PAGE_SHIFT)) +#define page_to_pfn(x) ((uint64_t)((struct page*)x - mem_map)) +#define pfn_to_page(x) ((struct page*)&mem_map[x]) +#define find_buddy_pfn(pfn, order) (pfn ^ (1 << order)) +#define get_page_order(p) (p->order & 0xffff) +#define get_buddy_leader(p) (p->buddy_leader) + +struct page{ +// if (order & BUDDY_MEMBER), then it is freed and it is not a buddy leader +// if (order & BUDDY_ALLOCATED), then it is allocated + void* buddy_leader; + uint32_t order; + uint32_t type; + struct list_head list; +}; + +struct free_list{ + size_t count; + struct list_head list; +}; + +struct buddy_system{ + struct free_list free_lists[BUDDY_MAX_ORDER]; +}; + +extern void buddy_init(); +extern void* alloc_page(); +extern void* alloc_pages(uint32_t); +extern void free_pages(void*, uint32_t); +extern void free_page(void*); +extern void debug_buddy(); +extern void print_buddy_statistics(); + +#endif + diff --git a/lab4/include/mm/slab.h b/lab4/include/mm/slab.h new file mode 100644 index 000000000..bea128048 --- /dev/null +++ b/lab4/include/mm/slab.h @@ -0,0 +1,37 @@ +#ifndef _SLAB_H_ +#define _SLAB_H_ + +#include "mm/mm.h" +#include "mm/page_alloc.h" +#include "lib/list.h" +#include "lib/string.h" +#include "debug/debug.h" + +struct slab{ + size_t size; // object size + void* s_mem; // pointe to the first object + size_t inuse; + struct list_head free_list; // free list + struct list_head list; // next slab +}; + +#define SLAB_ALIGNMENT (ALIGN_UP(sizeof(struct list_head), 0x20)) +#define SLAB_SIZE (ALIGN_UP(sizeof(struct slab), SLAB_ALIGNMENT)) +#define SLAB_MAX_OBJECT_SIZE (PAGE_SIZE * (1 << (BUDDY_MAX_ORDER - 1)) - SLAB_SIZE) + +#define KMEM_MIN_SIZE SLAB_ALIGNMENT +#define KMEM_ALIGNMENT SLAB_ALIGNMENT +#define KMEM_CACHE_NUM (SLAB_MAX_OBJECT_SIZE / KMEM_ALIGNMENT + 1) + +extern struct slab* slab_create(size_t); +extern void slab_destroy(struct slab*); +extern void *slab_alloc(struct slab*); +extern void slab_free(struct slab* , void*); + +extern void* kmalloc(size_t); +extern void kfree(void*); +extern void kmalloc_init(); + +extern void debug_kmalloc(); +extern void debug_slab(); +#endif diff --git a/lab4/include/peripherals/iomapping.h b/lab4/include/peripherals/iomapping.h new file mode 100644 index 000000000..e06ff517b --- /dev/null +++ b/lab4/include/peripherals/iomapping.h @@ -0,0 +1,94 @@ +#ifndef _IOMAPPING_H_ +#define _IOMAPPING_H_ + + +/* Physical addresses range from 0x3F000000 to 0x3FFFFFFF for peripherals */ +#define IO_BASE 0x3F000000 + +/* Register's offset of GPIO */ +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL1 (IO_BASE + 0x200004) +#define GPFSEL2 (IO_BASE + 0x200008) +#define GPFSEL3 (IO_BASE + 0x20000C) +#define GPFSEL4 (IO_BASE + 0x200010) +#define GPFSEL5 (IO_BASE + 0x200014) +#define GPSET0 (IO_BASE + 0x20001C) +#define GPSET1 (IO_BASE + 0x200020) +#define GPCLR0 (IO_BASE + 0x200028) +#define GPCLR1 (IO_BASE + 0x20002C) +#define GPLEV0 (IO_BASE + 0x200034) +#define GPLEV1 (IO_BASE + 0x200038) +#define GPEDS0 (IO_BASE + 0x200040) +#define GPEDS1 (IO_BASE + 0x200044) +#define GPREN0 (IO_BASE + 0x20004C) +#define GPREN1 (IO_BASE + 0x200050) +#define GPFEN0 (IO_BASE + 0x200058) +#define GPFEN1 (IO_BASE + 0x20005C) +#define GPHEN0 (IO_BASE + 0x200064) +#define GPHEN1 (IO_BASE + 0x200068) +#define GPLEN0 (IO_BASE + 0x200070) +#define GPLEN1 (IO_BASE + 0x200074) +#define GPAREN0 (IO_BASE + 0x20007C) +#define GPAREN1 (IO_BASE + 0x200080) +#define GPAFEN0 (IO_BASE + 0x200088) +#define GPAFEN1 (IO_BASE + 0x20008C) +#define GPPUD (IO_BASE + 0x200094) +#define GPPUDCLK0 (IO_BASE + 0x200098) +#define GPPUDCLK1 (IO_BASE + 0x20009C) + + +/* Register's offset of UART and SPI */ +#define AUX_IRQ (IO_BASE + 0x215000) +#define AUX_ENABLES (IO_BASE + 0x215004) +#define AUX_MU_IO_REG (IO_BASE + 0x215040) +#define AUX_MU_IER_REG (IO_BASE + 0x215044) +#define AUX_MU_IIR_REG (IO_BASE + 0x215048) +#define AUX_MU_LCR_REG (IO_BASE + 0x21504C) +#define AUX_MU_MCR_REG (IO_BASE + 0x215050) +#define AUX_MU_LSR_REG (IO_BASE + 0x215054) +#define AUX_MU_MSR_REG (IO_BASE + 0x215058) +#define AUX_MU_SCRATCH (IO_BASE + 0x21505C) +#define AUX_MU_CNTL_REG (IO_BASE + 0x215060) +#define AUX_MU_STAT_REG (IO_BASE + 0x215064) +#define AUX_MU_BAUD_REG (IO_BASE + 0x215068) +#define AUX_SPI0_CNTL0_REG (IO_BASE + 0x215080) +#define AUX_SPI0_CNTL1_REG (IO_BASE + 0x215084) +#define AUX_SPI0_STAT_REG (IO_BASE + 0x215088) +#define AUX_SPI0_IO_REG (IO_BASE + 0x215090) +#define AUX_SPI0_PEEK_REG (IO_BASE + 0x215094) +#define AUX_SPI1_CNTL0_REG (IO_BASE + 0x2150C0) +#define AUX_SPI1_CNTL1_REG (IO_BASE + 0x2150C4) +#define AUX_SPI1_STAT_REG (IO_BASE + 0x2150C8) +#define AUX_SPI1_IO_REG (IO_BASE + 0x2150D0) +#define AUX_SPI1_PEEK_REG (IO_BASE + 0x2150D4) + +// mailbox register base address +#define MBOX_REG (IO_BASE + 0xB880) + +// interrupt +#define IRQ_BASIC_PENDING (IO_BASE + 0xB200) +#define IRQ_PENDING_1 (IO_BASE + 0xB204) +#define IRQ_PENDING_2 (IO_BASE + 0xB208) +#define CORE0_INTERRUPT_SOURCE (IO_BASE + 0x1000060) +#define ENABLE_IRQS_1 (IO_BASE + 0xB210) + + +// timer +#define CORE0_TIMER_IRQ_CTRL (IO_BASE + 0x1000040) + + +// watch dog +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_RSTC (IO_BASE + 0x10001c) +#define PM_WDOG (IO_BASE + 0x100024) + +#define IO_MMIO_write32(addr, val) *(uint32_t*)addr = val +#define IO_MMIO_read32(addr) *(uint32_t*)addr +#define IO_MMIO_write64(addr, val) *(uint64_t*)addr = val +#define IO_MMIO_read64(addr) *(uint64_t*)addr + + + +#endif + diff --git a/lab4/include/peripherals/mailbox.h b/lab4/include/peripherals/mailbox.h new file mode 100644 index 000000000..0d264f4de --- /dev/null +++ b/lab4/include/peripherals/mailbox.h @@ -0,0 +1,175 @@ +#ifndef _MAILBOX_H_ +#define _MAILBOX_H_ + +#include "types.h" +#include "lib/string.h" +#include "debug/debug.h" +#include "peripherals/iomapping.h" + +#define MBOX_CHANNEL_POWER 0 +#define MBOX_CHANNEL_FRAME_BUF 1 +#define MBOX_CHANNEL_VIRTUAL_UART 2 +#define MBOX_CHANNEL_VCHIQ 3 +#define MBOX_CHANNEL_LEDS 4 +#define MBOX_CHANNEL_BUTTONS 5 +#define MBOX_CHANNEL_TOUCH_SCREEN 6 +#define MBOX_CHANNEL_UNKOWN 7 +#define MBOX_CHANNEL_PROPERTY_TAGS 8 + +enum MBOX_PROPERTY_STATUS { + MBOX_STATUS_REQUEST = 0, + MBOX_STATUS_SUCCESS = 0x80000000, + MBOX_STATUS_ERROR = 0x80000001, +}; + +enum MBOX_PROPERTY_TAG{ + MBOX_PROPERTY_END = 0, + MBOX_GET_FIRMWARE_REVISION = 0x00000001, + + MBOX_SET_CURSOR_INFO = 0x00008010, + MBOX_SET_CURSOR_STATE = 0x00008011, + + MBOX_GET_BOARD_MODEL = 0x00010001, + MBOX_GET_BOARD_REVISION = 0x00010002, + MBOX_GET_BOARD_MAC_ADDRESS = 0x00010003, + MBOX_GET_BOARD_SERIAL = 0x00010004, + MBOX_GET_ARM_MEMORY = 0x00010005, + MBOX_GET_VC_MEMORY = 0x00010006, + MBOX_GET_CLOCKS = 0x00010007, + MBOX_GET_POWER_STATE = 0x00020001, + MBOX_GET_TIMING = 0x00020002, + MBOX_SET_POWER_STATE = 0x00028001, + MBOX_GET_CLOCK_STATE = 0x00030001, + MBOX_GET_CLOCK_RATE = 0x00030002, + MBOX_GET_VOLTAGE = 0x00030003, + MBOX_GET_MAX_CLOCK_RATE = 0x00030004, + MBOX_GET_MAX_VOLTAGE = 0x00030005, + MBOX_GET_TEMPERATURE = 0x00030006, + MBOX_GET_MIN_CLOCK_RATE = 0x00030007, + MBOX_GET_MIN_VOLTAGE = 0x00030008, + MBOX_GET_TURBO = 0x00030009, + MBOX_GET_MAX_TEMPERATURE = 0x0003000a, + MBOX_GET_STC = 0x0003000b, + MBOX_ALLOCATE_MEMORY = 0x0003000c, + MBOX_LOCK_MEMORY = 0x0003000d, + MBOX_UNLOCK_MEMORY = 0x0003000e, + MBOX_RELEASE_MEMORY = 0x0003000f, + MBOX_EXECUTE_CODE = 0x00030010, + MBOX_EXECUTE_QPU = 0x00030011, + MBOX_SET_ENABLE_QPU = 0x00030012, + MBOX_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, + MBOX_GET_EDID_BLOCK = 0x00030020, + MBOX_GET_CUSTOMER_OTP = 0x00030021, + MBOX_GET_DOMAIN_STATE = 0x00030030, + MBOX_SET_CLOCK_STATE = 0x00038001, + MBOX_SET_CLOCK_RATE = 0x00038002, + MBOX_SET_VOLTAGE = 0x00038003, + MBOX_SET_TURBO = 0x00038009, + MBOX_SET_CUSTOMER_OTP = 0x00038021, + MBOX_SET_DOMAIN_STATE = 0x00038030, + MBOX_GET_GPIO_STATE = 0x00030041, + MBOX_SET_GPIO_STATE = 0x00038041, + MBOX_SET_SDHOST_CLOCK = 0x00038042, + MBOX_GET_GPIO_CONFIG = 0x00030043, + MBOX_SET_GPIO_CONFIG = 0x00038043, + MBOX_GET_PERIPH_REG = 0x00030045, + MBOX_SET_PERIPH_REG = 0x00038045, + + + /* Dispmanx TAGS */ + MBOX_FRAMEBUFFER_ALLOCATE = 0x00040001, + MBOX_FRAMEBUFFER_BLANK = 0x00040002, + MBOX_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, + MBOX_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, + MBOX_FRAMEBUFFER_GET_DEPTH = 0x00040005, + MBOX_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006, + MBOX_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007, + MBOX_FRAMEBUFFER_GET_PITCH = 0x00040008, + MBOX_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, + MBOX_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, + MBOX_FRAMEBUFFER_GET_PALETTE = 0x0004000b, + MBOX_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, + MBOX_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010, + MBOX_FRAMEBUFFER_RELEASE = 0x00048001, + MBOX_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, + MBOX_FRAMEBUFFER_TEST_DEPTH = 0x00044005, + MBOX_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006, + MBOX_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, + MBOX_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, + MBOX_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, + MBOX_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, + MBOX_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, + MBOX_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, + MBOX_FRAMEBUFFER_SET_DEPTH = 0x00048005, + MBOX_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006, + MBOX_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007, + MBOX_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + MBOX_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + MBOX_FRAMEBUFFER_SET_PALETTE = 0x0004800b, + MBOX_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + MBOX_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, + MBOX_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + MBOX_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + + MBOX_VCHIQ_INIT = 0x00048010, + + MBOX_GET_COMMAND_LINE = 0x00050001, + MBOX_GET_DMA_CHANNELS = 0x00060001, +}; +/* + * Mailbox Read/Write Peek Sender Status Config + * 0 0x00 0x10 0x14 0x18 0x1c + * 1 0x20 0x30 0x34 0x38 0x3c + */ + +#define MBOX_READ_CHANNEL_MASK 15 +#define MBOX_WRITE_CHANNEL_MASK 15 +#define MBOX_WRITE_ADDR_MASK (~15) +#define MBOX_READ_ADDR_MASK (~15) +#define MBOX_STATUS_FULL_MASK 0x80000000 +#define MBOX_STATUS_EMPTY_MASK 0x40000000 +typedef struct{ + uint32_t read; + uint32_t unused[5]; + uint32_t status; + uint32_t config; + uint32_t write; +}__attribute__((packed)) MBox_register; + +/* 0 4 8 12 16 20 24 28 32 + +---------------------------------------------------------------+ +0x00 | Buffer Size | + +---------------------------------------------------------------+ +0x04 | Request/Response Code | + +---------------------------------------------------------------+ +0x08 | Tags | +... \\ \\ +0xXX | Tags | + +---------------------------------------------------------------+ +0xXX+4 | End Tag (0) | + +---------------------------------------------------------------+ +0xXX+8 | Padding | +... \\ \\ +0xXX+16| Padding | + +---------------------------------------------------------------+ +*/ +#define MBOX_TAG_REQUEST 0 +typedef struct{ + uint32_t id; + uint32_t value_size; + uint32_t code; + uint8_t values[0]; +}MBox_tag; + +typedef struct{ + uint32_t buf_size; + uint32_t code; + uint8_t buf[0]; +}MBox_buffer; + +extern void MBox_get_board_revision(uint32_t*); +extern void MBox_get_arm_memory(uint32_t*); + +#endif diff --git a/lab4/include/peripherals/mini_uart.h b/lab4/include/peripherals/mini_uart.h new file mode 100644 index 000000000..9cec1e688 --- /dev/null +++ b/lab4/include/peripherals/mini_uart.h @@ -0,0 +1,40 @@ +#ifndef _MINI_UART_H_ +#define _MINI_UART_H_ + +#include "types.h" +#include "asm.h" +#include "peripherals/iomapping.h" +#include "debug/debug.h" +#include "lib/print.h" +#include "lib/ring_buffer.h" + +#define SYSTEM_CLOCK_RATE (250000000) +#define BAUD_RATE 115200 +#define BAUD_RATE_REG (SYSTEM_CLOCK_RATE / (8 * BAUD_RATE) - 1) +#define TX 1 +#define RX 2 +extern void mini_uart_init(); +extern uint8_t mini_uart_read(void); +extern void mini_uart_write(uint8_t); +extern ssize_t write_bytes(uint8_t *, size_t); +extern void write_str(char *); +extern void write_hex(uint64_t); +extern void delay_cycles(uint64_t); +extern void disable_mini_uart_irq(uint32_t); +extern void enable_mini_uart_irq(uint32_t); +extern void mini_uart_irq_init(); +extern void mini_uart_irq_read(); +extern size_t mini_uart_get_rx_len(); +extern uint8_t mini_uart_aio_read(void); +extern void mini_uart_irq_write(); +extern size_t mini_uart_get_tx_len(); +extern void mini_uart_aio_write(uint8_t); +extern ssize_t aio_write_bytes(uint8_t *, size_t); +extern void enable_mini_uart_tx_irq(); +extern void enable_mini_uart_rx_irq(); +extern void disable_mini_uart_tx_irq(); +extern void disable_mini_uart_rx_irq(); +extern void mini_uart_tx_softirq_callback(); +extern void mini_uart_rx_softirq_callback(); + +#endif diff --git a/lab4/include/types.h b/lab4/include/types.h new file mode 100644 index 000000000..c565b425b --- /dev/null +++ b/lab4/include/types.h @@ -0,0 +1,45 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) (((uint64_t)(val) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_DOWN(val, align) ((uint64_t)(val) & ~((align) - 1)) + +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define min(x, y) ((x) < (y) ? (x) : (y)) + +#endif diff --git a/lab4/init/Makefile b/lab4/init/Makefile new file mode 100644 index 000000000..e5b218aa8 --- /dev/null +++ b/lab4/init/Makefile @@ -0,0 +1,24 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + kernel_init.o + +all: $(OBJECTS) + +%.o: %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab4/init/kernel_init.c b/lab4/init/kernel_init.c new file mode 100644 index 000000000..8184461ce --- /dev/null +++ b/lab4/init/kernel_init.c @@ -0,0 +1,14 @@ +#include "init/kernel_init.h" + +extern int __heap_start; +void kernel_init(void *dtb){ + init_core_timer(); + mini_uart_init(); + mini_uart_irq_init(); + + INFO("kernel start initialization..."); + mm_init(dtb); + fdt_parser(dtb, fdt_initrdfs_callback); + return; +} + diff --git a/lab4/initramfs.cpio b/lab4/initramfs.cpio new file mode 100644 index 000000000..98a9c8fae Binary files /dev/null and b/lab4/initramfs.cpio differ diff --git a/lab4/kernel/.gdb_history b/lab4/kernel/.gdb_history new file mode 100644 index 000000000..0e9b7b5ce --- /dev/null +++ b/lab4/kernel/.gdb_history @@ -0,0 +1,25 @@ +file ./../build/kernel8.elf +target remote:1234 +x/gx simple_shell +disassemble simple_shell +b* 0x0000000000081e1c +c +x/i 0x100000 +ni +x/i 0x100000 +b* 0x100008 +ni +quit +file ./../build/kernel8.elf +target remote:1234 +disassemble simple_shell +b* 0x0000000000081e1c +c +ni +x/i 0x1000000 +x/i 0x100000 +b*0x100008 +ni +ni +ni +quit diff --git a/lab4/kernel/Makefile b/lab4/kernel/Makefile new file mode 100644 index 000000000..809af1319 --- /dev/null +++ b/lab4/kernel/Makefile @@ -0,0 +1,36 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + shell.o \ + reboot.o \ + main.o \ + start.o \ + entry.o \ + syscall_test.o \ + syscall_table.o \ + timer.o \ + irq_handler.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab4/kernel/entry.S b/lab4/kernel/entry.S new file mode 100644 index 000000000..802939786 --- /dev/null +++ b/lab4/kernel/entry.S @@ -0,0 +1,123 @@ + .macro ventry label + .align 7 + b \label + .endm + + + .macro save_all + sub sp, sp, 17 * 16 + stp x0, x1, [sp ,16 * 0] + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + str x30, [sp, 16 * 15] + + mrs x24, spsr_el1 + mrs x25, elr_el1 + stp x24, x25, [sp, 16 * 16] + .endm + + .macro load_all + ldp x24, x25, [sp, 16 * 16] + msr spsr_el1, x24 + msr elr_el1, x25 + + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + ldr x30, [sp, 16 * 15] + add sp, sp, 17 * 16 + .endm + + +// exception vector table + +.align 11 +.global EL1_exception_vector_table +EL1_exception_vector_table: +// Exception from the current EL while using SP_EL0 + ventry invalid_handler // Synchronous EL1t + ventry invalid_handler // IRQ EL1t + ventry invalid_handler // FIQ EL1t + ventry invalid_handler // Error EL1t + +// Exception from the current EL while using SP_ELx + ventry el1_sync_handler // Synchronous EL1h + ventry el1_irq_handler // IRQ EL1h + ventry invalid_handler // FIQ EL1h + ventry invalid_handler // Error EL1h + +// Exception from a lower EL at least one lower EL is AArch64 + ventry el0_sync_handler // Synchronous 64-bit EL0 + ventry el0_irq_handler // IRQ 64-bit EL0 + ventry invalid_handler // FIQ 64-bit EL0 + ventry invalid_handler // Error 64-bit EL0 + +// Exception from a lower EL and all lower ELs are AArch32 + ventry invalid_handler // Synchronous 32-bit EL0 + ventry invalid_handler // IRQ 32-bit EL0 + ventry invalid_handler // FIQ 32-bit EL0 + ventry invalid_handler // Error 32-bit EL0 + + + +invalid_handler: +el1_sync_handler: + save_all + nop + load_all + eret + + +el1_irq_handler: +el0_irq_handler: + save_all + bl irq_handler + load_all + eret + +el0_sync_handler: + save_all + mrs x24, esr_el1 + lsr x24, x24, #26 + cmp x24, #0x15 + + b.eq svc_handler + b nothing + +svc_handler: + adr x24, syscall_table + ldr x24, [x24] + + blr x24 + + str x0, [sp] + load_all + eret + +nothing: + load_all + eret diff --git a/lab4/kernel/irq_handler.c b/lab4/kernel/irq_handler.c new file mode 100644 index 000000000..3433042a4 --- /dev/null +++ b/lab4/kernel/irq_handler.c @@ -0,0 +1,110 @@ +#include "kernel/irq_handler.h" + +struct softirq_status softirq_s = { + .pending = 0, + .in_softirq = 0 +}; + +irq_funcptr softirq_vec[END_OF_LIST] = { + timer_softirq_callback, + mini_uart_rx_softirq_callback, + mini_uart_tx_softirq_callback +}; +uint64_t irq_count[END_OF_LIST] = {0, 0, 0}; + +void enter_softirq(){ + softirq_s.in_softirq = 1; +} + +void exit_softirq(){ + softirq_s.in_softirq = 0; +} + +uint8_t in_softirq(){ + return softirq_s.in_softirq; +} + +uint8_t has_softirq_pending(){ + return softirq_s.pending ? 1 : 0; +} + +uint16_t get_softirq_pending(){ + return softirq_s.pending; +} + +void set_softirq_pending(uint16_t val){ + softirq_s.pending = val; +} + + +void add_softirq_task(uint32_t softirq_nr){ + softirq_s.pending |= (1 << softirq_nr); +} + +void do_softirq(){ + uint16_t try = 0; + uint16_t pending; + uint16_t softirq_bit; + irq_funcptr softirq_handler; + + while(try < MAX_SOFTIRQ_TRY){ + pending = get_softirq_pending(); + set_softirq_pending(0); + + local_irq_enable(); + while(pending){ + softirq_bit = ffs16(pending); + softirq_handler = softirq_vec[softirq_bit]; + softirq_handler(); + pending &= ~(1 << softirq_bit); + } + local_irq_disable(); + try++; + } +} + +void do_irq(uint32_t nr, irq_funcptr do_hardirq,irq_funcptr enable_device_irq , irq_funcptr disable_device_irq){ + disable_device_irq(); + irq_count[nr]++; + do_hardirq(); + add_softirq_task(nr); + + if(!in_softirq() && has_softirq_pending()){ + enter_softirq(); + do_softirq(); + exit_softirq(); + } + + enable_device_irq(); +} + +void irq_handler(){ + uint32_t irq_pending_1 = IO_MMIO_read32(IRQ_PENDING_1); + uint32_t core0_irq_source = IO_MMIO_read32(CORE0_INTERRUPT_SOURCE); + uint32_t auxirq, uart_irq_type; + if(core0_irq_source & 2){ + //core timer interrupt + do_irq(CORE0_TIMER, core_timer_irq_handler, enable_core_timer_irq, disable_core_timer_irq); + }else if(irq_pending_1 & (1 << 29)){ + auxirq = IO_MMIO_read32(AUX_IRQ); + if(auxirq & 1){ + uart_irq_type = (IO_MMIO_read32(AUX_MU_IIR_REG) >> 1) & (0b11); + if(uart_irq_type == RX){ + // Receiver holds valid byte + do_irq(MINI_UART_RX, mini_uart_irq_read, enable_mini_uart_rx_irq, disable_mini_uart_rx_irq); + }else if(uart_irq_type == TX){ + // Transmit holding register empty + do_irq(MINI_UART_TX, mini_uart_irq_write, enable_mini_uart_tx_irq, disable_mini_uart_tx_irq); + }else{ + LOG("UART interrupt"); + } + }else{ + LOG("Unkown AUX interrupt, DAIF: %x", get_DAIF()); + } + } + else{ +// LOG("Unkown interrupt, DAIF: %x", get_DAIF()); + } +} + + diff --git a/lab4/kernel/linker.ld b/lab4/kernel/linker.ld new file mode 100644 index 000000000..163f79777 --- /dev/null +++ b/lab4/kernel/linker.ld @@ -0,0 +1,45 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __kernel_image_start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __kernel_image_end = .; + __heap_start = .; + + __EL1_stack_size = 0x4000; + __EL1_stack = 0x80000; +} diff --git a/lab4/kernel/main.c b/lab4/kernel/main.c new file mode 100644 index 000000000..c38cd2970 --- /dev/null +++ b/lab4/kernel/main.c @@ -0,0 +1,13 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "init/kernel_init.h" +#include "debug/debug.h" +#include "kernel/shell.h" + +void kernel_main(void *dtb){ + kernel_init(dtb); + DEBUG_KERNEL_START(); + + simple_shell(); +} + diff --git a/lab4/kernel/reboot.c b/lab4/kernel/reboot.c new file mode 100644 index 000000000..2511cc06e --- /dev/null +++ b/lab4/kernel/reboot.c @@ -0,0 +1,14 @@ +#include "types.h" +#include "peripherals/iomapping.h" +#include "kernel/reboot.h" + +void reboot(int ticks){ + unsigned int pm_rstc,pm_wdog; + pm_rstc = IO_MMIO_read32(PM_RSTC); + + pm_wdog = PM_PASSWORD | (ticks & PM_WDOG_TIME_SET); + pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; + + IO_MMIO_write32(PM_RSTC, pm_rstc); + IO_MMIO_write32(PM_WDOG, pm_wdog); +} diff --git a/lab4/kernel/shell.c b/lab4/kernel/shell.c new file mode 100644 index 000000000..2a705accf --- /dev/null +++ b/lab4/kernel/shell.c @@ -0,0 +1,165 @@ +#include "kernel/shell.h" + +char *miku_ascii = "⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀\r\n⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁\r\n⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀\r\n⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀\r\n⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀\r\n⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀\r\n⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀\r\n⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀\r\n⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀\r\n⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀\r\n⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀"; +char buf[0x2000]; + +void print_irq_count(void){ + printf("irq_count: "); + for(uint32_t i = 0 ; i < END_OF_LIST ; i++){ + printf("%l ", irq_count[i]); + } + printf("\r\n"); +} + +void setTimeout_callback(void* data){ + uint64_t t = get_jiffies(); + printf("Elapsed time after booting: %l.%l\r\n", t / HZ, t % HZ); + print_irq_count(); + printf("Your message: %s\r\n",(char*) data); +} + + +void simple_shell(){ + unsigned int i; + char ch, *token; + printf(miku_ascii); + printf("\r\n\r\n"); + while(1){ + i = 0; + buf[0] = '\0'; + printf("# "); + // read command + while(1){ + ch = (char)getchar(); + if(ch == '\r'){ + printf("\r\n"); + buf[i] = '\0'; + break; + }else if(ch != '\n'){ + putchar(ch); + buf[i] = ch; + i++; + } + } + + token = strtok(buf, DELIM); + if(token == NULL) continue; + // match comman + if(strcmp(token, "help") == 0){ + printf("help : print this help menu\r\n" \ + "hello : print Hello World!\r\n" \ + "info : print hardware infomation\r\n" \ + "ls : list files\r\n" \ + "cat : cat files\r\n" \ + "laod : load user program\r\n" \ + "time : print time after booting\r\n" \ + "reboot : reboot the device\r\n" \ + "setTimeout : set a N seconds timer task\r\n" \ + " setTimeout \r\n" \ + "irq_count : list irq count\r\n" + "alloc_pages : get pages\r\n" \ + " alloc_pages \r\n" \ + "free_pages : free pages\r\n" \ + " free_pages \r\n" \ + "kmalloc : get an object\r\n" \ + " kmalloc \r\n" \ + "kfree : free an object\r\n" \ + " kfree \r\n" \ + + "page_info : get buddy system's statistics\r\n" \ + + ); + + }else if(strcmp(token, "hello") == 0){ + printf("Hello World!\r\n"); + }else if(strcmp(token, "info") == 0){ + uint32_t tmp[2]; + MBox_get_board_revision(tmp); + printf("Board revision: 0x%x\r\n", tmp[0]); + + MBox_get_arm_memory(tmp); + printf("Memory base: 0x%x\r\n", tmp[0]); + printf("Memory size: 0x%x\r\n", tmp[1]); + }else if(strcmp(token, "reboot") == 0){ + printf("Start rebooting...\r\n"); + reboot(100); + while(1); + }else if(strcmp(token, "ls") == 0){ + initrdfs_ls(); + }else if(strcmp(token, "cat") == 0){ + initrdfs_cat(); + }else if(strcmp(token, "load") == 0){ + initrdfs_loadfile("test.img",(uint8_t*) 0x100000); + asm volatile("mov x0, 0x0\n\t" + "msr spsr_el1, x0\n\t" + "mov x0, #0x100000\n\t" + "msr elr_el1, x0\n\t" + "eret\n\t" + ); + }else if(strcmp(token, "time") == 0){ + uint64_t j = get_jiffies(); + printf("Elapsed time after booting: %l.%l\r\n", j / HZ, j % HZ); + }else if(strcmp(token, "setTimeout") == 0){ + uint64_t j = 0, len = 0, timeout = 0; + char *data = NULL; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + len = strlen(token); + data = (char*)simple_malloc(len + 1); + strcpy(data, token); + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + timeout = atoul(token); + + j = get_jiffies(); + add_timer(setTimeout_callback, data, timeout * 1000); + printf("Elapsed time after booting: %l.%l\r\n", j / HZ, j % HZ); + print_irq_count(); + printf("Timer will trigger after %l seconds\r\n", timeout); + }else if(strcmp(token, "irq_count") == 0){ + print_irq_count(); + }else if(strcmp(token, "alloc_pages") == 0){ + uint32_t order; + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + order = atoul(token); + p = alloc_pages(order); + printf("Allocate pages at %l\r\n", p); + }else if(strcmp(token, "free_pages") == 0){ + void* p; + struct page* page; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + p = (void*)atoul(token); + page = pfn_to_page(addr_to_pfn(p)); + + free_pages(p, get_page_order(page)); + printf("Free pages\r\n"); + }else if(strcmp(token, "kmalloc") == 0){ + uint32_t size; + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + size = atoul(token); + p = kmalloc(size); + printf("Allocate an object at %l\r\n", p); + }else if(strcmp(token, "kfree") == 0){ + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + p = (void*)atoul(token); + + kfree(p); + printf("Free an object\r\n"); + }else if(strcmp(token, "page_info") == 0){ + print_buddy_statistics(); + } + } +} diff --git a/lab4/kernel/start.S b/lab4/kernel/start.S new file mode 100644 index 000000000..168336ea5 --- /dev/null +++ b/lab4/kernel/start.S @@ -0,0 +1,54 @@ +.section ".text.boot" +.global _start +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #0xff + + // cpu id > 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + +// cpu id == 0 +master_core: + adr x1, _dtb + str x0, [x1] +// initialize .bss section + ldr x1, =__bss_start + ldr x2, =__bss_end +bss_zero: + sub x3, x2, x1 + cbz x3, end + str xzr, [x1], #8 // store zero to [x1] and add 8 to x1 + b bss_zero + +end: +// modify vbar_el1 before changing exception level to 1 + adr x0, EL1_exception_vector_table + msr vbar_el1, x0 +// from el2 to el1 + bl from_el2_to_el1 + + adr x1, _dtb + ldr x0, [x1] +// jump to kernel_main + bl kernel_main + b proc_hang +from_el2_to_el1: + ldr x0, =__EL1_stack // Set el1 stack to __EL1_stack + msr sp_el1, x0 + + mov x0, (1 << 31) // Set hcr_el2.RW so EL1 uses aarch64 + msr hcr_el2, x0 + + mov x0, 0x5 // EL1h (SPSel = 1) + msr spsr_el2, x0 + msr elr_el2, lr + eret // return to EL1 + +.section ".data" +_dtb: .dword 0 + diff --git a/lab4/kernel/syscall_table.c b/lab4/kernel/syscall_table.c new file mode 100644 index 000000000..0b8582f1b --- /dev/null +++ b/lab4/kernel/syscall_table.c @@ -0,0 +1,6 @@ +#include "kernel/syscall_table.h" +void *syscall_table[] = { + sys_hello +}; + + diff --git a/lab4/kernel/syscall_test.c b/lab4/kernel/syscall_test.c new file mode 100644 index 000000000..8690295ca --- /dev/null +++ b/lab4/kernel/syscall_test.c @@ -0,0 +1,15 @@ +#include "types.h" +#include "debug/debug.h" +#include "asm.h" +#include "lib/print.h" +uint64_t sys_hello(uint64_t x0){ + LOG("Enter sys_hello"); + printf("CurrentEL: %x\r\n", get_currentEL()); + printf("DAIF: %x\r\n", get_DAIF()); + printf("SPSR_EL1: %p\r\n", (void*)get_SPSR_EL1()); + printf("ELR_EL1: %p\r\n", (void*)get_ELR_EL1()); + printf("ESR_EL1: %p\r\n", (void*)get_ESR_EL1()); + printf("SP : %p\r\n", (void*)get_SP()); + printf("\r\n"); + return x0; +} diff --git a/lab4/kernel/timer.c b/lab4/kernel/timer.c new file mode 100644 index 000000000..cc7539752 --- /dev/null +++ b/lab4/kernel/timer.c @@ -0,0 +1,82 @@ +#include "kernel/timer.h" + +static uint64_t jiffies = 0; +static struct list_head timer_list; + +/* + * We use core timer to update jiffies + */ +void enable_core_timer_irq(){ + IO_MMIO_write32(CORE0_TIMER_IRQ_CTRL, 2); +} +void disable_core_timer_irq(){ + IO_MMIO_write32(CORE0_TIMER_IRQ_CTRL, 0); +} + +void timer_softirq_callback(){ + struct list_head *head = &timer_list; + struct list_head *node; + timer_t* t; + + list_for_each(node, head){ + t = list_entry(node, timer_t, list); + t->ticks--; + if(t->ticks <= 0){ + list_del(node); + t->callback(t->data); + } + } +} + +void init_timer_list(void){ + INIT_LIST_HEAD(&timer_list); +} + +/** + * Timer with 10 microsecond resolution + * + * @param duration in microsecond + */ +void add_timer(timer_callback callback, uint8_t* data, uint64_t duration){ + if(duration == 0){ + callback(data); + return; + } + + timer_t* t = (timer_t*)simple_malloc(sizeof(timer_t)); + + t->ticks = duration / (1000 / HZ); + t->callback = callback; + t->data = data; + + disable_core_timer_irq(); + //critical section + list_add(&t->list, &timer_list); + enable_core_timer_irq(); +} + +void init_core_timer(){ + uint64_t freq; + + init_timer_list(); + set_CNTP_CTL_EL0(1); + freq = get_CNTFRQ_EL0(); + set_CNTP_TVAL_EL0(freq / HZ); + enable_core_timer_irq(); +} +void core_timer_irq_handler(){ + uint64_t freq; + + freq = get_CNTFRQ_EL0(); + set_CNTP_TVAL_EL0(freq / HZ); + + jiffies += 1; +} + +uint64_t inline get_jiffies(){ + return jiffies; +} + + + + diff --git a/lab4/lib/Makefile b/lab4/lib/Makefile new file mode 100644 index 000000000..328a22f1a --- /dev/null +++ b/lab4/lib/Makefile @@ -0,0 +1,36 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + print.o \ + string.o \ + list.o \ + cpio.o \ + simple_malloc.o \ + fdt_parse.o \ + asm.o \ + ring_buffer.o \ + bitops.o + + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab4/lib/asm.c b/lab4/lib/asm.c new file mode 100644 index 000000000..08c2a919a --- /dev/null +++ b/lab4/lib/asm.c @@ -0,0 +1,142 @@ +#include "types.h" +void local_irq_enable(){ + asm volatile("msr DAIFClr, 0xf"); +} + +void local_irq_disable(){ + asm volatile("msr DAIFSet, 0xf"); +} + +uint32_t get_currentEL(){ + uint64_t curEL = 0; + asm volatile("mrs %0, CurrentEL" + : "=&r" (curEL) + : + ); + return curEL >> 2; +} +uint64_t get_SP_ELx(uint32_t x){ + uint64_t sp = 0; + + switch(x){ + case 0: + asm volatile("mrs %0, SP_EL0" + : "=&r" (sp) + : + ); + break; + case 1: + asm volatile("mrs %0, SP_EL1" + : "=&r" (sp) + : + ); + break; + case 2: + asm volatile("mrs %0, SP_EL2" + : "=&r" (sp) + : + ); + break; + default: + break; + } + + + return sp; +} +uint64_t get_DAIF(){ + uint64_t daif = 0; + asm volatile("mrs %0, DAIF" + : "=&r" (daif) + : + ); + return daif >> 6; +} +void set_DAIF(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr daif, x0" + : + :[n] "r" (n) + ); +} + +uint64_t get_SPSel(){ + uint64_t spsel = 0; + asm volatile("mrs %0, spsel" + : "=&r" (spsel) + : + ); + return spsel; +} +uint64_t get_ESR_EL1(){ + uint64_t esr_el1 = 0; + asm volatile("mrs %0, esr_el1" + : "=&r" (esr_el1) + : + ); + return esr_el1; +} +uint64_t get_SPSR_EL1(){ + uint64_t spsr_el1 = 0; + asm volatile("mrs %0, spsr_el1" + : "=&r" (spsr_el1) + : + ); + return spsr_el1; +} +uint64_t get_ELR_EL1(){ + uint64_t elr_el1 = 0; + asm volatile("mrs %0, elr_el1" + : "=&r" (elr_el1) + : + ); + return elr_el1; +} +uint64_t get_SP(){ + uint64_t sp = 0; + asm volatile("mov %0, sp" + : "=&r" (sp) + : + ); + return sp; +} +uint64_t get_CNTP_CTL_EL0(){ + uint64_t cntp_ctl_el0 = 0; + asm volatile("mrs %0, cntp_ctl_el0" + : "=&r" (cntp_ctl_el0) + : + ); + return cntp_ctl_el0; +} +void set_CNTP_CTL_EL0(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr cntp_ctl_el0, x0" + : + :[n] "r" (n) + ); +} +uint64_t get_CNTFRQ_EL0(){ + uint64_t cntfrq_el0 = 0; + asm volatile("mrs %0, cntfrq_el0" + : "=&r" (cntfrq_el0) + : + ); + return cntfrq_el0; +} + +void set_CNTP_TVAL_EL0(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr cntp_tval_el0, x0" + : + :[n] "r" (n) + ); +} +uint64_t get_CNTPCT_EL0(){ + uint64_t cntpct_el0 = 0; + asm volatile("mrs %0, cntpct_el0" + : "=&r" (cntpct_el0) + : + ); + return cntpct_el0; +} + diff --git a/lab4/lib/bitops.c b/lab4/lib/bitops.c new file mode 100644 index 000000000..ad1080455 --- /dev/null +++ b/lab4/lib/bitops.c @@ -0,0 +1,55 @@ +#include "lib/bitops.h" + +uint16_t ffs16(uint16_t val){ +// val should not be zero! +// The behavior is undefined when val is zer! + uint16_t num = 0; + if((val & 0xff) == 0){ + num += 8; + val >>= 8; + } + if((val & 0xf) == 0){ + num += 4; + val >>= 4; + } + if((val & 0x3) == 0){ + num += 2; + val >>= 2; + } + if((val & 0x1) == 0) + num += 1; + + return num; +} + +uint64_t ffs64(uint64_t val){ +// val should not be zero! +// The behavior is undefined when val is zer! + uint64_t num = 0; + if((val & 0xffffffff) == 0){ + num += 32; + val >>= 32; + } + if((val & 0xffff) == 0){ + num += 16; + val >>= 16; + } + if((val & 0xff) == 0){ + num += 8; + val >>= 8; + } + if((val & 0xf) == 0){ + num += 4; + val >>= 4; + } + + if((val & 0x3) == 0){ + num += 2; + val >>= 2; + } + + if((val & 0x1) == 0) + num += 1; + + return num; +} diff --git a/lab4/lib/cpio.c b/lab4/lib/cpio.c new file mode 100644 index 000000000..4474ac83b --- /dev/null +++ b/lab4/lib/cpio.c @@ -0,0 +1,61 @@ +#include "lib/cpio.h" + +uint32_t cpio_hex2dec(const char *s){ + uint32_t ret = 0; + for(uint32_t i = 0 ; i < 8 ; i++){ + ret = ret << 4; + ret = ret + hex2dec(s[i]); + } + return ret; +} + +void cpio_iter_parse(struct cpio_iter* iter, struct fentry* f){ + LOG("Enter cpio_iter_parse"); + size_t count = 0; + struct cpio_newc_header* header = (struct cpio_newc_header* )iter->cur; + + if(!memcpy(header->c_magic, "070701", 6)){ + LOG("CPIO PARSE ERROR!!!!"); + return; + } + + f->ino = cpio_hex2dec(header->c_ino); + f->mode = cpio_hex2dec(header->c_mode); + f->uid = cpio_hex2dec(header->c_uid); + LOG("f->uid: %u", f->uid); + f->gid = cpio_hex2dec(header->c_gid); + f->nlink = cpio_hex2dec(header->c_nlink); + f->mtime = cpio_hex2dec(header->c_mtime); + f->filesize = cpio_hex2dec(header->c_filesize); + LOG("f->filesize: %u", f->filesize); + f->devmajor = cpio_hex2dec(header->c_devmajor); + f->devminor = cpio_hex2dec(header->c_devminor); + f->rdevmajor = cpio_hex2dec(header->c_rdevmajor); + f->rdevminor = cpio_hex2dec(header->c_rdevminor); + f->namesize = cpio_hex2dec(header->c_namesize); + LOG("f->namesize: %u", f->namesize); + f->check = cpio_hex2dec(header->c_check); + count = count + sizeof(struct cpio_newc_header); + + f->filename = (char*)simple_malloc(f->namesize); + memcpy(f->filename, (uint8_t* )header + count, f->namesize); + LOG("get f->filename"); + count = ALIGN_UP(count + f->namesize, 4); + if(f->filesize > 0){ + f->data = (uint8_t*)simple_malloc(f->filesize); + memcpy(f->data, (uint8_t* )header + count, f->filesize); + } + LOG("get f->data"); + count = ALIGN_UP(count + f->filesize, 4); + iter->cur = iter->cur + count; + LOG("count: %u, iter->cur: %p", count, iter->cur); + LOG("Leave cpio_iter_parse"); +} + +void cpio_iter_init(struct cpio_iter* iter, void* addr){ + iter->cur = addr; +} +int cpio_is_tailer(struct fentry* f){ + return (strcmp(f->filename, "TRAILER!!!") == 0); +} + diff --git a/lab4/lib/fdt_parse.c b/lab4/lib/fdt_parse.c new file mode 100644 index 000000000..579d28939 --- /dev/null +++ b/lab4/lib/fdt_parse.c @@ -0,0 +1,126 @@ +#include "lib/fdt_parse.h" + +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +static fdt_header header; +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = &header; + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) >> 2; + len += 2; +// printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + //printf("Parsing error!!\n"); + } + } +} +void fdt_parse_rsvmap(uint8_t* fdt, fdt_rsvmap_callback callback){ + uint64_t *mem_rsvmap; + uint64_t start, end; + uint64_t count = 0; + fdt_header * pheader = &header; + fdt_parse_header(fdt, pheader); + + mem_rsvmap = (uint64_t*)(fdt + pheader->off_mem_rsvmap); + do{ + start = bswap64(mem_rsvmap[count * 2]); + end = start + bswap64(mem_rsvmap[count * 2 + 1]); + if(end) + callback(start, end); + else + break; + count++; + }while(1); +} +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab4/lib/list.c b/lab4/lib/list.c new file mode 100644 index 000000000..caf123d3e --- /dev/null +++ b/lab4/lib/list.c @@ -0,0 +1,45 @@ +#include "lib/list.h" + +void INIT_LIST_HEAD(struct list_head* head){ + head->next = head; + head->prev = head; +} + +void list_add(struct list_head* node, struct list_head* head){ + struct list_head *next = head->next; + + next->prev = node; + head->next = node; + + node->next = next; + node->prev = head; +} + +void list_add_tail(struct list_head* node, struct list_head* head){ + struct list_head* tail = head->prev; + + tail->next = node; + head->prev = node; + + node->next = head; + node->prev = tail; +} + +void list_del(struct list_head* node){ + struct list_head* next = node->next; + struct list_head* prev = node->prev; + + next->prev = prev; + prev->next = next; +} +int list_empty(struct list_head* head){ + return (head->next == head); +} + +int list_is_last(struct list_head* node, struct list_head* head){ + return head->prev == node; +} + +int list_is_head(struct list_head* node, struct list_head* head){ + return head == node; +} diff --git a/lab4/lib/print.c b/lab4/lib/print.c new file mode 100644 index 000000000..19292e549 --- /dev/null +++ b/lab4/lib/print.c @@ -0,0 +1,111 @@ +#include "lib/print.h" + +int32_t aio_print(char* fmt, ...){ + +} +int32_t printf(char *fmt, ...){ + uint32_t uval; + int32_t val; + int64_t lval; + char str[64], ch; + char* p, *s; + void* addr; + volatile int32_t count = 0; + va_list ap; + + va_start(ap, fmt); + + while(*fmt){ + char c = *fmt++; + if(c == '%'){ + c = *fmt++; + switch(c){ + case 'u': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 10); + p = str; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + break; + case 'd': + val = va_arg(ap, int); + itoa(val, str, 10); + p = str; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + break; + case 'l': + lval = va_arg(ap, int64_t); + ltoa(lval, str, 10); + p = str; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + break; + case 'c': + ch = va_arg(ap, int); + mini_uart_aio_write(ch); + count++; + break; + case 'p': + addr = va_arg(ap, void*); + utoa((uint64_t)addr, str, 16); + + mini_uart_aio_write('0'); + mini_uart_aio_write('x'); + count += 2; + + p = str; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + break; + + break; + case 'x': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 16); + p = str; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + + break; + case 's': + s = va_arg(ap, char*); + p = s; + while(*p){ + mini_uart_aio_write(*p++); + count++; + } + break; + case '%': + mini_uart_aio_write('%'); + count++; + default: + mini_uart_aio_write('%'); + mini_uart_aio_write(c); + count += 2; + } + }else{ + mini_uart_aio_write(c); + count++; + } + } + va_end(ap); + return count; +} +int32_t putchar(uint8_t ch){ + mini_uart_aio_write(ch); + return ch; +} +int32_t getchar(){ + return mini_uart_aio_read(); +} diff --git a/lab4/lib/ring_buffer.c b/lab4/lib/ring_buffer.c new file mode 100644 index 000000000..fba0e78c2 --- /dev/null +++ b/lab4/lib/ring_buffer.c @@ -0,0 +1,63 @@ +#include "lib/ring_buffer.h" + +ring_buffer* create_simple_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)simple_malloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)simple_malloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + tmp->count = 0; + return tmp; +} + +// This function can only be used after initializing mm +ring_buffer* create_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)kmalloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)kmalloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + tmp->count = 0; + return tmp; +} + +void free_ring_buf(ring_buffer* rbuf){ + kfree(rbuf->buf); + kfree(rbuf); +} + +uint8_t ring_buf_is_empty(ring_buffer* rbuf){ + if(rbuf->head == rbuf->tail) return 1; + return 0; +} +uint8_t ring_buf_is_full(ring_buffer* rbuf){ + if((rbuf->tail + 1) % (rbuf->size + 1) == rbuf->head) return 1; + return 0; +} +size_t ring_buf_write(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count += count; + return count; +} +size_t ring_buf_read(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count -= count; + return count; +} +size_t ring_buf_get_len(ring_buffer* rbuf){ + return rbuf->count; +} diff --git a/lab4/lib/simple_malloc.c b/lab4/lib/simple_malloc.c new file mode 100644 index 000000000..f7d7188fa --- /dev/null +++ b/lab4/lib/simple_malloc.c @@ -0,0 +1,17 @@ +#include "lib/simple_malloc.h" + +extern int __heap_start; +static struct malloc_state mstate = { + .last_remainder = (uint8_t*)&__heap_start +}; + + +void* simple_malloc(size_t size){ + void* chunk = mstate.last_remainder; + size_t nb = req2size(size); + mstate.last_remainder = mstate.last_remainder + nb; + return chunk; +} +void* simple_malloc_get_remainder(){ + return mstate.last_remainder; +} diff --git a/lab4/lib/string.c b/lab4/lib/string.c new file mode 100644 index 000000000..3ab9d9ce6 --- /dev/null +++ b/lab4/lib/string.c @@ -0,0 +1,260 @@ +#include "lib/string.h" +#include "types.h" +char *int_table = "0123456789"; +char *hex_table = "0123456789abcdef"; +char * itoa(int32_t value, char* str, uint32_t base){ + char buf[32]; + uint32_t val; + volatile int i = 0, j = 0; + + switch(base){ + case 16: + val = (uint32_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} + +char * utoa(uint32_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint32_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} +char * ltoa(int64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val; + + switch(base){ + case 16: + val = (uint64_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +char * ultoa(uint64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +uint64_t atoul(const char* str){ + uint64_t val = 0; + const char* ps = str; + while(*ps){ + val *= 10; + val += (*ps - '0'); + ps++; + } + return val; +} +int32_t strcmp(char* str1, char* str2){ + do{ + if(*str1 > *str2) return 1; + else if(*str1 < *str2) return -1; + str1++;str2++; + }while(*str1 != '\0' || *str2 != '\0'); + return 0; +} +size_t strlen(const char* s){ + size_t i = 0; + while(s[i++]); + i--; + return i; +} +// Do not maninpulate data by using (uint64*) or it may sometimes trigger alignment issue +// Manipulating data by using (uint8*) is best choice in this homework +void* memcpy(void* dst, const void* src, size_t n){ + const uint8_t* ps = src; + uint8_t *pd = dst; + size_t i; + for(i = 0 ; i < n ; i++) pd[i] = ps[i]; + return dst; +} +char *strcpy(char *dest, const char *src){ + memcpy(dest, src, strlen(src) + 1); +} +void* memset(void* s, int c, size_t n){ + uint8_t* ps = s; + for(size_t i = 0 ; i < n ; i++) ps[i] = c; + return s; +} + +int32_t memcmp(void* m1, const void* m2, size_t n){ + size_t i = 0; + char *s1 = m1; + const char* s2 = m2; + while(i < n){ + if(s1[i] > s2[i]) return 1; + else if(s1[i] < s2[i]) return -1; + i++; + } + return 0; +} + +uint8_t hex2dec(char hex){ + if('0' <= hex && hex <= '9'){ + return (uint8_t)hex - (uint8_t)'0'; + }else if('a' <= hex && hex <= 'f'){ + return (uint8_t)hex - (uint8_t)'a' + 10; + }else{ + return (uint8_t)hex - (uint8_t)'A' + 10; + } +} +uint8_t _is_delim(char c,const char* delim){ + uint32_t i = 0; + while(delim[i]){ + if(c == delim[i++]) return 1; + } + return 0; +} +char* _next_token(char* s,const char* delim){ + char* pos = s; + + do{ + if(*pos == '\0'){ + return NULL; + }else if(_is_delim(*pos, delim)){ + *pos = '\0'; + return pos + 1; + } + pos++; + }while(1); +} +char* _skip_delim(char* s,const char* delim){ + char* pos = s; + while(*pos != '\0' && _is_delim(*pos, delim)) pos++; + return pos; +} +char* strtok(char* s,const char* delim){ + static char *pos = NULL; + char *tmp_pos = NULL; + if(s == NULL){ + if(pos == NULL || *pos =='\0') return NULL; + + tmp_pos = pos = _skip_delim(pos, delim); + if(*pos != '\0'){ + pos = _next_token(pos, delim); + }else{ + pos = tmp_pos = NULL; + } + }else{ + if(*s == '\0') return NULL; + + pos = s; + tmp_pos = pos = _skip_delim(pos, delim); + if(*pos != '\0'){ + pos = _next_token(pos, delim); + }else{ + pos = tmp_pos = NULL; + } + } + return tmp_pos; +} diff --git a/lab4/mm/Makefile b/lab4/mm/Makefile new file mode 100644 index 000000000..c115b35a7 --- /dev/null +++ b/lab4/mm/Makefile @@ -0,0 +1,27 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + page_alloc.o \ + slab.o \ + mm.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab4/mm/mm.c b/lab4/mm/mm.c new file mode 100644 index 000000000..15f09504a --- /dev/null +++ b/lab4/mm/mm.c @@ -0,0 +1,201 @@ +#include "mm/mm.h" + +extern int __heap_start; +extern int __kernel_image_start; +extern int __kernel_image_end; +extern int __kernel_image_end; +extern int __EL1_stack_size; +extern int __EL1_stack; + +struct list_head mem_rsvmap; +struct list_head mem_unusedmap; +struct mem_node memory_node; +struct page *mem_map; + +void reserve_memory(uint64_t start, uint64_t end){ + struct list_head *node; + struct list_head *head; + struct mem_block *mb = simple_malloc(sizeof(struct mem_block)); + struct mem_block *tmp_mb; + + start = ALIGN_DOWN(start, PAGE_SIZE); + end = ALIGN_UP(end, PAGE_SIZE); + mb->start = start; + mb->end = end; + list_for_each(node, &mem_rsvmap){ + tmp_mb = list_entry(node, struct mem_block, list); + if(tmp_mb->start > start){ + head = node->prev; + list_add(&mb->list, head); + break; + } + } + + if(list_is_head(node, &mem_rsvmap)){ + list_add(&mb->list, node->prev); + } +} + +size_t get_reserved_size(){ + uint64_t start, end; + struct list_head* node; + struct mem_block* mb; + size_t size = 0; + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + start = mb->start; + end = mb->end; + size += (end - start); + } + return size; +} + +size_t get_unused_size(){ + uint64_t start, end; + struct list_head* node; + struct mem_block* mb; + size_t size = 0; + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + start = mb->start; + end = mb->end; + size += (end - start); + LOG("unused map: start: %p, end: %p", start, end); + } + return size; +} + +uint64_t _reserve_dtb(void *dtb){ + fdt_header header; + fdt_header *pheader = &header; + uint64_t start, end; + size_t size = 0; + + fdt_parse_header((uint8_t*)dtb, pheader); + size = ALIGN_UP(pheader->totalsize, PAGE_SIZE); + + start = (uint64_t)dtb; + end = start + size; + reserve_memory(start, end); +} + +void* _reserve_cpio(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + static uint64_t start, end; + static uint8_t found_start = 0, found_end = 0; + if(prop != NULL){ + if(strcmp(prop->name, "linux,initrd-start") == 0){ + start = bswap32(*(uint32_t*)prop->value); + found_start = 1; + } + if(strcmp(prop->name, "linux,initrd-end") == 0){ + end = bswap32(*(uint32_t*)prop->value); + found_end = 1; + } + if(found_start && found_end){ + found_start = found_end = 0; + reserve_memory(start, end); + } + } +} + +void _create_memory_rsvmap(void *dtb){ + uint64_t start, end; + // reseved memory in dtb + fdt_parse_rsvmap((uint8_t*)dtb, reserve_memory); + + // reverse memory for kernel image + reserve_memory((uint64_t)&__kernel_image_start, (uint64_t)&__kernel_image_end); + + // reserve memory for stack + reserve_memory((uint64_t)&__EL1_stack - (uint64_t)&__EL1_stack_size, (uint64_t)&__EL1_stack); + + // reserve memory for device tree + _reserve_dtb(dtb); + + // reserve memory for cpio + fdt_parser(dtb, _reserve_cpio); + + // Create struct page table for mapping every physical frame to it + mem_map = simple_malloc(sizeof(struct page) * (memory_node.end >> PAGE_SHIFT)); + + // reserve memory for simple memory allocator + start = (uint64_t)&__heap_start; + end = ALIGN_UP((uint64_t)simple_malloc_get_remainder(), PAGE_SIZE) + 8 * PAGE_SIZE; + reserve_memory(start, end); + +} + +void _create_memory_unusedmap(){ + uint64_t unused_start = 0; + struct list_head *node; + struct mem_block *mb; + struct mem_block *tmp_mb; + + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + if(unused_start < mb->start){ + tmp_mb = (struct mem_block*)simple_malloc(sizeof(struct mem_block)); + + tmp_mb->start = unused_start; + tmp_mb->end = mb->start; + list_add_tail(&tmp_mb->list, &mem_unusedmap); + } + INFO("unused map: start = %p, end = %p", tmp_mb->start, tmp_mb->end); + unused_start = mb->end; + } + + if(unused_start < memory_node.end){ + tmp_mb = (struct mem_block*)simple_malloc(sizeof(struct mem_block)); + tmp_mb->start = unused_start; + tmp_mb->end = memory_node.end; + list_add_tail(&tmp_mb->list, &mem_unusedmap); + } +} + +void* _get_memory_node(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + static int found_memory_node = 0; + uint32_t* pw; + if(node != NULL && strcmp(node->name, "memory@0") == 0){ + memory_node.name = "memory@0"; + found_memory_node = 1; + } + if(found_memory_node && prop != NULL && strcmp(prop->name, "reg") == 0){ + pw = (uint32_t*)prop->value; + memory_node.start = bswap32(pw[0]); + memory_node.end = memory_node.start + bswap32(pw[1]); + found_memory_node = 0; + } +} + + +void mm_init(void *dtb){ + INFO("Init mm subsystem.."); + // initialize mm's global variable + INIT_LIST_HEAD(&mem_rsvmap); + INIT_LIST_HEAD(&mem_unusedmap); + fdt_parser((uint8_t*)dtb, _get_memory_node); + + _create_memory_rsvmap(dtb); + _create_memory_unusedmap(); + + INFO("Memory node: %s, size: %p", memory_node.name, memory_node.end - memory_node.start); + INFO("Memory reserved size: %p", get_reserved_size()); + INFO("Memory unused size : %p", get_unused_size()); + + // initialize buddy system + buddy_init(); + + print_buddy_statistics(); + + if(debug) + debug_slab(); + + kmalloc_init(); + + if(debug){ + debug_kmalloc(); + //debug_buddy(); + print_buddy_statistics(); + } + +} diff --git a/lab4/mm/page_alloc.c b/lab4/mm/page_alloc.c new file mode 100644 index 000000000..0a0f61f92 --- /dev/null +++ b/lab4/mm/page_alloc.c @@ -0,0 +1,361 @@ +#include "mm/page_alloc.h" +static struct buddy_system buddy; + +void _init_mem_map(){ + struct list_head *node; + struct mem_block *mb; + uint64_t start_pfn, end_pfn, size; + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + + start_pfn = addr_to_pfn(mb->start); + end_pfn = addr_to_pfn(mb->end); + size = (end_pfn - start_pfn) * sizeof(struct page); + + memset(&mem_map[start_pfn], '\0', size); + } + + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + + start_pfn = addr_to_pfn(mb->start); + end_pfn = addr_to_pfn(mb->end); + for(uint64_t i = start_pfn ; i < end_pfn ; i++){ + memset(&mem_map[i], '\0', sizeof(struct page)); + mem_map[i].type |= PAGE_TYPE_RESERVED; + } + } +} + +void __free_pages(struct page* page, uint32_t order){ + struct page* end_page = page + (1 << order); + // initialize buddy group leader and add it to free list + page->order = order; + list_add(&page->list, &buddy.free_lists[order].list); + buddy.free_lists[order].count++; + + // initialize buddy group members + + for(struct page* p = page + 1 ; p < end_page ; p++){ + p->order = BUDDY_GROUP_MEMBER; + } +} + +void _free_pages_memory(uint64_t start, uint64_t end){ + // start and end is page frame number ( pfn ) + uint64_t order; + while(start < end){ + order = min(BUDDY_MAX_ORDER - 1, _buddy_ffs(start)); + + // decrease the order if last page's pfn in buddy is larger than end + while(start + (1 << order) > end) order--; + + __free_pages(&mem_map[start], order); + start += (1 << order); + } +} + +void _free_pages(struct page* page, uint32_t order){ + struct page* buddy_page; + uint64_t pfn = page_to_pfn(page); + uint64_t buddy_pfn; + + // check the order of page + if(BUDDY_IS_FREED(page)){ + INFO("Error: _free_pages(%u) try to free freed pfn %p", order, pfn); + return; + } + if(order > _buddy_ffs(pfn)){ + INFO("Error: _free_pages(%u) try to free pfn %p", order, pfn); + return; + } + + while(order < BUDDY_MAX_ORDER - 1){ + buddy_pfn = find_buddy_pfn(pfn, order); + buddy_page = pfn_to_page(buddy_pfn); + + // Check if buddy is not reserved and freed + LOG("%p is buddy of %p in order %u free list and it can be merged", pfn_to_addr(buddy_pfn), pfn_to_addr(pfn), order); + if(!PAGE_IS_RESERVED(buddy_page) && BUDDY_IS_FREED(buddy_page) && buddy_page->order == order){ + list_del(&buddy_page->list); + buddy.free_lists[order].count--; + }else{ + break; + } + + pfn = pfn & ~(1 << order); + page = pfn_to_page(pfn); + order++; + } + LOG("Merge %p into order %u free list ", pfn_to_addr(pfn), order); + __free_pages(page, order); + LOG("end merge pages"); + +} + +// free 2^order pages +void free_pages(void* addr, uint32_t order){ + LOG("_free_pages(%p, %u)",addr, order); + uint64_t pfn = addr_to_pfn(addr); + struct page *page = pfn_to_page(pfn); + + _free_pages(page, order); +} + +// free one page +void free_page(void* addr){ + uint64_t pfn = addr_to_pfn(addr); + struct page *page = pfn_to_page(pfn); + + _free_pages(page, 0); +} + +// split large buddy group to two small buddy groups +void expand(struct page *page, uint32_t high, uint32_t low){ + struct page* tmp_page; + while(high > low){ + high--; + tmp_page = page + (1 << high); + + LOG("add page %p to order %u free list",pfn_to_addr(page_to_pfn(tmp_page)) , high); + __free_pages(tmp_page, high); + } +} + +struct page* _alloc_pages(uint32_t order){ + LOG("_alloc_pages(%u)", order); + struct list_head *node; + struct free_list* free_list; + struct page* page, *tmp_page; + + // find appropriate buddy group for user + for(uint32_t i = order ; i < BUDDY_MAX_ORDER ; i++){ + free_list = &buddy.free_lists[i]; + + if(list_empty(&free_list->list)){ + LOG("free list of order %u is empty", i); + continue; + } + + page = list_first_entry(&free_list->list, struct page, list); + list_del(&page->list); + free_list->count--; + LOG("get free page %p from order %u", pfn_to_addr(page_to_pfn(page)), i); + + + for(uint32_t j = 0 ; j < (1 << order) ; j++){ + page[j].order = BUDDY_ALLOCATED|order; + page[j].buddy_leader = page; + } + + if(i > order){ + LOG("start expand pages of order %u to order %u", i, order); + expand(page, i, order); + LOG("end expand pages from order %u to order %u", i, order); + } + return page; + } + return NULL; +} + +// return 2^order pages +void* alloc_pages(uint32_t order){ + if(order > BUDDY_MAX_ORDER - 1) return NULL; + + struct page* page = _alloc_pages(order); + uint64_t pfn = page_to_pfn(page); + + return pfn_to_addr(pfn); +} + +// return one page +void* alloc_page(){ + struct page* page = _alloc_pages(0); + uint64_t pfn = page_to_pfn(page); + return pfn_to_addr(pfn); +} + +void print_buddy_statistics(){ + uint64_t free_page_count = 0; + uint64_t tmp; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + INFO("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + INFO("Total free page #: %l", free_page_count); +} + +uint8_t* _debug_alloc_page(uint32_t order){ + LOG("###########################################"); + uint64_t free_page_count = 0; + uint64_t tmp; + uint8_t * ret; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + LOG("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + ret = alloc_pages(order); + LOG("Total free page #: %l", free_page_count); + LOG("allocate page: %p", ret); + return ret; +} + +uint8_t* _debug_free_page(void *addr, uint32_t order){ + LOG("###########################################"); + uint64_t free_page_count = 0; + uint64_t tmp; + uint8_t * ret; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + LOG("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + free_pages(addr, order); + LOG("Total free page #: %l", free_page_count); + LOG("freed page: %p", addr); + return ret; +} + +void debug_buddy(){ + uint8_t *arr[1500]; + int32_t i = 0, count = 0; + struct list_head* node; + struct page* page, *target_page; + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(1); + count++; + } + for(i = 0 ; i < 4; i++){ + arr[count] = _debug_alloc_page(2); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(3); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(1); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(2); + count++; + } + for(i = 0 ; i < 1400; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + LOG("###########################################"); + for(i = 0 ; i < count ; i++){ + target_page = pfn_to_page(addr_to_pfn(arr[i])); + if(!BUDDY_IS_ALLOCATED(target_page)){ + LOG("******* page %p didn't set to allocated *******", pfn_to_addr(page_to_pfn(page))); + goto error; + } + for(uint32_t j = 0 ; j < BUDDY_MAX_ORDER ; j++){ + list_for_each(node, &buddy.free_lists[j].list){ + page = list_entry(node, struct page, list); + if(target_page == page){ + LOG("******* allocated page didn't remove from free list *******", pfn_to_addr(page_to_pfn(page))); + goto error; + } + } + } + } + count = 0; + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 1); + count++; + } + for(i = 0 ; i < 4; i++){ + _debug_free_page(arr[count], 2); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 3); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 1); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 2); + count++; + } + for(i = 0 ; i < 1400; i++){ + _debug_free_page(arr[count], 0); + count++; + } + // check the integrity of linked list by using grep to check how many unique lines + // + // ./debug.sh > t + // grep "\[test\]" t|sort|uniq|wc -l + // + struct list_head* tmp_node; + struct page* tmp_page; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + list_for_each(tmp_node, &buddy.free_lists[i].list){ + tmp_page = list_entry(tmp_node, struct page, list); + for(uint32_t j = 0; j < (1 << i) ; j++){ + printf("[test] : %p\n", pfn_to_addr(page_to_pfn(tmp_page) + j)); + } + } + } + LOG("******* Pass the testcases *******"); + return; +error: + LOG("******* Something is wrong in buddy system alloc_pages *******"); + return; +} +void buddy_init(){ + struct list_head * node; + struct mem_block* mb; + uint64_t start_pfn, end_pfn; + + INFO("Initialize buddy system..."); + // Initialize global variable + memset(&buddy, '\0', sizeof(struct buddy_system)); + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER; i++){ + INIT_LIST_HEAD(&buddy.free_lists[i].list); + } + + // Initialize mem map + _init_mem_map(); + + // Add free page frame to buddy system + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + start_pfn = addr_to_pfn(mb->start); + end_pfn = addr_to_pfn(mb->end); + + _free_pages_memory(start_pfn, end_pfn); + } + +} diff --git a/lab4/mm/slab.c b/lab4/mm/slab.c new file mode 100644 index 000000000..3b7c110b9 --- /dev/null +++ b/lab4/mm/slab.c @@ -0,0 +1,237 @@ +#include "mm/slab.h" + +struct list_head kmem_cache[KMEM_CACHE_NUM] = {0}; + +struct slab* slab_create(size_t obj_size){ + size_t allocated_size; + uint32_t order = 0; + size_t page_num; + void* pages; + struct slab * pslab; + + // object size align to slab_alignment + obj_size = ALIGN_UP(obj_size, SLAB_ALIGNMENT); + + // check if obj_size exceed slab's limit + if(obj_size > SLAB_MAX_OBJECT_SIZE){ + LOG("invalid obj_size: %l, slab_max_object_size is %l", obj_size, SLAB_MAX_OBJECT_SIZE); + return NULL; + } + + // get sufficient order + page_num = ALIGN_UP(obj_size + SLAB_SIZE, 4096) >> PAGE_SHIFT; + order = BUDDY_MAX_ORDER - 1; + pages = alloc_pages(order); + if(pages == NULL){ + LOG("Not enough page for slab"); + return NULL; + } + + // initialize struct slab + pslab = pages; + pslab->size = obj_size; + pslab->s_mem = pages + SLAB_SIZE; + pslab->inuse = 0; + INIT_LIST_HEAD(&pslab->free_list); + + return pslab; +} + +void slab_destroy(struct slab* slab){ + size_t page_num; + struct page* page = pfn_to_page(addr_to_pfn(slab)); + + LOG("slab_destroy recycle order %u buddy %p", (void*)slab, get_page_order(page)); + // free pages + free_pages((void*)slab, get_page_order(page)); +} + +void *slab_alloc(struct slab* slab){ + void *ret = NULL; + struct page* page; + uint32_t order; + size_t max_size; + if(!list_empty(&slab->free_list)){ + // check free list + ret = slab->free_list.next; + list_del(slab->free_list.next); + slab->inuse++; + }else{ + page = pfn_to_page(addr_to_pfn(slab)); + order = get_page_order(page); + max_size = (1 << order) * PAGE_SIZE; + if(SLAB_SIZE + (slab->inuse + 1) * slab->size > max_size){ + ret = NULL; + }else{ + ret = (uint8_t*)slab->s_mem + slab->inuse * slab->size; + slab->inuse++; + } + } + return ret; +} + +void slab_free(struct slab* slab, void* obj){ + list_add((struct list_head*)obj, &slab->free_list); + slab->inuse--; +} + +void kmalloc_init(){ + for(uint64_t i = 0 ; i < KMEM_CACHE_NUM ; i++){ + INIT_LIST_HEAD(&kmem_cache[i]); + } +} +void* kmalloc(size_t size){ + uint64_t cache_idx; + struct list_head* cache_list, *node; + struct slab *s; + void * ret = NULL; + + size = ALIGN_UP(size, SLAB_ALIGNMENT); + + LOG("kmalloc(%u) start", size); + if(size > SLAB_MAX_OBJECT_SIZE){ + LOG("kmalloc invalid size %l", size); + return NULL; + } + + // allocate memory from corresponding cache bin + cache_idx = ALIGN_UP(size, SLAB_ALIGNMENT) / SLAB_ALIGNMENT; + cache_list = &kmem_cache[cache_idx]; + + list_for_each(node, cache_list){ + s = list_entry(node, struct slab, list); + ret = slab_alloc(s); + if(ret != NULL){ + LOG("kmalloc(%u) found a free object %p in kmem_cache[%u]", size, ret, cache_idx); + break; + } + } + + if(ret == NULL){ + s = slab_create(size); + list_add(&s->list, cache_list); + ret = slab_alloc(s); + if(ret != NULL){ + LOG("kmalloc(%u) found a free object %p in kmem_cache[%u]", size, ret, cache_idx); + } + } + + + LOG("kmalloc s->inuse: %x", s->inuse); + LOG("kmalloc(%u) end, ret: %p", size, ret); + return ret; +} + +void kfree(void* obj){ + uint64_t pfn = addr_to_pfn(ALIGN_DOWN(obj, PAGE_SIZE)); + struct page* page = pfn_to_page(pfn); + struct page* buddy_leader = get_buddy_leader(page); + struct slab* s = pfn_to_addr(page_to_pfn(buddy_leader)); + + LOG("kfree(%p) free an object", obj); + slab_free(s, obj); + + if((int64_t)s->inuse < 0){ + LOG("[Error]: s->inuse : %p", s->inuse); + } + if(s->inuse == 0){ + LOG("kfree(%p) triger recycle unused slab", obj); + list_del(&s->list); + slab_destroy(s); + } +} + +#define TEST_SIZE 64 +#define TEST_INVALID_SIZE ((1 << (BUDDY_MAX_ORDER - 1)) * PAGE_SIZE - SLAB_SIZE + 1) +void debug_slab(){ + uint32_t i, max_i; + uint8_t *a[ (1 << BUDDY_MAX_ORDER - 1) * PAGE_SIZE / TEST_SIZE]; + + struct slab* s = slab_create(TEST_SIZE); + + for(i = 0 ; i < 10; i++){ + a[i] = slab_alloc(s); + LOG("%u: slab_alloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("slab is full"); + break; + } + } + max_i = i; + for(i = 0 ; i < max_i ; i++){ + slab_free(s, a[i]); + } + + for(i = 0 ; i < 10; i++){ + a[i] = slab_alloc(s); + LOG("%u: slab_alloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("slab is full"); + break; + } + } + + + + for(i = 0 ; i < max_i ; i++){ + slab_free(s, a[i]); + } + + slab_destroy(s); + uint64_t pfn = addr_to_pfn(s); + struct page* page = pfn_to_page(pfn); + + if(BUDDY_IS_FREED(page) && get_page_order(page) == BUDDY_MAX_ORDER - 1){ + LOG("slab_destroy success"); + }else{ + + LOG("slab_destroy failed"); + } + + s = slab_create(TEST_INVALID_SIZE); + + if(s == NULL){ + LOG("create super large slab %l failed", TEST_INVALID_SIZE); + }else{ + LOG("create super large slab %l success", TEST_INVALID_SIZE); + } +} + +void debug_kmalloc(){ + uint32_t i, max_i; + uint8_t *a[20]; + + + for(i = 0 ; i < 20; i++){ + a[i] = kmalloc(TEST_SIZE); + LOG("%l: kmalloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("kmalloc is failed"); + break; + } + } + + max_i = i; + for(i = 0 ; i < max_i ; i++){ + LOG("kfree(%p)", a[i]); + kfree(a[i]); + } +/* + for(i = 0 ; i < 200; i++){ + a[i] = kmalloc(TEST_SIZE); + LOG("%u: kmalloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("kmalloc is failed"); + break; + } + } + + for(i = 0 ; i < max_i ; i++){ + kfree(a[i]); + } +*/ +} diff --git a/lab4/peripherals/Makefile b/lab4/peripherals/Makefile new file mode 100644 index 000000000..50b5d0780 --- /dev/null +++ b/lab4/peripherals/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + mini_uart.o \ + mailbox.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab4/peripherals/mailbox.c b/lab4/peripherals/mailbox.c new file mode 100644 index 000000000..d8ae82621 --- /dev/null +++ b/lab4/peripherals/mailbox.c @@ -0,0 +1,114 @@ +#include "peripherals/mailbox.h" + +static uint32_t MBox_buf[4096] __attribute__((aligned(16))); + +static uint32_t MBox_read(int channel){ + int ch, data; + + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_EMPTY_MASK); + + data = mbox_reg->read; + ch = data & MBOX_WRITE_CHANNEL_MASK; + if(ch == channel){ + LOG("MBox read address: %p", data & MBOX_READ_ADDR_MASK); + return (data & MBOX_READ_ADDR_MASK); + } + LOG("Leave"); + return 0; +} + +static void MBox_write(uint32_t data, int channel){ + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_FULL_MASK); + + mbox_reg->write = data | channel; + LOG("Leave"); +} + +static uint32_t MBox_process(uint8_t* tags, size_t tags_size){ + LOG("Enter"); + MBox_buffer* mbuf = (MBox_buffer*)MBox_buf; + // set buffer header + mbuf->buf_size = tags_size + 12; + mbuf->code = MBOX_STATUS_REQUEST; + + // copy tags to buffer + memcpy(mbuf->buf, tags, tags_size); + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + LOG("mbuf->buf: %p", mbuf->buf); + LOG("mbuf->buf + tags_size: %p", mbuf->buf + tags_size); + // end of MBox_buf + memset(mbuf->buf + tags_size, 0, 4); + + pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + // write to mailbox + MBox_write((uint32_t)(uint64_t)MBox_buf, MBOX_CHANNEL_PROPERTY_TAGS); + + // read from mailbox + uint32_t result = MBox_read(MBOX_CHANNEL_PROPERTY_TAGS); + + + LOG("Leave"); + return result; +} +void MBox_get_board_revision(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 4]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_BOARD_REVISION; + tag->value_size = 4; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer *)(uint64_t)MBox_process(buf, sizeof(MBox_tag) + 4); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + *ret = ((uint32_t*)tag->values)[0]; + LOG("Leave"); +} +void MBox_get_arm_memory(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 8]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_ARM_MEMORY; + tag->value_size = 8; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + ((uint32_t*)tag->values)[1] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer *)(uint64_t)MBox_process(buf, sizeof(MBox_tag) + 8); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + ret[0] = ((uint32_t*)tag->values)[0]; + ret[1] = ((uint32_t*)tag->values)[1]; + LOG("Leave"); +} + + diff --git a/lab4/peripherals/mini_uart.c b/lab4/peripherals/mini_uart.c new file mode 100644 index 000000000..661929cce --- /dev/null +++ b/lab4/peripherals/mini_uart.c @@ -0,0 +1,195 @@ +#include "peripherals/mini_uart.h" + +static ring_buffer* rx_rbuf = NULL; +static ring_buffer* tx_rbuf = NULL; + +inline void delay_cycles(uint64_t n){ + for(register uint64_t i = 0 ; i < n ; i++) asm volatile("nop"); +} + +inline void enable_mini_uart_irq(uint32_t tx){ + uint32_t old_ier = IO_MMIO_read32(AUX_MU_IER_REG); + + if(tx == TX) IO_MMIO_write32(AUX_MU_IER_REG, 0b10 | old_ier); + else IO_MMIO_write32(AUX_MU_IER_REG, 0b01 | old_ier); +} + +inline void enable_mini_uart_tx_irq(){ + if(mini_uart_get_tx_len() > 0){ + enable_mini_uart_irq(TX); + } +} + +inline void enable_mini_uart_rx_irq(){ + enable_mini_uart_irq(RX); +} + +inline void disable_mini_uart_irq(uint32_t tx){ + uint32_t old_ier = IO_MMIO_read32(AUX_MU_IER_REG); + + if(tx == TX) IO_MMIO_write32(AUX_MU_IER_REG, ~(0b10) & old_ier); + else IO_MMIO_write32(AUX_MU_IER_REG, ~(0b01) & old_ier); +} + +inline void disable_mini_uart_tx_irq(){ + disable_mini_uart_irq(TX); +} + +inline void disable_mini_uart_rx_irq(){ + disable_mini_uart_irq(RX); +} + +void mini_uart_init(){ + // GPIO 14 & 15 take function 0 + // Read out GPFSEL1 register + uint32_t tmp = IO_MMIO_read32(GPFSEL1); + + // Set GPIO 14 & 15 function bits + tmp &= ~(0b111111 << 12); + tmp |= 0b010010 << 12; + IO_MMIO_write32(GPFSEL1, tmp); + + + // disable pull-up/down of GPIO 14 & 15 + // Write to GPPUD to set the required control signal + IO_MMIO_write32(GPPUD, 0); + + // Wait 150 cycles – this provides the required set-up time for the control signal + delay_cycles(150); + + // Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to modify + IO_MMIO_write32(GPPUDCLK0, (1 << 14) | (1 << 15)); + + // Wait 150 cycles – this provides the required hold time for the control signal + delay_cycles(150); + + // Write to GPPUD to remove the control signa + IO_MMIO_write32(GPPUD, 0); + + // Write to GPPUDCLK0/1 to remove the clock + IO_MMIO_write32(GPPUDCLK0, 0); + + // Initialize Auxiliary peripherals Register + // Mini UART enable + IO_MMIO_write32(AUX_ENABLES, 1); + + // To disable auto flow control and disable receiver and transmitter, set control register to 0 + IO_MMIO_write32(AUX_MU_CNTL_REG, 0); + + // Disable mini UART's interrupt + IO_MMIO_write32(AUX_MU_IER_REG, 0); + + // Set UART to 8-bit mode + IO_MMIO_write32(AUX_MU_LCR_REG, 3); + + // To indicate that our UART is able to receive data, set RTS line to be always high + IO_MMIO_write32(AUX_MU_MCR_REG, 0); + + // Set Baud rate to 115200 + IO_MMIO_write32(AUX_MU_BAUD_REG, BAUD_RATE_REG); + + // disable FIFO + IO_MMIO_write32(AUX_MU_IIR_REG, 6); + + // Start UART + IO_MMIO_write32(AUX_MU_CNTL_REG, 3); + + return; +} + +uint8_t mini_uart_read(void){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & 0x1)); + return IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; +} + +void mini_uart_write(uint8_t val){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & (0x1 << 5))); + IO_MMIO_write32(AUX_MU_IO_REG, val); +} + +ssize_t write_bytes(uint8_t* buf, size_t n){ + for(uint64_t i = 0 ; i < n ; i++) mini_uart_write(buf[i]); + return n; +} + +void write_str(char* buf){ + while(*buf) mini_uart_write((uint8_t)*buf++); + return; +} + +void write_hex(uint64_t n){ + int i = 0; + char buf[16]; + char *hex_table = "0123456789abcdef"; + do{ + buf[i] = hex_table[n & 0xf]; + n = n >> 4; + i++; + }while(n); + do{ + i--; + mini_uart_write(buf[i]); + }while(i > 0); +} + +void mini_uart_irq_init(){ + rx_rbuf = create_simple_ring_buf(4096 * 4 - 1); + tx_rbuf = create_simple_ring_buf(4095 * 4 - 1); + + + IO_MMIO_write32(ENABLE_IRQS_1, 1 << 29); + // only enable receive interrupt. transmit interrupts should be enable when user want to transmit data. + enable_mini_uart_irq(RX); +} + +void mini_uart_tx_softirq_callback(){ +} + +void mini_uart_rx_softirq_callback(){ +} + +void mini_uart_irq_read(){ + uint8_t b[1]; + b[0] = IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; + ring_buf_write(rx_rbuf, b, 1); +} +size_t mini_uart_get_rx_len(){ + return ring_buf_get_len(rx_rbuf); +} + +uint8_t mini_uart_aio_read(void){ + uint8_t b[1]; + while(ring_buf_is_empty(rx_rbuf)); + + local_irq_disable(); + ring_buf_read(rx_rbuf, b, 1); + local_irq_enable(); + return b[0]; +} + +void mini_uart_irq_write(){ + uint8_t b[1]; + if(ring_buf_read(tx_rbuf, b, 1)){ + IO_MMIO_write32(AUX_MU_IO_REG, b[0]); + } +} +size_t mini_uart_get_tx_len(){ + return ring_buf_get_len(tx_rbuf); +} + +void mini_uart_aio_write(uint8_t c){ + uint8_t b[1]; + while(ring_buf_is_full(tx_rbuf)); + b[0] = c; + + local_irq_disable(); + ring_buf_write(tx_rbuf, b, 1); + local_irq_enable(); + + enable_mini_uart_irq(TX); +} + +ssize_t aio_write_bytes(uint8_t* buf, size_t n){ + for(uint64_t i = 0 ; i < n ; i++) mini_uart_aio_write(buf[i]); + return n; +} diff --git a/lab4/test/lib/.gdb_history b/lab4/test/lib/.gdb_history new file mode 100644 index 000000000..58afc787f --- /dev/null +++ b/lab4/test/lib/.gdb_history @@ -0,0 +1,2 @@ +run +quit diff --git a/lab4/test/lib/dtb_parse/.gdb_history b/lab4/test/lib/dtb_parse/.gdb_history new file mode 100644 index 000000000..8ae386791 --- /dev/null +++ b/lab4/test/lib/dtb_parse/.gdb_history @@ -0,0 +1,43 @@ +b main +run +n +quit +run +p fdt +quit +b main +n +run +n +x/gx ptr +quit +b main +run +n +statbuf->size +p statbuf->size +p statbuf->st_size +quit +run +b main +run +n +s +n +p token +p/x pdft_struct +p/x pdt_struct +x/gx 0x7ffff7fb3048 +x/s 0x7ffff7fb3048 +x/dx 0x7ffff7fb3048 +x/wx 0x7ffff7fb3048 +x/4wx 0x7ffff7fb3048 +n +p len +n +quit +quit +run +quit +run +quit diff --git a/lab4/test/lib/dtb_parse/Makefile b/lab4/test/lib/dtb_parse/Makefile new file mode 100644 index 000000000..d6e1a8f08 --- /dev/null +++ b/lab4/test/lib/dtb_parse/Makefile @@ -0,0 +1,2 @@ +all: + gcc main.c fdt_parse.c -o main -g -O0 diff --git a/lab4/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb b/lab4/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 000000000..6f9ef31cc Binary files /dev/null and b/lab4/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb differ diff --git a/lab4/test/lib/dtb_parse/fdt_parse.c b/lab4/test/lib/dtb_parse/fdt_parse.c new file mode 100644 index 000000000..bb8abd2c8 --- /dev/null +++ b/lab4/test/lib/dtb_parse/fdt_parse.c @@ -0,0 +1,113 @@ +#include "fdt_parse.h" +#include +#include +#include + +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } + +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = (fdt_header*)malloc(sizeof(fdt_header)); + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) / 4; + //printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + len += 2; + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + printf("Parsing error!!\n"); + exit(0); + } + } +} + +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab4/test/lib/dtb_parse/fdt_parse.h b/lab4/test/lib/dtb_parse/fdt_parse.h new file mode 100644 index 000000000..876b4087a --- /dev/null +++ b/lab4/test/lib/dtb_parse/fdt_parse.h @@ -0,0 +1,53 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +#endif diff --git a/lab4/test/lib/dtb_parse/main b/lab4/test/lib/dtb_parse/main new file mode 100755 index 000000000..aa43f24f6 Binary files /dev/null and b/lab4/test/lib/dtb_parse/main differ diff --git a/lab4/test/lib/dtb_parse/main.c b/lab4/test/lib/dtb_parse/main.c new file mode 100644 index 000000000..9af1de752 --- /dev/null +++ b/lab4/test/lib/dtb_parse/main.c @@ -0,0 +1,19 @@ +#include "fdt_parse.h" +#include +#include +#include +#include +#include +#include + +int main(void){ + int fd = open("./bcm2710-rpi-3-b-plus.dtb", O_RDONLY); + if(fd < 0){ + printf("failed to open file\n"); + } + struct stat statbuf; + fstat(fd, &statbuf); + char *ptr = mmap(NULL,statbuf.st_size,PROT_READ,MAP_PRIVATE,fd,0); + + fdt_parser(ptr, fdt_print_callback); +} diff --git a/lab4/test/lib/dtb_parse/tmp.dts b/lab4/test/lib/dtb_parse/tmp.dts new file mode 100644 index 000000000..1ceb3539f --- /dev/null +++ b/lab4/test/lib/dtb_parse/tmp.dts @@ -0,0 +1,1515 @@ +/dts-v1/; + +/memreserve/ 0x0000000000000000 0x0000000000001000; +/ { + compatible = "raspberrypi,3-model-b-plus\0brcm,bcm2837"; + model = "Raspberry Pi 3 Model B+"; + #address-cells = <0x01>; + #size-cells = <0x01>; + interrupt-parent = <0x01>; + + aliases { + serial0 = "/soc/serial@7e215040"; + serial1 = "/soc/serial@7e201000"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + aux = "/soc/aux@7e215000"; + sound = "/soc/sound"; + soc = "/soc"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + uart0 = "/soc/serial@7e201000"; + uart1 = "/soc/serial@7e215040"; + sdhost = "/soc/mmc@7e202000"; + mmc = "/soc/mmc@7e300000"; + mmc1 = "/soc/mmcnr@7e300000"; + mmc0 = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c1 = "/soc/i2c@7e804000"; + i2c10 = "/soc/i2c0mux/i2c@1"; + spi0 = "/soc/spi@7e204000"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + usb = "/soc/usb@7e980000"; + leds = "/leds"; + fb = "/soc/fb"; + thermal = "/soc/thermal@7e212000"; + axiperf = "/soc/axiperf"; + i2c2 = "/soc/i2c@7e805000"; + ethernet0 = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + }; + + chosen { + bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; + }; + + reserved-memory { + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges; + phandle = <0x37>; + + linux,cma { + compatible = "shared-dma-pool"; + size = <0x4000000>; + reusable; + linux,cma-default; + phandle = <0x38>; + }; + }; + + thermal-zones { + + cpu-thermal { + polling-delay-passive = <0x00>; + polling-delay = <0x3e8>; + thermal-sensors = <0x02>; + coefficients = <0xfffffde6 0x64960>; + phandle = <0x39>; + + cooling-maps { + }; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x7e000000 0x3f000000 0x1000000 0x40000000 0x40000000 0x1000>; + dma-ranges = <0xc0000000 0x00 0x3f000000>; + phandle = <0x3a>; + + txp@7e004000 { + compatible = "brcm,bcm2835-txp"; + reg = <0x7e004000 0x20>; + interrupts = <0x01 0x0b>; + status = "disabled"; + phandle = <0x3b>; + }; + + cprman@7e101000 { + compatible = "brcm,bcm2835-cprman"; + #clock-cells = <0x01>; + reg = <0x7e101000 0x2000>; + clocks = <0x03 0x04 0x00 0x04 0x01 0x04 0x02 0x05 0x00 0x05 0x01 0x05 0x02>; + firmware = <0x06>; + phandle = <0x08>; + }; + + mailbox@7e00b880 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0x00 0x01>; + #mbox-cells = <0x00>; + phandle = <0x1f>; + }; + + gpio@7e200000 { + compatible = "brcm,bcm2835-gpio"; + reg = <0x7e200000 0xb4>; + interrupts = <0x02 0x11 0x02 0x12>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x07 0x00 0x00 0x36>; + pinctrl-names = "default"; + gpio-line-names = "ID_SDA\0ID_SCL\0SDA1\0SCL1\0GPIO_GCLK\0GPIO5\0GPIO6\0SPI_CE1_N\0SPI_CE0_N\0SPI_MISO\0SPI_MOSI\0SPI_SCLK\0GPIO12\0GPIO13\0TXD1\0RXD1\0GPIO16\0GPIO17\0GPIO18\0GPIO19\0GPIO20\0GPIO21\0GPIO22\0GPIO23\0GPIO24\0GPIO25\0GPIO26\0GPIO27\0HDMI_HPD_N\0STATUS_LED_G\0CTS0\0RTS0\0TXD0\0RXD0\0SD1_CLK\0SD1_CMD\0SD1_DATA0\0SD1_DATA1\0SD1_DATA2\0SD1_DATA3\0PWM0_OUT\0PWM1_OUT\0ETH_CLK\0WIFI_CLK\0SDA0\0SCL0\0SMPS_SCL\0SMPS_SDA\0SD_CLK_R\0SD_CMD_R\0SD_DATA0_R\0SD_DATA1_R\0SD_DATA2_R\0SD_DATA3_R"; + phandle = <0x07>; + + dpi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x06>; + phandle = <0x3c>; + }; + + emmc_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x07>; + phandle = <0x3d>; + }; + + emmc_gpio34 { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x3e>; + }; + + emmc_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x07>; + phandle = <0x17>; + }; + + gpclk0_gpio4 { + brcm,pins = <0x04>; + brcm,function = <0x04>; + phandle = <0x3f>; + }; + + gpclk1_gpio5 { + brcm,pins = <0x05>; + brcm,function = <0x04>; + phandle = <0x40>; + }; + + gpclk1_gpio42 { + brcm,pins = <0x2a>; + brcm,function = <0x04>; + phandle = <0x41>; + }; + + gpclk1_gpio44 { + brcm,pins = <0x2c>; + brcm,function = <0x04>; + phandle = <0x42>; + }; + + gpclk2_gpio6 { + brcm,pins = <0x06>; + brcm,function = <0x04>; + phandle = <0x43>; + }; + + gpclk2_gpio43 { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x44>; + }; + + i2c0_gpio0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x12>; + }; + + i2c0_gpio28 { + brcm,pins = <0x1c 0x1d>; + brcm,function = <0x04>; + phandle = <0x45>; + }; + + i2c0_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x05>; + phandle = <0x13>; + }; + + i2c1_gpio2 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x46>; + }; + + i2c1_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x06>; + phandle = <0x47>; + }; + + jtag_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x03>; + phandle = <0x48>; + }; + + pcm_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x49>; + }; + + pcm_gpio28 { + brcm,pins = <0x1c 0x1d 0x1e 0x1f>; + brcm,function = <0x06>; + phandle = <0x4a>; + }; + + sdhost_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x04>; + phandle = <0x0d>; + }; + + spi0_gpio7 { + brcm,pins = <0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x4b>; + }; + + spi0_gpio35 { + brcm,pins = <0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x04>; + phandle = <0x4c>; + }; + + spi1_gpio16 { + brcm,pins = <0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x03>; + phandle = <0x4d>; + }; + + spi2_gpio40 { + brcm,pins = <0x28 0x29 0x2a 0x2b 0x2c 0x2d>; + brcm,function = <0x03>; + phandle = <0x4e>; + }; + + uart0_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x04>; + phandle = <0x4f>; + }; + + uart0_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x07>; + phandle = <0x50>; + }; + + uart0_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x07>; + brcm,pull = <0x02 0x00>; + phandle = <0x51>; + }; + + uart0_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x52>; + }; + + uart0_gpio36 { + brcm,pins = <0x24 0x25>; + brcm,function = <0x06>; + phandle = <0x53>; + }; + + uart0_ctsrts_gpio38 { + brcm,pins = <0x26 0x27>; + brcm,function = <0x06>; + phandle = <0x54>; + }; + + uart1_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x02>; + phandle = <0x55>; + }; + + uart1_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x02>; + phandle = <0x56>; + }; + + uart1_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x02>; + phandle = <0x57>; + }; + + uart1_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x02>; + phandle = <0x58>; + }; + + uart1_gpio40 { + brcm,pins = <0x28 0x29>; + brcm,function = <0x02>; + phandle = <0x59>; + }; + + uart1_ctsrts_gpio42 { + brcm,pins = <0x2a 0x2b>; + brcm,function = <0x02>; + phandle = <0x5a>; + }; + + i2c_slave_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x07>; + phandle = <0x5b>; + }; + + jtag_gpio4 { + brcm,pins = <0x04 0x05 0x06 0x0c 0x0d>; + brcm,function = <0x02>; + phandle = <0x5c>; + }; + + pwm0_gpio12 { + brcm,pins = <0x0c>; + brcm,function = <0x04>; + phandle = <0x5d>; + }; + + pwm0_gpio18 { + brcm,pins = <0x12>; + brcm,function = <0x02>; + phandle = <0x5e>; + }; + + pwm0_gpio40 { + brcm,pins = <0x28>; + brcm,function = <0x04>; + phandle = <0x5f>; + }; + + pwm1_gpio13 { + brcm,pins = <0x0d>; + brcm,function = <0x04>; + phandle = <0x60>; + }; + + pwm1_gpio19 { + brcm,pins = <0x13>; + brcm,function = <0x02>; + phandle = <0x61>; + }; + + pwm1_gpio41 { + brcm,pins = <0x29>; + brcm,function = <0x04>; + phandle = <0x62>; + }; + + pwm1_gpio45 { + brcm,pins = <0x2d>; + brcm,function = <0x04>; + phandle = <0x63>; + }; + + dpi_18bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + brcm,pull = <0x00>; + phandle = <0x64>; + }; + + dpi_18bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + phandle = <0x65>; + }; + + dpi_18bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x66>; + }; + + dpi_18bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x67>; + }; + + dpi_16bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x68>; + }; + + dpi_16bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x69>; + }; + + dpi_16bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6a>; + }; + + dpi_16bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6b>; + }; + + gpioout { + brcm,pins = <0x06>; + brcm,function = <0x01>; + phandle = <0x6c>; + }; + + alt0 { + brcm,pins = <0x04 0x05 0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x6d>; + }; + + spi0_pins { + brcm,pins = <0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x0f>; + }; + + spi0_cs_pins { + brcm,pins = <0x08 0x07>; + brcm,function = <0x01>; + phandle = <0x10>; + }; + + i2c0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x6e>; + }; + + i2c1 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x18>; + }; + + i2s { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x0e>; + }; + + sdio_pins { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x1e>; + }; + + bt_pins { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x0a>; + }; + + uart0_pins { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x09>; + }; + + uart1_pins { + brcm,pins; + brcm,function; + brcm,pull; + phandle = <0x16>; + }; + + audio_pins { + brcm,pins = <0x28 0x29>; + brcm,function = <0x04>; + phandle = <0x20>; + }; + }; + + serial@7e201000 { + compatible = "arm,pl011\0arm,primecell"; + reg = <0x7e201000 0x200>; + interrupts = <0x02 0x19>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk\0apb_pclk"; + arm,primecell-periphid = <0x241011>; + cts-event-workaround; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x09 0x0a>; + status = "okay"; + phandle = <0x26>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <0x2dc6c0>; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x33>; + }; + }; + + mmc@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <0x02 0x18>; + clocks = <0x08 0x14>; + status = "okay"; + dmas = <0x0c 0x2000000d>; + dma-names = "rx-tx"; + bus-width = <0x04>; + brcm,overclock-50 = <0x00>; + brcm,pio-limit = <0x01>; + firmware = <0x06>; + pinctrl-names = "default"; + pinctrl-0 = <0x0d>; + phandle = <0x2f>; + }; + + i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; + reg = <0x7e203000 0x24>; + clocks = <0x08 0x1f>; + status = "disabled"; + dmas = <0x0c 0x02 0x0c 0x03>; + dma-names = "tx\0rx"; + #sound-dai-cells = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x0e>; + phandle = <0x28>; + }; + + spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x200>; + interrupts = <0x02 0x16>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + dmas = <0x0c 0x06 0x0c 0x07>; + dma-names = "tx\0rx"; + pinctrl-names = "default"; + pinctrl-0 = <0x0f 0x10>; + cs-gpios = <0x07 0x08 0x01 0x07 0x07 0x01>; + phandle = <0x29>; + + spidev@0 { + compatible = "spidev"; + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x6f>; + }; + + spidev@1 { + compatible = "spidev"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x70>; + }; + }; + + i2c@7e205000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e205000 0x200>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x11>; + }; + + i2c0mux { + compatible = "i2c-mux-pinctrl"; + #address-cells = <0x01>; + #size-cells = <0x00>; + i2c-parent = <0x11>; + pinctrl-names = "i2c0\0i2c_csi_dsi"; + status = "disabled"; + pinctrl-0 = <0x12>; + pinctrl-1 = <0x13>; + phandle = <0x2a>; + + i2c@0 { + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x71>; + }; + + i2c@1 { + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x72>; + }; + }; + + dpi@7e208000 { + compatible = "brcm,bcm2835-dpi"; + reg = <0x7e208000 0x8c>; + clocks = <0x08 0x14 0x08 0x2c>; + clock-names = "core\0pixel"; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x73>; + }; + + dsi@7e209000 { + compatible = "brcm,bcm2835-dsi0"; + reg = <0x7e209000 0x78>; + interrupts = <0x02 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x20 0x08 0x2f 0x08 0x31>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi0_byte\0dsi0_ddr2\0dsi0_ddr"; + status = "disabled"; + power-domains = <0x14 0x11>; + phandle = <0x04>; + }; + + aux@7e215000 { + compatible = "brcm,bcm2835-aux"; + #clock-cells = <0x01>; + reg = <0x7e215000 0x08>; + clocks = <0x08 0x14>; + phandle = <0x15>; + }; + + serial@7e215040 { + compatible = "brcm,bcm2835-aux-uart"; + reg = <0x7e215040 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x00>; + status = "okay"; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x16>; + phandle = <0x27>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = "\0\a\b"; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x74>; + }; + }; + + spi@7e215080 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e215080 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x75>; + }; + + spi@7e2150c0 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e2150c0 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x02>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x76>; + }; + + pwm@7e20c000 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x7e20c000 0x28>; + clocks = <0x08 0x1e>; + assigned-clocks = <0x08 0x1e>; + assigned-clock-rates = <0x989680>; + #pwm-cells = <0x02>; + status = "disabled"; + phandle = <0x77>; + }; + + mmc@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + status = "disabled"; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x17>; + bus-width = <0x04>; + phandle = <0x30>; + }; + + hvs@7e400000 { + compatible = "brcm,bcm2835-hvs"; + reg = <0x7e400000 0x6000>; + interrupts = <0x02 0x01>; + status = "disabled"; + phandle = <0x78>; + }; + + dsi@7e700000 { + compatible = "brcm,bcm2835-dsi1"; + reg = <0x7e700000 0x8c>; + interrupts = <0x02 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x23 0x08 0x30 0x08 0x32>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi1_byte\0dsi1_ddr2\0dsi1_ddr"; + status = "disabled"; + power-domains = <0x14 0x12>; + phandle = <0x05>; + }; + + i2c@7e804000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e804000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x18>; + clock-frequency = <0x186a0>; + phandle = <0x2b>; + }; + + usb@7e980000 { + compatible = "brcm,bcm2708-usb"; + reg = <0x7e980000 0x10000 0x7e006000 0x1000>; + interrupts = <0x01 0x09 0x02 0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x19>; + clock-names = "otg"; + phys = <0x1a>; + phy-names = "usb2-phy"; + interrupt-names = "usb\0soft"; + power-domains = <0x14 0x06>; + phandle = <0x79>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet@1 { + compatible = "usb424,7800"; + reg = <0x01>; + phandle = <0x7a>; + + mdio { + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet-phy@1 { + reg = <0x01>; + microchip,led-modes = <0x01 0x06>; + microchip,eee-enabled; + microchip,tx-lpi-timer = <0x258>; + microchip,downshift-after = <0x02>; + phandle = <0x36>; + }; + }; + }; + }; + }; + }; + + dma@7e007000 { + compatible = "brcm,bcm2835-dma"; + reg = <0x7e007000 0xf00>; + interrupts = <0x01 0x10 0x01 0x11 0x01 0x12 0x01 0x13 0x01 0x14 0x01 0x15 0x01 0x16 0x01 0x17 0x01 0x18 0x01 0x19 0x01 0x1a 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1c>; + interrupt-names = "dma0\0dma1\0dma2\0dma3\0dma4\0dma5\0dma6\0dma7\0dma8\0dma9\0dma10\0dma11\0dma12\0dma13\0dma14\0dma-shared-all"; + #dma-cells = <0x01>; + brcm,dma-channel-mask = <0x7f35>; + phandle = <0x0c>; + }; + + interrupt-controller@7e00b200 { + compatible = "brcm,bcm2836-armctrl-ic"; + reg = <0x7e00b200 0x200>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + interrupts = <0x08 0x04>; + phandle = <0x01>; + }; + + watchdog@7e100000 { + compatible = "brcm,bcm2835-pm\0brcm,bcm2835-pm-wdt"; + #power-domain-cells = <0x01>; + #reset-cells = <0x01>; + reg = <0x7e100000 0x114 0x7e00a000 0x24>; + clocks = <0x08 0x15 0x08 0x1d 0x08 0x17 0x08 0x16>; + clock-names = "v3d\0peri_image\0h264\0isp"; + system-power-controller; + phandle = <0x2d>; + }; + + rng@7e104000 { + compatible = "brcm,bcm2835-rng"; + reg = <0x7e104000 0x10>; + interrupts = <0x02 0x1d>; + phandle = <0x2e>; + }; + + pixelvalve@7e206000 { + compatible = "brcm,bcm2835-pixelvalve0"; + reg = <0x7e206000 0x100>; + interrupts = <0x02 0x0d>; + status = "disabled"; + phandle = <0x7b>; + }; + + pixelvalve@7e207000 { + compatible = "brcm,bcm2835-pixelvalve1"; + reg = <0x7e207000 0x100>; + interrupts = <0x02 0x0e>; + status = "disabled"; + phandle = <0x7c>; + }; + + thermal@7e212000 { + compatible = "brcm,bcm2837-thermal"; + reg = <0x7e212000 0x08>; + clocks = <0x08 0x1b>; + #thermal-sensor-cells = <0x00>; + status = "okay"; + phandle = <0x02>; + }; + + i2c@7e805000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e805000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x1d>; + }; + + vec@7e806000 { + compatible = "brcm,bcm2835-vec"; + reg = <0x7e806000 0x1000>; + clocks = <0x1c 0x0f>; + interrupts = <0x02 0x1b>; + status = "disabled"; + power-domains = <0x14 0x07>; + phandle = <0x7d>; + }; + + pixelvalve@7e807000 { + compatible = "brcm,bcm2835-pixelvalve2"; + reg = <0x7e807000 0x100>; + interrupts = <0x02 0x0a>; + status = "disabled"; + phandle = <0x7e>; + }; + + hdmi@7e902000 { + compatible = "brcm,bcm2835-hdmi"; + reg = <0x7e902000 0x600 0x7e808000 0x100>; + reg-names = "hdmi\0hd"; + interrupts = <0x02 0x08 0x02 0x09>; + ddc = <0x1d>; + clocks = <0x1c 0x09 0x1c 0x0d>; + clock-names = "pixel\0hdmi"; + dmas = <0x0c 0x9000011>; + dma-names = "audio-rx"; + status = "disabled"; + power-domains = <0x14 0x05>; + hpd-gpios = <0x07 0x1c 0x01>; + phandle = <0x7f>; + }; + + v3d@7ec00000 { + compatible = "brcm,vc4-v3d"; + reg = <0x7ec00000 0x1000>; + interrupts = <0x01 0x0a>; + power-domains = <0x14 0x0a>; + status = "disabled"; + phandle = <0x80>; + }; + + gpu { + compatible = "brcm,bcm2835-vc4"; + status = "disabled"; + raspberrypi,firmware = <0x06>; + phandle = <0x81>; + }; + + local_intc@40000000 { + compatible = "brcm,bcm2836-l1-intc"; + reg = <0x40000000 0x100>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + phandle = <0x1b>; + }; + + mmcnr@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + non-removable; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x1e>; + bus-width = <0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x31>; + + wifi@1 { + reg = <0x01>; + compatible = "brcm,bcm4329-fmac"; + phandle = <0x82>; + }; + }; + + firmwarekms@7e600000 { + compatible = "raspberrypi,rpi-firmware-kms"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + brcm,firmware = <0x06>; + status = "disabled"; + phandle = <0x83>; + }; + + smi@7e600000 { + compatible = "brcm,bcm2835-smi"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + clocks = <0x08 0x2a>; + assigned-clocks = <0x08 0x2a>; + assigned-clock-rates = <0x7735940>; + dmas = <0x0c 0x04>; + dma-names = "rx-tx"; + status = "disabled"; + phandle = <0x84>; + }; + + csi@7e800000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e800000 0x800 0x7e802000 0x04>; + interrupts = <0x02 0x06>; + clocks = <0x08 0x2d 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + phandle = <0x85>; + }; + + csi@7e801000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e801000 0x800 0x7e802004 0x04>; + interrupts = <0x02 0x07>; + clocks = <0x08 0x2e 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0d>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + brcm,num-data-lanes = <0x02>; + phandle = <0x86>; + }; + + axiperf { + compatible = "brcm,bcm2835-axiperf"; + reg = <0x7e009800 0x100 0x7ee08000 0x100>; + firmware = <0x06>; + status = "disabled"; + phandle = <0x32>; + }; + + firmware { + compatible = "raspberrypi,bcm2835-firmware\0simple-mfd"; + #address-cells = <0x01>; + #size-cells = <0x01>; + mboxes = <0x1f>; + dma-ranges; + phandle = <0x06>; + + clocks { + compatible = "raspberrypi,firmware-clocks"; + #clock-cells = <0x01>; + phandle = <0x1c>; + }; + + vcio { + compatible = "raspberrypi,vcio"; + phandle = <0x87>; + }; + + expgpio { + compatible = "raspberrypi,firmware-gpio"; + gpio-controller; + #gpio-cells = <0x02>; + gpio-line-names = "BT_ON\0WL_ON\0PWR_LED_R\0LAN_RUN\0NC\0CAM_GPIO0\0CAM_GPIO1\0NC"; + status = "okay"; + phandle = <0x0b>; + }; + }; + + power { + compatible = "raspberrypi,bcm2835-power"; + firmware = <0x06>; + #power-domain-cells = <0x01>; + phandle = <0x14>; + }; + + mailbox@7e00b840 { + compatible = "brcm,bcm2836-vchiq\0brcm,bcm2835-vchiq"; + reg = <0x7e00b840 0x3c>; + interrupts = <0x00 0x02>; + phandle = <0x88>; + + bcm2835_audio { + compatible = "brcm,bcm2835-audio"; + brcm,firmware = <0x06>; + brcm,pwm-channels = <0x08>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x20>; + phandle = <0x2c>; + }; + }; + + gpiomem { + compatible = "brcm,bcm2835-gpiomem"; + reg = <0x7e200000 0x1000>; + }; + + fb { + compatible = "brcm,bcm2708-fb"; + firmware = <0x06>; + status = "okay"; + phandle = <0x89>; + }; + + sound { + status = "disabled"; + phandle = <0x8a>; + }; + }; + + clocks { + + clk-osc { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "osc"; + clock-frequency = <0x124f800>; + phandle = <0x03>; + }; + + clk-usb { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "otg"; + clock-frequency = <0x1c9c3800>; + phandle = <0x19>; + }; + }; + + phy { + compatible = "usb-nop-xceiv"; + #phy-cells = <0x00>; + phandle = <0x1a>; + }; + + arm-pmu { + compatible = "arm,cortex-a53-pmu\0arm,cortex-a7-pmu"; + interrupt-parent = <0x1b>; + interrupts = <0x09 0x04>; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupt-parent = <0x1b>; + interrupts = <0x00 0x04 0x01 0x04 0x03 0x04 0x02 0x04>; + always-on; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + enable-method = "brcm,bcm2836-smp"; + phandle = <0x8b>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x00>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xd8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x22>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x01>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x23>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x02>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x24>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x03>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xf0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x25>; + }; + + l2-cache0 { + compatible = "cache"; + cache-size = <0x80000>; + cache-line-size = <0x40>; + cache-sets = <0x200>; + cache-level = <0x02>; + phandle = <0x21>; + }; + }; + + cam1_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam1-reg"; + enable-active-high; + status = "okay"; + gpio = <0x0b 0x05 0x00>; + phandle = <0x8c>; + }; + + cam1_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8d>; + }; + + cam0_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam0-reg"; + enable-active-high; + status = "disabled"; + phandle = <0x8e>; + }; + + cam0_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8f>; + }; + + cam_dummy_reg { + compatible = "regulator-fixed"; + regulator-name = "cam-dummy-reg"; + status = "okay"; + phandle = <0x90>; + }; + + __overrides__ { + cam0-pwdn-ctrl; + cam0-pwdn; + cam0-led-ctrl; + cam0-led; + arm_freq = "\0\0\0\"clock-frequency:0\0\0\0\0#clock-frequency:0\0\0\0\0$clock-frequency:0\0\0\0\0%clock-frequency:0"; + cache_line_size; + uart0 = "\0\0\0&status"; + uart1 = "\0\0\0'status"; + i2s = "\0\0\0(status"; + spi = "\0\0\0)status"; + i2c0 = [00 00 00 11 73 74 61 74 75 73 00 00 00 00 2a 73 74 61 74 75 73 00]; + i2c1 = "\0\0\0+status"; + i2c0_baudrate = [00 00 00 11 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + i2c1_baudrate = "\0\0\0+clock-frequency:0"; + audio = "\0\0\0,status"; + watchdog = "\0\0\0-status"; + random = "\0\0\0.status"; + sd_overclock = "\0\0\0/brcm,overclock-50:0"; + sd_force_pio = "\0\0\0/brcm,force-pio?"; + sd_pio_limit = "\0\0\0/brcm,pio-limit:0"; + sd_debug = "\0\0\0/brcm,debug"; + sdio_overclock = "\0\0\00brcm,overclock-50:0\0\0\0\01brcm,overclock-50:0"; + axiperf = "\0\0\02status"; + i2c2_iknowwhatimdoing = [00 00 00 1d 73 74 61 74 75 73 00]; + i2c2_baudrate = [00 00 00 1d 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + sd_poll_once = "\0\0\0/non-removable?"; + krnbt = "\0\0\03status"; + krnbt_baudrate = "\0\0\03max-speed:0"; + act_led_gpio = "\0\0\04gpios:4"; + act_led_activelow = "\0\0\04gpios:8"; + act_led_trigger = "\0\0\04linux,default-trigger"; + pwr_led_gpio = "\0\0\05gpios:4"; + pwr_led_activelow = "\0\0\05gpios:8"; + pwr_led_trigger = "\0\0\05linux,default-trigger"; + eee = "\0\0\06microchip,eee-enabled?"; + tx_lpi_timer = "\0\0\06microchip,tx-lpi-timer:0"; + eth_led0 = "\0\0\06microchip,led-modes:0"; + eth_led1 = "\0\0\06microchip,led-modes:4"; + eth_downshift_after = "\0\0\06microchip,downshift-after:0"; + eth_max_speed = "\0\0\06max-speed:0"; + }; + + leds { + compatible = "gpio-leds"; + phandle = <0x91>; + + led-act { + label = "led0"; + default-state = "keep"; + linux,default-trigger = "mmc0"; + gpios = <0x07 0x1d 0x00>; + phandle = <0x34>; + }; + + led-pwr { + label = "led1"; + linux,default-trigger = "default-on"; + gpios = <0x0b 0x02 0x01>; + phandle = <0x35>; + }; + }; + + fixedregulator_3v3 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microvolt = <0x325aa0>; + regulator-name = "3v3"; + phandle = <0x92>; + }; + + fixedregulator_5v0 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x4c4b40>; + regulator-min-microvolt = <0x4c4b40>; + regulator-name = "5v0"; + phandle = <0x93>; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00 0x00>; + }; + + __symbols__ { + rmem = "/reserved-memory"; + cma = "/reserved-memory/linux,cma"; + cpu_thermal = "/thermal-zones/cpu-thermal"; + soc = "/soc"; + txp = "/soc/txp@7e004000"; + clocks = "/soc/cprman@7e101000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + dpi_gpio0 = "/soc/gpio@7e200000/dpi_gpio0"; + emmc_gpio22 = "/soc/gpio@7e200000/emmc_gpio22"; + emmc_gpio34 = "/soc/gpio@7e200000/emmc_gpio34"; + emmc_gpio48 = "/soc/gpio@7e200000/emmc_gpio48"; + gpclk0_gpio4 = "/soc/gpio@7e200000/gpclk0_gpio4"; + gpclk1_gpio5 = "/soc/gpio@7e200000/gpclk1_gpio5"; + gpclk1_gpio42 = "/soc/gpio@7e200000/gpclk1_gpio42"; + gpclk1_gpio44 = "/soc/gpio@7e200000/gpclk1_gpio44"; + gpclk2_gpio6 = "/soc/gpio@7e200000/gpclk2_gpio6"; + gpclk2_gpio43 = "/soc/gpio@7e200000/gpclk2_gpio43"; + i2c0_gpio0 = "/soc/gpio@7e200000/i2c0_gpio0"; + i2c0_gpio28 = "/soc/gpio@7e200000/i2c0_gpio28"; + i2c0_gpio44 = "/soc/gpio@7e200000/i2c0_gpio44"; + i2c1_gpio2 = "/soc/gpio@7e200000/i2c1_gpio2"; + i2c1_gpio44 = "/soc/gpio@7e200000/i2c1_gpio44"; + jtag_gpio22 = "/soc/gpio@7e200000/jtag_gpio22"; + pcm_gpio18 = "/soc/gpio@7e200000/pcm_gpio18"; + pcm_gpio28 = "/soc/gpio@7e200000/pcm_gpio28"; + sdhost_gpio48 = "/soc/gpio@7e200000/sdhost_gpio48"; + spi0_gpio7 = "/soc/gpio@7e200000/spi0_gpio7"; + spi0_gpio35 = "/soc/gpio@7e200000/spi0_gpio35"; + spi1_gpio16 = "/soc/gpio@7e200000/spi1_gpio16"; + spi2_gpio40 = "/soc/gpio@7e200000/spi2_gpio40"; + uart0_gpio14 = "/soc/gpio@7e200000/uart0_gpio14"; + uart0_ctsrts_gpio16 = "/soc/gpio@7e200000/uart0_ctsrts_gpio16"; + uart0_ctsrts_gpio30 = "/soc/gpio@7e200000/uart0_ctsrts_gpio30"; + uart0_gpio32 = "/soc/gpio@7e200000/uart0_gpio32"; + uart0_gpio36 = "/soc/gpio@7e200000/uart0_gpio36"; + uart0_ctsrts_gpio38 = "/soc/gpio@7e200000/uart0_ctsrts_gpio38"; + uart1_gpio14 = "/soc/gpio@7e200000/uart1_gpio14"; + uart1_ctsrts_gpio16 = "/soc/gpio@7e200000/uart1_ctsrts_gpio16"; + uart1_gpio32 = "/soc/gpio@7e200000/uart1_gpio32"; + uart1_ctsrts_gpio30 = "/soc/gpio@7e200000/uart1_ctsrts_gpio30"; + uart1_gpio40 = "/soc/gpio@7e200000/uart1_gpio40"; + uart1_ctsrts_gpio42 = "/soc/gpio@7e200000/uart1_ctsrts_gpio42"; + i2c_slave_gpio18 = "/soc/gpio@7e200000/i2c_slave_gpio18"; + jtag_gpio4 = "/soc/gpio@7e200000/jtag_gpio4"; + pwm0_gpio12 = "/soc/gpio@7e200000/pwm0_gpio12"; + pwm0_gpio18 = "/soc/gpio@7e200000/pwm0_gpio18"; + pwm0_gpio40 = "/soc/gpio@7e200000/pwm0_gpio40"; + pwm1_gpio13 = "/soc/gpio@7e200000/pwm1_gpio13"; + pwm1_gpio19 = "/soc/gpio@7e200000/pwm1_gpio19"; + pwm1_gpio41 = "/soc/gpio@7e200000/pwm1_gpio41"; + pwm1_gpio45 = "/soc/gpio@7e200000/pwm1_gpio45"; + dpi_18bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio0"; + dpi_18bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio2"; + dpi_18bit_gpio0 = "/soc/gpio@7e200000/dpi_18bit_gpio0"; + dpi_18bit_gpio2 = "/soc/gpio@7e200000/dpi_18bit_gpio2"; + dpi_16bit_gpio0 = "/soc/gpio@7e200000/dpi_16bit_gpio0"; + dpi_16bit_gpio2 = "/soc/gpio@7e200000/dpi_16bit_gpio2"; + dpi_16bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio0"; + dpi_16bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio2"; + gpioout = "/soc/gpio@7e200000/gpioout"; + alt0 = "/soc/gpio@7e200000/alt0"; + spi0_pins = "/soc/gpio@7e200000/spi0_pins"; + spi0_cs_pins = "/soc/gpio@7e200000/spi0_cs_pins"; + i2c0_pins = "/soc/gpio@7e200000/i2c0"; + i2c1_pins = "/soc/gpio@7e200000/i2c1"; + i2s_pins = "/soc/gpio@7e200000/i2s"; + sdio_pins = "/soc/gpio@7e200000/sdio_pins"; + bt_pins = "/soc/gpio@7e200000/bt_pins"; + uart0_pins = "/soc/gpio@7e200000/uart0_pins"; + uart1_pins = "/soc/gpio@7e200000/uart1_pins"; + audio_pins = "/soc/gpio@7e200000/audio_pins"; + uart0 = "/soc/serial@7e201000"; + bt = "/soc/serial@7e201000/bluetooth"; + sdhost = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + spi0 = "/soc/spi@7e204000"; + spi = "/soc/spi@7e204000"; + spidev0 = "/soc/spi@7e204000/spidev@0"; + spidev1 = "/soc/spi@7e204000/spidev@1"; + i2c0if = "/soc/i2c@7e205000"; + i2c0mux = "/soc/i2c0mux"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c_csi_dsi = "/soc/i2c0mux/i2c@1"; + dpi = "/soc/dpi@7e208000"; + dsi0 = "/soc/dsi@7e209000"; + aux = "/soc/aux@7e215000"; + uart1 = "/soc/serial@7e215040"; + minibt = "/soc/serial@7e215040/bluetooth"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + pwm = "/soc/pwm@7e20c000"; + mmc = "/soc/mmc@7e300000"; + sdhci = "/soc/mmc@7e300000"; + hvs = "/soc/hvs@7e400000"; + dsi1 = "/soc/dsi@7e700000"; + i2c1 = "/soc/i2c@7e804000"; + usb = "/soc/usb@7e980000"; + ethernet = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + eth_phy = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1/mdio/ethernet-phy@1"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + pm = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + pixelvalve0 = "/soc/pixelvalve@7e206000"; + pixelvalve1 = "/soc/pixelvalve@7e207000"; + thermal = "/soc/thermal@7e212000"; + i2c2 = "/soc/i2c@7e805000"; + vec = "/soc/vec@7e806000"; + pixelvalve2 = "/soc/pixelvalve@7e807000"; + hdmi = "/soc/hdmi@7e902000"; + v3d = "/soc/v3d@7ec00000"; + vc4 = "/soc/gpu"; + local_intc = "/soc/local_intc@40000000"; + mmcnr = "/soc/mmcnr@7e300000"; + brcmf = "/soc/mmcnr@7e300000/wifi@1"; + firmwarekms = "/soc/firmwarekms@7e600000"; + smi = "/soc/smi@7e600000"; + csi0 = "/soc/csi@7e800000"; + csi1 = "/soc/csi@7e801000"; + axiperf = "/soc/axiperf"; + firmware = "/soc/firmware"; + firmware_clocks = "/soc/firmware/clocks"; + vcio = "/soc/firmware/vcio"; + expgpio = "/soc/firmware/expgpio"; + power = "/soc/power"; + vchiq = "/soc/mailbox@7e00b840"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + fb = "/soc/fb"; + sound = "/soc/sound"; + clk_osc = "/clocks/clk-osc"; + clk_usb = "/clocks/clk-usb"; + usbphy = "/phy"; + cpus = "/cpus"; + cpu0 = "/cpus/cpu@0"; + cpu1 = "/cpus/cpu@1"; + cpu2 = "/cpus/cpu@2"; + cpu3 = "/cpus/cpu@3"; + l2 = "/cpus/l2-cache0"; + cam1_reg = "/cam1_regulator"; + cam1_clk = "/cam1_clk"; + cam0_regulator = "/cam0_regulator"; + cam0_clk = "/cam0_clk"; + cam0_reg = "/cam_dummy_reg"; + cam_dummy_reg = "/cam_dummy_reg"; + leds = "/leds"; + act_led = "/leds/led-act"; + pwr_led = "/leds/led-pwr"; + vdd_3v3_reg = "/fixedregulator_3v3"; + vdd_5v0_reg = "/fixedregulator_5v0"; + }; +}; diff --git a/lab4/test/lib/dtb_parse/types.h b/lab4/test/lib/dtb_parse/types.h new file mode 100644 index 000000000..94f612c66 --- /dev/null +++ b/lab4/test/lib/dtb_parse/types.h @@ -0,0 +1,26 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#define NULL ((void*)0) + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) +#endif diff --git a/lab4/test/lib/list/Makefile b/lab4/test/lib/list/Makefile new file mode 100644 index 000000000..764af75c6 --- /dev/null +++ b/lab4/test/lib/list/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/list.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab4/test/lib/list/test b/lab4/test/lib/list/test new file mode 100755 index 000000000..dd63c9895 Binary files /dev/null and b/lab4/test/lib/list/test differ diff --git a/lab4/test/lib/list/test.c b/lab4/test/lib/list/test.c new file mode 100644 index 000000000..b568a42a4 --- /dev/null +++ b/lab4/test/lib/list/test.c @@ -0,0 +1,59 @@ +#include "lib/list.h" +#include +#include +#include +struct student{ + int id; + char name[100]; + struct list_head list; +}; + +struct student* create_student(int id, char* name){ + struct student* s = (struct student*)malloc(sizeof(struct student)); + s->id = id; + strcpy(s->name, name); + return s; +} +void print_student(struct student* s){ + printf("------------------------------------------\n"); + printf(" id: %d\n", s->id); + printf(" name: %s\n", s->name); + printf("------------------------------------------\n"); +} +int main(void){ + struct list_head* node, head; + INIT_LIST_HEAD(&head); + + if(list_empty(&head)){ + printf("List is empty\n"); + } + list_add(&create_student(13, "xiaobye")->list, &head); + list_add(&create_student(35, "test01")->list, &head); + list_add(&create_student(34, "test02")->list, &head); + + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + if(!list_empty(&head)){ + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + } + + + return 0; +} + diff --git a/lab4/test/lib/malloc/.gdb_history b/lab4/test/lib/malloc/.gdb_history new file mode 100644 index 000000000..1b332373d --- /dev/null +++ b/lab4/test/lib/malloc/.gdb_history @@ -0,0 +1,9 @@ +b main +run +ni +x/gx $rax +x/gx $rax - 0x10 + call malloc(1) +x/gx $rax - 0x10 +x/gx 0x5555555592c0 +quit diff --git a/lab4/test/lib/malloc/Makefile b/lab4/test/lib/malloc/Makefile new file mode 100644 index 000000000..2aedecaf1 --- /dev/null +++ b/lab4/test/lib/malloc/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/simple_malloc.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab4/test/lib/malloc/test b/lab4/test/lib/malloc/test new file mode 100755 index 000000000..194c23579 Binary files /dev/null and b/lab4/test/lib/malloc/test differ diff --git a/lab4/test/lib/malloc/test.c b/lab4/test/lib/malloc/test.c new file mode 100644 index 000000000..374f6deff --- /dev/null +++ b/lab4/test/lib/malloc/test.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include "lib/simple_malloc.h" + +#define RANGE 1000 +int main(void){ + void* cur,* next; + size_t req_size, real_size; + void* p = mmap( NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 ); + init_malloc_state(p); + srand((unsigned)time(0)); + + for(int i = 0 ; i < 30 ; i++){ + req_size = (uint64_t)rand() % RANGE; + cur = simple_malloc(req_size); + next = get_remainder(); + real_size = (uint64_t)next - (uint64_t)cur; + printf("cur: %p, next: %p, request size: %lu, real size: %lu, legal: %d\n", cur, next , req_size, real_size, (req_size <= real_size) && !(real_size % 16)); + } + + return 0; +} diff --git a/lab4/test/lib/malloc/test.py b/lab4/test/lib/malloc/test.py new file mode 100644 index 000000000..cce0d171c --- /dev/null +++ b/lab4/test/lib/malloc/test.py @@ -0,0 +1,9 @@ +def req2size(val, a): + if val < 16: + print(val,": ", hex(32)) + else: + print(val,": ",hex((val + 16 + (a - 1)) & ~(a-1))) + +for i in range(0, 64): + req2size(i, 16) + diff --git a/lab4/test/lib/ring_buffer/.gdb_history b/lab4/test/lib/ring_buffer/.gdb_history new file mode 100644 index 000000000..b7bc3d7af --- /dev/null +++ b/lab4/test/lib/ring_buffer/.gdb_history @@ -0,0 +1,17 @@ +run +quit +file main +run +p rbuf +quit +quit +run +x/gx 0x555555556008 +p rbuf->buf[rbuf->head] +s +ni +quit +b main +run +n +quit diff --git a/lab4/test/lib/ring_buffer/Makefile b/lab4/test/lib/ring_buffer/Makefile new file mode 100644 index 000000000..ec3d806b1 --- /dev/null +++ b/lab4/test/lib/ring_buffer/Makefile @@ -0,0 +1,2 @@ +all: + gcc main.c ring_buffer.c -o main -g -O0 diff --git a/lab4/test/lib/ring_buffer/main b/lab4/test/lib/ring_buffer/main new file mode 100755 index 000000000..bc8cc09fa Binary files /dev/null and b/lab4/test/lib/ring_buffer/main differ diff --git a/lab4/test/lib/ring_buffer/main.c b/lab4/test/lib/ring_buffer/main.c new file mode 100644 index 000000000..ea70d0e9b --- /dev/null +++ b/lab4/test/lib/ring_buffer/main.c @@ -0,0 +1,50 @@ +#include "ring_buffer.h" +#include +#include +char* s = "abcdefghijklmn"; +int main(void){ + char b[10]; + ring_buffer* rbuf = create_ring_buf(10); + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } + + ring_buf_write(rbuf, s, 8); + + if(!ring_buf_is_empty(rbuf)){ + printf("Ring buffer is has some contant now!\n"); + int i = ring_buf_read(rbuf, b, 100); + b[i] = '\0'; + + printf("%d: %s\n", i, b); + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } + } + printf("%lu\n", ring_buf_write(rbuf, s, 16)); + if(ring_buf_is_full(rbuf)){ + printf("Ring buffer is full now!\n"); + } + + int i = ring_buf_read(rbuf, b, 4); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + i = ring_buf_write(rbuf, b, 10); + printf("%d\n", i); + + i = ring_buf_read(rbuf, b, 7); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + i = ring_buf_read(rbuf, b, 10); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + if(ring_buf_is_full(rbuf)){ + printf("Ring buffer is full now!\n"); + } + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } +} diff --git a/lab4/test/lib/ring_buffer/ring_buffer.c b/lab4/test/lib/ring_buffer/ring_buffer.c new file mode 100644 index 000000000..a5e7e3612 --- /dev/null +++ b/lab4/test/lib/ring_buffer/ring_buffer.c @@ -0,0 +1,42 @@ +#include "ring_buffer.h" +#include +ring_buffer* create_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)malloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)malloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + return tmp; +} + +uint8_t ring_buf_is_empty(ring_buffer* rbuf){ + if(rbuf->head == rbuf->tail) return 1; + return 0; +} +uint8_t ring_buf_is_full(ring_buffer* rbuf){ + if((rbuf->tail + 1) % (rbuf->size + 1) == rbuf->head) return 1; + return 0; +} +size_t ring_buf_write(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + return count; +} +size_t ring_buf_read(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + return count; +} + diff --git a/lab4/test/lib/ring_buffer/ring_buffer.h b/lab4/test/lib/ring_buffer/ring_buffer.h new file mode 100644 index 000000000..61c0431d4 --- /dev/null +++ b/lab4/test/lib/ring_buffer/ring_buffer.h @@ -0,0 +1,17 @@ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ +#include "types.h" + +typedef struct{ + size_t size; + uint64_t head; + uint64_t tail; + uint8_t* buf; +}ring_buffer; + +extern ring_buffer* create_ring_buf(size_t); +extern size_t ring_buf_write(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read(ring_buffer*, uint8_t*, size_t); +extern uint8_t ring_buf_is_full(ring_buffer*); +extern uint8_t ring_buf_is_empty(ring_buffer*); +#endif diff --git a/lab4/test/lib/ring_buffer/types.h b/lab4/test/lib/ring_buffer/types.h new file mode 100644 index 000000000..94f612c66 --- /dev/null +++ b/lab4/test/lib/ring_buffer/types.h @@ -0,0 +1,26 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#define NULL ((void*)0) + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) +#endif diff --git a/lab4/test/lib/string/.gdb_history b/lab4/test/lib/string/.gdb_history new file mode 100644 index 000000000..d0d68342a --- /dev/null +++ b/lab4/test/lib/string/.gdb_history @@ -0,0 +1,47 @@ +b main +run +n +quit +run +b main +run +n +quit +b main +run +n +run +n +s +s +n +x/gx rax +x/gx $rax +run +s +n +s +x/bx s +s +p c +n +n +quit +b main +run +s +x/s delim +s +s +ni +n +ni +x/s s +x/s pos +x/b pos +x/bx pos +n +n +s +s +quit diff --git a/lab4/test/lib/string/Makefile b/lab4/test/lib/string/Makefile new file mode 100644 index 000000000..e7e0f12c1 --- /dev/null +++ b/lab4/test/lib/string/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/string.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab4/test/lib/string/test b/lab4/test/lib/string/test new file mode 100755 index 000000000..a0a7ea144 Binary files /dev/null and b/lab4/test/lib/string/test differ diff --git a/lab4/test/lib/string/test.c b/lab4/test/lib/string/test.c new file mode 100644 index 000000000..b23d13172 --- /dev/null +++ b/lab4/test/lib/string/test.c @@ -0,0 +1,31 @@ + +// C code to demonstrate working of +// strtok +#include +#include "string.h" + +// Driver function +int main() +{ + // Declaration of string + char *gfg = "setTimeout 123"; + + // Declaration of delimiter + const char s[4] = "-"; + char* tok; + + // Use of strtok + // get first token + tok = strtok(gfg, s); + + // Checks for delimiter + while (tok != 0) { + printf(" %s\n", tok); + + // Use of strtok + // go through other tokens + tok = strtok(0, s); + } + + return (0); +} diff --git a/lab4/tmp b/lab4/tmp new file mode 100644 index 000000000..cfe6ea8df --- /dev/null +++ b/lab4/tmp @@ -0,0 +1,1449 @@ +sudo qemu-system-aarch64 -M raspi3b -kernel /home/xiaobye/Documents/OSDI/osc2022/lab2/build/kernel8.img -display none -serial null -serial stdio -initrd tools/cpio/initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + { + compatible ; + model ; + #address-cells ; + #size-cells ; + interrupt-parent ; + memory@0 { + reg ; + device_type ; + } + aliases { + serial0 ; + serial1 ; + audio ; + aux ; + sound ; + soc ; + dma ; + intc ; + watchdog ; + random ; + mailbox ; + gpio ; + uart0 ; + uart1 ; + sdhost ; + mmc ; + mmc1 ; + mmc0 ; + i2s ; + i2c0 ; + i2c1 ; + i2c10 ; + spi0 ; + spi1 ; + spi2 ; + usb ; + leds ; + fb ; + thermal ; + axiperf ; + i2c2 ; + ethernet0 ; + } + chosen { + linux,initrd-end ; + linux,initrd-start ; + bootargs ; + } + reserved-memory { + #address-cells ; + #size-cells ; + ranges ; + phandle ; + linux,cma { + compatible ; + size ; + reusable ; + linux,cma-default ; + phandle ; + } + } + thermal-zones { + cpu-thermal { + polling-delay-passive ; + polling-delay ; + thermal-sensors ; + coefficients ; + phandle ; + cooling-maps { + } + } + } + soc { + compatible ; + #address-cells ; + #size-cells ; + ranges ; + dma-ranges ; + phandle ; + txp@7e004000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + cprman@7e101000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + firmware ; + phandle ; + } + mailbox@7e00b880 { + compatible ; + reg ; + interrupts ; + #mbox-cells ; + phandle ; + } + gpio@7e200000 { + compatible ; + reg ; + interrupts ; + gpio-controller ; + #gpio-cells ; + interrupt-controller ; + #interrupt-cells ; + gpio-ranges ; + pinctrl-names ; + gpio-line-names ; + phandle ; + dpi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio34 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + emmc_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk0_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio5 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio6 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio43 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + i2c0_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + sdhost_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio7 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio35 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi1_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi2_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio32 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio36 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio38 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio32 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c_slave_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio12 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio13 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio19 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio41 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio45 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + dpi_18bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpioout { + brcm,pins ; + brcm,function ; + phandle ; + } + alt0 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_cs_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2s { + brcm,pins ; + brcm,function ; + phandle ; + } + sdio_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + bt_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart1_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + audio_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + } + serial@7e201000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + arm,primecell-periphid ; + cts-event-workaround ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + status ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + mmc@7e202000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + bus-width ; + brcm,overclock-50 ; + brcm,pio-limit ; + firmware ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + i2s@7e203000 { + compatible ; + reg ; + clocks ; + status ; + dmas ; + dma-names ; + #sound-dai-cells ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + spi@7e204000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + dmas ; + dma-names ; + pinctrl-names ; + pinctrl-0 ; + cs-gpios ; + phandle ; + spidev@0 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + spidev@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + } + i2c@7e205000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + i2c0mux { + compatible ; + #address-cells ; + #size-cells ; + i2c-parent ; + pinctrl-names ; + status ; + pinctrl-0 ; + pinctrl-1 ; + phandle ; + i2c@0 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + i2c@1 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + } + dpi@7e208000 { + compatible ; + reg ; + clocks ; + clock-names ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + dsi@7e209000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + aux@7e215000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + phandle ; + } + serial@7e215040 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + spi@7e215080 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + spi@7e2150c0 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + pwm@7e20c000 { + compatible ; + reg ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + #pwm-cells ; + status ; + phandle ; + } + mmc@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + brcm,overclock-50 ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + phandle ; + } + hvs@7e400000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + dsi@7e700000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + i2c@7e804000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + pinctrl-names ; + pinctrl-0 ; + clock-frequency ; + phandle ; + } + usb@7e980000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + clocks ; + clock-names ; + phys ; + phy-names ; + interrupt-names ; + power-domains ; + phandle ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + ethernet@1 { + compatible ; + reg ; + phandle ; + mdio { + #address-cells ; + #size-cells ; + ethernet-phy@1 { + reg ; + microchip,led-modes ; + microchip,eee-enabled ; + microchip,tx-lpi-timer ; + microchip,downshift-after ; + phandle ; + } + } + } + } + } + } + dma@7e007000 { + compatible ; + reg ; + interrupts ; + interrupt-names ; + #dma-cells ; + brcm,dma-channel-mask ; + phandle ; + } + interrupt-controller@7e00b200 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + interrupts ; + phandle ; + } + watchdog@7e100000 { + compatible ; + #power-domain-cells ; + #reset-cells ; + reg ; + clocks ; + clock-names ; + system-power-controller ; + phandle ; + } + rng@7e104000 { + compatible ; + reg ; + interrupts ; + phandle ; + } + pixelvalve@7e206000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + pixelvalve@7e207000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + thermal@7e212000 { + compatible ; + reg ; + clocks ; + #thermal-sensor-cells ; + status ; + phandle ; + } + i2c@7e805000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + vec@7e806000 { + compatible ; + reg ; + clocks ; + interrupts ; + status ; + power-domains ; + phandle ; + } + pixelvalve@7e807000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + hdmi@7e902000 { + compatible ; + reg ; + reg-names ; + interrupts ; + ddc ; + clocks ; + clock-names ; + dmas ; + dma-names ; + status ; + power-domains ; + hpd-gpios ; + phandle ; + } + v3d@7ec00000 { + compatible ; + reg ; + interrupts ; + power-domains ; + status ; + phandle ; + } + gpu { + compatible ; + status ; + raspberrypi,firmware ; + phandle ; + } + local_intc@40000000 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + phandle ; + } + mmcnr@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + dmas ; + dma-names ; + brcm,overclock-50 ; + non-removable ; + status ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + #address-cells ; + #size-cells ; + phandle ; + wifi@1 { + reg ; + compatible ; + phandle ; + } + } + firmwarekms@7e600000 { + compatible ; + reg ; + interrupts ; + brcm,firmware ; + status ; + phandle ; + } + smi@7e600000 { + compatible ; + reg ; + interrupts ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + dmas ; + dma-names ; + status ; + phandle ; + } + csi@7e800000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + phandle ; + } + csi@7e801000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + brcm,num-data-lanes ; + phandle ; + } + axiperf { + compatible ; + reg ; + firmware ; + status ; + phandle ; + } + firmware { + compatible ; + #address-cells ; + #size-cells ; + mboxes ; + dma-ranges ; + phandle ; + clocks { + compatible ; + #clock-cells ; + phandle ; + } + vcio { + compatible ; + phandle ; + } + expgpio { + compatible ; + gpio-controller ; + #gpio-cells ; + gpio-line-names ; + status ; + phandle ; + } + } + power { + compatible ; + firmware ; + #power-domain-cells ; + phandle ; + } + mailbox@7e00b840 { + compatible ; + reg ; + interrupts ; + phandle ; + bcm2835_audio { + compatible ; + brcm,firmware ; + brcm,pwm-channels ; + status ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + } + gpiomem { + compatible ; + reg ; + } + fb { + compatible ; + firmware ; + status ; + phandle ; + } + sound { + status ; + phandle ; + } + } + clocks { + clk-osc { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + clk-usb { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + } + phy { + compatible ; + #phy-cells ; + phandle ; + } + arm-pmu { + compatible ; + interrupt-parent ; + interrupts ; + } + timer { + compatible ; + interrupt-parent ; + interrupts ; + always-on ; + } + cpus { + #address-cells ; + #size-cells ; + enable-method ; + phandle ; + cpu@0 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@1 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@2 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@3 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + l2-cache0 { + compatible ; + cache-size ; + cache-line-size ; + cache-sets ; + cache-level ; + phandle ; + } + } + cam1_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + gpio ; + phandle ; + } + cam1_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam0_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + phandle ; + } + cam0_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam_dummy_reg { + compatible ; + regulator-name ; + status ; + phandle ; + } + __overrides__ { + cam0-pwdn-ctrl ; + cam0-pwdn ; + cam0-led-ctrl ; + cam0-led ; + arm_freq ; + cache_line_size ; + uart0 ; + uart1 ; + i2s ; + spi ; + i2c0 ; + i2c1 ; + i2c0_baudrate ; + i2c1_baudrate ; + audio ; + watchdog ; + random ; + sd_overclock ; + sd_force_pio ; + sd_pio_limit ; + sd_debug ; + sdio_overclock ; + axiperf ; + i2c2_iknowwhatimdoing ; + i2c2_baudrate ; + sd_poll_once ; + krnbt ; + krnbt_baudrate ; + act_led_gpio ; + act_led_activelow ; + act_led_trigger ; + pwr_led_gpio ; + pwr_led_activelow ; + pwr_led_trigger ; + eee ; + tx_lpi_timer ; + eth_led0 ; + eth_led1 ; + eth_downshift_after ; + eth_max_speed ; + } + leds { + compatible ; + phandle ; + led-act { + label ; + default-state ; + linux,default-trigger ; + gpios ; + phandle ; + } + led-pwr { + label ; + linux,default-trigger ; + gpios ; + phandle ; + } + } + fixedregulator_3v3 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + fixedregulator_5v0 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + __symbols__ { + rmem ; + cma ; + cpu_thermal ; + soc ; + txp ; + clocks ; + mailbox ; + gpio ; + dpi_gpio0 ; + emmc_gpio22 ; + emmc_gpio34 ; + emmc_gpio48 ; + gpclk0_gpio4 ; + gpclk1_gpio5 ; + gpclk1_gpio42 ; + gpclk1_gpio44 ; + gpclk2_gpio6 ; + gpclk2_gpio43 ; + i2c0_gpio0 ; + i2c0_gpio28 ; + i2c0_gpio44 ; + i2c1_gpio2 ; + i2c1_gpio44 ; + jtag_gpio22 ; + pcm_gpio18 ; + pcm_gpio28 ; + sdhost_gpio48 ; + spi0_gpio7 ; + spi0_gpio35 ; + spi1_gpio16 ; + spi2_gpio40 ; + uart0_gpio14 ; + uart0_ctsrts_gpio16 ; + uart0_ctsrts_gpio30 ; + uart0_gpio32 ; + uart0_gpio36 ; + uart0_ctsrts_gpio38 ; + uart1_gpio14 ; + uart1_ctsrts_gpio16 ; + uart1_gpio32 ; + uart1_ctsrts_gpio30 ; + uart1_gpio40 ; + uart1_ctsrts_gpio42 ; + i2c_slave_gpio18 ; + jtag_gpio4 ; + pwm0_gpio12 ; + pwm0_gpio18 ; + pwm0_gpio40 ; + pwm1_gpio13 ; + pwm1_gpio19 ; + pwm1_gpio41 ; + pwm1_gpio45 ; + dpi_18bit_cpadhi_gpio0 ; + dpi_18bit_cpadhi_gpio2 ; + dpi_18bit_gpio0 ; + dpi_18bit_gpio2 ; + dpi_16bit_gpio0 ; + dpi_16bit_gpio2 ; + dpi_16bit_cpadhi_gpio0 ; + dpi_16bit_cpadhi_gpio2 ; + gpioout ; + alt0 ; + spi0_pins ; + spi0_cs_pins ; + i2c0_pins ; + i2c1_pins ; + i2s_pins ; + sdio_pins ; + bt_pins ; + uart0_pins ; + uart1_pins ; + audio_pins ; + uart0 ; + bt ; + sdhost ; + i2s ; + spi0 ; + spi ; + spidev0 ; + spidev1 ; + i2c0if ; + i2c0mux ; + i2c0 ; + i2c_csi_dsi ; + dpi ; + dsi0 ; + aux ; + uart1 ; + minibt ; + spi1 ; + spi2 ; + pwm ; + mmc ; + sdhci ; + hvs ; + dsi1 ; + i2c1 ; + usb ; + ethernet ; + eth_phy ; + dma ; + intc ; + watchdog ; + pm ; + random ; + pixelvalve0 ; + pixelvalve1 ; + thermal ; + i2c2 ; + vec ; + pixelvalve2 ; + hdmi ; + v3d ; + vc4 ; + local_intc ; + mmcnr ; + brcmf ; + firmwarekms ; + smi ; + csi0 ; + csi1 ; + axiperf ; + firmware ; + firmware_clocks ; + vcio ; + expgpio ; + power ; + vchiq ; + audio ; + fb ; + sound ; + clk_osc ; + clk_usb ; + usbphy ; + cpus ; + cpu0 ; + cpu1 ; + cpu2 ; + cpu3 ; + l2 ; + cam1_reg ; + cam1_clk ; + cam0_regulator ; + cam0_clk ; + cam0_reg ; + cam_dummy_reg ; + leds ; + act_led ; + pwr_led ; + vdd_3v3_reg ; + vdd_5v0_reg ; + } +} +[simple_malloc.c/init_malloc_state:12] Simple heap start address: 0x8e000 + +[initrdfs.c/initrdfs_init:7] Enter initrdfs_int +[initrdfs.c/initrdfs_init:8] initrd start at 0x8000000 + +[initrdfs.c/initrdfs_init:9] initrd first 4 bytes: 37303730 + +[initrdfs.c/initrdfs_init:23] Start parsing new ascii format's cpio +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 2 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 112, iter->cur: 0x8000070 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: . +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 21 +[cpio.c/cpio_iter_parse:38] f->namesize: 6 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 140, iter->cur: 0x80000fc +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file1 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 34 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 156, iter->cur: 0x8000198 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file2.txt +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 5 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 116, iter->cur: 0x800020c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 5 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 128, iter->cur: 0x800028c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test/1234 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 0 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 11 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 124, iter->cur: 0x8000308 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: TRAILER!!! +[initrdfs.c/initrdfs_init:32] Leave initrdfs_int +text_start=0x80000, text_end=0x84000, text_size=16384 +rodata_start=0x84000, rodata_end=0x86000, rodata_size=8192 +data_start=0x86000, data_end=0x87000, data_size=4096 +bss_start=0x87000, bss_end=0x8e000, bss_size=28672 +heap_start=0x8e000 +⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀ +⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀ +⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁ +⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀ +⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀ +⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀ +⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀ +⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀ +⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀ +⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀ +⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀ +⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀ +⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀ + +# diff --git a/lab4/tools/AUX_PERIPHERALS b/lab4/tools/AUX_PERIPHERALS new file mode 100644 index 000000000..324eb3019 --- /dev/null +++ b/lab4/tools/AUX_PERIPHERALS @@ -0,0 +1,23 @@ +0x7E215000 AUX_IRQ Auxiliary Interrupt status 3 +0x7E215004 AUX_ENABLES Auxiliary enables 3 +0x7E215040 AUX_MU_IO_REG Mini Uart I/O Data 8 +0x7E215044 AUX_MU_IER_REG Mini Uart Interrupt Enable 8 +0x7E215048 AUX_MU_IIR_REG Mini Uart Interrupt Identify 8 +0x7E21504C AUX_MU_LCR_REG Mini Uart Line Control 8 +0x7E215050 AUX_MU_MCR_REG Mini Uart Modem Control 8 +0x7E215054 AUX_MU_LSR_REG Mini Uart Line Status 8 +0x7E215058 AUX_MU_MSR_REG Mini Uart Modem Status 8 +0x7E21505C AUX_MU_SCRATCH Mini Uart Scratch 8 +0x7E215060 AUX_MU_CNTL_REG Mini Uart Extra Control 8 +0x7E215064 AUX_MU_STAT_REG Mini Uart Extra Status 32 +0x7E215068 AUX_MU_BAUD_REG Mini Uart Baudrate 16 +0x7E215080 AUX_SPI0_CNTL0_REG SPI 1 Control register 0 32 +0x7E215084 AUX_SPI0_CNTL1_REG SPI 1 Control register 1 8 +0x7E215088 AUX_SPI0_STAT_REG SPI 1 Status 32 +0x7E215090 AUX_SPI0_IO_REG SPI 1 Data 32 +0x7E215094 AUX_SPI0_PEEK_REG SPI 1 Peek 16 +0x7E2150C0 AUX_SPI1_CNTL0_REG SPI 2 Control register 0 32 +0x7E2150C4 AUX_SPI1_CNTL1_REG SPI 2 Control register 1 8 +0x7E2150C8 AUX_SPI1_STAT_REG SPI 2 Status 32 +0x7E2150D0 AUX_SPI1_IO_REG SPI 2 Data 32 +0x7E2150D4 AUX_SPI1_PEEK_REG SPI 2 Peek 16 diff --git a/lab4/tools/GPIO b/lab4/tools/GPIO new file mode 100644 index 000000000..ad2b10794 --- /dev/null +++ b/lab4/tools/GPIO @@ -0,0 +1,43 @@ +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200004 GPFSEL1 GPIO Function Select 1 32 R/W +0x7E200008 GPFSEL2 GPIO Function Select 2 32 R/W +0x7E20000C GPFSEL3 GPIO Function Select 3 32 R/W +0x7E200010 GPFSEL4 GPIO Function Select 4 32 R/W +0x7E200014 GPFSEL5 GPIO Function Select 5 32 R/W +0x7E200018 - Reserved - - +0x7E20001C GPSET0 GPIO Pin Output Set 0 32 W +0x7E200020 GPSET1 GPIO Pin Output Set 1 32 W +0x7E200024 - Reserved - - +0x7E200028 GPCLR0 GPIO Pin Output Clear 0 32 W +0x7E20002C GPCLR1 GPIO Pin Output Clear 1 32 W +0x7E200030 - Reserved - - +0x7E200034 GPLEV0 GPIO Pin Level 0 32 R +0x7E200038 GPLEV1 GPIO Pin Level 1 32 R +0x7E20003C - Reserved - - +0x7E200040 GPEDS0 GPIO Pin Event Detect Status 0 32 R/W +0x7E200044 GPEDS1 GPIO Pin Event Detect Status 1 32 R/W +0x7E200048 - Reserved - - +0x7E20004C GPREN0 GPIO Pin Rising Edge Detect Enable 0 32 R/W +0x7E200050 GPREN1 GPIO Pin Rising Edge Detect Enable 1 32 R/W +0x7E200054 - Reserved - - +0x7E200058 GPFEN0 GPIO Pin Falling Edge Detect Enable 0 32 R/W +0x7E20005C GPFEN1 GPIO Pin Falling Edge Detect Enable 1 32 R/W +0x7E200060 - Reserved - - +0x7E200064 GPHEN0 GPIO Pin High Detect Enable 0 32 R/W +0x7E200068 GPHEN1 GPIO Pin High Detect Enable 1 32 R/W +0x7E20006C - Reserved - - +0x7E200070 GPLEN0 GPIO Pin Low Detect Enable 0 32 R/W +0x7E200074 GPLEN1 GPIO Pin Low Detect Enable 1 32 R/W +0x7E200078 - Reserved - - +0x7E20007C GPAREN0 GPIO Pin Async. Rising Edge Detect 0 32 R/W +0x7E200080 GPAREN1 GPIO Pin Async. Rising Edge Detect 1 32 R/W +0x7E200084 - Reserved - - +0x7E200088 GPAFEN0 GPIO Pin Async. Falling Edge Detect 0 32 R/W +0x7E20008C GPAFEN1 GPIO Pin Async. Falling Edge Detect 1 32 R/W +0x7E200090 - Reserved - - +0x7E200094 GPPUD GPIO Pin Pull-up/down Enable 32 R/W +0x7E200098 GPPUDCLK0 GPIO Pin Pull-up/down Enable Clock 0 32 R/W +0x7E20009C GPPUDCLK1 GPIO Pin Pull-up/down Enable Clock 1 32 R/W +0x7E2000A0 - Reserved - - +0x7E2000B0 - Test 4 R/W diff --git a/lab4/tools/cpio/Makefile b/lab4/tools/cpio/Makefile new file mode 100644 index 000000000..1cbe92c74 --- /dev/null +++ b/lab4/tools/cpio/Makefile @@ -0,0 +1,35 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +override CFLAGS += \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin \ + +LDFLAGS ?= \ + -nostdlib \ + +CXXFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJDUMP = aarch64-linux-gnu-objdump +QEMU = qemu-system-aarch64 +RASPI_VER = raspi3b + + +LINKER_FILE = ./linker.ld +HEADERS = $(PWD)/include/ +OUTPUT = $(PWD)/build +KNAME = kernel8 +BNAME = bootloader + +.PHONY: all + + +all: + $(CC) -c -o test.o test.S $(CFLAGS) + $(LD) -T linker.ld -o test.elf test.o $(LDFLAGS) + $(OBJCOPY) -O binary test.elf test.img + diff --git a/lab4/tools/cpio/create_initramfs.sh b/lab4/tools/cpio/create_initramfs.sh new file mode 100755 index 000000000..2736e47fe --- /dev/null +++ b/lab4/tools/cpio/create_initramfs.sh @@ -0,0 +1,4 @@ +#! /bin/sh +cd rootfs +find . | cpio -o -H newc > ../initramfs.cpio +cd .. diff --git a/lab4/tools/cpio/initramfs.cpio b/lab4/tools/cpio/initramfs.cpio new file mode 100644 index 000000000..98a9c8fae Binary files /dev/null and b/lab4/tools/cpio/initramfs.cpio differ diff --git a/lab4/tools/cpio/linker.ld b/lab4/tools/cpio/linker.ld new file mode 100644 index 000000000..a550bf32e --- /dev/null +++ b/lab4/tools/cpio/linker.ld @@ -0,0 +1,41 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + +} diff --git a/lab4/tools/cpio/rootfs/file1 b/lab4/tools/cpio/rootfs/file1 new file mode 100644 index 000000000..b7b514317 --- /dev/null +++ b/lab4/tools/cpio/rootfs/file1 @@ -0,0 +1 @@ +This is your flag!!! diff --git a/lab4/tools/cpio/rootfs/file2.txt b/lab4/tools/cpio/rootfs/file2.txt new file mode 100644 index 000000000..367edaf2d --- /dev/null +++ b/lab4/tools/cpio/rootfs/file2.txt @@ -0,0 +1 @@ +FLAG{...........................} diff --git a/lab4/tools/cpio/rootfs/test.img b/lab4/tools/cpio/rootfs/test.img new file mode 100755 index 000000000..1adf648a4 Binary files /dev/null and b/lab4/tools/cpio/rootfs/test.img differ diff --git a/lab4/tools/cpio/rootfs/test/1234 b/lab4/tools/cpio/rootfs/test/1234 new file mode 100644 index 000000000..81c545efe --- /dev/null +++ b/lab4/tools/cpio/rootfs/test/1234 @@ -0,0 +1 @@ +1234 diff --git a/lab4/tools/cpio/test.S b/lab4/tools/cpio/test.S new file mode 100644 index 000000000..ce7e53908 --- /dev/null +++ b/lab4/tools/cpio/test.S @@ -0,0 +1,11 @@ +.section ".text" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b diff --git a/lab4/tools/cpio/test.elf b/lab4/tools/cpio/test.elf new file mode 100755 index 000000000..fbf6baf3c Binary files /dev/null and b/lab4/tools/cpio/test.elf differ diff --git a/lab4/tools/cpio/test.img b/lab4/tools/cpio/test.img new file mode 100755 index 000000000..1adf648a4 Binary files /dev/null and b/lab4/tools/cpio/test.img differ diff --git a/lab4/tools/cpio/test.o b/lab4/tools/cpio/test.o new file mode 100644 index 000000000..f84f74464 Binary files /dev/null and b/lab4/tools/cpio/test.o differ diff --git a/lab4/tools/gen.sh b/lab4/tools/gen.sh new file mode 100755 index 000000000..235b38c28 --- /dev/null +++ b/lab4/tools/gen.sh @@ -0,0 +1,24 @@ +#! /bin/sh +BUS_IO_BASE=0x7E000000 +PHY_IO_BASE=0x3F000000 +echo "/* Register's offset of GPIO */" +grep -v " - " GPIO | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + +echo "" +echo "" +echo "/* Register's offset of UART and SPI */" +grep -v " - " AUX_PERIPHERALS | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + + diff --git a/lab4/uart_upload.py b/lab4/uart_upload.py new file mode 100755 index 000000000..9a2a52d80 --- /dev/null +++ b/lab4/uart_upload.py @@ -0,0 +1,69 @@ +#! /usr/bin/python3 + +import sys +import struct +import serial +import os +import time +if len(sys.argv) < 4: + print(sys.argv[0], "", "", "") + sys.exit(-1) + +tty_name = sys.argv[1] +kernel_name = sys.argv[2] +base_addr = int(sys.argv[3], 16) + +ser = None + +def readline(): + os.write(1,b'[From bootloader]: ') + while 1: + c = ser.read(1) + if c == b'\n': + os.write(1, b'\n') + return + elif c != b'\r': + os.write(1, c) + + + +with open(kernel_name, "rb",) as kernel: + kernel_buf = kernel.read() + kernel_size = len(kernel_buf) + + + while(1): + ser = serial.Serial( + # Serial Port to read the data from + port = tty_name, + #Rate at which the information is shared to the communication channel + baudrate = 115200, + timeout = .1 + ) + + # start upload kernel to rasberry pi 3b+ by uart interface + # start header + ser.write(b"A") + ser.flush() + readline() + + # transfer kernel base address and kernel size ( both are 8 bytes ) in little endian + ser.write(struct.pack(" 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + + +master_core: +// stack + ldr x1, =_start + mov sp, x1 + +// recover dtb to x0 + adr x1, _dtb + ldr x0, [x1] + + +// jump to kernel_main + bl uart_recv_kernel + + b proc_hang + +// rebase our boot loader +rebase_bootloader: + // manipulate our return address ( x30 a.k.a LR ) to the rebased bootloader + // x19 = current PC + offset to _start + // x20 = absolute address ( _start ) that specify by linker script + adr x19, _start + ldr x20, =_start + sub x19, x19, x20 + sub lr , lr, x19 + + // x21 = absolute address ( __bootloader_start ) that specify by linker script + // x22 = current PC + offset to __bootloader_start ( In linker script ) + ldr x21, =__bootloader_start + adr x22, __bootloader_start + ldr x23, =__bootloader_size + // start rebasing bootloader +copy_bootloader: + cbz x23, end_rebase_bootloader + ldr x24, [x22], #8 + str x24, [x21], #8 + sub x23, x23, #8 + b copy_bootloader + +// Since ldr and str memory operation should obey 8 bytes alignment rule, the code here would failed on real device +// cbz x23, end_rebase_bootloader +// ldr x24, [x22], #1 +// str x24, [x21], #1 +// sub x23, x23, #1 +// b copy_bootloader + + + // return to rebased bootloader +end_rebase_bootloader: + ret + +.section ".data" +_dtb: .dword 0 diff --git a/lab5/boot/linker.ld b/lab5/boot/linker.ld new file mode 100644 index 000000000..740945ab2 --- /dev/null +++ b/lab5/boot/linker.ld @@ -0,0 +1,43 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x60000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __bootloader_start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + __bootloader_end = .; + __bootloader_size = (__bootloader_end - __bootloader_start); +} diff --git a/lab5/boot/uart_boot.c b/lab5/boot/uart_boot.c new file mode 100644 index 000000000..faec51411 --- /dev/null +++ b/lab5/boot/uart_boot.c @@ -0,0 +1,47 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "lib/print.h" + +void recv_boot_header(){ + while('A' != mini_uart_read()); +} + +size_t recv_kernel_base(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +size_t recv_kernel_size(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +void recv_kernel(uint64_t base, size_t size){ + uint8_t *pb; + size_t i; + for(pb = (uint8_t*)base , i = 0 ; i < size ; i++){ + pb[i] = mini_uart_read(); + } +} +uint64_t uart_recv_kernel(uint64_t dtb){ + size_t size; + uint64_t base; + mini_uart_init(); + + recv_boot_header(); +// printf("Receive A...\r\n"); + + base = recv_kernel_base(); +// printf("Receive kernel base 0x%x...\r\n", base); + + size = recv_kernel_size(); +// printf("Receive kernel size 0x%x...\r\n", size); + + recv_kernel(base, size); +// printf("Jump to kernel iamge...\r\n"); + + delay_cycles(10000); + ((void (*)(uint64_t))base)(dtb); +} diff --git a/lab5/build/asm.o b/lab5/build/asm.o new file mode 100644 index 000000000..f9d451c11 Binary files /dev/null and b/lab5/build/asm.o differ diff --git a/lab5/build/bitops.o b/lab5/build/bitops.o new file mode 100644 index 000000000..f6889106e Binary files /dev/null and b/lab5/build/bitops.o differ diff --git a/lab5/build/boot.o b/lab5/build/boot.o new file mode 100644 index 000000000..d9a96fce6 Binary files /dev/null and b/lab5/build/boot.o differ diff --git a/lab5/build/cpio.o b/lab5/build/cpio.o new file mode 100644 index 000000000..d84f1e0af Binary files /dev/null and b/lab5/build/cpio.o differ diff --git a/lab5/build/debug.o b/lab5/build/debug.o new file mode 100644 index 000000000..a1f50d30c Binary files /dev/null and b/lab5/build/debug.o differ diff --git a/lab5/build/entry.o b/lab5/build/entry.o new file mode 100644 index 000000000..6f0a71bed Binary files /dev/null and b/lab5/build/entry.o differ diff --git a/lab5/build/fdt_parse.o b/lab5/build/fdt_parse.o new file mode 100644 index 000000000..512b452a1 Binary files /dev/null and b/lab5/build/fdt_parse.o differ diff --git a/lab5/build/initrdfs.o b/lab5/build/initrdfs.o new file mode 100644 index 000000000..db9722714 Binary files /dev/null and b/lab5/build/initrdfs.o differ diff --git a/lab5/build/irq_handler.o b/lab5/build/irq_handler.o new file mode 100644 index 000000000..5b00b26b4 Binary files /dev/null and b/lab5/build/irq_handler.o differ diff --git a/lab5/build/kernel8.elf b/lab5/build/kernel8.elf new file mode 100755 index 000000000..1ba43b9c0 Binary files /dev/null and b/lab5/build/kernel8.elf differ diff --git a/lab5/build/kernel8.img b/lab5/build/kernel8.img new file mode 100755 index 000000000..57b69da00 Binary files /dev/null and b/lab5/build/kernel8.img differ diff --git a/lab5/build/kernel_init.o b/lab5/build/kernel_init.o new file mode 100644 index 000000000..f05821006 Binary files /dev/null and b/lab5/build/kernel_init.o differ diff --git a/lab5/build/kthread.o b/lab5/build/kthread.o new file mode 100644 index 000000000..df70aad55 Binary files /dev/null and b/lab5/build/kthread.o differ diff --git a/lab5/build/list.o b/lab5/build/list.o new file mode 100644 index 000000000..4380f49c8 Binary files /dev/null and b/lab5/build/list.o differ diff --git a/lab5/build/mailbox.o b/lab5/build/mailbox.o new file mode 100644 index 000000000..01d507747 Binary files /dev/null and b/lab5/build/mailbox.o differ diff --git a/lab5/build/main.o b/lab5/build/main.o new file mode 100644 index 000000000..7441c8d16 Binary files /dev/null and b/lab5/build/main.o differ diff --git a/lab5/build/mini_uart.o b/lab5/build/mini_uart.o new file mode 100644 index 000000000..5b7c43867 Binary files /dev/null and b/lab5/build/mini_uart.o differ diff --git a/lab5/build/mm.o b/lab5/build/mm.o new file mode 100644 index 000000000..262c79678 Binary files /dev/null and b/lab5/build/mm.o differ diff --git a/lab5/build/page_alloc.o b/lab5/build/page_alloc.o new file mode 100644 index 000000000..54af94477 Binary files /dev/null and b/lab5/build/page_alloc.o differ diff --git a/lab5/build/print.o b/lab5/build/print.o new file mode 100644 index 000000000..ea82eb88d Binary files /dev/null and b/lab5/build/print.o differ diff --git a/lab5/build/reboot.o b/lab5/build/reboot.o new file mode 100644 index 000000000..b2e138124 Binary files /dev/null and b/lab5/build/reboot.o differ diff --git a/lab5/build/ring_buffer.o b/lab5/build/ring_buffer.o new file mode 100644 index 000000000..9ae58b65e Binary files /dev/null and b/lab5/build/ring_buffer.o differ diff --git a/lab5/build/sched.o b/lab5/build/sched.o new file mode 100644 index 000000000..212ef7251 Binary files /dev/null and b/lab5/build/sched.o differ diff --git a/lab5/build/shell.o b/lab5/build/shell.o new file mode 100644 index 000000000..edc183199 Binary files /dev/null and b/lab5/build/shell.o differ diff --git a/lab5/build/signal.o b/lab5/build/signal.o new file mode 100644 index 000000000..e093fac36 Binary files /dev/null and b/lab5/build/signal.o differ diff --git a/lab5/build/simple_malloc.o b/lab5/build/simple_malloc.o new file mode 100644 index 000000000..30561a330 Binary files /dev/null and b/lab5/build/simple_malloc.o differ diff --git a/lab5/build/slab.o b/lab5/build/slab.o new file mode 100644 index 000000000..080e4de97 Binary files /dev/null and b/lab5/build/slab.o differ diff --git a/lab5/build/start.o b/lab5/build/start.o new file mode 100644 index 000000000..53c432e17 Binary files /dev/null and b/lab5/build/start.o differ diff --git a/lab5/build/string.o b/lab5/build/string.o new file mode 100644 index 000000000..59c6f1bcd Binary files /dev/null and b/lab5/build/string.o differ diff --git a/lab5/build/syscall_table.o b/lab5/build/syscall_table.o new file mode 100644 index 000000000..bcd9933f2 Binary files /dev/null and b/lab5/build/syscall_table.o differ diff --git a/lab5/build/syscall_test.o b/lab5/build/syscall_test.o new file mode 100644 index 000000000..d5ff32a03 Binary files /dev/null and b/lab5/build/syscall_test.o differ diff --git a/lab5/build/task.o b/lab5/build/task.o new file mode 100644 index 000000000..2f24371c1 Binary files /dev/null and b/lab5/build/task.o differ diff --git a/lab5/build/timer.o b/lab5/build/timer.o new file mode 100644 index 000000000..2063d6899 Binary files /dev/null and b/lab5/build/timer.o differ diff --git a/lab5/build/uart_boot.o b/lab5/build/uart_boot.o new file mode 100644 index 000000000..4b0da3041 Binary files /dev/null and b/lab5/build/uart_boot.o differ diff --git a/lab5/debug.sh b/lab5/debug.sh new file mode 100755 index 000000000..81d573d80 --- /dev/null +++ b/lab5/debug.sh @@ -0,0 +1,3 @@ +#!/bin/sh +make CFLAGS=-DDEBUG >/dev/null +make qemu-run diff --git a/lab5/debug/Makefile b/lab5/debug/Makefile new file mode 100644 index 000000000..22ac23500 --- /dev/null +++ b/lab5/debug/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + debug.o + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab5/debug/debug.c b/lab5/debug/debug.c new file mode 100644 index 000000000..e990517b5 --- /dev/null +++ b/lab5/debug/debug.c @@ -0,0 +1,50 @@ +#include "debug/debug.h" + +extern int __bss_start, __bss_end; +extern int __text_start, __text_end; +extern int __rodata_start, __rodata_end; +extern int __data_start, __data_end; +extern int __heap_start; + +#ifdef DEBUG +int debug = 1; +#else +int debug = 0; +#endif + +void log_kernel_start(){ + uint64_t currentEL; + if(debug == 0) return; + printf("text_start=%p, text_end=%p, text_size=%u\r\n", \ + &__text_start, \ + &__text_end, \ + (uint64_t)&__text_end - (uint64_t)&__text_start + ); + + + printf("rodata_start=%p, rodata_end=%p, rodata_size=%u\r\n", \ + &__rodata_start, \ + &__rodata_end, \ + (uint64_t)&__rodata_end - (uint64_t)&__rodata_start + ); + + printf("data_start=%p, data_end=%p, data_size=%u\r\n", \ + &__data_start, \ + &__data_end, \ + (uint64_t)&__data_end - (uint64_t)&__data_start + ); + + printf("bss_start=%p, bss_end=%p, bss_size=%u\r\n", \ + &__bss_start, \ + &__bss_end, \ + (uint64_t)&__bss_end - (uint64_t)&__bss_start + ); + printf("heap_start=%p\r\n", &__heap_start); + + printf("current exception level: %u\r\n", get_currentEL()); + printf("SP_EL0: 0x%x\r\n", get_SP_ELx(0)); + printf("DAIF: 0x%x\r\n", get_DAIF()); + printf("SPSel: 0x%x\r\n", get_SPSel()); + printf("stack pointer: %p\r\n", ¤tEL); + +} diff --git a/lab5/fs/Makefile b/lab5/fs/Makefile new file mode 100644 index 000000000..15fbb2fa3 --- /dev/null +++ b/lab5/fs/Makefile @@ -0,0 +1,24 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + initrdfs.o +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab5/fs/initrdfs.c b/lab5/fs/initrdfs.c new file mode 100644 index 000000000..d38d128d5 --- /dev/null +++ b/lab5/fs/initrdfs.c @@ -0,0 +1,97 @@ +#include "fs/initrdfs.h" + +static struct fentry * root; + +void initrdfs_init(void* addr){ + INFO("Initrd filesystem start address: %p", addr); + LOG("Enter initrdfs_int"); + LOG("initrd start at %p\n", addr); + LOG("initrd first 4 bytes: %x\n", *(uint32_t*)addr); + root = (struct fentry*)kmalloc(sizeof(struct fentry)); + struct cpio_iter iter; + char *fname = (char*)kmalloc(2); + strcpy(fname, "/"); + + memset(root, 0, sizeof(struct fentry)); + root->filename = fname; + root->namesize = 1; + root->mode = root->mode & FILE_TYPE_DIR; + + INIT_LIST_HEAD(&root->list); + + // Start parsing initrd in New ASCII Format at addr + LOG("Start parsing new ascii format's cpio"); + cpio_iter_init(&iter, addr); + do{ + struct fentry *f = (struct fentry*)kmalloc(sizeof(struct fentry)); + cpio_iter_parse(&iter, f); + LOG("FILE: %s", f->filename); + if(cpio_is_tailer(f)) break; + list_add(&f->list, &root->list); + }while(1); + LOG("Leave initrdfs_int"); +} +void* fdt_initrdfs_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(prop != NULL){ + if(strcmp(prop->name, "linux,initrd-start") == 0){ + uint64_t initrd_start = bswap32(*(uint32_t*)prop->value); + LOG("linux,initrd-start: %x", (uint32_t)initrd_start); + initrdfs_init((void*)initrd_start); + } + } +} + +void initrdfs_ls(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + printf("%s\r\n", f->filename); + } +} +void initrdfs_cat(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + printf("Filename : %s\r\n", f->filename); + printf("File size: %u\r\n", f->filesize); + write_bytes(f->data, f->filesize); + printf("\r\n"); + } + } +} + +void initrdfs_loadfile(char* name, uint8_t* addr){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + if(strcmp(name, f->filename) == 0){ + LOG("Load file %s to %p", name, addr); + memcpy(addr, f->data, f->filesize); + break; + } + } + } +} + +size_t initrdfs_filesize(char* name){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + if(strcmp(name, f->filename) == 0){ + return f->filesize; + } + } + } + return 0; +} diff --git a/lab5/include/asm.h b/lab5/include/asm.h new file mode 100644 index 000000000..0b2fd9c46 --- /dev/null +++ b/lab5/include/asm.h @@ -0,0 +1,23 @@ +#ifndef _ASM_H_ +#define _ASM_H_ +extern uint32_t get_currentEL(); +extern uint64_t get_SP_ELx(uint32_t); +extern uint64_t get_DAIF(); +extern void set_DAIF(uint64_t); +extern uint64_t get_SPSel(); +extern uint64_t get_ESR_EL1(); +extern uint64_t get_SPSR_EL1(); +extern uint64_t get_ELR_EL1(); +extern uint64_t get_SP(); +extern uint64_t get_CNTP_CTL_EL0(); +extern void set_CNTP_CTL_EL0(uint64_t); +extern uint64_t get_CNTFRQ_EL0(); +extern void set_CNTP_TVAL_EL0(uint64_t); +extern uint64_t get_CNTPCT_EL0(); +extern void local_irq_enable(); +extern void local_irq_disable(); +extern uint64_t local_irq_disable_save(); +extern void local_irq_restore(uint64_t); + +#endif + diff --git a/lab5/include/debug/debug.h b/lab5/include/debug/debug.h new file mode 100644 index 000000000..098653069 --- /dev/null +++ b/lab5/include/debug/debug.h @@ -0,0 +1,18 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "lib/print.h" +#include "types.h" +#include "asm.h" + +#define DEBUG_KERNEL_START() log_kernel_start() +#define LOG(fmt, ...) \ + if(debug) \ + printf("[%s/%s:%d] " fmt "\r\n" , __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) + + + +extern void log_kernel_start(void); + +extern int debug; +#endif diff --git a/lab5/include/fs/initrdfs.h b/lab5/include/fs/initrdfs.h new file mode 100644 index 000000000..a83418543 --- /dev/null +++ b/lab5/include/fs/initrdfs.h @@ -0,0 +1,19 @@ +#ifndef _INITRDFS_H_ +#define _INITRDFS_H_ +#include "types.h" +#include "lib/cpio.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "mm/slab.h" +#include "lib/list.h" +#include "lib/string.h" +#include "debug/debug.h" +#include "peripherals/mini_uart.h" + +extern void initrdfs_init(void*); +extern void initrdfs_ls(); +extern void initrdfs_cat(); +extern void* fdt_initrdfs_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void initrdfs_loadfile(char* , uint8_t*); +extern size_t initrdfs_filesize(char*); +#endif diff --git a/lab5/include/init/kernel_init.h b/lab5/include/init/kernel_init.h new file mode 100644 index 000000000..fdd21d689 --- /dev/null +++ b/lab5/include/init/kernel_init.h @@ -0,0 +1,16 @@ +#ifndef _KERNEL_INIT_H +#define _KERNEL_INIT_H +#include "types.h" +#include "peripherals/mini_uart.h" +#include "fs/initrdfs.h" +#include "kernel/timer.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "mm/mm.h" +#include "asm.h" +#include "kernel/sched/sched.h" +#include "kernel/sched/kthread.h" + +extern void kernel_init(void *); + +#endif diff --git a/lab5/include/kernel/irq_handler.h b/lab5/include/kernel/irq_handler.h new file mode 100644 index 000000000..52ff3091f --- /dev/null +++ b/lab5/include/kernel/irq_handler.h @@ -0,0 +1,25 @@ +#ifndef _IRQ_HANDLER_H_ +#define _IRQ_HANDLER_H_ + +#include "types.h" +#include "peripherals/iomapping.h" +#include "peripherals/mini_uart.h" +#include "lib/print.h" +#include "lib/bitops.h" +#include "kernel/timer.h" +#include "kernel/sched/sched.h" +#include "debug/debug.h" +#include "asm.h" + +#define MAX_SOFTIRQ_TRY 10 + +enum {CORE0_TIMER = 0, MINI_UART_RX, UNKNOWN_IRQ, END_OF_LIST}; +typedef void (*irq_funcptr)(void); + +struct softirq_status{ + uint16_t pending; // support 16 interrupt + uint8_t in_softirq; +}; +extern uint64_t irq_count[END_OF_LIST]; +extern uint8_t in_softirq(); +#endif diff --git a/lab5/include/kernel/reboot.h b/lab5/include/kernel/reboot.h new file mode 100644 index 000000000..cc8e8730b --- /dev/null +++ b/lab5/include/kernel/reboot.h @@ -0,0 +1,16 @@ +#ifndef _REBOOT_H_ +#define _REBOOT_H_ + +#include "peripherals/iomapping.h" + +#define PM_WDOG_RESET 0000000000 +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +extern void reboot(int tick); + +#endif diff --git a/lab5/include/kernel/sched/kthread.h b/lab5/include/kernel/sched/kthread.h new file mode 100644 index 000000000..97254fc67 --- /dev/null +++ b/lab5/include/kernel/sched/kthread.h @@ -0,0 +1,19 @@ +#ifndef _KTHREAD_H_ +#define _KTHREAD_H_ + +#include "kernel/sched/sched.h" +#include "kernel/sched/task.h" +#include "mm/page_alloc.h" +#include "debug/debug.h" +#include "mm/slab.h" +typedef void (*kthread_func)(void); + +extern void kthread_init(); +extern void kthread_idle(); +extern void kthread_test(); +extern uint64_t kthread_create(kthread_func func); +extern void kthread_exit(); +extern void kthread_destroy(struct task_struct*); +extern void kthread_start(kthread_func); + +#endif diff --git a/lab5/include/kernel/sched/sched.h b/lab5/include/kernel/sched/sched.h new file mode 100644 index 000000000..ce97779b0 --- /dev/null +++ b/lab5/include/kernel/sched/sched.h @@ -0,0 +1,142 @@ +#ifndef _SCHED_H_ +#define _SCHED_H_ +#include "lib/list.h" +#include "kernel/irq_handler.h" +#include "kernel/signal.h" + +typedef uint64_t pid_t; + + +#define TASK_RUNNING 0 +#define TASK_INTERRUPTIBLE 1 +#define TASK_UNINTERRUPTIBLE 2 +#define TASK_DEAD 64 +#define VM_AREA_STACK 1 +#define VM_AREA_PROGRAM 2 +#define get_trap_frame(task) (task->stack + PAGE_SIZE * 2 - sizeof(struct trap_frame)) +struct thread_info{ + pid_t pid; + volatile int64_t state; +}; + +struct sched_info{ + int64_t rticks; // running ticks = user + system ticks + int64_t priority; + int64_t counter; // reset counter -> counter = priority + struct list_head sched_list; +}; + +struct trap_frame{ + uint64_t x0; + uint64_t x1; + uint64_t x2; + uint64_t x3; + uint64_t x4; + uint64_t x5; + uint64_t x6; + uint64_t x7; + uint64_t x8; + uint64_t x9; + uint64_t x10; + uint64_t x11; + uint64_t x12; + uint64_t x13; + uint64_t x14; + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t x29; // fp + uint64_t x30; // lr + uint64_t sp_el0; + uint64_t spsr_el1; + uint64_t elr_el1; +}__attribute__((packed)); + +struct task_ctx{ + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t fp; + uint64_t lr; + uint64_t sp; + uint64_t redzone; +}__attribute__((packed)); + +struct vm_area_struct{ + uint64_t vm_start; + uint64_t vm_end; + uint64_t type; + int64_t ref; +}; + +struct vm_area_struct_list{ + struct vm_area_struct* vm_area; + struct list_head list; +}; + +struct mm_struct{ + struct list_head mmap_list; +}; + +struct task_struct{ + struct task_ctx ctx; + + struct thread_info thread_info; + + struct mm_struct* mm; + + // kernel stack + void* stack; + + // schedule info + struct sched_info sched_info; + + // signal + struct sigpending sigpending; + struct sighand_struct sighandler; + + // relationship + struct task_struct* parent; + struct task_struct* child; + struct list_head siblings; + + // task list + struct list_head list; + + // zombie list + struct list_head zombie; +}; + +extern int need_sched; +extern struct list_head zombies; +extern struct list_head task_list; +extern struct task_struct* user_init; + +extern void add_task_to_rq(struct task_struct *task); +extern struct task_struct* pick_next_task_from_rq(); +extern void schedule(); +extern void switch_to(struct task_struct*, struct task_struct*); +extern struct task_struct* get_current(); +extern pid_t get_pid_counter(void); +extern void preempt_schedule(); +extern void print_rq(void); +extern struct task_struct* find_task_by_pid(uint64_t pid); +#endif diff --git a/lab5/include/kernel/sched/task.h b/lab5/include/kernel/sched/task.h new file mode 100644 index 000000000..c1759c829 --- /dev/null +++ b/lab5/include/kernel/sched/task.h @@ -0,0 +1,19 @@ +#ifndef _TASK_H_ +#define _TASK_H_ + +#include "kernel/sched/sched.h" +#include "fs/initrdfs.h" +#include "mm/page_alloc.h" +#include "debug/debug.h" +#include "mm/slab.h" + + +extern void task_init(); +extern uint64_t task_dup(); +extern void task_exit(); +extern void task_destroy(struct task_struct*); +extern void run_init_task(char*); +extern struct trap_frame* get_current_trap_frame(); +extern void sys_kill(uint64_t pid); + +#endif diff --git a/lab5/include/kernel/shell.h b/lab5/include/kernel/shell.h new file mode 100644 index 000000000..81f8b0988 --- /dev/null +++ b/lab5/include/kernel/shell.h @@ -0,0 +1,19 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ +#include "types.h" +#include "lib/print.h" +#include "lib/string.h" +#include "lib/simple_malloc.h" +#include "peripherals/mailbox.h" +#include "kernel/reboot.h" +#include "fs/initrdfs.h" +#include "kernel/timer.h" +#include "kernel/irq_handler.h" +#include "mm/slab.h" +#include "kernel/sched/task.h" +#include "kernel/sched/kthread.h" + +void simple_shell(void); + +#define DELIM " \t\n\r" +#endif diff --git a/lab5/include/kernel/signal.h b/lab5/include/kernel/signal.h new file mode 100644 index 000000000..091811f06 --- /dev/null +++ b/lab5/include/kernel/signal.h @@ -0,0 +1,79 @@ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +#include "types.h" +#include "lib/list.h" + +#define SIG_SIGHUP 1 +#define SIG_SIGINT 2 +#define SIG_SIGQUIT 3 +#define SIG_SIGILL 4 +#define SIG_SIGTRAP 5 +#define SIG_SIGABRT 6 +#define SIG_SIGBUS 7 +#define SIG_SIGFPE 8 +#define SIG_SIGKILL 9 +#define SIG_SIGUSR1 10 +#define SIG_SIGSEGV 11 +#define SIG_SIGUSR2 12 +#define SIG_SIGPIPE 13 +#define SIG_SIGALRM 14 +#define SIG_SIGTERM 15 +#define SIG_SIGSTKFLT 16 +#define SIG_SIGCHLD 17 +#define SIG_SIGCONT 18 +#define SIG_SIGSTOP 19 +#define SIG_SIGTSTP 20 +#define SIG_SIGTTIN 21 +#define SIG_SIGTTOU 22 +#define SIG_SIGURG 23 +#define SIG_SIGXCPU 24 +#define SIG_SIGXFSZ 25 +#define SIG_SIGVTALRM 26 +#define SIG_SIGPROF 27 +#define SIG_SIGWINCH 28 +#define SIG_SIGIO 29 +#define SIG_SIGPWR 30 +#define SIG_SIGSYS 31 + +#define SIG_FLAG_KERNEL 1 + +#define SIG_MAX_NUM 32 + +typedef void (*sig_handler)(); + +struct signal_queue{ + struct list_head list; + int32_t signal; +}; + +struct sigpending{ + struct list_head pending; + int32_t cur_signal; +}; + +struct sigaction{ + uint32_t sa_flags; + sig_handler sa_handler; +}; + +struct sighand_struct{ + struct sigaction actions[SIG_MAX_NUM]; +}; + +extern void sigpending_init(struct sigpending*); +extern void default_sighand_init(struct sighand_struct*); +extern int send_signal(uint64_t, int); +extern int register_signal(int, sig_handler); +extern void handle_sigreturn(); +extern void handle_signal(); +extern void sigreturn_frame_save(sig_handler); +extern void sigreturn_frame_restore(); +extern void sys_sigreturn(); +extern void sys_signal(int, sig_handler); +extern int sys_sigkill(uint64_t, int); +extern void sig_default(); +extern void sig_terminate(); + + +#endif diff --git a/lab5/include/kernel/signal_inner.h b/lab5/include/kernel/signal_inner.h new file mode 100644 index 000000000..daebe14be --- /dev/null +++ b/lab5/include/kernel/signal_inner.h @@ -0,0 +1,74 @@ +#ifndef _SIGNAL_INNER_H_ +#define _SIGNAL_INNER_H_ + +#include "kernel/signal.h" +struct sigaction default_actions[SIG_MAX_NUM] = { + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_terminate}, // 9 + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default} +}; + +char* sig_to_str[SIG_MAX_NUM] = { + "SIGUNKOWN", + "SIGHUP", + "SIGINT", + "SIGQUIT", + "SIGILL", + "SIGTRAP", + "SIGABRT", + "SIGBUS", + "SIGFPE", + "SIGKILL", + "SIGUSR1", + "SIGSEGV", + "SIGUSR2", + "SIGPIPE", + "SIGALRM", + "SIGTERM", + "SIGSTKFLT", + "SIGCHLD", + "SIGCONT", + "SIGSTOP", + "SIGTSTP", + "SIGTTIN", + "SIGTTOU", + "SIGURG", + "SIGXCPU", + "SIGXFSZ", + "SIGVTALRM", + "SIGPROF", + "SIGWINCH", + "SIGIO", + "SIGPWR", + "SIGSYS" +}; +#endif diff --git a/lab5/include/kernel/syscall.h b/lab5/include/kernel/syscall.h new file mode 100644 index 000000000..485e9d221 --- /dev/null +++ b/lab5/include/kernel/syscall.h @@ -0,0 +1,18 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ +#include "types.h" +#include "kernel/signal.h" +extern uint64_t sys_hello(uint64_t); +extern size_t sys_uart_write(char *, size_t); +extern size_t sys_uart_read(char *, size_t); +extern uint64_t sys_fork(); +extern uint64_t sys_getpid(); +extern int sys_mbox_call(uint8_t, uint32_t *); +extern void sys_exit(); +extern void sys_kill(uint64_t pid); +extern int sys_exec(const char *, char *const []); +extern void sys_sigreturn(); +extern void sys_signal(int, sig_handler); +extern int sys_sigkill(uint64_t, int); + +#endif diff --git a/lab5/include/kernel/syscall_table.h b/lab5/include/kernel/syscall_table.h new file mode 100644 index 000000000..cb853be3a --- /dev/null +++ b/lab5/include/kernel/syscall_table.h @@ -0,0 +1,6 @@ +#ifndef _SYSCALL_TABLE_H_ +#define _SYSCALL_TABLE_H_ + +#include "kernel/syscall.h" +#include "kernel/sched/sched.h" +#endif diff --git a/lab5/include/kernel/timer.h b/lab5/include/kernel/timer.h new file mode 100644 index 000000000..f7cacf702 --- /dev/null +++ b/lab5/include/kernel/timer.h @@ -0,0 +1,32 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ +#include "types.h" +#include "lib/list.h" +#include "lib/simple_malloc.h" +#include "peripherals/iomapping.h" +#include "debug/debug.h" +#include "asm.h" +#include "kernel/sched/sched.h" + + +#define HZ 32 + +typedef void (*timer_callback)(void*); + +typedef struct{ + uint64_t ticks; + timer_callback callback; + void *data; + struct list_head list; +}timer_t; + +extern void core_timer_irq_handler(); +extern void init_core_timer(); +extern uint64_t get_jiffies(); +extern void enable_core_timer_irq(); +extern void disable_core_timer_irq(); +extern void init_timer_list(); +extern void add_timer(timer_callback, uint8_t*, uint64_t); +extern void timer_softirq_callback(); + +#endif diff --git a/lab5/include/lib/bitops.h b/lab5/include/lib/bitops.h new file mode 100644 index 000000000..1a22a6136 --- /dev/null +++ b/lab5/include/lib/bitops.h @@ -0,0 +1,8 @@ +#ifndef _BITOPS_H_ +#define _BITOPS_H_ + +#include "types.h" +extern uint16_t ffs16(uint16_t); +extern uint64_t ffs64(uint64_t); + +#endif diff --git a/lab5/include/lib/cpio.h b/lab5/include/lib/cpio.h new file mode 100644 index 000000000..9e9eaf129 --- /dev/null +++ b/lab5/include/lib/cpio.h @@ -0,0 +1,66 @@ +#ifndef _CPIO_H_ +#define _CPIO_H_ + +#include "types.h" +#include "lib/list.h" +#include "lib/fdt_parse.h" +#include "lib/string.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "debug/debug.h" + +#define FILE_TYPE_MASK 0170000 +#define FILE_TYPE_SOCKET 0140000 +#define FILE_TYPE_SYMLINK 0120000 +#define FILE_TYPE_REGULAR 0100000 +#define FILE_TYPE_BLKDEV 0060000 +#define FILE_TYPE_DIR 0040000 +#define FILE_TYPE_CHRDEV 0020000 +#define FILE_TYPE_NAMED_PIPE 0010000 +#define FILE_SUID 0004000 +#define FILE_SGID 0002000 +#define FILE_STICKY 0001000 +#define FILE_PERMISSION_MASK 0000777 + +struct cpio_iter{ + uint8_t *cur; +}; +struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} __attribute((packed)); + +struct fentry { + uint32_t ino; + uint32_t mode; + uint32_t uid; + uint32_t gid; + uint32_t nlink; + uint32_t mtime; + uint32_t filesize; + uint32_t devmajor; + uint32_t devminor; + uint32_t rdevmajor; + uint32_t rdevminor; + uint32_t namesize; + uint32_t check; + char *filename; + uint8_t *data; + struct list_head list; +}; +void cpio_iter_parse(struct cpio_iter*, struct fentry*); +extern void cpio_iter_init(struct cpio_iter*, void*); +extern int cpio_is_tailer(struct fentry*); +#endif diff --git a/lab5/include/lib/fdt_parse.h b/lab5/include/lib/fdt_parse.h new file mode 100644 index 000000000..d01497474 --- /dev/null +++ b/lab5/include/lib/fdt_parse.h @@ -0,0 +1,47 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "lib/string.h" + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +typedef void (*fdt_rsvmap_callback)(uint64_t, uint64_t); +extern void fdt_parse_header(uint8_t*, fdt_header*); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parse_rsvmap(uint8_t*, fdt_rsvmap_callback); +#endif diff --git a/lab5/include/lib/list.h b/lab5/include/lib/list.h new file mode 100644 index 000000000..f102aef06 --- /dev/null +++ b/lab5/include/lib/list.h @@ -0,0 +1,25 @@ +#ifndef _LIST_H_ +#define _LIST_H_ + +#include "types.h" +struct list_head{ + struct list_head* next, *prev; +}; + +#define LIST_HEAD(head) struct list_head head = { &(head), &(head) } +#define list_entry(node, type, member) container_of(node, type, member) +#define list_first_entry(head, type, member) list_entry((head)->next, type, member) +#define list_last_entry(head, type, member) list_entry((head)->prev, type, member) +#define list_for_each(node, head) \ + for(node = (head)->next ; node != (head) ; node = node->next) + +extern void INIT_LIST_HEAD(struct list_head*); +extern void list_add(struct list_head* node, struct list_head*); +extern void list_add_tail(struct list_head*, struct list_head*); +extern void list_del(struct list_head*); +extern int list_empty(struct list_head*); +extern int list_is_last(struct list_head*, struct list_head*); +extern int list_is_head(struct list_head*, struct list_head*); +extern void list_splice(struct list_head*, struct list_head*); +extern void list_splice_tail(struct list_head*, struct list_head*); +#endif diff --git a/lab5/include/lib/print.h b/lab5/include/lib/print.h new file mode 100644 index 000000000..7752c069c --- /dev/null +++ b/lab5/include/lib/print.h @@ -0,0 +1,21 @@ +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#include "types.h" +#include "kernel/timer.h" +#include "lib/string.h" +#include "peripherals/mini_uart.h" +#include "kernel/irq_handler.h" +#include + +extern int32_t printf(char *, ...); +extern int32_t putchar(uint8_t); +extern int32_t getchar(); + +#define INFO(fmt, ...) \ + do{ \ + printf("%l: [%s] " fmt "\r\n" , (int64_t)get_jiffies(), __FUNCTION__, ##__VA_ARGS__); \ + }while(0) + + +#endif diff --git a/lab5/include/lib/ring_buffer.h b/lab5/include/lib/ring_buffer.h new file mode 100644 index 000000000..282b61b53 --- /dev/null +++ b/lab5/include/lib/ring_buffer.h @@ -0,0 +1,27 @@ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ +#include "types.h" +#include "lib/simple_malloc.h" +#include "mm/slab.h" + +typedef struct{ + size_t size; + uint64_t head; + uint64_t tail; + uint8_t* buf; + size_t count; +}ring_buffer; + +extern ring_buffer* create_simple_ring_buf(size_t); + +extern ring_buffer* create_ring_buf(size_t); +extern void free_ring_buf(ring_buffer*); +extern size_t ring_buf_write(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_write_unsafe(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read_unsafe(ring_buffer*, uint8_t*, size_t); +extern uint8_t ring_buf_is_full(ring_buffer*); +extern uint8_t ring_buf_is_empty(ring_buffer*); +extern size_t ring_buf_get_len(ring_buffer*); + +#endif diff --git a/lab5/include/lib/simple_malloc.h b/lab5/include/lib/simple_malloc.h new file mode 100644 index 000000000..8f8c0f4dc --- /dev/null +++ b/lab5/include/lib/simple_malloc.h @@ -0,0 +1,15 @@ +#ifndef _SIMPLE_MALLOC_H_ +#define _SIMPLE_MALLOC_H_ + +#include "types.h" +#include "debug/debug.h" + +#define req2size(req) ALIGN_UP(req, 16) + +struct malloc_state{ + uint8_t* last_remainder; +}; + +extern void* simple_malloc(size_t); +extern void* simple_malloc_get_remainder(); +#endif diff --git a/lab5/include/lib/string.h b/lab5/include/lib/string.h new file mode 100644 index 000000000..4a6a30cd7 --- /dev/null +++ b/lab5/include/lib/string.h @@ -0,0 +1,19 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#include "types.h" + +extern char * itoa(int32_t, char*, uint32_t); +extern char * utoa(uint32_t, char*, uint32_t); +extern char * ltoa(int64_t, char*, uint32_t); +extern char * ultoa(uint64_t, char*, uint32_t); +extern int32_t strcmp(char*, char*); +extern char *strcpy(char *, const char *); +extern size_t strlen(const char*); +extern void* memcpy(void*, const void*, size_t); +extern void* memset(void*, int, size_t); +extern int32_t memcmp(void*, const void*, size_t); +extern uint8_t hex2dec(char); +extern char* strtok(char*,const char*); +extern uint64_t atoul(const char*); +#endif diff --git a/lab5/include/mm/mm.h b/lab5/include/mm/mm.h new file mode 100644 index 000000000..52532cce5 --- /dev/null +++ b/lab5/include/mm/mm.h @@ -0,0 +1,35 @@ +#ifndef _MM_H_ +#define _MM_H_ + +#include "types.h" +#include "lib/fdt_parse.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "lib/list.h" +#include "lib/string.h" +#include "mm/page_alloc.h" +#include "mm/slab.h" + + +struct mem_block{ + uint64_t start; + uint64_t end; + struct list_head list; +}; + +struct mem_node{ + uint64_t start; + uint64_t end; + char *name; + struct list_head list; +}; + +extern struct list_head mem_rsvmap; +extern struct list_head mem_unusedmap; +extern struct mem_node memory_node; +extern struct page *mem_map; + +extern void mm_init(void *); + + +#endif diff --git a/lab5/include/mm/page_alloc.h b/lab5/include/mm/page_alloc.h new file mode 100644 index 000000000..20f92a7fd --- /dev/null +++ b/lab5/include/mm/page_alloc.h @@ -0,0 +1,58 @@ +#ifndef _PAGE_ALLOC_H_ +#define _PAGE_ALLOC_H_ + +#include "types.h" +#include "lib/list.h" +#include "lib/print.h" +#include "lib/bitops.h" +#include "mm/mm.h" + +#define BUDDY_GROUP_MEMBER 0x80000000 +#define BUDDY_ALLOCATED 0x40000000 +#define BUDDY_MAX_ORDER 7 + +#define PAGE_TYPE_RESERVED 1 +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1ul << PAGE_SHIFT) + +#define BUDDY_IS_ALLOCATED(x) (((struct page*)x)->order & BUDDY_ALLOCATED) +#define BUDDY_IS_MEMBER(x) (((struct page*)x)->order & BUDDY_GROUP_MEMBER) +#define BUDDY_IS_FREED(x) (!BUDDY_IS_ALLOCATED(x)) +#define PAGE_IS_RESERVED(x) (((struct page*)x)->type & PAGE_TYPE_RESERVED) +#define _buddy_ffs(x) ((x) == 0 ? BUDDY_MAX_ORDER : ffs64(x)) +#define addr_to_pfn(addr) ((uint64_t)(addr) >> PAGE_SHIFT) +#define pfn_to_addr(n) ((void*)(n << PAGE_SHIFT)) +#define page_to_pfn(x) ((uint64_t)((struct page*)x - mem_map)) +#define pfn_to_page(x) ((struct page*)&mem_map[x]) +#define find_buddy_pfn(pfn, order) (pfn ^ (1 << order)) +#define get_page_order(p) (p->order & 0xffff) +#define get_buddy_leader(p) (p->buddy_leader) + +struct page{ +// if (order & BUDDY_MEMBER), then it is freed and it is not a buddy leader +// if (order & BUDDY_ALLOCATED), then it is allocated + void* buddy_leader; + uint32_t order; + uint32_t type; + struct list_head list; +}; + +struct free_list{ + size_t count; + struct list_head list; +}; + +struct buddy_system{ + struct free_list free_lists[BUDDY_MAX_ORDER]; +}; + +extern void buddy_init(); +extern void* alloc_page(); +extern void* alloc_pages(uint32_t); +extern void free_pages(void*, uint32_t); +extern void free_page(void*); +extern void debug_buddy(); +extern void print_buddy_statistics(); + +#endif + diff --git a/lab5/include/mm/slab.h b/lab5/include/mm/slab.h new file mode 100644 index 000000000..0558c471e --- /dev/null +++ b/lab5/include/mm/slab.h @@ -0,0 +1,37 @@ +#ifndef _SLAB_H_ +#define _SLAB_H_ + +#include "mm/mm.h" +#include "mm/page_alloc.h" +#include "lib/list.h" +#include "lib/string.h" +#include "debug/debug.h" + +struct slab{ + size_t size; // object size + void* s_mem; // pointe to the first object + int64_t inuse; + struct list_head free_list; // free list + struct list_head list; // next slab +}; + +#define SLAB_ALIGNMENT (ALIGN_UP(sizeof(struct list_head), 0x20)) +#define SLAB_SIZE (ALIGN_UP(sizeof(struct slab), SLAB_ALIGNMENT)) +#define SLAB_MAX_OBJECT_SIZE (PAGE_SIZE * (1 << (BUDDY_MAX_ORDER - 1)) - SLAB_SIZE) + +#define KMEM_MIN_SIZE SLAB_ALIGNMENT +#define KMEM_ALIGNMENT SLAB_ALIGNMENT +#define KMEM_CACHE_NUM (SLAB_MAX_OBJECT_SIZE / KMEM_ALIGNMENT + 1) + +extern struct slab* slab_create(size_t); +extern void slab_destroy(struct slab*); +extern void *slab_alloc(struct slab*); +extern void slab_free(struct slab* , void*); + +extern void* kmalloc(size_t); +extern void kfree(void*); +extern void kmalloc_init(); + +extern void debug_kmalloc(); +extern void debug_slab(); +#endif diff --git a/lab5/include/peripherals/iomapping.h b/lab5/include/peripherals/iomapping.h new file mode 100644 index 000000000..d938d506b --- /dev/null +++ b/lab5/include/peripherals/iomapping.h @@ -0,0 +1,101 @@ +#ifndef _IOMAPPING_H_ +#define _IOMAPPING_H_ + + +/* Physical addresses range from 0x3F000000 to 0x3FFFFFFF for peripherals */ +#define IO_BASE 0x3F000000 + +/* Register's offset of GPIO */ +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL1 (IO_BASE + 0x200004) +#define GPFSEL2 (IO_BASE + 0x200008) +#define GPFSEL3 (IO_BASE + 0x20000C) +#define GPFSEL4 (IO_BASE + 0x200010) +#define GPFSEL5 (IO_BASE + 0x200014) +#define GPSET0 (IO_BASE + 0x20001C) +#define GPSET1 (IO_BASE + 0x200020) +#define GPCLR0 (IO_BASE + 0x200028) +#define GPCLR1 (IO_BASE + 0x20002C) +#define GPLEV0 (IO_BASE + 0x200034) +#define GPLEV1 (IO_BASE + 0x200038) +#define GPEDS0 (IO_BASE + 0x200040) +#define GPEDS1 (IO_BASE + 0x200044) +#define GPREN0 (IO_BASE + 0x20004C) +#define GPREN1 (IO_BASE + 0x200050) +#define GPFEN0 (IO_BASE + 0x200058) +#define GPFEN1 (IO_BASE + 0x20005C) +#define GPHEN0 (IO_BASE + 0x200064) +#define GPHEN1 (IO_BASE + 0x200068) +#define GPLEN0 (IO_BASE + 0x200070) +#define GPLEN1 (IO_BASE + 0x200074) +#define GPAREN0 (IO_BASE + 0x20007C) +#define GPAREN1 (IO_BASE + 0x200080) +#define GPAFEN0 (IO_BASE + 0x200088) +#define GPAFEN1 (IO_BASE + 0x20008C) +#define GPPUD (IO_BASE + 0x200094) +#define GPPUDCLK0 (IO_BASE + 0x200098) +#define GPPUDCLK1 (IO_BASE + 0x20009C) + + +/* Register's offset of UART and SPI */ +#define AUX_IRQ (IO_BASE + 0x215000) +#define AUX_ENABLES (IO_BASE + 0x215004) +#define AUX_MU_IO_REG (IO_BASE + 0x215040) +#define AUX_MU_IER_REG (IO_BASE + 0x215044) +#define AUX_MU_IIR_REG (IO_BASE + 0x215048) +#define AUX_MU_LCR_REG (IO_BASE + 0x21504C) +#define AUX_MU_MCR_REG (IO_BASE + 0x215050) +#define AUX_MU_LSR_REG (IO_BASE + 0x215054) +#define AUX_MU_MSR_REG (IO_BASE + 0x215058) +#define AUX_MU_SCRATCH (IO_BASE + 0x21505C) +#define AUX_MU_CNTL_REG (IO_BASE + 0x215060) +#define AUX_MU_STAT_REG (IO_BASE + 0x215064) +#define AUX_MU_BAUD_REG (IO_BASE + 0x215068) +#define AUX_SPI0_CNTL0_REG (IO_BASE + 0x215080) +#define AUX_SPI0_CNTL1_REG (IO_BASE + 0x215084) +#define AUX_SPI0_STAT_REG (IO_BASE + 0x215088) +#define AUX_SPI0_IO_REG (IO_BASE + 0x215090) +#define AUX_SPI0_PEEK_REG (IO_BASE + 0x215094) +#define AUX_SPI1_CNTL0_REG (IO_BASE + 0x2150C0) +#define AUX_SPI1_CNTL1_REG (IO_BASE + 0x2150C4) +#define AUX_SPI1_STAT_REG (IO_BASE + 0x2150C8) +#define AUX_SPI1_IO_REG (IO_BASE + 0x2150D0) +#define AUX_SPI1_PEEK_REG (IO_BASE + 0x2150D4) + +// mailbox register base address +#define MBOX_REG (IO_BASE + 0xB880) + +// interrupt +#define IRQ_BASIC_PENDING (IO_BASE + 0xB200) +#define IRQ_PENDING_1 (IO_BASE + 0xB204) +#define IRQ_PENDING_2 (IO_BASE + 0xB208) +#define CORE0_IRQ_SOURCE (IO_BASE + 0x1000060) +#define CORE1_IRQ_SOURCE (IO_BASE + 0x1000064) +#define CORE2_IRQ_SOURCE (IO_BASE + 0x1000068) +#define CORE3_IRQ_SOURCE (IO_BASE + 0x100006C) +#define CORE0_FIQ_SOURCE (IO_BASE + 0x1000070) +#define CORE1_FIQ_SOURCE (IO_BASE + 0x1000074) +#define CORE2_FIQ_SOURCE (IO_BASE + 0x1000078) +#define CORE3_FIQ_SOURCE (IO_BASE + 0x100007C) +#define ENABLE_IRQS_1 (IO_BASE + 0xB210) + + +// timer +#define CORE0_TIMER_IRQ_CTRL (IO_BASE + 0x1000040) + + +// watch dog +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_RSTC (IO_BASE + 0x10001c) +#define PM_WDOG (IO_BASE + 0x100024) + +#define IO_MMIO_write32(addr, val) *(uint32_t*)addr = val +#define IO_MMIO_read32(addr) *(uint32_t*)addr +#define IO_MMIO_write64(addr, val) *(uint64_t*)addr = val +#define IO_MMIO_read64(addr) *(uint64_t*)addr + + + +#endif + diff --git a/lab5/include/peripherals/mailbox.h b/lab5/include/peripherals/mailbox.h new file mode 100644 index 000000000..92265354b --- /dev/null +++ b/lab5/include/peripherals/mailbox.h @@ -0,0 +1,176 @@ +#ifndef _MAILBOX_H_ +#define _MAILBOX_H_ + +#include "types.h" +#include "lib/string.h" +#include "debug/debug.h" +#include "peripherals/iomapping.h" +#include "kernel/sched/sched.h" + +#define MBOX_CHANNEL_POWER 0 +#define MBOX_CHANNEL_FRAME_BUF 1 +#define MBOX_CHANNEL_VIRTUAL_UART 2 +#define MBOX_CHANNEL_VCHIQ 3 +#define MBOX_CHANNEL_LEDS 4 +#define MBOX_CHANNEL_BUTTONS 5 +#define MBOX_CHANNEL_TOUCH_SCREEN 6 +#define MBOX_CHANNEL_UNKOWN 7 +#define MBOX_CHANNEL_PROPERTY_TAGS 8 + +enum MBOX_PROPERTY_STATUS { + MBOX_STATUS_REQUEST = 0, + MBOX_STATUS_SUCCESS = 0x80000000, + MBOX_STATUS_ERROR = 0x80000001, +}; + +enum MBOX_PROPERTY_TAG{ + MBOX_PROPERTY_END = 0, + MBOX_GET_FIRMWARE_REVISION = 0x00000001, + + MBOX_SET_CURSOR_INFO = 0x00008010, + MBOX_SET_CURSOR_STATE = 0x00008011, + + MBOX_GET_BOARD_MODEL = 0x00010001, + MBOX_GET_BOARD_REVISION = 0x00010002, + MBOX_GET_BOARD_MAC_ADDRESS = 0x00010003, + MBOX_GET_BOARD_SERIAL = 0x00010004, + MBOX_GET_ARM_MEMORY = 0x00010005, + MBOX_GET_VC_MEMORY = 0x00010006, + MBOX_GET_CLOCKS = 0x00010007, + MBOX_GET_POWER_STATE = 0x00020001, + MBOX_GET_TIMING = 0x00020002, + MBOX_SET_POWER_STATE = 0x00028001, + MBOX_GET_CLOCK_STATE = 0x00030001, + MBOX_GET_CLOCK_RATE = 0x00030002, + MBOX_GET_VOLTAGE = 0x00030003, + MBOX_GET_MAX_CLOCK_RATE = 0x00030004, + MBOX_GET_MAX_VOLTAGE = 0x00030005, + MBOX_GET_TEMPERATURE = 0x00030006, + MBOX_GET_MIN_CLOCK_RATE = 0x00030007, + MBOX_GET_MIN_VOLTAGE = 0x00030008, + MBOX_GET_TURBO = 0x00030009, + MBOX_GET_MAX_TEMPERATURE = 0x0003000a, + MBOX_GET_STC = 0x0003000b, + MBOX_ALLOCATE_MEMORY = 0x0003000c, + MBOX_LOCK_MEMORY = 0x0003000d, + MBOX_UNLOCK_MEMORY = 0x0003000e, + MBOX_RELEASE_MEMORY = 0x0003000f, + MBOX_EXECUTE_CODE = 0x00030010, + MBOX_EXECUTE_QPU = 0x00030011, + MBOX_SET_ENABLE_QPU = 0x00030012, + MBOX_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, + MBOX_GET_EDID_BLOCK = 0x00030020, + MBOX_GET_CUSTOMER_OTP = 0x00030021, + MBOX_GET_DOMAIN_STATE = 0x00030030, + MBOX_SET_CLOCK_STATE = 0x00038001, + MBOX_SET_CLOCK_RATE = 0x00038002, + MBOX_SET_VOLTAGE = 0x00038003, + MBOX_SET_TURBO = 0x00038009, + MBOX_SET_CUSTOMER_OTP = 0x00038021, + MBOX_SET_DOMAIN_STATE = 0x00038030, + MBOX_GET_GPIO_STATE = 0x00030041, + MBOX_SET_GPIO_STATE = 0x00038041, + MBOX_SET_SDHOST_CLOCK = 0x00038042, + MBOX_GET_GPIO_CONFIG = 0x00030043, + MBOX_SET_GPIO_CONFIG = 0x00038043, + MBOX_GET_PERIPH_REG = 0x00030045, + MBOX_SET_PERIPH_REG = 0x00038045, + + + /* Dispmanx TAGS */ + MBOX_FRAMEBUFFER_ALLOCATE = 0x00040001, + MBOX_FRAMEBUFFER_BLANK = 0x00040002, + MBOX_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, + MBOX_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, + MBOX_FRAMEBUFFER_GET_DEPTH = 0x00040005, + MBOX_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006, + MBOX_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007, + MBOX_FRAMEBUFFER_GET_PITCH = 0x00040008, + MBOX_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, + MBOX_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, + MBOX_FRAMEBUFFER_GET_PALETTE = 0x0004000b, + MBOX_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, + MBOX_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010, + MBOX_FRAMEBUFFER_RELEASE = 0x00048001, + MBOX_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, + MBOX_FRAMEBUFFER_TEST_DEPTH = 0x00044005, + MBOX_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006, + MBOX_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, + MBOX_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, + MBOX_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, + MBOX_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, + MBOX_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, + MBOX_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, + MBOX_FRAMEBUFFER_SET_DEPTH = 0x00048005, + MBOX_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006, + MBOX_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007, + MBOX_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + MBOX_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + MBOX_FRAMEBUFFER_SET_PALETTE = 0x0004800b, + MBOX_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + MBOX_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, + MBOX_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + MBOX_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + + MBOX_VCHIQ_INIT = 0x00048010, + + MBOX_GET_COMMAND_LINE = 0x00050001, + MBOX_GET_DMA_CHANNELS = 0x00060001, +}; +/* + * Mailbox Read/Write Peek Sender Status Config + * 0 0x00 0x10 0x14 0x18 0x1c + * 1 0x20 0x30 0x34 0x38 0x3c + */ + +#define MBOX_READ_CHANNEL_MASK 15 +#define MBOX_WRITE_CHANNEL_MASK 15 +#define MBOX_WRITE_ADDR_MASK (~15) +#define MBOX_READ_ADDR_MASK (~15) +#define MBOX_STATUS_FULL_MASK 0x80000000 +#define MBOX_STATUS_EMPTY_MASK 0x40000000 +typedef struct{ + uint32_t read; + uint32_t unused[5]; + uint32_t status; + uint32_t config; + uint32_t write; +}__attribute__((packed)) MBox_register; + +/* 0 4 8 12 16 20 24 28 32 + +---------------------------------------------------------------+ +0x00 | Buffer Size | + +---------------------------------------------------------------+ +0x04 | Request/Response Code | + +---------------------------------------------------------------+ +0x08 | Tags | +... \\ \\ +0xXX | Tags | + +---------------------------------------------------------------+ +0xXX+4 | End Tag (0) | + +---------------------------------------------------------------+ +0xXX+8 | Padding | +... \\ \\ +0xXX+16| Padding | + +---------------------------------------------------------------+ +*/ +#define MBOX_TAG_REQUEST 0 +typedef struct{ + uint32_t id; + uint32_t value_size; + uint32_t code; + uint8_t values[0]; +}MBox_tag; + +typedef struct{ + uint32_t buf_size; + uint32_t code; + uint8_t buf[0]; +}MBox_buffer; + +extern void MBox_get_board_revision(uint32_t*); +extern void MBox_get_arm_memory(uint32_t*); + +#endif diff --git a/lab5/include/peripherals/mini_uart.h b/lab5/include/peripherals/mini_uart.h new file mode 100644 index 000000000..696c0b7fe --- /dev/null +++ b/lab5/include/peripherals/mini_uart.h @@ -0,0 +1,35 @@ +#ifndef _MINI_UART_H_ +#define _MINI_UART_H_ + +#include "types.h" +#include "kernel/sched/sched.h" +#include "asm.h" +#include "peripherals/iomapping.h" +#include "debug/debug.h" +#include "lib/print.h" +#include "lib/ring_buffer.h" + +#define SYSTEM_CLOCK_RATE (250000000) +#define BAUD_RATE 115200 +#define BAUD_RATE_REG (SYSTEM_CLOCK_RATE / (8 * BAUD_RATE) - 1) +#define TX 1 +#define RX 2 +extern void mini_uart_init(); +extern uint8_t mini_uart_read(void); +extern void mini_uart_write(uint8_t); +extern ssize_t write_bytes(uint8_t *, size_t); +extern void write_str(char *); +extern void write_hex(uint64_t); +extern void delay_cycles(uint64_t); +extern void disable_mini_uart_irq(uint32_t); +extern void enable_mini_uart_irq(uint32_t); +extern void mini_uart_irq_init(); +extern void mini_uart_irq_read(); +extern size_t mini_uart_get_rx_len(); +extern uint8_t mini_uart_aio_read(void); +extern size_t mini_uart_get_tx_len(); +extern void enable_mini_uart_rx_irq(); +extern void disable_mini_uart_rx_irq(); +extern void mini_uart_rx_softirq_callback(); + +#endif diff --git a/lab5/include/types.h b/lab5/include/types.h new file mode 100644 index 000000000..c565b425b --- /dev/null +++ b/lab5/include/types.h @@ -0,0 +1,45 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) (((uint64_t)(val) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_DOWN(val, align) ((uint64_t)(val) & ~((align) - 1)) + +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define min(x, y) ((x) < (y) ? (x) : (y)) + +#endif diff --git a/lab5/init/Makefile b/lab5/init/Makefile new file mode 100644 index 000000000..e5b218aa8 --- /dev/null +++ b/lab5/init/Makefile @@ -0,0 +1,24 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + kernel_init.o + +all: $(OBJECTS) + +%.o: %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab5/init/kernel_init.c b/lab5/init/kernel_init.c new file mode 100644 index 000000000..be29b5f6f --- /dev/null +++ b/lab5/init/kernel_init.c @@ -0,0 +1,18 @@ +#include "init/kernel_init.h" + +extern int __heap_start; +void kernel_init(void *dtb){ + init_core_timer(); + mini_uart_init(); + mini_uart_irq_init(); + + local_irq_enable(); + INFO("kernel start initialization..."); + + // memory management initialization + mm_init(dtb); + + fdt_parser(dtb, fdt_initrdfs_callback); + return; +} + diff --git a/lab5/initramfs.cpio b/lab5/initramfs.cpio new file mode 100644 index 000000000..d2c1db2c9 Binary files /dev/null and b/lab5/initramfs.cpio differ diff --git a/lab5/kernel/.gdb_history b/lab5/kernel/.gdb_history new file mode 100644 index 000000000..0e9b7b5ce --- /dev/null +++ b/lab5/kernel/.gdb_history @@ -0,0 +1,25 @@ +file ./../build/kernel8.elf +target remote:1234 +x/gx simple_shell +disassemble simple_shell +b* 0x0000000000081e1c +c +x/i 0x100000 +ni +x/i 0x100000 +b* 0x100008 +ni +quit +file ./../build/kernel8.elf +target remote:1234 +disassemble simple_shell +b* 0x0000000000081e1c +c +ni +x/i 0x1000000 +x/i 0x100000 +b*0x100008 +ni +ni +ni +quit diff --git a/lab5/kernel/Makefile b/lab5/kernel/Makefile new file mode 100644 index 000000000..2a8b23db0 --- /dev/null +++ b/lab5/kernel/Makefile @@ -0,0 +1,40 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + shell.o \ + reboot.o \ + main.o \ + start.o \ + entry.o \ + syscall_test.o \ + syscall_table.o \ + timer.o \ + irq_handler.o \ + signal.o \ + +.PHONY: all sched +all: $(OBJECTS) sched + +sched: + $(MAKE) -C sched OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab5/kernel/entry.S b/lab5/kernel/entry.S new file mode 100644 index 000000000..ddd5879c6 --- /dev/null +++ b/lab5/kernel/entry.S @@ -0,0 +1,174 @@ + .macro ventry label + .align 7 + b \label + .endm + + + .macro save_all + sub sp, sp, 17 * 16 + stp x0, x1, [sp ,16 * 0] + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + mrs x24, sp_el0 + stp x30, x24, [sp, 16 * 15] + + mrs x24, spsr_el1 + mrs x25, elr_el1 + stp x24, x25, [sp, 16 * 16] + .endm + + .macro load_all + ldp x24, x25, [sp, 16 * 16] + msr spsr_el1, x24 + msr elr_el1, x25 + + ldp x30, x24, [sp, 16 * 15] + msr sp_el0, x24 + + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + + add sp, sp, 17 * 16 + + .endm + +.global task_load_all +task_load_all: + load_all + eret + +.global kthread_trampoline +kthread_trampoline: + bl local_irq_enable + mov x0, x19 + bl kthread_start + +// exception vector table +.align 11 +.global EL1_exception_vector_table +EL1_exception_vector_table: +// Exception from the current EL while using SP_EL0 + ventry invalid_handler // Synchronous EL1t + ventry invalid_handler // IRQ EL1t + ventry invalid_handler // FIQ EL1t + ventry invalid_handler // Error EL1t + +// Exception from the current EL while using SP_ELx + ventry el1_sync_invalid_handler// Synchronous EL1h + ventry el1_irq_handler // IRQ EL1h + ventry invalid_handler // FIQ EL1h + ventry invalid_handler // Error EL1h + +// Exception from a lower EL at least one lower EL is AArch64 + ventry el0_sync_handler // Synchronous 64-bit EL0 + ventry el0_irq_handler // IRQ 64-bit EL0 + ventry invalid_handler // FIQ 64-bit EL0 + ventry invalid_handler // Error 64-bit EL0 + +// Exception from a lower EL and all lower ELs are AArch32 + ventry invalid_handler // Synchronous 32-bit EL0 + ventry invalid_handler // IRQ 32-bit EL0 + ventry invalid_handler // FIQ 32-bit EL0 + ventry invalid_handler // Error 32-bit EL0 + +el1_sync_invalid_handler: + mov x0, 135 +invalid_handler: + save_all + mrs x1, esr_el1 + mrs x2, elr_el1 + mrs x3, spsr_el1 + mrs x4, sp_el0 + mov x5, sp + bl err_handler + load_all + eret + + +el0_irq_handler: +el1_irq_handler: + save_all + bl irq_handler + bl schedule + bl handle_signal + load_all + eret + +el0_sync_handler: + save_all + mrs x24, esr_el1 + lsr x24, x24, #26 + cmp x24, #0x15 + + b.eq svc_handler + b nothing + +svc_handler: + bl local_irq_enable + bl syscall_handler + str x0, [sp] + +nothing: + bl handle_signal + load_all + eret + +.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 sigreturn_trampoline +sigreturn_trampoline: + mov x8, 10 + svc 0 + +sigreturn_error: + b sigreturn_error diff --git a/lab5/kernel/irq_handler.c b/lab5/kernel/irq_handler.c new file mode 100644 index 000000000..bc20fe595 --- /dev/null +++ b/lab5/kernel/irq_handler.c @@ -0,0 +1,182 @@ +#include "kernel/irq_handler.h" +struct softirq_status softirq_s = { + .pending = 0, + .in_softirq = 0 +}; + +irq_funcptr softirq_vec[END_OF_LIST] = { + timer_softirq_callback, + mini_uart_rx_softirq_callback, +}; +uint64_t irq_count[END_OF_LIST] = {0, 0, 0}; + +void enter_softirq(){ + softirq_s.in_softirq = 1; +} + +void exit_softirq(){ + softirq_s.in_softirq = 0; +} + +uint8_t in_softirq(){ + return softirq_s.in_softirq; +} + +uint8_t has_softirq_pending(){ + return softirq_s.pending ? 1 : 0; +} + +uint16_t get_softirq_pending(){ + return softirq_s.pending; +} + +void set_softirq_pending(uint16_t val){ + softirq_s.pending = val; +} + + +void add_softirq_task(uint32_t softirq_nr){ + softirq_s.pending |= (1 << softirq_nr); +} + +void do_softirq(){ + uint16_t try = 0; + volatile uint16_t pending; + uint16_t softirq_bit; + irq_funcptr softirq_handler; + + while(try < MAX_SOFTIRQ_TRY){ + pending = get_softirq_pending(); + set_softirq_pending(0); + + local_irq_enable(); + while(pending){ + softirq_bit = ffs16(pending); + softirq_handler = softirq_vec[softirq_bit]; + softirq_handler(); + pending &= ~(1 << softirq_bit); + } + local_irq_disable(); + try++; + } +} + +void do_irq(uint32_t nr, irq_funcptr do_hardirq,irq_funcptr enable_device_irq , irq_funcptr disable_device_irq){ + disable_device_irq(); + irq_count[nr]++; + add_softirq_task(nr); + do_hardirq(); + + if(!in_softirq() && has_softirq_pending()){ + enter_softirq(); + do_softirq(); + exit_softirq(); + } + + enable_device_irq(); +} + +void irq_handler(){ + uint32_t irq_pending_1 = IO_MMIO_read32(IRQ_PENDING_1); + uint32_t core0_irq_source = IO_MMIO_read32(CORE0_IRQ_SOURCE); + uint32_t auxirq, uart_irq_type; + /* + uint32_t irq_pending_2 = IO_MMIO_read32(IRQ_PENDING_2); + uint32_t irq_basic_pending = IO_MMIO_read32(IRQ_BASIC_PENDING); + uint32_t core1_irq_source = IO_MMIO_read32(CORE1_IRQ_SOURCE); + uint32_t core2_irq_source = IO_MMIO_read32(CORE2_IRQ_SOURCE); + uint32_t core3_irq_source = IO_MMIO_read32(CORE3_IRQ_SOURCE); + uint32_t core0_fiq_source = IO_MMIO_read32(CORE0_FIQ_SOURCE); + uint32_t core1_fiq_source = IO_MMIO_read32(CORE1_FIQ_SOURCE); + uint32_t core2_fiq_source = IO_MMIO_read32(CORE2_FIQ_SOURCE); + uint32_t core3_fiq_source = IO_MMIO_read32(CORE3_FIQ_SOURCE); + */ + + + if(core0_irq_source & 2){ + //core timer interrupt + do_irq(CORE0_TIMER, core_timer_irq_handler, enable_core_timer_irq, disable_core_timer_irq); + }else if(irq_pending_1 & (1 << 29)){ + auxirq = IO_MMIO_read32(AUX_IRQ); + if(auxirq & 1){ + uart_irq_type = (IO_MMIO_read32(AUX_MU_IIR_REG) >> 1) & (0b11); + if(uart_irq_type == RX){ + // Receiver holds valid byte + do_irq(MINI_UART_RX, mini_uart_irq_read, enable_mini_uart_rx_irq, disable_mini_uart_rx_irq); + }else{ + irq_count[UNKNOWN_IRQ]++; + LOG("UART interrupt"); + while(1); + } + }else{ + irq_count[UNKNOWN_IRQ]++; + LOG("Unkown AUX interrupt, DAIF: %x", get_DAIF()); + } + } + else{ + irq_count[UNKNOWN_IRQ]++; + LOG("Unkown interrupt"); + } +} + +void err_handler(uint64_t type, uint64_t esr, uint64_t elr, uint64_t spsr_el1, uint64_t sp_el0, uint64_t sp){ + struct task_struct *cur = get_current(); + struct trap_frame *trap_frame = get_trap_frame(cur); + write_str("unkown irq count: "); + write_hex(irq_count[UNKNOWN_IRQ]); + write_str("\r\n"); + + write_str("pid: "); + write_hex(cur->thread_info.pid); + write_str("\r\n"); + + write_str("trap frame: "); + write_hex((uint64_t)get_trap_frame(cur)); + write_str("\r\n"); + + write_str("cur->ctx.lr: "); + write_hex(cur->ctx.lr); + write_str("\r\n"); + + write_str("cur->ctx.sp: "); + write_hex(cur->ctx.sp); + write_str("\r\n"); + + write_str("cur->ctx.fp: "); + write_hex(cur->ctx.fp); + write_str("\r\n"); + + write_str("trap_frame->x0: "); + write_hex(trap_frame->x0); + write_str("\r\n"); + + write_str("kernel stack: "); + write_hex((uint64_t)cur->stack); + write_str("\r\n"); + + write_str("type: "); + write_hex(type); + write_str("\r\n"); + + write_str("esr_el1: "); + write_hex(esr); + write_str("\r\n"); + + write_str("elr_el1: "); + write_hex(get_ELR_EL1()); + write_str("\r\n"); + + write_str("spsr_el1: "); + write_hex(spsr_el1); + write_str("\r\n"); + + write_str("sp_el0: "); + write_hex(sp_el0); + write_str("\r\n"); + + write_str("sp: "); + write_hex(sp); + write_str("\r\n"); + + while(1); +} diff --git a/lab5/kernel/linker.ld b/lab5/kernel/linker.ld new file mode 100644 index 000000000..163f79777 --- /dev/null +++ b/lab5/kernel/linker.ld @@ -0,0 +1,45 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __kernel_image_start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __kernel_image_end = .; + __heap_start = .; + + __EL1_stack_size = 0x4000; + __EL1_stack = 0x80000; +} diff --git a/lab5/kernel/main.c b/lab5/kernel/main.c new file mode 100644 index 000000000..41d5395ea --- /dev/null +++ b/lab5/kernel/main.c @@ -0,0 +1,27 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "init/kernel_init.h" +#include "debug/debug.h" +#include "kernel/shell.h" +#include "kernel/sched/sched.h" +#include "kernel/sched/kthread.h" + +void kernel_main_thread(void){ + INFO("create kthread kthread_idle"); + kthread_create(kthread_idle); + for(uint32_t i = 0 ; i < 10 ; i++){ + INFO("create kthread kthread_test"); + kthread_create(kthread_test); + } + INFO("create kthread simple_shell"); + kthread_create(simple_shell); +} + +void kernel_main(void *dtb){ + kernel_init(dtb); + DEBUG_KERNEL_START(); + + INFO("create kernel main thread"); + kthread_create(kernel_main_thread); +} + diff --git a/lab5/kernel/reboot.c b/lab5/kernel/reboot.c new file mode 100644 index 000000000..2511cc06e --- /dev/null +++ b/lab5/kernel/reboot.c @@ -0,0 +1,14 @@ +#include "types.h" +#include "peripherals/iomapping.h" +#include "kernel/reboot.h" + +void reboot(int ticks){ + unsigned int pm_rstc,pm_wdog; + pm_rstc = IO_MMIO_read32(PM_RSTC); + + pm_wdog = PM_PASSWORD | (ticks & PM_WDOG_TIME_SET); + pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; + + IO_MMIO_write32(PM_RSTC, pm_rstc); + IO_MMIO_write32(PM_WDOG, pm_wdog); +} diff --git a/lab5/kernel/sched/Makefile b/lab5/kernel/sched/Makefile new file mode 100644 index 000000000..6b4756fe2 --- /dev/null +++ b/lab5/kernel/sched/Makefile @@ -0,0 +1,30 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../../include +OBJECTS = \ + sched.o \ + kthread.o \ + task.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab5/kernel/sched/kthread.c b/lab5/kernel/sched/kthread.c new file mode 100644 index 000000000..46c779fee --- /dev/null +++ b/lab5/kernel/sched/kthread.c @@ -0,0 +1,107 @@ +#include "kernel/sched/kthread.h" + +extern void kthread_trampoline(); + +void kthread_destroy(struct task_struct* task){ +// LOG("kthread_destroy %l", task->thread_info.pid); + list_del(&task->list); + free_pages(task->stack, 1); + kfree(task); +} +void _kthread_remove_zombies(){ + struct list_head* node; + struct task_struct* zombie; + volatile uint64_t daif; + //volatile uint64_t daif; + //daif = local_irq_disable_save(); + local_irq_disable(); + while(!list_empty(&zombies)){ + zombie = list_first_entry(&zombies, struct task_struct, zombie); + LOG("Remove %l", zombie->thread_info.pid); + list_del(zombies.next); + if(zombie->mm == NULL) kthread_destroy(zombie); + else task_destroy(zombie); + } + local_irq_enable(daif); + //local_irq_restore(daif); +} + +void kthread_idle(){ + while(1){ + preempt_schedule(); + _kthread_remove_zombies(); + } +} + +void kthread_test(){ + struct task_struct* cur; + cur = get_current(); + for(uint32_t i = 0 ; i < 10 ; i++){ + printf("%u: pid: %l\r\n",i , cur->thread_info.pid); + for(uint32_t j = 0 ; j < 100000 ; j ++){ + asm volatile("nop"); + } + } +} + +uint64_t kthread_create(kthread_func func){ + LOG("kthread enter"); + volatile uint64_t daif; + struct task_struct* kthread = (struct task_struct*)kmalloc(sizeof(struct task_struct)); + + // initialize kernel stack + kthread->stack = alloc_pages(1); + + // initialize thread_info + kthread->thread_info.pid = get_pid_counter(); + kthread->thread_info.state = TASK_RUNNING; + + // initialize thread context + kthread->ctx.lr = (uint64_t)kthread_trampoline; + kthread->ctx.x19 = (uint64_t)func; + kthread->ctx.sp = (uint64_t)kthread->stack + PAGE_SIZE * 2; + kthread->ctx.fp = kthread->ctx.sp; + + // initialize mm + kthread->mm = NULL; + + // initialize relationship + kthread->parent = NULL; + kthread->child = NULL; + INIT_LIST_HEAD(&kthread->siblings); + + // initialize schedule info + kthread->sched_info.rticks = 0; + kthread->sched_info.priority = 1; + kthread->sched_info.counter = kthread->sched_info.priority; + list_add_tail(&kthread->list, &task_list); + + // initialzie singal + sigpending_init(&kthread->sigpending); + default_sighand_init(&kthread->sighandler); + + LOG("kthread end"); + daif = local_irq_disable_save(); + add_task_to_rq(kthread); + local_irq_restore(daif); + return 0; +} + +void kthread_start(kthread_func func){ + func(); + kthread_exit(); +} + +void kthread_exit(){ + volatile uint64_t daif; + LOG("kthread_exit start"); + struct task_struct* cur; + cur = get_current(); + cur->thread_info.state = TASK_DEAD; + + daif = local_irq_disable_save(); + list_add_tail(&cur->zombie, &zombies); + local_irq_restore(daif); + LOG("kthread_exit end"); + preempt_schedule(); +} diff --git a/lab5/kernel/sched/sched.c b/lab5/kernel/sched/sched.c new file mode 100644 index 000000000..8adc041d4 --- /dev/null +++ b/lab5/kernel/sched/sched.c @@ -0,0 +1,98 @@ +#include "kernel/sched/sched.h" + +LIST_HEAD(zombies); +LIST_HEAD(rq); +LIST_HEAD(task_list); +uint64_t pid_count = 0; +int need_sched = 0; +struct task_struct* user_init = NULL; + +void add_task_to_rq(struct task_struct *task){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + task->thread_info.state = TASK_RUNNING; + + list_add_tail(&task->sched_info.sched_list, &rq); + need_sched = 1; + local_irq_restore(daif); +} + +struct task_struct* pick_next_task_from_rq(){ + if(!list_empty(&rq)) + return list_first_entry(&rq, struct task_struct, sched_info.sched_list); + else + return NULL; +} + +void schedule(){ + struct task_struct* current, *next; + // prevent running scheduler in softirq + if(in_softirq()){ + return; + } + + if(need_sched){ + need_sched = 0; + next = pick_next_task_from_rq(); + + // add current task to schdule list + current = get_current(); + if( current != NULL && current->thread_info.state != TASK_DEAD){ + current->sched_info.counter = current->sched_info.priority; + list_add_tail(¤t->sched_info.sched_list, &rq); + } + + // context switch + if(next != NULL){ + list_del(&next->sched_info.sched_list); + switch_to(current, next); + } + } +} + +void preempt_schedule(){ + local_irq_disable(); + need_sched = 1; + schedule(); + local_irq_enable(); +} + +pid_t get_pid_counter(void){ + pid_t ret; + ret = pid_count++; + return ret; +} + +struct task_struct* find_task_by_pid(uint64_t pid){ + struct list_head *node; + struct task_struct *tmp_task; + uint64_t daif; + + daif = local_irq_disable_save(); + list_for_each(node, &task_list){ + tmp_task = list_entry(node, struct task_struct, list); + if(tmp_task->thread_info.pid == pid){ + local_irq_restore(daif); + return tmp_task; + } + } + local_irq_restore(daif); + return NULL; +} + + +/* debug */ +void print_rq(void){ + struct list_head *node; + struct task_struct *tmp_task; + struct task_pid *tmp_task_pid; + volatile uint64_t daif; + // In printf, interrupt will be enable, so we can't directly print run queue + daif = local_irq_disable_save(); + list_for_each(node, &task_list){ + tmp_task = list_entry(node, struct task_struct, list); + printf("%l ", tmp_task->thread_info.pid); + } + local_irq_restore(daif); + printf("\r\n"); +} diff --git a/lab5/kernel/sched/task.c b/lab5/kernel/sched/task.c new file mode 100644 index 000000000..780d75c4d --- /dev/null +++ b/lab5/kernel/sched/task.c @@ -0,0 +1,366 @@ +#include "kernel/sched/task.h" + +extern void task_load_all(void); + +void task_init(){ +} + +uint64_t task_dup(struct task_struct* parent){ + LOG("task_dup start"); + volatile uint64_t daif; + struct task_struct* child = (struct task_struct*)kmalloc(sizeof(struct task_struct)); + struct vm_area_struct* pvma, *ppvma; + struct vm_area_struct_list* pvmal, *ppvmal; + struct list_head *node; + struct trap_frame *pptrap_frame; + struct trap_frame *pctrap_frame; + uint64_t child_pid; + uint64_t user_sp, kernel_sp; + uint64_t user_fp, kernel_fp; + + + daif = local_irq_disable_save(); + + // fix child's kernel stack + child->stack = alloc_pages(1); + memcpy(child->stack, parent->stack, PAGE_SIZE * 2); + + pptrap_frame = get_trap_frame(parent); + // initialize mm + child->mm = kmalloc(sizeof(struct mm_struct)); + INIT_LIST_HEAD(&child->mm->mmap_list); + list_for_each(node, &parent->mm->mmap_list){ + ppvmal = list_entry(node, struct vm_area_struct_list, list); + ppvma = ppvmal->vm_area; + + LOG("parent's vm area type 0x%x", ppvma->type); + if(ppvma->type == VM_AREA_STACK){ + // user stack + pvma = kmalloc(sizeof(struct vm_area_struct)); + pvmal = kmalloc(sizeof(struct vm_area_struct_list)); + pvma->type = ppvma->type; + pvma->vm_start = (uint64_t)alloc_pages(1); + pvma->vm_end = pvma->vm_start + PAGE_SIZE * 2; + pvma->ref = 1; + pvmal->vm_area = pvma; + + LOG("parent user stack 0x%x", ppvma->vm_end); + LOG("Create child user stack 0x%x", pvma->vm_end); + + memcpy((void*)pvma->vm_start, (void*)ppvma->vm_start, PAGE_SIZE * 2); + user_sp = pvma->vm_end - (ppvma->vm_end - pptrap_frame->sp_el0); + LOG("parent's sp 0x%x", pptrap_frame->sp_el0); + LOG("user_sp 0x%x", user_sp); + + user_fp = pvma->vm_end - (ppvma->vm_end - pptrap_frame->x29); + LOG("parent's fp 0x%x", pptrap_frame->x29); + LOG("user_fp 0x%x", user_fp); + }else{ + pvmal = kmalloc(sizeof(struct vm_area_struct_list)); + pvmal->vm_area = ppvma; + ppvma->ref++; + } + list_add_tail(&pvmal->list, &child->mm->mmap_list); + } + + // fix child's trap frame + pctrap_frame = get_trap_frame(child); + LOG("parent kernel stack: %x\r\n", parent->stack + PAGE_SIZE * 2); + LOG("child trap stack: %x\r\n", child->stack + PAGE_SIZE * 2); + + LOG("parent trap frame: %x\r\n", pptrap_frame); + LOG("child trap frame: %x\r\n", pctrap_frame); + pctrap_frame->x29 = user_fp; + pctrap_frame->sp_el0 = user_sp; + pctrap_frame->spsr_el1 = 0; + // set child's return value to 0 + pctrap_frame->x0 = 0; + + // initialize thread_info + child->thread_info.pid = get_pid_counter(); + child_pid = child->thread_info.pid; + child->thread_info.state = TASK_RUNNING; + + // initialize thread context + // directly back to user space + memcpy(&child->ctx, &parent->ctx, sizeof(struct task_ctx)); + child->ctx.lr = (uint64_t)task_load_all; + child->ctx.sp = (uint64_t)pctrap_frame; + child->ctx.fp = (uint64_t)pctrap_frame; + + // initialize child's relationship + child->parent = parent; + child->child = NULL; + INIT_LIST_HEAD(&child->siblings); + + // initialize parent's relationship + if(parent->child != NULL){ + list_add_tail(&child->siblings, &parent->child->siblings); + }else{ + parent->child = child; + } + + // initialize schedule info + child->sched_info.rticks = 0; + child->sched_info.priority = parent->sched_info.priority ; + child->sched_info.counter = child->sched_info.priority; + + // initialzie singal + sigpending_init(&child->sigpending); + memcpy(&child->sighandler, &parent->sighandler, sizeof(struct sighand_struct)); + + // insert task to run queue and task list + list_add_tail(&child->list, &task_list); + local_irq_restore(daif); + add_task_to_rq(child); + LOG("task_dup end"); + return child_pid; +} + +void task_kill(uint64_t pid){ + LOG("task_kill start"); + volatile uint64_t daif; + struct task_struct* target; + struct task_struct* current; + + target = find_task_by_pid(pid); + if(target == NULL || (target->thread_info.state == TASK_DEAD)) return; + + current = get_current(); + + daif = local_irq_disable_save(); + + target->thread_info.state = TASK_DEAD; + list_add_tail(&target->zombie, &zombies); + if(target != current){ + list_del(&target->sched_info.sched_list); + } + + local_irq_restore(daif); + + LOG("task_kill end"); + + preempt_schedule(); +} + +void task_exit(){ + volatile uint64_t daif; + LOG("task_exit start"); + struct task_struct* cur; + cur = get_current(); + cur->thread_info.state = TASK_DEAD; + + daif = local_irq_disable_save(); + list_add_tail(&cur->zombie, &zombies); + local_irq_restore(daif); + LOG("task_exit end"); + preempt_schedule(); +} + +void task_destroy(struct task_struct* task){ + struct vm_area_struct *vm_area; + struct vm_area_struct_list *vm_area_list; + struct list_head* node; + struct task_struct* child; + + list_del(&task->list); + + // free kernel stack + free_pages(task->stack, 1); + + // free mm + while(!list_empty(&task->mm->mmap_list)){ + vm_area_list = list_first_entry(&task->mm->mmap_list, struct vm_area_struct_list, list); + vm_area = vm_area_list->vm_area; + vm_area->ref--; + + if(vm_area->ref <= 0){ + if(vm_area->type == VM_AREA_PROGRAM) free_pages((void*)vm_area->vm_start, BUDDY_MAX_ORDER - 1); + else if(vm_area->type == VM_AREA_STACK) free_pages((void*)vm_area->vm_start, 1); + kfree(vm_area); + } + + list_del(&vm_area_list->list); + kfree(vm_area_list); + } + kfree(task->mm); + + //unlink from parent and sibliings and set re-parent + if(task->parent){ + //unlink from parent + if(task->parent->child == task){ + child = list_first_entry(&task->siblings, struct task_struct, siblings); + task->parent->child = child; + list_del(&task->siblings); + } + // re-parent + if(task->child){ + task->child->parent = task->parent; + list_for_each(node, &task->child->siblings){ + child = list_entry(node, struct task_struct, siblings); + child->parent = task->parent; + } + list_splice_tail(&task->child->siblings, &task->parent->child->siblings); + list_add_tail(&task->child->siblings, &task->parent->child->siblings); + } + } + + kfree(task); + if(user_init == task) user_init = NULL; +} + +int task_exec(const char* name, char* const argv[]){ + LOG("enter task_exec"); + LOG("file name: %s", name); + int ret = -1; + struct list_head* node; + struct vm_area_struct *pvma; + struct vm_area_struct_list *pvmal; + struct task_struct* current = get_current(); + struct trap_frame *trap_frame = get_trap_frame(current); + volatile uint64_t daif; + size_t s; + + daif = local_irq_disable_save(); + // initialize mm + if(s = initrdfs_filesize((char*)name)){ + list_for_each(node, ¤t->mm->mmap_list){ + LOG("node[-1]: %x", ((uint64_t*)node)[-1]); + pvmal = list_entry(node, struct vm_area_struct_list, list); + LOG("pvmal: %x", pvmal); + pvma = pvmal->vm_area; + LOG("pvma: %x", pvma); + if(pvma->type == VM_AREA_STACK){ + trap_frame->sp_el0 = pvma->vm_end; + }else if(pvma->type == VM_AREA_PROGRAM){ + pvma->ref--; + if(pvma->ref <= 0){ + free_pages((void*)pvma->vm_start, BUDDY_MAX_ORDER - 1); + }else{ + pvma = kmalloc(sizeof(struct vm_area_struct)); + } + pvmal->vm_area = pvma; + pvma->vm_start = (uint64_t)alloc_pages(BUDDY_MAX_ORDER - 1); + trap_frame->elr_el1 = pvma->vm_start; + initrdfs_loadfile((char*)name, (void*)pvma->vm_start); + pvma->vm_end = pvma->vm_start + (1 << (BUDDY_MAX_ORDER - 1)) * PAGE_SIZE; + pvma->type = VM_AREA_PROGRAM; + pvma->ref = 1; + }else{ + printf("unkown vm area\r\n"); + while(1); + } + } + trap_frame->spsr_el1 = 0; + ret = 0; + } + // initialize signal + default_sighand_init(¤t->sighandler); + + local_irq_restore(daif); + LOG("end task_exec"); + return ret; +} + +void run_init_task(char* filename){ + uint64_t size; + struct vm_area_struct* pvma; + struct vm_area_struct_list* pvmal; + uint64_t user_entry, user_sp; + struct trap_frame* ptrap_frame; + volatile uint64_t daif; + LOG("run_init_task enter"); + LOG("Size of struct trap_frame: %x", sizeof(struct trap_frame)); + + daif = local_irq_disable_save(); + struct task_struct* task = (struct task_struct*)kmalloc(sizeof(struct task_struct)); + + // initialize mm + // load executable + size = initrdfs_filesize(filename); + task->mm = kmalloc(sizeof(struct mm_struct)); + INIT_LIST_HEAD(&task->mm->mmap_list); + // create text memory area + pvma = kmalloc(sizeof(struct vm_area_struct)); + pvmal = kmalloc(sizeof(struct vm_area_struct_list)); + pvma->vm_start = (uint64_t)alloc_pages(BUDDY_MAX_ORDER - 1); + pvma->vm_end = pvma->vm_start + (1 << (BUDDY_MAX_ORDER - 1)) * PAGE_SIZE; + pvma->ref = 1; + pvma->type = VM_AREA_PROGRAM; + pvmal->vm_area = pvma; + list_add_tail(&pvmal->list, &task->mm->mmap_list); + // copy file to text memory area + initrdfs_loadfile(filename, (void*)pvma->vm_start); + user_entry = (uint64_t)pvma->vm_start; + LOG("pvmal: %x", pvmal); + // create user stack + pvma = kmalloc(sizeof(struct vm_area_struct)); + pvmal = kmalloc(sizeof(struct vm_area_struct_list)); + pvma->vm_start = (uint64_t)alloc_pages(1); + pvma->vm_end = pvma->vm_start + PAGE_SIZE * 2; + pvma->ref = 1; + pvma->type = VM_AREA_STACK; + pvmal->vm_area = pvma; + list_add_tail(&pvmal->list, &task->mm->mmap_list); + user_sp = (uint64_t)pvma->vm_end; + + LOG("pvmal: %x", pvmal); + // create kernel stack + task->stack = alloc_pages(1); + + // initialize trap frame in kernel stack + ptrap_frame = (struct trap_frame*)get_trap_frame(task); + ptrap_frame->spsr_el1 = 0x0; + ptrap_frame->sp_el0 = user_sp; + ptrap_frame->elr_el1 = user_entry; + + // initialize thread_info + task->thread_info.pid = get_pid_counter(); + task->thread_info.state = TASK_RUNNING; + + // initialize thread context + task->ctx.lr = (uint64_t)task_load_all; + task->ctx.sp = (uint64_t)get_trap_frame(task); + task->ctx.fp = task->ctx.sp; + + // initialize relationship + task->parent = NULL; + task->child = NULL; + INIT_LIST_HEAD(&task->siblings); + + // initialize schedule info + task->sched_info.rticks = 0; + task->sched_info.priority = 1; + task->sched_info.counter = task->sched_info.priority; + + // initialzie singal + sigpending_init(&task->sigpending); + default_sighand_init(&task->sighandler); + + // insert task to run queue and task list + user_init = task; + list_add_tail(&task->list, &task_list); + local_irq_restore(daif); + + LOG("run_init_task end"); + add_task_to_rq(task); +} + +uint64_t sys_fork(){ + return task_dup(get_current()); +} + +uint64_t sys_getpid(){ + return get_current()->thread_info.pid; +} + +void sys_exit(uint64_t status){ + task_exit(status); +} + +void sys_kill(uint64_t pid){ + task_kill(pid); +} +uint64_t sys_exec(const char* name, char *const argv[]){ + return task_exec(name, argv); +} diff --git a/lab5/kernel/shell.c b/lab5/kernel/shell.c new file mode 100644 index 000000000..7b860454f --- /dev/null +++ b/lab5/kernel/shell.c @@ -0,0 +1,178 @@ +#include "kernel/shell.h" + +char *miku_ascii = "⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀\r\n⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁\r\n⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀\r\n⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀\r\n⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀\r\n⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀\r\n⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀\r\n⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀\r\n⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀\r\n⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀\r\n⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀"; +char buf[0x2000]; + +void print_irq_count(void){ + printf("irq_count: "); + for(uint32_t i = 0 ; i < END_OF_LIST ; i++){ + printf("%l ", irq_count[i]); + } + printf("\r\n"); +} + +void setTimeout_callback(void* data){ + uint64_t t = get_jiffies(); + printf("Elapsed time after booting: %l.%l\r\n", t / HZ, t % HZ); + print_irq_count(); + printf("Your message: %s\r\n",(char*) data); +} + + +void simple_shell(){ + unsigned int i; + char ch, *token; + printf(miku_ascii); + printf("\r\n\r\n"); + while(1){ + i = 0; + buf[0] = '\0'; + printf("# "); + // read command + while(1){ + ch = (char)getchar(); + if(ch == '\r'){ + printf("\r\n"); + buf[i] = '\0'; + break; + }else if(ch != '\n'){ + putchar(ch); + buf[i] = ch; + i++; + } + } + + token = strtok(buf, DELIM); + if(token == NULL) continue; + // match comman + if(strcmp(token, "help") == 0){ + printf("help : print this help menu\r\n" \ + "hello : print Hello World!\r\n" \ + "info : print hardware infomation\r\n" \ + "ls : list files\r\n" \ + "cat : cat files\r\n" \ + "load : load user program\r\n" \ + "time : print time after booting\r\n" \ + "reboot : reboot the device\r\n" \ + "setTimeout : set a N seconds timer task\r\n" \ + " setTimeout \r\n" \ + "irq_count : list irq count\r\n" + "alloc_pages : get pages\r\n" \ + " alloc_pages \r\n" \ + "free_pages : free pages\r\n" \ + " free_pages \r\n" \ + "kmalloc : get an object\r\n" \ + " kmalloc \r\n" \ + "kfree : free an object\r\n" \ + " kfree \r\n" \ + + "page_info : get buddy system's statistics\r\n" \ + "print_rq : print run queue\r\n" \ + + ); + + }else if(strcmp(token, "hello") == 0){ + printf("Hello World!\r\n"); + }else if(strcmp(token, "info") == 0){ + uint32_t tmp[2]; + MBox_get_board_revision(tmp); + printf("Board revision: 0x%x\r\n", tmp[0]); + + MBox_get_arm_memory(tmp); + printf("Memory base: 0x%x\r\n", tmp[0]); + printf("Memory size: 0x%x\r\n", tmp[1]); + }else if(strcmp(token, "reboot") == 0){ + printf("Start rebooting...\r\n"); + reboot(100); + while(1); + }else if(strcmp(token, "ls") == 0){ + initrdfs_ls(); + }else if(strcmp(token, "cat") == 0){ + initrdfs_cat(); + }else if(strcmp(token, "load") == 0){ + /*( initrdfs_loadfile("test.img",(uint8_t*) 0x100000); + asm volatile("mov x0, 0x0\n\t" + "msr spsr_el1, x0\n\t" + "mov x0, 0x100000\n\t" + "msr sp_el0, x0\n\t" + "mov x0, #0x100000\n\t" + "msr elr_el1, x0\n\t" + "eret\n\t" + );*/ + run_init_task("syscall.img"); + while(1){ + local_irq_disable(); + if(user_init == NULL) break; + preempt_schedule(); + local_irq_enable(); + } + local_irq_enable(); + }else if(strcmp(token, "time") == 0){ + uint64_t j = get_jiffies(); + printf("Elapsed time after booting: %l.%l\r\n", j / HZ, j % HZ); + }else if(strcmp(token, "setTimeout") == 0){ + uint64_t j = 0, len = 0, timeout = 0; + char *data = NULL; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + len = strlen(token); + data = (char*)simple_malloc(len + 1); + strcpy(data, token); + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + timeout = atoul(token); + + j = get_jiffies(); + add_timer(setTimeout_callback, data, timeout * 1000); + printf("Elapsed time after booting: %l.%l\r\n", j / HZ, j % HZ); + print_irq_count(); + printf("Timer will trigger after %l seconds\r\n", timeout); + }else if(strcmp(token, "irq_count") == 0){ + print_irq_count(); + }else if(strcmp(token, "alloc_pages") == 0){ + uint32_t order; + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + order = atoul(token); + p = alloc_pages(order); + printf("Allocate pages at %l\r\n", p); + }else if(strcmp(token, "free_pages") == 0){ + void* p; + struct page* page; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + p = (void*)atoul(token); + page = pfn_to_page(addr_to_pfn(p)); + + free_pages(p, get_page_order(page)); + printf("Free pages\r\n"); + }else if(strcmp(token, "kmalloc") == 0){ + uint32_t size; + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + size = atoul(token); + p = kmalloc(size); + printf("Allocate an object at %l\r\n", p); + }else if(strcmp(token, "kfree") == 0){ + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + p = (void*)atoul(token); + + kfree(p); + printf("Free an object\r\n"); + }else if(strcmp(token, "page_info") == 0){ + print_buddy_statistics(); + }else if(strcmp(token, "print_rq") == 0){ + print_rq(); + } + } +} diff --git a/lab5/kernel/signal.c b/lab5/kernel/signal.c new file mode 100644 index 000000000..628930ef1 --- /dev/null +++ b/lab5/kernel/signal.c @@ -0,0 +1,192 @@ +#include "kernel/sched/task.h" +#include "kernel/signal.h" +#include "kernel/signal_inner.h" + +extern void sigreturn_trampoline(); + +int is_valid_signal(int signal){ + return (signal > 0 && signal < SIG_MAX_NUM); +} +void sigpending_init(struct sigpending* sigpending){ + INIT_LIST_HEAD(&sigpending->pending); + sigpending->cur_signal = 0; +} + +void default_sighand_init(struct sighand_struct* sighandler){ + memcpy(sighandler->actions, default_actions, sizeof(default_actions)); +} + +int send_signal(uint64_t pid, int signal){ + LOG("enter send_signal, pid: %l signal %d", pid, signal); + struct task_struct* target = find_task_by_pid(pid); + struct signal_queue* sigq; + volatile uint64_t daif; + + if(!is_valid_signal(signal) || target == NULL) return 0; + + LOG("target %p", target); + sigq = kmalloc(sizeof(struct signal_queue)); + + daif = local_irq_disable_save(); + + sigq->signal = signal; + list_add_tail(&sigq->list, &target->sigpending.pending); + + local_irq_restore(daif); + + LOG("end send_signal"); + return 0; +} + +int register_signal(int signal, sig_handler handler){ + LOG("enter register_signal"); + uint64_t daif; + int ret; + struct task_struct* current = get_current(); + + if(current == NULL) return -1; + + LOG("signal: %d, handler: %p", signal, handler); + daif = local_irq_disable_save(); + // install signal handler from user space + if(is_valid_signal(signal)){ + current->sighandler.actions[signal].sa_flags &= ~(SIG_FLAG_KERNEL); + current->sighandler.actions[signal].sa_handler = handler; + + local_irq_restore(daif); + return 0; + } + + local_irq_restore(daif); + return -1; +} + +void handle_sigreturn(){ + sigreturn_frame_restore(); +} + +int get_pending_signal(struct task_struct *task){ + struct signal_queue* sigq; + uint64_t signal = 0; + if(!list_empty(&task->sigpending.pending)){ + sigq = list_first_entry(&task->sigpending.pending, struct signal_queue, list); + signal = sigq->signal; + list_del(&sigq->list); + kfree(sigq); + LOG("get pending signal %d", signal); + } + return signal; +} + +void handle_signal(){ + int cur_signal; + volatile uint64_t daif; + struct sigaction* action; + struct task_struct* current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + if(current == NULL) return; + + daif = local_irq_disable_save(); + + cur_signal = get_pending_signal(current); + if(!is_valid_signal(cur_signal)) return; + LOG("handle signal %d", cur_signal); + + action = ¤t->sighandler.actions[cur_signal]; + current->sigpending.cur_signal = cur_signal; + + if(action->sa_flags & SIG_FLAG_KERNEL){ + // if signal handler is in kernel space, just directly execute it + LOG("execute kernel signal handler"); + action->sa_handler(); + }else{ + // if signal handler is in user space, execute it in user space by modify trap frame + LOG("execute user signal handler"); + sigreturn_frame_save(action->sa_handler); + } + + local_irq_restore(daif); +} + +void sigreturn_frame_save(sig_handler handler){ + LOG("enter sigreturn_frame_save"); + struct task_struct* current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + uint64_t old_trap_frame; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + // store a copy of current trap frame onto user stack + old_trap_frame = trap_frame->sp_el0 - sizeof(struct trap_frame); + memcpy((void*)old_trap_frame, trap_frame, sizeof(struct trap_frame)); + + // change sp to point to this copy + trap_frame->sp_el0 = old_trap_frame; + + // set elr_el1 to handler + // set lr to jump to our sigreturn_trampoline + // so that when task return to user from kernel mode, it will back to sigreturn_trampoline + trap_frame->x30 = (uint64_t)sigreturn_trampoline; // in entry.S + trap_frame->elr_el1 = (uint64_t)handler; // in entry.S + + local_irq_restore(daif); + LOG("end sigreturn_frame_save"); +} + +void sigreturn_frame_restore(){ + LOG("enter sigreturn_frame_restore"); + struct task_struct* current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + struct trap_frame* old_trap_frame; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + // restore old trap frame + old_trap_frame = (struct trap_frame*)trap_frame->sp_el0; + memcpy(trap_frame, old_trap_frame, sizeof(struct trap_frame)); + + local_irq_restore(daif); + LOG("end sigreturn_frame_restore"); +} + +void sig_terminate(){ + struct task_struct *current = get_current(); + uint64_t pid; + volatile uint64_t daif; + LOG("enter signal_terminate"); + + daif = local_irq_disable_save(); + + pid = current->thread_info.pid; + printf("pid: %l, Receive signal: %s\r\n",pid ,sig_to_str[current->sigpending.cur_signal]); + local_irq_restore(daif); + + task_exit(); +} + +void sig_default(){ + struct task_struct *current = get_current(); + uint64_t pid; + volatile uint64_t daif; + LOG("enter signal_default"); + + daif = local_irq_disable_save(); + + pid = current->thread_info.pid; + printf("pid: %l, Receive signal: %s\r\n",pid , sig_to_str[current->sigpending.cur_signal]); + local_irq_restore(daif); + + LOG("end signal_default"); +} + +void sys_sigreturn(){ + handle_sigreturn(); +} + +void sys_signal(int signal, sig_handler handler){ + register_signal(signal, handler); +} + +int sys_sigkill(uint64_t pid, int signal){ + return send_signal(pid, signal); +} diff --git a/lab5/kernel/start.S b/lab5/kernel/start.S new file mode 100644 index 000000000..7b4d17321 --- /dev/null +++ b/lab5/kernel/start.S @@ -0,0 +1,61 @@ +.section ".text.boot" +.global _start +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #0xff + + // cpu id > 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + +// cpu id == 0 +master_core: + adr x1, _dtb + str x0, [x1] +// initialize .bss section + ldr x1, =__bss_start + ldr x2, =__bss_end +bss_zero: + sub x3, x2, x1 + cbz x3, end + str xzr, [x1], #8 // store zero to [x1] and add 8 to x1 + b bss_zero + +end: +// modify vbar_el1 before changing exception level to 1 + adr x0, EL1_exception_vector_table + msr vbar_el1, x0 + +// from el2 to el1 + bl from_el2_to_el1 + +// set tpidr_el1 to NULL + mov x1, 0 + msr tpidr_el1, x1 + +// kernel_main(_dtb) + adr x1, _dtb + ldr x0, [x1] + +// jump to kernel_main + bl kernel_main + b proc_hang +from_el2_to_el1: + ldr x0, =__EL1_stack // Set el1 stack to __EL1_stack + msr sp_el1, x0 + + mov x0, (1 << 31) // Set hcr_el2.RW so EL1 uses aarch64 + msr hcr_el2, x0 + + mov x0, 0x3c5 // EL1h (SPSel = 1) + msr spsr_el2, x0 + msr elr_el2, lr + eret // return to EL1 + +.section ".data" +_dtb: .dword 0 + diff --git a/lab5/kernel/syscall_table.c b/lab5/kernel/syscall_table.c new file mode 100644 index 000000000..8834caa85 --- /dev/null +++ b/lab5/kernel/syscall_table.c @@ -0,0 +1,63 @@ +#include "kernel/syscall_table.h" + +uint64_t syscall_handler(){ + struct task_struct *current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + uint64_t NR_syscall = trap_frame->x8; + uint64_t x0, x1, x2, x3, x4; + uint64_t ret; + + switch(NR_syscall){ + case 0: + ret = sys_getpid(); + break; + case 1: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_uart_read((uint8_t*)x0, x1); + break; + case 2: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_uart_write((uint8_t*)x0, x1); + break; + case 3: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_exec((const char *)x0, (char **const)x1); + break; + case 4: + ret = sys_fork(); + break; + case 5: + x0 = trap_frame->x0; + sys_exit(x0); + break; + case 6: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_mbox_call(x0, (uint32_t*)x1); + break; + case 7: + x0 = trap_frame->x0; + sys_kill(x0); + break; + case 8: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + sys_signal((int)x0,(void (*)())x1); + break; + case 9: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + sys_sigkill((uint64_t)x0,(int)x1); + break; + case 10: + sys_sigreturn(); + break; + default: + printf("Unknown system call\r\n"); + while(1); + } + return ret; +} diff --git a/lab5/kernel/syscall_test.c b/lab5/kernel/syscall_test.c new file mode 100644 index 000000000..b5dd80c13 --- /dev/null +++ b/lab5/kernel/syscall_test.c @@ -0,0 +1,17 @@ +#include "types.h" +#include "debug/debug.h" +#include "asm.h" +#include "lib/print.h" +uint64_t sys_hello(uint64_t x0){ + LOG("Enter sys_hello"); + printf("CurrentEL: %x\r\n", get_currentEL()); + printf("DAIF: %x\r\n", get_DAIF()); + printf("SPSR_EL1: %p\r\n", (void*)get_SPSR_EL1()); + printf("SPSel: %p\r\n", (void*)get_SPSel()); + printf("SP_EL0: %p\r\n", (void*)get_SP_ELx(0)); + printf("ELR_EL1: %p\r\n", (void*)get_ELR_EL1()); + printf("ESR_EL1: %p\r\n", (void*)get_ESR_EL1()); + printf("SP : %p\r\n", (void*)get_SP()); + printf("\r\n"); + return x0; +} diff --git a/lab5/kernel/timer.c b/lab5/kernel/timer.c new file mode 100644 index 000000000..cd43b94f9 --- /dev/null +++ b/lab5/kernel/timer.c @@ -0,0 +1,100 @@ +#include "kernel/timer.h" + +static uint64_t jiffies = 0; +static struct list_head timer_list; + +/* + * We use core timer to update jiffies + */ +void enable_core_timer_irq(){ + IO_MMIO_write32(CORE0_TIMER_IRQ_CTRL, 2); +} +void disable_core_timer_irq(){ + IO_MMIO_write32(CORE0_TIMER_IRQ_CTRL, 0); +} + +void timer_softirq_callback(){ + struct list_head *head = &timer_list; + struct list_head *node; + timer_t* t; + + list_for_each(node, head){ + t = list_entry(node, timer_t, list); + t->ticks--; + if(t->ticks <= 0){ + list_del(node); + t->callback(t->data); + } + } +} + +void init_timer_list(void){ + INIT_LIST_HEAD(&timer_list); +} + +/** + * Timer with 10 microsecond resolution + * + * @param duration in microsecond + */ +void add_timer(timer_callback callback, uint8_t* data, uint64_t duration){ + if(duration == 0){ + callback(data); + return; + } + + timer_t* t = (timer_t*)simple_malloc(sizeof(timer_t)); + + t->ticks = duration / (1000 / HZ); + t->callback = callback; + t->data = data; + + disable_core_timer_irq(); + //critical section + list_add(&t->list, &timer_list); + enable_core_timer_irq(); +} + +void init_core_timer(){ + uint64_t freq; + + init_timer_list(); + set_CNTP_CTL_EL0(1); + freq = get_CNTFRQ_EL0(); + set_CNTP_TVAL_EL0(freq / HZ); + + + // lab5, user space want to access cpu timer register + uint64_t tmp; + asm volatile("mrs %0, cntkctl_el1" : "=r"(tmp)); + tmp |= 1; + asm volatile("msr cntkctl_el1, %0" : : "r"(tmp)); + + enable_core_timer_irq(); +} +void core_timer_irq_handler(){ + uint64_t freq; + struct task_struct* current = get_current(); + + freq = get_CNTFRQ_EL0(); + set_CNTP_TVAL_EL0(freq / HZ); + + jiffies += 1; + + // update task schedule info + if(current){ + current->sched_info.rticks++; + current->sched_info.counter--; + if(current->sched_info.counter <= 0){ + need_sched = 1; + } + } +} + +uint64_t inline get_jiffies(){ + return jiffies; +} + + + + diff --git a/lab5/lib/Makefile b/lab5/lib/Makefile new file mode 100644 index 000000000..328a22f1a --- /dev/null +++ b/lab5/lib/Makefile @@ -0,0 +1,36 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + print.o \ + string.o \ + list.o \ + cpio.o \ + simple_malloc.o \ + fdt_parse.o \ + asm.o \ + ring_buffer.o \ + bitops.o + + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab5/lib/asm.c b/lab5/lib/asm.c new file mode 100644 index 000000000..3eb7a887a --- /dev/null +++ b/lab5/lib/asm.c @@ -0,0 +1,161 @@ +#include "types.h" +void local_irq_enable(){ + asm volatile("msr DAIFClr, 0xf"); +} + +void local_irq_disable(){ + asm volatile("msr DAIFSet, 0xf"); +} + +uint64_t local_irq_disable_save() { + volatile uint64_t daif; + asm volatile( + "mrs %0, DAIF\t\n" + "msr DAIFSet, 0xf" + :"=&r"(daif) + : + ); + + return daif; +} + +void local_irq_restore(uint64_t daif) { + asm volatile( + "msr DAIF, %0" + ::"r"(daif) + ); +} + +uint32_t get_currentEL(){ + uint64_t curEL = 0; + asm volatile("mrs %0, CurrentEL" + : "=&r" (curEL) + : + ); + return curEL >> 2; +} +uint64_t get_SP_ELx(uint32_t x){ + uint64_t sp = 0; + + switch(x){ + case 0: + asm volatile("mrs %0, SP_EL0" + : "=&r" (sp) + : + ); + break; + case 1: + asm volatile("mrs %0, SP_EL1" + : "=&r" (sp) + : + ); + break; + case 2: + asm volatile("mrs %0, SP_EL2" + : "=&r" (sp) + : + ); + break; + default: + break; + } + + + return sp; +} +uint64_t get_DAIF(){ + uint64_t daif; + asm volatile("mrs %0, DAIF" + : "=&r" (daif) + : + ); + return daif; +} +void set_DAIF(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr daif, x0" + : + :[n] "r" (n) + ); +} + +uint64_t get_SPSel(){ + uint64_t spsel = 0; + asm volatile("mrs %0, spsel" + : "=&r" (spsel) + : + ); + return spsel; +} +uint64_t get_ESR_EL1(){ + uint64_t esr_el1 = 0; + asm volatile("mrs %0, esr_el1" + : "=&r" (esr_el1) + : + ); + return esr_el1; +} +uint64_t get_SPSR_EL1(){ + uint64_t spsr_el1 = 0; + asm volatile("mrs %0, spsr_el1" + : "=&r" (spsr_el1) + : + ); + return spsr_el1; +} +uint64_t get_ELR_EL1(){ + uint64_t elr_el1 = 0; + asm volatile("mrs %0, elr_el1" + : "=&r" (elr_el1) + : + ); + return elr_el1; +} +uint64_t get_SP(){ + uint64_t sp = 0; + asm volatile("mov %0, sp" + : "=&r" (sp) + : + ); + return sp; +} +uint64_t get_CNTP_CTL_EL0(){ + uint64_t cntp_ctl_el0 = 0; + asm volatile("mrs %0, cntp_ctl_el0" + : "=&r" (cntp_ctl_el0) + : + ); + return cntp_ctl_el0; +} +void set_CNTP_CTL_EL0(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr cntp_ctl_el0, x0" + : + :[n] "r" (n) + ); +} +uint64_t get_CNTFRQ_EL0(){ + uint64_t cntfrq_el0 = 0; + asm volatile("mrs %0, cntfrq_el0" + : "=&r" (cntfrq_el0) + : + ); + return cntfrq_el0; +} + +void set_CNTP_TVAL_EL0(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr cntp_tval_el0, x0" + : + :[n] "r" (n) + ); +} +uint64_t get_CNTPCT_EL0(){ + uint64_t cntpct_el0 = 0; + asm volatile("mrs %0, cntpct_el0" + : "=&r" (cntpct_el0) + : + ); + return cntpct_el0; +} + diff --git a/lab5/lib/bitops.c b/lab5/lib/bitops.c new file mode 100644 index 000000000..ad1080455 --- /dev/null +++ b/lab5/lib/bitops.c @@ -0,0 +1,55 @@ +#include "lib/bitops.h" + +uint16_t ffs16(uint16_t val){ +// val should not be zero! +// The behavior is undefined when val is zer! + uint16_t num = 0; + if((val & 0xff) == 0){ + num += 8; + val >>= 8; + } + if((val & 0xf) == 0){ + num += 4; + val >>= 4; + } + if((val & 0x3) == 0){ + num += 2; + val >>= 2; + } + if((val & 0x1) == 0) + num += 1; + + return num; +} + +uint64_t ffs64(uint64_t val){ +// val should not be zero! +// The behavior is undefined when val is zer! + uint64_t num = 0; + if((val & 0xffffffff) == 0){ + num += 32; + val >>= 32; + } + if((val & 0xffff) == 0){ + num += 16; + val >>= 16; + } + if((val & 0xff) == 0){ + num += 8; + val >>= 8; + } + if((val & 0xf) == 0){ + num += 4; + val >>= 4; + } + + if((val & 0x3) == 0){ + num += 2; + val >>= 2; + } + + if((val & 0x1) == 0) + num += 1; + + return num; +} diff --git a/lab5/lib/cpio.c b/lab5/lib/cpio.c new file mode 100644 index 000000000..4474ac83b --- /dev/null +++ b/lab5/lib/cpio.c @@ -0,0 +1,61 @@ +#include "lib/cpio.h" + +uint32_t cpio_hex2dec(const char *s){ + uint32_t ret = 0; + for(uint32_t i = 0 ; i < 8 ; i++){ + ret = ret << 4; + ret = ret + hex2dec(s[i]); + } + return ret; +} + +void cpio_iter_parse(struct cpio_iter* iter, struct fentry* f){ + LOG("Enter cpio_iter_parse"); + size_t count = 0; + struct cpio_newc_header* header = (struct cpio_newc_header* )iter->cur; + + if(!memcpy(header->c_magic, "070701", 6)){ + LOG("CPIO PARSE ERROR!!!!"); + return; + } + + f->ino = cpio_hex2dec(header->c_ino); + f->mode = cpio_hex2dec(header->c_mode); + f->uid = cpio_hex2dec(header->c_uid); + LOG("f->uid: %u", f->uid); + f->gid = cpio_hex2dec(header->c_gid); + f->nlink = cpio_hex2dec(header->c_nlink); + f->mtime = cpio_hex2dec(header->c_mtime); + f->filesize = cpio_hex2dec(header->c_filesize); + LOG("f->filesize: %u", f->filesize); + f->devmajor = cpio_hex2dec(header->c_devmajor); + f->devminor = cpio_hex2dec(header->c_devminor); + f->rdevmajor = cpio_hex2dec(header->c_rdevmajor); + f->rdevminor = cpio_hex2dec(header->c_rdevminor); + f->namesize = cpio_hex2dec(header->c_namesize); + LOG("f->namesize: %u", f->namesize); + f->check = cpio_hex2dec(header->c_check); + count = count + sizeof(struct cpio_newc_header); + + f->filename = (char*)simple_malloc(f->namesize); + memcpy(f->filename, (uint8_t* )header + count, f->namesize); + LOG("get f->filename"); + count = ALIGN_UP(count + f->namesize, 4); + if(f->filesize > 0){ + f->data = (uint8_t*)simple_malloc(f->filesize); + memcpy(f->data, (uint8_t* )header + count, f->filesize); + } + LOG("get f->data"); + count = ALIGN_UP(count + f->filesize, 4); + iter->cur = iter->cur + count; + LOG("count: %u, iter->cur: %p", count, iter->cur); + LOG("Leave cpio_iter_parse"); +} + +void cpio_iter_init(struct cpio_iter* iter, void* addr){ + iter->cur = addr; +} +int cpio_is_tailer(struct fentry* f){ + return (strcmp(f->filename, "TRAILER!!!") == 0); +} + diff --git a/lab5/lib/fdt_parse.c b/lab5/lib/fdt_parse.c new file mode 100644 index 000000000..762563031 --- /dev/null +++ b/lab5/lib/fdt_parse.c @@ -0,0 +1,127 @@ +#include "lib/fdt_parse.h" + +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +static fdt_header header; +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = &header; + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) >> 2; + len += 2; +// printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + printf("Parsing error!!\n"); + while(1); + } + } +} +void fdt_parse_rsvmap(uint8_t* fdt, fdt_rsvmap_callback callback){ + uint64_t *mem_rsvmap; + uint64_t start, end; + uint64_t count = 0; + fdt_header * pheader = &header; + fdt_parse_header(fdt, pheader); + + mem_rsvmap = (uint64_t*)(fdt + pheader->off_mem_rsvmap); + do{ + start = bswap64(mem_rsvmap[count * 2]); + end = start + bswap64(mem_rsvmap[count * 2 + 1]); + if(end) + callback(start, end); + else + break; + count++; + }while(1); +} +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab5/lib/list.c b/lab5/lib/list.c new file mode 100644 index 000000000..6539320c1 --- /dev/null +++ b/lab5/lib/list.c @@ -0,0 +1,75 @@ +#include "lib/list.h" + +void INIT_LIST_HEAD(struct list_head* head){ + head->next = head; + head->prev = head; +} + +void list_add(struct list_head* node, struct list_head* head){ + struct list_head *next = head->next; + + next->prev = node; + head->next = node; + + node->next = next; + node->prev = head; +} + +void list_add_tail(struct list_head* node, struct list_head* head){ + struct list_head* tail = head->prev; + + tail->next = node; + head->prev = node; + + node->next = head; + node->prev = tail; +} + +void list_del(struct list_head* node){ + struct list_head* next = node->next; + struct list_head* prev = node->prev; + + next->prev = prev; + prev->next = next; +} +int list_empty(struct list_head* head){ + return (head->next == head); +} + +int list_is_last(struct list_head* node, struct list_head* head){ + return head->prev == node; +} + +int list_is_head(struct list_head* node, struct list_head* head){ + return head == node; +} + +void list_splice(struct list_head *list, struct list_head *head){ + struct list_head *head_first = head->next; + struct list_head *list_first = list->next; + struct list_head *list_last = list->prev; + + if (list_empty(list)) + return; + + head->next = list_first; + list_first->prev = head; + + list_last->next = head_first; + head_first->prev = list_last; +} + +void list_splice_tail(struct list_head *list, struct list_head *head){ + struct list_head *head_last = head->prev; + struct list_head *list_first = list->next; + struct list_head *list_last = list->prev; + + if (list_empty(list)) + return; + + head->prev = list_last; + list_last->next = head; + + list_first->prev = head_last; + head_last->next = list_first; +} diff --git a/lab5/lib/print.c b/lab5/lib/print.c new file mode 100644 index 000000000..7ce4c6c82 --- /dev/null +++ b/lab5/lib/print.c @@ -0,0 +1,111 @@ +#include "lib/print.h" + +int32_t aio_print(char* fmt, ...){ + +} +int32_t printf(char *fmt, ...){ + uint32_t uval; + int32_t val; + int64_t lval; + char str[64], ch; + char* p, *s; + void* addr; + volatile int32_t count = 0; + va_list ap; + + va_start(ap, fmt); + + while(*fmt){ + char c = *fmt++; + if(c == '%'){ + c = *fmt++; + switch(c){ + case 'u': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'd': + val = va_arg(ap, int); + itoa(val, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'l': + lval = va_arg(ap, int64_t); + ltoa(lval, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'c': + ch = va_arg(ap, int); + mini_uart_write(ch); + count++; + break; + case 'p': + addr = va_arg(ap, void*); + utoa((uint64_t)addr, str, 16); + + mini_uart_write('0'); + mini_uart_write('x'); + count += 2; + + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + + break; + case 'x': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 16); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + + break; + case 's': + s = va_arg(ap, char*); + p = s; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case '%': + mini_uart_write('%'); + count++; + default: + mini_uart_write('%'); + mini_uart_write(c); + count += 2; + } + }else{ + mini_uart_write(c); + count++; + } + } + va_end(ap); + return count; +} +int32_t putchar(uint8_t ch){ + mini_uart_write(ch); + return ch; +} +int32_t getchar(){ + return mini_uart_aio_read(); +} diff --git a/lab5/lib/ring_buffer.c b/lab5/lib/ring_buffer.c new file mode 100644 index 000000000..1f7e750b1 --- /dev/null +++ b/lab5/lib/ring_buffer.c @@ -0,0 +1,117 @@ +#include "lib/ring_buffer.h" + +ring_buffer* create_simple_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)simple_malloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)simple_malloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + tmp->count = 0; + return tmp; +} + +// This function can only be used after initializing mm +ring_buffer* create_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)kmalloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)kmalloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + tmp->count = 0; + return tmp; +} + +void free_ring_buf(ring_buffer* rbuf){ + kfree(rbuf->buf); + kfree(rbuf); +} + +uint8_t ring_buf_is_empty(ring_buffer* rbuf){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + if(rbuf->head == rbuf->tail){ + local_irq_restore(daif); + return 1; + } + local_irq_restore(daif); + return 0; +} + +uint8_t ring_buf_is_full(ring_buffer* rbuf){ + volatile uint64_t daif; + if((rbuf->tail + 1) % (rbuf->size + 1) == rbuf->head){ + local_irq_disable_save(daif); + return 1; + } + local_irq_restore(daif); + return 0; +} + +size_t ring_buf_write(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count += count; + local_irq_restore(daif); + return count; +} + +size_t ring_buf_write_unsafe(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count += count; + return count; +} + +size_t ring_buf_read(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count -= count; + local_irq_restore(daif); + return count; +} + +size_t ring_buf_read_unsafe(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count -= count; + return count; +} + +size_t ring_buf_get_len(ring_buffer* rbuf){ + volatile uint64_t daif; + size_t ret; + + daif = local_irq_disable_save(); + ret = rbuf->count; + local_irq_restore(daif); + + return ret; +} diff --git a/lab5/lib/simple_malloc.c b/lab5/lib/simple_malloc.c new file mode 100644 index 000000000..f7d7188fa --- /dev/null +++ b/lab5/lib/simple_malloc.c @@ -0,0 +1,17 @@ +#include "lib/simple_malloc.h" + +extern int __heap_start; +static struct malloc_state mstate = { + .last_remainder = (uint8_t*)&__heap_start +}; + + +void* simple_malloc(size_t size){ + void* chunk = mstate.last_remainder; + size_t nb = req2size(size); + mstate.last_remainder = mstate.last_remainder + nb; + return chunk; +} +void* simple_malloc_get_remainder(){ + return mstate.last_remainder; +} diff --git a/lab5/lib/string.c b/lab5/lib/string.c new file mode 100644 index 000000000..3ab9d9ce6 --- /dev/null +++ b/lab5/lib/string.c @@ -0,0 +1,260 @@ +#include "lib/string.h" +#include "types.h" +char *int_table = "0123456789"; +char *hex_table = "0123456789abcdef"; +char * itoa(int32_t value, char* str, uint32_t base){ + char buf[32]; + uint32_t val; + volatile int i = 0, j = 0; + + switch(base){ + case 16: + val = (uint32_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} + +char * utoa(uint32_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint32_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} +char * ltoa(int64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val; + + switch(base){ + case 16: + val = (uint64_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +char * ultoa(uint64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +uint64_t atoul(const char* str){ + uint64_t val = 0; + const char* ps = str; + while(*ps){ + val *= 10; + val += (*ps - '0'); + ps++; + } + return val; +} +int32_t strcmp(char* str1, char* str2){ + do{ + if(*str1 > *str2) return 1; + else if(*str1 < *str2) return -1; + str1++;str2++; + }while(*str1 != '\0' || *str2 != '\0'); + return 0; +} +size_t strlen(const char* s){ + size_t i = 0; + while(s[i++]); + i--; + return i; +} +// Do not maninpulate data by using (uint64*) or it may sometimes trigger alignment issue +// Manipulating data by using (uint8*) is best choice in this homework +void* memcpy(void* dst, const void* src, size_t n){ + const uint8_t* ps = src; + uint8_t *pd = dst; + size_t i; + for(i = 0 ; i < n ; i++) pd[i] = ps[i]; + return dst; +} +char *strcpy(char *dest, const char *src){ + memcpy(dest, src, strlen(src) + 1); +} +void* memset(void* s, int c, size_t n){ + uint8_t* ps = s; + for(size_t i = 0 ; i < n ; i++) ps[i] = c; + return s; +} + +int32_t memcmp(void* m1, const void* m2, size_t n){ + size_t i = 0; + char *s1 = m1; + const char* s2 = m2; + while(i < n){ + if(s1[i] > s2[i]) return 1; + else if(s1[i] < s2[i]) return -1; + i++; + } + return 0; +} + +uint8_t hex2dec(char hex){ + if('0' <= hex && hex <= '9'){ + return (uint8_t)hex - (uint8_t)'0'; + }else if('a' <= hex && hex <= 'f'){ + return (uint8_t)hex - (uint8_t)'a' + 10; + }else{ + return (uint8_t)hex - (uint8_t)'A' + 10; + } +} +uint8_t _is_delim(char c,const char* delim){ + uint32_t i = 0; + while(delim[i]){ + if(c == delim[i++]) return 1; + } + return 0; +} +char* _next_token(char* s,const char* delim){ + char* pos = s; + + do{ + if(*pos == '\0'){ + return NULL; + }else if(_is_delim(*pos, delim)){ + *pos = '\0'; + return pos + 1; + } + pos++; + }while(1); +} +char* _skip_delim(char* s,const char* delim){ + char* pos = s; + while(*pos != '\0' && _is_delim(*pos, delim)) pos++; + return pos; +} +char* strtok(char* s,const char* delim){ + static char *pos = NULL; + char *tmp_pos = NULL; + if(s == NULL){ + if(pos == NULL || *pos =='\0') return NULL; + + tmp_pos = pos = _skip_delim(pos, delim); + if(*pos != '\0'){ + pos = _next_token(pos, delim); + }else{ + pos = tmp_pos = NULL; + } + }else{ + if(*s == '\0') return NULL; + + pos = s; + tmp_pos = pos = _skip_delim(pos, delim); + if(*pos != '\0'){ + pos = _next_token(pos, delim); + }else{ + pos = tmp_pos = NULL; + } + } + return tmp_pos; +} diff --git a/lab5/mm/Makefile b/lab5/mm/Makefile new file mode 100644 index 000000000..c115b35a7 --- /dev/null +++ b/lab5/mm/Makefile @@ -0,0 +1,27 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + page_alloc.o \ + slab.o \ + mm.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab5/mm/mm.c b/lab5/mm/mm.c new file mode 100644 index 000000000..01775feae --- /dev/null +++ b/lab5/mm/mm.c @@ -0,0 +1,203 @@ +#include "mm/mm.h" + +extern int __heap_start; +extern int __kernel_image_start; +extern int __kernel_image_end; +extern int __kernel_image_end; +extern int __EL1_stack_size; +extern int __EL1_stack; + +struct list_head mem_rsvmap; +struct list_head mem_unusedmap; +struct mem_node memory_node; +struct page *mem_map; + +void reserve_memory(uint64_t start, uint64_t end){ + struct list_head *node; + struct list_head *head; + struct mem_block *mb = simple_malloc(sizeof(struct mem_block)); + struct mem_block *tmp_mb; + + start = ALIGN_DOWN(start, PAGE_SIZE); + end = ALIGN_UP(end, PAGE_SIZE); + mb->start = start; + mb->end = end; + list_for_each(node, &mem_rsvmap){ + tmp_mb = list_entry(node, struct mem_block, list); + if(tmp_mb->start > start){ + head = node->prev; + list_add(&mb->list, head); + break; + } + } + + if(list_is_head(node, &mem_rsvmap)){ + list_add(&mb->list, node->prev); + } +} + +size_t get_reserved_size(){ + uint64_t start, end; + struct list_head* node; + struct mem_block* mb; + size_t size = 0; + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + start = mb->start; + end = mb->end; + size += (end - start); + } + return size; +} + +size_t get_unused_size(){ + uint64_t start, end; + struct list_head* node; + struct mem_block* mb; + size_t size = 0; + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + start = mb->start; + end = mb->end; + size += (end - start); + LOG("unused map: start: %p, end: %p", start, end); + } + return size; +} + +uint64_t _reserve_dtb(void *dtb){ + fdt_header header; + fdt_header *pheader = &header; + uint64_t start, end; + size_t size = 0; + + fdt_parse_header((uint8_t*)dtb, pheader); + size = ALIGN_UP(pheader->totalsize, PAGE_SIZE); + + start = (uint64_t)dtb; + end = start + size; + reserve_memory(start, end); +} + +void* _reserve_cpio(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + static uint64_t start, end; + static uint8_t found_start = 0, found_end = 0; + if(prop != NULL){ + if(strcmp(prop->name, "linux,initrd-start") == 0){ + start = bswap32(*(uint32_t*)prop->value); + found_start = 1; + } + if(strcmp(prop->name, "linux,initrd-end") == 0){ + end = bswap32(*(uint32_t*)prop->value); + found_end = 1; + } + if(found_start && found_end){ + found_start = found_end = 0; + reserve_memory(start, end); + } + } +} + +void _create_memory_rsvmap(void *dtb){ + uint64_t start, end; + // reseved memory in dtb + fdt_parse_rsvmap((uint8_t*)dtb, reserve_memory); + + // reverse memory for kernel image + reserve_memory((uint64_t)&__kernel_image_start, (uint64_t)&__kernel_image_end); + + // reserve memory for stack + reserve_memory((uint64_t)&__EL1_stack - (uint64_t)&__EL1_stack_size, (uint64_t)&__EL1_stack); + + // reserve memory for device tree + _reserve_dtb(dtb); + + // reserve memory for cpio + fdt_parser(dtb, _reserve_cpio); + + // Create struct page table for mapping every physical frame to it + mem_map = simple_malloc(sizeof(struct page) * (memory_node.end >> PAGE_SHIFT)); + + // reserve memory for simple memory allocator + start = (uint64_t)&__heap_start; + end = ALIGN_UP((uint64_t)simple_malloc_get_remainder(), PAGE_SIZE) + 8 * PAGE_SIZE; + reserve_memory(start, end); + +} + +void _create_memory_unusedmap(){ + uint64_t unused_start = 0; + struct list_head *node; + struct mem_block *mb; + struct mem_block *tmp_mb; + + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + INFO("rsv map: start = %p, end = %p", mb->start, mb->end); + if(unused_start < mb->start){ + tmp_mb = (struct mem_block*)simple_malloc(sizeof(struct mem_block)); + + tmp_mb->start = unused_start; + tmp_mb->end = mb->start; + list_add_tail(&tmp_mb->list, &mem_unusedmap); + INFO("unused map: start = %p, end = %p", tmp_mb->start, tmp_mb->end); + + } + unused_start = mb->end; + } + + if(unused_start < memory_node.end){ + tmp_mb = (struct mem_block*)simple_malloc(sizeof(struct mem_block)); + tmp_mb->start = unused_start; + tmp_mb->end = memory_node.end; + list_add_tail(&tmp_mb->list, &mem_unusedmap); + } +} + +void* _get_memory_node(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + static int found_memory_node = 0; + uint32_t* pw; + if(node != NULL && strcmp(node->name, "memory@0") == 0){ + memory_node.name = "memory@0"; + found_memory_node = 1; + } + if(found_memory_node && prop != NULL && strcmp(prop->name, "reg") == 0){ + pw = (uint32_t*)prop->value; + memory_node.start = bswap32(pw[0]); + memory_node.end = memory_node.start + bswap32(pw[1]); + found_memory_node = 0; + } +} + + +void mm_init(void *dtb){ + INFO("Init mm subsystem.."); + // initialize mm's global variable + INIT_LIST_HEAD(&mem_rsvmap); + INIT_LIST_HEAD(&mem_unusedmap); + fdt_parser((uint8_t*)dtb, _get_memory_node); + + _create_memory_rsvmap(dtb); + _create_memory_unusedmap(); + + INFO("Memory node: %s, size: %p", memory_node.name, memory_node.end - memory_node.start); + INFO("Memory reserved size: %p", get_reserved_size()); + INFO("Memory unused size : %p", get_unused_size()); + + // initialize buddy system + buddy_init(); + + print_buddy_statistics(); + + /* if(debug) + debug_slab();*/ + + kmalloc_init(); + +/* if(debug){ + debug_kmalloc(); + //debug_buddy(); + print_buddy_statistics(); + }*/ + +} diff --git a/lab5/mm/page_alloc.c b/lab5/mm/page_alloc.c new file mode 100644 index 000000000..1f45e734f --- /dev/null +++ b/lab5/mm/page_alloc.c @@ -0,0 +1,377 @@ +#include "mm/page_alloc.h" +static struct buddy_system buddy; + +void _init_mem_map(){ + struct list_head *node; + struct mem_block *mb; + uint64_t start_pfn, end_pfn, size; + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + + start_pfn = addr_to_pfn(mb->start); + end_pfn = addr_to_pfn(mb->end); + size = (end_pfn - start_pfn) * sizeof(struct page); + + memset(&mem_map[start_pfn], '\0', size); + } + + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + + start_pfn = addr_to_pfn(mb->start); + end_pfn = addr_to_pfn(mb->end); + for(uint64_t i = start_pfn ; i < end_pfn ; i++){ + memset(&mem_map[i], '\0', sizeof(struct page)); + mem_map[i].type |= PAGE_TYPE_RESERVED; + } + } +} + +void __free_pages(struct page* page, uint32_t order){ + volatile uint64_t daif; + struct page* end_page = page + (1 << order); + + // initialize buddy group leader and add it to free list + page->order = order; + list_add(&page->list, &buddy.free_lists[order].list); + buddy.free_lists[order].count++; + + // initialize buddy group members + + for(struct page* p = page + 1 ; p < end_page ; p++){ + p->order = BUDDY_GROUP_MEMBER; + } +} + +void _free_pages_memory(uint64_t start, uint64_t end){ + // start and end is page frame number ( pfn ) + uint64_t order; + while(start < end){ + order = min(BUDDY_MAX_ORDER - 1, _buddy_ffs(start)); + + // decrease the order if last page's pfn in buddy is larger than end + while(start + (1 << order) > end) order--; + + __free_pages(&mem_map[start], order); + start += (1 << order); + } +} + +void _free_pages(struct page* page, uint32_t order){ + struct page* buddy_page; + uint64_t pfn = page_to_pfn(page); + uint64_t buddy_pfn; + + // check the order of page + if(BUDDY_IS_FREED(page)){ + INFO("Error: _free_pages(%u) try to free freed pfn %p", order, pfn); + return; + } + if(order > _buddy_ffs(pfn)){ + INFO("Error: _free_pages(%u) try to free pfn %p", order, pfn); + return; + } + + while(order < BUDDY_MAX_ORDER - 1){ + buddy_pfn = find_buddy_pfn(pfn, order); + buddy_page = pfn_to_page(buddy_pfn); + + if(!PAGE_IS_RESERVED(buddy_page) && BUDDY_IS_FREED(buddy_page) && buddy_page->order == order){ + // Check if buddy is not reserved and freed + LOG("%p is buddy of %p in order %u free list and it can be merged", pfn_to_addr(buddy_pfn), pfn_to_addr(pfn), order); + list_del(&buddy_page->list); + buddy.free_lists[order].count--; + }else{ + break; + } + + pfn = pfn & ~(1 << order); + page = pfn_to_page(pfn); + order++; + } + + LOG("Merge %p into order %u free list ", pfn_to_addr(pfn), order); + __free_pages(page, order); + LOG("end merge pages"); +} + +// free 2^order pages +void free_pages(void* addr, uint32_t order){ + LOG("_free_pages(%p, %u)",addr, order); + volatile uint64_t daif; + uint64_t pfn = addr_to_pfn(addr); + struct page *page = pfn_to_page(pfn); + + daif = local_irq_disable_save(); + _free_pages(page, order); + local_irq_restore(daif); +} + +// free one page +void free_page(void* addr){ + volatile uint64_t daif; + uint64_t pfn = addr_to_pfn(addr); + struct page *page = pfn_to_page(pfn); + + daif = local_irq_disable_save(); + _free_pages(page, 0); + local_irq_restore(daif); +} + +// split large buddy group to two small buddy groups +void expand(struct page *page, uint32_t high, uint32_t low){ + struct page* tmp_page; + volatile uint64_t daif; + while(high > low){ + high--; + tmp_page = page + (1 << high); + + LOG("add page %p to order %u free list",pfn_to_addr(page_to_pfn(tmp_page)) , high); + __free_pages(tmp_page, high); + } +} + +struct page* _alloc_pages(uint32_t order){ + LOG("_alloc_pages(%u)", order); + struct list_head *node; + struct free_list* free_list; + struct page* page, *tmp_page; + + // find appropriate buddy group for user + for(uint32_t i = order ; i < BUDDY_MAX_ORDER ; i++){ + free_list = &buddy.free_lists[i]; + + if(list_empty(&free_list->list)){ + LOG("free list of order %u is empty", i); + continue; + } + + page = list_first_entry(&free_list->list, struct page, list); + list_del(&page->list); + free_list->count--; + LOG("get free page %p from order %u", pfn_to_addr(page_to_pfn(page)), i); + + + for(uint32_t j = 0 ; j < (1 << order) ; j++){ + page[j].order = BUDDY_ALLOCATED|order; + page[j].buddy_leader = page; + } + + if(i > order){ + LOG("start expand pages of order %u to order %u", i, order); + expand(page, i, order); + LOG("end expand pages from order %u to order %u", i, order); + } + return page; + } + return NULL; +} + +// return 2^order pages +void* alloc_pages(uint32_t order){ + if(order > BUDDY_MAX_ORDER - 1) return NULL; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + struct page* page = _alloc_pages(order); + local_irq_restore(daif); + uint64_t pfn = page_to_pfn(page); + + return pfn_to_addr(pfn); +} + +// return one page +void* alloc_page(){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + struct page* page = _alloc_pages(0); + local_irq_restore(daif); + + uint64_t pfn = page_to_pfn(page); + return pfn_to_addr(pfn); +} + +void print_buddy_statistics(){ + uint64_t free_page_count = 0; + uint64_t tmp; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + INFO("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + INFO("Total free page #: %l", free_page_count); +} + +uint8_t* _debug_alloc_page(uint32_t order){ + LOG("###########################################"); + uint64_t free_page_count = 0; + uint64_t tmp; + uint8_t * ret; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + LOG("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + ret = alloc_pages(order); + LOG("Total free page #: %l", free_page_count); + LOG("allocate page: %p", ret); + return ret; +} + +uint8_t* _debug_free_page(void *addr, uint32_t order){ + LOG("###########################################"); + uint64_t free_page_count = 0; + uint64_t tmp; + uint8_t * ret; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + LOG("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + free_pages(addr, order); + LOG("Total free page #: %l", free_page_count); + LOG("freed page: %p", addr); + return ret; +} + +void debug_buddy(){ + uint8_t *arr[1500]; + int32_t i = 0, count = 0; + struct list_head* node; + struct page* page, *target_page; + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(1); + count++; + } + for(i = 0 ; i < 4; i++){ + arr[count] = _debug_alloc_page(2); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(3); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(1); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(2); + count++; + } + for(i = 0 ; i < 1400; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + LOG("###########################################"); + for(i = 0 ; i < count ; i++){ + target_page = pfn_to_page(addr_to_pfn(arr[i])); + if(!BUDDY_IS_ALLOCATED(target_page)){ + LOG("******* page %p didn't set to allocated *******", pfn_to_addr(page_to_pfn(page))); + goto error; + } + for(uint32_t j = 0 ; j < BUDDY_MAX_ORDER ; j++){ + list_for_each(node, &buddy.free_lists[j].list){ + page = list_entry(node, struct page, list); + if(target_page == page){ + LOG("******* allocated page didn't remove from free list *******", pfn_to_addr(page_to_pfn(page))); + goto error; + } + } + } + } + count = 0; + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 1); + count++; + } + for(i = 0 ; i < 4; i++){ + _debug_free_page(arr[count], 2); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 3); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 1); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 2); + count++; + } + for(i = 0 ; i < 1400; i++){ + _debug_free_page(arr[count], 0); + count++; + } + // check the integrity of linked list by using grep to check how many unique lines + // + // ./debug.sh > t + // grep "\[test\]" t|sort|uniq|wc -l + // + struct list_head* tmp_node; + struct page* tmp_page; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + list_for_each(tmp_node, &buddy.free_lists[i].list){ + tmp_page = list_entry(tmp_node, struct page, list); + for(uint32_t j = 0; j < (1 << i) ; j++){ + printf("[test] : %p\n", pfn_to_addr(page_to_pfn(tmp_page) + j)); + } + } + } + LOG("******* Pass the testcases *******"); + return; +error: + LOG("******* Something is wrong in buddy system alloc_pages *******"); + return; +} +void buddy_init(){ + struct list_head * node; + struct mem_block* mb; + uint64_t start_pfn, end_pfn; + + INFO("Initialize buddy system..."); + // Initialize global variable + memset(&buddy, '\0', sizeof(struct buddy_system)); + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER; i++){ + INIT_LIST_HEAD(&buddy.free_lists[i].list); + } + + // Initialize mem map + _init_mem_map(); + + // Add free page frame to buddy system + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + start_pfn = addr_to_pfn(mb->start); + end_pfn = addr_to_pfn(mb->end); + + _free_pages_memory(start_pfn, end_pfn); + } + +} diff --git a/lab5/mm/slab.c b/lab5/mm/slab.c new file mode 100644 index 000000000..542320d26 --- /dev/null +++ b/lab5/mm/slab.c @@ -0,0 +1,251 @@ +#include "mm/slab.h" + +struct list_head kmem_cache[KMEM_CACHE_NUM] = {0}; + +struct slab* slab_create(size_t obj_size){ + size_t allocated_size; + uint32_t order = 0; + size_t page_num; + void* pages; + struct slab * pslab; + + // object size align to slab_alignment + obj_size = ALIGN_UP(obj_size, SLAB_ALIGNMENT); + + // check if obj_size exceed slab's limit + if(obj_size > SLAB_MAX_OBJECT_SIZE){ + LOG("invalid obj_size: %l, slab_max_object_size is %l", obj_size, SLAB_MAX_OBJECT_SIZE); + return NULL; + } + + // get sufficient order + //page_num = ALIGN_UP(obj_size + SLAB_SIZE, 4096) >> PAGE_SHIFT; + order = BUDDY_MAX_ORDER - 1; + pages = alloc_pages(order); + if(pages == NULL){ + LOG("Not enough page for slab"); + return NULL; + } + + // initialize struct slab + pslab = pages; + pslab->size = obj_size; + pslab->s_mem = pages + SLAB_SIZE; + pslab->inuse = 0; + INIT_LIST_HEAD(&pslab->free_list); + + return pslab; +} + +void slab_destroy(struct slab* slab){ + size_t page_num; + struct page* page = pfn_to_page(addr_to_pfn(slab)); + volatile uint64_t daif; + LOG("slab_destroy recycle order %u buddy %p", (void*)slab, get_page_order(page)); + // free pages + free_pages((void*)slab, get_page_order(page)); +} + +void *slab_alloc(struct slab* slab){ + void *ret = NULL; + struct page* page; + uint32_t order; + size_t max_size; + volatile uint64_t daif; + daif = local_irq_disable_save(); + if(!list_empty(&slab->free_list)){ + // check free list + ret = slab->free_list.next; + list_del(slab->free_list.next); + slab->inuse++; + }else{ + page = pfn_to_page(addr_to_pfn(slab)); + order = get_page_order(page); + max_size = (1 << order) * PAGE_SIZE; + if(SLAB_SIZE + (slab->inuse + 1) * slab->size > max_size){ + ret = NULL; + }else{ + ret = (uint8_t*)slab->s_mem + slab->inuse * slab->size; + slab->inuse++; + } + } + local_irq_restore(daif); + return ret; +} + +void slab_free(struct slab* slab, void* obj){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + list_add((struct list_head*)obj, &slab->free_list); + slab->inuse--; + local_irq_restore(daif); +} + +void kmalloc_init(){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + for(uint64_t i = 0 ; i < KMEM_CACHE_NUM ; i++){ + INIT_LIST_HEAD(&kmem_cache[i]); + } + local_irq_restore(daif); +} +void* kmalloc(size_t size){ + uint64_t cache_idx; + struct list_head* cache_list, *node; + struct slab *s; + void * ret = NULL; + volatile uint64_t daif; + + size = ALIGN_UP(size, SLAB_ALIGNMENT); + + LOG("kmalloc(%u) start", size); + if(size > SLAB_MAX_OBJECT_SIZE){ + LOG("kmalloc invalid size %l", size); + return NULL; + } + // allocate memory from corresponding cache bin + cache_idx = ALIGN_UP(size, SLAB_ALIGNMENT) / SLAB_ALIGNMENT; + + daif = local_irq_disable_save(); + cache_list = &kmem_cache[cache_idx]; + + list_for_each(node, cache_list){ + s = list_entry(node, struct slab, list); + ret = slab_alloc(s); + if(ret != NULL){ + LOG("kmalloc(%u) found a free object %p in kmem_cache[%u]", size, ret, cache_idx); + break; + } + } + + if(ret == NULL){ + s = slab_create(size); + list_add(&s->list, cache_list); + ret = slab_alloc(s); + if(ret != NULL){ + LOG("kmalloc(%u) found a free object %p in kmem_cache[%u]", size, ret, cache_idx); + } + } + local_irq_restore(daif); + + LOG("kmalloc s->inuse: %x", s->inuse); + LOG("kmalloc(%u) end, ret: %p", size, ret); + return ret; +} + +void kfree(void* obj){ + volatile uint64_t daif = local_irq_disable_save(); + uint64_t pfn = addr_to_pfn(ALIGN_DOWN(obj, PAGE_SIZE)); + struct page* page = pfn_to_page(pfn); + struct page* buddy_leader = get_buddy_leader(page); + struct slab* s = pfn_to_addr(page_to_pfn(buddy_leader)); + + slab_free(s, obj); + LOG("kfree(%p) free an object, s->inuse: %l", obj, s->inuse); + + if(s->inuse < 0){ + LOG("[Error]: s->inuse : %p", s->inuse); + } + if(s->inuse == 0){ + LOG("kfree(%p) triger recycle unused slab", obj); + + list_del(&s->list); + slab_destroy(s); + } + local_irq_restore(daif); +} + +#define TEST_SIZE 64 +#define TEST_INVALID_SIZE ((1 << (BUDDY_MAX_ORDER - 1)) * PAGE_SIZE - SLAB_SIZE + 1) +void debug_slab(){ + uint32_t i, max_i; + uint8_t *a[ (1 << BUDDY_MAX_ORDER - 1) * PAGE_SIZE / TEST_SIZE]; + + struct slab* s = slab_create(TEST_SIZE); + + for(i = 0 ; i < 30; i++){ + a[i] = slab_alloc(s); + LOG("%u: slab_alloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("slab is full"); + break; + } + } + max_i = i; + for(i = 0 ; i < max_i ; i++){ + slab_free(s, a[i]); + } + + for(i = 0 ; i < 30; i++){ + a[i] = slab_alloc(s); + LOG("%u: slab_alloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("slab is full"); + break; + } + } + + + + for(i = 0 ; i < max_i ; i++){ + slab_free(s, a[i]); + } + + slab_destroy(s); + uint64_t pfn = addr_to_pfn(s); + struct page* page = pfn_to_page(pfn); + + if(BUDDY_IS_FREED(page) && get_page_order(page) == BUDDY_MAX_ORDER - 1){ + LOG("slab_destroy success"); + }else{ + + LOG("slab_destroy failed"); + } + + s = slab_create(TEST_INVALID_SIZE); + + if(s == NULL){ + LOG("create super large slab %l failed", TEST_INVALID_SIZE); + }else{ + LOG("create super large slab %l success", TEST_INVALID_SIZE); + } +} + +void debug_kmalloc(){ + uint32_t i, max_i; + uint8_t *a[20]; + + + for(i = 0 ; i < 20; i++){ + a[i] = kmalloc(TEST_SIZE); + LOG("%l: kmalloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("kmalloc is failed"); + break; + } + } + + max_i = i; + for(i = 0 ; i < max_i ; i++){ + LOG("kfree(%p)", a[i]); + kfree(a[i]); + } +/* + for(i = 0 ; i < 200; i++){ + a[i] = kmalloc(TEST_SIZE); + LOG("%u: kmalloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("kmalloc is failed"); + break; + } + } + + for(i = 0 ; i < max_i ; i++){ + kfree(a[i]); + } +*/ +} diff --git a/lab5/peripherals/Makefile b/lab5/peripherals/Makefile new file mode 100644 index 000000000..50b5d0780 --- /dev/null +++ b/lab5/peripherals/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + mini_uart.o \ + mailbox.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab5/peripherals/mailbox.c b/lab5/peripherals/mailbox.c new file mode 100644 index 000000000..95a9a7142 --- /dev/null +++ b/lab5/peripherals/mailbox.c @@ -0,0 +1,130 @@ +#include "peripherals/mailbox.h" + +static uint32_t MBox_buf[4096] __attribute__((aligned(16))); + +static uint32_t MBox_read(int channel){ + int ch, data; + + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_EMPTY_MASK); + + data = mbox_reg->read; + ch = data & MBOX_WRITE_CHANNEL_MASK; + if(ch == channel){ + LOG("MBox read address: %p", data & MBOX_READ_ADDR_MASK); + return (data & MBOX_READ_ADDR_MASK); + } + LOG("Leave"); + return 0; +} + +static void MBox_write(uint32_t data, int channel){ + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_FULL_MASK); + + mbox_reg->write = data | channel; + LOG("Leave"); +} + +static uint32_t MBox_process(uint8_t* tags, size_t tags_size){ + LOG("Enter"); + MBox_buffer* mbuf = (MBox_buffer*)MBox_buf; + // set buffer header + mbuf->buf_size = tags_size + 12; + mbuf->code = MBOX_STATUS_REQUEST; + + // copy tags to buffer + memcpy(mbuf->buf, tags, tags_size); + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + LOG("mbuf->buf: %p", mbuf->buf); + LOG("mbuf->buf + tags_size: %p", mbuf->buf + tags_size); + // end of MBox_buf + memset(mbuf->buf + tags_size, 0, 4); + + pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + // write to mailbox + MBox_write((uint32_t)(uint64_t)MBox_buf, MBOX_CHANNEL_PROPERTY_TAGS); + + // read from mailbox + uint32_t result = MBox_read(MBOX_CHANNEL_PROPERTY_TAGS); + + + LOG("Leave"); + return result; +} +void MBox_get_board_revision(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 4]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_BOARD_REVISION; + tag->value_size = 4; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer *)(uint64_t)MBox_process(buf, sizeof(MBox_tag) + 4); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + *ret = ((uint32_t*)tag->values)[0]; + LOG("Leave"); +} +void MBox_get_arm_memory(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 8]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_ARM_MEMORY; + tag->value_size = 8; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + ((uint32_t*)tag->values)[1] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer *)(uint64_t)MBox_process(buf, sizeof(MBox_tag) + 8); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + ret[0] = ((uint32_t*)tag->values)[0]; + ret[1] = ((uint32_t*)tag->values)[1]; + LOG("Leave"); +} + +int Mbox_call(uint32_t* mbox, uint8_t ch) { + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_FULL_MASK){ + preempt_schedule(); + } + + mbox_reg->write = ((uint32_t)(uint64_t)mbox & ~0xF) | ch; + + while (mbox_reg->status & MBOX_STATUS_EMPTY_MASK){ + preempt_schedule(); + } + + return mbox_reg->read == (((uint32_t)(uint64_t)mbox & ~0xF) | ch); +} +int sys_mbox_call(uint8_t ch, uint32_t *mbox){ + return Mbox_call(mbox, ch); +} diff --git a/lab5/peripherals/mini_uart.c b/lab5/peripherals/mini_uart.c new file mode 100644 index 000000000..aed80ab2b --- /dev/null +++ b/lab5/peripherals/mini_uart.c @@ -0,0 +1,158 @@ +#include "peripherals/mini_uart.h" + +static ring_buffer* rx_rbuf = NULL; + +inline void delay_cycles(uint64_t n){ + for(register uint64_t i = 0 ; i < n ; i++) asm volatile("nop"); +} + +inline void enable_mini_uart_rx_irq(){ +} + +inline void disable_mini_uart_rx_irq(){ +} + +void mini_uart_init(){ + // GPIO 14 & 15 take function 0 + // Read out GPFSEL1 register + uint32_t tmp = IO_MMIO_read32(GPFSEL1); + + // Set GPIO 14 & 15 function bits + tmp &= ~(0b111111 << 12); + tmp |= 0b010010 << 12; + IO_MMIO_write32(GPFSEL1, tmp); + + + // disable pull-up/down of GPIO 14 & 15 + // Write to GPPUD to set the required control signal + IO_MMIO_write32(GPPUD, 0); + + // Wait 150 cycles – this provides the required set-up time for the control signal + delay_cycles(150); + + // Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to modify + IO_MMIO_write32(GPPUDCLK0, (1 << 14) | (1 << 15)); + + // Wait 150 cycles – this provides the required hold time for the control signal + delay_cycles(150); + + // Write to GPPUD to remove the control signa + IO_MMIO_write32(GPPUD, 0); + + // Write to GPPUDCLK0/1 to remove the clock + IO_MMIO_write32(GPPUDCLK0, 0); + + // Initialize Auxiliary peripherals Register + // Mini UART enable + IO_MMIO_write32(AUX_ENABLES, 1); + + // To disable auto flow control and disable receiver and transmitter, set control register to 0 + IO_MMIO_write32(AUX_MU_CNTL_REG, 0); + + // Disable mini UART's interrupt + IO_MMIO_write32(AUX_MU_IER_REG, 0); + + // Set UART to 8-bit mode + IO_MMIO_write32(AUX_MU_LCR_REG, 3); + + // To indicate that our UART is able to receive data, set RTS line to be always high + IO_MMIO_write32(AUX_MU_MCR_REG, 0); + + // Set Baud rate to 115200 + IO_MMIO_write32(AUX_MU_BAUD_REG, BAUD_RATE_REG); + + // disable FIFO + IO_MMIO_write32(AUX_MU_IIR_REG, 6); + + // Start UART + IO_MMIO_write32(AUX_MU_CNTL_REG, 3); + + return; +} + +uint8_t mini_uart_read(void){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & 0x1)); + return IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; +} + +void mini_uart_write(uint8_t val){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & (0x1 << 5))); + IO_MMIO_write32(AUX_MU_IO_REG, val); +} + +ssize_t write_bytes(uint8_t* buf, size_t n){ + for(uint64_t i = 0 ; i < n ; i++) mini_uart_write(buf[i]); + return n; +} + +void write_str(char* buf){ + while(*buf) mini_uart_write((uint8_t)*buf++); + return; +} + +void write_hex(uint64_t n){ + int i = 0; + char buf[16]; + char *hex_table = "0123456789abcdef"; + do{ + buf[i] = hex_table[n & 0xf]; + n = n >> 4; + i++; + }while(n); + do{ + i--; + mini_uart_write(buf[i]); + }while(i > 0); +} + +void mini_uart_irq_init(){ + rx_rbuf = create_simple_ring_buf(4095); + + IO_MMIO_write32(AUX_MU_IER_REG, 1); + IO_MMIO_write32(ENABLE_IRQS_1, 1 << 29); +} + + +void mini_uart_rx_softirq_callback(){ +} + +void mini_uart_irq_read(){ + uint8_t b[1]; + b[0] = IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; + ring_buf_write_unsafe(rx_rbuf, b, 1); +} + +size_t mini_uart_get_rx_len(){ + return ring_buf_get_len(rx_rbuf); +} + +uint8_t mini_uart_aio_read(void){ + uint8_t b[1]; + IO_MMIO_write32(AUX_MU_IER_REG, 1); + while(!ring_buf_read(rx_rbuf, b, 1)); + IO_MMIO_write32(AUX_MU_IER_REG, 0); + return b[0]; +} + +size_t sys_uart_write(char *buf, size_t size){ + uint64_t daif,ret; + //size_t c; + daif = local_irq_disable_save(); + ret = write_bytes(buf, size); + local_irq_restore(daif); + return ret; +} + +size_t sys_uart_read(char *buf, size_t size){ + size_t c = 0, tmp; + IO_MMIO_write32(AUX_MU_IER_REG, 1); + while(size){ + tmp = ring_buf_read(rx_rbuf, buf + c, size); + + size = size - tmp; + c = c + tmp; + preempt_schedule(); + } + IO_MMIO_write32(AUX_MU_IER_REG, 0); + return c; +} diff --git a/lab5/test/lib/.gdb_history b/lab5/test/lib/.gdb_history new file mode 100644 index 000000000..58afc787f --- /dev/null +++ b/lab5/test/lib/.gdb_history @@ -0,0 +1,2 @@ +run +quit diff --git a/lab5/test/lib/dtb_parse/.gdb_history b/lab5/test/lib/dtb_parse/.gdb_history new file mode 100644 index 000000000..8ae386791 --- /dev/null +++ b/lab5/test/lib/dtb_parse/.gdb_history @@ -0,0 +1,43 @@ +b main +run +n +quit +run +p fdt +quit +b main +n +run +n +x/gx ptr +quit +b main +run +n +statbuf->size +p statbuf->size +p statbuf->st_size +quit +run +b main +run +n +s +n +p token +p/x pdft_struct +p/x pdt_struct +x/gx 0x7ffff7fb3048 +x/s 0x7ffff7fb3048 +x/dx 0x7ffff7fb3048 +x/wx 0x7ffff7fb3048 +x/4wx 0x7ffff7fb3048 +n +p len +n +quit +quit +run +quit +run +quit diff --git a/lab5/test/lib/dtb_parse/Makefile b/lab5/test/lib/dtb_parse/Makefile new file mode 100644 index 000000000..d6e1a8f08 --- /dev/null +++ b/lab5/test/lib/dtb_parse/Makefile @@ -0,0 +1,2 @@ +all: + gcc main.c fdt_parse.c -o main -g -O0 diff --git a/lab5/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb b/lab5/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 000000000..6f9ef31cc Binary files /dev/null and b/lab5/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb differ diff --git a/lab5/test/lib/dtb_parse/fdt_parse.c b/lab5/test/lib/dtb_parse/fdt_parse.c new file mode 100644 index 000000000..bb8abd2c8 --- /dev/null +++ b/lab5/test/lib/dtb_parse/fdt_parse.c @@ -0,0 +1,113 @@ +#include "fdt_parse.h" +#include +#include +#include + +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } + +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = (fdt_header*)malloc(sizeof(fdt_header)); + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) / 4; + //printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + len += 2; + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + printf("Parsing error!!\n"); + exit(0); + } + } +} + +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab5/test/lib/dtb_parse/fdt_parse.h b/lab5/test/lib/dtb_parse/fdt_parse.h new file mode 100644 index 000000000..876b4087a --- /dev/null +++ b/lab5/test/lib/dtb_parse/fdt_parse.h @@ -0,0 +1,53 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +#endif diff --git a/lab5/test/lib/dtb_parse/main b/lab5/test/lib/dtb_parse/main new file mode 100755 index 000000000..aa43f24f6 Binary files /dev/null and b/lab5/test/lib/dtb_parse/main differ diff --git a/lab5/test/lib/dtb_parse/main.c b/lab5/test/lib/dtb_parse/main.c new file mode 100644 index 000000000..9af1de752 --- /dev/null +++ b/lab5/test/lib/dtb_parse/main.c @@ -0,0 +1,19 @@ +#include "fdt_parse.h" +#include +#include +#include +#include +#include +#include + +int main(void){ + int fd = open("./bcm2710-rpi-3-b-plus.dtb", O_RDONLY); + if(fd < 0){ + printf("failed to open file\n"); + } + struct stat statbuf; + fstat(fd, &statbuf); + char *ptr = mmap(NULL,statbuf.st_size,PROT_READ,MAP_PRIVATE,fd,0); + + fdt_parser(ptr, fdt_print_callback); +} diff --git a/lab5/test/lib/dtb_parse/tmp.dts b/lab5/test/lib/dtb_parse/tmp.dts new file mode 100644 index 000000000..1ceb3539f --- /dev/null +++ b/lab5/test/lib/dtb_parse/tmp.dts @@ -0,0 +1,1515 @@ +/dts-v1/; + +/memreserve/ 0x0000000000000000 0x0000000000001000; +/ { + compatible = "raspberrypi,3-model-b-plus\0brcm,bcm2837"; + model = "Raspberry Pi 3 Model B+"; + #address-cells = <0x01>; + #size-cells = <0x01>; + interrupt-parent = <0x01>; + + aliases { + serial0 = "/soc/serial@7e215040"; + serial1 = "/soc/serial@7e201000"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + aux = "/soc/aux@7e215000"; + sound = "/soc/sound"; + soc = "/soc"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + uart0 = "/soc/serial@7e201000"; + uart1 = "/soc/serial@7e215040"; + sdhost = "/soc/mmc@7e202000"; + mmc = "/soc/mmc@7e300000"; + mmc1 = "/soc/mmcnr@7e300000"; + mmc0 = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c1 = "/soc/i2c@7e804000"; + i2c10 = "/soc/i2c0mux/i2c@1"; + spi0 = "/soc/spi@7e204000"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + usb = "/soc/usb@7e980000"; + leds = "/leds"; + fb = "/soc/fb"; + thermal = "/soc/thermal@7e212000"; + axiperf = "/soc/axiperf"; + i2c2 = "/soc/i2c@7e805000"; + ethernet0 = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + }; + + chosen { + bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; + }; + + reserved-memory { + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges; + phandle = <0x37>; + + linux,cma { + compatible = "shared-dma-pool"; + size = <0x4000000>; + reusable; + linux,cma-default; + phandle = <0x38>; + }; + }; + + thermal-zones { + + cpu-thermal { + polling-delay-passive = <0x00>; + polling-delay = <0x3e8>; + thermal-sensors = <0x02>; + coefficients = <0xfffffde6 0x64960>; + phandle = <0x39>; + + cooling-maps { + }; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x7e000000 0x3f000000 0x1000000 0x40000000 0x40000000 0x1000>; + dma-ranges = <0xc0000000 0x00 0x3f000000>; + phandle = <0x3a>; + + txp@7e004000 { + compatible = "brcm,bcm2835-txp"; + reg = <0x7e004000 0x20>; + interrupts = <0x01 0x0b>; + status = "disabled"; + phandle = <0x3b>; + }; + + cprman@7e101000 { + compatible = "brcm,bcm2835-cprman"; + #clock-cells = <0x01>; + reg = <0x7e101000 0x2000>; + clocks = <0x03 0x04 0x00 0x04 0x01 0x04 0x02 0x05 0x00 0x05 0x01 0x05 0x02>; + firmware = <0x06>; + phandle = <0x08>; + }; + + mailbox@7e00b880 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0x00 0x01>; + #mbox-cells = <0x00>; + phandle = <0x1f>; + }; + + gpio@7e200000 { + compatible = "brcm,bcm2835-gpio"; + reg = <0x7e200000 0xb4>; + interrupts = <0x02 0x11 0x02 0x12>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x07 0x00 0x00 0x36>; + pinctrl-names = "default"; + gpio-line-names = "ID_SDA\0ID_SCL\0SDA1\0SCL1\0GPIO_GCLK\0GPIO5\0GPIO6\0SPI_CE1_N\0SPI_CE0_N\0SPI_MISO\0SPI_MOSI\0SPI_SCLK\0GPIO12\0GPIO13\0TXD1\0RXD1\0GPIO16\0GPIO17\0GPIO18\0GPIO19\0GPIO20\0GPIO21\0GPIO22\0GPIO23\0GPIO24\0GPIO25\0GPIO26\0GPIO27\0HDMI_HPD_N\0STATUS_LED_G\0CTS0\0RTS0\0TXD0\0RXD0\0SD1_CLK\0SD1_CMD\0SD1_DATA0\0SD1_DATA1\0SD1_DATA2\0SD1_DATA3\0PWM0_OUT\0PWM1_OUT\0ETH_CLK\0WIFI_CLK\0SDA0\0SCL0\0SMPS_SCL\0SMPS_SDA\0SD_CLK_R\0SD_CMD_R\0SD_DATA0_R\0SD_DATA1_R\0SD_DATA2_R\0SD_DATA3_R"; + phandle = <0x07>; + + dpi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x06>; + phandle = <0x3c>; + }; + + emmc_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x07>; + phandle = <0x3d>; + }; + + emmc_gpio34 { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x3e>; + }; + + emmc_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x07>; + phandle = <0x17>; + }; + + gpclk0_gpio4 { + brcm,pins = <0x04>; + brcm,function = <0x04>; + phandle = <0x3f>; + }; + + gpclk1_gpio5 { + brcm,pins = <0x05>; + brcm,function = <0x04>; + phandle = <0x40>; + }; + + gpclk1_gpio42 { + brcm,pins = <0x2a>; + brcm,function = <0x04>; + phandle = <0x41>; + }; + + gpclk1_gpio44 { + brcm,pins = <0x2c>; + brcm,function = <0x04>; + phandle = <0x42>; + }; + + gpclk2_gpio6 { + brcm,pins = <0x06>; + brcm,function = <0x04>; + phandle = <0x43>; + }; + + gpclk2_gpio43 { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x44>; + }; + + i2c0_gpio0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x12>; + }; + + i2c0_gpio28 { + brcm,pins = <0x1c 0x1d>; + brcm,function = <0x04>; + phandle = <0x45>; + }; + + i2c0_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x05>; + phandle = <0x13>; + }; + + i2c1_gpio2 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x46>; + }; + + i2c1_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x06>; + phandle = <0x47>; + }; + + jtag_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x03>; + phandle = <0x48>; + }; + + pcm_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x49>; + }; + + pcm_gpio28 { + brcm,pins = <0x1c 0x1d 0x1e 0x1f>; + brcm,function = <0x06>; + phandle = <0x4a>; + }; + + sdhost_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x04>; + phandle = <0x0d>; + }; + + spi0_gpio7 { + brcm,pins = <0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x4b>; + }; + + spi0_gpio35 { + brcm,pins = <0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x04>; + phandle = <0x4c>; + }; + + spi1_gpio16 { + brcm,pins = <0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x03>; + phandle = <0x4d>; + }; + + spi2_gpio40 { + brcm,pins = <0x28 0x29 0x2a 0x2b 0x2c 0x2d>; + brcm,function = <0x03>; + phandle = <0x4e>; + }; + + uart0_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x04>; + phandle = <0x4f>; + }; + + uart0_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x07>; + phandle = <0x50>; + }; + + uart0_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x07>; + brcm,pull = <0x02 0x00>; + phandle = <0x51>; + }; + + uart0_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x52>; + }; + + uart0_gpio36 { + brcm,pins = <0x24 0x25>; + brcm,function = <0x06>; + phandle = <0x53>; + }; + + uart0_ctsrts_gpio38 { + brcm,pins = <0x26 0x27>; + brcm,function = <0x06>; + phandle = <0x54>; + }; + + uart1_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x02>; + phandle = <0x55>; + }; + + uart1_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x02>; + phandle = <0x56>; + }; + + uart1_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x02>; + phandle = <0x57>; + }; + + uart1_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x02>; + phandle = <0x58>; + }; + + uart1_gpio40 { + brcm,pins = <0x28 0x29>; + brcm,function = <0x02>; + phandle = <0x59>; + }; + + uart1_ctsrts_gpio42 { + brcm,pins = <0x2a 0x2b>; + brcm,function = <0x02>; + phandle = <0x5a>; + }; + + i2c_slave_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x07>; + phandle = <0x5b>; + }; + + jtag_gpio4 { + brcm,pins = <0x04 0x05 0x06 0x0c 0x0d>; + brcm,function = <0x02>; + phandle = <0x5c>; + }; + + pwm0_gpio12 { + brcm,pins = <0x0c>; + brcm,function = <0x04>; + phandle = <0x5d>; + }; + + pwm0_gpio18 { + brcm,pins = <0x12>; + brcm,function = <0x02>; + phandle = <0x5e>; + }; + + pwm0_gpio40 { + brcm,pins = <0x28>; + brcm,function = <0x04>; + phandle = <0x5f>; + }; + + pwm1_gpio13 { + brcm,pins = <0x0d>; + brcm,function = <0x04>; + phandle = <0x60>; + }; + + pwm1_gpio19 { + brcm,pins = <0x13>; + brcm,function = <0x02>; + phandle = <0x61>; + }; + + pwm1_gpio41 { + brcm,pins = <0x29>; + brcm,function = <0x04>; + phandle = <0x62>; + }; + + pwm1_gpio45 { + brcm,pins = <0x2d>; + brcm,function = <0x04>; + phandle = <0x63>; + }; + + dpi_18bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + brcm,pull = <0x00>; + phandle = <0x64>; + }; + + dpi_18bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + phandle = <0x65>; + }; + + dpi_18bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x66>; + }; + + dpi_18bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x67>; + }; + + dpi_16bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x68>; + }; + + dpi_16bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x69>; + }; + + dpi_16bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6a>; + }; + + dpi_16bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6b>; + }; + + gpioout { + brcm,pins = <0x06>; + brcm,function = <0x01>; + phandle = <0x6c>; + }; + + alt0 { + brcm,pins = <0x04 0x05 0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x6d>; + }; + + spi0_pins { + brcm,pins = <0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x0f>; + }; + + spi0_cs_pins { + brcm,pins = <0x08 0x07>; + brcm,function = <0x01>; + phandle = <0x10>; + }; + + i2c0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x6e>; + }; + + i2c1 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x18>; + }; + + i2s { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x0e>; + }; + + sdio_pins { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x1e>; + }; + + bt_pins { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x0a>; + }; + + uart0_pins { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x09>; + }; + + uart1_pins { + brcm,pins; + brcm,function; + brcm,pull; + phandle = <0x16>; + }; + + audio_pins { + brcm,pins = <0x28 0x29>; + brcm,function = <0x04>; + phandle = <0x20>; + }; + }; + + serial@7e201000 { + compatible = "arm,pl011\0arm,primecell"; + reg = <0x7e201000 0x200>; + interrupts = <0x02 0x19>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk\0apb_pclk"; + arm,primecell-periphid = <0x241011>; + cts-event-workaround; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x09 0x0a>; + status = "okay"; + phandle = <0x26>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <0x2dc6c0>; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x33>; + }; + }; + + mmc@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <0x02 0x18>; + clocks = <0x08 0x14>; + status = "okay"; + dmas = <0x0c 0x2000000d>; + dma-names = "rx-tx"; + bus-width = <0x04>; + brcm,overclock-50 = <0x00>; + brcm,pio-limit = <0x01>; + firmware = <0x06>; + pinctrl-names = "default"; + pinctrl-0 = <0x0d>; + phandle = <0x2f>; + }; + + i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; + reg = <0x7e203000 0x24>; + clocks = <0x08 0x1f>; + status = "disabled"; + dmas = <0x0c 0x02 0x0c 0x03>; + dma-names = "tx\0rx"; + #sound-dai-cells = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x0e>; + phandle = <0x28>; + }; + + spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x200>; + interrupts = <0x02 0x16>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + dmas = <0x0c 0x06 0x0c 0x07>; + dma-names = "tx\0rx"; + pinctrl-names = "default"; + pinctrl-0 = <0x0f 0x10>; + cs-gpios = <0x07 0x08 0x01 0x07 0x07 0x01>; + phandle = <0x29>; + + spidev@0 { + compatible = "spidev"; + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x6f>; + }; + + spidev@1 { + compatible = "spidev"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x70>; + }; + }; + + i2c@7e205000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e205000 0x200>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x11>; + }; + + i2c0mux { + compatible = "i2c-mux-pinctrl"; + #address-cells = <0x01>; + #size-cells = <0x00>; + i2c-parent = <0x11>; + pinctrl-names = "i2c0\0i2c_csi_dsi"; + status = "disabled"; + pinctrl-0 = <0x12>; + pinctrl-1 = <0x13>; + phandle = <0x2a>; + + i2c@0 { + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x71>; + }; + + i2c@1 { + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x72>; + }; + }; + + dpi@7e208000 { + compatible = "brcm,bcm2835-dpi"; + reg = <0x7e208000 0x8c>; + clocks = <0x08 0x14 0x08 0x2c>; + clock-names = "core\0pixel"; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x73>; + }; + + dsi@7e209000 { + compatible = "brcm,bcm2835-dsi0"; + reg = <0x7e209000 0x78>; + interrupts = <0x02 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x20 0x08 0x2f 0x08 0x31>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi0_byte\0dsi0_ddr2\0dsi0_ddr"; + status = "disabled"; + power-domains = <0x14 0x11>; + phandle = <0x04>; + }; + + aux@7e215000 { + compatible = "brcm,bcm2835-aux"; + #clock-cells = <0x01>; + reg = <0x7e215000 0x08>; + clocks = <0x08 0x14>; + phandle = <0x15>; + }; + + serial@7e215040 { + compatible = "brcm,bcm2835-aux-uart"; + reg = <0x7e215040 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x00>; + status = "okay"; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x16>; + phandle = <0x27>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = "\0\a\b"; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x74>; + }; + }; + + spi@7e215080 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e215080 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x75>; + }; + + spi@7e2150c0 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e2150c0 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x02>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x76>; + }; + + pwm@7e20c000 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x7e20c000 0x28>; + clocks = <0x08 0x1e>; + assigned-clocks = <0x08 0x1e>; + assigned-clock-rates = <0x989680>; + #pwm-cells = <0x02>; + status = "disabled"; + phandle = <0x77>; + }; + + mmc@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + status = "disabled"; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x17>; + bus-width = <0x04>; + phandle = <0x30>; + }; + + hvs@7e400000 { + compatible = "brcm,bcm2835-hvs"; + reg = <0x7e400000 0x6000>; + interrupts = <0x02 0x01>; + status = "disabled"; + phandle = <0x78>; + }; + + dsi@7e700000 { + compatible = "brcm,bcm2835-dsi1"; + reg = <0x7e700000 0x8c>; + interrupts = <0x02 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x23 0x08 0x30 0x08 0x32>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi1_byte\0dsi1_ddr2\0dsi1_ddr"; + status = "disabled"; + power-domains = <0x14 0x12>; + phandle = <0x05>; + }; + + i2c@7e804000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e804000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x18>; + clock-frequency = <0x186a0>; + phandle = <0x2b>; + }; + + usb@7e980000 { + compatible = "brcm,bcm2708-usb"; + reg = <0x7e980000 0x10000 0x7e006000 0x1000>; + interrupts = <0x01 0x09 0x02 0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x19>; + clock-names = "otg"; + phys = <0x1a>; + phy-names = "usb2-phy"; + interrupt-names = "usb\0soft"; + power-domains = <0x14 0x06>; + phandle = <0x79>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet@1 { + compatible = "usb424,7800"; + reg = <0x01>; + phandle = <0x7a>; + + mdio { + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet-phy@1 { + reg = <0x01>; + microchip,led-modes = <0x01 0x06>; + microchip,eee-enabled; + microchip,tx-lpi-timer = <0x258>; + microchip,downshift-after = <0x02>; + phandle = <0x36>; + }; + }; + }; + }; + }; + }; + + dma@7e007000 { + compatible = "brcm,bcm2835-dma"; + reg = <0x7e007000 0xf00>; + interrupts = <0x01 0x10 0x01 0x11 0x01 0x12 0x01 0x13 0x01 0x14 0x01 0x15 0x01 0x16 0x01 0x17 0x01 0x18 0x01 0x19 0x01 0x1a 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1c>; + interrupt-names = "dma0\0dma1\0dma2\0dma3\0dma4\0dma5\0dma6\0dma7\0dma8\0dma9\0dma10\0dma11\0dma12\0dma13\0dma14\0dma-shared-all"; + #dma-cells = <0x01>; + brcm,dma-channel-mask = <0x7f35>; + phandle = <0x0c>; + }; + + interrupt-controller@7e00b200 { + compatible = "brcm,bcm2836-armctrl-ic"; + reg = <0x7e00b200 0x200>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + interrupts = <0x08 0x04>; + phandle = <0x01>; + }; + + watchdog@7e100000 { + compatible = "brcm,bcm2835-pm\0brcm,bcm2835-pm-wdt"; + #power-domain-cells = <0x01>; + #reset-cells = <0x01>; + reg = <0x7e100000 0x114 0x7e00a000 0x24>; + clocks = <0x08 0x15 0x08 0x1d 0x08 0x17 0x08 0x16>; + clock-names = "v3d\0peri_image\0h264\0isp"; + system-power-controller; + phandle = <0x2d>; + }; + + rng@7e104000 { + compatible = "brcm,bcm2835-rng"; + reg = <0x7e104000 0x10>; + interrupts = <0x02 0x1d>; + phandle = <0x2e>; + }; + + pixelvalve@7e206000 { + compatible = "brcm,bcm2835-pixelvalve0"; + reg = <0x7e206000 0x100>; + interrupts = <0x02 0x0d>; + status = "disabled"; + phandle = <0x7b>; + }; + + pixelvalve@7e207000 { + compatible = "brcm,bcm2835-pixelvalve1"; + reg = <0x7e207000 0x100>; + interrupts = <0x02 0x0e>; + status = "disabled"; + phandle = <0x7c>; + }; + + thermal@7e212000 { + compatible = "brcm,bcm2837-thermal"; + reg = <0x7e212000 0x08>; + clocks = <0x08 0x1b>; + #thermal-sensor-cells = <0x00>; + status = "okay"; + phandle = <0x02>; + }; + + i2c@7e805000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e805000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x1d>; + }; + + vec@7e806000 { + compatible = "brcm,bcm2835-vec"; + reg = <0x7e806000 0x1000>; + clocks = <0x1c 0x0f>; + interrupts = <0x02 0x1b>; + status = "disabled"; + power-domains = <0x14 0x07>; + phandle = <0x7d>; + }; + + pixelvalve@7e807000 { + compatible = "brcm,bcm2835-pixelvalve2"; + reg = <0x7e807000 0x100>; + interrupts = <0x02 0x0a>; + status = "disabled"; + phandle = <0x7e>; + }; + + hdmi@7e902000 { + compatible = "brcm,bcm2835-hdmi"; + reg = <0x7e902000 0x600 0x7e808000 0x100>; + reg-names = "hdmi\0hd"; + interrupts = <0x02 0x08 0x02 0x09>; + ddc = <0x1d>; + clocks = <0x1c 0x09 0x1c 0x0d>; + clock-names = "pixel\0hdmi"; + dmas = <0x0c 0x9000011>; + dma-names = "audio-rx"; + status = "disabled"; + power-domains = <0x14 0x05>; + hpd-gpios = <0x07 0x1c 0x01>; + phandle = <0x7f>; + }; + + v3d@7ec00000 { + compatible = "brcm,vc4-v3d"; + reg = <0x7ec00000 0x1000>; + interrupts = <0x01 0x0a>; + power-domains = <0x14 0x0a>; + status = "disabled"; + phandle = <0x80>; + }; + + gpu { + compatible = "brcm,bcm2835-vc4"; + status = "disabled"; + raspberrypi,firmware = <0x06>; + phandle = <0x81>; + }; + + local_intc@40000000 { + compatible = "brcm,bcm2836-l1-intc"; + reg = <0x40000000 0x100>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + phandle = <0x1b>; + }; + + mmcnr@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + non-removable; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x1e>; + bus-width = <0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x31>; + + wifi@1 { + reg = <0x01>; + compatible = "brcm,bcm4329-fmac"; + phandle = <0x82>; + }; + }; + + firmwarekms@7e600000 { + compatible = "raspberrypi,rpi-firmware-kms"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + brcm,firmware = <0x06>; + status = "disabled"; + phandle = <0x83>; + }; + + smi@7e600000 { + compatible = "brcm,bcm2835-smi"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + clocks = <0x08 0x2a>; + assigned-clocks = <0x08 0x2a>; + assigned-clock-rates = <0x7735940>; + dmas = <0x0c 0x04>; + dma-names = "rx-tx"; + status = "disabled"; + phandle = <0x84>; + }; + + csi@7e800000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e800000 0x800 0x7e802000 0x04>; + interrupts = <0x02 0x06>; + clocks = <0x08 0x2d 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + phandle = <0x85>; + }; + + csi@7e801000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e801000 0x800 0x7e802004 0x04>; + interrupts = <0x02 0x07>; + clocks = <0x08 0x2e 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0d>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + brcm,num-data-lanes = <0x02>; + phandle = <0x86>; + }; + + axiperf { + compatible = "brcm,bcm2835-axiperf"; + reg = <0x7e009800 0x100 0x7ee08000 0x100>; + firmware = <0x06>; + status = "disabled"; + phandle = <0x32>; + }; + + firmware { + compatible = "raspberrypi,bcm2835-firmware\0simple-mfd"; + #address-cells = <0x01>; + #size-cells = <0x01>; + mboxes = <0x1f>; + dma-ranges; + phandle = <0x06>; + + clocks { + compatible = "raspberrypi,firmware-clocks"; + #clock-cells = <0x01>; + phandle = <0x1c>; + }; + + vcio { + compatible = "raspberrypi,vcio"; + phandle = <0x87>; + }; + + expgpio { + compatible = "raspberrypi,firmware-gpio"; + gpio-controller; + #gpio-cells = <0x02>; + gpio-line-names = "BT_ON\0WL_ON\0PWR_LED_R\0LAN_RUN\0NC\0CAM_GPIO0\0CAM_GPIO1\0NC"; + status = "okay"; + phandle = <0x0b>; + }; + }; + + power { + compatible = "raspberrypi,bcm2835-power"; + firmware = <0x06>; + #power-domain-cells = <0x01>; + phandle = <0x14>; + }; + + mailbox@7e00b840 { + compatible = "brcm,bcm2836-vchiq\0brcm,bcm2835-vchiq"; + reg = <0x7e00b840 0x3c>; + interrupts = <0x00 0x02>; + phandle = <0x88>; + + bcm2835_audio { + compatible = "brcm,bcm2835-audio"; + brcm,firmware = <0x06>; + brcm,pwm-channels = <0x08>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x20>; + phandle = <0x2c>; + }; + }; + + gpiomem { + compatible = "brcm,bcm2835-gpiomem"; + reg = <0x7e200000 0x1000>; + }; + + fb { + compatible = "brcm,bcm2708-fb"; + firmware = <0x06>; + status = "okay"; + phandle = <0x89>; + }; + + sound { + status = "disabled"; + phandle = <0x8a>; + }; + }; + + clocks { + + clk-osc { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "osc"; + clock-frequency = <0x124f800>; + phandle = <0x03>; + }; + + clk-usb { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "otg"; + clock-frequency = <0x1c9c3800>; + phandle = <0x19>; + }; + }; + + phy { + compatible = "usb-nop-xceiv"; + #phy-cells = <0x00>; + phandle = <0x1a>; + }; + + arm-pmu { + compatible = "arm,cortex-a53-pmu\0arm,cortex-a7-pmu"; + interrupt-parent = <0x1b>; + interrupts = <0x09 0x04>; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupt-parent = <0x1b>; + interrupts = <0x00 0x04 0x01 0x04 0x03 0x04 0x02 0x04>; + always-on; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + enable-method = "brcm,bcm2836-smp"; + phandle = <0x8b>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x00>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xd8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x22>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x01>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x23>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x02>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x24>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x03>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xf0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x25>; + }; + + l2-cache0 { + compatible = "cache"; + cache-size = <0x80000>; + cache-line-size = <0x40>; + cache-sets = <0x200>; + cache-level = <0x02>; + phandle = <0x21>; + }; + }; + + cam1_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam1-reg"; + enable-active-high; + status = "okay"; + gpio = <0x0b 0x05 0x00>; + phandle = <0x8c>; + }; + + cam1_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8d>; + }; + + cam0_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam0-reg"; + enable-active-high; + status = "disabled"; + phandle = <0x8e>; + }; + + cam0_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8f>; + }; + + cam_dummy_reg { + compatible = "regulator-fixed"; + regulator-name = "cam-dummy-reg"; + status = "okay"; + phandle = <0x90>; + }; + + __overrides__ { + cam0-pwdn-ctrl; + cam0-pwdn; + cam0-led-ctrl; + cam0-led; + arm_freq = "\0\0\0\"clock-frequency:0\0\0\0\0#clock-frequency:0\0\0\0\0$clock-frequency:0\0\0\0\0%clock-frequency:0"; + cache_line_size; + uart0 = "\0\0\0&status"; + uart1 = "\0\0\0'status"; + i2s = "\0\0\0(status"; + spi = "\0\0\0)status"; + i2c0 = [00 00 00 11 73 74 61 74 75 73 00 00 00 00 2a 73 74 61 74 75 73 00]; + i2c1 = "\0\0\0+status"; + i2c0_baudrate = [00 00 00 11 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + i2c1_baudrate = "\0\0\0+clock-frequency:0"; + audio = "\0\0\0,status"; + watchdog = "\0\0\0-status"; + random = "\0\0\0.status"; + sd_overclock = "\0\0\0/brcm,overclock-50:0"; + sd_force_pio = "\0\0\0/brcm,force-pio?"; + sd_pio_limit = "\0\0\0/brcm,pio-limit:0"; + sd_debug = "\0\0\0/brcm,debug"; + sdio_overclock = "\0\0\00brcm,overclock-50:0\0\0\0\01brcm,overclock-50:0"; + axiperf = "\0\0\02status"; + i2c2_iknowwhatimdoing = [00 00 00 1d 73 74 61 74 75 73 00]; + i2c2_baudrate = [00 00 00 1d 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + sd_poll_once = "\0\0\0/non-removable?"; + krnbt = "\0\0\03status"; + krnbt_baudrate = "\0\0\03max-speed:0"; + act_led_gpio = "\0\0\04gpios:4"; + act_led_activelow = "\0\0\04gpios:8"; + act_led_trigger = "\0\0\04linux,default-trigger"; + pwr_led_gpio = "\0\0\05gpios:4"; + pwr_led_activelow = "\0\0\05gpios:8"; + pwr_led_trigger = "\0\0\05linux,default-trigger"; + eee = "\0\0\06microchip,eee-enabled?"; + tx_lpi_timer = "\0\0\06microchip,tx-lpi-timer:0"; + eth_led0 = "\0\0\06microchip,led-modes:0"; + eth_led1 = "\0\0\06microchip,led-modes:4"; + eth_downshift_after = "\0\0\06microchip,downshift-after:0"; + eth_max_speed = "\0\0\06max-speed:0"; + }; + + leds { + compatible = "gpio-leds"; + phandle = <0x91>; + + led-act { + label = "led0"; + default-state = "keep"; + linux,default-trigger = "mmc0"; + gpios = <0x07 0x1d 0x00>; + phandle = <0x34>; + }; + + led-pwr { + label = "led1"; + linux,default-trigger = "default-on"; + gpios = <0x0b 0x02 0x01>; + phandle = <0x35>; + }; + }; + + fixedregulator_3v3 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microvolt = <0x325aa0>; + regulator-name = "3v3"; + phandle = <0x92>; + }; + + fixedregulator_5v0 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x4c4b40>; + regulator-min-microvolt = <0x4c4b40>; + regulator-name = "5v0"; + phandle = <0x93>; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00 0x00>; + }; + + __symbols__ { + rmem = "/reserved-memory"; + cma = "/reserved-memory/linux,cma"; + cpu_thermal = "/thermal-zones/cpu-thermal"; + soc = "/soc"; + txp = "/soc/txp@7e004000"; + clocks = "/soc/cprman@7e101000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + dpi_gpio0 = "/soc/gpio@7e200000/dpi_gpio0"; + emmc_gpio22 = "/soc/gpio@7e200000/emmc_gpio22"; + emmc_gpio34 = "/soc/gpio@7e200000/emmc_gpio34"; + emmc_gpio48 = "/soc/gpio@7e200000/emmc_gpio48"; + gpclk0_gpio4 = "/soc/gpio@7e200000/gpclk0_gpio4"; + gpclk1_gpio5 = "/soc/gpio@7e200000/gpclk1_gpio5"; + gpclk1_gpio42 = "/soc/gpio@7e200000/gpclk1_gpio42"; + gpclk1_gpio44 = "/soc/gpio@7e200000/gpclk1_gpio44"; + gpclk2_gpio6 = "/soc/gpio@7e200000/gpclk2_gpio6"; + gpclk2_gpio43 = "/soc/gpio@7e200000/gpclk2_gpio43"; + i2c0_gpio0 = "/soc/gpio@7e200000/i2c0_gpio0"; + i2c0_gpio28 = "/soc/gpio@7e200000/i2c0_gpio28"; + i2c0_gpio44 = "/soc/gpio@7e200000/i2c0_gpio44"; + i2c1_gpio2 = "/soc/gpio@7e200000/i2c1_gpio2"; + i2c1_gpio44 = "/soc/gpio@7e200000/i2c1_gpio44"; + jtag_gpio22 = "/soc/gpio@7e200000/jtag_gpio22"; + pcm_gpio18 = "/soc/gpio@7e200000/pcm_gpio18"; + pcm_gpio28 = "/soc/gpio@7e200000/pcm_gpio28"; + sdhost_gpio48 = "/soc/gpio@7e200000/sdhost_gpio48"; + spi0_gpio7 = "/soc/gpio@7e200000/spi0_gpio7"; + spi0_gpio35 = "/soc/gpio@7e200000/spi0_gpio35"; + spi1_gpio16 = "/soc/gpio@7e200000/spi1_gpio16"; + spi2_gpio40 = "/soc/gpio@7e200000/spi2_gpio40"; + uart0_gpio14 = "/soc/gpio@7e200000/uart0_gpio14"; + uart0_ctsrts_gpio16 = "/soc/gpio@7e200000/uart0_ctsrts_gpio16"; + uart0_ctsrts_gpio30 = "/soc/gpio@7e200000/uart0_ctsrts_gpio30"; + uart0_gpio32 = "/soc/gpio@7e200000/uart0_gpio32"; + uart0_gpio36 = "/soc/gpio@7e200000/uart0_gpio36"; + uart0_ctsrts_gpio38 = "/soc/gpio@7e200000/uart0_ctsrts_gpio38"; + uart1_gpio14 = "/soc/gpio@7e200000/uart1_gpio14"; + uart1_ctsrts_gpio16 = "/soc/gpio@7e200000/uart1_ctsrts_gpio16"; + uart1_gpio32 = "/soc/gpio@7e200000/uart1_gpio32"; + uart1_ctsrts_gpio30 = "/soc/gpio@7e200000/uart1_ctsrts_gpio30"; + uart1_gpio40 = "/soc/gpio@7e200000/uart1_gpio40"; + uart1_ctsrts_gpio42 = "/soc/gpio@7e200000/uart1_ctsrts_gpio42"; + i2c_slave_gpio18 = "/soc/gpio@7e200000/i2c_slave_gpio18"; + jtag_gpio4 = "/soc/gpio@7e200000/jtag_gpio4"; + pwm0_gpio12 = "/soc/gpio@7e200000/pwm0_gpio12"; + pwm0_gpio18 = "/soc/gpio@7e200000/pwm0_gpio18"; + pwm0_gpio40 = "/soc/gpio@7e200000/pwm0_gpio40"; + pwm1_gpio13 = "/soc/gpio@7e200000/pwm1_gpio13"; + pwm1_gpio19 = "/soc/gpio@7e200000/pwm1_gpio19"; + pwm1_gpio41 = "/soc/gpio@7e200000/pwm1_gpio41"; + pwm1_gpio45 = "/soc/gpio@7e200000/pwm1_gpio45"; + dpi_18bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio0"; + dpi_18bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio2"; + dpi_18bit_gpio0 = "/soc/gpio@7e200000/dpi_18bit_gpio0"; + dpi_18bit_gpio2 = "/soc/gpio@7e200000/dpi_18bit_gpio2"; + dpi_16bit_gpio0 = "/soc/gpio@7e200000/dpi_16bit_gpio0"; + dpi_16bit_gpio2 = "/soc/gpio@7e200000/dpi_16bit_gpio2"; + dpi_16bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio0"; + dpi_16bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio2"; + gpioout = "/soc/gpio@7e200000/gpioout"; + alt0 = "/soc/gpio@7e200000/alt0"; + spi0_pins = "/soc/gpio@7e200000/spi0_pins"; + spi0_cs_pins = "/soc/gpio@7e200000/spi0_cs_pins"; + i2c0_pins = "/soc/gpio@7e200000/i2c0"; + i2c1_pins = "/soc/gpio@7e200000/i2c1"; + i2s_pins = "/soc/gpio@7e200000/i2s"; + sdio_pins = "/soc/gpio@7e200000/sdio_pins"; + bt_pins = "/soc/gpio@7e200000/bt_pins"; + uart0_pins = "/soc/gpio@7e200000/uart0_pins"; + uart1_pins = "/soc/gpio@7e200000/uart1_pins"; + audio_pins = "/soc/gpio@7e200000/audio_pins"; + uart0 = "/soc/serial@7e201000"; + bt = "/soc/serial@7e201000/bluetooth"; + sdhost = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + spi0 = "/soc/spi@7e204000"; + spi = "/soc/spi@7e204000"; + spidev0 = "/soc/spi@7e204000/spidev@0"; + spidev1 = "/soc/spi@7e204000/spidev@1"; + i2c0if = "/soc/i2c@7e205000"; + i2c0mux = "/soc/i2c0mux"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c_csi_dsi = "/soc/i2c0mux/i2c@1"; + dpi = "/soc/dpi@7e208000"; + dsi0 = "/soc/dsi@7e209000"; + aux = "/soc/aux@7e215000"; + uart1 = "/soc/serial@7e215040"; + minibt = "/soc/serial@7e215040/bluetooth"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + pwm = "/soc/pwm@7e20c000"; + mmc = "/soc/mmc@7e300000"; + sdhci = "/soc/mmc@7e300000"; + hvs = "/soc/hvs@7e400000"; + dsi1 = "/soc/dsi@7e700000"; + i2c1 = "/soc/i2c@7e804000"; + usb = "/soc/usb@7e980000"; + ethernet = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + eth_phy = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1/mdio/ethernet-phy@1"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + pm = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + pixelvalve0 = "/soc/pixelvalve@7e206000"; + pixelvalve1 = "/soc/pixelvalve@7e207000"; + thermal = "/soc/thermal@7e212000"; + i2c2 = "/soc/i2c@7e805000"; + vec = "/soc/vec@7e806000"; + pixelvalve2 = "/soc/pixelvalve@7e807000"; + hdmi = "/soc/hdmi@7e902000"; + v3d = "/soc/v3d@7ec00000"; + vc4 = "/soc/gpu"; + local_intc = "/soc/local_intc@40000000"; + mmcnr = "/soc/mmcnr@7e300000"; + brcmf = "/soc/mmcnr@7e300000/wifi@1"; + firmwarekms = "/soc/firmwarekms@7e600000"; + smi = "/soc/smi@7e600000"; + csi0 = "/soc/csi@7e800000"; + csi1 = "/soc/csi@7e801000"; + axiperf = "/soc/axiperf"; + firmware = "/soc/firmware"; + firmware_clocks = "/soc/firmware/clocks"; + vcio = "/soc/firmware/vcio"; + expgpio = "/soc/firmware/expgpio"; + power = "/soc/power"; + vchiq = "/soc/mailbox@7e00b840"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + fb = "/soc/fb"; + sound = "/soc/sound"; + clk_osc = "/clocks/clk-osc"; + clk_usb = "/clocks/clk-usb"; + usbphy = "/phy"; + cpus = "/cpus"; + cpu0 = "/cpus/cpu@0"; + cpu1 = "/cpus/cpu@1"; + cpu2 = "/cpus/cpu@2"; + cpu3 = "/cpus/cpu@3"; + l2 = "/cpus/l2-cache0"; + cam1_reg = "/cam1_regulator"; + cam1_clk = "/cam1_clk"; + cam0_regulator = "/cam0_regulator"; + cam0_clk = "/cam0_clk"; + cam0_reg = "/cam_dummy_reg"; + cam_dummy_reg = "/cam_dummy_reg"; + leds = "/leds"; + act_led = "/leds/led-act"; + pwr_led = "/leds/led-pwr"; + vdd_3v3_reg = "/fixedregulator_3v3"; + vdd_5v0_reg = "/fixedregulator_5v0"; + }; +}; diff --git a/lab5/test/lib/dtb_parse/types.h b/lab5/test/lib/dtb_parse/types.h new file mode 100644 index 000000000..94f612c66 --- /dev/null +++ b/lab5/test/lib/dtb_parse/types.h @@ -0,0 +1,26 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#define NULL ((void*)0) + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) +#endif diff --git a/lab5/test/lib/list/Makefile b/lab5/test/lib/list/Makefile new file mode 100644 index 000000000..764af75c6 --- /dev/null +++ b/lab5/test/lib/list/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/list.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab5/test/lib/list/test b/lab5/test/lib/list/test new file mode 100755 index 000000000..dd63c9895 Binary files /dev/null and b/lab5/test/lib/list/test differ diff --git a/lab5/test/lib/list/test.c b/lab5/test/lib/list/test.c new file mode 100644 index 000000000..b568a42a4 --- /dev/null +++ b/lab5/test/lib/list/test.c @@ -0,0 +1,59 @@ +#include "lib/list.h" +#include +#include +#include +struct student{ + int id; + char name[100]; + struct list_head list; +}; + +struct student* create_student(int id, char* name){ + struct student* s = (struct student*)malloc(sizeof(struct student)); + s->id = id; + strcpy(s->name, name); + return s; +} +void print_student(struct student* s){ + printf("------------------------------------------\n"); + printf(" id: %d\n", s->id); + printf(" name: %s\n", s->name); + printf("------------------------------------------\n"); +} +int main(void){ + struct list_head* node, head; + INIT_LIST_HEAD(&head); + + if(list_empty(&head)){ + printf("List is empty\n"); + } + list_add(&create_student(13, "xiaobye")->list, &head); + list_add(&create_student(35, "test01")->list, &head); + list_add(&create_student(34, "test02")->list, &head); + + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + if(!list_empty(&head)){ + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + } + + + return 0; +} + diff --git a/lab5/test/lib/malloc/.gdb_history b/lab5/test/lib/malloc/.gdb_history new file mode 100644 index 000000000..1b332373d --- /dev/null +++ b/lab5/test/lib/malloc/.gdb_history @@ -0,0 +1,9 @@ +b main +run +ni +x/gx $rax +x/gx $rax - 0x10 + call malloc(1) +x/gx $rax - 0x10 +x/gx 0x5555555592c0 +quit diff --git a/lab5/test/lib/malloc/Makefile b/lab5/test/lib/malloc/Makefile new file mode 100644 index 000000000..2aedecaf1 --- /dev/null +++ b/lab5/test/lib/malloc/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/simple_malloc.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab5/test/lib/malloc/test b/lab5/test/lib/malloc/test new file mode 100755 index 000000000..194c23579 Binary files /dev/null and b/lab5/test/lib/malloc/test differ diff --git a/lab5/test/lib/malloc/test.c b/lab5/test/lib/malloc/test.c new file mode 100644 index 000000000..374f6deff --- /dev/null +++ b/lab5/test/lib/malloc/test.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include "lib/simple_malloc.h" + +#define RANGE 1000 +int main(void){ + void* cur,* next; + size_t req_size, real_size; + void* p = mmap( NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 ); + init_malloc_state(p); + srand((unsigned)time(0)); + + for(int i = 0 ; i < 30 ; i++){ + req_size = (uint64_t)rand() % RANGE; + cur = simple_malloc(req_size); + next = get_remainder(); + real_size = (uint64_t)next - (uint64_t)cur; + printf("cur: %p, next: %p, request size: %lu, real size: %lu, legal: %d\n", cur, next , req_size, real_size, (req_size <= real_size) && !(real_size % 16)); + } + + return 0; +} diff --git a/lab5/test/lib/malloc/test.py b/lab5/test/lib/malloc/test.py new file mode 100644 index 000000000..cce0d171c --- /dev/null +++ b/lab5/test/lib/malloc/test.py @@ -0,0 +1,9 @@ +def req2size(val, a): + if val < 16: + print(val,": ", hex(32)) + else: + print(val,": ",hex((val + 16 + (a - 1)) & ~(a-1))) + +for i in range(0, 64): + req2size(i, 16) + diff --git a/lab5/test/lib/ring_buffer/.gdb_history b/lab5/test/lib/ring_buffer/.gdb_history new file mode 100644 index 000000000..b7bc3d7af --- /dev/null +++ b/lab5/test/lib/ring_buffer/.gdb_history @@ -0,0 +1,17 @@ +run +quit +file main +run +p rbuf +quit +quit +run +x/gx 0x555555556008 +p rbuf->buf[rbuf->head] +s +ni +quit +b main +run +n +quit diff --git a/lab5/test/lib/ring_buffer/Makefile b/lab5/test/lib/ring_buffer/Makefile new file mode 100644 index 000000000..ec3d806b1 --- /dev/null +++ b/lab5/test/lib/ring_buffer/Makefile @@ -0,0 +1,2 @@ +all: + gcc main.c ring_buffer.c -o main -g -O0 diff --git a/lab5/test/lib/ring_buffer/main b/lab5/test/lib/ring_buffer/main new file mode 100755 index 000000000..bc8cc09fa Binary files /dev/null and b/lab5/test/lib/ring_buffer/main differ diff --git a/lab5/test/lib/ring_buffer/main.c b/lab5/test/lib/ring_buffer/main.c new file mode 100644 index 000000000..ea70d0e9b --- /dev/null +++ b/lab5/test/lib/ring_buffer/main.c @@ -0,0 +1,50 @@ +#include "ring_buffer.h" +#include +#include +char* s = "abcdefghijklmn"; +int main(void){ + char b[10]; + ring_buffer* rbuf = create_ring_buf(10); + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } + + ring_buf_write(rbuf, s, 8); + + if(!ring_buf_is_empty(rbuf)){ + printf("Ring buffer is has some contant now!\n"); + int i = ring_buf_read(rbuf, b, 100); + b[i] = '\0'; + + printf("%d: %s\n", i, b); + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } + } + printf("%lu\n", ring_buf_write(rbuf, s, 16)); + if(ring_buf_is_full(rbuf)){ + printf("Ring buffer is full now!\n"); + } + + int i = ring_buf_read(rbuf, b, 4); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + i = ring_buf_write(rbuf, b, 10); + printf("%d\n", i); + + i = ring_buf_read(rbuf, b, 7); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + i = ring_buf_read(rbuf, b, 10); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + if(ring_buf_is_full(rbuf)){ + printf("Ring buffer is full now!\n"); + } + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } +} diff --git a/lab5/test/lib/ring_buffer/ring_buffer.c b/lab5/test/lib/ring_buffer/ring_buffer.c new file mode 100644 index 000000000..a5e7e3612 --- /dev/null +++ b/lab5/test/lib/ring_buffer/ring_buffer.c @@ -0,0 +1,42 @@ +#include "ring_buffer.h" +#include +ring_buffer* create_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)malloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)malloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + return tmp; +} + +uint8_t ring_buf_is_empty(ring_buffer* rbuf){ + if(rbuf->head == rbuf->tail) return 1; + return 0; +} +uint8_t ring_buf_is_full(ring_buffer* rbuf){ + if((rbuf->tail + 1) % (rbuf->size + 1) == rbuf->head) return 1; + return 0; +} +size_t ring_buf_write(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + return count; +} +size_t ring_buf_read(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + return count; +} + diff --git a/lab5/test/lib/ring_buffer/ring_buffer.h b/lab5/test/lib/ring_buffer/ring_buffer.h new file mode 100644 index 000000000..61c0431d4 --- /dev/null +++ b/lab5/test/lib/ring_buffer/ring_buffer.h @@ -0,0 +1,17 @@ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ +#include "types.h" + +typedef struct{ + size_t size; + uint64_t head; + uint64_t tail; + uint8_t* buf; +}ring_buffer; + +extern ring_buffer* create_ring_buf(size_t); +extern size_t ring_buf_write(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read(ring_buffer*, uint8_t*, size_t); +extern uint8_t ring_buf_is_full(ring_buffer*); +extern uint8_t ring_buf_is_empty(ring_buffer*); +#endif diff --git a/lab5/test/lib/ring_buffer/types.h b/lab5/test/lib/ring_buffer/types.h new file mode 100644 index 000000000..94f612c66 --- /dev/null +++ b/lab5/test/lib/ring_buffer/types.h @@ -0,0 +1,26 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#define NULL ((void*)0) + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) +#endif diff --git a/lab5/test/lib/string/.gdb_history b/lab5/test/lib/string/.gdb_history new file mode 100644 index 000000000..d0d68342a --- /dev/null +++ b/lab5/test/lib/string/.gdb_history @@ -0,0 +1,47 @@ +b main +run +n +quit +run +b main +run +n +quit +b main +run +n +run +n +s +s +n +x/gx rax +x/gx $rax +run +s +n +s +x/bx s +s +p c +n +n +quit +b main +run +s +x/s delim +s +s +ni +n +ni +x/s s +x/s pos +x/b pos +x/bx pos +n +n +s +s +quit diff --git a/lab5/test/lib/string/Makefile b/lab5/test/lib/string/Makefile new file mode 100644 index 000000000..e7e0f12c1 --- /dev/null +++ b/lab5/test/lib/string/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/string.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab5/test/lib/string/test b/lab5/test/lib/string/test new file mode 100755 index 000000000..a0a7ea144 Binary files /dev/null and b/lab5/test/lib/string/test differ diff --git a/lab5/test/lib/string/test.c b/lab5/test/lib/string/test.c new file mode 100644 index 000000000..b23d13172 --- /dev/null +++ b/lab5/test/lib/string/test.c @@ -0,0 +1,31 @@ + +// C code to demonstrate working of +// strtok +#include +#include "string.h" + +// Driver function +int main() +{ + // Declaration of string + char *gfg = "setTimeout 123"; + + // Declaration of delimiter + const char s[4] = "-"; + char* tok; + + // Use of strtok + // get first token + tok = strtok(gfg, s); + + // Checks for delimiter + while (tok != 0) { + printf(" %s\n", tok); + + // Use of strtok + // go through other tokens + tok = strtok(0, s); + } + + return (0); +} diff --git a/lab5/tmp b/lab5/tmp new file mode 100644 index 000000000..cfe6ea8df --- /dev/null +++ b/lab5/tmp @@ -0,0 +1,1449 @@ +sudo qemu-system-aarch64 -M raspi3b -kernel /home/xiaobye/Documents/OSDI/osc2022/lab2/build/kernel8.img -display none -serial null -serial stdio -initrd tools/cpio/initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + { + compatible ; + model ; + #address-cells ; + #size-cells ; + interrupt-parent ; + memory@0 { + reg ; + device_type ; + } + aliases { + serial0 ; + serial1 ; + audio ; + aux ; + sound ; + soc ; + dma ; + intc ; + watchdog ; + random ; + mailbox ; + gpio ; + uart0 ; + uart1 ; + sdhost ; + mmc ; + mmc1 ; + mmc0 ; + i2s ; + i2c0 ; + i2c1 ; + i2c10 ; + spi0 ; + spi1 ; + spi2 ; + usb ; + leds ; + fb ; + thermal ; + axiperf ; + i2c2 ; + ethernet0 ; + } + chosen { + linux,initrd-end ; + linux,initrd-start ; + bootargs ; + } + reserved-memory { + #address-cells ; + #size-cells ; + ranges ; + phandle ; + linux,cma { + compatible ; + size ; + reusable ; + linux,cma-default ; + phandle ; + } + } + thermal-zones { + cpu-thermal { + polling-delay-passive ; + polling-delay ; + thermal-sensors ; + coefficients ; + phandle ; + cooling-maps { + } + } + } + soc { + compatible ; + #address-cells ; + #size-cells ; + ranges ; + dma-ranges ; + phandle ; + txp@7e004000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + cprman@7e101000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + firmware ; + phandle ; + } + mailbox@7e00b880 { + compatible ; + reg ; + interrupts ; + #mbox-cells ; + phandle ; + } + gpio@7e200000 { + compatible ; + reg ; + interrupts ; + gpio-controller ; + #gpio-cells ; + interrupt-controller ; + #interrupt-cells ; + gpio-ranges ; + pinctrl-names ; + gpio-line-names ; + phandle ; + dpi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio34 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + emmc_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk0_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio5 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio6 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio43 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + i2c0_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + sdhost_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio7 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio35 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi1_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi2_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio32 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio36 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio38 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio32 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c_slave_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio12 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio13 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio19 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio41 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio45 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + dpi_18bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpioout { + brcm,pins ; + brcm,function ; + phandle ; + } + alt0 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_cs_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2s { + brcm,pins ; + brcm,function ; + phandle ; + } + sdio_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + bt_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart1_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + audio_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + } + serial@7e201000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + arm,primecell-periphid ; + cts-event-workaround ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + status ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + mmc@7e202000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + bus-width ; + brcm,overclock-50 ; + brcm,pio-limit ; + firmware ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + i2s@7e203000 { + compatible ; + reg ; + clocks ; + status ; + dmas ; + dma-names ; + #sound-dai-cells ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + spi@7e204000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + dmas ; + dma-names ; + pinctrl-names ; + pinctrl-0 ; + cs-gpios ; + phandle ; + spidev@0 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + spidev@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + } + i2c@7e205000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + i2c0mux { + compatible ; + #address-cells ; + #size-cells ; + i2c-parent ; + pinctrl-names ; + status ; + pinctrl-0 ; + pinctrl-1 ; + phandle ; + i2c@0 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + i2c@1 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + } + dpi@7e208000 { + compatible ; + reg ; + clocks ; + clock-names ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + dsi@7e209000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + aux@7e215000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + phandle ; + } + serial@7e215040 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + spi@7e215080 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + spi@7e2150c0 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + pwm@7e20c000 { + compatible ; + reg ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + #pwm-cells ; + status ; + phandle ; + } + mmc@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + brcm,overclock-50 ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + phandle ; + } + hvs@7e400000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + dsi@7e700000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + i2c@7e804000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + pinctrl-names ; + pinctrl-0 ; + clock-frequency ; + phandle ; + } + usb@7e980000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + clocks ; + clock-names ; + phys ; + phy-names ; + interrupt-names ; + power-domains ; + phandle ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + ethernet@1 { + compatible ; + reg ; + phandle ; + mdio { + #address-cells ; + #size-cells ; + ethernet-phy@1 { + reg ; + microchip,led-modes ; + microchip,eee-enabled ; + microchip,tx-lpi-timer ; + microchip,downshift-after ; + phandle ; + } + } + } + } + } + } + dma@7e007000 { + compatible ; + reg ; + interrupts ; + interrupt-names ; + #dma-cells ; + brcm,dma-channel-mask ; + phandle ; + } + interrupt-controller@7e00b200 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + interrupts ; + phandle ; + } + watchdog@7e100000 { + compatible ; + #power-domain-cells ; + #reset-cells ; + reg ; + clocks ; + clock-names ; + system-power-controller ; + phandle ; + } + rng@7e104000 { + compatible ; + reg ; + interrupts ; + phandle ; + } + pixelvalve@7e206000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + pixelvalve@7e207000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + thermal@7e212000 { + compatible ; + reg ; + clocks ; + #thermal-sensor-cells ; + status ; + phandle ; + } + i2c@7e805000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + vec@7e806000 { + compatible ; + reg ; + clocks ; + interrupts ; + status ; + power-domains ; + phandle ; + } + pixelvalve@7e807000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + hdmi@7e902000 { + compatible ; + reg ; + reg-names ; + interrupts ; + ddc ; + clocks ; + clock-names ; + dmas ; + dma-names ; + status ; + power-domains ; + hpd-gpios ; + phandle ; + } + v3d@7ec00000 { + compatible ; + reg ; + interrupts ; + power-domains ; + status ; + phandle ; + } + gpu { + compatible ; + status ; + raspberrypi,firmware ; + phandle ; + } + local_intc@40000000 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + phandle ; + } + mmcnr@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + dmas ; + dma-names ; + brcm,overclock-50 ; + non-removable ; + status ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + #address-cells ; + #size-cells ; + phandle ; + wifi@1 { + reg ; + compatible ; + phandle ; + } + } + firmwarekms@7e600000 { + compatible ; + reg ; + interrupts ; + brcm,firmware ; + status ; + phandle ; + } + smi@7e600000 { + compatible ; + reg ; + interrupts ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + dmas ; + dma-names ; + status ; + phandle ; + } + csi@7e800000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + phandle ; + } + csi@7e801000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + brcm,num-data-lanes ; + phandle ; + } + axiperf { + compatible ; + reg ; + firmware ; + status ; + phandle ; + } + firmware { + compatible ; + #address-cells ; + #size-cells ; + mboxes ; + dma-ranges ; + phandle ; + clocks { + compatible ; + #clock-cells ; + phandle ; + } + vcio { + compatible ; + phandle ; + } + expgpio { + compatible ; + gpio-controller ; + #gpio-cells ; + gpio-line-names ; + status ; + phandle ; + } + } + power { + compatible ; + firmware ; + #power-domain-cells ; + phandle ; + } + mailbox@7e00b840 { + compatible ; + reg ; + interrupts ; + phandle ; + bcm2835_audio { + compatible ; + brcm,firmware ; + brcm,pwm-channels ; + status ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + } + gpiomem { + compatible ; + reg ; + } + fb { + compatible ; + firmware ; + status ; + phandle ; + } + sound { + status ; + phandle ; + } + } + clocks { + clk-osc { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + clk-usb { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + } + phy { + compatible ; + #phy-cells ; + phandle ; + } + arm-pmu { + compatible ; + interrupt-parent ; + interrupts ; + } + timer { + compatible ; + interrupt-parent ; + interrupts ; + always-on ; + } + cpus { + #address-cells ; + #size-cells ; + enable-method ; + phandle ; + cpu@0 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@1 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@2 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@3 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + l2-cache0 { + compatible ; + cache-size ; + cache-line-size ; + cache-sets ; + cache-level ; + phandle ; + } + } + cam1_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + gpio ; + phandle ; + } + cam1_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam0_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + phandle ; + } + cam0_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam_dummy_reg { + compatible ; + regulator-name ; + status ; + phandle ; + } + __overrides__ { + cam0-pwdn-ctrl ; + cam0-pwdn ; + cam0-led-ctrl ; + cam0-led ; + arm_freq ; + cache_line_size ; + uart0 ; + uart1 ; + i2s ; + spi ; + i2c0 ; + i2c1 ; + i2c0_baudrate ; + i2c1_baudrate ; + audio ; + watchdog ; + random ; + sd_overclock ; + sd_force_pio ; + sd_pio_limit ; + sd_debug ; + sdio_overclock ; + axiperf ; + i2c2_iknowwhatimdoing ; + i2c2_baudrate ; + sd_poll_once ; + krnbt ; + krnbt_baudrate ; + act_led_gpio ; + act_led_activelow ; + act_led_trigger ; + pwr_led_gpio ; + pwr_led_activelow ; + pwr_led_trigger ; + eee ; + tx_lpi_timer ; + eth_led0 ; + eth_led1 ; + eth_downshift_after ; + eth_max_speed ; + } + leds { + compatible ; + phandle ; + led-act { + label ; + default-state ; + linux,default-trigger ; + gpios ; + phandle ; + } + led-pwr { + label ; + linux,default-trigger ; + gpios ; + phandle ; + } + } + fixedregulator_3v3 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + fixedregulator_5v0 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + __symbols__ { + rmem ; + cma ; + cpu_thermal ; + soc ; + txp ; + clocks ; + mailbox ; + gpio ; + dpi_gpio0 ; + emmc_gpio22 ; + emmc_gpio34 ; + emmc_gpio48 ; + gpclk0_gpio4 ; + gpclk1_gpio5 ; + gpclk1_gpio42 ; + gpclk1_gpio44 ; + gpclk2_gpio6 ; + gpclk2_gpio43 ; + i2c0_gpio0 ; + i2c0_gpio28 ; + i2c0_gpio44 ; + i2c1_gpio2 ; + i2c1_gpio44 ; + jtag_gpio22 ; + pcm_gpio18 ; + pcm_gpio28 ; + sdhost_gpio48 ; + spi0_gpio7 ; + spi0_gpio35 ; + spi1_gpio16 ; + spi2_gpio40 ; + uart0_gpio14 ; + uart0_ctsrts_gpio16 ; + uart0_ctsrts_gpio30 ; + uart0_gpio32 ; + uart0_gpio36 ; + uart0_ctsrts_gpio38 ; + uart1_gpio14 ; + uart1_ctsrts_gpio16 ; + uart1_gpio32 ; + uart1_ctsrts_gpio30 ; + uart1_gpio40 ; + uart1_ctsrts_gpio42 ; + i2c_slave_gpio18 ; + jtag_gpio4 ; + pwm0_gpio12 ; + pwm0_gpio18 ; + pwm0_gpio40 ; + pwm1_gpio13 ; + pwm1_gpio19 ; + pwm1_gpio41 ; + pwm1_gpio45 ; + dpi_18bit_cpadhi_gpio0 ; + dpi_18bit_cpadhi_gpio2 ; + dpi_18bit_gpio0 ; + dpi_18bit_gpio2 ; + dpi_16bit_gpio0 ; + dpi_16bit_gpio2 ; + dpi_16bit_cpadhi_gpio0 ; + dpi_16bit_cpadhi_gpio2 ; + gpioout ; + alt0 ; + spi0_pins ; + spi0_cs_pins ; + i2c0_pins ; + i2c1_pins ; + i2s_pins ; + sdio_pins ; + bt_pins ; + uart0_pins ; + uart1_pins ; + audio_pins ; + uart0 ; + bt ; + sdhost ; + i2s ; + spi0 ; + spi ; + spidev0 ; + spidev1 ; + i2c0if ; + i2c0mux ; + i2c0 ; + i2c_csi_dsi ; + dpi ; + dsi0 ; + aux ; + uart1 ; + minibt ; + spi1 ; + spi2 ; + pwm ; + mmc ; + sdhci ; + hvs ; + dsi1 ; + i2c1 ; + usb ; + ethernet ; + eth_phy ; + dma ; + intc ; + watchdog ; + pm ; + random ; + pixelvalve0 ; + pixelvalve1 ; + thermal ; + i2c2 ; + vec ; + pixelvalve2 ; + hdmi ; + v3d ; + vc4 ; + local_intc ; + mmcnr ; + brcmf ; + firmwarekms ; + smi ; + csi0 ; + csi1 ; + axiperf ; + firmware ; + firmware_clocks ; + vcio ; + expgpio ; + power ; + vchiq ; + audio ; + fb ; + sound ; + clk_osc ; + clk_usb ; + usbphy ; + cpus ; + cpu0 ; + cpu1 ; + cpu2 ; + cpu3 ; + l2 ; + cam1_reg ; + cam1_clk ; + cam0_regulator ; + cam0_clk ; + cam0_reg ; + cam_dummy_reg ; + leds ; + act_led ; + pwr_led ; + vdd_3v3_reg ; + vdd_5v0_reg ; + } +} +[simple_malloc.c/init_malloc_state:12] Simple heap start address: 0x8e000 + +[initrdfs.c/initrdfs_init:7] Enter initrdfs_int +[initrdfs.c/initrdfs_init:8] initrd start at 0x8000000 + +[initrdfs.c/initrdfs_init:9] initrd first 4 bytes: 37303730 + +[initrdfs.c/initrdfs_init:23] Start parsing new ascii format's cpio +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 2 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 112, iter->cur: 0x8000070 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: . +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 21 +[cpio.c/cpio_iter_parse:38] f->namesize: 6 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 140, iter->cur: 0x80000fc +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file1 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 34 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 156, iter->cur: 0x8000198 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file2.txt +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 5 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 116, iter->cur: 0x800020c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 5 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 128, iter->cur: 0x800028c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test/1234 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 0 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 11 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 124, iter->cur: 0x8000308 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: TRAILER!!! +[initrdfs.c/initrdfs_init:32] Leave initrdfs_int +text_start=0x80000, text_end=0x84000, text_size=16384 +rodata_start=0x84000, rodata_end=0x86000, rodata_size=8192 +data_start=0x86000, data_end=0x87000, data_size=4096 +bss_start=0x87000, bss_end=0x8e000, bss_size=28672 +heap_start=0x8e000 +⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀ +⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀ +⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁ +⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀ +⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀ +⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀ +⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀ +⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀ +⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀ +⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀ +⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀ +⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀ +⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀ + +# diff --git a/lab5/tools/AUX_PERIPHERALS b/lab5/tools/AUX_PERIPHERALS new file mode 100644 index 000000000..324eb3019 --- /dev/null +++ b/lab5/tools/AUX_PERIPHERALS @@ -0,0 +1,23 @@ +0x7E215000 AUX_IRQ Auxiliary Interrupt status 3 +0x7E215004 AUX_ENABLES Auxiliary enables 3 +0x7E215040 AUX_MU_IO_REG Mini Uart I/O Data 8 +0x7E215044 AUX_MU_IER_REG Mini Uart Interrupt Enable 8 +0x7E215048 AUX_MU_IIR_REG Mini Uart Interrupt Identify 8 +0x7E21504C AUX_MU_LCR_REG Mini Uart Line Control 8 +0x7E215050 AUX_MU_MCR_REG Mini Uart Modem Control 8 +0x7E215054 AUX_MU_LSR_REG Mini Uart Line Status 8 +0x7E215058 AUX_MU_MSR_REG Mini Uart Modem Status 8 +0x7E21505C AUX_MU_SCRATCH Mini Uart Scratch 8 +0x7E215060 AUX_MU_CNTL_REG Mini Uart Extra Control 8 +0x7E215064 AUX_MU_STAT_REG Mini Uart Extra Status 32 +0x7E215068 AUX_MU_BAUD_REG Mini Uart Baudrate 16 +0x7E215080 AUX_SPI0_CNTL0_REG SPI 1 Control register 0 32 +0x7E215084 AUX_SPI0_CNTL1_REG SPI 1 Control register 1 8 +0x7E215088 AUX_SPI0_STAT_REG SPI 1 Status 32 +0x7E215090 AUX_SPI0_IO_REG SPI 1 Data 32 +0x7E215094 AUX_SPI0_PEEK_REG SPI 1 Peek 16 +0x7E2150C0 AUX_SPI1_CNTL0_REG SPI 2 Control register 0 32 +0x7E2150C4 AUX_SPI1_CNTL1_REG SPI 2 Control register 1 8 +0x7E2150C8 AUX_SPI1_STAT_REG SPI 2 Status 32 +0x7E2150D0 AUX_SPI1_IO_REG SPI 2 Data 32 +0x7E2150D4 AUX_SPI1_PEEK_REG SPI 2 Peek 16 diff --git a/lab5/tools/GPIO b/lab5/tools/GPIO new file mode 100644 index 000000000..ad2b10794 --- /dev/null +++ b/lab5/tools/GPIO @@ -0,0 +1,43 @@ +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200004 GPFSEL1 GPIO Function Select 1 32 R/W +0x7E200008 GPFSEL2 GPIO Function Select 2 32 R/W +0x7E20000C GPFSEL3 GPIO Function Select 3 32 R/W +0x7E200010 GPFSEL4 GPIO Function Select 4 32 R/W +0x7E200014 GPFSEL5 GPIO Function Select 5 32 R/W +0x7E200018 - Reserved - - +0x7E20001C GPSET0 GPIO Pin Output Set 0 32 W +0x7E200020 GPSET1 GPIO Pin Output Set 1 32 W +0x7E200024 - Reserved - - +0x7E200028 GPCLR0 GPIO Pin Output Clear 0 32 W +0x7E20002C GPCLR1 GPIO Pin Output Clear 1 32 W +0x7E200030 - Reserved - - +0x7E200034 GPLEV0 GPIO Pin Level 0 32 R +0x7E200038 GPLEV1 GPIO Pin Level 1 32 R +0x7E20003C - Reserved - - +0x7E200040 GPEDS0 GPIO Pin Event Detect Status 0 32 R/W +0x7E200044 GPEDS1 GPIO Pin Event Detect Status 1 32 R/W +0x7E200048 - Reserved - - +0x7E20004C GPREN0 GPIO Pin Rising Edge Detect Enable 0 32 R/W +0x7E200050 GPREN1 GPIO Pin Rising Edge Detect Enable 1 32 R/W +0x7E200054 - Reserved - - +0x7E200058 GPFEN0 GPIO Pin Falling Edge Detect Enable 0 32 R/W +0x7E20005C GPFEN1 GPIO Pin Falling Edge Detect Enable 1 32 R/W +0x7E200060 - Reserved - - +0x7E200064 GPHEN0 GPIO Pin High Detect Enable 0 32 R/W +0x7E200068 GPHEN1 GPIO Pin High Detect Enable 1 32 R/W +0x7E20006C - Reserved - - +0x7E200070 GPLEN0 GPIO Pin Low Detect Enable 0 32 R/W +0x7E200074 GPLEN1 GPIO Pin Low Detect Enable 1 32 R/W +0x7E200078 - Reserved - - +0x7E20007C GPAREN0 GPIO Pin Async. Rising Edge Detect 0 32 R/W +0x7E200080 GPAREN1 GPIO Pin Async. Rising Edge Detect 1 32 R/W +0x7E200084 - Reserved - - +0x7E200088 GPAFEN0 GPIO Pin Async. Falling Edge Detect 0 32 R/W +0x7E20008C GPAFEN1 GPIO Pin Async. Falling Edge Detect 1 32 R/W +0x7E200090 - Reserved - - +0x7E200094 GPPUD GPIO Pin Pull-up/down Enable 32 R/W +0x7E200098 GPPUDCLK0 GPIO Pin Pull-up/down Enable Clock 0 32 R/W +0x7E20009C GPPUDCLK1 GPIO Pin Pull-up/down Enable Clock 1 32 R/W +0x7E2000A0 - Reserved - - +0x7E2000B0 - Test 4 R/W diff --git a/lab5/tools/cpio/.gdb_history b/lab5/tools/cpio/.gdb_history new file mode 100644 index 000000000..ff604669b --- /dev/null +++ b/lab5/tools/cpio/.gdb_history @@ -0,0 +1 @@ +quit diff --git a/lab5/tools/cpio/Makefile b/lab5/tools/cpio/Makefile new file mode 100644 index 000000000..1cbe92c74 --- /dev/null +++ b/lab5/tools/cpio/Makefile @@ -0,0 +1,35 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +override CFLAGS += \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin \ + +LDFLAGS ?= \ + -nostdlib \ + +CXXFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJDUMP = aarch64-linux-gnu-objdump +QEMU = qemu-system-aarch64 +RASPI_VER = raspi3b + + +LINKER_FILE = ./linker.ld +HEADERS = $(PWD)/include/ +OUTPUT = $(PWD)/build +KNAME = kernel8 +BNAME = bootloader + +.PHONY: all + + +all: + $(CC) -c -o test.o test.S $(CFLAGS) + $(LD) -T linker.ld -o test.elf test.o $(LDFLAGS) + $(OBJCOPY) -O binary test.elf test.img + diff --git a/lab5/tools/cpio/create_initramfs.sh b/lab5/tools/cpio/create_initramfs.sh new file mode 100755 index 000000000..2736e47fe --- /dev/null +++ b/lab5/tools/cpio/create_initramfs.sh @@ -0,0 +1,4 @@ +#! /bin/sh +cd rootfs +find . | cpio -o -H newc > ../initramfs.cpio +cd .. diff --git a/lab5/tools/cpio/initramfs.cpio b/lab5/tools/cpio/initramfs.cpio new file mode 100644 index 000000000..d2c1db2c9 Binary files /dev/null and b/lab5/tools/cpio/initramfs.cpio differ diff --git a/lab5/tools/cpio/linker.ld b/lab5/tools/cpio/linker.ld new file mode 100644 index 000000000..a550bf32e --- /dev/null +++ b/lab5/tools/cpio/linker.ld @@ -0,0 +1,41 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + +} diff --git a/lab5/tools/cpio/rootfs/file1 b/lab5/tools/cpio/rootfs/file1 new file mode 100644 index 000000000..b7b514317 --- /dev/null +++ b/lab5/tools/cpio/rootfs/file1 @@ -0,0 +1 @@ +This is your flag!!! diff --git a/lab5/tools/cpio/rootfs/file2.txt b/lab5/tools/cpio/rootfs/file2.txt new file mode 100644 index 000000000..367edaf2d --- /dev/null +++ b/lab5/tools/cpio/rootfs/file2.txt @@ -0,0 +1 @@ +FLAG{...........................} diff --git a/lab5/tools/cpio/rootfs/syscall.img b/lab5/tools/cpio/rootfs/syscall.img new file mode 100755 index 000000000..3be46e1bf Binary files /dev/null and b/lab5/tools/cpio/rootfs/syscall.img differ diff --git a/lab5/tools/cpio/rootfs/test/1234 b/lab5/tools/cpio/rootfs/test/1234 new file mode 100644 index 000000000..81c545efe --- /dev/null +++ b/lab5/tools/cpio/rootfs/test/1234 @@ -0,0 +1 @@ +1234 diff --git a/lab5/tools/gen.sh b/lab5/tools/gen.sh new file mode 100755 index 000000000..235b38c28 --- /dev/null +++ b/lab5/tools/gen.sh @@ -0,0 +1,24 @@ +#! /bin/sh +BUS_IO_BASE=0x7E000000 +PHY_IO_BASE=0x3F000000 +echo "/* Register's offset of GPIO */" +grep -v " - " GPIO | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + +echo "" +echo "" +echo "/* Register's offset of UART and SPI */" +grep -v " - " AUX_PERIPHERALS | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + + diff --git a/lab5/uart_upload.py b/lab5/uart_upload.py new file mode 100755 index 000000000..9a2a52d80 --- /dev/null +++ b/lab5/uart_upload.py @@ -0,0 +1,69 @@ +#! /usr/bin/python3 + +import sys +import struct +import serial +import os +import time +if len(sys.argv) < 4: + print(sys.argv[0], "", "", "") + sys.exit(-1) + +tty_name = sys.argv[1] +kernel_name = sys.argv[2] +base_addr = int(sys.argv[3], 16) + +ser = None + +def readline(): + os.write(1,b'[From bootloader]: ') + while 1: + c = ser.read(1) + if c == b'\n': + os.write(1, b'\n') + return + elif c != b'\r': + os.write(1, c) + + + +with open(kernel_name, "rb",) as kernel: + kernel_buf = kernel.read() + kernel_size = len(kernel_buf) + + + while(1): + ser = serial.Serial( + # Serial Port to read the data from + port = tty_name, + #Rate at which the information is shared to the communication channel + baudrate = 115200, + timeout = .1 + ) + + # start upload kernel to rasberry pi 3b+ by uart interface + # start header + ser.write(b"A") + ser.flush() + readline() + + # transfer kernel base address and kernel size ( both are 8 bytes ) in little endian + ser.write(struct.pack("member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) (((uint64_t)(val) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_DOWN(val, align) ((uint64_t)(val) & ~((align) - 1)) + +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define min(x, y) ((x) < (y) ? (x) : (y)) + +#endif diff --git a/lab5/user/user_lib.c b/lab5/user/user_lib.c new file mode 100644 index 000000000..d7d14da24 --- /dev/null +++ b/lab5/user/user_lib.c @@ -0,0 +1,323 @@ +#include "user_lib.h" + +char int_table[] = "0123456789"; +char hex_table[] = "0123456789abcdef"; + +uint64_t getpid(void){ + asm volatile("mov x8, 0\n\t" + "svc 0\n\t" + : + : + ); +} + +size_t uart_read(char *buf, size_t size){ + asm volatile("mov x0, %[buf]\n\t" + "mov x1, %[size]\n\t" + "mov x8, 1\n\t" + "svc 0\n\t" + : + :[buf] "r" (buf), [size] "r" (size) + ); +} + +size_t uart_write(char *buf, size_t size){ + asm volatile("mov x0, %[buf]\n\t" + "mov x1, %[size]\n\t" + "mov x8, 2\n\t" + "svc 0\n\t" + : + :[buf] "r" (buf), [size] "r" (size) + ); +} + +uint64_t fork(void){ + asm volatile("mov x8, 4\n\t" + "svc 0\n\t" + : + : + ); +} + +void debug_info(void){ + asm volatile("mov x8, 5\n\t" + "svc 0\n\t" + : + : + ); +} + +void signal(uint64_t pid, sig_handler handler){ + asm volatile("mov x0, %[pid]\n\t" + "mov x1, %[handler]\n\t" + "mov x8, 8\n\t" + "svc 0\n\t" + : + :[pid] "r" (pid), [handler] "r" (handler) + ); +} + +void kill(uint64_t pid, int signal){ + asm volatile("mov x0, %[pid]\n\t" + "mov x1, %[signal]\n\t" + "mov x8, 9\n\t" + "svc 0\n\t" + : + :[pid] "r" (pid), [signal] "r" (signal) + ); +} + +void delay(uint64_t clock){ + for(uint64_t i = 0 ; i < clock ; i++) asm volatile("nop"); +} + +size_t strlen(const char* s){ + size_t i = 0; + while(s[i++]); + i--; + return i; +} + + +char * itoa(int32_t value, char* str, uint32_t base){ + char buf[32]; + uint32_t val; + volatile int i = 0, j = 0; + + switch(base){ + case 16: + val = (uint32_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} + +char * utoa(uint32_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint32_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} +char * ltoa(int64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val; + + switch(base){ + case 16: + val = (uint64_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +char * ultoa(uint64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} + +uint64_t atoul(const char* str){ + uint64_t val = 0; + const char* ps = str; + while(*ps){ + val *= 10; + val += (*ps - '0'); + ps++; + } + return val; +} + +int32_t printf(char *fmt, ...){ + uint32_t uval; + int32_t val; + int64_t lval; + char str[64], ch; + char* s; + void* addr; + size_t tmp_c; + volatile int32_t count = 0; + va_list ap; + + va_start(ap, fmt); + + while(*fmt){ + char c = *fmt++; + if(c == '%'){ + c = *fmt++; + switch(c){ + case 'u': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 10); + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + break; + case 'd': + val = va_arg(ap, int); + itoa(val, str, 10); + uart_write(str, strlen(str)); + break; + case 'l': + lval = va_arg(ap, int64_t); + ltoa(lval, str, 10); + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + break; + case 'c': + ch = va_arg(ap, int); + uart_write(&ch, 1); + count++; + break; + case 'p': + addr = va_arg(ap, void*); + utoa((uint64_t)addr, str, 16); + + uart_write("0x", 2); + count += 2; + + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + + break; + + break; + case 'x': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 16); + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + + break; + case 's': + s = va_arg(ap, char*); + tmp_c = strlen(s); + uart_write(s, tmp_c); + count += tmp_c; + break; + case '%': + uart_write("%", 1); + count++; + default: + uart_write("%", 1); + uart_write(&c, 1); + count += 2; + } + }else{ + uart_write(&c, 1); + count++; + } + } + va_end(ap); + return count; +} + diff --git a/lab5/user/user_lib.h b/lab5/user/user_lib.h new file mode 100644 index 000000000..782e21ae8 --- /dev/null +++ b/lab5/user/user_lib.h @@ -0,0 +1,18 @@ +#ifndef _USER_LIB_H_ +#define _USER_LIB_H_ +#include "types.h" +#include + +typedef void (*sig_handler)(); + +extern size_t uart_write(char *, size_t); +extern size_t uart_read(char *, size_t); +extern uint64_t fork(void); +extern uint64_t getpid(void); +extern void debug_info(void); +extern void delay(uint64_t); +extern int32_t printf(char *, ...); +extern void signal(uint64_t, sig_handler); +extern void kill(uint64_t, int); + +#endif diff --git a/lab5/user/user_lib.o b/lab5/user/user_lib.o new file mode 100644 index 000000000..06924793e Binary files /dev/null and b/lab5/user/user_lib.o differ diff --git a/lab6/.gdb_history b/lab6/.gdb_history new file mode 100644 index 000000000..0cba255db --- /dev/null +++ b/lab6/.gdb_history @@ -0,0 +1,256 @@ +x/gx bb000 +x/gx 0xbb000 +quit +file ./build/kernel8.elf +target remote:1234 +c +x/gx 0xffff000008215000 +x/gx 0x821c000 +x/gx 0x821d000 +x/gx 0x8216000 +file ./build/kernel8.elf +file ./build/kernel8.elf +b* MBox_process +c +target remot:1234 +c +ni +si +ni +ni +b* MBox_write +c +ni +ni +ni +ni +x/i 0xffff00000008238c +b* 0xffff000000082440 +c +ls +c +c +target remot:1234 +info b +del 1 +del 2 +c +ni +quit +target remote;1234 +target remote:1234 +file ./build/kernel8.elf +c +b task_load_all +c +c +ni +target remote:1234 +target remote:1234 +c +info reg +p $TTBR0_EL1 +p/x $TTBR0_EL1 +ni +ni +ni +ni +c +ni +p $TTBR0_EL1 +p/x $TTBR0_EL1 +p 0xffff00000006b000 +x/gx 0xffff00000006b000 +x/gx 0xffff00003be82000 +x/gx 0xffff00003be83000 +x/gx 0xffff00003be84000 +x/gx 0xffff00003be84000 +quit +file ./build/kernel8.elf +b task_load_all +c +target remot:1234 +c +p/x $TTBR0_EL! +p/x $TTBR0_EL1 +x/gx 0x8215000 +x/gx 0xffff00008215000 +x/gx 0xffff000008215000 +x/gx 0xffff000000001000 +x/gx 0xffff000008218000 +x/gx 0xffff000008219000 +x/gx 0xffff00000803d000 +x/i 0xffff00000803d000 +c +x/gx 0xffff00000006b000 +x/gx 0xffff00003be82003 +x/gx 0xffff00003be82000 +x/gx 0xffff00003be83000 +x/gx 0xffff00003be84000 +c +b dup_vma_stack +c +x/gx 0xffff00003be8e000 +x/gx 0xffff00003be8e000 +x/gx 0xffff00003bdc3000 +x/gx 0xffff00003bdc4000 +x/gx 0xffff00003bdc5000 +quit +file ./build/kernel8.elf +target remote;1234 +target remote:1234 +c +b dup_vma_stack +c +x/gx 0xffff000000 +x/gx 0xffff00003be82000 +b dup_mm_struct +c +target remot:1234 +c +ni +x/i +ni +b * dup_pages +c +ni +ni +bu +ni +x/gx 0xffff00000006b000, +x/gx 0xffff00000006b000 +ni +ni +x/gx 0xffff00000006b000 +watch 0xffff00000006b000 +watch *0xffff00000006b000 +c +watch *0xffff00000006b000 +x/gx 0xffff00000006b000 +x/gx 0xffff00000006b000 +x/gx 0xffff00000006b000 +n +i +ni +ni +ni +ni +file ./build/kernel8.elf +file ./build/kernel8.elf +target remote:1234 +info b +del 1 + del 2 +del 3 +del 4 +del 5 +b task_load_all +c +c +file ./build/kernel8.elf +file ./build/kernel8.elf +target remote:1234 +c +info b +del 6 +b task_load_all +c +c +x/gx 0xffff000008215000 +x/gx 0xffff000000001000 +x/gx 0xffff000000e2a000 +x/gx 0xffff000000e2b000 +x/gx 0xffff00000803d000 +x/i 0xffff00000803d000 +p/x $TTBR0_EL1 +x/gx 0xffff00000006b000 +x/gx 0xffff00000006e000 +x/gx 0xffff00000006f000 +x/gx 0xffff000000100000 +x/gx 0xffff000000010000 +ni +ni +ni +ni +quit +quit +file ./build/kernel8.elf +b Mbox_call +c +target remote:1234 +c +x/gx 0x17de0 +ni +x/gx 0xffff000000017000 +x/gx 0xffff000000017de0 +ni +c +c +quit +file ./build/kernel8.elf +target remote:1234 +c +b sys_mbox_call +c +x/gx 0xffffffffede0 +x/dx 0xffffffffede0 +x/wx 0xffffffffede0 +x/gx 0xffffffffede0 +x/dx 0xffffffffede0 +x/wx 0xffffffffede0 +x/wx 0xffffffffede0 +ni +ni +x/i +x/i 0xffff000000081a1c +x/i 0xffff000000082b5c +b* 0xffff000000082e8c +c +x/wx 0xffffffffede0 +quit +file ./build/kernel8.elf +target remote:1234 +c +c +ni +c +ni +c +ni +quit +target remote:1234 +ls +file ./build/kernel8.elf +target remote:1234 +target remote:1234 +c +b task_exec +target remote:1q234 +target remote:1234 +c +x/i 0xffff00000008a1dc +b* 0xffff00000008a3a4 +c +ni +ni +ni +c +c +c +c +c +file build/kernel8.elf +file build/kernel8.elf +target remote:1234 +c +c +c +c +x/gx 0x65000 +x/gx 0x65000 +x/gx 0xffff000000065000 +x/i 0xffff000000065000 +x/gx 0xffff000000065000 +x/bx 0xffff000000065000 +x/i 0xffff00000006596c +quit diff --git a/lab6/Makefile b/lab6/Makefile new file mode 100644 index 000000000..1a83efde9 --- /dev/null +++ b/lab6/Makefile @@ -0,0 +1,104 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +override CFLAGS += \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin \ + +LDFLAGS ?= \ + -nostdlib \ + +CXXFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJDUMP = aarch64-linux-gnu-objdump +QEMU = qemu-system-aarch64 +RASPI_VER = raspi3b + + +LINKER_FILE = ./linker.ld +HEADERS = $(PWD)/include/ +OUTPUT = $(PWD)/build +KNAME = kernel8 +BNAME = bootloader + +LIBS = \ + $(OUTPUT)/print.o \ + $(OUTPUT)/string.o \ + $(OUTPUT)/list.o \ + $(OUTPUT)/cpio.o \ + $(OUTPUT)/simple_malloc.o \ + $(OUTPUT)/fdt_parse.o \ + $(OUTPUT)/ring_buffer.o \ + $(OUTPUT)/asm.o \ + $(OUTPUT)/bitops.o + +KOBJECTS = \ + $(OUTPUT)/start.o \ + $(OUTPUT)/entry.o \ + $(OUTPUT)/syscall_test.o \ + $(OUTPUT)/syscall_table.o \ + $(OUTPUT)/mini_uart.o \ + $(OUTPUT)/mailbox.o \ + $(OUTPUT)/main.o \ + $(OUTPUT)/kernel_init.o \ + $(OUTPUT)/reboot.o \ + $(OUTPUT)/shell.o \ + $(OUTPUT)/debug.o \ + $(OUTPUT)/initrdfs.o \ + $(OUTPUT)/timer.o \ + $(OUTPUT)/irq_handler.o \ + $(OUTPUT)/page_alloc.o \ + $(OUTPUT)/mm.o \ + $(OUTPUT)/mmu.o \ + $(OUTPUT)/slab.o \ + $(OUTPUT)/sched.o \ + $(OUTPUT)/kthread.o \ + $(OUTPUT)/task.o \ + $(OUTPUT)/signal.o \ + $(OUTPUT)/fault.o \ + $(LIBS) + + +.PHONY: all start kernel end clean dump + + +all: start link kernel end + +start: + @echo "Start building kernel8.img" + + $(MAKE) -C peripherals OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C init OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C kernel OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C lib OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C debug OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C fs OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C mm OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + +link: $(OBJECTS) + $(LD) -T kernel/$(LINKER_FILE) -o $(OUTPUT)/$(KNAME).elf $(KOBJECTS) $(LDFLAGS) + +kernel: $(OUTPUT)/$(KNAME).elf + $(OBJCOPY) -O binary $(OUTPUT)/$(KNAME).elf $(OUTPUT)/$(KNAME).img + +end: + @echo "Finish building kernel8.img" + +dump: + $(OBJDUMP) -m aarch64 -b binary -D $(OUTPUT)/$(KNAME).img + +qemu-run: + sudo $(QEMU) -M $(RASPI_VER) -kernel $(OUTPUT)/$(KNAME).img -display none -serial null -serial stdio -initrd ./initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + +qemu-run-gui: + sudo $(QEMU) -M $(RASPI_VER) -kernel $(OUTPUT)/$(KNAME).img -serial null -serial stdio -initrd ./initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + +qemu-run-instr: + sudo $(QEMU) -M $(RASPI_VER) -kernel $(OUTPUT)/$(KNAME).img -display none -d in_asm + +clean: + rm $(OUTPUT)/* diff --git a/lab6/README.md b/lab6/README.md new file mode 100644 index 000000000..788565858 --- /dev/null +++ b/lab6/README.md @@ -0,0 +1,18 @@ +# Requirements + +## Features + +- Basic Exercise 1 + - [x] Virtual Memory in Kernel Space +- Basic Exercise 2 + - [x] Virtual Memory in User Space +- Advanced Exercise 1 + - [x] Mmap +- Advanced Exercise 2 + - [x] Page Fault Handler & Demand Paging +- Advanced Exercise 1 + - [x] Copy on Write + + + + diff --git a/lab6/bcm2710-rpi-3-b-plus.dtb b/lab6/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 000000000..6f9ef31cc Binary files /dev/null and b/lab6/bcm2710-rpi-3-b-plus.dtb differ diff --git a/lab6/boot/Makefile b/lab6/boot/Makefile new file mode 100644 index 000000000..b98c365cd --- /dev/null +++ b/lab6/boot/Makefile @@ -0,0 +1,28 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + boot.o \ + uart_boot.o + +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab6/boot/boot.S b/lab6/boot/boot.S new file mode 100644 index 000000000..b28524a42 --- /dev/null +++ b/lab6/boot/boot.S @@ -0,0 +1,84 @@ +.section ".text.boot" +.global _start +_start: +// x1 = current PC + offset to _dtb + adr x1, _dtb + str x0, [x1] + +// stack + adr x1, _start + mov sp, x1 + +// rebase boot loader to specific address +// indicated by linker script + bl rebase_bootloader + +// slave cpu should not sleep before bootloader finishes rebase +// Since if they wake up, there next instruction will be invalid instruction +rebase_entry: + // read cpu id, stop slave cores + // cpu id == 0 + // store pointer to dtb to _dtb + mrs x1, mpidr_el1 + and x1, x1, #0xff + + // cpu id > 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + + +master_core: +// stack + ldr x1, =_start + mov sp, x1 + +// recover dtb to x0 + adr x1, _dtb + ldr x0, [x1] + + +// jump to kernel_main + bl uart_recv_kernel + + b proc_hang + +// rebase our boot loader +rebase_bootloader: + // manipulate our return address ( x30 a.k.a LR ) to the rebased bootloader + // x19 = current PC + offset to _start + // x20 = absolute address ( _start ) that specify by linker script + adr x19, _start + ldr x20, =_start + sub x19, x19, x20 + sub lr , lr, x19 + + // x21 = absolute address ( __bootloader_start ) that specify by linker script + // x22 = current PC + offset to __bootloader_start ( In linker script ) + ldr x21, =__bootloader_start + adr x22, __bootloader_start + ldr x23, =__bootloader_size + // start rebasing bootloader +copy_bootloader: + cbz x23, end_rebase_bootloader + ldr x24, [x22], #8 + str x24, [x21], #8 + sub x23, x23, #8 + b copy_bootloader + +// Since ldr and str memory operation should obey 8 bytes alignment rule, the code here would failed on real device +// cbz x23, end_rebase_bootloader +// ldr x24, [x22], #1 +// str x24, [x21], #1 +// sub x23, x23, #1 +// b copy_bootloader + + + // return to rebased bootloader +end_rebase_bootloader: + ret + +.section ".data" +_dtb: .dword 0 diff --git a/lab6/boot/linker.ld b/lab6/boot/linker.ld new file mode 100644 index 000000000..740945ab2 --- /dev/null +++ b/lab6/boot/linker.ld @@ -0,0 +1,43 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x60000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __bootloader_start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + __bootloader_end = .; + __bootloader_size = (__bootloader_end - __bootloader_start); +} diff --git a/lab6/boot/uart_boot.c b/lab6/boot/uart_boot.c new file mode 100644 index 000000000..faec51411 --- /dev/null +++ b/lab6/boot/uart_boot.c @@ -0,0 +1,47 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "lib/print.h" + +void recv_boot_header(){ + while('A' != mini_uart_read()); +} + +size_t recv_kernel_base(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +size_t recv_kernel_size(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +void recv_kernel(uint64_t base, size_t size){ + uint8_t *pb; + size_t i; + for(pb = (uint8_t*)base , i = 0 ; i < size ; i++){ + pb[i] = mini_uart_read(); + } +} +uint64_t uart_recv_kernel(uint64_t dtb){ + size_t size; + uint64_t base; + mini_uart_init(); + + recv_boot_header(); +// printf("Receive A...\r\n"); + + base = recv_kernel_base(); +// printf("Receive kernel base 0x%x...\r\n", base); + + size = recv_kernel_size(); +// printf("Receive kernel size 0x%x...\r\n", size); + + recv_kernel(base, size); +// printf("Jump to kernel iamge...\r\n"); + + delay_cycles(10000); + ((void (*)(uint64_t))base)(dtb); +} diff --git a/lab6/build/asm.o b/lab6/build/asm.o new file mode 100644 index 000000000..a854464e8 Binary files /dev/null and b/lab6/build/asm.o differ diff --git a/lab6/build/bitops.o b/lab6/build/bitops.o new file mode 100644 index 000000000..f6889106e Binary files /dev/null and b/lab6/build/bitops.o differ diff --git a/lab6/build/cpio.o b/lab6/build/cpio.o new file mode 100644 index 000000000..d84f1e0af Binary files /dev/null and b/lab6/build/cpio.o differ diff --git a/lab6/build/debug.o b/lab6/build/debug.o new file mode 100644 index 000000000..7beb42607 Binary files /dev/null and b/lab6/build/debug.o differ diff --git a/lab6/build/entry.o b/lab6/build/entry.o new file mode 100644 index 000000000..3f6006ac2 Binary files /dev/null and b/lab6/build/entry.o differ diff --git a/lab6/build/fault.o b/lab6/build/fault.o new file mode 100644 index 000000000..8dc66c972 Binary files /dev/null and b/lab6/build/fault.o differ diff --git a/lab6/build/fdt_parse.o b/lab6/build/fdt_parse.o new file mode 100644 index 000000000..512b452a1 Binary files /dev/null and b/lab6/build/fdt_parse.o differ diff --git a/lab6/build/initrdfs.o b/lab6/build/initrdfs.o new file mode 100644 index 000000000..ce3c47f1a Binary files /dev/null and b/lab6/build/initrdfs.o differ diff --git a/lab6/build/irq_handler.o b/lab6/build/irq_handler.o new file mode 100644 index 000000000..579bf8401 Binary files /dev/null and b/lab6/build/irq_handler.o differ diff --git a/lab6/build/kernel8.elf b/lab6/build/kernel8.elf new file mode 100755 index 000000000..bd01fa566 Binary files /dev/null and b/lab6/build/kernel8.elf differ diff --git a/lab6/build/kernel8.img b/lab6/build/kernel8.img new file mode 100755 index 000000000..5a4f5908e Binary files /dev/null and b/lab6/build/kernel8.img differ diff --git a/lab6/build/kernel_init.o b/lab6/build/kernel_init.o new file mode 100644 index 000000000..5be64f66e Binary files /dev/null and b/lab6/build/kernel_init.o differ diff --git a/lab6/build/kthread.o b/lab6/build/kthread.o new file mode 100644 index 000000000..12111abca Binary files /dev/null and b/lab6/build/kthread.o differ diff --git a/lab6/build/list.o b/lab6/build/list.o new file mode 100644 index 000000000..4380f49c8 Binary files /dev/null and b/lab6/build/list.o differ diff --git a/lab6/build/mailbox.o b/lab6/build/mailbox.o new file mode 100644 index 000000000..f63cd9705 Binary files /dev/null and b/lab6/build/mailbox.o differ diff --git a/lab6/build/main.o b/lab6/build/main.o new file mode 100644 index 000000000..7a06fed84 Binary files /dev/null and b/lab6/build/main.o differ diff --git a/lab6/build/mini_uart.o b/lab6/build/mini_uart.o new file mode 100644 index 000000000..f310fb6e4 Binary files /dev/null and b/lab6/build/mini_uart.o differ diff --git a/lab6/build/mm.o b/lab6/build/mm.o new file mode 100644 index 000000000..24d5c8853 Binary files /dev/null and b/lab6/build/mm.o differ diff --git a/lab6/build/mmu.o b/lab6/build/mmu.o new file mode 100644 index 000000000..744cbcbcf Binary files /dev/null and b/lab6/build/mmu.o differ diff --git a/lab6/build/page_alloc.o b/lab6/build/page_alloc.o new file mode 100644 index 000000000..357da1a15 Binary files /dev/null and b/lab6/build/page_alloc.o differ diff --git a/lab6/build/print.o b/lab6/build/print.o new file mode 100644 index 000000000..95d4f9c85 Binary files /dev/null and b/lab6/build/print.o differ diff --git a/lab6/build/reboot.o b/lab6/build/reboot.o new file mode 100644 index 000000000..e176e8d8e Binary files /dev/null and b/lab6/build/reboot.o differ diff --git a/lab6/build/ring_buffer.o b/lab6/build/ring_buffer.o new file mode 100644 index 000000000..9ae58b65e Binary files /dev/null and b/lab6/build/ring_buffer.o differ diff --git a/lab6/build/sched.o b/lab6/build/sched.o new file mode 100644 index 000000000..1500096e9 Binary files /dev/null and b/lab6/build/sched.o differ diff --git a/lab6/build/shell.o b/lab6/build/shell.o new file mode 100644 index 000000000..bf4244397 Binary files /dev/null and b/lab6/build/shell.o differ diff --git a/lab6/build/signal.o b/lab6/build/signal.o new file mode 100644 index 000000000..2f303aae0 Binary files /dev/null and b/lab6/build/signal.o differ diff --git a/lab6/build/simple_malloc.o b/lab6/build/simple_malloc.o new file mode 100644 index 000000000..30561a330 Binary files /dev/null and b/lab6/build/simple_malloc.o differ diff --git a/lab6/build/slab.o b/lab6/build/slab.o new file mode 100644 index 000000000..5f6a5bd00 Binary files /dev/null and b/lab6/build/slab.o differ diff --git a/lab6/build/start.o b/lab6/build/start.o new file mode 100644 index 000000000..d52bd549c Binary files /dev/null and b/lab6/build/start.o differ diff --git a/lab6/build/string.o b/lab6/build/string.o new file mode 100644 index 000000000..59c6f1bcd Binary files /dev/null and b/lab6/build/string.o differ diff --git a/lab6/build/syscall_table.o b/lab6/build/syscall_table.o new file mode 100644 index 000000000..c866237fc Binary files /dev/null and b/lab6/build/syscall_table.o differ diff --git a/lab6/build/syscall_test.o b/lab6/build/syscall_test.o new file mode 100644 index 000000000..d5ff32a03 Binary files /dev/null and b/lab6/build/syscall_test.o differ diff --git a/lab6/build/task.o b/lab6/build/task.o new file mode 100644 index 000000000..17712e3c7 Binary files /dev/null and b/lab6/build/task.o differ diff --git a/lab6/build/timer.o b/lab6/build/timer.o new file mode 100644 index 000000000..a219a3a7f Binary files /dev/null and b/lab6/build/timer.o differ diff --git a/lab6/debug.sh b/lab6/debug.sh new file mode 100755 index 000000000..81d573d80 --- /dev/null +++ b/lab6/debug.sh @@ -0,0 +1,3 @@ +#!/bin/sh +make CFLAGS=-DDEBUG >/dev/null +make qemu-run diff --git a/lab6/debug/Makefile b/lab6/debug/Makefile new file mode 100644 index 000000000..22ac23500 --- /dev/null +++ b/lab6/debug/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + debug.o + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab6/debug/debug.c b/lab6/debug/debug.c new file mode 100644 index 000000000..057db34ab --- /dev/null +++ b/lab6/debug/debug.c @@ -0,0 +1,58 @@ +#include "debug/debug.h" + +extern int __bss_start, __bss_end; +extern int __text_start, __text_end; +extern int __rodata_start, __rodata_end; +extern int __data_start, __data_end; +extern int __heap_start; +extern int __reserved_page_table_start, __reserved_page_table_end; + +#ifdef DEBUG +int debug = 1; +#else +int debug = 0; +#endif + +void log_kernel_start(){ + uint64_t currentEL; + if(debug == 0) return; + printf("text_start=%p, text_end=%p, text_size=%u\r\n", \ + &__text_start, \ + &__text_end, \ + (uint64_t)&__text_end - (uint64_t)&__text_start + ); + + + printf("rodata_start=%p, rodata_end=%p, rodata_size=%u\r\n", \ + &__rodata_start, \ + &__rodata_end, \ + (uint64_t)&__rodata_end - (uint64_t)&__rodata_start + ); + + printf("data_start=%p, data_end=%p, data_size=%u\r\n", \ + &__data_start, \ + &__data_end, \ + (uint64_t)&__data_end - (uint64_t)&__data_start + ); + + printf("bss_start=%p, bss_end=%p, bss_size=%u\r\n", \ + &__bss_start, \ + &__bss_end, \ + (uint64_t)&__bss_end - (uint64_t)&__bss_start + ); + + printf("__reserved_page_table_start=%p, __reserved_page_table_end=%p,size=%l\r\n", \ + &__reserved_page_table_start, \ + &__reserved_page_table_end, \ + (uint64_t)&__reserved_page_table_end - (uint64_t)&__reserved_page_table_start + ); + + printf("heap_start=%p\r\n", &__heap_start); + + printf("current exception level: %u\r\n", get_currentEL()); + printf("SP_EL0: 0x%x\r\n", get_SP_ELx(0)); + printf("DAIF: 0x%x\r\n", get_DAIF()); + printf("SPSel: 0x%x\r\n", get_SPSel()); + printf("stack pointer: %p\r\n", ¤tEL); + +} diff --git a/lab6/fs/Makefile b/lab6/fs/Makefile new file mode 100644 index 000000000..54bae8cb4 --- /dev/null +++ b/lab6/fs/Makefile @@ -0,0 +1,25 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + initrdfs.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab6/fs/initrdfs.c b/lab6/fs/initrdfs.c new file mode 100644 index 000000000..4f2f4d136 --- /dev/null +++ b/lab6/fs/initrdfs.c @@ -0,0 +1,107 @@ +#include "fs/initrdfs.h" + +static struct fentry * root; + +void initrdfs_init(void* addr){ + INFO("Initrd filesystem start address: %p", addr); + LOG("Enter initrdfs_int"); + LOG("initrd start at %p\n", addr); + LOG("initrd first 4 bytes: %x\n", *(uint32_t*)addr); + root = (struct fentry*)kmalloc(sizeof(struct fentry)); + struct cpio_iter iter; + char *fname = (char*)kmalloc(2); + strcpy(fname, "/"); + + memset(root, 0, sizeof(struct fentry)); + root->filename = fname; + root->namesize = 1; + root->mode = root->mode & FILE_TYPE_DIR; + + INIT_LIST_HEAD(&root->list); + + // Start parsing initrd in New ASCII Format at addr + LOG("Start parsing new ascii format's cpio"); + cpio_iter_init(&iter, addr); + do{ + struct fentry *f = (struct fentry*)kmalloc(sizeof(struct fentry)); + cpio_iter_parse(&iter, f); + LOG("FILE: %s", f->filename); + if(cpio_is_tailer(f)) break; + list_add(&f->list, &root->list); + }while(1); + LOG("Leave initrdfs_int"); +} +void* fdt_initrdfs_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(prop != NULL){ + if(strcmp(prop->name, "linux,initrd-start") == 0){ + uint64_t initrd_start = bswap32(*(uint32_t*)prop->value) + UPPER_ADDR_SPACE_BASE; + LOG("linux,initrd-start: %x", (uint32_t)initrd_start); + initrdfs_init((void*)initrd_start); + } + } +} + +void initrdfs_ls(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + printf("%s\r\n", f->filename); + } +} +void initrdfs_cat(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + printf("Filename : %s\r\n", f->filename); + printf("File size: %u\r\n", f->filesize); + write_bytes(f->data, f->filesize); + printf("\r\n"); + } + } +} + +size_t initrdfs_loadfile(char* name, uint8_t* addr, uint64_t offset, uint64_t size){ + struct list_head* head = &root->list; + struct list_head* node; + + LOG("initrdfs_loadfile(%s, %p, %lu, %lu)", name, addr, offset, size); + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + if(strcmp(name, f->filename) == 0){ + if(offset <= f->filesize){ + if(offset + size > f->filesize){ + size = f->filesize - offset; + } + LOG("Load %lu bytes %s at offset %lu to %p",size , name, offset, addr); + memcpy(addr, &f->data[offset], size); + return size; + }else{ + LOG("error occur"); + } + break; + } + } + } + return 0; +} + +size_t initrdfs_filesize(char* name){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + if(strcmp(name, f->filename) == 0){ + return f->filesize; + } + } + } + return 0; +} diff --git a/lab6/include/asm.h b/lab6/include/asm.h new file mode 100644 index 000000000..633fd18fa --- /dev/null +++ b/lab6/include/asm.h @@ -0,0 +1,24 @@ +#ifndef _ASM_H_ +#define _ASM_H_ +extern uint32_t get_currentEL(); +extern uint64_t get_SP_ELx(uint32_t); +extern uint64_t get_DAIF(); +extern void set_DAIF(uint64_t); +extern uint64_t get_SPSel(); +extern uint64_t get_ESR_EL1(); +extern uint64_t get_SPSR_EL1(); +extern uint64_t get_ELR_EL1(); +extern uint64_t get_SP(); +extern uint64_t get_CNTP_CTL_EL0(); +extern void set_CNTP_CTL_EL0(uint64_t); +extern uint64_t get_CNTFRQ_EL0(); +extern void set_CNTP_TVAL_EL0(uint64_t); +extern uint64_t get_CNTPCT_EL0(); +extern void local_irq_enable(); +extern void local_irq_disable(); +extern uint64_t local_irq_disable_save(); +extern void local_irq_restore(uint64_t); +extern void set_tpidr_el1(uint64_t); + +#endif + diff --git a/lab6/include/debug/debug.h b/lab6/include/debug/debug.h new file mode 100644 index 000000000..098653069 --- /dev/null +++ b/lab6/include/debug/debug.h @@ -0,0 +1,18 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "lib/print.h" +#include "types.h" +#include "asm.h" + +#define DEBUG_KERNEL_START() log_kernel_start() +#define LOG(fmt, ...) \ + if(debug) \ + printf("[%s/%s:%d] " fmt "\r\n" , __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) + + + +extern void log_kernel_start(void); + +extern int debug; +#endif diff --git a/lab6/include/fs/initrdfs.h b/lab6/include/fs/initrdfs.h new file mode 100644 index 000000000..7abdde1ce --- /dev/null +++ b/lab6/include/fs/initrdfs.h @@ -0,0 +1,19 @@ +#ifndef _INITRDFS_H_ +#define _INITRDFS_H_ +#include "types.h" +#include "lib/cpio.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "mm/slab.h" +#include "lib/list.h" +#include "lib/string.h" +#include "debug/debug.h" +#include "peripherals/mini_uart.h" + +extern void initrdfs_init(void*); +extern void initrdfs_ls(); +extern void initrdfs_cat(); +extern void* fdt_initrdfs_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +extern size_t initrdfs_loadfile(char* , uint8_t*, size_t, size_t); +extern size_t initrdfs_filesize(char*); +#endif diff --git a/lab6/include/init/kernel_init.h b/lab6/include/init/kernel_init.h new file mode 100644 index 000000000..fdd21d689 --- /dev/null +++ b/lab6/include/init/kernel_init.h @@ -0,0 +1,16 @@ +#ifndef _KERNEL_INIT_H +#define _KERNEL_INIT_H +#include "types.h" +#include "peripherals/mini_uart.h" +#include "fs/initrdfs.h" +#include "kernel/timer.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "mm/mm.h" +#include "asm.h" +#include "kernel/sched/sched.h" +#include "kernel/sched/kthread.h" + +extern void kernel_init(void *); + +#endif diff --git a/lab6/include/kernel/fault.h b/lab6/include/kernel/fault.h new file mode 100644 index 000000000..7052892cf --- /dev/null +++ b/lab6/include/kernel/fault.h @@ -0,0 +1,13 @@ +#ifndef _FAULT_H_ +#define _FAULT_H_ + +#include "mm/mm.h" +#include "lib/print.h" +#include "types.h" + +#define FAULT_DATA_ABORT_LOW_EL (0b100100) +#define FAULT_DATA_ABORT (0b100101) +#define FAULT_INSTR_ABORT_LOW_EL (0b100000) +#define FAULT_INSTR_ABORT (0b100001) + +#endif diff --git a/lab6/include/kernel/irq_handler.h b/lab6/include/kernel/irq_handler.h new file mode 100644 index 000000000..52ff3091f --- /dev/null +++ b/lab6/include/kernel/irq_handler.h @@ -0,0 +1,25 @@ +#ifndef _IRQ_HANDLER_H_ +#define _IRQ_HANDLER_H_ + +#include "types.h" +#include "peripherals/iomapping.h" +#include "peripherals/mini_uart.h" +#include "lib/print.h" +#include "lib/bitops.h" +#include "kernel/timer.h" +#include "kernel/sched/sched.h" +#include "debug/debug.h" +#include "asm.h" + +#define MAX_SOFTIRQ_TRY 10 + +enum {CORE0_TIMER = 0, MINI_UART_RX, UNKNOWN_IRQ, END_OF_LIST}; +typedef void (*irq_funcptr)(void); + +struct softirq_status{ + uint16_t pending; // support 16 interrupt + uint8_t in_softirq; +}; +extern uint64_t irq_count[END_OF_LIST]; +extern uint8_t in_softirq(); +#endif diff --git a/lab6/include/kernel/reboot.h b/lab6/include/kernel/reboot.h new file mode 100644 index 000000000..cc8e8730b --- /dev/null +++ b/lab6/include/kernel/reboot.h @@ -0,0 +1,16 @@ +#ifndef _REBOOT_H_ +#define _REBOOT_H_ + +#include "peripherals/iomapping.h" + +#define PM_WDOG_RESET 0000000000 +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +extern void reboot(int tick); + +#endif diff --git a/lab6/include/kernel/sched/kthread.h b/lab6/include/kernel/sched/kthread.h new file mode 100644 index 000000000..36d471908 --- /dev/null +++ b/lab6/include/kernel/sched/kthread.h @@ -0,0 +1,20 @@ +#ifndef _KTHREAD_H_ +#define _KTHREAD_H_ + +#include "kernel/sched/sched.h" +#include "kernel/sched/task.h" +#include "mm/page_alloc.h" +#include "debug/debug.h" +#include "mm/slab.h" +typedef void (*kthread_func)(void); + +extern void kthread_init(); +extern void kthread_idle(); +extern void kthread_test(); +extern uint64_t kthread_create(kthread_func func); +extern void kthread_exit(); +extern void kthread_destroy(struct task_struct*); +extern void kthread_start(kthread_func); +extern void kthread_int(); + +#endif diff --git a/lab6/include/kernel/sched/sched.h b/lab6/include/kernel/sched/sched.h new file mode 100644 index 000000000..e2eee0a3d --- /dev/null +++ b/lab6/include/kernel/sched/sched.h @@ -0,0 +1,163 @@ +#ifndef _SCHED_H_ +#define _SCHED_H_ +#include "mm/mmu.h" +#include "lib/list.h" +#include "kernel/irq_handler.h" +#include "kernel/signal.h" + +typedef uint64_t pid_t; + + +#define TASK_RUNNING 0 +#define TASK_INTERRUPTIBLE 1 +#define TASK_UNINTERRUPTIBLE 2 +#define TASK_DEAD 64 +#define VMA_STACK (1 << 0) +#define VMA_FILE (1 << 1) +#define VMA_VC_RAM (2 << 1) +#define VMA_ANONYMOUS (3 << 1) + +#define VMA_PROT_READ (1 << 0) +#define VMA_PROT_WRITE (1 << 1) +#define VMA_PROT_EXEC (1 << 2) +#define VMA_SHARED_EXEC (1 << 3) + +#define PROT_NONE 0 +#define PROT_READ (1 << 0) +#define PROT_WRITE (1 << 1) +#define PROT_EXEC (1 << 2) + +#define MAP_ANONYMOUS 0x20 +#define MAP_POPULATE 0x08000 + +#define VMA_CODE_BASE 0 +#define VMA_STACK_END 0xfffffffff000 +#define VMA_STACK_SIZE 0x4000 +#define VMA_VC_BASE 0x3c000000 +#define VMA_VC_END 0x3f000000 + +#define get_trap_frame(task) (task->stack + PAGE_SIZE * 2 - sizeof(struct trap_frame)) +struct thread_info{ + pid_t pid; + volatile int64_t state; +}; + +struct sched_info{ + int64_t rticks; // running ticks = user + system ticks + int64_t priority; + int64_t counter; // reset counter -> counter = priority + struct list_head sched_list; +}; + +struct trap_frame{ + uint64_t x0; + uint64_t x1; + uint64_t x2; + uint64_t x3; + uint64_t x4; + uint64_t x5; + uint64_t x6; + uint64_t x7; + uint64_t x8; + uint64_t x9; + uint64_t x10; + uint64_t x11; + uint64_t x12; + uint64_t x13; + uint64_t x14; + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t x29; // fp + uint64_t x30; // lr + uint64_t sp_el0; + uint64_t spsr_el1; + uint64_t elr_el1; +}__attribute__((packed)); + +struct task_ctx{ + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t fp; + uint64_t lr; + uint64_t sp; + uint64_t redzone; +}__attribute__((packed)); + +struct vm_area_struct{ + uint64_t vm_start; + uint64_t vm_end; + uint64_t vm_flags; + uint64_t type; + char* filename; + struct list_head list; +}; + +struct mm_struct{ + struct list_head mmap_list; + pgdval_t* pgd; +}; + +struct task_struct{ + struct task_ctx ctx; + + struct thread_info thread_info; + + struct mm_struct* mm; + + // kernel stack + void* stack; + + // schedule info + struct sched_info sched_info; + + // signal + struct sigpending sigpending; + struct sighand_struct sighandler; + + // relationship + struct task_struct* parent; + struct task_struct* child; + struct list_head siblings; + + // task list + struct list_head list; + + // zombie list + struct list_head zombie; +}; + +extern int need_sched; +extern struct list_head zombies; +extern struct list_head task_list; +extern struct task_struct* user_init; + +extern void add_task_to_rq(struct task_struct *task); +extern struct task_struct* pick_next_task_from_rq(); +extern void schedule(); +extern void switch_to(struct task_struct*, struct task_struct*); +extern struct task_struct* get_current(); +extern pid_t get_pid_counter(void); +extern void preempt_schedule(); +extern void print_rq(void); +extern struct task_struct* find_task_by_pid(uint64_t pid); +#endif diff --git a/lab6/include/kernel/sched/task.h b/lab6/include/kernel/sched/task.h new file mode 100644 index 000000000..af87b12f0 --- /dev/null +++ b/lab6/include/kernel/sched/task.h @@ -0,0 +1,27 @@ +#ifndef _TASK_H_ +#define _TASK_H_ + +#include "kernel/sched/sched.h" +#include "fs/initrdfs.h" +#include "mm/page_alloc.h" +#include "debug/debug.h" +#include "mm/slab.h" + +extern void task_init(); +extern uint64_t task_dup(); +extern void task_exit(); +extern void task_destroy(struct task_struct*); +extern void run_init_task(char*); +extern struct trap_frame* get_current_trap_frame(); +extern void sys_kill(uint64_t); +extern struct vm_area_struct* create_vma_stack(struct mm_struct*); +extern struct vm_area_struct* create_vma_code(struct mm_struct*, char*); +extern struct mm_struct* mm_struct_create(); +extern void dup_mm_struct(struct mm_struct*, struct mm_struct*); +extern void mm_struct_destroy(struct mm_struct*); +extern void dup_vma_stack(struct mm_struct*, struct mm_struct*); +uint64_t mmap(void*, size_t, int, int, int, int); +extern struct vm_area_struct* create_vma_vc(struct mm_struct*); +extern struct vm_area_struct* find_vma(struct mm_struct*, uint64_t); +extern void* sys_mmap(void*, size_t, int, int, int, int); +#endif diff --git a/lab6/include/kernel/shell.h b/lab6/include/kernel/shell.h new file mode 100644 index 000000000..81f8b0988 --- /dev/null +++ b/lab6/include/kernel/shell.h @@ -0,0 +1,19 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ +#include "types.h" +#include "lib/print.h" +#include "lib/string.h" +#include "lib/simple_malloc.h" +#include "peripherals/mailbox.h" +#include "kernel/reboot.h" +#include "fs/initrdfs.h" +#include "kernel/timer.h" +#include "kernel/irq_handler.h" +#include "mm/slab.h" +#include "kernel/sched/task.h" +#include "kernel/sched/kthread.h" + +void simple_shell(void); + +#define DELIM " \t\n\r" +#endif diff --git a/lab6/include/kernel/signal.h b/lab6/include/kernel/signal.h new file mode 100644 index 000000000..1d4ae3073 --- /dev/null +++ b/lab6/include/kernel/signal.h @@ -0,0 +1,80 @@ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +#include "types.h" +#include "lib/list.h" + +#define SIG_SIGHUP 1 +#define SIG_SIGINT 2 +#define SIG_SIGQUIT 3 +#define SIG_SIGILL 4 +#define SIG_SIGTRAP 5 +#define SIG_SIGABRT 6 +#define SIG_SIGBUS 7 +#define SIG_SIGFPE 8 +#define SIG_SIGKILL 9 +#define SIG_SIGUSR1 10 +#define SIG_SIGSEGV 11 +#define SIG_SIGUSR2 12 +#define SIG_SIGPIPE 13 +#define SIG_SIGALRM 14 +#define SIG_SIGTERM 15 +#define SIG_SIGSTKFLT 16 +#define SIG_SIGCHLD 17 +#define SIG_SIGCONT 18 +#define SIG_SIGSTOP 19 +#define SIG_SIGTSTP 20 +#define SIG_SIGTTIN 21 +#define SIG_SIGTTOU 22 +#define SIG_SIGURG 23 +#define SIG_SIGXCPU 24 +#define SIG_SIGXFSZ 25 +#define SIG_SIGVTALRM 26 +#define SIG_SIGPROF 27 +#define SIG_SIGWINCH 28 +#define SIG_SIGIO 29 +#define SIG_SIGPWR 30 +#define SIG_SIGSYS 31 + +#define SIG_FLAG_KERNEL 1 + +#define SIG_MAX_NUM 32 + +typedef void (*sig_handler)(); + +struct signal_queue{ + struct list_head list; + int32_t signal; +}; + +struct sigpending{ + struct list_head pending; + int32_t cur_signal; +}; + +struct sigaction{ + uint32_t sa_flags; + sig_handler sa_handler; +}; + +struct sighand_struct{ + struct sigaction actions[SIG_MAX_NUM]; +}; + +extern void sigpending_init(struct sigpending*); +extern void default_sighand_init(struct sighand_struct*); +extern int send_signal(uint64_t, int); +extern int register_signal(int, sig_handler); +extern void handle_sigreturn(); +extern void handle_signal(); +extern void sigreturn_frame_save(sig_handler); +extern void sigreturn_frame_restore(); +extern void sys_sigreturn(); +extern void sys_signal(int, sig_handler); +extern int sys_sigkill(uint64_t, int); +extern void sig_default(); +extern void sig_terminate(); +extern void free_sigpendings(struct sigpending*); + + +#endif diff --git a/lab6/include/kernel/signal_inner.h b/lab6/include/kernel/signal_inner.h new file mode 100644 index 000000000..4f9c8c2bd --- /dev/null +++ b/lab6/include/kernel/signal_inner.h @@ -0,0 +1,74 @@ +#ifndef _SIGNAL_INNER_H_ +#define _SIGNAL_INNER_H_ + +#include "kernel/signal.h" +struct sigaction default_actions[SIG_MAX_NUM] = { + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_terminate}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_terminate}, // 9 + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_terminate}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default} +}; + +char* sig_to_str[SIG_MAX_NUM] = { + "SIGUNKOWN", + "SIGHUP", + "SIGINT", + "SIGQUIT", + "SIGILL", + "SIGTRAP", + "SIGABRT", + "SIGBUS", + "SIGFPE", + "SIGKILL", + "SIGUSR1", + "SIGSEGV", + "SIGUSR2", + "SIGPIPE", + "SIGALRM", + "SIGTERM", + "SIGSTKFLT", + "SIGCHLD", + "SIGCONT", + "SIGSTOP", + "SIGTSTP", + "SIGTTIN", + "SIGTTOU", + "SIGURG", + "SIGXCPU", + "SIGXFSZ", + "SIGVTALRM", + "SIGPROF", + "SIGWINCH", + "SIGIO", + "SIGPWR", + "SIGSYS" +}; +#endif diff --git a/lab6/include/kernel/syscall.h b/lab6/include/kernel/syscall.h new file mode 100644 index 000000000..029fbc909 --- /dev/null +++ b/lab6/include/kernel/syscall.h @@ -0,0 +1,18 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ +#include "types.h" +#include "kernel/signal.h" +extern uint64_t sys_hello(uint64_t); +extern size_t sys_uart_write(char *, size_t); +extern size_t sys_uart_read(char *, size_t); +extern uint64_t sys_fork(); +extern uint64_t sys_getpid(); +extern int sys_mbox_call(uint8_t, uint32_t *); +extern void sys_exit(); +extern void sys_kill(uint64_t pid); +extern int sys_exec(const char *, char *const []); +extern void sys_sigreturn(); +extern void sys_signal(int, sig_handler); +extern int sys_sigkill(uint64_t, int); +extern void* sys_mmap(void*, size_t, int, int, int, int); +#endif diff --git a/lab6/include/kernel/syscall_table.h b/lab6/include/kernel/syscall_table.h new file mode 100644 index 000000000..cb853be3a --- /dev/null +++ b/lab6/include/kernel/syscall_table.h @@ -0,0 +1,6 @@ +#ifndef _SYSCALL_TABLE_H_ +#define _SYSCALL_TABLE_H_ + +#include "kernel/syscall.h" +#include "kernel/sched/sched.h" +#endif diff --git a/lab6/include/kernel/timer.h b/lab6/include/kernel/timer.h new file mode 100644 index 000000000..a07d425c9 --- /dev/null +++ b/lab6/include/kernel/timer.h @@ -0,0 +1,32 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ +#include "types.h" +#include "lib/list.h" +#include "lib/simple_malloc.h" +#include "peripherals/iomapping.h" +#include "debug/debug.h" +#include "asm.h" +#include "kernel/sched/sched.h" + + +#define HZ 100 + +typedef void (*timer_callback)(void*); + +typedef struct{ + uint64_t ticks; + timer_callback callback; + void *data; + struct list_head list; +}timer_t; + +extern void core_timer_irq_handler(); +extern void init_core_timer(); +extern uint64_t get_jiffies(); +extern void enable_core_timer_irq(); +extern void disable_core_timer_irq(); +extern void init_timer_list(); +extern void add_timer(timer_callback, uint8_t*, uint64_t); +extern void timer_softirq_callback(); + +#endif diff --git a/lab6/include/lib/bitops.h b/lab6/include/lib/bitops.h new file mode 100644 index 000000000..1a22a6136 --- /dev/null +++ b/lab6/include/lib/bitops.h @@ -0,0 +1,8 @@ +#ifndef _BITOPS_H_ +#define _BITOPS_H_ + +#include "types.h" +extern uint16_t ffs16(uint16_t); +extern uint64_t ffs64(uint64_t); + +#endif diff --git a/lab6/include/lib/cpio.h b/lab6/include/lib/cpio.h new file mode 100644 index 000000000..9e9eaf129 --- /dev/null +++ b/lab6/include/lib/cpio.h @@ -0,0 +1,66 @@ +#ifndef _CPIO_H_ +#define _CPIO_H_ + +#include "types.h" +#include "lib/list.h" +#include "lib/fdt_parse.h" +#include "lib/string.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "debug/debug.h" + +#define FILE_TYPE_MASK 0170000 +#define FILE_TYPE_SOCKET 0140000 +#define FILE_TYPE_SYMLINK 0120000 +#define FILE_TYPE_REGULAR 0100000 +#define FILE_TYPE_BLKDEV 0060000 +#define FILE_TYPE_DIR 0040000 +#define FILE_TYPE_CHRDEV 0020000 +#define FILE_TYPE_NAMED_PIPE 0010000 +#define FILE_SUID 0004000 +#define FILE_SGID 0002000 +#define FILE_STICKY 0001000 +#define FILE_PERMISSION_MASK 0000777 + +struct cpio_iter{ + uint8_t *cur; +}; +struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} __attribute((packed)); + +struct fentry { + uint32_t ino; + uint32_t mode; + uint32_t uid; + uint32_t gid; + uint32_t nlink; + uint32_t mtime; + uint32_t filesize; + uint32_t devmajor; + uint32_t devminor; + uint32_t rdevmajor; + uint32_t rdevminor; + uint32_t namesize; + uint32_t check; + char *filename; + uint8_t *data; + struct list_head list; +}; +void cpio_iter_parse(struct cpio_iter*, struct fentry*); +extern void cpio_iter_init(struct cpio_iter*, void*); +extern int cpio_is_tailer(struct fentry*); +#endif diff --git a/lab6/include/lib/fdt_parse.h b/lab6/include/lib/fdt_parse.h new file mode 100644 index 000000000..22616d335 --- /dev/null +++ b/lab6/include/lib/fdt_parse.h @@ -0,0 +1,48 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "lib/string.h" +#include "mm/mmu.h" + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +typedef void (*fdt_rsvmap_callback)(uint64_t, uint64_t); +extern void fdt_parse_header(uint8_t*, fdt_header*); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parse_rsvmap(uint8_t*, fdt_rsvmap_callback); +#endif diff --git a/lab6/include/lib/list.h b/lab6/include/lib/list.h new file mode 100644 index 000000000..f102aef06 --- /dev/null +++ b/lab6/include/lib/list.h @@ -0,0 +1,25 @@ +#ifndef _LIST_H_ +#define _LIST_H_ + +#include "types.h" +struct list_head{ + struct list_head* next, *prev; +}; + +#define LIST_HEAD(head) struct list_head head = { &(head), &(head) } +#define list_entry(node, type, member) container_of(node, type, member) +#define list_first_entry(head, type, member) list_entry((head)->next, type, member) +#define list_last_entry(head, type, member) list_entry((head)->prev, type, member) +#define list_for_each(node, head) \ + for(node = (head)->next ; node != (head) ; node = node->next) + +extern void INIT_LIST_HEAD(struct list_head*); +extern void list_add(struct list_head* node, struct list_head*); +extern void list_add_tail(struct list_head*, struct list_head*); +extern void list_del(struct list_head*); +extern int list_empty(struct list_head*); +extern int list_is_last(struct list_head*, struct list_head*); +extern int list_is_head(struct list_head*, struct list_head*); +extern void list_splice(struct list_head*, struct list_head*); +extern void list_splice_tail(struct list_head*, struct list_head*); +#endif diff --git a/lab6/include/lib/print.h b/lab6/include/lib/print.h new file mode 100644 index 000000000..7752c069c --- /dev/null +++ b/lab6/include/lib/print.h @@ -0,0 +1,21 @@ +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#include "types.h" +#include "kernel/timer.h" +#include "lib/string.h" +#include "peripherals/mini_uart.h" +#include "kernel/irq_handler.h" +#include + +extern int32_t printf(char *, ...); +extern int32_t putchar(uint8_t); +extern int32_t getchar(); + +#define INFO(fmt, ...) \ + do{ \ + printf("%l: [%s] " fmt "\r\n" , (int64_t)get_jiffies(), __FUNCTION__, ##__VA_ARGS__); \ + }while(0) + + +#endif diff --git a/lab6/include/lib/ring_buffer.h b/lab6/include/lib/ring_buffer.h new file mode 100644 index 000000000..282b61b53 --- /dev/null +++ b/lab6/include/lib/ring_buffer.h @@ -0,0 +1,27 @@ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ +#include "types.h" +#include "lib/simple_malloc.h" +#include "mm/slab.h" + +typedef struct{ + size_t size; + uint64_t head; + uint64_t tail; + uint8_t* buf; + size_t count; +}ring_buffer; + +extern ring_buffer* create_simple_ring_buf(size_t); + +extern ring_buffer* create_ring_buf(size_t); +extern void free_ring_buf(ring_buffer*); +extern size_t ring_buf_write(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_write_unsafe(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read_unsafe(ring_buffer*, uint8_t*, size_t); +extern uint8_t ring_buf_is_full(ring_buffer*); +extern uint8_t ring_buf_is_empty(ring_buffer*); +extern size_t ring_buf_get_len(ring_buffer*); + +#endif diff --git a/lab6/include/lib/simple_malloc.h b/lab6/include/lib/simple_malloc.h new file mode 100644 index 000000000..8f8c0f4dc --- /dev/null +++ b/lab6/include/lib/simple_malloc.h @@ -0,0 +1,15 @@ +#ifndef _SIMPLE_MALLOC_H_ +#define _SIMPLE_MALLOC_H_ + +#include "types.h" +#include "debug/debug.h" + +#define req2size(req) ALIGN_UP(req, 16) + +struct malloc_state{ + uint8_t* last_remainder; +}; + +extern void* simple_malloc(size_t); +extern void* simple_malloc_get_remainder(); +#endif diff --git a/lab6/include/lib/string.h b/lab6/include/lib/string.h new file mode 100644 index 000000000..4a6a30cd7 --- /dev/null +++ b/lab6/include/lib/string.h @@ -0,0 +1,19 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#include "types.h" + +extern char * itoa(int32_t, char*, uint32_t); +extern char * utoa(uint32_t, char*, uint32_t); +extern char * ltoa(int64_t, char*, uint32_t); +extern char * ultoa(uint64_t, char*, uint32_t); +extern int32_t strcmp(char*, char*); +extern char *strcpy(char *, const char *); +extern size_t strlen(const char*); +extern void* memcpy(void*, const void*, size_t); +extern void* memset(void*, int, size_t); +extern int32_t memcmp(void*, const void*, size_t); +extern uint8_t hex2dec(char); +extern char* strtok(char*,const char*); +extern uint64_t atoul(const char*); +#endif diff --git a/lab6/include/mm/mm.h b/lab6/include/mm/mm.h new file mode 100644 index 000000000..0e3454127 --- /dev/null +++ b/lab6/include/mm/mm.h @@ -0,0 +1,36 @@ +#ifndef _MM_H_ +#define _MM_H_ + +#include "types.h" +#include "lib/fdt_parse.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "lib/list.h" +#include "lib/string.h" +#include "mm/page_alloc.h" +#include "mm/slab.h" +#include "mm/mmu.h" + + +struct mem_block{ + uint64_t start; + uint64_t end; + struct list_head list; +}; + +struct mem_node{ + uint64_t start; + uint64_t end; + char *name; + struct list_head list; +}; + +extern struct list_head mem_rsvmap; +extern struct list_head mem_unusedmap; +extern struct mem_node memory_node; +extern struct page *mem_map; + +extern void mm_init(void *); + + +#endif diff --git a/lab6/include/mm/mmu.h b/lab6/include/mm/mmu.h new file mode 100644 index 000000000..58855ea95 --- /dev/null +++ b/lab6/include/mm/mmu.h @@ -0,0 +1,65 @@ +#ifndef _MMU_H_ +#define _MMU_H_ +#include "mm/pgtable.h" +#include "types.h" +#include "asm.h" + +typedef uint64_t pgdval_t; +typedef uint64_t pudval_t; +typedef uint64_t pmdval_t; +typedef uint64_t pteval_t; + +#define UPPER_ADDR_SPACE_BASE ((uint64_t)0xFFFF000000000000) +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1ul << PAGE_SHIFT) + + +#define pgd_index(addr) (((uint64_t)addr >> PGD_SHIFT) & 0b111111111) +#define pgd_offset(pgd, addr) ((pgdval_t*)pgd + pgd_index(addr)) +#define pgd_none(val) (val == 0) +#define pgd_set(pgd, val) do{*((pgdval_t*)pgd) = val;}while(0) + +#define pud_index(addr) (((uint64_t)addr >> PUD_SHIFT) & 0b111111111) +#define pud_offset(pgd_e, addr) ((pudval_t*)phys_to_virt(((uint64_t)*pgd_e & PHYS_ADDR_MASK)) + pud_index(addr)) +#define pud_none(val) (val == 0) +#define pud_set(pud, val) do{*((pudval_t*)pud) = val;}while(0) + +#define pmd_index(addr) (((uint64_t)addr >> PMD_SHIFT) & 0b111111111) +#define pmd_offset(pud_e, addr) ((pmdval_t*)phys_to_virt(((uint64_t)*pud_e & PHYS_ADDR_MASK)) + pmd_index(addr)) +#define pmd_none(val) (val == 0) +#define pmd_set(pmd, val) do{*((pmdval_t*)pmd) = val;}while(0) + +#define pte_index(addr) (((uint64_t)addr >> PTE_SHIFT) & 0b111111111) +#define pte_offset(pmd_e, addr) ((pteval_t*)phys_to_virt(((uint64_t)*pmd_e & PHYS_ADDR_MASK)) + pte_index(addr)) +#define pte_val(pte_e) (*pte_e) +#define pte_none(val) (val == 0) +#define pte_set(pte, val) do{*((pteval_t*)pte) = val;}while(0) +#define pte_page(pte_e) ((struct page*)phys_to_page(((uint64_t)*pte_e & PHYS_ADDR_MASK))) +#define pte_reuse(pte_e) do{ \ + uint64_t daif = local_irq_disable_save(); \ + struct page* page = phys_to_page(((uint64_t)*pte_e & PHYS_ADDR_MASK)); \ + page->ref_cnt++; \ + local_irq_restore(daif); \ + }while(0) + +#define pte_inuse(pte_e) (((struct page*)phys_to_page(((uint64_t)*pte_e & PHYS_ADDR_MASK)))->ref_cnt != 0) +#define pte_writable(pte_e) (((uint64_t)*pte_e & PAGE_ATTR_RDONLY) == 0) +#define pte_ref_cnt(pte_e) (((struct page*)phys_to_page(((uint64_t)*pte_e & PHYS_ADDR_MASK)))->ref_cnt) + +#define VM_FAULT_NONE 0 +#define VM_FAULT_BADMAP 1 +#define VM_FAULT_BADACCESS 2 + +#define VM_USER_SPACE 0xffffffffffff + +extern void page_init(); +extern void mappages(pgdval_t*, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); +extern void dup_pages(pgdval_t*, pgdval_t*, uint64_t, uint64_t, uint64_t); +extern void free_page_table(pgdval_t*); +extern void free_one_pgd(pgdval_t*); +extern void free_one_pud(pudval_t*); +extern void free_one_pmd(pmdval_t*); +extern void free_one_pte(pteval_t*); +extern void do_mem_abort(uint64_t, uint64_t); +extern pteval_t* get_pte(pgdval_t*, uint64_t); +#endif diff --git a/lab6/include/mm/page_alloc.h b/lab6/include/mm/page_alloc.h new file mode 100644 index 000000000..1f59adf59 --- /dev/null +++ b/lab6/include/mm/page_alloc.h @@ -0,0 +1,65 @@ +#ifndef _PAGE_ALLOC_H_ +#define _PAGE_ALLOC_H_ + +#include "types.h" +#include "lib/list.h" +#include "lib/print.h" +#include "lib/bitops.h" +#include "mm/mm.h" + +#define BUDDY_GROUP_MEMBER 0x80000000 +#define BUDDY_ALLOCATED 0x40000000 +#define BUDDY_MAX_ORDER 7 + +#define PAGE_TYPE_RESERVED 1 + +#define BUDDY_IS_ALLOCATED(x) (((struct page*)x)->order & BUDDY_ALLOCATED) +#define BUDDY_IS_MEMBER(x) (((struct page*)x)->order & BUDDY_GROUP_MEMBER) +#define BUDDY_IS_FREED(x) (!BUDDY_IS_ALLOCATED(x)) +#define PAGE_IS_RESERVED(x) (((struct page*)x)->type & PAGE_TYPE_RESERVED) +#define _buddy_ffs(x) ((x) == 0 ? BUDDY_MAX_ORDER : ffs64(x)) +#define find_buddy_pfn(pfn, order) (pfn ^ (1 << order)) +#define get_page_order(p) (p->order & 0xffff) +#define get_buddy_leader(p) (p->buddy_leader) + +#define virt_to_pfn(addr) ((uint64_t)(((uint64_t)addr) - UPPER_ADDR_SPACE_BASE) >> PAGE_SHIFT) +#define pfn_to_virt(n) ((void*)((n << PAGE_SHIFT) + UPPER_ADDR_SPACE_BASE)) +#define page_to_pfn(x) ((uint64_t)((struct page*)x - mem_map)) +#define pfn_to_page(x) ((struct page*)&mem_map[(uint64_t)x]) +#define page_to_virt(x) (pfn_to_virt(page_to_pfn(x))) +#define page_to_phys(x) (page_to_pfn(x) << PAGE_SHIFT) +#define virt_to_page(x) (pfn_to_page(virt_to_pfn(x))) +#define virt_to_phys(addr) (((uint64_t)addr) - UPPER_ADDR_SPACE_BASE) +#define phys_to_virt(addr) (((uint64_t)addr) + UPPER_ADDR_SPACE_BASE) +#define phys_to_page(addr) (pfn_to_page((uint64_t)addr >> PAGE_SHIFT)) + +struct page{ +// if (order & BUDDY_MEMBER), then it is freed and it is not a buddy leader +// if (order & BUDDY_ALLOCATED), then it is allocated + void* buddy_leader; + uint32_t order; + uint32_t type; + struct list_head list; + size_t ref_cnt; +}; + +struct free_list{ + size_t count; + struct list_head list; +}; + +struct buddy_system{ + struct free_list free_lists[BUDDY_MAX_ORDER]; +}; + +extern void buddy_init(); +extern void* alloc_page(); +extern void* calloc_page(); +extern void* alloc_pages(uint32_t); +extern void free_pages(void*, uint32_t); +extern void free_page(void*); +extern void debug_buddy(); +extern void print_buddy_statistics(); + +#endif + diff --git a/lab6/include/mm/pgtable.h b/lab6/include/mm/pgtable.h new file mode 100644 index 000000000..2ce4227f6 --- /dev/null +++ b/lab6/include/mm/pgtable.h @@ -0,0 +1,72 @@ +#ifndef _PGTABLE_H_ +#define _PGTABLE_H_ + +#define PGD_SHIFT (39) +#define PGD_TYPE_MASK (3 << 0) +#define PGD_TYPE_TABLE (3 << 0) +#define PGD_TABLE_BIT (1 << 1) +#define PGD_TYPE_BLOCK (1 << 0) + +#define PUD_SHIFT (30) +#define PUD_TYPE_MASK (3 << 0) +#define PUD_TYPE_TABLE (3 << 0) +#define PUD_TABLE_BIT (1 << 1) +#define PUD_TYPE_BLOCK (1 << 0) + +#define PMD_SHIFT (21) +#define PMD_TYPE_MASK (3 << 0) +#define PMD_TYPE_TABLE (3 << 0) +#define PMD_TABLE_BIT (1 << 1) +#define PMD_TYPE_BLOCK (1 << 0) + +#define PTE_SHIFT (12) +#define PTE_TYPE_MASK (3 << 0) +#define PTE_TYPE_FAULT (0 << 0) +#define PTE_TYPE_PAGE (3 << 0) +#define PTE_TABLE_BIT (1 << 1) + +#define PAGE_MAIR_SHIFT (2) +#define PAGE_ATTR_USER (1 << 6) +#define PAGE_ATTR_RDONLY (1 << 7) +#define PAGE_ATTR_SHARED (3 << 8) +#define PAGE_ATTR_AF (1 << 10) +#define PAGE_ATTR_NG (1 << 11) +#define PAGE_ATTR_DBM (1ul << 51) +#define PAGE_ATTR_CONT (1ul << 52) +#define PAGE_ATTR_PXN (1ul << 53) +#define PAGE_ATTR_UXN (1ul << 54) +#define PAGE_ATTR_DIRTY (1ul << 55) // Hardware doesn't support dirty bit. + +#define BLOCK_MAIR_SHIFT (2) +#define BLOCK_ATTR_USER (1 << 6) +#define BLOCK_ATTR_RDONLY (1 << 7) +#define BLOCK_ATTR_SHARED (3 << 8) +#define BLOCK_ATTR_AF (1 << 10) +#define BLOCK_ATTR_NG (1 << 11) +#define BLOCK_ATTR_DBM (1ul << 51) +#define BLOCK_ATTR_CONT (1ul << 52) +#define BLOCK_ATTR_PXN (1ul << 53) +#define BLOCK_ATTR_UXN (1ul << 54) + +#define PHYS_ADDR_MASK (0xfffffffff000) + +#define TCR_CONFIG_REGION_48bit (((64 - 48) << 0) | ((64 - 48) << 16)) +#define TCR_CONFIG_4KB ((0b00 << 14) | (0b10 << 30)) +#define TCR_CONFIG_DEFAULT (TCR_CONFIG_REGION_48bit | TCR_CONFIG_4KB) + +#define MAIR_DEVICE_nGnRnE 0b00000000 +#define MAIR_NORMAL_NOCACHE 0b01000100 +#define MAIR_IDX_DEVICE_nGnRnE 0 +#define MAIR_IDX_NORMAL_NOCACHE 1 + +#define BOOT_PGD_ATTR (PGD_TYPE_TABLE) +#define BOOT_PUD_ATTR (PUD_TYPE_BLOCK | BLOCK_ATTR_AF | (MAIR_IDX_DEVICE_nGnRnE << BLOCK_MAIR_SHIFT)) + +#define VM_PGD_ATTR (PGD_TYPE_TABLE) +#define VM_PUD_ATTR (PUD_TYPE_TABLE) +#define VM_PMD_ATTR (PMD_TYPE_TABLE) +#define VM_PTE_DEVICE_ATTR (PTE_TYPE_PAGE | PAGE_ATTR_AF | (MAIR_IDX_DEVICE_nGnRnE << PAGE_MAIR_SHIFT)) +#define VM_PTE_NORMAL_ATTR (PTE_TYPE_PAGE | PAGE_ATTR_AF | (MAIR_IDX_NORMAL_NOCACHE << PAGE_MAIR_SHIFT)) + +#define VM_PTE_USER_ATTR (PTE_TYPE_PAGE | PAGE_ATTR_AF | PAGE_ATTR_USER | (MAIR_IDX_NORMAL_NOCACHE << PAGE_MAIR_SHIFT)) +#endif diff --git a/lab6/include/mm/slab.h b/lab6/include/mm/slab.h new file mode 100644 index 000000000..0558c471e --- /dev/null +++ b/lab6/include/mm/slab.h @@ -0,0 +1,37 @@ +#ifndef _SLAB_H_ +#define _SLAB_H_ + +#include "mm/mm.h" +#include "mm/page_alloc.h" +#include "lib/list.h" +#include "lib/string.h" +#include "debug/debug.h" + +struct slab{ + size_t size; // object size + void* s_mem; // pointe to the first object + int64_t inuse; + struct list_head free_list; // free list + struct list_head list; // next slab +}; + +#define SLAB_ALIGNMENT (ALIGN_UP(sizeof(struct list_head), 0x20)) +#define SLAB_SIZE (ALIGN_UP(sizeof(struct slab), SLAB_ALIGNMENT)) +#define SLAB_MAX_OBJECT_SIZE (PAGE_SIZE * (1 << (BUDDY_MAX_ORDER - 1)) - SLAB_SIZE) + +#define KMEM_MIN_SIZE SLAB_ALIGNMENT +#define KMEM_ALIGNMENT SLAB_ALIGNMENT +#define KMEM_CACHE_NUM (SLAB_MAX_OBJECT_SIZE / KMEM_ALIGNMENT + 1) + +extern struct slab* slab_create(size_t); +extern void slab_destroy(struct slab*); +extern void *slab_alloc(struct slab*); +extern void slab_free(struct slab* , void*); + +extern void* kmalloc(size_t); +extern void kfree(void*); +extern void kmalloc_init(); + +extern void debug_kmalloc(); +extern void debug_slab(); +#endif diff --git a/lab6/include/peripherals/iomapping.h b/lab6/include/peripherals/iomapping.h new file mode 100644 index 000000000..91c4aec1b --- /dev/null +++ b/lab6/include/peripherals/iomapping.h @@ -0,0 +1,102 @@ +#ifndef _IOMAPPING_H_ +#define _IOMAPPING_H_ + +#include "mm/mmu.h" + +/* Physical addresses range from 0x3F000000 to 0x3FFFFFFF for peripherals */ +#define IO_BASE (0x3F000000 + UPPER_ADDR_SPACE_BASE) + +/* Register's offset of GPIO */ +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL1 (IO_BASE + 0x200004) +#define GPFSEL2 (IO_BASE + 0x200008) +#define GPFSEL3 (IO_BASE + 0x20000C) +#define GPFSEL4 (IO_BASE + 0x200010) +#define GPFSEL5 (IO_BASE + 0x200014) +#define GPSET0 (IO_BASE + 0x20001C) +#define GPSET1 (IO_BASE + 0x200020) +#define GPCLR0 (IO_BASE + 0x200028) +#define GPCLR1 (IO_BASE + 0x20002C) +#define GPLEV0 (IO_BASE + 0x200034) +#define GPLEV1 (IO_BASE + 0x200038) +#define GPEDS0 (IO_BASE + 0x200040) +#define GPEDS1 (IO_BASE + 0x200044) +#define GPREN0 (IO_BASE + 0x20004C) +#define GPREN1 (IO_BASE + 0x200050) +#define GPFEN0 (IO_BASE + 0x200058) +#define GPFEN1 (IO_BASE + 0x20005C) +#define GPHEN0 (IO_BASE + 0x200064) +#define GPHEN1 (IO_BASE + 0x200068) +#define GPLEN0 (IO_BASE + 0x200070) +#define GPLEN1 (IO_BASE + 0x200074) +#define GPAREN0 (IO_BASE + 0x20007C) +#define GPAREN1 (IO_BASE + 0x200080) +#define GPAFEN0 (IO_BASE + 0x200088) +#define GPAFEN1 (IO_BASE + 0x20008C) +#define GPPUD (IO_BASE + 0x200094) +#define GPPUDCLK0 (IO_BASE + 0x200098) +#define GPPUDCLK1 (IO_BASE + 0x20009C) + + +/* Register's offset of UART and SPI */ +#define AUX_IRQ (IO_BASE + 0x215000) +#define AUX_ENABLES (IO_BASE + 0x215004) +#define AUX_MU_IO_REG (IO_BASE + 0x215040) +#define AUX_MU_IER_REG (IO_BASE + 0x215044) +#define AUX_MU_IIR_REG (IO_BASE + 0x215048) +#define AUX_MU_LCR_REG (IO_BASE + 0x21504C) +#define AUX_MU_MCR_REG (IO_BASE + 0x215050) +#define AUX_MU_LSR_REG (IO_BASE + 0x215054) +#define AUX_MU_MSR_REG (IO_BASE + 0x215058) +#define AUX_MU_SCRATCH (IO_BASE + 0x21505C) +#define AUX_MU_CNTL_REG (IO_BASE + 0x215060) +#define AUX_MU_STAT_REG (IO_BASE + 0x215064) +#define AUX_MU_BAUD_REG (IO_BASE + 0x215068) +#define AUX_SPI0_CNTL0_REG (IO_BASE + 0x215080) +#define AUX_SPI0_CNTL1_REG (IO_BASE + 0x215084) +#define AUX_SPI0_STAT_REG (IO_BASE + 0x215088) +#define AUX_SPI0_IO_REG (IO_BASE + 0x215090) +#define AUX_SPI0_PEEK_REG (IO_BASE + 0x215094) +#define AUX_SPI1_CNTL0_REG (IO_BASE + 0x2150C0) +#define AUX_SPI1_CNTL1_REG (IO_BASE + 0x2150C4) +#define AUX_SPI1_STAT_REG (IO_BASE + 0x2150C8) +#define AUX_SPI1_IO_REG (IO_BASE + 0x2150D0) +#define AUX_SPI1_PEEK_REG (IO_BASE + 0x2150D4) + +// mailbox register base address +#define MBOX_REG (IO_BASE + 0xB880) + +// interrupt +#define IRQ_BASIC_PENDING (IO_BASE + 0xB200) +#define IRQ_PENDING_1 (IO_BASE + 0xB204) +#define IRQ_PENDING_2 (IO_BASE + 0xB208) +#define CORE0_IRQ_SOURCE (IO_BASE + 0x1000060) +#define CORE1_IRQ_SOURCE (IO_BASE + 0x1000064) +#define CORE2_IRQ_SOURCE (IO_BASE + 0x1000068) +#define CORE3_IRQ_SOURCE (IO_BASE + 0x100006C) +#define CORE0_FIQ_SOURCE (IO_BASE + 0x1000070) +#define CORE1_FIQ_SOURCE (IO_BASE + 0x1000074) +#define CORE2_FIQ_SOURCE (IO_BASE + 0x1000078) +#define CORE3_FIQ_SOURCE (IO_BASE + 0x100007C) +#define ENABLE_IRQS_1 (IO_BASE + 0xB210) + + +// timer +#define CORE0_TIMER_IRQ_CTRL (IO_BASE + 0x1000040) + + +// watch dog +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_RSTC (IO_BASE + 0x10001c) +#define PM_WDOG (IO_BASE + 0x100024) + +#define IO_MMIO_write32(addr, val) *(uint32_t*)addr = val +#define IO_MMIO_read32(addr) *(uint32_t*)addr +#define IO_MMIO_write64(addr, val) *(uint64_t*)addr = val +#define IO_MMIO_read64(addr) *(uint64_t*)addr + + + +#endif + diff --git a/lab6/include/peripherals/mailbox.h b/lab6/include/peripherals/mailbox.h new file mode 100644 index 000000000..ce8ba67f6 --- /dev/null +++ b/lab6/include/peripherals/mailbox.h @@ -0,0 +1,177 @@ +#ifndef _MAILBOX_H_ +#define _MAILBOX_H_ + +#include "types.h" +#include "lib/string.h" +#include "debug/debug.h" +#include "peripherals/iomapping.h" +#include "kernel/sched/sched.h" +#include "mm/mm.h" + +#define MBOX_CHANNEL_POWER 0 +#define MBOX_CHANNEL_FRAME_BUF 1 +#define MBOX_CHANNEL_VIRTUAL_UART 2 +#define MBOX_CHANNEL_VCHIQ 3 +#define MBOX_CHANNEL_LEDS 4 +#define MBOX_CHANNEL_BUTTONS 5 +#define MBOX_CHANNEL_TOUCH_SCREEN 6 +#define MBOX_CHANNEL_UNKOWN 7 +#define MBOX_CHANNEL_PROPERTY_TAGS 8 + +enum MBOX_PROPERTY_STATUS { + MBOX_STATUS_REQUEST = 0, + MBOX_STATUS_SUCCESS = 0x80000000, + MBOX_STATUS_ERROR = 0x80000001, +}; + +enum MBOX_PROPERTY_TAG{ + MBOX_PROPERTY_END = 0, + MBOX_GET_FIRMWARE_REVISION = 0x00000001, + + MBOX_SET_CURSOR_INFO = 0x00008010, + MBOX_SET_CURSOR_STATE = 0x00008011, + + MBOX_GET_BOARD_MODEL = 0x00010001, + MBOX_GET_BOARD_REVISION = 0x00010002, + MBOX_GET_BOARD_MAC_ADDRESS = 0x00010003, + MBOX_GET_BOARD_SERIAL = 0x00010004, + MBOX_GET_ARM_MEMORY = 0x00010005, + MBOX_GET_VC_MEMORY = 0x00010006, + MBOX_GET_CLOCKS = 0x00010007, + MBOX_GET_POWER_STATE = 0x00020001, + MBOX_GET_TIMING = 0x00020002, + MBOX_SET_POWER_STATE = 0x00028001, + MBOX_GET_CLOCK_STATE = 0x00030001, + MBOX_GET_CLOCK_RATE = 0x00030002, + MBOX_GET_VOLTAGE = 0x00030003, + MBOX_GET_MAX_CLOCK_RATE = 0x00030004, + MBOX_GET_MAX_VOLTAGE = 0x00030005, + MBOX_GET_TEMPERATURE = 0x00030006, + MBOX_GET_MIN_CLOCK_RATE = 0x00030007, + MBOX_GET_MIN_VOLTAGE = 0x00030008, + MBOX_GET_TURBO = 0x00030009, + MBOX_GET_MAX_TEMPERATURE = 0x0003000a, + MBOX_GET_STC = 0x0003000b, + MBOX_ALLOCATE_MEMORY = 0x0003000c, + MBOX_LOCK_MEMORY = 0x0003000d, + MBOX_UNLOCK_MEMORY = 0x0003000e, + MBOX_RELEASE_MEMORY = 0x0003000f, + MBOX_EXECUTE_CODE = 0x00030010, + MBOX_EXECUTE_QPU = 0x00030011, + MBOX_SET_ENABLE_QPU = 0x00030012, + MBOX_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, + MBOX_GET_EDID_BLOCK = 0x00030020, + MBOX_GET_CUSTOMER_OTP = 0x00030021, + MBOX_GET_DOMAIN_STATE = 0x00030030, + MBOX_SET_CLOCK_STATE = 0x00038001, + MBOX_SET_CLOCK_RATE = 0x00038002, + MBOX_SET_VOLTAGE = 0x00038003, + MBOX_SET_TURBO = 0x00038009, + MBOX_SET_CUSTOMER_OTP = 0x00038021, + MBOX_SET_DOMAIN_STATE = 0x00038030, + MBOX_GET_GPIO_STATE = 0x00030041, + MBOX_SET_GPIO_STATE = 0x00038041, + MBOX_SET_SDHOST_CLOCK = 0x00038042, + MBOX_GET_GPIO_CONFIG = 0x00030043, + MBOX_SET_GPIO_CONFIG = 0x00038043, + MBOX_GET_PERIPH_REG = 0x00030045, + MBOX_SET_PERIPH_REG = 0x00038045, + + + /* Dispmanx TAGS */ + MBOX_FRAMEBUFFER_ALLOCATE = 0x00040001, + MBOX_FRAMEBUFFER_BLANK = 0x00040002, + MBOX_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, + MBOX_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, + MBOX_FRAMEBUFFER_GET_DEPTH = 0x00040005, + MBOX_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006, + MBOX_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007, + MBOX_FRAMEBUFFER_GET_PITCH = 0x00040008, + MBOX_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, + MBOX_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, + MBOX_FRAMEBUFFER_GET_PALETTE = 0x0004000b, + MBOX_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, + MBOX_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010, + MBOX_FRAMEBUFFER_RELEASE = 0x00048001, + MBOX_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, + MBOX_FRAMEBUFFER_TEST_DEPTH = 0x00044005, + MBOX_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006, + MBOX_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, + MBOX_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, + MBOX_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, + MBOX_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, + MBOX_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, + MBOX_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, + MBOX_FRAMEBUFFER_SET_DEPTH = 0x00048005, + MBOX_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006, + MBOX_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007, + MBOX_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + MBOX_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + MBOX_FRAMEBUFFER_SET_PALETTE = 0x0004800b, + MBOX_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + MBOX_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, + MBOX_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + MBOX_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + + MBOX_VCHIQ_INIT = 0x00048010, + + MBOX_GET_COMMAND_LINE = 0x00050001, + MBOX_GET_DMA_CHANNELS = 0x00060001, +}; +/* + * Mailbox Read/Write Peek Sender Status Config + * 0 0x00 0x10 0x14 0x18 0x1c + * 1 0x20 0x30 0x34 0x38 0x3c + */ + +#define MBOX_READ_CHANNEL_MASK 15 +#define MBOX_WRITE_CHANNEL_MASK 15 +#define MBOX_WRITE_ADDR_MASK (~15) +#define MBOX_READ_ADDR_MASK (~15) +#define MBOX_STATUS_FULL_MASK 0x80000000 +#define MBOX_STATUS_EMPTY_MASK 0x40000000 +typedef struct{ + uint32_t read; + uint32_t unused[5]; + uint32_t status; + uint32_t config; + uint32_t write; +}__attribute__((packed)) MBox_register; + +/* 0 4 8 12 16 20 24 28 32 + +---------------------------------------------------------------+ +0x00 | Buffer Size | + +---------------------------------------------------------------+ +0x04 | Request/Response Code | + +---------------------------------------------------------------+ +0x08 | Tags | +... \\ \\ +0xXX | Tags | + +---------------------------------------------------------------+ +0xXX+4 | End Tag (0) | + +---------------------------------------------------------------+ +0xXX+8 | Padding | +... \\ \\ +0xXX+16| Padding | + +---------------------------------------------------------------+ +*/ +#define MBOX_TAG_REQUEST 0 +typedef struct{ + uint32_t id; + uint32_t value_size; + uint32_t code; + uint8_t values[0]; +}MBox_tag; + +typedef struct{ + uint32_t buf_size; + uint32_t code; + uint8_t buf[0]; +}MBox_buffer; + +extern void MBox_get_board_revision(uint32_t*); +extern void MBox_get_arm_memory(uint32_t*); + +#endif diff --git a/lab6/include/peripherals/mini_uart.h b/lab6/include/peripherals/mini_uart.h new file mode 100644 index 000000000..696c0b7fe --- /dev/null +++ b/lab6/include/peripherals/mini_uart.h @@ -0,0 +1,35 @@ +#ifndef _MINI_UART_H_ +#define _MINI_UART_H_ + +#include "types.h" +#include "kernel/sched/sched.h" +#include "asm.h" +#include "peripherals/iomapping.h" +#include "debug/debug.h" +#include "lib/print.h" +#include "lib/ring_buffer.h" + +#define SYSTEM_CLOCK_RATE (250000000) +#define BAUD_RATE 115200 +#define BAUD_RATE_REG (SYSTEM_CLOCK_RATE / (8 * BAUD_RATE) - 1) +#define TX 1 +#define RX 2 +extern void mini_uart_init(); +extern uint8_t mini_uart_read(void); +extern void mini_uart_write(uint8_t); +extern ssize_t write_bytes(uint8_t *, size_t); +extern void write_str(char *); +extern void write_hex(uint64_t); +extern void delay_cycles(uint64_t); +extern void disable_mini_uart_irq(uint32_t); +extern void enable_mini_uart_irq(uint32_t); +extern void mini_uart_irq_init(); +extern void mini_uart_irq_read(); +extern size_t mini_uart_get_rx_len(); +extern uint8_t mini_uart_aio_read(void); +extern size_t mini_uart_get_tx_len(); +extern void enable_mini_uart_rx_irq(); +extern void disable_mini_uart_rx_irq(); +extern void mini_uart_rx_softirq_callback(); + +#endif diff --git a/lab6/include/types.h b/lab6/include/types.h new file mode 100644 index 000000000..c565b425b --- /dev/null +++ b/lab6/include/types.h @@ -0,0 +1,45 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) (((uint64_t)(val) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_DOWN(val, align) ((uint64_t)(val) & ~((align) - 1)) + +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define min(x, y) ((x) < (y) ? (x) : (y)) + +#endif diff --git a/lab6/init/Makefile b/lab6/init/Makefile new file mode 100644 index 000000000..e5b218aa8 --- /dev/null +++ b/lab6/init/Makefile @@ -0,0 +1,24 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + kernel_init.o + +all: $(OBJECTS) + +%.o: %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab6/init/kernel_init.c b/lab6/init/kernel_init.c new file mode 100644 index 000000000..81b105fb1 --- /dev/null +++ b/lab6/init/kernel_init.c @@ -0,0 +1,25 @@ +#include "init/kernel_init.h" + +extern int __heap_start; +void kernel_init(void *dtb){ + mini_uart_init(); + INFO("core timer start initialization..."); + init_core_timer(); + INFO("uart interrupt start initialization..."); + mini_uart_irq_init(); + + local_irq_enable(); + INFO("kernel start initialization..."); + + // memory management initialization + mm_init(dtb); + + // change ttbr1_el1 to 4-level + page_init(); + + // filesystem initialize + fs_init(); + fdt_parser(dtb, fdt_initrdfs_callback); + return; +} + diff --git a/lab6/initramfs.cpio b/lab6/initramfs.cpio new file mode 100644 index 000000000..b3bf061ff Binary files /dev/null and b/lab6/initramfs.cpio differ diff --git a/lab6/kernel/.gdb_history b/lab6/kernel/.gdb_history new file mode 100644 index 000000000..0e9b7b5ce --- /dev/null +++ b/lab6/kernel/.gdb_history @@ -0,0 +1,25 @@ +file ./../build/kernel8.elf +target remote:1234 +x/gx simple_shell +disassemble simple_shell +b* 0x0000000000081e1c +c +x/i 0x100000 +ni +x/i 0x100000 +b* 0x100008 +ni +quit +file ./../build/kernel8.elf +target remote:1234 +disassemble simple_shell +b* 0x0000000000081e1c +c +ni +x/i 0x1000000 +x/i 0x100000 +b*0x100008 +ni +ni +ni +quit diff --git a/lab6/kernel/Makefile b/lab6/kernel/Makefile new file mode 100644 index 000000000..910d3329b --- /dev/null +++ b/lab6/kernel/Makefile @@ -0,0 +1,42 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin \ + -g +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + shell.o \ + reboot.o \ + main.o \ + start.o \ + entry.o \ + syscall_test.o \ + syscall_table.o \ + timer.o \ + irq_handler.o \ + signal.o \ + fault.o \ + +.PHONY: all sched +all: $(OBJECTS) sched + +sched: + $(MAKE) -C sched OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab6/kernel/entry.S b/lab6/kernel/entry.S new file mode 100644 index 000000000..753ab4c5b --- /dev/null +++ b/lab6/kernel/entry.S @@ -0,0 +1,189 @@ + .macro ventry label + .align 7 + b \label + .endm + + + .macro save_all + sub sp, sp, 17 * 16 + stp x0, x1, [sp ,16 * 0] + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + mrs x24, sp_el0 + stp x30, x24, [sp, 16 * 15] + + mrs x24, spsr_el1 + mrs x25, elr_el1 + stp x24, x25, [sp, 16 * 16] + .endm + + .macro load_all + ldp x24, x25, [sp, 16 * 16] + msr spsr_el1, x24 + msr elr_el1, x25 + + ldp x30, x24, [sp, 16 * 15] + msr sp_el0, x24 + + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + + add sp, sp, 17 * 16 + + .endm + +.global task_load_all +task_load_all: + load_all + eret + +.global kthread_trampoline +kthread_trampoline: + bl local_irq_enable + mov x0, x19 + bl kthread_start + +// exception vector table +.align 11 +.global EL1_exception_vector_table +EL1_exception_vector_table: +// Exception from the current EL while using SP_EL0 + ventry invalid_handler // Synchronous EL1t + ventry invalid_handler // IRQ EL1t + ventry invalid_handler // FIQ EL1t + ventry invalid_handler // Error EL1t + +// Exception from the current EL while using SP_ELx + ventry el1_sync_handler // Synchronous EL1h + ventry el1_irq_handler // IRQ EL1h + ventry invalid_handler // FIQ EL1h + ventry invalid_handler // Error EL1h + +// Exception from a lower EL at least one lower EL is AArch64 + ventry el0_sync_handler // Synchronous 64-bit EL0 + ventry el0_irq_handler // IRQ 64-bit EL0 + ventry invalid_handler // FIQ 64-bit EL0 + ventry invalid_handler // Error 64-bit EL0 + +// Exception from a lower EL and all lower ELs are AArch32 + ventry invalid_handler // Synchronous 32-bit EL0 + ventry invalid_handler // IRQ 32-bit EL0 + ventry invalid_handler // FIQ 32-bit EL0 + ventry invalid_handler // Error 32-bit EL0 + +el1_sync_invalid_handler: + mov x0, 135 +invalid_handler: + save_all + mrs x1, esr_el1 + mrs x2, elr_el1 + mrs x3, spsr_el1 + mrs x4, sp_el0 + mov x5, sp + bl err_handler + load_all + eret + + +el0_irq_handler: +el1_irq_handler: + save_all + bl irq_handler + bl schedule + bl handle_signal + load_all + eret + +el1_sync_handler: +el0_sync_handler: + save_all + mrs x24, esr_el1 + lsr x24, x24, #26 + cmp x24, #0x15 + + b.eq svc_handler + + mrs x0, esr_el1 + mrs x1, far_el1 + bl fault_handler + + b end +svc_handler: + bl local_irq_enable + bl syscall_handler + str x0, [sp] + +end: + bl handle_signal + load_all + eret + +.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 sigreturn_trampoline +sigreturn_trampoline: + mov x8, 20 + svc 0 + +sigreturn_error: + b sigreturn_error + +.global switch_ttbr0 +switch_ttbr0: + dsb ish + msr ttbr0_el1, x0 + tlbi vmalle1is + dsb ish + isb + ret + diff --git a/lab6/kernel/fault.c b/lab6/kernel/fault.c new file mode 100644 index 000000000..2f0f932a2 --- /dev/null +++ b/lab6/kernel/fault.c @@ -0,0 +1,11 @@ +#include "kernel/fault.h" + +// far save the address that trigger data abort +void fault_handler(uint64_t esr, uint64_t far){ + uint32_t ec = esr >> 26; // error code + if(ec == FAULT_DATA_ABORT_LOW_EL || ec == FAULT_INSTR_ABORT_LOW_EL || ec == FAULT_INSTR_ABORT || ec == FAULT_DATA_ABORT){ + do_mem_abort(esr, far); + }else{ + INFO("unknown error: ec = %p, far: %p, esr: %p", ec, far, esr); + } +} diff --git a/lab6/kernel/irq_handler.c b/lab6/kernel/irq_handler.c new file mode 100644 index 000000000..80ec9d121 --- /dev/null +++ b/lab6/kernel/irq_handler.c @@ -0,0 +1,190 @@ +#include "kernel/irq_handler.h" +struct softirq_status softirq_s = { + .pending = 0, + .in_softirq = 0 +}; + +irq_funcptr softirq_vec[END_OF_LIST] = { + timer_softirq_callback, + mini_uart_rx_softirq_callback, +}; +uint64_t irq_count[END_OF_LIST] = {0, 0, 0}; + +void enter_softirq(){ + softirq_s.in_softirq = 1; +} + +void exit_softirq(){ + softirq_s.in_softirq = 0; +} + +uint8_t in_softirq(){ + return softirq_s.in_softirq; +} + +uint8_t has_softirq_pending(){ + return softirq_s.pending ? 1 : 0; +} + +uint16_t get_softirq_pending(){ + return softirq_s.pending; +} + +void set_softirq_pending(uint16_t val){ + softirq_s.pending = val; +} + + +void add_softirq_task(uint32_t softirq_nr){ + softirq_s.pending |= (1 << softirq_nr); +} + +void do_softirq(){ + uint16_t try = 0; + volatile uint16_t pending; + uint16_t softirq_bit; + irq_funcptr softirq_handler; + + while(try < MAX_SOFTIRQ_TRY){ + pending = get_softirq_pending(); + set_softirq_pending(0); + + local_irq_enable(); + while(pending){ + softirq_bit = ffs16(pending); + softirq_handler = softirq_vec[softirq_bit]; + softirq_handler(); + pending &= ~(1 << softirq_bit); + } + local_irq_disable(); + try++; + } +} + +void do_irq(uint32_t nr, irq_funcptr do_hardirq,irq_funcptr enable_device_irq , irq_funcptr disable_device_irq){ + disable_device_irq(); + irq_count[nr]++; + add_softirq_task(nr); + do_hardirq(); + + if(!in_softirq() && has_softirq_pending()){ + enter_softirq(); + do_softirq(); + exit_softirq(); + } + + enable_device_irq(); +} + +void irq_handler(){ + uint32_t irq_pending_1 = IO_MMIO_read32(IRQ_PENDING_1); + uint32_t core0_irq_source = IO_MMIO_read32(CORE0_IRQ_SOURCE); + uint32_t auxirq, uart_irq_type; + /* + uint32_t irq_pending_2 = IO_MMIO_read32(IRQ_PENDING_2); + uint32_t irq_basic_pending = IO_MMIO_read32(IRQ_BASIC_PENDING); + uint32_t core1_irq_source = IO_MMIO_read32(CORE1_IRQ_SOURCE); + uint32_t core2_irq_source = IO_MMIO_read32(CORE2_IRQ_SOURCE); + uint32_t core3_irq_source = IO_MMIO_read32(CORE3_IRQ_SOURCE); + uint32_t core0_fiq_source = IO_MMIO_read32(CORE0_FIQ_SOURCE); + uint32_t core1_fiq_source = IO_MMIO_read32(CORE1_FIQ_SOURCE); + uint32_t core2_fiq_source = IO_MMIO_read32(CORE2_FIQ_SOURCE); + uint32_t core3_fiq_source = IO_MMIO_read32(CORE3_FIQ_SOURCE); + */ + + + if(core0_irq_source & 2){ + //core timer interrupt + do_irq(CORE0_TIMER, core_timer_irq_handler, enable_core_timer_irq, disable_core_timer_irq); + }else if(irq_pending_1 & (1 << 29)){ + auxirq = IO_MMIO_read32(AUX_IRQ); + if(auxirq & 1){ + uart_irq_type = (IO_MMIO_read32(AUX_MU_IIR_REG) >> 1) & (0b11); + if(uart_irq_type == RX){ + // Receiver holds valid byte + do_irq(MINI_UART_RX, mini_uart_irq_read, enable_mini_uart_rx_irq, disable_mini_uart_rx_irq); + }else{ + irq_count[UNKNOWN_IRQ]++; + LOG("UART interrupt"); + while(1); + } + }else{ + irq_count[UNKNOWN_IRQ]++; + LOG("Unkown AUX interrupt, DAIF: %x", get_DAIF()); + } + } + else{ + irq_count[UNKNOWN_IRQ]++; + LOG("Unkown interrupt"); + } +} + +void err_handler(uint64_t type, uint64_t esr, uint64_t elr, uint64_t spsr_el1, uint64_t sp_el0, uint64_t sp){ + struct task_struct *cur = get_current(); + struct trap_frame *trap_frame = get_trap_frame(cur); + write_str("unkown irq count: "); + write_hex(irq_count[UNKNOWN_IRQ]); + write_str("\r\n"); + + write_str("pid: "); + write_hex(cur->thread_info.pid); + write_str("\r\n"); + + write_str("trap frame: "); + write_hex((uint64_t)get_trap_frame(cur)); + write_str("\r\n"); + + write_str("cur->ctx.lr: "); + write_hex(cur->ctx.lr); + write_str("\r\n"); + + write_str("cur->ctx.sp: "); + write_hex(cur->ctx.sp); + write_str("\r\n"); + + write_str("cur->ctx.fp: "); + write_hex(cur->ctx.fp); + write_str("\r\n"); + + write_str("trap_frame->x0: "); + write_hex(trap_frame->x0); + write_str("\r\n"); + + write_str("trap_frame->x30: "); + write_hex(trap_frame->x30); + write_str("\r\n"); + + write_str("trap_frame->x29: "); + write_hex(trap_frame->x29); + write_str("\r\n"); + + write_str("kernel stack: "); + write_hex((uint64_t)cur->stack); + write_str("\r\n"); + + write_str("type: "); + write_hex(type); + write_str("\r\n"); + + write_str("esr_el1: "); + write_hex(esr); + write_str("\r\n"); + + write_str("elr_el1: "); + write_hex(get_ELR_EL1()); + write_str("\r\n"); + + write_str("spsr_el1: "); + write_hex(spsr_el1); + write_str("\r\n"); + + write_str("sp_el0: "); + write_hex(sp_el0); + write_str("\r\n"); + + write_str("sp: "); + write_hex(sp); + write_str("\r\n"); + + while(1); +} diff --git a/lab6/kernel/linker.ld b/lab6/kernel/linker.ld new file mode 100644 index 000000000..757465f77 --- /dev/null +++ b/lab6/kernel/linker.ld @@ -0,0 +1,64 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0xffff000000000000; /* kernel space 0xffff000000000000 ~ 0xffffffffffffffff */ + . += 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __kernel_image_start = .; + __EL1_stack_size = 0x4000; + __EL1_stack = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + . = ALIGN(0x1000); + __bss_end = .; + __reserved_page_table_start = .; + __PGD_start = .; + . = . + 4096; + __PGD_end = .; + + __PUD_start = .; + . = . + 4096; + __PUD_end = .; + + __PMD_start = .; + . = . + 4096 * 2; + __PMD_end = .; + + __PTE_start = .; + . = . + 4096 * 1024; + __PTE_end = .; + + . = ALIGN(0x1000); + __reserved_page_table_end = .; + __kernel_image_end = .; + __heap_start = .; + +} diff --git a/lab6/kernel/main.c b/lab6/kernel/main.c new file mode 100644 index 000000000..6e71324a6 --- /dev/null +++ b/lab6/kernel/main.c @@ -0,0 +1,29 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "init/kernel_init.h" +#include "debug/debug.h" +#include "kernel/shell.h" +#include "kernel/sched/sched.h" +#include "kernel/sched/kthread.h" + +void kernel_main_thread(void){ + for(uint32_t i = 0 ; i < 10 ; i++){ + INFO("create kthread kthread_test"); + kthread_create(kthread_test); + } + INFO("create kthread simple_shell"); + kthread_create(simple_shell); +} + +void kernel_main(void *dtb){ + dtb += UPPER_ADDR_SPACE_BASE; + kernel_init(dtb); + kthread_init(); + DEBUG_KERNEL_START(); + + INFO("create kernel main thread"); + kthread_create(kernel_main_thread); + + kthread_idle(); +} + diff --git a/lab6/kernel/reboot.c b/lab6/kernel/reboot.c new file mode 100644 index 000000000..2511cc06e --- /dev/null +++ b/lab6/kernel/reboot.c @@ -0,0 +1,14 @@ +#include "types.h" +#include "peripherals/iomapping.h" +#include "kernel/reboot.h" + +void reboot(int ticks){ + unsigned int pm_rstc,pm_wdog; + pm_rstc = IO_MMIO_read32(PM_RSTC); + + pm_wdog = PM_PASSWORD | (ticks & PM_WDOG_TIME_SET); + pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; + + IO_MMIO_write32(PM_RSTC, pm_rstc); + IO_MMIO_write32(PM_WDOG, pm_wdog); +} diff --git a/lab6/kernel/sched/Makefile b/lab6/kernel/sched/Makefile new file mode 100644 index 000000000..6b4756fe2 --- /dev/null +++ b/lab6/kernel/sched/Makefile @@ -0,0 +1,30 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../../include +OBJECTS = \ + sched.o \ + kthread.o \ + task.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab6/kernel/sched/kthread.c b/lab6/kernel/sched/kthread.c new file mode 100644 index 000000000..558f1ba89 --- /dev/null +++ b/lab6/kernel/sched/kthread.c @@ -0,0 +1,147 @@ +#include "kernel/sched/kthread.h" + +extern void kthread_trampoline(); +extern int __EL1_stack; +extern int __EL1_stack_size; +void kthread_init(){ + LOG("kthread_init enter"); + volatile uint64_t daif; + struct task_struct* kthread = (struct task_struct*)kmalloc(sizeof(struct task_struct)); + + daif = local_irq_disable_save(); + kthread->stack = (void*)((uint64_t)&__EL1_stack - (uint64_t)&__EL1_stack_size); + LOG("kthread->stack: %p", kthread->stack); + + // initialize thread_info + kthread->thread_info.pid = get_pid_counter(); + kthread->thread_info.state = TASK_RUNNING; + + // initialize mm + kthread->mm = NULL; + + // initialize relationship + kthread->parent = NULL; + kthread->child = NULL; + INIT_LIST_HEAD(&kthread->siblings); + + // initialize schedule info + kthread->sched_info.rticks = 0; + kthread->sched_info.priority = 1; + kthread->sched_info.counter = kthread->sched_info.priority; + + list_add_tail(&kthread->list, &task_list); + + // initialzie singal + sigpending_init(&kthread->sigpending); + default_sighand_init(&kthread->sighandler); + + set_tpidr_el1((uint64_t)kthread); + local_irq_restore(daif); + LOG("kthread_init end"); +} + +void kthread_destroy(struct task_struct* task){ +// LOG("kthread_destroy %l", task->thread_info.pid); + list_del(&task->list); + free_pages(task->stack, 1); + kfree(task); +} +void _kthread_remove_zombies(){ + struct list_head* node; + struct task_struct* zombie; + volatile uint64_t daif; + //volatile uint64_t daif; + //daif = local_irq_disable_save(); + local_irq_disable(); + while(!list_empty(&zombies)){ + zombie = list_first_entry(&zombies, struct task_struct, zombie); + LOG("Remove %l", zombie->thread_info.pid); + list_del(zombies.next); + if(zombie->mm == NULL) kthread_destroy(zombie); + else task_destroy(zombie); + } + local_irq_enable(daif); + //local_irq_restore(daif); +} + +void kthread_idle(){ + while(1){ + //LOG("kthread_idle"); + _kthread_remove_zombies(); + preempt_schedule(); + } +} + +void kthread_test(){ + struct task_struct* cur; + cur = get_current(); + for(uint32_t i = 0 ; i < 10 ; i++){ + printf("%u: pid: %l\r\n",i , cur->thread_info.pid); + for(uint32_t j = 0 ; j < 100000 ; j ++){ + asm volatile("nop"); + } + } +} + +uint64_t kthread_create(kthread_func func){ + LOG("kthread enter"); + volatile uint64_t daif; + struct task_struct* kthread = (struct task_struct*)kmalloc(sizeof(struct task_struct)); + + // initialize kernel stack + kthread->stack = alloc_pages(1); + + // initialize thread_info + kthread->thread_info.pid = get_pid_counter(); + kthread->thread_info.state = TASK_RUNNING; + + // initialize thread context + kthread->ctx.lr = (uint64_t)kthread_trampoline; + kthread->ctx.x19 = (uint64_t)func; + kthread->ctx.sp = (uint64_t)kthread->stack + PAGE_SIZE * 2; + kthread->ctx.fp = kthread->ctx.sp; + + // initialize mm + kthread->mm = NULL; + + // initialize relationship + kthread->parent = NULL; + kthread->child = NULL; + INIT_LIST_HEAD(&kthread->siblings); + + // initialize schedule info + kthread->sched_info.rticks = 0; + kthread->sched_info.priority = 1; + kthread->sched_info.counter = kthread->sched_info.priority; + + daif = local_irq_disable_save(); + list_add_tail(&kthread->list, &task_list); + local_irq_restore(daif); + + // initialzie singal + sigpending_init(&kthread->sigpending); + default_sighand_init(&kthread->sighandler); + + LOG("kthread end"); + add_task_to_rq(kthread); + return 0; +} + +void kthread_start(kthread_func func){ + func(); + kthread_exit(); +} + +void kthread_exit(){ + volatile uint64_t daif; + LOG("kthread_exit start"); + struct task_struct* cur; + cur = get_current(); + cur->thread_info.state = TASK_DEAD; + + daif = local_irq_disable_save(); + list_add_tail(&cur->zombie, &zombies); + local_irq_restore(daif); + LOG("kthread_exit end"); + preempt_schedule(); +} diff --git a/lab6/kernel/sched/sched.c b/lab6/kernel/sched/sched.c new file mode 100644 index 000000000..526e9d51d --- /dev/null +++ b/lab6/kernel/sched/sched.c @@ -0,0 +1,114 @@ +#include "kernel/sched/sched.h" + +LIST_HEAD(zombies); +LIST_HEAD(rq); +LIST_HEAD(task_list); +uint64_t pid_count = 0; +int need_sched = 0; +struct task_struct* user_init = NULL; + +void add_task_to_rq(struct task_struct *task){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + task->thread_info.state = TASK_RUNNING; + + list_add_tail(&task->sched_info.sched_list, &rq); + need_sched = 1; + local_irq_restore(daif); +} + +struct task_struct* pick_next_task_from_rq(){ + if(!list_empty(&rq)) + return list_first_entry(&rq, struct task_struct, sched_info.sched_list); + else + return NULL; +} +extern void switch_ttbr0(uint64_t); +void switch_mm(struct task_struct* next){ + pgdval_t* pgd; + if(next->mm){ + pgd = next->mm->pgd; + if(pgd == 0){ + printf("switch_mm error\r\n"); + while(1); + } + switch_ttbr0(virt_to_phys(pgd)); + } +} + +void schedule(){ + struct task_struct* current, *next; + // prevent running scheduler in softirq + if(in_softirq()){ + return; + } + + if(need_sched){ + need_sched = 0; + next = pick_next_task_from_rq(); + + // add current task to schdule list + current = get_current(); + if( current != NULL && current->thread_info.state != TASK_DEAD && next != NULL){ + current->sched_info.counter = current->sched_info.priority; + list_add_tail(¤t->sched_info.sched_list, &rq); + }else if(current == NULL){ + printf("schedule error\r\b"); + while(1); + } + + // context switch + if(next != NULL){ + list_del(&next->sched_info.sched_list); + switch_mm(next); + switch_to(current, next); + } + } +} + +void preempt_schedule(){ + local_irq_disable(); + need_sched = 1; + schedule(); + local_irq_enable(); +} + +pid_t get_pid_counter(void){ + pid_t ret; + ret = pid_count++; + return ret; +} + +struct task_struct* find_task_by_pid(uint64_t pid){ + struct list_head *node; + struct task_struct *tmp_task; + uint64_t daif; + + daif = local_irq_disable_save(); + list_for_each(node, &task_list){ + tmp_task = list_entry(node, struct task_struct, list); + if(tmp_task->thread_info.pid == pid && tmp_task->thread_info.state != TASK_DEAD){ + local_irq_restore(daif); + return tmp_task; + } + } + local_irq_restore(daif); + return NULL; +} + + +/* debug */ +void print_rq(void){ + struct list_head *node; + struct task_struct *tmp_task; + struct task_pid *tmp_task_pid; + volatile uint64_t daif; + // In printf, interrupt will be enable, so we can't directly print run queue + daif = local_irq_disable_save(); + list_for_each(node, &task_list){ + tmp_task = list_entry(node, struct task_struct, list); + printf("%l ", tmp_task->thread_info.pid); + } + local_irq_restore(daif); + printf("\r\n"); +} diff --git a/lab6/kernel/sched/task.c b/lab6/kernel/sched/task.c new file mode 100644 index 000000000..8a75af13a --- /dev/null +++ b/lab6/kernel/sched/task.c @@ -0,0 +1,503 @@ +#include "kernel/sched/task.h" + +extern void task_load_all(void); +extern void switch_ttbr0(uint64_t); + +void task_init(){ +} + +uint64_t task_dup(struct task_struct* parent){ + LOG("task_dup start"); + volatile uint64_t daif; + struct task_struct* child = (struct task_struct*)kmalloc(sizeof(struct task_struct)); + struct vm_area_struct* pvma, *ppvma; + struct trap_frame *pptrap_frame; + struct trap_frame *pctrap_frame; + uint64_t child_pid; + + daif = local_irq_disable_save(); + + // initialize mm + child->mm = mm_struct_create(); + // copy vma in parent->mm to child->mm except for user stack1 + dup_mm_struct(child->mm, parent->mm); + // create user stack vma + //dup_vma_stack(child->mm, parent->mm); + //create vc ram identity mapping +// create_vma_vc(child->mm); + + + // initialize child's trap frame and kernel stack + child->stack = alloc_pages(1); + memcpy(child->stack, parent->stack, PAGE_SIZE * 2); + + pptrap_frame = get_trap_frame(parent); + pctrap_frame = get_trap_frame(child); + LOG("parent kernel stack: %p", parent->stack + PAGE_SIZE * 2); + LOG("parent trap frame: %p", pptrap_frame); + LOG("child trap stack: %p", child->stack + PAGE_SIZE * 2); + LOG("child trap frame: %p", pctrap_frame); + + // set child's return value to 0 + pctrap_frame->x0 = 0; + + // initialize thread_info + child->thread_info.pid = get_pid_counter(); + child_pid = child->thread_info.pid; + child->thread_info.state = TASK_RUNNING; + + // initialize thread context + // directly back to user space + memcpy(&child->ctx, &parent->ctx, sizeof(struct task_ctx)); + child->ctx.lr = (uint64_t)task_load_all; + child->ctx.sp = (uint64_t)pctrap_frame; + child->ctx.fp = (uint64_t)pctrap_frame; + + // initialize child's relationship + child->parent = parent; + child->child = NULL; + INIT_LIST_HEAD(&child->siblings); + + // initialize parent's relationship + if(parent->child != NULL){ + list_add_tail(&child->siblings, &parent->child->siblings); + }else{ + parent->child = child; + } + + // initialize schedule info + child->sched_info.rticks = 0; + child->sched_info.priority = parent->sched_info.priority ; + child->sched_info.counter = child->sched_info.priority; + + // initialzie singal + sigpending_init(&child->sigpending); + memcpy(&child->sighandler, &parent->sighandler, sizeof(struct sighand_struct)); + + // insert task to run queue and task list + list_add_tail(&child->list, &task_list); + local_irq_restore(daif); + add_task_to_rq(child); + LOG("task_dup end"); + return child_pid; +} + +void task_kill(uint64_t pid){ + LOG("task_kill start"); + volatile uint64_t daif; + struct task_struct* target; + struct task_struct* current; + + target = find_task_by_pid(pid); + if(target == NULL || (target->thread_info.state == TASK_DEAD)) return; + + current = get_current(); + + daif = local_irq_disable_save(); + + target->thread_info.state = TASK_DEAD; + list_add_tail(&target->zombie, &zombies); + if(target != current){ + list_del(&target->sched_info.sched_list); + } + + local_irq_restore(daif); + + LOG("task_kill end"); + + preempt_schedule(); +} + +void task_exit(){ + volatile uint64_t daif; + LOG("task_exit start"); + struct task_struct* cur; + cur = get_current(); + cur->thread_info.state = TASK_DEAD; + + daif = local_irq_disable_save(); + list_add_tail(&cur->zombie, &zombies); + local_irq_restore(daif); + LOG("task_exit end"); + preempt_schedule(); +} + +void task_destroy(struct task_struct* task){ + struct vm_area_struct *vma; + struct list_head* node; + struct task_struct* child; + + list_del(&task->list); + + // free kernel stack + free_pages(task->stack, 1); + + // free mm + mm_struct_destroy(task->mm); + + //unlink from parent and sibliings and set re-parent + if(task->parent){ + //unlink from parent + if(task->parent->child == task){ + child = list_first_entry(&task->siblings, struct task_struct, siblings); + task->parent->child = child; + list_del(&task->siblings); + } + // re-parent + if(task->child){ + task->child->parent = task->parent; + list_for_each(node, &task->child->siblings){ + child = list_entry(node, struct task_struct, siblings); + child->parent = task->parent; + } + list_splice_tail(&task->child->siblings, &task->parent->child->siblings); + list_add_tail(&task->child->siblings, &task->parent->child->siblings); + } + }else{ + if(task->child){ + list_for_each(node, &task->child->siblings){ + child = list_entry(node, struct task_struct, siblings); + child->parent = task->child; + } + task->child->child = list_first_entry(&task->child->siblings, struct task_struct, siblings); + list_del(&task->child->siblings); + task->child->parent = NULL; + } + } + // free signal pending queue + free_sigpendings(&task->sigpending); + kfree(task); + if(user_init == task) user_init = NULL; +} + +int task_exec(const char* name, char* const argv[]){ + LOG("enter task_exec"); + LOG("file name: %s", name); + int ret = -1; + struct list_head* node; + struct vm_area_struct *vma; + struct task_struct* current = get_current(); + struct trap_frame *trap_frame = get_trap_frame(current); + volatile uint64_t daif; + char* tmp_name; + size_t s; + + // since we will destroy pgb and it will cause page table broken, + // we have to save the name in userspace first + tmp_name = kmalloc(strlen(name) + 10); + strcpy(tmp_name, name); + // initialize mm + if(s = initrdfs_filesize((char*)tmp_name)){ + mm_struct_destroy(current->mm); + current->mm = mm_struct_create(); + // load executable + // create code memory area + vma = create_vma_code(current->mm,(char*)tmp_name); + trap_frame->elr_el1 = (uint64_t)vma->vm_start; + //create vc ram identity mapping + create_vma_vc(current->mm); + + // create user stack + vma = create_vma_stack(current->mm); + trap_frame->sp_el0 = (uint64_t)vma->vm_end; + + // initialize Saved Program Status Register el1 + trap_frame->spsr_el1 = 0; + ret = 0; + } + kfree(tmp_name); + + // initialize signal + default_sighand_init(¤t->sighandler); + // switch ttbr0_el1 before return to user space + daif = local_irq_disable_save(); + switch_ttbr0(virt_to_phys(current->mm->pgd)); + local_irq_restore(daif); + LOG("end task_exec"); + return ret; +} + + +void run_init_task(char* filename){ + struct vm_area_struct* vma; + uint64_t user_entry, user_sp; + struct trap_frame* ptrap_frame; + volatile uint64_t daif; + LOG("run_init_task enter"); + LOG("Size of struct trap_frame: %x", sizeof(struct trap_frame)); + + daif = local_irq_disable_save(); + struct task_struct* task = (struct task_struct*)kmalloc(sizeof(struct task_struct)); + + // initialize mm + task->mm = mm_struct_create(); + // load executable + // create code memory area + vma = create_vma_code(task->mm, filename); + user_entry = (uint64_t)vma->vm_start; + //create vc ram identity mapping + create_vma_vc(task->mm); + + // create user stack + vma = create_vma_stack(task->mm); + user_sp = (uint64_t)vma->vm_end; + + LOG("vma: %p, user_sp: %p, user_entry: %p", vma, user_sp, user_entry); + // create kernel stack + task->stack = alloc_pages(1); + + // initialize trap frame in kernel stack + ptrap_frame = (struct trap_frame*)get_trap_frame(task); + ptrap_frame->spsr_el1 = 0x0; + ptrap_frame->sp_el0 = user_sp; + ptrap_frame->elr_el1 = user_entry; + + // initialize thread_info + task->thread_info.pid = get_pid_counter(); + task->thread_info.state = TASK_RUNNING; + + // initialize thread context + task->ctx.lr = (uint64_t)task_load_all; + task->ctx.sp = (uint64_t)get_trap_frame(task); + task->ctx.fp = task->ctx.sp; + + // initialize relationship + task->parent = NULL; + task->child = NULL; + INIT_LIST_HEAD(&task->siblings); + + // initialize schedule info + task->sched_info.rticks = 0; + task->sched_info.priority = 1; + task->sched_info.counter = task->sched_info.priority; + + // initialzie singal + sigpending_init(&task->sigpending); + default_sighand_init(&task->sighandler); + + // insert task to run queue and task list + user_init = task; + list_add_tail(&task->list, &task_list); + local_irq_restore(daif); + + LOG("run_init_task end"); + add_task_to_rq(task); +} + +struct vm_area_struct* create_vma_vc(struct mm_struct* mm){ + uint64_t va, pa; + struct vm_area_struct *vma; + uint8_t* addr; + + vma = kmalloc(sizeof(struct vm_area_struct)); + vma->vm_start = VMA_VC_BASE; + vma->vm_end = VMA_VC_END; + vma->type = VMA_VC_RAM; + vma->vm_flags = VMA_PROT_READ | VMA_PROT_WRITE; + vma->filename == NULL; + list_add_tail(&vma->list, &mm->mmap_list); +/* + va = vma->vm_start; + while(va != vma->vm_end){ + // identity mapping for vc ram + mappages(mm->pgd, va, va, PAGE_SIZE, VM_PTE_USER_ATTR); + va += PAGE_SIZE; + }*/ + return vma; +} + +struct vm_area_struct* create_vma(struct mm_struct* mm, uint64_t vm_start, uint64_t vm_end, uint64_t prot, uint64_t type){ + uint64_t va, pa; + struct vm_area_struct *vma; + uint8_t* addr; + + vma = kmalloc(sizeof(struct vm_area_struct)); + vma->vm_start = vm_start; + vma->vm_end = vm_end; + vma->type = type; + vma->vm_flags = prot; + vma->filename == NULL; + list_add_tail(&vma->list, &mm->mmap_list); + + return vma; +} +struct vm_area_struct* create_vma_stack(struct mm_struct* mm){ + uint64_t va, pa; + struct vm_area_struct *vma; + uint8_t* addr; + + vma = kmalloc(sizeof(struct vm_area_struct)); + vma->vm_start = VMA_STACK_END - VMA_STACK_SIZE; + vma->vm_end = VMA_STACK_END; + vma->type = VMA_STACK; + vma->vm_flags = VMA_PROT_READ | VMA_PROT_WRITE; + vma->filename == NULL; + list_add_tail(&vma->list, &mm->mmap_list); + + va = vma->vm_start; + /* + while(va != vma->vm_end){ + addr = calloc_page(); + mappages(mm->pgd, va, virt_to_phys(addr), PAGE_SIZE, VM_PTE_USER_ATTR); + + va += PAGE_SIZE; + }*/ + return vma; + +} + +struct vm_area_struct* create_vma_code(struct mm_struct* mm, char* filename){ + uint64_t va, pa; + size_t size, offset = 0, n; + struct vm_area_struct *vma; + uint8_t* addr; + char* tmp_name; + + vma = kmalloc(sizeof(struct vm_area_struct)); + size = initrdfs_filesize(filename); + vma->vm_start = VMA_CODE_BASE; + vma->vm_end = VMA_CODE_BASE + ALIGN_UP(size, PAGE_SIZE); + vma->vm_flags = VMA_PROT_READ | VMA_PROT_WRITE | VMA_PROT_EXEC; + vma->type = VMA_FILE; + tmp_name = kmalloc(strlen(filename) + 5); + strcpy(tmp_name, filename); + + vma->filename = tmp_name; + list_add_tail(&vma->list, &mm->mmap_list); + + // copy file to code memory area and set page table +/* + va = VMA_CODE_BASE; + while(size){ + addr = calloc_page(); + n = initrdfs_loadfile(filename, addr, offset, PAGE_SIZE); + mappages(mm->pgd, va, virt_to_phys(addr), PAGE_SIZE, VM_PTE_USER_ATTR); + + va += PAGE_SIZE; + size -= n; + offset += n; + } +*/ + return vma; +} + +// Only duplicate area that not belong to user stack +void dup_mm_struct(struct mm_struct* dst_mm, struct mm_struct* src_mm){ + uint64_t va; + struct list_head* node; + struct vm_area_struct* vma,*tmp_vma; + char* tmp_name; + + list_for_each(node, &src_mm->mmap_list){ + tmp_vma = list_entry(node, struct vm_area_struct, list); + LOG("src_mm's vm area type 0x%x", tmp_vma->type); + vma = (struct vm_area_struct*)kmalloc(sizeof(struct vm_area_struct)); + vma = kmalloc(sizeof(struct vm_area_struct)); + vma->vm_start = tmp_vma->vm_start; + vma->vm_flags = tmp_vma->vm_flags; + vma->vm_end = tmp_vma->vm_end; + vma->type = tmp_vma->type; + if(tmp_vma->type == VMA_FILE){ + tmp_name = kmalloc(strlen(tmp_vma->filename) + 5); + strcpy(tmp_name, tmp_vma->filename); + vma->filename = tmp_name; + } + + // VC RAM should do copy on write and it only support demand paging + if(vma->type != VMA_VC_RAM){ + // COW + dup_pages(dst_mm->pgd, src_mm->pgd, vma->vm_start, vma->vm_end - vma->vm_start, PAGE_ATTR_RDONLY); + // also set parent's page to read only to trigger COW + mappages(src_mm->pgd, tmp_vma->vm_start, 0x0, tmp_vma->vm_end - tmp_vma->vm_start, PAGE_ATTR_RDONLY, 1); + } + + list_add_tail(&vma->list, &dst_mm->mmap_list); + } +} + +struct mm_struct* mm_struct_create(){ + struct mm_struct *mm = kmalloc(sizeof(struct mm_struct)); + INIT_LIST_HEAD(&mm->mmap_list); + mm->pgd = calloc_page(); + return mm; +} + +void mm_struct_destroy(struct mm_struct* mm){ + struct vm_area_struct *vma; + while(!list_empty(&mm->mmap_list)){ + vma = list_first_entry(&mm->mmap_list, struct vm_area_struct, list); + if(vma->type == VMA_FILE){ + kfree(vma->filename); + } + list_del(&vma->list); + kfree(vma); + } + free_page_table(mm->pgd); + kfree(mm); +} + +struct vm_area_struct* find_vma(struct mm_struct *mm, uint64_t addr){ + struct vm_area_struct *vma; + struct list_head *node; + list_for_each(node, &mm->mmap_list){ + vma = list_entry(node, struct vm_area_struct, list); + if(vma->vm_start <= addr && vma->vm_end > addr){ + return vma; + } + } + return NULL; +} + +uint64_t sys_fork(){ + return task_dup(get_current()); +} + +uint64_t sys_getpid(){ + return get_current()->thread_info.pid; +} + +void sys_exit(uint64_t status){ + task_exit(status); +} + +void sys_kill(uint64_t pid){ + task_kill(pid); +} +uint64_t sys_exec(const char* name, char *const argv[]){ + return task_exec(name, argv); +} + +uint64_t mmap(void* addr, size_t len, int prot, int flags, int fd, int file_offset){ + struct task_struct* current = get_current(); + struct mm_struct* mm = current->mm; + struct vm_area_struct* tmp_vma, *vma; + uint64_t vm_start = 0, vm_end; + uint64_t daif; + uint64_t tmp_prot = 0, tmp_type = 0; + + INFO("mmap(%p, %p, %p, %p, %p, %p)", addr, len, prot, flags, fd, file_offset); + tmp_prot = prot & (VMA_PROT_READ | VMA_PROT_WRITE | VMA_PROT_EXEC); + if(flags & MAP_ANONYMOUS) tmp_type = VMA_ANONYMOUS; + + daif = local_irq_disable_save(); + if(addr != NULL){ + vm_start = ALIGN_DOWN(addr, PAGE_SIZE); + }else{ + vm_start = 0x0; + } + + while(tmp_vma = find_vma(mm , vm_start)){ + vm_start = tmp_vma->vm_end; + } + vm_end = vm_start + ALIGN_UP(len, PAGE_SIZE); + create_vma(mm, vm_start, vm_end, tmp_prot, tmp_type); + + INFO("return value: %p", vm_start); + local_irq_restore(daif); + return vm_start; +} + +void* sys_mmap(void* addr, size_t len, int prot, int flags, int fd, int file_offset){ + return (void*)mmap(addr, len, prot, flags, fd, file_offset); +} + diff --git a/lab6/kernel/shell.c b/lab6/kernel/shell.c new file mode 100644 index 000000000..888b41df7 --- /dev/null +++ b/lab6/kernel/shell.c @@ -0,0 +1,178 @@ +#include "kernel/shell.h" + +char *miku_ascii = "⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀\r\n⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁\r\n⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀\r\n⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀\r\n⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀\r\n⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀\r\n⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀\r\n⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀\r\n⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀\r\n⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀\r\n⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀"; +char buf[0x2000]; + +void print_irq_count(void){ + printf("irq_count: "); + for(uint32_t i = 0 ; i < END_OF_LIST ; i++){ + printf("%l ", irq_count[i]); + } + printf("\r\n"); +} + +void setTimeout_callback(void* data){ + uint64_t t = get_jiffies(); + printf("Elapsed time after booting: %l.%l\r\n", t / HZ, t % HZ); + print_irq_count(); + printf("Your message: %s\r\n",(char*) data); +} + + +void simple_shell(){ + unsigned int i; + char ch, *token; + printf(miku_ascii); + printf("\r\n\r\n"); + while(1){ + i = 0; + buf[0] = '\0'; + printf("# "); + // read command + while(1){ + ch = (char)getchar(); + if(ch == '\r'){ + printf("\r\n"); + buf[i] = '\0'; + break; + }else if(ch != '\n'){ + putchar(ch); + buf[i] = ch; + i++; + } + } + + token = strtok(buf, DELIM); + if(token == NULL) continue; + // match comman + if(strcmp(token, "help") == 0){ + printf("help : print this help menu\r\n" \ + "hello : print Hello World!\r\n" \ + "info : print hardware infomation\r\n" \ + "ls : list files\r\n" \ + "cat : cat files\r\n" \ + "load : load user program\r\n" \ + "time : print time after booting\r\n" \ + "reboot : reboot the device\r\n" \ + "setTimeout : set a N seconds timer task\r\n" \ + " setTimeout \r\n" \ + "irq_count : list irq count\r\n" + "alloc_pages : get pages\r\n" \ + " alloc_pages \r\n" \ + "free_pages : free pages\r\n" \ + " free_pages \r\n" \ + "kmalloc : get an object\r\n" \ + " kmalloc \r\n" \ + "kfree : free an object\r\n" \ + " kfree \r\n" \ + + "page_info : get buddy system's statistics\r\n" \ + "print_rq : print run queue\r\n" \ + + ); + + }else if(strcmp(token, "hello") == 0){ + printf("Hello World!\r\n"); + }else if(strcmp(token, "info") == 0){ + uint32_t tmp[2]; + MBox_get_board_revision(tmp); + printf("Board revision: 0x%x\r\n", tmp[0]); + + MBox_get_arm_memory(tmp); + printf("Memory base: 0x%x\r\n", tmp[0]); + printf("Memory size: 0x%x\r\n", tmp[1]); + }else if(strcmp(token, "reboot") == 0){ + printf("Start rebooting...\r\n"); + reboot(100); + while(1); + }else if(strcmp(token, "ls") == 0){ + initrdfs_ls(); + }else if(strcmp(token, "cat") == 0){ + initrdfs_cat(); + }else if(strcmp(token, "load") == 0){ + /*( initrdfs_loadfile("test.img",(uint8_t*) 0x100000); + asm volatile("mov x0, 0x0\n\t" + "msr spsr_el1, x0\n\t" + "mov x0, 0x100000\n\t" + "msr sp_el0, x0\n\t" + "mov x0, #0x100000\n\t" + "msr elr_el1, x0\n\t" + "eret\n\t" + );*/ + run_init_task("syscall.img"); + while(1){ + local_irq_disable(); + if(user_init == NULL) break; + preempt_schedule(); + local_irq_enable(); + } + local_irq_enable(); + }else if(strcmp(token, "time") == 0){ + uint64_t j = get_jiffies(); + printf("Elapsed time after booting: %l.%l\r\n", j / HZ, j % HZ); + }else if(strcmp(token, "setTimeout") == 0){ + uint64_t j = 0, len = 0, timeout = 0; + char *data = NULL; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + len = strlen(token); + data = (char*)simple_malloc(len + 1); + strcpy(data, token); + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + timeout = atoul(token); + + j = get_jiffies(); + add_timer(setTimeout_callback, data, timeout * 1000); + printf("Elapsed time after booting: %l.%l\r\n", j / HZ, j % HZ); + print_irq_count(); + printf("Timer will trigger after %l seconds\r\n", timeout); + }else if(strcmp(token, "irq_count") == 0){ + print_irq_count(); + }else if(strcmp(token, "alloc_pages") == 0){ + uint32_t order; + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + order = atoul(token); + p = alloc_pages(order); + printf("Allocate pages at %l\r\n", p); + }else if(strcmp(token, "free_pages") == 0){ + void* p; + struct page* page; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + p = (void*)atoul(token); + page = pfn_to_page(virt_to_pfn(p)); + + free_pages(p, get_page_order(page)); + printf("Free pages\r\n"); + }else if(strcmp(token, "kmalloc") == 0){ + uint32_t size; + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + size = atoul(token); + p = kmalloc(size); + printf("Allocate an object at %l\r\n", p); + }else if(strcmp(token, "kfree") == 0){ + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + p = (void*)atoul(token); + + kfree(p); + printf("Free an object\r\n"); + }else if(strcmp(token, "page_info") == 0){ + print_buddy_statistics(); + }else if(strcmp(token, "print_rq") == 0){ + print_rq(); + } + } +} diff --git a/lab6/kernel/signal.c b/lab6/kernel/signal.c new file mode 100644 index 000000000..7a8dfa096 --- /dev/null +++ b/lab6/kernel/signal.c @@ -0,0 +1,202 @@ +#include "kernel/sched/task.h" +#include "kernel/signal.h" +#include "kernel/signal_inner.h" + +extern void sigreturn_trampoline(); + +int is_valid_signal(int signal){ + return (signal > 0 && signal < SIG_MAX_NUM); +} +void sigpending_init(struct sigpending* sigpending){ + INIT_LIST_HEAD(&sigpending->pending); + sigpending->cur_signal = 0; +} + +void default_sighand_init(struct sighand_struct* sighandler){ + memcpy(sighandler->actions, default_actions, sizeof(default_actions)); +} + +int send_signal(uint64_t pid, int signal){ + LOG("enter send_signal, pid: %l signal %d", pid, signal); + struct task_struct* target = find_task_by_pid(pid); + struct signal_queue* sigq; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + if(!is_valid_signal(signal) || target == NULL) goto end; + if(target->thread_info.state == TASK_DEAD) goto end; + + LOG("target %p", target); + sigq = kmalloc(sizeof(struct signal_queue)); + + + sigq->signal = signal; + list_add_tail(&sigq->list, &target->sigpending.pending); + +end: + local_irq_restore(daif); + LOG("end send_signal"); + return 0; +} + +int register_signal(int signal, sig_handler handler){ + LOG("enter register_signal"); + uint64_t daif; + int ret; + struct task_struct* current = get_current(); + + if(current == NULL) return -1; + + LOG("signal: %d, handler: %p", signal, handler); + daif = local_irq_disable_save(); + // install signal handler from user space + if(is_valid_signal(signal)){ + current->sighandler.actions[signal].sa_flags &= ~(SIG_FLAG_KERNEL); + current->sighandler.actions[signal].sa_handler = handler; + + local_irq_restore(daif); + return 0; + } + + local_irq_restore(daif); + return -1; +} + +void handle_sigreturn(){ + sigreturn_frame_restore(); +} + +int get_pending_signal(struct task_struct *task){ + struct signal_queue* sigq; + uint64_t signal = 0; + if(!list_empty(&task->sigpending.pending)){ + sigq = list_first_entry(&task->sigpending.pending, struct signal_queue, list); + signal = sigq->signal; + list_del(&sigq->list); + kfree(sigq); + LOG("get pending signal %d", signal); + } + return signal; +} + +void handle_signal(){ + int cur_signal; + volatile uint64_t daif; + struct sigaction* action; + struct task_struct* current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + if(current == NULL) return; + + daif = local_irq_disable_save(); + + cur_signal = get_pending_signal(current); + if(!is_valid_signal(cur_signal)) return; + LOG("handle signal %d", cur_signal); + + action = ¤t->sighandler.actions[cur_signal]; + current->sigpending.cur_signal = cur_signal; + + if(action->sa_flags & SIG_FLAG_KERNEL){ + // if signal handler is in kernel space, just directly execute it + LOG("execute kernel signal handler"); + action->sa_handler(); + }else{ + // if signal handler is in user space, execute it in user space by modify trap frame + LOG("execute user signal handler"); + sigreturn_frame_save(action->sa_handler); + } + + local_irq_restore(daif); +} + +void sigreturn_frame_save(sig_handler handler){ + LOG("enter sigreturn_frame_save"); + struct task_struct* current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + uint64_t old_trap_frame; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + // store a copy of current trap frame onto user stack + old_trap_frame = trap_frame->sp_el0 - sizeof(struct trap_frame); + memcpy((void*)old_trap_frame, trap_frame, sizeof(struct trap_frame)); + + // change sp to point to this copy + trap_frame->sp_el0 = old_trap_frame; + + // set elr_el1 to handler + // set lr to jump to our sigreturn_trampoline + // so that when task return to user from kernel mode, it will back to sigreturn_trampoline + trap_frame->x30 = (uint64_t)sigreturn_trampoline; // in entry.S + trap_frame->elr_el1 = (uint64_t)handler; // in entry.S + + local_irq_restore(daif); + LOG("end sigreturn_frame_save"); +} + +void sigreturn_frame_restore(){ + LOG("enter sigreturn_frame_restore"); + struct task_struct* current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + struct trap_frame* old_trap_frame; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + // restore old trap frame + old_trap_frame = (struct trap_frame*)trap_frame->sp_el0; + memcpy(trap_frame, old_trap_frame, sizeof(struct trap_frame)); + + local_irq_restore(daif); + LOG("end sigreturn_frame_restore"); +} + +void sig_terminate(){ + struct task_struct *current = get_current(); + uint64_t pid; + volatile uint64_t daif; + LOG("enter signal_terminate"); + + daif = local_irq_disable_save(); + + pid = current->thread_info.pid; + printf("pid: %l, Receive signal: %s\r\n",pid ,sig_to_str[current->sigpending.cur_signal]); + local_irq_restore(daif); + + task_exit(); +} + +void sig_default(){ + struct task_struct *current = get_current(); + uint64_t pid; + volatile uint64_t daif; + LOG("enter signal_default"); + + daif = local_irq_disable_save(); + + pid = current->thread_info.pid; + printf("pid: %l, Receive signal: %s\r\n",pid , sig_to_str[current->sigpending.cur_signal]); + local_irq_restore(daif); + + LOG("end signal_default"); +} + +void free_sigpendings(struct sigpending* sigp){ + struct signal_queue* sigq; + while(!list_empty(&sigp->pending)){ + sigq = list_first_entry(&sigp->pending, struct signal_queue, list); + list_del(&sigq->list); + kfree(sigq); + } +} + +void sys_sigreturn(){ + handle_sigreturn(); +} + +void sys_signal(int signal, sig_handler handler){ + register_signal(signal, handler); +} + +int sys_sigkill(uint64_t pid, int signal){ + return send_signal(pid, signal); +} diff --git a/lab6/kernel/start.S b/lab6/kernel/start.S new file mode 100644 index 000000000..3932f36f2 --- /dev/null +++ b/lab6/kernel/start.S @@ -0,0 +1,120 @@ +#include "mm/pgtable.h" +.section ".text.boot" +.global _start +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #0xff + + // cpu id > 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + +// cpu id == 0 +master_core: + adr x1, _dtb + str x0, [x1] +// initialize .bss section + adr x1, __bss_start + adr x2, __bss_end +bss_zero: + sub x3, x2, x1 + cbz x3, end + str xzr, [x1], #8 // store zero to [x1] and add 8 to x1 + b bss_zero + +end: +// modify vbar_el1 before changing exception level to 1 (in virtual address) + ldr x0, =EL1_exception_vector_table + msr vbar_el1, x0 + +// set up identity pageing + bl identity_paging + +// from el2 to el1 + bl from_el2_to_el1 + +// enable virtual memory + ldr x2, =vm_enable + br x2 + +vm_enable: +// kernel_main(_dtb) + ldr x1, =_dtb + ldr x0, [x1] + +// set tpidr_el1 to NULL to avoid timer interrupt accidently update current task_strcut + mov x1, 0 + msr tpidr_el1, x1 + + +// jump to kernel_main + bl kernel_main + b proc_hang + +from_el2_to_el1: + ldr x0, =__EL1_stack // Set el1 stack to __EL1_stack + msr sp_el1, x0 + + mov x0, (1 << 31) // Set hcr_el2.RW so EL1 uses aarch64 + msr hcr_el2, x0 + + mov x0, 0x3c5 // EL1h (SPSel = 1) + msr spsr_el2, x0 + msr elr_el2, lr + eret // return to EL1 + +identity_paging: +// set page granularity ofttbr0 and ttbr1 to 4KiB and set virtual memory mapping region to 0 ~ 2^48 + ldr x0, =TCR_CONFIG_DEFAULT + msr tcr_el1, x0 + +// set mair_el1 + ldr x0, =( \ + (MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | \ + (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8)) \ + ) + msr mair_el1, x0 + +// initialize identity page table + adr x0, __PGD_start + mov x1, x0 + ldr x2, =(0x1000 * 1028) +pg_zero: + sub x3, x1, x0 + sub x3, x3, x2 + cbz x3, pg_zero_end + str xzr, [x1], #8 // store zero to [x1] and add 8 to x1 + b pg_zero + +pg_zero_end: + adr x1, __PUD_start +// initialize PGD + ldr x2, = BOOT_PGD_ATTR + orr x2, x1, x2 // combine the physical address of next level page with attribute. + str x2, [x0] +// initialize PUD + ldr x2, = BOOT_PUD_ATTR + mov x3, 0x00000000 + orr x3, x2, x3 + str x3, [x1] // 1st 1GB mapped by the 1st entry of PUD + mov x3, 0x40000000 + orr x3, x2, x3 + str x3, [x1, 8] // 2nd 1GB mapped by the 2nd entry of PUD +// set ttbr0_el1 to PGU + msr ttbr0_el1, x0 // load PGD to the bottom translation-based register (el0 mapping). + msr ttbr1_el1, x0 // load PGD to the bottom translation-based register (el1 mapping). + + mrs x2, sctlr_el1 + orr x2 , x2, 1 // set first bit to 1 to enable MMU + msr sctlr_el1, x2 // enable MMU, cache remains disabled + + ret + + +.section ".data" +_dtb: .dword 0 + diff --git a/lab6/kernel/syscall_table.c b/lab6/kernel/syscall_table.c new file mode 100644 index 000000000..1883ae653 --- /dev/null +++ b/lab6/kernel/syscall_table.c @@ -0,0 +1,72 @@ +#include "kernel/syscall_table.h" + +uint64_t syscall_handler(){ + struct task_struct *current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + uint64_t NR_syscall = trap_frame->x8; + uint64_t x0, x1, x2, x3, x4, x5; + uint64_t ret; + + switch(NR_syscall){ + case 0: + ret = sys_getpid(); + break; + case 1: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_uart_read((uint8_t*)x0, x1); + break; + case 2: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_uart_write((uint8_t*)x0, x1); + break; + case 3: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_exec((const char *)x0, (char **const)x1); + break; + case 4: + ret = sys_fork(); + break; + case 5: + x0 = trap_frame->x0; + sys_exit(x0); + break; + case 6: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_mbox_call(x0, (uint32_t*)x1); + break; + case 7: + x0 = trap_frame->x0; + sys_kill(x0); + break; + case 8: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + sys_signal((int)x0,(void (*)())x1); + break; + case 9: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + sys_sigkill((uint64_t)x0,(int)x1); + break; + case 10: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + x2 = trap_frame->x2; + x3 = trap_frame->x3; + x4 = trap_frame->x4; + x5 = trap_frame->x5; + ret = (uint64_t)sys_mmap((void*)x0, (size_t)x1, (int)x2, (int)x3, (int)x4, (int)x5); + break; + case 20: + sys_sigreturn(); + break; + default: + printf("Unknown system call %p\r\n", NR_syscall); + while(1); + } + return ret; +} diff --git a/lab6/kernel/syscall_test.c b/lab6/kernel/syscall_test.c new file mode 100644 index 000000000..b5dd80c13 --- /dev/null +++ b/lab6/kernel/syscall_test.c @@ -0,0 +1,17 @@ +#include "types.h" +#include "debug/debug.h" +#include "asm.h" +#include "lib/print.h" +uint64_t sys_hello(uint64_t x0){ + LOG("Enter sys_hello"); + printf("CurrentEL: %x\r\n", get_currentEL()); + printf("DAIF: %x\r\n", get_DAIF()); + printf("SPSR_EL1: %p\r\n", (void*)get_SPSR_EL1()); + printf("SPSel: %p\r\n", (void*)get_SPSel()); + printf("SP_EL0: %p\r\n", (void*)get_SP_ELx(0)); + printf("ELR_EL1: %p\r\n", (void*)get_ELR_EL1()); + printf("ESR_EL1: %p\r\n", (void*)get_ESR_EL1()); + printf("SP : %p\r\n", (void*)get_SP()); + printf("\r\n"); + return x0; +} diff --git a/lab6/kernel/timer.c b/lab6/kernel/timer.c new file mode 100644 index 000000000..cd43b94f9 --- /dev/null +++ b/lab6/kernel/timer.c @@ -0,0 +1,100 @@ +#include "kernel/timer.h" + +static uint64_t jiffies = 0; +static struct list_head timer_list; + +/* + * We use core timer to update jiffies + */ +void enable_core_timer_irq(){ + IO_MMIO_write32(CORE0_TIMER_IRQ_CTRL, 2); +} +void disable_core_timer_irq(){ + IO_MMIO_write32(CORE0_TIMER_IRQ_CTRL, 0); +} + +void timer_softirq_callback(){ + struct list_head *head = &timer_list; + struct list_head *node; + timer_t* t; + + list_for_each(node, head){ + t = list_entry(node, timer_t, list); + t->ticks--; + if(t->ticks <= 0){ + list_del(node); + t->callback(t->data); + } + } +} + +void init_timer_list(void){ + INIT_LIST_HEAD(&timer_list); +} + +/** + * Timer with 10 microsecond resolution + * + * @param duration in microsecond + */ +void add_timer(timer_callback callback, uint8_t* data, uint64_t duration){ + if(duration == 0){ + callback(data); + return; + } + + timer_t* t = (timer_t*)simple_malloc(sizeof(timer_t)); + + t->ticks = duration / (1000 / HZ); + t->callback = callback; + t->data = data; + + disable_core_timer_irq(); + //critical section + list_add(&t->list, &timer_list); + enable_core_timer_irq(); +} + +void init_core_timer(){ + uint64_t freq; + + init_timer_list(); + set_CNTP_CTL_EL0(1); + freq = get_CNTFRQ_EL0(); + set_CNTP_TVAL_EL0(freq / HZ); + + + // lab5, user space want to access cpu timer register + uint64_t tmp; + asm volatile("mrs %0, cntkctl_el1" : "=r"(tmp)); + tmp |= 1; + asm volatile("msr cntkctl_el1, %0" : : "r"(tmp)); + + enable_core_timer_irq(); +} +void core_timer_irq_handler(){ + uint64_t freq; + struct task_struct* current = get_current(); + + freq = get_CNTFRQ_EL0(); + set_CNTP_TVAL_EL0(freq / HZ); + + jiffies += 1; + + // update task schedule info + if(current){ + current->sched_info.rticks++; + current->sched_info.counter--; + if(current->sched_info.counter <= 0){ + need_sched = 1; + } + } +} + +uint64_t inline get_jiffies(){ + return jiffies; +} + + + + diff --git a/lab6/lib/Makefile b/lab6/lib/Makefile new file mode 100644 index 000000000..328a22f1a --- /dev/null +++ b/lab6/lib/Makefile @@ -0,0 +1,36 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + print.o \ + string.o \ + list.o \ + cpio.o \ + simple_malloc.o \ + fdt_parse.o \ + asm.o \ + ring_buffer.o \ + bitops.o + + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab6/lib/asm.c b/lab6/lib/asm.c new file mode 100644 index 000000000..e071c7a86 --- /dev/null +++ b/lab6/lib/asm.c @@ -0,0 +1,168 @@ +#include "types.h" +void local_irq_enable(){ + asm volatile("msr DAIFClr, 0xf"); +} + +void local_irq_disable(){ + asm volatile("msr DAIFSet, 0xf"); +} + +uint64_t local_irq_disable_save() { + volatile uint64_t daif; + asm volatile( + "mrs %0, DAIF\t\n" + "msr DAIFSet, 0xf" + :"=&r"(daif) + : + ); + + return daif; +} + +void local_irq_restore(uint64_t daif) { + asm volatile( + "msr DAIF, %0" + ::"r"(daif) + ); +} + +uint32_t get_currentEL(){ + uint64_t curEL = 0; + asm volatile("mrs %0, CurrentEL" + : "=&r" (curEL) + : + ); + return curEL >> 2; +} +uint64_t get_SP_ELx(uint32_t x){ + uint64_t sp = 0; + + switch(x){ + case 0: + asm volatile("mrs %0, SP_EL0" + : "=&r" (sp) + : + ); + break; + case 1: + asm volatile("mrs %0, SP_EL1" + : "=&r" (sp) + : + ); + break; + case 2: + asm volatile("mrs %0, SP_EL2" + : "=&r" (sp) + : + ); + break; + default: + break; + } + + + return sp; +} +uint64_t get_DAIF(){ + uint64_t daif; + asm volatile("mrs %0, DAIF" + : "=&r" (daif) + : + ); + return daif; +} +void set_DAIF(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr daif, x0" + : + :[n] "r" (n) + ); +} + +uint64_t get_SPSel(){ + uint64_t spsel = 0; + asm volatile("mrs %0, spsel" + : "=&r" (spsel) + : + ); + return spsel; +} +uint64_t get_ESR_EL1(){ + uint64_t esr_el1 = 0; + asm volatile("mrs %0, esr_el1" + : "=&r" (esr_el1) + : + ); + return esr_el1; +} +uint64_t get_SPSR_EL1(){ + uint64_t spsr_el1 = 0; + asm volatile("mrs %0, spsr_el1" + : "=&r" (spsr_el1) + : + ); + return spsr_el1; +} +uint64_t get_ELR_EL1(){ + uint64_t elr_el1 = 0; + asm volatile("mrs %0, elr_el1" + : "=&r" (elr_el1) + : + ); + return elr_el1; +} +uint64_t get_SP(){ + uint64_t sp = 0; + asm volatile("mov %0, sp" + : "=&r" (sp) + : + ); + return sp; +} +uint64_t get_CNTP_CTL_EL0(){ + uint64_t cntp_ctl_el0 = 0; + asm volatile("mrs %0, cntp_ctl_el0" + : "=&r" (cntp_ctl_el0) + : + ); + return cntp_ctl_el0; +} +void set_CNTP_CTL_EL0(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr cntp_ctl_el0, x0" + : + :[n] "r" (n) + ); +} +uint64_t get_CNTFRQ_EL0(){ + uint64_t cntfrq_el0 = 0; + asm volatile("mrs %0, cntfrq_el0" + : "=&r" (cntfrq_el0) + : + ); + return cntfrq_el0; +} + +void set_CNTP_TVAL_EL0(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr cntp_tval_el0, x0" + : + :[n] "r" (n) + ); +} +uint64_t get_CNTPCT_EL0(){ + uint64_t cntpct_el0 = 0; + asm volatile("mrs %0, cntpct_el0" + : "=&r" (cntpct_el0) + : + ); + return cntpct_el0; +} + +void set_tpidr_el1(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr tpidr_el1, x0" + : + :[n] "r" (n) + ); +} diff --git a/lab6/lib/bitops.c b/lab6/lib/bitops.c new file mode 100644 index 000000000..ad1080455 --- /dev/null +++ b/lab6/lib/bitops.c @@ -0,0 +1,55 @@ +#include "lib/bitops.h" + +uint16_t ffs16(uint16_t val){ +// val should not be zero! +// The behavior is undefined when val is zer! + uint16_t num = 0; + if((val & 0xff) == 0){ + num += 8; + val >>= 8; + } + if((val & 0xf) == 0){ + num += 4; + val >>= 4; + } + if((val & 0x3) == 0){ + num += 2; + val >>= 2; + } + if((val & 0x1) == 0) + num += 1; + + return num; +} + +uint64_t ffs64(uint64_t val){ +// val should not be zero! +// The behavior is undefined when val is zer! + uint64_t num = 0; + if((val & 0xffffffff) == 0){ + num += 32; + val >>= 32; + } + if((val & 0xffff) == 0){ + num += 16; + val >>= 16; + } + if((val & 0xff) == 0){ + num += 8; + val >>= 8; + } + if((val & 0xf) == 0){ + num += 4; + val >>= 4; + } + + if((val & 0x3) == 0){ + num += 2; + val >>= 2; + } + + if((val & 0x1) == 0) + num += 1; + + return num; +} diff --git a/lab6/lib/cpio.c b/lab6/lib/cpio.c new file mode 100644 index 000000000..4474ac83b --- /dev/null +++ b/lab6/lib/cpio.c @@ -0,0 +1,61 @@ +#include "lib/cpio.h" + +uint32_t cpio_hex2dec(const char *s){ + uint32_t ret = 0; + for(uint32_t i = 0 ; i < 8 ; i++){ + ret = ret << 4; + ret = ret + hex2dec(s[i]); + } + return ret; +} + +void cpio_iter_parse(struct cpio_iter* iter, struct fentry* f){ + LOG("Enter cpio_iter_parse"); + size_t count = 0; + struct cpio_newc_header* header = (struct cpio_newc_header* )iter->cur; + + if(!memcpy(header->c_magic, "070701", 6)){ + LOG("CPIO PARSE ERROR!!!!"); + return; + } + + f->ino = cpio_hex2dec(header->c_ino); + f->mode = cpio_hex2dec(header->c_mode); + f->uid = cpio_hex2dec(header->c_uid); + LOG("f->uid: %u", f->uid); + f->gid = cpio_hex2dec(header->c_gid); + f->nlink = cpio_hex2dec(header->c_nlink); + f->mtime = cpio_hex2dec(header->c_mtime); + f->filesize = cpio_hex2dec(header->c_filesize); + LOG("f->filesize: %u", f->filesize); + f->devmajor = cpio_hex2dec(header->c_devmajor); + f->devminor = cpio_hex2dec(header->c_devminor); + f->rdevmajor = cpio_hex2dec(header->c_rdevmajor); + f->rdevminor = cpio_hex2dec(header->c_rdevminor); + f->namesize = cpio_hex2dec(header->c_namesize); + LOG("f->namesize: %u", f->namesize); + f->check = cpio_hex2dec(header->c_check); + count = count + sizeof(struct cpio_newc_header); + + f->filename = (char*)simple_malloc(f->namesize); + memcpy(f->filename, (uint8_t* )header + count, f->namesize); + LOG("get f->filename"); + count = ALIGN_UP(count + f->namesize, 4); + if(f->filesize > 0){ + f->data = (uint8_t*)simple_malloc(f->filesize); + memcpy(f->data, (uint8_t* )header + count, f->filesize); + } + LOG("get f->data"); + count = ALIGN_UP(count + f->filesize, 4); + iter->cur = iter->cur + count; + LOG("count: %u, iter->cur: %p", count, iter->cur); + LOG("Leave cpio_iter_parse"); +} + +void cpio_iter_init(struct cpio_iter* iter, void* addr){ + iter->cur = addr; +} +int cpio_is_tailer(struct fentry* f){ + return (strcmp(f->filename, "TRAILER!!!") == 0); +} + diff --git a/lab6/lib/fdt_parse.c b/lab6/lib/fdt_parse.c new file mode 100644 index 000000000..762563031 --- /dev/null +++ b/lab6/lib/fdt_parse.c @@ -0,0 +1,127 @@ +#include "lib/fdt_parse.h" + +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +static fdt_header header; +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = &header; + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) >> 2; + len += 2; +// printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + printf("Parsing error!!\n"); + while(1); + } + } +} +void fdt_parse_rsvmap(uint8_t* fdt, fdt_rsvmap_callback callback){ + uint64_t *mem_rsvmap; + uint64_t start, end; + uint64_t count = 0; + fdt_header * pheader = &header; + fdt_parse_header(fdt, pheader); + + mem_rsvmap = (uint64_t*)(fdt + pheader->off_mem_rsvmap); + do{ + start = bswap64(mem_rsvmap[count * 2]); + end = start + bswap64(mem_rsvmap[count * 2 + 1]); + if(end) + callback(start, end); + else + break; + count++; + }while(1); +} +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab6/lib/list.c b/lab6/lib/list.c new file mode 100644 index 000000000..6539320c1 --- /dev/null +++ b/lab6/lib/list.c @@ -0,0 +1,75 @@ +#include "lib/list.h" + +void INIT_LIST_HEAD(struct list_head* head){ + head->next = head; + head->prev = head; +} + +void list_add(struct list_head* node, struct list_head* head){ + struct list_head *next = head->next; + + next->prev = node; + head->next = node; + + node->next = next; + node->prev = head; +} + +void list_add_tail(struct list_head* node, struct list_head* head){ + struct list_head* tail = head->prev; + + tail->next = node; + head->prev = node; + + node->next = head; + node->prev = tail; +} + +void list_del(struct list_head* node){ + struct list_head* next = node->next; + struct list_head* prev = node->prev; + + next->prev = prev; + prev->next = next; +} +int list_empty(struct list_head* head){ + return (head->next == head); +} + +int list_is_last(struct list_head* node, struct list_head* head){ + return head->prev == node; +} + +int list_is_head(struct list_head* node, struct list_head* head){ + return head == node; +} + +void list_splice(struct list_head *list, struct list_head *head){ + struct list_head *head_first = head->next; + struct list_head *list_first = list->next; + struct list_head *list_last = list->prev; + + if (list_empty(list)) + return; + + head->next = list_first; + list_first->prev = head; + + list_last->next = head_first; + head_first->prev = list_last; +} + +void list_splice_tail(struct list_head *list, struct list_head *head){ + struct list_head *head_last = head->prev; + struct list_head *list_first = list->next; + struct list_head *list_last = list->prev; + + if (list_empty(list)) + return; + + head->prev = list_last; + list_last->next = head; + + list_first->prev = head_last; + head_last->next = list_first; +} diff --git a/lab6/lib/print.c b/lab6/lib/print.c new file mode 100644 index 000000000..9e64ca936 --- /dev/null +++ b/lab6/lib/print.c @@ -0,0 +1,111 @@ +#include "lib/print.h" + +int32_t aio_print(char* fmt, ...){ + +} +int32_t printf(char *fmt, ...){ + uint32_t uval; + int32_t val; + int64_t lval; + char str[64], ch; + char* p, *s; + void* addr; + volatile int32_t count = 0; + va_list ap; + + va_start(ap, fmt); + + while(*fmt){ + char c = *fmt++; + if(c == '%'){ + c = *fmt++; + switch(c){ + case 'u': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'd': + val = va_arg(ap, int); + itoa(val, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'l': + lval = va_arg(ap, int64_t); + ltoa(lval, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'c': + ch = va_arg(ap, int); + mini_uart_write(ch); + count++; + break; + case 'p': + addr = va_arg(ap, void*); + ultoa((uint64_t)addr, str, 16); + + mini_uart_write('0'); + mini_uart_write('x'); + count += 2; + + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + + break; + case 'x': + uval = va_arg(ap, uint32_t); + ultoa(uval, str, 16); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + + break; + case 's': + s = va_arg(ap, char*); + p = s; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case '%': + mini_uart_write('%'); + count++; + default: + mini_uart_write('%'); + mini_uart_write(c); + count += 2; + } + }else{ + mini_uart_write(c); + count++; + } + } + va_end(ap); + return count; +} +int32_t putchar(uint8_t ch){ + mini_uart_write(ch); + return ch; +} +int32_t getchar(){ + return mini_uart_aio_read(); +} diff --git a/lab6/lib/ring_buffer.c b/lab6/lib/ring_buffer.c new file mode 100644 index 000000000..1f7e750b1 --- /dev/null +++ b/lab6/lib/ring_buffer.c @@ -0,0 +1,117 @@ +#include "lib/ring_buffer.h" + +ring_buffer* create_simple_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)simple_malloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)simple_malloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + tmp->count = 0; + return tmp; +} + +// This function can only be used after initializing mm +ring_buffer* create_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)kmalloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)kmalloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + tmp->count = 0; + return tmp; +} + +void free_ring_buf(ring_buffer* rbuf){ + kfree(rbuf->buf); + kfree(rbuf); +} + +uint8_t ring_buf_is_empty(ring_buffer* rbuf){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + if(rbuf->head == rbuf->tail){ + local_irq_restore(daif); + return 1; + } + local_irq_restore(daif); + return 0; +} + +uint8_t ring_buf_is_full(ring_buffer* rbuf){ + volatile uint64_t daif; + if((rbuf->tail + 1) % (rbuf->size + 1) == rbuf->head){ + local_irq_disable_save(daif); + return 1; + } + local_irq_restore(daif); + return 0; +} + +size_t ring_buf_write(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count += count; + local_irq_restore(daif); + return count; +} + +size_t ring_buf_write_unsafe(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count += count; + return count; +} + +size_t ring_buf_read(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count -= count; + local_irq_restore(daif); + return count; +} + +size_t ring_buf_read_unsafe(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count -= count; + return count; +} + +size_t ring_buf_get_len(ring_buffer* rbuf){ + volatile uint64_t daif; + size_t ret; + + daif = local_irq_disable_save(); + ret = rbuf->count; + local_irq_restore(daif); + + return ret; +} diff --git a/lab6/lib/simple_malloc.c b/lab6/lib/simple_malloc.c new file mode 100644 index 000000000..f2f67ac0a --- /dev/null +++ b/lab6/lib/simple_malloc.c @@ -0,0 +1,18 @@ +#include "lib/simple_malloc.h" +#include "mm/mmu.h" + +extern int __heap_start; +static struct malloc_state mstate = { + .last_remainder = (uint8_t*)&__heap_start +}; + + +void* simple_malloc(size_t size){ + void* chunk = mstate.last_remainder; + size_t nb = req2size(size); + mstate.last_remainder = mstate.last_remainder + nb; + return chunk; +} +void* simple_malloc_get_remainder(){ + return mstate.last_remainder; +} diff --git a/lab6/lib/string.c b/lab6/lib/string.c new file mode 100644 index 000000000..3ab9d9ce6 --- /dev/null +++ b/lab6/lib/string.c @@ -0,0 +1,260 @@ +#include "lib/string.h" +#include "types.h" +char *int_table = "0123456789"; +char *hex_table = "0123456789abcdef"; +char * itoa(int32_t value, char* str, uint32_t base){ + char buf[32]; + uint32_t val; + volatile int i = 0, j = 0; + + switch(base){ + case 16: + val = (uint32_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} + +char * utoa(uint32_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint32_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} +char * ltoa(int64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val; + + switch(base){ + case 16: + val = (uint64_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +char * ultoa(uint64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +uint64_t atoul(const char* str){ + uint64_t val = 0; + const char* ps = str; + while(*ps){ + val *= 10; + val += (*ps - '0'); + ps++; + } + return val; +} +int32_t strcmp(char* str1, char* str2){ + do{ + if(*str1 > *str2) return 1; + else if(*str1 < *str2) return -1; + str1++;str2++; + }while(*str1 != '\0' || *str2 != '\0'); + return 0; +} +size_t strlen(const char* s){ + size_t i = 0; + while(s[i++]); + i--; + return i; +} +// Do not maninpulate data by using (uint64*) or it may sometimes trigger alignment issue +// Manipulating data by using (uint8*) is best choice in this homework +void* memcpy(void* dst, const void* src, size_t n){ + const uint8_t* ps = src; + uint8_t *pd = dst; + size_t i; + for(i = 0 ; i < n ; i++) pd[i] = ps[i]; + return dst; +} +char *strcpy(char *dest, const char *src){ + memcpy(dest, src, strlen(src) + 1); +} +void* memset(void* s, int c, size_t n){ + uint8_t* ps = s; + for(size_t i = 0 ; i < n ; i++) ps[i] = c; + return s; +} + +int32_t memcmp(void* m1, const void* m2, size_t n){ + size_t i = 0; + char *s1 = m1; + const char* s2 = m2; + while(i < n){ + if(s1[i] > s2[i]) return 1; + else if(s1[i] < s2[i]) return -1; + i++; + } + return 0; +} + +uint8_t hex2dec(char hex){ + if('0' <= hex && hex <= '9'){ + return (uint8_t)hex - (uint8_t)'0'; + }else if('a' <= hex && hex <= 'f'){ + return (uint8_t)hex - (uint8_t)'a' + 10; + }else{ + return (uint8_t)hex - (uint8_t)'A' + 10; + } +} +uint8_t _is_delim(char c,const char* delim){ + uint32_t i = 0; + while(delim[i]){ + if(c == delim[i++]) return 1; + } + return 0; +} +char* _next_token(char* s,const char* delim){ + char* pos = s; + + do{ + if(*pos == '\0'){ + return NULL; + }else if(_is_delim(*pos, delim)){ + *pos = '\0'; + return pos + 1; + } + pos++; + }while(1); +} +char* _skip_delim(char* s,const char* delim){ + char* pos = s; + while(*pos != '\0' && _is_delim(*pos, delim)) pos++; + return pos; +} +char* strtok(char* s,const char* delim){ + static char *pos = NULL; + char *tmp_pos = NULL; + if(s == NULL){ + if(pos == NULL || *pos =='\0') return NULL; + + tmp_pos = pos = _skip_delim(pos, delim); + if(*pos != '\0'){ + pos = _next_token(pos, delim); + }else{ + pos = tmp_pos = NULL; + } + }else{ + if(*s == '\0') return NULL; + + pos = s; + tmp_pos = pos = _skip_delim(pos, delim); + if(*pos != '\0'){ + pos = _next_token(pos, delim); + }else{ + pos = tmp_pos = NULL; + } + } + return tmp_pos; +} diff --git a/lab6/mm/Makefile b/lab6/mm/Makefile new file mode 100644 index 000000000..47bcf9c04 --- /dev/null +++ b/lab6/mm/Makefile @@ -0,0 +1,28 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + page_alloc.o \ + slab.o \ + mmu.o \ + mm.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab6/mm/mm.c b/lab6/mm/mm.c new file mode 100644 index 000000000..6a7cdd3c4 --- /dev/null +++ b/lab6/mm/mm.c @@ -0,0 +1,201 @@ +#include "mm/mm.h" +#include "mm/mmu.h" + +extern int __heap_start; +extern int __kernel_image_start; +extern int __kernel_image_end; +extern int __kernel_image_end; +extern int __EL1_stack_size; +extern int __EL1_stack; + +struct list_head mem_rsvmap; +struct list_head mem_unusedmap; +struct mem_node memory_node; +struct page *mem_map; + +void reserve_memory(uint64_t start, uint64_t end){ + struct list_head *node; + struct list_head *head; + struct mem_block *mb = simple_malloc(sizeof(struct mem_block)); + struct mem_block *tmp_mb; + + start = ALIGN_DOWN(start, PAGE_SIZE); + end = ALIGN_UP(end, PAGE_SIZE); + mb->start = start; + mb->end = end; + list_for_each(node, &mem_rsvmap){ + tmp_mb = list_entry(node, struct mem_block, list); + if(tmp_mb->start > start){ + head = node->prev; + list_add(&mb->list, head); + break; + } + } + + if(list_is_head(node, &mem_rsvmap)){ + list_add(&mb->list, node->prev); + } +} + +size_t get_reserved_size(){ + uint64_t start, end; + struct list_head* node; + struct mem_block* mb; + size_t size = 0; + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + start = mb->start; + end = mb->end; + size += (end - start); + } + return size; +} + +size_t get_unused_size(){ + uint64_t start, end; + struct list_head* node; + struct mem_block* mb; + size_t size = 0; + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + start = mb->start; + end = mb->end; + size += (end - start); + LOG("unused map: start: %p, end: %p", start, end); + } + return size; +} + +uint64_t _reserve_dtb(void *dtb){ + fdt_header header; + fdt_header *pheader = &header; + uint64_t start, end; + size_t size = 0; + + fdt_parse_header((uint8_t*)dtb, pheader); + size = ALIGN_UP(pheader->totalsize, PAGE_SIZE); + + start = (uint64_t)dtb; + end = start + size; + reserve_memory(start, end); +} + +void* _reserve_cpio(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + static uint64_t start, end; + static uint8_t found_start = 0, found_end = 0; + if(prop != NULL){ + if(strcmp(prop->name, "linux,initrd-start") == 0){ + start = bswap32(*(uint32_t*)prop->value); + found_start = 1; + } + if(strcmp(prop->name, "linux,initrd-end") == 0){ + end = bswap32(*(uint32_t*)prop->value); + found_end = 1; + } + if(found_start && found_end){ + found_start = found_end = 0; + reserve_memory(start, end); + } + } +} + +void _create_memory_rsvmap(void *dtb){ + uint64_t start, end; + // reseved memory in dtb + fdt_parse_rsvmap((uint8_t*)dtb, reserve_memory); + + // reverse memory for kernel image + reserve_memory((uint64_t)&__kernel_image_start - UPPER_ADDR_SPACE_BASE, (uint64_t)&__kernel_image_end - UPPER_ADDR_SPACE_BASE); + + // reserve memory for stack + reserve_memory((uint64_t)&__EL1_stack - (uint64_t)&__EL1_stack_size - UPPER_ADDR_SPACE_BASE, (uint64_t)&__EL1_stack - UPPER_ADDR_SPACE_BASE); + + // reserve memory for device tree + _reserve_dtb((void*)((uint64_t)dtb - UPPER_ADDR_SPACE_BASE)); + + // reserve memory for cpio + fdt_parser(dtb, _reserve_cpio); + + // Create struct page table for mapping every physical frame to it + mem_map = simple_malloc(sizeof(struct page) * (memory_node.end >> PAGE_SHIFT)); + + // reserve memory for simple memory allocator + start = (uint64_t)&__heap_start - UPPER_ADDR_SPACE_BASE; + end = ALIGN_UP((uint64_t)simple_malloc_get_remainder() - UPPER_ADDR_SPACE_BASE, PAGE_SIZE) + 8 * PAGE_SIZE; + reserve_memory(start, end); +} + +void _create_memory_unusedmap(){ + uint64_t unused_start = 0; + struct list_head *node; + struct mem_block *mb; + struct mem_block *tmp_mb; + + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + if(unused_start < mb->start){ + tmp_mb = (struct mem_block*)simple_malloc(sizeof(struct mem_block)); + + tmp_mb->start = unused_start; + tmp_mb->end = mb->start; + list_add_tail(&tmp_mb->list, &mem_unusedmap); + INFO("unused map: start = %p, end = %p", tmp_mb->start, tmp_mb->end); + } + unused_start = mb->end; + } + + if(unused_start < memory_node.end){ + tmp_mb = (struct mem_block*)simple_malloc(sizeof(struct mem_block)); + tmp_mb->start = unused_start; + tmp_mb->end = memory_node.end; + list_add_tail(&tmp_mb->list, &mem_unusedmap); + } +} + +void* _get_memory_node(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + static int found_memory_node = 0; + uint32_t* pw; + if(node != NULL && strcmp(node->name, "memory@0") == 0){ + memory_node.name = "memory@0"; + found_memory_node = 1; + } + if(found_memory_node && prop != NULL && strcmp(prop->name, "reg") == 0){ + pw = (uint32_t*)prop->value; + memory_node.start = bswap32(pw[0]); + memory_node.end = memory_node.start + bswap32(pw[1]); + found_memory_node = 0; + } +} + + +void mm_init(void *dtb){ + INFO("Init mm subsystem.."); + // initialize mm's global variable + INIT_LIST_HEAD(&mem_rsvmap); + INIT_LIST_HEAD(&mem_unusedmap); + fdt_parser((uint8_t*)dtb, _get_memory_node); + + _create_memory_rsvmap(dtb); + _create_memory_unusedmap(); + + INFO("Memory node: %s, size: %p", memory_node.name, memory_node.end - memory_node.start); + INFO("Memory reserved size: %p", get_reserved_size()); + INFO("Memory unused size : %p", get_unused_size()); + + // initialize buddy system + buddy_init(); + + print_buddy_statistics(); + + /* if(debug) + debug_slab();*/ + + kmalloc_init(); + +/* if(debug){ + debug_kmalloc(); + //debug_buddy(); + print_buddy_statistics(); + }*/ + +} diff --git a/lab6/mm/mmu.c b/lab6/mm/mmu.c new file mode 100644 index 000000000..f0ffd6171 --- /dev/null +++ b/lab6/mm/mmu.c @@ -0,0 +1,398 @@ +#include "mm/mmu.h" +#include "mm/mm.h" +#include "kernel/fault.h" +#include "kernel/sched/task.h" +#include "kernel/signal.h" + +extern int __reserved_page_table_start, __reserved_page_table_end; +extern int __PGD_start, __PGD_end; +extern int __PUD_start, __PUD_end; +extern int __PMD_start, __PMD_end; +extern int __PTE_start, __PTE_end; +extern struct mem_node memory_node; + +void page_init(){ + uint64_t daif = local_irq_disable_save(); + uint64_t pgt_start = (uint64_t)&__reserved_page_table_start; + uint64_t pgt_end = (uint64_t)&__reserved_page_table_end; + uint64_t pgd = (uint64_t)&__PGD_start; + uint64_t pud = (uint64_t)&__PUD_start; + uint64_t pmd = (uint64_t)&__PMD_start; + uint64_t pte = (uint64_t)&__PTE_start; + pgdval_t* tmp_pgd_e = (pgdval_t*)pgd; + pudval_t* tmp_pud_e = (pudval_t*)pud; + pmdval_t* tmp_pmd_e = (pmdval_t*)pmd; + pteval_t* tmp_pte_e = (pteval_t*)pte; + uint64_t mem_size = ALIGN_UP(memory_node.end - memory_node.start, PAGE_SIZE); + uint64_t max_page_num = mem_size / PAGE_SIZE; + + pgd = virt_to_phys(pgd); + pud = virt_to_phys(pud); + pmd = virt_to_phys(pmd); + pte = virt_to_phys(pte); + + // memset((void*)pgt_start, 0, pgt_end - pgt_start); + + INFO("mem_size: %p", mem_size); + INFO("max number of page: %p", max_page_num); + + INFO("Initialize 4-level page table for upper address space"); + + INFO("level 4 page table at %p...", tmp_pte_e); + for(uint64_t i = 0 ; i < max_page_num ; i++){ + pte_set(tmp_pte_e, VM_PTE_NORMAL_ATTR | (i * PAGE_SIZE)); + tmp_pte_e++; + } + + for(uint64_t i = max_page_num ; i < 2 * 512 * 512; i++){ + pte_set(tmp_pte_e, VM_PTE_DEVICE_ATTR | (i * PAGE_SIZE)); + tmp_pte_e++; + } + + INFO("level 3 page table %p...", tmp_pmd_e); + for(uint64_t i = 0 ; i < 2 * 512 ; i++){ + pmd_set(tmp_pmd_e, VM_PMD_ATTR | (pte + i * PAGE_SIZE)); + tmp_pmd_e++; + } + + INFO("level 2 page table %p...", tmp_pud_e); + for(uint64_t i = 0 ; i < 2 ; i++){ + pud_set(tmp_pud_e, VM_PUD_ATTR | (pmd + i * PAGE_SIZE)); + tmp_pud_e++; + } + + INFO("level 1 page table %p...", tmp_pgd_e); + asm volatile( + "dsb ish\n\t" // ensure write has completed + "tlbi vmalle1is\n\t" // invalidate all TLB entries + "dsb ish\n\t" // ensure completion of TLB invalidatation + "isb\n\t" // clear pipeline + ); + local_irq_restore(daif); + INFO("finish"); +} + +void mappages(pgdval_t* pgd, uint64_t va, uint64_t pa, uint64_t size, uint64_t prot, uint64_t set_attr){ + //LOG("mappages start"); + uint64_t vstart, vend; + uint64_t pgtable = 0; + pudval_t* pgd_e; + pudval_t* pud_e; + pmdval_t* pmd_e; + pteval_t* pte_e; + size = ALIGN_UP(size, PAGE_SIZE); + //LOG("mappages(%p, %p, %p, %l, %p)", pgd, va, pa, size, prot); + for(vstart = va, vend = va + size ; vstart != vend ; vstart += PAGE_SIZE){ + // LOG("physical addr: %p", pa); + pgd_e = pgd_offset(pgd, vstart); + if(pgd_none(*pgd_e)){ + pgtable = virt_to_phys(calloc_page()); + pgd_set(pgd_e, PGD_TYPE_TABLE | pgtable); + LOG("pgd_e: %p, *pgd_e = %p\r\n",pgd_e, *pgd_e); + } + + pud_e = pud_offset(pgd_e, vstart); + if(pud_none(*pud_e)){ + pgtable = virt_to_phys(calloc_page()); + pud_set(pud_e, PUD_TYPE_TABLE | pgtable); + LOG("pud_e: %p, *pud_e = %p\r\n",pud_e, *pud_e); + } + + pmd_e = pmd_offset(pud_e, vstart); + if(pmd_none(*pmd_e)){ + pgtable = virt_to_phys(calloc_page()); + pmd_set(pmd_e, PMD_TYPE_TABLE | pgtable); + LOG("pmd_e: %p, *pmd_e = %p\r\n",pmd_e, *pmd_e); + } + + pte_e = pte_offset(pmd_e, vstart); + //printf("pte_index(%p) = %p\r\n", vstart, pte_index(vstart)); + + + if(set_attr){ + // only set attribute + if(!pte_none(*pte_e)){ + pte_set(pte_e, prot | pte_val(pte_e)); + } + }else{ + if(!pte_none(*pte_e)){ + INFO("error: try to overwrite pte"); + while(1); + }else{ + pte_set(pte_e, prot | PAGE_ATTR_AF | (pa & PHYS_ADDR_MASK)); + } + } + //LOG("pte_e: %p, *pte_e = %p\r\n",pte_e, *pte_e); + pa += PAGE_SIZE; + } + //LOG("mappages end"); +} + +void dup_pages(pgdval_t* dst_pgd, pgdval_t* src_pgd, uint64_t va, uint64_t size, uint64_t prot){ + LOG("dup_pages start"); + uint64_t vstart, vend; + uint64_t pgtable = 0; + pudval_t* tmp_pgd_e, *pgd_e; + pudval_t* tmp_pud_e, *pud_e; + pmdval_t* tmp_pmd_e, *pmd_e; + pteval_t* tmp_pte_e, *pte_e; + size = ALIGN_UP(size, PAGE_SIZE); + LOG("dup_pages(%p, %p, %p, %p, %p)", dst_pgd, src_pgd, va, size, prot); + for(vstart = va, vend = va + size ; vstart != vend ; vstart += PAGE_SIZE){ + tmp_pgd_e = pgd_offset(src_pgd, vstart); + pgd_e = pgd_offset(dst_pgd, vstart); + if(pgd_none(*pgd_e)){ + pgtable = virt_to_phys(calloc_page()); + pgd_set(pgd_e, (*tmp_pgd_e & ~PHYS_ADDR_MASK) | pgtable); + LOG("tmp_pgd_e: %p, *tmp_pgd_e = %p",tmp_pgd_e, *tmp_pgd_e); + LOG("pgd_e: %p, *pgd_e: %p",pgd_e, *pgd_e); + } + + + tmp_pud_e = pud_offset(tmp_pgd_e, vstart); + pud_e = pud_offset(pgd_e, vstart); + if(pud_none(*pud_e)){ + pgtable = virt_to_phys(calloc_page()); + pud_set(pud_e, (*tmp_pud_e & ~PHYS_ADDR_MASK) | pgtable); + LOG("tmp_pud_e: %p, *tmp_pud_e = %p",tmp_pud_e, *tmp_pud_e); + LOG("pud_e: %p, *pud_e: %p",pud_e, *pud_e); + + } + + tmp_pmd_e = pmd_offset(tmp_pud_e, vstart); + pmd_e = pmd_offset(pud_e, vstart); + if(pmd_none(*pmd_e)){ + pgtable = virt_to_phys(calloc_page()); + pmd_set(pmd_e, (*tmp_pmd_e & ~PHYS_ADDR_MASK) | pgtable); + LOG("tmp_pmd_e: %p, *tmp_pmd_e = %p",tmp_pmd_e, *tmp_pmd_e); + LOG("pmd_e: %p, *pmd_e: %p",pmd_e, *pmd_e); + } + + tmp_pte_e = pte_offset(tmp_pmd_e, vstart); + if(!pte_none(*tmp_pte_e)){ + // Since we have implement demand paging, sometimes page is not exist in memory + pte_e = pte_offset(pmd_e, vstart); + pte_set(pte_e, pte_val(tmp_pte_e) | prot); + // add 1 to page reference count + pte_reuse(pte_e); + LOG("tmp_pte_e: %p, *tmp_pte_e = %p",tmp_pte_e, *tmp_pte_e); + LOG("pte_e: %p, *pte_e: %p, pte_ref_cnt(%p) = %p ",pte_e, *pte_e, pte_e, pte_ref_cnt(pte_e)); + } + } + LOG("dup_pages end"); +} +void free_one_pte(pteval_t* pte){ + //LOG("free_one_pte(%p)", pte); + pteval_t* pte_e = pte; + void* page_frame; + for(uint64_t i = 0 ; i < 512 ; i++){ + if(!pte_none(pte_e[i])){ + page_frame = (void*)phys_to_virt(pte_e[i] & PHYS_ADDR_MASK); + //LOG("free page frame: %p", page_frame); + free_page(page_frame); + } + } + free_page(pte); +} + +void free_one_pmd(pmdval_t* pmd){ + //LOG("free_one_pmd(%p)", pmd); + pmdval_t* pmd_e = pmd; + pteval_t* pte; + for(uint64_t i = 0 ; i < 512 ; i++){ + if(!pmd_none(pmd_e[i])){ + pte = (pteval_t*)phys_to_virt(pmd_e[i] & PHYS_ADDR_MASK); + free_one_pte(pte); + } + } + free_page(pmd); +} + +void free_one_pud(pudval_t* pud){ + //LOG("free_one_pud(%p)", pud); + pudval_t* pud_e = pud; + pmdval_t* pmd; + for(uint64_t i = 0 ; i < 512 ; i++){ + if(!pud_none(pud_e[i])){ + pmd = (pmdval_t*)phys_to_virt(pud_e[i] & PHYS_ADDR_MASK); + free_one_pmd(pmd); + } + } + free_page(pud); +} + +void free_one_pgd(pgdval_t* pgd){ + //LOG("free_one_pgd(%p)", pgd); + pgdval_t* pgd_e = pgd; + pudval_t* pud; + for(uint64_t i = 0 ; i < 512 ; i++){ + if(!pgd_none(pgd_e[i])){ + pud = (pudval_t*)phys_to_virt(pgd_e[i] & PHYS_ADDR_MASK); + free_one_pud(pud); + } + } + free_page(pgd); +} +pteval_t* get_pte(pgdval_t* pgd, uint64_t addr){ + uint64_t pgtable; + pudval_t* pgd_e; + pudval_t* pud_e; + pmdval_t* pmd_e; + pteval_t* pte_e; + + pgd_e = pgd_offset(pgd, addr); + if(pgd_none(*pgd_e)){ + pgtable = virt_to_phys(calloc_page()); + pgd_set(pgd_e, PGD_TYPE_TABLE | pgtable); + LOG("pgd_e: %p, *pgd_e = %p\r\n",pgd_e, *pgd_e); + } + + pud_e = pud_offset(pgd_e, addr); + if(pud_none(*pud_e)){ + pgtable = virt_to_phys(calloc_page()); + pud_set(pud_e, PUD_TYPE_TABLE | pgtable); + LOG("pud_e: %p, *pud_e = %p\r\n",pud_e, *pud_e); + } + + pmd_e = pmd_offset(pud_e, addr); + if(pmd_none(*pmd_e)){ + pgtable = virt_to_phys(calloc_page()); + pmd_set(pmd_e, PMD_TYPE_TABLE | pgtable); + LOG("pmd_e: %p, *pmd_e = %p\r\n",pmd_e, *pmd_e); + } + + pte_e = pte_offset(pmd_e, addr); + return pte_e; +} + +void free_page_table(pgdval_t* pgd){ + LOG("free_page_table(%p)", pgd); + free_one_pgd(pgd); +} + +uint64_t do_file_page(pteval_t* pte_e, struct mm_struct* mm, struct vm_area_struct* vma, uint64_t addr, uint64_t vm_flags){ + //INFO("start do_file_fault, page ref count: %p, value of pte: %p", pte_ref_cnt(pte_e), pte_val(pte_e)); + uint64_t offset = addr - vma->vm_start; + char* filename = vma->filename; + uint8_t* page; + + page = alloc_page(); + initrdfs_loadfile(filename, page, offset, PAGE_SIZE); + mappages(mm->pgd, addr, virt_to_phys(page), PAGE_SIZE, VM_PTE_USER_ATTR, 0); + + //INFO("end do_file_fault page ref count: %p, value of pte: %p", pte_ref_cnt(pte_e), pte_val(pte_e)); + return VM_FAULT_NONE; +} + +uint64_t do_anonymous_page(pteval_t* pte_e, struct mm_struct* mm, struct vm_area_struct* vma, uint64_t addr){ + uint64_t page_frame; + if(vma->type == VMA_VC_RAM){ + // identity mapping + pte_set(pte_e, addr | VM_PTE_USER_ATTR); + }else{ + page_frame = virt_to_phys(calloc_page()); + mappages(mm->pgd, addr, page_frame, PAGE_SIZE, VM_PTE_USER_ATTR, 0); + } + return VM_FAULT_NONE; +} + +uint64_t do_wp_page(pteval_t* pte_e, struct mm_struct* mm, struct vm_area_struct* vma, uint64_t addr){ + struct page* page = pte_page(pte_e); + uint8_t * old_page, * new_page; + uint64_t new_page_frame, orig_attr; + + INFO("start do_wp_page, page ref count: %p, value of pte: %p", pte_ref_cnt(pte_e), pte_val(pte_e)); + if(pte_ref_cnt(pte_e) == 1){ + pte_set(pte_e, pte_val(pte_e) & ~PAGE_ATTR_RDONLY); + }else{ + INFO("start COW"); + old_page = page_to_virt(page); + new_page = alloc_page(); + new_page_frame = virt_to_phys(new_page); + orig_attr = pte_val(pte_e) & ~PAGE_ATTR_RDONLY & ~PHYS_ADDR_MASK; + + memcpy(new_page, old_page, PAGE_SIZE); + pte_set(pte_e, orig_attr | new_page_frame); + free_page(old_page); + } + INFO("end do_wp_page page ref count: %p, value of pte: %p", pte_ref_cnt(pte_e), pte_val(pte_e)); + return VM_FAULT_NONE; +} + +uint64_t handle_mm_fault(struct mm_struct* mm, struct vm_area_struct* vma, uint64_t far, uint64_t vm_flags){ + uint64_t addr = ALIGN_DOWN(far, PAGE_SIZE); + pteval_t *pte_e = get_pte(mm->pgd, addr); + uint64_t ret; + if(pte_none(*pte_e)){ + // page frame does not exist in memory + if(vma->type == VMA_FILE){ + // handle file mapping page frame + ret = do_file_page(pte_e, mm ,vma, addr, vm_flags); + }else{ + ret = do_anonymous_page(pte_e, mm, vma, addr); + } + printf("%l: [Translation fault]: %p\r\n",get_current()->thread_info.pid, far); + }else{ + // page frame exists in memory + // copy on write + if(vm_flags & VMA_PROT_WRITE && !pte_writable(pte_e)){ + ret = do_wp_page(pte_e, mm, vma, addr); + printf("%l: [COPY ON WRITE]: %p\r\n",get_current()->thread_info.pid, far); + }else{ + // which kind of situation will lead execution flow to here??? + printf("[Unknown MMU fault]: %p\r\n", far); + INFO("vm_flags: %p, *pte_e: %p\r\n", vm_flags, *pte_e); + while(1); + } + } + return ret; +} + +uint64_t do_page_fault(uint64_t esr, uint64_t far){ + struct vm_area_struct* vma; + struct task_struct* current = get_current(); + uint32_t ec = esr >> 26; + uint64_t vm_flags = 0; + if(ec == FAULT_INSTR_ABORT_LOW_EL){ + vm_flags |= VMA_PROT_EXEC; + }else{ + // get WnR ( wirte not read ) bit + vm_flags |= (esr & (1 << 6)) ? VMA_PROT_WRITE : VMA_PROT_READ; + } + + //check if far is in user space + //INFO("far: %p", far); + if(far >= VM_USER_SPACE){ + return VM_FAULT_BADACCESS; + } + // check if the far is in mm + vma = find_vma(current->mm, far); + if(vma == NULL){ + // access invalid address + return VM_FAULT_BADMAP; + } + // check if proccess has permission + if(!(vma->vm_flags & vm_flags)){ + return VM_FAULT_BADACCESS; + } + + return handle_mm_fault(current->mm, vma, far, vm_flags); +} +void do_mem_abort(uint64_t esr, uint64_t far){ + uint64_t fault; + // IFSC: instruct fault status code + // DFSC: data fault status code + uint8_t dfsc = esr & 0b111111; + if(dfsc == 8 || dfsc == 12){ + printf("unkown memory fault\r\n"); + while(1); + }else if(dfsc >= 4 && dfsc <= 15){ + fault = do_page_fault(esr, far); + } + if(fault != VM_FAULT_NONE){ + // send signal to notify proccess that MMU error occess + send_signal(get_current()->thread_info.pid, SIG_SIGSEGV); + } + return; +} + diff --git a/lab6/mm/page_alloc.c b/lab6/mm/page_alloc.c new file mode 100644 index 000000000..73de432f8 --- /dev/null +++ b/lab6/mm/page_alloc.c @@ -0,0 +1,410 @@ +#include "mm/page_alloc.h" +static struct buddy_system buddy; +extern struct mem_node memory_node; +void _init_mem_map(){ + struct list_head *node; + struct mem_block *mb; + uint64_t start_pfn, end_pfn, size; + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + + start_pfn = virt_to_pfn(mb->start + UPPER_ADDR_SPACE_BASE); + end_pfn = virt_to_pfn(mb->end + UPPER_ADDR_SPACE_BASE); + size = (end_pfn - start_pfn) * sizeof(struct page); + + memset(&mem_map[start_pfn], '\0', size); + } + + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + + start_pfn = virt_to_pfn(mb->start + UPPER_ADDR_SPACE_BASE); + end_pfn = virt_to_pfn(mb->end + UPPER_ADDR_SPACE_BASE); + for(uint64_t i = start_pfn ; i < end_pfn ; i++){ + memset(&mem_map[i], '\0', sizeof(struct page)); + mem_map[i].type = PAGE_TYPE_RESERVED; + } + } +} + +void __free_pages(struct page* page, uint32_t order){ + volatile uint64_t daif; + struct page* end_page = page + (1 << order); + + // initialize buddy group leader and add it to free list + page->order = order; + list_add(&page->list, &buddy.free_lists[order].list); + buddy.free_lists[order].count++; + + // initialize buddy group members + + for(struct page* p = page + 1 ; p < end_page ; p++){ + p->order = BUDDY_GROUP_MEMBER; + } +} + +void _free_pages_memory(uint64_t start, uint64_t end){ + // start and end is page frame number ( pfn ) + uint64_t order; + while(start < end){ + order = min(BUDDY_MAX_ORDER - 1, _buddy_ffs(start)); + + // decrease the order if last page's pfn in buddy is larger than end + while(start + (1 << order) > end) order--; + + __free_pages(&mem_map[start], order); + start += (1 << order); + } +} + +void _free_pages(struct page* page, uint32_t order){ + struct page* buddy_page; + uint64_t pfn = page_to_pfn(page); + uint64_t buddy_pfn; + + if(PAGE_IS_RESERVED(page)){ + INFO("Error: _free_pages(%u) try to free reserved pfn %p", order, pfn); + } + // check the order of page + if(BUDDY_IS_FREED(page)){ + INFO("Error: _free_pages(%u) try to free freed pfn %p", order, pfn); + return; + } + if(order > _buddy_ffs(pfn)){ + INFO("Error: _free_pages(%u) try to free pfn %p", order, pfn); + return; + } + + while(order < BUDDY_MAX_ORDER - 1){ + buddy_pfn = find_buddy_pfn(pfn, order); + buddy_page = pfn_to_page(buddy_pfn); + + if(!PAGE_IS_RESERVED(buddy_page) && BUDDY_IS_FREED(buddy_page) && buddy_page->order == order){ + // Check if buddy is not reserved and freed + LOG("%p is buddy of %p in order %u free list and it can be merged", pfn_to_virt(buddy_pfn), pfn_to_virt(pfn), order); + list_del(&buddy_page->list); + buddy.free_lists[order].count--; + }else{ + break; + } + + pfn = pfn & ~(1 << order); + page = pfn_to_page(pfn); + order++; + } + + LOG("Merge %p into order %u free list ", pfn_to_virt(pfn), order); + __free_pages(page, order); + LOG("end merge pages"); +} + +// free 2^order pages +void free_pages(void* addr, uint32_t order){ + LOG("_free_pages(%p, %u)",addr, order); + volatile uint64_t daif; + uint64_t pfn = virt_to_pfn(addr); + struct page *page; + if(pfn >= (memory_node.end >> PAGE_SHIFT)){ + //INFO("try to free pfn %p that not belong to memory", pfn); + return; + } + page = pfn_to_page(pfn); + + daif = local_irq_disable_save(); + page->ref_cnt--; + if(page->ref_cnt == 0){ + _free_pages(page, order); + }else{ + LOG("addr: %p, ref_cnt: %p", addr, page->ref_cnt); + } + local_irq_restore(daif); +} + +// free one page +void free_page(void* addr){ + volatile uint64_t daif; + uint64_t pfn = virt_to_pfn(addr); + struct page *page; + if(pfn >= (memory_node.end >> PAGE_SHIFT)){ + //INFO("try to free pfn %p that not belong to memory", pfn); + return; + } + page = pfn_to_page(pfn); + + daif = local_irq_disable_save(); + page->ref_cnt--; + if(page->ref_cnt == 0){ + _free_pages(page, 0); + }else{ + LOG("addr: %p, ref_cnt: %p", addr, page->ref_cnt); + } + local_irq_restore(daif); +} + +// split large buddy group to two small buddy groups +void expand(struct page *page, uint32_t high, uint32_t low){ + struct page* tmp_page; + volatile uint64_t daif; + while(high > low){ + high--; + tmp_page = page + (1 << high); + + LOG("add page %p to order %u free list",page_to_virt(tmp_page) , high); + __free_pages(tmp_page, high); + } +} + +struct page* _alloc_pages(uint32_t order){ + LOG("_alloc_pages(%u)", order); + struct list_head *node; + struct free_list* free_list; + struct page* page, *tmp_page; + + // find appropriate buddy group for user + for(uint32_t i = order ; i < BUDDY_MAX_ORDER ; i++){ + free_list = &buddy.free_lists[i]; + + if(list_empty(&free_list->list)){ + LOG("free list of order %u is empty", i); + continue; + } + + page = list_first_entry(&free_list->list, struct page, list); + list_del(&page->list); + free_list->count--; + LOG("get free page %p from order %u", page_to_virt(page), i); + + + for(uint32_t j = 0 ; j < (1 << order) ; j++){ + page[j].order = BUDDY_ALLOCATED|order; + page[j].buddy_leader = page; + } + + if(i > order){ + LOG("start expand pages of order %u to order %u", i, order); + expand(page, i, order); + LOG("end expand pages from order %u to order %u", i, order); + } + return page; + } + return NULL; +} + +// return 2^order pages +void* alloc_pages(uint32_t order){ + if(order > BUDDY_MAX_ORDER - 1) return NULL; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + struct page* page = _alloc_pages(order); + page->ref_cnt++; + local_irq_restore(daif); + + return page_to_virt(page); +} + +// return one page +void* alloc_page(){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + struct page* page = _alloc_pages(0); + page->ref_cnt++; + local_irq_restore(daif); + + return page_to_virt(page); +} + +void* calloc_page(){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + struct page* page = _alloc_pages(0); + page->ref_cnt++; + local_irq_restore(daif); + memset(page_to_virt(page), 0, PAGE_SIZE); + return page_to_virt(page); +} + +void print_buddy_statistics(){ + uint64_t free_page_count = 0; + uint64_t tmp; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + INFO("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + INFO("Total free page #: %l", free_page_count); +} + +uint8_t* _debug_alloc_page(uint32_t order){ + LOG("###########################################"); + uint64_t free_page_count = 0; + uint64_t tmp; + uint8_t * ret; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + LOG("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + ret = alloc_pages(order); + LOG("Total free page #: %l", free_page_count); + LOG("allocate page: %p", ret); + return ret; +} + +uint8_t* _debug_free_page(void *addr, uint32_t order){ + LOG("###########################################"); + uint64_t free_page_count = 0; + uint64_t tmp; + uint8_t * ret; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + LOG("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + free_pages(addr, order); + LOG("Total free page #: %l", free_page_count); + LOG("freed page: %p", addr); + return ret; +} + +void debug_buddy(){ + uint8_t *arr[1500]; + int32_t i = 0, count = 0; + struct list_head* node; + struct page* page, *target_page; + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(1); + count++; + } + for(i = 0 ; i < 4; i++){ + arr[count] = _debug_alloc_page(2); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(3); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(1); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(2); + count++; + } + for(i = 0 ; i < 1400; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + LOG("###########################################"); + for(i = 0 ; i < count ; i++){ + target_page = virt_to_page(arr[i]); + if(!BUDDY_IS_ALLOCATED(target_page)){ + LOG("******* page %p didn't set to allocated *******", page_to_virt(page)); + goto error; + } + for(uint32_t j = 0 ; j < BUDDY_MAX_ORDER ; j++){ + list_for_each(node, &buddy.free_lists[j].list){ + page = list_entry(node, struct page, list); + if(target_page == page){ + LOG("******* allocated page didn't remove from free list *******", page_to_virt(page)); + goto error; + } + } + } + } + count = 0; + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 1); + count++; + } + for(i = 0 ; i < 4; i++){ + _debug_free_page(arr[count], 2); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 3); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 1); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 2); + count++; + } + for(i = 0 ; i < 1400; i++){ + _debug_free_page(arr[count], 0); + count++; + } + // check the integrity of linked list by using grep to check how many unique lines + // + // ./debug.sh > t + // grep "\[test\]" t|sort|uniq|wc -l + // + struct list_head* tmp_node; + struct page* tmp_page; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + list_for_each(tmp_node, &buddy.free_lists[i].list){ + tmp_page = list_entry(tmp_node, struct page, list); + for(uint32_t j = 0; j < (1 << i) ; j++){ + printf("[test] : %p\n", page_to_virt(tmp_page + j)); + } + } + } + LOG("******* Pass the testcases *******"); + return; +error: + LOG("******* Something is wrong in buddy system alloc_pages *******"); + return; +} +void buddy_init(){ + struct list_head * node; + struct mem_block* mb; + uint64_t start_pfn, end_pfn; + + INFO("Initialize buddy system..."); + // Initialize global variable + memset(&buddy, '\0', sizeof(struct buddy_system)); + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER; i++){ + INIT_LIST_HEAD(&buddy.free_lists[i].list); + } + + // Initialize mem map + _init_mem_map(); + + // Add free page frame to buddy system + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + start_pfn = virt_to_pfn(mb->start + UPPER_ADDR_SPACE_BASE); + end_pfn = virt_to_pfn(mb->end + UPPER_ADDR_SPACE_BASE); + + _free_pages_memory(start_pfn, end_pfn); + } + +} diff --git a/lab6/mm/slab.c b/lab6/mm/slab.c new file mode 100644 index 000000000..76956fa34 --- /dev/null +++ b/lab6/mm/slab.c @@ -0,0 +1,251 @@ +#include "mm/slab.h" + +struct list_head kmem_cache[KMEM_CACHE_NUM] = {0}; + +struct slab* slab_create(size_t obj_size){ + size_t allocated_size; + uint32_t order = 0; + size_t page_num; + void* pages; + struct slab * pslab; + + // object size align to slab_alignment + obj_size = ALIGN_UP(obj_size, SLAB_ALIGNMENT); + + // check if obj_size exceed slab's limit + if(obj_size > SLAB_MAX_OBJECT_SIZE){ + LOG("invalid obj_size: %l, slab_max_object_size is %l", obj_size, SLAB_MAX_OBJECT_SIZE); + return NULL; + } + + // get sufficient order + //page_num = ALIGN_UP(obj_size + SLAB_SIZE, 4096) >> PAGE_SHIFT; + order = BUDDY_MAX_ORDER - 1; + pages = alloc_pages(order); + if(pages == NULL){ + LOG("Not enough page for slab"); + return NULL; + } + + // initialize struct slab + pslab = pages; + pslab->size = obj_size; + pslab->s_mem = pages + SLAB_SIZE; + pslab->inuse = 0; + INIT_LIST_HEAD(&pslab->free_list); + + return pslab; +} + +void slab_destroy(struct slab* slab){ + size_t page_num; + struct page* page = virt_to_page(slab); + volatile uint64_t daif; + LOG("slab_destroy recycle order %u buddy %p", (void*)slab, get_page_order(page)); + // free pages + free_pages((void*)slab, get_page_order(page)); +} + +void *slab_alloc(struct slab* slab){ + void *ret = NULL; + struct page* page; + uint32_t order; + size_t max_size; + volatile uint64_t daif; + daif = local_irq_disable_save(); + if(!list_empty(&slab->free_list)){ + // check free list + ret = slab->free_list.next; + list_del(slab->free_list.next); + slab->inuse++; + }else{ + page = virt_to_page(slab); + order = get_page_order(page); + max_size = (1 << order) * PAGE_SIZE; + if(SLAB_SIZE + (slab->inuse + 1) * slab->size > max_size){ + ret = NULL; + }else{ + ret = (uint8_t*)slab->s_mem + slab->inuse * slab->size; + slab->inuse++; + } + } + local_irq_restore(daif); + return ret; +} + +void slab_free(struct slab* slab, void* obj){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + list_add((struct list_head*)obj, &slab->free_list); + slab->inuse--; + local_irq_restore(daif); +} + +void kmalloc_init(){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + for(uint64_t i = 0 ; i < KMEM_CACHE_NUM ; i++){ + INIT_LIST_HEAD(&kmem_cache[i]); + } + local_irq_restore(daif); +} +void* kmalloc(size_t size){ + uint64_t cache_idx; + struct list_head* cache_list, *node; + struct slab *s; + void * ret = NULL; + volatile uint64_t daif; + + size = ALIGN_UP(size, SLAB_ALIGNMENT); + + LOG("kmalloc(%u) start", size); + if(size > SLAB_MAX_OBJECT_SIZE){ + LOG("kmalloc invalid size %l", size); + return NULL; + } + // allocate memory from corresponding cache bin + cache_idx = ALIGN_UP(size, SLAB_ALIGNMENT) / SLAB_ALIGNMENT; + + daif = local_irq_disable_save(); + cache_list = &kmem_cache[cache_idx]; + + list_for_each(node, cache_list){ + s = list_entry(node, struct slab, list); + ret = slab_alloc(s); + if(ret != NULL){ + LOG("kmalloc(%u) found a free object %p in kmem_cache[%u]", size, ret, cache_idx); + break; + } + } + + if(ret == NULL){ + s = slab_create(size); + list_add(&s->list, cache_list); + ret = slab_alloc(s); + if(ret != NULL){ + LOG("kmalloc(%u) found a free object %p in kmem_cache[%u]", size, ret, cache_idx); + } + } + local_irq_restore(daif); + + LOG("kmalloc s->inuse: %x", s->inuse); + LOG("kmalloc(%u) end, ret: %p", size, ret); + return ret; +} + +void kfree(void* obj){ + volatile uint64_t daif = local_irq_disable_save(); + uint64_t pfn = virt_to_pfn(ALIGN_DOWN(obj, PAGE_SIZE)); + struct page* page = pfn_to_page(pfn); + struct page* buddy_leader = get_buddy_leader(page); + struct slab* s = page_to_virt(buddy_leader); + + slab_free(s, obj); + LOG("kfree(%p) free an object, s->inuse: %l", obj, s->inuse); + + if(s->inuse < 0){ + LOG("[Error]: s->inuse : %p", s->inuse); + } + if(s->inuse == 0){ + LOG("kfree(%p) triger recycle unused slab", obj); + + list_del(&s->list); + slab_destroy(s); + } + local_irq_restore(daif); +} + +#define TEST_SIZE 64 +#define TEST_INVALID_SIZE ((1 << (BUDDY_MAX_ORDER - 1)) * PAGE_SIZE - SLAB_SIZE + 1) +void debug_slab(){ + uint32_t i, max_i; + uint8_t *a[ (1 << BUDDY_MAX_ORDER - 1) * PAGE_SIZE / TEST_SIZE]; + + struct slab* s = slab_create(TEST_SIZE); + + for(i = 0 ; i < 30; i++){ + a[i] = slab_alloc(s); + LOG("%u: slab_alloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("slab is full"); + break; + } + } + max_i = i; + for(i = 0 ; i < max_i ; i++){ + slab_free(s, a[i]); + } + + for(i = 0 ; i < 30; i++){ + a[i] = slab_alloc(s); + LOG("%u: slab_alloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("slab is full"); + break; + } + } + + + + for(i = 0 ; i < max_i ; i++){ + slab_free(s, a[i]); + } + + slab_destroy(s); + uint64_t pfn = virt_to_pfn(s); + struct page* page = pfn_to_page(pfn); + + if(BUDDY_IS_FREED(page) && get_page_order(page) == BUDDY_MAX_ORDER - 1){ + LOG("slab_destroy success"); + }else{ + + LOG("slab_destroy failed"); + } + + s = slab_create(TEST_INVALID_SIZE); + + if(s == NULL){ + LOG("create super large slab %l failed", TEST_INVALID_SIZE); + }else{ + LOG("create super large slab %l success", TEST_INVALID_SIZE); + } +} + +void debug_kmalloc(){ + uint32_t i, max_i; + uint8_t *a[20]; + + + for(i = 0 ; i < 20; i++){ + a[i] = kmalloc(TEST_SIZE); + LOG("%l: kmalloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("kmalloc is failed"); + break; + } + } + + max_i = i; + for(i = 0 ; i < max_i ; i++){ + LOG("kfree(%p)", a[i]); + kfree(a[i]); + } +/* + for(i = 0 ; i < 200; i++){ + a[i] = kmalloc(TEST_SIZE); + LOG("%u: kmalloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("kmalloc is failed"); + break; + } + } + + for(i = 0 ; i < max_i ; i++){ + kfree(a[i]); + } +*/ +} diff --git a/lab6/peripherals/Makefile b/lab6/peripherals/Makefile new file mode 100644 index 000000000..50b5d0780 --- /dev/null +++ b/lab6/peripherals/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + mini_uart.o \ + mailbox.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab6/peripherals/mailbox.c b/lab6/peripherals/mailbox.c new file mode 100644 index 000000000..90435180a --- /dev/null +++ b/lab6/peripherals/mailbox.c @@ -0,0 +1,150 @@ +#include "peripherals/mailbox.h" + +static uint32_t MBox_buf[4096] __attribute__((aligned(16))); + +static uint32_t MBox_read(int channel){ + int ch, data; + + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_EMPTY_MASK); + + data = mbox_reg->read; + ch = data & MBOX_WRITE_CHANNEL_MASK; + if(ch == channel){ + LOG("MBox read address: %p", data & MBOX_READ_ADDR_MASK); + return (data & MBOX_READ_ADDR_MASK); + } + LOG("Leave"); + return 0; +} + +static void MBox_write(uint32_t data, int channel){ + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_FULL_MASK); + + mbox_reg->write = data | channel; + LOG("Leave"); +} + +static uint32_t MBox_process(uint8_t* tags, size_t tags_size){ + LOG("Enter"); + MBox_buffer* mbuf = (MBox_buffer*)MBox_buf; + // set buffer header + mbuf->buf_size = tags_size + 12; + mbuf->code = MBOX_STATUS_REQUEST; + + // copy tags to buffer + memcpy(mbuf->buf, tags, tags_size); + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + LOG("mbuf->buf: %p", mbuf->buf); + LOG("mbuf->buf + tags_size: %p", mbuf->buf + tags_size); + // end of MBox_buf + memset(mbuf->buf + tags_size, 0, 4); + + pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + // write to mailbox + MBox_write((uint32_t)(uint64_t)virt_to_phys(MBox_buf), MBOX_CHANNEL_PROPERTY_TAGS); + + // read from mailbox + uint32_t result = MBox_read(MBOX_CHANNEL_PROPERTY_TAGS); + + + LOG("Leave"); + return result; +} +void MBox_get_board_revision(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 4]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_BOARD_REVISION; + tag->value_size = 4; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer*)phys_to_virt(MBox_process(buf, sizeof(MBox_tag) + 4)); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + *ret = ((uint32_t*)tag->values)[0]; + LOG("Leave"); +} +void MBox_get_arm_memory(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 8]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_ARM_MEMORY; + tag->value_size = 8; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + ((uint32_t*)tag->values)[1] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer*)phys_to_virt(MBox_process(buf, sizeof(MBox_tag) + 8)); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + ret[0] = ((uint32_t*)tag->values)[0]; + ret[1] = ((uint32_t*)tag->values)[1]; + LOG("Leave"); +} + +int Mbox_call(uint32_t* mbox, uint8_t ch) { + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_FULL_MASK); + + mbox_reg->write = ((uint32_t)(uint64_t)mbox & ~0xF) | ch; + + while (mbox_reg->status & MBOX_STATUS_EMPTY_MASK); + + return mbox_reg->read == (((uint32_t)(uint64_t)mbox & ~0xF) | ch); +} +int sys_mbox_call(uint8_t ch, uint32_t *mbox){ + uint64_t va = (uint64_t)mbox; + uint64_t pa; + struct task_struct* current = get_current(); + struct page* page; + int ret; + pgdval_t* pgd_e; + pudval_t* pud_e; + pmdval_t* pmd_e; + pteval_t* pte_e; + + LOG("va: %p",va); + pgd_e = pgd_offset(current->mm->pgd, va); + LOG("*pgd_e: %p",*pgd_e); + pud_e = pud_offset(pgd_e, va); + LOG("*pud_e: %p",*pud_e); + pmd_e = pmd_offset(pud_e, va); + LOG("*pmd_e: %p",*pmd_e); + pte_e = pte_offset(pmd_e, va); + LOG("*pte_e: %p",*pte_e); + page = pte_page(pte_e); + pa = page_to_phys(page) | ((uint64_t)mbox & 0xfff); + LOG("page_to_phys: %p, page_to_pfn: %p, pa: %p", page_to_phys(page), page_to_pfn(page), pa); + ret = Mbox_call((uint32_t *)pa, ch); + LOG("ret: %p", ret); + return ret; +} diff --git a/lab6/peripherals/mini_uart.c b/lab6/peripherals/mini_uart.c new file mode 100644 index 000000000..999947352 --- /dev/null +++ b/lab6/peripherals/mini_uart.c @@ -0,0 +1,159 @@ +#include "peripherals/mini_uart.h" + +static ring_buffer* rx_rbuf = NULL; + +inline void delay_cycles(uint64_t n){ + for(register uint64_t i = 0 ; i < n ; i++) asm volatile("nop"); +} + +inline void enable_mini_uart_rx_irq(){ +} + +inline void disable_mini_uart_rx_irq(){ +} + +void mini_uart_init(){ + // GPIO 14 & 15 take function 0 + // Read out GPFSEL1 register + uint32_t tmp = IO_MMIO_read32(GPFSEL1); + + // Set GPIO 14 & 15 function bits + tmp &= ~(0b111111 << 12); + tmp |= 0b010010 << 12; + IO_MMIO_write32(GPFSEL1, tmp); + + + // disable pull-up/down of GPIO 14 & 15 + // Write to GPPUD to set the required control signal + IO_MMIO_write32(GPPUD, 0); + + // Wait 150 cycles – this provides the required set-up time for the control signal + delay_cycles(150); + + // Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to modify + IO_MMIO_write32(GPPUDCLK0, (1 << 14) | (1 << 15)); + + // Wait 150 cycles – this provides the required hold time for the control signal + delay_cycles(150); + + // Write to GPPUD to remove the control signa + IO_MMIO_write32(GPPUD, 0); + + // Write to GPPUDCLK0/1 to remove the clock + IO_MMIO_write32(GPPUDCLK0, 0); + + // Initialize Auxiliary peripherals Register + // Mini UART enable + IO_MMIO_write32(AUX_ENABLES, 1); + + // To disable auto flow control and disable receiver and transmitter, set control register to 0 + IO_MMIO_write32(AUX_MU_CNTL_REG, 0); + + // Disable mini UART's interrupt + IO_MMIO_write32(AUX_MU_IER_REG, 0); + + // Set UART to 8-bit mode + IO_MMIO_write32(AUX_MU_LCR_REG, 3); + + // To indicate that our UART is able to receive data, set RTS line to be always high + IO_MMIO_write32(AUX_MU_MCR_REG, 0); + + // Set Baud rate to 115200 + IO_MMIO_write32(AUX_MU_BAUD_REG, BAUD_RATE_REG); + + // disable FIFO + IO_MMIO_write32(AUX_MU_IIR_REG, 6); + + // Start UART + IO_MMIO_write32(AUX_MU_CNTL_REG, 3); + + return; +} + +uint8_t mini_uart_read(void){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & 0x1)); + return IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; +} + +void mini_uart_write(uint8_t val){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & (0x1 << 5))); + IO_MMIO_write32(AUX_MU_IO_REG, val); +} + +ssize_t write_bytes(uint8_t* buf, size_t n){ + for(uint64_t i = 0 ; i < n ; i++) mini_uart_write(buf[i]); + return n; +} + +void write_str(char* buf){ + while(*buf) mini_uart_write((uint8_t)*buf++); + return; +} + +void write_hex(uint64_t n){ + int i = 0; + char buf[16]; + char *hex_table = "0123456789abcdef"; + do{ + buf[i] = hex_table[n & 0xf]; + n = n >> 4; + i++; + }while(n); + do{ + i--; + mini_uart_write(buf[i]); + }while(i > 0); +} + +void mini_uart_irq_init(){ + rx_rbuf = create_simple_ring_buf(4095); + + IO_MMIO_write32(AUX_MU_IER_REG, 1); + IO_MMIO_write32(ENABLE_IRQS_1, 1 << 29); +} + + +void mini_uart_rx_softirq_callback(){ +} + +void mini_uart_irq_read(){ + uint8_t b[1]; + b[0] = IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; + ring_buf_write_unsafe(rx_rbuf, b, 1); +} + +size_t mini_uart_get_rx_len(){ + return ring_buf_get_len(rx_rbuf); +} + +uint8_t mini_uart_aio_read(void){ + uint8_t b[1]; + IO_MMIO_write32(AUX_MU_IER_REG, 1); + while(!ring_buf_read(rx_rbuf, b, 1)); + IO_MMIO_write32(AUX_MU_IER_REG, 0); + return b[0]; +} + +size_t sys_uart_write(char *buf, size_t size){ + uint64_t daif,ret; + //size_t c; + daif = local_irq_disable_save(); + ret = write_bytes(buf, size); + local_irq_restore(daif); + return ret; +} + +size_t sys_uart_read(char *buf, size_t size){ + size_t c = 0, tmp; + + IO_MMIO_write32(AUX_MU_IER_REG, 1); + while(size){ + tmp = ring_buf_read(rx_rbuf, buf + c, size); + + size = size - tmp; + c = c + tmp; + preempt_schedule(); + } + IO_MMIO_write32(AUX_MU_IER_REG, 0); + return c; +} diff --git a/lab6/test/lib/.gdb_history b/lab6/test/lib/.gdb_history new file mode 100644 index 000000000..58afc787f --- /dev/null +++ b/lab6/test/lib/.gdb_history @@ -0,0 +1,2 @@ +run +quit diff --git a/lab6/test/lib/dtb_parse/.gdb_history b/lab6/test/lib/dtb_parse/.gdb_history new file mode 100644 index 000000000..8ae386791 --- /dev/null +++ b/lab6/test/lib/dtb_parse/.gdb_history @@ -0,0 +1,43 @@ +b main +run +n +quit +run +p fdt +quit +b main +n +run +n +x/gx ptr +quit +b main +run +n +statbuf->size +p statbuf->size +p statbuf->st_size +quit +run +b main +run +n +s +n +p token +p/x pdft_struct +p/x pdt_struct +x/gx 0x7ffff7fb3048 +x/s 0x7ffff7fb3048 +x/dx 0x7ffff7fb3048 +x/wx 0x7ffff7fb3048 +x/4wx 0x7ffff7fb3048 +n +p len +n +quit +quit +run +quit +run +quit diff --git a/lab6/test/lib/dtb_parse/Makefile b/lab6/test/lib/dtb_parse/Makefile new file mode 100644 index 000000000..d6e1a8f08 --- /dev/null +++ b/lab6/test/lib/dtb_parse/Makefile @@ -0,0 +1,2 @@ +all: + gcc main.c fdt_parse.c -o main -g -O0 diff --git a/lab6/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb b/lab6/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 000000000..6f9ef31cc Binary files /dev/null and b/lab6/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb differ diff --git a/lab6/test/lib/dtb_parse/fdt_parse.c b/lab6/test/lib/dtb_parse/fdt_parse.c new file mode 100644 index 000000000..bb8abd2c8 --- /dev/null +++ b/lab6/test/lib/dtb_parse/fdt_parse.c @@ -0,0 +1,113 @@ +#include "fdt_parse.h" +#include +#include +#include + +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } + +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = (fdt_header*)malloc(sizeof(fdt_header)); + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) / 4; + //printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + len += 2; + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + printf("Parsing error!!\n"); + exit(0); + } + } +} + +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab6/test/lib/dtb_parse/fdt_parse.h b/lab6/test/lib/dtb_parse/fdt_parse.h new file mode 100644 index 000000000..876b4087a --- /dev/null +++ b/lab6/test/lib/dtb_parse/fdt_parse.h @@ -0,0 +1,53 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +#endif diff --git a/lab6/test/lib/dtb_parse/main b/lab6/test/lib/dtb_parse/main new file mode 100755 index 000000000..aa43f24f6 Binary files /dev/null and b/lab6/test/lib/dtb_parse/main differ diff --git a/lab6/test/lib/dtb_parse/main.c b/lab6/test/lib/dtb_parse/main.c new file mode 100644 index 000000000..9af1de752 --- /dev/null +++ b/lab6/test/lib/dtb_parse/main.c @@ -0,0 +1,19 @@ +#include "fdt_parse.h" +#include +#include +#include +#include +#include +#include + +int main(void){ + int fd = open("./bcm2710-rpi-3-b-plus.dtb", O_RDONLY); + if(fd < 0){ + printf("failed to open file\n"); + } + struct stat statbuf; + fstat(fd, &statbuf); + char *ptr = mmap(NULL,statbuf.st_size,PROT_READ,MAP_PRIVATE,fd,0); + + fdt_parser(ptr, fdt_print_callback); +} diff --git a/lab6/test/lib/dtb_parse/tmp.dts b/lab6/test/lib/dtb_parse/tmp.dts new file mode 100644 index 000000000..1ceb3539f --- /dev/null +++ b/lab6/test/lib/dtb_parse/tmp.dts @@ -0,0 +1,1515 @@ +/dts-v1/; + +/memreserve/ 0x0000000000000000 0x0000000000001000; +/ { + compatible = "raspberrypi,3-model-b-plus\0brcm,bcm2837"; + model = "Raspberry Pi 3 Model B+"; + #address-cells = <0x01>; + #size-cells = <0x01>; + interrupt-parent = <0x01>; + + aliases { + serial0 = "/soc/serial@7e215040"; + serial1 = "/soc/serial@7e201000"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + aux = "/soc/aux@7e215000"; + sound = "/soc/sound"; + soc = "/soc"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + uart0 = "/soc/serial@7e201000"; + uart1 = "/soc/serial@7e215040"; + sdhost = "/soc/mmc@7e202000"; + mmc = "/soc/mmc@7e300000"; + mmc1 = "/soc/mmcnr@7e300000"; + mmc0 = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c1 = "/soc/i2c@7e804000"; + i2c10 = "/soc/i2c0mux/i2c@1"; + spi0 = "/soc/spi@7e204000"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + usb = "/soc/usb@7e980000"; + leds = "/leds"; + fb = "/soc/fb"; + thermal = "/soc/thermal@7e212000"; + axiperf = "/soc/axiperf"; + i2c2 = "/soc/i2c@7e805000"; + ethernet0 = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + }; + + chosen { + bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; + }; + + reserved-memory { + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges; + phandle = <0x37>; + + linux,cma { + compatible = "shared-dma-pool"; + size = <0x4000000>; + reusable; + linux,cma-default; + phandle = <0x38>; + }; + }; + + thermal-zones { + + cpu-thermal { + polling-delay-passive = <0x00>; + polling-delay = <0x3e8>; + thermal-sensors = <0x02>; + coefficients = <0xfffffde6 0x64960>; + phandle = <0x39>; + + cooling-maps { + }; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x7e000000 0x3f000000 0x1000000 0x40000000 0x40000000 0x1000>; + dma-ranges = <0xc0000000 0x00 0x3f000000>; + phandle = <0x3a>; + + txp@7e004000 { + compatible = "brcm,bcm2835-txp"; + reg = <0x7e004000 0x20>; + interrupts = <0x01 0x0b>; + status = "disabled"; + phandle = <0x3b>; + }; + + cprman@7e101000 { + compatible = "brcm,bcm2835-cprman"; + #clock-cells = <0x01>; + reg = <0x7e101000 0x2000>; + clocks = <0x03 0x04 0x00 0x04 0x01 0x04 0x02 0x05 0x00 0x05 0x01 0x05 0x02>; + firmware = <0x06>; + phandle = <0x08>; + }; + + mailbox@7e00b880 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0x00 0x01>; + #mbox-cells = <0x00>; + phandle = <0x1f>; + }; + + gpio@7e200000 { + compatible = "brcm,bcm2835-gpio"; + reg = <0x7e200000 0xb4>; + interrupts = <0x02 0x11 0x02 0x12>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x07 0x00 0x00 0x36>; + pinctrl-names = "default"; + gpio-line-names = "ID_SDA\0ID_SCL\0SDA1\0SCL1\0GPIO_GCLK\0GPIO5\0GPIO6\0SPI_CE1_N\0SPI_CE0_N\0SPI_MISO\0SPI_MOSI\0SPI_SCLK\0GPIO12\0GPIO13\0TXD1\0RXD1\0GPIO16\0GPIO17\0GPIO18\0GPIO19\0GPIO20\0GPIO21\0GPIO22\0GPIO23\0GPIO24\0GPIO25\0GPIO26\0GPIO27\0HDMI_HPD_N\0STATUS_LED_G\0CTS0\0RTS0\0TXD0\0RXD0\0SD1_CLK\0SD1_CMD\0SD1_DATA0\0SD1_DATA1\0SD1_DATA2\0SD1_DATA3\0PWM0_OUT\0PWM1_OUT\0ETH_CLK\0WIFI_CLK\0SDA0\0SCL0\0SMPS_SCL\0SMPS_SDA\0SD_CLK_R\0SD_CMD_R\0SD_DATA0_R\0SD_DATA1_R\0SD_DATA2_R\0SD_DATA3_R"; + phandle = <0x07>; + + dpi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x06>; + phandle = <0x3c>; + }; + + emmc_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x07>; + phandle = <0x3d>; + }; + + emmc_gpio34 { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x3e>; + }; + + emmc_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x07>; + phandle = <0x17>; + }; + + gpclk0_gpio4 { + brcm,pins = <0x04>; + brcm,function = <0x04>; + phandle = <0x3f>; + }; + + gpclk1_gpio5 { + brcm,pins = <0x05>; + brcm,function = <0x04>; + phandle = <0x40>; + }; + + gpclk1_gpio42 { + brcm,pins = <0x2a>; + brcm,function = <0x04>; + phandle = <0x41>; + }; + + gpclk1_gpio44 { + brcm,pins = <0x2c>; + brcm,function = <0x04>; + phandle = <0x42>; + }; + + gpclk2_gpio6 { + brcm,pins = <0x06>; + brcm,function = <0x04>; + phandle = <0x43>; + }; + + gpclk2_gpio43 { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x44>; + }; + + i2c0_gpio0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x12>; + }; + + i2c0_gpio28 { + brcm,pins = <0x1c 0x1d>; + brcm,function = <0x04>; + phandle = <0x45>; + }; + + i2c0_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x05>; + phandle = <0x13>; + }; + + i2c1_gpio2 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x46>; + }; + + i2c1_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x06>; + phandle = <0x47>; + }; + + jtag_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x03>; + phandle = <0x48>; + }; + + pcm_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x49>; + }; + + pcm_gpio28 { + brcm,pins = <0x1c 0x1d 0x1e 0x1f>; + brcm,function = <0x06>; + phandle = <0x4a>; + }; + + sdhost_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x04>; + phandle = <0x0d>; + }; + + spi0_gpio7 { + brcm,pins = <0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x4b>; + }; + + spi0_gpio35 { + brcm,pins = <0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x04>; + phandle = <0x4c>; + }; + + spi1_gpio16 { + brcm,pins = <0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x03>; + phandle = <0x4d>; + }; + + spi2_gpio40 { + brcm,pins = <0x28 0x29 0x2a 0x2b 0x2c 0x2d>; + brcm,function = <0x03>; + phandle = <0x4e>; + }; + + uart0_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x04>; + phandle = <0x4f>; + }; + + uart0_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x07>; + phandle = <0x50>; + }; + + uart0_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x07>; + brcm,pull = <0x02 0x00>; + phandle = <0x51>; + }; + + uart0_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x52>; + }; + + uart0_gpio36 { + brcm,pins = <0x24 0x25>; + brcm,function = <0x06>; + phandle = <0x53>; + }; + + uart0_ctsrts_gpio38 { + brcm,pins = <0x26 0x27>; + brcm,function = <0x06>; + phandle = <0x54>; + }; + + uart1_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x02>; + phandle = <0x55>; + }; + + uart1_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x02>; + phandle = <0x56>; + }; + + uart1_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x02>; + phandle = <0x57>; + }; + + uart1_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x02>; + phandle = <0x58>; + }; + + uart1_gpio40 { + brcm,pins = <0x28 0x29>; + brcm,function = <0x02>; + phandle = <0x59>; + }; + + uart1_ctsrts_gpio42 { + brcm,pins = <0x2a 0x2b>; + brcm,function = <0x02>; + phandle = <0x5a>; + }; + + i2c_slave_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x07>; + phandle = <0x5b>; + }; + + jtag_gpio4 { + brcm,pins = <0x04 0x05 0x06 0x0c 0x0d>; + brcm,function = <0x02>; + phandle = <0x5c>; + }; + + pwm0_gpio12 { + brcm,pins = <0x0c>; + brcm,function = <0x04>; + phandle = <0x5d>; + }; + + pwm0_gpio18 { + brcm,pins = <0x12>; + brcm,function = <0x02>; + phandle = <0x5e>; + }; + + pwm0_gpio40 { + brcm,pins = <0x28>; + brcm,function = <0x04>; + phandle = <0x5f>; + }; + + pwm1_gpio13 { + brcm,pins = <0x0d>; + brcm,function = <0x04>; + phandle = <0x60>; + }; + + pwm1_gpio19 { + brcm,pins = <0x13>; + brcm,function = <0x02>; + phandle = <0x61>; + }; + + pwm1_gpio41 { + brcm,pins = <0x29>; + brcm,function = <0x04>; + phandle = <0x62>; + }; + + pwm1_gpio45 { + brcm,pins = <0x2d>; + brcm,function = <0x04>; + phandle = <0x63>; + }; + + dpi_18bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + brcm,pull = <0x00>; + phandle = <0x64>; + }; + + dpi_18bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + phandle = <0x65>; + }; + + dpi_18bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x66>; + }; + + dpi_18bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x67>; + }; + + dpi_16bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x68>; + }; + + dpi_16bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x69>; + }; + + dpi_16bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6a>; + }; + + dpi_16bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6b>; + }; + + gpioout { + brcm,pins = <0x06>; + brcm,function = <0x01>; + phandle = <0x6c>; + }; + + alt0 { + brcm,pins = <0x04 0x05 0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x6d>; + }; + + spi0_pins { + brcm,pins = <0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x0f>; + }; + + spi0_cs_pins { + brcm,pins = <0x08 0x07>; + brcm,function = <0x01>; + phandle = <0x10>; + }; + + i2c0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x6e>; + }; + + i2c1 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x18>; + }; + + i2s { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x0e>; + }; + + sdio_pins { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x1e>; + }; + + bt_pins { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x0a>; + }; + + uart0_pins { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x09>; + }; + + uart1_pins { + brcm,pins; + brcm,function; + brcm,pull; + phandle = <0x16>; + }; + + audio_pins { + brcm,pins = <0x28 0x29>; + brcm,function = <0x04>; + phandle = <0x20>; + }; + }; + + serial@7e201000 { + compatible = "arm,pl011\0arm,primecell"; + reg = <0x7e201000 0x200>; + interrupts = <0x02 0x19>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk\0apb_pclk"; + arm,primecell-periphid = <0x241011>; + cts-event-workaround; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x09 0x0a>; + status = "okay"; + phandle = <0x26>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <0x2dc6c0>; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x33>; + }; + }; + + mmc@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <0x02 0x18>; + clocks = <0x08 0x14>; + status = "okay"; + dmas = <0x0c 0x2000000d>; + dma-names = "rx-tx"; + bus-width = <0x04>; + brcm,overclock-50 = <0x00>; + brcm,pio-limit = <0x01>; + firmware = <0x06>; + pinctrl-names = "default"; + pinctrl-0 = <0x0d>; + phandle = <0x2f>; + }; + + i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; + reg = <0x7e203000 0x24>; + clocks = <0x08 0x1f>; + status = "disabled"; + dmas = <0x0c 0x02 0x0c 0x03>; + dma-names = "tx\0rx"; + #sound-dai-cells = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x0e>; + phandle = <0x28>; + }; + + spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x200>; + interrupts = <0x02 0x16>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + dmas = <0x0c 0x06 0x0c 0x07>; + dma-names = "tx\0rx"; + pinctrl-names = "default"; + pinctrl-0 = <0x0f 0x10>; + cs-gpios = <0x07 0x08 0x01 0x07 0x07 0x01>; + phandle = <0x29>; + + spidev@0 { + compatible = "spidev"; + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x6f>; + }; + + spidev@1 { + compatible = "spidev"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x70>; + }; + }; + + i2c@7e205000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e205000 0x200>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x11>; + }; + + i2c0mux { + compatible = "i2c-mux-pinctrl"; + #address-cells = <0x01>; + #size-cells = <0x00>; + i2c-parent = <0x11>; + pinctrl-names = "i2c0\0i2c_csi_dsi"; + status = "disabled"; + pinctrl-0 = <0x12>; + pinctrl-1 = <0x13>; + phandle = <0x2a>; + + i2c@0 { + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x71>; + }; + + i2c@1 { + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x72>; + }; + }; + + dpi@7e208000 { + compatible = "brcm,bcm2835-dpi"; + reg = <0x7e208000 0x8c>; + clocks = <0x08 0x14 0x08 0x2c>; + clock-names = "core\0pixel"; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x73>; + }; + + dsi@7e209000 { + compatible = "brcm,bcm2835-dsi0"; + reg = <0x7e209000 0x78>; + interrupts = <0x02 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x20 0x08 0x2f 0x08 0x31>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi0_byte\0dsi0_ddr2\0dsi0_ddr"; + status = "disabled"; + power-domains = <0x14 0x11>; + phandle = <0x04>; + }; + + aux@7e215000 { + compatible = "brcm,bcm2835-aux"; + #clock-cells = <0x01>; + reg = <0x7e215000 0x08>; + clocks = <0x08 0x14>; + phandle = <0x15>; + }; + + serial@7e215040 { + compatible = "brcm,bcm2835-aux-uart"; + reg = <0x7e215040 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x00>; + status = "okay"; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x16>; + phandle = <0x27>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = "\0\a\b"; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x74>; + }; + }; + + spi@7e215080 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e215080 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x75>; + }; + + spi@7e2150c0 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e2150c0 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x02>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x76>; + }; + + pwm@7e20c000 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x7e20c000 0x28>; + clocks = <0x08 0x1e>; + assigned-clocks = <0x08 0x1e>; + assigned-clock-rates = <0x989680>; + #pwm-cells = <0x02>; + status = "disabled"; + phandle = <0x77>; + }; + + mmc@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + status = "disabled"; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x17>; + bus-width = <0x04>; + phandle = <0x30>; + }; + + hvs@7e400000 { + compatible = "brcm,bcm2835-hvs"; + reg = <0x7e400000 0x6000>; + interrupts = <0x02 0x01>; + status = "disabled"; + phandle = <0x78>; + }; + + dsi@7e700000 { + compatible = "brcm,bcm2835-dsi1"; + reg = <0x7e700000 0x8c>; + interrupts = <0x02 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x23 0x08 0x30 0x08 0x32>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi1_byte\0dsi1_ddr2\0dsi1_ddr"; + status = "disabled"; + power-domains = <0x14 0x12>; + phandle = <0x05>; + }; + + i2c@7e804000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e804000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x18>; + clock-frequency = <0x186a0>; + phandle = <0x2b>; + }; + + usb@7e980000 { + compatible = "brcm,bcm2708-usb"; + reg = <0x7e980000 0x10000 0x7e006000 0x1000>; + interrupts = <0x01 0x09 0x02 0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x19>; + clock-names = "otg"; + phys = <0x1a>; + phy-names = "usb2-phy"; + interrupt-names = "usb\0soft"; + power-domains = <0x14 0x06>; + phandle = <0x79>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet@1 { + compatible = "usb424,7800"; + reg = <0x01>; + phandle = <0x7a>; + + mdio { + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet-phy@1 { + reg = <0x01>; + microchip,led-modes = <0x01 0x06>; + microchip,eee-enabled; + microchip,tx-lpi-timer = <0x258>; + microchip,downshift-after = <0x02>; + phandle = <0x36>; + }; + }; + }; + }; + }; + }; + + dma@7e007000 { + compatible = "brcm,bcm2835-dma"; + reg = <0x7e007000 0xf00>; + interrupts = <0x01 0x10 0x01 0x11 0x01 0x12 0x01 0x13 0x01 0x14 0x01 0x15 0x01 0x16 0x01 0x17 0x01 0x18 0x01 0x19 0x01 0x1a 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1c>; + interrupt-names = "dma0\0dma1\0dma2\0dma3\0dma4\0dma5\0dma6\0dma7\0dma8\0dma9\0dma10\0dma11\0dma12\0dma13\0dma14\0dma-shared-all"; + #dma-cells = <0x01>; + brcm,dma-channel-mask = <0x7f35>; + phandle = <0x0c>; + }; + + interrupt-controller@7e00b200 { + compatible = "brcm,bcm2836-armctrl-ic"; + reg = <0x7e00b200 0x200>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + interrupts = <0x08 0x04>; + phandle = <0x01>; + }; + + watchdog@7e100000 { + compatible = "brcm,bcm2835-pm\0brcm,bcm2835-pm-wdt"; + #power-domain-cells = <0x01>; + #reset-cells = <0x01>; + reg = <0x7e100000 0x114 0x7e00a000 0x24>; + clocks = <0x08 0x15 0x08 0x1d 0x08 0x17 0x08 0x16>; + clock-names = "v3d\0peri_image\0h264\0isp"; + system-power-controller; + phandle = <0x2d>; + }; + + rng@7e104000 { + compatible = "brcm,bcm2835-rng"; + reg = <0x7e104000 0x10>; + interrupts = <0x02 0x1d>; + phandle = <0x2e>; + }; + + pixelvalve@7e206000 { + compatible = "brcm,bcm2835-pixelvalve0"; + reg = <0x7e206000 0x100>; + interrupts = <0x02 0x0d>; + status = "disabled"; + phandle = <0x7b>; + }; + + pixelvalve@7e207000 { + compatible = "brcm,bcm2835-pixelvalve1"; + reg = <0x7e207000 0x100>; + interrupts = <0x02 0x0e>; + status = "disabled"; + phandle = <0x7c>; + }; + + thermal@7e212000 { + compatible = "brcm,bcm2837-thermal"; + reg = <0x7e212000 0x08>; + clocks = <0x08 0x1b>; + #thermal-sensor-cells = <0x00>; + status = "okay"; + phandle = <0x02>; + }; + + i2c@7e805000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e805000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x1d>; + }; + + vec@7e806000 { + compatible = "brcm,bcm2835-vec"; + reg = <0x7e806000 0x1000>; + clocks = <0x1c 0x0f>; + interrupts = <0x02 0x1b>; + status = "disabled"; + power-domains = <0x14 0x07>; + phandle = <0x7d>; + }; + + pixelvalve@7e807000 { + compatible = "brcm,bcm2835-pixelvalve2"; + reg = <0x7e807000 0x100>; + interrupts = <0x02 0x0a>; + status = "disabled"; + phandle = <0x7e>; + }; + + hdmi@7e902000 { + compatible = "brcm,bcm2835-hdmi"; + reg = <0x7e902000 0x600 0x7e808000 0x100>; + reg-names = "hdmi\0hd"; + interrupts = <0x02 0x08 0x02 0x09>; + ddc = <0x1d>; + clocks = <0x1c 0x09 0x1c 0x0d>; + clock-names = "pixel\0hdmi"; + dmas = <0x0c 0x9000011>; + dma-names = "audio-rx"; + status = "disabled"; + power-domains = <0x14 0x05>; + hpd-gpios = <0x07 0x1c 0x01>; + phandle = <0x7f>; + }; + + v3d@7ec00000 { + compatible = "brcm,vc4-v3d"; + reg = <0x7ec00000 0x1000>; + interrupts = <0x01 0x0a>; + power-domains = <0x14 0x0a>; + status = "disabled"; + phandle = <0x80>; + }; + + gpu { + compatible = "brcm,bcm2835-vc4"; + status = "disabled"; + raspberrypi,firmware = <0x06>; + phandle = <0x81>; + }; + + local_intc@40000000 { + compatible = "brcm,bcm2836-l1-intc"; + reg = <0x40000000 0x100>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + phandle = <0x1b>; + }; + + mmcnr@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + non-removable; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x1e>; + bus-width = <0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x31>; + + wifi@1 { + reg = <0x01>; + compatible = "brcm,bcm4329-fmac"; + phandle = <0x82>; + }; + }; + + firmwarekms@7e600000 { + compatible = "raspberrypi,rpi-firmware-kms"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + brcm,firmware = <0x06>; + status = "disabled"; + phandle = <0x83>; + }; + + smi@7e600000 { + compatible = "brcm,bcm2835-smi"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + clocks = <0x08 0x2a>; + assigned-clocks = <0x08 0x2a>; + assigned-clock-rates = <0x7735940>; + dmas = <0x0c 0x04>; + dma-names = "rx-tx"; + status = "disabled"; + phandle = <0x84>; + }; + + csi@7e800000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e800000 0x800 0x7e802000 0x04>; + interrupts = <0x02 0x06>; + clocks = <0x08 0x2d 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + phandle = <0x85>; + }; + + csi@7e801000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e801000 0x800 0x7e802004 0x04>; + interrupts = <0x02 0x07>; + clocks = <0x08 0x2e 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0d>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + brcm,num-data-lanes = <0x02>; + phandle = <0x86>; + }; + + axiperf { + compatible = "brcm,bcm2835-axiperf"; + reg = <0x7e009800 0x100 0x7ee08000 0x100>; + firmware = <0x06>; + status = "disabled"; + phandle = <0x32>; + }; + + firmware { + compatible = "raspberrypi,bcm2835-firmware\0simple-mfd"; + #address-cells = <0x01>; + #size-cells = <0x01>; + mboxes = <0x1f>; + dma-ranges; + phandle = <0x06>; + + clocks { + compatible = "raspberrypi,firmware-clocks"; + #clock-cells = <0x01>; + phandle = <0x1c>; + }; + + vcio { + compatible = "raspberrypi,vcio"; + phandle = <0x87>; + }; + + expgpio { + compatible = "raspberrypi,firmware-gpio"; + gpio-controller; + #gpio-cells = <0x02>; + gpio-line-names = "BT_ON\0WL_ON\0PWR_LED_R\0LAN_RUN\0NC\0CAM_GPIO0\0CAM_GPIO1\0NC"; + status = "okay"; + phandle = <0x0b>; + }; + }; + + power { + compatible = "raspberrypi,bcm2835-power"; + firmware = <0x06>; + #power-domain-cells = <0x01>; + phandle = <0x14>; + }; + + mailbox@7e00b840 { + compatible = "brcm,bcm2836-vchiq\0brcm,bcm2835-vchiq"; + reg = <0x7e00b840 0x3c>; + interrupts = <0x00 0x02>; + phandle = <0x88>; + + bcm2835_audio { + compatible = "brcm,bcm2835-audio"; + brcm,firmware = <0x06>; + brcm,pwm-channels = <0x08>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x20>; + phandle = <0x2c>; + }; + }; + + gpiomem { + compatible = "brcm,bcm2835-gpiomem"; + reg = <0x7e200000 0x1000>; + }; + + fb { + compatible = "brcm,bcm2708-fb"; + firmware = <0x06>; + status = "okay"; + phandle = <0x89>; + }; + + sound { + status = "disabled"; + phandle = <0x8a>; + }; + }; + + clocks { + + clk-osc { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "osc"; + clock-frequency = <0x124f800>; + phandle = <0x03>; + }; + + clk-usb { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "otg"; + clock-frequency = <0x1c9c3800>; + phandle = <0x19>; + }; + }; + + phy { + compatible = "usb-nop-xceiv"; + #phy-cells = <0x00>; + phandle = <0x1a>; + }; + + arm-pmu { + compatible = "arm,cortex-a53-pmu\0arm,cortex-a7-pmu"; + interrupt-parent = <0x1b>; + interrupts = <0x09 0x04>; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupt-parent = <0x1b>; + interrupts = <0x00 0x04 0x01 0x04 0x03 0x04 0x02 0x04>; + always-on; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + enable-method = "brcm,bcm2836-smp"; + phandle = <0x8b>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x00>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xd8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x22>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x01>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x23>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x02>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x24>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x03>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xf0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x25>; + }; + + l2-cache0 { + compatible = "cache"; + cache-size = <0x80000>; + cache-line-size = <0x40>; + cache-sets = <0x200>; + cache-level = <0x02>; + phandle = <0x21>; + }; + }; + + cam1_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam1-reg"; + enable-active-high; + status = "okay"; + gpio = <0x0b 0x05 0x00>; + phandle = <0x8c>; + }; + + cam1_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8d>; + }; + + cam0_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam0-reg"; + enable-active-high; + status = "disabled"; + phandle = <0x8e>; + }; + + cam0_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8f>; + }; + + cam_dummy_reg { + compatible = "regulator-fixed"; + regulator-name = "cam-dummy-reg"; + status = "okay"; + phandle = <0x90>; + }; + + __overrides__ { + cam0-pwdn-ctrl; + cam0-pwdn; + cam0-led-ctrl; + cam0-led; + arm_freq = "\0\0\0\"clock-frequency:0\0\0\0\0#clock-frequency:0\0\0\0\0$clock-frequency:0\0\0\0\0%clock-frequency:0"; + cache_line_size; + uart0 = "\0\0\0&status"; + uart1 = "\0\0\0'status"; + i2s = "\0\0\0(status"; + spi = "\0\0\0)status"; + i2c0 = [00 00 00 11 73 74 61 74 75 73 00 00 00 00 2a 73 74 61 74 75 73 00]; + i2c1 = "\0\0\0+status"; + i2c0_baudrate = [00 00 00 11 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + i2c1_baudrate = "\0\0\0+clock-frequency:0"; + audio = "\0\0\0,status"; + watchdog = "\0\0\0-status"; + random = "\0\0\0.status"; + sd_overclock = "\0\0\0/brcm,overclock-50:0"; + sd_force_pio = "\0\0\0/brcm,force-pio?"; + sd_pio_limit = "\0\0\0/brcm,pio-limit:0"; + sd_debug = "\0\0\0/brcm,debug"; + sdio_overclock = "\0\0\00brcm,overclock-50:0\0\0\0\01brcm,overclock-50:0"; + axiperf = "\0\0\02status"; + i2c2_iknowwhatimdoing = [00 00 00 1d 73 74 61 74 75 73 00]; + i2c2_baudrate = [00 00 00 1d 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + sd_poll_once = "\0\0\0/non-removable?"; + krnbt = "\0\0\03status"; + krnbt_baudrate = "\0\0\03max-speed:0"; + act_led_gpio = "\0\0\04gpios:4"; + act_led_activelow = "\0\0\04gpios:8"; + act_led_trigger = "\0\0\04linux,default-trigger"; + pwr_led_gpio = "\0\0\05gpios:4"; + pwr_led_activelow = "\0\0\05gpios:8"; + pwr_led_trigger = "\0\0\05linux,default-trigger"; + eee = "\0\0\06microchip,eee-enabled?"; + tx_lpi_timer = "\0\0\06microchip,tx-lpi-timer:0"; + eth_led0 = "\0\0\06microchip,led-modes:0"; + eth_led1 = "\0\0\06microchip,led-modes:4"; + eth_downshift_after = "\0\0\06microchip,downshift-after:0"; + eth_max_speed = "\0\0\06max-speed:0"; + }; + + leds { + compatible = "gpio-leds"; + phandle = <0x91>; + + led-act { + label = "led0"; + default-state = "keep"; + linux,default-trigger = "mmc0"; + gpios = <0x07 0x1d 0x00>; + phandle = <0x34>; + }; + + led-pwr { + label = "led1"; + linux,default-trigger = "default-on"; + gpios = <0x0b 0x02 0x01>; + phandle = <0x35>; + }; + }; + + fixedregulator_3v3 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microvolt = <0x325aa0>; + regulator-name = "3v3"; + phandle = <0x92>; + }; + + fixedregulator_5v0 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x4c4b40>; + regulator-min-microvolt = <0x4c4b40>; + regulator-name = "5v0"; + phandle = <0x93>; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00 0x00>; + }; + + __symbols__ { + rmem = "/reserved-memory"; + cma = "/reserved-memory/linux,cma"; + cpu_thermal = "/thermal-zones/cpu-thermal"; + soc = "/soc"; + txp = "/soc/txp@7e004000"; + clocks = "/soc/cprman@7e101000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + dpi_gpio0 = "/soc/gpio@7e200000/dpi_gpio0"; + emmc_gpio22 = "/soc/gpio@7e200000/emmc_gpio22"; + emmc_gpio34 = "/soc/gpio@7e200000/emmc_gpio34"; + emmc_gpio48 = "/soc/gpio@7e200000/emmc_gpio48"; + gpclk0_gpio4 = "/soc/gpio@7e200000/gpclk0_gpio4"; + gpclk1_gpio5 = "/soc/gpio@7e200000/gpclk1_gpio5"; + gpclk1_gpio42 = "/soc/gpio@7e200000/gpclk1_gpio42"; + gpclk1_gpio44 = "/soc/gpio@7e200000/gpclk1_gpio44"; + gpclk2_gpio6 = "/soc/gpio@7e200000/gpclk2_gpio6"; + gpclk2_gpio43 = "/soc/gpio@7e200000/gpclk2_gpio43"; + i2c0_gpio0 = "/soc/gpio@7e200000/i2c0_gpio0"; + i2c0_gpio28 = "/soc/gpio@7e200000/i2c0_gpio28"; + i2c0_gpio44 = "/soc/gpio@7e200000/i2c0_gpio44"; + i2c1_gpio2 = "/soc/gpio@7e200000/i2c1_gpio2"; + i2c1_gpio44 = "/soc/gpio@7e200000/i2c1_gpio44"; + jtag_gpio22 = "/soc/gpio@7e200000/jtag_gpio22"; + pcm_gpio18 = "/soc/gpio@7e200000/pcm_gpio18"; + pcm_gpio28 = "/soc/gpio@7e200000/pcm_gpio28"; + sdhost_gpio48 = "/soc/gpio@7e200000/sdhost_gpio48"; + spi0_gpio7 = "/soc/gpio@7e200000/spi0_gpio7"; + spi0_gpio35 = "/soc/gpio@7e200000/spi0_gpio35"; + spi1_gpio16 = "/soc/gpio@7e200000/spi1_gpio16"; + spi2_gpio40 = "/soc/gpio@7e200000/spi2_gpio40"; + uart0_gpio14 = "/soc/gpio@7e200000/uart0_gpio14"; + uart0_ctsrts_gpio16 = "/soc/gpio@7e200000/uart0_ctsrts_gpio16"; + uart0_ctsrts_gpio30 = "/soc/gpio@7e200000/uart0_ctsrts_gpio30"; + uart0_gpio32 = "/soc/gpio@7e200000/uart0_gpio32"; + uart0_gpio36 = "/soc/gpio@7e200000/uart0_gpio36"; + uart0_ctsrts_gpio38 = "/soc/gpio@7e200000/uart0_ctsrts_gpio38"; + uart1_gpio14 = "/soc/gpio@7e200000/uart1_gpio14"; + uart1_ctsrts_gpio16 = "/soc/gpio@7e200000/uart1_ctsrts_gpio16"; + uart1_gpio32 = "/soc/gpio@7e200000/uart1_gpio32"; + uart1_ctsrts_gpio30 = "/soc/gpio@7e200000/uart1_ctsrts_gpio30"; + uart1_gpio40 = "/soc/gpio@7e200000/uart1_gpio40"; + uart1_ctsrts_gpio42 = "/soc/gpio@7e200000/uart1_ctsrts_gpio42"; + i2c_slave_gpio18 = "/soc/gpio@7e200000/i2c_slave_gpio18"; + jtag_gpio4 = "/soc/gpio@7e200000/jtag_gpio4"; + pwm0_gpio12 = "/soc/gpio@7e200000/pwm0_gpio12"; + pwm0_gpio18 = "/soc/gpio@7e200000/pwm0_gpio18"; + pwm0_gpio40 = "/soc/gpio@7e200000/pwm0_gpio40"; + pwm1_gpio13 = "/soc/gpio@7e200000/pwm1_gpio13"; + pwm1_gpio19 = "/soc/gpio@7e200000/pwm1_gpio19"; + pwm1_gpio41 = "/soc/gpio@7e200000/pwm1_gpio41"; + pwm1_gpio45 = "/soc/gpio@7e200000/pwm1_gpio45"; + dpi_18bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio0"; + dpi_18bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio2"; + dpi_18bit_gpio0 = "/soc/gpio@7e200000/dpi_18bit_gpio0"; + dpi_18bit_gpio2 = "/soc/gpio@7e200000/dpi_18bit_gpio2"; + dpi_16bit_gpio0 = "/soc/gpio@7e200000/dpi_16bit_gpio0"; + dpi_16bit_gpio2 = "/soc/gpio@7e200000/dpi_16bit_gpio2"; + dpi_16bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio0"; + dpi_16bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio2"; + gpioout = "/soc/gpio@7e200000/gpioout"; + alt0 = "/soc/gpio@7e200000/alt0"; + spi0_pins = "/soc/gpio@7e200000/spi0_pins"; + spi0_cs_pins = "/soc/gpio@7e200000/spi0_cs_pins"; + i2c0_pins = "/soc/gpio@7e200000/i2c0"; + i2c1_pins = "/soc/gpio@7e200000/i2c1"; + i2s_pins = "/soc/gpio@7e200000/i2s"; + sdio_pins = "/soc/gpio@7e200000/sdio_pins"; + bt_pins = "/soc/gpio@7e200000/bt_pins"; + uart0_pins = "/soc/gpio@7e200000/uart0_pins"; + uart1_pins = "/soc/gpio@7e200000/uart1_pins"; + audio_pins = "/soc/gpio@7e200000/audio_pins"; + uart0 = "/soc/serial@7e201000"; + bt = "/soc/serial@7e201000/bluetooth"; + sdhost = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + spi0 = "/soc/spi@7e204000"; + spi = "/soc/spi@7e204000"; + spidev0 = "/soc/spi@7e204000/spidev@0"; + spidev1 = "/soc/spi@7e204000/spidev@1"; + i2c0if = "/soc/i2c@7e205000"; + i2c0mux = "/soc/i2c0mux"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c_csi_dsi = "/soc/i2c0mux/i2c@1"; + dpi = "/soc/dpi@7e208000"; + dsi0 = "/soc/dsi@7e209000"; + aux = "/soc/aux@7e215000"; + uart1 = "/soc/serial@7e215040"; + minibt = "/soc/serial@7e215040/bluetooth"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + pwm = "/soc/pwm@7e20c000"; + mmc = "/soc/mmc@7e300000"; + sdhci = "/soc/mmc@7e300000"; + hvs = "/soc/hvs@7e400000"; + dsi1 = "/soc/dsi@7e700000"; + i2c1 = "/soc/i2c@7e804000"; + usb = "/soc/usb@7e980000"; + ethernet = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + eth_phy = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1/mdio/ethernet-phy@1"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + pm = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + pixelvalve0 = "/soc/pixelvalve@7e206000"; + pixelvalve1 = "/soc/pixelvalve@7e207000"; + thermal = "/soc/thermal@7e212000"; + i2c2 = "/soc/i2c@7e805000"; + vec = "/soc/vec@7e806000"; + pixelvalve2 = "/soc/pixelvalve@7e807000"; + hdmi = "/soc/hdmi@7e902000"; + v3d = "/soc/v3d@7ec00000"; + vc4 = "/soc/gpu"; + local_intc = "/soc/local_intc@40000000"; + mmcnr = "/soc/mmcnr@7e300000"; + brcmf = "/soc/mmcnr@7e300000/wifi@1"; + firmwarekms = "/soc/firmwarekms@7e600000"; + smi = "/soc/smi@7e600000"; + csi0 = "/soc/csi@7e800000"; + csi1 = "/soc/csi@7e801000"; + axiperf = "/soc/axiperf"; + firmware = "/soc/firmware"; + firmware_clocks = "/soc/firmware/clocks"; + vcio = "/soc/firmware/vcio"; + expgpio = "/soc/firmware/expgpio"; + power = "/soc/power"; + vchiq = "/soc/mailbox@7e00b840"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + fb = "/soc/fb"; + sound = "/soc/sound"; + clk_osc = "/clocks/clk-osc"; + clk_usb = "/clocks/clk-usb"; + usbphy = "/phy"; + cpus = "/cpus"; + cpu0 = "/cpus/cpu@0"; + cpu1 = "/cpus/cpu@1"; + cpu2 = "/cpus/cpu@2"; + cpu3 = "/cpus/cpu@3"; + l2 = "/cpus/l2-cache0"; + cam1_reg = "/cam1_regulator"; + cam1_clk = "/cam1_clk"; + cam0_regulator = "/cam0_regulator"; + cam0_clk = "/cam0_clk"; + cam0_reg = "/cam_dummy_reg"; + cam_dummy_reg = "/cam_dummy_reg"; + leds = "/leds"; + act_led = "/leds/led-act"; + pwr_led = "/leds/led-pwr"; + vdd_3v3_reg = "/fixedregulator_3v3"; + vdd_5v0_reg = "/fixedregulator_5v0"; + }; +}; diff --git a/lab6/test/lib/dtb_parse/types.h b/lab6/test/lib/dtb_parse/types.h new file mode 100644 index 000000000..94f612c66 --- /dev/null +++ b/lab6/test/lib/dtb_parse/types.h @@ -0,0 +1,26 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#define NULL ((void*)0) + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) +#endif diff --git a/lab6/test/lib/list/Makefile b/lab6/test/lib/list/Makefile new file mode 100644 index 000000000..764af75c6 --- /dev/null +++ b/lab6/test/lib/list/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/list.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab6/test/lib/list/test b/lab6/test/lib/list/test new file mode 100755 index 000000000..dd63c9895 Binary files /dev/null and b/lab6/test/lib/list/test differ diff --git a/lab6/test/lib/list/test.c b/lab6/test/lib/list/test.c new file mode 100644 index 000000000..b568a42a4 --- /dev/null +++ b/lab6/test/lib/list/test.c @@ -0,0 +1,59 @@ +#include "lib/list.h" +#include +#include +#include +struct student{ + int id; + char name[100]; + struct list_head list; +}; + +struct student* create_student(int id, char* name){ + struct student* s = (struct student*)malloc(sizeof(struct student)); + s->id = id; + strcpy(s->name, name); + return s; +} +void print_student(struct student* s){ + printf("------------------------------------------\n"); + printf(" id: %d\n", s->id); + printf(" name: %s\n", s->name); + printf("------------------------------------------\n"); +} +int main(void){ + struct list_head* node, head; + INIT_LIST_HEAD(&head); + + if(list_empty(&head)){ + printf("List is empty\n"); + } + list_add(&create_student(13, "xiaobye")->list, &head); + list_add(&create_student(35, "test01")->list, &head); + list_add(&create_student(34, "test02")->list, &head); + + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + if(!list_empty(&head)){ + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + } + + + return 0; +} + diff --git a/lab6/test/lib/malloc/.gdb_history b/lab6/test/lib/malloc/.gdb_history new file mode 100644 index 000000000..1b332373d --- /dev/null +++ b/lab6/test/lib/malloc/.gdb_history @@ -0,0 +1,9 @@ +b main +run +ni +x/gx $rax +x/gx $rax - 0x10 + call malloc(1) +x/gx $rax - 0x10 +x/gx 0x5555555592c0 +quit diff --git a/lab6/test/lib/malloc/Makefile b/lab6/test/lib/malloc/Makefile new file mode 100644 index 000000000..2aedecaf1 --- /dev/null +++ b/lab6/test/lib/malloc/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/simple_malloc.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab6/test/lib/malloc/test b/lab6/test/lib/malloc/test new file mode 100755 index 000000000..194c23579 Binary files /dev/null and b/lab6/test/lib/malloc/test differ diff --git a/lab6/test/lib/malloc/test.c b/lab6/test/lib/malloc/test.c new file mode 100644 index 000000000..374f6deff --- /dev/null +++ b/lab6/test/lib/malloc/test.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include "lib/simple_malloc.h" + +#define RANGE 1000 +int main(void){ + void* cur,* next; + size_t req_size, real_size; + void* p = mmap( NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 ); + init_malloc_state(p); + srand((unsigned)time(0)); + + for(int i = 0 ; i < 30 ; i++){ + req_size = (uint64_t)rand() % RANGE; + cur = simple_malloc(req_size); + next = get_remainder(); + real_size = (uint64_t)next - (uint64_t)cur; + printf("cur: %p, next: %p, request size: %lu, real size: %lu, legal: %d\n", cur, next , req_size, real_size, (req_size <= real_size) && !(real_size % 16)); + } + + return 0; +} diff --git a/lab6/test/lib/malloc/test.py b/lab6/test/lib/malloc/test.py new file mode 100644 index 000000000..cce0d171c --- /dev/null +++ b/lab6/test/lib/malloc/test.py @@ -0,0 +1,9 @@ +def req2size(val, a): + if val < 16: + print(val,": ", hex(32)) + else: + print(val,": ",hex((val + 16 + (a - 1)) & ~(a-1))) + +for i in range(0, 64): + req2size(i, 16) + diff --git a/lab6/test/lib/ring_buffer/.gdb_history b/lab6/test/lib/ring_buffer/.gdb_history new file mode 100644 index 000000000..b7bc3d7af --- /dev/null +++ b/lab6/test/lib/ring_buffer/.gdb_history @@ -0,0 +1,17 @@ +run +quit +file main +run +p rbuf +quit +quit +run +x/gx 0x555555556008 +p rbuf->buf[rbuf->head] +s +ni +quit +b main +run +n +quit diff --git a/lab6/test/lib/ring_buffer/Makefile b/lab6/test/lib/ring_buffer/Makefile new file mode 100644 index 000000000..ec3d806b1 --- /dev/null +++ b/lab6/test/lib/ring_buffer/Makefile @@ -0,0 +1,2 @@ +all: + gcc main.c ring_buffer.c -o main -g -O0 diff --git a/lab6/test/lib/ring_buffer/main b/lab6/test/lib/ring_buffer/main new file mode 100755 index 000000000..bc8cc09fa Binary files /dev/null and b/lab6/test/lib/ring_buffer/main differ diff --git a/lab6/test/lib/ring_buffer/main.c b/lab6/test/lib/ring_buffer/main.c new file mode 100644 index 000000000..ea70d0e9b --- /dev/null +++ b/lab6/test/lib/ring_buffer/main.c @@ -0,0 +1,50 @@ +#include "ring_buffer.h" +#include +#include +char* s = "abcdefghijklmn"; +int main(void){ + char b[10]; + ring_buffer* rbuf = create_ring_buf(10); + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } + + ring_buf_write(rbuf, s, 8); + + if(!ring_buf_is_empty(rbuf)){ + printf("Ring buffer is has some contant now!\n"); + int i = ring_buf_read(rbuf, b, 100); + b[i] = '\0'; + + printf("%d: %s\n", i, b); + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } + } + printf("%lu\n", ring_buf_write(rbuf, s, 16)); + if(ring_buf_is_full(rbuf)){ + printf("Ring buffer is full now!\n"); + } + + int i = ring_buf_read(rbuf, b, 4); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + i = ring_buf_write(rbuf, b, 10); + printf("%d\n", i); + + i = ring_buf_read(rbuf, b, 7); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + i = ring_buf_read(rbuf, b, 10); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + if(ring_buf_is_full(rbuf)){ + printf("Ring buffer is full now!\n"); + } + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } +} diff --git a/lab6/test/lib/ring_buffer/ring_buffer.c b/lab6/test/lib/ring_buffer/ring_buffer.c new file mode 100644 index 000000000..a5e7e3612 --- /dev/null +++ b/lab6/test/lib/ring_buffer/ring_buffer.c @@ -0,0 +1,42 @@ +#include "ring_buffer.h" +#include +ring_buffer* create_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)malloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)malloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + return tmp; +} + +uint8_t ring_buf_is_empty(ring_buffer* rbuf){ + if(rbuf->head == rbuf->tail) return 1; + return 0; +} +uint8_t ring_buf_is_full(ring_buffer* rbuf){ + if((rbuf->tail + 1) % (rbuf->size + 1) == rbuf->head) return 1; + return 0; +} +size_t ring_buf_write(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + return count; +} +size_t ring_buf_read(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + return count; +} + diff --git a/lab6/test/lib/ring_buffer/ring_buffer.h b/lab6/test/lib/ring_buffer/ring_buffer.h new file mode 100644 index 000000000..61c0431d4 --- /dev/null +++ b/lab6/test/lib/ring_buffer/ring_buffer.h @@ -0,0 +1,17 @@ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ +#include "types.h" + +typedef struct{ + size_t size; + uint64_t head; + uint64_t tail; + uint8_t* buf; +}ring_buffer; + +extern ring_buffer* create_ring_buf(size_t); +extern size_t ring_buf_write(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read(ring_buffer*, uint8_t*, size_t); +extern uint8_t ring_buf_is_full(ring_buffer*); +extern uint8_t ring_buf_is_empty(ring_buffer*); +#endif diff --git a/lab6/test/lib/ring_buffer/types.h b/lab6/test/lib/ring_buffer/types.h new file mode 100644 index 000000000..94f612c66 --- /dev/null +++ b/lab6/test/lib/ring_buffer/types.h @@ -0,0 +1,26 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#define NULL ((void*)0) + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) +#endif diff --git a/lab6/test/lib/string/.gdb_history b/lab6/test/lib/string/.gdb_history new file mode 100644 index 000000000..d0d68342a --- /dev/null +++ b/lab6/test/lib/string/.gdb_history @@ -0,0 +1,47 @@ +b main +run +n +quit +run +b main +run +n +quit +b main +run +n +run +n +s +s +n +x/gx rax +x/gx $rax +run +s +n +s +x/bx s +s +p c +n +n +quit +b main +run +s +x/s delim +s +s +ni +n +ni +x/s s +x/s pos +x/b pos +x/bx pos +n +n +s +s +quit diff --git a/lab6/test/lib/string/Makefile b/lab6/test/lib/string/Makefile new file mode 100644 index 000000000..e7e0f12c1 --- /dev/null +++ b/lab6/test/lib/string/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/string.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab6/test/lib/string/test b/lab6/test/lib/string/test new file mode 100755 index 000000000..a0a7ea144 Binary files /dev/null and b/lab6/test/lib/string/test differ diff --git a/lab6/test/lib/string/test.c b/lab6/test/lib/string/test.c new file mode 100644 index 000000000..b23d13172 --- /dev/null +++ b/lab6/test/lib/string/test.c @@ -0,0 +1,31 @@ + +// C code to demonstrate working of +// strtok +#include +#include "string.h" + +// Driver function +int main() +{ + // Declaration of string + char *gfg = "setTimeout 123"; + + // Declaration of delimiter + const char s[4] = "-"; + char* tok; + + // Use of strtok + // get first token + tok = strtok(gfg, s); + + // Checks for delimiter + while (tok != 0) { + printf(" %s\n", tok); + + // Use of strtok + // go through other tokens + tok = strtok(0, s); + } + + return (0); +} diff --git a/lab6/tmp b/lab6/tmp new file mode 100644 index 000000000..cfe6ea8df --- /dev/null +++ b/lab6/tmp @@ -0,0 +1,1449 @@ +sudo qemu-system-aarch64 -M raspi3b -kernel /home/xiaobye/Documents/OSDI/osc2022/lab2/build/kernel8.img -display none -serial null -serial stdio -initrd tools/cpio/initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + { + compatible ; + model ; + #address-cells ; + #size-cells ; + interrupt-parent ; + memory@0 { + reg ; + device_type ; + } + aliases { + serial0 ; + serial1 ; + audio ; + aux ; + sound ; + soc ; + dma ; + intc ; + watchdog ; + random ; + mailbox ; + gpio ; + uart0 ; + uart1 ; + sdhost ; + mmc ; + mmc1 ; + mmc0 ; + i2s ; + i2c0 ; + i2c1 ; + i2c10 ; + spi0 ; + spi1 ; + spi2 ; + usb ; + leds ; + fb ; + thermal ; + axiperf ; + i2c2 ; + ethernet0 ; + } + chosen { + linux,initrd-end ; + linux,initrd-start ; + bootargs ; + } + reserved-memory { + #address-cells ; + #size-cells ; + ranges ; + phandle ; + linux,cma { + compatible ; + size ; + reusable ; + linux,cma-default ; + phandle ; + } + } + thermal-zones { + cpu-thermal { + polling-delay-passive ; + polling-delay ; + thermal-sensors ; + coefficients ; + phandle ; + cooling-maps { + } + } + } + soc { + compatible ; + #address-cells ; + #size-cells ; + ranges ; + dma-ranges ; + phandle ; + txp@7e004000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + cprman@7e101000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + firmware ; + phandle ; + } + mailbox@7e00b880 { + compatible ; + reg ; + interrupts ; + #mbox-cells ; + phandle ; + } + gpio@7e200000 { + compatible ; + reg ; + interrupts ; + gpio-controller ; + #gpio-cells ; + interrupt-controller ; + #interrupt-cells ; + gpio-ranges ; + pinctrl-names ; + gpio-line-names ; + phandle ; + dpi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio34 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + emmc_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk0_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio5 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio6 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio43 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + i2c0_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + sdhost_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio7 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio35 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi1_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi2_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio32 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio36 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio38 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio32 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c_slave_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio12 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio13 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio19 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio41 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio45 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + dpi_18bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpioout { + brcm,pins ; + brcm,function ; + phandle ; + } + alt0 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_cs_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2s { + brcm,pins ; + brcm,function ; + phandle ; + } + sdio_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + bt_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart1_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + audio_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + } + serial@7e201000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + arm,primecell-periphid ; + cts-event-workaround ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + status ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + mmc@7e202000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + bus-width ; + brcm,overclock-50 ; + brcm,pio-limit ; + firmware ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + i2s@7e203000 { + compatible ; + reg ; + clocks ; + status ; + dmas ; + dma-names ; + #sound-dai-cells ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + spi@7e204000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + dmas ; + dma-names ; + pinctrl-names ; + pinctrl-0 ; + cs-gpios ; + phandle ; + spidev@0 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + spidev@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + } + i2c@7e205000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + i2c0mux { + compatible ; + #address-cells ; + #size-cells ; + i2c-parent ; + pinctrl-names ; + status ; + pinctrl-0 ; + pinctrl-1 ; + phandle ; + i2c@0 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + i2c@1 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + } + dpi@7e208000 { + compatible ; + reg ; + clocks ; + clock-names ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + dsi@7e209000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + aux@7e215000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + phandle ; + } + serial@7e215040 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + spi@7e215080 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + spi@7e2150c0 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + pwm@7e20c000 { + compatible ; + reg ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + #pwm-cells ; + status ; + phandle ; + } + mmc@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + brcm,overclock-50 ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + phandle ; + } + hvs@7e400000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + dsi@7e700000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + i2c@7e804000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + pinctrl-names ; + pinctrl-0 ; + clock-frequency ; + phandle ; + } + usb@7e980000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + clocks ; + clock-names ; + phys ; + phy-names ; + interrupt-names ; + power-domains ; + phandle ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + ethernet@1 { + compatible ; + reg ; + phandle ; + mdio { + #address-cells ; + #size-cells ; + ethernet-phy@1 { + reg ; + microchip,led-modes ; + microchip,eee-enabled ; + microchip,tx-lpi-timer ; + microchip,downshift-after ; + phandle ; + } + } + } + } + } + } + dma@7e007000 { + compatible ; + reg ; + interrupts ; + interrupt-names ; + #dma-cells ; + brcm,dma-channel-mask ; + phandle ; + } + interrupt-controller@7e00b200 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + interrupts ; + phandle ; + } + watchdog@7e100000 { + compatible ; + #power-domain-cells ; + #reset-cells ; + reg ; + clocks ; + clock-names ; + system-power-controller ; + phandle ; + } + rng@7e104000 { + compatible ; + reg ; + interrupts ; + phandle ; + } + pixelvalve@7e206000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + pixelvalve@7e207000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + thermal@7e212000 { + compatible ; + reg ; + clocks ; + #thermal-sensor-cells ; + status ; + phandle ; + } + i2c@7e805000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + vec@7e806000 { + compatible ; + reg ; + clocks ; + interrupts ; + status ; + power-domains ; + phandle ; + } + pixelvalve@7e807000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + hdmi@7e902000 { + compatible ; + reg ; + reg-names ; + interrupts ; + ddc ; + clocks ; + clock-names ; + dmas ; + dma-names ; + status ; + power-domains ; + hpd-gpios ; + phandle ; + } + v3d@7ec00000 { + compatible ; + reg ; + interrupts ; + power-domains ; + status ; + phandle ; + } + gpu { + compatible ; + status ; + raspberrypi,firmware ; + phandle ; + } + local_intc@40000000 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + phandle ; + } + mmcnr@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + dmas ; + dma-names ; + brcm,overclock-50 ; + non-removable ; + status ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + #address-cells ; + #size-cells ; + phandle ; + wifi@1 { + reg ; + compatible ; + phandle ; + } + } + firmwarekms@7e600000 { + compatible ; + reg ; + interrupts ; + brcm,firmware ; + status ; + phandle ; + } + smi@7e600000 { + compatible ; + reg ; + interrupts ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + dmas ; + dma-names ; + status ; + phandle ; + } + csi@7e800000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + phandle ; + } + csi@7e801000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + brcm,num-data-lanes ; + phandle ; + } + axiperf { + compatible ; + reg ; + firmware ; + status ; + phandle ; + } + firmware { + compatible ; + #address-cells ; + #size-cells ; + mboxes ; + dma-ranges ; + phandle ; + clocks { + compatible ; + #clock-cells ; + phandle ; + } + vcio { + compatible ; + phandle ; + } + expgpio { + compatible ; + gpio-controller ; + #gpio-cells ; + gpio-line-names ; + status ; + phandle ; + } + } + power { + compatible ; + firmware ; + #power-domain-cells ; + phandle ; + } + mailbox@7e00b840 { + compatible ; + reg ; + interrupts ; + phandle ; + bcm2835_audio { + compatible ; + brcm,firmware ; + brcm,pwm-channels ; + status ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + } + gpiomem { + compatible ; + reg ; + } + fb { + compatible ; + firmware ; + status ; + phandle ; + } + sound { + status ; + phandle ; + } + } + clocks { + clk-osc { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + clk-usb { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + } + phy { + compatible ; + #phy-cells ; + phandle ; + } + arm-pmu { + compatible ; + interrupt-parent ; + interrupts ; + } + timer { + compatible ; + interrupt-parent ; + interrupts ; + always-on ; + } + cpus { + #address-cells ; + #size-cells ; + enable-method ; + phandle ; + cpu@0 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@1 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@2 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@3 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + l2-cache0 { + compatible ; + cache-size ; + cache-line-size ; + cache-sets ; + cache-level ; + phandle ; + } + } + cam1_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + gpio ; + phandle ; + } + cam1_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam0_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + phandle ; + } + cam0_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam_dummy_reg { + compatible ; + regulator-name ; + status ; + phandle ; + } + __overrides__ { + cam0-pwdn-ctrl ; + cam0-pwdn ; + cam0-led-ctrl ; + cam0-led ; + arm_freq ; + cache_line_size ; + uart0 ; + uart1 ; + i2s ; + spi ; + i2c0 ; + i2c1 ; + i2c0_baudrate ; + i2c1_baudrate ; + audio ; + watchdog ; + random ; + sd_overclock ; + sd_force_pio ; + sd_pio_limit ; + sd_debug ; + sdio_overclock ; + axiperf ; + i2c2_iknowwhatimdoing ; + i2c2_baudrate ; + sd_poll_once ; + krnbt ; + krnbt_baudrate ; + act_led_gpio ; + act_led_activelow ; + act_led_trigger ; + pwr_led_gpio ; + pwr_led_activelow ; + pwr_led_trigger ; + eee ; + tx_lpi_timer ; + eth_led0 ; + eth_led1 ; + eth_downshift_after ; + eth_max_speed ; + } + leds { + compatible ; + phandle ; + led-act { + label ; + default-state ; + linux,default-trigger ; + gpios ; + phandle ; + } + led-pwr { + label ; + linux,default-trigger ; + gpios ; + phandle ; + } + } + fixedregulator_3v3 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + fixedregulator_5v0 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + __symbols__ { + rmem ; + cma ; + cpu_thermal ; + soc ; + txp ; + clocks ; + mailbox ; + gpio ; + dpi_gpio0 ; + emmc_gpio22 ; + emmc_gpio34 ; + emmc_gpio48 ; + gpclk0_gpio4 ; + gpclk1_gpio5 ; + gpclk1_gpio42 ; + gpclk1_gpio44 ; + gpclk2_gpio6 ; + gpclk2_gpio43 ; + i2c0_gpio0 ; + i2c0_gpio28 ; + i2c0_gpio44 ; + i2c1_gpio2 ; + i2c1_gpio44 ; + jtag_gpio22 ; + pcm_gpio18 ; + pcm_gpio28 ; + sdhost_gpio48 ; + spi0_gpio7 ; + spi0_gpio35 ; + spi1_gpio16 ; + spi2_gpio40 ; + uart0_gpio14 ; + uart0_ctsrts_gpio16 ; + uart0_ctsrts_gpio30 ; + uart0_gpio32 ; + uart0_gpio36 ; + uart0_ctsrts_gpio38 ; + uart1_gpio14 ; + uart1_ctsrts_gpio16 ; + uart1_gpio32 ; + uart1_ctsrts_gpio30 ; + uart1_gpio40 ; + uart1_ctsrts_gpio42 ; + i2c_slave_gpio18 ; + jtag_gpio4 ; + pwm0_gpio12 ; + pwm0_gpio18 ; + pwm0_gpio40 ; + pwm1_gpio13 ; + pwm1_gpio19 ; + pwm1_gpio41 ; + pwm1_gpio45 ; + dpi_18bit_cpadhi_gpio0 ; + dpi_18bit_cpadhi_gpio2 ; + dpi_18bit_gpio0 ; + dpi_18bit_gpio2 ; + dpi_16bit_gpio0 ; + dpi_16bit_gpio2 ; + dpi_16bit_cpadhi_gpio0 ; + dpi_16bit_cpadhi_gpio2 ; + gpioout ; + alt0 ; + spi0_pins ; + spi0_cs_pins ; + i2c0_pins ; + i2c1_pins ; + i2s_pins ; + sdio_pins ; + bt_pins ; + uart0_pins ; + uart1_pins ; + audio_pins ; + uart0 ; + bt ; + sdhost ; + i2s ; + spi0 ; + spi ; + spidev0 ; + spidev1 ; + i2c0if ; + i2c0mux ; + i2c0 ; + i2c_csi_dsi ; + dpi ; + dsi0 ; + aux ; + uart1 ; + minibt ; + spi1 ; + spi2 ; + pwm ; + mmc ; + sdhci ; + hvs ; + dsi1 ; + i2c1 ; + usb ; + ethernet ; + eth_phy ; + dma ; + intc ; + watchdog ; + pm ; + random ; + pixelvalve0 ; + pixelvalve1 ; + thermal ; + i2c2 ; + vec ; + pixelvalve2 ; + hdmi ; + v3d ; + vc4 ; + local_intc ; + mmcnr ; + brcmf ; + firmwarekms ; + smi ; + csi0 ; + csi1 ; + axiperf ; + firmware ; + firmware_clocks ; + vcio ; + expgpio ; + power ; + vchiq ; + audio ; + fb ; + sound ; + clk_osc ; + clk_usb ; + usbphy ; + cpus ; + cpu0 ; + cpu1 ; + cpu2 ; + cpu3 ; + l2 ; + cam1_reg ; + cam1_clk ; + cam0_regulator ; + cam0_clk ; + cam0_reg ; + cam_dummy_reg ; + leds ; + act_led ; + pwr_led ; + vdd_3v3_reg ; + vdd_5v0_reg ; + } +} +[simple_malloc.c/init_malloc_state:12] Simple heap start address: 0x8e000 + +[initrdfs.c/initrdfs_init:7] Enter initrdfs_int +[initrdfs.c/initrdfs_init:8] initrd start at 0x8000000 + +[initrdfs.c/initrdfs_init:9] initrd first 4 bytes: 37303730 + +[initrdfs.c/initrdfs_init:23] Start parsing new ascii format's cpio +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 2 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 112, iter->cur: 0x8000070 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: . +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 21 +[cpio.c/cpio_iter_parse:38] f->namesize: 6 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 140, iter->cur: 0x80000fc +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file1 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 34 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 156, iter->cur: 0x8000198 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file2.txt +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 5 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 116, iter->cur: 0x800020c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 5 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 128, iter->cur: 0x800028c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test/1234 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 0 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 11 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 124, iter->cur: 0x8000308 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: TRAILER!!! +[initrdfs.c/initrdfs_init:32] Leave initrdfs_int +text_start=0x80000, text_end=0x84000, text_size=16384 +rodata_start=0x84000, rodata_end=0x86000, rodata_size=8192 +data_start=0x86000, data_end=0x87000, data_size=4096 +bss_start=0x87000, bss_end=0x8e000, bss_size=28672 +heap_start=0x8e000 +⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀ +⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀ +⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁ +⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀ +⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀ +⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀ +⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀ +⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀ +⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀ +⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀ +⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀ +⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀ +⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀ + +# diff --git a/lab6/tools/AUX_PERIPHERALS b/lab6/tools/AUX_PERIPHERALS new file mode 100644 index 000000000..324eb3019 --- /dev/null +++ b/lab6/tools/AUX_PERIPHERALS @@ -0,0 +1,23 @@ +0x7E215000 AUX_IRQ Auxiliary Interrupt status 3 +0x7E215004 AUX_ENABLES Auxiliary enables 3 +0x7E215040 AUX_MU_IO_REG Mini Uart I/O Data 8 +0x7E215044 AUX_MU_IER_REG Mini Uart Interrupt Enable 8 +0x7E215048 AUX_MU_IIR_REG Mini Uart Interrupt Identify 8 +0x7E21504C AUX_MU_LCR_REG Mini Uart Line Control 8 +0x7E215050 AUX_MU_MCR_REG Mini Uart Modem Control 8 +0x7E215054 AUX_MU_LSR_REG Mini Uart Line Status 8 +0x7E215058 AUX_MU_MSR_REG Mini Uart Modem Status 8 +0x7E21505C AUX_MU_SCRATCH Mini Uart Scratch 8 +0x7E215060 AUX_MU_CNTL_REG Mini Uart Extra Control 8 +0x7E215064 AUX_MU_STAT_REG Mini Uart Extra Status 32 +0x7E215068 AUX_MU_BAUD_REG Mini Uart Baudrate 16 +0x7E215080 AUX_SPI0_CNTL0_REG SPI 1 Control register 0 32 +0x7E215084 AUX_SPI0_CNTL1_REG SPI 1 Control register 1 8 +0x7E215088 AUX_SPI0_STAT_REG SPI 1 Status 32 +0x7E215090 AUX_SPI0_IO_REG SPI 1 Data 32 +0x7E215094 AUX_SPI0_PEEK_REG SPI 1 Peek 16 +0x7E2150C0 AUX_SPI1_CNTL0_REG SPI 2 Control register 0 32 +0x7E2150C4 AUX_SPI1_CNTL1_REG SPI 2 Control register 1 8 +0x7E2150C8 AUX_SPI1_STAT_REG SPI 2 Status 32 +0x7E2150D0 AUX_SPI1_IO_REG SPI 2 Data 32 +0x7E2150D4 AUX_SPI1_PEEK_REG SPI 2 Peek 16 diff --git a/lab6/tools/GPIO b/lab6/tools/GPIO new file mode 100644 index 000000000..ad2b10794 --- /dev/null +++ b/lab6/tools/GPIO @@ -0,0 +1,43 @@ +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200004 GPFSEL1 GPIO Function Select 1 32 R/W +0x7E200008 GPFSEL2 GPIO Function Select 2 32 R/W +0x7E20000C GPFSEL3 GPIO Function Select 3 32 R/W +0x7E200010 GPFSEL4 GPIO Function Select 4 32 R/W +0x7E200014 GPFSEL5 GPIO Function Select 5 32 R/W +0x7E200018 - Reserved - - +0x7E20001C GPSET0 GPIO Pin Output Set 0 32 W +0x7E200020 GPSET1 GPIO Pin Output Set 1 32 W +0x7E200024 - Reserved - - +0x7E200028 GPCLR0 GPIO Pin Output Clear 0 32 W +0x7E20002C GPCLR1 GPIO Pin Output Clear 1 32 W +0x7E200030 - Reserved - - +0x7E200034 GPLEV0 GPIO Pin Level 0 32 R +0x7E200038 GPLEV1 GPIO Pin Level 1 32 R +0x7E20003C - Reserved - - +0x7E200040 GPEDS0 GPIO Pin Event Detect Status 0 32 R/W +0x7E200044 GPEDS1 GPIO Pin Event Detect Status 1 32 R/W +0x7E200048 - Reserved - - +0x7E20004C GPREN0 GPIO Pin Rising Edge Detect Enable 0 32 R/W +0x7E200050 GPREN1 GPIO Pin Rising Edge Detect Enable 1 32 R/W +0x7E200054 - Reserved - - +0x7E200058 GPFEN0 GPIO Pin Falling Edge Detect Enable 0 32 R/W +0x7E20005C GPFEN1 GPIO Pin Falling Edge Detect Enable 1 32 R/W +0x7E200060 - Reserved - - +0x7E200064 GPHEN0 GPIO Pin High Detect Enable 0 32 R/W +0x7E200068 GPHEN1 GPIO Pin High Detect Enable 1 32 R/W +0x7E20006C - Reserved - - +0x7E200070 GPLEN0 GPIO Pin Low Detect Enable 0 32 R/W +0x7E200074 GPLEN1 GPIO Pin Low Detect Enable 1 32 R/W +0x7E200078 - Reserved - - +0x7E20007C GPAREN0 GPIO Pin Async. Rising Edge Detect 0 32 R/W +0x7E200080 GPAREN1 GPIO Pin Async. Rising Edge Detect 1 32 R/W +0x7E200084 - Reserved - - +0x7E200088 GPAFEN0 GPIO Pin Async. Falling Edge Detect 0 32 R/W +0x7E20008C GPAFEN1 GPIO Pin Async. Falling Edge Detect 1 32 R/W +0x7E200090 - Reserved - - +0x7E200094 GPPUD GPIO Pin Pull-up/down Enable 32 R/W +0x7E200098 GPPUDCLK0 GPIO Pin Pull-up/down Enable Clock 0 32 R/W +0x7E20009C GPPUDCLK1 GPIO Pin Pull-up/down Enable Clock 1 32 R/W +0x7E2000A0 - Reserved - - +0x7E2000B0 - Test 4 R/W diff --git a/lab6/tools/cpio/.gdb_history b/lab6/tools/cpio/.gdb_history new file mode 100644 index 000000000..123309d64 --- /dev/null +++ b/lab6/tools/cpio/.gdb_history @@ -0,0 +1,58 @@ +quit +target remote:1234 +file ../../build/kernel8.elf +c +ni +c +ni +quit +file ../../build/kernel8.elf +x/gx 9a8 +x/gx 0x9a8 +target remote:1234 +c +x/i 9a8 +x/i 0x9a8 +x/i 0x9a4 +x/i 0x9a8 +b 0x9a8 +b *0x9a8 +file ../../build/kernel8.elf +b *0x9a8 +target remote:1234 +c +ni +ni +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +b *0x9a4 +x/i 0x9a4 +target remote:1234 +target remote:1234 +info b +del 1 +del 2 +c +c +b *0x9a4 +b *0x9a8 +c +quit diff --git a/lab6/tools/cpio/Makefile b/lab6/tools/cpio/Makefile new file mode 100644 index 000000000..1cbe92c74 --- /dev/null +++ b/lab6/tools/cpio/Makefile @@ -0,0 +1,35 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +override CFLAGS += \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin \ + +LDFLAGS ?= \ + -nostdlib \ + +CXXFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJDUMP = aarch64-linux-gnu-objdump +QEMU = qemu-system-aarch64 +RASPI_VER = raspi3b + + +LINKER_FILE = ./linker.ld +HEADERS = $(PWD)/include/ +OUTPUT = $(PWD)/build +KNAME = kernel8 +BNAME = bootloader + +.PHONY: all + + +all: + $(CC) -c -o test.o test.S $(CFLAGS) + $(LD) -T linker.ld -o test.elf test.o $(LDFLAGS) + $(OBJCOPY) -O binary test.elf test.img + diff --git a/lab6/tools/cpio/create_initramfs.sh b/lab6/tools/cpio/create_initramfs.sh new file mode 100755 index 000000000..2736e47fe --- /dev/null +++ b/lab6/tools/cpio/create_initramfs.sh @@ -0,0 +1,4 @@ +#! /bin/sh +cd rootfs +find . | cpio -o -H newc > ../initramfs.cpio +cd .. diff --git a/lab6/tools/cpio/initramfs.cpio b/lab6/tools/cpio/initramfs.cpio new file mode 100644 index 000000000..b3bf061ff Binary files /dev/null and b/lab6/tools/cpio/initramfs.cpio differ diff --git a/lab6/tools/cpio/linker.ld b/lab6/tools/cpio/linker.ld new file mode 100644 index 000000000..a550bf32e --- /dev/null +++ b/lab6/tools/cpio/linker.ld @@ -0,0 +1,41 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + +} diff --git a/lab6/tools/cpio/rootfs/file1 b/lab6/tools/cpio/rootfs/file1 new file mode 100644 index 000000000..b7b514317 --- /dev/null +++ b/lab6/tools/cpio/rootfs/file1 @@ -0,0 +1 @@ +This is your flag!!! diff --git a/lab6/tools/cpio/rootfs/file2.txt b/lab6/tools/cpio/rootfs/file2.txt new file mode 100644 index 000000000..367edaf2d --- /dev/null +++ b/lab6/tools/cpio/rootfs/file2.txt @@ -0,0 +1 @@ +FLAG{...........................} diff --git a/lab6/tools/cpio/rootfs/syscall.img b/lab6/tools/cpio/rootfs/syscall.img new file mode 100644 index 000000000..f7baf4607 Binary files /dev/null and b/lab6/tools/cpio/rootfs/syscall.img differ diff --git a/lab6/tools/cpio/rootfs/test/1234 b/lab6/tools/cpio/rootfs/test/1234 new file mode 100644 index 000000000..81c545efe --- /dev/null +++ b/lab6/tools/cpio/rootfs/test/1234 @@ -0,0 +1 @@ +1234 diff --git a/lab6/tools/gen.sh b/lab6/tools/gen.sh new file mode 100755 index 000000000..235b38c28 --- /dev/null +++ b/lab6/tools/gen.sh @@ -0,0 +1,24 @@ +#! /bin/sh +BUS_IO_BASE=0x7E000000 +PHY_IO_BASE=0x3F000000 +echo "/* Register's offset of GPIO */" +grep -v " - " GPIO | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + +echo "" +echo "" +echo "/* Register's offset of UART and SPI */" +grep -v " - " AUX_PERIPHERALS | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + + diff --git a/lab6/uart_upload.py b/lab6/uart_upload.py new file mode 100755 index 000000000..9a2a52d80 --- /dev/null +++ b/lab6/uart_upload.py @@ -0,0 +1,69 @@ +#! /usr/bin/python3 + +import sys +import struct +import serial +import os +import time +if len(sys.argv) < 4: + print(sys.argv[0], "", "", "") + sys.exit(-1) + +tty_name = sys.argv[1] +kernel_name = sys.argv[2] +base_addr = int(sys.argv[3], 16) + +ser = None + +def readline(): + os.write(1,b'[From bootloader]: ') + while 1: + c = ser.read(1) + if c == b'\n': + os.write(1, b'\n') + return + elif c != b'\r': + os.write(1, c) + + + +with open(kernel_name, "rb",) as kernel: + kernel_buf = kernel.read() + kernel_size = len(kernel_buf) + + + while(1): + ser = serial.Serial( + # Serial Port to read the data from + port = tty_name, + #Rate at which the information is shared to the communication channel + baudrate = 115200, + timeout = .1 + ) + + # start upload kernel to rasberry pi 3b+ by uart interface + # start header + ser.write(b"A") + ser.flush() + readline() + + # transfer kernel base address and kernel size ( both are 8 bytes ) in little endian + ser.write(struct.pack("member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) (((uint64_t)(val) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_DOWN(val, align) ((uint64_t)(val) & ~((align) - 1)) + +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define min(x, y) ((x) < (y) ? (x) : (y)) + +#endif diff --git a/lab6/user/user_lib.c b/lab6/user/user_lib.c new file mode 100644 index 000000000..d7d14da24 --- /dev/null +++ b/lab6/user/user_lib.c @@ -0,0 +1,323 @@ +#include "user_lib.h" + +char int_table[] = "0123456789"; +char hex_table[] = "0123456789abcdef"; + +uint64_t getpid(void){ + asm volatile("mov x8, 0\n\t" + "svc 0\n\t" + : + : + ); +} + +size_t uart_read(char *buf, size_t size){ + asm volatile("mov x0, %[buf]\n\t" + "mov x1, %[size]\n\t" + "mov x8, 1\n\t" + "svc 0\n\t" + : + :[buf] "r" (buf), [size] "r" (size) + ); +} + +size_t uart_write(char *buf, size_t size){ + asm volatile("mov x0, %[buf]\n\t" + "mov x1, %[size]\n\t" + "mov x8, 2\n\t" + "svc 0\n\t" + : + :[buf] "r" (buf), [size] "r" (size) + ); +} + +uint64_t fork(void){ + asm volatile("mov x8, 4\n\t" + "svc 0\n\t" + : + : + ); +} + +void debug_info(void){ + asm volatile("mov x8, 5\n\t" + "svc 0\n\t" + : + : + ); +} + +void signal(uint64_t pid, sig_handler handler){ + asm volatile("mov x0, %[pid]\n\t" + "mov x1, %[handler]\n\t" + "mov x8, 8\n\t" + "svc 0\n\t" + : + :[pid] "r" (pid), [handler] "r" (handler) + ); +} + +void kill(uint64_t pid, int signal){ + asm volatile("mov x0, %[pid]\n\t" + "mov x1, %[signal]\n\t" + "mov x8, 9\n\t" + "svc 0\n\t" + : + :[pid] "r" (pid), [signal] "r" (signal) + ); +} + +void delay(uint64_t clock){ + for(uint64_t i = 0 ; i < clock ; i++) asm volatile("nop"); +} + +size_t strlen(const char* s){ + size_t i = 0; + while(s[i++]); + i--; + return i; +} + + +char * itoa(int32_t value, char* str, uint32_t base){ + char buf[32]; + uint32_t val; + volatile int i = 0, j = 0; + + switch(base){ + case 16: + val = (uint32_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} + +char * utoa(uint32_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint32_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} +char * ltoa(int64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val; + + switch(base){ + case 16: + val = (uint64_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +char * ultoa(uint64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} + +uint64_t atoul(const char* str){ + uint64_t val = 0; + const char* ps = str; + while(*ps){ + val *= 10; + val += (*ps - '0'); + ps++; + } + return val; +} + +int32_t printf(char *fmt, ...){ + uint32_t uval; + int32_t val; + int64_t lval; + char str[64], ch; + char* s; + void* addr; + size_t tmp_c; + volatile int32_t count = 0; + va_list ap; + + va_start(ap, fmt); + + while(*fmt){ + char c = *fmt++; + if(c == '%'){ + c = *fmt++; + switch(c){ + case 'u': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 10); + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + break; + case 'd': + val = va_arg(ap, int); + itoa(val, str, 10); + uart_write(str, strlen(str)); + break; + case 'l': + lval = va_arg(ap, int64_t); + ltoa(lval, str, 10); + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + break; + case 'c': + ch = va_arg(ap, int); + uart_write(&ch, 1); + count++; + break; + case 'p': + addr = va_arg(ap, void*); + utoa((uint64_t)addr, str, 16); + + uart_write("0x", 2); + count += 2; + + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + + break; + + break; + case 'x': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 16); + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + + break; + case 's': + s = va_arg(ap, char*); + tmp_c = strlen(s); + uart_write(s, tmp_c); + count += tmp_c; + break; + case '%': + uart_write("%", 1); + count++; + default: + uart_write("%", 1); + uart_write(&c, 1); + count += 2; + } + }else{ + uart_write(&c, 1); + count++; + } + } + va_end(ap); + return count; +} + diff --git a/lab6/user/user_lib.h b/lab6/user/user_lib.h new file mode 100644 index 000000000..782e21ae8 --- /dev/null +++ b/lab6/user/user_lib.h @@ -0,0 +1,18 @@ +#ifndef _USER_LIB_H_ +#define _USER_LIB_H_ +#include "types.h" +#include + +typedef void (*sig_handler)(); + +extern size_t uart_write(char *, size_t); +extern size_t uart_read(char *, size_t); +extern uint64_t fork(void); +extern uint64_t getpid(void); +extern void debug_info(void); +extern void delay(uint64_t); +extern int32_t printf(char *, ...); +extern void signal(uint64_t, sig_handler); +extern void kill(uint64_t, int); + +#endif diff --git a/lab6/user/user_lib.o b/lab6/user/user_lib.o new file mode 100644 index 000000000..79fb27b61 Binary files /dev/null and b/lab6/user/user_lib.o differ diff --git a/lab7/.gdb_history b/lab7/.gdb_history new file mode 100644 index 000000000..0cba255db --- /dev/null +++ b/lab7/.gdb_history @@ -0,0 +1,256 @@ +x/gx bb000 +x/gx 0xbb000 +quit +file ./build/kernel8.elf +target remote:1234 +c +x/gx 0xffff000008215000 +x/gx 0x821c000 +x/gx 0x821d000 +x/gx 0x8216000 +file ./build/kernel8.elf +file ./build/kernel8.elf +b* MBox_process +c +target remot:1234 +c +ni +si +ni +ni +b* MBox_write +c +ni +ni +ni +ni +x/i 0xffff00000008238c +b* 0xffff000000082440 +c +ls +c +c +target remot:1234 +info b +del 1 +del 2 +c +ni +quit +target remote;1234 +target remote:1234 +file ./build/kernel8.elf +c +b task_load_all +c +c +ni +target remote:1234 +target remote:1234 +c +info reg +p $TTBR0_EL1 +p/x $TTBR0_EL1 +ni +ni +ni +ni +c +ni +p $TTBR0_EL1 +p/x $TTBR0_EL1 +p 0xffff00000006b000 +x/gx 0xffff00000006b000 +x/gx 0xffff00003be82000 +x/gx 0xffff00003be83000 +x/gx 0xffff00003be84000 +x/gx 0xffff00003be84000 +quit +file ./build/kernel8.elf +b task_load_all +c +target remot:1234 +c +p/x $TTBR0_EL! +p/x $TTBR0_EL1 +x/gx 0x8215000 +x/gx 0xffff00008215000 +x/gx 0xffff000008215000 +x/gx 0xffff000000001000 +x/gx 0xffff000008218000 +x/gx 0xffff000008219000 +x/gx 0xffff00000803d000 +x/i 0xffff00000803d000 +c +x/gx 0xffff00000006b000 +x/gx 0xffff00003be82003 +x/gx 0xffff00003be82000 +x/gx 0xffff00003be83000 +x/gx 0xffff00003be84000 +c +b dup_vma_stack +c +x/gx 0xffff00003be8e000 +x/gx 0xffff00003be8e000 +x/gx 0xffff00003bdc3000 +x/gx 0xffff00003bdc4000 +x/gx 0xffff00003bdc5000 +quit +file ./build/kernel8.elf +target remote;1234 +target remote:1234 +c +b dup_vma_stack +c +x/gx 0xffff000000 +x/gx 0xffff00003be82000 +b dup_mm_struct +c +target remot:1234 +c +ni +x/i +ni +b * dup_pages +c +ni +ni +bu +ni +x/gx 0xffff00000006b000, +x/gx 0xffff00000006b000 +ni +ni +x/gx 0xffff00000006b000 +watch 0xffff00000006b000 +watch *0xffff00000006b000 +c +watch *0xffff00000006b000 +x/gx 0xffff00000006b000 +x/gx 0xffff00000006b000 +x/gx 0xffff00000006b000 +n +i +ni +ni +ni +ni +file ./build/kernel8.elf +file ./build/kernel8.elf +target remote:1234 +info b +del 1 + del 2 +del 3 +del 4 +del 5 +b task_load_all +c +c +file ./build/kernel8.elf +file ./build/kernel8.elf +target remote:1234 +c +info b +del 6 +b task_load_all +c +c +x/gx 0xffff000008215000 +x/gx 0xffff000000001000 +x/gx 0xffff000000e2a000 +x/gx 0xffff000000e2b000 +x/gx 0xffff00000803d000 +x/i 0xffff00000803d000 +p/x $TTBR0_EL1 +x/gx 0xffff00000006b000 +x/gx 0xffff00000006e000 +x/gx 0xffff00000006f000 +x/gx 0xffff000000100000 +x/gx 0xffff000000010000 +ni +ni +ni +ni +quit +quit +file ./build/kernel8.elf +b Mbox_call +c +target remote:1234 +c +x/gx 0x17de0 +ni +x/gx 0xffff000000017000 +x/gx 0xffff000000017de0 +ni +c +c +quit +file ./build/kernel8.elf +target remote:1234 +c +b sys_mbox_call +c +x/gx 0xffffffffede0 +x/dx 0xffffffffede0 +x/wx 0xffffffffede0 +x/gx 0xffffffffede0 +x/dx 0xffffffffede0 +x/wx 0xffffffffede0 +x/wx 0xffffffffede0 +ni +ni +x/i +x/i 0xffff000000081a1c +x/i 0xffff000000082b5c +b* 0xffff000000082e8c +c +x/wx 0xffffffffede0 +quit +file ./build/kernel8.elf +target remote:1234 +c +c +ni +c +ni +c +ni +quit +target remote:1234 +ls +file ./build/kernel8.elf +target remote:1234 +target remote:1234 +c +b task_exec +target remote:1q234 +target remote:1234 +c +x/i 0xffff00000008a1dc +b* 0xffff00000008a3a4 +c +ni +ni +ni +c +c +c +c +c +file build/kernel8.elf +file build/kernel8.elf +target remote:1234 +c +c +c +c +x/gx 0x65000 +x/gx 0x65000 +x/gx 0xffff000000065000 +x/i 0xffff000000065000 +x/gx 0xffff000000065000 +x/bx 0xffff000000065000 +x/i 0xffff00000006596c +quit diff --git a/lab7/Makefile b/lab7/Makefile new file mode 100644 index 000000000..048650a48 --- /dev/null +++ b/lab7/Makefile @@ -0,0 +1,109 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +override CFLAGS += \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin \ + +LDFLAGS ?= \ + -nostdlib \ + +CXXFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJDUMP = aarch64-linux-gnu-objdump +QEMU = qemu-system-aarch64 +RASPI_VER = raspi3b + + +LINKER_FILE = ./linker.ld +HEADERS = $(PWD)/include/ +OUTPUT = $(PWD)/build +KNAME = kernel8 +BNAME = bootloader + +LIBS = \ + $(OUTPUT)/print.o \ + $(OUTPUT)/string.o \ + $(OUTPUT)/list.o \ + $(OUTPUT)/cpio.o \ + $(OUTPUT)/simple_malloc.o \ + $(OUTPUT)/fdt_parse.o \ + $(OUTPUT)/ring_buffer.o \ + $(OUTPUT)/asm.o \ + $(OUTPUT)/bitops.o + +KOBJECTS = \ + $(OUTPUT)/start.o \ + $(OUTPUT)/entry.o \ + $(OUTPUT)/syscall_test.o \ + $(OUTPUT)/syscall_table.o \ + $(OUTPUT)/mini_uart.o \ + $(OUTPUT)/mailbox.o \ + $(OUTPUT)/main.o \ + $(OUTPUT)/kernel_init.o \ + $(OUTPUT)/reboot.o \ + $(OUTPUT)/shell.o \ + $(OUTPUT)/debug.o \ + $(OUTPUT)/initrdfs.o \ + $(OUTPUT)/timer.o \ + $(OUTPUT)/irq_handler.o \ + $(OUTPUT)/page_alloc.o \ + $(OUTPUT)/mm.o \ + $(OUTPUT)/mmu.o \ + $(OUTPUT)/slab.o \ + $(OUTPUT)/sched.o \ + $(OUTPUT)/kthread.o \ + $(OUTPUT)/task.o \ + $(OUTPUT)/signal.o \ + $(OUTPUT)/fault.o \ + $(OUTPUT)/vfs.o \ + $(OUTPUT)/tmpfs.o \ + $(OUTPUT)/fs.o \ + $(OUTPUT)/uartfs.o \ + $(OUTPUT)/framebuffer.o \ + $(LIBS) + + +.PHONY: all start kernel end clean dump + + +all: start link kernel end + +start: + @echo "Start building kernel8.img" + + $(MAKE) -C peripherals OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C init OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C kernel OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C lib OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C debug OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C fs OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + $(MAKE) -C mm OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + +link: $(OBJECTS) + $(LD) -T kernel/$(LINKER_FILE) -o $(OUTPUT)/$(KNAME).elf $(KOBJECTS) $(LDFLAGS) + +kernel: $(OUTPUT)/$(KNAME).elf + $(OBJCOPY) -O binary $(OUTPUT)/$(KNAME).elf $(OUTPUT)/$(KNAME).img + +end: + @echo "Finish building kernel8.img" + +dump: + $(OBJDUMP) -m aarch64 -b binary -D $(OUTPUT)/$(KNAME).img + +qemu-run: + sudo $(QEMU) -M $(RASPI_VER) -kernel $(OUTPUT)/$(KNAME).img -display none -serial null -serial stdio -initrd ./initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + +qemu-run-gui: + sudo $(QEMU) -M $(RASPI_VER) -kernel $(OUTPUT)/$(KNAME).img -serial null -serial stdio -initrd ./initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + +qemu-run-instr: + sudo $(QEMU) -M $(RASPI_VER) -kernel $(OUTPUT)/$(KNAME).img -display none -d in_asm + +clean: + rm $(OUTPUT)/* diff --git a/lab7/README.md b/lab7/README.md new file mode 100644 index 000000000..788565858 --- /dev/null +++ b/lab7/README.md @@ -0,0 +1,18 @@ +# Requirements + +## Features + +- Basic Exercise 1 + - [x] Virtual Memory in Kernel Space +- Basic Exercise 2 + - [x] Virtual Memory in User Space +- Advanced Exercise 1 + - [x] Mmap +- Advanced Exercise 2 + - [x] Page Fault Handler & Demand Paging +- Advanced Exercise 1 + - [x] Copy on Write + + + + diff --git a/lab7/bcm2710-rpi-3-b-plus.dtb b/lab7/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 000000000..6f9ef31cc Binary files /dev/null and b/lab7/bcm2710-rpi-3-b-plus.dtb differ diff --git a/lab7/boot/Makefile b/lab7/boot/Makefile new file mode 100644 index 000000000..b98c365cd --- /dev/null +++ b/lab7/boot/Makefile @@ -0,0 +1,28 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + boot.o \ + uart_boot.o + +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab7/boot/boot.S b/lab7/boot/boot.S new file mode 100644 index 000000000..b28524a42 --- /dev/null +++ b/lab7/boot/boot.S @@ -0,0 +1,84 @@ +.section ".text.boot" +.global _start +_start: +// x1 = current PC + offset to _dtb + adr x1, _dtb + str x0, [x1] + +// stack + adr x1, _start + mov sp, x1 + +// rebase boot loader to specific address +// indicated by linker script + bl rebase_bootloader + +// slave cpu should not sleep before bootloader finishes rebase +// Since if they wake up, there next instruction will be invalid instruction +rebase_entry: + // read cpu id, stop slave cores + // cpu id == 0 + // store pointer to dtb to _dtb + mrs x1, mpidr_el1 + and x1, x1, #0xff + + // cpu id > 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + + +master_core: +// stack + ldr x1, =_start + mov sp, x1 + +// recover dtb to x0 + adr x1, _dtb + ldr x0, [x1] + + +// jump to kernel_main + bl uart_recv_kernel + + b proc_hang + +// rebase our boot loader +rebase_bootloader: + // manipulate our return address ( x30 a.k.a LR ) to the rebased bootloader + // x19 = current PC + offset to _start + // x20 = absolute address ( _start ) that specify by linker script + adr x19, _start + ldr x20, =_start + sub x19, x19, x20 + sub lr , lr, x19 + + // x21 = absolute address ( __bootloader_start ) that specify by linker script + // x22 = current PC + offset to __bootloader_start ( In linker script ) + ldr x21, =__bootloader_start + adr x22, __bootloader_start + ldr x23, =__bootloader_size + // start rebasing bootloader +copy_bootloader: + cbz x23, end_rebase_bootloader + ldr x24, [x22], #8 + str x24, [x21], #8 + sub x23, x23, #8 + b copy_bootloader + +// Since ldr and str memory operation should obey 8 bytes alignment rule, the code here would failed on real device +// cbz x23, end_rebase_bootloader +// ldr x24, [x22], #1 +// str x24, [x21], #1 +// sub x23, x23, #1 +// b copy_bootloader + + + // return to rebased bootloader +end_rebase_bootloader: + ret + +.section ".data" +_dtb: .dword 0 diff --git a/lab7/boot/linker.ld b/lab7/boot/linker.ld new file mode 100644 index 000000000..740945ab2 --- /dev/null +++ b/lab7/boot/linker.ld @@ -0,0 +1,43 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x60000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __bootloader_start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + __bootloader_end = .; + __bootloader_size = (__bootloader_end - __bootloader_start); +} diff --git a/lab7/boot/uart_boot.c b/lab7/boot/uart_boot.c new file mode 100644 index 000000000..faec51411 --- /dev/null +++ b/lab7/boot/uart_boot.c @@ -0,0 +1,47 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "lib/print.h" + +void recv_boot_header(){ + while('A' != mini_uart_read()); +} + +size_t recv_kernel_base(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +size_t recv_kernel_size(){ + uint8_t size[8]; + for(uint64_t i = 0 ; i < 8 ; i++) size[i] = mini_uart_read(); + return *(size_t*)size; +} + +void recv_kernel(uint64_t base, size_t size){ + uint8_t *pb; + size_t i; + for(pb = (uint8_t*)base , i = 0 ; i < size ; i++){ + pb[i] = mini_uart_read(); + } +} +uint64_t uart_recv_kernel(uint64_t dtb){ + size_t size; + uint64_t base; + mini_uart_init(); + + recv_boot_header(); +// printf("Receive A...\r\n"); + + base = recv_kernel_base(); +// printf("Receive kernel base 0x%x...\r\n", base); + + size = recv_kernel_size(); +// printf("Receive kernel size 0x%x...\r\n", size); + + recv_kernel(base, size); +// printf("Jump to kernel iamge...\r\n"); + + delay_cycles(10000); + ((void (*)(uint64_t))base)(dtb); +} diff --git a/lab7/build/asm.o b/lab7/build/asm.o new file mode 100644 index 000000000..a854464e8 Binary files /dev/null and b/lab7/build/asm.o differ diff --git a/lab7/build/bitops.o b/lab7/build/bitops.o new file mode 100644 index 000000000..f6889106e Binary files /dev/null and b/lab7/build/bitops.o differ diff --git a/lab7/build/cpio.o b/lab7/build/cpio.o new file mode 100644 index 000000000..319a39468 Binary files /dev/null and b/lab7/build/cpio.o differ diff --git a/lab7/build/debug.o b/lab7/build/debug.o new file mode 100644 index 000000000..7beb42607 Binary files /dev/null and b/lab7/build/debug.o differ diff --git a/lab7/build/entry.o b/lab7/build/entry.o new file mode 100644 index 000000000..3f6006ac2 Binary files /dev/null and b/lab7/build/entry.o differ diff --git a/lab7/build/fault.o b/lab7/build/fault.o new file mode 100644 index 000000000..8dc66c972 Binary files /dev/null and b/lab7/build/fault.o differ diff --git a/lab7/build/fdt_parse.o b/lab7/build/fdt_parse.o new file mode 100644 index 000000000..512b452a1 Binary files /dev/null and b/lab7/build/fdt_parse.o differ diff --git a/lab7/build/framebuffer.o b/lab7/build/framebuffer.o new file mode 100644 index 000000000..674194910 Binary files /dev/null and b/lab7/build/framebuffer.o differ diff --git a/lab7/build/fs.o b/lab7/build/fs.o new file mode 100644 index 000000000..c84947aa3 Binary files /dev/null and b/lab7/build/fs.o differ diff --git a/lab7/build/initrdfs.o b/lab7/build/initrdfs.o new file mode 100644 index 000000000..92658f322 Binary files /dev/null and b/lab7/build/initrdfs.o differ diff --git a/lab7/build/irq_handler.o b/lab7/build/irq_handler.o new file mode 100644 index 000000000..7aae1bf0f Binary files /dev/null and b/lab7/build/irq_handler.o differ diff --git a/lab7/build/kernel8.elf b/lab7/build/kernel8.elf new file mode 100755 index 000000000..3b55f0224 Binary files /dev/null and b/lab7/build/kernel8.elf differ diff --git a/lab7/build/kernel8.img b/lab7/build/kernel8.img new file mode 100755 index 000000000..68ae7edab Binary files /dev/null and b/lab7/build/kernel8.img differ diff --git a/lab7/build/kernel_init.o b/lab7/build/kernel_init.o new file mode 100644 index 000000000..8cbdd4c8d Binary files /dev/null and b/lab7/build/kernel_init.o differ diff --git a/lab7/build/kthread.o b/lab7/build/kthread.o new file mode 100644 index 000000000..a21aca6ef Binary files /dev/null and b/lab7/build/kthread.o differ diff --git a/lab7/build/list.o b/lab7/build/list.o new file mode 100644 index 000000000..4380f49c8 Binary files /dev/null and b/lab7/build/list.o differ diff --git a/lab7/build/mailbox.o b/lab7/build/mailbox.o new file mode 100644 index 000000000..73a56ddb2 Binary files /dev/null and b/lab7/build/mailbox.o differ diff --git a/lab7/build/main.o b/lab7/build/main.o new file mode 100644 index 000000000..98d926b9a Binary files /dev/null and b/lab7/build/main.o differ diff --git a/lab7/build/mini_uart.o b/lab7/build/mini_uart.o new file mode 100644 index 000000000..89eff5af7 Binary files /dev/null and b/lab7/build/mini_uart.o differ diff --git a/lab7/build/mm.o b/lab7/build/mm.o new file mode 100644 index 000000000..7bccbaaf8 Binary files /dev/null and b/lab7/build/mm.o differ diff --git a/lab7/build/mmu.o b/lab7/build/mmu.o new file mode 100644 index 000000000..d0ac8576b Binary files /dev/null and b/lab7/build/mmu.o differ diff --git a/lab7/build/page_alloc.o b/lab7/build/page_alloc.o new file mode 100644 index 000000000..dea9f1c42 Binary files /dev/null and b/lab7/build/page_alloc.o differ diff --git a/lab7/build/print.o b/lab7/build/print.o new file mode 100644 index 000000000..95d4f9c85 Binary files /dev/null and b/lab7/build/print.o differ diff --git a/lab7/build/reboot.o b/lab7/build/reboot.o new file mode 100644 index 000000000..e176e8d8e Binary files /dev/null and b/lab7/build/reboot.o differ diff --git a/lab7/build/ring_buffer.o b/lab7/build/ring_buffer.o new file mode 100644 index 000000000..9ae58b65e Binary files /dev/null and b/lab7/build/ring_buffer.o differ diff --git a/lab7/build/sched.o b/lab7/build/sched.o new file mode 100644 index 000000000..54f1dd0e0 Binary files /dev/null and b/lab7/build/sched.o differ diff --git a/lab7/build/shell.o b/lab7/build/shell.o new file mode 100644 index 000000000..bcd1b0886 Binary files /dev/null and b/lab7/build/shell.o differ diff --git a/lab7/build/signal.o b/lab7/build/signal.o new file mode 100644 index 000000000..f0527dcbe Binary files /dev/null and b/lab7/build/signal.o differ diff --git a/lab7/build/simple_malloc.o b/lab7/build/simple_malloc.o new file mode 100644 index 000000000..30561a330 Binary files /dev/null and b/lab7/build/simple_malloc.o differ diff --git a/lab7/build/slab.o b/lab7/build/slab.o new file mode 100644 index 000000000..34eb6d7c5 Binary files /dev/null and b/lab7/build/slab.o differ diff --git a/lab7/build/start.o b/lab7/build/start.o new file mode 100644 index 000000000..d52bd549c Binary files /dev/null and b/lab7/build/start.o differ diff --git a/lab7/build/string.o b/lab7/build/string.o new file mode 100644 index 000000000..59c6f1bcd Binary files /dev/null and b/lab7/build/string.o differ diff --git a/lab7/build/syscall_table.o b/lab7/build/syscall_table.o new file mode 100644 index 000000000..61805bb82 Binary files /dev/null and b/lab7/build/syscall_table.o differ diff --git a/lab7/build/syscall_test.o b/lab7/build/syscall_test.o new file mode 100644 index 000000000..cf547fb9d Binary files /dev/null and b/lab7/build/syscall_test.o differ diff --git a/lab7/build/task.o b/lab7/build/task.o new file mode 100644 index 000000000..ae7b57a0c Binary files /dev/null and b/lab7/build/task.o differ diff --git a/lab7/build/timer.o b/lab7/build/timer.o new file mode 100644 index 000000000..a219a3a7f Binary files /dev/null and b/lab7/build/timer.o differ diff --git a/lab7/build/tmpfs.o b/lab7/build/tmpfs.o new file mode 100644 index 000000000..6e4e92550 Binary files /dev/null and b/lab7/build/tmpfs.o differ diff --git a/lab7/build/uartfs.o b/lab7/build/uartfs.o new file mode 100644 index 000000000..8ee083c94 Binary files /dev/null and b/lab7/build/uartfs.o differ diff --git a/lab7/build/vfs.o b/lab7/build/vfs.o new file mode 100644 index 000000000..4af2284bc Binary files /dev/null and b/lab7/build/vfs.o differ diff --git a/lab7/debug.sh b/lab7/debug.sh new file mode 100755 index 000000000..81d573d80 --- /dev/null +++ b/lab7/debug.sh @@ -0,0 +1,3 @@ +#!/bin/sh +make CFLAGS=-DDEBUG >/dev/null +make qemu-run diff --git a/lab7/debug/Makefile b/lab7/debug/Makefile new file mode 100644 index 000000000..22ac23500 --- /dev/null +++ b/lab7/debug/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + debug.o + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab7/debug/debug.c b/lab7/debug/debug.c new file mode 100644 index 000000000..057db34ab --- /dev/null +++ b/lab7/debug/debug.c @@ -0,0 +1,58 @@ +#include "debug/debug.h" + +extern int __bss_start, __bss_end; +extern int __text_start, __text_end; +extern int __rodata_start, __rodata_end; +extern int __data_start, __data_end; +extern int __heap_start; +extern int __reserved_page_table_start, __reserved_page_table_end; + +#ifdef DEBUG +int debug = 1; +#else +int debug = 0; +#endif + +void log_kernel_start(){ + uint64_t currentEL; + if(debug == 0) return; + printf("text_start=%p, text_end=%p, text_size=%u\r\n", \ + &__text_start, \ + &__text_end, \ + (uint64_t)&__text_end - (uint64_t)&__text_start + ); + + + printf("rodata_start=%p, rodata_end=%p, rodata_size=%u\r\n", \ + &__rodata_start, \ + &__rodata_end, \ + (uint64_t)&__rodata_end - (uint64_t)&__rodata_start + ); + + printf("data_start=%p, data_end=%p, data_size=%u\r\n", \ + &__data_start, \ + &__data_end, \ + (uint64_t)&__data_end - (uint64_t)&__data_start + ); + + printf("bss_start=%p, bss_end=%p, bss_size=%u\r\n", \ + &__bss_start, \ + &__bss_end, \ + (uint64_t)&__bss_end - (uint64_t)&__bss_start + ); + + printf("__reserved_page_table_start=%p, __reserved_page_table_end=%p,size=%l\r\n", \ + &__reserved_page_table_start, \ + &__reserved_page_table_end, \ + (uint64_t)&__reserved_page_table_end - (uint64_t)&__reserved_page_table_start + ); + + printf("heap_start=%p\r\n", &__heap_start); + + printf("current exception level: %u\r\n", get_currentEL()); + printf("SP_EL0: 0x%x\r\n", get_SP_ELx(0)); + printf("DAIF: 0x%x\r\n", get_DAIF()); + printf("SPSel: 0x%x\r\n", get_SPSel()); + printf("stack pointer: %p\r\n", ¤tEL); + +} diff --git a/lab7/fs/Makefile b/lab7/fs/Makefile new file mode 100644 index 000000000..364a756ea --- /dev/null +++ b/lab7/fs/Makefile @@ -0,0 +1,30 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + initrdfs.o \ + vfs.o \ + tmpfs.o \ + fs.o \ + uartfs.o \ + framebuffer.o \ + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab7/fs/framebuffer.c b/lab7/fs/framebuffer.c new file mode 100644 index 000000000..9f37156f6 --- /dev/null +++ b/lab7/fs/framebuffer.c @@ -0,0 +1,179 @@ +#include "fs/framebuffer.h" + +struct framebuffer_info fb_info; + +struct filesystem_type framebufferfs = { + .fs_name = "framebufferfs", + .mount = framebufferfs_mount +}; + +struct inode_operations framebufferfs_i_ops = { + .create = framebufferfs_create, + .lookup = framebufferfs_lookup, + .mkdir = framebufferfs_mkdir +}; + +struct file_operations framebufferfs_f_ops = { + .lseek64 = framebufferfs_lseek64, + .read = framebufferfs_read, + .write = framebufferfs_write, + .open = framebufferfs_open, + .flush = framebufferfs_flush, + .release = framebufferfs_release, + .ioctl = framebufferfs_ioctl +}; + +struct dentry* framebufferfs_create(struct dentry * parent, const char* new_file_name){ + FS_LOG("framebufferfs_create"); + return NULL; +} + +struct dentry *framebufferfs_lookup(struct dentry *parent, char* target){ + FS_LOG("framebufferfs_lookup"); + return NULL; +} + +int framebufferfs_lseek64(struct file * file, loff_t offset, int whence){ + FS_LOG("framebufferfs_lseek64"); + loff_t new_offset; + switch (whence) { + case SEEK_SET: + new_offset = offset; + break; + case SEEK_CUR: + new_offset = file->f_pos + offset; + break; + case SEEK_END: + new_offset = fb_info.lfb_size; + break; + default: + return -1; + } + if(new_offset > fb_info.lfb_size) return -1; + file->f_pos = new_offset; + return 0; +} + +long framebufferfs_read(struct file *file, char *buf, size_t len, loff_t *offset){ + return -1; +} + +long framebufferfs_write(struct file * file, char * buf, size_t len, loff_t * offset){ + uint64_t daif = local_irq_disable_save(); + struct dentry* d_file = file->f_dentry; + struct tmpfs_file* tmp_file = d_file->d_inode->private_data; + if(*offset + len > fb_info.lfb_size) len = fb_info.lfb_size - *offset; + + memcpy((void*)(fb_info.lfb + *offset), buf, len); + *offset += len; + + local_irq_restore(daif); + + return len; +} + +struct file* framebufferfs_open(struct dentry* d_file,uint32_t flags,umode_t mode){ + FS_LOG("framebufferfs_open"); + return create_file(d_file, flags, mode); +} +int framebufferfs_flush(struct file *){ + FS_LOG("framebufferfs_flush"); + return 0; +} +int framebufferfs_release(struct inode * inode, struct file * file){ + FS_LOG("framebufferfs_release"); + if(file == NULL) return -1; + + file->f_count--; + if(file->f_count == 0) kfree(file); + return 0; +} + +struct mount* framebufferfs_mount(struct filesystem_type* fs_type, struct dentry* target){ + FS_LOG("framebufferfs_mount"); + uint64_t daif = local_irq_disable_save(); + struct dentry* new_root, *link; + new_root->d_parent = target->d_parent; + struct inode* root_node = create_inode(&framebufferfs_f_ops, &framebufferfs_i_ops, S_IFCHR); + struct mount* ret = (struct mount*)kmalloc(sizeof(struct mount)); + + new_root = create_dentry("framebufferfs", 0, root_node); + target->d_mnt = ret; + ret->mnt_root = new_root; + local_irq_restore(daif); + return ret; +} + +int framebufferfs_ioctl(struct file*file, unsigned long request, va_list args){ + unsigned int __attribute__((aligned(16))) mbox[36]; + unsigned int width, height, pitch, isrgb; /* dimensions and channel order */ + unsigned char *lfb; /* raw frame buffer address */ + + mbox[0] = 35 * 4; + mbox[1] = MBOX_REQUEST; + + mbox[2] = 0x48003; // set phy wh + mbox[3] = 8; + mbox[4] = 8; + mbox[5] = 1024; // FrameBufferInfo.width + mbox[6] = 768; // FrameBufferInfo.height + + mbox[7] = 0x48004; // set virt wh + mbox[8] = 8; + mbox[9] = 8; + mbox[10] = 1024; // FrameBufferInfo.virtual_width + mbox[11] = 768; // FrameBufferInfo.virtual_height + + mbox[12] = 0x48009; // set virt offset + mbox[13] = 8; + mbox[14] = 8; + mbox[15] = 0; // FrameBufferInfo.x_offset + mbox[16] = 0; // FrameBufferInfo.y.offset + + mbox[17] = 0x48005; // set depth + mbox[18] = 4; + mbox[19] = 4; + mbox[20] = 32; // FrameBufferInfo.depth + + mbox[21] = 0x48006; // set pixel order + mbox[22] = 4; + mbox[23] = 4; + mbox[24] = 1; // RGB, not BGR preferably + + mbox[25] = 0x40001; // get framebuffer, gets alignment on request + mbox[26] = 8; + mbox[27] = 8; + mbox[28] = 4096; // FrameBufferInfo.pointer + mbox[29] = 0; // FrameBufferInfo.size + + mbox[30] = 0x40008; // get pitch + mbox[31] = 4; + mbox[32] = 4; + mbox[33] = 0; // FrameBufferInfo.pitch + + mbox[34] = MBOX_TAG_LAST; + + // this might not return exactly what we asked for, could be + // the closest supported resolution instead + if (Mbox_call(mbox, MBOX_CH_PROP) && mbox[20] == 32 && mbox[28] != 0) { + mbox[28] &= 0x3FFFFFFF; // convert GPU address to ARM address + fb_info.width = mbox[5]; // get actual physical width + fb_info.height = mbox[6]; // get actual physical height + fb_info.pitch = mbox[33]; // get number of bytes per line + fb_info.isrgb = mbox[24]; // get the actual channel order + fb_info.lfb = mbox[28]; + fb_info.lfb_size = mbox[29]; + + struct framebuffer_info* info = va_arg(args, void*); + info->width = fb_info.width; + info->height = fb_info.height; + info->pitch = fb_info.pitch; + info->isrgb = fb_info.isrgb; + // FS_LOG("lfb: %p", fb_info.lfb); + } + return 0; +} + +int framebufferfs_mkdir(struct dentry * parent, const char * target, umode_t mode){ + return -1; +} diff --git a/lab7/fs/fs.c b/lab7/fs/fs.c new file mode 100644 index 000000000..e92bd557d --- /dev/null +++ b/lab7/fs/fs.c @@ -0,0 +1,136 @@ +#include "fs/fs.h" +char *fbuf = "/dev/framebuffer"; +void fs_init(){ + vfs_init(&tmpfs); + register_filesystem(&tmpfs); + register_filesystem(&uartfs); + register_filesystem(&framebufferfs); + + vfs_mkdir("/dev", 0); + vfs_mkdir("/dev/uart", 0); + vfs_mount(vfs_lookup("/dev/uart"), "uartfs"); + + vfs_mkdir(fbuf, 0); + vfs_mount(vfs_lookup(fbuf), "framebufferfs"); +} + +// syscall number : 11 +int sys_open(const char *pathname, int flags){ + FS_LOG("sys_open"); + struct task_struct* current = get_current(); + struct files_struct *files = current->files; + struct file* f; + int fd, ret; + + fd = get_unused_fd(files); + if(fd == -1 || ((f = vfs_open(pathname, flags, 0)) == NULL)){ + put_unused_fd(files, fd); + ret = -1; + }else{ + fd_install(files, fd, f); + ret = fd; + } + FS_LOG("return fd: %d", ret); + return ret; +} + +// syscall number : 11 +int sys_close(int fd){ + FS_LOG("sys_close(%p)", fd); + if(fd > NR_OPEN_DEFAULT || fd < 0) return -1; + struct task_struct* current = get_current(); + struct files_struct* files = current->files; + struct file* file = get_file_by_fd(files, fd); + int ret = -1; + + if(file != NULL){ + ret = vfs_close(file); + if(ret != -1){ + put_unused_fd(files, fd); + } + } + return ret; +} + +// syscall number : 13 +// remember to return read size or error code +long sys_write(int fd, char *buf, unsigned long count){ + FS_LOG("sys_write(%p, %p, %p)",fd, buf, count); + if(fd > NR_OPEN_DEFAULT || fd < 0) return -1; + struct task_struct* current = get_current(); + struct file* file = get_file_by_fd(current->files, fd); + + return vfs_write(file, buf, count); +} + +// syscall number : 14 +// remember to return read size or error code +long sys_read(int fd, char *buf, unsigned long count){ + FS_LOG("sys_read(%p, %p, %p)",fd, buf, count); + if(fd > NR_OPEN_DEFAULT || fd < 0) return -1; + struct task_struct* current = get_current(); + struct file* file = get_file_by_fd(current->files, fd); + + return vfs_read(file, buf, count); +} + +// syscall number : 15 +// you can ignore mode, since there is no access control +int sys_mkdir(const char *pathname, unsigned mode){ + FS_LOG("sys_mkdir"); + + return vfs_mkdir(pathname, mode); +} + +// syscall number : 16 +// you can ignore arguments other than target (where to mount) and filesystem (fs name) +int sys_mount(const char *src, const char *target, const char *filesystem, unsigned long flags, const void *data){ + FS_LOG("sys_mount"); + int ret = -1; + struct dentry* target_dir; + target_dir = vfs_lookup(target); + if(target_dir != NULL && S_ISDIR(target_dir->d_inode->i_modes)){ + ret = vfs_mount(target_dir, filesystem); + } + return ret; +} + +// syscall number : 17 +int sys_chdir(const char *path){ + FS_LOG("sys_chdir"); + struct dentry* dest_dir; + struct task_struct* current = get_current(); + dest_dir = vfs_lookup(path); + + if(dest_dir == NULL || !S_ISDIR(dest_dir->d_inode->i_modes)) { + return -1; + }else{ + current->fs->pwd = dest_dir; + FS_LOG("PWD: %s", current->fs->pwd->d_name); + return 0; + } +} + +// syscall number : 18 +// you only need to implement seek set +long sys_lseek64(int fd, long offset, int whence){ + FS_LOG("sys_lseek64(%p, %p, %p)",fd, offset, whence); + if(fd > NR_OPEN_DEFAULT || fd < 0) return -1; + struct task_struct* current = get_current(); + struct file* file = get_file_by_fd(current->files, fd); + + return vfs_lseek64(file, offset, whence); +} + +// syscall number : 19 +long sys_ioctl(int fd, long request, ...){ + FS_LOG("sys_ioctl(%p, %p, ...)",fd, request); + if(fd > NR_OPEN_DEFAULT || fd < 0) return -1; + struct task_struct* current = get_current(); + struct file* file = get_file_by_fd(current->files, fd); + va_list ap; + + va_start(ap, request); + + return vfs_ioctl(file, request, ap); +} diff --git a/lab7/fs/initrdfs.c b/lab7/fs/initrdfs.c new file mode 100644 index 000000000..b0e656c90 --- /dev/null +++ b/lab7/fs/initrdfs.c @@ -0,0 +1,270 @@ +#include "fs/initrdfs.h" +static struct fentry * root; +/* +struct filesystem_type initrdfs = { + .fs_name = "initrdfs", + .mount = initrdfs_mount +}; + +struct inode_operations initrdfs_i_ops = { + .create = initrdfs_create, + .lookup = initrdfs_lookup, + .mkdir = initrdfs_mkdir +}; + +struct file_operations initrdfs_f_ops = { + .lseek64 = initrdfs_lseek64, + .read = initrdfs_read, + .write = initrdfs_write, + .open = initrdfs_open, + .flush = initrdfs_flush, + .release = initrdfs_release +};*/ + + +void initrdfs_init(void* addr){ + INFO("Initrd filesystem start address: %p", addr); + LOG("Enter initrdfs_int"); + LOG("initrd start at %p\n", addr); + LOG("initrd first 4 bytes: %x\n", *(uint32_t*)addr); + root = (struct fentry*)kmalloc(sizeof(struct fentry)); + struct cpio_iter iter; + char *fname = (char*)kmalloc(2); + strcpy(fname, "/"); + + memset(root, 0, sizeof(struct fentry)); + root->filename = fname; + root->namesize = 1; + root->mode = root->mode & FILE_TYPE_DIR; + + INIT_LIST_HEAD(&root->list); + + // Start parsing initrd in New ASCII Format at addr + LOG("Start parsing new ascii format's cpio"); + cpio_iter_init(&iter, addr); + do{ + struct fentry *f = (struct fentry*)kmalloc(sizeof(struct fentry)); + cpio_iter_parse(&iter, f); + LOG("FILE: %s", f->filename); + if(cpio_is_tailer(f)) break; + list_add_tail(&f->list, &root->list); + }while(1); + LOG("Leave initrdfs_int"); +} + +void* fdt_initrdfs_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(prop != NULL){ + if(strcmp(prop->name, "linux,initrd-start") == 0){ + uint64_t initrd_start = bswap32(*(uint32_t*)prop->value) + UPPER_ADDR_SPACE_BASE; + LOG("linux,initrd-start: %x", (uint32_t)initrd_start); + initrdfs_init((void*)initrd_start); + } + } +} + +void initrdfs_ls(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + printf("%s\r\n", f->filename); + } +} +void initrdfs_cat(){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + printf("Filename : %s\r\n", f->filename); + printf("File size: %u\r\n", f->filesize); + write_bytes(f->data, f->filesize); + printf("\r\n"); + } + } +} + +size_t initrdfs_loadfile(char* name, uint8_t* addr, uint64_t offset, uint64_t size){ + struct list_head* head = &root->list; + struct list_head* node; + + LOG("initrdfs_loadfile(%s, %p, %lu, %lu)", name, addr, offset, size); + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + if(strcmp(name, f->filename) == 0){ + if(offset <= f->filesize){ + if(offset + size > f->filesize){ + size = f->filesize - offset; + } + LOG("Load %lu bytes %s at offset %lu to %p",size , name, offset, addr); + memcpy(addr, &f->data[offset], size); + return size; + }else{ + LOG("error occur"); + } + break; + } + } + } + return 0; +} + +size_t initrdfs_filesize(char* name){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if((f->mode & FILE_TYPE_MASK) == FILE_TYPE_REGULAR){ + if(strcmp(name, f->filename) == 0){ + return f->filesize; + } + } + } + return 0; +} + + +// VFS +/* +struct initrdfs_dir* create_initrdfs_dir(){ + struct initrdfs_dir* ret = kmalloc(sizeof(struct initrdfs_dir)); + memset(ret, 0, sizeof(struct initrdfs_dir)); + return ret; +} + +struct dentry* create_initrdfs_file(const char* name, struct dentry* link, umode_t mode){ + char *new_file_name = kmalloc(strlen(name)); + struct dentry* ret; + struct initrdfs_file * tmp_file; + strcpy(new_file_name, name); + + // create dentry + ret = create_dentry(new_file_name, 0, NULL); + + // create and initialzie inode + ret->d_inode = create_inode(&initrdfs_f_ops, &initrdfs_i_ops, mode); + if(S_ISREG(mode)){ + ret->d_inode->private_data = kmalloc(sizeof(struct initrdfs_file)); + // create file data space + tmp_file = ret->d_inode->private_data; + tmp_file->size = 0; + tmp_file->data = calloc_page(); + }else if(S_ISDIR(mode)){ + ret->d_inode->private_data = create_initrdfs_dir(); + }else if(S_ISLNK(mode)){ + ret->d_inode->private_data = link; + } + + return ret; +} + +struct dentry* initrdfs_create(struct dentry * parent, const char* new_file_name){ + FS_LOG("initrdfs_create"); + return NULL; +} + +struct dentry *initrdfs_lookup(struct dentry *parent, char* target){ + FS_LOG("initrdfs_lookup"); + struct dentry* ent; + uint64_t daif = local_irq_disable_save(); + struct inode* parent_inode = parent->d_inode; + struct initrdfs_dir* parent_dir = parent_inode->private_data; + + for(uint64_t i = 0 ; i < MAX_NUM_DIR_ENTRY ; i++){ + ent = parent_dir->entries[i]; + if(ent != NULL && strcmp(ent->d_name, target) == 0){ + if(S_ISLNK(ent->d_inode->i_modes)){ + ent = ent->d_inode->private_data; + } + FS_LOG("found %s", ent->d_name); + local_irq_restore(daif); + return ent; + } + } + local_irq_restore(daif); + return NULL; +} + +loff_t initrdfs_lseek64(struct file *, loff_t, int){ + FS_LOG("initrdfs_lseek64"); +} + +long initrdfs_read(struct file *file, char *buf, size_t len, loff_t *offset){ + FS_LOG("initrdfs_read"); + uint64_t daif = local_irq_disable_save(); + struct dentry* d_file = file->f_dentry; + struct initrdfs_file* tmp_file = d_file->d_inode->private_data; + char* data = tmp_file->data; + size_t file_size = tmp_file->size; + if(*offset + len > file_size) len = file_size - *offset; + + memcpy(buf, &data[*offset], len); + *offset += len; + + local_irq_restore(daif); + return len; +} + +long initrdfs_write(struct file * file, char * buf, size_t len, loff_t * offset){ + FS_LOG("initrdfs_write"); + return -1; +} + +struct file* initrdfs_open(struct dentry* d_file,uint32_t flags,umode_t mode){ + FS_LOG("initrdfs_open"); + return create_file(d_file, flags, mode); +} +int initrdfs_flush(struct file *){ + FS_LOG("initrdfs_flush"); + return 0; +} +int initrdfs_release(struct inode * inode, struct file * file){ + FS_LOG("initrdfs_release"); + if(file == NULL) return -1; + + file->f_count--; + if(file->f_count == 0) kfree(file); + return 0; +} + +void initrdfs_mount_init(struct dentry* root){ + struct list_head* head = &root->list; + struct list_head* node; + + list_for_each(node, head){ + struct fentry* f = list_entry(node, struct fentry, list); + if(strcmp(f->fileanme, ".") != 0){ + + } + } +} + +struct mount* initrdfs_mount(struct filesystem_type* fs_type, struct dentry* target){ + FS_LOG("initrdfs_mount"); + uint64_t daif = local_irq_disable_save(); + struct dentry* new_root = create_initrdfs_file("", NULL, S_IFDIR), *link; + new_root->d_parent = target->d_parent; + struct inode* root_node = new_root->d_inode; + struct initrdfs_dir* new_dir; + struct mount* ret = (struct mount*)kmalloc(sizeof(struct mount)); + target->d_mnt = ret; + ret->mnt_root = new_root; + + new_dir = new_root->d_inode->private_data; + new_dir->count += 2; + link = new_root; + new_dir->entries[0] = create_initrdfs_file(".", link, S_IFLNK); + link = target->d_parent; + new_dir->entries[1] = create_initrdfs_file("..", link, S_IFLNK); + local_irq_restore(daif); + return ret; +} + + +int initrdfs_mkdir(struct dentry * parent, const char * target, umode_t mode){ + return -1; +}*/ diff --git a/lab7/fs/tmpfs.c b/lab7/fs/tmpfs.c new file mode 100644 index 000000000..79116b252 --- /dev/null +++ b/lab7/fs/tmpfs.c @@ -0,0 +1,201 @@ +#include "fs/tmpfs.h" + +struct filesystem_type tmpfs = { + .fs_name = "tmpfs", + .mount = tmpfs_mount +}; + +struct inode_operations tmpfs_i_ops = { + .create = tmpfs_create, + .lookup = tmpfs_lookup, + .mkdir = tmpfs_mkdir +}; + +struct file_operations tmpfs_f_ops = { + .lseek64 = tmpfs_lseek64, + .read = tmpfs_read, + .write = tmpfs_write, + .open = tmpfs_open, + .flush = tmpfs_flush, + .release = tmpfs_release +}; + +struct tmpfs_dir* create_tmpfs_dir(){ + struct tmpfs_dir* ret = kmalloc(sizeof(struct tmpfs_dir)); + memset(ret, 0, sizeof(struct tmpfs_dir)); + return ret; +} + +struct dentry* create_tmpfs_file(const char* name, struct dentry* link, umode_t mode){ + char *new_file_name = kmalloc(strlen(name)); + struct dentry* ret; + struct tmpfs_file * tmp_file; + strcpy(new_file_name, name); + + // create dentry + ret = create_dentry(new_file_name, 0, NULL); + + // create and initialzie inode + ret->d_inode = create_inode(&tmpfs_f_ops, &tmpfs_i_ops, mode); + if(S_ISREG(mode)){ + ret->d_inode->private_data = kmalloc(sizeof(struct tmpfs_file)); + // create file data space + tmp_file = ret->d_inode->private_data; + tmp_file->size = 0; + tmp_file->data = calloc_page(); + }else if(S_ISDIR(mode)){ + ret->d_inode->private_data = create_tmpfs_dir(); + }else if(S_ISLNK(mode)){ + ret->d_inode->private_data = link; + } + + return ret; +} + +struct dentry* tmpfs_create(struct dentry * parent, const char* new_file_name){ + FS_LOG("tmpfs_create"); + struct dentry* ent; + uint64_t daif = local_irq_disable_save(); + struct inode* parent_inode = parent->d_inode; + struct tmpfs_dir* parent_dir = parent_inode->private_data; + struct dentry* new_file; + + for(uint64_t i = 0 ; i < MAX_NUM_DIR_ENTRY ; i++){ + if(parent_dir->entries[i] == NULL){ + new_file = create_tmpfs_file(new_file_name, NULL, S_IFREG); + new_file->d_parent = parent; + parent_dir->entries[i] = new_file; + parent_dir->count++; + local_irq_restore(daif); + return new_file; + } + } + local_irq_restore(daif); + return NULL; +} + +struct dentry *tmpfs_lookup(struct dentry *parent, char* target){ + FS_LOG("tmpfs_lookup(%s, %s)", parent->d_name, target); + struct dentry* ent; + uint64_t daif = local_irq_disable_save(); + struct inode* parent_inode = parent->d_inode; + struct tmpfs_dir* parent_dir = parent_inode->private_data; + + for(uint64_t i = 0 ; i < MAX_NUM_DIR_ENTRY ; i++){ + ent = parent_dir->entries[i]; + if(ent!=NULL)FS_LOG("%s", ent->d_name); + if(ent != NULL && strcmp(ent->d_name, target) == 0){ + if(ent->d_flags & DENTRY_FLAG_MOUNTED){ + ent = ent->d_mnt->mnt_root; + }else if(S_ISLNK(ent->d_inode->i_modes)){ + ent = ent->d_inode->private_data; + } + FS_LOG("found %s", ent->d_name); + return ent; + } + } + local_irq_restore(daif); + return NULL; +} + +int tmpfs_lseek64(struct file *, loff_t, int){ + FS_LOG("tmpfs_lseek64"); +} + +long tmpfs_read(struct file *file, char *buf, size_t len, loff_t *offset){ + FS_LOG("tmpfs_read"); + uint64_t daif = local_irq_disable_save(); + struct dentry* d_file = file->f_dentry; + struct tmpfs_file* tmp_file = d_file->d_inode->private_data; + char* data = tmp_file->data; + size_t file_size = tmp_file->size; + if(*offset + len > file_size) len = file_size - *offset; + + memcpy(buf, &data[*offset], len); + *offset += len; + + local_irq_restore(daif); + return len; +} + +long tmpfs_write(struct file * file, char * buf, size_t len, loff_t * offset){ + FS_LOG("tmpfs_write"); + uint64_t daif = local_irq_disable_save(); + struct dentry* d_file = file->f_dentry; + struct tmpfs_file* tmp_file = d_file->d_inode->private_data; + char* data = tmp_file->data; + if(*offset + len > MAX_FILE_SIZE) len = MAX_FILE_SIZE - *offset; + + memcpy(&data[*offset], buf, len); + *offset += len; + tmp_file->size = *offset; + + local_irq_restore(daif); + return len; +} + +struct file* tmpfs_open(struct dentry* d_file,uint32_t flags,umode_t mode){ + FS_LOG("tmpfs_open"); + return create_file(d_file, flags, mode); +} +int tmpfs_flush(struct file *){ + FS_LOG("tmpfs_flush"); + return 0; +} +int tmpfs_release(struct inode * inode, struct file * file){ + FS_LOG("tmpfs_release"); + if(file == NULL) return -1; + + file->f_count--; + if(file->f_count == 0) kfree(file); + return 0; +} +struct mount* tmpfs_mount(struct filesystem_type* fs_type, struct dentry* target){ + FS_LOG("tmpfs_mount"); + uint64_t daif = local_irq_disable_save(); + struct dentry* new_root = create_tmpfs_file("", NULL, S_IFDIR), *link; + new_root->d_parent = target->d_parent; + struct inode* root_node = new_root->d_inode; + struct tmpfs_dir* new_dir; + struct mount* ret = (struct mount*)kmalloc(sizeof(struct mount)); + target->d_mnt = ret; + ret->mnt_root = new_root; + + new_dir = new_root->d_inode->private_data; + new_dir->count += 2; + link = new_root; + new_dir->entries[0] = create_tmpfs_file(".", link, S_IFLNK); + link = target->d_parent; + new_dir->entries[1] = create_tmpfs_file("..", link, S_IFLNK); + local_irq_restore(daif); + return ret; +} + + +int tmpfs_mkdir(struct dentry * parent, const char * target, umode_t mode){ + uint64_t daif = local_irq_disable_save(); + struct tmpfs_dir* parent_dir = parent->d_inode->private_data; + struct dentry* new_file, *link; + struct tmpfs_dir* new_dir; + + for(uint64_t i = 0 ; i < MAX_NUM_DIR_ENTRY ; i++){ + if(parent_dir->entries[i] == NULL){ + new_file = create_tmpfs_file(target, NULL, mode|S_IFDIR); + new_file->d_parent = parent; + parent_dir->entries[i] = new_file; + parent_dir->count++; + + // add . and .. + new_dir = new_file->d_inode->private_data; + new_dir->count += 2; + link = new_file; + new_dir->entries[0] = create_tmpfs_file(".", link, S_IFLNK); + link = parent; + new_dir->entries[1] = create_tmpfs_file("..", link, S_IFLNK); + local_irq_restore(daif); + return 0; + } + } + local_irq_restore(daif); + return -1; +} diff --git a/lab7/fs/uartfs.c b/lab7/fs/uartfs.c new file mode 100644 index 000000000..728e250bf --- /dev/null +++ b/lab7/fs/uartfs.c @@ -0,0 +1,80 @@ +#include "fs/uartfs.h" + +struct filesystem_type uartfs = { + .fs_name = "uartfs", + .mount = uartfs_mount +}; + +struct inode_operations uartfs_i_ops = { + .create = uartfs_create, + .lookup = uartfs_lookup, + .mkdir = uartfs_mkdir +}; + +struct file_operations uartfs_f_ops = { + .lseek64 = uartfs_lseek64, + .read = uartfs_read, + .write = uartfs_write, + .open = uartfs_open, + .flush = uartfs_flush, + .release = uartfs_release +}; + +struct dentry* uartfs_create(struct dentry * parent, const char* new_file_name){ + FS_LOG("uartfs_create"); + return NULL; +} + +struct dentry *uartfs_lookup(struct dentry *parent, char* target){ + FS_LOG("uartfs_lookup"); + return NULL; +} + +int uartfs_lseek64(struct file *, loff_t, int){ + FS_LOG("uartfs_lseek64"); +} + +long uartfs_read(struct file *file, char *buf, size_t len, loff_t *offset){ + return uart_read(buf, len); +} + +long uartfs_write(struct file * file, char * buf, size_t len, loff_t * offset){ + return uart_write(buf, len); +} + +struct file* uartfs_open(struct dentry* d_file,uint32_t flags,umode_t mode){ + FS_LOG("uartfs_open"); + return create_file(d_file, flags, mode); +} +int uartfs_flush(struct file *){ + FS_LOG("uartfs_flush"); + return 0; +} +int uartfs_release(struct inode * inode, struct file * file){ + FS_LOG("uartfs_release"); + if(file == NULL) return -1; + + file->f_count--; + if(file->f_count == 0) kfree(file); + return 0; +} +struct mount* uartfs_mount(struct filesystem_type* fs_type, struct dentry* target){ + FS_LOG("uartfs_mount"); + uint64_t daif = local_irq_disable_save(); + struct dentry* new_root, *link; + new_root->d_parent = target->d_parent; + struct inode* root_node = create_inode(&uartfs_f_ops, &uartfs_i_ops, S_IFCHR); + struct mount* ret = (struct mount*)kmalloc(sizeof(struct mount)); + + new_root = create_dentry("uartfs", 0, root_node); + target->d_mnt = ret; + ret->mnt_root = new_root; + + local_irq_restore(daif); + return ret; +} + + +int uartfs_mkdir(struct dentry * parent, const char * target, umode_t mode){ + return -1; +} diff --git a/lab7/fs/vfs.c b/lab7/fs/vfs.c new file mode 100644 index 000000000..595d455c5 --- /dev/null +++ b/lab7/fs/vfs.c @@ -0,0 +1,320 @@ +#include "mm/mm.h" +#include "fs/tmpfs.h" +#include "fs/vfs.h" + +struct mount* rootfs; +LIST_HEAD(mount_list); +LIST_HEAD(filesystem_type_list); + +struct file* get_file_by_fd(struct files_struct* files, int fd){ + struct file* ret; + uint64_t daif = local_irq_disable_save(); + ret = files->fd_array[fd]; + local_irq_restore(daif); + return ret; +} + +int get_unused_fd(struct files_struct* files){ + int fd = -1; + uint64_t daif = local_irq_disable_save(); + for(int i = 0 ; i < NR_OPEN_DEFAULT ; i++){ + if(files->fd_array[i] == NULL){ + fd = i; + files->fd_array[i] = (struct file*)1; + break; + } + } + local_irq_restore(daif); + return fd; +} + +int put_unused_fd(struct files_struct* files, int fd){ + uint64_t daif = local_irq_disable_save(); + files->fd_array[fd] = NULL; + local_irq_restore(daif); +} + +int fd_install(struct files_struct* files, int fd, struct file *f){ + uint64_t daif = local_irq_disable_save(); + files->fd_array[fd] = f; + local_irq_restore(daif); +} + +int vfs_lseek64(struct file * file, loff_t offset, int whence){ + return file->f_ops->lseek64(file, offset, whence); +} + +void vfs_init(struct filesystem_type* fs_type){ + struct inode* inode_root; + struct dentry* root, *link; + struct tmpfs_dir* root_dir; + struct mount* root_mnt; + + // create root filesystem + root = create_tmpfs_file("/", NULL, S_IFDIR); + root->d_parent = root; + + root_dir = root->d_inode->private_data; + root_dir->count += 2; + link = root; + root_dir->entries[0] = create_tmpfs_file(".", link, S_IFLNK); + root_dir->entries[1] = create_tmpfs_file("..", link, S_IFLNK); + + + root_mnt = fs_type->mount(fs_type, root); + root->d_flags |= DENTRY_FLAG_MOUNTED; + + // add root mount to mount list + list_add_tail(&root_mnt->list, &mount_list); + + // set rootfs + rootfs = root_mnt; +} + +struct inode* create_inode(struct file_operations *f_ops, struct inode_operations *i_ops, umode_t i_modes){ + struct inode* ret = (struct inode*)kmalloc(sizeof(struct inode)); + ret->i_modes = i_modes; + ret->i_ops = i_ops; + ret->f_ops = f_ops; + ret->private_data = NULL; + return ret; +} + +struct dentry* create_dentry(char *d_name, int d_flags, struct inode* d_inode){ + struct dentry* ret = (struct dentry*)kmalloc(sizeof(struct dentry)); + ret->d_name = d_name; + ret->d_flags = d_flags; + + ret->d_inode = d_inode; + return ret; +} + +struct file* create_file(struct dentry* d, unsigned int flags, unsigned mode){ + struct file* ret = (struct file*)kmalloc(sizeof(struct file)); + ret->f_dentry = d; + ret->f_count = 1; + ret->f_flags = flags; + ret->f_pos = 0; + ret->f_ops = d->d_inode->f_ops; + ret->f_mode = mode; + + return ret; +} + +struct file* vfs_open(const char* pathname, int flags, umode_t mode){ + const char* delim = "/"; + char* name, *prev_tok; + struct task_struct* current = get_current(); + struct dentry* prev = NULL, *next, *pwd; + char* tok, *new_file_name; + FS_LOG("vfs_open(%s, %p, %p)", pathname, flags, mode); + if(pathname[0] == '\0') goto error; + + if(pathname[0] == '/'){ + next = rootfs->mnt_root; + pathname++; + }else{ + current = get_current(); + pwd = current->fs->pwd; + next = pwd; + } + + name = (char*)kmalloc(strlen(pathname)); + strcpy(name, pathname); + FS_LOG("target pathname: %s", name); + FS_LOG("lookup start from: %s", next->d_name); + + tok = strtok(name, delim); + while (tok != NULL) { + FS_LOG("%s", tok); + if(next == NULL || !S_ISDIR(next->d_inode->i_modes)) goto free; + prev_tok = tok; + prev = next; + next = next->d_inode->i_ops->lookup(next, tok); + FS_LOG("next: %p, next->d_name: %s", next, next == NULL ? "[NULL]" : next->d_name); + tok = strtok(NULL, delim); + } + + if(next == NULL && (flags | O_CREAT)){ + next = prev->d_inode->i_ops->create(prev, prev_tok); + } + + FS_LOG("open file: %p, i_modes: %p", next, next->d_inode->i_modes); + if(next != NULL && (S_ISREG(next->d_inode->i_modes) || S_ISCHR(next->d_inode->i_modes))) goto found; + +free: + kfree(name); +error: + FS_LOG("not found"); + return NULL; +found: + FS_LOG("found"); + kfree(name); + return prev->d_inode->f_ops->open(next, flags, mode); +} + +int vfs_close(struct file* file){ + struct inode* inode = file->f_dentry->d_inode; + int ret = -1; + + do{ + if(file == NULL) break; + + ret = file->f_ops->flush(file); + if(ret == -1) break; + + ret = file->f_ops->release(inode, file); + if(ret == -1) break; + + + + ret = 0; + }while(0); + return ret; +} + +long vfs_write(struct file* file, char* buf, ssize_t len){ + int ret; + ret = file->f_ops->write(file, buf, len, &file->f_pos); + return ret; +} + +long vfs_read(struct file* file, char* buf, ssize_t len){ + int ret; + ret = file->f_ops->read(file, buf, len, &file->f_pos); + return ret; +} + +struct dentry* vfs_lookup(const char* pathname){ + const char* delim = "/"; + char* name, *prev_tok; + struct task_struct* current = get_current(); + struct dentry* prev = NULL, *next, *pwd; + char* tok, *new_file_name; + uint64_t daif; + FS_LOG("vfs_lookup(%s)", pathname); + if(pathname[0] == '\0') goto error; + + if(pathname[0] == '/'){ + next = rootfs->mnt_root; + pathname++; + }else{ + current = get_current(); + pwd = current->fs->pwd; + next = pwd; + } + + name = (char*)kmalloc(strlen(pathname)); + strcpy(name, pathname); + FS_LOG("pathname: %s", name); + FS_LOG("next->d_name: %s", next->d_name); + + tok = strtok(name, delim); + + daif = local_irq_disable_save(); + while (tok != NULL) { + FS_LOG("%s", tok); + if(next == NULL || !S_ISDIR(next->d_inode->i_modes)) goto free; + prev_tok = tok; + prev = next; + next = next->d_inode->i_ops->lookup(next, tok); + FS_LOG("next: %p, next->d_name: %s", next, next == NULL ? "[NULL]" : next->d_name); + tok = strtok(NULL, delim); + } + local_irq_restore(daif); + if(next != NULL) goto found; + +free: + kfree(name); +error: + FS_LOG("not found"); + return NULL; +found: + FS_LOG("found"); + kfree(name); + return next; +} + +int vfs_mount(struct dentry* target, const char* filesystem){ + FS_LOG("vfs_mount(%s, %s)", target->d_name, filesystem); + struct list_head* node; + struct filesystem_type* fs_type; + struct mount* mount; + int ret = -1; + uint64_t daif = local_irq_disable_save(); + if(target->d_flags & DENTRY_FLAG_MOUNTED) goto end; + + list_for_each(node, &filesystem_type_list){ + fs_type = list_entry(node, struct filesystem_type, list); + if(strcmp(fs_type->fs_name,(char*) filesystem) == 0) break; + } + + mount = fs_type->mount(fs_type, target); + if(mount){ + list_add_tail(&mount->list, &mount_list); + target->d_flags |= DENTRY_FLAG_MOUNTED; + ret = 0; + } +end: + if(!ret)FS_LOG("vfs_mount success!"); + else FS_LOG("vfs_mount failed!"); + local_irq_restore(daif); + return ret; +} + +int register_filesystem(struct filesystem_type* fs){ + // register the file system to the kernel. + // you can also initialize memory pool of the file system here. + list_add_tail(&fs->list, &filesystem_type_list); +} + +int vfs_mkdir(const char* pathname, umode_t mode){ + const char* delim = "/"; + char* name, *prev_tok; + struct task_struct* current = get_current(); + struct dentry* prev = NULL, *next, *pwd; + char* tok, *new_file_name; + FS_LOG("vfs_mkdir(%s, %p)", pathname, mode); + if(pathname[0] == '\0') goto error; + + if(pathname[0] == '/'){ + next = rootfs->mnt_root; + pathname++; + }else{ + current = get_current(); + pwd = current->fs->pwd; + next = pwd; + } + + name = (char*)kmalloc(strlen(pathname)); + strcpy(name, pathname); + FS_LOG("pathname: %s", name); + FS_LOG("next->d_name: %s", next->d_name); + + tok = strtok(name, delim); + while (tok != NULL) { + FS_LOG("%s", tok); + if(next == NULL || !S_ISDIR(next->d_inode->i_modes)) goto free; + prev_tok = tok; + prev = next; + next = next->d_inode->i_ops->lookup(next, tok); + FS_LOG("next: %p, next->d_name: %s", next, (next == NULL) ? "[NULL]" : next->d_name); + tok = strtok(NULL, delim); + } + + if(next == NULL){ + if(!prev->d_inode->i_ops->mkdir(prev, prev_tok, mode|S_IFDIR)) goto success; + } + +free: + kfree(name); +error: + return -1; +success: + kfree(name); + return 0; +} + +int vfs_ioctl(struct file *file, uint32_t request, va_list args){ + return file->f_ops->ioctl(file, request, args); +} diff --git a/lab7/include/asm.h b/lab7/include/asm.h new file mode 100644 index 000000000..633fd18fa --- /dev/null +++ b/lab7/include/asm.h @@ -0,0 +1,24 @@ +#ifndef _ASM_H_ +#define _ASM_H_ +extern uint32_t get_currentEL(); +extern uint64_t get_SP_ELx(uint32_t); +extern uint64_t get_DAIF(); +extern void set_DAIF(uint64_t); +extern uint64_t get_SPSel(); +extern uint64_t get_ESR_EL1(); +extern uint64_t get_SPSR_EL1(); +extern uint64_t get_ELR_EL1(); +extern uint64_t get_SP(); +extern uint64_t get_CNTP_CTL_EL0(); +extern void set_CNTP_CTL_EL0(uint64_t); +extern uint64_t get_CNTFRQ_EL0(); +extern void set_CNTP_TVAL_EL0(uint64_t); +extern uint64_t get_CNTPCT_EL0(); +extern void local_irq_enable(); +extern void local_irq_disable(); +extern uint64_t local_irq_disable_save(); +extern void local_irq_restore(uint64_t); +extern void set_tpidr_el1(uint64_t); + +#endif + diff --git a/lab7/include/debug/debug.h b/lab7/include/debug/debug.h new file mode 100644 index 000000000..1f93f57a7 --- /dev/null +++ b/lab7/include/debug/debug.h @@ -0,0 +1,21 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "lib/print.h" +#include "types.h" +#include "asm.h" + +#define DEBUG_KERNEL_START() log_kernel_start() +#define LOG(fmt, ...) \ + if(0) \ + printf("[%s/%s:%d] " fmt "\r\n" , __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) + +#define FS_LOG(fmt, ...) \ + if(debug) \ + printf("[%s/%s:%d] " fmt "\r\n" , __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) + + +extern void log_kernel_start(void); + +extern int debug; +#endif diff --git a/lab7/include/fs/framebuffer.h b/lab7/include/fs/framebuffer.h new file mode 100644 index 000000000..9cc432b0e --- /dev/null +++ b/lab7/include/fs/framebuffer.h @@ -0,0 +1,32 @@ +#ifndef _FRAMEBUFFER_H_ +#define _FRAMEBUFFER_H_ +#include "fs/vfs.h" +#include "asm.h" +#include "peripherals/mailbox.h" + +struct framebuffer_info{ + uint32_t width; + uint32_t height; + uint32_t pitch; + uint32_t isrgb; + uint32_t lfb; + uint32_t lfb_size; +}; + +extern struct filesystem_type framebufferfs; +extern struct inode_operations framebufferfs_i_ops; +extern struct file_operations framebufferfs_f_ops; +extern struct mount* framebufferfs_mount(struct filesystem_type*, struct dentry*); +extern struct dentry* framebufferfs_create(struct dentry *, const char*); +extern struct dentry *framebufferfs_lookup(struct dentry *, char*); +extern int framebufferfs_lseek64(struct file *, loff_t, int); +extern long framebufferfs_read(struct file *, char *, size_t, loff_t *); +extern long framebufferfs_write(struct file *, char *, size_t, loff_t *); +extern struct file* framebufferfs_open(struct dentry *,uint32_t , umode_t ); +extern int framebufferfs_flush(struct file *); +extern int framebufferfs_release(struct inode *, struct file*); +extern int framebufferfs_mkdir(struct dentry *, const char *, umode_t); +extern int framebufferfs_ioctl(struct file*, unsigned long, va_list); + +extern struct filesystem_type framebufferfs; +#endif diff --git a/lab7/include/fs/fs.h b/lab7/include/fs/fs.h new file mode 100644 index 000000000..a41be81c4 --- /dev/null +++ b/lab7/include/fs/fs.h @@ -0,0 +1,19 @@ +#ifndef _FS_H_ +#define _FS_H_ +#include "fs/tmpfs.h" +#include "fs/uartfs.h" +#include "fs/framebuffer.h" + +extern int sys_open(const char *, int); +extern int sys_close(int); +extern long sys_write(int, char *, unsigned long); +extern long sys_read(int, char *, unsigned long); +extern int sys_mkdir(const char *, unsigned); +extern int sys_mount(const char *, const char *, const char *, unsigned long, const void *); +extern int sys_chdir(const char *); +extern long sys_lseek64(int, long, int); +extern long sys_ioctl(int, long, ...); +extern void fs_init(); + + +#endif diff --git a/lab7/include/fs/initrdfs.h b/lab7/include/fs/initrdfs.h new file mode 100644 index 000000000..5290ac969 --- /dev/null +++ b/lab7/include/fs/initrdfs.h @@ -0,0 +1,20 @@ +#ifndef _INITRDFS_H_ +#define _INITRDFS_H_ +#include "types.h" +#include "lib/cpio.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "mm/slab.h" +#include "lib/list.h" +#include "lib/string.h" +#include "debug/debug.h" +#include "peripherals/mini_uart.h" +#include "fs/vfs.h" + +extern void initrdfs_init(void*); +extern void initrdfs_ls(); +extern void initrdfs_cat(); +extern void* fdt_initrdfs_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +extern size_t initrdfs_loadfile(char* , uint8_t*, size_t, size_t); +extern size_t initrdfs_filesize(char*); +#endif diff --git a/lab7/include/fs/tmpfs.h b/lab7/include/fs/tmpfs.h new file mode 100644 index 000000000..745601a29 --- /dev/null +++ b/lab7/include/fs/tmpfs.h @@ -0,0 +1,34 @@ +#ifndef _TMPFS_H_ +#define _TMPFS_H_ +#include "fs/vfs.h" +#include "types.h" +#include "mm/mmu.h" + +#define MAX_NUM_DIR_ENTRY 20 +#define MAX_FILE_SIZE PAGE_SIZE + +struct tmpfs_dir{ + uint64_t count; + struct dentry* entries[MAX_NUM_DIR_ENTRY]; +}; + +struct tmpfs_file{ + size_t size; + void* data; +}; + +extern struct filesystem_type tmpfs; +extern struct inode_operations tmpfs_i_ops; +extern struct file_operations tmpfs_f_ops; +extern struct mount* tmpfs_mount(struct filesystem_type*, struct dentry*); +extern struct dentry* tmpfs_create(struct dentry *, const char*); +extern struct dentry *tmpfs_lookup(struct dentry *, char*); +extern int tmpfs_lseek64(struct file *, loff_t, int); +extern long tmpfs_read(struct file *, char *, size_t, loff_t *); +extern long tmpfs_write(struct file *, char *, size_t, loff_t *); +extern struct file* tmpfs_open(struct dentry *,uint32_t , umode_t ); +extern int tmpfs_flush(struct file *); +extern int tmpfs_release(struct inode *, struct file*); +extern int tmpfs_mkdir(struct dentry *, const char *, umode_t); +extern struct dentry* create_tmpfs_file(const char*, struct dentry*, umode_t); +#endif diff --git a/lab7/include/fs/uartfs.h b/lab7/include/fs/uartfs.h new file mode 100644 index 000000000..54ccf3599 --- /dev/null +++ b/lab7/include/fs/uartfs.h @@ -0,0 +1,22 @@ +#ifndef _UARTFS_H_ +#define _UARTFS_H_ +#include "fs/vfs.h" +#include "asm.h" +#include "peripherals/mini_uart.h" + +extern struct filesystem_type uartfs; +extern struct inode_operations uartfs_i_ops; +extern struct file_operations uartfs_f_ops; +extern struct mount* uartfs_mount(struct filesystem_type*, struct dentry*); +extern struct dentry* uartfs_create(struct dentry *, const char*); +extern struct dentry *uartfs_lookup(struct dentry *, char*); +extern int uartfs_lseek64(struct file *, loff_t, int); +extern long uartfs_read(struct file *, char *, size_t, loff_t *); +extern long uartfs_write(struct file *, char *, size_t, loff_t *); +extern struct file* uartfs_open(struct dentry *,uint32_t , umode_t ); +extern int uartfs_flush(struct file *); +extern int uartfs_release(struct inode *, struct file*); +extern int uartfs_mkdir(struct dentry *, const char *, umode_t); + +extern struct filesystem_type uartfs; +#endif diff --git a/lab7/include/fs/vfs.h b/lab7/include/fs/vfs.h new file mode 100644 index 000000000..ccb562399 --- /dev/null +++ b/lab7/include/fs/vfs.h @@ -0,0 +1,123 @@ +#ifndef _VFS_H_ +#define _VFS_H_ +#include "lib/list.h" +#include "asm.h" +#include "lib/print.h" +#include "types.h" +#include "lib/string.h" +#include +typedef uint64_t umode_t; +typedef uint64_t loff_t; +typedef uint64_t dev_t; +#define SEEK_SET 0x0 +#define SEEK_CUR 0x1 +#define SEEK_END 0x2 + +#define NR_OPEN_DEFAULT 64 + +#define O_CREAT 00000100 + +#define DENTRY_FLAG_MOUNTED (1 << 0) + +#define S_IFMT 00170000 +#define S_IFSOCK 0140000 +#define S_IFLNK 0120000 +#define S_IFREG 0100000 +#define S_IFBLK 0060000 +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFIFO 0010000 + +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) + + +struct mount{ + struct dentry* mnt_root; + struct list_head list; +}; + +struct filesystem_type{ + char* fs_name; + struct mount* (*mount)(struct filesystem_type*, struct dentry*); + struct list_head list; +}; + +struct inode{ + umode_t i_modes; + struct inode_operations *i_ops; + struct file_operations *f_ops; + void * private_data; +}; + +struct dentry{ + char* d_name; + struct dentry* d_parent; + int d_flags; + struct mount* d_mnt; + + struct inode *d_inode; +}; + +struct file{ + struct dentry *f_dentry; /* associated dentry object */ + struct file_operations *f_ops; /* file operations table */ + uint64_t f_count; /* file object's usage count */ + loff_t f_pos; + unsigned int f_flags; /* flags specified on open */ + umode_t f_mode; /* file access mode */ +}; + +struct fs_struct{ + struct dentry *pwd; + struct dentry *root; +}; + +struct files_struct{ + struct file* fd_array[NR_OPEN_DEFAULT]; +}; + +struct inode_operations{ + struct dentry *(*create) (struct dentry *, const char*); + struct dentry * (*lookup) (struct dentry *, char*); + int (*link) (struct dentry *,struct inode *,struct dentry *); + int (*mkdir) (struct dentry *, const char *, umode_t); + int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); +}; + +struct file_operations{ + int (*lseek64) (struct file *, loff_t, int); + long (*read) (struct file *, char *, size_t, loff_t *); + long (*write) (struct file *, char *, size_t, loff_t *); + struct file* (*open) (struct dentry *, unsigned int, umode_t); + int (*flush) (struct file *); + int (*release) (struct inode *, struct file *); + int (*ioctl)(struct file*, unsigned long, va_list ); +}; + +extern struct file* vfs_open(const char*, int, umode_t); +extern int vfs_close(struct file*); +extern long vfs_write(struct file*, char*, ssize_t); +extern long vfs_read(struct file*, char*, ssize_t); +extern struct dentry* vfs_lookup(const char*); +extern int vfs_mount(struct dentry*, const char*); +extern struct dentry* create_dentry(char *, int, struct inode*); +extern struct inode* create_inode(struct file_operations *, struct inode_operations *, umode_t); +extern int register_filesystem(struct filesystem_type*); +extern void vfs_init(struct filesystem_type*); +extern int get_unused_fd(struct files_struct* ); +extern int put_unused_fd(struct files_struct*, int); +extern int fd_install(struct files_struct*, int, struct file*); +extern struct file* get_file_by_fd(struct files_struct*, int); +extern int vfs_mkdir(const char*, umode_t); +extern struct file* create_file(struct dentry* , unsigned int, unsigned); +extern int vfs_lseek64(struct file *, loff_t, int); +extern int vfs_ioctl(struct file *, uint32_t, va_list ); + +extern struct mount* rootfs; +#endif diff --git a/lab7/include/init/kernel_init.h b/lab7/include/init/kernel_init.h new file mode 100644 index 000000000..97168ccc9 --- /dev/null +++ b/lab7/include/init/kernel_init.h @@ -0,0 +1,17 @@ +#ifndef _KERNEL_INIT_H +#define _KERNEL_INIT_H +#include "types.h" +#include "peripherals/mini_uart.h" +#include "fs/initrdfs.h" +#include "kernel/timer.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "mm/mm.h" +#include "asm.h" +#include "kernel/sched/sched.h" +#include "kernel/sched/kthread.h" +#include "fs/fs.h" + +extern void kernel_init(void *); + +#endif diff --git a/lab7/include/kernel/fault.h b/lab7/include/kernel/fault.h new file mode 100644 index 000000000..7052892cf --- /dev/null +++ b/lab7/include/kernel/fault.h @@ -0,0 +1,13 @@ +#ifndef _FAULT_H_ +#define _FAULT_H_ + +#include "mm/mm.h" +#include "lib/print.h" +#include "types.h" + +#define FAULT_DATA_ABORT_LOW_EL (0b100100) +#define FAULT_DATA_ABORT (0b100101) +#define FAULT_INSTR_ABORT_LOW_EL (0b100000) +#define FAULT_INSTR_ABORT (0b100001) + +#endif diff --git a/lab7/include/kernel/irq_handler.h b/lab7/include/kernel/irq_handler.h new file mode 100644 index 000000000..52ff3091f --- /dev/null +++ b/lab7/include/kernel/irq_handler.h @@ -0,0 +1,25 @@ +#ifndef _IRQ_HANDLER_H_ +#define _IRQ_HANDLER_H_ + +#include "types.h" +#include "peripherals/iomapping.h" +#include "peripherals/mini_uart.h" +#include "lib/print.h" +#include "lib/bitops.h" +#include "kernel/timer.h" +#include "kernel/sched/sched.h" +#include "debug/debug.h" +#include "asm.h" + +#define MAX_SOFTIRQ_TRY 10 + +enum {CORE0_TIMER = 0, MINI_UART_RX, UNKNOWN_IRQ, END_OF_LIST}; +typedef void (*irq_funcptr)(void); + +struct softirq_status{ + uint16_t pending; // support 16 interrupt + uint8_t in_softirq; +}; +extern uint64_t irq_count[END_OF_LIST]; +extern uint8_t in_softirq(); +#endif diff --git a/lab7/include/kernel/reboot.h b/lab7/include/kernel/reboot.h new file mode 100644 index 000000000..cc8e8730b --- /dev/null +++ b/lab7/include/kernel/reboot.h @@ -0,0 +1,16 @@ +#ifndef _REBOOT_H_ +#define _REBOOT_H_ + +#include "peripherals/iomapping.h" + +#define PM_WDOG_RESET 0000000000 +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +extern void reboot(int tick); + +#endif diff --git a/lab7/include/kernel/sched/kthread.h b/lab7/include/kernel/sched/kthread.h new file mode 100644 index 000000000..36d471908 --- /dev/null +++ b/lab7/include/kernel/sched/kthread.h @@ -0,0 +1,20 @@ +#ifndef _KTHREAD_H_ +#define _KTHREAD_H_ + +#include "kernel/sched/sched.h" +#include "kernel/sched/task.h" +#include "mm/page_alloc.h" +#include "debug/debug.h" +#include "mm/slab.h" +typedef void (*kthread_func)(void); + +extern void kthread_init(); +extern void kthread_idle(); +extern void kthread_test(); +extern uint64_t kthread_create(kthread_func func); +extern void kthread_exit(); +extern void kthread_destroy(struct task_struct*); +extern void kthread_start(kthread_func); +extern void kthread_int(); + +#endif diff --git a/lab7/include/kernel/sched/sched.h b/lab7/include/kernel/sched/sched.h new file mode 100644 index 000000000..64535a345 --- /dev/null +++ b/lab7/include/kernel/sched/sched.h @@ -0,0 +1,168 @@ +#ifndef _SCHED_H_ +#define _SCHED_H_ +#include "mm/mmu.h" +#include "lib/list.h" +#include "kernel/irq_handler.h" +#include "kernel/signal.h" +#include "fs/vfs.h" + +typedef uint64_t pid_t; + + +#define TASK_RUNNING 0 +#define TASK_INTERRUPTIBLE 1 +#define TASK_UNINTERRUPTIBLE 2 +#define TASK_DEAD 64 +#define VMA_STACK (1 << 0) +#define VMA_FILE (1 << 1) +#define VMA_VC_RAM (2 << 1) +#define VMA_ANONYMOUS (3 << 1) + +#define VMA_PROT_READ (1 << 0) +#define VMA_PROT_WRITE (1 << 1) +#define VMA_PROT_EXEC (1 << 2) +#define VMA_SHARED_EXEC (1 << 3) + +#define PROT_NONE 0 +#define PROT_READ (1 << 0) +#define PROT_WRITE (1 << 1) +#define PROT_EXEC (1 << 2) + +#define MAP_ANONYMOUS 0x20 +#define MAP_POPULATE 0x08000 + +#define VMA_CODE_BASE 0 +#define VMA_STACK_END 0xfffffffff000 +#define VMA_STACK_SIZE 0x4000 +#define VMA_VC_BASE 0x3c000000 +#define VMA_VC_END 0x3f000000 + +#define get_trap_frame(task) (task->stack + PAGE_SIZE * 2 - sizeof(struct trap_frame)) +struct thread_info{ + pid_t pid; + volatile int64_t state; +}; + +struct sched_info{ + int64_t rticks; // running ticks = user + system ticks + int64_t priority; + int64_t counter; // reset counter -> counter = priority + struct list_head sched_list; +}; + +struct trap_frame{ + uint64_t x0; + uint64_t x1; + uint64_t x2; + uint64_t x3; + uint64_t x4; + uint64_t x5; + uint64_t x6; + uint64_t x7; + uint64_t x8; + uint64_t x9; + uint64_t x10; + uint64_t x11; + uint64_t x12; + uint64_t x13; + uint64_t x14; + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t x29; // fp + uint64_t x30; // lr + uint64_t sp_el0; + uint64_t spsr_el1; + uint64_t elr_el1; +}__attribute__((packed)); + +struct task_ctx{ + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t fp; + uint64_t lr; + uint64_t sp; + uint64_t redzone; +}__attribute__((packed)); + +struct vm_area_struct{ + uint64_t vm_start; + uint64_t vm_end; + uint64_t vm_flags; + uint64_t type; + char* filename; + struct list_head list; +}; + +struct mm_struct{ + struct list_head mmap_list; + pgdval_t* pgd; +}; + +struct task_struct{ + struct task_ctx ctx; + + struct thread_info thread_info; + + struct mm_struct* mm; + + // kernel stack + void* stack; + + // schedule info + struct sched_info sched_info; + + // signal + struct sigpending sigpending; + struct sighand_struct sighandler; + + // fs + struct files_struct *files; + struct fs_struct* fs; + + // relationship + struct task_struct* parent; + struct task_struct* child; + struct list_head siblings; + + // task list + struct list_head list; + + // zombie list + struct list_head zombie; +}; + +extern int need_sched; +extern struct list_head zombies; +extern struct list_head task_list; +extern struct task_struct* user_init; + +extern void add_task_to_rq(struct task_struct *task); +extern struct task_struct* pick_next_task_from_rq(); +extern void schedule(); +extern void switch_to(struct task_struct*, struct task_struct*); +extern struct task_struct* get_current(); +extern pid_t get_pid_counter(void); +extern void preempt_schedule(); +extern void print_rq(void); +extern struct task_struct* find_task_by_pid(uint64_t pid); +#endif diff --git a/lab7/include/kernel/sched/task.h b/lab7/include/kernel/sched/task.h new file mode 100644 index 000000000..dfe57bf63 --- /dev/null +++ b/lab7/include/kernel/sched/task.h @@ -0,0 +1,28 @@ +#ifndef _TASK_H_ +#define _TASK_H_ + +#include "kernel/sched/sched.h" +#include "fs/initrdfs.h" +#include "mm/page_alloc.h" +#include "debug/debug.h" +#include "mm/slab.h" + +extern void task_init(); +extern uint64_t task_dup(); +extern void task_exit(); +extern void task_destroy(struct task_struct*); +extern void run_init_task(char*); +extern struct trap_frame* get_current_trap_frame(); +extern void sys_kill(uint64_t); +extern struct vm_area_struct* create_vma_stack(struct mm_struct*); +extern struct vm_area_struct* create_vma_code(struct mm_struct*, char*); +extern struct mm_struct* mm_struct_create(); +extern void dup_mm_struct(struct mm_struct*, struct mm_struct*); +extern void mm_struct_destroy(struct mm_struct*); +extern void dup_vma_stack(struct mm_struct*, struct mm_struct*); +uint64_t mmap(void*, size_t, int, int, int, int); +extern struct vm_area_struct* create_vma_vc(struct mm_struct*); +extern struct vm_area_struct* find_vma(struct mm_struct*, uint64_t); +extern void* sys_mmap(void*, size_t, int, int, int, int); +extern void dup_fs(struct task_struct*, struct task_struct *); +#endif diff --git a/lab7/include/kernel/shell.h b/lab7/include/kernel/shell.h new file mode 100644 index 000000000..81f8b0988 --- /dev/null +++ b/lab7/include/kernel/shell.h @@ -0,0 +1,19 @@ +#ifndef _SHELL_H_ +#define _SHELL_H_ +#include "types.h" +#include "lib/print.h" +#include "lib/string.h" +#include "lib/simple_malloc.h" +#include "peripherals/mailbox.h" +#include "kernel/reboot.h" +#include "fs/initrdfs.h" +#include "kernel/timer.h" +#include "kernel/irq_handler.h" +#include "mm/slab.h" +#include "kernel/sched/task.h" +#include "kernel/sched/kthread.h" + +void simple_shell(void); + +#define DELIM " \t\n\r" +#endif diff --git a/lab7/include/kernel/signal.h b/lab7/include/kernel/signal.h new file mode 100644 index 000000000..1d4ae3073 --- /dev/null +++ b/lab7/include/kernel/signal.h @@ -0,0 +1,80 @@ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +#include "types.h" +#include "lib/list.h" + +#define SIG_SIGHUP 1 +#define SIG_SIGINT 2 +#define SIG_SIGQUIT 3 +#define SIG_SIGILL 4 +#define SIG_SIGTRAP 5 +#define SIG_SIGABRT 6 +#define SIG_SIGBUS 7 +#define SIG_SIGFPE 8 +#define SIG_SIGKILL 9 +#define SIG_SIGUSR1 10 +#define SIG_SIGSEGV 11 +#define SIG_SIGUSR2 12 +#define SIG_SIGPIPE 13 +#define SIG_SIGALRM 14 +#define SIG_SIGTERM 15 +#define SIG_SIGSTKFLT 16 +#define SIG_SIGCHLD 17 +#define SIG_SIGCONT 18 +#define SIG_SIGSTOP 19 +#define SIG_SIGTSTP 20 +#define SIG_SIGTTIN 21 +#define SIG_SIGTTOU 22 +#define SIG_SIGURG 23 +#define SIG_SIGXCPU 24 +#define SIG_SIGXFSZ 25 +#define SIG_SIGVTALRM 26 +#define SIG_SIGPROF 27 +#define SIG_SIGWINCH 28 +#define SIG_SIGIO 29 +#define SIG_SIGPWR 30 +#define SIG_SIGSYS 31 + +#define SIG_FLAG_KERNEL 1 + +#define SIG_MAX_NUM 32 + +typedef void (*sig_handler)(); + +struct signal_queue{ + struct list_head list; + int32_t signal; +}; + +struct sigpending{ + struct list_head pending; + int32_t cur_signal; +}; + +struct sigaction{ + uint32_t sa_flags; + sig_handler sa_handler; +}; + +struct sighand_struct{ + struct sigaction actions[SIG_MAX_NUM]; +}; + +extern void sigpending_init(struct sigpending*); +extern void default_sighand_init(struct sighand_struct*); +extern int send_signal(uint64_t, int); +extern int register_signal(int, sig_handler); +extern void handle_sigreturn(); +extern void handle_signal(); +extern void sigreturn_frame_save(sig_handler); +extern void sigreturn_frame_restore(); +extern void sys_sigreturn(); +extern void sys_signal(int, sig_handler); +extern int sys_sigkill(uint64_t, int); +extern void sig_default(); +extern void sig_terminate(); +extern void free_sigpendings(struct sigpending*); + + +#endif diff --git a/lab7/include/kernel/signal_inner.h b/lab7/include/kernel/signal_inner.h new file mode 100644 index 000000000..4f9c8c2bd --- /dev/null +++ b/lab7/include/kernel/signal_inner.h @@ -0,0 +1,74 @@ +#ifndef _SIGNAL_INNER_H_ +#define _SIGNAL_INNER_H_ + +#include "kernel/signal.h" +struct sigaction default_actions[SIG_MAX_NUM] = { + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_terminate}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_terminate}, // 9 + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_terminate}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default}, + {SIG_FLAG_KERNEL, sig_default} +}; + +char* sig_to_str[SIG_MAX_NUM] = { + "SIGUNKOWN", + "SIGHUP", + "SIGINT", + "SIGQUIT", + "SIGILL", + "SIGTRAP", + "SIGABRT", + "SIGBUS", + "SIGFPE", + "SIGKILL", + "SIGUSR1", + "SIGSEGV", + "SIGUSR2", + "SIGPIPE", + "SIGALRM", + "SIGTERM", + "SIGSTKFLT", + "SIGCHLD", + "SIGCONT", + "SIGSTOP", + "SIGTSTP", + "SIGTTIN", + "SIGTTOU", + "SIGURG", + "SIGXCPU", + "SIGXFSZ", + "SIGVTALRM", + "SIGPROF", + "SIGWINCH", + "SIGIO", + "SIGPWR", + "SIGSYS" +}; +#endif diff --git a/lab7/include/kernel/syscall.h b/lab7/include/kernel/syscall.h new file mode 100644 index 000000000..bd48b9db0 --- /dev/null +++ b/lab7/include/kernel/syscall.h @@ -0,0 +1,19 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ +#include "types.h" +#include "kernel/signal.h" +#include "fs/fs.h" +extern uint64_t sys_hello(uint64_t); +extern size_t sys_uart_write(char *, size_t); +extern size_t sys_uart_read(char *, size_t); +extern uint64_t sys_fork(); +extern uint64_t sys_getpid(); +extern int sys_mbox_call(uint8_t, uint32_t *); +extern void sys_exit(); +extern void sys_kill(uint64_t pid); +extern int sys_exec(const char *, char *const []); +extern void sys_sigreturn(); +extern void sys_signal(int, sig_handler); +extern int sys_sigkill(uint64_t, int); +extern void* sys_mmap(void*, size_t, int, int, int, int); +#endif diff --git a/lab7/include/kernel/syscall_table.h b/lab7/include/kernel/syscall_table.h new file mode 100644 index 000000000..cb853be3a --- /dev/null +++ b/lab7/include/kernel/syscall_table.h @@ -0,0 +1,6 @@ +#ifndef _SYSCALL_TABLE_H_ +#define _SYSCALL_TABLE_H_ + +#include "kernel/syscall.h" +#include "kernel/sched/sched.h" +#endif diff --git a/lab7/include/kernel/timer.h b/lab7/include/kernel/timer.h new file mode 100644 index 000000000..a07d425c9 --- /dev/null +++ b/lab7/include/kernel/timer.h @@ -0,0 +1,32 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ +#include "types.h" +#include "lib/list.h" +#include "lib/simple_malloc.h" +#include "peripherals/iomapping.h" +#include "debug/debug.h" +#include "asm.h" +#include "kernel/sched/sched.h" + + +#define HZ 100 + +typedef void (*timer_callback)(void*); + +typedef struct{ + uint64_t ticks; + timer_callback callback; + void *data; + struct list_head list; +}timer_t; + +extern void core_timer_irq_handler(); +extern void init_core_timer(); +extern uint64_t get_jiffies(); +extern void enable_core_timer_irq(); +extern void disable_core_timer_irq(); +extern void init_timer_list(); +extern void add_timer(timer_callback, uint8_t*, uint64_t); +extern void timer_softirq_callback(); + +#endif diff --git a/lab7/include/lib/bitops.h b/lab7/include/lib/bitops.h new file mode 100644 index 000000000..1a22a6136 --- /dev/null +++ b/lab7/include/lib/bitops.h @@ -0,0 +1,8 @@ +#ifndef _BITOPS_H_ +#define _BITOPS_H_ + +#include "types.h" +extern uint16_t ffs16(uint16_t); +extern uint64_t ffs64(uint64_t); + +#endif diff --git a/lab7/include/lib/cpio.h b/lab7/include/lib/cpio.h new file mode 100644 index 000000000..9e9eaf129 --- /dev/null +++ b/lab7/include/lib/cpio.h @@ -0,0 +1,66 @@ +#ifndef _CPIO_H_ +#define _CPIO_H_ + +#include "types.h" +#include "lib/list.h" +#include "lib/fdt_parse.h" +#include "lib/string.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "debug/debug.h" + +#define FILE_TYPE_MASK 0170000 +#define FILE_TYPE_SOCKET 0140000 +#define FILE_TYPE_SYMLINK 0120000 +#define FILE_TYPE_REGULAR 0100000 +#define FILE_TYPE_BLKDEV 0060000 +#define FILE_TYPE_DIR 0040000 +#define FILE_TYPE_CHRDEV 0020000 +#define FILE_TYPE_NAMED_PIPE 0010000 +#define FILE_SUID 0004000 +#define FILE_SGID 0002000 +#define FILE_STICKY 0001000 +#define FILE_PERMISSION_MASK 0000777 + +struct cpio_iter{ + uint8_t *cur; +}; +struct cpio_newc_header { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} __attribute((packed)); + +struct fentry { + uint32_t ino; + uint32_t mode; + uint32_t uid; + uint32_t gid; + uint32_t nlink; + uint32_t mtime; + uint32_t filesize; + uint32_t devmajor; + uint32_t devminor; + uint32_t rdevmajor; + uint32_t rdevminor; + uint32_t namesize; + uint32_t check; + char *filename; + uint8_t *data; + struct list_head list; +}; +void cpio_iter_parse(struct cpio_iter*, struct fentry*); +extern void cpio_iter_init(struct cpio_iter*, void*); +extern int cpio_is_tailer(struct fentry*); +#endif diff --git a/lab7/include/lib/fdt_parse.h b/lab7/include/lib/fdt_parse.h new file mode 100644 index 000000000..22616d335 --- /dev/null +++ b/lab7/include/lib/fdt_parse.h @@ -0,0 +1,48 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "lib/string.h" +#include "mm/mmu.h" + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +typedef void (*fdt_rsvmap_callback)(uint64_t, uint64_t); +extern void fdt_parse_header(uint8_t*, fdt_header*); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parse_rsvmap(uint8_t*, fdt_rsvmap_callback); +#endif diff --git a/lab7/include/lib/list.h b/lab7/include/lib/list.h new file mode 100644 index 000000000..f102aef06 --- /dev/null +++ b/lab7/include/lib/list.h @@ -0,0 +1,25 @@ +#ifndef _LIST_H_ +#define _LIST_H_ + +#include "types.h" +struct list_head{ + struct list_head* next, *prev; +}; + +#define LIST_HEAD(head) struct list_head head = { &(head), &(head) } +#define list_entry(node, type, member) container_of(node, type, member) +#define list_first_entry(head, type, member) list_entry((head)->next, type, member) +#define list_last_entry(head, type, member) list_entry((head)->prev, type, member) +#define list_for_each(node, head) \ + for(node = (head)->next ; node != (head) ; node = node->next) + +extern void INIT_LIST_HEAD(struct list_head*); +extern void list_add(struct list_head* node, struct list_head*); +extern void list_add_tail(struct list_head*, struct list_head*); +extern void list_del(struct list_head*); +extern int list_empty(struct list_head*); +extern int list_is_last(struct list_head*, struct list_head*); +extern int list_is_head(struct list_head*, struct list_head*); +extern void list_splice(struct list_head*, struct list_head*); +extern void list_splice_tail(struct list_head*, struct list_head*); +#endif diff --git a/lab7/include/lib/print.h b/lab7/include/lib/print.h new file mode 100644 index 000000000..7752c069c --- /dev/null +++ b/lab7/include/lib/print.h @@ -0,0 +1,21 @@ +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#include "types.h" +#include "kernel/timer.h" +#include "lib/string.h" +#include "peripherals/mini_uart.h" +#include "kernel/irq_handler.h" +#include + +extern int32_t printf(char *, ...); +extern int32_t putchar(uint8_t); +extern int32_t getchar(); + +#define INFO(fmt, ...) \ + do{ \ + printf("%l: [%s] " fmt "\r\n" , (int64_t)get_jiffies(), __FUNCTION__, ##__VA_ARGS__); \ + }while(0) + + +#endif diff --git a/lab7/include/lib/ring_buffer.h b/lab7/include/lib/ring_buffer.h new file mode 100644 index 000000000..282b61b53 --- /dev/null +++ b/lab7/include/lib/ring_buffer.h @@ -0,0 +1,27 @@ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ +#include "types.h" +#include "lib/simple_malloc.h" +#include "mm/slab.h" + +typedef struct{ + size_t size; + uint64_t head; + uint64_t tail; + uint8_t* buf; + size_t count; +}ring_buffer; + +extern ring_buffer* create_simple_ring_buf(size_t); + +extern ring_buffer* create_ring_buf(size_t); +extern void free_ring_buf(ring_buffer*); +extern size_t ring_buf_write(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_write_unsafe(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read_unsafe(ring_buffer*, uint8_t*, size_t); +extern uint8_t ring_buf_is_full(ring_buffer*); +extern uint8_t ring_buf_is_empty(ring_buffer*); +extern size_t ring_buf_get_len(ring_buffer*); + +#endif diff --git a/lab7/include/lib/simple_malloc.h b/lab7/include/lib/simple_malloc.h new file mode 100644 index 000000000..8f8c0f4dc --- /dev/null +++ b/lab7/include/lib/simple_malloc.h @@ -0,0 +1,15 @@ +#ifndef _SIMPLE_MALLOC_H_ +#define _SIMPLE_MALLOC_H_ + +#include "types.h" +#include "debug/debug.h" + +#define req2size(req) ALIGN_UP(req, 16) + +struct malloc_state{ + uint8_t* last_remainder; +}; + +extern void* simple_malloc(size_t); +extern void* simple_malloc_get_remainder(); +#endif diff --git a/lab7/include/lib/string.h b/lab7/include/lib/string.h new file mode 100644 index 000000000..4a6a30cd7 --- /dev/null +++ b/lab7/include/lib/string.h @@ -0,0 +1,19 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#include "types.h" + +extern char * itoa(int32_t, char*, uint32_t); +extern char * utoa(uint32_t, char*, uint32_t); +extern char * ltoa(int64_t, char*, uint32_t); +extern char * ultoa(uint64_t, char*, uint32_t); +extern int32_t strcmp(char*, char*); +extern char *strcpy(char *, const char *); +extern size_t strlen(const char*); +extern void* memcpy(void*, const void*, size_t); +extern void* memset(void*, int, size_t); +extern int32_t memcmp(void*, const void*, size_t); +extern uint8_t hex2dec(char); +extern char* strtok(char*,const char*); +extern uint64_t atoul(const char*); +#endif diff --git a/lab7/include/mm/mm.h b/lab7/include/mm/mm.h new file mode 100644 index 000000000..0e3454127 --- /dev/null +++ b/lab7/include/mm/mm.h @@ -0,0 +1,36 @@ +#ifndef _MM_H_ +#define _MM_H_ + +#include "types.h" +#include "lib/fdt_parse.h" +#include "lib/print.h" +#include "lib/simple_malloc.h" +#include "lib/list.h" +#include "lib/string.h" +#include "mm/page_alloc.h" +#include "mm/slab.h" +#include "mm/mmu.h" + + +struct mem_block{ + uint64_t start; + uint64_t end; + struct list_head list; +}; + +struct mem_node{ + uint64_t start; + uint64_t end; + char *name; + struct list_head list; +}; + +extern struct list_head mem_rsvmap; +extern struct list_head mem_unusedmap; +extern struct mem_node memory_node; +extern struct page *mem_map; + +extern void mm_init(void *); + + +#endif diff --git a/lab7/include/mm/mmu.h b/lab7/include/mm/mmu.h new file mode 100644 index 000000000..58855ea95 --- /dev/null +++ b/lab7/include/mm/mmu.h @@ -0,0 +1,65 @@ +#ifndef _MMU_H_ +#define _MMU_H_ +#include "mm/pgtable.h" +#include "types.h" +#include "asm.h" + +typedef uint64_t pgdval_t; +typedef uint64_t pudval_t; +typedef uint64_t pmdval_t; +typedef uint64_t pteval_t; + +#define UPPER_ADDR_SPACE_BASE ((uint64_t)0xFFFF000000000000) +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1ul << PAGE_SHIFT) + + +#define pgd_index(addr) (((uint64_t)addr >> PGD_SHIFT) & 0b111111111) +#define pgd_offset(pgd, addr) ((pgdval_t*)pgd + pgd_index(addr)) +#define pgd_none(val) (val == 0) +#define pgd_set(pgd, val) do{*((pgdval_t*)pgd) = val;}while(0) + +#define pud_index(addr) (((uint64_t)addr >> PUD_SHIFT) & 0b111111111) +#define pud_offset(pgd_e, addr) ((pudval_t*)phys_to_virt(((uint64_t)*pgd_e & PHYS_ADDR_MASK)) + pud_index(addr)) +#define pud_none(val) (val == 0) +#define pud_set(pud, val) do{*((pudval_t*)pud) = val;}while(0) + +#define pmd_index(addr) (((uint64_t)addr >> PMD_SHIFT) & 0b111111111) +#define pmd_offset(pud_e, addr) ((pmdval_t*)phys_to_virt(((uint64_t)*pud_e & PHYS_ADDR_MASK)) + pmd_index(addr)) +#define pmd_none(val) (val == 0) +#define pmd_set(pmd, val) do{*((pmdval_t*)pmd) = val;}while(0) + +#define pte_index(addr) (((uint64_t)addr >> PTE_SHIFT) & 0b111111111) +#define pte_offset(pmd_e, addr) ((pteval_t*)phys_to_virt(((uint64_t)*pmd_e & PHYS_ADDR_MASK)) + pte_index(addr)) +#define pte_val(pte_e) (*pte_e) +#define pte_none(val) (val == 0) +#define pte_set(pte, val) do{*((pteval_t*)pte) = val;}while(0) +#define pte_page(pte_e) ((struct page*)phys_to_page(((uint64_t)*pte_e & PHYS_ADDR_MASK))) +#define pte_reuse(pte_e) do{ \ + uint64_t daif = local_irq_disable_save(); \ + struct page* page = phys_to_page(((uint64_t)*pte_e & PHYS_ADDR_MASK)); \ + page->ref_cnt++; \ + local_irq_restore(daif); \ + }while(0) + +#define pte_inuse(pte_e) (((struct page*)phys_to_page(((uint64_t)*pte_e & PHYS_ADDR_MASK)))->ref_cnt != 0) +#define pte_writable(pte_e) (((uint64_t)*pte_e & PAGE_ATTR_RDONLY) == 0) +#define pte_ref_cnt(pte_e) (((struct page*)phys_to_page(((uint64_t)*pte_e & PHYS_ADDR_MASK)))->ref_cnt) + +#define VM_FAULT_NONE 0 +#define VM_FAULT_BADMAP 1 +#define VM_FAULT_BADACCESS 2 + +#define VM_USER_SPACE 0xffffffffffff + +extern void page_init(); +extern void mappages(pgdval_t*, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); +extern void dup_pages(pgdval_t*, pgdval_t*, uint64_t, uint64_t, uint64_t); +extern void free_page_table(pgdval_t*); +extern void free_one_pgd(pgdval_t*); +extern void free_one_pud(pudval_t*); +extern void free_one_pmd(pmdval_t*); +extern void free_one_pte(pteval_t*); +extern void do_mem_abort(uint64_t, uint64_t); +extern pteval_t* get_pte(pgdval_t*, uint64_t); +#endif diff --git a/lab7/include/mm/page_alloc.h b/lab7/include/mm/page_alloc.h new file mode 100644 index 000000000..1f59adf59 --- /dev/null +++ b/lab7/include/mm/page_alloc.h @@ -0,0 +1,65 @@ +#ifndef _PAGE_ALLOC_H_ +#define _PAGE_ALLOC_H_ + +#include "types.h" +#include "lib/list.h" +#include "lib/print.h" +#include "lib/bitops.h" +#include "mm/mm.h" + +#define BUDDY_GROUP_MEMBER 0x80000000 +#define BUDDY_ALLOCATED 0x40000000 +#define BUDDY_MAX_ORDER 7 + +#define PAGE_TYPE_RESERVED 1 + +#define BUDDY_IS_ALLOCATED(x) (((struct page*)x)->order & BUDDY_ALLOCATED) +#define BUDDY_IS_MEMBER(x) (((struct page*)x)->order & BUDDY_GROUP_MEMBER) +#define BUDDY_IS_FREED(x) (!BUDDY_IS_ALLOCATED(x)) +#define PAGE_IS_RESERVED(x) (((struct page*)x)->type & PAGE_TYPE_RESERVED) +#define _buddy_ffs(x) ((x) == 0 ? BUDDY_MAX_ORDER : ffs64(x)) +#define find_buddy_pfn(pfn, order) (pfn ^ (1 << order)) +#define get_page_order(p) (p->order & 0xffff) +#define get_buddy_leader(p) (p->buddy_leader) + +#define virt_to_pfn(addr) ((uint64_t)(((uint64_t)addr) - UPPER_ADDR_SPACE_BASE) >> PAGE_SHIFT) +#define pfn_to_virt(n) ((void*)((n << PAGE_SHIFT) + UPPER_ADDR_SPACE_BASE)) +#define page_to_pfn(x) ((uint64_t)((struct page*)x - mem_map)) +#define pfn_to_page(x) ((struct page*)&mem_map[(uint64_t)x]) +#define page_to_virt(x) (pfn_to_virt(page_to_pfn(x))) +#define page_to_phys(x) (page_to_pfn(x) << PAGE_SHIFT) +#define virt_to_page(x) (pfn_to_page(virt_to_pfn(x))) +#define virt_to_phys(addr) (((uint64_t)addr) - UPPER_ADDR_SPACE_BASE) +#define phys_to_virt(addr) (((uint64_t)addr) + UPPER_ADDR_SPACE_BASE) +#define phys_to_page(addr) (pfn_to_page((uint64_t)addr >> PAGE_SHIFT)) + +struct page{ +// if (order & BUDDY_MEMBER), then it is freed and it is not a buddy leader +// if (order & BUDDY_ALLOCATED), then it is allocated + void* buddy_leader; + uint32_t order; + uint32_t type; + struct list_head list; + size_t ref_cnt; +}; + +struct free_list{ + size_t count; + struct list_head list; +}; + +struct buddy_system{ + struct free_list free_lists[BUDDY_MAX_ORDER]; +}; + +extern void buddy_init(); +extern void* alloc_page(); +extern void* calloc_page(); +extern void* alloc_pages(uint32_t); +extern void free_pages(void*, uint32_t); +extern void free_page(void*); +extern void debug_buddy(); +extern void print_buddy_statistics(); + +#endif + diff --git a/lab7/include/mm/pgtable.h b/lab7/include/mm/pgtable.h new file mode 100644 index 000000000..2ce4227f6 --- /dev/null +++ b/lab7/include/mm/pgtable.h @@ -0,0 +1,72 @@ +#ifndef _PGTABLE_H_ +#define _PGTABLE_H_ + +#define PGD_SHIFT (39) +#define PGD_TYPE_MASK (3 << 0) +#define PGD_TYPE_TABLE (3 << 0) +#define PGD_TABLE_BIT (1 << 1) +#define PGD_TYPE_BLOCK (1 << 0) + +#define PUD_SHIFT (30) +#define PUD_TYPE_MASK (3 << 0) +#define PUD_TYPE_TABLE (3 << 0) +#define PUD_TABLE_BIT (1 << 1) +#define PUD_TYPE_BLOCK (1 << 0) + +#define PMD_SHIFT (21) +#define PMD_TYPE_MASK (3 << 0) +#define PMD_TYPE_TABLE (3 << 0) +#define PMD_TABLE_BIT (1 << 1) +#define PMD_TYPE_BLOCK (1 << 0) + +#define PTE_SHIFT (12) +#define PTE_TYPE_MASK (3 << 0) +#define PTE_TYPE_FAULT (0 << 0) +#define PTE_TYPE_PAGE (3 << 0) +#define PTE_TABLE_BIT (1 << 1) + +#define PAGE_MAIR_SHIFT (2) +#define PAGE_ATTR_USER (1 << 6) +#define PAGE_ATTR_RDONLY (1 << 7) +#define PAGE_ATTR_SHARED (3 << 8) +#define PAGE_ATTR_AF (1 << 10) +#define PAGE_ATTR_NG (1 << 11) +#define PAGE_ATTR_DBM (1ul << 51) +#define PAGE_ATTR_CONT (1ul << 52) +#define PAGE_ATTR_PXN (1ul << 53) +#define PAGE_ATTR_UXN (1ul << 54) +#define PAGE_ATTR_DIRTY (1ul << 55) // Hardware doesn't support dirty bit. + +#define BLOCK_MAIR_SHIFT (2) +#define BLOCK_ATTR_USER (1 << 6) +#define BLOCK_ATTR_RDONLY (1 << 7) +#define BLOCK_ATTR_SHARED (3 << 8) +#define BLOCK_ATTR_AF (1 << 10) +#define BLOCK_ATTR_NG (1 << 11) +#define BLOCK_ATTR_DBM (1ul << 51) +#define BLOCK_ATTR_CONT (1ul << 52) +#define BLOCK_ATTR_PXN (1ul << 53) +#define BLOCK_ATTR_UXN (1ul << 54) + +#define PHYS_ADDR_MASK (0xfffffffff000) + +#define TCR_CONFIG_REGION_48bit (((64 - 48) << 0) | ((64 - 48) << 16)) +#define TCR_CONFIG_4KB ((0b00 << 14) | (0b10 << 30)) +#define TCR_CONFIG_DEFAULT (TCR_CONFIG_REGION_48bit | TCR_CONFIG_4KB) + +#define MAIR_DEVICE_nGnRnE 0b00000000 +#define MAIR_NORMAL_NOCACHE 0b01000100 +#define MAIR_IDX_DEVICE_nGnRnE 0 +#define MAIR_IDX_NORMAL_NOCACHE 1 + +#define BOOT_PGD_ATTR (PGD_TYPE_TABLE) +#define BOOT_PUD_ATTR (PUD_TYPE_BLOCK | BLOCK_ATTR_AF | (MAIR_IDX_DEVICE_nGnRnE << BLOCK_MAIR_SHIFT)) + +#define VM_PGD_ATTR (PGD_TYPE_TABLE) +#define VM_PUD_ATTR (PUD_TYPE_TABLE) +#define VM_PMD_ATTR (PMD_TYPE_TABLE) +#define VM_PTE_DEVICE_ATTR (PTE_TYPE_PAGE | PAGE_ATTR_AF | (MAIR_IDX_DEVICE_nGnRnE << PAGE_MAIR_SHIFT)) +#define VM_PTE_NORMAL_ATTR (PTE_TYPE_PAGE | PAGE_ATTR_AF | (MAIR_IDX_NORMAL_NOCACHE << PAGE_MAIR_SHIFT)) + +#define VM_PTE_USER_ATTR (PTE_TYPE_PAGE | PAGE_ATTR_AF | PAGE_ATTR_USER | (MAIR_IDX_NORMAL_NOCACHE << PAGE_MAIR_SHIFT)) +#endif diff --git a/lab7/include/mm/slab.h b/lab7/include/mm/slab.h new file mode 100644 index 000000000..0558c471e --- /dev/null +++ b/lab7/include/mm/slab.h @@ -0,0 +1,37 @@ +#ifndef _SLAB_H_ +#define _SLAB_H_ + +#include "mm/mm.h" +#include "mm/page_alloc.h" +#include "lib/list.h" +#include "lib/string.h" +#include "debug/debug.h" + +struct slab{ + size_t size; // object size + void* s_mem; // pointe to the first object + int64_t inuse; + struct list_head free_list; // free list + struct list_head list; // next slab +}; + +#define SLAB_ALIGNMENT (ALIGN_UP(sizeof(struct list_head), 0x20)) +#define SLAB_SIZE (ALIGN_UP(sizeof(struct slab), SLAB_ALIGNMENT)) +#define SLAB_MAX_OBJECT_SIZE (PAGE_SIZE * (1 << (BUDDY_MAX_ORDER - 1)) - SLAB_SIZE) + +#define KMEM_MIN_SIZE SLAB_ALIGNMENT +#define KMEM_ALIGNMENT SLAB_ALIGNMENT +#define KMEM_CACHE_NUM (SLAB_MAX_OBJECT_SIZE / KMEM_ALIGNMENT + 1) + +extern struct slab* slab_create(size_t); +extern void slab_destroy(struct slab*); +extern void *slab_alloc(struct slab*); +extern void slab_free(struct slab* , void*); + +extern void* kmalloc(size_t); +extern void kfree(void*); +extern void kmalloc_init(); + +extern void debug_kmalloc(); +extern void debug_slab(); +#endif diff --git a/lab7/include/peripherals/iomapping.h b/lab7/include/peripherals/iomapping.h new file mode 100644 index 000000000..91c4aec1b --- /dev/null +++ b/lab7/include/peripherals/iomapping.h @@ -0,0 +1,102 @@ +#ifndef _IOMAPPING_H_ +#define _IOMAPPING_H_ + +#include "mm/mmu.h" + +/* Physical addresses range from 0x3F000000 to 0x3FFFFFFF for peripherals */ +#define IO_BASE (0x3F000000 + UPPER_ADDR_SPACE_BASE) + +/* Register's offset of GPIO */ +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL0 (IO_BASE + 0x200000) +#define GPFSEL1 (IO_BASE + 0x200004) +#define GPFSEL2 (IO_BASE + 0x200008) +#define GPFSEL3 (IO_BASE + 0x20000C) +#define GPFSEL4 (IO_BASE + 0x200010) +#define GPFSEL5 (IO_BASE + 0x200014) +#define GPSET0 (IO_BASE + 0x20001C) +#define GPSET1 (IO_BASE + 0x200020) +#define GPCLR0 (IO_BASE + 0x200028) +#define GPCLR1 (IO_BASE + 0x20002C) +#define GPLEV0 (IO_BASE + 0x200034) +#define GPLEV1 (IO_BASE + 0x200038) +#define GPEDS0 (IO_BASE + 0x200040) +#define GPEDS1 (IO_BASE + 0x200044) +#define GPREN0 (IO_BASE + 0x20004C) +#define GPREN1 (IO_BASE + 0x200050) +#define GPFEN0 (IO_BASE + 0x200058) +#define GPFEN1 (IO_BASE + 0x20005C) +#define GPHEN0 (IO_BASE + 0x200064) +#define GPHEN1 (IO_BASE + 0x200068) +#define GPLEN0 (IO_BASE + 0x200070) +#define GPLEN1 (IO_BASE + 0x200074) +#define GPAREN0 (IO_BASE + 0x20007C) +#define GPAREN1 (IO_BASE + 0x200080) +#define GPAFEN0 (IO_BASE + 0x200088) +#define GPAFEN1 (IO_BASE + 0x20008C) +#define GPPUD (IO_BASE + 0x200094) +#define GPPUDCLK0 (IO_BASE + 0x200098) +#define GPPUDCLK1 (IO_BASE + 0x20009C) + + +/* Register's offset of UART and SPI */ +#define AUX_IRQ (IO_BASE + 0x215000) +#define AUX_ENABLES (IO_BASE + 0x215004) +#define AUX_MU_IO_REG (IO_BASE + 0x215040) +#define AUX_MU_IER_REG (IO_BASE + 0x215044) +#define AUX_MU_IIR_REG (IO_BASE + 0x215048) +#define AUX_MU_LCR_REG (IO_BASE + 0x21504C) +#define AUX_MU_MCR_REG (IO_BASE + 0x215050) +#define AUX_MU_LSR_REG (IO_BASE + 0x215054) +#define AUX_MU_MSR_REG (IO_BASE + 0x215058) +#define AUX_MU_SCRATCH (IO_BASE + 0x21505C) +#define AUX_MU_CNTL_REG (IO_BASE + 0x215060) +#define AUX_MU_STAT_REG (IO_BASE + 0x215064) +#define AUX_MU_BAUD_REG (IO_BASE + 0x215068) +#define AUX_SPI0_CNTL0_REG (IO_BASE + 0x215080) +#define AUX_SPI0_CNTL1_REG (IO_BASE + 0x215084) +#define AUX_SPI0_STAT_REG (IO_BASE + 0x215088) +#define AUX_SPI0_IO_REG (IO_BASE + 0x215090) +#define AUX_SPI0_PEEK_REG (IO_BASE + 0x215094) +#define AUX_SPI1_CNTL0_REG (IO_BASE + 0x2150C0) +#define AUX_SPI1_CNTL1_REG (IO_BASE + 0x2150C4) +#define AUX_SPI1_STAT_REG (IO_BASE + 0x2150C8) +#define AUX_SPI1_IO_REG (IO_BASE + 0x2150D0) +#define AUX_SPI1_PEEK_REG (IO_BASE + 0x2150D4) + +// mailbox register base address +#define MBOX_REG (IO_BASE + 0xB880) + +// interrupt +#define IRQ_BASIC_PENDING (IO_BASE + 0xB200) +#define IRQ_PENDING_1 (IO_BASE + 0xB204) +#define IRQ_PENDING_2 (IO_BASE + 0xB208) +#define CORE0_IRQ_SOURCE (IO_BASE + 0x1000060) +#define CORE1_IRQ_SOURCE (IO_BASE + 0x1000064) +#define CORE2_IRQ_SOURCE (IO_BASE + 0x1000068) +#define CORE3_IRQ_SOURCE (IO_BASE + 0x100006C) +#define CORE0_FIQ_SOURCE (IO_BASE + 0x1000070) +#define CORE1_FIQ_SOURCE (IO_BASE + 0x1000074) +#define CORE2_FIQ_SOURCE (IO_BASE + 0x1000078) +#define CORE3_FIQ_SOURCE (IO_BASE + 0x100007C) +#define ENABLE_IRQS_1 (IO_BASE + 0xB210) + + +// timer +#define CORE0_TIMER_IRQ_CTRL (IO_BASE + 0x1000040) + + +// watch dog +#define PM_PASSWORD (IO_BASE + 0x1b000000) +#define PM_RSTC (IO_BASE + 0x10001c) +#define PM_WDOG (IO_BASE + 0x100024) + +#define IO_MMIO_write32(addr, val) *(uint32_t*)addr = val +#define IO_MMIO_read32(addr) *(uint32_t*)addr +#define IO_MMIO_write64(addr, val) *(uint64_t*)addr = val +#define IO_MMIO_read64(addr) *(uint64_t*)addr + + + +#endif + diff --git a/lab7/include/peripherals/mailbox.h b/lab7/include/peripherals/mailbox.h new file mode 100644 index 000000000..736fb6fe6 --- /dev/null +++ b/lab7/include/peripherals/mailbox.h @@ -0,0 +1,181 @@ +#ifndef _MAILBOX_H_ +#define _MAILBOX_H_ + +#include "types.h" +#include "lib/string.h" +#include "debug/debug.h" +#include "peripherals/iomapping.h" +#include "kernel/sched/sched.h" +#include "mm/mm.h" + +#define MBOX_REQUEST 0 +#define MBOX_CH_PROP 8 +#define MBOX_TAG_LAST 0 + +#define MBOX_CHANNEL_POWER 0 +#define MBOX_CHANNEL_FRAME_BUF 1 +#define MBOX_CHANNEL_VIRTUAL_UART 2 +#define MBOX_CHANNEL_VCHIQ 3 +#define MBOX_CHANNEL_LEDS 4 +#define MBOX_CHANNEL_BUTTONS 5 +#define MBOX_CHANNEL_TOUCH_SCREEN 6 +#define MBOX_CHANNEL_UNKOWN 7 +#define MBOX_CHANNEL_PROPERTY_TAGS 8 + +enum MBOX_PROPERTY_STATUS { + MBOX_STATUS_REQUEST = 0, + MBOX_STATUS_SUCCESS = 0x80000000, + MBOX_STATUS_ERROR = 0x80000001, +}; + +enum MBOX_PROPERTY_TAG{ + MBOX_PROPERTY_END = 0, + MBOX_GET_FIRMWARE_REVISION = 0x00000001, + + MBOX_SET_CURSOR_INFO = 0x00008010, + MBOX_SET_CURSOR_STATE = 0x00008011, + + MBOX_GET_BOARD_MODEL = 0x00010001, + MBOX_GET_BOARD_REVISION = 0x00010002, + MBOX_GET_BOARD_MAC_ADDRESS = 0x00010003, + MBOX_GET_BOARD_SERIAL = 0x00010004, + MBOX_GET_ARM_MEMORY = 0x00010005, + MBOX_GET_VC_MEMORY = 0x00010006, + MBOX_GET_CLOCKS = 0x00010007, + MBOX_GET_POWER_STATE = 0x00020001, + MBOX_GET_TIMING = 0x00020002, + MBOX_SET_POWER_STATE = 0x00028001, + MBOX_GET_CLOCK_STATE = 0x00030001, + MBOX_GET_CLOCK_RATE = 0x00030002, + MBOX_GET_VOLTAGE = 0x00030003, + MBOX_GET_MAX_CLOCK_RATE = 0x00030004, + MBOX_GET_MAX_VOLTAGE = 0x00030005, + MBOX_GET_TEMPERATURE = 0x00030006, + MBOX_GET_MIN_CLOCK_RATE = 0x00030007, + MBOX_GET_MIN_VOLTAGE = 0x00030008, + MBOX_GET_TURBO = 0x00030009, + MBOX_GET_MAX_TEMPERATURE = 0x0003000a, + MBOX_GET_STC = 0x0003000b, + MBOX_ALLOCATE_MEMORY = 0x0003000c, + MBOX_LOCK_MEMORY = 0x0003000d, + MBOX_UNLOCK_MEMORY = 0x0003000e, + MBOX_RELEASE_MEMORY = 0x0003000f, + MBOX_EXECUTE_CODE = 0x00030010, + MBOX_EXECUTE_QPU = 0x00030011, + MBOX_SET_ENABLE_QPU = 0x00030012, + MBOX_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, + MBOX_GET_EDID_BLOCK = 0x00030020, + MBOX_GET_CUSTOMER_OTP = 0x00030021, + MBOX_GET_DOMAIN_STATE = 0x00030030, + MBOX_SET_CLOCK_STATE = 0x00038001, + MBOX_SET_CLOCK_RATE = 0x00038002, + MBOX_SET_VOLTAGE = 0x00038003, + MBOX_SET_TURBO = 0x00038009, + MBOX_SET_CUSTOMER_OTP = 0x00038021, + MBOX_SET_DOMAIN_STATE = 0x00038030, + MBOX_GET_GPIO_STATE = 0x00030041, + MBOX_SET_GPIO_STATE = 0x00038041, + MBOX_SET_SDHOST_CLOCK = 0x00038042, + MBOX_GET_GPIO_CONFIG = 0x00030043, + MBOX_SET_GPIO_CONFIG = 0x00038043, + MBOX_GET_PERIPH_REG = 0x00030045, + MBOX_SET_PERIPH_REG = 0x00038045, + + + /* Dispmanx TAGS */ + MBOX_FRAMEBUFFER_ALLOCATE = 0x00040001, + MBOX_FRAMEBUFFER_BLANK = 0x00040002, + MBOX_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, + MBOX_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, + MBOX_FRAMEBUFFER_GET_DEPTH = 0x00040005, + MBOX_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006, + MBOX_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007, + MBOX_FRAMEBUFFER_GET_PITCH = 0x00040008, + MBOX_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, + MBOX_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, + MBOX_FRAMEBUFFER_GET_PALETTE = 0x0004000b, + MBOX_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, + MBOX_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010, + MBOX_FRAMEBUFFER_RELEASE = 0x00048001, + MBOX_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, + MBOX_FRAMEBUFFER_TEST_DEPTH = 0x00044005, + MBOX_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006, + MBOX_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007, + MBOX_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, + MBOX_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, + MBOX_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, + MBOX_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, + MBOX_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, + MBOX_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, + MBOX_FRAMEBUFFER_SET_DEPTH = 0x00048005, + MBOX_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006, + MBOX_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007, + MBOX_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + MBOX_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + MBOX_FRAMEBUFFER_SET_PALETTE = 0x0004800b, + MBOX_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + MBOX_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, + MBOX_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + MBOX_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + + MBOX_VCHIQ_INIT = 0x00048010, + + MBOX_GET_COMMAND_LINE = 0x00050001, + MBOX_GET_DMA_CHANNELS = 0x00060001, +}; +/* + * Mailbox Read/Write Peek Sender Status Config + * 0 0x00 0x10 0x14 0x18 0x1c + * 1 0x20 0x30 0x34 0x38 0x3c + */ + +#define MBOX_READ_CHANNEL_MASK 15 +#define MBOX_WRITE_CHANNEL_MASK 15 +#define MBOX_WRITE_ADDR_MASK (~15) +#define MBOX_READ_ADDR_MASK (~15) +#define MBOX_STATUS_FULL_MASK 0x80000000 +#define MBOX_STATUS_EMPTY_MASK 0x40000000 +typedef struct{ + uint32_t read; + uint32_t unused[5]; + uint32_t status; + uint32_t config; + uint32_t write; +}__attribute__((packed)) MBox_register; + +/* 0 4 8 12 16 20 24 28 32 + +---------------------------------------------------------------+ +0x00 | Buffer Size | + +---------------------------------------------------------------+ +0x04 | Request/Response Code | + +---------------------------------------------------------------+ +0x08 | Tags | +... \\ \\ +0xXX | Tags | + +---------------------------------------------------------------+ +0xXX+4 | End Tag (0) | + +---------------------------------------------------------------+ +0xXX+8 | Padding | +... \\ \\ +0xXX+16| Padding | + +---------------------------------------------------------------+ +*/ +#define MBOX_TAG_REQUEST 0 +typedef struct{ + uint32_t id; + uint32_t value_size; + uint32_t code; + uint8_t values[0]; +}MBox_tag; + +typedef struct{ + uint32_t buf_size; + uint32_t code; + uint8_t buf[0]; +}MBox_buffer; + +extern void MBox_get_board_revision(uint32_t*); +extern void MBox_get_arm_memory(uint32_t*); +extern int Mbox_call(uint32_t*, uint8_t); +#endif diff --git a/lab7/include/peripherals/mini_uart.h b/lab7/include/peripherals/mini_uart.h new file mode 100644 index 000000000..4acaf4af7 --- /dev/null +++ b/lab7/include/peripherals/mini_uart.h @@ -0,0 +1,37 @@ +#ifndef _MINI_UART_H_ +#define _MINI_UART_H_ + +#include "lib/ring_buffer.h" +#include "types.h" +#include "kernel/sched/sched.h" +#include "asm.h" +#include "peripherals/iomapping.h" +#include "debug/debug.h" +#include "lib/print.h" + +#define SYSTEM_CLOCK_RATE (250000000) +#define BAUD_RATE 115200 +#define BAUD_RATE_REG (SYSTEM_CLOCK_RATE / (8 * BAUD_RATE) - 1) +#define TX 1 +#define RX 2 +extern void mini_uart_init(); +extern uint8_t mini_uart_read(void); +extern void mini_uart_write(uint8_t); +extern ssize_t write_bytes(uint8_t *, size_t); +extern void write_str(char *); +extern void write_hex(uint64_t); +extern void delay_cycles(uint64_t); +extern void disable_mini_uart_irq(uint32_t); +extern void enable_mini_uart_irq(uint32_t); +extern void mini_uart_irq_init(); +extern void mini_uart_irq_read(); +extern size_t mini_uart_get_rx_len(); +extern uint8_t mini_uart_aio_read(void); +extern size_t mini_uart_get_tx_len(); +extern void enable_mini_uart_rx_irq(); +extern void disable_mini_uart_rx_irq(); +extern void mini_uart_rx_softirq_callback(); +extern size_t uart_write(char *, size_t); +extern size_t uart_read(char *, size_t); + +#endif diff --git a/lab7/include/types.h b/lab7/include/types.h new file mode 100644 index 000000000..c565b425b --- /dev/null +++ b/lab7/include/types.h @@ -0,0 +1,45 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) (((uint64_t)(val) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_DOWN(val, align) ((uint64_t)(val) & ~((align) - 1)) + +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define min(x, y) ((x) < (y) ? (x) : (y)) + +#endif diff --git a/lab7/init/Makefile b/lab7/init/Makefile new file mode 100644 index 000000000..e5b218aa8 --- /dev/null +++ b/lab7/init/Makefile @@ -0,0 +1,24 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + kernel_init.o + +all: $(OBJECTS) + +%.o: %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab7/init/kernel_init.c b/lab7/init/kernel_init.c new file mode 100644 index 000000000..f7446d051 --- /dev/null +++ b/lab7/init/kernel_init.c @@ -0,0 +1,26 @@ +#include "init/kernel_init.h" + +extern int __heap_start; +void kernel_init(void *dtb){ + mini_uart_init(); + INFO("core timer start initialization..."); + init_core_timer(); + INFO("uart interrupt start initialization..."); + mini_uart_irq_init(); + + local_irq_enable(); + INFO("kernel start initialization..."); + + // memory management initialization + mm_init(dtb); + + // change ttbr1_el1 to 4-level + page_init(); + + // fs initialize + fs_init(); + + fdt_parser(dtb, fdt_initrdfs_callback); + return; +} + diff --git a/lab7/initramfs.cpio b/lab7/initramfs.cpio new file mode 100644 index 000000000..3269cb83a Binary files /dev/null and b/lab7/initramfs.cpio differ diff --git a/lab7/kernel/.gdb_history b/lab7/kernel/.gdb_history new file mode 100644 index 000000000..0e9b7b5ce --- /dev/null +++ b/lab7/kernel/.gdb_history @@ -0,0 +1,25 @@ +file ./../build/kernel8.elf +target remote:1234 +x/gx simple_shell +disassemble simple_shell +b* 0x0000000000081e1c +c +x/i 0x100000 +ni +x/i 0x100000 +b* 0x100008 +ni +quit +file ./../build/kernel8.elf +target remote:1234 +disassemble simple_shell +b* 0x0000000000081e1c +c +ni +x/i 0x1000000 +x/i 0x100000 +b*0x100008 +ni +ni +ni +quit diff --git a/lab7/kernel/Makefile b/lab7/kernel/Makefile new file mode 100644 index 000000000..910d3329b --- /dev/null +++ b/lab7/kernel/Makefile @@ -0,0 +1,42 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin \ + -g +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + shell.o \ + reboot.o \ + main.o \ + start.o \ + entry.o \ + syscall_test.o \ + syscall_table.o \ + timer.o \ + irq_handler.o \ + signal.o \ + fault.o \ + +.PHONY: all sched +all: $(OBJECTS) sched + +sched: + $(MAKE) -C sched OUTPUT=$(OUTPUT) HEADERS=$(HEADERS) CFLAGS="$(CFLAGS)" + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab7/kernel/entry.S b/lab7/kernel/entry.S new file mode 100644 index 000000000..753ab4c5b --- /dev/null +++ b/lab7/kernel/entry.S @@ -0,0 +1,189 @@ + .macro ventry label + .align 7 + b \label + .endm + + + .macro save_all + sub sp, sp, 17 * 16 + stp x0, x1, [sp ,16 * 0] + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + mrs x24, sp_el0 + stp x30, x24, [sp, 16 * 15] + + mrs x24, spsr_el1 + mrs x25, elr_el1 + stp x24, x25, [sp, 16 * 16] + .endm + + .macro load_all + ldp x24, x25, [sp, 16 * 16] + msr spsr_el1, x24 + msr elr_el1, x25 + + ldp x30, x24, [sp, 16 * 15] + msr sp_el0, x24 + + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + + add sp, sp, 17 * 16 + + .endm + +.global task_load_all +task_load_all: + load_all + eret + +.global kthread_trampoline +kthread_trampoline: + bl local_irq_enable + mov x0, x19 + bl kthread_start + +// exception vector table +.align 11 +.global EL1_exception_vector_table +EL1_exception_vector_table: +// Exception from the current EL while using SP_EL0 + ventry invalid_handler // Synchronous EL1t + ventry invalid_handler // IRQ EL1t + ventry invalid_handler // FIQ EL1t + ventry invalid_handler // Error EL1t + +// Exception from the current EL while using SP_ELx + ventry el1_sync_handler // Synchronous EL1h + ventry el1_irq_handler // IRQ EL1h + ventry invalid_handler // FIQ EL1h + ventry invalid_handler // Error EL1h + +// Exception from a lower EL at least one lower EL is AArch64 + ventry el0_sync_handler // Synchronous 64-bit EL0 + ventry el0_irq_handler // IRQ 64-bit EL0 + ventry invalid_handler // FIQ 64-bit EL0 + ventry invalid_handler // Error 64-bit EL0 + +// Exception from a lower EL and all lower ELs are AArch32 + ventry invalid_handler // Synchronous 32-bit EL0 + ventry invalid_handler // IRQ 32-bit EL0 + ventry invalid_handler // FIQ 32-bit EL0 + ventry invalid_handler // Error 32-bit EL0 + +el1_sync_invalid_handler: + mov x0, 135 +invalid_handler: + save_all + mrs x1, esr_el1 + mrs x2, elr_el1 + mrs x3, spsr_el1 + mrs x4, sp_el0 + mov x5, sp + bl err_handler + load_all + eret + + +el0_irq_handler: +el1_irq_handler: + save_all + bl irq_handler + bl schedule + bl handle_signal + load_all + eret + +el1_sync_handler: +el0_sync_handler: + save_all + mrs x24, esr_el1 + lsr x24, x24, #26 + cmp x24, #0x15 + + b.eq svc_handler + + mrs x0, esr_el1 + mrs x1, far_el1 + bl fault_handler + + b end +svc_handler: + bl local_irq_enable + bl syscall_handler + str x0, [sp] + +end: + bl handle_signal + load_all + eret + +.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 sigreturn_trampoline +sigreturn_trampoline: + mov x8, 20 + svc 0 + +sigreturn_error: + b sigreturn_error + +.global switch_ttbr0 +switch_ttbr0: + dsb ish + msr ttbr0_el1, x0 + tlbi vmalle1is + dsb ish + isb + ret + diff --git a/lab7/kernel/fault.c b/lab7/kernel/fault.c new file mode 100644 index 000000000..2f0f932a2 --- /dev/null +++ b/lab7/kernel/fault.c @@ -0,0 +1,11 @@ +#include "kernel/fault.h" + +// far save the address that trigger data abort +void fault_handler(uint64_t esr, uint64_t far){ + uint32_t ec = esr >> 26; // error code + if(ec == FAULT_DATA_ABORT_LOW_EL || ec == FAULT_INSTR_ABORT_LOW_EL || ec == FAULT_INSTR_ABORT || ec == FAULT_DATA_ABORT){ + do_mem_abort(esr, far); + }else{ + INFO("unknown error: ec = %p, far: %p, esr: %p", ec, far, esr); + } +} diff --git a/lab7/kernel/irq_handler.c b/lab7/kernel/irq_handler.c new file mode 100644 index 000000000..80ec9d121 --- /dev/null +++ b/lab7/kernel/irq_handler.c @@ -0,0 +1,190 @@ +#include "kernel/irq_handler.h" +struct softirq_status softirq_s = { + .pending = 0, + .in_softirq = 0 +}; + +irq_funcptr softirq_vec[END_OF_LIST] = { + timer_softirq_callback, + mini_uart_rx_softirq_callback, +}; +uint64_t irq_count[END_OF_LIST] = {0, 0, 0}; + +void enter_softirq(){ + softirq_s.in_softirq = 1; +} + +void exit_softirq(){ + softirq_s.in_softirq = 0; +} + +uint8_t in_softirq(){ + return softirq_s.in_softirq; +} + +uint8_t has_softirq_pending(){ + return softirq_s.pending ? 1 : 0; +} + +uint16_t get_softirq_pending(){ + return softirq_s.pending; +} + +void set_softirq_pending(uint16_t val){ + softirq_s.pending = val; +} + + +void add_softirq_task(uint32_t softirq_nr){ + softirq_s.pending |= (1 << softirq_nr); +} + +void do_softirq(){ + uint16_t try = 0; + volatile uint16_t pending; + uint16_t softirq_bit; + irq_funcptr softirq_handler; + + while(try < MAX_SOFTIRQ_TRY){ + pending = get_softirq_pending(); + set_softirq_pending(0); + + local_irq_enable(); + while(pending){ + softirq_bit = ffs16(pending); + softirq_handler = softirq_vec[softirq_bit]; + softirq_handler(); + pending &= ~(1 << softirq_bit); + } + local_irq_disable(); + try++; + } +} + +void do_irq(uint32_t nr, irq_funcptr do_hardirq,irq_funcptr enable_device_irq , irq_funcptr disable_device_irq){ + disable_device_irq(); + irq_count[nr]++; + add_softirq_task(nr); + do_hardirq(); + + if(!in_softirq() && has_softirq_pending()){ + enter_softirq(); + do_softirq(); + exit_softirq(); + } + + enable_device_irq(); +} + +void irq_handler(){ + uint32_t irq_pending_1 = IO_MMIO_read32(IRQ_PENDING_1); + uint32_t core0_irq_source = IO_MMIO_read32(CORE0_IRQ_SOURCE); + uint32_t auxirq, uart_irq_type; + /* + uint32_t irq_pending_2 = IO_MMIO_read32(IRQ_PENDING_2); + uint32_t irq_basic_pending = IO_MMIO_read32(IRQ_BASIC_PENDING); + uint32_t core1_irq_source = IO_MMIO_read32(CORE1_IRQ_SOURCE); + uint32_t core2_irq_source = IO_MMIO_read32(CORE2_IRQ_SOURCE); + uint32_t core3_irq_source = IO_MMIO_read32(CORE3_IRQ_SOURCE); + uint32_t core0_fiq_source = IO_MMIO_read32(CORE0_FIQ_SOURCE); + uint32_t core1_fiq_source = IO_MMIO_read32(CORE1_FIQ_SOURCE); + uint32_t core2_fiq_source = IO_MMIO_read32(CORE2_FIQ_SOURCE); + uint32_t core3_fiq_source = IO_MMIO_read32(CORE3_FIQ_SOURCE); + */ + + + if(core0_irq_source & 2){ + //core timer interrupt + do_irq(CORE0_TIMER, core_timer_irq_handler, enable_core_timer_irq, disable_core_timer_irq); + }else if(irq_pending_1 & (1 << 29)){ + auxirq = IO_MMIO_read32(AUX_IRQ); + if(auxirq & 1){ + uart_irq_type = (IO_MMIO_read32(AUX_MU_IIR_REG) >> 1) & (0b11); + if(uart_irq_type == RX){ + // Receiver holds valid byte + do_irq(MINI_UART_RX, mini_uart_irq_read, enable_mini_uart_rx_irq, disable_mini_uart_rx_irq); + }else{ + irq_count[UNKNOWN_IRQ]++; + LOG("UART interrupt"); + while(1); + } + }else{ + irq_count[UNKNOWN_IRQ]++; + LOG("Unkown AUX interrupt, DAIF: %x", get_DAIF()); + } + } + else{ + irq_count[UNKNOWN_IRQ]++; + LOG("Unkown interrupt"); + } +} + +void err_handler(uint64_t type, uint64_t esr, uint64_t elr, uint64_t spsr_el1, uint64_t sp_el0, uint64_t sp){ + struct task_struct *cur = get_current(); + struct trap_frame *trap_frame = get_trap_frame(cur); + write_str("unkown irq count: "); + write_hex(irq_count[UNKNOWN_IRQ]); + write_str("\r\n"); + + write_str("pid: "); + write_hex(cur->thread_info.pid); + write_str("\r\n"); + + write_str("trap frame: "); + write_hex((uint64_t)get_trap_frame(cur)); + write_str("\r\n"); + + write_str("cur->ctx.lr: "); + write_hex(cur->ctx.lr); + write_str("\r\n"); + + write_str("cur->ctx.sp: "); + write_hex(cur->ctx.sp); + write_str("\r\n"); + + write_str("cur->ctx.fp: "); + write_hex(cur->ctx.fp); + write_str("\r\n"); + + write_str("trap_frame->x0: "); + write_hex(trap_frame->x0); + write_str("\r\n"); + + write_str("trap_frame->x30: "); + write_hex(trap_frame->x30); + write_str("\r\n"); + + write_str("trap_frame->x29: "); + write_hex(trap_frame->x29); + write_str("\r\n"); + + write_str("kernel stack: "); + write_hex((uint64_t)cur->stack); + write_str("\r\n"); + + write_str("type: "); + write_hex(type); + write_str("\r\n"); + + write_str("esr_el1: "); + write_hex(esr); + write_str("\r\n"); + + write_str("elr_el1: "); + write_hex(get_ELR_EL1()); + write_str("\r\n"); + + write_str("spsr_el1: "); + write_hex(spsr_el1); + write_str("\r\n"); + + write_str("sp_el0: "); + write_hex(sp_el0); + write_str("\r\n"); + + write_str("sp: "); + write_hex(sp); + write_str("\r\n"); + + while(1); +} diff --git a/lab7/kernel/linker.ld b/lab7/kernel/linker.ld new file mode 100644 index 000000000..757465f77 --- /dev/null +++ b/lab7/kernel/linker.ld @@ -0,0 +1,64 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0xffff000000000000; /* kernel space 0xffff000000000000 ~ 0xffffffffffffffff */ + . += 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __kernel_image_start = .; + __EL1_stack_size = 0x4000; + __EL1_stack = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + . = ALIGN(0x1000); + __bss_end = .; + __reserved_page_table_start = .; + __PGD_start = .; + . = . + 4096; + __PGD_end = .; + + __PUD_start = .; + . = . + 4096; + __PUD_end = .; + + __PMD_start = .; + . = . + 4096 * 2; + __PMD_end = .; + + __PTE_start = .; + . = . + 4096 * 1024; + __PTE_end = .; + + . = ALIGN(0x1000); + __reserved_page_table_end = .; + __kernel_image_end = .; + __heap_start = .; + +} diff --git a/lab7/kernel/main.c b/lab7/kernel/main.c new file mode 100644 index 000000000..505c83b5c --- /dev/null +++ b/lab7/kernel/main.c @@ -0,0 +1,29 @@ +#include "types.h" +#include "peripherals/mini_uart.h" +#include "init/kernel_init.h" +#include "debug/debug.h" +#include "kernel/shell.h" +#include "kernel/sched/sched.h" +#include "kernel/sched/kthread.h" + +void kernel_main_thread(void){ + for(uint32_t i = 0 ; i < 10 ; i++){ + INFO("create kthread kthread_test"); +// kthread_create(kthread_test); + } + INFO("create kthread simple_shell"); + kthread_create(simple_shell); +} + +void kernel_main(void *dtb){ + dtb += UPPER_ADDR_SPACE_BASE; + kernel_init(dtb); + kthread_init(); + DEBUG_KERNEL_START(); + + INFO("create kernel main thread"); + kthread_create(kernel_main_thread); + + kthread_idle(); +} + diff --git a/lab7/kernel/reboot.c b/lab7/kernel/reboot.c new file mode 100644 index 000000000..2511cc06e --- /dev/null +++ b/lab7/kernel/reboot.c @@ -0,0 +1,14 @@ +#include "types.h" +#include "peripherals/iomapping.h" +#include "kernel/reboot.h" + +void reboot(int ticks){ + unsigned int pm_rstc,pm_wdog; + pm_rstc = IO_MMIO_read32(PM_RSTC); + + pm_wdog = PM_PASSWORD | (ticks & PM_WDOG_TIME_SET); + pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; + + IO_MMIO_write32(PM_RSTC, pm_rstc); + IO_MMIO_write32(PM_WDOG, pm_wdog); +} diff --git a/lab7/kernel/sched/Makefile b/lab7/kernel/sched/Makefile new file mode 100644 index 000000000..6b4756fe2 --- /dev/null +++ b/lab7/kernel/sched/Makefile @@ -0,0 +1,30 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../../include +OBJECTS = \ + sched.o \ + kthread.o \ + task.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + +%.o : %.S + $(CC) -c $^ -o $(OUTPUT)/$@ -I$(HEADERS) $(CFLAGS) + + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab7/kernel/sched/kthread.c b/lab7/kernel/sched/kthread.c new file mode 100644 index 000000000..558f1ba89 --- /dev/null +++ b/lab7/kernel/sched/kthread.c @@ -0,0 +1,147 @@ +#include "kernel/sched/kthread.h" + +extern void kthread_trampoline(); +extern int __EL1_stack; +extern int __EL1_stack_size; +void kthread_init(){ + LOG("kthread_init enter"); + volatile uint64_t daif; + struct task_struct* kthread = (struct task_struct*)kmalloc(sizeof(struct task_struct)); + + daif = local_irq_disable_save(); + kthread->stack = (void*)((uint64_t)&__EL1_stack - (uint64_t)&__EL1_stack_size); + LOG("kthread->stack: %p", kthread->stack); + + // initialize thread_info + kthread->thread_info.pid = get_pid_counter(); + kthread->thread_info.state = TASK_RUNNING; + + // initialize mm + kthread->mm = NULL; + + // initialize relationship + kthread->parent = NULL; + kthread->child = NULL; + INIT_LIST_HEAD(&kthread->siblings); + + // initialize schedule info + kthread->sched_info.rticks = 0; + kthread->sched_info.priority = 1; + kthread->sched_info.counter = kthread->sched_info.priority; + + list_add_tail(&kthread->list, &task_list); + + // initialzie singal + sigpending_init(&kthread->sigpending); + default_sighand_init(&kthread->sighandler); + + set_tpidr_el1((uint64_t)kthread); + local_irq_restore(daif); + LOG("kthread_init end"); +} + +void kthread_destroy(struct task_struct* task){ +// LOG("kthread_destroy %l", task->thread_info.pid); + list_del(&task->list); + free_pages(task->stack, 1); + kfree(task); +} +void _kthread_remove_zombies(){ + struct list_head* node; + struct task_struct* zombie; + volatile uint64_t daif; + //volatile uint64_t daif; + //daif = local_irq_disable_save(); + local_irq_disable(); + while(!list_empty(&zombies)){ + zombie = list_first_entry(&zombies, struct task_struct, zombie); + LOG("Remove %l", zombie->thread_info.pid); + list_del(zombies.next); + if(zombie->mm == NULL) kthread_destroy(zombie); + else task_destroy(zombie); + } + local_irq_enable(daif); + //local_irq_restore(daif); +} + +void kthread_idle(){ + while(1){ + //LOG("kthread_idle"); + _kthread_remove_zombies(); + preempt_schedule(); + } +} + +void kthread_test(){ + struct task_struct* cur; + cur = get_current(); + for(uint32_t i = 0 ; i < 10 ; i++){ + printf("%u: pid: %l\r\n",i , cur->thread_info.pid); + for(uint32_t j = 0 ; j < 100000 ; j ++){ + asm volatile("nop"); + } + } +} + +uint64_t kthread_create(kthread_func func){ + LOG("kthread enter"); + volatile uint64_t daif; + struct task_struct* kthread = (struct task_struct*)kmalloc(sizeof(struct task_struct)); + + // initialize kernel stack + kthread->stack = alloc_pages(1); + + // initialize thread_info + kthread->thread_info.pid = get_pid_counter(); + kthread->thread_info.state = TASK_RUNNING; + + // initialize thread context + kthread->ctx.lr = (uint64_t)kthread_trampoline; + kthread->ctx.x19 = (uint64_t)func; + kthread->ctx.sp = (uint64_t)kthread->stack + PAGE_SIZE * 2; + kthread->ctx.fp = kthread->ctx.sp; + + // initialize mm + kthread->mm = NULL; + + // initialize relationship + kthread->parent = NULL; + kthread->child = NULL; + INIT_LIST_HEAD(&kthread->siblings); + + // initialize schedule info + kthread->sched_info.rticks = 0; + kthread->sched_info.priority = 1; + kthread->sched_info.counter = kthread->sched_info.priority; + + daif = local_irq_disable_save(); + list_add_tail(&kthread->list, &task_list); + local_irq_restore(daif); + + // initialzie singal + sigpending_init(&kthread->sigpending); + default_sighand_init(&kthread->sighandler); + + LOG("kthread end"); + add_task_to_rq(kthread); + return 0; +} + +void kthread_start(kthread_func func){ + func(); + kthread_exit(); +} + +void kthread_exit(){ + volatile uint64_t daif; + LOG("kthread_exit start"); + struct task_struct* cur; + cur = get_current(); + cur->thread_info.state = TASK_DEAD; + + daif = local_irq_disable_save(); + list_add_tail(&cur->zombie, &zombies); + local_irq_restore(daif); + LOG("kthread_exit end"); + preempt_schedule(); +} diff --git a/lab7/kernel/sched/sched.c b/lab7/kernel/sched/sched.c new file mode 100644 index 000000000..526e9d51d --- /dev/null +++ b/lab7/kernel/sched/sched.c @@ -0,0 +1,114 @@ +#include "kernel/sched/sched.h" + +LIST_HEAD(zombies); +LIST_HEAD(rq); +LIST_HEAD(task_list); +uint64_t pid_count = 0; +int need_sched = 0; +struct task_struct* user_init = NULL; + +void add_task_to_rq(struct task_struct *task){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + task->thread_info.state = TASK_RUNNING; + + list_add_tail(&task->sched_info.sched_list, &rq); + need_sched = 1; + local_irq_restore(daif); +} + +struct task_struct* pick_next_task_from_rq(){ + if(!list_empty(&rq)) + return list_first_entry(&rq, struct task_struct, sched_info.sched_list); + else + return NULL; +} +extern void switch_ttbr0(uint64_t); +void switch_mm(struct task_struct* next){ + pgdval_t* pgd; + if(next->mm){ + pgd = next->mm->pgd; + if(pgd == 0){ + printf("switch_mm error\r\n"); + while(1); + } + switch_ttbr0(virt_to_phys(pgd)); + } +} + +void schedule(){ + struct task_struct* current, *next; + // prevent running scheduler in softirq + if(in_softirq()){ + return; + } + + if(need_sched){ + need_sched = 0; + next = pick_next_task_from_rq(); + + // add current task to schdule list + current = get_current(); + if( current != NULL && current->thread_info.state != TASK_DEAD && next != NULL){ + current->sched_info.counter = current->sched_info.priority; + list_add_tail(¤t->sched_info.sched_list, &rq); + }else if(current == NULL){ + printf("schedule error\r\b"); + while(1); + } + + // context switch + if(next != NULL){ + list_del(&next->sched_info.sched_list); + switch_mm(next); + switch_to(current, next); + } + } +} + +void preempt_schedule(){ + local_irq_disable(); + need_sched = 1; + schedule(); + local_irq_enable(); +} + +pid_t get_pid_counter(void){ + pid_t ret; + ret = pid_count++; + return ret; +} + +struct task_struct* find_task_by_pid(uint64_t pid){ + struct list_head *node; + struct task_struct *tmp_task; + uint64_t daif; + + daif = local_irq_disable_save(); + list_for_each(node, &task_list){ + tmp_task = list_entry(node, struct task_struct, list); + if(tmp_task->thread_info.pid == pid && tmp_task->thread_info.state != TASK_DEAD){ + local_irq_restore(daif); + return tmp_task; + } + } + local_irq_restore(daif); + return NULL; +} + + +/* debug */ +void print_rq(void){ + struct list_head *node; + struct task_struct *tmp_task; + struct task_pid *tmp_task_pid; + volatile uint64_t daif; + // In printf, interrupt will be enable, so we can't directly print run queue + daif = local_irq_disable_save(); + list_for_each(node, &task_list){ + tmp_task = list_entry(node, struct task_struct, list); + printf("%l ", tmp_task->thread_info.pid); + } + local_irq_restore(daif); + printf("\r\n"); +} diff --git a/lab7/kernel/sched/task.c b/lab7/kernel/sched/task.c new file mode 100644 index 000000000..24a7da0e3 --- /dev/null +++ b/lab7/kernel/sched/task.c @@ -0,0 +1,539 @@ +#include "kernel/sched/task.h" + +extern void task_load_all(void); +extern void switch_ttbr0(uint64_t); + +void task_init(){ +} + +uint64_t task_dup(struct task_struct* parent){ + LOG("task_dup start"); + volatile uint64_t daif; + struct task_struct* child = (struct task_struct*)kmalloc(sizeof(struct task_struct)); + struct vm_area_struct* pvma, *ppvma; + struct trap_frame *pptrap_frame; + struct trap_frame *pctrap_frame; + uint64_t child_pid; + + daif = local_irq_disable_save(); + + // initialize mm + child->mm = mm_struct_create(); + // copy vma in parent->mm to child->mm except for user stack1 + dup_mm_struct(child->mm, parent->mm); + // create user stack vma + //dup_vma_stack(child->mm, parent->mm); + //create vc ram identity mapping +// create_vma_vc(child->mm); + + + // initialize child's trap frame and kernel stack + child->stack = alloc_pages(1); + memcpy(child->stack, parent->stack, PAGE_SIZE * 2); + + pptrap_frame = get_trap_frame(parent); + pctrap_frame = get_trap_frame(child); + LOG("parent kernel stack: %p", parent->stack + PAGE_SIZE * 2); + LOG("parent trap frame: %p", pptrap_frame); + LOG("child trap stack: %p", child->stack + PAGE_SIZE * 2); + LOG("child trap frame: %p", pctrap_frame); + + // set child's return value to 0 + pctrap_frame->x0 = 0; + + // initialize thread_info + child->thread_info.pid = get_pid_counter(); + child_pid = child->thread_info.pid; + child->thread_info.state = TASK_RUNNING; + + // initialize thread context + // directly back to user space + memcpy(&child->ctx, &parent->ctx, sizeof(struct task_ctx)); + child->ctx.lr = (uint64_t)task_load_all; + child->ctx.sp = (uint64_t)pctrap_frame; + child->ctx.fp = (uint64_t)pctrap_frame; + + // initialize child's relationship + child->parent = parent; + child->child = NULL; + INIT_LIST_HEAD(&child->siblings); + + // initialize parent's relationship + if(parent->child != NULL){ + list_add_tail(&child->siblings, &parent->child->siblings); + }else{ + parent->child = child; + } + + // initialize schedule info + child->sched_info.rticks = 0; + child->sched_info.priority = parent->sched_info.priority ; + child->sched_info.counter = child->sched_info.priority; + + // initialzie singal + sigpending_init(&child->sigpending); + memcpy(&child->sighandler, &parent->sighandler, sizeof(struct sighand_struct)); + + // initialize fs + dup_fs(parent, child); + + // insert task to run queue and task list + list_add_tail(&child->list, &task_list); + local_irq_restore(daif); + add_task_to_rq(child); + LOG("task_dup end"); + return child_pid; +} + +void task_kill(uint64_t pid){ + LOG("task_kill start"); + volatile uint64_t daif; + struct task_struct* target; + struct task_struct* current; + + target = find_task_by_pid(pid); + if(target == NULL || (target->thread_info.state == TASK_DEAD)) return; + + current = get_current(); + + daif = local_irq_disable_save(); + + target->thread_info.state = TASK_DEAD; + list_add_tail(&target->zombie, &zombies); + if(target != current){ + list_del(&target->sched_info.sched_list); + } + + local_irq_restore(daif); + + LOG("task_kill end"); + + preempt_schedule(); +} + +void task_exit(){ + volatile uint64_t daif; + LOG("task_exit start"); + struct task_struct* cur; + cur = get_current(); + cur->thread_info.state = TASK_DEAD; + + daif = local_irq_disable_save(); + list_add_tail(&cur->zombie, &zombies); + local_irq_restore(daif); + LOG("task_exit end"); + preempt_schedule(); +} + +void task_destroy(struct task_struct* task){ + struct vm_area_struct *vma; + struct list_head* node; + struct task_struct* child; + + list_del(&task->list); + + // free kernel stack + free_pages(task->stack, 1); + + // free mm + mm_struct_destroy(task->mm); + + //unlink from parent and sibliings and set re-parent + if(task->parent){ + //unlink from parent + if(task->parent->child == task){ + child = list_first_entry(&task->siblings, struct task_struct, siblings); + task->parent->child = child; + list_del(&task->siblings); + } + // re-parent + if(task->child){ + task->child->parent = task->parent; + list_for_each(node, &task->child->siblings){ + child = list_entry(node, struct task_struct, siblings); + child->parent = task->parent; + } + list_splice_tail(&task->child->siblings, &task->parent->child->siblings); + list_add_tail(&task->child->siblings, &task->parent->child->siblings); + } + }else{ + if(task->child){ + list_for_each(node, &task->child->siblings){ + child = list_entry(node, struct task_struct, siblings); + child->parent = task->child; + } + task->child->child = list_first_entry(&task->child->siblings, struct task_struct, siblings); + list_del(&task->child->siblings); + task->child->parent = NULL; + } + } + // free fs + kfree(task->files); // remember to close all files + kfree(task->fs); + + // free signal pending queue + free_sigpendings(&task->sigpending); + kfree(task); + if(user_init == task) user_init = NULL; +} + +int task_exec(const char* name, char* const argv[]){ + LOG("enter task_exec"); + LOG("file name: %s", name); + int ret = -1; + struct list_head* node; + struct vm_area_struct *vma; + struct task_struct* current = get_current(); + struct trap_frame *trap_frame = get_trap_frame(current); + volatile uint64_t daif; + char* tmp_name; + size_t s; + + // since we will destroy pgb and it will cause page table broken, + // we have to save the name in userspace first + if(name[0] == '/') name++; + tmp_name = kmalloc(strlen(name) + 10); + strcpy(tmp_name, name); + // initialize mm + if(s = initrdfs_filesize((char*)tmp_name)){ + mm_struct_destroy(current->mm); + current->mm = mm_struct_create(); + // load executable + // create code memory area + vma = create_vma_code(current->mm,(char*)tmp_name); + trap_frame->elr_el1 = (uint64_t)vma->vm_start; + //create vc ram identity mapping + create_vma_vc(current->mm); + + // create user stack + vma = create_vma_stack(current->mm); + trap_frame->sp_el0 = (uint64_t)vma->vm_end; + + // initialize Saved Program Status Register el1 + trap_frame->spsr_el1 = 0; + ret = 0; + } + kfree(tmp_name); + + // initialize signal + default_sighand_init(¤t->sighandler); + // switch ttbr0_el1 before return to user space + daif = local_irq_disable_save(); + switch_ttbr0(virt_to_phys(current->mm->pgd)); + local_irq_restore(daif); + LOG("end task_exec"); + return ret; +} + + +void run_init_task(char* filename){ + struct vm_area_struct* vma; + uint64_t user_entry, user_sp; + struct trap_frame* ptrap_frame; + volatile uint64_t daif; + LOG("run_init_task enter"); + LOG("Size of struct trap_frame: %x", sizeof(struct trap_frame)); + + daif = local_irq_disable_save(); + struct task_struct* task = (struct task_struct*)kmalloc(sizeof(struct task_struct)); + + // initialize mm + task->mm = mm_struct_create(); + // load executable + // create code memory area + vma = create_vma_code(task->mm, filename); + user_entry = (uint64_t)vma->vm_start; + //create vc ram identity mapping + create_vma_vc(task->mm); + + // create user stack + vma = create_vma_stack(task->mm); + user_sp = (uint64_t)vma->vm_end; + + LOG("vma: %p, user_sp: %p, user_entry: %p", vma, user_sp, user_entry); + // create kernel stack + task->stack = alloc_pages(1); + + // initialize trap frame in kernel stack + ptrap_frame = (struct trap_frame*)get_trap_frame(task); + ptrap_frame->spsr_el1 = 0x0; + ptrap_frame->sp_el0 = user_sp; + ptrap_frame->elr_el1 = user_entry; + + // initialize thread_info + task->thread_info.pid = get_pid_counter(); + task->thread_info.state = TASK_RUNNING; + + // initialize thread context + task->ctx.lr = (uint64_t)task_load_all; + task->ctx.sp = (uint64_t)get_trap_frame(task); + task->ctx.fp = task->ctx.sp; + + // initialize relationship + task->parent = NULL; + task->child = NULL; + INIT_LIST_HEAD(&task->siblings); + + // initialize schedule info + task->sched_info.rticks = 0; + task->sched_info.priority = 1; + task->sched_info.counter = task->sched_info.priority; + + // initialzie singal + sigpending_init(&task->sigpending); + default_sighand_init(&task->sighandler); + + // initialize fs + task->files = (struct files_struct*)kmalloc(sizeof(struct files_struct)); + memset(task->files, 0, sizeof(struct files_struct)); + task->files->fd_array[0] = vfs_open("/dev/uart", 0, 0); + task->files->fd_array[1] = vfs_open("/dev/uart", 0, 0); + task->files->fd_array[2] = vfs_open("/dev/uart", 0, 0); + + task->fs = (struct fs_struct*)kmalloc(sizeof(struct fs_struct)); + task->fs->root = rootfs->mnt_root; + task->fs->pwd = rootfs->mnt_root; + + // insert task to run queue and task list + user_init = task; + list_add_tail(&task->list, &task_list); + local_irq_restore(daif); + + LOG("run_init_task end"); + add_task_to_rq(task); +} + +struct vm_area_struct* create_vma_vc(struct mm_struct* mm){ + uint64_t va, pa; + struct vm_area_struct *vma; + uint8_t* addr; + + vma = kmalloc(sizeof(struct vm_area_struct)); + vma->vm_start = VMA_VC_BASE; + vma->vm_end = VMA_VC_END; + vma->type = VMA_VC_RAM; + vma->vm_flags = VMA_PROT_READ | VMA_PROT_WRITE; + vma->filename == NULL; + list_add_tail(&vma->list, &mm->mmap_list); +/* + va = vma->vm_start; + while(va != vma->vm_end){ + // identity mapping for vc ram + mappages(mm->pgd, va, va, PAGE_SIZE, VM_PTE_USER_ATTR); + va += PAGE_SIZE; + }*/ + return vma; +} + +struct vm_area_struct* create_vma(struct mm_struct* mm, uint64_t vm_start, uint64_t vm_end, uint64_t prot, uint64_t type){ + uint64_t va, pa; + struct vm_area_struct *vma; + uint8_t* addr; + + vma = kmalloc(sizeof(struct vm_area_struct)); + vma->vm_start = vm_start; + vma->vm_end = vm_end; + vma->type = type; + vma->vm_flags = prot; + vma->filename == NULL; + list_add_tail(&vma->list, &mm->mmap_list); + + return vma; +} +struct vm_area_struct* create_vma_stack(struct mm_struct* mm){ + uint64_t va, pa; + struct vm_area_struct *vma; + uint8_t* addr; + + vma = kmalloc(sizeof(struct vm_area_struct)); + vma->vm_start = VMA_STACK_END - VMA_STACK_SIZE; + vma->vm_end = VMA_STACK_END; + vma->type = VMA_STACK; + vma->vm_flags = VMA_PROT_READ | VMA_PROT_WRITE; + vma->filename == NULL; + list_add_tail(&vma->list, &mm->mmap_list); + + va = vma->vm_start; + /* + while(va != vma->vm_end){ + addr = calloc_page(); + mappages(mm->pgd, va, virt_to_phys(addr), PAGE_SIZE, VM_PTE_USER_ATTR); + + va += PAGE_SIZE; + }*/ + return vma; + +} + +struct vm_area_struct* create_vma_code(struct mm_struct* mm, char* filename){ + uint64_t va, pa; + size_t size, offset = 0, n; + struct vm_area_struct *vma; + uint8_t* addr; + char* tmp_name; + + vma = kmalloc(sizeof(struct vm_area_struct)); + size = initrdfs_filesize(filename); + vma->vm_start = VMA_CODE_BASE; + vma->vm_end = VMA_CODE_BASE + ALIGN_UP(size, PAGE_SIZE); + vma->vm_flags = VMA_PROT_READ | VMA_PROT_WRITE | VMA_PROT_EXEC; + vma->type = VMA_FILE; + tmp_name = kmalloc(strlen(filename) + 5); + strcpy(tmp_name, filename); + + vma->filename = tmp_name; + list_add_tail(&vma->list, &mm->mmap_list); + + // copy file to code memory area and set page table +/* + va = VMA_CODE_BASE; + while(size){ + addr = calloc_page(); + n = initrdfs_loadfile(filename, addr, offset, PAGE_SIZE); + mappages(mm->pgd, va, virt_to_phys(addr), PAGE_SIZE, VM_PTE_USER_ATTR); + + va += PAGE_SIZE; + size -= n; + offset += n; + } +*/ + return vma; +} + +// Only duplicate area that not belong to user stack +void dup_mm_struct(struct mm_struct* dst_mm, struct mm_struct* src_mm){ + uint64_t va; + struct list_head* node; + struct vm_area_struct* vma,*tmp_vma; + char* tmp_name; + + list_for_each(node, &src_mm->mmap_list){ + tmp_vma = list_entry(node, struct vm_area_struct, list); + LOG("src_mm's vm area type 0x%x", tmp_vma->type); + vma = (struct vm_area_struct*)kmalloc(sizeof(struct vm_area_struct)); + vma = kmalloc(sizeof(struct vm_area_struct)); + vma->vm_start = tmp_vma->vm_start; + vma->vm_flags = tmp_vma->vm_flags; + vma->vm_end = tmp_vma->vm_end; + vma->type = tmp_vma->type; + if(tmp_vma->type == VMA_FILE){ + tmp_name = kmalloc(strlen(tmp_vma->filename) + 5); + strcpy(tmp_name, tmp_vma->filename); + vma->filename = tmp_name; + } + + // VC RAM should do copy on write and it only support demand paging + if(vma->type != VMA_VC_RAM){ + // COW + dup_pages(dst_mm->pgd, src_mm->pgd, vma->vm_start, vma->vm_end - vma->vm_start, PAGE_ATTR_RDONLY); + // also set parent's page to read only to trigger COW + mappages(src_mm->pgd, tmp_vma->vm_start, 0x0, tmp_vma->vm_end - tmp_vma->vm_start, PAGE_ATTR_RDONLY, 1); + } + + list_add_tail(&vma->list, &dst_mm->mmap_list); + } +} + +struct mm_struct* mm_struct_create(){ + struct mm_struct *mm = kmalloc(sizeof(struct mm_struct)); + INIT_LIST_HEAD(&mm->mmap_list); + mm->pgd = calloc_page(); + return mm; +} + +void mm_struct_destroy(struct mm_struct* mm){ + struct vm_area_struct *vma; + while(!list_empty(&mm->mmap_list)){ + vma = list_first_entry(&mm->mmap_list, struct vm_area_struct, list); + if(vma->type == VMA_FILE){ + kfree(vma->filename); + } + list_del(&vma->list); + kfree(vma); + } + free_page_table(mm->pgd); + kfree(mm); +} + +struct vm_area_struct* find_vma(struct mm_struct *mm, uint64_t addr){ + struct vm_area_struct *vma; + struct list_head *node; + list_for_each(node, &mm->mmap_list){ + vma = list_entry(node, struct vm_area_struct, list); + if(vma->vm_start <= addr && vma->vm_end > addr){ + return vma; + } + } + return NULL; +} + +void dup_fs(struct task_struct* parent, struct task_struct *child){ + uint64_t daif = local_irq_disable_save(); + child->files = (struct files_struct*)kmalloc(sizeof(struct files_struct)); + memcpy(child->files, parent->files, sizeof(struct files_struct)); + // add reference count of file + for(uint64_t i = 0 ; i < NR_OPEN_DEFAULT ; i++){ + if(child->files->fd_array[i] != NULL){ + child->files->fd_array[i]->f_count++; + } + } + + child->fs = (struct fs_struct*)kmalloc(sizeof(struct fs_struct)); + child->fs->root = parent->fs->root; + child->fs->pwd = parent->fs->pwd; + local_irq_restore(daif); +} + +uint64_t sys_fork(){ + return task_dup(get_current()); +} + +uint64_t sys_getpid(){ + return get_current()->thread_info.pid; +} + +void sys_exit(uint64_t status){ + task_exit(status); +} + +void sys_kill(uint64_t pid){ + task_kill(pid); +} +uint64_t sys_exec(const char* name, char *const argv[]){ + return task_exec(name, argv); +} + +uint64_t mmap(void* addr, size_t len, int prot, int flags, int fd, int file_offset){ + struct task_struct* current = get_current(); + struct mm_struct* mm = current->mm; + struct vm_area_struct* tmp_vma, *vma; + uint64_t vm_start = 0, vm_end; + uint64_t daif; + uint64_t tmp_prot = 0, tmp_type = 0; + + INFO("mmap(%p, %p, %p, %p, %p, %p)", addr, len, prot, flags, fd, file_offset); + tmp_prot = prot & (VMA_PROT_READ | VMA_PROT_WRITE | VMA_PROT_EXEC); + if(flags & MAP_ANONYMOUS) tmp_type = VMA_ANONYMOUS; + + daif = local_irq_disable_save(); + if(addr != NULL){ + vm_start = ALIGN_DOWN(addr, PAGE_SIZE); + }else{ + vm_start = 0x0; + } + + while(tmp_vma = find_vma(mm , vm_start)){ + vm_start = tmp_vma->vm_end; + } + vm_end = vm_start + ALIGN_UP(len, PAGE_SIZE); + create_vma(mm, vm_start, vm_end, tmp_prot, tmp_type); + + INFO("return value: %p", vm_start); + local_irq_restore(daif); + return vm_start; +} + +void* sys_mmap(void* addr, size_t len, int prot, int flags, int fd, int file_offset){ + return (void*)mmap(addr, len, prot, flags, fd, file_offset); +} + diff --git a/lab7/kernel/shell.c b/lab7/kernel/shell.c new file mode 100644 index 000000000..82c210243 --- /dev/null +++ b/lab7/kernel/shell.c @@ -0,0 +1,178 @@ +#include "kernel/shell.h" + +char *miku_ascii = "⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀\r\n⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁\r\n⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀\r\n⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀\r\n⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀\r\n⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀\r\n⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀\r\n⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀\r\n⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀\r\n⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀\r\n⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀\r\n⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀\r\n⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀\r\n⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀"; +char buf[0x2000]; + +void print_irq_count(void){ + printf("irq_count: "); + for(uint32_t i = 0 ; i < END_OF_LIST ; i++){ + printf("%l ", irq_count[i]); + } + printf("\r\n"); +} + +void setTimeout_callback(void* data){ + uint64_t t = get_jiffies(); + printf("Elapsed time after booting: %l.%l\r\n", t / HZ, t % HZ); + print_irq_count(); + printf("Your message: %s\r\n",(char*) data); +} + + +void simple_shell(){ + unsigned int i; + char ch, *token; + printf(miku_ascii); + printf("\r\n\r\n"); + while(1){ + i = 0; + buf[0] = '\0'; + printf("# "); + // read command + while(1){ + ch = (char)getchar(); + if(ch == '\r'){ + printf("\r\n"); + buf[i] = '\0'; + break; + }else if(ch != '\n'){ + putchar(ch); + buf[i] = ch; + i++; + } + } + + token = strtok(buf, DELIM); + if(token == NULL) continue; + // match comman + if(strcmp(token, "help") == 0){ + printf("help : print this help menu\r\n" \ + "hello : print Hello World!\r\n" \ + "info : print hardware infomation\r\n" \ + "ls : list files\r\n" \ + "cat : cat files\r\n" \ + "load : load user program\r\n" \ + "time : print time after booting\r\n" \ + "reboot : reboot the device\r\n" \ + "setTimeout : set a N seconds timer task\r\n" \ + " setTimeout \r\n" \ + "irq_count : list irq count\r\n" + "alloc_pages : get pages\r\n" \ + " alloc_pages \r\n" \ + "free_pages : free pages\r\n" \ + " free_pages \r\n" \ + "kmalloc : get an object\r\n" \ + " kmalloc \r\n" \ + "kfree : free an object\r\n" \ + " kfree \r\n" \ + + "page_info : get buddy system's statistics\r\n" \ + "print_rq : print run queue\r\n" \ + + ); + + }else if(strcmp(token, "hello") == 0){ + printf("Hello World!\r\n"); + }else if(strcmp(token, "info") == 0){ + uint32_t tmp[2]; + MBox_get_board_revision(tmp); + printf("Board revision: 0x%x\r\n", tmp[0]); + + MBox_get_arm_memory(tmp); + printf("Memory base: 0x%x\r\n", tmp[0]); + printf("Memory size: 0x%x\r\n", tmp[1]); + }else if(strcmp(token, "reboot") == 0){ + printf("Start rebooting...\r\n"); + reboot(100); + while(1); + }else if(strcmp(token, "ls") == 0){ + initrdfs_ls(); + }else if(strcmp(token, "cat") == 0){ + initrdfs_cat(); + }else if(strcmp(token, "load") == 0){ + /*( initrdfs_loadfile("test.img",(uint8_t*) 0x100000); + asm volatile("mov x0, 0x0\n\t" + "msr spsr_el1, x0\n\t" + "mov x0, 0x100000\n\t" + "msr sp_el0, x0\n\t" + "mov x0, #0x100000\n\t" + "msr elr_el1, x0\n\t" + "eret\n\t" + );*/ + run_init_task("initramfs/vfs1.img"); + while(1){ + local_irq_disable(); + if(user_init == NULL) break; + preempt_schedule(); + local_irq_enable(); + } + local_irq_enable(); + }else if(strcmp(token, "time") == 0){ + uint64_t j = get_jiffies(); + printf("Elapsed time after booting: %l.%l\r\n", j / HZ, j % HZ); + }else if(strcmp(token, "setTimeout") == 0){ + uint64_t j = 0, len = 0, timeout = 0; + char *data = NULL; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + len = strlen(token); + data = (char*)simple_malloc(len + 1); + strcpy(data, token); + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + timeout = atoul(token); + + j = get_jiffies(); + add_timer(setTimeout_callback, data, timeout * 1000); + printf("Elapsed time after booting: %l.%l\r\n", j / HZ, j % HZ); + print_irq_count(); + printf("Timer will trigger after %l seconds\r\n", timeout); + }else if(strcmp(token, "irq_count") == 0){ + print_irq_count(); + }else if(strcmp(token, "alloc_pages") == 0){ + uint32_t order; + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + order = atoul(token); + p = alloc_pages(order); + printf("Allocate pages at %l\r\n", p); + }else if(strcmp(token, "free_pages") == 0){ + void* p; + struct page* page; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + p = (void*)atoul(token); + page = pfn_to_page(virt_to_pfn(p)); + + free_pages(p, get_page_order(page)); + printf("Free pages\r\n"); + }else if(strcmp(token, "kmalloc") == 0){ + uint32_t size; + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + size = atoul(token); + p = kmalloc(size); + printf("Allocate an object at %l\r\n", p); + }else if(strcmp(token, "kfree") == 0){ + void* p; + + token = strtok(NULL, DELIM); + if(token == NULL) continue; + p = (void*)atoul(token); + + kfree(p); + printf("Free an object\r\n"); + }else if(strcmp(token, "page_info") == 0){ + print_buddy_statistics(); + }else if(strcmp(token, "print_rq") == 0){ + print_rq(); + } + } +} diff --git a/lab7/kernel/signal.c b/lab7/kernel/signal.c new file mode 100644 index 000000000..7a8dfa096 --- /dev/null +++ b/lab7/kernel/signal.c @@ -0,0 +1,202 @@ +#include "kernel/sched/task.h" +#include "kernel/signal.h" +#include "kernel/signal_inner.h" + +extern void sigreturn_trampoline(); + +int is_valid_signal(int signal){ + return (signal > 0 && signal < SIG_MAX_NUM); +} +void sigpending_init(struct sigpending* sigpending){ + INIT_LIST_HEAD(&sigpending->pending); + sigpending->cur_signal = 0; +} + +void default_sighand_init(struct sighand_struct* sighandler){ + memcpy(sighandler->actions, default_actions, sizeof(default_actions)); +} + +int send_signal(uint64_t pid, int signal){ + LOG("enter send_signal, pid: %l signal %d", pid, signal); + struct task_struct* target = find_task_by_pid(pid); + struct signal_queue* sigq; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + if(!is_valid_signal(signal) || target == NULL) goto end; + if(target->thread_info.state == TASK_DEAD) goto end; + + LOG("target %p", target); + sigq = kmalloc(sizeof(struct signal_queue)); + + + sigq->signal = signal; + list_add_tail(&sigq->list, &target->sigpending.pending); + +end: + local_irq_restore(daif); + LOG("end send_signal"); + return 0; +} + +int register_signal(int signal, sig_handler handler){ + LOG("enter register_signal"); + uint64_t daif; + int ret; + struct task_struct* current = get_current(); + + if(current == NULL) return -1; + + LOG("signal: %d, handler: %p", signal, handler); + daif = local_irq_disable_save(); + // install signal handler from user space + if(is_valid_signal(signal)){ + current->sighandler.actions[signal].sa_flags &= ~(SIG_FLAG_KERNEL); + current->sighandler.actions[signal].sa_handler = handler; + + local_irq_restore(daif); + return 0; + } + + local_irq_restore(daif); + return -1; +} + +void handle_sigreturn(){ + sigreturn_frame_restore(); +} + +int get_pending_signal(struct task_struct *task){ + struct signal_queue* sigq; + uint64_t signal = 0; + if(!list_empty(&task->sigpending.pending)){ + sigq = list_first_entry(&task->sigpending.pending, struct signal_queue, list); + signal = sigq->signal; + list_del(&sigq->list); + kfree(sigq); + LOG("get pending signal %d", signal); + } + return signal; +} + +void handle_signal(){ + int cur_signal; + volatile uint64_t daif; + struct sigaction* action; + struct task_struct* current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + if(current == NULL) return; + + daif = local_irq_disable_save(); + + cur_signal = get_pending_signal(current); + if(!is_valid_signal(cur_signal)) return; + LOG("handle signal %d", cur_signal); + + action = ¤t->sighandler.actions[cur_signal]; + current->sigpending.cur_signal = cur_signal; + + if(action->sa_flags & SIG_FLAG_KERNEL){ + // if signal handler is in kernel space, just directly execute it + LOG("execute kernel signal handler"); + action->sa_handler(); + }else{ + // if signal handler is in user space, execute it in user space by modify trap frame + LOG("execute user signal handler"); + sigreturn_frame_save(action->sa_handler); + } + + local_irq_restore(daif); +} + +void sigreturn_frame_save(sig_handler handler){ + LOG("enter sigreturn_frame_save"); + struct task_struct* current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + uint64_t old_trap_frame; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + // store a copy of current trap frame onto user stack + old_trap_frame = trap_frame->sp_el0 - sizeof(struct trap_frame); + memcpy((void*)old_trap_frame, trap_frame, sizeof(struct trap_frame)); + + // change sp to point to this copy + trap_frame->sp_el0 = old_trap_frame; + + // set elr_el1 to handler + // set lr to jump to our sigreturn_trampoline + // so that when task return to user from kernel mode, it will back to sigreturn_trampoline + trap_frame->x30 = (uint64_t)sigreturn_trampoline; // in entry.S + trap_frame->elr_el1 = (uint64_t)handler; // in entry.S + + local_irq_restore(daif); + LOG("end sigreturn_frame_save"); +} + +void sigreturn_frame_restore(){ + LOG("enter sigreturn_frame_restore"); + struct task_struct* current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + struct trap_frame* old_trap_frame; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + // restore old trap frame + old_trap_frame = (struct trap_frame*)trap_frame->sp_el0; + memcpy(trap_frame, old_trap_frame, sizeof(struct trap_frame)); + + local_irq_restore(daif); + LOG("end sigreturn_frame_restore"); +} + +void sig_terminate(){ + struct task_struct *current = get_current(); + uint64_t pid; + volatile uint64_t daif; + LOG("enter signal_terminate"); + + daif = local_irq_disable_save(); + + pid = current->thread_info.pid; + printf("pid: %l, Receive signal: %s\r\n",pid ,sig_to_str[current->sigpending.cur_signal]); + local_irq_restore(daif); + + task_exit(); +} + +void sig_default(){ + struct task_struct *current = get_current(); + uint64_t pid; + volatile uint64_t daif; + LOG("enter signal_default"); + + daif = local_irq_disable_save(); + + pid = current->thread_info.pid; + printf("pid: %l, Receive signal: %s\r\n",pid , sig_to_str[current->sigpending.cur_signal]); + local_irq_restore(daif); + + LOG("end signal_default"); +} + +void free_sigpendings(struct sigpending* sigp){ + struct signal_queue* sigq; + while(!list_empty(&sigp->pending)){ + sigq = list_first_entry(&sigp->pending, struct signal_queue, list); + list_del(&sigq->list); + kfree(sigq); + } +} + +void sys_sigreturn(){ + handle_sigreturn(); +} + +void sys_signal(int signal, sig_handler handler){ + register_signal(signal, handler); +} + +int sys_sigkill(uint64_t pid, int signal){ + return send_signal(pid, signal); +} diff --git a/lab7/kernel/start.S b/lab7/kernel/start.S new file mode 100644 index 000000000..3932f36f2 --- /dev/null +++ b/lab7/kernel/start.S @@ -0,0 +1,120 @@ +#include "mm/pgtable.h" +.section ".text.boot" +.global _start +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #0xff + + // cpu id > 0, stop + cbz x1, master_core + +proc_hang: + wfe + b proc_hang + +// cpu id == 0 +master_core: + adr x1, _dtb + str x0, [x1] +// initialize .bss section + adr x1, __bss_start + adr x2, __bss_end +bss_zero: + sub x3, x2, x1 + cbz x3, end + str xzr, [x1], #8 // store zero to [x1] and add 8 to x1 + b bss_zero + +end: +// modify vbar_el1 before changing exception level to 1 (in virtual address) + ldr x0, =EL1_exception_vector_table + msr vbar_el1, x0 + +// set up identity pageing + bl identity_paging + +// from el2 to el1 + bl from_el2_to_el1 + +// enable virtual memory + ldr x2, =vm_enable + br x2 + +vm_enable: +// kernel_main(_dtb) + ldr x1, =_dtb + ldr x0, [x1] + +// set tpidr_el1 to NULL to avoid timer interrupt accidently update current task_strcut + mov x1, 0 + msr tpidr_el1, x1 + + +// jump to kernel_main + bl kernel_main + b proc_hang + +from_el2_to_el1: + ldr x0, =__EL1_stack // Set el1 stack to __EL1_stack + msr sp_el1, x0 + + mov x0, (1 << 31) // Set hcr_el2.RW so EL1 uses aarch64 + msr hcr_el2, x0 + + mov x0, 0x3c5 // EL1h (SPSel = 1) + msr spsr_el2, x0 + msr elr_el2, lr + eret // return to EL1 + +identity_paging: +// set page granularity ofttbr0 and ttbr1 to 4KiB and set virtual memory mapping region to 0 ~ 2^48 + ldr x0, =TCR_CONFIG_DEFAULT + msr tcr_el1, x0 + +// set mair_el1 + ldr x0, =( \ + (MAIR_DEVICE_nGnRnE << (MAIR_IDX_DEVICE_nGnRnE * 8)) | \ + (MAIR_NORMAL_NOCACHE << (MAIR_IDX_NORMAL_NOCACHE * 8)) \ + ) + msr mair_el1, x0 + +// initialize identity page table + adr x0, __PGD_start + mov x1, x0 + ldr x2, =(0x1000 * 1028) +pg_zero: + sub x3, x1, x0 + sub x3, x3, x2 + cbz x3, pg_zero_end + str xzr, [x1], #8 // store zero to [x1] and add 8 to x1 + b pg_zero + +pg_zero_end: + adr x1, __PUD_start +// initialize PGD + ldr x2, = BOOT_PGD_ATTR + orr x2, x1, x2 // combine the physical address of next level page with attribute. + str x2, [x0] +// initialize PUD + ldr x2, = BOOT_PUD_ATTR + mov x3, 0x00000000 + orr x3, x2, x3 + str x3, [x1] // 1st 1GB mapped by the 1st entry of PUD + mov x3, 0x40000000 + orr x3, x2, x3 + str x3, [x1, 8] // 2nd 1GB mapped by the 2nd entry of PUD +// set ttbr0_el1 to PGU + msr ttbr0_el1, x0 // load PGD to the bottom translation-based register (el0 mapping). + msr ttbr1_el1, x0 // load PGD to the bottom translation-based register (el1 mapping). + + mrs x2, sctlr_el1 + orr x2 , x2, 1 // set first bit to 1 to enable MMU + msr sctlr_el1, x2 // enable MMU, cache remains disabled + + ret + + +.section ".data" +_dtb: .dword 0 + diff --git a/lab7/kernel/syscall_table.c b/lab7/kernel/syscall_table.c new file mode 100644 index 000000000..9bc2143fe --- /dev/null +++ b/lab7/kernel/syscall_table.c @@ -0,0 +1,124 @@ +#include "kernel/syscall_table.h" + +uint64_t syscall_handler(){ + struct task_struct *current = get_current(); + struct trap_frame* trap_frame = get_trap_frame(current); + uint64_t NR_syscall = trap_frame->x8; + uint64_t x0, x1, x2, x3, x4, x5; + uint64_t ret; + + switch(NR_syscall){ + case 0: + ret = sys_getpid(); + break; + case 1: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_uart_read((uint8_t*)x0, x1); + break; + case 2: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_uart_write((uint8_t*)x0, x1); + break; + case 3: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_exec((const char *)x0, (char **const)x1); + break; + case 4: + ret = sys_fork(); + break; + case 5: + x0 = trap_frame->x0; + sys_exit(x0); + break; + case 6: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_mbox_call(x0, (uint32_t*)x1); + break; + case 7: + x0 = trap_frame->x0; + sys_kill(x0); + break; + case 8: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + sys_signal((int)x0,(void (*)())x1); + break; + case 9: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + sys_sigkill((uint64_t)x0,(int)x1); + break; + case 10: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + x2 = trap_frame->x2; + x3 = trap_frame->x3; + x4 = trap_frame->x4; + x5 = trap_frame->x5; + ret = (uint64_t)sys_mmap((void*)x0, (size_t)x1, (int)x2, (int)x3, (int)x4, (int)x5); + break; + case 11: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + ret = sys_open((const char*)x0,(int)x1); + break; + case 12: + x0 = trap_frame->x0; + ret = sys_close((int)x0); + break; + case 13: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + x2 = trap_frame->x2; + ret = sys_write((int)x0, (char*)x1, (ssize_t)x2); + break; + case 14: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + x2 = trap_frame->x2; + ret = sys_read((int)x0, (char*)x1, (ssize_t)x2); + break; + case 15: + x0 = trap_frame->x0; + ret = sys_mkdir((const char*)x0, 0); + break; + case 16: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + x2 = trap_frame->x2; + x3 = trap_frame->x3; + x4 = trap_frame->x4; + ret = (int)sys_mount((const char*)x0, (const char*)x1, (const char*)x2, (uint64_t)x3, (const void*)x4); + break; + case 17: + x0 = trap_frame->x0; + ret = sys_chdir((const char*)x0); + break; + case 18: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + x2 = trap_frame->x2; + ret = sys_lseek64((int)x0, (uint64_t)x1, (int)x2); + break; + case 19: + x0 = trap_frame->x0; + x1 = trap_frame->x1; + x2 = trap_frame->x2; + x3 = trap_frame->x3; + x4 = trap_frame->x4; + ret = (int)sys_ioctl((int)x0, (uint32_t)x1, x2, x3, x4); + break; + + case 20: + sys_sigreturn(); + break; + default: + printf("Unknown system call %p\r\n", NR_syscall); + while(1); + } + return ret; +} diff --git a/lab7/kernel/syscall_test.c b/lab7/kernel/syscall_test.c new file mode 100644 index 000000000..b5dd80c13 --- /dev/null +++ b/lab7/kernel/syscall_test.c @@ -0,0 +1,17 @@ +#include "types.h" +#include "debug/debug.h" +#include "asm.h" +#include "lib/print.h" +uint64_t sys_hello(uint64_t x0){ + LOG("Enter sys_hello"); + printf("CurrentEL: %x\r\n", get_currentEL()); + printf("DAIF: %x\r\n", get_DAIF()); + printf("SPSR_EL1: %p\r\n", (void*)get_SPSR_EL1()); + printf("SPSel: %p\r\n", (void*)get_SPSel()); + printf("SP_EL0: %p\r\n", (void*)get_SP_ELx(0)); + printf("ELR_EL1: %p\r\n", (void*)get_ELR_EL1()); + printf("ESR_EL1: %p\r\n", (void*)get_ESR_EL1()); + printf("SP : %p\r\n", (void*)get_SP()); + printf("\r\n"); + return x0; +} diff --git a/lab7/kernel/timer.c b/lab7/kernel/timer.c new file mode 100644 index 000000000..cd43b94f9 --- /dev/null +++ b/lab7/kernel/timer.c @@ -0,0 +1,100 @@ +#include "kernel/timer.h" + +static uint64_t jiffies = 0; +static struct list_head timer_list; + +/* + * We use core timer to update jiffies + */ +void enable_core_timer_irq(){ + IO_MMIO_write32(CORE0_TIMER_IRQ_CTRL, 2); +} +void disable_core_timer_irq(){ + IO_MMIO_write32(CORE0_TIMER_IRQ_CTRL, 0); +} + +void timer_softirq_callback(){ + struct list_head *head = &timer_list; + struct list_head *node; + timer_t* t; + + list_for_each(node, head){ + t = list_entry(node, timer_t, list); + t->ticks--; + if(t->ticks <= 0){ + list_del(node); + t->callback(t->data); + } + } +} + +void init_timer_list(void){ + INIT_LIST_HEAD(&timer_list); +} + +/** + * Timer with 10 microsecond resolution + * + * @param duration in microsecond + */ +void add_timer(timer_callback callback, uint8_t* data, uint64_t duration){ + if(duration == 0){ + callback(data); + return; + } + + timer_t* t = (timer_t*)simple_malloc(sizeof(timer_t)); + + t->ticks = duration / (1000 / HZ); + t->callback = callback; + t->data = data; + + disable_core_timer_irq(); + //critical section + list_add(&t->list, &timer_list); + enable_core_timer_irq(); +} + +void init_core_timer(){ + uint64_t freq; + + init_timer_list(); + set_CNTP_CTL_EL0(1); + freq = get_CNTFRQ_EL0(); + set_CNTP_TVAL_EL0(freq / HZ); + + + // lab5, user space want to access cpu timer register + uint64_t tmp; + asm volatile("mrs %0, cntkctl_el1" : "=r"(tmp)); + tmp |= 1; + asm volatile("msr cntkctl_el1, %0" : : "r"(tmp)); + + enable_core_timer_irq(); +} +void core_timer_irq_handler(){ + uint64_t freq; + struct task_struct* current = get_current(); + + freq = get_CNTFRQ_EL0(); + set_CNTP_TVAL_EL0(freq / HZ); + + jiffies += 1; + + // update task schedule info + if(current){ + current->sched_info.rticks++; + current->sched_info.counter--; + if(current->sched_info.counter <= 0){ + need_sched = 1; + } + } +} + +uint64_t inline get_jiffies(){ + return jiffies; +} + + + + diff --git a/lab7/lib/Makefile b/lab7/lib/Makefile new file mode 100644 index 000000000..328a22f1a --- /dev/null +++ b/lab7/lib/Makefile @@ -0,0 +1,36 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +LIBS = \ + print.o \ + string.o \ + list.o \ + cpio.o \ + simple_malloc.o \ + fdt_parse.o \ + asm.o \ + ring_buffer.o \ + bitops.o + + +all: $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $(OUTPUT)/$@ $^ -I$(HEADERS) + + + + +clean: + rm $(OUTPUT)/$(LIBS) diff --git a/lab7/lib/asm.c b/lab7/lib/asm.c new file mode 100644 index 000000000..e071c7a86 --- /dev/null +++ b/lab7/lib/asm.c @@ -0,0 +1,168 @@ +#include "types.h" +void local_irq_enable(){ + asm volatile("msr DAIFClr, 0xf"); +} + +void local_irq_disable(){ + asm volatile("msr DAIFSet, 0xf"); +} + +uint64_t local_irq_disable_save() { + volatile uint64_t daif; + asm volatile( + "mrs %0, DAIF\t\n" + "msr DAIFSet, 0xf" + :"=&r"(daif) + : + ); + + return daif; +} + +void local_irq_restore(uint64_t daif) { + asm volatile( + "msr DAIF, %0" + ::"r"(daif) + ); +} + +uint32_t get_currentEL(){ + uint64_t curEL = 0; + asm volatile("mrs %0, CurrentEL" + : "=&r" (curEL) + : + ); + return curEL >> 2; +} +uint64_t get_SP_ELx(uint32_t x){ + uint64_t sp = 0; + + switch(x){ + case 0: + asm volatile("mrs %0, SP_EL0" + : "=&r" (sp) + : + ); + break; + case 1: + asm volatile("mrs %0, SP_EL1" + : "=&r" (sp) + : + ); + break; + case 2: + asm volatile("mrs %0, SP_EL2" + : "=&r" (sp) + : + ); + break; + default: + break; + } + + + return sp; +} +uint64_t get_DAIF(){ + uint64_t daif; + asm volatile("mrs %0, DAIF" + : "=&r" (daif) + : + ); + return daif; +} +void set_DAIF(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr daif, x0" + : + :[n] "r" (n) + ); +} + +uint64_t get_SPSel(){ + uint64_t spsel = 0; + asm volatile("mrs %0, spsel" + : "=&r" (spsel) + : + ); + return spsel; +} +uint64_t get_ESR_EL1(){ + uint64_t esr_el1 = 0; + asm volatile("mrs %0, esr_el1" + : "=&r" (esr_el1) + : + ); + return esr_el1; +} +uint64_t get_SPSR_EL1(){ + uint64_t spsr_el1 = 0; + asm volatile("mrs %0, spsr_el1" + : "=&r" (spsr_el1) + : + ); + return spsr_el1; +} +uint64_t get_ELR_EL1(){ + uint64_t elr_el1 = 0; + asm volatile("mrs %0, elr_el1" + : "=&r" (elr_el1) + : + ); + return elr_el1; +} +uint64_t get_SP(){ + uint64_t sp = 0; + asm volatile("mov %0, sp" + : "=&r" (sp) + : + ); + return sp; +} +uint64_t get_CNTP_CTL_EL0(){ + uint64_t cntp_ctl_el0 = 0; + asm volatile("mrs %0, cntp_ctl_el0" + : "=&r" (cntp_ctl_el0) + : + ); + return cntp_ctl_el0; +} +void set_CNTP_CTL_EL0(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr cntp_ctl_el0, x0" + : + :[n] "r" (n) + ); +} +uint64_t get_CNTFRQ_EL0(){ + uint64_t cntfrq_el0 = 0; + asm volatile("mrs %0, cntfrq_el0" + : "=&r" (cntfrq_el0) + : + ); + return cntfrq_el0; +} + +void set_CNTP_TVAL_EL0(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr cntp_tval_el0, x0" + : + :[n] "r" (n) + ); +} +uint64_t get_CNTPCT_EL0(){ + uint64_t cntpct_el0 = 0; + asm volatile("mrs %0, cntpct_el0" + : "=&r" (cntpct_el0) + : + ); + return cntpct_el0; +} + +void set_tpidr_el1(uint64_t n){ + asm volatile("mov x0, %[n]\n\t" + "msr tpidr_el1, x0" + : + :[n] "r" (n) + ); +} diff --git a/lab7/lib/bitops.c b/lab7/lib/bitops.c new file mode 100644 index 000000000..ad1080455 --- /dev/null +++ b/lab7/lib/bitops.c @@ -0,0 +1,55 @@ +#include "lib/bitops.h" + +uint16_t ffs16(uint16_t val){ +// val should not be zero! +// The behavior is undefined when val is zer! + uint16_t num = 0; + if((val & 0xff) == 0){ + num += 8; + val >>= 8; + } + if((val & 0xf) == 0){ + num += 4; + val >>= 4; + } + if((val & 0x3) == 0){ + num += 2; + val >>= 2; + } + if((val & 0x1) == 0) + num += 1; + + return num; +} + +uint64_t ffs64(uint64_t val){ +// val should not be zero! +// The behavior is undefined when val is zer! + uint64_t num = 0; + if((val & 0xffffffff) == 0){ + num += 32; + val >>= 32; + } + if((val & 0xffff) == 0){ + num += 16; + val >>= 16; + } + if((val & 0xff) == 0){ + num += 8; + val >>= 8; + } + if((val & 0xf) == 0){ + num += 4; + val >>= 4; + } + + if((val & 0x3) == 0){ + num += 2; + val >>= 2; + } + + if((val & 0x1) == 0) + num += 1; + + return num; +} diff --git a/lab7/lib/cpio.c b/lab7/lib/cpio.c new file mode 100644 index 000000000..4474ac83b --- /dev/null +++ b/lab7/lib/cpio.c @@ -0,0 +1,61 @@ +#include "lib/cpio.h" + +uint32_t cpio_hex2dec(const char *s){ + uint32_t ret = 0; + for(uint32_t i = 0 ; i < 8 ; i++){ + ret = ret << 4; + ret = ret + hex2dec(s[i]); + } + return ret; +} + +void cpio_iter_parse(struct cpio_iter* iter, struct fentry* f){ + LOG("Enter cpio_iter_parse"); + size_t count = 0; + struct cpio_newc_header* header = (struct cpio_newc_header* )iter->cur; + + if(!memcpy(header->c_magic, "070701", 6)){ + LOG("CPIO PARSE ERROR!!!!"); + return; + } + + f->ino = cpio_hex2dec(header->c_ino); + f->mode = cpio_hex2dec(header->c_mode); + f->uid = cpio_hex2dec(header->c_uid); + LOG("f->uid: %u", f->uid); + f->gid = cpio_hex2dec(header->c_gid); + f->nlink = cpio_hex2dec(header->c_nlink); + f->mtime = cpio_hex2dec(header->c_mtime); + f->filesize = cpio_hex2dec(header->c_filesize); + LOG("f->filesize: %u", f->filesize); + f->devmajor = cpio_hex2dec(header->c_devmajor); + f->devminor = cpio_hex2dec(header->c_devminor); + f->rdevmajor = cpio_hex2dec(header->c_rdevmajor); + f->rdevminor = cpio_hex2dec(header->c_rdevminor); + f->namesize = cpio_hex2dec(header->c_namesize); + LOG("f->namesize: %u", f->namesize); + f->check = cpio_hex2dec(header->c_check); + count = count + sizeof(struct cpio_newc_header); + + f->filename = (char*)simple_malloc(f->namesize); + memcpy(f->filename, (uint8_t* )header + count, f->namesize); + LOG("get f->filename"); + count = ALIGN_UP(count + f->namesize, 4); + if(f->filesize > 0){ + f->data = (uint8_t*)simple_malloc(f->filesize); + memcpy(f->data, (uint8_t* )header + count, f->filesize); + } + LOG("get f->data"); + count = ALIGN_UP(count + f->filesize, 4); + iter->cur = iter->cur + count; + LOG("count: %u, iter->cur: %p", count, iter->cur); + LOG("Leave cpio_iter_parse"); +} + +void cpio_iter_init(struct cpio_iter* iter, void* addr){ + iter->cur = addr; +} +int cpio_is_tailer(struct fentry* f){ + return (strcmp(f->filename, "TRAILER!!!") == 0); +} + diff --git a/lab7/lib/fdt_parse.c b/lab7/lib/fdt_parse.c new file mode 100644 index 000000000..762563031 --- /dev/null +++ b/lab7/lib/fdt_parse.c @@ -0,0 +1,127 @@ +#include "lib/fdt_parse.h" + +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +static fdt_header header; +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = &header; + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) >> 2; + len += 2; +// printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + printf("Parsing error!!\n"); + while(1); + } + } +} +void fdt_parse_rsvmap(uint8_t* fdt, fdt_rsvmap_callback callback){ + uint64_t *mem_rsvmap; + uint64_t start, end; + uint64_t count = 0; + fdt_header * pheader = &header; + fdt_parse_header(fdt, pheader); + + mem_rsvmap = (uint64_t*)(fdt + pheader->off_mem_rsvmap); + do{ + start = bswap64(mem_rsvmap[count * 2]); + end = start + bswap64(mem_rsvmap[count * 2 + 1]); + if(end) + callback(start, end); + else + break; + count++; + }while(1); +} +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab7/lib/list.c b/lab7/lib/list.c new file mode 100644 index 000000000..6539320c1 --- /dev/null +++ b/lab7/lib/list.c @@ -0,0 +1,75 @@ +#include "lib/list.h" + +void INIT_LIST_HEAD(struct list_head* head){ + head->next = head; + head->prev = head; +} + +void list_add(struct list_head* node, struct list_head* head){ + struct list_head *next = head->next; + + next->prev = node; + head->next = node; + + node->next = next; + node->prev = head; +} + +void list_add_tail(struct list_head* node, struct list_head* head){ + struct list_head* tail = head->prev; + + tail->next = node; + head->prev = node; + + node->next = head; + node->prev = tail; +} + +void list_del(struct list_head* node){ + struct list_head* next = node->next; + struct list_head* prev = node->prev; + + next->prev = prev; + prev->next = next; +} +int list_empty(struct list_head* head){ + return (head->next == head); +} + +int list_is_last(struct list_head* node, struct list_head* head){ + return head->prev == node; +} + +int list_is_head(struct list_head* node, struct list_head* head){ + return head == node; +} + +void list_splice(struct list_head *list, struct list_head *head){ + struct list_head *head_first = head->next; + struct list_head *list_first = list->next; + struct list_head *list_last = list->prev; + + if (list_empty(list)) + return; + + head->next = list_first; + list_first->prev = head; + + list_last->next = head_first; + head_first->prev = list_last; +} + +void list_splice_tail(struct list_head *list, struct list_head *head){ + struct list_head *head_last = head->prev; + struct list_head *list_first = list->next; + struct list_head *list_last = list->prev; + + if (list_empty(list)) + return; + + head->prev = list_last; + list_last->next = head; + + list_first->prev = head_last; + head_last->next = list_first; +} diff --git a/lab7/lib/print.c b/lab7/lib/print.c new file mode 100644 index 000000000..9e64ca936 --- /dev/null +++ b/lab7/lib/print.c @@ -0,0 +1,111 @@ +#include "lib/print.h" + +int32_t aio_print(char* fmt, ...){ + +} +int32_t printf(char *fmt, ...){ + uint32_t uval; + int32_t val; + int64_t lval; + char str[64], ch; + char* p, *s; + void* addr; + volatile int32_t count = 0; + va_list ap; + + va_start(ap, fmt); + + while(*fmt){ + char c = *fmt++; + if(c == '%'){ + c = *fmt++; + switch(c){ + case 'u': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'd': + val = va_arg(ap, int); + itoa(val, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'l': + lval = va_arg(ap, int64_t); + ltoa(lval, str, 10); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case 'c': + ch = va_arg(ap, int); + mini_uart_write(ch); + count++; + break; + case 'p': + addr = va_arg(ap, void*); + ultoa((uint64_t)addr, str, 16); + + mini_uart_write('0'); + mini_uart_write('x'); + count += 2; + + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + + break; + case 'x': + uval = va_arg(ap, uint32_t); + ultoa(uval, str, 16); + p = str; + while(*p){ + mini_uart_write(*p++); + count++; + } + + break; + case 's': + s = va_arg(ap, char*); + p = s; + while(*p){ + mini_uart_write(*p++); + count++; + } + break; + case '%': + mini_uart_write('%'); + count++; + default: + mini_uart_write('%'); + mini_uart_write(c); + count += 2; + } + }else{ + mini_uart_write(c); + count++; + } + } + va_end(ap); + return count; +} +int32_t putchar(uint8_t ch){ + mini_uart_write(ch); + return ch; +} +int32_t getchar(){ + return mini_uart_aio_read(); +} diff --git a/lab7/lib/ring_buffer.c b/lab7/lib/ring_buffer.c new file mode 100644 index 000000000..1f7e750b1 --- /dev/null +++ b/lab7/lib/ring_buffer.c @@ -0,0 +1,117 @@ +#include "lib/ring_buffer.h" + +ring_buffer* create_simple_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)simple_malloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)simple_malloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + tmp->count = 0; + return tmp; +} + +// This function can only be used after initializing mm +ring_buffer* create_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)kmalloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)kmalloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + tmp->count = 0; + return tmp; +} + +void free_ring_buf(ring_buffer* rbuf){ + kfree(rbuf->buf); + kfree(rbuf); +} + +uint8_t ring_buf_is_empty(ring_buffer* rbuf){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + if(rbuf->head == rbuf->tail){ + local_irq_restore(daif); + return 1; + } + local_irq_restore(daif); + return 0; +} + +uint8_t ring_buf_is_full(ring_buffer* rbuf){ + volatile uint64_t daif; + if((rbuf->tail + 1) % (rbuf->size + 1) == rbuf->head){ + local_irq_disable_save(daif); + return 1; + } + local_irq_restore(daif); + return 0; +} + +size_t ring_buf_write(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count += count; + local_irq_restore(daif); + return count; +} + +size_t ring_buf_write_unsafe(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count += count; + return count; +} + +size_t ring_buf_read(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count -= count; + local_irq_restore(daif); + return count; +} + +size_t ring_buf_read_unsafe(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + rbuf->count -= count; + return count; +} + +size_t ring_buf_get_len(ring_buffer* rbuf){ + volatile uint64_t daif; + size_t ret; + + daif = local_irq_disable_save(); + ret = rbuf->count; + local_irq_restore(daif); + + return ret; +} diff --git a/lab7/lib/simple_malloc.c b/lab7/lib/simple_malloc.c new file mode 100644 index 000000000..f2f67ac0a --- /dev/null +++ b/lab7/lib/simple_malloc.c @@ -0,0 +1,18 @@ +#include "lib/simple_malloc.h" +#include "mm/mmu.h" + +extern int __heap_start; +static struct malloc_state mstate = { + .last_remainder = (uint8_t*)&__heap_start +}; + + +void* simple_malloc(size_t size){ + void* chunk = mstate.last_remainder; + size_t nb = req2size(size); + mstate.last_remainder = mstate.last_remainder + nb; + return chunk; +} +void* simple_malloc_get_remainder(){ + return mstate.last_remainder; +} diff --git a/lab7/lib/string.c b/lab7/lib/string.c new file mode 100644 index 000000000..3ab9d9ce6 --- /dev/null +++ b/lab7/lib/string.c @@ -0,0 +1,260 @@ +#include "lib/string.h" +#include "types.h" +char *int_table = "0123456789"; +char *hex_table = "0123456789abcdef"; +char * itoa(int32_t value, char* str, uint32_t base){ + char buf[32]; + uint32_t val; + volatile int i = 0, j = 0; + + switch(base){ + case 16: + val = (uint32_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} + +char * utoa(uint32_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint32_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} +char * ltoa(int64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val; + + switch(base){ + case 16: + val = (uint64_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +char * ultoa(uint64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +uint64_t atoul(const char* str){ + uint64_t val = 0; + const char* ps = str; + while(*ps){ + val *= 10; + val += (*ps - '0'); + ps++; + } + return val; +} +int32_t strcmp(char* str1, char* str2){ + do{ + if(*str1 > *str2) return 1; + else if(*str1 < *str2) return -1; + str1++;str2++; + }while(*str1 != '\0' || *str2 != '\0'); + return 0; +} +size_t strlen(const char* s){ + size_t i = 0; + while(s[i++]); + i--; + return i; +} +// Do not maninpulate data by using (uint64*) or it may sometimes trigger alignment issue +// Manipulating data by using (uint8*) is best choice in this homework +void* memcpy(void* dst, const void* src, size_t n){ + const uint8_t* ps = src; + uint8_t *pd = dst; + size_t i; + for(i = 0 ; i < n ; i++) pd[i] = ps[i]; + return dst; +} +char *strcpy(char *dest, const char *src){ + memcpy(dest, src, strlen(src) + 1); +} +void* memset(void* s, int c, size_t n){ + uint8_t* ps = s; + for(size_t i = 0 ; i < n ; i++) ps[i] = c; + return s; +} + +int32_t memcmp(void* m1, const void* m2, size_t n){ + size_t i = 0; + char *s1 = m1; + const char* s2 = m2; + while(i < n){ + if(s1[i] > s2[i]) return 1; + else if(s1[i] < s2[i]) return -1; + i++; + } + return 0; +} + +uint8_t hex2dec(char hex){ + if('0' <= hex && hex <= '9'){ + return (uint8_t)hex - (uint8_t)'0'; + }else if('a' <= hex && hex <= 'f'){ + return (uint8_t)hex - (uint8_t)'a' + 10; + }else{ + return (uint8_t)hex - (uint8_t)'A' + 10; + } +} +uint8_t _is_delim(char c,const char* delim){ + uint32_t i = 0; + while(delim[i]){ + if(c == delim[i++]) return 1; + } + return 0; +} +char* _next_token(char* s,const char* delim){ + char* pos = s; + + do{ + if(*pos == '\0'){ + return NULL; + }else if(_is_delim(*pos, delim)){ + *pos = '\0'; + return pos + 1; + } + pos++; + }while(1); +} +char* _skip_delim(char* s,const char* delim){ + char* pos = s; + while(*pos != '\0' && _is_delim(*pos, delim)) pos++; + return pos; +} +char* strtok(char* s,const char* delim){ + static char *pos = NULL; + char *tmp_pos = NULL; + if(s == NULL){ + if(pos == NULL || *pos =='\0') return NULL; + + tmp_pos = pos = _skip_delim(pos, delim); + if(*pos != '\0'){ + pos = _next_token(pos, delim); + }else{ + pos = tmp_pos = NULL; + } + }else{ + if(*s == '\0') return NULL; + + pos = s; + tmp_pos = pos = _skip_delim(pos, delim); + if(*pos != '\0'){ + pos = _next_token(pos, delim); + }else{ + pos = tmp_pos = NULL; + } + } + return tmp_pos; +} diff --git a/lab7/mm/Makefile b/lab7/mm/Makefile new file mode 100644 index 000000000..47bcf9c04 --- /dev/null +++ b/lab7/mm/Makefile @@ -0,0 +1,28 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + page_alloc.o \ + slab.o \ + mmu.o \ + mm.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab7/mm/mm.c b/lab7/mm/mm.c new file mode 100644 index 000000000..6a7cdd3c4 --- /dev/null +++ b/lab7/mm/mm.c @@ -0,0 +1,201 @@ +#include "mm/mm.h" +#include "mm/mmu.h" + +extern int __heap_start; +extern int __kernel_image_start; +extern int __kernel_image_end; +extern int __kernel_image_end; +extern int __EL1_stack_size; +extern int __EL1_stack; + +struct list_head mem_rsvmap; +struct list_head mem_unusedmap; +struct mem_node memory_node; +struct page *mem_map; + +void reserve_memory(uint64_t start, uint64_t end){ + struct list_head *node; + struct list_head *head; + struct mem_block *mb = simple_malloc(sizeof(struct mem_block)); + struct mem_block *tmp_mb; + + start = ALIGN_DOWN(start, PAGE_SIZE); + end = ALIGN_UP(end, PAGE_SIZE); + mb->start = start; + mb->end = end; + list_for_each(node, &mem_rsvmap){ + tmp_mb = list_entry(node, struct mem_block, list); + if(tmp_mb->start > start){ + head = node->prev; + list_add(&mb->list, head); + break; + } + } + + if(list_is_head(node, &mem_rsvmap)){ + list_add(&mb->list, node->prev); + } +} + +size_t get_reserved_size(){ + uint64_t start, end; + struct list_head* node; + struct mem_block* mb; + size_t size = 0; + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + start = mb->start; + end = mb->end; + size += (end - start); + } + return size; +} + +size_t get_unused_size(){ + uint64_t start, end; + struct list_head* node; + struct mem_block* mb; + size_t size = 0; + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + start = mb->start; + end = mb->end; + size += (end - start); + LOG("unused map: start: %p, end: %p", start, end); + } + return size; +} + +uint64_t _reserve_dtb(void *dtb){ + fdt_header header; + fdt_header *pheader = &header; + uint64_t start, end; + size_t size = 0; + + fdt_parse_header((uint8_t*)dtb, pheader); + size = ALIGN_UP(pheader->totalsize, PAGE_SIZE); + + start = (uint64_t)dtb; + end = start + size; + reserve_memory(start, end); +} + +void* _reserve_cpio(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + static uint64_t start, end; + static uint8_t found_start = 0, found_end = 0; + if(prop != NULL){ + if(strcmp(prop->name, "linux,initrd-start") == 0){ + start = bswap32(*(uint32_t*)prop->value); + found_start = 1; + } + if(strcmp(prop->name, "linux,initrd-end") == 0){ + end = bswap32(*(uint32_t*)prop->value); + found_end = 1; + } + if(found_start && found_end){ + found_start = found_end = 0; + reserve_memory(start, end); + } + } +} + +void _create_memory_rsvmap(void *dtb){ + uint64_t start, end; + // reseved memory in dtb + fdt_parse_rsvmap((uint8_t*)dtb, reserve_memory); + + // reverse memory for kernel image + reserve_memory((uint64_t)&__kernel_image_start - UPPER_ADDR_SPACE_BASE, (uint64_t)&__kernel_image_end - UPPER_ADDR_SPACE_BASE); + + // reserve memory for stack + reserve_memory((uint64_t)&__EL1_stack - (uint64_t)&__EL1_stack_size - UPPER_ADDR_SPACE_BASE, (uint64_t)&__EL1_stack - UPPER_ADDR_SPACE_BASE); + + // reserve memory for device tree + _reserve_dtb((void*)((uint64_t)dtb - UPPER_ADDR_SPACE_BASE)); + + // reserve memory for cpio + fdt_parser(dtb, _reserve_cpio); + + // Create struct page table for mapping every physical frame to it + mem_map = simple_malloc(sizeof(struct page) * (memory_node.end >> PAGE_SHIFT)); + + // reserve memory for simple memory allocator + start = (uint64_t)&__heap_start - UPPER_ADDR_SPACE_BASE; + end = ALIGN_UP((uint64_t)simple_malloc_get_remainder() - UPPER_ADDR_SPACE_BASE, PAGE_SIZE) + 8 * PAGE_SIZE; + reserve_memory(start, end); +} + +void _create_memory_unusedmap(){ + uint64_t unused_start = 0; + struct list_head *node; + struct mem_block *mb; + struct mem_block *tmp_mb; + + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + if(unused_start < mb->start){ + tmp_mb = (struct mem_block*)simple_malloc(sizeof(struct mem_block)); + + tmp_mb->start = unused_start; + tmp_mb->end = mb->start; + list_add_tail(&tmp_mb->list, &mem_unusedmap); + INFO("unused map: start = %p, end = %p", tmp_mb->start, tmp_mb->end); + } + unused_start = mb->end; + } + + if(unused_start < memory_node.end){ + tmp_mb = (struct mem_block*)simple_malloc(sizeof(struct mem_block)); + tmp_mb->start = unused_start; + tmp_mb->end = memory_node.end; + list_add_tail(&tmp_mb->list, &mem_unusedmap); + } +} + +void* _get_memory_node(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + static int found_memory_node = 0; + uint32_t* pw; + if(node != NULL && strcmp(node->name, "memory@0") == 0){ + memory_node.name = "memory@0"; + found_memory_node = 1; + } + if(found_memory_node && prop != NULL && strcmp(prop->name, "reg") == 0){ + pw = (uint32_t*)prop->value; + memory_node.start = bswap32(pw[0]); + memory_node.end = memory_node.start + bswap32(pw[1]); + found_memory_node = 0; + } +} + + +void mm_init(void *dtb){ + INFO("Init mm subsystem.."); + // initialize mm's global variable + INIT_LIST_HEAD(&mem_rsvmap); + INIT_LIST_HEAD(&mem_unusedmap); + fdt_parser((uint8_t*)dtb, _get_memory_node); + + _create_memory_rsvmap(dtb); + _create_memory_unusedmap(); + + INFO("Memory node: %s, size: %p", memory_node.name, memory_node.end - memory_node.start); + INFO("Memory reserved size: %p", get_reserved_size()); + INFO("Memory unused size : %p", get_unused_size()); + + // initialize buddy system + buddy_init(); + + print_buddy_statistics(); + + /* if(debug) + debug_slab();*/ + + kmalloc_init(); + +/* if(debug){ + debug_kmalloc(); + //debug_buddy(); + print_buddy_statistics(); + }*/ + +} diff --git a/lab7/mm/mmu.c b/lab7/mm/mmu.c new file mode 100644 index 000000000..2e25f6f75 --- /dev/null +++ b/lab7/mm/mmu.c @@ -0,0 +1,399 @@ +#include "mm/mmu.h" +#include "mm/mm.h" +#include "kernel/fault.h" +#include "kernel/sched/task.h" +#include "kernel/signal.h" + +extern int __reserved_page_table_start, __reserved_page_table_end; +extern int __PGD_start, __PGD_end; +extern int __PUD_start, __PUD_end; +extern int __PMD_start, __PMD_end; +extern int __PTE_start, __PTE_end; +extern struct mem_node memory_node; + +void page_init(){ + uint64_t daif = local_irq_disable_save(); + uint64_t pgt_start = (uint64_t)&__reserved_page_table_start; + uint64_t pgt_end = (uint64_t)&__reserved_page_table_end; + uint64_t pgd = (uint64_t)&__PGD_start; + uint64_t pud = (uint64_t)&__PUD_start; + uint64_t pmd = (uint64_t)&__PMD_start; + uint64_t pte = (uint64_t)&__PTE_start; + pgdval_t* tmp_pgd_e = (pgdval_t*)pgd; + pudval_t* tmp_pud_e = (pudval_t*)pud; + pmdval_t* tmp_pmd_e = (pmdval_t*)pmd; + pteval_t* tmp_pte_e = (pteval_t*)pte; + uint64_t mem_size = ALIGN_UP(memory_node.end - memory_node.start, PAGE_SIZE); + uint64_t max_page_num = mem_size / PAGE_SIZE; + + pgd = virt_to_phys(pgd); + pud = virt_to_phys(pud); + pmd = virt_to_phys(pmd); + pte = virt_to_phys(pte); + + // memset((void*)pgt_start, 0, pgt_end - pgt_start); + + INFO("mem_size: %p", mem_size); + INFO("max number of page: %p", max_page_num); + + INFO("Initialize 4-level page table for upper address space"); + + INFO("level 4 page table at %p...", tmp_pte_e); + for(uint64_t i = 0 ; i < max_page_num ; i++){ + pte_set(tmp_pte_e, VM_PTE_NORMAL_ATTR | (i * PAGE_SIZE)); + tmp_pte_e++; + } + + for(uint64_t i = max_page_num ; i < 2 * 512 * 512; i++){ + pte_set(tmp_pte_e, VM_PTE_DEVICE_ATTR | (i * PAGE_SIZE)); + tmp_pte_e++; + } + + INFO("level 3 page table %p...", tmp_pmd_e); + for(uint64_t i = 0 ; i < 2 * 512 ; i++){ + pmd_set(tmp_pmd_e, VM_PMD_ATTR | (pte + i * PAGE_SIZE)); + tmp_pmd_e++; + } + + INFO("level 2 page table %p...", tmp_pud_e); + for(uint64_t i = 0 ; i < 2 ; i++){ + pud_set(tmp_pud_e, VM_PUD_ATTR | (pmd + i * PAGE_SIZE)); + tmp_pud_e++; + } + + INFO("level 1 page table %p...", tmp_pgd_e); + asm volatile( + "dsb ish\n\t" // ensure write has completed + "tlbi vmalle1is\n\t" // invalidate all TLB entries + "dsb ish\n\t" // ensure completion of TLB invalidatation + "isb\n\t" // clear pipeline + ); + local_irq_restore(daif); + INFO("finish"); +} + +void mappages(pgdval_t* pgd, uint64_t va, uint64_t pa, uint64_t size, uint64_t prot, uint64_t set_attr){ + //LOG("mappages start"); + uint64_t vstart, vend; + uint64_t pgtable = 0; + pudval_t* pgd_e; + pudval_t* pud_e; + pmdval_t* pmd_e; + pteval_t* pte_e; + size = ALIGN_UP(size, PAGE_SIZE); + //LOG("mappages(%p, %p, %p, %l, %p)", pgd, va, pa, size, prot); + for(vstart = va, vend = va + size ; vstart != vend ; vstart += PAGE_SIZE){ + // LOG("physical addr: %p", pa); + pgd_e = pgd_offset(pgd, vstart); + if(pgd_none(*pgd_e)){ + pgtable = virt_to_phys(calloc_page()); + pgd_set(pgd_e, PGD_TYPE_TABLE | pgtable); + LOG("pgd_e: %p, *pgd_e = %p\r\n",pgd_e, *pgd_e); + } + + pud_e = pud_offset(pgd_e, vstart); + if(pud_none(*pud_e)){ + pgtable = virt_to_phys(calloc_page()); + pud_set(pud_e, PUD_TYPE_TABLE | pgtable); + LOG("pud_e: %p, *pud_e = %p\r\n",pud_e, *pud_e); + } + + pmd_e = pmd_offset(pud_e, vstart); + if(pmd_none(*pmd_e)){ + pgtable = virt_to_phys(calloc_page()); + pmd_set(pmd_e, PMD_TYPE_TABLE | pgtable); + LOG("pmd_e: %p, *pmd_e = %p\r\n",pmd_e, *pmd_e); + } + + pte_e = pte_offset(pmd_e, vstart); + //printf("pte_index(%p) = %p\r\n", vstart, pte_index(vstart)); + + + if(set_attr){ + // only set attribute + if(!pte_none(*pte_e)){ + pte_set(pte_e, prot | pte_val(pte_e)); + } + }else{ + if(!pte_none(*pte_e)){ + INFO("error: try to overwrite pte"); + while(1); + }else{ + pte_set(pte_e, prot | PAGE_ATTR_AF | (pa & PHYS_ADDR_MASK)); + } + } + //LOG("pte_e: %p, *pte_e = %p\r\n",pte_e, *pte_e); + pa += PAGE_SIZE; + } + //LOG("mappages end"); +} + +void dup_pages(pgdval_t* dst_pgd, pgdval_t* src_pgd, uint64_t va, uint64_t size, uint64_t prot){ + LOG("dup_pages start"); + uint64_t vstart, vend; + uint64_t pgtable = 0; + pudval_t* tmp_pgd_e, *pgd_e; + pudval_t* tmp_pud_e, *pud_e; + pmdval_t* tmp_pmd_e, *pmd_e; + pteval_t* tmp_pte_e, *pte_e; + size = ALIGN_UP(size, PAGE_SIZE); + LOG("dup_pages(%p, %p, %p, %p, %p)", dst_pgd, src_pgd, va, size, prot); + for(vstart = va, vend = va + size ; vstart != vend ; vstart += PAGE_SIZE){ + tmp_pgd_e = pgd_offset(src_pgd, vstart); + pgd_e = pgd_offset(dst_pgd, vstart); + if(pgd_none(*pgd_e)){ + pgtable = virt_to_phys(calloc_page()); + pgd_set(pgd_e, (*tmp_pgd_e & ~PHYS_ADDR_MASK) | pgtable); + LOG("tmp_pgd_e: %p, *tmp_pgd_e = %p",tmp_pgd_e, *tmp_pgd_e); + LOG("pgd_e: %p, *pgd_e: %p",pgd_e, *pgd_e); + } + + + tmp_pud_e = pud_offset(tmp_pgd_e, vstart); + pud_e = pud_offset(pgd_e, vstart); + if(pud_none(*pud_e)){ + pgtable = virt_to_phys(calloc_page()); + pud_set(pud_e, (*tmp_pud_e & ~PHYS_ADDR_MASK) | pgtable); + LOG("tmp_pud_e: %p, *tmp_pud_e = %p",tmp_pud_e, *tmp_pud_e); + LOG("pud_e: %p, *pud_e: %p",pud_e, *pud_e); + + } + + tmp_pmd_e = pmd_offset(tmp_pud_e, vstart); + pmd_e = pmd_offset(pud_e, vstart); + if(pmd_none(*pmd_e)){ + pgtable = virt_to_phys(calloc_page()); + pmd_set(pmd_e, (*tmp_pmd_e & ~PHYS_ADDR_MASK) | pgtable); + LOG("tmp_pmd_e: %p, *tmp_pmd_e = %p",tmp_pmd_e, *tmp_pmd_e); + LOG("pmd_e: %p, *pmd_e: %p",pmd_e, *pmd_e); + } + + tmp_pte_e = pte_offset(tmp_pmd_e, vstart); + if(!pte_none(*tmp_pte_e)){ + // Since we have implement demand paging, sometimes page is not exist in memory + pte_e = pte_offset(pmd_e, vstart); + pte_set(pte_e, pte_val(tmp_pte_e) | prot); + // add 1 to page reference count + pte_reuse(pte_e); + LOG("tmp_pte_e: %p, *tmp_pte_e = %p",tmp_pte_e, *tmp_pte_e); + LOG("pte_e: %p, *pte_e: %p, pte_ref_cnt(%p) = %p ",pte_e, *pte_e, pte_e, pte_ref_cnt(pte_e)); + } + } + LOG("dup_pages end"); +} +void free_one_pte(pteval_t* pte){ + //LOG("free_one_pte(%p)", pte); + pteval_t* pte_e = pte; + void* page_frame; + for(uint64_t i = 0 ; i < 512 ; i++){ + if(!pte_none(pte_e[i])){ + page_frame = (void*)phys_to_virt(pte_e[i] & PHYS_ADDR_MASK); + //LOG("free page frame: %p", page_frame); + free_page(page_frame); + } + } + free_page(pte); +} + +void free_one_pmd(pmdval_t* pmd){ + //LOG("free_one_pmd(%p)", pmd); + pmdval_t* pmd_e = pmd; + pteval_t* pte; + for(uint64_t i = 0 ; i < 512 ; i++){ + if(!pmd_none(pmd_e[i])){ + pte = (pteval_t*)phys_to_virt(pmd_e[i] & PHYS_ADDR_MASK); + free_one_pte(pte); + } + } + free_page(pmd); +} + +void free_one_pud(pudval_t* pud){ + //LOG("free_one_pud(%p)", pud); + pudval_t* pud_e = pud; + pmdval_t* pmd; + for(uint64_t i = 0 ; i < 512 ; i++){ + if(!pud_none(pud_e[i])){ + pmd = (pmdval_t*)phys_to_virt(pud_e[i] & PHYS_ADDR_MASK); + free_one_pmd(pmd); + } + } + free_page(pud); +} + +void free_one_pgd(pgdval_t* pgd){ + //LOG("free_one_pgd(%p)", pgd); + pgdval_t* pgd_e = pgd; + pudval_t* pud; + for(uint64_t i = 0 ; i < 512 ; i++){ + if(!pgd_none(pgd_e[i])){ + pud = (pudval_t*)phys_to_virt(pgd_e[i] & PHYS_ADDR_MASK); + free_one_pud(pud); + } + } + free_page(pgd); +} +pteval_t* get_pte(pgdval_t* pgd, uint64_t addr){ + uint64_t pgtable; + pudval_t* pgd_e; + pudval_t* pud_e; + pmdval_t* pmd_e; + pteval_t* pte_e; + + pgd_e = pgd_offset(pgd, addr); + if(pgd_none(*pgd_e)){ + pgtable = virt_to_phys(calloc_page()); + pgd_set(pgd_e, PGD_TYPE_TABLE | pgtable); + LOG("pgd_e: %p, *pgd_e = %p\r\n",pgd_e, *pgd_e); + } + + pud_e = pud_offset(pgd_e, addr); + if(pud_none(*pud_e)){ + pgtable = virt_to_phys(calloc_page()); + pud_set(pud_e, PUD_TYPE_TABLE | pgtable); + LOG("pud_e: %p, *pud_e = %p\r\n",pud_e, *pud_e); + } + + pmd_e = pmd_offset(pud_e, addr); + if(pmd_none(*pmd_e)){ + pgtable = virt_to_phys(calloc_page()); + pmd_set(pmd_e, PMD_TYPE_TABLE | pgtable); + LOG("pmd_e: %p, *pmd_e = %p\r\n",pmd_e, *pmd_e); + } + + pte_e = pte_offset(pmd_e, addr); + return pte_e; +} + +void free_page_table(pgdval_t* pgd){ + LOG("free_page_table(%p)", pgd); + free_one_pgd(pgd); +} + +uint64_t do_file_page(pteval_t* pte_e, struct mm_struct* mm, struct vm_area_struct* vma, uint64_t addr, uint64_t vm_flags){ + //INFO("start do_file_fault, page ref count: %p, value of pte: %p", pte_ref_cnt(pte_e), pte_val(pte_e)); + uint64_t offset = addr - vma->vm_start; + char* filename = vma->filename; + uint8_t* page; + + page = alloc_page(); + initrdfs_loadfile(filename, page, offset, PAGE_SIZE); + mappages(mm->pgd, addr, virt_to_phys(page), PAGE_SIZE, VM_PTE_USER_ATTR, 0); + + //INFO("end do_file_fault page ref count: %p, value of pte: %p", pte_ref_cnt(pte_e), pte_val(pte_e)); + return VM_FAULT_NONE; +} + +uint64_t do_anonymous_page(pteval_t* pte_e, struct mm_struct* mm, struct vm_area_struct* vma, uint64_t addr){ + uint64_t page_frame; + if(vma->type == VMA_VC_RAM){ + // identity mapping + pte_set(pte_e, addr | VM_PTE_USER_ATTR); + }else{ + page_frame = virt_to_phys(calloc_page()); + mappages(mm->pgd, addr, page_frame, PAGE_SIZE, VM_PTE_USER_ATTR, 0); + } + return VM_FAULT_NONE; +} + +uint64_t do_wp_page(pteval_t* pte_e, struct mm_struct* mm, struct vm_area_struct* vma, uint64_t addr){ + struct page* page = pte_page(pte_e); + uint8_t * old_page, * new_page; + uint64_t new_page_frame, orig_attr; + + INFO("start do_wp_page, page ref count: %p, value of pte: %p", pte_ref_cnt(pte_e), pte_val(pte_e)); + if(pte_ref_cnt(pte_e) == 1){ + pte_set(pte_e, pte_val(pte_e) & ~PAGE_ATTR_RDONLY); + }else{ + INFO("start COW"); + old_page = page_to_virt(page); + new_page = alloc_page(); + new_page_frame = virt_to_phys(new_page); + orig_attr = pte_val(pte_e) & ~PAGE_ATTR_RDONLY & ~PHYS_ADDR_MASK; + + memcpy(new_page, old_page, PAGE_SIZE); + pte_set(pte_e, orig_attr | new_page_frame); + free_page(old_page); + } + INFO("end do_wp_page page ref count: %p, value of pte: %p", pte_ref_cnt(pte_e), pte_val(pte_e)); + return VM_FAULT_NONE; +} + +uint64_t handle_mm_fault(struct mm_struct* mm, struct vm_area_struct* vma, uint64_t far, uint64_t vm_flags){ + uint64_t addr = ALIGN_DOWN(far, PAGE_SIZE); + pteval_t *pte_e = get_pte(mm->pgd, addr); + uint64_t ret; + if(pte_none(*pte_e)){ + // page frame does not exist in memory + if(vma->type == VMA_FILE){ + // handle file mapping page frame + ret = do_file_page(pte_e, mm ,vma, addr, vm_flags); + }else{ + ret = do_anonymous_page(pte_e, mm, vma, addr); + } + printf("%l: [Translation fault]: %p\r\n",get_current()->thread_info.pid, far); + }else{ + // page frame exists in memory + // copy on write + if(vm_flags & VMA_PROT_WRITE && !pte_writable(pte_e)){ + ret = do_wp_page(pte_e, mm, vma, addr); + printf("%l: [COPY ON WRITE]: %p\r\n",get_current()->thread_info.pid, far); + }else{ + // which kind of situation will lead execution flow to here??? + printf("[Unknown MMU fault]: %p\r\n", far); + INFO("vm_flags: %p, *pte_e: %p\r\n", vm_flags, *pte_e); + while(1); + } + } + return ret; +} + +uint64_t do_page_fault(uint64_t esr, uint64_t far){ + struct vm_area_struct* vma; + struct task_struct* current = get_current(); + uint32_t ec = esr >> 26; + uint64_t vm_flags = 0; + if(ec == FAULT_INSTR_ABORT_LOW_EL){ + vm_flags |= VMA_PROT_EXEC; + }else{ + // get WnR ( wirte not read ) bit + vm_flags |= (esr & (1 << 6)) ? VMA_PROT_WRITE : VMA_PROT_READ; + } + + //check if far is in user space + //INFO("far: %p", far); + if(far >= VM_USER_SPACE){ + return VM_FAULT_BADACCESS; + } + // check if the far is in mm + vma = find_vma(current->mm, far); + if(vma == NULL){ + // access invalid address + return VM_FAULT_BADMAP; + } + // check if proccess has permission + if(!(vma->vm_flags & vm_flags)){ + return VM_FAULT_BADACCESS; + } + + return handle_mm_fault(current->mm, vma, far, vm_flags); +} +void do_mem_abort(uint64_t esr, uint64_t far){ + uint64_t fault; + // IFSC: instruct fault status code + // DFSC: data fault status code + uint8_t dfsc = esr & 0b111111; + if(dfsc == 8 || dfsc == 12){ + printf("unkown memory fault\r\n"); + while(1); + }else if(dfsc >= 4 && dfsc <= 15){ + fault = do_page_fault(esr, far); + } + if(fault != VM_FAULT_NONE){ + // send signal to notify proccess that MMU error occess + LOG("esr: %p, far: %p, elr_el1: %p", esr, far, ((struct trap_frame*)get_trap_frame(get_current()))->elr_el1); + send_signal(get_current()->thread_info.pid, SIG_SIGSEGV); + } + return; +} + diff --git a/lab7/mm/page_alloc.c b/lab7/mm/page_alloc.c new file mode 100644 index 000000000..73de432f8 --- /dev/null +++ b/lab7/mm/page_alloc.c @@ -0,0 +1,410 @@ +#include "mm/page_alloc.h" +static struct buddy_system buddy; +extern struct mem_node memory_node; +void _init_mem_map(){ + struct list_head *node; + struct mem_block *mb; + uint64_t start_pfn, end_pfn, size; + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + + start_pfn = virt_to_pfn(mb->start + UPPER_ADDR_SPACE_BASE); + end_pfn = virt_to_pfn(mb->end + UPPER_ADDR_SPACE_BASE); + size = (end_pfn - start_pfn) * sizeof(struct page); + + memset(&mem_map[start_pfn], '\0', size); + } + + list_for_each(node, &mem_rsvmap){ + mb = list_entry(node, struct mem_block, list); + + start_pfn = virt_to_pfn(mb->start + UPPER_ADDR_SPACE_BASE); + end_pfn = virt_to_pfn(mb->end + UPPER_ADDR_SPACE_BASE); + for(uint64_t i = start_pfn ; i < end_pfn ; i++){ + memset(&mem_map[i], '\0', sizeof(struct page)); + mem_map[i].type = PAGE_TYPE_RESERVED; + } + } +} + +void __free_pages(struct page* page, uint32_t order){ + volatile uint64_t daif; + struct page* end_page = page + (1 << order); + + // initialize buddy group leader and add it to free list + page->order = order; + list_add(&page->list, &buddy.free_lists[order].list); + buddy.free_lists[order].count++; + + // initialize buddy group members + + for(struct page* p = page + 1 ; p < end_page ; p++){ + p->order = BUDDY_GROUP_MEMBER; + } +} + +void _free_pages_memory(uint64_t start, uint64_t end){ + // start and end is page frame number ( pfn ) + uint64_t order; + while(start < end){ + order = min(BUDDY_MAX_ORDER - 1, _buddy_ffs(start)); + + // decrease the order if last page's pfn in buddy is larger than end + while(start + (1 << order) > end) order--; + + __free_pages(&mem_map[start], order); + start += (1 << order); + } +} + +void _free_pages(struct page* page, uint32_t order){ + struct page* buddy_page; + uint64_t pfn = page_to_pfn(page); + uint64_t buddy_pfn; + + if(PAGE_IS_RESERVED(page)){ + INFO("Error: _free_pages(%u) try to free reserved pfn %p", order, pfn); + } + // check the order of page + if(BUDDY_IS_FREED(page)){ + INFO("Error: _free_pages(%u) try to free freed pfn %p", order, pfn); + return; + } + if(order > _buddy_ffs(pfn)){ + INFO("Error: _free_pages(%u) try to free pfn %p", order, pfn); + return; + } + + while(order < BUDDY_MAX_ORDER - 1){ + buddy_pfn = find_buddy_pfn(pfn, order); + buddy_page = pfn_to_page(buddy_pfn); + + if(!PAGE_IS_RESERVED(buddy_page) && BUDDY_IS_FREED(buddy_page) && buddy_page->order == order){ + // Check if buddy is not reserved and freed + LOG("%p is buddy of %p in order %u free list and it can be merged", pfn_to_virt(buddy_pfn), pfn_to_virt(pfn), order); + list_del(&buddy_page->list); + buddy.free_lists[order].count--; + }else{ + break; + } + + pfn = pfn & ~(1 << order); + page = pfn_to_page(pfn); + order++; + } + + LOG("Merge %p into order %u free list ", pfn_to_virt(pfn), order); + __free_pages(page, order); + LOG("end merge pages"); +} + +// free 2^order pages +void free_pages(void* addr, uint32_t order){ + LOG("_free_pages(%p, %u)",addr, order); + volatile uint64_t daif; + uint64_t pfn = virt_to_pfn(addr); + struct page *page; + if(pfn >= (memory_node.end >> PAGE_SHIFT)){ + //INFO("try to free pfn %p that not belong to memory", pfn); + return; + } + page = pfn_to_page(pfn); + + daif = local_irq_disable_save(); + page->ref_cnt--; + if(page->ref_cnt == 0){ + _free_pages(page, order); + }else{ + LOG("addr: %p, ref_cnt: %p", addr, page->ref_cnt); + } + local_irq_restore(daif); +} + +// free one page +void free_page(void* addr){ + volatile uint64_t daif; + uint64_t pfn = virt_to_pfn(addr); + struct page *page; + if(pfn >= (memory_node.end >> PAGE_SHIFT)){ + //INFO("try to free pfn %p that not belong to memory", pfn); + return; + } + page = pfn_to_page(pfn); + + daif = local_irq_disable_save(); + page->ref_cnt--; + if(page->ref_cnt == 0){ + _free_pages(page, 0); + }else{ + LOG("addr: %p, ref_cnt: %p", addr, page->ref_cnt); + } + local_irq_restore(daif); +} + +// split large buddy group to two small buddy groups +void expand(struct page *page, uint32_t high, uint32_t low){ + struct page* tmp_page; + volatile uint64_t daif; + while(high > low){ + high--; + tmp_page = page + (1 << high); + + LOG("add page %p to order %u free list",page_to_virt(tmp_page) , high); + __free_pages(tmp_page, high); + } +} + +struct page* _alloc_pages(uint32_t order){ + LOG("_alloc_pages(%u)", order); + struct list_head *node; + struct free_list* free_list; + struct page* page, *tmp_page; + + // find appropriate buddy group for user + for(uint32_t i = order ; i < BUDDY_MAX_ORDER ; i++){ + free_list = &buddy.free_lists[i]; + + if(list_empty(&free_list->list)){ + LOG("free list of order %u is empty", i); + continue; + } + + page = list_first_entry(&free_list->list, struct page, list); + list_del(&page->list); + free_list->count--; + LOG("get free page %p from order %u", page_to_virt(page), i); + + + for(uint32_t j = 0 ; j < (1 << order) ; j++){ + page[j].order = BUDDY_ALLOCATED|order; + page[j].buddy_leader = page; + } + + if(i > order){ + LOG("start expand pages of order %u to order %u", i, order); + expand(page, i, order); + LOG("end expand pages from order %u to order %u", i, order); + } + return page; + } + return NULL; +} + +// return 2^order pages +void* alloc_pages(uint32_t order){ + if(order > BUDDY_MAX_ORDER - 1) return NULL; + volatile uint64_t daif; + + daif = local_irq_disable_save(); + struct page* page = _alloc_pages(order); + page->ref_cnt++; + local_irq_restore(daif); + + return page_to_virt(page); +} + +// return one page +void* alloc_page(){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + struct page* page = _alloc_pages(0); + page->ref_cnt++; + local_irq_restore(daif); + + return page_to_virt(page); +} + +void* calloc_page(){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + struct page* page = _alloc_pages(0); + page->ref_cnt++; + local_irq_restore(daif); + memset(page_to_virt(page), 0, PAGE_SIZE); + return page_to_virt(page); +} + +void print_buddy_statistics(){ + uint64_t free_page_count = 0; + uint64_t tmp; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + INFO("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + INFO("Total free page #: %l", free_page_count); +} + +uint8_t* _debug_alloc_page(uint32_t order){ + LOG("###########################################"); + uint64_t free_page_count = 0; + uint64_t tmp; + uint8_t * ret; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + LOG("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + ret = alloc_pages(order); + LOG("Total free page #: %l", free_page_count); + LOG("allocate page: %p", ret); + return ret; +} + +uint8_t* _debug_free_page(void *addr, uint32_t order){ + LOG("###########################################"); + uint64_t free_page_count = 0; + uint64_t tmp; + uint8_t * ret; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + tmp = buddy.free_lists[i].count; + LOG("free page's count of order %l = %l", i, tmp); + free_page_count += tmp * (1 << i); + } + free_pages(addr, order); + LOG("Total free page #: %l", free_page_count); + LOG("freed page: %p", addr); + return ret; +} + +void debug_buddy(){ + uint8_t *arr[1500]; + int32_t i = 0, count = 0; + struct list_head* node; + struct page* page, *target_page; + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(1); + count++; + } + for(i = 0 ; i < 4; i++){ + arr[count] = _debug_alloc_page(2); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 3; i++){ + arr[count] = _debug_alloc_page(3); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(1); + count++; + } + for(i = 0 ; i < 1; i++){ + arr[count] = _debug_alloc_page(2); + count++; + } + for(i = 0 ; i < 1400; i++){ + arr[count] = _debug_alloc_page(0); + count++; + } + LOG("###########################################"); + for(i = 0 ; i < count ; i++){ + target_page = virt_to_page(arr[i]); + if(!BUDDY_IS_ALLOCATED(target_page)){ + LOG("******* page %p didn't set to allocated *******", page_to_virt(page)); + goto error; + } + for(uint32_t j = 0 ; j < BUDDY_MAX_ORDER ; j++){ + list_for_each(node, &buddy.free_lists[j].list){ + page = list_entry(node, struct page, list); + if(target_page == page){ + LOG("******* allocated page didn't remove from free list *******", page_to_virt(page)); + goto error; + } + } + } + } + count = 0; + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 1); + count++; + } + for(i = 0 ; i < 4; i++){ + _debug_free_page(arr[count], 2); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 3; i++){ + _debug_free_page(arr[count], 3); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 0); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 1); + count++; + } + for(i = 0 ; i < 1; i++){ + _debug_free_page(arr[count], 2); + count++; + } + for(i = 0 ; i < 1400; i++){ + _debug_free_page(arr[count], 0); + count++; + } + // check the integrity of linked list by using grep to check how many unique lines + // + // ./debug.sh > t + // grep "\[test\]" t|sort|uniq|wc -l + // + struct list_head* tmp_node; + struct page* tmp_page; + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER ; i++){ + list_for_each(tmp_node, &buddy.free_lists[i].list){ + tmp_page = list_entry(tmp_node, struct page, list); + for(uint32_t j = 0; j < (1 << i) ; j++){ + printf("[test] : %p\n", page_to_virt(tmp_page + j)); + } + } + } + LOG("******* Pass the testcases *******"); + return; +error: + LOG("******* Something is wrong in buddy system alloc_pages *******"); + return; +} +void buddy_init(){ + struct list_head * node; + struct mem_block* mb; + uint64_t start_pfn, end_pfn; + + INFO("Initialize buddy system..."); + // Initialize global variable + memset(&buddy, '\0', sizeof(struct buddy_system)); + for(uint32_t i = 0 ; i < BUDDY_MAX_ORDER; i++){ + INIT_LIST_HEAD(&buddy.free_lists[i].list); + } + + // Initialize mem map + _init_mem_map(); + + // Add free page frame to buddy system + list_for_each(node, &mem_unusedmap){ + mb = list_entry(node, struct mem_block, list); + start_pfn = virt_to_pfn(mb->start + UPPER_ADDR_SPACE_BASE); + end_pfn = virt_to_pfn(mb->end + UPPER_ADDR_SPACE_BASE); + + _free_pages_memory(start_pfn, end_pfn); + } + +} diff --git a/lab7/mm/slab.c b/lab7/mm/slab.c new file mode 100644 index 000000000..76956fa34 --- /dev/null +++ b/lab7/mm/slab.c @@ -0,0 +1,251 @@ +#include "mm/slab.h" + +struct list_head kmem_cache[KMEM_CACHE_NUM] = {0}; + +struct slab* slab_create(size_t obj_size){ + size_t allocated_size; + uint32_t order = 0; + size_t page_num; + void* pages; + struct slab * pslab; + + // object size align to slab_alignment + obj_size = ALIGN_UP(obj_size, SLAB_ALIGNMENT); + + // check if obj_size exceed slab's limit + if(obj_size > SLAB_MAX_OBJECT_SIZE){ + LOG("invalid obj_size: %l, slab_max_object_size is %l", obj_size, SLAB_MAX_OBJECT_SIZE); + return NULL; + } + + // get sufficient order + //page_num = ALIGN_UP(obj_size + SLAB_SIZE, 4096) >> PAGE_SHIFT; + order = BUDDY_MAX_ORDER - 1; + pages = alloc_pages(order); + if(pages == NULL){ + LOG("Not enough page for slab"); + return NULL; + } + + // initialize struct slab + pslab = pages; + pslab->size = obj_size; + pslab->s_mem = pages + SLAB_SIZE; + pslab->inuse = 0; + INIT_LIST_HEAD(&pslab->free_list); + + return pslab; +} + +void slab_destroy(struct slab* slab){ + size_t page_num; + struct page* page = virt_to_page(slab); + volatile uint64_t daif; + LOG("slab_destroy recycle order %u buddy %p", (void*)slab, get_page_order(page)); + // free pages + free_pages((void*)slab, get_page_order(page)); +} + +void *slab_alloc(struct slab* slab){ + void *ret = NULL; + struct page* page; + uint32_t order; + size_t max_size; + volatile uint64_t daif; + daif = local_irq_disable_save(); + if(!list_empty(&slab->free_list)){ + // check free list + ret = slab->free_list.next; + list_del(slab->free_list.next); + slab->inuse++; + }else{ + page = virt_to_page(slab); + order = get_page_order(page); + max_size = (1 << order) * PAGE_SIZE; + if(SLAB_SIZE + (slab->inuse + 1) * slab->size > max_size){ + ret = NULL; + }else{ + ret = (uint8_t*)slab->s_mem + slab->inuse * slab->size; + slab->inuse++; + } + } + local_irq_restore(daif); + return ret; +} + +void slab_free(struct slab* slab, void* obj){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + list_add((struct list_head*)obj, &slab->free_list); + slab->inuse--; + local_irq_restore(daif); +} + +void kmalloc_init(){ + volatile uint64_t daif; + daif = local_irq_disable_save(); + for(uint64_t i = 0 ; i < KMEM_CACHE_NUM ; i++){ + INIT_LIST_HEAD(&kmem_cache[i]); + } + local_irq_restore(daif); +} +void* kmalloc(size_t size){ + uint64_t cache_idx; + struct list_head* cache_list, *node; + struct slab *s; + void * ret = NULL; + volatile uint64_t daif; + + size = ALIGN_UP(size, SLAB_ALIGNMENT); + + LOG("kmalloc(%u) start", size); + if(size > SLAB_MAX_OBJECT_SIZE){ + LOG("kmalloc invalid size %l", size); + return NULL; + } + // allocate memory from corresponding cache bin + cache_idx = ALIGN_UP(size, SLAB_ALIGNMENT) / SLAB_ALIGNMENT; + + daif = local_irq_disable_save(); + cache_list = &kmem_cache[cache_idx]; + + list_for_each(node, cache_list){ + s = list_entry(node, struct slab, list); + ret = slab_alloc(s); + if(ret != NULL){ + LOG("kmalloc(%u) found a free object %p in kmem_cache[%u]", size, ret, cache_idx); + break; + } + } + + if(ret == NULL){ + s = slab_create(size); + list_add(&s->list, cache_list); + ret = slab_alloc(s); + if(ret != NULL){ + LOG("kmalloc(%u) found a free object %p in kmem_cache[%u]", size, ret, cache_idx); + } + } + local_irq_restore(daif); + + LOG("kmalloc s->inuse: %x", s->inuse); + LOG("kmalloc(%u) end, ret: %p", size, ret); + return ret; +} + +void kfree(void* obj){ + volatile uint64_t daif = local_irq_disable_save(); + uint64_t pfn = virt_to_pfn(ALIGN_DOWN(obj, PAGE_SIZE)); + struct page* page = pfn_to_page(pfn); + struct page* buddy_leader = get_buddy_leader(page); + struct slab* s = page_to_virt(buddy_leader); + + slab_free(s, obj); + LOG("kfree(%p) free an object, s->inuse: %l", obj, s->inuse); + + if(s->inuse < 0){ + LOG("[Error]: s->inuse : %p", s->inuse); + } + if(s->inuse == 0){ + LOG("kfree(%p) triger recycle unused slab", obj); + + list_del(&s->list); + slab_destroy(s); + } + local_irq_restore(daif); +} + +#define TEST_SIZE 64 +#define TEST_INVALID_SIZE ((1 << (BUDDY_MAX_ORDER - 1)) * PAGE_SIZE - SLAB_SIZE + 1) +void debug_slab(){ + uint32_t i, max_i; + uint8_t *a[ (1 << BUDDY_MAX_ORDER - 1) * PAGE_SIZE / TEST_SIZE]; + + struct slab* s = slab_create(TEST_SIZE); + + for(i = 0 ; i < 30; i++){ + a[i] = slab_alloc(s); + LOG("%u: slab_alloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("slab is full"); + break; + } + } + max_i = i; + for(i = 0 ; i < max_i ; i++){ + slab_free(s, a[i]); + } + + for(i = 0 ; i < 30; i++){ + a[i] = slab_alloc(s); + LOG("%u: slab_alloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("slab is full"); + break; + } + } + + + + for(i = 0 ; i < max_i ; i++){ + slab_free(s, a[i]); + } + + slab_destroy(s); + uint64_t pfn = virt_to_pfn(s); + struct page* page = pfn_to_page(pfn); + + if(BUDDY_IS_FREED(page) && get_page_order(page) == BUDDY_MAX_ORDER - 1){ + LOG("slab_destroy success"); + }else{ + + LOG("slab_destroy failed"); + } + + s = slab_create(TEST_INVALID_SIZE); + + if(s == NULL){ + LOG("create super large slab %l failed", TEST_INVALID_SIZE); + }else{ + LOG("create super large slab %l success", TEST_INVALID_SIZE); + } +} + +void debug_kmalloc(){ + uint32_t i, max_i; + uint8_t *a[20]; + + + for(i = 0 ; i < 20; i++){ + a[i] = kmalloc(TEST_SIZE); + LOG("%l: kmalloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("kmalloc is failed"); + break; + } + } + + max_i = i; + for(i = 0 ; i < max_i ; i++){ + LOG("kfree(%p)", a[i]); + kfree(a[i]); + } +/* + for(i = 0 ; i < 200; i++){ + a[i] = kmalloc(TEST_SIZE); + LOG("%u: kmalloc(%u) = %p", i, TEST_SIZE, a[i]); + + if(a[i] == NULL){ + LOG("kmalloc is failed"); + break; + } + } + + for(i = 0 ; i < max_i ; i++){ + kfree(a[i]); + } +*/ +} diff --git a/lab7/peripherals/Makefile b/lab7/peripherals/Makefile new file mode 100644 index 000000000..50b5d0780 --- /dev/null +++ b/lab7/peripherals/Makefile @@ -0,0 +1,26 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +CFLAGS ?= \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin + +CXXFLAGS = + +OUTPUT ?= . +HEADERS ?= ../include +OBJECTS = \ + mini_uart.o \ + mailbox.o + +.PHONY: all +all: $(OBJECTS) + +%.o : %.c + $(CC) -c $^ -o $(OUTPUT)/$@ -I $(HEADERS) $(CFLAGS) + +clean: + rm $(OUTPUT)/$(OBJECTS) diff --git a/lab7/peripherals/mailbox.c b/lab7/peripherals/mailbox.c new file mode 100644 index 000000000..90435180a --- /dev/null +++ b/lab7/peripherals/mailbox.c @@ -0,0 +1,150 @@ +#include "peripherals/mailbox.h" + +static uint32_t MBox_buf[4096] __attribute__((aligned(16))); + +static uint32_t MBox_read(int channel){ + int ch, data; + + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_EMPTY_MASK); + + data = mbox_reg->read; + ch = data & MBOX_WRITE_CHANNEL_MASK; + if(ch == channel){ + LOG("MBox read address: %p", data & MBOX_READ_ADDR_MASK); + return (data & MBOX_READ_ADDR_MASK); + } + LOG("Leave"); + return 0; +} + +static void MBox_write(uint32_t data, int channel){ + LOG("Enter"); + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_FULL_MASK); + + mbox_reg->write = data | channel; + LOG("Leave"); +} + +static uint32_t MBox_process(uint8_t* tags, size_t tags_size){ + LOG("Enter"); + MBox_buffer* mbuf = (MBox_buffer*)MBox_buf; + // set buffer header + mbuf->buf_size = tags_size + 12; + mbuf->code = MBOX_STATUS_REQUEST; + + // copy tags to buffer + memcpy(mbuf->buf, tags, tags_size); + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + LOG("mbuf->buf: %p", mbuf->buf); + LOG("mbuf->buf + tags_size: %p", mbuf->buf + tags_size); + // end of MBox_buf + memset(mbuf->buf + tags_size, 0, 4); + + pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + // write to mailbox + MBox_write((uint32_t)(uint64_t)virt_to_phys(MBox_buf), MBOX_CHANNEL_PROPERTY_TAGS); + + // read from mailbox + uint32_t result = MBox_read(MBOX_CHANNEL_PROPERTY_TAGS); + + + LOG("Leave"); + return result; +} +void MBox_get_board_revision(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 4]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_BOARD_REVISION; + tag->value_size = 4; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer*)phys_to_virt(MBox_process(buf, sizeof(MBox_tag) + 4)); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + *ret = ((uint32_t*)tag->values)[0]; + LOG("Leave"); +} +void MBox_get_arm_memory(uint32_t* ret){ + LOG("Enter"); + // create tags + uint8_t buf[sizeof(MBox_tag) + 8]; + MBox_tag* tag = (MBox_tag*)buf; + tag->id = MBOX_GET_ARM_MEMORY; + tag->value_size = 8; + tag->code = MBOX_TAG_REQUEST; + ((uint32_t*)tag->values)[0] = 0; + ((uint32_t*)tag->values)[1] = 0; + + // process tags + MBox_buffer* mbuf = (MBox_buffer*)phys_to_virt(MBox_process(buf, sizeof(MBox_tag) + 8)); + + // precoess response tags + tag = (MBox_tag*)mbuf->buf; + uint32_t *pbuf = (uint32_t*)mbuf; + for(int i = 0 ; i < 10 ; i++){ + LOG("%p: %p", &pbuf[i], pbuf[i]); + } + + ret[0] = ((uint32_t*)tag->values)[0]; + ret[1] = ((uint32_t*)tag->values)[1]; + LOG("Leave"); +} + +int Mbox_call(uint32_t* mbox, uint8_t ch) { + MBox_register* mbox_reg = (MBox_register*)MBOX_REG; + while(mbox_reg->status & MBOX_STATUS_FULL_MASK); + + mbox_reg->write = ((uint32_t)(uint64_t)mbox & ~0xF) | ch; + + while (mbox_reg->status & MBOX_STATUS_EMPTY_MASK); + + return mbox_reg->read == (((uint32_t)(uint64_t)mbox & ~0xF) | ch); +} +int sys_mbox_call(uint8_t ch, uint32_t *mbox){ + uint64_t va = (uint64_t)mbox; + uint64_t pa; + struct task_struct* current = get_current(); + struct page* page; + int ret; + pgdval_t* pgd_e; + pudval_t* pud_e; + pmdval_t* pmd_e; + pteval_t* pte_e; + + LOG("va: %p",va); + pgd_e = pgd_offset(current->mm->pgd, va); + LOG("*pgd_e: %p",*pgd_e); + pud_e = pud_offset(pgd_e, va); + LOG("*pud_e: %p",*pud_e); + pmd_e = pmd_offset(pud_e, va); + LOG("*pmd_e: %p",*pmd_e); + pte_e = pte_offset(pmd_e, va); + LOG("*pte_e: %p",*pte_e); + page = pte_page(pte_e); + pa = page_to_phys(page) | ((uint64_t)mbox & 0xfff); + LOG("page_to_phys: %p, page_to_pfn: %p, pa: %p", page_to_phys(page), page_to_pfn(page), pa); + ret = Mbox_call((uint32_t *)pa, ch); + LOG("ret: %p", ret); + return ret; +} diff --git a/lab7/peripherals/mini_uart.c b/lab7/peripherals/mini_uart.c new file mode 100644 index 000000000..2f3eaa2d2 --- /dev/null +++ b/lab7/peripherals/mini_uart.c @@ -0,0 +1,169 @@ +#include "peripherals/mini_uart.h" + +ring_buffer* rx_rbuf = NULL; + +inline void delay_cycles(uint64_t n){ + for(register uint64_t i = 0 ; i < n ; i++) asm volatile("nop"); +} + +inline void enable_mini_uart_rx_irq(){ +} + +inline void disable_mini_uart_rx_irq(){ +} + +void mini_uart_init(){ + // GPIO 14 & 15 take function 0 + // Read out GPFSEL1 register + uint32_t tmp = IO_MMIO_read32(GPFSEL1); + + // Set GPIO 14 & 15 function bits + tmp &= ~(0b111111 << 12); + tmp |= 0b010010 << 12; + IO_MMIO_write32(GPFSEL1, tmp); + + + // disable pull-up/down of GPIO 14 & 15 + // Write to GPPUD to set the required control signal + IO_MMIO_write32(GPPUD, 0); + + // Wait 150 cycles – this provides the required set-up time for the control signal + delay_cycles(150); + + // Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to modify + IO_MMIO_write32(GPPUDCLK0, (1 << 14) | (1 << 15)); + + // Wait 150 cycles – this provides the required hold time for the control signal + delay_cycles(150); + + // Write to GPPUD to remove the control signa + IO_MMIO_write32(GPPUD, 0); + + // Write to GPPUDCLK0/1 to remove the clock + IO_MMIO_write32(GPPUDCLK0, 0); + + // Initialize Auxiliary peripherals Register + // Mini UART enable + IO_MMIO_write32(AUX_ENABLES, 1); + + // To disable auto flow control and disable receiver and transmitter, set control register to 0 + IO_MMIO_write32(AUX_MU_CNTL_REG, 0); + + // Disable mini UART's interrupt + IO_MMIO_write32(AUX_MU_IER_REG, 0); + + // Set UART to 8-bit mode + IO_MMIO_write32(AUX_MU_LCR_REG, 3); + + // To indicate that our UART is able to receive data, set RTS line to be always high + IO_MMIO_write32(AUX_MU_MCR_REG, 0); + + // Set Baud rate to 115200 + IO_MMIO_write32(AUX_MU_BAUD_REG, BAUD_RATE_REG); + + // disable FIFO + IO_MMIO_write32(AUX_MU_IIR_REG, 6); + + // Start UART + IO_MMIO_write32(AUX_MU_CNTL_REG, 3); + + return; +} + +uint8_t mini_uart_read(void){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & 0x1)); + return IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; +} + +void mini_uart_write(uint8_t val){ + while(!(IO_MMIO_read32(AUX_MU_LSR_REG) & (0x1 << 5))); + IO_MMIO_write32(AUX_MU_IO_REG, val); +} + +ssize_t write_bytes(uint8_t* buf, size_t n){ + for(uint64_t i = 0 ; i < n ; i++) mini_uart_write(buf[i]); + return n; +} + +void write_str(char* buf){ + while(*buf) mini_uart_write((uint8_t)*buf++); + return; +} + +void write_hex(uint64_t n){ + int i = 0; + char buf[16]; + char *hex_table = "0123456789abcdef"; + do{ + buf[i] = hex_table[n & 0xf]; + n = n >> 4; + i++; + }while(n); + do{ + i--; + mini_uart_write(buf[i]); + }while(i > 0); +} + +void mini_uart_irq_init(){ + rx_rbuf = create_simple_ring_buf(4095); + + IO_MMIO_write32(AUX_MU_IER_REG, 1); + IO_MMIO_write32(ENABLE_IRQS_1, 1 << 29); +} + + +void mini_uart_rx_softirq_callback(){ +} + +void mini_uart_irq_read(){ + uint8_t b[1]; + b[0] = IO_MMIO_read32(AUX_MU_IO_REG) & 0xff; + ring_buf_write_unsafe(rx_rbuf, b, 1); +} + +size_t mini_uart_get_rx_len(){ + return ring_buf_get_len(rx_rbuf); +} + +uint8_t mini_uart_aio_read(void){ + uint8_t b[1]; + IO_MMIO_write32(AUX_MU_IER_REG, 1); + while(!ring_buf_read(rx_rbuf, b, 1)); + IO_MMIO_write32(AUX_MU_IER_REG, 0); + return b[0]; +} + +size_t uart_write(char *buf, size_t size){ + uint64_t daif,ret; + //size_t c; + daif = local_irq_disable_save(); + ret = write_bytes(buf, size); + local_irq_restore(daif); + return ret; +} + + +size_t sys_uart_write(char *buf, size_t size){ + return uart_write(buf, size); +} + +size_t uart_read(char *buf, size_t size){ + size_t c = 0, tmp; + + IO_MMIO_write32(AUX_MU_IER_REG, 1); + while(size){ + tmp = ring_buf_read(rx_rbuf, buf + c, size); + + size = size - tmp; + c = c + tmp; + preempt_schedule(); + } + IO_MMIO_write32(AUX_MU_IER_REG, 0); + return c; +} + +size_t sys_uart_read(char *buf, size_t size){ + return uart_read(buf, size); +} + diff --git a/lab7/test/lib/.gdb_history b/lab7/test/lib/.gdb_history new file mode 100644 index 000000000..58afc787f --- /dev/null +++ b/lab7/test/lib/.gdb_history @@ -0,0 +1,2 @@ +run +quit diff --git a/lab7/test/lib/dtb_parse/.gdb_history b/lab7/test/lib/dtb_parse/.gdb_history new file mode 100644 index 000000000..8ae386791 --- /dev/null +++ b/lab7/test/lib/dtb_parse/.gdb_history @@ -0,0 +1,43 @@ +b main +run +n +quit +run +p fdt +quit +b main +n +run +n +x/gx ptr +quit +b main +run +n +statbuf->size +p statbuf->size +p statbuf->st_size +quit +run +b main +run +n +s +n +p token +p/x pdft_struct +p/x pdt_struct +x/gx 0x7ffff7fb3048 +x/s 0x7ffff7fb3048 +x/dx 0x7ffff7fb3048 +x/wx 0x7ffff7fb3048 +x/4wx 0x7ffff7fb3048 +n +p len +n +quit +quit +run +quit +run +quit diff --git a/lab7/test/lib/dtb_parse/Makefile b/lab7/test/lib/dtb_parse/Makefile new file mode 100644 index 000000000..d6e1a8f08 --- /dev/null +++ b/lab7/test/lib/dtb_parse/Makefile @@ -0,0 +1,2 @@ +all: + gcc main.c fdt_parse.c -o main -g -O0 diff --git a/lab7/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb b/lab7/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 000000000..6f9ef31cc Binary files /dev/null and b/lab7/test/lib/dtb_parse/bcm2710-rpi-3-b-plus.dtb differ diff --git a/lab7/test/lib/dtb_parse/fdt_parse.c b/lab7/test/lib/dtb_parse/fdt_parse.c new file mode 100644 index 000000000..bb8abd2c8 --- /dev/null +++ b/lab7/test/lib/dtb_parse/fdt_parse.c @@ -0,0 +1,113 @@ +#include "fdt_parse.h" +#include +#include +#include + +// callback type for fdt_parser +// void* (*)(fdt_node* node, fdt_property* prop) + +void fdt_parse_header(uint8_t* fdt, fdt_header* pheader){ + int i = 0; + uint32_t *ph = (uint32_t*)pheader, *pfdt = (uint32_t *)fdt; + + for(i = 0; i < sizeof(fdt_header) / 4 ; i++){ + uint32_t tmp = pfdt[i]; + ph[i] = bswap32(tmp); + } + +} + +void fdt_parser(uint8_t* fdt, fdt_callback callback){ + uint32_t finished = 0; + int32_t layer = -1; // To address recursive structure + uint32_t count = 0; + uint32_t token = 0; + uint32_t *pdt_struct; + uint8_t *pdt_strings; + fdt_node node; + fdt_property prop; + uint32_t len; + uint32_t str_offset; + + fdt_header * pheader = (fdt_header*)malloc(sizeof(fdt_header)); + fdt_parse_header(fdt, pheader); + + pdt_struct = (uint32_t *)(fdt + pheader->off_dt_struct); + pdt_strings = fdt + pheader->off_dt_strings; + + // start parsing structure + while(!finished){ + token = pdt_struct[count]; + count += 1; + switch(token){ + case FDT_BEGIN_NODE: + layer += 1; + + node.name = (char*)&pdt_struct[count]; + + len = strlen(node.name); + len = ALIGN_UP(len + 1, 4) / 4; + count += len; + + callback(token, &node, NULL, layer); + break; + case FDT_END_NODE: + callback(token, NULL, NULL, layer); + layer--; + break; + case FDT_PROP: + prop.value_len = bswap32(pdt_struct[count]); + str_offset = bswap32(pdt_struct[count + 1]); + prop.name = pdt_strings + str_offset; + prop.value = (uint8_t*)&pdt_struct[count + 2]; + + len = ALIGN_UP(prop.value_len, 4) / 4; + //printf("prop.value_len: %u, prop.name: %s, len: %u\n", prop.value_len, prop.name, len); + len += 2; + + count += len; + callback(token, NULL, &prop, layer); + break; + case FDT_NOP: + callback(token, NULL, NULL, layer); + break; + case FDT_END: + callback(token, NULL, NULL, layer); + finished = 1; + break; + default: + printf("Parsing error!!\n"); + exit(0); + } + } +} + +void* fdt_print_callback(uint32_t token, fdt_node* node, fdt_property* prop, int32_t layer){ + if(node != NULL){ + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("%s {\n", node->name); + }else if(prop != NULL){ + for(uint32_t i = 0 ; i < layer * 4 + 4; i++){ + printf(" "); + } + printf("%s ;\n", prop->name); + }else{ + switch(token){ + case FDT_END_NODE: + for(uint32_t i = 0 ; i < layer * 4 ; i++){ + printf(" "); + } + printf("}\n"); + break; + case FDT_NOP: + break; + case FDT_END: + break; + default: + break; + } + } + +} diff --git a/lab7/test/lib/dtb_parse/fdt_parse.h b/lab7/test/lib/dtb_parse/fdt_parse.h new file mode 100644 index 000000000..876b4087a --- /dev/null +++ b/lab7/test/lib/dtb_parse/fdt_parse.h @@ -0,0 +1,53 @@ +#ifndef _FDT_PARSE_H_ +#define _FDT_PARSE_H_ +#include "types.h" +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define FDT_BEGIN_NODE bswap32(0x00000001) +#define FDT_END_NODE bswap32(0x00000002) +#define FDT_PROP bswap32(0x00000003) +#define FDT_NOP bswap32(0x00000004) +#define FDT_END bswap32(0x00000009) +typedef struct{ + 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{ + uint64_t address; + uint64_t size; +} fdt_reserve_entry; + +typedef struct{ + char *name; +} fdt_node; + +typedef struct{ + char* name; + uint8_t* value; + uint32_t value_len; +} fdt_property; + +typedef void* (*fdt_callback)(uint32_t, fdt_node*, fdt_property*, int32_t); +extern void fdt_parser(uint8_t*, fdt_callback); +extern void* fdt_print_callback(uint32_t, fdt_node*, fdt_property*, int32_t); +#endif diff --git a/lab7/test/lib/dtb_parse/main b/lab7/test/lib/dtb_parse/main new file mode 100755 index 000000000..aa43f24f6 Binary files /dev/null and b/lab7/test/lib/dtb_parse/main differ diff --git a/lab7/test/lib/dtb_parse/main.c b/lab7/test/lib/dtb_parse/main.c new file mode 100644 index 000000000..9af1de752 --- /dev/null +++ b/lab7/test/lib/dtb_parse/main.c @@ -0,0 +1,19 @@ +#include "fdt_parse.h" +#include +#include +#include +#include +#include +#include + +int main(void){ + int fd = open("./bcm2710-rpi-3-b-plus.dtb", O_RDONLY); + if(fd < 0){ + printf("failed to open file\n"); + } + struct stat statbuf; + fstat(fd, &statbuf); + char *ptr = mmap(NULL,statbuf.st_size,PROT_READ,MAP_PRIVATE,fd,0); + + fdt_parser(ptr, fdt_print_callback); +} diff --git a/lab7/test/lib/dtb_parse/tmp.dts b/lab7/test/lib/dtb_parse/tmp.dts new file mode 100644 index 000000000..1ceb3539f --- /dev/null +++ b/lab7/test/lib/dtb_parse/tmp.dts @@ -0,0 +1,1515 @@ +/dts-v1/; + +/memreserve/ 0x0000000000000000 0x0000000000001000; +/ { + compatible = "raspberrypi,3-model-b-plus\0brcm,bcm2837"; + model = "Raspberry Pi 3 Model B+"; + #address-cells = <0x01>; + #size-cells = <0x01>; + interrupt-parent = <0x01>; + + aliases { + serial0 = "/soc/serial@7e215040"; + serial1 = "/soc/serial@7e201000"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + aux = "/soc/aux@7e215000"; + sound = "/soc/sound"; + soc = "/soc"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + uart0 = "/soc/serial@7e201000"; + uart1 = "/soc/serial@7e215040"; + sdhost = "/soc/mmc@7e202000"; + mmc = "/soc/mmc@7e300000"; + mmc1 = "/soc/mmcnr@7e300000"; + mmc0 = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c1 = "/soc/i2c@7e804000"; + i2c10 = "/soc/i2c0mux/i2c@1"; + spi0 = "/soc/spi@7e204000"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + usb = "/soc/usb@7e980000"; + leds = "/leds"; + fb = "/soc/fb"; + thermal = "/soc/thermal@7e212000"; + axiperf = "/soc/axiperf"; + i2c2 = "/soc/i2c@7e805000"; + ethernet0 = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + }; + + chosen { + bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; + }; + + reserved-memory { + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges; + phandle = <0x37>; + + linux,cma { + compatible = "shared-dma-pool"; + size = <0x4000000>; + reusable; + linux,cma-default; + phandle = <0x38>; + }; + }; + + thermal-zones { + + cpu-thermal { + polling-delay-passive = <0x00>; + polling-delay = <0x3e8>; + thermal-sensors = <0x02>; + coefficients = <0xfffffde6 0x64960>; + phandle = <0x39>; + + cooling-maps { + }; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x7e000000 0x3f000000 0x1000000 0x40000000 0x40000000 0x1000>; + dma-ranges = <0xc0000000 0x00 0x3f000000>; + phandle = <0x3a>; + + txp@7e004000 { + compatible = "brcm,bcm2835-txp"; + reg = <0x7e004000 0x20>; + interrupts = <0x01 0x0b>; + status = "disabled"; + phandle = <0x3b>; + }; + + cprman@7e101000 { + compatible = "brcm,bcm2835-cprman"; + #clock-cells = <0x01>; + reg = <0x7e101000 0x2000>; + clocks = <0x03 0x04 0x00 0x04 0x01 0x04 0x02 0x05 0x00 0x05 0x01 0x05 0x02>; + firmware = <0x06>; + phandle = <0x08>; + }; + + mailbox@7e00b880 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0x00 0x01>; + #mbox-cells = <0x00>; + phandle = <0x1f>; + }; + + gpio@7e200000 { + compatible = "brcm,bcm2835-gpio"; + reg = <0x7e200000 0xb4>; + interrupts = <0x02 0x11 0x02 0x12>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x07 0x00 0x00 0x36>; + pinctrl-names = "default"; + gpio-line-names = "ID_SDA\0ID_SCL\0SDA1\0SCL1\0GPIO_GCLK\0GPIO5\0GPIO6\0SPI_CE1_N\0SPI_CE0_N\0SPI_MISO\0SPI_MOSI\0SPI_SCLK\0GPIO12\0GPIO13\0TXD1\0RXD1\0GPIO16\0GPIO17\0GPIO18\0GPIO19\0GPIO20\0GPIO21\0GPIO22\0GPIO23\0GPIO24\0GPIO25\0GPIO26\0GPIO27\0HDMI_HPD_N\0STATUS_LED_G\0CTS0\0RTS0\0TXD0\0RXD0\0SD1_CLK\0SD1_CMD\0SD1_DATA0\0SD1_DATA1\0SD1_DATA2\0SD1_DATA3\0PWM0_OUT\0PWM1_OUT\0ETH_CLK\0WIFI_CLK\0SDA0\0SCL0\0SMPS_SCL\0SMPS_SDA\0SD_CLK_R\0SD_CMD_R\0SD_DATA0_R\0SD_DATA1_R\0SD_DATA2_R\0SD_DATA3_R"; + phandle = <0x07>; + + dpi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x06>; + phandle = <0x3c>; + }; + + emmc_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x07>; + phandle = <0x3d>; + }; + + emmc_gpio34 { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x3e>; + }; + + emmc_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x07>; + phandle = <0x17>; + }; + + gpclk0_gpio4 { + brcm,pins = <0x04>; + brcm,function = <0x04>; + phandle = <0x3f>; + }; + + gpclk1_gpio5 { + brcm,pins = <0x05>; + brcm,function = <0x04>; + phandle = <0x40>; + }; + + gpclk1_gpio42 { + brcm,pins = <0x2a>; + brcm,function = <0x04>; + phandle = <0x41>; + }; + + gpclk1_gpio44 { + brcm,pins = <0x2c>; + brcm,function = <0x04>; + phandle = <0x42>; + }; + + gpclk2_gpio6 { + brcm,pins = <0x06>; + brcm,function = <0x04>; + phandle = <0x43>; + }; + + gpclk2_gpio43 { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x44>; + }; + + i2c0_gpio0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x12>; + }; + + i2c0_gpio28 { + brcm,pins = <0x1c 0x1d>; + brcm,function = <0x04>; + phandle = <0x45>; + }; + + i2c0_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x05>; + phandle = <0x13>; + }; + + i2c1_gpio2 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x46>; + }; + + i2c1_gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x06>; + phandle = <0x47>; + }; + + jtag_gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x03>; + phandle = <0x48>; + }; + + pcm_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x49>; + }; + + pcm_gpio28 { + brcm,pins = <0x1c 0x1d 0x1e 0x1f>; + brcm,function = <0x06>; + phandle = <0x4a>; + }; + + sdhost_gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x04>; + phandle = <0x0d>; + }; + + spi0_gpio7 { + brcm,pins = <0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x4b>; + }; + + spi0_gpio35 { + brcm,pins = <0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x04>; + phandle = <0x4c>; + }; + + spi1_gpio16 { + brcm,pins = <0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x03>; + phandle = <0x4d>; + }; + + spi2_gpio40 { + brcm,pins = <0x28 0x29 0x2a 0x2b 0x2c 0x2d>; + brcm,function = <0x03>; + phandle = <0x4e>; + }; + + uart0_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x04>; + phandle = <0x4f>; + }; + + uart0_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x07>; + phandle = <0x50>; + }; + + uart0_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x07>; + brcm,pull = <0x02 0x00>; + phandle = <0x51>; + }; + + uart0_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x52>; + }; + + uart0_gpio36 { + brcm,pins = <0x24 0x25>; + brcm,function = <0x06>; + phandle = <0x53>; + }; + + uart0_ctsrts_gpio38 { + brcm,pins = <0x26 0x27>; + brcm,function = <0x06>; + phandle = <0x54>; + }; + + uart1_gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x02>; + phandle = <0x55>; + }; + + uart1_ctsrts_gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x02>; + phandle = <0x56>; + }; + + uart1_gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x02>; + phandle = <0x57>; + }; + + uart1_ctsrts_gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x02>; + phandle = <0x58>; + }; + + uart1_gpio40 { + brcm,pins = <0x28 0x29>; + brcm,function = <0x02>; + phandle = <0x59>; + }; + + uart1_ctsrts_gpio42 { + brcm,pins = <0x2a 0x2b>; + brcm,function = <0x02>; + phandle = <0x5a>; + }; + + i2c_slave_gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x07>; + phandle = <0x5b>; + }; + + jtag_gpio4 { + brcm,pins = <0x04 0x05 0x06 0x0c 0x0d>; + brcm,function = <0x02>; + phandle = <0x5c>; + }; + + pwm0_gpio12 { + brcm,pins = <0x0c>; + brcm,function = <0x04>; + phandle = <0x5d>; + }; + + pwm0_gpio18 { + brcm,pins = <0x12>; + brcm,function = <0x02>; + phandle = <0x5e>; + }; + + pwm0_gpio40 { + brcm,pins = <0x28>; + brcm,function = <0x04>; + phandle = <0x5f>; + }; + + pwm1_gpio13 { + brcm,pins = <0x0d>; + brcm,function = <0x04>; + phandle = <0x60>; + }; + + pwm1_gpio19 { + brcm,pins = <0x13>; + brcm,function = <0x02>; + phandle = <0x61>; + }; + + pwm1_gpio41 { + brcm,pins = <0x29>; + brcm,function = <0x04>; + phandle = <0x62>; + }; + + pwm1_gpio45 { + brcm,pins = <0x2d>; + brcm,function = <0x04>; + phandle = <0x63>; + }; + + dpi_18bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + brcm,pull = <0x00>; + phandle = <0x64>; + }; + + dpi_18bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + phandle = <0x65>; + }; + + dpi_18bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x66>; + }; + + dpi_18bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0x67>; + }; + + dpi_16bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x68>; + }; + + dpi_16bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0x69>; + }; + + dpi_16bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6a>; + }; + + dpi_16bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0x6b>; + }; + + gpioout { + brcm,pins = <0x06>; + brcm,function = <0x01>; + phandle = <0x6c>; + }; + + alt0 { + brcm,pins = <0x04 0x05 0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x6d>; + }; + + spi0_pins { + brcm,pins = <0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x0f>; + }; + + spi0_cs_pins { + brcm,pins = <0x08 0x07>; + brcm,function = <0x01>; + phandle = <0x10>; + }; + + i2c0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x6e>; + }; + + i2c1 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x18>; + }; + + i2s { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x0e>; + }; + + sdio_pins { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x1e>; + }; + + bt_pins { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x0a>; + }; + + uart0_pins { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x09>; + }; + + uart1_pins { + brcm,pins; + brcm,function; + brcm,pull; + phandle = <0x16>; + }; + + audio_pins { + brcm,pins = <0x28 0x29>; + brcm,function = <0x04>; + phandle = <0x20>; + }; + }; + + serial@7e201000 { + compatible = "arm,pl011\0arm,primecell"; + reg = <0x7e201000 0x200>; + interrupts = <0x02 0x19>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk\0apb_pclk"; + arm,primecell-periphid = <0x241011>; + cts-event-workaround; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x09 0x0a>; + status = "okay"; + phandle = <0x26>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <0x2dc6c0>; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x33>; + }; + }; + + mmc@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <0x02 0x18>; + clocks = <0x08 0x14>; + status = "okay"; + dmas = <0x0c 0x2000000d>; + dma-names = "rx-tx"; + bus-width = <0x04>; + brcm,overclock-50 = <0x00>; + brcm,pio-limit = <0x01>; + firmware = <0x06>; + pinctrl-names = "default"; + pinctrl-0 = <0x0d>; + phandle = <0x2f>; + }; + + i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; + reg = <0x7e203000 0x24>; + clocks = <0x08 0x1f>; + status = "disabled"; + dmas = <0x0c 0x02 0x0c 0x03>; + dma-names = "tx\0rx"; + #sound-dai-cells = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x0e>; + phandle = <0x28>; + }; + + spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x200>; + interrupts = <0x02 0x16>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + dmas = <0x0c 0x06 0x0c 0x07>; + dma-names = "tx\0rx"; + pinctrl-names = "default"; + pinctrl-0 = <0x0f 0x10>; + cs-gpios = <0x07 0x08 0x01 0x07 0x07 0x01>; + phandle = <0x29>; + + spidev@0 { + compatible = "spidev"; + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x6f>; + }; + + spidev@1 { + compatible = "spidev"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0x70>; + }; + }; + + i2c@7e205000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e205000 0x200>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x11>; + }; + + i2c0mux { + compatible = "i2c-mux-pinctrl"; + #address-cells = <0x01>; + #size-cells = <0x00>; + i2c-parent = <0x11>; + pinctrl-names = "i2c0\0i2c_csi_dsi"; + status = "disabled"; + pinctrl-0 = <0x12>; + pinctrl-1 = <0x13>; + phandle = <0x2a>; + + i2c@0 { + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x71>; + }; + + i2c@1 { + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x72>; + }; + }; + + dpi@7e208000 { + compatible = "brcm,bcm2835-dpi"; + reg = <0x7e208000 0x8c>; + clocks = <0x08 0x14 0x08 0x2c>; + clock-names = "core\0pixel"; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x73>; + }; + + dsi@7e209000 { + compatible = "brcm,bcm2835-dsi0"; + reg = <0x7e209000 0x78>; + interrupts = <0x02 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x20 0x08 0x2f 0x08 0x31>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi0_byte\0dsi0_ddr2\0dsi0_ddr"; + status = "disabled"; + power-domains = <0x14 0x11>; + phandle = <0x04>; + }; + + aux@7e215000 { + compatible = "brcm,bcm2835-aux"; + #clock-cells = <0x01>; + reg = <0x7e215000 0x08>; + clocks = <0x08 0x14>; + phandle = <0x15>; + }; + + serial@7e215040 { + compatible = "brcm,bcm2835-aux-uart"; + reg = <0x7e215040 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x00>; + status = "okay"; + skip-init; + pinctrl-names = "default"; + pinctrl-0 = <0x16>; + phandle = <0x27>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = "\0\a\b"; + shutdown-gpios = <0x0b 0x00 0x00>; + status = "disabled"; + phandle = <0x74>; + }; + }; + + spi@7e215080 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e215080 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x75>; + }; + + spi@7e2150c0 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e2150c0 0x40>; + interrupts = <0x01 0x1d>; + clocks = <0x15 0x02>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0x76>; + }; + + pwm@7e20c000 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x7e20c000 0x28>; + clocks = <0x08 0x1e>; + assigned-clocks = <0x08 0x1e>; + assigned-clock-rates = <0x989680>; + #pwm-cells = <0x02>; + status = "disabled"; + phandle = <0x77>; + }; + + mmc@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + status = "disabled"; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x17>; + bus-width = <0x04>; + phandle = <0x30>; + }; + + hvs@7e400000 { + compatible = "brcm,bcm2835-hvs"; + reg = <0x7e400000 0x6000>; + interrupts = <0x02 0x01>; + status = "disabled"; + phandle = <0x78>; + }; + + dsi@7e700000 { + compatible = "brcm,bcm2835-dsi1"; + reg = <0x7e700000 0x8c>; + interrupts = <0x02 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x23 0x08 0x30 0x08 0x32>; + clock-names = "phy\0escape\0pixel"; + clock-output-names = "dsi1_byte\0dsi1_ddr2\0dsi1_ddr"; + status = "disabled"; + power-domains = <0x14 0x12>; + phandle = <0x05>; + }; + + i2c@7e804000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e804000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x18>; + clock-frequency = <0x186a0>; + phandle = <0x2b>; + }; + + usb@7e980000 { + compatible = "brcm,bcm2708-usb"; + reg = <0x7e980000 0x10000 0x7e006000 0x1000>; + interrupts = <0x01 0x09 0x02 0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x19>; + clock-names = "otg"; + phys = <0x1a>; + phy-names = "usb2-phy"; + interrupt-names = "usb\0soft"; + power-domains = <0x14 0x06>; + phandle = <0x79>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + usb-port@1 { + compatible = "usb424,2514"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet@1 { + compatible = "usb424,7800"; + reg = <0x01>; + phandle = <0x7a>; + + mdio { + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet-phy@1 { + reg = <0x01>; + microchip,led-modes = <0x01 0x06>; + microchip,eee-enabled; + microchip,tx-lpi-timer = <0x258>; + microchip,downshift-after = <0x02>; + phandle = <0x36>; + }; + }; + }; + }; + }; + }; + + dma@7e007000 { + compatible = "brcm,bcm2835-dma"; + reg = <0x7e007000 0xf00>; + interrupts = <0x01 0x10 0x01 0x11 0x01 0x12 0x01 0x13 0x01 0x14 0x01 0x15 0x01 0x16 0x01 0x17 0x01 0x18 0x01 0x19 0x01 0x1a 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1b 0x01 0x1c>; + interrupt-names = "dma0\0dma1\0dma2\0dma3\0dma4\0dma5\0dma6\0dma7\0dma8\0dma9\0dma10\0dma11\0dma12\0dma13\0dma14\0dma-shared-all"; + #dma-cells = <0x01>; + brcm,dma-channel-mask = <0x7f35>; + phandle = <0x0c>; + }; + + interrupt-controller@7e00b200 { + compatible = "brcm,bcm2836-armctrl-ic"; + reg = <0x7e00b200 0x200>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + interrupts = <0x08 0x04>; + phandle = <0x01>; + }; + + watchdog@7e100000 { + compatible = "brcm,bcm2835-pm\0brcm,bcm2835-pm-wdt"; + #power-domain-cells = <0x01>; + #reset-cells = <0x01>; + reg = <0x7e100000 0x114 0x7e00a000 0x24>; + clocks = <0x08 0x15 0x08 0x1d 0x08 0x17 0x08 0x16>; + clock-names = "v3d\0peri_image\0h264\0isp"; + system-power-controller; + phandle = <0x2d>; + }; + + rng@7e104000 { + compatible = "brcm,bcm2835-rng"; + reg = <0x7e104000 0x10>; + interrupts = <0x02 0x1d>; + phandle = <0x2e>; + }; + + pixelvalve@7e206000 { + compatible = "brcm,bcm2835-pixelvalve0"; + reg = <0x7e206000 0x100>; + interrupts = <0x02 0x0d>; + status = "disabled"; + phandle = <0x7b>; + }; + + pixelvalve@7e207000 { + compatible = "brcm,bcm2835-pixelvalve1"; + reg = <0x7e207000 0x100>; + interrupts = <0x02 0x0e>; + status = "disabled"; + phandle = <0x7c>; + }; + + thermal@7e212000 { + compatible = "brcm,bcm2837-thermal"; + reg = <0x7e212000 0x08>; + clocks = <0x08 0x1b>; + #thermal-sensor-cells = <0x00>; + status = "okay"; + phandle = <0x02>; + }; + + i2c@7e805000 { + compatible = "brcm,bcm2835-i2c"; + reg = <0x7e805000 0x1000>; + interrupts = <0x02 0x15>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x1d>; + }; + + vec@7e806000 { + compatible = "brcm,bcm2835-vec"; + reg = <0x7e806000 0x1000>; + clocks = <0x1c 0x0f>; + interrupts = <0x02 0x1b>; + status = "disabled"; + power-domains = <0x14 0x07>; + phandle = <0x7d>; + }; + + pixelvalve@7e807000 { + compatible = "brcm,bcm2835-pixelvalve2"; + reg = <0x7e807000 0x100>; + interrupts = <0x02 0x0a>; + status = "disabled"; + phandle = <0x7e>; + }; + + hdmi@7e902000 { + compatible = "brcm,bcm2835-hdmi"; + reg = <0x7e902000 0x600 0x7e808000 0x100>; + reg-names = "hdmi\0hd"; + interrupts = <0x02 0x08 0x02 0x09>; + ddc = <0x1d>; + clocks = <0x1c 0x09 0x1c 0x0d>; + clock-names = "pixel\0hdmi"; + dmas = <0x0c 0x9000011>; + dma-names = "audio-rx"; + status = "disabled"; + power-domains = <0x14 0x05>; + hpd-gpios = <0x07 0x1c 0x01>; + phandle = <0x7f>; + }; + + v3d@7ec00000 { + compatible = "brcm,vc4-v3d"; + reg = <0x7ec00000 0x1000>; + interrupts = <0x01 0x0a>; + power-domains = <0x14 0x0a>; + status = "disabled"; + phandle = <0x80>; + }; + + gpu { + compatible = "brcm,bcm2835-vc4"; + status = "disabled"; + raspberrypi,firmware = <0x06>; + phandle = <0x81>; + }; + + local_intc@40000000 { + compatible = "brcm,bcm2836-l1-intc"; + reg = <0x40000000 0x100>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupt-parent = <0x1b>; + phandle = <0x1b>; + }; + + mmcnr@7e300000 { + compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x02 0x1e>; + clocks = <0x08 0x1c>; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + non-removable; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x1e>; + bus-width = <0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0x31>; + + wifi@1 { + reg = <0x01>; + compatible = "brcm,bcm4329-fmac"; + phandle = <0x82>; + }; + }; + + firmwarekms@7e600000 { + compatible = "raspberrypi,rpi-firmware-kms"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + brcm,firmware = <0x06>; + status = "disabled"; + phandle = <0x83>; + }; + + smi@7e600000 { + compatible = "brcm,bcm2835-smi"; + reg = <0x7e600000 0x100>; + interrupts = <0x02 0x10>; + clocks = <0x08 0x2a>; + assigned-clocks = <0x08 0x2a>; + assigned-clock-rates = <0x7735940>; + dmas = <0x0c 0x04>; + dma-names = "rx-tx"; + status = "disabled"; + phandle = <0x84>; + }; + + csi@7e800000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e800000 0x800 0x7e802000 0x04>; + interrupts = <0x02 0x06>; + clocks = <0x08 0x2d 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + phandle = <0x85>; + }; + + csi@7e801000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e801000 0x800 0x7e802004 0x04>; + interrupts = <0x02 0x07>; + clocks = <0x08 0x2e 0x1c 0x04>; + clock-names = "lp\0vpu"; + power-domains = <0x14 0x0d>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + brcm,num-data-lanes = <0x02>; + phandle = <0x86>; + }; + + axiperf { + compatible = "brcm,bcm2835-axiperf"; + reg = <0x7e009800 0x100 0x7ee08000 0x100>; + firmware = <0x06>; + status = "disabled"; + phandle = <0x32>; + }; + + firmware { + compatible = "raspberrypi,bcm2835-firmware\0simple-mfd"; + #address-cells = <0x01>; + #size-cells = <0x01>; + mboxes = <0x1f>; + dma-ranges; + phandle = <0x06>; + + clocks { + compatible = "raspberrypi,firmware-clocks"; + #clock-cells = <0x01>; + phandle = <0x1c>; + }; + + vcio { + compatible = "raspberrypi,vcio"; + phandle = <0x87>; + }; + + expgpio { + compatible = "raspberrypi,firmware-gpio"; + gpio-controller; + #gpio-cells = <0x02>; + gpio-line-names = "BT_ON\0WL_ON\0PWR_LED_R\0LAN_RUN\0NC\0CAM_GPIO0\0CAM_GPIO1\0NC"; + status = "okay"; + phandle = <0x0b>; + }; + }; + + power { + compatible = "raspberrypi,bcm2835-power"; + firmware = <0x06>; + #power-domain-cells = <0x01>; + phandle = <0x14>; + }; + + mailbox@7e00b840 { + compatible = "brcm,bcm2836-vchiq\0brcm,bcm2835-vchiq"; + reg = <0x7e00b840 0x3c>; + interrupts = <0x00 0x02>; + phandle = <0x88>; + + bcm2835_audio { + compatible = "brcm,bcm2835-audio"; + brcm,firmware = <0x06>; + brcm,pwm-channels = <0x08>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x20>; + phandle = <0x2c>; + }; + }; + + gpiomem { + compatible = "brcm,bcm2835-gpiomem"; + reg = <0x7e200000 0x1000>; + }; + + fb { + compatible = "brcm,bcm2708-fb"; + firmware = <0x06>; + status = "okay"; + phandle = <0x89>; + }; + + sound { + status = "disabled"; + phandle = <0x8a>; + }; + }; + + clocks { + + clk-osc { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "osc"; + clock-frequency = <0x124f800>; + phandle = <0x03>; + }; + + clk-usb { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "otg"; + clock-frequency = <0x1c9c3800>; + phandle = <0x19>; + }; + }; + + phy { + compatible = "usb-nop-xceiv"; + #phy-cells = <0x00>; + phandle = <0x1a>; + }; + + arm-pmu { + compatible = "arm,cortex-a53-pmu\0arm,cortex-a7-pmu"; + interrupt-parent = <0x1b>; + interrupts = <0x09 0x04>; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupt-parent = <0x1b>; + interrupts = <0x00 0x04 0x01 0x04 0x03 0x04 0x02 0x04>; + always-on; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + enable-method = "brcm,bcm2836-smp"; + phandle = <0x8b>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x00>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xd8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x22>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x01>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x23>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x02>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x24>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x03>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xf0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x21>; + phandle = <0x25>; + }; + + l2-cache0 { + compatible = "cache"; + cache-size = <0x80000>; + cache-line-size = <0x40>; + cache-sets = <0x200>; + cache-level = <0x02>; + phandle = <0x21>; + }; + }; + + cam1_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam1-reg"; + enable-active-high; + status = "okay"; + gpio = <0x0b 0x05 0x00>; + phandle = <0x8c>; + }; + + cam1_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8d>; + }; + + cam0_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam0-reg"; + enable-active-high; + status = "disabled"; + phandle = <0x8e>; + }; + + cam0_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0x8f>; + }; + + cam_dummy_reg { + compatible = "regulator-fixed"; + regulator-name = "cam-dummy-reg"; + status = "okay"; + phandle = <0x90>; + }; + + __overrides__ { + cam0-pwdn-ctrl; + cam0-pwdn; + cam0-led-ctrl; + cam0-led; + arm_freq = "\0\0\0\"clock-frequency:0\0\0\0\0#clock-frequency:0\0\0\0\0$clock-frequency:0\0\0\0\0%clock-frequency:0"; + cache_line_size; + uart0 = "\0\0\0&status"; + uart1 = "\0\0\0'status"; + i2s = "\0\0\0(status"; + spi = "\0\0\0)status"; + i2c0 = [00 00 00 11 73 74 61 74 75 73 00 00 00 00 2a 73 74 61 74 75 73 00]; + i2c1 = "\0\0\0+status"; + i2c0_baudrate = [00 00 00 11 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + i2c1_baudrate = "\0\0\0+clock-frequency:0"; + audio = "\0\0\0,status"; + watchdog = "\0\0\0-status"; + random = "\0\0\0.status"; + sd_overclock = "\0\0\0/brcm,overclock-50:0"; + sd_force_pio = "\0\0\0/brcm,force-pio?"; + sd_pio_limit = "\0\0\0/brcm,pio-limit:0"; + sd_debug = "\0\0\0/brcm,debug"; + sdio_overclock = "\0\0\00brcm,overclock-50:0\0\0\0\01brcm,overclock-50:0"; + axiperf = "\0\0\02status"; + i2c2_iknowwhatimdoing = [00 00 00 1d 73 74 61 74 75 73 00]; + i2c2_baudrate = [00 00 00 1d 63 6c 6f 63 6b 2d 66 72 65 71 75 65 6e 63 79 3a 30 00]; + sd_poll_once = "\0\0\0/non-removable?"; + krnbt = "\0\0\03status"; + krnbt_baudrate = "\0\0\03max-speed:0"; + act_led_gpio = "\0\0\04gpios:4"; + act_led_activelow = "\0\0\04gpios:8"; + act_led_trigger = "\0\0\04linux,default-trigger"; + pwr_led_gpio = "\0\0\05gpios:4"; + pwr_led_activelow = "\0\0\05gpios:8"; + pwr_led_trigger = "\0\0\05linux,default-trigger"; + eee = "\0\0\06microchip,eee-enabled?"; + tx_lpi_timer = "\0\0\06microchip,tx-lpi-timer:0"; + eth_led0 = "\0\0\06microchip,led-modes:0"; + eth_led1 = "\0\0\06microchip,led-modes:4"; + eth_downshift_after = "\0\0\06microchip,downshift-after:0"; + eth_max_speed = "\0\0\06max-speed:0"; + }; + + leds { + compatible = "gpio-leds"; + phandle = <0x91>; + + led-act { + label = "led0"; + default-state = "keep"; + linux,default-trigger = "mmc0"; + gpios = <0x07 0x1d 0x00>; + phandle = <0x34>; + }; + + led-pwr { + label = "led1"; + linux,default-trigger = "default-on"; + gpios = <0x0b 0x02 0x01>; + phandle = <0x35>; + }; + }; + + fixedregulator_3v3 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microvolt = <0x325aa0>; + regulator-name = "3v3"; + phandle = <0x92>; + }; + + fixedregulator_5v0 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x4c4b40>; + regulator-min-microvolt = <0x4c4b40>; + regulator-name = "5v0"; + phandle = <0x93>; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00 0x00>; + }; + + __symbols__ { + rmem = "/reserved-memory"; + cma = "/reserved-memory/linux,cma"; + cpu_thermal = "/thermal-zones/cpu-thermal"; + soc = "/soc"; + txp = "/soc/txp@7e004000"; + clocks = "/soc/cprman@7e101000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + dpi_gpio0 = "/soc/gpio@7e200000/dpi_gpio0"; + emmc_gpio22 = "/soc/gpio@7e200000/emmc_gpio22"; + emmc_gpio34 = "/soc/gpio@7e200000/emmc_gpio34"; + emmc_gpio48 = "/soc/gpio@7e200000/emmc_gpio48"; + gpclk0_gpio4 = "/soc/gpio@7e200000/gpclk0_gpio4"; + gpclk1_gpio5 = "/soc/gpio@7e200000/gpclk1_gpio5"; + gpclk1_gpio42 = "/soc/gpio@7e200000/gpclk1_gpio42"; + gpclk1_gpio44 = "/soc/gpio@7e200000/gpclk1_gpio44"; + gpclk2_gpio6 = "/soc/gpio@7e200000/gpclk2_gpio6"; + gpclk2_gpio43 = "/soc/gpio@7e200000/gpclk2_gpio43"; + i2c0_gpio0 = "/soc/gpio@7e200000/i2c0_gpio0"; + i2c0_gpio28 = "/soc/gpio@7e200000/i2c0_gpio28"; + i2c0_gpio44 = "/soc/gpio@7e200000/i2c0_gpio44"; + i2c1_gpio2 = "/soc/gpio@7e200000/i2c1_gpio2"; + i2c1_gpio44 = "/soc/gpio@7e200000/i2c1_gpio44"; + jtag_gpio22 = "/soc/gpio@7e200000/jtag_gpio22"; + pcm_gpio18 = "/soc/gpio@7e200000/pcm_gpio18"; + pcm_gpio28 = "/soc/gpio@7e200000/pcm_gpio28"; + sdhost_gpio48 = "/soc/gpio@7e200000/sdhost_gpio48"; + spi0_gpio7 = "/soc/gpio@7e200000/spi0_gpio7"; + spi0_gpio35 = "/soc/gpio@7e200000/spi0_gpio35"; + spi1_gpio16 = "/soc/gpio@7e200000/spi1_gpio16"; + spi2_gpio40 = "/soc/gpio@7e200000/spi2_gpio40"; + uart0_gpio14 = "/soc/gpio@7e200000/uart0_gpio14"; + uart0_ctsrts_gpio16 = "/soc/gpio@7e200000/uart0_ctsrts_gpio16"; + uart0_ctsrts_gpio30 = "/soc/gpio@7e200000/uart0_ctsrts_gpio30"; + uart0_gpio32 = "/soc/gpio@7e200000/uart0_gpio32"; + uart0_gpio36 = "/soc/gpio@7e200000/uart0_gpio36"; + uart0_ctsrts_gpio38 = "/soc/gpio@7e200000/uart0_ctsrts_gpio38"; + uart1_gpio14 = "/soc/gpio@7e200000/uart1_gpio14"; + uart1_ctsrts_gpio16 = "/soc/gpio@7e200000/uart1_ctsrts_gpio16"; + uart1_gpio32 = "/soc/gpio@7e200000/uart1_gpio32"; + uart1_ctsrts_gpio30 = "/soc/gpio@7e200000/uart1_ctsrts_gpio30"; + uart1_gpio40 = "/soc/gpio@7e200000/uart1_gpio40"; + uart1_ctsrts_gpio42 = "/soc/gpio@7e200000/uart1_ctsrts_gpio42"; + i2c_slave_gpio18 = "/soc/gpio@7e200000/i2c_slave_gpio18"; + jtag_gpio4 = "/soc/gpio@7e200000/jtag_gpio4"; + pwm0_gpio12 = "/soc/gpio@7e200000/pwm0_gpio12"; + pwm0_gpio18 = "/soc/gpio@7e200000/pwm0_gpio18"; + pwm0_gpio40 = "/soc/gpio@7e200000/pwm0_gpio40"; + pwm1_gpio13 = "/soc/gpio@7e200000/pwm1_gpio13"; + pwm1_gpio19 = "/soc/gpio@7e200000/pwm1_gpio19"; + pwm1_gpio41 = "/soc/gpio@7e200000/pwm1_gpio41"; + pwm1_gpio45 = "/soc/gpio@7e200000/pwm1_gpio45"; + dpi_18bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio0"; + dpi_18bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio2"; + dpi_18bit_gpio0 = "/soc/gpio@7e200000/dpi_18bit_gpio0"; + dpi_18bit_gpio2 = "/soc/gpio@7e200000/dpi_18bit_gpio2"; + dpi_16bit_gpio0 = "/soc/gpio@7e200000/dpi_16bit_gpio0"; + dpi_16bit_gpio2 = "/soc/gpio@7e200000/dpi_16bit_gpio2"; + dpi_16bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio0"; + dpi_16bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio2"; + gpioout = "/soc/gpio@7e200000/gpioout"; + alt0 = "/soc/gpio@7e200000/alt0"; + spi0_pins = "/soc/gpio@7e200000/spi0_pins"; + spi0_cs_pins = "/soc/gpio@7e200000/spi0_cs_pins"; + i2c0_pins = "/soc/gpio@7e200000/i2c0"; + i2c1_pins = "/soc/gpio@7e200000/i2c1"; + i2s_pins = "/soc/gpio@7e200000/i2s"; + sdio_pins = "/soc/gpio@7e200000/sdio_pins"; + bt_pins = "/soc/gpio@7e200000/bt_pins"; + uart0_pins = "/soc/gpio@7e200000/uart0_pins"; + uart1_pins = "/soc/gpio@7e200000/uart1_pins"; + audio_pins = "/soc/gpio@7e200000/audio_pins"; + uart0 = "/soc/serial@7e201000"; + bt = "/soc/serial@7e201000/bluetooth"; + sdhost = "/soc/mmc@7e202000"; + i2s = "/soc/i2s@7e203000"; + spi0 = "/soc/spi@7e204000"; + spi = "/soc/spi@7e204000"; + spidev0 = "/soc/spi@7e204000/spidev@0"; + spidev1 = "/soc/spi@7e204000/spidev@1"; + i2c0if = "/soc/i2c@7e205000"; + i2c0mux = "/soc/i2c0mux"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c_csi_dsi = "/soc/i2c0mux/i2c@1"; + dpi = "/soc/dpi@7e208000"; + dsi0 = "/soc/dsi@7e209000"; + aux = "/soc/aux@7e215000"; + uart1 = "/soc/serial@7e215040"; + minibt = "/soc/serial@7e215040/bluetooth"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + pwm = "/soc/pwm@7e20c000"; + mmc = "/soc/mmc@7e300000"; + sdhci = "/soc/mmc@7e300000"; + hvs = "/soc/hvs@7e400000"; + dsi1 = "/soc/dsi@7e700000"; + i2c1 = "/soc/i2c@7e804000"; + usb = "/soc/usb@7e980000"; + ethernet = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1"; + eth_phy = "/soc/usb@7e980000/usb-port@1/usb-port@1/ethernet@1/mdio/ethernet-phy@1"; + dma = "/soc/dma@7e007000"; + intc = "/soc/interrupt-controller@7e00b200"; + watchdog = "/soc/watchdog@7e100000"; + pm = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + pixelvalve0 = "/soc/pixelvalve@7e206000"; + pixelvalve1 = "/soc/pixelvalve@7e207000"; + thermal = "/soc/thermal@7e212000"; + i2c2 = "/soc/i2c@7e805000"; + vec = "/soc/vec@7e806000"; + pixelvalve2 = "/soc/pixelvalve@7e807000"; + hdmi = "/soc/hdmi@7e902000"; + v3d = "/soc/v3d@7ec00000"; + vc4 = "/soc/gpu"; + local_intc = "/soc/local_intc@40000000"; + mmcnr = "/soc/mmcnr@7e300000"; + brcmf = "/soc/mmcnr@7e300000/wifi@1"; + firmwarekms = "/soc/firmwarekms@7e600000"; + smi = "/soc/smi@7e600000"; + csi0 = "/soc/csi@7e800000"; + csi1 = "/soc/csi@7e801000"; + axiperf = "/soc/axiperf"; + firmware = "/soc/firmware"; + firmware_clocks = "/soc/firmware/clocks"; + vcio = "/soc/firmware/vcio"; + expgpio = "/soc/firmware/expgpio"; + power = "/soc/power"; + vchiq = "/soc/mailbox@7e00b840"; + audio = "/soc/mailbox@7e00b840/bcm2835_audio"; + fb = "/soc/fb"; + sound = "/soc/sound"; + clk_osc = "/clocks/clk-osc"; + clk_usb = "/clocks/clk-usb"; + usbphy = "/phy"; + cpus = "/cpus"; + cpu0 = "/cpus/cpu@0"; + cpu1 = "/cpus/cpu@1"; + cpu2 = "/cpus/cpu@2"; + cpu3 = "/cpus/cpu@3"; + l2 = "/cpus/l2-cache0"; + cam1_reg = "/cam1_regulator"; + cam1_clk = "/cam1_clk"; + cam0_regulator = "/cam0_regulator"; + cam0_clk = "/cam0_clk"; + cam0_reg = "/cam_dummy_reg"; + cam_dummy_reg = "/cam_dummy_reg"; + leds = "/leds"; + act_led = "/leds/led-act"; + pwr_led = "/leds/led-pwr"; + vdd_3v3_reg = "/fixedregulator_3v3"; + vdd_5v0_reg = "/fixedregulator_5v0"; + }; +}; diff --git a/lab7/test/lib/dtb_parse/types.h b/lab7/test/lib/dtb_parse/types.h new file mode 100644 index 000000000..94f612c66 --- /dev/null +++ b/lab7/test/lib/dtb_parse/types.h @@ -0,0 +1,26 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#define NULL ((void*)0) + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) +#endif diff --git a/lab7/test/lib/list/Makefile b/lab7/test/lib/list/Makefile new file mode 100644 index 000000000..764af75c6 --- /dev/null +++ b/lab7/test/lib/list/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/list.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab7/test/lib/list/test b/lab7/test/lib/list/test new file mode 100755 index 000000000..dd63c9895 Binary files /dev/null and b/lab7/test/lib/list/test differ diff --git a/lab7/test/lib/list/test.c b/lab7/test/lib/list/test.c new file mode 100644 index 000000000..b568a42a4 --- /dev/null +++ b/lab7/test/lib/list/test.c @@ -0,0 +1,59 @@ +#include "lib/list.h" +#include +#include +#include +struct student{ + int id; + char name[100]; + struct list_head list; +}; + +struct student* create_student(int id, char* name){ + struct student* s = (struct student*)malloc(sizeof(struct student)); + s->id = id; + strcpy(s->name, name); + return s; +} +void print_student(struct student* s){ + printf("------------------------------------------\n"); + printf(" id: %d\n", s->id); + printf(" name: %s\n", s->name); + printf("------------------------------------------\n"); +} +int main(void){ + struct list_head* node, head; + INIT_LIST_HEAD(&head); + + if(list_empty(&head)){ + printf("List is empty\n"); + } + list_add(&create_student(13, "xiaobye")->list, &head); + list_add(&create_student(35, "test01")->list, &head); + list_add(&create_student(34, "test02")->list, &head); + + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + if(!list_empty(&head)){ + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + list_del(head.next); + list_for_each(node, &head){ + struct student* s = list_entry(node, struct student, list); + print_student(s); + } + } + + + return 0; +} + diff --git a/lab7/test/lib/malloc/.gdb_history b/lab7/test/lib/malloc/.gdb_history new file mode 100644 index 000000000..1b332373d --- /dev/null +++ b/lab7/test/lib/malloc/.gdb_history @@ -0,0 +1,9 @@ +b main +run +ni +x/gx $rax +x/gx $rax - 0x10 + call malloc(1) +x/gx $rax - 0x10 +x/gx 0x5555555592c0 +quit diff --git a/lab7/test/lib/malloc/Makefile b/lab7/test/lib/malloc/Makefile new file mode 100644 index 000000000..2aedecaf1 --- /dev/null +++ b/lab7/test/lib/malloc/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/simple_malloc.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab7/test/lib/malloc/test b/lab7/test/lib/malloc/test new file mode 100755 index 000000000..194c23579 Binary files /dev/null and b/lab7/test/lib/malloc/test differ diff --git a/lab7/test/lib/malloc/test.c b/lab7/test/lib/malloc/test.c new file mode 100644 index 000000000..374f6deff --- /dev/null +++ b/lab7/test/lib/malloc/test.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include "lib/simple_malloc.h" + +#define RANGE 1000 +int main(void){ + void* cur,* next; + size_t req_size, real_size; + void* p = mmap( NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 ); + init_malloc_state(p); + srand((unsigned)time(0)); + + for(int i = 0 ; i < 30 ; i++){ + req_size = (uint64_t)rand() % RANGE; + cur = simple_malloc(req_size); + next = get_remainder(); + real_size = (uint64_t)next - (uint64_t)cur; + printf("cur: %p, next: %p, request size: %lu, real size: %lu, legal: %d\n", cur, next , req_size, real_size, (req_size <= real_size) && !(real_size % 16)); + } + + return 0; +} diff --git a/lab7/test/lib/malloc/test.py b/lab7/test/lib/malloc/test.py new file mode 100644 index 000000000..cce0d171c --- /dev/null +++ b/lab7/test/lib/malloc/test.py @@ -0,0 +1,9 @@ +def req2size(val, a): + if val < 16: + print(val,": ", hex(32)) + else: + print(val,": ",hex((val + 16 + (a - 1)) & ~(a-1))) + +for i in range(0, 64): + req2size(i, 16) + diff --git a/lab7/test/lib/ring_buffer/.gdb_history b/lab7/test/lib/ring_buffer/.gdb_history new file mode 100644 index 000000000..b7bc3d7af --- /dev/null +++ b/lab7/test/lib/ring_buffer/.gdb_history @@ -0,0 +1,17 @@ +run +quit +file main +run +p rbuf +quit +quit +run +x/gx 0x555555556008 +p rbuf->buf[rbuf->head] +s +ni +quit +b main +run +n +quit diff --git a/lab7/test/lib/ring_buffer/Makefile b/lab7/test/lib/ring_buffer/Makefile new file mode 100644 index 000000000..ec3d806b1 --- /dev/null +++ b/lab7/test/lib/ring_buffer/Makefile @@ -0,0 +1,2 @@ +all: + gcc main.c ring_buffer.c -o main -g -O0 diff --git a/lab7/test/lib/ring_buffer/main b/lab7/test/lib/ring_buffer/main new file mode 100755 index 000000000..bc8cc09fa Binary files /dev/null and b/lab7/test/lib/ring_buffer/main differ diff --git a/lab7/test/lib/ring_buffer/main.c b/lab7/test/lib/ring_buffer/main.c new file mode 100644 index 000000000..ea70d0e9b --- /dev/null +++ b/lab7/test/lib/ring_buffer/main.c @@ -0,0 +1,50 @@ +#include "ring_buffer.h" +#include +#include +char* s = "abcdefghijklmn"; +int main(void){ + char b[10]; + ring_buffer* rbuf = create_ring_buf(10); + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } + + ring_buf_write(rbuf, s, 8); + + if(!ring_buf_is_empty(rbuf)){ + printf("Ring buffer is has some contant now!\n"); + int i = ring_buf_read(rbuf, b, 100); + b[i] = '\0'; + + printf("%d: %s\n", i, b); + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } + } + printf("%lu\n", ring_buf_write(rbuf, s, 16)); + if(ring_buf_is_full(rbuf)){ + printf("Ring buffer is full now!\n"); + } + + int i = ring_buf_read(rbuf, b, 4); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + i = ring_buf_write(rbuf, b, 10); + printf("%d\n", i); + + i = ring_buf_read(rbuf, b, 7); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + i = ring_buf_read(rbuf, b, 10); + b[i] = '\0'; + printf("%d: %s\n", i, b); + + if(ring_buf_is_full(rbuf)){ + printf("Ring buffer is full now!\n"); + } + if(ring_buf_is_empty(rbuf)){ + printf("Ring buffer is empty now!\n"); + } +} diff --git a/lab7/test/lib/ring_buffer/ring_buffer.c b/lab7/test/lib/ring_buffer/ring_buffer.c new file mode 100644 index 000000000..a5e7e3612 --- /dev/null +++ b/lab7/test/lib/ring_buffer/ring_buffer.c @@ -0,0 +1,42 @@ +#include "ring_buffer.h" +#include +ring_buffer* create_ring_buf(size_t s){ + ring_buffer* tmp = (ring_buffer*)malloc(sizeof(ring_buffer)); + tmp->buf = (uint8_t*)malloc(s + 1); + tmp->size = s; + tmp->head = 0; + tmp->tail = 0; + return tmp; +} + +uint8_t ring_buf_is_empty(ring_buffer* rbuf){ + if(rbuf->head == rbuf->tail) return 1; + return 0; +} +uint8_t ring_buf_is_full(ring_buffer* rbuf){ + if((rbuf->tail + 1) % (rbuf->size + 1) == rbuf->head) return 1; + return 0; +} +size_t ring_buf_write(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_full(rbuf) && count < s){ + rbuf->buf[rbuf->tail] = data[count]; + + rbuf->tail = (rbuf->tail + 1) % (rbuf->size + 1); + count = count + 1; + } + return count; +} +size_t ring_buf_read(ring_buffer* rbuf, uint8_t* data, size_t s){ + size_t count = 0; + + while(!ring_buf_is_empty(rbuf) && count < s){ + data[count] = rbuf->buf[rbuf->head]; + + rbuf->head = (rbuf->head + 1) % (rbuf->size + 1); + count = count + 1; + } + return count; +} + diff --git a/lab7/test/lib/ring_buffer/ring_buffer.h b/lab7/test/lib/ring_buffer/ring_buffer.h new file mode 100644 index 000000000..61c0431d4 --- /dev/null +++ b/lab7/test/lib/ring_buffer/ring_buffer.h @@ -0,0 +1,17 @@ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ +#include "types.h" + +typedef struct{ + size_t size; + uint64_t head; + uint64_t tail; + uint8_t* buf; +}ring_buffer; + +extern ring_buffer* create_ring_buf(size_t); +extern size_t ring_buf_write(ring_buffer*, uint8_t*, size_t); +extern size_t ring_buf_read(ring_buffer*, uint8_t*, size_t); +extern uint8_t ring_buf_is_full(ring_buffer*); +extern uint8_t ring_buf_is_empty(ring_buffer*); +#endif diff --git a/lab7/test/lib/ring_buffer/types.h b/lab7/test/lib/ring_buffer/types.h new file mode 100644 index 000000000..94f612c66 --- /dev/null +++ b/lab7/test/lib/ring_buffer/types.h @@ -0,0 +1,26 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +typedef unsigned long int uint64_t; +typedef unsigned int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; + +typedef long int int64_t; +typedef int int32_t; +typedef short int int16_t; +typedef signed char int8_t; + +typedef uint64_t size_t; +typedef int64_t ssize_t; + +#define NULL ((void*)0) + +#define offset_of(type, member) \ + ((uint64_t) &((type*)0)->member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) ((val + (align - 1)) & ~(align - 1)) +#endif diff --git a/lab7/test/lib/string/.gdb_history b/lab7/test/lib/string/.gdb_history new file mode 100644 index 000000000..d0d68342a --- /dev/null +++ b/lab7/test/lib/string/.gdb_history @@ -0,0 +1,47 @@ +b main +run +n +quit +run +b main +run +n +quit +b main +run +n +run +n +s +s +n +x/gx rax +x/gx $rax +run +s +n +s +x/bx s +s +p c +n +n +quit +b main +run +s +x/s delim +s +s +ni +n +ni +x/s s +x/s pos +x/b pos +x/bx pos +n +n +s +s +quit diff --git a/lab7/test/lib/string/Makefile b/lab7/test/lib/string/Makefile new file mode 100644 index 000000000..e7e0f12c1 --- /dev/null +++ b/lab7/test/lib/string/Makefile @@ -0,0 +1,5 @@ +all: + gcc test.c ../../../lib/string.c -I ../../../include -o test -g + +clean: + rm test diff --git a/lab7/test/lib/string/test b/lab7/test/lib/string/test new file mode 100755 index 000000000..a0a7ea144 Binary files /dev/null and b/lab7/test/lib/string/test differ diff --git a/lab7/test/lib/string/test.c b/lab7/test/lib/string/test.c new file mode 100644 index 000000000..b23d13172 --- /dev/null +++ b/lab7/test/lib/string/test.c @@ -0,0 +1,31 @@ + +// C code to demonstrate working of +// strtok +#include +#include "string.h" + +// Driver function +int main() +{ + // Declaration of string + char *gfg = "setTimeout 123"; + + // Declaration of delimiter + const char s[4] = "-"; + char* tok; + + // Use of strtok + // get first token + tok = strtok(gfg, s); + + // Checks for delimiter + while (tok != 0) { + printf(" %s\n", tok); + + // Use of strtok + // go through other tokens + tok = strtok(0, s); + } + + return (0); +} diff --git a/lab7/tmp b/lab7/tmp new file mode 100644 index 000000000..cfe6ea8df --- /dev/null +++ b/lab7/tmp @@ -0,0 +1,1449 @@ +sudo qemu-system-aarch64 -M raspi3b -kernel /home/xiaobye/Documents/OSDI/osc2022/lab2/build/kernel8.img -display none -serial null -serial stdio -initrd tools/cpio/initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb + { + compatible ; + model ; + #address-cells ; + #size-cells ; + interrupt-parent ; + memory@0 { + reg ; + device_type ; + } + aliases { + serial0 ; + serial1 ; + audio ; + aux ; + sound ; + soc ; + dma ; + intc ; + watchdog ; + random ; + mailbox ; + gpio ; + uart0 ; + uart1 ; + sdhost ; + mmc ; + mmc1 ; + mmc0 ; + i2s ; + i2c0 ; + i2c1 ; + i2c10 ; + spi0 ; + spi1 ; + spi2 ; + usb ; + leds ; + fb ; + thermal ; + axiperf ; + i2c2 ; + ethernet0 ; + } + chosen { + linux,initrd-end ; + linux,initrd-start ; + bootargs ; + } + reserved-memory { + #address-cells ; + #size-cells ; + ranges ; + phandle ; + linux,cma { + compatible ; + size ; + reusable ; + linux,cma-default ; + phandle ; + } + } + thermal-zones { + cpu-thermal { + polling-delay-passive ; + polling-delay ; + thermal-sensors ; + coefficients ; + phandle ; + cooling-maps { + } + } + } + soc { + compatible ; + #address-cells ; + #size-cells ; + ranges ; + dma-ranges ; + phandle ; + txp@7e004000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + cprman@7e101000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + firmware ; + phandle ; + } + mailbox@7e00b880 { + compatible ; + reg ; + interrupts ; + #mbox-cells ; + phandle ; + } + gpio@7e200000 { + compatible ; + reg ; + interrupts ; + gpio-controller ; + #gpio-cells ; + interrupt-controller ; + #interrupt-cells ; + gpio-ranges ; + pinctrl-names ; + gpio-line-names ; + phandle ; + dpi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + emmc_gpio34 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + emmc_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk0_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio5 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio6 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpclk2_gpio43 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + i2c0_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1_gpio44 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio22 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pcm_gpio28 { + brcm,pins ; + brcm,function ; + phandle ; + } + sdhost_gpio48 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio7 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_gpio35 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi1_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi2_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio32 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_gpio36 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart0_ctsrts_gpio38 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio14 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio16 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio32 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio30 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + uart1_ctsrts_gpio42 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c_slave_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + jtag_gpio4 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio12 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio18 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm0_gpio40 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio13 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio19 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio41 { + brcm,pins ; + brcm,function ; + phandle ; + } + pwm1_gpio45 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + dpi_18bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_18bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio0 { + brcm,pins ; + brcm,function ; + phandle ; + } + dpi_16bit_cpadhi_gpio2 { + brcm,pins ; + brcm,function ; + phandle ; + } + gpioout { + brcm,pins ; + brcm,function ; + phandle ; + } + alt0 { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + spi0_cs_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c0 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2c1 { + brcm,pins ; + brcm,function ; + phandle ; + } + i2s { + brcm,pins ; + brcm,function ; + phandle ; + } + sdio_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + bt_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart0_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + uart1_pins { + brcm,pins ; + brcm,function ; + brcm,pull ; + phandle ; + } + audio_pins { + brcm,pins ; + brcm,function ; + phandle ; + } + } + serial@7e201000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + arm,primecell-periphid ; + cts-event-workaround ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + status ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + mmc@7e202000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + bus-width ; + brcm,overclock-50 ; + brcm,pio-limit ; + firmware ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + i2s@7e203000 { + compatible ; + reg ; + clocks ; + status ; + dmas ; + dma-names ; + #sound-dai-cells ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + spi@7e204000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + dmas ; + dma-names ; + pinctrl-names ; + pinctrl-0 ; + cs-gpios ; + phandle ; + spidev@0 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + spidev@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + spi-max-frequency ; + phandle ; + } + } + i2c@7e205000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + i2c0mux { + compatible ; + #address-cells ; + #size-cells ; + i2c-parent ; + pinctrl-names ; + status ; + pinctrl-0 ; + pinctrl-1 ; + phandle ; + i2c@0 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + i2c@1 { + reg ; + #address-cells ; + #size-cells ; + phandle ; + } + } + dpi@7e208000 { + compatible ; + reg ; + clocks ; + clock-names ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + dsi@7e209000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + aux@7e215000 { + compatible ; + #clock-cells ; + reg ; + clocks ; + phandle ; + } + serial@7e215040 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + skip-init ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + bluetooth { + compatible ; + max-speed ; + shutdown-gpios ; + status ; + phandle ; + } + } + spi@7e215080 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + spi@7e2150c0 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + phandle ; + } + pwm@7e20c000 { + compatible ; + reg ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + #pwm-cells ; + status ; + phandle ; + } + mmc@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + status ; + dmas ; + dma-names ; + brcm,overclock-50 ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + phandle ; + } + hvs@7e400000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + dsi@7e700000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + #clock-cells ; + clocks ; + clock-names ; + clock-output-names ; + status ; + power-domains ; + phandle ; + } + i2c@7e804000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + pinctrl-names ; + pinctrl-0 ; + clock-frequency ; + phandle ; + } + usb@7e980000 { + compatible ; + reg ; + interrupts ; + #address-cells ; + #size-cells ; + clocks ; + clock-names ; + phys ; + phy-names ; + interrupt-names ; + power-domains ; + phandle ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + usb-port@1 { + compatible ; + reg ; + #address-cells ; + #size-cells ; + ethernet@1 { + compatible ; + reg ; + phandle ; + mdio { + #address-cells ; + #size-cells ; + ethernet-phy@1 { + reg ; + microchip,led-modes ; + microchip,eee-enabled ; + microchip,tx-lpi-timer ; + microchip,downshift-after ; + phandle ; + } + } + } + } + } + } + dma@7e007000 { + compatible ; + reg ; + interrupts ; + interrupt-names ; + #dma-cells ; + brcm,dma-channel-mask ; + phandle ; + } + interrupt-controller@7e00b200 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + interrupts ; + phandle ; + } + watchdog@7e100000 { + compatible ; + #power-domain-cells ; + #reset-cells ; + reg ; + clocks ; + clock-names ; + system-power-controller ; + phandle ; + } + rng@7e104000 { + compatible ; + reg ; + interrupts ; + phandle ; + } + pixelvalve@7e206000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + pixelvalve@7e207000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + thermal@7e212000 { + compatible ; + reg ; + clocks ; + #thermal-sensor-cells ; + status ; + phandle ; + } + i2c@7e805000 { + compatible ; + reg ; + interrupts ; + clocks ; + #address-cells ; + #size-cells ; + status ; + clock-frequency ; + phandle ; + } + vec@7e806000 { + compatible ; + reg ; + clocks ; + interrupts ; + status ; + power-domains ; + phandle ; + } + pixelvalve@7e807000 { + compatible ; + reg ; + interrupts ; + status ; + phandle ; + } + hdmi@7e902000 { + compatible ; + reg ; + reg-names ; + interrupts ; + ddc ; + clocks ; + clock-names ; + dmas ; + dma-names ; + status ; + power-domains ; + hpd-gpios ; + phandle ; + } + v3d@7ec00000 { + compatible ; + reg ; + interrupts ; + power-domains ; + status ; + phandle ; + } + gpu { + compatible ; + status ; + raspberrypi,firmware ; + phandle ; + } + local_intc@40000000 { + compatible ; + reg ; + interrupt-controller ; + #interrupt-cells ; + interrupt-parent ; + phandle ; + } + mmcnr@7e300000 { + compatible ; + reg ; + interrupts ; + clocks ; + dmas ; + dma-names ; + brcm,overclock-50 ; + non-removable ; + status ; + pinctrl-names ; + pinctrl-0 ; + bus-width ; + #address-cells ; + #size-cells ; + phandle ; + wifi@1 { + reg ; + compatible ; + phandle ; + } + } + firmwarekms@7e600000 { + compatible ; + reg ; + interrupts ; + brcm,firmware ; + status ; + phandle ; + } + smi@7e600000 { + compatible ; + reg ; + interrupts ; + clocks ; + assigned-clocks ; + assigned-clock-rates ; + dmas ; + dma-names ; + status ; + phandle ; + } + csi@7e800000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + phandle ; + } + csi@7e801000 { + compatible ; + reg ; + interrupts ; + clocks ; + clock-names ; + power-domains ; + #address-cells ; + #size-cells ; + #clock-cells ; + status ; + brcm,num-data-lanes ; + phandle ; + } + axiperf { + compatible ; + reg ; + firmware ; + status ; + phandle ; + } + firmware { + compatible ; + #address-cells ; + #size-cells ; + mboxes ; + dma-ranges ; + phandle ; + clocks { + compatible ; + #clock-cells ; + phandle ; + } + vcio { + compatible ; + phandle ; + } + expgpio { + compatible ; + gpio-controller ; + #gpio-cells ; + gpio-line-names ; + status ; + phandle ; + } + } + power { + compatible ; + firmware ; + #power-domain-cells ; + phandle ; + } + mailbox@7e00b840 { + compatible ; + reg ; + interrupts ; + phandle ; + bcm2835_audio { + compatible ; + brcm,firmware ; + brcm,pwm-channels ; + status ; + pinctrl-names ; + pinctrl-0 ; + phandle ; + } + } + gpiomem { + compatible ; + reg ; + } + fb { + compatible ; + firmware ; + status ; + phandle ; + } + sound { + status ; + phandle ; + } + } + clocks { + clk-osc { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + clk-usb { + compatible ; + #clock-cells ; + clock-output-names ; + clock-frequency ; + phandle ; + } + } + phy { + compatible ; + #phy-cells ; + phandle ; + } + arm-pmu { + compatible ; + interrupt-parent ; + interrupts ; + } + timer { + compatible ; + interrupt-parent ; + interrupts ; + always-on ; + } + cpus { + #address-cells ; + #size-cells ; + enable-method ; + phandle ; + cpu@0 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@1 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@2 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + cpu@3 { + device_type ; + compatible ; + reg ; + enable-method ; + cpu-release-addr ; + d-cache-size ; + d-cache-line-size ; + d-cache-sets ; + i-cache-size ; + i-cache-line-size ; + i-cache-sets ; + next-level-cache ; + phandle ; + } + l2-cache0 { + compatible ; + cache-size ; + cache-line-size ; + cache-sets ; + cache-level ; + phandle ; + } + } + cam1_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + gpio ; + phandle ; + } + cam1_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam0_regulator { + compatible ; + regulator-name ; + enable-active-high ; + status ; + phandle ; + } + cam0_clk { + compatible ; + #clock-cells ; + status ; + phandle ; + } + cam_dummy_reg { + compatible ; + regulator-name ; + status ; + phandle ; + } + __overrides__ { + cam0-pwdn-ctrl ; + cam0-pwdn ; + cam0-led-ctrl ; + cam0-led ; + arm_freq ; + cache_line_size ; + uart0 ; + uart1 ; + i2s ; + spi ; + i2c0 ; + i2c1 ; + i2c0_baudrate ; + i2c1_baudrate ; + audio ; + watchdog ; + random ; + sd_overclock ; + sd_force_pio ; + sd_pio_limit ; + sd_debug ; + sdio_overclock ; + axiperf ; + i2c2_iknowwhatimdoing ; + i2c2_baudrate ; + sd_poll_once ; + krnbt ; + krnbt_baudrate ; + act_led_gpio ; + act_led_activelow ; + act_led_trigger ; + pwr_led_gpio ; + pwr_led_activelow ; + pwr_led_trigger ; + eee ; + tx_lpi_timer ; + eth_led0 ; + eth_led1 ; + eth_downshift_after ; + eth_max_speed ; + } + leds { + compatible ; + phandle ; + led-act { + label ; + default-state ; + linux,default-trigger ; + gpios ; + phandle ; + } + led-pwr { + label ; + linux,default-trigger ; + gpios ; + phandle ; + } + } + fixedregulator_3v3 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + fixedregulator_5v0 { + compatible ; + regulator-always-on ; + regulator-max-microvolt ; + regulator-min-microvolt ; + regulator-name ; + phandle ; + } + __symbols__ { + rmem ; + cma ; + cpu_thermal ; + soc ; + txp ; + clocks ; + mailbox ; + gpio ; + dpi_gpio0 ; + emmc_gpio22 ; + emmc_gpio34 ; + emmc_gpio48 ; + gpclk0_gpio4 ; + gpclk1_gpio5 ; + gpclk1_gpio42 ; + gpclk1_gpio44 ; + gpclk2_gpio6 ; + gpclk2_gpio43 ; + i2c0_gpio0 ; + i2c0_gpio28 ; + i2c0_gpio44 ; + i2c1_gpio2 ; + i2c1_gpio44 ; + jtag_gpio22 ; + pcm_gpio18 ; + pcm_gpio28 ; + sdhost_gpio48 ; + spi0_gpio7 ; + spi0_gpio35 ; + spi1_gpio16 ; + spi2_gpio40 ; + uart0_gpio14 ; + uart0_ctsrts_gpio16 ; + uart0_ctsrts_gpio30 ; + uart0_gpio32 ; + uart0_gpio36 ; + uart0_ctsrts_gpio38 ; + uart1_gpio14 ; + uart1_ctsrts_gpio16 ; + uart1_gpio32 ; + uart1_ctsrts_gpio30 ; + uart1_gpio40 ; + uart1_ctsrts_gpio42 ; + i2c_slave_gpio18 ; + jtag_gpio4 ; + pwm0_gpio12 ; + pwm0_gpio18 ; + pwm0_gpio40 ; + pwm1_gpio13 ; + pwm1_gpio19 ; + pwm1_gpio41 ; + pwm1_gpio45 ; + dpi_18bit_cpadhi_gpio0 ; + dpi_18bit_cpadhi_gpio2 ; + dpi_18bit_gpio0 ; + dpi_18bit_gpio2 ; + dpi_16bit_gpio0 ; + dpi_16bit_gpio2 ; + dpi_16bit_cpadhi_gpio0 ; + dpi_16bit_cpadhi_gpio2 ; + gpioout ; + alt0 ; + spi0_pins ; + spi0_cs_pins ; + i2c0_pins ; + i2c1_pins ; + i2s_pins ; + sdio_pins ; + bt_pins ; + uart0_pins ; + uart1_pins ; + audio_pins ; + uart0 ; + bt ; + sdhost ; + i2s ; + spi0 ; + spi ; + spidev0 ; + spidev1 ; + i2c0if ; + i2c0mux ; + i2c0 ; + i2c_csi_dsi ; + dpi ; + dsi0 ; + aux ; + uart1 ; + minibt ; + spi1 ; + spi2 ; + pwm ; + mmc ; + sdhci ; + hvs ; + dsi1 ; + i2c1 ; + usb ; + ethernet ; + eth_phy ; + dma ; + intc ; + watchdog ; + pm ; + random ; + pixelvalve0 ; + pixelvalve1 ; + thermal ; + i2c2 ; + vec ; + pixelvalve2 ; + hdmi ; + v3d ; + vc4 ; + local_intc ; + mmcnr ; + brcmf ; + firmwarekms ; + smi ; + csi0 ; + csi1 ; + axiperf ; + firmware ; + firmware_clocks ; + vcio ; + expgpio ; + power ; + vchiq ; + audio ; + fb ; + sound ; + clk_osc ; + clk_usb ; + usbphy ; + cpus ; + cpu0 ; + cpu1 ; + cpu2 ; + cpu3 ; + l2 ; + cam1_reg ; + cam1_clk ; + cam0_regulator ; + cam0_clk ; + cam0_reg ; + cam_dummy_reg ; + leds ; + act_led ; + pwr_led ; + vdd_3v3_reg ; + vdd_5v0_reg ; + } +} +[simple_malloc.c/init_malloc_state:12] Simple heap start address: 0x8e000 + +[initrdfs.c/initrdfs_init:7] Enter initrdfs_int +[initrdfs.c/initrdfs_init:8] initrd start at 0x8000000 + +[initrdfs.c/initrdfs_init:9] initrd first 4 bytes: 37303730 + +[initrdfs.c/initrdfs_init:23] Start parsing new ascii format's cpio +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 2 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 112, iter->cur: 0x8000070 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: . +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 21 +[cpio.c/cpio_iter_parse:38] f->namesize: 6 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 140, iter->cur: 0x80000fc +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file1 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 34 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 156, iter->cur: 0x8000198 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: file2.txt +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 5 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 116, iter->cur: 0x800020c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 1000 +[cpio.c/cpio_iter_parse:32] f->filesize: 5 +[cpio.c/cpio_iter_parse:38] f->namesize: 10 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 128, iter->cur: 0x800028c +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: test/1234 +[cpio.c/cpio_iter_parse:15] Enter cpio_iter_parse +[cpio.c/cpio_iter_parse:27] f->uid: 0 +[cpio.c/cpio_iter_parse:32] f->filesize: 0 +[cpio.c/cpio_iter_parse:38] f->namesize: 11 +[cpio.c/cpio_iter_parse:44] get f->filename +[cpio.c/cpio_iter_parse:50] get f->data +[cpio.c/cpio_iter_parse:53] count: 124, iter->cur: 0x8000308 +[cpio.c/cpio_iter_parse:54] Leave cpio_iter_parse +[initrdfs.c/initrdfs_init:28] FILE: TRAILER!!! +[initrdfs.c/initrdfs_init:32] Leave initrdfs_int +text_start=0x80000, text_end=0x84000, text_size=16384 +rodata_start=0x84000, rodata_end=0x86000, rodata_size=8192 +data_start=0x86000, data_end=0x87000, data_size=4096 +bss_start=0x87000, bss_end=0x8e000, bss_size=28672 +heap_start=0x8e000 +⠀⠀⠀⠀⠀⠀⢀⡤⣢⠟⢁⣴⣾⡿⠋⢉⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠑⠒⠦⢄⣀⣴⠟⢡⣠⣼⣿⡿⢳⣄⡀⠀⠀ +⠀⠀⠀⠀⠀⢀⣾⡿⠃⣠⣿⣿⠿⠂⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢲⡿⠋⢰⣾⣿⣿⡟⠀⠀⠈⠙⢆⠀ +⠀⠀⠀⠀⠀⡜⠻⣷⣾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣁⣰⢸⣿⢻⠟⢀⠀⠀⠀⠀⠀⠁ +⠀⠀⠀⠀⠰⠀⠀⢙⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣯⡀⠀⢃⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⣼⠀⢀⠀⠀⠀⠀⠀⢠⣷⡀⠀⠀⠀⠀⡀⠄⠀⠀⠀⠀⢻⣿⣿⣿⣧⠑⠀⣢⡄⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⡰⠃⢀⠄⠀⠀⠀⠀⣼⡿⡆⢸⠀⠀⠀⠀⠀⠈⣿⢷⡄⠀⠀⠀⠱⡀⠰⡀⠀⠀⠈⢿⣿⣿⣿⣧⠀⢸⣧⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠡⢢⠋⠀⠀⠀⠀⣼⡟⠀⣇⢸⡆⠀⠀⠀⡄⠀⢿⠀⢳⡄⠀⠀⠀⢳⠀⢳⠀⠀⠀⠈⣿⣿⣿⣿⣷⣘⡟⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⣸⡿⢤⠤⠸⡸⣷⠀⠀⠀⢱⠀⣾⡤⠤⢿⡤⢀⡀⠀⢧⠘⡆⠀⠀⠀⢸⡟⠻⢿⠟⣿⣷⡄⠀⠀⠀ +⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⢰⡿⢠⠇⠀⠀⢳⣿⢇⠀⠀⠈⡇⣿⡇⠀⠀⠻⣄⠀⠀⠘⡆⡇⠀⠀⠀⠀⣇⢀⡏⠀⣿⡿⣄⠀⠀⠀ +⠀⠀⠀⠀⢰⠁⠀⠀⠀⠀⣿⠁⣄⣀⣀⡀⠈⢿⡜⡄⠀⠀⢹⣿⡇⠐⢄⣀⠘⢧⡀⠀⠹⣿⠀⠀⠀⠀⢸⣿⣷⣶⣿⡇⢹⡇⠀⠀ +⠀⠀⠀⠀⠾⠀⠀⠀⠀⢸⣧⣾⠟⢉⣽⣿⣦⠈⢷⡘⣆⠀⠸⡟⣷⣶⠟⠛⢻⣷⣦⣀⠀⢻⠀⠀⠀⠀⢸⣏⣩⣼⣿⡇⠈⣷⠀⠀ +⠀⠀⠀⠃⠀⠀⠀⠀⠀⣿⡿⠁⠀⣠⣾⣿⣿⠀⠈⢿⠺⡆⠀⣧⢸⠀⠀⢀⣹⣿⣿⣿⣷⣼⣤⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⣿⠀⠀ +⠀⠀⣠⠄⣀⠀⠀⠀⢠⣿⡇⠀⠀⢻⢻⣟⢿⠀⠀⠈⠣⠈⠓⠾⠀⠀⠀⣿⣿⢿⣿⣿⠘⡇⡞⠀⠀⢠⣾⣿⣿⣿⡏⠀⠀⢹⠀⠀ +⠀⠀⠛⠀⣿⠀⠀⠀⢸⣿⣿⡀⠀⠈⠃⠐⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣄⣐⣠⠏⢠⣿⠁⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀ +⠀⠀⠀⠀⢹⡆⠰⡀⢸⡟⠩⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⢸⣿⣿⣿⠟⠀⠀⠀⠘⠀⠀ +⠀⠀⠀⠀⢎⣿⡀⢱⢞⣁⣀⡿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⡏⡼⠀⠀⠀⣾⣿⠋⠁⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠈⠿⠻⡇⠀⠀⠒⠢⢵⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣽⠁⠀⠀⢠⡿⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⠀⡟⣦⡀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢿⡇⠀⠀⡄⣸⣇⣼⣀⣀⣀⠀⠀⠀⠀⠀⠀ +⡀⠀⠀⠀⠀⠀⢰⠇⣿⢸⣦⡀⠀⠀⠀⠀⠈⠲⣄⡀⠀⠀⠀⠀⠀⣀⡤⠒⢉⡴⠃⣸⠀⠀⢰⣿⣿⣿⠃⡤⠊⠁⠉⠑⢄⠀⠀⠀ +⡇⠀⠀⠀⠀⠀⢸⠀⣿⣾⣿⢿⠲⣄⠀⠀⠀⠀⠘⠟⣦⣤⣴⡒⠉⢀⡠⠖⠉⠀⣠⠃⠀⣠⣿⣿⡿⠁⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣿⠛⢿⠈⢢⠏⠀⠀⠀⠀⠀⣰⣏⣀⣿⠗⠊⠁⠀⠀⣠⣾⠃⢀⡴⠿⠛⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⢀⠇⠀⠈⢠⠃⠀⠀⠀⠀⠀⢰⠟⠁⠀⢹⢇⠀⣀⠴⠊⡱⠥⠔⠋⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⡟⠀⢀⡴⠁⠀⠀⠀⠀⠀⢠⡟⠀⠀⣰⢿⡘⣾⡅⠀⠀⠀⠀⢀⠄⠀⢠⠏⢀⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⢸⠀⣰⣿⠀⠀⠀⠀⠀⠀⢠⣿⠃⢀⡾⡇⠘⠻⡿⢷⡀⠀⠀⠒⠁⠀⢠⠏⢀⠏⣸⠃⢻⠏⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⣧⣾⣹⣿⠀⠀⠀⠀⠀⢠⠏⢉⠀⡞⣰⡇⠀⣴⣥⠞⢷⠀⠀⠀⠀⣠⠎⠀⠸⣶⠋⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀ + +# diff --git a/lab7/tools/AUX_PERIPHERALS b/lab7/tools/AUX_PERIPHERALS new file mode 100644 index 000000000..324eb3019 --- /dev/null +++ b/lab7/tools/AUX_PERIPHERALS @@ -0,0 +1,23 @@ +0x7E215000 AUX_IRQ Auxiliary Interrupt status 3 +0x7E215004 AUX_ENABLES Auxiliary enables 3 +0x7E215040 AUX_MU_IO_REG Mini Uart I/O Data 8 +0x7E215044 AUX_MU_IER_REG Mini Uart Interrupt Enable 8 +0x7E215048 AUX_MU_IIR_REG Mini Uart Interrupt Identify 8 +0x7E21504C AUX_MU_LCR_REG Mini Uart Line Control 8 +0x7E215050 AUX_MU_MCR_REG Mini Uart Modem Control 8 +0x7E215054 AUX_MU_LSR_REG Mini Uart Line Status 8 +0x7E215058 AUX_MU_MSR_REG Mini Uart Modem Status 8 +0x7E21505C AUX_MU_SCRATCH Mini Uart Scratch 8 +0x7E215060 AUX_MU_CNTL_REG Mini Uart Extra Control 8 +0x7E215064 AUX_MU_STAT_REG Mini Uart Extra Status 32 +0x7E215068 AUX_MU_BAUD_REG Mini Uart Baudrate 16 +0x7E215080 AUX_SPI0_CNTL0_REG SPI 1 Control register 0 32 +0x7E215084 AUX_SPI0_CNTL1_REG SPI 1 Control register 1 8 +0x7E215088 AUX_SPI0_STAT_REG SPI 1 Status 32 +0x7E215090 AUX_SPI0_IO_REG SPI 1 Data 32 +0x7E215094 AUX_SPI0_PEEK_REG SPI 1 Peek 16 +0x7E2150C0 AUX_SPI1_CNTL0_REG SPI 2 Control register 0 32 +0x7E2150C4 AUX_SPI1_CNTL1_REG SPI 2 Control register 1 8 +0x7E2150C8 AUX_SPI1_STAT_REG SPI 2 Status 32 +0x7E2150D0 AUX_SPI1_IO_REG SPI 2 Data 32 +0x7E2150D4 AUX_SPI1_PEEK_REG SPI 2 Peek 16 diff --git a/lab7/tools/GPIO b/lab7/tools/GPIO new file mode 100644 index 000000000..ad2b10794 --- /dev/null +++ b/lab7/tools/GPIO @@ -0,0 +1,43 @@ +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200000 GPFSEL0 GPIO Function Select 0 32 R/W +0x7E200004 GPFSEL1 GPIO Function Select 1 32 R/W +0x7E200008 GPFSEL2 GPIO Function Select 2 32 R/W +0x7E20000C GPFSEL3 GPIO Function Select 3 32 R/W +0x7E200010 GPFSEL4 GPIO Function Select 4 32 R/W +0x7E200014 GPFSEL5 GPIO Function Select 5 32 R/W +0x7E200018 - Reserved - - +0x7E20001C GPSET0 GPIO Pin Output Set 0 32 W +0x7E200020 GPSET1 GPIO Pin Output Set 1 32 W +0x7E200024 - Reserved - - +0x7E200028 GPCLR0 GPIO Pin Output Clear 0 32 W +0x7E20002C GPCLR1 GPIO Pin Output Clear 1 32 W +0x7E200030 - Reserved - - +0x7E200034 GPLEV0 GPIO Pin Level 0 32 R +0x7E200038 GPLEV1 GPIO Pin Level 1 32 R +0x7E20003C - Reserved - - +0x7E200040 GPEDS0 GPIO Pin Event Detect Status 0 32 R/W +0x7E200044 GPEDS1 GPIO Pin Event Detect Status 1 32 R/W +0x7E200048 - Reserved - - +0x7E20004C GPREN0 GPIO Pin Rising Edge Detect Enable 0 32 R/W +0x7E200050 GPREN1 GPIO Pin Rising Edge Detect Enable 1 32 R/W +0x7E200054 - Reserved - - +0x7E200058 GPFEN0 GPIO Pin Falling Edge Detect Enable 0 32 R/W +0x7E20005C GPFEN1 GPIO Pin Falling Edge Detect Enable 1 32 R/W +0x7E200060 - Reserved - - +0x7E200064 GPHEN0 GPIO Pin High Detect Enable 0 32 R/W +0x7E200068 GPHEN1 GPIO Pin High Detect Enable 1 32 R/W +0x7E20006C - Reserved - - +0x7E200070 GPLEN0 GPIO Pin Low Detect Enable 0 32 R/W +0x7E200074 GPLEN1 GPIO Pin Low Detect Enable 1 32 R/W +0x7E200078 - Reserved - - +0x7E20007C GPAREN0 GPIO Pin Async. Rising Edge Detect 0 32 R/W +0x7E200080 GPAREN1 GPIO Pin Async. Rising Edge Detect 1 32 R/W +0x7E200084 - Reserved - - +0x7E200088 GPAFEN0 GPIO Pin Async. Falling Edge Detect 0 32 R/W +0x7E20008C GPAFEN1 GPIO Pin Async. Falling Edge Detect 1 32 R/W +0x7E200090 - Reserved - - +0x7E200094 GPPUD GPIO Pin Pull-up/down Enable 32 R/W +0x7E200098 GPPUDCLK0 GPIO Pin Pull-up/down Enable Clock 0 32 R/W +0x7E20009C GPPUDCLK1 GPIO Pin Pull-up/down Enable Clock 1 32 R/W +0x7E2000A0 - Reserved - - +0x7E2000B0 - Test 4 R/W diff --git a/lab7/tools/cpio/.gdb_history b/lab7/tools/cpio/.gdb_history new file mode 100644 index 000000000..123309d64 --- /dev/null +++ b/lab7/tools/cpio/.gdb_history @@ -0,0 +1,58 @@ +quit +target remote:1234 +file ../../build/kernel8.elf +c +ni +c +ni +quit +file ../../build/kernel8.elf +x/gx 9a8 +x/gx 0x9a8 +target remote:1234 +c +x/i 9a8 +x/i 0x9a8 +x/i 0x9a4 +x/i 0x9a8 +b 0x9a8 +b *0x9a8 +file ../../build/kernel8.elf +b *0x9a8 +target remote:1234 +c +ni +ni +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +b *0x9a4 +x/i 0x9a4 +target remote:1234 +target remote:1234 +info b +del 1 +del 2 +c +c +b *0x9a4 +b *0x9a8 +c +quit diff --git a/lab7/tools/cpio/Makefile b/lab7/tools/cpio/Makefile new file mode 100644 index 000000000..1cbe92c74 --- /dev/null +++ b/lab7/tools/cpio/Makefile @@ -0,0 +1,35 @@ +CC = aarch64-linux-gnu-gcc +CPP = aarch64-linux-gnu-cpp +override CFLAGS += \ + -nostdlib \ + -nodefaultlibs \ + -ffreestanding \ + -nostartfiles \ + -mgeneral-regs-only \ + -fno-builtin \ + +LDFLAGS ?= \ + -nostdlib \ + +CXXFLAGS = +LD = aarch64-linux-gnu-ld +OBJCOPY = aarch64-linux-gnu-objcopy +OBJDUMP = aarch64-linux-gnu-objdump +QEMU = qemu-system-aarch64 +RASPI_VER = raspi3b + + +LINKER_FILE = ./linker.ld +HEADERS = $(PWD)/include/ +OUTPUT = $(PWD)/build +KNAME = kernel8 +BNAME = bootloader + +.PHONY: all + + +all: + $(CC) -c -o test.o test.S $(CFLAGS) + $(LD) -T linker.ld -o test.elf test.o $(LDFLAGS) + $(OBJCOPY) -O binary test.elf test.img + diff --git a/lab7/tools/cpio/create_initramfs.sh b/lab7/tools/cpio/create_initramfs.sh new file mode 100755 index 000000000..2736e47fe --- /dev/null +++ b/lab7/tools/cpio/create_initramfs.sh @@ -0,0 +1,4 @@ +#! /bin/sh +cd rootfs +find . | cpio -o -H newc > ../initramfs.cpio +cd .. diff --git a/lab7/tools/cpio/initramfs.cpio b/lab7/tools/cpio/initramfs.cpio new file mode 100644 index 000000000..3269cb83a Binary files /dev/null and b/lab7/tools/cpio/initramfs.cpio differ diff --git a/lab7/tools/cpio/linker.ld b/lab7/tools/cpio/linker.ld new file mode 100644 index 000000000..a550bf32e --- /dev/null +++ b/lab7/tools/cpio/linker.ld @@ -0,0 +1,41 @@ +ENTRY(_start) /* set _start in boot.S as entry point */ + +SECTIONS +{ + . = 0x80000; /* bootloader (start.elf) will loader kernel8.img to 0x80000*/ + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + + . = ALIGN(0x1000); + __text_end = .; + __rodata_start = .; + .rodata : + { + *(.rodata) + } + + . = ALIGN(0x1000); + __rodata_end = .; + __data_start = .; + .data : + { + *(.data) + } + + . = ALIGN(0x1000); + __data_end = .; + __bss_start = .; + .bss : + { + *(.bss) + } + + . = ALIGN(0x1000); + __bss_end = .; + __heap_start = .; + +} diff --git a/lab7/tools/cpio/rootfs/initramfs/vfs1.img b/lab7/tools/cpio/rootfs/initramfs/vfs1.img new file mode 100644 index 000000000..2c41bd71a Binary files /dev/null and b/lab7/tools/cpio/rootfs/initramfs/vfs1.img differ diff --git a/lab7/tools/gen.sh b/lab7/tools/gen.sh new file mode 100755 index 000000000..235b38c28 --- /dev/null +++ b/lab7/tools/gen.sh @@ -0,0 +1,24 @@ +#! /bin/sh +BUS_IO_BASE=0x7E000000 +PHY_IO_BASE=0x3F000000 +echo "/* Register's offset of GPIO */" +grep -v " - " GPIO | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + +echo "" +echo "" +echo "/* Register's offset of UART and SPI */" +grep -v " - " AUX_PERIPHERALS | while read s +do + name=`echo $s | cut -d " " -f2` + addr=`echo $s | cut -d " " -f1` + addr=`(printf "(IO_BASE + 0x%X)\n" $((addr - BUS_IO_BASE)))` + echo "#define $name $addr" +done + + diff --git a/lab7/uart_upload.py b/lab7/uart_upload.py new file mode 100755 index 000000000..9a2a52d80 --- /dev/null +++ b/lab7/uart_upload.py @@ -0,0 +1,69 @@ +#! /usr/bin/python3 + +import sys +import struct +import serial +import os +import time +if len(sys.argv) < 4: + print(sys.argv[0], "", "", "") + sys.exit(-1) + +tty_name = sys.argv[1] +kernel_name = sys.argv[2] +base_addr = int(sys.argv[3], 16) + +ser = None + +def readline(): + os.write(1,b'[From bootloader]: ') + while 1: + c = ser.read(1) + if c == b'\n': + os.write(1, b'\n') + return + elif c != b'\r': + os.write(1, c) + + + +with open(kernel_name, "rb",) as kernel: + kernel_buf = kernel.read() + kernel_size = len(kernel_buf) + + + while(1): + ser = serial.Serial( + # Serial Port to read the data from + port = tty_name, + #Rate at which the information is shared to the communication channel + baudrate = 115200, + timeout = .1 + ) + + # start upload kernel to rasberry pi 3b+ by uart interface + # start header + ser.write(b"A") + ser.flush() + readline() + + # transfer kernel base address and kernel size ( both are 8 bytes ) in little endian + ser.write(struct.pack("member) + +#define container_of(ptr, type, member) \ + ((type* )((char*)ptr - offset_of(type, member))) + +#define ALIGN_UP(val, align) (((uint64_t)(val) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_DOWN(val, align) ((uint64_t)(val) & ~((align) - 1)) + +#define bswap32(n) (((n & 0xff000000) >> 24) | \ + ((n & 0x00ff0000) >> 8) | \ + ((n & 0x0000ff00) << 8) | \ + ((n & 0x000000ff) << 24) ) +#define bswap64(n) (((n & 0xff00000000000000) >> 56) | \ + ((n & 0x00ff000000000000) >> 40) | \ + ((n & 0x0000ff0000000000) >> 24) | \ + ((n & 0x000000ff00000000) >> 8) | \ + ((n & 0x00000000ff000000) << 8) | \ + ((n & 0x0000000000ff0000) << 24)| \ + ((n & 0x000000000000ff00) << 40)| \ + ((n & 0x00000000000000ff) << 56)) + +#define min(x, y) ((x) < (y) ? (x) : (y)) + +#endif diff --git a/lab7/user/user_lib.c b/lab7/user/user_lib.c new file mode 100644 index 000000000..d7d14da24 --- /dev/null +++ b/lab7/user/user_lib.c @@ -0,0 +1,323 @@ +#include "user_lib.h" + +char int_table[] = "0123456789"; +char hex_table[] = "0123456789abcdef"; + +uint64_t getpid(void){ + asm volatile("mov x8, 0\n\t" + "svc 0\n\t" + : + : + ); +} + +size_t uart_read(char *buf, size_t size){ + asm volatile("mov x0, %[buf]\n\t" + "mov x1, %[size]\n\t" + "mov x8, 1\n\t" + "svc 0\n\t" + : + :[buf] "r" (buf), [size] "r" (size) + ); +} + +size_t uart_write(char *buf, size_t size){ + asm volatile("mov x0, %[buf]\n\t" + "mov x1, %[size]\n\t" + "mov x8, 2\n\t" + "svc 0\n\t" + : + :[buf] "r" (buf), [size] "r" (size) + ); +} + +uint64_t fork(void){ + asm volatile("mov x8, 4\n\t" + "svc 0\n\t" + : + : + ); +} + +void debug_info(void){ + asm volatile("mov x8, 5\n\t" + "svc 0\n\t" + : + : + ); +} + +void signal(uint64_t pid, sig_handler handler){ + asm volatile("mov x0, %[pid]\n\t" + "mov x1, %[handler]\n\t" + "mov x8, 8\n\t" + "svc 0\n\t" + : + :[pid] "r" (pid), [handler] "r" (handler) + ); +} + +void kill(uint64_t pid, int signal){ + asm volatile("mov x0, %[pid]\n\t" + "mov x1, %[signal]\n\t" + "mov x8, 9\n\t" + "svc 0\n\t" + : + :[pid] "r" (pid), [signal] "r" (signal) + ); +} + +void delay(uint64_t clock){ + for(uint64_t i = 0 ; i < clock ; i++) asm volatile("nop"); +} + +size_t strlen(const char* s){ + size_t i = 0; + while(s[i++]); + i--; + return i; +} + + +char * itoa(int32_t value, char* str, uint32_t base){ + char buf[32]; + uint32_t val; + volatile int i = 0, j = 0; + + switch(base){ + case 16: + val = (uint32_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} + +char * utoa(uint32_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint32_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; +} +char * ltoa(int64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val; + + switch(base){ + case 16: + val = (uint64_t)value; + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + if(value < 0){ + val = -value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '-'; + buf[++i] = '\0'; + }else{ + val = value; + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} +char * ultoa(uint64_t value, char* str, uint32_t base){ + char buf[32]; + volatile int i = 0, j = 0; + uint64_t val = value; + + switch(base){ + case 16: + do{ + buf[i] = hex_table[val & 15]; + i++; + }while(val >>= 4); + buf[i] = '\0'; + break; + default: + case 10: + do{ + buf[i] = int_table[val % 10]; + i++; + }while(val /= 10); + buf[i] = '\0'; + } + i--; + do{ + str[j] = buf[i]; + j++;i--; + }while(i >= 0); + str[j] = '\0'; + return str; + +} + +uint64_t atoul(const char* str){ + uint64_t val = 0; + const char* ps = str; + while(*ps){ + val *= 10; + val += (*ps - '0'); + ps++; + } + return val; +} + +int32_t printf(char *fmt, ...){ + uint32_t uval; + int32_t val; + int64_t lval; + char str[64], ch; + char* s; + void* addr; + size_t tmp_c; + volatile int32_t count = 0; + va_list ap; + + va_start(ap, fmt); + + while(*fmt){ + char c = *fmt++; + if(c == '%'){ + c = *fmt++; + switch(c){ + case 'u': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 10); + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + break; + case 'd': + val = va_arg(ap, int); + itoa(val, str, 10); + uart_write(str, strlen(str)); + break; + case 'l': + lval = va_arg(ap, int64_t); + ltoa(lval, str, 10); + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + break; + case 'c': + ch = va_arg(ap, int); + uart_write(&ch, 1); + count++; + break; + case 'p': + addr = va_arg(ap, void*); + utoa((uint64_t)addr, str, 16); + + uart_write("0x", 2); + count += 2; + + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + + break; + + break; + case 'x': + uval = va_arg(ap, uint32_t); + utoa(uval, str, 16); + tmp_c = strlen(str); + uart_write(str, tmp_c); + count += tmp_c; + + break; + case 's': + s = va_arg(ap, char*); + tmp_c = strlen(s); + uart_write(s, tmp_c); + count += tmp_c; + break; + case '%': + uart_write("%", 1); + count++; + default: + uart_write("%", 1); + uart_write(&c, 1); + count += 2; + } + }else{ + uart_write(&c, 1); + count++; + } + } + va_end(ap); + return count; +} + diff --git a/lab7/user/user_lib.h b/lab7/user/user_lib.h new file mode 100644 index 000000000..782e21ae8 --- /dev/null +++ b/lab7/user/user_lib.h @@ -0,0 +1,18 @@ +#ifndef _USER_LIB_H_ +#define _USER_LIB_H_ +#include "types.h" +#include + +typedef void (*sig_handler)(); + +extern size_t uart_write(char *, size_t); +extern size_t uart_read(char *, size_t); +extern uint64_t fork(void); +extern uint64_t getpid(void); +extern void debug_info(void); +extern void delay(uint64_t); +extern int32_t printf(char *, ...); +extern void signal(uint64_t, sig_handler); +extern void kill(uint64_t, int); + +#endif diff --git a/lab7/user/user_lib.o b/lab7/user/user_lib.o new file mode 100644 index 000000000..79fb27b61 Binary files /dev/null and b/lab7/user/user_lib.o differ diff --git a/tools/update-branchs.py b/tools/update-branchs.py deleted file mode 100644 index 044ea58cc..000000000 --- a/tools/update-branchs.py +++ /dev/null @@ -1,49 +0,0 @@ -import argparse -import typing - -import yaml -import git - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - - parser.add_argument('file') - - args = parser.parse_args() - - with open(args.file) as f: - ids = yaml.safe_load(f) - - # find origin - repo = git.Repo(".") - - origin = repo.remote(name='origin') - fetch_infos: typing.List[git.remote.FetchInfo] = origin.fetch() - source_branch: git.RemoteReference = origin.refs["0856085-example"] - origin_head = repo.head.ref - source_branch.checkout() - - def exist_branch(name: str) -> bool: - for info in fetch_infos: - if name in info.name: - return True - return False - - push_count = 0 - try: - for idx in ids: - if exist_branch(idx): - print(f'{idx} already exists!') - continue - print(f'create {idx} & push ...') - # create branch - h = repo.create_head(idx) - # push - origin.push(idx) - # remove local - repo.delete_head(h) - push_count += 1 - - print(f'total: {len(ids)}, push {push_count} branch') - finally: - origin_head.checkout() diff --git "a/\350\256\200\346\210\221.md" "b/\350\256\200\346\210\221.md" deleted file mode 100644 index aa0a57571..000000000 --- "a/\350\256\200\346\210\221.md" +++ /dev/null @@ -1,30 +0,0 @@ -# 作業系統總整與實作 課程 2021 - -[英文](README.md) - -給學生繳交作業的儲存庫 - -## 如何繳交作業 - -1. 在 GitHub 複製 ( fork ) [該儲存庫](https://github.com/GrassLab/osc2021) - ![](images/fork_button.png) -2. 撰寫以下資訊在你的 `README.md` - - GitHub 帳號名稱 - - 學號 - - 你的姓名 -3. 設計並實作你的 kernel 在複製出的儲存庫 -4. 建立一個 GitHub 拉取請求 ( pull request ) - - 選擇 `GrassLab/osc2021` 當作 基儲存庫 ( base repository ) 和 `{你的學號}` 當作 基分支 ( base branch ) - - 選擇在你的儲存庫內的分支作為 比較分支 ( compare branch ) - - 用學號與哪一次 lab 命名它 範例: `0856085 lab0` - ![](images/pull_request.png) -5. 我們將會在 lab 截止時接受拉取請求 - -重複 3-5 步去繳交之後的 lab. - -## 範例 - -- 複製的儲存庫: https://github.com/t0037799/osc2021 -- 拉取請求: https://github.com/GrassLab/osc2021/pull/1 - -## Happy Coding ~