Index: trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk	(revision 36629)
+++ trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk	(revision 36630)
@@ -25,6 +25,6 @@
  VBoxManage_SOURCES = \
 	VBoxManage.cpp \
- 	VBoxManageHelp.cpp \
- 	$(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \
+	VBoxManageHelp.cpp \
+	$(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \
 	$(if $(VBOX_WITH_GUEST_CONTROL),VBoxManageGuestCtrl.cpp)
  VBoxManage_LIBS      += $(LIB_RUNTIME)
@@ -33,44 +33,45 @@
  VBoxManage_DEFS.win   = _WIN32_WINNT=0x0500
  VBoxManage_SOURCES = \
- 	VBoxManage.cpp \
- 	VBoxInternalManage.cpp \
- 	VBoxManageControlVM.cpp \
- 	VBoxManageDebugVM.cpp \
- 	VBoxManageDHCPServer.cpp \
- 	VBoxManageDisk.cpp \
- 	$(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \
+	VBoxManage.cpp \
+	VBoxInternalManage.cpp \
+	VBoxManageControlVM.cpp \
+	VBoxManageDebugVM.cpp \
+	VBoxManageDHCPServer.cpp \
+	VBoxManageDisk.cpp \
+	$(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \
 	$(if $(VBOX_WITH_GUEST_CONTROL),VBoxManageGuestCtrl.cpp) \
- 	VBoxManageHelp.cpp \
- 	VBoxManageHostonly.cpp \
- 	VBoxManageAppliance.cpp \
- 	VBoxManageInfo.cpp \
- 	VBoxManageList.cpp \
- 	VBoxManageMetrics.cpp \
- 	VBoxManageMisc.cpp \
- 	VBoxManageModifyVM.cpp \
- 	VBoxManageSnapshot.cpp \
- 	VBoxManageStorageController.cpp \
- 	VBoxManageUSB.cpp \
- 	VBoxManageBandwidthControl.cpp
+	VBoxManageHelp.cpp \
+	VBoxManageHostonly.cpp \
+	VBoxManageAppliance.cpp \
+	VBoxManageInfo.cpp \
+	VBoxManageList.cpp \
+	VBoxManageMetrics.cpp \
+	VBoxManageMisc.cpp \
+	VBoxManageModifyVM.cpp \
+	VBoxManageSnapshot.cpp \
+	VBoxManageStorageController.cpp \
+	VBoxManageUSB.cpp \
+	VBoxManageBandwidthControl.cpp
 endif # !VBOX_ONLY_DOCS
 
 VBoxManage_DEFS      += \
- 	$(if $(VBOX_WITH_AHCI), VBOX_WITH_AHCI) \
- 	$(if $(VBOX_WITH_ALSA), VBOX_WITH_ALSA) \
+	$(if $(VBOX_WITH_AHCI), VBOX_WITH_AHCI) \
+	$(if $(VBOX_WITH_ALSA), VBOX_WITH_ALSA) \
 	$(if $(VBOX_WITH_COPYTOGUEST),VBOX_WITH_COPYTOGUEST) \
- 	$(if $(VBOX_WITH_E1000),VBOX_WITH_E1000) \
- 	$(if $(VBOX_WITH_GUEST_CONTROL),VBOX_WITH_GUEST_CONTROL) \
- 	$(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS) \
- 	$(if $(VBOX_WITH_HEADLESS), VBOX_WITH_HEADLESS) \
+	$(if $(VBOX_WITH_E1000),VBOX_WITH_E1000) \
+	$(if $(VBOX_WITH_GUEST_CONTROL),VBOX_WITH_GUEST_CONTROL) \
+	$(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS) \
+	$(if $(VBOX_WITH_HEADLESS), VBOX_WITH_HEADLESS) \
 	$(if $(VBOX_WITH_HGCM), VBOX_WITH_HGCM) \
- 	$(if $(VBOX_WITH_HOSTNETIF_API), VBOX_WITH_HOSTNETIF_API) \
+	$(if $(VBOX_WITH_HOSTNETIF_API), VBOX_WITH_HOSTNETIF_API) \
 	$(if $(VBOX_WITH_NETFLT), VBOX_WITH_NETFLT) \
- 	$(if $(VBOX_WITH_PULSE),VBOX_WITH_PULSE) \
- 	$(if $(VBOX_WITH_SCSI), VBOX_WITH_SCSI) \
- 	$(if $(VBOX_WITH_SOLARIS_OSS), VBOX_WITH_SOLARIS_OSS) \
- 	$(if $(VBOX_WITH_VBOXSDL), VBOX_WITH_VBOXSDL) \
- 	$(if $(VBOX_WITH_VDE), VBOX_WITH_VDE) \
+	$(if $(VBOX_WITH_PULSE),VBOX_WITH_PULSE) \
+	$(if $(VBOX_WITH_SCSI), VBOX_WITH_SCSI) \
+	$(if $(VBOX_WITH_SOLARIS_OSS), VBOX_WITH_SOLARIS_OSS) \
+	$(if $(VBOX_WITH_VBOXSDL), VBOX_WITH_VBOXSDL) \
+	$(if $(VBOX_WITH_VDE), VBOX_WITH_VDE) \
 	$(if $(VBOX_WITH_VIDEOHWACCEL), VBOX_WITH_VIDEOHWACCEL) \
- 	$(if $(VBOX_WITH_VIRTIO),VBOX_WITH_VIRTIO)
+	$(if $(VBOX_WITH_VIRTIO),VBOX_WITH_VIRTIO) \
+        $(if $(VBOX_WITH_PCI_PASSTHROUGH),VBOX_WITH_PCI_PASSTHROUGH)
 
 ifneq ($(KBUILD_TARGET),win)
Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 36629)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 36630)
@@ -151,4 +151,9 @@
                      "                            [--vram <vramsize in MB>]\n"
                      "                            [--acpi on|off]\n"
+#ifdef VBOX_WITH_PCI_PASSTHROUGH
+                     "                            [--attachpci 03:04.0]\n"
+                     "                            [--attachpci 03:04.0@02:01.0]\n"
+                     "                            [--detachpci 03:04.0]\n"
+#endif
                      "                            [--ioapic on|off]\n"
                      "                            [--pae on|off]\n"
Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 36629)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 36630)
@@ -29,4 +29,8 @@
 
 #include <VBox/com/VirtualBox.h>
+
+#ifdef VBOX_WITH_PCI_PASSTHROUGH
+#include <VBox/pci.h>
+#endif
 
 #include <VBox/log.h>
@@ -1803,4 +1807,44 @@
     } /* USB */
 
+#ifdef VBOX_WITH_PCI_PASSTHROUGH
+    /* Host PCI passthrough devices */
+    {
+         SafeIfaceArray <IPciDeviceAttachment> assignments;
+         rc = machine->COMGETTER(PciDeviceAssignments)(ComSafeArrayAsOutParam(assignments));
+         if (SUCCEEDED(rc))
+         {
+             if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
+             {
+                 RTPrintf("\nAttached physical PCI devices:\n\n");
+             }
+             
+             for (size_t index = 0; index < assignments.size(); ++index)
+             {
+                 ComPtr<IPciDeviceAttachment> Assignment = assignments[index];
+                 char szHostPciAddress[32], szGuestPciAddress[32];
+                 int32_t iHostPciAddress = -1, iGuestPciAddress = -1;
+                 Bstr DevName;
+
+                 Assignment->COMGETTER(Name)(DevName.asOutParam());
+                 Assignment->COMGETTER(HostAddress)(&iHostPciAddress);
+                 Assignment->COMGETTER(GuestAddress)(&iGuestPciAddress);
+                 PciBusAddress().fromLong(iHostPciAddress).format(szHostPciAddress, sizeof(szHostPciAddress));
+                 PciBusAddress().fromLong(iGuestPciAddress).format(szGuestPciAddress, sizeof(szGuestPciAddress));
+
+                 if (details == VMINFO_MACHINEREADABLE)
+                     RTPrintf("AttachedHostPci=%s,%s\n", szHostPciAddress, szGuestPciAddress);
+                 else
+                     RTPrintf("   Host device %lS at %s attached as %s\n", DevName.raw(), szHostPciAddress, szGuestPciAddress);
+             }
+             
+             if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
+             {
+                 RTPrintf("\n");
+             }
+         }
+    }
+    /* Host PCI passthrough devices */
+#endif
+
     /*
      * Shared folders
Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 36629)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 36630)
@@ -171,4 +171,8 @@
     MODIFYVM_FAULT_TOLERANCE_SYNC_INTERVAL,
     MODIFYVM_CPU_EXECTUION_CAP,
+#ifdef VBOX_WITH_PCI_PASSTHROUGH
+    MODIFYVM_ATTACH_PCI,
+    MODIFYVM_DETACH_PCI,
+#endif
     MODIFYVM_CHIPSET
 };
@@ -299,4 +303,8 @@
     { "--faulttolerancesyncinterval", MODIFYVM_FAULT_TOLERANCE_SYNC_INTERVAL, RTGETOPT_REQ_UINT32 },
     { "--chipset",                  MODIFYVM_CHIPSET,                   RTGETOPT_REQ_STRING },
+#ifdef VBOX_WITH_PCI_PASSTHROUGH
+    { "--attachpci",                MODIFYVM_ATTACH_PCI,                RTGETOPT_REQ_STRING },
+    { "--detachpci",                MODIFYVM_DETACH_PCI,                RTGETOPT_REQ_STRING },
+#endif
 };
 
@@ -306,4 +314,25 @@
 }
 
+/** Parse PCI address in format 01:02.03 and convert it to the numeric representation. */
+static int32_t parsePci(const char* szPciAddr)
+{
+    char* pszNext = (char*)szPciAddr;
+    int rc;
+    uint8_t aVals[3] = {0, 0, 0};
+    
+    rc = RTStrToUInt8Ex(pszNext, &pszNext, 16, &aVals[0]);
+    if (RT_FAILURE(rc) || pszNext == NULL || *pszNext != ':')
+        return -1;
+    
+    rc = RTStrToUInt8Ex(pszNext+1, &pszNext, 16, &aVals[1]);
+    if (RT_FAILURE(rc) || pszNext == NULL || *pszNext != '.')
+        return -1;
+
+    rc = RTStrToUInt8Ex(pszNext+1, &pszNext, 16, &aVals[2]);
+    if (RT_FAILURE(rc) || pszNext == NULL)
+        return -1;
+
+    return (aVals[0] << 8) | (aVals[1] << 3) | (aVals[2] << 0);
+}
 
 int handleModifyVM(HandlerArg *a)
@@ -2178,5 +2207,43 @@
                 break;
             }
-
+#ifdef VBOX_WITH_PCI_PASSTHROUGH
+            case MODIFYVM_ATTACH_PCI:
+            {
+                const char* pAt = strchr(ValueUnion.psz, '@');
+                int32_t iHostAddr, iGuestAddr;
+
+                iHostAddr = parsePci(ValueUnion.psz);
+                iGuestAddr = pAt != NULL ? parsePci(pAt + 1) : iHostAddr;
+                
+                if (iHostAddr == -1 || iGuestAddr == -1)
+                {
+                    errorArgument("Invalid --attachpci argument '%s' (valid: 'HB:HD.HF@GB:GD.GF' or just 'HB:HD.HF')", ValueUnion.psz);
+                    rc = E_FAIL;
+                }
+                else
+                {
+                    CHECK_ERROR(machine, AttachHostPciDevice(iHostAddr, iGuestAddr, TRUE));
+                }
+
+                break;
+            }
+            case MODIFYVM_DETACH_PCI:
+            {
+                int32_t iHostAddr;
+
+                iHostAddr = parsePci(ValueUnion.psz);
+                if (iHostAddr == -1)
+                {
+                    errorArgument("Invalid --detachpci argument '%s' (valid: 'HB:HD.HF')", ValueUnion.psz);
+                    rc = E_FAIL;
+                }
+                else
+                {
+                    CHECK_ERROR(machine, DetachHostPciDevice(iHostAddr));
+                }
+
+                break;
+            }
+#endif
             default:
             {
Index: trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 36629)
+++ trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 36630)
@@ -4704,7 +4704,4 @@
         and most information will be delivered as IHostPciDevicePlugEvent
         on IVirtualBox event source.
-        <note>
-          Not yet implemented.
-        </note>
 
         <see>IHostPciDevicePlugEvent</see>
@@ -4738,8 +4735,4 @@
         will be delivered. As currently we don't support hot device
         unplug, IHostPciDevicePlugEvent event is delivered immediately.
-
-        <note>
-          Not yet implemented.
-        </note>
 
         <see>IHostPciDevicePlugEvent</see>
Index: trunk/src/VBox/Main/src-client/BusAssignmentManager.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/BusAssignmentManager.cpp	(revision 36629)
+++ trunk/src/VBox/Main/src-client/BusAssignmentManager.cpp	(revision 36630)
@@ -376,12 +376,12 @@
         const DeviceAssignmentRule* rule = matchingRules[iRule];
 
-        Address.iBus = rule->iBus;
-        Address.iDevice = rule->iDevice;
-        Address.iFn = rule->iFn;
+        Address.miBus = rule->iBus;
+        Address.miDevice = rule->iDevice;
+        Address.miFn = rule->iFn;
 
         if (checkAvailable(Address))
             return S_OK;
     }
-    AssertMsg(false, ("All possible candidate positions for %s exhausted\n", pszName));
+    AssertMsgFailed(("All possible candidate positions for %s exhausted\n", pszName));
 
     return E_INVALIDARG;
@@ -490,11 +490,11 @@
         return rc;
 
-    rc = InsertConfigInteger(pCfg, "PCIBusNo",      GuestAddress.iBus);
+    rc = InsertConfigInteger(pCfg, "PCIBusNo",      GuestAddress.miBus);
     if (FAILED(rc))
         return rc;
-    rc = InsertConfigInteger(pCfg, "PCIDeviceNo",   GuestAddress.iDevice);
+    rc = InsertConfigInteger(pCfg, "PCIDeviceNo",   GuestAddress.miDevice);
     if (FAILED(rc))
         return rc;
-    rc = InsertConfigInteger(pCfg, "PCIFunctionNo", GuestAddress.iFn);
+    rc = InsertConfigInteger(pCfg, "PCIFunctionNo", GuestAddress.miFn);
     if (FAILED(rc))
         return rc;
Index: trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 36629)
+++ trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 36630)
@@ -485,8 +485,8 @@
         Assert(GuestPciAddress.valid());
 
-        if (GuestPciAddress.iBus > 0)
+        if (GuestPciAddress.miBus > 0)
         {
             int iBridgesMissed = 0;
-            int iBase = GuestPciAddress.iBus - 1;
+            int iBase = GuestPciAddress.miBus - 1;
 
             while (!BusMgr->hasPciDevice("ich9pcibridge", iBase) && iBase > 0)
@@ -547,7 +547,7 @@
 
         InsertConfigInteger(pCfg,      "DetachHostDriver",  1);
-        InsertConfigInteger(pCfg,      "HostPCIBusNo",      HostPciAddress.iBus);
-        InsertConfigInteger(pCfg,      "HostPCIDeviceNo",   HostPciAddress.iDevice);
-        InsertConfigInteger(pCfg,      "HostPCIFunctionNo", HostPciAddress.iFn);
+        InsertConfigInteger(pCfg,      "HostPCIBusNo",      HostPciAddress.miBus);
+        InsertConfigInteger(pCfg,      "HostPCIDeviceNo",   HostPciAddress.miDevice);
+        InsertConfigInteger(pCfg,      "HostPCIFunctionNo", HostPciAddress.miFn);
 
         GuestPciAddress.fromLong(guest);
@@ -557,7 +557,7 @@
             return hrc;
 
-        InsertConfigInteger(pCfg,      "GuestPCIBusNo",      GuestPciAddress.iBus);
-        InsertConfigInteger(pCfg,      "GuestPCIDeviceNo",   GuestPciAddress.iDevice);
-        InsertConfigInteger(pCfg,      "GuestPCIFunctionNo", GuestPciAddress.iFn);
+        InsertConfigInteger(pCfg,      "GuestPCIBusNo",      GuestPciAddress.miBus);
+        InsertConfigInteger(pCfg,      "GuestPCIDeviceNo",   GuestPciAddress.miDevice);
+        InsertConfigInteger(pCfg,      "GuestPCIFunctionNo", GuestPciAddress.miFn);
 
         /* the Main driver */
@@ -1880,7 +1880,7 @@
                 InsertConfigNode(pNetBootCfg, achBootIdx, &pNetBtDevCfg);
                 InsertConfigInteger(pNetBtDevCfg, "NIC", it->mInstance);
-                InsertConfigInteger(pNetBtDevCfg, "PCIBusNo",      it->mPciAddress.iBus);
-                InsertConfigInteger(pNetBtDevCfg, "PCIDeviceNo",   it->mPciAddress.iDevice);
-                InsertConfigInteger(pNetBtDevCfg, "PCIFunctionNo", it->mPciAddress.iFn);
+                InsertConfigInteger(pNetBtDevCfg, "PCIBusNo",      it->mPciAddress.miBus);
+                InsertConfigInteger(pNetBtDevCfg, "PCIDeviceNo",   it->mPciAddress.miDevice);
+                InsertConfigInteger(pNetBtDevCfg, "PCIFunctionNo", it->mPciAddress.miFn);
             }
         }
@@ -2509,5 +2509,5 @@
             {
                 BootNic aNic = llBootNics.front();
-                uint32_t u32NicPciAddr = (aNic.mPciAddress.iDevice << 16) | aNic.mPciAddress.iFn;
+                uint32_t u32NicPciAddr = (aNic.mPciAddress.miDevice << 16) | aNic.mPciAddress.miFn;
                 InsertConfigInteger(pCfg, "NicPciAddress",    u32NicPciAddr);
             }
@@ -2517,5 +2517,5 @@
                 if (BusMgr->findPciAddress("hda", 0, Address))
                 {
-                    uint32_t u32AudioPciAddr = (Address.iDevice << 16) | Address.iFn;
+                    uint32_t u32AudioPciAddr = (Address.miDevice << 16) | Address.miFn;
                     InsertConfigInteger(pCfg, "AudioPciAddress",    u32AudioPciAddr);
                 }
Index: trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 36629)
+++ trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 36630)
@@ -5933,6 +5933,9 @@
         fireHostPciDevicePlugEvent(es, mid.raw(), false /* unplugged */, true /* success */, pAttach, NULL);
     }
-
-    return S_OK;
+    
+    return fRemoved ? S_OK : setError(VBOX_E_OBJECT_NOT_FOUND,
+                                      tr("No host PCI device %08x attached"),
+                                      hostAddress
+                                      );
 }
 
