diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/Makefile new file mode 100644 index 000000000..c794367b8 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := cache.c isr.c abstraction_mmu.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/abstraction_mmu.c b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/abstraction_mmu.c new file mode 100755 index 000000000..6f37b7d6f --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/abstraction_mmu.c @@ -0,0 +1,206 @@ +/* +* 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: abstraction_mmu.c +* @brief: the general management of system mmu +* @version: 3.0 +* @author: AIIT XUOS Lab +* @date: 2023/4/27 +* +*/ + +#include + +AbstractionMmu abstraction_mmu; + +volatile uint32_t global_L1_pte_table[4096]; + +/** + * @description: write cmd to CP15 register + * @param reg_type - CP15 register type + * @param val - ops val pointer + * @return + */ +static void MmuCp15Write(uint8_t reg_type, uint32_t *val) +{ + uint32_t write_val = *val; + switch (reg_type) { + case AM_MMU_CP15_TTBCR: + TTBCR_W(write_val); + AM_ISB; + case AM_MMU_CP15_TTBR0: + TTBR0_W(write_val); + AM_ISB; + default: + break; + } +} + +/** + * @description: read CP15 register from mmu + * @param reg_type - CP15 register type + * @param val - ops val pointer + * @return + */ +static void MmuCp15Read(uint8_t reg_type, uint32_t *val) +{ + uint32_t read_val = 0; + switch (reg_type) { + case AM_MMU_CP15_TTBCR: + TTBCR_R(read_val); + case AM_MMU_CP15_TTBR0: + TTBR0_R(read_val); + default: + break; + } + + *val = read_val; +} + +/** + * @description: write or read CP15 register to set mmu + * @param ops_type - CP15 write or read + * @param reg_type - CP15 register type + * @param val - ops val pointer + * @return + */ +static void MmuRegOps(uint8_t ops_type, uint8_t reg_type, uint32_t *val) +{ + switch (ops_type) { + case AM_MMU_CP15_WRITE: + MmuCp15Write(reg_type, val); + case AM_MMU_CP15_READ: + MmuCp15Read(reg_type, val); + default: + break; + } +} + +/** + * @description: Init abstraction_mmu function + * @param mmu - abstraction mmu pointer + * @param ttb_base - ttb base pointer + * @return success : 0 error : -1 + */ +static int _AbstractionMmuInit(AbstractionMmu *mmu, uint32_t *ttb_base) +{ + mmu_init(); + + return 0; +} + +/** + * @description: map L1 or L2 page table section + * @param mmu - abstraction mmu pointer + * @param section_size - section size + * @return success : 0 error : -1 + */ +static int _AbstractionMmuSectionMap(AbstractionMmu *mmu, uint32_t section_size) +{ + uint32_t vaddr_length = mmu->vaddr_end - mmu->vaddr_start + 1; + + mmu_map_l1_range(mmu->paddr_start, mmu->vaddr_start, vaddr_length, + mmu->mmu_memory_type, mmu->mmu_shareability, mmu->mmu_access); + + mmu->mmu_status = 1; + + return 0; +} + +/** + * @description: unmap L1 or L2 page table section + * @param mmu - abstraction mmu pointer + * @param vaddr_start - virtual address start + * @param vaddr_size - virtual address size + * @return success : 0 error : -1 + */ +static int _AbstractionMmuSectionUnmap(AbstractionMmu *mmu, uint32_t vaddr_start, uint32_t vaddr_size) +{ + uint32_t *l1_umap_ventry = mmu->ttb_vbase + (vaddr_start >> AM_MMU_L1_SECTION_SHIFT); + uint32_t vaddr_end = vaddr_start + vaddr_size - 1; + uint32_t umap_count = (vaddr_end >> AM_MMU_L1_SECTION_SHIFT) - (vaddr_start >> AM_MMU_L1_SECTION_SHIFT) + 1; + + while (umap_count) { + AM_DMB; + *l1_umap_ventry = 0; + AM_DSB; + + umap_count--; + l1_umap_ventry += (1 << AM_MMU_L1_SECTION_SHIFT);//1MB section + } + + AM_DSB; + CLEARTLB(0);//clear TLB data and configure + AM_DSB; + AM_ISB; + mmu->mmu_status = 0; + + return 0; +} + +/** + * @description: switch ttb base by re-write ttbr register + * @param mmu - abstraction mmu pointer + * @return success : 0 error : -1 + */ +static int _AbstractionMmuTtbSwitch(AbstractionMmu *mmu) +{ + uint32_t ttbr, ttbcr; + MmuRegOps(AM_MMU_CP15_READ, AM_MMU_CP15_TTBCR, &ttbcr); + + /* Set TTBR0 with inner/outer write back write allocate and not shareable, [4:3]=01, [1]=0, [6,0]=01 */ + ttbr = ((mmu->ttb_pbase & 0xFFFFC000UL) | 0x9UL); + /* enable TTBR0 */ + ttbcr = 0; + + AM_DSB; + MmuRegOps(AM_MMU_CP15_WRITE, AM_MMU_CP15_TTBR0, &ttbr); + MmuRegOps(AM_MMU_CP15_WRITE, AM_MMU_CP15_TTBCR, &ttbcr); + + return 0; +} + +/** + * @description: get physical address transformed from virtual address + * @param mmu - abstraction mmu pointer + * @param vaddr - virtual address pointer + * @param paddr - physical address pointer + * @return success : 0 error : -1 + */ +static int _AbstracktonMmuTransform(AbstractionMmu *mmu, uint32_t *vaddr, uint32_t *paddr) +{ + uint32_t virtualAddress = *vaddr; + + if (mmu->mmu_status) { + mmu_virtual_to_physical(virtualAddress, paddr); + } + + return 0; +} + +static struct AbstractionMmuDone mmu_done = { + .AbstractionMmuInit = _AbstractionMmuInit, + .AbstractionMmuSectionMap = _AbstractionMmuSectionMap, + .AbstractionMmuSectionUnmap = _AbstractionMmuSectionUnmap, + .AbstractionMmuTtbSwitch = _AbstractionMmuTtbSwitch, + .AbstracktonMmuTransform = _AbstracktonMmuTransform, +}; + +/** + * @description: init abstraciton mmu info when system start + * @return success : 0 error : -1 + */ +int SysInitAbstractionMmu(void) +{ + abstraction_mmu.mmu_done = &mmu_done; +} diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/abstraction_mmu.h b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/abstraction_mmu.h new file mode 100644 index 000000000..ce3c35d06 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/abstraction_mmu.h @@ -0,0 +1,114 @@ +/* +* 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: mmu.h +* @brief: the general management of system mmu +* @version: 3.0 +* @author: AIIT XUOS Lab +* @date: 2023/5/24 +* +*/ +#include +#include + +#define ARCH_ARM +#ifdef ARCH_ARM +/* ARM System Registers */ +#define AM_DSB __asm__ volatile("dsb" ::: "memory") +#define AM_DMB __asm__ volatile("dmb" ::: "memory") +#define AM_ISB __asm__ volatile("isb" ::: "memory") +#define AM_WFI __asm__ volatile("wfi" ::: "memory") +#define AM_BARRIER __asm__ volatile("":::"memory") +#define AM_WFE __asm__ volatile("wfe" ::: "memory") +#define AM_SEV __asm__ volatile("sev" ::: "memory") + +#define TTBR0_R(val) __asm__ volatile("mrc p15, 0, %0, c2, c0, 0" : "=r"(val)) +#define TTBR0_W(val) __asm__ volatile("mcr p15, 0, %0, c2, c0, 0" ::"r"(val)) + +#define TTBCR_R(val) __asm__ volatile("mrc p15, 0, %0, c2, c0, 2" : "=r"(val)) +#define TTBCR_W(val) __asm__ volatile("mcr p15, 0, %0, c2, c0, 2" ::"r"(val)) + +#define CLEARTLB(val) __asm__ volatile("mcr p15, 0, %0, c8, c7, 0" ::"r"(val)) +#endif + +#define AM_MMU_L1_PAGE_TABLE_SIZE (4 * 4096) +#define AM_MMU_L1_SECTION_SHIFT 20 + +typedef enum +{ + AM_MMU_CP15_WRITE = 0, + AM_MMU_CP15_READ, +}MmuCP15OpsType; + +typedef enum +{ + AM_MMU_CP15_TTBCR = 0, + AM_MMU_CP15_TTBR0, + AM_MMU_CP15_CLEARTLB, +}MmuCP15RegType; + +typedef enum +{ + AM_StronglyOrdered = 0, + AM_Device, + AM_OuterInner_WB_WA, + AM_OuterInner_WT, + AM_Noncacheable, +}MmuMemoryType; + +typedef enum +{ + AM_Noaccess = 0, + AM_Read_Write, + AM_Read, +}MmuAccess; + +typedef enum +{ + AM_Shareable = 1, + AM_Nonshareable = 0 +}MmuShareability; + +struct AbstractionMmuDone +{ + int (*AbstractionMmuInit)(AbstractionMmu *mmu, uint32_t *ttb_base); + int (*AbstractionMmuSectionMap)(AbstractionMmu *mmu, uint32_t section_size); + int (*AbstractionMmuSectionUnmap)(AbstractionMmu *mmu, uint32_t vaddr_start, uint32_t vaddr_size); + int (*AbstractionMmuTtbSwitch)(AbstractionMmu *mmu); + int (*AbstracktonMmuTransform)(AbstractionMmu *mmu, uint32_t *vaddr, uint32_t *paddr); +}; + +typedef struct +{ + uint32_t ttb_vbase; + uint32_t ttb_pbase; + + uint32_t vaddr_start; + uint32_t vaddr_end; + uint32_t paddr_start; + uint32_t paddr_end; + + uint32_t vpaddr_offset; + + uint32_t pte_attr; + uint32_t mmu_status; + + MmuMemoryType mmu_memory_type; + MmuAccess mmu_access; + MmuShareability mmu_shareability; + + struct AbstractionMmuDone *mmu_done; + + int lock; + int link_list; +}AbstractionMmu; \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/cache.c b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/cache.c new file mode 100755 index 000000000..4a71e6c30 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/cache.c @@ -0,0 +1,35 @@ +/* +* 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: cache.c +* @brief: the general management of system cache +* @version: 3.0 +* @author: AIIT XUOS Lab +* @date: 2023/4/27 +* +*/ + +void InvalidInsCache() +{ + PlatInvalidInsCache(); +} + +void InvalidDataCache(unsigned long start, unsigned long end) +{ + PlatInvalidDateCache(start, end); +} + +void CleanDataCache(unsigned long start, unsigned long end) +{ + PlatCleanDateCache(start, end); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/isr.c b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/isr.c new file mode 100644 index 000000000..94dbc9fb1 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/isr.c @@ -0,0 +1,215 @@ +/* +* 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: isr.c +* @brief: the general management of system isr +* @version: 1.0 +* @author: AIIT XUOS Lab +* @date: 2020/3/15 +* +*/ +#include +#include "isr.h" + +struct InterruptServiceRoutines isrManager = {0} ; + +#ifdef ARCH_SMP +extern int GetCpuId(void); +#endif +/** + * This functionwill get the isr nest level. + * + * @return isr nest level + */ +static uint16_t GetIsrCounter() +{ + uint16_t ret = 0; + +#ifdef ARCH_SMP + ret = isrManager.isr_count[GetCpuId()]; +#else + ret = isrManager.isr_count; +#endif + return ret; +} + +static void IncIsrCounter() +{ +#ifdef ARCH_SMP + isrManager.isr_count[GetCpuId()] ++ ; +#else + isrManager.isr_count ++; +#endif + return ; +} + +static void DecIsrCounter() +{ + +#ifdef ARCH_SMP + isrManager.isr_count[GetCpuId()] -- ; +#else + isrManager.isr_count --; +#endif + return ; +} + +bool IsInIsr() +{ +#ifdef ARCH_SMP + return ( isrManager.isr_count[GetCpuId()] != 0 ? TRUE : FALSE ) ; +#else + return ( isrManager.isr_count != 0 ? TRUE : FALSE ) ; +#endif + +} +/** + * This function will register a new irq. + * + * @param irq_num the number of the irq + * @param handler the callback of the interrupt + * @param arg param of thge callback + * + * @return 0 on success; -1 on failure + */ +static int32_t RegisterHwIrq(uint32_t irq_num, IsrHandlerType handler, void *arg) +{ + if (irq_num >= ARCH_MAX_IRQ_NUM ) + return -1; + + struct IrqDesc *desc = &isrManager.irq_table[irq_num]; + + desc->handler = handler; + desc->param = arg; + + return 0; +} +/** + * This function will free a irq. + * + * @param irq_num the number of the irq + * + * @return 0 on success; -1 on failure + */ +static int32_t FreeHwIrq(uint32_t irq_num) +{ + if (irq_num >= ARCH_MAX_IRQ_NUM ) + return -1; + + memset(&isrManager.irq_table[irq_num], 0, sizeof(struct IrqDesc)); + + return 0; +} + +/** + * This function will enable a irq. + * + * @param irq_num the number of the irq + * + * @return 0 on success; -1 on failure + */ +static int32_t EnableHwIrq(uint32_t irq_num, uint32_t cpu_id) +{ + if (irq_num >= ARCH_MAX_IRQ_NUM ) + return -1; + + return ArchEnableHwIrq(irq_num, cpu_id); +} +/** + * This function will disable a irq. + * + * @param irq_num the number of the irq + * + * @return 0 on success; -1 on failure + */ + +static int32_t DisableHwIrq(uint32_t irq_num, uint32_t cpu_id) +{ + if (irq_num >= ARCH_MAX_IRQ_NUM ) + return -1; + + return ArchDisableHwIrq(irq_num, cpu_id); +} + +/* called from arch-specific ISR wrapper */ +static void IsrCommon(uint32_t irq_num) +{ + struct IrqDesc *desc = &isrManager.irq_table[irq_num]; + + if (desc->handler == NULL) { + // SYS_KDEBUG_LOG(KDBG_IRQ, ("Spurious interrupt: IRQ No. %d\n", irq_num)); + while (1) {} + } + desc->handler(irq_num, desc->param); + +} + +static void SetIsrSwitchTrigerFlag() +{ + +#ifdef ARCH_SMP + isrManager.isr_switch_trigger_flag[GetCpuId()] = 1; +#else + isrManager.isr_switch_trigger_flag = 1; +#endif +} + +static void ClearIsrSwitchTrigerFlag() +{ + +#ifdef ARCH_SMP + isrManager.isr_switch_trigger_flag[GetCpuId()] = 0; +#else + isrManager.isr_switch_trigger_flag = 0; +#endif +} + +static uint8_t GetIsrSwitchTrigerFlag() +{ + +#ifdef ARCH_SMP + return isrManager.isr_switch_trigger_flag[GetCpuId()]; +#else + return isrManager.isr_switch_trigger_flag ; +#endif +} + +struct IsrDone isrDone = { + IsInIsr, + RegisterHwIrq , + FreeHwIrq, + EnableHwIrq, + DisableHwIrq, + IsrCommon, + GetIsrCounter, + IncIsrCounter, + DecIsrCounter, + GetIsrSwitchTrigerFlag, + SetIsrSwitchTrigerFlag, + ClearIsrSwitchTrigerFlag +}; + +void SysInitIsrManager() +{ + extern int __isrtbl_idx_start; + extern int __isrtbl_start; + extern int __isrtbl_end; + memset(&isrManager,0,sizeof(struct InterruptServiceRoutines)); + isrManager.done = &isrDone; + + uint32_t *index = (uint32_t *)&__isrtbl_idx_start; + struct IrqDesc *desc = (struct IrqDesc *)&__isrtbl_start; + + while (desc != (struct IrqDesc *)&__isrtbl_end) + isrManager.irq_table[*index++] = *desc++; +} diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/isr.h b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/isr.h new file mode 100644 index 000000000..1e0ddcfbf --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction/isr.h @@ -0,0 +1,98 @@ +/* +* 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: isr.h +* @brief: function declaration and structure defintion of isr +* @version: 1.0 +* @author: AIIT XUOS Lab +* @date: 2020/3/10 +* +*/ + +#ifndef __ISR_H__ +#define __ISR_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define DECLARE_HW_IRQ(_irq_num, _handler, _arg) \ + const uint32_t __irq_desc_idx_##_handler SECTION(".isrtbl.idx") = _irq_num + ARCH_IRQ_NUM_OFFSET ; \ + const struct IrqDesc __irq_desc_##_handler SECTION(".isrtbl") = { \ + .handler = _handler, \ + .param = _arg, \ + } + +typedef void (*IsrHandlerType)(int vector, void *param); + +struct IrqDesc +{ + IsrHandlerType handler; + void *param; + +#ifdef CONFIG_INTERRUPT_INFO + char name[NAME_NUM_MAX]; + uint32_t counter; +#endif +}; + +struct IsrDone +{ + bool (*isInIsr)(); + int32_t (*registerIrq)(uint32_t irq_num, IsrHandlerType handler, void *arg); + int32_t (*freeIrq)(uint32_t irq_num); + int32_t (*enableIrq)(uint32_t irq_num, uint32_t cpu_id); + int32_t (*disableIrq)(uint32_t irq_num, uint32_t cpu_id); + void (*handleIrq)(uint32_t irq_num); + uint16_t (*getCounter)() ; + void (*incCounter)(); + void (*decCounter)(); + uint8_t (*getSwitchTrigerFlag)(); + void (*setSwitchTrigerFlag)(); + void (*clearSwitchTrigerFlag)(); +}; + +struct InterruptServiceRoutines { + +#ifdef ARCH_SMP + volatile uint16_t isr_count[CPU_NUMBERS]; + volatile uint8_t isr_switch_trigger_flag[CPU_NUMBERS]; +#else + volatile uint16_t isr_count ; + volatile uint8_t isr_switch_trigger_flag; +#endif + struct IrqDesc irq_table[ARCH_MAX_IRQ_NUM]; + struct IsrDone *done; +}; + +extern struct InterruptServiceRoutines isrManager ; + +uint32_t DisableLocalInterrupt(); +void EnableLocalInterrupt(unsigned long level); + +#define DISABLE_INTERRUPT DisableLocalInterrupt +#define ENABLE_INTERRUPT EnableLocalInterrupt + +void SysInitIsrManager(); +void InitHwinterrupt(void); + + +#ifdef __cplusplus +} +#endif + +#endif