2022-06-27 19:36:56 +02:00
|
|
|
/*
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
UMKa - User-Mode KolibriOS developer tools
|
|
|
|
|
2023-02-01 19:30:44 +01:00
|
|
|
Copyright (C) 2019-2020,2022-2023 Ivan Baravy <dunkaist@gmail.com>
|
2022-06-27 19:36:56 +02:00
|
|
|
Copyright (C) 2021 Magomed Kostoev <mkostoevr@yandex.ru>
|
|
|
|
*/
|
|
|
|
|
2019-10-09 01:35:47 +02:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
2021-12-12 11:35:35 +01:00
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
#include <unistd.h>
|
2019-10-09 01:35:47 +02:00
|
|
|
#include <fcntl.h>
|
2021-12-12 11:35:35 +01:00
|
|
|
#endif
|
|
|
|
|
2020-05-07 03:57:01 +02:00
|
|
|
#include "umka.h"
|
2019-10-09 01:35:47 +02:00
|
|
|
|
2022-06-13 23:46:48 +02:00
|
|
|
#define MSR_IA32_DEBUGCTL 0x1d9
|
|
|
|
#define MSR_IA32_DEBUGCTL_LBR 0x1 // enable profiling
|
|
|
|
#define MSR_IA32_DEBUGCTL_BTF 0x2 // profile only branches if EFLAGS.TF
|
2020-02-21 03:21:09 +01:00
|
|
|
#define MSR_IA32_LASTBRANCHFROMIP 0x1db
|
|
|
|
#define MSR_IA32_LASTBRANCHTOIP 0x1dc
|
|
|
|
|
2022-06-13 23:46:48 +02:00
|
|
|
int msrfd;
|
2019-10-09 01:35:47 +02:00
|
|
|
|
|
|
|
uint64_t rdmsr(uint32_t reg)
|
|
|
|
{
|
2021-12-12 11:35:35 +01:00
|
|
|
uint64_t data = 0;
|
2019-10-09 01:35:47 +02:00
|
|
|
|
2021-12-12 11:35:35 +01:00
|
|
|
#ifndef _WIN32
|
2019-10-09 01:35:47 +02:00
|
|
|
if (pread(msrfd, &data, sizeof data, reg) != sizeof data) {
|
|
|
|
perror("rdmsr: pread");
|
|
|
|
exit(1);
|
|
|
|
}
|
2021-12-12 11:35:35 +01:00
|
|
|
#else
|
2023-02-01 19:30:44 +01:00
|
|
|
(void)reg;
|
2021-12-12 11:35:35 +01:00
|
|
|
printf("STUB: %s:%d", __FILE__, __LINE__);
|
|
|
|
#endif
|
2019-10-09 01:35:47 +02:00
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
void wrmsr(uint32_t reg, uint64_t data)
|
|
|
|
{
|
2021-12-12 11:35:35 +01:00
|
|
|
#ifndef _WIN32
|
2019-10-09 01:35:47 +02:00
|
|
|
int fd;
|
|
|
|
fd = open("/dev/cpu/0/msr", O_WRONLY);
|
|
|
|
if (fd < 0) {
|
|
|
|
perror("wrmsr: open");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pwrite(fd, &data, sizeof data, reg) != sizeof data) {
|
|
|
|
perror("wrmsr: pwrite");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
close(fd);
|
2021-12-12 11:35:35 +01:00
|
|
|
#else
|
2023-02-01 19:30:44 +01:00
|
|
|
(void)reg;
|
|
|
|
(void)data;
|
2021-12-12 11:35:35 +01:00
|
|
|
printf("STUB: %s:%d", __FILE__, __LINE__);
|
|
|
|
#endif
|
2019-10-09 01:35:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void handle_sigtrap() {
|
2021-12-12 11:35:35 +01:00
|
|
|
#ifndef _WIN32
|
2020-02-21 03:21:09 +01:00
|
|
|
uint64_t from = rdmsr(MSR_IA32_LASTBRANCHFROMIP);
|
|
|
|
uint64_t to = rdmsr(MSR_IA32_LASTBRANCHTOIP);
|
2019-10-09 01:35:47 +02:00
|
|
|
|
2022-06-13 23:46:48 +02:00
|
|
|
if (from >= (uintptr_t)coverage_begin && from < (uintptr_t)coverage_end) {
|
|
|
|
coverage_table[from - (uintptr_t)coverage_begin].from_cnt++;
|
2019-10-09 01:35:47 +02:00
|
|
|
}
|
|
|
|
|
2022-06-13 23:46:48 +02:00
|
|
|
if (to >= (uintptr_t)coverage_begin && to < (uintptr_t)coverage_end) {
|
|
|
|
coverage_table[to - (uintptr_t)coverage_begin].to_cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
wrmsr(MSR_IA32_DEBUGCTL, MSR_IA32_DEBUGCTL_LBR + MSR_IA32_DEBUGCTL_BTF);
|
2021-12-12 11:35:35 +01:00
|
|
|
#else
|
|
|
|
printf("STUB: %s:%d", __FILE__, __LINE__);
|
|
|
|
#endif
|
2020-02-21 03:21:09 +01:00
|
|
|
}
|
|
|
|
|
2021-12-04 18:58:16 +01:00
|
|
|
uint32_t set_eflags_tf(uint32_t tf);
|
2019-10-09 01:35:47 +02:00
|
|
|
|
|
|
|
void trace_lbr_begin() {
|
2021-12-12 11:35:35 +01:00
|
|
|
#ifndef _WIN32
|
2019-10-09 01:35:47 +02:00
|
|
|
struct sigaction action;
|
|
|
|
action.sa_sigaction = &handle_sigtrap;
|
|
|
|
action.sa_flags = SA_SIGINFO;
|
|
|
|
sigaction(SIGTRAP, &action, NULL);
|
|
|
|
|
2022-06-13 23:46:48 +02:00
|
|
|
wrmsr(MSR_IA32_DEBUGCTL, MSR_IA32_DEBUGCTL_LBR + MSR_IA32_DEBUGCTL_BTF);
|
2019-10-09 01:35:47 +02:00
|
|
|
msrfd = open("/dev/cpu/0/msr", O_RDONLY);
|
|
|
|
if (msrfd < 0) {
|
|
|
|
perror("rdmsr: open");
|
|
|
|
exit(1);
|
|
|
|
}
|
2021-12-12 11:35:35 +01:00
|
|
|
#else
|
|
|
|
printf("STUB: %s:%d", __FILE__, __LINE__);
|
|
|
|
#endif
|
2019-10-09 01:35:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void trace_lbr_end() {
|
2021-12-12 11:35:35 +01:00
|
|
|
#ifndef _WIN32
|
2022-06-13 23:46:48 +02:00
|
|
|
wrmsr(MSR_IA32_DEBUGCTL, 0);
|
2019-10-09 01:35:47 +02:00
|
|
|
close(msrfd);
|
2021-12-12 11:35:35 +01:00
|
|
|
#else
|
|
|
|
printf("STUB: %s:%d", __FILE__, __LINE__);
|
|
|
|
#endif
|
2019-10-09 01:35:47 +02:00
|
|
|
}
|
2020-03-09 22:03:57 +01:00
|
|
|
|
|
|
|
uint32_t trace_lbr_pause(void) {
|
|
|
|
return set_eflags_tf(0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
void trace_lbr_resume(uint32_t value) {
|
|
|
|
set_eflags_tf(value);
|
|
|
|
}
|