diff options
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(); -} |