Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lguest: use the PCI console device's emerg_wr for early boot messages.

This involves manually checking the console device (which is always in
slot 1 of bus 0) and using the window in VIRTIO_PCI_CAP_PCI_CFG to
program it (as we can't map the BAR yet).

We could in fact do this much earlier, but we wait for the first
write from the virtio_cons_early_init() facility.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

+134 -12
+134 -12
arch/x86/lguest/boot.c
··· 57 57 #include <linux/pm.h> 58 58 #include <linux/export.h> 59 59 #include <linux/pci.h> 60 + #include <linux/virtio_pci.h> 60 61 #include <asm/acpi.h> 61 62 #include <asm/apic.h> 62 63 #include <asm/lguest.h> ··· 75 74 #include <asm/reboot.h> /* for struct machine_ops */ 76 75 #include <asm/kvm_para.h> 77 76 #include <asm/pci_x86.h> 77 + #include <asm/pci-direct.h> 78 78 79 79 /*G:010 80 80 * Welcome to the Guest! ··· 1204 1202 return "LGUEST"; 1205 1203 } 1206 1204 1205 + /* Offset within PCI config space of BAR access capability. */ 1206 + static int console_cfg_offset = 0; 1207 + static int console_access_cap; 1208 + 1209 + /* Set up so that we access off in bar0 (on bus 0, device 1, function 0) */ 1210 + static void set_cfg_window(u32 cfg_offset, u32 off) 1211 + { 1212 + write_pci_config_byte(0, 1, 0, 1213 + cfg_offset + offsetof(struct virtio_pci_cap, bar), 1214 + 0); 1215 + write_pci_config(0, 1, 0, 1216 + cfg_offset + offsetof(struct virtio_pci_cap, length), 1217 + 4); 1218 + write_pci_config(0, 1, 0, 1219 + cfg_offset + offsetof(struct virtio_pci_cap, offset), 1220 + off); 1221 + } 1222 + 1223 + static u32 read_bar_via_cfg(u32 cfg_offset, u32 off) 1224 + { 1225 + set_cfg_window(cfg_offset, off); 1226 + return read_pci_config(0, 1, 0, 1227 + cfg_offset + sizeof(struct virtio_pci_cap)); 1228 + } 1229 + 1230 + static void write_bar_via_cfg(u32 cfg_offset, u32 off, u32 val) 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 + /* Offsets within BAR0 */ 1241 + u32 common_offset, device_offset; 1242 + 1243 + /* Avoid recursive printk into here. */ 1244 + console_cfg_offset = -1; 1245 + 1246 + if (!early_pci_allowed()) { 1247 + printk(KERN_ERR "lguest: early PCI access not allowed!\n"); 1248 + return; 1249 + } 1250 + 1251 + /* We expect a console PCI device at BUS0, slot 1. */ 1252 + if (read_pci_config(0, 1, 0, 0) != 0x10431AF4) { 1253 + printk(KERN_ERR "lguest: PCI device is %#x!\n", 1254 + read_pci_config(0, 1, 0, 0)); 1255 + return; 1256 + } 1257 + 1258 + /* Find the capabilities we need (must be in bar0) */ 1259 + cap = read_pci_config_byte(0, 1, 0, PCI_CAPABILITY_LIST); 1260 + while (cap) { 1261 + u8 vndr = read_pci_config_byte(0, 1, 0, cap); 1262 + if (vndr == PCI_CAP_ID_VNDR) { 1263 + u8 type, bar; 1264 + u32 offset; 1265 + 1266 + type = read_pci_config_byte(0, 1, 0, 1267 + cap + offsetof(struct virtio_pci_cap, cfg_type)); 1268 + bar = read_pci_config_byte(0, 1, 0, 1269 + cap + offsetof(struct virtio_pci_cap, bar)); 1270 + offset = read_pci_config(0, 1, 0, 1271 + cap + offsetof(struct virtio_pci_cap, offset)); 1272 + 1273 + switch (type) { 1274 + case VIRTIO_PCI_CAP_COMMON_CFG: 1275 + if (bar == 0) { 1276 + common_cap = cap; 1277 + common_offset = offset; 1278 + } 1279 + break; 1280 + case VIRTIO_PCI_CAP_DEVICE_CFG: 1281 + if (bar == 0) { 1282 + device_cap = cap; 1283 + device_offset = offset; 1284 + } 1285 + break; 1286 + case VIRTIO_PCI_CAP_PCI_CFG: 1287 + console_access_cap = cap; 1288 + break; 1289 + } 1290 + } 1291 + cap = read_pci_config_byte(0, 1, 0, cap + PCI_CAP_LIST_NEXT); 1292 + } 1293 + if (!common_cap || !device_cap || !console_access_cap) { 1294 + printk(KERN_ERR "lguest: No caps (%u/%u/%u) in console!\n", 1295 + common_cap, device_cap, console_access_cap); 1296 + return; 1297 + } 1298 + 1299 + 1300 + #define write_common_config(reg, val) \ 1301 + write_bar_via_cfg(console_access_cap, \ 1302 + common_offset+offsetof(struct virtio_pci_common_cfg,reg),\ 1303 + val) 1304 + 1305 + #define read_common_config(reg) \ 1306 + read_bar_via_cfg(console_access_cap, \ 1307 + common_offset+offsetof(struct virtio_pci_common_cfg,reg)) 1308 + 1309 + /* Check features: they must offer EMERG_WRITE */ 1310 + write_common_config(device_feature_select, 0); 1311 + 1312 + if (!(read_common_config(device_feature) 1313 + & (1 << VIRTIO_CONSOLE_F_EMERG_WRITE))) { 1314 + printk(KERN_ERR "lguest: console missing EMERG_WRITE\n"); 1315 + return; 1316 + } 1317 + 1318 + console_cfg_offset = device_offset; 1319 + } 1320 + 1207 1321 /* 1208 1322 * We will eventually use the virtio console device to produce console output, 1209 - * but before that is set up we use LHCALL_NOTIFY on normal memory to produce 1210 - * console output. 1323 + * but before that is set up we use the virtio PCI console's backdoor mmio 1324 + * access and the "emergency" write facility (which is legal even before the 1325 + * device is configured). 1211 1326 */ 1212 1327 static __init int early_put_chars(u32 vtermno, const char *buf, int count) 1213 1328 { 1214 - char scratch[17]; 1215 - unsigned int len = count; 1329 + /* If we couldn't find PCI console, forget it. */ 1330 + if (console_cfg_offset < 0) 1331 + return count; 1216 1332 1217 - /* We use a nul-terminated string, so we make a copy. Icky, huh? */ 1218 - if (len > sizeof(scratch) - 1) 1219 - len = sizeof(scratch) - 1; 1220 - scratch[len] = '\0'; 1221 - memcpy(scratch, buf, len); 1222 - hcall(LHCALL_NOTIFY, __pa(scratch), 0, 0, 0); 1333 + if (unlikely(!console_cfg_offset)) { 1334 + probe_pci_console(); 1335 + if (console_cfg_offset < 0) 1336 + return count; 1337 + } 1223 1338 1224 - /* This routine returns the number of bytes actually written. */ 1225 - return len; 1339 + write_bar_via_cfg(console_access_cap, 1340 + console_cfg_offset 1341 + + offsetof(struct virtio_console_config, emerg_wr), 1342 + buf[0]); 1343 + return 1; 1226 1344 } 1227 1345 1228 1346 /*