I have a ARMv5-powered non-XScale device (the SHARP Brain™ electronic dictionary) with Windows Embedded CE 6.0 installed in NAND flash, and I use TCPMP to play my favorite AAC tunes and MPEG-4 movies.
But, when I start TCPMP, sometimes TCPMP freezes. So I looked into TCPMP and I managed to found that the freeze happens when this code is executed.
CheckARMXScale PROC
mov r0,#0x1000000
mov r1,#0x1000000
mar acc0,r0,r1 ; <--- here
mov r0,#32
mov r1,#32
mra r0,r1,acc0
cmp r0,#0x1000000
moveq r0,#1
movne r0,#0
cmp r1,#0x1000000 ;64bit or just 40bit?
moveq r0,#2
mov pc,lr
This code determines whether XScale is present by trying executing XScale instruction, and catching the exception if the "Undefined Instruction" exception was thrown.
The problem is that somehow the system fails to pass this exception to TCPMP properly, causing TCPMP to freeze. It seems to be not because of Windows CE, but rather because of buggy drivers in this device. Any driver updates are not expected since running TCPMP on this device is not officially supported.
I posted this issue to 2channel, and some people claimed that this way to determine if XScale is present is not good, but no one even tried to find a better way. So I googled and read through ARMv5 Architecture Reference Manual and so on, but I could find nothing. It appears that almost every program that utilizes XScale instruction set determines if XScale is present in the same way.
The question is that, is it possible to determine if XScale instruction set is present, without making use of any exception or any CPU mode except user mode?
Try IOCTL_PROCESSOR_INFORMATION
(needs switching into kernel mode) read the CP15 register c0, Main ID register aka ID Code Register aka ARM CPUID. The top byte is the implementor which will be 0x69 ('i', Intel) for XScale.
Check also this thread.
Related
I am trying to understand how interrupts work in an ARM architecture(ARM7TDMI to be specific). I know that there are seven exceptions (Reset,Data Abort, FIQ, IRQ, Pre-fetch abort, SWI and Undefined instruction) and they execute in particular modes(Supervisor, Abort, FIQ, IRQ, Abort, Supervisor and Undefined respectively). I have the following questions.
1. When the I and F bits in CPSR(status register) are set to 1 to disable external and fast interrupt, does the other 5 exceptions are also disabled ?
2. If the SWI is not disabled when I and F bits are enabled then, is it possible to intentionally trigger a SWI exception within ISR of an external interrupt?
3.When any interrupt is triggered saving the CPSR to SPSR, changing the mode is done by the processor itself. So, is it enough to write the ISR handler function and update the vector table with the handler addresses(I don't want to save r0 to r12 general purpose registers) ?
4. Whenever the mode of execution is changed does context saving happens internally by the processor(even when we change the mode manually)?
5. How to mask/disable a SWI exception?
Thank you.
When the I and F bits in CPSR(status register) are set to 1 to disable external and fast interrupt, does the other 5 exceptions are
also disabled ?
No, these all depend on your code to be correct. For instance, a compiler will not normally generate an swi instruction.
If the SWI is not disabled when I and F bits are enabled then, is it possible to intentionally trigger a SWI exception within ISR of an
external interrupt?
Yes, it is possible. You may check the mode of the SPSR in your swi handler and abort (or whatever is appropriate) if you want.
3.When any interrupt is triggered saving the CPSR to SPSR, changing the mode is done by the processor itself. So, is it enough to write
the ISR handler function and update the vector table with the handler
addresses(I don't want to save r0 to r12 general purpose registers) ?
No one wants to save registers. However, if you use r0 to r12 then the main code will become corrupt. The banked sp is made to store these registers. Also, the vector table is not a handler address but an instruction/code.
Whenever the mode of execution is changed does context saving happens internally by the processor(even when we change the mode
manually)?
No, the instruction/code in the vector page is responsible for saving the context. If you have a pre-emptable OS then you need to save the context for the process and restore later. You may have 1000s of processes. So a CPU could not do this automatically. Your context save area may be rooted in the super mode stack; you can use the ISR/FIQ sp as a temporary register in this case. For instance, the switch_to function in ARM Linux maybe helpful. thread_info is rooted in the supervisor stack for the kernel management of the user space process/thread. The minimum code (with features removed) is,
__switch_to:
add ip, r1, #TI_CPU_SAVE # Get save area to `ip`.
stmia ip!, {r4 - sl, fp, sp, lr} ) # Store most regs on stack
add r4, r2, #TI_CPU_SAVE # Get restore area to `r4`
ldmia r4, {r4 - sl, fp, sp, pc} ) # Load all regs saved previously
# note the last instruction returns to a previous
# switch_to call by the destination thread/process
How to mask/disable a SWI exception?
You can not do this. You could write an swi handler that does nothing but increment the PC and/or you could just jump to the undefined handler depending on what it does.
I am working with a Cortex-A9 and my program crashes because of an UNDEFINED_INSTRUCTION exception. The assembly line that causes this exception is according to my debugger's trace:
Trace #9999 : S:0x022D9A7C E92D4800 ARM PUSH {r11,lr}
Exception: UNDEFINED_INSTRUCTION (9)
I program in C and don't write assembly or binary and I am using gcc. Is this really the instruction that causes the exception, i.e. is the encoding of this PUSH instruction wrong and hence a compiler/assembler bug? Or is the encoding correct and something strange is going on? Scrolling back in the trace I found another PUSH instruction, that does not cause errors and looks like this:
Trace #9966 : S:0x022A65FC E52DB004 ARM PUSH {r11}
And of course there are a lot of other PUSH instruction too. But I did not find any other that tries to push specifically R11 and LR, so I can't compare.
I can't answer my own question, so I edit it:
Sorry guys, I don't exactly know what happend. I tried it several times and got the same error again and again. Then I turned the device off, went away and tried it again later and know it works fine...
Maybe the memory was corrupted somehow due to overheating or something? I don't know. Thanks for your answers anyway.
I use gcc 4.7.2 btw.
I suspect something is corrupting the SP register. Load/store multiple (of which PUSH is one alias) to unaligned addresses are undefined in the architecture, so if SP gets overwritten with something that's not a multiple of 4, then a subsequent push/pop will throw an undef exception.
Now, if you're on ARM Linux, there is (usually) a kernel trap for unaligned accesses left over from the bad old days which if enabled will attempt to fix up most unaligned load/store multiple instructions (despite them being architecturally invalid). However if the address is invalid (as is likely in the case of SP being overwritten with nonsense) it will give up and leave the undef handler to do its thing.
In the (highly unlikely) case that the compiler has somehow generated bad code that is fix-uppable most of the time,
cat /proc/cpuinfo/alignment
would show some non-zero fixup counts, but as I say, it's most likely corruption - a previous function has smashed the stack in such a way that an invalid SP is loaded on return, that then shows up at the next stack operation. Best double-check your pointer and array accesses.
Just for the purposes of experimenting and playing around, I wrote the following short x64 assembly program:
.code
AsmFun proc
mov rax, MyLabel
mov byte ptr [rax], 0C3h ; C3 is x64 machine code for "ret"
MyLabel:
mov rax, 239847 ; This isn't "ret"
AsmFun endp
end
(I then called the code from C.)
It compiles/assembles/links just fine, but when I walk through the program, Visual Studio complains that an un-handled exception has been raised: "Access writing violation as [MyLabel].", where of course it doesn't actually say "[MyLabel]", but rather the address that happens to be at in memory.
Why is this happening? Is it a Windows thing that was put in place to avoid security exploits?
I live in Linux world, but perhaps you can adapt what I've found out.
Memory pages are generally read-only if they have execute permission. How I got around this was with mmap() and mprotect()... I'm sure there's something similar in Windows. It's a good bet the Mono source code would shed some light.
I used mmap() to allocate a new page with write access (but not read or execute). I populated it, then called mprotect() to change it to read-only and executable.
Don't forget... there are registers you want to avoid trashing. See the ABI documentation for further details.
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.
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.