diff --git a/Config.uk b/Config.uk new file mode 100644 index 0000000000000000000000000000000000000000..0e5828f5b5420a2cfd6bad2c27ec0804d02e3b54 --- /dev/null +++ b/Config.uk @@ -0,0 +1,28 @@ +menuconfig PLAT_RK3568 + bool "RK3568" + default n + depends on ARCH_ARM_64 + select HAVE_FDT + select LIBFDT + select LIBUKOFW + select LIBTNTTY_NS8250 + select HAVE_INTCTLR + select LIBUKINTCTLR_GICV3 + select ARM_GENERIC_TIMER + help + Create a kernel image that runs on RK3568 + +if (PLAT_RK3568) + +config RAM_BASE_ADDR + hex + prompt "Starting address of kernel stored in ram" + default 0x280000 + +config PLATRK3568_TEST + bool "Enable unit tests" + default n + +endif + + diff --git a/Linker.uk b/Linker.uk new file mode 100644 index 0000000000000000000000000000000000000000..619d75ca784df18a19a6375e754ff23931824720 --- /dev/null +++ b/Linker.uk @@ -0,0 +1,70 @@ +ifeq (arm64,$(CONFIG_UK_ARCH)) +RK3568_LDFLAGS-y += -Wl,--entry=_start +RK3568_LDFLAGS-y += -Wl,-m,aarch64elf +RK3568_LINK_LIBGCC_FLAG := -lgcc +endif + +## +## Link image +## +RK3568_IMAGE := $(BUILD_DIR)/$(CONFIG_UK_NAME)_rk3568-$(CONFIG_UK_ARCH) +RK3568_DEBUG_IMAGE := $(RK3568_IMAGE).dbg + +RK3568_LD_SCRIPT_FLAGS := $(addprefix -Wl$(comma)-dT$(comma),\ + $(UK_PLAT_RK3568_DEF_LDS)) +RK3568_LD_SCRIPT_FLAGS += $(addprefix -Wl$(comma)-T$(comma),\ + $(RK3568_LD_SCRIPT-y) $(EXTRA_LD_SCRIPT-y)) + +$(RK3568_DEBUG_IMAGE): $(RK3568_ALIBS) $(RK3568_ALIBS-y) $(RK3568_OLIBS) $(RK3568_OLIBS-y) \ + $(UK_ALIBS) $(UK_ALIBS-y) $(UK_OLIBS) $(UK_OLIBS-y) \ + $(RK3568_LD_SCRIPT-y) $(EXTRA_LD_SCRIPT-y) \ + $(UK_PLAT_RK3568_DEF_LDS) $(UK_LDEPS) + $(call build_cmd,LD,,$@,\ + $(LD) \ + $(RK3568_LDFLAGS) $(RK3568_LDFLAGS-y) \ + $(RK3568_OLIBS) $(RK3568_OLIBS-y) \ + $(UK_OLIBS) $(UK_OLIBS-y) \ + -Wl$(comma)--start-group \ + $(RK3568_ALIBS) $(RK3568_ALIBS-y) \ + $(UK_ALIBS) $(UK_ALIBS-y) \ + $(RK3568_LINK_LIBGCC_FLAG) \ + -Wl$(comma)--end-group \ + $(LDFLAGS) $(LDFLAGS-y) \ + $(RK3568_LD_SCRIPT_FLAGS) \ + -o $@) +ifeq ($(CONFIG_OPTIMIZE_PIE),y) + $(call build_uk_reloc,$@) +endif + + +$(RK3568_IMAGE): $(RK3568_IMAGE).dbg + $(call build_cmd,SCSTRIP,,$@,\ + $(STRIP) -s \ + $(SECT_STRIP_FLAGS) $(SECT_STRIP_FLAGS-y) \ + $(RK3568_STRIPFLAGS) \ + $< -o $@ 2>&1 | \ + { $(GREP) -Ev \ + "Empty loadable segment detected|section.*lma.*adjusted to.*" || \ + true; }) + $(call build_bootinfo,$@) + + $(call build_cmd,OBJCOPY,,$(RK3568_IMAGE).img,\ + $(OBJCOPY) -O binary $(RK3568_IMAGE) $(BUILD_DIR)/kernel.img) + +$(RK3568_IMAGE).sym: $(RK3568_DEBUG_IMAGE) + $(call build_cmd,NM,,$@, $(NM) -n $< > $@) + +$(RK3568_IMAGE).gz: $(RK3568_IMAGE) + $(call build_cmd,GZ,,$@, $(GZIP) -f -9 -c $< >$@) + +# register images to the build +ifeq ($(CONFIG_PLAT_RK3568),y) +UK_DEBUG_IMAGES-y += $(RK3568_DEBUG_IMAGE) +UK_IMAGES-y += $(RK3568_IMAGE) +UK_IMAGES-$(CONFIG_OPTIMIZE_SYMFILE) += $(RK3568_IMAGE).sym +UK_IMAGES-$(CONFIG_OPTIMIZE_COMPRESS) += $(RK3568_IMAGE).gz +endif + +# ...for cleaning: +LIBRK3568PLAT_CLEAN += $(call build_clean,$(RK3568_DEBUG_IMAGE).bootinfo) +LIBRK3568PLAT_CLEAN += $(call build_clean,$(BUILD_DIR)/kernel.img) \ No newline at end of file diff --git a/Makefile.uk b/Makefile.uk new file mode 100644 index 0000000000000000000000000000000000000000..cd0a72384086c7fb4419204b7862b4f06588daa3 --- /dev/null +++ b/Makefile.uk @@ -0,0 +1,68 @@ +## +## RK3568 platform registration +## +$(eval $(call addplat_s,rk3568,$(CONFIG_PLAT_RK3568))) + +## +## RK3568 platform library registration +## +$(eval $(call addplatlib,rk3568,librk3568plat)) + +## +## Platform library definitions +## +LIBRK3568PLAT_ASINCLUDES-y += -I$(LIBRK3568PLAT_BASE)/include +LIBRK3568PLAT_ASINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include +LIBRK3568PLAT_CINCLUDES-y += -I$(LIBRK3568PLAT_BASE)/include +LIBRK3568PLAT_CINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include +LIBRK3568PLAT_CINCLUDES-y += -I$(UK_PLAT_DRIVERS_BASE)/include + +LIBRK3568PLAT_ASFLAGS += -DRK3568PLAT -DUK_USE_SECTION_SEGMENTS +LIBRK3568PLAT_CFLAGS += -DRK3568PLAT -DUK_USE_SECTION_SEGMENTS +LIBRK3568PLAT_CXXFLAGS += -DRK3568PLAT -DUK_USE_SECTION_SEGMENTS + +## +## Default Linker script +UK_PLAT_RK3568_DEF_LDS := $(UK_PLAT_COMMON_BASE)/arm/link64.lds.S + +## +## Architecture library definitions +## +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/arm/cpu_native.c|common +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/arm/cache64.S|common +ifneq ($(CONFIG_HAVE_SYSTICK),y) +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/arm/generic_timer.c|common +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/arm/time.c|common +endif +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/arm/lcpu.c|arm64_common +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/arm/traps_arm64.c|isr +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/arm/smccc.c|common +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/arm/smccc_invoke.S|common +LIBRK3568PLAT_SRCS-y += $(UK_PLAT_COMMON_BASE)/lcpu.c|common +LIBRK3568PLAT_SRCS-y += $(UK_PLAT_COMMON_BASE)/memory.c|common +LIBRK3568PLAT_SRCS-y += $(UK_PLAT_COMMON_BASE)/tls.c|common +ifeq ($(CONFIG_ENFORCE_W_XOR_X),y) +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/w_xor_x.c|common +endif +LIBRK3568PLAT_SRCS-$(CONFIG_FPSIMD) += $(UK_PLAT_COMMON_BASE)/arm/fp_arm64.c|isr +ifeq ($(CONFIG_PAGING),y) +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/paging.c|isr +endif + +LIBRK3568PLAT_SRCS-y += $(UK_PLAT_COMMON_BASE)/bootinfo.c|common +LIBRK3568PLAT_SRCS-$(CONFIG_LIBFDT) += $(UK_PLAT_COMMON_BASE)/bootinfo_fdt.c|common +LIBRK3568PLAT_SRCS-y += $(UK_PLAT_COMMON_BASE)/bootinfo.lds.S|common +LIBRK3568PLAT_SRCS-y += $(UK_PLAT_COMMON_BASE)/arm/exceptions64.S|arm64_common + +LIBRK3568PLAT_SRCS-y += $(LIBRK3568PLAT_BASE)/start.S|isr +LIBRK3568PLAT_SRCS-y += $(LIBRK3568PLAT_BASE)/console.c +LIBRK3568PLAT_SRCS-y += $(LIBRK3568PLAT_BASE)/gpio.c +LIBRK3568PLAT_SRCS-y += $(LIBRK3568PLAT_BASE)/lcpu.c +LIBRK3568PLAT_SRCS-y += $(LIBRK3568PLAT_BASE)/io.c +LIBRK3568PLAT_SRCS-y += $(LIBRK3568PLAT_BASE)/memory.c +LIBRK3568PLAT_SRCS-y += $(LIBRK3568PLAT_BASE)/setup.c +LIBRK3568PLAT_SRCS-y += $(LIBRK3568PLAT_BASE)/shutdown.c +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBRK3568PLAT_BASE)/mmu.S|isr +LIBRK3568PLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBRK3568PLAT_BASE)/rk3568_bpt64.S|arm +LIBRK3568PLAT_SRCS-y += $(UK_PLAT_RK3568_DEF_LDS) + diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..621d631c28ba9db1b2ba4c4c60b4f1c4f1319f0e --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +RK3568 平台 + +为正常编译一个将在rk3568上运行的应用程序,请在make菜单中选择/取消选择以下选项: + +Architecture Selection --> Architecture --> select: Arrmv8 compatible (64 bits) +Architecture Selection --> Processor Optimization --> select: Generic Armv8 Cortex A55 +Architecture Selection --> deselect: Workaround for Cortex-A73 erratum +Platform Configuration --> select: RK3568 +Build Options --> select: Drop unused functions and data + +编译完成后,在build路径下,可得到内核镜像kernel.img,后续该镜像可用于与设备树文件打包生成FIT镜像boot.img。 + + diff --git a/console.c b/console.c new file mode 100644 index 0000000000000000000000000000000000000000..0cc84df870a70f545df35e5dddd019c6d6f33c15 --- /dev/null +++ b/console.c @@ -0,0 +1,24 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ + +#include +#include + +void _librk3568plat_init_console(void *dtb) +{ + ns8250_console_init(dtb); +} + diff --git a/gpio.c b/gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..97bde844d61ffc0580abad4df2fcd16ce5c28570 --- /dev/null +++ b/gpio.c @@ -0,0 +1,70 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ + +#include +#include +#include +#include + +static uint64_t grf_base_addr; +static uint8_t gpio_initialized; + +/* Macros to access gpio Registers with base address 'grf_base_addr'*/ +#define GPIO_REG(r) ((uint32_t *)(grf_base_addr + (r))) +#define GPIO_REG_READ(r) ioreg_read32(GPIO_REG(r)) +#define GPIO_REG_WRITE(r, v) ioreg_write32(GPIO_REG(r), v) + +/** + * @brief map uart4 to gpio39/40 + * + * @return -1: gpio not initialized, mapping error + * 0: mapping success + */ +static int map_uart_to_gpio(void) +{ + if (!gpio_initialized) { + UK_CRASH("GPIO not initialized!\n"); + return -1; + } + + GPIO_REG_WRITE(GRF_IOFUNC_SEL3, MODE_UART4_SEL); + + GPIO_REG_WRITE(GRF_GPIO3B_IOMUX_L, UART4_ON); + return 0; +} + +void _librk3568plat_init_gpio(void *fdtp) +{ + int grf_offset, rc; + uint64_t addr, size; + + grf_offset = fdt_node_offset_by_compatible(fdtp, -1, + "rockchip,rk3568-grf"); + + if (grf_offset < 0) + UK_CRASH("No General Register Files node found!\n"); + + rc = fdt_get_address(fdtp, grf_offset, 0, &addr, &size); + if (rc < 0) + UK_CRASH("Could not find grf address!\n"); + + grf_base_addr = addr; + gpio_initialized = 1; + + map_uart_to_gpio(); +} + + diff --git a/include/rk3568/console.h b/include/rk3568/console.h new file mode 100644 index 0000000000000000000000000000000000000000..bea9ac59dab735c33a3f4f8cbdc88ab4d306b29b --- /dev/null +++ b/include/rk3568/console.h @@ -0,0 +1,21 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ + +#ifndef __RK3568_CONSOLE_H__ +#define __RK3568_CONSOLE_H__ + +void _librk3568plat_init_console(void *dtb); +#endif /* __RK3568_CONSOLE_H__ */ diff --git a/include/rk3568/gpio.h b/include/rk3568/gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..7916bfdd3d15b75fea4dd440a5e914e211727d91 --- /dev/null +++ b/include/rk3568/gpio.h @@ -0,0 +1,40 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ + +#ifndef __RK3568_GPIO_H__ +#define __RK3568_GPIO_H__ + +/*GPIO Register offset*/ +#define GRF_GPIO3B_IOMUX_L 0x48 +#define GRF_IOFUNC_SEL3 0x30C + +/** map UART4 to GPIO pins39/40 + * bit 31:16 1'b0: Write access disable 1'b1: Write access enable + * bit 10:8 3'h4: UART4_TXM1 + * bit 6:4 3'h4: UART4_RXM1 + */ +#define UART4_ON 0x04400440 + +/** choose uart4 mode + * bit 31:16 1'b0: Write access disable 1'b1: Write access enable + * bit 14: UART4 IO mux selection + * 1'b0:M0 mux solution 1'b1:M1 mux solution + */ +#define MODE_UART4_SEL 0x40004000 + +void _librk3568plat_init_gpio(void *fdtp); + +#endif /* __RK3568_GPIO_H__ */ diff --git a/include/rk3568/sysregs.h b/include/rk3568/sysregs.h new file mode 100644 index 0000000000000000000000000000000000000000..1b346f0fd80bd1db3e9be9c107f2abf67a630320 --- /dev/null +++ b/include/rk3568/sysregs.h @@ -0,0 +1,42 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ + +#ifndef __RK3568_SYSREGS_H__ +#define __RK3568_SYSREGS_H__ + +// *************************************** +// HCR_EL2, Hypervisor Configuration Register (EL2), +// Page 351 of Cortex-A55 Core Techinical-Reference-Manual. +// *************************************** + +#define HCR_EL2_RW (1 << 31) +#define HCR_EL2_IMO (1 << 4) +#define HCR_EL2_SWIO (1 << 1) +#define HCR_EL2_VALUE (HCR_EL2_RW) +#define SCTLR_EL2_VALUE (0) + +// *************************************** +// CPACR_EL1, Architectural Feature Access Control Register. +// *************************************** + +#define CPACR_EL1_FPEN_TRAP_NONE (3 << 20) +#define CPACR_EL1_VALUE (CPACR_EL1_FPEN_TRAP_NONE) + +#define SPSR_MASK_ALL (7 << 6) +#define SPSR_ELxh (5 << 0) +#define SPSR_EL2_VALUE (SPSR_MASK_ALL | SPSR_ELxh) + +#endif /* __RK3568_SYSREGS_H__ */ diff --git a/io.c b/io.c new file mode 100644 index 0000000000000000000000000000000000000000..1ee4e96b4141cfeabe8930a48eada09df4c41d75 --- /dev/null +++ b/io.c @@ -0,0 +1,28 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ + +#include + +/** + * TODO: + * For rk3568 platform, the guest virtual address = guest physical address. + * We may have to reconsider this implementation when condition changes. + */ + +__paddr_t ukplat_virt_to_phys(const __volatile__ void *address) +{ + return (__paddr_t)address; +} diff --git a/lcpu.c b/lcpu.c new file mode 100644 index 0000000000000000000000000000000000000000..4613f84f19f4469cabce462fedd76495249712ba --- /dev/null +++ b/lcpu.c @@ -0,0 +1,60 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ +#include +#include +#include +#include + +void ukplat_lcpu_enable_irq(void) +{ + local_irq_enable(); +} + +void ukplat_lcpu_disable_irq(void) +{ + local_irq_disable(); +} + +void ukplat_lcpu_halt_irq(void) +{ + UK_ASSERT(ukplat_lcpu_irqs_disabled()); + + halt(); +} + +unsigned long ukplat_lcpu_save_irqf(void) +{ + unsigned long flags; + + local_irq_save(flags); + + return flags; +} + +void ukplat_lcpu_restore_irqf(unsigned long flags) +{ + local_irq_restore(flags); +} + +int ukplat_lcpu_irqs_disabled(void) +{ + return irqs_disabled(); +} + +void ukplat_lcpu_irqs_handle_pending(void) +{ + // TODO +} diff --git a/memory.c b/memory.c new file mode 100644 index 0000000000000000000000000000000000000000..3458945e0599c370885397cb36ff64842b295683 --- /dev/null +++ b/memory.c @@ -0,0 +1,20 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ + +int _ukplat_mem_mappings_init(void) +{ + return 0; +} diff --git a/mmu.S b/mmu.S new file mode 100644 index 0000000000000000000000000000000000000000..1399d93f068a79f1d1254f10c9c9ea385a01808c --- /dev/null +++ b/mmu.S @@ -0,0 +1,95 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ + +#include +#include +#include +#include + +ENTRY(start_mmu) + /* Load ttbr0, pagetable starts from _end */ + ur_ldr x27, arm64_bpt_l3_pt0 + msr ttbr0_el1, x27 + isb + + /* Clear the Monitor Debug System control register */ + msr mdscr_el1, xzr + + /* Invalidate the TLB to avoid stale one */ + tlbi vmalle1 + dsb nsh + + ldr x2, =MAIR_INIT_ATTR + msr mair_el1, x2 + +#ifdef CONFIG_PAGING + /* Set up TCR_EL1. The platform must provide a + * configuration compatible with the paging API. + */ + ldr x2, =TCR_INIT_FLAGS + msr tcr_el1, x2 +#else /* CONFIG_PAGING */ + /* Get VIRT_BITS from id_aa64mmfr0_el1.PARange */ + mrs x3, id_aa64mmfr0_el1 + ur_ldr x5, tcr_ips_bits + ubfx x4, x3, #0, #4 + ldrb w4, [x5, x4] + cmp x4, #52 + b.lt setup_tcr_el1 + /* + * We currently do not provide 5-level page tables used in + * implementing 52-bit virtual addresing with 4K granularity, so we + * enforce the max VA to 48-bit for PARange >= 52. + */ + mov x4, #48 +setup_tcr_el1: + /* Setup TCR_EL1_TxSZ(64 - VIRT_BITS) for TCR_INIT_FLAGS */ + mov x5, #64 + sub x5, x5, x4 + mov x4, x5 + lsl x5, x5, #TCR_EL1_T1SZ_SHIFT + orr x5, x4, x5 + ldr x2, =TCR_INIT_FLAGS + orr x2, x5, x2 + bfi x2, x3, #32, #3 + msr tcr_el1, x2 +#endif /* CONFIG_PAGING */ + + /* Setup SCTLR */ + ldr x2, =SCTLR_SET_BITS + ldr x3, =SCTLR_CLEAR_BITS + mrs x1, sctlr_el1 + bic x1, x1, x3 /* Clear the required bits */ + orr x1, x1, x2 /* Set the required bits */ + msr sctlr_el1, x1 + isb + + ret +END(start_mmu) + +ENTRY(clear_bss) +clear_bss_start: + // Clear bss + ldr x1, =__bss_start + ldr w2, =__bss_size +clear_bss_loop: + cbz w2, clear_bss_done + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, clear_bss_loop +clear_bss_done: + ret +END(clear_bss) diff --git a/rk3568_bpt64.S b/rk3568_bpt64.S new file mode 100644 index 0000000000000000000000000000000000000000..380a3cb24eaf8bd3585f49b5043b07a7785783df --- /dev/null +++ b/rk3568_bpt64.S @@ -0,0 +1,118 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ + +#include + +#include +#include +/* ------------------------- Memory Map of rk3568 ----------------------- + * + * 0x0000,0000,0000 - 0x0000,3FFF,FFFF NormalMem: 0-1GiB attr:normal + * 0x0000,F000,0000 - 0x0000,FE8D,FFFF Device: attr:device + * 0x0003,0000,0000 - 0x0003,BFFF,FFFF PCIe: attr:device + * 0x0003,C000,0000 - 0x0003,C0BF,FFFF PCIe_DBI attr:device + * Notice: The page tables below use the Unikraft indexing convention. + */ + +.section .data +.align 4 +.global bpt_unmap_mrd +bpt_unmap_mrd: + .quad 0x000000000200000 /* 4K */ + .quad 0x000000000200000 /* 4k */ + /* Used for struct ukplat_memregion_desc + * Unmapping starts at 4K and ends at 1G + */ + .quad 0x000000003FE00000 + .short 0x0000000000000000 + .short 0x0000000000000010 /* UKPLAT_MEMRF_UNMAP */ + .space 36 + +.global arm64_bpt_l3_pt0 +.align 12 +arm64_bpt_l3_pt0: + ur_pte arm64_bpt_l2_pt0, PTE_TYPE_TABLE + pte_zero , 510 +#if CONFIG_PAGING + ur_pte arm64_bpt_l2_pt511, PTE_TYPE_TABLE +#else /* !CONFIG_PAGING */ + pte_zero , 1 +#endif /* !CONFIG_PAGING */ + + +/* l2_pt0: 1GiB / entry + * 0x0000,0000,0000 - 0x0000,3FFF,FFFF RAM + * 0x0000,4000,0000 - 0x0000,BFFF,FFFF hole + * 0x0000,C000,0000 - 0x0000,FFFF,FFFF Device + * 0x0001,0000,0000 - 0x0002,FFFF,FFFF hole + * 0x0003,0000,0000 - 0x0003,BFFF,FFFF PCIe (PCIe2x1_S PCIe3x1_S PCIe3x2_S) + * 0x0003,C000,0000 - 0x0003,FFFF,FFFF Device (PCIE_DBI) +*/ +.align 12 +arm64_bpt_l2_pt0: + ur_pte arm64_bpt_l1_pt0, PTE_TYPE_TABLE + pte_zero ,2 + ur_pte arm64_bpt_l1_pt3, PTE_TYPE_TABLE + pte_zero ,8 + pte_fill 0x300000000, 3, 2, PTE_BLOCK_DEVICE_nGnRnE + ur_pte arm64_bpt_l1_pt15, PTE_TYPE_TABLE + pte_zero ,496 + +#if CONFIG_PAGING +/* l2_pt511: 1GiB / entry + * + * 0x0000ff8000000000 - 0x0000ffffffffffff Direct-mapped + */ +.align 12 +arm64_bpt_l2_pt511: + pte_fill 0x0000000000000000, 1, 2, PTE_BLOCK_NORMAL_RW + pte_zero , 511 +#endif /* CONFIG_PAGING */ + + +/* l1_pt0: 2MiB / entry + * 0x0000,0000 - 0x001F,FFFF hole + * 0x0020,0000 - 0x083F,FFFF RAM + * 0x0840,0000 - 0x093F,FFFF hole + * 0x0940,0000 - 0x3FFF,FFFF RAM +*/ +.align 12 +arm64_bpt_l1_pt0: + pte_zero , 1 + pte_fill 0x200000, 65, 1, PTE_BLOCK_NORMAL_RWX + pte_zero , 8 + pte_fill 0x9400000, 438, 1, PTE_BLOCK_NORMAL_RWX + +/* l1_pt3: 2MiB / entry + * 0xC000,0000 - 0xEFFF,FFFF hole + * 0xF000,0000 - 0xFE8D,FFFF device + * 0xFE8E,0000 - 0xFFFF,FFFF hole +*/ +.align 12 +arm64_bpt_l1_pt3: + pte_zero ,384 + pte_fill 0x000000F0000000, 116, 1, PTE_BLOCK_DEVICE_nGnRnE + pte_zero ,12 + + +/* l1_pt15: 2MiB / entry + * 0x3,C000,0000 - 0x3,C0BF,FFFF + * PCIe (PCIe2x1_DBI PCIe3x1_DBI PCIe3x2_DBI) +*/ +.align 12 +arm64_bpt_l1_pt15: + pte_fill 0x3C0000000, 6, 1, PTE_BLOCK_DEVICE_nGnRnE + pte_zero ,506 diff --git a/setup.c b/setup.c new file mode 100644 index 0000000000000000000000000000000000000000..41c8787ac8b2fb7683c0cec6b9d723aa47286616 --- /dev/null +++ b/setup.c @@ -0,0 +1,184 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +smccc_conduit_fn_t smccc_psci_call; + +static char *cmdline; +static __sz cmdline_len; + +static inline int cmdline_init(struct ukplat_bootinfo *bi) +{ + char *cmdl; + + if (bi->cmdline_len) { + cmdl = (char *)bi->cmdline; + cmdline_len = bi->cmdline_len; + } else { + cmdl = CONFIG_UK_NAME; + cmdline_len = sizeof(CONFIG_UK_NAME) - 1; + } + + /* TODO: Only extract what we need before passing to application. */ + + /* This is not the original command-line, but one that will be thrashed + * by `ukplat_entry_argp` to obtain argc/argv. So mark it as a kernel + * resource instead. + */ + cmdline = ukplat_memregion_alloc(cmdline_len + 1, UKPLAT_MEMRT_KERNEL, + UKPLAT_MEMRF_READ | UKPLAT_MEMRF_WRITE + | UKPLAT_MEMRF_MAP); + if (unlikely(!cmdline)) + return -ENOMEM; + + memcpy(cmdline, cmdl, cmdline_len); + cmdline[cmdline_len] = 0; + + return 0; +} + +static int get_psci_method(struct ukplat_bootinfo *bi) +{ + const char *fdtmethod; + int fdtpsci, len; + void *fdt; + + fdt = (void *)bi->dtb; + UK_ASSERT(bi->dtb); + + /* + * We just support PSCI-0.2 and PSCI-1.0, the PSCI-0.1 would not + * be supported. + */ + fdtpsci = fdt_node_offset_by_compatible(fdt, -1, "arm,psci-1.0"); + if (unlikely(fdtpsci < 0)) + fdtpsci = + fdt_node_offset_by_compatible(fdt, -1, "arm,psci-0.2"); + + if (unlikely(fdtpsci < 0)) { + uk_pr_info("No PSCI conduit found in DTB\n"); + goto enomethod; + } + + fdtmethod = fdt_getprop(fdt, fdtpsci, "method", &len); + if (unlikely(!fdtmethod || len <= 0)) { + uk_pr_info("No PSCI method found\n"); + goto enomethod; + } + + if (!strcmp(fdtmethod, "hvc")) + smccc_psci_call = smccc_hvc; + else if (!strcmp(fdtmethod, "smc")) + smccc_psci_call = smccc_smc; + else { + uk_pr_info("Invalid PSCI conduit method: %s\n", fdtmethod); + goto enomethod; + } + uk_pr_info("PSCI method: %s\n", fdtmethod); + + return 0; + +enomethod: + uk_pr_info("PSCI versions above 0.2 are supported\n"); + smccc_psci_call = NULL; + + return -ENOENT; +} + +static void __noreturn _ukplat_entry2(void) +{ + ukplat_entry_argp(NULL, cmdline, cmdline_len); + + ukplat_lcpu_halt(); +} + +void _librk3568plat_entry(void *fdtp) +{ + int rc; + void *bstack; + struct ukplat_bootinfo *bi; + + ukplat_bootinfo_fdt_setup(fdtp); + + _librk3568plat_init_gpio(fdtp); + + _librk3568plat_init_console(fdtp); + + bi = ukplat_bootinfo_get(); + + if (unlikely(!bi)) + UK_CRASH("Invalid bootinfo"); + + rc = cmdline_init(bi); + if (unlikely(rc < 0)) + UK_CRASH("Failed to initialize command-line\n"); + + /* Allocate boot stack */ + bstack = ukplat_memregion_alloc(__STACK_SIZE, UKPLAT_MEMRT_STACK, + UKPLAT_MEMRF_READ | UKPLAT_MEMRF_WRITE + | UKPLAT_MEMRF_MAP); + if (unlikely(!bstack)) + UK_CRASH("Boot stack alloc failed\n"); + bstack = (void *)((__uptr)bstack + __STACK_SIZE); + + /* Initialize paging */ + rc = ukplat_mem_init(); + if (unlikely(rc)) + UK_CRASH("Could not initialize paging (%d)\n", rc); + +#if defined(CONFIG_ENFORCE_W_XOR_X) && defined(CONFIG_PAGING) + enforce_w_xor_x(); +#endif /* CONFIG_ENFORCE_W_XOR_X && CONFIG_PAGING */ + + /* Initialize interrupt controller */ + rc = uk_intctlr_probe(); + if (unlikely(rc)) + UK_CRASH("Could not initialize the IRQ controller: %d\n", rc); + + /* Initialize logical boot CPU */ + rc = lcpu_init(lcpu_get_bsp()); + if (unlikely(rc)) + UK_CRASH("Failed to initialize bootstrapping CPU: %d\n", rc); + /* Initialize PSCI */ + rc = get_psci_method(bi); + if (unlikely(rc < 0)) + UK_CRASH("Failed to get PSCI method: %d.\n", rc); + + /* Initialize RTC */ + /* TODO */ + + /* + * Switch away from the bootstrap stack as early as possible. + */ + uk_pr_info("Switch from bootstrap stack to stack @%p\n", bstack); + + /* Print boot information */ + uk_pr_info("Print bootinfo before jump to entry:\n"); + ukplat_bootinfo_print(); + + /* + * Enter Unikraft with new allocated stack. + */ + lcpu_arch_jump_to(bstack, _ukplat_entry2); +} diff --git a/shutdown.c b/shutdown.c new file mode 100644 index 0000000000000000000000000000000000000000..44bda52b132aeac4496d81685bf289c6984868ea --- /dev/null +++ b/shutdown.c @@ -0,0 +1,40 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ + +#include +#include +#include +#include + +static void cpu_halt(void) __noreturn; + +void ukplat_terminate(enum ukplat_gstate request) +{ + /* Try to make system off */ + system_off(request); + + cpu_halt(); +} + +static void cpu_halt(void) +{ + __CPU_HALT(); +} + +int ukplat_suspend(void) +{ + return -EBUSY; +} diff --git a/start.S b/start.S new file mode 100644 index 0000000000000000000000000000000000000000..35d8c4a881f8d814abf4a787f99a934a00ed94c8 --- /dev/null +++ b/start.S @@ -0,0 +1,112 @@ +/* + * Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the 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. + */ +#include +#include +#include +#include +#include + +#define BOOTSTACK_SIZE 4096 + +.section .bss +.align 16 +.space BOOTSTACK_SIZE +lcpu_bootstack: + +.section ".text.boot" + +.global _start +_start: + + /* preserve dtb addr */ + mov x25, x0 + + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #3 + cbz x1, master + +// If the cpu id is > 0, hang here +hang: wfe + b hang + +// Continue if cpu id == 0 +master: + // disable mmu and cache + mrs x2, sctlr_el1 + mov x3, #SCTLR_EL1_M_BIT|SCTLR_EL1_C_BIT + bic x2, x2, x3 + msr sctlr_el1, x2 + + ldr x0, =SCTLR_EL2_VALUE + msr sctlr_el2, x0 + isb + + // Disable coprocessor traps + ldr x0, =CPACR_EL1_VALUE + msr cpacr_el1, x0 + + // define register width, el1: aarch64, el0: by code. other bits are 0. + ldr x0, =HCR_EL2_VALUE + msr hcr_el2, x0 + + // Set the SPSR state to restore when returning from EL2 to EL1 + ldr x0, =SPSR_EL2_VALUE + msr spsr_el2, x0 + + // set return address when returning from EL2 to EL1 + adr x0, el1_entry + msr elr_el2, x0 + + eret + +el1_entry: + /* + * We will disable MMU and cache before the pagetables are ready. + * This means we will change memory with cache disabled, so we need to + * invalidate the cache to ensure there is no stale data in it. + * But it would be expensive to invalidate the whole cache. + * In this case, just need to invalidate what we are going to use: + * DTB, TEXT, DATA, BSS, and bootstack. + */ + ldr x0, =_start_ram_addr + ldr x1, =_end + sub x1, x1, x0 + bl clean_and_invalidate_dcache_range + + /* Enable the mmu */ + bl start_mmu + + bl clear_bss + + ldr x0, =lcpu_bootstack + and x0, x0, ~(__STACK_ALIGN_SIZE - 1) + mov sp, x0 + + /* Set exception vector table*/ + ldr x0, =vectors_el1 + msr vbar_el1, x0 + + /* Set the context id */ + msr contextidr_el1, xzr + + /* Load dtb address to x0 as a parameter */ + mov x0, x25 + + bl _librk3568plat_entry + + /* As a failsafe, we also hang the main core */ + b hang