{"id":10577,"date":"2025-05-09T03:00:00","date_gmt":"2025-05-09T07:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=10577"},"modified":"2025-05-09T09:09:47","modified_gmt":"2025-05-09T13:09:47","slug":"emulating-systems-with-qemu","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=10577","title":{"rendered":"Emulating systems with QEMU"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"10577\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div>\n<p class=\"wp-block-paragraph\">I don\u2019t do all of my open source work on Linux; sometimes, I need to run another system to do a specific task. It can be expensive to buy a system that\u2019s dedicated to <em>just one<\/em> other system, especially if I don\u2019t need to run that system all of the time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One example that comes up a <em>lot<\/em> for me is my open source work with the <a href=\"https:\/\/www.freedos.org\/\">FreeDOS Project<\/a>. FreeDOS is an open source implementation of the classic DOS operating system, and it can run on any system that has an Intel CPU and a PC-compatible BIOS. I have a small \u2019386 laptop that I use when I want to run FreeDOS on real hardware, but for my day-to-day work, I prefer to use a <em>virtual machine<\/em> instead.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There are many virtual machines you can choose from. I like QEMU because it is flexible and supports different system architectures. It is also installed by default on most Linux systems, or at least available as a package that can be installed with a command like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo dnf install qemu<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"booting-with-the-defaults\">Booting with the defaults<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Unlike other virtual machine systems like VirtualBox, you need to configure QEMU from the command line. This sounds hard, but QEMU defines some default values that make sense for most use cases, such as providing a keyboard, mouse, video, memory, and machine type. Let\u2019s say I wanted to boot the FreeDOS 1.4 LiveCD. If you don\u2019t want to get into the different ways to run QEMU, you can boot the LiveCD in QEMU using this command line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ qemu-system-x86_64 -cdrom FD14LIVE.iso <\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This sets up an x86 system with default values, and a CD-ROM drive attached to it, using the <code>FD16LIVE.iso<\/code> image file. The system will boot into the LiveCD where you can run commands, like the <strong>mem<\/strong> command to see the available memory available to FreeDOS:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"730\" height=\"461\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2025\/05\/qemu-mem.png\" alt=\"booting FreeDOS in QEMU with default memory size\" class=\"wp-image-10580\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">However, the system will not run very well. Every command you run will have a delay. That\u2019s because the virtual machine is emulating the CPU instructions <em>through software<\/em>. You can get better performance using the Kernel Virtual Machine (KVM) that\u2019s built into the Linux kernel. To do that, add the <code>-enable-kvm<\/code> option to the command line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ qemu-system-x86_64 -enable-kvm -cdrom FD14LIVE.iso <\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Command line options can go in any order, but I usually specify the KVM first so I don\u2019t forget to use it. In general, I usually define the <em>machine<\/em> specifications up front, and any <em>storage<\/em> or other modifications last on the command line, but this is just my preference in typing the command line.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to add more memory to the virtual machine, use the <code>-m<\/code> option and specify the amount of memory. Plain numbers are assumed to be <em>megabytes<\/em> but you can append <code>G<\/code> to indicate <em>gigabytes<\/em>. DOS is an old operating system from an era when computers counted memory in single-digit or double-digit <em>megabytes<\/em>, so I usually limit DOS to about 16 MB memory, which is more memory than I had in the computer that I took with me to university:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ qemu-system-x86_64 -enable-kvm -m 16 -cdrom FD14LIVE.iso<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"730\" height=\"461\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2025\/05\/qemu-16mb.png\" alt=\"booting FreeDOS in QEMU with 16 MB memory\" class=\"wp-image-10579\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"adding-storage\">Adding storage<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A virtual machine needs a hard disk to be useful, so you can write data back to the disk. To use a hard disk with QEMU, you first need to define a <em>virtual disk image<\/em> using the <strong>qemu-img<\/strong> command. By default, this creates <em>img<\/em> formatted disk images, which do not contain metadata. You can use QEMU with these disk images, but you will see warnings that QEMU needed to guess values for the disk, such as this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>WARNING: Image format was not specified for 'disk.img' and probing guessed raw.\n         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.\n         Specify the 'raw' format explicitly to remove the restrictions.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Instead, I recommend the QCOW2 disk image format. This image format is also a little faster to use in QEMU. To define a QCOW2 disk image, specify the <code>-f qcow2<\/code> option when creating a new disk image. For example, to create a disk image called <code>disk.qcow2<\/code> that\u2019s 5 MB in size, use this command line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ qemu-img create -f qcow2 disk.qcow2 5M<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You can define larger disks using <code>G<\/code> to indicate <em>gigabytes<\/em>, such as <code>2G<\/code> to define a 2 GB disk image.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Add the disk to the system using the <code>-hda<\/code> option. This uses the common Linux notation where <code>-hda<\/code> indicates an IDE disk drive. You can also add <code>-hdb<\/code> to indicate a second IDE disk drive.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">However, I prefer to tell the virtual machine what device to boot from, using the <code>-boot order<\/code> option. This uses the DOS drive letters to indicate devices: <code>a<\/code> or <code>b<\/code> to indicate the first or second floppy drive, <code>c<\/code> for the first hard disk, or <code>d<\/code> to use the first CD-ROM drive. You can also boot from the by using <code>n<\/code> through <code>p<\/code> to indicate one of four network adapters. To boot FreeDOS using QEMU from the CD-ROM, use <code>order=d<\/code> to boot from the LiveCD:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ qemu-system-x86_64 -enable-kvm -m 16 -hda disk.qcow2 -cdrom FD14LIVE.iso -boot order=d<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"my-qemu-command-line\">My QEMU command line<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You can specify all kinds of options to configure a QEMU virtual machine in a particular way. The command line can become quite long, so I prefer to save my standard boot options in a Bash script, so I can just type <code>qemu<\/code> and the script starts QEMU using my very long command line with my special configurations. This is the command line I use:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>qemu-system-i386 -enable-kvm -m 32 -rtc base=localtime -audiodev pa,id=snd -machine pcspk-audiodev=snd -device sb16,audiodev=snd -device adlib,audiodev=snd -global i8042.kbd-throttle=on -hda freedos.qcow2 -hdb files.qcow2 -cdrom T2505BNS.iso<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This has a lot of options, but we already know several items on this command line:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>I use a <code>i386<\/code> machine for the QEMU virtual machine type, with 32 MB memory.<\/li>\n\n\n\n<li>My first hard disk is <code>freedos.qcow2<\/code>. I usually start with a fresh virtual disk every time I install a new version of FreeDOS.<\/li>\n\n\n\n<li>My second hard disk is <code>files.qcow2<\/code>, where I store all of my personal files and anything else I don\u2019t want to lose whenever I reinstall FreeDOS.<\/li>\n\n\n\n<li>The CD-ROM is <code>T2505BNS.iso<\/code>, which is the FreeDOS Monthly Test Release from May 2025.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Some of the other command line options may be easier to understand if you pay close attention to the command line options:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The virtual machine\u2019s <em>real time clock<\/em> uses my computer\u2019s local time.<\/li>\n\n\n\n<li>I set up an audio device using my Linux system\u2019s Pulse Audio, called \u201csnd.\u201d<\/li>\n\n\n\n<li>I defined the virtual machine\u2019s internal monaural PC speaker to generate tones through Pulse Audio (\u201csnd\u201d).<\/li>\n\n\n\n<li>I emulated a Sound Blaster 16 sound effects card, and an Ad Lib digital music card, both using Pulse Audio (\u201csnd\u201d).<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The only option that\u2019s a bit tricky is the extra <code>-global i8042.kbd-throttle=on<\/code> option. This activates a QEMU fix so that programs compiled with Borland (such as the IDE in Borland C or Borland Pascal) will read the keyboard correctly; Borland did a weird trick to read arrow keys which is not supported by the default keyboard configuration in QEMU.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here&#8217;s how I boot other systems using virtual machines in QEMU<\/p>\n","protected":false},"author":33,"featured_media":2815,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[5,428],"tags":[104,91],"class_list":["post-10577","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux","category-qemu","tag-command-line","tag-linux"],"modified_by":"Jim Hall","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/10577","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10577"}],"version-history":[{"count":6,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/10577\/revisions"}],"predecessor-version":[{"id":10617,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/10577\/revisions\/10617"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/2815"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10577"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10577"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10577"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}