Faking a device via ACPI

I need to write a driver for a device that does not exist yet. So, I am going to use the Linux kernel tooling fro ACPI to create the illusion that the device exists. Here is how.

Devices on an ACPI enabled Linux machine typically exist in a able called the DSDT. This has a real name, but I just thing of it as “Different Stuff Different Table”. However, you can also have a machine specific table that you create at boot time and put entries in there. This is called the SSDT. Again, it has a real name, but I just think of it as “Same Device Different Table” Here is my simple SSDT definition in the ACPI domain specific language.

 /*
 * Template for [SSDT] ACPI Table (AML byte code table)
 */
DefinitionBlock("","SSDT", 2, "Ampere", "_SSDT_01", 0x00000001)
{

    Scope(\_SB)
    {
       Device(MCTP)
       {
           Name (_HID, "MCTPA1B2")

           Name (_STA, 0x0F)
       }
       Device(PLDM)
       {
           Name (_HID, "PLDMA1B2")

           Name (_STA, 0x0F)
       }
       Device(PSTL)
       {
           Name (_HID, "POSTA1B2")

           Name (_STA, 0x0F)
       }
     }

}

Now, this actually has three devices in it, and I was doing some unit testing setup with dependent devices so I though I might use the other ones. I left them in as an example to show how multiple devices look in an SSDT.

To convert this to the binary format, I use iasl, a utility in the acpica-tools RPM. Yes, I still do RPM, although all of this works on Debian based systems as well.

Here is my script to load it into the Linux kernel. It uses a module for the ACPI configuration filesystem.

#! /bin/sh 
modprobe acpi_configfs
mkdir /sys/kernel/config/acpi/table/ssdd
cat ~/acpi/bak/mctpdev.aml > /sys/kernel/config/acpi/table/ssdd/aml

To confirm that the file exists, you can use the acpidump command. If you run it with the -b flag you get all the tables in binary format.

[root@hackery tmp]# mkdir acpi
[root@hackery tmp]# cd acpi/
[root@hackery acpi]# acpidump -b

The iasl command will then decompile the table and you can view the contents. I’ll leave you with the full content.

[root@hackery acpi]# iasl ssdt.dat 

Intel ACPI Component Architecture
ASL+ Optimizing Compiler/Disassembler version 20220331
Copyright (c) 2000 - 2022 Intel Corporation

File appears to be binary: found 31 non-ASCII characters, disassembling
Binary file appears to be a valid ACPI table, disassembling
Input file ssdt.dat, Length 0x83 (131) bytes
ACPI: SSDT 0x0000000000000000 000083 (v02 Ampere _SSDT_01 00000001 INTL 20220331)
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)

Parsing completed
Disassembly completed
ASL Output:    ssdt.dsl - 1141 bytes
[root@hackery acpi]# cat ssdt.dsl 
/*
 * Intel ACPI Component Architecture
 * AML/ASL+ Disassembler version 20220331 (64-bit version)
 * Copyright (c) 2000 - 2022 Intel Corporation
 * 
 * Disassembling to symbolic ASL+ operators
 *
 * Disassembly of ssdt.dat, Sat Jul  8 04:42:31 2023
 *
 * Original Table Header:
 *     Signature        "SSDT"
 *     Length           0x00000083 (131)
 *     Revision         0x02
 *     Checksum         0xCE
 *     OEM ID           "Ampere"
 *     OEM Table ID     "_SSDT_01"
 *     OEM Revision     0x00000001 (1)
 *     Compiler ID      "INTL"
 *     Compiler Version 0x20220331 (539099953)
 */
DefinitionBlock ("", "SSDT", 2, "Ampere", "_SSDT_01", 0x00000001)
{
    Scope (\_SB)
    {
        Device (MCTP)
        {
            Name (_HID, "MCTPA1B2")  // _HID: Hardware ID
            Name (_STA, 0x0F)  // _STA: Status
        }

        Device (PLDM)
        {
            Name (_HID, "PLDMA1B2")  // _HID: Hardware ID
            Name (_STA, 0x0F)  // _STA: Status
        }

        Device (PSTL)
        {
            Name (_HID, "POSTA1B2")  // _HID: Hardware ID
            Name (_STA, 0x0F)  // _STA: Status
        }
    }
}

Opening the perf file descriptor

A couple months back I recorded this line on my blog as part of investigating perf:

perf record --branch-filter any,save_type,u true 

What is the interface between the perf binary and the linux Kernel when I run this? There is a system call to open a file handle. The man page says this:

int syscall(SYS_perf_event_open, struct perf_event_attr *attr,
                    pid_t pid, int cpu, int group_fd, 
                    unsigned long flags);


But how does that get called by the perf binary…the answer is trickier than I originally thought.

Continue reading

Testing an MCTP Driver via Echo request

MCTP stands for Management Component Transport Protocol. While it is designed around a server, it is also designed as a network protocol. As such, the Linux implementation makes use of the Socket interface and the Kernel plumbing for dealing with network protocols. To support a new transport mechanism, you implement a new device driver specific to that transport mechanism that implements the struct net_device contract, which includes implementing the functions for struct net_device_ops.

Before I write a full implementation, I want to write something that only echos a packet back to the receiver. This mimics the behavior of the mctp-echo server in the user tools, and can make use of the mctp-req echo client.

Continue reading

Remote git with ssh

Working on a different architecture from my Laptop means that I am invariably working on a remote machine. My current development can be done on an Ampere AltraMax machine, which means I have 80 processors available; quite a nice benefit when doing a Linux Kernel compile that can use all of the processors available.

Because the machine is a shared resource out of out lab, I want to make sure I can recreate my work there on another machine; this one could be reclaimed or powered down due to lab priorities. Thus, all my remote work is done in git, and I use the ssh protocol to pull changes from my work server to my laptop fairly regularly…whenever I feel I have valuable work that could be potentially lost.

Continue reading