summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-01-18 15:01:40 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-01-18 15:01:40 +0100
commitf7cc4541626279b07626b9d98beba03a7230b518 (patch)
tree3aaebc55d63a16825b27d70160316b7d1e86c735 /Kernel
parent9454c5dd5254c9cd75b1b039da0cadb8c020ae38 (diff)
downloadserenity-f7cc4541626279b07626b9d98beba03a7230b518.zip
Add mechanism to expose kernel variables to userspace via ProcFS.
Only booleans are supported at first. More types can be added easily. Use this to add /proc/sys/wm_flash_flush which when enabled flashes pending screen flush rects in yellow before they happen.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/MemoryManager.h3
-rw-r--r--Kernel/ProcFileSystem.cpp78
-rw-r--r--Kernel/ProcFileSystem.h5
3 files changed, 72 insertions, 14 deletions
diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h
index cd82206966..17b99fcfe1 100644
--- a/Kernel/MemoryManager.h
+++ b/Kernel/MemoryManager.h
@@ -15,6 +15,7 @@
class Process;
extern Process* current;
+class SynthFSInode;
enum class PageFaultResponse {
ShouldCrash,
@@ -166,7 +167,7 @@ class MemoryManager {
friend class PhysicalPage;
friend class Region;
friend class VMObject;
- friend ByteBuffer procfs$mm();
+ friend ByteBuffer procfs$mm(SynthFSInode&);
public:
static MemoryManager& the() PURE;
diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp
index 7c2293df32..37d0b0d2e0 100644
--- a/Kernel/ProcFileSystem.cpp
+++ b/Kernel/ProcFileSystem.cpp
@@ -156,15 +156,15 @@ void ProcFS::add_process(Process& process)
ksprintf(buf, "%d", process.pid());
auto dir = add_file(create_directory(buf));
m_pid2inode.set(process.pid(), dir.index());
- add_file(create_generated_file("vm", [&process] { return procfs$pid_vm(process); }), dir.index());
- add_file(create_generated_file("vmo", [&process] { return procfs$pid_vmo(process); }), dir.index());
- add_file(create_generated_file("stack", [&process] { return procfs$pid_stack(process); }), dir.index());
- add_file(create_generated_file("regs", [&process] { return procfs$pid_regs(process); }), dir.index());
- add_file(create_generated_file("fds", [&process] { return procfs$pid_fds(process); }), dir.index());
+ add_file(create_generated_file("vm", [&process] (SynthFSInode&) { return procfs$pid_vm(process); }), dir.index());
+ add_file(create_generated_file("vmo", [&process] (SynthFSInode&) { return procfs$pid_vmo(process); }), dir.index());
+ add_file(create_generated_file("stack", [&process] (SynthFSInode&) { return procfs$pid_stack(process); }), dir.index());
+ add_file(create_generated_file("regs", [&process] (SynthFSInode&) { return procfs$pid_regs(process); }), dir.index());
+ add_file(create_generated_file("fds", [&process] (SynthFSInode&) { return procfs$pid_fds(process); }), dir.index());
if (process.executable_inode())
- add_file(create_generated_file("exe", [&process] { return procfs$pid_exe(process); }, 00120777), dir.index());
+ add_file(create_generated_file("exe", [&process] (SynthFSInode&) { return procfs$pid_exe(process); }, 00120777), dir.index());
if (process.cwd_inode())
- add_file(create_generated_file("cwd", [&process] { return procfs$pid_cwd(process); }, 00120777), dir.index());
+ add_file(create_generated_file("cwd", [&process] (SynthFSInode&) { return procfs$pid_cwd(process); }, 00120777), dir.index());
}
void ProcFS::remove_process(Process& process)
@@ -179,7 +179,7 @@ void ProcFS::remove_process(Process& process)
m_pid2inode.remove(pid);
}
-ByteBuffer procfs$mm()
+ByteBuffer procfs$mm(SynthFSInode&)
{
// FIXME: Implement
InterruptDisabler disabler;
@@ -198,7 +198,7 @@ ByteBuffer procfs$mm()
return builder.to_byte_buffer();
}
-ByteBuffer procfs$mounts()
+ByteBuffer procfs$mounts(SynthFSInode&)
{
InterruptDisabler disabler;
StringBuilder builder;
@@ -213,7 +213,7 @@ ByteBuffer procfs$mounts()
return builder.to_byte_buffer();
}
-ByteBuffer procfs$cpuinfo()
+ByteBuffer procfs$cpuinfo(SynthFSInode&)
{
StringBuilder builder;
{
@@ -276,7 +276,7 @@ ByteBuffer procfs$cpuinfo()
return builder.to_byte_buffer();
}
-ByteBuffer procfs$kmalloc()
+ByteBuffer procfs$kmalloc(SynthFSInode&)
{
StringBuilder builder;
builder.appendf(
@@ -290,7 +290,7 @@ ByteBuffer procfs$kmalloc()
return builder.to_byte_buffer();
}
-ByteBuffer procfs$summary()
+ByteBuffer procfs$summary(SynthFSInode&)
{
InterruptDisabler disabler;
auto processes = Process::allProcesses();
@@ -313,7 +313,7 @@ ByteBuffer procfs$summary()
return builder.to_byte_buffer();
}
-ByteBuffer procfs$inodes()
+ByteBuffer procfs$inodes(SynthFSInode&)
{
extern HashTable<Inode*>& all_inodes();
auto& vfs = VFS::the();
@@ -326,6 +326,57 @@ ByteBuffer procfs$inodes()
return builder.to_byte_buffer();
}
+struct SysVariableData final : public SynthFSInodeCustomData {
+ virtual ~SysVariableData() override { }
+
+ enum Type {
+ Invalid,
+ Boolean,
+ };
+ Type type { Invalid };
+ Function<void()> change_callback;
+ void* address;
+};
+
+static ByteBuffer read_sys_bool(SynthFSInode& inode)
+{
+ ASSERT(inode.custom_data());
+ auto buffer = ByteBuffer::create_uninitialized(2);
+ auto& custom_data = *static_cast<const SysVariableData*>(inode.custom_data());
+ ASSERT(custom_data.type == SysVariableData::Boolean);
+ ASSERT(custom_data.address);
+ buffer[0] = *reinterpret_cast<bool*>(custom_data.address) ? '1' : '0';
+ buffer[1] = '\n';
+ return buffer;
+}
+
+static ssize_t write_sys_bool(SynthFSInode& inode, const ByteBuffer& data)
+{
+ ASSERT(inode.custom_data());
+ if (data.size() >= 1 && (data[0] == '0' || data[0] == '1')) {
+ auto& custom_data = *static_cast<const SysVariableData*>(inode.custom_data());
+ ASSERT(custom_data.address);
+ bool old_value = *reinterpret_cast<bool*>(custom_data.address);
+ bool new_value = data[0] == '1';
+ *reinterpret_cast<bool*>(custom_data.address) = new_value;
+ if (old_value != new_value && custom_data.change_callback)
+ custom_data.change_callback();
+ }
+ return data.size();
+}
+
+void ProcFS::add_sys_bool(String&& name, bool* var, Function<void()>&& change_callback)
+{
+ auto file = create_generated_file(move(name), move(read_sys_bool), move(write_sys_bool));
+ auto data = make<SysVariableData>();
+ data->type = SysVariableData::Boolean;
+ data->change_callback = move(change_callback);
+ data->address = var;
+ file->set_custom_data(move(data));
+ InterruptDisabler disabler;
+ add_file(move(file), m_sys_dir.index());
+}
+
bool ProcFS::initialize()
{
SynthFS::initialize();
@@ -335,6 +386,7 @@ bool ProcFS::initialize()
add_file(create_generated_file("summary", procfs$summary));
add_file(create_generated_file("cpuinfo", procfs$cpuinfo));
add_file(create_generated_file("inodes", procfs$inodes));
+ m_sys_dir = add_file(create_directory("sys"));
return true;
}
diff --git a/Kernel/ProcFileSystem.h b/Kernel/ProcFileSystem.h
index 5f6aa061d1..3b0050556f 100644
--- a/Kernel/ProcFileSystem.h
+++ b/Kernel/ProcFileSystem.h
@@ -18,9 +18,14 @@ public:
void add_process(Process&);
void remove_process(Process&);
+ void add_sys_file(String&&, Function<ByteBuffer(SynthFSInode&)>&& read_callback, Function<ssize_t(SynthFSInode&, const ByteBuffer&)>&& write_callback);
+
+ void add_sys_bool(String&&, bool*, Function<void()>&& change_callback = nullptr);
+
private:
ProcFS();
HashMap<pid_t, InodeIndex> m_pid2inode;
+ InodeIdentifier m_sys_dir;
};