diff --git a/src/arch/rh850/aborts.c b/src/arch/rh850/aborts.c new file mode 100644 index 000000000..23d2acb5c --- /dev/null +++ b/src/arch/rh850/aborts.c @@ -0,0 +1,238 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define F8_OPCODE (0x3EUL) +#define F9_OPCODE (0x3FUL) +#define F9_SUBOPCODE (0x1CUL) + +#define OPCODE_SHIFT (5) +#define OPCODE_MASK (0x3FUL << OPCODE_SHIFT) + +#define SUBOPCODE_SHIFT (19) +#define SUBOPCODE_MASK (0x1FFFUL << SUBOPCODE_SHIFT) + +#define SUB8_SHIFT (14) +#define SUB8_MASK (0x3UL << SUB8_SHIFT) + +#define SUB9_SHIFT (17) +#define SUB9_MASK (0x3UL << SUB9_SHIFT) + +#define BITIDX_SHIFT (11) +#define BITIDX_MASK (0x7UL << BITIDX_SHIFT) + +#define REGIDX_SHIFT (11) +#define REGIDX_MASK (0x1FUL << REGIDX_SHIFT) + +// LEN (Bits 31-28) +#define MEI_LEN_MASK (0xFUL << 28) +#define MEI_LEN_SHIFT 28 +#define MEI_GET_LEN(val) (((val) & MEI_LEN_MASK) >> MEI_LEN_SHIFT) + +// REG (Bits 20-16) +#define MEI_REG_MASK (0x1F << 16) +#define MEI_REG_SHIFT 16 +#define MEI_GET_REG(val) (((val) & MEI_REG_MASK) >> MEI_REG_SHIFT) + +// DS (Bits 11-9) +#define MEI_DS_MASK (0x7 << 9) +#define MEI_DS_SHIFT 9 +#define MEI_GET_DS(val) (((val) & MEI_DS_MASK) >> MEI_DS_SHIFT) + +// U (Bit 8) +#define MEI_U_MASK (1 << 8) +#define MEI_GET_U(val) (((val) & MEI_U_MASK) >> 8) + +// RW (Bit 0) +#define MEI_RW_MASK (1 << 0) +#define MEI_GET_RW(val) ((val) & MEI_RW_MASK) + +static unsigned long read_instruction(unsigned long pc) +{ + unsigned long inst = 0; + unsigned short* pc_ptr = (unsigned short*)(pc); + + if (pc & 0x1) { + ERROR("Trying to read guest unaligned instruction"); + } + + /* Enable Hyp access to VM space */ + set_mpid7(HYP_SPID); + fence_sync(); + + inst = (unsigned long)(*pc_ptr | (*(pc_ptr+1) << 16)); + + /* Disable Hyp access to VM space */ + set_mpid7(HYP_AUX_SPID); + fence_sync(); + + return inst; +} + +static void data_abort(void) +{ + unsigned long mea = get_mea(); + unsigned long mei = get_mei(); + + unsigned int len = MEI_GET_LEN(mei); + unsigned int reg = MEI_GET_REG(mei); + unsigned int ds = MEI_GET_DS(mei); + unsigned int u = MEI_GET_U(mei); + /* unsigned int itype = MEI_GET_ITYPE(mei); */ + unsigned int rw = MEI_GET_RW(mei); + vaddr_t addr = mea; + + /* Decode possible bitwise instruction */ + unsigned long inst = read_instruction(vcpu_readpc(cpu()->vcpu)); + unsigned long opcode = ((inst & OPCODE_MASK) >> OPCODE_SHIFT); + unsigned long subopcode = ((inst & SUBOPCODE_MASK) >> SUBOPCODE_SHIFT); + unsigned long bit_op = 0; + unsigned long mask = 0; + + if (opcode == F8_OPCODE) { + mask = 1UL << ((inst & BITIDX_MASK) >> BITIDX_SHIFT); + bit_op = ((inst & SUB8_MASK) >> SUB8_SHIFT) + 1; + } + else if (opcode == F9_OPCODE && subopcode == F9_SUBOPCODE) { + unsigned long reg_idx = (inst & REGIDX_MASK) >> REGIDX_SHIFT; + unsigned long bit_idx = vcpu_readreg(cpu()->vcpu, reg_idx); + mask = 1UL << (bit_idx & 0x7UL); + bit_op = ((inst & SUB9_MASK) >> SUB9_SHIFT) + 1; + } + + emul_handler_t handler = vm_emul_get_mem(cpu()->vcpu->vm, addr); + if (handler != NULL) { + struct emul_access emul; + emul.addr = addr; + emul.width = len; + emul.write = rw ? true : false; + emul.reg = reg; + emul.reg_width = ds; + emul.sign_ext = ~u; + + emul.arch.op = (enum bitwise_op)bit_op; + emul.arch.byte_mask = mask; + + if (handler(&emul)) { + unsigned long pc_step = len; + vcpu_writepc(cpu()->vcpu, vcpu_readpc(cpu()->vcpu) + pc_step); + } else { + ERROR("Data abort emulation failed (0x%x)", addr); + } + } else { + ERROR("No emulation handler for access to 0x%x, at 0x%x", addr, vcpu_readpc(cpu()->vcpu)); + } +} + +static void hvtrap(void) { + unsigned long r6 = vcpu_readreg(cpu()->vcpu , 6); + unsigned long res = (unsigned long)hypercall(r6); + vcpu_writereg(cpu()->vcpu, 6, res); +} + +void abort(void) +{ + unsigned long psw = get_psw(); + unsigned long cause = (psw & (0x1UL << 7)) ? + (get_feic() & 0xFFFFUL) : + (get_eiic() & 0xFFFFUL); + + switch (cause) { + case 0x01: + WARNING("Exception: RESET - Reset input\n"); + break; + + case 0x1C: + WARNING("Exception: SYSERR - System error (context saving error)\n"); + break; + + case 0x1D: + WARNING("Exception: SYSERR - System error (error prior to register bank " + "restoration)\n"); + break; + + case 0x60: + WARNING("Exception: RIE - Reserved instruction exception\n"); + break; + + case 0x71: + WARNING("Exception: FPE - FPU exception (precise)\n"); + break; + + case 0x75: + WARNING("Exception: FXE - FXU exception (precise)\n"); + break; + + case 0x80: + case 0x81: + case 0x82: + WARNING("Exception: UCPOP - Coprocessor unusable exception\n"); + break; + + case 0x90: + WARNING("Exception: MIP - Memory protection exception due to instruction fetching\n"); + break; + case 0x91: + data_abort(); + break; + case 0x95: + WARNING("Exception: MDP - Memory protection exception (interrupt table reference " + "method)\n"); + break; + case 0x98: + WARNING("Exception: MIP - Guest memory protection exception due to instruction " + "fetching\n"); + break; + case 0x99: + data_abort(); + break; + case 0x9D: + WARNING("Exception: MDP - Guest memory protection exception (interrupt table " + "reference method)\n"); + break; + + case 0xA0: + WARNING("Exception: PIE - Privilege instruction exception\n"); + break; + + case 0xC0: + WARNING("Exception: MAE - Misalignment exception\n"); + break; + + case 0xE0: + WARNING("Exception: FENMI - FENMI interrupt\n"); + break; + + default: + + if (cause >= 0xF0 && cause <= 0xFF) { + WARNING("FEINT - FEINT interrupt"); + } else if (cause >= 0x1000 && cause <= 0x17FF) { + WARNING("EIINT - User interrupt"); + } else if (cause >= 0x10 && cause <= 0x1F) { + WARNING("SYSERR - System error (instruction fetch error)"); + } else if (cause >= 0xf000 && cause <= 0xf01f) { + hvtrap(); + }else if (cause >= 0x8000 && cause <= 0x80FF) { + WARNING("SYSCALL - System call"); + } else if (cause >= 0x31 && cause <= 0x3F) { + WARNING("FETRAP - FE level trap"); + } else if (cause >= 0x40 && cause <= 0x4F) { + WARNING("TRAP0 - EI level trap 0"); + } else if (cause >= 0x50 && cause <= 0x5F) { + WARNING("TRAP1 - EI level trap 1"); + } else { + WARNING("Exception: Unknown exception code: 0x%X\n", cause); + } + break; + } +} diff --git a/src/arch/rh850/arch.mk b/src/arch/rh850/arch.mk new file mode 100644 index 000000000..b833f83f7 --- /dev/null +++ b/src/arch/rh850/arch.mk @@ -0,0 +1,17 @@ +## SPDX-License-Identifier: Apache-2.0 +## Copyright (c) Bao Project and Contributors. All rights reserved. + +# RH850 specific flags for compiler +arch-cflags+=-mv850e3v5 +arch-cflags+=-mrh850-abi +arch-cflags+=-m8byte-align +arch-cflags+=-msoft-float +arch-cflags+=-fno-leading-underscore + +# RH850 specific flags for assembler +arch-asflags+=-mv850e3v5 +arch-asflags+=-mrh850-abi +arch-asflags+=-m8byte-align + +arch_mem_prot:=mpu +PAGE_SIZE:=64 diff --git a/src/arch/rh850/asm_defs.c b/src/arch/rh850/asm_defs.c new file mode 100644 index 000000000..2dda053b5 --- /dev/null +++ b/src/arch/rh850/asm_defs.c @@ -0,0 +1,30 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include +#include + +__attribute__((used)) static void cpu_defines(void) +{ + DEFINE_SIZE(CPU_SIZE, struct cpu); + DEFINE_OFFSET(CPU_STACK_OFF, struct cpu, stack); + DEFINE_SIZE(CPU_STACK_SIZE, ((struct cpu*)NULL)->stack); + DEFINE_OFFSET(CPU_VCPU_OFF, struct cpu, vcpu); +} + +__attribute__((used)) static void vcpu_defines(void) +{ + DEFINE_SIZE(VCPU_ARCH_SIZE, struct vcpu_arch); + DEFINE_OFFSET(VCPU_REGS_OFF, struct vcpu, regs); + DEFINE_SIZE(VCPU_REGS_SIZE, struct arch_regs); +} + +__attribute__((used)) static void platform_defines(void) +{ + DEFINE_OFFSET(PLAT_CPUNUM_OFF, struct platform, cpu_num); + DEFINE_OFFSET(PLAT_ARCH_OFF, struct platform, arch); +} diff --git a/src/arch/rh850/boot.S b/src/arch/rh850/boot.S new file mode 100644 index 000000000..a057e2de8 --- /dev/null +++ b/src/arch/rh850/boot.S @@ -0,0 +1,253 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include + +.macro LOAD_ADDR sym, reg + movhi hi(\sym), r0, \reg + movea lo(\sym), \reg, \reg +.endm + +/** + * The following code MUST be at the base of the image, as this is bao's entrypoint. Therefore + * .boot section must also be the first in the linker script. DO NOT implement any code before the + * _reset_handler in this section. + */ + .section ".boot", "ax" +.global _reset_handler +_reset_handler: + + /** + * Not following any ABI for registers in this boot code. + * The following registers are however reserved to be passed to main + * as arguments: + * r6 -> CPU ID + * + * Register r10 is reserved to hold the CPU ID + * Register r11 is reserved to hold the master CPU ID + * Register r12 is reserved to hold the CPU struct size + * Register r13 is reserved to hold the CPU struct pointer + * Register r31 is reserved as link pointer when calling a routine + * + * The remaining code must use r20-r29 as scratchpad registers in the main + * flow and r15-r19 as arguments and return values. r10-r14 are used to hold constants. + */ + + di /* Disable interrupts */ + + stsr 0, r10, 2 /* get current CPU ID from PEID */ + + mov CPU_MASTER_FIXED, r11 /* identify master cpu */ + /* TODO: Support for non-fixed master cpu*/ + +/* TODO: Remove. + This loop serves as a workaround for the fact that, when using e2studio to debug execution, + all cores start executing simultaneously, instead of following the BOOTCTRL mechanism */ +sync_loop: + /* mov 3, r20 + cmp r10, r20 + be sync_loop + mov 2, r20 + cmp r10, r20 + be sync_loop + mov 1, r20 + cmp r10, r20 + be sync_loop */ + + /* set PSW.EBV and PSW.ID */ + mov 0x8020, r20 + ldsr r20, 5, 0 + + /* configure EBASE with exception vector */ + LOAD_ADDR _hyp_vector_table, r20 + ori 0x2, r20, r20 /* direct vector method */ + ldsr r20, 3, 1 + + /* configure INTBP with interrupt vector */ + LOAD_ADDR _hyp_interrupt_table, r20 + ldsr r20, 4, 1 + + /* clear MPM to disable memory protections */ + mov r0, r20 + ldsr r20, 0, 5 + + /* configure protection setting check */ + ldsr r0, 8, 5 /* MCA = MCS = 0 covers all memory */ + ldsr r0, 9, 5 + ldsr r0, 12, 5 /* MCI = 0 */ + ldsr r10, 0, 1 /* set SPID = CPU ID */ + + /* initialize mpu entries for bank 0 */ + /* TODO: Discover number of MPU banks */ + ldsr r0, 17, 5 /* set MPBK.BK = 0 */ + jarl _clear_mpu, lp + + /* initialize local RAM */ + /* TODO: use macros for platform addresses */ + mov 0xFDE00000, r20 + mov 0xFDE0FFFF, r21 + jarl _boot_clear, lp + + /* check if current CPU is CPU_MASTER */ + cmp r11, r10 + bne _clear_cpu + /* bne _check_barrier */ + + /* enable interrupt virtualization support, + recommended at CPU initialization after reset */ + mov 0xFFFC402F0, r20 + mov 0x1, r21 + st.w r21, 0[r20] /* IHVCFG.IHVE = 0x1 */ + + /* initialize cluster RAM */ + /* TODO: use macros for platform addresses */ + mov 0xFE000000, r15 + mov 0xFE07FFFF, r16 + jarl _boot_clear, lp + + mov 0xFE100000, r15 + mov 0xFE17FFFF, r16 + jarl _boot_clear, lp + + mov 0xFE400000, r15 + mov 0xFE5FFFFF, r16 + jarl _boot_clear, lp + + mov 0xFE800000, r15 + mov 0xFE83FFFF, r16 + jarl _boot_clear, lp + + /* copy non-text sections from flash to ram */ + LOAD_ADDR _data_lma_start, r15 + LOAD_ADDR _image_load_end, r16 + mov PLAT_DATA_ADDR, r17 + jarl _copy_data, lp + + /* clear .bss in ram */ + LOAD_ADDR _image_noload_start, r15 + LOAD_ADDR _image_end, r16 + jarl _boot_clear, lp + + /* store CPU_MASTER */ + LOAD_ADDR CPU_MASTER, r20 + st.w r11, 0[r20] + + /* store image load address in img_addr */ + LOAD_ADDR _image_start, r20 + LOAD_ADDR img_addr, r21 + st.w r20, 0[r21] + + /* store data section address in data_addr */ + mov PLAT_DATA_ADDR, r20 + LOAD_ADDR data_addr, r21 + st.w r20, 0 [r21] + +/* +_check_barrier: + # Initialize CPU barrier + ## Write 0x3 to BR0EN + mov 0xFFFB8004, r20 + mov 0x3, r21 # TODO: create macro for BR0EN macro + st.b r21, 0[r20] + # ## Write 0x1 to BR0INIT + # mov 0xFFFB8000, r20 + # mov 0x1, r21 + # st.b r21, 0[r20] + ## Write 0x1 to BR0CHKS + mov 0xFFFB8100, r20 + mov 0x1, r21 + st.b r21, 0[r20] + +_poll_barrier: + # Poll BR0SYNCS + mov 0xFFFB8104, r20 + ld.bu 0[r20], r21 + cmp r0, r21 + be _poll_barrier +*/ + +_clear_cpu: + /* clear CPUn struct */ + LOAD_ADDR _image_end, r20 + mov CPU_SIZE, r12 + mov r10, r21 + mulh r12, r21 /* cpu struct offset */ + add r21, r20 /* end of .bss + cpu struct offset = r20 points to cpu */ + mov r20, r13 /* r13 holds the CPU pointer */ + mov r13, r15 + mov r13, r16 + add r12, r16 + jarl _boot_clear, lp + + ldsr r13, 29, 0 /* use FEWR as CPU* pointer holder */ + + /* Initialize stack pointer */ + mov CPU_STACK_OFF, r20 + add r13, r20 + mov CPU_STACK_SIZE, r21 + add r21, r20 + mov r20, sp + + /* Set init arguments */ + mov r10, r6 /* copy CPU ID to r6 */ + LOAD_ADDR init, r5 + + br init + + +/** + * Clear from [r15] to [r16] + * r15: start of region + * r16: end of region + */ +_boot_clear: + cmp r16, r15 + bge _boot_clear_exit + st.w r0, 0[r15] + addi 4, r15, r15 + br _boot_clear +_boot_clear_exit: + jmp [lp] + + +/** + * Copy contents from [r15] until [r16] to [r17] + * r15: start of the source region + * r16: end of the source region + * r17: start of the destination region + * uses r18 + */ +_copy_data: + ld.w 0[r15], r18 + st.w r18, 0[r17] + addi 4, r15, r15 + addi 4, r17, r17 + cmp r15, r16 + bne _copy_data + jmp [lp] + +/** + * Clear MPU SRs + * Uses r15, r16 + */ +_clear_mpu: + mov r0, r15 +_clear_mpu_1: + mov 32, r16 /* TODO: discover number of MPU entries */ + cmp r15, r16 + be _clear_mpu_exit + + ldsr r15, 16, 5 /* set MPIX */ + + ldsr r0, 20, 5 /* clear MPLA */ + ldsr r0, 21, 5 /* clear MPUA */ + ldsr r0, 22, 5 /* clear MPAT */ + + addi 1, r15, r15 + bne _clear_mpu_1 +_clear_mpu_exit: + jmp [lp] diff --git a/src/arch/rh850/cache.c b/src/arch/rh850/cache.c new file mode 100644 index 000000000..50491e56c --- /dev/null +++ b/src/arch/rh850/cache.c @@ -0,0 +1,35 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include +#include +#include + +/* #pragma inline_asm cist */ +/* static void cist(void) */ +/* { */ +/* cist */ +/* } */ + +/* #pragma inline_asm cild */ +/* static void cild(void) */ +/* { */ +/* cild */ +/* } */ + +void cache_arch_enumerate(struct cache* dscrp) { + UNUSED_ARG(dscrp); +} + +void cache_flush_range(vaddr_t base, size_t size) +{ + UNUSED_ARG(base); + UNUSED_ARG(size); + /* unsigned long lpn = (base & (1<<(11-1))) << 11; */ + /* set_ictagl(lpn | 1); */ + /* set_ictagh(base+size-1); */ +} diff --git a/src/arch/rh850/cpu.c b/src/arch/rh850/cpu.c new file mode 100644 index 000000000..c3ff58534 --- /dev/null +++ b/src/arch/rh850/cpu.c @@ -0,0 +1,75 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include +#include + +cpuid_t CPU_MASTER __attribute__((section(".datanocopy"))); + +/* Perform architecture dependent cpu cores initializations */ +void cpu_arch_init(cpuid_t cpuid, paddr_t load_addr) +{ + UNUSED_ARG(load_addr); + volatile unsigned long* bootcrl = (unsigned long*)platform.arch.bootctrl_addr; + + if (cpuid == CPU_MASTER) { + for (size_t c = 0; c < platform.cpu_num; c++) { + if (c == cpuid) { + continue; + } + + (*bootcrl) |= (1UL << c); + } + } + + /* clear exception registers */ + set_eipc(0x0); + set_fepc(0x0); + set_mea(0x0); + set_mei(0x0); + set_eiic(0x0); + set_feic(0x0); + + /* set xxPSW.EBV */ + set_eipsw(0x8000); + set_fepsw(0x8000); + + /* Set snooze time */ + set_snzcfg(SNZCFG_PERIOD); +} + +static void reset_stack_and_jump(void* stack_base, void (*jmp_target)(void)) +{ + __asm__ volatile( + "mov %[stack], sp\n\t" + "st.w lp, -4[sp]\n\t" + "add -4, sp\n\t" + "jarl %[target], lp\n\t" + "ld.w 0[sp], lp\n\t" + "add 4, sp\n\t" + "jmp [lp]\n\t" + : + : [stack] "r" (stack_base), + [target] "r" (jmp_target) + : "lp", "memory" + ); +} + + +void cpu_arch_standby() +{ + snooze(); + reset_stack_and_jump(&cpu()->stack[STACK_SIZE], cpu_standby_wakeup); + ERROR("returned from standby wake up"); +} + +void cpu_arch_powerdown() +{ + snooze(); + reset_stack_and_jump(&cpu()->stack[STACK_SIZE], cpu_powerdown_wakeup); + ERROR("returned from powerdown wake up"); +} diff --git a/src/arch/rh850/exceptions.S b/src/arch/rh850/exceptions.S new file mode 100644 index 000000000..c4156495f --- /dev/null +++ b/src/arch/rh850/exceptions.S @@ -0,0 +1,305 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include + +.text + +.macro VM_EXIT + + /* set SPID to HYP_SPID */ + ldsr r31, 28, 0 /* use EIWR as scratchpad */ + mov HYP_SPID, r31 + ldsr r31, 0, 1 + + /* save program registers in vcpu struct */ + stsr 29, r31, 0 /* get cpu* from FEWR */ + addi CPU_VCPU_OFF, r31, r31 /* CPU_VCPU_OFF */ + ld.w 0[r31], r31 /* get vcpu* */ + add VCPU_REGS_OFF, r31 + st.dw r0, 0[r31] + st.dw r2, 8[r31] + st.dw r4, 16[r31] + st.dw r6, 24[r31] + st.dw r8, 32[r31] + st.dw r10, 40[r31] + st.dw r12, 48[r31] + st.dw r14, 56[r31] + st.dw r16, 64[r31] + st.dw r18, 72[r31] + st.dw r20, 80[r31] + st.dw r22, 88[r31] + st.dw r24, 96[r31] + st.dw r26, 104[r31] + st.dw r28, 112[r31] + st.w r30, 120[r31] + + mov r31, r30 + stsr 28, r31, 0 + st.w r31, 124[r30] + + /* save PC */ + jarl _save_pc, lp + + /* restore stack pointer */ + stsr 29, r20, 0 + mov CPU_STACK_OFF, r21 + add r21, r20 + mov CPU_STACK_SIZE, r21 + add r21, r20 + mov r20, sp +.endm + +.macro VM_ENTRY + /* load vcpu registers from memory */ + stsr 29, r30, 0 + addi CPU_VCPU_OFF, r30, r30 + ld.w 0[r30], r30 + add VCPU_REGS_OFF, r30 + + /* restore PC */ + jarl _restore_pc, lp + mov r30, r31 + + ld.dw 0[r31], r0 + ld.dw 8[r31], r2 + ld.dw 16[r31], r4 + ld.dw 24[r31], r6 + ld.dw 32[r31], r8 + ld.dw 40[r31], r10 + ld.dw 48[r31], r12 + ld.dw 56[r31], r14 + ld.dw 64[r31], r16 + ld.dw 72[r31], r18 + ld.dw 80[r31], r20 + ld.dw 88[r31], r22 + ld.dw 96[r31], r24 + ld.dw 104[r31], r26 + ld.dw 112[r31], r28 + ld.w 120[r31], r30 + + /* set SPID to VMID. + The code below uses EIWR and HVSB as scratchpad registers */ + ldsr r31, 28, 0 + ld.w 124[r31], r31 + ldsr r31, 20, 1 + stsr 28, r31, 0 + ld.w 132[r31], r31 + ldsr r31, 0, 1 /* set SPID = VMID */ + + /* the instructions below should not trigger any MIP exception + as all the hypervisor code belongs to an MPU entry with RG = 1 */ + + /* select ret instruction */ + br _select_xxret +.endm + +/** + * Save PC from EIPC or FEPC depending on the exception type + * r30: vcpu register struct base address + * uses r20 + */ +_save_pc: + stsr 5, r20, 0 + andi 0x80, r20, r20 + cmp r0, r20 + be _save_ei + stsr 2, r20, 0 /* FEPC */ + br _save_pc_exit +_save_ei: + stsr 0, r20, 0 /* EIPC */ +_save_pc_exit: + st.w r20, 128[r30] + jmp [lp] + +/** + * Restore PC to EIPC or FEPC depending on the exception type + * r30: vcpu register struct base address + * uses r20 and r21 + */ +_restore_pc: + ld.w 128[r30], r20 + stsr 5, r21, 0 + andi 0x80, r21, r21 + cmp r0, r21 + be _restore_ei + ldsr r20, 2, 0 /* set FEPC */ + br _restore_pc_exit +_restore_ei: + ldsr r20, 2, 0 /* set EIPC */ +_restore_pc_exit: + jmp [lp] + +/** + * Execute eiret or feret depending on the exception type + * and restores r31 from HVSB + */ +_select_xxret: + stsr 5, r31, 0 + andi 0x80, r31, r31 + cmp r0, r31 + be _ei_ret + stsr 20, r31, 1 + feret +_ei_ret: + stsr 20, r31, 1 + eiret + +.balign 0x200 +.global _hyp_vector_table +_hyp_vector_table: + br . + + .balign 0x10 + syncp + br _guest_exception /* SYSERR ; Guest */ + + .balign 0x10 + br _guest_exception, /* HVTRAP; Guest */ + + .balign 0x10 + br _guest_exception /* FETRAP ; Guest? */ + + .balign 0x10 + br _guest_exception /* TRAP0 ; Guest? */ + + .balign 0x10 + br _guest_exception /* TRAP1 ; Guest? */ + + .balign 0x10 + br _host_exception /* RIE */ + + .balign 0x10 + syncp + br _host_exception /* FPP/FPI */ + + .balign 0x10 + br _host_exception /* UCPOP */ + + /* TODO: Dfferentiate between MIP/MDP guest and hyp exceptions */ + .balign 0x10 + br _guest_exception /* MIP/MDP ; Guest */ + + .balign 0x10 + br _host_exception /* RIE */ + + .balign 0x10 + br _host_exception /* PIE */ + + .balign 0x10 + br _host_exception /* MAE */ + + .balign 0x10 + br _host_exception /* UCPOP */ + + .balign 0x10 + syncp + br _host_exception, /* FENMI */ + + .balign 0x10 + syncp + br _host_exception /* FEINT */ + + /* only used with direct vector method */ + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority0) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority1) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority2) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority3) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority4) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority5) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority6) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority7) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority8) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority9) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority10) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority11) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority12) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority13) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority14) */ + + .balign 0x10 + syncp + br _Interrupt_EI /* INTn(priority15) */ + +/* only used with table reference method */ +.balign 0x200 +.global _hyp_interrupt_table +_hyp_interrupt_table: + .long _Interrupt_EI /* INT0 */ + .long _Interrupt_EI /* INT1 */ + .long _Interrupt_EI /* INT2 */ + .rept 2048 - 3 + .long _Interrupt_EI /* INTn */ + .endr + +_guest_exception: + + VM_EXIT + jarl abort, lp + VM_ENTRY + +_host_exception: + br _host_exception + +_Interrupt_EI: + + VM_EXIT + + /* copy int_id to r6 */ + stsr 13, r6, 0 /* EIIC (TODO: FEIC ?) */ + mov 0x7FF, r20 + and r20, r6 + + jarl interrupts_handle, lp + +.global vcpu_arch_entry +vcpu_arch_entry: + VM_ENTRY diff --git a/src/arch/rh850/inc/arch/aborts.h b/src/arch/rh850/inc/arch/aborts.h new file mode 100644 index 000000000..52c248bd1 --- /dev/null +++ b/src/arch/rh850/inc/arch/aborts.h @@ -0,0 +1,13 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ABORTS_H__ +#define __ABORTS_H__ + +#include + +void abort(void); + +#endif /* __ABORTS_H__ */ \ No newline at end of file diff --git a/src/arch/rh850/inc/arch/bao.h b/src/arch/rh850/inc/arch/bao.h new file mode 100644 index 000000000..f6589268a --- /dev/null +++ b/src/arch/rh850/inc/arch/bao.h @@ -0,0 +1,17 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_BAO_H__ +#define __ARCH_BAO_H__ + +#define BAO_VAS_BASE CONFIG_HYP_BASE_ADDR +#define PAGE_SIZE (64) +#define STACK_SIZE (0x1000) + +#ifndef __ASSEMBLER__ + +#endif /* !__ASSEMBLER__ */ + +#endif /* __ARCH_BAO_H__ */ diff --git a/src/arch/rh850/inc/arch/cache.h b/src/arch/rh850/inc/arch/cache.h new file mode 100644 index 000000000..096a19c72 --- /dev/null +++ b/src/arch/rh850/inc/arch/cache.h @@ -0,0 +1,13 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_CACHE_H__ +#define __ARCH_CACHE_H__ + +#include + +#define CACHE_MAX_LVL 8 // Does this make sense in all architectures? + +#endif /* __ARCH_CACHE_H__ */ diff --git a/src/arch/rh850/inc/arch/cpu.h b/src/arch/rh850/inc/arch/cpu.h new file mode 100644 index 000000000..2aa9f028d --- /dev/null +++ b/src/arch/rh850/inc/arch/cpu.h @@ -0,0 +1,40 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_CPU_H__ +#define __ARCH_CPU_H__ + +#include +#include +#include +#include + +#define SNZCFG_PERIOD (uint8_t)(-1) + +#define CPU_HAS_EXTENSION(EXT) (DEFINED(EXT)) + +extern cpuid_t CPU_MASTER; + +struct cpu_arch { + struct { + BITMAP_ALLOC(bitmap, MPU_ARCH_MAX_NUM_ENTRIES); + /** + * A locked region means that it can never be removed from the MPU. For example, + */ + BITMAP_ALLOC(locked, MPU_ARCH_MAX_NUM_ENTRIES); + } mpu_hyp; +}; + +static inline struct cpu* cpu(void) +{ + return (struct cpu*)get_fewr(); +} + +static inline void snooze(void) +{ + __asm__ volatile("snooze"); +} + +#endif /* __ARCH_CPU_H__ */ diff --git a/src/arch/rh850/inc/arch/emul.h b/src/arch/rh850/inc/arch/emul.h new file mode 100644 index 000000000..1616559e5 --- /dev/null +++ b/src/arch/rh850/inc/arch/emul.h @@ -0,0 +1,25 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_EMUL_H__ +#define __ARCH_EMUL_H__ + +#include + +/* The order of the operations can NOT be modified */ +enum bitwise_op { + NO_OP, + SET1, + NOT1, + CLR1, + TST1 +}; + +struct emul_access_arch { + enum bitwise_op op; + unsigned long byte_mask; +}; + +#endif /* __ARCH_EMUL_H__ */ \ No newline at end of file diff --git a/src/arch/rh850/inc/arch/fences.h b/src/arch/rh850/inc/arch/fences.h new file mode 100644 index 000000000..846453046 --- /dev/null +++ b/src/arch/rh850/inc/arch/fences.h @@ -0,0 +1,61 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_FENCES_H__ +#define __ARCH_FENCES_H__ + +#include + +static inline void syncp(void) +{ + __asm__ volatile("syncp" ::: "memory"); +} + +static inline void syncm(void) +{ + __asm__ volatile("syncm" ::: "memory"); +} + +static inline void synci(void) +{ + __asm__ volatile("synci" ::: "memory"); +} + +static inline void synce(void) +{ + __asm__ volatile("synce" ::: "memory"); +} + +static inline void fence_ord_write(void) +{ + synci(); +} + +static inline void fence_ord_read(void) +{ + synci(); +} + +static inline void fence_ord(void) +{ + synci(); +} + +static inline void fence_sync_write(void) +{ + synci(); +} + +static inline void fence_sync_read(void) +{ + synci(); +} + +static inline void fence_sync(void) +{ + synci(); +} + +#endif /* __ARCH_FENCES_H__ */ diff --git a/src/arch/rh850/inc/arch/hypercall.h b/src/arch/rh850/inc/arch/hypercall.h new file mode 100644 index 000000000..ede9412e1 --- /dev/null +++ b/src/arch/rh850/inc/arch/hypercall.h @@ -0,0 +1,12 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_HYPERCALL_H__ +#define __ARCH_HYPERCALL_H__ + +#define HYPCALL_IN_ARG_REG(ARG) ((ARG) + 6 + 1) +#define HYPCALL_OUT_ARG_REG(ARG) ((ARG) + 10) + +#endif /* ARCH_HYPERCALL_H */ diff --git a/src/arch/rh850/inc/arch/intc.h b/src/arch/rh850/inc/arch/intc.h new file mode 100644 index 000000000..91c409de8 --- /dev/null +++ b/src/arch/rh850/inc/arch/intc.h @@ -0,0 +1,85 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __INTC_H__ +#define __INTC_H__ + +#include + +#define PRIVATE_IRQS_NUM 32 + +struct intc1 { + uint16_t EIC[PRIVATE_IRQS_NUM]; + uint8_t pad0[0xF0-0x40]; + uint32_t IMR; + uint8_t pad1[0x100-0xF4]; + uint32_t EIBD[PRIVATE_IRQS_NUM]; + uint8_t pad2[0x1C0-0x180]; + uint32_t FIBD; + uint8_t pad3[0x200-0x1C4]; + uint32_t EEIC[PRIVATE_IRQS_NUM]; + uint32_t EIBG; + uint8_t pad4[0x2C0-0x284]; + uint32_t FIBG; + uint8_t pad5[0x2F0-0x2C4]; + uint32_t IHVCFG; +}; + +#define INTC2_IRQ_NUM (ARCH_MAX_INTERRUPTS - PRIVATE_IRQS_NUM) +#define INTC2_IMR_NUM ((ARCH_MAX_INTERRUPTS + 31) / 32 - 1) +#define INTC2_I2EIBG_OFF (0x1FE0) +#define INTC2_EIBD_OFF (0x2000) +#define PAD3_LEN ((INTC2_EIBD_OFF - INTC2_I2EIBG_OFF) - (PLAT_CPU_NUM * 4) + 0x80) + +struct intc2 { + uint8_t PAD0[64]; /* 0x0000 - 0x003F */ + uint16_t EIC[INTC2_IRQ_NUM]; /* 0x0040 - 0x0FFF */ + uint8_t PAD1[4]; /* 0x1000 - 0x1003 */ + uint32_t IMR[INTC2_IMR_NUM]; /* 0x1004 - 0x10FF */ + uint8_t PAD2[3808]; /* 0x1100 - 0x1FDF */ + uint32_t I2EIBG[PLAT_CPU_NUM]; /* 0x1FE0 - (0x1FE0 + 4*cpu_num - 1) */ + uint8_t PAD3[PAD3_LEN]; /* (0x1FE0 + 4*cpu_num) - 0x203F */ + uint32_t EIBD[INTC2_IRQ_NUM]; /* 0x2080 - 0x3FFF */ + uint8_t PAD4[128]; /* 0x4000 - 0x407F */ + uint32_t EEIC[INTC2_IRQ_NUM]; /* 0x4080 - 0x5FFF */ +}; + +struct intif { + uint32_t PINT[8]; + uint32_t PINTCLR[8]; + uint32_t PAD[112]; + uint32_t TPTMSEL; +}; + +struct eint { + uint8_t sintr[PLAT_CPU_NUM]; +}; + +struct fenc { + uint64_t FENMIF; + uint32_t FENMIC; +}; + +struct feinc { + uint32_t FEINTF; + uint32_t FEINTFMSK; + uint32_t FEINTC; +}; + +void intc_init(void); +void intc_map_mmio(void); + +void intc_set_trgt(irqid_t int_id, cpuid_t cpu_id); +void intc_set_enable(irqid_t int_id, bool en); +void intc_set_prio(irqid_t int_id, unsigned long prio); + +void intc_vm_assign(irqid_t int_id, vmid_t vm_id); +void intc_hyp_assign(irqid_t int_id); + +void intc_set_pend(irqid_t int_id, bool en); +bool intc_get_pend(irqid_t int_id); + + +#endif /* INTC_H */ diff --git a/src/arch/rh850/inc/arch/interrupts.h b/src/arch/rh850/inc/arch/interrupts.h new file mode 100644 index 000000000..cb995bf79 --- /dev/null +++ b/src/arch/rh850/inc/arch/interrupts.h @@ -0,0 +1,19 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_INTERRUPTS_H__ +#define __ARCH_INTERRUPTS_H__ + +#include +#include + +#define ARCH_MAX_INTERRUPTS 2048 +#define MAX_INTERRUPTS PLAT_MAX_INTERRUPTS +#define MAX_GUEST_INTERRUPTS (MAX_INTERRUPTS) + +#define MAX_INTERRUPT_LINES MAX_INTERRUPTS +#define MAX_INTERRUPT_HANDLERS MAX_INTERRUPTS + +#endif /* __ARCH_INTERRUPTS_H__ */ diff --git a/src/arch/rh850/inc/arch/ipir.h b/src/arch/rh850/inc/arch/ipir.h new file mode 100644 index 000000000..4174e0ddf --- /dev/null +++ b/src/arch/rh850/inc/arch/ipir.h @@ -0,0 +1,51 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include + +#ifndef __ARCH_IPIR_H__ +#define __ARCH_IPIR_H__ + +#define IPIR_CH3_IRQ_ID (3) +#define IPIR_NUM_CHANNELS (4) + +/* We reserve the last IPIR channel for Bao */ +#define IPI_HYP_IRQ_ID (IPIR_CH3_IRQ_ID) + +struct vcpu; +struct emul_access; + +struct ipir_chann { + uint8_t IPInEN; + uint8_t pad0[0x4-0x1]; + uint8_t IPInFLG; + uint8_t pad1[0x8-0x5]; + uint8_t IPInFCLR; + uint8_t pad2[0x10-0x9]; + uint8_t IPInREQ; + uint8_t pad3[0x14-0x11]; + uint8_t IPInRCLR; + uint8_t pad4[0x20-0x15]; +}; + +struct ipir_pe_set { + struct ipir_chann chann[IPIR_NUM_CHANNELS]; + uint8_t pad[0x100-0x80]; +}; + +struct ipir_hw { + struct ipir_chann self[IPIR_NUM_CHANNELS]; + uint8_t pad[0x800-0x80]; + struct ipir_pe_set pe[PLAT_CPU_NUM]; +}; + +void ipir_handle(irqid_t int_id); +void ipir_send_ipi(cpuid_t cpu_target); +void ipir_init(void); + +bool vipir_emul_handler(struct emul_access* acc); +void vipir_init(struct vm* vm); + +#endif /* __ARCH_IPIR_H__ */ \ No newline at end of file diff --git a/src/arch/rh850/inc/arch/mem.h b/src/arch/rh850/inc/arch/mem.h new file mode 100644 index 000000000..a33b251d3 --- /dev/null +++ b/src/arch/rh850/inc/arch/mem.h @@ -0,0 +1,96 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_MEM_H__ +#define __ARCH_MEM_H__ + +#include + +#define MPU_ARCH_MAX_NUM_ENTRIES (32) + +struct addr_space; +struct mp_region; + +typedef union { + struct { + uint16_t ur : 1; // hyp att? + uint16_t uw : 1; // hyp att? + uint16_t ux : 1; // hyp att? + uint16_t sr : 1; // hyp att? + uint16_t sw : 1; // hyp att? + uint16_t sx : 1; // hyp att? + uint16_t res1 : 1; + uint16_t e : 1; + uint16_t res2 : 6; + uint16_t rg : 1; + uint16_t wg : 1; + uint16_t rmpid0 : 1; // VM attributes? + uint16_t rmpid1 : 1; // VM attributes? + uint16_t rmpid2 : 1; // VM attributes? + uint16_t rmpid3 : 1; // VM attributes? + uint16_t rmpid4 : 1; // VM attributes? + uint16_t rmpid5 : 1; // VM attributes? + uint16_t rmpid6 : 1; // VM attributes? + uint16_t rmpid7 : 1; // VM attributes? + uint16_t wmpid0 : 1; // VM attributes? + uint16_t wmpid1 : 1; // VM attributes? + uint16_t wmpid2 : 1; // VM attributes? + uint16_t wmpid3 : 1; // VM attributes? + uint16_t wmpid4 : 1; // VM attributes? + uint16_t wmpid5 : 1; // VM attributes? + uint16_t wmpid6 : 1; // VM attributes? + uint16_t wmpid7 : 1; // VM attributes? + }; + uint32_t raw; +} mpat_flags_t; + +struct addr_space_arch { + unsigned long mpu_entry_mask; +}; + + +typedef mpat_flags_t mem_flags_t; + +#define PTE_INVALID ((mem_flags_t){ .e = 0 }) +/** + * Any SPID can read from this region + * No SPID can write to this region + */ +#define PTE_HYP_FLAGS_CODE ((mem_flags_t){ .e = 1, .sr = 1, .sw = 1, .sx = 1, .rg = 1 }) +/** + * Only SPID0 can read from this region + * Only SPID0 can write to this region + */ +#define PTE_HYP_FLAGS ((mem_flags_t){ .e = 1, .sr = 1, .sw = 1, .sx = 1, .rmpid0 = 1, .wmpid0 = 1 }) +/** + * Only the SPID in MPID0 can read from this region + * Only the SPID in MPID0 can write to this region + */ +#define PTE_HYP_DEV_FLAGS ((mem_flags_t){ .e = 1, .sr = 1, .sw = 1, .sx = 0, .rmpid0 = 1, .wmpid0 = 1 }) + +/* TODO in the future we need to deal with IO permissions securely */ +/** + * Only SPIDs in MPID1 and MPID7 can read from this region + * Only SPIDs in MPID1 and MPID7 can write to this region + */ +#define PTE_VM_FLAGS \ + ((mem_flags_t){ .e = 1, .sr = 1, .sw = 1, .sx = 1, .ur = 1, .uw = 1, .ux = 1, .rmpid1 = 1, .wmpid1 = 1, .rmpid7 = 1, .wmpid7 = 1 }) + +/* TODO in the future we need to deal with IO permissions securely */ +/** + * Only the SPID in MPID1 can read from this region + * Only the SPID in MPID1 can write to this region + */ +#define PTE_VM_DEV_FLAGS \ + ((mem_flags_t){ .e = 1, .sr = 1, .sw = 1, .sx = 0, .ur = 1, .uw = 1, .ux = 0, .rmpid1 = 1, .wmpid1 = 1 }) + +static inline size_t mpu_granularity(void) +{ + return (size_t)PAGE_SIZE; +} + +bool mpu_perms_compatible(uint32_t perms1, uint32_t perms2); + +#endif /* __ARCH_MEM_H__ */ diff --git a/src/arch/rh850/inc/arch/mpu.h b/src/arch/rh850/inc/arch/mpu.h new file mode 100644 index 000000000..2fc65eb9e --- /dev/null +++ b/src/arch/rh850/inc/arch/mpu.h @@ -0,0 +1,22 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_MPU_H__ +#define __ARCH_MPU_H__ + +#include +#include + +struct addr_space; +struct mp_region; + +void mpu_arch_init(void); +bool mpu_add_region(struct mp_region* reg, bool locked); +bool mpu_remove_region(struct mp_region* reg); +bool mpu_update_region(struct mp_region* reg); +void mpu_arch_enable(void); +void mpu_arch_disable(void); + +#endif /* __ARCH_MPU_H__ */ diff --git a/src/arch/rh850/inc/arch/platform.h b/src/arch/rh850/inc/arch/platform.h new file mode 100644 index 000000000..9672889ed --- /dev/null +++ b/src/arch/rh850/inc/arch/platform.h @@ -0,0 +1,27 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_PLATFORM_H__ +#define __ARCH_PLATFORM_H__ + +#include + +// Arch-specific platform data +struct arch_platform { + struct { + paddr_t intc1_addr; + paddr_t intc2_addr; + paddr_t intif_addr; + paddr_t eint_addr; + paddr_t fenc_addr; + paddr_t feinc_addr[8]; + } intc; + + paddr_t bootctrl_addr; + + paddr_t ipir_addr; +}; + +#endif /* __ARCH_PLATFORM_H__ */ diff --git a/src/arch/rh850/inc/arch/spinlock.h b/src/arch/rh850/inc/arch/spinlock.h new file mode 100644 index 000000000..783f40f5b --- /dev/null +++ b/src/arch/rh850/inc/arch/spinlock.h @@ -0,0 +1,47 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_SPINLOCK_H__ +#define __ARCH_SPINLOCK_H__ + +#include +#include + +#define SPINLOCK_INITVAL 0 + +typedef uint32_t spinlock_t; + +static inline void spin_lock(spinlock_t* lock) +{ + __asm__ volatile ( + "1:\n\t" + " ldl.w [%0], r19 \n\t" + " cmp r0, r19 \n\t" + " bnz 2f \n\t" + " mov 1, r19 \n\t" + " stc.w r19, [%0] \n\t" + " cmp r0, r19 \n\t" + " bnz 3f \n\t" + "2:\n\t" + " snooze \n\t" + " br 1b \n\t" + "3:\n\t" + : + : "r"(lock) + : "r19", "memory" + ); +} + +static inline void spin_unlock(spinlock_t* lock) +{ + __asm__ volatile ( + "st.w r0, 0[%0]\n\t" + : + : "r"(lock) + : "memory" + ); +} + +#endif /* __ARCH_SPINLOCK_H__ */ diff --git a/src/arch/rh850/inc/arch/srs.h b/src/arch/rh850/inc/arch/srs.h new file mode 100644 index 000000000..6d971a00e --- /dev/null +++ b/src/arch/rh850/inc/arch/srs.h @@ -0,0 +1,999 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_SRS_H__ +#define __ARCH_SRS_H__ + +#include + +/* Basic System Registers */ +#define PSW_Z (1UL << 0) +#define PSW_EBV (1UL << 15) + +#define EIPSW_EBV (PSW_EBV) +#define FEPSW_EBV (PSW_EBV) + +/* MPU Registers */ +#define MPM_MPE (1UL << 0) +#define MPM_SVP (1UL << 1) +#define MPCFG_HBE_OFF (8) +#define MPCFG_HBE_LEN (6) +#define MPCFG_HBE_MASK (BIT_MASK(MPCFG_HBE_OFF, MPCFG_HBE_LEN)) +#define MPIDX_IDX_OFF (0) +#define MPIDX_IDX_LEN (5) +#define MPIDX_IDX_MASK (BIT_MASK(MPIDX_IDX_OFF, MPIDX_IDX_LEN)) +#define MPLA_OFF (2) +#define MPLA_LEN (30) +#define MPLA_MASK (BIT_MASK(MPLA_OFF, MPLA_LEN)) +#define MPUA_OFF (2) +#define MPUA_LEN (30) +#define MPUA_MASK (BIT_MASK(MPUA_OFF, MPUA_LEN)) + +/* Hypervisor registers */ +#define GMCFG_HMP (1UL << 1) +#define GMCFG_GSYSE (1UL << 4) +#define GMCFG_GCU0 (1UL << 16) +#define GMCFG_GCU1 (1UL << 17) + +#define EIPSWH_GPID_OFF (8) +#define EIPSWH_GPID_LEN (3) +#define EIPSWH_GPID_MASK (BIT_MASK(EIPSWH_GPID_OFF, EIPSWH_GPID_LEN)) +#define EIPSWH_GM (1UL << 31) + +#define FEPSWH_GPID_OFF (EIPSWH_GPID_OFF) +#define FEPSWH_GPID_LEN (EIPSWH_GPID_LEN) +#define FEPSWH_GPID_MASK (EIPSWH_GPID_MASK) +#define FEPSWH_GM (EIPSWH_GM) + +/* Guest context registers */ +#define GMMPM_GMPE (1UL << 2) + +#ifndef __ASSEMBLER__ + +/* BASIC SYS REG */ +static inline unsigned long get_eipc(void) +{ + unsigned long val; + __asm__ volatile ("stsr 0, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_eipc(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 0, 0" : : "r"(val)); +} + +static inline unsigned long get_eipsw(void) +{ + unsigned long val; + __asm__ volatile ("stsr 1, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_eipsw(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 1, 0" : : "r"(val)); +} + +static inline unsigned long get_fepc(void) +{ + unsigned long val; + __asm__ volatile ("stsr 2, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_fepc(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 2, 0" : : "r"(val)); +} + +static inline unsigned long get_fepsw(void) +{ + unsigned long val; + __asm__ volatile ("stsr 3, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_fepsw(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 3, 0" : : "r"(val)); +} + +static inline unsigned long get_psw(void) +{ + unsigned long val; + __asm__ volatile ("stsr 5, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_psw(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 5, 0" : : "r"(val)); +} + +static inline unsigned long get_fpsr(void) +{ + unsigned long val; + __asm__ volatile ("stsr 6, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_fpsr(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 6, 0" : : "r"(val)); +} + +static inline unsigned long get_fpepc(void) +{ + unsigned long val; + __asm__ volatile ("stsr 7, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_fpepc(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 7, 0" : : "r"(val)); +} + +static inline unsigned long get_fpst(void) +{ + unsigned long val; + __asm__ volatile ("stsr 8, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_fpst(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 8, 0" : : "r"(val)); +} + +static inline unsigned long get_fpcc(void) +{ + unsigned long val; + __asm__ volatile ("stsr 9, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_fpcc(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 9, 0" : : "r"(val)); +} + +static inline unsigned long get_fpcfg(void) +{ + unsigned long val; + __asm__ volatile ("stsr 10, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_fpcfg(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 10, 0" : : "r"(val)); +} + +static inline unsigned long get_eiic(void) +{ + unsigned long val; + __asm__ volatile ("stsr 13, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_eiic(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 13, 0" : : "r"(val)); +} + +static inline unsigned long get_feic(void) +{ + unsigned long val; + __asm__ volatile ("stsr 14, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_feic(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 14, 0" : : "r"(val)); +} + +static inline unsigned long get_ctpc(void) +{ + unsigned long val; + __asm__ volatile ("stsr 16, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_ctpc(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 16, 0" : : "r"(val)); +} + +static inline unsigned long get_ctpsw(void) +{ + unsigned long val; + __asm__ volatile ("stsr 17, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_ctpsw(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 17, 0" : : "r"(val)); +} + +static inline unsigned long get_ctbp(void) +{ + unsigned long val; + __asm__ volatile ("stsr 20, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_ctbp(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 20, 0" : : "r"(val)); +} + +static inline unsigned long get_snzcfg(void) +{ + unsigned long val; + __asm__ volatile ("stsr 21, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_snzcfg(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 21, 0" : : "r"(val)); +} + +static inline unsigned long get_eiwr(void) +{ + unsigned long val; + __asm__ volatile ("stsr 28, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_eiwr(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 28, 0" : : "r"(val)); +} + +static inline unsigned long get_fewr(void) +{ + unsigned long val; + __asm__ volatile ("stsr 29, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_fewr(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 29, 0" : : "r"(val)); +} + +static inline unsigned long get_spid(void) +{ + unsigned long val; + __asm__ volatile ("stsr 0, %0, 1" : "=r"(val)); + return val; +} + +static inline void set_spid(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 0, 1" : : "r"(val)); +} + +static inline unsigned long get_spidlist(void) +{ + unsigned long val; + __asm__ volatile ("stsr 1, %0, 1" : "=r"(val)); + return val; +} + +static inline void set_spidlist(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 1, 1" : : "r"(val)); +} + +static inline unsigned long get_rbase(void) +{ + unsigned long val; + __asm__ volatile ("stsr 2, %0, 1" : "=r"(val)); + return val; +} + +static inline void set_rbase(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 2, 1" : : "r"(val)); +} + +static inline unsigned long get_ebase(void) +{ + unsigned long val; + __asm__ volatile ("stsr 3, %0, 1" : "=r"(val)); + return val; +} + +static inline void set_ebase(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 3, 1" : : "r"(val)); +} + +static inline unsigned long get_peid(void) +{ + unsigned long val; + __asm__ volatile ("stsr 0, %0, 2" : "=r"(val)); + return val; +} + +static inline void set_peid(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 0, 2" : : "r"(val)); +} + +static inline unsigned long get_bmid(void) +{ + unsigned long val; + __asm__ volatile ("stsr 1, %0, 2" : "=r"(val)); + return val; +} + +static inline void set_bmid(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 1, 2" : : "r"(val)); +} + +static inline unsigned long get_intbp(void) +{ + unsigned long val; + __asm__ volatile ("stsr 4, %0, 1" : "=r"(val)); + return val; +} + +static inline void set_intbp(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 4, 1" : : "r"(val)); +} + +static inline unsigned long get_mea(void) +{ + unsigned long val; + __asm__ volatile ("stsr 6, %0, 2" : "=r"(val)); + return val; +} + +static inline void set_mea(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 6, 2" : : "r"(val)); +} + +static inline unsigned long get_mei(void) +{ + unsigned long val; + __asm__ volatile ("stsr 8, %0, 2" : "=r"(val)); + return val; +} + +static inline void set_mei(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 8, 2" : : "r"(val)); +} + +static inline unsigned long get_rbip(void) +{ + unsigned long val; + __asm__ volatile ("stsr 18, %0, 2" : "=r"(val)); + return val; +} + +static inline void set_rbip(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 18, 2" : : "r"(val)); +} + +/* INTERRUPT SYS REGS */ +static inline unsigned long get_ispr(void) +{ + unsigned long val; + __asm__ volatile ("stsr 10, %0, 2" : "=r"(val)); + return val; +} + +static inline void set_ispr(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 10, 2" : : "r"(val)); +} + +static inline unsigned long get_imsr(void) +{ + unsigned long val; + __asm__ volatile ("stsr 11, %0, 2" : "=r"(val)); + return val; +} + +static inline void set_imsr(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 11, 2" : : "r"(val)); +} + +static inline unsigned long get_icsr(void) +{ + unsigned long val; + __asm__ volatile ("stsr 12, %0, 2" : "=r"(val)); + return val; +} + +static inline void set_icsr(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 12, 2" : : "r"(val)); +} + +static inline unsigned long get_intcfg(void) +{ + unsigned long val; + __asm__ volatile ("stsr 13, %0, 2" : "=r"(val)); + return val; +} + +static inline void set_intcfg(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 13, 2" : : "r"(val)); +} + +static inline unsigned long get_plmr(void) +{ + unsigned long val; + __asm__ volatile ("stsr 14, %0, 2" : "=r"(val)); + return val; +} + +static inline void set_plmr(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 14, 2" : : "r"(val)); +} + +/* MPU FUNCTION REGISTERS */ +/* #pragma inline_asm get_mpm */ +static inline unsigned long get_mpm(void) +{ + unsigned long val; + __asm__ volatile ("stsr 0, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpm(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 0, 5" : : "r"(val)); +} + +static inline unsigned long get_mpcfg(void) +{ + unsigned long val; + __asm__ volatile ("stsr 2, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpcfg(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 2, 5" : : "r"(val)); +} + +static inline unsigned long get_mca(void) +{ + unsigned long val; + __asm__ volatile ("stsr 8, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mca(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 8, 5" : : "r"(val)); +} + +static inline unsigned long get_mcs(void) +{ + unsigned long val; + __asm__ volatile ("stsr 9, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mcs(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 9, 5" : : "r"(val)); +} + +static inline unsigned long get_mcc(void) +{ + unsigned long val; + __asm__ volatile ("stsr 10, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mcc(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 10, 5" : : "r"(val)); +} + +static inline unsigned long get_mcr(void) +{ + unsigned long val; + __asm__ volatile ("stsr 11, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mcr(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 11, 5" : : "r"(val)); +} + +static inline unsigned long get_mci(void) +{ + unsigned long val; + __asm__ volatile ("stsr 12, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mci(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 12, 5" : : "r"(val)); +} + +static inline unsigned long get_mpidx(void) +{ + unsigned long val; + __asm__ volatile ("stsr 16, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpidx(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 16, 5" : : "r"(val)); +} + +static inline unsigned long get_mpbk(void) +{ + unsigned long val; + __asm__ volatile ("stsr 17, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpbk(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 17, 5" : : "r"(val)); +} + +static inline unsigned long get_mpla(void) +{ + unsigned long val; + __asm__ volatile ("stsr 20, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpla(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 20, 5" : : "r"(val)); +} + +static inline unsigned long get_mpua(void) +{ + unsigned long val; + __asm__ volatile ("stsr 21, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpua(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 21, 5" : : "r"(val)); +} + +static inline unsigned long get_mpat(void) +{ + unsigned long val; + __asm__ volatile ("stsr 22, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpat(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 22, 5" : : "r"(val)); +} + +static inline unsigned long get_mpid0(void) +{ + unsigned long val; + __asm__ volatile ("stsr 24, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpid0(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 24, 5" : : "r"(val)); +} + +static inline unsigned long get_mpid1(void) +{ + unsigned long val; + __asm__ volatile ("stsr 25, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpid1(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 25, 5" : : "r"(val)); +} + +static inline unsigned long get_mpid2(void) +{ + unsigned long val; + __asm__ volatile ("stsr 26, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpid2(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 26, 5" : : "r"(val)); +} + +static inline unsigned long get_mpid3(void) +{ + unsigned long val; + __asm__ volatile ("stsr 27, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpid3(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 27, 5" : : "r"(val)); +} + +static inline unsigned long get_mpid4(void) +{ + unsigned long val; + __asm__ volatile ("stsr 28, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpid4(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 28, 5" : : "r"(val)); +} + +static inline unsigned long get_mpid5(void) +{ + unsigned long val; + __asm__ volatile ("stsr 29, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpid5(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 29, 5" : : "r"(val)); +} + +static inline unsigned long get_mpid6(void) +{ + unsigned long val; + __asm__ volatile ("stsr 30, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpid6(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 30, 5" : : "r"(val)); +} + +static inline unsigned long get_mpid7(void) +{ + unsigned long val; + __asm__ volatile ("stsr 31, %0, 5" : "=r"(val)); + return val; +} + +static inline void set_mpid7(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 31, 5" : : "r"(val)); +} + +/* CACHE OPERATION REGISTERS */ +static inline unsigned long get_ictagl(void) +{ + unsigned long val; + __asm__ volatile ("stsr 16, %0, 4" : "=r"(val)); + return val; +} + +static inline void set_ictagl(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 16, 4" : : "r"(val)); +} + +static inline unsigned long get_ictagh(void) +{ + unsigned long val; + __asm__ volatile ("stsr 17, %0, 4" : "=r"(val)); + return val; +} + +static inline void set_ictagh(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 17, 4" : : "r"(val)); +} + +static inline unsigned long get_icdatl(void) +{ + unsigned long val; + __asm__ volatile ("stsr 18, %0, 4" : "=r"(val)); + return val; +} + +static inline void set_icdatl(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 18, 4" : : "r"(val)); +} + +static inline unsigned long get_icdath(void) +{ + unsigned long val; + __asm__ volatile ("stsr 19, %0, 4" : "=r"(val)); + return val; +} + +static inline void set_icdath(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 19, 4" : : "r"(val)); +} + +static inline unsigned long get_icctrl(void) +{ + unsigned long val; + __asm__ volatile ("stsr 24, %0, 4" : "=r"(val)); + return val; +} + +static inline void set_icctrl(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 24, 4" : : "r"(val)); +} + +static inline unsigned long get_iccfg(void) +{ + unsigned long val; + __asm__ volatile ("stsr 26, %0, 4" : "=r"(val)); + return val; +} + +static inline void set_iccfg(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 26, 4" : : "r"(val)); +} + +static inline unsigned long get_icerr(void) +{ + unsigned long val; + __asm__ volatile ("stsr 28, %0, 4" : "=r"(val)); + return val; +} + +static inline void set_icerr(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 28, 4" : : "r"(val)); +} + +/* VIRTUALIZATION SUPPORT REGISTERS */ +static inline unsigned long get_hvcfg(void) +{ + unsigned long val; + __asm__ volatile ("stsr 16, %0, 1" : "=r"(val)); + return val; +} + +static inline void set_hvcfg(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 16, 1" : : "r"(val)); +} + +static inline unsigned long get_gmcfg(void) +{ + unsigned long val; + __asm__ volatile ("stsr 17, %0, 1" : "=r"(val)); + return val; +} + +static inline void set_gmcfg(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 17, 1" : : "r"(val)); +} + +static inline unsigned long get_pswh(void) +{ + unsigned long val; + __asm__ volatile ("stsr 15, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_pswh(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 15, 0" : : "r"(val)); +} + +static inline unsigned long get_eipswh(void) +{ + unsigned long val; + __asm__ volatile ("stsr 18, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_eipswh(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 18, 0" : : "r"(val)); +} + +static inline unsigned long get_fepswh(void) +{ + unsigned long val; + __asm__ volatile ("stsr 19, %0, 0" : "=r"(val)); + return val; +} + +static inline void set_fepswh(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 19, 0" : : "r"(val)); +} + +static inline unsigned long get_hvsb(void) +{ + unsigned long val; + __asm__ volatile ("stsr 20, %0, 1" : "=r"(val)); + return val; +} + +static inline void set_hvsb(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 20, 1" : : "r"(val)); +} + +static inline unsigned long get_dbgen(void) +{ + unsigned long val; + __asm__ volatile ("stsr 0, %0, 3" : "=r"(val)); + return val; +} + +static inline void set_dbgen(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 0, 3" : : "r"(val)); +} + +/* GUEST CONTEXT REGISTERS */ +static inline unsigned long get_gmeipc(void) +{ + unsigned long val; + __asm__ volatile ("stsr 0, %0, 9" : "=r"(val)); + return val; +} + +static inline void set_gmeipc(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 0, 9" : : "r"(val)); +} + +static inline unsigned long get_gmfepc(void) +{ + unsigned long val; + __asm__ volatile ("stsr 2, %0, 9" : "=r"(val)); + return val; +} + +static inline void set_gmfepc(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 2, 9" : : "r"(val)); +} + +static inline unsigned long get_gmpsw(void) +{ + unsigned long val; + __asm__ volatile ("stsr 5, %0, 9" : "=r"(val)); + return val; +} + +static inline void set_gmpsw(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 5, 9" : : "r"(val)); +} + +static inline unsigned long get_gmmea(void) +{ + unsigned long val; + __asm__ volatile ("stsr 6, %0, 9" : "=r"(val)); + return val; +} + +static inline void set_gmmea(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 6, 9" : : "r"(val)); +} + +static inline unsigned long get_gmmei(void) +{ + unsigned long val; + __asm__ volatile ("stsr 8, %0, 9" : "=r"(val)); + return val; +} + +static inline void set_gmmei(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 8, 9" : : "r"(val)); +} + +static inline unsigned long get_gmeiic(void) +{ + unsigned long val; + __asm__ volatile ("stsr 13, %0, 9" : "=r"(val)); + return val; +} + +static inline void set_gmeiic(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 13, 9" : : "r"(val)); +} + +static inline unsigned long get_gmfeic(void) +{ + unsigned long val; + __asm__ volatile ("stsr 14, %0, 9" : "=r"(val)); + return val; +} + +static inline void set_gmfeic(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 14, 9" : : "r"(val)); +} + +static inline unsigned long get_gmspid(void) +{ + unsigned long val; + __asm__ volatile ("stsr 16, %0, 9" : "=r"(val)); + return val; +} + +static inline void set_gmspid(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 16, 9" : : "r"(val)); +} + +static inline unsigned long get_gmspidlist(void) +{ + unsigned long val; + __asm__ volatile ("stsr 17, %0, 9" : "=r"(val)); + return val; +} + +static inline void set_gmspidlist(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 17, 9" : : "r"(val)); +} + +static inline unsigned long get_gmmpm(void) +{ + unsigned long val; + __asm__ volatile ("stsr 25, %0, 9" : "=r"(val)); + return val; +} + +static inline void set_gmmpm(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 25, 9" : : "r"(val)); +} + +static inline unsigned long get_gmpeid(void) +{ + unsigned long val; + __asm__ volatile ("stsr 30, %0, 9" : "=r"(val)); + return val; +} + +static inline void set_gmpeid(unsigned long val) +{ + __asm__ volatile ("ldsr %0, 30, 9" : : "r"(val)); +} + +#endif /* __ASSEMBLER__ */ +#endif /* __ARCH_SRS_H__ */ \ No newline at end of file diff --git a/src/arch/rh850/inc/arch/vintc.h b/src/arch/rh850/inc/arch/vintc.h new file mode 100644 index 000000000..ea4aea63c --- /dev/null +++ b/src/arch/rh850/inc/arch/vintc.h @@ -0,0 +1,27 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __VINTC_H__ +#define __VINTC_H__ + +#include +#include + +struct vcpu; +struct emul_access; + +void vintc_init(struct vm* vm); +void vintc_inject(struct vcpu* vcpu, irqid_t int_id); +void vintc_vcpu_reset(struct vcpu* vcpu); +void vintc_vm_reset(struct vm* vm); + +bool vintc1_emul_handler(struct emul_access* acc); +bool vintc2_emul_handler(struct emul_access* acc); +bool vintif_emul_handler(struct emul_access* acc); +bool veint_emul_handler(struct emul_access* acc); +bool vfenc_emul_handler(struct emul_access* acc); +bool vfeinc_emul_handler(struct emul_access* acc); + +#endif /* __VINTC_H__ */ diff --git a/src/arch/rh850/inc/arch/vm.h b/src/arch/rh850/inc/arch/vm.h new file mode 100644 index 000000000..9298d49e8 --- /dev/null +++ b/src/arch/rh850/inc/arch/vm.h @@ -0,0 +1,103 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_VM_H__ +#define __ARCH_VM_H__ + +#include +#include +#include +#include + +#define MAX_OF_GP_REGS (sizeof(union gp_regs) / sizeof(unsigned long)) + +struct intc_dscrp { + paddr_t intc1_addr; + paddr_t intc2_addr; +}; + +struct arch_vm_platform { + /* interrupt controller */ + struct intc_dscrp vir; +}; + +struct vm_arch { + /* interrupt controller */ + struct emul_mem intc1_emul; + struct emul_mem intc2_emul; + struct emul_mem intif_emul; + struct emul_mem eint_emul; + struct emul_mem fenc_emul; + struct emul_mem feinc_emul; + struct emul_mem ipir_emul; + /* BOOTCTRL */ + struct emul_mem bootctrl_emul; +}; + +struct vcpu_arch { + bool started; +}; + +struct arch_regs { + union gp_regs { + unsigned long r[32]; /* r0 is always 0x0 */ + struct { + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long sp; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + unsigned long r16; + unsigned long r17; + unsigned long r18; + unsigned long r19; + unsigned long r20; + unsigned long r21; + unsigned long r22; + unsigned long r23; + unsigned long r24; + unsigned long r25; + unsigned long r26; + unsigned long r27; + unsigned long r28; + unsigned long r29; + unsigned long r30; + unsigned long r31; + }; + } gp_regs; + // Basic system registers + unsigned long pc; + unsigned long spid; +}; + +void vcpu_arch_entry(void); +void vcpu_restore_state(struct vcpu* vcpu); +void vcpu_save_state(struct vcpu* vcpu); + +static inline void vcpu_arch_inject_hw_irq(struct vcpu* vcpu, irqid_t id) +{ + vintc_inject(vcpu, id); +} + +static inline void vcpu_arch_inject_irq(struct vcpu* vcpu, irqid_t id) +{ + vintc_inject(vcpu, id); +} + +void vbootctrl_init(struct vm* vm); +bool vbootctrl_emul_handler(struct emul_access* acc); + +#endif /* __ARCH_VM_H__ */ diff --git a/src/arch/rh850/inc/arch/vmm.h b/src/arch/rh850/inc/arch/vmm.h new file mode 100644 index 000000000..2567ca9e1 --- /dev/null +++ b/src/arch/rh850/inc/arch/vmm.h @@ -0,0 +1,19 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __ARCH_VMM_H__ +#define __ARCH_VMM_H__ + +#include + +/* Bao uses MPID0 and MPID7 */ +#define HYP_SPID 0x10 +#define HYP_AUX_SPID 0x1F + +#ifndef __ASSEMBLER__ + +#endif /* __ASSEMBLER__ */ + +#endif /* __ARCH_VMM_H__ */ \ No newline at end of file diff --git a/src/arch/rh850/intc.c b/src/arch/rh850/intc.c new file mode 100644 index 000000000..a56db8818 --- /dev/null +++ b/src/arch/rh850/intc.c @@ -0,0 +1,201 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include + +/* EIC */ +#define EIRFn_BIT (1U << 12) +#define EIMKn_BIT (1U << 7) + +#define EIPn_MASK (0xF) + +#define EIC_SET_EIRFn(reg) ((reg) |= (uint16_t)EIRFn_BIT) +#define EIC_CLR_EIRFn(reg) ((reg) &= (uint16_t)(~EIRFn_BIT)) +#define EIC_GET_EIRFn(reg) (((reg) & (uint16_t)EIRFn_BIT) >> 12) + +#define EIC_SET_EIMKn(reg) ((reg) |= (uint16_t)EIMKn_BIT) +#define EIC_CLR_EIMKn(reg) ((reg) &= (uint16_t)(~EIMKn_BIT)) + +#define EIC_SET_EIPn(reg, value) \ + ((reg) = (uint16_t)(((reg) & (uint16_t)(~EIPn_MASK)) | \ + ((value) & EIPn_MASK))) + +/* EIBD */ +#define EIBD_GM_BIT (1U << 15) + +#define EIBD_GPID_MASK (0x7U << 8) +#define EIBD_GPID_SHIFT 8 + +#define EIBD_PEID_MASK (0x7U) + +#define EIBD_SET_GM(reg) ((reg) |= (unsigned long)EIBD_GM_BIT) +#define EIBD_CLR_GM(reg) ((reg) &= (unsigned long)(~EIBD_GM_BIT)) + +#define EIBD_SET_GPID(reg, value) \ + ((reg) = ((reg) & (unsigned long)(~EIBD_GPID_MASK)) | \ + (((value) & 0x7) << EIBD_GPID_SHIFT)) + +#define EIBD_SET_PEID(reg, value) \ + ((reg) = ((reg) & (unsigned long)(~EIBD_PEID_MASK)) | \ + ((value) & EIBD_PEID_MASK)) + + +volatile struct intc1* intc1_hw; +volatile struct intc2* intc2_hw; +volatile struct intif* intif_hw; +volatile struct eint* eint_hw; +volatile struct fenc* fenc_hw; +volatile struct feinc* feinc_hw[PLAT_CPU_NUM]; + + +void intc_set_pend(irqid_t int_id, bool en) +{ + if (int_id < PRIVATE_IRQS_NUM) { + if (en) { + EIC_SET_EIRFn(intc1_hw->EIC[int_id]); + } else { + EIC_CLR_EIRFn(intc1_hw->EIC[int_id]); + } + } else { + irqid_t intc2_irq_id = int_id - PRIVATE_IRQS_NUM; + if (en) { + EIC_SET_EIRFn(intc2_hw->EIC[intc2_irq_id]); + } else { + EIC_CLR_EIRFn(intc2_hw->EIC[intc2_irq_id]); + } + } +} + +bool intc_get_pend(irqid_t int_id) +{ + unsigned int pend = 0; + if (int_id < PRIVATE_IRQS_NUM) { + pend = EIC_GET_EIRFn(intc1_hw->EIC[int_id]); + + } else { + irqid_t intc2_irq_id = int_id - PRIVATE_IRQS_NUM; + pend = EIC_GET_EIRFn(intc2_hw->EIC[intc2_irq_id]); + } + + return !!pend; +} + +void intc_hyp_assign(irqid_t int_id) +{ + if (int_id < PRIVATE_IRQS_NUM) { + EIBD_CLR_GM(intc1_hw->EIBD[int_id]); + } else { + irqid_t intc2_irq_id = int_id - PRIVATE_IRQS_NUM; + EIBD_CLR_GM(intc2_hw->EIBD[intc2_irq_id]); + } +} + +void intc_vm_assign(irqid_t int_id, vmid_t vm_id) +{ + /* assumes calling cpu is configuring this interrupt */ + if (int_id < PRIVATE_IRQS_NUM) { + EIBD_SET_GM(intc1_hw->EIBD[int_id]); + EIBD_SET_GPID(intc1_hw->EIBD[int_id], vm_id); + } else { + irqid_t intc2_irq_id = int_id - PRIVATE_IRQS_NUM; + EIBD_SET_GM(intc2_hw->EIBD[intc2_irq_id]); + EIBD_SET_GPID(intc2_hw->EIBD[intc2_irq_id], vm_id); + + EIBD_SET_PEID(intc2_hw->EIBD[intc2_irq_id], cpu()->id); + } +} + +void intc_set_trgt(irqid_t int_id, cpuid_t cpu_id) +{ + if (int_id < PRIVATE_IRQS_NUM) { + if (cpu()->id != cpu_id) { + ERROR("setting private interrupt on another core"); + } + } else { + irqid_t intc2_irq_id = int_id - PRIVATE_IRQS_NUM; + EIBD_SET_PEID(intc2_hw->EIBD[intc2_irq_id], cpu_id); + } +} + +void intc_set_enable(irqid_t int_id, bool en) +{ + if (int_id < PRIVATE_IRQS_NUM) { + if (en) { + EIC_CLR_EIMKn(intc1_hw->EIC[int_id]); + } else { + EIC_SET_EIMKn(intc1_hw->EIC[int_id]); + } + } else { + irqid_t intc2_irq_id = int_id - PRIVATE_IRQS_NUM; + if (en) { + EIC_CLR_EIMKn(intc2_hw->EIC[intc2_irq_id]); + } else { + EIC_SET_EIMKn(intc2_hw->EIC[intc2_irq_id]); + } + } +} + +void intc_set_prio(irqid_t int_id, unsigned long prio) +{ + if (int_id < PRIVATE_IRQS_NUM) { + EIC_SET_EIPn(intc1_hw->EIC[int_id], prio); + } else { + irqid_t intc2_irq_id = int_id - PRIVATE_IRQS_NUM; + EIC_SET_EIPn(intc2_hw->EIC[intc2_irq_id], prio); + } +} + +static void intc_map_local_mmio(void) +{ + /* because we are mapping an alias this could be global mapping actually */ + vaddr_t intc1_ptr = mem_alloc_map_dev(&cpu()->as, SEC_HYP_PRIVATE, INVALID_VA, + platform.arch.intc.intc1_addr, NUM_PAGES(sizeof(struct intc1))); + if (intc1_ptr == INVALID_VA) { + ERROR("maping intc1 failed"); + } + intc1_hw = (struct intc1*)intc1_ptr; + + // TODO: I'm mapping FEINC twice + vaddr_t feinc_ptr; + feinc_ptr = mem_alloc_map_dev(&cpu()->as, SEC_HYP_PRIVATE, INVALID_VA, + platform.arch.intc.feinc_addr[cpu()->id], NUM_PAGES(sizeof(struct feinc))); + if (feinc_ptr == INVALID_VA) { + ERROR("maping feinc_ptr failed"); + } + + feinc_hw[cpu()->id] = (struct feinc*)feinc_ptr; +} + +static void intc_map_global_mmio(void) +{ + vaddr_t global_start_addr = platform.arch.intc.intif_addr; + vaddr_t global_end_addr = platform.arch.intc.intc2_addr + sizeof(struct intc2); + size_t global_size = global_end_addr - global_start_addr; + size_t global_npages = NUM_PAGES(global_size); + + vaddr_t global_ptr; + global_ptr = + mem_alloc_map_dev(&cpu()->as, SEC_HYP_GLOBAL, INVALID_VA, global_start_addr, global_npages); + if (global_ptr == INVALID_VA) { + ERROR("maping global interrupt controller region failed"); + } + + intc2_hw = (struct intc2*)platform.arch.intc.intc2_addr; + intif_hw = (struct intif*)platform.arch.intc.intif_addr; + eint_hw = (struct eint*)platform.arch.intc.eint_addr; + fenc_hw = (struct fenc*)platform.arch.intc.fenc_addr; + feinc_hw[cpu()->id] = (struct feinc*)platform.arch.intc.feinc_addr[cpu()->id]; +} + +void intc_init() +{ + intc_map_local_mmio(); + if (cpu_is_master()) { + intc_map_global_mmio(); + } + + cpu_sync_and_clear_msgs(&cpu_glb_sync); +} diff --git a/src/arch/rh850/interrupts.c b/src/arch/rh850/interrupts.c new file mode 100644 index 000000000..d59ae60da --- /dev/null +++ b/src/arch/rh850/interrupts.c @@ -0,0 +1,64 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void interrupts_arch_init() +{ + intc_init(); +} + +void interrupts_arch_enable(irqid_t int_id, bool en) +{ + intc_set_enable(int_id, en); + intc_set_prio(int_id, 0x01); + intc_set_trgt(int_id, cpu()->id); +} + +bool interrupts_arch_check(irqid_t int_id) +{ + return intc_get_pend(int_id); +} + +void interrupts_arch_clear(irqid_t int_id) +{ + intc_set_pend(int_id, false); +} + +irqid_t interrupts_arch_reserve(irqid_t int_id) +{ + intc_hyp_assign(int_id); + + return int_id; +} + +inline bool interrupts_arch_conflict(bitmap_t* interrupt_bitmap, irqid_t int_id) +{ + /* IPIR channels not used by the hypervisor are shared between VMs */ + return bitmap_get(interrupt_bitmap, int_id) && + !(int_id < IPIR_NUM_CHANNELS && int_id != IPI_HYP_IRQ_ID); +} + +void interrupts_arch_vm_assign(struct vm* vm, irqid_t int_id) +{ + intc_vm_assign(int_id, vm->id); +} + +void interrupts_arch_ipi_init(void) +{ + ipir_init(); +} + +void interrupts_arch_ipi_send(cpuid_t cpu_target) +{ + ipir_send_ipi(cpu_target); +} diff --git a/src/arch/rh850/ipir.c b/src/arch/rh850/ipir.c new file mode 100644 index 000000000..697cb0829 --- /dev/null +++ b/src/arch/rh850/ipir.c @@ -0,0 +1,276 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include + +#define IPIR_REGS_PAT_MASK (0x9FUL) + +#define IPInENS_PAT (0x000UL) +#define IPInFLGS_PAT (0x004UL) +#define IPInFCLRS_PAT (0x008UL) +#define IPInREQS_PAT (0x010UL) +#define IPInRCLRS_PAT (0x014UL) + +#define IPInENm_PAT (0x800UL) +#define IPInFLGm_PAT (0x804UL) +#define IPInFCLRm_PAT (0x808UL) +#define IPInREQm_PAT (0x810UL) +#define IPInRCLRm_PAT (0x814UL) + +typedef enum { + IPInEN, + IPInFLG, + IPInFCLR, + IPInREQ, + IPInRCLR +} ipir_reg_t; + +static const unsigned long ipir_reg_self_pat[] = { + IPInENS_PAT, + IPInFLGS_PAT, + IPInFCLRS_PAT, + IPInREQS_PAT, + IPInRCLRS_PAT +}; + +static const unsigned long ipir_reg_pem_pat[] = { + IPInENm_PAT, + IPInFLGm_PAT, + IPInFCLRm_PAT, + IPInREQm_PAT, + IPInRCLRm_PAT +}; + +volatile struct ipir_hw* ipir; +static bool ipir_ready = false; + +extern irqid_t interrupts_ipi_id; + +static bool decode_ipir_chann(size_t* chann, size_t reg_idx, size_t offset, bool self) { + + bool ret = false; + + if (self) { + size_t delta = offset - ipir_reg_self_pat[reg_idx]; + if (delta % 0x20 == 0) { + *chann = delta / 0x20; + ret = true; + } + } + else { + size_t delta = offset - ipir_reg_pem_pat[reg_idx]; + size_t rem = delta % 0x100; + if (rem % 0x20 == 0) { + *chann = rem / 0x20; + ret = true; + } + } + return ret; +} + +void ipir_handle(irqid_t int_id) +{ + UNUSED_ARG(int_id); + + /* Clear IPI */ + uint8_t src_cpu_idx = ipir->self[IPI_HYP_IRQ_ID].IPInFLG; + ipir->self[IPI_HYP_IRQ_ID].IPInFCLR = src_cpu_idx; + + cpu_msg_handler(); +} + +void ipir_send_ipi(cpuid_t cpu_target) +{ + if (ipir_ready){ + ipir->self[IPI_HYP_IRQ_ID].IPInREQ = (uint8_t)(1U << cpu_target); + } +} + +void ipir_init(void) +{ + if (cpu_is_master()) { + + vaddr_t ipir_ptr = mem_alloc_map_dev(&cpu()->as, SEC_HYP_GLOBAL, INVALID_VA, + platform.arch.ipir_addr, NUM_PAGES(sizeof(struct ipir_hw))); + if (ipir_ptr == INVALID_VA) { + ERROR("Mapping IPIR failed"); + } + ipir = (struct ipir_hw*)ipir_ptr; + + interrupts_ipi_id = interrupts_reserve(IPI_HYP_IRQ_ID, ipir_handle); + if (interrupts_ipi_id == INVALID_IRQID) { + ERROR("Failed to reserve IPIR interrupt"); + } + + ipir_ready = true; + } + + cpu_sync_and_clear_msgs(&cpu_glb_sync); + + ipir->self[IPI_HYP_IRQ_ID].IPInEN = ((1 << PLAT_CPU_NUM) - 1); +} + +bool vipir_emul_handler(struct emul_access* acc) +{ + struct vcpu* vcpu = cpu()->vcpu; + struct vm* vm = vcpu->vm; + + size_t acc_offset = acc->addr - platform.arch.ipir_addr; + uint8_t bitop_mask = 0; + cpuid_t pe_idx = 0; + size_t chann_idx = 0; + volatile uint8_t* tgt_reg = NULL; + bool self = false; + bool ignore = false; + + size_t ipir_self_bot = offsetof(struct ipir_hw, self); + size_t ipir_self_top = sizeof(((struct ipir_hw*)NULL)->self) + ipir_self_bot; + size_t ipir_pe_bot = offsetof(struct ipir_hw, pe); + size_t ipir_pe_top = sizeof(((struct ipir_hw*)NULL)->pe) + ipir_pe_bot; + + /* Determine whether the access was made to the self region or to a PEm region */ + if (acc_offset >= ipir_self_bot && acc_offset < ipir_self_top) { + /* If the access was made to a self register, redirect + the access to the corresponding PEm register of the CPU */ + pe_idx = vcpu->phys_id; + self = true; + } + else if (acc_offset >= ipir_pe_bot && acc_offset < ipir_pe_top) { + /* If the access was made to a PEm register, check whether the CPU + corresponding to the target register belongs to the VM */ + pe_idx = (acc_offset - ipir_pe_bot) >> 8; + if (!(vm->cpus & (1UL << pe_idx))) + ignore = true; + } + else { + ignore = true; + } + + /* Determine target IPIR register */ + switch (acc->addr & IPIR_REGS_PAT_MASK) { + case IPInENS_PAT: + ignore = !decode_ipir_chann(&chann_idx, IPInEN, acc_offset, self); + tgt_reg = &(ipir->pe[pe_idx].chann[chann_idx].IPInEN); + break; + case IPInFLGS_PAT: + ignore = !decode_ipir_chann(&chann_idx, IPInFLG, acc_offset, self); + tgt_reg = &(ipir->pe[pe_idx].chann[chann_idx].IPInFLG); + break; + case IPInFCLRS_PAT: + ignore = !decode_ipir_chann(&chann_idx, IPInFCLR, acc_offset, self); + tgt_reg = &(ipir->pe[pe_idx].chann[chann_idx].IPInFCLR); + break; + case IPInREQS_PAT: + ignore = !decode_ipir_chann(&chann_idx, IPInREQ, acc_offset, self); + tgt_reg = &(ipir->pe[pe_idx].chann[chann_idx].IPInREQ); + break; + case IPInRCLRS_PAT: + ignore = !decode_ipir_chann(&chann_idx, IPInRCLR, acc_offset, self); + tgt_reg = &(ipir->pe[pe_idx].chann[chann_idx].IPInRCLR); + break; + default: + ignore = true; + break; + } + + if (chann_idx == IPI_HYP_IRQ_ID) + ignore = true; + + /* Ignore access */ + if (ignore) { + if (!acc->write && acc->arch.op == NO_OP) + vcpu_writereg(vcpu, acc->reg, 0); + return true; + } + + /* Translate access */ + if (acc->arch.op != NO_OP) { + + for (size_t i = 0; i < vcpu->vm->cpu_num; i++) { + if ((1U << i) & acc->arch.byte_mask) { + size_t phys_id = vm->vcpus[i].phys_id; + bitop_mask = (uint8_t)(1U << phys_id); + break; + } + } + + unsigned long psw = get_gmpsw(); + if (*tgt_reg & bitop_mask) + set_gmpsw(psw & ~PSW_Z); + else + set_gmpsw(psw | PSW_Z); + + switch (acc->arch.op) + { + case SET1: + *tgt_reg |= bitop_mask; + break; + case NOT1: + *tgt_reg = (uint8_t)((*tgt_reg & bitop_mask) ? + (*tgt_reg & ~bitop_mask) : + (*tgt_reg | bitop_mask)); + break; + case CLR1: + *tgt_reg &= (uint8_t)(~bitop_mask); + break; + /* TST1 only modifies the PSW.Z flag */ + default: + break; + } + } + else if (acc->write) { + unsigned long val = vcpu_readreg(vcpu, acc->reg); + unsigned long write_val = 0; + for (size_t i = 0; i < vcpu->vm->cpu_num; i++) { + size_t virt_id = vm->vcpus[i].id; + size_t phys_id = vm->vcpus[i].phys_id; + if (phys_id >= virt_id) + write_val |= ((val & (1UL << virt_id)) << (phys_id - virt_id)); + else + write_val |= ((val & (1UL << virt_id)) >> (virt_id - phys_id)); + } + *tgt_reg = (uint8_t)((*tgt_reg & ~vm->cpus) | (write_val & vm->cpus)); + } + else { + unsigned long val = *tgt_reg; + unsigned long read_val = 0; + for (size_t i = 0; i < vcpu->vm->cpu_num; i++) { + size_t virt_id = vm->vcpus[i].id; + size_t phys_id = vm->vcpus[i].phys_id; + if (phys_id >= virt_id) + read_val |= (val & (1UL << phys_id)) >> (phys_id - virt_id); + else + read_val |= (val & (1UL << phys_id)) << (virt_id - phys_id); + } + vcpu_writereg(vcpu, acc->reg, read_val); + } + return true; +} + +void vipir_init(struct vm* vm) +{ + if (cpu()->id == vm->master) { + vm->arch.ipir_emul = (struct emul_mem){ + .va_base = platform.arch.ipir_addr, + .size = ALIGN(sizeof(struct ipir_hw), PAGE_SIZE), + .handler = vipir_emul_handler, + }; + vm_emul_add_mem(vm, &vm->arch.ipir_emul); + + // TODO: Add spinlock for IPIR emulation? + } + + /* Reserve IPIR channels not used by the hypervisor */ + for (size_t i = 0; i < IPIR_NUM_CHANNELS; i++) + { + if (i != IPI_HYP_IRQ_ID) { + if (!interrupts_vm_assign(vm, i)) { + ERROR("Failed to reserve VM IPIR channel interrupt"); + } + } + } +} \ No newline at end of file diff --git a/src/arch/rh850/mem.c b/src/arch/rh850/mem.c new file mode 100644 index 000000000..245360541 --- /dev/null +++ b/src/arch/rh850/mem.c @@ -0,0 +1,71 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include + +void as_arch_init(struct addr_space* as) +{ + UNUSED_ARG(as); +} + +void mpu_init(void) +{ + mpu_arch_init(); +} + +void mpu_enable(void) +{ + mpu_arch_enable(); +} + +bool mpu_map(struct addr_space* as, struct mp_region* mem, bool locked) +{ + bool failed = true; + UNUSED_ARG(as); + UNUSED_ARG(locked); + + /* Add region to MPU */ + if (!mpu_add_region(mem, false)) { + ERROR("failed to register mpu entry"); + } else { + failed = false; + } + return !failed; +} + +bool mpu_unmap(struct addr_space* as, struct mp_region* mem) +{ + bool failed = true; + UNUSED_ARG(as); + + if (!mpu_remove_region(mem)) { + ERROR("failed to register mpu entry"); + } else { + failed = false; + } + + return !failed; +} + +bool mpu_update(struct addr_space* as, struct mp_region* mpr) +{ + bool failed = true; + UNUSED_ARG(as); + + /* Remove region */ + if (!mpu_update_region(mpr)) { + ERROR("failed to register mpu entry"); + } else { + failed = false; + } + + return !failed; +} + +bool mpu_perms_compatible(uint32_t perms1, uint32_t perms2) +{ + return perms1 == perms2; +} diff --git a/src/arch/rh850/mpu.c b/src/arch/rh850/mpu.c new file mode 100644 index 000000000..11ce18e19 --- /dev/null +++ b/src/arch/rh850/mpu.c @@ -0,0 +1,229 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include +#include + +static inline size_t mpu_num_entries(void) +{ + unsigned long mpcfg = get_mpcfg(); + size_t num = (mpcfg & 0x1f) + 1; + return num; +} + +static inline void mpu_lock_entry(mpid_t mpid) +{ + bitmap_set(cpu()->arch.mpu_hyp.locked, mpid); +} + +// static inline bool mpu_entry_locked(mpid_t mpid) +// { +// return !!bitmap_get(cpu()->arch.mpu_hyp.locked, mpid); +// } + +static void mpu_entry_set(mpid_t mpid, struct mp_region *mpr) +{ + unsigned long lim = mpr->base + mpr->size - 4; + + set_mpidx(mpid & MPIDX_IDX_MASK); + set_mpla(mpr->base & MPLA_MASK); + set_mpua(lim & MPUA_MASK); + set_mpat(mpr->mem_flags.raw); +} + +static void mpu_entry_clear(mpid_t mpid) +{ + set_mpidx(mpid & MPIDX_IDX_MASK); + set_mpla(0); + set_mpua(0); + set_mpat(0); +} + +// // TODO: add hyp mpu entry counter to prevent guest mpu entries from +// // spiling into hyp entries +// static mpid_t mpu_entry_allocate_guest(void) +// { +// mpid_t reg_num = INVALID_MPID; +// for (mpid_t i = 0; i < (mpid_t)mpu_num_entries(); i++) { +// mpid_t idx = i - 1; +// if (bitmap_get(cpu()->arch.mpu_hyp.bitmap, idx) == 0) { +// bitmap_set(cpu()->arch.mpu_hyp.bitmap, idx); +// reg_num = idx; + +// // Update HBE +// unsigned long mpcfg = get_mpcfg(); + +// // spiling into hyp entries +// unsigned long hbe = (reg_num + 1) << MPCFG_HBE_OFF; +// mpcfg = (mpcfg & ~MPCFG_HBE_MASK) | hbe; +// set_mpcfg(mpcfg); +// break; +// } +// } + +// return reg_num; +// } + +static mpid_t mpu_entry_allocate_hyp(void) +{ + mpid_t reg_num = INVALID_MPID; + for (mpid_t i = (mpid_t)mpu_num_entries(); i > 0; i--) { + mpid_t idx = i - 1; + if (bitmap_get(cpu()->arch.mpu_hyp.bitmap, idx) == 0) { + bitmap_set(cpu()->arch.mpu_hyp.bitmap, idx); + reg_num = idx; + + break; + } + } + + return reg_num; +} + +bool mpu_add_region(struct mp_region *reg, bool locked) +{ + bool failed = true; + + if (reg->size > 0) { + mpid_t mpid = 0; + mpid = mpu_entry_allocate_hyp(); + + if (mpid != INVALID_MPID) { + failed = false; + mpu_entry_set(mpid, reg); + if (locked) { + mpu_lock_entry(mpid); + } + } + } + + return !failed; +} + +static void mpu_entry_get_region(mpid_t mpid, struct mp_region *mpe) +{ + set_mpidx(mpid & MPIDX_IDX_MASK); + + unsigned long base = get_mpla(); + unsigned long limit = get_mpua(); + + mpe->mem_flags.raw = get_mpat(); + mpe->base = base; + mpe->size = (limit - base) + 4; + mpe->as_sec = SEC_UNKNOWN; +} + +static mpid_t mpu_entry_get_region_id(struct mp_region *mpe) +{ + mpid_t mpid = INVALID_MPID; + + for (mpid_t i = 0; i < (mpid_t)mpu_num_entries(); i++) { + if (bitmap_get(cpu()->arch.mpu_hyp.bitmap, i)) { + struct mp_region mpe_cmp; + mpu_entry_get_region(i, &mpe_cmp); + + if (mpe_cmp.base == mpe->base && mpe_cmp.size == mpe->size) { + mpid = i; + break; + } + } + } + + return mpid; +} + +static inline void mpu_entry_free(mpid_t mpid) +{ + mpu_entry_clear(mpid); + bitmap_clear(cpu()->arch.mpu_hyp.bitmap, mpid); +} + +bool mpu_remove_region(struct mp_region *reg) +{ + bool failed = true; + + if (reg->size > 0) + { + mpid_t mpid = mpu_entry_get_region_id(reg); + + if (mpid != INVALID_MPID) + { + failed = false; + mpu_entry_free(mpid); + } + } + + return !failed; +} + +bool mpu_update_region(struct mp_region *mpr) +{ + bool failed = true; + + for (mpid_t mpid = 0; mpid < (mpid_t)mpu_num_entries(); mpid++) + { + if (bitmap_get(cpu()->arch.mpu_hyp.bitmap, mpid) == 0) + { + continue; + } + struct mp_region mpe_cmp; + mpu_entry_get_region(mpid, &mpe_cmp); + + if (mpe_cmp.base == mpr->base) + { + mpu_entry_set(mpid, mpr); + failed = false; + break; + } + } + + return !failed; +} + +static inline bool mpu_entry_valid(mpid_t mpid) +{ + set_mpidx(mpid & MPIDX_IDX_MASK); + unsigned long attr = get_mpat(); + unsigned long valid_bit = (attr & (1 << 7)) >> 7; + + return !!valid_bit; +} + +void mpu_arch_init(void) +{ + bitmap_clear_consecutive(cpu()->arch.mpu_hyp.bitmap, 0, mpu_num_entries()); + + for (mpid_t mpid = 0; mpid < (mpid_t)mpu_num_entries(); mpid++) { + /* No entry should be valid at this point */ + if (mpu_entry_valid(mpid)) { + bitmap_set(cpu()->arch.mpu_hyp.bitmap, mpid); + bitmap_set(cpu()->arch.mpu_hyp.locked, mpid); + } + } + + unsigned long mpcfg = get_mpcfg(); + // give all entries to the hypervisor + unsigned long hbe = 0; + mpcfg = (mpcfg & ~MPCFG_HBE_MASK) | hbe; + set_mpcfg(mpcfg); + + /* At this point we configure MPIDs as PEID to perform platform initialization */ + unsigned long peid = get_peid(); + set_mpid0(peid); + set_spid(peid); +} + +void mpu_arch_enable(void) +{ + set_mpm(MPM_SVP | MPM_MPE); +} + +void mpu_arch_disable(void) +{ + unsigned long mpm = get_mpm() & ~MPM_MPE; + set_mpm(mpm); +} diff --git a/src/arch/rh850/objects.mk b/src/arch/rh850/objects.mk new file mode 100644 index 000000000..c2785aea1 --- /dev/null +++ b/src/arch/rh850/objects.mk @@ -0,0 +1,17 @@ +## SPDX-License-Identifier: Apache-2.0 +## Copyright (c) Bao Project and Contributors. All rights reserved. + +cpu-objs-y+=aborts.o +cpu-objs-y+=boot.o +cpu-objs-y+=cache.o +cpu-objs-y+=cpu.o +cpu-objs-y+=exceptions.o +cpu-objs-y+=intc.o +cpu-objs-y+=ipir.o +cpu-objs-y+=interrupts.o +cpu-objs-y+=mem.o +cpu-objs-y+=mpu.o +cpu-objs-y+=vintc.o +cpu-objs-y+=vm.o +cpu-objs-y+=vmm.o + diff --git a/src/arch/rh850/vintc.c b/src/arch/rh850/vintc.c new file mode 100644 index 000000000..44de89b7e --- /dev/null +++ b/src/arch/rh850/vintc.c @@ -0,0 +1,582 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern volatile struct intc1* intc1_hw; +extern volatile struct intc2* intc2_hw; +extern volatile struct intif* intif_hw; +extern volatile struct eint* eint_hw; +extern volatile struct fenc* fenc_hw; +extern volatile struct feinc* feinc_hw[PLAT_CPU_NUM]; + + +void vintc_inject(struct vcpu* vcpu, irqid_t int_id) +{ + struct vm* vm = vcpu->vm; + + if (!vm_has_interrupt(vm, int_id)) { + ERROR("VM tried to access unassigned interrupt"); + } + intc_set_pend(int_id, true); +} + +static void emulate_intc_eic_access(struct emul_access* acc, size_t reg_idx, unsigned long mask) +{ + struct vcpu* vcpu = cpu()->vcpu; + struct vm* vm = vcpu->vm; + + size_t addr_off = acc->addr & 0x1UL; + uint16_t bitop_mask = (uint16_t)(acc->arch.byte_mask << (addr_off * 8)); + irqid_t int_id = 0; + volatile uint16_t* tgt_reg = NULL; + + if (acc->addr < platform.arch.intc.intc1_addr) { /* INTC2 */ + int_id = reg_idx + 32; + tgt_reg = &(intc2_hw->EIC[reg_idx]); + } + else { /* INTC1 */ + int_id = reg_idx; + tgt_reg = &(intc1_hw->EIC[reg_idx]); + } + + if (!vm_has_interrupt(vm, int_id)) { + ERROR("VM tried to access unassigned interrupt"); + } + + /* bit manipulation instruction */ + if (acc->arch.op != NO_OP) { + + unsigned long psw = get_gmpsw(); + if (*tgt_reg & bitop_mask) + set_gmpsw(psw & ~PSW_Z); + else + set_gmpsw(psw | PSW_Z); + + switch (acc->arch.op) + { + case SET1: + *tgt_reg |= bitop_mask; + break; + case NOT1: + *tgt_reg = (uint16_t)((*tgt_reg & bitop_mask) ? + (*tgt_reg & ~bitop_mask) : + (*tgt_reg | bitop_mask)); + break; + case CLR1: + *tgt_reg &= (uint16_t)(~bitop_mask); + break; + /* TST1 only modifies the PSW.Z flag */ + default: + break; + } + } + else if (acc->write) { + unsigned long val = vcpu_readreg(vcpu, acc->reg); + *tgt_reg = (uint16_t)(((val & mask) << (addr_off * 8)) | + (*tgt_reg & ~(mask << (addr_off * 8)))); + } + else { + unsigned long val = *tgt_reg; + + val = (val >> (addr_off * 8)) & mask; + if (acc->sign_ext && (1UL << ((acc->reg_width * 8) + 7) & val)) { + val |= ~mask; + } + + vcpu_writereg(vcpu, acc->reg, val); + } +} + +static void emulate_intc_imr_access(struct emul_access* acc, size_t reg_idx, uint32_t mask) +{ + struct vcpu* vcpu = cpu()->vcpu; + struct vm* vm = vcpu->vm; + + size_t addr_off = acc->addr & 0x3UL; + uint32_t bitop_mask = acc->arch.byte_mask << (addr_off * 8); + irqid_t int_id = 0; + irqid_t first_imr_int = 0; + volatile uint32_t* tgt_reg = NULL; + + if (acc->addr < platform.arch.intc.intc1_addr) { /* INTC2 */ + first_imr_int = reg_idx * 32 + 32; + tgt_reg = &(intc2_hw->IMR[reg_idx]); + } + else { /* INTC1 */ + first_imr_int = 0; + tgt_reg = &(intc1_hw->IMR); + } + + /* bit manipulation instruction */ + if (acc->arch.op != NO_OP) { + + for (unsigned int i = first_imr_int; i < first_imr_int + 32; i++) { + if ((1UL << (i % 32)) & bitop_mask) { + int_id = i; + break; + } + } + + if (int_id == IPI_HYP_IRQ_ID) + bitop_mask = 0; + else if (!vm_has_interrupt(vm, int_id)) { + ERROR("VM tried to access unassigned interrupt"); + } + + unsigned long psw = get_gmpsw(); + if (*tgt_reg & bitop_mask) + set_gmpsw(psw & ~PSW_Z); + else + set_gmpsw(psw | PSW_Z); + + switch (acc->arch.op) + { + case SET1: + *tgt_reg |= bitop_mask; + break; + case NOT1: + *tgt_reg = (*tgt_reg & bitop_mask) ? + (*tgt_reg & ~bitop_mask) : + (*tgt_reg | bitop_mask); + break; + case CLR1: + *tgt_reg &= ~bitop_mask; + break; + /* TST1 only modifies the PSW.Z flag */ + default: + break; + } + } + else if (acc->write) { + unsigned long val = vcpu_readreg(vcpu, acc->reg); + unsigned long write_val = *tgt_reg; + + for (unsigned int i = first_imr_int; i < first_imr_int + 32; i++) { + + if (!vm_has_interrupt(vm, i) || (int_id == IPI_HYP_IRQ_ID)) { + continue; + } + + unsigned int imr_bit = (i % 32); + if ((1UL << imr_bit) & val) + write_val |= (1UL << imr_bit); + else + write_val &= ~(1UL << imr_bit); + } + *tgt_reg = ((write_val & mask) << (addr_off * 8)) | + (*tgt_reg & ~(mask << (addr_off * 8))); + } else { + unsigned long val = 0; + + for (unsigned int i = first_imr_int; i < first_imr_int + 32; i++) { + if (!vm_has_interrupt(vm, i) || (int_id == IPI_HYP_IRQ_ID)) { + continue; + } + + unsigned int imr_bit = (i % 32); + unsigned int imr_val = *tgt_reg; + if ((1UL << imr_bit) & imr_val) { + val |= (1UL << imr_bit); + } + } + + val = (val >> (addr_off * 8)) & mask; + if (acc->sign_ext && (1UL << ((acc->reg_width * 8) + 7) & val)) { + val |= ~mask; + } + vcpu_writereg(vcpu, acc->reg, val); + } +} + +static void emulate_intc_eibd_access(struct emul_access* acc, size_t reg_idx, uint32_t mask) +{ + struct vcpu* vcpu = cpu()->vcpu; + struct vm* vm = vcpu->vm; + + size_t addr_off = acc->addr & 0x3UL; + uint32_t bitop_mask = (acc->arch.byte_mask << (addr_off * 8)) & 0xFFFF0000; + irqid_t int_id = 0; + volatile uint32_t* tgt_reg = NULL; + + if (acc->addr < platform.arch.intc.intc1_addr) { /* INTC2 */ + int_id = reg_idx + 32; + tgt_reg = &(intc2_hw->EIBD[reg_idx]); + } + else { /* INTC1 */ + int_id = reg_idx; + tgt_reg = &(intc1_hw->EIBD[reg_idx]); + } + + if (!vm_has_interrupt(vm, int_id)) { + ERROR("VM tried to access unassigned interrupt"); + } + + /* we use 0xFFFF0000 to mask access to virtualization configuration */ + /* bit manipulation instruction */ + if (acc->arch.op != NO_OP) { + + unsigned long psw = get_gmpsw(); + if (*tgt_reg & bitop_mask) + set_gmpsw(psw & ~PSW_Z); + else + set_gmpsw(psw | PSW_Z); + + switch (acc->arch.op) + { + case SET1: + *tgt_reg |= bitop_mask; + break; + case NOT1: + *tgt_reg = (*tgt_reg & bitop_mask) ? + (*tgt_reg & ~bitop_mask) : + (*tgt_reg | bitop_mask); + break; + case CLR1: + *tgt_reg &= ~bitop_mask; + break; + /* TST1 only modifies the PSW.Z flag */ + default: + break; + } + } + else if (acc->write) { + unsigned long val = vcpu_readreg(vcpu, acc->reg); + unsigned long virt_peid = val & 0x7UL; + unsigned long phys_peid = vm_translate_to_pcpuid(vm, virt_peid); + if (phys_peid != INVALID_CPUID) + val = (val & 0xFFFF0000) | (*tgt_reg & 0xFFF8) | (phys_peid & 0x7UL); + else + val = (val & 0xFFFF0000) | (*tgt_reg & ~0xFFFF0000); + *tgt_reg = ((val & mask) << (addr_off * 8)) | + (*tgt_reg & ~(mask << (addr_off * 8))); + } + else { + unsigned long val = *tgt_reg; + unsigned long phys_peid = val & 0x7UL; + unsigned long virt_peid = INVALID_CPUID; + for (size_t i = 0; i < vm->cpu_num; i++) { + if (vm->vcpus[i].phys_id == phys_peid) + virt_peid = vm->vcpus[i].id; + } + if (virt_peid != INVALID_CPUID) + val = (val & 0xFFFF0000) | (virt_peid & 0x7UL); + else + val = (val & 0xFFFF0000); + + val = (val >> (addr_off * 8)) & mask; + if (acc->sign_ext && (1UL << ((acc->reg_width * 8) + 7) & val)) { + val |= ~mask; + } + + vcpu_writereg(vcpu, acc->reg, val); + } +} + +static void emulate_intc_fibd_access(struct emul_access* acc, uint32_t mask) +{ + struct vcpu* vcpu = cpu()->vcpu; + struct vm* vm = vcpu->vm; + + size_t addr_off = acc->addr & 0x3UL; + volatile uint32_t* tgt_reg = &(intc1_hw->FIBD); + + if (acc->arch.op != NO_OP || acc->write) { + /* FIBD register can not be written/modified by any guest */ + } + else { + unsigned long val = 0; + unsigned long phys_peid = *tgt_reg & 0x7UL; + unsigned long virt_peid = INVALID_CPUID; + for (size_t i = 0; i < vm->cpu_num; i++) { + if (vm->vcpus[i].phys_id == phys_peid) + virt_peid = vm->vcpus[i].id; + } + if (virt_peid != INVALID_CPUID) + val = virt_peid & 0x7UL; + + val = (val >> (addr_off * 8)) & mask; + if (acc->sign_ext && (1UL << ((acc->reg_width * 8) + 7) & val)) { + val |= ~mask; + } + + vcpu_writereg(vcpu, acc->reg, val); + } +} + +static void emulate_intc_eeic_access(struct emul_access* acc, size_t reg_idx, uint32_t mask) +{ + struct vcpu* vcpu = cpu()->vcpu; + struct vm* vm = vcpu->vm; + + size_t addr_off = acc->addr & 0x3UL; + uint32_t bitop_mask = acc->arch.byte_mask << (addr_off * 8); + irqid_t int_id = 0; + volatile uint32_t* tgt_reg = NULL; + + if (acc->addr < platform.arch.intc.intc1_addr) { /* INTC2 */ + int_id = reg_idx + 32; + tgt_reg = &(intc2_hw->EEIC[reg_idx]); + } + else { /* INTC1 */ + int_id = reg_idx; + tgt_reg = &(intc1_hw->EEIC[reg_idx]); + } + + if (!vm_has_interrupt(vm, int_id)) { + ERROR("VM tried to access unassigned interrupt"); + } + + /* bit manipulation instruction */ + if (acc->arch.op != NO_OP) { + + unsigned long psw = get_gmpsw(); + if (*tgt_reg & bitop_mask) + set_gmpsw(psw & ~PSW_Z); + else + set_gmpsw(psw | PSW_Z); + + switch (acc->arch.op) + { + case SET1: + *tgt_reg |= bitop_mask; + break; + case NOT1: + *tgt_reg = (*tgt_reg & bitop_mask) ? + (*tgt_reg & ~bitop_mask) : + (*tgt_reg | bitop_mask); + break; + case CLR1: + *tgt_reg &= ~bitop_mask; + break; + /* TST1 only modifies the PSW.Z flag */ + default: + break; + } + } + else if (acc->write) { + unsigned long val = vcpu_readreg(vcpu, acc->reg); + *tgt_reg = ((val & mask) << (addr_off * 8)) | + (*tgt_reg & ~(mask << (addr_off * 8))); + } + else { + unsigned long val = *tgt_reg; + + val = (val >> (addr_off * 8)) & mask; + if (acc->sign_ext && (1UL << ((acc->reg_width * 8) + 7) & val)) { + val |= ~mask; + } + + vcpu_writereg(vcpu, acc->reg, val); + } +} + +bool vintc1_emul_handler(struct emul_access* acc) +{ + size_t acc_offset = acc->addr - platform.arch.intc.intc1_addr; + unsigned long mask = ((1U << (8 * (acc->reg_width + 1))) - 1) + | ((acc->reg_width == 2) * 0xFF000000); + + size_t intc1_eic_bot = offsetof(struct intc1, EIC); + size_t intc1_eic_top = sizeof(((struct intc1*)NULL)->EIC) + intc1_eic_bot; + size_t intc1_eic_idx = (ALIGN(acc_offset - intc1_eic_bot, 2)) / 2; + if (acc_offset >= intc1_eic_bot && acc_offset < intc1_eic_top && + intc1_eic_idx != IPI_HYP_IRQ_ID) { + emulate_intc_eic_access(acc, intc1_eic_idx, mask); + return true; + } + + size_t intc1_imr_bot = offsetof(struct intc1, IMR); + size_t intc1_imr_top = sizeof(((struct intc1*)NULL)->IMR) + intc1_imr_bot; + size_t intc1_imr_idx = (ALIGN(acc_offset - intc1_imr_bot, 4)) / 4; + if (acc_offset >= intc1_imr_bot && acc_offset < intc1_imr_top) { + emulate_intc_imr_access(acc, intc1_imr_idx, mask); + return true; + } + + size_t intc1_eibd_bot = offsetof(struct intc1, EIBD); + size_t intc1_eibd_top = sizeof(((struct intc1*)NULL)->EIBD) + intc1_eibd_bot; + size_t intc1_eibd_idx = (ALIGN(acc_offset - intc1_eibd_bot, 4)) / 4; + if (acc_offset >= intc1_eibd_bot && acc_offset < intc1_eibd_top && + intc1_eibd_idx != IPI_HYP_IRQ_ID) { + emulate_intc_eibd_access(acc, intc1_eibd_idx, mask); + return true; + } + + size_t intc1_fibd_bot = offsetof(struct intc1, FIBD); + size_t intc1_fibd_top = sizeof(((struct intc1*)NULL)->FIBD) + intc1_fibd_bot; + if (acc_offset >= intc1_fibd_bot && acc_offset < intc1_fibd_top) { + emulate_intc_fibd_access(acc, mask); + return true; + } + + size_t intc1_eeic_bot = offsetof(struct intc1, EEIC); + size_t intc1_eeic_top = sizeof(((struct intc1*)NULL)->EEIC) + intc1_eeic_bot; + size_t intc1_eeic_idx = (ALIGN(acc_offset - intc1_eeic_bot, 4)) / 4; + if (acc_offset >= intc1_eeic_bot && acc_offset < intc1_eeic_top && + intc1_eeic_idx != IPI_HYP_IRQ_ID) { + emulate_intc_eeic_access(acc, intc1_eeic_idx, mask); + return true; + } + + /* Ignore access */ + if (!acc->write && acc->arch.op == NO_OP) + vcpu_writereg(cpu()->vcpu, acc->reg, 0); + + return true; +} + +bool vintc2_emul_handler(struct emul_access* acc) +{ + size_t acc_offset = acc->addr - platform.arch.intc.intc2_addr; + unsigned long mask = ((1U << (8 * (acc->reg_width + 1))) - 1) + | ((acc->reg_width == 2) * 0xFF000000); + + size_t intc2_eic_bot = offsetof(struct intc2, EIC); + size_t intc2_eic_top = sizeof(((struct intc2*)NULL)->EIC) + intc2_eic_bot; + size_t intc2_eic_idx = (ALIGN(acc_offset - intc2_eic_bot, 2)) / 2; + if (acc_offset >= intc2_eic_bot && acc_offset < intc2_eic_top) { + emulate_intc_eic_access(acc, intc2_eic_idx, mask); + return true; + } + + size_t intc2_imr_bot = offsetof(struct intc2, IMR); + size_t intc2_imr_top = sizeof(((struct intc2*)NULL)->IMR) + intc2_imr_bot; + size_t intc2_imr_idx = (ALIGN(acc_offset - intc2_imr_bot, 4)) / 4; + if (acc_offset >= intc2_imr_bot && acc_offset < intc2_imr_top) { + emulate_intc_imr_access(acc, intc2_imr_idx, mask); + return true; + } + + size_t intc2_eibd_bot = offsetof(struct intc2, EIBD); + size_t intc2_eibd_top = sizeof(((struct intc2*)NULL)->EIBD) + intc2_eibd_bot; + size_t intc2_eibd_idx = (ALIGN(acc_offset - intc2_eibd_bot, 4)) / 4; + if (acc_offset >= intc2_eibd_bot && acc_offset < intc2_eibd_top) { + emulate_intc_eibd_access(acc, intc2_eibd_idx, mask); + return true; + } + + size_t intc2_eeic_bot = offsetof(struct intc2, EEIC); + size_t intc2_eeic_top = sizeof(((struct intc2*)NULL)->EEIC) + intc2_eeic_bot; + size_t intc2_eeic_idx = (ALIGN(acc_offset - intc2_eeic_bot, 4)) / 4; + if (acc_offset >= intc2_eeic_bot && acc_offset < intc2_eeic_top) { + emulate_intc_eeic_access(acc, intc2_eeic_idx, mask); + return true; + } + + /* Ignore access */ + if (!acc->write && acc->arch.op == NO_OP) + vcpu_writereg(cpu()->vcpu, acc->reg, 0); + + return true; +} + +bool vintif_emul_handler(struct emul_access* acc) +{ + UNUSED_ARG(acc); + ERROR("%s not implemented", __func__); +} + +bool veint_emul_handler(struct emul_access* acc) +{ + UNUSED_ARG(acc); + ERROR("%s not implemented", __func__); +} + +bool vfenc_emul_handler(struct emul_access* acc) +{ + UNUSED_ARG(acc); + ERROR("%s not implemented", __func__); +} + +bool vfeinc_emul_handler(struct emul_access* acc) +{ + UNUSED_ARG(acc); + ERROR("%s not implemented", __func__); +} + +void vintc_init(struct vm* vm) +{ + if (cpu()->id == vm->master) { + + vm->arch.intc1_emul = (struct emul_mem){ + .va_base = platform.arch.intc.intc1_addr, + .size = ALIGN(sizeof(struct intc1), PAGE_SIZE), + .handler = vintc1_emul_handler, + }; + vm_emul_add_mem(vm, &vm->arch.intc1_emul); + + vm->arch.intc2_emul = (struct emul_mem){ + .va_base = platform.arch.intc.intc2_addr, + .size = ALIGN(sizeof(struct intc2), PAGE_SIZE), + .handler = vintc2_emul_handler, + }; + vm_emul_add_mem(vm, &vm->arch.intc2_emul); + + /* of the following which can we bypass? */ + vm->arch.intif_emul = (struct emul_mem){ + .va_base = platform.arch.intc.intif_addr, + .size = ALIGN(sizeof(struct intif), PAGE_SIZE), + .handler = vintif_emul_handler, + }; + vm_emul_add_mem(vm, &vm->arch.intif_emul); + + vm->arch.eint_emul = (struct emul_mem){ + .va_base = platform.arch.intc.eint_addr, + .size = ALIGN(sizeof(struct eint), PAGE_SIZE), + .handler = veint_emul_handler, + }; + vm_emul_add_mem(vm, &vm->arch.eint_emul); + + vm->arch.fenc_emul = (struct emul_mem){ + .va_base = platform.arch.intc.fenc_addr, + .size = ALIGN(sizeof(struct fenc), PAGE_SIZE), + .handler = vfenc_emul_handler, + }; + vm_emul_add_mem(vm, &vm->arch.fenc_emul); + + vm->arch.feinc_emul = (struct emul_mem){ + .va_base = platform.arch.intc.feinc_addr[cpu()->id], + .size = ALIGN(sizeof(struct feinc), PAGE_SIZE), + .handler = vfeinc_emul_handler, + }; + vm_emul_add_mem(vm, &vm->arch.feinc_emul); + + // TODO: Add spinlock for INTC emulation + } +} + +void vintc_vcpu_reset(struct vcpu* vcpu) { + for (size_t i = 0; i < PRIVATE_IRQS_NUM; i++) { + if (vm_has_interrupt(vcpu->vm, i)) { + intc_set_trgt(i, vcpu->phys_id); + intc_set_enable(i, false); + intc_set_prio(i, 0); + // intc_set_act(i, false); + intc_set_pend(i, false); + } + } +} + +void vintc_vm_reset(struct vm* vm) { + if (vm->master == cpu()->id) { + for (size_t i = PRIVATE_IRQS_NUM; i < MAX_INTERRUPTS; i++) { + if (vm_has_interrupt(vm, i)) { + intc_set_trgt(i, cpu()->id); + intc_set_enable(i, false); + intc_set_prio(i, 0); + // intc_set_act(i, false); + intc_set_pend(i, false); + } + } + } +} diff --git a/src/arch/rh850/vm.c b/src/arch/rh850/vm.c new file mode 100644 index 000000000..c97be7ead --- /dev/null +++ b/src/arch/rh850/vm.c @@ -0,0 +1,194 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include +#include +#include + +void vm_arch_init(struct vm* vm, const struct vm_config* vm_config) +{ + UNUSED_ARG(vm_config); + + /* All VMs use MPID1 for memory protection */ + set_mpid1(vm->id); + + vintc_init(vm); + vipir_init(vm); + vbootctrl_init(vm); +} + +void vcpu_arch_init(struct vcpu* vcpu, struct vm* vm) +{ + UNUSED_ARG(vm); + UNUSED_ARG(vcpu); +} + +void vcpu_arch_reset(struct vcpu* vcpu, vaddr_t entry) +{ + struct vm* vm = vcpu->vm; + + memset(&vcpu->regs, 0, sizeof(struct arch_regs)); + + vcpu_writepc(vcpu, entry); + set_eipc(entry); + + vcpu->arch.started = vcpu->id == 0 ? true : false; + + /* Bao fixes the VMID as SPID to isolate VM memory regions */ + vcpu->regs.spid = vm->id; + set_gmspid(vm->id); + set_gmspidlist(0x0); + + set_gmmpm(GMMPM_GMPE); + + unsigned long eipswh = get_eipswh() & ~EIPSWH_GPID_MASK; + set_eipswh(eipswh | (vm->id << EIPSWH_GPID_OFF)); + + unsigned long fepswh = get_fepswh() & ~FEPSWH_GPID_MASK; + set_fepswh(fepswh | (vm->id << FEPSWH_GPID_OFF)); + + set_gmpeid(vcpu->id); + + /* clear guest-context exception registers */ + set_gmeipc(0x0); + set_gmfepc(0x0); + set_gmmea(0x0); + set_gmmei(0x0); + set_gmeiic(0x0); + set_gmfeic(0x0); + + vintc_vcpu_reset(vcpu); +} + +bool vcpu_arch_is_on(struct vcpu* vcpu) +{ + return vcpu->arch.started; +} + +unsigned long vcpu_readreg(struct vcpu* vcpu, unsigned long reg) +{ + if (reg > 32) { + ERROR("reading register out of bounds"); + } + + return vcpu->regs.gp_regs.r[reg]; +} + +void vcpu_writereg(struct vcpu* vcpu, unsigned long reg, unsigned long val) +{ + if (reg > 32) { + ERROR("writing register out of bounds"); + } + + vcpu->regs.gp_regs.r[reg] = val; +} + +unsigned long vcpu_readpc(struct vcpu* vcpu) +{ + return vcpu->regs.pc; +} + +void vcpu_writepc(struct vcpu* vcpu, unsigned long val) +{ + vcpu->regs.pc = val; +} + +void vcpu_restore_state(struct vcpu* vcpu) +{ + UNUSED_ARG(vcpu); + ERROR("%s not implemented", __func__); +} + +void vcpu_save_state(struct vcpu* vcpu) +{ + UNUSED_ARG(vcpu); + ERROR("%s not implemented", __func__); +} + +bool vbootctrl_emul_handler(struct emul_access* acc) +{ + struct vcpu* vcpu = cpu()->vcpu; + struct vm* vm = vcpu->vm; + unsigned long notify = 0; + + /* Translate access */ + if (acc->arch.op != NO_OP) { + size_t virt_id = INVALID_CPUID; + + for (size_t i = 0; i < vcpu->vm->cpu_num; i++) { + if ((1U << i) & acc->arch.byte_mask) { + virt_id = vm->vcpus[i].id; + if (!vm->vcpus[i].arch.started) { + notify |= (1UL << vm->vcpus[i].phys_id); + } + break; + } + } + + if (virt_id == INVALID_CPUID) + return true; + + unsigned long psw = get_gmpsw(); + if (vm->vcpus[virt_id].arch.started) + set_gmpsw(psw & ~PSW_Z); + else + set_gmpsw(psw | PSW_Z); + + switch (acc->arch.op) + { + case SET1: + vm->vcpus[virt_id].arch.started = true; + break; + case NOT1: + vm->vcpus[virt_id].arch.started = true; + break; + /* CLR1 accesses are ignored */ + /* TST1 only modifies the PSW.Z flag */ + default: + break; + } + } + else if (acc->write) { + unsigned long val = vcpu_readreg(vcpu, acc->reg); + for (size_t i = 0; i < vcpu->vm->cpu_num; i++) { + if ((1U << i) & val) { + if (!vm->vcpus[i].arch.started) { + notify |= 1UL << vm->vcpus[i].phys_id; + } + vm->vcpus[i].arch.started = true; + } + } + } + else { + unsigned long val = 0; + for (size_t i = 0; i < vcpu->vm->cpu_num; i++) { + if (vm->vcpus[i].arch.started) { + val |= 1UL << i; + } + } + vcpu_writereg(vcpu, acc->reg, val); + } + + /* Notify physical CPUs, if any */ + for (cpuid_t c = 0; c < platform.cpu_num; c++) + if (notify & (1UL << c)) + interrupts_cpu_sendipi(c); + + return true; +} + +void vbootctrl_init(struct vm* vm) +{ + if (cpu()->id == vm->master) { + vm->arch.bootctrl_emul = (struct emul_mem){ + .va_base = platform.arch.bootctrl_addr, + .size = 0x10, + .handler = vbootctrl_emul_handler, + }; + vm_emul_add_mem(vm, &vm->arch.bootctrl_emul); + } +} diff --git a/src/arch/rh850/vmm.c b/src/arch/rh850/vmm.c new file mode 100644 index 000000000..015c89639 --- /dev/null +++ b/src/arch/rh850/vmm.c @@ -0,0 +1,26 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include +#include + +void vmm_arch_init(void) +{ + /* HVCFG.HVE is set after reset */ + + /* configure Hypervisor MPIDs for memory protection */ + mpu_arch_disable(); + set_mpid0(HYP_SPID); + set_mpid7(HYP_AUX_SPID); + set_spid(HYP_SPID); + mpu_arch_enable(); + + set_gmcfg(GMCFG_GCU1 | GMCFG_GCU0 | GMCFG_GSYSE | GMCFG_HMP); + + set_eipswh(EIPSWH_GM); + set_fepswh(FEPSWH_GM); +} diff --git a/src/core/inc/emul.h b/src/core/inc/emul.h index 8a88af42c..430f7ea1d 100644 --- a/src/core/inc/emul.h +++ b/src/core/inc/emul.h @@ -8,6 +8,7 @@ #include #include +#include struct emul_access { vaddr_t addr; @@ -18,6 +19,7 @@ struct emul_access { unsigned long reg_high; bool multi_reg; size_t reg_width; + struct emul_access_arch arch; }; typedef bool (*emul_handler_t)(struct emul_access*); diff --git a/src/platform/drivers/renesas_rlin3/inc/drivers/renesas_rlin3.h b/src/platform/drivers/renesas_rlin3/inc/drivers/renesas_rlin3.h new file mode 100644 index 000000000..4169eb4b7 --- /dev/null +++ b/src/platform/drivers/renesas_rlin3/inc/drivers/renesas_rlin3.h @@ -0,0 +1,72 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef RENESAS_RLIN3_H +#define RENESAS_RLIN3_H + +#include + +#define RLIN3_LWBR_LPRS_16 (0x4 << 1) +#define RLIN3_LWBR_NSPB_10 (0x9 << 4) +#define RLN3_LBFC_UBLS_8B (0) +#define RLN3_LBFC_UBOS_LSB (0) +#define RLN3_LBFC_USBLS_1B (0) +#define RLN3_LBFC_UPS_DIS (0) +#define RLIN3_LMST_OMM0_MSK (1) +#define RLN3_LUOER_UROE (0x1 << 1) +#define RLN3_LUOER_UTOE (0x1 << 0) +#define RLN3_LST_UTS_MSK (0x1 << 4) +#define RLN3_LST_URS_MSK (0x1 << 5) +#define RLN3_LMD_UART_MODE (0x1) +#define RLN3_LCUC_LIN_CANC (0x1) + +struct renesas_rlin3 { + uint8_t pad0[1]; // 0x0 + volatile uint8_t RLN3nLWBR; // 0x1 + volatile uint16_t RLN3nLBRP01; // 0x2 + volatile uint8_t RLN3nLSTC; // 0x4 + volatile uint8_t pad1[3]; // 0x5 + volatile uint8_t RLN3nLMD; // 0x8 + volatile uint8_t RLN3nLBFC; // 0x9 + volatile uint8_t RLN3nLSC; // 0xa + volatile uint8_t RLN3nLWUP; // 0xb + volatile uint8_t RLN3nLIE; // 0xc + volatile uint8_t RLN3nLEDE; // 0xd + volatile uint8_t RLN3nLCUC; // 0xe + volatile uint8_t pad2[1]; // 0xf + volatile uint8_t RLN3nLTRC; // 0x10 + volatile uint8_t RLN3nLMST; // 0x11 + volatile uint8_t RLN3nLST; // 0x12 + volatile uint8_t RLN3nLEST; // 0x13 + volatile uint8_t RLN3nLDFC; // 0x14 + volatile uint8_t RLN3nLIDB; // 0x15 + volatile uint8_t RLN3nLCBR; // 0x16 + volatile uint8_t RLN3nLUDB0; // 0x17 + volatile uint8_t RLN3nLDBR1; // 0x18 + volatile uint8_t RLN3nLDBR2; // 0x19 + volatile uint8_t RLN3nLDBR3; // 0x1a + volatile uint8_t RLN3nLDBR4; // 0x1b + volatile uint8_t RLN3nLDBR5; // 0x1c + volatile uint8_t RLN3nLDBR6; // 0x1d + volatile uint8_t RLN3nLDBR7; // 0x1e + volatile uint8_t RLN3nLDBR8; // 0x1f + volatile uint8_t RLN3nLUOER; // 0x20 + volatile uint8_t RLN3nLUOR1; // 0x21 + uint8_t pad3[2]; // 0x22 + volatile uint16_t RLN3nLUTDR; // 0x24 + volatile uint16_t RLN3nLURDR; // 0x26 + volatile uint16_t RLN3nLUWTDR; // 0x28 + volatile uint8_t RLN3nLBSS; // 0x30 + volatile uint8_t pad4[3]; // 0x31 + volatile uint8_t RLN3nLRSS; // 0x34 +}; + +typedef struct renesas_rlin3 bao_uart_t; + +void uart_enable(volatile struct renesas_rlin3* uart); +void uart_init(volatile struct renesas_rlin3* uart); +void uart_putc(volatile struct renesas_rlin3* uart, int8_t c); + +#endif /* RENESAS_RLIN3_H */ diff --git a/src/platform/drivers/renesas_rlin3/objects.mk b/src/platform/drivers/renesas_rlin3/objects.mk new file mode 100644 index 000000000..489b5e2e2 --- /dev/null +++ b/src/platform/drivers/renesas_rlin3/objects.mk @@ -0,0 +1,4 @@ +## SPDX-License-Identifier: Apache-2.0 +## Copyright (c) Bao Project and Contributors. All rights reserved. + +drivers-objs-y+=renesas_rlin3/renesas_rlin3.o diff --git a/src/platform/drivers/renesas_rlin3/renesas_rlin3.c b/src/platform/drivers/renesas_rlin3/renesas_rlin3.c new file mode 100644 index 000000000..3148fef54 --- /dev/null +++ b/src/platform/drivers/renesas_rlin3/renesas_rlin3.c @@ -0,0 +1,51 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include + +void uart_init(volatile struct renesas_rlin3* uart) +{ + // Set reset mode + uart->RLN3nLCUC = 0; + + while ((uart->RLN3nLMST & RLIN3_LMST_OMM0_MSK) != 0x0) + ; + + uart->RLN3nLWBR = 0; // prescaler reset; + + // Set baud rate to 500000 assuming CLK_RLIN = 80 MHz + uart->RLN3nLWBR = RLIN3_LWBR_LPRS_16 | RLIN3_LWBR_NSPB_10; + uart->RLN3nLBRP01 = 0; + + // // // Set baud rate to 9600 assuming CLK_RLIN = 80 MHz + // uart->RLN3nLWBR = 0x76; + // uart->RLN3nLBRP01 = 0x81; + + // Set data format + uart->RLN3nLBFC = + RLN3_LBFC_UBLS_8B | + RLN3_LBFC_UBOS_LSB | + RLN3_LBFC_USBLS_1B | + RLN3_LBFC_UPS_DIS; + + // Set uart mode + uart->RLN3nLMD = RLN3_LMD_UART_MODE; + uart->RLN3nLCUC = RLN3_LCUC_LIN_CANC; + + while ((uart->RLN3nLMST & RLIN3_LMST_OMM0_MSK) != 0x1) + ; +} + +void uart_enable(volatile struct renesas_rlin3* uart) +{ + uart->RLN3nLUOER = RLN3_LUOER_UROE | RLN3_LUOER_UTOE; +} + +void uart_putc(volatile struct renesas_rlin3* uart, int8_t c) +{ + while (uart->RLN3nLST & RLN3_LST_UTS_MSK); + uart->RLN3nLUTDR = (uint16_t)(c); +} + \ No newline at end of file diff --git a/src/platform/rh850-u2a16/clock.c b/src/platform/rh850-u2a16/clock.c new file mode 100644 index 000000000..5b070e7df --- /dev/null +++ b/src/platform/rh850-u2a16/clock.c @@ -0,0 +1,76 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include + +volatile struct clk_ctl_iso_hw* clk_ctl_iso; +volatile struct clk_ctl_awo_hw* clk_ctl_awo; + +void clock_init(void) { + + size_t stab_cnt = 0; + + /* Map ISO clock controller MMIO */ + vaddr_t clk_iso_ptr = mem_alloc_map_dev(&cpu()->as, SEC_HYP_PRIVATE, INVALID_VA, + (paddr_t)(PLAT_CLK_ISO_BASE), NUM_PAGES(sizeof(struct clk_ctl_iso_hw))); + if (clk_iso_ptr == INVALID_VA) { + ERROR("Maping clock ISO area failed"); + } + clk_ctl_iso = (struct clk_ctl_iso_hw*)clk_iso_ptr; + + /* Map AWO clock controller MMIO */ + vaddr_t clk_awo_ptr = mem_alloc_map_dev(&cpu()->as, SEC_HYP_PRIVATE, INVALID_VA, + (paddr_t)(PLAT_CLK_AWO_BASE), NUM_PAGES(sizeof(struct clk_ctl_awo_hw))); + if (clk_awo_ptr == INVALID_VA) { + ERROR("maping clock AWO area failed"); + } + clk_ctl_awo = (struct clk_ctl_awo_hw*)clk_awo_ptr; + + /* Disable CLK registers protection */ + clk_ctl_iso->CLKKCPROT1 = CLKKCPROT1_ENABLE_WR; + + /* Start main oscillator, if not started */ + if (!(clk_ctl_awo->MOSCS & MOSCS_MOSCEN_BIT) && + !(clk_ctl_awo->MOSCS & MOSCS_MOSCSTAB_BIT)) { + + /* Start the Main OSC */ + clk_ctl_awo->MOSCE = MOSCE_MOSCENTRG_BIT; + /* Confirm that the Main OSC has been stable */ + while (!(clk_ctl_awo->MOSCS & MOSCS_MOSCEN_BIT) || + !(clk_ctl_awo->MOSCS & MOSCS_MOSCSTAB_BIT)); + /* Wait 1.4us or Read the MOSCS.MOSCSTAB = 1 four times */ + while (stab_cnt < 4) + stab_cnt += ((clk_ctl_awo->MOSCS & MOSCS_MOSCSTAB_BIT) >> 1); + } + + stab_cnt = 0; + + /* Trigger PLL, if not already started */ + if (!(clk_ctl_iso->PLLS & PLLS_PLLCLKEN_BIT) && + !(clk_ctl_iso->PLLS & PLLS_PLLCLKSTAB_BIT)) { + + /* Trigger PLL */ + clk_ctl_iso->PLLE = PLLE_PLLENTRG_BIT; + /* Confirm that the PLL has been stable */ + while (!(clk_ctl_iso->PLLS & PLLS_PLLCLKEN_BIT) || + !(clk_ctl_iso->PLLS & PLLS_PLLCLKSTAB_BIT)); + /* Wait 1.4us or Read the PLLS.PLLCLKSTAB = 1 four times */ + while (stab_cnt < 4) + stab_cnt += ((clk_ctl_iso->PLLS & PLLS_PLLCLKSTAB_BIT) >> 1); + } + + /* Select CLK_PLLO clock source */ + clk_ctl_iso->CKSC_CPUC = 0UL; + + /* Set CLKs to continue in standby mode */ + clk_ctl_iso->PLLSTPM = 1UL; + clk_ctl_awo->MOSCSTPM = 1UL; + + /* Enable CLK registers protection */ + clk_ctl_iso->CLKKCPROT1 = CLKKCPROT1_DISABLE_WR; + + mem_unmap(&cpu()->as, (vaddr_t)(PLAT_CLK_ISO_BASE), NUM_PAGES(sizeof(struct clk_ctl_iso_hw)), true); + mem_unmap(&cpu()->as, (vaddr_t)(PLAT_CLK_AWO_BASE), NUM_PAGES(sizeof(struct clk_ctl_awo_hw)), true); +} \ No newline at end of file diff --git a/src/platform/rh850-u2a16/inc/plat/clock.h b/src/platform/rh850-u2a16/inc/plat/clock.h new file mode 100644 index 000000000..5793d4f12 --- /dev/null +++ b/src/platform/rh850-u2a16/inc/plat/clock.h @@ -0,0 +1,114 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __PLAT_CLOCK_H__ +#define __PLAT_CLOCK_H__ + +#include + +#define PLAT_CLK_ISO_BASE (0xFF980000UL) +#define PLAT_CLK_AWO_BASE (0xFF988000UL) + +#define CLKKCPROT1_ENABLE_WR (0xA5A5A501UL) +#define CLKKCPROT1_DISABLE_WR (0xA5A5A500UL) + +#define MOSCE_MOSCENTRG_BIT (0x1UL << 0) + +#define MOSCS_MOSCEN_BIT (0x1UL << 0) +#define MOSCS_MOSCSTAB_BIT (0x1UL << 1) + +#define PLLE_PLLENTRG_BIT (0x1UL << 0) + +#define PLLS_PLLCLKEN_BIT (0x1UL << 0) +#define PLLS_PLLCLKSTAB_BIT (0x1UL << 1) + +/* Clock Controller Registers for ISO area */ +struct clk_ctl_iso_hw { + uint32_t PLLE; // 0x0000 PLL Enable Register + uint32_t PLLS; // 0x0004 PLL Status Register + uint8_t pad0[0xC-0x8]; + uint32_t PLLSTPM; // 0x000C PLL Stop Mask Register + uint8_t pad1[0x100-0x10]; + uint32_t CKSC_CPUC; // 0x0100 CLK_CPU Selector Control Register + uint8_t pad2[0x108-0x104]; + uint32_t CKSC_CPUS; // 0x0108 CLK_CPU Selector Status Register + uint8_t pad3[0x120-0x10C]; + uint32_t CLKD_PLLC; // 0x0120 CLK_PLLO Divider Control Register + uint8_t pad4[0x128-0x124]; + uint32_t CLKD_PLLS; // 0x0128 CLK_PLLO Divider Status Register + uint8_t pad5[0x140-0x12C]; + uint32_t CKSC_RLINC; // 0x0140 CLK_RLIN Selector Control Register + uint8_t pad6[0x148-0x144]; + uint32_t CKSC_RLINS; // 0x0148 CLK_RLIN Selector Status Register + uint8_t pad7[0x150-0x14C]; + uint32_t CKSC_RCANC; // 0x0150 CLK_RCANO Selector Control Register + uint8_t pad8[0x158-0x154]; + uint32_t CKSC_RCANS; // 0x0158 CLK_RCANO Selector Status Register + uint8_t pad9[0x160-0x15C]; + uint32_t CKSC_ADCC; // 0x0160 CLK_ADC Selector Control Register + uint8_t pad10[0x168-0x164]; + uint32_t CKSC_ADCS; // 0x0168 CLK_ADC Selector Status Register + uint8_t pad11[0x170-0x16C]; + uint32_t CKSC_MSPIC; // 0x0170 CLK_MSPI Selector Control Register + uint8_t pad12[0x178-0x174]; + uint32_t CKSC_MSPIS; // 0x0178 CLK_MSPI Selector Status Register + uint8_t pad13[0x700-0x17C]; + uint32_t CLKKCPROT1; // 0x0700 Clock Controller Register Key Code Protection 1 +}; + +/* Clock Controller Registers for AWO area */ +struct clk_ctl_awo_hw { + uint32_t MOSCE; // 0x0000 Main OSC Enable Register + uint32_t MOSCS; // 0x0004 Main OSC Status Register + uint8_t pad0[0xC-0x8]; + uint32_t MOSCSTPM; // 0x000C Main OSC Stop Mask Register + uint8_t pad1[0x100-0x10]; + uint32_t HSOSCS; // 0x0100 HS IntOSC Status Register + uint32_t HSOSCSTPM; // 0x0104 HS IntOSC Stop Mask Register + uint8_t pad2[0x200 - 0x108]; + uint32_t CKSC_AWDTC; // 0x0200 CLKA_WDT Selector Control Register + uint8_t pad3[0x208 - 0x204]; + uint32_t CKSC_AWDTS; // 0x0208 CLKA_WDT Selector Status Register + uint8_t pad4[0x210 - 0x20C]; + uint32_t CKSC_ATAUJC; // 0x0210 CLKA_TAUJ Selector Control Register + uint8_t pad5[0x218 - 0x214]; + uint32_t CKSC_ATAUJS; // 0x0218 CLKA_TAUJ Selector Status Register + uint8_t pad6[0x220 - 0x21C]; + uint32_t CKSC_ARTCAC; // 0x0220 CLKA_RTCA Selector Control Register + uint8_t pad7[0x228 - 0x224]; + uint32_t CKSC_ARTCAS; // 0x0228 CLKA_RTCA Selector Status Register + uint8_t pad8[0x230 - 0x22C]; + uint32_t CKSC_AADCC; // 0x0230 CLKA_ADC Selector Control Register + uint8_t pad9[0x238 - 0x234]; + uint32_t CKSC_AADCS; // 0x0238 CLKA_ADC Selector Status Register + uint8_t pad10[0x240 - 0x23C]; + uint32_t CLKD_AADCC; // 0x0240 CLKA_ADC Divider Control Register + uint8_t pad11[0x248 - 0x244]; + uint32_t CLKD_AADCS; // 0x0248 CLKA_ADC Divider Status Register + uint8_t pad12[0x250 - 0x24C]; + uint32_t CKSC_FOUT0C; // 0x0250 FOUT0 Clock Selector Control Register + uint8_t pad13[0x258 - 0x254]; + uint32_t CKSC_FOUT0S; // 0x0258 FOUT0 Clock Selector Status Register + uint8_t pad14[0x260 - 0x25C]; + uint32_t CLKD_FOUT0C; // 0x0260 FOUT0 Clock Divider Control Register + uint8_t pad15[0x268 - 0x264]; + uint32_t CLKD_FOUT0S; // 0x0268 FOUT0 Clock Divider Status Register + uint8_t pad16[0x270 - 0x26C]; + uint32_t CKSC_FOUT1C; // 0x0270 FOUT1 Clock Selector Control Register + uint8_t pad17[0x278 - 0x274]; + uint32_t CKSC_FOUT1S; // 0x0278 FOUT1 Clock Selector Status Register + uint8_t pad18[0x280 - 0x27C]; + uint32_t CLKD_FOUT1C; // 0x0280 FOUT1 Clock Divider Control Register + uint8_t pad19[0x288 - 0x284]; + uint32_t CLKD_FOUT1S; // 0x0288 FOUT1 Clock Divider Status Register + uint8_t pad20[0x300 - 0x28C]; + uint32_t CKSC_WDTC; // 0x0300 CLK_WDT Selector Control Register + uint8_t pad21[0x308 - 0x304]; + uint32_t CKSC_WDTS; // 0x0308 CLK_WDT Selector Status Register +}; + +void clock_init(void); + +#endif /* __PLAT_CLOCK_H__ */ diff --git a/src/platform/rh850-u2a16/inc/plat/pbg.h b/src/platform/rh850-u2a16/inc/plat/pbg.h new file mode 100644 index 000000000..92ac3e823 --- /dev/null +++ b/src/platform/rh850-u2a16/inc/plat/pbg.h @@ -0,0 +1,106 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __PLAT_PBG_H__ +#define __PLAT_PBG_H__ + +#include + +#define PLAT_NUM_PBG_CHANNELS (16) + +#define PLAT_PBG_BASE (0xFF0A1300UL) + +#define PBGKCPROT_ENABLE_WR (0xA5A5A501UL) +#define PBGKCPROT_DISABLE_WR (0xA5A5A500UL) + +struct pbg_channel { + uint32_t PBGPROT0; + uint32_t PBGPROT1; +}; + +struct pbgn { + struct pbg_channel ch[PLAT_NUM_PBG_CHANNELS]; +}; + +struct pbgerrslvn { + uint32_t PBGOVFCLR; + uint32_t PBGOVFSTAT; + uint32_t PBGRRADDR; + uint32_t PBGRRTYPE; + uint32_t PBGSPIDERRCLR; + uint32_t PBGSPIDERRSTAT; + uint32_t PBGKCPROT; +}; + +struct pbg_hw { + struct pbgn PBG90; + uint8_t pad0[0xFF0A1400 - 0xFF0A1380]; + struct pbgerrslvn PBGERRSLV90; + uint8_t pad1[0xFF751000 - 0xFF0A141C]; + struct pbgn PBG6H0; + uint8_t pad2[0xFF752000 - 0xFF751080]; + struct pbgerrslvn PBGERRSLV6H0; + uint8_t pad3[0xFFC63000 - 0xFF75201C]; + struct pbgn PBG10; + uint8_t pad4[0xFFC63100 - 0xFFC63080]; + struct pbgerrslvn PBGERRSLV10; + uint8_t pad5[0xFFC6B000 - 0xFFC6311C]; + struct pbgerrslvn PBGERRSLV00; + uint8_t pad6[0xFFC6B080 - 0xFFC6B01C]; + struct pbgn PBG00; + struct pbgn PBG01; + uint8_t pad7[0xFFC72B00 - 0xFFC6B180]; + struct pbgn PBG30; + uint8_t pad8[0xFFC72C00 - 0xFFC72B80]; + struct pbgn PBG31; + uint8_t pad9[0xFFC72D00 - 0xFFC72C80]; + struct pbgn PBG32; + uint8_t pad10[0xFFC72E00 - 0xFFC72D80]; + struct pbgn PBG33; + uint8_t pad11[0xFFC73200 - 0xFFC72E80]; + struct pbgerrslvn PBGERRSLV30; + uint8_t pad12[0xFFC75300 - 0xFFC7321C]; + struct pbgn PBG40; + uint8_t pad13[0xFFC75400 - 0xFFC75380]; + struct pbgerrslvn PBGERRSLV40; + uint8_t pad14[0xFFC7A300 - 0xFFC7541C]; + struct pbgn PBG50; + uint8_t pad15[0xFFC7A400 - 0xFFC7A380]; + struct pbgn PBG51; + uint8_t pad16[0xFFC7A500 - 0xFFC7A480]; + struct pbgn PBG52; + uint8_t pad17[0xFFC7A600 - 0xFFC7A580]; + struct pbgn PBG53; + uint8_t pad18[0xFFC7B000 - 0xFFC7A680]; + struct pbgerrslvn PBGERRSLV50; + uint8_t pad19[0xFFC81000 - 0xFFC7B01C]; + struct pbgn PBG6L0; + uint8_t pad20[0xFFC81200 - 0xFFC81080]; + struct pbgn PBG6L1; + uint8_t pad21[0xFFC83000 - 0xFFC81280]; + struct pbgerrslvn PBGERRSLV6L0; + uint8_t pad22[0xFFC83040 - 0xFFC8301C]; + struct pbgerrslvn PBGERRSLV6L1; + uint8_t pad23[0xFFDE0B00 - 0xFFC8305C]; + struct pbgn PBG20; + uint8_t pad24[0xFFDE0C00 - 0xFFDE0B80]; + struct pbgn PBG21; + uint8_t pad25[0xFFDE0D00 - 0xFFDE0C80]; + struct pbgn PBG22; + uint8_t pad26[0xFFDE1000 - 0xFFDE0D80]; + struct pbgerrslvn PBGERRSLV20; + uint8_t pad27[0xFFF29300 - 0xFFDE101C]; + struct pbgn PBG80; + uint8_t pad28[0xFFF2A000 - 0xFFF29380]; + struct pbgerrslvn PBGERRSLV80; + uint8_t pad29[0xFFF49400 - 0xFFF2A01C]; + struct pbgn PBG70; + uint8_t pad30[0xFFF4A000 - 0xFFF49480]; + struct pbgerrslvn PBGERRSLV70; +}; + +void pbg_init(void); + +#endif /* __PLAT_PBG_H__ */ \ No newline at end of file diff --git a/src/platform/rh850-u2a16/inc/plat/platform.h b/src/platform/rh850-u2a16/inc/plat/platform.h new file mode 100644 index 000000000..10bab4209 --- /dev/null +++ b/src/platform/rh850-u2a16/inc/plat/platform.h @@ -0,0 +1,19 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __PLAT_PLATFORM_H__ +#define __PLAT_PLATFORM_H__ + +#include +#include +#include +#include +#include +#include + +/* Interrupts */ +#define PLAT_MAX_INTERRUPTS 768 + +#endif /* __PLAT_PLATFORM_H__ */ diff --git a/src/platform/rh850-u2a16/inc/plat/port.h b/src/platform/rh850-u2a16/inc/plat/port.h new file mode 100644 index 000000000..679cc15a4 --- /dev/null +++ b/src/platform/rh850-u2a16/inc/plat/port.h @@ -0,0 +1,215 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __PLAT_PORT_H__ +#define __PLAT_PORT_H__ + +#include + +#define PLAT_MAX_NUM_PORT_GROUPS (25) +#define PLAT_MAX_NUM_APORT_GROUPS (6) + +#define PLAT_NUM_PORT_GROUPS (11) +#define PLAT_NUM_APORT_GROUPS (5) + +#define PLAT_NUM_PORT_CFG_REGS (21) +#define PLAT_NUM_APORT_CFG_REGS (11) + +#define PLAT_PORT_GROUP_MASK ((1UL << 2) | \ + (1UL << 3) | \ + (1UL << 4) | \ + (1UL << 5) | \ + (1UL << 6) | \ + (1UL << 10) | \ + (1UL << 17) | \ + (1UL << 20) | \ + (1UL << 21) | \ + (1UL << 22) | \ + (1UL << 24)) + +#define PLAT_APORT_GROUP_MASK ((1UL << 0) | \ + (1UL << 1) | \ + (1UL << 2) | \ + (1UL << 3) | \ + (1UL << 4)) + +#define PORT_PKCPROT_ENABLE_WR (0xA5A5A501UL) +#define PORT_PKCPROT_DISABLE_WR (0xA5A5A500UL) +#define PORT_PWE_ENABLE_ALL_MASK (0x0BF724F8UL) + +#define PLAT_PORT_BASE (0xFFD90000UL) + +enum port_reg_idx { + Pn, + PMn, + PMCn, + PFCn, + PFCEn, + PFCAEn, + PINVn, + PIBCn, + PBDCn, + PIPCn, + PUn, + PDn, + PODCn, + PDSCn, + PISn, + PISAn, + PUCCn, + PODCEn, + PSFCn, + PSFTSn, + PSFTSEn +}; + +enum aport_reg_idx { + APn, + APMn, + APINVn, + APIBCn, + APBDCn, + APODCn, + APDSCn, + APODCEn, + APSFCn, + APSFTSn, + APSFTSEn +}; + +/* Port Group Register Sets */ +struct port_group_regset1 { + uint16_t P; /* 0x0000 + 0x40*n */ + uint8_t pad0[2]; /* 0x0002 + 0x40*n */ + uint32_t PSR; /* 0x0004 + 0x40*n */ + uint16_t PNOT; /* 0x0008 + 0x40*n */ + uint8_t pad1[2]; /* 0x000A + 0x40*n */ + uint16_t PPR; /* 0x000C + 0x40*n */ + uint8_t pad2[2]; /* 0x000E + 0x40*n */ + uint16_t PM; /* 0x0010 + 0x40*n */ + uint8_t pad3[2]; /* 0x0012 + 0x40*n */ + uint16_t PMC; /* 0x0014 + 0x40*n */ + uint8_t pad4[2]; /* 0x0016 + 0x40*n */ + uint16_t PFC; /* 0x0018 + 0x40*n */ + uint8_t pad5[2]; /* 0x001A + 0x40*n */ + uint16_t PFCE; /* 0x001C + 0x40*n */ + uint8_t pad6[2]; /* 0x001E + 0x40*n */ + uint32_t PMSR; /* 0x0020 + 0x40*n */ + uint32_t PMCSR; /* 0x0024 + 0x40*n */ + uint16_t PFCAE; /* 0x0028 + 0x40*n */ + uint8_t pad7[6]; /* 0x002A + 0x40*n */ + uint16_t PINV; /* 0x0030 + 0x40*n */ + uint8_t pad8[14]; /* 0x0032 + 0x40*n */ +}; + +struct port_group_regset2 { + uint32_t PCR_m[16]; /* 0x2000 + 0x40*n */ +}; + +struct port_group_regset3 { + uint16_t PIBC; /* 0x4000 + 0x40*n */ + uint8_t pad0[2]; /* 0x4002 + 0x40*n */ + uint16_t PBDC; /* 0x4004 + 0x40*n */ + uint8_t pad1[2]; /* 0x4006 + 0x40*n */ + uint16_t PIPC; /* 0x4008 + 0x40*n */ + uint8_t pad2[2]; /* 0x400A + 0x40*n */ + uint16_t PU; /* 0x400C + 0x40*n */ + uint8_t pad3[2]; /* 0x400E + 0x40*n */ + uint16_t PD; /* 0x4010 + 0x40*n */ + uint8_t pad4[2]; /* 0x4012 + 0x40*n */ + uint16_t PODC; /* 0x4014 + 0x40*n */ + uint8_t pad5[2]; /* 0x4016 + 0x40*n */ + uint16_t PDSC; /* 0x4018 + 0x40*n */ + uint8_t pad6[2]; /* 0x401A + 0x40*n */ + uint16_t PIS; /* 0x401C + 0x40*n */ + uint8_t pad7[6]; /* 0x401E + 0x40*n */ + uint16_t PISA; /* 0x4024 + 0x40*n */ + uint8_t pad8[2]; /* 0x4026 + 0x40*n */ + uint16_t PUCC; /* 0x4028 + 0x40*n */ + uint8_t pad9[14]; /* 0x402A + 0x40*n */ + uint16_t PODCE; /* 0x4038 + 0x40*n */ + uint8_t pad10[6]; /* 0x403A + 0x40*n */ +}; + +struct port_group_regset4 { + uint16_t PSFC; /* 0x6000 + 0x40*n */ + uint8_t pad0[14]; /* 0x6002 + 0x40*n */ + uint16_t PSFTS; /* 0x6010 + 0x40*n */ + uint8_t pad1[2]; /* 0x6012 + 0x40*n */ + uint16_t PSFTSE; /* 0x6014 + 0x40*n */ + uint8_t pad2[42]; /* 0x6016 + 0x40*n */ +}; + +/* Analog Port Group Register Sets */ +struct analog_port_group_regset1 { + uint16_t AP; /* 0x0C80 + 0x40*n */ + uint8_t pad0[2]; /* 0x0C82 + 0x40*n */ + uint32_t APSR; /* 0x0C84 + 0x40*n */ + uint16_t APNOT; /* 0x0C88 + 0x40*n */ + uint8_t pad1[2]; /* 0x0C8A + 0x40*n */ + uint16_t APPR; /* 0x0C8C + 0x40*n */ + uint8_t pad2[2]; /* 0x0C8E + 0x40*n */ + uint16_t APM; /* 0x0C90 + 0x40*n */ + uint8_t pad3[14]; /* 0x0C92 + 0x40*n */ + uint32_t APMSR; /* 0x0CA0 + 0x40*n */ + uint8_t pad4[12]; /* 0x0CAA + 0x40*n */ + uint16_t APINV; /* 0x0CB0 + 0x40*n */ + uint8_t pad5[14]; /* 0x0CB2 + 0x40*n */ +}; + +struct analog_port_group_regset2 { + uint32_t APCR_m[16]; /* 0x2C80 + 0x40*n */ +}; + +struct analog_port_group_regset3 { + uint16_t APIBC; /* 0x4C80 + 0x40*n */ + uint8_t pad0[2]; /* 0x4C82 + 0x40*n */ + uint16_t APBDC; /* 0x4C84 + 0x40*n */ + uint8_t pad1[14]; /* 0x4C86 + 0x40*n */ + uint16_t APODC; /* 0x4C94 + 0x40*n */ + uint8_t pad2[2]; /* 0x4C96 + 0x40*n */ + uint16_t APDSC; /* 0x4C98 + 0x40*n */ + uint8_t pad3[30]; /* 0x4C9A + 0x40*n */ + uint16_t APODCE; /* 0x4CB8 + 0x40*n */ + uint8_t pad4[6]; /* 0x4CBA + 0x40*n */ +}; + +struct analog_port_group_regset4 { + uint16_t APSFC; /* 0x6C80 + 0x40*n */ + uint8_t pad0[14]; /* 0x6C82 + 0x40*n */ + uint16_t APSFTS; /* 0x6C90 + 0x40*n */ + uint8_t pad1[2]; /* 0x6C92 + 0x40*n */ + uint16_t APSFTSE; /* 0x6C94 + 0x40*n */ + uint8_t pad2[42]; /* 0x6C96 + 0x40*n */ +}; + +/* PORT Register Map Struct */ +struct port_hw { + struct port_group_regset1 p_regset1[PLAT_MAX_NUM_PORT_GROUPS]; /* 0x0000 - 0x063F */ + uint8_t pad0[0xC80-0x640]; /* 0x0640 - 0x0C7F */ + struct analog_port_group_regset1 ap_regset1[PLAT_MAX_NUM_APORT_GROUPS]; /* 0x0C80 - 0x0DFF */ + uint8_t pad1[0x2000-0xE00]; /* 0x0E00 - 0x1FFF */ + struct port_group_regset2 p_regset2[PLAT_MAX_NUM_PORT_GROUPS]; /* 0x2000 - 0x263F */ + uint8_t pad2[0x2C80-0x2640]; /* 0x2640 - 0x2C7F */ + struct analog_port_group_regset2 ap_regset2[PLAT_MAX_NUM_APORT_GROUPS]; /* 0x2C80 - 0x2DFF */ + uint8_t pad3[0x2F40-0x2E00]; /* 0x2E00 - 0x2F3F */ + uint32_t PKCPROT; /* 0x2F40 - 0x2F43 */ + uint32_t PWE; /* 0x2F44 - 0x2F47 */ + uint8_t pad4[0x2F50-0x2F48]; /* 0x2F48 - 0x2F4F */ + uint32_t LVDSCTRLA; /* 0x2F50 - 0x2F43 */ + uint32_t LVDSCTRLB; /* 0x2F54 - 0x2F57 */ + uint8_t pad5[0x4000-0x2F58]; /* 0x2F58 - 0x3FFF */ + struct port_group_regset3 p_regset3[PLAT_MAX_NUM_PORT_GROUPS]; /* 0x4000 - 0x463F */ + uint8_t pad6[0x4C80-0x4640]; /* 0x4640 - 0x4C7F */ + struct analog_port_group_regset3 ap_regset3[PLAT_MAX_NUM_APORT_GROUPS]; /* 0x4C80 - 0x4DFF */ + uint8_t pad7[0x6000-0x4E00]; /* 0x4E00 - 0x5FFF */ + struct port_group_regset4 p_regset4[PLAT_MAX_NUM_PORT_GROUPS]; /* 0x6000 - 0x663F */ + uint8_t pad8[0x6C80-0x6640]; /* 0x6640 - 0x6C7F */ + struct analog_port_group_regset4 ap_regset4[PLAT_MAX_NUM_APORT_GROUPS]; /* 0x6C80 - 0x6DFF */ +}; + +void port_init(void); + +#endif /* __PLAT_PORT_H__ */ \ No newline at end of file diff --git a/src/platform/rh850-u2a16/inc/plat/stbc.h b/src/platform/rh850-u2a16/inc/plat/stbc.h new file mode 100644 index 000000000..204a7ac1b --- /dev/null +++ b/src/platform/rh850-u2a16/inc/plat/stbc.h @@ -0,0 +1,72 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __PLAT_STBC_H__ +#define __PLAT_STBC_H__ + +#include + +#define MSRKCPROT_ENABLE_WR (0xA5A5A501UL) +#define MSRKCPROT_DISABLE_WR (0xA5A5A500UL) + +#define PLAT_STBC_BASE (0xFF981000UL) + +/* Standby Controller MMIO Registers */ +struct stbc_hw { + uint32_t MSR_RSCFD; + uint8_t pad0[0x0010-0x0004]; + uint32_t MSR_FLXA; + uint8_t pad1[0x0020-0x0014]; + uint32_t MSR_GTM; + uint8_t pad2[0x0030-0x0024]; + uint32_t MSR_ETNB; + uint8_t pad3[0x0040-0x0034]; + uint32_t MSR_RSENT; + uint8_t pad4[0x0050-0x0044]; + uint32_t MSR_MSPI; + uint8_t pad5[0x0060-0x0054]; + uint32_t MSR_RLIN3; + uint8_t pad6[0x0070-0x0064]; + uint32_t MSR_ADCJ_ISO; + uint8_t pad7[0x0080-0x0074]; + uint32_t MSR_CXPI; + uint8_t pad8[0x0090-0x0084]; + uint32_t MSR_MMCA; + uint8_t pad9[0x00A0-0x0094]; + uint32_t MSR_ENCA; + uint8_t pad10[0x00B0-0x00A4]; + uint32_t MSR_PSI5; + uint8_t pad11[0x00C0-0x00B4]; + uint32_t MSR_PSI5S; + uint8_t pad12[0x00D0-0x00C4]; + uint32_t MSR_PWMD; + uint8_t pad13[0x00E0-0x00D4]; + uint32_t MSR_RHSIF; + uint8_t pad14[0x00F0-0x00E4]; + uint32_t MSR_RIIC; + uint8_t pad15[0x0100-0x00F4]; + uint32_t MSR_SCI3; + uint8_t pad16[0x0120-0x0104]; + uint32_t MSR_TAPA; + uint8_t pad17[0x0130-0x0124]; + uint32_t MSR_TAUD; + uint8_t pad18[0x0140-0x0134]; + uint32_t MSR_TAUJ_ISO; + uint8_t pad19[0x0150-0x0144]; + uint32_t MSR_TPBA; + uint8_t pad20[0x0160-0x0154]; + uint32_t MSR_TSG3; + uint8_t pad21[0x0180-0x0164]; + uint32_t MSR_OSTM; + uint8_t pad22[0x0700-0x0184]; + uint32_t STBCKCPROT; + uint8_t pad23[0x0710-0x0704]; + uint32_t MSRKCPROT; +}; +// TODO: Map remainder of the STBC MMIO + +void stbc_init(void); + +#endif /* __PLAT_STBC_H__ */ \ No newline at end of file diff --git a/src/platform/rh850-u2a16/objects.mk b/src/platform/rh850-u2a16/objects.mk new file mode 100644 index 000000000..9b16aa19f --- /dev/null +++ b/src/platform/rh850-u2a16/objects.mk @@ -0,0 +1,9 @@ +## SPDX-License-Identifier: Apache-2.0 +## Copyright (c) Bao Project and Contributors. All rights reserved. + +boards-objs-y+=u2a16_desc.o +boards-objs-y+=plat.o +boards-objs-y+=port.o +boards-objs-y+=clock.o +boards-objs-y+=stbc.o +boards-objs-y+=pbg.o diff --git a/src/platform/rh850-u2a16/pbg.c b/src/platform/rh850-u2a16/pbg.c new file mode 100644 index 000000000..bed8bfc02 --- /dev/null +++ b/src/platform/rh850-u2a16/pbg.c @@ -0,0 +1,68 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include + +#define PBGPROT1_SPID_MASK (((1UL << 16) - 1) | (1UL << 16)) + +volatile struct pbg_hw* pbg; + +void pbg_init(void) { + + /* Enable temporary access to PBG registers */ + vaddr_t pbg_ptr = mem_alloc_map_dev(&cpu()->as, SEC_HYP_PRIVATE, INVALID_VA, + (paddr_t)(PLAT_PBG_BASE), NUM_PAGES(sizeof(struct pbg_hw))); + if (pbg_ptr == INVALID_VA) { + ERROR("Maping PBG MMIO failed"); + } + pbg = (struct pbg_hw*)pbg_ptr; + + /* Enable write to PBGPROT registers */ + pbg->PBGERRSLV00.PBGKCPROT = PBGKCPROT_ENABLE_WR; + pbg->PBGERRSLV10.PBGKCPROT = PBGKCPROT_ENABLE_WR; + pbg->PBGERRSLV20.PBGKCPROT = PBGKCPROT_ENABLE_WR; + pbg->PBGERRSLV30.PBGKCPROT = PBGKCPROT_ENABLE_WR; + pbg->PBGERRSLV40.PBGKCPROT = PBGKCPROT_ENABLE_WR; + pbg->PBGERRSLV50.PBGKCPROT = PBGKCPROT_ENABLE_WR; + pbg->PBGERRSLV6L0.PBGKCPROT = PBGKCPROT_ENABLE_WR; + pbg->PBGERRSLV6L1.PBGKCPROT = PBGKCPROT_ENABLE_WR; + pbg->PBGERRSLV6H0.PBGKCPROT = PBGKCPROT_ENABLE_WR; + pbg->PBGERRSLV70.PBGKCPROT = PBGKCPROT_ENABLE_WR; + pbg->PBGERRSLV80.PBGKCPROT = PBGKCPROT_ENABLE_WR; + pbg->PBGERRSLV90.PBGKCPROT = PBGKCPROT_ENABLE_WR; + + /* Allow SPIDs [0-16] to write to P-Bus */ + for (size_t i = 0; i < PLAT_NUM_PBG_CHANNELS; i++) + { + pbg->PBG00.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + pbg->PBG10.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + pbg->PBG20.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + pbg->PBG30.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + pbg->PBG40.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + pbg->PBG50.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + pbg->PBG6L0.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + pbg->PBG6L1.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + pbg->PBG6H0.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + pbg->PBG70.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + pbg->PBG80.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + pbg->PBG90.ch[i].PBGPROT1 |= (PBGPROT1_SPID_MASK); + } + + /* Disable write to PBGPROT registers */ + pbg->PBGERRSLV00.PBGKCPROT = PBGKCPROT_DISABLE_WR; + pbg->PBGERRSLV10.PBGKCPROT = PBGKCPROT_DISABLE_WR; + pbg->PBGERRSLV20.PBGKCPROT = PBGKCPROT_DISABLE_WR; + pbg->PBGERRSLV30.PBGKCPROT = PBGKCPROT_DISABLE_WR; + pbg->PBGERRSLV40.PBGKCPROT = PBGKCPROT_DISABLE_WR; + pbg->PBGERRSLV50.PBGKCPROT = PBGKCPROT_DISABLE_WR; + pbg->PBGERRSLV6L0.PBGKCPROT = PBGKCPROT_DISABLE_WR; + pbg->PBGERRSLV6L1.PBGKCPROT = PBGKCPROT_DISABLE_WR; + pbg->PBGERRSLV6H0.PBGKCPROT = PBGKCPROT_DISABLE_WR; + pbg->PBGERRSLV70.PBGKCPROT = PBGKCPROT_DISABLE_WR; + pbg->PBGERRSLV80.PBGKCPROT = PBGKCPROT_DISABLE_WR; + pbg->PBGERRSLV90.PBGKCPROT = PBGKCPROT_DISABLE_WR; + + mem_unmap(&cpu()->as, (vaddr_t)(PLAT_PBG_BASE), NUM_PAGES(sizeof(struct pbg_hw)), true); +} \ No newline at end of file diff --git a/src/platform/rh850-u2a16/plat.c b/src/platform/rh850-u2a16/plat.c new file mode 100644 index 000000000..fc8cff08b --- /dev/null +++ b/src/platform/rh850-u2a16/plat.c @@ -0,0 +1,26 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include + +void platform_default_init(void) { + + if (cpu_is_master()) { + + /*** Peripheral Bus Guard Initialization ***/ + pbg_init(); + + /*** Module Standby Initialization ***/ + stbc_init(); + + /*** MCU Clock Initialization ***/ + clock_init(); + + /*** IO Ports Initialization ***/ + port_init(); + } + + cpu_sync_and_clear_msgs(&cpu_glb_sync); +} diff --git a/src/platform/rh850-u2a16/platform.mk b/src/platform/rh850-u2a16/platform.mk new file mode 100644 index 000000000..5dfc80a78 --- /dev/null +++ b/src/platform/rh850-u2a16/platform.mk @@ -0,0 +1,16 @@ +## SPDX-License-Identifier: Apache-2.0 +## Copyright (c) Bao Project and Contributors. All rights reserved. + +# Architecture definition +ARCH:=rh850 +ARCH_PROFILE:=main +drivers:=renesas_rlin3 + +platform_description:=u2a16_desc.c + +platform-cppflags = +platform-cflags = -gdwarf-4 +platform-asflags = -gdwarf-4 +platform-ldflags = + +plat_mem:=non_unified diff --git a/src/platform/rh850-u2a16/port.c b/src/platform/rh850-u2a16/port.c new file mode 100644 index 000000000..ac5bac566 --- /dev/null +++ b/src/platform/rh850-u2a16/port.c @@ -0,0 +1,117 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include + +extern uint16_t port_reg_val[PLAT_NUM_PORT_CFG_REGS][PLAT_NUM_PORT_GROUPS]; +extern uint16_t aport_reg_val[PLAT_NUM_APORT_CFG_REGS][PLAT_NUM_APORT_GROUPS]; + +volatile struct port_hw* port; + +void port_init(void) { + + size_t shift = 0; + + /* Map port MMIO */ + vaddr_t port_ptr = mem_alloc_map_dev(&cpu()->as, SEC_HYP_PRIVATE, INVALID_VA, + (paddr_t)(PLAT_PORT_BASE), NUM_PAGES(sizeof(struct port_hw))); + if (port_ptr == INVALID_VA) { + ERROR("Maping PORT area failed"); + } + port = (struct port_hw*)port_ptr; + + /* Enable write to port registers */ + port->PKCPROT = PORT_PKCPROT_ENABLE_WR; + port->PWE = PORT_PWE_ENABLE_ALL_MASK; + port->PKCPROT = PORT_PKCPROT_DISABLE_WR; + + /* Configure port registers */ + for (size_t i = 0; i < PLAT_MAX_NUM_PORT_GROUPS; i++) { + /* If port group is not supported, skip */ + if (!((1UL << i) & PLAT_PORT_GROUP_MASK)) { + shift++; + continue; + } + + port->p_regset1[i].P = port_reg_val[Pn][i-shift]; + port->p_regset1[i].PM = port_reg_val[PMn][i-shift]; + port->p_regset1[i].PMC = port_reg_val[PMCn][i-shift]; + port->p_regset1[i].PFC = port_reg_val[PFCn][i-shift]; + port->p_regset1[i].PFCE = port_reg_val[PFCEn][i-shift]; + port->p_regset1[i].PFCAE = port_reg_val[PFCAEn][i-shift]; + port->p_regset1[i].PINV = port_reg_val[PINVn][i-shift]; + + port->p_regset3[i].PIBC = port_reg_val[PIBCn][i-shift]; + port->p_regset3[i].PBDC = port_reg_val[PBDCn][i-shift]; + port->p_regset3[i].PIPC = port_reg_val[PIPCn][i-shift]; + port->p_regset3[i].PU = port_reg_val[PUn][i-shift]; + port->p_regset3[i].PD = port_reg_val[PDn][i-shift]; + port->p_regset3[i].PODC = port_reg_val[PODCn][i-shift]; + port->p_regset3[i].PDSC = port_reg_val[PDSCn][i-shift]; + port->p_regset3[i].PIS = port_reg_val[PISn][i-shift]; + port->p_regset3[i].PISA = port_reg_val[PISAn][i-shift]; + port->p_regset3[i].PUCC = port_reg_val[PUCCn][i-shift]; + port->p_regset3[i].PODCE = port_reg_val[PODCEn][i-shift]; + + port->p_regset4[i].PSFC = port_reg_val[PSFCn][i-shift]; + port->p_regset4[i].PSFTS = port_reg_val[PSFTSn][i-shift]; + port->p_regset4[i].PSFTSE = port_reg_val[PSFTSEn][i-shift]; + + /* + The following port registers are not configured, since they + either provide an alternative mechanism to access the registers + above or they do not represent a static port configuration. + - PSR + - PNOT + - PPR + - PMSR + - PMCSR + - PCR + */ + } + + shift = 0; + + /* Configure analogic port registers */ + for (size_t i = 0; i < PLAT_MAX_NUM_APORT_GROUPS; i++) { + /* If port group is not supported, skip */ + if (!((1UL << i) & PLAT_APORT_GROUP_MASK)) { + shift++; + continue; + } + + port->ap_regset1[i].AP = aport_reg_val[APn][i-shift]; + port->ap_regset1[i].APM = aport_reg_val[APMn][i-shift]; + port->ap_regset1[i].APINV = aport_reg_val[APINVn][i-shift]; + + port->ap_regset3[i].APIBC = aport_reg_val[APIBCn][i-shift]; + port->ap_regset3[i].APBDC = aport_reg_val[APBDCn][i-shift]; + port->ap_regset3[i].APODC = aport_reg_val[APODCn][i-shift]; + port->ap_regset3[i].APDSC = aport_reg_val[APDSCn][i-shift]; + port->ap_regset3[i].APODCE = aport_reg_val[APODCEn][i-shift]; + + port->ap_regset4[i].APSFC = aport_reg_val[APSFCn][i-shift]; + port->ap_regset4[i].APSFTS = aport_reg_val[APSFTSn][i-shift]; + port->ap_regset4[i].APSFTSE = aport_reg_val[APSFTSEn][i-shift]; + + /* + The following port registers are not configured, since they + either provide an alternative mechanism to access the registers + above or they do not represent a static port configuration. + - APSR + - APNOT + - APPR + - APMSR + - APCR + */ + } + + /* Disable write to port registers */ + port->PKCPROT = PORT_PKCPROT_ENABLE_WR; + port->PWE = 0; + port->PKCPROT = PORT_PKCPROT_DISABLE_WR; + + mem_unmap(&cpu()->as, (vaddr_t)(PLAT_PORT_BASE), NUM_PAGES(sizeof(struct port_hw)), true); +} \ No newline at end of file diff --git a/src/platform/rh850-u2a16/stbc.c b/src/platform/rh850-u2a16/stbc.c new file mode 100644 index 000000000..1d5be9c88 --- /dev/null +++ b/src/platform/rh850-u2a16/stbc.c @@ -0,0 +1,30 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include + +volatile struct stbc_hw* stbc; + +void stbc_init(void) { + + /* Enable temporary access to STBC registers */ + vaddr_t stbc_ptr = mem_alloc_map_dev(&cpu()->as, SEC_HYP_PRIVATE, INVALID_VA, + (paddr_t)(PLAT_STBC_BASE), NUM_PAGES(sizeof(struct stbc_hw))); + if (stbc_ptr == INVALID_VA) { + ERROR("Maping STBC MMIO failed"); + } + stbc = (struct stbc_hw*)stbc_ptr; + + /* Supply clocks for required peripherals */ + // TODO: Are OSTM, TAUD, and RSCFD required? + stbc->MSRKCPROT = MSRKCPROT_ENABLE_WR; + stbc->MSR_RSCFD = 0; + stbc->MSR_RLIN3 = 0; + stbc->MSR_TAUD = 0; + stbc->MSR_OSTM = 0; + stbc->MSRKCPROT = MSRKCPROT_DISABLE_WR; + + mem_unmap(&cpu()->as, (vaddr_t)(PLAT_STBC_BASE), NUM_PAGES(sizeof(struct stbc_hw)), true); +} \ No newline at end of file diff --git a/src/platform/rh850-u2a16/u2a16_desc.c b/src/platform/rh850-u2a16/u2a16_desc.c new file mode 100644 index 000000000..78753e48d --- /dev/null +++ b/src/platform/rh850-u2a16/u2a16_desc.c @@ -0,0 +1,167 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include + +irqid_t plat_ints[2048]; + +struct platform platform = { + + .cpu_num = 4, + .cpu_master_fixed = true, + .cpu_master = 0, + + .region_num = 12, + .regions = + (struct mem_region[]){ + // Code flash (User Areas) + { + .base = 0x0, + .size = 0x1000000, + .perms = MEM_RX, + }, + // Code flash (Non-overlay area & User Boot Area 0) + { + .base = 0x4000000, + .size = 0x4010000, + .perms = MEM_RX, + }, + // Code flash (User Boot Area 1) + { + .base = 0x8400000, + .size = 0x10000, + .perms = MEM_RX, + }, + // Cluster0 RAM + { + .base = 0xFE000000, + .size = 0x80000, + .perms = MEM_RWX, + }, + // Cluster1 RAM + { + .base = 0xFE100000, + .size = 0x80000, + .perms = MEM_RWX, + }, + // Cluster2 RAM + { + .base = 0xFE400000, + .size = 0x200000, + .perms = MEM_RWX, + }, + // Cluster3 RAM (Retention RAM) + { + .base = 0xFE800000, + .size = 0x40000, + .perms = MEM_RWX, + }, + // Local RAM (self region) + { + .base = 0xFDE00000, + .size = 0x10000, + .perms = MEM_RWX, + }, + // Local RAM (CPU0) + { + .base = 0xFDC00000, + .size = 0x10000, + .perms = MEM_RWX, + }, + // Local RAM (CPU1) + { + .base = 0xFDA00000, + .size = 0x10000, + .perms = MEM_RWX, + }, + // Local RAM (CPU2) + { + .base = 0xFD800000, + .size = 0x10000, + .perms = MEM_RWX, + }, + // Local RAM (CPU3) + { + .base = 0xFD600000, + .size = 0x10000, + .perms = MEM_RWX, + } + }, + + .console = { + .base = 0xFFC7C100, // RLIN35 + }, + + .arch = { + .intc = { + .intc1_addr = 0xFFFC0000, + .intc2_addr = 0xFFF80000, + .intif_addr = 0xFF090000, + .eint_addr = 0xFFC00000, + .fenc_addr = 0xFF9A3A00, + .feinc_addr = { + 0xFF9A3B00, + 0xFF9A3C00, + 0xFF9A3D00, + 0xFF9A3E00, + }, + }, + + .bootctrl_addr = 0xFFFB2000, + .ipir_addr = 0xFFFB9000 + } +}; + +/* + Array of port register values + + Index: |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 | + Groups: |G2|G3|G4|G5|G6|G10|G17|G20|G21|G22|G24| +*/ +uint16_t port_reg_val[PLAT_NUM_PORT_CFG_REGS][PLAT_NUM_PORT_GROUPS] = { + /*| G2 | G3 | G4 | G5 | G6 | G10 | G17 | G20 | G21 | G22 | G24 |*/ + /* P */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0800U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* PM */ { 0x8CD3U, 0xFFEBU, 0x2A5FU, 0xFFEBU, 0xEE2FU, 0xF39CU, 0xFFDCU, 0xB9A7U, 0xFF1FU, 0xFFE2U, 0xFFFFU }, + /* PMC */ { 0x7830U, 0x003CU, 0x1BC0U, 0x0004U, 0x9B40U, 0x3F18U, 0x0000U, 0x66C8U, 0x00E0U, 0x001FU, 0x0000U }, + /* PFC */ { 0x0000U, 0x0014U, 0x1B40U, 0x0000U, 0x1340U, 0x2118U, 0x0000U, 0x66C8U, 0x00E0U, 0x001FU, 0x0000U }, + /* PFCE */ { 0x7830U, 0x0028U, 0x0800U, 0x0004U, 0x9B40U, 0x1E00U, 0x0000U, 0x0000U, 0x0000U, 0x0013U, 0x0000U }, + /* PFCAE */ { 0x0010U, 0x0028U, 0x10C0U, 0x0000U, 0x8000U, 0x2100U, 0x0000U, 0x0000U, 0x00E0U, 0x000CU, 0x0000U }, + /* PINV */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* PIBC */ { 0x0001U, 0x0040U, 0x2003U, 0x0040U, 0x0020U, 0x0000U, 0x0000U, 0x0100U, 0x0000U, 0x0000U, 0x0000U }, + /* PBDC */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* PIPC */ { 0x2000U, 0x0000U, 0x0000U, 0x0004U, 0x0000U, 0x0400U, 0x0000U, 0x0008U, 0x00E0U, 0x0001U, 0x0000U }, + /* PU */ { 0x0000U, 0x0000U, 0x0200U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* PD */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* PODC */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0008U, 0x0000U, 0x0000U, 0x0000U }, + /* PDSC */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0018U, 0x0000U, 0x6680U, 0x0000U, 0x0000U, 0x0000U }, + /* PIS */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* PISA */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0018U, 0x0000U, 0x6680U, 0x0000U, 0x0000U, 0x0000U }, + /* PUCC */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* PODCE */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* PSFC */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* PSFTS */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* PSFTSE */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U } +}; + +/* + Array of analogic port register values + + Index: |0 |1 |2 |3 |4 | + Groups: |G0|G1|G2|G3|G4| +*/ +uint16_t aport_reg_val[PLAT_NUM_APORT_CFG_REGS][PLAT_NUM_APORT_GROUPS] = { + /*| G0 | G1 | G2 | G3 | G4 |*/ + /* AP */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* APM */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* APINV */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* APIBC */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* APBDC */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* APODC */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* APDSC */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* APODCE */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* APSFC */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* APSFTS */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U }, + /* APSFTSE */ { 0x0000U, 0x0000U, 0x0000U, 0x0000U, 0x0000U } +};