Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Basic HVM data structures and functions
[palacios.git] / v3_config_guest.pl
1 #!/usr/bin/perl -w
2
3 use Data::Dumper;
4
5 print <<END
6
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.
11
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
15 v3_config_v3vee.pl.
16
17 This tool also assumes that you have the environment produced by
18 v3_config_v3vee.pl sourced:
19
20   source ./ENV
21
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.
29
30 Any .pal guest configuration file is instantiated as a VM in the
31 following way:
32
33   cd guest
34   v3_create -b guest.pal name_of_guest
35
36 Any files (disk images) that your guest configuration depends on
37 must be accessible when v3_create is run.  
38
39 Once the VM is instantiated, you can then launch it:
40
41   v3_launch /dev/v3-vmN  (N is given by the v3_create command)
42
43 We will configure your guest via a sequence of questions.
44
45 END
46 ;
47
48 $pdir = $ENV{PALACIOS_DIR};
49 $qdir = $ENV{PALACIOS_QEMU_DIR};
50
51 $haveqemu = defined($qdir);
52
53 if (!defined($pdir)) { 
54   print "Please set PALACIOS_DIR (you probably have not sourced ENV) and try again\n";
55   exit -1;
56 }
57
58 $otherbios = get_palacios_core_feature($pdir,"V3_CONFIG_OTHERBIOS");
59 $otherbios = !defined($otherbios) ? 0 : $otherbios eq "y" ? 1: 0;
60 if ($otherbios) {
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; }
64 }
65
66
67 $name = "myguest";
68 print "What is the name of your guest? [$name] : ";
69 $name = get_user($name);
70
71 $dir = "./$name";
72 print "What is the directory into which we will put your guest? [$dir] : ";
73 $dir = get_user($dir);
74 if (!mkdir($dir)) { 
75   print "Unable to create the directory\n";
76   exit -1;
77 }
78
79 $config{numcores} = quant_question("How many cores will your guest have?", 1);
80
81 $config{mem} = quant_question("How much memory should it have in MB?", 256);
82
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);
87   }
88 }
89
90 do_swapping(\%config, $pdir);
91
92
93 print "We will give your guest the default performance tuning characteristics\n";
94 $config{perftune_block} .= <<PERFTUNE
95   <group name="yield">
96    <strategy>friendly</strategy>
97    <threshold>1000</threshold>
98    <time>1000</time>
99   </group>
100 PERFTUNE
101 ;
102
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";
105
106
107 $config{telemetry} = yn_question("Do you want telemetry (information about guest exits) ?", "y", "enable", "disable");
108
109
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");
111
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");
113
114 print "We will give your guest the default shadow paging strategy for when shadow paging is used.\n";
115 $config{shadow_strategy} = "VTLB";
116
117
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";
120
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";
124 }
125
126
127 do_bioses(\%config, $pdir, $dir);
128
129
130 #
131 # Basic debugging
132 #
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");
135
136 #
137 # Interrupt control
138 #
139 #
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") { 
145     goto intr_done;
146   }
147 }
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"); 
150
151
152 #
153 # PCI buses and north/south bridge - all must haves
154 #
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
158
159 #
160 # MPTABLE for legacy BIOS.  Innocuous for SEABIOS or OTHERBIOS
161 #
162 #
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");
166 } else {
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") { 
172       exit -1;
173     }
174   }
175 }
176
177
178
179 # Legacy timer
180 #
181 do_device(\%config, $pdir, "V3_CONFIG_PIT", "8254_PIT", "PIT",1); # must have
182
183
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);
189   }
190 }
191
192 if (!defined($config{qemu_ui})) { 
193   #
194   # Keyboard and mouse (PS/2 controller)
195   #
196   do_device(\%config, $pdir, "V3_CONFIG_KEYBOARD", "KEYBOARD", "keyboard",1); #must have
197
198   #
199   # Displays, Consoles, Serial
200   #
201   print "\nWe will now consider consoles and serial ports.\n\n";
202   do_consoles_and_ports(\%config, $pdir);
203   
204 }
205
206
207 #
208 # Storage controllers and devices (attached to PCI bus)
209 #
210 #
211 print "\nWe will now consider storage controllers and devices.\n\n";
212 do_storage(\%config, $pdir, $dir, $name, "pci0", "southbridge");
213
214
215
216
217 #
218 # Network interfaces (attached to PCI bus)
219 #
220 #
221 print "\nWe will now consider network interfaces.\n\n";
222 do_network(\%config, $pdir, $dir, $name, "pci0", "southbridge");
223
224
225 #
226 # Sanity-check - is there something bootable?
227 #
228 #
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";
235   } else {
236     print "The guest does have a NIC, so a network boot is possible, if the\n";
237     print "BIOS supports it.\n";
238   }
239   print "If this is not your intent, you probably want to CTRL-C and try again.\n";
240 }
241
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";
244
245 #
246 # NVRAM 
247 #
248 # Note: do_storage *must* have placed an IDE named ide0 in order for this to work
249 #
250 do_device(\%config, $pdir, "V3_CONFIG_NVRAM", "NVRAM", "nvram", 1, undef, "     <storage>ide0</storage>\n     <bootseq>cd,hd</bootseq>\n"); #must have
251
252 #
253 #
254 # Generic Catch-all Device
255 #
256 do_generic(\%config, $pdir);
257
258
259 open(PAL,">$dir/$name.pal") or die "Cannot open $dir/$name.pal\n";
260
261 $target = PAL;
262
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";
278
279 close(PAL);
280
281 print Dumper(\%config);
282
283 if (defined($config{qemu}) && $config{qemu} eq "y") {
284   gen_qemu_startup(\%config, $pdir, $dir);
285 }
286
287 print "\n\nYour guest is now ready in the directory $dir\n\n";
288 print "To run it, do:\n\n";
289 print "  cd $dir\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";
295
296 exit;
297
298
299 sub quant_question {
300   my ($ques, $default) = @_;
301
302   print $ques." [$default] : ";
303   
304   return get_user($default);
305 }
306
307 sub yn_question {
308   my ($ques, $default, $yans, $nans) = @_;
309   
310   my $ans;
311   
312   print $ques." [$default] : ";
313   $ans = get_user($default);
314   
315   if (substr($ans,0,1) eq 'y' || substr($ans,0,1) eq 'Y') { 
316     return $yans;
317   } else {
318     return $nans;
319   }
320 }
321
322 sub do_numa_config {
323   my ($cr, $pdir) =@_;
324   my %numa;
325   my $numpnodes;
326   my $numpcores;
327   my $numvnodes;
328   my $numvcores;
329   my $memblock="";
330   my $pernode;
331   my $lastnode;
332   my $i;
333   my @vnodemap;
334   my @vcoremap;
335   my $canauto=1;
336
337   %numa = get_numa_data();
338
339   $numvcores = $cr->{numcores};
340
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});
354   do {
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};
371   }
372   my $doauto=0;
373   if ($canauto) { 
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");
378   } else {
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";
381     $doauto=0;
382   }
383   if ($doauto) { 
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;
393     }
394   } else {
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;
405     }
406   }
407   $cr->{numa}=1;
408 }
409
410
411 sub get_numa_data() {
412   my $line;
413   my $maxnode=0;
414   my $maxcpu=0;
415   my %numa;
416
417   open (N, "numactl --hardware |");
418   while ($line=<N>) { 
419     if ($line=~/^node\s+(\d+)\s+cpus:\s+(.*)$/) { 
420       my $node=$1;
421       my @cpus = split(/\s+/,$2);
422       my $cpu;
423       if ($node>$maxnode) { $maxnode=$node; }
424       foreach $cpu (@cpus) { 
425         if ($cpu>$maxcpu) { $maxcpu=$cpu; }
426       }
427       $numa{"node$node"}{cores}=\@cpus;
428     }
429   }
430   $numa{numnodes}=$maxnode+1;
431   $numa{numcores}=$maxcpu+1;
432   return %numa;
433 }
434
435
436 sub do_swapping {
437   my ($cr, $pdir) = @_;
438
439   my $canswap = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_SWAPPING");
440   my $mem = $cr->{mem};
441
442   if ($canswap) { 
443     #Config for swapping
444     $cr->{swapping} = yn_question("Do you want to use swapping?", "n", "y", "n");
445
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");
452     }
453   }
454 }
455
456 sub add_bios   {
457   my ($cr, $name, $fileid, $address) =@_;
458
459   push @{$cr->{bios_list}},  { name=>$name, fileid=>$fileid, address=>$address };
460   
461 }
462
463 sub do_bios {
464   my ($cr, $pdir, $dir) = @_;
465   my $nextbios = defined($cr->{bios_list}) ? "bios".($#{$cr->{bios_list}}+1) : "bios0";
466   
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);
471     while (1) { 
472       print "Where is the path to the file for bios $n ? ";
473       $fn = get_user("");
474       if (!(-e $fn)) { 
475         print "Cannot find $fn, try again\n";
476         next;
477       } else {
478         if (system("cp $fn $dir/$n.dat")) { 
479           print "Unable to copy $fn\n";
480           next;
481         } else {
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);
486           return 1;
487         }
488       }
489     }
490   } else {
491     return 0;
492   }
493 }
494
495 sub do_bioses { 
496   my ($cr, $pdir, $dir) = @_;
497
498   $cr->{bios_custom} = yn_question("Do you want to customize BIOSes?   (done automatically later for QEMU devices) ", "n", "y", "n");
499
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");
503     
504     while (do_bios($cr, $pdir, $dir)) {}
505   }
506 }
507       
508     
509                                             
510
511 sub do_device {
512   my ($cr,$pdir,$feature, $class, $id, $hardfail, $optblob, $nestblob) =@_;
513
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);
517   } else {
518     if (defined($hardfail) && $hardfail) { 
519       print "Wow, your Palacios build doesn't have a $class... We can't live without that...\n";
520       exit -1;
521     } else {
522       print "Not configuring a $class since your Palacios build doesn't have it enabled\n";
523     }
524   }
525 }
526
527 sub add_qemu_device {
528   my ($cr, $pdir, $type, $name, $url) = @_;
529
530   $cr->{qemu}='y';
531   
532   push @{$cr->{qemu_devices}}, { type=>$type, name=>$name, url=>$url } ;
533
534 }
535
536 sub do_qemu_ui {
537   my ($cr, $pdir, $dir) = @_;
538   my $vgabios=$ENV{PALACIOS_QEMU_DIR}."/share/qemu/vgabios-cirrus.bin";
539
540   $cr->{qemu_ui}='y';
541   
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");
549
550   # so is serial
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");
558
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");
565
566   add_device($cr, "PCI_FRONT", "qemu-video",
567              " hostdev=\"user:qemu-video\" ",
568              "    <bus>pci0</bus>\n");
569
570   add_qemu_device($cr,$pdir, "qemu-video", "qemu-video", "user:qemu-video");
571
572   print "To use QEMU video, we will need to add the relevant bios. \n";
573   while (1) { 
574     print "Where is the QEMU video bios ? [$vgabios] : ";
575     $vgabios = get_user($vgabios); 
576     if (-e $vgabios) { 
577       if (system("cp $vgabios $dir/qemu-videobios.dat")) { 
578         print "Cannot copy $vgabios, try again\n";
579         next;
580       } else {
581         last;
582         }
583     } else {
584       print "Cannot find $vgabios, try again\n";
585       next;
586     } 
587   }
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';
592
593 }
594
595 sub do_consoles_and_ports {
596   my ($cr, $pdir) = @_;
597
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;
613
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";
622   
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";
626   }
627   
628   $didcga=0;
629   if ($cancga) { 
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");
636       $didcga=1;
637     }
638   }
639   
640   $didvga=0;
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
646       $didvga=1;
647     }
648   }
649   
650   $didserial=0;
651   if ($canserial) {
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");
662       $didserial=1;
663     }
664   }
665   
666   
667   $didvirtioconsole=0;
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";
673       $didvirtioconsole=1;
674     }
675   }
676   
677   $didparagraph=0;
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");
684       $didparagraph=1;
685     }
686   }
687   
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";
691   } 
692
693
694
695
696 sub do_network {
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"); 
705   my @devs;
706   my @backends;
707   my $front;
708   my $back;
709   my $num;
710   my @test;
711   my $mac;
712
713   push @devs, "virtio" if $canvirtio;
714   push @devs, "rtl8139" if $canrtl8139;
715   push @devs, "ne2000" if $canne2k;
716
717   push @backends, "bridge" if $canbridge;
718   push @backends, "vnet" if $canoverlay;
719
720   if ($#devs==-1) { 
721     print "You have no network device implementations enabled in your Palacios build, so we are skipping networking\n";
722     return -1;
723   }
724   
725   if ($#backends==-1) { 
726     print "You have no network device backends enabled in your Palacios build, so we are skipping networking\n";
727     return -1;
728   }
729
730
731   $num=0;
732   while (1) { 
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;
742     if ($#test!=0) { 
743       print "Unknown frontend\n"; 
744       next;
745     }
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;
752     if ($#test!=0) { 
753       print "Unknown backend\n"; 
754       next;
755     }
756     $mac=gen_macaddr();
757     print "What MAC address do you want your NIC to have? [$mac] : ";
758     $mac=get_user($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";
765     }
766     if ($front eq "rtl8139") {
767        add_device($cr,"RTL8139","net$num",undef,
768                   "    <bus>$pcibus</bus>\n".
769                   "    <mac>$mac</mac>\n");
770     }
771     if ($front eq "ne2000") {
772        add_device($cr,"NE2000","net$num",undef,
773                   "    <bus>$pcibus</bus>\n".
774                   "    <mac>$mac</mac>\n");
775     }
776
777     if ($back eq "bridge") { 
778        my $host;
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");
784     }
785
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";
790     }
791     $num++;
792   }
793
794   if ($num>0) { 
795     $cr->{havenic}=1;
796   }
797  }
798
799
800 sub gen_macaddr {
801   return sprintf("%02X:%02X:%02X:%02X:%02X:%02X",
802                  int(rand(256)),
803                  int(rand(256)),
804                  int(rand(256)),
805                  int(rand(256)),
806                  int(rand(256)),
807                  int(rand(256)));
808 }
809                                                  
810
811 sub do_storage {
812   my ($cr,$pdir,$dir,$name,$pcibus,$controller)=@_;
813
814   # 
815   # IDE controller
816   #
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");
833   
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");
837     my $i;
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", "");
841     }
842   }
843
844 }      
845
846
847
848 sub do_storage_backend {
849   my ($cr, $pdir, $dir, $name, $frontend, $loc, $frontendblock) = @_;
850   my ($canramdisk, $canfiledisk, $cannetdisk, $cantmpdisk);
851   my @devs=("cd","hd","nothing");
852   my @disks;
853   my $type;
854   my @type;
855   my $file;
856   my $size;
857
858   $canramdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_RAMDISK");
859   $canfiledisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_FILEDISK");
860   $cannetdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_NETDISK");
861   $cantmpdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_TMPDISK");
862   push @disks, "ramdisk" if $canramdisk;
863   push @disks, "filedisk" if $canramdisk;
864   push @disks, "netdisk" if $cannetdisk;
865   push @disks, "tmpdisk" if $cantmpdisk;
866
867
868   if (!$canramdisk && !$canfiledisk && !$cannetdisk && !$cantmpdisk) {
869     print "You have no storage implementations enabled in your Palacios build, so it is impossible\n";
870     print "to add anything to storage controller \"$frontend\" location \"$loc\"\n";
871     return -1;
872   }
873    
874
875   while (1) { 
876     print "What do you want to attach to storage controller \"$frontend\" location \"$loc\"\n";
877     print "  Your options are {".join(", ",@devs)."} [nothing] : ";
878     $what = get_user("nothing");
879     @test = grep { /^$what$/ } @devs;
880     next if $#test!=0;
881     if ($what eq "nothing") {
882       return;
883     }
884     print "A storage device requires one of the following implementations\n";
885     print "  * RAMDISK - the data is kept in memory (common) : ".($canramdisk ? "available" : "UNAVAILABLE")."\n";
886     print "  * FILEDISK - the data is kept in a host file (common) : ".($canfiledisk ? "available" : "UNAVAILABLE")."\n";
887     print "  * NETDISK - the data is accessed via the network (uncommon) : ".($cannetdisk ? "available" : "UNAVAILABLE")."\n";
888     print "  * TMPDISK - the data is kept in memory and discarded (common) : ".($cantmpdisk ? "available" : "UNAVAILABLE")."\n";
889     while (1) {
890       print "Which option do you want for this device? {".join(", ",@disks)."} [] : ";
891       $type = get_user("");
892       my @test = grep {/^$type$/} @disks;
893       last if $#test==0;
894     }
895
896     if ($type eq "filedisk" || $type eq "ramdisk") { 
897       print "$type requires a file (.iso for example).  Do you have one? [y] : ";
898       if (get_user("y") eq "y") { 
899         while (1) { 
900           print "What is its path? [] : ";
901           $file = get_user("");
902           if (!(-e $file)) {
903             print "$file does not exist\n";
904             next;
905           }
906           if (system("cp $file $dir/$frontend\_$loc.dat")) { 
907             print "Unable to copy $file\n";
908             next;
909           }
910           last;
911         }
912       } else {
913         print "We will make one.  How big should it be in MB? [64] : ";
914         $size = get_user("64");
915         gen_image_file("$dir/$frontend\_$loc.dat",$size);
916       }
917       $attach="    <frontend tag=\"$frontend\">\n";
918       if ($what eq "cd") { 
919         $attach.="     <model>V3VEE CDROM</model>\n".
920                  "     <type>CDROM</type>\n".$frontendblock;
921         $cr->{havecd}=1;
922       } else {
923         $attach.="     <model>V3VEE HD</model>\n".
924                  "     <type>HD</type>\n".$frontendblock;
925         $cr->{havehd}=1;
926       }
927       $attach.="    </frontend>\n";
928
929       if ($type eq "ramdisk") { 
930         add_device($cr,"RAMDISK","$frontend\_$loc", undef, 
931                    "    <file>$frontend\_$loc</file>\n".$attach);
932         add_file($cr, "$frontend\_$loc", "$frontend\_$loc.dat");
933       } else {
934         add_device($cr,"FILEDISK","$frontend\_$loc", $what eq "hd" ? "writable=\"1\"" : undef, 
935                    "    <path>$frontend\_$loc.dat</path>\n".$attach);
936       }
937       last;
938     } else {
939       print "$type is not currently supported\n";
940       next;
941     }
942   }
943 }
944
945
946 sub do_generic {
947   my ($cr, $pdir)=@_;
948
949   $block = <<GENERIC1
950     <ports> 
951       <!-- DMA 1 registers -->
952       <start>0x00</start>
953       <end>0x07</end>
954       <mode>PRINT_AND_IGNORE</mode>
955     </ports>
956     <ports>
957       <!-- DMA 2 registers -->
958       <start>0xc0</start>
959       <end>0xc7</end>
960       <mode>PRINT_AND_IGNORE</mode>
961     </ports>
962     <ports>
963      <!-- DMA 1 page registers -->
964      <start>0x81</start>
965      <end>0x87</end>
966      <mode>PRINT_AND_IGNORE</mode>
967     </ports>
968     <ports>
969      <!-- DMA 2 page registers -->
970      <start>0x88</start>
971      <end>0x8f</end>
972      <mode>PRINT_AND_IGNORE</mode>
973     </ports>
974     <ports>
975       <!-- DMA 1 Misc Registers -->
976       <start>0x08</start>
977       <end>0x0f</end>
978       <mode>PRINT_AND_IGNORE</mode>
979     </ports>
980     <ports>
981      <!-- DMA 2 Misc Registers -->
982      <start>0xd0</start>
983      <end>0xde</end>
984      <mode>PRINT_AND_IGNORE</mode>
985     </ports>
986     <ports>
987      <!-- ISA PNP -->
988      <start>0x274</start>
989      <end>0x277</end>
990      <mode>PRINT_AND_IGNORE</mode>
991     </ports>
992     <ports>
993      <!-- ISA PNP -->
994      <start>0x279</start>
995      <end>0x279</end>
996      <mode>PRINT_AND_IGNORE</mode>
997     </ports>
998     <ports>
999      <!-- ISA PNP -->
1000      <start>0xa79</start>
1001      <end>0xa79</end>
1002      <mode>PRINT_AND_IGNORE</mode>
1003     </ports>
1004 GENERIC1
1005 ;
1006   my @dev = find_devices_by_class($cr,"PARALLEL");
1007   if ($#dev<0) { 
1008     $block .= <<GENERIC2
1009     <ports>
1010      <!-- Parallel Port -->
1011      <start>0x378</start>
1012      <end>0x37f</end>
1013      <mode>PRINT_AND_IGNORE</mode>
1014     </ports>
1015 GENERIC2
1016 ;
1017   }
1018   my @par = find_devices_by_class($cr,"SERIAL");
1019   if ($#par<0 && !defined($cr->{qemu_ui})) {
1020     $block .=<<GENERIC3
1021     <ports>
1022      <!-- Serial COM 1 -->
1023      <start>0x3f8</start>
1024      <end>0x3ff</end>
1025      <mode>PRINT_AND_IGNORE</mode>
1026     </ports>
1027     <ports>
1028      <!-- Serial COM 2 -->
1029      <start>0x2f8</start>
1030      <end>0x2ff</end>
1031      <mode>PRINT_AND_IGNORE</mode>
1032     </ports>
1033     <ports>
1034      <!-- Serial COM 3 -->
1035      <start>0x3e8</start>
1036      <end>0x3ef</end>
1037      <mode>PRINT_AND_IGNORE</mode>
1038     </ports>
1039     <ports>
1040     <!-- Serial COM 4 -->
1041      <start>0x2e8</start>
1042      <end>0x2ef</end>
1043      <mode>PRINT_AND_IGNORE</mode>
1044     </ports>
1045 GENERIC3
1046 ;
1047   }
1048
1049   do_device($cr, $pdir, "V3_CONFIG_GENERIC", "GENERIC", "generic", 1, undef, $block);
1050 }
1051
1052 sub add_file {
1053   my ($cr, $name, $file) = @_;
1054   
1055   push @{$cr->{files}}, { name=>$name, file=>$file};
1056
1057 }
1058
1059 sub add_device {
1060   my ($cr, $class, $id, $optblob, $nestblob) = @_;
1061
1062   push @{$cr->{devices}}, { class=>$class, id=>$id, opt=>$optblob, nest=>$nestblob };
1063 }
1064
1065 sub find_devices_by_class {
1066   my ($cr,$c)=@_;
1067   return grep { $_->{class} eq $c } @{$cr->{devices}};
1068 }
1069
1070 sub numa_setup {
1071   my $cr =shift;
1072   my $vnode;
1073   my $s="";
1074
1075   if (!defined($cr->{numa})) { 
1076     return "";
1077   } else {
1078     $s.=" <mem_layout vnodes=\"".($#{$cr->{nodes}}+1)."\" >\n";
1079     foreach $vnode (@{$cr->{nodes}}) {
1080       $s.="   <region start_addr=\"".$vnode->{start}."\" end_addr=\"".$vnode->{end}."\" vnode=\"".$vnode->{vnode}."\" node=\"".$vnode->{pnode}."\" />\n";
1081     }
1082     $s.=" </mem_layout>\n";
1083     return $s;
1084   }
1085 }
1086
1087 sub core_setup  {
1088   my $cr = shift;
1089   my $i;
1090   my $s="";
1091   
1092   
1093   $s.= " <cores count=\"".$cr->{numcores}."\">\n";
1094   if (!defined($cr->{numa})) { 
1095     $s.= "  <core />\n";
1096   } else {
1097     for ($i=0;$i<$cr->{numcores};$i++) { 
1098       $s.= "  <core target_cpu=\"".$cr->{"core$i"}{pcore}."\" vnode=\"".$cr->{"core$i"}{vnode}."\" />\n";
1099     }
1100   }
1101   $s.= " </cores>\n";
1102   
1103   return $s;
1104 }
1105
1106 sub memory_setup
1107 {
1108   my $cr=shift;
1109
1110   return " <memory>".$cr->{mem}."</memory>\n";
1111 }
1112
1113 sub paging_setup  {
1114   my $cr = shift;
1115   my $s="";
1116   
1117   $s.= " <paging mode=\"".$cr->{paging_mode}."\">\n";
1118   $s.= "  <large_pages>".$cr->{large_pages}."</large_pages>\n";
1119   $s.= "  <strategy>".$cr->{shadow_strategy}."</strategy>\n";
1120   $s.= " </paging>\n";
1121   
1122   return $s;
1123 }
1124
1125 sub memmap_setup {
1126   my $cr = shift;
1127
1128   return $cr->{memmap_block};
1129 }
1130
1131 sub schedule_setup {
1132   my $cr = shift;
1133
1134   return $cr->{schedule_hz_block};
1135 }
1136
1137
1138 sub perftune_setup  {
1139   my $cr=shift;
1140   my $s="";
1141   if (defined($cr->{perftune_block})) { 
1142     $s.=" <perftune>\n";
1143     $s.= $cr->{perftune_block};
1144     $s.=" </perftune>\n";
1145   }
1146   return $s;
1147 }
1148
1149 sub extensions_setup  {
1150   my $cr=shift;
1151   my $s="";
1152   if (defined($cr->{extensions_block})) { 
1153     $s.=" <extensions>\n";
1154     $s.= $cr->{extensions_block};
1155     $s.=" </extensions>\n";
1156   }
1157   return $s;
1158 }
1159
1160 sub swapping_setup {
1161   my $cr=shift;
1162   if (defined($cr->{swapping}) && $cr->{swapping} eq "y") { 
1163     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";
1164   } else {
1165     return " <!-- there is no swapping configuration, but you can add one manually -->\n";
1166   }
1167 }
1168 sub telemetry_setup  {
1169   my $cr=shift;
1170   return " <telemetry>".$cr->{telemetry}."</telemetry>\n";
1171 }
1172
1173 sub file_setup { 
1174   my $cr=shift;
1175   my $cf;
1176   my $s="";
1177
1178   if (!defined($cr->{files})) { 
1179     return " <!-- this configuration contains no files -->\n";
1180   } else {
1181
1182     $s.=" <files>\n";
1183    
1184     foreach $cf (@{$cr->{files}}) {
1185       $s.="   <file id=\"".$cf->{name}."\" filename=\"".$cf->{file}."\" />\n";
1186     }
1187     $s.=" </files>\n";
1188     return $s;
1189   }
1190 }
1191
1192 sub bios_setup {
1193   my $cr=shift;
1194   
1195   if (!defined($cr->{bios_custom}) || $cr->{bios_custom} eq "n") { 
1196     return " <!-- this configuration does not use a custom bios setup but you can add one with the <bioses> syntax-->\n";
1197   } else {
1198     my $s;
1199     my $b;
1200     $s = " <bioses>\n";
1201     $s.= "  <disable_rombios/>\n" if defined($cr->{bios_custom_nobios}) && $cr->{bios_custom_nobios} eq "y";
1202     $s.= "  <disable_vgabios/>\n" if defined($cr->{bios_custom_novgabios}) && $cr->{bios_custom_novgabios} eq "y";
1203     foreach $b (@{$cr->{bios_list}}) { 
1204       $s.= "  <bios file=\"".$b->{fileid}."\" address=\"".$b->{address}."\" />\n";
1205     }
1206     $s.= " </bioses>\n";
1207     return $s;
1208   }
1209 }
1210
1211 sub device_setup { 
1212   my $cr=shift;
1213   my $cd;
1214   my $s="";
1215
1216   $s.=" <devices>\n";
1217
1218   foreach $cd (@{$cr->{devices}}) {
1219     $s.="   <device class=\"".$cd->{class}."\" id=\"".$cd->{id}."\"";
1220     if (defined($cd->{opt})) { 
1221       $s.=" ".$cd->{opt};
1222     }
1223     if (!defined($cd->{nest})) { 
1224       $s.=" />\n";
1225     } else {
1226       $s.=" >\n";
1227       $s.=$cd->{nest};
1228       $s.="   </device>\n";
1229     }
1230   }
1231
1232   $s.=" </devices>\n";
1233
1234   return $s;
1235
1236 }
1237
1238
1239
1240 sub get_user {
1241   my $def = shift;
1242   
1243   my $inp = <STDIN>; chomp($inp);
1244   
1245   if ($inp eq "") { 
1246     return $def;
1247   } else {
1248     return $inp;
1249   }
1250 }
1251
1252 sub get_kernel_feature {
1253   my $dir=shift;
1254   my $feature=shift;
1255   my $x;
1256
1257   $x=`grep $feature= $dir/config-\`uname -r\``;
1258
1259   if ($x=~/^\s*\#/) {
1260     return undef;
1261   } else {
1262     if ($x=~/\s*$feature=\s*(\S*)\s*$/) {
1263       return $1;
1264     } else {
1265       return undef;
1266     }
1267   }
1268 }
1269   
1270 sub get_palacios_core_feature {
1271   my $dir=shift;
1272   my $feature=shift;
1273   my $x;
1274
1275   $x=`grep $feature= $dir/.config`;
1276
1277   if ($x=~/^\s*\#/) {
1278     return undef;
1279   } else {
1280     if ($x=~/\s*$feature=\s*(\S*)\s*$/) {
1281       return $1;
1282     } else {
1283       return undef;
1284     }
1285   }
1286 }
1287
1288 sub is_palacios_core_feature_enabled {
1289   my $out = get_palacios_core_feature(@_);
1290   return !defined($out) ? 0 : $out eq "y";
1291 }
1292
1293
1294 sub powerof2  {
1295   my $x = shift;
1296   my $exp;
1297   
1298   $exp = log($x) /log(2);
1299
1300   return $exp==int($exp);
1301 }
1302
1303
1304 sub gen_image_file {
1305   my ($name, $size_mb) = @_;
1306
1307   if (system("dd if=/dev/zero of=$name bs=1048576 count=$size_mb")) { 
1308     return -1;
1309   } else  {
1310     return 0;
1311   }
1312 }
1313
1314
1315 sub gen_qemu_startup {
1316   my ($cr, $pdir, $dir) = @_;
1317   my $d;
1318
1319   # FIX ME
1320   print "Generating QEMU Startup Script\n";
1321
1322   open(Q,">$dir/qemu_startup.sh");
1323   print Q $ENV{PALACIOS_QEMU_DIR}."/bin/qemu-system-x86_64 -m 2048 -accel pal  ";
1324   foreach $d (@{$cr->{qemu_devices}}) { 
1325     if ($d->{type} eq "qemu-ps2") { 
1326       print Q " -map KBD ".$d->{url}." ";
1327     } elsif ($d->{type} eq "qemu-serial") { 
1328       print Q " -serial stdio -map SERIAL ".$d->{url}." ";
1329     } elsif ($d->{type} eq "qemu-video-legacy") { 
1330       print Q " -map VGA ".$d->{url}." ";
1331     } elsif ($d->{type} eq "qemu-video") { 
1332       print Q " -vga cirrus -map CIRRUS ".$d->{url}." ";
1333     } elsif ($d->{type} eq "qemu-e1000") { 
1334       print Q " -nic e1000 -map E1000 ".$d->{url}." ";
1335     } elsif ($d->{type} eq "qemu-ide-legacy") { 
1336       print Q " -ide ... -map IDE-LEGACY ".$d->{url}." ";
1337     } elsif ($d->{type} eq "qemu-ide") { 
1338       print Q " -ide ... -map IDE ".$d->{url}." ";
1339     } else {
1340       die "Do not know how to handle QEMU device of type ".$d->{type}."\n";
1341     }
1342   }
1343
1344   print Q "\n";
1345
1346   close(Q);
1347 }