├── include ├── uapi │ ├── io │ └── monitor │ │ └── syscalls.h ├── io │ ├── bitsperlong.h │ ├── kbuild.h │ ├── build_bug.h │ ├── const.h │ ├── linkage.h │ ├── asm.h │ ├── sizes.h │ └── nospec.h ├── asm │ ├── cache.h │ ├── processor.h │ ├── mcall.h │ ├── tlbflush.h │ ├── csr_bits │ │ ├── ideleg.h │ │ ├── pmpcfg.h │ │ ├── ie.h │ │ ├── ip.h │ │ ├── satp.h │ │ ├── isa.h │ │ ├── edeleg.h │ │ ├── cause.h │ │ └── status.h │ ├── page.h │ ├── barrier.h │ ├── setup.h │ ├── pgtable-bits.h │ ├── word-at-a-time.h │ ├── ptrace.h │ ├── pmp.h │ ├── bitops.h │ ├── asm-offsets.h │ ├── entry.h │ ├── io.h │ ├── sbi.h │ └── pgtable.h └── sys │ ├── sections.h │ ├── init.h │ ├── poison.h │ ├── timex.h │ ├── unaligned.h │ ├── log2.h │ ├── byteorder.h │ ├── console.h │ ├── spinlock.h │ ├── bug.h │ ├── bitops │ ├── fls64.h │ ├── __ffs.h │ └── __fls.h │ ├── pfn.h │ ├── swab.h │ ├── ioport.h │ ├── bitmap.h │ ├── ilist.h │ ├── unaligned │ ├── le_byteshift.h │ ├── be_byteshift.h │ └── generic.h │ ├── bitops.h │ ├── of.h │ ├── vmlinux.lds.h │ ├── ctype.h │ ├── printk.h │ ├── string.h │ └── memblock.h ├── monitor ├── verif │ ├── generated │ ├── test.rkt │ ├── asm-offsets.c │ ├── verif.mk │ ├── safety.rkt │ └── spec.rkt ├── entry.S ├── kernel │ ├── syscall.S │ ├── kernel.mk │ └── main.c ├── monitor.mk ├── monitor.c └── main.c ├── bbl ├── bbl.o ├── libutil.a ├── libmachine.a ├── libsoftfloat.a ├── payload.S └── bbl.lds ├── .dockerignore ├── serval ├── serval │ ├── spec │ │ ├── lang │ │ │ └── reader.rkt │ │ ├── refinement.rkt │ │ ├── ni.rkt │ │ └── refcnt.rkt │ ├── x32.rkt │ ├── info.rkt │ ├── unicorn │ │ ├── engine.rkt │ │ ├── gen.sh │ │ ├── x86.rkt │ │ ├── const_generator.py │ │ ├── python │ │ │ └── unicorn_const.py │ │ └── const │ │ │ └── unicorn.rkt │ ├── llvm │ │ ├── base.rkt │ │ ├── capi │ │ │ ├── irreader.rkt │ │ │ └── target.rkt │ │ ├── lang.rkt │ │ └── print.rkt │ ├── riscv │ │ ├── synth.rkt │ │ ├── shims.rkt │ │ ├── pmp.rkt │ │ └── spec.rkt │ ├── lang │ │ └── nm.rkt │ ├── lib │ │ ├── unittest.rkt │ │ └── debug.rkt │ ├── unicorn.rkt │ ├── python.rkt │ └── sha256.rkt ├── info.rkt └── .gitignore ├── slides ├── rosette.pdf └── overview.pdf ├── bios ├── ptrace.c ├── bios.mk ├── traps.c ├── entry.S ├── bios.lds.S ├── shutdown.c ├── cpu.c ├── htif.c ├── boot │ └── head.S ├── sifive.c ├── uart8250.c └── mcall.c ├── kernel ├── smp.c ├── shutdown.c ├── libfdt │ ├── libfdt_env.h │ ├── fdt_addresses.c │ ├── libfdt_internal.h │ └── fdt_strerror.c ├── kernel.mk ├── kernel.lds.S ├── panic.c ├── bswap.c ├── sbi_console.c ├── time.c ├── ptrace.c ├── setup.c ├── asm-offsets.c ├── entry.S ├── dumpstack.c ├── hexdump.c ├── ctype.c ├── boot │ └── head.S ├── console.c └── bitops.c ├── .gitignore ├── config.mk └── scripts └── Dockerfile /include/uapi/io: -------------------------------------------------------------------------------- 1 | ../io -------------------------------------------------------------------------------- /monitor/verif/generated: -------------------------------------------------------------------------------- 1 | ../../o.riscv64/ -------------------------------------------------------------------------------- /monitor/entry.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | .section .text 4 | 5 | -------------------------------------------------------------------------------- /bbl/bbl.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uw-unsat/serval-tutorial-sosp19/HEAD/bbl/bbl.o -------------------------------------------------------------------------------- /bbl/libutil.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uw-unsat/serval-tutorial-sosp19/HEAD/bbl/libutil.a -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.git 2 | o.riscv64 3 | .gitlab-ci.yml 4 | .gitignore 5 | .dockerignore 6 | local.mk -------------------------------------------------------------------------------- /bbl/libmachine.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uw-unsat/serval-tutorial-sosp19/HEAD/bbl/libmachine.a -------------------------------------------------------------------------------- /bbl/libsoftfloat.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uw-unsat/serval-tutorial-sosp19/HEAD/bbl/libsoftfloat.a -------------------------------------------------------------------------------- /serval/serval/spec/lang/reader.rkt: -------------------------------------------------------------------------------- 1 | #lang s-exp syntax/module-reader 2 | serval/spec/lang/expander 3 | -------------------------------------------------------------------------------- /slides/rosette.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uw-unsat/serval-tutorial-sosp19/HEAD/slides/rosette.pdf -------------------------------------------------------------------------------- /slides/overview.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uw-unsat/serval-tutorial-sosp19/HEAD/slides/overview.pdf -------------------------------------------------------------------------------- /bios/ptrace.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct pt_regs *current_pt_regs(void) 4 | { 5 | return (void *)(uintptr_t)csr_read(mscratch); 6 | } 7 | -------------------------------------------------------------------------------- /include/io/bitsperlong.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define BITS_PER_BYTE 8 4 | #define BITS_PER_LONG (BITS_PER_BYTE * __SIZEOF_LONG__) 5 | -------------------------------------------------------------------------------- /kernel/smp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | uint64_t cpu_stack[NR_CPUS][CPU_STACK_SIZE / sizeof(uint64_t)] __aligned(SZ_4K); 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.d 3 | __pycache__ 4 | compiled 5 | /.vscode 6 | /local.mk 7 | /o.* 8 | .codemod.bookmark 9 | *.pyc 10 | .DS_Store 11 | .gdbinit 12 | -------------------------------------------------------------------------------- /kernel/shutdown.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void __weak shutdown(void) 4 | { 5 | sbi_shutdown(); 6 | while (1) 7 | ; 8 | } 9 | -------------------------------------------------------------------------------- /bios/bios.mk: -------------------------------------------------------------------------------- 1 | BIOS_LDS := $(O)/bios/bios.lds 2 | BIOS_OBJS := $(call object,$(wildcard bios/*.S bios/*.c)) 3 | BIOS_BOOT_OBJS := $(call object,$(wildcard bios/boot/*.S)) 4 | -------------------------------------------------------------------------------- /include/asm/cache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define L1_CACHE_SHIFT 6 4 | 5 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) 6 | 7 | #define SMP_CACHE_BYTES L1_CACHE_BYTES 8 | -------------------------------------------------------------------------------- /serval/serval/x32.rkt: -------------------------------------------------------------------------------- 1 | 2 | #lang rosette 3 | 4 | (require "x32/base.rkt" 5 | "x32/interp.rkt") 6 | 7 | (provide (all-from-out "x32/base.rkt") 8 | (all-from-out "x32/interp.rkt")) 9 | -------------------------------------------------------------------------------- /serval/serval/info.rkt: -------------------------------------------------------------------------------- 1 | #lang info 2 | 3 | (define collection 'use-pkg-name) 4 | 5 | (define raco-commands 6 | '(("serval" 7 | serval/bin/serval 8 | "Run serval verification" 9 | #f))) 10 | 11 | -------------------------------------------------------------------------------- /serval/info.rkt: -------------------------------------------------------------------------------- 1 | #lang info 2 | 3 | (define collection 'multi) 4 | 5 | (define deps '("rosette" "base" "rackunit-lib")) 6 | 7 | (define pkg-desc "Serval verification framework") 8 | (define version "0.0.1a") 9 | 10 | -------------------------------------------------------------------------------- /bbl/payload.S: -------------------------------------------------------------------------------- 1 | .section ".payload","a",@progbits 2 | 3 | .globl _payload_start, _payload_end 4 | .p2align 21 /* 2M */ 5 | _payload_start: 6 | .incbin BBL_PAYLOAD 7 | .p2align 12 /* 4K */ 8 | _payload_end: 9 | -------------------------------------------------------------------------------- /include/sys/sections.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern char _stext[], _etext[]; 4 | extern char _sdata[], _edata[]; 5 | extern char _start[], _end[]; 6 | extern char __bss_start[], __bss_end[]; 7 | extern char _payload_start[], _payload_end[]; 8 | -------------------------------------------------------------------------------- /serval/serval/unicorn/engine.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (require racket/generic) 4 | 5 | (provide (all-defined-out)) 6 | 7 | (define-generics engine 8 | (engine-ptr engine) 9 | (engine-reg-enum engine) 10 | (engine-reg-type engine reg)) 11 | -------------------------------------------------------------------------------- /include/asm/processor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | static inline void cpu_relax(void) 7 | { 8 | barrier(); 9 | } 10 | 11 | static inline void wait_for_interrupt(void) 12 | { 13 | asm volatile("wfi"); 14 | } 15 | -------------------------------------------------------------------------------- /include/sys/init.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define COMMAND_LINE_SIZE 512 4 | 5 | extern char boot_command_line[]; 6 | 7 | void htif_init(void); 8 | void sifive_init(void); 9 | void sbi_console_init(const char *color); 10 | void time_init(void); 11 | void uart8250_init(void); 12 | -------------------------------------------------------------------------------- /serval/.gitignore: -------------------------------------------------------------------------------- 1 | # OS generated files # 2 | ###################### 3 | .DS_Store 4 | .DS_Store? 5 | ._* 6 | .Spotlight-V100 7 | .Trashes 8 | ehthumbs.db 9 | Thumbs.db 10 | 11 | **/doc/*.css 12 | **/doc/*.html 13 | **/doc/*.js 14 | **/serval/doc/** 15 | **/bin/** 16 | **/compiled 17 | **/compiled/** 18 | *~ -------------------------------------------------------------------------------- /monitor/kernel/syscall.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define __SYSCALL(x, y) \ 4 | ENTRY(y); \ 5 | li a7, x; \ 6 | ecall; \ 7 | ret; \ 8 | ENDPROC(y) 9 | 10 | #include -------------------------------------------------------------------------------- /monitor/verif/test.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette/safe 2 | 3 | (require 4 | serval/lib/unittest 5 | serval/lib/core 6 | serval/riscv/base 7 | serval/riscv/interp 8 | serval/riscv/objdump 9 | "refinement.rkt" 10 | "safety.rkt") 11 | 12 | 13 | (module+ test 14 | (refinement-tests) 15 | (safety-tests)) 16 | -------------------------------------------------------------------------------- /include/asm/mcall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | extern phys_addr_t kernel_dtb; 7 | 8 | void mcall_init(phys_addr_t dtb); 9 | 10 | long do_mcall(struct pt_regs *regs); 11 | 12 | void mcall_console_putchar(uint8_t c); 13 | noreturn void mcall_shutdown(void); 14 | -------------------------------------------------------------------------------- /include/asm/tlbflush.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /* 5 | * Flush entire local TLB. 'sfence.vma' implicitly fences with the instruction 6 | * cache as well, so a 'fence.i' is not necessary. 7 | */ 8 | static __always_inline void local_flush_tlb_all(void) 9 | { 10 | asm volatile("sfence.vma" : : : "memory"); 11 | } 12 | -------------------------------------------------------------------------------- /monitor/kernel/kernel.mk: -------------------------------------------------------------------------------- 1 | TEST_KERNEL_ELF := $(O)/monitor/kernel.elf 2 | 3 | TEST_KERNEL_OBJS := $(call object,$(wildcard monitor/kernel/*.c monitor/kernel/*.S)) 4 | 5 | $(TEST_KERNEL_ELF): $(KERNEL_LDS) $(KERNEL_BOOT_OBJS) $(KERNEL_OBJS) $(TEST_KERNEL_OBJS) 6 | $(QUIET_LD)$(LD) -o $@ $(LDFLAGS) -T $^ 7 | $(Q)$(OBJDUMP) -S $@ > $(basename $@).asm 8 | -------------------------------------------------------------------------------- /kernel/libfdt/libfdt_env.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | typedef be16_t fdt16_t; 7 | typedef be32_t fdt32_t; 8 | typedef be64_t fdt64_t; 9 | 10 | #define fdt32_to_cpu(x) be32_to_cpu(x) 11 | #define cpu_to_fdt32(x) cpu_to_be32(x) 12 | #define fdt64_to_cpu(x) be64_to_cpu(x) 13 | #define cpu_to_fdt64(x) cpu_to_be64(x) 14 | -------------------------------------------------------------------------------- /serval/serval/unicorn/gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ./const_generator.py python/unicorn_const.py \ 4 | --enum UC_ARCH \ 5 | --enum UC_ERR \ 6 | --enum UC_MEM \ 7 | --enum UC_HOOK \ 8 | --bitmask UC_MODE \ 9 | --bitmask UC_PROT \ 10 | > const/unicorn.rkt 11 | 12 | ./const_generator.py python/x86_const.py \ 13 | --enum UC_X86_REG \ 14 | --enum UC_X86_INS_ \ 15 | > const/x86.rkt 16 | -------------------------------------------------------------------------------- /include/asm/csr_bits/ideleg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define IDEL_SOFT_U IP_USIP 6 | #define IDEL_SOFT_S IP_SSIP 7 | #define IDEL_SOFT_M IP_MSIP 8 | #define IDEL_TIMER_U IP_UTIP 9 | #define IDEL_TIMER_S IP_STIP 10 | #define IDEL_TIMER_M IP_MTIP 11 | #define IDEL_EXT_U IP_UEIP 12 | #define IDEL_EXT_S IP_SEIP 13 | #define IDEL_EXT_M IP_MEIP 14 | -------------------------------------------------------------------------------- /include/io/kbuild.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #define DEFINE(sym, val) \ 6 | asm volatile("\n.ascii \"->" #sym " %0 " #val "\"" : : "i" (val)) 7 | 8 | #define BLANK() asm volatile("\n.ascii \"->\"" : : ) 9 | 10 | #define OFFSET(sym, str, mem) \ 11 | DEFINE(sym, offsetof(struct str, mem)) 12 | 13 | #define COMMENT(x) \ 14 | asm volatile("\n.ascii \"->#" x "\"") 15 | -------------------------------------------------------------------------------- /include/uapi/monitor/syscalls.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYSCALL 2 | #define __SYSCALL(x, y) 3 | #endif 4 | 5 | /* Max number */ 6 | #define MAXUSER 4 7 | 8 | /* Start syscalls from 10, reserve 0-9 for SBI */ 9 | 10 | #define __NR_dict_get 10 11 | __SYSCALL(__NR_dict_get, sys_dict_get) 12 | 13 | #define __NR_dict_set 11 14 | __SYSCALL(__NR_dict_set, sys_dict_set) 15 | 16 | #define __NR_change_user 12 17 | __SYSCALL(__NR_change_user, sys_change_user) 18 | -------------------------------------------------------------------------------- /kernel/kernel.mk: -------------------------------------------------------------------------------- 1 | KERNEL_LDS := $(O)/kernel/kernel.lds 2 | KERNEL_OBJS := $(call object,$(wildcard kernel/*.S kernel/*.c kernel/libfdt/*.c kernel/hacl/*.c)) 3 | KERNEL_BOOT_OBJS := $(call object,$(wildcard kernel/boot/*.S)) 4 | 5 | include/asm/asm-offsets.h: $(O)/kernel/asm-offsets.S 6 | $(QUIET_GEN)$(call gen-offsets) < $< > $@~ 7 | $(Q)mv $@~ $@ 8 | 9 | $(O)/kernel/libfdt/%.o: CFLAGS += -I kernel/libfdt 10 | -------------------------------------------------------------------------------- /include/sys/poison.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #define POISON_POINTER_DELTA 0 6 | 7 | /* 8 | * These are non-NULL pointers that will result in page faults 9 | * under normal circumstances, used to verify that nobody uses 10 | * non-initialized list entries. 11 | */ 12 | #define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA) 13 | #define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA) 14 | -------------------------------------------------------------------------------- /bios/traps.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void show_sys_regs(void) 8 | { 9 | pr_info("mcause : " REG_FMT "\n", csr_read(mcause)); 10 | pr_info("mtval : " REG_FMT "\n", csr_read(mtval)); 11 | pr_info("mepc : " REG_FMT "\n", csr_read(mepc)); 12 | pr_info("mstatus : " REG_FMT "\n", csr_read(mstatus)); 13 | } 14 | -------------------------------------------------------------------------------- /include/sys/timex.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-only */ 2 | /* 3 | * Copyright (C) 2012 Regents of the University of California 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | typedef unsigned long cycles_t; 11 | typedef unsigned long useconds_t; 12 | 13 | static inline cycles_t get_cycles(void) 14 | { 15 | cycles_t n; 16 | 17 | asm volatile("rdcycle %0" : "=r" (n)); 18 | return n; 19 | } 20 | 21 | useconds_t uptime(void); 22 | -------------------------------------------------------------------------------- /kernel/kernel.lds.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | OUTPUT_ARCH(riscv) 6 | ENTRY(_start) 7 | 8 | SECTIONS 9 | { 10 | . = KERNEL_VIRTUAL_START; 11 | 12 | _stext = .; 13 | TEXT_SECTION 14 | _etext = .; 15 | 16 | _sdata = .; 17 | RO_DATA_SECTION(SZ_4K) 18 | RW_DATA_SECTION(SZ_4K) 19 | _edata = .; 20 | 21 | BSS_SECTION(SZ_4K, SZ_4K) 22 | _end = .; 23 | } 24 | -------------------------------------------------------------------------------- /include/asm/page.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define MAX_PHYSMEM_BITS 56 7 | 8 | #define PAGE_SHIFT (12) 9 | #define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) 10 | #define PAGE_MASK (~(PAGE_SIZE - 1)) 11 | 12 | #ifndef __ASSEMBLER__ 13 | 14 | extern unsigned long va_pa_offset; 15 | 16 | #define __pa(x) ((uintptr_t)(x) - va_pa_offset) 17 | #define __va(x) ((void *)((uintptr_t)(x) + va_pa_offset)) 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/asm/csr_bits/pmpcfg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define PMPCFG_R BIT_64(0) 6 | #define PMPCFG_W BIT_64(1) 7 | #define PMPCFG_X BIT_64(2) 8 | #define PMPCFG_RWX (PMPCFG_R | PMPCFG_W | PMPCFG_X) 9 | 10 | #define PMPCFG_A_SHIFT 3 11 | #define PMPCFG_A_OFF (0 << PMPCFG_A_SHIFT) 12 | #define PMPCFG_A_TOR (1 << PMPCFG_A_SHIFT) 13 | #define PMPCFG_A_NA4 (2 << PMPCFG_A_SHIFT) 14 | #define PMPCFG_A_NAPOT (3 << PMPCFG_A_SHIFT) 15 | 16 | #define PMPCFG_L BIT_64(7) 17 | -------------------------------------------------------------------------------- /include/asm/barrier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RISCV_FENCE(p, s) \ 4 | __asm__ __volatile__("fence " #p "," #s : : : "memory") 5 | 6 | static inline void memory_barrier(void) 7 | { 8 | RISCV_FENCE(rw, rw); 9 | } 10 | 11 | static inline void memory_load_barrier(void) 12 | { 13 | RISCV_FENCE(r, r); 14 | } 15 | 16 | static inline void memory_acquire_barrier(void) 17 | { 18 | RISCV_FENCE(r, rw); 19 | } 20 | 21 | static inline void memory_release_barrier(void) 22 | { 23 | RISCV_FENCE(rw, w); 24 | } 25 | -------------------------------------------------------------------------------- /include/asm/csr_bits/ie.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define IE_USIE BIT_64(0) 6 | #define IE_SSIE BIT_64(1) 7 | /* RESERVED BIT_64(2) */ 8 | #define IE_MSIE BIT_64(3) 9 | #define IE_UTIE BIT_64(4) 10 | #define IE_STIE BIT_64(5) 11 | /* RESERVED BIT_64(6) */ 12 | #define IE_MTIE BIT_64(7) 13 | #define IE_UEIE BIT_64(8) 14 | #define IE_SEIE BIT_64(9) 15 | /* RESERVED BIT_64(10) */ 16 | #define IE_MEIE BIT_64(11) 17 | -------------------------------------------------------------------------------- /include/asm/csr_bits/ip.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define IP_USIP BIT_64(0) 6 | #define IP_SSIP BIT_64(1) 7 | /* RESERVED BIT_64(2) */ 8 | #define IP_MSIP BIT_64(3) 9 | #define IP_UTIP BIT_64(4) 10 | #define IP_STIP BIT_64(5) 11 | /* RESERVED BIT_64(6) */ 12 | #define IP_MTIP BIT_64(7) 13 | #define IP_UEIP BIT_64(8) 14 | #define IP_SEIP BIT_64(9) 15 | /* RESERVED BIT_64(10) */ 16 | #define IP_MEIP BIT_64(11) 17 | -------------------------------------------------------------------------------- /monitor/verif/asm-offsets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void asm_offsets(void) 8 | { 9 | DEFINE(CONFIG_BOOT_CPU, CONFIG_BOOT_CPU); 10 | 11 | DEFINE(__NR_dict_get, __NR_dict_get); 12 | DEFINE(__NR_dict_set, __NR_dict_set); 13 | DEFINE(__NR_change_user, __NR_change_user); 14 | 15 | DEFINE(MAXUSER, MAXUSER); 16 | 17 | DEFINE(EXC_ECALL_S, EXC_ECALL_S); 18 | } 19 | -------------------------------------------------------------------------------- /bios/entry.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | .text 5 | 6 | ENTRY(machine_trap_vector) 7 | SAVE_REGS scratch=mscratch 8 | 9 | mv a0, sp 10 | csrr a1, mcause 11 | call do_trap 12 | 13 | restore_regs: 14 | RESTORE_REGS 15 | mret 16 | END(machine_trap_vector) 17 | 18 | ENTRY(mret_with_regs) 19 | /* a0 holds pt_regs */ 20 | mv sp, a0 21 | j restore_regs 22 | END(mret_with_regs) 23 | 24 | ENTRY(mret) 25 | mret 26 | END(mret) 27 | -------------------------------------------------------------------------------- /kernel/panic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void panic(const char *fmt, ...) 5 | { 6 | static char buf[1024]; 7 | va_list args; 8 | 9 | va_start(args, fmt); 10 | vsnprintf(buf, sizeof(buf), fmt, args); 11 | va_end(args); 12 | pr_emerg("panic: %s", buf); 13 | 14 | dump_stack(); 15 | shutdown(); 16 | } 17 | 18 | void die(struct pt_regs *regs, const char *str) 19 | { 20 | pr_emerg("%s", str); 21 | show_regs(regs); 22 | 23 | dump_stack(); 24 | shutdown(); 25 | } 26 | -------------------------------------------------------------------------------- /include/sys/unaligned.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 11 | # define get_unaligned __get_unaligned_le 12 | # define put_unaligned __put_unaligned_le 13 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 14 | # define get_unaligned __get_unaligned_be 15 | # define put_unaligned __put_unaligned_be 16 | #else 17 | # error need to define endianess 18 | #endif 19 | -------------------------------------------------------------------------------- /serval/serval/llvm/base.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (provide (all-defined-out)) 4 | 5 | (struct module (globals functions) #:transparent) 6 | 7 | (struct value (name type) #:transparent) 8 | 9 | (struct function value (arguments blocks) #:transparent) 10 | 11 | (struct argument value () #:transparent) 12 | 13 | (struct basic-block value (instructions) #:transparent) 14 | 15 | (struct instruction value (opcode operands attributes) #:transparent) 16 | 17 | (struct array-offset (index size) #:transparent) 18 | (struct struct-offset (value) #:transparent) 19 | 20 | (struct asm (template constraint) #:transparent) 21 | -------------------------------------------------------------------------------- /include/asm/csr_bits/satp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define SATP_PPN GENMASK_64(43, 0) 6 | #define SATP_ASID GENMASK_64(59, 44) 7 | #define SATP_MODE GENMASK_64(63, 60) 8 | 9 | #define SATP_MODE_SHIFT 60 10 | #define SATP_MODE_BARE (UINT64_C(0) << SATP_MODE_SHIFT) 11 | /* Reserved ... */ 12 | #define SATP_MODE_SV39 (UINT64_C(8) << SATP_MODE_SHIFT) 13 | #define SATP_MODE_SV48 (UINT64_C(9) << SATP_MODE_SHIFT) 14 | /* Reserved ... */ 15 | -------------------------------------------------------------------------------- /monitor/monitor.mk: -------------------------------------------------------------------------------- 1 | MONITOR_ELF := $(O)/monitor.elf 2 | 3 | MONITOR_OBJS := $(call object,$(wildcard monitor/*.c monitor/*.S)) 4 | MONITOR_OBJS += $(O)/monitor/kernel.bin.o 5 | 6 | include monitor/kernel/kernel.mk 7 | include monitor/verif/verif.mk 8 | 9 | $(MONITOR_ELF): $(BIOS_LDS) $(BIOS_BOOT_OBJS) $(BIOS_OBJS) $(KERNEL_OBJS) $(MONITOR_OBJS) 10 | $(QUIET_LD)$(LD) -o $@ $(LDFLAGS) -T $^ 11 | 12 | qemu-monitor: $(MONITOR_ELF) 13 | $(QEMU) $(QEMU_OPTS) -kernel $< 14 | 15 | spike-toymon: $(MONITOR_ELF) 16 | $(SPIKE) $(SPIKE_OPTS) $< 17 | 18 | ALL += $(MONITOR_ELF) 19 | 20 | PHONY += qemu-monitor spike-toymon 21 | -------------------------------------------------------------------------------- /serval/serval/riscv/synth.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette/safe 2 | 3 | (require 4 | "base.rkt" 5 | "interp.rkt" 6 | rosette/lib/synthax 7 | rosette/lib/angelic 8 | ) 9 | 10 | (provide (all-defined-out)) 11 | 12 | (define (binary-op) 13 | (choose* 14 | 'addi 15 | 'subi)) 16 | 17 | (define (gpr) (choose* 'x0 'x1 'x2 'x3 'x4 'x5 'x6 'x7 'x8 'x9 'x10 'x11 'x12 'x13 'x14 'x15)) 18 | 19 | (define-synthax ??-binary-op-imm 20 | ([(_) 21 | (let 22 | ([op (binary-op)] 23 | [dst (gpr)] 24 | [src1 (gpr)] 25 | [src2 'x0] 26 | [imm (?? (bitvector 12))] 27 | [size 4]) 28 | (instr op dst src1 src2 imm size))])) 29 | -------------------------------------------------------------------------------- /bios/bios.lds.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | OUTPUT_ARCH(riscv) 6 | ENTRY(_start) 7 | 8 | SECTIONS 9 | { 10 | . = DRAM_START; 11 | 12 | _stext = .; 13 | TEXT_SECTION 14 | _etext = .; 15 | 16 | _sdata = .; 17 | RO_DATA_SECTION(L1_CACHE_BYTES) 18 | . = ALIGN(SZ_4K); 19 | .htif : { 20 | *(.htif .htif.*) 21 | } 22 | RW_DATA_SECTION(SZ_4K) 23 | _edata = .; 24 | 25 | BSS_SECTION(SZ_4K, SZ_2M) 26 | _end = .; 27 | 28 | .payload : { 29 | *(.payload) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /include/sys/log2.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* Integer base 2 logarithm calculation 3 | * 4 | * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. 5 | * Written by David Howells (dhowells@redhat.com) 6 | */ 7 | 8 | #pragma once 9 | 10 | /** 11 | * is_power_of_2() - check if a value is a power of two 12 | * @n: the value to check 13 | * 14 | * Determine whether some value is a power of two, where zero is 15 | * *not* considered a power of two. 16 | * Return: true if @n is a power of 2, otherwise false. 17 | */ 18 | static inline bool is_power_of_2(unsigned long n) 19 | { 20 | return (n != 0 && ((n & (n - 1)) == 0)); 21 | } 22 | -------------------------------------------------------------------------------- /monitor/verif/verif.mk: -------------------------------------------------------------------------------- 1 | TOYMON_TESTS := \ 2 | monitor/verif/test.rkt \ 3 | 4 | verify-monitor: $(TOYMON_TESTS) 5 | $(RACO_TEST) $^ 6 | 7 | verify-monitor-%: monitor/verif/%.rkt $(TOYMON_TESTS) 8 | $(RACO_TEST) $< 9 | 10 | $(TOYMON_TESTS): | \ 11 | $(O)/monitor.c.asm \ 12 | $(O)/monitor.asm.rkt \ 13 | $(O)/monitor.map.rkt \ 14 | $(O)/monitor.globals.rkt \ 15 | $(O)/monitor/verif/asm-offsets.rkt \ 16 | # $(O)/monitor.ll.rkt \ 17 | 18 | # $(O)/monitors/toymon.ll: $(O)/monitor/main.ll 19 | # $(QUIET_GEN)$(LLVM_LINK) $^ | $(LLVM_OPT) -o $@~ $(LLVM_OPTFLAGS) -S 20 | # $(Q)mv $@~ $@ 21 | 22 | PHONY += verify-monitor 23 | -------------------------------------------------------------------------------- /kernel/bswap.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | uint32_t __bswapsi2(uint32_t u) 4 | { 5 | return (((u & 0xff000000) >> 24) 6 | | ((u & 0x00ff0000) >> 8) 7 | | ((u & 0x0000ff00) << 8) 8 | | ((u & 0x000000ff) << 24)); 9 | } 10 | 11 | uint64_t __bswapdi2(uint64_t u) 12 | { 13 | return (((u & 0xff00000000000000ull) >> 56) 14 | | ((u & 0x00ff000000000000ull) >> 40) 15 | | ((u & 0x0000ff0000000000ull) >> 24) 16 | | ((u & 0x000000ff00000000ull) >> 8) 17 | | ((u & 0x00000000ff000000ull) << 8) 18 | | ((u & 0x0000000000ff0000ull) << 24) 19 | | ((u & 0x000000000000ff00ull) << 40) 20 | | ((u & 0x00000000000000ffull) << 56)); 21 | } 22 | -------------------------------------------------------------------------------- /include/asm/setup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifndef CONFIG_NR_CPUS 6 | #error "CONFIG_NR_CPUS is not defined!" 7 | #endif 8 | 9 | #define NR_CPUS CONFIG_NR_CPUS 10 | 11 | #ifndef CONFIG_DRAM_START 12 | #error "CONFIG_DRAM_START is not defined!" 13 | #endif 14 | 15 | #define DRAM_START UINT64_C(CONFIG_DRAM_START) 16 | 17 | /* 128GB */ 18 | #define KERNEL_VIRTUAL_START UINT64_C(0xffffffe000000000) 19 | #define KERNEL_VIRTUAL_SIZE (-KERNEL_VIRTUAL_START) 20 | 21 | /* 16K */ 22 | #define CPU_STACK_SHIFT 14 23 | #define CPU_STACK_SIZE (1 << CPU_STACK_SHIFT) 24 | 25 | #define XLEN 64 26 | 27 | #define IS_ENABLED(option) (option != 0) 28 | -------------------------------------------------------------------------------- /include/sys/byteorder.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 9 | 10 | #define cpu_to_be16(x) swab16(x) 11 | #define be16_to_cpu(x) swab16(x) 12 | #define cpu_to_be32(x) swab32(x) 13 | #define be32_to_cpu(x) swab32(x) 14 | #define cpu_to_be64(x) swab64(x) 15 | #define be64_to_cpu(x) swab64(x) 16 | #define cpu_to_le16(x) (x) 17 | #define le16_to_cpu(x) (x) 18 | #define cpu_to_le32(x) (x) 19 | #define le32_to_cpu(x) (x) 20 | #define cpu_to_le64(x) (x) 21 | #define le64_to_cpu(x) (x) 22 | 23 | #endif 24 | 25 | static inline uint32_t be32_to_cpup(const be32_t *p) 26 | { 27 | return be32_to_cpu(*(uint32_t *)p); 28 | } 29 | -------------------------------------------------------------------------------- /bios/shutdown.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void htif_shutdown(void); 6 | 7 | void test_shutdown(void) 8 | { 9 | struct device_node *np; 10 | const be32_t *cell; 11 | void __iomem *membase; 12 | 13 | np = of_find_node_by_path("/test"); 14 | if (!np) 15 | return; 16 | 17 | cell = of_get_property(np, "reg", NULL); 18 | if (!cell) 19 | return; 20 | 21 | membase = (void *)(uintptr_t)of_read_number(cell, of_n_addr_cells(np)); 22 | writel(0x5555, membase); 23 | } 24 | 25 | void shutdown(void) 26 | { 27 | htif_shutdown(); 28 | test_shutdown(); 29 | while (1) 30 | wait_for_interrupt(); 31 | } 32 | -------------------------------------------------------------------------------- /serval/serval/unicorn/x86.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (require ffi/unsafe) 4 | 5 | (provide (all-defined-out)) 6 | 7 | (require "const/x86.rkt" 8 | "engine.rkt") 9 | 10 | (define-cstruct _uc_x86_mmr ([selector _uint16] [base _uint64] [limit _uint32] [flags _uint32])) 11 | 12 | (define-cstruct _uc_x86_msr ([rid _uint32] [value _uint64])) 13 | 14 | (struct x86-engine (ptr mode) 15 | #:methods gen:engine 16 | [(define (engine-ptr engine) 17 | (x86-engine-ptr engine)) 18 | (define (engine-reg-enum engine) 19 | _uc_x86_reg) 20 | (define (engine-reg-type engine reg) 21 | (case reg 22 | [(idtr gdtr ldtr tr) _uc_x86_mmr] 23 | [(msr) _uc_x86_msr] 24 | ; FIXME: FP/SEE registers 25 | ; be safe - default to 64-bit 26 | [else _uint64]))]) 27 | -------------------------------------------------------------------------------- /include/io/build_bug.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | /* Force a compilation error if condition is true, but also produce a 6 | result (of value 0 and type size_t), so the expression can be used 7 | e.g. in a structure initializer (or where-ever else comma expressions 8 | aren't permitted). */ 9 | #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) 10 | #define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); })) 11 | 12 | #define BUILD_BUG_ON_MSG(cond, msg) _Static_assert(!(cond), msg) 13 | 14 | #define BUILD_BUG_ON(condition) \ 15 | BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) 16 | 17 | #define BUILD_BUG_ON_NOT_POWER_OF_2(n) \ 18 | BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0)) 19 | -------------------------------------------------------------------------------- /include/sys/console.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | /* Colors */ 7 | #define BRIGHT_RED "\x1b[31;1m" 8 | #define BRIGHT_GREEN "\x1b[32;1m" 9 | #define BRIGHT_YELLOW "\x1b[33;1m" 10 | #define BRIGHT_BLUE "\x1b[34;1m" 11 | #define BRIGHT_MAGENTA "\x1b[35;1m" 12 | #define BRIGHT_CYAN "\x1b[36;1m" 13 | #define BRIGHT_WHITE "\x1b[37;1m" 14 | #define RESET_COLOR "\x1b[0m" 15 | 16 | struct console { 17 | int (*getchar)(struct console *); 18 | void (*putchar)(struct console *, int c); 19 | const char *color; 20 | struct list_head list; 21 | }; 22 | 23 | void register_console(struct console *); 24 | 25 | int console_getchar(void); 26 | void console_putchar(char c); 27 | void console_write(const char *s, size_t n); 28 | -------------------------------------------------------------------------------- /include/asm/pgtable-bits.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | * PTE format: 5 | * | XLEN-1 10 | 9 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 6 | * PFN reserved for SW D A G U X W R V 7 | */ 8 | 9 | #define _PAGE_PRESENT (1 << 0) 10 | #define _PAGE_READ (1 << 1) /* Readable */ 11 | #define _PAGE_WRITE (1 << 2) /* Writable */ 12 | #define _PAGE_EXEC (1 << 3) /* Executable */ 13 | #define _PAGE_USER (1 << 4) /* User */ 14 | #define _PAGE_GLOBAL (1 << 5) /* Global */ 15 | #define _PAGE_ACCESSED (1 << 6) /* Set by hardware on any access */ 16 | #define _PAGE_DIRTY (1 << 7) /* Set by hardware on any write */ 17 | #define _PAGE_SOFT (1 << 8) /* Reserved for software */ 18 | 19 | #define _PAGE_PFN_SHIFT 10 20 | 21 | #define _PAGE_TABLE _PAGE_PRESENT 22 | -------------------------------------------------------------------------------- /include/sys/spinlock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct spinlock { 6 | atomic_flag lock; 7 | }; 8 | 9 | #define DEFINE_SPINLOCK(x) struct spinlock x = { ATOMIC_FLAG_INIT } 10 | 11 | static inline void spinlock_init(struct spinlock *lock) 12 | { 13 | atomic_flag_clear(&lock->lock); 14 | } 15 | 16 | /* return whether it has acquired the lock */ 17 | static inline bool spin_trylock(struct spinlock *lock) 18 | { 19 | return !atomic_flag_test_and_set_explicit(&lock->lock, memory_order_acquire); 20 | } 21 | 22 | static inline void spin_lock(struct spinlock *lock) 23 | { 24 | while (!spin_trylock(lock)) 25 | cpu_relax(); 26 | } 27 | 28 | static inline void spin_unlock(struct spinlock *lock) 29 | { 30 | atomic_flag_clear_explicit(&lock->lock, memory_order_release); 31 | } 32 | -------------------------------------------------------------------------------- /bios/cpu.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void cpu_info(void) 5 | { 6 | unsigned long hartid, vendorid, archid, impid, misa; 7 | char extensions[26 + 1]; 8 | size_t i; 9 | 10 | hartid = csr_read(mhartid); 11 | vendorid = csr_read(mvendorid); 12 | archid = csr_read(marchid); 13 | impid = csr_read(mimpid); 14 | misa = csr_read(misa); 15 | 16 | for (i = 0; i < 26; ++i) 17 | extensions[i] = (misa & (1 << i)) ? ('A' + i) : '-'; 18 | extensions[26] = 0; 19 | 20 | pr_info("mhartid = %lu\n" 21 | "mvendorid = 0x%016lx\n" 22 | "marchid = 0x%016lx\n" 23 | "mimpid = 0x%016lx\n" 24 | "misa = 0x%016lx\n" 25 | "extensions = %s\n\n", 26 | hartid, vendorid, archid, impid, misa, extensions); 27 | } 28 | -------------------------------------------------------------------------------- /include/sys/bug.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #if IS_ENABLED(CONFIG_VERIFICATION) 10 | #define BUG() do { unreachable(); } while (0) 11 | #else /* ! IS_ENABLED(CONFIG_VERIFICATION) */ 12 | #define BUG() do { \ 13 | panic("BUG: failure at %s:%d/%s()\n", __FILE__, __LINE__, __func__); \ 14 | } while (0) 15 | #endif /* IS_ENABLED(CONFIG_VERIFICATION) */ 16 | 17 | #define BUG_ON(condition) do { if (condition) BUG(); } while (0) 18 | 19 | struct pt_regs; 20 | 21 | noreturn void die(struct pt_regs *regs, const char *str); 22 | void show_regs(struct pt_regs *regs); 23 | void show_gp_regs(struct pt_regs *regs); 24 | void show_sys_regs(void); 25 | 26 | __printf(1, 2) noreturn 27 | void panic(const char *fmt, ...); 28 | 29 | noreturn void shutdown(void); 30 | 31 | void dump_stack(void); 32 | -------------------------------------------------------------------------------- /include/asm/csr_bits/isa.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /* Atomic extension */ 6 | #define MISA_A BIT_64(0) 7 | 8 | /* Compressed extension */ 9 | #define MISA_C BIT_64(2) 10 | 11 | /* Double-precision floating-point extension */ 12 | #define MISA_D BIT_64(3) 13 | 14 | /* RV32E base ISA */ 15 | #define MISA_E BIT_64(4) 16 | 17 | /* Single-precision floating-point extension */ 18 | #define MISA_F BIT_64(5) 19 | 20 | /* RV32I / 64I / 128I base ISA */ 21 | #define MISA_I BIT_64(8) 22 | 23 | /* Integer Multiply / Divide extension */ 24 | #define MISA_M BIT_64(12) 25 | 26 | /* User-level interrupts supported */ 27 | #define MISA_N BIT_64(13) 28 | 29 | /* Supervisor mode implemented */ 30 | #define MISA_S BIT_64(18) 31 | 32 | /* User mode implemented */ 33 | #define MISA_U BIT_64(20) 34 | 35 | /* Non-standard extensions present */ 36 | #define MISA_X BIT_64(23) 37 | -------------------------------------------------------------------------------- /kernel/sbi_console.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static int sbi_getchar(struct console *con) 6 | { 7 | return sbi_console_getchar(); 8 | } 9 | 10 | static void sbi_putchar(struct console *con, int c) 11 | { 12 | size_t i; 13 | 14 | if (con->color) 15 | for (i = 0; i < strlen(con->color); ++i) 16 | sbi_console_putchar((uint8_t)con->color[i]); 17 | 18 | sbi_console_putchar((uint8_t)c); 19 | 20 | if (con->color) 21 | for (i = 0; i < strlen(RESET_COLOR); ++i) 22 | sbi_console_putchar((uint8_t)RESET_COLOR[i]); 23 | 24 | } 25 | 26 | static struct console con = { 27 | .getchar = sbi_getchar, 28 | .putchar = sbi_putchar, 29 | }; 30 | 31 | void sbi_console_init(const char *color) 32 | { 33 | con.color = color; 34 | register_console(&con); 35 | } 36 | -------------------------------------------------------------------------------- /monitor/monitor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | unsigned long current_user; 12 | 13 | long dictionary[MAXUSER]; 14 | 15 | void init_dict(void) 16 | { 17 | current_user = 0; 18 | for (int i = 0; i < MAXUSER; i++) { 19 | dictionary[i] = 0; 20 | } 21 | } 22 | 23 | long sys_dict_get(void) 24 | { 25 | if (current_user < MAXUSER) 26 | return dictionary[current_user]; 27 | 28 | return -1; 29 | } 30 | 31 | long sys_dict_set(long value) 32 | { 33 | if (current_user < MAXUSER) { 34 | dictionary[current_user] = value; 35 | return 0; 36 | } 37 | 38 | return -1; 39 | } 40 | 41 | long sys_change_user(long newuser) 42 | { 43 | current_user = newuser; 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /include/asm/csr_bits/edeleg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define EDEL_INST_MISALIGNED BIT_64(EXC_INST_MISALIGNED) 7 | #define EDEL_INST_ACCESS BIT_64(EXC_INST_ACCESS) 8 | #define EDEL_ILLEGAL_INST BIT_64(EXC_ILLEGAL_INST) 9 | #define EDEL_BREAKPOINT BIT_64(EXC_BREAKPOINT) 10 | #define EDEL_LOAD_MISALIGNED BIT_64(EXC_LOAD_MISALIGNED) 11 | #define EDEL_LOAD_ACCESS BIT_64(EXC_LOAD_ACCESS) 12 | #define EDEL_STORE_MISALIGNED BIT_64(EXC_STORE_MISALIGNED) 13 | #define EDEL_STORE_ACCESS BIT_64(EXC_STORE_ACCESS) 14 | #define EDEL_ECALL_U BIT_64(EXC_ECALL_U) 15 | #define EDEL_ECALL_S BIT_64(EXC_ECALL_S) 16 | #define EDEL_ECALL_M BIT_64(EXC_ECALL_M) 17 | #define EDEL_INST_PAGE_FAULT BIT_64(EXC_INST_PAGE_FAULT) 18 | #define EDEL_LOAD_PAGE_FAULT BIT_64(EXC_LOAD_PAGE_FAULT) 19 | #define EDEL_STORE_PAGE_FAULT BIT_64(EXC_STORE_PAGE_FAULT) 20 | -------------------------------------------------------------------------------- /serval/serval/llvm/capi/irreader.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (require ffi/unsafe 4 | ffi/unsafe/alloc 5 | "core.rkt") 6 | 7 | (provide LLVMParseIRInContext) 8 | 9 | ; allocate a new _LLVMMemoryBufferRef, which is consumed by this function 10 | (define-llvm LLVMParseIRInContext 11 | (_fun [_LLVMContextRef = (LLVMGetGlobalContext)] 12 | [data : _?] 13 | [_LLVMMemoryBufferRef = (LLVMCreateMemoryBufferWithMemoryRangeCopy data "" 0)] 14 | [m : (_ptr o (_or-null _LLVMModuleRef))] 15 | [msg : (_ptr o _pointer)] 16 | -> [r : _LLVMBool] 17 | -> (begin (check r msg) m)) 18 | #:wrap (allocator LLVMDisposeModule)) 19 | 20 | ; no allocator here 21 | (define-llvm LLVMCreateMemoryBufferWithMemoryRangeCopy 22 | (_fun [data : _bytes] 23 | [length : _size = (bytes-length data)] 24 | [buffer-name : _string] 25 | [requires-null-terminator? : _LLVMBool] 26 | -> _LLVMMemoryBufferRef)) 27 | -------------------------------------------------------------------------------- /include/sys/bitops/fls64.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | /** 8 | * fls64 - find last set bit in a 64-bit word 9 | * @x: the word to search 10 | * 11 | * This is defined in a similar way as the libc and compiler builtin 12 | * ffsll, but returns the position of the most significant set bit. 13 | * 14 | * fls64(value) returns 0 if value is 0 or the position of the last 15 | * set bit if value is nonzero. The last (most significant) bit is 16 | * at position 64. 17 | */ 18 | #if BITS_PER_LONG == 32 19 | static __always_inline int fls64(uint64_t x) 20 | { 21 | uint32_t h = x >> 32; 22 | if (h) 23 | return fls(h) + 32; 24 | return fls(x); 25 | } 26 | #elif BITS_PER_LONG == 64 27 | static __always_inline int fls64(uint64_t x) 28 | { 29 | if (x == 0) 30 | return 0; 31 | return __fls(x) + 1; 32 | } 33 | #else 34 | #error BITS_PER_LONG not 32 or 64 35 | #endif 36 | -------------------------------------------------------------------------------- /include/asm/word-at-a-time.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct word_at_a_time { 7 | const unsigned long one_bits, high_bits; 8 | }; 9 | 10 | #define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } 11 | 12 | static inline unsigned long has_zero(unsigned long val, 13 | unsigned long *bits, const struct word_at_a_time *c) 14 | { 15 | unsigned long mask = ((val - c->one_bits) & ~val) & c->high_bits; 16 | *bits = mask; 17 | return mask; 18 | } 19 | 20 | static inline unsigned long prep_zero_mask(unsigned long val, 21 | unsigned long bits, const struct word_at_a_time *c) 22 | { 23 | return bits; 24 | } 25 | 26 | static inline unsigned long create_zero_mask(unsigned long bits) 27 | { 28 | bits = (bits - 1) & ~bits; 29 | return bits >> 7; 30 | } 31 | 32 | static inline unsigned long find_zero(unsigned long mask) 33 | { 34 | return fls64(mask) >> 3; 35 | } 36 | 37 | /* The mask we created is directly usable as a bytemask */ 38 | #define zero_bytemask(mask) (mask) 39 | -------------------------------------------------------------------------------- /include/sys/pfn.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | typedef struct { 8 | uint64_t val; 9 | } pfn_t; 10 | 11 | #define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) 12 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) 13 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) 14 | #define PFN_PHYS(x) ((phys_addr_t)(x) << PAGE_SHIFT) 15 | #define PHYS_PFN(x) ((unsigned long)((x) >> PAGE_SHIFT)) 16 | 17 | static inline pfn_t pfn_to_pfn_t(unsigned long pfn) 18 | { 19 | pfn_t pfn_t = { .val = pfn }; 20 | 21 | return pfn_t; 22 | } 23 | 24 | static inline unsigned long pfn_t_to_pfn(pfn_t pfn) 25 | { 26 | return pfn.val; 27 | } 28 | 29 | static inline phys_addr_t pfn_t_to_phys(pfn_t pfn) 30 | { 31 | return PFN_PHYS(pfn_t_to_pfn(pfn)); 32 | } 33 | 34 | static inline void *pfn_t_to_virt(pfn_t pfn) 35 | { 36 | return __va(pfn_t_to_phys(pfn)); 37 | } 38 | 39 | #define virt_to_pfn(vaddr) (__pa(vaddr) >> PAGE_SHIFT) 40 | #define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) 41 | -------------------------------------------------------------------------------- /include/sys/bitops/__ffs.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | /** 8 | * __ffs - find first bit in word. 9 | * @word: The word to search 10 | * 11 | * Undefined if no bit exists, so code should check against 0 first. 12 | */ 13 | static __always_inline unsigned long __ffs(unsigned long word) 14 | { 15 | int num = 0; 16 | 17 | #if BITS_PER_LONG == 64 18 | if ((word & 0xffffffff) == 0) { 19 | num += 32; 20 | word >>= 32; 21 | } 22 | #endif 23 | if ((word & 0xffff) == 0) { 24 | num += 16; 25 | word >>= 16; 26 | } 27 | if ((word & 0xff) == 0) { 28 | num += 8; 29 | word >>= 8; 30 | } 31 | if ((word & 0xf) == 0) { 32 | num += 4; 33 | word >>= 4; 34 | } 35 | if ((word & 0x3) == 0) { 36 | num += 2; 37 | word >>= 2; 38 | } 39 | if ((word & 0x1) == 0) 40 | num += 1; 41 | return num; 42 | } 43 | -------------------------------------------------------------------------------- /serval/serval/riscv/shims.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette 2 | 3 | (require "base.rkt" 4 | (prefix-in core: "../lib/core.rkt")) 5 | 6 | (provide (all-defined-out)) 7 | 8 | ; void *memset(void *p, int c, size_t len) 9 | (define (memset-shim cpu) 10 | (define ptr (gpr-ref cpu 'a0)) 11 | (define c (extract 7 0 (gpr-ref cpu 'a1))) 12 | (define len (gpr-ref cpu 'a2)) 13 | 14 | (define mregion (core:guess-mregion-from-addr (cpu-mregions cpu) ptr (bv 0 12) #:dbg current-pc-debug)) 15 | (core:bug-on (eq? mregion #f) #:msg "memset-shim: failed to guess mregion" #:dbg current-pc-debug) 16 | 17 | (core:bug-on (not (core:mregion-inbounds? mregion ptr len)) 18 | #:dbg current-pc-debug #:msg "memset-shim: address out of range") 19 | 20 | (define offset (bvsub ptr (bv (core:mregion-start mregion) (XLEN)))) 21 | 22 | (when (not (bveq len (bv 0 (XLEN)))) 23 | (core:mblock-memset! (core:mregion-block mregion) c offset len #:dbg current-pc-debug)) 24 | 25 | ; Fake a 'ret' instruction to return control to calling function 26 | (set-cpu-pc! cpu (gpr-ref cpu 'x1)) 27 | (havoc-caller-saved! cpu) 28 | (gpr-set! cpu 'a0 ptr)) 29 | -------------------------------------------------------------------------------- /kernel/time.c: -------------------------------------------------------------------------------- 1 | #define pr_fmt(fmt) __MODULE__ ": " fmt 2 | #include 3 | #include 4 | 5 | static unsigned long cpu_khz; 6 | static cycles_t boot_cycles; 7 | 8 | useconds_t uptime(void) 9 | { 10 | if (!cpu_khz) 11 | return 0; 12 | 13 | /* 14 | * Subtract boot_cycles as QEMU returns the host CPU's 15 | * cycles rather than starting from 0. Also the value 16 | * from cpu_khz doesn't really make sense on QEMU, but 17 | * it's good enough for debugging. 18 | */ 19 | return (get_cycles() - boot_cycles) * 1000 / cpu_khz; 20 | } 21 | 22 | void time_init(void) 23 | { 24 | struct device_node *cpu; 25 | uint32_t prop; 26 | 27 | boot_cycles = get_cycles(); 28 | 29 | cpu = of_find_node_by_path("/cpus/cpu"); 30 | if (!cpu) { 31 | pr_warn("no 'cpu' in DTS\n"); 32 | return; 33 | } 34 | 35 | if (of_property_read_u32(cpu, "clock-frequency", &prop)) { 36 | pr_warn("no 'clock-frequency' in DTS\n"); 37 | return; 38 | } 39 | 40 | cpu_khz = prop / 1000; 41 | } 42 | -------------------------------------------------------------------------------- /serval/serval/llvm/capi/target.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (require ffi/unsafe 4 | ffi/unsafe/alloc 5 | "core.rkt") 6 | 7 | (provide (all-defined-out)) 8 | 9 | (define _LLVMByteOrdering 10 | (_enum 11 | '(big = 0 12 | little))) 13 | 14 | (struct _data-layout (pointer module) #:transparent) 15 | 16 | (define _LLVMTargetDataRef 17 | (make-ctype _pointer 18 | _data-layout-pointer 19 | #f)) 20 | 21 | (define-llvm LLVMGetModuleDataLayout 22 | (_fun (m : _LLVMModuleRef) 23 | -> (cptr : _pointer) 24 | -> (_data-layout cptr m))) 25 | 26 | (define-llvm LLVMCopyStringRepOfTargetData 27 | (_fun _LLVMTargetDataRef 28 | -> _LLVMMessageRef)) 29 | 30 | (define-llvm LLVMByteOrder 31 | (_fun _LLVMTargetDataRef 32 | -> _LLVMByteOrdering)) 33 | 34 | (define-llvm LLVMPointerSize 35 | (_fun _LLVMTargetDataRef 36 | -> _uint)) 37 | 38 | (define-llvm LLVMABISizeOfType 39 | (_fun _LLVMTargetDataRef 40 | _LLVMTypeRef 41 | -> _ullong)) 42 | 43 | (define-llvm LLVMOffsetOfElement 44 | (_fun _LLVMTargetDataRef 45 | _LLVMTypeRef 46 | _uint 47 | -> _ullong)) 48 | -------------------------------------------------------------------------------- /include/io/const.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #ifndef __ASSEMBLER__ 6 | 7 | #include 8 | 9 | #define __AC(X,Y) (X##Y) 10 | #define _AC(X,Y) __AC(X,Y) 11 | #define _AT(T,X) ((T)(X)) 12 | 13 | typedef uint16_t le16_t; 14 | typedef uint16_t be16_t; 15 | typedef uint32_t le32_t; 16 | typedef uint32_t be32_t; 17 | typedef uint64_t le64_t; 18 | typedef uint64_t be64_t; 19 | 20 | #else /* !__ASSEMBLER__ */ 21 | 22 | #define _AC(X,Y) X 23 | #define _AT(T,X) X 24 | 25 | #define UINT32_C(x) x 26 | #define UINT64_C(x) x 27 | 28 | #endif /* __ASSEMBLER__ */ 29 | 30 | #define BIT(nr) (_AC(1, UL) << (nr)) 31 | #define BIT_32(nr) (UINT32_C(1) << (nr)) 32 | #define BIT_64(nr) (UINT64_C(1) << (nr)) 33 | 34 | /* 35 | * Create a contiguous bitmask starting at bit position @l and 36 | * ending at * position @h. For example, GENMASK_64(39, 21) gives 37 | * the 64-bit vector 0x000000ffffe00000. 38 | */ 39 | #define GENMASK_32(h, l) \ 40 | (((~UINT32_C(0)) - BIT_32(l) + 1) & (~UINT32_C(0) >> (31 - (h)))) 41 | 42 | #define GENMASK_64(h, l) \ 43 | (((~UINT64_C(0)) - BIT_64(l) + 1) & (~UINT64_C(0) >> (63 - (h)))) 44 | -------------------------------------------------------------------------------- /include/asm/ptrace.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define REG_FMT "%016lx" 6 | 7 | struct pt_regs { 8 | unsigned long ra; 9 | unsigned long sp; 10 | unsigned long gp; 11 | unsigned long tp; 12 | unsigned long t0; 13 | unsigned long t1; 14 | unsigned long t2; 15 | unsigned long s0; 16 | unsigned long s1; 17 | unsigned long a0; 18 | unsigned long a1; 19 | unsigned long a2; 20 | unsigned long a3; 21 | unsigned long a4; 22 | unsigned long a5; 23 | unsigned long a6; 24 | unsigned long a7; 25 | unsigned long s2; 26 | unsigned long s3; 27 | unsigned long s4; 28 | unsigned long s5; 29 | unsigned long s6; 30 | unsigned long s7; 31 | unsigned long s8; 32 | unsigned long s9; 33 | unsigned long s10; 34 | unsigned long s11; 35 | unsigned long t3; 36 | unsigned long t4; 37 | unsigned long t5; 38 | unsigned long t6; 39 | }; 40 | 41 | struct pt_regs *current_pt_regs(void); 42 | 43 | void copy_pt_regs(struct pt_regs *dst, struct pt_regs *src); 44 | 45 | noreturn void mret_with_regs(struct pt_regs *regs); 46 | -------------------------------------------------------------------------------- /include/sys/bitops/__fls.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | /** 8 | * __fls - find last (most-significant) set bit in a long word 9 | * @word: the word to search 10 | * 11 | * Undefined if no set bit exists, so code should check against 0 first. 12 | */ 13 | static __always_inline unsigned long __fls(unsigned long word) 14 | { 15 | int num = BITS_PER_LONG - 1; 16 | 17 | #if BITS_PER_LONG == 64 18 | if (!(word & (~0ul << 32))) { 19 | num -= 32; 20 | word <<= 32; 21 | } 22 | #endif 23 | if (!(word & (~0ul << (BITS_PER_LONG-16)))) { 24 | num -= 16; 25 | word <<= 16; 26 | } 27 | if (!(word & (~0ul << (BITS_PER_LONG-8)))) { 28 | num -= 8; 29 | word <<= 8; 30 | } 31 | if (!(word & (~0ul << (BITS_PER_LONG-4)))) { 32 | num -= 4; 33 | word <<= 4; 34 | } 35 | if (!(word & (~0ul << (BITS_PER_LONG-2)))) { 36 | num -= 2; 37 | word <<= 2; 38 | } 39 | if (!(word & (~0ul << (BITS_PER_LONG-1)))) 40 | num -= 1; 41 | return num; 42 | } 43 | -------------------------------------------------------------------------------- /kernel/ptrace.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | __weak struct pt_regs *current_pt_regs(void) 6 | { 7 | return (void *)(uintptr_t)csr_read(sscratch); 8 | } 9 | 10 | void copy_pt_regs(struct pt_regs *dst, struct pt_regs *src) 11 | { 12 | dst->ra = src->ra; 13 | dst->sp = src->sp; 14 | dst->gp = src->gp; 15 | dst->tp = src->tp; 16 | dst->t0 = src->t0; 17 | dst->t1 = src->t1; 18 | dst->t2 = src->t2; 19 | dst->s0 = src->s0; 20 | dst->s1 = src->s1; 21 | dst->a0 = src->a0; 22 | dst->a1 = src->a1; 23 | dst->a2 = src->a2; 24 | dst->a3 = src->a3; 25 | dst->a4 = src->a4; 26 | dst->a5 = src->a5; 27 | dst->a6 = src->a6; 28 | dst->a7 = src->a7; 29 | dst->s2 = src->s2; 30 | dst->s3 = src->s3; 31 | dst->s4 = src->s4; 32 | dst->s5 = src->s5; 33 | dst->s6 = src->s6; 34 | dst->s7 = src->s7; 35 | dst->s8 = src->s8; 36 | dst->s9 = src->s9; 37 | dst->s10 = src->s10; 38 | dst->s11 = src->s11; 39 | dst->t3 = src->t3; 40 | dst->t4 = src->t4; 41 | dst->t5 = src->t5; 42 | dst->t6 = src->t6; 43 | } 44 | -------------------------------------------------------------------------------- /monitor/kernel/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define CHECK(e) BUG_ON((e) != 0) 12 | 13 | extern long sys_dict_get(void); 14 | extern long sys_dict_set(long); 15 | extern long sys_change_user(long); 16 | 17 | noreturn void main(unsigned int hartid, phys_addr_t dtb) 18 | { 19 | sbi_console_init(BRIGHT_MAGENTA); 20 | pr_info("Hello from kernel!\n"); 21 | 22 | pr_info("change_user(0)\n"); 23 | CHECK(sys_change_user(0)); 24 | pr_info("dict_set(5)\n"); 25 | CHECK(sys_dict_set(5)); 26 | pr_info("dict_get() -> %ld\n", sys_dict_get()); 27 | 28 | pr_info("change_user(3)\n"); 29 | CHECK(sys_change_user(3)); 30 | pr_info("dict_set(2)\n"); 31 | CHECK(sys_dict_set(2)); 32 | pr_info("dict_get -> %ld\n", sys_dict_get()); 33 | 34 | pr_info("change_user(0)\n"); 35 | CHECK(sys_change_user(0)); 36 | pr_info("dict_get -> %ld\n", sys_dict_get()); 37 | 38 | sbi_shutdown(); 39 | for (;;) 40 | wait_for_interrupt(); 41 | } 42 | -------------------------------------------------------------------------------- /include/io/linkage.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #ifdef __ASSEMBLER__ 6 | 7 | #define __ALIGN .balign 4 8 | #define __ALIGN_STR ".balign 4" 9 | 10 | #define ALIGN __ALIGN 11 | 12 | /* Some toolchains use other characters (e.g. '`') to mark new line in macro */ 13 | #ifndef ASM_NL 14 | #define ASM_NL ; 15 | #endif 16 | 17 | #define SYSCALL_ALIAS(alias, name) \ 18 | .globl alias; \ 19 | .set alias, name 20 | 21 | #define ENTRY(name) \ 22 | .globl name ASM_NL \ 23 | ALIGN ASM_NL \ 24 | name: 25 | 26 | #define END(name) \ 27 | .size name, .-name 28 | 29 | /* If symbol 'name' is treated as a subroutine (gets called, and returns) 30 | * then please use ENDPROC to mark 'name' as STT_FUNC for the benefit of 31 | * static analysis tools such as stack depth analyzer. 32 | */ 33 | #define ENDPROC(name) \ 34 | .type name, @function ASM_NL \ 35 | END(name) 36 | 37 | #define GLOBAL(name) \ 38 | .globl name; \ 39 | name: 40 | 41 | #else /* !__ASSEMBLER__ */ 42 | 43 | #ifdef __cplusplus 44 | #define CPP_ASMLINKAGE extern "C" 45 | #else 46 | #define CPP_ASMLINKAGE 47 | #endif 48 | 49 | #ifndef asmlinkage 50 | #define asmlinkage CPP_ASMLINKAGE 51 | #endif 52 | 53 | #endif /* __ASSEMBLER__ */ 54 | -------------------------------------------------------------------------------- /serval/serval/llvm/lang.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | ;(require ffi/unsafe 4 | ; ffi/unsafe/alloc 5 | ; racket/port 6 | ; racket/sequence 7 | ; syntax/strip-context 8 | ; "capi/core.rkt" 9 | ; "util.rkt") 10 | 11 | ; (provide #%module-begin #%datum #%top-interaction #%app define quote) 12 | 13 | ; (define (llvm-read-syntax path port) 14 | ; (define m (bytes->module (context) (port->bytes port))) 15 | 16 | ; (define fns (for/list ([f (in-functions m)]) (read-function f))) 17 | 18 | ; (strip-context 19 | ; (quasisyntax 20 | ; (module anything serval/llvm/lang 21 | ; #,@fns 22 | ; )))) 23 | 24 | ; (provide (rename-out [llvm-read-syntax read-syntax])) 25 | 26 | ; (define (read-function f) 27 | ; (define bbs (for/list ([bb (in-basic-blocks f)]) (read-basic-block bb))) 28 | ; (with-syntax ([fnname (string->symbol (value-name f))]) 29 | ; (quasisyntax 30 | ; (define (fnname) '#,@bbs)))) 31 | 32 | ; (define (read-basic-block bb) 33 | ; (define insns (for/list ([insn (in-instructions bb)]) (read-instruction insn))) 34 | 35 | ; (with-syntax ([name (string->symbol (value->string bb))]) 36 | ; (quasisyntax 37 | ; (name #,@insns)))) 38 | 39 | ; (define (read-instruction insn) 40 | ; (with-syntax ([s (value->string insn)]) 41 | ; (quasisyntax 42 | ; s))) 43 | -------------------------------------------------------------------------------- /include/asm/csr_bits/cause.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define INTR_BIT BIT_64(XLEN - 1) 7 | 8 | #define INTR_SOFT_U (INTR_BIT | 0) 9 | #define INTR_SOFT_S (INTR_BIT | 1) 10 | /* RESERVED (INTR_BIT | 2) */ 11 | #define INTR_SOFT_M (INTR_BIT | 3) 12 | #define INTR_TIMER_U (INTR_BIT | 4) 13 | #define INTR_TIMER_S (INTR_BIT | 5) 14 | /* RESERVED (INTR_BIT | 6) */ 15 | #define INTR_TIMER_M (INTR_BIT | 7) 16 | #define INTR_EXT_U (INTR_BIT | 8) 17 | #define INTR_EXT_S (INTR_BIT | 9) 18 | /* RESERVED (INTR_BIT | 10) */ 19 | #define INTR_EXT_M (INTR_BIT | 11) 20 | 21 | #define EXC_INST_MISALIGNED 0 22 | #define EXC_INST_ACCESS 1 23 | #define EXC_ILLEGAL_INST 2 24 | #define EXC_BREAKPOINT 3 25 | #define EXC_LOAD_MISALIGNED 4 26 | #define EXC_LOAD_ACCESS 5 27 | #define EXC_STORE_MISALIGNED 6 28 | #define EXC_STORE_ACCESS 7 29 | #define EXC_ECALL_U 8 30 | #define EXC_ECALL_S 9 31 | /* RESERVED 10 */ 32 | #define EXC_ECALL_M 11 33 | #define EXC_INST_PAGE_FAULT 12 34 | #define EXC_LOAD_PAGE_FAULT 13 35 | /* RESERVED 14 */ 36 | #define EXC_STORE_PAGE_FAULT 15 37 | -------------------------------------------------------------------------------- /bios/htif.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define HTIF_DEV_SYSCALL 0 5 | #define HTIF_DEV_CONSOLE 1 6 | 7 | #define HTIF_CMD_WRITE 1 8 | 9 | volatile uint64_t tohost __section(.htif); 10 | volatile uint64_t fromhost __section(.htif); 11 | 12 | static bool has_htif; 13 | 14 | static void wait(void) 15 | { 16 | while (tohost) { 17 | uint64_t val = fromhost; 18 | 19 | if (!val) 20 | continue; 21 | fromhost = 0; 22 | } 23 | } 24 | 25 | static void write_tohost(uint64_t dev, uint64_t cmd, uint64_t data) 26 | { 27 | wait(); 28 | tohost = (dev << 56) | (cmd << 48) | data; 29 | } 30 | 31 | static void htif_putchar(struct console *con, int c) 32 | { 33 | write_tohost(HTIF_DEV_CONSOLE, HTIF_CMD_WRITE, (uint8_t)c); 34 | } 35 | 36 | static struct console con = { 37 | .putchar = htif_putchar, 38 | }; 39 | 40 | void htif_init(void) 41 | { 42 | has_htif = !!of_find_node_by_path("/htif"); 43 | if (!has_htif) 44 | return; 45 | register_console(&con); 46 | } 47 | 48 | void htif_shutdown(void) 49 | { 50 | if (!has_htif) 51 | return; 52 | 53 | /* (payload & 1) means exit, with value (payload >> 1) */ 54 | while (1) 55 | write_tohost(HTIF_DEV_SYSCALL, 0, 1); 56 | } 57 | -------------------------------------------------------------------------------- /include/sys/swab.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #if 1 8 | 9 | #define swab16 __builtin_bswap16 10 | #define swab32 __builtin_bswap32 11 | #define swab64 __builtin_bswap64 12 | 13 | #else 14 | 15 | /* 16 | * There is no need to provide implementations for these calls. 17 | * LLVM rewrites the following swap* to llvm.bswap.i* anyway. 18 | */ 19 | 20 | static inline uint16_t swab16(uint16_t x) 21 | { 22 | return ((x & UINT16_C(0x00ff)) << 8) | 23 | ((x & UINT16_C(0xff00)) >> 8); 24 | } 25 | 26 | static inline uint32_t swab32(uint32_t x) 27 | { 28 | return ((x & UINT32_C(0x000000ff)) << 24) | 29 | ((x & UINT32_C(0x0000ff00)) << 8) | 30 | ((x & UINT32_C(0x00ff0000)) >> 8) | 31 | ((x & UINT32_C(0xff000000)) >> 24); 32 | } 33 | 34 | static inline uint64_t swab64(uint64_t x) 35 | { 36 | return ((x & UINT64_C(0x00000000000000ff)) << 56) | 37 | ((x & UINT64_C(0x000000000000ff00)) << 40) | 38 | ((x & UINT64_C(0x0000000000ff0000)) << 24) | 39 | ((x & UINT64_C(0x00000000ff000000)) << 8) | 40 | ((x & UINT64_C(0x000000ff00000000)) >> 8) | 41 | ((x & UINT64_C(0x0000ff0000000000)) >> 24) | 42 | ((x & UINT64_C(0x00ff000000000000)) >> 40) | 43 | ((x & UINT64_C(0xff00000000000000)) >> 56); 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/asm/pmp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define pmpaddr_read(reg) (csr_read(reg) << 2) 8 | #define pmpaddr_write(reg, val) csr_write(reg, ((val) >> 2)) 9 | 10 | enum pmpcfg { 11 | pmp0cfg = 0, 12 | pmp1cfg, 13 | pmp2cfg, 14 | pmp3cfg, 15 | pmp4cfg, 16 | pmp5cfg, 17 | pmp6cfg, 18 | pmp7cfg, 19 | /* pmp8cfg, 20 | pmp9cfg, 21 | pmp10cfg, 22 | pmp11cfg, 23 | pmp12cfg, 24 | pmp13cfg, 25 | pmp14cfg, 26 | pmp15cfg, */ 27 | NR_PMP_ENTRIES, 28 | }; 29 | 30 | static inline unsigned long pmpcfg_read(enum pmpcfg nr) 31 | { 32 | unsigned long r, shift = (nr % 8) * 8; 33 | 34 | r = (nr < 8) ? csr_read(pmpcfg0) : csr_read(pmpcfg2); 35 | return (r >> shift) & 0xff; 36 | } 37 | 38 | static inline void pmpcfg_write(enum pmpcfg nr, unsigned long value) 39 | { 40 | unsigned long shift = (nr % 8) * 8; 41 | unsigned long mask = 0xffL << shift; 42 | 43 | if (nr < 8) { 44 | csr_clear(pmpcfg0, mask); 45 | csr_set(pmpcfg0, value << shift); 46 | } else { 47 | csr_clear(pmpcfg2, mask); 48 | csr_set(pmpcfg2, value << shift); 49 | } 50 | 51 | if (pmpcfg_read(nr) != value) 52 | pr_err("pmpcfg_write: %d 0x%lx\n", nr, value); 53 | } 54 | -------------------------------------------------------------------------------- /include/sys/ioport.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * ioport.h Definitions of routines for detecting, reserving and 4 | * allocating system resources. 5 | * 6 | * Authors: Linus Torvalds 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | struct resource { 14 | resource_size_t start; 15 | resource_size_t end; 16 | unsigned long flags; 17 | }; 18 | 19 | #define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */ 20 | #define IORESOURCE_IO 0x00000100 /* PCI/ISA I/O ports */ 21 | #define IORESOURCE_MEM 0x00000200 22 | #define IORESOURCE_IRQ 0x00000400 23 | #define IORESOURCE_DMA 0x00000800 24 | #define IORESOURCE_BUS 0x00001000 25 | 26 | #define IORESOURCE_PREFETCH 0x00002000 /* No side effects */ 27 | 28 | #define IORESOURCE_SIZEALIGN 0x00040000 /* size indicates alignment */ 29 | 30 | #define IORESOURCE_MEM_64 0x00100000 31 | #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ 32 | 33 | #define IORESOURCE_DISABLED 0x10000000 34 | #define IORESOURCE_UNSET 0x20000000 /* No address assigned yet */ 35 | 36 | static inline resource_size_t resource_size(const struct resource *res) 37 | { 38 | return res->end - res->start + 1; 39 | } 40 | 41 | static inline unsigned long resource_type(const struct resource *res) 42 | { 43 | return res->flags & IORESOURCE_TYPE_BITS; 44 | } 45 | -------------------------------------------------------------------------------- /serval/serval/lang/nm.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (require 4 | racket/list 5 | racket/match 6 | racket/port 7 | racket/string 8 | syntax/strip-context) 9 | 10 | (provide (rename-out [literal-read read] 11 | [literal-read-syntax read-syntax])) 12 | 13 | (define (literal-read in) 14 | (syntax->datum 15 | (literal-read-syntax #f in))) 16 | 17 | (define (read-syms in) 18 | (datum->syntax #f 19 | (for/list ([l (filter non-empty-string? (port->lines in))]) 20 | (match l 21 | ; Two addrs 22 | [(pregexp #px"^([0-9a-f]+) ([0-9a-f]+) (\\S) (\\S+)$" (list _ begin size type name)) 23 | (with-syntax ([begin (string->number begin 16)] 24 | [end (+ (string->number begin 16) 25 | (string->number size 16))] 26 | [type (string->symbol type)] 27 | [name (string->symbol name)]) 28 | #'(begin end type name))] 29 | 30 | ; No size 31 | [(pregexp #px"^([0-9a-f]+) (\\S) (\\S+)$" (list _ begin type name)) 32 | (with-syntax ([begin (string->number begin 16)] 33 | [type (string->symbol type)] 34 | [name (string->symbol name)]) 35 | #'(begin begin type name))])))) 36 | 37 | 38 | (define (literal-read-syntax src in) 39 | (strip-context 40 | #`(module anything racket/base 41 | (provide symbols) 42 | (define symbols '#,(read-syms in))))) 43 | -------------------------------------------------------------------------------- /config.mk: -------------------------------------------------------------------------------- 1 | # CPU architecture 2 | ARCH = riscv64 3 | 4 | # output directory 5 | O = o.$(ARCH) 6 | 7 | # Number of host processors 8 | NPROC = $(shell nproc 2> /dev/null) 9 | ifeq ($(NPROC),) 10 | NPROC = 4 11 | endif 12 | 13 | # optimization level 14 | OLEVEL = 0 15 | 16 | # number of CPUs used in simulation 17 | CONFIG_NR_CPUS = 5 18 | 19 | # CPU to boot up initially 20 | CONFIG_BOOT_CPU = 1 21 | 22 | # DRAM start address 23 | CONFIG_DRAM_START = 0x80000000 24 | 25 | # verification build (0 - off; 1 - on) 26 | CONFIG_VERIFICATION = 1 27 | 28 | # configuration used by QEMU for simulation 29 | QEMU = qemu-system-$(ARCH) 30 | QEMU_MACHINE = virt 31 | QEMU_BIOS = none 32 | QEMU_OPTS = -smp cpus=$(CONFIG_NR_CPUS) -nographic -machine $(QEMU_MACHINE) -bios $(QEMU_BIOS) 33 | QEMU_USER = qemu-$(ARCH) 34 | QEMU_DEBUG = -S -s 35 | 36 | # GDB configuration 37 | GDB_OPTS = -ex 'target remote :1234' 38 | 39 | # configuration used by Spike for simulation 40 | SPIKE = spike 41 | SPIKE_OPTS = -p$(CONFIG_NR_CPUS) 42 | 43 | # Racket configuration 44 | RACO_JOBS = $(NPROC) 45 | RACO_TIMEOUT = 1200 46 | RACO_TEST = raco test --check-stderr --table --timeout $(RACO_TIMEOUT) --jobs $(RACO_JOBS) 47 | 48 | # overwrite using local settings 49 | -include local.mk 50 | -------------------------------------------------------------------------------- /include/io/asm.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-only */ 2 | /* 3 | * Copyright (C) 2015 Regents of the University of California 4 | */ 5 | 6 | #pragma once 7 | 8 | #ifdef __ASSEMBLER__ 9 | #define __ASM_STR(x) x 10 | #else 11 | #define __ASM_STR(x) #x 12 | #endif 13 | 14 | #if __riscv_xlen == 64 15 | #define __REG_SEL(a, b) __ASM_STR(a) 16 | #elif __riscv_xlen == 32 17 | #define __REG_SEL(a, b) __ASM_STR(b) 18 | #else 19 | #error "Unexpected __riscv_xlen" 20 | #endif 21 | 22 | #define REG_L __REG_SEL(ld, lw) 23 | #define REG_S __REG_SEL(sd, sw) 24 | #define SZREG __REG_SEL(8, 4) 25 | #define LGREG __REG_SEL(3, 2) 26 | 27 | #define STACK_ALIGN 16 28 | 29 | #if __SIZEOF_POINTER__ == 8 30 | #define RISCV_PTR __ASM_STR(.dword) 31 | #define RISCV_SZPTR __ASM_STR(8) 32 | #define RISCV_LGPTR __ASM_STR(3) 33 | #elif __SIZEOF_POINTER__ == 4 34 | #define RISCV_PTR __ASM_STR(.word) 35 | #define RISCV_SZPTR __ASM_STR(4) 36 | #define RISCV_LGPTR __ASM_STR(2) 37 | #else 38 | #error "Unexpected __SIZEOF_POINTER__" 39 | #endif 40 | 41 | #if (__SIZEOF_INT__ == 4) 42 | #define RISCV_INT __ASM_STR(.word) 43 | #define RISCV_SZINT __ASM_STR(4) 44 | #define RISCV_LGINT __ASM_STR(2) 45 | #else 46 | #error "Unexpected __SIZEOF_INT__" 47 | #endif 48 | 49 | #if (__SIZEOF_SHORT__ == 2) 50 | #define RISCV_SHORT __ASM_STR(.half) 51 | #define RISCV_SZSHORT __ASM_STR(2) 52 | #define RISCV_LGSHORT __ASM_STR(1) 53 | #else 54 | #error "Unexpected __SIZEOF_SHORT__" 55 | #endif 56 | -------------------------------------------------------------------------------- /kernel/setup.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | unsigned long va_pa_offset; 6 | 7 | pgd_t kernel_pgd[PTRS_PER_PGD] __aligned(PAGE_SIZE); 8 | 9 | static pmd_t kernel_pmd[PTRS_PER_PMD * (KERNEL_VIRTUAL_SIZE / PGD_SIZE)] __aligned(PAGE_SIZE); 10 | 11 | static pmd_t head_pmd[PTRS_PER_PMD] __aligned(PAGE_SIZE); 12 | static pte_t head_pte[PTRS_PER_PTE] __aligned(PAGE_SIZE); 13 | 14 | char boot_command_line[COMMAND_LINE_SIZE]; 15 | 16 | void setup_vm(void) 17 | { 18 | size_t i; 19 | phys_addr_t pa = (phys_addr_t)_start; 20 | pgprot_t prot = PAGE_KERNEL_EXEC; 21 | 22 | BUILD_BUG_ON(KERNEL_VIRTUAL_START % PGD_SIZE); 23 | BUG_ON(pa % PMD_SIZE); 24 | 25 | va_pa_offset = KERNEL_VIRTUAL_START - pa; 26 | 27 | /* Identity mapping of 4k at kernel _start */ 28 | kernel_pgd[pgd_index(pa)] = pfn_pgd(PFN_DOWN((phys_addr_t) head_pmd), __pgprot(_PAGE_TABLE)); 29 | head_pmd[pmd_index(pa)] = pfn_pmd(PFN_DOWN((phys_addr_t) head_pte), __pgprot(_PAGE_TABLE)); 30 | head_pte[pte_index(pa)] = pfn_pte(PFN_DOWN((phys_addr_t) pa), prot); 31 | 32 | for (i = 0; i < KERNEL_VIRTUAL_SIZE / PGD_SIZE; ++i) { 33 | kernel_pgd[pgd_index(KERNEL_VIRTUAL_START) + i] = pfn_pgd( 34 | PFN_DOWN((phys_addr_t)kernel_pmd) + i, 35 | __pgprot(_PAGE_TABLE)); 36 | } 37 | for (i = 0; i < ARRAY_SIZE(kernel_pmd); i++) 38 | kernel_pmd[i] = pfn_pmd(PFN_DOWN(pa + i * PMD_SIZE), prot); 39 | } 40 | -------------------------------------------------------------------------------- /monitor/verif/safety.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette 2 | 3 | (require 4 | serval/lib/core 5 | serval/lib/unittest 6 | (prefix-in constants: "generated/monitor/verif/asm-offsets.rkt") 7 | "spec.rkt" 8 | "refinement.rkt") 9 | 10 | (provide safety-tests) 11 | 12 | ; Helpful debugging utility 13 | (define (debug-counterexample cex op args s1 s2) 14 | (printf "Confidentiality violation:\n") 15 | (printf "Operation: ~v\n" op) 16 | (printf "Arguments: ~v\n\n" (map bitvector->natural (evaluate args cex))) 17 | (printf "State 1:\n") 18 | (print-state cex s1) 19 | (printf "\nState 2:\n") 20 | (print-state cex s2)) 21 | 22 | 23 | ; Defines when two states appear equivalent to a user 24 | (define (equiv-user s t) 25 | (&& 26 | (equal? (state-current-user s) (state-current-user t)) 27 | (equal? ((state-dict s) (state-current-user s)) ((state-dict t) (state-current-user s))) 28 | (equal? (state-retval s) (state-retval t)))) 29 | 30 | 31 | (define (verify-confidentiality op [args null]) 32 | (define s1 (fresh-state)) 33 | (define s2 (fresh-state)) 34 | 35 | (define equiv-before (equiv-user s1 s2)) 36 | 37 | (apply op s1 args) 38 | (apply op s2 args) 39 | 40 | (define equiv-after (equiv-user s1 s2)) 41 | 42 | (define cex (verify (assert (implies equiv-before equiv-after)))) 43 | (when (sat? cex) 44 | (debug-counterexample cex op args s1 s2)) 45 | (check-unsat? cex)) 46 | 47 | 48 | (define (safety-tests) 49 | (test-case+ "confidentiality sys-dict-get" 50 | (verify-confidentiality sys-dict-get))) 51 | 52 | (module+ test 53 | (safety-tests)) -------------------------------------------------------------------------------- /include/sys/bitmap.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | #define DECLARE_BITMAP(name,bits) \ 9 | unsigned long name[BITS_TO_LONGS(bits)] 10 | 11 | #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) 12 | #define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1))) 13 | 14 | #define small_const_nbits(nbits) \ 15 | (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG) 16 | 17 | extern int __bitmap_subset(const unsigned long *bitmap1, 18 | const unsigned long *bitmap2, unsigned int nbits); 19 | 20 | static inline void bitmap_fill(unsigned long *dst, unsigned int nbits) 21 | { 22 | if (small_const_nbits(nbits)) 23 | *dst = ~0UL; 24 | else { 25 | unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); 26 | memset(dst, 0xff, len); 27 | } 28 | } 29 | 30 | static inline void bitmap_zero(unsigned long *dst, unsigned int nbits) 31 | { 32 | if (small_const_nbits(nbits)) 33 | *dst = 0UL; 34 | else { 35 | unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); 36 | memset(dst, 0, len); 37 | } 38 | } 39 | 40 | static inline int bitmap_subset(const unsigned long *src1, 41 | const unsigned long *src2, unsigned int nbits) 42 | { 43 | if (small_const_nbits(nbits)) 44 | return ! ((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits)); 45 | else 46 | return __bitmap_subset(src1, src2, nbits); 47 | } 48 | -------------------------------------------------------------------------------- /kernel/asm-offsets.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-only 2 | /* 3 | * Copyright (C) 2012 Regents of the University of California 4 | * Copyright (C) 2017 SiFive 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | void asm_offsets(void) 13 | { 14 | DEFINE(PT_SIZE_ON_STACK, ALIGN(sizeof(struct pt_regs), STACK_ALIGN)); 15 | OFFSET(PT_RA, pt_regs, ra); 16 | OFFSET(PT_FP, pt_regs, s0); 17 | OFFSET(PT_S0, pt_regs, s0); 18 | OFFSET(PT_S1, pt_regs, s1); 19 | OFFSET(PT_S2, pt_regs, s2); 20 | OFFSET(PT_S3, pt_regs, s3); 21 | OFFSET(PT_S4, pt_regs, s4); 22 | OFFSET(PT_S5, pt_regs, s5); 23 | OFFSET(PT_S6, pt_regs, s6); 24 | OFFSET(PT_S7, pt_regs, s7); 25 | OFFSET(PT_S8, pt_regs, s8); 26 | OFFSET(PT_S9, pt_regs, s9); 27 | OFFSET(PT_S10, pt_regs, s10); 28 | OFFSET(PT_S11, pt_regs, s11); 29 | OFFSET(PT_SP, pt_regs, sp); 30 | OFFSET(PT_TP, pt_regs, tp); 31 | OFFSET(PT_A0, pt_regs, a0); 32 | OFFSET(PT_A1, pt_regs, a1); 33 | OFFSET(PT_A2, pt_regs, a2); 34 | OFFSET(PT_A3, pt_regs, a3); 35 | OFFSET(PT_A4, pt_regs, a4); 36 | OFFSET(PT_A5, pt_regs, a5); 37 | OFFSET(PT_A6, pt_regs, a6); 38 | OFFSET(PT_A7, pt_regs, a7); 39 | OFFSET(PT_T0, pt_regs, t0); 40 | OFFSET(PT_T1, pt_regs, t1); 41 | OFFSET(PT_T2, pt_regs, t2); 42 | OFFSET(PT_T3, pt_regs, t3); 43 | OFFSET(PT_T4, pt_regs, t4); 44 | OFFSET(PT_T5, pt_regs, t5); 45 | OFFSET(PT_T6, pt_regs, t6); 46 | OFFSET(PT_GP, pt_regs, gp); 47 | } 48 | -------------------------------------------------------------------------------- /kernel/entry.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | .text 4 | 5 | ENTRY(supervisor_trap_vector) 6 | SAVE_REGS scratch=sscratch 7 | 8 | mv a0, sp 9 | csrr a1, scause 10 | call do_trap 11 | 12 | restore_regs: 13 | RESTORE_REGS 14 | sret 15 | END(supervisor_trap_vector) 16 | 17 | ENTRY(restore_regs_and_return_to_user) 18 | csrr sp, sscratch 19 | j restore_regs 20 | END(restore_regs_and_return_to_user) 21 | 22 | #if 0 23 | /* 24 | * a0 - cause 25 | * sp - pt_regs 26 | */ 27 | ENTRY(do_trap) 28 | /* each entry (j offset) has 4 bytes */ 29 | slli t0, a0, 2 30 | la t1, excp_vect_table 31 | la t2, excp_vect_table_end 32 | /* pt_regs */ 33 | move a0, sp 34 | add t0, t1, t0 35 | /* check if exception code lies within bounds */ 36 | bgeu t0, t2, 1f 37 | jr t0 38 | 1: 39 | j do_trap_unknown 40 | END(do_trap) 41 | 42 | ENTRY(excp_vect_table) 43 | j do_trap_insn_misaligned 44 | j do_trap_insn_fault 45 | j do_trap_insn_illegal 46 | j do_trap_break 47 | j do_trap_load_misaligned 48 | j do_trap_load_fault 49 | j do_trap_store_misaligned 50 | j do_trap_store_fault 51 | j do_trap_ecall_u 52 | j do_trap_ecall_s 53 | j do_trap_unknown 54 | j do_trap_ecall_m 55 | j do_trap_insn_fault 56 | j do_trap_load_fault 57 | j do_trap_unknown 58 | j do_trap_store_fault 59 | excp_vect_table_end: 60 | END(excp_vect_table) 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /kernel/dumpstack.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-only 2 | /* 3 | * Copyright (C) 2008 ARM Limited 4 | * Copyright (C) 2014 Regents of the University of California 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | static inline int kstack_end(void *addr) 13 | { 14 | /* Reliable end of stack detection: 15 | * Some APM bios versions misalign the stack 16 | */ 17 | return !(((unsigned long)addr + sizeof(void *) - 1) & 18 | (CPU_STACK_SIZE - sizeof(void *))); 19 | } 20 | 21 | static bool kernel_text_address(unsigned long addr) 22 | { 23 | if (addr >= (unsigned long)_stext && 24 | addr < (unsigned long)_etext) 25 | return 1; 26 | 27 | return 0; 28 | } 29 | 30 | /* assume no frame pointer */ 31 | static void walk_stackframe(bool (*fn)(unsigned long, void *), void *arg) 32 | { 33 | unsigned long sp, pc; 34 | unsigned long *ksp; 35 | const register unsigned long current_sp asm("sp"); 36 | 37 | sp = current_sp; 38 | pc = (uintptr_t)walk_stackframe; 39 | 40 | if (sp & 0x7) 41 | return; 42 | 43 | ksp = (unsigned long *)sp; 44 | while (!kstack_end(ksp)) { 45 | if (kernel_text_address(pc) && fn(pc, arg)) 46 | break; 47 | pc = (*ksp++) - 0x4; 48 | } 49 | } 50 | 51 | static bool print_trace_address(unsigned long pc, void *arg) 52 | { 53 | pr_info("[<%px>]\n", (void *)pc); 54 | return false; 55 | } 56 | 57 | void dump_stack(void) 58 | { 59 | pr_info("Call Trace:\n"); 60 | walk_stackframe(print_trace_address, NULL); 61 | } 62 | -------------------------------------------------------------------------------- /kernel/hexdump.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-only 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | const char hex_asc[] = "0123456789abcdef"; 8 | const char hex_asc_upper[] = "0123456789ABCDEF"; 9 | 10 | /** 11 | * hex_to_bin - convert a hex digit to its real value 12 | * @ch: ascii character represents hex digit 13 | * 14 | * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad 15 | * input. 16 | */ 17 | int hex_to_bin(char ch) 18 | { 19 | if ((ch >= '0') && (ch <= '9')) 20 | return ch - '0'; 21 | ch = tolower(ch); 22 | if ((ch >= 'a') && (ch <= 'f')) 23 | return ch - 'a' + 10; 24 | return -1; 25 | } 26 | 27 | /** 28 | * hex2bin - convert an ascii hexadecimal string to its binary representation 29 | * @dst: binary result 30 | * @src: ascii hexadecimal string 31 | * @count: result length 32 | * 33 | * Return 0 on success, -EINVAL in case of bad input. 34 | */ 35 | int hex2bin(uint8_t *dst, const char *src, size_t count) 36 | { 37 | while (count--) { 38 | int hi = hex_to_bin(*src++); 39 | int lo = hex_to_bin(*src++); 40 | 41 | if ((hi < 0) || (lo < 0)) 42 | return -EINVAL; 43 | 44 | *dst++ = (hi << 4) | lo; 45 | } 46 | return 0; 47 | } 48 | 49 | /** 50 | * bin2hex - convert binary data to an ascii hexadecimal string 51 | * @dst: ascii hexadecimal result 52 | * @src: binary data 53 | * @count: binary data length 54 | */ 55 | char *bin2hex(char *dst, const void *src, size_t count) 56 | { 57 | const unsigned char *_src = src; 58 | 59 | while (count--) 60 | dst = hex_byte_pack(dst, *_src++); 61 | return dst; 62 | } 63 | -------------------------------------------------------------------------------- /serval/serval/unicorn/const_generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import argparse, re, sys 4 | from collections import OrderedDict 5 | 6 | def generate(out, d, typ, prefixes): 7 | for prefix in prefixes: 8 | out.write("\n(define _%s\n (_%s '(" % (prefix.lower(), typ)) 9 | first = True 10 | for key, value in d.items(): 11 | if not key.startswith(prefix): 12 | continue 13 | if first: 14 | first = False 15 | else: 16 | out.write("\n" + ' ' * (len(typ) + 7)) 17 | key = key[len(prefix)+1:].lower().replace('_', '-') 18 | # patch numeric as they cannot be used as symbols 19 | if key.isdigit(): 20 | assert prefix == 'UC_MODE' 21 | key = 'x86-' + key 22 | out.write("%s = %s" % (key, value)) 23 | out.write(")))\n") 24 | 25 | def main(): 26 | parser = argparse.ArgumentParser() 27 | parser.add_argument('--enum', action='append', default=[]) 28 | parser.add_argument('--bitmask', action='append', default=[]) 29 | parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin) 30 | parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'), default=sys.stdout) 31 | args = parser.parse_args() 32 | 33 | pattern = re.compile(r'^([A-Z0-9_]+)\s*=\s*([0-9]+)') 34 | d = OrderedDict() 35 | for s in args.infile: 36 | m = pattern.match(s.strip()) 37 | if m: 38 | d.update({m.group(1): m.group(2)}) 39 | 40 | out = args.outfile 41 | out.write('#lang racket/base\n\n(require ffi/unsafe)\n\n(provide (all-defined-out))\n') 42 | 43 | generate(out, d, "enum", args.enum) 44 | generate(out, d, "bitmask", args.bitmask) 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /include/sys/ilist.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /* 6 | * Use integers instead of pointers to form a list. 7 | * This makes verification easier. 8 | */ 9 | 10 | /* insert new beteween prev and next */ 11 | #define __ilist_add(a, new, iprev, inext) \ 12 | ({ \ 13 | typeof(new) _new = new; \ 14 | typeof(iprev) _prev = iprev; \ 15 | typeof(inext) _next = inext; \ 16 | a[_next].prev = _new; \ 17 | a[_new].next = _next; \ 18 | a[_new].prev = _prev; \ 19 | a[_prev].next = _new; \ 20 | }) 21 | 22 | #define ilist_add(a, new, head) \ 23 | __ilist_add(a, new, head, a[head].next) 24 | 25 | #define ilist_add_tail(a, new, head) \ 26 | __ilist_add(a, new, a[head].prev, head) 27 | 28 | /* delete by pointing prev and next to each other */ 29 | #define __ilist_del(a, iprev, inext) \ 30 | ({ \ 31 | typeof(iprev) _prev = iprev; \ 32 | typeof(inext) _next = inext; \ 33 | a[_next].prev = _prev; \ 34 | a[_prev].next = _next; \ 35 | }) 36 | 37 | #define ilist_del(a, i, poison) \ 38 | ({ \ 39 | typeof(i) _i = i; \ 40 | __ilist_del(a, a[_i].prev, a[_i].next); \ 41 | a[_i].prev = poison; \ 42 | a[_i].next = poison; \ 43 | }) 44 | 45 | #define ilist_empty(a, head) \ 46 | (a[head].next == (head)) 47 | 48 | #define ilist_first_entry(a, head) \ 49 | (a[head].next) 50 | -------------------------------------------------------------------------------- /include/sys/unaligned/le_byteshift.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #pragma once 3 | 4 | #include 5 | 6 | static inline uint16_t __get_unaligned_le16(const uint8_t *p) 7 | { 8 | return p[0] | p[1] << 8; 9 | } 10 | 11 | static inline uint32_t __get_unaligned_le32(const uint8_t *p) 12 | { 13 | return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; 14 | } 15 | 16 | static inline uint64_t __get_unaligned_le64(const uint8_t *p) 17 | { 18 | return (uint64_t)__get_unaligned_le32(p + 4) << 32 | 19 | __get_unaligned_le32(p); 20 | } 21 | 22 | static inline void __put_unaligned_le16(uint16_t val, uint8_t *p) 23 | { 24 | *p++ = val; 25 | *p++ = val >> 8; 26 | } 27 | 28 | static inline void __put_unaligned_le32(uint32_t val, uint8_t *p) 29 | { 30 | __put_unaligned_le16(val >> 16, p + 2); 31 | __put_unaligned_le16(val, p); 32 | } 33 | 34 | static inline void __put_unaligned_le64(uint64_t val, uint8_t *p) 35 | { 36 | __put_unaligned_le32(val >> 32, p + 4); 37 | __put_unaligned_le32(val, p); 38 | } 39 | 40 | static inline uint16_t get_unaligned_le16(const void *p) 41 | { 42 | return __get_unaligned_le16((const uint8_t *)p); 43 | } 44 | 45 | static inline uint32_t get_unaligned_le32(const void *p) 46 | { 47 | return __get_unaligned_le32((const uint8_t *)p); 48 | } 49 | 50 | static inline uint64_t get_unaligned_le64(const void *p) 51 | { 52 | return __get_unaligned_le64((const uint8_t *)p); 53 | } 54 | 55 | static inline void put_unaligned_le16(uint16_t val, void *p) 56 | { 57 | __put_unaligned_le16(val, p); 58 | } 59 | 60 | static inline void put_unaligned_le32(uint32_t val, void *p) 61 | { 62 | __put_unaligned_le32(val, p); 63 | } 64 | 65 | static inline void put_unaligned_le64(uint64_t val, void *p) 66 | { 67 | __put_unaligned_le64(val, p); 68 | } 69 | -------------------------------------------------------------------------------- /include/io/sizes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define SZ_1 0x00000001 6 | #define SZ_2 0x00000002 7 | #define SZ_4 0x00000004 8 | #define SZ_8 0x00000008 9 | #define SZ_16 0x00000010 10 | #define SZ_32 0x00000020 11 | #define SZ_64 0x00000040 12 | #define SZ_128 0x00000080 13 | #define SZ_256 0x00000100 14 | #define SZ_512 0x00000200 15 | 16 | #define SZ_1K 0x00000400 17 | #define SZ_2K 0x00000800 18 | #define SZ_4K 0x00001000 19 | #define SZ_8K 0x00002000 20 | #define SZ_16K 0x00004000 21 | #define SZ_32K 0x00008000 22 | #define SZ_64K 0x00010000 23 | #define SZ_128K 0x00020000 24 | #define SZ_256K 0x00040000 25 | #define SZ_512K 0x00080000 26 | 27 | #define SZ_1M 0x00100000 28 | #define SZ_2M 0x00200000 29 | #define SZ_4M 0x00400000 30 | #define SZ_8M 0x00800000 31 | #define SZ_16M 0x01000000 32 | #define SZ_32M 0x02000000 33 | #define SZ_64M 0x04000000 34 | #define SZ_128M 0x08000000 35 | #define SZ_256M 0x10000000 36 | #define SZ_512M 0x20000000 37 | 38 | #define SZ_1G 0x40000000 39 | #define SZ_2G 0x80000000 40 | #define SZ_4G UINT64_C(0x100000000) 41 | -------------------------------------------------------------------------------- /include/sys/bitops.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) 11 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(long)) 12 | 13 | #define ffz(x) __ffs(~(x)) 14 | 15 | /** 16 | * ror32 - rotate a 32-bit value right 17 | * @word: value to rotate 18 | * @shift: bits to roll 19 | */ 20 | static inline uint32_t ror32(uint32_t word, unsigned int shift) 21 | { 22 | return (word >> shift) | (word << (32 - shift)); 23 | } 24 | 25 | unsigned long find_first_bit(const unsigned long *addr, unsigned long size); 26 | 27 | unsigned long find_last_bit(const unsigned long *addr, unsigned long size); 28 | 29 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, 30 | unsigned long offset); 31 | 32 | unsigned long find_first_zero_bit(const unsigned long *addr, 33 | unsigned long size); 34 | 35 | unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, 36 | unsigned long offset); 37 | 38 | unsigned long find_next_and_bit(const unsigned long *addr1, 39 | const unsigned long *addr2, unsigned long size, 40 | unsigned long offset); 41 | 42 | #define for_each_set_bit(bit, addr, size) \ 43 | for ((bit) = find_first_bit((addr), (size)); \ 44 | (bit) < (size); \ 45 | (bit) = find_next_bit((addr), (size), (bit) + 1)) 46 | 47 | /** 48 | * test_bit - Determine whether a bit is set 49 | * @nr: bit number to test 50 | * @addr: Address to start counting from 51 | */ 52 | static inline int test_bit(int nr, const volatile unsigned long *addr) 53 | { 54 | return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); 55 | } 56 | -------------------------------------------------------------------------------- /include/sys/unaligned/be_byteshift.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #pragma once 3 | 4 | #include 5 | 6 | static inline uint16_t __get_unaligned_be16(const uint8_t *p) 7 | { 8 | return p[0] << 8 | p[1]; 9 | } 10 | 11 | static inline uint32_t __get_unaligned_be32(const uint8_t *p) 12 | { 13 | return (uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | 14 | (uint32_t)p[2] << 8 | (uint32_t)p[3]; 15 | } 16 | 17 | static inline uint64_t __get_unaligned_be64(const uint8_t *p) 18 | { 19 | return (uint64_t)__get_unaligned_be32(p) << 32 | 20 | __get_unaligned_be32(p + 4); 21 | } 22 | 23 | static inline void __put_unaligned_be16(uint16_t val, uint8_t *p) 24 | { 25 | *p++ = val >> 8; 26 | *p++ = val; 27 | } 28 | 29 | static inline void __put_unaligned_be32(uint32_t val, uint8_t *p) 30 | { 31 | __put_unaligned_be16(val >> 16, p); 32 | __put_unaligned_be16(val, p + 2); 33 | } 34 | 35 | static inline void __put_unaligned_be64(uint64_t val, uint8_t *p) 36 | { 37 | __put_unaligned_be32(val >> 32, p); 38 | __put_unaligned_be32(val, p + 4); 39 | } 40 | 41 | static inline uint16_t get_unaligned_be16(const void *p) 42 | { 43 | return __get_unaligned_be16((const uint8_t *)p); 44 | } 45 | 46 | static inline uint32_t get_unaligned_be32(const void *p) 47 | { 48 | return __get_unaligned_be32((const uint8_t *)p); 49 | } 50 | 51 | static inline uint64_t get_unaligned_be64(const void *p) 52 | { 53 | return __get_unaligned_be64((const uint8_t *)p); 54 | } 55 | 56 | static inline void put_unaligned_be16(uint16_t val, void *p) 57 | { 58 | __put_unaligned_be16(val, p); 59 | } 60 | 61 | static inline void put_unaligned_be32(uint32_t val, void *p) 62 | { 63 | __put_unaligned_be32(val, p); 64 | } 65 | 66 | static inline void put_unaligned_be64(uint64_t val, void *p) 67 | { 68 | __put_unaligned_be64(val, p); 69 | } 70 | -------------------------------------------------------------------------------- /kernel/ctype.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * linux/lib/ctype.c 4 | * 5 | * Copyright (C) 1991, 1992 Linus Torvalds 6 | */ 7 | 8 | #include 9 | 10 | const unsigned char _ctype[] = { 11 | _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ 12 | _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ 13 | _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ 14 | _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ 15 | _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ 16 | _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ 17 | _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ 18 | _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ 19 | _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ 20 | _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ 21 | _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ 22 | _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ 23 | _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ 24 | _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ 25 | _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ 26 | _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ 27 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ 28 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ 29 | _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ 30 | _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ 31 | _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ 32 | _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ 33 | _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ 34 | _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ 35 | -------------------------------------------------------------------------------- /bios/boot/head.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | .section .head.text 7 | 8 | /* 9 | * Upon entry: 10 | * - a0 is the hart ID; 11 | * - a1 is a pointer to the device tree blob. 12 | */ 13 | ENTRY(_start) 14 | 15 | /* Clear interrupt-pending and interrupt-enable bits */ 16 | csrw mip, x0 17 | csrw mie, x0 18 | 19 | /* Clear status register */ 20 | csrw mstatus, x0 21 | 22 | /* Only boot one CPU */ 23 | li t0, CONFIG_BOOT_CPU 24 | bne a0, t0, hartN 25 | 26 | 27 | /* 28 | * Hart IDs are not guaranteed to be contiguous. 29 | * For simplicity, we use hart IDs to index into cpu_stack. 30 | */ 31 | 32 | /* set up the per-CPU stack */ 33 | la sp, cpu_stack + CPU_STACK_SIZE - PT_SIZE_ON_STACK 34 | slli t0, a0, CPU_STACK_SHIFT 35 | add sp, sp, t0 36 | 37 | /* set up trap handling */ 38 | csrw mscratch, sp 39 | la t0, machine_trap_vector 40 | csrw mtvec, t0 41 | 42 | /* Bring PMP into well-known state by disabling everything */ 43 | csrw pmpcfg0, zero 44 | csrw pmpcfg2, zero 45 | csrw pmpaddr0, zero 46 | csrw pmpaddr1, zero 47 | csrw pmpaddr2, zero 48 | csrw pmpaddr3, zero 49 | csrw pmpaddr4, zero 50 | csrw pmpaddr5, zero 51 | csrw pmpaddr6, zero 52 | csrw pmpaddr7, zero 53 | csrw pmpaddr8, zero 54 | csrw pmpaddr9, zero 55 | csrw pmpaddr10, zero 56 | csrw pmpaddr11, zero 57 | csrw pmpaddr12, zero 58 | csrw pmpaddr13, zero 59 | csrw pmpaddr14, zero 60 | csrw pmpaddr15, zero 61 | sfence.vma 62 | 63 | tail main 64 | 65 | hartN: 66 | wfi 67 | j hartN 68 | END(_start) 69 | -------------------------------------------------------------------------------- /include/asm/bitops.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #if (BITS_PER_LONG == 64) 6 | #define __AMO(op) "amo" #op ".d" 7 | #elif (BITS_PER_LONG == 32) 8 | #define __AMO(op) "amo" #op ".w" 9 | #else 10 | #error "Unexpected BITS_PER_LONG" 11 | #endif 12 | 13 | #define __op_bit_ord(op, mod, nr, addr, ord) \ 14 | __asm__ __volatile__ ( \ 15 | __AMO(op) #ord " zero, %1, %0" \ 16 | : "+A" (addr[BIT_WORD(nr)]) \ 17 | : "r" (mod(BIT_MOD(nr))) \ 18 | : "memory"); 19 | 20 | #define __op_bit(op, mod, nr, addr) \ 21 | __op_bit_ord(op, mod, nr, addr, ) 22 | 23 | /* Bitmask modifiers */ 24 | #define __NOP(x) (x) 25 | #define __NOT(x) (~(x)) 26 | 27 | /** 28 | * set_bit - Atomically set a bit in memory 29 | * @nr: the bit to set 30 | * @addr: the address to start counting from 31 | * 32 | * Note: there are no guarantees that this function will not be reordered 33 | * on non x86 architectures, so if you are writing portable code, 34 | * make sure not to rely on its reordering guarantees. 35 | * 36 | * Note that @nr may be almost arbitrarily large; this function is not 37 | * restricted to acting on a single-word quantity. 38 | */ 39 | static inline void set_bit(int nr, volatile unsigned long *addr) 40 | { 41 | __op_bit(or, __NOP, nr, addr); 42 | } 43 | 44 | /** 45 | * clear_bit - Clears a bit in memory 46 | * @nr: Bit to clear 47 | * @addr: Address to start counting from 48 | * 49 | * Note: there are no guarantees that this function will not be reordered 50 | * on non x86 architectures, so if you are writing portable code, 51 | * make sure not to rely on its reordering guarantees. 52 | */ 53 | static inline void clear_bit(int nr, volatile unsigned long *addr) 54 | { 55 | __op_bit(and, __NOT, nr, addr); 56 | } 57 | -------------------------------------------------------------------------------- /include/sys/of.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0+ */ 2 | /* 3 | * Definitions for talking to the Open Firmware PROM on 4 | * Power Macintosh and other computers. 5 | * 6 | * Copyright (C) 1996-2005 Paul Mackerras. 7 | * 8 | * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp. 9 | * Updates for SPARC64 by David S. Miller 10 | * Derived from PowerPC and Sparc prom.h files by Stephen Rothwell, IBM Corp. 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | struct device_node; 19 | 20 | #define for_each_of_allnodes_from(from, dn) \ 21 | for (dn = __of_find_all_nodes(from); dn; dn = __of_find_all_nodes(dn)) 22 | #define for_each_of_allnodes(dn) for_each_of_allnodes_from(NULL, dn) 23 | 24 | struct device_node *__of_find_all_nodes(struct device_node *prev); 25 | 26 | struct device_node *of_find_node_by_path(const char *path); 27 | struct device_node *of_find_compatible_node(struct device_node *from, const char *type, const char *compat); 28 | 29 | const void *of_get_property(const struct device_node *node, const char *name, int *lenp); 30 | int of_property_read_u32(const struct device_node *np, const char *propname, uint32_t *out_value); 31 | 32 | int of_device_is_compatible(const struct device_node *device, const char *compat); 33 | 34 | /* Helper to read a big number; size is in cells (not bytes) */ 35 | static inline uint64_t of_read_number(const be32_t *cell, int size) 36 | { 37 | uint64_t r = 0; 38 | 39 | while (size--) 40 | r = (r << 32) | be32_to_cpu(*(cell++)); 41 | return r; 42 | } 43 | 44 | int of_n_addr_cells(struct device_node *np); 45 | int of_n_size_cells(struct device_node *np); 46 | 47 | bool early_init_dt_verify(void *params); 48 | void early_init_dt_scan_nodes(void); 49 | bool early_init_dt_scan(void *params); 50 | void early_init_fdt_reserve_self(void); 51 | extern int of_get_flat_dt_size(void); 52 | 53 | void of_dt_move(void *buf, size_t size); 54 | -------------------------------------------------------------------------------- /include/asm/asm-offsets.h: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT MODIFY. 3 | * 4 | * This file was automatically generated. 5 | */ 6 | 7 | #pragma once 8 | 9 | #define PT_SIZE_ON_STACK 256 /* ALIGN(sizeof(struct pt_regs), STACK_ALIGN) */ 10 | #define PT_RA 0 /* offsetof(struct pt_regs, ra) */ 11 | #define PT_FP 56 /* offsetof(struct pt_regs, s0) */ 12 | #define PT_S0 56 /* offsetof(struct pt_regs, s0) */ 13 | #define PT_S1 64 /* offsetof(struct pt_regs, s1) */ 14 | #define PT_S2 136 /* offsetof(struct pt_regs, s2) */ 15 | #define PT_S3 144 /* offsetof(struct pt_regs, s3) */ 16 | #define PT_S4 152 /* offsetof(struct pt_regs, s4) */ 17 | #define PT_S5 160 /* offsetof(struct pt_regs, s5) */ 18 | #define PT_S6 168 /* offsetof(struct pt_regs, s6) */ 19 | #define PT_S7 176 /* offsetof(struct pt_regs, s7) */ 20 | #define PT_S8 184 /* offsetof(struct pt_regs, s8) */ 21 | #define PT_S9 192 /* offsetof(struct pt_regs, s9) */ 22 | #define PT_S10 200 /* offsetof(struct pt_regs, s10) */ 23 | #define PT_S11 208 /* offsetof(struct pt_regs, s11) */ 24 | #define PT_SP 8 /* offsetof(struct pt_regs, sp) */ 25 | #define PT_TP 24 /* offsetof(struct pt_regs, tp) */ 26 | #define PT_A0 72 /* offsetof(struct pt_regs, a0) */ 27 | #define PT_A1 80 /* offsetof(struct pt_regs, a1) */ 28 | #define PT_A2 88 /* offsetof(struct pt_regs, a2) */ 29 | #define PT_A3 96 /* offsetof(struct pt_regs, a3) */ 30 | #define PT_A4 104 /* offsetof(struct pt_regs, a4) */ 31 | #define PT_A5 112 /* offsetof(struct pt_regs, a5) */ 32 | #define PT_A6 120 /* offsetof(struct pt_regs, a6) */ 33 | #define PT_A7 128 /* offsetof(struct pt_regs, a7) */ 34 | #define PT_T0 32 /* offsetof(struct pt_regs, t0) */ 35 | #define PT_T1 40 /* offsetof(struct pt_regs, t1) */ 36 | #define PT_T2 48 /* offsetof(struct pt_regs, t2) */ 37 | #define PT_T3 216 /* offsetof(struct pt_regs, t3) */ 38 | #define PT_T4 224 /* offsetof(struct pt_regs, t4) */ 39 | #define PT_T5 232 /* offsetof(struct pt_regs, t5) */ 40 | #define PT_T6 240 /* offsetof(struct pt_regs, t6) */ 41 | #define PT_GP 16 /* offsetof(struct pt_regs, gp) */ 42 | -------------------------------------------------------------------------------- /serval/serval/spec/refinement.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette 2 | 3 | (require 4 | "../lib/core.rkt" 5 | "../lib/unittest.rkt" 6 | ) 7 | 8 | (provide (all-defined-out)) 9 | 10 | (define (handle-lowlevel-ce counterexample assertion) 11 | (when assertion 12 | (define bug (first (bug-ref assertion))) 13 | (displayln "Low-level bug:") 14 | (printf " Location: ~v\n" (cdr (assoc 'location bug))) 15 | (printf " Message: ~v\n" ((cdr (assoc 'message bug )))))) 16 | 17 | (define 18 | (verify-refinement 19 | #:implstate impl-state 20 | #:impl impl-func 21 | #:specstate spec-state 22 | #:spec spec-func 23 | #:abs abs-function 24 | #:ri rep-invariant 25 | [args null] 26 | [ce-handler (lambda args (void))]) 27 | 28 | (define ri0 (rep-invariant impl-state)) 29 | 30 | (define pre (check-asserts (equal? spec-state (abs-function impl-state)))) 31 | 32 | (check-sat? (solve (assert ri0))) 33 | (check-sat? (solve (assert pre))) 34 | 35 | ; spec state transition 36 | (apply spec-func spec-state args) 37 | ; make sure spec-func doesn't generate assertions 38 | (check-equal? (asserts) null) 39 | 40 | ; impl state transition 41 | (define impl-asserted 42 | (with-spectre-asserts-only (apply impl-func impl-state args))) 43 | 44 | (for ([as impl-asserted]) 45 | (define cex (verify (assert (=> ri0 as)))) 46 | (when (sat? cex) (handle-lowlevel-ce cex as)) 47 | (check-unsat? cex)) 48 | 49 | (define-values (ri1 ri1-asserted) 50 | (with-asserts (rep-invariant impl-state))) 51 | (check-unsat? (verify (assert (=> ri0 (apply && ri1-asserted))))) 52 | 53 | (define-values (post post-asserted) 54 | (with-asserts (equal? spec-state (abs-function impl-state)))) 55 | 56 | (check-unsat? (verify (assert (=> ri0 (apply && post-asserted))))) 57 | 58 | (let ([sol (verify (assert (=> (&& pre ri0) post)))]) 59 | (when (sat? sol) (ce-handler spec-state (abs-function impl-state) sol)) 60 | (check-unsat? sol)) 61 | 62 | (check-unsat? (verify (assert (=> (&& pre ri0) ri1)))) 63 | 64 | (void)) 65 | -------------------------------------------------------------------------------- /include/asm/csr_bits/status.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define SR_UIE BIT_64(0) /* User interrupt-enable */ 6 | #define SR_SIE BIT_64(1) /* Supervisor interrupt-enable */ 7 | /* RESERVED BIT_64(2) */ 8 | #define SR_MIE BIT_64(3) /* Machine interrupt-enable */ 9 | #define SR_UPIE BIT_64(4) /* User previous interrupt-enable */ 10 | #define SR_SPIE BIT_64(5) /* Supervisor previous interrupt-enable */ 11 | /* RESERVED BIT_64(6) */ 12 | #define SR_MPIE BIT_64(7) /* Machine previous interrupt-enable */ 13 | #define SR_SPP BIT_64(8) /* Supervisor previous privilege */ 14 | /* RESERVED GENMASK_64(10, 9) */ 15 | #define SR_MPP GENMASK_64(12, 11) /* Machine previous privilege */ 16 | #define SR_FS GENMASK_64(14, 13) 17 | #define SR_XS GENMASK_64(16, 15) 18 | #define SR_MPRV BIT_64(17) /* Modify privilege */ 19 | #define SR_SUM BIT_64(18) /* Permit supervisor user memory access */ 20 | #define SR_MXR BIT_64(19) /* Make executable readable */ 21 | #define SR_TVM BIT_64(20) /* Trap virtual memory */ 22 | #define SR_TW BIT_64(21) /* Timeout wait */ 23 | #define SR_TSR BIT_64(22) /* Trap SRET */ 24 | /* RESERVED GENMASK_64(31, 23) */ 25 | #define SR_UXL GENMASK_64(33, 32) /* User XLEN */ 26 | #define SR_SXL GENMASK_64(35, 34) /* Supervisor XLEN */ 27 | /* RESERVED GENMASK_64(62, 36) */ 28 | #define SR_SD BIT_64(63) 29 | 30 | #define SR_MPP_SHIFT 11 31 | #define SR_MPP_U (0 << SR_MPP_SHIFT) 32 | #define SR_MPP_S (1 << SR_MPP_SHIFT) 33 | #define SR_MPP_M (3 << SR_MPP_SHIFT) 34 | 35 | #define SR_UXL_SHIFT 32ul 36 | #define SR_UXL_32 (1ul << SR_UXL_SHIFT) 37 | #define SR_UXL_64 (2ul << SR_UXL_SHIFT) 38 | #define SR_UXL_128 (3ul << SR_UXL_SHIFT) 39 | 40 | #define SR_SXL_SHIFT 34ul 41 | #define SR_SXL_32 (1ul << SR_SXL_SHIFT) 42 | #define SR_SXL_64 (2ul << SR_SXL_SHIFT) 43 | #define SR_SXL_128 (3ul << SR_SXL_SHIFT) 44 | -------------------------------------------------------------------------------- /include/sys/vmlinux.lds.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define __VMLINUX_SYMBOL(x) x 6 | #define __VMLINUX_SYMBOL_STR(x) #x 7 | 8 | /* Indirect, so macros are expanded before pasting. */ 9 | #define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x) 10 | #define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x) 11 | 12 | /* Align . to a 8 byte boundary equals to maximum function alignment. */ 13 | #define ALIGN_FUNCTION() . = ALIGN(8) 14 | 15 | #define TEXT_SECTION \ 16 | .text : { \ 17 | *(.head.text) \ 18 | ALIGN_FUNCTION(); \ 19 | *(.text .text.*) \ 20 | *(.fixup) \ 21 | } 22 | 23 | #define RO_DATA_SECTION(align) \ 24 | . = ALIGN(align); \ 25 | .rodata : { \ 26 | *(.rodata .rodata.*) \ 27 | } 28 | 29 | #define RW_DATA_SECTION(align) \ 30 | . = ALIGN(align); \ 31 | .data : { \ 32 | *(.data .data.*) \ 33 | } 34 | 35 | #define BSS_SECTION(bss_align, stop_align) \ 36 | . = ALIGN(bss_align); \ 37 | __bss_start = .; \ 38 | .bss : { \ 39 | *(.bss .bss.* .sbss .sbss.*) \ 40 | } \ 41 | . = ALIGN(stop_align); \ 42 | __bss_end = .; 43 | -------------------------------------------------------------------------------- /kernel/boot/head.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | .section .head.text 6 | 7 | ENTRY(_start) 8 | /* mask interrupts */ 9 | csrw sie, zero 10 | 11 | csrw sstatus, zero 12 | 13 | /* allow one CPU to boot first */ 14 | li t0, CONFIG_BOOT_CPU 15 | bne a0, t0, hartN 16 | 17 | /* save hart ID and DTB physical address */ 18 | mv s0, a0 19 | mv s1, a1 20 | 21 | /* clear BSS */ 22 | la a0, __bss_start 23 | la a1, __bss_end 24 | bss_loop: 25 | REG_S zero, 0(a0) 26 | addi a0, a0, SZREG 27 | bltu a0, a1, bss_loop 28 | 29 | /* fill kernel_gd (sp holds a physical address) */ 30 | la sp, cpu_stack + CPU_STACK_SIZE - PT_SIZE_ON_STACK 31 | call setup_vm 32 | 33 | /* relocate pc and sp */ 34 | call relocate 35 | 36 | /* reload sp */ 37 | la sp, cpu_stack + CPU_STACK_SIZE - PT_SIZE_ON_STACK 38 | 39 | /* set sscratch for trap handling */ 40 | csrw sscratch, sp 41 | 42 | /* set trap vector */ 43 | la t0, supervisor_trap_vector 44 | csrw stvec, t0 45 | 46 | /* start the kernel */ 47 | mv a0, s0 48 | mv a1, s1 49 | tail main 50 | 51 | relocate: 52 | /* a1: va_pa_offset */ 53 | li a1, KERNEL_VIRTUAL_START 54 | la a0, _start 55 | sub a1, a1, a0 56 | 57 | /* relocate return address */ 58 | add ra, ra, a1 59 | 60 | /* point stvec to the VA after satp write */ 61 | la a0, 1f 62 | add a0, a0, a1 63 | csrw stvec, a0 64 | 65 | /* load the kernel page table */ 66 | la a0, kernel_pgd 67 | srl a0, a0, PAGE_SHIFT 68 | li a1, SATP_MODE_SV39 69 | or a0, a0, a1 70 | sfence.vma 71 | csrw satp, a0 72 | 73 | /* fall through if VA == PA; trap here otherwise */ 74 | 1: 75 | ret 76 | 77 | hartN: 78 | wfi 79 | j hartN 80 | END(_start) 81 | -------------------------------------------------------------------------------- /serval/serval/lib/unittest.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette 2 | 3 | (require "debug.rkt" rackunit rackunit/text-ui rosette/lib/roseunit) 4 | 5 | (provide (all-defined-out) run-tests (all-from-out rackunit) (all-from-out rosette/lib/roseunit)) 6 | 7 | (define quickcheck-max-success (make-parameter 100)) 8 | 9 | (define-simple-check (check-unsat? sol) (unsat? sol)) 10 | (define-simple-check (check-sat? sol) (sat? sol)) 11 | 12 | ; A version of test-case that clears all Rosette state after; executing and 13 | ; inserts an additional check that the test does not leave around unnecessary 14 | ; assertions. 15 | (define-syntax-rule (test-case+ name body ...) 16 | (test-case name (begin 17 | (printf "Running test ~v\n" name) 18 | (time (with-asserts-only 19 | (parameterize ([current-bitwidth (current-bitwidth)] 20 | [term-cache (hash-copy (term-cache))] 21 | [current-solver (current-solver)] 22 | [current-oracle (oracle (current-oracle))]) 23 | (check-asserts-only (begin body ...)) 24 | (check-equal? (asserts) null)))) 25 | (bug-clear!) 26 | (printf "Finished test ~v\n" name)))) 27 | 28 | (define-syntax-rule (check-asserts expr) 29 | (let-values ([(result asserted) (with-asserts expr)]) 30 | (check-unsat? (verify (assert (apply && asserted)))) 31 | result)) 32 | 33 | (define-syntax-rule (check-asserts-only expr) 34 | (let ([asserted (with-asserts-only expr)]) 35 | (check-unsat? (verify (assert (apply && asserted)))) 36 | (void))) 37 | 38 | 39 | ; random testing 40 | 41 | ; generate a random value from a symbolic expression 42 | (define (arbitrary expr) 43 | (define syms (symbolics expr)) 44 | (define sol 45 | (for/hash [(v syms)] 46 | (values v (cond 47 | [(boolean? v) 48 | (zero? (random 2))] 49 | [(bv? v) 50 | (apply concat (build-list (bitvector-size (type-of v)) 51 | (lambda (x) (bv (random 2) 1))))])))) 52 | (evaluate expr (sat sol))) 53 | 54 | (define-syntax-rule (quickcheck body ...) 55 | (let ([n (quickcheck-max-success)]) 56 | (for ([i (in-range n)]) 57 | body ...) 58 | (printf "+++ OK, passed ~a tests.\n" n))) 59 | -------------------------------------------------------------------------------- /include/sys/ctype.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | /* 6 | * NOTE! This ctype does not handle EOF like the standard C 7 | * library is required to. 8 | */ 9 | 10 | #define _U 0x01 /* upper */ 11 | #define _L 0x02 /* lower */ 12 | #define _D 0x04 /* digit */ 13 | #define _C 0x08 /* cntrl */ 14 | #define _P 0x10 /* punct */ 15 | #define _S 0x20 /* white space (space/lf/tab) */ 16 | #define _X 0x40 /* hex digit */ 17 | #define _SP 0x80 /* hard space (0x20) */ 18 | 19 | extern const unsigned char _ctype[]; 20 | 21 | #define __ismask(x) (_ctype[(int)(unsigned char)(x)]) 22 | 23 | #define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) 24 | #define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) 25 | #define iscntrl(c) ((__ismask(c)&(_C)) != 0) 26 | static inline int isdigit(int c) 27 | { 28 | return '0' <= c && c <= '9'; 29 | } 30 | #define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) 31 | #define islower(c) ((__ismask(c)&(_L)) != 0) 32 | #define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) 33 | #define ispunct(c) ((__ismask(c)&(_P)) != 0) 34 | /* Note: isspace() must return false for %NUL-terminator */ 35 | #define isspace(c) ((__ismask(c)&(_S)) != 0) 36 | #define isupper(c) ((__ismask(c)&(_U)) != 0) 37 | #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) 38 | 39 | #define isascii(c) (((unsigned char)(c))<=0x7f) 40 | #define toascii(c) (((unsigned char)(c))&0x7f) 41 | 42 | static inline unsigned char __tolower(unsigned char c) 43 | { 44 | if (isupper(c)) 45 | c -= 'A'-'a'; 46 | return c; 47 | } 48 | 49 | static inline unsigned char __toupper(unsigned char c) 50 | { 51 | if (islower(c)) 52 | c -= 'a'-'A'; 53 | return c; 54 | } 55 | 56 | #define tolower(c) __tolower(c) 57 | #define toupper(c) __toupper(c) 58 | 59 | /* 60 | * Fast implementation of tolower() for internal usage. Do not use in your 61 | * code. 62 | */ 63 | static inline char _tolower(const char c) 64 | { 65 | return c | 0x20; 66 | } 67 | 68 | /* Fast check for octal digit */ 69 | static inline int isodigit(const char c) 70 | { 71 | return c >= '0' && c <= '7'; 72 | } 73 | -------------------------------------------------------------------------------- /monitor/verif/spec.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette 2 | 3 | (require 4 | (prefix-in constants: "generated/monitor/verif/asm-offsets.rkt")) 5 | 6 | (provide (all-defined-out)) 7 | 8 | (struct state (retval current-user dict) 9 | #:transparent 10 | #:mutable 11 | #:methods gen:equal+hash 12 | [(define (equal-proc s t equal?-recur) (state-equal? s t)) 13 | (define (hash-proc s hash-recur) 1) 14 | (define (hash2-proc s hash2-recur) 2)]) 15 | 16 | ; Debuging function to print specification state 17 | (define (print-state cex s) 18 | (printf " retval: ~v\n" (bitvector->natural (evaluate (state-retval s) cex))) 19 | (printf " current-user: ~v\n" (bitvector->natural (evaluate (state-current-user s) cex))) 20 | (printf " dict: ~v\n" 21 | (for/list ([i (range constants:MAXUSER)]) 22 | (bitvector->natural (evaluate ((state-dict s) (bv i 64)) cex))))) 23 | 24 | (define (state-equal? s t) 25 | (define-symbolic* idx (bitvector 64)) 26 | (&& 27 | (equal? (state-retval s) (state-retval t)) 28 | (equal? (state-current-user s) (state-current-user t)) 29 | (forall (list idx) 30 | (=> (bvult idx (bv constants:MAXUSER 64)) 31 | (equal? ((state-dict s) idx) ((state-dict t) idx)))))) 32 | 33 | (define (update-dict! st key value) 34 | (define old-dict (state-dict st)) 35 | (set-state-dict! st (lambda (idx) (if (equal? key idx) value (old-dict idx))))) 36 | 37 | (define (fresh-state) 38 | (define-symbolic* retval (bitvector 64)) 39 | (define-symbolic* current-user (bitvector 64)) 40 | (define-symbolic* dictionary (~> (bitvector 64) (bitvector 64))) 41 | (state retval current-user dictionary)) 42 | 43 | (define (sys-dict-get st) 44 | (define current-user (state-current-user st)) 45 | (define dict (state-dict st)) 46 | 47 | (if (bvult current-user (bv constants:MAXUSER 64)) 48 | (set-state-retval! st (dict current-user)) 49 | (set-state-retval! st (bv -1 64)))) 50 | 51 | 52 | (define (sys-dict-set st value) 53 | (define current-user (state-current-user st)) 54 | 55 | (if (bvult current-user (bv constants:MAXUSER 64)) 56 | (begin 57 | (update-dict! st current-user value) 58 | (set-state-retval! st (bv 0 64))) 59 | (set-state-retval! st (bv -1 64)))) 60 | 61 | (define (sys-change-user st newuser) 62 | (set-state-current-user! st newuser) 63 | (set-state-retval! st (bv 0 64))) 64 | -------------------------------------------------------------------------------- /serval/serval/lib/debug.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette 2 | 3 | (provide (all-defined-out)) 4 | 5 | (define target-spectre (make-parameter #f)) 6 | 7 | (define (concrete?) 8 | (&& (null? (asserts)) 9 | (equal? #t (pc)))) 10 | 11 | (define assert-db (make-hash)) 12 | 13 | (define (bug-clear!) (hash-clear! assert-db)) 14 | 15 | (define (bug-format data sol) 16 | (define key (dict-ref data 'key #f)) 17 | (define location (dict-ref data 'location #f)) 18 | (define message ((dict-ref data 'message (thunk* #f)) sol)) 19 | (define (fmt v) (if v (~a v) "")) 20 | (string-join (map fmt (list key location message)) ": ")) 21 | 22 | ; bug-on is for bugs in the program under symbolic evaluation. 23 | ; Verification will fail unless the bug is not reachable. 24 | (define (bug-on x #:key [key #f] #:dbg [dbg #f] #:msg [msg "Unknown assert"]) 25 | (define msg-proc (if (procedure? msg) msg (thunk* msg))) 26 | (define expr (=> (pc) (! x))) 27 | (define data `((key . ,key) 28 | (location . ,dbg) 29 | (message . ,msg-proc))) 30 | (when x 31 | (hash-set! assert-db expr (cons data (hash-ref! assert-db expr null)))) 32 | ; show a concrete message if this is trivially true 33 | (define msg-str (bug-format data (sat))) 34 | (assert (not x) msg-str)) 35 | 36 | (define (bug-ref expr #:key [key #f]) 37 | (hash-ref assert-db expr null)) 38 | 39 | (define (simplify-asserts asserted) 40 | (filter-not (lambda (expr) (unsat? (verify (assert expr)))) asserted)) 41 | 42 | ; spectre 43 | 44 | ; For spectre checks we need to hide path conditions from Rosette to 45 | ; mimic speculative execution. Use parameter as it's not lifted by 46 | ; Rosette; this will omit path conditions when using spectre-bug-on. 47 | 48 | (define spectre-asserts (make-parameter null)) 49 | 50 | (define (spectre-bug-on expr #:msg [msg #f] #:dbg [dbg #f]) 51 | (when (target-spectre) 52 | (spectre-asserts (cons (lambda () (bug-on expr #:msg msg #:dbg dbg)) (spectre-asserts))))) 53 | 54 | (define-syntax-rule (with-spectre-asserts expr) 55 | (with-asserts 56 | (begin0 57 | (begin expr) 58 | (for-each (lambda (f) (f)) (spectre-asserts)) 59 | (spectre-asserts null)))) 60 | 61 | (define-syntax-rule (with-spectre-asserts-only form) 62 | (let-values ([(out asserts) (with-spectre-asserts form)]) 63 | asserts)) 64 | -------------------------------------------------------------------------------- /bios/sifive.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define UART_TXFIFO 0 8 | #define UART_RXFIFO 4 9 | #define UART_TXCTRL 8 10 | #define UART_RXCTRL 12 11 | 12 | struct uart_port { 13 | void __iomem *membase; 14 | struct console console; 15 | }; 16 | 17 | static int uart_in(struct uart_port *port, int offset) 18 | { 19 | return readl(port->membase + offset); 20 | } 21 | 22 | static void uart_out(struct uart_port *port, int offset, uint8_t value) 23 | { 24 | writel(value, port->membase + offset); 25 | } 26 | 27 | static int uart_getchar(struct console *con) 28 | { 29 | struct uart_port *port = container_of(con, struct uart_port, console); 30 | int c; 31 | 32 | c = uart_in(port, UART_RXFIFO); 33 | if (c < 0) 34 | return -EAGAIN; 35 | 36 | return c; 37 | } 38 | 39 | static void uart_putchar(struct console *con, int c) 40 | { 41 | struct uart_port *port = container_of(con, struct uart_port, console); 42 | 43 | while (uart_in(port, UART_TXFIFO) < 0) 44 | cpu_relax(); 45 | 46 | uart_out(port, UART_TXFIFO, c); 47 | } 48 | 49 | static void init_port(struct uart_port *port) 50 | { 51 | uart_out(port, UART_TXCTRL, 1); 52 | uart_out(port, UART_RXCTRL, 1); 53 | } 54 | 55 | void sifive_init(void) 56 | { 57 | /* there are two serial ports on hifive boards */ 58 | static struct uart_port ports[2]; 59 | struct device_node *np = NULL; 60 | size_t i; 61 | 62 | for (i = 0; i < ARRAY_SIZE(ports); ++i) { 63 | struct uart_port *port = &ports[i]; 64 | const be32_t *cell; 65 | 66 | np = of_find_compatible_node(np, NULL, "sifive,uart0"); 67 | if (!np) 68 | break; 69 | cell = of_get_property(np, "reg", NULL); 70 | if (!cell) 71 | continue; 72 | 73 | port->membase = (void *)(uintptr_t)of_read_number(cell, of_n_addr_cells(np)); 74 | port->console.getchar = uart_getchar; 75 | port->console.putchar = uart_putchar; 76 | init_port(port); 77 | register_console(&port->console); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /serval/serval/spec/ni.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette 2 | 3 | (require serval/lib/unittest) 4 | 5 | (provide (all-defined-out)) 6 | 7 | (define 8 | (check-local-respect 9 | #:state-init init-state 10 | #:state-copy state-copy 11 | #:invariants inv 12 | #:dom dom 13 | #:u u 14 | #:unwinding unwinding 15 | #:flowsto flowsto 16 | action 17 | spec 18 | [args null]) 19 | 20 | (define s (init-state)) 21 | (define old-s (state-copy s)) 22 | 23 | (apply spec s args) 24 | 25 | (for/all ([doma (dom action old-s) #:exhaustive]) 26 | (for/all ([u u #:exhaustive]) (begin 27 | 28 | (define pre (&& (inv old-s) 29 | (! (flowsto doma u)))) 30 | 31 | (define post (check-asserts (unwinding u old-s s))) 32 | 33 | (check-equal? (asserts) null) 34 | (check-unsat? (verify (assert (=> pre post)))))))) 35 | 36 | (define 37 | (check-step-consistency 38 | #:state-init init-state 39 | #:state-copy state-copy 40 | #:unwinding unwinding 41 | spec 42 | [args null]) 43 | (define s (init-state)) 44 | (define t (init-state)) 45 | (define old-s (state-copy s)) 46 | (define old-t (state-copy t)) 47 | 48 | (apply spec s args) 49 | (apply spec t args) 50 | 51 | (define pre (unwinding old-s old-t)) 52 | (define post (unwinding s t)) 53 | 54 | (check-equal? (asserts) null) 55 | (check-unsat? (verify (assert (=> pre post))))) 56 | 57 | (define 58 | (check-weak-step-consistency 59 | #:state-init init-state 60 | #:state-copy state-copy 61 | #:invariants inv 62 | #:dom dom 63 | #:u u 64 | #:unwinding unwinding 65 | #:flowsto flowsto 66 | action 67 | spec 68 | [args null]) 69 | 70 | (define s (init-state)) 71 | (define t (init-state)) 72 | (define old-s (state-copy s)) 73 | (define old-t (state-copy t)) 74 | 75 | (apply spec s args) 76 | (apply spec t args) 77 | 78 | (for/all ([u u #:exhaustive]) 79 | (for/all ([doma (dom action old-s) #:exhaustive]) (begin 80 | 81 | (define pre (&& (inv old-s) 82 | (inv old-t) 83 | (unwinding u old-s old-t) 84 | (flowsto doma u) 85 | (unwinding doma old-s old-t) 86 | )) 87 | 88 | (define post (check-asserts (unwinding u s t))) 89 | 90 | (check-equal? (asserts) null) 91 | (check-unsat? (verify (assert (=> pre post)))))))) 92 | -------------------------------------------------------------------------------- /monitor/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | noreturn static void supervisor_init(unsigned int, phys_addr_t); 11 | extern char _payload_start[], _payload_end[]; 12 | 13 | noreturn void main(unsigned int hartid, phys_addr_t dtb) 14 | { 15 | extern void init_dict(void); 16 | 17 | init_dict(); 18 | mcall_init(dtb); 19 | pr_info("Hello from ToyMon!\n"); 20 | supervisor_init(hartid, dtb); 21 | } 22 | 23 | 24 | noreturn static void supervisor_init(unsigned int hartid, phys_addr_t dtb) 25 | { 26 | struct pt_regs regs = { 27 | .a0 = hartid, 28 | .a1 = dtb, 29 | }; 30 | 31 | /* mret to S-mode */ 32 | csr_write(mstatus, SR_MPP_S); 33 | 34 | /* entry to supervisor_main */ 35 | csr_write(mepc, (uintptr_t) _payload_start); 36 | 37 | /* PMP to allow S-mode access only to supervisor payload */ 38 | csr_write(pmpcfg0, 0); 39 | csr_write(pmpcfg2, 0); 40 | /* NB: the -1 here is because of a bug in QEMU's PMP implementation 41 | when S-mode tries to execute the first instruction in a PMP region */ 42 | pmpaddr_write(pmpaddr0, (uintptr_t) _payload_start - 1); 43 | pmpaddr_write(pmpaddr1, (uintptr_t) _payload_end); 44 | pmpcfg_write(pmp1cfg, PMPCFG_A_TOR | PMPCFG_R | PMPCFG_W | PMPCFG_X); 45 | local_flush_tlb_all(); 46 | 47 | /* "return" to supervisor */ 48 | mret_with_regs(®s); 49 | } 50 | 51 | extern long sys_dict_get(void); 52 | extern long sys_dict_set(long); 53 | extern long sys_change_user(long); 54 | 55 | void do_trap_ecall_s(struct pt_regs *regs) 56 | { 57 | long nr = regs->a7, r = -ENOSYS; 58 | 59 | csr_write(mepc, csr_read(mepc) + 4); 60 | 61 | switch (nr) { 62 | case SBI_FIRST ... SBI_LAST: 63 | r = do_mcall(regs); 64 | break; 65 | case __NR_dict_get: 66 | r = sys_dict_get(); 67 | break; 68 | case __NR_dict_set: 69 | r = sys_dict_set(regs->a0); 70 | break; 71 | case __NR_change_user: 72 | r = sys_change_user(regs->a0); 73 | break; 74 | } 75 | 76 | regs->a0 = r; 77 | } 78 | -------------------------------------------------------------------------------- /include/io/nospec.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // Copyright(c) 2018 Linus Torvalds. All rights reserved. 3 | // Copyright(c) 2018 Alexei Starovoitov. All rights reserved. 4 | // Copyright(c) 2018 Intel Corporation. All rights reserved. 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | /** 13 | * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise 14 | * @index: array element index 15 | * @size: number of elements in array 16 | * 17 | * When @index is out of bounds (@index >= @size), the sign bit will be 18 | * set. Extend the sign bit to all bits and invert, giving a result of 19 | * zero for an out of bounds index, or ~0 if within bounds [0, @size). 20 | */ 21 | static inline unsigned long array_index_mask_nospec(unsigned long index, 22 | unsigned long size) 23 | { 24 | /* 25 | * Always calculate and emit the mask even if the compiler 26 | * thinks the mask is not needed. The compiler does not take 27 | * into account the value of @index under speculation. 28 | */ 29 | OPTIMIZER_HIDE_VAR(index); 30 | return ~(long)(index | (size - 1UL - index)) >> (BITS_PER_LONG - 1); 31 | } 32 | 33 | /* 34 | * array_index_nospec - sanitize an array index after a bounds check 35 | * 36 | * For a code sequence like: 37 | * 38 | * if (index < size) { 39 | * index = array_index_nospec(index, size); 40 | * val = array[index]; 41 | * } 42 | * 43 | * ...if the CPU speculates past the bounds check then 44 | * array_index_nospec() will clamp the index within the range of [0, 45 | * size). 46 | */ 47 | #define array_index_nospec(index, size) \ 48 | ({ \ 49 | typeof(index) _i = (index); \ 50 | typeof(size) _s = (size); \ 51 | unsigned long _mask = array_index_mask_nospec(_i, _s); \ 52 | \ 53 | BUILD_BUG_ON(sizeof(_i) > sizeof(long)); \ 54 | BUILD_BUG_ON(sizeof(_s) > sizeof(long)); \ 55 | \ 56 | (typeof(_i)) (_i & _mask); \ 57 | }) 58 | 59 | -------------------------------------------------------------------------------- /serval/serval/unicorn/python/unicorn_const.py: -------------------------------------------------------------------------------- 1 | # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.py] 2 | UC_API_MAJOR = 1 3 | 4 | UC_API_MINOR = 0 5 | UC_VERSION_MAJOR = 1 6 | 7 | UC_VERSION_MINOR = 0 8 | UC_VERSION_EXTRA = 2 9 | UC_SECOND_SCALE = 1000000 10 | UC_MILISECOND_SCALE = 1000 11 | UC_ARCH_ARM = 1 12 | UC_ARCH_ARM64 = 2 13 | UC_ARCH_MIPS = 3 14 | UC_ARCH_X86 = 4 15 | UC_ARCH_PPC = 5 16 | UC_ARCH_SPARC = 6 17 | UC_ARCH_M68K = 7 18 | UC_ARCH_MAX = 8 19 | 20 | UC_MODE_LITTLE_ENDIAN = 0 21 | UC_MODE_BIG_ENDIAN = 1073741824 22 | 23 | UC_MODE_ARM = 0 24 | UC_MODE_THUMB = 16 25 | UC_MODE_MCLASS = 32 26 | UC_MODE_V8 = 64 27 | UC_MODE_MICRO = 16 28 | UC_MODE_MIPS3 = 32 29 | UC_MODE_MIPS32R6 = 64 30 | UC_MODE_MIPS32 = 4 31 | UC_MODE_MIPS64 = 8 32 | UC_MODE_16 = 2 33 | UC_MODE_32 = 4 34 | UC_MODE_64 = 8 35 | UC_MODE_PPC32 = 4 36 | UC_MODE_PPC64 = 8 37 | UC_MODE_QPX = 16 38 | UC_MODE_SPARC32 = 4 39 | UC_MODE_SPARC64 = 8 40 | UC_MODE_V9 = 16 41 | 42 | UC_ERR_OK = 0 43 | UC_ERR_NOMEM = 1 44 | UC_ERR_ARCH = 2 45 | UC_ERR_HANDLE = 3 46 | UC_ERR_MODE = 4 47 | UC_ERR_VERSION = 5 48 | UC_ERR_READ_UNMAPPED = 6 49 | UC_ERR_WRITE_UNMAPPED = 7 50 | UC_ERR_FETCH_UNMAPPED = 8 51 | UC_ERR_HOOK = 9 52 | UC_ERR_INSN_INVALID = 10 53 | UC_ERR_MAP = 11 54 | UC_ERR_WRITE_PROT = 12 55 | UC_ERR_READ_PROT = 13 56 | UC_ERR_FETCH_PROT = 14 57 | UC_ERR_ARG = 15 58 | UC_ERR_READ_UNALIGNED = 16 59 | UC_ERR_WRITE_UNALIGNED = 17 60 | UC_ERR_FETCH_UNALIGNED = 18 61 | UC_ERR_HOOK_EXIST = 19 62 | UC_ERR_RESOURCE = 20 63 | UC_ERR_EXCEPTION = 21 64 | UC_MEM_READ = 16 65 | UC_MEM_WRITE = 17 66 | UC_MEM_FETCH = 18 67 | UC_MEM_READ_UNMAPPED = 19 68 | UC_MEM_WRITE_UNMAPPED = 20 69 | UC_MEM_FETCH_UNMAPPED = 21 70 | UC_MEM_WRITE_PROT = 22 71 | UC_MEM_READ_PROT = 23 72 | UC_MEM_FETCH_PROT = 24 73 | UC_MEM_READ_AFTER = 25 74 | UC_HOOK_INTR = 1 75 | UC_HOOK_INSN = 2 76 | UC_HOOK_CODE = 4 77 | UC_HOOK_BLOCK = 8 78 | UC_HOOK_MEM_READ_UNMAPPED = 16 79 | UC_HOOK_MEM_WRITE_UNMAPPED = 32 80 | UC_HOOK_MEM_FETCH_UNMAPPED = 64 81 | UC_HOOK_MEM_READ_PROT = 128 82 | UC_HOOK_MEM_WRITE_PROT = 256 83 | UC_HOOK_MEM_FETCH_PROT = 512 84 | UC_HOOK_MEM_READ = 1024 85 | UC_HOOK_MEM_WRITE = 2048 86 | UC_HOOK_MEM_FETCH = 4096 87 | UC_HOOK_MEM_READ_AFTER = 8192 88 | UC_HOOK_MEM_UNMAPPED = 112 89 | UC_HOOK_MEM_PROT = 896 90 | UC_HOOK_MEM_READ_INVALID = 144 91 | UC_HOOK_MEM_WRITE_INVALID = 288 92 | UC_HOOK_MEM_FETCH_INVALID = 576 93 | UC_HOOK_MEM_INVALID = 1008 94 | UC_HOOK_MEM_VALID = 7168 95 | UC_QUERY_MODE = 1 96 | UC_QUERY_PAGE_SIZE = 2 97 | UC_QUERY_ARCH = 3 98 | 99 | UC_PROT_NONE = 0 100 | UC_PROT_READ = 1 101 | UC_PROT_WRITE = 2 102 | UC_PROT_EXEC = 4 103 | UC_PROT_ALL = 7 104 | -------------------------------------------------------------------------------- /serval/serval/riscv/pmp.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette/safe 2 | 3 | (require 4 | "base.rkt" 5 | "../lib/core.rkt" 6 | (only-in racket/base for/list) 7 | (only-in racket/list range) 8 | (only-in racket/match match) 9 | ) 10 | 11 | (provide pmp-privs) 12 | 13 | (define PMPCFG_A_OFF 0) ; PMPCFG_A_OFF 14 | (define PMPCFG_A_NAPOT 24) ; PMPCFG_A_NAPOT 15 | (define PMPCFG_A_TOR 8) ; PMPCFG_A_TOR 16 | (define PMPCFG_R 1) ; PMPCFG_R 17 | (define PMPCFG_W 2) ; PMPCFG_W 18 | (define PMPCFG_X 4) ; PMPCFG_X 19 | (define PMPCFG_RWX 7) ; PMPCFG_RWX 20 | 21 | (define (pmp-privs cpu ptr size) 22 | (define pmpcfg0 (csr-ref cpu 'pmpcfg0)) 23 | (define pmpcfg2 (csr-ref cpu 'pmpcfg2)) 24 | 25 | (define addrs (map (lambda (r) (csr-ref cpu r)) 26 | '(pmpaddr0 pmpaddr1 pmpaddr2 pmpaddr3 27 | pmpaddr4 pmpaddr5 pmpaddr6 pmpaddr7 28 | pmpaddr8 pmpaddr9 pmpaddr10 pmpaddr11 29 | pmpaddr12 pmpaddr13 pmpaddr14 pmpaddr15))) 30 | (define configs 31 | (list (extract 7 0 pmpcfg0) 32 | (extract 15 8 pmpcfg0) 33 | (extract 23 16 pmpcfg0) 34 | (extract 31 24 pmpcfg0) 35 | (extract 39 32 pmpcfg0) 36 | (extract 47 40 pmpcfg0) 37 | (extract 55 48 pmpcfg0) 38 | (extract 63 56 pmpcfg0) 39 | (extract 7 0 pmpcfg2) 40 | (extract 15 8 pmpcfg2) 41 | (extract 23 16 pmpcfg2) 42 | (extract 31 24 pmpcfg2) 43 | (extract 39 32 pmpcfg2) 44 | (extract 47 40 pmpcfg2) 45 | (extract 55 48 pmpcfg2) 46 | (extract 63 56 pmpcfg2))) 47 | 48 | (define (pmp-privs prev-addr any? cfgs addrs) 49 | (match (cons cfgs addrs) 50 | [(cons (cons cfg cfgs-rest) (cons addr addrs-rest)) 51 | 52 | (define cfg-a (bvand cfg (bv PMPCFG_A_NAPOT 8))) 53 | (define cfg-perm (bvand cfg (bv PMPCFG_RWX 8))) 54 | (define this-addr (bvshl addr (bv 2 64))) 55 | 56 | (cond 57 | [(bveq cfg-a (bv PMPCFG_A_OFF 8)) 58 | (pmp-privs this-addr any? cfgs-rest addrs-rest)] 59 | [(bveq cfg-a (bv PMPCFG_A_TOR 8)) 60 | 61 | (define overlaps (&& (bvugt (bvadd ptr size) prev-addr) 62 | (bvult ptr this-addr))) 63 | (define contains (&& (bvuge ptr prev-addr) 64 | (bvule (bvadd ptr size) this-addr))) 65 | (if overlaps 66 | (if contains cfg-perm (bv 0 8)) 67 | (pmp-privs this-addr #t cfgs-rest addrs-rest))] 68 | [#t (assert #f)])] 69 | [(cons null null) (if (! any?) (bv PMPCFG_RWX 8) (bv 0 8))] 70 | [_ (assert #f)])) 71 | 72 | (pmp-privs (bv 0 64) #f configs addrs)) 73 | -------------------------------------------------------------------------------- /include/sys/printk.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #define LOGLEVEL_EMERG 0 /* system is unusable */ 10 | #define LOGLEVEL_ERR 3 /* error conditions */ 11 | #define LOGLEVEL_WARNING 4 /* warning conditions */ 12 | #define LOGLEVEL_INFO 6 /* informational */ 13 | #define LOGLEVEL_DEBUG 7 /* debug-level messages */ 14 | #define LOGLEVEL_CONT -1 15 | 16 | #define LOGLEVEL_DEFAULT LOGLEVEL_INFO 17 | 18 | #ifndef pr_fmt 19 | #define pr_fmt(fmt) fmt 20 | #endif 21 | 22 | #if IS_ENABLED(CONFIG_VERIFICATION) 23 | 24 | #define pr_emerg printk_unused 25 | #define pr_err printk_unused 26 | #define pr_warn printk_unused 27 | #define pr_info printk_unused 28 | #define pr_debug printk_unused 29 | #define pr_cont printk_unused 30 | 31 | __printf(1, 2) 32 | static inline void __always_unused printk_unused(const char *fmt, ...) {} 33 | 34 | #else /* !IS_ENABLED(CONFIG_VERIFICATION) */ 35 | 36 | #define pr_emerg(fmt, ...) \ 37 | printk(LOGLEVEL_EMERG, pr_fmt(fmt), ##__VA_ARGS__) 38 | #define pr_err(fmt, ...) \ 39 | printk(LOGLEVEL_ERR, pr_fmt(fmt), ##__VA_ARGS__) 40 | #define pr_warn(fmt, ...) \ 41 | printk(LOGLEVEL_WARNING, pr_fmt(fmt), ##__VA_ARGS__) 42 | #define pr_info(fmt, ...) \ 43 | printk(LOGLEVEL_INFO, pr_fmt(fmt), ##__VA_ARGS__) 44 | #define pr_debug(fmt, ...) \ 45 | printk(LOGLEVEL_DEBUG, pr_fmt(fmt), ##__VA_ARGS__) 46 | 47 | #define pr_cont(fmt, ...) \ 48 | printk(LOGLEVEL_CONT, fmt, ##__VA_ARGS__) 49 | 50 | #endif /* IS_ENABLED(CONFIG_VERIFICATION) */ 51 | 52 | /* format specifier macros (inttypes.h is not for freestanding) */ 53 | #if defined(__LP64__) || defined(_LP64) 54 | #define __PRI64_PREFIX "l" 55 | #else 56 | #define __PRI64_PREFIX "ll" 57 | #endif 58 | 59 | #ifndef PRIx64 60 | #define PRIx64 __PRI64_PREFIX "x" 61 | #endif 62 | 63 | #ifndef PRIX64 64 | #define PRIX64 __PRI64_PREFIX "X" 65 | #endif 66 | 67 | #ifndef PRIu64 68 | #define PRIu64 __PRI64_PREFIX "u" 69 | #endif 70 | 71 | #ifndef PRIxPTR 72 | #define PRIxPTR "lx" 73 | #endif 74 | 75 | __printf(2, 0) 76 | int vprintk(int level, const char *fmt, va_list args); 77 | 78 | __printf(2, 3) 79 | int printk(int level, const char *fmt, ...); 80 | 81 | __printf(3, 0) 82 | int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); 83 | 84 | __printf(3, 0) 85 | int vscnprintf(char *buf, size_t size, const char *fmt, va_list args); 86 | 87 | __printf(3, 4) 88 | int scnprintf(char *buf, size_t size, const char *fmt, ...); 89 | -------------------------------------------------------------------------------- /bbl/bbl.lds: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | 3 | ENTRY( reset_vector ) 4 | 5 | SECTIONS 6 | { 7 | 8 | /*--------------------------------------------------------------------*/ 9 | /* Code and read-only segment */ 10 | /*--------------------------------------------------------------------*/ 11 | 12 | /* Begining of code and text segment */ 13 | . = 0x80000000; 14 | _ftext = .; 15 | PROVIDE( eprol = . ); 16 | 17 | .text : 18 | { 19 | *(.text.init) 20 | } 21 | 22 | /* text: Program code section */ 23 | .text : 24 | { 25 | *(.text) 26 | *(.text.*) 27 | *(.gnu.linkonce.t.*) 28 | } 29 | 30 | /* rodata: Read-only data */ 31 | .rodata : 32 | { 33 | *(.rdata) 34 | *(.rodata) 35 | *(.rodata.*) 36 | *(.gnu.linkonce.r.*) 37 | } 38 | 39 | /* End of code and read-only segment */ 40 | PROVIDE( etext = . ); 41 | _etext = .; 42 | 43 | /*--------------------------------------------------------------------*/ 44 | /* HTIF, isolated onto separate page */ 45 | /*--------------------------------------------------------------------*/ 46 | . = ALIGN(0x1000); 47 | .htif : 48 | { 49 | PROVIDE( __htif_base = .); 50 | *(.htif) 51 | } 52 | . = ALIGN(0x1000); 53 | 54 | /*--------------------------------------------------------------------*/ 55 | /* Initialized data segment */ 56 | /*--------------------------------------------------------------------*/ 57 | 58 | /* Start of initialized data segment */ 59 | . = ALIGN(16); 60 | _fdata = .; 61 | 62 | /* data: Writable data */ 63 | .data : 64 | { 65 | *(.data) 66 | *(.data.*) 67 | *(.srodata*) 68 | *(.gnu.linkonce.d.*) 69 | *(.comment) 70 | } 71 | 72 | /* End of initialized data segment */ 73 | . = ALIGN(4); 74 | PROVIDE( edata = . ); 75 | _edata = .; 76 | 77 | /*--------------------------------------------------------------------*/ 78 | /* Uninitialized data segment */ 79 | /*--------------------------------------------------------------------*/ 80 | 81 | /* Start of uninitialized data segment */ 82 | . = .; 83 | _fbss = .; 84 | 85 | /* sbss: Uninitialized writeable small data section */ 86 | . = .; 87 | 88 | /* bss: Uninitialized writeable data section */ 89 | . = .; 90 | _bss_start = .; 91 | .bss : 92 | { 93 | *(.bss) 94 | *(.bss.*) 95 | *(.sbss*) 96 | *(.gnu.linkonce.b.*) 97 | *(COMMON) 98 | } 99 | 100 | .sbi : 101 | { 102 | *(.sbi) 103 | } 104 | 105 | .payload : 106 | { 107 | *(.payload) 108 | } 109 | 110 | _end = .; 111 | } 112 | -------------------------------------------------------------------------------- /bios/uart8250.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* 8 | * DLAB=0 9 | */ 10 | #define UART_RX 0 /* In: Receive buffer */ 11 | #define UART_TX 0 /* Out: Transmit buffer */ 12 | 13 | #define UART_IER 1 /* Out: Interrupt Enable Register */ 14 | #define UART_IER_UUE 0x40 /* UART Unit Enable */ 15 | 16 | #define UART_LSR 5 /* In: Line Status Register */ 17 | #define UART_LSR_TEMT 0x40 /* Transmitter empty */ 18 | #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ 19 | #define UART_LSR_DR 0x01 /* Receiver data ready */ 20 | 21 | struct uart_port { 22 | void __iomem *membase; 23 | struct console console; 24 | }; 25 | 26 | static int uart_in(struct uart_port *port, int offset) 27 | { 28 | return readb(port->membase + offset); 29 | } 30 | 31 | static void uart_out(struct uart_port *port, int offset, uint8_t value) 32 | { 33 | writeb(value, port->membase + offset); 34 | } 35 | 36 | static int uart_getchar(struct console *con) 37 | { 38 | struct uart_port *port = container_of(con, struct uart_port, console); 39 | 40 | if (!(uart_in(port, UART_LSR) & UART_LSR_DR)) 41 | return -EAGAIN; 42 | 43 | return uart_in(port, UART_RX); 44 | } 45 | 46 | static void uart_putchar(struct console *con, int c) 47 | { 48 | struct uart_port *port = container_of(con, struct uart_port, console); 49 | unsigned int status, both_empty = UART_LSR_TEMT|UART_LSR_THRE; 50 | 51 | uart_out(port, UART_TX, c); 52 | 53 | for (;;) { 54 | status = uart_in(port, UART_LSR); 55 | if ((status & both_empty) == both_empty) 56 | break; 57 | cpu_relax(); 58 | } 59 | } 60 | 61 | static void init_port(struct uart_port *port) 62 | { 63 | unsigned int ier; 64 | 65 | /* only mask interrupts; good enough for QEMU */ 66 | ier = uart_in(port, UART_IER); 67 | uart_out(port, UART_IER, ier & UART_IER_UUE); 68 | } 69 | 70 | void uart8250_init(void) 71 | { 72 | static struct uart_port port; 73 | struct device_node *np; 74 | const be32_t *cell; 75 | 76 | np = of_find_node_by_path("/uart"); 77 | if (!np) 78 | return; 79 | 80 | if (!of_device_is_compatible(np, "ns16550a")) 81 | return; 82 | 83 | cell = of_get_property(np, "reg", NULL); 84 | if (!cell) 85 | return; 86 | 87 | port.membase = (void *)(uintptr_t)of_read_number(cell, of_n_addr_cells(np)); 88 | port.console.getchar = uart_getchar; 89 | port.console.putchar = uart_putchar; 90 | init_port(&port); 91 | register_console(&port.console); 92 | } 93 | -------------------------------------------------------------------------------- /bios/mcall.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | phys_addr_t kernel_dtb; 12 | 13 | #if !IS_ENABLED(CONFIG_VERIFICATION) 14 | 15 | void mcall_console_putchar(uint8_t c) 16 | { 17 | console_putchar(c); 18 | } 19 | 20 | long mcall_console_getchar(void) 21 | { 22 | return console_getchar(); 23 | } 24 | 25 | noreturn void mcall_shutdown(void) 26 | { 27 | shutdown(); 28 | } 29 | 30 | void mcall_init(phys_addr_t dtb) 31 | { 32 | size_t size; 33 | 34 | early_init_dt_verify(__va(dtb)); 35 | htif_init(); 36 | uart8250_init(); 37 | sifive_init(); 38 | 39 | early_init_dt_scan_nodes(); 40 | memblock_reserve(__pa(_start), _end - _start); 41 | memblock_reserve(__pa(_payload_start), _payload_end - _payload_start); 42 | 43 | /* 44 | * Make a copy of the DTB so that the kernel can access it. 45 | * Note that the kernel only maps memory from its _start up; 46 | * the kernel can read the new DTB because the DTB is after 47 | * the payload. Also, there is no need to shrink or reserve 48 | * the memory size in the new DTB, as the kernel will not 49 | * access memory before its _start. 50 | */ 51 | size = of_get_flat_dt_size(); 52 | kernel_dtb = memblock_alloc(size, SZ_4K); 53 | of_dt_move(__va(kernel_dtb), size); 54 | 55 | memblock_dump_all(); 56 | } 57 | 58 | #else /* IS_ENABLED(CONFIG_VERIFICATION) */ 59 | 60 | extern volatile uint64_t tohost; 61 | 62 | void mcall_console_putchar(uint8_t c) 63 | { 64 | tohost = (UINT64_C(1) << 56) | (UINT64_C(1) << 48) | c; 65 | } 66 | 67 | long mcall_console_getchar(void) 68 | { 69 | /* FIXME */ 70 | return -ENOSYS; 71 | } 72 | 73 | noreturn void mcall_shutdown(void) 74 | { 75 | tohost = 1; 76 | unreachable(); 77 | } 78 | 79 | void mcall_init(phys_addr_t dtb) 80 | { 81 | } 82 | 83 | #endif /* !IS_ENABLED(CONFIG_VERIFICATION) */ 84 | 85 | long do_mcall(struct pt_regs *regs) 86 | { 87 | unsigned long nr = regs->a7; 88 | long r = -ENOSYS; 89 | 90 | switch (nr) { 91 | default: 92 | pr_warn("unknown sbi call: %lu\n", nr); 93 | break; 94 | case SBI_CONSOLE_PUTCHAR: 95 | mcall_console_putchar(regs->a0); 96 | r = 0; 97 | break; 98 | case SBI_CONSOLE_GETCHAR: 99 | r = mcall_console_getchar(); 100 | break; 101 | case SBI_SHUTDOWN: 102 | mcall_shutdown(); 103 | break; 104 | }; 105 | 106 | return r; 107 | } 108 | -------------------------------------------------------------------------------- /include/asm/entry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | .macro SAVE_REGS scratch:req 9 | /* 10 | * Load kernel sp and save user sp temporarily in scratch first. 11 | * Note that if the trap comes from kernel (which shouldn't happen 12 | * as we assume no recursive traps), sp will be reset to scratch. 13 | */ 14 | csrrw sp, \scratch, sp 15 | 16 | REG_S x1, PT_RA(sp) 17 | /* save x2/sp in the end */ 18 | REG_S x3, PT_GP(sp) 19 | REG_S x4, PT_TP(sp) 20 | REG_S x5, PT_T0(sp) 21 | REG_S x6, PT_T1(sp) 22 | REG_S x7, PT_T2(sp) 23 | REG_S x8, PT_S0(sp) 24 | REG_S x9, PT_S1(sp) 25 | REG_S x10, PT_A0(sp) 26 | REG_S x11, PT_A1(sp) 27 | REG_S x12, PT_A2(sp) 28 | REG_S x13, PT_A3(sp) 29 | REG_S x14, PT_A4(sp) 30 | REG_S x15, PT_A5(sp) 31 | REG_S x16, PT_A6(sp) 32 | REG_S x17, PT_A7(sp) 33 | REG_S x18, PT_S2(sp) 34 | REG_S x19, PT_S3(sp) 35 | REG_S x20, PT_S4(sp) 36 | REG_S x21, PT_S5(sp) 37 | REG_S x22, PT_S6(sp) 38 | REG_S x23, PT_S7(sp) 39 | REG_S x24, PT_S8(sp) 40 | REG_S x25, PT_S9(sp) 41 | REG_S x26, PT_S10(sp) 42 | REG_S x27, PT_S11(sp) 43 | REG_S x28, PT_T3(sp) 44 | REG_S x29, PT_T4(sp) 45 | REG_S x30, PT_T5(sp) 46 | REG_S x31, PT_T6(sp) 47 | 48 | /* restore scratch & save user sp */ 49 | csrrw tp, \scratch, sp 50 | REG_S tp, PT_SP(sp) 51 | .endm 52 | 53 | .macro RESTORE_REGS 54 | REG_L x1, PT_RA(sp) 55 | /* restore x2/sp in the end */ 56 | REG_L x3, PT_GP(sp) 57 | REG_L x4, PT_TP(sp) 58 | REG_L x5, PT_T0(sp) 59 | REG_L x6, PT_T1(sp) 60 | REG_L x7, PT_T2(sp) 61 | REG_L x8, PT_S0(sp) 62 | REG_L x9, PT_S1(sp) 63 | REG_L x10, PT_A0(sp) 64 | REG_L x11, PT_A1(sp) 65 | REG_L x12, PT_A2(sp) 66 | REG_L x13, PT_A3(sp) 67 | REG_L x14, PT_A4(sp) 68 | REG_L x15, PT_A5(sp) 69 | REG_L x16, PT_A6(sp) 70 | REG_L x17, PT_A7(sp) 71 | REG_L x18, PT_S2(sp) 72 | REG_L x19, PT_S3(sp) 73 | REG_L x20, PT_S4(sp) 74 | REG_L x21, PT_S5(sp) 75 | REG_L x22, PT_S6(sp) 76 | REG_L x23, PT_S7(sp) 77 | REG_L x24, PT_S8(sp) 78 | REG_L x25, PT_S9(sp) 79 | REG_L x26, PT_S10(sp) 80 | REG_L x27, PT_S11(sp) 81 | REG_L x28, PT_T3(sp) 82 | REG_L x29, PT_T4(sp) 83 | REG_L x30, PT_T5(sp) 84 | REG_L x31, PT_T6(sp) 85 | 86 | /* restore sp */ 87 | REG_L x2, PT_SP(sp) 88 | .endm 89 | -------------------------------------------------------------------------------- /serval/serval/unicorn/const/unicorn.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (require ffi/unsafe) 4 | 5 | (provide (all-defined-out)) 6 | 7 | (define _uc_arch 8 | (_enum '(arm = 1 9 | arm64 = 2 10 | mips = 3 11 | x86 = 4 12 | ppc = 5 13 | sparc = 6 14 | m68k = 7 15 | max = 8))) 16 | 17 | (define _uc_err 18 | (_enum '(ok = 0 19 | nomem = 1 20 | arch = 2 21 | handle = 3 22 | mode = 4 23 | version = 5 24 | read-unmapped = 6 25 | write-unmapped = 7 26 | fetch-unmapped = 8 27 | hook = 9 28 | insn-invalid = 10 29 | map = 11 30 | write-prot = 12 31 | read-prot = 13 32 | fetch-prot = 14 33 | arg = 15 34 | read-unaligned = 16 35 | write-unaligned = 17 36 | fetch-unaligned = 18 37 | hook-exist = 19 38 | resource = 20 39 | exception = 21))) 40 | 41 | (define _uc_mem 42 | (_enum '(read = 16 43 | write = 17 44 | fetch = 18 45 | read-unmapped = 19 46 | write-unmapped = 20 47 | fetch-unmapped = 21 48 | write-prot = 22 49 | read-prot = 23 50 | fetch-prot = 24 51 | read-after = 25))) 52 | 53 | (define _uc_hook 54 | (_enum '(intr = 1 55 | insn = 2 56 | code = 4 57 | block = 8 58 | mem-read-unmapped = 16 59 | mem-write-unmapped = 32 60 | mem-fetch-unmapped = 64 61 | mem-read-prot = 128 62 | mem-write-prot = 256 63 | mem-fetch-prot = 512 64 | mem-read = 1024 65 | mem-write = 2048 66 | mem-fetch = 4096 67 | mem-read-after = 8192 68 | mem-unmapped = 112 69 | mem-prot = 896 70 | mem-read-invalid = 144 71 | mem-write-invalid = 288 72 | mem-fetch-invalid = 576 73 | mem-invalid = 1008 74 | mem-valid = 7168))) 75 | 76 | (define _uc_mode 77 | (_bitmask '(little-endian = 0 78 | big-endian = 1073741824 79 | arm = 0 80 | thumb = 16 81 | mclass = 32 82 | v8 = 64 83 | micro = 16 84 | mips3 = 32 85 | mips32r6 = 64 86 | mips32 = 4 87 | mips64 = 8 88 | x86-16 = 2 89 | x86-32 = 4 90 | x86-64 = 8 91 | ppc32 = 4 92 | ppc64 = 8 93 | qpx = 16 94 | sparc32 = 4 95 | sparc64 = 8 96 | v9 = 16))) 97 | 98 | (define _uc_prot 99 | (_bitmask '(none = 0 100 | read = 1 101 | write = 2 102 | exec = 4 103 | all = 7))) 104 | -------------------------------------------------------------------------------- /kernel/console.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define LOG_LINE_MAX 1024 8 | 9 | #define for_each_console(con) \ 10 | list_for_each_entry(con, &console_drivers, list) 11 | 12 | static LIST_HEAD(console_drivers); 13 | static int loglevel = LOGLEVEL_DEFAULT; 14 | static int curlevel = LOGLEVEL_DEFAULT; 15 | 16 | static DEFINE_SPINLOCK(console_lock); 17 | 18 | void register_console(struct console *newcon) 19 | { 20 | list_add_tail(&newcon->list, &console_drivers); 21 | } 22 | 23 | int console_getchar(void) 24 | { 25 | struct console *con; 26 | 27 | for_each_console(con) { 28 | int r; 29 | 30 | if (!con->getchar) 31 | continue; 32 | 33 | r = con->getchar(con); 34 | if (r >= 0) 35 | return r; 36 | } 37 | 38 | return -EAGAIN; 39 | } 40 | 41 | void console_putchar(char c) 42 | { 43 | struct console *con; 44 | 45 | for_each_console(con) { 46 | if (con->putchar) { 47 | if (c == '\n') 48 | con->putchar(con, '\r'); 49 | con->putchar(con, c); 50 | } 51 | } 52 | } 53 | 54 | void console_write(const char *s, size_t n) 55 | { 56 | size_t i; 57 | 58 | for (i = 0; i < n; ++i) 59 | console_putchar(s[i]); 60 | } 61 | 62 | __weak size_t pr_timestamp(char *buf, size_t size) 63 | { 64 | return 0; 65 | } 66 | 67 | __weak size_t pr_prefix(char *buf, size_t size) 68 | { 69 | return 0; 70 | } 71 | 72 | __weak size_t pr_suffix(char *buf, size_t size) 73 | { 74 | return 0; 75 | } 76 | 77 | int vprintk(int level, const char *fmt, va_list args) 78 | { 79 | static char buf[LOG_LINE_MAX]; 80 | int thislevel; 81 | size_t len = 0; 82 | 83 | thislevel = (level == LOGLEVEL_CONT) ? curlevel : level; 84 | curlevel = thislevel; 85 | 86 | if (thislevel > loglevel) 87 | goto done; 88 | 89 | len += pr_prefix(buf + len, sizeof(buf) - len); 90 | if (level != LOGLEVEL_CONT) 91 | len += pr_timestamp(buf + len, sizeof(buf) - len); 92 | len += vscnprintf(buf + len, sizeof(buf) - len, fmt, args); 93 | len += pr_suffix(buf + len, sizeof(buf) - len); 94 | 95 | console_write(buf, len); 96 | 97 | done: 98 | return len; 99 | } 100 | 101 | int printk(int level, const char *fmt, ...) 102 | { 103 | va_list args; 104 | int r; 105 | 106 | spin_lock(&console_lock); 107 | 108 | va_start(args, fmt); 109 | r = vprintk(level, fmt, args); 110 | va_end(args); 111 | 112 | spin_unlock(&console_lock); 113 | 114 | return r; 115 | } 116 | -------------------------------------------------------------------------------- /include/sys/string.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #pragma once 3 | 4 | #include 5 | 6 | void *memchr(const void *s, int c, size_t n); 7 | int memcmp(const void *dest, const void *src, size_t count); 8 | size_t memfind64(const uint64_t *s, uint64_t v, size_t n); 9 | void *memset(void *s, int c, size_t count); 10 | void *memset64(uint64_t *s, uint64_t v, size_t n); 11 | void *memmove(void *dest, const void *src, size_t count); 12 | void memzero_explicit(void *s, size_t count); 13 | 14 | /* 15 | * Expand memcpy according to dest/src tyeps to avoid modeling it. 16 | * In all our use cases, the size is constant. 17 | */ 18 | 19 | #define memcpy(dest, src, n) \ 20 | __builtin_choose_expr((sizeof(*(dest)) == 8) && (sizeof(*(src)) == 8), \ 21 | __memcpy_64((dest), (src), (n)), \ 22 | __builtin_choose_expr((sizeof(*(dest)) == 4) && (sizeof(*(src)) == 4), \ 23 | __memcpy_32((dest), (src), (n)), \ 24 | __builtin_choose_expr((sizeof(*(dest)) == 2) && (sizeof(*(src)) == 2), \ 25 | __memcpy_16((dest), (src), (n)), \ 26 | __memcpy_8((dest), (src), (n))))) 27 | 28 | #define __memcpy(n) \ 29 | static inline \ 30 | void *__memcpy_##n(void *dest, const void *src, size_t count) \ 31 | { \ 32 | uint##n##_t *tmp = dest; \ 33 | const uint##n##_t *s = src; \ 34 | \ 35 | if (count % sizeof(uint##n##_t)) \ 36 | return __memcpy_8(dest, src, count); \ 37 | \ 38 | for (; count; count -= sizeof(uint##n##_t)) \ 39 | *tmp++ = *s++; \ 40 | return dest; \ 41 | } 42 | 43 | __memcpy(8) 44 | __memcpy(16) 45 | __memcpy(32) 46 | __memcpy(64) 47 | 48 | #undef __memcpy 49 | 50 | char *strchr(const char *s, int c); 51 | int strcmp(const char *dest, const char *src); 52 | size_t strlen(const char *s); 53 | int strncmp(const char *dest, const char *src, size_t count); 54 | size_t strnlen(const char *s, size_t count); 55 | char *strpbrk(const char *s, const char *accept); 56 | char *strrchr(const char *s, int c); 57 | ssize_t strscpy(char *dest, const char *src, size_t count); 58 | char *strsep(char **stringp, const char *delim); 59 | char *strstr(const char *haystack, const char *needle); 60 | 61 | /** 62 | * kbasename - return the last part of a pathname. 63 | * 64 | * @path: path to extract the filename from. 65 | */ 66 | static inline const char *kbasename(const char *path) 67 | { 68 | const char *tail = strrchr(path, '/'); 69 | return tail ? tail + 1 : path; 70 | } 71 | -------------------------------------------------------------------------------- /scripts/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:19.04 2 | 3 | RUN apt-get update && apt-get install -y \ 4 | autoconf \ 5 | automake \ 6 | autotools-dev \ 7 | bc \ 8 | bc \ 9 | bison \ 10 | build-essential \ 11 | clang \ 12 | cloc \ 13 | curl \ 14 | device-tree-compiler \ 15 | flex \ 16 | gawk \ 17 | gcc \ 18 | gcc-riscv64-linux-gnu \ 19 | git \ 20 | gperf \ 21 | libattr1-dev \ 22 | libcap-dev \ 23 | libexpat-dev \ 24 | libfdt-dev \ 25 | libglib2.0-dev \ 26 | libgmp-dev \ 27 | libmpc-dev \ 28 | libmpfr-dev \ 29 | libncurses-dev \ 30 | libpixman-1-dev \ 31 | libtool \ 32 | libusb-1.0-0-dev \ 33 | llvm \ 34 | make \ 35 | patchutils \ 36 | pkg-config \ 37 | python \ 38 | python-pip \ 39 | python3 \ 40 | texinfo \ 41 | vim \ 42 | wget \ 43 | zlib1g-dev \ 44 | && rm -rf /var/lib/apt/lists/* 45 | 46 | WORKDIR /code 47 | 48 | RUN wget 'https://mirror.racket-lang.org/installers/7.3/racket-7.3-x86_64-linux.sh' && \ 49 | chmod +x ./racket-7.3-x86_64-linux.sh && \ 50 | echo 'yes\n1' | ./racket-7.3-x86_64-linux.sh && \ 51 | rm -f racket-7.3-x86_64-linux.sh 52 | 53 | # Install QEMU 54 | RUN git clone 'https://github.com/qemu/qemu.git' && \ 55 | cd qemu && \ 56 | git checkout 'v4.1.0' && \ 57 | ./configure \ 58 | --disable-gtk \ 59 | --disable-opengl \ 60 | --disable-sdl \ 61 | --disable-vnc \ 62 | --disable-vte \ 63 | --enable-kvm \ 64 | --enable-virtfs \ 65 | --target-list=riscv64-softmmu,riscv32-softmmu,x86_64-softmmu && \ 66 | make -j4 && make install && \ 67 | cd /code && rm -rfv qemu 68 | 69 | # Install Unicorn 70 | RUN git clone 'https://github.com/unicorn-engine/unicorn.git' && \ 71 | cd unicorn && \ 72 | env UNICORN_ARCHS="x86" ./make.sh && \ 73 | env UNICORN_ARCHS="x86" ./make.sh install && \ 74 | cd /code && rm -rfv unicorn 75 | 76 | # Install Rosette 77 | RUN git clone 'https://github.com/emina/rosette.git' && \ 78 | cd rosette && \ 79 | raco pkg install --auto -i --no-setup && raco setup -Dl rosette 80 | 81 | # Install riscv-fesvr 82 | RUN git clone 'https://github.com/riscv/riscv-fesvr.git' && \ 83 | cd riscv-fesvr && \ 84 | mkdir build && \ 85 | cd build && \ 86 | ../configure --prefix=/opt/riscv --target=riscv64-unknown-elf && \ 87 | make -j4 && \ 88 | make install && \ 89 | cd /code && rm -rfv riscv-fesvr 90 | 91 | # Install Spike 92 | RUN git clone 'https://github.com/riscv/riscv-isa-sim.git' && \ 93 | cd riscv-isa-sim && \ 94 | mkdir build && cd build && \ 95 | ../configure --prefix=/opt/riscv --with-fesvr=/opt/riscv && \ 96 | make -j4 && make install && \ 97 | cd /code && rm -rfv riscv-isa-sim && \ 98 | ln -s /opt/riscv/bin/spike /usr/bin/spike 99 | 100 | RUN pip install parcon 101 | 102 | ADD . /serval 103 | 104 | RUN raco pkg install /serval/serval 105 | 106 | # Set /serval to default working directory 107 | WORKDIR /serval -------------------------------------------------------------------------------- /serval/serval/riscv/spec.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette/safe 2 | 3 | (require 4 | "base.rkt") 5 | 6 | (provide (all-defined-out)) 7 | 8 | (struct regs 9 | (ra sp gp tp t0 t1 t2 s0 s1 a0 a1 a2 a3 a4 a5 a6 a7 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 t3 t4 t5 t6 10 | satp scause scounteren sepc sscratch sstatus stvec stval mepc sip sie) 11 | #:methods 12 | gen:equal+hash 13 | [(define (equal-proc a b equal?-recur) 14 | (&& (equal?-recur (regs-ra a) (regs-ra b)) 15 | (equal?-recur (regs-sp a) (regs-sp b)) 16 | (equal?-recur (regs-gp a) (regs-gp b)) 17 | (equal?-recur (regs-tp a) (regs-tp b)) 18 | (equal?-recur (regs-t0 a) (regs-t0 b)) 19 | (equal?-recur (regs-t1 a) (regs-t1 b)) 20 | (equal?-recur (regs-t2 a) (regs-t2 b)) 21 | (equal?-recur (regs-s0 a) (regs-s0 b)) 22 | (equal?-recur (regs-s1 a) (regs-s1 b)) 23 | (equal?-recur (regs-a0 a) (regs-a0 b)) 24 | (equal?-recur (regs-a1 a) (regs-a1 b)) 25 | (equal?-recur (regs-a2 a) (regs-a2 b)) 26 | (equal?-recur (regs-a3 a) (regs-a3 b)) 27 | (equal?-recur (regs-a4 a) (regs-a4 b)) 28 | (equal?-recur (regs-a5 a) (regs-a5 b)) 29 | (equal?-recur (regs-a6 a) (regs-a6 b)) 30 | (equal?-recur (regs-a7 a) (regs-a7 b)) 31 | (equal?-recur (regs-s2 a) (regs-s2 b)) 32 | (equal?-recur (regs-s3 a) (regs-s3 b)) 33 | (equal?-recur (regs-s4 a) (regs-s4 b)) 34 | (equal?-recur (regs-s5 a) (regs-s5 b)) 35 | (equal?-recur (regs-s6 a) (regs-s6 b)) 36 | (equal?-recur (regs-s7 a) (regs-s7 b)) 37 | (equal?-recur (regs-s8 a) (regs-s8 b)) 38 | (equal?-recur (regs-s9 a) (regs-s9 b)) 39 | (equal?-recur (regs-s10 a) (regs-s10 b)) 40 | (equal?-recur (regs-s11 a) (regs-s11 b)) 41 | (equal?-recur (regs-t3 a) (regs-t3 b)) 42 | (equal?-recur (regs-t4 a) (regs-t4 b)) 43 | (equal?-recur (regs-t5 a) (regs-t5 b)) 44 | (equal?-recur (regs-t6 a) (regs-t6 b)) 45 | (equal?-recur (regs-satp a) (regs-satp b)) 46 | (equal?-recur (regs-scause a) (regs-scause b)) 47 | (equal?-recur (regs-scounteren a) (regs-scounteren b)) 48 | (equal?-recur (regs-sepc a) (regs-sepc b)) 49 | (equal?-recur (regs-sscratch a) (regs-sscratch b)) 50 | (equal?-recur (regs-sstatus a) (regs-sstatus b)) 51 | (equal?-recur (regs-stvec a) (regs-stvec b)) 52 | (equal?-recur (regs-stval a) (regs-stval b)) 53 | (equal?-recur (regs-mepc a) (regs-mepc b)) 54 | (equal?-recur (regs-sip a) (regs-sip b)) 55 | (equal?-recur (regs-sie a) (regs-sie b)))) 56 | 57 | (define (hash-proc a hash-recur) 1) 58 | (define (hash2-proc a hash2-recur) 22)]) 59 | 60 | (define (zero-regs) 61 | (regs (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) 62 | (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) 63 | (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) 64 | (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) 65 | (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) (bv 0 64) 66 | (bv 0 64) (bv 0 64))) -------------------------------------------------------------------------------- /include/asm/io.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define __iomem 6 | 7 | static inline uint8_t __raw_readb(const volatile void __iomem *addr) 8 | { 9 | uint8_t val; 10 | 11 | asm volatile("lb %0, 0(%1)" : "=r" (val) : "r" (addr)); 12 | return val; 13 | } 14 | 15 | static inline uint16_t __raw_readw(const volatile void __iomem *addr) 16 | { 17 | uint16_t val; 18 | 19 | asm volatile("lh %0, 0(%1)" : "=r" (val) : "r" (addr)); 20 | return val; 21 | } 22 | 23 | static inline uint32_t __raw_readl(const volatile void __iomem *addr) 24 | { 25 | uint32_t val; 26 | 27 | asm volatile("lw %0, 0(%1)" : "=r" (val) : "r" (addr)); 28 | return val; 29 | } 30 | 31 | static inline uint64_t __raw_readq(const volatile void __iomem *addr) 32 | { 33 | uint64_t val; 34 | 35 | asm volatile("ld %0, 0(%1)" : "=r" (val) : "r" (addr)); 36 | return val; 37 | } 38 | 39 | static inline void __raw_writeb(uint8_t val, volatile void __iomem *addr) 40 | { 41 | asm volatile("sb %0, 0(%1)" : : "r" (val), "r" (addr)); 42 | } 43 | 44 | static inline void __raw_writew(uint16_t val, volatile void __iomem *addr) 45 | { 46 | asm volatile("sh %0, 0(%1)" : : "r" (val), "r" (addr)); 47 | } 48 | 49 | static inline void __raw_writel(uint32_t val, volatile void __iomem *addr) 50 | { 51 | asm volatile("sw %0, 0(%1)" : : "r" (val), "r" (addr)); 52 | } 53 | 54 | static inline void __raw_writeq(uint64_t val, volatile void __iomem *addr) 55 | { 56 | asm volatile("sd %0, 0(%1)" : : "r" (val), "r" (addr)); 57 | } 58 | 59 | /* 60 | * Unordered I/O memory access primitives. These are even more relaxed than 61 | * the relaxed versions, as they don't even order accesses between successive 62 | * operations to the I/O regions. 63 | */ 64 | #define readb_cpu __raw_readb 65 | #define readw_cpu __raw_readw 66 | #define readl_cpu __raw_readl 67 | #define readq_cpu __raw_readq 68 | 69 | #define writeb_cpu __raw_writeb 70 | #define writew_cpu __raw_writew 71 | #define writel_cpu __raw_writel 72 | #define writeq_cpu __raw_writeq 73 | 74 | /* 75 | * I/O memory access primitives. Reads are ordered relative to any 76 | * following Normal memory access. Writes are ordered relative to any prior 77 | * Normal memory access. The memory barriers here are necessary as RISC-V 78 | * doesn't define any ordering between the memory space and the I/O space. 79 | */ 80 | #define __io_br() do {} while (0) 81 | #define __io_ar() asm volatile("fence i,r" : : : "memory"); 82 | #define __io_bw() asm volatile("fence w,o" : : : "memory"); 83 | #define __io_aw() do {} while (0) 84 | 85 | #define readb(c) ({ uint8_t __v; __io_br(); __v = readb_cpu(c); __io_ar(); __v; }) 86 | #define readw(c) ({ uint16_t __v; __io_br(); __v = readw_cpu(c); __io_ar(); __v; }) 87 | #define readl(c) ({ uint32_t __v; __io_br(); __v = readl_cpu(c); __io_ar(); __v; }) 88 | #define readq(c) ({ uint64_t __v; __io_br(); __v = readq_cpu(c); __io_ar(); __v; }) 89 | 90 | #define writeb(v,c) ({ __io_bw(); writeb_cpu((v),(c)); __io_aw(); }) 91 | #define writew(v,c) ({ __io_bw(); writew_cpu((v),(c)); __io_aw(); }) 92 | #define writel(v,c) ({ __io_bw(); writel_cpu((v),(c)); __io_aw(); }) 93 | #define writeq(v,c) ({ __io_bw(); writeq_cpu((v),(c)); __io_aw(); }) 94 | -------------------------------------------------------------------------------- /serval/serval/unicorn.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (require ffi/unsafe 4 | ffi/unsafe/alloc 5 | ffi/unsafe/define 6 | ffi/unsafe/define/conventions 7 | "unicorn/const/unicorn.rkt" 8 | "unicorn/engine.rkt" 9 | "unicorn/x86.rkt") 10 | 11 | (provide (except-out (all-defined-out) 12 | arch->engine check define-unicorn)) 13 | 14 | (define unicorn-lib (ffi-lib "libunicorn")) 15 | 16 | (define-ffi-definer define-unicorn unicorn-lib 17 | #:make-c-id convention:hyphen->underscore) 18 | 19 | (define (arch->engine arch) 20 | (case arch 21 | [(x86) x86-engine])) 22 | 23 | (define-fun-syntax _uc_engine 24 | (syntax-id-rules () 25 | [_ (type: _pointer 26 | pre: (x => (engine-ptr x)))])) 27 | 28 | (define (check v) 29 | (unless (equal? v 'ok) 30 | (error v))) 31 | 32 | (define-unicorn uc-version 33 | (_fun [major : (_ptr o _uint)] 34 | [minor : (_ptr o _uint)] 35 | -> _uint)) 36 | 37 | (define-unicorn uc-arch-supported 38 | (_fun [arch : _uc_arch] 39 | -> _stdbool)) 40 | 41 | (define-unicorn uc-close 42 | (_fun [uc : _uc_engine] 43 | -> [r : _uc_err]) 44 | #:wrap (deallocator)) 45 | 46 | (define-unicorn uc-open 47 | (_fun [arch : _uc_arch] 48 | [mode : _uc_mode] 49 | [ucptr : (_ptr o _pointer)] 50 | -> [r : _uc_err] 51 | -> (begin (check r) ((arch->engine arch) ucptr mode))) 52 | #:wrap (allocator uc-close)) 53 | 54 | (define-unicorn uc-errno 55 | (_fun [uc : _uc_engine] -> _uc_err)) 56 | 57 | (define-unicorn uc-strerror 58 | (_fun [code : _uc_err] -> _string)) 59 | 60 | (define-unicorn uc-reg-write 61 | (_fun [uc : _uc_engine] 62 | [regid : _?] 63 | [_int = (cast regid (engine-reg-enum uc) _int)] 64 | [type : _? = (engine-reg-type uc regid)] 65 | [value : (_ptr i type)] 66 | -> [r : _uc_err] 67 | -> (check r))) 68 | 69 | (define-unicorn uc-reg-read 70 | (_fun [uc : _uc_engine] 71 | [regid : _?] 72 | [_int = (cast regid (engine-reg-enum uc) _int)] 73 | [type : _? = (engine-reg-type uc regid)] 74 | [value : (_ptr io type) = 0] ; use io rather than o to zeroize value 75 | -> [r : _uc_err] 76 | -> (begin (check r) value))) 77 | 78 | (define-unicorn uc-mem-write 79 | (_fun [uc : _uc_engine] 80 | [address : _uint64] 81 | [bytes : _bytes] 82 | [_size = (bytes-length bytes)] 83 | -> [r : _uc_err] 84 | -> (check r))) 85 | 86 | (define-unicorn uc-mem-read 87 | (_fun [uc : _uc_engine] 88 | [address : _uint64] 89 | [bytes : (_bytes o size)] 90 | [size : _size] 91 | -> [r : _uc_err] 92 | -> (begin (check r) bytes))) 93 | 94 | (define-unicorn uc-emu-start 95 | (_fun [uc : _uc_engine] 96 | [begin : _uint64] 97 | [until : _uint64] 98 | [timeout : _uint64] 99 | [count : _size] 100 | -> [r : _uc_err] 101 | -> (check r))) 102 | 103 | (define-unicorn uc-emu-stop 104 | (_fun [uc : _uc_engine] 105 | -> [r : _uc_err] 106 | -> (check r))) 107 | 108 | (define-unicorn uc-mem-map 109 | (_fun [uc : _uc_engine] 110 | [address : _uint64] 111 | [size : _size] 112 | [perm : _uc_prot] 113 | -> [r : _uc_err] 114 | -> (check r))) 115 | -------------------------------------------------------------------------------- /include/asm/sbi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define SBI_SET_TIMER 0 6 | #define SBI_CONSOLE_PUTCHAR 1 7 | #define SBI_CONSOLE_GETCHAR 2 8 | #define SBI_CLEAR_IPI 3 9 | #define SBI_SEND_IPI 4 10 | #define SBI_REMOTE_FENCE_I 5 11 | #define SBI_REMOTE_SFENCE_VMA 6 12 | #define SBI_REMOTE_SFENCE_VMA_ASID 7 13 | #define SBI_SHUTDOWN 8 14 | 15 | #define SBI_FIRST SBI_SET_TIMER 16 | #define SBI_LAST SBI_SHUTDOWN 17 | 18 | #if !defined(__ASSEMBLER__) && defined(__riscv) 19 | 20 | #define SBI_CALL(which, arg0, arg1, arg2, arg3) ({ \ 21 | register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); \ 22 | register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); \ 23 | register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); \ 24 | register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3); \ 25 | register uintptr_t a7 asm ("a7") = (uintptr_t)(which); \ 26 | asm volatile ("ecall" \ 27 | : "+r" (a0) \ 28 | : "r" (a1), "r" (a2), "r" (a3), "r" (a7) \ 29 | : "memory"); \ 30 | a0; \ 31 | }) 32 | 33 | /* Lazy implementations until SBI is finalized */ 34 | #define SBI_CALL_0(which) SBI_CALL(which, 0, 0, 0, 0) 35 | #define SBI_CALL_1(which, arg0) SBI_CALL(which, arg0, 0, 0, 0) 36 | #define SBI_CALL_2(which, arg0, arg1) SBI_CALL(which, arg0, arg1, 0, 0) 37 | #define SBI_CALL_3(which, arg0, arg1, arg2) SBI_CALL(which, arg0, arg1, arg2, 0) 38 | 39 | static inline void sbi_console_putchar(int ch) 40 | { 41 | SBI_CALL_1(SBI_CONSOLE_PUTCHAR, ch); 42 | } 43 | 44 | static inline int sbi_console_getchar(void) 45 | { 46 | return SBI_CALL_0(SBI_CONSOLE_GETCHAR); 47 | } 48 | 49 | static inline void sbi_set_timer(uint64_t stime_value) 50 | { 51 | #if __riscv_xlen == 32 52 | SBI_CALL_2(SBI_SET_TIMER, stime_value, stime_value >> 32); 53 | #else 54 | SBI_CALL_1(SBI_SET_TIMER, stime_value); 55 | #endif 56 | } 57 | 58 | static inline void sbi_shutdown(void) 59 | { 60 | SBI_CALL_0(SBI_SHUTDOWN); 61 | } 62 | 63 | static inline void sbi_clear_ipi(void) 64 | { 65 | SBI_CALL_0(SBI_CLEAR_IPI); 66 | } 67 | 68 | static inline void sbi_send_ipi(const unsigned long *hart_mask) 69 | { 70 | SBI_CALL_1(SBI_SEND_IPI, hart_mask); 71 | } 72 | 73 | static inline void sbi_remote_fence_i(const unsigned long *hart_mask) 74 | { 75 | SBI_CALL_1(SBI_REMOTE_FENCE_I, hart_mask); 76 | } 77 | 78 | static inline void sbi_remote_sfence_vma(const unsigned long *hart_mask, 79 | unsigned long start, 80 | unsigned long size) 81 | { 82 | SBI_CALL_1(SBI_REMOTE_SFENCE_VMA, hart_mask); 83 | } 84 | 85 | static inline void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, 86 | unsigned long start, 87 | unsigned long size, 88 | unsigned long asid) 89 | { 90 | SBI_CALL_1(SBI_REMOTE_SFENCE_VMA_ASID, hart_mask); 91 | } 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /include/sys/memblock.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* 3 | * Logical memory blocks. 4 | * 5 | * Copyright (C) 2001 Peter Bergner, IBM Corp. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #define INIT_MEMBLOCK_REGIONS 128 13 | 14 | struct memblock_region { 15 | phys_addr_t base; 16 | phys_addr_t size; 17 | }; 18 | 19 | struct memblock_type { 20 | unsigned long cnt; /* number of regions */ 21 | unsigned long max; /* size of the allocated array */ 22 | phys_addr_t total_size; /* size of all regions */ 23 | struct memblock_region *regions; 24 | char *name; 25 | }; 26 | 27 | struct memblock { 28 | struct memblock_type memory; 29 | struct memblock_type reserved; 30 | }; 31 | 32 | extern struct memblock memblock; 33 | 34 | int memblock_add(phys_addr_t base, phys_addr_t size); 35 | int memblock_reserve(phys_addr_t base, phys_addr_t size); 36 | phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align); 37 | void memblock_dump_all(void); 38 | 39 | void __next_mem_range_rev(uint64_t *idx, 40 | struct memblock_type *type_a, 41 | struct memblock_type *type_b, 42 | phys_addr_t *out_start, phys_addr_t *out_end); 43 | 44 | #define for_each_memblock(memblock_type, region) \ 45 | for (region = memblock.memblock_type.regions; \ 46 | region < (memblock.memblock_type.regions + memblock.memblock_type.cnt); \ 47 | region++) 48 | 49 | #define for_each_memblock_type(i, memblock_type, rgn) \ 50 | for (i = 0, rgn = &memblock_type->regions[0]; \ 51 | i < memblock_type->cnt; \ 52 | i++, rgn = &memblock_type->regions[i]) 53 | 54 | /** 55 | * for_each_mem_range_rev - reverse iterate through memblock areas from 56 | * type_a and not included in type_b. Or just type_a if type_b is NULL. 57 | * @i: u64 used as loop variable 58 | * @type_a: ptr to memblock_type to iterate 59 | * @type_b: ptr to memblock_type which excludes from the iteration 60 | * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL 61 | * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL 62 | */ 63 | #define for_each_mem_range_rev(i, type_a, type_b, p_start, p_end) \ 64 | for (i = (uint64_t)ULLONG_MAX, \ 65 | __next_mem_range_rev(&i, type_a, type_b, \ 66 | p_start, p_end); \ 67 | i != (uint64_t)ULLONG_MAX; \ 68 | __next_mem_range_rev(&i, type_a, type_b, p_start, p_end)) \ 69 | 70 | /** 71 | * for_each_free_mem_range_reverse - rev-iterate through free memblock areas 72 | * @i: u64 used as loop variable 73 | * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL 74 | * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL 75 | * 76 | * Walks over free (memory && !reserved) areas of memblock in reverse 77 | * order. Available as soon as memblock is initialized. 78 | */ 79 | #define for_each_free_mem_range_reverse(i, p_start, p_end) \ 80 | for_each_mem_range_rev(i, &memblock.memory, &memblock.reserved, \ 81 | p_start, p_end) 82 | -------------------------------------------------------------------------------- /include/asm/pgtable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define PGD_SHIFT 30 8 | #define PGD_SIZE (_AC(1, UL) << PGD_SHIFT) 9 | #define PGD_MASK (~(PGD_SIZE - 1)) 10 | 11 | #define PMD_SHIFT 21 12 | #define PMD_SIZE (_AC(1, UL) << PMD_SHIFT) 13 | #define PMD_MASK (~(PMD_SIZE - 1)) 14 | 15 | #define PTE_SHIFT 12 16 | #define PTE_SIZE (_AC(1, UL) << PTE_SHIFT) 17 | #define PTE_MASK (~(PTE_SIZE - 1)) 18 | 19 | #ifndef __ASSEMBLER__ 20 | 21 | /* 22 | * Use struct definitions to apply C type checking 23 | */ 24 | 25 | #include 26 | 27 | /* Page Global Directory entry */ 28 | typedef struct { 29 | unsigned long pgd; 30 | } pgd_t; 31 | 32 | /* Page Middle Directory entry */ 33 | typedef struct { 34 | unsigned long pmd; 35 | } pmd_t; 36 | 37 | /* Page Table entry */ 38 | typedef struct { 39 | unsigned long pte; 40 | } pte_t; 41 | 42 | typedef struct { 43 | unsigned long pgprot; 44 | } pgprot_t; 45 | 46 | #define pgd_val(x) ((x).pgd) 47 | #define pmd_val(x) ((x).pmd) 48 | #define pte_val(x) ((x).pte) 49 | #define pgprot_val(x) ((x).pgprot) 50 | 51 | #define __pgd(x) ((pgd_t) { (x) }) 52 | #define __pmd(x) ((pmd_t) { (x) }) 53 | #define __pte(x) ((pte_t) { (x) }) 54 | #define __pgprot(x) ((pgprot_t) { (x) }) 55 | 56 | #define PTRS_PER_PGD (PAGE_SIZE / sizeof(pgd_t)) 57 | #define PTRS_PER_PMD (PAGE_SIZE / sizeof(pmd_t)) 58 | #define PTRS_PER_PTE (PAGE_SIZE / sizeof(pte_t)) 59 | 60 | #define pgd_index(addr) (((addr) >> PGD_SHIFT) & (PTRS_PER_PGD - 1)) 61 | #define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) 62 | #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) 63 | 64 | #define _PAGE_KERNEL (_PAGE_READ \ 65 | | _PAGE_WRITE \ 66 | | _PAGE_PRESENT \ 67 | | _PAGE_ACCESSED \ 68 | | _PAGE_DIRTY) 69 | 70 | #define PAGE_KERNEL __pgprot(_PAGE_KERNEL) 71 | #define PAGE_KERNEL_EXEC __pgprot(_PAGE_KERNEL | _PAGE_EXEC) 72 | 73 | static inline pgd_t pfn_pgd(unsigned long pfn, pgprot_t prot) 74 | { 75 | return __pgd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot)); 76 | } 77 | 78 | static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot) 79 | { 80 | return __pmd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot)); 81 | } 82 | 83 | static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) 84 | { 85 | return __pte((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot)); 86 | } 87 | 88 | static inline unsigned long pgd_pfn(pgd_t pgd) 89 | { 90 | return (pgd_val(pgd) >> _PAGE_PFN_SHIFT); 91 | } 92 | 93 | static inline unsigned long pmd_pfn(pmd_t pmd) 94 | { 95 | return (pmd_val(pmd) >> _PAGE_PFN_SHIFT); 96 | } 97 | 98 | static inline unsigned long pte_pfn(pte_t pte) 99 | { 100 | return (pte_val(pte) >> _PAGE_PFN_SHIFT); 101 | } 102 | 103 | static inline int pgd_present(pgd_t pgd) 104 | { 105 | return (pgd_val(pgd) & _PAGE_PRESENT); 106 | } 107 | 108 | static inline int pmd_present(pmd_t pmd) 109 | { 110 | return (pmd_val(pmd) & _PAGE_PRESENT); 111 | } 112 | 113 | static inline int pte_present(pte_t pte) 114 | { 115 | return (pte_val(pte) & _PAGE_PRESENT); 116 | } 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /kernel/libfdt/fdt_addresses.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libfdt - Flat Device Tree manipulation 3 | * Copyright (C) 2014 David Gibson 4 | * 5 | * libfdt is dual licensed: you can use it either under the terms of 6 | * the GPL, or the BSD license, at your option. 7 | * 8 | * a) This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License as 10 | * published by the Free Software Foundation; either version 2 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public 19 | * License along with this library; if not, write to the Free 20 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 21 | * MA 02110-1301 USA 22 | * 23 | * Alternatively, 24 | * 25 | * b) Redistribution and use in source and binary forms, with or 26 | * without modification, are permitted provided that the following 27 | * conditions are met: 28 | * 29 | * 1. Redistributions of source code must retain the above 30 | * copyright notice, this list of conditions and the following 31 | * disclaimer. 32 | * 2. Redistributions in binary form must reproduce the above 33 | * copyright notice, this list of conditions and the following 34 | * disclaimer in the documentation and/or other materials 35 | * provided with the distribution. 36 | * 37 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 38 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 39 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 40 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 41 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 42 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 47 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 48 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 49 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 | */ 51 | #include "libfdt_env.h" 52 | 53 | #include 54 | #include 55 | 56 | #include "libfdt_internal.h" 57 | 58 | int fdt_address_cells(const void *fdt, int nodeoffset) 59 | { 60 | const fdt32_t *ac; 61 | int val; 62 | int len; 63 | 64 | ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len); 65 | if (!ac) 66 | return 2; 67 | 68 | if (len != sizeof(*ac)) 69 | return -FDT_ERR_BADNCELLS; 70 | 71 | val = fdt32_to_cpu(*ac); 72 | if ((val <= 0) || (val > FDT_MAX_NCELLS)) 73 | return -FDT_ERR_BADNCELLS; 74 | 75 | return val; 76 | } 77 | 78 | int fdt_size_cells(const void *fdt, int nodeoffset) 79 | { 80 | const fdt32_t *sc; 81 | int val; 82 | int len; 83 | 84 | sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len); 85 | if (!sc) 86 | return 2; 87 | 88 | if (len != sizeof(*sc)) 89 | return -FDT_ERR_BADNCELLS; 90 | 91 | val = fdt32_to_cpu(*sc); 92 | if ((val < 0) || (val > FDT_MAX_NCELLS)) 93 | return -FDT_ERR_BADNCELLS; 94 | 95 | return val; 96 | } 97 | -------------------------------------------------------------------------------- /serval/serval/python.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette 2 | 3 | (require 4 | (prefix-in core: "lib/core.rkt") 5 | rosette/base/core/polymorphic) 6 | 7 | (provide (all-defined-out)) 8 | 9 | (struct interpreter (func locals stack pc) #:mutable #:transparent) 10 | 11 | (define (make-interpreter func args) 12 | (define nlocals (hash-ref func 'co_nlocals)) 13 | (define locals (vector-append (list->vector args) 14 | (make-vector (- nlocals (length args)) #f))) 15 | (interpreter func locals null 0)) 16 | 17 | ; since Python 3.6, every instruction takes 2 bytes 18 | (define (interpreter-next! interp) 19 | (set-interpreter-pc! interp (+ 2 (interpreter-pc interp)))) 20 | 21 | (define (interpreter-jump! interp pc) 22 | (set-interpreter-pc! interp pc)) 23 | 24 | (define (interpreter-push! interp val) 25 | (set-interpreter-stack! interp (cons val (interpreter-stack interp)))) 26 | 27 | (define (interpreter-pop! interp n) 28 | (define-values (args stack) (split-at (interpreter-stack interp) n)) 29 | (set-interpreter-stack! interp stack) 30 | (reverse args)) 31 | 32 | (define (interpreter-pop1! interp) 33 | (car (interpreter-pop! interp 1))) 34 | 35 | (define (interpret-call args) 36 | (match args 37 | [(list 'BitVecVal val n) (bv val n)] 38 | [(list 'UDiv x y) (bvudiv x y)] 39 | [_ (core:bug-on #t #:dbg pc #:msg (format "unknown call ~e\n" args))])) 40 | 41 | (define (interpret-compare op args) 42 | (when (not (equal? (length args) 2)) 43 | (core:bug-on #t #:dbg pc #:msg (format "unknown compare args ~e\n" args))) 44 | (define lhs (first args)) 45 | (define rhs (second args)) 46 | (case op 47 | [(2) (equal? lhs rhs)] 48 | [else (core:bug-on #t #:dbg pc #:msg (format "unknown compare op ~e\n" op))])) 49 | 50 | (define (interpret-instr interp instr) 51 | (define pc (interpreter-pc interp)) 52 | (define locals (interpreter-locals interp)) 53 | (define func (interpreter-func interp)) 54 | (define consts (hash-ref func 'co_consts)) 55 | (define names (hash-ref func 'co_names)) 56 | (match instr 57 | [(list 'CALL_FUNCTION arg) 58 | (define result (interpret-call (interpreter-pop! interp (add1 arg)))) 59 | (interpreter-push! interp result) 60 | (interpreter-next! interp)] 61 | 62 | [(list 'COMPARE_OP arg) 63 | (define result (interpret-compare arg (interpreter-pop! interp 2))) 64 | (interpreter-push! interp result) 65 | (interpreter-next! interp)] 66 | 67 | [(list 'LOAD_CONST arg) 68 | (interpreter-push! interp (vector-ref consts arg)) 69 | (interpreter-next! interp)] 70 | 71 | [(list 'LOAD_FAST arg) 72 | (interpreter-push! interp (vector-ref locals arg)) 73 | (interpreter-next! interp)] 74 | 75 | [(list 'LOAD_GLOBAL arg) 76 | (interpreter-push! interp (vector-ref names arg)) 77 | (interpreter-next! interp)] 78 | 79 | [(list 'POP_JUMP_IF_FALSE arg) 80 | (if (interpreter-pop1! interp) 81 | (interpreter-next! interp) 82 | (interpreter-jump! interp arg))] 83 | 84 | [_ (core:bug-on #t #:dbg pc #:msg (format "unknown instruction ~e\n" instr))])) 85 | 86 | (define (interpret-program interp) 87 | (define func (interpreter-func interp)) 88 | (define crunched-pc (interpreter-pc interp)) 89 | (for/all ([pc crunched-pc #:exhaustive]) (begin 90 | (core:bug-on (not (hash-has-key? func pc)) 91 | #:msg "interpret-program: no instruction found" #:dbg pc) 92 | (match (hash-ref func pc) 93 | ; no function call support - terminate for now 94 | [(list 'RETURN_VALUE) 95 | (interpreter-pop1! interp)] 96 | 97 | [(list instr ...) 98 | (interpret-instr interp instr) 99 | (interpret-program interp)] 100 | 101 | [any (core:bug-on #t #:dbg pc #:msg (format "Bad instruction format ~e\n" any))])))) 102 | -------------------------------------------------------------------------------- /serval/serval/spec/refcnt.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette/safe 2 | 3 | (provide (all-defined-out)) 4 | 5 | (struct refcnt (cnt perm perm-inv) #:transparent) 6 | 7 | (define (make-havoc-refcnt) 8 | (define-symbolic* cnt (~> (bitvector 64) (bitvector 64))) 9 | (define-symbolic* perm (~> (bitvector 64) (bitvector 64) (bitvector 64))) 10 | (define-symbolic* perm-inv (~> (bitvector 64) (bitvector 64) (bitvector 64))) 11 | (refcnt cnt perm perm-inv)) 12 | 13 | (define (init-refcnt) 14 | (refcnt 15 | (lambda (own) (bv 0 64)) 16 | (lambda (own idx) idx) 17 | (lambda (own obj) obj))) 18 | 19 | (define (incr-refcnt ref owner object) 20 | (define old-cnt (refcnt-cnt ref)) 21 | (define old-perm (refcnt-perm ref)) 22 | (define old-perm-inv (refcnt-perm-inv ref)) 23 | 24 | (define old-owned (old-perm owner (old-cnt owner))) 25 | (define old-idx (old-perm-inv owner object)) 26 | 27 | (define (new-cnt own) 28 | (if (bveq own owner) 29 | (bvadd (bv 1 64) (old-cnt own)) 30 | (old-cnt own))) 31 | 32 | (define (new-perm own idx) 33 | (cond 34 | [(&& (bveq own owner) (bveq idx (old-cnt owner))) object] 35 | [(&& (bveq own owner) (bveq idx old-idx)) old-owned] 36 | [else (old-perm own idx)])) 37 | 38 | (define (new-perm-inv own obj) 39 | (cond 40 | [(&& (bveq own owner) (bveq obj object)) (old-cnt owner)] 41 | [(&& (bveq own owner) (bveq obj old-owned)) old-idx] 42 | [else (old-perm-inv own obj)])) 43 | 44 | (refcnt new-cnt new-perm new-perm-inv)) 45 | 46 | (define (decr-refcnt ref owner object) 47 | (define old-cnt (refcnt-cnt ref)) 48 | (define old-perm (refcnt-perm ref)) 49 | (define old-perm-inv (refcnt-perm-inv ref)) 50 | 51 | (define old-owned (old-perm owner (bvsub (old-cnt owner) (bv 1 64)))) 52 | (define old-idx (old-perm-inv owner object)) 53 | 54 | (define (new-cnt own) 55 | (if (bveq own owner) 56 | (bvsub (old-cnt own) (bv 1 64)) 57 | (old-cnt own))) 58 | 59 | (define (new-perm own idx) 60 | (cond 61 | [(&& (bveq own owner) (bveq idx (bvsub (old-cnt own) (bv 1 64)))) object] 62 | [(&& (bveq own owner) (bveq idx old-idx)) old-owned] 63 | [else (old-perm own idx)])) 64 | 65 | (define (new-perm-inv own obj) 66 | (cond 67 | [(&& (bveq own owner) (bveq obj object)) (bvsub (old-cnt own) (bv 1 64))] 68 | [(&& (bveq own owner) (bveq obj old-owned)) old-idx] 69 | [else (old-perm-inv own obj)])) 70 | 71 | (refcnt new-cnt new-perm new-perm-inv)) 72 | 73 | (define (refcnt-invariants refcnt owner-valid? object-valid? max-refs owned-by?) 74 | (define cnt (refcnt-cnt refcnt)) 75 | (define perm (refcnt-perm refcnt)) 76 | (define perm-inv (refcnt-perm-inv refcnt)) 77 | 78 | (define-symbolic owner object idx (bitvector 64)) 79 | 80 | (&& 81 | (forall (list owner object) 82 | (=> (&& (owner-valid? owner) (object-valid? object)) 83 | (bvult (perm-inv owner object) max-refs))) 84 | (forall (list owner object idx) 85 | (=> (&& (owner-valid? owner) (object-valid? object) (bvult idx max-refs)) 86 | (&& (bveq idx (perm-inv owner (perm owner idx))) 87 | (bveq (perm owner (perm-inv owner object)) object)))) 88 | 89 | ; The owner is always the first page to allocate and the last one to go 90 | (forall (list owner) 91 | (=> (&& (owner-valid? owner) (owned-by? owner owner)) 92 | (&& (bveq (perm-inv owner owner) (bv 0 64)) 93 | (bveq (perm owner (bv 0 64)) owner)))) 94 | 95 | (forall (list owner object) 96 | (=> (&& (owner-valid? owner) (object-valid? object)) 97 | (<=> (owned-by? owner object) 98 | (bvult (perm-inv owner object) (cnt owner))))) 99 | 100 | (forall (list owner) 101 | (=> (owner-valid? owner) 102 | (bvule (cnt owner) max-refs))) 103 | 104 | )) 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /kernel/libfdt/libfdt_internal.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBFDT_INTERNAL_H 2 | #define LIBFDT_INTERNAL_H 3 | /* 4 | * libfdt - Flat Device Tree manipulation 5 | * Copyright (C) 2006 David Gibson, IBM Corporation. 6 | * 7 | * libfdt is dual licensed: you can use it either under the terms of 8 | * the GPL, or the BSD license, at your option. 9 | * 10 | * a) This library is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License as 12 | * published by the Free Software Foundation; either version 2 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This library is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public 21 | * License along with this library; if not, write to the Free 22 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 23 | * MA 02110-1301 USA 24 | * 25 | * Alternatively, 26 | * 27 | * b) Redistribution and use in source and binary forms, with or 28 | * without modification, are permitted provided that the following 29 | * conditions are met: 30 | * 31 | * 1. Redistributions of source code must retain the above 32 | * copyright notice, this list of conditions and the following 33 | * disclaimer. 34 | * 2. Redistributions in binary form must reproduce the above 35 | * copyright notice, this list of conditions and the following 36 | * disclaimer in the documentation and/or other materials 37 | * provided with the distribution. 38 | * 39 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 40 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 41 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 42 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 43 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 44 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 49 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 50 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 51 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 | */ 53 | #include 54 | 55 | #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) 56 | #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) 57 | 58 | int fdt_ro_probe_(const void *fdt); 59 | #define FDT_RO_PROBE(fdt) \ 60 | { \ 61 | int err_; \ 62 | if ((err_ = fdt_ro_probe_(fdt)) != 0) \ 63 | return err_; \ 64 | } 65 | 66 | int fdt_check_node_offset_(const void *fdt, int offset); 67 | int fdt_check_prop_offset_(const void *fdt, int offset); 68 | const char *fdt_find_string_(const char *strtab, int tabsize, const char *s); 69 | int fdt_node_end_offset_(void *fdt, int nodeoffset); 70 | 71 | static inline const void *fdt_offset_ptr_(const void *fdt, int offset) 72 | { 73 | return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; 74 | } 75 | 76 | static inline void *fdt_offset_ptr_w_(void *fdt, int offset) 77 | { 78 | return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset); 79 | } 80 | 81 | static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n) 82 | { 83 | const struct fdt_reserve_entry *rsv_table = 84 | (const struct fdt_reserve_entry *) 85 | ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); 86 | 87 | return rsv_table + n; 88 | } 89 | static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) 90 | { 91 | return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n); 92 | } 93 | 94 | #define FDT_SW_MAGIC (~FDT_MAGIC) 95 | 96 | #endif /* LIBFDT_INTERNAL_H */ 97 | -------------------------------------------------------------------------------- /include/sys/unaligned/generic.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #pragma once 3 | 4 | /* 5 | * Cause a link-time error if we try an unaligned access other than 6 | * 1,2,4 or 8 bytes long 7 | */ 8 | extern void __bad_unaligned_access_size(void); 9 | 10 | #define __get_unaligned_le(ptr) ((typeof(*(ptr)))({ \ 11 | __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \ 12 | __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)), \ 13 | __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)), \ 14 | __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)), \ 15 | __bad_unaligned_access_size())))); \ 16 | })) 17 | 18 | #define __get_unaligned_be(ptr) ((typeof(*(ptr)))({ \ 19 | __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \ 20 | __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)), \ 21 | __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)), \ 22 | __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)), \ 23 | __bad_unaligned_access_size())))); \ 24 | })) 25 | 26 | #define put_unaligned_le(val, ptr) ({ \ 27 | void *__gu_p = (ptr); \ 28 | switch (sizeof(*(ptr))) { \ 29 | case 1: \ 30 | *(uint8_t *)__gu_p = (uint8_t)(val); \ 31 | break; \ 32 | case 2: \ 33 | put_unaligned_le16((uint16_t)(val), __gu_p); \ 34 | break; \ 35 | case 4: \ 36 | put_unaligned_le32((uint32_t)(val), __gu_p); \ 37 | break; \ 38 | case 8: \ 39 | put_unaligned_le64((uint64_t)(val), __gu_p); \ 40 | break; \ 41 | default: \ 42 | __bad_unaligned_access_size(); \ 43 | break; \ 44 | } \ 45 | (void)0; }) 46 | 47 | #define __put_unaligned_be(val, ptr) ({ \ 48 | void *__gu_p = (ptr); \ 49 | switch (sizeof(*(ptr))) { \ 50 | case 1: \ 51 | *(uint8_t *)__gu_p = (uint8_t)(val); \ 52 | break; \ 53 | case 2: \ 54 | put_unaligned_be16((uint16_t)(val), __gu_p); \ 55 | break; \ 56 | case 4: \ 57 | put_unaligned_be32((uint32_t)(val), __gu_p); \ 58 | break; \ 59 | case 8: \ 60 | put_unaligned_be64((uint64_t)(val), __gu_p); \ 61 | break; \ 62 | default: \ 63 | __bad_unaligned_access_size(); \ 64 | break; \ 65 | } \ 66 | (void)0; }) 67 | -------------------------------------------------------------------------------- /kernel/bitops.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | /* bit search implementation 3 | * 4 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 5 | * Written by David Howells (dhowells@redhat.com) 6 | * 7 | * Copyright (C) 2008 IBM Corporation 8 | * 'find_last_bit' is written by Rusty Russell 9 | * (Inspired by David Howell's find_next_bit implementation) 10 | * 11 | * Rewritten by Yury Norov to decrease 12 | * size and improve performance, 2015. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | /* 20 | * Find the first set bit in a memory region. 21 | */ 22 | unsigned long find_first_bit(const unsigned long *addr, unsigned long size) 23 | { 24 | unsigned long idx; 25 | 26 | for (idx = 0; idx * BITS_PER_LONG < size; idx++) { 27 | if (addr[idx]) 28 | return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size); 29 | } 30 | 31 | return size; 32 | } 33 | 34 | unsigned long find_last_bit(const unsigned long *addr, unsigned long size) 35 | { 36 | if (size) { 37 | unsigned long val = BITMAP_LAST_WORD_MASK(size); 38 | unsigned long idx = (size-1) / BITS_PER_LONG; 39 | 40 | do { 41 | val &= addr[idx]; 42 | if (val) 43 | return idx * BITS_PER_LONG + __fls(val); 44 | 45 | val = ~0ul; 46 | } while (idx--); 47 | } 48 | return size; 49 | } 50 | 51 | /* 52 | * This is a common helper function for find_next_bit, find_next_zero_bit, and 53 | * find_next_and_bit. The differences are: 54 | * - The "invert" argument, which is XORed with each fetched word before 55 | * searching it for one bits. 56 | * - The optional "addr2", which is anded with "addr1" if present. 57 | */ 58 | static inline unsigned long _find_next_bit(const unsigned long *addr1, 59 | const unsigned long *addr2, unsigned long nbits, 60 | unsigned long start, unsigned long invert) 61 | { 62 | unsigned long tmp; 63 | 64 | if (start >= nbits) 65 | return nbits; 66 | 67 | tmp = addr1[start / BITS_PER_LONG]; 68 | if (addr2) 69 | tmp &= addr2[start / BITS_PER_LONG]; 70 | tmp ^= invert; 71 | 72 | /* Handle 1st word. */ 73 | tmp &= BITMAP_FIRST_WORD_MASK(start); 74 | start = rounddown_2(start, BITS_PER_LONG); 75 | 76 | while (!tmp) { 77 | start += BITS_PER_LONG; 78 | if (start >= nbits) 79 | return nbits; 80 | 81 | tmp = addr1[start / BITS_PER_LONG]; 82 | if (addr2) 83 | tmp &= addr2[start / BITS_PER_LONG]; 84 | tmp ^= invert; 85 | } 86 | 87 | return min(start + __ffs(tmp), nbits); 88 | } 89 | 90 | /* 91 | * Find the next set bit in a memory region. 92 | */ 93 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, 94 | unsigned long offset) 95 | { 96 | return _find_next_bit(addr, NULL, size, offset, 0UL); 97 | } 98 | 99 | /* 100 | * Find the first cleared bit in a memory region. 101 | */ 102 | unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) 103 | { 104 | unsigned long idx; 105 | 106 | for (idx = 0; idx * BITS_PER_LONG < size; idx++) { 107 | if (addr[idx] != ~0UL) 108 | return min(idx * BITS_PER_LONG + ffz(addr[idx]), size); 109 | } 110 | 111 | return size; 112 | } 113 | 114 | unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, 115 | unsigned long offset) 116 | { 117 | return _find_next_bit(addr, NULL, size, offset, ~0UL); 118 | } 119 | 120 | unsigned long find_next_and_bit(const unsigned long *addr1, 121 | const unsigned long *addr2, unsigned long size, 122 | unsigned long offset) 123 | { 124 | return _find_next_bit(addr1, addr2, size, offset, 0UL); 125 | } 126 | -------------------------------------------------------------------------------- /kernel/libfdt/fdt_strerror.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libfdt - Flat Device Tree manipulation 3 | * Copyright (C) 2006 David Gibson, IBM Corporation. 4 | * 5 | * libfdt is dual licensed: you can use it either under the terms of 6 | * the GPL, or the BSD license, at your option. 7 | * 8 | * a) This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License as 10 | * published by the Free Software Foundation; either version 2 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public 19 | * License along with this library; if not, write to the Free 20 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 21 | * MA 02110-1301 USA 22 | * 23 | * Alternatively, 24 | * 25 | * b) Redistribution and use in source and binary forms, with or 26 | * without modification, are permitted provided that the following 27 | * conditions are met: 28 | * 29 | * 1. Redistributions of source code must retain the above 30 | * copyright notice, this list of conditions and the following 31 | * disclaimer. 32 | * 2. Redistributions in binary form must reproduce the above 33 | * copyright notice, this list of conditions and the following 34 | * disclaimer in the documentation and/or other materials 35 | * provided with the distribution. 36 | * 37 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 38 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 39 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 40 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 41 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 42 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 47 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 48 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 49 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 | */ 51 | #include "libfdt_env.h" 52 | 53 | #include 54 | #include 55 | 56 | #include "libfdt_internal.h" 57 | 58 | struct fdt_errtabent { 59 | const char *str; 60 | }; 61 | 62 | #define FDT_ERRTABENT(val) \ 63 | [(val)] = { .str = #val, } 64 | 65 | static struct fdt_errtabent fdt_errtable[] = { 66 | FDT_ERRTABENT(FDT_ERR_NOTFOUND), 67 | FDT_ERRTABENT(FDT_ERR_EXISTS), 68 | FDT_ERRTABENT(FDT_ERR_NOSPACE), 69 | 70 | FDT_ERRTABENT(FDT_ERR_BADOFFSET), 71 | FDT_ERRTABENT(FDT_ERR_BADPATH), 72 | FDT_ERRTABENT(FDT_ERR_BADPHANDLE), 73 | FDT_ERRTABENT(FDT_ERR_BADSTATE), 74 | 75 | FDT_ERRTABENT(FDT_ERR_TRUNCATED), 76 | FDT_ERRTABENT(FDT_ERR_BADMAGIC), 77 | FDT_ERRTABENT(FDT_ERR_BADVERSION), 78 | FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), 79 | FDT_ERRTABENT(FDT_ERR_BADLAYOUT), 80 | FDT_ERRTABENT(FDT_ERR_INTERNAL), 81 | FDT_ERRTABENT(FDT_ERR_BADNCELLS), 82 | FDT_ERRTABENT(FDT_ERR_BADVALUE), 83 | FDT_ERRTABENT(FDT_ERR_BADOVERLAY), 84 | FDT_ERRTABENT(FDT_ERR_NOPHANDLES), 85 | }; 86 | #define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) 87 | 88 | const char *fdt_strerror(int errval) 89 | { 90 | if (errval > 0) 91 | return ""; 92 | else if (errval == 0) 93 | return ""; 94 | else if (errval > -FDT_ERRTABSIZE) { 95 | const char *s = fdt_errtable[-errval].str; 96 | 97 | if (s) 98 | return s; 99 | } 100 | 101 | return ""; 102 | } 103 | -------------------------------------------------------------------------------- /serval/serval/sha256.rkt: -------------------------------------------------------------------------------- 1 | #lang rosette 2 | 3 | (require rosette/lib/match 4 | "lib/core.rkt") 5 | 6 | (provide (all-defined-out)) 7 | 8 | (struct sha256 (state count) #:transparent) 9 | 10 | (define (sha256-init) 11 | (define state (list 12 | (bv #x6a09e667 32) 13 | (bv #xbb67ae85 32) 14 | (bv #x3c6ef372 32) 15 | (bv #xa54ff53a 32) 16 | (bv #x510e527f 32) 17 | (bv #x9b05688c 32) 18 | (bv #x1f83d9ab 32) 19 | (bv #x5be0cd19 32))) 20 | (sha256 state (bv 0 32))) 21 | 22 | (define (Ch x y z) 23 | (bvxor z 24 | (bvand x (bvxor y z)))) 25 | 26 | (define (Maj x y z) 27 | (bvor (bvand x y) 28 | (bvand z (bvor x y)))) 29 | 30 | (define (rotate-right x n) 31 | (define w (bv-size n)) 32 | (bvor (bvlshr x n) (bvshl x (bvsub (bv w w) n)))) 33 | 34 | (define (Sigma0 x) 35 | (bvxor (rotate-right x (bv 2 32)) 36 | (rotate-right x (bv 13 32)) 37 | (rotate-right x (bv 22 32)))) 38 | 39 | (define (Sigma1 x) 40 | (bvxor (rotate-right x (bv 6 32)) 41 | (rotate-right x (bv 11 32)) 42 | (rotate-right x (bv 25 32)))) 43 | 44 | (define (Gamma0 x) 45 | (bvxor (rotate-right x (bv 7 32)) 46 | (rotate-right x (bv 18 32)) 47 | (bvlshr x (bv 3 32)))) 48 | 49 | (define (Gamma1 x) 50 | (bvxor (rotate-right x (bv 17 32)) 51 | (rotate-right x (bv 19 32)) 52 | (bvlshr x (bv 10 32)))) 53 | 54 | (define K (vector 55 | #x428a2f98 #x71374491 #xb5c0fbcf #xe9b5dba5 56 | #x3956c25b #x59f111f1 #x923f82a4 #xab1c5ed5 57 | #xd807aa98 #x12835b01 #x243185be #x550c7dc3 58 | #x72be5d74 #x80deb1fe #x9bdc06a7 #xc19bf174 59 | #xe49b69c1 #xefbe4786 #x0fc19dc6 #x240ca1cc 60 | #x2de92c6f #x4a7484aa #x5cb0a9dc #x76f988da 61 | #x983e5152 #xa831c66d #xb00327c8 #xbf597fc7 62 | #xc6e00bf3 #xd5a79147 #x06ca6351 #x14292967 63 | #x27b70a85 #x2e1b2138 #x4d2c6dfc #x53380d13 64 | #x650a7354 #x766a0abb #x81c2c92e #x92722c85 65 | #xa2bfe8a1 #xa81a664b #xc24b8b70 #xc76c51a3 66 | #xd192e819 #xd6990624 #xf40e3585 #x106aa070 67 | #x19a4c116 #x1e376c08 #x2748774c #x34b0bcb5 68 | #x391c0cb3 #x4ed8aa4a #x5b9cca4f #x682e6ff3 69 | #x748f82ee #x78a5636f #x84c87814 #x8cc70208 70 | #x90befffa #xa4506ceb #xbef9a3f7 #xc67178f2)) 71 | 72 | (define (sha256-transform state data) 73 | (define (W i) 74 | (if (< i 16) 75 | (list->bitvector/be (take (drop data (* i 4)) 4)) 76 | (bvadd (Gamma1 (W (- i 2))) 77 | (W (- i 7)) 78 | (Gamma0 (W (- i 15))) 79 | (W (- i 16))))) 80 | (define (RND state k w) 81 | (match state 82 | [(list a b c d e f g h) 83 | (define t0 (bvadd h (Sigma1 e) (Ch e f g) k w)) 84 | (define t1 (bvadd (Sigma0 a) (Maj a b c))) 85 | (list (bvadd t0 t1) a b c (bvadd d t0) e f g)])) 86 | (define (round state n) 87 | (if (< n 0) 88 | state 89 | (RND (round state (- n 1)) (bv (vector-ref K n) 32) (W n)))) 90 | (define s (round state 63)) 91 | (map bvadd state s)) 92 | 93 | 94 | (define (sha256-update ctx data) 95 | (sha256 (sha256-transform (sha256-state ctx) data) 96 | (bvadd (sha256-count ctx) (bv 1 32)))) 97 | 98 | (define (sha256-update-multi ctx data) 99 | (if (empty? data) 100 | ctx 101 | (let-values ([(head tail) (split-at data 64)]) 102 | (sha256-update-multi (sha256-update ctx head) tail)))) 103 | 104 | (define (sha256-update-last ctx data) 105 | (define len (length data)) 106 | (define total (bvadd (bvmul (bv 64 32) (sha256-count ctx)) (bv len 32))) 107 | (define last-data 108 | (append data 109 | (list (bv #x80 8)) 110 | (make-list (- (if (< len 56) 55 (+ 63 56)) len) (bv 0 8)) 111 | (bitvector->list/be (zero-extend (bvshl total (bv 3 32)) (bitvector 64))))) 112 | (sha256-update-multi ctx last-data)) 113 | 114 | (define (sha256-finish ctx) 115 | (flatten (map bitvector->list/be (sha256-state ctx)))) 116 | 117 | (define (sha256-hash data) 118 | (define len (length data)) 119 | (define-values (n r) (quotient/remainder len 64)) 120 | (define-values (head tail) (split-at-right data r)) 121 | (sha256-finish 122 | (sha256-update-last 123 | (sha256-update-multi (sha256-init) head) 124 | tail))) 125 | 126 | ; (sha256-hash (list)) 127 | ; (sha256-hash (make-list 64 (bv (char->integer #\a) 8))) 128 | -------------------------------------------------------------------------------- /serval/serval/llvm/print.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (require racket/format 4 | racket/list 5 | racket/string 6 | (prefix-in core: serval/lib/core) 7 | "base.rkt") 8 | 9 | (provide print-module) 10 | 11 | (define (print-module m [out (current-output-port)]) 12 | (displayln (string-join (list 13 | "; DO NOT MODIFY." 14 | ";" 15 | "; This file was automatically generated." 16 | "" 17 | "#lang rosette" 18 | "" 19 | "(provide (all-defined-out))" 20 | "" 21 | "(require serval/lib/core" 22 | " serval/llvm" 23 | " serval/ubsan)" 24 | "") "\n") out) 25 | 26 | (define globals 27 | (for/list ([gv (module-globals m)]) 28 | (global->string gv))) 29 | (define functions 30 | (for/list ([f (module-functions m)]) 31 | (function->string f))) 32 | (displayln (string-join 33 | (list (string-join globals "\n") 34 | (string-join functions "\n\n")) 35 | "\n\n") out)) 36 | 37 | (define (global->string gv) 38 | (format "(define-global ~a)" gv)) 39 | 40 | (define (function->string f) 41 | (define args 42 | (for/list ([arg (function-arguments f)]) 43 | (format " ~a" (value-name arg)))) 44 | (define hd (format "(define (~a~a)\n" (value-name f) (apply string-append args))) 45 | (define blocks 46 | (for/list ([bb (function-blocks f)]) 47 | (block->string bb))) 48 | (define prologue 49 | (cond 50 | [(null? blocks) 51 | (list " (unreachable)")] 52 | [else 53 | (define vars (flatten 54 | (for/list ([bb (function-blocks f)]) 55 | (filter value-type (basic-block-instructions bb))))) 56 | (append 57 | (list "\n") 58 | (for/list ([v vars]) 59 | (format " (define-value ~a)" (value-name v))) 60 | (list (format " (enter! ~a)" (value-name (first (function-blocks f))))))])) 61 | (string-append hd 62 | (string-join blocks "\n\n") 63 | (string-join prologue "\n") 64 | ")")) 65 | 66 | (define (block->string bb) 67 | (define name (value-name bb)) 68 | (define hd (format "; ~a\n (define-label (~a) #:merge #f\n" name name)) 69 | (define insns 70 | (for/list ([insn (basic-block-instructions bb)]) 71 | (string-append " " (instruction->string insn)))) 72 | (string-append hd (string-join insns "\n") ")")) 73 | 74 | (define (instruction->string insn) 75 | (define body 76 | (string-append 77 | "(" 78 | (opcode->string (instruction-opcode insn)) 79 | (apply string-append 80 | (map (lambda (x) (string-append " " (operand->string x insn))) 81 | (instruction-operands insn))) 82 | (apply string-append 83 | (map (lambda (x) (format " #:~a ~a" (car x) (cdr x))) 84 | (instruction-attributes insn))) 85 | ")")) 86 | (if (value-type insn) 87 | (format "(set! ~a ~a)" (value-name insn) body) 88 | body)) 89 | 90 | (define (opcode->string opcode) 91 | (if (list? opcode) 92 | (string-join (map ~a opcode) "/") 93 | (~a opcode))) 94 | 95 | (define (operand->string v insn) 96 | (define opcode (instruction-opcode insn)) 97 | (cond 98 | [(and (or (equal? opcode 'phi) (equal? opcode 'switch)) (pair? v)) 99 | (format "[~a ~a]" (car v) (cdr v))] 100 | [(list? v) 101 | (string-join 102 | (for/list ([op v]) 103 | (string-append " " (operand->string op insn))) 104 | "" 105 | #:before-first "(list" 106 | #:after-last ")")] 107 | [(array-offset? v) 108 | (format "(array-offset ~a ~a)" (array-offset-index v) (array-offset-size v))] 109 | [(struct-offset? v) 110 | (format "(struct-offset ~a)" (struct-offset-value v))] 111 | [(core:marray? v) 112 | (format "(marray ~a ~a)" (core:marray-length v) (operand->string (core:marray-elements v) insn))] 113 | [(core:mstruct? v) 114 | (format "(mstruct ~a (list~a))" 115 | (core:mstruct-size v) 116 | (string-join 117 | (for/list ([f (core:mstruct-fields v)]) 118 | (format " (mfield ~a ~a ~a)" (core:mfield-name f) (core:mfield-offset f) (operand->string (core:mfield-element f) insn))) 119 | ""))] 120 | [(core:mcell? v) 121 | (format "(mcell ~a)" (core:mcell-size v))] 122 | [(asm? v) 123 | (let ([template (asm-template v)]) 124 | (cond 125 | [(equal? template "") 126 | "'nop"] 127 | [(not (string-contains? template " ")) 128 | (string-append "'" template)] 129 | [else 130 | (~s template)]))] 131 | ; constant expr 132 | [(instruction? v) 133 | (instruction->string v)] 134 | [else 135 | (~s v)])) 136 | --------------------------------------------------------------------------------