Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@

INC = -Iinclude
LIB = -lpthread

SRC = src
OBJ = obj
INCLUDE = include

CC = gcc
DEBUG = -g
CFLAGS = -Wall -c $(DEBUG)
LFLAGS = -Wall $(DEBUG)

vpath %.c $(SRC)
vpath %.h $(INCLUDE)

MAKE = $(CC) $(INC)

# Object files needed by modules
MEM_OBJ = $(addprefix $(OBJ)/, paging.o mem.o cpu.o loader.o)
TLB_OBJ = $(addprefix $(OBJ)/, cpu-tlb.o cpu-tlbcache.o)
OS_OBJ = $(addprefix $(OBJ)/, cpu.o cpu-tlb.o cpu-tlbcache.o mem.o loader.o queue.o os.o sched.o timer.o mm-vm.o mm.o mm-memphy.o)
SCHED_OBJ = $(addprefix $(OBJ)/, cpu.o loader.o)
HEADER = $(wildcard $(INCLUDE)/*.h)

all: os
#mem sched os

# Just compile memory management modules
mem: $(MEM_OBJ) $(TLB_OBJ)
$(MAKE) $(LFLAGS) $(MEM_OBJ) $(TLB_OBJ) -o mem $(LIB)

# Just compile scheduler
sched: $(SCHED_OBJ)
$(MAKE) $(LFLAGS) $(MEM_OBJ) -o sched $(LIB)

# Compile the whole OS simulation
os: $(OS_OBJ)
$(MAKE) $(LFLAGS) $(OS_OBJ) -o os $(LIB)

$(OBJ)/%.o: %.c ${HEADER} $(OBJ)
$(MAKE) $(CFLAGS) $< -o $@

# Prepare objectives container
$(OBJ):
mkdir -p $(OBJ)

clean:
rm -f $(OBJ)/*.o os sched mem
rm -r $(OBJ)

48 changes: 48 additions & 0 deletions include/bitops.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifdef CONFIG_64BIT
#define BITS_PER_LONG 64
#else
#define BITS_PER_LONG 32
#endif /* CONFIG_64BIT */

#define BITS_PER_BYTE 8
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define DIV_ROUND_DOWN(n,d) ((n) / (d))

#define BIT(nr) (1U << (nr))
#define BIT_ULL(nr) (1ULL << (nr))
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG))
#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG)

#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))

#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG))
#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG)

/*
* Create a contiguous bitmask starting at bit position @l and ending at
* position @h. For example
* GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
*/
#define GENMASK(h, l) \
(((~0U) << (l)) & (~0U >> (BITS_PER_LONG - (h) - 1)))

#define NBITS2(n) ((n&2)?1:0)
#define NBITS4(n) ((n&(0xC))?(2+NBITS2(n>>2)):(NBITS2(n)))
#define NBITS8(n) ((n&0xF0)?(4+NBITS4(n>>4)):(NBITS4(n)))
#define NBITS16(n) ((n&0xFF00)?(8+NBITS8(n>>8)):(NBITS8(n)))
#define NBITS32(n) ((n&0xFFFF0000)?(16+NBITS16(n>>16)):(NBITS16(n)))
#define NBITS(n) (n==0?0:NBITS32(n))

#define EXTRACT_NBITS(nr, h, l) ((nr&GENMASK(h,l)) >> l)

/*
* student implemented macros
*/

// macros supporting 64-bit address
#define GENMASK64(h, l) \
(((~0ULL) << (l)) & (~0ULL >> (64 - (h) - 1)))

#define EXTRACT_NBITS64(nr, h, l) ((nr & GENMASK64(h,l)) >> l)
93 changes: 93 additions & 0 deletions include/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#ifndef COMMON_H
#define COMMON_H

/* Define structs and routine could be used by every source files */

#include <stdint.h>

#ifndef OSCFG_H
#include "os-cfg.h"
#endif

#ifndef OSMM_H
#include "os-mm.h"
#endif

#define ADDRESS_SIZE 20
#define OFFSET_LEN 10
#define FIRST_LV_LEN 5
#define SECOND_LV_LEN 5
#define SEGMENT_LEN FIRST_LV_LEN
#define PAGE_LEN SECOND_LV_LEN

#define NUM_PAGES (1 << (ADDRESS_SIZE - OFFSET_LEN))
#define PAGE_SIZE (1 << OFFSET_LEN)

enum ins_opcode_t {
CALC, // Just perform calculation, only use CPU
ALLOC, // Allocate memory
FREE, // Deallocated a memory block
READ, // Write data to a byte on memory
WRITE // Read data from a byte on memory
};

/* instructions executed by the CPU */
struct inst_t {
enum ins_opcode_t opcode;
uint32_t arg_0; // Argument lists for instructions
uint32_t arg_1;
uint32_t arg_2;
};

struct code_seg_t {
struct inst_t * text;
uint32_t size;
};

struct trans_table_t {
/* A row in the page table of the second layer */
struct {
addr_t v_index; // The index of virtual address
addr_t p_index; // The index of physical address
} table[1 << SECOND_LV_LEN];
int size;
};

/* Mapping virtual addresses and physical ones */
struct page_table_t {
/* Translation table for the first layer */
struct {
addr_t v_index; // Virtual index
struct trans_table_t * next_lv;
} table[1 << FIRST_LV_LEN];
int size; // Number of row in the first layer
};

/* PCB, describe information about a process */
struct pcb_t {
uint32_t pid; // PID
uint32_t priority; // Default priority, this legacy (FIXED) value depend on process itself
struct code_seg_t * code; // Code segment
addr_t regs[10]; // Registers, store address of allocated regions
uint32_t pc; // Program pointer, point to the next instruction
#ifdef MLQ_SCHED
// Priority on execution (if supported), on-fly aka. changeable
// and this vale overwrites the default priority when it existed
uint32_t prio;
#endif
#ifdef CPU_TLB
struct memphy_struct *tlb;
#endif
#ifdef MM_PAGING
struct mm_struct *mm;
struct memphy_struct *mram;
struct memphy_struct **mswp;
struct memphy_struct *active_mswp;
#endif
struct page_table_t * page_table; // Page table
uint32_t bp; // Break pointer

};

#endif

13 changes: 13 additions & 0 deletions include/cpu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

#ifndef CPU_H
#define CPU_H

#include "common.h"

/* Execute an instruction of a process. Return 0
* if the instruction is executed successfully.
* Otherwise, return 1. */
int run(struct pcb_t * proc);

#endif

9 changes: 9 additions & 0 deletions include/loader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef LOADER_H
#define LOADER_H

#include "common.h"

struct pcb_t * load(const char * path);

#endif

32 changes: 32 additions & 0 deletions include/mem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef MEM_H
#define MEM_H

#include "common.h"

#define RAM_SIZE (1 << ADDRESS_SIZE)

/* Init related parameters, must be called before being used */
void init_mem(void);

/* Allocate [size] bytes for process [proc] and return its virtual address.
* If we cannot allocate new memory region for this process, return 0 */
addr_t alloc_mem(uint32_t size, struct pcb_t * proc);

/* Free a memory block having the first byte at [address] used by
* process [proc]. Return 0 if [address] is valid. Otherwise, return 1 */
int free_mem(addr_t address, struct pcb_t * proc);

/* Read 1 byte memory pointed by [address] used by process [proc] and
* save it to [data].
* If the given [address] is valid, return 0. Otherwise, return 1 */
int read_mem(addr_t address, struct pcb_t * proc, BYTE * data);

/* Write [data] to 1 byte on the memory pointed by [address] of process
* [proc]. If given [address] is valid, return 0. Otherwise, return 1 */
int write_mem(addr_t address, struct pcb_t * proc, BYTE data);

void dump(void);

#endif


Loading