Compare commits
8 Commits
0adb28e23f
...
eeadf5fff1
Author | SHA1 | Date |
---|---|---|
Bananymous | eeadf5fff1 | |
Bananymous | 58be87ba3c | |
Bananymous | 6d7e61225b | |
Bananymous | eb69fc477b | |
Bananymous | 74b3fc2e7c | |
Bananymous | 4a0bfd08e0 | |
Bananymous | 816f8091a9 | |
Bananymous | 46ad4f2818 |
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kernel/FS/TmpFS/Inode.h>
|
#include <kernel/FS/TmpFS/Inode.h>
|
||||||
|
#include <kernel/Memory/MemoryRegion.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
@ -15,6 +16,8 @@ namespace Kernel
|
||||||
virtual bool is_partition() const { return false; }
|
virtual bool is_partition() const { return false; }
|
||||||
virtual bool is_storage_device() const { return false; }
|
virtual bool is_storage_device() const { return false; }
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) { return BAN::Error::from_errno(EINVAL); }
|
||||||
|
|
||||||
virtual dev_t rdev() const override = 0;
|
virtual dev_t rdev() const override = 0;
|
||||||
|
|
||||||
virtual BAN::StringView name() const = 0;
|
virtual BAN::StringView name() const = 0;
|
||||||
|
|
|
@ -21,6 +21,8 @@ namespace Kernel
|
||||||
void sync_pixels_linear(uint32_t first_pixel, uint32_t pixel_count);
|
void sync_pixels_linear(uint32_t first_pixel, uint32_t pixel_count);
|
||||||
void sync_pixels_rectangle(uint32_t top_right_x, uint32_t top_right_y, uint32_t width, uint32_t height);
|
void sync_pixels_rectangle(uint32_t top_right_x, uint32_t top_right_y, uint32_t width, uint32_t height);
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) override;
|
||||||
|
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
virtual dev_t rdev() const override { return m_rdev; }
|
||||||
virtual BAN::StringView name() const override { return m_name.sv(); }
|
virtual BAN::StringView name() const override { return m_name.sv(); }
|
||||||
|
|
||||||
|
@ -44,6 +46,8 @@ namespace Kernel
|
||||||
const uint8_t m_bpp;
|
const uint8_t m_bpp;
|
||||||
|
|
||||||
BAN::UniqPtr<VirtualRange> m_video_buffer;
|
BAN::UniqPtr<VirtualRange> m_video_buffer;
|
||||||
|
|
||||||
|
friend class FramebufferMemoryRegion;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -10,6 +10,8 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
~SharedFileData();
|
~SharedFileData();
|
||||||
|
|
||||||
|
void sync(size_t page_index);
|
||||||
|
|
||||||
// FIXME: this should probably be ordered tree like map
|
// FIXME: this should probably be ordered tree like map
|
||||||
// for fast lookup and less memory usage
|
// for fast lookup and less memory usage
|
||||||
BAN::Vector<paddr_t> pages;
|
BAN::Vector<paddr_t> pages;
|
||||||
|
@ -26,6 +28,8 @@ namespace Kernel
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t);
|
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t);
|
||||||
~FileBackedRegion();
|
~FileBackedRegion();
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -14,9 +14,10 @@ namespace Kernel
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t);
|
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t);
|
||||||
~MemoryBackedRegion();
|
~MemoryBackedRegion();
|
||||||
|
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||||
|
|
||||||
// Copy data from buffer into this region
|
// Copy data from buffer into this region
|
||||||
// This can fail if no memory is mapped and no free memory was available
|
// This can fail if no memory is mapped and no free memory was available
|
||||||
BAN::ErrorOr<void> copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size);
|
BAN::ErrorOr<void> copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size);
|
||||||
|
|
|
@ -40,6 +40,8 @@ namespace Kernel
|
||||||
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
|
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
|
||||||
size_t physical_page_count() const { return m_physical_page_count; }
|
size_t physical_page_count() const { return m_physical_page_count; }
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0;
|
||||||
|
|
||||||
// Returns error if no memory was available
|
// Returns error if no memory was available
|
||||||
// Returns true if page was succesfully allocated
|
// Returns true if page was succesfully allocated
|
||||||
// Returns false if page was already allocated
|
// Returns false if page was already allocated
|
||||||
|
|
|
@ -105,6 +105,8 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> sys_readlink(const char* path, char* buffer, size_t bufsize);
|
BAN::ErrorOr<long> sys_readlink(const char* path, char* buffer, size_t bufsize);
|
||||||
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
|
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> sys_pread(int fd, void* buffer, size_t count, off_t offset);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_chmod(const char*, mode_t);
|
BAN::ErrorOr<long> sys_chmod(const char*, mode_t);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
|
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
|
||||||
|
@ -130,6 +132,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*);
|
BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*);
|
||||||
BAN::ErrorOr<long> sys_munmap(void* addr, size_t len);
|
BAN::ErrorOr<long> sys_munmap(void* addr, size_t len);
|
||||||
|
BAN::ErrorOr<long> sys_msync(void* addr, size_t len, int flags);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
|
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
#include <kernel/Memory/Heap.h>
|
#include <kernel/Memory/Heap.h>
|
||||||
|
|
||||||
|
#include <sys/framebuffer.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -82,8 +85,20 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> FramebufferDevice::read_impl(off_t offset, BAN::ByteSpan buffer)
|
BAN::ErrorOr<size_t> FramebufferDevice::read_impl(off_t offset, BAN::ByteSpan buffer)
|
||||||
{
|
{
|
||||||
|
// Reading from negative offset will fill buffer with framebuffer info
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
{
|
||||||
|
if (buffer.size() < sizeof(framebuffer_info_t))
|
||||||
|
return BAN::Error::from_errno(ENOBUFS);
|
||||||
|
|
||||||
|
auto& fb_info = buffer.as<framebuffer_info_t>();
|
||||||
|
fb_info.width = m_width;
|
||||||
|
fb_info.height = m_height;
|
||||||
|
fb_info.bpp = m_bpp;
|
||||||
|
|
||||||
|
return sizeof(framebuffer_info_t);
|
||||||
|
}
|
||||||
|
|
||||||
if ((size_t)offset >= m_width * m_height * bytes_per_pixel_internal)
|
if ((size_t)offset >= m_width * m_height * bytes_per_pixel_internal)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -178,4 +193,86 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FramebufferMemoryRegion : public MemoryRegion
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static BAN::ErrorOr<BAN::UniqPtr<FramebufferMemoryRegion>> create(PageTable& page_table, size_t size, AddressRange address_range, MemoryRegion::Type region_type, PageTable::flags_t page_flags, BAN::RefPtr<FramebufferDevice> framebuffer)
|
||||||
|
{
|
||||||
|
auto* region_ptr = new FramebufferMemoryRegion(page_table, size, region_type, page_flags, framebuffer);
|
||||||
|
if (region_ptr == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
auto region = BAN::UniqPtr<FramebufferMemoryRegion>::adopt(region_ptr);
|
||||||
|
|
||||||
|
TRY(region->initialize(address_range));
|
||||||
|
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
~FramebufferMemoryRegion()
|
||||||
|
{
|
||||||
|
m_framebuffer->sync_pixels_full();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<void> msync(vaddr_t vaddr, size_t size, int flags) override
|
||||||
|
{
|
||||||
|
if (flags != MS_SYNC)
|
||||||
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
|
||||||
|
if (vaddr < m_vaddr)
|
||||||
|
vaddr = m_vaddr;
|
||||||
|
if (vaddr + size > m_vaddr + m_size)
|
||||||
|
size = (vaddr - m_vaddr) + m_size;
|
||||||
|
|
||||||
|
m_framebuffer->sync_pixels_linear(
|
||||||
|
(vaddr - m_vaddr) / bytes_per_pixel_internal,
|
||||||
|
BAN::Math::div_round_up<uint32_t>((vaddr % bytes_per_pixel_internal) + size, bytes_per_pixel_internal)
|
||||||
|
);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override
|
||||||
|
{
|
||||||
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Returns error if no memory was available
|
||||||
|
// Returns true if page was succesfully allocated
|
||||||
|
// Returns false if page was already allocated
|
||||||
|
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr) override
|
||||||
|
{
|
||||||
|
vaddr &= PAGE_ADDR_MASK;
|
||||||
|
if (m_page_table.physical_address_of(vaddr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
paddr_t paddr = PageTable::kernel().physical_address_of(m_framebuffer->m_video_buffer->vaddr() + (vaddr - m_vaddr));
|
||||||
|
m_page_table.map_page_at(paddr, vaddr, m_flags);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FramebufferMemoryRegion(PageTable& page_table, size_t size, MemoryRegion::Type region_type, PageTable::flags_t page_flags, BAN::RefPtr<FramebufferDevice> framebuffer)
|
||||||
|
: MemoryRegion(page_table, size, region_type, page_flags)
|
||||||
|
, m_framebuffer(framebuffer)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private:
|
||||||
|
BAN::RefPtr<FramebufferDevice> m_framebuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FramebufferDevice::mmap_region(PageTable& page_table, off_t offset, size_t len, AddressRange address_range, MemoryRegion::Type region_type, PageTable::flags_t page_flags)
|
||||||
|
{
|
||||||
|
if (offset != 0)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
if (len > m_video_buffer->size())
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
if (region_type != MemoryRegion::Type::SHARED)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
auto region = TRY(FramebufferMemoryRegion::create(page_table, len, address_range, region_type, page_flags, this));
|
||||||
|
return BAN::UniqPtr<MemoryRegion>(BAN::move(region));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
#include <kernel/Memory/FileBackedRegion.h>
|
#include <kernel/Memory/FileBackedRegion.h>
|
||||||
#include <kernel/Memory/Heap.h>
|
#include <kernel/Memory/Heap.h>
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -70,17 +72,43 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
if (pages[i] == 0)
|
if (pages[i] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
sync(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedFileData::sync(size_t page_index)
|
||||||
|
{
|
||||||
|
// FIXME: should this be locked?
|
||||||
|
|
||||||
|
if (pages[page_index] == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
{
|
{
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
PageTable::map_fast_page(pages[i]);
|
PageTable::with_fast_page(pages[page_index], [&] {
|
||||||
memcpy(page_buffer, PageTable::fast_page_as_ptr(), PAGE_SIZE);
|
memcpy(page_buffer, PageTable::fast_page_as_ptr(), PAGE_SIZE);
|
||||||
PageTable::unmap_fast_page();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto ret = inode->write(i * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer)); ret.is_error())
|
if (auto ret = inode->write(page_index * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer)); ret.is_error())
|
||||||
dwarnln("{}", ret.error());
|
dwarnln("{}", ret.error());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> FileBackedRegion::msync(vaddr_t address, size_t size, int flags)
|
||||||
|
{
|
||||||
|
if (flags != MS_SYNC)
|
||||||
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
if (m_type != Type::SHARED)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
vaddr_t first_page = address & PAGE_ADDR_MASK;
|
||||||
|
vaddr_t last_page = BAN::Math::div_round_up<vaddr_t>(address + size, PAGE_SIZE) * PAGE_SIZE;
|
||||||
|
|
||||||
|
for (vaddr_t page_addr = first_page; page_addr < last_page; page_addr += PAGE_SIZE)
|
||||||
|
if (contains(page_addr))
|
||||||
|
m_shared_data->sync((page_addr - m_vaddr) / PAGE_SIZE);
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<bool> FileBackedRegion::allocate_page_containing_impl(vaddr_t address)
|
BAN::ErrorOr<bool> FileBackedRegion::allocate_page_containing_impl(vaddr_t address)
|
||||||
|
|
|
@ -823,6 +823,14 @@ namespace Kernel
|
||||||
return readlink_impl(absolute_path.sv(), buffer, bufsize);
|
return readlink_impl(absolute_path.sv(), buffer, bufsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset)
|
||||||
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
validate_pointer_access(buffer, count);
|
||||||
|
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
|
||||||
|
return TRY(inode->read(offset, { (uint8_t*)buffer, count }));
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_chmod(const char* path, mode_t mode)
|
BAN::ErrorOr<long> Process::sys_chmod(const char* path, mode_t mode)
|
||||||
{
|
{
|
||||||
if (mode & S_IFMASK)
|
if (mode & S_IFMASK)
|
||||||
|
@ -1050,12 +1058,13 @@ namespace Kernel
|
||||||
return m_mapped_regions.back()->vaddr();
|
return m_mapped_regions.back()->vaddr();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto inode = TRY(m_open_file_descriptors.inode_of(args->fildes));
|
|
||||||
if (inode->mode().ifreg())
|
|
||||||
{
|
|
||||||
if (args->addr != nullptr)
|
if (args->addr != nullptr)
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
auto inode = TRY(m_open_file_descriptors.inode_of(args->fildes));
|
||||||
|
|
||||||
auto inode_flags = TRY(m_open_file_descriptors.flags_of(args->fildes));
|
auto inode_flags = TRY(m_open_file_descriptors.flags_of(args->fildes));
|
||||||
if (!(inode_flags & O_RDONLY))
|
if (!(inode_flags & O_RDONLY))
|
||||||
return BAN::Error::from_errno(EACCES);
|
return BAN::Error::from_errno(EACCES);
|
||||||
|
@ -1063,20 +1072,32 @@ namespace Kernel
|
||||||
if ((args->prot & PROT_WRITE) && !(inode_flags & O_WRONLY))
|
if ((args->prot & PROT_WRITE) && !(inode_flags & O_WRONLY))
|
||||||
return BAN::Error::from_errno(EACCES);
|
return BAN::Error::from_errno(EACCES);
|
||||||
|
|
||||||
auto region = TRY(FileBackedRegion::create(
|
BAN::UniqPtr<MemoryRegion> memory_region;
|
||||||
|
if (inode->mode().ifreg())
|
||||||
|
{
|
||||||
|
memory_region = TRY(FileBackedRegion::create(
|
||||||
inode,
|
inode,
|
||||||
page_table(),
|
page_table(),
|
||||||
args->off, args->len,
|
args->off, args->len,
|
||||||
{ .start = 0x400000, .end = KERNEL_OFFSET },
|
{ .start = 0x400000, .end = KERNEL_OFFSET },
|
||||||
region_type, page_flags
|
region_type, page_flags
|
||||||
));
|
));
|
||||||
|
}
|
||||||
LockGuard _(m_lock);
|
else if (inode->is_device())
|
||||||
TRY(m_mapped_regions.push_back(BAN::move(region)));
|
{
|
||||||
return m_mapped_regions.back()->vaddr();
|
memory_region = TRY(static_cast<Device&>(*inode).mmap_region(
|
||||||
|
page_table(),
|
||||||
|
args->off, args->len,
|
||||||
|
{ .start = 0x400000, .end = KERNEL_OFFSET },
|
||||||
|
region_type, page_flags
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
if (!memory_region)
|
||||||
|
return BAN::Error::from_errno(ENODEV);
|
||||||
|
|
||||||
|
TRY(m_mapped_regions.push_back(BAN::move(memory_region)));
|
||||||
|
return m_mapped_regions.back()->vaddr();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_munmap(void* addr, size_t len)
|
BAN::ErrorOr<long> Process::sys_munmap(void* addr, size_t len)
|
||||||
|
@ -1098,6 +1119,24 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_msync(void* addr, size_t len, int flags)
|
||||||
|
{
|
||||||
|
if (flags != MS_SYNC && flags != MS_ASYNC && flags != MS_INVALIDATE)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
vaddr_t vaddr = (vaddr_t)addr;
|
||||||
|
if (vaddr % PAGE_SIZE != 0)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
for (auto& mapped_region : m_mapped_regions)
|
||||||
|
if (mapped_region->overlaps(vaddr, len))
|
||||||
|
TRY(mapped_region->msync(vaddr, len, flags));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_tty_ctrl(int fildes, int command, int flags)
|
BAN::ErrorOr<long> Process::sys_tty_ctrl(int fildes, int command, int flags)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
|
@ -217,6 +217,12 @@ namespace Kernel
|
||||||
case SYS_READLINKAT:
|
case SYS_READLINKAT:
|
||||||
ret = Process::current().sys_readlinkat((int)arg1, (const char*)arg2, (char*)arg3, (size_t)arg4);
|
ret = Process::current().sys_readlinkat((int)arg1, (const char*)arg2, (char*)arg3, (size_t)arg4);
|
||||||
break;
|
break;
|
||||||
|
case SYS_MSYNC:
|
||||||
|
ret = Process::current().sys_msync((void*)arg1, (size_t)arg2, (int)arg3);
|
||||||
|
break;
|
||||||
|
case SYS_PREAD:
|
||||||
|
ret = Process::current().sys_pread((int)arg1, (void*)arg2, (size_t)arg3, (off_t)arg4);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dwarnln("Unknown syscall {}", syscall);
|
dwarnln("Unknown syscall {}", syscall);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -129,7 +129,10 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
|
||||||
|
|
||||||
auto framebuffer_device = FramebufferDevice::create_from_boot_framebuffer();
|
auto framebuffer_device = FramebufferDevice::create_from_boot_framebuffer();
|
||||||
if (!framebuffer_device.is_error())
|
if (!framebuffer_device.is_error())
|
||||||
|
{
|
||||||
|
DevFileSystem::get().add_device(framebuffer_device.value());
|
||||||
g_terminal_driver = FramebufferTerminalDriver::create(framebuffer_device.value());
|
g_terminal_driver = FramebufferTerminalDriver::create(framebuffer_device.value());
|
||||||
|
}
|
||||||
if (g_terminal_driver)
|
if (g_terminal_driver)
|
||||||
dprintln("Framebuffer terminal initialized");
|
dprintln("Framebuffer terminal initialized");
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef _FRAMEBUFFER_H
|
||||||
|
#define _FRAMEBUFFER_H 1
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct framebuffer_info_t
|
||||||
|
{
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
uint8_t bpp;
|
||||||
|
};
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -61,6 +61,8 @@ __BEGIN_DECLS
|
||||||
#define SYS_UNLINK 58
|
#define SYS_UNLINK 58
|
||||||
#define SYS_READLINK 59
|
#define SYS_READLINK 59
|
||||||
#define SYS_READLINKAT 60
|
#define SYS_READLINKAT 60
|
||||||
|
#define SYS_MSYNC 61
|
||||||
|
#define SYS_PREAD 62
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -22,3 +22,8 @@ int munmap(void* addr, size_t len)
|
||||||
{
|
{
|
||||||
return syscall(SYS_MUNMAP, addr, len);
|
return syscall(SYS_MUNMAP, addr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int msync(void* addr, size_t len, int flags)
|
||||||
|
{
|
||||||
|
return syscall(SYS_MSYNC, addr, len, flags);
|
||||||
|
}
|
||||||
|
|
|
@ -88,6 +88,11 @@ ssize_t readlinkat(int fd, const char* __restrict path, char* __restrict buf, si
|
||||||
return syscall(SYS_READLINKAT, fd, path, buf, bufsize);
|
return syscall(SYS_READLINKAT, fd, path, buf, bufsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t pread(int fildes, void* buf, size_t nbyte, off_t offset)
|
||||||
|
{
|
||||||
|
return syscall(SYS_PREAD, fildes, buf, nbyte, offset);
|
||||||
|
}
|
||||||
|
|
||||||
int dup(int fildes)
|
int dup(int fildes)
|
||||||
{
|
{
|
||||||
return syscall(SYS_DUP, fildes);
|
return syscall(SYS_DUP, fildes);
|
||||||
|
|
|
@ -24,6 +24,7 @@ set(USERSPACE_PROJECTS
|
||||||
tee
|
tee
|
||||||
test
|
test
|
||||||
test-globals
|
test-globals
|
||||||
|
test-framebuffer
|
||||||
touch
|
touch
|
||||||
u8sum
|
u8sum
|
||||||
whoami
|
whoami
|
||||||
|
|
|
@ -30,12 +30,10 @@ int prepare_file()
|
||||||
free(null_buffer);
|
free(null_buffer);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
printf("file created\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int job1()
|
int test1_job1()
|
||||||
{
|
{
|
||||||
int fd = open(FILE_NAME, O_RDONLY);
|
int fd = open(FILE_NAME, O_RDONLY);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
|
@ -60,12 +58,12 @@ int job1()
|
||||||
munmap(addr, FILE_SIZE);
|
munmap(addr, FILE_SIZE);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
printf("sum: %zu\n", sum);
|
printf("got: %zu\n", sum);
|
||||||
|
|
||||||
return 0;
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int job2()
|
int test1_job2()
|
||||||
{
|
{
|
||||||
sleep(2);
|
sleep(2);
|
||||||
|
|
||||||
|
@ -93,14 +91,14 @@ int job2()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int test1()
|
||||||
{
|
{
|
||||||
if (int ret = prepare_file())
|
if (int ret = prepare_file())
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
return job1();
|
return test1_job1();
|
||||||
|
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
{
|
{
|
||||||
|
@ -108,8 +106,92 @@ int main()
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = job2();
|
int ret = test1_job2();
|
||||||
waitpid(pid, nullptr, 0);
|
waitpid(pid, nullptr, 0);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int test2_job1()
|
||||||
|
{
|
||||||
|
sleep(2);
|
||||||
|
|
||||||
|
int fd = open(FILE_NAME, O_RDWR);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
perror("open");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t value = 0;
|
||||||
|
if (read(fd, &value, sizeof(size_t)) == -1)
|
||||||
|
{
|
||||||
|
perror("read");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("got: %zu\n", value);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int test2_job2()
|
||||||
|
{
|
||||||
|
int fd = open(FILE_NAME, O_RDWR);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
perror("open");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* addr = mmap(nullptr, FILE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
if (addr == MAP_FAILED)
|
||||||
|
{
|
||||||
|
perror("mmap");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(size_t*)addr = 0x123456789;
|
||||||
|
|
||||||
|
if (msync(addr, sizeof(size_t), MS_SYNC) == -1)
|
||||||
|
{
|
||||||
|
perror("msync");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("expecting: %zu\n", *(size_t*)addr);
|
||||||
|
|
||||||
|
sleep(4);
|
||||||
|
|
||||||
|
munmap(addr, FILE_SIZE);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test2()
|
||||||
|
{
|
||||||
|
if (int ret = prepare_file())
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == 0)
|
||||||
|
return test2_job1();
|
||||||
|
|
||||||
|
if (pid == -1)
|
||||||
|
{
|
||||||
|
perror("fork");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = test2_job2();
|
||||||
|
waitpid(pid, nullptr, 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test1();
|
||||||
|
test2();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
cmake_minimum_required(VERSION 3.26)
|
||||||
|
|
||||||
|
project(test-framebuffer CXX)
|
||||||
|
|
||||||
|
set(SOURCES
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(test-framebuffer ${SOURCES})
|
||||||
|
target_compile_options(test-framebuffer PUBLIC -O2 -g)
|
||||||
|
target_link_libraries(test-framebuffer PUBLIC libc)
|
||||||
|
|
||||||
|
add_custom_target(test-framebuffer-install
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/test-framebuffer ${BANAN_BIN}/
|
||||||
|
DEPENDS test-framebuffer
|
||||||
|
)
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/framebuffer.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int fd = open("/dev/fb0", O_RDWR);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
perror("open");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
framebuffer_info_t fb_info;
|
||||||
|
if (pread(fd, &fb_info, sizeof(fb_info), -1) == -1)
|
||||||
|
{
|
||||||
|
perror("read");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fb_size = fb_info.width * fb_info.height * fb_info.bpp / 8;
|
||||||
|
|
||||||
|
void* addr = mmap(nullptr, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
if (addr == MAP_FAILED)
|
||||||
|
{
|
||||||
|
perror("mmap");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(addr, 0xFF, fb_size);
|
||||||
|
|
||||||
|
if (msync(addr, fb_size, MS_SYNC) == -1)
|
||||||
|
{
|
||||||
|
perror("msync");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(4);
|
||||||
|
|
||||||
|
munmap(addr, fb_size);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue