已开启
添加 RK3588 多核支持 #23
yzm创建于 22 天前
添加 RK3588 多核支持 #23
已开启
共 19 个文件变更+250-9
| @@ -41,6 +41,12 @@ if [[ -z "${CHCORE_PLAT}" ]]; then | |||
| 41 | echo "failed to get CHCORE_PLAT from ${CONFIG_MK}" | 41 | echo "failed to get CHCORE_PLAT from ${CONFIG_MK}" |
| 42 | exit 1 | 42 | exit 1 |
| 43 | fi | 43 | fi |
| 44 | +PLAT_MACHINE_H=${CHCORE_DIR}/kernel/include/arch/aarch64/plat/${CHCORE_PLAT}/machine.h | ||
| 45 | +TEE_CORE_NUM=$(awk '/^[[:space:]]*#define[[:space:]]+PLAT_CPU_NUM[[:space:]]+/ {print $3; exit}' ${PLAT_MACHINE_H}) | ||
| 46 | +if ! [[ "${TEE_CORE_NUM}" =~ ^[0-9]+$ ]]; then | ||
| 47 | + echo "failed to get PLAT_CPU_NUM from ${PLAT_MACHINE_H}" | ||
| 48 | + exit 1 | ||
| 49 | +fi | ||
| 44 | CHCORE_LLM=$(sed -n 's/^[[:space:]]*CHCORE_LLM[[:space:]]*=[[:space:]]*\([^[:space:]\\]*\).*/\1/p' ${CONFIG_MK} | head -n 1) | 50 | CHCORE_LLM=$(sed -n 's/^[[:space:]]*CHCORE_LLM[[:space:]]*=[[:space:]]*\([^[:space:]\\]*\).*/\1/p' ${CONFIG_MK} | head -n 1) |
| 45 | if [[ "${CHCORE_LLM}" = "ON" && "${CHCORE_PLAT}" = "rk3588" ]]; then | 51 | if [[ "${CHCORE_LLM}" = "ON" && "${CHCORE_PLAT}" = "rk3588" ]]; then |
| 46 | CHCORE_LLM=1 | 52 | CHCORE_LLM=1 |
| @@ -76,7 +82,7 @@ cp -r ${CHCORE_DIR}/user/chcore-libc/musl-libc/install/include/* ${OH_TEE_HEADER | |||
| 76 | cp ${CHCORE_DIR}/user/chcore-libs/sys-libs/libohtee/include/* ${OH_TEE_HEADERS_DIR}/sys/ | 82 | cp ${CHCORE_DIR}/user/chcore-libs/sys-libs/libohtee/include/* ${OH_TEE_HEADERS_DIR}/sys/ |
| 77 | # go to framework and build it | 83 | # go to framework and build it |
| 78 | cd ${OH_TEE_FRAMEWORK_DIR}/build | 84 | cd ${OH_TEE_FRAMEWORK_DIR}/build |
| 79 | -./build_framework.sh oh_64 ${CHCORE_DIR}/oh_tee ${COMPILER_DIR} ${COMPILER_VER} ${OH_TEE_FRAMEWORK_DIR} ${THIRD_PARTY} ${CHCORE_PLAT} | 85 | +./build_framework.sh oh_64 ${CHCORE_DIR}/oh_tee ${COMPILER_DIR} ${COMPILER_VER} ${OH_TEE_FRAMEWORK_DIR} ${THIRD_PARTY} ${CHCORE_PLAT} ${TEE_CORE_NUM} |
| 80 | # compile again to put the apps into ramdisk-dir | 86 | # compile again to put the apps into ramdisk-dir |
| 81 | cd ${CHCORE_DIR} | 87 | cd ${CHCORE_DIR} |
| 82 | if [ "${CHCORE_LLM}" = 1 ]; then | 88 | if [ "${CHCORE_LLM}" = 1 ]; then |
| @@ -148,10 +148,12 @@ EXPORT(el1_vector) | |||
| 148 | * - t: SP_EL0 is used | 148 | * - t: SP_EL0 is used |
| 149 | * - h: SP_ELx is used | 149 | * - h: SP_ELx is used |
| 150 | * | 150 | * |
| 151 | - * ChCore does not enable or handle irq_el1t, fiq_xxx, and error_xxx. | 151 | + * ChCore does not enable or handle irq_el1t, fiq_el1t, and error_xxx. |
| 152 | * The SPSR_EL1 of idle threads is set to 0b0101, which means interrupt | 152 | * The SPSR_EL1 of idle threads is set to 0b0101, which means interrupt |
| 153 | * are enabled during the their execution and SP_EL1 is selected (h). | 153 | * are enabled during the their execution and SP_EL1 is selected (h). |
| 154 | * Thus, irq_el1h is enabled and handled. | 154 | * Thus, irq_el1h is enabled and handled. |
| 155 | + * OH-TEE also handles fiq_el1h because a secure preemption FIQ can arrive | ||
| 156 | + * while an idle thread is running in EL1h. | ||
| 155 | * | 157 | * |
| 156 | * Similarly, sync_el1t is also not enabled while we simply reuse the handler for | 158 | * Similarly, sync_el1t is also not enabled while we simply reuse the handler for |
| 157 | * sync_el0 to handle sync_el1h (e.g., page fault during copy_to_user and fpu). | 159 | * sync_el0 to handle sync_el1h (e.g., page fault during copy_to_user and fpu). |
| @@ -169,12 +171,25 @@ irq_el1h: | |||
| 169 | 171 | ||
| 170 | irq_el1t: | 172 | irq_el1t: |
| 171 | fiq_el1t: | 173 | fiq_el1t: |
| 174 | +#ifndef CHCORE_OH_TEE | ||
| 172 | fiq_el1h: | 175 | fiq_el1h: |
| 176 | +#endif /* CHCORE_OH_TEE */ | ||
| 173 | error_el1t: | 177 | error_el1t: |
| 174 | error_el1h: | 178 | error_el1h: |
| 175 | sync_el1t: | 179 | sync_el1t: |
| 176 | bl unexpected_handler | 180 | bl unexpected_handler |
| 177 | 181 | ||
| 182 | +#ifdef CHCORE_OH_TEE | ||
| 183 | +fiq_el1h: | ||
| 184 | + exception_enter | ||
| 185 | +#ifndef CHCORE_KERNEL_RT | ||
| 186 | + switch_to_cpu_stack | ||
| 187 | +#endif | ||
| 188 | + bl handle_fiq | ||
| 189 | + /* should never reach here */ | ||
| 190 | + b . | ||
| 191 | +#endif /* CHCORE_OH_TEE */ | ||
| 192 | + | ||
| 178 | sync_el1h: | 193 | sync_el1h: |
| 179 | exception_enter | 194 | exception_enter |
| 180 | mov x0, #SYNC_EL1h | 195 | mov x0, #SYNC_EL1h |
| @@ -27,6 +27,7 @@ | |||
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | + | ||
| 30 | 31 | ||
| 31 | 32 | ||
| 32 | 33 | ||
| @@ -103,6 +104,8 @@ void main(paddr_t boot_flag, void *info) | |||
| 103 | /* Other cores are busy looping on the boot_flag, wake up those cores */ | 104 | /* Other cores are busy looping on the boot_flag, wake up those cores */ |
| 104 | enable_smp_cores(boot_flag); | 105 | enable_smp_cores(boot_flag); |
| 105 | kinfo("[ChCore] boot multicore finished\n"); | 106 | kinfo("[ChCore] boot multicore finished\n"); |
| 107 | + | ||
| 108 | + init_ipi_data(); | ||
| 106 | 109 | ||
| 107 | 110 | ||
| 108 | 111 | ||
| @@ -138,6 +141,7 @@ void main(paddr_t boot_flag, void *info) | |||
| 138 | 141 | ||
| 139 | void secondary_start(u32 cpuid) | 142 | void secondary_start(u32 cpuid) |
| 140 | { | 143 | { |
| 144 | + kinfo("[ChCore] secondary_start: cpu %d\n", cpuid); | ||
| 141 | /* Init per_cpu info */ | 145 | /* Init per_cpu info */ |
| 142 | init_per_cpu_info(cpuid); | 146 | init_per_cpu_info(cpuid); |
| 143 | 147 | ||
| @@ -0,0 +1,76 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU) | ||
| 3 | + * Licensed under the Mulan PSL v2. | ||
| 4 | + * You can use this software according to the terms and conditions of the Mulan PSL v2. | ||
| 5 | + * You may obtain a copy of Mulan PSL v2 at: | ||
| 6 | + * http://license.coscl.org.cn/MulanPSL2 | ||
| 7 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR | ||
| 8 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR | ||
| 9 | + * PURPOSE. | ||
| 10 | + * See the Mulan PSL v2 for more details. | ||
| 11 | + */ | ||
| 12 | +#include "boot.h" | ||
| 13 | +#include <arch/machine/registers.h> | ||
| 14 | +#include <common/asm.h> | ||
| 15 | + | ||
| 16 | + .macro set_sctlr_el1 | ||
| 17 | + mrs x0, sctlr_el1 | ||
| 18 | + orr x0, x0, #SCTLR_EL1_I | ||
| 19 | + orr x0, x0, #SCTLR_EL1_SA | ||
| 20 | + orr x0, x0, #SCTLR_EL2_SPAN | ||
| 21 | + orr x0, x0, #SCTLR_EL2_WXN | ||
| 22 | + bic x0, x0, #SCTLR_EL2_A | ||
| 23 | + msr sctlr_el1, x0 | ||
| 24 | + .endm | ||
| 25 | + | ||
| 26 | + /* | ||
| 27 | + * Setup SP_EL0 and SPEL1, SP will be set to SP_EL0. | ||
| 28 | + * SP_EL0 is assigned: | ||
| 29 | + * stack_tmp + (cpu_id + 1) * stack_tmp_stride - STACK_TMP_GUARD | ||
| 30 | + * SP_EL1 is assigned thread_core_local[cpu_id] | ||
| 31 | + */ | ||
| 32 | + .macro set_sp | ||
| 33 | + bl __get_core_pos | ||
| 34 | + add x0, x0, #1 | ||
| 35 | + mov x1, #BOOT_STACK_SIZE | ||
| 36 | + mul x1, x0, x1 | ||
| 37 | + adr x0, boot_stacks | ||
| 38 | + add x0, x0, x1 | ||
| 39 | + msr spsel, #1 | ||
| 40 | + mov sp, x0 | ||
| 41 | + # msr spsel, #0 | ||
| 42 | + .endm | ||
| 43 | + | ||
| 44 | +BEGIN_FUNC(__get_core_pos) | ||
| 45 | + mrs x0, mpidr_el1 | ||
| 46 | + b get_core_pos_mpidr | ||
| 47 | +END_FUNC(__get_core_pos) | ||
| 48 | + | ||
| 49 | +/* size_t get_core_pos_mpidr(uint32_t mpidr); */ | ||
| 50 | +/* Let platforms override this if needed */ | ||
| 51 | +BEGIN_FUNC(get_core_pos_mpidr) | ||
| 52 | + /* RK3588 encodes logical CPUs as MPIDR values 0x0, 0x100, ..., 0x700. */ | ||
| 53 | + and x1, x0, #0xff | ||
| 54 | + ubfx x0, x0, #8, #8 | ||
| 55 | + add x0, x0, x1 | ||
| 56 | + | ||
| 57 | + ret | ||
| 58 | +END_FUNC(get_core_pos_mpidr) | ||
| 59 | + | ||
| 60 | +BEGIN_FUNC(cpu_on_handler) | ||
| 61 | + mov x19, x30 | ||
| 62 | + | ||
| 63 | + /* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */ | ||
| 64 | + set_sp | ||
| 65 | + | ||
| 66 | + bl el1_mmu_activate | ||
| 67 | + isb | ||
| 68 | + | ||
| 69 | + /* Get current cpu id and store it in x0 */ | ||
| 70 | + bl __get_core_pos | ||
| 71 | + | ||
| 72 | +/***************** Begin return *****************/ | ||
| 73 | + mov x30, x19 | ||
| 74 | + b secondary_cpu_boot | ||
| 75 | +/****************** End return ******************/ | ||
| 76 | +END_FUNC(cpu_on_handler) | ||
| @@ -19,9 +19,10 @@ BEGIN_FUNC(fast_smc_entry) | |||
| 19 | END_FUNC(fast_smc_entry) | 19 | END_FUNC(fast_smc_entry) |
| 20 | 20 | ||
| 21 | BEGIN_FUNC(cpu_on_entry) | 21 | BEGIN_FUNC(cpu_on_entry) |
| 22 | - ldr x0, =SMC_ON_DONE | 22 | + b cpu_on_handler // Should not return |
| 23 | - mov x1, #0 | 23 | +err: |
| 24 | - smc #0 | 24 | + wfe |
| 25 | + b err | ||
| 25 | END_FUNC(cpu_on_entry) | 26 | END_FUNC(cpu_on_entry) |
| 26 | 27 | ||
| 27 | BEGIN_FUNC(cpu_off_entry) | 28 | BEGIN_FUNC(cpu_off_entry) |
| @@ -60,6 +61,8 @@ BEGIN_FUNC(system_reset_entry) | |||
| 60 | smc #0 | 61 | smc #0 |
| 61 | END_FUNC(system_reset_entry) | 62 | END_FUNC(system_reset_entry) |
| 62 | 63 | ||
| 64 | +.align 3 | ||
| 65 | + | ||
| 63 | BEGIN_FUNC(tz_vectors) | 66 | BEGIN_FUNC(tz_vectors) |
| 64 | b yield_smc_entry | 67 | b yield_smc_entry |
| 65 | b fast_smc_entry | 68 | b fast_smc_entry |
| @@ -344,6 +344,9 @@ int sys_tee_switch_req(struct smc_registers *regs_u) | |||
| 344 | if (regs_k.x0 == TZ_SWITCH_REQ_ENTRY_DONE) { | 344 | if (regs_k.x0 == TZ_SWITCH_REQ_ENTRY_DONE) { |
| 345 | regs_k.x0 = SMC_ENTRY_DONE; | 345 | regs_k.x0 = SMC_ENTRY_DONE; |
| 346 | regs_k.x1 = (vaddr_t)&tz_vectors; | 346 | regs_k.x1 = (vaddr_t)&tz_vectors; |
| 347 | + } else if (regs_k.x0 == TZ_SWITCH_REQ_ON_DONE) { | ||
| 348 | + regs_k.x0 = SMC_ON_DONE; | ||
| 349 | + regs_k.x1 = 0; | ||
| 347 | } else if (regs_k.x0 == TZ_SWITCH_REQ_STD_RESPONSE) { | 350 | } else if (regs_k.x0 == TZ_SWITCH_REQ_STD_RESPONSE) { |
| 348 | regs_k.x0 = SMC_STD_RESPONSE; | 351 | regs_k.x0 = SMC_STD_RESPONSE; |
| 349 | regs_k.x1 = SMC_EXIT_NORMAL; | 352 | regs_k.x1 = SMC_EXIT_NORMAL; |
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | enum tz_switch_req { | 18 | enum tz_switch_req { |
| 19 | TZ_SWITCH_REQ_ENTRY_DONE, | 19 | TZ_SWITCH_REQ_ENTRY_DONE, |
| 20 | + TZ_SWITCH_REQ_ON_DONE, | ||
| 20 | TZ_SWITCH_REQ_STD_REQUEST, | 21 | TZ_SWITCH_REQ_STD_REQUEST, |
| 21 | TZ_SWITCH_REQ_STD_RESPONSE, | 22 | TZ_SWITCH_REQ_STD_RESPONSE, |
| 22 | TZ_SWITCH_REQ_NR | 23 | TZ_SWITCH_REQ_NR |
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | -#define PLAT_CPU_NUM 1 | 16 | +#define PLAT_CPU_NUM 8 |
| 17 | 17 | ||
| 18 | void teeos_cfg_init(paddr_t start_pa); | 18 | void teeos_cfg_init(paddr_t start_pa); |
| 19 | 19 | ||
| @@ -496,6 +496,7 @@ void sys_thread_exit(void) | |||
| 496 | int sys_set_affinity(cap_t thread_cap, int aff) | 496 | int sys_set_affinity(cap_t thread_cap, int aff) |
| 497 | { | 497 | { |
| 498 | struct thread *thread; | 498 | struct thread *thread; |
| 499 | + int ret; | ||
| 499 | 500 | ||
| 500 | if (aff >= PLAT_CPU_NUM) | 501 | if (aff >= PLAT_CPU_NUM) |
| 501 | return -EINVAL; | 502 | return -EINVAL; |
| @@ -509,7 +510,23 @@ int sys_set_affinity(cap_t thread_cap, int aff) | |||
| 509 | if (thread == NULL) | 510 | if (thread == NULL) |
| 510 | return -ECAPBILITY; | 511 | return -ECAPBILITY; |
| 511 | 512 | ||
| 512 | - thread->thread_ctx->affinity = aff; | 513 | + if (thread->thread_ctx->state == TS_READY) { |
| 514 | + ret = sched_dequeue(thread); | ||
| 515 | + if (ret != 0) { | ||
| 516 | + if (thread_cap != 0) | ||
| 517 | + obj_put(thread); | ||
| 518 | + return ret; | ||
| 519 | + } | ||
| 520 | + thread->thread_ctx->affinity = aff; | ||
| 521 | + ret = sched_enqueue(thread); | ||
| 522 | + if (ret != 0) { | ||
| 523 | + if (thread_cap != 0) | ||
| 524 | + obj_put(thread); | ||
| 525 | + return ret; | ||
| 526 | + } | ||
| 527 | + } else { | ||
| 528 | + thread->thread_ctx->affinity = aff; | ||
| 529 | + } | ||
| 513 | 530 | ||
| 514 | if (thread_cap != 0) | 531 | if (thread_cap != 0) |
| 515 | obj_put(thread); | 532 | obj_put(thread); |
| @@ -190,7 +190,13 @@ static void __pbrr_sched_dequeue(struct thread *thread) | |||
| 190 | 190 | ||
| 191 | static int pbrr_sched_dequeue(struct thread *thread) | 191 | static int pbrr_sched_dequeue(struct thread *thread) |
| 192 | { | 192 | { |
| 193 | - return -1; // unused | 193 | + if (thread->thread_ctx->state != TS_READY) { |
| 194 | + kwarn("%s: thread state is %d\n", __func__, thread->thread_ctx->state); | ||
| 195 | + return -EINVAL; | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + __pbrr_sched_dequeue(thread); | ||
| 199 | + return 0; | ||
| 194 | } | 200 | } |
| 195 | 201 | ||
| 196 | static struct thread *pbrr_sched_choose_thread(void) | 202 | static struct thread *pbrr_sched_choose_thread(void) |
| @@ -39,6 +39,9 @@ | |||
| 39 | 39 | ||
| 40 | 40 | ||
| 41 | 41 | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + | ||
| 42 | 45 | ||
| 43 | 46 | ||
| 44 | 47 | ||
| @@ -155,6 +158,15 @@ void sys_perf_null(void) | |||
| 155 | } | 158 | } |
| 156 | /* DELETE */ | 159 | /* DELETE */ |
| 157 | 160 | ||
| 161 | +int sys_get_cpu_id(void) | ||
| 162 | +{ | ||
| 163 | + | ||
| 164 | + return smp_get_cpu_id(); | ||
| 165 | + | ||
| 166 | + return 0; | ||
| 167 | + | ||
| 168 | +} | ||
| 169 | + | ||
| 158 | void sys_get_pci_device(int class, u64 pci_dev_uaddr) | 170 | void sys_get_pci_device(int class, u64 pci_dev_uaddr) |
| 159 | { | 171 | { |
| 160 | 172 | ||
| @@ -245,6 +257,7 @@ const void *syscall_table[NR_SYSCALL] = { | |||
| 245 | [SYS_get_affinity] = sys_get_affinity, | 257 | [SYS_get_affinity] = sys_get_affinity, |
| 246 | [SYS_set_prio] = sys_set_prio, | 258 | [SYS_set_prio] = sys_set_prio, |
| 247 | [SYS_get_prio] = sys_get_prio, | 259 | [SYS_get_prio] = sys_get_prio, |
| 260 | + [SYS_get_cpu_id] = sys_get_cpu_id, | ||
| 248 | /* IPC */ | 261 | /* IPC */ |
| 249 | /* - procedure call */ | 262 | /* - procedure call */ |
| 250 | [SYS_register_server] = sys_register_server, | 263 | [SYS_register_server] = sys_register_server, |
| @@ -72,6 +72,7 @@ | |||
| 72 | 72 | ||
| 73 | 73 | ||
| 74 | 74 | ||
| 75 | + | ||
| 75 | 76 | ||
| 76 | /* IPC */ | 77 | /* IPC */ |
| 77 | /* - procedure call */ | 78 | /* - procedure call */ |
| @@ -12,12 +12,45 @@ | |||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | + | ||
| 15 | 16 | ||
| 16 | 17 | ||
| 17 | int32_t enable_local_irq(void); | 18 | int32_t enable_local_irq(void); |
| 18 | 19 | ||
| 19 | int32_t disable_local_irq(void); | 20 | int32_t disable_local_irq(void); |
| 20 | 21 | ||
| 22 | +/* | ||
| 23 | + * set_irq_pending() raises a GIC interrupt from a user-space system service. | ||
| 24 | + * | ||
| 25 | + * This is used by TEE framework services that need to notify the REE through a | ||
| 26 | + * non-secure SPI. The irq argument must be a GIC hardware interrupt number, not | ||
| 27 | + * a Linux virtual IRQ. | ||
| 28 | + */ | ||
| 29 | +int32_t set_irq_pending(uint32_t irq); | ||
| 30 | + | ||
| 31 | +/* | ||
| 32 | + * clear_irq_pending() clears a GIC interrupt pending state. | ||
| 33 | + * | ||
| 34 | + * This is used before enabling a notify SPI so stale pending state does not | ||
| 35 | + * generate a spurious REE wakeup. | ||
| 36 | + */ | ||
| 37 | +int32_t clear_irq_pending(uint32_t irq); | ||
| 38 | + | ||
| 39 | +/* | ||
| 40 | + * set_irq_nonsecure() moves a GIC interrupt into the non-secure group. | ||
| 41 | + * | ||
| 42 | + * The notify SPI must be non-secure because Linux owns the IRQ handler that | ||
| 43 | + * drains the notify shared memory. | ||
| 44 | + */ | ||
| 45 | +int32_t set_irq_nonsecure(uint32_t irq); | ||
| 46 | + | ||
| 47 | +/* | ||
| 48 | + * mask_irq() masks or unmasks a GIC interrupt. | ||
| 49 | + * | ||
| 50 | + * Passing true masks the interrupt and passing false unmasks it. | ||
| 51 | + */ | ||
| 52 | +int32_t mask_irq(uint32_t irq, bool mask); | ||
| 53 | + | ||
| 21 | void init_sysctrl_hdlr(void); | 54 | void init_sysctrl_hdlr(void); |
| 22 | 55 | ||
| 23 | 56 | ||
| @@ -28,6 +28,7 @@ enum cap_teesmc_buf_ops { | |||
| 28 | 28 | ||
| 29 | enum cap_teesmc_req { | 29 | enum cap_teesmc_req { |
| 30 | CAP_TEESMC_REQ_STARTTZ, | 30 | CAP_TEESMC_REQ_STARTTZ, |
| 31 | + CAP_TEESMC_REQ_ONDONE, | ||
| 31 | CAP_TEESMC_REQ_IDLE, | 32 | CAP_TEESMC_REQ_IDLE, |
| 32 | }; | 33 | }; |
| 33 | 34 | ||
| @@ -14,6 +14,12 @@ | |||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | +enum gicv3_irq_op { | ||
| 18 | + GICV3_OP_SET_GROUP = 2, | ||
| 19 | + GICV3_OP_SET_PENDING = 4, | ||
| 20 | + GICV3_OP_MASK = 5, | ||
| 21 | +}; | ||
| 22 | + | ||
| 17 | int32_t enable_local_irq(void) | 23 | int32_t enable_local_irq(void) |
| 18 | { | 24 | { |
| 19 | usys_enable_local_irq(); | 25 | usys_enable_local_irq(); |
| @@ -26,6 +32,52 @@ int32_t disable_local_irq(void) | |||
| 26 | return 0; | 32 | return 0; |
| 27 | } | 33 | } |
| 28 | 34 | ||
| 35 | +/* | ||
| 36 | + * set_irq_pending() asks the kernel to set a hardware interrupt pending. | ||
| 37 | + * | ||
| 38 | + * The caller passes a GIC hardware interrupt number that has already been | ||
| 39 | + * agreed with the REE side. The kernel validates the interrupt range in | ||
| 40 | + * sys_irq_op()/gicv3_op(), so this wrapper only keeps the framework code from | ||
| 41 | + * depending on raw GIC operation numbers. | ||
| 42 | + */ | ||
| 43 | +int32_t set_irq_pending(uint32_t irq) | ||
| 44 | +{ | ||
| 45 | + return usys_irq_op((int)irq, GICV3_OP_SET_PENDING, 1); | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +/* | ||
| 49 | + * clear_irq_pending() clears pending state before enabling a notify interrupt. | ||
| 50 | + * | ||
| 51 | + * This keeps old pending state from generating a spurious notification after | ||
| 52 | + * the REE handler has been registered. | ||
| 53 | + */ | ||
| 54 | +int32_t clear_irq_pending(uint32_t irq) | ||
| 55 | +{ | ||
| 56 | + return usys_irq_op((int)irq, GICV3_OP_SET_PENDING, 0); | ||
| 57 | +} | ||
| 58 | + | ||
| 59 | +/* | ||
| 60 | + * set_irq_nonsecure() configures an interrupt as non-secure Group 1. | ||
| 61 | + * | ||
| 62 | + * Linux receives the notify SPI in the non-secure world, so TEE must not leave | ||
| 63 | + * the interrupt in a secure group. | ||
| 64 | + */ | ||
| 65 | +int32_t set_irq_nonsecure(uint32_t irq) | ||
| 66 | +{ | ||
| 67 | + return usys_irq_op((int)irq, GICV3_OP_SET_GROUP, 1); | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +/* | ||
| 71 | + * mask_irq() masks or unmasks a GIC interrupt. | ||
| 72 | + * | ||
| 73 | + * The wrapper keeps system services from depending on the raw GIC operation | ||
| 74 | + * number while still allowing notify initialization to unmask its SPI. | ||
| 75 | + */ | ||
| 76 | +int32_t mask_irq(uint32_t irq, bool mask) | ||
| 77 | +{ | ||
| 78 | + return usys_irq_op((int)irq, GICV3_OP_MASK, mask ? 1 : 0); | ||
| 79 | +} | ||
| 80 | + | ||
| 29 | void init_sysctrl_hdlr(void) | 81 | void init_sysctrl_hdlr(void) |
| 30 | { | 82 | { |
| 31 | printf("%s not implemented!\n", __func__); | 83 | printf("%s not implemented!\n", __func__); |
| @@ -29,10 +29,12 @@ int smc_wait_switch_req(struct cap_teesmc_buf *smc_buf) | |||
| 29 | 29 | ||
| 30 | int smc_switch_req(enum cap_teesmc_req req) | 30 | int smc_switch_req(enum cap_teesmc_req req) |
| 31 | { | 31 | { |
| 32 | - struct smc_registers regs; | 32 | + struct smc_registers regs = {0}; |
| 33 | 33 | ||
| 34 | if (req == CAP_TEESMC_REQ_STARTTZ) { | 34 | if (req == CAP_TEESMC_REQ_STARTTZ) { |
| 35 | regs.x0 = TZ_SWITCH_REQ_ENTRY_DONE; | 35 | regs.x0 = TZ_SWITCH_REQ_ENTRY_DONE; |
| 36 | + } else if (req == CAP_TEESMC_REQ_ONDONE) { | ||
| 37 | + regs.x0 = TZ_SWITCH_REQ_ON_DONE; | ||
| 36 | } else if (req == CAP_TEESMC_REQ_IDLE) { | 38 | } else if (req == CAP_TEESMC_REQ_IDLE) { |
| 37 | regs.x0 = TZ_SWITCH_REQ_STD_RESPONSE; | 39 | regs.x0 = TZ_SWITCH_REQ_STD_RESPONSE; |
| 38 | regs.x1 = 0; | 40 | regs.x1 = 0; |
| @@ -164,6 +164,7 @@ | |||
| 164 | 164 | ||
| 165 | 165 | ||
| 166 | 166 | ||
| 167 | + | ||
| 167 | 168 | ||
| 168 | /* IPC */ | 169 | /* IPC */ |
| 169 | /* - procedure call */ | 170 | /* - procedure call */ |
| @@ -65,6 +65,7 @@ _Noreturn void usys_ipc_exit_routine_return(void); | |||
| 65 | void usys_debug_log(long arg); | 65 | void usys_debug_log(long arg); |
| 66 | int usys_set_affinity(cap_t thread_cap, s32 aff); | 66 | int usys_set_affinity(cap_t thread_cap, s32 aff); |
| 67 | s32 usys_get_affinity(cap_t thread_cap); | 67 | s32 usys_get_affinity(cap_t thread_cap); |
| 68 | +int usys_get_cpu_id(void); | ||
| 68 | 69 | ||
| 69 | unsigned long usys_get_free_mem_size(void); | 70 | unsigned long usys_get_free_mem_size(void); |
| 70 | void usys_get_mem_usage_msg(void); | 71 | void usys_get_mem_usage_msg(void); |
| @@ -132,6 +133,7 @@ struct smc_registers { | |||
| 132 | }; | 133 | }; |
| 133 | enum tz_switch_req { | 134 | enum tz_switch_req { |
| 134 | TZ_SWITCH_REQ_ENTRY_DONE, | 135 | TZ_SWITCH_REQ_ENTRY_DONE, |
| 136 | + TZ_SWITCH_REQ_ON_DONE, | ||
| 135 | TZ_SWITCH_REQ_STD_REQUEST, | 137 | TZ_SWITCH_REQ_STD_REQUEST, |
| 136 | TZ_SWITCH_REQ_STD_RESPONSE, | 138 | TZ_SWITCH_REQ_STD_RESPONSE, |
| 137 | TZ_SWITCH_REQ_NR | 139 | TZ_SWITCH_REQ_NR |
| @@ -99,6 +99,11 @@ s32 usys_get_affinity(cap_t thread_cap) | |||
| 99 | return chcore_syscall1(CHCORE_SYS_get_affinity, thread_cap); | 99 | return chcore_syscall1(CHCORE_SYS_get_affinity, thread_cap); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | +int usys_get_cpu_id(void) | ||
| 103 | +{ | ||
| 104 | + return chcore_syscall0(CHCORE_SYS_get_cpu_id); | ||
| 105 | +} | ||
| 106 | + | ||
| 102 | int usys_get_prio(cap_t thread_cap) | 107 | int usys_get_prio(cap_t thread_cap) |
| 103 | { | 108 | { |
| 104 | return chcore_syscall1(CHCORE_SYS_get_prio, thread_cap); | 109 | return chcore_syscall1(CHCORE_SYS_get_prio, thread_cap); |