blob: f766bb5946d21c6dd97c405961edd98c0f8da7f9 [file] [log] [blame]
Kevin O'Connorda4a6482008-06-08 13:48:06 -04001// Support for enabling/disabling BIOS ram shadowing.
2//
Kevin O'Connor5bd01de2010-09-13 21:19:27 -04003// Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connorda4a6482008-06-08 13:48:06 -04004// Copyright (C) 2006 Fabrice Bellard
5//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05006// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connorda4a6482008-06-08 13:48:06 -04007
Kevin O'Connor9521e262008-07-04 13:04:29 -04008#include "config.h" // CONFIG_*
Kevin O'Connor2d2fa312013-09-14 21:55:26 -04009#include "dev-q35.h" // PCI_VENDOR_ID_INTEL
Paolo Bonzini40d03122014-05-15 13:22:26 +020010#include "dev-piix.h" // I440FX_PAM0
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040011#include "hw/pci.h" // pci_config_writeb
Kevin O'Connor5d369d82013-09-02 20:48:46 -040012#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
13#include "hw/pci_regs.h" // PCI_VENDOR_ID
Kevin O'Connor9dea5902013-09-14 20:23:54 -040014#include "malloc.h" // rom_get_last
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040015#include "output.h" // dprintf
16#include "paravirt.h" // runningOnXen
Kevin O'Connorfa9c66a2013-09-14 19:10:40 -040017#include "string.h" // memset
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040018#include "util.h" // make_bios_writable
Kevin O'Connorb9c6a962013-09-14 13:01:30 -040019#include "x86.h" // wbinvd
Kevin O'Connorda4a6482008-06-08 13:48:06 -040020
Kevin O'Connor35284962009-07-24 21:49:26 -040021// On the emulators, the bios at 0xf0000 is also at 0xffff0000
Kevin O'Connor5bd01de2010-09-13 21:19:27 -040022#define BIOS_SRC_OFFSET 0xfff00000
Kevin O'Connor35284962009-07-24 21:49:26 -040023
Kevin O'Connorda4a6482008-06-08 13:48:06 -040024// Enable shadowing and copy bios.
25static void
Isaku Yamahata08328e72010-07-20 16:50:45 +090026__make_bios_writable_intel(u16 bdf, u32 pam0)
Kevin O'Connorda4a6482008-06-08 13:48:06 -040027{
Kevin O'Connore7739302009-07-26 19:16:09 -040028 // Make ram from 0xc0000-0xf0000 writable
Kevin O'Connore7739302009-07-26 19:16:09 -040029 int i;
30 for (i=0; i<6; i++) {
Kevin O'Connor5bd01de2010-09-13 21:19:27 -040031 u32 pam = pam0 + 1 + i;
Kevin O'Connor9d691ac2016-04-01 14:23:36 -040032 pci_config_writeb(bdf, pam, 0x33);
Kevin O'Connore7739302009-07-26 19:16:09 -040033 }
Kevin O'Connore7739302009-07-26 19:16:09 -040034
Kevin O'Connor5b8f8092009-09-20 19:47:45 -040035 // Make ram from 0xf0000-0x100000 writable
Isaku Yamahata08328e72010-07-20 16:50:45 +090036 int reg = pci_config_readb(bdf, pam0);
37 pci_config_writeb(bdf, pam0, 0x30);
Kevin O'Connor5b8f8092009-09-20 19:47:45 -040038 if (reg & 0x10)
39 // Ram already present.
40 return;
41
42 // Copy bios.
Kevin O'Connor5d912262015-10-08 11:18:17 -040043 memcpy(VSYMBOL(code32flat_start), VSYMBOL(code32flat_start) + BIOS_SRC_OFFSET
44 , SYMBOL(code32flat_end) - SYMBOL(code32flat_start));
Kevin O'Connor5b8f8092009-09-20 19:47:45 -040045}
46
Kevin O'Connor6e4583c2011-06-19 10:09:26 -040047static void
Isaku Yamahata08328e72010-07-20 16:50:45 +090048make_bios_writable_intel(u16 bdf, u32 pam0)
49{
50 int reg = pci_config_readb(bdf, pam0);
51 if (!(reg & 0x10)) {
52 // QEMU doesn't fully implement the piix shadow capabilities -
53 // if ram isn't backing the bios segment when shadowing is
Stefan Weil6bcacf72015-10-02 08:46:40 +020054 // disabled, the code itself won't be in memory. So, run the
Isaku Yamahata08328e72010-07-20 16:50:45 +090055 // code from the high-memory flash location.
Kevin O'Connor5bd01de2010-09-13 21:19:27 -040056 u32 pos = (u32)__make_bios_writable_intel + BIOS_SRC_OFFSET;
Isaku Yamahata08328e72010-07-20 16:50:45 +090057 void (*func)(u16 bdf, u32 pam0) = (void*)pos;
58 func(bdf, pam0);
59 return;
60 }
61 // Ram already present - just enable writes
62 __make_bios_writable_intel(bdf, pam0);
63}
64
Kevin O'Connor6e4583c2011-06-19 10:09:26 -040065static void
Isaku Yamahata08328e72010-07-20 16:50:45 +090066make_bios_readonly_intel(u16 bdf, u32 pam0)
67{
68 // Flush any pending writes before locking memory.
69 wbinvd();
70
71 // Write protect roms from 0xc0000-0xf0000
Kevin O'Connor2b0fb8c2013-08-07 23:03:47 -040072 u32 romlast = BUILD_BIOS_ADDR, rommax = BUILD_BIOS_ADDR;
Kevin O'Connorc98424c2013-07-21 16:38:18 -040073 if (CONFIG_WRITABLE_UPPERMEMORY)
74 romlast = rom_get_last();
Kevin O'Connor2b0fb8c2013-08-07 23:03:47 -040075 if (CONFIG_MALLOC_UPPERMEMORY)
76 rommax = rom_get_max();
Isaku Yamahata08328e72010-07-20 16:50:45 +090077 int i;
78 for (i=0; i<6; i++) {
79 u32 mem = BUILD_ROM_START + i * 32*1024;
80 u32 pam = pam0 + 1 + i;
Kevin O'Connorc98424c2013-07-21 16:38:18 -040081 if (romlast < mem + 16*1024 || rommax < mem + 32*1024) {
82 if (romlast >= mem && rommax >= mem + 16*1024)
Isaku Yamahata08328e72010-07-20 16:50:45 +090083 pci_config_writeb(bdf, pam, 0x31);
84 break;
85 }
86 pci_config_writeb(bdf, pam, 0x11);
87 }
88
89 // Write protect 0xf0000-0x100000
90 pci_config_writeb(bdf, pam0, 0x10);
91}
92
Kevin O'Connor96d4c432013-03-08 19:31:14 -050093static int ShadowBDF = -1;
Kevin O'Connor6e4583c2011-06-19 10:09:26 -040094
Kevin O'Connor5b8f8092009-09-20 19:47:45 -040095// Make the 0xc0000-0x100000 area read/writable.
96void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -050097make_bios_writable(void)
Kevin O'Connor5b8f8092009-09-20 19:47:45 -040098{
Kevin O'Connor897fb112013-02-07 23:32:48 -050099 if (!CONFIG_QEMU || runningOnXen())
Kevin O'Connor5b8f8092009-09-20 19:47:45 -0400100 return;
101
102 dprintf(3, "enabling shadow ram\n");
103
Kevin O'Connorfaf6a4e2011-06-21 21:22:01 -0400104 // At this point, statically allocated variables can't be written,
105 // so do this search manually.
Kevin O'Connor2b333e42011-07-02 14:49:41 -0400106 int bdf;
107 foreachbdf(bdf, 0) {
Kevin O'Connorfaf6a4e2011-06-21 21:22:01 -0400108 u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID);
109 u16 vendor = vendev & 0xffff, device = vendev >> 16;
110 if (vendor == PCI_VENDOR_ID_INTEL
111 && device == PCI_DEVICE_ID_INTEL_82441) {
112 make_bios_writable_intel(bdf, I440FX_PAM0);
Kevin O'Connora48f6022016-01-12 14:22:33 -0500113 code_mutable_preinit();
Kevin O'Connor96d4c432013-03-08 19:31:14 -0500114 ShadowBDF = bdf;
Kevin O'Connorfaf6a4e2011-06-21 21:22:01 -0400115 return;
116 }
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100117 if (vendor == PCI_VENDOR_ID_INTEL
118 && device == PCI_DEVICE_ID_INTEL_Q35_MCH) {
119 make_bios_writable_intel(bdf, Q35_HOST_BRIDGE_PAM0);
Kevin O'Connora48f6022016-01-12 14:22:33 -0500120 code_mutable_preinit();
Kevin O'Connor96d4c432013-03-08 19:31:14 -0500121 ShadowBDF = bdf;
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100122 return;
123 }
Kevin O'Connor35284962009-07-24 21:49:26 -0400124 }
Kevin O'Connorfaf6a4e2011-06-21 21:22:01 -0400125 dprintf(1, "Unable to unlock ram - bridge not found\n");
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400126}
127
128// Make the BIOS code segment area (0xf0000) read-only.
129void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500130make_bios_readonly(void)
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400131{
Kevin O'Connor897fb112013-02-07 23:32:48 -0500132 if (!CONFIG_QEMU || runningOnXen())
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400133 return;
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400134 dprintf(3, "locking shadow ram\n");
Kevin O'Connor96d4c432013-03-08 19:31:14 -0500135
136 if (ShadowBDF < 0) {
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400137 dprintf(1, "Unable to lock ram - bridge not found\n");
Kevin O'Connor96d4c432013-03-08 19:31:14 -0500138 return;
139 }
140
141 u16 device = pci_config_readw(ShadowBDF, PCI_DEVICE_ID);
142 if (device == PCI_DEVICE_ID_INTEL_82441)
143 make_bios_readonly_intel(ShadowBDF, I440FX_PAM0);
144 else
145 make_bios_readonly_intel(ShadowBDF, Q35_HOST_BRIDGE_PAM0);
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400146}
Kevin O'Connor244caf82010-09-15 21:48:16 -0400147
148void
149qemu_prep_reset(void)
150{
Kevin O'Connor897fb112013-02-07 23:32:48 -0500151 if (!CONFIG_QEMU || runningOnXen())
Kevin O'Connor244caf82010-09-15 21:48:16 -0400152 return;
153 // QEMU doesn't map 0xc0000-0xfffff back to the original rom on a
154 // reset, so do that manually before invoking a hard reset.
Kevin O'Connorb837e682015-11-09 15:00:19 -0500155 void *cstart = VSYMBOL(code32flat_start), *cend = VSYMBOL(code32flat_end);
156 void *hrp = &HaveRunPost;
157 if (readl(hrp + BIOS_SRC_OFFSET)) {
158 // Some old versions of KVM don't store a pristine copy of the
159 // BIOS in high memory. Try to shutdown the machine instead.
160 dprintf(1, "Unable to hard-reboot machine - attempting shutdown.\n");
161 apm_shutdown();
162 }
163 // Copy the BIOS making sure to only reset HaveRunPost at end
Kevin O'Connor244caf82010-09-15 21:48:16 -0400164 make_bios_writable();
Kevin O'Connorb837e682015-11-09 15:00:19 -0500165 memcpy(cstart, cstart + BIOS_SRC_OFFSET, hrp - cstart);
166 memcpy(hrp + 4, hrp + 4 + BIOS_SRC_OFFSET, cend - (hrp + 4));
167 barrier();
168 HaveRunPost = 0;
Kevin O'Connor244caf82010-09-15 21:48:16 -0400169}