123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- /*
- * Copyright (c) 2021, Patrick Meyer <git@the-space.agency>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include <AK/Assertions.h>
- #include <AK/NonnullOwnPtr.h>
- #include <Kernel/Devices/KCOVDevice.h>
- #include <Kernel/Devices/KCOVInstance.h>
- #include <Kernel/FileSystem/FileDescription.h>
- #include <LibC/sys/ioctl_numbers.h>
- #include <Kernel/Panic.h>
- namespace Kernel {
- HashMap<ProcessID, KCOVInstance*>* KCOVDevice::proc_instance;
- HashMap<ThreadID, KCOVInstance*>* KCOVDevice::thread_instance;
- UNMAP_AFTER_INIT NonnullRefPtr<KCOVDevice> KCOVDevice::must_create()
- {
- return adopt_ref(*new KCOVDevice);
- }
- UNMAP_AFTER_INIT KCOVDevice::KCOVDevice()
- : BlockDevice(30, 0)
- {
- proc_instance = new HashMap<ProcessID, KCOVInstance*>();
- thread_instance = new HashMap<ThreadID, KCOVInstance*>();
- dbgln("KCOVDevice created");
- }
- void KCOVDevice::free_thread()
- {
- auto thread = Thread::current();
- auto tid = thread->tid();
- auto maybe_kcov_instance = thread_instance->get(tid);
- if (!maybe_kcov_instance.has_value())
- return;
- auto kcov_instance = maybe_kcov_instance.value();
- VERIFY(kcov_instance->state == KCOVInstance::TRACING);
- kcov_instance->state = KCOVInstance::OPENED;
- thread_instance->remove(tid);
- }
- void KCOVDevice::free_process()
- {
- auto pid = Process::current().pid();
- auto maybe_kcov_instance = proc_instance->get(pid);
- if (!maybe_kcov_instance.has_value())
- return;
- auto kcov_instance = maybe_kcov_instance.value();
- VERIFY(kcov_instance->state == KCOVInstance::OPENED);
- kcov_instance->state = KCOVInstance::UNUSED;
- proc_instance->remove(pid);
- delete kcov_instance;
- }
- KResultOr<NonnullRefPtr<FileDescription>> KCOVDevice::open(int options)
- {
- auto pid = Process::current().pid();
- if (proc_instance->get(pid).has_value())
- return EBUSY; // This process already open()ed the kcov device
- auto kcov_instance = new KCOVInstance(pid);
- kcov_instance->state = KCOVInstance::OPENED;
- proc_instance->set(pid, kcov_instance);
- return File::open(options);
- }
- KResult KCOVDevice::ioctl(FileDescription&, unsigned request, Userspace<void*> arg)
- {
- KResult return_value = KSuccess;
- auto thread = Thread::current();
- auto tid = thread->tid();
- auto pid = thread->pid();
- auto maybe_kcov_instance = proc_instance->get(pid);
- if (!maybe_kcov_instance.has_value())
- return ENXIO; // This proc hasn't opened the kcov dev yet
- auto kcov_instance = maybe_kcov_instance.value();
- SpinlockLocker lock(kcov_instance->lock);
- switch (request) {
- case KCOV_SETBUFSIZE: {
- if (kcov_instance->state >= KCOVInstance::TRACING) {
- return_value = EBUSY;
- break;
- }
- return_value = kcov_instance->buffer_allocate((FlatPtr)arg.unsafe_userspace_ptr());
- break;
- }
- case KCOV_ENABLE: {
- if (kcov_instance->state >= KCOVInstance::TRACING) {
- return_value = EBUSY;
- break;
- }
- if (!kcov_instance->has_buffer()) {
- return_value = ENOBUFS;
- break;
- }
- VERIFY(kcov_instance->state == KCOVInstance::OPENED);
- kcov_instance->state = KCOVInstance::TRACING;
- thread_instance->set(tid, kcov_instance);
- break;
- }
- case KCOV_DISABLE: {
- auto maybe_kcov_instance = thread_instance->get(tid);
- if (!maybe_kcov_instance.has_value()) {
- return_value = ENOENT;
- break;
- }
- VERIFY(kcov_instance->state == KCOVInstance::TRACING);
- kcov_instance->state = KCOVInstance::OPENED;
- thread_instance->remove(tid);
- break;
- }
- default: {
- return_value = EINVAL;
- }
- };
- return return_value;
- }
- KResultOr<Memory::Region*> KCOVDevice::mmap(Process& process, FileDescription&, Memory::VirtualRange const& range, u64 offset, int prot, bool shared)
- {
- auto pid = process.pid();
- auto maybe_kcov_instance = proc_instance->get(pid);
- VERIFY(maybe_kcov_instance.has_value()); // Should happen on fd open()
- auto kcov_instance = maybe_kcov_instance.value();
- if (!kcov_instance->vmobject) {
- return ENOBUFS; // Mmaped, before KCOV_SETBUFSIZE
- }
- return process.address_space().allocate_region_with_vmobject(
- range, *kcov_instance->vmobject, offset, {}, prot, shared);
- }
- String KCOVDevice::device_name() const
- {
- return "kcov"sv;
- }
- }
|