7 Welcome. The purpose of this tool is to simplify the creation of
8 common forms of guests for the V3VEE environment on a Linux system.
9 These guests *should* work for any host embedding (e.g., Kitten) but
10 there may be hidden Linux assumptions.
12 The tool assumes you have already built Palacios, the Linux embedding,
13 and the Linux user-space tools. If you haven't done this, hit CTRL-C
14 now, configure and build Palacios, the user-space tools, and run
17 This tool also assumes that you have the environment produced by
18 v3_config_v3vee.pl sourced:
22 What this tool builds is a directory that contains a guest
23 configuration file (the ".pal" file) and its dependent files. Note
24 that lots of additional functionality is possible beyond what can be
25 configured with this tool. The precise functionality depends on the
26 version and branch of Palacios, and what was configured into it when
27 it was built. To access such functionality, you need to write your
28 own .pal file, or use one generated by this tool as a basis.
30 Any .pal guest configuration file is instantiated as a VM in the
34 v3_create -b guest.pal name_of_guest
36 Any files (disk images) that your guest configuration depends on
37 must be accessible when v3_create is run.
39 Once the VM is instantiated, you can then launch it:
41 v3_launch /dev/v3-vmN (N is given by the v3_create command)
43 We will configure your guest via a sequence of questions.
48 $pdir = $ENV{PALACIOS_DIR};
49 $qdir = $ENV{PALACIOS_QEMU_DIR};
51 $haveqemu = defined($qdir);
53 if (!defined($pdir)) {
54 print "Please set PALACIOS_DIR (you probably have not sourced ENV) and try again\n";
58 $otherbios = get_palacios_core_feature($pdir,"V3_CONFIG_OTHERBIOS");
59 $otherbios = !defined($otherbios) ? 0 : $otherbios eq "y" ? 1: 0;
61 print "Your Palacios installation is set up for a custom BIOS. \n";
62 print "You probably do NOT want to use this tool... Continue ? [n] : ";
63 if (get_user("n") eq "n") { exit -1; }
68 print "What is the name of your guest? [$name] : ";
69 $name = get_user($name);
72 print "What is the directory into which we will put your guest? [$dir] : ";
73 $dir = get_user($dir);
75 print "Unable to create the directory\n";
79 $config{numcores} = quant_question("How many cores will your guest have?", 1);
81 $config{mem} = quant_question("How much memory should it have in MB?", 256);
83 if ($config{numcores}>1) {
84 print "Do you want to to produce a NUMA configuration and mapping for your guest? [n] : ";
85 if (get_user("n") eq "y") {
86 do_numa_config(\%config,$pdir);
90 do_swapping(\%config, $pdir);
93 print "We will give your guest the default performance tuning characteristics\n";
94 $config{perftune_block} .= <<PERFTUNE
96 <strategy>friendly</strategy>
97 <threshold>1000</threshold>
103 print "We will give your guest the default host scheduler interaction characteristics\n";
104 $config{schedule_hz_block} .= " <schedule_hz>100</schedule_hz>\n";
107 $config{telemetry} = yn_question("Do you want telemetry (information about guest exits) ?", "y", "enable", "disable");
110 $config{paging_mode} = yn_question("Do you want to use nested paging if possible on your hardware?\n This will often (but not always) perform faster than shadow paging. ", "y", "nested", "shadow");
112 $config{large_pages} = yn_question("Do you want to use large pages if possible on your hardware?\n This will often (but not always) perform faster. ", "n", "true", "false");
114 print "We will give your guest the default shadow paging strategy for when shadow paging is used.\n";
115 $config{shadow_strategy} = "VTLB";
118 $config{memmap_block} = " <!-- there are no passthrough memory regions, but you can add them using\n".
119 " the <memmap> syntax described in the manual -->\n";
121 if (is_palacios_core_feature_enabled($pdir, "V3_CONFIG_EXT_VMWARE")) {
122 print "We will include the VMware Personality Extension since your Palacios build has it enabled\n";
123 $config{extensions_block} .= " <extension name=\"VMWARE_IFACE\"></extension>\n";
127 do_bioses(\%config, $pdir, $dir);
133 do_device(\%config, $pdir, "V3_CONFIG_BOCHS_DEBUG", "BOCHS_DEBUG", "bios_debug");
134 do_device(\%config, $pdir, "V3_CONFIG_OS_DEBUG", "OS_DEBUG", "os_debug");
140 do_device(\%config, $pdir, "V3_CONFIG_PIC", "8259A", "PIC", 1); # must have
141 if ($config{numcores}==1 && is_palacios_core_feature_enabled($pdir,"V3_CONFIG_BOCHSBIOS")) {
142 print "This is a single core guest and your Palacios setup uses the legacy BOCHS BIOS.\n";
143 print " Do you want to have only the legacy (pre-APIC) interrupt controller logic? [n] :";
144 if (get_user("n") eq "y") {
148 do_device(\%config, $pdir, "V3_CONFIG_APIC", "LAPIC", "apic", 1); # must have
149 do_device(\%config, $pdir, "V3_CONFIG_IO_APIC", "IOAPIC", "ioapic", 1, undef, " <apic>apic</apic>\n");
153 # PCI buses and north/south bridge - all must haves
155 do_device(\%config, $pdir, "V3_CONFIG_PCI", "PCI", "pci0",1); # must have
156 do_device(\%config, $pdir, "V3_CONFIG_I440FX", "i440FX", "northbridge",1, undef, " <bus>pci0</bus>\n"); #must have
157 do_device(\%config, $pdir, "V3_CONFIG_PIIX3", "PIIX3", "southbridge",1, undef, " <bus>pci0</bus>\n"); #must have
160 # MPTABLE for legacy BIOS. Innocuous for SEABIOS or OTHERBIOS
163 if (is_palacios_core_feature_enabled($pdir,"V3_CONFIG_MPTABLE")) {
164 print "We will include a classic MPTABLE constructor to describe your machine to the guest\n";
165 add_device(\%config, "MPTABLE", "mptable");
167 if ($config{numcores}>1 && is_palacios_core_feature_enabled($pdir,"V3_CONFIG_BOCHSBIOS")) {
168 print "This is a multicore guest, and your Palacios configuration uses the classic BOCHS BIOS\n".
169 "but does not have the MPTABLE constructor enabled... This guest will almost\n".
170 "certainly fail to work. Do you want to continue anyway? [n] :";
171 if (get_user("n") eq "n") {
181 do_device(\%config, $pdir, "V3_CONFIG_PIT", "8254_PIT", "PIT",1); # must have
184 if (defined($ENV{PALACIOS_QEMU_DIR})) {
185 print "\nYour Palacios configuration includes the ability to use QEMU devices from a patched QEMU.\n";
186 print "Do you want to use QEMU's PS/2, graphics, and serial port devices? [n] : ";
187 if (get_user("n") eq "y") {
188 do_qemu_ui(\%config, $pdir, $dir);
192 if (!defined($config{qemu_ui})) {
194 # Keyboard and mouse (PS/2 controller)
196 do_device(\%config, $pdir, "V3_CONFIG_KEYBOARD", "KEYBOARD", "keyboard",1); #must have
199 # Displays, Consoles, Serial
201 print "\nWe will now consider consoles and serial ports.\n\n";
202 do_consoles_and_ports(\%config, $pdir);
208 # Storage controllers and devices (attached to PCI bus)
211 print "\nWe will now consider storage controllers and devices.\n\n";
212 do_storage(\%config, $pdir, $dir, $name, "pci0", "southbridge");
218 # Network interfaces (attached to PCI bus)
221 print "\nWe will now consider network interfaces.\n\n";
222 do_network(\%config, $pdir, $dir, $name, "pci0", "southbridge");
226 # Sanity-check - is there something bootable?
229 if (!($config{havecd} && !($config{havehd}))) {
230 print "The guest's storage configuration does not have either a CD or an HD. \n";
231 print "This means the guest BIOS will have nothing local to boot. \n";
232 if (!($config{havenic})) {
233 print "The guest also does does not have a NIC, which means the BIOS cannot\n";
234 print "do a network boot.\n";
236 print "The guest does have a NIC, so a network boot is possible, if the\n";
237 print "BIOS supports it.\n";
239 print "If this is not your intent, you probably want to CTRL-C and try again.\n";
242 print "The BIOS boot sequence will be set to CD,HD. If you need to change this\n";
243 print "later, edit the <bootseq> block within the NVRAM device.\n";
248 # Note: do_storage *must* have placed an IDE named ide0 in order for this to work
250 do_device(\%config, $pdir, "V3_CONFIG_NVRAM", "NVRAM", "nvram", 1, undef, " <storage>ide0</storage>\n <bootseq>cd,hd</bootseq>\n"); #must have
254 # Generic Catch-all Device
256 do_generic(\%config, $pdir);
259 open(PAL,">$dir/$name.pal") or die "Cannot open $dir/$name.pal\n";
263 print $target "<vm class=\"PC\">\n\n";
264 print $target file_setup(\%config), "\n";
265 print $target bios_setup(\%config),"\n";
266 print $target memory_setup(\%config), "\n";
267 print $target swapping_setup(\%config), "\n";
268 print $target paging_setup(\%config), "\n";
269 print $target memmap_setup(\%config), "\n";
270 print $target numa_setup(\%config), "\n";
271 print $target core_setup(\%config), "\n";
272 print $target schedule_setup(\%config), "\n";
273 print $target perftune_setup(\%config), "\n";
274 print $target telemetry_setup(\%config), "\n";
275 print $target extensions_setup(\%config), "\n";
276 print $target device_setup(\%config), "\n";
277 print $target "</vm>\n";
281 #print Dumper(\%config);
283 if (defined($config{qemu}) && $config{qemu} eq "y") {
284 gen_qemu_startup(\%config, $pdir, $dir);
287 print "\n\nYour guest is now ready in the directory $dir\n\n";
288 print "To run it, do:\n\n";
290 print " v3_create -b $name.pal $name\n";
291 print " v3_launch /dev/v3-vmN (N given by v3_create)\n\n";
292 print "Other useful tools:\n\n";
293 print " v3_console (CGA console)\n";
294 print " v3_stream (connect to stream, for example, serial port)\n\n";
300 my ($ques, $default) = @_;
302 print $ques." [$default] : ";
304 return get_user($default);
308 my ($ques, $default, $yans, $nans) = @_;
312 print $ques." [$default] : ";
313 $ans = get_user($default);
315 if (substr($ans,0,1) eq 'y' || substr($ans,0,1) eq 'Y') {
337 %numa = get_numa_data();
339 $numvcores = $cr->{numcores};
341 print "NUMA configuration involves the following:\n";
342 print " 1. Definition of virtual NUMA nodes and their corresponding regions of guest physical memory\n";
343 print " 2. Mapping of virtual NUMA nodes to physical NUMA nodes\n";
344 print " 3. Mapping of virtual cores to virtual NUMA nodes\n";
345 print " 4. Mapping of virtual cores to physical cores\n";
346 print "Your guest contains ".$numvcores." virtual cores.\n";
347 print "This host contains ".$numa{numcores}." physical cores and ".$numa{numnodes}." physical nodes.\n";
348 print "How many physical NUMA nodes does your target hardware have? [".$numa{numnodes}."] ? ";
349 $numpnodes=get_user($numa{numnodes});
350 $canauto=0 if ($numpnodes > $numa{numnodes});
351 print "How many physical cores does your target hardware have? [".$numa{numcores}."] ? ";
352 $numpcores=get_user($numa{numcores});
353 $canauto=0 if ($numpcores > $numa{numcores});
355 print "How many virtual NUMA nodes do you want? (up to $numvcores) for auto) [2] : ";
356 $numvnodes=get_user("2");
357 } while ($numvnodes<=0 || $numvnodes>$numvcores);
358 $cr->{numnodes} = $numvnodes;
359 $pernode = int(($cr->{mem}*1024*1024)/$numvnodes);
360 $lastnode = $pernode + ($cr->{mem}*1024*1024)-$pernode*$numvnodes;
361 print "Your guest has ".$cr->{mem}." MB of RAM, which we have defined and mapped like this:\n";
362 for ($i=0;$i<$numvnodes;$i++) {
363 my $start=$i*$pernode;
364 my $end=(($i==($numvnodes-1)) ? $start+$lastnode : $start+$pernode);
365 my $pnode = $i % $numpnodes;
366 $vnodemap[$i]=$pnode;
367 $start=sprintf("0x%x",$start);
368 $end=sprintf("0x%x",$end);
369 print "vnode $i : GPA $start to GPA $end : pnode $pnode\n";
370 push @{$cr->{nodes}}, { start=>$start, end=>$end, vnode=>$i, pnode=>$pnode};
374 print "We can now automatically map virtual cores to virtual NUMA nodes and physical CPUs using strided assignment\n";
375 print "assuming *this host's* NUMA configuration. Or you can enter the assignments manually. \n";
376 print " Which would you prefer {auto,manual} [auto] ? : ";
377 $doauto=1 if (get_user("auto") eq "auto");
379 print "Automatic mapping of virtual cores to virtual NUMA nodes and physical CPUs is not possible\n";
380 print "given your host configuration. Please configure manually below.\n";
384 for ($i=0;$i<$numvcores;$i++) {
385 my $vnode = $i % $numvnodes;
386 my $pnode = $vnodemap[$vnode];
387 my $pcores = $numa{"node$pnode"}{cores};
388 my $numpcores_per_pnode = $#{$pcores}+1; # assumes identical number on each node...
389 my $pcore = $numa{"node$pnode"}{cores}->[int($i/$numpnodes) % $numpcores_per_pnode];
390 print "vcore $i : vnode $vnode : pnode $pnode : pcore $pcore\n";
391 $cr->{"core$i"}{pcore} = $pcore;
392 $cr->{"core$i"}{vnode} = $vnode;
395 for ($i=0;$i<$numvcores;$i++) {
396 print "What is the virtual NUMA node for virtual core $i ? [] : ";
397 my $vnode = get_user("");
398 my $pnode = $vnodemap[$vnode];
399 print "That maps to physical NUMA node $pnode.\n";
400 print "What is the physical core for virtual core $i ? [] : ";
401 my $pcore = get_user("");
402 print "vcore $i : vnode $vnode : pnode $pnode : pcore $pcore\n";
403 $cr->{"core$i"}{pcore} = $pcore;
404 $cr->{"core$i"}{vnode} = $vnode;
411 sub get_numa_data() {
417 open (N, "numactl --hardware |");
419 if ($line=~/^node\s+(\d+)\s+cpus:\s+(.*)$/) {
421 my @cpus = split(/\s+/,$2);
423 if ($node>$maxnode) { $maxnode=$node; }
424 foreach $cpu (@cpus) {
425 if ($cpu>$maxcpu) { $maxcpu=$cpu; }
427 $numa{"node$node"}{cores}=\@cpus;
430 $numa{numnodes}=$maxnode+1;
431 $numa{numcores}=$maxcpu+1;
437 my ($cr, $pdir) = @_;
439 my $canswap = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_SWAPPING");
440 my $mem = $cr->{mem};
444 $cr->{swapping} = yn_question("Do you want to use swapping?", "n", "y", "n");
446 if ($cr->{swapping} eq "y") {
447 $cr->{swap_alloc} = quant_question("How much memory do you want to allocate [MB] ?", $mem/2);
448 print "We will use the default swapping strategy.\n";
449 $cr->{swap_strat} = "default";
450 print "What file do you want to swap to? [./swap.bin] ";
451 $cr->{swap_file} = get_user("./swap.bin");
457 my ($cr, $name, $fileid, $address) =@_;
459 push @{$cr->{bios_list}}, { name=>$name, fileid=>$fileid, address=>$address };
464 my ($cr, $pdir, $dir) = @_;
465 my $nextbios = defined($cr->{bios_list}) ? "bios".($#{$cr->{bios_list}}+1) : "bios0";
467 if (yn_question("Add a".($nextbios eq "bios0" ? "" : "nother")." custom bios? ", "n", "y", "n") eq "y") {
468 my ($n, $fn, $addr) ;
469 print "What is your name for this bios? [$nextbios] : ";
470 $n = get_user($nextbios);
472 print "Where is the path to the file for bios $n ? ";
475 print "Cannot find $fn, try again\n";
478 if (system("cp $fn $dir/$n.dat")) {
479 print "Unable to copy $fn\n";
482 add_file($cr, "$n", "$n.dat");
483 print "What is the destination physical linear address (in hex) for bios $n [0xf0000] ? ";
484 $addr = get_user("0xf0000");
485 add_bios($cr,$n,$n,$addr);
496 my ($cr, $pdir, $dir) = @_;
498 $cr->{bios_custom} = yn_question("Do you want to customize BIOSes? (done automatically later for QEMU devices) ", "n", "y", "n");
500 if ($cr->{bios_custom} eq "y") {
501 $cr->{bios_custom_nobios} = yn_question("Disable built-in system bios? ", "n", "y", "n");
502 $cr->{bios_custom_novgabios} = yn_question("Disable built-in VGA bios? ", "n", "y", "n");
504 while (do_bios($cr, $pdir, $dir)) {}
512 my ($cr,$pdir,$feature, $class, $id, $hardfail, $optblob, $nestblob) =@_;
514 if (is_palacios_core_feature_enabled($pdir, $feature)) {
515 print "We will include a $class since your Palacios build has it enabled\n";
516 add_device(\%config, $class, $id, $optblob, $nestblob);
518 if (defined($hardfail) && $hardfail) {
519 print "Wow, your Palacios build doesn't have a $class... We can't live without that...\n";
522 print "Not configuring a $class since your Palacios build doesn't have it enabled\n";
527 sub add_qemu_device {
528 my ($cr, $pdir, $type, $name, $url) = @_;
532 push @{$cr->{qemu_devices}}, { type=>$type, name=>$name, url=>$url } ;
537 my ($cr, $pdir, $dir) = @_;
538 my $vgabios=$ENV{PALACIOS_QEMU_DIR}."/share/qemu/vgabios-cirrus.bin";
542 # PS/2 is a generic device
543 add_device($cr,"GENERIC","qemu-ps2",
544 " forward=\"host_device\" hostdev=\"user:qemu-ps2\" ",
545 " <ports> <start>0x60</start> <end>0x60</end> <mode>PASSTHROUGH</mode> </ports>\n".
546 " <ports> <start>0x64</start> <end>0x64</end> <mode>PASSTHROUGH</mode> </ports>\n".
547 " <ports> <start>0x80</start> <end>0x80</end> <mode>PASSTHROUGH</mode> </ports>\n");
548 add_qemu_device($cr,$pdir, "qemu-ps2", "qemu-ps2", "user:qemu-ps2");
551 add_device($cr,"GENERIC", "qemu-serial",
552 " forward=\"host_device\" hostdev=\"user:qemu-serial\" ",
553 " <ports> <start>0x3f8</start> <end>0x3ff</end> <mode>PASSTHROUGH</mode> </ports>\n".
554 " <ports> <start>0x2f8</start> <end>0x2ff</end> <mode>PASSTHROUGH</mode> </ports>\n".
555 " <ports> <start>0x3e8</start> <end>0x3ef</end> <mode>PASSTHROUGH</mode> </ports>\n".
556 " <ports> <start>0x2e8</start> <end>0x2ef</end> <mode>PASSTHROUGH</mode> </ports>\n");
557 add_qemu_device($cr,$pdir, "qemu-serial", "qemu-serial", "user:qemu-serial");
559 # Video has both a generic device and a PCI device (enhanced vga) and a bios
560 add_device($cr,"GENERIC", "qemu-video-legacy",
561 " forward=\"host_device\" hostdev=\"user:qemu-video-legacy\" ",
562 " <ports> <start>0x3b4</start> <end>0x3da</end> <mode>PASSTHROUGH</mode> </ports>\n".
563 " <memory> <start>0xa0000</start> <end>0xbffff</end> <mode>PASSTHROUGH</mode> </memory>\n");
564 add_qemu_device($cr,$pdir, "qemu-video-legacy", "qemu-video-legacy", "user:qemu-video-legacy");
566 add_device($cr, "PCI_FRONT", "qemu-video",
567 " hostdev=\"user:qemu-video\" ",
568 " <bus>pci0</bus>\n");
570 add_qemu_device($cr,$pdir, "qemu-video", "qemu-video", "user:qemu-video");
572 print "To use QEMU video, we will need to add the relevant bios. \n";
574 print "Where is the QEMU video bios ? [$vgabios] : ";
575 $vgabios = get_user($vgabios);
577 if (system("cp $vgabios $dir/qemu-videobios.dat")) {
578 print "Cannot copy $vgabios, try again\n";
584 print "Cannot find $vgabios, try again\n";
588 add_file($cr, "qemu-videobios", "qemu-videobios.dat");
589 add_bios($cr, "qemu-videobios", "qemu-videobios", "0xc0000");
590 $cr->{bios_custom} = 'y';
591 $cr->{bios_custom_novgabios} = 'y';
595 sub do_consoles_and_ports {
596 my ($cr, $pdir) = @_;
598 my $cga = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_CGA");
599 my $curses = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_CURSES_CONSOLE");
600 my $cons = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_CONSOLE");
601 my $cancga = $cga && $curses && $cons;
602 my $vga = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_VGA");
603 my $gcons = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_GRAPHICS_CONSOLE");
604 my $canvga = $vga && $gcons;
605 my $serial = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_SERIAL_UART");
606 my $charstream = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_CHAR_STREAM");
607 my $stream = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_STREAM");
608 my $canserial = $serial && $charstream && $stream;
609 my $virtioconsole = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_LINUX_VIRTIO_CONSOLE");
610 my $canvirtioconsole = $virtioconsole; # probably need to verify frontend
611 my $paragraph = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_PARAGRAPH");
612 my $canparagraph = $paragraph && $gcons;
614 print "Your Palacios configuration allows the following options:\n";
615 print " * CGA: classic 80x25 text-only PC console (common option): ".($cancga ? "available\n" : "NOT AVAILABLE\n");
616 print " * VGA: classic 640x480 graphical PC console (uncommon option): ".($canvga ? "available\n" : "NOT AVAILABLE\n");
617 print " * SERIAL: classic PC serial ports (common option): ".($canserial ? "available\n" : "NOT AVAILABLE\n");
618 print " * VIRTIO: Linux Virtio Console (uncommon option): ".($canvirtioconsole ? "available\n" : "NOT AVAILABLE\n");
619 print " * PARAGRAPH: Paravirtualized graphics card (uncommon option): ".($canparagraph ? "available\n" : "NOT AVAILABLE\n");
620 print "The CGA and VGA options are mutually exclusive\n";
621 print "THe VGA and PARAGRAPH options are mutually exclusive\n";
623 if (!($cancga || $canvga || $canserial || $canvirtioconsole)) {
624 print "Hmm... No console mechanism is enabled in your Palacios build...\n";
625 print " This is probably not what you want...\n";
630 print "Do you want to use CGA as a console? [y] : ";
631 if (get_user("y") eq "y") {
632 add_device(\%config, "CGA_VIDEO", "cga", "passthrough=\"disable\"");
633 add_device(\%config, "CURSES_CONSOLE", "console", undef,
634 " <frontend tag=\"cga\" />\n".
635 " <tty>user</tty>\n");
641 if ($canvga && !$didcga) {
642 print "Do you want to use VGA as a console? [n] : ";
643 if (get_user("n") eq "y") {
644 add_device(\%config, "VGA", "vga", "passthrough=\"disable\" hostframebuf=\"enable\"");
645 # there is no gconsole device
652 print "You can include serial ports whether you use them for a console or not\n";
653 print "Note that you must configure your guest to place its console onto a serial port\n";
654 print "for it to be visible\n";
655 print "Do you want to include the serial ports (COM1..4) ? [y] : ";
656 if (get_user("y") eq "y") {
657 add_device(\%config,"SERIAL","serial");
658 add_device(\%config,"CHAR_STREAM","stream1","name=\"com1\"", " <frontend tag=\"serial\" com_port=\"1\" />\n");
659 add_device(\%config,"CHAR_STREAM","stream2","name=\"com2\"", " <frontend tag=\"serial\" com_port=\"2\" />\n");
660 add_device(\%config,"CHAR_STREAM","stream3","name=\"com3\"", " <frontend tag=\"serial\" com_port=\"3\" />\n");
661 add_device(\%config,"CHAR_STREAM","stream4","name=\"com4\"", " <frontend tag=\"serial\" com_port=\"4\" />\n");
668 if ($canvirtioconsole) {
669 print "Do you want to add a VIRTIO console? [n] : ";
670 if (get_user("n") eq "y") {
671 add_device(\%config,"LNX_VIRTIO_CONSOLE","virtio-cons",undef," <bus>pci0</bus>\n");
672 print "NOTE: no backend for the VIRTIO console is currently configured\n";
678 if ($canparagraph && !$didvga) {
679 print "Do you want to add a PARAGRAPH graphics card? [n] : ";
680 if (get_user("n") eq "y") {
681 add_device(\%config, "PARAGRAPH", "paragraph", undef,
682 " <bus>pci0</bus>\n".
683 " <mode>gcons_mem</bus>\n");
688 if (!($didcga || $didvga || $didserial || $didvirtioconsole || $didparagraph)) {
689 print "You have configured your guest without any obvious way of interacting with it....\n";
690 print " This is probably not what you want...\n";
697 my ($cr,$pdir,$dir,$name, $pcibus)=@_;
698 my $canvnet = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_VNET");
699 my $canbridge = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_NIC_BRIDGE");
700 my $canoverlay = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_VNET_NIC") && $canvnet;
701 my $canvirtio = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_LINUX_VIRTIO_NET");
702 my $canvirtiovnet = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_LINUX_VIRTIO_VNET"); # not sure...
703 my $canne2k = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_NE2K");
704 my $canrtl8139 = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_RTL8139");
713 push @devs, "virtio" if $canvirtio;
714 push @devs, "rtl8139" if $canrtl8139;
715 push @devs, "ne2000" if $canne2k;
717 push @backends, "bridge" if $canbridge;
718 push @backends, "vnet" if $canoverlay;
721 print "You have no network device implementations enabled in your Palacios build, so we are skipping networking\n";
725 if ($#backends==-1) {
726 print "You have no network device backends enabled in your Palacios build, so we are skipping networking\n";
733 last if (!yn_question("Do you want to add ".($num==0 ? "a" : "another")." network device?","n",1,0));
734 print "This requires the addition of the frontend device (the NIC) and a backend device.\n";
735 print "Frontends in Palacios include:\n";
736 print " * Virtio NIC (paravirtualized - common) : ".($canvirtio? "available" : "UNAVAILABLE")."\n";
737 print " * RTL8139 NIC (uncommon) : ".($canrtl8139? "available" : "UNAVAILABLE")."\n";
738 print " * NE2000 NIC (uncommon) : ".($canne2k? "available" : "UNAVAILABLE")."\n";
739 print "Which frontend do you want to add? {".join(", ", @devs)."} : ";
740 $front = get_user("");
741 @test = grep { /^$front$/ } @devs;
743 print "Unknown frontend\n";
746 print "Backends in Palacios include:\n";
747 print " * Bridge (direct attach to host NIC - common) : ".($canbridge? "available" : "UNAVAILABLE")."\n";
748 print " * VNET overlay (uncommon) : ".($canoverlay ? "available" : "UNAVAILABLE")."\n";
749 print "Which backend do you want to add? {".join(", ", @backends)."} : ";
750 $back = get_user("");
751 @test = grep { /^$back/ } @backends;
753 print "Unknown backend\n";
757 print "What MAC address do you want your NIC to have? [$mac] : ";
759 if ($front eq "virtio") {
760 add_device($cr,"LNX_VIRTIO_NIC","net$num",undef,
761 " <bus>$pcibus</bus>\n".
762 " <mac>$mac</mac>\n".
763 " <model mode=\"guest-driven\" />\n");
764 print "The device is configured with default guest-driven operation\n";
766 if ($front eq "rtl8139") {
767 add_device($cr,"RTL8139","net$num",undef,
768 " <bus>$pcibus</bus>\n".
769 " <mac>$mac</mac>\n");
771 if ($front eq "ne2000") {
772 add_device($cr,"NE2000","net$num",undef,
773 " <bus>$pcibus</bus>\n".
774 " <mac>$mac</mac>\n");
777 if ($back eq "bridge") {
779 print "What is the name of the host NIC you want to bridge to? [eth0] : ";
780 $host=get_user("eth0");
781 add_device($cr,"NIC_BRIDGE","net$num-back",undef,
782 " <frontend tag=\"net$num\" />\n".
783 " <hostnic name=\"$host\" />\n");
786 if ($back eq "vnet") {
787 add_device($cr,"VNET_NIC","net$num-back",undef,
788 " <frontend tag=\"net$num\" />\n");
789 print "Important: In order to use the VNET overlay, you must also create routes at run-time via /proc/v3vee/vnet\n";
801 return sprintf("%02X:%02X:%02X:%02X:%02X:%02X",
812 my ($cr,$pdir,$dir,$name,$pcibus,$controller)=@_;
817 do_device($cr, $pdir, "V3_CONFIG_IDE", "IDE", "ide0",1,undef,
818 " <bus>$pcibus</bus>\n".
819 " <controller>$controller</controller>\n" ); # must have
820 print "You can attach up to four storage devices to the storage controller \"ide\"\n";
821 do_storage_backend($cr, $pdir, $dir, $name, "ide0", "0_0",
822 " <bus_num>0</bus_num>\n".
823 " <drive_num>0</drive_num>\n");
824 do_storage_backend($cr, $pdir, $dir, $name, "ide0", "0_1",
825 " <bus_num>0</bus_num>\n".
826 " <drive_num>1</drive_num>\n");
827 do_storage_backend($cr, $pdir, $dir, $name, "ide0", "1_0",
828 " <bus_num>1</bus_num>\n".
829 " <drive_num>0</drive_num>\n");
830 do_storage_backend($cr, $pdir, $dir, $name, "ide0", "1_1",
831 " <bus_num>1</bus_num>\n".
832 " <drive_num>1</drive_num>\n");
834 if (is_palacios_core_feature_enabled($pdir,"V3_CONFIG_LINUX_VIRTIO_BLOCK")) {
835 print "You can attach VIRTIO block devices. How many do you need? [0] : ";
836 my $num = get_user("0");
838 for ($i=0;$i<$num;$i++) {
839 add_device($cr,"LNX_VIRTIO_BLK","virtioblk$i",undef," <bus>$pcibus</bus>\n");
840 do_storage_backend($cr, $pdir, $dir, $name, "virtioblk$i", "data$i", "");
848 sub do_storage_backend {
849 my ($cr, $pdir, $dir, $name, $frontend, $loc, $frontendblock) = @_;
850 my ($canramdisk, $canfiledisk, $cannetdisk, $cantmpdisk, $canqcowdisk);
851 my @devs=("cd","hd","nothing");
858 $canramdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_RAMDISK");
859 $canfiledisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_FILEDISK");
860 $canqcowdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_QCOWDISK");
861 $cannetdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_NETDISK");
862 $cantmpdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_TMPDISK");
863 push @disks, "ramdisk" if $canramdisk;
864 push @disks, "filedisk" if $canramdisk;
865 push @disks, "qcowdisk" if $canramdisk;
866 push @disks, "netdisk" if $cannetdisk;
867 push @disks, "tmpdisk" if $cantmpdisk;
870 if (!$canramdisk && !$canfiledisk && !$cannetdisk && !$cantmpdisk && !$canqcowdisk) {
871 print "You have no storage implementations enabled in your Palacios build, so it is impossible\n";
872 print "to add anything to storage controller \"$frontend\" location \"$loc\"\n";
878 print "What do you want to attach to storage controller \"$frontend\" location \"$loc\"\n";
879 print " Your options are {".join(", ",@devs)."} [nothing] : ";
880 $what = get_user("nothing");
881 @test = grep { /^$what$/ } @devs;
883 if ($what eq "nothing") {
886 print "A storage device requires one of the following implementations\n";
887 print " * RAMDISK - the data is kept in memory (common) : ".($canramdisk ? "available" : "UNAVAILABLE")."\n";
888 print " * FILEDISK - the data is kept in a host file (common) : ".($canfiledisk ? "available" : "UNAVAILABLE")."\n";
889 print " * QCOWDISK - the data is kept in a host file (qcow) : ".($canqcowdisk ? "available" : "UNAVAILABLE")."\n";
890 print " * NETDISK - the data is accessed via the network (uncommon) : ".($cannetdisk ? "available" : "UNAVAILABLE")."\n";
891 print " * TMPDISK - the data is kept in memory and discarded (common) : ".($cantmpdisk ? "available" : "UNAVAILABLE")."\n";
893 print "Which option do you want for this device? {".join(", ",@disks)."} [] : ";
894 $type = get_user("");
895 my @test = grep {/^$type$/} @disks;
899 if ($type eq "filedisk" || $type eq "ramdisk" || $type eq "qcowdisk") {
900 print "$type requires a file (.iso for example). Do you have one? [y] : ";
901 if (get_user("y") eq "y") {
903 print "What is its path? [] : ";
904 $file = get_user("");
906 print "$file does not exist\n";
909 if (system("cp $file $dir/$frontend\_$loc.dat")) {
910 print "Unable to copy $file\n";
916 print "We will make one. How big should it be in MB? [64] : ";
917 $size = get_user("64");
918 gen_image_file("$dir/$frontend\_$loc.dat",$size);
920 $attach=" <frontend tag=\"$frontend\">\n";
922 $attach.=" <model>V3VEE CDROM</model>\n".
923 " <type>CDROM</type>\n".$frontendblock;
926 $attach.=" <model>V3VEE HD</model>\n".
927 " <type>HD</type>\n".$frontendblock;
930 $attach.=" </frontend>\n";
932 if ($type eq "ramdisk") {
933 add_device($cr,"RAMDISK","$frontend\_$loc", undef,
934 " <file>$frontend\_$loc</file>\n".$attach);
935 add_file($cr, "$frontend\_$loc", "$frontend\_$loc.dat");
936 } elsif ($type eq "filedisk") {
937 add_device($cr,"FILEDISK","$frontend\_$loc", $what eq "hd" ? "writable=\"1\"" : undef,
938 " <path>$frontend\_$loc.dat</path>\n".$attach);
940 add_device($cr,"QCOWDISK","$frontend\_$loc", $what eq "hd" ? "writable=\"1\"" : undef,
941 " <path>$frontend\_$loc.dat</path>\n".$attach);
945 print "$type is not currently supported\n";
957 <!-- DMA 1 registers -->
960 <mode>PRINT_AND_IGNORE</mode>
963 <!-- DMA 2 registers -->
966 <mode>PRINT_AND_IGNORE</mode>
969 <!-- DMA 1 page registers -->
972 <mode>PRINT_AND_IGNORE</mode>
975 <!-- DMA 2 page registers -->
978 <mode>PRINT_AND_IGNORE</mode>
981 <!-- DMA 1 Misc Registers -->
984 <mode>PRINT_AND_IGNORE</mode>
987 <!-- DMA 2 Misc Registers -->
990 <mode>PRINT_AND_IGNORE</mode>
996 <mode>PRINT_AND_IGNORE</mode>
1000 <start>0x279</start>
1002 <mode>PRINT_AND_IGNORE</mode>
1006 <start>0xa79</start>
1008 <mode>PRINT_AND_IGNORE</mode>
1012 my @dev = find_devices_by_class($cr,"PARALLEL");
1014 $block .= <<GENERIC2
1016 <!-- Parallel Port -->
1017 <start>0x378</start>
1019 <mode>PRINT_AND_IGNORE</mode>
1024 my @par = find_devices_by_class($cr,"SERIAL");
1025 if ($#par<0 && !defined($cr->{qemu_ui})) {
1028 <!-- Serial COM 1 -->
1029 <start>0x3f8</start>
1031 <mode>PRINT_AND_IGNORE</mode>
1034 <!-- Serial COM 2 -->
1035 <start>0x2f8</start>
1037 <mode>PRINT_AND_IGNORE</mode>
1040 <!-- Serial COM 3 -->
1041 <start>0x3e8</start>
1043 <mode>PRINT_AND_IGNORE</mode>
1046 <!-- Serial COM 4 -->
1047 <start>0x2e8</start>
1049 <mode>PRINT_AND_IGNORE</mode>
1055 do_device($cr, $pdir, "V3_CONFIG_GENERIC", "GENERIC", "generic", 1, undef, $block);
1059 my ($cr, $name, $file) = @_;
1061 push @{$cr->{files}}, { name=>$name, file=>$file};
1066 my ($cr, $class, $id, $optblob, $nestblob) = @_;
1068 push @{$cr->{devices}}, { class=>$class, id=>$id, opt=>$optblob, nest=>$nestblob };
1071 sub find_devices_by_class {
1073 return grep { $_->{class} eq $c } @{$cr->{devices}};
1081 if (!defined($cr->{numa})) {
1084 $s.=" <mem_layout vnodes=\"".($#{$cr->{nodes}}+1)."\" >\n";
1085 foreach $vnode (@{$cr->{nodes}}) {
1086 $s.=" <region start_addr=\"".$vnode->{start}."\" end_addr=\"".$vnode->{end}."\" vnode=\"".$vnode->{vnode}."\" node=\"".$vnode->{pnode}."\" />\n";
1088 $s.=" </mem_layout>\n";
1099 $s.= " <cores count=\"".$cr->{numcores}."\">\n";
1100 if (!defined($cr->{numa})) {
1103 for ($i=0;$i<$cr->{numcores};$i++) {
1104 $s.= " <core target_cpu=\"".$cr->{"core$i"}{pcore}."\" vnode=\"".$cr->{"core$i"}{vnode}."\" />\n";
1116 return " <memory>".$cr->{mem}."</memory>\n";
1123 $s.= " <paging mode=\"".$cr->{paging_mode}."\">\n";
1124 $s.= " <large_pages>".$cr->{large_pages}."</large_pages>\n";
1125 $s.= " <strategy>".$cr->{shadow_strategy}."</strategy>\n";
1126 $s.= " </paging>\n";
1134 return $cr->{memmap_block};
1137 sub schedule_setup {
1140 return $cr->{schedule_hz_block};
1144 sub perftune_setup {
1147 if (defined($cr->{perftune_block})) {
1148 $s.=" <perftune>\n";
1149 $s.= $cr->{perftune_block};
1150 $s.=" </perftune>\n";
1155 sub extensions_setup {
1158 if (defined($cr->{extensions_block})) {
1159 $s.=" <extensions>\n";
1160 $s.= $cr->{extensions_block};
1161 $s.=" </extensions>\n";
1166 sub swapping_setup {
1168 if (defined($cr->{swapping}) && $cr->{swapping} eq "y") {
1169 return " <swapping enable=\"y\">\n <allocated>".$cr->{swap_alloc}."</allocated>\n <file>".$cr->{swap_file}."</file>\n <strategy>".$cr->{swap_strat}."</strategy>\n </swapping>\n";
1171 return " <!-- there is no swapping configuration, but you can add one manually -->\n";
1174 sub telemetry_setup {
1176 return " <telemetry>".$cr->{telemetry}."</telemetry>\n";
1184 if (!defined($cr->{files})) {
1185 return " <!-- this configuration contains no files -->\n";
1190 foreach $cf (@{$cr->{files}}) {
1191 $s.=" <file id=\"".$cf->{name}."\" filename=\"".$cf->{file}."\" />\n";
1201 if (!defined($cr->{bios_custom}) || $cr->{bios_custom} eq "n") {
1202 return " <!-- this configuration does not use a custom bios setup but you can add one with the <bioses> syntax-->\n";
1207 $s.= " <disable_rombios/>\n" if defined($cr->{bios_custom_nobios}) && $cr->{bios_custom_nobios} eq "y";
1208 $s.= " <disable_vgabios/>\n" if defined($cr->{bios_custom_novgabios}) && $cr->{bios_custom_novgabios} eq "y";
1209 foreach $b (@{$cr->{bios_list}}) {
1210 $s.= " <bios file=\"".$b->{fileid}."\" address=\"".$b->{address}."\" />\n";
1212 $s.= " </bioses>\n";
1224 foreach $cd (@{$cr->{devices}}) {
1225 $s.=" <device class=\"".$cd->{class}."\" id=\"".$cd->{id}."\"";
1226 if (defined($cd->{opt})) {
1229 if (!defined($cd->{nest})) {
1238 $s.=" </devices>\n";
1249 my $inp = <STDIN>; chomp($inp);
1258 sub get_kernel_feature {
1263 $x=`grep $feature= $dir/config-\`uname -r\``;
1268 if ($x=~/\s*$feature=\s*(\S*)\s*$/) {
1276 sub get_palacios_core_feature {
1281 $x=`grep $feature= $dir/.config`;
1286 if ($x=~/\s*$feature=\s*(\S*)\s*$/) {
1294 sub is_palacios_core_feature_enabled {
1295 my $out = get_palacios_core_feature(@_);
1296 return !defined($out) ? 0 : $out eq "y";
1304 $exp = log($x) /log(2);
1306 return $exp==int($exp);
1310 sub gen_image_file {
1311 my ($name, $size_mb) = @_;
1313 if (system("dd if=/dev/zero of=$name bs=1048576 count=$size_mb")) {
1321 sub gen_qemu_startup {
1322 my ($cr, $pdir, $dir) = @_;
1326 print "Generating QEMU Startup Script\n";
1328 open(Q,">$dir/qemu_startup.sh");
1329 print Q $ENV{PALACIOS_QEMU_DIR}."/bin/qemu-system-x86_64 -m 2048 -accel pal ";
1330 foreach $d (@{$cr->{qemu_devices}}) {
1331 if ($d->{type} eq "qemu-ps2") {
1332 print Q " -map KBD ".$d->{url}." ";
1333 } elsif ($d->{type} eq "qemu-serial") {
1334 print Q " -serial stdio -map SERIAL ".$d->{url}." ";
1335 } elsif ($d->{type} eq "qemu-video-legacy") {
1336 print Q " -map VGA ".$d->{url}." ";
1337 } elsif ($d->{type} eq "qemu-video") {
1338 print Q " -vga cirrus -map CIRRUS ".$d->{url}." ";
1339 } elsif ($d->{type} eq "qemu-e1000") {
1340 print Q " -nic e1000 -map E1000 ".$d->{url}." ";
1341 } elsif ($d->{type} eq "qemu-ide-legacy") {
1342 print Q " -ide ... -map IDE-LEGACY ".$d->{url}." ";
1343 } elsif ($d->{type} eq "qemu-ide") {
1344 print Q " -ide ... -map IDE ".$d->{url}." ";
1346 die "Do not know how to handle QEMU device of type ".$d->{type}."\n";