Compare commits

..

29 Commits

Author SHA1 Message Date
6e22261116
kernel/ATA: Pass extra information to DeviceRegistry
All checks were successful
continuous-integration/drone/pr Build is passing
This is needed since merging e7d482e from main.
2023-05-20 13:12:41 +02:00
090c73910e
kernel+init: Create a device node in /dev to access the CDROM from userspace!
Still using PIO, though.
2023-05-20 13:12:41 +02:00
6855d13a6e
kernel/ATA: Read the CDROM's first sector using ATAPI PIO!!
Sadly, for some reason, DMA is not working right now.
This is a problem, as PIO is inconvenient. But hey, it works for now!
2023-05-20 13:12:41 +02:00
40f9afc13b
kernel/x86_64: Implement writing to PCI fields 2023-05-20 13:12:41 +02:00
463e2f7d34
kernel/PCI: Add bit enum for the Command field 2023-05-20 13:12:41 +02:00
91b891843e
kernel: Actually register interrupt handlers properly 2023-05-20 13:12:40 +02:00
57072ab0c5
kernel/ATA: Calculate block sizes for ATA devices as well 2023-05-20 13:12:40 +02:00
6c1990ab98
kernel/ATA: Send a READ CAPACITY packet to an ATA drive on initialization 2023-05-20 13:12:40 +02:00
dd4b5a58b2
kernel/ATA: Read the PCI Busmaster registers and start preparing for DMA 2023-05-20 13:12:40 +02:00
911e84644a
kernel/ATA: Read the Busmaster base port and verify it 2023-05-20 13:12:40 +02:00
e6b725f469
kernel: Handle device BARs properly 2023-05-20 13:12:40 +02:00
0866c207cd
kernel/ATA: Read ATA strings properly instead of backwards
Now we can see the model string. What does it say...

"QEMU DVD-ROM". Let's go!
2023-05-20 13:12:39 +02:00
313153b411
kernel/ATA: Implement enough to send an IDENTIFY command and read the model number :) 2023-05-20 13:12:39 +02:00
6f0f412d69
kernel/ATA: Handle drive IRQs in compatibility mode 2023-05-20 13:12:39 +02:00
21f8e1684d
kernel/CPU: Allow passing arbitrary data to interrupt handlers 2023-05-20 13:12:39 +02:00
32e9c8dd6f
kernel/ATA: Start reading/writing registers and detecting drives 2023-05-20 13:12:39 +02:00
7172521e6e
kernel: Warn if no ATA controller is found 2023-05-20 13:12:39 +02:00
d044818963
kernel: Add a KMutex class and use that for ATA::Controller locking 2023-05-20 13:12:39 +02:00
d73098153f
kernel/x86_64: Add basic ATA controller and channel identification 2023-05-20 13:12:38 +02:00
222ad84fbe
kernel/PCI: Add more PCI field types 2023-05-20 13:12:38 +02:00
2dd60428ac
kernel/x86_64: Add a way to register IRQ handlers from other kernel subsystems 2023-05-20 13:12:33 +02:00
5117b410db
apps: Add time
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-20 12:48:25 +02:00
6de90b3c93
libc: Add getrusage() 2023-05-20 12:48:17 +02:00
01111442d3
kernel: Add the getrusage() system call 2023-05-20 12:48:07 +02:00
1fa8aeecce
libos: Allow Process::exec to take a slice of StringViews instead of Strings as arguments 2023-05-20 12:47:10 +02:00
30d1dad149
libluna: Let String::join take a vector of StringViews instead of Strings 2023-05-20 12:46:33 +02:00
1db60b5a82
sh: Print a message on exit
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-20 12:07:56 +02:00
a7c6163e7c
libc: Add gettimeofday() 2023-05-20 12:05:22 +02:00
dc169124cc
libc: Add fchown, fchmod, and some POSIX feature test macros
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-19 19:59:20 +02:00
26 changed files with 254 additions and 16 deletions

View File

@ -27,3 +27,4 @@ luna_app(ipc-test.cpp ipc-test)
luna_app(mount.cpp mount)
luna_app(umount.cpp umount)
luna_app(ps.cpp ps)
luna_app(time.cpp time)

View File

@ -86,7 +86,11 @@ Result<int> luna_main(int argc, char** argv)
}
auto cmd = TRY(input_file->read_line());
if (cmd.is_empty()) break;
if (cmd.is_empty())
{
puts("exit");
break;
}
if (strspn(cmd.chars(), " \n") == cmd.length()) continue;

45
apps/time.cpp Normal file
View File

@ -0,0 +1,45 @@
#include <os/ArgumentParser.h>
#include <os/File.h>
#include <os/Process.h>
#include <stdio.h>
#include <sys/resource.h>
#include <sys/wait.h>
Result<int> luna_main(int argc, char** argv)
{
Vector<StringView> command;
os::ArgumentParser parser;
parser.add_description("Time a command.");
parser.add_system_program_info("time"_sv);
parser.set_vector_argument(command, true);
TRY(parser.parse(argc, argv));
auto pid = TRY(os::Process::fork());
if (pid == 0)
{
TRY(os::Process::exec(command[0], command.slice()));
unreachable();
}
if (waitpid(pid, nullptr, 0) < 0)
{
perror("waitpid");
return 1;
}
struct rusage usage;
if (getrusage(RUSAGE_CHILDREN, &usage) < 0)
{
perror("getrusage");
return 1;
}
auto cmdline = TRY(String::join(command, " "));
os::println("%s %d.%.2ds user %d.%.2ds system"_sv, cmdline.chars(), usage.ru_utime.tv_sec,
usage.ru_utime.tv_usec / 10000, usage.ru_stime.tv_sec, usage.ru_stime.tv_usec / 10000);
return 0;
}

View File

@ -39,6 +39,7 @@ set(SOURCES
src/sys/link.cpp
src/sys/uname.cpp
src/sys/mount.cpp
src/sys/resource.cpp
src/fs/VFS.cpp
src/fs/Pipe.cpp
src/fs/Mount.cpp

View File

@ -28,9 +28,9 @@ Result<u64> sys_pstat(Registers*, SyscallArgs args)
proc.ps_egid = thread->auth.egid;
proc.ps_state = (int)thread->state;
proc.ps_flags = thread->is_kernel ? PS_FLAG_KRNL : 0;
set_timespec(proc.ps_time, thread->ticks);
set_timespec(proc.ps_ktime, thread->ticks_in_kernel);
set_timespec(proc.ps_utime, thread->ticks_in_user);
set_timespec(proc.ps_time, thread->user_ticks_self + thread->kernel_ticks_self);
set_timespec(proc.ps_ktime, thread->kernel_ticks_self);
set_timespec(proc.ps_utime, thread->kernel_ticks_children);
strlcpy(proc.ps_name, thread->name.chars(), sizeof(proc.ps_name));
strlcpy(proc.ps_cwd, thread->current_directory_path.is_empty() ? "/" : thread->current_directory_path.chars(),
sizeof(proc.ps_cwd));

View File

@ -0,0 +1,32 @@
#include "memory/MemoryManager.h"
#include "sys/Syscall.h"
#include "thread/Scheduler.h"
#include <bits/rusage.h>
static void ticks_to_rusage(struct rusage* ru, u64 sticks, u64 uticks)
{
ru->ru_stime.tv_sec = sticks / 1000;
ru->ru_stime.tv_usec = (sticks % 1000) * 1000;
ru->ru_utime.tv_sec = uticks / 1000;
ru->ru_utime.tv_usec = (uticks % 1000) * 1000;
}
Result<u64> sys_getrusage(Registers*, SyscallArgs args)
{
int who = (int)args[0];
struct rusage* ru = (struct rusage*)args[1];
auto* current = Scheduler::current();
struct rusage kru;
switch (who)
{
case RUSAGE_SELF: ticks_to_rusage(&kru, current->kernel_ticks_self, current->user_ticks_self); break;
case RUSAGE_CHILDREN: ticks_to_rusage(&kru, current->kernel_ticks_children, current->user_ticks_children); break;
default: return err(EINVAL);
}
if (!MemoryManager::copy_to_user_typed(ru, &kru)) return err(EFAULT);
return 0;
}

View File

@ -50,6 +50,9 @@ Result<u64> sys_waitpid(Registers*, SyscallArgs args)
int status = (int)thread->status;
u64 id = thread->id;
current->user_ticks_children += thread->user_ticks_self;
current->kernel_ticks_children += thread->kernel_ticks_self;
thread->state = ThreadState::Dying;
Scheduler::signal_reap_thread();

View File

@ -261,11 +261,9 @@ namespace Scheduler
{
CPU::disable_interrupts();
g_current->ticks++;
if (is_in_kernel(regs)) g_current->ticks_in_kernel++;
if (is_in_kernel(regs)) g_current->kernel_ticks_self++;
else
g_current->ticks_in_user++;
g_current->user_ticks_self++;
g_current->ticks_left--;
@ -342,11 +340,11 @@ namespace Scheduler
for (const auto* thread : g_threads)
{
kdbgln("%p %c [%-20s] %4zu, parent = (%-18p,%zu), state = %d, ticks: (t:%04zu,k:%04zu,u:%04zu), status = "
kdbgln("%p %c [%-20s] %4zu, parent = (%-18p,%zu), state = %d, ticks: (k:%04zu,u:%04zu), status = "
"%d, cwd = %s",
thread, thread->is_kernel ? 'k' : 'u', thread->name.chars(), thread->id, thread->parent,
thread->parent ? thread->parent->id : 0, (int)thread->state, thread->ticks, thread->ticks_in_kernel,
thread->ticks_in_user, thread->status,
thread->parent ? thread->parent->id : 0, (int)thread->state, thread->kernel_ticks_self,
thread->user_ticks_self, thread->status,
thread->current_directory_path.is_empty() ? "/" : thread->current_directory_path.chars());
}

View File

@ -59,9 +59,10 @@ struct Thread : public LinkedListNode<Thread>
Credentials auth;
u64 ticks = 0;
u64 ticks_in_user = 0;
u64 ticks_in_kernel = 0;
u64 user_ticks_self = 0;
u64 kernel_ticks_self = 0;
u64 user_ticks_children = 0;
u64 kernel_ticks_children = 0;
u64 ticks_left;
u64 sleep_ticks_left;

View File

@ -26,6 +26,7 @@ set(SOURCES
src/sys/utsname.cpp
src/sys/mount.cpp
src/sys/pstat.cpp
src/sys/resource.cpp
)
if(${LUNA_ARCH} STREQUAL "x86_64")

View File

@ -0,0 +1,17 @@
/* bits/rusage.h: The rusage structure. */
#ifndef _BITS_RUSAGE_H
#define _BITS_RUSAGE_H
#include <bits/timespec.h>
struct rusage
{
struct timeval ru_utime;
struct timeval ru_stime;
};
#define RUSAGE_SELF 0
#define RUSAGE_CHILDREN 1
#endif

View File

@ -1,4 +1,4 @@
/* bits/timespec.h: The timespec structure. */
/* bits/timespec.h: The timespec and timeval structures. */
#ifndef _BITS_TIMESPEC_H
#define _BITS_TIMESPEC_H
@ -11,4 +11,10 @@ struct timespec
long tv_nsec;
};
struct timeval
{
time_t tv_sec;
suseconds_t tv_usec;
};
#endif

View File

@ -0,0 +1,20 @@
/* sys/resource.h: System resource management. */
#ifndef _SYS_RESOURCE_H
#define _SYS_RESOURCE_H
#include <bits/rusage.h>
#ifdef __cplusplus
extern "C"
{
#endif
/* Get this process or its children's resource usage. */
int getrusage(int who, struct rusage* ru);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -18,6 +18,9 @@ extern "C"
/* Change the mode bits of a file. */
int chmod(const char* path, mode_t mode);
/* Change the mode bits of a file descriptor. */
int fchmod(int fd, mode_t mode);
#pragma GCC push_options
#pragma GCC diagnostic ignored "-Wshadow"

21
libc/include/sys/time.h Normal file
View File

@ -0,0 +1,21 @@
/* sys/time.h: POSIX time types. */
#ifndef _SYS_TIME_H
#define _SYS_TIME_H
#include <bits/attrs.h>
#include <bits/timespec.h>
#ifdef __cplusplus
extern "C"
{
#endif
/* Get the current time of day. */
__deprecated int gettimeofday(struct timeval* tp, void* timezone);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -19,6 +19,7 @@ typedef __u64_t ino_t;
typedef __u32_t uid_t;
typedef __u32_t gid_t;
typedef __u64_t nlink_t;
typedef __i64_t suseconds_t;
typedef off_t fpos_t;

View File

@ -14,6 +14,9 @@
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#define _POSIX_CHOWN_RESTRICTED 200112L
#define _POSIX_SHELL 200112L
#ifdef __cplusplus
extern "C"
{
@ -55,6 +58,9 @@ extern "C"
/* Change the owner and group of a file. */
int chown(const char* path, uid_t uid, gid_t gid);
/* Change the owner and group of a file descriptor. */
int fchown(int fd, uid_t uid, gid_t gid);
/* Replace the current process with another one. On success, does not return. */
int execv(const char* path, char* const* argv);

13
libc/src/sys/resource.cpp Normal file
View File

@ -0,0 +1,13 @@
#include <bits/errno-return.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <unistd.h>
extern "C"
{
int getrusage(int who, struct rusage* ru)
{
long rc = syscall(SYS_getrusage, who, ru);
__errno_return(rc, int);
}
}

View File

@ -18,6 +18,12 @@ extern "C"
__errno_return(rc, int);
}
int fchmod(int fd, mode_t mode)
{
long rc = syscall(SYS_fchmodat, fd, "", mode, AT_EMPTY_PATH);
__errno_return(rc, int);
}
int stat(const char* path, struct stat* st)
{
long rc = syscall(SYS_fstatat, AT_FDCWD, path, st, 0);

View File

@ -1,6 +1,8 @@
#include <bits/errno-return.h>
#include <luna/Check.h>
#include <luna/Format.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
@ -148,4 +150,21 @@ extern "C"
{
return asctime(localtime(tp));
}
int gettimeofday(struct timeval* tp, void* timezone)
{
if (timezone)
{
fputs("gettimeofday: timezone was not NULL, abort\n", stderr);
abort();
}
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) < 0) return -1;
tp->tv_sec = ts.tv_sec;
tp->tv_usec = ts.tv_nsec / 1000;
return 0;
}
}

View File

@ -148,6 +148,12 @@ extern "C"
__errno_return(rc, int);
}
int fchown(int fd, uid_t uid, gid_t gid)
{
long rc = syscall(SYS_fchownat, fd, "", uid, gid, AT_EMPTY_PATH);
__errno_return(rc, int);
}
int execv(const char* path, char* const* argv)
{
return execve(path, argv, environ);

View File

@ -55,6 +55,9 @@ class String
/* Creates a single String consisting of a list of strings separated by a delimiter. */
static Result<String> join(const Vector<String>& vec, StringView delim);
/* Creates a single String consisting of a list of strings separated by a delimiter. */
static Result<String> join(const Vector<StringView>& vec, StringView delim);
/* Removes all trailing characters contained in delim. */
void trim(StringView delim);

View File

@ -5,7 +5,7 @@
_e(lseek) _e(mkdir) _e(execve) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) _e(geteuid) \
_e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \
_e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \
_e(umount) _e(pstat)
_e(umount) _e(pstat) _e(getrusage)
enum Syscalls
{

View File

@ -181,6 +181,23 @@ Result<String> String::join(const Vector<String>& vec, StringView delim)
return sb.string();
}
Result<String> String::join(const Vector<StringView>& vec, StringView delim)
{
if (vec.size() == 0) return String {};
if (vec.size() == 1) return from_string_view(vec[0]);
StringBuilder sb;
TRY(sb.add(vec[0]));
for (usize i = 1; i < vec.size(); i++)
{
TRY(sb.add(delim));
TRY(sb.add(vec[i]));
}
return sb.string();
}
int String::compare(const String* a, const String* b)
{
return strcmp(a->chars(), b->chars());

View File

@ -11,6 +11,7 @@ namespace os
static Result<pid_t> fork();
static Result<void> exec(StringView path, Slice<String> args, bool search_in_path = true);
static Result<void> exec(StringView path, Slice<StringView> args, bool search_in_path = true);
static Result<void> exec(StringView path, Slice<String> args, Slice<String> env, bool search_in_path = true);
};
}

View File

@ -24,6 +24,19 @@ namespace os
return err(errno);
}
Result<void> Process::exec(StringView path, Slice<StringView> args, bool search_in_path)
{
Vector<const char*> argv;
for (const auto& arg : args) { TRY(argv.try_append(arg.chars())); }
TRY(argv.try_append(nullptr));
if (search_in_path) execvp(path.chars(), const_cast<char**>(argv.data()));
else
execv(path.chars(), const_cast<char**>(argv.data()));
return err(errno);
}
Result<void> Process::exec(StringView path, Slice<String> args, Slice<String> env, bool search_in_path)
{
Vector<const char*> argv;