diff options
author | Jack Rosenthal <jrosenth@chromium.org> | 2021-11-04 12:11:58 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-11-05 04:22:34 +0000 |
commit | 252457d4b21f46889eebad61d4c0a65331919cec (patch) | |
tree | 01856c4d31d710b20e85a74c8d7b5836e35c3b98 /core | |
parent | 08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff) | |
download | chrome-ec-stabilize-14388.61.B-ish.tar.gz |
ish: Trim down the release branchstabilize-wristpin-14469.59.B-ishstabilize-voshyr-14637.B-ishstabilize-quickfix-14695.187.B-ishstabilize-quickfix-14695.124.B-ishstabilize-quickfix-14526.91.B-ishstabilize-14695.85.B-ishstabilize-14695.107.B-ishstabilize-14682.B-ishstabilize-14633.B-ishstabilize-14616.B-ishstabilize-14589.B-ishstabilize-14588.98.B-ishstabilize-14588.14.B-ishstabilize-14588.123.B-ishstabilize-14536.B-ishstabilize-14532.B-ishstabilize-14528.B-ishstabilize-14526.89.B-ishstabilize-14526.84.B-ishstabilize-14526.73.B-ishstabilize-14526.67.B-ishstabilize-14526.57.B-ishstabilize-14498.B-ishstabilize-14496.B-ishstabilize-14477.B-ishstabilize-14469.9.B-ishstabilize-14469.8.B-ishstabilize-14469.58.B-ishstabilize-14469.41.B-ishstabilize-14442.B-ishstabilize-14438.B-ishstabilize-14411.B-ishstabilize-14396.B-ishstabilize-14395.B-ishstabilize-14388.62.B-ishstabilize-14388.61.B-ishstabilize-14388.52.B-ishstabilize-14385.B-ishstabilize-14345.B-ishstabilize-14336.B-ishstabilize-14333.B-ishrelease-R99-14469.B-ishrelease-R98-14388.B-ishrelease-R102-14695.B-ishrelease-R101-14588.B-ishrelease-R100-14526.B-ishfirmware-cherry-14454.B-ishfirmware-brya-14505.B-ishfirmware-brya-14505.71.B-ishfactory-kukui-14374.B-ishfactory-guybrush-14600.B-ishfactory-cherry-14455.B-ishfactory-brya-14517.B-ish
In the interest of making long-term branch maintenance incur as little
technical debt on us as possible, we should not maintain any files on
the branch we are not actually using.
This has the added effect of making it extremely clear when merging CLs
from the main branch when changes have the possibility to affect us.
The follow-on CL adds a convenience script to actually pull updates from
the main branch and generate a CL for the update.
BUG=b:204206272
BRANCH=ish
TEST=make BOARD=arcada_ish && make BOARD=drallion_ish
Signed-off-by: Jack Rosenthal <jrosenth@chromium.org>
Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038
Reviewed-by: Jett Rink <jettrink@chromium.org>
Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'core')
97 files changed, 0 insertions, 12564 deletions
diff --git a/core/cortex-m/aes.S b/core/cortex-m/aes.S deleted file mode 120000 index 39d1286943..0000000000 --- a/core/cortex-m/aes.S +++ /dev/null @@ -1 +0,0 @@ -../../third_party/boringssl/core/cortex-m/aes.S
\ No newline at end of file diff --git a/core/cortex-m/atomic.h b/core/cortex-m/atomic.h deleted file mode 100644 index e9b96f6fd5..0000000000 --- a/core/cortex-m/atomic.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Atomic operations for ARMv7 */ - -#ifndef __CROS_EC_ATOMIC_H -#define __CROS_EC_ATOMIC_H - -#include "common.h" - -typedef int atomic_t; -typedef atomic_t atomic_val_t; - -static inline atomic_val_t atomic_clear_bits(atomic_t *addr, atomic_val_t bits) -{ - return __atomic_fetch_and(addr, ~bits, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_or(atomic_t *addr, atomic_val_t bits) -{ - return __atomic_fetch_or(addr, bits, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_add(atomic_t *addr, atomic_val_t value) -{ - return __atomic_fetch_add(addr, value, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_sub(atomic_t *addr, atomic_val_t value) -{ - return __atomic_fetch_sub(addr, value, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_clear(atomic_t *addr) -{ - return __atomic_exchange_n(addr, 0, __ATOMIC_SEQ_CST); -} - -#endif /* __CROS_EC_ATOMIC_H */ diff --git a/core/cortex-m/build.mk b/core/cortex-m/build.mk deleted file mode 100644 index ad7ab6eacc..0000000000 --- a/core/cortex-m/build.mk +++ /dev/null @@ -1,34 +0,0 @@ -# -*- makefile -*- -# Copyright 2012 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Cortex-M4 core OS files build -# - -# Use coreboot-sdk -$(call set-option,CROSS_COMPILE,\ - $(CROSS_COMPILE_arm),\ - /opt/coreboot-sdk/bin/arm-eabi-) - -# FPU compilation flags -CFLAGS_FPU-$(CONFIG_FPU)=-mfpu=fpv4-sp-d16 -mfloat-abi=hard - -# CPU specific compilation flags -CFLAGS_CPU+=-mthumb -Os -mno-sched-prolog -CFLAGS_CPU+=-mno-unaligned-access -CFLAGS_CPU+=$(CFLAGS_FPU-y) - -ifneq ($(CONFIG_LTO),) -CFLAGS_CPU+=-flto -LDFLAGS_EXTRA+=-flto -endif - -core-y=cpu.o debug.o init.o ldivmod.o llsr.o uldivmod.o vecttable.o -core-$(CONFIG_AES)+=aes.o -core-$(CONFIG_AES_GCM)+=ghash.o -core-$(CONFIG_ARMV7M_CACHE)+=cache.o -core-$(CONFIG_COMMON_PANIC_OUTPUT)+=panic.o -core-$(CONFIG_COMMON_RUNTIME)+=switch.o task.o -core-$(CONFIG_WATCHDOG)+=watchdog.o -core-$(CONFIG_MPU)+=mpu.o diff --git a/core/cortex-m/cache.S b/core/cortex-m/cache.S deleted file mode 100644 index 0a3d3bb67d..0000000000 --- a/core/cortex-m/cache.S +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * ARMv7-M architectural caches maintenance operations. - */ - -.syntax unified -.text -.thumb - -/* System Control Block: cache registers */ -#define SCB_CCSIDR 0xe000ed80 -#define SCB_CCSELR 0xe000ed84 -#define SCB_DCISW 0xe000ef60 -#define SCB_DCCISW 0xe000ef74 - -.macro dcache_set_way_op name register -@ -@ Perform an operation on all D-cache sets/ways. -@ -@ Note: implemented in assembly to guarantee that we are not touching the -@ D-cache in the middle of the loop. -@ -.thumb_func -.section .text.\name -.global \name -\name: - /* Select Level-1 Data cache (for operations on CCSIDR). */ - ldr r1, =SCB_CCSELR - movs r0, #0 - ldr r2, =SCB_CCSIDR - str r0, [r1] /* set CCSELR = 0 */ - - /* Ensure the CCSELR write is effective before reading CCSIDR. */ - dsb - /* CCSIDR contains the cache geometry. */ - ldr r3, [r2] /* [27:13] Number of sets -1 [12:3] Number of ways -1 */ - - /* register used to do the set/way cache operation. */ - ldr r0, =\register - /* r2 is the number of cache 'sets' - 1 */ - ubfx r2, r3, #13, #15 - /* r12 is the number of cache 'ways' - 1 */ - ubfx r12, r3, #3, #10 - -1: - mov r1, r12 /* reset way index */ -2: - /* - * Build address Set/Way operation e.g DC(C)ISW - * [31:30] way index [13:5] set index - */ - lsls r3, r2, #5 /* set index */ - /* TODO(crbug.com/848704) remove cache geometry assumptions */ - orr r3, r3, r1, lsl #30 /* way index */ - /* Perform operation (e.g invalidate) on a D-cache line */ - str r3, [r0] - /* go to previous way */ - subs r1, #1 - bcs 2b - /* go to previous set */ - subs r2, #1 - bcs 1b - - /* Ensure everything has propagated and return. */ - dsb - isb - bx lr -.endm - -/* D-cache Invalidate by set-way */ -dcache_set_way_op cpu_invalidate_dcache SCB_DCISW - -/* D-cache Clean and Invalidate by set-way, to Point of Coherency */ -dcache_set_way_op cpu_clean_invalidate_dcache SCB_DCCISW diff --git a/core/cortex-m/config_core.h b/core/cortex-m/config_core.h deleted file mode 100644 index 0665b28852..0000000000 --- a/core/cortex-m/config_core.h +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_CONFIG_CORE_H -#define __CROS_EC_CONFIG_CORE_H - -/* Linker binary architecture and format */ -#define BFD_ARCH arm -#define BFD_FORMAT "elf32-littlearm" - -#define CONFIG_SOFTWARE_PANIC - -#endif /* __CROS_EC_CONFIG_CORE_H */ diff --git a/core/cortex-m/cpu.c b/core/cortex-m/cpu.c deleted file mode 100644 index 7c31892c18..0000000000 --- a/core/cortex-m/cpu.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Set up the Cortex-M core - */ - -#include "common.h" -#include "cpu.h" -#include "hooks.h" - -void cpu_init(void) -{ - /* Catch divide by 0 and unaligned access */ - CPU_NVIC_CCR |= CPU_NVIC_CCR_DIV_0_TRAP | CPU_NVIC_CCR_UNALIGN_TRAP; - - /* Enable reporting of memory faults, bus faults and usage faults */ - CPU_NVIC_SHCSR |= CPU_NVIC_SHCSR_MEMFAULTENA | - CPU_NVIC_SHCSR_BUSFAULTENA | CPU_NVIC_SHCSR_USGFAULTENA; -} - -#ifdef CONFIG_ARMV7M_CACHE -static void cpu_invalidate_icache(void) -{ - /* - * Invalidates the entire instruction cache to the point of - * unification. - */ - CPU_SCB_ICIALLU = 0; - asm volatile("dsb; isb"); -} - -void cpu_enable_caches(void) -{ - /* Check whether the I-cache is already enabled */ - if (!(CPU_NVIC_CCR & CPU_NVIC_CCR_ICACHE)) { - /* Invalidate the I-cache first */ - cpu_invalidate_icache(); - /* Turn on the caching */ - CPU_NVIC_CCR |= CPU_NVIC_CCR_ICACHE; - asm volatile("dsb; isb"); - } - /* Check whether the D-cache is already enabled */ - if (!(CPU_NVIC_CCR & CPU_NVIC_CCR_DCACHE)) { - /* Invalidate the D-cache first */ - cpu_invalidate_dcache(); - /* Turn on the caching */ - CPU_NVIC_CCR |= CPU_NVIC_CCR_DCACHE; - asm volatile("dsb; isb"); - } -} - -void cpu_disable_caches(void) -{ - /* - * Disable the I-cache and the D-cache - * The I-cache will be invalidated after the reboot/sysjump if needed - * (e.g after a flash update). - */ - cpu_clean_invalidate_dcache(); - CPU_NVIC_CCR &= ~(CPU_NVIC_CCR_ICACHE | CPU_NVIC_CCR_DCACHE); - asm volatile("dsb; isb"); -} -DECLARE_HOOK(HOOK_SYSJUMP, cpu_disable_caches, HOOK_PRIO_LAST); -#endif /* CONFIG_ARMV7M_CACHE */ diff --git a/core/cortex-m/cpu.h b/core/cortex-m/cpu.h deleted file mode 100644 index 0b03302bfc..0000000000 --- a/core/cortex-m/cpu.h +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Registers map and definitions for Cortex-MLM4x processor - */ - -#ifndef __CROS_EC_CPU_H -#define __CROS_EC_CPU_H - -#include <stdint.h> -#include "compile_time_macros.h" - -/* Macro to access 32-bit registers */ -#define CPUREG(addr) (*(volatile uint32_t*)(addr)) - -#define CPU_NVIC_ST_CTRL CPUREG(0xE000E010) -#define ST_ENABLE BIT(0) -#define ST_TICKINT BIT(1) -#define ST_CLKSOURCE BIT(2) -#define ST_COUNTFLAG BIT(16) - -/* Nested Vectored Interrupt Controller */ -#define CPU_NVIC_EN(x) CPUREG(0xe000e100 + 4 * (x)) -#define CPU_NVIC_DIS(x) CPUREG(0xe000e180 + 4 * (x)) -#define CPU_NVIC_UNPEND(x) CPUREG(0xe000e280 + 4 * (x)) -#define CPU_NVIC_PRI(x) CPUREG(0xe000e400 + 4 * (x)) -/* SCB AIRCR : Application interrupt and reset control register */ -#define CPU_NVIC_APINT CPUREG(0xe000ed0c) -#define CPU_NVIC_APINT_SYSRST BIT(2) /* System reset request */ -#define CPU_NVIC_APINT_PRIOGRP (BIT(8)|BIT(9)|BIT(10)) -#define CPU_NVIC_APINT_ENDIAN BIT(15) /* Endianness */ -#define CPU_NVIC_APINT_KEY_RD (0xFA05U << 16) -#define CPU_NVIC_APINT_KEY_WR (0x05FAU << 16) -/* NVIC STIR : Software Trigger Interrupt Register */ -#define CPU_NVIC_SWTRIG CPUREG(0xe000ef00) -/* SCB SCR : System Control Register */ -#define CPU_SCB_SYSCTRL CPUREG(0xe000ed10) - -#define CPU_NVIC_CCR CPUREG(0xe000ed14) -#define CPU_NVIC_SHCSR CPUREG(0xe000ed24) -#define CPU_NVIC_CFSR CPUREG(0xe000ed28) -#define CPU_NVIC_HFSR CPUREG(0xe000ed2c) -#define CPU_NVIC_DFSR CPUREG(0xe000ed30) -#define CPU_NVIC_MFAR CPUREG(0xe000ed34) -#define CPU_NVIC_BFAR CPUREG(0xe000ed38) - -enum { - CPU_NVIC_CFSR_BFARVALID = BIT(15), - CPU_NVIC_CFSR_MFARVALID = BIT(7), - - CPU_NVIC_CCR_ICACHE = BIT(17), - CPU_NVIC_CCR_DCACHE = BIT(16), - CPU_NVIC_CCR_DIV_0_TRAP = BIT(4), - CPU_NVIC_CCR_UNALIGN_TRAP = BIT(3), - - CPU_NVIC_HFSR_DEBUGEVT = 1UL << 31, - CPU_NVIC_HFSR_FORCED = BIT(30), - CPU_NVIC_HFSR_VECTTBL = BIT(1), - - CPU_NVIC_SHCSR_MEMFAULTENA = BIT(16), - CPU_NVIC_SHCSR_BUSFAULTENA = BIT(17), - CPU_NVIC_SHCSR_USGFAULTENA = BIT(18), -}; - -/* System Control Block: cache registers */ -#define CPU_SCB_CCSIDR CPUREG(0xe000ed80) -#define CPU_SCB_CCSELR CPUREG(0xe000ed84) -#define CPU_SCB_ICIALLU CPUREG(0xe000ef50) -#define CPU_SCB_DCISW CPUREG(0xe000ef60) -#define CPU_SCB_DCCISW CPUREG(0xe000ef74) - -/* Set up the cpu to detect faults */ -void cpu_init(void); -/* Enable the CPU I-cache and D-cache if they are not already enabled */ -void cpu_enable_caches(void); -/* Disable the CPU I-cache and D-cache */ -void cpu_disable_caches(void); -/* Invalidate the D-cache */ -void cpu_invalidate_dcache(void); -/* Clean and Invalidate the D-cache to the Point of Coherency */ -void cpu_clean_invalidate_dcache(void); - -/* Invalidate a single range of the D-cache */ -void cpu_invalidate_dcache_range(uintptr_t base, unsigned int length); -/* Clean and Invalidate a single range of the D-cache */ -void cpu_clean_invalidate_dcache_range(uintptr_t base, unsigned int length); - -/* Set the priority of the given IRQ in the NVIC (0 is highest). */ -static inline void cpu_set_interrupt_priority(uint8_t irq, uint8_t priority) -{ - const uint32_t prio_shift = irq % 4 * 8 + 5; - - if (priority > 7) - priority = 7; - - CPU_NVIC_PRI(irq / 4) = - (CPU_NVIC_PRI(irq / 4) & - ~(7 << prio_shift)) | - (priority << prio_shift); -} - -#endif /* __CROS_EC_CPU_H */ diff --git a/core/cortex-m/debug.c b/core/cortex-m/debug.c deleted file mode 100644 index db8891b5d8..0000000000 --- a/core/cortex-m/debug.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "debug.h" -#include "stdbool.h" - -bool debugger_is_connected(void) -{ - return CPU_DHCSR & DHCSR_C_DEBUGEN; -} diff --git a/core/cortex-m/debug.h b/core/cortex-m/debug.h deleted file mode 100644 index ae5ef08d06..0000000000 --- a/core/cortex-m/debug.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_DEBUG_H -#define __CROS_EC_DEBUG_H - -#include "common.h" -#include "stdbool.h" - -/* For Cortex-M0, see "C1.6.3 Debug Halting Control and Status Register, DHCSR" - * in the ARMv6-M Architecture Reference Manual. - * - * For other Cortex-M, see - * "C1.6.2 Debug Halting Control and Status Register, DHCSR" in the ARMv7-M - * Architecture Reference Manual or - * https://developer.arm.com/documentation/ddi0337/e/core-debug/core-debug-registers/debug-halting-control-and-status-register. - */ -#define CPU_DHCSR REG32(0xE000EDF0) -#define DHCSR_C_DEBUGEN BIT(0) -#define DHCSR_C_HALT BIT(1) -#define DHCSR_C_STEP BIT(2) -#define DHCSR_C_MASKINTS BIT(3) -#ifndef CHIP_CORE_CORTEX_M0 -#define DHCSR_C_SNAPSTALL BIT(5) /* Not available on Cortex-M0 */ -#endif -#define DHCSR_S_REGRDY BIT(16) -#define DHCSR_S_HALT BIT(17) -#define DHCSR_S_SLEEP BIT(18) -#define DHCSR_S_LOCKUP BIT(19) -#define DHCSR_S_RETIRE_ST BIT(24) -#define DHCSR_S_RESET_ST BIT(25) - -bool debugger_is_connected(void); - -#endif /* __CROS_EC_DEBUG_H */ diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S deleted file mode 100644 index 7b08be81a6..0000000000 --- a/core/cortex-m/ec.lds.S +++ /dev/null @@ -1,721 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "config.h" -#include "rwsig.h" - -#define CONCAT_STAGE_1(w, x, y, z) w ## x ## y ## z -#define CONCAT2(w, x) CONCAT_STAGE_1(w, x, , ) -#define CONCAT3(w, x, y) CONCAT_STAGE_1(w, x, y, ) -#define CONCAT4(w, x, y, z) CONCAT_STAGE_1(w, x, y, z) - -#define STRINGIFY0(name) #name -#define STRINGIFY(name) STRINGIFY0(name) - -#ifdef RW_B_LDS -#define FW_MEM_OFF_(section) CONFIG_##section##_B_MEM_OFF -#else -#define FW_MEM_OFF_(section) CONFIG_##section##_MEM_OFF -#endif -#define FW_MEM_OFF(section) (FW_MEM_OFF_(section)) -#define FW_OFF(section) (CONFIG_PROGRAM_MEMORY_BASE + FW_MEM_OFF(section)) - -#define FW_SIZE_(section) CONFIG_##section##_SIZE -#define FW_SIZE(section) FW_SIZE_(section) - -/* - * Define the VMA (virtual memory address) of the ROM_RESIDENT region within - * the EC image. This is full 32-bit address starting from - * CONFIG_PROGRAM_MEMORY_BASE. - */ -#define ROM_RES_OFF(section) FW_OFF(CONCAT2(section, _ROM_RESIDENT)) -#define ROM_RES_SIZE(section) FW_SIZE(CONCAT2(section, _ROM_RESIDENT)) - -/* - * Define the VMA (virtual memory address) of the ROM_RESIDENT region. Instead - * of a full 32-bit address, set the VMA to be an offset within the flash memory - * section. Objects linked into this section can pass the address of the - * object unmodified to the public APIs of the flash and init_rom modules. - */ -#ifdef SECTION_IS_RO -#define ROM_RES_FLASH_OFF(section) \ - FW_MEM_OFF(CONCAT2(section, _ROM_RESIDENT)) + \ - CONFIG_EC_PROTECTED_STORAGE_OFF -#else -#define ROM_RES_FLASH_OFF(section) \ - FW_MEM_OFF(CONCAT2(section, _ROM_RESIDENT)) + \ - CONFIG_EC_WRITABLE_STORAGE_OFF -#endif - -/* Indicates where .data LMA should reside. */ -#undef DATA_LMA_MEM_REGION - -OUTPUT_FORMAT(BFD_FORMAT, BFD_FORMAT, BFD_FORMAT) -OUTPUT_ARCH(BFD_ARCH) -ENTRY(reset) - -MEMORY -{ -#if !defined(CONFIG_FLASH_PHYSICAL) - IROM (rx) : ORIGIN = CONFIG_ROM_BASE, LENGTH = CONFIG_ROM_SIZE -#else -#if defined(SECTION_IS_RO) && defined(NPCX_RO_HEADER) - /* - * Header structure used by npcx booter in RO region. - * Please notice the location of header must be in front of FW - * which needs copy. But header itself won't be copied to code ram - * by booter. - */ - FLASH_HDR (rx) : ORIGIN = FW_OFF(RO_HDR), LENGTH = FW_SIZE(RO_HDR) - FLASH (rx) : ORIGIN = FW_OFF(SECTION) + FW_SIZE(RO_HDR), \ - LENGTH = FW_SIZE(SECTION) - FW_SIZE(RO_HDR) -#else - FLASH (rx) : ORIGIN = FW_OFF(SECTION), LENGTH = FW_SIZE(SECTION) -#endif -#ifdef CONFIG_CHIP_INIT_ROM_REGION - ROM_RESIDENT (r) : \ - ORIGIN = ROM_RES_OFF(SECTION), \ - LENGTH = ROM_RES_SIZE(SECTION) - - ROM_RESIDENT_VMA (r) : \ - ORIGIN = ROM_RES_FLASH_OFF(SECTION), \ - LENGTH = ROM_RES_SIZE(SECTION) -#endif /* CONFIG_CHIP_INIT_ROM_REGION */ -#ifdef CONFIG_SHAREDLIB - SHARED_LIB (rx) : ORIGIN = FW_OFF(SHAREDLIB), \ - LENGTH = FW_SIZE(SHAREDLIB) -#endif -#endif /* !CONFIG_FLASH_PHYSICAL */ - IRAM (rw) : ORIGIN = CONFIG_RAM_BASE, LENGTH = CONFIG_RAM_SIZE - -#ifdef CONFIG_EXTERNAL_STORAGE - CDRAM (rx) : \ - ORIGIN = CONFIG_PROGRAM_MEMORY_BASE + FW_MEM_OFF(SECTION), \ - LENGTH = FW_SIZE(SECTION) -#endif /* CONFIG_EXTERNAL_STORAGE */ - -#ifdef CONFIG_CHIP_MEMORY_REGIONS -#define REGION(name, attr, start, size) \ - name(attr) : ORIGIN = (start), LENGTH = (size) -#define REGION_LOAD REGION -#include "memory_regions.inc" -#undef REGION -#undef REGION_LOAD -#endif /* CONFIG_MEMORY_REGIONS */ - -#ifdef CONFIG_DRAM_BASE - DRAM (rwx) : ORIGIN = CONFIG_DRAM_BASE, LENGTH = CONFIG_DRAM_SIZE -#endif -} - -/* - * Convenience macros for determining the correct output memory section. - */ -#if !defined(CONFIG_FLASH_PHYSICAL) - #define EC_IMAGE_LMA_MEM_REGION IROM - #define EC_IMAGE_VMA_MEM_REGION IROM - #define DATA_LMA_MEM_REGION IROM -#else - #define EC_IMAGE_LMA_MEM_REGION FLASH - #ifdef CONFIG_EXTERNAL_STORAGE - #define EC_IMAGE_VMA_MEM_REGION CDRAM - #else - #define EC_IMAGE_VMA_MEM_REGION FLASH - #endif - - #ifdef CONFIG_CHIP_DATA_IN_INIT_ROM - #define DATA_LMA_MEM_REGION ROM_RESIDENT - #else - #define DATA_LMA_MEM_REGION FLASH - #endif -#endif - -SECTIONS -{ -#if defined(SECTION_IS_RO) && defined(NPCX_RO_HEADER) - .header : { - KEEP(*(.header)) - } > FLASH_HDR -#endif -#ifdef CONFIG_SHAREDLIB - .roshared : { - KEEP(*(.roshared*)) - } > SHARED_LIB -#endif - .text : { -#ifdef SECTION_IS_RO - . = . + CONFIG_RO_HEAD_ROOM; -#endif -#ifdef SECTION_IS_RW - . = . + CONFIG_RW_HEAD_ROOM; -#endif - *(.text.vecttable) - . = ALIGN(4); - __image_data_offset = .; - KEEP(*(.rodata.ver)) - - . = ALIGN(4); - KEEP(*(.rodata.pstate)) - - . = ALIGN(4); - STRINGIFY(OUTDIR/core/CORE/init.o) (.text) -#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 && !defined(CONFIG_HIBERNATE_PSL) - /* Keep hibernate utility in last code ram block */ - . = ALIGN(4); - KEEP(*(.after_init)) - __after_init_end = .; -#endif - *(.text*) -#ifdef CONFIG_EXTERNAL_STORAGE - . = ALIGN(4); - __flash_lpfw_start = .; - /* Entering deep idle FW for better power consumption */ - KEEP(*(.lowpower_ram)) - . = ALIGN(4); - __flash_lpfw_end = .; - __flash_lplfw_start = .; - /* GDMA utilities for better FW download speed */ - KEEP(*(.lowpower_ram2)) - . = ALIGN(4); - __flash_lplfw_end = .; -#endif /* CONFIG_EXTERNAL_STORAGE */ - } > EC_IMAGE_VMA_MEM_REGION AT > EC_IMAGE_LMA_MEM_REGION - - . = ALIGN(4); - .rodata : { - /* Symbols defined here are declared in link_defs.h */ - __irqprio = .; - KEEP(*(.rodata.irqprio)) - __irqprio_end = .; - - . = ALIGN(4); - __cmds = .; - KEEP(*(SORT(.rodata.cmds*))) - __cmds_end = .; - - . = ALIGN(4); - __extension_cmds = .; - KEEP(*(.rodata.extensioncmds)) - __extension_cmds_end = .; - - . = ALIGN(4); - __hcmds = .; - KEEP(*(SORT(.rodata.hcmds*))) - __hcmds_end = .; - - . = ALIGN(4); - __mkbp_evt_srcs = .; - KEEP(*(.rodata.evtsrcs)) - __mkbp_evt_srcs_end = .; - - . = ALIGN(4); - __hooks_init = .; - KEEP(*(.rodata.HOOK_INIT)) - __hooks_init_end = .; - - __hooks_pre_freq_change = .; - KEEP(*(.rodata.HOOK_PRE_FREQ_CHANGE)) - __hooks_pre_freq_change_end = .; - - __hooks_freq_change = .; - KEEP(*(.rodata.HOOK_FREQ_CHANGE)) - __hooks_freq_change_end = .; - - __hooks_sysjump = .; - KEEP(*(.rodata.HOOK_SYSJUMP)) - __hooks_sysjump_end = .; - - __hooks_chipset_pre_init = .; - KEEP(*(.rodata.HOOK_CHIPSET_PRE_INIT)) - __hooks_chipset_pre_init_end = .; - - __hooks_chipset_startup = .; - KEEP(*(.rodata.HOOK_CHIPSET_STARTUP)) - __hooks_chipset_startup_end = .; - - __hooks_chipset_resume = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESUME)) - __hooks_chipset_resume_end = .; - - __hooks_chipset_suspend = .; - KEEP(*(.rodata.HOOK_CHIPSET_SUSPEND)) - __hooks_chipset_suspend_end = .; - -#ifdef CONFIG_CHIPSET_RESUME_INIT_HOOK - __hooks_chipset_resume_init = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESUME_INIT)) - __hooks_chipset_resume_init_end = .; - - __hooks_chipset_suspend_complete = .; - KEEP(*(.rodata.HOOK_CHIPSET_SUSPEND_COMPLETE)) - __hooks_chipset_suspend_complete_end = .; -#endif - - __hooks_chipset_shutdown = .; - KEEP(*(.rodata.HOOK_CHIPSET_SHUTDOWN)) - __hooks_chipset_shutdown_end = .; - - __hooks_chipset_shutdown_complete = .; - KEEP(*(.rodata.HOOK_CHIPSET_SHUTDOWN_COMPLETE)) - __hooks_chipset_shutdown_complete_end = .; - - __hooks_chipset_hard_off = .; - KEEP(*(.rodata.HOOK_CHIPSET_HARD_OFF)) - __hooks_chipset_hard_off_end = .; - - __hooks_chipset_reset = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESET)) - __hooks_chipset_reset_end = .; - - __hooks_ac_change = .; - KEEP(*(.rodata.HOOK_AC_CHANGE)) - __hooks_ac_change_end = .; - - __hooks_lid_change = .; - KEEP(*(.rodata.HOOK_LID_CHANGE)) - __hooks_lid_change_end = .; - - __hooks_tablet_mode_change = .; - KEEP(*(.rodata.HOOK_TABLET_MODE_CHANGE)) - __hooks_tablet_mode_change_end = .; - - __hooks_base_attached_change = .; - KEEP(*(.rodata.HOOK_BASE_ATTACHED_CHANGE)) - __hooks_base_attached_change_end = .; - - __hooks_pwrbtn_change = .; - KEEP(*(.rodata.HOOK_POWER_BUTTON_CHANGE)) - __hooks_pwrbtn_change_end = .; - - __hooks_battery_soc_change = .; - KEEP(*(.rodata.HOOK_BATTERY_SOC_CHANGE)) - __hooks_battery_soc_change_end = .; - -#ifdef CONFIG_USB_SUSPEND - __hooks_usb_change = .; - KEEP(*(.rodata.HOOK_USB_PM_CHANGE)) - __hooks_usb_change_end = .; -#endif - - __hooks_tick = .; - KEEP(*(.rodata.HOOK_TICK)) - __hooks_tick_end = .; - - __hooks_second = .; - KEEP(*(.rodata.HOOK_SECOND)) - __hooks_second_end = .; - - __hooks_usb_pd_disconnect = .; - KEEP(*(.rodata.HOOK_USB_PD_DISCONNECT)) - __hooks_usb_pd_disconnect_end = .; - - __hooks_usb_pd_connect = .; - KEEP(*(.rodata.HOOK_USB_PD_CONNECT)) - __hooks_usb_pd_connect_end = .; - - __deferred_funcs = .; - KEEP(*(.rodata.deferred)) - __deferred_funcs_end = .; - - __usb_desc = .; - KEEP(*(.rodata.usb_desc_conf)) - KEEP(*(SORT(.rodata.usb_desc*))) - __usb_desc_end = .; - . = ALIGN(4); - KEEP(*(.rodata.usb_ep)) - KEEP(*(.rodata.usb_ep.usb_ep_tx)) - KEEP(*(.rodata.usb_ep.usb_ep_rx)) - KEEP(*(.rodata.usb_ep.usb_ep_reset)) - KEEP(*(.rodata.usb_ep.usb_iface_request)) - - . = ALIGN(4); - *(.rodata*) - -#ifndef CONFIG_CHIP_INIT_ROM_REGION - /* - * When a separate ROM resident section isn't enabled, ensure - * the corresponding data objects are linked into the .rodata - * section. - */ - . = ALIGN(4); - __init_rom_start = .; - *(.init.rom) - __init_rom_end = .; -#endif /* CONFIG_CHIP_INIT_ROM_REGION */ - -#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS) - . = ALIGN(64); - KEEP(*(.google)) -#endif - - . = ALIGN(4); - } > EC_IMAGE_VMA_MEM_REGION AT > EC_IMAGE_LMA_MEM_REGION - -#ifdef CONFIG_CHIP_DATA_IN_INIT_ROM - __data_lma_start = ORIGIN(ROM_RESIDENT_VMA); - #define INIT_ROM_LMA (ORIGIN(ROM_RESIDENT_VMA) + SIZEOF(.data)) -#else - __data_lma_start = .; - #define INIT_ROM_LMA ORIGIN(ROM_RESIDENT_VMA) -#endif - -#ifdef CONFIG_PRESERVE_LOGS - .preserve_logs(NOLOAD) : { - . = ALIGN(8); - *(SORT(.preserved_logs.*)) - . = ALIGN(8); - __preserved_logs_end = .; - } > IRAM - - ASSERT((SIZEOF(.preserve_logs) + CONFIG_RAM_BASE) == - __preserved_logs_end, - "preserve_logs must be at CONFIG_RAM_BASE.") -#endif - - .bss : { - /* - * Align to 512 bytes. This is convenient when some memory block - * needs big alignment. This is the beginning of the RAM, - * so there is usually no penalty on aligning this. - */ - . = ALIGN(512); - __bss_start = .; - *(.bss.big_align) - /* Stacks must be 64-bit aligned */ - . = ALIGN(8); - *(.bss.system_stack) - /* Rest of .bss takes care of its own alignment */ - - /* Group libtpm2 data so it can be cleared on system reset */ - __bss_libtpm2_start = .; - /* TPM registers should be cleared at the same time */ - STRINGIFY(OUTDIR/common/tpm_registers.o*)(.bss) - *(.bss.Tpm2_common) - __bss_libtpm2_end = .; - - *(.bss) - - /* - * Reserve space for deferred function firing times. - * Each time is a uint64_t, each func is a 32-bit pointer, - * thus the scaling factor of two. The 8 byte alignment of - * uint64_t is required by the ARM ABI. - */ - . = ALIGN(8); - __deferred_until = .; - . += (__deferred_funcs_end - __deferred_funcs) * (8 / 4); - __deferred_until_end = .; - } > IRAM - - .bss.slow : { - /* Region of RAM reclaimed from the little firmware(LFW). */ - *(.bss.slow) - /* - * Not replacing the loader, so .bss.slow is part of .bss. - * It needs to be followed by __bss_end so that .bss.slow - * will be zeroed by init. - */ - . = ALIGN(4); - __bss_end = .; - } > IRAM - - .data : { - . = ALIGN(4); - __data_start = .; - *(.data.tasks) - - /* - * Group libtpm2 data so it can be reinitialized on - * system reset - */ - __data_libtpm2_start = .; - Tpm2_*(.data) - /* TPM registers should be reinitialized at the same time */ - STRINGIFY(OUTDIR/common/tpm_registers.o*)(.data) - __data_libtpm2_end = .; - - /* - * TPM reset currently only clears BSS for the TPM library. - * It does not reset any initialized variables in data. - * So, make sure there aren't any. - */ - ASSERT(__data_libtpm2_start == __data_libtpm2_end, - "libtpm2 .data section is nonzero"); - - *(.data*) -#ifdef CONFIG_MPU - /* - * It has to be aligned by 32 bytes to be a valid - * MPU region. - */ - . = ALIGN(32); - __iram_text_start = .; -#else - . = ALIGN(4); -#endif - *(.iram.text) -#ifdef CONFIG_MPU - . = ALIGN(32); - __iram_text_end = .; -#else - . = ALIGN(4); -#endif - __data_end = .; - - /* - * Shared memory buffer must be at the end of preallocated - * RAM, so it can expand to use all the remaining RAM. - */ - __shared_mem_buf = .; - - /* NOTHING MAY GO AFTER THIS! */ - } > IRAM AT > DATA_LMA_MEM_REGION - - ASSERT((__shared_mem_buf + CONFIG_SHAREDMEM_MINIMUM_SIZE) <= - (CONFIG_RAM_BASE + CONFIG_RAM_SIZE), - "Not enough space for shared memory.") - - __ram_free = (CONFIG_RAM_BASE + CONFIG_RAM_SIZE) - - (__shared_mem_buf + CONFIG_SHAREDMEM_MINIMUM_SIZE); - -#ifdef CONFIG_CHIP_DATA_IN_INIT_ROM - /* - * .data is ROM resident, last section in the EC image is the .rodata - * section. - */ - #define FLASH_USED_END (LOADADDR(.rodata) + SIZEOF(.rodata)) -#else - /* - * .data is included in the EC image and copied to RAM by the loader. - */ - #define FLASH_USED_END (LOADADDR(.data) + SIZEOF(.data)) -#endif - - /* - * __flash_used is used in flash free calculations by the makefile. - * __image_size is stored in the struct image_data header and used - * in hash calcuations. - */ - __flash_used = FLASH_USED_END - ORIGIN(EC_IMAGE_LMA_MEM_REGION); -#ifndef CONFIG_CHIP_INIT_ROM_REGION -#if !(defined(SECTION_IS_RW) && (CONFIG_FLASH_WRITE_SIZE > 4)) - __image_size = __flash_used; -#else - .rw_image_size_alignment : - { - . = ORIGIN(FLASH) + __flash_used; - BYTE(0xFF); - . = ALIGN (CONFIG_FLASH_WRITE_SIZE); - } > FLASH = 0xFF - - __image_size = __flash_used + SIZEOF(.rw_image_size_alignment); -#endif -#endif /* CONFIG_CHIP_INIT_ROM_REGION */ - -#ifdef CONFIG_FLASH_CROS - /* - * These linker labels are just for analysis and not used in the code. - */ - __config_flash_size = CONFIG_FLASH_SIZE_BYTES; - __config_ro_size = CONFIG_RO_SIZE; - __config_ec_protected_storage_size = CONFIG_EC_PROTECTED_STORAGE_SIZE; - __config_rw_size = CONFIG_RW_SIZE; - __config_ec_writable_storage_size = CONFIG_EC_WRITABLE_STORAGE_SIZE; -#endif - - /* - * The linker won't notice if the .data section is too big to fit, - * apparently because we're sending it into IRAM, not FLASH. - * Verify that all sections linked into the FLASH region will fit. - */ - ASSERT((LENGTH(EC_IMAGE_LMA_MEM_REGION) -#if defined(CONFIG_RWSIG) && defined(SECTION_IS_RO) - - CONFIG_RO_PUBKEY_SIZE -#endif -#if defined(CONFIG_RWSIG) && defined(SECTION_IS_RW) - - CONFIG_RW_SIG_SIZE -#endif - ) >= __flash_used, - "No room left in the flash") - -#ifdef CONFIG_CHIP_INIT_ROM_REGION - /* - * Image layout when ROM_RESIDENT region is used (lower addresses - * at the top). This layout is setup by the LMA assignment. - * - * EC image layout (LMA) VMA - * .header (if RO image) none - * .text code RAM - * .rodata code RAM + .text size - * .data data RAM - * .fill none - * .init_rom flash offset - * - * The loader code copies the .text, .rodata, and .data sections into - * the code RAM of the EC. The .header and .init_rom sections are not - * copied by the loader. - * - * Image layout when ROM_RESIDENT region is used, and - * CONFIG_CHIP_DATA_IN_INIT_ROM is enabled. - * - * EC image layout (LMA) VMA - * .header (if RO image) none - * .text code RAM - * .rodata code RAM + .text size - * .fill none - * .data data RAM - * .init_rom flash offset - * - * The loader code copies the .text and .rodata sections into the code - * RAM of the EC. The .header, .data, and .init_rom sections are not - * copied by the loader. - * - * EC initialization code copies the .data directly from flash to - * data RAM at runtime. - */ - - /* - * The layout assumes the ROM_RESIDENT region follows the FLASH - * region. - */ - ASSERT((ORIGIN(FLASH) + LENGTH(FLASH)) == ORIGIN(ROM_RESIDENT), - ".init_rom section must follow the flash section") - - .init_rom INIT_ROM_LMA : { - . = ALIGN(4); - __init_rom_start = .; - *(.init.rom) - __init_rom_end = .; - } > ROM_RESIDENT_VMA AT > ROM_RESIDENT - - /* - * The ROM_RESIDENT section is assumed to be in the same physical - * flash as the FLASH section. Fill the space between. - */ - .fill : { - . = FLASH_USED_END; - . = ALIGN(4); - __fill_start = .; - FILL(0xFF); - . = ORIGIN(FLASH) + LENGTH(FLASH) - 1; - /* Need at least one byte so section is not omitted */ - BYTE(0xFF); - __fill_end = .; - } > FLASH - - /* - * The end of the .fill region should also be the start of the ROM - * resident region. - */ - ASSERT(__fill_end == ORIGIN(ROM_RESIDENT), - ".fill region end not aligned to start of ROM_RESIDENT region") - - /* - * __image_size is used for hash calculation. When - * CONFIG_CHIP_INIT_ROM_REGION is enabled, this includes the entire - * FLASH region and the bytes used in the .init_rom section. - */ -#ifdef CONFIG_CHIP_DATA_IN_INIT_ROM - __image_size = LENGTH(FLASH) + SIZEOF(.init_rom) + SIZEOF(.data); -#else - __image_size = LENGTH(FLASH) + SIZEOF(.init_rom); -#endif /* CONFIG_CHIP_DATA_IN_INIT_ROM */ -#endif /* CONFIG_CHIP_INIT_ROM_REGION */ - -#ifdef CONFIG_CHIP_MEMORY_REGIONS -#define REGION(name, attr, start, size) \ - .name(NOLOAD) : { \ - __##name##_start = .; \ - KEEP(*(SORT(.name.keep.*))) \ - *(SORT(.name.*)) \ - } > name -#define REGION_LOAD(name, attr, start, size) \ - .name : { \ - __##name##_start = .; \ - KEEP(*(SORT(.name.keep.*))) \ - *(SORT(.name.*)) \ - } > name -#include "memory_regions.inc" -#undef REGION -#undef REGION_LOAD -#endif /* CONFIG_CHIP_MEMORY_REGIONS */ - -#ifdef CONFIG_DRAM_BASE - - /* - * Sections in DRAM region are constructed as like in non-DRAM regions: - * .dram.data LMA is for preserving initialized data across resets. - * The only difference is that they are all in the DRAM region: - * .dram.text | LOAD - * .dram.rodata | LOAD - * .dram.data LMA | LOAD - * .dram.data VMA | - * .dram.bss | NOLOAD - * TODO(b:123269246): Enable MPU protectable DRAM section. This might - * introduce a RO-DRAM section for .dram.text, .dram.rodata and - * .dram.data LMA. - */ - - .dram.text : { - . = ALIGN(4); - KEEP(*(SORT(.dram.text.keep.*))) - *(SORT(.dram.text.*)) - . = ALIGN(4); - } > DRAM - - .dram.rodata : { - . = ALIGN(4); - KEEP(*(SORT(.dram.rodata.keep.*))) - *(SORT(.dram.rodata.*)) - . = ALIGN(4); - } > DRAM - - __dram_data_lma_start = ADDR(.dram.rodata) + SIZEOF(.dram.rodata); - - /* Place .dram.data LMA in between .dram.rodata and .dram.data VMA. */ -#ifdef __clang__ - /* - * The evaluation timing for SIZEOF() and symbols are different in - * ld and lld. - */ - .dram.data __dram_data_lma_start + SIZEOF(.dram.data) : { -#else - .dram.data __dram_data_lma_start + - (__dram_data_end - __dram_data_start) : { -#endif /* __clang__ */ - . = ALIGN(4); - __dram_data_start = .; - *(.dram.data*) - . = ALIGN(4); - __dram_data_end = .; - - /* - * Normally, '> DRAM AT > DRAM' should be the same as '> DRAM', - * and they will be at the same address. However, if the address - * of VMA specified, LMA and VMA might have different addresses: - * '> DRAM' places VMA at the address where section declaration - * specified. - * 'AT > DRAM' places LMA at the location counter's address. - */ - } > DRAM AT > DRAM - - /* - * ld assigns correct attribute for .bss, but not for other .*.bss, - * we need an explicltly NOLOAD. - */ - .dram.bss(NOLOAD) : { - . = ALIGN(4); - __dram_bss_start = .; - *(SORT(.dram.bss*)) - . = ALIGN(4); - __dram_bss_end = .; - } > DRAM -#endif - -#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS)) - /DISCARD/ : { *(.google) } -#endif - /DISCARD/ : { *(.ARM.*) } -} diff --git a/core/cortex-m/ghash.S b/core/cortex-m/ghash.S deleted file mode 120000 index e9acbf4b25..0000000000 --- a/core/cortex-m/ghash.S +++ /dev/null @@ -1 +0,0 @@ -../../third_party/boringssl/core/cortex-m/ghash.S
\ No newline at end of file diff --git a/core/cortex-m/include/fpu.h b/core/cortex-m/include/fpu.h deleted file mode 100644 index 0949d336e2..0000000000 --- a/core/cortex-m/include/fpu.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Math utility functions for ARMv7 */ - -#ifndef __CROS_EC_FPU_H -#define __CROS_EC_FPU_H - -#ifdef CONFIG_FPU -static inline float sqrtf(float v) -{ - float root; - asm volatile( - "fsqrts %0, %1" - : "=w" (root) - : "w" (v) - ); - return root; -} - -static inline float fabsf(float v) -{ - float root; - asm volatile( - "fabss %0, %1" - : "=w" (root) - : "w" (v) - ); - return root; -} -#endif /* CONFIG_FPU */ - -#endif /* __CROS_EC_FPU_H */ diff --git a/core/cortex-m/include/mpu.h b/core/cortex-m/include/mpu.h deleted file mode 100644 index 610728b501..0000000000 --- a/core/cortex-m/include/mpu.h +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* MPU module for Cortex-M3 */ - -#ifndef __CROS_EC_MPU_H -#define __CROS_EC_MPU_H - -#include "common.h" -#include "config.h" /* chips might override MPU attribute settings */ - -/* - * ARMv7-M SRAM region - */ -#define CORTEX_M_SRAM_BASE 0x20000000 - -/* - * Region assignment. 7 as the highest, a higher index has a higher priority. - * For example, using 7 for .iram.text allows us to mark entire RAM XN except - * .iram.text, which is used for hibernation. - * Region assignment is currently wasteful and can be changed if more - * regions are needed in the future. For example, a second region may not - * be necessary for all types, and REGION_CODE_RAM / REGION_STORAGE can be - * made mutually exclusive. - */ -enum mpu_region { - REGION_DATA_RAM = 0, /* For internal data RAM */ - REGION_DATA_RAM2 = 1, /* Second region for unaligned size */ - REGION_CODE_RAM = 2, /* For internal code RAM */ - REGION_CODE_RAM2 = 3, /* Second region for unaligned size */ - REGION_STORAGE = 4, /* For mapped internal storage */ - REGION_STORAGE2 = 5, /* Second region for unaligned size */ - REGION_DATA_RAM_TEXT = 6, /* Exempt region of data RAM */ - REGION_CHIP_RESERVED = 7, /* Reserved for use in chip/ */ - /* only for chips with MPU supporting 16 regions */ - REGION_UNCACHED_RAM = 8, /* For uncached data RAM */ - REGION_UNCACHED_RAM2 = 9, /* Second region for unaligned size */ - REGION_ROLLBACK = 10, /* For rollback */ -}; - -#define MPU_TYPE REG32(0xe000ed90) -#define MPU_CTRL REG32(0xe000ed94) -#define MPU_NUMBER REG32(0xe000ed98) -#define MPU_BASE REG32(0xe000ed9c) -#define MPU_SIZE REG16(0xe000eda0) -#define MPU_ATTR REG16(0xe000eda2) - -/* - * See ARM v7-M Architecture Reference Manual - * Section B3.5.5 MPU Type Register, MPU_TYPE - */ -#define MPU_TYPE_UNIFIED_MASK 0x00FF0001 -#define MPU_TYPE_REG_COUNT(t) (((t) >> 8) & 0xFF) - -#define MPU_CTRL_PRIVDEFEN BIT(2) -#define MPU_CTRL_HFNMIENA BIT(1) -#define MPU_CTRL_ENABLE BIT(0) - -/* - * Minimum region size is 32 bytes, 5 bits of address space - */ -#define MPU_SIZE_BITS_MIN 5 - -/* - * XN (execute never) bit. It's bit 12 if accessed by halfword. - * 0: XN off - * 1: XN on - */ -#define MPU_ATTR_XN BIT(12) - -/* AP bit. See table 3-5 of Stellaris LM4F232H5QC datasheet for details */ -#define MPU_ATTR_NO_NO (0 << 8) /* previleged no access, unprev no access */ -#define MPU_ATTR_RW_NO (1 << 8) /* previleged ReadWrite, unprev no access */ -#define MPU_ATTR_RW_RO (2 << 8) /* previleged ReadWrite, unprev Read-only */ -#define MPU_ATTR_RW_RW (3 << 8) /* previleged ReadWrite, unprev ReadWrite */ -#define MPU_ATTR_RO_NO (5 << 8) /* previleged Read-only, unprev no access */ - -/* Suggested value for TEX S/C/B bit. See table 3-6 of Stellaris LM4F232H5QC - * datasheet and table 38 of STM32F10xxx Cortex-M3 programming manual. */ -#ifndef MPU_ATTR_INTERNAL_SRAM -#define MPU_ATTR_INTERNAL_SRAM 6 /* for Internal SRAM */ -#endif -#ifndef MPU_ATTR_FLASH_MEMORY -#define MPU_ATTR_FLASH_MEMORY 2 /* for flash memory */ -#endif - -/* Represent RW with at most 2 MPU regions. */ -#define MAX_RW_REGIONS 2 -struct mpu_rw_regions { - int num_regions; - uint32_t addr[MAX_RW_REGIONS]; - uint32_t size[MAX_RW_REGIONS]; -}; - -/** - * Enable MPU - */ -void mpu_enable(void); - -/** - * Returns the value of MPU type register - * - * Bit fields: - * [15:8] Number of the data regions implemented or 0 if MPU is not present. - * [1] 0: unified (no distinction between instruction and data) - * 1: separated - */ -uint32_t mpu_get_type(void); - -/* Location of iram.text */ -extern char __iram_text_start; -extern char __iram_text_end; - -/** - * Protect RAM from code execution - */ -int mpu_protect_data_ram(void); - -/** - * Protect code RAM from being overwritten - */ -int mpu_protect_code_ram(void); - -/** - * Protect internal mapped flash memory from code execution - */ -int mpu_lock_ro_flash(void); -int mpu_lock_rw_flash(void); - -/** - * Protect/unprotect rollback region readback. - */ -int mpu_lock_rollback(int lock); - -/** - * Initialize MPU. - * It disables all regions if MPU is implemented. Otherwise, returns - * EC_ERROR_UNIMPLEMENTED. - */ -int mpu_pre_init(void); - -#endif /* __CROS_EC_MPU_H */ diff --git a/core/cortex-m/include/mpu_private.h b/core/cortex-m/include/mpu_private.h deleted file mode 100644 index e6030114c2..0000000000 --- a/core/cortex-m/include/mpu_private.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/** - * @file - * - * @brief Private header file. Not meant to be used outside of mpu.c and tests. - */ - -#ifndef __CROS_EC_MPU_PRIVATE_H -#define __CROS_EC_MPU_PRIVATE_H - -int mpu_num_regions(void); -bool has_mpu(void); -bool mpu_is_unified(void); -void mpu_disable(void); -int mpu_update_region(uint8_t region, uint32_t addr, uint8_t size_bit, - uint16_t attr, uint8_t enable, uint8_t srd); -int mpu_config_region(uint8_t region, uint32_t addr, uint32_t size, - uint16_t attr, uint8_t enable); -struct mpu_rw_regions mpu_get_rw_regions(void); - -#endif /* __CROS_EC_MPU_PRIVATE_H */ diff --git a/core/cortex-m/init.S b/core/cortex-m/init.S deleted file mode 100644 index bc650c4c64..0000000000 --- a/core/cortex-m/init.S +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright 2011 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Cortex-M CPU initialization - */ - -#include "config.h" - -.text -.syntax unified -.code 16 - -.global reset -.thumb_func -reset: - /* - * Ensure we're in privileged mode with main stack. Necessary if - * we've jumped directly here from another image after task_start(). - */ -#ifdef CONFIG_FPU - mov r0, #(1 << 2) @ priv. mode / main stack / floating point on -#else - mov r0, #0 @ priv. mode / main stack / no floating point -#endif - msr control, r0 - isb @ ensure the write is done - - /* Set the vector table on our current code */ - ldr r1, =vectors - ldr r2, =0xE000ED08 /* VTABLE register in SCB*/ - str r1, [r2] - - /* Clear BSS */ - mov r0, #0 - ldr r1,_bss_start - ldr r2,_bss_end -bss_loop: - cmp r1, r2 - it lt - strlt r0, [r1], #4 - blt bss_loop - - /* Copy initialized data to Internal RAM */ - ldr r0,_data_lma_start - - /* - * When the .data section is linked into the .init_rom section, - * _data_lma_start is defined as a flash offset instead of a full - * 32-bit address by the linker script. Add the 32-bit flash base - * address to get a full 32-bit address. - * - * Flash locking isn't needed here as no tasks have been started. - */ -#ifdef CONFIG_CHIP_DATA_IN_INIT_ROM - ldr r1, =CONFIG_MAPPED_STORAGE_BASE - add r0, r0, r1 -#endif - - ldr r1,_data_start - ldr r2,_data_end -data_loop: - ldr r3, [r0], #4 - cmp r1, r2 - it lt - strlt r3, [r1], #4 - blt data_loop - - /* - * Set stack pointer. Already done by Cortex-M hardware, but re-doing - * this here allows software to jump directly to the reset vector. - */ - ldr r0, =stack_end - mov sp, r0 - -#ifdef CONFIG_FPU - /* Enable FPU */ - /* CPACR is located at address 0xE000ED88 */ - ldr r0, =0xE000ED88 - /* Read CPACR */ - ldr r1, [r0] - /* Set bits 20-23 to enable CP10 and CP11 coprocessors */ - orr r1, r1, #(0xF << 20) - /* Write back the modified value to the CPACR */ - str r1, [r0] /* wait for store to complete */ - dsb - /* reset pipeline now the FPU is enabled */ - isb -#endif /* CONFIG_FPU */ - -#ifdef CONFIG_DEBUG_DISABLE_WRITE_BUFFER - /* Disable write buffer used for default memory map accesses */ - ldr r0, =0xE000E008 /* Load address of ACTLR */ - ldr r1, [r0] /* Read ACTLR */ - orr r1, r1, #2 /* Set DISDEFWBUF bit */ - str r1, [r0] /* Write back ACTLR */ - dsb /* Wait for store to complete */ - isb /* Reset pipeline */ -#endif /* CONFIG_DEBUG_DISABLE_WRITE_BUFFER */ - - /* Jump to C code */ - bl main - - /* That should not return. If it does, loop forever. */ -fini_loop: - b fini_loop - -.align 2 -_bss_start: -.long __bss_start -_bss_end: -.long __bss_end -_data_start: -.long __data_start -_data_end: -.long __data_end -_data_lma_start: -.long __data_lma_start - -/* Mock functions to avoid linker complaints */ -.global __aeabi_unwind_cpp_pr0 -.global __aeabi_unwind_cpp_pr1 -.global __aeabi_unwind_cpp_pr2 -__aeabi_unwind_cpp_pr0: -__aeabi_unwind_cpp_pr1: -__aeabi_unwind_cpp_pr2: - bx lr - -/* Reserve space for system stack */ -.section .bss.system_stack -stack_start: -.space CONFIG_STACK_SIZE, 0 -stack_end: -.global stack_end - diff --git a/core/cortex-m/irq_handler.h b/core/cortex-m/irq_handler.h deleted file mode 100644 index ae5d95cd94..0000000000 --- a/core/cortex-m/irq_handler.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Helper to declare IRQ handling routines */ - -#ifndef __CROS_EC_IRQ_HANDLER_H -#define __CROS_EC_IRQ_HANDLER_H - -#ifdef CONFIG_TASK_PROFILING -#define bl_task_start_irq_handler "bl task_start_irq_handler\n" -#else -#define bl_task_start_irq_handler "" -#endif - -/* Helper macros to build the IRQ handler and priority struct names */ -#define IRQ_HANDLER(irqname) CONCAT3(irq_, irqname, _handler) -#define IRQ_PRIORITY(irqname) CONCAT2(prio_, irqname) -/* - * Macro to connect the interrupt handler "routine" to the irq number "irq" and - * ensure it is enabled in the interrupt controller with the right priority. - */ -#define DECLARE_IRQ(irq, routine, priority) DECLARE_IRQ_(irq, routine, priority) -#define DECLARE_IRQ_(irq, routine, priority) \ - void IRQ_HANDLER(irq)(void) __attribute__((naked)); \ - typedef struct { \ - int fake[irq >= CONFIG_IRQ_COUNT ? -1 : 1]; \ - } irq_num_check_##irq; \ - void __keep routine(void); \ - void IRQ_HANDLER(irq)(void) \ - { \ - asm volatile("mov r0, lr\n" \ - "push {r0, lr}\n" \ - bl_task_start_irq_handler \ - "bl "#routine"\n" \ - "pop {r0, lr}\n" \ - "b task_resched_if_needed\n" \ - ); \ - } \ - const struct irq_priority __keep IRQ_PRIORITY(irq) \ - __attribute__((section(".rodata.irqprio"))) \ - = {irq, priority} -#endif /* __CROS_EC_IRQ_HANDLER_H */ diff --git a/core/cortex-m/ldivmod.S b/core/cortex-m/ldivmod.S deleted file mode 120000 index afdeb4ec1f..0000000000 --- a/core/cortex-m/ldivmod.S +++ /dev/null @@ -1 +0,0 @@ -../../third_party/libaeabi-cortexm0/core/cortex-m/ldivmod.S
\ No newline at end of file diff --git a/core/cortex-m/llsr.c b/core/cortex-m/llsr.c deleted file mode 100644 index 0827121e97..0000000000 --- a/core/cortex-m/llsr.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Enable the use of right shift for uint64_t. */ - -#include <console.h> -#include <compile_time_macros.h> -#include <stdint.h> - -union words { - uint64_t u64; - uint32_t w[2]; -}; - -uint64_t __attribute__((used)) __aeabi_llsr(uint64_t v, uint32_t shift) -{ - union words val; - union words res; - - val.u64 = v; - res.w[1] = val.w[1] >> shift; - res.w[0] = val.w[0] >> shift; - res.w[0] |= val.w[1] >> (shift - 32); /* Handle shift >= 32*/ - res.w[0] |= val.w[1] << (32 - shift); /* Handle shift <= 32*/ - return res.u64; -} - -#ifdef CONFIG_LLSR_TEST - -static int command_llsr(int argc, char **argv) -{ - /* Volatile to prevent compilier optimization from interfering. */ - volatile uint64_t start = 0x123456789ABCDEF0ull; - uint32_t x; - - const struct { - uint32_t shift_by; - uint64_t result; - } cases[] = { - {0, start}, - {16, 0x123456789ABCull}, - {32, 0x12345678u}, - {48, 0x1234u}, - {64, 0u} - }; - - for (x = 0; x < ARRAY_SIZE(cases); ++x) { - if ((start >> cases[x].shift_by) != cases[x].result) { - ccprintf("FAILED %d\n", cases[x].shift_by); - return EC_ERROR_UNKNOWN; - } - } - - ccprintf("SUCCESS\n"); - return EC_SUCCESS; -} - -DECLARE_CONSOLE_COMMAND( - llsrtest, command_llsr, - "", - "Run tests against the LLSR ABI. Prints SUCCESS or FAILURE."); - -#endif /* CONFIG_LLSR_TEST */ diff --git a/core/cortex-m/mpu.c b/core/cortex-m/mpu.c deleted file mode 100644 index 29da931a28..0000000000 --- a/core/cortex-m/mpu.c +++ /dev/null @@ -1,457 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* MPU module for Chrome EC */ - -#include "mpu.h" -#include "console.h" -#include "cpu.h" -#include "registers.h" -#include "task.h" -#include "util.h" - -/** - * @return Number of regions supported by the MPU. 0 means the processor does - * not implement an MPU. - */ -int mpu_num_regions(void) -{ - return MPU_TYPE_REG_COUNT(mpu_get_type()); -} - -/** - * @return true if processor has MPU, false otherwise - */ -bool has_mpu(void) -{ - return mpu_num_regions() != 0; -} - -/** - * @return true if MPU has unified instruction and data maps, false otherwise - */ -bool mpu_is_unified(void) -{ - return (mpu_get_type() & MPU_TYPE_UNIFIED_MASK) == 0; -} - - -/** - * Update a memory region. - * - * region: index of the region to update - * addr: base address of the region - * size_bit: size of the region in power of two. - * attr: attribute bits. Current value will be overwritten if enable is true. - * enable: enables the region if non zero. Otherwise, disables the region. - * srd: subregion mask to partition region into 1/8ths, 0 = subregion enabled. - * - * Based on 3.1.4.1 'Updating an MPU Region' of Stellaris LM4F232H5QC Datasheet - */ -int mpu_update_region(uint8_t region, uint32_t addr, uint8_t size_bit, - uint16_t attr, uint8_t enable, uint8_t srd) -{ - /* - * Note that on the Cortex-M3, Cortex-M4, and Cortex-M7, the base - * address used for an MPU region must be aligned to the size of the - * region: - * - * https://developer.arm.com/docs/dui0553/a/cortex-m4-peripherals/optional-memory-protection-unit/mpu-region-base-address-register - * https://developer.arm.com/docs/dui0552/a/cortex-m3-peripherals/optional-memory-protection-unit/mpu-region-base-address-register - * https://developer.arm.com/docs/dui0646/a/cortex-m7-peripherals/optional-memory-protection-unit/mpu-region-base-address-register#BABDAHJG - */ - if (!is_aligned(addr, BIT(size_bit))) - return -EC_ERROR_INVAL; - - if (region >= mpu_num_regions()) - return -EC_ERROR_INVAL; - - if (size_bit < MPU_SIZE_BITS_MIN) - return -EC_ERROR_INVAL; - - asm volatile("isb; dsb;"); - - MPU_NUMBER = region; - MPU_SIZE &= ~1; /* Disable */ - if (enable) { - MPU_BASE = addr; - /* - * MPU_ATTR = attr; - * MPU_SIZE = (srd << 8) | ((size_bit - 1) << 1) | 1; - * - * WORKAROUND: the 2 half-word accesses above should work - * according to the doc, but they don't ..., do a single 32-bit - * one. - */ - REG32(&MPU_SIZE) = ((uint32_t)attr << 16) - | (srd << 8) | ((size_bit - 1) << 1) | 1; - } - - asm volatile("isb; dsb;"); - - return EC_SUCCESS; -} - -/* - * Greedily configure the largest possible part of the given region from the - * base address. - * - * Returns EC_SUCCESS on success and sets *consumed to the number of bytes - * mapped from the base address. In case of error, the value of *consumed is - * unpredictable. - * - * For instance, if addr is 0x10070000 and size is 0x30000 then memory in the - * range 0x10070000-0x10080000 will be configured and *consumed will be set to - * 0x10000. - */ -static int mpu_config_region_greedy(uint8_t region, uint32_t addr, - uint32_t size, uint16_t attr, - uint8_t enable, uint32_t *consumed) -{ - /* - * Compute candidate alignment to be used for the MPU region. - * - * This is the minimum of the base address and size alignment, since - * regions must be naturally aligned to their size. - */ - uint8_t natural_alignment = MIN(addr == 0 ? 32 : alignment_log2(addr), - alignment_log2(size)); - uint8_t subregion_disable = 0; - - if (natural_alignment >= 5) { - int sr_idx; - uint32_t subregion_base, subregion_size; - /* - * For MPU regions larger than 256 bytes we can use subregions, - * (which are a minimum of 32 bytes in size) making the actual - * MPU region 8x larger. Depending on the address alignment this - * can allow us to cover a larger area (and never a smaller - * one). - */ - natural_alignment += 3; - /* Region size cannot exceed 4GB. */ - if (natural_alignment > 32) - natural_alignment = 32; - - /* - * Generate the subregion mask by walking through each, - * disabling if it is not completely contained in the requested - * range. - */ - subregion_base = addr & ~((1 << natural_alignment) - 1); - subregion_size = 1 << (natural_alignment - 3); - *consumed = 0; - for (sr_idx = 0; sr_idx < 8; sr_idx++) { - if (subregion_base < addr || - (subregion_base + subregion_size) > (addr + size)) - /* lsb of subregion mask is lowest address */ - subregion_disable |= 1 << sr_idx; - else - /* not disabled means consumed */ - *consumed += subregion_size; - - subregion_base += subregion_size; - } - } else { - /* Not using subregions; all enabled */ - *consumed = 1 << natural_alignment; - } - - return mpu_update_region(region, - addr & ~((1 << natural_alignment) - 1), - natural_alignment, - attr, enable, subregion_disable); -} - -/** - * Configure a region - * - * region: index of the region to update - * addr: Base address of the region - * size: Size of the region in bytes - * attr: Attribute bits. Current value will be overwritten if enable is set. - * enable: Enables the region if non zero. Otherwise, disables the region. - * - * Returns EC_SUCCESS on success, -EC_ERROR_OVERFLOW if it is not possible to - * fully configure the given region, or -EC_ERROR_INVAL if a parameter is - * invalid (such as the address or size having unsupported alignment). - */ -int mpu_config_region(uint8_t region, uint32_t addr, uint32_t size, - uint16_t attr, uint8_t enable) -{ - int rv; - uint32_t consumed; - - /* Zero size doesn't require configuration */ - if (size == 0) - return EC_SUCCESS; - - rv = mpu_config_region_greedy(region, addr, size, - attr, enable, &consumed); - if (rv != EC_SUCCESS) - return rv; - ASSERT(consumed <= size); - addr += consumed; - size -= consumed; - - /* Regions other than DATA_RAM_TEXT may use two MPU regions */ - if (size > 0 && region != REGION_DATA_RAM_TEXT) { - rv = mpu_config_region_greedy(region + 1, addr, size, - attr, enable, &consumed); - if (rv != EC_SUCCESS) - return rv; - ASSERT(consumed <= size); - addr += consumed; - size -= consumed; - } - - if (size > 0) - return EC_ERROR_OVERFLOW; - return EC_SUCCESS; -} - -/** - * Set a region executable and read-write. - * - * region: index of the region - * addr: base address of the region - * size: size of the region in bytes - * texscb: TEX and SCB bit field - */ -static int mpu_unlock_region(uint8_t region, uint32_t addr, uint32_t size, - uint8_t texscb) -{ - return mpu_config_region(region, addr, size, - MPU_ATTR_RW_RW | texscb, 1); -} - -void mpu_enable(void) -{ - MPU_CTRL |= MPU_CTRL_PRIVDEFEN | MPU_CTRL_HFNMIENA | MPU_CTRL_ENABLE; -} - -void mpu_disable(void) -{ - MPU_CTRL &= ~(MPU_CTRL_PRIVDEFEN | MPU_CTRL_HFNMIENA | MPU_CTRL_ENABLE); -} - -uint32_t mpu_get_type(void) -{ - return MPU_TYPE; -} - -int mpu_protect_data_ram(void) -{ - int ret; - - /* Prevent code execution from data RAM */ - ret = mpu_config_region(REGION_DATA_RAM, - CONFIG_RAM_BASE, - CONFIG_DATA_RAM_SIZE, - MPU_ATTR_XN | - MPU_ATTR_RW_RW | - MPU_ATTR_INTERNAL_SRAM, - 1); - if (ret != EC_SUCCESS) - return ret; - - /* Exempt the __iram_text section */ - return mpu_unlock_region( - REGION_DATA_RAM_TEXT, (uint32_t)&__iram_text_start, - (uint32_t)(&__iram_text_end - &__iram_text_start), - MPU_ATTR_INTERNAL_SRAM); -} - -#if defined(CONFIG_EXTERNAL_STORAGE) || !defined(CONFIG_FLASH_PHYSICAL) -int mpu_protect_code_ram(void) -{ - /* Prevent write access to code RAM */ - return mpu_config_region(REGION_STORAGE, - CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RO_MEM_OFF, - CONFIG_CODE_RAM_SIZE, - MPU_ATTR_RO_NO | MPU_ATTR_INTERNAL_SRAM, - 1); -} -#else -int mpu_lock_ro_flash(void) -{ - /* Prevent execution from internal mapped RO flash */ - return mpu_config_region(REGION_STORAGE, - CONFIG_MAPPED_STORAGE_BASE + CONFIG_RO_MEM_OFF, - CONFIG_RO_SIZE, - MPU_ATTR_XN | MPU_ATTR_RW_RW | - MPU_ATTR_FLASH_MEMORY, 1); -} - -/* Represent RW with at most 2 MPU regions. */ -struct mpu_rw_regions mpu_get_rw_regions(void) -{ - int aligned_size_bit; - struct mpu_rw_regions regions = {}; - - regions.addr[0] = CONFIG_MAPPED_STORAGE_BASE + CONFIG_RW_MEM_OFF; - - /* - * Least significant set bit of the address determines the max size of - * the region because on the Cortex-M3, Cortex-M4 and Cortex-M7, the - * address used for an MPU region must be aligned to the size. - */ - aligned_size_bit = - __fls(regions.addr[0] & -regions.addr[0]); - regions.size[0] = MIN(BIT(aligned_size_bit), CONFIG_RW_SIZE); - regions.addr[1] = regions.addr[0] + regions.size[0]; - regions.size[1] = CONFIG_RW_SIZE - regions.size[0]; - regions.num_regions = (regions.size[1] == 0) ? 1 : 2; - - return regions; -} - -int mpu_lock_rw_flash(void) -{ - /* Prevent execution from internal mapped RW flash */ - const uint16_t mpu_attr = MPU_ATTR_XN | MPU_ATTR_RW_RW | - MPU_ATTR_FLASH_MEMORY; - const struct mpu_rw_regions regions = mpu_get_rw_regions(); - int rv; - - rv = mpu_config_region(REGION_STORAGE, regions.addr[0], regions.size[0], - mpu_attr, 1); - if ((rv != EC_SUCCESS) || (regions.num_regions == 1)) - return rv; - - /* If this fails then it's impossible to represent with two regions. */ - return mpu_config_region(REGION_STORAGE2, regions.addr[1], - regions.size[1], mpu_attr, 1); -} -#endif /* !CONFIG_EXTERNAL_STORAGE */ - -#ifdef CONFIG_ROLLBACK_MPU_PROTECT -int mpu_lock_rollback(int lock) -{ - int rv; - int num_mpu_regions = mpu_num_regions(); - - const uint32_t rollback_region_start_address = - CONFIG_MAPPED_STORAGE_BASE + CONFIG_ROLLBACK_OFF; - const uint32_t rollback_region_total_size = CONFIG_ROLLBACK_SIZE; - const uint16_t mpu_attr = - MPU_ATTR_XN /* Execute never */ | - MPU_ATTR_NO_NO /* No access (privileged or unprivileged */; - - /* - * Originally rollback MPU support was added on Cortex-M7, which - * supports 16 MPU regions and has rollback region aligned in a way - * that we can use a single region. - */ - uint8_t rollback_mpu_region = REGION_ROLLBACK; - - if (rollback_mpu_region < num_mpu_regions) { - rv = mpu_config_region(rollback_mpu_region, - rollback_region_start_address, - rollback_region_total_size, mpu_attr, - lock); - return rv; - } - - /* - * If we get here, we can't use REGION_ROLLBACK because our MPU doesn't - * have enough regions. Instead, we choose unused MPU regions. - * - * Note that on the Cortex-M3, Cortex-M4, and Cortex-M7, the base - * address used for an MPU region must be aligned to the size of the - * region, so it's not possible to use a single region to protect the - * entire rollback flash on the STM32F412 (bloonchipper); we have to - * use two. - * - * See mpu_update_region for alignment details. - */ - - rollback_mpu_region = REGION_CHIP_RESERVED; - rv = mpu_config_region(rollback_mpu_region, - rollback_region_start_address, - rollback_region_total_size / 2, mpu_attr, lock); - if (rv != EC_SUCCESS) - return rv; - - rollback_mpu_region = REGION_CODE_RAM; - rv = mpu_config_region(rollback_mpu_region, - rollback_region_start_address + - (rollback_region_total_size / 2), - rollback_region_total_size / 2, mpu_attr, lock); - return rv; -} -#endif - -#ifdef CONFIG_CHIP_UNCACHED_REGION -/* Store temporarily the regions ranges to use them for the MPU configuration */ -#define REGION(_name, _flag, _start, _size) \ - static const uint32_t CONCAT2(_region_start_, _name) \ - __attribute__((unused, section(".unused"))) = _start; \ - static const uint32_t CONCAT2(_region_size_, _name) \ - __attribute__((unused, section(".unused"))) = _size; -#include "memory_regions.inc" -#undef REGION -#endif /* CONFIG_CHIP_UNCACHED_REGION */ - -int mpu_pre_init(void) -{ - int i; - int num_mpu_regions; - int rv; - - if (!has_mpu()) - return EC_ERROR_HW_INTERNAL; - - num_mpu_regions = mpu_num_regions(); - - /* Supports MPU with 8 or 16 unified regions */ - if (!mpu_is_unified() || - (num_mpu_regions != 8 && num_mpu_regions != 16)) - return EC_ERROR_UNIMPLEMENTED; - - mpu_disable(); - - for (i = 0; i < num_mpu_regions; ++i) { - /* - * Disable all regions. - * - * We use the smallest possible size (32 bytes), but it - * doesn't really matter since the regions are disabled. - * - * Use the fixed SRAM region base to ensure base is aligned - * to the region size. - */ - rv = mpu_update_region(i, CORTEX_M_SRAM_BASE, MPU_SIZE_BITS_MIN, - 0, 0, 0); - if (rv != EC_SUCCESS) - return rv; - } - - if (IS_ENABLED(CONFIG_ROLLBACK_MPU_PROTECT)) { - rv = mpu_lock_rollback(1); - if (rv != EC_SUCCESS) - return rv; - } - - if (IS_ENABLED(CONFIG_ARMV7M_CACHE)) { -#ifdef CONFIG_CHIP_UNCACHED_REGION - rv = mpu_config_region( - REGION_UNCACHED_RAM, - CONCAT2(_region_start_, CONFIG_CHIP_UNCACHED_REGION), - CONCAT2(_region_size_, CONFIG_CHIP_UNCACHED_REGION), - MPU_ATTR_XN | MPU_ATTR_RW_RW, 1); - if (rv != EC_SUCCESS) - return rv; - -#endif - } - - mpu_enable(); - - if (IS_ENABLED(CONFIG_ARMV7M_CACHE)) - cpu_enable_caches(); - - return EC_SUCCESS; -} diff --git a/core/cortex-m/panic-internal.h b/core/cortex-m/panic-internal.h deleted file mode 100644 index 1a58afa8a2..0000000000 --- a/core/cortex-m/panic-internal.h +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_PANIC_INTERNAL_H -#define __CROS_EC_PANIC_INTERNAL_H - -void exception_panic(void) __attribute__((naked)); - -#endif /* __CROS_EC_PANIC_INTERNAL_H */ diff --git a/core/cortex-m/panic.c b/core/cortex-m/panic.c deleted file mode 100644 index da6900b1b9..0000000000 --- a/core/cortex-m/panic.c +++ /dev/null @@ -1,475 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" -#include "console.h" -#include "cpu.h" -#include "host_command.h" -#include "panic.h" -#include "panic-internal.h" -#include "printf.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "uart.h" -#include "util.h" -#include "watchdog.h" - -/* Whether bus fault is ignored */ -static int bus_fault_ignored; - - -/* Panic data goes at the end of RAM. */ -static struct panic_data * const pdata_ptr = PANIC_DATA_PTR; - -/* Preceded by stack, rounded down to nearest 64-bit-aligned boundary */ -static const uint32_t pstack_addr = (CONFIG_RAM_BASE + CONFIG_RAM_SIZE - - sizeof(struct panic_data)) & ~7; - -/** - * Print the name and value of a register - * - * This is a convenient helper function for displaying a register value. - * It shows the register name in a 3 character field, followed by a colon. - * The register value is regs[index], and this is shown in hex. If regs is - * NULL, then we display spaces instead. - * - * After displaying the value, either a space or \n is displayed depending - * on the register number, so that (assuming the caller passes all 16 - * registers in sequence) we put 4 values per line like this - * - * r0 :0000000b r1 :00000047 r2 :60000000 r3 :200012b5 - * r4 :00000000 r5 :08004e64 r6 :08004e1c r7 :200012a8 - * r8 :08004e64 r9 :00000002 r10:00000000 r11:00000000 - * r12:0000003f sp :200009a0 lr :0800270d pc :0800351a - * - * @param regnum Register number to display (0-15) - * @param regs Pointer to array holding the registers, or NULL - * @param index Index into array where the register value is present - */ -static void print_reg(int regnum, const uint32_t *regs, int index) -{ - static const char regname[] = "r10r11r12sp lr pc "; - static char rname[3] = "r "; - const char *name; - - rname[1] = '0' + regnum; - name = regnum < 10 ? rname : ®name[(regnum - 10) * 3]; - panic_printf("%c%c%c:", name[0], name[1], name[2]); - if (regs) - panic_printf("%08x", regs[index]); - else - panic_puts(" "); - panic_puts((regnum & 3) == 3 ? "\n" : " "); -} - -/* - * Returns non-zero if the exception frame was created on the main stack, or - * zero if it's on the process stack. - * - * See B1.5.8 "Exception return behavior" of ARM DDI 0403D for details. - */ -static int32_t is_frame_in_handler_stack(const uint32_t exc_return) -{ - return (exc_return & 0xf) == 1 || (exc_return & 0xf) == 9; -} - -#ifdef CONFIG_DEBUG_EXCEPTIONS -/* Names for each of the bits in the cfs register, starting at bit 0 */ -static const char * const cfsr_name[32] = { - /* MMFSR */ - [0] = "Instruction access violation", - [1] = "Data access violation", - [3] = "Unstack from exception violation", - [4] = "Stack from exception violation", - - /* BFSR */ - [8] = "Instruction bus error", - [9] = "Precise data bus error", - [10] = "Imprecise data bus error", - [11] = "Unstack from exception bus fault", - [12] = "Stack from exception bus fault", - - /* UFSR */ - [16] = "Undefined instructions", - [17] = "Invalid state", - [18] = "Invalid PC", - [19] = "No coprocessor", - [24] = "Unaligned", - [25] = "Divide by 0", -}; - -/* Names for the first 5 bits in the DFSR */ -static const char * const dfsr_name[] = { - "Halt request", - "Breakpoint", - "Data watchpoint/trace", - "Vector catch", - "External debug request", -}; - -/** - * Helper function to display a separator after the previous item - * - * If items have been displayed already, we display a comma separator. - * In any case, the count of items displayed is incremeneted. - * - * @param count Number of items displayed so far (0 for none) - */ -static void do_separate(int *count) -{ - if (*count) - panic_puts(", "); - (*count)++; -} - -/** - * Show a textual representaton of the fault registers - * - * A list of detected faults is shown, with no trailing newline. - * - * @param cfsr Value of Configurable Fault Status - * @param hfsr Value of Hard Fault Status - * @param dfsr Value of Debug Fault Status - */ -static void show_fault(uint32_t cfsr, uint32_t hfsr, uint32_t dfsr) -{ - unsigned int upto; - int count = 0; - - for (upto = 0; upto < 32; upto++) { - if ((cfsr & BIT(upto)) && cfsr_name[upto]) { - do_separate(&count); - panic_puts(cfsr_name[upto]); - } - } - - if (hfsr & CPU_NVIC_HFSR_DEBUGEVT) { - do_separate(&count); - panic_puts("Debug event"); - } - if (hfsr & CPU_NVIC_HFSR_FORCED) { - do_separate(&count); - panic_puts("Forced hard fault"); - } - if (hfsr & CPU_NVIC_HFSR_VECTTBL) { - do_separate(&count); - panic_puts("Vector table bus fault"); - } - - for (upto = 0; upto < 5; upto++) { - if ((dfsr & BIT(upto))) { - do_separate(&count); - panic_puts(dfsr_name[upto]); - } - } -} - -/* - * Returns the size of the exception frame. - * - * See B1.5.7 "Stack alignment on exception entry" of ARM DDI 0403D for details. - * In short, the exception frame size can be either 0x20, 0x24, 0x68, or 0x6c - * depending on FPU context and padding for 8-byte alignment. - */ -static uint32_t get_exception_frame_size(const struct panic_data *pdata) -{ - uint32_t frame_size = 0; - - /* base exception frame */ - frame_size += 8 * sizeof(uint32_t); - - /* CPU uses xPSR[9] to indicate whether it padded the stack for - * alignment or not. */ - if (pdata->cm.frame[7] & BIT(9)) - frame_size += sizeof(uint32_t); - -#ifdef CONFIG_FPU - /* CPU uses EXC_RETURN[4] to indicate whether it stored extended - * frame for FPU or not. */ - if (!(pdata->cm.regs[11] & BIT(4))) - frame_size += 18 * sizeof(uint32_t); -#endif - - return frame_size; -} - -/* - * Returns the position of the process stack before the exception frame. - * It computes the size of the exception frame and adds it to psp. - * If the exception happened in the exception context, it returns psp as is. - */ -static uint32_t get_process_stack_position(const struct panic_data *pdata) -{ - uint32_t psp = pdata->cm.regs[0]; - - if (!is_frame_in_handler_stack(pdata->cm.regs[11])) - psp += get_exception_frame_size(pdata); - - return psp; -} - -/* - * Show extra information that might be useful to understand a panic() - * - * We show fault register information, including the fault address registers - * if valid. - */ -static void panic_show_extra(const struct panic_data *pdata) -{ - show_fault(pdata->cm.cfsr, pdata->cm.hfsr, pdata->cm.dfsr); - if (pdata->cm.cfsr & CPU_NVIC_CFSR_BFARVALID) - panic_printf(", bfar = %x", pdata->cm.bfar); - if (pdata->cm.cfsr & CPU_NVIC_CFSR_MFARVALID) - panic_printf(", mfar = %x", pdata->cm.mfar); - panic_printf("\ncfsr = %x, ", pdata->cm.cfsr); - panic_printf("shcsr = %x, ", pdata->cm.shcsr); - panic_printf("hfsr = %x, ", pdata->cm.hfsr); - panic_printf("dfsr = %x\n", pdata->cm.dfsr); -} - -/* - * Prints process stack contents stored above the exception frame. - */ -static void panic_show_process_stack(const struct panic_data *pdata) -{ - panic_printf("\n=========== Process Stack Contents ==========="); - if (pdata->flags & PANIC_DATA_FLAG_FRAME_VALID) { - uint32_t psp = get_process_stack_position(pdata); - int i; - for (i = 0; i < 16; i++) { - if (psp + sizeof(uint32_t) > - CONFIG_RAM_BASE + CONFIG_RAM_SIZE) - break; - if (i % 4 == 0) - panic_printf("\n%08x:", psp); - panic_printf(" %08x", *(uint32_t *)psp); - psp += sizeof(uint32_t); - } - } else { - panic_printf("\nBad psp"); - } -} -#endif /* CONFIG_DEBUG_EXCEPTIONS */ - -/* - * Print panic data - */ -void panic_data_print(const struct panic_data *pdata) -{ - const uint32_t *lregs = pdata->cm.regs; - const uint32_t *sregs = NULL; - const int32_t in_handler = - is_frame_in_handler_stack(pdata->cm.regs[11]); - int i; - - if (pdata->flags & PANIC_DATA_FLAG_FRAME_VALID) - sregs = pdata->cm.frame; - - panic_printf("\n=== %s EXCEPTION: %02x ====== xPSR: %08x ===\n", - in_handler ? "HANDLER" : "PROCESS", - lregs[1] & 0xff, sregs ? sregs[7] : -1); - for (i = 0; i < 4; i++) - print_reg(i, sregs, i); - for (i = 4; i < 10; i++) - print_reg(i, lregs, i - 1); - print_reg(10, lregs, 9); - print_reg(11, lregs, 10); - print_reg(12, sregs, 4); - print_reg(13, lregs, in_handler ? 2 : 0); - print_reg(14, sregs, 5); - print_reg(15, sregs, 6); - -#ifdef CONFIG_DEBUG_EXCEPTIONS - panic_show_extra(pdata); -#endif -} - -void __keep report_panic(void) -{ - /* - * Don't need to get pointer via get_panic_data_write() - * because memory below pdata_ptr is stack now (see exception_panic()) - */ - struct panic_data *pdata = pdata_ptr; - uint32_t sp; - - pdata->magic = PANIC_DATA_MAGIC; - pdata->struct_size = sizeof(*pdata); - pdata->struct_version = 2; - pdata->arch = PANIC_ARCH_CORTEX_M; - pdata->flags = 0; - pdata->reserved = 0; - - /* Choose the right sp (psp or msp) based on EXC_RETURN value */ - sp = is_frame_in_handler_stack(pdata->cm.regs[11]) - ? pdata->cm.regs[2] : pdata->cm.regs[0]; - /* If stack is valid, copy exception frame to pdata */ - if ((sp & 3) == 0 && - sp >= CONFIG_RAM_BASE && - sp <= CONFIG_RAM_BASE + CONFIG_RAM_SIZE - 8 * sizeof(uint32_t)) { - const uint32_t *sregs = (const uint32_t *)sp; - int i; - - /* Skip r0-r3 and r12 registers if necessary */ - for (i = CORTEX_PANIC_FRAME_REGISTER_R0; - i <= CORTEX_PANIC_FRAME_REGISTER_R12; i++) - if (IS_ENABLED(CONFIG_PANIC_STRIP_GPR)) - pdata->cm.frame[i] = 0; - else - pdata->cm.frame[i] = sregs[i]; - - for (i = CORTEX_PANIC_FRAME_REGISTER_LR; - i < NUM_CORTEX_PANIC_FRAME_REGISTERS; i++) - pdata->cm.frame[i] = sregs[i]; - - pdata->flags |= PANIC_DATA_FLAG_FRAME_VALID; - } - - /* Save extra information */ - pdata->cm.cfsr = CPU_NVIC_CFSR; - pdata->cm.bfar = CPU_NVIC_BFAR; - pdata->cm.mfar = CPU_NVIC_MFAR; - pdata->cm.shcsr = CPU_NVIC_SHCSR; - pdata->cm.hfsr = CPU_NVIC_HFSR; - pdata->cm.dfsr = CPU_NVIC_DFSR; - -#ifdef CONFIG_UART_PAD_SWITCH - uart_reset_default_pad_panic(); -#endif - panic_data_print(pdata); -#ifdef CONFIG_DEBUG_EXCEPTIONS - panic_show_process_stack(pdata); - /* - * TODO(crosbug.com/p/23760): Dump main stack contents as well if the - * exception happened in a handler's context. - */ -#endif - - /* Make sure that all changes are saved into RAM */ - if (IS_ENABLED(CONFIG_ARMV7M_CACHE)) - cpu_clean_invalidate_dcache(); - - panic_reboot(); -} - -/** - * Default exception handler, which reports a panic. - * - * Declare this as a naked call so we can extract raw LR and IPSR values. - */ -void exception_panic(void) -{ - /* Save registers and branch directly to panic handler */ - asm volatile( - "mov r0, %[pregs]\n" - "mrs r1, psp\n" - "mrs r2, ipsr\n" - "mov r3, sp\n" -#ifdef CONFIG_PANIC_STRIP_GPR - /* - * Check if we are in exception. This is similar to - * in_interrupt_context(). Exception bits are 9 LSB, so - * we can perform left shift for 23 bits and check if result - * is 0 (lsls instruction is setting appropriate flags). - */ - "lsls r6, r2, #23\n" - /* - * If this is software panic (shift result == 0) then register - * r4 and r5 contain additional info about panic. - * Clear r6-r11 always and r4, r5 only if this is exception - * panic. To clear r4 and r5, 'movne' conditional instruction - * is used. It works only when flags contain information that - * result was != 0. Itt is pseudo instruction which is used - * to make sure we are using correct conditional instructions. - */ - "itt ne\n" - "movne r4, #0\n" - "movne r5, #0\n" - "mov r6, #0\n" - "mov r7, #0\n" - "mov r8, #0\n" - "mov r9, #0\n" - "mov r10, #0\n" - "mov r11, #0\n" -#endif - "stmia r0, {r1-r11, lr}\n" - "mov sp, %[pstack]\n" - "bl report_panic\n" : : - [pregs] "r" (pdata_ptr->cm.regs), - [pstack] "r" (pstack_addr) : - /* Constraints protecting these from being clobbered. - * Gcc should be using r0 & r12 for pregs and pstack. */ - "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", - "r10", "r11", "cc", "memory" - ); -} - -#ifdef CONFIG_SOFTWARE_PANIC -void software_panic(uint32_t reason, uint32_t info) -{ - __asm__("mov " STRINGIFY(SOFTWARE_PANIC_INFO_REG) ", %0\n" - "mov " STRINGIFY(SOFTWARE_PANIC_REASON_REG) ", %1\n" - "bl exception_panic\n" - : : "r"(info), "r"(reason)); - __builtin_unreachable(); -} - -void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) -{ - struct panic_data * const pdata = get_panic_data_write(); - uint32_t *lregs; - - lregs = pdata->cm.regs; - - /* Setup panic data structure */ - memset(pdata, 0, CONFIG_PANIC_DATA_SIZE); - pdata->magic = PANIC_DATA_MAGIC; - pdata->struct_size = CONFIG_PANIC_DATA_SIZE; - pdata->struct_version = 2; - pdata->arch = PANIC_ARCH_CORTEX_M; - - /* Log panic cause */ - lregs[1] = exception; - lregs[3] = reason; - lregs[4] = info; -} - -void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) -{ - struct panic_data * const pdata = panic_get_data(); - uint32_t *lregs; - - if (pdata && pdata->struct_version == 2) { - lregs = pdata->cm.regs; - *exception = lregs[1]; - *reason = lregs[3]; - *info = lregs[4]; - } else { - *exception = *reason = *info = 0; - } -} -#endif - -void bus_fault_handler(void) -{ - if (!bus_fault_ignored) - exception_panic(); -} - -void ignore_bus_fault(int ignored) -{ - if (IS_ENABLED(CHIP_FAMILY_STM32H7)) { - if (ignored == 0) - asm volatile("dsb; isb"); - } - - /* - * Flash code might call this before cpu_init(), - * ensure that the bus faults really go through our handler. - */ - CPU_NVIC_SHCSR |= CPU_NVIC_SHCSR_BUSFAULTENA; - bus_fault_ignored = ignored; -} diff --git a/core/cortex-m/switch.S b/core/cortex-m/switch.S deleted file mode 100644 index f56c5e4c74..0000000000 --- a/core/cortex-m/switch.S +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Context swtching - */ - -#include "config.h" - -.text - -.syntax unified -.code 16 - -/** - * Task context switching - * - * Change the task scheduled after returning from the exception. - * - * Save the registers of the current task below the exception context on - * its task, then restore the live registers of the next task and set the - * process stack pointer to the new stack. - * - * r0: pointer to the task to switch from - * r1: pointer to the task to switch to - * - * must be called from interrupt context - * - * the structure of the saved context on the stack is : - * r0, r1, r2, r3, r12, lr, pc, psr, r4, r5, r6, r7, r8, r9, r10, r11 - * exception frame <|> additional registers - * - * if using the FPU, then to store FPU context, add FP regs to the stack. in - * this case the exception frame by default contains: - * r0, r1, r2, r3, r12, lr, pc, psr, - * s0 - s15, FPSCR, +1 word for 64-bit alignment - * then in addition we store the following registers: - * r4, r5, r6, r7, r8, r9, r10, r11 - * s16 - s31 (stored iff FP was used by the task (see EXC_RETURN[4])) - * note that for the context switch to know if the next task has the extra FP - * regs on the stack or not, we make use of the least significant bit of the - * stack pointer. lsb of stack pointer is 1 if task has FP regs on stack, and - * 0 otherwise. - * - */ -.global __switchto -.thumb_func -__switchto: - mrs r3, psp @ get the task stack where the context has been saved - ldr r2, [r1] @ get the new scheduled task stack pointer - stmdb r3!, {r4-r11} @ save additional r4-r11 in the task stack - -#ifdef CONFIG_FPU - tst lr, #(1<<4) @ test EXC_RETURN[4] for old task - itt eq @ if EXC_RETURN[4] is zero, add FP regs to stack - vstmdbeq r3!, {s16-s31}@ save additional FP s16-s31 in the task stack. - @ if using lazy stacking, this will trigger saving - @ s0-s15 in the reserved stack space. - orreq r3, #1 @ set lsb of old stack pointer high to represent this - @ task uses FPU. note stack pointer should be 64-bit - @ aligned, so using this bit should be safe. - - tst r2, #1 @ test lsb of next stack pointer - ittte ne @ if lsb is 1, then next task has FP regs on stack - bicne r2, #1 @ clear lsb of new stack pointer - bicne lr, #(1<<4) @ clear EXC_RETURN[4] for next task - vldmiane r2!, {s16-s31}@ restore s16-s31 for the next task context - orreq lr, #(1<<4) @ else if new stack doesn't use FP, set EXC_RETURN[4] -#endif - - ldmia r2!, {r4-r11} @ restore r4-r11 for the next task context - str r3, [r0] @ save the task stack pointer in its context - msr psp, r2 @ set the process stack pointer to exception context - bx lr @ return from exception - -/** - * Start the task scheduling. r0 is a pointer to task_stack_ready, which is - * set to 1 after the task stack is set up. - */ -.global __task_start -.thumb_func -__task_start: - ldr r2,=scratchpad @ area used as thread stack for the first switch - mov r3, #2 @ use : priv. mode / thread stack / no floating point - @ setting FP to unused here means first context switch - @ will not store FP regs - add r2, #17*4 @ put the pointer at the top of the stack - mov r1, #0 @ __Schedule parameter : re-schedule nothing - msr psp, r2 @ setup a thread stack up to the first context switch - mov r2, #1 - isb @ ensure the write is done - msr control, r3 - mov r3, r0 - mov r0, #0 @ __Schedule parameter : de-schedule nothing - isb @ ensure the write is done - str r2, [r3] @ Task scheduling is now active - bl __schedule @ execute the task with the highest priority - /* we should never return here */ - mov r0, #1 @ set to EC_ERROR_UNKNOWN - bx lr - diff --git a/core/cortex-m/task.c b/core/cortex-m/task.c deleted file mode 100644 index bf0eb5b397..0000000000 --- a/core/cortex-m/task.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Task scheduling / events module for Chrome EC operating system */ - -#include "atomic.h" -#include "common.h" -#include "console.h" -#include "cpu.h" -#include "link_defs.h" -#include "panic.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -typedef union { - struct { - /* - * Note that sp must be the first element in the task struct - * for __switchto() to work. - */ - uint32_t sp; /* Saved stack pointer for context switch */ - uint32_t events; /* Bitmaps of received events */ - uint64_t runtime; /* Time spent in task */ - uint32_t *stack; /* Start of stack */ - }; -} task_; - -/* Value to store in unused stack */ -#define STACK_UNUSED_VALUE 0xdeadd00d - -/* declare task routine prototypes */ -#define TASK(n, r, d, s) void r(void *); -void __idle(void); -CONFIG_TASK_LIST -CONFIG_TEST_TASK_LIST -CONFIG_CTS_TASK_LIST -#undef TASK - -/* Task names for easier debugging */ -#define TASK(n, r, d, s) #n, -static const char * const task_names[] = { - "<< idle >>", - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST -}; -#undef TASK - -#ifdef CONFIG_TASK_PROFILING -static uint64_t task_start_time; /* Time task scheduling started */ -/* - * We only keep 32-bit values for exception start/end time, to avoid - * accounting errors when we service interrupt when the timer wraps around. - */ -static uint32_t exc_start_time; /* Time of task->exception transition */ -static uint32_t exc_end_time; /* Time of exception->task transition */ -static uint64_t exc_total_time; /* Total time in exceptions */ -static uint32_t svc_calls; /* Number of service calls */ -static uint32_t task_switches; /* Number of times active task changed */ -static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ -#endif - -extern void __switchto(task_ *from, task_ *to); -extern int __task_start(int *task_stack_ready); - -#ifndef CONFIG_LOW_POWER_IDLE -/* Idle task. Executed when no tasks are ready to be scheduled. */ -void __idle(void) -{ - while (1) { -#ifdef CHIP_NPCX - - /* - * Using host access to make sure M4 core clock will - * return when the eSPI accesses the Host modules if - * CSAE bit is set. Please notice this symptom only - * occurs at npcx5. - */ -#if defined(CHIP_FAMILY_NPCX5) && defined(CONFIG_HOSTCMD_ESPI) - /* Enable Host access wakeup */ - SET_BIT(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 6); -#endif - - /* - * TODO (ML): A interrupt that occurs shortly before entering - * idle mode starts getting services while the Core transitions - * into idle mode. The results in a hard fault when the Core, - * shortly therefore, resumes execution on exiting idle mode. - * Workaround: Replace the idle function with the followings - */ - asm ( - "cpsid i\n" /* Disable interrupt */ - "push {r0-r5}\n" /* Save needed registers */ - "wfi\n" /* Wait for int to enter idle */ - "ldm %0, {r0-r5}\n" /* Add a delay after WFI */ - "pop {r0-r5}\n" /* Restore regs before enabling ints */ - "isb\n" /* Flush the cpu pipeline */ - "cpsie i\n" :: "r" (0x100A8000) /* Enable interrupts */ - ); -#else - /* - * Wait for the next irq event. This stops the CPU clock - * (sleep / deep sleep, depending on chip config). - */ - asm("wfi"); -#endif - } -} -#endif /* !CONFIG_LOW_POWER_IDLE */ - -static void task_exit_trap(void) -{ - int i = task_get_current(); - cprints(CC_TASK, "Task %d (%s) exited!", i, task_names[i]); - /* Exited tasks simply sleep forever */ - while (1) - task_wait_event(-1); -} - -/* Startup parameters for all tasks. */ -#define TASK(n, r, d, s) { \ - .r0 = (uint32_t)d, \ - .pc = (uint32_t)r, \ - .stack_size = s, \ -}, -static const struct { - uint32_t r0; - uint32_t pc; - uint16_t stack_size; -} tasks_init[] = { - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST -}; -#undef TASK - -/* Contexts for all tasks */ -static task_ tasks[TASK_ID_COUNT]; - -/* Reset constants and state for all tasks */ -#define TASK_RESET_SUPPORTED BIT(31) -#define TASK_RESET_LOCK BIT(30) -#define TASK_RESET_STATE_MASK (TASK_RESET_SUPPORTED | TASK_RESET_LOCK) -#define TASK_RESET_WAITERS_MASK ~TASK_RESET_STATE_MASK -#define TASK_RESET_UNSUPPORTED 0 -#define TASK_RESET_STATE_LOCKED (TASK_RESET_SUPPORTED | TASK_RESET_LOCK) -#define TASK_RESET_STATE_UNLOCKED TASK_RESET_SUPPORTED - -#ifdef CONFIG_TASK_RESET_LIST -#define ENABLE_RESET(n) \ - [TASK_ID_##n] = TASK_RESET_SUPPORTED, -static uint32_t task_reset_state[TASK_ID_COUNT] = { -#ifdef CONFIG_TASK_RESET_LIST - CONFIG_TASK_RESET_LIST -#endif -}; -#undef ENABLE_RESET -#endif /* CONFIG_TASK_RESET_LIST */ - -/* Validity checks about static task invariants */ -BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned) * 8); -BUILD_ASSERT(TASK_ID_COUNT < (1 << (sizeof(task_id_t) * 8))); -BUILD_ASSERT(BIT(TASK_ID_COUNT) < TASK_RESET_LOCK); - -/* Stacks for all tasks */ -#define TASK(n, r, d, s) + s -uint8_t task_stacks[0 - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST -] __aligned(8); - -#undef TASK - -/* Reserve space to discard context on first context switch. */ -uint32_t scratchpad[17]; - -static task_ *current_task = (task_ *)scratchpad; - -/* - * Should IRQs chain to svc_handler()? This should be set if either of the - * following is true: - * - * 1) Task scheduling has started, and task profiling is enabled. Task - * profiling does its tracking in svc_handler(). - * - * 2) An event was set by an interrupt; this could result in a higher-priority - * task unblocking. After checking for a task switch, svc_handler() will clear - * the flag (unless profiling is also enabled; then the flag remains set). - */ -static int need_resched_or_profiling; - -/* - * Bitmap of all tasks ready to be run. - * - * Start off with only the hooks task marked as ready such that all the modules - * can do their init within a task switching context. The hooks task will then - * make a call to enable all tasks. - */ -static uint32_t tasks_ready = BIT(TASK_ID_HOOKS); -/* - * Initially allow only the HOOKS and IDLE task to run, regardless of ready - * status, in order for HOOK_INIT to complete before other tasks. - * task_enable_all_tasks() will open the flood gates. - */ -static uint32_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); - -static int start_called; /* Has task swapping started */ - -static inline task_ *__task_id_to_ptr(task_id_t id) -{ - return tasks + id; -} - -void interrupt_disable(void) -{ - asm("cpsid i"); -} - -void interrupt_enable(void) -{ - asm("cpsie i"); -} - -inline int is_interrupt_enabled(void) -{ - int primask; - - /* Interrupts are enabled when PRIMASK bit is 0 */ - asm("mrs %0, primask":"=r"(primask)); - - return !(primask & 0x1); -} - -inline int in_interrupt_context(void) -{ - int ret; - asm("mrs %0, ipsr \n" /* read exception number */ - "lsl %0, #23 \n":"=r"(ret)); /* exception bits are the 9 LSB */ - return ret; -} - -#ifdef CONFIG_TASK_PROFILING -static inline int get_interrupt_context(void) -{ - int ret; - asm("mrs %0, ipsr \n":"=r"(ret)); /* read exception number */ - return ret & 0x1ff; /* exception bits are the 9 LSB */ -} -#endif - -task_id_t task_get_current(void) -{ -#ifdef CONFIG_DEBUG_BRINGUP - /* If we haven't done a context switch then our task ID isn't valid */ - ASSERT(current_task != (task_ *)scratchpad); -#endif - return current_task - tasks; -} - -uint32_t *task_get_event_bitmap(task_id_t tskid) -{ - task_ *tsk = __task_id_to_ptr(tskid); - return &tsk->events; -} - -int task_start_called(void) -{ - return start_called; -} - -/** - * Scheduling system call - */ -void svc_handler(int desched, task_id_t resched) -{ - task_ *current, *next; -#ifdef CONFIG_TASK_PROFILING - int exc = get_interrupt_context(); - uint32_t t; -#endif - - /* - * Push the priority to -1 until the return, to avoid being - * interrupted. - */ - asm volatile("cpsid f\n" - "isb\n"); - -#ifdef CONFIG_TASK_PROFILING - /* - * SVCall isn't triggered via DECLARE_IRQ(), so it needs to track its - * start time explicitly. - */ - if (exc == 0xb) { - exc_start_time = get_time().le.lo; - svc_calls++; - } -#endif - - current = current_task; - -#ifdef CONFIG_DEBUG_STACK_OVERFLOW - if (*current->stack != STACK_UNUSED_VALUE) { - panic_printf("\n\nStack overflow in %s task!\n", - task_names[current - tasks]); -#ifdef CONFIG_SOFTWARE_PANIC - software_panic(PANIC_SW_STACK_OVERFLOW, current - tasks); -#endif - } -#endif - - if (desched && !current->events) { - /* - * Remove our own ready bit (current - tasks is same as - * task_get_current()) - */ - tasks_ready &= ~(1 << (current - tasks)); - } - ASSERT(resched <= TASK_ID_COUNT); - tasks_ready |= 1 << resched; - - ASSERT(tasks_ready & tasks_enabled); - next = __task_id_to_ptr(__fls(tasks_ready & tasks_enabled)); - -#ifdef CONFIG_TASK_PROFILING - /* Track time in interrupts */ - t = get_time().le.lo; - exc_total_time += (t - exc_start_time); - - /* - * Bill the current task for time between the end of the last interrupt - * and the start of this one. - */ - current->runtime += (exc_start_time - exc_end_time); - exc_end_time = t; -#else - /* - * Don't chain here from interrupts until the next time an interrupt - * sets an event. - */ - need_resched_or_profiling = 0; -#endif - - /* Nothing to do */ - if (next == current) - return; - - /* Switch to new task */ -#ifdef CONFIG_TASK_PROFILING - task_switches++; -#endif - current_task = next; - __switchto(current, next); -} - -void __schedule(int desched, int resched) -{ - register int p0 asm("r0") = desched; - register int p1 asm("r1") = resched; - - asm("svc 0"::"r"(p0),"r"(p1)); -} - -#ifdef CONFIG_TASK_PROFILING -void __keep task_start_irq_handler(void *excep_return) -{ - /* - * Get time before checking depth, in case this handler is - * pre-empted. - */ - uint32_t t = get_time().le.lo; - int irq = get_interrupt_context() - 16; - - /* - * Track IRQ distribution. No need for atomic add, because an IRQ - * can't pre-empt itself. - */ - if (irq < ARRAY_SIZE(irq_dist)) - irq_dist[irq]++; - - /* - * Continue iff a rescheduling event happened or profiling is active, - * and we are not called from another exception (this must match the - * logic for when we chain to svc_handler() below). - */ - if (!need_resched_or_profiling || (((uint32_t)excep_return & 0xf) == 1)) - return; - - exc_start_time = t; -} -#endif - -void __keep task_resched_if_needed(void *excep_return) -{ - /* - * Continue iff a rescheduling event happened or profiling is active, - * and we are not called from another exception. - */ - if (!need_resched_or_profiling || (((uint32_t)excep_return & 0xf) == 1)) - return; - - svc_handler(0, 0); -} - -static uint32_t __wait_evt(int timeout_us, task_id_t resched) -{ - task_ *tsk = current_task; - task_id_t me = tsk - tasks; - uint32_t evt; - int ret __attribute__((unused)); - - /* - * Scheduling task when interrupts are disabled will result in Forced - * Hard Fault because: - * - Disabling interrupt using 'cpsid i' also disables SVCall handler - * (because it has configurable priority) - * - Escalation to Hard Fault (also known as 'priority escalation') - * occurs when handler for that fault is not enabled - */ - ASSERT(is_interrupt_enabled()); - ASSERT(!in_interrupt_context()); - - if (timeout_us > 0) { - timestamp_t deadline = get_time(); - deadline.val += timeout_us; - ret = timer_arm(deadline, me); - ASSERT(ret == EC_SUCCESS); - } - while (!(evt = atomic_clear(&tsk->events))) { - /* Remove ourself and get the next task in the scheduler */ - __schedule(1, resched); - resched = TASK_ID_IDLE; - } - if (timeout_us > 0) { - timer_cancel(me); - /* Ensure timer event is clear, we no longer care about it */ - atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); - } - return evt; -} - -uint32_t task_set_event(task_id_t tskid, uint32_t event) -{ - task_ *receiver = __task_id_to_ptr(tskid); - ASSERT(receiver); - - /* Set the event bit in the receiver message bitmap */ - atomic_or(&receiver->events, event); - - /* Re-schedule if priorities have changed */ - if (in_interrupt_context() || !is_interrupt_enabled()) { - /* The receiver might run again */ - atomic_or(&tasks_ready, 1 << tskid); -#ifndef CONFIG_TASK_PROFILING - if (start_called) - need_resched_or_profiling = 1; -#endif - } else { - __schedule(0, tskid); - } - - return 0; -} - -uint32_t task_wait_event(int timeout_us) -{ - return __wait_evt(timeout_us, TASK_ID_IDLE); -} - -uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) -{ - uint64_t deadline = get_time().val + timeout_us; - uint32_t events = 0; - int time_remaining_us = timeout_us; - - /* Add the timer event to the mask so we can indicate a timeout */ - event_mask |= TASK_EVENT_TIMER; - - while (!(events & event_mask)) { - /* Collect events to re-post later */ - events |= __wait_evt(time_remaining_us, TASK_ID_IDLE); - - time_remaining_us = deadline - get_time().val; - if (timeout_us > 0 && time_remaining_us <= 0) { - /* Ensure we return a TIMER event if we timeout */ - events |= TASK_EVENT_TIMER; - break; - } - } - - /* Re-post any other events collected */ - if (events & ~event_mask) - atomic_or(¤t_task->events, events & ~event_mask); - - return events & event_mask; -} - -void task_enable_all_tasks(void) -{ - /* Mark all tasks as ready and able to run. */ - tasks_ready = tasks_enabled = BIT(TASK_ID_COUNT) - 1; - /* Reschedule the highest priority task. */ - if (is_interrupt_enabled()) - __schedule(0, 0); -} - -void task_enable_task(task_id_t tskid) -{ - atomic_or(&tasks_enabled, BIT(tskid)); -} - -void task_disable_task(task_id_t tskid) -{ - atomic_clear_bits(&tasks_enabled, BIT(tskid)); - - if (!in_interrupt_context() && is_interrupt_enabled() && - tskid == task_get_current()) - __schedule(0, 0); -} - -void task_enable_irq(int irq) -{ - CPU_NVIC_EN(irq / 32) = 1 << (irq % 32); -} - -void __keep task_disable_irq(int irq) -{ - CPU_NVIC_DIS(irq / 32) = 1 << (irq % 32); -} - -void task_clear_pending_irq(int irq) -{ - CPU_NVIC_UNPEND(irq / 32) = 1 << (irq % 32); -} - -void task_trigger_irq(int irq) -{ - CPU_NVIC_SWTRIG = irq; -} - -static uint32_t init_task_context(task_id_t id) -{ - uint32_t *sp; - /* Stack size in words */ - uint32_t ssize = tasks_init[id].stack_size / 4; - - /* - * Update stack used by first frame: 8 words for the normal - * stack, plus 8 for R4-R11. Even if using FPU, the first frame - * does not store FP regs. - */ - sp = tasks[id].stack + ssize - 16; - tasks[id].sp = (uint32_t)sp; - - /* Initial context on stack (see __switchto()) */ - sp[8] = tasks_init[id].r0; /* r0 */ - sp[13] = (uint32_t)task_exit_trap; /* lr */ - sp[14] = tasks_init[id].pc; /* pc */ - sp[15] = 0x01000000; /* psr */ - - /* Fill unused stack; also used to detect stack overflow. */ - for (sp = tasks[id].stack; sp < (uint32_t *)tasks[id].sp; sp++) - *sp = STACK_UNUSED_VALUE; - - return ssize; -} - -#ifdef CONFIG_TASK_RESET_LIST - -/* - * Re-initializes a task stack to its initial state, and marks it ready. - * The task reset lock must be held prior to calling this function. - */ -static void do_task_reset(task_id_t id) -{ - interrupt_disable(); - init_task_context(id); - tasks_ready |= 1 << id; - /* TODO: Clear all pending events? */ - interrupt_enable(); -} - -/* We can't pass a parameter to a deferred call. Use this instead. */ -/* Mask of task IDs waiting to be reset. */ -static uint32_t deferred_reset_task_ids; - -/* Tasks may call this function if they want to reset themselves. */ -static void deferred_task_reset(void) -{ - while (deferred_reset_task_ids) { - task_id_t reset_id = __fls(deferred_reset_task_ids); - - atomic_clear_bits(&deferred_reset_task_ids, 1 << reset_id); - do_task_reset(reset_id); - } -} -DECLARE_DEFERRED(deferred_task_reset); - -/* - * Helper for updating task_reset state atomically. Checks the current state, - * and if it matches if_value, updates the state to new_value, and returns - * TRUE. - */ -static int update_reset_state(uint32_t *state, - uint32_t if_value, - uint32_t to_value) -{ - int update; - - interrupt_disable(); - update = *state == if_value; - if (update) - *state = to_value; - interrupt_enable(); - - return update; -} - -/* - * Helper that acquires the reset lock iff it is not currently held. - * Returns TRUE if the lock was acquired. - */ -static inline int try_acquire_reset_lock(uint32_t *state) -{ - return update_reset_state(state, - /* if the lock is not held */ - TASK_RESET_STATE_UNLOCKED, - /* acquire it */ - TASK_RESET_STATE_LOCKED); -} - -/* - * Helper that releases the reset lock iff it is currently held, and there - * are no pending resets. Returns TRUE if the lock was released. - */ -static inline int try_release_reset_lock(uint32_t *state) -{ - return update_reset_state(state, - /* if the lock is held, with no waiters */ - TASK_RESET_STATE_LOCKED, - /* release it */ - TASK_RESET_STATE_UNLOCKED); -} - -/* - * Helper to cause the current task to sleep indefinitely; useful if the - * calling task just needs to block until it is reset. - */ -static inline void sleep_forever(void) -{ - while (1) - usleep(-1); -} - -void task_enable_resets(void) -{ - task_id_t id = task_get_current(); - uint32_t *state = &task_reset_state[id]; - - if (*state == TASK_RESET_UNSUPPORTED) { - cprints(CC_TASK, - "%s called from non-resettable task, id: %d", - __func__, id); - return; - } - - /* - * A correctly written resettable task will only call this function - * if resets are currently disabled; this implies that this task - * holds the reset lock. - */ - - if (*state == TASK_RESET_STATE_UNLOCKED) { - cprints(CC_TASK, - "%s called, but resets already enabled, id: %d", - __func__, id); - return; - } - - /* - * Attempt to release the lock. If we cannot, it means there are tasks - * waiting for a reset. - */ - if (try_release_reset_lock(state)) - return; - - /* People are waiting for us to reset; schedule a reset. */ - atomic_or(&deferred_reset_task_ids, 1 << id); - /* - * This will always trigger a deferred call after our new ID was - * written. If the hook call is currently executing, it will run - * again. - */ - hook_call_deferred(&deferred_task_reset_data, 0); - /* Wait to be reset. */ - sleep_forever(); -} - -void task_disable_resets(void) -{ - task_id_t id = task_get_current(); - uint32_t *state = &task_reset_state[id]; - - if (*state == TASK_RESET_UNSUPPORTED) { - cprints(CC_TASK, - "%s called from non-resettable task, id %d", - __func__, id); - return; - } - - /* - * A correctly written resettable task will only call this function - * if resets are currently enabled; this implies that this task does - * not hold the reset lock. - */ - - if (try_acquire_reset_lock(state)) - return; - - /* - * If we can't acquire the lock, we are about to be reset by another - * task. - */ - sleep_forever(); -} - -int task_reset_cleanup(void) -{ - task_id_t id = task_get_current(); - uint32_t *state = &task_reset_state[id]; - - /* - * If the task has never started before, state will be - * TASK_RESET_ENABLED. - * - * If the task was reset, the TASK_RESET_LOCK bit will be set, and - * there may additionally be bits representing tasks we must notify - * that we have reset. - */ - - /* - * Only this task can unset the lock bit so we can read this safely, - * even though other tasks may be modifying the state to add themselves - * as waiters. - */ - int cleanup_req = *state & TASK_RESET_LOCK; - - /* - * Attempt to release the lock. We can only do this when there are no - * tasks waiting to be notified that we have been reset, so we loop - * until no tasks are waiting. - * - * Other tasks may still be trying to reset us at this point; if they - * do, they will add themselves to the list of tasks we must notify. We - * will simply notify them (multiple times if necessary) until we are - * free to unlock. - */ - if (cleanup_req) { - while (!try_release_reset_lock(state)) { - /* Find the first waiter to notify. */ - task_id_t notify_id = __fls( - *state & TASK_RESET_WAITERS_MASK); - /* - * Remove the task from waiters first, so that - * when it wakes after being notified, it is in - * a consistent state (it should not be waiting - * to be notified and running). - * After being notified, the task may try to - * reset us again; if it does, it will just add - * itself back to the list of tasks to notify, - * and we will notify it again. - */ - atomic_clear_bits(state, 1 << notify_id); - /* - * Skip any invalid ids set by tasks that - * requested a non-blocking reset. - */ - if (notify_id < TASK_ID_COUNT) - task_set_event(notify_id, - TASK_EVENT_RESET_DONE); - } - } - - return cleanup_req; -} - -int task_reset(task_id_t id, int wait) -{ - task_id_t current = task_get_current(); - uint32_t *state = &task_reset_state[id]; - uint32_t waiter_id; - int resets_disabled; - - if (id == current) - return EC_ERROR_INVAL; - - /* - * This value is only set at compile time, and will never be modified. - */ - if (*state == TASK_RESET_UNSUPPORTED) - return EC_ERROR_INVAL; - - /* - * If we are not blocking for reset, we use an invalid task id to notify - * the task that _someone_ wanted it to reset, but didn't want to be - * notified when the reset is complete. - */ - waiter_id = 1 << (wait ? current : TASK_ID_COUNT); - - /* - * Try and take the lock. If we can't have it, just notify the task we - * tried; it will reset itself when it next tries to release the lock. - */ - interrupt_disable(); - resets_disabled = *state & TASK_RESET_LOCK; - if (resets_disabled) - *state |= waiter_id; - else - *state |= TASK_RESET_LOCK; - interrupt_enable(); - - if (!resets_disabled) { - /* We got the lock, do the reset immediately. */ - do_task_reset(id); - } else if (wait) { - /* - * We couldn't get the lock, and have been asked to block for - * reset. We have asked the task to reset itself; it will notify - * us when it has. - */ - task_wait_event_mask(TASK_EVENT_RESET_DONE, -1); - } - - return EC_SUCCESS; -} - -#endif /* CONFIG_TASK_RESET_LIST */ - -/* - * Initialize IRQs in the NVIC and set their priorities as defined by the - * DECLARE_IRQ statements. - */ -static void __nvic_init_irqs(void) -{ - /* Get the IRQ priorities section from the linker */ - int exc_calls = __irqprio_end - __irqprio; - int i; - - /* Mask and clear all pending interrupts */ - for (i = 0; i < 5; i++) { - CPU_NVIC_DIS(i) = 0xffffffff; - CPU_NVIC_UNPEND(i) = 0xffffffff; - } - - /* - * Re-enable global interrupts in case they're disabled. On a reboot, - * they're already enabled; if we've jumped here from another image, - * they're not. - */ - interrupt_enable(); - - /* Set priorities */ - for (i = 0; i < exc_calls; i++) { - cpu_set_interrupt_priority(__irqprio[i].irq, - __irqprio[i].priority); - } -} - -void mutex_lock(struct mutex *mtx) -{ - uint32_t value; - uint32_t id; - - /* - * mutex_lock() must not be used in interrupt context (because we wait - * if there is contention). - */ - ASSERT(!in_interrupt_context()); - - /* - * Task ID is not valid before task_start() (since current_task is - * scratchpad), and no need for mutex locking before task switching has - * begun. - */ - if (!task_start_called()) - return; - - id = 1 << task_get_current(); - - atomic_or(&mtx->waiters, id); - - do { - /* Try to get the lock (set 1 into the lock field) */ - __asm__ __volatile__(" ldrex %0, [%1]\n" - " teq %0, #0\n" - " it eq\n" - " strexeq %0, %2, [%1]\n" - : "=&r" (value) - : "r" (&mtx->lock), "r" (2) : "cc"); - /* - * "value" is equals to 1 if the store conditional failed, - * 2 if somebody else owns the mutex, 0 else. - */ - if (value == 2) - /* Contention on the mutex */ - task_wait_event_mask(TASK_EVENT_MUTEX, 0); - } while (value); - - atomic_clear_bits(&mtx->waiters, id); -} - -void mutex_unlock(struct mutex *mtx) -{ - uint32_t waiters; - task_ *tsk = current_task; - - /* - * Add a critical section to keep the unlock and the snapshotting of - * waiters atomic in case a task switching occurs between them. - */ - interrupt_disable(); - waiters = mtx->waiters; - mtx->lock = 0; - interrupt_enable(); - - while (waiters) { - task_id_t id = __fls(waiters); - waiters &= ~BIT(id); - - /* Somebody is waiting on the mutex */ - task_set_event(id, TASK_EVENT_MUTEX); - } - - /* Ensure no event is remaining from mutex wake-up */ - atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); -} - -void task_print_list(void) -{ - int i; - - ccputs("Task Ready Name Events Time (s) StkUsed\n"); - - for (i = 0; i < TASK_ID_COUNT; i++) { - char is_ready = (tasks_ready & (1<<i)) ? 'R' : ' '; - uint32_t *sp; - - int stackused = tasks_init[i].stack_size; - - for (sp = tasks[i].stack; - sp < (uint32_t *)tasks[i].sp && *sp == STACK_UNUSED_VALUE; - sp++) - stackused -= sizeof(uint32_t); - - ccprintf("%4d %c %-16s %08x %11.6lld %3d/%3d\n", i, is_ready, - task_names[i], tasks[i].events, tasks[i].runtime, - stackused, tasks_init[i].stack_size); - cflush(); - } -} - -int command_task_info(int argc, char **argv) -{ -#ifdef CONFIG_TASK_PROFILING - int total = 0; - int i; -#endif - - task_print_list(); - -#ifdef CONFIG_TASK_PROFILING - ccputs("IRQ counts by type:\n"); - cflush(); - for (i = 0; i < ARRAY_SIZE(irq_dist); i++) { - if (irq_dist[i]) { - ccprintf("%4d %8d\n", i, irq_dist[i]); - total += irq_dist[i]; - } - } - ccprintf("Service calls: %11d\n", svc_calls); - ccprintf("Total exceptions: %11d\n", total + svc_calls); - ccprintf("Task switches: %11d\n", task_switches); - ccprintf("Task switching started: %11.6lld s\n", task_start_time); - ccprintf("Time in tasks: %11.6lld s\n", - get_time().val - task_start_time); - ccprintf("Time in exceptions: %11.6lld s\n", exc_total_time); -#endif - - return EC_SUCCESS; -} -DECLARE_SAFE_CONSOLE_COMMAND(taskinfo, command_task_info, - NULL, - "Print task info"); - -#ifdef CONFIG_CMD_TASKREADY -static int command_task_ready(int argc, char **argv) -{ - if (argc < 2) { - ccprintf("tasks_ready: 0x%08x\n", tasks_ready); - } else { - tasks_ready = strtoi(argv[1], NULL, 16); - ccprintf("Setting tasks_ready to 0x%08x\n", tasks_ready); - __schedule(0, 0); - } - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(taskready, command_task_ready, - "[setmask]", - "Print/set ready tasks"); -#endif - -void task_pre_init(void) -{ - uint32_t *stack_next = (uint32_t *)task_stacks; - int i; - - /* Fill the task memory with initial values */ - for (i = 0; i < TASK_ID_COUNT; i++) { - tasks[i].stack = stack_next; - stack_next += init_task_context(i); - } - - /* - * Fill in guard value in scratchpad to prevent stack overflow - * detection failure on the first context switch. This works because - * the first word in the scratchpad is where the switcher will store - * sp, so it's ok to blow away. - */ - ((task_ *)scratchpad)->stack = (uint32_t *)scratchpad; - *(uint32_t *)scratchpad = STACK_UNUSED_VALUE; - - /* Initialize IRQs */ - __nvic_init_irqs(); -} - -void task_clear_fp_used(void) -{ - int ctrl; - - /* Clear the CONTROL.FPCA bit, which represents FP context active. */ - asm volatile("mrs %0, control" : "=r"(ctrl)); - ctrl &= ~0x4; - asm volatile("msr control, %0" : : "r"(ctrl)); - - /* Flush pipeline before returning. */ - asm volatile("isb"); -} - -int task_start(void) -{ -#ifdef CONFIG_TASK_PROFILING - timestamp_t t = get_time(); - - task_start_time = t.val; - exc_end_time = t.le.lo; -#endif - start_called = 1; - - return __task_start(&need_resched_or_profiling); -} - -#ifdef CONFIG_CMD_TASK_RESET -static int command_task_reset(int argc, char **argv) -{ - task_id_t id; - char *e; - - if (argc == 2) { - id = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - ccprintf("Resetting task %d\n", id); - return task_reset(id, 1); - } - - return EC_ERROR_PARAM_COUNT; -} -DECLARE_CONSOLE_COMMAND(taskreset, command_task_reset, - "task_id", - "Reset a task"); -#endif /* CONFIG_CMD_TASK_RESET */ diff --git a/core/cortex-m/uldivmod.S b/core/cortex-m/uldivmod.S deleted file mode 120000 index 7047a8c5d4..0000000000 --- a/core/cortex-m/uldivmod.S +++ /dev/null @@ -1 +0,0 @@ -../../third_party/libaeabi-cortexm0/core/cortex-m/uldivmod.S
\ No newline at end of file diff --git a/core/cortex-m/vecttable.c b/core/cortex-m/vecttable.c deleted file mode 100644 index 10b4b22422..0000000000 --- a/core/cortex-m/vecttable.c +++ /dev/null @@ -1,400 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Cortex-M CPU vector table - */ - -#ifndef ___INIT -#define ___INIT -#include "config.h" -#include <task.h> -#endif - -typedef void (*func)(void); - -#ifndef PASS -#define PASS 1 -#endif - -#if PASS == 1 -/* Default exception handler */ -void __attribute__((used, naked)) default_handler(void); -void default_handler() -{ - asm( - ".thumb_func\n" - " b exception_panic" - ); -} - -#define table(x) x - -#define weak_with_default __attribute__((used,weak,alias("default_handler"))) - -#define vec(name) extern void weak_with_default name ## _handler(void); -#define irq(num) vec(irq_ ## num) - -#define item(name) extern void name(void); -#define null - -extern void stack_end(void); /* not technically correct, it's just a pointer */ -extern void reset(void); - -#pragma GCC diagnostic push -#if __GNUC__ >= 8 -#pragma GCC diagnostic ignored "-Wattribute-alias" -#endif -/* Call default_handler if svc_handler is not found (task.c is not built) */ -void weak_with_default svc_handler(int desched, task_id_t resched); -#pragma GCC diagnostic pop - -/* - * SVC handler helper - * - * Work around issue where a late exception can corrupt r0 to r3, - * see section 2.7 (svc) of Cortex-M3 Application Note 179: - * http://infocenter.arm.com/help/topic/com.arm.doc.dai0179b/AppsNote179.pdf - * - * This approach differs slightly from the one in the document, - * it only loads r0 (desched) and r1 (resched) for svc_handler. - */ -void __attribute__((used,naked)) svc_helper_handler(void); -void svc_helper_handler() -{ - asm( - ".thumb_func\n" - " tst lr, #4 /* see if called from supervisor mode */\n" - " mrs r2, msp /* get the correct stack pointer into r2 */\n" - " it ne\n" - " mrsne r2, psp\n" - " ldr r1, [r2, #4] /* get regs from stack frame */\n" - " ldr r0, [r2]\n" - " b %0 /* call svc_handler */\n" - : - : "i"(svc_handler) - ); -} - -#endif /* PASS 1 */ - -#if PASS == 2 -#undef table -#undef vec -#undef irq -#undef item -#undef null - -/* number of elements before the first irq vector */ -#define IRQ_OFFSET 16 -/* element in the table that is null: extra IRQs are routed there, - * then finally overwritten - */ -#define IRQ_UNUSED_OFFSET 8 - -/* Disable warning that "initializer overrides prior initialization of this - * subobject", since we are explicitly doing this to handle the unused IRQs. - */ -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Winitializer-overrides" -#endif /* __clang__ */ - -#define table(x) \ - const func vectors[] __attribute__((section(".text.vecttable"))) = { \ - x \ - [IRQ_UNUSED_OFFSET] = null \ - }; - -#define vec(name) name ## _handler, -#define irq(num) [num < CONFIG_IRQ_COUNT ? num + IRQ_OFFSET : IRQ_UNUSED_OFFSET] = vec(irq_ ## num) - -#define item(name) name, -#define null (void*)0, -#endif /* PASS 2 */ - -table( - item(stack_end) - item(reset) - vec(nmi) - vec(hard_fault) - vec(mpu_fault) - vec(bus_fault) - vec(usage_fault) - null - null - null - null - item(svc_helper_handler) - vec(debug) - null - vec(pendsv) - vec(sys_tick) - irq(0) - irq(1) - irq(2) - irq(3) - irq(4) - irq(5) - irq(6) - irq(7) - irq(8) - irq(9) - irq(10) - irq(11) - irq(12) - irq(13) - irq(14) - irq(15) - irq(16) - irq(17) - irq(18) - irq(19) - irq(20) - irq(21) - irq(22) - irq(23) - irq(24) - irq(25) - irq(26) - irq(27) - irq(28) - irq(29) - irq(30) - irq(31) - irq(32) - irq(33) - irq(34) - irq(35) - irq(36) - irq(37) - irq(38) - irq(39) - irq(40) - irq(41) - irq(42) - irq(43) - irq(44) - irq(45) - irq(46) - irq(47) - irq(48) - irq(49) - irq(50) - irq(51) - irq(52) - irq(53) - irq(54) - irq(55) - irq(56) - irq(57) - irq(58) - irq(59) - irq(60) - irq(61) - irq(62) - irq(63) - irq(64) - irq(65) - irq(66) - irq(67) - irq(68) - irq(69) - irq(70) - irq(71) - irq(72) - irq(73) - irq(74) - irq(75) - irq(76) - irq(77) - irq(78) - irq(79) - irq(80) - irq(81) - irq(82) - irq(83) - irq(84) - irq(85) - irq(86) - irq(87) - irq(88) - irq(89) - irq(90) - irq(91) - irq(92) - irq(93) - irq(94) - irq(95) - irq(96) - irq(97) - irq(98) - irq(99) - irq(100) - irq(101) - irq(102) - irq(103) - irq(104) - irq(105) - irq(106) - irq(107) - irq(108) - irq(109) - irq(110) - irq(111) - irq(112) - irq(113) - irq(114) - irq(115) - irq(116) - irq(117) - irq(118) - irq(119) - irq(120) - irq(121) - irq(122) - irq(123) - irq(124) - irq(125) - irq(126) - irq(127) - irq(128) - irq(129) - irq(130) - irq(131) - irq(132) - irq(133) - irq(134) - irq(135) - irq(136) - irq(137) - irq(138) - irq(139) - irq(140) - irq(141) - irq(142) - irq(143) - irq(144) - irq(145) - irq(146) - irq(147) - irq(148) - irq(149) - irq(150) - irq(151) - irq(152) - irq(153) - irq(154) - irq(155) - irq(156) - irq(157) - irq(158) - irq(159) - irq(160) - irq(161) - irq(162) - irq(163) - irq(164) - irq(165) - irq(166) - irq(167) - irq(168) - irq(169) - irq(170) - irq(171) - irq(172) - irq(173) - irq(174) - irq(175) - irq(176) - irq(177) - irq(178) - irq(179) - irq(180) - irq(181) - irq(182) - irq(183) - irq(184) - irq(185) - irq(186) - irq(187) - irq(188) - irq(189) - irq(190) - irq(191) - irq(192) - irq(193) - irq(194) - irq(195) - irq(196) - irq(197) - irq(198) - irq(199) - irq(200) - irq(201) - irq(202) - irq(203) - irq(204) - irq(205) - irq(206) - irq(207) - irq(208) - irq(209) - irq(210) - irq(211) - irq(212) - irq(213) - irq(214) - irq(215) - irq(216) - irq(217) - irq(218) - irq(219) - irq(220) - irq(221) - irq(222) - irq(223) - irq(224) - irq(225) - irq(226) - irq(227) - irq(228) - irq(229) - irq(230) - irq(231) - irq(232) - irq(233) - irq(234) - irq(235) - irq(236) - irq(237) - irq(238) - irq(239) - irq(240) - irq(241) - irq(242) - irq(243) - irq(244) - irq(245) - irq(246) - irq(247) - irq(248) - irq(249) - irq(250) - irq(251) - irq(252) - irq(253) - irq(254) -) - -#if PASS == 2 -#ifdef __clang__ -#pragma clang diagnostic pop -#endif /* __clang__ */ -#endif - -#if PASS == 1 -#undef PASS -#define PASS 2 -#include "vecttable.c" -#endif diff --git a/core/cortex-m/watchdog.c b/core/cortex-m/watchdog.c deleted file mode 100644 index c9faf54b2b..0000000000 --- a/core/cortex-m/watchdog.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Watchdog common code */ - -#include "common.h" -#include "cpu.h" -#include "panic.h" -#include "task.h" -#include "timer.h" -#include "watchdog.h" - -/* - * As defined by Armv7-M Reference Manual B1.5.6 "Exception Entry Behavior", - * the structure of the saved context on the stack is: - * r0, r1, r2, r3, r12, lr, pc, psr, ... - */ -#define STACK_IDX_REG_LR 5 -#define STACK_IDX_REG_PC 6 - -void __keep watchdog_trace(uint32_t excep_lr, uint32_t excep_sp) -{ - uint32_t psp; - uint32_t *stack; - - asm("mrs %0, psp" : "=r"(psp)); - if ((excep_lr & 0xf) == 1) { - /* we were already in exception context */ - stack = (uint32_t *)excep_sp; - } else { - /* we were in task context */ - stack = (uint32_t *)psp; - } - - panic_set_reason(PANIC_SW_WATCHDOG, stack[STACK_IDX_REG_PC], - (excep_lr & 0xf) == 1 ? 0xff : task_get_current()); - - /* - * This is our last breath, the last opportunity to sort out all - * matters. Flush and invalidate D-cache if cache enabled. - */ - if (IS_ENABLED(CONFIG_ARMV7M_CACHE)) - cpu_clean_invalidate_dcache(); - - panic_printf("### WATCHDOG PC=%08x / LR=%08x / pSP=%08x ", - stack[STACK_IDX_REG_PC], stack[STACK_IDX_REG_LR], psp); - if ((excep_lr & 0xf) == 1) - panic_puts("(exc) ###\n"); - else - panic_printf("(task %d) ###\n", task_get_current()); - - /* If we are blocked in a high priority IT handler, the following debug - * messages might not appear but they are useless in that situation. */ - timer_print_info(); - task_print_list(); -} diff --git a/core/cortex-m0/__builtin.c b/core/cortex-m0/__builtin.c deleted file mode 100644 index 4bf495a011..0000000000 --- a/core/cortex-m0/__builtin.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" - -/* - * __builtin_ffs: - * Returns one plus the index of the least significant 1-bit of x, - * or if x is zero, returns zero. - */ -int __keep __ffssi2(int x) -{ - return 32 - __builtin_clz(x & -x); -} diff --git a/core/cortex-m0/atomic.h b/core/cortex-m0/atomic.h deleted file mode 100644 index 0c58e71e41..0000000000 --- a/core/cortex-m0/atomic.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Atomic operations for ARMv6-M */ - -#ifndef __CROS_EC_ATOMIC_H -#define __CROS_EC_ATOMIC_H - -#include "common.h" - -typedef int atomic_t; -typedef atomic_t atomic_val_t; - -/** - * Implements atomic arithmetic operations on 32-bit integers. - * - * There is no load/store exclusive on ARMv6-M, just disable interrupts - */ -#define ATOMIC_OP(asm_op, a, v) \ -({ \ - uint32_t reg0, reg1; \ - \ - __asm__ __volatile__(" cpsid i\n" \ - " ldr %0, [%2]\n" \ - " mov %1, %0\n" \ - #asm_op" %0, %0, %3\n" \ - " str %0, [%2]\n" \ - " cpsie i\n" \ - : "=&l"(reg0), "=&l"(reg1) \ - : "l"(a), "r"(v) \ - : "cc", "memory"); \ - reg1; \ -}) - -static inline atomic_val_t atomic_clear_bits(atomic_t *addr, atomic_val_t bits) -{ - return ATOMIC_OP(bic, addr, bits); -} - -static inline atomic_val_t atomic_or(atomic_t *addr, atomic_val_t bits) -{ - return ATOMIC_OP(orr, addr, bits); -} - -static inline atomic_val_t atomic_add(atomic_t *addr, atomic_val_t value) -{ - return ATOMIC_OP(add, addr, value); -} - -static inline atomic_val_t atomic_sub(atomic_t *addr, atomic_val_t value) -{ - return ATOMIC_OP(sub, addr, value); -} - -static inline atomic_val_t atomic_clear(atomic_t *addr) -{ - atomic_t ret; - - __asm__ __volatile__(" mov %2, #0\n" - " cpsid i\n" - " ldr %0, [%1]\n" - " str %2, [%1]\n" - " cpsie i\n" - : "=&l" (ret) - : "l" (addr), "r" (0) - : "cc", "memory"); - - return ret; -} - -#endif /* __CROS_EC_ATOMIC_H */ diff --git a/core/cortex-m0/build.mk b/core/cortex-m0/build.mk deleted file mode 100644 index b0136f347e..0000000000 --- a/core/cortex-m0/build.mk +++ /dev/null @@ -1,36 +0,0 @@ -# -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Cortex-M0 core OS files build -# - -# Use coreboot-sdk -$(call set-option,CROSS_COMPILE,\ - $(CROSS_COMPILE_arm),\ - /opt/coreboot-sdk/bin/arm-eabi-) - -# CPU specific compilation flags -CFLAGS_CPU+=-mthumb -Os -mno-sched-prolog -CFLAGS_CPU+=-mno-unaligned-access - -ifneq ($(CONFIG_LTO),) -CFLAGS_CPU+=-flto -LDFLAGS_EXTRA+=-flto -endif - -core-y=cpu.o debug.o init.o thumb_case.o div.o lmul.o ldivmod.o mula.o uldivmod.o -core-y+=vecttable.o __builtin.o -core-$(CONFIG_COMMON_PANIC_OUTPUT)+=panic.o -core-$(CONFIG_COMMON_RUNTIME)+=switch.o task.o - -dirs-y += core/$(CORE)/curve25519 - -core-$(CONFIG_CURVE25519)+=curve25519/mpy121666.o -core-$(CONFIG_CURVE25519)+=curve25519/reduce25519.o -core-$(CONFIG_CURVE25519)+=curve25519/mul.o -core-$(CONFIG_CURVE25519)+=curve25519/scalarmult.o -core-$(CONFIG_CURVE25519)+=curve25519/sqr.o - -core-$(CONFIG_WATCHDOG)+=watchdog.o diff --git a/core/cortex-m0/config_core.h b/core/cortex-m0/config_core.h deleted file mode 100644 index c31adc471c..0000000000 --- a/core/cortex-m0/config_core.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_CONFIG_CORE_H -#define __CROS_EC_CONFIG_CORE_H - -/* Linker binary architecture and format */ -#define BFD_ARCH arm -#define BFD_FORMAT "elf32-littlearm" - -/* Emulate the CLZ/CTZ instructions since the CPU core is lacking support */ -#define CONFIG_SOFTWARE_CLZ -#define CONFIG_SOFTWARE_CTZ -#define CONFIG_SOFTWARE_PANIC - -#define CONFIG_ASSEMBLY_MULA32 - -#endif /* __CROS_EC_CONFIG_CORE_H */ diff --git a/core/cortex-m0/cpu.c b/core/cortex-m0/cpu.c deleted file mode 100644 index b354cc03e2..0000000000 --- a/core/cortex-m0/cpu.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Set up the Cortex-M0 core - */ - -#include "cpu.h" - -void cpu_init(void) -{ - /* Catch unaligned access */ - CPU_NVIC_CCR |= CPU_NVIC_CCR_UNALIGN_TRAP; - - /* Set supervisor call (SVC) to priority 0 */ - CPU_NVIC_SHCSR2 = 0; - - /* Set lowest priority for PendSV */ - CPU_NVIC_SHCSR3 = (0xff << 16); -} diff --git a/core/cortex-m0/cpu.h b/core/cortex-m0/cpu.h deleted file mode 100644 index ac184090f9..0000000000 --- a/core/cortex-m0/cpu.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Registers map and definitions for Cortex-M0 processor - */ - -#ifndef __CROS_EC_CPU_H -#define __CROS_EC_CPU_H - -#include <stdint.h> -#include "compile_time_macros.h" - -/* Macro to access 32-bit registers */ -#define CPUREG(addr) (*(volatile uint32_t*)(addr)) - -/* Nested Vectored Interrupt Controller */ -#define CPU_NVIC_EN(x) CPUREG(0xe000e100) -#define CPU_NVIC_DIS(x) CPUREG(0xe000e180) -#define CPU_NVIC_UNPEND(x) CPUREG(0xe000e280) -#define CPU_NVIC_ISPR(x) CPUREG(0xe000e200) -#define CPU_NVIC_PRI(x) CPUREG(0xe000e400 + 4 * (x)) - -/* System Control Block */ -#define CPU_SCB_ICSR CPUREG(0xe000ed04) - -/* SCB AIRCR : Application interrupt and reset control register */ -#define CPU_NVIC_APINT CPUREG(0xe000ed0c) -#define CPU_NVIC_APINT_SYSRST BIT(2) /* System reset request */ -#define CPU_NVIC_APINT_ENDIAN BIT(15) /* Endianness */ -#define CPU_NVIC_APINT_KEY_RD (0U) -#define CPU_NVIC_APINT_KEY_WR (0x05FAU << 16) -/* SCB SCR : System Control Register */ -#define CPU_SCB_SYSCTRL CPUREG(0xe000ed10) -#define CPU_NVIC_CCR CPUREG(0xe000ed14) -#define CPU_NVIC_SHCSR2 CPUREG(0xe000ed1c) -#define CPU_NVIC_SHCSR3 CPUREG(0xe000ed20) - -#define CPU_NVIC_CCR_UNALIGN_TRAP BIT(3) - -/* Set up the cpu to detect faults */ -void cpu_init(void); - -/* Set the priority of the given IRQ in the NVIC (0 is highest). */ -static inline void cpu_set_interrupt_priority(uint8_t irq, uint8_t priority) -{ - const uint32_t prio_shift = irq % 4 * 8 + 6; - - if (priority > 3) - priority = 3; - - CPU_NVIC_PRI(irq / 4) = - (CPU_NVIC_PRI(irq / 4) & - ~(3 << prio_shift)) | - (priority << prio_shift); -} - -#endif /* __CROS_EC_CPU_H */ diff --git a/core/cortex-m0/curve25519 b/core/cortex-m0/curve25519 deleted file mode 120000 index ee9cb3b4a9..0000000000 --- a/core/cortex-m0/curve25519 +++ /dev/null @@ -1 +0,0 @@ -../../third_party/unacl-curve25519/core/cortex-m0/curve25519
\ No newline at end of file diff --git a/core/cortex-m0/debug.c b/core/cortex-m0/debug.c deleted file mode 120000 index 3cada87897..0000000000 --- a/core/cortex-m0/debug.c +++ /dev/null @@ -1 +0,0 @@ -../cortex-m/debug.c
\ No newline at end of file diff --git a/core/cortex-m0/debug.h b/core/cortex-m0/debug.h deleted file mode 120000 index d79be16190..0000000000 --- a/core/cortex-m0/debug.h +++ /dev/null @@ -1 +0,0 @@ -../cortex-m/debug.h
\ No newline at end of file diff --git a/core/cortex-m0/div.S b/core/cortex-m0/div.S deleted file mode 120000 index 776b7d2405..0000000000 --- a/core/cortex-m0/div.S +++ /dev/null @@ -1 +0,0 @@ -../../third_party/libaeabi-cortexm0/core/cortex-m0/div.S
\ No newline at end of file diff --git a/core/cortex-m0/ec.lds.S b/core/cortex-m0/ec.lds.S deleted file mode 100644 index bc461b90de..0000000000 --- a/core/cortex-m0/ec.lds.S +++ /dev/null @@ -1,360 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "config.h" -#include "rwsig.h" - -#define STRINGIFY0(name) #name -#define STRINGIFY(name) STRINGIFY0(name) - -#define FW_OFF_(section) CONFIG_##section##_MEM_OFF -#define FW_OFF(section) (CONFIG_PROGRAM_MEMORY_BASE + FW_OFF_(section)) - -#define FW_SIZE_(section) CONFIG_##section##_SIZE -#define FW_SIZE(section) FW_SIZE_(section) - -OUTPUT_FORMAT(BFD_FORMAT, BFD_FORMAT, BFD_FORMAT) -OUTPUT_ARCH(BFD_ARCH) -ENTRY(reset) - -MEMORY -{ -#ifdef CONFIG_SHAREDLIB - SHARED_LIB (rx) : ORIGIN = FW_OFF(SHAREDLIB), - LENGTH = FW_SIZE(SHAREDLIB) -#endif - FLASH (rx) : ORIGIN = FW_OFF(SECTION), LENGTH = FW_SIZE(SECTION) - IRAM (rw) : ORIGIN = CONFIG_RAM_BASE, LENGTH = CONFIG_RAM_SIZE - -#ifdef CONFIG_CHIP_MEMORY_REGIONS -#define REGION(name, attr, start, size) \ - name(attr) : ORIGIN = (start), LENGTH = (size) -#include "memory_regions.inc" -#undef REGION -#endif /* CONFIG_MEMORY_REGIONS */ -} - -SECTIONS -{ -#ifdef CONFIG_SHAREDLIB - .roshared : { - KEEP(*(.roshared*)) - } > SHARED_LIB -#endif - .text : { - *(.text.vecttable) - . = ALIGN(4); - __image_data_offset = .; - KEEP(*(.rodata.ver)) - - . = ALIGN(4); - KEEP(*(.rodata.pstate)) - - . = ALIGN(4); - STRINGIFY(OUTDIR/core/CORE/init.o) (.text) - *(.text*) - } > FLASH - - . = ALIGN(4); - .rodata : { - /* Symbols defined here are declared in link_defs.h */ - __irqprio = .; - KEEP(*(.rodata.irqprio)) - __irqprio_end = .; - - . = ALIGN(4); - __cmds = .; - KEEP(*(SORT(.rodata.cmds*))) - __cmds_end = .; - - . = ALIGN(4); - __extension_cmds = .; - KEEP(*(.rodata.extensioncmds)) - __extension_cmds_end = .; - - . = ALIGN(4); - __hcmds = .; - KEEP(*(SORT(.rodata.hcmds*))) - __hcmds_end = .; - - . = ALIGN(4); - __mkbp_evt_srcs = .; - KEEP(*(.rodata.evtsrcs)) - __mkbp_evt_srcs_end = .; - - . = ALIGN(4); - __hooks_init = .; - KEEP(*(.rodata.HOOK_INIT)) - __hooks_init_end = .; - - __hooks_pre_freq_change = .; - KEEP(*(.rodata.HOOK_PRE_FREQ_CHANGE)) - __hooks_pre_freq_change_end = .; - - __hooks_freq_change = .; - KEEP(*(.rodata.HOOK_FREQ_CHANGE)) - __hooks_freq_change_end = .; - - __hooks_sysjump = .; - KEEP(*(.rodata.HOOK_SYSJUMP)) - __hooks_sysjump_end = .; - - __hooks_chipset_pre_init = .; - KEEP(*(.rodata.HOOK_CHIPSET_PRE_INIT)) - __hooks_chipset_pre_init_end = .; - - __hooks_chipset_startup = .; - KEEP(*(.rodata.HOOK_CHIPSET_STARTUP)) - __hooks_chipset_startup_end = .; - - __hooks_chipset_resume = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESUME)) - __hooks_chipset_resume_end = .; - - __hooks_chipset_suspend = .; - KEEP(*(.rodata.HOOK_CHIPSET_SUSPEND)) - __hooks_chipset_suspend_end = .; - -#ifdef CONFIG_CHIPSET_RESUME_INIT_HOOK - __hooks_chipset_resume_init = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESUME_INIT)) - __hooks_chipset_resume_init_end = .; - - __hooks_chipset_suspend_complete = .; - KEEP(*(.rodata.HOOK_CHIPSET_SUSPEND_COMPLETE)) - __hooks_chipset_suspend_complete_end = .; -#endif - - __hooks_chipset_shutdown = .; - KEEP(*(.rodata.HOOK_CHIPSET_SHUTDOWN)) - __hooks_chipset_shutdown_end = .; - - __hooks_chipset_shutdown_complete = .; - KEEP(*(.rodata.HOOK_CHIPSET_SHUTDOWN_COMPLETE)) - __hooks_chipset_shutdown_complete_end = .; - - __hooks_chipset_hard_off = .; - KEEP(*(.rodata.HOOK_CHIPSET_HARD_OFF)) - __hooks_chipset_hard_off_end = .; - - __hooks_chipset_reset = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESET)) - __hooks_chipset_reset_end = .; - - __hooks_ac_change = .; - KEEP(*(.rodata.HOOK_AC_CHANGE)) - __hooks_ac_change_end = .; - - __hooks_lid_change = .; - KEEP(*(.rodata.HOOK_LID_CHANGE)) - __hooks_lid_change_end = .; - - __hooks_tablet_mode_change = .; - KEEP(*(.rodata.HOOK_TABLET_MODE_CHANGE)) - __hooks_tablet_mode_change_end = .; - - __hooks_base_attached_change = .; - KEEP(*(.rodata.HOOK_BASE_ATTACHED_CHANGE)) - __hooks_base_attached_change_end = .; - - __hooks_pwrbtn_change = .; - KEEP(*(.rodata.HOOK_POWER_BUTTON_CHANGE)) - __hooks_pwrbtn_change_end = .; - - __hooks_battery_soc_change = .; - KEEP(*(.rodata.HOOK_BATTERY_SOC_CHANGE)) - __hooks_battery_soc_change_end = .; - -#ifdef CONFIG_USB_SUSPEND - __hooks_usb_change = .; - KEEP(*(.rodata.HOOK_USB_PM_CHANGE)) - __hooks_usb_change_end = .; -#endif - - __hooks_tick = .; - KEEP(*(.rodata.HOOK_TICK)) - __hooks_tick_end = .; - - __hooks_second = .; - KEEP(*(.rodata.HOOK_SECOND)) - __hooks_second_end = .; - - __hooks_usb_pd_disconnect = .; - KEEP(*(.rodata.HOOK_USB_PD_DISCONNECT)) - __hooks_usb_pd_disconnect_end = .; - - __hooks_usb_pd_connect = .; - KEEP(*(.rodata.HOOK_USB_PD_CONNECT)) - __hooks_usb_pd_connect_end = .; - - __deferred_funcs = .; - KEEP(*(.rodata.deferred)) - __deferred_funcs_end = .; - - __usb_desc = .; - KEEP(*(.rodata.usb_desc_conf)) - KEEP(*(SORT(.rodata.usb_desc*))) - __usb_desc_end = .; - . = ALIGN(4); - KEEP(*(.rodata.usb_ep)) - KEEP(*(.rodata.usb_ep.usb_ep_tx)) - KEEP(*(.rodata.usb_ep.usb_ep_rx)) - KEEP(*(.rodata.usb_ep.usb_ep_event)) - KEEP(*(.rodata.usb_ep.usb_iface_request)) - - . = ALIGN(4); - *(.rodata*) - -#ifdef CONFIG_CHIP_INIT_ROM_REGION - ASSERT(0, "CONFIG_CHIP_INIT_ROM_REGION not supported by linker script") -#endif /* CONFIG_CHIP_INIT_ROM_REGION */ - /* - * This linker file does not yet support a separate ROM resident - * section. Ensure the corresponding data objects are linked - * into the .rodata section. - */ - . = ALIGN(4); - __init_rom_start = .; - *(.init.rom) - __init_rom_end = .; - -#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS) - . = ALIGN(64); - KEEP(*(.google)) -#endif - . = ALIGN(4); - } > FLASH - - __data_lma_start = . ; - .vtable : { - /* - * Vector table must be at the base of SRAM. The vector - * table section contains a RAM copy of the vector table used on - * STM chips for relocating the vector table. - */ - . = ALIGN(8); - *(.bss.vector_table) - . = ALIGN(8); - } > IRAM - -#ifdef CONFIG_PRESERVE_LOGS - .preserve_logs(NOLOAD) : { - /* - * The size of the vector table is fixed. Thus, the address of - * the preserved logs is also fixed. - */ - . = ALIGN(8); - *(SORT(.preserved_logs.*)) - . = ALIGN(8); - __preserved_logs_end = .; - } > IRAM - - ASSERT((SIZEOF(.vtable) + SIZEOF(.preserve_logs) + CONFIG_RAM_BASE) == - __preserved_logs_end, - "preserve_logs must be right after vtable") -#endif - - .bss : { - . = ALIGN(8); - __bss_start = .; - /* Stacks must be 64-bit aligned */ - . = ALIGN(8); - *(.bss.system_stack) - /* Rest of .bss takes care of its own alignment */ - *(.bss) - *(.bss.slow) - - /* - * Reserve space for deferred function firing times. - * Each time is a uint64_t, each func is a 32-bit pointer, - * thus the scaling factor of two. The 8 byte alignment of - * uint64_t is required by the ARM ABI. - */ - . = ALIGN(8); - __deferred_until = .; - . += (__deferred_funcs_end - __deferred_funcs) * (8 / 4); - __deferred_until_end = .; - - . = ALIGN(4); - __bss_end = .; - } > IRAM - - .data : AT(ADDR(.rodata) + SIZEOF(.rodata)) { - . = ALIGN(4); - __data_start = .; - *(.data.tasks) - *(.data) - . = ALIGN(4); - *(.iram.text) - . = ALIGN(4); - __data_end = .; - - /* - * Shared memory buffer must be at the end of preallocated - * RAM, so it can expand to use all the remaining RAM. - */ - __shared_mem_buf = .; - - /* NOTHING MAY GO AFTER THIS! */ - } > IRAM - - ASSERT((__shared_mem_buf + CONFIG_SHAREDMEM_MINIMUM_SIZE) <= - (CONFIG_RAM_BASE + CONFIG_RAM_SIZE), - "Not enough space for shared memory.") - - __ram_free = (CONFIG_RAM_BASE + CONFIG_RAM_SIZE) - - (__shared_mem_buf + CONFIG_SHAREDMEM_MINIMUM_SIZE); - - /* - * __flash_used is used in flash free calculations by the makefile. - * __image_size is stored in the struct image_data header and used - * in hash calcuations. - */ - __flash_used = LOADADDR(.data) + SIZEOF(.data) - ORIGIN(FLASH); - __image_size = __flash_used; - -#ifdef CONFIG_FLASH_CROS - /* - * These linker labels are just for analysis and not used in the code. - */ - __config_flash_size = CONFIG_FLASH_SIZE_BYTES; - __config_ro_size = CONFIG_RO_SIZE; - __config_ec_protected_storage_size = CONFIG_EC_PROTECTED_STORAGE_SIZE; - __config_rw_size = CONFIG_RW_SIZE; - __config_ec_writable_storage_size = CONFIG_EC_WRITABLE_STORAGE_SIZE; -#endif - - /* - * The linker won't notice if the .data section is too big to fit, - * apparently because we're sending it into IRAM, not FLASH. - * Verify that all sections linked into the FLASH region will fit. - */ - ASSERT((LENGTH(FLASH) -#if defined(CONFIG_RWSIG) && defined(SECTION_IS_RO) - - CONFIG_RO_PUBKEY_SIZE -#endif -#if defined(CONFIG_RWSIG) && defined(SECTION_IS_RW) - - CONFIG_RW_SIG_SIZE -#endif - ) >= __flash_used, - "No room left in the flash") - - __image_size = __flash_used; - -#ifdef CONFIG_CHIP_MEMORY_REGIONS -#define REGION(name, attr, start, size) \ - .name(NOLOAD) : { \ - __##name##_start = .; \ - *(SORT(.name.*)) \ - } > name -#include "memory_regions.inc" -#undef REGION -#endif /* CONFIG_CHIP_MEMORY_REGIONS */ - -#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS)) - /DISCARD/ : { *(.google) } -#endif - /DISCARD/ : { *(.ARM.*) } -} diff --git a/core/cortex-m0/include/fpu.h b/core/cortex-m0/include/fpu.h deleted file mode 100644 index 3acec557a7..0000000000 --- a/core/cortex-m0/include/fpu.h +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Math utility functions for ARMv6-M */ - -#ifndef __CROS_EC_FPU_H -#define __CROS_EC_FPU_H - -#endif /* __CROS_EC_FPU_H */ diff --git a/core/cortex-m0/init.S b/core/cortex-m0/init.S deleted file mode 100644 index 5047d18380..0000000000 --- a/core/cortex-m0/init.S +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Cortex-M0 CPU initialization - */ - -#include "config.h" - -#ifdef CHIP_FAMILY_STM32F0 -/* Allocate space for SRAM vector table at SRAM based address */ -.section .bss.vector_table -sram_vtable: .skip (48*4) -#endif - -.text -.syntax unified -.code 16 - -.global reset -.thumb_func -reset: - /* - * Ensure we're in privileged mode with main stack. Necessary if - * we've jumped directly here from another image after task_start(). - */ - movs r0, #0 @ priv. mode / main stack / no floating point - msr control, r0 - isb @ ensure the write is done - - /* Clear BSS */ - movs r0, #0 - ldr r1,_bss_start - ldr r2,_bss_end -bss_loop: - str r0, [r1] - adds r1, #4 - cmp r1, r2 - blt bss_loop - -#ifdef CHIP_FAMILY_STM32F0 - /* - * STM32F0 parts don't have the VTOR register for relocating - * the vector table. Instead, we must copy the vector table from - * flash into SRAM. - */ - ldr r1, =vectors - ldr r2, =sram_vtable - movs r0, #0 -vtable_loop: - ldr r3, [r1] - str r3, [r2] - adds r1, #4 - adds r2, #4 - adds r0, #1 - cmp r0, #48 - blt vtable_loop - - /* Set SYSCFG_CFGR1 mem_mode to load vector table from SRAM */ - movs r0, #3 - ldr r1, =0x40010000 - str r0, [r1] -#else - /* Set the vector table on our current code */ - ldr r1, =vectors - ldr r2, =0xE000ED08 /* VTOR register in SCB*/ - str r1, [r2] -#endif - - /* Copy initialized data to Internal RAM */ - ldr r0,_data_lma_start - ldr r1,_data_start - ldr r2,_data_end -data_loop: - ldr r3, [r0] - adds r0, #4 - str r3, [r1] - adds r1, #4 - cmp r1, r2 - blt data_loop - - /* - * Set stack pointer. Already done by Cortex-M hardware, but re-doing - * this here allows software to jump directly to the reset vector. - */ - ldr r0, =stack_end - mov sp, r0 - - /* Jump to C code */ - bl main - - /* That should not return. If it does, loop forever. */ -fini_loop: - b fini_loop - -/* Default exception handler */ -.thumb_func -default_handler: - ldr r0, =exception_panic - bx r0 - -.align 2 -_bss_start: -.long __bss_start -_bss_end: -.long __bss_end -_data_start: -.long __data_start -_data_end: -.long __data_end -_data_lma_start: -.long __data_lma_start - -/* Mock functions to avoid linker complaints */ -.global __aeabi_unwind_cpp_pr0 -.global __aeabi_unwind_cpp_pr1 -.global __aeabi_unwind_cpp_pr2 -__aeabi_unwind_cpp_pr0: -__aeabi_unwind_cpp_pr1: -__aeabi_unwind_cpp_pr2: - bx lr - -/* Reserve space for system stack */ -.section .bss.system_stack -stack_start: -.space CONFIG_STACK_SIZE, 0 -stack_end: -.global stack_end - diff --git a/core/cortex-m0/irq_handler.h b/core/cortex-m0/irq_handler.h deleted file mode 100644 index de36ef7623..0000000000 --- a/core/cortex-m0/irq_handler.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Helper to declare IRQ handling routines */ - -#ifndef __CROS_EC_IRQ_HANDLER_H -#define __CROS_EC_IRQ_HANDLER_H - -#include "cpu.h" - -/* Helper macros to build the IRQ handler and priority struct names */ -#define IRQ_HANDLER(irqname) CONCAT3(irq_, irqname, _handler) -#define IRQ_PRIORITY(irqname) CONCAT2(prio_, irqname) - -/* - * Macro to connect the interrupt handler "routine" to the irq number "irq" and - * ensure it is enabled in the interrupt controller with the right priority. - */ -#define DECLARE_IRQ(irq, routine, priority) DECLARE_IRQ_(irq, routine, priority) -#ifdef CONFIG_TASK_PROFILING -#define DECLARE_IRQ_(irq, routine, priority) \ - void routine(void); \ - void IRQ_HANDLER(irq)(void) \ - { \ - void *ret = __builtin_return_address(0); \ - task_start_irq_handler(ret); \ - routine(); \ - task_end_irq_handler(ret); \ - } \ - const struct irq_priority __keep IRQ_PRIORITY(irq) \ - __attribute__((section(".rodata.irqprio"))) \ - = {irq, priority} -#else /* CONFIG_TASK_PROFILING */ -/* No Profiling : connect directly the IRQ vector */ -#define DECLARE_IRQ_(irq, routine, priority) \ - void routine(void); \ - void IRQ_HANDLER(irq)(void) __attribute__((alias(STRINGIFY(routine))));\ - const struct irq_priority __keep IRQ_PRIORITY(irq) \ - __attribute__((section(".rodata.irqprio"))) \ - = {irq, priority} -#endif /* CONFIG_TASK_PROFILING */ -#endif /* __CROS_EC_IRQ_HANDLER_H */ diff --git a/core/cortex-m0/ldivmod.S b/core/cortex-m0/ldivmod.S deleted file mode 120000 index 603ea316c8..0000000000 --- a/core/cortex-m0/ldivmod.S +++ /dev/null @@ -1 +0,0 @@ -../../third_party/libaeabi-cortexm0/core/cortex-m0/ldivmod.S
\ No newline at end of file diff --git a/core/cortex-m0/lmul.S b/core/cortex-m0/lmul.S deleted file mode 120000 index ab5bfc3cb2..0000000000 --- a/core/cortex-m0/lmul.S +++ /dev/null @@ -1 +0,0 @@ -../../third_party/libaeabi-cortexm0/core/cortex-m0/lmul.S
\ No newline at end of file diff --git a/core/cortex-m0/mula.S b/core/cortex-m0/mula.S deleted file mode 100644 index 02e617c328..0000000000 --- a/core/cortex-m0/mula.S +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Cortex-M0 multiply-accumulate[-accumulate] functions - */ - - .syntax unified - .text - .thumb - -@ uint64_t mula32(uint32_t a, uint32_t b, uint32_t c) -@ -@ Multiply a (r0) and b (r1), add c (r2) and return the product in r1:r0 -@ - .thumb_func - .section .text.mula32 - .global mula32 -mula32: - - push {r4, r5} - uxth r4, r0 /* r4 = a.lo16 */ - uxth r5, r1 /* r5 = b.lo16 */ - uxth r3, r2 /* r3 = c.lo16 */ - muls r4, r5 /* r4 = a.lo16 * b.lo16 */ - adds r4, r3 /* r4 = a.lo16 * b.lo16 + c.lo16 == r.lo32 */ - lsrs r3, r0, 16 /* r3 = a.hi16 */ - lsrs r2, r2, 16 /* r2 = c.hi16 */ - muls r5, r3 /* r5 = a.hi16 * b.lo16 */ - adds r5, r2 /* r5 = a.hi16 * b.lo16 + c.hi16 == r.mid32.1 */ - uxth r2, r0 /* r2 = a.lo16 */ - lsrs r1, r1, 16 /* r1 = b.hi16 */ - muls r2, r1 /* r2 = a.lo16 * b.hi16 == r.mid32.2 */ - muls r1, r3 /* r1 = b.hi16 * a.hi16 == r.hi32 */ - movs r3, 0 /* r3 = 0 */ - adds r5, r2 /* r5 = (r.mid32.1 + r.mid32.2).lo32 == r.mid.lo32 */ - adcs r3, r3 /* r3 = (r.mid32.1 + r.mid32.2).hi32 == r.mid.hi32 */ - lsls r0, r5, 16 /* r0 = r.mid.lo32.lo16 << 16 == r.mid.inpos.lo32 */ - lsrs r5, r5, 16 /* r5 = r.mid.lo32.hi16 >> 16 */ - lsls r3, r3, 16 /* r3 = r.mid.hi.lo16 << 16 */ - adds r3, r5 /* r3 = r5 + r3 = r.mid.inpos.hi32 */ - adds r0, r4 /* r0 = r.lo32 */ - adcs r1, r3 /* r1 = r.hi32 */ - pop {r4, r5} - bx lr - -@ uint64_t mulaa32(uint32_t a, uint32_t b, uint32_t c, uint32_t d) -@ -@ Multiply a (r0) and b (r1), add c (r2), add d (r3) and return the product in -@ r1:r0 - .thumb_func - .section .text.mulaa32 - .global mulaa32 -mulaa32: - - push {r4, r5, r6} - uxth r5, r0 /* r5 = a.lo16 */ - uxth r6, r1 /* r6 = b.lo16 */ - uxth r4, r2 /* r4 = c.lo16 */ - muls r5, r6 /* r5 = a.lo16 * b.lo16 */ - adds r5, r4 /* r5 = a.lo16 * b.lo16 + c.lo16 == r.lo32 */ - lsrs r4, r0, 16 /* r4 = a.hi16 */ - lsrs r2, r2, 16 /* r2 = c.hi16 */ - muls r6, r4 /* r6 = a.hi16 * b.lo16 */ - adds r6, r2 /* r6 = a.hi16 * b.lo16 + c.hi16 == r.mid32.1 */ - uxth r2, r0 /* r2 = a.lo16 */ - lsrs r1, r1, 16 /* r1 = b.hi16 */ - muls r2, r1 /* r2 = a.lo16 * b.hi16 == r.mid32.2 */ - muls r1, r4 /* r1 = b.hi16 * a.hi16 == r.hi32 */ - movs r4, 0 /* r4 = 0 */ - adds r6, r2 /* r6 = (r.mid32.1 + r.mid32.2).lo32 == r.mid.lo32 */ - adcs r4, r4 /* r4 = (r.mid32.1 + r.mid32.2).hi32 == r.mid.hi32 */ - lsls r0, r6, 16 /* r0 = r.mid.lo32.lo16 << 16 == r.mid.inpos.lo32 */ - lsrs r6, r6, 16 /* r6 = r.mid.lo32.hi16 >> 16 */ - lsls r4, r4, 16 /* r4 = r.mid.hi.lo16 << 16 */ - adds r0, r3 /* r0 = r.mid.inposition.lo32 + d */ - adcs r4, r6 /* r4 = r6 + r4 + carry = r.mid.inpos.hi32 */ - adds r0, r5 /* r0 = r.lo32 */ - adcs r1, r4 /* r1 = r.hi32 */ - pop {r4, r5, r6} - bx lr diff --git a/core/cortex-m0/panic-internal.h b/core/cortex-m0/panic-internal.h deleted file mode 100644 index 51c12f65b2..0000000000 --- a/core/cortex-m0/panic-internal.h +++ /dev/null @@ -1,13 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_PANIC_INTERNAL_H -#define __CROS_EC_PANIC_INTERNAL_H - -#include <stdnoreturn.h> - -noreturn void exception_panic(void) __attribute__((naked)); - -#endif /* __CROS_EC_PANIC_INTERNAL_H */ diff --git a/core/cortex-m0/panic.c b/core/cortex-m0/panic.c deleted file mode 100644 index 4fe69fddb1..0000000000 --- a/core/cortex-m0/panic.c +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" -#include "console.h" -#include "cpu.h" -#include "host_command.h" -#include "panic.h" -#include "panic-internal.h" -#include "printf.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#include "watchdog.h" - -/* Whether bus fault is ignored */ -static int bus_fault_ignored; - - -/* Panic data goes at the end of RAM. */ -static struct panic_data * const pdata_ptr = PANIC_DATA_PTR; - -/* Preceded by stack, rounded down to nearest 64-bit-aligned boundary */ -static const uint32_t pstack_addr = (CONFIG_RAM_BASE + CONFIG_RAM_SIZE - - sizeof(struct panic_data)) & ~7; - -/** - * Print the name and value of a register - * - * This is a convenient helper function for displaying a register value. - * It shows the register name in a 3 character field, followed by a colon. - * The register value is regs[index], and this is shown in hex. If regs is - * NULL, then we display spaces instead. - * - * After displaying the value, either a space or \n is displayed depending - * on the register number, so that (assuming the caller passes all 16 - * registers in sequence) we put 4 values per line like this - * - * r0 :0000000b r1 :00000047 r2 :60000000 r3 :200012b5 - * r4 :00000000 r5 :08004e64 r6 :08004e1c r7 :200012a8 - * r8 :08004e64 r9 :00000002 r10:00000000 r11:00000000 - * r12:0000003f sp :200009a0 lr :0800270d pc :0800351a - * - * @param regnum Register number to display (0-15) - * @param regs Pointer to array holding the registers, or NULL - * @param index Index into array where the register value is present - */ -static void print_reg(int regnum, const uint32_t *regs, int index) -{ - static const char regname[] = "r10r11r12sp lr pc "; - static char rname[3] = "r "; - const char *name; - - rname[1] = '0' + regnum; - name = regnum < 10 ? rname : ®name[(regnum - 10) * 3]; - panic_printf("%c%c%c:", name[0], name[1], name[2]); - if (regs) - panic_printf("%08x", regs[index]); - else - panic_puts(" "); - panic_puts((regnum & 3) == 3 ? "\n" : " "); -} - -/* - * Returns non-zero if the exception frame was created on the main stack, or - * zero if it's on the process stack. - * - * See B1.5.8 "Exception return behavior" of ARM DDI 0403D for details. - */ -static int32_t is_frame_in_handler_stack(const uint32_t exc_return) -{ - return (exc_return & 0xf) == 1 || (exc_return & 0xf) == 9; -} - -/* - * Print panic data - */ -void panic_data_print(const struct panic_data *pdata) -{ - const uint32_t *lregs = pdata->cm.regs; - const uint32_t *sregs = NULL; - const int32_t in_handler = - is_frame_in_handler_stack(pdata->cm.regs[11]); - int i; - - if (pdata->flags & PANIC_DATA_FLAG_FRAME_VALID) - sregs = pdata->cm.frame; - - panic_printf("\n=== %s EXCEPTION: %02x ====== xPSR: %08x ===\n", - in_handler ? "HANDLER" : "PROCESS", - lregs[1] & 0xff, sregs ? sregs[7] : -1); - for (i = 0; i < 4; i++) - print_reg(i, sregs, i); - for (i = 4; i < 10; i++) - print_reg(i, lregs, i - 1); - print_reg(10, lregs, 9); - print_reg(11, lregs, 10); - print_reg(12, sregs, 4); - print_reg(13, lregs, in_handler ? 2 : 0); - print_reg(14, sregs, 5); - print_reg(15, sregs, 6); -} - -void __keep report_panic(void) -{ - /* - * Don't need to get pointer via get_panic_data_write() - * because memory below pdata_ptr is stack now (see exception_panic()) - */ - struct panic_data *pdata = pdata_ptr; - uint32_t sp; - - pdata->magic = PANIC_DATA_MAGIC; - pdata->struct_size = sizeof(*pdata); - pdata->struct_version = 2; - pdata->arch = PANIC_ARCH_CORTEX_M; - pdata->flags = 0; - pdata->reserved = 0; - - /* Choose the right sp (psp or msp) based on EXC_RETURN value */ - sp = is_frame_in_handler_stack(pdata->cm.regs[11]) - ? pdata->cm.regs[2] : pdata->cm.regs[0]; - /* If stack is valid, copy exception frame to pdata */ - if ((sp & 3) == 0 && - sp >= CONFIG_RAM_BASE && - sp <= CONFIG_RAM_BASE + CONFIG_RAM_SIZE - 8 * sizeof(uint32_t)) { - const uint32_t *sregs = (const uint32_t *)sp; - int i; - for (i = 0; i < 8; i++) - pdata->cm.frame[i] = sregs[i]; - pdata->flags |= PANIC_DATA_FLAG_FRAME_VALID; - } - - panic_data_print(pdata); - panic_reboot(); -} - -/** - * Default exception handler, which reports a panic. - * - * Declare this as a naked call so we can extract raw LR and IPSR values. - */ -void exception_panic(void) -{ - /* Save registers and branch directly to panic handler */ - asm volatile( - "mov r0, %[pregs]\n" - "mrs r1, psp\n" - "mrs r2, ipsr\n" - "mov r3, sp\n" - "stmia r0!, {r1-r7}\n" - "mov r1, r8\n" - "mov r2, r9\n" - "mov r3, r10\n" - "mov r4, r11\n" - "mov r5, lr\n" - "stmia r0!, {r1-r5}\n" - "mov sp, %[pstack]\n" - "bl report_panic\n" : : - [pregs] "r" (pdata_ptr->cm.regs), - [pstack] "r" (pstack_addr) : - /* Constraints protecting these from being clobbered. - * Gcc should be using r0 & r12 for pregs and pstack. */ - "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", - "r10", "r11", "cc", "memory" - ); -} - -#ifdef CONFIG_SOFTWARE_PANIC -void software_panic(uint32_t reason, uint32_t info) -{ - __asm__("mov " STRINGIFY(SOFTWARE_PANIC_INFO_REG) ", %0\n" - "mov " STRINGIFY(SOFTWARE_PANIC_REASON_REG) ", %1\n" - "bl exception_panic\n" - : : "r"(info), "r"(reason)); - __builtin_unreachable(); -} - -void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) -{ - struct panic_data * const pdata = get_panic_data_write(); - uint32_t *lregs; - - lregs = pdata->cm.regs; - - /* Setup panic data structure */ - memset(pdata, 0, CONFIG_PANIC_DATA_SIZE); - pdata->magic = PANIC_DATA_MAGIC; - pdata->struct_size = CONFIG_PANIC_DATA_SIZE; - pdata->struct_version = 2; - pdata->arch = PANIC_ARCH_CORTEX_M; - - /* Log panic cause */ - lregs[1] = exception; - lregs[3] = reason; - lregs[4] = info; -} - -void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) -{ - struct panic_data * const pdata = panic_get_data(); - uint32_t *lregs; - - if (pdata && pdata->struct_version == 2) { - lregs = pdata->cm.regs; - *exception = lregs[1]; - *reason = lregs[3]; - *info = lregs[4]; - } else { - *exception = *reason = *info = 0; - } -} -#endif - -void bus_fault_handler(void) -{ - if (!bus_fault_ignored) - exception_panic(); -} - -void ignore_bus_fault(int ignored) -{ - bus_fault_ignored = ignored; -} diff --git a/core/cortex-m0/switch.S b/core/cortex-m0/switch.S deleted file mode 100644 index a75daad939..0000000000 --- a/core/cortex-m0/switch.S +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Context swtching - */ - -#include "config.h" - -#define CPU_SCB_ICSR 0xe000ed04 - -.text - -.syntax unified -.code 16 - -/** - * Task context switching - * - * Change the task scheduled after returning from the exception. - * - * Save the registers of the current task below the exception context on - * its task, then restore the live registers of the next task and set the - * process stack pointer to the new stack. - * - * r0: pointer to the task to switch from - * r1: pointer to the task to switch to - * - * must be called from interrupt context - * - * the structure of the saved context on the stack is : - * r8, r9, r10, r11, r4, r5, r6, r7, r0, r1, r2, r3, r12, lr, pc, psr - * additional registers <|> exception frame - */ -.global __switchto -.thumb_func -__switchto: - mrs r2, psp @ get the task stack where the context has been saved - mov r3, sp - mov sp, r2 - push {r4-r7} @ save additional r4-r7 in the task stack - mov r4, r8 - mov r5, r9 - mov r6, r10 - mov r7, r11 - push {r4-r7} @ save additional r8-r11 in the task stack - mov r2, sp @ prepare to save former task stack pointer - mov sp, r3 @ restore system stack pointer - str r2, [r0] @ save the task stack pointer in its context - ldr r2, [r1] @ get the new scheduled task stack pointer - ldmia r2!, {r4-r7} @ restore r8-r11 for the next task context - mov r8, r4 - mov r9, r5 - mov r10, r6 - mov r11, r7 - ldmia r2!, {r4-r7} @ restore r4-r7 for the next task context - msr psp, r2 @ set the process stack pointer to exception context - bx lr @ return from exception - -/** - * Start the task scheduling. r0 is a pointer to task_stack_ready, which is - * set to 1 after the task stack is set up. - */ -.global __task_start -.thumb_func -__task_start: - ldr r2,=scratchpad @ area used as thread stack for the first switch - movs r3, #2 @ use : priv. mode / thread stack / no floating point - adds r2, #17*4 @ put the pointer at the top of the stack - movs r1, #0 @ __Schedule parameter : re-schedule nothing - msr psp, r2 @ setup a thread stack up to the first context switch - movs r2, #1 @ r2 = TASK_SCHEDULER_INIT - isb @ ensure the write is done - msr control, r3 - movs r3, r0 - movs r0, #0 @ __Schedule parameter : de-schedule nothing - isb @ ensure the write is done - str r2, [r3] @ Task scheduling is now active - bl __schedule @ execute the task with the highest priority - /* we should never return here */ - movs r0, #1 @ set to EC_ERROR_UNKNOWN - bx lr - -/** - * SVC exception handler - */ -.global svc_handler -.thumb_func -svc_handler: - push {r3, lr} @ save link register and keep stack aligned - bl __svc_handler @ call svc handler helper - ldr r3,=current_task @ load the current task's address - ldr r1, [r3] @ load the current task - cmp r0, r1 @ compare with previous task returned by helper - beq svc_handler_return @ return if they are the same - bl __switchto @ context switch to the next task -svc_handler_return: - pop {r3, pc} @ return from exception or return to caller - -/** - * PendSVC exception handler - */ -.global pendsv_handler -.thumb_func -pendsv_handler: - push {r3, lr} @ save link register and keep stack aligned - ldr r0, =CPU_SCB_ICSR @ load CPU_SCB_ICSR's address - movs r1, #1 @ prepare left shift (1 << 27) - lsls r1, #27 @ shift the bit - str r1, [r0] @ clear pending flag - cpsid i @ ensure we have priority 0 during re-scheduling - movs r1, #0 @ desched nothing - movs r0, #0 @ resched nothing - bl svc_handler @ re-schedule the highest priority task - cpsie i @ leave priority 0 - pop {r3, pc} @ return from exception diff --git a/core/cortex-m0/task.c b/core/cortex-m0/task.c deleted file mode 100644 index ba40b667b6..0000000000 --- a/core/cortex-m0/task.c +++ /dev/null @@ -1,691 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Task scheduling / events module for Chrome EC operating system */ - -#include "atomic.h" -#include "common.h" -#include "console.h" -#include "cpu.h" -#include "link_defs.h" -#include "panic.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -typedef union { - struct { - /* - * Note that sp must be the first element in the task struct - * for __switchto() to work. - */ - uint32_t sp; /* Saved stack pointer for context switch */ - uint32_t events; /* Bitmaps of received events */ - uint64_t runtime; /* Time spent in task */ - uint32_t *stack; /* Start of stack */ - }; -} task_; - -/* Value to store in unused stack */ -#define STACK_UNUSED_VALUE 0xdeadd00d - -/* declare task routine prototypes */ -#define TASK(n, r, d, s) void r(void *); -void __idle(void); -CONFIG_TASK_LIST -CONFIG_TEST_TASK_LIST -CONFIG_CTS_TASK_LIST -#undef TASK - -/* Task names for easier debugging */ -#define TASK(n, r, d, s) #n, -static const char * const task_names[] = { - "<< idle >>", - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST -}; -#undef TASK - -#ifdef CONFIG_TASK_PROFILING -static uint64_t task_start_time; /* Time task scheduling started */ -/* - * We only keep 32-bit values for exception start/end time, to avoid - * accounting errors when we service interrupt when the timer wraps around. - */ -static uint32_t exc_start_time; /* Time of task->exception transition */ -static uint32_t exc_end_time; /* Time of exception->task transition */ -static uint64_t exc_total_time; /* Total time in exceptions */ -static uint32_t svc_calls; /* Number of service calls */ -static uint32_t task_switches; /* Number of times active task changed */ -static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ -#endif - -extern int __task_start(int *task_stack_ready); - -#ifndef CONFIG_LOW_POWER_IDLE -/* Idle task. Executed when no tasks are ready to be scheduled. */ -void __idle(void) -{ - while (1) { - /* - * Wait for the next irq event. This stops the CPU clock - * (sleep / deep sleep, depending on chip config). - */ - asm("wfi"); - } -} -#endif /* !CONFIG_LOW_POWER_IDLE */ - -static void task_exit_trap(void) -{ - int i = task_get_current(); - cprints(CC_TASK, "Task %d (%s) exited!", i, task_names[i]); - /* Exited tasks simply sleep forever */ - while (1) - task_wait_event(-1); -} - -/* Startup parameters for all tasks. */ -#define TASK(n, r, d, s) { \ - .r0 = (uint32_t)d, \ - .pc = (uint32_t)r, \ - .stack_size = s, \ -}, -static const struct { - uint32_t r0; - uint32_t pc; - uint16_t stack_size; -} tasks_init[] = { - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST -}; -#undef TASK - -/* Contexts for all tasks */ -static task_ tasks[TASK_ID_COUNT]; -/* Validity checks about static task invariants */ -BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned) * 8); -BUILD_ASSERT(TASK_ID_COUNT < (1 << (sizeof(task_id_t) * 8))); - - -/* Stacks for all tasks */ -#define TASK(n, r, d, s) + s -uint8_t task_stacks[0 - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST -] __aligned(8); - -#undef TASK - -/* Reserve space to discard context on first context switch. */ -uint32_t scratchpad[17]; - -task_ *current_task = (task_ *)scratchpad; - -/* - * Bitmap of all tasks ready to be run. - * - * Start off with only the hooks task marked as ready such that all the modules - * can do their init within a task switching context. The hooks task will then - * make a call to enable all tasks. - */ -static uint32_t tasks_ready = BIT(TASK_ID_HOOKS); -/* - * Initially allow only the HOOKS and IDLE task to run, regardless of ready - * status, in order for HOOK_INIT to complete before other tasks. - * task_enable_all_tasks() will open the flood gates. - */ -static uint32_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); - -static int start_called; /* Has task swapping started */ - -static inline task_ *__task_id_to_ptr(task_id_t id) -{ - return tasks + id; -} - -void interrupt_disable(void) -{ - asm("cpsid i"); -} - -void interrupt_enable(void) -{ - asm("cpsie i"); -} - -inline int is_interrupt_enabled(void) -{ - int primask; - - /* Interrupts are enabled when PRIMASK bit is 0 */ - asm("mrs %0, primask":"=r"(primask)); - - return !(primask & 0x1); -} - -inline int in_interrupt_context(void) -{ - int ret; - asm("mrs %0, ipsr\n" /* read exception number */ - "lsl %0, #23\n" : "=r"(ret)); /* exception bits are the 9 LSB */ - return ret; -} - -static inline int get_interrupt_context(void) -{ - int ret; - asm("mrs %0, ipsr\n" : "=r"(ret)); /* read exception number */ - return ret & 0x1ff; /* exception bits are the 9 LSB */ -} - -task_id_t task_get_current(void) -{ -#ifdef CONFIG_DEBUG_BRINGUP - /* If we haven't done a context switch then our task ID isn't valid */ - ASSERT(current_task != (task_ *)scratchpad); -#endif - return current_task - tasks; -} - -uint32_t *task_get_event_bitmap(task_id_t tskid) -{ - task_ *tsk = __task_id_to_ptr(tskid); - return &tsk->events; -} - -int task_start_called(void) -{ - return start_called; -} - -/** - * Scheduling system call - */ -task_ __attribute__((noinline)) *__svc_handler(int desched, task_id_t resched) -{ - task_ *current, *next; -#ifdef CONFIG_TASK_PROFILING - int exc = get_interrupt_context(); - uint32_t t; -#endif - - /* Priority is already at 0 we cannot be interrupted */ - -#ifdef CONFIG_TASK_PROFILING - /* - * SVCall isn't triggered via DECLARE_IRQ(), so it needs to track its - * start time explicitly. - */ - if (exc == 0xb) { - t = get_time().le.lo; - current_task->runtime += (t - exc_end_time); - exc_end_time = t; - svc_calls++; - } -#endif - - current = current_task; - -#ifdef CONFIG_DEBUG_STACK_OVERFLOW - if (*current->stack != STACK_UNUSED_VALUE) { - panic_printf("\n\nStack overflow in %s task!\n", - task_names[current - tasks]); -#ifdef CONFIG_SOFTWARE_PANIC - software_panic(PANIC_SW_STACK_OVERFLOW, current - tasks); -#endif - } -#endif - - if (desched && !current->events) { - /* - * Remove our own ready bit (current - tasks is same as - * task_get_current()) - */ - tasks_ready &= ~(1 << (current - tasks)); - } - tasks_ready |= 1 << resched; - - ASSERT(tasks_ready & tasks_enabled); - next = __task_id_to_ptr(__fls(tasks_ready & tasks_enabled)); - -#ifdef CONFIG_TASK_PROFILING - /* Track additional time in re-sched exception context */ - t = get_time().le.lo; - exc_total_time += (t - exc_end_time); - - exc_end_time = t; -#endif - - /* Switch to new task */ -#ifdef CONFIG_TASK_PROFILING - if (next != current) - task_switches++; -#endif - current_task = next; - return current; -} - -void __schedule(int desched, int resched) -{ - register int p0 asm("r0") = desched; - register int p1 asm("r1") = resched; - - asm("svc 0" : : "r"(p0), "r"(p1)); -} - -#ifdef CONFIG_TASK_PROFILING -void task_start_irq_handler(void *excep_return) -{ - /* - * Get time before checking depth, in case this handler is - * pre-empted. - */ - uint32_t t = get_time().le.lo; - int irq = get_interrupt_context() - 16; - - /* - * Track IRQ distribution. No need for atomic add, because an IRQ - * can't pre-empt itself. - */ - if (irq < ARRAY_SIZE(irq_dist)) - irq_dist[irq]++; - - /* - * Continue iff the tasks are ready and we are not called from another - * exception (as the time accouting is done in the outer irq). - */ - if (!start_called || ((uint32_t)excep_return & 0xf) == 1) - return; - - exc_start_time = t; - /* - * Bill the current task for time between the end of the last interrupt - * and the start of this one. - */ - current_task->runtime += (exc_start_time - exc_end_time); -} - -void task_end_irq_handler(void *excep_return) -{ - uint32_t t = get_time().le.lo; - /* - * Continue iff the tasks are ready and we are not called from another - * exception (as the time accouting is done in the outer irq). - */ - if (!start_called || ((uint32_t)excep_return & 0xf) == 1) - return; - - /* Track time in interrupts */ - exc_total_time += (t - exc_start_time); - exc_end_time = t; -} -#endif - -static uint32_t __wait_evt(int timeout_us, task_id_t resched) -{ - task_ *tsk = current_task; - task_id_t me = tsk - tasks; - uint32_t evt; - int ret __attribute__((unused)); - - /* - * Scheduling task when interrupts are disabled will result in Forced - * Hard Fault because disabling interrupt using 'cpsid i' also disables - * SVCall handler (because it has configurable priority) - */ - ASSERT(is_interrupt_enabled()); - ASSERT(!in_interrupt_context()); - - if (timeout_us > 0) { - timestamp_t deadline = get_time(); - deadline.val += timeout_us; - ret = timer_arm(deadline, me); - ASSERT(ret == EC_SUCCESS); - } - while (!(evt = atomic_clear(&tsk->events))) { - /* - * We need to ensure that the execution priority is actually - * decreased after the "cpsie i" in the atomic operation above - * else the "svc" in the __schedule call below will trigger - * a HardFault. Use a barrier to force it at that point. - */ - asm volatile("isb"); - /* Remove ourself and get the next task in the scheduler */ - __schedule(1, resched); - resched = TASK_ID_IDLE; - } - if (timeout_us > 0) { - timer_cancel(me); - /* Ensure timer event is clear, we no longer care about it */ - atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); - } - return evt; -} - -uint32_t task_set_event(task_id_t tskid, uint32_t event) -{ - task_ *receiver = __task_id_to_ptr(tskid); - ASSERT(receiver); - - /* Set the event bit in the receiver message bitmap */ - atomic_or(&receiver->events, event); - - /* Re-schedule if priorities have changed */ - if (in_interrupt_context() || !is_interrupt_enabled()) { - /* The receiver might run again */ - atomic_or(&tasks_ready, 1 << tskid); - if (start_called) { - /* - * Trigger the scheduler when there's - * no other irqs happening. - */ - CPU_SCB_ICSR = BIT(28); - } - } else { - /* - * We need to ensure that the execution priority is - * actually decreased after the "cpsie i" in the atomic - * operation above else the "svc" in the __schedule - * call below will trigger a HardFault. - * Use a barrier to force it at that point. - */ - asm volatile("isb"); - __schedule(0, tskid); - } - - return 0; -} - -uint32_t task_wait_event(int timeout_us) -{ - return __wait_evt(timeout_us, TASK_ID_IDLE); -} - -uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) -{ - uint64_t deadline = get_time().val + timeout_us; - uint32_t events = 0; - int time_remaining_us = timeout_us; - - /* Add the timer event to the mask so we can indicate a timeout */ - event_mask |= TASK_EVENT_TIMER; - - while (!(events & event_mask)) { - /* Collect events to re-post later */ - events |= __wait_evt(time_remaining_us, TASK_ID_IDLE); - - time_remaining_us = deadline - get_time().val; - if (timeout_us > 0 && time_remaining_us <= 0) { - /* Ensure we return a TIMER event if we timeout */ - events |= TASK_EVENT_TIMER; - break; - } - } - - /* Re-post any other events collected */ - if (events & ~event_mask) - atomic_or(¤t_task->events, events & ~event_mask); - - return events & event_mask; -} - -void task_enable_all_tasks(void) -{ - /* Mark all tasks as ready and able to run. */ - tasks_ready = tasks_enabled = BIT(TASK_ID_COUNT) - 1; - /* Reschedule the highest priority task. */ - if (is_interrupt_enabled()) - __schedule(0, 0); -} - -void task_enable_task(task_id_t tskid) -{ - atomic_or(&tasks_enabled, BIT(tskid)); -} - -void task_disable_task(task_id_t tskid) -{ - atomic_clear_bits(&tasks_enabled, BIT(tskid)); - - if (!in_interrupt_context() && is_interrupt_enabled() && - tskid == task_get_current()) - __schedule(0, 0); -} - -void task_enable_irq(int irq) -{ - CPU_NVIC_EN(0) = 1 << irq; -} - -void task_disable_irq(int irq) -{ - CPU_NVIC_DIS(0) = 1 << irq; -} - -void task_clear_pending_irq(int irq) -{ - CPU_NVIC_UNPEND(0) = 1 << irq; -} - -void task_trigger_irq(int irq) -{ - CPU_NVIC_ISPR(0) = 1 << irq; -} - -/* - * Initialize IRQs in the NVIC and set their priorities as defined by the - * DECLARE_IRQ statements. - */ -static void __nvic_init_irqs(void) -{ - /* Get the IRQ priorities section from the linker */ - int exc_calls = __irqprio_end - __irqprio; - int i; - - /* Mask and clear all pending interrupts */ - CPU_NVIC_DIS(0) = 0xffffffff; - CPU_NVIC_UNPEND(0) = 0xffffffff; - - /* - * Re-enable global interrupts in case they're disabled. On a reboot, - * they're already enabled; if we've jumped here from another image, - * they're not. - */ - interrupt_enable(); - - /* Set priorities */ - for (i = 0; i < exc_calls; i++) { - cpu_set_interrupt_priority(__irqprio[i].irq, - __irqprio[i].priority); - } -} - -void mutex_lock(struct mutex *mtx) -{ - uint32_t id = 1 << task_get_current(); - - ASSERT(id != TASK_ID_INVALID); - atomic_or(&mtx->waiters, id); - - while (1) { - /* Try to get the lock (set 2 into the lock field) */ - __asm__ __volatile__("cpsid i"); - if (mtx->lock == 0) - break; - __asm__ __volatile__("cpsie i"); - /* Contention on the mutex */ - task_wait_event_mask(TASK_EVENT_MUTEX, 0); - } - mtx->lock = 2; - __asm__ __volatile__("cpsie i"); - - atomic_clear_bits(&mtx->waiters, id); -} - -void mutex_unlock(struct mutex *mtx) -{ - uint32_t waiters; - task_ *tsk = current_task; - - /* - * Add a critical section to keep the unlock and the snapshotting of - * waiters atomic in case a task switching occurs between them. - */ - interrupt_disable(); - waiters = mtx->waiters; - mtx->lock = 0; - interrupt_enable(); - - while (waiters) { - task_id_t id = __fls(waiters); - waiters &= ~BIT(id); - - /* Somebody is waiting on the mutex */ - task_set_event(id, TASK_EVENT_MUTEX); - } - - /* Ensure no event is remaining from mutex wake-up */ - atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); -} - -void task_print_list(void) -{ - int i; - - ccputs("Task Ready Name Events Time (s) StkUsed\n"); - - for (i = 0; i < TASK_ID_COUNT; i++) { - char is_ready = (tasks_ready & (1<<i)) ? 'R' : ' '; - uint32_t *sp; - - int stackused = tasks_init[i].stack_size; - - for (sp = tasks[i].stack; - sp < (uint32_t *)tasks[i].sp && *sp == STACK_UNUSED_VALUE; - sp++) - stackused -= sizeof(uint32_t); - - ccprintf("%4d %c %-16s %08x %11.6lld %3d/%3d\n", i, is_ready, - task_names[i], tasks[i].events, tasks[i].runtime, - stackused, tasks_init[i].stack_size); - cflush(); - } -} - -int command_task_info(int argc, char **argv) -{ -#ifdef CONFIG_TASK_PROFILING - int total = 0; - int i; -#endif - - task_print_list(); - -#ifdef CONFIG_TASK_PROFILING - ccputs("IRQ counts by type:\n"); - cflush(); - for (i = 0; i < ARRAY_SIZE(irq_dist); i++) { - if (irq_dist[i]) { - ccprintf("%4d %8d\n", i, irq_dist[i]); - total += irq_dist[i]; - } - } - ccprintf("Service calls: %11d\n", svc_calls); - ccprintf("Total exceptions: %11d\n", total + svc_calls); - ccprintf("Task switches: %11d\n", task_switches); - ccprintf("Task switching started: %11.6lld s\n", task_start_time); - ccprintf("Time in tasks: %11.6lld s\n", - get_time().val - task_start_time); - ccprintf("Time in exceptions: %11.6lld s\n", exc_total_time); -#endif - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(taskinfo, command_task_info, - NULL, - "Print task info"); - -#ifdef CONFIG_CMD_TASKREADY -static int command_task_ready(int argc, char **argv) -{ - if (argc < 2) { - ccprintf("tasks_ready: 0x%08x\n", tasks_ready); - } else { - tasks_ready = strtoi(argv[1], NULL, 16); - ccprintf("Setting tasks_ready to 0x%08x\n", tasks_ready); - __schedule(0, 0); - } - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(taskready, command_task_ready, - "[setmask]", - "Print/set ready tasks"); -#endif - -void task_pre_init(void) -{ - uint32_t *stack_next = (uint32_t *)task_stacks; - int i; - - /* Fill the task memory with initial values */ - for (i = 0; i < TASK_ID_COUNT; i++) { - uint32_t *sp; - /* Stack size in words */ - uint32_t ssize = tasks_init[i].stack_size / 4; - - tasks[i].stack = stack_next; - - /* - * Update stack used by first frame: 8 words for the normal - * stack, plus 8 for R4-R11. With FP enabled, we need another - * 18 words for S0-S15 and FPCSR and to align to 64-bit. - */ - sp = stack_next + ssize - 16; - tasks[i].sp = (uint32_t)sp; - - /* Initial context on stack (see __switchto()) */ - sp[8] = tasks_init[i].r0; /* r0 */ - sp[13] = (uint32_t)task_exit_trap; /* lr */ - sp[14] = tasks_init[i].pc; /* pc */ - sp[15] = 0x01000000; /* psr */ - - /* Fill unused stack; also used to detect stack overflow. */ - for (sp = stack_next; sp < (uint32_t *)tasks[i].sp; sp++) - *sp = STACK_UNUSED_VALUE; - - stack_next += ssize; - } - - /* - * Fill in guard value in scratchpad to prevent stack overflow - * detection failure on the first context switch. This works because - * the first word in the scratchpad is where the switcher will store - * sp, so it's ok to blow away. - */ - ((task_ *)scratchpad)->stack = (uint32_t *)scratchpad; - *(uint32_t *)scratchpad = STACK_UNUSED_VALUE; - - /* Initialize IRQs */ - __nvic_init_irqs(); -} - -int task_start(void) -{ -#ifdef CONFIG_TASK_PROFILING - timestamp_t t = get_time(); - - task_start_time = t.val; - exc_end_time = t.le.lo; -#endif - - return __task_start(&start_called); -} diff --git a/core/cortex-m0/thumb_case.S b/core/cortex-m0/thumb_case.S deleted file mode 100644 index 5628361a94..0000000000 --- a/core/cortex-m0/thumb_case.S +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Thumb mode toolchain helpers for compact switch/case statement. - */ - -#include "config.h" - -.text - -.syntax unified -.code 16 - -/* - * Helpers for compact switch - * - * r0: the table index - * lr: the table base address (need to clear bit 0) - * - * r0 and lr must be PRESERVED. - * r12 can be clobbered. - */ -.section .text.__gnu_thumb1_case_uqi -.global __gnu_thumb1_case_uqi -.thumb_func -__gnu_thumb1_case_uqi: - mov r12, r1 - mov r1, lr - lsrs r1, r1, #1 - lsls r1, r1, #1 - ldrb r1, [r1, r0] - lsls r1, r1, #1 - add lr, lr, r1 - mov r1, r12 - bx lr - -.section .text.__gnu_thumb1_case_sqi -.global __gnu_thumb1_case_sqi -.thumb_func -__gnu_thumb1_case_sqi: - mov r12, r1 - mov r1, lr - lsrs r1, r1, #1 - lsls r1, r1, #1 - ldrsb r1, [r1, r0] - lsls r1, r1, #1 - add lr, lr, r1 - mov r1, r12 - bx lr - -.section .text.__gnu_thumb1_case_uhi -.global __gnu_thumb1_case_uhi -.thumb_func -__gnu_thumb1_case_uhi: - push {r0, r1} - mov r1, lr - lsrs r1, r1, #1 - lsls r0, r0, #1 - lsls r1, r1, #1 - ldrh r1, [r1, r0] - lsls r1, r1, #1 - add lr, lr, r1 - pop {r0, r1} - bx lr - -.section .text.__gnu_thumb1_case_shi -.global __gnu_thumb1_case_shi -.thumb_func -__gnu_thumb1_case_shi: - push {r0, r1} - mov r1, lr - lsrs r1, r1, #1 - lsls r0, r0, #1 - lsls r1, r1, #1 - ldrsh r1, [r1, r0] - lsls r1, r1, #1 - add lr, lr, r1 - pop {r0, r1} - bx lr - -.section .text.__gnu_thumb1_case_si -.global __gnu_thumb1_case_si -.thumb_func -__gnu_thumb1_case_si: - push {r0, r1} - mov r1, lr - adds.n r1, r1, #2 - lsrs r1, r1, #2 - lsls r0, r0, #2 - lsls r1, r1, #2 - ldr r0, [r1, r0] - adds r0, r0, r1 - mov lr, r0 - pop {r0, r1} - mov pc, lr diff --git a/core/cortex-m0/uldivmod.S b/core/cortex-m0/uldivmod.S deleted file mode 120000 index 6d1e5e1998..0000000000 --- a/core/cortex-m0/uldivmod.S +++ /dev/null @@ -1 +0,0 @@ -../../third_party/libaeabi-cortexm0/core/cortex-m0/uldivmod.S
\ No newline at end of file diff --git a/core/cortex-m0/vecttable.c b/core/cortex-m0/vecttable.c deleted file mode 100644 index b1eaa957e0..0000000000 --- a/core/cortex-m0/vecttable.c +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Cortex-M CPU vector table - */ - -#ifndef ___INIT -#define ___INIT -#include <stddef.h> -#include <stdint.h> - -#include "config.h" -#include "panic-internal.h" -#include "task.h" -#endif /* __INIT */ - -typedef void (*func)(void); - -#ifndef PASS -#define PASS 1 -#endif - -#if PASS == 1 - -void __attribute__((naked)) default_handler(void) -{ - /* - * An (enforced) long tail call to preserve exn_return in lr without - * restricting the relative placement of default_handler and - * exception_panic. - */ - asm volatile("bx %0\n" : : "r" (exception_panic)); -} - -#define table(x) x - -/* Note: the alias target must be defined in this translation unit */ -#define weak_with_default __attribute__((used, weak, alias("default_handler"))) - -#define vec(name) extern void weak_with_default name ## _handler(void); -#define irq(num) vec(irq_ ## num) - -#define item(name) extern void name(void); -#define null - -extern void stack_end(void); /* not technically correct, it's just a pointer */ -extern void reset(void); - -#pragma GCC diagnostic push -#if __GNUC__ >= 8 -#pragma GCC diagnostic ignored "-Wattribute-alias" -#endif -#pragma GCC diagnostic pop - -#endif /* PASS 1 */ - -#if PASS == 2 -#undef table -#undef vec -#undef irq -#undef item -#undef null - -/* number of elements before the first irq vector */ -#define IRQ_OFFSET 16 -/* element in the table that is null: extra IRQs are routed there, - * then finally overwritten - */ -#define IRQ_UNUSED_OFFSET 8 - -#define table(x) func vectors[] __attribute__((section(".text.vecttable,\"a\" @"))) = { x[IRQ_UNUSED_OFFSET] = null }; - -#define vec(name) name ## _handler, -#define irq(num) [num < CONFIG_IRQ_COUNT ? num + IRQ_OFFSET : IRQ_UNUSED_OFFSET] = vec(irq_ ## num) - -#define item(name) name, -#define null (void *)0, -#endif /* PASS 2 */ - -table( - item(stack_end) - item(reset) - vec(nmi) - vec(hard_fault) - vec(mpu_fault) - vec(bus_fault) - vec(usage_fault) - null - null - null - null - vec(svc) - vec(debug) - null - vec(pendsv) - vec(sys_tick) - irq(0) - irq(1) - irq(2) - irq(3) - irq(4) - irq(5) - irq(6) - irq(7) - irq(8) - irq(9) - irq(10) - irq(11) - irq(12) - irq(13) - irq(14) - irq(15) - irq(16) - irq(17) - irq(18) - irq(19) - irq(20) - irq(21) - irq(22) - irq(23) - irq(24) - irq(25) - irq(26) - irq(27) - irq(28) - irq(29) - irq(30) - irq(31) -) - -#if PASS == 1 -#undef PASS -#define PASS 2 -#include "vecttable.c" -#endif diff --git a/core/cortex-m0/watchdog.c b/core/cortex-m0/watchdog.c deleted file mode 100644 index 9961922ee5..0000000000 --- a/core/cortex-m0/watchdog.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Watchdog common code */ - -#include "common.h" -#include "panic.h" -#include "task.h" -#include "timer.h" -#include "watchdog.h" - -/* - * As defined by Armv7-M Reference Manual B1.5.6 "Exception Entry Behavior", - * the structure of the saved context on the stack is: - * r0, r1, r2, r3, r12, lr, pc, psr, ... - */ -#define STACK_IDX_REG_LR 5 -#define STACK_IDX_REG_PC 6 - -void watchdog_trace(uint32_t excep_lr, uint32_t excep_sp) -{ - uint32_t psp; - uint32_t *stack; - - asm("mrs %0, psp" : "=r"(psp)); - if ((excep_lr & 0xf) == 1) { - /* we were already in exception context */ - stack = (uint32_t *)excep_sp; - } else { - /* we were in task context */ - stack = (uint32_t *)psp; - } - - /* Log PC. If we were in task context, log task id too. */ -#ifdef CONFIG_SOFTWARE_PANIC - panic_set_reason(PANIC_SW_WATCHDOG, stack[STACK_IDX_REG_PC], - (excep_lr & 0xf) == 1 ? 0xff : task_get_current()); -#endif - - panic_printf("### WATCHDOG PC=%08x / LR=%08x / pSP=%08x ", - stack[STACK_IDX_REG_PC], stack[STACK_IDX_REG_LR], psp); - if ((excep_lr & 0xf) == 1) - panic_puts("(exc) ###\n"); - else - panic_printf("(task %d) ###\n", task_get_current()); - - /* If we are blocked in a high priority IT handler, the following debug - * messages might not appear but they are useless in that situation. */ - timer_print_info(); - task_print_list(); -} diff --git a/core/host/atomic.h b/core/host/atomic.h deleted file mode 100644 index 83786de904..0000000000 --- a/core/host/atomic.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Atomic operations for emulator */ - -#ifndef __CROS_EC_ATOMIC_H -#define __CROS_EC_ATOMIC_H - -#include "common.h" - -typedef int atomic_t; -typedef atomic_t atomic_val_t; - -static inline atomic_val_t atomic_clear_bits(atomic_t *addr, atomic_val_t bits) -{ - return __atomic_fetch_and(addr, ~bits, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_or(atomic_t *addr, atomic_val_t bits) -{ - return __atomic_fetch_or(addr, bits, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_add(atomic_t *addr, atomic_val_t value) -{ - return __atomic_fetch_add(addr, value, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_sub(atomic_t *addr, atomic_val_t value) -{ - return __atomic_fetch_sub(addr, value, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_clear(atomic_t *addr) -{ - return __atomic_exchange_n(addr, 0, __ATOMIC_SEQ_CST); -} -#endif /* __CROS_EC_ATOMIC_H */ diff --git a/core/host/build.mk b/core/host/build.mk deleted file mode 100644 index 503aa5538a..0000000000 --- a/core/host/build.mk +++ /dev/null @@ -1,11 +0,0 @@ -# -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# emulator specific files build -# - -CFLAGS_CPU=-fno-builtin - -core-y=main.o task.o timer.o panic.o disabled.o stack_trace.o diff --git a/core/host/cpu.h b/core/host/cpu.h deleted file mode 100644 index d990e06afa..0000000000 --- a/core/host/cpu.h +++ /dev/null @@ -1,13 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* CPU specific header file */ - -#ifndef __CROS_EC_CPU_H -#define __CROS_EC_CPU_H - -static inline void cpu_init(void) { } - -#endif /* __CROS_EC_CPU_H */ diff --git a/core/host/disabled.c b/core/host/disabled.c deleted file mode 100644 index 759c215ebd..0000000000 --- a/core/host/disabled.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Disabled functions */ - -#define DISABLED(proto) proto { } - -DISABLED(void clock_init(void)); diff --git a/core/host/host_exe.lds b/core/host/host_exe.lds deleted file mode 100644 index ab8d352ecc..0000000000 --- a/core/host/host_exe.lds +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -SECTIONS { - .rodata.ec_sections : { - /* Symbols defined here are declared in link_defs.h */ - __irqprio = .; - *(.rodata.irqprio) - __irqprio_end = .; - - . = ALIGN(8); - __cmds = .; - *(SORT(.rodata.cmds*)) - __cmds_end = .; - - . = ALIGN(8); - __hcmds = .; - *(SORT(.rodata.hcmds*)) - __hcmds_end = .; - - . = ALIGN(4); - __mkbp_evt_srcs = .; - KEEP(*(.rodata.evtsrcs)) - __mkbp_evt_srcs_end = .; - - . = ALIGN(8); - __hooks_init = .; - *(.rodata.HOOK_INIT) - __hooks_init_end = .; - - __hooks_pre_freq_change = .; - *(.rodata.HOOK_PRE_FREQ_CHANGE) - __hooks_pre_freq_change_end = .; - - __hooks_freq_change = .; - *(.rodata.HOOK_FREQ_CHANGE) - __hooks_freq_change_end = .; - - __hooks_sysjump = .; - *(.rodata.HOOK_SYSJUMP) - __hooks_sysjump_end = .; - - __hooks_chipset_pre_init = .; - *(.rodata.HOOK_CHIPSET_PRE_INIT) - __hooks_chipset_pre_init_end = .; - - __hooks_chipset_startup = .; - *(.rodata.HOOK_CHIPSET_STARTUP) - __hooks_chipset_startup_end = .; - - __hooks_chipset_resume = .; - *(.rodata.HOOK_CHIPSET_RESUME) - __hooks_chipset_resume_end = .; - - __hooks_chipset_suspend = .; - *(.rodata.HOOK_CHIPSET_SUSPEND) - __hooks_chipset_suspend_end = .; - - __hooks_chipset_shutdown = .; - *(.rodata.HOOK_CHIPSET_SHUTDOWN) - __hooks_chipset_shutdown_end = .; - - __hooks_chipset_shutdown_complete = .; - *(.rodata.HOOK_CHIPSET_SHUTDOWN_COMPLETE) - __hooks_chipset_shutdown_complete_end = .; - - __hooks_chipset_hard_off = .; - KEEP(*(.rodata.HOOK_CHIPSET_HARD_OFF)) - __hooks_chipset_hard_off_end = .; - - __hooks_chipset_reset = .; - *(.rodata.HOOK_CHIPSET_RESET) - __hooks_chipset_reset_end = .; - - __hooks_ac_change = .; - *(.rodata.HOOK_AC_CHANGE) - __hooks_ac_change_end = .; - - __hooks_lid_change = .; - *(.rodata.HOOK_LID_CHANGE) - __hooks_lid_change_end = .; - - __hooks_tablet_mode_change = .; - KEEP(*(.rodata.HOOK_TABLET_MODE_CHANGE)) - __hooks_tablet_mode_change_end = .; - - __hooks_base_attached_change = .; - KEEP(*(.rodata.HOOK_BASE_ATTACHED_CHANGE)) - __hooks_base_attached_change_end = .; - - __hooks_pwrbtn_change = .; - *(.rodata.HOOK_POWER_BUTTON_CHANGE) - __hooks_pwrbtn_change_end = .; - - __hooks_battery_soc_change = .; - *(.rodata.HOOK_BATTERY_SOC_CHANGE) - __hooks_battery_soc_change_end = .; - - __hooks_tick = .; - *(.rodata.HOOK_TICK) - __hooks_tick_end = .; - - __hooks_second = .; - *(.rodata.HOOK_SECOND) - __hooks_second_end = .; - - __hooks_usb_pd_disconnect = .; - *(.rodata.HOOK_USB_PD_DISCONNECT) - __hooks_usb_pd_disconnect_end = .; - - __hooks_usb_pd_connect = .; - KEEP(*(.rodata.HOOK_USB_PD_CONNECT)) - __hooks_usb_pd_connect_end = .; - - __deferred_funcs = .; - *(.rodata.deferred) - __deferred_funcs_end = .; - - __test_i2c_xfer = .; - *(.rodata.test_i2c.xfer) - __test_i2c_xfer_end = .; - } -} -INSERT BEFORE .rodata; - -SECTIONS { - .bss.ec_sections : { - /* Symbols defined here are declared in link_defs.h */ - . = ALIGN(8); - __deferred_until = .; - . += (__deferred_funcs_end - __deferred_funcs) * (8 / 4); - __deferred_until_end = .; - } -} -INSERT BEFORE .bss; diff --git a/core/host/host_task.h b/core/host/host_task.h deleted file mode 100644 index 30cd2ff594..0000000000 --- a/core/host/host_task.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Emulator task scheduling module */ - -#ifndef __CROS_EC_HOST_TASK_H -#define __CROS_EC_HOST_TASK_H - -#include <pthread.h> - -#include "task.h" - -/** - * Returns the thread corresponding to the task. - */ -pthread_t task_get_thread(task_id_t tskid); - -/** - * Returns the ID of the active task, regardless of current thread - * context. - */ -task_id_t task_get_running(void); - -/** - * Initializes the interrupt semaphore and associates a signal handler with - * SIGNAL_INTERRUPT. - */ -void task_register_interrupt(void); - -/** - * Returns the process ID of the calling process. - */ -pid_t getpid(void); - -#endif /* __CROS_EC_HOST_TASK_H */ diff --git a/core/host/irq_handler.h b/core/host/irq_handler.h deleted file mode 100644 index f905f463c1..0000000000 --- a/core/host/irq_handler.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Helper to declare IRQ handling routines */ - -#ifndef __CROS_EC_IRQ_HANDLER_H -#define __CROS_EC_IRQ_HANDLER_H - -/* Helper macros to build the IRQ handler and priority struct names */ -#define IRQ_HANDLER(irqname) CONCAT3(irq_, irqname, _handler) -#define IRQ_PRIORITY(irqname) CONCAT2(prio_, irqname) -/* - * Macro to connect the interrupt handler "routine" to the irq number "irq" and - * ensure it is enabled in the interrupt controller with the right priority. - */ -#define DECLARE_IRQ(irq, routine, priority) \ - void routine(void); \ - void IRQ_HANDLER(irq)(void) \ - { \ - void *ret = __builtin_return_address(0); \ - task_start_irq_handler(ret); \ - routine(); \ - task_resched_if_needed(ret); \ - } \ - const struct irq_priority __keep IRQ_PRIORITY(irq) \ - __attribute__((section(".rodata.irqprio"))) \ - = {irq, priority} -#endif /* __CROS_EC_IRQ_HANDLER_H */ diff --git a/core/host/main.c b/core/host/main.c deleted file mode 100644 index ed7032eb63..0000000000 --- a/core/host/main.c +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Entry point of unit test executable */ - -#include "console.h" -#include "flash.h" -#include "hooks.h" -#include "host_task.h" -#include "keyboard_scan.h" -#include "stack_trace.h" -#include "system.h" -#include "task.h" -#include "test_util.h" -#include "timer.h" -#include "uart.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) - -const char *__prog_name; - -const char *__get_prog_name(void) -{ - return __prog_name; -} - -static int test_main(void) -{ - /* - * In order to properly service IRQs before task switching is enabled, - * we must set up our signal handler for the main thread. - */ - task_register_interrupt(); - - task_register_tracedump(); - - register_test_end_hook(); - - crec_flash_pre_init(); - system_pre_init(); - system_common_pre_init(); - - test_init(); - - timer_init(); -#ifdef HAS_TASK_KEYSCAN - keyboard_scan_init(); -#endif - uart_init(); - - if (system_jumped_to_this_image()) { - CPRINTS("Emulator initialized after sysjump"); - } else { - CPUTS("\n\n--- Emulator initialized after reboot ---\n"); - CPUTS("[Reset cause: "); - system_print_reset_flags(); - CPUTS("]\n"); - } - - task_start(); - - return 0; -} - -#ifdef TEST_FUZZ -/* - * Fuzzing tests need to start the main function in a thread, so that - * LLVMFuzzerTestOneInput can run freely. - */ -void *_main_thread(void *a) -{ - test_main(); - return NULL; -} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - static int initialized; - static pthread_t main_t; - /* - * We lose the program name as LLVM fuzzer takes over main function: - * make up one. - */ - static const char *name = STRINGIFY(PROJECT)".exe"; - - if (!initialized) { - __prog_name = name; - pthread_create(&main_t, NULL, _main_thread, NULL); - initialized = 1; - /* We can't sleep yet, busy loop waiting for tasks to start. */ - wait_for_task_started_nosleep(); - /* Let tasks settle. */ - msleep(50 * MSEC); - } - - return test_fuzz_one_input(data, size); -} -#else -int main(int argc, char **argv) -{ - __prog_name = argv[0]; - return test_main(); -} -#endif diff --git a/core/host/panic.c b/core/host/panic.c deleted file mode 100644 index 7b0829989d..0000000000 --- a/core/host/panic.c +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <stdio.h> -#include <stdlib.h> - -#include "stack_trace.h" - -void panic_assert_fail(const char *msg, const char *func, const char *fname, - int linenum) -{ - fprintf(stderr, "ASSERTION FAIL: %s:%d:%s - %s\n", - fname, linenum, func, msg); - task_dump_trace(); - - puts("Fail!"); /* Inform test runner */ - fflush(stdout); - - exit(1); -} diff --git a/core/host/stack_trace.c b/core/host/stack_trace.c deleted file mode 100644 index adef66dd44..0000000000 --- a/core/host/stack_trace.c +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <execinfo.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> - -#include "host_task.h" -#include "host_test.h" -#include "timer.h" - -#define SIGNAL_TRACE_DUMP SIGTERM -#define MAX_TRACE 30 -/* - * When trace dump is requested from signal handler, skip: - * _task_dump_trace_impl - * _task_dump_trace_dispath - * A function in libc - */ -#define SIGNAL_TRACE_OFFSET 3 -/* - * When trace dump is requested from task_dump_trace(), skip: - * task_dump_trace - * _task_dump_trace_impl - */ -#define DIRECT_TRACE_OFFSET 2 - -static pthread_t main_thread; - -static void __attribute__((noinline)) _task_dump_trace_impl(int offset) -{ - void *trace[MAX_TRACE]; - size_t sz; - char **messages; - char buf[256]; - FILE *file; - int i, nb; - - sz = backtrace(trace, MAX_TRACE); - messages = backtrace_symbols(trace + offset, sz - offset); - - for (i = 0; i < sz - offset; ++i) { - fprintf(stderr, "#%-2d %s\n", i, messages[i]); - /* %p is correct (as opposed to %pP) since this is the host */ - sprintf(buf, "addr2line %p -e %s", - trace[i + offset], __get_prog_name()); - file = popen(buf, "r"); - if (file) { - nb = fread(buf, 1, sizeof(buf) - 1, file); - buf[nb] = '\0'; - fprintf(stderr, " %s", buf); - pclose(file); - } - } - fflush(stderr); - free(messages); -} - -void __attribute__((noinline)) task_dump_trace(void) -{ - _task_dump_trace_impl(DIRECT_TRACE_OFFSET); -} - -static void __attribute__((noinline)) _task_dump_trace_dispatch(int sig) -{ - int need_dispatch = 1; - task_id_t running = task_get_running(); - - if (!pthread_equal(pthread_self(), main_thread)) { - need_dispatch = 0; - } else if (!task_start_called()) { - fprintf(stderr, "Stack trace of main thread:\n"); - need_dispatch = 0; - } else if (in_interrupt_context()) { - fprintf(stderr, "Stack trace of ISR:\n"); - } else { - fprintf(stderr, "Stack trace of task %d (%s):\n", - running, task_get_name(running)); - } - - if (need_dispatch) { - pthread_kill(task_get_thread(running), SIGNAL_TRACE_DUMP); - } else { - _task_dump_trace_impl(SIGNAL_TRACE_OFFSET); - exit(1); - } -} - -void task_register_tracedump(void) -{ - /* Trace dumper MUST be registered from main thread */ - main_thread = pthread_self(); - signal(SIGNAL_TRACE_DUMP, _task_dump_trace_dispatch); -} diff --git a/core/host/task.c b/core/host/task.c deleted file mode 100644 index be7ed3c579..0000000000 --- a/core/host/task.c +++ /dev/null @@ -1,564 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Task scheduling / events module for Chrome EC operating system */ - -#include <malloc.h> -#include <pthread.h> -#include <semaphore.h> -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "atomic.h" -#include "common.h" -#include "console.h" -#include "host_task.h" -#include "task.h" -#include "task_id.h" -#include "test_util.h" -#include "timer.h" - -#define SIGNAL_INTERRUPT SIGUSR1 - -struct emu_task_t { - pthread_t thread; - pthread_cond_t resume; - uint32_t event; - timestamp_t wake_time; - uint8_t started; -}; - -struct task_args { - void (*routine)(void *); - void *d; -}; - -static struct emu_task_t tasks[TASK_ID_COUNT]; -static pthread_cond_t scheduler_cond; -static pthread_mutex_t run_lock; -static task_id_t running_task_id; -static int task_started; - -static sem_t interrupt_sem; -static pthread_mutex_t interrupt_lock; -static pthread_t interrupt_thread; -static int in_interrupt; -static int interrupt_disabled; -static void (*pending_isr)(void); -static int generator_sleeping; -static timestamp_t generator_sleep_deadline; -static int has_interrupt_generator = 1; - -/* thread local task id */ -static __thread task_id_t my_task_id = TASK_ID_INVALID; - -static void task_enable_all_tasks_callback(void); - -#define TASK(n, r, d, s) void r(void *); -CONFIG_TASK_LIST -CONFIG_TEST_TASK_LIST -CONFIG_CTS_TASK_LIST -#undef TASK - -/* usleep that uses OS functions, instead of emulated timer. */ -void _usleep(int usec) -{ - struct timespec req; - - req.tv_sec = usec / 1000000; - req.tv_nsec = (usec % 1000000) * 1000; - - nanosleep(&req, NULL); -} - -/* msleep that uses OS functions, instead of emulated timer. */ -void _msleep(int msec) -{ - _usleep(1000 * msec); -} - -/* Idle task */ -void __idle(void *d) -{ - while (1) - task_wait_event(-1); -} - -void _run_test(void *d) -{ - run_test(0, NULL); -} - -#define TASK(n, r, d, s) {r, d}, -const struct task_args task_info[TASK_ID_COUNT] = { - {__idle, NULL}, - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST - {_run_test, NULL}, -}; -#undef TASK - -#define TASK(n, r, d, s) #n, -static const char * const task_names[] = { - "<< idle >>", - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST - "<< test runner >>", -}; -#undef TASK - -void task_pre_init(void) -{ - /* Nothing */ -} - -int in_interrupt_context(void) -{ - return !!in_interrupt; -} - -test_mockable void interrupt_disable(void) -{ - pthread_mutex_lock(&interrupt_lock); - interrupt_disabled = 1; - pthread_mutex_unlock(&interrupt_lock); -} - -test_mockable void interrupt_enable(void) -{ - pthread_mutex_lock(&interrupt_lock); - interrupt_disabled = 0; - pthread_mutex_unlock(&interrupt_lock); -} - -inline int is_interrupt_enabled(void) -{ - return !interrupt_disabled; -} - -static void _task_execute_isr(int sig) -{ - in_interrupt = 1; - pending_isr(); - sem_post(&interrupt_sem); - in_interrupt = 0; -} - -void task_register_interrupt(void) -{ - sem_init(&interrupt_sem, 0, 0); - signal(SIGNAL_INTERRUPT, _task_execute_isr); -} - -void task_trigger_test_interrupt(void (*isr)(void)) -{ - pid_t main_pid; - pthread_mutex_lock(&interrupt_lock); - if (interrupt_disabled) { - pthread_mutex_unlock(&interrupt_lock); - return; - } - - /* Suspend current task and excute ISR */ - pending_isr = isr; - if (task_started) { - pthread_kill(tasks[running_task_id].thread, SIGNAL_INTERRUPT); - } else { - main_pid = getpid(); - kill(main_pid, SIGNAL_INTERRUPT); - } - - /* Wait for ISR to complete */ - sem_wait(&interrupt_sem); - while (in_interrupt) - _usleep(10); - pending_isr = NULL; - - pthread_mutex_unlock(&interrupt_lock); -} - -void interrupt_generator_udelay(unsigned us) -{ - generator_sleep_deadline.val = get_time().val + us; - generator_sleeping = 1; - while (get_time().val < generator_sleep_deadline.val) - ; - generator_sleeping = 0; -} - -const char *task_get_name(task_id_t tskid) -{ - return task_names[tskid]; -} - -pthread_t task_get_thread(task_id_t tskid) -{ - return tasks[tskid].thread; -} - -uint32_t task_set_event(task_id_t tskid, uint32_t event) -{ - atomic_or(&tasks[tskid].event, event); - return 0; -} - -uint32_t *task_get_event_bitmap(task_id_t tskid) -{ - return &tasks[tskid].event; -} - -uint32_t task_wait_event(int timeout_us) -{ - int tid = task_get_current(); - int ret; - pthread_mutex_lock(&interrupt_lock); - if (timeout_us > 0) - tasks[tid].wake_time.val = get_time().val + timeout_us; - - /* Transfer control to scheduler */ - pthread_cond_signal(&scheduler_cond); - pthread_cond_wait(&tasks[tid].resume, &run_lock); - - /* Resume */ - ret = atomic_clear(&tasks[tid].event); - pthread_mutex_unlock(&interrupt_lock); - return ret; -} - -uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) -{ - uint64_t deadline = get_time().val + timeout_us; - uint32_t events = 0; - int time_remaining_us = timeout_us; - - /* Add the timer event to the mask so we can indicate a timeout */ - event_mask |= TASK_EVENT_TIMER; - - while (!(events & event_mask)) { - /* Collect events to re-post later */ - events |= task_wait_event(time_remaining_us); - - time_remaining_us = deadline - get_time().val; - if (timeout_us > 0 && time_remaining_us <= 0) { - /* Ensure we return a TIMER event if we timeout */ - events |= TASK_EVENT_TIMER; - break; - } - } - - /* Re-post any other events collected */ - if (events & ~event_mask) - atomic_or(&tasks[task_get_current()].event, - events & ~event_mask); - - return events & event_mask; -} - -void mutex_lock(struct mutex *mtx) -{ - int value = 0; - int id = 1 << task_get_current(); - - mtx->waiters |= id; - - do { - if (mtx->lock == 0) { - mtx->lock = 1; - value = 1; - } - - if (!value) - task_wait_event_mask(TASK_EVENT_MUTEX, 0); - } while (!value); - - mtx->waiters &= ~id; -} - -void mutex_unlock(struct mutex *mtx) -{ - int v; - mtx->lock = 0; - - for (v = 31; v >= 0; --v) - if ((1ul << v) & mtx->waiters) { - mtx->waiters &= ~(1ul << v); - task_set_event(v, TASK_EVENT_MUTEX); - break; - } -} - -task_id_t task_get_current(void) -{ - return my_task_id; -} - -task_id_t task_get_running(void) -{ - return running_task_id; -} - -void task_print_list(void) -{ - int i; - - ccputs("Name Events\n"); - - for (i = 0; i < TASK_ID_COUNT; i++) { - ccprintf("%4d %-16s %08x\n", i, task_names[i], tasks[i].event); - cflush(); - } -} - -int command_task_info(int argc, char **argv) -{ - task_print_list(); - - return EC_SUCCESS; -} -DECLARE_SAFE_CONSOLE_COMMAND(taskinfo, command_task_info, - NULL, - "Print task info"); - -static void _wait_for_task_started(int can_sleep) -{ - int i, ok; - - while (1) { - ok = 1; - for (i = 0; i < TASK_ID_COUNT - 1; ++i) { - if (!tasks[i].started) { - if (can_sleep) - msleep(10); - else - _msleep(10); - ok = 0; - break; - } - } - if (ok) - return; - } -} - -void wait_for_task_started(void) -{ - _wait_for_task_started(1); -} - -void wait_for_task_started_nosleep(void) -{ - _wait_for_task_started(0); -} - -static task_id_t task_get_next_wake(void) -{ - int i; - timestamp_t min_time; - int which_task = TASK_ID_INVALID; - - min_time.val = ~0ull; - - for (i = TASK_ID_COUNT - 1; i >= 0; --i) - if (min_time.val >= tasks[i].wake_time.val) { - min_time.val = tasks[i].wake_time.val; - which_task = i; - } - - return which_task; -} - -static int fast_forward(void) -{ - /* - * No task has event pending, and thus the next time we have an - * event to process must be either of: - * 1. Interrupt generator triggers an interrupt - * 2. The next wake alarm is reached - * So we should check whether an interrupt may happen, and fast - * forward to the nearest among: - * 1. When interrupt generator wakes up - * 2. When the next task wakes up - */ - int task_id = task_get_next_wake(); - - if (!has_interrupt_generator) { - if (task_id == TASK_ID_INVALID) { - return TASK_ID_IDLE; - } else { - force_time(tasks[task_id].wake_time); - return task_id; - } - } - - if (!generator_sleeping) - return TASK_ID_IDLE; - - if (task_id != TASK_ID_INVALID && - tasks[task_id].thread != (pthread_t)NULL && - tasks[task_id].wake_time.val < generator_sleep_deadline.val) { - force_time(tasks[task_id].wake_time); - return task_id; - } else { - force_time(generator_sleep_deadline); - return TASK_ID_IDLE; - } -} - -int task_start_called(void) -{ - return task_started; -} - -void task_scheduler(void) -{ - int i; - timestamp_t now; - - task_started = 1; - - while (1) { - now = get_time(); - i = TASK_ID_COUNT - 1; - while (i >= 0) { - /* - * Only tasks with spawned threads are valid to be - * resumed. - */ - if (tasks[i].thread) { - if (tasks[i].event || - now.val >= tasks[i].wake_time.val) - break; - } - --i; - } - if (i < 0) - i = fast_forward(); - - now = get_time(); - if (now.val >= tasks[i].wake_time.val) - tasks[i].event |= TASK_EVENT_TIMER; - tasks[i].wake_time.val = ~0ull; - running_task_id = i; - tasks[i].started = 1; - pthread_cond_signal(&tasks[i].resume); - pthread_cond_wait(&scheduler_cond, &run_lock); - } -} - -void *_task_start_impl(void *a) -{ - long tid = (long)a; - const struct task_args *arg = task_info + tid; - my_task_id = tid; - pthread_mutex_lock(&run_lock); - - /* Wait for scheduler */ - task_wait_event(1); - tasks[tid].event = 0; - - /* Start the task routine */ - (arg->routine)(arg->d); - - /* Catch exited routine */ - while (1) - task_wait_event(-1); -} - -test_mockable void interrupt_generator(void) -{ - has_interrupt_generator = 0; -} - -void *_task_int_generator_start(void *d) -{ - my_task_id = TASK_ID_INT_GEN; - interrupt_generator(); - return NULL; -} - -int task_start(void) -{ - int i = TASK_ID_HOOKS; - - pthread_mutex_init(&run_lock, NULL); - pthread_mutex_init(&interrupt_lock, NULL); - pthread_cond_init(&scheduler_cond, NULL); - - pthread_mutex_lock(&run_lock); - - /* - * Initialize the hooks task first. After its init, it will callback to - * enable the remaining tasks. - */ - tasks[i].event = TASK_EVENT_WAKE; - tasks[i].wake_time.val = ~0ull; - tasks[i].started = 0; - pthread_cond_init(&tasks[i].resume, NULL); - pthread_create(&tasks[i].thread, NULL, _task_start_impl, - (void *)(uintptr_t)i); - pthread_cond_wait(&scheduler_cond, &run_lock); - /* - * Interrupt lock is grabbed by the task which just started. - * Let's unlock it so the next task can be started. - */ - pthread_mutex_unlock(&interrupt_lock); - - /* - * The hooks task is waiting in task_wait_event(). Lock interrupt_lock - * here so the first task chosen sees it locked. - */ - pthread_mutex_lock(&interrupt_lock); - - pthread_create(&interrupt_thread, NULL, - _task_int_generator_start, NULL); - - /* - * Tell the hooks task to continue so that it can call back to enable - * the other tasks. - */ - pthread_cond_signal(&tasks[i].resume); - pthread_cond_wait(&scheduler_cond, &run_lock); - task_enable_all_tasks_callback(); - - task_scheduler(); - - return 0; -} - -static void task_enable_all_tasks_callback(void) -{ - int i; - - /* Initialize the remaning tasks. */ - for (i = 0; i < TASK_ID_COUNT; ++i) { - if (tasks[i].thread != (pthread_t)NULL) - continue; - - tasks[i].event = TASK_EVENT_WAKE; - tasks[i].wake_time.val = ~0ull; - tasks[i].started = 0; - pthread_cond_init(&tasks[i].resume, NULL); - pthread_create(&tasks[i].thread, NULL, _task_start_impl, - (void *)(uintptr_t)i); - /* - * Interrupt lock is grabbed by the task which just started. - * Let's unlock it so the next task can be started. - */ - pthread_mutex_unlock(&interrupt_lock); - pthread_cond_wait(&scheduler_cond, &run_lock); - } - -} - -void task_enable_all_tasks(void) -{ - /* Signal to the scheduler to enable the remaining tasks. */ - pthread_cond_signal(&scheduler_cond); -} diff --git a/core/host/timer.c b/core/host/timer.c deleted file mode 100644 index 3c3695cad4..0000000000 --- a/core/host/timer.c +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Timer module */ - -#include <stdint.h> -#include <stdio.h> - -#include "task.h" -#include "test_util.h" -#include "timer.h" -#include "util.h" - -static timestamp_t boot_time; -static int time_set; - -void usleep(unsigned us) -{ - if (!task_start_called() || task_get_current() == TASK_ID_INVALID) { - udelay(us); - return; - } - - ASSERT(!in_interrupt_context() && - task_get_current() != TASK_ID_INT_GEN); - - task_wait_event(us); -} - -timestamp_t _get_time(void) -{ - static timestamp_t time; - - /* - * We just monotonically increase the microsecond every time we check - * the time. Do not depend on host system time as this introduces - * flakyness in tests. The time is periodically fast forwarded with - * force_time() during the host's task scheduler implementation. - */ - ++time.val; - return time; -} - -test_mockable timestamp_t get_time(void) -{ - timestamp_t ret = _get_time(); - ret.val -= boot_time.val; - return ret; -} - -uint32_t __hw_clock_source_read(void) -{ - return get_time().le.lo; -} - -void force_time(timestamp_t ts) -{ - timestamp_t now = _get_time(); - boot_time.val = now.val - ts.val; - time_set = 1; -} - -void udelay(unsigned us) -{ - timestamp_t deadline; - - if (!in_interrupt_context() && task_get_current() == TASK_ID_INT_GEN) { - interrupt_generator_udelay(us); - return; - } - - deadline.val = get_time().val + us; - while (get_time().val < deadline.val) - ; -} - -int timestamp_expired(timestamp_t deadline, const timestamp_t *now) -{ - timestamp_t now_val; - - if (!now) { - now_val = get_time(); - now = &now_val; - } - - return ((int64_t)(now->val - deadline.val) >= 0); -} - -void timer_init(void) -{ - - if (!time_set) { - /* - * Start the timer just before the 64-bit rollover to try - * and catch 32-bit rollover/truncation bugs. - */ - timestamp_t ts = { - .val = 0xFFFFFFF0 - }; - - force_time(ts); - } -} diff --git a/core/nds32/__builtin.c b/core/nds32/__builtin.c deleted file mode 100644 index 7b1d5eea62..0000000000 --- a/core/nds32/__builtin.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" - -/* - * __builtin_ffs: - * Returns one plus the index of the least significant 1-bit of x, - * or if x is zero, returns zero. - */ -int __keep __ffssi2(int x) -{ - return 32 - __builtin_clz(x & -x); -} diff --git a/core/nds32/__divdi3.S b/core/nds32/__divdi3.S deleted file mode 100644 index d86e8f6273..0000000000 --- a/core/nds32/__divdi3.S +++ /dev/null @@ -1,372 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * __divdi3.S: signed 64 bit division - */ - -#define NREGS $r6 -#define DREGS $r8 -#define P1H $r1 -#define P1L $r0 -#define P2H $r3 -#define P2L $r2 -#define NUMHI $r7 -#define NUMLO $r6 -#define DENHI $r9 -#define DENLO $r8 -#define OFFSET_L 0 -#define OFFSET_H 4 -#define MHI P1H -#define MLO P1L -#define W2 $r3 -#define W1 $r5 -#define W0 $r4 -#define T2 P1L -#define NHI P1H -#define NLO P1L -#define D $r2 -#define DLO $r3 -#define DHI $r10 -#define Q NHI -#define QHI W0 -#define R NLO -#define RHI NHI -#define M T2 -#define M2 DLO - - .text - .align 2 - .globl umul_ppmm - .type umul_ppmm, @function - ! ===================================================================== - ! uint64_t umul_ppmm(uint32_t a, uint32_t b) - ! - ! This function multiplies `a' by `b' to obtain a 64-bit product. The - ! product is broken into two 32-bit pieces which are stored in the zl - ! (low-part at P1L) and zh (high-part at P1H). - ! ===================================================================== -umul_ppmm: - zeh P2L, $r0 ! al=a&0xffff - srli P2H, $r0, 16 ! ah=a>>16 - zeh P1L, $r1 ! bl=b&0xffff - srli P1H, $r1, 16 ! bh=b>>16 - mul W1, P2L, P1H ! zA=al*bh - mul P2L, P2L, P1L ! zl=al*bl - mul P1L, P2H, P1L ! zB=ah*bl - add W1, W1, P1L ! zA+=zB - slt $ta, W1, P1L ! zA<zB - slli $ta, $ta, 16 ! (zA<zB)<<16 - maddr32 $ta, P2H, P1H ! zh=ah*bh+((zA<zB)<<16) - srli P1H, W1, 16 ! zA>>16 - add P1H, P1H, $ta ! zh+=(zA>>16) - slli P1L, W1, 16 ! zA<<=16 - add P1L, P1L, P2L ! zl+=zA - slt $ta, P1L, P2L ! zl<zA - add P1H, P1H, $ta ! zh+=(zl<zA) - ret - .size umul_ppmm, .-umul_ppmm - - .text - .align 2 - .type fudiv_qrnnd, @function - ! ===================================================================== - ! uint64_t fudiv_qrnnd(uint64_t n, uint32_t d) - ! - ! This function divides 64-bit numerator n by 32-bit denominator d. The - ! 64-bit return value contains remainder (low-part at P1L) and quotient - ! (high-part at P1H). - ! This function uses a custom calling convention, - ! with register DHI ($r10) call-clobbered instead of callee-saved. - ! ===================================================================== -fudiv_qrnnd: - srli DHI, D, 16 ! d1 = ll_highpart (d) - zeh W1, NLO ! ll_lowpart (n0) - srli T2, NLO, 16 ! ll_highpart (n0) - divr QHI, RHI, NHI, DHI ! q1 = n1 / __d1, r1 = n1 % __d1 - zeh DLO, D ! d0 = ll_lowpart (d) - slli RHI, RHI, 16 ! r1 << 16 - or RHI, RHI, T2 ! __r1 = (__r1 << 16) | ll_highpart(n0) - mul M, QHI, DLO ! m = __q1*__d0 - slt $ta, RHI, M ! __r1 < __m - beqz $ta, .L2 ! if no, skip - addi QHI, QHI, -1 ! __q1-- - add RHI, RHI, D ! __r1 += d - slt $ta, RHI, D ! __r1 < d - bnez $ta, .L2 ! if yes, skip - slt $ta, RHI, M ! __r1 < __m - beqz $ta, .L2 ! if no, skip - addi QHI, QHI, -1 ! __q1-- - add RHI, RHI, D ! __r1 += d -.L2: - sub RHI, RHI, M ! __r1 -= __m - divr Q, T2, RHI, DHI ! __q0 = r1 / __d1, __r0 = r1 % __d1 - slli T2, T2, 16 ! __r0 << 16 - or R, T2, W1 ! __r0 = (__r0 << 16) | ll_lowpart(n0) - mul M2, DLO, Q ! __m = __q0 * __d0 - slt $ta, R, M2 ! __r0 < __m - beqz $ta, .L5 ! if no, skip - add R, R, D ! __r0 += d - addi Q, Q, -1 ! __q0-- - slt $ta, R, D ! __r0 < d - bnez $ta, .L5 ! if yes, skip - slt $ta, R, M2 ! __r0 < __m - beqz $ta, .L5 ! if no, skip - add R, R, D ! __r0 += d - addi Q, Q, -1 ! __q0-- - -.L5: - sub R, R, M2 ! r = r0 = __r0 - __m - slli QHI, QHI, 16 ! __q1 << 16 - or Q, Q, QHI ! q = (__q1 << 16) | __q0 - ret - .size fudiv_qrnnd, .-fudiv_qrnnd - - .align 2 - .globl __udivmoddi4 - .type __udivmoddi4, @function - ! ===================================================================== - ! uint64_t __udivmoddi4(uint64_t n, uint64_t d, uint64_t *r) - ! - ! This function divides 64-bit numerator n by 64-bit denominator d. The - ! quotient is returned as 64-bit return value and the 64-bit remainder - ! is stored at the input address r. - ! stack allocation: - ! sp+40 +------------------+ - ! | q | - ! sp+32 +------------------+ - ! | bm | - ! sp+28 +------------------+ - ! | $lp | - ! sp+24 +------------------+ - ! | $fp | - ! sp+20 +------------------+ - ! | $r10 | - ! sp+16 +------------------+ - ! | $r6 - $r9 | - ! sp +------------------+ - ! ===================================================================== -__udivmoddi4: - addi $sp, $sp, -40 - smw.bi $r6, [$sp], $r10 , 10 - movd44 NREGS, $r0 ! (n1,n0) - movd44 DREGS, $r2 ! (d1,d0) - move $fp, $r4 ! rp - bnez P2H, .L9 ! if d1 != 0, skip - slt $ta, NUMHI, DENLO ! n1 < d0 - beqz $ta, .L10 ! if no, skip - move $r0, DENLO - bal __clzsi2 - swi $r0, [$sp+(28)] ! bm - beqz $r0, .LZskipnorm1 ! if bm == 0, skip - sll DENLO, DENLO, $r0 ! d0 <<= bm - subri W1, $r0, 32 ! 32 - bm - srl W1, NUMLO, W1 ! n0 >> (32 - bm) - sll NUMHI, NUMHI, $r0 ! n1 << bm - or NUMHI, NUMHI, W1 ! n1 = (n1 << bm) | (n0 >> (32 - bm)) - sll NUMLO, NUMLO, $r0 ! n0 <<= bm -.LZskipnorm1: - movd44 $r0, NREGS ! (n1,n0) - move $r2, DENLO ! d0 - bal fudiv_qrnnd ! calculate q0 n0 - swi P1H, [$sp+(32+OFFSET_L)]! q0 - move NUMLO, P1L ! n0 - move W1, 0 - swi W1, [$sp+(32+OFFSET_H)] ! q1 = 0 - b .L19 -.L10: - beqz P2L, .LZdivzero ! if d0 != 0, skip - move $r0, DENLO - bal __clzsi2 - swi $r0, [$sp+(28)] ! bm - bnez $r0, .LZnorm1 ! if bm != 0, skip - sub NUMHI, NUMHI, DENLO ! n1 -= d0 - movi W1, 1 - swi W1, [$sp+(32+OFFSET_H)] ! q1 = 1 - b .L29 - - ! to eliminate unaligned branch target - .align 2 -.LZnorm1: - subri $ta, $r0, 32 ! b = 32 - bm - sll DENLO, DENLO, $r0 ! d0 <<= bm - move $r2, DENLO - srl W0, NUMLO, $ta ! n0 >> b - sll W1, NUMHI, $r0 ! n1 << bm - sll NUMLO, NUMLO, $r0 ! n0 <<= bm - or P1L, W1, W0 ! n1 = (n1 << bm) | (n0 >> b) - srl P1H, NUMHI, $ta ! n2 = n1 >> b - bal fudiv_qrnnd ! caculate q1, n1 - swi P1H, [$sp+(32+OFFSET_H)]! q1 - move NUMHI, P1L ! n1 -.L29: - movd44 $r0, NREGS ! (n1,n0) - move $r2, DENLO ! d0 - bal fudiv_qrnnd ! calcuate q0, n0 - swi P1H, [$sp+(32+OFFSET_L)] - move NUMLO, P1L - - ! to eliminate unaligned branch target - .align 2 -.L19: - beqz $fp, .LZsetq ! if rp == 0, skip - lwi W2, [$sp+(28)] ! bm - movi NUMHI, 0 - srl NUMLO, NUMLO, W2 ! n0 >> bm - b .LZsetr - - ! to eliminate unaligned branch target - .align 2 -.LZdivzero: - ! divide-by-zero exception or quotient = 0 and remainder = 0 returned - divr NUMHI, NUMLO, DENLO, DENLO -.LZqzero: - movi P1H, 0 - movi P1L, 0 - beqz $fp, .LZret ! if rp == NULL, skip - swi NUMLO, [$fp+OFFSET_L] ! *rp - swi NUMHI, [$fp+OFFSET_H] - b .LZret -.L9: - slt $ta, NUMHI, DENHI ! n1 < d1 - bnez $ta, .LZqzero ! if yes, skip - move $r0, DENHI - bal __clzsi2 - swi $r0, [$sp+(28)] ! bm - beqz $r0, .LZskipnorm2 ! if bm == 0, skip - subri W0, $r0, 32 ! b = 32 - bm - srl W1, DENLO, W0 ! d0 >> b - sll $r2, DENHI, $r0 ! d1 << bm - or $r2, $r2, W1 ! d1 = (d0 >> b) | (d1 << bm) - move DENHI, $r2 - sll DENLO, DENLO, $r0 ! d0 <<= bm - srl W2, NUMLO, W0 ! n0 >> b - sll NUMLO, NUMLO, $r0 ! n0 <<= bm - sll P1L, NUMHI, $r0 ! n1 << bm - srl P1H, NUMHI, W0 ! n2 = n1 >> b - or P1L, P1L, W2 ! n1 = (n0 >> b) | (n1 << bm) - bal fudiv_qrnnd ! calculate q0, n1 - swi P1H, [$sp+(32+OFFSET_L)] - move NUMHI, P1L - move P1L, DENLO ! d0 - bal umul_ppmm - slt $ta, NUMHI, MHI ! n1 < m1 - bnez $ta, .L46 ! if yes, skip - bne MHI, NUMHI, .L45 ! if m1 != n1, skip - slt $ta, NUMLO, MLO ! n0 < m0 - beqz $ta, .L45 ! if no, skip -.L46: - lwi W2, [$sp+(32+OFFSET_L)] - sub MHI, MHI, DENHI ! m1 - d1 - addi W2, W2, -1 ! q0-- - swi W2, [$sp+(32+OFFSET_L)] - sub W2, MLO, DENLO ! __x = m0 - d0 - slt $ta, MLO, W2 ! m0 < __x - sub MHI, MHI, $ta ! m1 = m1 - d1 - (__x > m0) - move MLO, W2 ! m0 = __x -.L45: - movi W2, 0 - swi W2, [$sp+(32+OFFSET_H)] ! q1 = 0 - beqz $fp, .LZsetq ! if yes, skip - sub P1L, NUMLO, MLO ! __x = n0 - m0 - sub P1H, NUMHI, MHI ! n1 - m1 - slt $ta, NUMLO, P1L ! n0 < __x - sub P1H, P1H, $ta ! n1 = n1 - m1 - (__x > n0) - lwi W2, [$sp+(28)] ! bm - subri W0, W2, 32 ! b - sll NUMHI, P1H, W0 ! n1 << b - srl NUMLO, P1L, W2 ! n0 >> bm - or NUMLO, NUMLO, NUMHI ! (n1 << b) | (n0 >> bm) - srl NUMHI, P1H, W2 ! n1 >> bm -.LZsetr: - swi NUMLO, [$fp+OFFSET_L] ! remainder - swi NUMHI, [$fp+OFFSET_H] -.LZsetq: - lwi P1L, [$sp+(32+OFFSET_L)]! quotient - lwi P1H, [$sp+(32+OFFSET_H)] - - ! to eliminate unaligned branch target - .align 2 -.LZret: - lmw.bi $r6, [$sp], $r10 , 10 - addi $sp, $sp, 40 - ret - -.LZskipnorm2: - move W2, 0 - slt $ta, DENHI, NUMHI ! n1 > d1 - bnez $ta, .L52 ! if yes, skip - slt $ta, NUMLO, DENLO ! n0 < d0 - bnez $ta, .L51 ! if yes, skip -.L52: - move W1, 1 - swi W1, [$sp+(32+OFFSET_L)] ! q0 = 1 - sub W0, NUMLO, DENLO ! __x = n0 - d0 - sub NUMHI, NUMHI, DENHI ! n1 - d1 - slt $ta, NUMLO, W0 ! n0 < __x - sub NUMHI, NUMHI, $ta ! n1 = n1 -d1 - (_-x > n0) - move NUMLO, W0 ! n0 = __x - b .L54 -.L51: - swi W2, [$sp+(32+OFFSET_L)] ! q0 = 0 -.L54: - swi W2, [$sp+(32+OFFSET_H)] ! q1 = 0 - bnez $fp, .LZsetr - b .LZsetq - .size __udivmoddi4, .-__udivmoddi4 - - .text - .align 2 - .globl __divdi3 - .type __divdi3, @function -__divdi3: - ! ===================================================================== - ! uint64_t __divdi3(uint64_t n, uint64-t d) - ! - ! This function divides n by d and returns the quotient. - ! - ! stack allocation: - ! sp+8 +-----------------------+ - ! | $lp | - ! sp+4 +-----------------------+ - ! | $r6 | - ! sp +-----------------------+ - ! ===================================================================== - smw.adm $r6, [$sp], $r6, 2 - - xor $r6, P1H, P2H - srai45 $r6, 31 ! signof(numerator xor denominator) - ! abs(denominator) - bgez P2H, .L80 - neg P2H, P2H - beqz P2L, .L80 - neg P2L, P2L - addi P2H, P2H, -1 - -.L80: - ! abs(numerator) - bgez P1H, .L81 - neg P1H, P1H - beqz P1L, .L81 - neg P1L, P1L - addi P1H, P1H, -1 - -.L81: - ! abs(numerator) / abs(denominator) - movi $r4, 0 ! ignore remainder - bal __udivmoddi4 - ! numerator / denominator - beqz $r6, .L82 - or $r4, P1H, P1L - beqz $r4, .L82 - neg P1H, P1H - beqz P1L, .L82 - neg P1L, P1L - addi P1H, P1H, -1 - - ! to eliminate unaligned branch target - .align 2 -.L82: - lmw.bim $r6, [$sp], $r6, 2 - ret - .size __divdi3, .-__divdi3 diff --git a/core/nds32/__libsoftfpu.S b/core/nds32/__libsoftfpu.S deleted file mode 100644 index 672e6bbb3d..0000000000 --- a/core/nds32/__libsoftfpu.S +++ /dev/null @@ -1,195 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - .text - .align 2 - .global __gtsf2 - .type __gtsf2, @function -__gtsf2: - ! --------------------------------------------------------------------- - ! int __gtsf2(float a, float b): - ! This function returns a value greater than zero if neither argument - ! is NaN and a is strictly greater than b. - ! --------------------------------------------------------------------- - .global __gesf2 - .type __gesf2, @function -__gesf2: - ! --------------------------------------------------------------------- - ! int __gesf2(float a, float b): - ! This function returns a value greater than or equal to zero if - ! neither argument is NaN and a is greater than or equal to b. - ! --------------------------------------------------------------------- - move $r4, #-1 - b .LA - - .global __eqsf2 - .type __eqsf2, @function -__eqsf2: - ! --------------------------------------------------------------------- - ! int __eqsf2(float a, float b): - ! This function returns zero value if neither argument is NaN, - ! and a and b are equal. - ! --------------------------------------------------------------------- - .global __nesf2 - .type __nesf2, @function -__nesf2: - ! --------------------------------------------------------------------- - ! int __nesf2(float a, float b): - ! This function returns a nonzero value if either argument is NaN or if - ! a and b are unequal. - ! --------------------------------------------------------------------- - .global __lesf2 - .type __lesf2, @function -__lesf2: - ! --------------------------------------------------------------------- - ! int __lesf2(float a, float b): - ! This function returns a value less than or equal to zero if neither - ! argument is NaN and a is less than b. - ! --------------------------------------------------------------------- - .global __ltsf2 - .type __ltsf2, @function -__ltsf2: - ! --------------------------------------------------------------------- - ! int __ltsf2(float a, float b): - ! This function returns a value less than zero if neither argument is - ! NaN and a is strictly less than b. - ! --------------------------------------------------------------------- - .global __cmpsf2 - .type __cmpsf2, @function -__cmpsf2: - ! --------------------------------------------------------------------- - ! int __cmpsf2(float a, float b); - ! This function calculates a <=> b. That is, if a is less than b, it - ! returns -1; if a if greater than b, it returns 1; and if a and b are - ! equal, it returns 0. If either argument is NaN, it returns 1, But you - ! should not rely on this; If NaN is a possibility, use higher-level - ! comparison function __unordsf2(). - ! --------------------------------------------------------------------- - move $r4, #1 - - .align 2 -.LA: - move $r5, #0xff000000 - slli $r2, $r0, #1 - slt $r15, $r5, $r2 - bnez $r15, .LMnan ! a is NaN - slli $r3, $r1, #1 - slt $r15, $r5, $r3 - bnez $r15, .LMnan ! b is NaN - xor $r5, $r0, $r1 ! a and b have same sign? - bgez $r5, .LSameSign -.LDiffSign: - or $r2, $r2, $r3 - beqz $r2, .LMequ ! 0.0f and -0.0f are equal - move $r2, #1 ! when a==0.0f, return 1 - cmovz $r0, $r2, $r0 ! otherwise, simply return a - ret5 $lp -.LSameSign: - sltsi $r15, $r0, 0 ! a < 0 ? - bnez $r15, .LSameSignNeg -.LSameSignPos: - ! a >= 0 && b >= 0, return a - b - sub $r0, $r0, $r1 - ret5 $lp -.LSameSignNeg: - ! a < 0 && b < 0, return b - a - sub $r0, $r1, $r0 - ret5 $lp -.LMequ: - move $r0, #0 - ret5 $lp -.LMnan: - move $r0, $r4 - ret5 $lp - .size __cmpsf2, .-__cmpsf2 - .size __ltsf2, .-__ltsf2 - .size __lesf2, .-__lesf2 - .size __nesf2, .-__nesf2 - .size __eqsf2, .-__eqsf2 - .size __gesf2, .-__gesf2 - .size __gtsf2, .-__gtsf2 - -#define MANTA $r0 -#define EXPOA $r1 - .text - .align 2 - .global __floatsisf - .type __floatsisf, @function -__floatsisf: - beqz $r0, .LKzero ! A is zero - move $r4, #0x80000000 - and $r2, $r0, $r4 ! sign(A) - beqz $r2, .LKcont - subri $r0, $r0, #0 - ! abs(A) -.LKcont: - move EXPOA, #0x9e - move $r5, 16 - move $r3, 0 -.LKloop: - add $r3, $r3, $r5 - srl $r15, MANTA, $r3 - bnez $r15, .LKloop2 - sll MANTA, MANTA, $r5 - sub EXPOA, EXPOA, $r5 -.LKloop2: - srli $r5, $r5, #1 - bnez $r5, .LKloop - ! do rounding - srli $r4, $r4, #24 ! 0x80 - add MANTA, MANTA, $r4 - slt $r15, MANTA, $r4 - add EXPOA, EXPOA, $r15 - srai $r4, MANTA, #8 - andi $r4, $r4, #1 - sub MANTA, MANTA, $r4 - slli MANTA, MANTA, #1 ! shift out implied 1 - ! pack - srli MANTA, MANTA, #9 - slli $r4, EXPOA, #23 - or $r0, MANTA, $r4 - or $r0, $r0, $r2 -.LKzero: - ret5 $lp - .size __floatsisf, .-__floatsisf - -#undef EXPOA -#undef MANTA -#define VALUA $r1 -#define EXPOA VALUA -#define MANTA $r2 -#define W0 $r4 -#define W1 $r5 - .text - .align 2 - .global __fixsfsi - .type __fixsfsi, @function -__fixsfsi: - slli VALUA, $r0, #1 - slli MANTA, VALUA, #7 - srli EXPOA, VALUA, #24 - subri EXPOA, EXPOA, #0x9e - move W1, #0x80000000 - blez EXPOA, .LJover ! number is too big - sltsi $r15, EXPOA, #0x20 - beqz $r15, .LJzero ! number is too small - or MANTA, MANTA, W1 - srl MANTA, MANTA, EXPOA - sltsi $r15, $r0, #0 - subri $r0, MANTA, #0 - cmovz $r0, MANTA, $r15 - ret5 $lp -.LJzero: - move $r0, #0 - ret5 $lp -.LJover: - move W0, #0x7f800000 - slt $r15, W0, $r0 - beqzs8 .LJnan - move $r0, W1 - ret5 $lp -.LJnan: - addi $r0, W1, -1 - ret5 $lp - .size __fixsfsi, .-__fixsfsi diff --git a/core/nds32/__muldi3.S b/core/nds32/__muldi3.S deleted file mode 100644 index ef4a491183..0000000000 --- a/core/nds32/__muldi3.S +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * __muldi3.S: signed 64 bit multiplication - */ - -#define P1H $r1 -#define P1L $r0 -#define P2H $r3 -#define P2L $r2 - - .text - .align 2 - .globl __muldi3 - .type __muldi3, @function -__muldi3: - mul $r5, P1H, P2L ! (ah=a>>31)*(bl=b&0xffffffff) - srli P1H, P1L, 16 ! alh=al>>16 - maddr32 $r5, P1L, P2H ! ah*bl+(bh=b>>31)*(al=a&0xffffffff) - zeh P1L, P1L ! all=al&0xffff - srli P2H, P2L, 16 ! blh=bl>>16 - zeh P2L, P2L ! bll=bl&0xffff - - mul $ta, P1L, P2H ! zA=all*blh - mul $r4, P1L, P2L ! zl=all*bll - mul P2L, P1H, P2L ! zB=alh*bll - add P1L, $ta, P2L ! zA+=zB - slt $ta, P1L, P2L ! zA<zB - slli $ta, $ta, 16 ! (zA<zB)<<16 - slli P2L, P1L, 16 ! zA<<16 - maddr32 $ta, P1H, P2H ! zh=alh*blh+((zA<zB)<<16) - srli P1H, P1L, 16 ! zA>>16 - add P1H, P1H, $ta ! zh+=(zA>>16) - add P1L, $r4, P2L ! zl+=(zA<<16) - slt $ta, P1L, $r4 ! zl<zA - add P1H, P1H, $ta ! zh+=(zl<zA) - add P1H, P1H, $r5 ! zh+=ah*bl+bh*al - ret - .size __muldi3, .-__muldi3 diff --git a/core/nds32/__udivdi3.S b/core/nds32/__udivdi3.S deleted file mode 100644 index 4cb3b058fe..0000000000 --- a/core/nds32/__udivdi3.S +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * __udivdi3.S: unsigned 64 bit division - */ - - .text - .align 2 - .globl __udivdi3 - .type __udivdi3, @function -__udivdi3: - movi $r4, 0 ! ignore remainder - b __udivmoddi4 - .size __udivdi3, .-__udivdi3 diff --git a/core/nds32/atomic.h b/core/nds32/atomic.h deleted file mode 100644 index b634c3a551..0000000000 --- a/core/nds32/atomic.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Atomic operations for Andes */ - -#ifndef __CROS_EC_ATOMIC_H -#define __CROS_EC_ATOMIC_H - -#include "common.h" -#include "cpu.h" -#include "task.h" - -typedef int atomic_t; -typedef atomic_t atomic_val_t; - -static inline atomic_val_t atomic_clear_bits(atomic_t *addr, atomic_val_t bits) -{ - atomic_val_t ret; - atomic_t volatile *ptr = addr; - uint32_t int_mask = read_clear_int_mask(); - - ret = *ptr; - *ptr &= ~bits; - set_int_mask(int_mask); - return ret; -} - -static inline atomic_val_t atomic_or(atomic_t *addr, atomic_val_t bits) -{ - atomic_val_t ret; - atomic_t volatile *ptr = addr; - uint32_t int_mask = read_clear_int_mask(); - - ret = *ptr; - *ptr |= bits; - set_int_mask(int_mask); - return ret; -} - -static inline atomic_val_t atomic_add(atomic_t *addr, atomic_val_t value) -{ - atomic_val_t ret; - atomic_t volatile *ptr = addr; - uint32_t int_mask = read_clear_int_mask(); - - ret = *ptr; - *ptr += value; - set_int_mask(int_mask); - return ret; -} - -static inline atomic_val_t atomic_sub(atomic_t *addr, atomic_val_t value) -{ - atomic_val_t ret; - atomic_t volatile *ptr = addr; - uint32_t int_mask = read_clear_int_mask(); - - ret = *ptr; - *ptr -= value; - set_int_mask(int_mask); - return ret; -} - -static inline atomic_val_t atomic_clear(atomic_t *addr) -{ - atomic_val_t ret; - atomic_t volatile *ptr = addr; - uint32_t int_mask = read_clear_int_mask(); - - ret = *ptr; - *ptr = 0; - set_int_mask(int_mask); - return ret; -} - -#endif /* __CROS_EC_ATOMIC_H */ diff --git a/core/nds32/build.mk b/core/nds32/build.mk deleted file mode 100644 index ddd65c680b..0000000000 --- a/core/nds32/build.mk +++ /dev/null @@ -1,26 +0,0 @@ -# -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Andestar v3m architecture core OS files build -# - -# Set coreboot-sdk as the default toolchain for nds32 -NDS32_DEFAULT_COMPILE=/opt/coreboot-sdk/bin/nds32le-elf- - -# Select Andes bare-metal toolchain -$(call set-option,CROSS_COMPILE,$(CROSS_COMPILE_nds32),$(NDS32_DEFAULT_COMPILE)) - -# CPU specific compilation flags -CFLAGS_CPU+=-march=v3m -Os -LDFLAGS_EXTRA+=-mrelax - -ifneq ($(CONFIG_LTO),) -CFLAGS_CPU+=-flto -LDFLAGS_EXTRA+=-flto -endif - -core-y=cpu.o init.o panic.o task.o switch.o __muldi3.o math.o __builtin.o -core-y+=__divdi3.o __udivdi3.o -core-$(CONFIG_FPU)+=__libsoftfpu.o diff --git a/core/nds32/config_core.h b/core/nds32/config_core.h deleted file mode 100644 index 7670e5cfad..0000000000 --- a/core/nds32/config_core.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_CONFIG_CORE_H -#define __CROS_EC_CONFIG_CORE_H - -/* Linker binary architecture and format */ -#define BFD_ARCH nds32 -#define BFD_FORMAT "elf32-nds32le" - -#define CONFIG_SOFTWARE_PANIC - -/* - * The Andestar v3m architecture has no CLZ/CTZ instructions (contrary to v3), - * so let's use the software implementation. - */ -#define CONFIG_SOFTWARE_CLZ -#define CONFIG_SOFTWARE_CTZ - -#endif /* __CROS_EC_CONFIG_CORE_H */ diff --git a/core/nds32/cpu.c b/core/nds32/cpu.c deleted file mode 100644 index 6a3f3b5bc4..0000000000 --- a/core/nds32/cpu.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Set up the N8 core - */ - -#include "cpu.h" -#include "registers.h" - -void cpu_init(void) -{ - /* DLM initialization is done in init.S */ - /* Global interrupt enable */ - asm volatile ("setgie.e"); -} diff --git a/core/nds32/cpu.h b/core/nds32/cpu.h deleted file mode 100644 index 3bd5a93efc..0000000000 --- a/core/nds32/cpu.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Registers map and definitions for Andes cores - */ - -#ifndef __CROS_EC_CPU_H -#define __CROS_EC_CPU_H - -/* - * This is the space required by both irq_x_ and __switch_task to store all - * of the caller and callee registers for each task context before switching. - */ -#define TASK_SCRATCHPAD_SIZE (18) - -/* Process Status Word bits */ -#define PSW_GIE BIT(0) /* Global Interrupt Enable */ -#define PSW_INTL_SHIFT 1 /* Interrupt Stack Level */ -#define PSW_INTL_MASK (0x3 << PSW_INTL_SHIFT) - -#ifndef __ASSEMBLER__ - -#include <stdint.h> - -/* write Process Status Word privileged register */ -static inline void set_psw(uint32_t val) -{ - asm volatile ("mtsr %0, $PSW" : : "r"(val)); -} - -/* read Process Status Word privileged register */ -static inline uint32_t get_psw(void) -{ - uint32_t ret; - asm volatile ("mfsr %0, $PSW" : "=r"(ret)); - return ret; -} - -/* write Interruption Program Counter privileged register */ -static inline void set_ipc(uint32_t val) -{ - asm volatile ("mtsr %0, $IPC" : : "r"(val)); -} - -/* read Interruption Program Counter privileged register */ -static inline uint32_t get_ipc(void) -{ - uint32_t ret; - asm volatile ("mfsr %0, $IPC" : "=r"(ret)); - return ret; -} - -/* read Interruption Type privileged register */ -static inline uint32_t get_itype(void) -{ - uint32_t ret; - asm volatile ("mfsr %0, $ITYPE" : "=r"(ret)); - return ret; -} - -/* Generic CPU core initialization */ -void cpu_init(void); - -extern uint32_t ilp; -extern uint32_t ec_reset_lp; - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_CPU_H */ diff --git a/core/nds32/ec.lds.S b/core/nds32/ec.lds.S deleted file mode 100644 index 2c21b94761..0000000000 --- a/core/nds32/ec.lds.S +++ /dev/null @@ -1,321 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "config.h" - -#define STRINGIFY0(name) #name -#define STRINGIFY(name) STRINGIFY0(name) - -#define FW_OFF_(section) CONFIG_##section##_MEM_OFF -#define FW_OFF(section) (CONFIG_PROGRAM_MEMORY_BASE + FW_OFF_(section)) - -#define FW_SIZE_(section) CONFIG_##section##_SIZE -#define FW_SIZE(section) FW_SIZE_(section) - - -OUTPUT_FORMAT(BFD_FORMAT, BFD_FORMAT, BFD_FORMAT) -OUTPUT_ARCH(BFD_ARCH) -ENTRY(reset) - -MEMORY -{ - FLASH (rx) : ORIGIN = FW_OFF(SECTION), LENGTH = FW_SIZE(SECTION) - IRAM (rw) : ORIGIN = CONFIG_RAM_BASE, LENGTH = CONFIG_RAM_SIZE -#if defined(CONFIG_HOSTCMD_X86) || defined(CONFIG_I2C_PERIPHERAL) - H2RAM (rw) : ORIGIN = CONFIG_H2RAM_BASE, LENGTH = CONFIG_H2RAM_SIZE -#endif -} - -SECTIONS -{ - .text : { - /* - * We put "__flash_dma_start" at the beginning of - * the text section to avoid gap. - */ - __flash_dma_start = .; - ASSERT((__flash_dma_start == 0), - "__flash_dma_start has to be 4k-byte aligned"); - KEEP(STRINGIFY(OUTDIR/core/CORE/init.o) (.text.vecttable)) - . = ALIGN(4); - __image_data_offset = .; - KEEP(*(.rodata.ver)) - . = ALIGN(4); - KEEP(STRINGIFY(OUTDIR/core/CORE/init.o) (.text.vectirq)) - KEEP(STRINGIFY(OUTDIR/core/CORE/init.o) (.text)) - KEEP(*(.flash_direct_map)) - . = ALIGN(16); - KEEP(*(.ram_code)) - __flash_dma_size = . - __flash_dma_start; - ASSERT((__flash_dma_size < IT83XX_ILM_BLOCK_SIZE), - "__flash_dma_size < IT83XX_ILM_BLOCK_SIZE"); - . = ALIGN(IT83XX_ILM_BLOCK_SIZE); - __flash_text_start = .; - *(.text*) - } > FLASH - . = ALIGN(4); - .rodata : { - /* Symbols defined here are declared in link_defs.h */ - __irqprio = .; - KEEP(*(.rodata.irqprio)) - __irqprio_end = .; - - . = ALIGN(4); - __irqhandler = .; - KEEP(STRINGIFY(OUTDIR/core/CORE/init.o) (.rodata.vecthandlers)) - - . = ALIGN(4); - __cmds = .; - KEEP(*(SORT(.rodata.cmds*))) - __cmds_end = .; - - . = ALIGN(4); - __hcmds = .; - KEEP(*(SORT(.rodata.hcmds*))) - __hcmds_end = .; - - . = ALIGN(4); - __mkbp_evt_srcs = .; - KEEP(*(.rodata.evtsrcs)) - __mkbp_evt_srcs_end = .; - - . = ALIGN(4); - __hooks_init = .; - KEEP(*(.rodata.HOOK_INIT)) - __hooks_init_end = .; - - __hooks_pre_freq_change = .; - KEEP(*(.rodata.HOOK_PRE_FREQ_CHANGE)) - __hooks_pre_freq_change_end = .; - - __hooks_freq_change = .; - KEEP(*(.rodata.HOOK_FREQ_CHANGE)) - __hooks_freq_change_end = .; - - __hooks_sysjump = .; - KEEP(*(.rodata.HOOK_SYSJUMP)) - __hooks_sysjump_end = .; - - __hooks_chipset_pre_init = .; - KEEP(*(.rodata.HOOK_CHIPSET_PRE_INIT)) - __hooks_chipset_pre_init_end = .; - - __hooks_chipset_startup = .; - KEEP(*(.rodata.HOOK_CHIPSET_STARTUP)) - __hooks_chipset_startup_end = .; - - __hooks_chipset_resume = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESUME)) - __hooks_chipset_resume_end = .; - - __hooks_chipset_suspend = .; - KEEP(*(.rodata.HOOK_CHIPSET_SUSPEND)) - __hooks_chipset_suspend_end = .; - -#ifdef CONFIG_CHIPSET_RESUME_INIT_HOOK - __hooks_chipset_resume_init = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESUME_INIT)) - __hooks_chipset_resume_init_end = .; - - __hooks_chipset_suspend_complete = .; - KEEP(*(.rodata.HOOK_CHIPSET_SUSPEND_COMPLETE)) - __hooks_chipset_suspend_complete_end = .; -#endif - - __hooks_chipset_shutdown = .; - KEEP(*(.rodata.HOOK_CHIPSET_SHUTDOWN)) - __hooks_chipset_shutdown_end = .; - - __hooks_chipset_shutdown_complete = .; - KEEP(*(.rodata.HOOK_CHIPSET_SHUTDOWN_COMPLETE)) - __hooks_chipset_shutdown_complete_end = .; - - __hooks_chipset_hard_off = .; - KEEP(*(.rodata.HOOK_CHIPSET_HARD_OFF)) - __hooks_chipset_hard_off_end = .; - - __hooks_chipset_reset = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESET)) - __hooks_chipset_reset_end = .; - - __hooks_ac_change = .; - KEEP(*(.rodata.HOOK_AC_CHANGE)) - __hooks_ac_change_end = .; - - __hooks_lid_change = .; - KEEP(*(.rodata.HOOK_LID_CHANGE)) - __hooks_lid_change_end = .; - - __hooks_tablet_mode_change = .; - KEEP(*(.rodata.HOOK_TABLET_MODE_CHANGE)) - __hooks_tablet_mode_change_end = .; - - __hooks_base_attached_change = .; - KEEP(*(.rodata.HOOK_BASE_ATTACHED_CHANGE)) - __hooks_base_attached_change_end = .; - - __hooks_pwrbtn_change = .; - KEEP(*(.rodata.HOOK_POWER_BUTTON_CHANGE)) - __hooks_pwrbtn_change_end = .; - - __hooks_battery_soc_change = .; - KEEP(*(.rodata.HOOK_BATTERY_SOC_CHANGE)) - __hooks_battery_soc_change_end = .; - -#ifdef CONFIG_USB_SUSPEND - __hooks_usb_change = .; - KEEP(*(.rodata.HOOK_USB_PM_CHANGE)) - __hooks_usb_change_end = .; -#endif - - __hooks_tick = .; - KEEP(*(.rodata.HOOK_TICK)) - __hooks_tick_end = .; - - __hooks_second = .; - KEEP(*(.rodata.HOOK_SECOND)) - __hooks_second_end = .; - - __hooks_usb_pd_disconnect = .; - KEEP(*(.rodata.HOOK_USB_PD_DISCONNECT)) - __hooks_usb_pd_disconnect_end = .; - - __hooks_usb_pd_connect = .; - KEEP(*(.rodata.HOOK_USB_PD_CONNECT)) - __hooks_usb_pd_connect_end = .; - - __deferred_funcs = .; - KEEP(*(.rodata.deferred)) - __deferred_funcs_end = .; - - . = ALIGN(4); - *(.rodata*) - -#ifdef CONFIG_CHIP_INIT_ROM_REGION - ASSERT(0, "CONFIG_CHIP_INIT_ROM_REGION not supported by linker script") -#endif /* CONFIG_CHIP_INIT_ROM_REGION */ - /* - * This linker file does not yet support a separate ROM resident - * section. Ensure the corresponding data objects are linked - * into the .rodata section. - */ - . = ALIGN(4); - __init_rom_start = .; - *(.init.rom) - __init_rom_end = .; - -#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS) - . = ALIGN(64); - KEEP(*(.google)) -#endif - . = ALIGN(4); - } >FLASH - - __data_lma_start = . ; - - .data : { - . = ALIGN(4); - __data_start = .; - *(.data.tasks) - *(.data) -#ifdef CONFIG_MPU - /* It has to be aligned by 32 bytes to be a valid MPU region. */ - . = ALIGN(32); - __iram_text_start = .; -#else - . = ALIGN(4); -#endif - *(.iram.text) -#ifdef CONFIG_MPU - . = ALIGN(32); - __iram_text_end = .; -#else - . = ALIGN(4); -#endif - __data_end = .; - - } > IRAM AT>FLASH - - .bss : { - /* Stacks must be 64-bit aligned */ - . = ALIGN(8); - __bss_start = .; - *(.bss.tasks) - . = ALIGN(8); - *(.bss.system_stack) - . = ALIGN(8); - *(.bss.task_scratchpad) - /* Rest of .bss takes care of its own alignment */ - *(.bss) - *(.bss.slow) - - /* - * Reserve space for deferred function firing times. - * Each time is a uint64_t, each func is a 32-bit pointer, - * thus the scaling factor of two. - */ - . = ALIGN(8); - __deferred_until = .; - . += (__deferred_funcs_end - __deferred_funcs) * (8 / 4); - __deferred_until_end = .; - - . = ALIGN(4); - __bss_end = .; - - /* - * Shared memory buffer must be at the end of preallocated RAM, - * so it can expand to use all the remaining RAM. - */ - __shared_mem_buf = .; - - } > IRAM - - ASSERT((__shared_mem_buf + CONFIG_SHAREDMEM_MINIMUM_SIZE) <= - (CONFIG_RAM_BASE + CONFIG_RAM_SIZE), - "Not enough space for shared memory.") - __ram_free = (CONFIG_RAM_BASE + CONFIG_RAM_SIZE) - - (__shared_mem_buf + CONFIG_SHAREDMEM_MINIMUM_SIZE); - - /* - * __flash_used is used in flash free calculations by the makefile. - * __image_size is stored in the struct image_data header and used - * in hash calcuations. - */ - __flash_used = LOADADDR(.data) + SIZEOF(.data) - FW_OFF(SECTION); - __image_size = __flash_used; - -#ifdef CONFIG_FLASH_CROS - /* - * These linker labels are just for analysis and not used in the code. - */ - __config_flash_size = CONFIG_FLASH_SIZE_BYTES; - __config_ro_size = CONFIG_RO_SIZE; - __config_ec_protected_storage_size = CONFIG_EC_PROTECTED_STORAGE_SIZE; - __config_rw_size = CONFIG_RW_SIZE; - __config_ec_writable_storage_size = CONFIG_EC_WRITABLE_STORAGE_SIZE; -#endif - -#if defined(CONFIG_HOSTCMD_X86) || defined(CONFIG_I2C_PERIPHERAL) - .h2ram (NOLOAD) : { - . += CONFIG_H2RAM_HOST_LPC_IO_BASE; - *(.h2ram.pool.hostcmd) - . = ALIGN(256); - *(.h2ram.pool.acpiec) -#ifdef CONFIG_I2C_PERIPHERAL - . = ALIGN(256); - *(.h2ram.pool.i2cslv) -#endif - __h2ram_end = .; - } > H2RAM - - ASSERT((__h2ram_end) <= (CONFIG_H2RAM_BASE + CONFIG_H2RAM_SIZE), - "Not enough space for h2ram section.") -#endif - -#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS)) - /DISCARD/ : { *(.google) } -#endif - - /DISCARD/ : { *(.ARM.*) } -} diff --git a/core/nds32/include/fpu.h b/core/nds32/include/fpu.h deleted file mode 100644 index 4f3efc2e5a..0000000000 --- a/core/nds32/include/fpu.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Math utility functions for N8 */ - -#ifndef __CROS_EC_FPU_H -#define __CROS_EC_FPU_H - -float sqrtf(float x); -float fabsf(float x); - -#endif /* __CROS_EC_FPU_H */ diff --git a/core/nds32/init.S b/core/nds32/init.S deleted file mode 100644 index b8e109c434..0000000000 --- a/core/nds32/init.S +++ /dev/null @@ -1,269 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * N8 CPU initialization - */ - -#include "config.h" - -/* magic macro to implement IRQ prefix / exit */ -.macro vector name, entry_number -.weak \name\()_handler -.set \name\()_handler, unhandled_irq -j __entry_\()\name -.pushsection .text.vectirq -.global __entry_\()\name -__entry_\()\name: - /* the context is stored on the current task stack*/ - /* save r15, fp, lp and sp */ - smw.adm $r15, [$sp], $r15, 0xb - /* r0-r5 are caller saved */ - smw.adm $r0, [$sp], $r5, 0 - /* store link pointer register */ - swi.gp $lp, [ + ilp] - /* switch to system stack if we are called from process stack */ - la $r3, stack_end - mov55 $fp, $sp - slt45 $r3, $sp /* if sp > end of system stack, then r15 = 1 and */ - cmovn $sp, $r3, $r15 /* point sp to the top of the system stack */ - /* save entry number of HW interrupt */ - movi55 $r3, \entry_number\() - swi.gp $r3, [ + cpu_int_entry_number] - /* isr entry */ - jal start_irq_handler - /* C routine handler */ - jal \name\()_handler - /* check whether we need to change the scheduled task */ - lwi.gp $r2, [ + need_resched] - bnez $r2, __switch_task - /* isr exit */ - jal end_irq_handler - /* restore r0-r5 */ - lmw.bim $r0, [$fp], $r5, 0 - /* restore r15, fp, lp and sp */ - lmw.bi $r15, [$fp], $r15, 0xb - /* restore PC and PSW */ - iret -.popsection -.pushsection .rodata.vecthandlers -.long \name\()_handler -.popsection -.endm - -.section .text.vecttable - -/* Exceptions vector */ -vectors: -j reset /* reset / NMI */ -j excep_handler /* TLB fill */ -j excep_handler /* PTE not present */ -j excep_handler /* TLB misc */ -j excep_handler /* TLB VLPT miss */ -j excep_handler /* Machine error */ -j excep_handler /* Debug related */ -j excep_handler /* General exception */ -vector syscall, -1 /* Syscall */ -vector irq_0, 0 /* HW 0 */ -vector irq_1, 1 /* HW 1 */ -vector irq_2, 2 /* HW 2 */ -vector irq_3, 3 /* HW 3 */ -vector irq_4, 4 /* HW 4 */ -vector irq_5, 5 /* HW 5 */ -vector irq_6, 6 /* HW 6 */ -vector irq_7, 7 /* HW 7 */ -vector irq_8, 8 /* HW 8 */ -vector irq_9, 9 /* HW 9 */ -vector irq_10, 10 /* HW 10 */ -vector irq_11, 11 /* HW 11 */ -vector irq_12, 12 /* HW 12 */ -vector irq_13, 13 /* HW 13 */ -vector irq_14, 14 /* HW 14 */ -vector irq_15, 15 /* HW 15 */ - -/* E-flash signature */ -.org 0x80 -.balign 16 -.global eflash_sig -eflash_sig: -.byte 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5 -#ifdef CONFIG_HOSTCMD_ESPI -.byte 0xA4 /* eSPI */ -#else -.byte 0xA5 /* LPC */ -#endif -.byte 0xB4 /* flag of signature */ -.byte 0x85, 0x12, 0x5A, 0x5A, 0xAA, 0xAA, 0x55, 0x55 -/* flags: internal oscillator + implicit location */ - -.text - -.global reset -reset: - /* - * GIE (global interrupt) is always disabled here. the first - * "iret" instruction of syscall interrupt (triggered by __task_start) - * will restore PSW from IPSW, and will enable GIE. - * Firmware will not change GIE settings (set/clear) until the next - * reset, unless there's an interrupt event. - * When there is an interrupt event, N8 CPU will save PSW register to - * IPSW register and clear GIE then jump to interrupt service routine. - * N8 will restore PSW from IPSW after "iret" instruction. - */ - setgie.d - dsb - - /* GP register is used to access .data and .bss */ - la $gp, _SDA_BASE_ - - /* Set system stack pointer. */ - la $sp, stack_end - - /* - * move content of lp into r5 and then store the content - * into variable "ec_reset_lp" later after memory initialization. - */ - mov55 $r5, $lp - - /* map/enable the 16kB of DLM at 0x00080000 */ - li $r0, 0x00080005 - mtsr $r0, $mr7 - - /* Set ROM address at 0x80000 (disabled). */ - li $r1, 0x00F0109B - movi $r0, #0x8 - sbi $r0, [$r1] - - /* Enable DLM 8k~12K(bit2) and DLM 12k~16k(bit3) */ - li $r1, 0x00F02030 - lbi $r0, [$r1] - ori $r0, $r0, 0x0C - sbi $r0, [$r1] - - /* Enable DLM 16k~36K bit[2-6] */ - li $r1, 0x00F0203E - lbi $r0, [$r1] - ori $r0, $r0, 0x7C - sbi $r0, [$r1] - - /* Enable DLM 36k~48K bit[0-2] */ - li $r1, 0x00F02044 - lbi $r0, [$r1] - ori $r0, $r0, 0x7 - sbi $r0, [$r1] - - /* Clear BSS */ - la $r0, _bss_start - lwi $r1, [$r0] - la $r0, _bss_end - lwi $r2, [$r0] - movi $r0, #0 -bss_loop: - swi.bi $r0, [$r1], 4 - bne $r1, $r2, bss_loop - - /* Copy initialized data to DLM */ - la $r0, _data_start - lwi $r1, [$r0] - la $r0, _data_end - lwi $r2, [$r0] - la $r0, _data_lma_start - lwi $r0, [$r0] -data_loop: - lwi.bi $r3, [$r0], 4 - swi.bi $r3, [$r1], 4 - bne $r1, $r2, data_loop - - /* store the content of r5 (lp after reset) into "ec_reset_lp" */ - swi.gp $r5, [ + ec_reset_lp] - - /* we switch to our own exception vectors */ - /* go back to it level 0 with HW interrupts globally disabled */ - li $r4, 0x70008 - mtsr $r4, $PSW - /* IT8380 specific: set vectors at 0 */ - li $r5, 0x0F02041 /* IVTBAR in GCTRL */ - movi $r15, 0 - sbi $r15, [$r5] - /* Interrupt vectors are every 4 bytes */ - li $r5, 0x00000007 - mtsr $r5, $IVB - - /* clear BRAM if it is not valid */ - jal chip_bram_valid - /* Jump to C routine */ - jal main - - /* That should not return. If it does, loop forever. */ - j . - -.global unhandled_irq -unhandled_irq: - mfsr $gp, $ITYPE - sethi $r15, 0xBAD0 - or $r15, $r15, $gp - mtsr $r15, $ITYPE - dsb - j excep_handler /* display exception with ITYPE=bad00<irq> */ - -.global excep_handler -excep_handler: -#ifdef CONFIG_FPU - /* - * We have to restore ALU so that we can continue the next - * sequence if arithmetic instructions are used. - * (Apply to floating point division by zero) - */ - sethi $gp, 0x80 - ori $gp, $gp,0x9 - mtsr $gp, $dlmb - dsb -#endif - /* safety: reload GP even though it should be already set */ - la $gp, _SDA_BASE_ - /* save r0 to free one register */ - swi.gp $r0, [ + saved_regs] - /* save the remaining 15 registers */ - la $r0, saved_regs + 4 - smw.bim $r1, [$r0], $r10, 0 - smw.bim $r15,[$r0], $r15, 0xF - /* put a valid stack pointer */ - la $sp, stack_end - /* add IPC, IPSW to the context */ - mfsr $r1, $IPC - mfsr $r2, $IPSW - smw.bi $r1, [$r0], $r2, 0 - /* pass ir6/ITYPE as the second parameter */ - mfsr $r1, $ITYPE - /* exception context pointer as first parameter */ - addi $r0, $r0, -16*4 - /* jump to panic dump C routine */ - jal report_panic - /* we never return: exceptions are fatal */ - j . - -.align 2 -_bss_start: -.long __bss_start -_bss_end: -.long __bss_end -_data_start: -.long __data_start -_data_end: -.long __data_end -_data_lma_start: -.long __data_lma_start - -/* Reserve space for system stack */ -.section .bss.system_stack -stack_start: -.space CONFIG_STACK_SIZE, 0 -stack_end: -.global stack_end -/* registers state at exception entry */ -.global saved_regs -saved_regs: -.long 0, 0, 0, 0, 0, 0, 0, 0 -.long 0, 0, 0, 0, 0, 0, 0, 0 -/* IPC, IPSW for convenient access */ -.long 0, 0 diff --git a/core/nds32/irq_chip.h b/core/nds32/irq_chip.h deleted file mode 100644 index ca517558b3..0000000000 --- a/core/nds32/irq_chip.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Chip-specific part of the IRQ handling. - */ - -#ifndef __CROS_EC_IRQ_CHIP_H -#define __CROS_EC_IRQ_CHIP_H - -/** - * Enable an IRQ in the chip interrupt controller. - * - * @param irq interrupt request index. - */ -void chip_enable_irq(int irq); - -/** - * Disable an IRQ in the chip interrupt controller. - * - * @param irq interrupt request index. - */ -void chip_disable_irq(int irq); - -/** - * Clear a pending IRQ in the chip interrupt controller. - * - * @param irq interrupt request index. - * - * Note that most interrupts can be removed from the pending state simply by - * handling whatever caused the interrupt in the first place. This only needs - * to be called if an interrupt handler disables itself without clearing the - * reason for the interrupt, and then the interrupt is re-enabled from a - * different context. - */ -void chip_clear_pending_irq(int irq); - -/** - * Software-trigger an IRQ in the chip interrupt controller. - * - * @param irq interrupt request index. - * @return CPU interrupt number to trigger if any, -1 else. - */ -int chip_trigger_irq(int irq); - -/** - * Initialize chip interrupt controller. - */ -void chip_init_irqs(void); - -/** - * Return external interrupt number. - */ -int chip_get_ec_int(void); - -/** - * Return group number of the given external interrupt number. - */ -int chip_get_intc_group(int irq); - -#endif /* __CROS_EC_IRQ_CHIP_H */ diff --git a/core/nds32/irq_handler.h b/core/nds32/irq_handler.h deleted file mode 100644 index eb55d9e233..0000000000 --- a/core/nds32/irq_handler.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Helper to declare IRQ handling routines */ - -#ifndef __CROS_EC_IRQ_HANDLER_H -#define __CROS_EC_IRQ_HANDLER_H - -/* Helper macros to build the IRQ handler and priority struct names */ -#define IRQ_HANDLER(irqname) CONCAT3(irq_, irqname, _handler) -#define IRQ_PRIORITY(irqname) CONCAT2(prio_, irqname) -/* - * Macro to connect the interrupt handler "routine" to the irq number "irq" and - * ensure it is enabled in the interrupt controller with the right priority. - */ -#define DECLARE_IRQ(irq, routine, priority) \ - void routine(void); \ - void IRQ_HANDLER(CPU_INT(irq))(void) \ - __attribute__ ((alias(STRINGIFY(routine)))); \ - const struct irq_priority __keep IRQ_PRIORITY(CPU_INT(irq)) \ - __attribute__((section(".rodata.irqprio"))) \ - = {CPU_INT(irq), priority} - -#endif /* __CROS_EC_IRQ_HANDLER_H */ diff --git a/core/nds32/math.c b/core/nds32/math.c deleted file mode 100644 index 496fcc0e5d..0000000000 --- a/core/nds32/math.c +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" - -#ifdef CONFIG_FPU -union ieee_float_shape_type { - float value; - uint32_t word; -}; - -/* Get a 32 bit int from a float. */ -#define GET_FLOAT_WORD(i, d) \ - do { \ - union ieee_float_shape_type gf_u; \ - gf_u.value = (d); \ - (i) = gf_u.word; \ - } while (0) - -/* Set a float from a 32 bit int. */ -#define SET_FLOAT_WORD(d, i) \ - do { \ - union ieee_float_shape_type sf_u; \ - sf_u.word = (i); \ - (d) = sf_u.value; \ - } while (0) - -float fabsf(float x) -{ - uint32_t ix; - - GET_FLOAT_WORD(ix, x); - SET_FLOAT_WORD(x, (ix & 0x7fffffff)); - - return x; -} - -#define FLT_UWORD_IS_ZERO(x) ((x) == 0) -#define FLT_UWORD_IS_SUBNORMAL(x) ((x) < 0x00800000L) -#define FLT_UWORD_IS_FINITE(x) ((x) < 0x7f800000L) - -static const float one = 1.0f, tiny = 1.0e-30f; -static float __ieee754_sqrtf(float x) -{ - float z; - uint32_t r, hx; - int32_t ix, s, q, m, t, i; - - GET_FLOAT_WORD(ix, x); - hx = ix & 0x7fffffff; - - /* - * take care of Inf and NaN - * sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN - */ - if (!FLT_UWORD_IS_FINITE(hx)) - return x * x + x; - /* take care of zero and -ves */ - if (FLT_UWORD_IS_ZERO(hx)) - return x; - if (ix < 0) - return (x - x) / (x - x); - - m = (ix >> 23); - if (FLT_UWORD_IS_SUBNORMAL(hx)) { - for (i = 0; (ix & 0x00800000L) == 0; i++) - ix <<= 1; - m -= i - 1; - } - - m -= 127; - ix = (ix & 0x007fffffL) | 0x00800000L; - if (m & 1) - ix += ix; - - m >>= 1; - ix += ix; - q = s = 0; - r = 0x01000000L; - - while (r != 0) { - t = s + r; - if (t <= ix) { - s = t + r; - ix -= t; - q += r; - } - ix += ix; - r >>= 1; - } - - if (ix != 0) { - z = one - tiny; - if (z >= one) { - z = one + tiny; - if (z > one) - q += 2; - else - q += (q & 1); - } - } - - ix = (q >> 1) + 0x3f000000L; - ix += (m << 23); - SET_FLOAT_WORD(z, ix); - - return z; -} - -float sqrtf(float x) -{ - return __ieee754_sqrtf(x); -} -#endif diff --git a/core/nds32/panic.c b/core/nds32/panic.c deleted file mode 100644 index 70e2cae3e0..0000000000 --- a/core/nds32/panic.c +++ /dev/null @@ -1,209 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" -#include "console.h" -#include "cpu.h" -#include "panic.h" -#include "printf.h" -#include "software_panic.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* General purpose register (r6) for saving software panic reason */ -#define SOFT_PANIC_GPR_REASON 6 -/* General purpose register (r7) for saving software panic information */ -#define SOFT_PANIC_GPR_INFO 7 - -#ifdef CONFIG_DEBUG_EXCEPTIONS -/** - * bit[4] @ ITYPE, Indicates if an exception is caused by an instruction fetch - * or a data memory access for the following exceptions: - * -TLB fill - * -TLB VLPT miss - * -TLB read protection - * -TLB write protection - * -TLB non-executable page - * -TLB page modified - * -TLB Access bit - * -PTE not present (all) - * -Reserved PTE Attribute - * -Alignment check - * -Branch target alignment - * -Machine error - * -Precise bus error - * -Imprecise bus error - * -Nonexistent local memory address - * -MPZIU Control - * -Cache locking error - * -TLB locking error - * -TLB multiple hit - * -Parity/ECC error - * All other exceptions not in the abovetable should have the INST field of - * the ITYPE register set to 0. - */ -static const char * const itype_inst[2] = { - "a data memory access", - "an instruction fetch access", -}; - -/** - * bit[3-0] @ ITYPE, general exception type information. - */ -static const char * const itype_exc_type[16] = { - "Alignment check", - "Reserved instruction", - "Trap", - "Arithmetic", - "Precise bus error", - "Imprecise bus error", - "Coprocessor", - "Privileged instruction", - - "Reserved value", - "Nonexistent local memory address", - "MPZIU Control", - NULL, - NULL, - NULL, - NULL, - NULL, -}; -#endif /* CONFIG_DEBUG_EXCEPTIONS */ - -#ifdef CONFIG_SOFTWARE_PANIC -void software_panic(uint32_t reason, uint32_t info) -{ - asm volatile ("mov55 $r6, %0" : : "r"(reason)); - asm volatile ("mov55 $r7, %0" : : "r"(info)); - if (in_interrupt_context()) - asm("j excep_handler"); - else - asm("break 0"); - __builtin_unreachable(); -} - -void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) -{ - /* - * It is safe to get pointer using get_panic_data_write(). - * If it was called earlier (eg. when saving nds_n8.ipc) calling it - * once again won't remove any data - */ - struct panic_data * const pdata = get_panic_data_write(); - uint32_t warning_ipc; - uint32_t *regs; - - regs = pdata->nds_n8.regs; - - /* Setup panic data structure */ - if (reason != PANIC_SW_WATCHDOG) { - memset(pdata, 0, CONFIG_PANIC_DATA_SIZE); - } else { - warning_ipc = pdata->nds_n8.ipc; - memset(pdata, 0, CONFIG_PANIC_DATA_SIZE); - pdata->nds_n8.ipc = warning_ipc; - } - pdata->magic = PANIC_DATA_MAGIC; - pdata->struct_size = CONFIG_PANIC_DATA_SIZE; - pdata->struct_version = 2; - pdata->arch = PANIC_ARCH_NDS32_N8; - - /* Log panic cause */ - pdata->nds_n8.itype = exception; - regs[SOFT_PANIC_GPR_REASON] = reason; - regs[SOFT_PANIC_GPR_INFO] = info; -} - -void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) -{ - struct panic_data * const pdata = panic_get_data(); - uint32_t *regs; - - if (pdata && pdata->struct_version == 2) { - regs = pdata->nds_n8.regs; - *exception = pdata->nds_n8.itype; - *reason = regs[SOFT_PANIC_GPR_REASON]; - *info = regs[SOFT_PANIC_GPR_INFO]; - } else { - *exception = *reason = *info = 0; - } -} -#endif /* CONFIG_SOFTWARE_PANIC */ - -static void print_panic_information(uint32_t *regs, uint32_t itype, - uint32_t ipc, uint32_t ipsw) -{ - panic_printf("=== EXCEP: ITYPE=%x ===\n", itype); - panic_printf("R0 %08x R1 %08x R2 %08x R3 %08x\n", - regs[0], regs[1], regs[2], regs[3]); - panic_printf("R4 %08x R5 %08x R6 %08x R7 %08x\n", - regs[4], regs[5], regs[6], regs[7]); - panic_printf("R8 %08x R9 %08x R10 %08x R15 %08x\n", - regs[8], regs[9], regs[10], regs[11]); - panic_printf("FP %08x GP %08x LP %08x SP %08x\n", - regs[12], regs[13], regs[14], regs[15]); - panic_printf("IPC %08x IPSW %05x\n", ipc, ipsw); - if ((ipsw & PSW_INTL_MASK) == (2 << PSW_INTL_SHIFT)) { - /* 2nd level exception */ - uint32_t oipc; - - asm volatile("mfsr %0, $OIPC" : "=r"(oipc)); - panic_printf("OIPC %08x\n", oipc); - } - -#ifdef CONFIG_DEBUG_EXCEPTIONS - panic_printf("SWID of ITYPE: %x\n", ((itype >> 16) & 0x7fff)); - if (panic_sw_reason_is_valid(regs[SOFT_PANIC_GPR_REASON])) { -#ifdef CONFIG_SOFTWARE_PANIC - panic_printf("Software panic reason %s\n", - panic_sw_reasons[(regs[SOFT_PANIC_GPR_REASON] - - PANIC_SW_BASE)]); - panic_printf("Software panic info 0x%x\n", - regs[SOFT_PANIC_GPR_INFO]); -#endif - } else { - panic_printf("Exception type: General exception [%s]\n", - itype_exc_type[(itype & 0xf)]); - panic_printf("Exception is caused by %s\n", - itype_inst[(itype & BIT(4))]); - } -#endif -} - -void report_panic(uint32_t *regs, uint32_t itype) -{ - int i; - struct panic_data * const pdata = get_panic_data_write(); - - pdata->magic = PANIC_DATA_MAGIC; - pdata->struct_size = CONFIG_PANIC_DATA_SIZE; - pdata->struct_version = 2; - pdata->arch = PANIC_ARCH_NDS32_N8; - pdata->flags = 0; - pdata->reserved = 0; - - pdata->nds_n8.itype = itype; - for (i = 0; i < 16; i++) - pdata->nds_n8.regs[i] = regs[i]; - pdata->nds_n8.ipc = regs[16]; - pdata->nds_n8.ipsw = regs[17]; - - print_panic_information(regs, itype, regs[16], regs[17]); - panic_reboot(); -} - -void panic_data_print(const struct panic_data *pdata) -{ - uint32_t itype, *regs, ipc, ipsw; - itype = pdata->nds_n8.itype; - regs = (uint32_t *)pdata->nds_n8.regs; - ipc = pdata->nds_n8.ipc; - ipsw = pdata->nds_n8.ipsw; - - print_panic_information(regs, itype, ipc, ipsw); -} diff --git a/core/nds32/switch.S b/core/nds32/switch.S deleted file mode 100644 index 631b0e0fe2..0000000000 --- a/core/nds32/switch.S +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Context switching - */ - -#include "config.h" -#include "cpu.h" - -.section .ram_code - -/** - * Task context switching - * - * Change the task scheduled after returning from an interruption. - * - * This function must be called in interrupt context. - * - * Save the registers of the current task below the interrupt context on - * its task, then restore the live registers of the next task and set the - * process stack pointer to the new stack. - * - * $r0: pointer to the task to switch from - * $r1: pointer to the task to switch to - * $r2: pointer to the stack where the interrupt entry context is saved - * - * the structure of the saved context on the stack is : - * (top to bottom) - * sp, lp, fp, r15, r5, r4, r3, r2, r1, r0, r10, r9, r8, r7, r6, ipc, ipsw - * interrupt entry frame <|> - */ -.global __switch_task -__switch_task: - /* get the (new) highest priority task pointer in r0 */ - jal next_sched_task - movi55 $r3, 0 - /* pointer to the current task (which are switching from) */ - lwi.gp $r1, [ + current_task] - /* reset the re-scheduling request */ - swi.gp $r3, [ + need_resched] - /* Nothing to do: let's return to keep the same task scheduled */ - beq $r1, $r0, 1f - /* save our new scheduled task */ - swi.gp $r0, [ + current_task] - /* get the program status word saved at exception entry */ - mfsr $r4, $IPSW /* to save SP_ADJ bit */ - /* get the task program counter saved at exception entry */ - mfsr $r5, $IPC - /* get the new scheduled task stack pointer */ - lw $r3, [$r0] - /* save ipsw, ipc, r6, r7, r8, r9, r10 on the current process stack */ - smw.adm $r4, [$fp], $r10, 0 - /* restore ipsw, ipc, r6, r7, r8, r9, r10 from the next stack context */ - lmw.bim $r4, [$r3], $r10, 0 - /* set the program status word to restore SP_ADJ bit */ - mtsr $r4, $IPSW - /* set the task program counter to restore at exception exit */ - mtsr $r5, $IPC - /* save the task stack pointer in its context */ - sw $fp, [$r1] - /* barrier: ensure IPC is taken into account before IRET */ - dsb - /* exception frame pointer for the new task */ - mov55 $fp, $r3 -1: /* un-pile the interruption entry context */ - /* isr exit */ - jal end_irq_handler - /* restore r0-r5 */ - lmw.bim $r0, [$fp], $r5, 0 - /* restore r15, fp, lp and sp */ - lmw.bi $r15, [$fp], $r15, 0xb - /* restore PC and PSW */ - iret - -.text -/** - * Start the task scheduling. - * - * $r0 is a pointer to task_stack_ready, which is set to 1 after - * the task stack is set up. - */ -.global __task_start -__task_start: - /* - * Disable global interrupt here to ensure below sequence won't be - * broken. The "iret" instruction of ISR will enable GIE again. - */ - setgie.d - /* area used as thread stack for the first switch */ - la $r3, scratchpad - - movi55 $r4, 1 - movi55 $r2, 0 /* syscall 3rd parameter : not an IRQ emulation */ - movi55 $r1, 0 /* syscall 2nd parameter : re-schedule nothing */ - movi55 $r0, 0 /* syscall 1st parameter : de-schedule nothing */ - - /* put the stack pointer at the top of the stack in scratchpad */ - addi $sp, $r3, 4 * TASK_SCRATCHPAD_SIZE - /* we are ready to re-schedule */ - swi.gp $r4, [ + need_resched] - swi.gp $r4, [ + start_called] - - /* trigger scheduling to execute the task with the highest priority */ - syscall 0 - /* we should never return here: set code to EC_ERROR_UNKNOWN */ - movi55 $r0, 0x1 - ret5 $lp - diff --git a/core/nds32/task.c b/core/nds32/task.c deleted file mode 100644 index edacb7975e..0000000000 --- a/core/nds32/task.c +++ /dev/null @@ -1,794 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Task scheduling / events module for Chrome EC operating system */ - -#include "atomic.h" -#include "common.h" -#include "console.h" -#include "cpu.h" -#include "hwtimer_chip.h" -#include "intc.h" -#include "irq_chip.h" -#include "link_defs.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -typedef union { - struct { - /* - * Note that sp must be the first element in the task struct - * for __switchto() to work. - */ - uint32_t sp; /* Saved stack pointer for context switch */ - uint32_t events; /* Bitmaps of received events */ - uint64_t runtime; /* Time spent in task */ - uint32_t *stack; /* Start of stack */ - }; -} task_; - -/* Value to store in unused stack */ -#define STACK_UNUSED_VALUE 0xdeadd00d - -/* declare task routine prototypes */ -#define TASK(n, r, d, s) void r(void *); -void __idle(void); -CONFIG_TASK_LIST -CONFIG_TEST_TASK_LIST -#undef TASK - -/* Task names for easier debugging */ -#define TASK(n, r, d, s) #n, -static const char * const task_names[] = { - "<< idle >>", - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -}; -#undef TASK - -#ifdef CONFIG_TASK_PROFILING -static int task_will_switch; -static uint32_t exc_sub_time; -static uint64_t task_start_time; /* Time task scheduling started */ -static uint32_t exc_start_time; /* Time of task->exception transition */ -static uint32_t exc_end_time; /* Time of exception->task transition */ -static uint64_t exc_total_time; /* Total time in exceptions */ -static uint32_t svc_calls; /* Number of service calls */ -static uint32_t task_switches; /* Number of times active task changed */ -static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ -#endif - -extern int __task_start(void); - -#ifndef CONFIG_LOW_POWER_IDLE -/* Idle task. Executed when no tasks are ready to be scheduled. */ -void __idle(void) -{ - /* - * Print when the idle task starts. This is the lowest priority task, - * so this only starts once all other tasks have gotten a chance to do - * their task inits and have gone to sleep. - */ - cprints(CC_TASK, "idle task started"); - - while (1) { -#ifdef CHIP_FAMILY_IT83XX - /* doze mode */ - IT83XX_ECPM_PLLCTRL = EC_PLL_DOZE; -#endif - asm volatile ("dsb"); - /* - * Wait for the next irq event. This stops the CPU clock - * (sleep / deep sleep, depending on chip config). - */ - asm("standby wake_grant"); - } -} -#endif /* !CONFIG_LOW_POWER_IDLE */ - -static void task_exit_trap(void) -{ - int i = task_get_current(); - cprints(CC_TASK, "Task %d (%s) exited!", i, task_names[i]); - /* Exited tasks simply sleep forever */ - while (1) - task_wait_event(-1); -} - -/* Startup parameters for all tasks. */ -#define TASK(n, r, d, s) { \ - .r0 = (uint32_t)d, \ - .pc = (uint32_t)r, \ - .stack_size = s, \ -}, -static const struct { - uint32_t r0; - uint32_t pc; - uint16_t stack_size; -} tasks_init[] = { - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -}; -#undef TASK - -/* Contexts for all tasks */ -static task_ tasks[TASK_ID_COUNT]; -/* Validity checks about static task invariants */ -BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned) * 8); -BUILD_ASSERT(TASK_ID_COUNT < (1 << (sizeof(task_id_t) * 8))); - - -/* Stacks for all tasks */ -#define TASK(n, r, d, s) + s -uint8_t task_stacks[0 - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -] __aligned(8); - -#undef TASK - -/* Reserve space to discard context on first context switch. */ -uint32_t scratchpad[TASK_SCRATCHPAD_SIZE] __attribute__ - ((section(".bss.task_scratchpad"))); - -task_ *current_task = (task_ *)scratchpad; - -/* - * Should IRQs chain to svc_handler()? This should be set if either of the - * following is true: - * - * 1) Task scheduling has started, and task profiling is enabled. Task - * profiling does its tracking in svc_handler(). - * - * 2) An event was set by an interrupt; this could result in a higher-priority - * task unblocking. After checking for a task switch, svc_handler() will clear - * the flag (unless profiling is also enabled; then the flag remains set). - */ -int need_resched; - -/* - * Bitmap of all tasks ready to be run. - * - * Start off with only the hooks task marked as ready such that all the modules - * can do their init within a task switching context. The hooks task will then - * make a call to enable all tasks. - */ -static uint32_t tasks_ready = BIT(TASK_ID_HOOKS); -/* - * Initially allow only the HOOKS and IDLE task to run, regardless of ready - * status, in order for HOOK_INIT to complete before other tasks. - * task_enable_all_tasks() will open the flood gates. - */ -static uint32_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); - -int start_called; /* Has task swapping started */ - -/* interrupt number of sw interrupt */ -static int sw_int_num; - -/* - * This variable is used to save link pointer register, - * and it is updated at the beginning of each ISR. - */ -uint32_t ilp; - -/* This variable is used to save link pointer register at EC reset. */ -uint32_t ec_reset_lp; - -static inline task_ *__task_id_to_ptr(task_id_t id) -{ - return tasks + id; -} - -/* - * We use INT_MASK to enable (interrupt_enable)/ - * disable (interrupt_disable) all maskable interrupts. - * And, EC modules share HW2 ~ HW15 interrupts. If corresponding - * bit of INT_MASK is set, it will never be cleared - * (see chip_disable_irq()). To enable/disable individual - * interrupt of EC module, we can use corresponding EXT_IERx registers. - * - * ------------ ----------- - * | | | ------- | - * |EC modules| | | HW2 | | - * | | | ------- | - * | INT 0 | | ------- | ------- ------- - * | ~ | --> | | HW3 | | -> | GIE | -> | CPU | - * | INT 167 | | ------- | ------- ------- - * | | | ... | | - * | | | ... | - clear by HW while - * | | | ------- | interrupt occur and - * | | | | HW15| | restore from IPSW after - * | | | ------- | instruction "iret". - * | EXT_IERx | | INT_MASK| - * ------------ ----------- - */ -void __ram_code interrupt_disable(void) -{ - /* Mask all interrupts, only keep division by zero exception */ - uint32_t val = BIT(30); - asm volatile ("mtsr %0, $INT_MASK" : : "r"(val)); - asm volatile ("dsb"); -} - -void __ram_code interrupt_enable(void) -{ - /* Enable HW2 ~ HW15 and division by zero exception interrupts */ - uint32_t val = (BIT(30) | 0xFFFC); - asm volatile ("mtsr %0, $INT_MASK" : : "r"(val)); -} - -inline int is_interrupt_enabled(void) -{ - uint32_t val = 0; - - asm volatile ("mfsr %0, $INT_MASK" : "=r"(val)); - - /* Interrupts are enabled if any of HW2 ~ HW15 is enabled */ - return !!(val & 0xFFFC); -} - -inline int in_interrupt_context(void) -{ - /* check INTL (Interrupt Stack Level) bits */ - return get_psw() & PSW_INTL_MASK; -} - -task_id_t task_get_current(void) -{ -#ifdef CONFIG_DEBUG_BRINGUP - /* If we haven't done a context switch then our task ID isn't valid */ - ASSERT(current_task != (task_ *)scratchpad); -#endif - /* return invalid task id if task scheduling is not yet start */ - return start_called ? (current_task - tasks) : TASK_ID_INVALID; -} - -uint32_t *task_get_event_bitmap(task_id_t tskid) -{ - task_ *tsk = __task_id_to_ptr(tskid); - return &tsk->events; -} - -int task_start_called(void) -{ - return start_called; -} - -/** - * Scheduling system call - * - * Also includes emulation of software triggering interrupt vector - */ -void __ram_code __keep syscall_handler(int desched, task_id_t resched, - int swirq) -{ - /* are we emulating an interrupt ? */ - if (swirq) { - void (*handler)(void) = __irqhandler[swirq + 1]; - /* adjust IPC to return *after* the syscall instruction */ - set_ipc(get_ipc() + 4); - /* call the regular IRQ handler */ - handler(); - sw_int_num = 0; - return; - } - - if (desched && !current_task->events) { - /* - * Remove our own ready bit (current - tasks is same as - * task_get_current()) - */ - tasks_ready &= ~(1 << (current_task - tasks)); - } - tasks_ready |= 1 << resched; - - /* trigger a re-scheduling on exit */ - need_resched = 1; - -#ifdef CONFIG_TASK_PROFILING - svc_calls++; -#endif - - /* adjust IPC to return *after* the syscall instruction */ - set_ipc(get_ipc() + 4); -} - -task_ *next_sched_task(void) -{ - task_ *new_task = __task_id_to_ptr(__fls(tasks_ready & tasks_enabled)); - -#ifdef CONFIG_TASK_PROFILING - if (current_task != new_task) { - current_task->runtime += - (exc_start_time - exc_end_time - exc_sub_time); - task_will_switch = 1; - } -#endif - -#ifdef CONFIG_DEBUG_STACK_OVERFLOW - if (*current_task->stack != STACK_UNUSED_VALUE) { - int i = task_get_current(); - - panic_printf("\n\nStack overflow in %s task!\n", task_names[i]); -#ifdef CONFIG_SOFTWARE_PANIC - software_panic(PANIC_SW_STACK_OVERFLOW, i); -#endif - } -#endif - - return new_task; -} - -static inline void __schedule(int desched, int resched, int swirq) -{ - register int p0 asm("$r0") = desched; - register int p1 asm("$r1") = resched; - register int p2 asm("$r2") = swirq; - - asm("syscall 0" : : "r"(p0), "r"(p1), "r"(p2)); -} - -void update_exc_start_time(void) -{ -#ifdef CONFIG_TASK_PROFILING - exc_start_time = get_time().le.lo; -#endif -} - -/* Interrupt number of EC modules */ -volatile int ec_int; - -void __ram_code start_irq_handler(void) -{ - /* save r0, r1, and r2 for syscall */ - asm volatile ("smw.adm $r0, [$sp], $r2, 0"); - /* If this is a SW interrupt */ - if (get_itype() & 8) - ec_int = sw_int_num; - else - ec_int = chip_get_ec_int(); - -#if defined(CONFIG_LOW_POWER_IDLE) && defined(CHIP_FAMILY_IT83XX) - clock_sleep_mode_wakeup_isr(); -#endif -#ifdef CONFIG_TASK_PROFILING - update_exc_start_time(); - - /* - * Track IRQ distribution. No need for atomic add, because an IRQ - * can't pre-empt itself. - */ - if ((ec_int > 0) && (ec_int < ARRAY_SIZE(irq_dist))) - irq_dist[ec_int]++; -#endif - /* restore r0, r1, and r2 */ - asm volatile ("lmw.bim $r0, [$sp], $r2, 0"); -} - -void end_irq_handler(void) -{ -#ifdef CONFIG_TASK_PROFILING - uint32_t t, p; - /* - * save r0 and fp (fp for restore r0-r5, r15, fp, lp and sp - * while interrupt exit. - */ - asm volatile ("smw.adm $r0, [$sp], $r0, 8"); - - t = get_time().le.lo; - p = t - exc_start_time; - - exc_total_time += p; - exc_sub_time += p; - if (task_will_switch) { - task_will_switch = 0; - exc_sub_time = 0; - exc_end_time = t; - task_switches++; - } - - /* restore r0 and fp */ - asm volatile ("lmw.bim $r0, [$sp], $r0, 8"); -#endif -} - -static uint32_t __ram_code __wait_evt(int timeout_us, task_id_t resched) -{ - task_ *tsk = current_task; - task_id_t me = tsk - tasks; - uint32_t evt; - int ret; - - ASSERT(!in_interrupt_context()); - - if (timeout_us > 0) { - timestamp_t deadline = get_time(); - deadline.val += timeout_us; - ret = timer_arm(deadline, me); - ASSERT(ret == EC_SUCCESS); - } - while (!(evt = atomic_clear(&tsk->events))) { - /* Remove ourself and get the next task in the scheduler */ - __schedule(1, resched, 0); - resched = TASK_ID_IDLE; - } - if (timeout_us > 0) { - timer_cancel(me); - /* Ensure timer event is clear, we no longer care about it */ - atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); - } - return evt; -} - -uint32_t __ram_code task_set_event(task_id_t tskid, uint32_t event) -{ - task_ *receiver = __task_id_to_ptr(tskid); - ASSERT(receiver); - - /* Set the event bit in the receiver message bitmap */ - atomic_or(&receiver->events, event); - - /* Re-schedule if priorities have changed */ - if (in_interrupt_context()) { - /* The receiver might run again */ - atomic_or(&tasks_ready, 1 << tskid); - if (start_called) - need_resched = 1; - } else { - __schedule(0, tskid, 0); - } - - return 0; -} - -uint32_t __ram_code task_wait_event(int timeout_us) -{ - return __wait_evt(timeout_us, TASK_ID_IDLE); -} - -uint32_t __ram_code task_wait_event_mask(uint32_t event_mask, int timeout_us) -{ - uint64_t deadline = get_time().val + timeout_us; - uint32_t events = 0; - int time_remaining_us = timeout_us; - - /* Add the timer event to the mask so we can indicate a timeout */ - event_mask |= TASK_EVENT_TIMER; - - while (!(events & event_mask)) { - /* Collect events to re-post later */ - events |= __wait_evt(time_remaining_us, TASK_ID_IDLE); - - time_remaining_us = deadline - get_time().val; - if (timeout_us > 0 && time_remaining_us <= 0) { - /* Ensure we return a TIMER event if we timeout */ - events |= TASK_EVENT_TIMER; - break; - } - } - - /* Re-post any other events collected */ - if (events & ~event_mask) - atomic_or(¤t_task->events, events & ~event_mask); - - return events & event_mask; -} - -uint32_t __ram_code read_clear_int_mask(void) -{ - uint32_t int_mask, int_dis = BIT(30); - - asm volatile( - "mfsr %0, $INT_MASK\n\t" - "mtsr %1, $INT_MASK\n\t" - "dsb\n\t" - : "=&r"(int_mask) - : "r"(int_dis)); - - return int_mask; -} - -void __ram_code set_int_mask(uint32_t val) -{ - asm volatile ("mtsr %0, $INT_MASK" : : "r"(val)); -} - -static void set_int_priority(uint32_t val) -{ - asm volatile ("mtsr %0, $INT_PRI" : : "r"(val)); -} - -uint32_t get_int_ctrl(void) -{ - uint32_t ret; - - asm volatile ("mfsr %0, $INT_CTRL" : "=r"(ret)); - return ret; -} - -void set_int_ctrl(uint32_t val) -{ - asm volatile ("mtsr %0, $INT_CTRL" : : "r"(val)); -} - -void task_enable_all_tasks(void) -{ - /* Mark all tasks as ready and able to run. */ - tasks_ready = tasks_enabled = BIT(TASK_ID_COUNT) - 1; - /* Reschedule the highest priority task. */ - __schedule(0, 0, 0); -} - -void task_enable_task(task_id_t tskid) -{ - atomic_or(&tasks_enabled, BIT(tskid)); -} - -void task_disable_task(task_id_t tskid) -{ - atomic_clear_bits(&tasks_enabled, BIT(tskid)); - - if (!in_interrupt_context() && tskid == task_get_current()) - __schedule(0, 0, 0); -} - -void __ram_code task_enable_irq(int irq) -{ - uint32_t int_mask = read_clear_int_mask(); - - chip_enable_irq(irq); - set_int_mask(int_mask); -} - -void __ram_code task_disable_irq(int irq) -{ - uint32_t int_mask = read_clear_int_mask(); - - chip_disable_irq(irq); - set_int_mask(int_mask); -} - -void __ram_code task_clear_pending_irq(int irq) -{ - chip_clear_pending_irq(irq); -} - -void __ram_code task_trigger_irq(int irq) -{ - int cpu_int = chip_trigger_irq(irq); - - if (cpu_int > 0) { - sw_int_num = irq; - __schedule(0, 0, cpu_int); - } -} - -/* - * Initialize IRQs in the IVIC and set their priorities as defined by the - * DECLARE_IRQ statements. - */ -static void ivic_init_irqs(void) -{ - /* Get the IRQ priorities section from the linker */ - int exc_calls = __irqprio_end - __irqprio; - int i; - uint32_t all_priorities = 0; - - /* chip-specific interrupt controller initialization */ - chip_init_irqs(); - - /* - * bit0 @ INT_CTRL = 0, - * Interrupts still keep programmable priority level. - */ - set_int_ctrl((get_int_ctrl() & ~BIT(0))); - - /* - * Re-enable global interrupts in case they're disabled. On a reboot, - * they're already enabled; if we've jumped here from another image, - * they're not. - */ - interrupt_enable(); - - /* Set priorities */ - for (i = 0; i < exc_calls; i++) { - uint8_t irq = __irqprio[i].irq; - uint8_t prio = __irqprio[i].priority; - all_priorities |= (prio & 0x3) << (irq * 2); - } - set_int_priority(all_priorities); -} - -void __ram_code mutex_lock(struct mutex *mtx) -{ - uint32_t id = 1 << task_get_current(); - - ASSERT(id != TASK_ID_INVALID); - - /* critical section with interrupts off */ - interrupt_disable(); - mtx->waiters |= id; - while (1) { - if (!mtx->lock) { /* we got it ! */ - mtx->lock = 2; - mtx->waiters &= ~id; - /* end of critical section : re-enable interrupts */ - interrupt_enable(); - return; - } else { /* Contention on the mutex */ - /* end of critical section : re-enable interrupts */ - interrupt_enable(); - /* Sleep waiting for our turn */ - task_wait_event_mask(TASK_EVENT_MUTEX, 0); - /* re-enter critical section */ - interrupt_disable(); - } - } -} - -void __ram_code mutex_unlock(struct mutex *mtx) -{ - uint32_t waiters; - task_ *tsk = current_task; - - /* - * we need to read to waiters after giving the lock back - * otherwise we might miss a waiter between the two calls. - * - * prevent compiler reordering - */ - asm volatile( - /* give back the lock */ - "movi %0, #0\n\t" - "lwi %1, [%2]\n\t" - : "=&r"(mtx->lock), "=&r"(waiters) - : "r"(&mtx->waiters)); - - while (waiters) { - task_id_t id = __fls(waiters); - waiters &= ~BIT(id); - - /* Somebody is waiting on the mutex */ - task_set_event(id, TASK_EVENT_MUTEX); - } - - /* Ensure no event is remaining from mutex wake-up */ - atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); -} - -void task_print_list(void) -{ - int i; - - ccputs("Task Ready Name Events Time (s) StkUsed\n"); - - for (i = 0; i < TASK_ID_COUNT; i++) { - char is_ready = (tasks_ready & (1<<i)) ? 'R' : ' '; - uint32_t *sp; - - int stackused = tasks_init[i].stack_size; - - for (sp = tasks[i].stack; - sp < (uint32_t *)tasks[i].sp && *sp == STACK_UNUSED_VALUE; - sp++) - stackused -= sizeof(uint32_t); - - ccprintf("%4d %c %-16s %08x %11.6lld %3d/%3d\n", i, is_ready, - task_names[i], tasks[i].events, tasks[i].runtime, - stackused, tasks_init[i].stack_size); - cflush(); - } -} - -int command_task_info(int argc, char **argv) -{ -#ifdef CONFIG_TASK_PROFILING - int total = 0; - int i; -#endif - - task_print_list(); - -#ifdef CONFIG_TASK_PROFILING - ccputs("IRQ counts by type:\n"); - cflush(); - for (i = 0; i < ARRAY_SIZE(irq_dist); i++) { - if (irq_dist[i]) { - ccprintf("%4d %8d\n", i, irq_dist[i]); - total += irq_dist[i]; - } - } - - ccprintf("Service calls: %11d\n", svc_calls); - ccprintf("Total exceptions: %11d\n", total + svc_calls); - ccprintf("Task switches: %11d\n", task_switches); - ccprintf("Task switching started: %11.6lld s\n", task_start_time); - ccprintf("Time in tasks: %11.6lld s\n", - get_time().val - task_start_time); - ccprintf("Time in exceptions: %11.6lld s\n", exc_total_time); -#endif - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(taskinfo, command_task_info, - NULL, - "Print task info"); - -static int command_task_ready(int argc, char **argv) -{ - if (argc < 2) { - ccprintf("tasks_ready: 0x%08x\n", tasks_ready); - } else { - tasks_ready = strtoi(argv[1], NULL, 16); - ccprintf("Setting tasks_ready to 0x%08x\n", tasks_ready); - __schedule(0, 0, 0); - } - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(taskready, command_task_ready, - "[setmask]", - "Print/set ready tasks"); - -void task_pre_init(void) -{ - uint32_t *stack_next = (uint32_t *)task_stacks; - int i; - - /* Fill the task memory with initial values */ - for (i = 0; i < TASK_ID_COUNT; i++) { - uint32_t *sp; - /* Stack size in words */ - uint32_t ssize = tasks_init[i].stack_size / 4; - - tasks[i].stack = stack_next; - - /* - * Update stack used by first frame: 15 regs + PC + PSW - */ - sp = stack_next + ssize - 17; - tasks[i].sp = (uint32_t)sp; - - /* Initial context on stack (see __switchto()) */ - sp[7] = tasks_init[i].r0; /* r0 */ - sp[15] = (uint32_t)task_exit_trap; /* lr */ - sp[1] = tasks_init[i].pc; /* pc */ - sp[0] = 0x70009; /* psw */ - sp[16] = (uint32_t)(sp + 17); /* sp */ - - /* Fill unused stack; also used to detect stack overflow. */ - for (sp = stack_next; sp < (uint32_t *)tasks[i].sp; sp++) - *sp = STACK_UNUSED_VALUE; - - stack_next += ssize; - } - - /* - * Fill in guard value in scratchpad to prevent stack overflow - * detection failure on the first context switch. This works because - * the first word in the scratchpad is where the switcher will store - * sp, so it's ok to blow away. - */ - ((task_ *)scratchpad)->stack = (uint32_t *)scratchpad; - *(uint32_t *)scratchpad = STACK_UNUSED_VALUE; - - /* Initialize IRQs */ - ivic_init_irqs(); -} - -int task_start(void) -{ -#ifdef CONFIG_TASK_PROFILING - task_start_time = get_time().val; - exc_end_time = get_time().le.lo; -#endif - - return __task_start(); -} diff --git a/core/riscv-rv32i/__builtin.c b/core/riscv-rv32i/__builtin.c deleted file mode 100644 index 4bf495a011..0000000000 --- a/core/riscv-rv32i/__builtin.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" - -/* - * __builtin_ffs: - * Returns one plus the index of the least significant 1-bit of x, - * or if x is zero, returns zero. - */ -int __keep __ffssi2(int x) -{ - return 32 - __builtin_clz(x & -x); -} diff --git a/core/riscv-rv32i/atomic.h b/core/riscv-rv32i/atomic.h deleted file mode 100644 index e92beb2ca0..0000000000 --- a/core/riscv-rv32i/atomic.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Atomic operations for RISC_V */ - -#ifndef __CROS_EC_ATOMIC_H -#define __CROS_EC_ATOMIC_H - -#include "common.h" -#include "cpu.h" -#include "task.h" - -typedef int atomic_t; -typedef atomic_t atomic_val_t; - -static inline atomic_val_t atomic_clear_bits(atomic_t *addr, atomic_val_t bits) -{ - return __atomic_fetch_and(addr, ~bits, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_or(atomic_t *addr, atomic_val_t bits) -{ - return __atomic_fetch_or(addr, bits, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_add(atomic_t *addr, atomic_val_t value) -{ - return __atomic_fetch_add(addr, value, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_sub(atomic_t *addr, atomic_val_t value) -{ - return __atomic_fetch_sub(addr, value, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_clear(atomic_t *addr) -{ - return __atomic_exchange_n(addr, 0, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_read_add(atomic_t *addr, atomic_val_t value) -{ - return __atomic_fetch_add(addr, value, __ATOMIC_SEQ_CST); -} - -static inline atomic_val_t atomic_read_sub(atomic_t *addr, atomic_val_t value) -{ - return __atomic_fetch_sub(addr, value, __ATOMIC_SEQ_CST); -} - -#endif /* __CROS_EC_ATOMIC_H */ diff --git a/core/riscv-rv32i/build.mk b/core/riscv-rv32i/build.mk deleted file mode 100644 index 34f059e70c..0000000000 --- a/core/riscv-rv32i/build.mk +++ /dev/null @@ -1,29 +0,0 @@ -# -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# RISC-V core OS files build -# - -# Select RISC-V bare-metal toolchain -$(call set-option,CROSS_COMPILE,$(CROSS_COMPILE_riscv),\ - /opt/coreboot-sdk/bin/riscv64-elf-) - -# Enable FPU extension if config option of FPU is enabled. -_FPU_EXTENSION=$(if $(CONFIG_FPU),f,) -# CPU specific compilation flags -CFLAGS_CPU+=-march=rv32ima$(_FPU_EXTENSION)c -mabi=ilp32$(_FPU_EXTENSION) -Os -# RISC-V does not trap division by zero, enable the sanitizer to check those. -# With `-fsanitize-undefined-trap-on-error`, we lose a bit of specificity on the -# exact issue, but the added code is as small as it gets. -CFLAGS_CPU+=-fsanitize=integer-divide-by-zero -fsanitize-undefined-trap-on-error -LDFLAGS_EXTRA+=-mrelax -LDFLAGS_EXTRA+=-static-libgcc -lgcc - -ifneq ($(CONFIG_LTO),) -CFLAGS_CPU+=-flto -LDFLAGS_EXTRA+=-flto -endif - -core-y=cpu.o init.o panic.o task.o switch.o __builtin.o math.o diff --git a/core/riscv-rv32i/config_core.h b/core/riscv-rv32i/config_core.h deleted file mode 100644 index fe6135683d..0000000000 --- a/core/riscv-rv32i/config_core.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_CONFIG_CORE_H -#define __CROS_EC_CONFIG_CORE_H - -/* Linker binary architecture and format */ -#define BFD_ARCH riscv -#define BFD_FORMAT "elf32-littleriscv" - -/* - * The hardware doesn't support the risc-v bit manipulation - * extension (CLZ/CTZ instructions) so let's use the software implementation. - */ -#define CONFIG_SOFTWARE_CLZ -#define CONFIG_SOFTWARE_CTZ -#define CONFIG_SOFTWARE_PANIC - -#endif /* __CROS_EC_CONFIG_CORE_H */ diff --git a/core/riscv-rv32i/cpu.c b/core/riscv-rv32i/cpu.c deleted file mode 100644 index fd18896846..0000000000 --- a/core/riscv-rv32i/cpu.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Set up the RISC-V core - */ - -#include "cpu.h" - -void cpu_init(void) -{ - /* bit3: Global interrupt enable (M-mode) */ - asm volatile ("csrsi mstatus, 0x8"); -} diff --git a/core/riscv-rv32i/cpu.h b/core/riscv-rv32i/cpu.h deleted file mode 100644 index e46b893ad6..0000000000 --- a/core/riscv-rv32i/cpu.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Registers map and definitions for RISC-V cores - */ - -#ifndef __CROS_EC_CPU_H -#define __CROS_EC_CPU_H - -/* - * This is the space required by both __irq_isr and __switch_task to store all - * of the caller and callee registers for each task context before switching. - */ -#ifdef CONFIG_FPU -/* additional space to save FP registers (fcsr, ft0-11, fa0-7, fs0-11) */ -#define TASK_SCRATCHPAD_SIZE (62) -#else -#define TASK_SCRATCHPAD_SIZE (29) -#endif - -#ifndef __ASSEMBLER__ -#include <stdint.h> - -/* write Exception Program Counter register */ -static inline void set_mepc(uint32_t val) -{ - asm volatile ("csrw mepc, %0" : : "r"(val)); -} - -/* read Exception Program Counter register */ -static inline uint32_t get_mepc(void) -{ - uint32_t ret; - - asm volatile ("csrr %0, mepc" : "=r"(ret)); - return ret; -} - -/* read Trap cause register */ -static inline uint32_t get_mcause(void) -{ - uint32_t ret; - - asm volatile ("csrr %0, mcause" : "=r"(ret)); - return ret; -} - -/* Generic CPU core initialization */ -void cpu_init(void); -extern uint32_t ec_reset_lp; -extern uint32_t ira; -#endif - -#endif /* __CROS_EC_CPU_H */ diff --git a/core/riscv-rv32i/ec.lds.S b/core/riscv-rv32i/ec.lds.S deleted file mode 100644 index e8963c1b14..0000000000 --- a/core/riscv-rv32i/ec.lds.S +++ /dev/null @@ -1,458 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "config.h" - -#define STRINGIFY0(name) #name -#define STRINGIFY(name) STRINGIFY0(name) - -#define FW_OFF_(section) CONFIG_##section##_MEM_OFF -#define FW_OFF(section) (CONFIG_PROGRAM_MEMORY_BASE + FW_OFF_(section)) - -#define FW_SIZE_(section) CONFIG_##section##_SIZE -#define FW_SIZE(section) FW_SIZE_(section) - -OUTPUT_FORMAT(BFD_FORMAT, BFD_FORMAT, BFD_FORMAT) -OUTPUT_ARCH(BFD_ARCH) -ENTRY(__reset) - -MEMORY -{ -#if defined(CONFIG_FLASH_PHYSICAL) - FLASH (rx) : ORIGIN = FW_OFF(SECTION) - CHIP_ILM_BASE, \ - LENGTH = FW_SIZE(SECTION) -#else - IROM (rx) : ORIGIN = CONFIG_ROM_BASE, LENGTH = CONFIG_ROM_SIZE -#endif - -#if defined(CHIP_FAMILY_IT8XXX2) - /* - * On IT8XXX2 family, it reserves space for ramcode, h2ram, and - * immu sections. - */ - IRAM (rw) : ORIGIN = CONFIG_RAM_BASE + CHIP_RAM_SPACE_RESERVED, - LENGTH = CONFIG_RAM_SIZE - CHIP_RAM_SPACE_RESERVED - /* - * ILM (Instruction Local Memory). - * We connect ILM to internal flash so we are able to - * boot from the flash. - */ - ILM (rx) : ORIGIN = FW_OFF(SECTION), LENGTH = FW_SIZE(SECTION) - -#if defined(CONFIG_HOSTCMD_X86) || defined(CONFIG_I2C_PERIPHERAL) - H2RAM (rw) : ORIGIN = CONFIG_H2RAM_BASE, LENGTH = CONFIG_H2RAM_SIZE -#endif -#else - IRAM (rw) : ORIGIN = CONFIG_RAM_BASE, LENGTH = CONFIG_RAM_SIZE -#endif /* CHIP_FAMILY_IT8XXX2 */ - -#ifdef CONFIG_DRAM_BASE - DRAM (rwx) : ORIGIN = CONFIG_DRAM_BASE, LENGTH = CONFIG_DRAM_SIZE -#endif -} - -SECTIONS -{ - .text : { -#if defined(CHIP_FAMILY_IT8XXX2) - /* - * We put "__flash_dma_start" at the beginning of the - * text section to avoid gap. - */ - __flash_dma_start = .; - ASSERT((__flash_dma_start == 0), - "__flash_dma_start has to be 4k-byte aligned"); -#endif - KEEP(STRINGIFY(OUTDIR/core/CORE/init.o) (.text.vecttable)) - . = ALIGN(4); - __image_data_offset = .; - KEEP(*(.rodata.ver)) - - . = ALIGN(4); - KEEP(STRINGIFY(OUTDIR/core/CORE/init.o) (.text.vectirq)) - KEEP(STRINGIFY(OUTDIR/core/CORE/init.o) (.text)) -#if defined(CHIP_FAMILY_IT8XXX2) - KEEP(*(.flash_direct_map)) - . = ALIGN(16); - KEEP(*(.ram_code)) - - __flash_dma_size = . - __flash_dma_start; - ASSERT((__flash_dma_size < IT83XX_ILM_BLOCK_SIZE), - "__flash_dma_size < IT83XX_ILM_BLOCK_SIZE"); - . = ALIGN(IT83XX_ILM_BLOCK_SIZE); - __ilm0_ram_code = .; - OUTDIR/chip/it83xx/i2c.o (.text*) - OUTDIR/chip/it83xx/i2c.o (.rodata) - OUTDIR/chip/it83xx/hwtimer.o (.text*) - OUTDIR/chip/it83xx/hwtimer.o (.rodata) - . = ALIGN(16); -#endif - *(.text*) - . = ALIGN(4); -#if defined(CONFIG_FLASH_PHYSICAL) -# if defined(CHIP_FAMILY_IT8XXX2) - } > ILM AT > FLASH -# else - } > FLASH -# endif -#else - } > IROM -#endif /* CONFIG_FLASH_PHYSICAL */ - - . = ALIGN(4); - .rodata : { - /* Symbols defined here are declared in link_defs.h */ - __irqprio = .; - KEEP(*(.rodata.irqprio)) - __irqprio_end = .; - - . = ALIGN(4); - __irqhandler = .; - KEEP(STRINGIFY(OUTDIR/core/CORE/init.o) (.rodata.vecthandlers)) - - . = ALIGN(4); - __cmds = .; - KEEP(*(SORT(.rodata.cmds*))) - __cmds_end = .; - - . = ALIGN(4); - __hcmds = .; - KEEP(*(SORT(.rodata.hcmds*))) - __hcmds_end = .; - - . = ALIGN(4); - __mkbp_evt_srcs = .; - KEEP(*(.rodata.evtsrcs)) - __mkbp_evt_srcs_end = .; - - . = ALIGN(4); - __hooks_init = .; - KEEP(*(.rodata.HOOK_INIT)) - __hooks_init_end = .; - - __hooks_pre_freq_change = .; - KEEP(*(.rodata.HOOK_PRE_FREQ_CHANGE)) - __hooks_pre_freq_change_end = .; - - __hooks_freq_change = .; - KEEP(*(.rodata.HOOK_FREQ_CHANGE)) - __hooks_freq_change_end = .; - - __hooks_sysjump = .; - KEEP(*(.rodata.HOOK_SYSJUMP)) - __hooks_sysjump_end = .; - - __hooks_chipset_pre_init = .; - KEEP(*(.rodata.HOOK_CHIPSET_PRE_INIT)) - __hooks_chipset_pre_init_end = .; - - __hooks_chipset_startup = .; - KEEP(*(.rodata.HOOK_CHIPSET_STARTUP)) - __hooks_chipset_startup_end = .; - - __hooks_chipset_resume = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESUME)) - __hooks_chipset_resume_end = .; - - __hooks_chipset_suspend = .; - KEEP(*(.rodata.HOOK_CHIPSET_SUSPEND)) - __hooks_chipset_suspend_end = .; - -#ifdef CONFIG_CHIPSET_RESUME_INIT_HOOK - __hooks_chipset_resume_init = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESUME_INIT)) - __hooks_chipset_resume_init_end = .; - - __hooks_chipset_suspend_complete = .; - KEEP(*(.rodata.HOOK_CHIPSET_SUSPEND_COMPLETE)) - __hooks_chipset_suspend_complete_end = .; -#endif - - __hooks_chipset_shutdown = .; - KEEP(*(.rodata.HOOK_CHIPSET_SHUTDOWN)) - __hooks_chipset_shutdown_end = .; - - __hooks_chipset_shutdown_complete = .; - KEEP(*(.rodata.HOOK_CHIPSET_SHUTDOWN_COMPLETE)) - __hooks_chipset_shutdown_complete_end = .; - - __hooks_chipset_hard_off = .; - KEEP(*(.rodata.HOOK_CHIPSET_HARD_OFF)) - __hooks_chipset_hard_off_end = .; - - __hooks_chipset_reset = .; - KEEP(*(.rodata.HOOK_CHIPSET_RESET)) - __hooks_chipset_reset_end = .; - - __hooks_ac_change = .; - KEEP(*(.rodata.HOOK_AC_CHANGE)) - __hooks_ac_change_end = .; - - __hooks_lid_change = .; - KEEP(*(.rodata.HOOK_LID_CHANGE)) - __hooks_lid_change_end = .; - - __hooks_tablet_mode_change = .; - KEEP(*(.rodata.HOOK_TABLET_MODE_CHANGE)) - __hooks_tablet_mode_change_end = .; - - __hooks_base_attached_change = .; - KEEP(*(.rodata.HOOK_BASE_ATTACHED_CHANGE)) - __hooks_base_attached_change_end = .; - - __hooks_pwrbtn_change = .; - KEEP(*(.rodata.HOOK_POWER_BUTTON_CHANGE)) - __hooks_pwrbtn_change_end = .; - - __hooks_battery_soc_change = .; - KEEP(*(.rodata.HOOK_BATTERY_SOC_CHANGE)) - __hooks_battery_soc_change_end = .; - -#ifdef CONFIG_USB_SUSPEND - __hooks_usb_change = .; - KEEP(*(.rodata.HOOK_USB_PM_CHANGE)) - __hooks_usb_change_end = .; -#endif - - __hooks_tick = .; - KEEP(*(.rodata.HOOK_TICK)) - __hooks_tick_end = .; - - __hooks_second = .; - KEEP(*(.rodata.HOOK_SECOND)) - __hooks_second_end = .; - - __hooks_usb_pd_disconnect = .; - KEEP(*(.rodata.HOOK_USB_PD_DISCONNECT)) - __hooks_usb_pd_disconnect_end = .; - - __hooks_usb_pd_connect = .; - KEEP(*(.rodata.HOOK_USB_PD_CONNECT)) - __hooks_usb_pd_connect_end = .; - - __deferred_funcs = .; - KEEP(*(.rodata.deferred)) - __deferred_funcs_end = .; - - . = ALIGN(4); - *(.rodata*) - -#ifdef CONFIG_CHIP_INIT_ROM_REGION - ASSERT(0, "CONFIG_CHIP_INIT_ROM_REGION not supported by linker script") -#endif /* CONFIG_CHIP_INIT_ROM_REGION */ - /* - * This linker file does not yet support a separate ROM resident - * section. Ensure the corresponding data objects are linked - * into the .rodata section. - */ - . = ALIGN(4); - __init_rom_start = .; - *(.init.rom) - __init_rom_end = .; - - . = ALIGN(4); - *(.srodata*) -#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS) - . = ALIGN(64); - KEEP(*(.google)) -#endif - . = ALIGN(4); -#if defined(CONFIG_FLASH_PHYSICAL) -# if defined(CHIP_FAMILY_IT8XXX2) - } > ILM AT > FLASH -# else - } > FLASH -# endif -#else - } > IROM -#endif /* CONFIG_FLASH_PHYSICAL */ - - __data_lma_start = .; - -#ifdef CONFIG_PRESERVE_LOGS - .preserve_logs(NOLOAD) : { - /* - * The address of the preserved logs is fixed at the beginning - * of memory. - */ - . = ALIGN(8); - __preserved_logs_start = .; - *(SORT(.preserved_logs.*)) - . = ALIGN(8); - __preserved_logs_end = .; - } > IRAM - __preserved_logs_size = __preserved_logs_end - __preserved_logs_start; -#ifdef CONFIG_IT83XX_HARD_RESET_BY_GPG1 - ASSERT(__preserved_logs_size <= CHIP_FLASH_PRESERVE_LOGS_SIZE, - "Not enough flash space to save EC logs.") -#endif -#endif /* CONFIG_PRESERVE_LOGS */ - - .data : { - . = ALIGN(4); - __data_start = .; - *(.data) - *(.sdata) - . = ALIGN(4); - __data_end = .; -#if defined(CONFIG_FLASH_PHYSICAL) - } > IRAM AT > FLASH -#else - } > IRAM AT > IROM -#endif - - .bss : { - /* Stacks must be 128-bit aligned */ - . = ALIGN(16); - __bss_start = .; - *(.bss.tasks) - . = ALIGN(16); - *(.bss.system_stack) - . = ALIGN(16); - *(.bss.task_scratchpad) - . = ALIGN(16); - __global_pointer$ = .; - *(.sbss) - . = ALIGN(4); - /* Rest of .bss takes care of its own alignment */ - *(.bss) - *(.bss.slow) - - /* - * Reserve space for deferred function firing times. - * Each time is a uint64_t, each func is a 32-bit pointer, - * thus the scaling factor of two. - */ - . = ALIGN(8); - __deferred_until = .; - . += (__deferred_funcs_end - __deferred_funcs) * (8 / 4); - __deferred_until_end = .; - - . = ALIGN(4); - __bss_end = .; - - /* - * Shared memory buffer must be at the end of preallocated RAM, - * so it can expand to use all the remaining RAM. - */ - __shared_mem_buf = .; - } > IRAM - - ASSERT((__shared_mem_buf + CONFIG_SHAREDMEM_MINIMUM_SIZE) <= - (CONFIG_RAM_BASE + CONFIG_RAM_SIZE), - "Not enough space for shared memory.") - - __ram_free = (CONFIG_RAM_BASE + CONFIG_RAM_SIZE) - - (__shared_mem_buf + CONFIG_SHAREDMEM_MINIMUM_SIZE); - - /* - * __flash_used is used in flash free calculations by the makefile. - * __image_size is stored in the struct image_data header and used - * in hash calcuations. - */ -#if defined(CHIP_FAMILY_IT8XXX2) - __flash_used = LOADADDR(.data) + SIZEOF(.data) + \ - CHIP_ILM_BASE - FW_OFF(SECTION); -#else - __flash_used = LOADADDR(.data) + SIZEOF(.data) - FW_OFF(SECTION); -#endif - __image_size = __flash_used; - -#ifdef CONFIG_FLASH_CROS - /* - * These linker labels are just for analysis and not used in the code. - */ - __config_flash_size = CONFIG_FLASH_SIZE_BYTES; - __config_ro_size = CONFIG_RO_SIZE; - __config_ec_protected_storage_size = CONFIG_EC_PROTECTED_STORAGE_SIZE; - __config_rw_size = CONFIG_RW_SIZE; - __config_ec_writable_storage_size = CONFIG_EC_WRITABLE_STORAGE_SIZE; -#endif - -#if defined(CHIP_FAMILY_IT8XXX2) -#if defined(CONFIG_HOSTCMD_X86) || defined(CONFIG_I2C_PERIPHERAL) - .h2ram (NOLOAD) : { - . += CONFIG_H2RAM_HOST_LPC_IO_BASE; - *(.h2ram.pool.hostcmd) - . = ALIGN(256); - *(.h2ram.pool.acpiec) -#ifdef CONFIG_I2C_PERIPHERAL - . = ALIGN(256); - *(.h2ram.pool.i2cslv) -#endif - __h2ram_end = .; - } > H2RAM - - ASSERT((__h2ram_end) <= (CONFIG_H2RAM_BASE + CONFIG_H2RAM_SIZE), - "Not enough space for h2ram section.") -#endif -#endif /* CHIP_FAMILY_IT8XXX2 */ - -#ifdef CONFIG_DRAM_BASE - /* - * Sections in DRAM region are constructed as like in non-DRAM regions: - * .dram.data LMA is for preserving initialized data across resets. - * The only difference is that they are all in the DRAM region: - * .dram.text | LOAD - * .dram.rodata | LOAD - * .dram.data LMA | LOAD - * .dram.data VMA | - * .dram.bss | NOLOAD - */ - - .dram.text : { - . = ALIGN(4); - KEEP(*(SORT(.dram.text.keep.*))) - *(SORT(.dram.text.*)) - . = ALIGN(4); - } > DRAM - - .dram.rodata : { - . = ALIGN(4); - KEEP(*(SORT(.dram.rodata.keep.*))) - *(SORT(.dram.rodata.*)) - . = ALIGN(4); - } > DRAM - - __dram_data_lma_start = ADDR(.dram.rodata) + SIZEOF(.dram.rodata); - - /* Place .dram.data LMA in between .dram.rodata and .dram.data VMA. */ - .dram.data __dram_data_lma_start + - (__dram_data_end - __dram_data_start) : { - . = ALIGN(4); - __dram_data_start = .; - *(.dram.data*) - . = ALIGN(4); - __dram_data_end = .; - - /* - * Normally, '> DRAM AT > DRAM' should be the same as '> DRAM', - * and they will be at the same address. However, if the address - * of VMA specified, LMA and VMA might have different addresses: - * '> DRAM' places VMA at the address where section declaration - * specified. - * 'AT > DRAM' places LMA at the location counter's address. - */ - } > DRAM AT > DRAM - - /* - * ld assigns correct attribute for .bss, but not for other .*.bss, - * we need an explicltly NOLOAD. - */ - .dram.bss(NOLOAD) : { - . = ALIGN(4); - __dram_bss_start = .; - *(SORT(.dram.bss*)) - . = ALIGN(4); - __dram_bss_end = .; - } > DRAM -#endif /* CONFIG_DRAM_BASE */ - -#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS)) - /DISCARD/ : { *(.google) } -#endif - - /DISCARD/ : { *(.ARM.*) } -} diff --git a/core/riscv-rv32i/include/fpu.h b/core/riscv-rv32i/include/fpu.h deleted file mode 100644 index 25d83f228f..0000000000 --- a/core/riscv-rv32i/include/fpu.h +++ /dev/null @@ -1,13 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Math utility functions for RISC-V */ - -#ifndef __CROS_EC_FPU_H -#define __CROS_EC_FPU_H - -float sqrtf(float x); - -#endif /* __CROS_EC_FPU_H */ diff --git a/core/riscv-rv32i/init.S b/core/riscv-rv32i/init.S deleted file mode 100644 index 5715478356..0000000000 --- a/core/riscv-rv32i/init.S +++ /dev/null @@ -1,454 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * RISC-V CPU initialization - */ - -#include "config.h" - -.macro vector name -.set \name\()_handler, unhandled_ec_irq -.weak \name\()_handler -j __entry_\()\name -.pushsection .text.vectirq -.global __entry_\()\name -__entry_\()\name: - /* C routine handler */ - j \name\()_handler -.popsection -.pushsection .rodata.vecthandlers -.long \name\()_handler -.popsection -.endm - -.section .text.vecttable -.align 2 -__startup: - j __reset /* reset */ -__irq: - j __irq_isr /* interrupts / exceptions */ - -.align 2 -__ec_intc: - vector irq_0 /* INT GROUP 0 */ - vector irq_1 /* INT GROUP 1 */ - vector irq_2 /* INT GROUP 2 */ - vector irq_3 /* INT GROUP 3 */ - vector irq_4 /* INT GROUP 4 */ - vector irq_5 /* INT GROUP 5 */ - vector irq_6 /* INT GROUP 6 */ - vector irq_7 /* INT GROUP 7 */ - vector irq_8 /* INT GROUP 8 */ - vector irq_9 /* INT GROUP 9 */ - vector irq_10 /* INT GROUP 10 */ - vector irq_11 /* INT GROUP 11 */ - vector irq_12 /* INT GROUP 12 */ - vector irq_13 /* INT GROUP 13 */ - vector irq_14 /* INT GROUP 14 */ - vector irq_15 /* INT GROUP 15 */ - vector syscall /* system call (emulate INT GROUP 16) */ - -#ifdef CHIP_FAMILY_IT8XXX2 -/* - * E-flash signature used to enable specific function after power-on reset. - * (HW mechanism) - * The content of 16-bytes must be the following and at offset 0x80 of binary. - * ---------------------------------------------------------------------------- - * 1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th 12th 13th 14th 15th 16th - * ---------------------------------------------------------------------------- - * A5h A5h A5h A5h A5h A5h [host] [flag] 85h 12h 5Ah 5Ah AAh AAh 55h 55h - * ---------------------------------------------------------------------------- - * [host]: A4h = enable eSPI, A5h = enable LPC - * [flag]: - * bit7: it must be 1b. - * bit6: it must be 0b. - * bit5: it must be 1b. - * bit4: 1b = 32.768KHz is from the internal clock generator. - * bit3: it must be 0b. - * bit2: it must be 1b. - * bit1: it must be 0b. - * bit0: it must be 0b. - */ -.org 0x80 -.balign 16 -.global eflash_sig -eflash_sig: -.byte 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5 -#ifdef CONFIG_HOSTCMD_ESPI -.byte 0xA4 /* eSPI */ -#else -.byte 0xA5 /* LPC */ -#endif -.byte 0xB4 /* flag of signature */ -.byte 0x85, 0x12, 0x5A, 0x5A, 0xAA, 0xAA, 0x55, 0x55 -/* flags: internal oscillator + implicit location */ -#endif /* CHIP_FAMILY_IT8XXX2 */ - - -.align 2 -.section .text.vectirq -__irq_isr: - /* save t2 to scratch register */ - csrw mscratch, t2 - /* save registers (sp, ra, t0, and t1) state at exception entry */ - la t2, excep_entry_saved_regs - sw sp, 0*4(t2) - sw ra, 1*4(t2) - sw t0, 2*4(t2) - sw t1, 3*4(t2) - /* store return address register */ - la t2, ira - sw ra, 0(t2) - /* restore t2 */ - csrr t2, mscratch - /* save ra, a0-7, t0-t6 (high memory address to low) */ - sw t6, -16*4(sp) - sw t5, -15*4(sp) - sw t4, -14*4(sp) - sw t3, -13*4(sp) - sw t2, -12*4(sp) - sw t1, -11*4(sp) - sw t0, -10*4(sp) - sw a7, -9*4(sp) - sw a6, -8*4(sp) - sw a5, -7*4(sp) - sw a4, -6*4(sp) - sw a3, -5*4(sp) - sw a2, -4*4(sp) - sw a1, -3*4(sp) - /* Don't change index of ra and a0 (see task_pre_init()) */ - sw a0, -2*4(sp) - sw ra, -1*4(sp) -#ifdef CONFIG_FPU - /* save ft0-11, fa0-7, and fcsr. */ - csrr t0, fcsr - sw t0, -37*4(sp) - fsw fa7, -36*4(sp) - fsw fa6, -35*4(sp) - fsw fa5, -34*4(sp) - fsw fa4, -33*4(sp) - fsw fa3, -32*4(sp) - fsw fa2, -31*4(sp) - fsw fa1, -30*4(sp) - fsw fa0, -29*4(sp) - fsw ft11, -28*4(sp) - fsw ft10, -27*4(sp) - fsw ft9, -26*4(sp) - fsw ft8, -25*4(sp) - fsw ft7, -24*4(sp) - fsw ft6, -23*4(sp) - fsw ft5, -22*4(sp) - fsw ft4, -21*4(sp) - fsw ft3, -20*4(sp) - fsw ft2, -19*4(sp) - fsw ft1, -18*4(sp) - fsw ft0, -17*4(sp) - /* - * Note: we never execute on this stack frame, so it does not need to - * be 16-byte aligned. - */ - addi sp, sp, -37*4 -#else - /* - * Note: we never execute on this stack frame, so it does not need to - * be 16-byte aligned. - */ - addi sp, sp, -16*4 -#endif - /* Save sp to scratch register */ - csrw mscratch, sp - /* Load top of system stack address into t0 for comparison */ - la t0, stack_end - /* - * Switch to system stack (which is in lower memory than task stack) - * if we are not already operating with the system stack - */ - bltu sp, t0, __sp_16byte_aligned - mv sp, t0 -__sp_16byte_aligned: - /* in_interrupt = 1 */ - li t0, 1 - la t1, in_interrupt - sb t0, 0(t1) - /* - * This ensures sp is 16-byte aligned. This only applies to when there - * is an interrupt before tasks start. Otherwise stack_end is already - * 16-byte aligned. - */ - andi sp, sp, -16 - /* read exception cause */ - csrr t0, mcause - /* isolate exception cause */ - andi t1, t0, 0x1f - /* mcause = 11: external interrupt or environment call from M-mode */ - addi t1, t1, -11 - beqz t1, __irq_handler - /* branch if this is an exceptoin (the interrupt bit of mcause is 0) */ - bgez t0, excep_handler - /* This interrupt is unhandled */ - j unhandled_interrupt -__irq_handler: - /* save a0, a1, and a2 for syscall */ - addi sp, sp, -4*3 - sw a0, 0(sp) - sw a1, 1*4(sp) - sw a2, 2*4(sp) - jal start_irq_handler - /* a0 = -1 if it cannot find the corresponding interrupt source */ - bltz a0, unhandled_interrupt - /* restore a0, a1, and a2 */ - lw a0, 0(sp) - lw a1, 1*4(sp) - lw a2, 2*4(sp) - addi sp, sp, 4*3 - /* get EC interrupt group 0-15 or 16:ecall */ - la t0, ec_int_group - /* get corresponding isr */ - lw t1, 0(t0) - slli t1, t1, 2 - la t0, __ec_intc - add t0, t0, t1 - /* handle irq */ - jalr t0 - /* check whether we need to change the scheduled task */ - la t0, need_resched - lw t1, 0(t0) - bnez t1, __switch_task -.global __irq_exit -__irq_exit: - jal end_irq_handler - /* in_interrupt = 0 */ - la t0, in_interrupt - sb zero, 0(t0) - /* restore sp from scratch register */ - csrr sp, mscratch -#ifdef CONFIG_FPU - addi sp, sp, 37*4 - /* restore ft0-11, fa0-7, and fcsr. */ - lw t0, -37*4(sp) - csrw fcsr, t0 - flw fa7, -36*4(sp) - flw fa6, -35*4(sp) - flw fa5, -34*4(sp) - flw fa4, -33*4(sp) - flw fa3, -32*4(sp) - flw fa2, -31*4(sp) - flw fa1, -30*4(sp) - flw fa0, -29*4(sp) - flw ft11, -28*4(sp) - flw ft10, -27*4(sp) - flw ft9, -26*4(sp) - flw ft8, -25*4(sp) - flw ft7, -24*4(sp) - flw ft6, -23*4(sp) - flw ft5, -22*4(sp) - flw ft4, -21*4(sp) - flw ft3, -20*4(sp) - flw ft2, -19*4(sp) - flw ft1, -18*4(sp) - flw ft0, -17*4(sp) -#else - addi sp, sp, 16*4 -#endif - /* restore ra, a0-a7, t0-t6 */ - lw t6, -16*4(sp) - lw t5, -15*4(sp) - lw t4, -14*4(sp) - lw t3, -13*4(sp) - lw t2, -12*4(sp) - lw t1, -11*4(sp) - lw t0, -10*4(sp) - lw a7, -9*4(sp) - lw a6, -8*4(sp) - lw a5, -7*4(sp) - lw a4, -6*4(sp) - lw a3, -5*4(sp) - lw a2, -4*4(sp) - lw a1, -3*4(sp) - lw a0, -2*4(sp) - lw ra, -1*4(sp) - mret - -.text -.global __reset -__reset: - /* disable interrupts */ - csrw mie, zero -.option push -.option norelax - /* GP register is used to access .data and .bss (address +/- 2048) */ - la gp, __global_pointer$ -.option pop - /* Set system stack pointer. */ - la sp, stack_end -#ifdef CONFIG_FPU - li t0, 0x6000 - csrw mstatus, t0 - csrw fcsr, zero -#else - csrw mstatus, zero -#endif - /* - * move content of return address(ra) into t5 and then store the content - * into variable "ec_reset_lp" later after memory initialization. - */ - mv t5, ra - /* Clear the link register */ - li ra, 0 - /* Clear the thread pointer register */ - li tp, 0 - /* set machine trap-handler base address */ - la t0, __irq - csrw mtvec, t0 - /* reset scratch register */ - csrw mscratch, zero - /* The M-mode handles interrupt/exception */ - csrwi mideleg, 0 - csrwi medeleg, 0 -#if defined(IT83XX_CHIP_FLASH_SIZE_1MB) && defined(CHIP_FAMILY_IT8XXX2) - /* ILM size is 1M bytes */ - la t0, IT83XX_GCTRL_EIDSR - lb t1, 0(t0) - andi t1, t1, 0xf0 - ori t1, t1, 0x8 - sb t1, 0(t0) -#endif - /* Clear BSS */ - la t0, __bss_start - la t1, __bss_end -bss_loop: - sw zero, 0(t0) - addi t0, t0, 4 - bltu t0, t1, bss_loop - /* Copy initialized data to data section */ - la t0, __data_start - la t1, __data_end - la t2, __data_lma_start -data_loop: - lw t3, 0(t2) - sw t3, 0(t0) - addi t0, t0, 4 - addi t2, t2, 4 - bltu t0, t1, data_loop - /* store the content of t5 (ra after reset) into "ec_reset_lp" */ - la t0, ec_reset_lp - sw t5, 0(t0) -#ifdef CHIP_FAMILY_IT8XXX2 - /* clear BRAM if it is not valid */ - jal chip_bram_valid -#endif - /* Jump to C routine */ - jal main - /* That should not return. If it does, loop forever. */ - j . - -.global unhandled_ec_irq -.global unhandled_interrupt -unhandled_ec_irq: - li tp, 0xBAD1 - j __unhandled_irq -unhandled_interrupt: - li tp, 0xBAD0 -__unhandled_irq: - slli tp, tp, 16 - la t0, ec_int - lw t0, 0(t0) - add tp, tp, t0 - j excep_handler /* display exception with TP bad[0|1]<ec_int> */ - -.global excep_handler -excep_handler: - /* save t2 */ - csrw mscratch, t2 - /* restore registers (sp, ra, t0, and t1) state */ - la t2, excep_entry_saved_regs - lw sp, 0*4(t2) - lw ra, 1*4(t2) - lw t0, 2*4(t2) - lw t1, 3*4(t2) - /* restore t2 */ - csrr t2, mscratch - /* save sp to scratch register */ - csrw mscratch, sp - la sp, saved_regs - /* save sp, ra, gp, tp , a0-a7, t0-t6, and s0-s11 registers */ - sw s11, 0*4(sp) - sw s10, 1*4(sp) - sw s9, 2*4(sp) - sw s8, 3*4(sp) - sw s7, 4*4(sp) - sw s6, 5*4(sp) - sw s5, 6*4(sp) - sw s4, 7*4(sp) - sw s3, 8*4(sp) - sw s2, 9*4(sp) - sw s1, 10*4(sp) - sw s0, 11*4(sp) - sw t6, 12*4(sp) - sw t5, 13*4(sp) - sw t4, 14*4(sp) - sw t3, 15*4(sp) - sw t2, 16*4(sp) - sw t1, 17*4(sp) - sw t0, 18*4(sp) - sw a7, 19*4(sp) - sw a6, 20*4(sp) - sw a5, 21*4(sp) - sw a4, 22*4(sp) - sw a3, 23*4(sp) - sw a2, 24*4(sp) - sw a1, 25*4(sp) - sw a0, 26*4(sp) - sw tp, 27*4(sp) - sw gp, 28*4(sp) - sw ra, 29*4(sp) - la a0, saved_regs - csrr sp, mscratch - sw sp, 30*4(a0) - /* put a valid stack pointer */ - la sp, stack_end - /* jump to panic dump C routine */ - jal report_panic - j . - -.align 2 -_bss_start: -.long __bss_start -_bss_end: -.long __bss_end -_data_start: -.long __data_start -_data_end: -.long __data_end -_data_lma_start: -.long __data_lma_start - -/* - * Reserve space for system stack. - * - * Main routine and ISR will share this space before tasks start. - * This space is then dedicated to ISRs after tasks start. - * - * NOTE: Location of system stack (.bss.system_stack) must be less than - * tasks stacks (task_stacks@.bss) and scratchpad for first context switch - * (scratchpad[]@.bss.task_scratchpad). - */ -.section .bss.system_stack -stack_start: -.space CONFIG_STACK_SIZE, 0 -stack_end: -.global stack_end - -/* sp, ra, t0, t1 registers state at exception entry */ -.global excep_entry_saved_regs -excep_entry_saved_regs: -.long 0, 0, 0, 0 - -/* registers state at exception entry */ -.global saved_regs -saved_regs: -.long 0, 0, 0, 0, 0, 0, 0, 0 -.long 0, 0, 0, 0, 0, 0, 0, 0 -.long 0, 0, 0, 0, 0, 0, 0, 0 -.long 0, 0, 0, 0, 0, 0, 0, 0 diff --git a/core/riscv-rv32i/irq_chip.h b/core/riscv-rv32i/irq_chip.h deleted file mode 100644 index 45cabf346e..0000000000 --- a/core/riscv-rv32i/irq_chip.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Chip-specific part of the IRQ handling. - */ - -#ifndef __CROS_EC_IRQ_CHIP_H -#define __CROS_EC_IRQ_CHIP_H - -/** - * Enable an IRQ in the chip interrupt controller. - * - * @param irq interrupt request index. - */ -void chip_enable_irq(int irq); - -/** - * Disable an IRQ in the chip interrupt controller. - * - * @param irq interrupt request index. - */ -void chip_disable_irq(int irq); - -/** - * Clear a pending IRQ in the chip interrupt controller. - * - * @param irq interrupt request index. - * - * Note that most interrupts can be removed from the pending state simply by - * handling whatever caused the interrupt in the first place. This only needs - * to be called if an interrupt handler disables itself without clearing the - * reason for the interrupt, and then the interrupt is re-enabled from a - * different context. - */ -void chip_clear_pending_irq(int irq); - -/** - * Software-trigger an IRQ in the chip interrupt controller. - * - * @param irq interrupt request index. - * @return CPU interrupt number to trigger if any, -1 else. - */ -int chip_trigger_irq(int irq); - -/** - * Initialize chip interrupt controller. - */ -void chip_init_irqs(void); - -/** - * Return external interrupt number. - */ -int chip_get_ec_int(void); - -/** - * Return group number of the given external interrupt number. - */ -int chip_get_intc_group(int irq); - -#endif /* __CROS_EC_IRQ_CHIP_H */ diff --git a/core/riscv-rv32i/irq_handler.h b/core/riscv-rv32i/irq_handler.h deleted file mode 100644 index 6414f90c7f..0000000000 --- a/core/riscv-rv32i/irq_handler.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Helper to declare IRQ handling routines */ - -#ifndef __CROS_EC_IRQ_HANDLER_H -#define __CROS_EC_IRQ_HANDLER_H - -/* Helper macros to build the IRQ handler and priority struct names */ -#define IRQ_HANDLER(irqname) CONCAT3(irq_, irqname, _handler) -#define IRQ_PRIORITY(irqname) CONCAT2(prio_, irqname) - -#ifndef CPU_INT -#define CPU_INT(irq) irq -#endif - -/* - * Macro to connect the interrupt handler "routine" to the irq number "irq" and - * ensure it is enabled in the interrupt controller with the right priority. - */ -#define DECLARE_IRQ(irq, routine, priority) \ - void routine(void); \ - void IRQ_HANDLER(CPU_INT(irq))(void) \ - __attribute__ ((alias(STRINGIFY(routine)))); \ - const struct irq_priority __keep IRQ_PRIORITY(CPU_INT(irq)) \ - __attribute__((section(".rodata.irqprio"))) \ - = {CPU_INT(irq), priority} - -#endif /* __CROS_EC_IRQ_HANDLER_H */ diff --git a/core/riscv-rv32i/math.c b/core/riscv-rv32i/math.c deleted file mode 100644 index 591a67eb8f..0000000000 --- a/core/riscv-rv32i/math.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" - -#ifdef CONFIG_FPU -/* Single precision floating point square root. */ -float sqrtf(float x) -{ - asm volatile ( - "fsqrt.s %0, %1" - : "=f" (x) - : "f" (x)); - - return x; -} -#endif diff --git a/core/riscv-rv32i/panic.c b/core/riscv-rv32i/panic.c deleted file mode 100644 index b339fdf76c..0000000000 --- a/core/riscv-rv32i/panic.c +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "cpu.h" -#include "panic.h" -#include "task.h" -#include "util.h" - -#ifdef CONFIG_DEBUG_EXCEPTIONS -/** - * bit[3-0] @ mcause, general exception type information. - */ -static const char * const exc_type[16] = { - "Instruction address misaligned", - "Instruction access fault", - "Illegal instruction", - "Breakpoint", - "Load address misaligned", - "Load access fault", - "Store/AMO address misaligned", - "Store/AMO access fault", - - NULL, - NULL, - NULL, - "Environment call from M-mode", - NULL, - NULL, - NULL, - NULL, -}; -#endif /* CONFIG_DEBUG_EXCEPTIONS */ - -#ifdef CONFIG_SOFTWARE_PANIC -/* General purpose register (s0) for saving software panic reason */ -#define SOFT_PANIC_GPR_REASON 11 -/* General purpose register (s1) for saving software panic information */ -#define SOFT_PANIC_GPR_INFO 10 - -void software_panic(uint32_t reason, uint32_t info) -{ - asm volatile ("mv s0, %0" : : "r"(reason) : "s0"); - asm volatile ("mv s1, %0" : : "r"(info) : "s1"); - if (in_interrupt_context()) - asm("j excep_handler"); - else - asm("ebreak"); - __builtin_unreachable(); -} - -void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) -{ - /* - * It is safe to get pointer using get_panic_data_write(). - * If it was called earlier (eg. when saving riscv.mepc) calling it - * once again won't remove any data - */ - struct panic_data * const pdata = get_panic_data_write(); - uint32_t warning_mepc; - uint32_t *regs; - - regs = pdata->riscv.regs; - - /* Setup panic data structure */ - if (reason != PANIC_SW_WATCHDOG) { - memset(pdata, 0, CONFIG_PANIC_DATA_SIZE); - } else { - warning_mepc = pdata->riscv.mepc; - memset(pdata, 0, CONFIG_PANIC_DATA_SIZE); - pdata->riscv.mepc = warning_mepc; - } - pdata->magic = PANIC_DATA_MAGIC; - pdata->struct_size = CONFIG_PANIC_DATA_SIZE; - pdata->struct_version = 2; - pdata->arch = PANIC_ARCH_RISCV_RV32I; - - /* Log panic cause */ - pdata->riscv.mcause = exception; - regs[SOFT_PANIC_GPR_REASON] = reason; - regs[SOFT_PANIC_GPR_INFO] = info; -} - -void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) -{ - struct panic_data * const pdata = panic_get_data(); - uint32_t *regs; - - if (pdata && pdata->struct_version == 2) { - regs = pdata->riscv.regs; - *exception = pdata->riscv.mcause; - *reason = regs[SOFT_PANIC_GPR_REASON]; - *info = regs[SOFT_PANIC_GPR_INFO]; - } else { - *exception = *reason = *info = 0; - } -} -#endif /* CONFIG_SOFTWARE_PANIC */ - -static void print_panic_information(uint32_t *regs, uint32_t mcause, - uint32_t mepc) -{ - panic_printf("=== EXCEPTION: MCAUSE=%x ===\n", mcause); - panic_printf("S11 %08x S10 %08x S9 %08x S8 %08x\n", - regs[0], regs[1], regs[2], regs[3]); - panic_printf("S7 %08x S6 %08x S5 %08x S4 %08x\n", - regs[4], regs[5], regs[6], regs[7]); - panic_printf("S3 %08x S2 %08x S1 %08x S0 %08x\n", - regs[8], regs[9], regs[10], regs[11]); - panic_printf("T6 %08x T5 %08x T4 %08x T3 %08x\n", - regs[12], regs[13], regs[14], regs[15]); - panic_printf("T2 %08x T1 %08x T0 %08x A7 %08x\n", - regs[16], regs[17], regs[18], regs[19]); - panic_printf("A6 %08x A5 %08x A4 %08x A3 %08x\n", - regs[20], regs[21], regs[22], regs[23]); - panic_printf("A2 %08x A1 %08x A0 %08x TP %08x\n", - regs[24], regs[25], regs[26], regs[27]); - panic_printf("GP %08x RA %08x SP %08x MEPC %08x\n", - regs[28], regs[29], regs[30], mepc); - -#ifdef CONFIG_DEBUG_EXCEPTIONS - if ((regs[SOFT_PANIC_GPR_REASON] & 0xfffffff0) == PANIC_SW_BASE) { -#ifdef CONFIG_SOFTWARE_PANIC - panic_printf("Software panic reason: %s\n", - panic_sw_reasons[(regs[SOFT_PANIC_GPR_REASON] - - PANIC_SW_BASE)]); - panic_printf("Software panic info: %d\n", - regs[SOFT_PANIC_GPR_INFO]); -#endif - } else { - panic_printf("Exception type: %s\n", exc_type[(mcause & 0xf)]); - } -#endif -} - -void report_panic(uint32_t *regs) -{ - uint32_t i, mcause, mepc; - struct panic_data * const pdata = get_panic_data_write(); - - mepc = get_mepc(); - mcause = get_mcause(); - - pdata->magic = PANIC_DATA_MAGIC; - pdata->struct_size = CONFIG_PANIC_DATA_SIZE; - pdata->struct_version = 2; - pdata->arch = PANIC_ARCH_RISCV_RV32I; - pdata->flags = 0; - pdata->reserved = 0; - - pdata->riscv.mcause = mcause; - pdata->riscv.mepc = mepc; - for (i = 0; i < 31; i++) - pdata->riscv.regs[i] = regs[i]; - - print_panic_information(regs, mcause, mepc); - panic_reboot(); -} - -void panic_data_print(const struct panic_data *pdata) -{ - uint32_t *regs, mcause, mepc; - - regs = (uint32_t *)pdata->riscv.regs; - mcause = pdata->riscv.mcause; - mepc = pdata->riscv.mepc; - print_panic_information(regs, mcause, mepc); -} diff --git a/core/riscv-rv32i/switch.S b/core/riscv-rv32i/switch.S deleted file mode 100644 index 8760667c6b..0000000000 --- a/core/riscv-rv32i/switch.S +++ /dev/null @@ -1,171 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Context switching - */ - -#include "config.h" -#include "cpu.h" - -#ifdef __RAM_CODE_SECTION_NAME -.section __RAM_CODE_SECTION_NAME -#endif - -/** - * Task context switching - * - * Change the task scheduled after returning from an interruption. - * - * This function must be called in interrupt context. - * - * Save the registers of the current task below the interrupt context on - * its task, then restore the live registers of the next task and set the - * process stack pointer to the new stack. - * - * the structure of the saved context on the stack is : - * ra, a0-a7, t0-t6 (caller saved) , s0-s11 (callee saved), mepc - * interrupt entry frame <|> additional registers - * if enabling the FPU: - * ra, a0-a7, t0-t6, ft0-ft11, fa0-fa7, and fcsr <|> - * s0-s11, fs0-fs11, and mepc - * - */ -.global __switch_task -__switch_task: - /* get the (new) highest priority task pointer in a0 */ - jal next_sched_task - /* pointer to the current task (which are switching from) */ - la t1, current_task - lw t0, 0(t1) - /* reset the re-scheduling request */ - la t2, need_resched - sw zero, 0(t2) - /* Nothing to do: let's return to keep the same task scheduled */ - beq a0, t0, __irq_exit - /* save our new scheduled task */ - sw a0, 0(t1) - /* save our current location in system stack so we can restore at end */ - add t3, sp, zero - /* restore current process stack pointer */ - csrr sp, mscratch - /* get the task program counter saved at exception entry */ - csrr t5, mepc - /* save s0-s11 on the current process stack */ - sw s11, -12*4(sp) - sw s10, -11*4(sp) - sw s9, -10*4(sp) - sw s8, -9*4(sp) - sw s7, -8*4(sp) - sw s6, -7*4(sp) - sw s5, -6*4(sp) - sw s4, -5*4(sp) - sw s3, -4*4(sp) - sw s2, -3*4(sp) - sw s1, -2*4(sp) - sw s0, -1*4(sp) -#ifdef CONFIG_FPU - /* save fs0-fs11 on the current process stack */ - fsw fs11, -24*4(sp) - fsw fs10, -23*4(sp) - fsw fs9, -22*4(sp) - fsw fs8, -21*4(sp) - fsw fs7, -20*4(sp) - fsw fs6, -19*4(sp) - fsw fs5, -18*4(sp) - fsw fs4, -17*4(sp) - fsw fs3, -16*4(sp) - fsw fs2, -15*4(sp) - fsw fs1, -14*4(sp) - fsw fs0, -13*4(sp) - /* save program counter on the current process stack */ - sw t5, -25*4(sp) - /* - * Note: we never execute on this stack frame, so it does not need to - * be 16-byte aligned. - */ - addi sp, sp, -25*4 -#else - /* save program counter on the current process stack */ - sw t5, -13*4(sp) - /* - * Note: we never execute on this stack frame, so it does not need to - * be 16-byte aligned. - */ - addi sp, sp, -13*4 -#endif - /* save the task stack pointer in its context */ - sw sp, 0(t0) - /* get the new scheduled task stack pointer */ - lw sp, 0(a0) -#ifdef CONFIG_FPU - addi sp, sp, 25*4 - /* get mepc */ - lw t0, -25*4(sp) - /* restore FP registers (fs0-fs11) from the next stack context */ - flw fs11, -24*4(sp) - flw fs10, -23*4(sp) - flw fs9, -22*4(sp) - flw fs8, -21*4(sp) - flw fs7, -20*4(sp) - flw fs6, -19*4(sp) - flw fs5, -18*4(sp) - flw fs4, -17*4(sp) - flw fs3, -16*4(sp) - flw fs2, -15*4(sp) - flw fs1, -14*4(sp) - flw fs0, -13*4(sp) -#else - addi sp, sp, 13*4 - /* get mepc */ - lw t0, -13*4(sp) -#endif - /* restore program counter from the next stack context */ - csrw mepc, t0 - /* restore registers from the next stack context */ - lw s11, -12*4(sp) - lw s10, -11*4(sp) - lw s9, -10*4(sp) - lw s8, -9*4(sp) - lw s7, -8*4(sp) - lw s6, -7*4(sp) - lw s5, -6*4(sp) - lw s4, -5*4(sp) - lw s3, -4*4(sp) - lw s2, -3*4(sp) - lw s1, -2*4(sp) - lw s0, -1*4(sp) - /* - * save sp to scratch register and switch to system stack. - * __irq_exit will restore sp from scratch register again before mret. - */ - csrw mscratch, sp - /* restore system stack */ - add sp, t3, zero - j __irq_exit - -.text -/** - * Start the task scheduling. - */ -.global __task_start -__task_start: - csrci mstatus, 0x8 - /* area used as thread stack for the first switch */ - la a3, scratchpad - li a4, 1 - li a2, 0 /* system call 3rd parameter : not an IRQ emulation */ - li a1, 0 /* system call 2nd parameter : re-schedule nothing */ - li a0, 0 /* system call 1st parameter : de-schedule nothing */ - /* put the stack pointer at the top of the stack in scratchpad */ - addi sp, a3, 4 * TASK_SCRATCHPAD_SIZE - /* we are ready to re-schedule */ - la t0, need_resched - sw a4, 0(t0) - la t0, start_called - sw a4, 0(t0) - csrsi mstatus, 0x8 - /* trigger scheduling to execute the task with the highest priority */ - ecall - /* we should never return here */ - j . diff --git a/core/riscv-rv32i/task.c b/core/riscv-rv32i/task.c deleted file mode 100644 index 558177e969..0000000000 --- a/core/riscv-rv32i/task.c +++ /dev/null @@ -1,725 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Task scheduling / events module for Chrome EC operating system */ - -#include "atomic.h" -#include "console.h" -#include "cpu.h" -#include "irq_chip.h" -#include "link_defs.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -typedef struct { - /* - * Note that sp must be the first element in the task struct - * for __switchto() to work. - */ - uint32_t sp; /* Saved stack pointer for context switch */ - uint32_t events; /* Bitmaps of received events */ - uint64_t runtime; /* Time spent in task */ - uint32_t *stack; /* Start of stack */ -} task_; - -/* Value to store in unused stack */ -#define STACK_UNUSED_VALUE 0xdeadd00d - -/* declare task routine prototypes */ -#define TASK(n, r, d, s) void r(void *); -void __idle(void); -CONFIG_TASK_LIST -CONFIG_TEST_TASK_LIST -#undef TASK - -/* Task names for easier debugging */ -#define TASK(n, r, d, s) #n, -static const char * const task_names[] = { - "<< idle >>", - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -}; -#undef TASK - -#ifdef CONFIG_TASK_PROFILING -static int task_will_switch; -static uint32_t exc_sub_time; -static uint64_t task_start_time; /* Time task scheduling started */ -static uint32_t exc_start_time; /* Time of task->exception transition */ -static uint32_t exc_end_time; /* Time of exception->task transition */ -static uint64_t exc_total_time; /* Total time in exceptions */ -static uint32_t svc_calls; /* Number of service calls */ -static uint32_t task_switches; /* Number of times active task changed */ -static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ -#endif - -extern int __task_start(void); - -#if defined(CHIP_FAMILY_IT83XX) -extern void clock_sleep_mode_wakeup_isr(void); -#endif - -#ifndef CONFIG_LOW_POWER_IDLE -/* Idle task. Executed when no tasks are ready to be scheduled. */ -void __idle(void) -{ - /* - * Print when the idle task starts. This is the lowest priority task, - * so this only starts once all other tasks have gotten a chance to do - * their task inits and have gone to sleep. - */ - cprints(CC_TASK, "idle task started"); - - while (1) { -#if defined(CHIP_FAMILY_IT83XX) - /* doze mode */ - IT83XX_ECPM_PLLCTRL = EC_PLL_DOZE; - clock_cpu_standby(); -#else - asm("wfi"); -#endif - } -} -#endif /* !CONFIG_LOW_POWER_IDLE */ - -static void task_exit_trap(void) -{ - int i = task_get_current(); - - cprints(CC_TASK, "Task %d (%s) exited!", i, task_names[i]); - /* Exited tasks simply sleep forever */ - while (1) - task_wait_event(-1); -} - -/* Startup parameters for all tasks. */ -#define TASK(n, r, d, s) { \ - .a0 = (uint32_t)d, \ - .pc = (uint32_t)r, \ - .stack_size = s, \ -}, -static const struct { - uint32_t a0; - uint32_t pc; - uint16_t stack_size; -} tasks_init[] = { - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -}; -#undef TASK - -/* Contexts for all tasks */ -static task_ tasks[TASK_ID_COUNT] __attribute__ ((section(".bss.tasks"))); -/* Validity checks about static task invariants */ -BUILD_ASSERT(TASK_ID_COUNT <= (sizeof(unsigned) * 8)); -BUILD_ASSERT(TASK_ID_COUNT < (1 << (sizeof(task_id_t) * 8))); - -/* Stacks for all tasks */ -#define TASK(n, r, d, s) + s -uint8_t task_stacks[0 - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -] __aligned(8); - -#undef TASK - -/* Reserve space to discard context on first context switch. */ -uint32_t scratchpad[TASK_SCRATCHPAD_SIZE] __attribute__ - ((section(".bss.task_scratchpad"))); - -task_ *current_task = (task_ *)scratchpad; - -/* - * Should IRQs chain to svc_handler()? This should be set if either of the - * following is true: - * - * 1) Task scheduling has started, and task profiling is enabled. Task - * profiling does its tracking in svc_handler(). - * - * 2) An event was set by an interrupt; this could result in a higher-priority - * task unblocking. After checking for a task switch, svc_handler() will clear - * the flag (unless profiling is also enabled; then the flag remains set). - */ -int need_resched; - -/* - * Bitmap of all tasks ready to be run. - * - * Start off with only the hooks task marked as ready such that all the modules - * can do their init within a task switching context. The hooks task will then - * make a call to enable all tasks. - */ -static uint32_t tasks_ready = BIT(TASK_ID_HOOKS); -/* - * Initially allow only the HOOKS and IDLE task to run, regardless of ready - * status, in order for HOOK_INIT to complete before other tasks. - * task_enable_all_tasks() will open the flood gates. - */ -static uint32_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); - -int start_called; /* Has task swapping started */ - -/* in interrupt context */ -volatile bool in_interrupt; -/* Interrupt number of EC modules */ -volatile int ec_int; -/* Interrupt group of EC INTC modules */ -volatile int ec_int_group; -/* interrupt number of sw interrupt */ -static int sw_int_num; -/* This variable is used to save return address register at EC reset. */ -uint32_t ec_reset_lp; -/* - * This variable is used to save return address register, - * and it is updated at the beginning of each ISR. - */ -uint32_t ira; - -static inline task_ *__task_id_to_ptr(task_id_t id) -{ - return tasks + id; -} - -void __ram_code interrupt_disable(void) -{ - /* bit11: disable MEIE */ - asm volatile ("li t0, 0x800"); - asm volatile ("csrc mie, t0"); -} - -void __ram_code interrupt_enable(void) -{ - /* bit11: enable MEIE */ - asm volatile ("li t0, 0x800"); - asm volatile ("csrs mie, t0"); -} - -inline int is_interrupt_enabled(void) -{ - int mie = 0; - - asm volatile ("csrr %0, mie" : "=r"(mie)); - - /* Check if MEIE bit is set in MIE register */ - return !!(mie & 0x800); -} - -inline int in_interrupt_context(void) -{ - return in_interrupt; -} - -int in_soft_interrupt_context(void) -{ - /* group 16 is reserved for soft-irq */ - return in_interrupt_context() && ec_int_group == 16; -} - -task_id_t __ram_code task_get_current(void) -{ -#ifdef CONFIG_DEBUG_BRINGUP - /* If we haven't done a context switch then our task ID isn't valid */ - ASSERT(current_task != (task_ *)scratchpad); -#endif - return current_task - tasks; -} - -uint32_t * __ram_code task_get_event_bitmap(task_id_t tskid) -{ - task_ *tsk = __task_id_to_ptr(tskid); - - return &tsk->events; -} - -int task_start_called(void) -{ - return start_called; -} - -/** - * Scheduling system call - * - * Also includes emulation of software triggering interrupt vector - */ -void __ram_code __keep syscall_handler(int desched, task_id_t resched, - int swirq) -{ - /* are we emulating an interrupt ? */ - if (swirq) { - void (*handler)(void) = __irqhandler[swirq]; - /* adjust IPC to return *after* the syscall instruction */ - set_mepc(get_mepc() + 4); - /* call the regular IRQ handler */ - handler(); - sw_int_num = 0; - return; - } - - if (desched && !current_task->events) { - /* - * Remove our own ready bit (current - tasks is same as - * task_get_current()) - */ - tasks_ready &= ~(1 << (current_task - tasks)); - } - tasks_ready |= 1 << resched; - - /* trigger a re-scheduling on exit */ - need_resched = 1; - -#ifdef CONFIG_TASK_PROFILING - svc_calls++; -#endif - /* adjust IPC to return *after* the syscall instruction */ - set_mepc(get_mepc() + 4); -} - -task_ * __ram_code next_sched_task(void) -{ - task_ *new_task = __task_id_to_ptr(__fls(tasks_ready & tasks_enabled)); - -#ifdef CONFIG_TASK_PROFILING - if (current_task != new_task) { - current_task->runtime += - (exc_start_time - exc_end_time - exc_sub_time); - task_will_switch = 1; - } -#endif - -#ifdef CONFIG_DEBUG_STACK_OVERFLOW - if (*current_task->stack != STACK_UNUSED_VALUE) { - int i = task_get_current(); - - panic_printf("\n\nStack overflow in %s task!\n", task_names[i]); -#ifdef CONFIG_SOFTWARE_PANIC - software_panic(PANIC_SW_STACK_OVERFLOW, i); -#endif - } -#endif - - return new_task; -} - -static inline void __schedule(int desched, int resched, int swirq) -{ - register int p0 asm("a0") = desched; - register int p1 asm("a1") = resched; - register int p2 asm("a2") = swirq; - - asm("ecall" : : "r"(p0), "r"(p1), "r"(p2)); -} - -void __ram_code update_exc_start_time(void) -{ -#ifdef CONFIG_TASK_PROFILING - exc_start_time = get_time().le.lo; -#endif -} - -/** - * The beginning of interrupt handler of c language code. - * - * @param none - * @return -1 if it cannot find the corresponding interrupt source. - */ -int __ram_code start_irq_handler(void) -{ - /* If this is a SW interrupt */ - if (get_mcause() == 11) { - ec_int = sw_int_num; - ec_int_group = 16; - } else { - /* - * Determine interrupt number. - * -1 if it cannot find the corresponding interrupt source. - */ - if (chip_get_ec_int() == -1) - return -1; - ec_int_group = chip_get_intc_group(ec_int); - } - -#if defined(CONFIG_LOW_POWER_IDLE) && defined(CHIP_FAMILY_IT83XX) - clock_sleep_mode_wakeup_isr(); -#endif -#ifdef CONFIG_TASK_PROFILING - update_exc_start_time(); - - /* - * Track IRQ distribution. No need for atomic add, because an IRQ - * can't pre-empt itself. - */ - if ((ec_int > 0) && (ec_int < ARRAY_SIZE(irq_dist))) - irq_dist[ec_int]++; -#endif - - return EC_SUCCESS; -} - -void __ram_code end_irq_handler(void) -{ -#ifdef CONFIG_TASK_PROFILING - uint32_t t, p; - - t = get_time().le.lo; - p = t - exc_start_time; - - exc_total_time += p; - exc_sub_time += p; - if (task_will_switch) { - task_will_switch = 0; - exc_sub_time = 0; - exc_end_time = t; - task_switches++; - } -#endif -} - -static uint32_t __ram_code __wait_evt(int timeout_us, task_id_t resched) -{ - task_ *tsk = current_task; - task_id_t me = tsk - tasks; - uint32_t evt; - int ret; - - ASSERT(!in_interrupt_context()); - - if (timeout_us > 0) { - timestamp_t deadline = get_time(); - - deadline.val += timeout_us; - ret = timer_arm(deadline, me); - ASSERT(ret == EC_SUCCESS); - } - while (!(evt = atomic_clear(&tsk->events))) { - /* Remove ourself and get the next task in the scheduler */ - __schedule(1, resched, 0); - resched = TASK_ID_IDLE; - } - if (timeout_us > 0) { - timer_cancel(me); - /* Ensure timer event is clear, we no longer care about it */ - atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); - } - return evt; -} - -uint32_t __ram_code task_set_event(task_id_t tskid, uint32_t event) -{ - task_ *receiver = __task_id_to_ptr(tskid); - - ASSERT(receiver); - - /* Set the event bit in the receiver message bitmap */ - atomic_or(&receiver->events, event); - - /* Re-schedule if priorities have changed */ - if (in_interrupt_context()) { - /* The receiver might run again */ - atomic_or(&tasks_ready, 1 << tskid); - if (start_called) - need_resched = 1; - } else { - __schedule(0, tskid, 0); - } - - return 0; -} - -uint32_t __ram_code task_wait_event(int timeout_us) -{ - return __wait_evt(timeout_us, TASK_ID_IDLE); -} - -uint32_t __ram_code task_wait_event_mask(uint32_t event_mask, int timeout_us) -{ - uint64_t deadline = get_time().val + timeout_us; - uint32_t events = 0; - int time_remaining_us = timeout_us; - - /* Add the timer event to the mask so we can indicate a timeout */ - event_mask |= TASK_EVENT_TIMER; - - while (!(events & event_mask)) { - /* Collect events to re-post later */ - events |= __wait_evt(time_remaining_us, TASK_ID_IDLE); - - time_remaining_us = deadline - get_time().val; - if (timeout_us > 0 && time_remaining_us <= 0) { - /* Ensure we return a TIMER event if we timeout */ - events |= TASK_EVENT_TIMER; - break; - } - } - - /* Re-post any other events collected */ - if (events & ~event_mask) - atomic_or(¤t_task->events, events & ~event_mask); - - return events & event_mask; -} - -uint32_t __ram_code read_clear_int_mask(void) -{ - uint32_t mie, meie = BIT(11); - - /* Read and clear MEIE bit of MIE register. */ - asm volatile ("csrrc %0, mie, %1" : "=r"(mie) : "r"(meie)); - - return mie; -} - -void __ram_code set_int_mask(uint32_t val) -{ - asm volatile ("csrw mie, %0" : : "r"(val)); -} - -void task_enable_all_tasks(void) -{ - /* Mark all tasks as ready and able to run. */ - tasks_ready = tasks_enabled = BIT(TASK_ID_COUNT) - 1; - /* Reschedule the highest priority task. */ - __schedule(0, 0, 0); -} - -void task_enable_task(task_id_t tskid) -{ - atomic_or(&tasks_enabled, BIT(tskid)); -} - -void task_disable_task(task_id_t tskid) -{ - atomic_clear_bits(&tasks_enabled, BIT(tskid)); - - if (!in_interrupt_context() && tskid == task_get_current()) - __schedule(0, 0, 0); -} - -void __ram_code task_enable_irq(int irq) -{ - uint32_t int_mask = read_clear_int_mask(); - - chip_enable_irq(irq); - set_int_mask(int_mask); -} - -void __ram_code task_disable_irq(int irq) -{ - uint32_t int_mask = read_clear_int_mask(); - - chip_disable_irq(irq); - set_int_mask(int_mask); -} - -void __ram_code task_clear_pending_irq(int irq) -{ - chip_clear_pending_irq(irq); -} - -void __ram_code task_trigger_irq(int irq) -{ - int cpu_int = chip_trigger_irq(irq); - - if (cpu_int > 0) { - sw_int_num = irq; - __schedule(0, 0, cpu_int); - } -} - -/* - * Initialize IRQs in the IVIC and set their priorities as defined by the - * DECLARE_IRQ statements. - */ -static void ivic_init_irqs(void) -{ - /* chip-specific interrupt controller initialization */ - chip_init_irqs(); - /* - * Re-enable global interrupts in case they're disabled. On a reboot, - * they're already enabled; if we've jumped here from another image, - * they're not. - */ - interrupt_enable(); -} - -void __ram_code mutex_lock(struct mutex *mtx) -{ - uint32_t locked; - uint32_t id = 1 << task_get_current(); - - ASSERT(id != TASK_ID_INVALID); - atomic_or(&mtx->waiters, id); - - while (1) { - asm volatile ( - /* set lock value */ - "li %0, 2\n\t" - /* attempt to acquire lock */ - "amoswap.w.aq %0, %0, %1\n\t" - : "=&r" (locked), "+A" (mtx->lock)); - /* we got it ! */ - if (!locked) - break; - /* Contention on the mutex */ - /* Sleep waiting for our turn */ - task_wait_event_mask(TASK_EVENT_MUTEX, 0); - } - - atomic_clear_bits(&mtx->waiters, id); -} - -void __ram_code mutex_unlock(struct mutex *mtx) -{ - uint32_t waiters; - task_ *tsk = current_task; - - /* give back the lock */ - asm volatile ( - "amoswap.w.aqrl zero, zero, %0\n\t" - : "+A" (mtx->lock)); - waiters = mtx->waiters; - - while (waiters) { - task_id_t id = __fls(waiters); - - waiters &= ~BIT(id); - - /* Somebody is waiting on the mutex */ - task_set_event(id, TASK_EVENT_MUTEX); - } - - /* Ensure no event is remaining from mutex wake-up */ - atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); -} - -void task_print_list(void) -{ - int i; - - ccputs("Task Ready Name Events Time (s) StkUsed\n"); - - for (i = 0; i < TASK_ID_COUNT; i++) { - char is_ready = (tasks_ready & (1<<i)) ? 'R' : ' '; - uint32_t *sp; - - int stackused = tasks_init[i].stack_size; - - for (sp = tasks[i].stack; - sp < (uint32_t *)tasks[i].sp && *sp == STACK_UNUSED_VALUE; - sp++) - stackused -= sizeof(uint32_t); - - ccprintf("%4d %c %-16s %08x %11.6lld %3d/%3d\n", i, is_ready, - task_names[i], tasks[i].events, tasks[i].runtime, - stackused, tasks_init[i].stack_size); - cflush(); - } -} - -int command_task_info(int argc, char **argv) -{ -#ifdef CONFIG_TASK_PROFILING - unsigned int total = 0; - int i; -#endif - - task_print_list(); - -#ifdef CONFIG_TASK_PROFILING - ccputs("IRQ counts by type:\n"); - cflush(); - for (i = 0; i < ARRAY_SIZE(irq_dist); i++) { - if (irq_dist[i]) { - ccprintf("%4d %8d\n", i, irq_dist[i]); - total += irq_dist[i]; - } - } - - ccprintf("Service calls: %11u\n", svc_calls); - ccprintf("Total exceptions: %11u\n", total + svc_calls); - ccprintf("Task switches: %11u\n", task_switches); - ccprintf("Task switching started: %11.6llu s\n", task_start_time); - ccprintf("Time in tasks: %11.6llu s\n", - get_time().val - task_start_time); - ccprintf("Time in exceptions: %11.6llu s\n", exc_total_time); -#endif - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(taskinfo, command_task_info, - NULL, - "Print task info"); - -static int command_task_ready(int argc, char **argv) -{ - if (argc < 2) { - ccprintf("tasks_ready: 0x%08x\n", tasks_ready); - } else { - tasks_ready = strtoi(argv[1], NULL, 16); - ccprintf("Setting tasks_ready to 0x%08x\n", tasks_ready); - __schedule(0, 0, 0); - } - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(taskready, command_task_ready, - "[setmask]", - "Print/set ready tasks"); - -void task_pre_init(void) -{ - uint32_t *stack_next = (uint32_t *)task_stacks; - int i; - - /* Fill the task memory with initial values */ - for (i = 0; i < TASK_ID_COUNT; i++) { - uint32_t *sp; - /* Stack size in words */ - uint32_t ssize = tasks_init[i].stack_size / 4; - - tasks[i].stack = stack_next; - - /* - * Update stack used by first frame: 28 regs + MEPC + (FP regs) - */ - sp = stack_next + ssize - TASK_SCRATCHPAD_SIZE; - tasks[i].sp = (uint32_t)sp; - - /* Initial context on stack (see __switchto()) */ - sp[TASK_SCRATCHPAD_SIZE-2] = tasks_init[i].a0; /* a0 */ - sp[TASK_SCRATCHPAD_SIZE-1] = (uint32_t)task_exit_trap; /* ra */ - sp[0] = tasks_init[i].pc; /* pc/mepc */ - - /* Fill unused stack; also used to detect stack overflow. */ - for (sp = stack_next; sp < (uint32_t *)tasks[i].sp; sp++) - *sp = STACK_UNUSED_VALUE; - - stack_next += ssize; - } - - /* - * Fill in guard value in scratchpad to prevent stack overflow - * detection failure on the first context switch. This works because - * the first word in the scratchpad is where the switcher will store - * sp, so it's ok to blow away. - */ - ((task_ *)scratchpad)->stack = (uint32_t *)scratchpad; - *(uint32_t *)scratchpad = STACK_UNUSED_VALUE; - - /* Initialize IRQs */ - ivic_init_irqs(); -} - -int task_start(void) -{ -#ifdef CONFIG_TASK_PROFILING - task_start_time = get_time().val; - exc_end_time = get_time().le.lo; -#endif - - return __task_start(); -} |