blob: 4f00006bf01cc6445c6d018625165a7a6e745379 [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
29 int clear = 0;
30 int i;
31 for (i=0; i<6; i++) {
Kevin O'Connor5bd01de2010-09-13 21:19:27 -040032 u32 pam = pam0 + 1 + i;
33 int reg = pci_config_readb(bdf, pam);
34 if (CONFIG_OPTIONROMS_DEPLOYED && (reg & 0x11) != 0x11) {
Anthony Liguori034ce4b2009-12-18 12:16:01 +010035 // 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);
Isaku Yamahata08328e72010-07-20 16:50:45 +090038 pci_config_writeb(bdf, pam, 0x33);
Anthony Liguori034ce4b2009-12-18 12:16:01 +010039 memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024);
40 clear = 1;
Kevin O'Connore7739302009-07-26 19:16:09 -040041 } else {
Isaku Yamahata08328e72010-07-20 16:50:45 +090042 pci_config_writeb(bdf, pam, 0x33);
Kevin O'Connore7739302009-07-26 19:16:09 -040043 }
44 }
45 if (clear)
46 memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024);
47
Kevin O'Connor5b8f8092009-09-20 19:47:45 -040048 // Make ram from 0xf0000-0x100000 writable
Isaku Yamahata08328e72010-07-20 16:50:45 +090049 int reg = pci_config_readb(bdf, pam0);
50 pci_config_writeb(bdf, pam0, 0x30);
Kevin O'Connor5b8f8092009-09-20 19:47:45 -040051 if (reg & 0x10)
52 // Ram already present.
53 return;
54
55 // Copy bios.
Kevin O'Connor5bd01de2010-09-13 21:19:27 -040056 extern u8 code32flat_start[], code32flat_end[];
57 memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET
58 , code32flat_end - code32flat_start);
Kevin O'Connor5b8f8092009-09-20 19:47:45 -040059}
60
Kevin O'Connor6e4583c2011-06-19 10:09:26 -040061static void
Isaku Yamahata08328e72010-07-20 16:50:45 +090062make_bios_writable_intel(u16 bdf, u32 pam0)
63{
64 int reg = pci_config_readb(bdf, pam0);
65 if (!(reg & 0x10)) {
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.
Kevin O'Connor5bd01de2010-09-13 21:19:27 -040070 u32 pos = (u32)__make_bios_writable_intel + BIOS_SRC_OFFSET;
Isaku Yamahata08328e72010-07-20 16:50:45 +090071 void (*func)(u16 bdf, u32 pam0) = (void*)pos;
72 func(bdf, pam0);
73 return;
74 }
75 // Ram already present - just enable writes
76 __make_bios_writable_intel(bdf, pam0);
77}
78
Kevin O'Connor6e4583c2011-06-19 10:09:26 -040079static void
Isaku Yamahata08328e72010-07-20 16:50:45 +090080make_bios_readonly_intel(u16 bdf, u32 pam0)
81{
82 // Flush any pending writes before locking memory.
83 wbinvd();
84
85 // Write protect roms from 0xc0000-0xf0000
Kevin O'Connor2b0fb8c2013-08-07 23:03:47 -040086 u32 romlast = BUILD_BIOS_ADDR, rommax = BUILD_BIOS_ADDR;
Kevin O'Connorc98424c2013-07-21 16:38:18 -040087 if (CONFIG_WRITABLE_UPPERMEMORY)
88 romlast = rom_get_last();
Kevin O'Connor2b0fb8c2013-08-07 23:03:47 -040089 if (CONFIG_MALLOC_UPPERMEMORY)
90 rommax = rom_get_max();
Isaku Yamahata08328e72010-07-20 16:50:45 +090091 int i;
92 for (i=0; i<6; i++) {
93 u32 mem = BUILD_ROM_START + i * 32*1024;
94 u32 pam = pam0 + 1 + i;
Kevin O'Connorc98424c2013-07-21 16:38:18 -040095 if (romlast < mem + 16*1024 || rommax < mem + 32*1024) {
96 if (romlast >= mem && rommax >= mem + 16*1024)
Isaku Yamahata08328e72010-07-20 16:50:45 +090097 pci_config_writeb(bdf, pam, 0x31);
98 break;
99 }
100 pci_config_writeb(bdf, pam, 0x11);
101 }
102
103 // Write protect 0xf0000-0x100000
104 pci_config_writeb(bdf, pam0, 0x10);
105}
106
Kevin O'Connor96d4c432013-03-08 19:31:14 -0500107static int ShadowBDF = -1;
Kevin O'Connor6e4583c2011-06-19 10:09:26 -0400108
Kevin O'Connor5b8f8092009-09-20 19:47:45 -0400109// Make the 0xc0000-0x100000 area read/writable.
110void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500111make_bios_writable(void)
Kevin O'Connor5b8f8092009-09-20 19:47:45 -0400112{
Kevin O'Connor897fb112013-02-07 23:32:48 -0500113 if (!CONFIG_QEMU || runningOnXen())
Kevin O'Connor5b8f8092009-09-20 19:47:45 -0400114 return;
115
116 dprintf(3, "enabling shadow ram\n");
117
Kevin O'Connorfaf6a4e2011-06-21 21:22:01 -0400118 // At this point, statically allocated variables can't be written,
119 // so do this search manually.
Kevin O'Connor2b333e42011-07-02 14:49:41 -0400120 int bdf;
121 foreachbdf(bdf, 0) {
Kevin O'Connorfaf6a4e2011-06-21 21:22:01 -0400122 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);
Kevin O'Connor96d4c432013-03-08 19:31:14 -0500127 ShadowBDF = bdf;
Kevin O'Connorfaf6a4e2011-06-21 21:22:01 -0400128 return;
129 }
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100130 if (vendor == PCI_VENDOR_ID_INTEL
131 && device == PCI_DEVICE_ID_INTEL_Q35_MCH) {
132 make_bios_writable_intel(bdf, Q35_HOST_BRIDGE_PAM0);
Kevin O'Connor96d4c432013-03-08 19:31:14 -0500133 ShadowBDF = bdf;
Isaku Yamahata72a590e2012-11-28 10:17:33 +0100134 return;
135 }
Kevin O'Connor35284962009-07-24 21:49:26 -0400136 }
Kevin O'Connorfaf6a4e2011-06-21 21:22:01 -0400137 dprintf(1, "Unable to unlock ram - bridge not found\n");
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400138}
139
140// Make the BIOS code segment area (0xf0000) read-only.
141void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500142make_bios_readonly(void)
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400143{
Kevin O'Connor897fb112013-02-07 23:32:48 -0500144 if (!CONFIG_QEMU || runningOnXen())
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400145 return;
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400146 dprintf(3, "locking shadow ram\n");
Kevin O'Connor96d4c432013-03-08 19:31:14 -0500147
148 if (ShadowBDF < 0) {
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400149 dprintf(1, "Unable to lock ram - bridge not found\n");
Kevin O'Connor96d4c432013-03-08 19:31:14 -0500150 return;
151 }
152
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);
156 else
157 make_bios_readonly_intel(ShadowBDF, Q35_HOST_BRIDGE_PAM0);
Kevin O'Connorda4a6482008-06-08 13:48:06 -0400158}
Kevin O'Connor244caf82010-09-15 21:48:16 -0400159
160void
161qemu_prep_reset(void)
162{
Kevin O'Connor897fb112013-02-07 23:32:48 -0500163 if (!CONFIG_QEMU || runningOnXen())
Kevin O'Connor244caf82010-09-15 21:48:16 -0400164 return;
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);
171}