Compare commits

...

70 Commits

Author SHA1 Message Date
778999c8f4 Fix tests 2024-03-13 22:02:24 +01:00
d6ab0da231 Fix threadMsleep for 0 2024-03-13 21:40:51 +01:00
Mathieu Maret
dea0eba83d zero: keep track of allocated pages 2024-03-06 22:00:09 +01:00
86a0138d9c Merge pull request 'user_thread' (#9) from user_thread into master
Reviewed-on: #9
2024-02-28 20:24:12 +01:00
Mathieu Maret
dc4c465e94 Fix freeing squattedCtx when deleting thread 2024-02-27 23:14:09 +01:00
Mathieu Maret
1047400be2 Add missing debug.iso.gdb file 2024-02-26 23:03:49 +01:00
e0c392c16e Fix usleep for small values 2024-02-16 00:51:18 +01:00
4204087bd1 Implement thread_join
And use it for tinyc implementation
2024-02-16 00:51:07 +01:00
454f0875f5 Add isodebug target
Allow to take benefit from elf symboles
2024-02-15 23:41:58 +01:00
9713f527a8 Change userspace by partition type
Userspace should be on the first Linux partition found
2024-02-15 23:36:01 +01:00
70366fa7be Set pid_t type 2024-02-15 18:42:45 +01:00
a38a674a53 userspace: fix printf for unsigned 2024-02-15 18:42:45 +01:00
0688afa76d fix gettid==getpid for 1 thread 2024-02-15 17:20:47 +01:00
90436a4f46 Add usleep syscall 2024-02-14 18:43:47 +01:00
f9ce88e7a3 Makefile: use no intermediate file
To speedup, a bit, the compilation, use -pipe option for gcc
2024-02-14 18:28:11 +01:00
Mathieu Maret
1c2cd75c72 Add new thread sys call 2024-02-13 00:19:51 +01:00
Mathieu Maret
758017a8e7 mmap fix
Keep region list sorted on heap grow
Fix checking region overlap
Assert that mmap appends at loaded address for init
2024-02-12 18:25:35 +01:00
Mathieu Maret
f8b1b2c5a7 Fix printing long hex 2024-02-12 17:29:22 +01:00
Mathieu Maret
cb5e408525 Fix init ressource mapping 2024-02-12 09:41:56 +01:00
Mathieu Maret
a78aa420fd zero: less verbose 2024-02-11 19:00:17 +01:00
Mathieu Maret
fe6dfbc1c6 Add missing errno.h 2024-02-11 18:50:04 +01:00
Mathieu Maret
7b953e625e Show allocated/mapped stats 2024-02-11 15:34:33 +01:00
Mathieu Maret
026618a730 Merge close VR with same ressource mapped 2024-02-11 15:31:35 +01:00
607fcc7121 Merge pull request 'mmap' (#8) from mmap into master
Reviewed-on: #8
2024-02-11 15:29:57 +01:00
Mathieu Maret
c3f3eb435e implement munmap
Also add basic errno.h
2024-02-11 00:22:41 +01:00
Mathieu Maret
3339f8b059 Fix customData free 2024-02-10 22:49:24 +01:00
Mathieu Maret
88b9c3160b Improve headers and add sys/mman.h 2024-02-10 21:26:01 +01:00
Mathieu Maret
b352eab798 gdb: print_list can take the next element name in param 2024-02-08 23:15:29 +01:00
Mathieu Maret
b8c4c782de Fix findVirtualRegionBeforeAddr 2024-02-08 23:15:29 +01:00
Mathieu Maret
1895781213 Assign a mapped ressource to init prog 2024-02-08 23:15:29 +01:00
Mathieu Maret
cca78b269d init: use zero driver for stack alloc 2024-02-08 23:15:29 +01:00
Mathieu Maret
bf7008fc98 Fix write rights on pageflt 2024-02-08 23:15:29 +01:00
Mathieu Maret
ccfafe4a04 userspace: mmap test read and write 2024-02-08 23:15:29 +01:00
Mathieu Maret
62a1c1cefb zero: finish implementation 2024-02-08 23:15:29 +01:00
Mathieu Maret
f751835115 Improve debug message 2024-02-08 23:15:29 +01:00
Mathieu Maret
5a2042e577 Fix MMU context on ressource checking 2024-02-08 23:15:29 +01:00
Mathieu Maret
9fa9bd0411 userspace: add PROT flag for mmap 2024-02-08 23:15:29 +01:00
Mathieu Maret
a4873a7d30 Implement freeing ressource on uAS destroy 2024-02-08 23:15:29 +01:00
Mathieu Maret
205d174c8a pagefault_handler print error code before killing thread 2024-02-08 23:15:29 +01:00
Mathieu Maret
d9051ea59c Propagate page fault to ressource handler
Fix mmap arguments handling
2024-02-08 23:15:29 +01:00
Mathieu Maret
b9d741060f Add the ability to map/unmap a ressource 2024-02-08 23:15:29 +01:00
Mathieu Maret
1bb81fd57e Typo fix 2024-02-08 23:15:29 +01:00
Mathieu Maret
44c5551655 Wip: zero mmap 2024-02-08 23:15:29 +01:00
Mathieu Maret
b6fd550e7f Add some documentation 2024-02-08 23:15:26 +01:00
Mathieu Maret
8af3ba0762 mmap syscall declaration 2024-02-08 23:08:14 +01:00
Mathieu Maret
1e3be650f2 Put back kernel sym in debug.gdb
As gnu-debuglink does not seems to be working everwhere
2024-02-08 23:05:54 +01:00
Mathieu Maret
bd25bb8478 Add calloc, realloc, memmove. Sync klibc and libc 2024-01-31 12:57:35 +01:00
Mathieu Maret
946c47a988 Reorganize a bit includes like libc 2024-01-29 23:27:10 +01:00
a45dd96dc8 Merge pull request 'Implement malloc with a working free' (#7) from user_malloc into master
Reviewed-on: #7
2024-01-29 22:45:05 +01:00
Mathieu Maret
2b324ac62d Implement malloc with a working free 2024-01-29 22:43:26 +01:00
Mathieu Maret
edbbaec930 Correct some warnings 2024-01-26 22:53:39 +01:00
Mathieu Maret
45ec3c1a7b Fix brk api to match GLIC and add sbrk
Also free userspace allocated memory
2024-01-26 22:26:40 +01:00
Mathieu Maret
2359cf2744 process: add name getter 2024-01-26 22:23:58 +01:00
Mathieu Maret
ee42ba1350 Update gcc deps
Ubuntu gcc does not include libgcc for 32bits anymore and we are using access attribut from gcc 11
2024-01-26 22:23:10 +01:00
Mathieu Maret
01f5b872f2 ata: fix read/write on 2nd/4th disk 2023-11-21 00:06:09 +01:00
Mathieu Maret
8a4e0ff10f Fix ata device detection
After grub loading sector and LBA could have been altered
2023-11-20 23:11:12 +01:00
Mathieu Maret
f110f85498 Simplify partition setup
To prepare part1 for grub, part2 for userdata
2023-11-20 00:15:50 +01:00
Mathieu Maret
f05e017d45 backtrace: print function name instead of addr
Thx to the ELF header given by the bootloader
2023-11-20 00:12:58 +01:00
Mathieu Maret
60e71f6521 elf: move struct definition to header 2023-11-20 00:09:02 +01:00
Mathieu Maret
6a00aa4762 Correct ld variable type
They should be declared as char
2023-11-20 00:02:22 +01:00
Mathieu Maret
63757b1e0c Grub: change default timeout 2023-11-19 23:52:41 +01:00
Mathieu Maret
01d54dea85 Add partial multiboot2 support 2023-11-17 23:32:52 +01:00
Mathieu Maret
107bcedf90 Fix boot.S compilation 2023-11-17 15:32:24 +01:00
Mathieu Maret
cf3c2f10fd VGA: fix MAP when reconfigured 2023-11-17 14:54:26 +01:00
Mathieu Maret
a4f5a367ab Some userspace online doc 2023-11-11 00:09:00 +01:00
Mathieu Maret
bee58d9642 Add a (bad)free in userspace 2023-11-11 00:08:08 +01:00
Mathieu Maret
1120b40655 Rename Yolo syscall to Helo 2023-11-11 00:07:26 +01:00
Mathieu Maret
b0a192ce7c Add tinyC grammar desc 2023-11-10 22:54:35 +01:00
Mathieu Maret
d6dc298d35 Add more makefile doc 2023-11-09 23:46:26 +01:00
1e6614308a Merge pull request 'attribut_format' (#6) from attribut_format into master
Reviewed-on: #6
2023-11-09 23:45:14 +01:00
73 changed files with 2775 additions and 471 deletions

2
.gitignore vendored
View File

@ -1,6 +1,6 @@
serialOut
disk.img
kernel
kernel.sym
kernel.debug
userspace/user
docs/*.html

View File

@ -3,7 +3,7 @@ CPPFLAGS = -MMD
AS=nasm
ASFLAGS += -f elf32
LDFLAGS += -m elf_i386
CFLAGS += -m32 -Wall -Wextra -Werror -ffreestanding -fno-exceptions -fno-pie -fno-stack-protector -fno-tree-vectorize -D__KERNEL__
CFLAGS += -m32 -pipe -Wall -Wextra -Werror -ffreestanding -fno-exceptions -fno-pie -fno-stack-protector -fno-tree-vectorize -D__KERNEL__
#keep .i and .s
#CFLAGS += -save-temps
#CFLAGS += -fanalyzer -Wno-analyzer-malloc-leak -Wno-analyzer-out-of-bounds
@ -38,7 +38,7 @@ kernel kernel.debug &: $(asmobj) $(gasmobj) $(cobj) linker.ld
fd.iso: kernel
mkdir -p isodir/boot/grub
cp $< isodir/boot/
@printf "menuentry \"myos\" {\n\tmultiboot /boot/kernel\n}" > isodir/boot/grub/grub.cfg
@printf "set timeout=0\nset default=0\nmenuentry \"matos\" {\n\tmultiboot /boot/kernel\n}" > isodir/boot/grub/grub.cfg
grub-mkrescue -o $@ isodir
userspace: FORCE
@ -47,7 +47,7 @@ userspace: FORCE
FORCE:
@
doc: $(docobj)
doc: $(docobj) ## generate documentation
help: ## show this help
# regex for general help
@ -65,7 +65,7 @@ disk.img: disk.sfdisk userspace
# Before having filesystem support, just dump the user prog into the first partition
strip userspace/user -o userspace/user.strip
$(eval file_size:=$(shell du -b userspace/user.strip|awk '{print $$1}' | xargs printf "%016d" )) \
sed '1s/^/$(file_size)/' userspace/user.strip | dd of=disk.img seek=2048 bs=512
sed '1s/^/$(file_size)/' userspace/user.strip | dd of=disk.img seek=34816 bs=512
# NASM without preprocessing
%.o:%.asm
@ -88,20 +88,26 @@ test: clean kernel disk.img
run:kernel disk.img ## Run the OS on qemu
qemu-system-x86_64 -kernel $< -serial stdio $(QEMU_OPT)
debug: CFLAGS += $(DEBUG_FLAGS) ## Run the OS on qemu and attach a debugger to it (may need a clean befor to have the debug symbols)
debug: CFLAGS += $(DEBUG_FLAGS) ## Run the OS on qemu and attach a debugger to it (may need a clean before to have the debug symbols)
debug: CXXFLAGS += $(DEBUG_FLAGS)
debug:kernel kernel.debug disk.img
gdb -q -x debug.gdb
isodebug: CFLAGS += $(DEBUG_FLAGS) ## Same than previous but kernel is loaded by grub. So, for example, we can access the elf debug info
isodebug: CXXFLAGS += $(DEBUG_FLAGS)
isodebug:fd.iso disk.img
gdb -q -x debug.iso.gdb
debug_test: CFLAGS += $(DEBUG_FLAGS) -DRUN_TEST
debug_test: debug
screenshot:
screenshot: ## Take a screenshot of the qemu window
shutter --window=qemu -o screenshot_1.png -e && zopflipng screenshot_1.png screenshot_1.png
clean:
$(RM) kernel $(asmobj) $(gasmobj) $(cobj) $(deps) $(cinc) fd.iso kernel.debug kernel.map $(docobj)
$(RM) -r isodir
$(MAKE) -C userspace clean
.PHONY:
userspace screenshot

View File

@ -11,7 +11,7 @@ It's targetting x86 and inspirated by http://sos.enix.org/fr/PagePrincipale
To generate iso image
* `mtools xorriso (which is libisoburn on ArchLinux)`
* gcc >= 6
* gcc for 32bits (e.g. gcc-multilib for ubuntu) >= 11
* sfdisk (util-linux)
# Run it
@ -49,6 +49,16 @@ modify the disk image with your favorit tool (e.g. gparted) and re-generate disk
sfdisk -d > disk.sfdisk
# Multiboot
In arch/x86/boot, you can choose the assembly used to start the C part by removing the .opt extension
* boot.asm: intel syntax with multiboot support
* boot.S: GNU As syntax with multiboot support
* boot_multiboot2.S: GNU As syntax with multiboot2 support
/!\ multiboot2 is not supported by qemu for -kernel option (https://gitlab.com/qemu-project/qemu/-/issues/389).
So you may have to use the fd.iso image and modify the grub configuration from `multiboot /boot/kernel` to `multiboot2 /boot/kernel`
# Features

View File

@ -118,6 +118,8 @@ This is useful when debugging or when you implement call tracing.
*/
.size _start, . - _start
.global _stack_bottom
_stack_bottom: stack_bottom
.global _stack_stop
_stack_stop: stack_top
_stack_bottom:
.long stack_bottom
.global _stack_top
_stack_top:
.long stack_top

View File

@ -0,0 +1,125 @@
/* Inspired by from https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#boot_002eS */
/* boot.S - bootstrap the kernel */
/* Copyright (C) 1999, 2001, 2010 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define ASM_FILE 1
#include <multiboot2.h>
.section .multiboot
.align 4
/* Multiboot header. */
multiboot_header:
/* magic */
.long MULTIBOOT2_HEADER_MAGIC
/* ISA: i386 */
.long MULTIBOOT_ARCHITECTURE_I386
/* Header length. */
.long multiboot_header_end - multiboot_header
/* checksum */
.long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + (multiboot_header_end - multiboot_header))
multiboot_header_end:
.section .bss
.align 4096
stack_bottom:
.skip 16384 # 16 KiB
stack_top:
.section .text
.global _start
.type _start, @function
_start:
/*
The bootloader has loaded us into 32-bit protected mode on a x86
machine. Interrupts are disabled. Paging is disabled. The processor
state is as defined in the multiboot standard. The kernel has full
control of the CPU. The kernel can only make use of hardware features
and any code it provides as part of itself. There's no printf
function, unless the kernel provides its own <stdio.h> header and a
printf implementation. There are no security restrictions, no
safeguards, no debugging mechanisms, only what the kernel provides
itself. It has absolute and complete power over the
machine.
*/
/*
To set up a stack, we set the esp register to point to the top of our
stack (as it grows downwards on x86 systems). This is necessarily done
in assembly as languages such as C cannot function without a stack.
*/
mov $stack_top, %esp
mov $stack_bottom, %ebp
/*
This is a good place to initialize crucial processor state before the
high-level kernel is entered. It's best to minimize the early
environment where crucial features are offline. Note that the
processor is not fully initialized yet: Features such as floating
point instructions and instruction set extensions are not initialized
yet. The GDT should be loaded here. Paging should be enabled here.
C++ features such as global constructors and exceptions will require
runtime support to work as well.
*/
/* Reset EFLAGS. */
pushl $0
popf
/*
Enter the high-level kernel. The ABI requires the stack is 16-byte
aligned at the time of the call instruction (which afterwards pushes
the return pointer of size 4 bytes). The stack was originally 16-byte
aligned above and we've since pushed a multiple of 16 bytes to the
stack since (pushed 0 bytes so far) and the alignment is thus
preserved and the call is well defined.
*/
/* Push the pointer to the Multiboot information structure. */
pushl %ebx
/* Push the magic value. */
pushl %eax
call kmain
/*
If the system has nothing more to do, put the computer into an
infinite loop. To do that:
1) Disable interrupts with cli (clear interrupt enable in eflags).
They are already disabled by the bootloader, so this is not needed.
Mind that you might later enable interrupts and return from
kernel_main (which is sort of nonsensical to do).
2) Wait for the next interrupt to arrive with hlt (halt instruction).
Since they are disabled, this will lock up the computer.
3) Jump to the hlt instruction if it ever wakes up due to a
non-maskable interrupt occurring or due to system management mode.
*/
cli
1: hlt
jmp 1b
/*
Set the size of the _start symbol to the current location '.' minus its start.
This is useful when debugging or when you implement call tracing.
*/
.size _start, . - _start
.global _stack_bottom
_stack_bottom:
.long stack_bottom
.global _stack_top
_stack_top:
.long stack_top

View File

@ -45,30 +45,53 @@ int exceptionSetRoutine(int exception, exception_handler handler)
void print_handler(struct cpu_state *frame, ulong intr)
{
int intNbInt = intr;
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %d", intNbInt);
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %lu", intr);
printf("Exception %lu at 0x%p\n", intr, (void *)cpu_context_get_PC(frame));
asm("hlt");
}
void pagefault_handler(struct cpu_state *frame, ulong intr)
{
// PAGE_FAULT is a interrupt with an error code (see exception_wrapper.S)
uint32_t error_code = cpu_context_get_EX_err(frame);
struct thread *current = getCurrentThread();
struct uAddrSpace *as = processGetAddrSpace(current->process);
vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame);
if(!uAddrSpaceCheckNAlloc(as, faultAddr))
return;
if (cpu_context_is_in_user_mode(current->cpuState)) {
assert(frame == current->cpuState); // pagefault in kernel not supported ATM
printf("page fault while in thread [%s] at 0x%p when trying to access 0x%p err_code 0x%x\n", current->name,
(void *)cpu_context_get_PC(frame), (void *)faultAddr, cpu_context_get_EX_err(frame));
if (cpu_context_is_in_user_mode(frame)) {
struct uAddrSpace *as = processGetAddrSpace(current->process);
vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame);
int needMMUSetup =
(uAddrSpaceGetMMUContext(as) != getCurrentThread()->squattedContext);
if (needMMUSetup) {
threadChangeCurrentContext(uAddrSpaceGetMMUContext(as));
}
if (!uAddrSpaceHeapCheckNAlloc(as, faultAddr))
goto release_context;
int ret = uAddrSpaceSolvePageFault(as, faultAddr, error_code & 0x2);
if (!ret)
goto release_context;
printf(
"page fault while in thread [%s] at 0x%p when trying to access 0x%p err_code 0x%x ressource ret %d\n",
current->name, (void *)cpu_context_get_PC(frame), (void *)faultAddr, error_code,
ret);
printf("Killing User Thread\n");
threadExit();
release_context:
if (needMMUSetup)
threadChangeCurrentContext(NULL);
return;
}
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "PAGE FAULT %d", intr);
(void)intr;
for (;;)
continue;
}
@ -79,5 +102,6 @@ int exceptionSetup()
exceptionSetRoutine(i, print_handler);
}
exceptionSetRoutine(EXCEPTION_PAGE_FAULT, pagefault_handler);
return 0;
}

View File

@ -165,7 +165,7 @@
iret
.endm
/*List of exception w or w/o err codehttps://wiki.osdev.org/Exceptions*/
/* List of exception w or w/o err code https://wiki.osdev.org/Exceptions */
.irp exception_id, 8, 10, 11, 12, 13, 14, 17, 30
exception_mac_with_errcode exception_id
.endr

View File

@ -19,6 +19,8 @@
*/
#include "segment.h"
#include "gdt.h"
#include "stddef.h"
#include "stdint.h"
/**
* The sructure of a segment descriptor.

View File

@ -1,4 +1,6 @@
#include "idt.h"
#include "stddef.h"
static struct idtEntry idt[IDT_NUM];
int idtSetup()

View File

@ -1,5 +1,5 @@
#pragma once
#include "stdarg.h"
#include "stdint.h"
#define IDT_NUM 256

View File

@ -17,6 +17,7 @@
#define PAGING_MEM_USER (1U << 0)
#define PAGING_MEM_READ (1U << 1)
#define PAGING_MEM_WRITE (1U << 2)
#define PAGING_MEM_EXEC (1U << 3)
int pagingSetup(paddr_t lowerKernelAddr, paddr_t upperKernelAddr);

View File

@ -1,12 +1,19 @@
#pragma once
#include "paging.h"
#include "stdarg.h"
#include "stddef.h"
#include "types.h"
/** Arbitrary size allocator **/
/*
* Initialize malloc system
*/
int allocSetup(size_t sizeOfArea, vaddr_t *areaAddr, vaddr_t *descAddr, vaddr_t *entryAddr);
/*
* Add Slice for some simple/commun size
*/
int allocPopulate();
/*
* Allow malloc to allocate elements of this precise size.

View File

@ -7,6 +7,14 @@
#include "mem.h"
#include "stdarg.h"
struct memArea {
vaddr_t startAddr;
uint nbPages;
struct memArea *next;
struct memArea *prev;
};
static struct memArea *freeArea;
static struct memArea *usedArea;

View File

@ -1,6 +1,7 @@
#pragma once
#include "paging.h"
#include "stdarg.h"
#include "stdint.h"
/* Pure Virtual Memory Allocation */
@ -8,19 +9,29 @@
#define AREA_PHY_MAP (1<<0)
#define AREA_MEM_TOP PAGING_MIRROR_VADDR
struct memArea {
vaddr_t startAddr;
uint nbPages;
struct memArea *next;
struct memArea *prev;
};
/**
* Initialize the Area subsystem
**/
void areaInit(vaddr_t firstMemUsed, vaddr_t lastUsed, vaddr_t stack_bottom, vaddr_t stack_top);
/**
* Request a virtual memory area of @param nbPages
**/
vaddr_t areaAlloc(unsigned int nbPages, uint32_t flags);
// Remove an area from the free ones but do not add it into used ones.
// This area should be latter added woth areaAdd.
// Used by malloc to avoid recursivity issue
vaddr_t areaBook(unsigned int nbPages, uint32_t flags);
/**
* Free a virtual area
**/
int areaFree(vaddr_t addr);
/**
* Remove an area from the "free" ones but do not add it into used ones.
* This area should be latter added with areaAdd.
* Used by malloc to avoid recursivity issue
**/
vaddr_t areaBook(unsigned int nbPages, uint32_t flags);
/**
* Declare a virtual region to be managed by the subsytem
*/
int areaAdd(vaddr_t begin, vaddr_t end, int isFree);

View File

@ -27,7 +27,8 @@
*/
#include "errno.h"
#include "stdarg.h"
#include "stddef.h"
#include "stdint.h"
#include "types.h"
/**

View File

@ -5,6 +5,7 @@
#include "paging.h"
#include "thread.h"
#include "types.h"
#include "zero.h"
/**
* Make sure the program is in a valid ELF format, map it into memory,
@ -13,40 +14,11 @@
* @return 0 when the program is not a valid ELF
*/
uaddr_t loadElfProg(const char *prog, struct process * proc)
uaddr_t loadElfProg(const char *prog, struct process *proc)
{
int i;
uaddr_t lastUserAddr = 0;
/**
* Typedefs, constants and structure definitions as given by the ELF
* standard specifications.
*/
typedef unsigned long Elf32_Addr;
typedef unsigned long Elf32_Word;
typedef unsigned short Elf32_Half;
typedef unsigned long Elf32_Off;
// typedef signed long Elf32_Sword;
/* Elf identification */
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} __attribute__((packed)) Elf32_Ehdr_t;
struct uAddrSpace *as = processGetAddrSpace(proc);
/* e_ident value */
#define ELFMAG0 0x7f
@ -97,16 +69,6 @@ uaddr_t loadElfProg(const char *prog, struct process * proc)
#define EV_NONE 0 /* invalid version */
#define EV_CURRENT 1 /* current version */
typedef struct {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} __attribute__((packed)) Elf32_Phdr_t;
/* Reserved segment types p_type */
#define PT_NULL 0
@ -182,6 +144,11 @@ uaddr_t loadElfProg(const char *prog, struct process * proc)
if (lastUserAddr < uaddr) {
lastUserAddr = uaddr;
}
// Hack: Even if already allocated mark the adresse space as managed by a ressource
// So this address space is not used by another ressource.
uaddr = elf_phdrs[i].p_vaddr;
assert(zeroMmap(as, &uaddr, elf_phdrs[i].p_memsz, PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ, 0) == 0);
}
processInitHeap(proc, lastUserAddr);

View File

@ -3,4 +3,97 @@
#include "process.h"
#include "thread.h"
#include "types.h"
/**
* Typedefs, constants and structure definitions as given by the ELF
* standard specifications.
*/
typedef unsigned long Elf32_Addr;
typedef unsigned long Elf32_Word;
typedef unsigned short Elf32_Half;
typedef unsigned long Elf32_Off;
// typedef signed long Elf32_Sword;
/**
* ELF 32-bit format related structures.
* See http://www.cs.cmu.edu/afs/cs/academic/class/15213-f00/docs/elf.pdf
*/
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7fffffff
#define SHT_LOUSER 0x80000000
#define SHT_HIUSER 0xffffffff
/** ELF Header **/
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} __attribute__((packed)) Elf32_Ehdr_t;
/** ELF Section header */
typedef struct {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} __attribute__((packed)) Elf32_Shdr_t;
/** ELF Symbol **/
typedef struct {
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} __attribute__((packed)) Elf32_Sym_t;
/** ELF Program header **/
typedef struct {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} __attribute__((packed)) Elf32_Phdr_t;
#define ELF_SYM_TYPE(info) ((info) & 0xf)
#define ELF_SYM_TYPE_FUNC 0x2
uaddr_t loadElfProg(const char *prog, struct process *proc);

View File

@ -1,5 +1,5 @@
#pragma once
#include "stdarg.h"
#include "stdint.h"
// NIH http://wiki.osdev.org/Inline_Assembly/Examples#I.2FO_access
static inline void outb(uint16_t port, uint8_t val)

View File

@ -425,7 +425,8 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap)
case 'x': {
char val[sizeof(long long int) * 2];
unsigned int valIdx = 0;
long long int d = va_arg(ap, long long int);
unsigned long long int d =
va_arg(ap, unsigned long long int);
itoa(d, val, 16);
if (str) {
while (val[valIdx]) {
@ -453,7 +454,7 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap)
case 'x': {
char val[sizeof(int) * 2];
unsigned int valIdx = 0;
long int d = va_arg(ap, long int);
unsigned long int d = va_arg(ap, unsigned long int);
itoa(d, val, 16);
if (str) {
while (val[valIdx]) {

View File

@ -1,6 +1,7 @@
#pragma once
#include "assert.h"
#include "stdarg.h"
#include "stddef.h"
#include "minmax.h"
#define islower(c) (('a' <= (c)) && ((c) <= 'z'))
@ -36,8 +37,8 @@ int vprintf(const char *format, va_list ap) __attribute__ ((__format__ (printf,
int printf(const char *format, ...) __attribute__ ((__format__ (printf, 1, 2)));
// Could be used after malloc is available
int asprintf(char **strp, const char *fmt, ...);
int vasprintf(char **strp, const char *fmt, va_list ap);
int asprintf(char **strp, const char *fmt, ...) __attribute__ ((__format__ (printf, 2, 3)));
int vasprintf(char **strp, const char *fmt, va_list ap) __attribute__ ((__format__ (printf, 2, 0)));
/*
* Dummy printk for disabled debugging statements to use whilst maintaining

View File

@ -28,6 +28,7 @@
#include "time.h"
#include "types.h"
#include "vga.h"
#include "zero.h"
#define CHECK_FLAG(flags, bit) ((flags) & (1 << (bit)))
@ -35,7 +36,7 @@ void idleThread(void *arg)
{
(void)arg;
while (1) {
VGAPrintf(GREEN, BLACK, 0, VGA_HEIGHT - 1, "%d", (jiffies / HZ));
VGAPrintf(GREEN, BLACK, 0, VGA_HEIGHT - 1, "%d allocated %d, mapped %d", (jiffies / HZ), getNbAllocatedPage(), getNbMappedPage());
threadYield();
}
}
@ -45,7 +46,7 @@ void idleThread(void *arg)
#define FILE_MAX_SIZE 64 // In nb of sectors
void loadUserSpace()
{
struct ata_partition *part = ATAGetPartition(0);
struct ata_partition *part = ATAGetPartitionByType(PART_TYPE_LINUX);
if (part == NULL) {
printf("No user partition found\n");
@ -72,8 +73,8 @@ void loadUserSpace()
sectorToRead = DIV_ROUND_UP(sizeInt, DISK_SECTOR_SIZE) - 1;
}
if (sectorToRead > FILE_MAX_SIZE - 1) {
printf("File too long");
if (sectorToRead > FILE_MAX_SIZE - 1 || sectorToRead <= 0) {
printf("Invalid file size: %d (sector)\n", sectorToRead);
return;
}
@ -83,27 +84,28 @@ void loadUserSpace()
return;
}
struct process *proc = processCreate("UserSpace");
{
struct process *proc = processCreate("init");
struct uAddrSpace *as = processGetAddrSpace(proc);
threadChangeCurrentContext(processGetMMUContext(proc));
uaddr_t prog = loadElfProg(buf + FILE_HEADER_SIZE, proc);
if (prog == (uaddr_t)NULL) {
free(buf);
return;
threadChangeCurrentContext(processGetMMUContext(proc));
uaddr_t prog = loadElfProg(buf + FILE_HEADER_SIZE, proc);
if (prog == (uaddr_t)NULL) {
free(buf);
return;
}
// Alloc user stack
size_t stackSize = PAGE_SIZE * 2;
uaddr_t stack = PAGING_TOP_USER_ADDRESS - stackSize + 1;
zeroMmap(as, &stack, stackSize, PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ,
0);
threadCreateUser("init", proc, prog, 0, 0, stack + stackSize - 4);
processUnref(proc);
threadChangeCurrentContext(NULL);
}
// Alloc user stack
uaddr_t stackTop = 0xfffffffc;
uaddr_t stackBottom = ALIGN_DOWN(stackTop, PAGE_SIZE);
paddr_t stackPhy = allocPhyPage(1);
assert(pageMap(stackBottom, stackPhy,
PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ) == 0);
unrefPhyPage(stackPhy);
threadCreateUser("UserProg", proc, prog, 0, 0, stackTop);
processUnref(proc);
threadChangeCurrentContext(NULL);
free(buf);
}
@ -159,6 +161,9 @@ void kmain(unsigned long magic, unsigned long addr)
}
}
if (CHECK_FLAG(mbi->flags, 5)) {
stackSymbolSetup(mbi);
}
if (CHECK_FLAG(mbi->flags, 6)) {
memMapAvailable = 1;
}

View File

@ -1,5 +1,5 @@
#pragma once
#include "stdarg.h"
#include "stdint.h"
#include "types.h"
uint32_t log2(uint32_t x);

View File

@ -1,8 +1,9 @@
#pragma once
#include "stdarg.h"
#include "stdint.h"
#include "types.h"
/** Physical Page related function
/**
* Physical Page management
*/
#define PAGE_SHIFT 12U
@ -11,8 +12,8 @@
// Defined in linker.ld script
extern uint32_t __ld_kernel_begin;
extern uint32_t __ld_kernel_end;
extern char __ld_kernel_begin;
extern char __ld_kernel_end;
struct phyMemDesc {
paddr_t phy_addr;
@ -20,10 +21,33 @@ struct phyMemDesc {
struct phyMemDesc *next, *prev;
};
/**
* Initi Physical Page management subsystem
**/
int memSetup(paddr_t upperMem, paddr_t * firstUsed, paddr_t *lastUsed);
/**
* Declare a physical region to be managed by the physica page subsystem
**/
int memAddBank(paddr_t bottomMem, paddr_t topMem, int isFree);
/**
* Request @params nbPage free physical pages
**/
paddr_t allocPhyPage(uint nbPage);
/**
* Decrement the nb of user of a given physical page
**/
int unrefPhyPage(paddr_t addr);
/**
* Increment the nb of user of a given physical page
**/
int refPhyPage(paddr_t addr);
/**
* Return the number of physical allocated pages
**/
unsigned long getNbAllocatedPage(void);
void memGetStat(uint *free, uint *used);

View File

@ -1,5 +1,5 @@
#pragma once
#include "stdarg.h"
#include "stddef.h"
struct mmu_context;

418
core/multiboot2.h Normal file
View File

@ -0,0 +1,418 @@
/* Taken from https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#multiboot2_002eh */
/* multiboot2.h - Multiboot 2 header file. */
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MULTIBOOT_HEADER
#define MULTIBOOT_HEADER 1
/* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 32768
#define MULTIBOOT_HEADER_ALIGN 8
/* The magic field should contain this. */
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
/* This should be in %eax. */
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
/* Alignment of multiboot modules. */
#define MULTIBOOT_MOD_ALIGN 0x00001000
/* Alignment of the multiboot info structure. */
#define MULTIBOOT_INFO_ALIGN 0x00000008
/* Flags set in the flags member of the multiboot header. */
#define MULTIBOOT_TAG_ALIGN 8
#define MULTIBOOT_TAG_TYPE_END 0
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
#define MULTIBOOT_TAG_TYPE_MODULE 3
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
#define MULTIBOOT_TAG_TYPE_MMAP 6
#define MULTIBOOT_TAG_TYPE_VBE 7
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
#define MULTIBOOT_TAG_TYPE_APM 10
#define MULTIBOOT_TAG_TYPE_EFI32 11
#define MULTIBOOT_TAG_TYPE_EFI64 12
#define MULTIBOOT_TAG_TYPE_SMBIOS 13
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
#define MULTIBOOT_TAG_TYPE_NETWORK 16
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
#define MULTIBOOT_HEADER_TAG_END 0
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
#define MULTIBOOT_ARCHITECTURE_I386 0
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
#ifndef ASM_FILE
typedef unsigned char multiboot_uint8_t;
typedef unsigned short multiboot_uint16_t;
typedef unsigned int multiboot_uint32_t;
typedef unsigned long long multiboot_uint64_t;
struct multiboot_header
{
/* Must be MULTIBOOT_MAGIC - see above. */
multiboot_uint32_t magic;
/* ISA */
multiboot_uint32_t architecture;
/* Total header length. */
multiboot_uint32_t header_length;
/* The above fields plus this one must equal 0 mod 2^32. */
multiboot_uint32_t checksum;
};
struct multiboot_header_tag
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
};
struct multiboot_header_tag_information_request
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t requests[0];
};
struct multiboot_header_tag_address
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t header_addr;
multiboot_uint32_t load_addr;
multiboot_uint32_t load_end_addr;
multiboot_uint32_t bss_end_addr;
};
struct multiboot_header_tag_entry_address
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t entry_addr;
};
struct multiboot_header_tag_console_flags
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t console_flags;
};
struct multiboot_header_tag_framebuffer
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t width;
multiboot_uint32_t height;
multiboot_uint32_t depth;
};
struct multiboot_header_tag_module_align
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
};
struct multiboot_header_tag_relocatable
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t min_addr;
multiboot_uint32_t max_addr;
multiboot_uint32_t align;
multiboot_uint32_t preference;
};
struct multiboot_color
{
multiboot_uint8_t red;
multiboot_uint8_t green;
multiboot_uint8_t blue;
};
struct multiboot_mmap_entry
{
multiboot_uint64_t addr;
multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
#define MULTIBOOT_MEMORY_BADRAM 5
multiboot_uint32_t type;
multiboot_uint32_t zero;
};
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_tag
{
multiboot_uint32_t type;
multiboot_uint32_t size;
};
struct multiboot_tag_string
{
multiboot_uint32_t type;
multiboot_uint32_t size;
char string[0];
};
struct multiboot_tag_module
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end;
char cmdline[0];
};
struct multiboot_tag_basic_meminfo
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t mem_lower;
multiboot_uint32_t mem_upper;
};
struct multiboot_tag_bootdev
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t biosdev;
multiboot_uint32_t slice;
multiboot_uint32_t part;
};
struct multiboot_tag_mmap
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t entry_size;
multiboot_uint32_t entry_version;
struct multiboot_mmap_entry entries[0];
};
struct multiboot_vbe_info_block
{
multiboot_uint8_t external_specification[512];
};
struct multiboot_vbe_mode_info_block
{
multiboot_uint8_t external_specification[256];
};
struct multiboot_tag_vbe
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint16_t vbe_mode;
multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len;
struct multiboot_vbe_info_block vbe_control_info;
struct multiboot_vbe_mode_info_block vbe_mode_info;
};
struct multiboot_tag_framebuffer_common
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint64_t framebuffer_addr;
multiboot_uint32_t framebuffer_pitch;
multiboot_uint32_t framebuffer_width;
multiboot_uint32_t framebuffer_height;
multiboot_uint8_t framebuffer_bpp;
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
multiboot_uint8_t framebuffer_type;
multiboot_uint16_t reserved;
};
struct multiboot_tag_framebuffer
{
struct multiboot_tag_framebuffer_common common;
union
{
struct
{
multiboot_uint16_t framebuffer_palette_num_colors;
struct multiboot_color framebuffer_palette[0];
};
struct
{
multiboot_uint8_t framebuffer_red_field_position;
multiboot_uint8_t framebuffer_red_mask_size;
multiboot_uint8_t framebuffer_green_field_position;
multiboot_uint8_t framebuffer_green_mask_size;
multiboot_uint8_t framebuffer_blue_field_position;
multiboot_uint8_t framebuffer_blue_mask_size;
};
};
};
struct multiboot_tag_elf_sections
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t num;
multiboot_uint32_t entsize;
multiboot_uint32_t shndx;
char sections[0];
};
struct multiboot_tag_apm
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint16_t version;
multiboot_uint16_t cseg;
multiboot_uint32_t offset;
multiboot_uint16_t cseg_16;
multiboot_uint16_t dseg;
multiboot_uint16_t flags;
multiboot_uint16_t cseg_len;
multiboot_uint16_t cseg_16_len;
multiboot_uint16_t dseg_len;
};
struct multiboot_tag_efi32
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t pointer;
};
struct multiboot_tag_efi64
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint64_t pointer;
};
struct multiboot_tag_smbios
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint8_t major;
multiboot_uint8_t minor;
multiboot_uint8_t reserved[6];
multiboot_uint8_t tables[0];
};
struct multiboot_tag_old_acpi
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint8_t rsdp[0];
};
struct multiboot_tag_new_acpi
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint8_t rsdp[0];
};
struct multiboot_tag_network
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint8_t dhcpack[0];
};
struct multiboot_tag_efi_mmap
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t descr_size;
multiboot_uint32_t descr_vers;
multiboot_uint8_t efi_mmap[0];
};
struct multiboot_tag_efi32_ih
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t pointer;
};
struct multiboot_tag_efi64_ih
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint64_t pointer;
};
struct multiboot_tag_load_base_addr
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t load_base_addr;
};
#endif /* ! ASM_FILE */
#endif /* ! MULTIBOOT_HEADER */

View File

@ -5,12 +5,14 @@
#include "list.h"
#include "mmuContext.h"
#include "types.h"
#include "thread.h"
#include "uaddrspace.h"
struct process {
char name[PROCESS_NAME_MAX_LENGTH];
int ref;
int pid;
pid_t pid;
pid_t nextTid;
struct uAddrSpace *addrSpace;
struct thread *thList;
@ -47,7 +49,8 @@ struct process *processCreate(char *name)
new->ref = 1;
disable_IRQs(flags);
new->pid = nextPid++;
new->pid = nextPid++;
new->nextTid = new->pid;
list_add_tail(processList, new);
restore_IRQs(flags);
@ -66,7 +69,7 @@ void processListPrint()
struct thread *th;
int nbTh;
printf("%d %s %d %d\n", proc->pid, proc->name, processCountThread(proc), proc->ref);
printf("%lu %s %d %d\n", proc->pid, proc->name, processCountThread(proc), proc->ref);
list_foreach_named(proc->thList, th, nbTh, prevInProcess, nextInProcess)
{
if (th == cur) {
@ -164,6 +167,10 @@ int processSetName(struct process *proc, char *name)
return 0;
}
char *processGetName(struct process *proc){
return proc->name;
}
struct mmu_context *processGetMMUContext(struct process *proc)
{
return uAddrSpaceGetMMUContext(proc->addrSpace);
@ -176,3 +183,47 @@ struct uAddrSpace *processGetAddrSpace(struct process *proc){
int processInitHeap(struct process *proc, uaddr_t lastUserAddr){
return uAddrSpaceSetHeap(proc->addrSpace, lastUserAddr, 0);
}
pid_t processGetId(struct process *proc){
return proc->pid;
}
pid_t processGetNextTid(struct process *proc){
return proc->nextTid++;
}
//Should be called with IRQ disabled
struct thread *processGetThread(struct process *proc, pid_t tid)
{
int count;
struct thread *th;
struct thread *thFound = NULL;
list_foreach_named(proc->thList, th, count, prevInProcess, nextInProcess)
{
if (th->tid == tid) {
thFound = th;
break;
}
}
return thFound;
}
int processJoinThread(struct process *proc, pid_t tid)
{
uint32_t flags;
struct thread *th;
int ret = -1;
disable_IRQs(flags);
th = processGetThread(proc, tid);
if (th && th->wqExit) {
wait(th->wqExit);
ret = 0;
}
restore_IRQs(flags);
return ret;
}

View File

@ -1,9 +1,11 @@
#pragma once
#include "thread.h"
#include "types.h"
#define PROCESS_NAME_MAX_LENGTH 32
typedef unsigned long int pid_t;
struct process;
struct thread;
int processSetup();
struct process *processCreate(char *name);
@ -12,8 +14,12 @@ void processListPrint();
int processRef(struct process *proc);
int processUnref(struct process *proc);
int processSetName(struct process *proc, char *name);
char *processGetName(struct process *proc);
int processAddThread(struct process *proc, struct thread *th);
int processRemoveThread(struct thread *th);
struct mmu_context *processGetMMUContext(struct process *th);
struct uAddrSpace *processGetAddrSpace(struct process *proc);
int processInitHeap(struct process *proc, uaddr_t lastUserAddr);
pid_t processGetId(struct process *proc);
pid_t processGetNextTid(struct process *proc);
int processJoinThread(struct process *proc, pid_t tid);

View File

@ -1,7 +1,94 @@
#include "stack.h"
#include "elf.h"
#include "klibc.h"
#include "paging.h"
#include "types.h"
/** Defined in linker.ld script **/
extern char __multiboot_data_start;
extern char __multiboot_data_end;
static size_t multibootDataSize;
static size_t multibootUsage;
/** Initialized at 'StackSymbolSetup'. */
static Elf32_Sym_t *elfSymtab;
static size_t elfSymtabSize;
static const char *elfStrtab;
static size_t elfStrtabSize;
static void *stackSaveSection(const void *addr, size_t size, const char *sectionName)
{
if (size > (multibootDataSize - multibootUsage)) {
printf("No enough room to store %s (%d/%d). Increase multiboot_data section size",
sectionName, size, (multibootDataSize - multibootUsage));
return NULL;
}
void *destAddr = (void *)&__multiboot_data_start + multibootUsage;
memcpy((void *)destAddr, addr, size);
multibootUsage += size;
return destAddr;
}
/**
* Copy the symbols table and string table from a multiboot information.
* We need to copy them as they are loaded by the bootloader and could be override as soon
* as we play with memory around our loaded kernel.
* As special ELF section is allocated for this purpose.
*/
void stackSymbolSetup(multiboot_info_t *mbi)
{
/** Get the section header table as an array of section headers. */
Elf32_Shdr_t *sht = (Elf32_Shdr_t *)mbi->u.elf_sec.addr;
size_t sec_len = (size_t)mbi->u.elf_sec.num;
assert(mbi->u.elf_sec.size == sizeof(Elf32_Shdr_t));
multibootDataSize = &__multiboot_data_end - &__multiboot_data_start;
multibootUsage = 0;
/**
* The section header at index 'shndx' in the table is a meta section
* header. It contains a list of section header names in the table. We
* should look for section header names ".symtab" & ".strtab".
*/
const char *sh_names = (const char *)sht[mbi->u.elf_sec.shndx].sh_addr;
/** Loop through the table and look for ".symtab" & ".strtab". */
for (size_t i = 0; i < sec_len; ++i) {
const char *name = sh_names + sht[i].sh_name;
if (strcmp(name, ".symtab") == 0) {
assert(sht[i].sh_type == SHT_SYMTAB);
elfSymtab = stackSaveSection((void *)sht[i].sh_addr, sht[i].sh_size, name);
if (elfSymtab)
elfSymtabSize = sht[i].sh_size;
} else if (strcmp(name, ".strtab") == 0) {
assert(sht[i].sh_type == SHT_STRTAB);
elfStrtab = stackSaveSection((void *)sht[i].sh_addr, sht[i].sh_size, name);
if (elfStrtab)
elfStrtabSize = sht[i].sh_size;
}
}
}
/** Look up an address in symbols map and return its function name or NULL. */
const char *lookupSymbolName(uint32_t addr)
{
size_t symtab_len = elfSymtabSize / sizeof(Elf32_Sym_t);
for (size_t i = 0; i < symtab_len; ++i) {
if ((ELF_SYM_TYPE(elfSymtab[i].st_info) == ELF_SYM_TYPE_FUNC) &&
(addr >= elfSymtab[i].st_value) &&
(addr <= elfSymtab[i].st_value + elfSymtab[i].st_size)) {
return elfStrtab + elfSymtab[i].st_name;
}
}
return NULL;
}
void printStackTrace(unsigned int maxFrames)
{
#ifdef DEBUG
@ -21,7 +108,12 @@ void printStackTrace(unsigned int maxFrames)
break;
}
unsigned int *arguments = ebp + 2;
printf("[%d] 0x%x (", frame, eip);
const char *functionName = lookupSymbolName(eip);
if (functionName != NULL) {
printf("[%d] %s (", frame, functionName);
} else {
printf("[%d] 0x%x (", frame, eip);
}
int nbArg = 0;
do {
if ((_stack_bottom <= (vaddr_t)arguments) && ((vaddr_t)arguments <= _stack_top)) {

View File

@ -1,6 +1,8 @@
#pragma once
#include "multiboot.h"
#include "types.h"
extern vaddr_t _stack_bottom;
extern vaddr_t _stack_top;
void printStackTrace(unsigned int maxFrame);
void stackSymbolSetup(multiboot_info_t *mbi);

View File

@ -1,53 +1,5 @@
#pragma once
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#ifdef __GNUC__
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
#else
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
/* sysv */
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef __s8 int8_t;
typedef __s16 int16_t;
typedef __s32 int32_t;
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
typedef enum { FALSE = 0, TRUE } bool_t;
#define NULL ((void *)0)
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
#endif
//__builtin_va_list could be used instead
typedef char *va_list;
#define va_start(v, l) ((v) = (va_list) & (l) + sizeof(l))

29
core/stddef.h Normal file
View File

@ -0,0 +1,29 @@
#pragma once
typedef enum { FALSE = 0, TRUE } bool_t;
#define NULL ((void *)0)
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
typedef long int intptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
typedef int intptr_t;
#endif
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
typedef long int intptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
typedef int intptr_t;
#endif
typedef int wchar_t;

64
core/stdint.h Normal file
View File

@ -0,0 +1,64 @@
#pragma once
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#ifdef __GNUC__
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
#else
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
/* sysv */
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef __s8 int8_t;
typedef __s16 int16_t;
typedef __s32 int32_t;
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
#define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX >> 1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define INT_MAX ((int)(~0U >> 1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL >> 1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)
#define LLONG_MAX ((long long)(~0ULL >> 1))
#define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL)
#define SIZE_MAX (~(size_t)0)
#define PHYS_ADDR_MAX (~(phys_addr_t)0)
#define U8_MAX ((u8)~0U)
#define S8_MAX ((s8)(U8_MAX >> 1))
#define S8_MIN ((s8)(-S8_MAX - 1))
#define U16_MAX ((u16)~0U)
#define S16_MAX ((s16)(U16_MAX >> 1))
#define S16_MIN ((s16)(-S16_MAX - 1))
#define U32_MAX ((u32)~0U)
#define S32_MAX ((s32)(U32_MAX >> 1))
#define S32_MIN ((s32)(-S32_MAX - 1))
#define U64_MAX ((u64)~0ULL)
#define S64_MAX ((s64)(U64_MAX >> 1))
#define S64_MIN ((s64)(-S64_MAX - 1))

View File

@ -1,11 +1,15 @@
#include "syscall.h"
#include "kernel.h"
#include "keyboard.h"
#include "klibc.h"
#include "paging.h"
#include "process.h"
#include "stdarg.h"
#include "thread.h"
#include "types.h"
#include "uaccess.h"
#include "uaddrspace.h"
#include "zero.h"
int syscallExecute(int syscallId, const struct cpu_state *userCtx)
{
@ -22,8 +26,8 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
assert(0);
break;
}
case SYSCALL_ID_YOLO:
ret = printf("YOLO FROM USERSPACE\n");
case SYSCALL_ID_HELO:
ret = printf("HELLO FROM USERSPACE\n");
break;
case SYSCALL_ID_PUTC: {
unsigned int c;
@ -40,21 +44,150 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
printf("Got 5args from userspace %d %d %d %d %d\n", arg1, arg2, arg3, arg4, arg5);
break;
}
case SYSCALL_ID_BRK:{
case SYSCALL_ID_BRK: {
struct uAddrSpace *as;
uaddr_t newHeapTop;
as = processGetAddrSpace(getCurrentThread()->process);
as = processGetAddrSpace(getCurrentThread()->process);
ret = syscallGet1arg(userCtx, (unsigned int *)&newHeapTop);
if (ret != 0)
break;
threadChangeCurrentContext(uAddrSpaceGetMMUContext(as));
//TODO : what if *newHeapTop raise page fault?
// TODO : what if *newHeapTop raise page fault?
ret = sysBrk(as, newHeapTop);
threadChangeCurrentContext(NULL);
break;
}
case SYSCALL_ID_MMAP: {
struct uAddrSpace *as;
uaddr_t uaddr;
uaddr_t uaddr_ptr;
size_t size;
uint32_t rights;
uint32_t flags;
uaddr_t userPath;
char path[256];
as = processGetAddrSpace(getCurrentThread()->process);
ret = syscallGet5args(userCtx, (unsigned int *)&uaddr_ptr, (unsigned int *)&size,
(unsigned int *)&rights, (unsigned int *)&flags,
(unsigned int *)&userPath);
if (ret)
break;
if (memcpyFromUser((vaddr_t)&uaddr, uaddr_ptr, sizeof(uaddr)) != sizeof(uaddr)) {
ret = -EFAULT;
break;
}
strzcpyFromUser((vaddr_t *)path, (uaddr_t *)userPath, sizeof(path));
printf("Trying mmap for device %s at %lu\n", path, (vaddr_t)uaddr);
if (strcmp(path, "/dev/zero") == 0) {
ret = zeroMmap(as, &uaddr, size, rights, flags);
}
if (!ret) {
if (memcpyToUser(uaddr_ptr, (vaddr_t)&uaddr, sizeof(uaddr)) != sizeof(uaddr)) {
ret = -EFAULT;
break;
}
}
break;
}
case SYSCALL_ID_MUNMAP: {
struct uAddrSpace *as;
uaddr_t uaddr;
size_t size;
ret = syscallGet2args(userCtx, (unsigned int *)&uaddr, (unsigned int *)&size);
if (ret)
break;
as = processGetAddrSpace(getCurrentThread()->process);
ret = uAddrSpaceUnmap(as, uaddr, size);
break;
}
case SYSCALL_ID_NEW_THREAD: {
struct uAddrSpace *as;
thread_id_t threadIdPtr;
thread_id_t threadId;
uaddr_t funcAddr;
uint32_t arg1, arg2;
size_t stackSize;
ret = syscallGet5args(userCtx, (unsigned int *)&threadIdPtr,
(unsigned int *)&funcAddr, (unsigned int *)&arg1,
(unsigned int *)&arg2, (unsigned int *)&stackSize);
if (ret)
break;
if (stackSize <= 0) {
ret = -EINVAL;
break;
}
if (memcpyFromUser((vaddr_t)&threadId, threadIdPtr, sizeof(threadId)) !=
sizeof(threadId)) {
ret = -EFAULT;
break;
}
as = processGetAddrSpace(getCurrentThread()->process);
stackSize = ALIGN(stackSize, PAGE_SIZE);
uaddr_t stackAddr = 0;
ret = zeroMmap(as, &stackAddr, stackSize, PAGING_MEM_READ | PAGING_MEM_WRITE, 0);
if (ret)
break;
struct thread *th = threadCreateUser(NULL, getCurrentThread()->process, funcAddr,
arg1, arg2, stackAddr + stackSize);
if (th == NULL) {
ret = -ENOMEM;
uAddrSpaceUnmap(as, stackAddr, stackSize);
}
threadId = threadGetId(th);
if (memcpyToUser(threadIdPtr, (vaddr_t)&threadId, sizeof(threadId)) !=
sizeof(threadId)) {
ret = -EFAULT;
break;
}
break;
}
case SYSCALL_ID_USLEEP: {
unsigned int sleep;
ret = syscallGet1arg(userCtx, &sleep);
if (ret)
break;
ret = threadUsleep(sleep);
break;
}
case SYSCALL_ID_GETPID: {
ret = processGetId(getCurrentThread()->process);
break;
}
case SYSCALL_ID_GETTID: {
ret = threadGetId(getCurrentThread());
break;
}
case SYSCALL_ID_THREAD_JOIN: {
thread_id_t tid;
ret = syscallGet1arg(userCtx, (unsigned int *)&tid);
if (ret)
break;
ret = processJoinThread(getCurrentThread()->process, tid);
break;
}
default:
printf("Unknon syscall id %d\n", syscallId);
ret = -ENOENT;

View File

@ -1,14 +1,21 @@
#pragma once
#ifdef __KERNEL__
#include "cpu_context.h"
#include "cpu_context.h"
#endif
#define SYSCALL_ID_EXIT 1
#define SYSCALL_ID_YOLO 2
#define SYSCALL_ID_HELO 2
#define SYSCALL_ID_PUTC 3
#define SYSCALL_ID_READ 4
#define SYSCALL_ID_TEST 5
#define SYSCALL_ID_BRK 6
#define SYSCALL_ID_BRK 6
#define SYSCALL_ID_MMAP 7
#define SYSCALL_ID_MUNMAP 8
#define SYSCALL_ID_NEW_THREAD 9
#define SYSCALL_ID_USLEEP 10
#define SYSCALL_ID_GETPID 11
#define SYSCALL_ID_GETTID 12
#define SYSCALL_ID_THREAD_JOIN 13
#ifdef __KERNEL__
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);

View File

@ -12,6 +12,12 @@
static struct thread *currentThread;
static struct thread *threadWithTimeout;
static thread_id_t nextTid; // This is the TID for kernel thread ONLY
pid_t threadGetId(struct thread *th)
{
return th->tid;
}
static void threadPrepareContext(struct thread *th);
@ -83,7 +89,9 @@ struct thread *threadCreate(const char *name, cpu_kstate_function_arg1_t func, v
(cpu_kstate_function_arg1_t *)threadExit, 0))
goto free_mem;
thread->state = READY;
thread->state = READY;
thread->tid = nextTid++;
thread->wqExit = NULL;
uint32_t flags;
disable_IRQs(flags);
list_add_tail(currentThread, thread);
@ -110,6 +118,14 @@ struct thread *threadCreateUser(const char *name, struct process *proc, uaddr_t
}
thread->stackSize = THREAD_DEFAULT_STACK_SIZE;
thread->wqExit = (struct wait_queue * )malloc(sizeof(struct wait_queue));
if (!thread->wqExit) {
free((void *)thread->stackAddr);
free(thread);
return NULL;
}
waitQueueInit(thread->wqExit);
if (name)
strzcpy(thread->name, name, THREAD_NAME_MAX_LENGTH);
else
@ -124,6 +140,7 @@ struct thread *threadCreateUser(const char *name, struct process *proc, uaddr_t
goto free_mem;
thread->state = READY;
thread->tid = processGetNextTid(proc);
uint32_t flags;
disable_IRQs(flags);
list_add_tail(currentThread, thread);
@ -143,9 +160,14 @@ void threadDelete(struct thread *thread)
restore_IRQs(flags);
assert(thread->state == EXITING);
if (thread->squattedContext) {
threadChangeCurrentContext(NULL);
if (thread->wqExit) {
waitUp(thread->wqExit);
}
if (thread->squattedContext) {
mmuContextUnref(thread->squattedContext);
}
if (thread->process)
processRemoveThread(thread);
@ -210,17 +232,18 @@ int threadOnJieffiesTick()
disable_IRQs(flags);
list_foreach(currentThread, nextThread, idx)
{
if (nextThread->state == SLEEPING && nextThread->jiffiesSleeping) {
nextThread->jiffiesSleeping--;
if (!nextThread->jiffiesSleeping) {
if (nextThread->state == SLEEPING) {
if (nextThread->jiffiesSleeping)
nextThread->jiffiesSleeping--;
if (!nextThread->jiffiesSleeping)
nextThread->state = READY;
}
}
}
list_foreach_named(threadWithTimeout, nextThread, idx, timePrev, timeNext)
{
if (nextThread->state == WAITING && nextThread->jiffiesSleeping) {
nextThread->jiffiesSleeping--;
if (nextThread->state == WAITING) {
if (nextThread->jiffiesSleeping)
nextThread->jiffiesSleeping--;
if (!nextThread->jiffiesSleeping) {
nextThread->sleepHaveTimeouted = 1;
list_delete_named(threadWithTimeout, nextThread, timePrev, timeNext);
@ -292,6 +315,11 @@ int threadYield()
}
int threadMsleep(unsigned long msec)
{
return threadUsleep(msec*1000);
}
int threadUsleep(unsigned long usec)
{
uint32_t flags;
struct thread *next, *current;
@ -299,12 +327,12 @@ int threadMsleep(unsigned long msec)
disable_IRQs(flags);
current = currentThread;
assertmsg(current->state == RUNNING, "thread %s is in state %d for %lu\n", current->name,
current->state, msec);
assertmsg(current->state == RUNNING, "thread %s is in state %d for %lu us\n", current->name,
current->state, usec);
current->state = SLEEPING;
current->sleepHaveTimeouted = 0;
current->jiffiesSleeping = msecs_to_jiffies(msec);
current->jiffiesSleeping = usecs_to_jiffies(usec);
next = threadSelectNext();
assert(next != current);

View File

@ -4,6 +4,7 @@ struct thread;
#include "cpu_context.h"
#include "mem.h"
#include "process.h"
#include "wait.h"
#define THREAD_NAME_MAX_LENGTH 32
#define THREAD_DEFAULT_STACK_SIZE PAGE_SIZE
@ -17,8 +18,11 @@ typedef enum {
EXITING
} thread_state;
typedef unsigned long int thread_id_t;
struct thread {
char name[THREAD_NAME_MAX_LENGTH];
thread_id_t tid;
struct cpu_state *cpuState;
thread_state state;
vaddr_t stackAddr;
@ -32,6 +36,7 @@ struct thread {
// For User thread only
struct thread *nextInProcess, *prevInProcess;
struct process *process;
struct wait_queue *wqExit; // This will be signaled at thread exit (user only)
/**
* Address space currently "squatted" by the thread, or used to be
@ -83,8 +88,10 @@ int threadYield();
int threadWait(struct thread *current, struct thread *next, unsigned long msec);
int threadUnsched(struct thread *th);
int threadMsleep(unsigned long msec);
int threadUsleep(unsigned long usec);
int threadOnJieffiesTick();
struct thread *getCurrentThread();
int threadAddThread(struct thread *th);
int threadChangeCurrentContext(struct mmu_context *ctx);
int threadCount();
thread_id_t threadGetId(struct thread *th);

View File

@ -1,4 +1,6 @@
#include "time.h"
#include "stddef.h"
#include <stdint.h>
unsigned long volatile jiffies = INITIAL_JIFFIES;

View File

@ -1,5 +1,5 @@
#pragma once
#include <stdint.h>
#include "stdint.h"
#define HZ 100
/*

View File

@ -1,32 +1,5 @@
#pragma once
#define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX >> 1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define INT_MAX ((int)(~0U >> 1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL >> 1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)
#define LLONG_MAX ((long long)(~0ULL >> 1))
#define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL)
#define SIZE_MAX (~(size_t)0)
#define PHYS_ADDR_MAX (~(phys_addr_t)0)
#define U8_MAX ((u8)~0U)
#define S8_MAX ((s8)(U8_MAX >> 1))
#define S8_MIN ((s8)(-S8_MAX - 1))
#define U16_MAX ((u16)~0U)
#define S16_MAX ((s16)(U16_MAX >> 1))
#define S16_MIN ((s16)(-S16_MAX - 1))
#define U32_MAX ((u32)~0U)
#define S32_MAX ((s32)(U32_MAX >> 1))
#define S32_MIN ((s32)(-S32_MAX - 1))
#define U64_MAX ((u64)~0ULL)
#define S64_MAX ((s64)(U64_MAX >> 1))
#define S64_MIN ((s64)(-S64_MAX - 1))
// Virtual address
typedef unsigned long vaddr_t;

View File

@ -1,10 +1,12 @@
#include "uaccess.h"
#include "assert.h"
#include "errno.h"
#include "minmax.h"
#include "mmuContext.h"
#include "paging.h"
#include "process.h"
#include "thread.h"
#include "uaccess.h"
#include "types.h"
static int bindtoUserContext()
{
@ -42,6 +44,17 @@ static int memcpyUserMemNoCheck(vaddr_t dest, vaddr_t src, size_t size)
return size;
}
int memcpyToUser(uaddr_t to, vaddr_t from, size_t size)
{
if ((uint)to < PAGING_BASE_USER_ADDRESS)
return -EPERM;
if ((uint)to > PAGING_TOP_USER_ADDRESS - size)
return -EPERM;
return memcpyUserMemNoCheck(to, from, size);
}
int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size)
{
@ -52,3 +65,37 @@ int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size)
return memcpyUserMemNoCheck(to, from, size);
}
static int strzcpyFromUserNoCheck(char *to, char *from, size_t size)
{
int ret;
ret = bindtoUserContext();
if (ret != 0)
return ret;
for (unsigned int i = 0; i < size; i++) {
to[i] = from[i];
if (from[i] == '\0')
break;
}
if (size > 0)
to[size - 1] = '\0';
ret = unbindUserContext();
if (ret != 0)
return ret;
return size;
}
int strzcpyFromUser(vaddr_t *to, uaddr_t *from, size_t size)
{
if ((uint)from < PAGING_BASE_USER_ADDRESS)
return -EPERM;
if ((uint)from > PAGING_TOP_USER_ADDRESS - size)
return -EPERM;
return strzcpyFromUserNoCheck((char *)to, (char *)from, size);
}

View File

@ -1,5 +1,8 @@
#pragma once
#include "types.h"
#include "stddef.h"
#include "stdarg.h"
int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size);
int memcpyToUser(uaddr_t to, vaddr_t from, size_t size);
int strzcpyFromUser(vaddr_t *to, uaddr_t *from, size_t size);

View File

@ -1,9 +1,12 @@
#include "uaddrspace.h"
#include "alloc.h"
#include "errno.h"
#include "kernel.h"
#include "klibc.h"
#include "list.h"
#include "mem.h"
#include "mmuContext.h"
#include "paging.h"
#include "process.h"
#include "stdarg.h"
#include "thread.h"
@ -12,18 +15,6 @@
#include <stddef.h>
#include <stdint.h>
struct uAddrVirtualReg {
uaddr_t addr;
size_t size;
int right; // PAGING_MEM_*
uint32_t offset; // in the mappedRessource
uint flags;
struct mappedRessource *res;
struct uAddrVirtualReg *nextInAddrSpace, *prevInAddrSpace;
struct uAddrVirtualReg *nextInMappedRes, *prevInMappedRes;
};
struct uAddrSpace {
struct process *process; // The process that is represented by this AS
struct mmu_context *ctx; // The corresponding MMU configuration
@ -31,26 +22,89 @@ struct uAddrSpace {
struct uAddrVirtualReg *listVirtualReg; // List of Virtual Region used by this process
uaddr_t heapStart; // Start of the Head
size_t heapSize; // Hep size -> modified by brk()
size_t heapSize; // Heap size -> modified by brk()
};
struct mappedRessourceOps {
int (*open)(struct uAddrVirtualReg *vreg);
int (*close)(struct uAddrVirtualReg *vreg);
int (*unmap)(struct uAddrVirtualReg *vregi, uaddr_t addr, size_t size);
int (*nopage)(struct uAddrVirtualReg *vregi, uaddr_t addr,
int right); // Called by the pageflt handler when the page is missing
};
static int hasOverlap(uaddr_t addr1, size_t size1, uaddr_t addr2, size_t size2)
{
return max(addr1, addr2) < min(addr1 + size1, addr2 + size2);
}
struct mappedRessource {
int right; // PAGING_MEM_*
struct mappedRessourceOps *ops;
struct uAddrVirtualReg *listVirtualReg;
};
static struct uAddrVirtualReg *findVirtualRegionFromAddr(struct uAddrSpace *as, uaddr_t uaddr, size_t size)
{
struct uAddrVirtualReg *reg;
int idx;
list_foreach_named(as->listVirtualReg, reg, idx, prevInAddrSpace, nextInAddrSpace)
{
if (hasOverlap(reg->addr, reg->size, uaddr, size))
return reg;
}
return NULL;
}
static struct uAddrVirtualReg *findVirtualRegionBeforeAddr(struct uAddrSpace *as,
uaddr_t uaddr)
{
struct uAddrVirtualReg *reg, *prev = NULL;
int idx;
list_foreach_named(as->listVirtualReg, reg, idx, prevInAddrSpace, nextInAddrSpace)
{
if (uaddr < reg->addr)
break;
prev = reg;
}
return prev;
}
/**
* Find a address not alreay used in the virtual region of the AS.
* This address will be equals to uaddr if possible and could take size
*/
static uaddr_t findFreeAddrInVirtualRegion(struct uAddrSpace *as, uaddr_t uaddr, size_t size)
{
struct uAddrVirtualReg *reg, *regNext, *regOver;
if (uaddr < PAGING_BASE_USER_ADDRESS)
uaddr = PAGING_BASE_USER_ADDRESS;
if(uaddr > PAGING_TOP_USER_ADDRESS - size)
uaddr = PAGING_TOP_USER_ADDRESS - size;
reg = findVirtualRegionFromAddr(as, uaddr, size);
if (!reg)
return uaddr;
int idx;
regOver = reg;
//Find last region that overlap
list_foreach_named(reg->nextInAddrSpace, regNext, idx, prevInAddrSpace, nextInAddrSpace){
if(!hasOverlap(uaddr, size, regNext->addr, regNext->size))
break;
regOver = regNext;
}
uaddr = regOver->addr + regOver->size;
list_foreach_named(regOver->nextInAddrSpace, regNext, idx, prevInAddrSpace,
nextInAddrSpace)
{
if (!hasOverlap(uaddr, size, regNext->addr, regNext->size) &&
uaddr <= (PAGING_TOP_USER_ADDRESS - size)) {
return uaddr;
}
if (reg == regNext) // Already checked region
break;
uaddr = regNext->addr + regNext->size;
}
return (uaddr_t)NULL;
}
struct uAddrSpace *uAddrSpaceCreate(struct process *proc)
{
struct uAddrSpace *addr = (struct uAddrSpace *)malloc(sizeof(struct uAddrSpace));
struct uAddrSpace *addr = (struct uAddrSpace *)zalloc(sizeof(struct uAddrSpace));
if (addr == NULL)
return NULL;
@ -64,16 +118,130 @@ struct uAddrSpace *uAddrSpaceCreate(struct process *proc)
}
addr->process = proc;
list_init(addr->listVirtualReg);
return addr;
}
int uAddrSpaceDelete(struct uAddrSpace *addr)
{
// TODO Work on Virtual Region
struct uAddrVirtualReg *reg;
list_collapse_named(addr->listVirtualReg, reg, nextInAddrSpace, prevInAddrSpace) {
if (reg->res == NULL) {
// This is memory allocated for the heap just unmap it to free it
pr_devel("Freeing heap 0x%lx for process %s\n", reg->addr,
processGetName(addr->process));
pageUnmap(reg->addr);
free(reg);
} else {
if(reg->res->ops){
if(reg->res->ops->unmap)
reg->res->ops->unmap(reg, reg->addr, reg->size);
if(reg->res->ops->close)
reg->res->ops->close(reg);
}
free(reg);
}
}
return mmuContextUnref(addr->ctx);
}
/**
* Find the associated uAddrVirtualReg associated to the unmap space and free them;
*/
int uAddrSpaceUnmap(struct uAddrSpace *as, uaddr_t uaddr, size_t size)
{
if (uaddr < PAGING_BASE_USER_ADDRESS || uaddr > PAGING_TOP_USER_ADDRESS - size)
return -EINVAL;
if (!IS_ALIGNED(uaddr, PAGE_SIZE) || size <= 0)
return -EINVAL;
if(!as)
return -EINVAL;
size = ALIGN(size, PAGE_SIZE);
struct uAddrVirtualReg *reg = as->listVirtualReg;
struct uAddrVirtualReg *lastReg = reg ? reg->prevInAddrSpace : NULL;
while (reg != NULL) {
if (reg->addr > uaddr + size)
break;
struct uAddrVirtualReg *next = reg->nextInAddrSpace;
// The Virtual Region is completly inside the unmaped space
if (reg->addr >= uaddr && (reg->addr + reg->size <= uaddr + size)) {
list_delete_named(as->listVirtualReg, reg, prevInAddrSpace, nextInAddrSpace);
list_delete_named(reg->res->listVirtualReg, reg, prevInMappedRes, nextInMappedRes);
if (reg->res->ops && reg->res->ops->unmap)
reg->res->ops->unmap(reg, uaddr, size);
if (reg->res->ops && reg->res->ops->close)
reg->res->ops->close(reg);
if (reg == next)//singleton
next = NULL;
free(reg);
// Unmaped space is inside and smaller than the VR
// VR should be splitted
} else if (reg->addr > uaddr && (reg->addr + reg->size < uaddr + size)) {
struct uAddrVirtualReg *new =
(struct uAddrVirtualReg *)zalloc(sizeof(struct uAddrSpace));
if (!new)
return -ENOMEM;
new->addr = uaddr + size;
new->size = reg->addr + reg->size - (uaddr + size);
new->right = reg->right;
new->offset = uaddr + size - reg->addr;
reg->size = uaddr - reg->addr;
list_insert_after_named(as->listVirtualReg, reg, new, prevInAddrSpace,
nextInAddrSpace);
list_insert_after_named(reg->res->listVirtualReg, reg, new, prevInMappedRes,
nextInMappedRes);
if (reg->res->ops && reg->res->ops->unmap)
reg->res->ops->unmap(reg, uaddr, size);
if (new->res->ops && new->res->ops->open)
new->res->ops->open(new);
break;
// Only affect the beginning
} else if (uaddr <= reg->addr && uaddr + size > reg->addr) {
size_t offset = uaddr + size - reg->addr;
reg->size -= offset;
reg->offset += offset;
reg->addr += offset;
if (reg->res->ops && reg->res->ops->unmap)
reg->res->ops->unmap(reg, uaddr, size);
break;
// Only affect the end
} else if (uaddr > reg->addr && uaddr < reg->addr + size &&
uaddr + size > reg->addr + reg->size) {
size_t unmapSize = reg->addr + reg->size - uaddr;
reg->size = uaddr - reg->addr;
if (reg->res->ops && reg->res->ops->unmap)
reg->res->ops->unmap(reg, uaddr, unmapSize);
}
reg = next;
if (reg == lastReg)
break;
}
int needMMUSetup = as->ctx != getCurrentThread()->squattedContext;
if (needMMUSetup)
threadChangeCurrentContext(as->ctx);
for (vaddr_t addr = uaddr; addr < uaddr + size; addr += PAGE_SIZE) {
pageUnmap(addr);
}
if (needMMUSetup)
threadChangeCurrentContext(NULL);
return 0;
}
struct mmu_context *uAddrSpaceGetMMUContext(struct uAddrSpace *addr)
{
return addr->ctx;
@ -102,30 +270,190 @@ uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop)
incSize = ALIGN(newHeapTop - (as->heapStart + as->heapSize), PAGE_SIZE);
if (incSize < 0){
//FIXME
return as->heapStart + as->heapSize;
}
as->heapSize += incSize;
return 0;
return as->heapStart + as->heapSize;
}
int uAddrSpaceCheckNAlloc(struct uAddrSpace *as, vaddr_t addr)
int uAddrSpaceHeapCheckNAlloc(struct uAddrSpace *as, vaddr_t addr)
{
pr_devel("Checking %lx inside %lx and %lx\n", addr, as->heapStart, as->heapStart +as->heapSize);
struct uAddrVirtualReg *newReg;
int right = PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ;
pr_devel("Heap check: 0x%lx inside 0x%lx and 0x%lx\n", addr, as->heapStart,
as->heapStart + as->heapSize);
if (addr < as->heapStart || addr >= as->heapStart + as->heapSize) {
return -1;
}
pr_devel("Alloc heap for process %s\n", processGetName(as->process));
vaddr_t addrAlign = ALIGN_DOWN(addr, PAGE_SIZE);
paddr_t ppage = allocPhyPage(1);
if (0 != pageMap(addrAlign, ppage, PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ)) {
return -1;
}
if (0 != pageMap(addrAlign, ppage, right))
goto free_ppage;
newReg = zalloc(sizeof(struct uAddrVirtualReg));
if (newReg == NULL)
goto free_ppage;
newReg->addr = addrAlign;
newReg->size = PAGE_SIZE;
newReg->right = right;
// keep the AS list sorted
struct uAddrVirtualReg *prev = findVirtualRegionBeforeAddr(as, addrAlign);
if (prev)
list_insert_after_named(as->listVirtualReg, prev, newReg, prevInAddrSpace,
nextInAddrSpace);
else
list_add_tail_named(as->listVirtualReg, newReg, nextInAddrSpace, prevInAddrSpace);
unrefPhyPage(ppage);
return 0;
free_ppage:
unrefPhyPage(ppage);
return -1;
}
static struct uAddrVirtualReg *uAddrSpaceMergeVr(struct uAddrVirtualReg *prev,
struct uAddrVirtualReg *next)
{
if (prev && next && prev->addr + prev->size == next->addr && prev->right == next->right &&
prev->res == next->res && prev->flags == next->flags && prev->offset == next->offset) {
prev->size += next->size;
return next;
} else
return NULL;
}
int uAddrSpaceMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights,
uint32_t flags, struct mappedRessource *res, uint32_t offset )
{
int ret = 0;
uaddr_t hint_uaddr = *uaddr;
if (res == NULL || res->ops == NULL || res->ops->nopage == NULL)
return -ENOENT;
if (!IS_ALIGNED(hint_uaddr, PAGE_SIZE) || size <= 0)
return -EINVAL;
if (flags & UA_MAP_SHARED) {
if (((rights & PAGING_MEM_READ) && !(res->allowedRight & PAGING_MEM_READ)) ||
((rights & PAGING_MEM_WRITE) && !(res->allowedRight & PAGING_MEM_WRITE)) ||
((rights & PAGING_MEM_EXEC) && !(res->allowedRight & PAGING_MEM_EXEC)))
return -EPERM;
}
size = ALIGN(size, PAGE_SIZE);
struct uAddrVirtualReg *reg =
(struct uAddrVirtualReg *)malloc(sizeof(struct uAddrVirtualReg));
if (!reg)
return -ENOMEM;
if (flags & UA_MAP_FIXED) {
if (hint_uaddr < PAGING_BASE_USER_ADDRESS ||
hint_uaddr > PAGING_TOP_USER_ADDRESS - size) {
ret = -EINVAL;
goto free_reg;
}
ret = uAddrSpaceUnmap(as, hint_uaddr, size);
if (ret)
goto free_reg;
} else {
hint_uaddr = findFreeAddrInVirtualRegion(as, hint_uaddr, size);
if (!hint_uaddr) {
ret = -ENOMEM;
goto free_reg;
}
}
reg->addr = hint_uaddr;
reg->size = size;
reg->right = rights;
reg->res = res;
reg->offset = offset;
// keep the AddrSpace list sorted
struct uAddrVirtualReg *prev = findVirtualRegionBeforeAddr(as, hint_uaddr);
bool_t regIsNew = TRUE;
if (prev) {
struct uAddrVirtualReg *toFree = uAddrSpaceMergeVr(prev, reg);
if (toFree) {
pr_devel("Merge VR with prev\n");
reg = prev;
regIsNew = FALSE;
free(toFree);
}
toFree = uAddrSpaceMergeVr(reg, prev->nextInAddrSpace);
if (toFree) {
pr_devel("Merge VR with next\n");
regIsNew = FALSE;
if (toFree->res && toFree->res->ops && toFree->res->ops->close)
toFree->res->ops->close(toFree);
list_delete_named(as->listVirtualReg, toFree, prevInAddrSpace, nextInAddrSpace);
list_delete_named(toFree->res->listVirtualReg, toFree, prevInMappedRes,
nextInMappedRes);
free(toFree);
}
if (regIsNew)
list_insert_after_named(as->listVirtualReg, prev, reg, prevInAddrSpace,
nextInAddrSpace);
} else
list_add_tail_named(as->listVirtualReg, reg, prevInAddrSpace, nextInAddrSpace);
if (regIsNew) {
list_add_tail_named(reg->res->listVirtualReg, reg, prevInMappedRes, nextInMappedRes);
if (res->onResMapped) {
int cbret = res->onResMapped(reg);
if (cbret) {
pr_devel("Call back failed on ressource mmaped\n");
ret = uAddrSpaceUnmap(as, reg->addr, reg->size);
}
}
if (res->ops->open)
res->ops->open(reg);
}
*uaddr = hint_uaddr;
return ret;
free_reg:
free(reg);
return ret;
}
/**
* Check if @param faultAddr could be managed by the uAddrVirtualReg from @param as
**/
int uAddrSpaceSolvePageFault(struct uAddrSpace *as, vaddr_t faultAddr, int isWriteAccess)
{
struct uAddrVirtualReg *reg;
int rights = PAGING_MEM_READ | PAGING_MEM_USER;
reg = findVirtualRegionFromAddr(as, faultAddr, 1);
if (reg == NULL)
return -EFAULT;
pr_devel("Virtual Region for pageflt found\n");
if (isWriteAccess && !(reg->right & PAGING_MEM_WRITE))
return -EACCES;
if (isWriteAccess || (reg->right & PAGING_MEM_WRITE))
rights |= PAGING_MEM_WRITE;
if (reg->res->ops->nopage(reg, faultAddr, rights))
return -EFAULT;
return 0;
}

View File

@ -1,15 +1,54 @@
#pragma once
#include "mmuContext.h"
#include "process.h"
#include "stddef.h"
#include "stdint.h"
#include "types.h"
#include <stddef.h>
struct uAddrSpace;
struct uAddrVirtualReg;
struct uAddrSpace * uAddrSpaceCreate(struct process *proc);
#define UA_MAP_SHARED (1 << 0)
#define UA_MAP_PRIVATE (1 << 1)
#define UA_MAP_FIXED (1 << 2)
// TODO : move this struct to .c and add accessors
struct uAddrVirtualReg {
uaddr_t addr;
size_t size;
int right; // PAGING_MEM_*
uint32_t offset; // in the mappedRessource
uint flags;
struct mappedRessource *res;
struct uAddrVirtualReg *nextInAddrSpace, *prevInAddrSpace;
struct uAddrVirtualReg *nextInMappedRes, *prevInMappedRes;
};
struct mappedRessourceOps {
int (*open)(struct uAddrVirtualReg *vreg);
int (*close)(struct uAddrVirtualReg *vreg);
int (*unmap)(struct uAddrVirtualReg *vreg, uaddr_t addr, size_t size);
int (*nopage)(struct uAddrVirtualReg *vreg, uaddr_t addr,
int right); // Called by the pageflt handler when the page is missing
};
struct mappedRessource {
int allowedRight; // PAGING_MEM_*
struct mappedRessourceOps *ops;
struct uAddrVirtualReg *listVirtualReg;
void *customData;
int (*onResMapped)(struct uAddrVirtualReg *reg); // Callabck for when the ressourced get mapped
};
struct uAddrSpace *uAddrSpaceCreate(struct process *proc);
int uAddrSpaceDelete(struct uAddrSpace *addr);
struct mmu_context * uAddrSpaceGetMMUContext(struct uAddrSpace *addr);
struct mmu_context *uAddrSpaceGetMMUContext(struct uAddrSpace *addr);
int uAddrSpaceSetHeap(struct uAddrSpace *as, uaddr_t addr, size_t size);
int uAddrSpaceCheckNAlloc(struct uAddrSpace *as, vaddr_t addr);
int uAddrSpaceHeapCheckNAlloc(struct uAddrSpace *as, vaddr_t addr);
uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop);
int uAddrSpaceMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights,
uint32_t flags, struct mappedRessource *res, uint32_t offset);
int uAddrSpaceUnmap(struct uAddrSpace *as, uaddr_t uaddr, size_t size);
int uAddrSpaceSolvePageFault(struct uAddrSpace *as, vaddr_t faultAddr, int isWriteAccess);

View File

@ -184,18 +184,19 @@ class ListDumpCmd(gdb.Command):
"list_dump", gdb.COMMAND_USER
)
def _print_list(self, val):
def _print_list(self, val, next_name):
"""Walk through the linked list.
We will simply follow the 'next' pointers until we encounter the HEAD again
"""
idx = 0
head = val
thread_ptr = val
result = ""
while thread_ptr != 0 and (idx == 0 or thread_ptr != head):
result += gdb.execute('p *({}){}'.format(str(thread_ptr.type),thread_ptr), to_string=True)
thread_ptr = thread_ptr["next"]
result += gdb.execute('p *({}){}'.format(str(thread_ptr.type),
thread_ptr), to_string=True)
thread_ptr = thread_ptr[next_name]
idx += 1
result = ("Found a Linked List with %d items:" % idx) + "\n" + result
return result
@ -209,17 +210,21 @@ class ListDumpCmd(gdb.Command):
# We can pass args here and use Python CLI utilities like argparse
# to do argument parsing
print("Args Passed: %s" % args)
if args:
ptr_val = gdb.parse_and_eval(args)
else:
ptr_val = gdb.parse_and_eval("currentThread")
thread_name = "currentThread"
next_name = "next"
if(args):
args_arr = args.split()
thread_name = args_arr[0]
if(len(args_arr) >= 2):
next_name = args_arr[1]
ptr_val = gdb.parse_and_eval(thread_name)
try:
ptr_val["next"]
ptr_val[next_name]
except:
print("Expected pointer argument with a next field")
print("Expected pointer argument with a %s field" % next_name)
return
print(self._print_list(ptr_val))
print(self._print_list(ptr_val, next_name))
register_pretty_printer(None, CustomPrettyPrinterLocator(), replace=True)

10
debug.iso.gdb Normal file
View File

@ -0,0 +1,10 @@
add-symbol-file userspace/user
# Thx to add-gnu-debuglink gdb should know that symbols are in kernel.debug.
# And by default, it should be looking at executable.debug
# But we still have to give him the executable he is suppose to debug (See https://sourceware.org/gdb/current/onlinedocs/gdb.html/Separate-Debug-Files.html)
#add-symbol-file kernel.debug
file kernel
source custom_gdb_extension.py
#For ASM sources
directory arch/x86/:core
target remote | qemu-system-i386 -S -gdb stdio -m 16M -serial file:serialOut -hda fd.iso -hdb disk.img

View File

@ -2,8 +2,6 @@ label: dos
label-id: 0x9ec19bcc
device: disk.img
unit: sectors
sector-size: 512
disk.img1 : start= 2048, size= 10240, type=83
disk.img2 : start= 12288, size= 10240, type=b
disk.img3 : start= 22528, size= 43008, type=e
disk.img1 : start= 2048, size= 32768, type=6, bootable
disk.img2 : start= 34816, size= 30720, type=83

View File

@ -418,6 +418,10 @@ int ATADetectDevice(struct ata_device *dev)
struct ata_controller *ctl = dev->ctl;
outb(ctl->base + ATA_PIO_DRIVE,
ATA_PIO_DRIVE_IBM | (dev->isSlave ? ATA_PIO_DRIVE_SLAVE : ATA_PIO_DRIVE_MASTER));
outb(ctl->base + ATA_PIO_SEC_COUNT, 0);
outb(ctl->base + ATA_PIO_LBALO, 0);
outb(ctl->base + ATA_PIO_LBAMID, 0);
outb(ctl->base + ATA_PIO_LBAHI, 0);
unsigned st = inb(ctl->base + ATA_PIO_STATUS);
if (st & ATA_PIO_STATUS_DRIVE_BUSY)
goto no_disk;
@ -451,6 +455,10 @@ int ATAGetDeviceInfo(struct ata_device *dev)
outb(ctl->base + ATA_PIO_DRIVE,
ATA_PIO_DRIVE_IBM | (dev->isSlave ? ATA_PIO_DRIVE_SLAVE : ATA_PIO_DRIVE_MASTER));
outb(ctl->base + ATA_PIO_SEC_COUNT, 0);
outb(ctl->base + ATA_PIO_LBALO, 0);
outb(ctl->base + ATA_PIO_LBAMID, 0);
outb(ctl->base + ATA_PIO_LBAHI, 0);
outb(ctl->base + ATA_PIO_CMD, ATA_PIO_CMD_IDENTIFY);
/* Wait for command completion (wait while busy bit is set) */
@ -513,6 +521,19 @@ struct ata_partition *ATAGetPartition(int id)
return NULL;
}
struct ata_partition *ATAGetPartitionByType(uint type)
{
struct ata_partition *part;
int count;
list_foreach(partitions, part, count)
{
if (part->type == type)
return part;
}
return NULL;
}
struct ata_partition *ATAPartitionCreate(uint type, uint size, uint32_t lba,
struct ata_device *dev)
{
@ -609,41 +630,42 @@ int ATAReadPartitionSector(struct ata_partition *part, int offset, uint nbSector
int ATAReadSector(struct ata_device *dev, int lba, uint nb_sector, void *buf)
{
struct ata_controller *ctl = dev->ctl;
struct ata_controller *ctl = dev->ctl;
mutexLock(&ctl->mutex);
mutexLock(&ctl->mutex);
if (ctl->last_device_used != dev->id) {
outb(ctl->base + ATA_PIO_DRIVE, ATA_PIO_DRIVE_IBM | dev->isSlave << 4);
while (inb(ctl->base + ATA_PIO_STATUS) & ATA_PIO_STATUS_DRIVE_BUSY) {
}
ctl->last_device_used = dev->id;
}
outb(ctl->base + ATA_PIO_DRIVE, lba >> 24 | ATA_PIO_DRIVE_IBM | ATA_PIO_DRIVE_LBA);
outb(ctl->base + ATA_PIO_SEC_COUNT, nb_sector);
outb(ctl->base + ATA_PIO_LBALO, lba & 0xff);
outb(ctl->base + ATA_PIO_LBAMID, (lba >> 8) & 0xff);
outb(ctl->base + ATA_PIO_LBAHI, (lba >> 16) & 0xff);
outb(ctl->base + ATA_PIO_CMD, ATA_PIO_CMD_READ);
if (ctl->last_device_used != dev->id) {
outb(ctl->base + ATA_PIO_DRIVE,
ATA_PIO_DRIVE_IBM | (dev->isSlave ? ATA_PIO_DRIVE_SLAVE : ATA_PIO_DRIVE_MASTER));
while (inb(ctl->base + ATA_PIO_STATUS) & ATA_PIO_STATUS_DRIVE_BUSY) {
}
ctl->last_device_used = dev->id;
}
outb(ctl->base + ATA_PIO_DRIVE, lba >> 24 | ATA_PIO_DRIVE_IBM | ATA_PIO_DRIVE_LBA | (dev->isSlave ? ATA_PIO_DRIVE_SLAVE : ATA_PIO_DRIVE_MASTER));
outb(ctl->base + ATA_PIO_SEC_COUNT, nb_sector);
outb(ctl->base + ATA_PIO_LBALO, lba & 0xff);
outb(ctl->base + ATA_PIO_LBAMID, (lba >> 8) & 0xff);
outb(ctl->base + ATA_PIO_LBAHI, (lba >> 16) & 0xff);
outb(ctl->base + ATA_PIO_CMD, ATA_PIO_CMD_READ);
uint16_t *ptr = (uint16_t *)buf;
for (uint sector = 0; sector < nb_sector; sector++) {
while (inb(ctl->base + ATA_PIO_STATUS) & ATA_PIO_STATUS_DRIVE_BUSY) {
}
if (inb(ctl->base + ATA_PIO_STATUS) & ATA_PIO_STATUS_REG_ERR) {
mutexUnlock(&ctl->mutex);
printf("ATA read error at sector %d\n", sector);
return -1;
}
for (uint i = 0; i < (DISK_SECTOR_SIZE / sizeof(uint16_t)); i++) {
*ptr = inw(ctl->base + ATA_PIO_DATA);
ptr++;
}
}
uint16_t *ptr = (uint16_t *)buf;
for (uint sector = 0; sector < nb_sector; sector++) {
while (inb(ctl->base + ATA_PIO_STATUS) & ATA_PIO_STATUS_DRIVE_BUSY) {
}
if (inb(ctl->base + ATA_PIO_STATUS) & ATA_PIO_STATUS_REG_ERR) {
mutexUnlock(&ctl->mutex);
printf("ATA read error at sector %d\n", sector);
return -1;
}
for (uint i = 0; i < (DISK_SECTOR_SIZE / sizeof(uint16_t)); i++) {
*ptr = inw(ctl->base + ATA_PIO_DATA);
ptr++;
}
}
mutexUnlock(&ctl->mutex);
mutexUnlock(&ctl->mutex);
return 0;
return 0;
}
int ATAWriteSector(struct ata_device *dev, int lba, uint nb_sector, void *buf)
@ -659,7 +681,7 @@ int ATAWriteSector(struct ata_device *dev, int lba, uint nb_sector, void *buf)
}
ctl->last_device_used = dev->id;
}
outb(ctl->base + ATA_PIO_DRIVE, lba >> 24 | ATA_PIO_DRIVE_IBM | ATA_PIO_DRIVE_LBA);
outb(ctl->base + ATA_PIO_DRIVE, lba >> 24 | ATA_PIO_DRIVE_IBM | ATA_PIO_DRIVE_LBA | (dev->isSlave ? ATA_PIO_DRIVE_SLAVE : ATA_PIO_DRIVE_MASTER));
outb(ctl->base + ATA_PIO_SEC_COUNT, nb_sector);
outb(ctl->base + ATA_PIO_LBALO, lba & 0xff);
outb(ctl->base + ATA_PIO_LBAMID, (lba >> 8) & 0xff);

View File

@ -104,5 +104,6 @@ int ATAReadPartitionSector(struct ata_partition *part, int offset, uint nbSector
int ATAReadSector(struct ata_device *dev, int lba, uint nbSector, void *buf);
int ATAWriteSector(struct ata_device *dev, int lba, uint nbSector, void *buf);
struct ata_device *ATAGetDevice(int ctlId, int devId);
struct ata_partition *ATAGetPartitionByType(uint type);
int ATAReadPartition(struct ata_device *dev);
struct ata_partition *ATAGetPartition(int id);

View File

@ -460,7 +460,7 @@ void keyboard_do_irq()
}
if (key){
printf(key);
putc(*key);
ringbufferEnqueue(buf, *key);
}
}

View File

@ -178,7 +178,7 @@ static void cursorMove(int x, int y)
}
void VGAMap(void){
for (paddr_t i = VGA_ADDR; i < VGA_ADDR + VGA_WIDTH * VGA_HEIGHT * sizeof(short) ; i += PAGE_SIZE) {
for (paddr_t i = (paddr_t)vga; i < (paddr_t)vga + fbWidth * fbHeight * sizeof(short) ; i += PAGE_SIZE) {
pageMap(i, i, PAGING_MEM_WRITE);
}
}

View File

@ -1,5 +1,5 @@
#pragma once
#include "stdarg.h"
#include "stdint.h"
#include "types.h"
// https://wiki.osdev.org/Text_UI

124
drivers/zero.c Normal file
View File

@ -0,0 +1,124 @@
#include "zero.h"
#include "alloc.h"
#include "errno.h"
#include "kernel.h"
#include "klibc.h"
#include "mem.h"
#include "list.h"
#include "paging.h"
#include "types.h"
struct zeroMappedPage {
uaddr_t mappedAddr;
paddr_t phyAddr;
struct zeroMappedPage *prev, *next;
};
struct zeroMappedEntry {
int refCnt;
struct zeroMappedPage *listMapped;
};
static int insertMappedPage(struct zeroMappedEntry *entry, uaddr_t vAddr, paddr_t pAddr){
struct zeroMappedPage *info = (struct zeroMappedPage *)zalloc(sizeof(struct zeroMappedPage));
if(!info)
return -ENOMEM;
info->mappedAddr = vAddr;
info->phyAddr = pAddr;
list_add_tail(entry->listMapped, info);
return 0;
}
static int zeroOpen(struct uAddrVirtualReg *vreg)
{
struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData;
ent->refCnt++;
return 0;
}
static int zeroClose(struct uAddrVirtualReg *vreg)
{
struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData;
ent->refCnt--;
if (ent->refCnt == 0) {
struct zeroMappedPage *pageInfo;
list_collapse(ent->listMapped, pageInfo){
pageUnmap(pageInfo->mappedAddr);
free(pageInfo);
}
free(vreg->res->customData);
free(vreg->res);
}
return 0;
}
static int zeroNoPage(struct uAddrVirtualReg *vreg, uaddr_t addr, int right)
{
int ret = 0;
paddr_t ppage = allocPhyPage(1);
uaddr_t mappedAddr = ALIGN_DOWN(addr, PAGE_SIZE);
ret = pageMap(mappedAddr, ppage, right | PAGING_MEM_USER);
struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData;
unrefPhyPage(ppage);
if (ret) {
return ret;
}
ret = insertMappedPage(ent, mappedAddr, ppage);
if (ret) {
pageUnmap(mappedAddr);
return ret;
}
memset((void *)mappedAddr, 0, PAGE_SIZE);
return ret;
}
static struct mappedRessourceOps zeroOps = {
.open = zeroOpen,
.close = zeroClose,
.unmap = NULL,
.nopage = zeroNoPage,
};
int zeroOnMapped(struct uAddrVirtualReg *vreg)
{
(void)vreg;
return 0;
}
int zeroMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights,
uint32_t flags)
{
int ret = 0;
struct mappedRessource *res =
(struct mappedRessource *)zalloc(sizeof(struct mappedRessource));
struct zeroMappedEntry *cust =
(struct zeroMappedEntry *)zalloc(sizeof(struct zeroMappedEntry));
list_init(cust->listMapped);
res->allowedRight = PAGING_MEM_READ | PAGING_MEM_WRITE | PAGING_MEM_EXEC | PAGING_MEM_USER;
res->ops = &zeroOps;
res->customData = cust;
res->onResMapped = zeroOnMapped;
ret = uAddrSpaceMmap(as, uaddr, size, rights, flags, res, 0);
if (ret) {
free(res);
free(cust);
}
return ret;
}

11
drivers/zero.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include "types.h"
#include "uaddrspace.h"
#include <stddef.h>
#include <stdint.h>
int zeroSetup();
int zeroMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights, uint32_t flags);

View File

@ -39,6 +39,12 @@ SECTIONS
*(.bss)
}
.multiboot_data : {
__multiboot_data_size = 48k;
__multiboot_data_start = .;
. = . + __multiboot_data_size;
__multiboot_data_end = .;
}
__ld_kernel_end = .;
/* The compiler may produce other sections, by default it will put them in

View File

@ -306,9 +306,8 @@ void sleepThread(void *arg)
}
unsigned long ellapsedTime = jiffies_to_msecs(jiffies - initialJiffies);
assertmsg(ellapsedTime >= 500 && ellapsedTime < 510, "ellapsedTime %lu\n", ellapsedTime);
threadMsleep(0);
printf("I should never be showed\n");
assert(1);
threadMsleep(ULONG_MAX);
assert(0);
}
struct mutex mutexTest;
@ -399,7 +398,7 @@ static void userProgramm()
"int %5\n"
"movl %%eax, %0"
: "=g"(ret)
: "g"(SYSCALL_ID_YOLO), "g"(0), "g"(0), "g"(0), "i"(SYSCALL_INTR_NB)
: "g"(SYSCALL_ID_HELO), "g"(0), "g"(0), "g"(0), "i"(SYSCALL_INTR_NB)
: "eax", "ebx", "ecx", "edx");
asm volatile("movl %1,%%eax \n"
"movl %2,%%ebx \n"

View File

@ -5,8 +5,7 @@
do { \
if (!(p)) { \
printf("BUG at %s:%d assert(%s)\n", __FILE__, __LINE__, #p); \
while (1) { \
} \
_exit(-1); \
} \
} while (0)
@ -15,7 +14,6 @@
if (!(p)) { \
printf("BUG at %s:%d assert(%s)\n", __FILE__, __LINE__, #p); \
printf(__VA_ARGS__); \
while (1) { \
} \
_exit(-1); \
} \
} while (0)

37
userspace/errno.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
extern int errno;
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */

View File

@ -1,14 +1,21 @@
#pragma once
#ifdef __KERNEL__
#include "cpu_context.h"
#include "cpu_context.h"
#endif
#define SYSCALL_ID_EXIT 1
#define SYSCALL_ID_YOLO 2
#define SYSCALL_ID_HELO 2
#define SYSCALL_ID_PUTC 3
#define SYSCALL_ID_READ 4
#define SYSCALL_ID_TEST 5
#define SYSCALL_ID_BRK 6
#define SYSCALL_ID_BRK 6
#define SYSCALL_ID_MMAP 7
#define SYSCALL_ID_MUNMAP 8
#define SYSCALL_ID_NEW_THREAD 9
#define SYSCALL_ID_USLEEP 10
#define SYSCALL_ID_GETPID 11
#define SYSCALL_ID_GETTID 12
#define SYSCALL_ID_THREAD_JOIN 13
#ifdef __KERNEL__
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);

View File

@ -1,8 +1,14 @@
#include "libc.h"
#include "errno.h"
#include "list.h"
#include "minmax.h"
#include "swintr.h"
#include "sys/mman.h"
#include "syscall.h"
#include "thread.h"
#include "unistd.h"
int errno = 0;
int memcmp(const void *aptr, const void *bptr, size_t size)
{
const unsigned char *a = (const unsigned char *)aptr;
@ -42,12 +48,13 @@ void *memcpy(void *dst0, const void *src0, size_t len0)
#else
char *dst = dst0;
const char *src = src0;
long *aligned_dst;
const long *aligned_src;
/* If the size is small, or either SRC or DST is unaligned,
then punt into the byte copy loop. This should be rare. */
if (!TOO_SMALL(len0) && !UNALIGNED(src, dst)) {
long *aligned_dst;
const long *aligned_src;
aligned_dst = (long *)dst;
aligned_src = (long *)src;
@ -78,6 +85,16 @@ void *memcpy(void *dst0, const void *src0, size_t len0)
#endif
}
void *memmove(void *dst, const void *src, size_t n)
{
char *dstChar = dst;
const char *srcChar = src;
for (size_t i = 0; i < n; i++) {
*(dstChar++) = *(srcChar++);
}
return dst;
}
void *memset(void *src, int c, size_t n)
{
for (char *ptr = (char *)src; n > 0; n--, ptr++) {
@ -248,8 +265,57 @@ int puts(const char *str)
return ret; \
}
#define PRINT_UINT(name, type) \
int print##name(type integer, char *str, size_t size) \
{ \
char num[sizeof(integer) * 3]; \
int i = 0; \
int c = 0; \
int ret = 0; \
\
do { \
int digit = integer % 10; \
num[i++] = (digit > 0) ? digit : -digit; \
integer = integer / 10; \
} while (integer != 0); \
\
for (i = i - 1; i >= 0; i--) { \
if (str) { \
if (size) { \
str[c++] = num[i] + '0'; \
size--; \
ret++; \
} else { \
return ret; \
} \
} else { \
ret++; \
} \
} \
return ret; \
}
PRINT_INT(Int, int);
PRINT_INT(Int64, long long int);
PRINT_INT(Lint, long int);
PRINT_INT(Llint, long long int);
PRINT_UINT(Uint, unsigned int);
PRINT_UINT(Luint, long unsigned int);
PRINT_UINT(Lluint, long long unsigned int);
#define PRINT_PART(func, type, str, size, c, ret) \
{ \
int s; \
type d = va_arg(ap, type); \
if (str) \
s = func(d, &str[c], size); \
else \
s = func(d, NULL, size); \
\
size -= s; \
c += s; \
ret += s; \
break; \
}
int vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
@ -257,24 +323,13 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap)
int i = 0;
int c = 0;
while (format[i] != '\0' && (size || !str)) {
while (format[i] != '\0' && (size|| !str)) {
switch (format[i]) {
case '%':
switch (format[i + 1]) {
case 'i':
case 'd': {
int s;
int d = va_arg(ap, int);
if (str)
s = printInt(d, &str[c], size);
else
s = printInt(d, NULL, size);
size -= s;
c += s;
ret += s;
break;
}
case 'd': PRINT_PART(printInt, int, str, size, c, ret)
case 'u': PRINT_PART(printUint, uint, str, size, c, ret)
case 'p':
case 'x': {
char val[sizeof(int) * 2];
@ -335,24 +390,15 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap)
switch (format[i + 2]) {
case 'l':
switch (format[i + 3]) {
case 'd': {
int s;
long long int d = va_arg(ap, long long int);
if (str)
s = printInt64(d, &str[c], size);
else
s = printInt64(d, NULL, size);
size -= s;
c += s;
ret += s;
break;
}
case 'i':
case 'd': PRINT_PART(printLlint, long long int, str, size, c, ret)
case 'u': PRINT_PART(printLluint, long long unsigned int, str, size, c, ret)
case 'p':
case 'x': {
char val[sizeof(long long int) * 2];
unsigned int valIdx = 0;
long long int d = va_arg(ap, long long int);
unsigned long long int d =
va_arg(ap, unsigned long long int);
itoa(d, val, 16);
if (str) {
while (val[valIdx]) {
@ -373,17 +419,28 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap)
i++;
break;
case 'i':
case 'd': {
int s;
long int d = va_arg(ap, long int);
if (str)
s = printInt64(d, &str[c], size);
else
s = printInt64(d, NULL, size);
size -= s;
c += s;
ret += s;
case 'd': PRINT_PART(printLint, long int, str, size, c, ret)
case 'u':
PRINT_PART(printLuint, long unsigned int, str, size, c, ret)
case 'p':
case 'x': {
char val[sizeof(int) * 2];
unsigned int valIdx = 0;
unsigned long int d = va_arg(ap, unsigned long int);
itoa(d, val, 16);
if (str) {
while (val[valIdx]) {
if (size) {
str[c++] = val[valIdx++];
size--;
ret++;
} else {
return ret;
}
}
} else {
ret += strlen(val);
}
break;
}
}
@ -443,25 +500,28 @@ int vasprintf(char **strp, const char *fmt, va_list ap)
{
int n = 0;
size_t size = 0;
char *p = malloc(256);
char *p = malloc(256);
/* Determine required size */
n = vsnprintf(p, size, fmt, ap);
if (n < 0)
if (n < 0){
free(p);
return -1;
}
/* One extra byte for '\0' */
size = min(256U,(size_t)n + 1);
size = min(256U, (size_t)n + 1);
n = vsnprintf(p, size, fmt, ap);
if (n < 0) {
free(p);
return -1;
}
*strp = p;
*strp = p;
return size;
}
@ -521,9 +581,9 @@ int putc(const int c){
return syscall1(SYSCALL_ID_PUTC, c);
}
void yolo()
void helo()
{
syscall0(SYSCALL_ID_YOLO);
syscall0(SYSCALL_ID_HELO);
}
int testSycall5(uint arg1, uint arg2, uint arg3, uint arg4, uint arg5)
@ -566,28 +626,201 @@ int readline(char *buf, int size)
return i == (size-1);
}
void *brk(void *addr)
int brk(void *addr)
{
return (void *)syscall1(SYSCALL_ID_BRK, (unsigned int)addr);
uintptr_t new = syscall1(SYSCALL_ID_BRK, (unsigned int)addr);
//errno = ENOMEM
return (new >= (uintptr_t)addr)?0:-1;
}
void *sbrk(intptr_t increment)
{
void *current = (void *)syscall1(SYSCALL_ID_BRK, 0);
if (increment == 0) {
return current;
}
if ((uintptr_t)syscall1(SYSCALL_ID_BRK, (uintptr_t)current + increment) < ((uintptr_t)current + increment)) {
// errno = ENOMEM
return (void *)-1;
}
return current;
}
// Malloc internal
struct heapBlock {
size_t size;
struct heapBlock *next, *prev;
int free;
};
static struct heapBlock *heapBlkList = NULL;
static struct heapBlock *findFreeBlock(size_t size)
{
struct heapBlock *cur = NULL;
struct heapBlock *found = NULL;
int idx;
list_foreach(heapBlkList, cur, idx)
{
if (cur->size >= size && cur->free) {
found = cur;
break;
}
}
return found;
}
static struct heapBlock *allocNewBlock(size_t size)
{
struct heapBlock *blk = sbrk(size + sizeof(struct heapBlock));
struct heapBlock *head = sbrk(0);
size_t blkSize = (intptr_t)head - (intptr_t)blk - sizeof(struct heapBlock);
if (blk == (void *)-1) {
return NULL;
}
blk->size = blkSize;
blk->free = 1;
list_add_tail(heapBlkList, blk);
return blk;
}
static struct heapBlock *splitBlock(struct heapBlock *blk, size_t neededSize)
{
if (blk->size < neededSize + sizeof(struct heapBlock) + 1) {
return NULL;
}
struct heapBlock *newBlk = (struct heapBlock *)((uintptr_t)(blk + 1) + neededSize);
newBlk->free = 1;
newBlk->size = blk->size - sizeof(struct heapBlock) - neededSize;
blk->size = neededSize;
return newBlk;
}
void *malloc(size_t size)
{
void *heapTop = 0;
static void *free = 0;
if (size == 0)
return NULL;
if (heapTop == 0) {
heapTop = brk(0);
free = heapTop;
} else {
heapTop = brk(0);
struct heapBlock *blk = findFreeBlock(size);
if (!blk)
blk = allocNewBlock(size);
if (!blk)
return NULL;
struct heapBlock *remainBlock = splitBlock(blk, size);
if (remainBlock) {
list_add_head(heapBlkList, remainBlock);
}
blk->free = 0;
if (free + size > heapTop) {
if (brk(heapTop + size))
return NULL;
}
free += size;
return (free - size);
return blk + 1; // return the area after the blk description
}
static struct heapBlock *getHeapBlock(void *ptr)
{
return (struct heapBlock *)ptr - 1;
}
void free(void *ptr)
{
if (!ptr)
return;
struct heapBlock *blk = getHeapBlock(ptr);
assert(blk->free == 0);
blk->free = 1;
}
void *calloc(size_t nmemb, size_t size)
{
size_t allocSize = nmemb * size;
void *ptr = malloc(allocSize);
if (ptr != NULL)
memset(ptr, 0, allocSize);
return ptr;
}
void *realloc(void *ptr, size_t size)
{
if (!ptr) {
return malloc(size);
}
struct heapBlock *blk = getHeapBlock(ptr);
if (blk->size >= size) {
return ptr;
}
void *new_ptr;
new_ptr = malloc(size);
if (!new_ptr) {
return NULL;
}
memmove(new_ptr, ptr, blk->size);
free(ptr);
return new_ptr;
}
void *mmap(void *addr, size_t len, int prot, int flags, char *path) {
int ret = syscall5(SYSCALL_ID_MMAP, (unsigned int)&addr, len, prot, flags, (unsigned int)path);
if(!ret)
return addr;
errno = ret;
return MAP_FAILED;
}
int munmap(void *addr, size_t len)
{
if (len == 0)
return -EINVAL;
return syscall2(SYSCALL_ID_MUNMAP, (unsigned int)addr, len);
}
/* As when a new thread is run, the params are passed by register (See cpu_ustate_init), use
* this function to simplify new thread usage*/
static void thread_runner()
{
register unsigned long int reg_arg1 asm("%eax");
register unsigned long int reg_arg2 asm("%ebx");
start_routine *func = (start_routine *)reg_arg1;
void *arg = (void *)reg_arg2;
func(arg);
_exit(0);
}
int thread_create(pthread_t *thread, start_routine *func, void *arg, size_t stackSize) {
return syscall5(SYSCALL_ID_NEW_THREAD, (unsigned int)thread, (unsigned int)thread_runner, (unsigned int)func,
(unsigned int)arg, stackSize);
}
int thread_join(pthread_t thread, void **retval){
(void)retval;
return syscall1(SYSCALL_ID_THREAD_JOIN, (unsigned int)thread);
}
int usleep(useconds_t usec) {
return syscall1(SYSCALL_ID_USLEEP, (unsigned int)usec);
}
pid_t gettid(void) {
return syscall0(SYSCALL_ID_GETTID);
}
pid_t getpid(void) {
return syscall0(SYSCALL_ID_GETPID);
}

View File

@ -1,7 +1,10 @@
#pragma once
#include "assert.h"
#include "stdarg.h"
#include "stdint.h"
#include "stddef.h"
#include "minmax.h"
#include "unistd.h"
#define islower(c) (('a' <= (c)) && ((c) <= 'z'))
#define isupper(c) (('A' <= (c)) && ((c) <= 'Z'))
@ -12,8 +15,15 @@
#define isprint(c) ((' ' <= (c)) && ((c) <= '~'))
#define EOF (-1)
/** compares the first @param n bytes (each interpreted as
* unsigned char) of the memory areas @param s1 and @param s2.
*/
__attribute__ ((access (read_only, 1, 3), access (read_only, 2, 3))) int memcmp(const void *s1, const void *s2, size_t n);
/**
* copies n bytes from memory area src to memory area dest. The memory areas may overlap
*/
__attribute__ ((access (write_only, 1, 3), access (read_only, 2, 3))) void *memmove(void *dest, const void *src, size_t n);
__attribute__ ((access (write_only, 1, 3), access (read_only, 2, 3))) void *memcpy(void *dest, const void *src, size_t n);
__attribute__ ((access (write_only, 1, 3))) void *memset(void *s, int c, size_t n);
char *itoa(long long int value, char *str, int base);
@ -27,8 +37,9 @@ int putc(const int c);
int vsnprintf(char *str, size_t size, const char *format, va_list ap) __attribute__ ((__format__ (printf, 3, 0)));
int vprintf(const char *format, va_list ap) __attribute__ ((__format__ (printf, 1, 0)));
int printf(const char *format, ...) __attribute__ ((__format__ (printf, 1, 2)));
void *mmap(void *addr, size_t len, int prot, int flags, char *path);
int munmap(void *addr, size_t len);
// Could be used after malloc is available
int asprintf(char **strp, const char *fmt, ...) __attribute__ ((__format__ (printf, 2, 3)));
int vasprintf(char **strp, const char *fmt, va_list ap) __attribute__ ((__format__ (printf, 2, 0)));
@ -42,10 +53,17 @@ int syscall1(int id, unsigned int arg1);
int syscall0(int id);
void _exit(int status);
void yolo();
void helo();
int testSycall5(uint arg1, uint arg2, uint arg3, uint arg4, uint arg5);
char readc();
char getchar();
int readline(char *buf, int size);
void *brk(void *addr);
int brk(void *addr);
void *sbrk(intptr_t increment);
void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
pid_t gettid(void);
pid_t getpid(void);

189
userspace/list.h Normal file
View File

@ -0,0 +1,189 @@
/* Copyright (C) 2001 David Decotigny
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
*/
#ifndef _SOS_LIST_H_
#define _SOS_LIST_H_
/**
* @file list.h
*
* Circular doubly-linked lists implementation entirely based on C
* macros
*/
/* *_named are used when next and prev links are not exactly next
and prev. For instance when we have next_in_team, prev_in_team,
prev_global and next_global */
#define list_init_named(list, prev, next) ((list) = NULL)
#define list_singleton_named(list, item, prev, next) \
({ \
(item)->next = (item)->prev = (item); \
(list) = (item); \
})
#define list_is_empty_named(list, prev, next) ((list) == NULL)
#define list_is_singleton_named(list, prev, next) \
(((list) != NULL) && ((list)->prev == (list)->next) && ((list) == (list)->next))
#define list_get_head_named(list, prev, next) (list)
#define list_get_tail_named(list, prev, next) ((list) ? ((list)->prev) : NULL)
/* Internal macro : insert before the head == insert at tail */
#define __list_insert_atleft_named(before_this, item, prev, next) \
({ \
(before_this)->prev->next = (item); \
(item)->prev = (before_this)->prev; \
(before_this)->prev = (item); \
(item)->next = (before_this); \
})
/* @note Before_this and item are expected to be valid ! */
#define list_insert_before_named(list, before_this, item, prev, next) \
({ \
__list_insert_atleft_named(before_this, item, prev, next); \
if ((list) == (before_this)) \
(list) = (item); \
})
/** @note After_this and item are expected to be valid ! */
#define list_insert_after_named(list, after_this, item, prev, next) \
({ \
(after_this)->next->prev = (item); \
(item)->next = (after_this)->next; \
(after_this)->next = (item); \
(item)->prev = (after_this); \
})
#define list_add_head_named(list, item, prev, next) \
({ \
if (list) \
__list_insert_atleft_named(list, item, prev, next); \
else \
list_singleton_named(list, item, prev, next); \
(list) = (item); \
})
#define list_add_tail_named(list, item, prev, next) \
({ \
if (list) \
__list_insert_atleft_named(list, item, prev, next); \
else \
list_singleton_named(list, item, prev, next); \
})
/** @note NO check whether item really is in list ! */
#define list_delete_named(list, item, prev, next) \
({ \
if (((item)->next == (item)) && ((item)->prev == (item))) \
(item)->next = (item)->prev = (list) = NULL; \
else { \
(item)->prev->next = (item)->next; \
(item)->next->prev = (item)->prev; \
if ((item) == (list)) \
(list) = (item)->next; \
(item)->prev = (item)->next = NULL; \
} \
})
#define list_pop_head_named(list, prev, next) \
({ \
typeof(list) __ret_elt = (list); \
list_delete_named(list, __ret_elt, prev, next); \
__ret_elt; \
})
/** Loop statement that iterates through all of its elements, from
head to tail */
#define list_foreach_forward_named(list, iterator, nb_elements, prev, next) \
for (nb_elements = 0, (iterator) = (list); \
(iterator) && (!nb_elements || ((iterator) != (list))); \
nb_elements++, (iterator) = (iterator)->next)
/** Loop statement that iterates through all of its elements, from
tail back to head */
#define list_foreach_backward_named(list, iterator, nb_elements, prev, next) \
for (nb_elements = 0, (iterator) = list_get_tail_named(list, prev, next); \
(iterator) && \
(!nb_elements || ((iterator) != list_get_tail_named(list, prev, next))); \
nb_elements++, (iterator) = (iterator)->prev)
#define list_foreach_named list_foreach_forward_named
/** True when we exitted early from the foreach loop (ie break) */
#define list_foreach_early_break(list, iterator, nb_elements) \
((list) && (((list) != (iterator)) || (((list) == (iterator)) && (nb_elements == 0))))
/** Loop statement that also removes the item at each iteration. The
body of the loop is allowed to delete the iterator element from
memory. */
#define list_collapse_named(list, iterator, prev, next) \
for (; ({ \
((iterator) = (list)); \
if (list) \
list_delete_named(list, iterator, prev, next); \
(iterator); \
});)
/*
* the same macros : assume that the prev and next fields are really
* named "prev" and "next"
*/
#define list_init(list) list_init_named(list, prev, next)
#define list_singleton(list, item) list_singleton_named(list, item, prev, next)
#define list_is_empty(list) list_is_empty_named(list, prev, next)
#define list_is_singleton(list) list_is_singleton_named(list, prev, next)
#define list_get_head(list) list_get_head_named(list, prev, next)
#define list_get_tail(list) list_get_tail_named(list, prev, next)
/* @note Before_this and item are expected to be valid ! */
#define list_insert_after(list, after_this, item) \
list_insert_after_named(list, after_this, item, prev, next)
/* @note After_this and item are expected to be valid ! */
#define list_insert_before(list, before_this, item) \
list_insert_before_named(list, before_this, item, prev, next)
#define list_add_head(list, item) list_add_head_named(list, item, prev, next)
#define list_add_tail(list, item) list_add_tail_named(list, item, prev, next)
/* @note NO check whether item really is in list ! */
#define list_delete(list, item) list_delete_named(list, item, prev, next)
#define list_pop_head(list) list_pop_head_named(list, prev, next)
#define list_foreach_forward(list, iterator, nb_elements) \
list_foreach_forward_named(list, iterator, nb_elements, prev, next)
#define list_foreach_backward(list, iterator, nb_elements) \
list_foreach_backward_named(list, iterator, nb_elements, prev, next)
#define list_foreach list_foreach_forward
#define list_collapse(list, iterator) list_collapse_named(list, iterator, prev, next)
#endif /* _SOS_LIST_H_ */

View File

@ -1,15 +1,23 @@
#include "errno.h"
#include "libc.h"
#include "stdarg.h"
#include "stddef.h"
#include "sys/mman.h"
#include "thread.h"
#include "tiny.h"
#include "unistd.h"
int func_help()
{
printf("\nAvailable Commands:\n");
printf(" suicide\n");
printf(" help\n");
printf(" syscall5\n");
printf(" alloc\n");
printf(" tiny: a tiny C interpreter\n");
printf(" help: this help\n");
printf(" suicide: userspace self kill\n");
printf(" syscall5: a syscall with parameters over the stack \n");
printf(" alloc: test allocation\n");
printf(" tiny: a tiny C-like interpreter\n");
printf(" mmap: test mmap \n");
printf(" munmap: test munmap \n");
printf(" thread: run a user thread\n");
return 0;
}
@ -21,16 +29,15 @@ int func_suicide()
return 0;
}
void *initialHeap = 0;
char *initialHeap = 0;
int func_alloc()
{
if (initialHeap == 0) {
initialHeap = brk(0);
initialHeap = sbrk(0);
}
printf("Testing allocation\n");
int allocSize = 4096 * 2;
void *currentHeap = brk(0);
int allocSize = 4096 * 2;
char *currentHeap = sbrk(0);
if (currentHeap - initialHeap < allocSize) {
brk(initialHeap + allocSize);
}
@ -38,16 +45,104 @@ int func_alloc()
for (unsigned int i = 0; i < allocSize / sizeof(int); i++) {
allocatedData[i] = i;
}
printf("Success\n");
printf("Success\nTesting malloc\n");
uintptr_t heap = (uintptr_t)sbrk(0);
for (int i = 0; i < 12; i++) {
void *ptr = malloc(1 << i);
printf("malloc size %d: 0x%p\n", (1 << i), ptr);
if (ptr == NULL) {
printf("Malloc failed\n");
}
memset(ptr, 0, 1 << i);
free(ptr);
}
uintptr_t newHeap = (uintptr_t)sbrk(0);
printf("Malloc used %dB\n", newHeap - heap);
return 0;
}
int main(int argc, char *argv[])
struct mmapedArea {
void *addr;
size_t size;
struct mmapedArea *next;
};
static struct mmapedArea *listMmap = NULL;
int func_mmap()
{
struct mmapedArea *area = (struct mmapedArea *)malloc(sizeof(struct mmapedArea));
if (area == NULL) {
printf("Fail to allocate area\n");
return -1;
}
char *path = "/dev/zero";
void *mapAddr = mmap((void *)0, 4096, PROT_READ | PROT_WRITE, 0, path);
if (mapAddr == MAP_FAILED) {
printf("mmap failed errno %d\n", errno);
return -1;
}
printf("Zero mmaped at %p\n", mapAddr);
int data = *(int *)mapAddr;
*(int *)mapAddr = data;
area->addr = mapAddr;
area->size = 4096;
area->next = listMmap;
listMmap = area;
return 0;
}
int func_munmap()
{
if (!listMmap) {
printf("Nothing to unmap... mmap first! \n");
return -1;
}
struct mmapedArea *area = listMmap;
int ret = munmap(area->addr, area->size);
if (ret) {
printf("Fail to unmap area at 0x%p (size %d) error %d\n", area->addr, area->size, ret);
return ret;
}
printf("unmap done\n");
listMmap = listMmap->next;
free(area);
return ret;
}
static void *print_hello(void *arg) {
(void)arg;
printf("Hello World from thread %lu\n", gettid());
usleep(100);
return NULL;
}
int func_thread() {
pthread_t id;
void *retval;
thread_create(&id, print_hello, NULL, 4096);
thread_join(id, &retval);
return 0;
}
int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
char buf[64];
assert(getpid() == gettid());
printf("Shell starting... type \"help\" for help\n");
while (1) {
printf(">");
@ -70,7 +165,22 @@ int main(int argc, char *argv[])
continue;
}
if (strcmp(buf, "tiny") == 0) {
func_tiny();
pthread_t id;
void *retval;
thread_create(&id, func_tiny, NULL, 4096);
thread_join(id, &retval);
continue;
}
if (strcmp(buf, "mmap") == 0) {
func_mmap();
continue;
}
if (strcmp(buf, "munmap") == 0) {
func_munmap();
continue;
}
if (strcmp(buf, "thread") == 0) {
func_thread();
continue;
}
}

View File

@ -1,5 +1,5 @@
#pragma once
#include "stdarg.h"
#include "stdint.h"
#include "types.h"
uint32_t log2(uint32_t x);

View File

@ -1,53 +1,6 @@
#pragma once
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#ifdef __GNUC__
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
#else
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
/* sysv */
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef __s8 int8_t;
typedef __s16 int16_t;
typedef __s32 int32_t;
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
typedef enum { FALSE = 0, TRUE } bool_t;
#define NULL ((void *)0)
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
#endif
//__builtin_va_list could be used instead
typedef char *va_list;
#define va_start(v, l) ((v) = (va_list) & (l) + sizeof(l))
#define va_end(v) ((v) = NULL)

29
userspace/stddef.h Normal file
View File

@ -0,0 +1,29 @@
#pragma once
typedef enum { FALSE = 0, TRUE } bool_t;
#define NULL ((void *)0)
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
typedef long int intptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
typedef int intptr_t;
#endif
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
typedef long int intptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
typedef int intptr_t;
#endif
typedef int wchar_t;

64
userspace/stdint.h Normal file
View File

@ -0,0 +1,64 @@
#pragma once
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#ifdef __GNUC__
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
#else
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
/* sysv */
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef __s8 int8_t;
typedef __s16 int16_t;
typedef __s32 int32_t;
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
#define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX >> 1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define INT_MAX ((int)(~0U >> 1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL >> 1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)
#define LLONG_MAX ((long long)(~0ULL >> 1))
#define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL)
#define SIZE_MAX (~(size_t)0)
#define PHYS_ADDR_MAX (~(phys_addr_t)0)
#define U8_MAX ((u8)~0U)
#define S8_MAX ((s8)(U8_MAX >> 1))
#define S8_MIN ((s8)(-S8_MAX - 1))
#define U16_MAX ((u16)~0U)
#define S16_MAX ((s16)(U16_MAX >> 1))
#define S16_MIN ((s16)(-S16_MAX - 1))
#define U32_MAX ((u32)~0U)
#define S32_MAX ((s32)(U32_MAX >> 1))
#define S32_MIN ((s32)(-S32_MAX - 1))
#define U64_MAX ((u64)~0ULL)
#define S64_MAX ((s64)(U64_MAX >> 1))
#define S64_MIN ((s64)(-S64_MAX - 1))

13
userspace/sys/mman.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
/* To keep in sync with PAGING_MEM_* */
#define PROT_EXEC (1<<3)
#define PROT_READ (1<<1)
#define PROT_WRITE (1<<2)
#define MAP_SHARED (1 << 0)
#define MAP_PRIVATE (1 << 1)
#define MAP_FIXED (1 << 2)
#define MAP_FAILED (void *)-1

8
userspace/thread.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include <stddef.h>
typedef unsigned long int pthread_t;
typedef void *(start_routine)(void *);
int thread_create(pthread_t *thread, start_routine *func, void *arg, size_t stackSize);
/* retval is ignored ATM */
int thread_join(pthread_t thread, void **retval);

View File

@ -282,8 +282,27 @@ void run()
/* Main program. */
int func_tiny()
void * func_tiny(void *args)
{
(void)args;
printf("Enter your program then ESC\n\n");
printf("TinyC grammar\n");
printf("<program> ::= <statement>\n");
printf("<statement> ::= \"if\" <paren_expr> <statement> |\n");
printf(" \"if\" <paren_expr> <statement> \"else\" <statement> |\n");
printf(" \"while\" <paren_expr> <statement> |\n");
printf(" \"do\" <statement> \"while\" <paren_expr> \";\" |\n");
printf(" \"{\" { <statement> } \"}\" |\n");
printf(" <expr> \";\" |\n");
printf(" \";\"\n");
printf("<paren_expr> ::= \"(\" <expr> \")\"\n");
printf("<expr> ::= <test> | <id> \"=\" <expr>\n");
printf("<test> ::= <sum> | <sum> \"<\" <sum> | <sum> \">\" <sum>\n");
printf("<sum> ::= <term> | <sum> \"+\" <term> | <sum> \"-\" <term>\n");
printf("<term> ::= <id> | <int> | <paren_expr>\n");
printf("<id> ::= \"a\" | \"b\" | \"c\" | \"d\" | ... | \"z\"\n");
printf("<int> ::= <an_unsigned_decimal_integer>\n");
int i;
ch = ' ';
sym = 0;

View File

@ -1,4 +1,4 @@
#pragma once
int func_tiny();
void * func_tiny(void *args);

View File

@ -1,32 +1,5 @@
#pragma once
#define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX >> 1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define INT_MAX ((int)(~0U >> 1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL >> 1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)
#define LLONG_MAX ((long long)(~0ULL >> 1))
#define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL)
#define SIZE_MAX (~(size_t)0)
#define PHYS_ADDR_MAX (~(phys_addr_t)0)
#define U8_MAX ((u8)~0U)
#define S8_MAX ((s8)(U8_MAX >> 1))
#define S8_MIN ((s8)(-S8_MAX - 1))
#define U16_MAX ((u16)~0U)
#define S16_MAX ((s16)(U16_MAX >> 1))
#define S16_MIN ((s16)(-S16_MAX - 1))
#define U32_MAX ((u32)~0U)
#define S32_MAX ((s32)(U32_MAX >> 1))
#define S32_MIN ((s32)(-S32_MAX - 1))
#define U64_MAX ((u64)~0ULL)
#define S64_MAX ((s64)(U64_MAX >> 1))
#define S64_MIN ((s64)(-S64_MAX - 1))
// Virtual address
typedef unsigned long vaddr_t;

6
userspace/unistd.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
typedef unsigned int useconds_t;
int usleep(useconds_t usec);
typedef unsigned long int pid_t;