Cleanup and commenting source code

This commit is contained in:
Ali Mashtizadeh 2022-12-09 23:51:45 -05:00
parent 88cbddb3ad
commit f86e4ad966
11 changed files with 221 additions and 126 deletions

View File

@ -40,9 +40,9 @@ src_amd64 = [
src_common = [ src_common = [
"kern/copy.c", "kern/copy.c",
"kern/bufcache.c",
"kern/debug.c", "kern/debug.c",
"kern/disk.c", "kern/disk.c",
"kern/diskcache.c",
"kern/handle.c", "kern/handle.c",
"kern/ktime.c", "kern/ktime.c",
"kern/ktimer.c", "kern/ktimer.c",

View File

@ -17,7 +17,7 @@
#include <sys/thread.h> #include <sys/thread.h>
#include <sys/disk.h> #include <sys/disk.h>
#include <sys/diskcache.h> #include <sys/bufcache.h>
#include <sys/vfs.h> #include <sys/vfs.h>
#include <sys/elf64.h> #include <sys/elf64.h>
@ -163,7 +163,7 @@ void Machine_Init()
PS2_Init(); PS2_Init();
PCI_Init(); PCI_Init();
IDE_Init(); IDE_Init();
DiskCache_Init(); BufCache_Init();
Disk *root = Disk_GetByID(0, 0); Disk *root = Disk_GetByID(0, 0);
if (!root) if (!root)

View File

@ -57,8 +57,17 @@ Console_Getc()
Spinlock_Unlock(&consoles.keyLock); Spinlock_Unlock(&consoles.keyLock);
// Support serial debugging if interrupts are disabled // Support serial debugging if interrupts are disabled
if (Serial_HasData()) if (Serial_HasData()) {
return Serial_Getc(); char key = Serial_Getc();
switch (key) {
case '\r':
return '\n';
case 0x7f:
return '\b';
default:
return key;
}
}
} }
} }
@ -148,7 +157,7 @@ Console_Read(Handle *handle, void *buf, uint64_t off, uint64_t len)
{ {
char c = Console_Getc(); char c = Console_Getc();
Console_Putc(c); Console_Putc(c);
CopyOut(&c, b+i, 1); Copy_Out(&c, b+i, 1);
} }
return len; return len;
@ -164,7 +173,7 @@ Console_Write(Handle *handle, void *buf, uint64_t off, uint64_t len)
while (len > nbytes) { while (len > nbytes) {
uint64_t chunksz = len > 512 ? 512 : len; uint64_t chunksz = len > 512 ? 512 : len;
CopyIn(b + nbytes, &kbuf, chunksz); Copy_In(b + nbytes, &kbuf, chunksz);
nbytes += chunksz; nbytes += chunksz;
for (i = 0; i < chunksz; i++) for (i = 0; i < chunksz; i++)

View File

@ -8,7 +8,7 @@
#include <sys/kmem.h> #include <sys/kmem.h>
#include <sys/spinlock.h> #include <sys/spinlock.h>
#include <sys/disk.h> #include <sys/disk.h>
#include <sys/diskcache.h> #include <sys/bufcache.h>
#include <sys/vfs.h> #include <sys/vfs.h>
#include <sys/dirent.h> #include <sys/dirent.h>
#include <sys/thread.h> #include <sys/thread.h>
@ -43,7 +43,7 @@ O2FS_Mount(Disk *disk)
{ {
int status; int status;
VFS *fs = VFS_Alloc(); VFS *fs = VFS_Alloc();
DiskCacheEntry *entry; BufCacheEntry *entry;
SuperBlock *sb; SuperBlock *sb;
ASSERT(sizeof(BDirEntry) == 512); ASSERT(sizeof(BDirEntry) == 512);
@ -51,7 +51,7 @@ O2FS_Mount(Disk *disk)
if (!fs) if (!fs)
return NULL; return NULL;
status = DiskCache_Read(disk, 0, &entry); status = BufCache_Read(disk, 0, &entry);
if (status < 0) { if (status < 0) {
Alert(o2fs, "O2FS: Disk cache read failed\n"); Alert(o2fs, "O2FS: Disk cache read failed\n");
return NULL; return NULL;
@ -61,13 +61,13 @@ O2FS_Mount(Disk *disk)
sb = entry->buffer; sb = entry->buffer;
if (memcmp(sb->magic, SUPERBLOCK_MAGIC, 8) != 0) { if (memcmp(sb->magic, SUPERBLOCK_MAGIC, 8) != 0) {
Alert(o2fs, "O2FS: Invalid file system\n"); Alert(o2fs, "O2FS: Invalid file system\n");
DiskCache_Release(entry); BufCache_Release(entry);
return NULL; return NULL;
} }
if (sb->versionMajor != O2FS_VERSION_MAJOR || if (sb->versionMajor != O2FS_VERSION_MAJOR ||
sb->versionMinor != O2FS_VERSION_MINOR) { sb->versionMinor != O2FS_VERSION_MINOR) {
Alert(o2fs, "O2FS: Unsupported file system version\n"); Alert(o2fs, "O2FS: Unsupported file system version\n");
DiskCache_Release(entry); BufCache_Release(entry);
return NULL; return NULL;
} }
@ -87,7 +87,7 @@ O2FS_Mount(Disk *disk)
status = O2FS_GetRoot(fs, &fs->root); status = O2FS_GetRoot(fs, &fs->root);
if (status < 0) { if (status < 0) {
Alert(o2fs, "O2FS: Mount failed"); Alert(o2fs, "O2FS: Mount failed");
DiskCache_Release(entry); BufCache_Release(entry);
return NULL; return NULL;
} }
@ -107,9 +107,9 @@ O2FSLoadVNode(VFS *fs, ObjID *objid)
int status; int status;
VNode *vn; VNode *vn;
BNode *bn; BNode *bn;
DiskCacheEntry *entry; BufCacheEntry *entry;
status = DiskCache_Read(fs->disk, objid->offset, &entry); status = BufCache_Read(fs->disk, objid->offset, &entry);
if (status < 0) { if (status < 0) {
Alert(o2fs, "O2FS: disk read error\n"); Alert(o2fs, "O2FS: disk read error\n");
return NULL; return NULL;
@ -118,13 +118,13 @@ O2FSLoadVNode(VFS *fs, ObjID *objid)
bn = entry->buffer; bn = entry->buffer;
if (memcmp(&bn->magic, BNODE_MAGIC, 8) != 0) { if (memcmp(&bn->magic, BNODE_MAGIC, 8) != 0) {
Alert(o2fs, "O2FS: bad BNode magic\n"); Alert(o2fs, "O2FS: bad BNode magic\n");
DiskCache_Release(entry); BufCache_Release(entry);
return NULL; return NULL;
} }
if (bn->versionMajor != O2FS_VERSION_MAJOR || if (bn->versionMajor != O2FS_VERSION_MAJOR ||
bn->versionMinor != O2FS_VERSION_MINOR) { bn->versionMinor != O2FS_VERSION_MINOR) {
Alert(o2fs, "O2FS: unsupported BNode version\n"); Alert(o2fs, "O2FS: unsupported BNode version\n");
DiskCache_Release(entry); BufCache_Release(entry);
return NULL; return NULL;
} }
@ -154,7 +154,7 @@ O2FSReleaseVNode(VNode *vn)
{ {
vn->refCount--; vn->refCount--;
if (vn->refCount == 0) { if (vn->refCount == 0) {
DiskCache_Release(vn->fsptr); BufCache_Release(vn->fsptr);
Spinlock_Destroy(&vn->lock); Spinlock_Destroy(&vn->lock);
VNode_Free(vn); VNode_Free(vn);
} }
@ -165,7 +165,7 @@ O2FS_GetRoot(VFS *fs, VNode **dn)
{ {
int status; int status;
VNode *vn; VNode *vn;
DiskCacheEntry *entry; BufCacheEntry *entry;
BNode *bn; BNode *bn;
if (fs->root) { if (fs->root) {
@ -174,7 +174,7 @@ O2FS_GetRoot(VFS *fs, VNode **dn)
return 0; return 0;
} }
status = DiskCache_Read(fs->disk, fs->fsval, &entry); status = BufCache_Read(fs->disk, fs->fsval, &entry);
if (status < 0) { if (status < 0) {
Alert(o2fs, "O2FS: disk read error\n"); Alert(o2fs, "O2FS: disk read error\n");
return status; return status;
@ -183,13 +183,13 @@ O2FS_GetRoot(VFS *fs, VNode **dn)
bn = entry->buffer; bn = entry->buffer;
if (memcmp(&bn->magic, BNODE_MAGIC, 8) != 0) { if (memcmp(&bn->magic, BNODE_MAGIC, 8) != 0) {
Alert(o2fs, "O2FS: bad BNode magic\n"); Alert(o2fs, "O2FS: bad BNode magic\n");
DiskCache_Release(entry); BufCache_Release(entry);
return -1; return -1;
} }
if (bn->versionMajor != O2FS_VERSION_MAJOR || if (bn->versionMajor != O2FS_VERSION_MAJOR ||
bn->versionMinor != O2FS_VERSION_MINOR) { bn->versionMinor != O2FS_VERSION_MINOR) {
Alert(o2fs, "O2FS: unsupported BNode version\n"); Alert(o2fs, "O2FS: unsupported BNode version\n");
DiskCache_Release(entry); BufCache_Release(entry);
return -1; return -1;
} }
@ -217,9 +217,9 @@ O2FS_Lookup(VNode *dn, VNode **fn, const char *name)
{ {
int status; int status;
VFS *vfs = dn->vfs; VFS *vfs = dn->vfs;
DiskCacheEntry *sbEntry = (DiskCacheEntry *)vfs->fsptr; BufCacheEntry *sbEntry = (BufCacheEntry *)vfs->fsptr;
SuperBlock *sb = sbEntry->buffer; SuperBlock *sb = sbEntry->buffer;
DiskCacheEntry *dirEntry = (DiskCacheEntry *)dn->fsptr; BufCacheEntry *dirEntry = (BufCacheEntry *)dn->fsptr;
BNode *dirBN = dirEntry->buffer; BNode *dirBN = dirEntry->buffer;
uint64_t blocks = (dirBN->size + sb->blockSize - 1) / sb->blockSize; uint64_t blocks = (dirBN->size + sb->blockSize - 1) / sb->blockSize;
uint64_t b; uint64_t b;
@ -230,9 +230,9 @@ O2FS_Lookup(VNode *dn, VNode **fn, const char *name)
// Read block // Read block
int e; int e;
int entryPerBlock = sb->blockSize / sizeof(BDirEntry); int entryPerBlock = sb->blockSize / sizeof(BDirEntry);
DiskCacheEntry *entry; BufCacheEntry *entry;
BDirEntry *dir; BDirEntry *dir;
status = DiskCache_Read(dn->disk, dirBN->direct[b].offset, &entry); status = BufCache_Read(dn->disk, dirBN->direct[b].offset, &entry);
if (status < 0) if (status < 0)
return status; return status;
@ -248,7 +248,7 @@ O2FS_Lookup(VNode *dn, VNode **fn, const char *name)
} }
} }
DiskCache_Release(entry); BufCache_Release(entry);
} }
return -1; return -1;
@ -270,9 +270,9 @@ int
O2FS_Stat(VNode *fn, struct stat *statinfo) O2FS_Stat(VNode *fn, struct stat *statinfo)
{ {
VFS *vfs = fn->vfs; VFS *vfs = fn->vfs;
DiskCacheEntry *sbEntry = (DiskCacheEntry *)vfs->fsptr; BufCacheEntry *sbEntry = (BufCacheEntry *)vfs->fsptr;
SuperBlock *sb = sbEntry->buffer; SuperBlock *sb = sbEntry->buffer;
DiskCacheEntry *fileEntry = (DiskCacheEntry *)fn->fsptr; BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr;
BNode *fileBN = fileEntry->buffer; BNode *fileBN = fileEntry->buffer;
statinfo->st_size = fileBN->size; statinfo->st_size = fileBN->size;
@ -288,9 +288,9 @@ O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
{ {
int status; int status;
VFS *vfs = fn->vfs; VFS *vfs = fn->vfs;
DiskCacheEntry *sbEntry = (DiskCacheEntry *)vfs->fsptr; BufCacheEntry *sbEntry = (BufCacheEntry *)vfs->fsptr;
SuperBlock *sb = sbEntry->buffer; SuperBlock *sb = sbEntry->buffer;
DiskCacheEntry *fileEntry = (DiskCacheEntry *)fn->fsptr; BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr;
BNode *fileBN = fileEntry->buffer; BNode *fileBN = fileEntry->buffer;
uint64_t blocks = (fileBN->size + sb->blockSize - 1) / sb->blockSize; uint64_t blocks = (fileBN->size + sb->blockSize - 1) / sb->blockSize;
uint64_t readBytes = 0; uint64_t readBytes = 0;
@ -309,7 +309,7 @@ O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
uint64_t b = off / sb->blockSize; uint64_t b = off / sb->blockSize;
uint64_t bOff = off % sb->blockSize; uint64_t bOff = off % sb->blockSize;
uint64_t bLen; uint64_t bLen;
DiskCacheEntry *entry; BufCacheEntry *entry;
if (bOff + len > sb->blockSize) { if (bOff + len > sb->blockSize) {
bLen = sb->blockSize - bOff; bLen = sb->blockSize - bOff;
@ -317,12 +317,12 @@ O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
bLen = len; bLen = len;
} }
status = DiskCache_Read(fn->disk, fileBN->direct[b].offset, &entry); status = BufCache_Read(fn->disk, fileBN->direct[b].offset, &entry);
if (status < 0) if (status < 0)
return status; return status;
memcpy(buf, entry->buffer + bOff, bLen); memcpy(buf, entry->buffer + bOff, bLen);
DiskCache_Release(entry); BufCache_Release(entry);
readBytes += bLen; readBytes += bLen;
buf += bLen; buf += bLen;
@ -348,7 +348,7 @@ O2FS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off)
{ {
int count = 0; int count = 0;
int status; int status;
DiskCacheEntry *fileEntry = (DiskCacheEntry *)fn->fsptr; BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr;
BNode *fileBN = fileEntry->buffer; BNode *fileBN = fileEntry->buffer;
BDirEntry dirEntry; BDirEntry dirEntry;
struct dirent de; struct dirent de;
@ -370,7 +370,7 @@ O2FS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off)
// XXX: Validation and fill in all fields // XXX: Validation and fill in all fields
strcpy(de.d_name, (char *)dirEntry.name); strcpy(de.d_name, (char *)dirEntry.name);
status = CopyOut(&de, (uintptr_t)buf, sizeof(de)); status = Copy_Out(&de, (uintptr_t)buf, sizeof(de));
if (status != 0) if (status != 0)
return status; return status;

23
sys/include/bufcache.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef __SYS_BUFCACHE_H__
#define __SYS_BUFCACHE_H__
#include <sys/queue.h>
typedef struct BufCacheEntry {
Disk *disk;
uint64_t diskOffset;
uint64_t refCount;
void *buffer;
TAILQ_ENTRY(BufCacheEntry) htEntry;
TAILQ_ENTRY(BufCacheEntry) lruEntry;
} BufCacheEntry;
void BufCache_Init();
int BufCache_Alloc(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry);
void BufCache_Release(BufCacheEntry *entry);
int BufCache_Read(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry);
int BufCache_Write(BufCacheEntry *entry);
#endif /* __SYS_BUFCACHE_H__ */

View File

@ -1,23 +0,0 @@
#ifndef __SYS_DISKCACHE_H__
#define __SYS_DISKCACHE_H__
#include <sys/queue.h>
typedef struct DiskCacheEntry {
Disk *disk;
uint64_t diskOffset;
uint64_t refCount;
void *buffer;
TAILQ_ENTRY(DiskCacheEntry) htEntry;
TAILQ_ENTRY(DiskCacheEntry) lruEntry;
} DiskCacheEntry;
void DiskCache_Init();
int DiskCache_Alloc(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry);
void DiskCache_Release(DiskCacheEntry *entry);
int DiskCache_Read(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry);
int DiskCache_Write(DiskCacheEntry *entry);
#endif /* __SYS_DISKCACHE_H__ */

View File

@ -28,6 +28,9 @@
#define SYSCALL_STAT 0x1D #define SYSCALL_STAT 0x1D
#define SYSCALL_READDIR 0x1E #define SYSCALL_READDIR 0x1E
// IPC
#define SYSCALL_PIPE 0x20
// Threading // Threading
#define SYSCALL_THREADCREATE 0x30 #define SYSCALL_THREADCREATE 0x30
#define SYSCALL_GETTID 0x31 #define SYSCALL_GETTID 0x31

View File

@ -123,11 +123,11 @@ uint64_t Handle_Add(Process *proc, Handle *handle);
void Handle_Remove(Process *proc, Handle *handle); void Handle_Remove(Process *proc, Handle *handle);
Handle *Handle_Lookup(Process *proc, uint64_t fd); Handle *Handle_Lookup(Process *proc, uint64_t fd);
// CopyIn/CopyOut Functions // Copy_In/Copy_Out Functions
int CopyIn(uintptr_t fromuser, void *tokernel, uintptr_t len); int Copy_In(uintptr_t fromuser, void *tokernel, uintptr_t len);
int CopyOut(void *fromkernel, uintptr_t touser, uintptr_t len); int Copy_Out(void *fromkernel, uintptr_t touser, uintptr_t len);
int CopyStrIn(uintptr_t fromuser, void *tokernel, uintptr_t len); int Copy_StrIn(uintptr_t fromuser, void *tokernel, uintptr_t len);
int CopyStrOut(void *fromkernel, uintptr_t touser, uintptr_t len); int Copy_StrOut(void *fromkernel, uintptr_t touser, uintptr_t len);
#endif /* __SYS_THREAD_H__ */ #endif /* __SYS_THREAD_H__ */

View File

@ -1,3 +1,7 @@
/*
* Copyright (c) 2006-2022 Ali Mashtizadeh
* All rights reserved.
*/
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@ -8,55 +12,55 @@
#include <sys/kmem.h> #include <sys/kmem.h>
#include <sys/spinlock.h> #include <sys/spinlock.h>
#include <sys/disk.h> #include <sys/disk.h>
#include <sys/diskcache.h> #include <sys/bufcache.h>
Spinlock cacheLock; Spinlock cacheLock;
XMem *diskBuf; XMem *diskBuf;
static TAILQ_HEAD(CacheHashTable, DiskCacheEntry) *hashTable; static TAILQ_HEAD(CacheHashTable, BufCacheEntry) *hashTable;
static TAILQ_HEAD(LRUCacheList, DiskCacheEntry) lruList; static TAILQ_HEAD(LRUCacheList, BufCacheEntry) lruList;
static uint64_t cacheHit; static uint64_t cacheHit;
static uint64_t cacheMiss; static uint64_t cacheMiss;
static uint64_t cacheAlloc; static uint64_t cacheAlloc;
static Slab cacheEntrySlab; static Slab cacheEntrySlab;
DEFINE_SLAB(DiskCacheEntry, &cacheEntrySlab); DEFINE_SLAB(BufCacheEntry, &cacheEntrySlab);
#define CACHESIZE (16*1024*1024) #define CACHESIZE (16*1024*1024)
#define HASHTABLEENTRIES 128 #define HASHTABLEENTRIES 128
#define BLOCKSIZE (16*1024) #define BLOCKSIZE (16*1024)
void void
DiskCache_Init() BufCache_Init()
{ {
int i; int i;
Spinlock_Init(&cacheLock, "DiskCache Lock", SPINLOCK_TYPE_NORMAL); Spinlock_Init(&cacheLock, "BufCache Lock", SPINLOCK_TYPE_NORMAL);
diskBuf = XMem_New(); diskBuf = XMem_New();
if (!diskBuf) if (!diskBuf)
Panic("DiskCache: Cannot create XMem region\n"); Panic("BufCache: Cannot create XMem region\n");
if (!XMem_Allocate(diskBuf, CACHESIZE)) if (!XMem_Allocate(diskBuf, CACHESIZE))
Panic("DiskCache: Cannot back XMem region\n"); Panic("BufCache: Cannot back XMem region\n");
TAILQ_INIT(&lruList); TAILQ_INIT(&lruList);
hashTable = PAlloc_AllocPage(); hashTable = PAlloc_AllocPage();
if (!hashTable) if (!hashTable)
Panic("DiskCache: Cannot allocate hash table\n"); Panic("BufCache: Cannot allocate hash table\n");
for (i = 0; i < HASHTABLEENTRIES; i++) { for (i = 0; i < HASHTABLEENTRIES; i++) {
TAILQ_INIT(&hashTable[i]); TAILQ_INIT(&hashTable[i]);
} }
Slab_Init(&cacheEntrySlab, "DiskCacheEntry Slab", sizeof(DiskCacheEntry), 16); Slab_Init(&cacheEntrySlab, "BufCacheEntry Slab", sizeof(BufCacheEntry), 16);
// Initialize cache // Initialize cache
uintptr_t bufBase = XMem_GetBase(diskBuf); uintptr_t bufBase = XMem_GetBase(diskBuf);
for (i = 0; i < CACHESIZE/BLOCKSIZE; i++) { for (i = 0; i < CACHESIZE/BLOCKSIZE; i++) {
DiskCacheEntry *e = DiskCacheEntry_Alloc(); BufCacheEntry *e = BufCacheEntry_Alloc();
if (!e) { if (!e) {
Panic("DiskCache: Cannot allocate cache entry\n"); Panic("BufCache: Cannot allocate cache entry\n");
} }
memset(e, 0, sizeof(*e)); memset(e, 0, sizeof(*e));
@ -71,10 +75,10 @@ DiskCache_Init()
} }
static int static int
DiskCacheLookup(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) BufCacheLookup(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
{ {
struct CacheHashTable *table; struct CacheHashTable *table;
DiskCacheEntry *e; BufCacheEntry *e;
// Check hash table // Check hash table
table = &hashTable[diskOffset % HASHTABLEENTRIES]; table = &hashTable[diskOffset % HASHTABLEENTRIES];
@ -94,15 +98,15 @@ DiskCacheLookup(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry)
} }
static int static int
DiskCacheAlloc(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) BufCacheAlloc(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
{ {
struct CacheHashTable *table; struct CacheHashTable *table;
DiskCacheEntry *e; BufCacheEntry *e;
// Allocate from LRU list // Allocate from LRU list
e = TAILQ_FIRST(&lruList); e = TAILQ_FIRST(&lruList);
if (e == NULL) { if (e == NULL) {
kprintf("DiskCache: No space left!\n"); kprintf("BufCache: No space left!\n");
return -1; return -1;
} }
TAILQ_REMOVE(&lruList, e, lruEntry); TAILQ_REMOVE(&lruList, e, lruEntry);
@ -126,16 +130,24 @@ DiskCacheAlloc(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry)
return 0; return 0;
} }
/*
* BufCache_Alloc --
*
* Allocate a buffer cache entry.
*
* Results:
* Returns 0 if successful and sets the entry, otherwise returns an error code.
*/
int int
DiskCache_Alloc(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) BufCache_Alloc(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
{ {
int status; int status;
Spinlock_Lock(&cacheLock); Spinlock_Lock(&cacheLock);
status = DiskCacheLookup(disk, diskOffset, entry); status = BufCacheLookup(disk, diskOffset, entry);
if (*entry == NULL) { if (*entry == NULL) {
status = DiskCacheAlloc(disk, diskOffset, entry); status = BufCacheAlloc(disk, diskOffset, entry);
} }
cacheAlloc++; cacheAlloc++;
@ -145,39 +157,56 @@ DiskCache_Alloc(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry)
return status; return status;
} }
/*
* BufCache_Release --
*
* Release a buffer cache entry. If no other references are held the
* buffer cache entry is placed on the LRU list.
*
* Results:
* None.
*/
void void
DiskCache_Release(DiskCacheEntry *entry) BufCache_Release(BufCacheEntry *entry)
{ {
Spinlock_Lock(&cacheLock); Spinlock_Lock(&cacheLock);
entry->refCount--; entry->refCount--;
if (entry->refCount == 0) { if (entry->refCount == 0) {
TAILQ_INSERT_TAIL(&lruList, entry, lruEntry); TAILQ_INSERT_TAIL(&lruList, entry, lruEntry);
} }
Spinlock_Unlock(&cacheLock); Spinlock_Unlock(&cacheLock);
} }
/*
* BufCache_Read --
*
* Read block from disk into the buffer cache.
*
* Results:
* Returns 0 if successful, otherwise an error code is returned.
*/
int int
DiskCache_Read(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) BufCache_Read(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
{ {
int status; int status;
void *buf; void *buf;
SGArray sga; SGArray sga;
Spinlock_Lock(&cacheLock); Spinlock_Lock(&cacheLock);
status = DiskCacheLookup(disk, diskOffset, entry); status = BufCacheLookup(disk, diskOffset, entry);
if (*entry != NULL) { if (*entry != NULL) {
cacheHit++; cacheHit++;
Spinlock_Unlock(&cacheLock); Spinlock_Unlock(&cacheLock);
return status; return status;
} }
cacheMiss++; cacheMiss++;
status = DiskCacheAlloc(disk, diskOffset, entry); status = BufCacheAlloc(disk, diskOffset, entry);
if (status != 0) { if (status != 0) {
Spinlock_Unlock(&cacheLock); Spinlock_Unlock(&cacheLock);
return status; return status;
} }
buf = (*entry)->buffer; buf = (*entry)->buffer;
@ -194,8 +223,16 @@ DiskCache_Read(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry)
return status; return status;
} }
/*
* BufCache_Write --
*
* Write a buffer cache entry to disk.
*
* Results:
* Returns 0 if successful, otherwise an error code is returned.
*/
int int
DiskCache_Write(DiskCacheEntry *entry) BufCache_Write(BufCacheEntry *entry)
{ {
void *buf = entry->buffer; void *buf = entry->buffer;
SGArray sga; SGArray sga;
@ -207,12 +244,12 @@ DiskCache_Write(DiskCacheEntry *entry)
} }
static void static void
Debug_DiskCache(int argc, const char *argv[]) Debug_BufCache(int argc, const char *argv[])
{ {
kprintf("Hits: %lld\n", cacheHit); kprintf("Hits: %lld\n", cacheHit);
kprintf("Misses: %lld\n", cacheMiss); kprintf("Misses: %lld\n", cacheMiss);
kprintf("Allocations: %lld\n", cacheAlloc); kprintf("Allocations: %lld\n", cacheAlloc);
} }
REGISTER_DBGCMD(diskcache, "Display disk cache statistics", Debug_DiskCache); REGISTER_DBGCMD(diskcache, "Display disk cache statistics", Debug_BufCache);

View File

@ -1,4 +1,6 @@
/* /*
* Copyright (c) 2006-2022 Ali Mashtizadeh
* All rights reserved.
* Generic Copyin/Copyout routines * Generic Copyin/Copyout routines
*/ */
@ -13,84 +15,128 @@
extern int copy_unsafe(void *to_addr, void *from_addr, uintptr_t len); extern int copy_unsafe(void *to_addr, void *from_addr, uintptr_t len);
extern int copystr_unsafe(void *to_addr, void *from_addr, uintptr_t len); extern int copystr_unsafe(void *to_addr, void *from_addr, uintptr_t len);
/*
* Copy_In --
* Safely copy memory from userspace. Prevents userspace pointers from
* reading kernel memory.
*
* Results:
* Returns EFAULT if the address is invalid or causes a fault.
*
* Side effects:
* Kernel page fault may have occurred.
*/
int int
CopyIn(uintptr_t fromuser, void *tokernel, uintptr_t len) Copy_In(uintptr_t fromuser, void *tokernel, uintptr_t len)
{ {
if (len == 0) if (len == 0)
return 0; return 0;
// Kernel space // Kernel space
if (fromuser >= MEM_USERSPACE_TOP) { if (fromuser >= MEM_USERSPACE_TOP) {
kprintf("CopyIn: address exceeds userspace top\n"); kprintf("Copy_In: address exceeds userspace top\n");
return EFAULT; return EFAULT;
} }
// Wrap around // Wrap around
if (len > (MEM_USERSPACE_TOP - fromuser)) { if (len > (MEM_USERSPACE_TOP - fromuser)) {
kprintf("CopyIn: length exceeds userspace top\n"); kprintf("Copy_In: length exceeds userspace top\n");
return EFAULT; return EFAULT;
} }
return copy_unsafe(tokernel, (void *)fromuser, len); return copy_unsafe(tokernel, (void *)fromuser, len);
} }
/*
* Copy_Out --
* Safely copy memory to userspace. Prevents userspace pointers from
* writing kernel memory.
*
* Results:
* Returns EFAULT if the address is invalid or causes a fault.
*
* Side effects:
* Kernel page fault may have occurred.
*/
int int
CopyOut(void *fromkernel, uintptr_t touser, uintptr_t len) Copy_Out(void *fromkernel, uintptr_t touser, uintptr_t len)
{ {
if (len == 0) if (len == 0)
return 0; return 0;
// Kernel space // Kernel space
if (touser >= MEM_USERSPACE_TOP) { if (touser >= MEM_USERSPACE_TOP) {
kprintf("CopyOut: address exceeds userspace top\n"); kprintf("Copy_Out: address exceeds userspace top\n");
return EFAULT; return EFAULT;
} }
// Wrap around // Wrap around
if (len > (MEM_USERSPACE_TOP - touser)) { if (len > (MEM_USERSPACE_TOP - touser)) {
kprintf("CopyOut: length exceeds userspace top\n"); kprintf("Copy_Out: length exceeds userspace top\n");
return EFAULT; return EFAULT;
} }
return copy_unsafe((void *)touser, fromkernel, len); return copy_unsafe((void *)touser, fromkernel, len);
} }
/*
* Copy_StrIn --
* Safely copy a string from userspace. Prevents userspace pointers from
* reading kernel memory.
*
* Results:
* Returns EFAULT if the address is invalid or causes a fault.
*
* Side effects:
* Kernel page fault may have occurred.
*/
int int
CopyStrIn(uintptr_t fromuser, void *tokernel, uintptr_t len) Copy_StrIn(uintptr_t fromuser, void *tokernel, uintptr_t len)
{ {
if (len == 0) if (len == 0)
return 0; return 0;
// Kernel space // Kernel space
if (fromuser >= MEM_USERSPACE_TOP) { if (fromuser >= MEM_USERSPACE_TOP) {
kprintf("CopyStrIn: address exceeds userspace top\n"); kprintf("Copy_StrIn: address exceeds userspace top\n");
return EFAULT; return EFAULT;
} }
// Wrap around // Wrap around
if (len > (MEM_USERSPACE_TOP - fromuser)) { if (len > (MEM_USERSPACE_TOP - fromuser)) {
kprintf("CopyStrIn: length exceeds userspace top\n"); kprintf("Copy_StrIn: length exceeds userspace top\n");
return EFAULT; return EFAULT;
} }
return copystr_unsafe(tokernel, (void *)fromuser, len); return copystr_unsafe(tokernel, (void *)fromuser, len);
} }
/*
* Copy_StrOut --
* Safely copy a string to userspace. Prevents userspace pointers from
* writing kernel memory.
*
* Results:
* Returns EFAULT if the address is invalid or causes a fault.
*
* Side effects:
* Kernel page fault may have occurred.
*/
int int
CopyStrOut(void *fromkernel, uintptr_t touser, uintptr_t len) Copy_StrOut(void *fromkernel, uintptr_t touser, uintptr_t len)
{ {
if (len == 0) if (len == 0)
return 0; return 0;
// Kernel space // Kernel space
if (touser >= MEM_USERSPACE_TOP) { if (touser >= MEM_USERSPACE_TOP) {
kprintf("CopyStrOut: address exceeds userspace top\n"); kprintf("Copy_StrOut: address exceeds userspace top\n");
return EFAULT; return EFAULT;
} }
// Wrap around // Wrap around
if (len > (MEM_USERSPACE_TOP - touser)) { if (len > (MEM_USERSPACE_TOP - touser)) {
kprintf("CopyStrOut: length exceeds userspace top\n"); kprintf("Copy_StrOut: length exceeds userspace top\n");
return EFAULT; return EFAULT;
} }

View File

@ -71,7 +71,7 @@ Syscall_Spawn(uint64_t user_path)
Thread *thr; Thread *thr;
Thread *cur; Thread *cur;
status = CopyStrIn(user_path, &path, sizeof(path)); status = Copy_StrIn(user_path, &path, sizeof(path));
if (status != 0) if (status != 0)
return SYSCALL_PACK(status, 0); return SYSCALL_PACK(status, 0);
@ -246,7 +246,7 @@ Syscall_Open(uint64_t user_path, uint64_t flags)
int status; int status;
char path[256]; char path[256];
status = CopyStrIn(user_path, &path, sizeof(path)); status = Copy_StrIn(user_path, &path, sizeof(path));
if (status != 0) { if (status != 0) {
Thread_Release(cur); Thread_Release(cur);
return status; return status;
@ -301,7 +301,7 @@ Syscall_Stat(uint64_t user_path, uint64_t user_stat)
char path[256]; char path[256];
struct stat sb; struct stat sb;
status = CopyStrIn(user_path, &path, sizeof(path)); status = Copy_StrIn(user_path, &path, sizeof(path));
if (status != 0) { if (status != 0) {
return status; return status;
} }
@ -312,7 +312,7 @@ Syscall_Stat(uint64_t user_path, uint64_t user_stat)
return status; return status;
} }
status = CopyOut(&sb, user_stat, sizeof(struct stat)); status = Copy_Out(&sb, user_stat, sizeof(struct stat));
if (status != 0) { if (status != 0) {
return status; return status;
} }
@ -333,7 +333,7 @@ Syscall_ReadDir(uint64_t fd, char *user_buf, size_t len, uintptr_t user_off)
return -EBADF; return -EBADF;
} }
status = CopyIn(user_off, &offset, sizeof(offset)); status = Copy_In(user_off, &offset, sizeof(offset));
if (status != 0) { if (status != 0) {
Thread_Release(cur); Thread_Release(cur);
return status; return status;
@ -350,7 +350,7 @@ Syscall_ReadDir(uint64_t fd, char *user_buf, size_t len, uintptr_t user_off)
return rstatus; return rstatus;
} }
status = CopyOut(&offset, user_off, sizeof(offset)); status = Copy_Out(&offset, user_off, sizeof(offset));
if (status != 0) { if (status != 0) {
Thread_Release(cur); Thread_Release(cur);
return status; return status;
@ -480,7 +480,7 @@ Syscall_NICStat(uint64_t nicNo, uint64_t user_stat)
return ENOENT; return ENOENT;
} }
status = CopyOut(nic, user_stat, sizeof(NIC)); status = Copy_Out(nic, user_stat, sizeof(NIC));
if (status != 0) { if (status != 0) {
return status; return status;
} }
@ -495,7 +495,7 @@ Syscall_NICSend(uint64_t nicNo, uint64_t user_mbuf)
NIC *nic; NIC *nic;
MBuf mbuf; MBuf mbuf;
status = CopyIn(user_mbuf, &mbuf, sizeof(mbuf)); status = Copy_In(user_mbuf, &mbuf, sizeof(mbuf));
if (status != 0) { if (status != 0) {
return SYSCALL_PACK(status, 0); return SYSCALL_PACK(status, 0);
} }
@ -519,7 +519,7 @@ Syscall_NICRecv(uint64_t nicNo, uint64_t user_mbuf)
NIC *nic; NIC *nic;
MBuf mbuf; MBuf mbuf;
status = CopyIn(user_mbuf, &mbuf, sizeof(mbuf)); status = Copy_In(user_mbuf, &mbuf, sizeof(mbuf));
if (status != 0) { if (status != 0) {
return SYSCALL_PACK(status, 0); return SYSCALL_PACK(status, 0);
} }
@ -542,7 +542,7 @@ Syscall_SysCtl(uint64_t user_node, uint64_t user_oldval, uint64_t user_newval)
uint64_t status; uint64_t status;
char node[64]; char node[64];
status = CopyStrIn(user_node, &node, sizeof(node)); status = Copy_StrIn(user_node, &node, sizeof(node));
if (status != 0) { if (status != 0) {
return status; return status;
} }
@ -555,17 +555,17 @@ Syscall_SysCtl(uint64_t user_node, uint64_t user_oldval, uint64_t user_newval)
switch (scType) { switch (scType) {
case SYSCTL_TYPE_STR: { case SYSCTL_TYPE_STR: {
SysCtlString *scStr = SysCtl_GetObject(node); SysCtlString *scStr = SysCtl_GetObject(node);
status = CopyOut(scStr, user_oldval, sizeof(*scStr)); status = Copy_Out(scStr, user_oldval, sizeof(*scStr));
break; break;
} }
case SYSCTL_TYPE_INT: { case SYSCTL_TYPE_INT: {
SysCtlInt *scInt = SysCtl_GetObject(node); SysCtlInt *scInt = SysCtl_GetObject(node);
status = CopyOut(scInt, user_oldval, sizeof(*scInt)); status = Copy_Out(scInt, user_oldval, sizeof(*scInt));
break; break;
} }
case SYSCTL_TYPE_BOOL: { case SYSCTL_TYPE_BOOL: {
SysCtlBool *scBool = SysCtl_GetObject(node); SysCtlBool *scBool = SysCtl_GetObject(node);
status = CopyOut(scBool, user_oldval, sizeof(scBool)); status = Copy_Out(scBool, user_oldval, sizeof(scBool));
break; break;
} }
default: { default: {
@ -584,7 +584,7 @@ Syscall_SysCtl(uint64_t user_node, uint64_t user_oldval, uint64_t user_newval)
switch (scType) { switch (scType) {
case SYSCTL_TYPE_STR: { case SYSCTL_TYPE_STR: {
SysCtlString scStr; SysCtlString scStr;
status = CopyIn(user_newval, &scStr, sizeof(scStr)); status = Copy_In(user_newval, &scStr, sizeof(scStr));
if (status != 0) { if (status != 0) {
return status; return status;
} }
@ -593,7 +593,7 @@ Syscall_SysCtl(uint64_t user_node, uint64_t user_oldval, uint64_t user_newval)
} }
case SYSCTL_TYPE_INT: { case SYSCTL_TYPE_INT: {
SysCtlInt scInt; SysCtlInt scInt;
status = CopyIn(user_newval, &scInt, sizeof(scInt)); status = Copy_In(user_newval, &scInt, sizeof(scInt));
if (status != 0) { if (status != 0) {
return status; return status;
} }
@ -602,7 +602,7 @@ Syscall_SysCtl(uint64_t user_node, uint64_t user_oldval, uint64_t user_newval)
} }
case SYSCTL_TYPE_BOOL: { case SYSCTL_TYPE_BOOL: {
SysCtlBool scBool; SysCtlBool scBool;
status = CopyIn(user_newval, &scBool, sizeof(scBool)); status = Copy_In(user_newval, &scBool, sizeof(scBool));
if (status != 0) { if (status != 0) {
return status; return status;
} }