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.


Avoid strict-aliasing related issues when compiling with optimization
[palacios.git] / v3_config_guest.pl
index abe7d49..5b50f40 100755 (executable)
@@ -1,5 +1,6 @@
 #!/usr/bin/perl -w
 
+use Data::Dumper;
 
 print <<END
 
@@ -45,6 +46,9 @@ END
 ;
 
 $pdir = $ENV{PALACIOS_DIR};
+$qdir = $ENV{PALACIOS_QEMU_DIR};
+
+$haveqemu = defined($qdir);
 
 if (!defined($pdir)) { 
   print "Please set PALACIOS_DIR (you probably have not sourced ENV) and try again\n";
@@ -60,7 +64,7 @@ if ($otherbios) {
 }
 
 
-$name = "guest";
+$name = "myguest";
 print "What is the name of your guest? [$name] : ";
 $name = get_user($name);
 
@@ -83,6 +87,8 @@ if ($config{numcores}>1) {
   }
 }
 
+do_swapping(\%config, $pdir);
+
 
 print "We will give your guest the default performance tuning characteristics\n";
 $config{perftune_block} .= <<PERFTUNE
@@ -117,6 +123,10 @@ if (is_palacios_core_feature_enabled($pdir, "V3_CONFIG_EXT_VMWARE")) {
   $config{extensions_block} .= "  <extension name=\"VMWARE_IFACE\"></extension>\n";
 }
 
+
+do_bioses(\%config, $pdir, $dir);
+
+
 #
 # Basic debugging
 #
@@ -170,17 +180,28 @@ if (is_palacios_core_feature_enabled($pdir,"V3_CONFIG_MPTABLE")) {
 #
 do_device(\%config, $pdir, "V3_CONFIG_PIT", "8254_PIT", "PIT",1); # must have
 
-#
-# Keyboard and mouse (PS/2 controller)
-#
-do_device(\%config, $pdir, "V3_CONFIG_KEYBOARD", "KEYBOARD", "keyboard",1); #must have
 
+if (defined($ENV{PALACIOS_QEMU_DIR})) { 
+  print "\nYour Palacios configuration includes the ability to use QEMU devices from a patched QEMU.\n";
+  print "Do you want to use QEMU's PS/2, graphics, and serial port devices? [n] : ";
+  if (get_user("n") eq "y") { 
+    do_qemu_ui(\%config, $pdir, $dir);
+  }
+}
 
-#
-# Displays, Consoles, Serial
-#
-print "\nWe will now consider consoles and serial ports.\n\n";
-do_consoles_and_ports(\%config, $pdir);
+if (!defined($config{qemu_ui})) { 
+  #
+  # Keyboard and mouse (PS/2 controller)
+  #
+  do_device(\%config, $pdir, "V3_CONFIG_KEYBOARD", "KEYBOARD", "keyboard",1); #must have
+
+  #
+  # Displays, Consoles, Serial
+  #
+  print "\nWe will now consider consoles and serial ports.\n\n";
+  do_consoles_and_ports(\%config, $pdir);
+  
+}
 
 
 #
@@ -191,12 +212,6 @@ print "\nWe will now consider storage controllers and devices.\n\n";
 do_storage(\%config, $pdir, $dir, $name, "pci0", "southbridge");
 
 
-#
-# NVRAM 
-#
-# Note: do_storage *must* have placed an IDE named ide0 in order for this to work
-#
-do_device(\%config, $pdir, "V3_CONFIG_NVRAM", "NVRAM", "nvram", 1, undef, "     <storage>ide0</storage>\n"); #must have
 
 
 #
@@ -208,6 +223,33 @@ do_network(\%config, $pdir, $dir, $name, "pci0", "southbridge");
 
 
 #
+# Sanity-check - is there something bootable?
+#
+#
+if (!($config{havecd} && !($config{havehd}))) {
+  print "The guest's storage configuration does not have either a CD or an HD.  \n";
+  print "This means the guest BIOS will have nothing local to boot.  \n";
+  if (!($config{havenic})) { 
+    print "The guest also does does not have a NIC, which means the BIOS cannot\n";
+    print "do a network boot.\n";
+  } else {
+    print "The guest does have a NIC, so a network boot is possible, if the\n";
+    print "BIOS supports it.\n";
+  }
+  print "If this is not your intent, you probably want to CTRL-C and try again.\n";
+}
+
+print "The BIOS boot sequence will be set to CD,HD.   If you need to change this\n";
+print "later, edit the <bootseq> block within the NVRAM device.\n";
+
+#
+# NVRAM 
+#
+# Note: do_storage *must* have placed an IDE named ide0 in order for this to work
+#
+do_device(\%config, $pdir, "V3_CONFIG_NVRAM", "NVRAM", "nvram", 1, undef, "     <storage>ide0</storage>\n     <bootseq>cd,hd</bootseq>\n"); #must have
+
+#
 #
 # Generic Catch-all Device
 #
@@ -220,7 +262,9 @@ $target = PAL;
 
 print $target "<vm class=\"PC\">\n\n";
 print $target file_setup(\%config), "\n";
+print $target bios_setup(\%config),"\n";
 print $target memory_setup(\%config), "\n";
+print $target swapping_setup(\%config), "\n";
 print $target paging_setup(\%config), "\n";
 print $target memmap_setup(\%config), "\n";
 print $target numa_setup(\%config), "\n";
@@ -234,11 +278,17 @@ print $target "</vm>\n";
 
 close(PAL);
 
+#print Dumper(\%config);
+
+if (defined($config{qemu}) && $config{qemu} eq "y") {
+  gen_qemu_startup(\%config, $pdir, $dir);
+}
+
 print "\n\nYour guest is now ready in the directory $dir\n\n";
 print "To run it, do:\n\n";
 print "  cd $dir\n";
 print "  v3_create -b $name.pal $name\n";
-print "  v3_launch /dev/v3-vmN (N given by v3_create\n\n";
+print "  v3_launch /dev/v3-vmN (N given by v3_create)\n\n";
 print "Other useful tools:\n\n";
 print "  v3_console (CGA console)\n";
 print "  v3_stream (connect to stream, for example, serial port)\n\n";
@@ -382,6 +432,82 @@ sub get_numa_data() {
   return %numa;
 }
 
+
+sub do_swapping {
+  my ($cr, $pdir) = @_;
+
+  my $canswap = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_SWAPPING");
+  my $mem = $cr->{mem};
+
+  if ($canswap) { 
+    #Config for swapping
+    $cr->{swapping} = yn_question("Do you want to use swapping?", "n", "y", "n");
+
+    if ($cr->{swapping} eq "y") { 
+      $cr->{swap_alloc} = quant_question("How much memory do you want to allocate [MB] ?", $mem/2);
+      print "We will use the default swapping strategy.\n";
+      $cr->{swap_strat} = "default";
+      print "What file do you want to swap to? [./swap.bin] ";
+      $cr->{swap_file} = get_user("./swap.bin");
+    }
+  }
+}
+
+sub add_bios   {
+  my ($cr, $name, $fileid, $address) =@_;
+
+  push @{$cr->{bios_list}},  { name=>$name, fileid=>$fileid, address=>$address };
+  
+}
+
+sub do_bios {
+  my ($cr, $pdir, $dir) = @_;
+  my $nextbios = defined($cr->{bios_list}) ? "bios".($#{$cr->{bios_list}}+1) : "bios0";
+  
+  if (yn_question("Add a".($nextbios eq "bios0" ? "" : "nother")." custom bios? ", "n", "y", "n") eq "y") { 
+    my ($n, $fn, $addr) ;
+    print "What is your name for this bios? [$nextbios] : ";
+    $n = get_user($nextbios);
+    while (1) { 
+      print "Where is the path to the file for bios $n ? ";
+      $fn = get_user("");
+      if (!(-e $fn)) { 
+       print "Cannot find $fn, try again\n";
+       next;
+      } else {
+       if (system("cp $fn $dir/$n.dat")) { 
+         print "Unable to copy $fn\n";
+         next;
+       } else {
+         add_file($cr, "$n", "$n.dat");
+         print "What is the destination physical linear address (in hex) for bios $n [0xf0000] ? ";
+         $addr = get_user("0xf0000");
+         add_bios($cr,$n,$n,$addr);
+         return 1;
+       }
+      }
+    }
+  } else {
+    return 0;
+  }
+}
+
+sub do_bioses { 
+  my ($cr, $pdir, $dir) = @_;
+
+  $cr->{bios_custom} = yn_question("Do you want to customize BIOSes?   (done automatically later for QEMU devices) ", "n", "y", "n");
+
+  if ($cr->{bios_custom} eq "y") { 
+    $cr->{bios_custom_nobios} = yn_question("Disable built-in system bios? ", "n", "y", "n");
+    $cr->{bios_custom_novgabios} = yn_question("Disable built-in VGA bios? ", "n", "y", "n");
+    
+    while (do_bios($cr, $pdir, $dir)) {}
+  }
+}
+      
+    
+                                           
+
 sub do_device {
   my ($cr,$pdir,$feature, $class, $id, $hardfail, $optblob, $nestblob) =@_;
 
@@ -398,6 +524,74 @@ sub do_device {
   }
 }
 
+sub add_qemu_device {
+  my ($cr, $pdir, $type, $name, $url) = @_;
+
+  $cr->{qemu}='y';
+  
+  push @{$cr->{qemu_devices}}, { type=>$type, name=>$name, url=>$url } ;
+
+}
+
+sub do_qemu_ui {
+  my ($cr, $pdir, $dir) = @_;
+  my $vgabios=$ENV{PALACIOS_QEMU_DIR}."/share/qemu/vgabios-cirrus.bin";
+
+  $cr->{qemu_ui}='y';
+  
+  # PS/2 is a generic device
+  add_device($cr,"GENERIC","qemu-ps2",
+            " forward=\"host_device\" hostdev=\"user:qemu-ps2\" ",
+            "    <ports> <start>0x60</start> <end>0x60</end> <mode>PASSTHROUGH</mode> </ports>\n".
+            "    <ports> <start>0x64</start> <end>0x64</end> <mode>PASSTHROUGH</mode> </ports>\n".
+            "    <ports> <start>0x80</start> <end>0x80</end> <mode>PASSTHROUGH</mode> </ports>\n");
+  add_qemu_device($cr,$pdir, "qemu-ps2", "qemu-ps2", "user:qemu-ps2");
+
+  # so is serial
+  add_device($cr,"GENERIC", "qemu-serial",
+            " forward=\"host_device\" hostdev=\"user:qemu-serial\" ",
+            "    <ports> <start>0x3f8</start> <end>0x3ff</end>  <mode>PASSTHROUGH</mode> </ports>\n".
+            "    <ports> <start>0x2f8</start> <end>0x2ff</end>  <mode>PASSTHROUGH</mode> </ports>\n".
+            "    <ports> <start>0x3e8</start> <end>0x3ef</end>  <mode>PASSTHROUGH</mode> </ports>\n".
+            "    <ports> <start>0x2e8</start> <end>0x2ef</end>  <mode>PASSTHROUGH</mode> </ports>\n");
+  add_qemu_device($cr,$pdir, "qemu-serial", "qemu-serial", "user:qemu-serial");
+
+  # Video has both a generic device and a PCI device (enhanced vga) and a bios
+  add_device($cr,"GENERIC", "qemu-video-legacy",
+            " forward=\"host_device\" hostdev=\"user:qemu-video-legacy\" ",
+            "    <ports> <start>0x3b4</start> <end>0x3da</end>  <mode>PASSTHROUGH</mode> </ports>\n".
+            "    <memory> <start>0xa0000</start> <end>0xbffff</end>  <mode>PASSTHROUGH</mode> </memory>\n");
+  add_qemu_device($cr,$pdir, "qemu-video-legacy", "qemu-video-legacy", "user:qemu-video-legacy");
+
+  add_device($cr, "PCI_FRONT", "qemu-video",
+            " hostdev=\"user:qemu-video\" ",
+            "    <bus>pci0</bus>\n");
+
+  add_qemu_device($cr,$pdir, "qemu-video", "qemu-video", "user:qemu-video");
+
+  print "To use QEMU video, we will need to add the relevant bios. \n";
+  while (1) { 
+    print "Where is the QEMU video bios ? [$vgabios] : ";
+    $vgabios = get_user($vgabios); 
+    if (-e $vgabios) { 
+      if (system("cp $vgabios $dir/qemu-videobios.dat")) { 
+       print "Cannot copy $vgabios, try again\n";
+       next;
+      } else {
+       last;
+       }
+    } else {
+      print "Cannot find $vgabios, try again\n";
+      next;
+    } 
+  }
+  add_file($cr, "qemu-videobios", "qemu-videobios.dat");
+  add_bios($cr, "qemu-videobios", "qemu-videobios", "0xc0000");
+  $cr->{bios_custom} = 'y';
+  $cr->{bios_custom_novgabios} = 'y';
+
+}
+
 sub do_consoles_and_ports {
   my ($cr, $pdir) = @_;
 
@@ -429,7 +623,7 @@ sub do_consoles_and_ports {
   if (!($cancga || $canvga || $canserial || $canvirtioconsole)) { 
     print "Hmm... No console mechanism is enabled in your Palacios build...\n";
     print "  This is probably not what you want...\n";
-}
+  }
   
   $didcga=0;
   if ($cancga) { 
@@ -495,6 +689,7 @@ sub do_consoles_and_ports {
     print "You have configured your guest without any obvious way of interacting with it....\n";
     print "  This is probably not what you want...\n";
   } 
+
 } 
 
 
@@ -595,6 +790,10 @@ sub do_network {
     }
     $num++;
   }
+
+  if ($num>0) { 
+    $cr->{havenic}=1;
+  }
  }
 
 
@@ -641,12 +840,14 @@ sub do_storage {
       do_storage_backend($cr, $pdir, $dir, $name, "virtioblk$i", "data$i", "");
     }
   }
-}
+
+}      
+
 
 
 sub do_storage_backend {
   my ($cr, $pdir, $dir, $name, $frontend, $loc, $frontendblock) = @_;
-  my ($canramdisk, $canfiledisk, $cannetdisk, $cantmpdisk);
+  my ($canramdisk, $canfiledisk, $cannetdisk, $cantmpdisk, $canqcowdisk);
   my @devs=("cd","hd","nothing");
   my @disks;
   my $type;
@@ -656,15 +857,17 @@ sub do_storage_backend {
 
   $canramdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_RAMDISK");
   $canfiledisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_FILEDISK");
+  $canqcowdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_QCOWDISK");
   $cannetdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_NETDISK");
   $cantmpdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_TMPDISK");
   push @disks, "ramdisk" if $canramdisk;
   push @disks, "filedisk" if $canramdisk;
+  push @disks, "qcowdisk" if $canramdisk;
   push @disks, "netdisk" if $cannetdisk;
   push @disks, "tmpdisk" if $cantmpdisk;
 
 
-  if (!$canramdisk && !$canfiledisk && !$cannetdisk && !$cantmpdisk) {
+  if (!$canramdisk && !$canfiledisk && !$cannetdisk && !$cantmpdisk && !$canqcowdisk) {
     print "You have no storage implementations enabled in your Palacios build, so it is impossible\n";
     print "to add anything to storage controller \"$frontend\" location \"$loc\"\n";
     return -1;
@@ -683,6 +886,7 @@ sub do_storage_backend {
     print "A storage device requires one of the following implementations\n";
     print "  * RAMDISK - the data is kept in memory (common) : ".($canramdisk ? "available" : "UNAVAILABLE")."\n";
     print "  * FILEDISK - the data is kept in a host file (common) : ".($canfiledisk ? "available" : "UNAVAILABLE")."\n";
+    print "  * QCOWDISK - the data is kept in a host file (qcow) : ".($canqcowdisk ? "available" : "UNAVAILABLE")."\n";
     print "  * NETDISK - the data is accessed via the network (uncommon) : ".($cannetdisk ? "available" : "UNAVAILABLE")."\n";
     print "  * TMPDISK - the data is kept in memory and discarded (common) : ".($cantmpdisk ? "available" : "UNAVAILABLE")."\n";
     while (1) {
@@ -692,7 +896,7 @@ sub do_storage_backend {
       last if $#test==0;
     }
 
-    if ($type eq "filedisk" || $type eq "ramdisk") { 
+    if ($type eq "filedisk" || $type eq "ramdisk" || $type eq "qcowdisk") { 
       print "$type requires a file (.iso for example).  Do you have one? [y] : ";
       if (get_user("y") eq "y") { 
        while (1) { 
@@ -717,9 +921,11 @@ sub do_storage_backend {
       if ($what eq "cd") { 
        $attach.="     <model>V3VEE CDROM</model>\n".
                  "     <type>CDROM</type>\n".$frontendblock;
+       $cr->{havecd}=1;
       } else {
        $attach.="     <model>V3VEE HD</model>\n".
                  "     <type>HD</type>\n".$frontendblock;
+       $cr->{havehd}=1;
       }
       $attach.="    </frontend>\n";
 
@@ -727,9 +933,12 @@ sub do_storage_backend {
        add_device($cr,"RAMDISK","$frontend\_$loc", undef, 
                   "    <file>$frontend\_$loc</file>\n".$attach);
        add_file($cr, "$frontend\_$loc", "$frontend\_$loc.dat");
-      } else {
+      } elsif ($type eq "filedisk") {
        add_device($cr,"FILEDISK","$frontend\_$loc", $what eq "hd" ? "writable=\"1\"" : undef, 
                   "    <path>$frontend\_$loc.dat</path>\n".$attach);
+      } else {
+       add_device($cr,"QCOWDISK","$frontend\_$loc", $what eq "hd" ? "writable=\"1\"" : undef, 
+                  "    <path>$frontend\_$loc.dat</path>\n".$attach);
       }
       last;
     } else {
@@ -813,7 +1022,7 @@ GENERIC2
 ;
   }
   my @par = find_devices_by_class($cr,"SERIAL");
-  if ($#par<0) { 
+  if ($#par<0 && !defined($cr->{qemu_ui})) {
     $block .=<<GENERIC3
     <ports>
      <!-- Serial COM 1 -->
@@ -954,6 +1163,14 @@ sub extensions_setup  {
   return $s;
 }
 
+sub swapping_setup {
+  my $cr=shift;
+  if (defined($cr->{swapping}) && $cr->{swapping} eq "y") { 
+    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";
+  } else {
+    return " <!-- there is no swapping configuration, but you can add one manually -->\n";
+  }
+}
 sub telemetry_setup  {
   my $cr=shift;
   return " <telemetry>".$cr->{telemetry}."</telemetry>\n";
@@ -978,6 +1195,25 @@ sub file_setup {
   }
 }
 
+sub bios_setup {
+  my $cr=shift;
+  
+  if (!defined($cr->{bios_custom}) || $cr->{bios_custom} eq "n") { 
+    return " <!-- this configuration does not use a custom bios setup but you can add one with the <bioses> syntax-->\n";
+  } else {
+    my $s;
+    my $b;
+    $s = " <bioses>\n";
+    $s.= "  <disable_rombios/>\n" if defined($cr->{bios_custom_nobios}) && $cr->{bios_custom_nobios} eq "y";
+    $s.= "  <disable_vgabios/>\n" if defined($cr->{bios_custom_novgabios}) && $cr->{bios_custom_novgabios} eq "y";
+    foreach $b (@{$cr->{bios_list}}) { 
+      $s.= "  <bios file=\"".$b->{fileid}."\" address=\"".$b->{address}."\" />\n";
+    }
+    $s.= " </bioses>\n";
+    return $s;
+  }
+}
+
 sub device_setup { 
   my $cr=shift;
   my $cd;
@@ -1080,3 +1316,38 @@ sub gen_image_file {
     return 0;
   }
 }
+
+
+sub gen_qemu_startup {
+  my ($cr, $pdir, $dir) = @_;
+  my $d;
+
+  # FIX ME
+  print "Generating QEMU Startup Script\n";
+
+  open(Q,">$dir/qemu_startup.sh");
+  print Q $ENV{PALACIOS_QEMU_DIR}."/bin/qemu-system-x86_64 -m 2048 -accel pal  ";
+  foreach $d (@{$cr->{qemu_devices}}) { 
+    if ($d->{type} eq "qemu-ps2") { 
+      print Q " -map KBD ".$d->{url}." ";
+    } elsif ($d->{type} eq "qemu-serial") { 
+      print Q " -serial stdio -map SERIAL ".$d->{url}." ";
+    } elsif ($d->{type} eq "qemu-video-legacy") { 
+      print Q " -map VGA ".$d->{url}." ";
+    } elsif ($d->{type} eq "qemu-video") { 
+      print Q " -vga cirrus -map CIRRUS ".$d->{url}." ";
+    } elsif ($d->{type} eq "qemu-e1000") { 
+      print Q " -nic e1000 -map E1000 ".$d->{url}." ";
+    } elsif ($d->{type} eq "qemu-ide-legacy") { 
+      print Q " -ide ... -map IDE-LEGACY ".$d->{url}." ";
+    } elsif ($d->{type} eq "qemu-ide") { 
+      print Q " -ide ... -map IDE ".$d->{url}." ";
+    } else {
+      die "Do not know how to handle QEMU device of type ".$d->{type}."\n";
+    }
+  }
+
+  print Q "\n";
+
+  close(Q);
+}