Simple way to determine current processor mode on ARMv7-A
Asked Answered
R

0

7

On an ARMv7-A processor, I am looking for a simple way to determine the current mode of the processor (User, Supervisor, IRQ, etc) from any mode. This will allow me to dynamically decide whether to perform certain actions, such as making a supervisor call or performing an action directly.

At first glance, this seemed simple. The CPSR contains the (M) mode bits, which determine the processor mode.

Section B1.3.3 (Program Status Registers), on page 1150 of the revision C.b of the ARMv7-A Architecture Reference Manual, states:

This field can be written only at PL1 or higher. Its value can be read in any mode, but ARM deprecates software executing at PL0 making any use of its value, or attempting to change it.

So, use of the the CPSR.M bits is deprecated in user mode, but should work.

However, moving on to actually reading the CPSR using MRS (which is the only way I know of). Section B9.3.8 (MRS) on page 1988 of the ARM states:

An MRS that is executed in User mode and accesses the CPSR returns an UNKNOWN value for the CPSR.{E, A, I, F, M} fields.

Since these fields are unknown, there does not seem to be a way of reading the mode bits from user mode. Is there some alternate way to read the CPSR from user mode, or some alternate way to determine which mode code is executing?

I could likely instrument the undefined instruction exception, and attempt an instruction illegal in user mode, but I am hoping that there is a better way.

Ransom answered 14/3, 2014 at 19:38 Comment(6)
are there situations where this what mode am I code is going to be able to run everywhere? Basically where and why would you need to know what mode you are in?Subtract
The use case I have is for functions that may be called from an OS kernel, or from userspace. If called from userspace, they need to make a service call. If called from the kernel, they can skip the service call and perform the resulting action directly.Ransom
Technically, I can work around this issue by either splitting all functions between kernel and userspace, or by making service calls work, even when originating in the kernel.Ransom
Which OS? Does it have a defined kernel/userspace memory mapping such that you could inspect your caller's (or your own) address and work it out from there?Eunuchize
It is for an OS that I am writing myself. I ended up working around this issue by reworking my SVC handler to support entry from any mode, so service calls can be made unconditionally.Ransom
I have a feeling having kernel code and user code calling the same function and determining at runtime whether to make an SVCall or call directly would possibly open up security holes.Audiovisual

© 2022 - 2024 — McMap. All rights reserved.