diff options
Diffstat (limited to 'arch/x86/lguest/boot.c')
-rw-r--r-- | arch/x86/lguest/boot.c | 173 |
1 files changed, 153 insertions, 20 deletions
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index c1c1544b8485..ac4453d8520e 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
@@ -56,6 +56,9 @@ | |||
56 | #include <linux/virtio_console.h> | 56 | #include <linux/virtio_console.h> |
57 | #include <linux/pm.h> | 57 | #include <linux/pm.h> |
58 | #include <linux/export.h> | 58 | #include <linux/export.h> |
59 | #include <linux/pci.h> | ||
60 | #include <linux/virtio_pci.h> | ||
61 | #include <asm/acpi.h> | ||
59 | #include <asm/apic.h> | 62 | #include <asm/apic.h> |
60 | #include <asm/lguest.h> | 63 | #include <asm/lguest.h> |
61 | #include <asm/paravirt.h> | 64 | #include <asm/paravirt.h> |
@@ -71,6 +74,8 @@ | |||
71 | #include <asm/stackprotector.h> | 74 | #include <asm/stackprotector.h> |
72 | #include <asm/reboot.h> /* for struct machine_ops */ | 75 | #include <asm/reboot.h> /* for struct machine_ops */ |
73 | #include <asm/kvm_para.h> | 76 | #include <asm/kvm_para.h> |
77 | #include <asm/pci_x86.h> | ||
78 | #include <asm/pci-direct.h> | ||
74 | 79 | ||
75 | /*G:010 | 80 | /*G:010 |
76 | * Welcome to the Guest! | 81 | * Welcome to the Guest! |
@@ -831,6 +836,24 @@ static struct irq_chip lguest_irq_controller = { | |||
831 | .irq_unmask = enable_lguest_irq, | 836 | .irq_unmask = enable_lguest_irq, |
832 | }; | 837 | }; |
833 | 838 | ||
839 | static int lguest_enable_irq(struct pci_dev *dev) | ||
840 | { | ||
841 | u8 line = 0; | ||
842 | |||
843 | /* We literally use the PCI interrupt line as the irq number. */ | ||
844 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line); | ||
845 | irq_set_chip_and_handler_name(line, &lguest_irq_controller, | ||
846 | handle_level_irq, "level"); | ||
847 | dev->irq = line; | ||
848 | return 0; | ||
849 | } | ||
850 | |||
851 | /* We don't do hotplug PCI, so this shouldn't be called. */ | ||
852 | static void lguest_disable_irq(struct pci_dev *dev) | ||
853 | { | ||
854 | WARN_ON(1); | ||
855 | } | ||
856 | |||
834 | /* | 857 | /* |
835 | * This sets up the Interrupt Descriptor Table (IDT) entry for each hardware | 858 | * This sets up the Interrupt Descriptor Table (IDT) entry for each hardware |
836 | * interrupt (except 128, which is used for system calls), and then tells the | 859 | * interrupt (except 128, which is used for system calls), and then tells the |
@@ -1181,25 +1204,136 @@ static __init char *lguest_memory_setup(void) | |||
1181 | return "LGUEST"; | 1204 | return "LGUEST"; |
1182 | } | 1205 | } |
1183 | 1206 | ||
1207 | /* Offset within PCI config space of BAR access capability. */ | ||
1208 | static int console_cfg_offset = 0; | ||
1209 | static int console_access_cap; | ||
1210 | |||
1211 | /* Set up so that we access off in bar0 (on bus 0, device 1, function 0) */ | ||
1212 | static void set_cfg_window(u32 cfg_offset, u32 off) | ||
1213 | { | ||
1214 | write_pci_config_byte(0, 1, 0, | ||
1215 | cfg_offset + offsetof(struct virtio_pci_cap, bar), | ||
1216 | 0); | ||
1217 | write_pci_config(0, 1, 0, | ||
1218 | cfg_offset + offsetof(struct virtio_pci_cap, length), | ||
1219 | 4); | ||
1220 | write_pci_config(0, 1, 0, | ||
1221 | cfg_offset + offsetof(struct virtio_pci_cap, offset), | ||
1222 | off); | ||
1223 | } | ||
1224 | |||
1225 | static void write_bar_via_cfg(u32 cfg_offset, u32 off, u32 val) | ||
1226 | { | ||
1227 | /* | ||
1228 | * We could set this up once, then leave it; nothing else in the * | ||
1229 | * kernel should touch these registers. But if it went wrong, that | ||
1230 | * would be a horrible bug to find. | ||
1231 | */ | ||
1232 | set_cfg_window(cfg_offset, off); | ||
1233 | write_pci_config(0, 1, 0, | ||
1234 | cfg_offset + sizeof(struct virtio_pci_cap), val); | ||
1235 | } | ||
1236 | |||
1237 | static void probe_pci_console(void) | ||
1238 | { | ||
1239 | u8 cap, common_cap = 0, device_cap = 0; | ||
1240 | /* Offset within BAR0 */ | ||
1241 | u32 device_offset; | ||
1242 | u32 device_len; | ||
1243 | |||
1244 | /* Avoid recursive printk into here. */ | ||
1245 | console_cfg_offset = -1; | ||
1246 | |||
1247 | if (!early_pci_allowed()) { | ||
1248 | printk(KERN_ERR "lguest: early PCI access not allowed!\n"); | ||
1249 | return; | ||
1250 | } | ||
1251 | |||
1252 | /* We expect a console PCI device at BUS0, slot 1. */ | ||
1253 | if (read_pci_config(0, 1, 0, 0) != 0x10431AF4) { | ||
1254 | printk(KERN_ERR "lguest: PCI device is %#x!\n", | ||
1255 | read_pci_config(0, 1, 0, 0)); | ||
1256 | return; | ||
1257 | } | ||
1258 | |||
1259 | /* Find the capabilities we need (must be in bar0) */ | ||
1260 | cap = read_pci_config_byte(0, 1, 0, PCI_CAPABILITY_LIST); | ||
1261 | while (cap) { | ||
1262 | u8 vndr = read_pci_config_byte(0, 1, 0, cap); | ||
1263 | if (vndr == PCI_CAP_ID_VNDR) { | ||
1264 | u8 type, bar; | ||
1265 | u32 offset, length; | ||
1266 | |||
1267 | type = read_pci_config_byte(0, 1, 0, | ||
1268 | cap + offsetof(struct virtio_pci_cap, cfg_type)); | ||
1269 | bar = read_pci_config_byte(0, 1, 0, | ||
1270 | cap + offsetof(struct virtio_pci_cap, bar)); | ||
1271 | offset = read_pci_config(0, 1, 0, | ||
1272 | cap + offsetof(struct virtio_pci_cap, offset)); | ||
1273 | length = read_pci_config(0, 1, 0, | ||
1274 | cap + offsetof(struct virtio_pci_cap, length)); | ||
1275 | |||
1276 | switch (type) { | ||
1277 | case VIRTIO_PCI_CAP_DEVICE_CFG: | ||
1278 | if (bar == 0) { | ||
1279 | device_cap = cap; | ||
1280 | device_offset = offset; | ||
1281 | device_len = length; | ||
1282 | } | ||
1283 | break; | ||
1284 | case VIRTIO_PCI_CAP_PCI_CFG: | ||
1285 | console_access_cap = cap; | ||
1286 | break; | ||
1287 | } | ||
1288 | } | ||
1289 | cap = read_pci_config_byte(0, 1, 0, cap + PCI_CAP_LIST_NEXT); | ||
1290 | } | ||
1291 | if (!device_cap || !console_access_cap) { | ||
1292 | printk(KERN_ERR "lguest: No caps (%u/%u/%u) in console!\n", | ||
1293 | common_cap, device_cap, console_access_cap); | ||
1294 | return; | ||
1295 | } | ||
1296 | |||
1297 | /* | ||
1298 | * Note that we can't check features, until we've set the DRIVER | ||
1299 | * status bit. We don't want to do that until we have a real driver, | ||
1300 | * so we just check that the device-specific config has room for | ||
1301 | * emerg_wr. If it doesn't support VIRTIO_CONSOLE_F_EMERG_WRITE | ||
1302 | * it should ignore the access. | ||
1303 | */ | ||
1304 | if (device_len < (offsetof(struct virtio_console_config, emerg_wr) | ||
1305 | + sizeof(u32))) { | ||
1306 | printk(KERN_ERR "lguest: console missing emerg_wr field\n"); | ||
1307 | return; | ||
1308 | } | ||
1309 | |||
1310 | console_cfg_offset = device_offset; | ||
1311 | printk(KERN_INFO "lguest: Console via virtio-pci emerg_wr\n"); | ||
1312 | } | ||
1313 | |||
1184 | /* | 1314 | /* |
1185 | * We will eventually use the virtio console device to produce console output, | 1315 | * We will eventually use the virtio console device to produce console output, |
1186 | * but before that is set up we use LHCALL_NOTIFY on normal memory to produce | 1316 | * but before that is set up we use the virtio PCI console's backdoor mmio |
1187 | * console output. | 1317 | * access and the "emergency" write facility (which is legal even before the |
1318 | * device is configured). | ||
1188 | */ | 1319 | */ |
1189 | static __init int early_put_chars(u32 vtermno, const char *buf, int count) | 1320 | static __init int early_put_chars(u32 vtermno, const char *buf, int count) |
1190 | { | 1321 | { |
1191 | char scratch[17]; | 1322 | /* If we couldn't find PCI console, forget it. */ |
1192 | unsigned int len = count; | 1323 | if (console_cfg_offset < 0) |
1324 | return count; | ||
1193 | 1325 | ||
1194 | /* We use a nul-terminated string, so we make a copy. Icky, huh? */ | 1326 | if (unlikely(!console_cfg_offset)) { |
1195 | if (len > sizeof(scratch) - 1) | 1327 | probe_pci_console(); |
1196 | len = sizeof(scratch) - 1; | 1328 | if (console_cfg_offset < 0) |
1197 | scratch[len] = '\0'; | 1329 | return count; |
1198 | memcpy(scratch, buf, len); | 1330 | } |
1199 | hcall(LHCALL_NOTIFY, __pa(scratch), 0, 0, 0); | ||
1200 | 1331 | ||
1201 | /* This routine returns the number of bytes actually written. */ | 1332 | write_bar_via_cfg(console_access_cap, |
1202 | return len; | 1333 | console_cfg_offset |
1334 | + offsetof(struct virtio_console_config, emerg_wr), | ||
1335 | buf[0]); | ||
1336 | return 1; | ||
1203 | } | 1337 | } |
1204 | 1338 | ||
1205 | /* | 1339 | /* |
@@ -1400,14 +1534,6 @@ __init void lguest_init(void) | |||
1400 | atomic_notifier_chain_register(&panic_notifier_list, &paniced); | 1534 | atomic_notifier_chain_register(&panic_notifier_list, &paniced); |
1401 | 1535 | ||
1402 | /* | 1536 | /* |
1403 | * The IDE code spends about 3 seconds probing for disks: if we reserve | ||
1404 | * all the I/O ports up front it can't get them and so doesn't probe. | ||
1405 | * Other device drivers are similar (but less severe). This cuts the | ||
1406 | * kernel boot time on my machine from 4.1 seconds to 0.45 seconds. | ||
1407 | */ | ||
1408 | paravirt_disable_iospace(); | ||
1409 | |||
1410 | /* | ||
1411 | * This is messy CPU setup stuff which the native boot code does before | 1537 | * This is messy CPU setup stuff which the native boot code does before |
1412 | * start_kernel, so we have to do, too: | 1538 | * start_kernel, so we have to do, too: |
1413 | */ | 1539 | */ |
@@ -1436,6 +1562,13 @@ __init void lguest_init(void) | |||
1436 | /* Register our very early console. */ | 1562 | /* Register our very early console. */ |
1437 | virtio_cons_early_init(early_put_chars); | 1563 | virtio_cons_early_init(early_put_chars); |
1438 | 1564 | ||
1565 | /* Don't let ACPI try to control our PCI interrupts. */ | ||
1566 | disable_acpi(); | ||
1567 | |||
1568 | /* We control them ourselves, by overriding these two hooks. */ | ||
1569 | pcibios_enable_irq = lguest_enable_irq; | ||
1570 | pcibios_disable_irq = lguest_disable_irq; | ||
1571 | |||
1439 | /* | 1572 | /* |
1440 | * Last of all, we set the power management poweroff hook to point to | 1573 | * Last of all, we set the power management poweroff hook to point to |
1441 | * the Guest routine to power off, and the reboot hook to our restart | 1574 | * the Guest routine to power off, and the reboot hook to our restart |