gem5-dev@gem5.org

The gem5 Developer List

View all threads

Fwd: Question about Exception Handling and Instruction Decoding in Gem5-based ARM Minor CPU

YY
YF Yeh
Wed, Oct 30, 2024 8:49 AM

I regret to inform you that the previous email was automatically rejected
by the Gem5 system due to a technical issue (Gem5 account issue). I resend
the email to ensure its successful delivery.

Hi Experts,

I hope this email finds you well. I am Y.F., an engineer from Google.
I'm reaching out because I recently encountered an issue with the exception
handling mechanism in the GEM5 ARM MINOR CPU model, specifically when
executing programs with Thumb instructions. Here's what I found:

Exception Return Address Handling:

In src/arch/arm/faults.cc, the next program counter (PC) after an exception
is retrieved from the linker register and then incremented by 4 bytes
(using thumbPcOffset(false)). However, I believe this might be incorrect.
Thumb instructions can be either 2 or 4 bytes long, so simply adding 4
might not always point to the correct next instruction. Additionally,
cur_pc already
holds the PC value of the next instruction, so I'm unsure why it needs to
be incremented again.
[image: image.png]

Instruction Decoding (IWNPC function):

In src/arch/arm/pcstate.hh, the instIWNPC function determines whether an
instruction is Arm or Thumb based on the least significant bit (bit-0) of
the instruction address. Since Thumb instructions can be 2 bytes long, this
approach might not be accurate. Shouldn't the checking bit be bit-1 instead
of bit-0?
[image: image.png]

Workaround and Questions:

As a temporary solution, I've been adding 1 to cur_pc when the program is
compiled with Thumb instructions, and this seems to work. However, I'd like
to understand this issue better:

  • Has anyone else encountered this issue with exception return address
    handling in the GEM5 ARM MINOR CPU with Thumb instructions?
  • Have there been any tests of exception handling run on ARM MINOR CPU
    using the T32 instruction (a 2-byte Thumb instruction) ?
  • If so, could you share those tests or point me in the right direction
    to find them?

[image: image.png]

I appreciate your insights and any information you can provide on this
matter.

Thanks,
Y.F.

I regret to inform you that the previous email was automatically rejected by the Gem5 system due to a technical issue (Gem5 account issue). I resend the email to ensure its successful delivery. Hi Experts, I hope this email finds you well. I am Y.F., an engineer from Google. I'm reaching out because I recently encountered an issue with the exception handling mechanism in the GEM5 ARM MINOR CPU model, specifically when executing programs with Thumb instructions. Here's what I found: *Exception Return Address Handling:* In src/arch/arm/faults.cc, the next program counter (PC) after an exception is retrieved from the linker register and then incremented by 4 bytes (using thumbPcOffset(false)). However, I believe this might be incorrect. Thumb instructions can be either 2 or 4 bytes long, so simply adding 4 might not always point to the correct next instruction. Additionally, cur_pc already holds the PC value of the next instruction, so I'm unsure why it needs to be incremented again. [image: image.png] *Instruction Decoding (IWNPC function):* In src/arch/arm/pcstate.hh, the instIWNPC function determines whether an instruction is Arm or Thumb based on the least significant bit (bit-0) of the instruction address. Since Thumb instructions can be 2 bytes long, this approach might not be accurate. Shouldn't the checking bit be bit-1 instead of bit-0? [image: image.png] *Workaround and Questions:* As a temporary solution, I've been adding 1 to cur_pc when the program is compiled with Thumb instructions, and this seems to work. However, I'd like to understand this issue better: - Has anyone else encountered this issue with exception return address handling in the GEM5 ARM MINOR CPU with Thumb instructions? - Have there been any tests of exception handling run on ARM MINOR CPU using the T32 instruction (a 2-byte Thumb instruction) ? - If so, could you share those tests or point me in the right direction to find them? [image: image.png] I appreciate your insights and any information you can provide on this matter. Thanks, Y.F.
GT
Giacomo Travaglini
Wed, Oct 30, 2024 3:36 PM

Hi YF,

On 30/10/2024 08:49, YF Yeh wrote:

Exception Return Address Handling:

In src/arch/arm/faults.cc, the next program counter (PC) after an exception is retrieved from the linker register and then incremented by 4 bytes (using thumbPcOffset(false)). However, I believe this might be incorrect. Thumb instructions can be either 2 or 4 bytes long, so simply adding 4 might not always point to the correct next instruction. Additionally, cur_pc already holds the PC value of the next instruction, so I'm unsure why it needs to be incremented again.

[image.png]

Just to clarify, the logic you posted is not retrieving the next PC from link register (with the increment). It is actually the other way around: it is calculating the link register value from the current PC (when the exception happen) + an offset which is exception type dependent.

So it is not true that it always gets incremented by 4 bytes. The amount of increment depends on the exception type and you can check it in faults.cc 1 (in the line for UndefinedInstruction, the offset is 4 in Arm mode, and 2 in Thumb mode)

Instruction Decoding (IWNPC function):

In src/arch/arm/pcstate.hh, the instIWNPC function determines whether an instruction is Arm or Thumb based on the least significant bit (bit-0) of the instruction address. Since Thumb instructions can be 2 bytes long, this approach might not be accurate. Shouldn't the checking bit be bit-1 instead of bit-0?

[image.png]

There reason why the bit-0 is checked (and not bit-1) is because of how arm-thumb branch and exchange (BX) works.

Basically a BX instruction will check the LSB and it will switch CPU mode to T32 if it is set, to A32 otherwise. It has to be noted that the

BX address won't be the future PC: regardless of the next mode, the LSB will always be cleared to zero.

Workaround and Questions:

As a temporary solution, I've been adding 1 to cur_pc when the program is compiled with Thumb instructions, and this seems to work. However, I'd like to understand this issue better:

  • Has anyone else encountered this issue with exception return address handling in the GEM5 ARM MINOR CPU with Thumb instructions?
  • Have there been any tests of exception handling run on ARM MINOR CPU using the T32 instruction (a 2-byte Thumb instruction) ?
  • If so, could you share those tests or point me in the right direction to find them?

[image.png]

I appreciate your insights and any information you can provide on this matter.

I presume the reason why you are posting this is because you found a bug while executing some thumb code. I think the first step would be to understand (via gdb or dprintf) which is the exception being triggered.
But just so you know the logic you posted has nothing to do with the MinorCPU; it is actually shared by all CPU models in gem5. So if the error happens in MinorCPU only, it might be the issue is microrchitectural and not directly related to the architecture per se

Hope this helps! Let me know if this answers your questions

Giacomo

Thanks,

Y.F.
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

Hi YF, On 30/10/2024 08:49, YF Yeh wrote: Exception Return Address Handling: In src/arch/arm/faults.cc, the next program counter (PC) after an exception is retrieved from the linker register and then incremented by 4 bytes (using thumbPcOffset(false)). However, I believe this might be incorrect. Thumb instructions can be either 2 or 4 bytes long, so simply adding 4 might not always point to the correct next instruction. Additionally, cur_pc already holds the PC value of the next instruction, so I'm unsure why it needs to be incremented again. [image.png] Just to clarify, the logic you posted is not retrieving the next PC from link register (with the increment). It is actually the other way around: it is calculating the link register value from the current PC (when the exception happen) + an offset which is exception type dependent. So it is not true that it always gets incremented by 4 bytes. The amount of increment depends on the exception type and you can check it in faults.cc [1] (in the line for UndefinedInstruction, the offset is 4 in Arm mode, and 2 in Thumb mode) Instruction Decoding (IWNPC function): In src/arch/arm/pcstate.hh, the instIWNPC function determines whether an instruction is Arm or Thumb based on the least significant bit (bit-0) of the instruction address. Since Thumb instructions can be 2 bytes long, this approach might not be accurate. Shouldn't the checking bit be bit-1 instead of bit-0? [image.png] There reason why the bit-0 is checked (and not bit-1) is because of how arm-thumb branch and exchange (BX) works. Basically a BX instruction will check the LSB and it will switch CPU mode to T32 if it is set, to A32 otherwise. It has to be noted that the BX address won't be the future PC: regardless of the next mode, the LSB will always be cleared to zero. Workaround and Questions: As a temporary solution, I've been adding 1 to cur_pc when the program is compiled with Thumb instructions, and this seems to work. However, I'd like to understand this issue better: * Has anyone else encountered this issue with exception return address handling in the GEM5 ARM MINOR CPU with Thumb instructions? * Have there been any tests of exception handling run on ARM MINOR CPU using the T32 instruction (a 2-byte Thumb instruction) ? * If so, could you share those tests or point me in the right direction to find them? [image.png] I appreciate your insights and any information you can provide on this matter. I presume the reason why you are posting this is because you found a bug while executing some thumb code. I think the first step would be to understand (via gdb or dprintf) which is the exception being triggered. But just so you know the logic you posted has nothing to do with the MinorCPU; it is actually shared by all CPU models in gem5. So if the error happens in MinorCPU only, it might be the issue is microrchitectural and not *directly* related to the architecture per se Hope this helps! Let me know if this answers your questions Giacomo [1]: https://github.com/gem5/gem5/blob/stable/src/arch/arm/faults.cc#L213 Thanks, Y.F. IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.