Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Feb 2020 10:27:51 -0800
From:      Mark Millard <marklmi@yahoo.com>
To:        Kyle Evans <kevans@freebsd.org>
Cc:        Ralf Wenk <iz-rpi03@hs-karlsruhe.de>, Andrew Turner <andrew@freebsd.org>, Oleksandr Tymoshenko <gonzo@freebsd.org>, freebsd-arm <freebsd-arm@freebsd.org>, Emmanuel Vadot <manu@freebsd.org>
Subject:   Re: A investigative hack that makes (for example) head -r356529 boot and operate normally an RPi4B (finally!): protect all armstub8-gic.bin's loaded content from replacement by the kernel
Message-ID:  <27BE7BAF-FD2C-41C6-B270-4BAF77D1FB0C@yahoo.com>
In-Reply-To: <1BE59567-E669-4A88-8389-2E321B0AC1AE@yahoo.com>
References:  <7E7605DC-021D-448A-8459-8EC26BA9836D.ref@yahoo.com> <7E7605DC-021D-448A-8459-8EC26BA9836D@yahoo.com> <E1j2EmR-000Mwm-ID@iz-wera-new.HS-Karlsruhe.DE> <CACNAnaHVYeuoK=4f7XzokpAVjcqd6ovD58-0LdP_vPGjiXQgdw@mail.gmail.com> <E1j2FRX-000MyR-1O@iz-wera-new.HS-Karlsruhe.DE> <E1j2G3j-000Mzo-Dw@iz-wera-new.HS-Karlsruhe.DE> <CACNAnaHUwu0GmqW9QZRhS2sMK0HpsjdYRz3YouL5FMBdWBCW-Q@mail.gmail.com> <B64C6065-D804-4D6F-8660-F8DBB9946DEB@yahoo.com> <36CF6E4B-5607-4752-B2DF-C265BCFB95BA@yahoo.com> <1BE59567-E669-4A88-8389-2E321B0AC1AE@yahoo.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On 2020-Feb-13, at 09:55, Mark Millard <marklmi at yahoo.com> wrote:

On 2020-Feb-13, at 09:36, Mark Millard <marklmi at yahoo.com> wrote:
>=20
>> On 2020-Feb-13, at 08:50, Mark Millard <marklmi at yahoo.com> wrote:
>>=20
>>> On 2020-Feb-13, at 07:22, Kyle Evans <kevans at freebsd.org> wrote:
>>>=20
>>>> On Thu, Feb 13, 2020 at 9:05 AM Ralf Wenk =
<iz-rpi03@hs-karlsruhe.de> wrote:
>>>>>=20
>>>>> On 2020-02-13 at 15:26 +0100 Ralf Wenk wrote:
>>>>>> On 2020-02-13 at 7:49 -0600 Kyle Evans wrote:
>>>>>>> On Thu, Feb 13, 2020 at 7:43 AM Ralf Wenk =
<iz-rpi03@hs-karlsruhe.de> wrote:
>>>>>>>>=20
>>>>>>>> On 2020-02-12 at 18:00 -0800 Mark Millard wrote via =
freebsd-arm:
>>>>>>>>> [...]
>>>>>>>>>=20
>>>>>>>>> # svnlite diff /usr/src/sys/dev/fdt/fdt_common.c
>>>>>>>>> Index: /usr/src/sys/dev/fdt/fdt_common.c
>>>>>>>>> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>>>>>>>>> --- /usr/src/sys/dev/fdt/fdt_common.c (revision 357529)
>>>>>>>>> +++ /usr/src/sys/dev/fdt/fdt_common.c (working copy)
>>>>>>>>> @@ -485,7 +485,18 @@
>>>>>>>>>=20
>>>>>>>>>   tuples =3D res_len / tuple_size;
>>>>>>>>>   reservep =3D (pcell_t *)&reserve;
>>>>>>>>> +#ifdef __aarch64__
>>>>>>>>> +     //HACK!!!
>>>>>>>>> +     // Reserve the first few pages, for example to
>>>>>>>>> +     // preserve armstub8-gic.bin or armstub.bin
>>>>>>>>> +     // content.
>>>>>>>>> +     mr[0].mr_start=3D 0;
>>>>>>>>> +     mr[0].mr_size=3D 2*4096;
>>>>>>>>> +     tuples++;
>>>>>>>>> +     for (i =3D 1; i < tuples; i++) {
>>>>>>>>> +#else
>>>>>>>>>   for (i =3D 0; i < tuples; i++) {
>>>>>>>>> +#endif
>>>>>>>>>=20
>>>>>>>>>           rv =3D fdt_data_to_res(reservep, addr_cells, =
size_cells,
>>>>>>>>>                   (u_long *)&mr[i].mr_start, (u_long =
*)&mr[i].mr_size);
>>>>>>>>> @@ -512,6 +523,11 @@
>>>>>>>>>=20
>>>>>>>>>   root =3D OF_finddevice("/reserved-memory");
>>>>>>>>>   if (root =3D=3D -1) {
>>>>>>>>> +             // Fail over to checking for and handling =
memreserve,
>>>>>>>>> +             // such as for a RPi4B.
>>>>>>>>> +             if (0 =3D=3D =
fdt_get_reserved_regions(reserved,mreserved))
>>>>>>>>> +                     return (0);
>>>>>>>>> +
>>>>>>>>>           return (ENXIO);
>>>>>>>>>   }
>>>>>>>>>=20
>>>>>>>>=20
>>>>>>>> I can confirm that with your patch(es) my RPi3 does not freeze =
any more
>>>>>>>> when loading mac_ntpd.ko. The patches are applied against =
r357853M.
>>>>>=20
>>>>> An reboot is working again too.
>>>>>=20
>>>>>>> Have you tested the RPi3 with just this second hunk of patch to
>>>>>>> fallover to memreserve, or is the first hunk definitely required =
as
>>>>>>> well?
>>>>>>=20
>>>>>> Good question. I tested both hunks together.
>>>>>> Will try what happens when just applying the second and report =
back.
>>>>>=20
>>>>> Here it is:
>>>>> Without the first hunk the system freezes again when loading =
mac_ntpd.ko.
>>>>> Also the CPU information during boot for CPUs 1 to 3 looks strange =
again.
>>>>>=20
>>>>=20
>>>> Yeah- I see it now; both armstubs are about 5k. I've raised an
>>>> issue[0] with upstream for armstub/rpi bits to work out the proper
>>>> solution, because I don't necessarily want to commit the =
workaround.
>>>> I'll throw up the second hunk on phabricator for review by =
#arm/#arm64
>>>> folks, because that seems to me the proper fallback.
>>>>=20
>>>> I also discovered some issues when trying to read /memreserve/ with
>>>> our dtc and filed a PR[1] to fix those.
>>>>=20
>>>> Thanks,
>>>>=20
>>>> Kyle Evans
>>>>=20
>>>> [0] https://github.com/raspberrypi/tools/issues/107
>>>> [1] https://github.com/davidchisnall/dtc/pull/59
>>>=20
>>> The DTB information below is from:
>>>=20
>>> U-Boot> fdt addr 0x7ef2000=20
>>> U-Boot> fdt print /      =20
>>>=20
>>> on a RPi4B 4 GiByte.
>>>=20
>>> On at least the RPi4B memreserve is not what causes
>>> the first page to be excluded:
>>>=20
>>>      memreserve =3D <0x3b400000 0x04c00000>;
>>>=20
>>> Nor is memory@0 the cause:
>>>=20
>>>      memory@0 {
>>>              device_type =3D "memory";
>>>              reg =3D <0x00000000 0x00000000 0x3b400000 0x00000000 =
0x40000000 0xbc000000>;
>>>      };
>>>=20
>>> (That also skips the memreserve area.)
>>>=20
>>> I do not find anything in the DTB that indicates
>>> to exclude the first page.
>>>=20
>>> My hypothesis is that the FreeBSD code excludes
>>> the page based on some less obvious relationship
>>> that I'm not identifying.
>>>=20
>>> There is the cpu-rlease-addr information that seems
>>> to refer to some 1st memory page content:
>>>=20
>>>      cpus {
>>>              #address-cells =3D <0x00000001>;
>>>              #size-cells =3D <0x00000000>;
>>>              enable-method =3D "brcm,bcm2836-smp";
>>>              phandle =3D <0x000000be>;
>>>              cpu@0 {
>>>                      device_type =3D "cpu";
>>>                      compatible =3D "arm,cortex-a72";
>>>                      reg =3D <0x00000000>;
>>>                      enable-method =3D "spin-table";
>>>                      cpu-release-addr =3D <0x00000000 0x000000d8>;
>>>                      phandle =3D <0x0000001d>;
>>>              };
>>>              cpu@1 {
>>>                      device_type =3D "cpu";
>>>                      compatible =3D "arm,cortex-a72";
>>>                      reg =3D <0x00000001>;
>>>                      enable-method =3D "spin-table";
>>>                      cpu-release-addr =3D <0x00000000 0x000000e0>;
>>>                      phandle =3D <0x0000001e>;
>>>              };
>>>              cpu@2 {
>>>                      device_type =3D "cpu";
>>>                      compatible =3D "arm,cortex-a72";
>>>                      reg =3D <0x00000002>;
>>>                      enable-method =3D "spin-table";
>>>                      cpu-release-addr =3D <0x00000000 0x000000e8>;
>>>                      phandle =3D <0x0000001f>;
>>>              };
>>>              cpu@3 {
>>>                      device_type =3D "cpu";
>>>                      compatible =3D "arm,cortex-a72";
>>>                      reg =3D <0x00000003>;
>>>                      enable-method =3D "spin-table";
>>>                      cpu-release-addr =3D <0x00000000 0x000000f0>;
>>>                      phandle =3D <0x00000020>;
>>>              };
>>>      };
>>=20
>>=20
>>=20
>>=20
>> Looking at the code there is:
>>=20
>>       /* Load the physical memory ranges */
>>       efihdr =3D (struct efi_map_header *)preload_search_info(kmdp,
>>           MODINFO_METADATA | MODINFOMD_EFI_MAP);
>>       if (efihdr !=3D NULL)
>>               add_efi_map_entries(efihdr);
>> #ifdef FDT
>>       else {
>>               /* Grab physical memory regions information from device =
tree. */
>>               if (fdt_get_mem_regions(mem_regions, &mem_regions_sz,
>>                   NULL) !=3D 0)
>>                       panic("Cannot get physical memory regions");
>>               arm_physmem_hardware_regions(mem_regions, =
mem_regions_sz);
>>       }
>>       if (fdt_get_reserved_mem(mem_regions, &mem_regions_sz) =3D=3D =
0)
>>               arm_physmem_exclude_regions(mem_regions, =
mem_regions_sz,
>>                   EXFLAG_NODUMP | EXFLAG_NOALLOC);
>> #endif
>>=20
>>       /* Exclude the EFI framebuffer from our view of physical =
memory. */
>>       efifb =3D (struct efi_fb *)preload_search_info(kmdp,
>>           MODINFO_METADATA | MODINFOMD_EFI_FB);
>>       if (efifb !=3D NULL)
>>               arm_physmem_exclude_region(efifb->fb_addr, =
efifb->fb_size,
>>                   EXFLAG_NOALLOC);
>> . . .
>>       if (boothowto & RB_VERBOSE) {
>>               print_efi_map_entries(efihdr);
>>               arm_physmem_print_tables();
>>       }
>>=20
>>=20
>> It looks to me like the boot -v text:
>>=20
>>                  Type     Physical      Virtual   #Pages Attr
>>              Reserved 000000000000            0 00000001 WB=20
>>    ConventionalMemory 000000001000         1000 00007ef1 WB=20
>>      BootServicesData 000007ef2000      7ef2000 0000001c WB=20
>>    ConventionalMemory 000007f0e000      7f0e000 00029f93 WB=20
>>      BootServicesData 000031ea1000     31ea1000 00000001 WB=20
>>            LoaderData 000031ea2000     31ea2000 00008001 WB=20
>>            LoaderCode 000039ea3000     39ea3000 000000a6 WB=20
>>              Reserved 000039f49000     39f49000 00000007 WB=20
>>      BootServicesData 000039f50000     39f50000 00000001 WB=20
>>              Reserved 000039f51000     39f51000 00000002 WB=20
>>   RuntimeServicesData 000039f53000     39f53000 00000001 WB RUNTIME
>>              Reserved 000039f54000     39f54000 00000001 WB=20
>>      BootServicesData 000039f55000     39f55000 00000002 WB=20
>>   RuntimeServicesData 000039f57000     39f57000 00000001 WB RUNTIME
>>            LoaderData 000039f58000     39f58000 00001408 WB=20
>>   RuntimeServicesCode 00003b360000     3b360000 00000010 WB RUNTIME
>>            LoaderData 00003b370000     3b370000 00000090 WB=20
>>      BootServicesData 000040000000     40000000 000bc000 WB=20
>>        MemoryMappedIO 0000fe100000     fe100000 00000001 RUNTIME
>>=20
>> is from print_efi_map_entries via the efihdr instead
>> of from the FreeBSD FDT code and the DTB.
>>=20
>> So is it u-boot that provides the efihdr for which
>> add_efi_map_entries generated those regions?
>>=20
>> That might explain why I do not find matching DTB
>> material for all of it.
>=20
>=20
> Looks like the efi memory map traces back to the loader
> and its use of GetMemoryMap (as far as FreeBSD goes):
>=20
> # grep -r "GetMemoryMap" /usr/src/sys/ | more
> /usr/src/sys/amd64/amd64/machdep.c:      * Memory map data provided by =
UEFI via the GetMemoryMap
> /usr/src/sys/arm64/arm64/machdep.c:      * Memory map data provided by =
UEFI via the GetMemoryMap
> /usr/src/sys/arm/arm/machdep_boot.c:     * Memory map data provided by =
UEFI via the GetMemoryMap
> /usr/src/sys/contrib/edk2/Include/Uefi/UefiSpec.h:  EFI_GET_MEMORY_MAP =
             GetMemoryMap;
>=20
> # grep -r "GetMemoryMap" /usr/src/stand/ | more
> /usr/src/stand/efi/loader/copy.c:               status =3D =
BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
> /usr/src/stand/efi/loader/main.c:       status =3D =
BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
> /usr/src/stand/efi/loader/main.c:       status =3D =
BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
> /usr/src/stand/efi/loader/bootinfo.c:                   status =3D =
BS->GetMemoryMap(&sz, mm, &efi_mapkey, &dsz, &mmver);
> /usr/src/stand/efi/loader/bootinfo.c:                           =
printf("%s: GetMemoryMap error %lu\n", __func__,
> /usr/src/stand/efi/include/efiapi.h:  EFI_GET_MEMORY_MAP              =
GetMemoryMap;


Here is the memmap from the loader that is just based on EFI's
GetMemoryMap from what I can tell from a wuick look:

Hit [Enter] to boot immediately, or any other key for command prompt.
Booting [/boot/kernel/kernel] in 8 seconds...=20

Type '?' for a list of commands, 'help' for more detailed help.
OK memmap=20
                   Type     Physical      Virtual   #Pages Attr
               Reserved 000000000000 000000000000 00000001 WB=20
     ConventionalMemory 000000001000 000000001000 00007ef1 WB=20
       BootServicesData 000007ef2000 000007ef2000 0000001c WB=20
     ConventionalMemory 000007f0e000 000007f0e000 00029f93 WB=20
       BootServicesData 000031ea1000 000031ea1000 00000001 WB=20
             LoaderData 000031ea2000 000031ea2000 00004000 WB=20
       BootServicesData 000035ea2000 000035ea2000 00000001 WB=20
             LoaderData 000035ea3000 000035ea3000 00004000 WB=20
             LoaderCode 000039ea3000 000039ea3000 000000a6 WB=20
               Reserved 000039f49000 000039f49000 00000007 WB=20
       BootServicesData 000039f50000 000039f50000 00000001 WB=20
               Reserved 000039f51000 000039f51000 00000002 WB=20
    RuntimeServicesData 000039f53000 000039f53000 00000001 WB=20
               Reserved 000039f54000 000039f54000 00000001 WB=20
       BootServicesData 000039f55000 000039f55000 00000002 WB=20
    RuntimeServicesData 000039f57000 000039f57000 00000001 WB=20
             LoaderData 000039f58000 000039f58000 00001408 WB=20
    RuntimeServicesCode 00003b360000 00003b360000 00000010 WB=20
             LoaderData 00003b370000 00003b370000 00000090 WB=20
       BootServicesData 000040000000 000040000000 000bc000 WB=20
         MemoryMappedIO 0000fe100000 0000fe100000 00000001=20
OK=20

So at the loader time frame, the 2nd page of memory is not
Reserved (in EFI terms).

It would appear to me that avoiding messing up the
armstub8*.bin content should apply this early as well.

So it may be sysutils/u-boot-rpi{3,4} that needs to
arrange sufficient room to prevent messing up such.
(Unless armstub8*.bin can adjust something that
u-boot's EFI interface is based on for that initial
"Reserved" area?)


=3D=3D=3D
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?27BE7BAF-FD2C-41C6-B270-4BAF77D1FB0C>