1 // Support for enabling/disabling BIOS ram shadowing.
3 // Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2006 Fabrice Bellard
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
8 #include "config.h" // CONFIG_*
9 #include "dev-q35.h" // PCI_VENDOR_ID_INTEL
10 #include "dev-piix.h" // I440FX_PAM0
11 #include "hw/pci.h" // pci_config_writeb
12 #include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
13 #include "hw/pci_regs.h" // PCI_VENDOR_ID
14 #include "malloc.h" // rom_get_last
15 #include "output.h" // dprintf
16 #include "paravirt.h" // runningOnXen
17 #include "string.h" // memset
18 #include "util.h" // make_bios_writable
19 #include "x86.h" // wbinvd
21 // On the emulators, the bios at 0xf0000 is also at 0xffff0000
22 #define BIOS_SRC_OFFSET 0xfff00000
24 // Enable shadowing and copy bios.
26 __make_bios_writable_intel(u16 bdf, u32 pam0)
28 // Make ram from 0xc0000-0xf0000 writable
32 u32 pam = pam0 + 1 + i;
33 int reg = pci_config_readb(bdf, pam);
34 if (CONFIG_OPTIONROMS_DEPLOYED && (reg & 0x11) != 0x11) {
35 // Need to copy optionroms to work around qemu implementation
36 void *mem = (void*)(BUILD_ROM_START + i * 32*1024);
37 memcpy((void*)BUILD_BIOS_TMP_ADDR, mem, 32*1024);
38 pci_config_writeb(bdf, pam, 0x33);
39 memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024);
42 pci_config_writeb(bdf, pam, 0x33);
46 memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024);
48 // Make ram from 0xf0000-0x100000 writable
49 int reg = pci_config_readb(bdf, pam0);
50 pci_config_writeb(bdf, pam0, 0x30);
52 // Ram already present.
56 extern u8 code32flat_start[], code32flat_end[];
57 memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET
58 , code32flat_end - code32flat_start);
62 make_bios_writable_intel(u16 bdf, u32 pam0)
64 int reg = pci_config_readb(bdf, pam0);
66 // QEMU doesn't fully implement the piix shadow capabilities -
67 // if ram isn't backing the bios segment when shadowing is
68 // disabled, the code itself wont be in memory. So, run the
69 // code from the high-memory flash location.
70 u32 pos = (u32)__make_bios_writable_intel + BIOS_SRC_OFFSET;
71 void (*func)(u16 bdf, u32 pam0) = (void*)pos;
75 // Ram already present - just enable writes
76 __make_bios_writable_intel(bdf, pam0);
80 make_bios_readonly_intel(u16 bdf, u32 pam0)
82 // Flush any pending writes before locking memory.
85 // Write protect roms from 0xc0000-0xf0000
86 u32 romlast = BUILD_BIOS_ADDR, rommax = BUILD_BIOS_ADDR;
87 if (CONFIG_WRITABLE_UPPERMEMORY)
88 romlast = rom_get_last();
89 if (CONFIG_MALLOC_UPPERMEMORY)
90 rommax = rom_get_max();
93 u32 mem = BUILD_ROM_START + i * 32*1024;
94 u32 pam = pam0 + 1 + i;
95 if (romlast < mem + 16*1024 || rommax < mem + 32*1024) {
96 if (romlast >= mem && rommax >= mem + 16*1024)
97 pci_config_writeb(bdf, pam, 0x31);
100 pci_config_writeb(bdf, pam, 0x11);
103 // Write protect 0xf0000-0x100000
104 pci_config_writeb(bdf, pam0, 0x10);
107 static int ShadowBDF = -1;
109 // Make the 0xc0000-0x100000 area read/writable.
111 make_bios_writable(void)
113 if (!CONFIG_QEMU || runningOnXen())
116 dprintf(3, "enabling shadow ram\n");
118 // At this point, statically allocated variables can't be written,
119 // so do this search manually.
122 u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID);
123 u16 vendor = vendev & 0xffff, device = vendev >> 16;
124 if (vendor == PCI_VENDOR_ID_INTEL
125 && device == PCI_DEVICE_ID_INTEL_82441) {
126 make_bios_writable_intel(bdf, I440FX_PAM0);
130 if (vendor == PCI_VENDOR_ID_INTEL
131 && device == PCI_DEVICE_ID_INTEL_Q35_MCH) {
132 make_bios_writable_intel(bdf, Q35_HOST_BRIDGE_PAM0);
137 dprintf(1, "Unable to unlock ram - bridge not found\n");
140 // Make the BIOS code segment area (0xf0000) read-only.
142 make_bios_readonly(void)
144 if (!CONFIG_QEMU || runningOnXen())
146 dprintf(3, "locking shadow ram\n");
149 dprintf(1, "Unable to lock ram - bridge not found\n");
153 u16 device = pci_config_readw(ShadowBDF, PCI_DEVICE_ID);
154 if (device == PCI_DEVICE_ID_INTEL_82441)
155 make_bios_readonly_intel(ShadowBDF, I440FX_PAM0);
157 make_bios_readonly_intel(ShadowBDF, Q35_HOST_BRIDGE_PAM0);
161 qemu_prep_reset(void)
163 if (!CONFIG_QEMU || runningOnXen())
165 // QEMU doesn't map 0xc0000-0xfffff back to the original rom on a
166 // reset, so do that manually before invoking a hard reset.
167 make_bios_writable();
168 extern u8 code32flat_start[], code32flat_end[];
169 memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET
170 , code32flat_end - code32flat_start);