Re: RFC: partially available registers

Pedro Alves
2011-07-26T15:31:37Z

On Friday 22 July 2011 20:30:53, Tom Tromey wrote:
> >>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:

> Pedro> But before the <unavailable> stuff, it meant "supply the register
> Pedro> as 0". I seem to remember discussing this AVX stuff with H.J.,
> Pedro> and coming to the conclusion that what want is really 0, but
> Pedro> maybe not.
>
> I am far from being an expert in this area,

Same here...

> but from the Intel Architecture manual, section 13.5.1:

Thanks. I finally took a bit to read that too.

> Saving the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 state using FXSAVE
> requires processor overhead. If the new task does not access x87 FPU,
> MMX, XMM, and MXCSR registers, avoid overhead by not automatically
> saving the state on a task switch.
>
> The TS flag in control register CR0 is provided to allow the operating
> system to delay saving the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 state
> until an instruction that actually accesses this state is encountered in
> a new task.
>
> So I think what is going on here is that the upper bits of these
> registers are truly unavailable, because the inferior has never executed
> an instruction referencing them.

My mental model of <unavailable> is:

<unavailable> means the object exists, and its value exists,
but we have no means to fetch it. This corresponds to trying
to print the value of a register while inspecting a traceframe,
while that register had not been collected by the corresponding
tracepoint -- the register exists in the architecture/machine, but we
can't know what value it had when the tracepoint hit. It also
corresponds to a (trimmed/partial) core dump file not containing a
dump of all the machine's registers, or a dump of all the process'es
mapped memory (due to ulimit, perhaps). And corresponds to not
being able to get at some register's current value because the
debug API exposes no means to get at the current value. Along
with other similar scenarios.

Let me brain dump what I think is happening in this avx case,
to make sure we're on the same page:

In this case, IIUC, with the delayed xsave mechanism active,
if a task has already accessed the x87 states, but hasn't triggered
a delayed x87 states' save/restore since the last context switch, the
current value of the x87 states of that task should be in the
save area (and valie), which is what ptrace gives us when we read
registers. For a task that did access (and change) the x87 state
since the last x87 state save, (I hope!) a ptrace stopped task's
save area is up to date with the real x87 states.

That is, at runtime, the from ptrace's perpective, the delay/lazy
scheme should be transparent, save for one case...

... that is the case of gdb/ptrace reading an x87 state
before the program had first accessed the state itself for the
first time.

H.J.Lu wrote:

> Values in vector registers are invalid, not unavailable. OS
> initializes them to zero when they are set the firs time in
> a program. I prefer *value not valid".

That is, in between the program starting, and the program
acessing the vector registers, the register's values are
invalid. But, given that the kernel will fill them
in with zero's on first access (meaning, from userspace's
perspective, it's the same as if the registers have always
been zero from the start of the program), I think it's best
that a debugger provides the same illusion to the user.

As H.J. wrote:

> GDB may update vector registers before they are set by program.
> GDB sets proper bits in XSAVE area to tell OS/hardware that vector
> registers now have valid values.

... and indeed this is what i387-tdep.c:i387_collect_xsave
appears to be doing.

Am I making sense?

> Pedro> Whatever the answer, we need to fix one of native
> Pedro> gdb or gdbserver for consistency.
>
> If you agree with what I have checked in, I will update gdbserver.

I think your patch implements the right interface for partial
registers support. I like it...

> Otherwise, let me know what you think would be correct and I will
> implement that, instead, for both.

... but I think that we should go with 0, instead of <unavailable>,
meaning changing x87-tdep.c:i387_supply_xsave to supply
explicity zeroed buffer, instead of a NULL pointer, like
gdbserver does.

--
Pedro Alves