Add wbinvd around bios call.
Via C3 has problems with cache coherency when transitioning between the modes, so flush it around bios calls.
This commit is contained in:
parent
080a20861c
commit
25492a0f04
2 changed files with 35 additions and 0 deletions
|
@ -44,6 +44,13 @@ FUNCTION(grub_bios_interrupt)
|
||||||
movl 24(%edx), %esi
|
movl 24(%edx), %esi
|
||||||
movl 28(%edx), %edx
|
movl 28(%edx), %edx
|
||||||
|
|
||||||
|
/*
|
||||||
|
Via C3 CPUs have cache coherence problems, so we need to call
|
||||||
|
wbinvd at these 2 points. As wbinvd slows down boot, don't do
|
||||||
|
it on non-VIA. 9090 is nop nop. */
|
||||||
|
VARIABLE(grub_bios_via_workaround1)
|
||||||
|
.byte 0x90, 0x90
|
||||||
|
|
||||||
PROT_TO_REAL
|
PROT_TO_REAL
|
||||||
.code16
|
.code16
|
||||||
pushf
|
pushf
|
||||||
|
@ -92,6 +99,10 @@ intno:
|
||||||
movw %ax, LOCAL(bios_register_es)
|
movw %ax, LOCAL(bios_register_es)
|
||||||
|
|
||||||
popf
|
popf
|
||||||
|
|
||||||
|
VARIABLE(grub_bios_via_workaround2)
|
||||||
|
.byte 0x90, 0x90
|
||||||
|
|
||||||
REAL_TO_PROT
|
REAL_TO_PROT
|
||||||
.code32
|
.code32
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <grub/env.h>
|
#include <grub/env.h>
|
||||||
#include <grub/cache.h>
|
#include <grub/cache.h>
|
||||||
#include <grub/time.h>
|
#include <grub/time.h>
|
||||||
|
#include <grub/cpu/cpuid.h>
|
||||||
#include <grub/cpu/tsc.h>
|
#include <grub/cpu/tsc.h>
|
||||||
#include <grub/machine/time.h>
|
#include <grub/machine/time.h>
|
||||||
|
|
||||||
|
@ -184,6 +185,26 @@ mmap_iterate_hook (grub_uint64_t addr, grub_uint64_t size,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern grub_uint16_t grub_bios_via_workaround1, grub_bios_via_workaround2;
|
||||||
|
|
||||||
|
/* Via needs additional wbinvd. */
|
||||||
|
static void
|
||||||
|
grub_via_workaround_init (void)
|
||||||
|
{
|
||||||
|
grub_uint32_t manufacturer[3], max_cpuid;
|
||||||
|
if (! grub_cpu_is_cpuid_supported ())
|
||||||
|
return;
|
||||||
|
|
||||||
|
grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]);
|
||||||
|
|
||||||
|
if (grub_memcmp (manufacturer, "CentaurHauls", 12) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
grub_bios_via_workaround1 = 0x090f;
|
||||||
|
grub_bios_via_workaround2 = 0x090f;
|
||||||
|
asm volatile ("wbinvd");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_machine_init (void)
|
grub_machine_init (void)
|
||||||
{
|
{
|
||||||
|
@ -193,6 +214,9 @@ grub_machine_init (void)
|
||||||
#endif
|
#endif
|
||||||
grub_addr_t modend;
|
grub_addr_t modend;
|
||||||
|
|
||||||
|
/* This has to happen before any BIOS calls. */
|
||||||
|
grub_via_workaround_init ();
|
||||||
|
|
||||||
grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start);
|
grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start);
|
||||||
|
|
||||||
/* Initialize the console as early as possible. */
|
/* Initialize the console as early as possible. */
|
||||||
|
|
Loading…
Reference in a new issue