FreeBSD's armstub8-gic.bin or armstub8.bin is bigger than the reserve area is it loaded to; later part ends up overwritten
Mark Millard
marklmi at yahoo.com
Wed Feb 12 02:18:08 UTC 2020
Using FreeBSD's armstub8-gic.bin as the example that
applies to my test context: It has something like 0x15bc
bytes to the end of its last instruction. (I looked at
the .elf from a build that I did.)
Doing an experiment to make the PSCI version request
also report where it sees its _start,
el3_exception_vectors, and loop addresses showed
(my summary):
_start at 0x0
el3_exception_vectors at 0x800
loop at 0x100c
(given my code additions that made the size 0x15c8
instead of 0x15bc).
So: loaded to Address 0x0. I confirmed in ddb that
I see the code sequence starting at 0x0.
In my context boot -v was reporting the below.
Compare and contrast the reserved size starting
at 0x0 to the size of armstub8-gic's code
span:
Type Physical Virtual #Pages Attr
Reserved 000000000000 0 00000001 WB
ConventionalMemory 000000001000 1000 00007ef1 WB
. . .
Physical memory chunk(s):
0x00001000 - 0x39f48fff, 927 MB ( 237384 pages)
0x39f50000 - 0x39f50fff, 0 MB ( 1 pages)
. . .
Excluded memory regions:
0x00000000 - 0x00000fff, 0 MB ( 1 pages) NoAlloc
0x32000000 - 0x33773fff, 23 MB ( 6004 pages) NoAlloc
Using ddb I confirmed that starting at 0x1000
armstub8-gic.bin 's content had been replaced.
That includes swap32, memmove, and fixup_dt_blob.
It looks to me like fixup_dt_blob needs to take
into account the span of the armstub8* material
and reserve at least 1 more page (past the page
holding its self-observed start address) than is
now reserved. (Wording avoids assuming that all
aarch64 RPi*'s would use address 0x0.)
I do not claim to know that such a change would
be sufficient. But the above seems to be a
fragile structure.
Detailed evidence techniques:
I adjusted a copy of sysutils/rpi-firmware 's armstub8
code to have the pSCI version request also fill in
the address of _start, el3_exception_vectors, and loop:
psci_version:
/* Return v0.2 */
adr x3, loop
adr x2, el3_exception_vectors
adr x1, _start
mov x0, #0x00000002
eret
I then added a direct use of arm_smccc_smc in a place
early enough that I'd never seen the resulting version
number to be wrong:
uma_startup2();
//HACK!!!
#ifdef __aarch64__
struct arm_smccc_res result;
int psci_version= arm_smccc_smc(0x84000000,0,0,0,0,0,0,0,&result);
printf("psci_version+: %x %lx %lx %lx %lx\n", psci_version, result.a0, result.a1, result.a2, result.a3);
#endif
}
I added the printf in order find what address range over
which the armstub80-gic code would see itself span for my
RPi4B based test context. The result was:
psci_version+: 2 2 0 800 100c
So:
(minor) version 2 (twice)
_start at 0x0
el3_exception_vectors at 0x800
loop at 0x100c (given my code additions).
I'll note that this investigative hack was enough of
a change that the RPi4B made it to a login prompt
and I logged in. There were problems, but I could
do some stuff. The failure mechanism for the
"extra" cores (APs) was different, reporting
very early on:
Starting CPU 1 (1)
Failed to start CPU 1 (1)
Starting CPU 2 (2)
Failed to start CPU 2 (2)
Starting CPU 3 (3)
Failed to start CPU 3 (3)
===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)
More information about the freebsd-arm
mailing list