QEMU的-hda选项含义及自研操作系统访问该模拟硬盘的技术咨询
QEMU -hda选项及自研OS访问模拟硬盘指南
1. -hda选项的含义
-hda是QEMU指定主IDE硬盘设备的启动参数,它会把你指定的镜像文件或物理块设备,模拟成IDE总线(默认)下的第一个主设备。举个实际命令示例:
qemu-system-x86_64 -hda my_disk.img
这条命令会将my_disk.img作为主IDE硬盘挂载到虚拟机中。
2. 自研OS识别设备挂载位置
- 扫描IDE总线:QEMU默认把
-hda模拟为IDE控制器的通道0(Primary)、主设备(Master),对应的I/O端口范围是0x1F0-0x1F7(数据/命令端口)和0x3F6(控制端口)。 - 检测设备存在:通过读取IDE控制器的状态寄存器(端口
0x1F7)判断是否有设备响应,或者执行IDENTIFY DEVICE命令读取设备识别信息,确认这是一个硬盘设备。 - 记录设备标识:在OS的设备树或驱动链表中标记该设备为IDE主硬盘,后续用这个标识关联存储操作。
3. 访问设备的接口协议
QEMU默认用IDE协议模拟-hda,如果需要用SATA协议,得先调整QEMU启动命令,再在OS中实现对应驱动:
3.1 默认IDE协议访问步骤
IDE采用端口I/O操作,核心流程如下:
- 设置扇区数(端口
0x1F2)、起始扇区的LBA地址(0x1F3-0x1F6,LBA28模式下用4个字节); - 向命令寄存器(
0x1F7)发送读/写命令,比如读命令是0x20; - 轮询状态寄存器(
0x1F7)等待操作完成,再从数据端口(0x1F0)读取或写入数据; - 进阶优化:可以处理IDE控制器触发的IRQ14中断,实现异步操作,避免轮询占用CPU。
3.2 SATA协议访问(切换到AHCI控制器)
如果要让-hda对应SATA设备,先修改QEMU启动命令,把IDE换成AHCI控制器:
qemu-system-x86_64 -device ahci,id=ahci0 -drive id=disk0,file=my_disk.img,if=none -device ide-hd,drive=disk0,bus=ahci0.0
然后在自研OS中实现AHCI驱动,步骤如下:
- AHCI是SATA的主机控制器接口,用内存映射I/O(MMIO)替代传统端口I/O;
- 通过PCI总线枚举找到AHCI控制器的MMIO基地址(AHCI设备的PCI类代码是
0x0106); - 初始化AHCI控制器:启用全局中断、设置端口状态;
- 对目标端口(比如端口0)发送FIS(Frame Information Structure)命令,比如
IDENTIFY DEVICE、READ DMA EXT等; - 采用DMA方式传输数据,效率比IDE的PIO方式高很多。
4. 实操简化示例(IDE硬盘读扇区)
下面是自研OS中读取IDE硬盘第一个扇区的伪代码实现:
// 读取IDE硬盘第一个扇区的简化代码 void read_ide_sector(uint32_t lba, uint8_t* buf) { cli(); // 禁用中断 // 设置读取扇区数为1 outb(0x1F2, 1); // 写入LBA地址(LBA28模式) outb(0x1F3, lba & 0xFF); outb(0x1F4, (lba >> 8) & 0xFF); outb(0x1F5, (lba >> 16) & 0xFF); outb(0x1F6, 0xE0 | ((lba >> 24) & 0x0F)); // 指定主设备+LBA模式 // 发送读扇区命令 outb(0x1F7, 0x20); // 等待设备就绪 while (!(inb(0x1F7) & 0x08)); // 读取512字节数据(insw一次读2字节,循环256次) insw(0x1F0, buf, 256); sti(); // 恢复中断 }
内容的提问来源于stack exchange,提问作者LiShuang
相关产品推荐
相关产品推荐

