diff --git a/arch/xtensa/include/irq.h b/arch/xtensa/include/irq.h index 26b6a0e3db..1c11515dee 100644 --- a/arch/xtensa/include/irq.h +++ b/arch/xtensa/include/irq.h @@ -151,6 +151,7 @@ struct xcptcontext /* These are saved copies of registers used during signal processing. */ uint32_t saved_pc; + uint32_t saved_ps; #endif /* Register save area */ diff --git a/arch/xtensa/src/common/xtensa_schedsigaction.c b/arch/xtensa/src/common/xtensa_schedsigaction.c index 76c8669a39..8090bb262d 100644 --- a/arch/xtensa/src/common/xtensa_schedsigaction.c +++ b/arch/xtensa/src/common/xtensa_schedsigaction.c @@ -138,18 +138,24 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) /* Save the return lr and cpsr and one scratch register * These will be restored by the signal trampoline after * the signals have been delivered. + * + * NOTE: that hi-priority interrupts are not disabled. */ tcb->xcp.sigdeliver = sigdeliver; tcb->xcp.saved_pc = CURRENT_REGS[REG_PC]; -#warning REVISIT: Missing logic... need to save interrupt state + tcb->xcp.saved_ps = CURRENT_REGS[REG_PS]; /* Then set up to vector to the trampoline with interrupts * disabled */ CURRENT_REGS[REG_PC] = (uint32_t)xtensa_sigdeliver; -#warning REVISIT: Missing logic... need to set interrupt state with interrupts disabled +#ifdef CONFIG_XTENSA_CALL0_ABI + CURRENT_REGS[REG_PS] = (uint32_t)(PS_INTLEVEL(0) | PS_UM); +#else + CURRENT_REGS[REG_PS] = (uint32_t)(PS_INTLEVEL(0) | PS_UM | PS_WOE); +#endif /* And make sure that the saved context in the TCB is the same * as the interrupt return context. @@ -173,14 +179,18 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.sigdeliver = sigdeliver; tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; -#warning REVISIT: Missing logic... need to save interrupt state + tcb->xcp.saved_ps = tcb->xcp.regs[REG_PS]; /* Then set up to vector to the trampoline with interrupts * disabled */ tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sigdeliver; -#warning REVISIT: Missing logic... need to set interrupt state with interrupts disabled +#ifdef CONFIG_XTENSA_CALL0_ABI + tcb->xcp.regs[REG_PS] = (uint32_t)(PS_INTLEVEL(0) | PS_UM); +#else + tcb->xcp.regs[REG_PS] = (uint32_t)(PS_INTLEVEL(0) | PS_UM | PS_WOE); +#endif } } diff --git a/arch/xtensa/src/common/xtensa_sigdeliver.c b/arch/xtensa/src/common/xtensa_sigdeliver.c index 381b08f9a7..5f54c4035c 100644 --- a/arch/xtensa/src/common/xtensa_sigdeliver.c +++ b/arch/xtensa/src/common/xtensa_sigdeliver.c @@ -90,7 +90,7 @@ void xtensa_sigdeliver(void) xtensa_copystate(regs, rtcb->xcp.regs); regs[REG_PC] = rtcb->xcp.saved_pc; -#warning Missing Logic... Need to save the correct interrupt state + regs[REG_PS] = rtcb->xcp.saved_ps; /* 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 @@ -101,8 +101,8 @@ void xtensa_sigdeliver(void) rtcb->xcp.sigdeliver = NULL; /* Then restore the task interrupt state */ -#warning Missing Logic... Need to restore the correct interrupt state - //up_irq_restore(regs[REG_CPSR]); + + up_irq_restore(regs[REG_PS]); /* Deliver the signals */ diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index 3eea150d14..1270f0c0cc 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -76,7 +76,7 @@ endif CHIP_ASRCS = CHIP_CSRCS = esp32_allocateheap.c esp32_intdecode.c esp32_irq.c -CHIP_CSRCS += esp32_start.c esp32_timerisr.c +CHIP_CSRCS += esp32_region.c esp32_start.c esp32_timerisr.c # Configuration-dependent ESP32 files diff --git a/arch/xtensa/src/esp32/esp32_cpustart.c b/arch/xtensa/src/esp32/esp32_cpustart.c index 01e0412c75..038a2851c2 100644 --- a/arch/xtensa/src/esp32/esp32_cpustart.c +++ b/arch/xtensa/src/esp32/esp32_cpustart.c @@ -49,11 +49,10 @@ #include "sched/sched.h" #include "xtensa.h" +#include "esp32_region.h" #ifdef CONFIG_SMP -#warning REVISIT Need cpu_configure_region_protection() prototype -void cpu_configure_region_protection(void); #warning REVISIT Need ets_set_appcpu_boot_addr() prototype void ets_set_appcpu_boot_addr(uint32_t); @@ -126,7 +125,7 @@ int xtensa_start_handler(int irq, FAR void *context) /* Make page 0 access raise an exception */ - cpu_configure_region_protection(); + esp32_region_protection(); /* Dump registers so that we can see what is going to happen on return */ diff --git a/arch/xtensa/src/esp32/esp32_region.c b/arch/xtensa/src/esp32/esp32_region.c new file mode 100644 index 0000000000..bd3758342d --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_region.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_region.c + * + * Developed for NuttX by: + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Derives from code originally provided Espressif Systems: + * + * C opyright 2010-2016 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint32_t g_protected_pages[] = +{ + 0x00000000, 0x80000000, 0xa0000000, 0xc0000000, 0xe0000000 +}; + +#define NPROTECTED_PAGES (sizeof(g_protected_pages)/sizeof(uint32_t)) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: xtensa_write_dtlb and xtensa_write_itlb + * + * Description: + * Functions to set page attributes for Region Protection option in the + * CPU. See Xtensa ISA Reference manual for explanation of arguments + * (section 4.6.3.2). + * + ****************************************************************************/ + +static inline void xtensa_write_dtlb(uint32_t vpn, unsigned int attr) +{ + __asm__ __volatile__ + ( + "wdtlb %1, %0\n" + "dsync\n" + : : "r" (vpn), "r" (attr)); + ); +} + +static inline void xtensa_write_itlb(unsigned vpn, unsigned int attr) +{ + __asm__ __volatile__ + ( + "witlb %1, %0\n" + "isync\n" + : : "r" (vpn), "r" (attr)); + ); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32_region_protection + * + * Description: + * Make page 0 access raise an exception. Also protect some other unused + * pages so we can catch weirdness. + * + * Useful attribute values: + * 0 — cached, RW + * 2 — bypass cache, RWX (default value after CPU reset) + * 15 — no access, raise exception + * + ****************************************************************************/ + +void esp32_region_protection(void) +{ + for (int i = 0; i < NPROTECTED_PAGES; ++i) + { + xtensa_write_dtlb(g_protected_pages[i], 0xf); + xtensa_write_itlb(g_protected_pages[i], 0xf); + } + + xtensa_write_dtlb(0x20000000, 0); + xtensa_write_itlb(0x20000000, 0); +} diff --git a/arch/xtensa/src/esp32/esp32_region.h b/arch/xtensa/src/esp32/esp32_region.h new file mode 100644 index 0000000000..6a39afad09 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_region.h @@ -0,0 +1,67 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_region.h + * + * Copyright (C) 2016 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 + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32_ESP32_REGION_H +#define __ARCH_XTENSA_SRC_ESP32_ESP32_REGION_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32_region_protection + * + * Description: + * Make page 0 access raise an exception. Also protect some other unused + * pages so we can catch weirdness. + * + * Useful attribute values: + * 0 — cached, RW + * 2 — bypass cache, RWX (default value after CPU reset) + * 15 — no access, raise exception + * + ****************************************************************************/ + +void esp32_region_protection(void); + +#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_REGION_H */ diff --git a/arch/xtensa/src/esp32/esp32_start.c b/arch/xtensa/src/esp32/esp32_start.c index 8926f0e79c..3d1ca5c9b9 100644 --- a/arch/xtensa/src/esp32/esp32_start.c +++ b/arch/xtensa/src/esp32/esp32_start.c @@ -38,12 +38,10 @@ #include "chip/esp32_dport.h" #include "chip/esp32_rtccntl.h" #include "esp32_clockconfig.h" +#include "esp32_region.h" #include "esp32_start.h" #include "xtensa.h" -#warning REVISIT Need cpu_configure_region_protection() prototype -void cpu_configure_region_protection(void); - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -77,7 +75,7 @@ void IRAM_ATTR __start(void) /* Make page 0 access raise an exception */ - cpu_configure_region_protection(); + esp32_region_protection(); /* Move CPU0 exception vectors to IRAM */