From: Jim Wilson <jimw@sifive.com>
To: Andrew Burgess <andrew.burgess@embecosm.com>
Cc: gdb@sourceware.org
Subject: Re: RISC-V: decr_pc_after_break causing problems
Date: Wed, 11 Jul 2018 18:20:00 -0000 [thread overview]
Message-ID: <CAFyWVaav9FK4-TTA6TprkEfds2oJKfX5B1GfiMUdwpZXY6ZLAw@mail.gmail.com> (raw)
In-Reply-To: <20180711174659.GA6398@embecosm.com>
On Wed, Jul 11, 2018 at 10:46 AM, Andrew Burgess
<andrew.burgess@embecosm.com> wrote:
> * Jim Wilson <jimw@sifive.com> [2018-06-25 19:54:14 -0700]:
>
>> The RISC-V port in the riscv-tdep.c file has
>> set_gdbarch_decr_pc_after_break (gdbarch, (has_compressed_isa ? 2 : 4));
>>
>> The privileged architecture spec v1.10 states in section 3.2.1 that
>> the ebreak instruction causes the receiving privilege mode's epc
>> register to be set to the address of the ebreak instruction, not the
>> address of the following instruction. So gdb should not be
>> decrementing from the pc after a breakpoint is hit.
>
> Maybe I'm going to look completely silly here, but....
>
> ....aren't epc and pc different registers?
When you take a trap in linux, pc gets copied to sepc, and pc is set
to the linux kernel trap handler code. The trap handler then stores
sepc into the process context, as it is the application pc. When gdb
uses ptrace to get the pc, it is given the sepc, because that is the
application pc value. So as far as gdb is concerned, there is only
one program counter. The kernel just happens to call it sepc instead
of pc because that is where the application pc lives in the kernel.
When the kernel returns from a trap, executing the sret instruction,
the sepc is copied back into the pc thus returning us to the original
user code.
In the linux kernel sources, in arch/riscv/include/asm/ptrace.h, it has
struct pt_regs {
unsigned long sepc;
unsigned long ra;
unsigned long sp;
unsigned long gp;
...
};
so the kernel stores the pc where x0 would go, because we don't need
to save x0, and calls it sepc.
> The epc is really many register, right? one for each privilege level,
> uepc, sepc, and mepc.
Yes, but since linux runs at supervisor level, there is only sepc that
is interesting in this case.
> The spec is clear that when an ebreak or c.ebreak is hit the contents
> of *epc are the contents of the breaking instruction, but nothing is
> said about the contents of pc.
pc gets set to the trap handler address specified in the trap vector
table. For linux, the address of that is presumably held in the stvec
CSR, and then either you go to a default offset from stvec, or it is
vectored by the exception number, or whatever, I haven't really looked
at that code.
> Assuming that my above observations are correct, then when we hit a
> breakpoint *epc is defined, but pc is not, an implementation could do
> anything, right? The two obvious choices are not increment pc, or
> increment pc.
No, the pc has to be the address of a trap handler in the kernel,
because we took a trap.
> Right now my understanding is that GDB doesn't have special support
> for fetching the program counter from different places depending on
> the current inferior state (stopped at breakpoint, not stopped at
> breakpoint). So, somehow the value in *epc needs to be passed back
> into the pc register (I guess).
The kernel takes care of sepc. Gdb only needs to worry about the pc.
At least, that is how it works when running an OS like linux. I don't
know how this is going to work in an embedded system. Perhaps it is
OpenOCD that takes care of mapping the appropriate xepc to pc
depending on processor mode, and maybe OpenOCD also sets the
appropriate xtvec register to point at its trap handler code.
At no point in this process do we need to add or subtract anything from the pc.
Jim
next prev parent reply other threads:[~2018-07-11 18:20 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-26 2:54 Jim Wilson
2018-06-26 19:15 ` Tim Newsome
2018-07-04 0:17 ` Jim Wilson
2018-07-04 0:35 ` Palmer Dabbelt
2018-07-05 22:54 ` John Baldwin
2018-07-11 14:52 ` Andrew Burgess
2018-07-11 17:47 ` Andrew Burgess
2018-07-11 18:20 ` Jim Wilson [this message]
2018-07-16 22:09 ` Jim Wilson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAFyWVaav9FK4-TTA6TprkEfds2oJKfX5B1GfiMUdwpZXY6ZLAw@mail.gmail.com \
--to=jimw@sifive.com \
--cc=andrew.burgess@embecosm.com \
--cc=gdb@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox