Querying the PCCT in Python

The Platform Communication Channel Table contains information used to send messages in a shared memory buffer between the Operating System and other subsystems on the platform. Typically, the Channel has an interrupt defined that is used to tell the other subsystem that there is new data available.

Recently, I’ve been working with a couple entries that are of a newer type. In addition to the shared memory region and the interrupt values, the PCCT entries for type 3 and type 4 channels also have a series of registers. Where before the PCCT entries were normalized, now they are hierarchical. This makes them a little harder to scan with the human eye to confirm that the proper values have been recorded and read.

To simplify development, I build a simple script.

#!/usr/bin/python3

import json

import pdb

pcct = dict()

def to_json():
        current = pcct
        parent = pcct
        with open("pcct.dsl", "r") as f:
                for line in f:
                        if line.startswith("["):
                                index = line.find("]")
                                data = line[index +1:]  
                                index = data.find(":")
                                key = data[0:index].strip()
                                value = data[index+1:].strip()
                                
                                if (key == 'Subtable Type'):
                                        #subcount = 1
                                        parent = dict()
                                        subtables = pcct.get('subtables',[])
                                        subtables.append(parent)
                                        current = parent
                                        pcct['subtables'] = subtables
                                elif value == "[Generic Address Structure]": 
                                        current = dict()
                                        parent[key] = current
                                current[key] = value


def report_on_pcct():
        for sub in pcct['subtables']:
                sub_type = sub['Subtable Type']
                if sub_type.startswith('03') or sub_type.startswith('04'):
                        print(sub_type)
                        print( "  %29s       = %s" % ( "Base Address", sub.get('Base Address',"unset")))
                        print( "  %29s       = %s" % ( "Platform Interrupt ", sub.get('Platform Interrupt',"unset")))
                        for key, value in sub.items():
                                if isinstance(value, dict):
                                        if value.get(key, '') == "[Generic Address Structure]":
                                                print( "  %29s Address      = %s" % ( key, value.get('Address',"unset")))
                                                for k2, v2 in value.items():
                                                        if k2.endswith('Mask'):
                                                                print( "  %29s              = %s" % ( k2, v2))

to_json()                               
print(json.dumps(pcct, indent =2))
report_on_pcct()

Even in a simple script like this, I tend to iterate. My origianl intention was to merely convert the PCCT to JSON and then use jq to query it. Halfway through I realized it was easier to do the query in python. So, while I am still outputing the whole table in JSON, I display the values I actually care about underneath it.

Here is some of the output from a sample run:

03 [Extended PCC Master Subspace]
                   Base Address       = 00004000000D4004
            Platform Interrupt        = 0000002E
              Doorbell Register Address      = 00004000006B6010
                  Preserve Mask              = 0000000000000000
                     Write Mask              = 0000000000000000
          Platform ACK Register Address      = 00004000006B6020
              ACK Preserve Mask              = 0000000000000000
                   ACK Set Mask              = 0000000000000001
      Command Complete Register Address      = 00004000000D4000
    Command Complete Check Mask              = 0000000000000001
        Command Update Register Address      = 00004000000D4000
   Command Update Preserve Mask              = 0000000000FF0004
        Command Update Set Mask              = 0000000000000000
          Error Status Register Address      = 00004000000D4000
              Error Status Mask              = 0000000000000004

I made an effort at lining up the output values. Aside from neatness, it makes it easier to scan down the column.

Writing this allowed us to zoom in on the fact that the preserve and write masks were both 0. This was quickly confirmed to be correct. This is not the final set of values for this table, just an interim copy that we checked.

This script is a good example of Data munging. The idea is that it is a four stage process: read, convert to a standard form, query. The standard internal form means you can mix and match on the reading and the query portions with other code should you with to do so.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.