1// Copyright 2017 The Fuchsia Authors 2// 3// Use of this source code is governed by a MIT-style 4// license that can be found in the LICENSE file or at 5// https://opensource.org/licenses/MIT 6 7#ifdef __x86_64__ // entire file 8 9#include <inttypes.h> 10 11#include "lib/mtrace.h" 12#include "trace.h" 13 14#include <arch/user_copy.h> 15#include <object/process_dispatcher.h> 16#include <object/vm_object_dispatcher.h> 17 18#include <lib/zircon-internal/mtrace.h> 19 20#include "arch/x86/perf_mon.h" 21 22#define LOCAL_TRACE 0 23 24zx_status_t mtrace_cpuperf_control(uint32_t action, uint32_t options, 25 user_inout_ptr<void> arg, size_t size) { 26 TRACEF("action %u, options 0x%x, arg %p, size 0x%zx\n", 27 action, options, arg.get(), size); 28 29 switch (action) { 30 case MTRACE_CPUPERF_GET_PROPERTIES: { 31 zx_x86_ipm_properties_t props; 32 if (size != sizeof(props)) 33 return ZX_ERR_INVALID_ARGS; 34 if (options != 0) 35 return ZX_ERR_INVALID_ARGS; 36 auto status = x86_ipm_get_properties(&props); 37 if (status != ZX_OK) 38 return status; 39 status = arg.reinterpret<zx_x86_ipm_properties_t>().copy_to_user(props); 40 if (status != ZX_OK) 41 return status; 42 return ZX_OK; 43 } 44 45 case MTRACE_CPUPERF_INIT: 46 if (options != 0 || size != 0) 47 return ZX_ERR_INVALID_ARGS; 48 return x86_ipm_init(); 49 50 case MTRACE_CPUPERF_ASSIGN_BUFFER: { 51 zx_x86_ipm_buffer_t buffer; 52 if (size != sizeof(buffer)) 53 return ZX_ERR_INVALID_ARGS; 54 zx_status_t status = arg.reinterpret<zx_x86_ipm_buffer_t>().copy_from_user(&buffer); 55 if (status != ZX_OK) 56 return status; 57 58 // TODO(dje): Later need to rework to assign buffers to things 59 // like threads. 60 uint32_t cpu = MTRACE_CPUPERF_OPTIONS_CPU(options); 61 if ((options & ~MTRACE_CPUPERF_OPTIONS_CPU_MASK) != 0) 62 return ZX_ERR_INVALID_ARGS; 63 64 // lookup the VMO dispatcher from handle 65 // TODO(dje): Passing in a vmo from userspace, even from a device 66 // driver we control, to which we will write from kernel space, feels 67 // dodgey. Perhaps we should allocate the vmo here, but that put more 68 // of this driver in kernel space. Revisit. 69 auto up = ProcessDispatcher::GetCurrent(); 70 fbl::RefPtr<VmObjectDispatcher> vmo; 71 zx_rights_t vmo_rights; 72 zx_rights_t needed_rights = 73 ZX_RIGHT_MAP | ZX_RIGHT_READ | ZX_RIGHT_WRITE; 74 status = up->GetDispatcherWithRights(buffer.vmo, needed_rights, 75 &vmo, &vmo_rights); 76 if (status != ZX_OK) 77 return status; 78 79 return x86_ipm_assign_buffer(cpu, fbl::move(vmo->vmo())); 80 } 81 82 case MTRACE_CPUPERF_STAGE_CONFIG: { 83 zx_x86_ipm_config_t config; 84 if (size != sizeof(config)) 85 return ZX_ERR_INVALID_ARGS; 86 zx_status_t status = arg.reinterpret<zx_x86_ipm_config_t>().copy_from_user(&config); 87 if (status != ZX_OK) 88 return status; 89 if (options != 0) 90 return ZX_ERR_INVALID_ARGS; 91 TRACEF("action %u, global_ctrl 0x%" PRIx64 "\n", 92 action, config.global_ctrl); 93 return x86_ipm_stage_config(&config); 94 } 95 96 case MTRACE_CPUPERF_START: 97 if (options != 0 || size != 0) 98 return ZX_ERR_INVALID_ARGS; 99 return x86_ipm_start(); 100 101 case MTRACE_CPUPERF_STOP: 102 if (options != 0 || size != 0) 103 return ZX_ERR_INVALID_ARGS; 104 return x86_ipm_stop(); 105 106 case MTRACE_CPUPERF_FINI: 107 if (options != 0 || size != 0) 108 return ZX_ERR_INVALID_ARGS; 109 return x86_ipm_fini(); 110 111 default: 112 return ZX_ERR_INVALID_ARGS; 113 } 114} 115 116#endif 117