ARM9 SVC_STACK out of range? - exception

I'm debugging some odd ARM exceptions in an embedded system using the IAR workbench toolchain. Sometimes, when an exception is trapped the SVC_STACK is reported as out of range (very out of range!) Is this relevant, or just an artifact of the J-Link JTAG debugger? What is the SVC_STACK used for? It is set to 0x1000 size, but when it is out of range, it is way up in our heap area. Thanks!

ARMs SVC mode is entered when an exception occurs (not an IRQ or FIQ - fast IRQ). It can also be entered directly by code executing in non-user mode by setting the CPRS register, but I think this is uncommon except for when initializing the system.
When an exception occurs, the processor switches to the SVC stack, which has to be set up very early in the initialization of the system. I'm guessing that your initialization code is not properly setting up the SVC stack, or it's possible that one of the exception handlers is not coded properly and is trashing the stack.
A third possibility is that you're using an RTOS that sets up the ARM stacks the way it wants (basically overriding the SVC stack that the IAR's initialization code might set up). If this is the case, it's possible that everything is OK, but the IAR debugger thinks the SVC stack is out of range - the debugger will get its information from the linker config file - but if something changes the stack to another area of memory, then the debugger will get confused.
This happened to me all the time with the user mode stack in IAR when using an RTOS - the stacks were allocated based on task control blocks which were not in the CSTACK segment the debugger thought it should be in, and the debugger would issue irritating warnings. There was some project configuration setting that could be used to quiet the warnings, but I don't recall off the top of my head what it was - we rarely bothered with it, and just lived with the noise.
You'll need to verify that the the stack 'way up in the heap' area is valid - if you don't have some bit of code explicitly doing this, it's likely that it's wrong (or maybe you'll need to ask your RTOS vendor).
The ARM Architecture Reference Manual (ARM ARM) is freely available from arm.com and goes into excruciating detail about how the ARM stacks work. Another good reference is the ARM System Developer's Guide by Andrew Sloss, et al.

Related

RISC-V return from exception handler with compressed instructions

I see the standard way of exiting RISC-V exception handler is update mepc to mepc+4 before mret.
But won't this cause problem if the next instruction is only 2-bytes long in compressed instruction mode?
In compressed instruction mode there are mixed of 4-bytes and 2-bytes instructions. If you not update mepc and just mret then you keep getting same exception. But always adding 4 to trapped mepc seem like a bug for mixed compressed instruction.
Am I missing something?
I see the standard way of exiting risc-v exception handler is update mepc to mepc+4 before mret.
These are not serious exception handlers; they are illustrative only — to show catching of exceptions at all, and returning back to the interrupted code without having done the actual exception processing needed for the given situation. Thus, the easiest thing to do to prevent an infinite loop is to simply skip past the offending instruction.
One of the few places where we advance the pc in order to return to the code that cause the exception is in handling an ecall. As far as I know there is no compressed (16-bit) ecall instruction.
Many resumable exceptions need to rerun the instruction that caused the exception — loads & stores that cause page faults (available in both 32-bit and 16-bit form), for example, need to re-execute once the page tables have been fixed (the page read in from disc and mapped into the user's address space).
Many other exceptions are not generally resumable.
However, emulation of an instruction requires knowing its size, as is the case with ecall. if you choose to emulate, for example, misaligned memory accesses, you will indeed have to make a decision as to the size of the instruction, as emulating it means resuming past it. Also note that RISC V supports 16-bit, 32-bit, 48-bit, 64-bit and longer instructions, so an exception handler that is going to emulate instructions will need to be able to decode their length (only the instructions chosen for emulation, though).
The other thing to add is that the sample exception handlers you may be looking at are designed to work without the compressed instruction set, and since RVC is optional that is a reasonable design choice (though ideally, of course, would be clearly stated).

OS development: How to avoid an infinite loop after an exception routine

For some months I've been working on a "home-made" operating system.
Currently, it boots and goes into 32-bit protected mode.
I've loaded the interrupt table, but haven't set up the pagination (yet).
Now while writing my exception routines I've noticed that when an instruction throws an exception, the exception routine is executed, but then the CPU jumps back to the instruction which threw the exception! This does not apply to every exception (for example, a div by zero exception will jump back to the instruction AFTER the division instruction), but let's consider the following general protection exception:
MOV EAX, 0x8
MOV CS, EAX
My routine is simple: it calls a function that displays a red error message.
The result: MOV CS, EAX fails -> My error message is displayed -> CPU jumps back to MOV CS -> infinite loop spamming the error message.
I've talked about this issue with a teacher in operating systems and unix security.
He told me he knows Linux has a way around it, but he doesn't know which one.
The naive solution would be to parse the throwing instruction from within the routine, in order to get the length of that instruction.
That solution is pretty complex, and I feel a bit uncomfortable adding a call to a relatively heavy function in every affected exception routine...
Therefore, I was wondering if the is another way around the problem. Maybe there's a "magic" register that contains a bit that can change this behaviour?
--
Thank you very much in advance for any suggestion/information.
--
EDIT: It seems many people wonder why I want to skip over the problematic instruction and resume normal execution.
I have two reasons for this:
First of all, killing a process would be a possible solution, but not a clean one. That's not how it's done in Linux, for example, where (AFAIK) the kernel sends a signal (I think SIGSEGV) but does not immediately break execution. It makes sense, since the application can block or ignore the signal and resume its own execution. It's a very elegant way to tell the application it did something wrong IMO.
Another reason: what if the kernel itself performs an illegal operation? Could be due to a bug, but could also be due to a kernel extension. As I've stated in a comment: what should I do in that case? Shall I just kill the kernel and display a nice blue screen with a smiley?
That's why I would like to be able to jump over the instruction. "Guessing" the instruction size is obviously not an option, and parsing the instruction seems fairly complex (not that I mind implementing such a routine, but I need to be sure there is no better way).
Different exceptions have different causes. Some exceptions are normal, and the exception only tells the kernel what it needs to do before allowing the software to continue running. Examples of this include a page fault telling the kernel it needs to load data from swap space, an undefined instruction exception telling the kernel it needs to emulate an instruction that the CPU doesn't support, or a debug/breakpoint exception telling the kernel it needs to notify a debugger. For these it's normal for the kernel to fix things up and silently continue.
Some exceptions indicate abnormal conditions (e.g. that the software crashed). The only sane way of handling these types of exceptions is to stop running the software. You may save information (e.g. core dump) or display information (e.g. "blue screen of death") to help with debugging, but in the end the software stops (either the process is terminated, or the kernel goes into a "do nothing until user resets computer" state).
Ignoring abnormal conditions just makes it harder for people to figure out what went wrong. For example, imagine instructions to go to the toilet:
enter bathroom
remove pants
sit
start generating output
Now imagine that step 2 fails because you're wearing shorts (a "can't find pants" exception). Do you want to stop at that point (with a nice easy to understand error message or something), or ignore that step and attempt to figure out what went wrong later on, after all the useful diagnostic information has gone?
If I understand correctly, you want to skip the instruction that caused the exception (e.g. mov cs, eax) and continue executing the program at the next instruction.
Why would you want to do this? Normally, shouldn't the rest of the program depend on the effects of that instruction being successfully executed?
Generally speaking, there are three approaches to exception handling:
Treat the exception as an unrepairable condition and kill the process. For example, division by zero is usually handled this way.
Repair the environment and then execute the instruction again. For example, page faults are sometimes handled this way.
Emulate the instruction using software and skip over it in the instruction stream. For example, complicated arithmetic instructions are sometimes handled this way.
What you're seeing is the characteristic of the General Protection Exception. The Intel System Programming Guide clearly states that (6.15 Exception and Interrupt Reference / Interrupt 13 - General Protection Exception (#GP)) :
Saved Instruction Pointer
The saved contents of CS and EIP registers point to the instruction that generated the
exception.
Therefore, you need to write an exception handler that will skip over that instruction (which would be kind of weird), or just simply kill the offending process with "General Protection Exception at $SAVED_EIP" or a similar message.
I can imagine a few situations in which one would want to respond to a GPF by parsing the failed instruction, emulating its operation, and then returning to the instruction after. The normal pattern would be to set things up so that the instruction, if retried, would succeed, but one might e.g. have some code that expects to access some hardware at addresses 0x000A0000-0x000AFFFF and wish to run it on a machine that lacks such hardware. In such a situation, one might not want to ever bank in "real" memory in that space, since every single access must be trapped and dealt with separately. I'm not sure whether there's any way to handle that without having to decode whatever instruction was trying to access that memory, although I do know that some virtual-PC programs seem to manage it pretty well.
Otherwise, I would suggest that you should have for each thread a jump vector which should be used when the system encounters a GPF. Normally that vector should point to a thread-exit routine, but code which was about to do something "suspicious" with pointers could set it to an error handler that was suitable for that code (the code should unset the vector when laving the region where the error handler would have been appropriate).
I can imagine situations where one might want to emulate an instruction without executing it, and cases where one might want to transfer control to an error-handler routine, but I can't imagine any where one would want to simply skip over an instruction that would have caused a GPF.

When does an ARM7 processor increase its PC register?

I'm thinking about this question for a time: when does an ARM7(with 3 pipelines) processor increase its PC register.
I originally thought that after an instruction has been executed, the processor first check is there any exception in the last execution, then increase PC by 2 or 4 depending on current state. If an exception occur, ARM7 will change its running mode, store PC in the LR of current mode and begin to process current exception without modifying the PC register.
But it make no sense when analyzing returning instructions. I can not work out why PC will be assigned LR when returning from an undefined-instruction-exception while LR-4 from prefetch-abort-exception, don't both of these exceptions happened at the decoding state? What's more, according to my textbook, PC will always be assigned LR-4 when returning from prefetch-abort-exception no matter what state the processor is(ARM or Thumb) before exception occurs. However, I think PC should be assigned LR-2 if the original state is Thumb, since a Thumb-instruction is 2 bytes long instead of 4 bytes which an ARM-instruction holds, and we just wanna roll-back an instruction in current state. Is there any flaws in my reasoning or something wrong with the textbook.
Seems a long question. I really hope anyone can help me get the right answer.
Thanks in advance.
You return to LR from undefined-instruction handling because that points to the instruction after the one that caused the trap; you don't want to return to the same undefined instruction again, it'll only hit the same trap.
You return to LR-4 from prefetch-abort if you want to execute the same instruction again; presumably because you've mapped some memory in for it so it'll now work.
At what point in the pipeline an ARM7 actually increases its PC is irrelevant, because the value of PC during execution and consequently the value of LR in abort handlers is something laid down as part of the ARM architecture standard, based largely on what the ancient ARM2 did with its PC.
However, I think PC should be assigned LR-2 if the original state is Thumb
That would make sense, but then the exception handler would need to know whether the original code that caused it to trigger was ARM or Thumb code. This might have impacted compatibility too, as there was plenty of non-Thumb-aware exception handling code around. So instead the Thumb architecture fudged the LR on entry to exception handlers so that the handler could always use the same instruction to return, the one they were used to using for non-Thumb code.

Could ARM9 Prefetch Abort Exception be a software problem?

So I'm getting a "prefetch abort" exception on our arm9 system. This system does not have an MMU, so is there anyway this could be a software problem? All the registers seem correct to me, and the code looks right (not corrupted) from the JTAG point of view.
Right now I'm thinking this is some kind of hardware issue (although I hate to say it - the hardware has been fine until now).
What exactly is the exception you're getting?
Last time this happened to me, I went up the wrong creek for a while because I didn't realize an ARM "prefetch abort" meant the instruction prefetch, not data prefetch, and I'd just been playing with data prefetch instructions. It simply means that the program has attempted to jump to a memory location that doesn't exist. (The actual problem was that I'd mistyped "go 81000000" as "go 81000" in the bootloader.)
See also:
http://www.keil.com/support/docs/3080.htm (KB entry on debugging data aborts)
http://www.ethernut.de/en/documents/arm-exceptions.html (list of ARM exceptions)
What's the address that the prefetch abort is triggering on. It can occur because the program counter (PC or R15) is being set to an address that isn't valid on your microcontroller (this can happen even if you're not using an MMU - the microcontroller's address space likely has 'holes' in it that will trigger the prefetch abort). It could also occur if you try to prefetch an address that would be improperly aligned, but I think this dpends on the microcontroller implementation (the ARM ARM lists the behavior as 'UPREDICTABLE').
Is the CPU actually in Abort mode? If it's executing the Prefetch handler but isn't in abort mode that would mean that some code is branching through the prefetch abort vector, generally through address 0x0000000c but controllers often allow the vector addresses to be remapped.

How to determine why a task destroys , VxWorks?

I have a VxWorks application running on ARM uC.
First let me summarize the application;
Application consists of a 3rd party stack and a gateway application.
We have implemented an operating system abstraction layer to support OS in-dependency.
The underlying stack has its own memory management&control facility which holds memory blocks in a doubly linked list.
For instance ; we don't directly perform malloc/new , free/delege .Instead we call OSA layer's routines and it gets the memory from OS and puts it in a list then returns this memory to application.(routines : XXAlloc , XXFree,XXReAlloc)
And when freeing the memory we again use XXFree.
In fact this block is a struct which has
-magic numbers indication the beginning and end of memory block
-size that user requested allocated
-size in reality due to alignment issue previous and next pointers
-pointer to piece of memory given back to application. link register that shows where in the application xxAlloc is called.
With this block structure stack can check if a block is corrupted or not.
Also we have pthread library which is ported from Linux that we use to
-create/terminate threads(currently there are 22 threads)
-synchronization objects(events,mutexes..)
There is main task called by taskSpawn and later this task created other threads.
this was a description of application and its VxWorks interface.
The problem is :
one of tasks suddenly gets destroyed by VxWorks giving no information about what's wrong.
I also have a jtag debugger and it hits the VxWorks taskDestoy() routine but call stack doesn't give any information neither PC or r14.
I'm suspicious of specific routine in code where huge xxAlloc is done but problem occurs
very sporadic giving no clue that I can map it to source code.
I think OS detects and exception and performs its handling silently.
any help would be great
regards
It resolved.
I did an isolated test. Allocated 20MB with malloc and memset with 0x55 and stopped thread of my application.
And I wrote another thread which checks my 20MB if any data else than 0x55 is written.
And quess what!! some other thread which belongs other components in CPU (someone else developed them) write my allocated space.
Thanks 4 your help
If your task exits, taskDestroy() is called. If you are suspicious of huge xxAlloc, verify that the allocation code is not calling exit() when memory is exhausted. I've been bitten by this behavior in a third party OSAL before.
Sounds like you are debugging after integration; this can be a hell of a job.
I suggest breaking the problem into smaller pieces.
Process
1) you can get more insight by instrumenting the code and/or using VxWorks intrumentation (depending on which version). This allows you to get more visibility in what happens. Be sure to log everything to a file, so you move back in time from the point where the task ends. Instrumentation is a worthwile investment as it will be handy in more occasions. Interesting hooks in VxWorks: Taskhooklib
2) memory allocation/deallocation is very fundamental functionality. It would be my first candidate for thorough (unit) testing in a well-defined multi-thread environment. If you have done this and no errors are found, I'd first start to look why the tas has ended.
other possible causes
A task will also end when the work is done.. so it may be a return caused by a not-so-endless loop. Especially if it is always the same task, this would be my guess.
And some versions of VxWorks have MMU support which must be considered.