diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/core.h b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/core.h index 81eab608a..11043cb7c 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/core.h +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/core.h @@ -50,7 +50,7 @@ Modification: #define CPSR_MODE (0x1f) //!< Current processor mode //@} -#define MODE_STACK_SIZE 0x4000 +#define MODE_STACK_SIZE 0x1000 //! @name Interrupt enable bits in CPSR //@{ @@ -107,11 +107,11 @@ struct context { /// @brief init task context, set return address to trap return /// @param -extern void trap_return(void); +extern void task_prepare_enter(); __attribute__((__always_inline__)) static inline void arch_init_context(struct context* ctx) { memset(ctx, 0, sizeof(*ctx)); - ctx->lr = (uint32_t)(trap_return); + ctx->lr = (uint32_t)(task_prepare_enter + 4); } struct trapframe { @@ -193,4 +193,6 @@ __attribute__((__always_inline__)) static inline void arch_set_return(struct tra tf->r0 = (uint32_t)ret; } +void cpu_start_secondary(uint8_t cpu_id); +void start_smp_cache_broadcast(int cpu_id); #endif \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/Makefile index c03a9757d..4d0deb874 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/Makefile +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/Makefile @@ -1,3 +1,8 @@ -SRC_FILES := ivt.c dcd.c imx6q_lowlevel_init.S cortexA9.S boot.S +SRC_FILES := ivt.c \ + dcd.c \ + boot.S \ + imx6q_lowlevel_init.S \ + cortexA9.S \ + smp.c include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/boot.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/boot.S index d3f824508..2f5ab4867 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/boot.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/boot.S @@ -84,11 +84,10 @@ _boot_start: @ check cpu id - cpu0 is primary cpu cmp r5, #0 beq primary_cpu_init - bx r4 @ for secondary cpus, jump to argument function pointer passed in by ROM - - @ control should not return from the secondary cpu entry point - b . + bl bootmain @ for secondary cpus, jump to argument function pointer passed in by ROM + bl . + primary_cpu_init: /* init .bss */ /* clear the .bss section (zero init) */ diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/cortexA9.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/cortexA9.S index dd2483c3a..3ef2446fc 100755 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/cortexA9.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/cortexA9.S @@ -71,7 +71,7 @@ arm_set_interrupt_state: cpu_get_current: mrc p15, 0, r0, c0, c0, 5 and r0, r0, #3 - BX lr + BX lr .endfunc @cpu_get_current()@ .global enable_neon_fpu @@ -128,8 +128,8 @@ disable_L1_cache: get_arm_private_peripheral_base: @ Get base address of private perpherial space - mrc p15, 4, r0, c15, c0, 0 @ Read periph base address - @ mov r0, #0x00A00000 + @ mrc p15, 4, r0, c15, c0, 0 @ Read periph base address + mov r0, #0x00A00000 bx lr .endfunc @get_arm_private_peripheral_base()@ @@ -213,7 +213,8 @@ arm_branch_target_cache_invalidate_is: scu_enable: @ mrc p15, 4, r0, c15, c0, 0 @ Read periph base address - mov r0, #0x00A00000 + mov r0, #0x00A00000 + add r0, #0x80000000 ldr r1, [r0, #0x0] @ Read the SCU Control Register orr r1, r1, #0x1 @ Set bit 0 (The Enable bit) @@ -268,7 +269,8 @@ scu_leave_smp: scu_get_cpus_in_smp: @ mrc p15, 4, r0, c15, c0, 0 @ Read periph base address - mov r0, #0x00A00000 + mov r0, #0x00A00000 + add r0, #0x80000000 ldr r0, [r0, #0x004] @ Read SCU Configuration register mov r0, r0, lsr #4 @ Bits 7:4 gives the cores in SMP mode, shift then mask @@ -327,6 +329,7 @@ scu_secure_invalidate: mov r1, r1, lsl r0 @ Shift ways into the correct CPU field mrc p15, 4, r2, c15, c0, 0 @ Read periph base address + add r2, #0x80000000 str r1, [r2, #0x0C] @ Write to SCU Invalidate All in Secure State diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/include/regssrc.h b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/include/regssrc.h new file mode 100644 index 000000000..ec7b6e288 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/include/regssrc.h @@ -0,0 +1,1892 @@ +/* + * Copyright (c) 2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL FREESCALE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ +/* + * WARNING! DO NOT EDIT THIS FILE DIRECTLY! + * + * This file was generated automatically and any changes may be lost. + */ +#ifndef __HW_SRC_REGISTERS_H__ +#define __HW_SRC_REGISTERS_H__ + +#include "mmio_access.h" +#include "regs.h" + +/* + * i.MX6DQ SRC + * + * SRC + * + * Registers defined in this header file: + * - HW_SRC_SCR - SRC Control Register + * - HW_SRC_SBMR1 - SRC Boot Mode Register 1 + * - HW_SRC_SRSR - SRC Reset Status Register + * - HW_SRC_SISR - SRC Interrupt Status Register + * - HW_SRC_SIMR - SRC Interrupt Mask Register + * - HW_SRC_SBMR2 - SRC Boot Mode Register 2 + * - HW_SRC_GPR1 - SRC General Purpose Register 1 + * - HW_SRC_GPR2 - SRC General Purpose Register 2 + * - HW_SRC_GPR3 - SRC General Purpose Register 3 + * - HW_SRC_GPR4 - SRC General Purpose Register 4 + * - HW_SRC_GPR5 - SRC General Purpose Register 5 + * - HW_SRC_GPR6 - SRC General Purpose Register 6 + * - HW_SRC_GPR7 - SRC General Purpose Register 7 + * - HW_SRC_GPR8 - SRC General Purpose Register 8 + * - HW_SRC_GPR9 - SRC General Purpose Register 9 + * - HW_SRC_GPR10 - SRC General Purpose Register 10 + * + * - hw_src_t - Struct containing all module registers. + */ + +//! @name Module base addresses +//@{ +#ifndef REGS_SRC_BASE +#define HW_SRC_INSTANCE_COUNT (1) //!< Number of instances of the SRC module. +#define REGS_SRC_BASE MMIO_P2V_WO(0x020d8000) //!< Base address for SRC. +#endif +//@} + +//------------------------------------------------------------------------------------------- +// HW_SRC_SCR - SRC Control Register +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_SCR - SRC Control Register (RW) + * + * Reset value: 0x00000521 + * + * The Reset control register (SCR), contains bits that control operation of the reset controller. + */ +typedef union _hw_src_scr { + reg32_t U; + struct _hw_src_scr_bitfields { + unsigned WARM_RESET_ENABLE : 1; //!< [0] WARM reset enable bit. + unsigned SW_GPU_RST : 1; //!< [1] Software reset for gpu + unsigned SW_VPU_RST : 1; //!< [2] Software reset for vpu + unsigned SW_IPU1_RST : 1; //!< [3] Software reset for ipu1 + unsigned SW_OPEN_VG_RST : 1; //!< [4] Software reset for open_vg + unsigned WARM_RST_BYPASS_COUNT : 2; //!< [6:5] Defines the ckil cycles to count before bypassing the MMDC acknowledge for WARM reset. + unsigned MASK_WDOG_RST : 4; //!< [10:7] Mask wdog_rst_b source. + unsigned EIM_RST : 1; //!< [11] EIM reset is needed in order to reconfigure the eim chip select. + unsigned SW_IPU2_RST : 1; //!< [12] Software reset for ipu2 + unsigned CORE0_RST : 1; //!< [13] Software reset for core0 only. + unsigned CORE1_RST : 1; //!< [14] Software reset for core1 only. + unsigned CORE2_RST : 1; //!< [15] Software reset for core2 only. + unsigned CORE3_RST : 1; //!< [16] Software reset for core3 only. + unsigned CORE0_DBG_RST : 1; //!< [17] Software reset for core0 debug only. + unsigned CORE1_DBG_RST : 1; //!< [18] Software reset for core1 debug only. + unsigned CORE2_DBG_RST : 1; //!< [19] Software reset for core2 debug only. + unsigned CORE3_DBG_RST : 1; //!< [20] Software reset for core3 debug only. + unsigned CORES_DBG_RST : 1; //!< [21] Software reset for debug of arm platform only. + unsigned CORE1_ENABLE : 1; //!< [22] CPU core1 enable. + unsigned CORE2_ENABLE : 1; //!< [23] CPU core2 enable. + unsigned CORE3_ENABLE : 1; //!< [24] CPU core3 enable. + unsigned DBG_RST_MSK_PG : 1; //!< [25] Do not assert debug resets after power gating event of cpu + unsigned RESERVED0 : 6; //!< [31:26] Reserved + } B; +} hw_src_scr_t; +#endif + +/*! + * @name Constants and macros for entire SRC_SCR register + */ +//@{ +#define HW_SRC_SCR_ADDR (REGS_SRC_BASE + 0x0) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_SCR (*(volatile hw_src_scr_t*)HW_SRC_SCR_ADDR) +#define HW_SRC_SCR_RD() (HW_SRC_SCR.U) +#define HW_SRC_SCR_WR(v) (HW_SRC_SCR.U = (v)) +#define HW_SRC_SCR_SET(v) (HW_SRC_SCR_WR(HW_SRC_SCR_RD() | (v))) +#define HW_SRC_SCR_CLR(v) (HW_SRC_SCR_WR(HW_SRC_SCR_RD() & ~(v))) +#define HW_SRC_SCR_TOG(v) (HW_SRC_SCR_WR(HW_SRC_SCR_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_SCR bitfields + */ + +/*! @name Register SRC_SCR, field WARM_RESET_ENABLE[0] (RW) + * + * WARM reset enable bit. WARM reset will be enabled only if warm_reset_enable bit is set. Otherwise + * all WARM reset sources will generate COLD reset. + * + * Values: + * - 0 - WARM reset disabled + * - 1 - WARM reset enabled + */ +//@{ +#define BP_SRC_SCR_WARM_RESET_ENABLE (0) //!< Bit position for SRC_SCR_WARM_RESET_ENABLE. +#define BM_SRC_SCR_WARM_RESET_ENABLE (0x00000001) //!< Bit mask for SRC_SCR_WARM_RESET_ENABLE. + +//! @brief Get value of SRC_SCR_WARM_RESET_ENABLE from a register value. +#define BG_SRC_SCR_WARM_RESET_ENABLE(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_WARM_RESET_ENABLE) >> BP_SRC_SCR_WARM_RESET_ENABLE) + +//! @brief Format value for bitfield SRC_SCR_WARM_RESET_ENABLE. +#define BF_SRC_SCR_WARM_RESET_ENABLE(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_WARM_RESET_ENABLE) & BM_SRC_SCR_WARM_RESET_ENABLE) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the WARM_RESET_ENABLE field to a new value. +#define BW_SRC_SCR_WARM_RESET_ENABLE(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_WARM_RESET_ENABLE) | BF_SRC_SCR_WARM_RESET_ENABLE(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field SW_GPU_RST[1] (RW) + * + * Software reset for gpu this is a self clearing bit. Once it is set to 1, the reset process will + * begin, and once it finishes, this bit will be self cleared. Software can determine that the reset + * has finished once this bit is cleared. Software can also configure SRC to generate interrupt once + * the software has finished. Please refer to SISR register for details. the reset process will + * involve 8 gpu cycles before negating the gpu reset, to allow reset assertion to propagate into + * gpu. + * + * Values: + * - 0 - do not assert gpu reset + * - 1 - assert gpu reset + */ +//@{ +#define BP_SRC_SCR_SW_GPU_RST (1) //!< Bit position for SRC_SCR_SW_GPU_RST. +#define BM_SRC_SCR_SW_GPU_RST (0x00000002) //!< Bit mask for SRC_SCR_SW_GPU_RST. + +//! @brief Get value of SRC_SCR_SW_GPU_RST from a register value. +#define BG_SRC_SCR_SW_GPU_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_SW_GPU_RST) >> BP_SRC_SCR_SW_GPU_RST) + +//! @brief Format value for bitfield SRC_SCR_SW_GPU_RST. +#define BF_SRC_SCR_SW_GPU_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_SW_GPU_RST) & BM_SRC_SCR_SW_GPU_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the SW_GPU_RST field to a new value. +#define BW_SRC_SCR_SW_GPU_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_SW_GPU_RST) | BF_SRC_SCR_SW_GPU_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field SW_VPU_RST[2] (RW) + * + * Software reset for vpu this is a self clearing bit. Once it is set to 1, the reset process will + * begin, and once it finishes, this bit will be self cleared. Software can determine that the reset + * has finished once this bit is cleared. Software can also configure SRC to generate interrupt once + * the software has finished. Please refer to SISR register for details. the reset process will + * involve 8 vpu cycles before negating the vpu reset, to allow reset assertion to propagate into + * vpu. + * + * Values: + * - 0 - do not assert vpu reset + * - 1 - assert vpu reset + */ +//@{ +#define BP_SRC_SCR_SW_VPU_RST (2) //!< Bit position for SRC_SCR_SW_VPU_RST. +#define BM_SRC_SCR_SW_VPU_RST (0x00000004) //!< Bit mask for SRC_SCR_SW_VPU_RST. + +//! @brief Get value of SRC_SCR_SW_VPU_RST from a register value. +#define BG_SRC_SCR_SW_VPU_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_SW_VPU_RST) >> BP_SRC_SCR_SW_VPU_RST) + +//! @brief Format value for bitfield SRC_SCR_SW_VPU_RST. +#define BF_SRC_SCR_SW_VPU_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_SW_VPU_RST) & BM_SRC_SCR_SW_VPU_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the SW_VPU_RST field to a new value. +#define BW_SRC_SCR_SW_VPU_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_SW_VPU_RST) | BF_SRC_SCR_SW_VPU_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field SW_IPU1_RST[3] (RW) + * + * Software reset for ipu1 Note: this is a self clearing bit. Once it is set to 1, the reset process + * will begin, and once it finishes, this bit will be self cleared. Software can determine that the + * reset has finished once this bit is cleared. Software can also configure SRC to generate + * interrupt once the software has finished. Please refer to SISR register for details. + * + * Values: + * - 0 - do not assert ipu1 reset + * - 1 - assert ipu1 reset + */ +//@{ +#define BP_SRC_SCR_SW_IPU1_RST (3) //!< Bit position for SRC_SCR_SW_IPU1_RST. +#define BM_SRC_SCR_SW_IPU1_RST (0x00000008) //!< Bit mask for SRC_SCR_SW_IPU1_RST. + +//! @brief Get value of SRC_SCR_SW_IPU1_RST from a register value. +#define BG_SRC_SCR_SW_IPU1_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_SW_IPU1_RST) >> BP_SRC_SCR_SW_IPU1_RST) + +//! @brief Format value for bitfield SRC_SCR_SW_IPU1_RST. +#define BF_SRC_SCR_SW_IPU1_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_SW_IPU1_RST) & BM_SRC_SCR_SW_IPU1_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the SW_IPU1_RST field to a new value. +#define BW_SRC_SCR_SW_IPU1_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_SW_IPU1_RST) | BF_SRC_SCR_SW_IPU1_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field SW_OPEN_VG_RST[4] (RW) + * + * Software reset for open_vg This is a self clearing bit. Once it is set to 1, the reset process + * will begin, and once it finishes, this bit will be self cleared. Software can determine that the + * reset has finished once this bit is cleared. Software can also configure SRC to generate + * interrupt once the software has finished. Please refer to SISR register for details. The reset + * process will involve 8 open_vg cycles before negating the open_vg reset, to allow reset assertion + * to propagate into open_vg. + * + * Values: + * - 0 - do not assert open_vg reset + * - 1 - assert open_vg reset + */ +//@{ +#define BP_SRC_SCR_SW_OPEN_VG_RST (4) //!< Bit position for SRC_SCR_SW_OPEN_VG_RST. +#define BM_SRC_SCR_SW_OPEN_VG_RST (0x00000010) //!< Bit mask for SRC_SCR_SW_OPEN_VG_RST. + +//! @brief Get value of SRC_SCR_SW_OPEN_VG_RST from a register value. +#define BG_SRC_SCR_SW_OPEN_VG_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_SW_OPEN_VG_RST) >> BP_SRC_SCR_SW_OPEN_VG_RST) + +//! @brief Format value for bitfield SRC_SCR_SW_OPEN_VG_RST. +#define BF_SRC_SCR_SW_OPEN_VG_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_SW_OPEN_VG_RST) & BM_SRC_SCR_SW_OPEN_VG_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the SW_OPEN_VG_RST field to a new value. +#define BW_SRC_SCR_SW_OPEN_VG_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_SW_OPEN_VG_RST) | BF_SRC_SCR_SW_OPEN_VG_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field WARM_RST_BYPASS_COUNT[6:5] (RW) + * + * Defines the ckil cycles to count before bypassing the MMDC acknowledge for WARM reset. If the + * MMDC acknowledge will not be asserted before this counter has elapsed, then a COLD reset will be + * initiated. + * + * Values: + * - 00 - Counter not to be used - system will wait until MMDC acknowledge until it is asserted. + * - 01 - Wait 16 ckil cycles before changing WARM reset to a COLD reset. + * - 10 - Wait 32 ckil cycles before changing WARM reset to a COLD reset. + * - 11 - Wait 64 ckil cycles before changing WARM reset to a COLD reset + */ +//@{ +#define BP_SRC_SCR_WARM_RST_BYPASS_COUNT (5) //!< Bit position for SRC_SCR_WARM_RST_BYPASS_COUNT. +#define BM_SRC_SCR_WARM_RST_BYPASS_COUNT (0x00000060) //!< Bit mask for SRC_SCR_WARM_RST_BYPASS_COUNT. + +//! @brief Get value of SRC_SCR_WARM_RST_BYPASS_COUNT from a register value. +#define BG_SRC_SCR_WARM_RST_BYPASS_COUNT(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_WARM_RST_BYPASS_COUNT) >> BP_SRC_SCR_WARM_RST_BYPASS_COUNT) + +//! @brief Format value for bitfield SRC_SCR_WARM_RST_BYPASS_COUNT. +#define BF_SRC_SCR_WARM_RST_BYPASS_COUNT(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_WARM_RST_BYPASS_COUNT) & BM_SRC_SCR_WARM_RST_BYPASS_COUNT) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the WARM_RST_BYPASS_COUNT field to a new value. +#define BW_SRC_SCR_WARM_RST_BYPASS_COUNT(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_WARM_RST_BYPASS_COUNT) | BF_SRC_SCR_WARM_RST_BYPASS_COUNT(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field MASK_WDOG_RST[10:7] (RW) + * + * Mask wdog_rst_b source. If these 4 bits are coded from A to 5 then, the wdog_rst_b input to SRC + * will be masked and the wdog_rst_b will not create a reset to the IC. During the time the WDOG + * event is masked using SRC logic, it is likely that the WDOG Reset Status Register (WRSR) bit 1 + * (which indicates a WDOG timeout event) will get asserted. SW / OS developer must prepare for this + * case. Re-enabling the WDOG is possible, by un-masking it in SRC, though it must be preceded by + * servicing the WDOG. However, for the case that the event has been asserted, the status bit (WRSR + * bit-1) will remain asserted, regardless of servicing the WDOG module. (HW reset is the only way + * to cause the de-assertion of that bit). any other code will be coded to 1010 i.e. wdog_rst_b is + * not masked + * + * Values: + * - 0101 - wdog_rst_b is masked + * - 1010 - wdog_rst_b is not masked (default) + */ +//@{ +#define BP_SRC_SCR_MASK_WDOG_RST (7) //!< Bit position for SRC_SCR_MASK_WDOG_RST. +#define BM_SRC_SCR_MASK_WDOG_RST (0x00000780) //!< Bit mask for SRC_SCR_MASK_WDOG_RST. + +//! @brief Get value of SRC_SCR_MASK_WDOG_RST from a register value. +#define BG_SRC_SCR_MASK_WDOG_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_MASK_WDOG_RST) >> BP_SRC_SCR_MASK_WDOG_RST) + +//! @brief Format value for bitfield SRC_SCR_MASK_WDOG_RST. +#define BF_SRC_SCR_MASK_WDOG_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_MASK_WDOG_RST) & BM_SRC_SCR_MASK_WDOG_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the MASK_WDOG_RST field to a new value. +#define BW_SRC_SCR_MASK_WDOG_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_MASK_WDOG_RST) | BF_SRC_SCR_MASK_WDOG_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field EIM_RST[11] (RW) + * + * EIM reset is needed in order to reconfigure the eim chip select. The software reset bit must de- + * asserted. The eim chip select configuration should be updated. The software bit must be re- + * asserted since this is not self-refresh. + */ +//@{ +#define BP_SRC_SCR_EIM_RST (11) //!< Bit position for SRC_SCR_EIM_RST. +#define BM_SRC_SCR_EIM_RST (0x00000800) //!< Bit mask for SRC_SCR_EIM_RST. + +//! @brief Get value of SRC_SCR_EIM_RST from a register value. +#define BG_SRC_SCR_EIM_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_EIM_RST) >> BP_SRC_SCR_EIM_RST) + +//! @brief Format value for bitfield SRC_SCR_EIM_RST. +#define BF_SRC_SCR_EIM_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_EIM_RST) & BM_SRC_SCR_EIM_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the EIM_RST field to a new value. +#define BW_SRC_SCR_EIM_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_EIM_RST) | BF_SRC_SCR_EIM_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field SW_IPU2_RST[12] (RW) + * + * Software reset for ipu2 this is a self clearing bit. Once it is set to 1, the reset process will + * begin, and once it finishes, this bit will be self cleared. Software can determine that the reset + * has finished once this bit is cleared. Software can also configure SRC to generate interrupt once + * the software has finished. Please refer to SISR register for details. + * + * Values: + * - 0 - do not assert ipu2 reset + * - 1 - assert ipu2 reset + */ +//@{ +#define BP_SRC_SCR_SW_IPU2_RST (12) //!< Bit position for SRC_SCR_SW_IPU2_RST. +#define BM_SRC_SCR_SW_IPU2_RST (0x00001000) //!< Bit mask for SRC_SCR_SW_IPU2_RST. + +//! @brief Get value of SRC_SCR_SW_IPU2_RST from a register value. +#define BG_SRC_SCR_SW_IPU2_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_SW_IPU2_RST) >> BP_SRC_SCR_SW_IPU2_RST) + +//! @brief Format value for bitfield SRC_SCR_SW_IPU2_RST. +#define BF_SRC_SCR_SW_IPU2_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_SW_IPU2_RST) & BM_SRC_SCR_SW_IPU2_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the SW_IPU2_RST field to a new value. +#define BW_SRC_SCR_SW_IPU2_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_SW_IPU2_RST) | BF_SRC_SCR_SW_IPU2_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORE0_RST[13] (RW) + * + * Software reset for core0 only. this is a self clearing bit. Once it is set to 1, the reset + * process will begin, and once it finishes, this bit will be self cleared. + * + * Values: + * - 0 - do not assert core0 reset + * - 1 - assert core0 reset + */ +//@{ +#define BP_SRC_SCR_CORE0_RST (13) //!< Bit position for SRC_SCR_CORE0_RST. +#define BM_SRC_SCR_CORE0_RST (0x00002000) //!< Bit mask for SRC_SCR_CORE0_RST. + +//! @brief Get value of SRC_SCR_CORE0_RST from a register value. +#define BG_SRC_SCR_CORE0_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORE0_RST) >> BP_SRC_SCR_CORE0_RST) + +//! @brief Format value for bitfield SRC_SCR_CORE0_RST. +#define BF_SRC_SCR_CORE0_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORE0_RST) & BM_SRC_SCR_CORE0_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORE0_RST field to a new value. +#define BW_SRC_SCR_CORE0_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORE0_RST) | BF_SRC_SCR_CORE0_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORE1_RST[14] (RW) + * + * Software reset for core1 only. this is a self clearing bit. Once it is set to 1, the reset + * process will begin, and once it finishes, this bit will be self cleared. + * + * Values: + * - 0 - do not assert core1 reset + * - 1 - assert core1 reset + */ +//@{ +#define BP_SRC_SCR_CORE1_RST (14) //!< Bit position for SRC_SCR_CORE1_RST. +#define BM_SRC_SCR_CORE1_RST (0x00004000) //!< Bit mask for SRC_SCR_CORE1_RST. + +//! @brief Get value of SRC_SCR_CORE1_RST from a register value. +#define BG_SRC_SCR_CORE1_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORE1_RST) >> BP_SRC_SCR_CORE1_RST) + +//! @brief Format value for bitfield SRC_SCR_CORE1_RST. +#define BF_SRC_SCR_CORE1_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORE1_RST) & BM_SRC_SCR_CORE1_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORE1_RST field to a new value. +#define BW_SRC_SCR_CORE1_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORE1_RST) | BF_SRC_SCR_CORE1_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORE2_RST[15] (RW) + * + * Software reset for core2 only. this is a self clearing bit. Once it is set to 1, the reset + * process will begin, and once it finishes, this bit will be self cleared. + * + * Values: + * - 0 - do not assert core2 reset + * - 1 - assert core2 reset + */ +//@{ +#define BP_SRC_SCR_CORE2_RST (15) //!< Bit position for SRC_SCR_CORE2_RST. +#define BM_SRC_SCR_CORE2_RST (0x00008000) //!< Bit mask for SRC_SCR_CORE2_RST. + +//! @brief Get value of SRC_SCR_CORE2_RST from a register value. +#define BG_SRC_SCR_CORE2_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORE2_RST) >> BP_SRC_SCR_CORE2_RST) + +//! @brief Format value for bitfield SRC_SCR_CORE2_RST. +#define BF_SRC_SCR_CORE2_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORE2_RST) & BM_SRC_SCR_CORE2_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORE2_RST field to a new value. +#define BW_SRC_SCR_CORE2_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORE2_RST) | BF_SRC_SCR_CORE2_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORE3_RST[16] (RW) + * + * Software reset for core3 only. this is a self clearing bit. Once it is set to 1, the reset + * process will begin, and once it finishes, this bit will be self cleared. + * + * Values: + * - 0 - do not assert core3 reset + * - 1 - assert core3 reset + */ +//@{ +#define BP_SRC_SCR_CORE3_RST (16) //!< Bit position for SRC_SCR_CORE3_RST. +#define BM_SRC_SCR_CORE3_RST (0x00010000) //!< Bit mask for SRC_SCR_CORE3_RST. + +//! @brief Get value of SRC_SCR_CORE3_RST from a register value. +#define BG_SRC_SCR_CORE3_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORE3_RST) >> BP_SRC_SCR_CORE3_RST) + +//! @brief Format value for bitfield SRC_SCR_CORE3_RST. +#define BF_SRC_SCR_CORE3_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORE3_RST) & BM_SRC_SCR_CORE3_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORE3_RST field to a new value. +#define BW_SRC_SCR_CORE3_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORE3_RST) | BF_SRC_SCR_CORE3_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORE0_DBG_RST[17] (RW) + * + * Software reset for core0 debug only. this is a self clearing bit. Once it is set to 1, the reset + * process will begin, and once it finishes, this bit will be self cleared. + * + * Values: + * - 0 - do not assert core0 debug reset + * - 1 - assert core0 debug reset + */ +//@{ +#define BP_SRC_SCR_CORE0_DBG_RST (17) //!< Bit position for SRC_SCR_CORE0_DBG_RST. +#define BM_SRC_SCR_CORE0_DBG_RST (0x00020000) //!< Bit mask for SRC_SCR_CORE0_DBG_RST. + +//! @brief Get value of SRC_SCR_CORE0_DBG_RST from a register value. +#define BG_SRC_SCR_CORE0_DBG_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORE0_DBG_RST) >> BP_SRC_SCR_CORE0_DBG_RST) + +//! @brief Format value for bitfield SRC_SCR_CORE0_DBG_RST. +#define BF_SRC_SCR_CORE0_DBG_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORE0_DBG_RST) & BM_SRC_SCR_CORE0_DBG_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORE0_DBG_RST field to a new value. +#define BW_SRC_SCR_CORE0_DBG_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORE0_DBG_RST) | BF_SRC_SCR_CORE0_DBG_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORE1_DBG_RST[18] (RW) + * + * Software reset for core1 debug only. this is a self clearing bit. Once it is set to 1, the reset + * process will begin, and once it finishes, this bit will be self cleared. + * + * Values: + * - 0 - do not assert core1 debug reset + * - 1 - assert core1 debug reset + */ +//@{ +#define BP_SRC_SCR_CORE1_DBG_RST (18) //!< Bit position for SRC_SCR_CORE1_DBG_RST. +#define BM_SRC_SCR_CORE1_DBG_RST (0x00040000) //!< Bit mask for SRC_SCR_CORE1_DBG_RST. + +//! @brief Get value of SRC_SCR_CORE1_DBG_RST from a register value. +#define BG_SRC_SCR_CORE1_DBG_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORE1_DBG_RST) >> BP_SRC_SCR_CORE1_DBG_RST) + +//! @brief Format value for bitfield SRC_SCR_CORE1_DBG_RST. +#define BF_SRC_SCR_CORE1_DBG_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORE1_DBG_RST) & BM_SRC_SCR_CORE1_DBG_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORE1_DBG_RST field to a new value. +#define BW_SRC_SCR_CORE1_DBG_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORE1_DBG_RST) | BF_SRC_SCR_CORE1_DBG_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORE2_DBG_RST[19] (RW) + * + * Software reset for core2 debug only. this is a self clearing bit. Once it is set to 1, the reset + * process will begin, and once it finishes, this bit will be self cleared. + * + * Values: + * - 0 - do not assert core2 debug reset + * - 1 - assert core2 debug reset + */ +//@{ +#define BP_SRC_SCR_CORE2_DBG_RST (19) //!< Bit position for SRC_SCR_CORE2_DBG_RST. +#define BM_SRC_SCR_CORE2_DBG_RST (0x00080000) //!< Bit mask for SRC_SCR_CORE2_DBG_RST. + +//! @brief Get value of SRC_SCR_CORE2_DBG_RST from a register value. +#define BG_SRC_SCR_CORE2_DBG_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORE2_DBG_RST) >> BP_SRC_SCR_CORE2_DBG_RST) + +//! @brief Format value for bitfield SRC_SCR_CORE2_DBG_RST. +#define BF_SRC_SCR_CORE2_DBG_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORE2_DBG_RST) & BM_SRC_SCR_CORE2_DBG_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORE2_DBG_RST field to a new value. +#define BW_SRC_SCR_CORE2_DBG_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORE2_DBG_RST) | BF_SRC_SCR_CORE2_DBG_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORE3_DBG_RST[20] (RW) + * + * Software reset for core3 debug only. this is a self clearing bit. Once it is set to 1, the reset + * process will begin, and once it finishes, this bit will be self cleared. + * + * Values: + * - 0 - do not assert core3 debug reset + * - 1 - assert core3 debug reset + */ +//@{ +#define BP_SRC_SCR_CORE3_DBG_RST (20) //!< Bit position for SRC_SCR_CORE3_DBG_RST. +#define BM_SRC_SCR_CORE3_DBG_RST (0x00100000) //!< Bit mask for SRC_SCR_CORE3_DBG_RST. + +//! @brief Get value of SRC_SCR_CORE3_DBG_RST from a register value. +#define BG_SRC_SCR_CORE3_DBG_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORE3_DBG_RST) >> BP_SRC_SCR_CORE3_DBG_RST) + +//! @brief Format value for bitfield SRC_SCR_CORE3_DBG_RST. +#define BF_SRC_SCR_CORE3_DBG_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORE3_DBG_RST) & BM_SRC_SCR_CORE3_DBG_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORE3_DBG_RST field to a new value. +#define BW_SRC_SCR_CORE3_DBG_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORE3_DBG_RST) | BF_SRC_SCR_CORE3_DBG_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORES_DBG_RST[21] (RW) + * + * Software reset for debug of arm platform only. this is a self clearing bit. Once it is set to 1, + * the reset process will begin, and once it finishes, this bit will be self cleared. + * + * Values: + * - 0 - do not assert arm platform debug reset + * - 1 - assert arm platform debug reset + */ +//@{ +#define BP_SRC_SCR_CORES_DBG_RST (21) //!< Bit position for SRC_SCR_CORES_DBG_RST. +#define BM_SRC_SCR_CORES_DBG_RST (0x00200000) //!< Bit mask for SRC_SCR_CORES_DBG_RST. + +//! @brief Get value of SRC_SCR_CORES_DBG_RST from a register value. +#define BG_SRC_SCR_CORES_DBG_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORES_DBG_RST) >> BP_SRC_SCR_CORES_DBG_RST) + +//! @brief Format value for bitfield SRC_SCR_CORES_DBG_RST. +#define BF_SRC_SCR_CORES_DBG_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORES_DBG_RST) & BM_SRC_SCR_CORES_DBG_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORES_DBG_RST field to a new value. +#define BW_SRC_SCR_CORES_DBG_RST(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORES_DBG_RST) | BF_SRC_SCR_CORES_DBG_RST(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORE1_ENABLE[22] (RW) + * + * CPU core1 enable. core0 cannot be disabled + * + * Values: + * - 0 - core1 is disabled + * - 1 - core1 is enabled + */ +//@{ +#define BP_SRC_SCR_CORE1_ENABLE (22) //!< Bit position for SRC_SCR_CORE1_ENABLE. +#define BM_SRC_SCR_CORE1_ENABLE (0x00400000) //!< Bit mask for SRC_SCR_CORE1_ENABLE. + +//! @brief Get value of SRC_SCR_CORE1_ENABLE from a register value. +#define BG_SRC_SCR_CORE1_ENABLE(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORE1_ENABLE) >> BP_SRC_SCR_CORE1_ENABLE) + +//! @brief Format value for bitfield SRC_SCR_CORE1_ENABLE. +#define BF_SRC_SCR_CORE1_ENABLE(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORE1_ENABLE) & BM_SRC_SCR_CORE1_ENABLE) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORE1_ENABLE field to a new value. +#define BW_SRC_SCR_CORE1_ENABLE(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORE1_ENABLE) | BF_SRC_SCR_CORE1_ENABLE(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORE2_ENABLE[23] (RW) + * + * CPU core2 enable. core0 cannot be disabled + * + * Values: + * - 0 - core2 is disabled + * - 1 - core2 is enabled + */ +//@{ +#define BP_SRC_SCR_CORE2_ENABLE (23) //!< Bit position for SRC_SCR_CORE2_ENABLE. +#define BM_SRC_SCR_CORE2_ENABLE (0x00800000) //!< Bit mask for SRC_SCR_CORE2_ENABLE. + +//! @brief Get value of SRC_SCR_CORE2_ENABLE from a register value. +#define BG_SRC_SCR_CORE2_ENABLE(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORE2_ENABLE) >> BP_SRC_SCR_CORE2_ENABLE) + +//! @brief Format value for bitfield SRC_SCR_CORE2_ENABLE. +#define BF_SRC_SCR_CORE2_ENABLE(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORE2_ENABLE) & BM_SRC_SCR_CORE2_ENABLE) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORE2_ENABLE field to a new value. +#define BW_SRC_SCR_CORE2_ENABLE(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORE2_ENABLE) | BF_SRC_SCR_CORE2_ENABLE(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field CORE3_ENABLE[24] (RW) + * + * CPU core3 enable. core0 cannot be disabled + * + * Values: + * - 0 - core3 is disabled + * - 1 - core3 is enabled + */ +//@{ +#define BP_SRC_SCR_CORE3_ENABLE (24) //!< Bit position for SRC_SCR_CORE3_ENABLE. +#define BM_SRC_SCR_CORE3_ENABLE (0x01000000) //!< Bit mask for SRC_SCR_CORE3_ENABLE. + +//! @brief Get value of SRC_SCR_CORE3_ENABLE from a register value. +#define BG_SRC_SCR_CORE3_ENABLE(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_CORE3_ENABLE) >> BP_SRC_SCR_CORE3_ENABLE) + +//! @brief Format value for bitfield SRC_SCR_CORE3_ENABLE. +#define BF_SRC_SCR_CORE3_ENABLE(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_CORE3_ENABLE) & BM_SRC_SCR_CORE3_ENABLE) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CORE3_ENABLE field to a new value. +#define BW_SRC_SCR_CORE3_ENABLE(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_CORE3_ENABLE) | BF_SRC_SCR_CORE3_ENABLE(v))) +#endif +//@} + +/*! @name Register SRC_SCR, field DBG_RST_MSK_PG[25] (RW) + * + * Do not assert debug resets after power gating event of cpu + * + * Values: + * - 0 - don't mask cpu debug resets (debug resets will be asserted after power gating event) + * - 1 - makes cpu debug resets (debug resets won't be asserted after power gating event) + */ +//@{ +#define BP_SRC_SCR_DBG_RST_MSK_PG (25) //!< Bit position for SRC_SCR_DBG_RST_MSK_PG. +#define BM_SRC_SCR_DBG_RST_MSK_PG (0x02000000) //!< Bit mask for SRC_SCR_DBG_RST_MSK_PG. + +//! @brief Get value of SRC_SCR_DBG_RST_MSK_PG from a register value. +#define BG_SRC_SCR_DBG_RST_MSK_PG(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SCR_DBG_RST_MSK_PG) >> BP_SRC_SCR_DBG_RST_MSK_PG) + +//! @brief Format value for bitfield SRC_SCR_DBG_RST_MSK_PG. +#define BF_SRC_SCR_DBG_RST_MSK_PG(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SCR_DBG_RST_MSK_PG) & BM_SRC_SCR_DBG_RST_MSK_PG) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the DBG_RST_MSK_PG field to a new value. +#define BW_SRC_SCR_DBG_RST_MSK_PG(v) (HW_SRC_SCR_WR((HW_SRC_SCR_RD() & ~BM_SRC_SCR_DBG_RST_MSK_PG) | BF_SRC_SCR_DBG_RST_MSK_PG(v))) +#endif +//@} + +//------------------------------------------------------------------------------------------- +// HW_SRC_SBMR1 - SRC Boot Mode Register 1 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_SBMR1 - SRC Boot Mode Register 1 (RO) + * + * Reset value: 0x00000000 + * + * The Boot Mode register (SBMR) contains bits that reflect the status of Boot Mode Pins of the + * chip. The reset value is configuration dependent (depending on boot/fuses/IO pads). + */ +typedef union _hw_src_sbmr1 { + reg32_t U; + struct _hw_src_sbmr1_bitfields { + unsigned BOOT_CFG1 : 8; //!< [7:0] Please refer to fuse map. + unsigned BOOT_CFG2 : 8; //!< [15:8] Please refer to fuse map. + unsigned BOOT_CFG3 : 8; //!< [23:16] Please refer to fuse map. + unsigned BOOT_CFG4 : 8; //!< [31:24] Please refer to fuse map. + } B; +} hw_src_sbmr1_t; +#endif + +/*! + * @name Constants and macros for entire SRC_SBMR1 register + */ +//@{ +#define HW_SRC_SBMR1_ADDR (REGS_SRC_BASE + 0x4) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_SBMR1 (*(volatile hw_src_sbmr1_t*)HW_SRC_SBMR1_ADDR) +#define HW_SRC_SBMR1_RD() (HW_SRC_SBMR1.U) +#endif +//@} + +/* + * constants & macros for individual SRC_SBMR1 bitfields + */ + +/*! @name Register SRC_SBMR1, field BOOT_CFG1[7:0] (RO) + * + * Please refer to fuse map. + */ +//@{ +#define BP_SRC_SBMR1_BOOT_CFG1 (0) //!< Bit position for SRC_SBMR1_BOOT_CFG1. +#define BM_SRC_SBMR1_BOOT_CFG1 (0x000000ff) //!< Bit mask for SRC_SBMR1_BOOT_CFG1. + +//! @brief Get value of SRC_SBMR1_BOOT_CFG1 from a register value. +#define BG_SRC_SBMR1_BOOT_CFG1(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SBMR1_BOOT_CFG1) >> BP_SRC_SBMR1_BOOT_CFG1) +//@} + +/*! @name Register SRC_SBMR1, field BOOT_CFG2[15:8] (RO) + * + * Please refer to fuse map. + */ +//@{ +#define BP_SRC_SBMR1_BOOT_CFG2 (8) //!< Bit position for SRC_SBMR1_BOOT_CFG2. +#define BM_SRC_SBMR1_BOOT_CFG2 (0x0000ff00) //!< Bit mask for SRC_SBMR1_BOOT_CFG2. + +//! @brief Get value of SRC_SBMR1_BOOT_CFG2 from a register value. +#define BG_SRC_SBMR1_BOOT_CFG2(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SBMR1_BOOT_CFG2) >> BP_SRC_SBMR1_BOOT_CFG2) +//@} + +/*! @name Register SRC_SBMR1, field BOOT_CFG3[23:16] (RO) + * + * Please refer to fuse map. + */ +//@{ +#define BP_SRC_SBMR1_BOOT_CFG3 (16) //!< Bit position for SRC_SBMR1_BOOT_CFG3. +#define BM_SRC_SBMR1_BOOT_CFG3 (0x00ff0000) //!< Bit mask for SRC_SBMR1_BOOT_CFG3. + +//! @brief Get value of SRC_SBMR1_BOOT_CFG3 from a register value. +#define BG_SRC_SBMR1_BOOT_CFG3(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SBMR1_BOOT_CFG3) >> BP_SRC_SBMR1_BOOT_CFG3) +//@} + +/*! @name Register SRC_SBMR1, field BOOT_CFG4[31:24] (RO) + * + * Please refer to fuse map. + */ +//@{ +#define BP_SRC_SBMR1_BOOT_CFG4 (24) //!< Bit position for SRC_SBMR1_BOOT_CFG4. +#define BM_SRC_SBMR1_BOOT_CFG4 (0xff000000) //!< Bit mask for SRC_SBMR1_BOOT_CFG4. + +//! @brief Get value of SRC_SBMR1_BOOT_CFG4 from a register value. +#define BG_SRC_SBMR1_BOOT_CFG4(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SBMR1_BOOT_CFG4) >> BP_SRC_SBMR1_BOOT_CFG4) +//@} + +//------------------------------------------------------------------------------------------- +// HW_SRC_SRSR - SRC Reset Status Register +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_SRSR - SRC Reset Status Register (RW) + * + * Reset value: 0x00000001 + * + * The SRSR is a write to one clear register which records the source of the reset events for the + * chip. The SRC reset status register will capture all the reset sources that have occurred. This + * register is reset on ipp_reset_b. This is a read-write register, For bit[6-0] - writing zero does + * not have any effect. Writing one will clear the corresponding bit. The individual bits can be + * cleared by writing one to that bit. When the system comes out of reset, this register will have + * bits set corresponding to all the reset sources that occurred during system reset. Software has + * to take care to clear this register by writing one after every reset that occurs so that the + * register will contain the information of recently occurred reset. + */ +typedef union _hw_src_srsr { + reg32_t U; + struct _hw_src_srsr_bitfields { + unsigned IPP_RESET_B : 1; //!< [0] Indicates whether reset was the result of ipp_reset_b pin (Power-up sequence) + unsigned RESERVED0 : 1; //!< [1] Reserved. + unsigned CSU_RESET_B : 1; //!< [2] Indicates whether the reset was the result of the csu_reset_b input. + unsigned IPP_USER_RESET_B : 1; //!< [3] Indicates whether the reset was the result of the ipp_user_reset_b qualified reset. + unsigned WDOG_RST_B : 1; //!< [4] IC Watchdog Time-out reset. + unsigned JTAG_RST_B : 1; //!< [5] HIGH - Z JTAG reset. + unsigned JTAG_SW_RST : 1; //!< [6] JTAG SW reset. + unsigned RESERVED1 : 9; //!< [15:7] Reserved + unsigned WARM_BOOT : 1; //!< [16] WARM boot indication shows that WARM boot was initiated by software. + unsigned RESERVED2 : 15; //!< [31:17] Reserved + } B; +} hw_src_srsr_t; +#endif + +/*! + * @name Constants and macros for entire SRC_SRSR register + */ +//@{ +#define HW_SRC_SRSR_ADDR (REGS_SRC_BASE + 0x8) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_SRSR (*(volatile hw_src_srsr_t*)HW_SRC_SRSR_ADDR) +#define HW_SRC_SRSR_RD() (HW_SRC_SRSR.U) +#define HW_SRC_SRSR_WR(v) (HW_SRC_SRSR.U = (v)) +#define HW_SRC_SRSR_SET(v) (HW_SRC_SRSR_WR(HW_SRC_SRSR_RD() | (v))) +#define HW_SRC_SRSR_CLR(v) (HW_SRC_SRSR_WR(HW_SRC_SRSR_RD() & ~(v))) +#define HW_SRC_SRSR_TOG(v) (HW_SRC_SRSR_WR(HW_SRC_SRSR_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_SRSR bitfields + */ + +/*! @name Register SRC_SRSR, field IPP_RESET_B[0] (W1C) + * + * Indicates whether reset was the result of ipp_reset_b pin (Power-up sequence) + * + * Values: + * - 0 - Reset is not a result of ipp_reset_b pin. + * - 1 - Reset is a result of ipp_reset_b pin. + */ +//@{ +#define BP_SRC_SRSR_IPP_RESET_B (0) //!< Bit position for SRC_SRSR_IPP_RESET_B. +#define BM_SRC_SRSR_IPP_RESET_B (0x00000001) //!< Bit mask for SRC_SRSR_IPP_RESET_B. + +//! @brief Get value of SRC_SRSR_IPP_RESET_B from a register value. +#define BG_SRC_SRSR_IPP_RESET_B(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SRSR_IPP_RESET_B) >> BP_SRC_SRSR_IPP_RESET_B) + +//! @brief Format value for bitfield SRC_SRSR_IPP_RESET_B. +#define BF_SRC_SRSR_IPP_RESET_B(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SRSR_IPP_RESET_B) & BM_SRC_SRSR_IPP_RESET_B) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the IPP_RESET_B field to a new value. +#define BW_SRC_SRSR_IPP_RESET_B(v) (HW_SRC_SRSR_WR((HW_SRC_SRSR_RD() & ~BM_SRC_SRSR_IPP_RESET_B) | BF_SRC_SRSR_IPP_RESET_B(v))) +#endif +//@} + +/*! @name Register SRC_SRSR, field CSU_RESET_B[2] (W1C) + * + * Indicates whether the reset was the result of the csu_reset_b input. If case the csu_reset_b + * occurred during a WARM reset process, during the phase that ipg_clk is not available yet, then + * the occurrence of CSU reset will not be reflected in this bit. + * + * Values: + * - 0 - Reset is not a result of the csu_reset_b event. + * - 1 - Reset is a result of the csu_reset_b event. + */ +//@{ +#define BP_SRC_SRSR_CSU_RESET_B (2) //!< Bit position for SRC_SRSR_CSU_RESET_B. +#define BM_SRC_SRSR_CSU_RESET_B (0x00000004) //!< Bit mask for SRC_SRSR_CSU_RESET_B. + +//! @brief Get value of SRC_SRSR_CSU_RESET_B from a register value. +#define BG_SRC_SRSR_CSU_RESET_B(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SRSR_CSU_RESET_B) >> BP_SRC_SRSR_CSU_RESET_B) + +//! @brief Format value for bitfield SRC_SRSR_CSU_RESET_B. +#define BF_SRC_SRSR_CSU_RESET_B(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SRSR_CSU_RESET_B) & BM_SRC_SRSR_CSU_RESET_B) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the CSU_RESET_B field to a new value. +#define BW_SRC_SRSR_CSU_RESET_B(v) (HW_SRC_SRSR_WR((HW_SRC_SRSR_RD() & ~BM_SRC_SRSR_CSU_RESET_B) | BF_SRC_SRSR_CSU_RESET_B(v))) +#endif +//@} + +/*! @name Register SRC_SRSR, field IPP_USER_RESET_B[3] (W1C) + * + * Indicates whether the reset was the result of the ipp_user_reset_b qualified reset. + * + * Values: + * - 0 - Reset is not a result of the ipp_user_reset_b qualified as COLD reset event. + * - 1 - Reset is a result of the ipp_user_reset_b qualified as COLD reset event. + */ +//@{ +#define BP_SRC_SRSR_IPP_USER_RESET_B (3) //!< Bit position for SRC_SRSR_IPP_USER_RESET_B. +#define BM_SRC_SRSR_IPP_USER_RESET_B (0x00000008) //!< Bit mask for SRC_SRSR_IPP_USER_RESET_B. + +//! @brief Get value of SRC_SRSR_IPP_USER_RESET_B from a register value. +#define BG_SRC_SRSR_IPP_USER_RESET_B(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SRSR_IPP_USER_RESET_B) >> BP_SRC_SRSR_IPP_USER_RESET_B) + +//! @brief Format value for bitfield SRC_SRSR_IPP_USER_RESET_B. +#define BF_SRC_SRSR_IPP_USER_RESET_B(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SRSR_IPP_USER_RESET_B) & BM_SRC_SRSR_IPP_USER_RESET_B) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the IPP_USER_RESET_B field to a new value. +#define BW_SRC_SRSR_IPP_USER_RESET_B(v) (HW_SRC_SRSR_WR((HW_SRC_SRSR_RD() & ~BM_SRC_SRSR_IPP_USER_RESET_B) | BF_SRC_SRSR_IPP_USER_RESET_B(v))) +#endif +//@} + +/*! @name Register SRC_SRSR, field WDOG_RST_B[4] (W1C) + * + * IC Watchdog Time-out reset. Indicates whether the reset was the result of the watchdog time-out + * event. + * + * Values: + * - 0 - Reset is not a result of the watchdog time-out event. + * - 1 - Reset is a result of the watchdog time-out event. + */ +//@{ +#define BP_SRC_SRSR_WDOG_RST_B (4) //!< Bit position for SRC_SRSR_WDOG_RST_B. +#define BM_SRC_SRSR_WDOG_RST_B (0x00000010) //!< Bit mask for SRC_SRSR_WDOG_RST_B. + +//! @brief Get value of SRC_SRSR_WDOG_RST_B from a register value. +#define BG_SRC_SRSR_WDOG_RST_B(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SRSR_WDOG_RST_B) >> BP_SRC_SRSR_WDOG_RST_B) + +//! @brief Format value for bitfield SRC_SRSR_WDOG_RST_B. +#define BF_SRC_SRSR_WDOG_RST_B(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SRSR_WDOG_RST_B) & BM_SRC_SRSR_WDOG_RST_B) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the WDOG_RST_B field to a new value. +#define BW_SRC_SRSR_WDOG_RST_B(v) (HW_SRC_SRSR_WR((HW_SRC_SRSR_RD() & ~BM_SRC_SRSR_WDOG_RST_B) | BF_SRC_SRSR_WDOG_RST_B(v))) +#endif +//@} + +/*! @name Register SRC_SRSR, field JTAG_RST_B[5] (W1C) + * + * HIGH - Z JTAG reset. Indicates whether the reset was the result of HIGH-Z reset from JTAG. + * Connections at chip-level: jtag_rst_b -> sjc_ieee_reset_b + * + * Values: + * - 0 - Reset is not a result of HIGH-Z reset from JTAG. + * - 1 - Reset is a result of HIGH-Z reset from JTAG. + */ +//@{ +#define BP_SRC_SRSR_JTAG_RST_B (5) //!< Bit position for SRC_SRSR_JTAG_RST_B. +#define BM_SRC_SRSR_JTAG_RST_B (0x00000020) //!< Bit mask for SRC_SRSR_JTAG_RST_B. + +//! @brief Get value of SRC_SRSR_JTAG_RST_B from a register value. +#define BG_SRC_SRSR_JTAG_RST_B(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SRSR_JTAG_RST_B) >> BP_SRC_SRSR_JTAG_RST_B) + +//! @brief Format value for bitfield SRC_SRSR_JTAG_RST_B. +#define BF_SRC_SRSR_JTAG_RST_B(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SRSR_JTAG_RST_B) & BM_SRC_SRSR_JTAG_RST_B) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the JTAG_RST_B field to a new value. +#define BW_SRC_SRSR_JTAG_RST_B(v) (HW_SRC_SRSR_WR((HW_SRC_SRSR_RD() & ~BM_SRC_SRSR_JTAG_RST_B) | BF_SRC_SRSR_JTAG_RST_B(v))) +#endif +//@} + +/*! @name Register SRC_SRSR, field JTAG_SW_RST[6] (W1C) + * + * JTAG SW reset. Indicates whether the reset was the result of software reset from JTAG. + * Connections at chip-level: jtag_sw_rst -> sjc_gpccr_reg_2_b + * + * Values: + * - 0 - Reset is not a result of software reset from JTAG. + * - 1 - Reset is a result of software reset from JTAG. + */ +//@{ +#define BP_SRC_SRSR_JTAG_SW_RST (6) //!< Bit position for SRC_SRSR_JTAG_SW_RST. +#define BM_SRC_SRSR_JTAG_SW_RST (0x00000040) //!< Bit mask for SRC_SRSR_JTAG_SW_RST. + +//! @brief Get value of SRC_SRSR_JTAG_SW_RST from a register value. +#define BG_SRC_SRSR_JTAG_SW_RST(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SRSR_JTAG_SW_RST) >> BP_SRC_SRSR_JTAG_SW_RST) + +//! @brief Format value for bitfield SRC_SRSR_JTAG_SW_RST. +#define BF_SRC_SRSR_JTAG_SW_RST(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SRSR_JTAG_SW_RST) & BM_SRC_SRSR_JTAG_SW_RST) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the JTAG_SW_RST field to a new value. +#define BW_SRC_SRSR_JTAG_SW_RST(v) (HW_SRC_SRSR_WR((HW_SRC_SRSR_RD() & ~BM_SRC_SRSR_JTAG_SW_RST) | BF_SRC_SRSR_JTAG_SW_RST(v))) +#endif +//@} + +/*! @name Register SRC_SRSR, field WARM_BOOT[16] (RW) + * + * WARM boot indication shows that WARM boot was initiated by software. This indicates to the + * software that it saved the needed information in the memory before initiating the WARM reset. In + * this case, software will set this bit to '1', before initiating the WARM reset. The warm_boot bit + * should be used as indication only after a warm_reset sequence. Software should clear this bit + * after warm_reset to indicate that the next warm_reset is not performed with warm_boot. Please + * refer to for details on warm_reset. + * + * Values: + * - 0 - WARM boot process not initiated by software. + * - 1 - WARM boot initiated by software. + */ +//@{ +#define BP_SRC_SRSR_WARM_BOOT (16) //!< Bit position for SRC_SRSR_WARM_BOOT. +#define BM_SRC_SRSR_WARM_BOOT (0x00010000) //!< Bit mask for SRC_SRSR_WARM_BOOT. + +//! @brief Get value of SRC_SRSR_WARM_BOOT from a register value. +#define BG_SRC_SRSR_WARM_BOOT(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SRSR_WARM_BOOT) >> BP_SRC_SRSR_WARM_BOOT) + +//! @brief Format value for bitfield SRC_SRSR_WARM_BOOT. +#define BF_SRC_SRSR_WARM_BOOT(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SRSR_WARM_BOOT) & BM_SRC_SRSR_WARM_BOOT) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the WARM_BOOT field to a new value. +#define BW_SRC_SRSR_WARM_BOOT(v) (HW_SRC_SRSR_WR((HW_SRC_SRSR_RD() & ~BM_SRC_SRSR_WARM_BOOT) | BF_SRC_SRSR_WARM_BOOT(v))) +#endif +//@} + +//------------------------------------------------------------------------------------------- +// HW_SRC_SISR - SRC Interrupt Status Register +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_SISR - SRC Interrupt Status Register (RO) + * + * Reset value: 0x00000000 + */ +typedef union _hw_src_sisr { + reg32_t U; + struct _hw_src_sisr_bitfields { + unsigned GPU_PASSED_RESET : 1; //!< [0] Interrupt generated to indicate that gpu passed software reset and is ready to be used + unsigned VPU_PASSED_RESET : 1; //!< [1] Interrupt generated to indicate that vpu passed software reset and is ready to be used + unsigned IPU1_PASSED_RESET : 1; //!< [2] Interrupt generated to indicate that ipu passed software reset and is ready to be used + unsigned OPEN_VG_PASSED_RESET : 1; //!< [3] Interrupt generated to indicate that open_vg passed software reset and is ready to be used + unsigned IPU2_PASSED_RESET : 1; //!< [4] Interrupt generated to indicate that ipu2 passed software reset and is ready to be used + unsigned CORE0_WDOG_RST_REQ : 1; //!< [5] WDOG reset request from CPU core0. + unsigned CORE1_WDOG_RST_REQ : 1; //!< [6] WDOG reset request from CPU core1. + unsigned CORE2_WDOG_RST_REQ : 1; //!< [7] WDOG reset request from CPU core2. + unsigned CORE3_WDOG_RST_REQ : 1; //!< [8] WDOG reset request from CPU core3. + unsigned RESERVED0 : 23; //!< [31:9] Reserved + } B; +} hw_src_sisr_t; +#endif + +/*! + * @name Constants and macros for entire SRC_SISR register + */ +//@{ +#define HW_SRC_SISR_ADDR (REGS_SRC_BASE + 0x14) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_SISR (*(volatile hw_src_sisr_t*)HW_SRC_SISR_ADDR) +#define HW_SRC_SISR_RD() (HW_SRC_SISR.U) +#endif +//@} + +/* + * constants & macros for individual SRC_SISR bitfields + */ + +/*! @name Register SRC_SISR, field GPU_PASSED_RESET[0] (RO) + * + * Interrupt generated to indicate that gpu passed software reset and is ready to be used + * + * Values: + * - 0 - interrupt generated not due to gpu passed reset + * - 1 - interrupt generated due to gpu passed reset + */ +//@{ +#define BP_SRC_SISR_GPU_PASSED_RESET (0) //!< Bit position for SRC_SISR_GPU_PASSED_RESET. +#define BM_SRC_SISR_GPU_PASSED_RESET (0x00000001) //!< Bit mask for SRC_SISR_GPU_PASSED_RESET. + +//! @brief Get value of SRC_SISR_GPU_PASSED_RESET from a register value. +#define BG_SRC_SISR_GPU_PASSED_RESET(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SISR_GPU_PASSED_RESET) >> BP_SRC_SISR_GPU_PASSED_RESET) +//@} + +/*! @name Register SRC_SISR, field VPU_PASSED_RESET[1] (RO) + * + * Interrupt generated to indicate that vpu passed software reset and is ready to be used + * + * Values: + * - 0 - interrupt generated not due to vpu passed reset + * - 1 - interrupt generated due to vpu passed reset + */ +//@{ +#define BP_SRC_SISR_VPU_PASSED_RESET (1) //!< Bit position for SRC_SISR_VPU_PASSED_RESET. +#define BM_SRC_SISR_VPU_PASSED_RESET (0x00000002) //!< Bit mask for SRC_SISR_VPU_PASSED_RESET. + +//! @brief Get value of SRC_SISR_VPU_PASSED_RESET from a register value. +#define BG_SRC_SISR_VPU_PASSED_RESET(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SISR_VPU_PASSED_RESET) >> BP_SRC_SISR_VPU_PASSED_RESET) +//@} + +/*! @name Register SRC_SISR, field IPU1_PASSED_RESET[2] (RO) + * + * Interrupt generated to indicate that ipu passed software reset and is ready to be used + * + * Values: + * - 0 - interrupt generated not due to ipu passed reset + * - 1 - interrupt generated due to ipu passed reset + */ +//@{ +#define BP_SRC_SISR_IPU1_PASSED_RESET (2) //!< Bit position for SRC_SISR_IPU1_PASSED_RESET. +#define BM_SRC_SISR_IPU1_PASSED_RESET (0x00000004) //!< Bit mask for SRC_SISR_IPU1_PASSED_RESET. + +//! @brief Get value of SRC_SISR_IPU1_PASSED_RESET from a register value. +#define BG_SRC_SISR_IPU1_PASSED_RESET(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SISR_IPU1_PASSED_RESET) >> BP_SRC_SISR_IPU1_PASSED_RESET) +//@} + +/*! @name Register SRC_SISR, field OPEN_VG_PASSED_RESET[3] (RO) + * + * Interrupt generated to indicate that open_vg passed software reset and is ready to be used + * + * Values: + * - 0 - interrupt generated not due to open_vg passed reset + * - 1 - interrupt generated due to open_vg passed reset + */ +//@{ +#define BP_SRC_SISR_OPEN_VG_PASSED_RESET (3) //!< Bit position for SRC_SISR_OPEN_VG_PASSED_RESET. +#define BM_SRC_SISR_OPEN_VG_PASSED_RESET (0x00000008) //!< Bit mask for SRC_SISR_OPEN_VG_PASSED_RESET. + +//! @brief Get value of SRC_SISR_OPEN_VG_PASSED_RESET from a register value. +#define BG_SRC_SISR_OPEN_VG_PASSED_RESET(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SISR_OPEN_VG_PASSED_RESET) >> BP_SRC_SISR_OPEN_VG_PASSED_RESET) +//@} + +/*! @name Register SRC_SISR, field IPU2_PASSED_RESET[4] (RO) + * + * Interrupt generated to indicate that ipu2 passed software reset and is ready to be used + * + * Values: + * - 0 - interrupt generated not due to ipu2 passed reset + * - 1 - interrupt generated due to ipu2 passed reset + */ +//@{ +#define BP_SRC_SISR_IPU2_PASSED_RESET (4) //!< Bit position for SRC_SISR_IPU2_PASSED_RESET. +#define BM_SRC_SISR_IPU2_PASSED_RESET (0x00000010) //!< Bit mask for SRC_SISR_IPU2_PASSED_RESET. + +//! @brief Get value of SRC_SISR_IPU2_PASSED_RESET from a register value. +#define BG_SRC_SISR_IPU2_PASSED_RESET(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SISR_IPU2_PASSED_RESET) >> BP_SRC_SISR_IPU2_PASSED_RESET) +//@} + +/*! @name Register SRC_SISR, field CORE0_WDOG_RST_REQ[5] (RO) + * + * WDOG reset request from CPU core0. Read-only status bit. + */ +//@{ +#define BP_SRC_SISR_CORE0_WDOG_RST_REQ (5) //!< Bit position for SRC_SISR_CORE0_WDOG_RST_REQ. +#define BM_SRC_SISR_CORE0_WDOG_RST_REQ (0x00000020) //!< Bit mask for SRC_SISR_CORE0_WDOG_RST_REQ. + +//! @brief Get value of SRC_SISR_CORE0_WDOG_RST_REQ from a register value. +#define BG_SRC_SISR_CORE0_WDOG_RST_REQ(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SISR_CORE0_WDOG_RST_REQ) >> BP_SRC_SISR_CORE0_WDOG_RST_REQ) +//@} + +/*! @name Register SRC_SISR, field CORE1_WDOG_RST_REQ[6] (RO) + * + * WDOG reset request from CPU core1. Read-only status bit. + */ +//@{ +#define BP_SRC_SISR_CORE1_WDOG_RST_REQ (6) //!< Bit position for SRC_SISR_CORE1_WDOG_RST_REQ. +#define BM_SRC_SISR_CORE1_WDOG_RST_REQ (0x00000040) //!< Bit mask for SRC_SISR_CORE1_WDOG_RST_REQ. + +//! @brief Get value of SRC_SISR_CORE1_WDOG_RST_REQ from a register value. +#define BG_SRC_SISR_CORE1_WDOG_RST_REQ(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SISR_CORE1_WDOG_RST_REQ) >> BP_SRC_SISR_CORE1_WDOG_RST_REQ) +//@} + +/*! @name Register SRC_SISR, field CORE2_WDOG_RST_REQ[7] (RO) + * + * WDOG reset request from CPU core2. Read-only status bit. + */ +//@{ +#define BP_SRC_SISR_CORE2_WDOG_RST_REQ (7) //!< Bit position for SRC_SISR_CORE2_WDOG_RST_REQ. +#define BM_SRC_SISR_CORE2_WDOG_RST_REQ (0x00000080) //!< Bit mask for SRC_SISR_CORE2_WDOG_RST_REQ. + +//! @brief Get value of SRC_SISR_CORE2_WDOG_RST_REQ from a register value. +#define BG_SRC_SISR_CORE2_WDOG_RST_REQ(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SISR_CORE2_WDOG_RST_REQ) >> BP_SRC_SISR_CORE2_WDOG_RST_REQ) +//@} + +/*! @name Register SRC_SISR, field CORE3_WDOG_RST_REQ[8] (RO) + * + * WDOG reset request from CPU core3. Read-only status bit. + */ +//@{ +#define BP_SRC_SISR_CORE3_WDOG_RST_REQ (8) //!< Bit position for SRC_SISR_CORE3_WDOG_RST_REQ. +#define BM_SRC_SISR_CORE3_WDOG_RST_REQ (0x00000100) //!< Bit mask for SRC_SISR_CORE3_WDOG_RST_REQ. + +//! @brief Get value of SRC_SISR_CORE3_WDOG_RST_REQ from a register value. +#define BG_SRC_SISR_CORE3_WDOG_RST_REQ(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SISR_CORE3_WDOG_RST_REQ) >> BP_SRC_SISR_CORE3_WDOG_RST_REQ) +//@} + +//------------------------------------------------------------------------------------------- +// HW_SRC_SIMR - SRC Interrupt Mask Register +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_SIMR - SRC Interrupt Mask Register (RW) + * + * Reset value: 0x0000001f + */ +typedef union _hw_src_simr { + reg32_t U; + struct _hw_src_simr_bitfields { + unsigned MASK_GPU_PASSED_RESET : 1; //!< [0] mask interrupt generation due to gpu passed reset + unsigned MASK_VPU_PASSED_RESET : 1; //!< [1] mask interrupt generation due to vpu passed reset + unsigned MASK_IPU_PASSED_RESET : 1; //!< [2] mask interrupt generation due to ipu passed reset + unsigned MASK_OPEN_VG_PASSED_RESET : 1; //!< [3] mask interrupt generation due to open_vg passed reset + unsigned MASK_IPU2_PASSED_RESET : 1; //!< [4] mask interrupt generation due to ipu2 passing reset + unsigned RESERVED0 : 27; //!< [31:5] Reserved + } B; +} hw_src_simr_t; +#endif + +/*! + * @name Constants and macros for entire SRC_SIMR register + */ +//@{ +#define HW_SRC_SIMR_ADDR (REGS_SRC_BASE + 0x18) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_SIMR (*(volatile hw_src_simr_t*)HW_SRC_SIMR_ADDR) +#define HW_SRC_SIMR_RD() (HW_SRC_SIMR.U) +#define HW_SRC_SIMR_WR(v) (HW_SRC_SIMR.U = (v)) +#define HW_SRC_SIMR_SET(v) (HW_SRC_SIMR_WR(HW_SRC_SIMR_RD() | (v))) +#define HW_SRC_SIMR_CLR(v) (HW_SRC_SIMR_WR(HW_SRC_SIMR_RD() & ~(v))) +#define HW_SRC_SIMR_TOG(v) (HW_SRC_SIMR_WR(HW_SRC_SIMR_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_SIMR bitfields + */ + +/*! @name Register SRC_SIMR, field MASK_GPU_PASSED_RESET[0] (RW) + * + * mask interrupt generation due to gpu passed reset + * + * Values: + * - 0 - don't mask interrupt due to gpu passed reset - interrupt will be created + * - 1 - mask interrupt due to gpu passed reset + */ +//@{ +#define BP_SRC_SIMR_MASK_GPU_PASSED_RESET (0) //!< Bit position for SRC_SIMR_MASK_GPU_PASSED_RESET. +#define BM_SRC_SIMR_MASK_GPU_PASSED_RESET (0x00000001) //!< Bit mask for SRC_SIMR_MASK_GPU_PASSED_RESET. + +//! @brief Get value of SRC_SIMR_MASK_GPU_PASSED_RESET from a register value. +#define BG_SRC_SIMR_MASK_GPU_PASSED_RESET(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SIMR_MASK_GPU_PASSED_RESET) >> BP_SRC_SIMR_MASK_GPU_PASSED_RESET) + +//! @brief Format value for bitfield SRC_SIMR_MASK_GPU_PASSED_RESET. +#define BF_SRC_SIMR_MASK_GPU_PASSED_RESET(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SIMR_MASK_GPU_PASSED_RESET) & BM_SRC_SIMR_MASK_GPU_PASSED_RESET) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the MASK_GPU_PASSED_RESET field to a new value. +#define BW_SRC_SIMR_MASK_GPU_PASSED_RESET(v) (HW_SRC_SIMR_WR((HW_SRC_SIMR_RD() & ~BM_SRC_SIMR_MASK_GPU_PASSED_RESET) | BF_SRC_SIMR_MASK_GPU_PASSED_RESET(v))) +#endif +//@} + +/*! @name Register SRC_SIMR, field MASK_VPU_PASSED_RESET[1] (RW) + * + * mask interrupt generation due to vpu passed reset + * + * Values: + * - 0 - don't mask interrupt due to vpu passed reset - interrupt will be created + * - 1 - mask interrupt due to vpu passed reset + */ +//@{ +#define BP_SRC_SIMR_MASK_VPU_PASSED_RESET (1) //!< Bit position for SRC_SIMR_MASK_VPU_PASSED_RESET. +#define BM_SRC_SIMR_MASK_VPU_PASSED_RESET (0x00000002) //!< Bit mask for SRC_SIMR_MASK_VPU_PASSED_RESET. + +//! @brief Get value of SRC_SIMR_MASK_VPU_PASSED_RESET from a register value. +#define BG_SRC_SIMR_MASK_VPU_PASSED_RESET(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SIMR_MASK_VPU_PASSED_RESET) >> BP_SRC_SIMR_MASK_VPU_PASSED_RESET) + +//! @brief Format value for bitfield SRC_SIMR_MASK_VPU_PASSED_RESET. +#define BF_SRC_SIMR_MASK_VPU_PASSED_RESET(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SIMR_MASK_VPU_PASSED_RESET) & BM_SRC_SIMR_MASK_VPU_PASSED_RESET) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the MASK_VPU_PASSED_RESET field to a new value. +#define BW_SRC_SIMR_MASK_VPU_PASSED_RESET(v) (HW_SRC_SIMR_WR((HW_SRC_SIMR_RD() & ~BM_SRC_SIMR_MASK_VPU_PASSED_RESET) | BF_SRC_SIMR_MASK_VPU_PASSED_RESET(v))) +#endif +//@} + +/*! @name Register SRC_SIMR, field MASK_IPU_PASSED_RESET[2] (RW) + * + * mask interrupt generation due to ipu passed reset + * + * Values: + * - 0 - don't mask interrupt due to ipu passed reset - interrupt will be created + * - 1 - mask interrupt due to ipu passed reset + */ +//@{ +#define BP_SRC_SIMR_MASK_IPU_PASSED_RESET (2) //!< Bit position for SRC_SIMR_MASK_IPU_PASSED_RESET. +#define BM_SRC_SIMR_MASK_IPU_PASSED_RESET (0x00000004) //!< Bit mask for SRC_SIMR_MASK_IPU_PASSED_RESET. + +//! @brief Get value of SRC_SIMR_MASK_IPU_PASSED_RESET from a register value. +#define BG_SRC_SIMR_MASK_IPU_PASSED_RESET(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SIMR_MASK_IPU_PASSED_RESET) >> BP_SRC_SIMR_MASK_IPU_PASSED_RESET) + +//! @brief Format value for bitfield SRC_SIMR_MASK_IPU_PASSED_RESET. +#define BF_SRC_SIMR_MASK_IPU_PASSED_RESET(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SIMR_MASK_IPU_PASSED_RESET) & BM_SRC_SIMR_MASK_IPU_PASSED_RESET) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the MASK_IPU_PASSED_RESET field to a new value. +#define BW_SRC_SIMR_MASK_IPU_PASSED_RESET(v) (HW_SRC_SIMR_WR((HW_SRC_SIMR_RD() & ~BM_SRC_SIMR_MASK_IPU_PASSED_RESET) | BF_SRC_SIMR_MASK_IPU_PASSED_RESET(v))) +#endif +//@} + +/*! @name Register SRC_SIMR, field MASK_OPEN_VG_PASSED_RESET[3] (RW) + * + * mask interrupt generation due to open_vg passed reset + * + * Values: + * - 0 - don't mask interrupt due to open_vg passed reset - interrupt will be created + * - 1 - mask interrupt due to open_vg passed reset + */ +//@{ +#define BP_SRC_SIMR_MASK_OPEN_VG_PASSED_RESET (3) //!< Bit position for SRC_SIMR_MASK_OPEN_VG_PASSED_RESET. +#define BM_SRC_SIMR_MASK_OPEN_VG_PASSED_RESET (0x00000008) //!< Bit mask for SRC_SIMR_MASK_OPEN_VG_PASSED_RESET. + +//! @brief Get value of SRC_SIMR_MASK_OPEN_VG_PASSED_RESET from a register value. +#define BG_SRC_SIMR_MASK_OPEN_VG_PASSED_RESET(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SIMR_MASK_OPEN_VG_PASSED_RESET) >> BP_SRC_SIMR_MASK_OPEN_VG_PASSED_RESET) + +//! @brief Format value for bitfield SRC_SIMR_MASK_OPEN_VG_PASSED_RESET. +#define BF_SRC_SIMR_MASK_OPEN_VG_PASSED_RESET(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SIMR_MASK_OPEN_VG_PASSED_RESET) & BM_SRC_SIMR_MASK_OPEN_VG_PASSED_RESET) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the MASK_OPEN_VG_PASSED_RESET field to a new value. +#define BW_SRC_SIMR_MASK_OPEN_VG_PASSED_RESET(v) (HW_SRC_SIMR_WR((HW_SRC_SIMR_RD() & ~BM_SRC_SIMR_MASK_OPEN_VG_PASSED_RESET) | BF_SRC_SIMR_MASK_OPEN_VG_PASSED_RESET(v))) +#endif +//@} + +/*! @name Register SRC_SIMR, field MASK_IPU2_PASSED_RESET[4] (RW) + * + * mask interrupt generation due to ipu2 passing reset + * + * Values: + * - 0 - don't mask interrupt due to ipu2 passed reset - interrupt will be created + * - 1 - mask interrupt due to ipu2 passed reset + */ +//@{ +#define BP_SRC_SIMR_MASK_IPU2_PASSED_RESET (4) //!< Bit position for SRC_SIMR_MASK_IPU2_PASSED_RESET. +#define BM_SRC_SIMR_MASK_IPU2_PASSED_RESET (0x00000010) //!< Bit mask for SRC_SIMR_MASK_IPU2_PASSED_RESET. + +//! @brief Get value of SRC_SIMR_MASK_IPU2_PASSED_RESET from a register value. +#define BG_SRC_SIMR_MASK_IPU2_PASSED_RESET(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SIMR_MASK_IPU2_PASSED_RESET) >> BP_SRC_SIMR_MASK_IPU2_PASSED_RESET) + +//! @brief Format value for bitfield SRC_SIMR_MASK_IPU2_PASSED_RESET. +#define BF_SRC_SIMR_MASK_IPU2_PASSED_RESET(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_SRC_SIMR_MASK_IPU2_PASSED_RESET) & BM_SRC_SIMR_MASK_IPU2_PASSED_RESET) + +#ifndef __LANGUAGE_ASM__ +//! @brief Set the MASK_IPU2_PASSED_RESET field to a new value. +#define BW_SRC_SIMR_MASK_IPU2_PASSED_RESET(v) (HW_SRC_SIMR_WR((HW_SRC_SIMR_RD() & ~BM_SRC_SIMR_MASK_IPU2_PASSED_RESET) | BF_SRC_SIMR_MASK_IPU2_PASSED_RESET(v))) +#endif +//@} + +//------------------------------------------------------------------------------------------- +// HW_SRC_SBMR2 - SRC Boot Mode Register 2 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_SBMR2 - SRC Boot Mode Register 2 (RO) + * + * Reset value: 0x00000000 + * + * The Boot Mode register (SBMR), contains bits that reflect the status of Boot Mode Pins of the + * chip. The default values for those bits depends on the values of pins/fuses during reset + * sequence, hence the question mark on their default value. + */ +typedef union _hw_src_sbmr2 { + reg32_t U; + struct _hw_src_sbmr2_bitfields { + unsigned SEC_CONFIG : 2; //!< [1:0] Please refer to fuse map. + unsigned RESERVED0 : 1; //!< [2] Reserved + unsigned DIR_BT_DIS : 1; //!< [3] Please refer to fuse map. + unsigned BT_FUSE_SEL : 1; //!< [4] BT_FUSE_SEL (connected to gpio bt_fuse_sel) + unsigned RESERVED1 : 19; //!< [23:5] Reserved. + unsigned BMOD : 2; //!< [25:24] Please refer to fuse map. + unsigned RESERVED2 : 1; //!< [26] Reserved + unsigned TEST_MODE : 3; //!< [29:27] Please refer to fuse map. + unsigned RESERVED3 : 2; //!< [31:30] Reserved + } B; +} hw_src_sbmr2_t; +#endif + +/*! + * @name Constants and macros for entire SRC_SBMR2 register + */ +//@{ +#define HW_SRC_SBMR2_ADDR (REGS_SRC_BASE + 0x1c) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_SBMR2 (*(volatile hw_src_sbmr2_t*)HW_SRC_SBMR2_ADDR) +#define HW_SRC_SBMR2_RD() (HW_SRC_SBMR2.U) +#endif +//@} + +/* + * constants & macros for individual SRC_SBMR2 bitfields + */ + +/*! @name Register SRC_SBMR2, field SEC_CONFIG[1:0] (RO) + * + * Please refer to fuse map. + */ +//@{ +#define BP_SRC_SBMR2_SEC_CONFIG (0) //!< Bit position for SRC_SBMR2_SEC_CONFIG. +#define BM_SRC_SBMR2_SEC_CONFIG (0x00000003) //!< Bit mask for SRC_SBMR2_SEC_CONFIG. + +//! @brief Get value of SRC_SBMR2_SEC_CONFIG from a register value. +#define BG_SRC_SBMR2_SEC_CONFIG(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SBMR2_SEC_CONFIG) >> BP_SRC_SBMR2_SEC_CONFIG) +//@} + +/*! @name Register SRC_SBMR2, field DIR_BT_DIS[3] (RO) + * + * Please refer to fuse map. + */ +//@{ +#define BP_SRC_SBMR2_DIR_BT_DIS (3) //!< Bit position for SRC_SBMR2_DIR_BT_DIS. +#define BM_SRC_SBMR2_DIR_BT_DIS (0x00000008) //!< Bit mask for SRC_SBMR2_DIR_BT_DIS. + +//! @brief Get value of SRC_SBMR2_DIR_BT_DIS from a register value. +#define BG_SRC_SBMR2_DIR_BT_DIS(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SBMR2_DIR_BT_DIS) >> BP_SRC_SBMR2_DIR_BT_DIS) +//@} + +/*! @name Register SRC_SBMR2, field BT_FUSE_SEL[4] (RO) + * + * BT_FUSE_SEL (connected to gpio bt_fuse_sel) + */ +//@{ +#define BP_SRC_SBMR2_BT_FUSE_SEL (4) //!< Bit position for SRC_SBMR2_BT_FUSE_SEL. +#define BM_SRC_SBMR2_BT_FUSE_SEL (0x00000010) //!< Bit mask for SRC_SBMR2_BT_FUSE_SEL. + +//! @brief Get value of SRC_SBMR2_BT_FUSE_SEL from a register value. +#define BG_SRC_SBMR2_BT_FUSE_SEL(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SBMR2_BT_FUSE_SEL) >> BP_SRC_SBMR2_BT_FUSE_SEL) +//@} + +/*! @name Register SRC_SBMR2, field BMOD[25:24] (RO) + * + * Please refer to fuse map. + */ +//@{ +#define BP_SRC_SBMR2_BMOD (24) //!< Bit position for SRC_SBMR2_BMOD. +#define BM_SRC_SBMR2_BMOD (0x03000000) //!< Bit mask for SRC_SBMR2_BMOD. + +//! @brief Get value of SRC_SBMR2_BMOD from a register value. +#define BG_SRC_SBMR2_BMOD(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SBMR2_BMOD) >> BP_SRC_SBMR2_BMOD) +//@} + +/*! @name Register SRC_SBMR2, field TEST_MODE[29:27] (RO) + * + * Please refer to fuse map. + */ +//@{ +#define BP_SRC_SBMR2_TEST_MODE (27) //!< Bit position for SRC_SBMR2_TEST_MODE. +#define BM_SRC_SBMR2_TEST_MODE (0x38000000) //!< Bit mask for SRC_SBMR2_TEST_MODE. + +//! @brief Get value of SRC_SBMR2_TEST_MODE from a register value. +#define BG_SRC_SBMR2_TEST_MODE(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_SRC_SBMR2_TEST_MODE) >> BP_SRC_SBMR2_TEST_MODE) +//@} + +//------------------------------------------------------------------------------------------- +// HW_SRC_GPR1 - SRC General Purpose Register 1 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_GPR1 - SRC General Purpose Register 1 (RW) + * + * Reset value: 0x00000000 + * + * The general purpose register 1 (GPR1), contains read/write bits that can be used for any purpose. + */ +typedef union _hw_src_gpr1 { + reg32_t U; + struct _hw_src_gpr1_bitfields { + unsigned RESERVED0 : 32; //!< [31:0] Read/write bits, for general purpose + } B; +} hw_src_gpr1_t; +#endif + +/*! + * @name Constants and macros for entire SRC_GPR1 register + */ +//@{ +#define HW_SRC_GPR1_ADDR (REGS_SRC_BASE + 0x20) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_GPR1 (*(volatile hw_src_gpr1_t*)HW_SRC_GPR1_ADDR) +#define HW_SRC_GPR1_RD() (HW_SRC_GPR1.U) +#define HW_SRC_GPR1_WR(v) (HW_SRC_GPR1.U = (v)) +#define HW_SRC_GPR1_SET(v) (HW_SRC_GPR1_WR(HW_SRC_GPR1_RD() | (v))) +#define HW_SRC_GPR1_CLR(v) (HW_SRC_GPR1_WR(HW_SRC_GPR1_RD() & ~(v))) +#define HW_SRC_GPR1_TOG(v) (HW_SRC_GPR1_WR(HW_SRC_GPR1_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_GPR1 bitfields + */ + +//------------------------------------------------------------------------------------------- +// HW_SRC_GPR2 - SRC General Purpose Register 2 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_GPR2 - SRC General Purpose Register 2 (RW) + * + * Reset value: 0x00000000 + * + * The general purpose register 2(GPR2), contains read/write bits that can be used for any purpose. + */ +typedef union _hw_src_gpr2 { + reg32_t U; + struct _hw_src_gpr2_bitfields { + unsigned RESERVED0 : 32; //!< [31:0] Read/write bits, for general purpose + } B; +} hw_src_gpr2_t; +#endif + +/*! + * @name Constants and macros for entire SRC_GPR2 register + */ +//@{ +#define HW_SRC_GPR2_ADDR (REGS_SRC_BASE + 0x24) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_GPR2 (*(volatile hw_src_gpr2_t*)HW_SRC_GPR2_ADDR) +#define HW_SRC_GPR2_RD() (HW_SRC_GPR2.U) +#define HW_SRC_GPR2_WR(v) (HW_SRC_GPR2.U = (v)) +#define HW_SRC_GPR2_SET(v) (HW_SRC_GPR2_WR(HW_SRC_GPR2_RD() | (v))) +#define HW_SRC_GPR2_CLR(v) (HW_SRC_GPR2_WR(HW_SRC_GPR2_RD() & ~(v))) +#define HW_SRC_GPR2_TOG(v) (HW_SRC_GPR2_WR(HW_SRC_GPR2_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_GPR2 bitfields + */ + +//------------------------------------------------------------------------------------------- +// HW_SRC_GPR3 - SRC General Purpose Register 3 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_GPR3 - SRC General Purpose Register 3 (RW) + * + * Reset value: 0x00000000 + * + * The general purpose register 3 (GPR3), contains read/write bits that can be used for any purpose. + */ +typedef union _hw_src_gpr3 { + reg32_t U; + struct _hw_src_gpr3_bitfields { + unsigned RESERVED0 : 32; //!< [31:0] Read/write bits, for general purpose + } B; +} hw_src_gpr3_t; +#endif + +/*! + * @name Constants and macros for entire SRC_GPR3 register + */ +//@{ +#define HW_SRC_GPR3_ADDR (REGS_SRC_BASE + 0x28) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_GPR3 (*(volatile hw_src_gpr3_t*)HW_SRC_GPR3_ADDR) +#define HW_SRC_GPR3_RD() (HW_SRC_GPR3.U) +#define HW_SRC_GPR3_WR(v) (HW_SRC_GPR3.U = (v)) +#define HW_SRC_GPR3_SET(v) (HW_SRC_GPR3_WR(HW_SRC_GPR3_RD() | (v))) +#define HW_SRC_GPR3_CLR(v) (HW_SRC_GPR3_WR(HW_SRC_GPR3_RD() & ~(v))) +#define HW_SRC_GPR3_TOG(v) (HW_SRC_GPR3_WR(HW_SRC_GPR3_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_GPR3 bitfields + */ + +//------------------------------------------------------------------------------------------- +// HW_SRC_GPR4 - SRC General Purpose Register 4 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_GPR4 - SRC General Purpose Register 4 (RW) + * + * Reset value: 0x00000000 + * + * The general purpose register 4 (GPR4), contains read/write bits that can be used for any purpose. + */ +typedef union _hw_src_gpr4 { + reg32_t U; + struct _hw_src_gpr4_bitfields { + unsigned RESERVED0 : 32; //!< [31:0] Read/write bits, for general purpose + } B; +} hw_src_gpr4_t; +#endif + +/*! + * @name Constants and macros for entire SRC_GPR4 register + */ +//@{ +#define HW_SRC_GPR4_ADDR (REGS_SRC_BASE + 0x2c) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_GPR4 (*(volatile hw_src_gpr4_t*)HW_SRC_GPR4_ADDR) +#define HW_SRC_GPR4_RD() (HW_SRC_GPR4.U) +#define HW_SRC_GPR4_WR(v) (HW_SRC_GPR4.U = (v)) +#define HW_SRC_GPR4_SET(v) (HW_SRC_GPR4_WR(HW_SRC_GPR4_RD() | (v))) +#define HW_SRC_GPR4_CLR(v) (HW_SRC_GPR4_WR(HW_SRC_GPR4_RD() & ~(v))) +#define HW_SRC_GPR4_TOG(v) (HW_SRC_GPR4_WR(HW_SRC_GPR4_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_GPR4 bitfields + */ + +//------------------------------------------------------------------------------------------- +// HW_SRC_GPR5 - SRC General Purpose Register 5 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_GPR5 - SRC General Purpose Register 5 (RW) + * + * Reset value: 0x00000000 + * + * The general purpose register 5(GPR5), contains read/write bits that can be used for any purpose. + */ +typedef union _hw_src_gpr5 { + reg32_t U; + struct _hw_src_gpr5_bitfields { + unsigned RESERVED0 : 32; //!< [31:0] Read/write bits, for general purpose + } B; +} hw_src_gpr5_t; +#endif + +/*! + * @name Constants and macros for entire SRC_GPR5 register + */ +//@{ +#define HW_SRC_GPR5_ADDR (REGS_SRC_BASE + 0x30) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_GPR5 (*(volatile hw_src_gpr5_t*)HW_SRC_GPR5_ADDR) +#define HW_SRC_GPR5_RD() (HW_SRC_GPR5.U) +#define HW_SRC_GPR5_WR(v) (HW_SRC_GPR5.U = (v)) +#define HW_SRC_GPR5_SET(v) (HW_SRC_GPR5_WR(HW_SRC_GPR5_RD() | (v))) +#define HW_SRC_GPR5_CLR(v) (HW_SRC_GPR5_WR(HW_SRC_GPR5_RD() & ~(v))) +#define HW_SRC_GPR5_TOG(v) (HW_SRC_GPR5_WR(HW_SRC_GPR5_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_GPR5 bitfields + */ + +//------------------------------------------------------------------------------------------- +// HW_SRC_GPR6 - SRC General Purpose Register 6 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_GPR6 - SRC General Purpose Register 6 (RW) + * + * Reset value: 0x00000000 + * + * The general purpose register 6(GPR6), contains read/write bits that can be used for any purpose. + */ +typedef union _hw_src_gpr6 { + reg32_t U; + struct _hw_src_gpr6_bitfields { + unsigned RESERVED0 : 32; //!< [31:0] Read/write bits, for general purpose + } B; +} hw_src_gpr6_t; +#endif + +/*! + * @name Constants and macros for entire SRC_GPR6 register + */ +//@{ +#define HW_SRC_GPR6_ADDR (REGS_SRC_BASE + 0x34) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_GPR6 (*(volatile hw_src_gpr6_t*)HW_SRC_GPR6_ADDR) +#define HW_SRC_GPR6_RD() (HW_SRC_GPR6.U) +#define HW_SRC_GPR6_WR(v) (HW_SRC_GPR6.U = (v)) +#define HW_SRC_GPR6_SET(v) (HW_SRC_GPR6_WR(HW_SRC_GPR6_RD() | (v))) +#define HW_SRC_GPR6_CLR(v) (HW_SRC_GPR6_WR(HW_SRC_GPR6_RD() & ~(v))) +#define HW_SRC_GPR6_TOG(v) (HW_SRC_GPR6_WR(HW_SRC_GPR6_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_GPR6 bitfields + */ + +//------------------------------------------------------------------------------------------- +// HW_SRC_GPR7 - SRC General Purpose Register 7 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_GPR7 - SRC General Purpose Register 7 (RW) + * + * Reset value: 0x00000000 + * + * The general purpose register 7(GPR7), contains read/write bits that can be used for any purpose. + */ +typedef union _hw_src_gpr7 { + reg32_t U; + struct _hw_src_gpr7_bitfields { + unsigned RESERVED0 : 32; //!< [31:0] Read/write bits, for general purpose + } B; +} hw_src_gpr7_t; +#endif + +/*! + * @name Constants and macros for entire SRC_GPR7 register + */ +//@{ +#define HW_SRC_GPR7_ADDR (REGS_SRC_BASE + 0x38) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_GPR7 (*(volatile hw_src_gpr7_t*)HW_SRC_GPR7_ADDR) +#define HW_SRC_GPR7_RD() (HW_SRC_GPR7.U) +#define HW_SRC_GPR7_WR(v) (HW_SRC_GPR7.U = (v)) +#define HW_SRC_GPR7_SET(v) (HW_SRC_GPR7_WR(HW_SRC_GPR7_RD() | (v))) +#define HW_SRC_GPR7_CLR(v) (HW_SRC_GPR7_WR(HW_SRC_GPR7_RD() & ~(v))) +#define HW_SRC_GPR7_TOG(v) (HW_SRC_GPR7_WR(HW_SRC_GPR7_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_GPR7 bitfields + */ + +//------------------------------------------------------------------------------------------- +// HW_SRC_GPR8 - SRC General Purpose Register 8 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_GPR8 - SRC General Purpose Register 8 (RW) + * + * Reset value: 0x00000000 + * + * The general purpose register 8(GPR8), contains read/write bits that can be used for any purpose. + */ +typedef union _hw_src_gpr8 { + reg32_t U; + struct _hw_src_gpr8_bitfields { + unsigned RESERVED0 : 32; //!< [31:0] Read/write bits, for general purpose + } B; +} hw_src_gpr8_t; +#endif + +/*! + * @name Constants and macros for entire SRC_GPR8 register + */ +//@{ +#define HW_SRC_GPR8_ADDR (REGS_SRC_BASE + 0x3c) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_GPR8 (*(volatile hw_src_gpr8_t*)HW_SRC_GPR8_ADDR) +#define HW_SRC_GPR8_RD() (HW_SRC_GPR8.U) +#define HW_SRC_GPR8_WR(v) (HW_SRC_GPR8.U = (v)) +#define HW_SRC_GPR8_SET(v) (HW_SRC_GPR8_WR(HW_SRC_GPR8_RD() | (v))) +#define HW_SRC_GPR8_CLR(v) (HW_SRC_GPR8_WR(HW_SRC_GPR8_RD() & ~(v))) +#define HW_SRC_GPR8_TOG(v) (HW_SRC_GPR8_WR(HW_SRC_GPR8_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_GPR8 bitfields + */ + +//------------------------------------------------------------------------------------------- +// HW_SRC_GPR9 - SRC General Purpose Register 9 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_GPR9 - SRC General Purpose Register 9 (RW) + * + * Reset value: 0x00000000 + * + * The general purpose register 9(GPR9), contains read/write bits that can be used for any purpose. + */ +typedef union _hw_src_gpr9 { + reg32_t U; + struct _hw_src_gpr9_bitfields { + unsigned RESERVED0 : 32; //!< [31:0] Read/write bits, for general purpose. + } B; +} hw_src_gpr9_t; +#endif + +/*! + * @name Constants and macros for entire SRC_GPR9 register + */ +//@{ +#define HW_SRC_GPR9_ADDR (REGS_SRC_BASE + 0x40) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_GPR9 (*(volatile hw_src_gpr9_t*)HW_SRC_GPR9_ADDR) +#define HW_SRC_GPR9_RD() (HW_SRC_GPR9.U) +#define HW_SRC_GPR9_WR(v) (HW_SRC_GPR9.U = (v)) +#define HW_SRC_GPR9_SET(v) (HW_SRC_GPR9_WR(HW_SRC_GPR9_RD() | (v))) +#define HW_SRC_GPR9_CLR(v) (HW_SRC_GPR9_WR(HW_SRC_GPR9_RD() & ~(v))) +#define HW_SRC_GPR9_TOG(v) (HW_SRC_GPR9_WR(HW_SRC_GPR9_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_GPR9 bitfields + */ + +//------------------------------------------------------------------------------------------- +// HW_SRC_GPR10 - SRC General Purpose Register 10 +//------------------------------------------------------------------------------------------- + +#ifndef __LANGUAGE_ASM__ +/*! + * @brief HW_SRC_GPR10 - SRC General Purpose Register 10 (RW) + * + * Reset value: 0x00000000 + * + * The general purpose register 10(GPR10), contains read/write bits that can be used for any + * purpose. + */ +typedef union _hw_src_gpr10 { + reg32_t U; + struct _hw_src_gpr10_bitfields { + unsigned RESERVED0 : 32; //!< [31:0] Read/write bits, for general purpose. + } B; +} hw_src_gpr10_t; +#endif + +/*! + * @name Constants and macros for entire SRC_GPR10 register + */ +//@{ +#define HW_SRC_GPR10_ADDR (REGS_SRC_BASE + 0x44) + +#ifndef __LANGUAGE_ASM__ +#define HW_SRC_GPR10 (*(volatile hw_src_gpr10_t*)HW_SRC_GPR10_ADDR) +#define HW_SRC_GPR10_RD() (HW_SRC_GPR10.U) +#define HW_SRC_GPR10_WR(v) (HW_SRC_GPR10.U = (v)) +#define HW_SRC_GPR10_SET(v) (HW_SRC_GPR10_WR(HW_SRC_GPR10_RD() | (v))) +#define HW_SRC_GPR10_CLR(v) (HW_SRC_GPR10_WR(HW_SRC_GPR10_RD() & ~(v))) +#define HW_SRC_GPR10_TOG(v) (HW_SRC_GPR10_WR(HW_SRC_GPR10_RD() ^ (v))) +#endif +//@} + +/* + * constants & macros for individual SRC_GPR10 bitfields + */ + +//------------------------------------------------------------------------------------------- +// hw_src_t - module struct +//------------------------------------------------------------------------------------------- +/*! + * @brief All SRC module registers. + */ +#ifndef __LANGUAGE_ASM__ +#pragma pack(1) +typedef struct _hw_src { + volatile hw_src_scr_t SCR; //!< SRC Control Register + volatile hw_src_sbmr1_t SBMR1; //!< SRC Boot Mode Register 1 + volatile hw_src_srsr_t SRSR; //!< SRC Reset Status Register + reg32_t _reserved0[2]; + volatile hw_src_sisr_t SISR; //!< SRC Interrupt Status Register + volatile hw_src_simr_t SIMR; //!< SRC Interrupt Mask Register + volatile hw_src_sbmr2_t SBMR2; //!< SRC Boot Mode Register 2 + volatile hw_src_gpr1_t GPR1; //!< SRC General Purpose Register 1 + volatile hw_src_gpr2_t GPR2; //!< SRC General Purpose Register 2 + volatile hw_src_gpr3_t GPR3; //!< SRC General Purpose Register 3 + volatile hw_src_gpr4_t GPR4; //!< SRC General Purpose Register 4 + volatile hw_src_gpr5_t GPR5; //!< SRC General Purpose Register 5 + volatile hw_src_gpr6_t GPR6; //!< SRC General Purpose Register 6 + volatile hw_src_gpr7_t GPR7; //!< SRC General Purpose Register 7 + volatile hw_src_gpr8_t GPR8; //!< SRC General Purpose Register 8 + volatile hw_src_gpr9_t GPR9; //!< SRC General Purpose Register 9 + volatile hw_src_gpr10_t GPR10; //!< SRC General Purpose Register 10 +} hw_src_t; +#pragma pack() + +//! @brief Macro to access all SRC registers. +//! @return Reference (not a pointer) to the registers struct. To get a pointer to the struct, +//! use the '&' operator, like &HW_SRC. +#define HW_SRC (*(hw_src_t*)REGS_SRC_BASE) +#endif + +#endif // __HW_SRC_REGISTERS_H__ +// v18/121106/1.2.2 +// EOF diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/nxp_imx6q_sabrelite.lds b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/nxp_imx6q_sabrelite.lds index 2e39b0450..7a23ca569 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/nxp_imx6q_sabrelite.lds +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/nxp_imx6q_sabrelite.lds @@ -81,7 +81,7 @@ MEMORY { ocram (rwx) : ORIGIN = 0x00900000, LENGTH = 256K ddr3 (rwx) : ORIGIN = 0x10000000, LENGTH = 1024M - virt_ddr3 (WRX) : ORIGIN = 0x90010000, LENGTH = 1024M + virt_ddr3 (WRX) : ORIGIN = 0x90011000, LENGTH = 1024M } SECTIONS @@ -155,7 +155,7 @@ SECTIONS } > ddr3 /* Other Kernel code is placed over 0x80000000 + 128KB. */ - .text : AT(0x10010000) { + .text : AT(0x10011000) { *(.vectors) . = ALIGN(0x1000); *(.text .text.* .gnu.linkonce.t.*) diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/smp.c b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/smp.c new file mode 100644 index 000000000..2d16645cf --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/smp.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2010-2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file smp.c + * @brief start multicore + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2024.03.10 + */ + +/************************************************* +File name: smp.c +Description: +Others: +History: +1. Date: 2024-03-10 +Author: AIIT XUOS Lab +Modification: +1. No modifications +*************************************************/ +#include "cortex_a9.h" +#include "regssrc.h" + +extern void _boot_start(); +void cpu_start_secondary(uint8_t cpu_id) +{ + // Prepare pointers for ROM code. The entry point is always _start, which does some + // basic preparatory work and then calls the common_cpu_entry function, which itself + // calls the entry point saved in s_core_info. + switch (cpu_id) { + case 1: + HW_SRC_GPR3_WR((uint32_t)&_boot_start); + HW_SRC_SCR.B.CORE1_ENABLE = 1; + break; + + case 2: + HW_SRC_GPR5_WR((uint32_t)&_boot_start); + HW_SRC_SCR.B.CORE2_ENABLE = 1; + break; + + case 3: + HW_SRC_GPR7_WR((uint32_t)&_boot_start); + HW_SRC_SCR.B.CORE3_ENABLE = 1; + break; + default: + break; + } +} + +void start_smp_cache_broadcast(int cpu_id) +{ + return; +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_zynq7000-zc702/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_zynq7000-zc702/Makefile index 3fa7398fe..93ee942b5 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_zynq7000-zc702/Makefile +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_zynq7000-zc702/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := boot.S cpu_init.S xil-crt0.S cortexA9.S +SRC_FILES := boot.S cpu_init.S xil-crt0.S cortexA9.S smp.c include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_zynq7000-zc702/smp.c b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_zynq7000-zc702/smp.c new file mode 100644 index 000000000..e5e268e68 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_zynq7000-zc702/smp.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010-2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file smp.c + * @brief start multicore + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2024.03.10 + */ + +/************************************************* +File name: smp.c +Description: +Others: +History: +1. Date: 2024-03-10 +Author: AIIT XUOS Lab +Modification: +1. No modifications +*************************************************/ +#include "cortex_a9.h" + +extern void _boot_start(); +void cpu_start_secondary(uint8_t cpu_id) +{ + return; +} + +void start_smp_cache_broadcast(int cpu_id) +{ + return; +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_zynq7000-zc702/zynq7000-zc702.lds b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_zynq7000-zc702/zynq7000-zc702.lds index e7293cbfe..209d96510 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_zynq7000-zc702/zynq7000-zc702.lds +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_zynq7000-zc702/zynq7000-zc702.lds @@ -72,7 +72,6 @@ SECTIONS PROVIDE(boot_end_addr = .); } > ddr3 - /* Other Kernel code is placed over 0x80000000 + 128KB. */ .text : AT(0x00110000) { *(.vectors) . = ALIGN(0x1000); diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/clock/arm/armv7-a/cortex-a9/imx6q-sabrelite/clock.c b/Ubiquitous/XiZi_AIoT/hardkernel/clock/arm/armv7-a/cortex-a9/imx6q-sabrelite/clock.c index 2ac07efe0..cd144a057 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/clock/arm/armv7-a/cortex-a9/imx6q-sabrelite/clock.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/clock/arm/armv7-a/cortex-a9/imx6q-sabrelite/clock.c @@ -34,6 +34,7 @@ Modification: #include "clock_common_op.h" #include "irq_numbers.h" +#include "multicores.h" static void _sys_clock_init() { diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/hardkernel_init.c b/Ubiquitous/XiZi_AIoT/hardkernel/hardkernel_init.c index 00dfc357d..351a1266f 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/hardkernel_init.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/hardkernel_init.c @@ -36,6 +36,7 @@ Modification: #include "uart_common_ope.h" #include "assert.h" +#include "pagetable.h" #define KERN_BOOT_DRIVER(n, bi, f) \ { \ @@ -130,7 +131,6 @@ static bool xizi_gpt_init() struct XiziTrapDriver* p_intr_driver = (struct XiziTrapDriver*)AchieveResource(&intr_driver_tag); p_intr_driver->bind_irq_handler(p_clock_driver->get_clock_int(), xizi_clock_handler); p_intr_driver->single_irq_enable(p_clock_driver->get_clock_int(), 0, 0); - return true; } @@ -196,4 +196,31 @@ bool hardkernel_init(struct TraceTag* _hardkernel_tag) LOG_PRINTF("\n"); } return true; +} + +bool secondary_cpu_hardkernel_init(int cpu_id, struct TraceTag* _hardkernel_tag) +{ + struct TraceTag init_intr_tag, init_icache_tag, init_dcache_tag, init_clock_tag, init_mmu_tag; + AchieveResourceTag(&init_intr_tag, _hardkernel_tag, "intr-ac-resource"); + AchieveResourceTag(&init_icache_tag, _hardkernel_tag, "icache-ac-resource"); + AchieveResourceTag(&init_dcache_tag, _hardkernel_tag, "dcache-ac-resource"); + AchieveResourceTag(&init_clock_tag, _hardkernel_tag, "clock-ac-resource"); + AchieveResourceTag(&init_mmu_tag, _hardkernel_tag, "mmu-ac-resource"); + struct XiziTrapDriver* p_intr_driver = (struct XiziTrapDriver*)AchieveResource(&init_intr_tag); + struct ICacheDone* p_icache_driver = (struct ICacheDone*)AchieveResource(&init_icache_tag); + struct DCacheDone* p_dcache_driver = (struct DCacheDone*)AchieveResource(&init_dcache_tag); + struct XiziClockDriver* p_clock_driver = (struct XiziClockDriver*)AchieveResource(&init_clock_tag); + + // secondary cpu init hardwares + // intr + p_intr_driver->sys_irq_init(cpu_id); + p_intr_driver->cpu_irq_disable(); + // cache + p_icache_driver->enable(); + p_dcache_driver->enable(); + // clock + p_intr_driver->single_irq_enable(p_clock_driver->get_clock_int(), cpu_id, 0); + // mmu + secondary_cpu_load_kern_pgdir(&init_mmu_tag, &init_intr_tag); + return true; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/intr/Makefile index 7e69489a2..b199fd1e3 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/intr/Makefile +++ b/Ubiquitous/XiZi_AIoT/hardkernel/intr/Makefile @@ -1,3 +1,4 @@ SRC_DIR := arm/armv7-a/cortex-a9 +SRC_FILES := spinlock.c include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/Makefile index 8ea2c7e2f..ebcd0d1ff 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/Makefile +++ b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/Makefile @@ -1,5 +1,5 @@ -SRC_FILES := vector.S trampoline.S $(BOARD)/trap_common.c error_debug.c spinlock.c hard_spinlock.S +SRC_FILES := vector.S trampoline.S $(BOARD)/trap_common.c error_debug.c hard_spinlock.S ifeq ($(BOARD), imx6q-sabrelite) SRC_DIR := gicv2 @@ -9,7 +9,6 @@ ifeq ($(BOARD), zynq7000-zc702) # SRC_DIR := gicv2 SRC_DIR := gicv3 SRC_FILES += $(BOARD)/xil_assert.c -# SRC_FILES := vector.S trampoline.S imx6q-sabrelite/trap_common.c error_debug.c spinlock.c hard_spinlock.S endif diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/error_debug.c b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/error_debug.c index 9d7224da8..af072ff91 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/error_debug.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/error_debug.c @@ -41,31 +41,18 @@ Modification: *************************************************/ #include "core.h" #include "memlayout.h" +#include "spinlock.h" +#include "trap_common.h" -#include "log.h" +#include "assert.h" #include "multicores.h" #include "syscall.h" - -__attribute__((always_inline)) static inline void _abort_reason(uint32_t fault_status) -{ - if ((fault_status & 0xd) == 0x1) // Alignment failure - KPrintf("reason: alignment\n"); - else if ((fault_status & 0xd) == 0x5) // External abort "on translation" - KPrintf("reason: ext. abort on trnslt.\n"); - else if ((fault_status & 0xd) == 0x5) // Translation - KPrintf("reason: sect. translation\n"); - else if ((fault_status & 0xd) == 0x9) // Domain - KPrintf("reason: sect. domain\n"); - else if ((fault_status & 0xd) == 0xd) // Permission - KPrintf("reason: sect. permission\n"); - else if ((fault_status & 0xd) == 0x8) // External abort - KPrintf("reason: ext. abort\n"); - else - KPrintf("reason: unknown???\n"); -} +#include "task.h" void dump_tf(struct trapframe* tf) { + KPrintf("sp_usr: 0x%x\n", tf->sp_usr); + KPrintf("lr_usr: 0x%x\n", tf->lr_usr); KPrintf("lr_svc: 0x%x\n", tf->lr_svc); KPrintf(" spsr: 0x%x\n", tf->spsr); KPrintf(" r0: 0x%x\n", tf->r0); @@ -84,62 +71,74 @@ void dump_tf(struct trapframe* tf) KPrintf(" pc: 0x%x\n", tf->pc); } +void dabort_reason(struct trapframe* r) +{ + uint32_t fault_status, dfa; + __asm__ __volatile__("mrc p15, 0, %0, c5, c0, 0" : "=r"(fault_status)::); + __asm__ __volatile__("mrc p15, 0, %0, c6, c0, 0" : "=r"(dfa)::); + LOG("program counter: 0x%x caused\n", r->pc); + LOG("data abort at 0x%x, status 0x%x\n", dfa, fault_status); + + if ((fault_status & 0xd) == 0x1) // Alignment failure + KPrintf("reason: alignment\n"); + else if ((fault_status & 0xd) == 0x5) // External abort "on translation" + KPrintf("reason: ext. abort on trnslt.\n"); + else if ((fault_status & 0xd) == 0x5) // Translation + KPrintf("reason: sect. translation\n"); + else if ((fault_status & 0xd) == 0x9) // Domain + KPrintf("reason: sect. domain\n"); + else if ((fault_status & 0xd) == 0xd) // Permission + KPrintf("reason: sect. permission\n"); + else if ((fault_status & 0xd) == 0x8) // External abort + KPrintf("reason: ext. abort\n"); + else + KPrintf("reason: unknown???\n"); + + dump_tf(r); +} + +void iabort_reason(struct trapframe* r) +{ + uint32_t fault_status, ifa; + __asm__ __volatile__("mrc p15, 0, %0, c5, c0, 1" : "=r"(fault_status)::); + __asm__ __volatile__("mrc p15, 0, %0, c6, c0, 2" : "=r"(ifa)::); + LOG("prefetch abort at 0x%x, status 0x%x\n", ifa, fault_status); + + if ((fault_status & 0xd) == 0x1) // Alignment failure + KPrintf("reason: alignment\n"); + else if ((fault_status & 0xd) == 0x5) // External abort "on translation" + KPrintf("reason: ext. abort on trnslt.\n"); + else if ((fault_status & 0xd) == 0x5) // Translation + KPrintf("reason: sect. translation\n"); + else if ((fault_status & 0xd) == 0x9) // Domain + KPrintf("reason: sect. domain\n"); + else if ((fault_status & 0xd) == 0xd) // Permission + KPrintf("reason: sect. permission\n"); + else if ((fault_status & 0xd) == 0x8) // External abort + KPrintf("reason: ext. abort\n"); + else + KPrintf("reason: unknown???\n"); + + dump_tf(r); +} + void handle_undefined_instruction(struct trapframe* tf) { // unimplemented trap handler - KPrintf("undefined instruction at %x\n", tf->pc); + xizi_enter_kernel(); + ERROR("undefined instruction at %x\n", tf->pc); panic(""); } -extern void context_switch(struct context**, struct context*); -void dabort_handler(struct trapframe* r) +void handle_reserved(void) { - uint32_t dfs, dfa; - - __asm__ __volatile__("mrc p15, 0, %0, c5, c0, 0" : "=r"(dfs)::); - __asm__ __volatile__("mrc p15, 0, %0, c6, c0, 0" : "=r"(dfa)::); - - if (r->pc < KERN_MEM_BASE) { // Exception occured in User space: exit - ERROR("dabort in user space: %s\n", cur_cpu()->task->name); - LOG("program counter: 0x%x caused\n", r->pc); - LOG("data abort at 0x%x, status 0x%x\n", dfa, dfs); - _abort_reason(dfs); - dump_tf(r); - } - if (cur_cpu()->task != NULL) { - sys_exit(); - context_switch(&cur_cpu()->task->main_thread.context, cur_cpu()->scheduler); - } else { // Exception occured in Kernel space: panic - LOG("program counter: 0x%x caused\n", r->pc); - LOG("data abort at 0x%x, status 0x%x\n", dfa, dfs); - _abort_reason(dfs); - dump_tf(r); - panic("data abort exception\n"); - } + // unimplemented trap handler + xizi_enter_kernel(); + panic("Unimplemented Reserved\n"); } -void iabort_handler(struct trapframe* r) +void handle_fiq(void) { - uint32_t ifs, ifa; - - __asm__ __volatile__("mrc p15, 0, %0, c5, c0, 1" : "=r"(ifs)::); - __asm__ __volatile__("mrc p15, 0, %0, c6, c0, 2" : "=r"(ifa)::); - - if (r->pc < KERN_MEM_BASE) { // Exception occured in User space: exit - ERROR("iabort in user space: %s\n", cur_cpu()->task->name); - LOG("program counter: 0x%x(%s) caused\n", r->pc, cur_cpu()->task); - LOG("prefetch abort at 0x%x, status 0x%x\n", ifa, ifs); - _abort_reason(ifs); - dump_tf(r); - } - if (cur_cpu()->task != NULL) { - sys_exit(); - context_switch(&cur_cpu()->task->main_thread.context, cur_cpu()->scheduler); - } else { // Exception occured in Kernel space: panic - LOG("program counter: 0x%x(%s) caused\n", r->pc, cur_cpu()->task); - LOG("prefetch abort at 0x%x, status 0x%x\n", ifa, ifs); - _abort_reason(ifs); - dump_tf(r); - panic("prefetch abort exception\n"); - } -} + xizi_enter_kernel(); + panic("Unimplemented FIQ\n"); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/imx6q-sabrelite/trap_common.c b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/imx6q-sabrelite/trap_common.c index 3e1acbc0d..b564f8cb7 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/imx6q-sabrelite/trap_common.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/imx6q-sabrelite/trap_common.c @@ -34,6 +34,7 @@ Modification: #include "trap_common.h" #include "log.h" +#include "multicores.h" extern void init_stack(uint32_t, uint32_t); extern void user_trap_swi_enter(void); @@ -41,12 +42,13 @@ extern void trap_iabort(void); extern void trap_dabort(void); extern void trap_irq_enter(void); extern void trap_undefined_instruction(void); +extern void handle_reserved(void); +extern void handle_fiq(void); static struct XiziTrapDriver xizi_trap_driver; void panic(char* s) { - xizi_trap_driver.cpu_irq_disable(); KPrintf("panic: %s\n", s); for (;;) ; @@ -54,7 +56,6 @@ void panic(char* s) /* stack for different mode*/ static char mode_stack_pages[NR_CPU][NR_MODE_STACKS][MODE_STACK_SIZE]; - extern uint32_t _vector_jumper; extern uint32_t _vector_start; extern uint32_t _vector_end; @@ -69,37 +70,25 @@ void init_cpu_mode_stacks(int cpu_id) } } -void handle_reserved(void) -{ - // unimplemented trap handler - LOG("Unimplemented Reserved\n"); - panic(""); -} - -void handle_fiq(void) -{ - LOG("Unimplemented FIQ\n"); - panic(""); -} - -static void _sys_irq_init() +static void _sys_irq_init(int cpu_id) { /* load exception vectors */ - volatile uint32_t* vector_base = &_vector_start; + init_cpu_mode_stacks(cpu_id); + if (cpu_id == 0) { + volatile uint32_t* vector_base = &_vector_start; - // Set Interrupt handler start address - vector_base[1] = (uint32_t)trap_undefined_instruction; // Undefined Instruction - vector_base[2] = (uint32_t)user_trap_swi_enter; // Software Interrupt - vector_base[3] = (uint32_t)trap_iabort; // Prefetch Abort - vector_base[4] = (uint32_t)trap_dabort; // Data Abort - vector_base[5] = (uint32_t)handle_reserved; // Reserved - vector_base[6] = (uint32_t)trap_irq_enter; // IRQ - vector_base[7] = (uint32_t)handle_fiq; // FIQ - - init_cpu_mode_stacks(0); + // Set Interrupt handler start address + vector_base[1] = (uint32_t)trap_undefined_instruction; // Undefined Instruction + vector_base[2] = (uint32_t)user_trap_swi_enter; // Software Interrupt + vector_base[3] = (uint32_t)trap_iabort; // Prefetch Abort + vector_base[4] = (uint32_t)trap_dabort; // Data Abort + vector_base[5] = (uint32_t)handle_reserved; // Reserved + vector_base[6] = (uint32_t)trap_irq_enter; // IRQ + vector_base[7] = (uint32_t)handle_fiq; // FIQ + gic_init(); + } /* active hardware irq responser */ - gic_init(); xizi_trap_driver.switch_hw_irqtbl((uint32_t*)&_vector_jumper); } @@ -151,29 +140,6 @@ static void _bind_irq_handler(int irq, irq_handler_t handler) xizi_trap_driver.sw_irqtbl[irq].handler = handler; } -static bool _send_sgi(uint32_t irq, uint32_t bitmask, enum SgiFilterType type) -{ - if (bitmask > (1 << NR_CPU) - 1) { - return false; - } - - enum _gicd_sgi_filter sgi_filter; - switch (type) { - case SgiFilter_TargetList: - sgi_filter = kGicSgiFilter_UseTargetList; - break; - case SgiFilter_AllOtherCPUs: - sgi_filter = kGicSgiFilter_AllOtherCPUs; - break; - default: - sgi_filter = kGicSgiFilter_OnlyThisCPU; - break; - } - gic_send_sgi(irq, bitmask, sgi_filter); - - return true; -} - static uint32_t _hw_before_irq() { @@ -213,8 +179,14 @@ static int _is_interruptable(void) return !(val & DIS_INT); } +int _cur_cpu_id() +{ + return cpu_get_current(); +} + static struct XiziTrapDriver xizi_trap_driver = { .sys_irq_init = _sys_irq_init, + .cur_cpu_id = _cur_cpu_id, .cpu_irq_enable = _cpu_irq_enable, .cpu_irq_disable = _cpu_irq_disable, @@ -223,7 +195,6 @@ static struct XiziTrapDriver xizi_trap_driver = { .switch_hw_irqtbl = _switch_hw_irqtbl, .bind_irq_handler = _bind_irq_handler, - .send_sgi = _send_sgi, .is_interruptable = _is_interruptable, .hw_before_irq = _hw_before_irq, @@ -234,7 +205,7 @@ static struct XiziTrapDriver xizi_trap_driver = { struct XiziTrapDriver* hardkernel_intr_init(struct TraceTag* hardkernel_tag) { - xizi_trap_driver.sys_irq_init(); + xizi_trap_driver.sys_irq_init(0); xizi_trap_driver.cpu_irq_disable(); return &xizi_trap_driver; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/spinlock.c b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/spinlock.c deleted file mode 100644 index 5d143a444..000000000 --- a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/spinlock.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2020 AIIT XUOS Lab - * XiUOS is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ -/** - * @file spinlock.c - * @brief spinlock interfaces - * @version 3.0 - * @author AIIT XUOS Lab - * @date 2023.11.23 - */ -#include -#include - -#include "assert.h" -#include "spinlock.h" - -bool module_spinlock_use_intr_init(void) -{ - return true; -} - -#define SPINLOCK_STATE_UNLOCK 0xFF - -enum { - SPINLOCK_LOCK_NOWAIT = 0, - SPINLOCK_LOCK_WAITFOREVER = 0xFFFFFFFF, -}; - -void spinlock_init(struct spinlock* lock, char* name) -{ - lock->owner_cpu = SPINLOCK_STATE_UNLOCK; - strncpy(lock->name, name, 24); -} - -extern int _spinlock_lock(struct spinlock* lock, uint32_t timeout); -void spinlock_lock(struct spinlock* lock) -{ - if (lock->owner_cpu != SPINLOCK_STATE_UNLOCK) { - ERROR("spinlock %s lock double locked by core %d\n", lock->name, lock->owner_cpu); - panic(""); - } - assert(_spinlock_lock(lock, SPINLOCK_LOCK_WAITFOREVER) == 0); -} - -void _spinlock_unlock(struct spinlock* lock); -void spinlock_unlock(struct spinlock* lock) -{ - _spinlock_unlock(lock); -} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/trampoline.S b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/trampoline.S index 6ee8ba751..da7018964 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/trampoline.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/trampoline.S @@ -47,43 +47,17 @@ trap_return: ldmfd r13!, {r14} ldmfd r13!, {r2} msr spsr_cxsf, r2 - ldr r0, [r13], #4 - ldr r1, [r13], #4 - ldr r2, [r13], #4 - ldr r3, [r13], #4 - ldr r4, [r13], #4 - ldr r5, [r13], #4 - ldr r6, [r13], #4 - ldr r7, [r13], #4 - ldr r8, [r13], #4 - ldr r9, [r13], #4 - ldr r10, [r13], #4 - ldr r11, [r13], #4 - ldr r12, [r13], #4 - ldm r13!, {pc}^ + ldmfd r13!, {r0-r12, pc}^ // restore context and return user_trap_swi_enter: - # save trapframe to swi stack - sub sp, sp, #56 - str r14, [sp, #52] - str r12, [sp, #48] - str r11, [sp, #44] - str r10, [sp, #40] - str r9, [sp, #36] - str r8, [sp, #32] - str r7, [sp, #28] - str r6, [sp, #24] - str r5, [sp, #20] - str r4, [sp, #16] - str r3, [sp, #12] - str r2, [sp, #8] - str r1, [sp, #4] - str r0, [sp] + # save trapframe to swi stack + cpsid i + stmfd sp!, {r0-r12, r14} // save context + mrs r2, spsr // copy spsr to r2 + stmfd r13!, {r2} // save r2(spsr) to the stack - mrs r2, spsr - stmfd r13!, {r2} - stmfd r13!, {r14} - stmfd r13, {sp, lr}^ + stmfd r13!, {r14} // save r14 again to have one uniform trapframe + stmfd r13, {sp, lr}^ // save user mode sp and lr sub r13, r13, #8 # call syscall handler @@ -92,17 +66,13 @@ user_trap_swi_enter: b trap_return trap_irq_enter: - # save context in irq stack - sub r14, r14, #4 - sub sp, sp, #16 - str r14, [sp, #12] - str r2, [sp, #8] - str r1, [sp, #4] - str r0, [sp] - - mrs r1, spsr - mov r0, r13 // irq stack stop - add r13, r13, #16 // reset IRQ stack + # save it on the stack as r14 is banked + cpsid i + sub r14, r14, #4 // r14 (lr) contains the interrupted PC + stmfd r13!, {r0-r2, r14} // + mrs r1, spsr // save spsr_irq + mov r0, r13 // save stack stop (r13_irq) + add r13, r13, #16 // reset the IRQ stack # switch to the SVC mode mrs r2, cpsr @@ -111,134 +81,110 @@ trap_irq_enter: msr cpsr_cxsf, r2 # build the trap frame - ldr r2, [r0, #12] + ldr r2, [r0, #12] // read the r14_irq, then save it stmfd r13!, {r2} - sub r13, r13, #40 - str r12, [r13, #36] - str r11, [r13, #32] - str r10, [r13, #28] - str r9, [r13, #24] - str r8, [r13, #20] - str r7, [r13, #16] - str r6, [r13, #12] - str r5, [r13, #8] - str r4, [r13, #4] - str r3, [r13] - - ldmfd r0, {r3-r5} + stmfd r13!, {r3-r12} // r4-r12 are preserved (non-banked) + ldmfd r0, {r3-r5} // copy r0-r2 over from irq stack stmfd r13!, {r3-r5} - stmfd r13!, {r1} - stmfd r13!, {lr} - stmfd r13, {sp, lr}^ + stmfd r13!, {r1} // save spsr + stmfd r13!, {lr} // save lr_svc + + stmfd r13, {sp, lr}^ // save user mode sp and lr sub r13, r13, #8 mov r0, r13 // trapframe as parameters bl intr_irq_dispatch b trap_return -trap_reset_enter: - mov r14, #0 - sub r13, r13, #56 - str r14, [r13, #52] - str r12, [r13, #48] - str r11, [r13, #44] - str r10, [r13, #40] - str r9, [r13, #36] - str r8, [r13, #32] - str r7, [r13, #28] - str r6, [r13, #24] - str r5, [r13, #20] - str r4, [r13, #16] - str r3, [r13, #12] - str r2, [r13, #8] - str r1, [r13, #4] - str r0, [r13] - - mrs r2, spsr - stmfd r13!, {r2} - stmfd r13!, {r14} - stmfd r13, {sp, lr}^ - sub r13, r13, #8 - mov r0, r13 - bl _vector_jumper - trap_dabort: - sub r14, r14, #8 - sub r13, r13, #56 - str r14, [r13, #52] - str r12, [r13, #48] - str r11, [r13, #44] - str r10, [r13, #40] - str r9, [r13, #36] - str r8, [r13, #32] - str r7, [r13, #28] - str r6, [r13, #24] - str r5, [r13, #20] - str r4, [r13, #16] - str r3, [r13, #12] - str r2, [r13, #8] - str r1, [r13, #4] - str r0, [r13] + # save it on the stack as r14 is banked + cpsid i + sub r14, r14, #8 // r14 (lr) contains the interrupted PC + stmfd r13!, {r0-r2, r14} // + mrs r1, spsr // save spsr_irq + mov r0, r13 // save stack stop (r13_irq) + add r13, r13, #16 // reset the IRQ stack - mrs r2, spsr - stmfd r13!, {r2} - stmfd r13!, {r14} - stmfd r13, {sp, lr}^ + # switch to the SVC mode + mrs r2, cpsr + bic r2, r2, #ARM_CPSR_MODE_MASK + orr r2, r2, #ARM_MODE_SVC + msr cpsr_cxsf, r2 + + # build the trap frame + ldr r2, [r0, #12] // read the r14_irq, then save it + stmfd r13!, {r2} + stmfd r13!, {r3-r12} // r4-r12 are preserved (non-banked) + ldmfd r0, {r3-r5} // copy r0-r2 over from irq stack + stmfd r13!, {r3-r5} + stmfd r13!, {r1} // save spsr + stmfd r13!, {lr} // save lr_svc + + stmfd r13, {sp, lr}^ // save user mode sp and lr sub r13, r13, #8 - mov r0, r13 + + mov r0, r13 // trapframe as parameters bl dabort_handler trap_iabort: - sub r14, r14, #4 - sub r13, r13, #56 - str r14, [r13, #52] - str r12, [r13, #48] - str r11, [r13, #44] - str r10, [r13, #40] - str r9, [r13, #36] - str r8, [r13, #32] - str r7, [r13, #28] - str r6, [r13, #24] - str r5, [r13, #20] - str r4, [r13, #16] - str r3, [r13, #12] - str r2, [r13, #8] - str r1, [r13, #4] - str r0, [r13] +# save it on the stack as r14 is banked + cpsid i + sub r14, r14, #4 // r14 (lr) contains the interrupted PC + stmfd r13!, {r0-r2, r14} // + mrs r1, spsr // save spsr_irq + mov r0, r13 // save stack stop (r13_irq) + add r13, r13, #16 // reset the IRQ stack - mrs r2, spsr + # switch to the SVC mode + mrs r2, cpsr + bic r2, r2, #ARM_CPSR_MODE_MASK + orr r2, r2, #ARM_MODE_SVC + msr cpsr_cxsf, r2 + + # build the trap frame + ldr r2, [r0, #12] // read the r14_irq, then save it stmfd r13!, {r2} - stmfd r13!, {r14} - stmfd r13, {sp, lr}^ + stmfd r13!, {r3-r12} // r4-r12 are preserved (non-banked) + ldmfd r0, {r3-r5} // copy r0-r2 over from irq stack + stmfd r13!, {r3-r5} + stmfd r13!, {r1} // save spsr + stmfd r13!, {lr} // save lr_svc + + stmfd r13, {sp, lr}^ // save user mode sp and lr sub r13, r13, #8 - mov r0, r13 + + mov r0, r13 // trapframe as parameters bl iabort_handler trap_undefined_instruction: - sub r13, r13, #56 - str r14, [r13, #52] - str r12, [r13, #48] - str r11, [r13, #44] - str r10, [r13, #40] - str r9, [r13, #36] - str r8, [r13, #32] - str r7, [r13, #28] - str r6, [r13, #24] - str r5, [r13, #20] - str r4, [r13, #16] - str r3, [r13, #12] - str r2, [r13, #8] - str r1, [r13, #4] - str r0, [r13] + # save it on the stack as r14 is banked + cpsid i + sub r14, r14, #4 // r14 (lr) contains the interrupted PC + stmfd r13!, {r0-r2, r14} // + mrs r1, spsr // save spsr_irq + mov r0, r13 // save stack stop (r13_irq) + add r13, r13, #16 // reset the IRQ stack - mrs r2, spsr + # switch to the SVC mode + mrs r2, cpsr + bic r2, r2, #ARM_CPSR_MODE_MASK + orr r2, r2, #ARM_MODE_SVC + msr cpsr_cxsf, r2 + + # build the trap frame + ldr r2, [r0, #12] // read the r14_irq, then save it stmfd r13!, {r2} - stmfd r13!, {r14} - stmfd r13, {sp, lr}^ - sub r13, r13, #8 - mov r0, r13 - bl handle_undefined_instruction + stmfd r13!, {r3-r12} // r4-r12 are preserved (non-banked) + ldmfd r0, {r3-r5} // copy r0-r2 over from irq stack + stmfd r13!, {r3-r5} + stmfd r13!, {r1} // save spsr + stmfd r13!, {lr} // save lr_svc + stmfd r13, {sp, lr}^ // save user mode sp and lr + sub r13, r13, #8 + + mov r0, r13 // trapframe as parameters + bl handle_undefined_instruction init_stack: # set the stack for Other mode diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/zynq7000-zc702/trap_common.c b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/zynq7000-zc702/trap_common.c index 4d06f20f4..5cd8145a5 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/zynq7000-zc702/trap_common.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/zynq7000-zc702/trap_common.c @@ -42,12 +42,13 @@ extern void trap_iabort(void); extern void trap_dabort(void); extern void trap_irq_enter(void); extern void trap_undefined_instruction(void); +extern void handle_reserved(void); +extern void handle_fiq(void); static struct XiziTrapDriver xizi_trap_driver; void panic(char* s) { - xizi_trap_driver.cpu_irq_disable(); KPrintf("panic: %s\n", s); for (;;) ; @@ -55,7 +56,6 @@ void panic(char* s) /* stack for different mode*/ static char mode_stack_pages[NR_CPU][NR_MODE_STACKS][MODE_STACK_SIZE]; - extern uint32_t _vector_jumper; extern uint32_t _vector_start; extern uint32_t _vector_end; @@ -72,45 +72,34 @@ void init_cpu_mode_stacks(int cpu_id) } } -void handle_reserved(void) +static void _sys_irq_init(int cpu_id) { - // unimplemented trap handler - LOG("Unimplemented Reserved\n"); - panic(""); -} -void handle_fiq(void) -{ - LOG("Unimplemented FIQ\n"); - panic(""); -} + init_cpu_mode_stacks(cpu_id); + if (cpu_id == 0) { + /* load exception vectors */ + volatile uint32_t* vector_base = &_vector_start; -static void _sys_irq_init() -{ - /* load exception vectors */ - volatile uint32_t* vector_base = &_vector_start; + // Set Interrupt handler start address + vector_base[1] = (uint32_t)trap_undefined_instruction; // Undefined Instruction + vector_base[2] = (uint32_t)user_trap_swi_enter; // Software Interrupt + vector_base[3] = (uint32_t)trap_iabort; // Prefetch Abort + vector_base[4] = (uint32_t)trap_dabort; // Data Abort + vector_base[5] = (uint32_t)handle_reserved; // Reserved + vector_base[6] = (uint32_t)trap_irq_enter; // IRQ + vector_base[7] = (uint32_t)handle_fiq; // FIQ - // Set Interrupt handler start address - vector_base[1] = (uint32_t)trap_undefined_instruction; // Undefined Instruction - vector_base[2] = (uint32_t)user_trap_swi_enter; // Software Interrupt - vector_base[3] = (uint32_t)trap_iabort; // Prefetch Abort - vector_base[4] = (uint32_t)trap_dabort; // Data Abort - vector_base[5] = (uint32_t)handle_reserved; // Reserved - vector_base[6] = (uint32_t)trap_irq_enter; // IRQ - vector_base[7] = (uint32_t)handle_fiq; // FIQ - - init_cpu_mode_stacks(0); - - /* active hardware irq responser */ - XScuGic_Config* gic_config = XScuGic_LookupConfig(XPAR_PS7_SCUGIC_0_DEVICE_ID); - if (NULL == gic_config) { - ERROR("Error while looking up gic config\n"); - return; - } - int gic_init_status = XScuGic_CfgInitialize(&IntcInstance, gic_config, gic_config->CpuBaseAddress); - if (gic_init_status != XST_SUCCESS) { - ERROR("Error initializing gic\n"); - return; + /* active hardware irq responser */ + XScuGic_Config* gic_config = XScuGic_LookupConfig(XPAR_PS7_SCUGIC_0_DEVICE_ID); + if (NULL == gic_config) { + ERROR("Error while looking up gic config\n"); + return; + } + int gic_init_status = XScuGic_CfgInitialize(&IntcInstance, gic_config, gic_config->CpuBaseAddress); + if (gic_init_status != XST_SUCCESS) { + ERROR("Error initializing gic\n"); + return; + } } xizi_trap_driver.switch_hw_irqtbl((uint32_t*)&_vector_jumper); @@ -162,24 +151,6 @@ static void _bind_irq_handler(int irq, irq_handler_t handler) xizi_trap_driver.sw_irqtbl[irq].handler = handler; } -static bool _send_sgi(uint32_t irq, uint32_t bitmask, enum SgiFilterType type) -{ - if (bitmask > (1 << NR_CPU) - 1) { - return false; - } - - int cpu_id = 0; - while (bitmask != 0) { - if ((bitmask & 0x1) != 0) { - XScuGic_SoftwareIntr(&IntcInstance, irq, cpu_id); - } - cpu_id++; - bitmask >>= 1; - } - - return true; -} - static uint32_t _hw_before_irq() { @@ -215,8 +186,14 @@ static int _is_interruptable(void) return !(val & DIS_INT); } +int _cur_cpu_id() +{ + return cpu_get_current(); +} + static struct XiziTrapDriver xizi_trap_driver = { .sys_irq_init = _sys_irq_init, + .cur_cpu_id = _cur_cpu_id, .cpu_irq_enable = _cpu_irq_enable, .cpu_irq_disable = _cpu_irq_disable, @@ -225,7 +202,6 @@ static struct XiziTrapDriver xizi_trap_driver = { .switch_hw_irqtbl = _switch_hw_irqtbl, .bind_irq_handler = _bind_irq_handler, - .send_sgi = _send_sgi, .is_interruptable = _is_interruptable, .hw_before_irq = _hw_before_irq, @@ -236,7 +212,7 @@ static struct XiziTrapDriver xizi_trap_driver = { struct XiziTrapDriver* hardkernel_intr_init(struct TraceTag* hardkernel_tag) { - xizi_trap_driver.sys_irq_init(); - xizi_trap_driver.cpu_irq_enable(); + xizi_trap_driver.sys_irq_init(0); + xizi_trap_driver.cpu_irq_disable(); return &xizi_trap_driver; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/spinlock.c b/Ubiquitous/XiZi_AIoT/hardkernel/intr/spinlock.c new file mode 100644 index 000000000..9e1014316 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/intr/spinlock.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2020 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +/** + * @file spinlock.c + * @brief spinlock interfaces + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2023.11.23 + */ +#include +#include + +#include "spinlock.h" +#include "trap_common.h" + +#include "assert.h" +#include "list.h" +#include "multicores.h" + +struct lock_node { + struct double_list_node node; + int cpu_id; +}; + +static struct double_list_node lock_request_guard; +static struct lock_node core_lock_request[NR_CPU]; +static struct spinlock request_lock; +bool module_spinlock_use_intr_init(void) +{ + for (int i = 0; i < NR_CPU; i++) { + core_lock_request[i].cpu_id = i; + doubleListNodeInit(&core_lock_request[i].node); + } + doubleListNodeInit(&lock_request_guard); + spinlock_init(&request_lock, "requestlock"); + return true; +} + +#define SPINLOCK_STATE_UNLOCK 0xFF + +enum { + SPINLOCK_LOCK_NOWAIT = 0, + SPINLOCK_LOCK_WAITFOREVER = 0xFFFFFFFF, +}; + +void spinlock_init(struct spinlock* lock, char* name) +{ + lock->owner_cpu = SPINLOCK_STATE_UNLOCK; + strncpy(lock->name, name, 24); +} + +extern int _spinlock_lock(struct spinlock* lock, uint32_t timeout); +void _spinlock_unlock(struct spinlock* lock); + +void spinlock_lock(struct spinlock* lock) +{ + int cur_cpu_id = cur_cpuid(); + if (lock->owner_cpu != SPINLOCK_STATE_UNLOCK && lock->owner_cpu == cur_cpu_id) { + ERROR("spinlock %s lock double locked by core %d\n", lock->name, lock->owner_cpu); + panic(""); + } + + struct double_list_node* p_lock_node = &core_lock_request[cur_cpu_id].node; + _spinlock_lock(&request_lock, SPINLOCK_LOCK_WAITFOREVER); + doubleListAddOnBack(p_lock_node, &lock_request_guard); + _spinlock_unlock(&request_lock); + + while (lock_request_guard.next != p_lock_node) + ; + + _spinlock_lock(lock, SPINLOCK_LOCK_WAITFOREVER); +} + +void spinlock_unlock(struct spinlock* lock) +{ + struct double_list_node* p_lock_node = &core_lock_request[cur_cpuid()].node; + assert(lock_request_guard.next == p_lock_node); + _spinlock_lock(&request_lock, SPINLOCK_LOCK_WAITFOREVER); + _double_list_del(p_lock_node->prev, p_lock_node->next); + _spinlock_unlock(&request_lock); + + _spinlock_unlock(lock); +} + +bool spinlock_try_lock(struct spinlock* lock) +{ + int cur_cpu_id = cur_cpuid(); + if (lock->owner_cpu != SPINLOCK_STATE_UNLOCK && lock->owner_cpu == cur_cpu_id) { + ERROR("spinlock %s lock double locked by core %d\n", lock->name, lock->owner_cpu); + panic(""); + } + + struct double_list_node* p_lock_node = &core_lock_request[cur_cpu_id].node; + _spinlock_lock(&request_lock, SPINLOCK_LOCK_WAITFOREVER); + doubleListAddOnBack(p_lock_node, &lock_request_guard); + if (lock_request_guard.next != p_lock_node) { + _double_list_del(p_lock_node->prev, p_lock_node->next); + _spinlock_unlock(&request_lock); + return false; + } + _spinlock_unlock(&request_lock); + _spinlock_lock(lock, SPINLOCK_LOCK_WAITFOREVER); + + return true; +} + +bool is_spinlock_hold_by_current_cpu(struct spinlock* lock) +{ + return lock->owner_cpu; +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/spinlock.h b/Ubiquitous/XiZi_AIoT/hardkernel/intr/spinlock.h index 7454f9eec..d082cc67f 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/intr/spinlock.h +++ b/Ubiquitous/XiZi_AIoT/hardkernel/intr/spinlock.h @@ -34,11 +34,13 @@ Modification: #define STACK_DEPTH 32 struct spinlock { // Mutex. - uint32_t owner_cpu; // 1 for locked, 0 for unlocked + volatile uint32_t owner_cpu; // 1 for locked, 0 for unlocked char name[28]; // The call stack (an array of program counters) } __attribute__((aligned(32))); bool module_spinlock_use_intr_init(void); void spinlock_init(struct spinlock* lock, char* name); void spinlock_lock(struct spinlock* lock); -void spinlock_unlock(struct spinlock* lock); \ No newline at end of file +void spinlock_unlock(struct spinlock* lock); +bool spinlock_try_lock(struct spinlock* lock); +bool is_spinlock_hold_by_current_cpu(struct spinlock* lock); \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/trap_common.h b/Ubiquitous/XiZi_AIoT/hardkernel/intr/trap_common.h index 327f856b1..c86c3cc47 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/intr/trap_common.h +++ b/Ubiquitous/XiZi_AIoT/hardkernel/intr/trap_common.h @@ -59,15 +59,15 @@ struct XiziTrapDriver { /* current irq number happening in cpu*/ uint32_t curr_int[NR_CPU]; - void (*sys_irq_init)(); + void (*sys_irq_init)(int); + int (*cur_cpu_id)(); void (*cpu_irq_enable)(); void (*cpu_irq_disable)(); void (*single_irq_enable)(int irq, int cpu, int prio); void (*single_irq_disable)(int irq, int cpu); - uint32_t* (*switch_hw_irqtbl)(uint32_t*); - bool (*send_sgi)(uint32_t, uint32_t, enum SgiFilterType); + uint32_t* (*switch_hw_irqtbl)(uint32_t*); void (*bind_irq_handler)(int, irq_handler_t); /* check if no if interruptable */ @@ -100,4 +100,7 @@ void panic(char* s); bool intr_distributer_init(struct IrqDispatcherRightGroup*); void intr_irq_dispatch(struct trapframe* tf); bool swi_distributer_init(struct SwiDispatcherRightGroup*); -void software_irq_dispatch(struct trapframe* tf); \ No newline at end of file +void software_irq_dispatch(struct trapframe* tf); + +void dabort_reason(struct trapframe* r); +void iabort_reason(struct trapframe* r); \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/bootmmu.c b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/bootmmu.c index 086543471..00f484725 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/bootmmu.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/bootmmu.c @@ -89,11 +89,16 @@ static void load_boot_pgdir() } extern void main(void); +static bool _bss_inited = false; void bootmain() { build_boot_pgdir(); load_boot_pgdir(); __asm__ __volatile__("add sp, sp, %0" ::"r"(KERN_MEM_BASE - PHY_MEM_BASE)); - memset(&kernel_data_begin, 0x00, (uint32_t)kernel_data_end - (uint32_t)kernel_data_begin); + if (!_bss_inited) { + memset(&kernel_data_begin, 0x00, (uint32_t)kernel_data_end - (uint32_t)kernel_data_begin); + _bss_inited = true; + } + main(); } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/imx6q-sabrelite/memlayout.h b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/imx6q-sabrelite/memlayout.h index eef60ffe4..26957c7bb 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/imx6q-sabrelite/memlayout.h +++ b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/imx6q-sabrelite/memlayout.h @@ -56,10 +56,11 @@ Modification: #define MAX_NR_FREE_PAGES ((PHY_MEM_STOP - PHY_MEM_BASE) >> LEVEL4_PTE_SHIFT) /* User memory layout */ -#define USER_STACK_SIZE PAGE_SIZE +#define USER_STACK_SIZE MODE_STACK_SIZE #define USER_MEM_BASE (0x00000000) #define USER_MEM_TOP DEV_VRTMEM_BASE #define USER_IPC_SPACE_BASE (0x70000000) +#define USER_IPC_USE_ALLOCATOR_WATERMARK (0x70010000) #define USER_IPC_SPACE_TOP (USER_MEM_TOP - USER_STACK_SIZE) /* Deivce memory layout */ diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/mmu.c b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/mmu.c index 7bc5254c2..50d783b90 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/mmu.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/mmu.c @@ -82,6 +82,11 @@ static void tlb_flush_range(uintptr_t vstart, int len) } } +static void tlb_flush_all() +{ + CLEARTLB(0); +} + static struct MmuCommonDone mmu_common_done = { .MmuDevPteAttr = GetDevPteAttr, .MmuPdeAttr = GetPdeAttr, @@ -91,6 +96,7 @@ static struct MmuCommonDone mmu_common_done = { .LoadPgdirCrit = load_pgdir_critical, .LoadPgdir = load_pgdir, + .TlbFlushAll = tlb_flush_all, .TlbFlush = tlb_flush_range, }; diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/pagetable_attr.c b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/pagetable_attr.c index 455b1d759..bff47d1b3 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/pagetable_attr.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/pagetable_attr.c @@ -30,20 +30,6 @@ Modification: #include "mmu.h" #include "mmu_common.h" -void GetDevPteAttr(uintptr_t* attr) -{ - static char init = 0; - static PageTblEntry dev_pte_attr; - if (init == 0) { - init = 1; - - dev_pte_attr.entry = 0; - dev_pte_attr.desc_type = PAGE_4K; - dev_pte_attr.AP1_0 = AccessPermission_KernelOnly; - } - *attr = dev_pte_attr.entry; -} - void GetUsrPteAttr(uintptr_t* attr) { static char init = 0; @@ -55,6 +41,7 @@ void GetUsrPteAttr(uintptr_t* attr) usr_pte_attr.desc_type = PAGE_4K; usr_pte_attr.B = 1; usr_pte_attr.C = 1; + usr_pte_attr.S = 1; usr_pte_attr.AP1_0 = AccessPermission_KernelUser; } *attr = usr_pte_attr.entry; @@ -74,6 +61,20 @@ void GetUsrDevPteAttr(uintptr_t* attr) *attr = usr_pte_attr.entry; } +void GetDevPteAttr(uintptr_t* attr) +{ + static char init = 0; + static PageTblEntry dev_pte_attr; + if (init == 0) { + init = 1; + + dev_pte_attr.entry = 0; + dev_pte_attr.desc_type = PAGE_4K; + dev_pte_attr.AP1_0 = AccessPermission_KernelOnly; + } + *attr = dev_pte_attr.entry; +} + void GetKernPteAttr(uintptr_t* attr) { static char init = 0; @@ -85,6 +86,7 @@ void GetKernPteAttr(uintptr_t* attr) kern_pte_attr.desc_type = PAGE_4K; kern_pte_attr.B = 1; kern_pte_attr.C = 1; + kern_pte_attr.S = 1; kern_pte_attr.AP1_0 = AccessPermission_KernelOnly; } *attr = kern_pte_attr.entry; diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/zynq7000-zc702/memlayout.h b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/zynq7000-zc702/memlayout.h index f68861da0..cf480c399 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/zynq7000-zc702/memlayout.h +++ b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/zynq7000-zc702/memlayout.h @@ -53,13 +53,14 @@ Modification: #define NUM_TOPLEVEL_PDE NUM_LEVEL3_PDE #define PAGE_SIZE LEVEL4_PTE_SIZE -#define MAX_NR_FREE_PAGES ((PHY_MEM_STOP - PHY_MEM_BASE) >> LEVEL4_PTE_SHIFT) +#define MAX_NR_FREE_PAGES ((PHY_USER_FREEMEM_BASE - PHY_MEM_BASE) >> LEVEL4_PTE_SHIFT) /* User memory layout */ -#define USER_STACK_SIZE PAGE_SIZE +#define USER_STACK_SIZE MODE_STACK_SIZE #define USER_MEM_BASE (0x00000000) #define USER_MEM_TOP DEV_VRTMEM_BASE #define USER_IPC_SPACE_BASE (0x70000000) +#define USER_IPC_USE_ALLOCATOR_WATERMARK (0x70010000) #define USER_IPC_SPACE_TOP (USER_MEM_TOP - USER_STACK_SIZE) /* Deivce memory layout */ diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/mmu_common.h b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/mmu_common.h index 99aa7d38a..b979f80e8 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/mmu_common.h +++ b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/mmu_common.h @@ -29,6 +29,7 @@ struct MmuCommonDone void (*LoadPgdirCrit)(uintptr_t pgdir_paddr, struct TraceTag*); void (*LoadPgdir)(uintptr_t pgdir_paddr); + void (*TlbFlushAll)(); void (*TlbFlush)(uintptr_t vaddr, int len); }; diff --git a/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c index 32dcbf651..c0a259dee 100644 --- a/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c +++ b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c @@ -60,8 +60,6 @@ static inline int namecmp(const char* s, const char* t) static struct TraceMeta* alloc_trace_meta() { int index = -1; - - spinlock_lock(&sys_tracer.trace_meta_bitmap_lock); for (uint32_t idx = 0; idx < BITS_TRACEMETA_BITMAP; idx++) { if (sys_tracer.trace_meta_bit_map[idx] == 0xFFFFFFFF) { continue; @@ -74,7 +72,6 @@ static struct TraceMeta* alloc_trace_meta() break; } } - spinlock_unlock(&sys_tracer.trace_meta_bitmap_lock); if (index == -1) { panic("Tracer no enough TracerMeta."); @@ -87,15 +84,12 @@ static struct TraceMeta* alloc_trace_meta() static bool dealloc_trace_meta(struct TraceMeta* meta) { int index = meta->index; - - spinlock_lock(&sys_tracer.trace_meta_bitmap_lock); // clear bitmap uint32_t outer_index = index / 32; uint32_t inner_index = index % 32; sys_tracer.trace_meta_bit_map[outer_index] &= (uint32_t)(~(1 << inner_index)); // clear meta sys_tracer.trace_meta_poll[index].type = TRACER_INVALID; - spinlock_unlock(&sys_tracer.trace_meta_bitmap_lock); if (index == -1) { panic("Tracer no enough TracerMeta."); @@ -337,7 +331,7 @@ static struct TraceMeta* tracer_find_meta(struct TraceMeta* const p_owner, char* return p_owner_inside; } if ((vnp = tracer_find_meta_onestep(p_owner_inside, name, NULL)) == 0) { - ERROR("Not such object: %s\n", path); + DEBUG("Not such object: %s\n", path); return NULL; } p_owner_inside = vnp; @@ -527,7 +521,8 @@ bool CreateResourceTag(struct TraceTag* new_tag, struct TraceTag* owner, char* n if (!tracer_create_trace(new_tag, owner, name, type)) { return false; } - return tracer_write_trace(new_tag, (char*)&p_resource, 0, sizeof(void*)) == sizeof(void*); + bool ret = tracer_write_trace(new_tag, (char*)&p_resource, 0, sizeof(void*)) == sizeof(void*); + return ret; } bool DeleteResource(struct TraceTag* target, struct TraceTag* owner) diff --git a/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer_mem_chunk.c b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer_mem_chunk.c index 3dc554e69..44909c21e 100644 --- a/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer_mem_chunk.c +++ b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer_mem_chunk.c @@ -61,7 +61,6 @@ static void tracer_mem_chunk_sync(struct tracer_mem_chunk* b) void mem_chunk_synchronizer_init(uintptr_t mem_chunk_base, uint32_t mem_chunk_size, uint32_t nr_mem_chunks) { - spinlock_init(&tracer_mem_chunk_syner.lock, "tracer_mem_chunk_syner"); tracer_mem_chunk_syner.mem_chunk_base = mem_chunk_base; tracer_mem_chunk_syner.mem_chunk_size = mem_chunk_size; tracer_mem_chunk_syner.nr_mem_chunks = nr_mem_chunks; @@ -76,8 +75,6 @@ void mem_chunk_synchronizer_init(uintptr_t mem_chunk_base, uint32_t mem_chunk_si static struct tracer_mem_chunk* tracer_get_mem_chunk_cache(uint32_t chunk_id) { - spinlock_lock(&tracer_mem_chunk_syner.lock); - // cached mem_chunk cache struct tracer_mem_chunk* b; DOUBLE_LIST_FOR_EACH_ENTRY(b, &tracer_mem_chunk_syner.head, list_node) @@ -85,11 +82,8 @@ static struct tracer_mem_chunk* tracer_get_mem_chunk_cache(uint32_t chunk_id) if (b->chunk_id == chunk_id) { if (!(b->flag & TRACER_MEM_CHUNK_BUSY)) { b->flag |= TRACER_MEM_CHUNK_BUSY; - spinlock_unlock(&tracer_mem_chunk_syner.lock); return b; } - ERROR("tracer mem_chunk syner is locked\n"); - panic(""); } } @@ -99,7 +93,6 @@ static struct tracer_mem_chunk* tracer_get_mem_chunk_cache(uint32_t chunk_id) if ((b->flag & TRACER_MEM_CHUNK_BUSY) == 0) { b->chunk_id = chunk_id; b->flag = TRACER_MEM_CHUNK_BUSY; - spinlock_unlock(&tracer_mem_chunk_syner.lock); return b; } } @@ -130,17 +123,13 @@ void tracer_mem_chunk_write(struct tracer_mem_chunk* b) void tracer_mem_chunk_release(struct tracer_mem_chunk* b) { if ((b->flag & TRACER_MEM_CHUNK_BUSY) == 0) { - panic("tracer mem_chunk release but it's busy occupied"); + panic("tracer mem_chunk release but it's not busy occupied"); } // move mem_chunk that just used to the head of cache list - spinlock_lock(&tracer_mem_chunk_syner.lock); - doubleListDel(&b->list_node); doubleListAddOnHead(&b->list_node, &tracer_mem_chunk_syner.head); b->flag &= ~TRACER_MEM_CHUNK_BUSY; - - spinlock_unlock(&tracer_mem_chunk_syner.lock); } static void tracer_mem_chunk_zero(uint32_t chunk_id) @@ -157,7 +146,6 @@ static void tracer_mem_chunk_zero(uint32_t chunk_id) static uint32_t find_first_free_mem_chunk() { /// @todo another mem_chunk - spinlock_lock(&sys_tracer.mem_chunk_bitmap_lock); for (uint32_t idx = 0; idx < BITS_MEM_CHUNK_BITMAP; idx++) { if (sys_tracer.mem_chunks_bit_map[idx] == 0xFFFFFFFF) { continue; @@ -165,11 +153,9 @@ static uint32_t find_first_free_mem_chunk() uint32_t position = __builtin_ffs(~sys_tracer.mem_chunks_bit_map[idx]); if (position != 32) { sys_tracer.mem_chunks_bit_map[idx] |= (1 << (position - 1)); - spinlock_unlock(&sys_tracer.mem_chunk_bitmap_lock); return idx * 32 + position; } } - spinlock_unlock(&sys_tracer.mem_chunk_bitmap_lock); panic("Tracer no enough space."); return 0; } @@ -184,11 +170,9 @@ uint32_t tracer_mem_chunk_alloc() void tracer_mem_chunk_free(uint32_t chunk_id) { assert(chunk_id >= 0 && chunk_id < NR_TRACER_MEM_CHUNKS); - spinlock_lock(&sys_tracer.mem_chunk_bitmap_lock); uint32_t idx = chunk_id % 32; uint32_t inner_mem_chunk_bit = chunk_id / 32; // assert mem_chunk is allocated assert((sys_tracer.mem_chunks_bit_map[idx] & (1 << inner_mem_chunk_bit)) != 0); sys_tracer.mem_chunks_bit_map[idx] &= (uint32_t)(~(1 << inner_mem_chunk_bit)); - spinlock_unlock(&sys_tracer.mem_chunk_bitmap_lock); } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/app/Makefile b/Ubiquitous/XiZi_AIoT/services/app/Makefile index fd0fb506b..ebf29d76e 100644 --- a/Ubiquitous/XiZi_AIoT/services/app/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/app/Makefile @@ -23,7 +23,11 @@ INC_DIR = -I$(KERNEL_ROOT)/services/shell/letter-shell \ -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ -I$(KERNEL_ROOT)/services/app -all: init test_fs simple_client simple_server shell fs_server test_priority readme.txt | bin +ifeq ($(BOARD), imx6q-sabrelite) +all: init test_fs simple_client simple_server shell fs_server test_priority test_irq_hdlr test_irq_send readme.txt | bin +else +all: init test_fs simple_client simple_server shell fs_server test_priority test_irq_hdlr readme.txt | bin +endif ../tools/mkfs/mkfs ./fs.img $^ @mv $(filter-out readme.txt, $^) bin @mv *.o bin @@ -32,31 +36,41 @@ all: init test_fs simple_client simple_server shell fs_server test_priority read bin: @mkdir -p bin -shell: shell_port.o libserial.o shell_cmd_list.o shell.o shell_ext.o libfs_to_client.o libipc.o session.o usyscall.o +ifeq ($(BOARD), imx6q-sabrelite) +test_irq_send: test_irq_sender.o usyscall.o libserial.o + @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} + @${objdump} -S $@ > $@.asm +endif + +test_irq_hdlr: test_irq_handler.o libserial.o libipc.o session.o usyscall.o libmem.o + @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} + @${objdump} -S $@ > $@.asm + +shell: shell_port.o libserial.o shell_cmd_list.o shell.o shell_ext.o libfs_to_client.o libipc.o session.o usyscall.o libmem.o @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} @${objdump} -S $@ > $@.asm -init: init.o libfs_to_client.o libipc.o session.o libserial.o usyscall.o +init: init.o libfs_to_client.o libipc.o session.o libserial.o usyscall.o libmem.o @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} @${objdump} -S $@ > $@.asm -test_fs: test_fs.o libfs_to_client.o libipc.o session.o libserial.o usyscall.o +test_fs: test_fs.o libfs_to_client.o libipc.o session.o libserial.o usyscall.o libmem.o @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} @${objdump} -S $@ > $@.asm -simple_client: simple_client.o libserial.o libipc.o session.o simple_service.o libfs_to_client.o usyscall.o +simple_client: simple_client.o libserial.o libipc.o session.o simple_service.o libfs_to_client.o usyscall.o libmem.o @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} @${objdump} -S $@ > $@.asm -simple_server: simple_server.o libserial.o libipc.o session.o simple_service.o usyscall.o +simple_server: simple_server.o libserial.o libipc.o session.o simple_service.o usyscall.o libmem.o @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} @${objdump} -S $@ > $@.asm -fs_server: fs_server.o libfs_to_client.o fs.o libserial.o libipc.o session.o block_io.o usyscall.o +fs_server: fs_server.o libfs_to_client.o fs.o libserial.o libipc.o session.o block_io.o usyscall.o libmem.o @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} @${objdump} -S $@ > $@.asm -test_priority: test_priority.o libserial.o usyscall.o +test_priority: test_priority.o libserial.o usyscall.o libmem.o @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} @${objdump} -S $@ > $@.asm diff --git a/Ubiquitous/XiZi_AIoT/services/app/init.c b/Ubiquitous/XiZi_AIoT/services/app/init.c index f9622e996..3c3fc1446 100755 --- a/Ubiquitous/XiZi_AIoT/services/app/init.c +++ b/Ubiquitous/XiZi_AIoT/services/app/init.c @@ -19,7 +19,10 @@ int main(int argc, char* argv[]) { struct Session session; - connect_session(&session, "MemFS", 8092); + printf("init: connecting MemFS\n"); + while (connect_session(&session, "MemFS", 8092) < 0) + ; + printf("init: connect MemFS success\n"); int fd; char* shell_task_param[2] = { "/shell", 0 }; @@ -28,7 +31,7 @@ int main(int argc, char* argv[]) exit(); } - if (spawn(&session, fd, read, shell_task_param[0], shell_task_param) < 0) { + if (spawn(&session, fd, read, fsize, shell_task_param[0], shell_task_param) < 0) { printf("Syscall Spawn shell failed\n"); } diff --git a/Ubiquitous/XiZi_AIoT/services/app/shell_port.c b/Ubiquitous/XiZi_AIoT/services/app/shell_port.c index 52284c9f4..ce2453519 100644 --- a/Ubiquitous/XiZi_AIoT/services/app/shell_port.c +++ b/Ubiquitous/XiZi_AIoT/services/app/shell_port.c @@ -35,7 +35,7 @@ signed short userShellRead(char* data, unsigned short len) while (length--) { cur_read = getc(); if (cur_read == 0xff) { - yield(); + yield(SYS_TASK_YIELD_NO_REASON); } // *data++ = getc(); *data++ = cur_read; @@ -50,7 +50,8 @@ int main(void) shellInit(&shell, shellBuffer, 512); - connect_session(&session_fs, "MemFS", 8092); + while (connect_session(&session_fs, "MemFS", 8092) < 0) + ; if (!session_fs.buf) { printf("session connect faield\n"); return -1; diff --git a/Ubiquitous/XiZi_AIoT/services/app/simple_client.c b/Ubiquitous/XiZi_AIoT/services/app/simple_client.c index d3f335146..232916067 100755 --- a/Ubiquitous/XiZi_AIoT/services/app/simple_client.c +++ b/Ubiquitous/XiZi_AIoT/services/app/simple_client.c @@ -113,10 +113,10 @@ int main(int argc, char** argv) itoa(id - 1, id_buf, 10); char* shell_task_param[3] = { "/simple_client", id_buf, 0 }; if ((fd = open(&session, shell_task_param[0])) >= 0) { - if (spawn(&session, fd, read, shell_task_param[0], shell_task_param) < 0) { + if (spawn(&session, fd, read, fsize, shell_task_param[0], shell_task_param) < 0) { printf("Syscall Spawn simple_client failed\n"); } - if (spawn(&session, fd, read, shell_task_param[0], shell_task_param) < 0) { + if (spawn(&session, fd, read, fsize, shell_task_param[0], shell_task_param) < 0) { printf("Syscall Spawn simple_client failed\n"); } close(&session, fd); diff --git a/Ubiquitous/XiZi_AIoT/services/app/test_irq_handler.c b/Ubiquitous/XiZi_AIoT/services/app/test_irq_handler.c new file mode 100644 index 000000000..28e8fdd04 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/app/test_irq_handler.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +#include "libipc.h" +#include "libserial.h" +#include "usyscall.h" + +IPC_SERVICES(IpcSwIntrHandler, Ipc_intr_3); + +enum { + SW_INTERRUPT_3 = 3, +}; + +void sgi_test_handler(void) +{ + printf("TEST_SW_HDLR: In %s()\n", __func__); +} + +int IPC_DO_SERVE_FUNC(Ipc_intr_3)(void* useless) +{ + sgi_test_handler(); + return 0; +} + +IPC_SERVER_INTERFACE(Ipc_intr_3, 1); +IPC_SERVER_REGISTER_INTERFACES(IpcSwIntrHandler, 1, Ipc_intr_3); +int main() +{ + if (register_irq(SW_INTERRUPT_3, Ipc_intr_3) == -1) { + printf("TEST_SW_HDLR: bind failed"); + exit(); + } + ipc_server_loop(&IpcSwIntrHandler); + + exit(); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile index 71ddf042c..96a8dc345 100644 --- a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile @@ -13,12 +13,12 @@ cflags = -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=so c_useropts = -O0 INC_DIR = -I$(KERNEL_ROOT)/services/fs/libfs \ - -I$(KERNEL_ROOT)/services/fs/fs_server/include \ -I$(KERNEL_ROOT)/services/lib/ipc \ + -I$(KERNEL_ROOT)/services/lib/memory \ -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ -I$(KERNEL_ROOT)/services/app -board: libserial.o usyscall.o +board: libserial.o usyscall.o test_irq_sender.o @mv $^ ../../app %.o: %.c diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/test_irq_sender.c b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/test_irq_sender.c new file mode 100644 index 000000000..21e4a2fef --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/test_irq_sender.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "libserial.h" +#include "usyscall.h" + +enum { + SW_INTERRUPT_3 = 3, +}; + +enum { + ARM_PERIPHERAL_BASE = 0x00A00000, + MX6Q_GICD_BASE_OFFSET = 0x1000, + MX6Q_GICC_BASE_OFFSET = 0x100, + + ARM_PERIPHERAL_VIRT_BASE = 0x50000000, +}; + +enum _gicd_sgi_filter { + //! Forward the interrupt to the CPU interfaces specified in the @a target_list parameter. + kGicSgiFilter_UseTargetList = 0, + + //! Forward the interrupt to all CPU interfaces except that of the processor that requested + //! the interrupt. + kGicSgiFilter_AllOtherCPUs = 1, + + //! Forward the interrupt only to the CPU interface of the processor that requested the + //! interrupt. + kGicSgiFilter_OnlyThisCPU = 2 +}; + +struct _gicd_registers { + uint32_t CTLR; //!< Distributor Control Register. + uint32_t TYPER; //!< Interrupt Controller Type Register. + uint32_t IIDR; //!< Distributor Implementer Identification Register. + uint32_t _reserved0[29]; + uint32_t IGROUPRn[8]; //!< Interrupt Group Registers. + uint32_t _reserved1[24]; + uint32_t ISENABLERn[32]; //!< Interrupt Set-Enable Registers. + uint32_t ICENABLERn[32]; //!< Interrupt Clear-Enable Registers. + uint32_t ISPENDRn[32]; //!< Interrupt Set-Pending Registers. + uint32_t ICPENDRn[32]; //!< Interrupt Clear-Pending Registers. + uint32_t ICDABRn[32]; //!< Active Bit Registers. + uint32_t _reserved2[32]; + uint8_t IPRIORITYRn[255 * sizeof(uint32_t)]; //!< Interrupt Priority Registers. (Byte accessible) + uint32_t _reserved3; + uint8_t ITARGETSRn[255 * sizeof(uint32_t)]; //!< Interrupt Processor Targets Registers. (Byte accessible) + uint32_t _reserved4; + uint32_t ICFGRn[64]; //!< Interrupt Configuration Registers. + uint32_t _reserved5[128]; + uint32_t SGIR; //!< Software Generated Interrupt Register +}; +typedef volatile struct _gicd_registers gicd_t; + +enum _gicd_sgir_fields { + kBP_GICD_SGIR_TargetListFilter = 24, + kBM_GICD_SGIR_TargetListFilter = (0x3 << kBP_GICD_SGIR_TargetListFilter), + + kBP_GICD_SGIR_CPUTargetList = 16, + kBM_GICD_SGIR_CPUTargetList = (0xff << kBP_GICD_SGIR_CPUTargetList), + + kBP_GICD_SGIR_NSATT = 15, + kBM_GICD_SGIR_NSATT = (1 << kBP_GICD_SGIR_NSATT), + + kBP_GICD_SGIR_SGIINTID = 0, + kBM_GICD_SGIR_SGIINTID = 0xf +}; + +void gic_send_sgi(uint32_t irqID, uint32_t target_list, uint32_t filter_list) +{ + gicd_t* gicd = (gicd_t*)(ARM_PERIPHERAL_VIRT_BASE + MX6Q_GICD_BASE_OFFSET); + gicd->SGIR = (filter_list << kBP_GICD_SGIR_TargetListFilter) // + | (target_list << kBP_GICD_SGIR_CPUTargetList) // + | (irqID & 0xf); +} + +int main() +{ + static char prog_name[] = "TEST_IRQ_SEND"; + printf("%s: Mapping GIC\n", prog_name); + mmap(ARM_PERIPHERAL_VIRT_BASE, ARM_PERIPHERAL_BASE, 0x2000, true); + + int send_time = 1000; + printf("%s: Sending soft interrupt for %d times\n", prog_name, send_time); + for (int i = 0; i < send_time; i++) { + gic_send_sgi(SW_INTERRUPT_3, 0xF, kGicSgiFilter_UseTargetList); + printf("%s: Soft interrupt send 1 time\n", prog_name); + } + printf("%s: Soft interrupt send done\n", prog_name); + exit(); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/usyscall.c b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/usyscall.c index c03893a43..c1b49a489 100644 --- a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/usyscall.c +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/usyscall.c @@ -10,6 +10,7 @@ * See the Mulan PSL v2 for more details. */ #include "usyscall.h" +#include "libmem.h" static int syscall(int sys_num, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4) @@ -33,14 +34,18 @@ syscall(int sys_num, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4) return ret; } -int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv) +int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, ipc_fsize_fn ipc_fsize, char* name, char** argv) { - struct KernReadTool read_tool = { - .session = session, - .fd = fd, - .ipc_read = ipc_read, - }; - return syscall(SYSCALL_SPAWN, (intptr_t)&read_tool, (intptr_t)name, (intptr_t)argv, 0); + int file_size = ipc_fsize(session, fd); + void* img = malloc(file_size); + int read_len = 0, cur_read_len = 0; + while (read_len < file_size) { + cur_read_len = file_size - read_len < 4096 ? file_size - read_len : 4096; + read_len += ipc_read(session, fd, img + read_len, read_len, cur_read_len); + } + int ret = syscall(SYSCALL_SPAWN, (intptr_t)img, (intptr_t)name, (intptr_t)argv, 0); + free(img); + return ret; } int exit() @@ -48,9 +53,14 @@ int exit() return syscall(SYSCALL_EXIT, 0, 0, 0, 0); } -int yield() +int yield(task_yield_reason reason) { - return syscall(SYSCALL_YIELD, 0, 0, 0, 0); + return syscall(SYSCALL_YIELD, (uintptr_t)reason, 0, 0, 0); +} + +int kill(int pid) +{ + return syscall(SYSCALL_KILL, (intptr_t)pid, 0, 0, 0); } int register_server(char* name) diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/usyscall.h b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/usyscall.h index 65ab3cd6f..e1b9b7273 100644 --- a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/usyscall.h +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/usyscall.h @@ -30,6 +30,8 @@ #define SYSCALL_EXEC 9 // run elf using current task #define SYSCALL_SYS_STATE 10 // run system state #define SYSCALL_REGISTER_IRQ 11 // + +#define SYSCALL_KILL 12 // kill the task by id // clang-format on typedef enum { @@ -42,6 +44,12 @@ typedef enum { SYS_STATE_SHOW_CPU_INFO, } sys_state_option; +typedef enum { + SYS_TASK_YIELD_NO_REASON = 0x0, + SYS_TASK_YIELD_FOREVER = 0x1, + SYS_TASK_YIELD_BLOCK_IPC = 0x2, +} task_yield_reason; + typedef union { struct { uintptr_t memblock_start; @@ -51,17 +59,13 @@ typedef union { } sys_state_info; typedef int (*ipc_read_fn)(struct Session* session, int fd, char* dst, int offset, int len); +typedef int (*ipc_fsize_fn)(struct Session* session, int fd); typedef int (*ipc_write_fn)(struct Session* session, int fd, char* src, int offset, int len); -struct KernReadTool { - struct Session* session; - int fd; - ipc_read_fn ipc_read; -}; - -int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv); +int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, ipc_fsize_fn ipc_fsize, char* name, char** argv); int exit(); -int yield(); +int yield(task_yield_reason reason); +int kill(int pid); int register_server(char* name); int session(char* path, int capacity, struct Session* user_session); int poll_session(struct Session* userland_session_arr, int arr_capacity); diff --git a/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/Makefile b/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/Makefile index f312ba643..aa1013cfa 100644 --- a/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/Makefile @@ -18,6 +18,7 @@ c_useropts = -O0 INC_DIR = -I$(KERNEL_ROOT)/services/fs/libfs \ -I$(KERNEL_ROOT)/services/fs/fs_server/include \ -I$(KERNEL_ROOT)/services/lib/ipc \ + -I$(KERNEL_ROOT)/services/lib/memory \ -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ -I$(KERNEL_ROOT)/services/app diff --git a/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/usyscall.c b/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/usyscall.c index c03893a43..c1b49a489 100644 --- a/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/usyscall.c +++ b/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/usyscall.c @@ -10,6 +10,7 @@ * See the Mulan PSL v2 for more details. */ #include "usyscall.h" +#include "libmem.h" static int syscall(int sys_num, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4) @@ -33,14 +34,18 @@ syscall(int sys_num, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4) return ret; } -int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv) +int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, ipc_fsize_fn ipc_fsize, char* name, char** argv) { - struct KernReadTool read_tool = { - .session = session, - .fd = fd, - .ipc_read = ipc_read, - }; - return syscall(SYSCALL_SPAWN, (intptr_t)&read_tool, (intptr_t)name, (intptr_t)argv, 0); + int file_size = ipc_fsize(session, fd); + void* img = malloc(file_size); + int read_len = 0, cur_read_len = 0; + while (read_len < file_size) { + cur_read_len = file_size - read_len < 4096 ? file_size - read_len : 4096; + read_len += ipc_read(session, fd, img + read_len, read_len, cur_read_len); + } + int ret = syscall(SYSCALL_SPAWN, (intptr_t)img, (intptr_t)name, (intptr_t)argv, 0); + free(img); + return ret; } int exit() @@ -48,9 +53,14 @@ int exit() return syscall(SYSCALL_EXIT, 0, 0, 0, 0); } -int yield() +int yield(task_yield_reason reason) { - return syscall(SYSCALL_YIELD, 0, 0, 0, 0); + return syscall(SYSCALL_YIELD, (uintptr_t)reason, 0, 0, 0); +} + +int kill(int pid) +{ + return syscall(SYSCALL_KILL, (intptr_t)pid, 0, 0, 0); } int register_server(char* name) diff --git a/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/usyscall.h b/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/usyscall.h index 65ab3cd6f..e1b9b7273 100644 --- a/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/usyscall.h +++ b/Ubiquitous/XiZi_AIoT/services/boards/zynq7000-zc702/usyscall.h @@ -30,6 +30,8 @@ #define SYSCALL_EXEC 9 // run elf using current task #define SYSCALL_SYS_STATE 10 // run system state #define SYSCALL_REGISTER_IRQ 11 // + +#define SYSCALL_KILL 12 // kill the task by id // clang-format on typedef enum { @@ -42,6 +44,12 @@ typedef enum { SYS_STATE_SHOW_CPU_INFO, } sys_state_option; +typedef enum { + SYS_TASK_YIELD_NO_REASON = 0x0, + SYS_TASK_YIELD_FOREVER = 0x1, + SYS_TASK_YIELD_BLOCK_IPC = 0x2, +} task_yield_reason; + typedef union { struct { uintptr_t memblock_start; @@ -51,17 +59,13 @@ typedef union { } sys_state_info; typedef int (*ipc_read_fn)(struct Session* session, int fd, char* dst, int offset, int len); +typedef int (*ipc_fsize_fn)(struct Session* session, int fd); typedef int (*ipc_write_fn)(struct Session* session, int fd, char* src, int offset, int len); -struct KernReadTool { - struct Session* session; - int fd; - ipc_read_fn ipc_read; -}; - -int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv); +int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, ipc_fsize_fn ipc_fsize, char* name, char** argv); int exit(); -int yield(); +int yield(task_yield_reason reason); +int kill(int pid); int register_server(char* name); int session(char* path, int capacity, struct Session* user_session); int poll_session(struct Session* userland_session_arr, int arr_capacity); diff --git a/Ubiquitous/XiZi_AIoT/services/fs/fs_server/Makefile b/Ubiquitous/XiZi_AIoT/services/fs/fs_server/Makefile index 6e254bcee..e93df4cb0 100644 --- a/Ubiquitous/XiZi_AIoT/services/fs/fs_server/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/fs/fs_server/Makefile @@ -18,6 +18,7 @@ c_useropts = -O0 INC_DIR = -I$(KERNEL_ROOT)/services/fs/libfs \ -I$(KERNEL_ROOT)/services/fs/fs_server/include \ -I$(KERNEL_ROOT)/services/lib/ipc \ + -I$(KERNEL_ROOT)/services/lib/memory \ -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ -I$(KERNEL_ROOT)/services/app diff --git a/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs_server.c b/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs_server.c index 1e0d2dbad..ac7eb0cf5 100644 --- a/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs_server.c +++ b/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs_server.c @@ -66,7 +66,7 @@ int IPC_DO_SERVE_FUNC(Ipc_ls)(char* path) printf("ls: find target Inode failed, ip: %x(%d), dp: %x(%d)\n", ip, ip->inum, dp, dp->inum); return -1; } - if (ip->type != T_DIR) { + if (ip->type != FS_DIRECTORY) { printf("ls: not a dir\n"); return -1; } @@ -282,7 +282,7 @@ int IPC_DO_SERVE_FUNC(Ipc_read)(int* fd, char* dst, int* offset, int* len) int cur_read_len = InodeRead(ip, dst, *offset, *len); - return *len; + return cur_read_len; } int IPC_DO_SERVE_FUNC(Ipc_write)(int* fd, char* src, int* offset, int* len) @@ -305,18 +305,36 @@ int IPC_DO_SERVE_FUNC(Ipc_write)(int* fd, char* src, int* offset, int* len) return cur_write_len; } +int IPC_DO_SERVE_FUNC(Ipc_fsize)(int* fd) +{ + struct FileDescriptor* fdp = GetFileDescriptor(*fd); + if (!fdp) { + printf("read: fd invalid\n"); + return -1; + } + + struct Inode* ip = fdp->data; + if (ip->type != FS_FILE) { + printf("read: %s Is not a file\n", fdp->path); + return -1; + } + + return ip->size; +} + IPC_SERVER_INTERFACE(Ipc_ls, 1); IPC_SERVER_INTERFACE(Ipc_cd, 1); IPC_SERVER_INTERFACE(Ipc_mkdir, 1); IPC_SERVER_INTERFACE(Ipc_delete, 1); IPC_SERVER_INTERFACE(Ipc_cat, 1); +IPC_SERVER_INTERFACE(Ipc_fsize, 1); IPC_SERVER_INTERFACE(Ipc_open, 1); IPC_SERVER_INTERFACE(Ipc_close, 1); IPC_SERVER_INTERFACE(Ipc_read, 4); IPC_SERVER_INTERFACE(Ipc_write, 4); -IPC_SERVER_REGISTER_INTERFACES(IpcFsServer, 9, +IPC_SERVER_REGISTER_INTERFACES(IpcFsServer, 10, Ipc_ls, Ipc_cd, Ipc_mkdir, @@ -325,7 +343,8 @@ IPC_SERVER_REGISTER_INTERFACES(IpcFsServer, 9, Ipc_open, Ipc_close, Ipc_read, - Ipc_write); + Ipc_write, + Ipc_fsize); int main(int argc, char* argv[]) { diff --git a/Ubiquitous/XiZi_AIoT/services/fs/libfs/Makefile b/Ubiquitous/XiZi_AIoT/services/fs/libfs/Makefile index ce34b4855..336120483 100644 --- a/Ubiquitous/XiZi_AIoT/services/fs/libfs/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/fs/libfs/Makefile @@ -17,6 +17,7 @@ c_useropts = -O0 INC_DIR = -I$(KERNEL_ROOT)/services/fs/libfs \ -I$(KERNEL_ROOT)/services/lib/ipc \ + -I$(KERNEL_ROOT)/services/lib/memory \ -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ -I$(KERNEL_ROOT)/services/app diff --git a/Ubiquitous/XiZi_AIoT/services/fs/libfs/libfs_to_client.c b/Ubiquitous/XiZi_AIoT/services/fs/libfs/libfs_to_client.c index ceeb077a8..b2109b944 100644 --- a/Ubiquitous/XiZi_AIoT/services/fs/libfs/libfs_to_client.c +++ b/Ubiquitous/XiZi_AIoT/services/fs/libfs/libfs_to_client.c @@ -63,4 +63,10 @@ IPC_INTERFACE(Ipc_write, 4, fd, src, offset, len, sizeof(int), *(int*)len, sizeo int write(struct Session* session, int fd, char* src, int offset, int len) { return IPC_CALL(Ipc_write)(session, &fd, src, &offset, &len); +} + +IPC_INTERFACE(Ipc_fsize, 1, fd, sizeof(int)); +int fsize(struct Session* session, int fd) +{ + return IPC_CALL(Ipc_fsize)(session, &fd); } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/fs/libfs/libfs_to_client.h b/Ubiquitous/XiZi_AIoT/services/fs/libfs/libfs_to_client.h index fd9ab3e9a..c10a67ebf 100644 --- a/Ubiquitous/XiZi_AIoT/services/fs/libfs/libfs_to_client.h +++ b/Ubiquitous/XiZi_AIoT/services/fs/libfs/libfs_to_client.h @@ -15,13 +15,14 @@ #include "libipc.h" IPC_SERVICES(IpcFsServer, Ipc_ls, Ipc_cd, Ipc_mkdir, Ipc_delete, Ipc_cat, - Ipc_open, Ipc_close, Ipc_read, Ipc_write); + Ipc_open, Ipc_close, Ipc_read, Ipc_write, Ipc_fsize); int ls(struct Session* session, char* path); int cd(struct Session* session, char* path); int mkdir(struct Session* session, char* path); int rm(struct Session* session, char* path); int cat(struct Session* session, char* path); +int fsize(struct Session* session, int fd); int open(struct Session* session, char* path); int close(struct Session* session, int fd); diff --git a/Ubiquitous/XiZi_AIoT/services/lib/Makefile b/Ubiquitous/XiZi_AIoT/services/lib/Makefile index 1d6142afd..c242de34a 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/lib/Makefile @@ -1,4 +1,4 @@ -SRC_DIR := ipc +SRC_DIR := ipc memory include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/lib/ipc/Makefile b/Ubiquitous/XiZi_AIoT/services/lib/ipc/Makefile index c9c573cf2..48b6ef330 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/ipc/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/lib/ipc/Makefile @@ -15,8 +15,8 @@ objdump = ${toolchain}objdump c_useropts = -O0 -INC_DIR = -I$(KERNEL_ROOT)/services/shell/letter-shell \ - -I$(KERNEL_ROOT)/services/lib/ipc \ +INC_DIR = -I$(KERNEL_ROOT)/services/lib/ipc \ + -I$(KERNEL_ROOT)/services/lib/memory \ -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ -I$(KERNEL_ROOT)/services/app diff --git a/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c b/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c index 0d9582aae..e00df4e2d 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c +++ b/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c @@ -121,7 +121,7 @@ void ipc_msg_send_wait(struct IpcMsg* msg) msg->header.done = 0; while (msg->header.done == 0) { /// @todo syscall yield with prio decrease - yield(); + yield(SYS_TASK_YIELD_BLOCK_IPC); } assert(msg->header.done == 1); } @@ -138,7 +138,7 @@ int ipc_session_wait(struct Session* session) struct IpcMsg* msg = IPCSESSION_MSG(session); while (msg->header.done == 0) { /// @todo syscall yield with prio decrease - yield(); + yield(SYS_TASK_YIELD_BLOCK_IPC); } assert(msg->header.done == 1); return msg->header.ret_val; @@ -159,6 +159,7 @@ void delay_session(void) void ipc_server_loop(struct IpcNode* ipc_node) { struct Session session_list[NR_MAX_SESSION]; + memset(session_list, 0, sizeof(session_list)); for (;;) { /* if connect sessions are greater than NR_MAX_SESSION, a full round will require multiple polls. @@ -169,7 +170,7 @@ void ipc_server_loop(struct IpcNode* ipc_node) /* handle each session */ for (int i = 0; i < NR_MAX_SESSION; i++) { if (session_list[i].buf == NULL) { - yield(); + yield(SYS_TASK_YIELD_NO_REASON); break; } cur_sess_id = session_list[i].id; @@ -178,11 +179,13 @@ void ipc_server_loop(struct IpcNode* ipc_node) a session could be delay in case one of its message(current message) needs to wait for an interrupt message's arrival interfaces[opcode] should explicitly call delay_session() and return to delay this session */ - while (msg->header.magic == IPC_MSG_MAGIC && msg->header.valid == 1 && msg->header.done != 1) { + while (msg->header.magic == IPC_MSG_MAGIC && msg->header.valid == 1 && msg->header.done == 0) { // printf("session %d [%d, %d]\n", session_list[i].id, session_list[i].head, session_list[i].tail); if (session_used_size(&session_list[i]) == 0 && session_forward_tail(&session_list[i], msg->header.len) < 0) { break; } + + // this is a message needs to handle if (ipc_node->interfaces[msg->header.opcode]) { ipc_node->interfaces[msg->header.opcode](msg); // check if this session is delayed by op handler, all messages after the delayed message in current session is blocked. @@ -193,9 +196,10 @@ void ipc_server_loop(struct IpcNode* ipc_node) } else { printf("Unsupport opcode(%d) for server: %s\n", msg->header.opcode, ipc_node->name); } + // current msg is a message that needs to ignore // finish this message in server's perspective - while (session_forward_head(&session_list[i], msg->header.len) < 0) { - yield(); + if (session_forward_head(&session_list[i], msg->header.len) < 0) { + break; } msg = IPCSESSION_MSG(&session_list[i]); } diff --git a/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.h b/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.h index 86148a9a6..c7e399f05 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.h +++ b/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.h @@ -37,7 +37,7 @@ Modification: #include "ipcargs.h" #include "session.h" -#define NR_MAX_SESSION 16 +#define NR_MAX_SESSION 32 #define IPC_MSG_MAGIC 0xABCDDCBA typedef struct { diff --git a/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.c b/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.c index 27e88c706..a399dec18 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.c +++ b/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.c @@ -61,6 +61,6 @@ bool session_free_buf(struct Session* session, int len) if (len > session_used_size(session)) { return false; } - assert(session_forward_head(session, len) != 1); + assert(session_forward_head(session, len) != -1); return true; } diff --git a/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.h b/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.h index 24952db0c..196c6bf5b 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.h +++ b/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.h @@ -55,8 +55,8 @@ __attribute__((__always_inline__)) static inline int session_remain_capacity(str __attribute__((__always_inline__)) static inline int session_forward_head(struct Session* session, int len) { - if (((session->head + len) % session->capacity) > session->tail) { - printf("forward head with too much size\n"); + if (len > session_used_size(session)) { + printf("forward head with too much size, session used size: %d\n", session_used_size(session)); return -1; } session->head = (session->head + len) % session->capacity; diff --git a/Ubiquitous/XiZi_AIoT/services/lib/memory/Makefile b/Ubiquitous/XiZi_AIoT/services/lib/memory/Makefile index 80cb8d3da..54139e413 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/memory/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/lib/memory/Makefile @@ -12,11 +12,14 @@ user_ldflags = -N -Ttext 0 cflags = -std=c11 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie c_useropts = -O0 -INC_DIR = -I$(KERNEL_ROOT)/services/app \ - -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ - -I$(KERNEL_ROOT)/services/lib/ipc +INC_DIR = -I$(KERNEL_ROOT)/services/app \ + -I$(KERNEL_ROOT)/services/fs/libfs \ + -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ + -I$(KERNEL_ROOT)/services/lib/memory \ + -I$(KERNEL_ROOT)/services/lib/ipc -all: +all: libmem.o + @mv $^ ../../app %.o: %.c @echo "cc $^" diff --git a/Ubiquitous/XiZi_AIoT/services/lib/memory/libmem.c b/Ubiquitous/XiZi_AIoT/services/lib/memory/libmem.c new file mode 100644 index 000000000..feb746b5f --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/lib/memory/libmem.c @@ -0,0 +1,369 @@ +/* + * mm.c - malloc using segregated list + * KAIST + * Tony Kim + * + * In this approach, + * Every block has a header and a footer + * in which header contains reallocation information, size, and allocation info + * and footer contains size and allocation info. + * Free list are tagged to the segregated list. + * Therefore all free block contains pointer to the predecessor and successor. + * The segregated list headers are organized by 2^k size. + * + */ + +#include "libmem.h" +#include "usyscall.h" + +/* single word (4) or double word (8) alignment */ +#define ALIGNMENT 8 +/* rounds up to the nearest multiple of ALIGNMENT */ +#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~0x7) + +// My additional Macros +#define WSIZE 4 // word and header/footer size (bytes) +#define DSIZE 8 // double word size (bytes) +#define INITCHUNKSIZE (1 << 6) +#define CHUNKSIZE (1 << 12) //+(1<<7) + +#define LISTLIMIT 20 + +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + +// Pack a size and allocated bit into a word +#define PACK(size, alloc) ((size) | (alloc)) + +// Read and write a word at address p +#define GET(p) (*(unsigned int*)(p)) +#define PUT(p, val) (*(unsigned int*)(p) = (val) | GET_TAG(p)) +#define PUT_NOTAG(p, val) (*(unsigned int*)(p) = (val)) + +// Store predecessor or successor pointer for free blocks +#define SET_PTR(p, ptr) (*(unsigned int*)(p) = (unsigned int)(ptr)) + +// Read the size and allocation bit from address p +#define GET_SIZE(p) (GET(p) & ~0x7) +#define GET_ALLOC(p) (GET(p) & 0x1) +#define GET_TAG(p) (GET(p) & 0x2) +#define SET_RATAG(p) (GET(p) |= 0x2) +#define REMOVE_RATAG(p) (GET(p) &= ~0x2) + +// Address of block's header and footer +#define HDRP(ptr) ((char*)(ptr)-WSIZE) +#define FTRP(ptr) ((char*)(ptr) + GET_SIZE(HDRP(ptr)) - DSIZE) + +// Address of (physically) next and previous blocks +#define NEXT_BLKP(ptr) ((char*)(ptr) + GET_SIZE((char*)(ptr)-WSIZE)) +#define PREV_BLKP(ptr) ((char*)(ptr)-GET_SIZE((char*)(ptr)-DSIZE)) + +// Address of free block's predecessor and successor entries +#define PRED_PTR(ptr) ((char*)(ptr)) +#define SUCC_PTR(ptr) ((char*)(ptr) + WSIZE) + +// Address of free block's predecessor and successor on the segregated list +#define PRED(ptr) (*(char**)(ptr)) +#define SUCC(ptr) (*(char**)(SUCC_PTR(ptr))) + +// End of my additional macros + +// Global var +void* segregated_free_lists[LISTLIMIT]; + +// Functions +static void* extend_heap(size_t size); +static void* coalesce(void* ptr); +static void* place(void* ptr, size_t asize); +static void insert_node(void* ptr, size_t size); +static void delete_node(void* ptr); + +static uintptr_t userland_heap_base; +static uintptr_t userland_heap_top; +static uintptr_t requested_heap_size; + +static void* mem_sbrk(size_t size) +{ + uintptr_t userland_heap_size = userland_heap_top - userland_heap_base; + if (userland_heap_size - requested_heap_size >= size) { + void* ret_ptr = (void*)(userland_heap_base + requested_heap_size); + requested_heap_size += size; + return ret_ptr; + } + + uintptr_t size_needed = size - (userland_heap_size - requested_heap_size); + userland_heap_top = mmap(userland_heap_top, (uintptr_t)NULL, size_needed, false); + + return mem_sbrk(size); +} + +static void* extend_heap(size_t size) +{ + void* ptr; + size_t asize; // Adjusted size + + asize = ALIGN(size); + + if ((ptr = mem_sbrk(asize)) == (void*)-1) + return NULL; + + // Set headers and footer + PUT_NOTAG(HDRP(ptr), PACK(asize, 0)); + PUT_NOTAG(FTRP(ptr), PACK(asize, 0)); + PUT_NOTAG(HDRP(NEXT_BLKP(ptr)), PACK(0, 1)); + insert_node(ptr, asize); + + return coalesce(ptr); +} + +static void insert_node(void* ptr, size_t size) +{ + int list = 0; + void* search_ptr = ptr; + void* insert_ptr = NULL; + + // Select segregated list + while ((list < LISTLIMIT - 1) && (size > 1)) { + size >>= 1; + list++; + } + + // Keep size ascending order and search + search_ptr = segregated_free_lists[list]; + while ((search_ptr != NULL) && (size > GET_SIZE(HDRP(search_ptr)))) { + insert_ptr = search_ptr; + search_ptr = PRED(search_ptr); + } + + // Set predecessor and successor + if (search_ptr != NULL) { + if (insert_ptr != NULL) { + SET_PTR(PRED_PTR(ptr), search_ptr); + SET_PTR(SUCC_PTR(search_ptr), ptr); + SET_PTR(SUCC_PTR(ptr), insert_ptr); + SET_PTR(PRED_PTR(insert_ptr), ptr); + } else { + SET_PTR(PRED_PTR(ptr), search_ptr); + SET_PTR(SUCC_PTR(search_ptr), ptr); + SET_PTR(SUCC_PTR(ptr), NULL); + segregated_free_lists[list] = ptr; + } + } else { + if (insert_ptr != NULL) { + SET_PTR(PRED_PTR(ptr), NULL); + SET_PTR(SUCC_PTR(ptr), insert_ptr); + SET_PTR(PRED_PTR(insert_ptr), ptr); + } else { + SET_PTR(PRED_PTR(ptr), NULL); + SET_PTR(SUCC_PTR(ptr), NULL); + segregated_free_lists[list] = ptr; + } + } + + return; +} + +static void delete_node(void* ptr) +{ + int list = 0; + size_t size = GET_SIZE(HDRP(ptr)); + + // Select segregated list + while ((list < LISTLIMIT - 1) && (size > 1)) { + size >>= 1; + list++; + } + + if (PRED(ptr) != NULL) { + if (SUCC(ptr) != NULL) { + SET_PTR(SUCC_PTR(PRED(ptr)), SUCC(ptr)); + SET_PTR(PRED_PTR(SUCC(ptr)), PRED(ptr)); + } else { + SET_PTR(SUCC_PTR(PRED(ptr)), NULL); + segregated_free_lists[list] = PRED(ptr); + } + } else { + if (SUCC(ptr) != NULL) { + SET_PTR(PRED_PTR(SUCC(ptr)), NULL); + } else { + segregated_free_lists[list] = NULL; + } + } + + return; +} + +static void* coalesce(void* ptr) +{ + size_t prev_alloc = GET_ALLOC(HDRP(PREV_BLKP(ptr))); + size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(ptr))); + size_t size = GET_SIZE(HDRP(ptr)); + + // Do not coalesce with previous block if the previous block is tagged with Reallocation tag + if (GET_TAG(HDRP(PREV_BLKP(ptr)))) + prev_alloc = 1; + + if (prev_alloc && next_alloc) { // Case 1 + return ptr; + } else if (prev_alloc && !next_alloc) { // Case 2 + delete_node(ptr); + delete_node(NEXT_BLKP(ptr)); + size += GET_SIZE(HDRP(NEXT_BLKP(ptr))); + PUT(HDRP(ptr), PACK(size, 0)); + PUT(FTRP(ptr), PACK(size, 0)); + } else if (!prev_alloc && next_alloc) { // Case 3 + delete_node(ptr); + delete_node(PREV_BLKP(ptr)); + size += GET_SIZE(HDRP(PREV_BLKP(ptr))); + PUT(FTRP(ptr), PACK(size, 0)); + PUT(HDRP(PREV_BLKP(ptr)), PACK(size, 0)); + ptr = PREV_BLKP(ptr); + } else { // Case 4 + delete_node(ptr); + delete_node(PREV_BLKP(ptr)); + delete_node(NEXT_BLKP(ptr)); + size += GET_SIZE(HDRP(PREV_BLKP(ptr))) + GET_SIZE(HDRP(NEXT_BLKP(ptr))); + PUT(HDRP(PREV_BLKP(ptr)), PACK(size, 0)); + PUT(FTRP(NEXT_BLKP(ptr)), PACK(size, 0)); + ptr = PREV_BLKP(ptr); + } + + insert_node(ptr, size); + + return ptr; +} + +static void* place(void* ptr, size_t asize) +{ + size_t ptr_size = GET_SIZE(HDRP(ptr)); + size_t remainder = ptr_size - asize; + + delete_node(ptr); + + if (remainder <= DSIZE * 2) { + // Do not split block + PUT(HDRP(ptr), PACK(ptr_size, 1)); + PUT(FTRP(ptr), PACK(ptr_size, 1)); + } + + else if (asize >= 100) { + // Split block + PUT(HDRP(ptr), PACK(remainder, 0)); + PUT(FTRP(ptr), PACK(remainder, 0)); + PUT_NOTAG(HDRP(NEXT_BLKP(ptr)), PACK(asize, 1)); + PUT_NOTAG(FTRP(NEXT_BLKP(ptr)), PACK(asize, 1)); + insert_node(ptr, remainder); + return NEXT_BLKP(ptr); + + } + + else { + // Split block + PUT(HDRP(ptr), PACK(asize, 1)); + PUT(FTRP(ptr), PACK(asize, 1)); + PUT_NOTAG(HDRP(NEXT_BLKP(ptr)), PACK(remainder, 0)); + PUT_NOTAG(FTRP(NEXT_BLKP(ptr)), PACK(remainder, 0)); + insert_node(NEXT_BLKP(ptr), remainder); + } + return ptr; +} + +static bool malloc_inited = false; +int mm_init(void) +{ + // init heap + userland_heap_base = task_heap_base(); + userland_heap_top = userland_heap_base; + requested_heap_size = 0; + + int list; + char* heap_start; // Pointer to beginning of heap + + // Initialize segregated free lists + for (list = 0; list < LISTLIMIT; list++) { + segregated_free_lists[list] = NULL; + } + + // Allocate memory for the initial empty heap + if ((long)(heap_start = mem_sbrk(4 * WSIZE)) == -1) + return -1; + + PUT_NOTAG(heap_start, 0); /* Alignment padding */ + PUT_NOTAG(heap_start + (1 * WSIZE), PACK(DSIZE, 1)); /* Prologue header */ + PUT_NOTAG(heap_start + (2 * WSIZE), PACK(DSIZE, 1)); /* Prologue footer */ + PUT_NOTAG(heap_start + (3 * WSIZE), PACK(0, 1)); /* Epilogue header */ + + if (extend_heap(INITCHUNKSIZE) == NULL) + return -1; + + malloc_inited = true; + return 0; +} + +void* malloc(size_t size) +{ + while (!malloc_inited) { + mm_init(); + } + + size_t asize; /* Adjusted block size */ + size_t extendsize; /* Amount to extend heap if no fit */ + void* ptr = NULL; /* Pointer */ + + // Ignore size 0 cases + if (size == 0) + return NULL; + + // Align block size + if (size <= DSIZE) { + asize = 2 * DSIZE; + } else { + asize = ALIGN(size + DSIZE); + } + + int list = 0; + size_t searchsize = asize; + // Search for free block in segregated list + while (list < LISTLIMIT) { + if ((list == LISTLIMIT - 1) || ((searchsize <= 1) && (segregated_free_lists[list] != NULL))) { + ptr = segregated_free_lists[list]; + // Ignore blocks that are too small or marked with the reallocation bit + while ((ptr != NULL) && ((asize > GET_SIZE(HDRP(ptr))) || (GET_TAG(HDRP(ptr))))) { + ptr = PRED(ptr); + } + if (ptr != NULL) + break; + } + + searchsize >>= 1; + list++; + } + + // if free block is not found, extend the heap + if (ptr == NULL) { + extendsize = MAX(asize, CHUNKSIZE); + + if ((ptr = extend_heap(extendsize)) == NULL) + return NULL; + } + + // Place and divide block + ptr = place(ptr, asize); + + // Return pointer to newly allocated block + return ptr; +} + +void free(void* ptr) +{ + size_t size = GET_SIZE(HDRP(ptr)); + + REMOVE_RATAG(HDRP(NEXT_BLKP(ptr))); + PUT(HDRP(ptr), PACK(size, 0)); + PUT(FTRP(ptr), PACK(size, 0)); + + insert_node(ptr, size); + coalesce(ptr); + + return; +} diff --git a/Ubiquitous/XiZi_AIoT/services/lib/memory/libmalloc.h b/Ubiquitous/XiZi_AIoT/services/lib/memory/libmem.h similarity index 95% rename from Ubiquitous/XiZi_AIoT/services/lib/memory/libmalloc.h rename to Ubiquitous/XiZi_AIoT/services/lib/memory/libmem.h index 07669ae80..7f1b9631d 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/memory/libmalloc.h +++ b/Ubiquitous/XiZi_AIoT/services/lib/memory/libmem.h @@ -10,7 +10,7 @@ * See the Mulan PSL v2 for more details. */ /** - * @file libmalloc.h + * @file libmem.h * @brief support malloc and free in userland * @version 3.0 * @author AIIT XUOS Lab @@ -18,7 +18,7 @@ */ /************************************************* -File name: libmalloc.h +File name: libmem.h Description: support malloc and free in userland Others: History: diff --git a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/Makefile b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/Makefile index ac0b851b3..e2bdb095e 100644 --- a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/Makefile @@ -16,9 +16,10 @@ objdump = ${toolchain}objdump c_useropts = -O0 INC_DIR = -I$(KERNEL_ROOT)/services/app \ + -I$(KERNEL_ROOT)/services/fs/libfs \ + -I$(KERNEL_ROOT)/services/lib/memory \ -I$(KERNEL_ROOT)/services/lib/ipc \ - -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ - -I$(KERNEL_ROOT)/services/fs/libfs + -I$(KERNEL_ROOT)/services/boards/$(BOARD) all: shell_cmd_list.o shell_ext.o shell.o @mv $^ ../../app diff --git a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell.c b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell.c index 1fa2dd2d6..d7588636c 100644 --- a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell.c +++ b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell.c @@ -1282,7 +1282,7 @@ void shellExec(Shell* shell) if (fd < 0) { shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]); } else { - if (spawn(&session_fs, fd, read, shell->parser.param[0], shell->parser.param) < 0) { + if (spawn(&session_fs, fd, read, fsize, shell->parser.param[0], shell->parser.param) < 0) { shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]); } close(&session_fs, fd); @@ -1725,6 +1725,11 @@ int shellRun(Shell* shell, const char* cmd) } } +void shellKill(int pid) +{ + kill(pid); +} + /** * @brief ls 打印当前路径下所有文件(文件系统调用) */ diff --git a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cmd_list.c b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cmd_list.c index 266c9747c..762abed40 100644 --- a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cmd_list.c +++ b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cmd_list.c @@ -36,6 +36,7 @@ extern void shellMkdir(const char* path); extern void shellRm(const char* path); extern void shellCat(const char* path); +extern void shellKill(int pid); extern void shellShowTasks(); extern void shellShowMemInfo(); extern void shellShowCpusInfo(); @@ -97,8 +98,11 @@ const ShellCommand shellCommandList[] = { SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN, sh, SHELL_AGENCY_FUNC_NAME(shellRun), run command directly), + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN, + kill, shellKill, kill task by id), SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN, ls, shellLs, ls files), + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN, cd, shellCd, go to target path), SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN, diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/buddy.h b/Ubiquitous/XiZi_AIoT/softkernel/include/buddy.h index 6c890c840..d8a0354ca 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/buddy.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/buddy.h @@ -68,7 +68,6 @@ struct KFreeList { struct double_list_node list_head; }; -#define MAX_NR_PAGES MAX_NR_FREE_PAGES struct KBuddy { uint32_t n_pages; uint32_t use_lock; @@ -77,7 +76,7 @@ struct KBuddy { struct KPage* first_page; uint32_t mem_start; uint32_t mem_end; - struct KPage pages[MAX_NR_PAGES]; + struct KPage* pages; }; /********************************************* @@ -89,6 +88,7 @@ struct KBuddy { * @param mem_end free memory region end * @return void */ +bool KBuddyInit(struct KBuddy* pbuddy, uint32_t mem_start, uint32_t mem_end); void KBuddySysInit(struct KBuddy* pbuddy, uint32_t mem_start, uint32_t mem_end); /* @@ -105,6 +105,8 @@ char* KBuddyAlloc(struct KBuddy* pbuddy, uint32_t size); */ bool KBuddyFree(struct KBuddy* pbuddy, char* vaddr); +void KBuddyDestory(struct KBuddy* pbuddy); + /* * Print current free pages for debug. */ diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/kern_init.h b/Ubiquitous/XiZi_AIoT/softkernel/include/kern_init.h index 5bb31dad5..c807a75da 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/kern_init.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/kern_init.h @@ -37,5 +37,6 @@ struct XiziBootNode { }; bool hardkernel_init(struct TraceTag*); +bool secondary_cpu_hardkernel_init(int cpu_id, struct TraceTag* _hardkernel_tag); bool softkernel_init(struct TraceTag* _hardkernel_tag, struct TraceTag* _softkernel_tag); void show_xizi_bar(void); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/log.h b/Ubiquitous/XiZi_AIoT/softkernel/include/log.h index 22640817c..8b871fc9a 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/log.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/log.h @@ -34,6 +34,7 @@ Modification: #define OUTPUT_LEVLE_ERROR 2 #define OUTPUT_LEVLE OUTPUT_LEVLE_DEBUG +// #define OUTPUT_LEVLE OUTPUT_LEVLE_LOG extern void KPrintf(char* fmt, ...); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/multicores.h b/Ubiquitous/XiZi_AIoT/softkernel/include/multicores.h index 1db29ac9c..d0e950565 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/multicores.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/multicores.h @@ -30,6 +30,7 @@ Modification: #pragma once #include "core.h" +#include "spinlock.h" #include "trap_common.h" struct CPU { @@ -44,4 +45,11 @@ extern struct CPU global_cpus[NR_CPU]; static inline struct CPU* cur_cpu(void) { return &global_cpus[cur_cpuid()]; -} \ No newline at end of file +} + +struct spinlock whole_kernel_lock; + +void xizi_enter_kernel(); +bool xizi_try_enter_kernel(); +void xizi_leave_kernel(); +bool xizi_is_in_kernel(); \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/pagetable.h b/Ubiquitous/XiZi_AIoT/softkernel/include/pagetable.h index bd3f70af4..691430773 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/pagetable.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/pagetable.h @@ -72,6 +72,7 @@ uintptr_t* _page_walk(uintptr_t* pgdir, uintptr_t vaddr, bool alloc); extern struct TopLevelPageDirectory kern_pgdir; void load_kern_pgdir(struct TraceTag* mmu_driver_tag, struct TraceTag* intr_driver_tag); +void secondary_cpu_load_kern_pgdir(struct TraceTag* mmu_driver_tag, struct TraceTag* intr_driver_tag); extern struct XiziPageManager xizi_pager; bool module_pager_init(struct PagerRightGroup*); \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h b/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h index 7429916c7..052cfff9f 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h @@ -44,6 +44,8 @@ Modification: #define SYSCALL_EXEC 9 // run elf using current task #define SYSCALL_SYS_STATE 10 // run system state #define SYSCALL_REGISTER_IRQ 11 // + +#define SYSCALL_KILL 12 // kill the task by id // clang-format on #ifndef __ASSEMBLER__ @@ -62,6 +64,12 @@ typedef enum { SYS_STATE_SHOW_CPU_INFO, } sys_state_option; +typedef enum { + SYS_TASK_YIELD_NO_REASON = 0x0, + SYS_TASK_YIELD_FOREVER = 0x1, + SYS_TASK_YIELD_BLOCK_IPC = 0x2, +} task_yield_reason; + typedef union { struct { uintptr_t memblock_start; @@ -74,26 +82,23 @@ typedef union { typedef int (*ipc_read_fn)(struct Session* session, int fd, char* dst, int offset, int len); typedef int (*ipc_write_fn)(struct Session* session, int fd, char* src, int offset, int len); -struct KernReadTool { - struct Session* session; - int fd; - ipc_read_fn ipc_read; -}; - int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, uintptr_t param4); -int sys_spawn(struct KernReadTool* read_tool, char* name, char** argv); -int sys_exit(); -int sys_yield(); +int sys_spawn(char* img_start, char* name, char** argv); +int sys_exit(struct TaskMicroDescriptor* ptask); +int sys_yield(task_yield_reason reason); +int sys_kill(int id); int sys_register_as_server(char* name); int sys_connect_session(char* path, int capacity, struct Session* user_session); int sys_poll_session(struct Session* userland_session_arr, int arr_capacity); int sys_close_session(struct Session* session); -int sys_exec(struct KernReadTool* read_tool, char* name, char** argv); +int sys_exec(char* img_start, char* name, char** argv); int sys_state(sys_state_option option, sys_state_info* info); int sys_mmap(uintptr_t vaddr, uintptr_t paddr, int len, int is_dev); int sys_register_irq(int irq_num, int irq_opcode); +int sys_unbind_irq_all(struct TaskMicroDescriptor* task); +int sys_unbind_irq(struct TaskMicroDescriptor* task, int irq_num); #endif diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/task.h b/Ubiquitous/XiZi_AIoT/softkernel/include/task.h index adc872da6..da65da17f 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/task.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/task.h @@ -31,6 +31,7 @@ Modification: #include "core.h" +#include "buddy.h" #include "list.h" #include "object_allocator.h" #include "pagetable.h" @@ -47,6 +48,8 @@ enum ProcState { READY, RUNNING, DEAD, + BLOCKED, + NEVER_RUN, }; /* Thread Control Block */ @@ -59,33 +62,39 @@ struct Thread { /* Process Control Block */ struct TaskMicroDescriptor { - struct double_list_node node; - - struct spinlock lock; - /* task->lock needed */ + /* task debug resources */ int pid; + bool bind_irq; + bool dead; + char name[TASK_NAME_MAX_LEN]; + + /// @todo support return value + int ret; // state val that be returned to parent /// @todo support parent struct TaskMicroDescriptor* parent; - enum ProcState state; - /// @todo support ret value - int ret; // state val that be returned to parent + + /* task context resources */ + struct Thread main_thread; // will only access by task itself + + /* task memory resources */ struct TopLevelPageDirectory pgdir; // [phy] vm pgtbl base address + uintptr_t heap_base; // mem size of proc used(allocated by kernel) + /// @todo support heap_base + uintptr_t mem_size; + + /* task communication resources */ struct double_list_node cli_sess_listhead; struct double_list_node svr_sess_listhead; + bool current_ipc_handled; + struct KBuddy* massive_ipc_allocator; struct TraceTag server_identifier; - /* task->lock not necessary */ - struct Thread main_thread; // will only access by task itself + /* task schedule attributes */ + struct double_list_node node; + enum ProcState state; + int priority; // priority int remain_tick; int maxium_tick; - - struct TraceTag cwd; // current directory - - int priority; // priority - - /// @todo support mem_size - uintptr_t mem_size; // mem size of proc used(allocated by kernel) - char name[TASK_NAME_MAX_LEN]; }; struct SchedulerRightGroup { @@ -94,17 +103,12 @@ struct SchedulerRightGroup { }; struct XiziTaskManager { - struct spinlock lock; // lock to organize free and used task list struct double_list_node task_list_head[TASK_MAX_PRIORITY]; /* list of task control blocks that are allocated */ - int nr_pcb_used; // for debug + struct double_list_node task_blocked_list_head; struct slab_allocator task_allocator; - - /// @todo Add pid to task + struct slab_allocator task_buddy_allocator; uint32_t next_pid; - /* number of tcbs in which one page contains */ - int nr_tcb_per_page; - /* init task manager */ void (*init)(); /* new a task control block, checkout #sys_spawn for usage */ @@ -112,14 +116,19 @@ struct XiziTaskManager { /* free a task control block, this calls #free_user_pgdir to free all vitual spaces */ void (*free_pcb)(struct TaskMicroDescriptor*); /* init a task control block, set name, remain_tick, state, cwd, priority, etc. */ - void (*task_set_default_schedule_attr)(struct TaskMicroDescriptor*, struct TraceTag* cwd); + void (*task_set_default_schedule_attr)(struct TaskMicroDescriptor*); /* use by task_scheduler, find next READY task, should be in locked */ struct TaskMicroDescriptor* (*next_runnable_task)(void); /* function that's runing by kernel thread context, schedule use tasks */ void (*task_scheduler)(struct SchedulerRightGroup); + + /* handle task state */ /* call to yield current use task */ - void (*cur_task_yield_noschedule)(void); + void (*task_yield_noschedule)(struct TaskMicroDescriptor* task, bool is_blocking); + /* block and unblock task */ + void (*task_block)(struct TaskMicroDescriptor* task); + void (*task_unblock)(struct TaskMicroDescriptor* task); /* set task priority */ void (*set_cur_task_priority)(int priority); }; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/main.c b/Ubiquitous/XiZi_AIoT/softkernel/main.c index d283b4b27..e79beecaf 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/main.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/main.c @@ -27,48 +27,78 @@ Author: AIIT XUOS Lab Modification: 1. first version *************************************************/ +/// @todo use hardkernel + #include "kern_init.h" +#include "multicores.h" #include "assert.h" #include "task.h" -#include "trap_common.h" - extern uint32_t _binary_init_start[], _binary_default_fs_start[]; -extern int sys_spawn(char* path, char** argv); +extern int sys_spawn(char* img_start, char* name, char** argv); + +static struct TraceTag hardkernel_tag, softkernel_tag; +static int core_init_done = 0; int main(void) { /* init tracer */ - // clang-format off - tracer_init(); // init tracer system - struct TraceTag hardkernel_tag, softkernel_tag; - if (!CreateResourceTag(&hardkernel_tag, RequireRootTag(), "hardkernel", TRACER_OWNER, NULL) || - !CreateResourceTag(&softkernel_tag, RequireRootTag(), "softkernel", TRACER_OWNER, NULL)) { - ERROR("Failed to create hardkernel owner and softkernel owner.\n"); - return -1; - } - // clang-format on + uint32_t cpu_id = cur_cpuid(); - /* init hardkernel */ - if (!hardkernel_init(&hardkernel_tag)) { - return -1; - } - /* init softkernel */ - if (!softkernel_init(&hardkernel_tag, &softkernel_tag)) { - return -1; - } - show_xizi_bar(); + if (cpu_id == 0) { + tracer_init(); // init tracer system + // clang-format off + if (!CreateResourceTag(&hardkernel_tag, RequireRootTag(), "hardkernel", TRACER_OWNER, NULL) || + !CreateResourceTag(&softkernel_tag, RequireRootTag(), "softkernel", TRACER_OWNER, NULL)) { + ERROR("Failed to create hardkernel owner and softkernel owner.\n"); + return -1; + } + // clang-format on + /* init hardkernel */ + if (!hardkernel_init(&hardkernel_tag)) { + return -1; + } - /* start first task */ - char* init_task_param[2] = { "/app/init", 0 }; - spawn_embedded_task((char*)_binary_init_start, "init", init_task_param); - char* fs_server_task_param[2] = { "/app/fs_server", 0 }; - spawn_embedded_task((char*)_binary_default_fs_start, "memfs", fs_server_task_param); + spinlock_init(&whole_kernel_lock, "wklock"); + } else { + spinlock_lock(&whole_kernel_lock); + secondary_cpu_hardkernel_init(cpu_id, &hardkernel_tag); + spinlock_unlock(&whole_kernel_lock); + } + + spinlock_lock(&whole_kernel_lock); + if (cpu_id == 0) { + /* init softkernel */ + if (!softkernel_init(&hardkernel_tag, &softkernel_tag)) { + return -1; + } + show_xizi_bar(); + + for (int i = 1; i < NR_CPU; i++) { + // start secondary cpus + cpu_start_secondary(i); + } + + /* start first task */ + char* init_task_param[2] = { "/app/init", 0 }; + sys_spawn((char*)_binary_init_start, "init", init_task_param); + char* fs_server_task_param[2] = { "/app/fs_server", 0 }; + sys_spawn((char*)_binary_default_fs_start, "memfs", fs_server_task_param); + } /* start scheduler */ struct SchedulerRightGroup scheduler_rights; assert(AchieveResourceTag(&scheduler_rights.mmu_driver_tag, &hardkernel_tag, "mmu-ac-resource")); assert(AchieveResourceTag(&scheduler_rights.intr_driver_tag, &hardkernel_tag, "intr-ac-resource")); + core_init_done |= (1 << cpu_id); + LOG_PRINTF("CPU %d init done\n", cpu_id); + spinlock_unlock(&whole_kernel_lock); + + while (core_init_done != (1 << NR_CPU) - 1) + ; + + xizi_enter_kernel(); + start_smp_cache_broadcast(cpu_id); xizi_task_manager.task_scheduler(scheduler_rights); // never reached diff --git a/Ubiquitous/XiZi_AIoT/softkernel/memory/buddy.c b/Ubiquitous/XiZi_AIoT/softkernel/memory/buddy.c index 95d56e0d0..702c0409e 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/memory/buddy.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/memory/buddy.c @@ -29,6 +29,7 @@ Modification: *************************************************/ #include "buddy.h" +#include "kalloc.h" #include "log.h" static void _buddy_split_page(struct KPage* page, uint32_t low_order, uint32_t high_order, struct KFreeList* list) @@ -75,8 +76,6 @@ static struct KPage* KBuddyPagesAlloc(struct KBuddy* pbuddy, int nPages) struct KFreeList* list = NULL; int i = 0, order = 0; - spinlock_lock(&pbuddy->lock); - // find order for (order = 0; (FREE_LIST_INDEX(order)) < nPages; order++) ; @@ -99,12 +98,10 @@ static struct KPage* KBuddyPagesAlloc(struct KBuddy* pbuddy, int nPages) // set the pages' order _buddy_set_pages_order(page, order); - spinlock_unlock(&pbuddy->lock); return page; } // there is no enough free page to satisfy the nPages - spinlock_unlock(&pbuddy->lock); return NULL; } @@ -116,8 +113,6 @@ static void KBuddyPagesFree(struct KBuddy* pbuddy, struct KPage* page) uint32_t buddy_idx = 0, new_buddy_idx = 0; uint32_t page_idx = page - pbuddy->pages; - spinlock_lock(&pbuddy->lock); - for (; order < MAX_BUDDY_ORDER - 1; order++) { // find and delete buddy to combine buddy_idx = BUDDY_PAGE_INDEX(page_idx, order); @@ -141,19 +136,22 @@ static void KBuddyPagesFree(struct KBuddy* pbuddy, struct KPage* page) doubleListAddOnHead(&page->node, &pbuddy->free_list[order].list_head); pbuddy->free_list[order].n_free_pages++; - spinlock_unlock(&pbuddy->lock); return; } -void KBuddySysInit(struct KBuddy* pbuddy, uint32_t mem_start, uint32_t mem_end) +bool KBuddyInit(struct KBuddy* pbuddy, uint32_t mem_start, uint32_t mem_end) { + if (pbuddy->pages == NULL) { + if ((pbuddy->pages = (struct KPage*)kalloc(((mem_end - mem_start) >> LEVEL4_PTE_SHIFT) * sizeof(struct KPage))) == NULL) { + ERROR("Not space to init a buddy object.\n"); + return false; + } + } + uint32_t i = 0; struct KPage* page = NULL; struct KFreeList* free_list = NULL; - // init spinlock - spinlock_init(&pbuddy->lock, "kbuddy"); - // init global kernel Buddy system pbuddy->mem_start = mem_start; pbuddy->mem_end = mem_end; @@ -183,6 +181,16 @@ void KBuddySysInit(struct KBuddy* pbuddy, uint32_t mem_start, uint32_t mem_end) doubleListNodeInit(&page->node); KBuddyPagesFree(pbuddy, page); } + + return true; +} + +void KBuddySysInit(struct KBuddy* pbuddy, uint32_t mem_start, uint32_t mem_end) +{ +#define MAX_NR_PAGES MAX_NR_FREE_PAGES + static struct KPage kern_free_pages[MAX_NR_PAGES]; + pbuddy->pages = kern_free_pages; + KBuddyInit(pbuddy, mem_start, mem_end); } char* KBuddyAlloc(struct KBuddy* pbuddy, uint32_t size) @@ -221,6 +229,13 @@ bool KBuddyFree(struct KBuddy* pbuddy, char* vaddr) return true; } +void KBuddyDestory(struct KBuddy* pbuddy) +{ + if (pbuddy->pages) { + kfree((void*)pbuddy->pages); + } +} + void KFreePagesInfo(struct KBuddy* pbuddy) { DEBUG("Buddy structure:"); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/memory/kalloc.c b/Ubiquitous/XiZi_AIoT/softkernel/memory/kalloc.c index 9ce64eaa3..1d7f272bc 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/memory/kalloc.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/memory/kalloc.c @@ -45,7 +45,7 @@ bool module_phymem_init() uint32_t user_freemem_start = PHY_USER_FREEMEM_BASE; uint32_t user_freemem_end = PHY_MEM_STOP; KBuddySysInit(&kern_virtmem_buddy, kern_freemem_start, kern_freemem_end); - KBuddySysInit(&user_phy_freemem_buddy, user_freemem_start, user_freemem_end); + KBuddyInit(&user_phy_freemem_buddy, user_freemem_start, user_freemem_end); LOG_PRINTF("Free memory organized done.\n"); return true; } diff --git a/Ubiquitous/XiZi_AIoT/softkernel/memory/pagetable.c b/Ubiquitous/XiZi_AIoT/softkernel/memory/pagetable.c index 0ad42a9e3..a2a054119 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/memory/pagetable.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/memory/pagetable.c @@ -293,6 +293,12 @@ void load_kern_pgdir(struct TraceTag* mmu_driver_tag, struct TraceTag* intr_driv // dev mem _map_pages((uintptr_t*)kern_pgdir.pd_addr, DEV_VRTMEM_BASE, DEV_PHYMEM_BASE, DEV_MEM_SZ, dev_attr); - // _p_pgtbl_mmu_access->LoadPgdir((uintptr_t)V2P(kern_pgdir.pd_addr)); - _p_pgtbl_mmu_access->LoadPgdirCrit((uintptr_t)V2P(kern_pgdir.pd_addr), intr_driver_tag); + _p_pgtbl_mmu_access->LoadPgdir((uintptr_t)V2P(kern_pgdir.pd_addr)); + // _p_pgtbl_mmu_access->LoadPgdirCrit((uintptr_t)V2P(kern_pgdir.pd_addr), intr_driver_tag); +} + +void secondary_cpu_load_kern_pgdir(struct TraceTag* mmu_driver_tag, struct TraceTag* intr_driver_tag) +{ + _p_pgtbl_mmu_access->LoadPgdir((uintptr_t)V2P(kern_pgdir.pd_addr)); + // _p_pgtbl_mmu_access->LoadPgdirCrit((uintptr_t)V2P(kern_pgdir.pd_addr), intr_driver_tag); } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/memory/share_page.c b/Ubiquitous/XiZi_AIoT/softkernel/memory/share_page.c index 3f6001114..081367e70 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/memory/share_page.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/memory/share_page.c @@ -91,27 +91,39 @@ static uintptr_t map_task_share_page(struct TaskMicroDescriptor* task, const uin struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag); struct MmuCommonDone* p_mmu_driver = AchieveResource(&right_group.mmu_driver_tag); - spinlock_lock(&task->lock); // map double vaddr page to support uniform ring buffer r/w - uintptr_t vaddr = alloc_share_page_addr(task, nr_pages * 2); - if (UNLIKELY(vaddr == 0)) { - spinlock_unlock(&task->lock); + uintptr_t vaddr = (uintptr_t)NULL; + if (task->massive_ipc_allocator != NULL) { + vaddr = (uintptr_t)KBuddyAlloc(task->massive_ipc_allocator, PAGE_SIZE * nr_pages * 2); + } else { + vaddr = alloc_share_page_addr(task, nr_pages * 2); + if (vaddr >= USER_IPC_USE_ALLOCATOR_WATERMARK) { + task->massive_ipc_allocator = (struct KBuddy*)slab_alloc(&xizi_task_manager.task_buddy_allocator); + KBuddyInit(task->massive_ipc_allocator, USER_IPC_USE_ALLOCATOR_WATERMARK, USER_IPC_SPACE_TOP); + if (!task->massive_ipc_allocator) { + ERROR("Alloc task buddy failed.\n"); + return (uintptr_t)NULL; + } + return map_task_share_page(task, paddr, nr_pages); + } + } + + if (UNLIKELY(vaddr == (uintptr_t)NULL)) { return (uintptr_t)NULL; } if (!xizi_pager.map_pages(task->pgdir.pd_addr, vaddr, paddr, nr_pages * PAGE_SIZE, false)) { - spinlock_unlock(&task->lock); return (uintptr_t)NULL; } if (!xizi_pager.map_pages(task->pgdir.pd_addr, vaddr + (nr_pages * PAGE_SIZE), paddr, nr_pages * PAGE_SIZE, false)) { xizi_pager.unmap_pages(task->pgdir.pd_addr, vaddr, nr_pages * PAGE_SIZE); - spinlock_unlock(&task->lock); return (uintptr_t)NULL; } - spinlock_unlock(&task->lock); if (task == cur_cpu()->task) { p_mmu_driver->TlbFlush(vaddr, 2 * nr_pages * PAGE_SIZE); + /// @todo clean range rather than all - p_dcache_done->flushall(); + // p_dcache_done->flushall(); + p_dcache_done->invalidateall(); // p_dcache_done->flush(vaddr, vaddr + 2 * nr_pages * PAGE_SIZE); } return vaddr; @@ -123,21 +135,21 @@ uintptr_t task_map_pages(struct TaskMicroDescriptor* task, const uintptr_t vaddr struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag); struct MmuCommonDone* p_mmu_driver = AchieveResource(&right_group.mmu_driver_tag); - spinlock_lock(&task->lock); bool ret = false; if (is_dev) { ret = xizi_pager.map_pages(task->pgdir.pd_addr, vaddr, paddr, nr_pages * PAGE_SIZE, true); } else { ret = xizi_pager.map_pages(task->pgdir.pd_addr, vaddr, paddr, nr_pages * PAGE_SIZE, false); } - spinlock_unlock(&task->lock); if (!ret) { return (uintptr_t)NULL; } if (task == cur_cpu()->task) { p_mmu_driver->TlbFlush(vaddr, nr_pages * PAGE_SIZE); + /// @todo clean range rather than all - p_dcache_done->flushall(); + // p_dcache_done->flushall(); + p_dcache_done->invalidateall(); // p_dcache_done->flush(vaddr, vaddr + nr_pages * PAGE_SIZE); } @@ -150,14 +162,17 @@ void unmap_task_share_pages(struct TaskMicroDescriptor* task, const uintptr_t ta struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag); struct MmuCommonDone* p_mmu_driver = AchieveResource(&right_group.mmu_driver_tag); - spinlock_lock(&task->lock); xizi_pager.unmap_pages(task->pgdir.pd_addr, task_vaddr, nr_pages * PAGE_SIZE); xizi_pager.unmap_pages(task->pgdir.pd_addr, task_vaddr + (nr_pages * PAGE_SIZE), nr_pages * PAGE_SIZE); - spinlock_unlock(&task->lock); + if (task_vaddr >= USER_IPC_USE_ALLOCATOR_WATERMARK) { + KBuddyFree(task->massive_ipc_allocator, (void*)task_vaddr); + } if (task == cur_cpu()->task) { p_mmu_driver->TlbFlush(task_vaddr, 2 * nr_pages * PAGE_SIZE); + /// @todo clean range rather than all - p_dcache_done->flushall(); + // p_dcache_done->flushall(); + p_dcache_done->invalidateall(); // p_dcache_done->flush(task_vaddr, task_vaddr + 2 * nr_pages * PAGE_SIZE); } } @@ -181,12 +196,14 @@ struct session_backend* create_share_pages(struct TaskMicroDescriptor* client, s uintptr_t client_vaddr = map_task_share_page(client, V2P_WO(kern_vaddr), nr_pages); if (UNLIKELY(client_vaddr == 0)) { kfree((char*)kern_vaddr); + slab_free(SessionAllocator(), session_backend); return NULL; } uintptr_t server_vaddr = map_task_share_page(server, V2P_WO(kern_vaddr), nr_pages); if (UNLIKELY(server_vaddr == 0)) { unmap_task_share_pages(client, client_vaddr, nr_pages); kfree((char*)kern_vaddr); + slab_free(SessionAllocator(), session_backend); return NULL; } @@ -200,20 +217,19 @@ struct session_backend* create_share_pages(struct TaskMicroDescriptor* client, s session_backend->client_side.buf_addr = client_vaddr; session_backend->client_side.capacity = true_capacity; session_backend->client_side.closed = false; - spinlock_lock(&client->lock); doubleListNodeInit(&session_backend->client_side.node); doubleListAddOnBack(&session_backend->client_side.node, &client->cli_sess_listhead); - spinlock_unlock(&client->lock); // init server side session struct session_backend->server_side.buf_addr = server_vaddr; session_backend->server_side.capacity = true_capacity; session_backend->server_side.head = 0; session_backend->server_side.tail = 0; session_backend->server_side.closed = false; - spinlock_lock(&server->lock); doubleListNodeInit(&session_backend->server_side.node); doubleListAddOnBack(&session_backend->server_side.node, &server->svr_sess_listhead); - spinlock_unlock(&server->lock); + + server->mem_size += true_capacity; + client->mem_size += true_capacity; return session_backend; } @@ -232,17 +248,16 @@ int delete_share_pages(struct session_backend* session_backend) /* unmap share pages */ if (session_backend->client) { - spinlock_lock(&session_backend->client->lock); doubleListDel(&session_backend->client_side.node); - spinlock_unlock(&session_backend->client->lock); } if (session_backend->server) { - spinlock_lock(&session_backend->server->lock); doubleListDel(&session_backend->server_side.node); - spinlock_unlock(&session_backend->server->lock); } + session_backend->server->mem_size -= session_backend->nr_pages * PAGE_SIZE; + session_backend->client->mem_size -= session_backend->nr_pages * PAGE_SIZE; + /* free seesion backend */ kfree((void*)session_backend->buf_kernel_addr); slab_free(SessionAllocator(), (void*)session_backend); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/Makefile b/Ubiquitous/XiZi_AIoT/softkernel/syscall/Makefile index 90620a162..4fd4eb8f8 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/Makefile +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/Makefile @@ -9,6 +9,7 @@ SRC_FILES := syscall.c \ sys_register_irq.c \ sys_exit.c \ sys_state.c \ - sys_mmap.c + sys_mmap.c \ + sys_kill.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_connect_session.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_connect_session.c index debfb86d3..178ef83e3 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_connect_session.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_connect_session.c @@ -35,13 +35,13 @@ Modification: #include "syscall.h" #include "task.h" -int create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, int capacity, struct Session* user_session) +struct session_backend* create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, int capacity, struct Session* user_session) { // create share pages struct session_backend* session_backend = xizi_share_page_manager.create_share_pages(client, server, capacity); if (UNLIKELY(session_backend == NULL)) { DEBUG("create_share_pages failed\n"); - return -1; + return NULL; } // init user_session @@ -51,7 +51,7 @@ int create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDes user_session->tail = 0; user_session->id = session_backend->session_id; - return 0; + return session_backend; } int sys_connect_session(char* path, int capacity, struct Session* user_session) @@ -70,11 +70,14 @@ int sys_connect_session(char* path, int capacity, struct Session* user_session) struct TraceTag server_tag; if (!AchieveResourceTag(&server_tag, &server_identifier_owner, path)) { - ERROR("Not server: %s\n", path); + DEBUG("Not server: %s\n", path); return -1; } struct TaskMicroDescriptor* server = AchieveResource(&server_tag); assert(server != NULL); - return create_session_inner(client, server, capacity, user_session); + if (create_session_inner(client, server, capacity, user_session) == NULL) { + return -1; + } + return 0; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_exec.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_exec.c index 2b0d9f5ac..b087fdb98 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_exec.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_exec.c @@ -66,18 +66,21 @@ Modification: /// @param path path to elf file /// @param argv arguments giving to main /// @return -int task_exec(struct TaskMicroDescriptor* task, struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv) +int task_exec(struct TaskMicroDescriptor* task, char* img_start, char* name, char** argv) { + /* load img to task */ + if (img_start == NULL) { + return -1; + } + /* 1. load elf header */ struct elfhdr elf; + memcpy((void*)&elf, img_start, sizeof(elf)); + if (elf.magic != ELF_MAGIC) { + return -1; + } + // pgdir for new task struct TopLevelPageDirectory pgdir; pgdir.pd_addr = NULL; - - if (ipc_read(session, fd, (char*)&elf, 0, sizeof(elf)) < sizeof(elf) || elf.magic != ELF_MAGIC) { - ERROR("invalide elf file.\n"); - goto error_exec; - } - - // pgdir for new task if (UNLIKELY(!xizi_pager.new_pgdir(&pgdir))) { ERROR("create new pgdir failed.\n"); goto error_exec; @@ -88,10 +91,8 @@ int task_exec(struct TaskMicroDescriptor* task, struct Session* session, int fd, uintptr_t load_size = 0; struct proghdr ph; for (int sec_idx = 0, off = elf.phoff; sec_idx < elf.phnum; sec_idx++, off += sizeof(ph)) { - if (ipc_read(session, fd, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) { - ERROR("Read elf header failed\n"); - goto error_exec; - } + // load proghdr + memcpy((char*)&ph, img_start + off, sizeof(ph)); if (ph.type != ELF_PROG_LOAD) continue; @@ -111,13 +112,11 @@ int task_exec(struct TaskMicroDescriptor* task, struct Session* session, int fd, for (int addr_offset = 0; addr_offset < ph.filesz; addr_offset += PAGE_SIZE) { uintptr_t page_paddr = xizi_pager.address_translate(&pgdir, ph.vaddr + addr_offset); if (page_paddr == 0) { - panic("copy elf file to unmapped addr"); - } - uintptr_t read_size = (ph.filesz - addr_offset < PAGE_SIZE ? ph.filesz - addr_offset : PAGE_SIZE); - if (read_size != ipc_read(session, fd, P2V(page_paddr), ph.off + addr_offset, read_size)) { - ERROR("read size error, off: %d, read len: %d\n", ph.off + addr_offset, read_size); + ERROR("copy elf file to unmapped addr\n"); goto error_exec; } + uintptr_t read_size = (ph.filesz - addr_offset < PAGE_SIZE ? ph.filesz - addr_offset : PAGE_SIZE); + memcpy(P2V(page_paddr), img_start + (ph.off + addr_offset), read_size); } } @@ -176,13 +175,12 @@ int task_exec(struct TaskMicroDescriptor* task, struct Session* session, int fd, } strncpy(task->name, last, sizeof(task->name)); - struct TopLevelPageDirectory old_pgdir = task->pgdir; + if (task->pgdir.pd_addr != NULL) { + xizi_pager.free_user_pgdir(&task->pgdir); + } task->pgdir = pgdir; - - /// @todo record mem size used b task - task->mem_size = ALIGNUP(load_size, PAGE_SIZE); - - xizi_pager.free_user_pgdir(&old_pgdir); + task->heap_base = ALIGNUP(load_size, PAGE_SIZE); + task->mem_size = task->heap_base + USER_STACK_SIZE; return 0; error_exec: @@ -193,7 +191,7 @@ error_exec: return -1; } -int sys_exec(struct KernReadTool* read_tool, char* name, char** argv) +int sys_exec(char* img_start, char* name, char** argv) { /// @todo find a source of mmu_driver_tag instead of requiring from root static struct TraceTag mmu_driver_tag; @@ -204,14 +202,9 @@ int sys_exec(struct KernReadTool* read_tool, char* name, char** argv) } struct MmuCommonDone* p_mmu_driver = AchieveResource(&mmu_driver_tag); - struct TaskMicroDescriptor* current_task = cur_cpu()->task; - struct Session* session = read_tool->session; - int fd = read_tool->fd; - ipc_read_fn ipc_read = read_tool->ipc_read; - int ret = task_exec(current_task, session, fd, ipc_read, name, argv); + int ret = task_exec(current_task, img_start, name, argv); if (ret >= 0) { - spinlock_init(¤t_task->lock, current_task->name); p_mmu_driver->LoadPgdir((uintptr_t)V2P(current_task->pgdir.pd_addr)); return ret; } diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_exit.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_exit.c index b318f9843..ca5384910 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_exit.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_exit.c @@ -36,58 +36,10 @@ Modification: #include "syscall.h" #include "task.h" -int sys_exit() +int sys_exit(struct TaskMicroDescriptor* ptask) { - - struct TaskMicroDescriptor* cur_task = cur_cpu()->task; - assert(cur_task != NULL); - - /* handle sessions for condition 1, ref. delete_share_pages() */ - // close all server_sessions - struct server_session* server_session = NULL; - while (!IS_DOUBLE_LIST_EMPTY(&cur_task->svr_sess_listhead)) { - server_session = CONTAINER_OF(cur_task->svr_sess_listhead.next, struct server_session, node); - // cut the connection from task to session - if (!server_session->closed) { - xizi_share_page_manager.unmap_task_share_pages(cur_task, server_session->buf_addr, CLIENT_SESSION_BACKEND(server_session)->nr_pages); - server_session->closed = true; - } - doubleListDel(&server_session->node); - SERVER_SESSION_BACKEND(server_session)->server = NULL; - // delete session (also cut connection from session to task) - if (SERVER_SESSION_BACKEND(server_session)->client_side.closed) { - xizi_share_page_manager.delete_share_pages(SERVER_SESSION_BACKEND(server_session)); - } - } - // close all client_sessions - struct client_session* client_session = NULL; - while (!IS_DOUBLE_LIST_EMPTY(&cur_task->cli_sess_listhead)) { - client_session = CONTAINER_OF(cur_task->cli_sess_listhead.next, struct client_session, node); - // cut the connection from task to session - if (!client_session->closed) { - xizi_share_page_manager.unmap_task_share_pages(cur_task, client_session->buf_addr, CLIENT_SESSION_BACKEND(client_session)->nr_pages); - client_session->closed = true; - } - doubleListDel(&client_session->node); - CLIENT_SESSION_BACKEND(client_session)->client = NULL; - // delete session (also cut connection from session to task) - if (CLIENT_SESSION_BACKEND(client_session)->server_side.closed) { - xizi_share_page_manager.delete_share_pages(CLIENT_SESSION_BACKEND(client_session)); - } - } - - if (cur_task->server_identifier.meta != NULL) { - struct TraceTag server_identifier_owner; - AchieveResourceTag(&server_identifier_owner, RequireRootTag(), "softkernel/server-identifier"); - assert(server_identifier_owner.meta != NULL); - DeleteResource(&cur_task->server_identifier, &server_identifier_owner); - } - - // delete task for pcb_list - xizi_task_manager.cur_task_yield_noschedule(); - spinlock_lock(&cur_task->lock); - cur_task->state = DEAD; - spinlock_unlock(&cur_task->lock); - + assert(ptask != NULL); + ptask->dead = true; + xizi_task_manager.task_yield_noschedule(cur_cpu()->task, false); return 0; -} \ No newline at end of file +} diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_kill.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_kill.c new file mode 100644 index 000000000..5d9bef5c8 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_kill.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +/** + * @file sys_kill.c + * @brief task exit syscall + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2024.03.19 + */ + +/************************************************* +File name: sys_kill.c +Description: task kill syscall +Others: +History: +1. Date: 2023-03-19 +Author: AIIT XUOS Lab +Modification: +1. first version +*************************************************/ +#include "trap_common.h" + +#include "task.h" + +extern int sys_exit(struct TaskMicroDescriptor* task); +int sys_kill(int id) +{ + struct TaskMicroDescriptor* task = NULL; + + for (int prio = 0; prio < TASK_MAX_PRIORITY; prio++) { + DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_list_head[prio], node) + { + if (task->pid == id) { + sys_exit(task); + return 0; + } + } + } + + return -1; +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_mmap.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_mmap.c index 0b11adc62..3b2f7e727 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_mmap.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_mmap.c @@ -63,5 +63,7 @@ int sys_mmap(uintptr_t vaddr, uintptr_t paddr, int len, int is_dev) load_len += PAGE_SIZE; } } + + cur_task->mem_size += true_len; return vaddr + true_len; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_poll_session.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_poll_session.c index e1b826a08..4a9eb2999 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_poll_session.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_poll_session.c @@ -41,8 +41,6 @@ int sys_poll_session(struct Session* userland_session_arr, int arr_capacity) return -1; } - spinlock_lock(&cur_task->lock); - struct double_list_node* cur_node = NULL; struct server_session* server_session = NULL; /* update old sessions */ @@ -54,52 +52,44 @@ int sys_poll_session(struct Session* userland_session_arr, int arr_capacity) server_session = CONTAINER_OF(cur_node, struct server_session, node); if (UNLIKELY(server_session->buf_addr != (uintptr_t)userland_session_arr[i].buf)) { ERROR("mismatched old session addr, user buf: %x, server buf: %x\n", userland_session_arr[i].buf, server_session->buf_addr); - spinlock_unlock(&cur_task->lock); return -1; } // update session_backend + // if current session is handled + if (server_session->head != userland_session_arr[i].head) { + struct TaskMicroDescriptor* client = SERVER_SESSION_BACKEND(server_session)->client; + if (client->state == BLOCKED) { + xizi_task_manager.task_unblock(client); + } else { + client->current_ipc_handled = true; + } + } server_session->head = userland_session_arr[i].head; server_session->tail = userland_session_arr[i].tail; doubleListDel(cur_node); doubleListAddOnBack(cur_node, &cur_task->svr_sess_listhead); } - spinlock_unlock(&cur_task->lock); - - /* handle sessions for condition 2, ref. delete_share_pages() */ - bool has_delete = true; - while (has_delete) { - has_delete = false; - - spinlock_lock(&cur_task->lock); - DOUBLE_LIST_FOR_EACH_ENTRY(server_session, &cur_task->svr_sess_listhead, node) - { - if (SERVER_SESSION_BACKEND(server_session)->client_side.closed) { - // client had closed it, then server will close it too - struct session_backend* session_backend = SERVER_SESSION_BACKEND(server_session); - - spinlock_unlock(&cur_task->lock); - if (!session_backend->server_side.closed) { - session_backend->server_side.closed = true; - xizi_share_page_manager.unmap_task_share_pages(cur_task, session_backend->server_side.buf_addr, session_backend->nr_pages); - } - xizi_share_page_manager.delete_share_pages(session_backend); - has_delete = true; - break; - } - } - if (!has_delete) { - spinlock_unlock(&cur_task->lock); - } - } /* poll with new sessions */ - spinlock_lock(&cur_task->lock); int i = 0; DOUBLE_LIST_FOR_EACH_ENTRY(server_session, &cur_task->svr_sess_listhead, node) { if (i >= arr_capacity) { break; } + + if (SERVER_SESSION_BACKEND(server_session)->client_side.closed) { + // client had closed it, then server will close it too + struct session_backend* session_backend = SERVER_SESSION_BACKEND(server_session); + + if (!session_backend->server_side.closed) { + session_backend->server_side.closed = true; + xizi_share_page_manager.unmap_task_share_pages(cur_task, session_backend->server_side.buf_addr, session_backend->nr_pages); + } + xizi_share_page_manager.delete_share_pages(session_backend); + break; + } + userland_session_arr[i++] = (struct Session) { .buf = (void*)server_session->buf_addr, .capacity = server_session->capacity, @@ -111,7 +101,6 @@ int sys_poll_session(struct Session* userland_session_arr, int arr_capacity) if (LIKELY(i < arr_capacity)) { userland_session_arr[i].buf = 0; } - spinlock_unlock(&cur_task->lock); return 0; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c index 1e96a65c3..e7e0eb8cc 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c @@ -34,55 +34,90 @@ Modification: #include "actracer.h" #include "assert.h" #include "ipc.h" +#include "kalloc.h" +#include "mmu_common.h" #include "multicores.h" #include "share_page.h" #include "syscall.h" #include "task.h" -static struct TaskMicroDescriptor kernel_irq_proxy; +static struct TaskMicroDescriptor* kernel_irq_proxy; static struct { struct TaskMicroDescriptor* handle_task; - struct Session* session; + struct Session session; + struct session_backend* p_kernel_session; int opcode; } irq_forward_table[NR_IRQS]; static void send_irq_to_user(int irq_num) { + struct Session* session = &irq_forward_table[irq_num].session; int len = IPC_ARG_INFO_BASE_OFFSET; - /* add session tail */ - struct IpcMsg* buf = irq_forward_table[irq_num].session->buf + irq_forward_table[irq_num].session->tail; - irq_forward_table[irq_num].session->tail += len; + len += sizeof(struct IpcArgInfo); + + /* get message space and add session tail */ + void* session_kern_vaddr = P2V(xizi_pager.address_translate(&kernel_irq_proxy->pgdir, (uintptr_t)session->buf)); + struct IpcMsg* buf = session_kern_vaddr + session->tail; + + /* check if server session is full */ + if (buf->header.magic == IPC_MSG_MAGIC && buf->header.done == 0) { + DEBUG("irq server cannot handle new interrupt by now.\n"); + return; + } memset((void*)buf, 0, len); + session->tail = (session->tail + len) % session->capacity; + /* construct message */ buf->header.len = len; - buf->header.nr_args = 0; + buf->header.nr_args = 1; buf->header.init = 1; buf->header.opcode = irq_forward_table[irq_num].opcode; buf->header.done = 0; buf->header.magic = IPC_MSG_MAGIC; buf->header.valid = 1; + /* add session head */ - irq_forward_table[irq_num].session->head += len; + session->head = (session->head + len) % session->capacity; } int user_irq_handler(int irq, void* tf, void* arg) { - send_irq_to_user(irq); - next_task_emergency = irq_forward_table[irq].handle_task; - xizi_task_manager.cur_task_yield_noschedule(); + if (irq_forward_table[irq].handle_task != NULL) { + send_irq_to_user(irq); + + next_task_emergency = irq_forward_table[irq].handle_task; + if (cur_cpu()->task != NULL) { + xizi_task_manager.task_yield_noschedule(cur_cpu()->task, false); + } + } return 0; } -extern int create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, int capacity, struct Session* user_session); +extern struct session_backend* create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, int capacity, struct Session* user_session); +/// @warning no tested. + +static struct XiziTrapDriver* p_intr_driver = NULL; int sys_register_irq(int irq_num, int irq_opcode) { - static struct TraceTag intr_ac_tag; - if (!AchieveResourceTag(&intr_ac_tag, RequireRootTag(), "hardkernel/intr-ac-resource")) { - ERROR("intr not initialized.\n"); - return -1; + // init intr resource; + if (p_intr_driver == NULL) { + struct TraceTag intr_ac_tag; + if (!AchieveResourceTag(&intr_ac_tag, RequireRootTag(), "hardkernel/intr-ac-resource")) { + ERROR("intr not initialized.\n"); + return -1; + } + p_intr_driver = (struct XiziTrapDriver*)AchieveResource(&intr_ac_tag); } - struct XiziTrapDriver* p_intr_driver = AchieveResource(&intr_ac_tag); + // init kerenl sender proxy + if (kernel_irq_proxy == NULL) { + kernel_irq_proxy = xizi_task_manager.new_task_cb(); + kernel_irq_proxy->state = NEVER_RUN; + xizi_pager.new_pgdir(&kernel_irq_proxy->pgdir); + memcpy(kernel_irq_proxy->pgdir.pd_addr, kern_pgdir.pd_addr, TOPLEVLE_PAGEDIR_SIZE); + } + + // bind irq to session if (p_intr_driver->sw_irqtbl[irq_num].handler != NULL) { ERROR("irq %d is occupied.\n", irq_num); return -1; @@ -90,8 +125,32 @@ int sys_register_irq(int irq_num, int irq_opcode) struct TaskMicroDescriptor* cur_task = cur_cpu()->task; irq_forward_table[irq_num].handle_task = cur_task; irq_forward_table[irq_num].opcode = irq_opcode; - create_session_inner(&kernel_irq_proxy, cur_task, PAGE_SIZE, irq_forward_table[irq_num].session); + irq_forward_table[irq_num].p_kernel_session = create_session_inner(kernel_irq_proxy, cur_task, PAGE_SIZE, &irq_forward_table[irq_num].session); p_intr_driver->bind_irq_handler(irq_num, user_irq_handler); + cur_task->bind_irq = true; + return 0; +} + +int sys_unbind_irq(struct TaskMicroDescriptor* task, int irq_num) +{ + if (irq_forward_table[irq_num].handle_task != task) { + return -1; + } + + irq_forward_table[irq_num].handle_task = NULL; + sys_close_session(&irq_forward_table[irq_num].session); + DEBUG("Unbind: %s to irq %d", task->name, irq_num); + return 0; +} + +int sys_unbind_irq_all(struct TaskMicroDescriptor* task) +{ + for (int idx = 0; idx < NR_IRQS; idx++) { + if (irq_forward_table[idx].handle_task == task) { + sys_unbind_irq(task, idx); + } + } + task->bind_irq = false; return 0; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c index 6abb8b643..3d473e61b 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c @@ -33,8 +33,8 @@ Modification: #include "syscall.h" #include "task.h" -extern int task_exec(struct TaskMicroDescriptor* task, struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv); -int sys_spawn(struct KernReadTool* read_tool, char* name, char** argv) +extern int task_exec(struct TaskMicroDescriptor* task, char* img_start, char* name, char** argv); +int sys_spawn(char* img_start, char* name, char** argv) { // alloc a new pcb struct TaskMicroDescriptor* new_task_cb = xizi_task_manager.new_task_cb(); @@ -44,16 +44,12 @@ int sys_spawn(struct KernReadTool* read_tool, char* name, char** argv) } // init trapframe arch_init_trapframe(new_task_cb->main_thread.trapframe, 0, 0); - - struct Session* session = read_tool->session; - int fd = read_tool->fd; - ipc_read_fn ipc_read = read_tool->ipc_read; - if (UNLIKELY(task_exec(new_task_cb, session, fd, ipc_read, name, argv)) < 0) { + if (UNLIKELY(task_exec(new_task_cb, img_start, name, argv)) < 0) { xizi_task_manager.free_pcb(new_task_cb); return -1; } // init pcb - xizi_task_manager.task_set_default_schedule_attr(new_task_cb, RequireRootTag()); + xizi_task_manager.task_set_default_schedule_attr(new_task_cb); return 0; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_state.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_state.c index ff25885c5..01309cb22 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_state.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_state.c @@ -55,8 +55,17 @@ static inline void _padding(char* name) void show_tasks(void) { struct TaskMicroDescriptor* task = NULL; - DEBUG_PRINTF("******************************************************\n"); - DEBUG_PRINTF("STAT ID TASK PRI LEFT_TICKS\n"); + LOG_PRINTF("******************************************************\n"); + for (int i = 0; i < NR_CPU; i++) { + LOG_PRINTF("CPU %d: ", i); + if (global_cpus[i].task != NULL) { + LOG_PRINTF("%s\n", global_cpus[i].task->name); + } else { + LOG_PRINTF("NULL\n"); + } + } + LOG_PRINTF("******************************************************\n"); + LOG_PRINTF("STAT ID TASK PRI MEM(KB)\n"); for (int i = 0; i < TASK_MAX_PRIORITY; i++) { if (IS_DOUBLE_LIST_EMPTY(&xizi_task_manager.task_list_head[i])) { continue; @@ -64,19 +73,27 @@ void show_tasks(void) DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_list_head[i], node) { if (task->state == INIT) - DEBUG_PRINTF(" INIT "); + LOG_PRINTF(" INIT "); else if (task->state == READY) - DEBUG_PRINTF(" READY "); + LOG_PRINTF(" READY "); else if (task->state == RUNNING) - DEBUG_PRINTF("RUNNING "); + LOG_PRINTF("RUNNING "); else if (task->state == DEAD) - DEBUG_PRINTF(" DEAD "); + LOG_PRINTF(" DEAD "); _padding(task->name); - DEBUG_PRINTF(" %d %s %d %d\n", task->pid, task->name, task->priority, task->remain_tick); + LOG_PRINTF(" %d %s %d %d\n", task->pid, task->name, task->priority, task->mem_size >> 10); } } - DEBUG_PRINTF("******************************************************\n"); + + DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_blocked_list_head, node) + { + LOG_PRINTF(" BLOCK "); + _padding(task->name); + LOG_PRINTF(" %d %s %d %d\n", task->pid, task->name, task->priority, task->mem_size >> 10); + } + + LOG_PRINTF("******************************************************\n"); return; } @@ -85,8 +102,8 @@ extern struct KBuddy kern_virtmem_buddy; extern uint32_t kernel_data_end[]; void show_mem(void) { - DEBUG_PRINTF("*********************************************************\n"); - DEBUG_PRINTF(" TOTAL(KB) USED(KB) FREE(KB) \n"); + LOG_PRINTF("*********************************************************\n"); + LOG_PRINTF(" TOTAL(KB) USED(KB) FREE(KB) \n"); uint32_t total = (PHY_MEM_STOP - V2P(kernel_data_end)) >> 10; uint32_t used = 0; @@ -96,14 +113,14 @@ void show_mem(void) } used = used >> 10; - DEBUG_PRINTF(" %d %d %d\n", total, total - used, used); - DEBUG_PRINTF("*********************************************************\n"); + LOG_PRINTF(" %d %d %d\n", total, total - used, used); + LOG_PRINTF("*********************************************************\n"); return; } void show_cpu(void) { - DEBUG_PRINTF("**********************************************************\n"); + LOG_PRINTF("**********************************************************\n"); #ifdef ARCH_SMP /// @todo support smp KPrintf(" cpu VALUE \n"); @@ -116,10 +133,10 @@ void show_cpu(void) _padding(current_task->name); - DEBUG_PRINTF(" ID COMMAND USED_TICKS FREE_TICKS \n"); - DEBUG_PRINTF(" %d %s %d %d\n", cpu_id, current_task->name, TASK_CLOCK_TICK - current_task->remain_tick, current_task->remain_tick); + LOG_PRINTF(" ID COMMAND USED_TICKS FREE_TICKS \n"); + LOG_PRINTF(" %d %s %d %d\n", cpu_id, current_task->name, TASK_CLOCK_TICK - current_task->remain_tick, current_task->remain_tick); - DEBUG_PRINTF("***********************************************************\n"); + LOG_PRINTF("***********************************************************\n"); return; } @@ -129,7 +146,7 @@ int sys_state(sys_state_option option, sys_state_info* info) info->memblock_info.memblock_start = (uintptr_t)V2P(_binary_fs_img_start); info->memblock_info.memblock_end = (uintptr_t)V2P(_binary_fs_img_end); } else if (option == SYS_STATE_GET_HEAP_BASE) { - return cur_cpu()->task->mem_size; + return cur_cpu()->task->heap_base; } else if (option == SYS_STATE_SET_TASK_PRIORITY) { xizi_task_manager.set_cur_task_priority(info->priority); } else if (option == SYS_STATE_SHOW_TASKS) { diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_yield.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_yield.c index 6aa426047..7db762765 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_yield.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_yield.c @@ -33,8 +33,18 @@ Modification: #include "log.h" -int sys_yield() +int sys_yield(task_yield_reason reason) { - xizi_task_manager.cur_task_yield_noschedule(); + struct TaskMicroDescriptor* cur_task = cur_cpu()->task; + xizi_task_manager.task_yield_noschedule(cur_task, false); + + // handle ipc block + if ((reason & SYS_TASK_YIELD_BLOCK_IPC) != 0) { + if (cur_task->current_ipc_handled) { + cur_task->current_ipc_handled = false; + } else { + xizi_task_manager.task_block(cur_task); + } + } return 0; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/syscall.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/syscall.c index 4dd7660ff..2a4a29248 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/syscall.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/syscall.c @@ -28,6 +28,7 @@ Modification: 1. first version *************************************************/ #include "log.h" +#include "multicores.h" #include "trap_common.h" #include "syscall.h" @@ -41,13 +42,13 @@ int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, u ret = 0; break; case SYSCALL_SPAWN: - ret = sys_spawn((struct KernReadTool*)param1, (char*)param2, (char**)param3); + ret = sys_spawn((char*)param1, (char*)param2, (char**)param3); break; case SYSCALL_EXIT: - ret = sys_exit(); + ret = sys_exit(cur_cpu()->task); break; case SYSCALL_YIELD: - ret = sys_yield(); + ret = sys_yield((task_yield_reason)param1); break; case SYSCALL_SERVER: ret = sys_register_as_server((char*)param1); @@ -62,7 +63,7 @@ int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, u ret = sys_close_session((struct Session*)param1); break; case SYSCALL_EXEC: - ret = sys_exec((struct KernReadTool*)param1, (char*)param2, (char**)param3); + ret = sys_exec((char*)param1, (char*)param2, (char**)param3); break; case SYSCALL_SYS_STATE: ret = sys_state(param1, (sys_state_info*)param2); @@ -73,6 +74,9 @@ int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, u case SYSCALL_REGISTER_IRQ: ret = sys_register_irq((int)param1, (int)param2); break; + case SYSCALL_KILL: + ret = sys_kill((int)param1); + break; default: ERROR("Unsurport syscall(%d) right now\n", sys_num); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/Makefile b/Ubiquitous/XiZi_AIoT/softkernel/task/Makefile index 94bd1ecf3..a0f5db6ae 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/task/Makefile +++ b/Ubiquitous/XiZi_AIoT/softkernel/task/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := task.c scheduler.c spawn_default_task.c +SRC_FILES := task.c schedule.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/scheduler.c b/Ubiquitous/XiZi_AIoT/softkernel/task/schedule.c similarity index 75% rename from Ubiquitous/XiZi_AIoT/softkernel/task/scheduler.c rename to Ubiquitous/XiZi_AIoT/softkernel/task/schedule.c index bfddb0c32..a19d6a50d 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/task/scheduler.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/task/schedule.c @@ -38,20 +38,13 @@ struct TaskMicroDescriptor* max_priority_runnable_task(void) DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_list_head[priority], node) { - spinlock_lock(&task->lock); - if (task->state == READY) { + if (task->state == READY && !task->dead) { // found a runnable task, stop this look up - task->state = RUNNING; - spinlock_unlock(&task->lock); return task; - } else if (task->state == DEAD) { - // found a killed task, stop this loop - // change in pcb_list may break this loop, so find a runnable in next look up - spinlock_unlock(&task->lock); + } else if (task->dead && task->state != RUNNING) { xizi_task_manager.free_pcb(task); return NULL; } - spinlock_unlock(&task->lock); } return NULL; } @@ -62,21 +55,13 @@ struct TaskMicroDescriptor* round_robin_runnable_task(uint32_t priority) DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_list_head[priority], node) { - - spinlock_lock(&task->lock); - if (task->state == READY) { + if (task->state == READY && !task->dead) { // found a runnable task, stop this look up - spinlock_unlock(&task->lock); - task->state = RUNNING; return task; - } else if (task->state == DEAD) { - // found a killed task, stop this loop - // change in pcb_list may break this loop, so find a runnable in next look up - spinlock_unlock(&task->lock); + } else if (task->dead && task->state != RUNNING) { xizi_task_manager.free_pcb(task); return NULL; } - spinlock_unlock(&task->lock); } return NULL; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/spawn_default_task.c b/Ubiquitous/XiZi_AIoT/softkernel/task/spawn_default_task.c deleted file mode 100644 index 8e1cd6e42..000000000 --- a/Ubiquitous/XiZi_AIoT/softkernel/task/spawn_default_task.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2020 AIIT XUOS Lab - * XiUOS is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ -/** - * @file spawn_default_task.c - * @brief spawn task that embeded in kernel image - * @version 3.0 - * @author AIIT XUOS Lab - * @date 2023.08.25 - */ - -/************************************************* -File name: spawn_default_task.c -Description: spawn task that embeded in kernel image -Others: -History: -1. Date: 2023-08-28 -Author: AIIT XUOS Lab -Modification: -1. first version -*************************************************/ -#include "actracer.h" -#include "assert.h" -#include "kalloc.h" -#include "task.h" - -#include "execelf.h" - -int spawn_embedded_task(char* img_start, char* name, char** argv) -{ - struct TaskMicroDescriptor* new_task_cb = xizi_task_manager.new_task_cb(); - if (UNLIKELY(!new_task_cb)) { - ERROR("Unable to new task control block.\n"); - return -1; - } - // init trapframe - arch_init_trapframe(new_task_cb->main_thread.trapframe, 0, 0); - - /* load img to task */ - /* 1. load elf header */ - struct elfhdr* elf = (struct elfhdr*)img_start; - // pgdir for new task - struct TopLevelPageDirectory pgdir; - if (UNLIKELY(!xizi_pager.new_pgdir(&pgdir))) { - ERROR("create new pgdir failed.\n"); - goto error_exec; - } - memcpy(pgdir.pd_addr, kern_pgdir.pd_addr, TOPLEVLE_PAGEDIR_SIZE); - - /* 2. load elf content */ - uint32_t load_size = 0; - struct proghdr ph; - for (int sec_idx = 0, off = elf->phoff; sec_idx < elf->phnum; sec_idx++, off += sizeof(ph)) { - // load proghdr - memcpy((char*)&ph, img_start + off, sizeof(ph)); - - if (ph.type != ELF_PROG_LOAD) - continue; - if (ph.memsz < ph.filesz) { - ERROR("elf header mem size less than file size\n"); - goto error_exec; - } - - // read section - // 1. alloc space - if ((load_size = xizi_pager.resize_user_pgdir(&pgdir, load_size, ph.vaddr + ph.memsz)) - != ph.vaddr + ph.memsz) { - goto error_exec; - } - // 2. copy inode to space - assert(ph.vaddr % PAGE_SIZE == 0); - for (int addr_offset = 0; addr_offset < ph.filesz; addr_offset += PAGE_SIZE) { - uintptr_t page_paddr = xizi_pager.address_translate(&pgdir, ph.vaddr + addr_offset); - if (page_paddr == 0) { - panic("copy elf file to unmapped addr"); - } - uintptr_t read_size = (ph.filesz - addr_offset < PAGE_SIZE ? ph.filesz - addr_offset : PAGE_SIZE); - memcpy(P2V(page_paddr), img_start + (ph.off + addr_offset), read_size); - } - } - - /// elf file content now in memory - // alloc stack page and map to TOP of user vspace - uintptr_t* stack_bottom = (uintptr_t*)kalloc(USER_STACK_SIZE); - if (UNLIKELY(stack_bottom == NULL)) { - ERROR("No memory.\n"); - goto error_exec; - } - xizi_pager.map_pages(pgdir.pd_addr, USER_MEM_TOP - USER_STACK_SIZE, V2P(stack_bottom), USER_STACK_SIZE, false); - - uintptr_t user_vspace_sp = USER_MEM_TOP; - /// @todo change 32 to some macro - uintptr_t user_stack_init[32]; - uintptr_t argc = 0; - uintptr_t copy_len = 0; - for (argc = 0; argv != NULL && argv[argc] != NULL; argc++) { - /// @todo handle with large number of parameters - - // copy param to user stack - copy_len = strlen(argv[argc]) + 1; - user_vspace_sp = (user_vspace_sp - copy_len) & ~3; - uintptr_t copied_len = xizi_pager.cross_vspace_data_copy(&pgdir, user_vspace_sp, (uintptr_t)argv[argc], copy_len); - if (UNLIKELY(copied_len != copy_len)) { - ERROR("Something went wrong when copying params.\n"); - goto error_exec; - } - user_stack_init[argc] = user_vspace_sp; - } - user_stack_init[argc] = 0; - copy_len = (argc + 1) * sizeof(uintptr_t); - user_vspace_sp -= copy_len; - uintptr_t copied_len = xizi_pager.cross_vspace_data_copy(&pgdir, user_vspace_sp, (uintptr_t)user_stack_init, copy_len); - if (UNLIKELY(copied_len != copy_len)) { - ERROR("Something went wrong when copying params.\n"); - goto error_exec; - } - - // init task trapframe, which stores in svc stack - // do not go tp error_exec once we change trapframe! - assert(copied_len == (argc + 1) * sizeof(uintptr_t)); - arch_trapframe_set_sp_pc(new_task_cb->main_thread.trapframe, user_vspace_sp, elf->entry); - arch_set_main_params(new_task_cb->main_thread.trapframe, argc, user_vspace_sp); - - // save program name - strncpy(new_task_cb->name, name, sizeof(new_task_cb->name)); - - struct TopLevelPageDirectory old_pgdir = new_task_cb->pgdir; - new_task_cb->pgdir = pgdir; - - /// @todo record mem size used b task - new_task_cb->mem_size = ALIGNUP(load_size, PAGE_SIZE); - - xizi_pager.free_user_pgdir(&old_pgdir); - - xizi_task_manager.task_set_default_schedule_attr(new_task_cb, RequireRootTag()); - return 0; - -error_exec: - if (pgdir.pd_addr != NULL) { - xizi_pager.free_user_pgdir(&pgdir); - } - return -1; -} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/task.c b/Ubiquitous/XiZi_AIoT/softkernel/task/task.c index b90cc944e..b7133e3fe 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/task/task.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/task/task.c @@ -32,10 +32,11 @@ Modification: #include "core.h" #include "assert.h" +#include "kalloc.h" #include "log.h" #include "multicores.h" -#include "kalloc.h" #include "scheduler.h" +#include "syscall.h" #include "task.h" struct CPU global_cpus[NR_CPU]; @@ -43,14 +44,14 @@ uint32_t ready_task_priority; static void _task_manager_init() { - // init lock for task list - spinlock_init(&xizi_task_manager.lock, "proclist"); // init task list to NULL for (int i = 0; i < TASK_MAX_PRIORITY; i++) { doubleListNodeInit(&xizi_task_manager.task_list_head[i]); } + doubleListNodeInit(&xizi_task_manager.task_blocked_list_head); // init task (slab) allocator slab_init(&xizi_task_manager.task_allocator, sizeof(struct TaskMicroDescriptor)); + slab_init(&xizi_task_manager.task_buddy_allocator, sizeof(struct KBuddy)); // pid pool xizi_task_manager.next_pid = 0; @@ -62,24 +63,72 @@ static void _task_manager_init() /// @brief alloc a new task without init static struct TaskMicroDescriptor* _alloc_task_cb() { - spinlock_lock(&xizi_task_manager.lock); // alloc task and add it to used task list struct TaskMicroDescriptor* task = (struct TaskMicroDescriptor*)slab_alloc(&xizi_task_manager.task_allocator); if (UNLIKELY(task == NULL)) { ERROR("Not enough memory\n"); - spinlock_unlock(&xizi_task_manager.lock); return NULL; } // set pid once task is allocated memset(task, 0, sizeof(*task)); task->pid = xizi_task_manager.next_pid++; - // update pcb used - xizi_task_manager.nr_pcb_used += 1; - spinlock_unlock(&xizi_task_manager.lock); return task; } +int _task_retrieve_sys_resources(struct TaskMicroDescriptor* ptask) +{ + assert(ptask != NULL); + + /* handle sessions for condition 1, ref. delete_share_pages() */ + // close all server_sessions + struct server_session* server_session = NULL; + while (!IS_DOUBLE_LIST_EMPTY(&ptask->svr_sess_listhead)) { + server_session = CONTAINER_OF(ptask->svr_sess_listhead.next, struct server_session, node); + // cut the connection from task to session + if (!server_session->closed) { + xizi_share_page_manager.unmap_task_share_pages(ptask, server_session->buf_addr, CLIENT_SESSION_BACKEND(server_session)->nr_pages); + server_session->closed = true; + } + doubleListDel(&server_session->node); + SERVER_SESSION_BACKEND(server_session)->server = NULL; + // delete session (also cut connection from session to task) + if (SERVER_SESSION_BACKEND(server_session)->client_side.closed) { + xizi_share_page_manager.delete_share_pages(SERVER_SESSION_BACKEND(server_session)); + } + } + // close all client_sessions + struct client_session* client_session = NULL; + while (!IS_DOUBLE_LIST_EMPTY(&ptask->cli_sess_listhead)) { + client_session = CONTAINER_OF(ptask->cli_sess_listhead.next, struct client_session, node); + // cut the connection from task to session + if (!client_session->closed) { + xizi_share_page_manager.unmap_task_share_pages(ptask, client_session->buf_addr, CLIENT_SESSION_BACKEND(client_session)->nr_pages); + client_session->closed = true; + } + doubleListDel(&client_session->node); + CLIENT_SESSION_BACKEND(client_session)->client = NULL; + // delete session (also cut connection from session to task) + if (CLIENT_SESSION_BACKEND(client_session)->server_side.closed) { + xizi_share_page_manager.delete_share_pages(CLIENT_SESSION_BACKEND(client_session)); + } + } + + if (ptask->server_identifier.meta != NULL) { + struct TraceTag server_identifier_owner; + AchieveResourceTag(&server_identifier_owner, RequireRootTag(), "softkernel/server-identifier"); + assert(server_identifier_owner.meta != NULL); + DeleteResource(&ptask->server_identifier, &server_identifier_owner); + } + + // delete registered irq if there is one + if (ptask->bind_irq) { + sys_unbind_irq_all(ptask); + } + + return 0; +} + /// @brief this function changes task list without locking, so it must be called inside a lock critical area /// @param task static void _dealloc_task_cb(struct TaskMicroDescriptor* task) @@ -89,6 +138,8 @@ static void _dealloc_task_cb(struct TaskMicroDescriptor* task) return; } + _task_retrieve_sys_resources(task); + // stack is mapped in vspace, so it should be free by pgdir if (task->pgdir.pd_addr) { xizi_pager.free_user_pgdir(&task->pgdir); @@ -102,8 +153,11 @@ static void _dealloc_task_cb(struct TaskMicroDescriptor* task) doubleListDel(cur_node); // free task back to allocator + if (task->massive_ipc_allocator != NULL) { + KBuddyDestory(task->massive_ipc_allocator); + slab_free(&xizi_task_manager.task_buddy_allocator, (void*)task->massive_ipc_allocator); + } slab_free(&xizi_task_manager.task_allocator, (void*)task); - xizi_task_manager.nr_pcb_used -= 1; // remove priority if (IS_DOUBLE_LIST_EMPTY(&xizi_task_manager.task_list_head[task->priority])) { @@ -112,6 +166,13 @@ static void _dealloc_task_cb(struct TaskMicroDescriptor* task) } /* alloc a new task with init */ +extern void trap_return(void); +void task_prepare_enter() +{ + xizi_leave_kernel(); + trap_return(); +} + static struct TaskMicroDescriptor* _new_task_cb() { // alloc task space @@ -120,10 +181,7 @@ static struct TaskMicroDescriptor* _new_task_cb() return NULL; } // init vm - if (!xizi_pager.new_pgdir(&task->pgdir)) { - _dealloc_task_cb(task); - return NULL; - } + task->pgdir.pd_addr = NULL; /* init basic task member */ doubleListNodeInit(&task->cli_sess_listhead); doubleListNodeInit(&task->svr_sess_listhead); @@ -153,13 +211,11 @@ static struct TaskMicroDescriptor* _new_task_cb() return task; } -static void _task_set_default_schedule_attr(struct TaskMicroDescriptor* task, struct TraceTag* cwd) +static void _task_set_default_schedule_attr(struct TaskMicroDescriptor* task) { - spinlock_init(&task->lock, task->name); task->remain_tick = TASK_CLOCK_TICK; task->maxium_tick = TASK_CLOCK_TICK * 10; task->state = READY; - task->cwd = *cwd; task->priority = TASK_DEFAULT_PRIORITY; doubleListAddOnHead(&task->node, &xizi_task_manager.task_list_head[task->priority]); ready_task_priority |= (1 << task->priority); @@ -170,70 +226,81 @@ extern void context_switch(struct context**, struct context*); static void _scheduler(struct SchedulerRightGroup right_group) { struct MmuCommonDone* p_mmu_driver = AchieveResource(&right_group.mmu_driver_tag); - struct TaskMicroDescriptor* next_task; while (1) { - spinlock_lock(&xizi_task_manager.lock); next_task = NULL; /* find next runnable task */ assert(cur_cpu()->task == NULL); - if (next_task_emergency != NULL) { + if (next_task_emergency != NULL && next_task->state == READY) { next_task = next_task_emergency; - spinlock_lock(&next_task->lock); - next_task->state = RUNNING; - spinlock_unlock(&next_task->lock); - next_task_emergency = NULL; } else { next_task = xizi_task_manager.next_runnable_task(); } - spinlock_unlock(&xizi_task_manager.lock); + next_task_emergency = NULL; + if (next_task != NULL) { + assert(next_task->state == READY); + } + spinlock_unlock(&whole_kernel_lock); + /* not a runnable task */ if (UNLIKELY(next_task == NULL)) { + spinlock_lock(&whole_kernel_lock); continue; } - assert(next_task->state == RUNNING); - // p_mmu_driver->LoadPgdirCrit((uintptr_t)V2P(next_task->pgdir.pd_addr), &right_group.intr_driver_tag); - p_mmu_driver->LoadPgdir((uintptr_t)V2P(next_task->pgdir.pd_addr)); + /* a runnable task */ + spinlock_lock(&whole_kernel_lock); + if (next_task->state == READY) { + next_task->state = RUNNING; + } else { + continue; + } struct CPU* cpu = cur_cpu(); cpu->task = next_task; + p_mmu_driver->LoadPgdir((uintptr_t)V2P(next_task->pgdir.pd_addr)); context_switch(&cpu->scheduler, next_task->main_thread.context); + assert(cur_cpu()->task == NULL); + assert(next_task->state != RUNNING); } } -static uint32_t yield_cnt = 0; -static void _cur_task_yield_noschedule(void) +static void _task_yield_noschedule(struct TaskMicroDescriptor* task, bool blocking) { - yield_cnt++; - - spinlock_lock(&xizi_task_manager.lock); - struct TaskMicroDescriptor* current_task = cur_cpu()->task; - assert(current_task != NULL); + assert(task != NULL); // rearrage current task position - doubleListDel(¤t_task->node); - // DEBUG("%s,%d\n", current_task->name, strcmp(current_task->name, name1)); - if (current_task->maxium_tick <= 0) { - if (IS_DOUBLE_LIST_EMPTY(&xizi_task_manager.task_list_head[current_task->priority])) { - ready_task_priority &= ~(1 << current_task->priority); - } - current_task->priority += 1; - current_task->maxium_tick = TASK_CLOCK_TICK * 10; + doubleListDel(&task->node); + if (task->state == RUNNING) { + task->state = READY; } - doubleListAddOnBack(¤t_task->node, &xizi_task_manager.task_list_head[current_task->priority]); - ready_task_priority |= (1 << current_task->priority); - // set current task state - spinlock_lock(¤t_task->lock); - current_task->state = READY; - current_task->remain_tick = TASK_CLOCK_TICK; - spinlock_unlock(¤t_task->lock); - cur_cpu()->task = NULL; - if (yield_cnt == 50) { - recover_priority(); - yield_cnt = 0; + task->remain_tick = TASK_CLOCK_TICK; + if (task == cur_cpu()->task) { + cur_cpu()->task = NULL; } - spinlock_unlock(&xizi_task_manager.lock); + doubleListAddOnBack(&task->node, &xizi_task_manager.task_list_head[task->priority]); +} + +static void _task_block(struct TaskMicroDescriptor* task) +{ + assert(task != NULL); + assert(task->state != RUNNING); + doubleListDel(&task->node); + if (xizi_task_manager.task_list_head[task->priority].next == &xizi_task_manager.task_list_head[task->priority]) { + ready_task_priority &= ~(1 << task->priority); + } + task->state = BLOCKED; + doubleListAddOnHead(&task->node, &xizi_task_manager.task_blocked_list_head); +} + +static void _task_unblock(struct TaskMicroDescriptor* task) +{ + assert(task != NULL); + assert(task->state == BLOCKED); + doubleListDel(&task->node); + task->state = READY; + doubleListAddOnHead(&task->node, &xizi_task_manager.task_list_head[task->priority]); + ready_task_priority |= (1 << task->priority); } static void _set_cur_task_priority(int priority) @@ -264,7 +331,10 @@ struct XiziTaskManager xizi_task_manager = { .next_runnable_task = max_priority_runnable_task, .task_scheduler = _scheduler, - .cur_task_yield_noschedule = _cur_task_yield_noschedule, + + .task_block = _task_block, + .task_unblock = _task_unblock, + .task_yield_noschedule = _task_yield_noschedule, .set_cur_task_priority = _set_cur_task_priority }; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/trap/Makefile b/Ubiquitous/XiZi_AIoT/softkernel/trap/Makefile index 9fef57c16..0a795948d 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/trap/Makefile +++ b/Ubiquitous/XiZi_AIoT/softkernel/trap/Makefile @@ -1,6 +1,7 @@ SRC_FILES := default_irq_handler.c \ clock_irq_handler.c \ - software_irq_handler.c + software_irq_handler.c \ + abort_handler.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/softkernel/trap/abort_handler.c b/Ubiquitous/XiZi_AIoT/softkernel/trap/abort_handler.c new file mode 100644 index 000000000..8e13e7d86 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/softkernel/trap/abort_handler.c @@ -0,0 +1,90 @@ +/* Copyright (c) 2006-2018 Frans Kaashoek, Robert Morris, Russ Cox, + * Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/** + * @file abort_handler.c + * @brief handle program abort + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2023.11.23 + */ + +/************************************************* +File name: abort_handler.c +Description: handle program abort +Others: +History: +1. Date: 2023-11-23 +Author: AIIT XUOS Lab +Modification: +1. Modify iabort and dabort handler(in dabort_handler() and iabort_handler()) +*************************************************/ +#include "core.h" +#include "memlayout.h" +#include "spinlock.h" +#include "trap_common.h" + +#include "assert.h" +#include "multicores.h" +#include "syscall.h" +#include "task.h" + +extern void context_switch(struct context**, struct context*); +void dabort_handler(struct trapframe* r) +{ + if (r->pc >= DEV_VRTMEM_BASE && is_spinlock_hold_by_current_cpu(&whole_kernel_lock)) { + assert(is_spinlock_hold_by_current_cpu(&whole_kernel_lock)); + ERROR("dabort in kernel, current task: %s\n", cur_cpu()->task == NULL ? "NULL" : cur_cpu()->task->name); + dabort_reason(r); + panic("data abort exception\n"); + } + + xizi_enter_kernel(); + + struct TaskMicroDescriptor* cur_task = cur_cpu()->task; + ERROR("dabort in user space: %s\n", cur_task->name); + dabort_reason(r); + sys_exit(cur_task); + assert(cur_cpu()->task == NULL); + context_switch(&cur_task->main_thread.context, cur_cpu()->scheduler); + panic("dabort end should never be reashed.\n"); +} + +void iabort_handler(struct trapframe* r) +{ + if (r->pc >= DEV_VRTMEM_BASE && is_spinlock_hold_by_current_cpu(&whole_kernel_lock)) { + assert(is_spinlock_hold_by_current_cpu(&whole_kernel_lock)); + ERROR("iabort in kernel, current task: %s\n", cur_cpu()->task == NULL ? "NULL" : cur_cpu()->task->name); + iabort_reason(r); + panic("kernel prefetch abort exception\n"); + } + + xizi_enter_kernel(); + + struct TaskMicroDescriptor* cur_task = cur_cpu()->task; + ERROR("iabort in user space: %s\n", cur_task->name); + iabort_reason(r); + sys_exit(cur_task); + assert(cur_cpu()->task == NULL); + context_switch(&cur_task->main_thread.context, cur_cpu()->scheduler); + panic("iabort end should never be reashed.\n"); +} diff --git a/Ubiquitous/XiZi_AIoT/softkernel/trap/clock_irq_handler.c b/Ubiquitous/XiZi_AIoT/softkernel/trap/clock_irq_handler.c index b3453dd2c..6c4c92915 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/trap/clock_irq_handler.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/trap/clock_irq_handler.c @@ -58,7 +58,7 @@ int xizi_clock_handler(int irq, void* tf, void* arg) current_task->remain_tick--; current_task->maxium_tick--; if (current_task->remain_tick == 0) { - xizi_task_manager.cur_task_yield_noschedule(); + xizi_task_manager.task_yield_noschedule(current_task, false); } } } diff --git a/Ubiquitous/XiZi_AIoT/softkernel/trap/default_irq_handler.c b/Ubiquitous/XiZi_AIoT/softkernel/trap/default_irq_handler.c index 445c64add..7c3dc2c81 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/trap/default_irq_handler.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/trap/default_irq_handler.c @@ -56,19 +56,18 @@ void default_interrupt_routine(void) extern void context_switch(struct context**, struct context*); void intr_irq_dispatch(struct trapframe* tf) { - assert(p_intr_driver != NULL); + xizi_enter_kernel(); - p_intr_driver->cpu_irq_disable(); // enter irq + assert(p_intr_driver != NULL); uintptr_t int_info = 0; if ((int_info = p_intr_driver->hw_before_irq()) == 0) { - return; + goto intr_leave_interrupt; } struct TaskMicroDescriptor* current_task = cur_cpu()->task; - if (LIKELY(current_task != NULL)) { - current_task->main_thread.trapframe = tf; - } + assert(current_task != NULL); + current_task->main_thread.trapframe = tf; unsigned cpu = p_intr_driver->hw_cur_int_cpu(int_info); unsigned irq = p_intr_driver->hw_cur_int_num(int_info); @@ -76,7 +75,7 @@ void intr_irq_dispatch(struct trapframe* tf) // distribute irq irq_handler_t isr = p_intr_driver->sw_irqtbl[irq].handler; - if (isr) { + if (isr != NULL) { isr(irq, tf, NULL); } else { default_interrupt_routine(); @@ -86,10 +85,34 @@ void intr_irq_dispatch(struct trapframe* tf) p_intr_driver->curr_int[cpu] = 0; p_intr_driver->hw_after_irq(int_info); - if (UNLIKELY(cur_cpu()->task == NULL && current_task != NULL)) { + if (cur_cpu()->task == NULL || current_task->state != RUNNING) { + cur_cpu()->task = NULL; context_switch(¤t_task->main_thread.context, cur_cpu()->scheduler); } assert(current_task == cur_cpu()->task); - p_intr_driver->cpu_irq_enable(); +intr_leave_interrupt: + xizi_leave_kernel(); +} + +void xizi_enter_kernel() +{ + /// @warning trampoline is responsible for closing interrupt + spinlock_lock(&whole_kernel_lock); +} + +bool xizi_try_enter_kernel() +{ + /// @warning trampoline is responsible for closing interrupt + if (spinlock_try_lock(&whole_kernel_lock)) { + return true; + } + + return false; +} + +void xizi_leave_kernel() +{ + /// @warning trampoline is responsible for eabling interrupt by using user's state register + spinlock_unlock(&whole_kernel_lock); } diff --git a/Ubiquitous/XiZi_AIoT/softkernel/trap/software_irq_handler.c b/Ubiquitous/XiZi_AIoT/softkernel/trap/software_irq_handler.c index ddf3cccd8..dce844139 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/trap/software_irq_handler.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/trap/software_irq_handler.c @@ -48,9 +48,9 @@ bool swi_distributer_init(struct SwiDispatcherRightGroup* _right_group) extern void context_switch(struct context**, struct context*); void software_irq_dispatch(struct trapframe* tf) { + xizi_enter_kernel(); assert(p_intr_driver != NULL); - p_intr_driver->cpu_irq_disable(); // get current task struct TaskMicroDescriptor* cur_task = cur_cpu()->task; /// @todo: Handle dead task @@ -59,21 +59,22 @@ void software_irq_dispatch(struct trapframe* tf) if (cur_task && cur_task->state != DEAD) { cur_task->main_thread.trapframe = tf; // call syscall + int ret = arch_syscall(cur_task->main_thread.trapframe, &syscall_num); if (syscall_num != SYSCALL_EXEC) { arch_set_return(tf, ret); } - } else { - ERROR("syscall by killed task.\n"); } - if (cur_cpu()->task == NULL && cur_task != NULL) { + if ((cur_cpu()->task == NULL && cur_task != NULL) || cur_task->state != RUNNING) { + cur_cpu()->task = NULL; context_switch(&cur_task->main_thread.context, cur_cpu()->scheduler); } - assert(cur_task == cur_cpu()->task); if (syscall_num == SYSCALL_EXIT) { - ERROR("Exit reaches"); + panic("Exit reaches"); } - p_intr_driver->cpu_irq_enable(); + + assert(cur_task == cur_cpu()->task); + xizi_leave_kernel(); } \ No newline at end of file