// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) IBM Corporation, 2024 */ #define pr_fmt(fmt) "htmdump: " fmt #include #include #include #include #include static void *htm_buf; static u32 nodeindex; static u32 nodalchipindex; static u32 coreindexonchip; static u32 htmtype; static struct dentry *htmdump_debugfs_dir; static ssize_t htmdump_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) { void *htm_buf = filp->private_data; unsigned long page, read_size, available; loff_t offset; long rc; page = ALIGN_DOWN(*ppos, PAGE_SIZE); offset = (*ppos) % PAGE_SIZE; rc = htm_get_dump_hardware(nodeindex, nodalchipindex, coreindexonchip, htmtype, virt_to_phys(htm_buf), PAGE_SIZE, page); switch (rc) { case H_SUCCESS: /* H_PARTIAL for the case where all available data can't be * returned due to buffer size constraint. */ case H_PARTIAL: break; /* H_NOT_AVAILABLE indicates reading from an offset outside the range, * i.e. past end of file. */ case H_NOT_AVAILABLE: return 0; case H_BUSY: case H_LONG_BUSY_ORDER_1_MSEC: case H_LONG_BUSY_ORDER_10_MSEC: case H_LONG_BUSY_ORDER_100_MSEC: case H_LONG_BUSY_ORDER_1_SEC: case H_LONG_BUSY_ORDER_10_SEC: case H_LONG_BUSY_ORDER_100_SEC: return -EBUSY; case H_PARAMETER: case H_P2: case H_P3: case H_P4: case H_P5: case H_P6: return -EINVAL; case H_STATE: return -EIO; case H_AUTHORITY: return -EPERM; } available = PAGE_SIZE; read_size = min(count, available); *ppos += read_size; return simple_read_from_buffer(ubuf, count, &offset, htm_buf, available); } static const struct file_operations htmdump_fops = { .llseek = NULL, .read = htmdump_read, .open = simple_open, }; static int htmdump_init_debugfs(void) { htm_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!htm_buf) { pr_err("Failed to allocate htmdump buf\n"); return -ENOMEM; } htmdump_debugfs_dir = debugfs_create_dir("htmdump", arch_debugfs_dir); debugfs_create_u32("nodeindex", 0600, htmdump_debugfs_dir, &nodeindex); debugfs_create_u32("nodalchipindex", 0600, htmdump_debugfs_dir, &nodalchipindex); debugfs_create_u32("coreindexonchip", 0600, htmdump_debugfs_dir, &coreindexonchip); debugfs_create_u32("htmtype", 0600, htmdump_debugfs_dir, &htmtype); debugfs_create_file("trace", 0400, htmdump_debugfs_dir, htm_buf, &htmdump_fops); return 0; } static int __init htmdump_init(void) { if (htmdump_init_debugfs()) return -ENOMEM; return 0; } static void __exit htmdump_exit(void) { debugfs_remove_recursive(htmdump_debugfs_dir); kfree(htm_buf); } module_init(htmdump_init); module_exit(htmdump_exit); MODULE_DESCRIPTION("PHYP Hardware Trace Macro (HTM) data dumper"); MODULE_LICENSE("GPL");