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.


pci_front bugfix - do not propagate cmd reg write twice
[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, $canqcowdisk);
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   $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;
868
869
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";
873     return -1;
874   }
875    
876
877   while (1) { 
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;
882     next if $#test!=0;
883     if ($what eq "nothing") {
884       return;
885     }
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";
892     while (1) {
893       print "Which option do you want for this device? {".join(", ",@disks)."} [] : ";
894       $type = get_user("");
895       my @test = grep {/^$type$/} @disks;
896       last if $#test==0;
897     }
898
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") { 
902         while (1) { 
903           print "What is its path? [] : ";
904           $file = get_user("");
905           if (!(-e $file)) {
906             print "$file does not exist\n";
907             next;
908           }
909           if (system("cp $file $dir/$frontend\_$loc.dat")) { 
910             print "Unable to copy $file\n";
911             next;
912           }
913           last;
914         }
915       } else {
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);
919       }
920       $attach="    <frontend tag=\"$frontend\">\n";
921       if ($what eq "cd") { 
922         $attach.="     <model>V3VEE CDROM</model>\n".
923                  "     <type>CDROM</type>\n".$frontendblock;
924         $cr->{havecd}=1;
925       } else {
926         $attach.="     <model>V3VEE HD</model>\n".
927                  "     <type>HD</type>\n".$frontendblock;
928         $cr->{havehd}=1;
929       }
930       $attach.="    </frontend>\n";
931
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);
939       } else {
940         add_device($cr,"QCOWDISK","$frontend\_$loc", $what eq "hd" ? "writable=\"1\"" : undef, 
941                    "    <path>$frontend\_$loc.dat</path>\n".$attach);
942       }
943       last;
944     } else {
945       print "$type is not currently supported\n";
946       next;
947     }
948   }
949 }
950
951
952 sub do_generic {
953   my ($cr, $pdir)=@_;
954
955   $block = <<GENERIC1
956     <ports> 
957       <!-- DMA 1 registers -->
958       <start>0x00</start>
959       <end>0x07</end>
960       <mode>PRINT_AND_IGNORE</mode>
961     </ports>
962     <ports>
963       <!-- DMA 2 registers -->
964       <start>0xc0</start>
965       <end>0xc7</end>
966       <mode>PRINT_AND_IGNORE</mode>
967     </ports>
968     <ports>
969      <!-- DMA 1 page registers -->
970      <start>0x81</start>
971      <end>0x87</end>
972      <mode>PRINT_AND_IGNORE</mode>
973     </ports>
974     <ports>
975      <!-- DMA 2 page registers -->
976      <start>0x88</start>
977      <end>0x8f</end>
978      <mode>PRINT_AND_IGNORE</mode>
979     </ports>
980     <ports>
981       <!-- DMA 1 Misc Registers -->
982       <start>0x08</start>
983       <end>0x0f</end>
984       <mode>PRINT_AND_IGNORE</mode>
985     </ports>
986     <ports>
987      <!-- DMA 2 Misc Registers -->
988      <start>0xd0</start>
989      <end>0xde</end>
990      <mode>PRINT_AND_IGNORE</mode>
991     </ports>
992     <ports>
993      <!-- ISA PNP -->
994      <start>0x274</start>
995      <end>0x277</end>
996      <mode>PRINT_AND_IGNORE</mode>
997     </ports>
998     <ports>
999      <!-- ISA PNP -->
1000      <start>0x279</start>
1001      <end>0x279</end>
1002      <mode>PRINT_AND_IGNORE</mode>
1003     </ports>
1004     <ports>
1005      <!-- ISA PNP -->
1006      <start>0xa79</start>
1007      <end>0xa79</end>
1008      <mode>PRINT_AND_IGNORE</mode>
1009     </ports>
1010 GENERIC1
1011 ;
1012   my @dev = find_devices_by_class($cr,"PARALLEL");
1013   if ($#dev<0) { 
1014     $block .= <<GENERIC2
1015     <ports>
1016      <!-- Parallel Port -->
1017      <start>0x378</start>
1018      <end>0x37f</end>
1019      <mode>PRINT_AND_IGNORE</mode>
1020     </ports>
1021 GENERIC2
1022 ;
1023   }
1024   my @par = find_devices_by_class($cr,"SERIAL");
1025   if ($#par<0 && !defined($cr->{qemu_ui})) {
1026     $block .=<<GENERIC3
1027     <ports>
1028      <!-- Serial COM 1 -->
1029      <start>0x3f8</start>
1030      <end>0x3ff</end>
1031      <mode>PRINT_AND_IGNORE</mode>
1032     </ports>
1033     <ports>
1034      <!-- Serial COM 2 -->
1035      <start>0x2f8</start>
1036      <end>0x2ff</end>
1037      <mode>PRINT_AND_IGNORE</mode>
1038     </ports>
1039     <ports>
1040      <!-- Serial COM 3 -->
1041      <start>0x3e8</start>
1042      <end>0x3ef</end>
1043      <mode>PRINT_AND_IGNORE</mode>
1044     </ports>
1045     <ports>
1046     <!-- Serial COM 4 -->
1047      <start>0x2e8</start>
1048      <end>0x2ef</end>
1049      <mode>PRINT_AND_IGNORE</mode>
1050     </ports>
1051 GENERIC3
1052 ;
1053   }
1054
1055   do_device($cr, $pdir, "V3_CONFIG_GENERIC", "GENERIC", "generic", 1, undef, $block);
1056 }
1057
1058 sub add_file {
1059   my ($cr, $name, $file) = @_;
1060   
1061   push @{$cr->{files}}, { name=>$name, file=>$file};
1062
1063 }
1064
1065 sub add_device {
1066   my ($cr, $class, $id, $optblob, $nestblob) = @_;
1067
1068   push @{$cr->{devices}}, { class=>$class, id=>$id, opt=>$optblob, nest=>$nestblob };
1069 }
1070
1071 sub find_devices_by_class {
1072   my ($cr,$c)=@_;
1073   return grep { $_->{class} eq $c } @{$cr->{devices}};
1074 }
1075
1076 sub numa_setup {
1077   my $cr =shift;
1078   my $vnode;
1079   my $s="";
1080
1081   if (!defined($cr->{numa})) { 
1082     return "";
1083   } else {
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";
1087     }
1088     $s.=" </mem_layout>\n";
1089     return $s;
1090   }
1091 }
1092
1093 sub core_setup  {
1094   my $cr = shift;
1095   my $i;
1096   my $s="";
1097   
1098   
1099   $s.= " <cores count=\"".$cr->{numcores}."\">\n";
1100   if (!defined($cr->{numa})) { 
1101     $s.= "  <core />\n";
1102   } else {
1103     for ($i=0;$i<$cr->{numcores};$i++) { 
1104       $s.= "  <core target_cpu=\"".$cr->{"core$i"}{pcore}."\" vnode=\"".$cr->{"core$i"}{vnode}."\" />\n";
1105     }
1106   }
1107   $s.= " </cores>\n";
1108   
1109   return $s;
1110 }
1111
1112 sub memory_setup
1113 {
1114   my $cr=shift;
1115
1116   return " <memory>".$cr->{mem}."</memory>\n";
1117 }
1118
1119 sub paging_setup  {
1120   my $cr = shift;
1121   my $s="";
1122   
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";
1127   
1128   return $s;
1129 }
1130
1131 sub memmap_setup {
1132   my $cr = shift;
1133
1134   return $cr->{memmap_block};
1135 }
1136
1137 sub schedule_setup {
1138   my $cr = shift;
1139
1140   return $cr->{schedule_hz_block};
1141 }
1142
1143
1144 sub perftune_setup  {
1145   my $cr=shift;
1146   my $s="";
1147   if (defined($cr->{perftune_block})) { 
1148     $s.=" <perftune>\n";
1149     $s.= $cr->{perftune_block};
1150     $s.=" </perftune>\n";
1151   }
1152   return $s;
1153 }
1154
1155 sub extensions_setup  {
1156   my $cr=shift;
1157   my $s="";
1158   if (defined($cr->{extensions_block})) { 
1159     $s.=" <extensions>\n";
1160     $s.= $cr->{extensions_block};
1161     $s.=" </extensions>\n";
1162   }
1163   return $s;
1164 }
1165
1166 sub swapping_setup {
1167   my $cr=shift;
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";
1170   } else {
1171     return " <!-- there is no swapping configuration, but you can add one manually -->\n";
1172   }
1173 }
1174 sub telemetry_setup  {
1175   my $cr=shift;
1176   return " <telemetry>".$cr->{telemetry}."</telemetry>\n";
1177 }
1178
1179 sub file_setup { 
1180   my $cr=shift;
1181   my $cf;
1182   my $s="";
1183
1184   if (!defined($cr->{files})) { 
1185     return " <!-- this configuration contains no files -->\n";
1186   } else {
1187
1188     $s.=" <files>\n";
1189    
1190     foreach $cf (@{$cr->{files}}) {
1191       $s.="   <file id=\"".$cf->{name}."\" filename=\"".$cf->{file}."\" />\n";
1192     }
1193     $s.=" </files>\n";
1194     return $s;
1195   }
1196 }
1197
1198 sub bios_setup {
1199   my $cr=shift;
1200   
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";
1203   } else {
1204     my $s;
1205     my $b;
1206     $s = " <bioses>\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";
1211     }
1212     $s.= " </bioses>\n";
1213     return $s;
1214   }
1215 }
1216
1217 sub device_setup { 
1218   my $cr=shift;
1219   my $cd;
1220   my $s="";
1221
1222   $s.=" <devices>\n";
1223
1224   foreach $cd (@{$cr->{devices}}) {
1225     $s.="   <device class=\"".$cd->{class}."\" id=\"".$cd->{id}."\"";
1226     if (defined($cd->{opt})) { 
1227       $s.=" ".$cd->{opt};
1228     }
1229     if (!defined($cd->{nest})) { 
1230       $s.=" />\n";
1231     } else {
1232       $s.=" >\n";
1233       $s.=$cd->{nest};
1234       $s.="   </device>\n";
1235     }
1236   }
1237
1238   $s.=" </devices>\n";
1239
1240   return $s;
1241
1242 }
1243
1244
1245
1246 sub get_user {
1247   my $def = shift;
1248   
1249   my $inp = <STDIN>; chomp($inp);
1250   
1251   if ($inp eq "") { 
1252     return $def;
1253   } else {
1254     return $inp;
1255   }
1256 }
1257
1258 sub get_kernel_feature {
1259   my $dir=shift;
1260   my $feature=shift;
1261   my $x;
1262
1263   $x=`grep $feature= $dir/config-\`uname -r\``;
1264
1265   if ($x=~/^\s*\#/) {
1266     return undef;
1267   } else {
1268     if ($x=~/\s*$feature=\s*(\S*)\s*$/) {
1269       return $1;
1270     } else {
1271       return undef;
1272     }
1273   }
1274 }
1275   
1276 sub get_palacios_core_feature {
1277   my $dir=shift;
1278   my $feature=shift;
1279   my $x;
1280
1281   $x=`grep $feature= $dir/.config`;
1282
1283   if ($x=~/^\s*\#/) {
1284     return undef;
1285   } else {
1286     if ($x=~/\s*$feature=\s*(\S*)\s*$/) {
1287       return $1;
1288     } else {
1289       return undef;
1290     }
1291   }
1292 }
1293
1294 sub is_palacios_core_feature_enabled {
1295   my $out = get_palacios_core_feature(@_);
1296   return !defined($out) ? 0 : $out eq "y";
1297 }
1298
1299
1300 sub powerof2  {
1301   my $x = shift;
1302   my $exp;
1303   
1304   $exp = log($x) /log(2);
1305
1306   return $exp==int($exp);
1307 }
1308
1309
1310 sub gen_image_file {
1311   my ($name, $size_mb) = @_;
1312
1313   if (system("dd if=/dev/zero of=$name bs=1048576 count=$size_mb")) { 
1314     return -1;
1315   } else  {
1316     return 0;
1317   }
1318 }
1319
1320
1321 sub gen_qemu_startup {
1322   my ($cr, $pdir, $dir) = @_;
1323   my $d;
1324
1325   # FIX ME
1326   print "Generating QEMU Startup Script\n";
1327
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}." ";
1345     } else {
1346       die "Do not know how to handle QEMU device of type ".$d->{type}."\n";
1347     }
1348   }
1349
1350   print Q "\n";
1351
1352   close(Q);
1353 }