WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] XenAPI: Add Physical PCI Device (PPCI) Su

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] XenAPI: Add Physical PCI Device (PPCI) Support
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 03 Jul 2008 06:30:19 -0700
Delivery-date: Thu, 03 Jul 2008 06:31:05 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1215077176 -3600
# Node ID e65fe28b52887ffe61750474835cbd0afe8ccd48
# Parent  3d5f28d6e77711d3b5adb8fd75cd05fe0537302d
XenAPI: Add Physical PCI Device (PPCI) Support

Signed-off-by: Yosuke Iwamatsu <y-iwamatsu@xxxxxxxxxxxxx>
---
 tools/python/xen/util/pci.py      |  115 ++++++++++++++++++++++++++-
 tools/python/xen/xend/XendAPI.py  |   13 ++-
 tools/python/xen/xend/XendNode.py |   54 ++++++++++++
 tools/python/xen/xend/XendPPCI.py |  158 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 334 insertions(+), 6 deletions(-)

diff -r 3d5f28d6e777 -r e65fe28b5288 tools/python/xen/util/pci.py
--- a/tools/python/xen/util/pci.py      Wed Jul 02 17:28:27 2008 +0100
+++ b/tools/python/xen/util/pci.py      Thu Jul 03 10:26:16 2008 +0100
@@ -8,6 +8,8 @@ import sys
 import sys
 import os, os.path
 import resource
+import re
+import types
 
 PROC_MNT_PATH = '/proc/mounts'
 PROC_PCI_PATH = '/proc/bus/pci/devices'
@@ -22,6 +24,9 @@ SYSFS_PCI_DEV_DEVICE_PATH = '/device'
 SYSFS_PCI_DEV_DEVICE_PATH = '/device'
 SYSFS_PCI_DEV_SUBVENDOR_PATH = '/subsystem_vendor'
 SYSFS_PCI_DEV_SUBDEVICE_PATH = '/subsystem_device'
+SYSFS_PCI_DEV_CLASS_PATH = '/class'
+
+LSPCI_CMD = 'lspci'
 
 PCI_BAR_IO = 0x01
 PCI_BAR_IO_MASK = ~0x03
@@ -32,6 +37,9 @@ MSIX_BIR_MASK = 0x7
 MSIX_BIR_MASK = 0x7
 MSIX_SIZE_MASK = 0x7ff
 
+# Global variable to store information from lspci
+lspci_info = None
+
 #Calculate PAGE_SHIFT: number of bits to shift an address to get the page 
number
 PAGE_SIZE = resource.getpagesize()
 PAGE_SHIFT = 0
@@ -45,6 +53,15 @@ def PCI_DEVFN(slot, func):
 def PCI_DEVFN(slot, func):
     return ((((slot) & 0x1f) << 3) | ((func) & 0x07))
 
+def parse_hex(val):
+    try:
+        if isinstance(val, types.StringTypes):
+            return int(val, 16)
+        else:
+            return val
+    except ValueError:
+        return None
+
 def find_sysfs_mnt():
     mounts_file = open(PROC_MNT_PATH,'r')
 
@@ -57,6 +74,61 @@ def find_sysfs_mnt():
             return sline[1]
 
     return None
+
+def get_all_pci_names():
+    try:
+        sysfs_mnt = find_sysfs_mnt()
+    except IOError, (errno, strerr):
+        raise PciDeviceParseError(('Failed to locate sysfs mount: %s (%d)' %
+            (PROC_PCI_PATH, strerr, errno)))
+
+    pci_names = os.popen('ls ' + sysfs_mnt + 
SYSFS_PCI_DEVS_PATH).read().split()
+
+    return pci_names
+
+def get_all_pci_devices():
+    pci_devs = []
+    for pci_name in get_all_pci_names():
+        pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
+                r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
+                r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
+                r"(?P<func>[0-7])$", pci_name)
+        if pci_match is None:
+            raise PciDeviceParseError(('Failed to parse pci device name: %s' %
+                pci_name))
+        pci_dev_info = pci_match.groupdict('0')
+        domain = parse_hex(pci_dev_info['domain'])
+        bus = parse_hex(pci_dev_info['bus'])
+        slot = parse_hex(pci_dev_info['slot'])
+        func = parse_hex(pci_dev_info['func'])
+        try:
+            pci_dev = PciDevice(domain, bus, slot, func)
+        except:
+            continue
+        pci_devs.append(pci_dev)
+
+    return pci_devs
+
+def create_lspci_info():
+    global lspci_info
+    lspci_info = {}
+
+    # Execute 'lspci' command and parse the result.
+    # If the command does not exist, lspci_info will be kept blank ({}).
+    for paragraph in os.popen(LSPCI_CMD + ' -vmmD').read().split('\n\n'):
+        device_name = None
+        device_info = {}
+        for line in paragraph.split('\n'):
+            try:
+                (opt, value) = line.split(':\t')
+                if opt == 'Slot':
+                    device_name = value
+                else:
+                    device_info[opt] = value
+            except:
+                pass
+        if device_name is not None:
+            lspci_info[device_name] = device_info
 
 class PciDeviceNotFoundError(Exception):
     def __init__(self,domain,bus,slot,func):
@@ -92,7 +164,15 @@ class PciDevice:
         self.subdevice = None
         self.msix = 0
         self.msix_iomem = []
+        self.revision = 0
+        self.classcode = None
+        self.vendorname = ""
+        self.devicename = ""
+        self.classname = ""
+        self.subvendorname = ""
+        self.subdevicename = ""
         self.get_info_from_sysfs()
+        self.get_info_from_lspci()
 
     def find_capability(self, type):
         try:
@@ -208,9 +288,8 @@ class PciDevice:
                 self.name+SYSFS_PCI_DEV_DRIVER_DIR_PATH
         try:
             self.driver = os.path.basename(os.readlink(path))
-        except IOError, (errno, strerr):
-            raise PciDeviceParseError(('Failed to read %s: %s (%d)' %
-                (path, strerr, errno)))
+        except OSError, (errno, strerr):
+            self.driver = ""
 
         path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
                 self.name+SYSFS_PCI_DEV_VENDOR_PATH
@@ -243,6 +322,36 @@ class PciDevice:
         except IOError, (errno, strerr):
             raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
                 (path, strerr, errno)))
+
+        path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
+                self.name+SYSFS_PCI_DEV_CLASS_PATH
+        try:
+            self.classcode = int(open(path,'r').readline(), 16)
+        except IOError, (errno, strerr):
+            raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
+                (path, strerr, errno)))
+
+        return True
+
+    def get_info_from_lspci(self):
+        """ Get information such as vendor name, device name, class name, etc.
+        Since we cannot obtain these data from sysfs, use 'lspci' command.
+        """
+        global lspci_info
+
+        if lspci_info is None:
+            create_lspci_info()
+
+        try:
+            device_info = lspci_info[self.name]
+            self.revision = int(device_info['Rev'], 16)
+            self.vendorname = device_info['Vendor']
+            self.devicename = device_info['Device']
+            self.classname = device_info['Class']
+            self.subvendorname = device_info['SVendor']
+            self.subdevicename = device_info['SDevice']
+        except KeyError:
+            pass
 
         return True
 
diff -r 3d5f28d6e777 -r e65fe28b5288 tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py  Wed Jul 02 17:28:27 2008 +0100
+++ b/tools/python/xen/xend/XendAPI.py  Thu Jul 03 10:26:16 2008 +0100
@@ -40,6 +40,7 @@ from XendVMMetrics import XendVMMetrics
 from XendVMMetrics import XendVMMetrics
 from XendPIF import XendPIF
 from XendPBD import XendPBD
+from XendPPCI import XendPPCI
 from XendXSPolicy import XendXSPolicy, XendACMPolicy
 
 from XendAPIConstants import *
@@ -476,7 +477,8 @@ classes = {
     'PIF'          : valid_object("PIF"),
     'VM_metrics'   : valid_object("VM_metrics"),
     'PBD'          : valid_object("PBD"),
-    'PIF_metrics'  : valid_object("PIF_metrics")
+    'PIF_metrics'  : valid_object("PIF_metrics"),
+    'PPCI'         : valid_object("PPCI"),
 }
 
 autoplug_classes = {
@@ -485,6 +487,7 @@ autoplug_classes = {
     'VM_metrics'  : XendVMMetrics,
     'PBD'         : XendPBD,
     'PIF_metrics' : XendPIFMetrics,
+    'PPCI'        : XendPPCI,
     'XSPolicy'    : XendXSPolicy,
     'ACMPolicy'   : XendACMPolicy,
 }
@@ -874,6 +877,7 @@ class XendAPI(object):
                     'resident_VMs',
                     'PBDs',
                     'PIFs',
+                    'PPCIs',
                     'host_CPUs',
                     'cpu_configuration',
                     'metrics',
@@ -952,6 +956,8 @@ class XendAPI(object):
         return xen_api_success(XendPBD.get_all())
     def host_get_PIFs(self, session, ref):
         return xen_api_success(XendNode.instance().get_PIF_refs())
+    def host_get_PPCIs(self, session, ref):
+        return xen_api_success(XendNode.instance().get_PPCI_refs())
     def host_get_host_CPUs(self, session, host_ref):
         return xen_api_success(XendNode.instance().get_host_cpu_refs())
     def host_get_metrics(self, _, ref):
@@ -1027,7 +1033,8 @@ class XendAPI(object):
                   'sched_policy': node.get_vcpus_policy(),
                   'logging': {},
                   'PIFs': XendPIF.get_all(),
-                  'PBDs': XendPBD.get_all()}
+                  'PBDs': XendPBD.get_all(),
+                  'PPCIs': XendPPCI.get_all()}
         return xen_api_success(record)
 
     # class methods
@@ -1288,7 +1295,7 @@ class XendAPI(object):
     def VM_get_consoles(self, session, vm_ref):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
         return xen_api_success(dom.get_consoles())
-    
+
     def VM_get_tools_version(self, session, vm_ref):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
         return dom.get_tools_version()
diff -r 3d5f28d6e777 -r e65fe28b5288 tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Wed Jul 02 17:28:27 2008 +0100
+++ b/tools/python/xen/xend/XendNode.py Thu Jul 03 10:26:16 2008 +0100
@@ -21,6 +21,7 @@ import xen.lowlevel.xc
 import xen.lowlevel.xc
 
 from xen.util import Brctl
+from xen.util import pci as PciUtil
 from xen.xend import XendAPIStore
 
 import uuid, arch
@@ -35,6 +36,7 @@ from XendNetwork import *
 from XendNetwork import *
 from XendStateStore import XendStateStore
 from XendMonitor import XendMonitor
+from XendPPCI import XendPPCI
      
 class XendNode:
     """XendNode - Represents a Domain 0 Host."""
@@ -49,6 +51,7 @@ class XendNode:
         * PIF_metrics
         * network
         * Storage Repository
+        * PPCI
         """
         
         self.xc = xen.lowlevel.xc.xc()
@@ -230,6 +233,41 @@ class XendNode:
                 except CreateUnspecifiedAttributeError:
                     log.warn("Error recreating PBD %s", pbd_uuid) 
 
+
+        # Initialise PPCIs
+        saved_ppcis = self.state_store.load_state('ppci')
+        saved_ppci_table = {}
+        if saved_ppcis:
+            for ppci_uuid, ppci_record in saved_ppcis.items():
+                try:
+                    saved_ppci_table[ppci_record['name']] = ppci_uuid
+                except KeyError:
+                    pass
+
+        for pci_dev in PciUtil.get_all_pci_devices():
+            ppci_record = {
+                'domain':                   pci_dev.domain,
+                'bus':                      pci_dev.bus,
+                'slot':                     pci_dev.slot,
+                'func':                     pci_dev.func,
+                'vendor_id':                pci_dev.vendor,
+                'vendor_name':              pci_dev.vendorname,
+                'device_id':                pci_dev.device,
+                'device_name':              pci_dev.devicename,
+                'revision_id':              pci_dev.revision,
+                'class_code':               pci_dev.classcode,
+                'class_name':               pci_dev.classname,
+                'subsystem_vendor_id':      pci_dev.subvendor,
+                'subsystem_vendor_name':    pci_dev.subvendorname,
+                'subsystem_id':             pci_dev.subdevice,
+                'subsystem_name':           pci_dev.subdevicename,
+                'driver':                   pci_dev.driver
+                }
+            # If saved uuid exists, use it. Otherwise create one.
+            ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
+            XendPPCI(ppci_uuid, ppci_record)
+
+
 ##    def network_destroy(self, net_uuid):
  ##       del self.networks[net_uuid]
   ##      self.save_networks()
@@ -270,6 +308,15 @@ class XendNode:
 
 ##         del self.pifs[pif_uuid]
 ##         self.save_PIFs()
+
+
+    def get_PPCI_refs(self):
+        return XendPPCI.get_all()
+
+    def get_ppci_by_uuid(self, ppci_uuid):
+        if ppci_uuid in self.get_PPCI_refs():
+            return ppci_uuid
+        return None
 
 
     def save(self):
@@ -284,6 +331,7 @@ class XendNode:
         self.save_networks()
         self.save_PBDs()
         self.save_SRs()
+        self.save_PPCIs()
 
     def save_PIFs(self):
         pif_records = dict([(pif_uuid, XendAPIStore.get(
@@ -307,6 +355,12 @@ class XendNode:
         sr_records = dict([(k, v.get_record(transient = False))
                             for k, v in self.srs.items()])
         self.state_store.save_state('sr', sr_records)
+
+    def save_PPCIs(self):
+        ppci_records = dict([(ppci_uuid, XendAPIStore.get(
+                                 ppci_uuid, "PPCI").get_record())
+                            for ppci_uuid in XendPPCI.get_all()])
+        self.state_store.save_state('ppci', ppci_records)
 
     def shutdown(self):
         return 0
diff -r 3d5f28d6e777 -r e65fe28b5288 tools/python/xen/xend/XendPPCI.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xend/XendPPCI.py Thu Jul 03 10:26:16 2008 +0100
@@ -0,0 +1,158 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Copyright (c) 2008 NEC Corporation
+#       Yosuke Iwamatsu <y-iwamatsu at ab jp nec com>
+#============================================================================
+
+from xen.xend.XendBase import XendBase
+from xen.xend.XendBase import XendAPIStore
+from xen.xend import uuid as genuuid
+
+class XendPPCI(XendBase):
+    """Representation of a physical PCI device."""
+
+    def getClass(self):
+        return "PPCI"
+
+    def getAttrRO(self):
+        attrRO = ['host',
+                  'domain',
+                  'bus',
+                  'slot',
+                  'func',
+                  'name',
+                  'vendor_id',
+                  'vendor_name',
+                  'device_id',
+                  'device_name',
+                  'revision_id',
+                  'class_code',
+                  'class_name',
+                  'subsystem_vendor_id',
+                  'subsystem_vendor_name',
+                  'subsystem_id',
+                  'subsystem_name',
+                  'driver']
+        return XendBase.getAttrRO() + attrRO
+
+    def getAttrRW(self):
+        attrRW = []
+        return XendBase.getAttrRW() + attrRW
+
+    def getAttrInst(self):
+        attrInst = []
+        return XendBase.getAttrInst() + attrInst
+
+    def getMethods(self):
+        methods = []
+        return XendBase.getMethods() + methods
+
+    def getFuncs(self):
+        funcs = []
+        return XendBase.getFuncs() + funcs
+
+    getClass    = classmethod(getClass)
+    getAttrRO   = classmethod(getAttrRO)
+    getAttrRW   = classmethod(getAttrRW)
+    getAttrInst = classmethod(getAttrInst)
+    getMethods  = classmethod(getMethods)
+    getFuncs    = classmethod(getFuncs)
+ 
+    def get_by_sbdf(self, domain, bus, slot, func):
+        for ppci in XendAPIStore.get_all("PPCI"):
+            if ppci.get_domain() == int(domain, 16) and \
+               ppci.get_bus() == int(bus, 16) and \
+               ppci.get_slot() == int(slot, 16) and \
+               ppci.get_func() == int(func, 16):
+                return ppci.get_uuid()
+        return None
+
+    get_by_sbdf = classmethod(get_by_sbdf)
+
+    def __init__(self, uuid, record):
+        self.domain = record['domain']
+        self.bus = record['bus']
+        self.slot = record['slot']
+        self.func = record['func']
+        self.vendor_id = record['vendor_id']
+        self.vendor_name = record['vendor_name']
+        self.device_id = record['device_id']
+        self.device_name = record['device_name']
+        self.revision_id = record['revision_id']
+        self.class_code = record['class_code']
+        self.class_name = record['class_name']
+        self.subsystem_vendor_id = record['subsystem_vendor_id']
+        self.subsystem_vendor_name = record['subsystem_vendor_name']
+        self.subsystem_id = record['subsystem_id']
+        self.subsystem_name = record['subsystem_name']
+        self.driver = record['driver']
+        XendBase.__init__(self, uuid, record)
+
+    def get_host(self):
+        from xen.xend import XendNode
+        return XendNode.instance().get_uuid()
+
+    def get_domain(self):
+        return self.domain
+
+    def get_bus(self):
+        return self.bus
+
+    def get_slot(self):
+        return self.slot
+
+    def get_func(self):
+        return self.func
+
+    def get_name(self):
+        return "%04x:%02x:%02x.%01x" % (self.domain, self.bus, self.slot,
+                                        self.func)
+
+    def get_vendor_id(self):
+        return self.vendor_id
+
+    def get_vendor_name(self):
+        return self.vendor_name
+
+    def get_device_id(self):
+        return self.device_id
+
+    def get_device_name(self):
+        return self.device_name
+
+    def get_class_code(self):
+        return self.class_code
+
+    def get_class_name(self):
+        return self.class_name
+
+    def get_revision_id(self):
+        return self.revision_id
+
+    def get_subsystem_vendor_id(self):
+        return self.subsystem_vendor_id
+
+    def get_subsystem_vendor_name(self):
+        return self.subsystem_vendor_name
+
+    def get_subsystem_id(self):
+        return self.subsystem_id
+
+    def get_subsystem_name(self):
+        return self.subsystem_name
+
+    def get_driver(self):
+        return self.driver
+

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] XenAPI: Add Physical PCI Device (PPCI) Support, Xen patchbot-unstable <=