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.


Added guest configurator and renamed v3vee configurator
Peter Dinda [Fri, 4 Oct 2013 15:11:52 +0000 (10:11 -0500)]
v3_config_guest.pl [new file with mode: 0755]
v3_config_v3vee.pl [moved from v3_config.pl with 100% similarity]

diff --git a/v3_config_guest.pl b/v3_config_guest.pl
new file mode 100755 (executable)
index 0000000..a925cc7
--- /dev/null
@@ -0,0 +1,1068 @@
+#!/usr/bin/perl -w
+
+
+print <<END
+
+Welcome.  The purpose of this tool is to simplify the creation of
+common forms of guests for the V3VEE environment on a Linux system.
+These guests *should* work for any host embedding (e.g., Kitten) but
+there may be hidden Linux assumptions.
+
+The tool assumes you have already built Palacios, the Linux embedding,
+and the Linux user-sapce tools.  If you haven't done this, hit CTRL-C
+now, configure and build Palacios, the user-space tools, and run
+v3_config.pl.
+
+This tool also assumes that you have the environment produced by
+v3_config.pl sourced:
+
+  source ./ENV
+
+What this tool builds is a directory that contains a guest
+configuration file (the ".pal" file) and its dependent files. Note
+that lots of additional functionality is possible beyond what can be
+configured with this tool.  The precise functionality depends on the
+version and branch of Palacios, and what was configured into it when
+it was built.  To access such functionality, you need to write your
+own .pal file, or use one generated by this tool as a basis.
+
+Any .pal guest configuration file is instantiated as a VM in the
+following way:
+
+  cd guest
+  v3_create -b guest.pal name_of_guest
+
+Any files (disk images) that your guest configuration depends on
+must be accessible when v3_create is run.  
+
+Once the VM is instantiated, you can then launch it:
+
+  v3_launch /dev/v3-vmN  (N is given by the v3_create command)
+
+We will configure your guest via a sequence of questions.
+
+END
+;
+
+$pdir = $ENV{PALACIOS_DIR};
+
+if (!defined($pdir)) { 
+  print "Please set PALACIOS_DIR (you probably have not sourced ENV) and try again\n";
+  exit -1;
+}
+
+$otherbios = get_palacios_core_feature($pdir,"V3_CONFIG_OTHERBIOS");
+$otherbios = !defined($otherbios) ? 0 : $otherbios eq "y" ? 1: 0;
+if ($otherbios) {
+  print "Your Palacios installation is set up for a custom BIOS. \n";
+  print "You probably do NOT want to use this tool...  Continue ? [n] : ";
+  if (get_user("n") eq "n") { exit -1; }
+}
+
+
+$name = "guest";
+print "What is the name of your guest? [$name] : ";
+$name = get_user($name);
+
+$dir = "./$name";
+print "What is the directory into which we will put your guest? [$dir] : ";
+$dir = get_user($dir);
+if (!mkdir($dir)) { 
+  print "Unable to create the directory\n";
+  exit -1;
+}
+
+$config{numcores} = quant_question("How many cores will your guest have?", 1);
+
+$config{mem} = quant_question("How much memory should it have in MB?", 256);
+
+if ($config{numcores}>1) { 
+  print "Do you want to to produce a NUMA configuration and mapping for your guest? [n] : ";
+  if (get_user("n") eq "y") { 
+    do_numa_config(\%config,$pdir);
+  }
+}
+
+
+print "We will give your guest the default performance tuning characteristics\n";
+$config{perftune_block} .= <<PERFTUNE
+  <group name="yield">
+   <strategy>friendly</strategy>
+   <threshold>1000</threshold>
+   <time>1000</time>
+  </group>
+PERFTUNE
+;
+
+print "We will give your guest the default host scheduler interaction characteristics\n";
+$config{schedule_hz_block} .= " <schedule_hz>100</schedule_hz>\n";
+
+
+$config{telemetry} = yn_question("Do you want telemetry (information about guest exits) ?", "y", "enable", "disable");
+
+
+$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");
+
+$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");
+
+print "We will give your guest the default shadow paging strategy for when shadow paging is used.\n";
+$config{shadow_strategy} = "VTLB";
+
+
+$config{memmap_block} = " <!-- there are no passthrough memory regions, but you can add them using\n".
+                         "     the <memmap> syntax described in the manual -->\n";
+
+if (is_palacios_core_feature_enabled($pdir, "V3_CONFIG_EXT_VMWARE")) {
+  print "We will include the VMware Personality Extension since your Palacios build has it enabled\n";
+  $config{extensions_block} .= "  <extension name=\"VMWARE_IFACE\"></extension>\n";
+}
+
+#
+# Basic debugging
+#
+do_device(\%config, $pdir, "V3_CONFIG_BOCHS_DEBUG", "BOCHS_DEBUG", "bios_debug");
+do_device(\%config, $pdir, "V3_CONFIG_OS_DEBUG", "OS_DEBUG", "os_debug");
+
+#
+# Interrupt control
+#
+#
+do_device(\%config, $pdir, "V3_CONFIG_PIC", "8259A", "PIC", 1);  # must have
+if ($config{numcores}==1 && is_palacios_core_feature_enabled($pdir,"V3_CONFIG_BOCHSBIOS")) {
+  print "This is a single core guest and your Palacios setup uses the legacy BOCHS BIOS.\n";
+  print " Do you want to have only the legacy (pre-APIC) interrupt controller logic? [n] :";
+  if (get_user("n") eq "y") { 
+    goto intr_done;
+  }
+}
+do_device(\%config, $pdir, "V3_CONFIG_APIC", "LAPIC", "apic", 1); # must have
+do_device(\%config, $pdir, "V3_CONFIG_IO_APIC", "IOAPIC", "ioapic", 1, undef, "    <apic>apic</apic>\n"); 
+
+
+#
+# PCI buses and north/south bridge - all must haves
+#
+do_device(\%config, $pdir, "V3_CONFIG_PCI", "PCI", "pci0",1); # must have
+do_device(\%config, $pdir, "V3_CONFIG_I440FX", "i440FX", "northbridge",1, undef, "    <bus>pci0</bus>\n"); #must have
+do_device(\%config, $pdir, "V3_CONFIG_PIIX3", "PIIX3", "southbridge",1, undef, "    <bus>pci0</bus>\n"); #must have
+
+#
+# MPTABLE for legacy BIOS.  Innocuous for SEABIOS or OTHERBIOS
+#
+#
+if (is_palacios_core_feature_enabled($pdir,"V3_CONFIG_MPTABLE")) {
+  print "We will include a classic MPTABLE constructor to describe your machine to the guest\n";
+  add_device(\%config, "MPTABLE", "mptable");
+} else {
+  if ($numcores>1 &&  is_palacios_core_feature_enabled($pdir,"V3_CONFIG_BOCHSBIOS")) {
+    print "This is a multicore guest, and your Palacios configuration uses the classic BOCHS BIOS\n".
+      "but does not have the MPTABLE constructor enabled...  This guest will almost\n".
+       "certainly fail to work.  Do you want to continue anyway? [n] :";
+    if (get_user("n") eq "n") { 
+      exit -1;
+    }
+  }
+}
+
+
+# 
+# Legacy timer
+#
+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
+
+
+#
+# Displays, Consoles, Serial
+#
+print "\nWe will now consider consoles and serial ports.\n\n";
+do_consoles_and_ports(\%config, $pdir);
+
+
+#
+# Storage controllers and devices (attached to PCI bus)
+#
+#
+print "\nWe will now consider storage controllers and devices.\n\n";
+do_storage(\%config, $pdir, $dir, $name, "pci0", "southbridge");
+
+
+#
+# Network interfaces (attached to PCI bus)
+#
+#
+print "\nWe will now consider network interfaces.\n\n";
+do_network(\%config, $pdir, $dir, $name, "pci0", "southbridge");
+
+
+#
+#
+# Generic Catch-all Device
+#
+do_generic(\%config, $pdir);
+
+
+open(PAL,">$dir/$name.pal") or die "Cannot open $dir/$name.pal\n";
+
+$target = PAL;
+
+print $target "<vm class=\"PC\">\n\n";
+print $target file_setup(\%config), "\n";
+print $target memory_setup(\%config), "\n";
+print $target paging_setup(\%config), "\n";
+print $target memmap_setup(\%config), "\n";
+print $target numa_setup(\%config), "\n";
+print $target core_setup(\%config), "\n";
+print $target schedule_setup(\%config), "\n";
+print $target perftune_setup(\%config), "\n";
+print $target telemetry_setup(\%config), "\n";
+print $target extensions_setup(\%config), "\n";
+print $target device_setup(\%config), "\n";
+print $target "</vm>\n";
+
+close(PAL);
+
+print "\n\nYour guest is now ready in the directory $dir\n";
+
+exit;
+
+
+sub quant_question {
+  my ($ques, $default) = @_;
+
+  print $ques." [$default] : ";
+  
+  return get_user($default);
+}
+
+sub yn_question {
+  my ($ques, $default, $yans, $nans) = @_;
+  
+  my $ans;
+  
+  print $ques." [$default] : ";
+  $ans = get_user($default);
+  
+  if (substr($ans,0,1) eq 'y' || substr($ans,0,1) eq 'Y') { 
+    return $yans;
+  } else {
+    return $nans;
+  }
+}
+
+sub do_numa_config {
+  my ($cr, $pdir) =@_;
+  my %numa;
+  my $numpnodes;
+  my $numpcores;
+  my $numvnodes;
+  my $numvcores;
+  my $memblock="";
+  my $pernode;
+  my $lastnode;
+  my $i;
+  my @vnodemap;
+  my @vcoremap;
+  my $canauto=1;
+
+  %numa = get_numa_data();
+
+  $numvcores = $cr->{numcores};
+
+  print "NUMA configuration involves the following:\n";
+  print " 1. Definition of virtual NUMA nodes and their corresponding regions of guest physical memory\n";
+  print " 2. Mapping of virtual NUMA nodes to physical NUMA nodes\n";
+  print " 3. Mapping of virtual cores to virtual NUMA nodes\n";
+  print " 4. Mapping of virtual cores to physical cores\n";
+  print "Your guest contains ".$numvcores." virtual  cores.\n";
+  print "This host contains ".$numa{numcores}." physical cores and ".$numa{numnodes}." physical nodes.\n";
+  print "How many physical NUMA nodes does your target hardware have? [".$numa{numnodes}."] ? ";
+  $numpnodes=get_user($numa{numnodes});
+  $canauto=0 if ($numpnodes > $numa{numnodes});
+  print "How many physical cores does your target hardware have? [".$numa{numcores}."] ? ";
+  $numpcores=get_user($numa{numcores});
+  $canauto=0 if ($numpcores > $numa{numcores});
+  do {
+    print "How many virtual NUMA nodes do you want? (up to $numvcores) for auto) [2] : ";
+    $numvnodes=get_user("2");
+  } while ($numvnodes<=0 || $numvnodes>$numvcores);
+  $cr->{numnodes} = $numvnodes;
+  $pernode = int(($cr->{mem}*1024*1024)/$numvnodes);
+  $lastnode = $pernode + ($cr->{mem}*1024*1024)-$pernode*$numvnodes;
+  print "Your guest has ".$cr->{mem}." MB of RAM, which we have defined and mapped like this:\n";
+  for ($i=0;$i<$numvnodes;$i++) {
+    my $start=$i*$pernode;
+    my $end=(($i==($numvnodes-1)) ? $start+$lastnode : $start+$pernode);
+    my $pnode = $i % $numpnodes;
+    $vnodemap[$i]=$pnode;
+    $start=sprintf("0x%x",$start);
+    $end=sprintf("0x%x",$end);
+    print "vnode $i : GPA $start to GPA $end : pnode $pnode\n";
+    push @{$cr->{nodes}}, { start=>$start, end=>$end, vnode=>$i, pnode=>$pnode};
+  }
+  my $doauto=0;
+  if ($canauto) { 
+    print "We can now automatically map virtual cores to virtual NUMA nodes and physical CPUs using strided assignment\n";
+    print "assuming *this host's* NUMA configuration.  Or you can enter the assignments manually. \n";
+    print "  Which would you prefer {auto,manual} [auto] ? : ";
+    $doauto=1 if  (get_user("auto") eq "auto");
+  } else {
+    print "Automatic mapping of virtual cores to virtual NUMA nodes and physical CPUs is not possible\n";
+    print "given your host configuration.   Please configure manually below.\n";
+    $doauto=0;
+  }
+  if ($doauto) { 
+    for ($i=0;$i<$numvcores;$i++) { 
+      my $vnode = $i % $numvnodes;
+      my $pnode = $vnodemap[$vnode];
+      my $pcores = $numa{"node$pnode"}{cores};
+      my $numpcores_per_pnode = $#{$pcores}+1; # assumes identical number on each node...
+      my $pcore = $numa{"node$pnode"}{cores}->[int($i/$numpnodes) % $numpcores_per_pnode];
+      print "vcore $i : vnode $vnode : pnode $pnode : pcore $pcore\n";
+      $cr->{"core$i"}{pcore} = $pcore;
+      $cr->{"core$i"}{vnode} = $vnode;
+    }
+  } else {
+    for ($i=0;$i<$numvcores;$i++) { 
+      print "What is the virtual NUMA node for virtual core $i ? [] : ";
+      my $vnode = get_user("");
+      my $pnode = $vnodemap[$vnode];
+      print "That maps to physical NUMA node $pnode.\n";
+      print "What is the physical core for virtual core $i ? [] : ";
+      my $pcore = get_user("");
+      print "vcore $i : vnode $vnode : pnode $pnode : pcore $pcore\n";
+      $cr->{"core$i"}{pcore} = $pcore;
+      $cr->{"core$i"}{vnode} = $vnode;
+    }
+  }
+  $cr->{numa}=1;
+}
+
+
+sub get_numa_data() {
+  my $line;
+  my $maxnode=0;
+  my $maxcpu=0;
+  my %numa;
+
+  open (N, "numactl --hardware |");
+  while ($line=<N>) { 
+    if ($line=~/^node\s+(\d+)\s+cpus:\s+(.*)$/) { 
+      my $node=$1;
+      my @cpus = split(/\s+/,$2);
+      my $cpu;
+      if ($node>$maxnode) { $maxnode=$node; }
+      foreach $cpu (@cpus) { 
+       if ($cpu>$maxcpu) { $maxcpu=$cpu; }
+      }
+      $numa{"node$node"}{cores}=\@cpus;
+    }
+  }
+  $numa{numnodes}=$maxnode+1;
+  $numa{numcores}=$maxcpu+1;
+  return %numa;
+}
+
+sub do_device {
+  my ($cr,$pdir,$feature, $class, $id, $hardfail, $optblob, $nestblob) =@_;
+
+  if (is_palacios_core_feature_enabled($pdir, $feature)) {
+    print "We will include a $class since your Palacios build has it enabled\n";
+    add_device(\%config, $class, $id, $optblob, $nestblob);
+  } else {
+    if (defined($hardfail) && $hardfail) { 
+      print "Wow, your Palacios build doesn't have a $class... We can't live without that...\n";
+      exit -1;
+    } else {
+      print "Not configuring a $class since your Palacios build doesn't have it enabled\n";
+    }
+  }
+}
+
+sub do_consoles_and_ports {
+  my ($cr, $pdir) = @_;
+
+  my $cga = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_CGA");
+  my $curses = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_CURSES_CONSOLE");
+  my $cons = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_CONSOLE");
+  my $cancga = $cga && $curses && $cons;
+  my $vga = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_VGA");
+  my $gcons = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_GRAPHICS_CONSOLE");
+  my $canvga = $vga && $gcons;
+  my $serial = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_SERIAL_UART");
+  my $charstream = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_CHAR_STREAM");
+  my $stream = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_STREAM");
+  my $canserial = $serial && $charstream && $stream;
+  my $virtioconsole = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_LINUX_VIRTIO_CONSOLE");
+  my $canvirtioconsole = $virtioconsole; # probably need to verify frontend
+  my $paragraph = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_PARAGRAPH");
+  my $canparagraph = $paragraph && $gcons;
+
+  print "Your Palacios configuration allows the following options:\n";
+  print "  * CGA: classic 80x25 text-only PC console (common option): ".($cancga ? "available\n" : "NOT AVAILABLE\n");
+  print "  * VGA: classic 640x480 graphical PC console (uncommon option): ".($canvga ? "available\n" : "NOT AVAILABLE\n");
+  print "  * SERIAL: classic PC serial ports (common option): ".($canserial ? "available\n" : "NOT AVAILABLE\n");
+  print "  * VIRTIO: Linux Virtio Console (uncommon option): ".($canvirtioconsole ? "available\n" : "NOT AVAILABLE\n");
+  print "  * PARAGRAPH: Paravirtualized graphics card (uncommon option): ".($canparagraph ? "available\n" : "NOT AVAILABLE\n");
+  print "The CGA and VGA options are mutually exclusive\n";
+  print "THe VGA and PARAGRAPH options are mutually exclusive\n";
+  
+  if (!($cancga || $canvga || $canserial || $canvirioconsole)) { 
+    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) { 
+    print "Do you want to use CGA as a console? [y] : ";
+    if (get_user("y") eq "y") { 
+      add_device(\%config, "CGA_VIDEO", "cga", "passthrough=\"disable\"");
+      add_device(\%config, "CURSES_CONSOLE", "console", undef, 
+                "    <frontend tag=\"cga\" />\n".
+                "    <tty>user</tty>\n");
+      $didcga=1;
+    }
+  }
+  
+  $didvga=0;
+  if ($canvga && !$didcga) { 
+    print "Do you want to use VGA as a console? [n] : ";
+    if (get_user("n") eq "y") { 
+      add_device(\%config, "VGA", "vga", "passthrough=\"disable\" hostframebuf=\"enable\"");
+      # there is no gconsole device
+      $didvga=1;
+    }
+  }
+  
+  $didserial=0;
+  if ($canserial) {
+    print "You can include serial ports whether you use them for a console or not\n";
+    print "Note that you must configure your guest to place its console onto a serial port\n";
+    print "for it to be visible\n";
+    print "Do you want to include the serial ports (COM1..4) ? [y] : ";
+    if (get_user("y") eq "y") {
+      add_device(\%config,"SERIAL","serial");
+      add_device(\%config,"CHAR_STREAM","stream1","name=\"com1\"", "    <frontend tag=\"serial\" com_port=\"1\" />\n");
+      add_device(\%config,"CHAR_STREAM","stream2","name=\"com2\"", "    <frontend tag=\"serial\" com_port=\"2\" />\n");
+      add_device(\%config,"CHAR_STREAM","stream3","name=\"com3\"", "    <frontend tag=\"serial\" com_port=\"3\" />\n");
+      add_device(\%config,"CHAR_STREAM","stream4","name=\"com4\"", "    <frontend tag=\"serial\" com_port=\"4\" />\n");
+      $didserial=1;
+    }
+  }
+  
+  
+  $didvirtioconsole=0;
+  if ($canvirtioconsole) {
+    print "Do you want to add a VIRTIO console? [n] : ";
+    if (get_user("n") eq "y") { 
+      add_device(\%config,"LNX_VIRTIO_CONSOLE","virtio-cons",undef,"    <bus>pci0</bus>\n");
+      print "NOTE: no backend for the VIRTIO console is currently configured\n";
+      $didvirtioconsole=1;
+    }
+  }
+  
+  $didparagraph=0;
+  if ($canparagraph && !$didvga) {
+    print "Do you want to add a PARAGRAPH graphics card? [n] : ";
+    if (get_user("n") eq "y") {
+      add_device(\%config, "PARAGRAPH", "paragraph", undef,  
+                "    <bus>pci0</bus>\n".
+                "    <mode>gcons_mem</bus>\n");
+      $didparagraph=1;
+    }
+  }
+  
+  if (!($didcga || $didvga || $didserial || $didvirioconsole || $didparagraph)) { 
+    print "You have configured your guest without any obvious way of interacting with it....\n";
+    print "  This is probably not what you want...\n";
+  } 
+} 
+
+
+sub do_network {
+  my ($cr,$pdir,$dir,$name, $pcibus)=@_;
+  my $canvnet = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_VNET");
+  my $canbridge = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_NIC_BRIDGE");
+  my $canoverlay = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_VNET_NIC") && $canvnet; 
+  my $canvirtio = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_LINUX_VIRTIO_NET"); 
+  my $canvirtiovnet = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_LINUX_VIRTIO_VNET"); # not sure...
+  my $canne2k = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_NE2K"); 
+  my $canrtl8139 = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_RTL8139"); 
+  my @devs;
+  my @backends;
+  my $front;
+  my $back;
+  my $num;
+  my @test;
+  my $mac;
+
+  push @devs, "virtio" if $canvirtio;
+  push @devs, "rtl8139" if $canrtl8139;
+  push @devs, "ne2000" if $canne2k;
+
+  push @backends, "bridge" if $canbridge;
+  push @backends, "vnet" if $canoverlay;
+
+  if ($#devs==-1) { 
+    print "You have no network device implementations enabled in your Palacios build, so we are skipping networking\n";
+    return -1;
+  }
+  
+  if ($#backends==-1) { 
+    print "You have no network device backends enabled in your Palacios build, so we are skipping networking\n";
+    return -1;
+  }
+
+
+  $num=0;
+  while (1) { 
+    last if (!yn_question("Do you want to add ".($num==0 ? "a" : "another")." network device?","n",1,0));
+    print "This requires the addition of the frontend device (the NIC) and a backend device.\n";
+    print "Frontends in Palacios include:\n";
+    print "  * Virtio NIC (paravirtualized - common) : ".($canvirtio? "available" : "UNAVAILABLE")."\n";
+    print "  * RTL8139 NIC (uncommon) : ".($canrtl8139? "available" : "UNAVAILABLE")."\n";
+    print "  * NE2000 NIC (uncommon) : ".($canne2k? "available" : "UNAVAILABLE")."\n";
+    print "Which frontend do you want to add? {".join(", ", @devs)."} : ";
+    $front = get_user("");
+    @test = grep { /^$front$/ } @devs;
+    if ($#test!=0) { 
+      print "Unknown frontend\n"; 
+      next;
+    }
+    print "Backends in Palacios include:\n";
+    print "  * Bridge (direct attach to host NIC - common) : ".($canbridge? "available" : "UNAVAILABLE")."\n";
+    print "  * VNET overlay (uncommon) : ".($canoverlay ? "available" : "UNAVAILABLE")."\n";
+    print "Which backend do you want to add? {".join(", ", @backends)."} : ";
+    $back = get_user("");
+    @test = grep { /^$back/ } @backends;
+    if ($#test!=0) { 
+      print "Unknown backend\n"; 
+      next;
+    }
+    $mac=gen_macaddr();
+    print "What MAC address do you want your NIC to have? [$mac] : ";
+    $mac=get_user($mac);
+    if ($front eq "virtio") {
+       add_device($cr,"LNX_VIRTIO_NIC","net$num",undef,
+                  "    <bus>$pcibus</bus>\n".
+                  "    <mac>$mac</mac>\n".
+                  "    <model mode=\"guest-driven\" />\n");
+       print "The device is configured with default guest-driven operation\n";
+    }
+    if ($front eq "rtl8139") {
+       add_device($cr,"RTL8139","net$num",undef,
+                  "    <bus>$pcibus</bus>\n".
+                  "    <mac>$mac</mac>\n");
+    }
+    if ($front eq "ne2000") {
+       add_device($cr,"NE2000","net$num",undef,
+                  "    <bus>$pcibus</bus>\n".
+                  "    <mac>$mac</mac>\n");
+    }
+
+    if ($back eq "bridge") { 
+       my $host;
+       print "What is the name of the host NIC you want to bridge to? [eth0] : ";
+       $host=get_user("eth0");
+       add_device($cr,"NIC_BRIDGE","net$num-back",undef,
+                  "    <frontend tag=\"net$num\" />\n".
+                  "    <hostnic>$host</hostnic>\n");
+    }
+
+    if ($back eq "vnet") { 
+       add_device($cr,"VNET_NIC","net$num-back",undef,
+                  "    <frontend tag=\"net$num\" />\n");
+       print "Important: In order to use the VNET overlay, you must also create routes at run-time via /proc/v3vee/vnet\n";
+    }
+    $num++;
+  }
+ }
+
+
+sub gen_macaddr {
+  return sprintf("%02X:%02X:%02X:%02X:%02X:%02X",
+                int(rand(256)),
+                int(rand(256)),
+                int(rand(256)),
+                int(rand(256)),
+                int(rand(256)),
+                int(rand(256)));
+}
+                                                
+
+sub do_storage {
+  my ($cr,$pdir,$dir,$name,$pcibus,$controller)=@_;
+
+  # 
+  # IDE controller
+  #
+  do_device($cr, $pdir, "V3_CONFIG_IDE", "IDE", "ide0",1,undef,
+           "    <bus>$pcibus</bus>\n".
+           "    <controller>$controller</controller>\n" ); # must have
+  print "You can attach up to four storage devices to the storage controller \"ide\"\n";
+  do_storage_backend($cr, $pdir, $dir, $name, "ide0", "0_0", 
+                    "     <bus_num>0</bus_num>\n".
+                    "     <drive_num>0</drive_num>\n");
+  do_storage_backend($cr, $pdir, $dir, $name, "ide0", "0_1", 
+                  "     <bus_num>0</bus_num>\n".
+                  "     <drive_num>1</drive_num>\n");
+  do_storage_backend($cr, $pdir, $dir, $name, "ide0", "1_0", 
+                    "     <bus_num>1</bus_num>\n".
+                    "     <drive_num>0</drive_num>\n");
+  do_storage_backend($cr, $pdir, $dir, $name, "ide0", "1_1", 
+                    "     <bus_num>1</bus_num>\n".
+                  "     <drive_num>1</drive_num>\n");
+  
+  if (is_palacios_core_feature_enabled($pdir,"V3_CONFIG_LINUX_VIRTIO_BLOCK")) { 
+    print "You can attach VIRTIO block devices.  How many do you need? [0] : ";
+    my $num = get_user("0");
+    my $i;
+    for ($i=0;$i<$num;$i++) { 
+      add_device($cr,"LNX_VIRTIO_BLK","virtioblk$i",undef,"    <bus>$pcibus</bus>\n");
+      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 @devs=("cd","hd","nothing");
+  my @disks;
+  my $type;
+  my @type;
+  my $file;
+  my $size;
+
+  $canramdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_RAMDISK");
+  $canfiledisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_FILEDISK");
+  $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, "netdisk" if $cannetdisk;
+  push @disks, "tmpdisk" if $cantmpdisk;
+
+
+  if (!$canramdisk && !$canfiledisk && !$cannetdisk && !$cantmpdisk) {
+    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;
+  }
+   
+
+  while (1) { 
+    print "What do you want to attach to storage controller \"$frontend\" location \"$loc\"\n";
+    print "  Your options are {".join(", ",@devs)."} [nothing] : ";
+    $what = get_user("nothing");
+    @test = grep { /^$what$/ } @devs;
+    next if $#test!=0;
+    if ($what eq "nothing") {
+      return;
+    }
+    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 "  * 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";
+    print "  * RAMDISK - the data is kept in memory (common) : ".($canramdisk ? "available" : "UNAVAILABLE")."\n";
+    while (1) {
+      print "Which option do you want for this device? {".join(", ",@disks)."} [] : ";
+      $type = get_user("");
+      my @test = grep {/^$type$/} @disks;
+      last if $#test==0;
+    }
+
+    if ($type eq "filedisk" || $type eq "ramdisk") { 
+      print "$type requires a file (.iso for example).  Do you have one? [y] : ";
+      if (get_user("y") eq "y") { 
+       while (1) { 
+         print "What is its path? [] : ";
+         $file = get_user("");
+         if (!(-e $file)) {
+           print "$file does not exist\n";
+           next;
+         }
+         if (system("cp $file $dir/$frontend\_$loc.dat")) { 
+           print "Unable to copy $file\n";
+           next;
+         }
+          last;
+       }
+      } else {
+       print "We will make one.  How big should it be in MB? [64] : ";
+       $size = get_user("64");
+       gen_image_file("$dir/$frontend\_$loc.dat",$size);
+      }
+      $attach="    <frontend tag=\"$frontend\">\n";
+      if ($what eq "cd") { 
+       $attach.="     <model>V3VEE CDROM</model>\n".
+                 "     <type>CDROM</type>\n".$frontendblock;
+      } else {
+       $attach.="     <model>V3VEE HD</model>\n".
+                 "     <type>HD</type>\n".$frontendblock;
+      }
+      $attach.="    </frontend>\n";
+
+      if ($type eq "ramdisk") { 
+       add_device($cr,"RAMDISK","$frontend\_$loc", undef, 
+                  "    <file>$frontend\_$loc</file>\n".$attach);
+       add_file($cr, "$frontend\_$loc", "$frontend\_$loc.dat");
+      } else {
+       add_device($cr,"FILEDISK","$frontend\_$loc", $what eq "hd" ? "writable=\"1\"" : undef, 
+                  "    <path>$frontend\_$loc.dat</path>\n".$attach);
+      }
+      last;
+    } else {
+      print "$type is not currently supported\n";
+      next;
+    }
+  }
+}
+
+
+sub do_generic {
+  my ($cr, $pdir)=@_;
+
+  $block = <<GENERIC1
+    <ports> 
+      <!-- DMA 1 registers -->
+      <start>0x00</start>
+      <end>0x07</end>
+      <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+    <ports>
+      <!-- DMA 2 registers -->
+      <start>0xc0</start>
+      <end>0xc7</end>
+      <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+    <ports>
+     <!-- DMA 1 page registers -->
+     <start>0x81</start>
+     <end>0x87</end>
+     <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+    <ports>
+     <!-- DMA 2 page registers -->
+     <start>0x88</start>
+     <end>0x8f</end>
+     <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+    <ports>
+      <!-- DMA 1 Misc Registers -->
+      <start>0x08</start>
+      <end>0x0f</end>
+      <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+    <ports>
+     <!-- DMA 2 Misc Registers -->
+     <start>0xd0</start>
+     <end>0xde</end>
+     <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+    <ports>
+     <!-- ISA PNP -->
+     <start>0x274</start>
+     <end>0x277</end>
+     <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+    <ports>
+     <!-- ISA PNP -->
+     <start>0x279</start>
+     <end>0x279</end>
+     <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+    <ports>
+     <!-- ISA PNP -->
+     <start>0xa79</start>
+     <end>0xa79</end>
+     <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+GENERIC1
+;
+  my @dev = find_devices_by_class($cr,"PARALLEL");
+  if ($#dev<0) { 
+    $block .= <<GENERIC2
+    <ports>
+     <!-- Parallel Port -->
+     <start>0x378</start>
+     <end>0x37f</end>
+     <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+GENERIC2
+;
+  }
+  my @par = find_devices_by_class($cr,"SERIAL");
+  if ($#par<0) { 
+    $block .=<<GENERIC3
+    <ports>
+     <!-- Serial COM 1 -->
+     <start>0x3f8</start>
+     <end>0x3ff</end>
+     <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+    <ports>
+     <!-- Serial COM 2 -->
+     <start>0x2f8</start>
+     <end>0x2ff</end>
+     <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+    <ports>
+     <!-- Serial COM 3 -->
+     <start>0x3e8</start>
+     <end>0x3ef</end>
+     <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+    <ports>
+    <!-- Serial COM 4 -->
+     <start>0x2e8</start>
+     <end>0x2ef</end>
+     <mode>PRINT_AND_IGNORE</mode>
+    </ports>
+GENERIC3
+;
+  }
+
+  do_device($cr, $pdir, "V3_CONFIG_GENERIC", "GENERIC", "generic", 1, undef, $block);
+}
+
+sub add_file {
+  my ($cr, $name, $file) = @_;
+  
+  push @{$cr->{files}}, { name=>$name, file=>$file};
+
+}
+
+sub add_device {
+  my ($cr, $class, $id, $optblob, $nestblob) = @_;
+
+  push @{$cr->{devices}}, { class=>$class, id=>$id, opt=>$optblob, nest=>$nestblob };
+}
+
+sub find_devices_by_class {
+  my ($cr,$c)=@_;
+  return grep { $_->{class} eq $c } @{$cr->{devices}};
+}
+
+sub numa_setup {
+  my $cr =shift;
+  my $vnode;
+  my $s="";
+
+  if (!defined($cr->{numa})) { 
+    return "";
+  } else {
+    $s.=" <mem_layout vnodes=\"".($#{$cr->{nodes}}+1)."\" >\n";
+    foreach $vnode (@{$cr->{nodes}}) {
+      $s.="   <region start_addr=\"".$vnode->{start}."\" end_addr=\"".$vnode->{end}."\" vnode=\"".$vnode->{vnode}."\" node=\"".$vnode->{pnode}."\" />\n";
+    }
+    $s.=" </mem_layout>\n";
+    return $s;
+  }
+}
+
+sub core_setup  {
+  my $cr = shift;
+  my $i;
+  my $s="";
+  
+  
+  $s.= " <cores count=\"".$cr->{numcores}."\">\n";
+  if (!defined($cr->{numa})) { 
+    $s.= "  <core />\n";
+  } else {
+    for ($i=0;$i<$cr->{numcores};$i++) { 
+      $s.= "  <core target_cpu=\"".$cr->{"core$i"}{pcore}."\" vnode=\"".$cr->{"core$i"}{vnode}."\" />\n";
+    }
+  }
+  $s.= " </cores>\n";
+  
+  return $s;
+}
+
+sub memory_setup
+{
+  my $cr=shift;
+
+  return " <memory>".$cr->{mem}."</memory>\n";
+}
+
+sub paging_setup  {
+  my $cr = shift;
+  my $s="";
+  
+  $s.= " <paging mode=\"".$cr->{paging_mode}."\">\n";
+  $s.= "  <large_pages>".$cr->{large_pages}."</large_pages>\n";
+  $s.= "  <strategy>".$cr->{shadow_strategy}."</strategy>\n";
+  $s.= " </paging>\n";
+  
+  return $s;
+}
+
+sub memmap_setup {
+  my $cr = shift;
+
+  return $cr->{memmap_block};
+}
+
+sub schedule_setup {
+  my $cr = shift;
+
+  return $cr->{schedule_hz_block};
+}
+
+
+sub perftune_setup  {
+  my $cr=shift;
+  my $s="";
+  if (defined($cr->{perftune_block})) { 
+    $s.=" <perftune>\n";
+    $s.= $cr->{perftune_block};
+    $s.=" </perftune>\n";
+  }
+  return $s;
+}
+
+sub extensions_setup  {
+  my $cr=shift;
+  my $s="";
+  if (defined($cr->{extensions_block})) { 
+    $s.=" <extensions>\n";
+    $s.= $cr->{extensions_block};
+    $s.=" </extensions>\n";
+  }
+  return $s;
+}
+
+sub telemetry_setup  {
+  my $cr=shift;
+  return " <telemetry>".$cr->{telemetry}."</telemetry>\n";
+}
+
+sub file_setup { 
+  my $cr=shift;
+  my $cf;
+  my $s="";
+
+  if (!defined($cr->{files})) { 
+    return " <!-- this configuration contains no files -->\n";
+  } else {
+
+    $s.=" <files>\n";
+   
+    foreach $cf (@{$cr->{files}}) {
+      $s.="   <file id=\"".$cf->{name}."\" filename=\"".$cf->{file}."\" />\n";
+    }
+    $s.=" </files>\n";
+    return $s;
+  }
+}
+
+sub device_setup { 
+  my $cr=shift;
+  my $cd;
+  my $s="";
+
+  $s.=" <devices>\n";
+
+  foreach $cd (@{$cr->{devices}}) {
+    $s.="   <device class=\"".$cd->{class}."\" id=\"".$cd->{id}."\"";
+    if (defined($cd->{opt})) { 
+      $s.=" ".$cd->{opt};
+    }
+    if (!defined($cd->{nest})) { 
+      $s.=" />\n";
+    } else {
+      $s.=" >\n";
+      $s.=$cd->{nest};
+      $s.="   </device>\n";
+    }
+  }
+
+  $s.=" </devices>\n";
+
+  return $s;
+
+}
+
+
+
+sub get_user {
+  my $def = shift;
+  
+  my $inp = <STDIN>; chomp($inp);
+  
+  if ($inp eq "") { 
+    return $def;
+  } else {
+    return $inp;
+  }
+}
+
+sub get_kernel_feature {
+  my $dir=shift;
+  my $feature=shift;
+  my $x;
+
+  $x=`grep $feature= $dir/config-\`uname -r\``;
+
+  if ($x=~/^\s*\#/) {
+    return undef;
+  } else {
+    if ($x=~/\s*$feature=\s*(\S*)\s*$/) {
+      return $1;
+    } else {
+      return undef;
+    }
+  }
+}
+  
+sub get_palacios_core_feature {
+  my $dir=shift;
+  my $feature=shift;
+  my $x;
+
+  $x=`grep $feature= $dir/.config`;
+
+  if ($x=~/^\s*\#/) {
+    return undef;
+  } else {
+    if ($x=~/\s*$feature=\s*(\S*)\s*$/) {
+      return $1;
+    } else {
+      return undef;
+    }
+  }
+}
+
+sub is_palacios_core_feature_enabled {
+  my $out = get_palacios_core_feature(@_);
+  return !defined($out) ? 0 : $out eq "y";
+}
+
+
+sub powerof2  {
+  my $x = shift;
+  my $exp;
+  
+  $exp = log($x) /log(2);
+
+  return $exp==int($exp);
+}
+
+
+sub gen_image_file {
+  my ($name, $size_mb) = @_;
+
+  if (system("dd if=/dev/zero of=$name bs=1048576 count=$size_mb")) { 
+    return -1;
+  } else  {
+    return 0;
+  }
+}
similarity index 100%
rename from v3_config.pl
rename to v3_config_v3vee.pl