Skip to content
Permalink
Browse files
WIP: soc: apple: rtkit: Add RTKit library
Signed-off-by: Sven Peter <sven@svenpeter.dev>
  • Loading branch information
svenpeter42 committed Dec 9, 2021
1 parent 1d19a31 commit fd7c0ced9b5e58028c66dde6cb54fa61a19283b9
Show file tree
Hide file tree
Showing 6 changed files with 1,262 additions and 0 deletions.
@@ -16,6 +16,17 @@ config APPLE_PMGR_PWRSTATE
controls for SoC devices. This driver manages them through the
generic power domain framework, and also provides reset support.

config APPLE_RTKIT
bool "Apple RTKit co-processor IPC protocol"
depends on ARCH_APPLE || COMPILE_TEST
default ARCH_APPLE
help
Apple SoCs such as the M1 come with various co-processors running
their proprietary RTKit operating system. This option enables support
for the common IPC protocl used by these.

Say 'y' here if you have an Apple SoC.

config APPLE_SART
bool "Apple SART DMA address filter"
depends on ARCH_APPLE || COMPILE_TEST
@@ -1,5 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_APPLE_PMGR_PWRSTATE) += apple-pmgr-pwrstate.o

obj-$(CONFIG_APPLE_RTKIT) += apple-rtkit.o
apple-rtkit-y = rtkit.o rtkit-crashlog.o

obj-$(CONFIG_APPLE_SART) += apple-sart.o
apple-sart-y = sart.o
@@ -0,0 +1,142 @@
#include "rtkit-internal.h"

#define FOURCC(a, b, c, d) \
(((u32)(a) << 24) | ((u32)(b) << 16) | ((u32)(c) << 8) | ((u32)(d)))

#define APPLE_RTKIT_CRASHLOG_HEADER FOURCC('C', 'L', 'H', 'E')
#define APPLE_RTKIT_CRASHLOG_STR FOURCC('C', 's', 't', 'r')
#define APPLE_RTKIT_CRASHLOG_VERSION FOURCC('C', 'v', 'e', 'r')
#define APPLE_RTKIT_CRASHLOG_MBOX FOURCC('C', 'm', 'b', 'x')
#define APPLE_RTKIT_CRASHLOG_TIME FOURCC('C', 't', 'i', 'm')

struct apple_rtkit_crashlog_header {
u32 fourcc;
u32 version;
u32 size;
u32 flags;
u8 _unk[16];
};
static_assert(sizeof(struct apple_rtkit_crashlog_header) == 0x20);

struct apple_rtkit_crashlog_mbox_entry {
u64 msg0;
u64 msg1;
u32 timestamp;
u8 _unk[4];
};
static_assert(sizeof(struct apple_rtkit_crashlog_mbox_entry) == 0x18);

static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr,
size_t size)
{
u32 idx;
u8 *ptr, *end;

memcpy(&idx, bfr, 4);

ptr = bfr + 4;
end = bfr + size;
while (ptr < end) {
u8 *newline = memchr(ptr, '\n', end - ptr);

if (newline) {
u8 tmp = *newline;
*newline = '\0';
rtk_warn("Message (id=%x): %s\n", idx, ptr);
*newline = tmp;
ptr = newline + 1;
} else {
rtk_warn("Message (id=%x): %s", idx, ptr);
break;
}
}
}

static void apple_rtkit_crashlog_dump_version(struct apple_rtkit *rtk, u8 *bfr,
size_t size)
{
rtk_warn("Version: %s", bfr + 16);
}

static void apple_rtkit_crashlog_dump_time(struct apple_rtkit *rtk, u8 *bfr,
size_t size)
{
u64 crash_time;

memcpy(&crash_time, bfr, 8);
rtk_warn("Crash time: %lld", crash_time);
}

static void apple_rtkit_crashlog_dump_mailbox(struct apple_rtkit *rtk, u8 *bfr,
size_t size)
{
u32 type, index, i;
size_t n_messages;
struct apple_rtkit_crashlog_mbox_entry entry;

memcpy(&type, bfr + 16, 4);
memcpy(&index, bfr + 24, 4);
n_messages = (size - 28) / sizeof(entry);

rtk_warn("Mailbox history (type = %d, index = %d)", type, index);
for (i = 0; i < n_messages; ++i) {
memcpy(&entry, bfr + 28 + i * sizeof(entry), sizeof(entry));
rtk_warn(" #%03d@%08x: %016llx %016llx", i, entry.timestamp,
entry.msg0, entry.msg1);
}
}

void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size)
{
size_t offset;
u32 section_fourcc, section_size;
struct apple_rtkit_crashlog_header header;

memcpy(&header, bfr, sizeof(header));
if (header.fourcc != APPLE_RTKIT_CRASHLOG_HEADER) {
rtk_warn("Expected crashlog header but got %x", header.fourcc);
return;
}

if (header.size > size) {
rtk_warn("Crashlog size (%x) is too large", header.size);
return;
}

size = header.size;
offset = sizeof(header);

while (offset < size) {
memcpy(&section_fourcc, bfr + offset, 4);
memcpy(&section_size, bfr + offset + 12, 4);

switch (section_fourcc) {
case APPLE_RTKIT_CRASHLOG_HEADER:
rtk_dbg("End of crashlog reached");
return;
case APPLE_RTKIT_CRASHLOG_STR:
apple_rtkit_crashlog_dump_str(rtk, bfr + offset + 16,
section_size);
break;
case APPLE_RTKIT_CRASHLOG_VERSION:
apple_rtkit_crashlog_dump_version(
rtk, bfr + offset + 16, section_size);
break;
case APPLE_RTKIT_CRASHLOG_MBOX:
apple_rtkit_crashlog_dump_mailbox(
rtk, bfr + offset + 16, section_size);
break;
case APPLE_RTKIT_CRASHLOG_TIME:
apple_rtkit_crashlog_dump_time(
rtk, bfr + offset + 16, section_size);
break;
default:
rtk_warn("Unknown crashlog section: %x",
section_fourcc);
}

offset += section_size;
}

rtk_warn("End of crashlog reached but no footer present");
}
@@ -0,0 +1,77 @@
#ifndef _APPLE_RTKIT_INTERAL_H
#define _APPLE_RTKIT_INTERAL_H

#include <linux/apple-mailbox.h>
#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/kthread.h>
#include <linux/kfifo.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/soc/apple/rtkit.h>
#include <linux/wait.h>

#define rtk_err(format, arg...) dev_err(rtk->dev, "RTKit: " format, ##arg)
#define rtk_warn(format, arg...) dev_warn(rtk->dev, "RTKit: " format, ##arg)
#define rtk_info(format, arg...) dev_info(rtk->dev, "RTKit: " format, ##arg)
#define rtk_dbg(format, arg...) dev_dbg(rtk->dev, "RTKit: " format, ##arg)


#define APPLE_RTKIT_APP_ENDPOINT_START 0x20
#define APPLE_RTKIT_MAX_ENDPOINTS 0x100

struct apple_rtkit_shmem {
void *buffer;
void __iomem *iomem;
size_t size;
dma_addr_t iova;
};

struct apple_rtkit_work {
unsigned type;
struct apple_mbox_msg msg;
};

struct apple_rtkit {
void *cookie;
const struct apple_rtkit_ops *ops;
struct device *dev;
struct mbox_client mbox_cl;
struct mbox_chan *mbox_chan;

struct completion epmap_completion;
struct completion reinit_completion;
struct completion iop_pwr_ack_completion;
struct completion ap_pwr_ack_completion;

int boot_result;
int version;

unsigned iop_power_state;
unsigned ap_power_state;
bool crashed;

struct task_struct *task;

struct wait_queue_head wq;
DECLARE_KFIFO(work_fifo, struct apple_rtkit_work, 64);
spinlock_t work_lock;

DECLARE_BITMAP(endpoints, APPLE_RTKIT_MAX_ENDPOINTS);

struct apple_rtkit_shmem ioreport_buffer;
struct apple_rtkit_shmem crashlog_buffer;

struct apple_rtkit_shmem syslog_buffer;
char *syslog_msg_buffer;
size_t syslog_n_entries;
size_t syslog_msg_size;
};

void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size);

#endif

0 comments on commit fd7c0ce

Please sign in to comment.