├── .gdbinit ├── LICENSE ├── README.md ├── locateguest.c ├── makefile ├── nowhereOS ├── main.c ├── makefile ├── riscv-virt.lds ├── sbi.h ├── sbi.s └── start.s ├── qemustart.sh ├── sageVisor ├── main.c ├── makefile ├── primitives.s ├── riscv-virt.lds ├── sbi.h ├── sbi.s ├── start.s ├── vma.h └── vmspaces.c ├── setup.sh └── sophiaOS ├── api.h ├── application.c ├── main.c ├── makefile ├── primitives.s ├── riscv-virt.lds ├── sbi.h ├── sbi.s ├── start.s ├── syscall.s ├── vma.c └── vma.h /.gdbinit: -------------------------------------------------------------------------------- 1 | target remote localhost:10000 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 4 | 5 | Author : Hirokazu Takahashi 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Educational hypervisor and os for risc-v 2 | 3 | There are 3 components here: 4 | - Sophia OS is a tiny multi-core OS to run a program of the dining philosophers problem. 5 | - Nowhere OS is a tiny single core OS. 6 | - Sagevisor is a tiny hypervisor to run Sophia OS and Nowhere OS. 7 | 8 | # Getting started 9 | Install tools for riscv64 on Ubuntu 24.04LTS 10 | ``` 11 | $ sh setup.sh 12 | ``` 13 | Build the whole code. 14 | ``` 15 | $ make 16 | ``` 17 | Run the hypervisor and OSes. 18 | Sagevisor runs in HS-mode and and the two OSes run in VS and VU modes. 19 | ``` 20 | $ sh qemustart.sh 21 | ``` 22 | 23 | ``` 24 | +-----------------------------------------------+ 25 | | dining philosophers program (runs in VU-mode) | 26 | +-----------------------------------------------+ 27 | +------------------------------+ +-----------------------------------------------+ 28 | | Nowhere OS (runs in VS-mode) | | Sophia OS (runs in VS-mode) | 29 | +------------------------------+ +-----------------------------------------------+ 30 | +---------------------------------------------------------------------------------+ 31 | | Sagevisor hypervisor (runs in HS-mode) | 32 | +---------------------------------------------------------------------------------+ 33 | +---------------------------------------------------------------------------------+ 34 | | OpenSBI (runs in M-mode) | 35 | +---------------------------------------------------------------------------------+ 36 | +---------------------------------------------------------------------------------+ 37 | | riscv64 (qemu) | 38 | +---------------------------------------------------------------------------------+ 39 | ``` 40 | -------------------------------------------------------------------------------- /locateguest.c: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | 36 | void main(int argc, char** argv) 37 | { 38 | Elf64_Ehdr elfheader; 39 | Elf64_Phdr *pheader; 40 | unsigned long paddr; 41 | unsigned long offset = 0UL; 42 | int fd; 43 | int i; 44 | 45 | fd = open(argv[1], O_RDWR); 46 | if (fd < 0) { 47 | perror("open"); 48 | exit(fd); 49 | } 50 | if (read(fd, &elfheader, sizeof(elfheader)) < 0) { 51 | perror("read eheader"); 52 | exit(-1); 53 | } 54 | if (argc >= 3) { 55 | paddr = (unsigned long)strtol(argv[2], NULL, 16); 56 | } else { 57 | paddr = elfheader.e_entry; 58 | } 59 | if (paddr) { 60 | offset = paddr - elfheader.e_entry; 61 | } 62 | if (lseek(fd, elfheader.e_phoff, SEEK_SET) < 0) { 63 | perror("lseek"); 64 | exit(-1); 65 | } 66 | pheader = malloc(elfheader.e_phentsize * elfheader.e_phnum); 67 | if (read(fd, pheader, elfheader.e_phentsize * elfheader.e_phnum) < 0) { 68 | perror("read program header"); 69 | exit(-1); 70 | } 71 | for (i = 0; i < elfheader.e_phnum; i++) { 72 | pheader[i].p_paddr = pheader[i].p_vaddr + offset; 73 | } 74 | if (lseek(fd, elfheader.e_phoff, SEEK_SET) < 0) { 75 | perror("lseek"); 76 | exit(-1); 77 | } 78 | if (write(fd, pheader, elfheader.e_phentsize * elfheader.e_phnum) < 0) { 79 | perror("write program header"); 80 | exit(-1); 81 | } 82 | printf("%s is located at physical address:0x%lx\n", argv[1], paddr); 83 | close(fd); 84 | } 85 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | 2 | PREF=riscv64-unknown-elf- 3 | RVCC = ${PREF}gcc 4 | RVLD = ${PREF}ld 5 | RVAR = ${PREF}ar 6 | RVCFLAGS = -march=rv64g -O2 -mcmodel=medany -ffreestanding -g 7 | 8 | .SUFFIXES: .c .s .o 9 | 10 | .c.o: 11 | $(CC) $(CFLAGS) -c $< 12 | 13 | all: guestOS1 guestOS2 hyper relocate 14 | 15 | relocate: 16 | cc locateguest.c -o locateguest 17 | cp sophiaOS/sophia guest1 18 | cp nowhereOS/nowhere guest2 19 | ./locateguest guest1 0x80600000 20 | ./locateguest guest2 0x84600000 21 | 22 | hyper: 23 | CC=${RVCC} LD=${RVLD} AR=${RVAR} CFLAGS="${RVCFLAGS}" make -C sageVisor 24 | 25 | guestOS1: 26 | CC=${RVCC} LD=${RVLD} AR=${RVAR} CFLAGS="${RVCFLAGS}" make -C sophiaOS 27 | 28 | guestOS2: 29 | CC=${RVCC} LD=${RVLD} AR=${RVAR} CFLAGS="${RVCFLAGS}" make -C nowhereOS 30 | 31 | clean: 32 | -rm -f *.o guest? locateguest 33 | make clean -C nowhereOS 34 | make clean -C sophiaOS 35 | make clean -C sageVisor 36 | -------------------------------------------------------------------------------- /nowhereOS/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | #include "sbi.h" 28 | #include 29 | 30 | #define TRUE 1 31 | #define FALSE 0 32 | 33 | extern void trap_vectors(void); 34 | extern void SetTrapVectors(unsigned long); 35 | 36 | static void _print_message(const char *s, ...) 37 | { 38 | va_list ap; 39 | va_start (ap, s); 40 | 41 | while (*s) { 42 | if (*s == '%' && *(s+1) == 'x') { 43 | unsigned long v = va_arg(ap, unsigned long); 44 | _Bool print_started = FALSE; 45 | int i; 46 | 47 | s += 2; 48 | for (i = 15; i >= 0; i--) { 49 | unsigned long x = (v & 0xFUL << i*4) >> i*4; 50 | if (print_started || x != 0U || i == 0) { 51 | print_started = TRUE; 52 | sbi_debug_console_write_byte((x < 10 ? '0' : 'a' - 10) + x); 53 | } 54 | } 55 | } else { 56 | sbi_debug_console_write_byte(*s++); 57 | } 58 | } 59 | 60 | va_end (ap); 61 | } 62 | 63 | void main(void) 64 | { 65 | SetTrapVectors((unsigned long)trap_vectors); 66 | 67 | _print_message("nowhere guest started\n"); 68 | 69 | while (1) { 70 | static volatile unsigned int loop_count = 0; 71 | if (++loop_count % 0x8000000U == 0U) { 72 | _print_message("nowhere guest is running.\n"); 73 | } 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /nowhereOS/makefile: -------------------------------------------------------------------------------- 1 | 2 | CFLAGS += -msmall-data-limit=0 3 | 4 | .SUFFIXES: .c .s .o 5 | 6 | .c.o: 7 | $(CC) $(CFLAGS) -c $< 8 | 9 | .s.o: 10 | $(CC) $(CFLAGS) -c $< 11 | 12 | all: nowhere 13 | 14 | nowhere: main.o start.o sbi.o riscv-virt.lds 15 | $(LD) *.o -o $@ -T riscv-virt.lds ${LDFLAGS} 16 | 17 | clean: 18 | -rm -f *.o nowhere 19 | -------------------------------------------------------------------------------- /nowhereOS/riscv-virt.lds: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | OUTPUT_ARCH( "riscv" ) 28 | 29 | ENTRY( _start ) 30 | 31 | MEMORY 32 | { 33 | ram (wxa!ri) : ORIGIN = 0x80200000, LENGTH = 16M 34 | } 35 | 36 | _STACK_SIZE = 2048; 37 | 38 | SECTIONS 39 | { 40 | .text : { 41 | *(.reset) 42 | *(.text .text.*) 43 | } >ram AT>ram 44 | 45 | .rodata : { 46 | *(.rodata .rodata.*) 47 | } >ram AT>ram 48 | 49 | .data : { 50 | . = ALIGN(4096); 51 | *(.data .data.*) 52 | } >ram AT>ram 53 | 54 | .sdata : { 55 | PROVIDE( __global_pointer$ = . + 0x800 ); 56 | *.o(.sdata .sdata.*) 57 | } >ram AT>ram 58 | 59 | PROVIDE(_bss_start = .); 60 | 61 | .sbss : { 62 | *.o(.sbss .sbss.*) 63 | } >ram AT>ram 64 | 65 | .bss :{ 66 | PROVIDE(_bss_start = .); 67 | *(.bss .bss.*) 68 | PROVIDE(_bss_end = .); 69 | } >ram AT>ram 70 | 71 | .stack : { 72 | . = ALIGN(16); 73 | PROVIDE(_stack_start = .); 74 | . = . + _STACK_SIZE; 75 | . = ALIGN(16); 76 | PROVIDE(_stack_end = .); 77 | } >ram AT>ram 78 | } 79 | -------------------------------------------------------------------------------- /nowhereOS/sbi.h: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | struct sbiret { 28 | long error; 29 | long value; 30 | }; 31 | 32 | extern struct sbiret sbi_set_timer(unsigned long stime_value); 33 | extern struct sbiret sbi_send_ipi(unsigned long hart_mask, unsigned long hart_mask_base); 34 | extern struct sbiret sbi_hart_start(unsigned long hartid, unsigned long start_addr, unsigned long opaque); 35 | extern struct sbiret sbi_hart_get_status(unsigned long hartid); 36 | extern struct sbiret sbi_debug_console_write_byte(unsigned char byte); 37 | 38 | #define SBI_SUCCESS 0 39 | #define SBI_ERR_FAILED -1 40 | #define SBI_ERR_NOT_SUPPORTED -2 41 | #define SBI_ERR_INVALID_PARAM -3 42 | #define SBI_ERR_DENIED -4 43 | #define SBI_ERR_INVALID_ADDRESS -5 44 | #define SBI_ERR_ALREADY_AVAILABLE -6 45 | #define SBI_ERR_ALREADY_STARTED -7 46 | #define SBI_ERR_ALREADY_STOPPED -8 47 | #define SBI_ERR_NO_SHMEM -9 48 | #define SBI_ERR_INVALID_STATE -10 49 | #define SBI_ERR_BAD_RANGE -11 50 | 51 | #define STARTED 0 52 | #define STOPPED 1 53 | #define START_PENDING 2 54 | #define STOP_PENDING 3 55 | #define SUSPENDED 4 56 | #define SUSPEND_PENDING 5 57 | #define RESUME_PENDING 6 58 | 59 | -------------------------------------------------------------------------------- /nowhereOS/sbi.s: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | .equ EID_TIME, ('T'<<24U|'I'<<16U|'M'<<8U|'E') 28 | .equ EID_sPI, ('s'<<16U|'P'<<8U|'I') 29 | .equ EID_HSM, ('H'<<16U|'S'<<8U|'M') 30 | .equ EID_DBCN, ('D'<<24U|'B'<<16U|'C'<<8U|'N') 31 | 32 | .equ FID_TIME_SETTIMER, 0 33 | .equ FID_sPI_SENDIPI, 0 34 | .equ FID_HART_START, 0 35 | .equ FID_HART_GETSTATUS, 2 36 | .equ FID_DBCN_WRITE, 0 37 | .equ FID_DBCN_READ, 1 38 | .equ FID_DBCN_WRITE_BYTE, 2 39 | 40 | .global sbi_set_timer 41 | .type sbi_set_timer,@function 42 | sbi_set_timer: 43 | li a7, EID_TIME 44 | li a6, FID_TIME_SETTIMER 45 | ecall 46 | ret 47 | .size sbi_set_timer,.-sbi_set_timer 48 | 49 | .global sbi_send_ipi 50 | .type sbi_send_ipi,@function 51 | sbi_send_ipi: 52 | li a7, EID_sPI 53 | li a6, FID_sPI_SENDIPI 54 | ecall 55 | ret 56 | .size sbi_send_ipi,.-sbi_send_ipi 57 | 58 | .global sbi_hart_start 59 | .type sbi_hart_start,@function 60 | sbi_hart_start: 61 | li a7, EID_HSM 62 | li a6, FID_HART_START 63 | ecall 64 | ret 65 | .size sbi_hart_start,.-sbi_hart_start 66 | 67 | .global sbi_hart_get_status 68 | .type sbi_hart_get_status,@function 69 | sbi_hart_get_status: 70 | li a7, EID_HSM 71 | li a6, FID_HART_GETSTATUS 72 | ecall 73 | ret 74 | .size sbi_hart_get_status,.-sbi_hart_get_status 75 | 76 | .global sbi_debug_console_write_byte 77 | .type sbi_debug_console_write_byte,@function 78 | sbi_debug_console_write_byte: 79 | li a7, EID_DBCN 80 | li a6, FID_DBCN_WRITE_BYTE 81 | ecall 82 | ret 83 | .size sbi_debug_console_write_byte,.-sbi_debug_console_write_byte 84 | 85 | -------------------------------------------------------------------------------- /nowhereOS/start.s: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | .section .reset,"ax",@progbits 28 | .option norelax 29 | .globl _start 30 | _start: 31 | la gp, __global_pointer$ 32 | la sp, _stack_end 33 | li tp, 0xDEADBEEFU 34 | j main 35 | 36 | 37 | .text 38 | .globl trap_vectors 39 | .globl undefined_handler 40 | .type trap_vectors,@function 41 | .balign 256 42 | trap_vectors: 43 | undefined_handler: 44 | j trap_vectors 45 | .size trap_vectors,.-trap_vectors 46 | 47 | .global SetTrapVectors 48 | .type SetTrapVectors,@function 49 | SetTrapVectors: 50 | csrw stvec, a0 51 | ret 52 | .size SetTrapVectors,.-SetTrapVectors 53 | -------------------------------------------------------------------------------- /qemustart.sh: -------------------------------------------------------------------------------- 1 | : 2 | QEMU=qemu-system-riscv64 3 | OPENSBI=/usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.elf 4 | 5 | #$QEMU -smp 2 -nographic -machine virt -m 128M -kernel sageVisor/sagevisor -bios $OPENSBI -device loader,file=guest1 -device loader,file=guest2 -S -gdb tcp::10000 $@ 6 | $QEMU -smp 2 -nographic -machine virt -m 128M -kernel sageVisor/sagevisor -bios $OPENSBI -device loader,file=guest1 -device loader,file=guest2 $@ 7 | 8 | -------------------------------------------------------------------------------- /sageVisor/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include "sbi.h" 29 | #include "vma.h" 30 | 31 | #define TRUE 1 32 | #define FALSE 0 33 | 34 | #define STACKSIZE 0x800 35 | #define NCORE 8 36 | 37 | #define max(a, b) ((a) > (b) ? (a) : (b)) 38 | #define min(a, b) ((a) < (b) ? (a) : (b)) 39 | 40 | /* 2 phyical cores */ 41 | typedef enum { 42 | CORE0 = 0, 43 | CORE1, 44 | NUMBER_OF_CORES, 45 | CORE_UNASSIGNED = NUMBER_OF_CORES, 46 | CORE_RESERVED, 47 | } CoreIdType; 48 | 49 | /* 4 virtual cpus */ 50 | typedef enum { 51 | VCPU0 = 0, 52 | VCPU1, 53 | VCPU2, 54 | VCPU3, 55 | NUMBER_OF_VCPUS, 56 | } VcpuIdType; 57 | 58 | typedef enum { 59 | VM0 = 0, 60 | VM1, 61 | NUMBER_OF_VMS, 62 | } VmIdType; 63 | 64 | typedef struct { 65 | unsigned long s0; 66 | unsigned long s1; 67 | unsigned long s2; 68 | unsigned long s3; 69 | unsigned long s4; 70 | unsigned long s5; 71 | unsigned long s6; 72 | unsigned long s7; 73 | unsigned long s8; 74 | unsigned long s9; 75 | unsigned long s10; 76 | unsigned long s11; 77 | unsigned long ra; 78 | 79 | unsigned long vsstatus; 80 | unsigned long vsepc; 81 | unsigned long vscause; 82 | unsigned long vstval; 83 | unsigned long vsie; 84 | unsigned long vstvec; 85 | unsigned long vsscratch; 86 | unsigned long vsatp; 87 | unsigned long hvip; 88 | unsigned long hstatus; 89 | } context; 90 | 91 | typedef volatile int Lock_t; 92 | extern unsigned char ram_guest1_start[]; 93 | extern unsigned char ram_guest1_size[]; 94 | extern unsigned char ram_guest2_start[]; 95 | extern unsigned char ram_guest2_size[]; 96 | 97 | struct VcpuControl { 98 | volatile enum { CORE_STARTED = STARTED, CORE_STOPPED } state; 99 | CoreIdType coreid; /* this phisical core assigned */ 100 | unsigned long next_time; 101 | unsigned int vmid; 102 | volatile int ipi_request; 103 | void (*entry)(unsigned long param); 104 | unsigned long param; 105 | unsigned long sp; 106 | unsigned long stack[STACKSIZE]; 107 | } VcpuControl[NUMBER_OF_VCPUS] = { 108 | {.coreid = CORE_RESERVED, .state = STOPPED, .vmid = VM0}, 109 | {.coreid = CORE_RESERVED, .state = STOPPED, .vmid = VM1}, 110 | {.coreid = CORE_UNASSIGNED, .state = STOPPED, .vmid = VM1}, 111 | {.coreid = CORE_UNASSIGNED, .state = STOPPED, .vmid = VM1}, 112 | }; 113 | 114 | #define REQ_VSSI 0x1U 115 | 116 | struct VmControl { 117 | VcpuIdType boot_vcpu; 118 | unsigned long vm_hgatp; 119 | unsigned long vm_start; 120 | unsigned long vm_size; 121 | unsigned long vm_io_start; 122 | unsigned long vm_io_size; 123 | } VmControl[NUMBER_OF_VCPUS] = { 124 | {.boot_vcpu = VCPU0, .vm_start = (unsigned long)ram_guest2_start, .vm_size = (unsigned long)ram_guest2_size, .vm_io_start = 0x10000000UL, .vm_io_size = 0x200000UL, }, 125 | {.boot_vcpu = VCPU1, .vm_start = (unsigned long)ram_guest1_start, .vm_size = (unsigned long)ram_guest1_size, .vm_io_start = 0x10000000UL, .vm_io_size = 0x200000UL, }, 126 | }; 127 | 128 | /* the entry address of guests is the same as of the hypervisor */ 129 | #define VM_ENTRY_ADDR _start 130 | 131 | __thread VcpuIdType CurrentVcpu; 132 | __thread CoreIdType ThisCore; 133 | 134 | static Lock_t lock_sched; 135 | 136 | extern void _Snooze(int tim); 137 | extern int switch_context(unsigned long *next_sp, unsigned long* sp); 138 | extern void load_context(unsigned long *sp); 139 | extern void VcpuSwitch(struct VcpuControl *current, struct VcpuControl *next); 140 | extern void VcpuStart(void (*entry)(unsigned long vcpu), unsigned long vcpu); 141 | extern void EnableInterrupts(void); 142 | extern unsigned long _get_time(void); 143 | extern void trap_vectors(void); 144 | extern void SetTrapVectors(unsigned long); 145 | extern int TestAndSet(Lock_t *lock, int newval); 146 | extern void MemBarrier(void); 147 | extern void Pause(void); 148 | extern void SetupDeleg(void); 149 | extern void _start(unsigned long vcpu); 150 | extern void _secondary_start(unsigned long vcpu); 151 | extern void clear_IPI(void); 152 | extern void raiseVSI(unsigned long type); 153 | extern void clearVSI(unsigned long type); 154 | extern unsigned long GetVSTvec(void); 155 | extern void SetVSmodeRegs(unsigned long sepc, unsigned long scause, unsigned long stval); 156 | extern void EnableCounters(unsigned int types); 157 | extern void SetHGATP(unsigned long pagetable); 158 | extern unsigned long CreateVmSpace(unsigned long vm, unsigned long paddr, unsigned long size, unsigned long vaddr); 159 | extern unsigned long CreateVmIoSpace(unsigned long vm, unsigned long paddr, unsigned long size); /* pass through I/O */ 160 | 161 | #define TVEC_VECTORED_MODE 0x1U 162 | 163 | #define INT_SMODE_SOFT 1 164 | #define INT_VSMODE_SOFT 2 165 | #define INT_SMODE_TIMER 5 166 | #define INT_VSMODE_TIMER 6 167 | #define IP_VSSI (0x1U<= 0; i--) { 202 | unsigned long x = (v & 0xFUL << i*4) >> i*4; 203 | if (print_started || x != 0U || i == 0) { 204 | print_started = TRUE; 205 | sbi_debug_console_write_byte((x < 10 ? '0' : 'a' - 10) + x); 206 | } 207 | } 208 | } else { 209 | sbi_debug_console_write_byte(*s++); 210 | } 211 | } 212 | } 213 | 214 | void _print_message(const char *s, ...) 215 | { 216 | unsigned long coreid = ThisCore; 217 | static Lock_t lock_uart; 218 | 219 | SpinLock(&lock_uart); 220 | 221 | __print_message("Physical core%x: ", &coreid); 222 | 223 | va_list ap; 224 | va_start (ap, s); 225 | __print_message(s, ap); 226 | va_end (ap); 227 | 228 | SpinUnlock(&lock_uart); 229 | } 230 | 231 | /* 232 | * Convert a logical cpu id in the current VM to the corresponding 233 | * virtual cpu id the hypervisor manages. 234 | */ 235 | static VcpuIdType Lcpu2Vcpu(unsigned int lcpu) 236 | { 237 | VmIdType vm = VcpuControl[CurrentVcpu].vmid; 238 | return (VcpuIdType)(lcpu + VmControl[vm].boot_vcpu); 239 | } 240 | 241 | static struct sbiret SbiRaiseIPI(unsigned long hartmask, unsigned long firsthart) 242 | { 243 | struct sbiret ret = {SBI_SUCCESS, 0}; 244 | unsigned int lcpu; 245 | for (lcpu = 0U; lcpu < 32U; lcpu++) { 246 | VcpuIdType vcpu = Lcpu2Vcpu(lcpu); 247 | 248 | if (hartmask & (1U << lcpu)) { 249 | VcpuControl[vcpu].ipi_request = TRUE; 250 | MemBarrier(); 251 | if (vcpu == CurrentVcpu) { 252 | raiseVSI(IP_VSSI); 253 | } else { 254 | SpinLock(&lock_sched); 255 | if (VcpuControl[vcpu].coreid >= CORE_UNASSIGNED) { 256 | context* p = (context *)VcpuControl[vcpu].sp; 257 | p->hvip |= IP_VSSI; 258 | } else { 259 | sbi_send_ipi(1U<next_time = _get_time() + 10000000U; 271 | } 272 | 273 | static void ActivateVSTimer(void) 274 | { 275 | deactivateTimer(&VcpuControl[CurrentVcpu]); 276 | raiseVSI(IP_VSTI); 277 | } 278 | 279 | void VcpuSwitch(struct VcpuControl *current, struct VcpuControl *next) 280 | { 281 | context* p = (context *)next->sp; 282 | 283 | if ((long)(next->next_time - _get_time()) <= 0) { 284 | p->hvip |= IP_VSTI; 285 | deactivateTimer(next); 286 | } 287 | if (VcpuControl[CurrentVcpu].ipi_request) { 288 | VcpuControl[CurrentVcpu].ipi_request = FALSE; 289 | MemBarrier(); 290 | p->hvip |= IP_VSSI; 291 | } 292 | /* switch guest's physical space */ 293 | SetHGATP(VmControl[next->vmid].vm_hgatp); 294 | switch_context(&next->sp, ¤t->sp); 295 | } 296 | 297 | static VcpuIdType ChooseNextVcpu(void) 298 | { 299 | /* roundrobin scheduling */ 300 | VcpuIdType vcpu = CurrentVcpu; 301 | 302 | VcpuControl[vcpu].coreid = CORE_UNASSIGNED; 303 | 304 | do { 305 | vcpu = (vcpu + 1) % NUMBER_OF_VCPUS; 306 | } while ((VcpuControl[vcpu].state != STARTED || VcpuControl[vcpu].coreid != CORE_UNASSIGNED) && vcpu != CurrentVcpu); 307 | VcpuControl[vcpu].coreid = ThisCore; 308 | 309 | return vcpu; 310 | } 311 | 312 | void _Schedule(void) 313 | { 314 | SpinLock(&lock_sched); 315 | VcpuIdType from = CurrentVcpu; 316 | CurrentVcpu = ChooseNextVcpu(); 317 | if (from != CurrentVcpu) { 318 | VcpuSwitch(&VcpuControl[from], &VcpuControl[CurrentVcpu]); 319 | } 320 | SpinUnlock(&lock_sched); 321 | } 322 | 323 | static void VcpuEntry(void) 324 | { 325 | SpinUnlock(&lock_sched); 326 | VcpuStart(VcpuControl[CurrentVcpu].entry, VcpuControl[CurrentVcpu].param); 327 | } 328 | 329 | static void InitVcpu(VcpuIdType vcpu) 330 | { 331 | context* p = (context *)&VcpuControl[vcpu].stack[STACKSIZE] - 1; 332 | p->ra = (unsigned long)VcpuEntry; 333 | VcpuControl[vcpu].sp = (unsigned long)p; 334 | p->vsstatus = 0U; 335 | p->vsie = 0u; 336 | p->vsatp = 0u; 337 | p->hvip = 0u; 338 | p->hstatus = HSTATUS_SPV|HSTATUS_SPVP; 339 | } 340 | 341 | static void InitVm(VmIdType vm) 342 | { 343 | VcpuIdType vcpu = VmControl[vm].boot_vcpu; 344 | VcpuControl[vcpu].entry = VM_ENTRY_ADDR; 345 | if (VmControl[vm].vm_io_size) { 346 | CreateVmIoSpace(vm, VmControl[vm].vm_io_start, VmControl[vm].vm_io_size); 347 | } 348 | VmControl[vm].vm_hgatp = CreateVmSpace(vm, VmControl[vm].vm_start, VmControl[vm].vm_size, (unsigned long)VM_ENTRY_ADDR); 349 | } 350 | 351 | static __thread unsigned long nexttime; 352 | 353 | #define INTERVAL 1000000U 354 | 355 | static int Timer(void) 356 | { 357 | VcpuIdType vcpu; 358 | 359 | /* check if the current vcpu needs an interrupt */ 360 | if ((long)(VcpuControl[CurrentVcpu].next_time - _get_time()) <= 0) { 361 | ActivateVSTimer(); 362 | } 363 | 364 | /* set the next hypervisor timer */ 365 | do { 366 | nexttime += INTERVAL; 367 | sbi_set_timer(nexttime); 368 | } while ((long)(_get_time() - nexttime) >= 0); 369 | 370 | return TRUE; /* vcpu reschedule */ 371 | } 372 | 373 | static int InterCoreInt(void) 374 | { 375 | clear_IPI(); 376 | 377 | if (VcpuControl[CurrentVcpu].ipi_request) { 378 | VcpuControl[CurrentVcpu].ipi_request = FALSE; 379 | MemBarrier(); 380 | raiseVSI(IP_VSSI); 381 | } 382 | return FALSE; 383 | } 384 | 385 | int InterruptHandler(unsigned long cause) 386 | { 387 | switch ((unsigned short)cause) { 388 | case INT_SMODE_SOFT: 389 | return InterCoreInt(); 390 | break; 391 | case INT_SMODE_TIMER: 392 | return Timer(); 393 | break; 394 | default: 395 | _print_message("Unknown Interrupt: cause(0x%x)\n", cause); 396 | break; 397 | } 398 | return FALSE; 399 | } 400 | 401 | static struct sbiret SbiSetTimer(unsigned long tim) 402 | { 403 | struct sbiret ret = {SBI_SUCCESS, 0}; 404 | /* activate the next timer on this vcpu */ 405 | VcpuControl[CurrentVcpu].next_time = tim; 406 | clearVSI(IP_VSTI); 407 | return ret; 408 | } 409 | 410 | static struct sbiret SbiVcpuStart(unsigned long lcpu, unsigned long start_addr, unsigned long opaque) 411 | { 412 | struct sbiret ret = {SBI_SUCCESS, 0}; 413 | VcpuIdType vcpu = Lcpu2Vcpu(lcpu); 414 | 415 | if (VcpuControl[vcpu].state == STOPPED) { 416 | VcpuControl[vcpu].entry = (void (*)(unsigned long))start_addr; 417 | VcpuControl[vcpu].param = opaque; 418 | MemBarrier(); 419 | VcpuControl[vcpu].state = STARTED; 420 | } else { 421 | ret.error = SBI_ERR_ALREADY_STARTED; 422 | } 423 | return ret; 424 | } 425 | 426 | static struct sbiret SbiVcpuStatus(unsigned long lcpu) 427 | { 428 | VcpuIdType vcpu = Lcpu2Vcpu(lcpu); 429 | struct sbiret ret = {SBI_SUCCESS, VcpuControl[vcpu].state}; 430 | return ret; 431 | } 432 | 433 | static struct sbiret SbiNotSupported(void) 434 | { 435 | struct sbiret ret = {SBI_ERR_NOT_SUPPORTED, 0}; 436 | return ret; 437 | } 438 | 439 | #define GenerateEID(k1, k2, k3, k4) (k1<<24U | k2<<16U | k3<<8U | k4<<0U) 440 | /* SBI version 0.2 */ 441 | #define EID_TIME GenerateEID('T', 'I', 'M', 'E') 442 | #define EID_sPI GenerateEID(0U, 's', 'P', 'I') 443 | #define EID_HSM GenerateEID(0U, 'H', 'S', 'M') 444 | /* SBI version 2.0 */ 445 | #define EID_DBCN GenerateEID('D', 'B', 'C', 'N') 446 | 447 | #define FID_TIME_SETTIMER 0 448 | #define FID_IPI_SENDIPI 0 449 | #define FID_HART_START 0 450 | #define FID_HART_GETSTATUS 2 451 | #define FID_DBCN_WRITE 0 452 | #define FID_DBCN_READ 1 453 | #define FID_DBCN_WRITE_BYTE 2 454 | 455 | struct sbiret HypHandler(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, unsigned long fid, unsigned long eid) 456 | { 457 | switch (eid) { 458 | case EID_TIME: 459 | switch (fid) { 460 | case FID_TIME_SETTIMER: 461 | return SbiSetTimer(a0); 462 | default: 463 | break; 464 | } 465 | break; 466 | case EID_sPI: 467 | switch (fid) { 468 | case FID_IPI_SENDIPI: 469 | return SbiRaiseIPI(a0, a1); 470 | default: 471 | break; 472 | } 473 | break; 474 | case EID_HSM: 475 | switch (fid) { 476 | case FID_HART_START: 477 | return SbiVcpuStart(a0, a1, a2); 478 | case FID_HART_GETSTATUS: 479 | return SbiVcpuStatus(a0); 480 | default: 481 | break; 482 | } 483 | break; 484 | case EID_DBCN: 485 | switch (fid) { 486 | case FID_DBCN_WRITE_BYTE: 487 | return sbi_debug_console_write_byte(a0); 488 | default: 489 | break; 490 | } 491 | break; 492 | default: 493 | break; 494 | } 495 | 496 | return SbiNotSupported(); 497 | } 498 | 499 | #define EXCCTX_EPC 32 500 | #define EXCCTX_CAUSE 33 501 | #define EXCCTX_STATUS 34 502 | #define EXCCTX_TVAL 35 503 | 504 | #define EXC_ILLEGAL_INST 0x2U 505 | #define EXC_VIRTUAL_INST 0x16U 506 | #define OP_SYSTEM 0x73U 507 | #define CSR_TIME 0xC01U 508 | #define FUNC_CSSRS 0x2U 509 | 510 | #define EXCCTX_EPC 32 511 | #define EXCCTX_CAUSE 33 512 | #define EXCCTX_STATUS 34 513 | #define EXCCTX_TVAL 35 514 | #define EXCCTX_SP 2 515 | 516 | static _Bool emulate_inst(unsigned long* ctx, unsigned int inst) 517 | { 518 | unsigned int opcode = inst & 0x7FU; 519 | 520 | switch (opcode) { 521 | case OP_SYSTEM: 522 | { 523 | unsigned int funct3 = inst >> 12U & 0x7U; 524 | unsigned int csr = inst >> 20U; 525 | 526 | if (funct3 == FUNC_CSSRS && csr == CSR_TIME) { 527 | /* This emmulation is requred on OpenSBI */ 528 | unsigned int rd = inst >> 7 & 0x1F; 529 | /* emulate rdtime instruction */ 530 | ctx[rd] = _get_time(); 531 | ctx[EXCCTX_EPC] += 4U; 532 | return TRUE; 533 | } 534 | break; 535 | } 536 | default: 537 | break; 538 | } 539 | return FALSE; 540 | } 541 | 542 | static _Bool redirect_trap(unsigned long* ctx, unsigned long sepc, unsigned long scause, unsigned long sstatus, unsigned long stval) 543 | { 544 | SetVSmodeRegs(sepc, scause, stval); 545 | 546 | ctx[EXCCTX_STATUS] |= STATUS_SPP; /* return to VS-mode */ 547 | ctx[EXCCTX_EPC] = GetVSTvec() & ~TVEC_VECTORED_MODE; 548 | ctx[EXCCTX_STATUS] &= ~(STATUS_SIE|STATUS_SPIE); /* disable VS-mode interrupts */ 549 | if (sstatus & STATUS_SIE) { 550 | ctx[EXCCTX_STATUS] |= STATUS_SPIE; 551 | } 552 | 553 | return TRUE; 554 | } 555 | 556 | void ExcHandler(unsigned long* ctx, unsigned long sepc, unsigned long scause, unsigned long sstatus, unsigned long stval, unsigned long hstatus) 557 | { 558 | if (hstatus & HSTATUS_SPV) { /* trapped in a virtualized mode */ 559 | if (scause == EXC_VIRTUAL_INST) { 560 | if (emulate_inst(ctx, stval)) { 561 | return; 562 | } 563 | scause = EXC_ILLEGAL_INST; 564 | } 565 | 566 | if (redirect_trap(ctx, sepc, scause, sstatus, stval)) { 567 | return; 568 | } 569 | } 570 | 571 | _print_message("Exception: sepc(0x%x) scause(0x%x) sstatus(0x%x) stval(0x%x), hstatus(0x%x) sp(0x%x) ra(0x%x) s0(0x%x) s1(0x%x)\n", sepc, scause, sstatus, stval, hstatus, ctx[2], ctx[1], ctx[8], ctx[9]); 572 | _print_message(" a0(0x%x) a1(0x%x) a2(0x%x) a3(0x%x) a4(0x%x) a5(0x%x)\n", ctx[10], ctx[11], ctx[12], ctx[13], ctx[14], ctx[15]); 573 | while (1); 574 | } 575 | 576 | static void StartTimer(void) 577 | { 578 | nexttime = _get_time() + INTERVAL; 579 | sbi_set_timer(nexttime); 580 | } 581 | 582 | static void mem_clear(unsigned char *start, unsigned char *end) 583 | { 584 | unsigned char *p; 585 | for (p = start; p < end; p++) { 586 | *p = 0LL; 587 | } 588 | } 589 | 590 | static void mem_copy(unsigned char *to, unsigned char *from, unsigned int size) 591 | { 592 | unsigned int sz; 593 | for (sz = 0; sz < size; sz++) { 594 | to[sz] = from[sz]; 595 | } 596 | } 597 | 598 | static void clearbss(void) 599 | { 600 | extern unsigned char _bss_start[]; 601 | extern unsigned char _bss_end[]; 602 | 603 | mem_clear(_bss_start, _bss_end); 604 | } 605 | 606 | static void setupTLS(void) 607 | { 608 | extern unsigned char _tls_start[]; 609 | extern unsigned char _tdata_start[]; 610 | extern unsigned char _tdata_end[]; 611 | extern unsigned char _tbss_start[]; 612 | extern unsigned char _tbss_end[]; 613 | 614 | const unsigned int tdata_size = _tdata_end - _tdata_start; 615 | const unsigned int tbss_size = _tbss_end - _tbss_start; 616 | register unsigned char* threadp asm("tp"); 617 | 618 | mem_copy(threadp, _tdata_start, tdata_size); 619 | mem_clear(&threadp[tbss_size], &threadp[tdata_size + tbss_size]); 620 | } 621 | 622 | static volatile CoreIdType BootCore = CORE_UNASSIGNED; 623 | 624 | static void sync_cores(void) 625 | { 626 | volatile static _Bool notyet = TRUE; 627 | 628 | if (ThisCore == BootCore) { 629 | MemBarrier(); 630 | notyet = FALSE; 631 | } else { 632 | while (notyet); 633 | } 634 | } 635 | 636 | static void start_cores(void) 637 | { 638 | int coreid; 639 | 640 | for (coreid = CORE0; coreid < min(NCORE, NUMBER_OF_VCPUS); coreid++) { 641 | if (coreid != BootCore) { 642 | /* start phisical cores */ 643 | struct sbiret ret = sbi_hart_start(coreid, (unsigned long)_secondary_start, coreid); 644 | if (ret.error == SBI_ERR_INVALID_PARAM) { 645 | /* The specified core doesn't exit */ 646 | } else if (ret.error) { 647 | _print_message("sbi_hart_start(core%x) failed. error(0x%x)\n", coreid, ret.error); 648 | } 649 | } 650 | } 651 | } 652 | 653 | static void restart_bootcore(void) 654 | { 655 | struct sbiret ret; 656 | CoreIdType coreid; 657 | 658 | for (coreid = CORE0; coreid < NCORE; coreid++) { 659 | struct sbiret ret = sbi_hart_get_status(coreid); 660 | if (ret.error == SBI_SUCCESS && ret.value == STARTED) { 661 | BootCore = coreid; 662 | _secondary_start(BootCore); 663 | } 664 | } 665 | } 666 | 667 | void main(CoreIdType coreid) 668 | { 669 | VcpuIdType vcpu; 670 | 671 | SetTrapVectors((unsigned long)trap_vectors + TVEC_VECTORED_MODE); 672 | 673 | if (BootCore == CORE_UNASSIGNED) { 674 | restart_bootcore(); 675 | } 676 | 677 | setupTLS(); 678 | ThisCore = coreid; 679 | SetupDeleg(); 680 | 681 | if (ThisCore == BootCore) { 682 | VmIdType vm; 683 | 684 | clearbss(); 685 | 686 | for (vcpu = 0; vcpu < NUMBER_OF_VCPUS; vcpu++) { 687 | InitVcpu(vcpu); 688 | } 689 | for (vm = 0; vm < NUMBER_OF_VMS; vm++) { 690 | InitVm(vm); 691 | } 692 | 693 | start_cores(); 694 | } 695 | sync_cores(); 696 | 697 | StartTimer(); 698 | EnableInterrupts(); 699 | 700 | _print_message("Core%x started.\n", ThisCore); 701 | 702 | /* currently only supports two VMs */ 703 | if (ThisCore == BootCore) { 704 | CurrentVcpu = VmControl[VM0].boot_vcpu; 705 | } else { 706 | CurrentVcpu = VmControl[VM1].boot_vcpu; 707 | } 708 | 709 | SpinLock(&lock_sched); 710 | VcpuControl[CurrentVcpu].state = STARTED; 711 | VcpuControl[CurrentVcpu].coreid = ThisCore; 712 | SetHGATP(VmControl[VcpuControl[CurrentVcpu].vmid].vm_hgatp); 713 | load_context(&VcpuControl[CurrentVcpu].sp); 714 | } 715 | 716 | -------------------------------------------------------------------------------- /sageVisor/makefile: -------------------------------------------------------------------------------- 1 | 2 | .SUFFIXES: .c .s .o 3 | 4 | .c.o: 5 | $(CC) $(CFLAGS) -c $< 6 | 7 | .s.o: 8 | $(CC) $(CFLAGS) -c $< 9 | 10 | all: sagevisor 11 | 12 | sagevisor: main.o primitives.o start.o sbi.o vmspaces.o riscv-virt.lds 13 | $(LD) *.o -o $@ -T riscv-virt.lds ${LDFLAGS} 14 | 15 | clean: 16 | -rm -f *.o sagevisor 17 | -------------------------------------------------------------------------------- /sageVisor/primitives.s: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | .equ INT_SMODE_SOFT, 1 28 | .equ INT_VSMODE_SOFT, 2 29 | .equ INT_SMODE_TIMER, 5 30 | .equ INT_VSMODE_TIMER, 6 31 | 32 | .equ IP_SSI, (1U< 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | OUTPUT_ARCH( "riscv" ) 28 | 29 | ENTRY( _start ) 30 | 31 | MEMORY 32 | { 33 | ram (wxa!ri) : ORIGIN = 0x80200000, LENGTH = 4M 34 | 35 | /* guests' pysical location */ 36 | ram_guest1 (wxa!ri) : ORIGIN = 0x80600000, LENGTH = 64M 37 | ram_guest2 (wxa!ri) : ORIGIN = 0x84600000, LENGTH = 32M 38 | } 39 | 40 | _MAXCORE = 8; 41 | _CLV_SIZE = 1024; 42 | _STACK_SIZE = 2048; 43 | _ESTACK_SIZE = 1024; 44 | _TLS_SIZE = _CLV_SIZE + _STACK_SIZE; 45 | 46 | ram_guest1_start = ORIGIN(ram_guest1); 47 | ram_guest1_size = LENGTH(ram_guest1); 48 | ram_guest2_start = ORIGIN(ram_guest2); 49 | ram_guest2_size = LENGTH(ram_guest2); 50 | 51 | SECTIONS 52 | { 53 | .text : { 54 | *(.reset) 55 | *.o(.text .text.*) 56 | } >ram AT>ram 57 | 58 | .rodata : { 59 | *.o(.rodata .rodata.*) 60 | } >ram AT>ram 61 | 62 | .data : { 63 | *.o(.data .data.*) 64 | } >ram AT>ram 65 | 66 | .sdata : { 67 | PROVIDE( __global_pointer$ = . + 0x800 ); 68 | *.o(.sdata .sdata.*) 69 | } >ram AT>ram 70 | 71 | PROVIDE(_bss_start = .); 72 | 73 | .sbss : { 74 | *.o(.sbss .sbss.*) 75 | } >ram AT>ram 76 | 77 | .bss : { 78 | *.o(.bss .bss.*) 79 | } >ram AT>ram 80 | 81 | PROVIDE(_bss_end = .); 82 | 83 | /* tls data backup section */ 84 | .system_tdata : { 85 | PROVIDE(_tdata_start = .); 86 | *.o(.tdata .tdata.*) 87 | PROVIDE(_tdata_end = .); 88 | } >ram AT>ram 89 | 90 | .system_tbss : { 91 | PROVIDE(_tbss_start = .); 92 | *.o(.tbss .tbss.*) 93 | PROVIDE(_tbss_end = .); 94 | } >ram AT>ram 95 | 96 | .tls :{ 97 | . = ALIGN(16); 98 | PROVIDE(_tls_start = .); 99 | . = . + _TLS_SIZE * _MAXCORE; 100 | . = ALIGN(16); 101 | PROVIDE(_tls_end = .); 102 | } >ram AT>ram 103 | } 104 | -------------------------------------------------------------------------------- /sageVisor/sbi.h: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | struct sbiret { 28 | long error; 29 | long value; 30 | }; 31 | 32 | extern struct sbiret sbi_set_timer(unsigned long stime_value); 33 | extern struct sbiret sbi_send_ipi(unsigned long hart_mask, unsigned long hart_mask_base); 34 | extern struct sbiret sbi_hart_start(unsigned long hartid, unsigned long start_addr, unsigned long opaque); 35 | extern struct sbiret sbi_hart_get_status(unsigned long hartid); 36 | extern struct sbiret sbi_debug_console_write_byte(unsigned char byte); 37 | 38 | #define SBI_SUCCESS 0 39 | #define SBI_ERR_FAILED -1 40 | #define SBI_ERR_NOT_SUPPORTED -2 41 | #define SBI_ERR_INVALID_PARAM -3 42 | #define SBI_ERR_DENIED -4 43 | #define SBI_ERR_INVALID_ADDRESS -5 44 | #define SBI_ERR_ALREADY_AVAILABLE -6 45 | #define SBI_ERR_ALREADY_STARTED -7 46 | #define SBI_ERR_ALREADY_STOPPED -8 47 | #define SBI_ERR_NO_SHMEM -9 48 | #define SBI_ERR_INVALID_STATE -10 49 | #define SBI_ERR_BAD_RANGE -11 50 | 51 | #define STARTED 0 52 | #define STOPPED 1 53 | #define START_PENDING 2 54 | #define STOP_PENDING 3 55 | #define SUSPENDED 4 56 | #define SUSPEND_PENDING 5 57 | #define RESUME_PENDING 6 58 | 59 | -------------------------------------------------------------------------------- /sageVisor/sbi.s: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | .equ EID_TIME, ('T'<<24U|'I'<<16U|'M'<<8U|'E') 28 | .equ EID_sPI, ('s'<<16U|'P'<<8U|'I') 29 | .equ EID_HSM, ('H'<<16U|'S'<<8U|'M') 30 | .equ EID_DBCN, ('D'<<24U|'B'<<16U|'C'<<8U|'N') 31 | 32 | .equ FID_TIME_SETTIMER, 0 33 | .equ FID_sPI_SENDIPI, 0 34 | .equ FID_HART_START, 0 35 | .equ FID_HART_GETSTATUS, 2 36 | .equ FID_DBCN_WRITE, 0 37 | .equ FID_DBCN_READ, 1 38 | .equ FID_DBCN_WRITE_BYTE, 2 39 | 40 | .global sbi_set_timer 41 | .type sbi_set_timer,@function 42 | sbi_set_timer: 43 | li a7, EID_TIME 44 | li a6, FID_TIME_SETTIMER 45 | ecall 46 | ret 47 | .size sbi_set_timer,.-sbi_set_timer 48 | 49 | .global sbi_send_ipi 50 | .type sbi_send_ipi,@function 51 | sbi_send_ipi: 52 | li a7, EID_sPI 53 | li a6, FID_sPI_SENDIPI 54 | ecall 55 | ret 56 | .size sbi_send_ipi,.-sbi_send_ipi 57 | 58 | .global sbi_hart_start 59 | .type sbi_hart_start,@function 60 | sbi_hart_start: 61 | li a7, EID_HSM 62 | li a6, FID_HART_START 63 | ecall 64 | ret 65 | .size sbi_hart_start,.-sbi_hart_start 66 | 67 | .global sbi_hart_get_status 68 | .type sbi_hart_get_status,@function 69 | sbi_hart_get_status: 70 | li a7, EID_HSM 71 | li a6, FID_HART_GETSTATUS 72 | ecall 73 | ret 74 | .size sbi_hart_get_status,.-sbi_hart_get_status 75 | 76 | .global sbi_debug_console_write_byte 77 | .type sbi_debug_console_write_byte,@function 78 | sbi_debug_console_write_byte: 79 | li a7, EID_DBCN 80 | li a6, FID_DBCN_WRITE_BYTE 81 | ecall 82 | ret 83 | .size sbi_debug_console_write_byte,.-sbi_debug_console_write_byte 84 | 85 | -------------------------------------------------------------------------------- /sageVisor/start.s: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | .section .reset,"ax",@progbits 28 | .option norelax 29 | .globl _start 30 | .globl _secondary_start 31 | _start: 32 | mv a0, zero 33 | 34 | _secondary_start: 35 | /* a0 = mhartid */ 36 | la gp, __global_pointer$ 37 | 38 | /* tp = _tls_start + mhartid*_TLS_SIZE */ 39 | la tp, _tls_start 40 | la t1, _TLS_SIZE 41 | mul t2, t1, a0 42 | add tp, tp, t2 43 | 44 | /* sscratch = tp + _CLV_SIZE */ 45 | la t1, _CLV_SIZE 46 | add t3, tp, t1 47 | csrw sscratch, t3 48 | 49 | /* sp = sscratch + _STACK_SIZE */ 50 | la t1, _STACK_SIZE 51 | add sp, t3, t1 52 | 53 | j main 54 | 55 | -------------------------------------------------------------------------------- /sageVisor/vma.h: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | typedef unsigned long pte_t; 28 | 29 | #define PTE_V (1UL<<0U) 30 | #define PTE_R (1UL<<1U) 31 | #define PTE_W (1UL<<2U) 32 | #define PTE_X (1UL<<3U) 33 | #define PTE_U (1UL<<4U) 34 | #define PTE_G (1UL<<5U) 35 | #define PTE_A (1UL<<6U) 36 | #define PTE_D (1UL<<7U) 37 | #define PTE_PPN_SHIFT 10U 38 | 39 | #define PAGESIZE_SHIFT 12U 40 | #define PAGESIZE (1UL<> PAGESIZE_SHIFT) 48 | #define SUPER_PAGE_NUMBER(addr) (PAGE_NUMBER(addr)/NUM_PTE_IN_PAGE) 49 | #define HUGE_PAGE_NUMBER(addr) (SUPER_PAGE_NUMBER(addr)/NUM_PTE_IN_PAGE) 50 | 51 | #define ATP_MODE_BARE (0UL<<60U) 52 | #define ATP_MODE_SV39 (8UL<<60U) 53 | #define ATP_MODE_SV48 (9UL<<60U) 54 | #define ATP_MODE_SV57 (10UL<<60U) 55 | #define ATP_MODE_SV64 (11UL<<60U) 56 | #define ATP_ASID(asid) ((asid)<<44U) 57 | #define ATP_VMID(vmid) ATP_ASID(vmid) 58 | 59 | extern void SetupPageTables(void); 60 | extern void EnableMMU(void); 61 | -------------------------------------------------------------------------------- /sageVisor/vmspaces.c: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | #include "vma.h" 28 | 29 | /* currently supports two vms */ 30 | #define N_VM 2 31 | 32 | static pte_t pgtable_root_vm[N_VM][NUM_PTE_IN_PAGEx4] __attribute__ ((aligned (PAGESIZEx4))); 33 | static pte_t pgtable_lvl2_vm[N_VM][NUM_PTE_IN_PAGE] __attribute__ ((aligned (PAGESIZE))); 34 | static pte_t pgtable_lvl2_io[N_VM][NUM_PTE_IN_PAGE] __attribute__ ((aligned (PAGESIZE))); 35 | 36 | static void init_ptes(pte_t* pte, unsigned int begin, unsigned int end, unsigned long pfn, unsigned long mode) 37 | { 38 | int ent; 39 | 40 | for (ent = begin; ent < end; ent++, pfn += NUM_PTE_IN_PAGE) { 41 | pte[ent] = (pfn< 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #define TRUE 1 30 | #define FALSE 0 31 | 32 | typedef enum { 33 | TASK1 = 0, 34 | TASK2, 35 | TASK3, 36 | TASK4, 37 | TASK5, 38 | TASKIDLE, 39 | TASKIDLE_CORE0 = TASKIDLE, 40 | TASKIDLE_CORE1, 41 | TASKIDLE_CORE2, 42 | NUMBER_OF_TASKS, 43 | } TaskIdType; 44 | 45 | typedef enum { 46 | SEM1 = 0, 47 | SEM2, 48 | SEM3, 49 | SEM4, 50 | SEM5, 51 | NUMBER_OF_SEMS, 52 | } SemIdType; 53 | 54 | extern void Schedule(void); 55 | extern void AcquireSemaphore(SemIdType sem); 56 | extern int TryToAcquireSemaphore(SemIdType sem); 57 | extern void ReleaseSemaphore(SemIdType sem); 58 | extern void Snooze(int tim); 59 | extern void print_message(const char* s, ...); 60 | extern unsigned long get_time(void); 61 | 62 | #define USTACKSIZE 0x1000 63 | extern unsigned long task_ustack[NUMBER_OF_TASKS][USTACKSIZE]; 64 | 65 | extern void Task1(void); 66 | extern void Task2(void); 67 | extern void Task3(void); 68 | extern void Task4(void); 69 | extern void Task5(void); 70 | extern void Idle(void); 71 | -------------------------------------------------------------------------------- /sophiaOS/application.c: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | #include "api.h" 28 | 29 | unsigned long task_ustack[NUMBER_OF_TASKS][USTACKSIZE]; 30 | 31 | #define WAITTIME 20000000 32 | 33 | unsigned int myrandom(void) 34 | { 35 | static unsigned long long x = 11; 36 | x = (48271 * x) % 2147483647; 37 | return (unsigned int)x; 38 | } 39 | 40 | void spend_time(void) 41 | { 42 | unsigned long t = get_time(); 43 | unsigned long w = WAITTIME + myrandom()%10000000U; 44 | while ( get_time() - t < w ); 45 | } 46 | 47 | int GetForks(SemIdType fork_left, SemIdType fork_right) 48 | { 49 | AcquireSemaphore(fork_left); 50 | if (TryToAcquireSemaphore(fork_right)) { 51 | return TRUE; 52 | } 53 | ReleaseSemaphore(fork_left); 54 | return FALSE; 55 | } 56 | 57 | void ReleaseForks(SemIdType fork_left, SemIdType fork_right) 58 | { 59 | ReleaseSemaphore(fork_left); 60 | ReleaseSemaphore(fork_right); 61 | } 62 | 63 | void PhilosopherMeditate(const TaskIdType task) 64 | { 65 | print_message("Task%x Meditating\n", task + 1); 66 | Snooze(myrandom() % 2 + 1); 67 | } 68 | 69 | void PhilosopherEat(const TaskIdType task) 70 | { 71 | print_message("Task%x Eating\n", task + 1); 72 | spend_time(); 73 | } 74 | 75 | void TaskJob(const TaskIdType task, const SemIdType fork_left, const SemIdType fork_right) 76 | { 77 | while (1) { 78 | while ( !GetForks(fork_left, fork_right) ) { 79 | PhilosopherMeditate(task); 80 | } 81 | PhilosopherEat(task); 82 | ReleaseForks(fork_left, fork_right); 83 | } 84 | } 85 | 86 | void Task1(void) 87 | { 88 | TaskJob(TASK1, SEM1, SEM2); 89 | } 90 | 91 | void Task2(void) 92 | { 93 | TaskJob(TASK2, SEM2, SEM3); 94 | } 95 | 96 | void Task3(void) 97 | { 98 | TaskJob(TASK3, SEM3, SEM4); 99 | } 100 | 101 | void Task4(void) 102 | { 103 | TaskJob(TASK4, SEM4, SEM5); 104 | } 105 | 106 | void Task5(void) 107 | { 108 | TaskJob(TASK5, SEM5, SEM1); 109 | } 110 | 111 | void Idle(void) 112 | { 113 | Schedule(); 114 | while (1) { 115 | /* do nothing */ 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /sophiaOS/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | #include "api.h" 28 | #include "sbi.h" 29 | #include "vma.h" 30 | 31 | #define NO_SEM NUMBER_OF_SEMS 32 | #define KSTACKSIZE 0x800 33 | 34 | typedef enum { 35 | CORE0 = 0, 36 | CORE1, 37 | CORE2, 38 | NUMBER_OF_CORES, 39 | CORE_UNASSIGNED = NUMBER_OF_CORES, 40 | } CoreIdType; 41 | 42 | typedef struct { 43 | unsigned long s0; 44 | unsigned long s1; 45 | unsigned long s2; 46 | unsigned long s3; 47 | unsigned long s4; 48 | unsigned long s5; 49 | unsigned long s6; 50 | unsigned long s7; 51 | unsigned long s8; 52 | unsigned long s9; 53 | unsigned long s10; 54 | unsigned long s11; 55 | unsigned long ra; 56 | } context; 57 | 58 | typedef volatile int Lock_t; 59 | 60 | struct TaskControl { 61 | enum { READY, BLOCKED } state; 62 | CoreIdType coreid; 63 | void (*entry)(void); 64 | long time_slice; 65 | long remaining_time; 66 | int expire; 67 | SemIdType target_sem; 68 | unsigned long sp; 69 | unsigned long task_kstack[KSTACKSIZE]; 70 | } TaskControl[NUMBER_OF_TASKS] = { 71 | {.coreid = CORE_UNASSIGNED, .entry = Task1, .state = READY, .time_slice = 2}, 72 | {.coreid = CORE_UNASSIGNED, .entry = Task2, .state = READY, .time_slice = 4}, 73 | {.coreid = CORE_UNASSIGNED, .entry = Task3, .state = READY, .time_slice = 1}, 74 | {.coreid = CORE_UNASSIGNED, .entry = Task4, .state = READY, .time_slice = 3}, 75 | {.coreid = CORE_UNASSIGNED, .entry = Task5, .state = READY, .time_slice = 1}, 76 | {.coreid = CORE_UNASSIGNED, .entry = Idle, .state = READY, .time_slice = 1}, 77 | {.coreid = CORE_UNASSIGNED, .entry = Idle, .state = READY, .time_slice = 1}, 78 | {.coreid = CORE_UNASSIGNED, .entry = Idle, .state = READY, .time_slice = 1}, 79 | }; 80 | 81 | #define SEM_AVAILABLE TASKIDLE 82 | 83 | struct SemaphoreControl { 84 | TaskIdType owner_task; 85 | Lock_t lock; 86 | } SemaphoreControl[NUMBER_OF_SEMS] = { 87 | {.owner_task = SEM_AVAILABLE}, 88 | {.owner_task = SEM_AVAILABLE}, 89 | {.owner_task = SEM_AVAILABLE}, 90 | {.owner_task = SEM_AVAILABLE}, 91 | {.owner_task = SEM_AVAILABLE}, 92 | }; 93 | 94 | __thread TaskIdType CurrentTask; 95 | __thread CoreIdType ThisCore; 96 | 97 | static Lock_t lock_sched; 98 | 99 | extern void _AcquireSemaphore(SemIdType sem); 100 | extern int _TryToAcquireSemaphore(SemIdType sem); 101 | extern void _ReleaseSemaphore(SemIdType sem); 102 | extern void _Snooze(int tim); 103 | extern void _Schedule(void); 104 | extern int switch_context(unsigned long *next_sp, unsigned long* sp); 105 | extern void load_context(unsigned long *sp); 106 | extern void TaskSwitch(struct TaskControl *current, struct TaskControl *next); 107 | extern void TaskStart(void (*entry)(void), unsigned long *usp); 108 | extern void EnableInterrupts(void); 109 | extern unsigned long _get_time(void); 110 | extern void trap_vectors(void); 111 | extern void SetTrapVectors(unsigned long); 112 | extern int TestAndSet(Lock_t *lock, int newval); 113 | extern void MemBarrier(void); 114 | extern void Pause(void); 115 | extern void _secondary_start(unsigned long hartid); 116 | extern void clear_IPI(void); 117 | 118 | #define TVEC_VECTORED_MODE 0x1U 119 | 120 | #define INT_SMODE_SOFT 1 121 | #define INT_SMODE_TIMER 5 122 | 123 | void SpinLock(Lock_t *lock) 124 | { 125 | while (TestAndSet(lock, ThisCore + 1)) { 126 | Pause(); 127 | } 128 | } 129 | 130 | void SpinUnlock(Lock_t *lock) 131 | { 132 | MemBarrier(); 133 | *lock = 0; 134 | } 135 | 136 | void broardcast_IPI(void) 137 | { 138 | unsigned long core_mask = 0U; 139 | CoreIdType core = ThisCore + 1; 140 | do { 141 | core_mask |= (1U << core); 142 | core = (core + 1) % NUMBER_OF_CORES; 143 | } while (core != ThisCore); 144 | 145 | sbi_send_ipi(core_mask, 0U); 146 | } 147 | 148 | static void put_char(char c) 149 | { 150 | volatile unsigned char * const uart = (unsigned char *)0x10000000U; 151 | *uart = c; 152 | } 153 | 154 | static void __print_message(const char *s, va_list ap) 155 | { 156 | while (*s) { 157 | if (*s == '%' && *(s+1) == 'x') { 158 | unsigned long v = va_arg(ap, unsigned long); 159 | _Bool print_started = FALSE; 160 | int i; 161 | 162 | s += 2; 163 | for (i = 15; i >= 0; i--) { 164 | unsigned long x = (v & 0xFUL << i*4) >> i*4; 165 | if (print_started || x != 0U || i == 0) { 166 | print_started = TRUE; 167 | put_char((x < 10 ? '0' : 'a' - 10) + x); 168 | } 169 | } 170 | } else { 171 | put_char(*s++); 172 | } 173 | } 174 | } 175 | 176 | void _print_message(const char *s, ...) 177 | { 178 | unsigned long coreid = ThisCore; 179 | static Lock_t lock_uart; 180 | 181 | SpinLock(&lock_uart); 182 | 183 | __print_message("core%x: ", &coreid); 184 | 185 | va_list ap; 186 | va_start (ap, s); 187 | __print_message(s, ap); 188 | va_end (ap); 189 | 190 | SpinUnlock(&lock_uart); 191 | } 192 | 193 | void TaskSwitch(struct TaskControl *current, struct TaskControl *next) 194 | { 195 | switch_context(&next->sp, ¤t->sp); 196 | } 197 | 198 | static TaskIdType ChooseNextTask(void) 199 | { 200 | /* roundrobin scheduling */ 201 | TaskIdType task = CurrentTask; 202 | 203 | TaskControl[task].coreid = CORE_UNASSIGNED; 204 | 205 | do { 206 | task = (task + 1) % NUMBER_OF_TASKS; 207 | } while ((TaskControl[task].state != READY || TaskControl[task].coreid != CORE_UNASSIGNED || task >= TASKIDLE) && task != CurrentTask); 208 | 209 | if (TaskControl[task].state != READY) { 210 | task = TASKIDLE + ThisCore; 211 | } 212 | TaskControl[task].coreid = ThisCore; 213 | 214 | return task; 215 | } 216 | 217 | void _Schedule(void) 218 | { 219 | SpinLock(&lock_sched); 220 | TaskIdType from = CurrentTask; 221 | CurrentTask = ChooseNextTask(); 222 | if (from != CurrentTask) { 223 | TaskSwitch(&TaskControl[from], &TaskControl[CurrentTask]); 224 | } 225 | SpinUnlock(&lock_sched); 226 | } 227 | 228 | static void TaskSetReady(TaskIdType task) 229 | { 230 | MemBarrier(); 231 | TaskControl[task].state = READY; 232 | broardcast_IPI(); 233 | } 234 | 235 | void _TaskBlock(void) 236 | { 237 | MemBarrier(); 238 | TaskControl[CurrentTask].state = BLOCKED; 239 | _Schedule(); 240 | } 241 | 242 | void _TaskUnblock(TaskIdType task) 243 | { 244 | TaskSetReady(task); 245 | _Schedule(); 246 | } 247 | 248 | void _Snooze(int tim) 249 | { 250 | TaskControl[CurrentTask].expire = tim; 251 | _TaskBlock(); 252 | } 253 | 254 | void _AcquireSemaphore(SemIdType sem) 255 | { 256 | SpinLock(&SemaphoreControl[sem].lock); 257 | while (SemaphoreControl[sem].owner_task != SEM_AVAILABLE) { 258 | TaskControl[CurrentTask].target_sem = sem; 259 | TaskControl[CurrentTask].state = BLOCKED; 260 | SpinUnlock(&SemaphoreControl[sem].lock); 261 | _Schedule(); 262 | SpinLock(&SemaphoreControl[sem].lock); 263 | } 264 | SemaphoreControl[sem].owner_task = CurrentTask; 265 | SpinUnlock(&SemaphoreControl[sem].lock); 266 | } 267 | 268 | int _TryToAcquireSemaphore(SemIdType sem) 269 | { 270 | SpinLock(&SemaphoreControl[sem].lock); 271 | if (SemaphoreControl[sem].owner_task == SEM_AVAILABLE) { 272 | SemaphoreControl[sem].owner_task = CurrentTask; 273 | } 274 | SpinUnlock(&SemaphoreControl[sem].lock); 275 | return SemaphoreControl[sem].owner_task == CurrentTask; 276 | } 277 | 278 | void _ReleaseSemaphore(SemIdType sem) 279 | { 280 | TaskIdType task; 281 | SpinLock(&SemaphoreControl[sem].lock); 282 | SemaphoreControl[sem].owner_task = SEM_AVAILABLE; 283 | for (task = 0; task < NUMBER_OF_TASKS; task++) { 284 | if (TaskControl[task].state == BLOCKED && TaskControl[task].target_sem == sem) { 285 | TaskControl[task].target_sem = NO_SEM; 286 | TaskControl[task].expire = 0; /* XXX */ 287 | SpinUnlock(&SemaphoreControl[sem].lock); 288 | _TaskUnblock(task); 289 | SpinLock(&SemaphoreControl[sem].lock); 290 | } 291 | } 292 | SpinUnlock(&SemaphoreControl[sem].lock); 293 | } 294 | 295 | static void TaskEntry(void) 296 | { 297 | SpinUnlock(&lock_sched); 298 | TaskStart(TaskControl[CurrentTask].entry, &task_ustack[CurrentTask][USTACKSIZE]); 299 | } 300 | 301 | static void InitTask(TaskIdType task) 302 | { 303 | context* p = (context *)&TaskControl[task].task_kstack[KSTACKSIZE] - 1; 304 | p->ra = (unsigned long)TaskEntry; 305 | TaskControl[task].sp = (unsigned long)p; 306 | TaskControl[task].remaining_time = TaskControl[task].time_slice; 307 | TaskControl[task].target_sem = NO_SEM; 308 | } 309 | 310 | static __thread unsigned long nexttime; 311 | 312 | #define INTERVAL 10000000U 313 | 314 | static int Timer(void) 315 | { 316 | TaskIdType task; 317 | 318 | _print_message("Timer\n"); 319 | 320 | do { 321 | nexttime += INTERVAL; 322 | sbi_set_timer(nexttime); 323 | } while ((long)(_get_time() - nexttime) >= 0); 324 | 325 | if (ThisCore == CORE0) { 326 | for (task = 0; task < NUMBER_OF_TASKS; task++) { 327 | if (TaskControl[task].state == BLOCKED && TaskControl[task].expire > 0) { 328 | if (--TaskControl[task].expire == 0) { 329 | TaskSetReady(task); 330 | } 331 | } 332 | } 333 | } 334 | 335 | if (--TaskControl[CurrentTask].remaining_time <= 0) { 336 | TaskControl[CurrentTask].remaining_time = TaskControl[CurrentTask].time_slice; 337 | return TRUE; 338 | } 339 | 340 | return FALSE; 341 | } 342 | 343 | static int InterCoreInt(void) 344 | { 345 | _print_message("Inter-Core Interrupt\n"); 346 | 347 | clear_IPI(); 348 | 349 | if (CurrentTask >= TASKIDLE) { 350 | return TRUE; /* reschedule request */ 351 | } 352 | return FALSE; 353 | } 354 | 355 | int InterruptHandler(unsigned long cause) 356 | { 357 | switch ((unsigned short)cause) { 358 | case INT_SMODE_SOFT: 359 | return InterCoreInt(); 360 | break; 361 | case INT_SMODE_TIMER: 362 | return Timer(); 363 | break; 364 | default: 365 | break; 366 | } 367 | return FALSE; 368 | } 369 | 370 | long SvcHandler(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long sysno) 371 | { 372 | typedef long (*syscall_t)(long a0, long a1, long a2, long a3, long a4, long a5, long a6); 373 | const syscall_t systable[] = { 374 | (syscall_t)_Schedule, 375 | (syscall_t)_AcquireSemaphore, 376 | (syscall_t)_TryToAcquireSemaphore, 377 | (syscall_t)_ReleaseSemaphore, 378 | (syscall_t)_Snooze, 379 | (syscall_t)_print_message, 380 | (syscall_t)_get_time, 381 | }; 382 | 383 | return systable[sysno](a0, a1, a2, a3, a4, a5, a6); 384 | } 385 | 386 | int ExcHandler(unsigned long* ctx, unsigned long sepc, unsigned long scause, unsigned long sstatus, unsigned long stval) 387 | { 388 | _print_message("Exception: sepc(0x%x) scause(0x%x) sstatus(0x%x) stval(0x%x), sp(0x%x) ra(0x%x) s0(0x%x) s1(0x%x)\n", sepc, scause, sstatus, stval, ctx[2], ctx[1], ctx[8], ctx[9]); 389 | _print_message(" a0(0x%x) a1(0x%x) a2(0x%x) a3(0x%x) a4(0x%x) a5(0x%x)\n", ctx[10], ctx[11], ctx[12], ctx[13], ctx[14], ctx[15]); 390 | } 391 | 392 | static void StartTimer(void) 393 | { 394 | nexttime = _get_time() + INTERVAL; 395 | sbi_set_timer(nexttime); 396 | } 397 | 398 | static void mem_clear(unsigned char *start, unsigned char *end) 399 | { 400 | unsigned char *p; 401 | for (p = start; p < end; p++) { 402 | *p = 0LL; 403 | } 404 | } 405 | 406 | static void mem_copy(unsigned char *to, unsigned char *from, unsigned int size) 407 | { 408 | unsigned int sz; 409 | for (sz = 0; sz < size; sz++) { 410 | to[sz] = from[sz]; 411 | } 412 | } 413 | 414 | static void clearbss(void) 415 | { 416 | extern unsigned char _system_bss_start[]; 417 | extern unsigned char _system_bss_end[]; 418 | extern unsigned char _bss_start[]; 419 | extern unsigned char _bss_end[]; 420 | 421 | mem_clear(_system_bss_start, _system_bss_end); 422 | mem_clear(_bss_start, _bss_end); 423 | } 424 | 425 | static void setupTLS(void) 426 | { 427 | extern unsigned char _tls_start[]; 428 | extern unsigned char _tdata_start[]; 429 | extern unsigned char _tdata_end[]; 430 | extern unsigned char _tbss_start[]; 431 | extern unsigned char _tbss_end[]; 432 | 433 | const unsigned int tdata_size = _tdata_end - _tdata_start; 434 | const unsigned int tbss_size = _tbss_end - _tbss_start; 435 | register unsigned char* threadp asm("tp"); 436 | 437 | mem_copy(threadp, _tdata_start, tdata_size); 438 | mem_clear(&threadp[tbss_size], &threadp[tdata_size + tbss_size]); 439 | } 440 | 441 | static volatile CoreIdType BootCore = CORE_UNASSIGNED; 442 | 443 | static void sync_cores(void) 444 | { 445 | volatile static _Bool notyet = TRUE; 446 | 447 | if (ThisCore == BootCore) { 448 | MemBarrier(); 449 | notyet = FALSE; 450 | } else { 451 | while (notyet); 452 | } 453 | } 454 | 455 | static void start_cores(void) 456 | { 457 | int coreid; 458 | 459 | for (coreid = CORE0; coreid < NUMBER_OF_CORES; coreid++) { 460 | if (coreid != BootCore) { 461 | struct sbiret ret = sbi_hart_start(coreid, (unsigned long)_secondary_start, coreid); 462 | if (ret.error) { 463 | _print_message("sbi_hart_start(core%x) failed. error(0x%x)\n", coreid, ret.error); 464 | } 465 | } 466 | } 467 | } 468 | 469 | static void restart_bootcore(void) 470 | { 471 | struct sbiret ret; 472 | CoreIdType coreid; 473 | 474 | for (coreid = CORE0; coreid < NUMBER_OF_CORES; coreid++) { 475 | struct sbiret ret = sbi_hart_get_status(coreid); 476 | if (ret.error == SBI_SUCCESS && ret.value == STARTED) { 477 | BootCore = coreid; 478 | _secondary_start(BootCore); 479 | } 480 | } 481 | } 482 | 483 | void main(CoreIdType coreid) 484 | { 485 | TaskIdType task; 486 | 487 | SetTrapVectors((unsigned long)trap_vectors + TVEC_VECTORED_MODE); 488 | 489 | if (BootCore == CORE_UNASSIGNED) { 490 | restart_bootcore(); 491 | } 492 | 493 | setupTLS(); 494 | ThisCore = coreid; 495 | 496 | if (ThisCore == BootCore) { 497 | clearbss(); 498 | SetupPageTables(); 499 | 500 | for (task = 0; task < NUMBER_OF_TASKS; task++) { 501 | InitTask(task); 502 | } 503 | 504 | start_cores(); 505 | } 506 | sync_cores(); 507 | 508 | EnableMMU(); 509 | 510 | StartTimer(); 511 | EnableInterrupts(); 512 | 513 | _print_message("Core%x started.\n", ThisCore); 514 | 515 | SpinLock(&lock_sched); 516 | CurrentTask = TASKIDLE + ThisCore; 517 | TaskControl[CurrentTask].coreid = ThisCore; 518 | load_context(&TaskControl[CurrentTask].sp); 519 | } 520 | 521 | -------------------------------------------------------------------------------- /sophiaOS/makefile: -------------------------------------------------------------------------------- 1 | 2 | CFLAGS_APP = ${CFLAGS} -msmall-data-limit=0 3 | 4 | .SUFFIXES: .c .s .o 5 | 6 | .c.o: 7 | $(CC) $(CFLAGS) -c $< 8 | 9 | .s.o: 10 | $(CC) $(CFLAGS) -c $< 11 | 12 | all: sophia 13 | 14 | sophia: main.o vma.o primitives.o start.o syscall.o sbi.o application.o riscv-virt.lds 15 | $(LD) main.o vma.o primitives.o sbi.o start.o syscall.o application.o -T riscv-virt.lds -o $@ ${LDFLAGS} 16 | 17 | application.o: application.c 18 | $(CC) $(CFLAGS_APP) -c $< 19 | 20 | clean: 21 | -rm -f sophia *.o 22 | -------------------------------------------------------------------------------- /sophiaOS/primitives.s: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | .equ INT_SMODE_SOFT, 1 28 | .equ INT_SMODE_TIMER, 5 29 | 30 | .equ IP_SSI, (1U< 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | OUTPUT_ARCH( "riscv" ) 28 | 29 | ENTRY( _start ) 30 | 31 | MEMORY 32 | { 33 | ram_system (wxa!ri) : ORIGIN = 0x80200000, LENGTH = 16M 34 | ram_app (wxa!ri) : ORIGIN = 0x81200000, LENGTH = 16M 35 | /* Don't overwrite the memory at 0x82200000 where dtb exists */ 36 | } 37 | 38 | _CLV_SIZE = 1048; 39 | _STACK_SIZE = 4096; 40 | _ESTACK_SIZE = 1024; 41 | _TLS_SIZE = _CLV_SIZE + _STACK_SIZE; 42 | _MAXCORE = 8; 43 | 44 | SECTIONS 45 | { 46 | .system_text : { 47 | PROVIDE(_text_start = .); 48 | *(.reset) 49 | main.o(.text .text.*) 50 | vma.o(.text .text.*) 51 | primitives.o(.text .text.*) 52 | sbi.o(.text .text.*) 53 | PROVIDE(_text_end = .); 54 | } >ram_system AT>ram_system 55 | 56 | .system_rodata : { 57 | main.o(.rodata .rodata.*) 58 | vma.o(.rodata .rodata.*) 59 | primitives.o(.rodata .rodata.*) 60 | sbi.o(.rodata .rodata.*) 61 | *(.note.* ) 62 | } >ram_system AT>ram_system 63 | 64 | .system_data : { 65 | . = ALIGN(4096); 66 | main.o(.data .data.*) 67 | vma.o(.data .data.*) 68 | primitives.o(.data .data.*) 69 | sbi.o(.data .data.*) 70 | } >ram_system AT>ram_system 71 | 72 | .system_sdata : { 73 | PROVIDE( __global_pointer$ = . + 0x800 ); 74 | main.o(.sdata .sdata.*) 75 | vma.o(.sdata .sdata.*) 76 | primitives.o(.sdata .sdata.*) 77 | sbi.o(.sdata .sdata.*) 78 | } >ram_system AT>ram_system 79 | 80 | PROVIDE(_system_bss_start = .); 81 | 82 | .system_sbss : { 83 | main.o(.sbss .sbss.*) 84 | vma.o(.sbss .sbss.*) 85 | primitives.o(.sbss .sbss.*) 86 | sbi.o(.sbss .sbss.*) 87 | } >ram_system AT>ram_system 88 | 89 | .system_bss :{ 90 | main.o(.bss .bss.*) 91 | vma.o(.bss .bss.*) 92 | primitives.o(.bss .bss.*) 93 | sbi.o(.bss .bss.*) 94 | } >ram_system AT>ram_system 95 | 96 | PROVIDE(_system_bss_end = .); 97 | 98 | /* tls data backup section */ 99 | .system_tdata : { 100 | PROVIDE(_tdata_start = .); 101 | main.o(.tdata .tdata.*) 102 | vma.o(.tdata .tdata.*) 103 | primitives.o(.tdata .tdata.*) 104 | sbi.o(.tdata .tdata.*) 105 | PROVIDE(_tdata_end = .); 106 | } >ram_system AT>ram_system 107 | 108 | .system_tbss : { 109 | PROVIDE(_tbss_start = .); 110 | main.o(.tbss .tbss.*) 111 | vma.o(.tbss .tbss.*) 112 | primitives.o(.tbss .tbss.*) 113 | sbi.o(.tbss .tbss.*) 114 | PROVIDE(_tbss_end = .); 115 | } >ram_system AT>ram_system 116 | 117 | .tls :{ 118 | . = ALIGN(16); 119 | PROVIDE(_tls_start = .); 120 | . = . + _TLS_SIZE * _MAXCORE; 121 | . = ALIGN(16); 122 | PROVIDE(_tls_end = .); 123 | } >ram_system AT>ram_system 124 | 125 | .text : { 126 | *(.text .text.*) 127 | } >ram_app AT>ram_app 128 | 129 | .rodata : { 130 | *(.rodata .rodata.*) 131 | } >ram_app AT>ram_app 132 | 133 | .data : { 134 | . = ALIGN(4096); 135 | *(.data .data.*) 136 | } >ram_app AT>ram_app 137 | 138 | .bss :{ 139 | . = ALIGN(16); 140 | PROVIDE(_bss_start = .); 141 | *(.bss .bss.*) 142 | . = ALIGN(16); 143 | PROVIDE(_bss_end = .); 144 | } >ram_app AT>ram_app 145 | 146 | ram_system_start = ORIGIN(ram_system); 147 | ram_system_size = LENGTH(ram_system); 148 | ram_app_start = ORIGIN(ram_app); 149 | ram_app_size = LENGTH(ram_app); 150 | } 151 | -------------------------------------------------------------------------------- /sophiaOS/sbi.h: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | struct sbiret { 28 | long error; 29 | long value; 30 | }; 31 | 32 | extern struct sbiret sbi_set_timer(unsigned long stime_value); 33 | extern struct sbiret sbi_send_ipi(unsigned long hart_mask, unsigned long hart_mask_base); 34 | extern struct sbiret sbi_hart_start(unsigned long hartid, unsigned long start_addr, unsigned long opaque); 35 | extern struct sbiret sbi_hart_get_status(unsigned long hartid); 36 | extern struct sbiret sbi_debug_console_write_byte(unsigned char byte); 37 | 38 | #define SBI_SUCCESS 0 39 | #define SBI_ERR_FAILED -1 40 | #define SBI_ERR_NOT_SUPPORTED -2 41 | #define SBI_ERR_INVALID_PARAM -3 42 | #define SBI_ERR_DENIED -4 43 | #define SBI_ERR_INVALID_ADDRESS -5 44 | #define SBI_ERR_ALREADY_AVAILABLE -6 45 | #define SBI_ERR_ALREADY_STARTED -7 46 | #define SBI_ERR_ALREADY_STOPPED -8 47 | #define SBI_ERR_NO_SHMEM -9 48 | #define SBI_ERR_INVALID_STATE -10 49 | #define SBI_ERR_BAD_RANGE -11 50 | 51 | #define STARTED 0 52 | #define STOPPED 1 53 | #define START_PENDING 2 54 | #define STOP_PENDING 3 55 | #define SUSPENDED 4 56 | #define SUSPEND_PENDING 5 57 | #define RESUME_PENDING 6 58 | 59 | -------------------------------------------------------------------------------- /sophiaOS/sbi.s: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | .equ EID_TIME, ('T'<<24U|'I'<<16U|'M'<<8U|'E') 28 | .equ EID_sPI, ('s'<<16U|'P'<<8U|'I') 29 | .equ EID_HSM, ('H'<<16U|'S'<<8U|'M') 30 | .equ EID_DBCN, ('D'<<24U|'B'<<16U|'C'<<8U|'N') 31 | 32 | .equ FID_TIME_SETTIMER, 0 33 | .equ FID_sPI_SENDIPI, 0 34 | .equ FID_HART_START, 0 35 | .equ FID_HART_GETSTATUS, 2 36 | .equ FID_DBCN_WRITE, 0 37 | .equ FID_DBCN_READ, 1 38 | .equ FID_DBCN_WRITE_BYTE, 2 39 | 40 | .global sbi_set_timer 41 | .type sbi_set_timer,@function 42 | sbi_set_timer: 43 | li a7, EID_TIME 44 | li a6, FID_TIME_SETTIMER 45 | ecall 46 | ret 47 | .size sbi_set_timer,.-sbi_set_timer 48 | 49 | .global sbi_send_ipi 50 | .type sbi_send_ipi,@function 51 | sbi_send_ipi: 52 | li a7, EID_sPI 53 | li a6, FID_sPI_SENDIPI 54 | ecall 55 | ret 56 | .size sbi_send_ipi,.-sbi_send_ipi 57 | 58 | .global sbi_hart_start 59 | .type sbi_hart_start,@function 60 | sbi_hart_start: 61 | li a7, EID_HSM 62 | li a6, FID_HART_START 63 | ecall 64 | ret 65 | .size sbi_hart_start,.-sbi_hart_start 66 | 67 | .global sbi_hart_get_status 68 | .type sbi_hart_get_status,@function 69 | sbi_hart_get_status: 70 | li a7, EID_HSM 71 | li a6, FID_HART_GETSTATUS 72 | ecall 73 | ret 74 | .size sbi_hart_get_status,.-sbi_hart_get_status 75 | 76 | .global sbi_debug_console_write_byte 77 | .type sbi_debug_console_write_byte,@function 78 | sbi_debug_console_write_byte: 79 | li a7, EID_DBCN 80 | li a6, FID_DBCN_WRITE_BYTE 81 | ecall 82 | ret 83 | .size sbi_debug_console_write_byte,.-sbi_debug_console_write_byte 84 | 85 | -------------------------------------------------------------------------------- /sophiaOS/start.s: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | .section .reset,"ax",@progbits 28 | .option norelax 29 | .globl _start 30 | .globl _secondary_start 31 | _start: 32 | mv a0, zero 33 | 34 | _secondary_start: 35 | /* a0 = mhartid */ 36 | la gp, __global_pointer$ 37 | 38 | /* tp = _tls_start + mhartid*_TLS_SIZE */ 39 | la tp, _tls_start 40 | la t1, _TLS_SIZE 41 | mul t2, t1, a0 42 | add tp, tp, t2 43 | 44 | /* sscratch = tp + _CLV_SIZE */ 45 | la t1, _CLV_SIZE 46 | add t3, tp, t1 47 | csrw sscratch, t3 48 | 49 | /* sp = sscratch + _STACK_SIZE */ 50 | la t1, _STACK_SIZE 51 | add sp, t3, t1 52 | 53 | j main 54 | 55 | -------------------------------------------------------------------------------- /sophiaOS/syscall.s: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | .equ SYS_SCHEDULE, 0 28 | .equ SYS_ACQUIRESEMAPHORE, 1 29 | .equ SYS_TRYTOACQUIRESEMAPHORE, 2 30 | .equ SYS_RELEASESEMAPHORE, 3 31 | .equ SYS_SNOOZE, 4 32 | .equ SYS_PRINTMSG, 5 33 | .equ SYS_GETTIME, 6 34 | 35 | .global Schedule 36 | .type Schedule,@function 37 | Schedule: 38 | li a7, SYS_SCHEDULE 39 | ecall 40 | ret 41 | .size Schedule,.-Schedule 42 | 43 | .global AcquireSemaphore 44 | .type AcquireSemaphore,@function 45 | AcquireSemaphore: 46 | li a7, SYS_ACQUIRESEMAPHORE 47 | ecall 48 | ret 49 | .size AcquireSemaphore,.-AcquireSemaphore 50 | 51 | .global TryToAcquireSemaphore 52 | .type TryToAcquireSemaphore,@function 53 | TryToAcquireSemaphore: 54 | li a7, SYS_TRYTOACQUIRESEMAPHORE 55 | ecall 56 | ret 57 | .size TryToAcquireSemaphore,.-TryToAcquireSemaphore 58 | 59 | .global ReleaseSemaphore 60 | .type ReleaseSemaphore,@function 61 | ReleaseSemaphore: 62 | li a7, SYS_RELEASESEMAPHORE 63 | ecall 64 | ret 65 | .size ReleaseSemaphore,.-ReleaseSemaphore 66 | 67 | .global Snooze 68 | .type Snooze,@function 69 | Snooze: 70 | li a7, SYS_SNOOZE 71 | ecall 72 | ret 73 | .size Snooze,.-Snooze 74 | 75 | .global print_message 76 | .type print_message,@function 77 | print_message: 78 | li a7, SYS_PRINTMSG 79 | ecall 80 | ret 81 | .size print_message,.-print_message 82 | 83 | .global get_time 84 | .type get_time,@function 85 | get_time: 86 | li a7, SYS_GETTIME 87 | ecall 88 | ret 89 | .size get_time,.-get_time 90 | -------------------------------------------------------------------------------- /sophiaOS/vma.c: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2021 VA Linux Systems Japan, K.K. 5 | 6 | Author : Hirokazu Takahashi 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | #include "vma.h" 28 | 29 | extern unsigned char ram_app_size[]; /* The size must be a power of 2 */ 30 | extern unsigned char ram_app_start[]; /* The address must be multiples of the size */ 31 | extern unsigned char ram_system_size[]; /* The size must be a power of 2 */ 32 | extern unsigned char ram_system_start[]; /* The address must be multiples of the size */ 33 | 34 | #define SHARED_ASID 0UL 35 | 36 | extern void SetSATP(unsigned long pagetable); 37 | 38 | static pte_t pgtable_root[NUM_PTE_IN_PAGE] __attribute__ ((aligned (PAGESIZE))); 39 | static pte_t pgtable_lvl2_mem[NUM_PTE_IN_PAGE] __attribute__ ((aligned (PAGESIZE))); 40 | static pte_t pgtable_lvl2_io[NUM_PTE_IN_PAGE] __attribute__ ((aligned (PAGESIZE))); 41 | 42 | #define UART_SPACE 0x10000000U 43 | 44 | static void init_ptes(pte_t* pte, unsigned int begin, unsigned int end, unsigned long pfn, unsigned long mode) 45 | { 46 | int ent; 47 | 48 | for (ent = begin; ent < end; ent++, pfn += NUM_PTE_IN_PAGE) { 49 | pte[ent] = (pfn< 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | typedef unsigned long pte_t; 28 | 29 | #define PTE_V (1UL<<0U) 30 | #define PTE_R (1UL<<1U) 31 | #define PTE_W (1UL<<2U) 32 | #define PTE_X (1UL<<3U) 33 | #define PTE_U (1UL<<4U) 34 | #define PTE_G (1UL<<5U) 35 | #define PTE_A (1UL<<6U) 36 | #define PTE_D (1UL<<7U) 37 | #define PTE_PPN_SHIFT 10U 38 | 39 | #define PAGESIZE_SHIFT 12U 40 | #define PAGESIZE (1UL<> PAGESIZE_SHIFT) 46 | #define SUPER_PAGE_NUMBER(addr) (PAGE_NUMBER(addr)/NUM_PTE_IN_PAGE) 47 | #define HUGE_PAGE_NUMBER(addr) (SUPER_PAGE_NUMBER(addr)/NUM_PTE_IN_PAGE) 48 | 49 | #define ATP_MODE_BARE (0UL<<60U) 50 | #define ATP_MODE_SV39 (8UL<<60U) 51 | #define ATP_MODE_SV48 (9UL<<60U) 52 | #define ATP_MODE_SV57 (10UL<<60U) 53 | #define ATP_MODE_SV64 (11UL<<60U) 54 | #define ATP_ASID(asid) ((asid)<<44U) 55 | 56 | extern void SetupPageTables(void); 57 | extern void EnableMMU(void); 58 | --------------------------------------------------------------------------------