mirror of
https://github.com/kenshineto/kern.git
synced 2025-04-16 23:47:25 +00:00
remove legacy bullshit
This commit is contained in:
parent
f89a4592c9
commit
9b26a288ae
17 changed files with 0 additions and 1374 deletions
11
0.S
11
0.S
|
@ -1,11 +0,0 @@
|
|||
/**
|
||||
** @file ?
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief ?
|
||||
*/
|
||||
|
||||
#define ASM_SRC
|
||||
|
||||
.arch i386
|
35
0.c
35
0.c
|
@ -1,35 +0,0 @@
|
|||
/**
|
||||
** @file ?
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief ?
|
||||
*/
|
||||
|
||||
#define KERNEL_SRC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
** PRIVATE DEFINITIONS
|
||||
*/
|
||||
|
||||
/*
|
||||
** PRIVATE DATA TYPES
|
||||
*/
|
||||
|
||||
/*
|
||||
** PRIVATE GLOBAL VARIABLES
|
||||
*/
|
||||
|
||||
/*
|
||||
** PUBLIC GLOBAL VARIABLES
|
||||
*/
|
||||
|
||||
/*
|
||||
** PRIVATE FUNCTIONS
|
||||
*/
|
||||
|
||||
/*
|
||||
** PUBLIC FUNCTIONS
|
||||
*/
|
38
0.h
38
0.h
|
@ -1,38 +0,0 @@
|
|||
/**
|
||||
** @file ?
|
||||
**
|
||||
** @author CSCI-452 class of 20245
|
||||
**
|
||||
** @brief ?
|
||||
*/
|
||||
|
||||
#ifndef ?_H_
|
||||
#define ?_H_
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
** General (C and/or assembly) definitions
|
||||
*/
|
||||
|
||||
#ifndef ASM_SRC
|
||||
|
||||
/*
|
||||
** Start of C-only definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
** Types
|
||||
*/
|
||||
|
||||
/*
|
||||
** Globals
|
||||
*/
|
||||
|
||||
/*
|
||||
** Prototypes
|
||||
*/
|
||||
|
||||
#endif /* !ASM_SRC */
|
||||
|
||||
#endif
|
BIN
BuildImage
BIN
BuildImage
Binary file not shown.
36
MK
36
MK
|
@ -1,36 +0,0 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Run 'make', saving all output into a file named LOG
|
||||
#
|
||||
# usage:
|
||||
# MK [args] - prints timestamps and status
|
||||
# MKV [args] - echoes and saves 'make' output
|
||||
#
|
||||
|
||||
# remember this so we know what to do
|
||||
name="`basename $0`"
|
||||
|
||||
# starting timestamp
|
||||
time1="`date`"
|
||||
|
||||
if [ "$name" = "MK" ]
|
||||
then
|
||||
# run make, save output, check status
|
||||
echo -n + make $* '> LOG 2>&1 ... '
|
||||
if make $* > LOG 2>&1
|
||||
then
|
||||
echo done
|
||||
else
|
||||
echo check LOG for build errors
|
||||
fi
|
||||
else
|
||||
# just do the make and save a copy of the output
|
||||
echo + make $* '2>&1 | tee LOG'
|
||||
make $* 2>&1 | tee LOG
|
||||
fi
|
||||
|
||||
# ending timestamp
|
||||
time2="`date`"
|
||||
|
||||
echo Start: $time1
|
||||
echo "End: " $time2
|
36
MKV
36
MKV
|
@ -1,36 +0,0 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Run 'make', saving all output into a file named LOG
|
||||
#
|
||||
# usage:
|
||||
# MK [args] - prints timestamps and status
|
||||
# MKV [args] - echoes and saves 'make' output
|
||||
#
|
||||
|
||||
# remember this so we know what to do
|
||||
name="`basename $0`"
|
||||
|
||||
# starting timestamp
|
||||
time1="`date`"
|
||||
|
||||
if [ "$name" = "MK" ]
|
||||
then
|
||||
# run make, save output, check status
|
||||
echo -n + make $* '> LOG 2>&1 ... '
|
||||
if make $* > LOG 2>&1
|
||||
then
|
||||
echo done
|
||||
else
|
||||
echo check LOG for build errors
|
||||
fi
|
||||
else
|
||||
# just do the make and save a copy of the output
|
||||
echo + make $* '2>&1 | tee LOG'
|
||||
make $* 2>&1 | tee LOG
|
||||
fi
|
||||
|
||||
# ending timestamp
|
||||
time2="`date`"
|
||||
|
||||
echo Start: $time1
|
||||
echo "End: " $time2
|
16
QRUN
16
QRUN
|
@ -1,16 +0,0 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Run qemu-system-i386 on the baseline OS
|
||||
#
|
||||
|
||||
#
|
||||
# other options:
|
||||
# -nographic
|
||||
# -display gtk
|
||||
#
|
||||
|
||||
QEMU=/home/course/csci352/bin/qemu-system-i386
|
||||
|
||||
exec $QEMU \
|
||||
-serial mon:stdio \
|
||||
-drive file=disk.img,index=0,media=disk,format=raw
|
43
boot/Make.mk
43
boot/Make.mk
|
@ -1,43 +0,0 @@
|
|||
#
|
||||
# Makefile fragment for the bootstrap component of the system.
|
||||
#
|
||||
# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level
|
||||
# directory, and this will be pulled in automatically.
|
||||
#
|
||||
|
||||
SUBDIRS += boot
|
||||
|
||||
###################
|
||||
# FILES SECTION #
|
||||
###################
|
||||
|
||||
BOOT_SRC := boot/boot.S
|
||||
|
||||
BOOT_OBJ := $(BUILDDIR)/boot/boot.o
|
||||
|
||||
# BLDFLAGS := -Ttext 0x7c00 -s --oformat binary -e bootentry
|
||||
# BLDFLAGS := -Ttext 0 -s --oformat binary -e bootentry
|
||||
# BLDFLAGS := -N -Ttext 0x7c00 -s -e bootentry
|
||||
BLDFLAGS := -N -Ttext 0 -s -e bootentry
|
||||
|
||||
###################
|
||||
# RULES SECTION #
|
||||
###################
|
||||
|
||||
bootstrap: $(BUILDDIR)/boot/boot
|
||||
|
||||
$(BUILDDIR)/boot/%.o: boot/%.c $(BUILDDIR)/.vars.CFLAGS
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(BUILDDIR)/boot/%.o: boot/%.S $(BUILDDIR)/.vars.CFLAGS
|
||||
@mkdir -p $(@D)
|
||||
$(CPP) $(CPPFLAGS) -o $(@D)/$*.s $<
|
||||
$(AS) $(ASFLAGS) -o $@ $(@D)/$*.s -a=$(@D)/$*.lst
|
||||
$(RM) -f $(@D)/$*.s
|
||||
$(NM) -n $@ > $(@D)/$*.sym
|
||||
|
||||
$(BUILDDIR)/boot/boot: $(BOOT_OBJ)
|
||||
@mkdir -p $(@D)
|
||||
$(LD) $(LDFLAGS) $(BLDFLAGS) -o $@.out $^
|
||||
$(OBJCOPY) -S -O binary -j .text $@.out $@
|
|
@ -1,66 +0,0 @@
|
|||
#
|
||||
# Makefile fragment for the kernel components of the system.
|
||||
#
|
||||
# Makefile fragment for the kernel component of the system.
|
||||
#
|
||||
# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level
|
||||
# directory, and this will be pulled in automatically.
|
||||
#
|
||||
|
||||
SUBDIRS += kernel
|
||||
|
||||
###################
|
||||
# FILES SECTION #
|
||||
###################
|
||||
|
||||
BOOT_OBJ := $(patsubst %.c, $(BUILDDIR)/%.o, $(BOOT_SRC))
|
||||
|
||||
KERN_SRC := kernel/startup.S kernel/isrs.S \
|
||||
kernel/cio.c kernel/clock.c kernel/kernel.c kernel/kmem.c \
|
||||
kernel/list.c kernel/procs.c kernel/sio.c kernel/support.c \
|
||||
kernel/syscalls.c kernel/user.c kernel/vm.c kernel/vmtables.c
|
||||
|
||||
KERN_OBJ := $(patsubst %.c, $(BUILDDIR)/%.o, $(KERN_SRC))
|
||||
KERN_OBJ := $(patsubst %.S, $(BUILDDIR)/%.o, $(KERN_OBJ))
|
||||
|
||||
KCFLAGS := -ggdb
|
||||
KLDFLAGS := -T kernel/kernel.ld
|
||||
KLIBS := -lkernel -lcommon
|
||||
|
||||
###################
|
||||
# RULES SECTION #
|
||||
###################
|
||||
|
||||
kernel: $(BUILDDIR)/kernel/kernel.b
|
||||
|
||||
$(BUILDDIR)/kernel/%.o: kernel/%.c $(BUILDDIR)/.vars.CFLAGS
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) $(KCFLAGS) -c -o $@ $<
|
||||
|
||||
$(BUILDDIR)/kernel/%.o: kernel/%.S $(BUILDDIR)/.vars.CFLAGS
|
||||
@mkdir -p $(@D)
|
||||
$(CPP) $(CPPFLAGS) -o $(@D)/$*.s $<
|
||||
$(AS) $(ASFLAGS) $(KCFLAGS) -o $@ $(@D)/$*.s -a=$(@D)/$*.lst
|
||||
$(RM) -f $(@D)/$*.s
|
||||
|
||||
$(BUILDDIR)/kernel/kernel: $(KERN_OBJ)
|
||||
@mkdir -p $(@D)
|
||||
$(LD) $(KLDFLAGS) $(LDFLAGS) -o $@ $(KERN_OBJ) $(KLIBS)
|
||||
$(OBJDUMP) -S $@ > $@.asm
|
||||
$(NM) -n $@ > $@.sym
|
||||
$(READELF) -a $@ > $@.info
|
||||
|
||||
$(BUILDDIR)/kernel/kernel.b: $(BUILDDIR)/kernel/kernel
|
||||
$(LD) $(LDFLAGS) -o $(BUILDDIR)/kernel/kernel.b -s \
|
||||
--oformat binary -Ttext 0x10000 $(BUILDDIR)/kernel/kernel
|
||||
|
||||
# some debugging assist rules
|
||||
$(BUILDDIR)/kernel/%.i: kernel/%.c $(BUILDDIR)/.vars.CFLAGS
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) $(KCFLAGS) -E -c $< > $(@D)/$*.i
|
||||
|
||||
$(BUILDDIR)/kernel/%.dat: $(BUILDDIR)/kernel/%.o
|
||||
@mkdir -p $(@D)
|
||||
$(OBJCOPY) -S -O binary -j .data $< $@
|
||||
hexdump -C $@ > $(@D)/$*.hex
|
||||
|
73
lib/Make.mk
73
lib/Make.mk
|
@ -1,73 +0,0 @@
|
|||
#
|
||||
# Makefile fragment for the library components of the system.
|
||||
#
|
||||
# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level
|
||||
# directory, and this will be pulled in automatically.
|
||||
#
|
||||
|
||||
SUBDIRS += lib
|
||||
|
||||
###################
|
||||
# FILES SECTION #
|
||||
###################
|
||||
|
||||
#
|
||||
# library file lists
|
||||
#
|
||||
|
||||
# "common" library functions, used by kernel and users
|
||||
CLIB_SRC := lib/bound.c lib/cvtdec.c lib/cvtdec0.c \
|
||||
lib/cvthex.c lib/cvtoct.c lib/cvtuns.c \
|
||||
lib/cvtuns0.c lib/memclr.c lib/memcpy.c \
|
||||
lib/memset.c lib/pad.c lib/padstr.c \
|
||||
lib/sprint.c lib/str2int.c lib/strcat.c \
|
||||
lib/strcmp.c lib/strcpy.c lib/strlen.c
|
||||
|
||||
# user-only library functions
|
||||
ULIB_SRC := lib/ulibc.c lib/ulibs.S lib/entry.S
|
||||
|
||||
# kernel-only library functions
|
||||
KLIB_SRC := lib/klibc.c
|
||||
|
||||
# lists of object files
|
||||
CLIB_OBJ:= $(patsubst lib/%.c, $(BUILDDIR)/lib/%.o, $(CLIB_SRC))
|
||||
|
||||
ULIB_OBJ:= $(patsubst lib/%.c, $(BUILDDIR)/lib/%.o, $(ULIB_SRC))
|
||||
ULIB_OBJ:= $(patsubst lib/%.S, $(BUILDDIR)/lib/%.o, $(ULIB_OBJ))
|
||||
|
||||
KLIB_OBJ := $(patsubst lib/%.c, $(BUILDDIR)/lib/%.o, $(KLIB_SRC))
|
||||
KLIB_OBJ := $(patsubst lib/%.S, $(BUILDDIR)/lib/%.o, $(KLIB_OBJ))
|
||||
|
||||
# library file names
|
||||
CLIB_NAME := libcommon.a
|
||||
ULIB_NAME := libuser.a
|
||||
KLIB_NAME := libkernel.a
|
||||
|
||||
###################
|
||||
# RULES SECTION #
|
||||
###################
|
||||
|
||||
# how to make everything
|
||||
lib: $(BUILDDIR)/lib/$(CLIB_NAME) \
|
||||
$(BUILDDIR)/lib/$(KLIB_NAME) \
|
||||
$(BUILDDIR)/lib/$(ULIB_NAME)
|
||||
|
||||
$(BUILDDIR)/lib/%.o: lib/%.c $(BUILDDIR)/.vars.CFLAGS
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(BUILDDIR)/lib/%.o: lib/%.S $(BUILDDIR)/.vars.CFLAGS
|
||||
@mkdir -p $(@D)
|
||||
$(CPP) $(CPPFLAGS) -o $(@D)/$*.s $<
|
||||
$(AS) $(ASFLAGS) -o $@ $(@D)/$*.s -a=$(@D)/$*.lst
|
||||
$(RM) -f $(@D)/$*.s
|
||||
$(NM) -n $@ > $(@D)/$*.sym
|
||||
|
||||
$(BUILDDIR)/lib/$(CLIB_NAME): $(CLIB_OBJ)
|
||||
$(AR) $(ARFLAGS) $@ $(CLIB_OBJ)
|
||||
|
||||
$(BUILDDIR)/lib/$(ULIB_NAME): $(ULIB_OBJ)
|
||||
$(AR) $(ARFLAGS) $@ $(ULIB_OBJ)
|
||||
|
||||
$(BUILDDIR)/lib/$(KLIB_NAME): $(KLIB_OBJ)
|
||||
$(AR) $(ARFLAGS) $@ $(KLIB_OBJ)
|
64
user/Make.mk
64
user/Make.mk
|
@ -1,64 +0,0 @@
|
|||
#
|
||||
# Makefile fragment for the user components of the system.
|
||||
#
|
||||
# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level
|
||||
# directory, and this will be pulled in automatically.
|
||||
#
|
||||
|
||||
SUBDIRS += user
|
||||
|
||||
###################
|
||||
# FILES SECTION #
|
||||
###################
|
||||
|
||||
# order here must match the order of program names in the
|
||||
# 'user_e' enum defined in include/userids.h!!!
|
||||
USER_SRC := user/init.c user/idle.c user/shell.c \
|
||||
user/progABC.c user/progDE.c user/progFG.c user/progH.c \
|
||||
user/progI.c user/progJ.c user/progKL.c user/progMN.c \
|
||||
user/progP.c user/progQ.c user/progR.c user/progS.c \
|
||||
user/progTUV.c user/progW.c user/progX.c user/progY.c \
|
||||
user/progZ.c
|
||||
|
||||
USER_OBJ := $(patsubst %.c, $(BUILDDIR)/%.o, $(USER_SRC))
|
||||
|
||||
USER_BIN := $(basename $(USER_SRC))
|
||||
USER_BIN := $(addprefix $(BUILDDIR)/, $(USER_BIN))
|
||||
|
||||
ULDFLAGS := -T user/user.ld
|
||||
ULIBS := -luser -lcommon
|
||||
|
||||
###################
|
||||
# RULES SECTION #
|
||||
###################
|
||||
|
||||
userland: $(USER_BIN)
|
||||
|
||||
$(BUILDDIR)/user/%.o: user/%.c $(BUILDDIR)/.vars.CFLAGS
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(BUILDDIR)/user/%: $(BUILDDIR)/user/%.o
|
||||
@mkdir -p $(@D)
|
||||
$(LD) $(ULDFLAGS) $(LDFLAGS) -o $@ $@.o $(ULIBS)
|
||||
$(OBJDUMP) -S $@ > $@.asm
|
||||
$(NM) -n $@ > $@.sym
|
||||
$(READELF) -a $@ > $@.info
|
||||
|
||||
#
|
||||
# Remake the "user blob". When this happens, we also generate a new
|
||||
# version of the userids.h header file; we don't copy it over the
|
||||
# previous version if it is the same, to avoid triggering remakes
|
||||
# of the rest of the system.
|
||||
#
|
||||
user.img: $(USR_BIN) mkblob
|
||||
./mkblob $(USER_BIN)
|
||||
@./listblob -e $@ > $(BUILDDIR)/new_userids.h
|
||||
-@sh -c 'cmp -s include/userids.h $(BUILDDIR)/new_userids.h || \
|
||||
(cp $(BUILDDIR)/new_userids.h include/userids.h; \
|
||||
echo "\n*** NOTE - updated include/userids.h, rebuild\!" ; \
|
||||
rm -f $(BUILDDIR)/new_userids.h)'
|
||||
|
||||
# some debugging assist rules
|
||||
user.hex: user.img
|
||||
hexdump -C $< > $@
|
59
util/Make.mk
59
util/Make.mk
|
@ -1,59 +0,0 @@
|
|||
#
|
||||
# Makefile fragment for the utility programs
|
||||
#
|
||||
# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level
|
||||
# directory, and this will be pulled in automatically.
|
||||
#
|
||||
|
||||
###################
|
||||
# FILES SECTION #
|
||||
###################
|
||||
|
||||
UTIL_BIN := BuildImage Offsets mkblob listblob
|
||||
|
||||
###################
|
||||
# RULES SECTION #
|
||||
###################
|
||||
|
||||
# how to make everything
|
||||
util: $(UTIL_BIN)
|
||||
|
||||
#
|
||||
# Special rules for creating the utility programs. These are required
|
||||
# because we don't want to use the same options as for the standalone
|
||||
# binaries - we want these to be compiled as "normal" programs.
|
||||
#
|
||||
|
||||
BuildImage: util/BuildImage.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -std=c99 -ggdb -o BuildImage util/BuildImage.c
|
||||
|
||||
mkblob: util/mkblob.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -std=c99 -ggdb -o mkblob util/mkblob.c
|
||||
|
||||
listblob: util/listblob.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -std=c99 -ggdb -o listblob util/listblob.c
|
||||
|
||||
#
|
||||
# Offsets is compiled using -mx32 to force a 32-bit execution environment
|
||||
# for a program that runs under a 64-bit operating system. This ensures
|
||||
# that pointers and long ints are 32 bits rather than 64 bits, which is
|
||||
# critical to correctly determining the size of types and byte offsets for
|
||||
# fields in structs. We also compile with "-fno-builtin" to avoid signature
|
||||
# clashes between declarations in our system and function declarations
|
||||
# built into the C compiler.
|
||||
#
|
||||
# If compiled with the CPP macro CREATE_HEADER_FILE defined, Offsets
|
||||
# accepts a command-line argument "-h". This causes it to write its
|
||||
# output as a standard C header file into a file named "include/offsets.h"
|
||||
# where it can be included into other source files (e.g., to provide
|
||||
# sizes of structs in C and assembly, or to provide byte offsets into
|
||||
# structures for use in assembly code).
|
||||
#
|
||||
|
||||
Offsets: util/Offsets.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -mx32 -std=c99 $(INCLUDES) -fno-builtin \
|
||||
-o Offsets util/Offsets.c
|
|
@ -1,56 +0,0 @@
|
|||
#
|
||||
# Makefile fragment for the utility programs
|
||||
#
|
||||
# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level
|
||||
# directory, and this will be pulled in automatically.
|
||||
#
|
||||
|
||||
SUBDIRS += util
|
||||
|
||||
###################
|
||||
# RULES SECTION #
|
||||
###################
|
||||
|
||||
# how to make everything
|
||||
util: $(BUILDDIR)/util/BuildImage $(BUILDDIR)/util/Offsets \
|
||||
$(BUILDDIR)/util/mkblob $(BUILDDIR)/util/listblob
|
||||
|
||||
#
|
||||
# Special rules for creating the utility programs. These are required
|
||||
# because we don't want to use the same options as for the standalone
|
||||
# binaries - we want these to be compiled as "normal" programs.
|
||||
#
|
||||
|
||||
$(BUILDDIR)/util/BuildImage: util/BuildImage.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -std=c99 -o $(BUILDDIR)/util/BuildImage util/BuildImage.c
|
||||
|
||||
$(BUILDDIR)/util/mkblob: util/mkblob.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -std=c99 -o $(BUILDDIR)/util/mkblob util/mkblob.c
|
||||
|
||||
$(BUILDDIR)/util/listblob: util/listblob.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -std=c99 -o $(BUILDDIR)/util/listblob util/listblob.c
|
||||
|
||||
#
|
||||
# Offsets is compiled using -mx32 to force a 32-bit execution environment
|
||||
# for a program that runs under a 64-bit operating system. This ensures
|
||||
# that pointers and long ints are 32 bits rather than 64 bits, which is
|
||||
# critical to correctly determining the size of types and byte offsets for
|
||||
# fields in structs. We also compile with "-fno-builtin" to avoid signature
|
||||
# clashes between declarations in our system and function declarations
|
||||
# built into the C compiler.
|
||||
#
|
||||
# If compiled with the CPP macro CREATE_HEADER_FILE defined, Offsets
|
||||
# accepts a command-line argument "-h". This causes it to write its
|
||||
# output as a standard C header file into a file named "include/offsets.h"
|
||||
# where it can be included into other source files (e.g., to provide
|
||||
# sizes of structs in C and assembly, or to provide byte offsets into
|
||||
# structures for use in assembly code).
|
||||
#
|
||||
|
||||
$(BUILDDIR)/util/Offsets: util/Offsets.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -mx32 -std=c99 $(INCLUDES) -fno-builtin \
|
||||
-o $(BUILDDIR)/util/Offsets util/Offsets.c
|
|
@ -1,31 +0,0 @@
|
|||
This directory contains "alternative" versions of some pieces of the system.
|
||||
|
||||
Things included here:
|
||||
|
||||
Make.mk
|
||||
This version of the Makefile fragment puts the utility programs
|
||||
in build/util instead of in the top-level directory.
|
||||
|
||||
kmem.c
|
||||
A version of the memory allocator that works with blocks of memory
|
||||
that aren't exactly one page in length. During initialilzation, it
|
||||
just adds each memory region identified during the boot process by
|
||||
calls to the BIOS; as pages are requested, they are carved out of
|
||||
these large blocks. The freelist is ordered by starting block
|
||||
address, and allocation uses a first-fit strateby.
|
||||
|
||||
The allocation function has this prototype:
|
||||
|
||||
void *km_page_alloc( unsigned int count );
|
||||
|
||||
This allows the allocation of multiple contiguous pages. As pages
|
||||
are freed, they are merged back into the freelist, and adjacent
|
||||
free pages are coalesced into single, larger blocks.
|
||||
|
||||
lib.c
|
||||
This file pulls in all the individual .c files for the common
|
||||
library functions in the lib/ directory. It is intended as an
|
||||
alternative to having the libk.a archive file for the kernel;
|
||||
instead of linking against that library, the lib.o file can
|
||||
just be provided to the linker when the kernel is created,
|
||||
and all the common library functions will be available.
|
|
@ -1,749 +0,0 @@
|
|||
/**
|
||||
** @file kmem.c
|
||||
**
|
||||
** @author Warren R. Carithers
|
||||
** @author Kenneth Reek
|
||||
** @author 4003-506 class of 20013
|
||||
**
|
||||
** @brief Functions to perform dynamic memory allocation in the OS.
|
||||
**
|
||||
** NOTE: these should NOT be called by user processes!
|
||||
**
|
||||
** This allocator functions as a simple "slab" allocator; it allows
|
||||
** allocation of either 4096-byte ("page") or 1024-byte ("slice")
|
||||
** chunks of memory from the free pool. The free pool is initialized
|
||||
** using the memory map provided by the BIOS during the boot sequence,
|
||||
** and contains a series of blocks which are multiples of 4K bytes and
|
||||
** which are aligned at 4K boundaries; they are held in the free list
|
||||
** in order by base address.
|
||||
**
|
||||
** The "page" allocator allows allocation of one or more 4K blocks
|
||||
** at a time. Requests are made for a specific number of 4K pages;
|
||||
** the allocator locates the first free list entry that contains at
|
||||
** least the requested amount of space. If that entry is the exact
|
||||
** size requested, it is unlinked and returned; otherwise, the entry
|
||||
** is split into a chunk of the requested size and the remainder.
|
||||
** The chunk is returned, and the remainder replaces the original
|
||||
** block in the free list. On deallocation, the block is inserted
|
||||
** at the appropriate place in the free list, and physically adjacent
|
||||
** blocks are coalesced into single, larger blocks. If a multi-page
|
||||
** block is allocated, it should be deallocated one page at a time,
|
||||
** because there is no record of the size of the original allocation -
|
||||
** all we know is that it is N*4K bytes in length, so it's up to the
|
||||
** requesting code to figure this out.
|
||||
**
|
||||
** The "slice" allocator operates by taking blocks from the "page"
|
||||
** allocator and splitting them into four 1K slices, which it then
|
||||
** manages. Requests are made for slices one at a time. If the free
|
||||
** list contains an available slice, it is unlinked and returned;
|
||||
** otherwise, a page is requested from the page allocator, split into
|
||||
** slices, and the slices are added to the free list, after which the
|
||||
** first one is returned. The slice free list is a simple linked list
|
||||
** of these 1K blocks; because they are all the same size, no ordering
|
||||
** is done on the free list, and no coalescing is performed.
|
||||
**
|
||||
*/
|
||||
|
||||
#define KERNEL_SRC
|
||||
|
||||
#include <common.h>
|
||||
|
||||
// all other framework includes are next
|
||||
#include <lib.h>
|
||||
|
||||
#include <x86/arch.h>
|
||||
#include <x86/bios.h>
|
||||
#include <bootstrap.h>
|
||||
#include <cio.h>
|
||||
|
||||
#include <kmem.h>
|
||||
|
||||
/*
|
||||
** PRIVATE DEFINITIONS
|
||||
*/
|
||||
|
||||
// parameters related to word and block sizes
|
||||
|
||||
#define WORD_SIZE sizeof(int)
|
||||
#define LOG2_OF_WORD_SIZE 2
|
||||
|
||||
#define LOG2_OF_PAGE_SIZE 12
|
||||
|
||||
#define LOG2_OF_SLICE_SIZE 10
|
||||
|
||||
// converters: pages to bytes, bytes to pages
|
||||
|
||||
#define P2B(x) ((x) << LOG2_OF_PAGE_SIZE)
|
||||
#define B2P(x) ((x) >> LOG2_OF_PAGE_SIZE)
|
||||
|
||||
/*
|
||||
** Name: adjacent
|
||||
**
|
||||
** Arguments: addresses of two blocks
|
||||
**
|
||||
** Description: Determines whether the second block immediately
|
||||
** follows the first one.
|
||||
*/
|
||||
#define adjacent(first,second) \
|
||||
( (void *) (first) + P2B((first)->pages) == (void *) (second) )
|
||||
|
||||
/*
|
||||
** PRIVATE DATA TYPES
|
||||
*/
|
||||
|
||||
/*
|
||||
** This structure keeps track of a single block of memory. All blocks
|
||||
** are multiples of the base size (currently, 4KB).
|
||||
*/
|
||||
|
||||
typedef struct block_s {
|
||||
uint32_t pages; // length of this block, in pages
|
||||
struct block_s *next; // pointer to the next free block
|
||||
} block_t;
|
||||
|
||||
/*
|
||||
** Memory region information returned by the BIOS
|
||||
**
|
||||
** This data consists of a 32-bit integer followed
|
||||
** by an array of region descriptor structures.
|
||||
*/
|
||||
|
||||
// a handy union for playing with 64-bit addresses
|
||||
typedef union b64_u {
|
||||
uint32_t part[2];
|
||||
uint64_t all;
|
||||
} b64_t;
|
||||
|
||||
// the halves of a 64-bit address
|
||||
#define LOW part[0]
|
||||
#define HIGH part[1]
|
||||
|
||||
// memory region descriptor
|
||||
typedef struct memregion_s {
|
||||
b64_t base; // base address
|
||||
b64_t length; // region length
|
||||
uint32_t type; // type of region
|
||||
uint32_t acpi; // ACPI 3.0 info
|
||||
} __attribute__((packed)) region_t;
|
||||
|
||||
/*
|
||||
** Region types
|
||||
*/
|
||||
|
||||
#define REGION_USABLE 1
|
||||
#define REGION_RESERVED 2
|
||||
#define REGION_ACPI_RECL 3
|
||||
#define REGION_ACPI_NVS 4
|
||||
#define REGION_BAD 5
|
||||
|
||||
/*
|
||||
** ACPI 3.0 bit fields
|
||||
*/
|
||||
|
||||
#define REGION_IGNORE 0x01
|
||||
#define REGION_NONVOL 0x02
|
||||
|
||||
/*
|
||||
** 32-bit and 64-bit address values as 64-bit literals
|
||||
*/
|
||||
|
||||
#define ADDR_BIT_32 0x0000000100000000LL
|
||||
#define ADDR_LOW_HALF 0x00000000ffffffffLL
|
||||
#define ADDR_HIGH_HALR 0xffffffff00000000LL
|
||||
|
||||
#define ADDR_32_MAX ADDR_LOW_HALF
|
||||
#define ADDR_64_FIRST ADDR_BIT_32
|
||||
|
||||
/*
|
||||
** PRIVATE GLOBAL VARIABLES
|
||||
*/
|
||||
|
||||
// freespace pools
|
||||
static block_t *free_pages;
|
||||
static block_t *free_slices;
|
||||
|
||||
// initialization status
|
||||
static int km_initialized = 0;
|
||||
|
||||
/*
|
||||
** IMPORTED GLOBAL VARIABLES
|
||||
*/
|
||||
|
||||
extern int _end; // end of the BSS section - provided by the linker
|
||||
|
||||
/*
|
||||
** FUNCTIONS
|
||||
*/
|
||||
|
||||
/*
|
||||
** FREE LIST MANAGEMENT
|
||||
*/
|
||||
|
||||
/**
|
||||
** Name: add_block
|
||||
**
|
||||
** Add a block to the free list. The contents of the block
|
||||
** will be modified.
|
||||
**
|
||||
** @param[in] base Base address of the block
|
||||
** @param[in] length Block length, in bytes
|
||||
*/
|
||||
static void add_block( uint32_t base, uint32_t length ) {
|
||||
block_t *block;
|
||||
|
||||
// don't add it if it isn't at least 4K
|
||||
if( length < SZ_PAGE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only want to add multiples of 4K; check the lower bits
|
||||
if( (length & 0xfff) != 0 ) {
|
||||
// round it down to 4K
|
||||
length &= 0xfffff000;
|
||||
}
|
||||
|
||||
// create the "block"
|
||||
|
||||
block = (block_t *) base;
|
||||
block->pages = B2P(length);
|
||||
block->next = NULL;
|
||||
|
||||
#if TRACING_KMEM_FREE
|
||||
cio_printf( "KM: add(%08x,%u): addr %08x len %u\n",
|
||||
base, length, (uint32_t)block, block->length );
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We maintain the free list in order by address, to simplify
|
||||
** coalescing adjacent free blocks.
|
||||
**
|
||||
** Handle the easiest case first.
|
||||
*/
|
||||
|
||||
if( free_pages == NULL ) {
|
||||
free_pages = block;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Unfortunately, it's not always that easy....
|
||||
**
|
||||
** Find the correct insertion spot.
|
||||
*/
|
||||
|
||||
block_t *prev, *curr;
|
||||
|
||||
prev = NULL;
|
||||
curr = free_pages;
|
||||
|
||||
while( curr && curr < block ) {
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
// the new block always points to its successor
|
||||
block->next = curr;
|
||||
|
||||
/*
|
||||
** If prev is NULL, we're adding at the front; otherwise,
|
||||
** we're adding after some other entry (middle or end).
|
||||
*/
|
||||
|
||||
if( prev == NULL ) {
|
||||
// sanity check - both pointers can't be NULL
|
||||
assert( curr );
|
||||
// add at the beginning
|
||||
free_pages = block;
|
||||
} else {
|
||||
// inserting in the middle or at the end
|
||||
prev->next = block;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Name: km_init
|
||||
**
|
||||
** Find what memory is present on the system and
|
||||
** construct the list of free memory blocks.
|
||||
**
|
||||
** Dependencies:
|
||||
** Must be called before any other init routine that uses
|
||||
** dynamic storage is called.
|
||||
*/
|
||||
void km_init( void ) {
|
||||
int32_t entries;
|
||||
region_t *region;
|
||||
uint64_t cutoff;
|
||||
|
||||
#if TRACING_INIT
|
||||
// announce that we're starting initialization
|
||||
cio_puts( " Kmem" );
|
||||
#endif
|
||||
|
||||
// initially, nothing in the free lists
|
||||
free_slices = NULL;
|
||||
free_pages = NULL;
|
||||
|
||||
/*
|
||||
** We ignore all memory below the end of our OS. In theory,
|
||||
** we should be able to re-use much of that space; in practice,
|
||||
** this is safer.
|
||||
*/
|
||||
|
||||
// set our cutoff point as the end of the BSS section
|
||||
cutoff = (uint32_t) &_end;
|
||||
|
||||
// round it up to the next multiple of 4K (0x1000)
|
||||
if( cutoff & 0xfffLL ) {
|
||||
cutoff &= 0xfffff000LL;
|
||||
cutoff += 0x1000LL;
|
||||
}
|
||||
|
||||
// get the list length
|
||||
entries = *((int32_t *) MMAP_ADDRESS);
|
||||
|
||||
#if TRACING_KEMEM
|
||||
cio_printf( "\nKmem: %d regions\n", entries );
|
||||
#endif
|
||||
|
||||
// if there are no entries, we have nothing to do!
|
||||
if( entries < 1 ) { // note: entries == -1 could occur!
|
||||
return;
|
||||
}
|
||||
|
||||
// iterate through the entries, adding things to the freelist
|
||||
|
||||
region = ((region_t *) (MMAP_ADDRESS + 4));
|
||||
|
||||
for( int i = 0; i < entries; ++i, ++region ) {
|
||||
|
||||
#if TRACING_KMEM
|
||||
// report this region
|
||||
cio_printf( "%3d: ", i );
|
||||
cio_printf( " base %08x%08x",
|
||||
region->base.HIGH, region->base.LOW );
|
||||
cio_printf( " len %08x%08x",
|
||||
region->length.HIGH, region->length.LOW );
|
||||
cio_printf( " type %08x acpi %08x",
|
||||
region->type, region->acpi );
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine whether or not we should ignore this region.
|
||||
**
|
||||
** We ignore regions for several reasons:
|
||||
**
|
||||
** ACPI indicates it should be ignored
|
||||
** ACPI indicates it's non-volatile memory
|
||||
** Region type isn't "usable"
|
||||
** Region is above the 4GB address limit
|
||||
**
|
||||
** Currently, only "normal" (type 1) regions are considered
|
||||
** "usable" for our purposes. We could potentially expand
|
||||
** this to include ACPI "reclaimable" memory.
|
||||
*/
|
||||
|
||||
// first, check the ACPI one-bit flags
|
||||
|
||||
if( ((region->acpi) & REGION_IGNORE) == 0 ) {
|
||||
cio_puts( " IGN\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ((region->acpi) & REGION_NONVOL) != 0 ) {
|
||||
cio_puts( " NVOL\n" );
|
||||
continue; // we'll ignore this, too
|
||||
}
|
||||
|
||||
// next, the region type
|
||||
|
||||
if( (region->type) != REGION_USABLE ) {
|
||||
cio_puts( " RCLM\n" );
|
||||
continue; // we won't attempt to reclaim ACPI memory (yet)
|
||||
}
|
||||
|
||||
// OK, we have a "normal" memory region - verify that it's usable
|
||||
|
||||
// ignore it if it's above 4GB
|
||||
if( region->base.HIGH != 0 ) {
|
||||
cio_puts( " 4GB+\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
// grab the two 64-bit values to simplify things
|
||||
uint64_t base = region->base.all;
|
||||
uint64_t length = region->length.all;
|
||||
|
||||
// see if it's below our arbitrary cutoff point
|
||||
if( base < cutoff ) {
|
||||
|
||||
// is the whole thing too low, or just part?
|
||||
if( (base + length) < cutoff ) {
|
||||
// it's all below the cutoff!
|
||||
cio_puts( " LOW\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
// recalculate the length, starting at our cutoff point
|
||||
uint64_t loss = cutoff - base;
|
||||
|
||||
// reset the length and the base address
|
||||
length -= loss;
|
||||
base = cutoff;
|
||||
}
|
||||
|
||||
// see if it extends beyond the 4GB boundary
|
||||
|
||||
if( (base + length) > ADDR_32_MAX ) {
|
||||
|
||||
// OK, it extends beyond the 32-bit limit; figure out
|
||||
// how far over it goes, and lop off that portion
|
||||
|
||||
uint64_t loss = (base + length) - ADDR_64_FIRST;
|
||||
length -= loss;
|
||||
}
|
||||
|
||||
// we survived the gauntlet - add the new block
|
||||
|
||||
cio_puts( " OK\n" );
|
||||
|
||||
uint32_t b32 = base & ADDR_LOW_HALF;
|
||||
uint32_t l32 = length & ADDR_LOW_HALF;
|
||||
|
||||
add_block( b32, l32 );
|
||||
}
|
||||
|
||||
// record the initialization
|
||||
km_initialized = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
** Name: km_dump
|
||||
**
|
||||
** Dump the current contents of the free list to the console
|
||||
*/
|
||||
void km_dump( void ) {
|
||||
block_t *block;
|
||||
|
||||
cio_printf( "&_free_pages=%08x\n", &_free_pages );
|
||||
|
||||
for( block = _free_pages; block != NULL; block = block->next ) {
|
||||
cio_printf(
|
||||
"block @ 0x%08x 0x%08x pages (ends at 0x%08x) next @ 0x%08x\n",
|
||||
block, block->pages, P2B(block->pages) + (uint32_t) block,
|
||||
block->next );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
** PAGE MANAGEMENT
|
||||
*/
|
||||
|
||||
/**
|
||||
** Name: km_page_alloc
|
||||
**
|
||||
** Allocate a page of memory from the free list.
|
||||
**
|
||||
** @param[in] count Number of contiguous pages desired
|
||||
**
|
||||
** @return a pointer to the beginning of the first allocated page,
|
||||
** or NULL if no memory is available
|
||||
*/
|
||||
void *km_page_alloc( unsigned int count ) {
|
||||
|
||||
assert( km_initialized );
|
||||
|
||||
// make sure we actually need to do something!
|
||||
if( count < 1 ) {
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
#if TRACING_KMEM_FREE
|
||||
cio_printf( "KM: pg_alloc(%u)", count );
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Look for the first entry that is large enough.
|
||||
*/
|
||||
|
||||
// pointer to the current block
|
||||
block_t *block = free_pages;
|
||||
|
||||
// pointer to where the pointer to the current block is
|
||||
block_t **pointer = &free_pages;
|
||||
|
||||
while( block != NULL && block->pages < count ){
|
||||
pointer = &block->next;
|
||||
block = *pointer;
|
||||
}
|
||||
|
||||
// did we find a big enough block?
|
||||
if( block == NULL ){
|
||||
// nope!
|
||||
#if TRACING_KMEM_FREE
|
||||
cio_puts( " FAIL\n" );
|
||||
#endif
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
// found one! check the length
|
||||
|
||||
if( block->pages == count ) {
|
||||
|
||||
// exactly the right size - unlink it from the list
|
||||
|
||||
*pointer = block->next;
|
||||
|
||||
} else {
|
||||
|
||||
// bigger than we need - carve the amount we need off
|
||||
// the beginning of this block
|
||||
|
||||
// remember where this chunk begins
|
||||
block_t *chunk = block;
|
||||
|
||||
// how much space will be left over?
|
||||
int excess = block->pages - count;
|
||||
|
||||
// find the start of the new fragment
|
||||
block_t *fragment = (block_t *) ( (uint8_t *) block + P2B(count) );
|
||||
|
||||
// set the length and link for the new fragment
|
||||
fragment->pages = excess;
|
||||
fragment->next = block->next;
|
||||
|
||||
// replace this chunk with the fragment
|
||||
*pointer = fragment;
|
||||
|
||||
// return this chunk
|
||||
block = chunk;
|
||||
}
|
||||
|
||||
#if TRACING_KMEM_FREE
|
||||
cio_printf( " -> %08x\n", (uint32_t) block );
|
||||
#endif
|
||||
|
||||
return( block );
|
||||
}
|
||||
|
||||
/**
|
||||
** Name: km_page_free
|
||||
**
|
||||
** Returns a memory block to the list of available blocks,
|
||||
** combining it with adjacent blocks if they're present.
|
||||
**
|
||||
** CRITICAL ASSUMPTION: multi-page blocks will be freed one page
|
||||
** at a time!
|
||||
**
|
||||
** @param[in] block Pointer to the page to be returned to the free list
|
||||
*/
|
||||
void km_page_free( void *block ){
|
||||
block_t *used;
|
||||
block_t *prev;
|
||||
block_t *curr;
|
||||
|
||||
assert( km_initialized );
|
||||
|
||||
/*
|
||||
** Don't do anything if the address is NULL.
|
||||
*/
|
||||
if( block == NULL ){
|
||||
return;
|
||||
}
|
||||
|
||||
#if TRACING_KMEM_FREE
|
||||
cio_printf( "KM: pg_free(%08x)", (uint32_t) block );
|
||||
#endif
|
||||
|
||||
used = (block_t *) block;
|
||||
|
||||
/*
|
||||
** CRITICAL ASSUMPTION
|
||||
**
|
||||
** We assume that any multi-page block that is being freed will
|
||||
** be freed one page at a time. We make this assumption because we
|
||||
** don't track allocation sizes. We can't use the simple "allocate
|
||||
** four extra bytes before the returned pointer" scheme to do this
|
||||
** because we're managing pages, and the pointers we return must point
|
||||
** to page boundaries, so we would wind up allocating an extra page
|
||||
** for each allocation.
|
||||
**
|
||||
** Alternatively, we could keep an array of addresses and block
|
||||
** sizes ourselves, but that feels clunky, and would risk running out
|
||||
** of table entries if there are lots of allocations (assuming we use
|
||||
** a 4KB page to hold the table, at eight bytes per entry we would have
|
||||
** 512 entries per page).
|
||||
**
|
||||
** IF THIS ASSUMPTION CHANGES, THIS CODE MUST BE FIXED!!!
|
||||
*/
|
||||
|
||||
used->pages = 1;
|
||||
|
||||
/*
|
||||
** Advance through the list until current and previous
|
||||
** straddle the place where the new block should be inserted.
|
||||
*/
|
||||
prev = NULL;
|
||||
curr = free_pages;
|
||||
|
||||
while( curr != NULL && curr < used ){
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
/*
|
||||
** At this point, we have the following list structure:
|
||||
**
|
||||
** .... BLOCK BLOCK ....
|
||||
** (*prev) ^ (*curr)
|
||||
** |
|
||||
** "used" goes here
|
||||
**
|
||||
** We may need to merge the inserted block with either its
|
||||
** predecessor or its successor (or both).
|
||||
*/
|
||||
|
||||
/*
|
||||
** If this is not the first block in the resulting list,
|
||||
** we may need to merge it with its predecessor.
|
||||
*/
|
||||
if( prev != NULL ){
|
||||
|
||||
// There is a predecessor. Check to see if we need to merge.
|
||||
if( adjacent( prev, used ) ){
|
||||
|
||||
// yes - merge them
|
||||
prev->pages += used->pages;
|
||||
|
||||
// the predecessor becomes the "newly inserted" block,
|
||||
// because we still need to check to see if we should
|
||||
// merge with the successor
|
||||
used = prev;
|
||||
|
||||
} else {
|
||||
|
||||
// Not adjacent - just insert the new block
|
||||
// between the predecessor and the successor.
|
||||
used->next = prev->next;
|
||||
prev->next = used;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Yes, it is first. Update the list pointer to insert it.
|
||||
used->next = free_pages;
|
||||
free_pages = used;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
** If this is not the last block in the resulting list,
|
||||
** we may (also) need to merge it with its successor.
|
||||
*/
|
||||
if( curr != NULL ){
|
||||
|
||||
// No. Check to see if it should be merged with the successor.
|
||||
if( adjacent( used, curr ) ){
|
||||
|
||||
// Yes, combine them.
|
||||
used->next = curr->next;
|
||||
used->pages += curr->pages;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** SLICE MANAGEMENT
|
||||
*/
|
||||
|
||||
/*
|
||||
** Slices are 1024-byte fragments from pages. We maintain a free list of
|
||||
** slices for those parts of the OS which don't need full 4096-byte chunks
|
||||
** of space (e.g., the QNode and Queue allocators).
|
||||
*/
|
||||
|
||||
/**
|
||||
** Name: carve_slices
|
||||
**
|
||||
** Allocate a page and split it into four slices; If no
|
||||
** memory is available, we panic.
|
||||
*/
|
||||
static void carve_slices( void ) {
|
||||
void *page;
|
||||
|
||||
// get a page
|
||||
page = km_page_alloc( 1 );
|
||||
|
||||
// allocation failure is a show-stopping problem
|
||||
assert( page );
|
||||
|
||||
// we have the page; create the four slices from it
|
||||
uint8_t *ptr = (uint8_t *) page;
|
||||
for( int i = 0; i < 4; ++i ) {
|
||||
km_slice_free( (void *) ptr );
|
||||
ptr += SZ_SLICE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Name: km_slice_alloc
|
||||
**
|
||||
** Dynamically allocates a slice (1/4 of a page). If no
|
||||
** memory is available, we panic.
|
||||
**
|
||||
** @return a pointer to the allocated slice
|
||||
*/
|
||||
void *km_slice_alloc( void ) {
|
||||
block_t *slice;
|
||||
|
||||
assert( km_initialized );
|
||||
|
||||
#if TRACING_KMEM_FREE
|
||||
cio_printf( "KM: sl_alloc()\n" );
|
||||
#endif
|
||||
|
||||
// if we are out of slices, create a few more
|
||||
if( free_slices == NULL ) {
|
||||
carve_slices();
|
||||
}
|
||||
|
||||
// take the first one from the free list
|
||||
slice = free_slices;
|
||||
assert( slice != NULL );
|
||||
|
||||
// unlink it
|
||||
free_slices = slice->next;
|
||||
|
||||
// make it nice and shiny for the caller
|
||||
memclr( (void *) slice, SZ_SLICE );
|
||||
|
||||
return( slice );
|
||||
}
|
||||
|
||||
/**
|
||||
** Name: km_slice_free
|
||||
**
|
||||
** Returns a slice to the list of available slices.
|
||||
**
|
||||
** We make no attempt to merge slices, as they are independent
|
||||
** blocks of memory (unlike pages).
|
||||
**
|
||||
** @param[in] block Pointer to the slice (1/4 page) to be freed
|
||||
*/
|
||||
void km_slice_free( void *block ) {
|
||||
block_t *slice = (block_t *) block;
|
||||
|
||||
assert( km_initialized );
|
||||
|
||||
#if TRACING_KMEM_FREE
|
||||
cio_printf( "KM: sl_free(%08x)\n", (uint32_t) block );
|
||||
#endif
|
||||
|
||||
// just add it to the front of the free list
|
||||
slice->pages = SZ_SLICE;
|
||||
slice->next = free_slices;
|
||||
free_slices = slice;
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/**
|
||||
** @file lib.c
|
||||
**
|
||||
** @author Numerous CSCI-452 classes
|
||||
**
|
||||
** @brief C implementations of common library functions
|
||||
**
|
||||
** These are callable from either kernel or user code. Care should be taken
|
||||
** that user code is linked against these separately from kernel code, to
|
||||
** ensure separation of the address spaces.
|
||||
**
|
||||
** This file exists to pull them all in as a single object file.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <lib.h>
|
||||
|
||||
/*
|
||||
**********************************************
|
||||
** MEMORY MANIPULATION FUNCTIONS
|
||||
**********************************************
|
||||
*/
|
||||
|
||||
#include "common/memset.c"
|
||||
#include "common/memclr.c"
|
||||
#include "common/memcpy.c"
|
||||
|
||||
/*
|
||||
**********************************************
|
||||
** STRING MANIPULATION FUNCTIONS
|
||||
**********************************************
|
||||
*/
|
||||
|
||||
#include "common/str2int.c"
|
||||
#include "common/strlen.c"
|
||||
#include "common/strcmp.c"
|
||||
#include "common/strcpy.c"
|
||||
#include "common/strcat.c"
|
||||
#include "common/pad.c"
|
||||
#include "common/padstr.c"
|
||||
#include "common/sprint.c"
|
||||
|
||||
/*
|
||||
**********************************************
|
||||
** CONVERSION FUNCTIONS
|
||||
**********************************************
|
||||
*/
|
||||
|
||||
#include "common/cvtuns0.c"
|
||||
#include "common/cvtuns.c"
|
||||
#include "common/cvtdec0.c"
|
||||
#include "common/cvtdec.c"
|
||||
#include "common/cvthex.c"
|
||||
#include "common/cvtoct.c"
|
||||
#include "common/bound.c"
|
|
@ -1,5 +0,0 @@
|
|||
vmtables.o: kernel/vmtables.c include/common.h include/types.h \
|
||||
include/params.h include/defs.h include/kdefs.h include/debug.h \
|
||||
include/cio.h include/support.h include/lib.h include/klib.h \
|
||||
include/x86/ops.h include/kmem.h include/procs.h include/vm.h \
|
||||
include/x86/arch.h
|
Loading…
Add table
Reference in a new issue