> Date: Fri, 20 Sep 2019 02:55:27 -0700
> From: Mike Larkin <[email protected]>
>
> On Fri, Sep 20, 2019 at 01:09:56AM +0900, YASUOKA Masahiko wrote:
> > Hi,
> >
> > I recently got a VAIO Pro PK. The diff below is required to boot.
> > Without the diff, it freezes during boot.
> >
>
> > Its EFI framebuffer is located 0x4000000000 (9 zeros). This is > 4GB
> > and higher than highest available memory of the machine. These
> > configuraions seem to cause the problem.
> >
> > * * *
> >
> > Call cninit() after pmap_bootstrap() is called. Since the EFI
> > framebuffer may be located > 4GB which is not initialized by locore,
> > but by pmap_bootstrap(). Also make the address parameter passed to
> > pmap_bootstrap() cover the framebuffer. Actually VAIO pro PK's
> > framebuffer is located higher than the highest available memory
> > region.
> >
> > ok? comments?
> >
>
> Hi,
>
> I have a few questions...
>
> 1. There seems to be no limit on the max PA that we extend to here.
> This means, for example, if EFI places the framebuffer past 2TB
> PA, we won't have enough direct map to cover the mapping. Plus
> I think this will end up extending the direct map to cover any hole
> between "end of phys mem" and "efi fb addr". At a minimum, I think
> we need some sort of max PA clamp here. I don't know what Sony's
> placement algorithm is, but 0x4000000000 is 256GB PA.
A dmesg and pcidump output would be useful.
I suspect that this is a discrete graphics card where the EFI frame
buffer resides in VRAM. Using the direct map in this case is probably
not the right thing to do.
> 2. What does delaying cninit do for machines that have errors or
> printfs before this? Would those even print anymore? This would
> affect all machines, even those without efifb, correct?
Yes and no. It doesn't affect the classic VGA glass console, but it
does mean serial output might disappear. That isn't acceptable I'd
say.
> 3. I am not a big fan of placing device-specific quirks in
> init_x86_64. Could this not be done in the efifb specific console
> init code? You could pmap_enter whatever you wanted there, based on
> the PA EFI sent you. Or does efifb go through the direct map for
> all video output? If so, we may be stuck creating that big direct map
> range. If that's the case though, we should probably try to restrict
> the permissions in the unused holes.
The direct map is only used early on in the boot process. The frame
buffer is remapped in mainbus_attach() such that we can use
write-combining. But that is done after we print copyright. I think
the remapping could be done a bit earlier, but not before uvm gets
initialized, which happens after we print the copyright message.
We don't have to use the direct map during early boot. If you gave us
some other way to map the framebuffer before pmap_bootstrap() has been
called we could stick that into efifb_cnattach_common(). We'd need
your help with that though. Note that the framebuffer can be fairly
large though (but we can probably come up with a reasonable upper
limit).
Cheers,
Mark
> > Index: sys/arch/amd64/amd64/machdep.c
> > ===================================================================
> > RCS file: /cvs/src/sys/arch/amd64/amd64/machdep.c,v
> > retrieving revision 1.259
> > diff -u -p -r1.259 machdep.c
> > --- sys/arch/amd64/amd64/machdep.c 7 Sep 2019 19:05:44 -0000 1.259
> > +++ sys/arch/amd64/amd64/machdep.c 19 Sep 2019 15:55:18 -0000
> > @@ -193,6 +193,8 @@ int lid_action = 1;
> > int pwr_action = 1;
> > int forceukbd;
> >
> > +int docninit;
> > +
> > /*
> > * safepri is a safe priority for sleep to set for a spin-wait
> > * during autoconfiguration or after a panic.
> > @@ -1371,6 +1373,7 @@ init_x86_64(paddr_t first_avail)
> > bios_memmap_t *bmp;
> > int x, ist;
> > uint64_t max_dm_size = ((uint64_t)512 * NUM_L4_SLOT_DIRECT) << 30;
> > + paddr_t max_pa;
> >
> > cpu_init_msrs(&cpu_info_primary);
> >
> > @@ -1541,7 +1544,16 @@ init_x86_64(paddr_t first_avail)
> > * Call pmap initialization to make new kernel address space.
> > * We must do this before loading pages into the VM system.
> > */
> > - first_avail = pmap_bootstrap(first_avail, trunc_page(avail_end));
> > + max_pa = avail_end;
> > + /* Make sure max_pa covers the EFI frame buffer */
> > + if (bios_efiinfo->fb_addr != 0 &&
> > + max_pa < bios_efiinfo->fb_addr + bios_efiinfo->fb_size)
> > + max_pa = bios_efiinfo->fb_addr + bios_efiinfo->fb_size;
> > + first_avail = pmap_bootstrap(first_avail, trunc_page(max_pa));
> > +
> > + /* Call cninit after entire physical memory is available */
> > + if (docninit > 0)
> > + cninit();
> >
> > /* Allocate these out of the 640KB base memory */
> > if (avail_start != PAGE_SIZE)
> > @@ -1914,7 +1926,6 @@ getbootinfo(char *bootinfo, int bootinfo
> > bios_ddb_t *bios_ddb;
> > bios_bootduid_t *bios_bootduid;
> > bios_bootsr_t *bios_bootsr;
> > - int docninit = 0;
> >
> > #undef BOOTINFO_DEBUG
> > #ifdef BOOTINFO_DEBUG
> > @@ -2026,8 +2037,6 @@ getbootinfo(char *bootinfo, int bootinfo
> > break;
> > }
> > }
> > - if (docninit > 0)
> > - cninit();
> > #ifdef BOOTINFO_DEBUG
> > printf("\n");
> > #endif
> >
>
>