diff --git a/arch/Kconfig b/arch/Kconfig index 0a65a3de82..8b76605f6e 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -274,6 +274,9 @@ config ARCH_HAVE_VFORK bool default n +config ARCH_HAVE_MMU + bool + config ARCH_STACKDUMP bool "Dump stack on assertions" default n @@ -334,6 +337,7 @@ config ARCH_CALIBRATION config DRAM_START hex "DRAM start physical address" + default 0x0 help The physical start address of installed RAM. Despite the naming, this may be SDRAM or SRAM or any other RAM technology that support @@ -341,6 +345,7 @@ config DRAM_START config DRAM_VSTART hex "DRAM start virtual address" + default 0x0 depends on ARCH_HAVE_MMU help The virtual start address of installed RAM. Despite the naming, @@ -349,6 +354,7 @@ config DRAM_VSTART config DRAM_SIZE int "DRAM size" + default 0 help The size in bytes of the installed RAM. Despite the naming, this may be SDRAM or SRAM or any other RAM technology that support diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d7cd7dcf25..f5890c600a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -29,7 +29,6 @@ config ARCH_CHIP_DM320 bool "TMS320 DM320" select ARCH_ARM926EJS select ARCH_HAVE_LOWVECTORS - select ARCH_HAVE_MMU ---help--- TI DMS320 DM320 (ARM926EJS) @@ -38,7 +37,6 @@ config ARCH_CHIP_IMX select ARCH_ARM920T select ARCH_HAVE_HEAP2 select ARCH_HAVE_LOWVECTORS - select ARCH_HAVE_MMU ---help--- Freescale iMX architectures (ARM920T) @@ -91,7 +89,6 @@ config ARCH_CHIP_LPC31XX bool "NXP LPC31XX" select ARCH_ARM926EJS select ARCH_HAVE_LOWVECTORS - select ARCH_HAVE_MMU ---help--- NPX LPC31XX architectures (ARM926EJS). @@ -143,10 +140,12 @@ config ARCH_ARM7TDMI config ARCH_ARM926EJS bool default n + select ARCH_HAVE_MMU config ARCH_ARM920T bool default n + select ARCH_HAVE_MMU config ARCH_CORTEXM0 bool @@ -169,6 +168,7 @@ config ARCH_CORTEXA5 bool default n select ARCH_IRQPRIO + select ARCH_HAVE_MMU config ARCH_FAMILY string @@ -261,11 +261,9 @@ config ARCH_LOWVECTORS ---help--- Support ARM vectors in low memory. -config ARCH_HAVE_MMU - bool - config PGTABLE_VADDR hex "Page table virtual address" + default 0x0 depends on ARCH_HAVE_MMU ---help--- Page table virtual address (might be defined in the board.h file). Not diff --git a/arch/arm/src/arm/up_copystate.c b/arch/arm/src/arm/up_copystate.c index c76ee8e707..fdc7246d98 100644 --- a/arch/arm/src/arm/up_copystate.c +++ b/arch/arm/src/arm/up_copystate.c @@ -61,7 +61,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: up_undefinedinsn + * Name: up_copystate ****************************************************************************/ /* A little faster than most memcpy's */ diff --git a/arch/arm/src/arm/up_prefetchabort.c b/arch/arm/src/arm/up_prefetchabort.c index 78ca496abc..c75a92a499 100644 --- a/arch/arm/src/arm/up_prefetchabort.c +++ b/arch/arm/src/arm/up_prefetchabort.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/arm/src/src/up_prefetchabort.c + * arch/arm/src/arm/up_prefetchabort.c * * Copyright (C) 2007-2011, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt diff --git a/arch/arm/src/arm/up_vectoraddrexcptn.S b/arch/arm/src/arm/up_vectoraddrexcptn.S index ba5787cb91..d53129c46a 100644 --- a/arch/arm/src/arm/up_vectoraddrexcptn.S +++ b/arch/arm/src/arm/up_vectoraddrexcptn.S @@ -1,5 +1,5 @@ /************************************************************************************ - * arch/arm/src/src/up_vectoraddrexceptn.S + * arch/arm/src/arm/up_vectoraddrexceptn.S * * Copyright (C) 2008-2010 Gregory Nutt. All rights reserved. * Author: Gregory Nutt diff --git a/arch/arm/src/armv7-a/arm_allocpage.c b/arch/arm/src/armv7-a/arm_allocpage.c new file mode 100644 index 0000000000..3856dc531b --- /dev/null +++ b/arch/arm/src/armv7-a/arm_allocpage.c @@ -0,0 +1,243 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_allocpage.c + * Allocate a new page and map it to the fault address of a task. + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#ifdef CONFIG_PAGING + +#include + +#include "pg_macros.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#if CONFIG_PAGING_NPPAGED < 256 +typedef uint8_t pgndx_t; +#elif CONFIG_PAGING_NPPAGED < 65536 +typedef uint16_t pgndx_t; +#else +typedef uint32_t pgndx_t; +#endif + +#if PG_POOL_MAXL1NDX < 256 +typedef uint8_t L1ndx_t; +#elif PG_POOL_MAXL1NDX < 65536 +typedef uint16_t L1ndx_t; +#else +typedef uint32_t L1ndx_t; +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Free pages in memory are managed by indices ranging from up to + * CONFIG_PAGING_NPAGED. Initially all pages are free so the page can be + * simply allocated in order: 0, 1, 2, ... . After all CONFIG_PAGING_NPAGED + * pages have be filled, then they are blindly freed and re-used in the + * same order 0, 1, 2, ... because we don't know any better. No smart "least + * recently used" kind of logic is supported. + */ + +static pgndx_t g_pgndx; + +/* After CONFIG_PAGING_NPAGED have been allocated, the pages will be re-used. + * In order to re-used the page, we will have un-map the page from its previous + * mapping. In order to that, we need to be able to map a physical address to + * to an index into the PTE where it was mapped. The following table supports + * this backward lookup - it is indexed by the page number index, and holds + * another index to the mapped virtual page. + */ + +static L1ndx_t g_ptemap[CONFIG_PAGING_NPPAGED]; + +/* The contents of g_ptemap[] are not valid until g_pgndx has wrapped at + * least one time. + */ + +static bool g_pgwrap; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocpage() + * + * Description: + * This architecture-specific function will set aside page in memory and map + * the page to its correct virtual address. Architecture-specific context + * information saved within the TCB will provide the function with the + * information needed to identify the virtual miss address. + * + * This function will return the allocated physical page address in vpage. + * The size of the underlying physical page is determined by the + * configuration setting CONFIG_PAGING_PAGESIZE. + * + * NOTE 1: This function must always return a page allocation. If all + * available pages are in-use (the typical case), then this function will + * select a page in-use, un-map it, and make it available. + * + * NOTE 2: If an in-use page is un-mapped, it may be necessary to flush the + * instruction cache in some architectures. + * + * NOTE 3: Allocating and filling a page is a two step process. up_allocpage() + * allocates the page, and up_fillpage() fills it with data from some non- + * volatile storage device. This distinction is made because up_allocpage() + * can probably be implemented in board-independent logic whereas up_fillpage() + * probably must be implemented as board-specific logic. + * + * NOTE 4: The initial mapping of vpage should be read-able and write- + * able (but not cached). No special actions will be required of + * up_fillpage() in order to write into this allocated page. + * + * Input Parameters: + * tcb - A reference to the task control block of the task that needs to + * have a page fill. Architecture-specific logic can retrieve page + * fault information from the architecture-specific context + * information in this TCB to perform the mapping. + * + * Returned Value: + * This function will return zero (OK) if the allocation was successful. + * A negated errno value may be returned if an error occurs. All errors, + * however, are fatal. + * + * Assumptions: + * - This function is called from the normal tasking context (but with + * interrupts disabled). The implementation must take whatever actions + * are necessary to assure that the operation is safe within this + * context. + * + ****************************************************************************/ + +int up_allocpage(FAR struct tcb_s *tcb, FAR void **vpage) +{ + uintptr_t vaddr; + uintptr_t paddr; + uint32_t *pte; + unsigned int pgndx; + + /* Since interrupts are disabled, we don't need to anything special. */ + + DEBUGASSERT(tcb && vpage); + + /* Get the virtual address that caused the fault */ + + vaddr = tcb->xcp.far; + DEBUGASSERT(vaddr >= PG_PAGED_VBASE && vaddr < PG_PAGED_VEND); + + /* Allocate page memory to back up the mapping. Start by getting the + * index of the next page that we are going to allocate. + */ + + pgndx = g_pgndx++; + if (g_pgndx >= CONFIG_PAGING) + { + g_pgndx = 0; + g_pgwrap = true; + } + + /* Was this physical page previously mapped? If so, then we need to un-map + * it. + */ + + if (g_pgwrap) + { + /* Yes.. Get a pointer to the L2 entry corresponding to the previous + * mapping -- then zero it! + */ + + uintptr_t oldvaddr = PG_POOL_NDX2VA(g_ptemap[pgndx]); + pte = up_va2pte(oldvaddr); + *pte = 0; + + /* Invalidate the instruction TLB corresponding to the virtual address */ + + tlb_inst_invalidate_single(oldvaddr); + + /* I do not believe that it is necessary to flush the I-Cache in this + * case: The I-Cache uses a virtual address index and, hence, since the + * NuttX address space is flat, the cached instruction value should be + * correct even if the page mapping is no longer in place. + */ + } + + /* Then convert the index to a (physical) page address. */ + + paddr = PG_POOL_PGPADDR(pgndx); + + /* Now setup up the new mapping. Get a pointer to the L2 entry + * corresponding to the new mapping. Then set it map to the newly + * allocated page address. The inital mapping is read/write but + * non-cached (MMU_L2_ALLOCFLAGS) + */ + + pte = up_va2pte(vaddr); + *pte = (paddr | MMU_L2_ALLOCFLAGS); + + /* And save the new L1 index */ + + g_ptemap[pgndx] = PG_POOL_VA2L2NDX(vaddr); + + /* Finally, return the virtual address of allocated page */ + + *vpage = (void*)(vaddr & ~PAGEMASK); + return OK; +} + +#endif /* CONFIG_PAGING */ diff --git a/arch/arm/src/armv7-a/arm_assert.c b/arch/arm/src/armv7-a/arm_assert.c new file mode 100644 index 0000000000..a66d33c2e5 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_assert.c @@ -0,0 +1,304 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_assert.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Output debug info if stack dump is selected -- even if + * debug is not selected. + */ + +#ifdef CONFIG_ARCH_STACKDUMP +# undef lldbg +# define lldbg lowsyslog +#endif + +/* The following is just intended to keep some ugliness out of the mainline + * code. We are going to print the task name if: + * + * CONFIG_TASK_NAME_SIZE > 0 && <-- The task has a name + * (defined(CONFIG_DEBUG) || <-- And the debug is enabled (lldbg used) + * defined(CONFIG_ARCH_STACKDUMP) <-- Or lowsyslog() is used + */ + +#undef CONFIG_PRINT_TASKNAME +#if CONFIG_TASK_NAME_SIZE > 0 && (defined(CONFIG_DEBUG) || defined(CONFIG_ARCH_STACKDUMP)) +# define CONFIG_PRINT_TASKNAME 1 +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_getsp + ****************************************************************************/ + +/* I don't know if the builtin to get SP is enabled */ + +static inline uint32_t up_getsp(void) +{ + uint32_t sp; + __asm__ + ( + "\tmov %0, sp\n\t" + : "=r"(sp) + ); + return sp; +} + +/**************************************************************************** + * Name: up_stackdump + ****************************************************************************/ + +#ifdef CONFIG_ARCH_STACKDUMP +static void up_stackdump(uint32_t sp, uint32_t stack_base) +{ + uint32_t stack ; + + for (stack = sp & ~0x1f; stack < stack_base; stack += 32) + { + uint32_t *ptr = (uint32_t*)stack; + lldbg("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + stack, ptr[0], ptr[1], ptr[2], ptr[3], + ptr[4], ptr[5], ptr[6], ptr[7]); + } +} +#else +# define up_stackdump() +#endif + +/**************************************************************************** + * Name: up_registerdump + ****************************************************************************/ + +#ifdef CONFIG_ARCH_STACKDUMP +static inline void up_registerdump(void) +{ + /* Are user registers available from interrupt processing? */ + + if (current_regs) + { + int regs; + + /* Yes.. dump the interrupt registers */ + + for (regs = REG_R0; regs <= REG_R15; regs += 8) + { + uint32_t *ptr = (uint32_t*)¤t_regs[regs]; + lldbg("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n", + regs, ptr[0], ptr[1], ptr[2], ptr[3], + ptr[4], ptr[5], ptr[6], ptr[7]); + } + + lldbg("CPSR: %08x\n", current_regs[REG_CPSR]); + } +} +#else +# define up_registerdump() +#endif + +/**************************************************************************** + * Name: up_dumpstate + ****************************************************************************/ + +#ifdef CONFIG_ARCH_STACKDUMP +static void up_dumpstate(void) +{ + struct tcb_s *rtcb = (struct tcb_s*)g_readytorun.head; + uint32_t sp = up_getsp(); + uint32_t ustackbase; + uint32_t ustacksize; +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + uint32_t istackbase; + uint32_t istacksize; +#endif + + /* Get the limits on the user stack memory */ + + if (rtcb->pid == 0) + { + ustackbase = g_idle_topstack - 4; + ustacksize = CONFIG_IDLETHREAD_STACKSIZE; + } + else + { + ustackbase = (uint32_t)rtcb->adj_stack_ptr; + ustacksize = (uint32_t)rtcb->adj_stack_size; + } + + /* Get the limits on the interrupt stack memory */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + istackbase = (uint32_t)&g_userstack; + istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; + + /* Show interrupt stack info */ + + lldbg("sp: %08x\n", sp); + lldbg("IRQ stack:\n"); + lldbg(" base: %08x\n", istackbase); + lldbg(" size: %08x\n", istacksize); + + /* Does the current stack pointer lie within the interrupt + * stack? + */ + + if (sp <= istackbase && sp > istackbase - istacksize) + { + /* Yes.. dump the interrupt stack */ + + up_stackdump(sp, istackbase); + + /* Extract the user stack pointer which should lie + * at the base of the interrupt stack. + */ + + sp = g_userstack; + lldbg("sp: %08x\n", sp); + } + + /* Show user stack info */ + + lldbg("User stack:\n"); + lldbg(" base: %08x\n", ustackbase); + lldbg(" size: %08x\n", ustacksize); +#else + lldbg("sp: %08x\n", sp); + lldbg("stack base: %08x\n", ustackbase); + lldbg("stack size: %08x\n", ustacksize); +#endif + + /* Dump the user stack if the stack pointer lies within the allocated user + * stack memory. + */ + + if (sp > ustackbase || sp <= ustackbase - ustacksize) + { +#if !defined(CONFIG_ARCH_INTERRUPTSTACK) || CONFIG_ARCH_INTERRUPTSTACK < 4 + lldbg("ERROR: Stack pointer is not within allocated stack\n"); +#endif + } + else + { + up_stackdump(sp, ustackbase); + } + + /* Then dump the registers (if available) */ + + up_registerdump(); +} +#else +# define up_dumpstate() +#endif + +/**************************************************************************** + * Name: _up_assert + ****************************************************************************/ + +static void _up_assert(int errorcode) noreturn_function; +static void _up_assert(int errorcode) +{ + /* Are we in an interrupt handler or the idle task? */ + + if (current_regs || ((struct tcb_s*)g_readytorun.head)->pid == 0) + { + (void)irqsave(); + for(;;) + { +#ifdef CONFIG_ARCH_LEDS + up_ledon(LED_PANIC); + up_mdelay(250); + up_ledoff(LED_PANIC); + up_mdelay(250); +#endif + } + } + else + { + exit(errorcode); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_assert + ****************************************************************************/ + +void up_assert(const uint8_t *filename, int lineno) +{ +#ifdef CONFIG_PRINT_TASKNAME + struct tcb_s *rtcb = (struct tcb_s*)g_readytorun.head; +#endif + + up_ledon(LED_ASSERTION); + +#ifdef CONFIG_PRINT_TASKNAME + lldbg("Assertion failed at file:%s line: %d task: %s\n", + filename, lineno, rtcb->name); +#else + lldbg("Assertion failed at file:%s line: %d\n", + filename, lineno); +#endif + up_dumpstate(); + _up_assert(EXIT_FAILURE); +} diff --git a/arch/arm/src/armv7-a/arm_blocktask.c b/arch/arm/src/armv7-a/arm_blocktask.c new file mode 100644 index 0000000000..eac95984bc --- /dev/null +++ b/arch/arm/src/armv7-a/arm_blocktask.c @@ -0,0 +1,162 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/up_blocktask.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_block_task + * + * Description: + * The currently executing task at the head of + * the ready to run list must be stopped. Save its context + * and move it to the inactive list specified by task_state. + * + * Inputs: + * tcb: Refers to a task in the ready-to-run list (normally + * the task at the head of the list). It most be + * stopped, its context saved and moved into one of the + * waiting task lists. It it was the task at the head + * of the ready-to-run list, then a context to the new + * ready to run task must be performed. + * task_state: Specifies which waiting task list should be + * hold the blocked task TCB. + * + ****************************************************************************/ + +void up_block_task(struct tcb_s *tcb, tstate_t task_state) +{ + struct tcb_s *rtcb = (struct tcb_s*)g_readytorun.head; + bool switch_needed; + + /* Verify that the context switch can be performed */ + + ASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && + (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + + /* Remove the tcb task from the ready-to-run list. If we + * are blocking the task at the head of the task list (the + * most likely case), then a context switch to the next + * ready-to-run task is needed. In this case, it should + * also be true that rtcb == tcb. + */ + + switch_needed = sched_removereadytorun(tcb); + + /* Add the task to the specified blocked task list */ + + sched_addblocked(tcb, (tstate_t)task_state); + + /* If there are any pending tasks, then add them to the g_readytorun + * task list now + */ + + if (g_pendingtasks.head) + { + switch_needed |= sched_mergepending(); + } + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* Are we in an interrupt handler? */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (struct tcb_s*)g_readytorun.head; + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* Copy the user C context into the TCB at the (old) head of the + * g_readytorun Task list. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (struct tcb_s*)g_readytorun.head; + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } +} diff --git a/arch/arm/src/armv7-a/arm_checkmapping.c b/arch/arm/src/armv7-a/arm_checkmapping.c new file mode 100644 index 0000000000..50f05cf7ed --- /dev/null +++ b/arch/arm/src/armv7-a/arm_checkmapping.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_checkmapping.c + * Check if the current task's fault address has been mapped into the virtual + * address space. + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "up_internal.h" + +#ifdef CONFIG_PAGING + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_checkmapping() + * + * Description: + * The function up_checkmapping() returns an indication if the page fill + * still needs to performed or not. In certain conditions, the page fault + * may occur on several threads and be queued multiple times. This function + * will prevent the same page from be filled multiple times. + * + * Input Parameters: + * tcb - A reference to the task control block of the task that we believe + * needs to have a page fill. Architecture-specific logic can + * retrieve page fault information from the architecture-specific + * context information in this TCB and can consult processor resources + * (page tables or TLBs or ???) to determine if the fill still needs + * to be performed or not. + * + * Returned Value: + * This function will return true if the mapping is in place and false + * if the mapping is still needed. Errors encountered should be + * interpreted as fatal. + * + * Assumptions: + * - This function is called from the normal tasking context (but with + * interrupts disabled). The implementation must take whatever actions + * are necessary to assure that the operation is safe within this + * context. + * + ****************************************************************************/ + +bool up_checkmapping(FAR struct tcb_s *tcb) +{ + uintptr_t vaddr; + uint32_t *pte; + + /* Since interrupts are disabled, we don't need to anything special. */ + + DEBUGASSERT(tcb); + + /* Get the virtual address that caused the fault */ + + vaddr = tcb->xcp.far; + DEBUGASSERT(vaddr >= PG_PAGED_VBASE && vaddr < PG_PAGED_VEND); + + /* Get the PTE associated with this virtual address */ + + pte = up_va2pte(vaddr); + + /* Return true if this virtual address is mapped. */ + + return (*pte != 0); +} + +#endif /* CONFIG_PAGING */ diff --git a/arch/arm/src/armv7-a/arm_copystate.c b/arch/arm/src/armv7-a/arm_copystate.c new file mode 100644 index 0000000000..42c46628d5 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_copystate.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_copystate.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_copystate + ****************************************************************************/ + +/* A little faster than most memcpy's */ + +void up_copystate(uint32_t *dest, uint32_t *src) +{ + int i; + + /* In the current ARM model, the state is always copied to and from the + * stack and TCB. + */ + + for (i = 0; i < XCPTCONTEXT_REGS; i++) + { + *dest++ = *src++; + } +} + diff --git a/arch/arm/src/armv7-a/arm_dataabort.c b/arch/arm/src/armv7-a/arm_dataabort.c new file mode 100644 index 0000000000..dc39ac2c38 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_dataabort.c @@ -0,0 +1,201 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_dataabort.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "os_internal.h" +#include "up_internal.h" + +#ifdef CONFIG_PAGING +# include +# include "arm.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Output debug info if stack dump is selected -- even if + * debug is not selected. + */ + +#ifdef CONFIG_ARCH_STACKDUMP +# undef lldbg +# define lldbg lowsyslog +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_dataabort + * + * Input parameters: + * regs - The standard, ARM register save array. + * + * If CONFIG_PAGING is selected in the NuttX configuration file, then these + * additional input values are expected: + * + * far - Fault address register. On a data abort, the ARM MMU places the + * miss virtual address (MVA) into the FAR register. This is the address + * of the data which, when accessed, caused the fault. + * fsr - Fault status register. On a data a abort, the ARM MMU places an + * encoded four-bit value, the fault status, along with the four-bit + * encoded domain number, in the data FSR + * + * Description: + * This is the data abort exception handler. The ARM data abort exception + * occurs when a memory fault is detected during a data transfer. + * + ****************************************************************************/ + +#ifdef CONFIG_PAGING +void arm_dataabort(uint32_t *regs, uint32_t far, uint32_t fsr) +{ + FAR struct tcb_s *tcb = (FAR struct tcb_s *)g_readytorun.head; +#ifdef CONFIG_PAGING + uint32_t *savestate; + + /* Save the saved processor context in current_regs where it can be accessed + * for register dumps and possibly context switching. + */ + + + savestate = (uint32_t*)current_regs; +#endif + current_regs = regs; + +#ifdef CONFIG_PAGING + /* In the NuttX on-demand paging implementation, only the read-only, .text + * section is paged. However, the ARM compiler generated PC-relative data + * fetches from within the .text sections. Also, it is customary to locate + * read-only data (.rodata) within the same section as .text so that it + * does not require copying to RAM. Misses in either of these case should + * cause a data abort. + * + * We are only interested in data aborts due to page translations faults. + * Sections should already be in place and permissions should already be + * be set correctly (to read-only) so any other data abort reason is a + * fatal error. + */ + + pglldbg("FSR: %08x FAR: %08x\n", fsr, far); + if ((fsr & FSR_MASK) != FSR_PAGE) + { + goto segfault; + } + + /* Check the (virtual) address of data that caused the data abort. When + * the exception occurred, this address was provided in the FAR register. + * (It has not yet been saved in the register context save area). + */ + + pgllvdbg("VBASE: %08x VEND: %08x\n", PG_PAGED_VBASE, PG_PAGED_VEND); + if (far < PG_PAGED_VBASE || far >= PG_PAGED_VEND) + { + goto segfault; + } + + /* Save the offending data address as the fault address in the TCB of + * the currently task. This fault address is also used by the prefetch + * abort handling; this will allow common paging logic for both + * prefetch and data aborts. + */ + + tcb->xcp.far = regs[REG_R15]; + + /* Call pg_miss() to schedule the page fill. A consequences of this + * call are: + * + * (1) The currently executing task will be blocked and saved on + * on the g_waitingforfill task list. + * (2) An interrupt-level context switch will occur so that when + * this function returns, it will return to a different task, + * most likely the page fill worker thread. + * (3) The page fill worker task has been signalled and should + * execute immediately when we return from this exception. + */ + + pg_miss(); + + /* Restore the previous value of current_regs. NULL would indicate that + * we are no longer in an interrupt handler. It will be non-NULL if we + * are returning from a nested interrupt. + */ + + current_regs = savestate; + return; + +segfault: +#endif + lldbg("Data abort. PC: %08x FAR: %08x FSR: %08x\n", regs[REG_PC], far, fsr); + PANIC(); +} + +#else /* CONFIG_PAGING */ + +void arm_dataabort(uint32_t *regs) +{ + /* Save the saved processor context in current_regs where it can be accessed + * for register dumps and possibly context switching. + */ + + current_regs = regs; + + /* Crash -- possibly showing diagnost debug information. */ + + lldbg("Data abort. PC: %08x\n", regs[REG_PC]); + PANIC(); +} + +#endif /* CONFIG_PAGING */ diff --git a/arch/arm/src/armv7-a/arm_doirq.c b/arch/arm/src/armv7-a/arm_doirq.c new file mode 100644 index 0000000000..eec228b914 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_doirq.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_doirq.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void up_doirq(int irq, uint32_t *regs) +{ + up_ledon(LED_INIRQ); +#ifdef CONFIG_SUPPRESS_INTERRUPTS + PANIC(); +#else + uint32_t *savestate; + + /* Nested interrupts are not supported in this implementation. If you want + * to implement nested interrupts, you would have to (1) change the way that + * current_regs is handled and (2) the design associated with + * CONFIG_ARCH_INTERRUPTSTACK. The savestate variable will not work for + * that purpose as implemented here because only the outermost nested + * interrupt can result in a context switch (it can probably be deleted). + */ + + /* Current regs non-zero indicates that we are processing an interrupt; + * current_regs is also used to manage interrupt level context switches. + */ + + savestate = (uint32_t*)current_regs; + current_regs = regs; + + /* Mask and acknowledge the interrupt */ + + up_maskack_irq(irq); + + /* Deliver the IRQ */ + + irq_dispatch(irq, regs); + + /* Restore the previous value of current_regs. NULL would indicate that + * we are no longer in an interrupt handler. It will be non-NULL if we + * are returning from a nested interrupt. + */ + + current_regs = savestate; + + /* Unmask the last interrupt (global interrupts are still disabled) */ + + up_enable_irq(irq); +#endif + up_ledoff(LED_INIRQ); +} diff --git a/arch/arm/src/armv7-a/arm_elf.c b/arch/arm/src/armv7-a/arm_elf.c new file mode 100644 index 0000000000..3a9b86a8ae --- /dev/null +++ b/arch/arm/src/armv7-a/arm_elf.c @@ -0,0 +1,257 @@ +/**************************************************************************** + * arch/arm/src/armv-7a/arm_elf.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arch_checkarch + * + * Description: + * Given the ELF header in 'hdr', verify that the ELF file is appropriate + * for the current, configured architecture. Every architecture that uses + * the ELF loader must provide this function. + * + * Input Parameters: + * hdr - The ELF header read from the ELF file. + * + * Returned Value: + * True if the architecture supports this ELF file. + * + ****************************************************************************/ + +bool arch_checkarch(FAR const Elf32_Ehdr *ehdr) +{ + /* Make sure it's an ARM executable */ + + if (ehdr->e_machine != EM_ARM) + { + bdbg("Not for ARM: e_machine=%04x\n", ehdr->e_machine); + return -ENOEXEC; + } + + /* Make sure that 32-bit objects are supported */ + + if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) + { + bdbg("Need 32-bit objects: e_ident[EI_CLASS]=%02x\n", ehdr->e_ident[EI_CLASS]); + return -ENOEXEC; + } + + /* Verify endian-ness */ + +#ifdef CONFIG_ENDIAN_BIG + if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) +#else + if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) +#endif + { + bdbg("Wrong endian-ness: e_ident[EI_DATA]=%02x\n", ehdr->e_ident[EI_DATA]); + return -ENOEXEC; + } + + /* Make sure the entry point address is properly aligned */ + + if ((ehdr->e_entry & 3) != 0) + { + bdbg("Entry point is not properly aligned: %08x\n", ehdr->e_entry); + return -ENOEXEC + } + + /* TODO: Check ABI here. */ + return OK; +} + +/**************************************************************************** + * Name: arch_relocate and arch_relocateadd + * + * Description: + * Perform on architecture-specific ELF relocation. Every architecture + * that uses the ELF loader must provide this function. + * + * Input Parameters: + * rel - The relocation type + * sym - The ELF symbol structure containing the fully resolved value. + * addr - The address that requires the relocation. + * + * Returned Value: + * Zero (OK) if the relocation was successful. Otherwise, a negated errno + * value indicating the cause of the relocation failure. + * + ****************************************************************************/ + +int arch_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym, + uintptr_t addr) +{ + int32_t offset; + + switch (ELF32_R_TYPE(rel->r_info)) + { + case R_ARM_NONE: + { + /* No relocation */ + } + break; + + case R_ARM_PC24: + case R_ARM_CALL: + case R_ARM_JUMP24: + { + bvdbg("Performing PC24 [%d] link at addr %08lx [%08lx] to sym '%s' st_value=%08lx\n", + ELF32_R_TYPE(rel->r_info), (long)addr, (long)(*(uint32_t*)addr), + sym, (long)sym->st_value); + + offset = (*(uint32_t*)addr & 0x00ffffff) << 2; + if (offset & 0x02000000) + { + offset -= 0x04000000; + } + + offset += sym->st_value - addr; + if (offset & 3 || offset <= (int32_t) 0xfe000000 || offset >= (int32_t) 0x02000000) + { + bdbg(" ERROR: PC24 [%d] relocation out of range, offset=%08lx\n", + ELF32_R_TYPE(rel->r_info), offset); + + return -EINVAL; + } + + offset >>= 2; + + *(uint32_t*)addr &= 0xff000000; + *(uint32_t*)addr |= offset & 0x00ffffff; + } + break; + + case R_ARM_ABS32: + case R_ARM_TARGET1: /* New ABI: TARGET1 always treated as ABS32 */ + { + bvdbg("Performing ABS32 link at addr=%08lx [%08lx] to sym=%p st_value=%08lx\n", + (long)addr, (long)(*(uint32_t*)addr), sym, (long)sym->st_value); + + *(uint32_t*)addr += sym->st_value; + } + break; + + case R_ARM_V4BX: + { + bvdbg("Performing V4BX link at addr=%08lx [%08lx]\n", + (long)addr, (long)(*(uint32_t*)addr)); + + /* Preserve only Rm and the condition code */ + + *(uint32_t*)addr &= 0xf000000f; + + /* Change instruction to 'mov pc, Rm' */ + + *(uint32_t*)addr |= 0x01a0f000; + } + break; + + case R_ARM_PREL31: + { + bvdbg("Performing PREL31 link at addr=%08lx [%08lx] to sym=%p st_value=%08lx\n", + (long)addr, (long)(*(uint32_t*)addr), sym, (long)sym->st_value); + + offset = *(uint32_t*)addr + sym->st_value - addr; + *(uint32_t*)addr = offset & 0x7fffffff; + } + break; + + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVT_ABS: + { + bvdbg("Performing MOVx_ABS [%d] link at addr=%08lx [%08lx] to sym=%p st_value=%08lx\n", + ELF32_R_TYPE(rel->r_info), (long)addr, (long)(*(uint32_t*)addr), + sym, (long)sym->st_value); + + offset = *(uint32_t*)addr; + offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff); + offset = (offset ^ 0x8000) - 0x8000; + + offset += sym->st_value; + if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS) + { + offset >>= 16; + } + + *(uint32_t*)addr &= 0xfff0f000; + *(uint32_t*)addr |= ((offset & 0xf000) << 4) | (offset & 0x0fff); + } + break; + + default: + bdbg("Unsupported relocation: %d\n", ELF32_R_TYPE(rel->r_info)); + return -EINVAL; + } + + return OK; +} + +int arch_relocateadd(FAR const Elf32_Rela *rel, FAR const Elf32_Sym *sym, + uintptr_t addr) +{ + bdbg("RELA relocation not supported\n"); + return -ENOSYS; +} + diff --git a/arch/arm/src/armv7-a/arm_fullcontextrestore.S b/arch/arm/src/armv7-a/arm_fullcontextrestore.S new file mode 100644 index 0000000000..6b01256122 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_fullcontextrestore.S @@ -0,0 +1,117 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_fullcontextrestore.S + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "up_internal.h" + + .file "arm_fullcontextrestore.S" + +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .globl up_fullcontextrestore + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_fullcontextrestore + ****************************************************************************/ + + .globl up_fullcontextrestore + .type up_fullcontextrestore, function +up_fullcontextrestore: + + /* On entry, a1 (r0) holds address of the register save area */ + + /* Recover all registers except for r0, r1, R15, and CPSR */ + + add r1, r0, #(4*REG_R2) /* Offset to REG_R2 storage */ + ldmia r1, {r2-r14} /* Recover registers */ + + /* Create a stack frame to hold the PC */ + + sub sp, sp, #(3*4) /* Frame for three registers */ + ldr r1, [r0, #(4*REG_R0)] /* Fetch the stored r0 value */ + str r1, [sp] /* Save it at the top of the stack */ + ldr r1, [r0, #(4*REG_R1)] /* Fetch the stored r1 value */ + str r1, [sp, #4] /* Save it in the stack */ + ldr r1, [r0, #(4*REG_PC)] /* Fetch the stored pc value */ + str r1, [sp, #8] /* Save it at the bottom of the frame */ + + /* Now we can restore the CPSR. We wait until we are completely + * finished with the context save data to do this. Restore the CPSR + * may re-enable and interrupts and we could be in a context + * where the save structure is only protected by interrupts being + * disabled. + */ + + ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the stored CPSR value */ + msr cpsr, r1 /* Set the CPSR */ + + /* Now recover r0 and r1 */ + + ldr r0, [sp] + ldr r1, [sp, #4] + add sp, sp, #(2*4) + + /* Then return to the address at the stop of the stack, + * destroying the stack frame + */ + + ldr pc, [sp], #4 + .size up_fullcontextrestore, . - up_fullcontextrestore diff --git a/arch/arm/src/armv7-a/arm_head.S b/arch/arm/src/armv7-a/arm_head.S index f0d4b0da1d..df6981085a 100644 --- a/arch/arm/src/armv7-a/arm_head.S +++ b/arch/arm/src/armv7-a/arm_head.S @@ -46,6 +46,7 @@ #include "arm.h" #include "cp15.h" +#include "sctlr.h" /********************************************************************************** * Configuration @@ -355,77 +356,105 @@ __start: ldr lr, .LCvstart /* Abs. virtual address */ + /* Configure the domain access register (see mmu.h) */ + mov r0, #0x1f /* Domains 0, 1 = client */ - mcr p15, 0, r0, c3, c0 /* Load domain access register */ - mrc p15, 0, r0, c1, c0 /* Get control register */ + mcr CP15_DACR(r0) /* Load domain access register */ - /* Clear bits (see arm.h) + /* Configure the system control register (see sctrl.h) */ + + mrc CP15_SCTLR(r0) /* Get control register */ + + /* Clear bits to reset values. This is only necessary in situations like, for + * example, we get here via a bootloader and the control register is in some + * unknown state. * - * CR_R - ROM MMU protection - * CR_F - Implementation defined - * CR_Z - Implementation defined + * SCTLR_A Bit 1: Strict alignment disabled (reset value) + * SCTLR_C Bit 2: DCache disabled (reset value) * - * CR_A - Alignment abort enable - * CR_C - Dcache enable - * CR_W - Write buffer enable + * SCTLR_SW Bit 10: SWP/SWPB not enabled (reset value) + * SCTLR_I Bit 12: ICache disabled (reset value) + * SCTLR_V Bit 13: Assume low vectors (reset value) + * SCTLR_RR Bit 14: The Cortex-A5 processor only supports a fixed random + * replacement strategy. + * SCTLR_HA Bit 17: Not supported by A5 * - * CR_I - Icache enable + * SCTLR_EE Bit 25: Little endian (reset value). + * SCTLR_TRE Bit 28: No memory region remapping (reset value) + * SCTLR_AFE Bit 29: Full, legacy access permissions behavior (reset value). + * SCTLR_TE Bit 30: All exceptions handled in ARM state (reset value). */ - bic r0, r0, #(CR_R|CR_F|CR_Z) - bic r0, r0, #(CR_A|CR_C|CR_W) - bic r0, r0, #(CR_I) + bic r0, r0, #(SCTLR_A | SCTLR_C) + bic r0, r0, #(SCTLR_SW | SCTLR_I | SCTLR_V | SCTLR_RR | SCTLR_HA) + bic r0, r0, #(SCTLR_EE | SCTLR_TRE | SCTLR_AFE | SCTLR_TE) - /* Set bits (see arm.h) + /* Set bits to enable the MMU * - * CR_M - MMU enable - * CR_P - 32-bit exception handler - * CR_D - 32-bit data address range + * SCTLR_M Bit 0: Enable the MMU + * SCTLR_Z Bit 11: Program flow prediction control always enabled on A5 */ - orr r0, r0, #(CR_M|CR_P|CR_D) + orr r0, r0, #(SCTLR_M /* | SCTLR_Z */) - /* In most architectures, vectors are relocated to 0xffff0000. - * -- but not all + /* Position vectors to 0xffff0000 if so configured. * - * CR_S - System MMU protection - * CR_V - Vectors relocated to 0xffff0000 + * SCTLR_V Bit 13: High vectors */ #ifndef CONFIG_ARCH_LOWVECTORS - orr r0, r0, #(CR_S|CR_V) -#else - orr r0, r0, #(CR_S) + orr r0, r0, #(SCTLR_V) #endif - /* CR_RR - Round Robin cache replacement */ -#ifdef CPU_CACHE_ROUND_ROBIN - orr r0, r0, #(CR_RR) + /* CR_RR - Round Robin cache replacement + * + * SCTLR_RR Bit 14: The Cortex-A5 processor only supports a fixed random + * replacement strategy. + */ + +#ifndef CPU_CACHE_ROUND_ROBIN #endif - /* CR_C - Dcache enable */ + + /* CR_C - Dcache enable + * + * SCTLR_C Bit 2: DCache enable + */ #ifndef CPU_DCACHE_DISABLE - orr r0, r0, #(CR_C) + orr r0, r0, #(SCTLR_C) #endif - /* CR_C - Dcache enable */ + + /* CR_C - Icache enable + * + * SCTLR_I Bit 12: ICache enable + */ #ifndef CPU_ICACHE_DISABLE - orr r0, r0, #(CR_I) + orr r0, r0, #(SCTLR_I) #endif - /* CR_A - Alignment abort enable */ + + /* CR_A - Alignment abort enable + * + * SCTLR_A Bit 1: Strict alignment enabled + */ #ifdef ALIGNMENT_TRAP - orr r0, r0, #(CR_A) + orr r0, r0, #(SCTLR_A) #endif - mcr p15, 0, r0, c1, c0, 0 /* write control reg */ - /* Get TMP=2 Processor ID register */ + /* Then write the configured control register */ - mrc p15, 0, r1, c0, c0, 0 /* read id reg */ - mov r1,r1 /* Null-avoiding nop */ - mov r1,r1 /* Null-avoiding nop */ + mcr CP15_SCTLR(r0) /* Write control reg */ - /* And "jump" to .Lvstart */ + /* Read the Main ID register. This will be available in R1 after + * MMU trampoline (not currently used) + */ + + mrc CP15_MIDR(r1) /* Read main id reg */ + mov r1, r1 /* Null-avoiding nop */ + mov r1, r1 /* Null-avoiding nop */ + + /* And "jump" to .Lvstart in the newly mapped virtual address space */ mov pc, lr @@ -433,7 +462,7 @@ __start: * PC_Relative Data ****************************************************************************/ - /* Most addresses are all virtual address */ + /* Most addresses are virtual address */ .type .LCvstart, %object .LCvstart: diff --git a/arch/arm/src/armv7-a/arm_initialstate.c b/arch/arm/src/armv7-a/arm_initialstate.c new file mode 100644 index 0000000000..110faf3057 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_initialstate.c @@ -0,0 +1,146 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_initialstate.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "arm.h" +#include "up_internal.h" +#include "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_initial_state + * + * Description: + * A new thread is being started and a new TCB + * has been created. This function is called to initialize + * the processor specific portions of the new TCB. + * + * This function must setup the intial architecture registers + * and/or stack so that execution will begin at tcb->start + * on the next context switch. + * + ****************************************************************************/ + +void up_initial_state(struct tcb_s *tcb) +{ + struct xcptcontext *xcp = &tcb->xcp; + uint32_t cpsr; + + /* Initialize the initial exception register context structure */ + + memset(xcp, 0, sizeof(struct xcptcontext)); + + /* Save the initial stack pointer */ + + xcp->regs[REG_SP] = (uint32_t)tcb->adj_stack_ptr; + + /* Save the task entry point */ + + xcp->regs[REG_PC] = (uint32_t)tcb->start; + + /* If this task is running PIC, then set the PIC base register to the + * address of the allocated D-Space region. + */ + +#ifdef CONFIG_PIC + if (tcb->dspace != NULL) + { + /* Set the PIC base register (probably R10) to the address of the + * alloacated D-Space region. + */ + + xcp->regs[REG_PIC] = (uint32_t)tcb->dspace->region; + } +#endif + + /* Set supervisor- or user-mode, depending on how NuttX is configured and + * what kind of thread is being started. Disable FIQs in any event + */ + +#ifdef CONFIG_NUTTX_KERNEL + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL) + { + /* It is a kernel thread.. set supervisor mode */ + + cpsr = PSR_MODE_SUPER | PSR_F_BIT; + } + else + { + /* It is a normal task or a pthread. Set user mode */ + + cpsr = PSR_MODE_USER | PSR_F_BIT; + } +#else + /* If the kernel build is not selected, then all threads run in + * supervisor-mode. + */ + + cpsr = PSR_MODE_SUPER | PSR_F_BIT; +#endif + + /* Enable or disable interrupts, based on user configuration */ + +# ifdef CONFIG_SUPPRESS_INTERRUPTS + cpsr |= PSR_I_BIT; +# endif + + xcp->regs[REG_CPSR] = cpsr; +} + diff --git a/arch/arm/src/armv7-a/arm_pginitialize.c b/arch/arm/src/armv7-a/arm_pginitialize.c new file mode 100644 index 0000000000..f419a28ba4 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_pginitialize.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_pginitialize.c + * Initialize the MMU for on-demand paging support. + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "up_internal.h" + +#ifdef CONFIG_PAGING + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_pginitialize() + * + * Description: + * Initialize the MMU for on-demand paging support.. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. This function will crash if any errors are detected during MMU + * initialization + * + * Assumptions: + * - Called early in the platform initialization sequence so that no special + * concurrency protection is required. + * + ****************************************************************************/ + +void up_pginitialize(void) +{ + /* None needed at present. This file is just retained in case the need + * arises in the future. Nothing calls up_pginitialize() now. If needed, + * if should be called early in up_boot.c to assure that all paging is + * ready. + */ +} + +#endif /* CONFIG_PAGING */ diff --git a/arch/arm/src/armv7-a/arm_prefetchabort.c b/arch/arm/src/armv7-a/arm_prefetchabort.c new file mode 100644 index 0000000000..c98bc46ec8 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_prefetchabort.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_prefetchabort.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#ifdef CONFIG_PAGING +# include +#endif + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Debug ********************************************************************/ + +/* Output debug info if stack dump is selected -- even if + * debug is not selected. + */ + +#ifdef CONFIG_ARCH_STACKDUMP +# undef lldbg +# define lldbg lowsyslog +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_prefetchabort + * + * Description; + * This is the prefetch abort exception handler. The ARM prefetch abort + * exception occurs when a memory fault is detected during an an + * instruction fetch. + * + ****************************************************************************/ + +void arm_prefetchabort(uint32_t *regs) +{ +#ifdef CONFIG_PAGING + uint32_t *savestate; + + /* Save the saved processor context in current_regs where it can be accessed + * for register dumps and possibly context switching. + */ + + savestate = (uint32_t*)current_regs; +#endif + current_regs = regs; + +#ifdef CONFIG_PAGING + /* Get the (virtual) address of instruction that caused the prefetch abort. + * When the exception occurred, this address was provided in the lr register + * and this value was saved in the context save area as the PC at the + * REG_R15 index. + * + * Check to see if this miss address is within the configured range of + * virtual addresses. + */ + + pglldbg("VADDR: %08x VBASE: %08x VEND: %08x\n", + regs[REG_PC], PG_PAGED_VBASE, PG_PAGED_VEND); + + if (regs[REG_R15] >= PG_PAGED_VBASE && regs[REG_R15] < PG_PAGED_VEND) + { + /* Save the offending PC as the fault address in the TCB of the currently + * executing task. This value is, of course, already known in regs[REG_R15], + * but saving it in this location will allow common paging logic for both + * prefetch and data aborts. + */ + + FAR struct tcb_s *tcb = (FAR struct tcb_s *)g_readytorun.head; + tcb->xcp.far = regs[REG_R15]; + + /* Call pg_miss() to schedule the page fill. A consequences of this + * call are: + * + * (1) The currently executing task will be blocked and saved on + * on the g_waitingforfill task list. + * (2) An interrupt-level context switch will occur so that when + * this function returns, it will return to a different task, + * most likely the page fill worker thread. + * (3) The page fill worker task has been signalled and should + * execute immediately when we return from this exception. + */ + + pg_miss(); + + /* Restore the previous value of current_regs. NULL would indicate that + * we are no longer in an interrupt handler. It will be non-NULL if we + * are returning from a nested interrupt. + */ + + current_regs = savestate; + } + else +#endif + { + lldbg("Prefetch abort. PC: %08x\n", regs[REG_PC]); + PANIC(); + } +} diff --git a/arch/arm/src/armv7-a/arm_releasepending.c b/arch/arm/src/armv7-a/arm_releasepending.c new file mode 100644 index 0000000000..4dccc7e099 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_releasepending.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_releasepending.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_release_pending + * + * Description: + * Release and ready-to-run tasks that have + * collected in the pending task list. This can call a + * context switch if a new task is placed at the head of + * the ready to run list. + * + ****************************************************************************/ + +void up_release_pending(void) +{ + struct tcb_s *rtcb = (struct tcb_s*)g_readytorun.head; + + slldbg("From TCB=%p\n", rtcb); + + /* Merge the g_pendingtasks list into the g_readytorun task list */ + + /* sched_lock(); */ + if (sched_mergepending()) + { + /* The currently active task has changed! We will need to + * switch contexts. First check if we are operating in + * interrupt context: + */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (struct tcb_s*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* Copy the exception context into the TCB of the task that + * was currently active. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task + * restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (struct tcb_s*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } +} diff --git a/arch/arm/src/armv7-a/arm_reprioritizertr.c b/arch/arm/src/armv7-a/arm_reprioritizertr.c new file mode 100644 index 0000000000..2055d395bd --- /dev/null +++ b/arch/arm/src/armv7-a/arm_reprioritizertr.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_reprioritizertr.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_reprioritize_rtr + * + * Description: + * Called when the priority of a running or + * ready-to-run task changes and the reprioritization will + * cause a context switch. Two cases: + * + * 1) The priority of the currently running task drops and the next + * task in the ready to run list has priority. + * 2) An idle, ready to run task's priority has been raised above the + * the priority of the current, running task and it now has the + * priority. + * + * Inputs: + * tcb: The TCB of the task that has been reprioritized + * priority: The new task priority + * + ****************************************************************************/ + +void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) +{ + /* Verify that the caller is sane */ + + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE +#if SCHED_PRIORITY_MIN > 0 + || priority < SCHED_PRIORITY_MIN +#endif +#if SCHED_PRIORITY_MAX < UINT8_MAX + || priority > SCHED_PRIORITY_MAX +#endif + ) + { + PANIC(); + } + else + { + struct tcb_s *rtcb = (struct tcb_s*)g_readytorun.head; + bool switch_needed; + + slldbg("TCB=%p PRI=%d\n", tcb, priority); + + /* Remove the tcb task from the ready-to-run list. + * sched_removereadytorun will return true if we just + * remove the head of the ready to run list. + */ + + switch_needed = sched_removereadytorun(tcb); + + /* Setup up the new task priority */ + + tcb->sched_priority = (uint8_t)priority; + + /* Return the task to the specified blocked task list. + * sched_addreadytorun will return true if the task was + * added to the new list. We will need to perform a context + * switch only if the EXCLUSIVE or of the two calls is non-zero + * (i.e., one and only one the calls changes the head of the + * ready-to-run list). + */ + + switch_needed ^= sched_addreadytorun(tcb); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* If we are going to do a context switch, then now is the right + * time to add any pending tasks back into the ready-to-run list. + * task list now + */ + + if (g_pendingtasks.head) + { + sched_mergepending(); + } + + /* Are we in an interrupt handler? */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (struct tcb_s*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* Copy the exception context into the TCB at the (old) head of the + * g_readytorun Task list. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (struct tcb_s*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } + } +} diff --git a/arch/arm/src/armv7-a/arm_saveusercontext.S b/arch/arm/src/armv7-a/arm_saveusercontext.S new file mode 100644 index 0000000000..427a087659 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_saveusercontext.S @@ -0,0 +1,118 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_saveusercontext.S + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "up_internal.h" + + .file "arm_saveusercontext.S" + +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .globl up_saveusercontext + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_saveusercontext + ****************************************************************************/ + + .text + .globl up_saveusercontext + .type up_saveusercontext, function +up_saveusercontext: + /* On entry, a1 (r0) holds address of struct xcptcontext. + * Offset to the user region. + */ + + /* Make sure that the return value will be non-zero (the + * value of the other volatile registers don't matter -- + * r1-r3, ip). This function is called throught the + * normal C calling conventions and the values of these + * registers cannot be assumed at the point of setjmp + * return. + */ + + mov ip, #1 + str ip, [r0, #(4*REG_R0)] + + /* Save the volatile registers (plus r12 which really + * doesn't need to be saved) + */ + + add r1, r0, #(4*REG_R4) + stmia r1, {r4-r14} + + /* Save the current cpsr */ + + mrs r2, cpsr /* R3 = CPSR value */ + add r1, r0, #(4*REG_CPSR) + str r2, [r1] + + /* Finally save the return address as the PC so that we + * return to the exit from this function. + */ + + add r1, r0, #(4*REG_PC) + str lr, [r1] + + /* Return 0 */ + + mov r0, #0 /* Return value == 0 */ + mov pc, lr /* Return */ + .size up_saveusercontext, . - up_saveusercontext diff --git a/arch/arm/src/armv7-a/arm_schedulesigaction.c b/arch/arm/src/armv7-a/arm_schedulesigaction.c new file mode 100644 index 0000000000..6516af7913 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_schedulesigaction.c @@ -0,0 +1,204 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_schedulesigaction.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "arm.h" +#include "os_internal.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_schedule_sigaction + * + * Description: + * This function is called by the OS when one or more + * signal handling actions have been queued for execution. + * The architecture specific code must configure things so + * that the 'igdeliver' callback is executed on the thread + * specified by 'tcb' as soon as possible. + * + * This function may be called from interrupt handling logic. + * + * This operation should not cause the task to be unblocked + * nor should it cause any immediate execution of sigdeliver. + * Typically, a few cases need to be considered: + * + * (1) This function may be called from an interrupt handler + * During interrupt processing, all xcptcontext structures + * should be valid for all tasks. That structure should + * be modified to invoke sigdeliver() either on return + * from (this) interrupt or on some subsequent context + * switch to the recipient task. + * (2) If not in an interrupt handler and the tcb is NOT + * the currently executing task, then again just modify + * the saved xcptcontext structure for the recipient + * task so it will invoke sigdeliver when that task is + * later resumed. + * (3) If not in an interrupt handler and the tcb IS the + * currently executing task -- just call the signal + * handler now. + * + ****************************************************************************/ + +void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +{ + /* Refuse to handle nested signal actions */ + + sdbg("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); + + if (!tcb->xcp.sigdeliver) + { + irqstate_t flags; + + /* Make sure that interrupts are disabled */ + + flags = irqsave(); + + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ + + sdbg("rtcb=0x%p current_regs=0x%p\n", g_readytorun.head, current_regs); + + if (tcb == (struct tcb_s*)g_readytorun.head) + { + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. + */ + + if (!current_regs) + { + /* In this case just deliver the signal now. */ + + sigdeliver(tcb); + } + + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * current_regs does not refer to the thread at g_readytorun.head! + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = current_regs[REG_PC]; + tcb->xcp.saved_cpsr = current_regs[REG_CPSR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + current_regs[REG_PC] = (uint32_t)up_sigdeliver; + current_regs[REG_CPSR] = PSR_MODE_SUPER | PSR_I_BIT | PSR_F_BIT; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + up_savestate(tcb->xcp.regs); + } + } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver; + tcb->xcp.regs[REG_CPSR] = PSR_MODE_SUPER | PSR_I_BIT | PSR_F_BIT; + } + + irqrestore(flags); + } +} + +#endif /* !CONFIG_DISABLE_SIGNALS */ diff --git a/arch/arm/src/armv7-a/arm_sigdeliver.c b/arch/arm/src/armv7-a/arm_sigdeliver.c new file mode 100644 index 0000000000..d2ad984748 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_sigdeliver.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_sigdeliver.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_sigdeliver + * + * Description: + * This is the a signal handling trampoline. When a signal action was + * posted. The task context was mucked with and forced to branch to this + * location with interrupts disabled. + * + ****************************************************************************/ + +void up_sigdeliver(void) +{ + struct tcb_s *rtcb = (struct tcb_s*)g_readytorun.head; + uint32_t regs[XCPTCONTEXT_REGS]; + sig_deliver_t sigdeliver; + + /* Save the errno. This must be preserved throughout the signal handling + * so that the user code final gets the correct errno value (probably + * EINTR). + */ + + int saved_errno = rtcb->pterrno; + + up_ledon(LED_SIGNAL); + + sdbg("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", + rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); + ASSERT(rtcb->xcp.sigdeliver != NULL); + + /* Save the real return state on the stack. */ + + up_copystate(regs, rtcb->xcp.regs); + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_CPSR] = rtcb->xcp.saved_cpsr; + + /* Get a local copy of the sigdeliver function pointer. we do this so that + * we can nullify the sigdeliver function pointer in the TCB and accept + * more signal deliveries while processing the current pending signals. + */ + + sigdeliver = rtcb->xcp.sigdeliver; + rtcb->xcp.sigdeliver = NULL; + + /* Then restore the task interrupt state */ + + irqrestore(regs[REG_CPSR]); + + /* Deliver the signals */ + + sigdeliver(rtcb); + + /* Output any debug messages BEFORE restoring errno (because they may + * alter errno), then disable interrupts again and restore the original + * errno that is needed by the user logic (it is probably EINTR). + */ + + sdbg("Resuming\n"); + (void)irqsave(); + rtcb->pterrno = saved_errno; + + /* Then restore the correct state for this thread of execution. */ + + up_ledoff(LED_SIGNAL); + up_fullcontextrestore(regs); +} + +#endif /* !CONFIG_DISABLE_SIGNALS */ + diff --git a/arch/arm/src/armv7-a/arm_syscall.c b/arch/arm/src/armv7-a/arm_syscall.c new file mode 100644 index 0000000000..c3e6b2174a --- /dev/null +++ b/arch/arm/src/armv7-a/arm_syscall.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_syscall.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Output debug info if stack dump is selected -- even if + * debug is not selected. + */ + +#ifdef CONFIG_ARCH_STACKDUMP +# undef lldbg +# define lldbg lowsyslog +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * vectors + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_syscall + * + * Description: + * SWI interrupts will vection here with insn=the SWI + * instruction and xcp=the interrupt context + * + * The handler may get the SWI number be de-referencing + * the return address saved in the xcp and decoding + * the SWI instruction + * + ****************************************************************************/ + +void up_syscall(uint32_t *regs) +{ + lldbg("Syscall from 0x%x\n", regs[REG_PC]); + current_regs = regs; + PANIC(); +} diff --git a/arch/arm/src/armv7-a/arm_unblocktask.c b/arch/arm/src/armv7-a/arm_unblocktask.c new file mode 100644 index 0000000000..4906a4a8be --- /dev/null +++ b/arch/arm/src/armv7-a/arm_unblocktask.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_unblocktask.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "os_internal.h" +#include "clock_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_unblock_task + * + * Description: + * A task is currently in an inactive task list + * but has been prepped to execute. Move the TCB to the + * ready-to-run list, restore its context, and start execution. + * + * Inputs: + * tcb: Refers to the tcb to be unblocked. This tcb is + * in one of the waiting tasks lists. It must be moved to + * the ready-to-run list and, if it is the highest priority + * ready to run taks, executed. + * + ****************************************************************************/ + +void up_unblock_task(struct tcb_s *tcb) +{ + struct tcb_s *rtcb = (struct tcb_s*)g_readytorun.head; + + /* Verify that the context switch can be performed */ + + ASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && + (tcb->task_state <= LAST_BLOCKED_STATE)); + + /* Remove the task from the blocked task list */ + + sched_removeblocked(tcb); + + /* Reset its timeslice. This is only meaningful for round + * robin tasks but it doesn't here to do it for everything + */ + +#if CONFIG_RR_INTERVAL > 0 + tcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; +#endif + + /* Add the task in the correct location in the prioritized + * g_readytorun task list + */ + + if (sched_addreadytorun(tcb)) + { + /* The currently active task has changed! We need to do + * a context switch to the new task. + * + * Are we in an interrupt handler? + */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (struct tcb_s*)g_readytorun.head; + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* We are not in an interrupt handler. Copy the user C context + * into the TCB of the task that was previously active. if + * up_saveusercontext returns a non-zero value, then this is really the + * previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the new task that is ready to + * run (probably tcb). This is the new rtcb at the head of the + * g_readytorun task list. + */ + + rtcb = (struct tcb_s*)g_readytorun.head; + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } +} diff --git a/arch/arm/src/armv7-a/arm_undefinedinsn.c b/arch/arm/src/armv7-a/arm_undefinedinsn.c new file mode 100644 index 0000000000..4c63b467f6 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_undefinedinsn.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * arch/arm/src/armv7/arm_undefinedinsn.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Output debug info if stack dump is selected -- even if + * debug is not selected. + */ + +#ifdef CONFIG_ARCH_STACKDUMP +# undef lldbg +# define lldbg lowsyslog +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_undefinedinsn + ****************************************************************************/ + +void arm_undefinedinsn(uint32_t *regs) +{ + lldbg("Undefined instruction at 0x%x\n", regs[REG_PC]); + current_regs = regs; + PANIC(); +} diff --git a/arch/arm/src/armv7-a/arm_va2pte.c b/arch/arm/src/armv7-a/arm_va2pte.c new file mode 100644 index 0000000000..1d3aec414d --- /dev/null +++ b/arch/arm/src/armv7-a/arm_va2pte.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_va2pte.c + * Utility to map a virtual address to a L2 page table entry. + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "chip.h" +#include "pg_macros.h" +#include "up_internal.h" + +#ifdef CONFIG_PAGING + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_va2pte + * + * Description: + * Convert a virtual address within the paged text region into a pointer to + * the corresponding page table entry. + * + * Input Parameters: + * vaddr - The virtual address within the paged text region. + * + * Returned Value: + * A pointer to the corresponding page table entry. + * + * Assumptions: + * - This function is called from the normal tasking context (but with + * interrupts disabled). The implementation must take whatever actions + * are necessary to assure that the operation is safe within this + * context. + * + ****************************************************************************/ + +uint32_t *up_va2pte(uintptr_t vaddr) +{ + uint32_t L1; + uint32_t *L2; + unsigned int ndx; + + /* The virtual address is expected to lie in the paged text region */ + + DEBUGASSERT(vaddr >= PG_PAGED_VBASE && vaddr < PG_PAGED_VEND); + + /* Get the L1 table entry associated with this virtual address */ + + L1 = *(uint32_t*)PG_POOL_VA2L1VADDR(vaddr); + + /* Get the address of the L2 page table from the L1 entry */ + + L2 = (uint32_t*)PG_POOL_L12VPTABLE(L1); + + /* Get the index into the L2 page table. Each L1 entry maps + * 256 x 4Kb or 1024 x 1Kb pages. + */ + + ndx = (vaddr & 0x000fffff) >> PAGESHIFT; + + /* Return true if this virtual address is mapped. */ + + return &L2[ndx]; +} + +#endif /* CONFIG_PAGING */ diff --git a/arch/arm/src/armv7-a/arm_vectoraddrexcptn.S b/arch/arm/src/armv7-a/arm_vectoraddrexcptn.S new file mode 100644 index 0000000000..b23f6af1af --- /dev/null +++ b/arch/arm/src/armv7-a/arm_vectoraddrexcptn.S @@ -0,0 +1,87 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_vectoraddrexceptn.S + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "up_arch.h" + + .file "arm_vectoraddrexcptn.S" + +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .globl arm_vectoraddrexcption + +/**************************************************************************** + * Assembly Macros + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + + .text + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + .text + +/**************************************************************************** + * Name: arm_vectoraddrexcption + * + * Description: + * Shouldn't happen. This exception handler is in a separate file from + * other vector handlers because some processors (e.g., Cortex-A5) do not + * support the the Address Exception vector. + * + ****************************************************************************/ + + .globl arm_vectoraddrexcptn + .type arm_vectoraddrexcptn, %function +arm_vectoraddrexcptn: + b arm_vectoraddrexcptn + .size arm_vectoraddrexcptn, . - arm_vectoraddrexcptn + .end diff --git a/arch/arm/src/armv7-a/arm_vectors.S b/arch/arm/src/armv7-a/arm_vectors.S index 79597f1784..6ba12cd88e 100644 --- a/arch/arm/src/armv7-a/arm_vectors.S +++ b/arch/arm/src/armv7-a/arm_vectors.S @@ -78,71 +78,71 @@ g_aborttmp: .text /************************************************************************************ - * Name: up_vectorirq + * Name: arm_vectorirq * * Description: * Interrupt excetpion. Entered in IRQ mode with spsr = SVC CPSR, lr = SVC PC * ************************************************************************************/ - .globl up_vectorirq - .type up_vectorirq, %function -up_vectorirq: + .globl arm_vectorirq + .type arm_vectorirq, %function +arm_vectorirq: /* On entry, we are in IRQ mode. We are free to use * the IRQ mode r13 and r14. */ ldr r13, .Lirqtmp sub lr, lr, #4 - str lr, [r13] @ save lr_IRQ + str lr, [r13] /* Save lr_IRQ */ mrs lr, spsr - str lr, [r13, #4] @ save spsr_IRQ + str lr, [r13, #4] /* Save spsr_IRQ */ /* Then switch back to SVC mode */ - bic lr, lr, #PSR_MODE_MASK /* Keep F and T bits */ - orr lr, lr, #(PSR_MODE_SUPER | PSR_I_BIT) - msr cpsr_c, lr /* Switch to SVC mode */ + bic lr, lr, #PSR_MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(PSR_MODE_SUPER | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ /* Create a context structure. First set aside a stack frame * and store r0-r12 into the frame. */ - sub sp, sp, #XCPTCONTEXT_SIZE - stmia sp, {r0-r12} /* Save the SVC mode regs */ + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ - add r1, sp, #XCPTCONTEXT_SIZE - mov r2, r14 + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 /* Get the values for r15(pc) and CPSR in r3 and r4 */ - ldr r0, .Lirqtmp /* Points to temp storage */ - ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + ldr r0, .Lirqtmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ - add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ stmia r0, {r1-r4} /* Then call the IRQ handler with interrupts disabled. */ - mov fp, #0 /* Init frame pointer */ - mov r0, sp /* Get r0=xcp */ + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ #if CONFIG_ARCH_INTERRUPTSTACK > 3 - ldr sp, .Lirqstackbase /* SP = interrupt stack base */ - str r0, [sp] /* Save the user stack pointer */ - bl up_decodeirq /* Call the handler */ - ldr sp, [sp] /* Restore the user stack pointer */ + ldr sp, .Lirqstackbase /* SP = interrupt stack base */ + str r0, [sp] /* Save the user stack pointer */ + bl up_decodeirq /* Call the handler */ + ldr sp, [sp] /* Restore the user stack pointer */ #else - bl up_decodeirq /* Call the handler */ + bl up_decodeirq /* Call the handler */ #endif /* Restore the CPSR, SVC modr registers and return */ .Lnoirqset: - ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ - msr spsr, r0 - ldmia sp, {r0-r15}^ /* Return */ + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr, r0 + ldmia sp, {r0-r15}^ /* Return */ .Lirqtmp: .word g_irqtmp @@ -150,58 +150,58 @@ up_vectorirq: .Lirqstackbase: .word up_stackbase #endif - .size up_vectorirq, . - up_vectorirq + .size arm_vectorirq, . - arm_vectorirq .align 5 /************************************************************************************ - * Function: up_vectorswi + * Function: arm_vectorswi * * Description: * SWI interrupt. We enter the SWI in SVC mode. * ************************************************************************************/ - .globl up_vectorswi - .type up_vectorswi, %function -up_vectorswi: + .globl arm_vectorswi + .type arm_vectorswi, %function +arm_vectorswi: /* Create a context structure. First set aside a stack frame * and store r0-r12 into the frame. */ - sub sp, sp, #XCPTCONTEXT_SIZE - stmia sp, {r0-r12} /* Save the SVC mode regs */ + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ /* Get the correct values of r13(sp), r14(lr), r15(pc) * and CPSR in r1-r4 */ - add r1, sp, #XCPTCONTEXT_SIZE - mov r2, r14 /* R14 is altered on return from SWI */ - mov r3, r14 /* Save r14 as the PC as well */ - mrs r4, spsr /* Get the saved CPSR */ + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 /* R14 is altered on return from SWI */ + mov r3, r14 /* Save r14 as the PC as well */ + mrs r4, spsr /* Get the saved CPSR */ - add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ stmia r0, {r1-r4} /* Then call the SWI handler with interrupts disabled. * void up_syscall(struct xcptcontext *xcp) */ - mov fp, #0 /* Init frame pointer */ - mov r0, sp /* Get r0=xcp */ - bl up_syscall /* Call the handler */ + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ + bl up_syscall /* Call the handler */ /* Restore the CPSR, SVC modr registers and return */ - ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ - msr spsr, r0 - ldmia sp, {r0-r15}^ /* Return */ - .size up_vectorswi, . - up_vectorswi + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr, r0 + ldmia sp, {r0-r15}^ /* Return */ + .size arm_vectorswi, . - arm_vectorswi .align 5 /************************************************************************************ - * Name: up_vectordata + * Name: arm_vectordata * * Description: * This is the data abort exception dispatcher. The ARM data abort exception occurs @@ -210,72 +210,72 @@ up_vectorswi: * is entered in ABORT mode with spsr = SVC CPSR, lr = SVC PC * ************************************************************************************/ - - .globl up_vectordata - .type up_vectordata, %function -up_vectordata: + + .globl arm_vectordata + .type arm_vectordata, %function +arm_vectordata: /* On entry we are free to use the ABORT mode registers * r13 and r14 */ - ldr r13, .Ldaborttmp /* Points to temp storage */ - sub lr, lr, #8 /* Fixup return */ - str lr, [r13] /* Save in temp storage */ - mrs lr, spsr /* Get SPSR */ - str lr, [r13, #4] /* Save in temp storage */ + ldr r13, .Ldaborttmp /* Points to temp storage */ + sub lr, lr, #8 /* Fixup return */ + str lr, [r13] /* Save in temp storage */ + mrs lr, spsr /* Get SPSR */ + str lr, [r13, #4] /* Save in temp storage */ /* Then switch back to SVC mode */ - bic lr, lr, #PSR_MODE_MASK /* Keep F and T bits */ - orr lr, lr, #(PSR_MODE_SUPER | PSR_I_BIT) - msr cpsr_c, lr /* Switch to SVC mode */ + bic lr, lr, #PSR_MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(PSR_MODE_SUPER | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ /* Create a context structure. First set aside a stack frame * and store r0-r12 into the frame. */ - sub sp, sp, #XCPTCONTEXT_SIZE - stmia sp, {r0-r12} /* Save the SVC mode regs */ + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ - add r1, sp, #XCPTCONTEXT_SIZE - mov r2, r14 + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 /* Get the values for r15(pc) and CPSR in r3 and r4 */ - ldr r0, .Ldaborttmp /* Points to temp storage */ - ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + ldr r0, .Ldaborttmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ - add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ stmia r0, {r1-r4} /* Then call the data abort handler with interrupts disabled. - * void up_dataabort(struct xcptcontext *xcp) + * void arm_dataabort(struct xcptcontext *xcp) */ - mov fp, #0 /* Init frame pointer */ - mov r0, sp /* Get r0=xcp */ + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ #ifdef CONFIG_PAGING - mrc p15, 0, r2, c5, c0, 0 /* Get r2=FSR */ - mrc p15, 0, r1, c6, c0, 0 /* Get R1=FAR */ + mrc p15, 0, r2, c5, c0, 0 /* Get r2=FSR */ + mrc p15, 0, r1, c6, c0, 0 /* Get R1=FAR */ #endif - bl up_dataabort /* Call the handler */ + bl arm_dataabort /* Call the handler */ /* Restore the CPSR, SVC modr registers and return */ - ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ - msr spsr_cxsf, r0 - ldmia sp, {r0-r15}^ /* Return */ + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr_cxsf, r0 + ldmia sp, {r0-r15}^ /* Return */ .Ldaborttmp: .word g_aborttmp - .size up_vectordata, . - up_vectordata + .size arm_vectordata, . - arm_vectordata .align 5 /************************************************************************************ - * Name: up_vectorprefetch + * Name: arm_vectorprefetch * * Description: * This is the prefetch abort exception dispatcher. The ARM prefetch abort exception @@ -284,146 +284,146 @@ up_vectordata: * handler. This function is entered in ABT mode with spsr = SVC CPSR, lr = SVC PC. * ************************************************************************************/ - - .globl up_vectorprefetch - .type up_vectorprefetch, %function -up_vectorprefetch: + + .globl arm_vectorprefetch + .type arm_vectorprefetch, %function +arm_vectorprefetch: /* On entry we are free to use the ABORT mode registers * r13 and r14 */ - ldr r13, .Lpaborttmp /* Points to temp storage */ - sub lr, lr, #4 /* Fixup return */ - str lr, [r13] /* Save in temp storage */ - mrs lr, spsr /* Get SPSR */ - str lr, [r13, #4] /* Save in temp storage */ + ldr r13, .Lpaborttmp /* Points to temp storage */ + sub lr, lr, #4 /* Fixup return */ + str lr, [r13] /* Save in temp storage */ + mrs lr, spsr /* Get SPSR */ + str lr, [r13, #4] /* Save in temp storage */ /* Then switch back to SVC mode */ - bic lr, lr, #PSR_MODE_MASK /* Keep F and T bits */ - orr lr, lr, #(PSR_MODE_SUPER | PSR_I_BIT) - msr cpsr_c, lr /* Switch to SVC mode */ + bic lr, lr, #PSR_MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(PSR_MODE_SUPER | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ /* Create a context structure. First set aside a stack frame * and store r0-r12 into the frame. */ - sub sp, sp, #XCPTCONTEXT_SIZE - stmia sp, {r0-r12} /* Save the SVC mode regs */ + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ - add r1, sp, #XCPTCONTEXT_SIZE - mov r2, r14 + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 /* Get the values for r15(pc) and CPSR in r3 and r4 */ - ldr r0, .Lpaborttmp /* Points to temp storage */ - ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + ldr r0, .Lpaborttmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ - add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ stmia r0, {r1-r4} /* Then call the prefetch abort handler with interrupts disabled. - * void up_prefetchabort(struct xcptcontext *xcp) + * void arm_prefetchabort(struct xcptcontext *xcp) */ - mov fp, #0 /* Init frame pointer */ - mov r0, sp /* Get r0=xcp */ - bl up_prefetchabort /* Call the handler */ + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ + bl arm_prefetchabort /* Call the handler */ /* Restore the CPSR, SVC modr registers and return */ - ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ - msr spsr_cxsf, r0 - ldmia sp, {r0-r15}^ /* Return */ + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr_cxsf, r0 + ldmia sp, {r0-r15}^ /* Return */ .Lpaborttmp: .word g_aborttmp - .size up_vectorprefetch, . - up_vectorprefetch + .size arm_vectorprefetch, . - arm_vectorprefetch .align 5 /************************************************************************************ - * Name: up_vectorundefinsn + * Name: arm_vectorundefinsn * * Description: * Undefined instruction entry exception. Entered in UND mode, spsr = SVC CPSR, * lr = SVC PC * ************************************************************************************/ - - .globl up_vectorundefinsn - .type up_vectorundefinsn, %function -up_vectorundefinsn: + + .globl arm_vectorundefinsn + .type arm_vectorundefinsn, %function +arm_vectorundefinsn: /* On entry we are free to use the UND mode registers * r13 and r14 */ - ldr r13, .Lundeftmp /* Points to temp storage */ - str lr, [r13] /* Save in temp storage */ - mrs lr, spsr /* Get SPSR */ - str lr, [r13, #4] /* Save in temp storage */ + ldr r13, .Lundeftmp /* Points to temp storage */ + str lr, [r13] /* Save in temp storage */ + mrs lr, spsr /* Get SPSR */ + str lr, [r13, #4] /* Save in temp storage */ /* Then switch back to SVC mode */ - bic lr, lr, #PSR_MODE_MASK /* Keep F and T bits */ - orr lr, lr, #(PSR_MODE_SUPER | PSR_I_BIT) - msr cpsr_c, lr /* Switch to SVC mode */ + bic lr, lr, #PSR_MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(PSR_MODE_SUPER | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ /* Create a context structure. First set aside a stack frame * and store r0-r12 into the frame. */ - sub sp, sp, #XCPTCONTEXT_SIZE - stmia sp, {r0-r12} /* Save the SVC mode regs */ + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ - add r1, sp, #XCPTCONTEXT_SIZE - mov r2, r14 + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 /* Get the values for r15(pc) and CPSR in r3 and r4 */ - ldr r0, .Lundeftmp /* Points to temp storage */ - ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + ldr r0, .Lundeftmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ - add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ stmia r0, {r1-r4} /* Then call the undef insn handler with interrupts disabled. - * void up_undefinedinsn(struct xcptcontext *xcp) + * void arm_undefinedinsn(struct xcptcontext *xcp) */ - mov fp, #0 /* Init frame pointer */ - mov r0, sp /* Get r0=xcp */ - bl up_undefinedinsn /* Call the handler */ + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ + bl arm_undefinedinsn /* Call the handler */ /* Restore the CPSR, SVC modr registers and return */ - ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ - msr spsr_cxsf, r0 - ldmia sp, {r0-r15}^ /* Return */ + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr_cxsf, r0 + ldmia sp, {r0-r15}^ /* Return */ .Lundeftmp: .word g_undeftmp - .size up_vectorundefinsn, . - up_vectorundefinsn + .size arm_vectorundefinsn, . - arm_vectorundefinsn .align 5 /************************************************************************************ - * Name: up_vectorfiq + * Name: arm_vectorfiq * * Description: * Shouldn't happen * ************************************************************************************/ - .globl up_vectorfiq - .type up_vectorfiq, %function -up_vectorfiq: + .globl arm_vectorfiq + .type arm_vectorfiq, %function +arm_vectorfiq: subs pc, lr, #4 - .size up_vectorfiq, . - up_vectorfiq + .size arm_vectorfiq, . - arm_vectorfiq /************************************************************************************ * Name: up_interruptstack/g_userstack diff --git a/arch/arm/src/armv7-a/arm_vectortab.S b/arch/arm/src/armv7-a/arm_vectortab.S index 80de0f63a1..e01ae13b74 100644 --- a/arch/arm/src/armv7-a/arm_vectortab.S +++ b/arch/arm/src/armv7-a/arm_vectortab.S @@ -63,40 +63,40 @@ /* These will be relocated to VECTOR_BASE. */ _vector_start: - ldr pc, .Lresethandler /* 0x00: Reset */ - ldr pc, .Lundefinedhandler /* 0x04: Undefined instruction */ - ldr pc, .Lswihandler /* 0x08: Software interrupt */ - ldr pc, .Lprefetchaborthandler /* 0x0c: Prefetch abort */ - ldr pc, .Ldataaborthandler /* 0x10: Data abort */ - ldr pc, .Laddrexcptnhandler /* 0x14: Address exception (reserved) */ - ldr pc, .Lirqhandler /* 0x18: IRQ */ - ldr pc, .Lfiqhandler /* 0x1c: FIQ */ + ldr pc, .Lresethandler /* 0x00: Reset */ + ldr pc, .Lundefinedhandler /* 0x04: Undefined instruction */ + ldr pc, .Lswihandler /* 0x08: Software interrupt */ + ldr pc, .Lprefetchaborthandler /* 0x0c: Prefetch abort */ + ldr pc, .Ldataaborthandler /* 0x10: Data abort */ + ldr pc, .Laddrexcptnhandler /* 0x14: Address exception (reserved) */ + ldr pc, .Lirqhandler /* 0x18: IRQ */ + ldr pc, .Lfiqhandler /* 0x1c: FIQ */ .globl __start - .globl up_vectorundefinsn - .globl up_vectorswi - .globl up_vectorprefetch - .globl up_vectordata - .globl up_vectoraddrexcptn - .globl up_vectorirq - .globl up_vectorfiq + .globl arm_vectorundefinsn + .globl arm_vectorswi + .globl arm_vectorprefetch + .globl arm_vectordata + .globl arm_vectoraddrexcptn + .globl arm_vectorirq + .globl arm_vectorfiq .Lresethandler: - .long __start + .long __start .Lundefinedhandler: - .long up_vectorundefinsn + .long arm_vectorundefinsn .Lswihandler: - .long up_vectorswi + .long arm_vectorswi .Lprefetchaborthandler: - .long up_vectorprefetch + .long arm_vectorprefetch .Ldataaborthandler: - .long up_vectordata + .long arm_vectordata .Laddrexcptnhandler: - .long up_vectoraddrexcptn + .long arm_vectoraddrexcptn .Lirqhandler: - .long up_vectorirq + .long arm_vectorirq .Lfiqhandler: - .long up_vectorfiq + .long arm_vectorfiq .globl _vector_end _vector_end: diff --git a/arch/arm/src/armv7-a/arm_vfork.S b/arch/arm/src/armv7-a/arm_vfork.S new file mode 100644 index 0000000000..d8fa0e14cd --- /dev/null +++ b/arch/arm/src/armv7-a/arm_vfork.S @@ -0,0 +1,140 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_vfork.S + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "up_vfork.h" + + .file "vfork.S" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .globl up_vfork + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vfork + * + * Description: + * The vfork() function has the same effect as fork(), except that the + * behavior is undefined if the process created by vfork() either modifies + * any data other than a variable of type pid_t used to store the return + * value from vfork(), or returns from the function in which vfork() was + * called, or calls any other function before successfully calling _exit() + * or one of the exec family of functions. + * + * This thin layer implements vfork by simply calling up_vfork() with the + * vfork() context as an argument. The overall sequence is: + * + * 1) User code calls vfork(). vfork() collects context information and + * transfers control up up_vfork(). + * 2) up_vfork()and calls task_vforksetup(). + * 3) task_vforksetup() allocates and configures the child task's TCB. + * This consists of: + * - Allocation of the child task's TCB. + * - Initialization of file descriptors and streams + * - Configuration of environment variables + * - Setup the intput parameters for the task. + * - Initialization of the TCB (including call to up_initial_state() + * 4) up_vfork() provides any additional operating context. up_vfork must: + * - Allocate and initialize the stack + * - Initialize special values in any CPU registers that were not + * already configured by up_initial_state() + * 5) up_vfork() then calls task_vforkstart() + * 6) task_vforkstart() then executes the child thread. + * + * Input Paremeters: + * None + * + * Return: + * Upon successful completion, vfork() returns 0 to the child process and + * returns the process ID of the child process to the parent process. + * Otherwise, -1 is returned to the parent, no child process is created, + * and errno is set to indicate the error. + * + ****************************************************************************/ + + .globl vfork + .type vfork, function +vfork: + /* Create a stack frame */ + + mov r0, sp /* Save the value of the stack on entry */ + sub sp, sp, #VFORK_SIZEOF /* Allocate the structure on the stack */ + + /* CPU registers */ + /* Save the volatile registers */ + + str r4, [sp, #VFORK_R4_OFFSET] + str r5, [sp, #VFORK_R5_OFFSET] + str r6, [sp, #VFORK_R6_OFFSET] + str r7, [sp, #VFORK_R7_OFFSET] + str r8, [sp, #VFORK_R8_OFFSET] + str r9, [sp, #VFORK_R9_OFFSET] + str r10, [sp, #VFORK_R10_OFFSET] + + /* Save the frame pointer, stack pointer, and return address */ + + str fp, [sp, #VFORK_FP_OFFSET] + str r0, [sp, #VFORK_SP_OFFSET] + str lr, [sp, #VFORK_LR_OFFSET] + + /* Floating point registers (not yet) */ + + /* Then, call up_vfork(), passing it a pointer to the stack structure */ + + mov r0, sp + bl up_vfork + + /* Release the stack data and return the value returned by up_vfork */ + + ldr lr, [sp, #VFORK_LR_OFFSET] + add sp, sp, #VFORK_SIZEOF + mov pc, lr + .size vfork, .-vfork + .end diff --git a/arch/arm/src/armv7-a/cp15.h b/arch/arm/src/armv7-a/cp15.h index 160bc487b3..9c8bf91f18 100644 --- a/arch/arm/src/armv7-a/cp15.h +++ b/arch/arm/src/armv7-a/cp15.h @@ -194,7 +194,7 @@ #define CP15_IDATAR(r) _CP15(3, r, c15, c4, 1) /* Instruction Cache Data Read Operation Register */ #define CP15_TLBR(r) _CP15(3, r, c15, c4, 2) /* TLB Data Read Operation Register */ #define CP15_CBADDR(r) _CP15(4, r, c15, c0, 0) /* Configuration Base Address Register */ -#define CP15_TLBHITMAP(r) _CP15(5, r, c15, c0, 0) /* TLB access and attributes +#define CP15_TLBHITMAP(r) _CP15(5, r, c15, c0, 0) /* TLB access and attributes */ /* System control register descriptions. * diff --git a/arch/arm/src/armv7-a/mmu.h b/arch/arm/src/armv7-a/mmu.h index 2daab81fc1..f02d0ddbd4 100644 --- a/arch/arm/src/armv7-a/mmu.h +++ b/arch/arm/src/armv7-a/mmu.h @@ -60,8 +60,8 @@ * implement this feature, so this register always RAZ. */ -/* System Control Register (SCTRL). see sctrl.h */ -/* Non-secure Access Control Register (NSACR). See sctrl.h */ +/* System Control Register (SCTLR). see cstlr.h */ +/* Non-secure Access Control Register (NSACR). See cstlr.h */ /* Translation Table Base Register 0 (TTBR0)*/ @@ -205,7 +205,7 @@ #define TLBHR_16MB (1 << 3) /* Bit 3: 16MB supersections are present in the TLB */ /* Bits 4-31: Reserved */ -/* Context ID Register (CONTEXTIDR). See sctrl.h */ +/* Context ID Register (CONTEXTIDR). See cstlr.h */ /************************************************************************************ * Assemby Macros diff --git a/arch/arm/src/armv7-a/sctrl.h b/arch/arm/src/armv7-a/sctlr.h similarity index 93% rename from arch/arm/src/armv7-a/sctrl.h rename to arch/arm/src/armv7-a/sctlr.h index 7ea447b1b1..07959ef45a 100644 --- a/arch/arm/src/armv7-a/sctrl.h +++ b/arch/arm/src/armv7-a/sctlr.h @@ -1,5 +1,5 @@ /************************************************************************************ - * arch/arm/src/armv7-a/sctrl.h + * arch/arm/src/armv7-a/sctlr.h * CP15 System Control Registers * * Copyright (C) 2013 Gregory Nutt. All rights reserved. @@ -41,8 +41,8 @@ * ************************************************************************************/ -#ifndef __ARCH_ARM_SRC_ARMV7_A_CPSR_H -#define __ARCH_ARM_SRC_ARMV7_A_CPSR_H +#ifndef __ARCH_ARM_SRC_ARMV7_A_SCTLR_H +#define __ARCH_ARM_SRC_ARMV7_A_SCTLR_H /************************************************************************************ * Included Files @@ -124,14 +124,14 @@ #define SCTLR_C (1 << 2) /* Bit 2: Determines if data can be cached */ /* Bits 3-9: Reserved */ #define SCTLR_SW (1 << 10) /* Bit 10: SWP/SWPB Enable bit */ -#define SCTLR_A (1 << 11) /* Bit 11: Program flow prediction control (1) */ +#define SCTLR_Z (1 << 11) /* Bit 11: Program flow prediction control (1) */ #define SCTLR_I (1 << 12) /* Bit 12: Determines if instructions can be cached */ #define SCTLR_V (1 << 13) /* Bit 13: Vectors bit */ #define SCTLR_RR (1 << 14) /* Bit 14: Cache replacement strategy (2) */ /* Bits 15-16: Reserved */ #define SCTLR_HA (1 << 17) /* Bit 17: Hardware management access disabled (2) */ /* Bits 18-24: Reserved */ -#define SCTLR_EE (1 << 25) /* Bit 15: Determines the value the CPSR.E */ +#define SCTLR_EE (1 << 25) /* Bit 25: Determines the value the CPSR.E */ /* Bits 26-27: Reserved */ #define SCTLR_TRE (1 << 28) /* Bit 28: TEX remap */ #define SCTLR_AFE (1 << 29) /* Bit 29: Access Flag Enable bit */ @@ -237,14 +237,14 @@ mrc p15, 0, \id, c0, c0, 0 .endm -/* Read/write the system control register (SCTRL) */ +/* Read/write the system control register (SCTLR) */ - .macro cp15_rdsctrl, sctrl - mrc p15, 0, \sctrl, c1, c0, 0 + .macro cp15_rdsctlr, sctlr + mrc p15, 0, \sctlr, c1, c0, 0 .endm - .macro cp15_wrsctrl, sctrl - mcr p15, 0, \sctrl, c1, c0, 0 + .macro cp15_wrsctlr, sctlr + mcr p15, 0, \sctlr, c1, c0, 0 nop nop nop @@ -278,23 +278,23 @@ static inline unsigned int cp15_rdid(void) return id; } -/* Read/write the system control register (SCTRL) */ +/* Read/write the system control register (SCTLR) */ -static inline unsigned int cp15_rdsctrl(void) +static inline unsigned int cp15_rdsctlr(void) { - unsigned int sctrl; + unsigned int sctlr; __asm__ __volatile__ ( "\tmrc p15, 0, %0, c1, c0, 0" - : "=r" (sctrl) + : "=r" (sctlr) : : "memory" ); - return sctrl; + return sctlr; } -static inline void cp15_wrsctrl(unsigned int sctrl) +static inline void cp15_wrsctlr(unsigned int sctlr) { __asm__ __volatile__ ( @@ -308,7 +308,7 @@ static inline void cp15_wrsctrl(unsigned int sctrl) "\tnop\n" "\tnop\n" : - : "r" (sctrl) + : "r" (sctlr) : "memory" ); } @@ -337,4 +337,4 @@ extern "C" { #endif #endif /* __ASSEMBLY__ */ -#endif /* __ARCH_ARM_SRC_ARMV7_A_CPSR_H */ +#endif /* __ARCH_ARM_SRC_ARMV7_A_SCTLR_H */