2021-06-06 23:15:07 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2021, Patrick Meyer <git@the-space.agency>
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <AK/Assertions.h>
|
|
|
|
#include <AK/NonnullOwnPtr.h>
|
2023-01-07 20:52:06 +00:00
|
|
|
#include <Kernel/API/Ioctl.h>
|
2021-09-11 06:19:20 +00:00
|
|
|
#include <Kernel/Devices/DeviceManagement.h>
|
2021-06-06 23:15:07 +00:00
|
|
|
#include <Kernel/Devices/KCOVDevice.h>
|
|
|
|
#include <Kernel/Devices/KCOVInstance.h>
|
2021-09-07 11:39:11 +00:00
|
|
|
#include <Kernel/FileSystem/OpenFileDescription.h>
|
2021-06-06 23:15:07 +00:00
|
|
|
|
2023-02-24 18:10:59 +00:00
|
|
|
#include <Kernel/Library/Panic.h>
|
2021-06-06 23:15:07 +00:00
|
|
|
|
|
|
|
namespace Kernel {
|
|
|
|
|
2022-08-19 18:53:40 +00:00
|
|
|
UNMAP_AFTER_INIT NonnullLockRefPtr<KCOVDevice> KCOVDevice::must_create()
|
2021-06-06 23:15:07 +00:00
|
|
|
{
|
2021-09-11 06:19:20 +00:00
|
|
|
auto kcov_device_or_error = DeviceManagement::try_create_device<KCOVDevice>();
|
2021-09-10 11:44:46 +00:00
|
|
|
// FIXME: Find a way to propagate errors
|
|
|
|
VERIFY(!kcov_device_or_error.is_error());
|
|
|
|
return kcov_device_or_error.release_value();
|
2021-06-06 23:15:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UNMAP_AFTER_INIT KCOVDevice::KCOVDevice()
|
2024-04-07 17:12:31 +00:00
|
|
|
: BlockDevice(30, 0)
|
2021-06-06 23:15:07 +00:00
|
|
|
{
|
|
|
|
dbgln("KCOVDevice created");
|
|
|
|
}
|
|
|
|
|
2023-03-06 18:29:25 +00:00
|
|
|
ErrorOr<NonnullRefPtr<OpenFileDescription>> KCOVDevice::open(int options)
|
2021-06-06 23:15:07 +00:00
|
|
|
{
|
2024-04-08 00:49:15 +00:00
|
|
|
auto& proc = Process::current();
|
|
|
|
auto* kcov_instance = proc.kcov_instance();
|
|
|
|
if (kcov_instance != nullptr)
|
2021-06-06 23:15:07 +00:00
|
|
|
return EBUSY; // This process already open()ed the kcov device
|
|
|
|
|
2024-04-08 00:49:15 +00:00
|
|
|
proc.set_kcov_instance(new KCOVInstance(proc.pid()));
|
2022-12-02 09:33:57 +00:00
|
|
|
return Device::open(options);
|
2021-06-06 23:15:07 +00:00
|
|
|
}
|
|
|
|
|
2021-11-07 23:51:39 +00:00
|
|
|
ErrorOr<void> KCOVDevice::ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg)
|
2021-06-06 23:15:07 +00:00
|
|
|
{
|
2024-04-08 00:49:15 +00:00
|
|
|
auto& proc = Process::current();
|
|
|
|
auto* thread = Thread::current();
|
|
|
|
auto* kcov_instance = proc.kcov_instance();
|
|
|
|
if (kcov_instance == nullptr) {
|
|
|
|
VERIFY(!Process::is_kcov_busy()); // No thread should be tracing at this point.
|
|
|
|
return ENXIO; // This proc hasn't opened the kcov dev yet
|
|
|
|
}
|
2021-06-06 23:15:07 +00:00
|
|
|
|
2021-09-05 22:31:48 +00:00
|
|
|
SpinlockLocker locker(kcov_instance->spinlock());
|
2021-06-06 23:15:07 +00:00
|
|
|
switch (request) {
|
2021-11-07 23:51:39 +00:00
|
|
|
case KCOV_SETBUFSIZE:
|
2024-04-08 00:49:15 +00:00
|
|
|
if (Process::is_kcov_busy())
|
|
|
|
// Buffer is shared among all proc threads, hence we need to check if any of them
|
|
|
|
// are currently tracing. If so, don't mess with the buffer.
|
2021-11-07 23:51:39 +00:00
|
|
|
return EBUSY;
|
|
|
|
return kcov_instance->buffer_allocate((FlatPtr)arg.unsafe_userspace_ptr());
|
|
|
|
case KCOV_ENABLE:
|
|
|
|
if (!kcov_instance->has_buffer())
|
|
|
|
return ENOBUFS;
|
2024-04-08 00:49:15 +00:00
|
|
|
thread->m_kcov_enabled = true;
|
2021-11-07 23:51:39 +00:00
|
|
|
return {};
|
2021-06-06 23:15:07 +00:00
|
|
|
case KCOV_DISABLE: {
|
2024-04-08 00:49:15 +00:00
|
|
|
thread->m_kcov_enabled = false;
|
2021-11-07 23:51:39 +00:00
|
|
|
return {};
|
2021-06-06 23:15:07 +00:00
|
|
|
}
|
2021-11-07 23:51:39 +00:00
|
|
|
default:
|
|
|
|
return EINVAL;
|
2021-06-06 23:15:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-23 16:51:18 +00:00
|
|
|
ErrorOr<NonnullLockRefPtr<Memory::VMObject>> KCOVDevice::vmobject_for_mmap(Process& process, Memory::VirtualRange const&, u64&, bool)
|
2021-06-06 23:15:07 +00:00
|
|
|
{
|
2024-04-08 00:49:15 +00:00
|
|
|
auto* kcov_instance = process.kcov_instance();
|
|
|
|
VERIFY(kcov_instance != nullptr); // Should have happened on fd open()
|
2021-06-06 23:15:07 +00:00
|
|
|
|
2021-09-05 22:31:48 +00:00
|
|
|
if (!kcov_instance->vmobject())
|
|
|
|
return ENOBUFS; // mmaped, before KCOV_SETBUFSIZE
|
2021-06-06 23:15:07 +00:00
|
|
|
|
2022-08-23 16:51:18 +00:00
|
|
|
return *kcov_instance->vmobject();
|
2021-06-06 23:15:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|