Kernel, libc and userspace: Add basic errno support.

Kernel: Add an errno.h header with definitions for each header,
and return those, negated, from syscalls when there is an error.
mmap() returns an invalid address with errno encoded, instead of
returning a negated errno; this address is encoded as ffffffffffffffEE
where EE is errno in hex.

libc: make syscall() return -1 and set errno on error, instead of
returning the raw return value of the system call. Also, add mmap()
and munmap() wrappers in sys/mman.h :).

userspace: make the memeater program show the value of errno
when allocating memory fails.

Things to improve: add perror() and strerror() to make the errno
experience even better! >.<
This commit is contained in:
apio 2022-10-08 12:06:09 +02:00
parent ad115e9bab
commit 71e15e94af
15 changed files with 127 additions and 21 deletions

View File

@ -1,3 +1,4 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -13,5 +14,6 @@ int main()
printf("Allocating 4 MB of memory... %lx\n", (unsigned long)allocated);
sleep(1);
} while ((allocated = malloc(CHUNK)));
printf("Out of memory.\n");
printf("Out of memory. (errno=%d)\n", errno);
printf("Press any key to restart.\n");
}

5
kernel/include/errno.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#define EPERM 1
#define ENOMEM 12
#define EINVAL 22

View File

@ -1,17 +1,20 @@
#define MODULE "mem"
#include "errno.h"
#include "interrupts/Context.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
#include "memory/VMM.h"
#include <stddef.h>
#define MAP_FAIL(errno) 0xffffffffffffff00 | (unsigned char)(errno)
void sys_mmap(Context* context, void* address, size_t size, int flags)
{
if (size < 4096)
{
kdbgln("sys_mmap: size too small");
context->rax = 0;
context->rax = MAP_FAIL(EINVAL);
return;
}
int real_flags = MAP_USER;
@ -23,7 +26,7 @@ void sys_mmap(Context* context, void* address, size_t size, int flags)
if (kernelVMM.getPhysical((uint64_t)address) != (uint64_t)-1) // Address is already used.
{
kdbgln("attempt to mmap an already mapped address");
context->rax = 0;
context->rax = MAP_FAIL(ENOMEM);
return;
}
uint64_t offset = (uint64_t)address % 4096;
@ -37,7 +40,7 @@ void sys_mmap(Context* context, void* address, size_t size, int flags)
else
{
kdbgln("mmap failed");
context->rax = 0;
context->rax = MAP_FAIL(ENOMEM);
return;
}
}
@ -52,7 +55,7 @@ void sys_mmap(Context* context, void* address, size_t size, int flags)
else
{
kdbgln("mmap failed");
context->rax = 0;
context->rax = MAP_FAIL(ENOMEM);
return;
}
}
@ -60,17 +63,23 @@ void sys_mmap(Context* context, void* address, size_t size, int flags)
void sys_munmap(Context* context, void* address, size_t size)
{
kdbgln("sys_munmap: attempting to unmap %lx", (uint64_t)address);
if (size < 4096)
{
kdbgln("munmap failed: size is too small");
context->rax = -EINVAL;
return;
}
if (!address)
{
kdbgln("munmap failed: attempted to unmap page 0");
context->rax = -1;
context->rax = -EINVAL;
return;
}
uint64_t flags = kernelVMM.getFlags((uint64_t)address);
if (!(flags & MAP_USER))
{
kdbgln("munmap failed: attempted to unmap a kernel page");
context->rax = -1;
context->rax = -EINVAL;
return;
}
uint64_t offset = (uint64_t)address % 4096;

View File

@ -1,4 +1,5 @@
#include "bootboot.h"
#include "errno.h"
#include "interrupts/Context.h"
#include "render/Framebuffer.h"
#include <stdint.h>
@ -9,12 +10,12 @@ void sys_paint(Context* context, uint64_t x, uint64_t y, uint64_t w, uint64_t h,
{
if ((x + w) > bootboot.fb_width)
{
context->rax = -1;
context->rax = -EINVAL;
return;
}
if ((y + h) > bootboot.fb_height)
{
context->rax = -1;
context->rax = -EINVAL;
return;
}

View File

@ -1,8 +1,19 @@
#include "config.h"
#include "errno.h"
#include "interrupts/Context.h"
#include "std/stdio.h"
void sys_getversion(Context* context, char* buffer, size_t max)
{
if (!max)
{
context->rax = -EINVAL;
return;
}
if (!buffer)
{
context->rax = -EINVAL;
return;
}
context->rax = snprintf(buffer, max, "moon %s", moon_version());
}

View File

@ -0,0 +1,26 @@
#ifndef _BITS_ERROR_H
#define _BITS_ERROR_H
#include <errno.h>
#define _RETURN_WITH_ERRNO(rc, type) \
do { \
if (rc < 0) \
{ \
errno = (int)rc; \
return -1; \
} \
return (type)rc; \
} while (0)
#define _RETURN_WITH_MEMORY_ERRNO(rc, type) \
do { \
if ((unsigned long int)rc > 0xffffffffffffff00) \
{ \
errno = (int)((rc)&0xff); \
return (type)-1; \
} \
return (type)rc; \
} while (0)
#endif

View File

@ -1,5 +1,5 @@
#ifndef __BITS_MACROS_H
#define __BITS_MACROS_H
#ifndef _BITS_MACROS_H
#define _BITS_MACROS_H
#define noreturn __attribute__((noreturn))
#define align(n) __attribute__((aligned(n)))

View File

@ -0,0 +1,10 @@
#ifndef _ERRNO_H
#define _ERRNO_H
extern int errno;
#define EPERM 1
#define ENOMEM 12
#define EINVAL 22
#endif

View File

@ -0,0 +1,22 @@
#ifndef _SYS_MMAN_H
#define _SYS_MMAN_H
#include <stddef.h>
typedef unsigned long off_t;
#define MAP_FAILED (void*)-1
#ifdef __cplusplus
extern "C"
{
#endif
void* mmap(void*, size_t, int, int, int, off_t);
int munmap(void* addr, size_t len);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,6 +1,5 @@
#include <stddef.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <sys/mman.h>
int liballoc_lock()
{
@ -14,14 +13,12 @@ int liballoc_unlock()
void* liballoc_alloc(size_t size)
{
unsigned long int result = (unsigned long int)syscall(SYS_mmap, NULL, size * 4096, 1);
void* result = mmap(NULL, size * 4096, 0, 1, 0, 0);
if (result == MAP_FAILED) return 0;
return (void*)result;
}
int liballoc_free(void* address, size_t size)
{
int result = (int)syscall(SYS_munmap, address, size * 4096);
if (result < 0) return 1;
else
return 0;
return munmap(address, size * 4096);
}

3
libs/libc/src/errno.cpp Normal file
View File

@ -0,0 +1,3 @@
#include <errno.h>
int errno;

View File

@ -1,4 +1,5 @@
#include <luna.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>
@ -20,7 +21,6 @@ extern "C"
noreturn void __luna_abort(const char* message)
{
syscall(SYS_write, message, strlen(message));
syscall(SYS_exit);
__builtin_unreachable();
abort();
}
}

View File

@ -50,6 +50,7 @@ extern "C"
int puts(const char* s)
{
long nwritten = syscall(SYS_write, s, strlen(s));
if (nwritten < 0) return -1;
nwritten += syscall(SYS_write, "\n", 1);
return (int)nwritten;
}

View File

@ -0,0 +1,17 @@
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
extern "C"
{
// FIXME: Implement a POSIX-compliant mmap.
void* mmap(void* addr, size_t len, int, int flags, int, off_t)
{
return (void*)syscall(SYS_mmap, addr, len, flags);
}
int munmap(void* addr, size_t len)
{
return (int)syscall(SYS_munmap, addr, len);
}
}

View File

@ -1,3 +1,4 @@
#include <bits/error.h>
#include <luna.h>
#include <luna/syscall.h>
#include <stdarg.h>
@ -62,7 +63,8 @@ extern "C"
default: result = -1; break;
}
va_end(ap);
return result;
if (number == SYS_mmap) { _RETURN_WITH_MEMORY_ERRNO(result, long int); }
else { _RETURN_WITH_ERRNO(result, long); }
}
unsigned int sleep(unsigned int seconds)