1 Reset vector

Guest vCPU运行的第一行代码是什么?

对于正常的x86 CPU,在CPU reset之后,ip指针会被设置到reset_vector,参考

Wiki x86 Reset Vectoricon-default.png?t=M85Bhttps://en.wikipedia.org/wiki/Reset_vector

The reset vector for the 80386 and later x86 processors is physical address FFFFFFF0h (16 bytes below 4 GB). The value of the selector portion of the CS register at reset is F000h, the value of the base portion of the CS register is FFFF0000h, and the value of the IP register at reset is FFF0h to form the segmented address FFFF0000h:FFF0h, which maps to the physical address FFFFFFF0h in real mode.

参考QEMU的代码:

x86_cpu_reset()
---
	cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
                           DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
                           DESC_R_MASK | DESC_A_MASK);
	...
	env->eip = 0xfff0;
---

 那么,对于QEMU模拟出的vCPU来说,其16bytes below 4GB位置存放的是什么呢?

参考QEMU代码:

pc_init1()
  -> pc_memory_init()
	-> pc_system_firmware_init()
	  -> old_pc_system_rom_init()
		-> rom_add_file_fixed() //hwaddr = (uint32_t)(-bios_size)
		   ---
			rom->addr	 = addr;
			rom->romsize  = lseek(fd, 0, SEEK_END);
			rom->datasize = rom->romsize;
			rom->data	 = g_malloc0(rom->datasize);
			lseek(fd, 0, SEEK_SET);
			rc = read(fd, rom->data, rom->datasize);
			close(fd);
			rom_insert(rom);
		   ---

main()
  -> qemu_devices_reset()
	-> rom_reset()
	   ---
		QTAILQ_FOREACH(rom, &roms, next) {
			if (rom->mr) {
				void *host = memory_region_get_ram_ptr(rom->mr);
				memcpy(host, rom->data, rom->datasize);
			} else {
				cpu_physical_memory_write_rom(&address_space_memory,
											  rom->addr, rom->data, rom->datasize);
			}
		}
	  ---

参考rom_add_file_fixed()的调用,传入的hwaddr为(uint32_t)(-bios_size),它所代表的的含义就是4G - bios_size,参考下图:

              

上图引用自System address map initialization in x86/x64 architecture part 1: PCI-based systemsThis article serves as a clarification about the PCI expansion ROM address mapping, which was not sufficiently covered in my "Malicious PCI Expansion ROM"https://resources.infosecinstitute.com/topic/system-address-map-initialization-in-x86x64-architecture-part-1-pci-based-systems/

bios被拷贝的位置,就是上图中所示的Flash Memory的位置,即4G空间的尾巴上。


那reset vector的位置上呢?

Note: bios的大小必须是64K对齐的,这一点可以参考old_pc_system_rom_init()中对bios_size的检查,以及pc-bios目录下各个bios文件的大小

参考seabios的代码:seabios/romlayout.S at master · qemu/seabios · GitHubMirror of git.qemu.org/seabios.git. Contribute to qemu/seabios development by creating an account on GitHub.https://github.com/qemu/seabios/blob/master/src/romlayout.S

      // Specify a location in the fixed part of bios area.
        .macro ORG addr
        .section .fixedaddr.\addr
        .endm
  
    ORG 0xfff0 // Power-up Entry Point
        .global reset_vector
reset_vector:
        ljmpw $SEG_BIOS, $entry_post

        // 0xfff5 - BiosDate in misc.c

        // 0xfffe - BiosModelId in misc.c

        // 0xffff - BiosChecksum in misc.c

        .end

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐