diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index cfad19b08a95b022c181b9c0ce10cc0cf91692cc..3fca09fbefbbc22def94cfc3cf2bb79c693ac1b1 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -3054,7 +3054,7 @@ class LUCreateInstance(LogicalUnit):
     # set optional parameters to none if they don't exist
     for attr in ["kernel_path", "initrd_path", "hvm_boot_order", "pnode",
                  "iallocator", "hvm_acpi", "hvm_pae", "hvm_cdrom_image_path",
-                 "vnc_bind_address"]:
+                 "hvm_nic_type", "hvm_disk_type", "vnc_bind_address"]:
       if not hasattr(self.op, attr):
         setattr(self.op, attr, None)
 
@@ -3269,6 +3269,15 @@ class LUCreateInstance(LogicalUnit):
                                    " like a valid IP address" %
                                    self.op.vnc_bind_address)
 
+    # Xen HVM device type checks
+    if self.sstore.GetHypervisorType() == constants.HT_XEN_HVM31:
+      if self.op.hvm_nic_type not in constants.HT_HVM_VALID_NIC_TYPES:
+        raise errors.OpPrereqError("Invalid NIC type %s specified for Xen HVM"
+                                   " hypervisor" % self.op.hvm_nic_type)
+      if self.op.hvm_disk_type not in constants.HT_HVM_VALID_DISK_TYPES:
+        raise errors.OpPrereqError("Invalid disk type %s specified for Xen HVM"
+                                   " hypervisor" % self.op.hvm_disk_type)
+
     if self.op.start:
       self.instance_status = 'up'
     else:
@@ -3334,6 +3343,8 @@ class LUCreateInstance(LogicalUnit):
                             hvm_pae=self.op.hvm_pae,
                             hvm_cdrom_image_path=self.op.hvm_cdrom_image_path,
                             vnc_bind_address=self.op.vnc_bind_address,
+                            hvm_nic_type=self.op.hvm_nic_type,
+                            hvm_disk_type=self.op.hvm_disk_type,
                             )
 
     feedback_fn("* creating instance disks...")
@@ -4132,6 +4143,8 @@ class LUQueryInstanceData(NoHooksLU):
         idict["hvm_acpi"] = instance.hvm_acpi
         idict["hvm_pae"] = instance.hvm_pae
         idict["hvm_cdrom_image_path"] = instance.hvm_cdrom_image_path
+        idict["hvm_nic_type"] = instance.hvm_nic_type
+        idict["hvm_disk_type"] = instance.hvm_disk_type
 
       if htkind in constants.HTS_REQ_PORT:
         idict["vnc_bind_address"] = instance.vnc_bind_address
@@ -4203,12 +4216,14 @@ class LUSetInstanceParams(LogicalUnit):
     self.hvm_boot_order = getattr(self.op, "hvm_boot_order", None)
     self.hvm_acpi = getattr(self.op, "hvm_acpi", None)
     self.hvm_pae = getattr(self.op, "hvm_pae", None)
+    self.hvm_nic_type = getattr(self.op, "hvm_nic_type", None)
+    self.hvm_disk_type = getattr(self.op, "hvm_disk_type", None)
     self.hvm_cdrom_image_path = getattr(self.op, "hvm_cdrom_image_path", None)
     self.vnc_bind_address = getattr(self.op, "vnc_bind_address", None)
     all_parms = [self.mem, self.vcpus, self.ip, self.bridge, self.mac,
                  self.kernel_path, self.initrd_path, self.hvm_boot_order,
                  self.hvm_acpi, self.hvm_pae, self.hvm_cdrom_image_path,
-                 self.vnc_bind_address]
+                 self.vnc_bind_address, self.hvm_nic_type, self.hvm_disk_type]
     if all_parms.count(None) == len(all_parms):
       raise errors.OpPrereqError("No changes submitted")
     if self.mem is not None:
@@ -4334,6 +4349,12 @@ class LUSetInstanceParams(LogicalUnit):
     if self.hvm_pae is not None:
       instance.hvm_pae = self.hvm_pae
       result.append(("hvm_pae", self.hvm_pae))
+    if self.hvm_nic_type is not None:
+      instance.hvm_nic_type = self.hvm_nic_type
+      result.append(("hvm_nic_type", self.hvm_nic_type))
+    if self.hvm_disk_type is not None:
+      instance.hvm_disk_type = self.hvm_disk_type
+      result.append(("hvm_disk_type", self.hvm_disk_type))
     if self.hvm_cdrom_image_path:
       if self.hvm_cdrom_image_path == constants.VALUE_NONE:
         instance.hvm_cdrom_image_path = None
diff --git a/lib/constants.py b/lib/constants.py
index a8035705e5d1f4b08cd985aed61bddff3bdbf1bb..b78e7247cb43a642374cc0504089445c29a23b3d 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -262,6 +262,10 @@ HT_HVM_NIC_NE2K_PCI = "ne2k_pci"
 HT_HVM_NIC_NE2K_ISA = "ne2k_isa"
 HT_HVM_DEV_PARAVIRTUAL = "paravirtual"
 HT_HVM_DEV_IOEMU = "ioemu"
+HT_HVM_VALID_NIC_TYPES = frozenset([HT_HVM_NIC_RTL8139, HT_HVM_NIC_NE2K_PCI,
+                                    HT_HVM_NIC_NE2K_ISA,
+                                    HT_HVM_DEV_PARAVIRTUAL])
+HT_HVM_VALID_DISK_TYPES = frozenset([HT_HVM_DEV_PARAVIRTUAL, HT_HVM_DEV_IOEMU])
 
 # Cluster Verify steps
 VERIFY_NPLUSONE_MEM = 'nplusone_mem'
diff --git a/lib/hypervisor/hv_xen.py b/lib/hypervisor/hv_xen.py
index 08219bdd7f368aefe3475f0492bccfafca6541be..f97e2c945b79623adcdb7604040a2312487046f2 100644
--- a/lib/hypervisor/hv_xen.py
+++ b/lib/hypervisor/hv_xen.py
@@ -431,7 +431,14 @@ class XenHvmHypervisor(XenHypervisor):
 
     vif_data = []
     for nic in instance.nics:
-      nic_str = "mac=%s, bridge=%s, type=ioemu" % (nic.mac, nic.bridge)
+      if instance.hvm_nic_type is None: # ensure old instances don't change
+        nic_type = ", type=ioemu"
+      elif instance.hvm_nic_type == constants.HT_HVM_DEV_PARAVIRTUAL:
+        nic_type = ", type=paravirtualized"
+      else:
+        nic_type = ", model=%s, type=ioemu" % instance.hvm_nic_type
+
+      nic_str = "mac=%s, bridge=%s%s" % (nic.mac, nic.bridge, nic_type)
       ip = getattr(nic, "ip", None)
       if ip is not None:
         nic_str += ", ip=%s" % ip
@@ -440,7 +447,12 @@ class XenHvmHypervisor(XenHypervisor):
     config.write("vif = [%s]\n" % ",".join(vif_data))
     disk_data = cls._GetConfigFileDiskData(instance.disk_template,
                                             block_devices)
-    disk_data = [line.replace(",sd", ",ioemu:hd") for line in disk_data]
+    if ((instance.hvm_disk_type is None) or
+        (instance.hvm_disk_type == constants.HT_HVM_DEV_IOEMU)):
+      replacement = ",ioemu:hd"
+    else:
+      replacement = ",hd"
+    disk_data = [line.replace(",sd", replacement) for line in disk_data]
     if instance.hvm_cdrom_image_path is not None:
       iso = "'file:%s,hdc:cdrom,r'" % (instance.hvm_cdrom_image_path)
       disk_data.append(iso)
diff --git a/lib/opcodes.py b/lib/opcodes.py
index c5062a39920d80ba4864ee49bcdaa5b995f6d973..3137b8e4bbccb6a1f9d393712b7738cda63bbd58 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -310,7 +310,7 @@ class OpCreateInstance(OpCode):
     "kernel_path", "initrd_path", "hvm_boot_order", "hvm_acpi",
     "hvm_pae", "hvm_cdrom_image_path", "vnc_bind_address",
     "file_storage_dir", "file_driver",
-    "iallocator",
+    "iallocator", "hvm_nic_type", "hvm_disk_type",
     ]
 
 
@@ -399,7 +399,8 @@ class OpSetInstanceParams(OpCode):
   __slots__ = [
     "instance_name", "mem", "vcpus", "ip", "bridge", "mac",
     "kernel_path", "initrd_path", "hvm_boot_order", "hvm_acpi",
-    "hvm_pae", "hvm_cdrom_image_path", "vnc_bind_address"
+    "hvm_pae", "hvm_cdrom_image_path", "vnc_bind_address",
+    "hvm_nic_type", "hvm_disk_type"
     ]