Index: /trunk/include/VBox/log.h
===================================================================
--- /trunk/include/VBox/log.h	(revision 35884)
+++ /trunk/include/VBox/log.h	(revision 35885)
@@ -120,4 +120,6 @@
     /** PCI Device group. */
     LOG_GROUP_DEV_PCI,
+    /** PCI Raw Device group. */
+    LOG_GROUP_DEV_PCI_RAW,
     /** PCNet Device group. */
     LOG_GROUP_DEV_PCNET,
@@ -395,4 +397,5 @@
     "DEV_PC_BIOS",  \
     "DEV_PCI",      \
+    "DEV_PCI_RAW",  \
     "DEV_PCNET",    \
     "DEV_PIC",      \
Index: /trunk/include/VBox/settings.h
===================================================================
--- /trunk/include/VBox/settings.h	(revision 35884)
+++ /trunk/include/VBox/settings.h	(revision 35885)
@@ -693,4 +693,30 @@
 
 /**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct HostPciDeviceAttachment
+{
+    HostPciDeviceAttachment()
+        : uHostAddress(0),
+          uGuestAddress(0)
+    {}
+
+    bool operator==(const HostPciDeviceAttachment &a) const
+    {
+        return (   (uHostAddress   == a.uHostAddress)
+                && (uGuestAddress  == a.uGuestAddress)
+                && (strDeviceName  == a.strDeviceName)
+               );
+    }
+
+    com::Utf8Str    strDeviceName;
+    uint32_t        uHostAddress;
+    uint32_t        uGuestAddress;
+};
+typedef std::list<HostPciDeviceAttachment> HostPciDeviceAttachmentList;
+
+/**
  * Representation of Machine hardware; this is used in the MachineConfigFile.hardwareMachine
  * field.
@@ -761,4 +787,5 @@
 
     IoSettings          ioSettings;             // requires settings version 1.10 (VirtualBox 3.2)
+    HostPciDeviceAttachmentList pciAttachments; // requires settings version 1.12 (VirtualBox 4.1)
 };
 
Index: /trunk/src/VBox/Devices/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Devices/Makefile.kmk	(revision 35884)
+++ /trunk/src/VBox/Devices/Makefile.kmk	(revision 35885)
@@ -160,4 +160,7 @@
  ifdef VBOX_WITH_VDE
   VBoxDD_DEFS           += VBOX_WITH_VDE
+ endif
+ ifdef VBOX_WITH_PCI_PASSTHROUGH
+  VBoxDD_DEFS           += VBOX_WITH_PCI_PASSTHROUGH
  endif
 
@@ -261,5 +264,7 @@
  	VBOX_HGCM_HOST_CODE \
  	VBOX_WITH_HGCM \
- 	$(if $(VBOX_BIOS_DMI_FALLBACK),VBOX_BIOS_DMI_FALLBACK,)
+ 	$(if $(VBOX_BIOS_DMI_FALLBACK),VBOX_BIOS_DMI_FALLBACK,) \
+	$(if $(VBOX_WITH_PCI_PASSTHROUGH),VBOX_WITH_PCI_PASSTHROUGH,)
+
  DevicesR3_DEFS.linux   += _GNU_SOURCE
  DevicesR3_DEFS.l4      += _GNU_SOURCE
@@ -541,5 +546,4 @@
  	Bus/MsiCommon.cpp \
  	Bus/MsixCommon.cpp \
- 	$(if $(VBOX_WITH_PCI_PASSTHROUGH),Bus/DevPciRaw.cpp,) \
   	Graphics/DevVGA.cpp \
   	Input/DevPS2.cpp \
Index: /trunk/src/VBox/Devices/testcase/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Devices/testcase/Makefile.kmk	(revision 35884)
+++ /trunk/src/VBox/Devices/testcase/Makefile.kmk	(revision 35885)
@@ -40,5 +40,7 @@
 	$(if $(VBOX_WITH_VDMA),VBOX_WITH_VDMA,) \
 	$(if $(VBOX_WITH_WDDM),VBOX_WITH_WDDM,) \
-	$(if $(VBOX_WITH_VIDEOHWACCEL),VBOX_WITH_VIDEOHWACCEL,)
+	$(if $(VBOX_WITH_VIDEOHWACCEL),VBOX_WITH_VIDEOHWACCEL,) \
+	$(if $(VBOX_WITH_PCI_PASSTHROUGH),VBOX_WITH_PCI_PASSTHROUGH,)
+
 
 #
Index: /trunk/src/VBox/Devices/testcase/tstDeviceStructSize.cpp
===================================================================
--- /trunk/src/VBox/Devices/testcase/tstDeviceStructSize.cpp	(revision 35884)
+++ /trunk/src/VBox/Devices/testcase/tstDeviceStructSize.cpp	(revision 35885)
@@ -85,4 +85,9 @@
 # undef LOG_GROUP
 # include "../Storage/DevLsiLogicSCSI.cpp"
+#endif
+
+#ifdef VBOX_WITH_PCI_PASSTHROUGH
+# undef LOG_GROUP
+# include "../Bus/DevPciRaw.cpp"
 #endif
 
@@ -317,4 +322,7 @@
     CHECK_MEMBER_ALIGNMENT(VPCISTATE, Queues, 8);
 #endif
+#ifdef VBOX_WITH_PCI_PASSTHROUGH
+    CHECK_MEMBER_ALIGNMENT(PCIRAWSENDREQ, u.aGetRegionInfo.u64RegionSize, 8);
+#endif
 
 #ifdef VBOX_WITH_RAW_MODE
@@ -335,3 +343,2 @@
     return rc;
 }
-
Index: /trunk/src/VBox/Frontends/VBoxShell/vboxshell.py
===================================================================
--- /trunk/src/VBox/Frontends/VBoxShell/vboxshell.py	(revision 35884)
+++ /trunk/src/VBox/Frontends/VBoxShell/vboxshell.py	(revision 35885)
@@ -3103,4 +3103,11 @@
     return
 
+def parsePci(str):
+    pcire = re.compile(r'(?P<b>\d+):(?P<d>\d+)\.(?P<f>\d)')
+    m = pcire.search(str)
+    if m is None:
+        return -1
+    dict = m.groupdict()
+    return ((int(dict['b'])) << 8) | ((int(dict['d'])) << 3) | int(dict['f'])
 
 def lspciCmd(ctx, args):
@@ -3112,4 +3119,41 @@
         return 0
     cmdExistingVm(ctx, mach, 'guestlambda', [lambda ctx,mach,console,args:  lspci(ctx, console)])
+    return 0
+
+def attachpciCmd(ctx, args):
+    if (len(args) < 3):
+        print "usage: attachpci vm hostpci <guestpci>"
+        return 0
+    mach = argsToMach(ctx,args)
+    if mach == None:
+        return 0
+    hostaddr = parsePci(args[2])
+    if hostaddr == -1:
+        print "invalid host PCI %s, accepted format 01:02.3 for bus 1, device 2, function 3" %(args[2])
+        return 0
+
+    if (len(args) > 3):
+        guestaddr = parsePci(args[3])
+        if guestaddr == -1:
+            print "invalid guest PCI %s, accepted format 01:02.3 for bus 1, device 2, function 3" %(args[3])
+            return 0
+    else:
+        guestaddr = hostaddr
+    cmdClosedVm(ctx, mach, lambda ctx,mach,a: mach.attachHostPciDevice(hostaddr, guestaddr, True))
+    return 0
+
+def detachpciCmd(ctx, args):
+    if (len(args) < 3):
+        print "usage: detachpci vm hostpci"
+        return 0
+    mach = argsToMach(ctx,args)
+    if mach == None:
+        return 0
+    hostaddr = parsePci(args[2])
+    if hostaddr == -1:
+        print "invalid host PCI %s, accepted format 01:02.3 for bus 1, device 2, function 3" %(args[2])
+        return 0
+
+    cmdClosedVm(ctx, mach, 'guestlambda', lambda ctx,mach,a: mach.detachHostPciDevice(hostaddr))
     return 0
 
@@ -3200,5 +3244,7 @@
             'recordDemo':['Record demo: recordDemo Win32 file.dmo 10', recordDemoCmd, 0],
             'playbackDemo':['Playback demo: playbackDemo Win32 file.dmo 10', playbackDemoCmd, 0],
-            'lspci': ['List PCI devices attached to the VM: lspci Win32', lspciCmd]
+            'lspci': ['List PCI devices attached to the VM: lspci Win32', lspciCmd, 0],
+            'attachpci': ['Attach host PCI device to the VM: attachpci Win32 01:00.0', attachpciCmd, 0],
+            'detachpci': ['Detach host PCI device from the VM: detachpci Win32 01:00.0', detachpciCmd, 0]
             }
 
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 35884)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 35885)
@@ -481,4 +481,11 @@
       -->
     </const>
+    <const name="v1_12"     value="14">
+      <desc>Settings version "1.12", written by VirtualBox 4.1.x.</desc>
+      <!--
+          Machine changes: raw PCI device atatchment.
+      -->
+    </const>
+
     <const name="Future"     value="99999">
       <desc>Settings version greater than "1.11", written by a future VirtualBox version.</desc>
Index: /trunk/src/VBox/Main/include/PciDeviceAttachmentImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/PciDeviceAttachmentImpl.h	(revision 35884)
+++ /trunk/src/VBox/Main/include/PciDeviceAttachmentImpl.h	(revision 35885)
@@ -22,4 +22,5 @@
 
 #include "VirtualBoxBase.h"
+#include <VBox/settings.h>
 
 class ATL_NO_VTABLE PciAddress :
@@ -109,5 +110,11 @@
                  LONG          aGuestAddress,
                  BOOL          fPhysical);
+
     void uninit();
+
+    // settings
+    HRESULT loadSettings(IMachine * aParent,
+                         const settings::HostPciDeviceAttachment& aHpda);
+    HRESULT saveSettings(settings::HostPciDeviceAttachment &data);
 
     HRESULT FinalConstruct();
@@ -122,5 +129,5 @@
 private:
     struct Data;
-    Data *m;
+    Data*  m;
 };
 
Index: /trunk/src/VBox/Main/src-all/PciDeviceAttachmentImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-all/PciDeviceAttachmentImpl.cpp	(revision 35884)
+++ /trunk/src/VBox/Main/src-all/PciDeviceAttachmentImpl.cpp	(revision 35885)
@@ -33,4 +33,5 @@
           fPhysical(afPhysical)
     {
+        (void)aParent;
         DevName = aDevName;
     }
@@ -69,4 +70,22 @@
 
     return m != NULL ? S_OK : E_FAIL;
+}
+
+HRESULT PciDeviceAttachment::loadSettings(IMachine *aParent,
+                                          const settings::HostPciDeviceAttachment &hpda)
+{
+    Bstr bname(hpda.strDeviceName);
+    return init(aParent, bname,  hpda.uHostAddress, hpda.uGuestAddress, TRUE);
+}
+
+
+HRESULT PciDeviceAttachment::saveSettings(settings::HostPciDeviceAttachment &data)
+{
+    Assert(m);
+    data.uHostAddress = m->HostAddress;
+    data.uGuestAddress = m->GuestAddress;
+    data.strDeviceName = m->DevName;
+
+    return S_OK;
 }
 
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 35884)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 35885)
@@ -1734,5 +1734,11 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    mBusMgr->listAttachedPciDevices(ComSafeArrayOutArg(aAttachments));
+    if (mBusMgr)
+        mBusMgr->listAttachedPciDevices(ComSafeArrayOutArg(aAttachments));
+    else
+    {
+        com::SafeIfaceArray<IPciDeviceAttachment> result(0);
+        result.detachTo(ComSafeArrayOutArg(aAttachments));            
+    }
 
     return S_OK;
Index: /trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 35884)
+++ /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 35885)
@@ -5829,6 +5829,6 @@
         AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-        //HRESULT rc = checkStateDependency(MutableStateDep);
-        //if (FAILED(rc)) return rc;
+        HRESULT rc = checkStateDependency(MutableStateDep);
+        if (FAILED(rc)) return rc;
 
         ComObjPtr<PciDeviceAttachment> pda;
@@ -5843,8 +5843,4 @@
         mHWData->mPciDeviceAssignments.push_back(pda);
     }
-
-    // do we need it?
-    //saveSettings(NULL);
-    mHWData.commit();
 
     return S_OK;
@@ -5887,9 +5883,4 @@
             }
         }
-        // Indeed under lock?
-        mHWData.commit();
-
-        // do we need it?
-        // saveSettings(NULL);
     }
 
@@ -7451,4 +7442,17 @@
         rc = mBandwidthControl->loadSettings(data.ioSettings);
         if (FAILED(rc)) return rc;
+
+        // Host PCI devices
+        for (settings::HostPciDeviceAttachmentList::const_iterator it = data.pciAttachments.begin();
+             it != data.pciAttachments.end();
+             ++it)
+        {
+            const settings::HostPciDeviceAttachment &hpda = *it;
+            ComObjPtr<PciDeviceAttachment> pda;
+
+            pda.createObject();
+            pda->loadSettings(this, hpda);
+            mHWData->mPciDeviceAssignments.push_back(pda);
+        }
 
 #ifdef VBOX_WITH_GUEST_PROPS
@@ -8530,4 +8534,19 @@
         rc = mBandwidthControl->saveSettings(data.ioSettings);
         if (FAILED(rc)) throw rc;
+
+        /* Host PCI devices */
+        for (HWData::PciDeviceAssignmentList::const_iterator it = mHWData->mPciDeviceAssignments.begin();
+             it != mHWData->mPciDeviceAssignments.end();
+             ++it)
+        {
+            ComObjPtr<PciDeviceAttachment> pda = *it;
+            settings::HostPciDeviceAttachment hpda;
+
+            rc = pda->saveSettings(hpda);
+            if (FAILED(rc)) throw rc;
+
+            data.pciAttachments.push_back(hpda);
+        }
+
 
         // guest properties
Index: /trunk/src/VBox/Main/xml/Settings.cpp
===================================================================
--- /trunk/src/VBox/Main/xml/Settings.cpp	(revision 35884)
+++ /trunk/src/VBox/Main/xml/Settings.cpp	(revision 35885)
@@ -91,5 +91,5 @@
 
 /** VirtualBox XML settings version number substring ("x.y")  */
-#define VBOX_XML_VERSION        "1.11"
+#define VBOX_XML_VERSION        "1.12"
 
 /** VirtualBox XML settings version platform substring */
@@ -320,5 +320,7 @@
                 else if (ulMinor == 11)
                     m->sv = SettingsVersion_v1_11;
-                else if (ulMinor > 11)
+                else if (ulMinor == 12)
+                    m->sv = SettingsVersion_v1_12;
+                else if (ulMinor > 12)
                     m->sv = SettingsVersion_Future;
             }
@@ -340,5 +342,5 @@
         // creating new settings file:
         m->strSettingsVersionFull = VBOX_XML_VERSION_FULL;
-        m->sv = SettingsVersion_v1_11;
+        m->sv = SettingsVersion_v1_12;
     }
 }
@@ -818,9 +820,13 @@
             break;
 
+        case SettingsVersion_v1_12:
+            pcszVersion = "1.12";
+            break;
+
         case SettingsVersion_Future:
             // can be set if this code runs on XML files that were created by a future version of VBox;
             // in that case, downgrade to current version when writing since we can't write future versions...
-            pcszVersion = "1.11";
-            m->sv = SettingsVersion_v1_10;
+            pcszVersion = "1.12";
+            m->sv = SettingsVersion_v1_12;
         break;
 
@@ -846,5 +852,5 @@
  * set the "sv" member to the required settings version that is to
  * be written. For newly created files, the settings version will be
- * the latest (1.11); for files read in from disk earlier, it will be
+ * the latest (1.12); for files read in from disk earlier, it will be
  * the settings version indicated in the file. However, this method
  * will silently make sure that the settings version is always
@@ -1648,4 +1654,5 @@
                   && (strNotificationPatterns   == h.strNotificationPatterns)
                   && (ioSettings                == h.ioSettings)
+                  && (pciAttachments            == h.pciAttachments)
                 )
             );
@@ -2717,4 +2724,27 @@
                     pelmBandwidthGroup->getAttributeValue("maxMbPerSec", gr.cMaxMbPerSec);
                     hw.ioSettings.llBandwidthGroups.push_back(gr);
+                }
+            }
+        }  else if (pelmHwChild->nameEquals("HostPci")) {
+            const xml::ElementNode *pelmDevices;
+
+            if ((pelmDevices = pelmHwChild->findChildElement("Devices")))
+            {
+                xml::NodesLoop nl2(*pelmDevices, "Device");
+                const xml::ElementNode *pelmDevice;
+                while ((pelmDevice = nl2.forAllNodes()))
+                {
+                    HostPciDeviceAttachment hpda;
+
+                    if (!pelmDevice->getAttributeValue("host", hpda.uHostAddress))
+                         throw ConfigFileError(this, pelmDevice, N_("Missing Device/@host attribute"));
+
+                    if (!pelmDevice->getAttributeValue("host", hpda.uGuestAddress))
+                         throw ConfigFileError(this, pelmDevice, N_("Missing Device/@guest attribute"));
+
+                    /* name is optional */
+                    pelmDevice->getAttributeValue("name", hpda.strDeviceName);
+
+                    hw.pciAttachments.push_back(hpda);
                 }
             }
@@ -3863,4 +3893,23 @@
     }
 
+    if (m->sv >= SettingsVersion_v1_12)
+    {
+        xml::ElementNode *pelmPci = pelmHardware->createChild("HostPci");
+        xml::ElementNode *pelmPciDevices = pelmPci->createChild("Devices");
+
+        for (HostPciDeviceAttachmentList::const_iterator it = hw.pciAttachments.begin();
+             it != hw.pciAttachments.end();
+             ++it)
+        {
+            const HostPciDeviceAttachment &hpda = *it;
+
+            xml::ElementNode *pelmThis = pelmPciDevices->createChild("Device");
+
+            pelmThis->setAttribute("host",  hpda.uHostAddress);
+            pelmThis->setAttribute("guest", hpda.uGuestAddress);
+            pelmThis->setAttribute("name",  hpda.strDeviceName);
+        }
+    }
+
     xml::ElementNode *pelmGuest = pelmHardware->createChild("Guest");
     pelmGuest->setAttribute("memoryBalloonSize", hw.ulMemoryBalloonSize);
@@ -4418,4 +4467,11 @@
 void MachineConfigFile::bumpSettingsVersionIfNeeded()
 {
+    if (m->sv < SettingsVersion_v1_12)
+    {
+        // VirtualBox 4.1 adds PCI passthrough
+        if (hardwareMachine.pciAttachments.size())
+            m->sv = SettingsVersion_v1_12;
+    }
+
     if (m->sv < SettingsVersion_v1_11)
     {
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 35884)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 35885)
@@ -143,5 +143,5 @@
                                 }
                             }
-                            
+
                             /* bail out */
                             LogFlow(("ModuleTerm: returns %Rrc\n", rc));
@@ -192,5 +192,5 @@
     PGMR0DynMapTerm();
 #endif
-        
+
 #ifdef VBOX_WITH_PCI_PASSTHROUGH
     /*
