1// Copyright 2018 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <ddk/binding.h> 6#include <ddk/debug.h> 7#include <ddk/device.h> 8#include <ddk/protocol/platform-defs.h> 9#include <ddk/protocol/platform-device.h> 10#include <stdlib.h> 11#include <string.h> 12 13typedef struct cpu_trace_dev { 14 zx_device_t* zxdev; 15 zx_handle_t bti; 16} cpu_trace_dev_t; 17 18static const pdev_device_info_t cpu_trace_pdev_device_info = { 19 .vid = PDEV_VID_INTEL, 20 .pid = PDEV_PID_GENERIC, 21 .did = PDEV_DID_INTEL_CPU_TRACE, 22 .bti_count = 1, 23}; 24 25static zx_status_t cpu_trace_get_bti(void* ctx, uint32_t index, zx_handle_t* out_handle) { 26 cpu_trace_dev_t* dev = ctx; 27 if (index >= cpu_trace_pdev_device_info.bti_count || out_handle == NULL) { 28 return ZX_ERR_INVALID_ARGS; 29 } 30 return zx_handle_duplicate(dev->bti, ZX_RIGHT_SAME_RIGHTS, out_handle); 31} 32 33static zx_status_t cpu_trace_get_device_info(void* ctx, pdev_device_info_t* out_info) { 34 memcpy(out_info, &cpu_trace_pdev_device_info, sizeof(*out_info)); 35 return ZX_OK; 36} 37 38static zx_status_t cpu_trace_map_mmio(void* ctx, uint32_t index, uint32_t cache_policy, void** out_vaddr, 39 size_t* out_size, zx_paddr_t* out_paddr, zx_handle_t* out_handle) { 40 return ZX_ERR_NOT_SUPPORTED; 41} 42 43static zx_status_t cpu_trace_map_interrupt(void* ctx, uint32_t index, uint32_t flags, zx_handle_t* out_handle) { 44 return ZX_ERR_NOT_SUPPORTED; 45} 46 47static platform_device_protocol_ops_t cpu_trace_proto_ops = { 48 .map_mmio = cpu_trace_map_mmio, 49 .map_interrupt = cpu_trace_map_interrupt, 50 .get_bti = cpu_trace_get_bti, 51 .get_device_info = cpu_trace_get_device_info, 52}; 53 54 55static void cpu_trace_release(void* ctx) { 56 cpu_trace_dev_t* dev = ctx; 57 zx_handle_close(dev->bti); 58 free(dev); 59} 60 61static zx_protocol_device_t cpu_trace_dev_proto = { 62 .version = DEVICE_OPS_VERSION, 63 .release = cpu_trace_release, 64}; 65 66zx_status_t publish_cpu_trace(zx_handle_t bti, zx_device_t* sys_root) { 67 cpu_trace_dev_t* dev = calloc(1, sizeof(*dev)); 68 if (dev == NULL) { 69 return ZX_ERR_NO_MEMORY; 70 } 71 dev->bti = bti; 72 73 zx_device_prop_t props[] = { 74 {BIND_PLATFORM_DEV_VID, 0, cpu_trace_pdev_device_info.vid}, 75 {BIND_PLATFORM_DEV_PID, 0, cpu_trace_pdev_device_info.pid}, 76 {BIND_PLATFORM_DEV_DID, 0, cpu_trace_pdev_device_info.did}, 77 }; 78 device_add_args_t args = { 79 .version = DEVICE_ADD_ARGS_VERSION, 80 .name = "cpu-trace", 81 .ctx = dev, 82 .ops = &cpu_trace_dev_proto, 83 .proto_id = ZX_PROTOCOL_PLATFORM_DEV, 84 .proto_ops = &cpu_trace_proto_ops, 85 .props = props, 86 .prop_count = countof(props), 87 .proxy_args = NULL, 88 .flags = 0, 89 }; 90 91 // add as a child of the sysroot 92 zx_status_t status = device_add(sys_root, &args, &dev->zxdev); 93 if (status != ZX_OK) { 94 zxlogf(ERROR, "acpi-bus: error %d in device_add(sys/cpu-trace)\n", status); 95 cpu_trace_release(dev); 96 return status; 97 } 98 99 return ZX_OK; 100} 101