1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-06-30 23:06:44 +03:00
This commit is contained in:
Bas Wijnen 2009-05-20 22:07:56 +02:00
parent 616e81d7a8
commit 60ea570aaa
10 changed files with 367 additions and 98 deletions

View File

@ -8,7 +8,7 @@ LD = $(CROSS)ld
OBJCOPY = $(CROSS)objcopy
OBJDUMP = $(CROSS)objdump
kernel_sources = interrupts.cc panic.cc data.cc test.cc alloc.cc memory.cc
kernel_sources = interrupts.cc panic.cc data.cc test.cc alloc.cc memory.cc arch.cc invoke.cc schedule.cc
boot_sources = init.cc
BUILT_SOURCES = $(kernel_sources) $(boot_sources)
@ -22,7 +22,7 @@ PYPP = /usr/bin/pypp
uimage: all.raw Makefile
mkimage -A MIPS -O Linux -C none -a $(load) -e 0x$(shell /bin/sh -c '$(OBJDUMP) -t all | grep __start$$ | cut -b-8') -n "Shevek's kernel" -d $< $@ | sed -e 's/:/;/g'
arch.hh: mips.hh
arch.%: mips.%
ln -s $< $@ || true
%.o:%.cc Makefile kernel.hh arch.hh

111
alloc.ccp
View File

@ -1,6 +1,7 @@
#pypp 0
#include "kernel.hh"
// TODO: avoid recursion.
bool Memory::use ():
if used >= limit:
return false
@ -143,6 +144,34 @@ Thread *Memory::alloc_thread ():
ret->schedule_next = NULL
return ret
Message *Memory::alloc_message (Capability *source):
Message *ret = (Message *)search_free (sizeof (Message), (void **)&source->target->messages)
for unsigned i = 0; i < 4; ++i:
ret->capabilities[i] = NULL
ret->data[i] = 0
ret->protected_data = source->protected_data
return ret
Receiver *Memory::alloc_receiver ():
Receiver *ret = (Receiver *)search_free (sizeof (Receiver), (void **)&receivers)
ret->owner = NULL
ret->prev_owned = NULL
ret->next_owned = NULL
ret->capabilities = NULL
ret->messages = NULL
return ret
Capability *Memory::alloc_capability (Receiver *target, Capability **parent, unsigned protected_data):
Capability *ret = (Capability *)search_free (sizeof (Capability), (void **)&capabilities)
ret->target = target
ret->children = NULL
ret->sibling_prev = NULL
ret->sibling_next = parent ? *parent : NULL
if ret->sibling_next:
ret->sibling_next->sibling_prev = ret
ret->protected_data = protected_data
return ret
Memory *Memory::alloc_memory ():
Memory *ret = (Memory *)search_free (sizeof (Memory), (void **)&memories)
ret->parent = this
@ -164,7 +193,7 @@ void Memory::free_page (Page *page):
page->next->prev = page->prev
unuse ()
pfree (page->physical)
free_obj (this)
page->free_obj (this)
void Memory::free_thread (Thread *thread):
if thread->prev:
@ -173,8 +202,82 @@ void Memory::free_thread (Thread *thread):
threads = thread->next
if thread->next:
thread->next->prev = thread->prev
// TODO: unschedule
free_obj (this)
// Unschedule.
if thread->schedule_prev:
thread->schedule_prev->schedule_next = thread->schedule_next
else if first_scheduled == thread:
first_scheduled = thread->schedule_next
if thread->schedule_next:
thread->schedule_next->schedule_prev = thread->schedule_prev
thread->free_obj (this)
void Memory::free_message (Message *message):
for unsigned i = 0; i < 4; ++i:
free_capability (message->capabilities[i])
message->free_obj (this)
void Memory::free_receiver (Receiver *receiver):
if receiver->prev_owned:
receiver->prev_owned->next_owned = receiver->next_owned
else:
receiver->owner->receivers = receiver->next_owned
if receiver->next_owned:
receiver->next_owned->prev_owned = receiver->prev_owned
while receiver->capabilities:
receiver->capabilities->invalidate ()
while receiver->messages:
free_message (receiver->messages)
receiver->free_obj (this)
void Memory::free_capability (Capability *capability):
if capability->sibling_prev:
capability->sibling_prev->sibling_next = capability->sibling_next
else:
capability->target->capabilities = capability->sibling_next
if capability->sibling_next:
capability->sibling_next->sibling_prev = capability->sibling_prev
// The sibling_prev link is used here to point to the parent.
// This method is used to avoid recursion.
capability->sibling_prev = NULL
Capability *c = capability
while c->children:
c->children->sibling_prev = c
c = c->children
while c:
Capability *next = c->sibling_next
if !next:
next = c->sibling_prev
if next:
next->sibling_prev = c->sibling_prev
c->free_obj (this)
c = next
void Capability::invalidate ():
if sibling_prev:
sibling_prev->sibling_next = sibling_next
else:
target->capabilities = sibling_next
if sibling_next:
sibling_next->sibling_prev = sibling_prev
// The sibling_prev link is used here to point to the parent.
// This method is used to avoid recursion.
sibling_prev = NULL
Capability *c = this
while c->children:
c->children->sibling_prev = c
c = c->children
while c:
Capability *next = c->sibling_next
if !next:
next = c->sibling_prev
if next:
next->sibling_prev = c->sibling_prev
c->target = NULL
c->children = NULL
c->sibling_prev = NULL
c->sibling_next = NULL
c->protected_data = 0
c = next
void Memory::free_memory (Memory *mem):
if mem->prev:
@ -190,4 +293,4 @@ void Memory::free_memory (Memory *mem):
while mem->memories:
free_memory (mem->memories)
Memory_arch_free (mem)
free_obj (this)
mem->free_obj (this)

View File

@ -72,13 +72,6 @@ addr_100:
.fill 0x180 - (. - addr_000)
addr_180:
// General exception
// TODO
li $a0, 0xaaff0000
la $t9, panic
jr $t9
nop
sw $ra, -0x188($zero)
bal save_regs
la $t9, exception

View File

@ -41,7 +41,7 @@ static void init_idle ():
idle_memory.memories = NULL
idle_memory.limit = 0
idle_memory.used = 0
idle_memory.arch.directory = (Page ***)0x80000000
idle_memory.arch.directory = (unsigned **)0x80000000
idle_memory.arch.asid = 0
// initialize idle_page
idle_page.prev_obj = NULL

View File

@ -1,23 +1,11 @@
#pypp 0
#include "kernel.hh"
// hi and lo cannot be saved in assemply due to space restrictions.
#define save_hilo(x) do { __asm__ volatile ("mfhi %0 ; mflo %1" : "=r"((x)->arch.hi), "=r"((x)->arch.lo)); } while (0)
/// A TLB miss has occurred. This should eventually move to entry.S.
Thread *tlb_refill (Thread *current, unsigned EntryHi):
save_hilo (current)
Page ***dir = current->address_space->arch.directory
if !dir:
panic (0x00000000, "no page directory for thread")
EntryHi >>= 12
Page **table = dir[EntryHi >> 10]
if !table:
panic (0x11111111, "no page table at requested address")
EntryHi &= (1 << 10) - 1
Page *page0 = table[EntryHi & ~1]
Page *page1 = table[EntryHi | 1]
if (!(EntryHi & 1) && !page0) || ((EntryHi & 1) && !page1):
Page *page0 = current->address_space->get_mapping (EntryHi & ~(1 << 12))
Page *page1 = current->address_space->get_mapping (EntryHi | (1 << 12))
if (!(EntryHi & (1 << 12)) && !page0) || ((EntryHi & (1 << 12)) && !page1):
panic (0x22222222, "no page mapped at requested address")
unsigned low0, low1
if page0:
@ -33,17 +21,98 @@ Thread *tlb_refill (Thread *current, unsigned EntryHi):
/// An interrupt which is not an exception has occurred.
Thread *interrupt (Thread *current):
save_hilo (current)
unsigned cause
__asm__ volatile ("mfc0 %0, $13" : "=r"(cause))
for unsigned i = 0; i < 8; ++i:
if cause & (1 << (i + 8)):
// TODO: Handle interrupt.
// Disable all interrupts which are not handled.
unsigned status
__asm__ volatile ("mfc0 %0, $12" : "=r"(status))
__asm__ volatile ("mfc0 %0, $13" : "=r"(cause))
status &= ~(cause & 0x0000ff00)
__asm__ volatile ("mtc0 %0, $12" :: "r"(status))
return current
/// A general exception has occurred.
Thread *exception (Thread *current):
save_hilo (current)
panic (0xdeadbeaf, "exception")
unsigned cause
__asm__ volatile ("mfc0 %0, $13" : "=r"(cause))
switch (cause >> 2) & 0x1f:
case 0:
// Interrupt.
panic (0x11223344, "Interrupt.")
case 1:
// TLB modification.
panic (0x11223344, "TLB modification.")
case 2:
// TLB load or instruction fetch.
panic (0x11223344, "TLB load or instruction fetch.")
case 3:
// TLB store.
panic (0x11223344, "TLB store.")
case 4:
// Address error load or instruction fetch.
panic (0x11223344, "Address error load or instruction fetch.")
case 5:
// Address error store.
panic (0x11223344, "Address error store.")
case 6:
// Bus error instruction fetch.
panic (0x11223344, "Bus error instruction fetch.")
case 7:
// Bus error load or store.
panic (0x11223344, "Bus error load or store.")
case 8:
// Syscall.
Thread_arch_invoke ()
return current
case 9:
// Breakpoint.
panic (0x11223344, "Breakpoint.")
case 10:
// Reserved instruction.
panic (0x11223344, "Reserved instruction.")
case 11:
// Coprocessor unusable.
panic (0x11223344, "Coprocessor unusable.")
case 12:
// Arithmetic overflow.
panic (0x11223344, "Arithmetic overflow.")
case 13:
// Trap.
panic (0x11223344, "Trap.")
case 15:
// Floating point exception.
panic (0x11223344, "Floating point exception.")
case 23:
// Reference to WatchHi/WatchLo address.
panic (0x11223344, "Reference to WatchHi/WatchLo address.")
case 24:
// Machine check.
panic (0x11223344, "Machine check.")
case 30:
// Cache error (EJTAG only).
panic (0x11223344, "Cache error (EJTAG only).")
case 14:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 25:
case 26:
case 27:
case 28:
case 29:
case 31:
// Reserved.
panic (0x11223344, "Reserved.")
return current
/// There's a cache error. Big trouble. Probably not worth trying to recover.
Thread *cache_error (Thread *current):
save_hilo (current)
panic (0x33333333, "cache error")
return current

14
invoke.ccp Normal file
View File

@ -0,0 +1,14 @@
#pypp 0
#include "kernel.hh"
Capability *Memory::find_capability (unsigned code):
for Capability *c = capabilities; c; c = c->next:
if c == (Capability *)code:
return c
return NULL
void Capability::invoke (unsigned d0, unsigned d1, unsigned d2, unsigned d3, Capability *c0, Capability *c1, Capability *c2, Capability *c3):
if (unsigned)target & PAGE_MASK:
// TODO: Create message in receiver.
return
// TODO: Handle kernel request.

View File

@ -11,6 +11,9 @@
struct Object_base
struct Page
struct Thread
struct Message
struct Receiver
struct Capability
struct Memory
#include "arch.hh"
@ -42,18 +45,41 @@ struct Thread : public Object <Thread>:
unsigned pc, sp
Thread_arch arch
Thread *schedule_prev, *schedule_next
Receiver *receivers
struct Message : public Object <Message>:
Capability *capabilities[4]
unsigned data[4]
unsigned protected_data
struct Receiver : public Object <Receiver>:
Thread *owner
Receiver *prev_owned, *next_owned
Capability *capabilities
Message *messages
struct Capability : public Object <Capability>:
Receiver *target
Capability *children
Capability *sibling_prev, *sibling_next
unsigned protected_data
void invoke (unsigned d0, unsigned d1, unsigned d2, unsigned d3, Capability *c0, Capability *c1, Capability *c2, Capability *c3)
void invalidate ()
struct Memory : public Object <Memory>:
Memory *parent
Free *frees
Page *pages
Thread *threads
Receiver *receivers
Capability *capabilities
Memory *memories
unsigned limit, used
Memory_arch arch
void unmap (Page *page, void *address):
Memory_arch_unmap (this, page, address)
inline bool map (Page *page, unsigned address, bool write)
inline void unmap (Page *page, unsigned address)
inline Page *get_mapping (unsigned address)
// Allocation of pages.
bool use ()
@ -67,14 +93,19 @@ struct Memory : public Object <Memory>:
void *search_free (unsigned size, void **first)
Page *alloc_page ()
Thread *alloc_thread ()
Message *alloc_message (Capability *source)
Receiver *alloc_receiver ()
Capability *alloc_capability (Receiver *target, Capability **parent, unsigned protected_data)
Memory *alloc_memory ()
void free_page (Page *page)
void free_thread (Thread *thread)
void free_message (Message *message)
void free_receiver (Receiver *receiver)
void free_capability (Capability *capability)
void free_memory (Memory *mem)
#define ARCH_PART2
#include "arch.hh"
Capability *find_capability (unsigned code)
// Functions which can be called from assembly must not be mangled.
extern "C":
@ -83,6 +114,8 @@ extern "C":
// Debug: switch caps led
void led (bool one, bool two, bool three)
void schedule ()
struct FreePage:
FreePage *next
@ -92,5 +125,23 @@ EXTERN Thread *sleepers, *runners
EXTERN Thread idle
EXTERN Memory idle_memory
EXTERN Page idle_page
EXTERN Thread *first_scheduled
EXTERN Thread *current
// Defined in arch.cc
void Thread_arch_init (Thread *thread)
void Thread_arch_invoke ()
void Memory_arch_init (Memory *mem)
void Memory_arch_free (Memory *mem)
bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write)
void Memory_arch_unmap (Memory *mem, Page *page, unsigned address)
Page *Memory_arch_get_mapping (Memory *mem, unsigned address)
bool Memory::map (Page *page, unsigned address, bool write):
return Memory_arch_map (this, page, address, write)
void Memory::unmap (Page *page, unsigned address):
Memory_arch_unmap (this, page, address)
Page *Memory::get_mapping (unsigned address):
return Memory_arch_get_mapping (this, address)
#endif

88
mips.ccp Normal file
View File

@ -0,0 +1,88 @@
#pypp 0
#include "kernel.hh"
void Thread_arch_init (Thread *thread):
thread->arch.at = 0
thread->arch.v0 = 0
thread->arch.v1 = 0
thread->arch.a0 = 0
thread->arch.a1 = 0
thread->arch.a2 = 0
thread->arch.a3 = 0
thread->arch.t0 = 0
thread->arch.t1 = 0
thread->arch.t2 = 0
thread->arch.t3 = 0
thread->arch.t4 = 0
thread->arch.t5 = 0
thread->arch.t6 = 0
thread->arch.t7 = 0
thread->arch.t8 = 0
thread->arch.t9 = 0
thread->arch.gp = 0
thread->arch.fp = 0
thread->arch.ra = 0
thread->arch.hi = 0
thread->arch.lo = 0
thread->arch.k0 = 0
thread->arch.k1 = 0
void Memory_arch_init (Memory *mem):
++g_asid
g_asid &= 0x3f
if !g_asid:
++g_asid
mem->arch.asid = g_asid
mem->arch.directory = NULL
void Memory_arch_free (Memory *mem):
if !mem->arch.directory:
return
for unsigned i = 0; i < PAGE_SIZE; ++i:
unsigned *table = mem->arch.directory[i]
if !table:
continue
for unsigned j = 0; j < PAGE_SIZE; ++j:
Page *page = (Page *)(table[j] & ~3)
if !page:
continue
mem->unmap (page, i * 0x1000 * 0x400 + j * 0x1000)
mem->unuse ()
mem->zfree (table)
mem->arch.directory[i] = NULL
mem->unuse ()
mem->zfree (mem->arch.directory)
bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write):
unsigned *table = mem->arch.directory[(unsigned)address >> 22]
if !table:
table = (unsigned *)mem->zalloc ()
if !table:
return false
mem->arch.directory[(unsigned)address >> 22] = table
unsigned idx = ((unsigned)address >> 12) & ((1 << 10) - 1)
if table[idx]:
mem->unmap ((Page *)(table[idx] & ~3), address)
table[idx] = write ? (unsigned)page : (unsigned)page + 1
void Memory_arch_unmap (Memory *mem, Page *page, unsigned address):
unsigned *table = mem->arch.directory[(unsigned)address >> 22]
table[((unsigned)address >> 12) & ((1 << 10) - 1)] = 0
Page *Memory_arch_get_mapping (Memory *mem, unsigned address):
unsigned *table = mem->arch.directory[(unsigned)address >> 22]
unsigned v = table[((unsigned)address >> 12) & ((1 << 10) - 1)]
void Thread_arch_invoke ():
Capability *target, *c0, *c1, *c2, *c3
target = current->address_space->find_capability (current->arch.v0)
if !target:
// TODO: there must be no action here. This is just because the rest doesn't work yet.
led (current->arch.a0, current->arch.a1, current->arch.a2)
schedule ()
return
c0 = current->address_space->find_capability (current->arch.a0)
c1 = current->address_space->find_capability (current->arch.a1)
c2 = current->address_space->find_capability (current->arch.a2)
c3 = current->address_space->find_capability (current->arch.a3)
target->invoke (current->arch.t0, current->arch.t1, current->arch.t2, current->arch.t3, c0, c1, c2, c3)

View File

@ -13,69 +13,10 @@ struct Thread_arch:
struct Memory_arch:
unsigned asid
Page ***directory
static void Memory_arch_unmap (Memory *mem, Page *page, void *address)
#endif // _ARCH_HH
#ifdef ARCH_PART2
static void Thread_arch_init (Thread *thread):
thread->arch.at = 0
thread->arch.v0 = 0
thread->arch.v1 = 0
thread->arch.a0 = 0
thread->arch.a1 = 0
thread->arch.a2 = 0
thread->arch.a3 = 0
thread->arch.t0 = 0
thread->arch.t1 = 0
thread->arch.t2 = 0
thread->arch.t3 = 0
thread->arch.t4 = 0
thread->arch.t5 = 0
thread->arch.t6 = 0
thread->arch.t7 = 0
thread->arch.t8 = 0
thread->arch.t9 = 0
thread->arch.gp = 0
thread->arch.fp = 0
thread->arch.ra = 0
thread->arch.hi = 0
thread->arch.lo = 0
thread->arch.k0 = 0
thread->arch.k1 = 0
unsigned **directory
EXTERN unsigned g_asid
static void Memory_arch_init (Memory *mem):
++g_asid
g_asid &= 0x3f
if !g_asid:
++g_asid
mem->arch.asid = g_asid
mem->arch.directory = NULL
static void Memory_arch_free (Memory *mem):
if !mem->arch.directory:
return
for unsigned i = 0; i < PAGE_SIZE; ++i:
Page **table = mem->arch.directory[i]
if !table:
continue
for unsigned j = 0; j < PAGE_SIZE; ++j:
Page *page = table[j]
if !page:
continue
mem->unmap (page, (void *)(i * 0x1000 * 0x400 + j * 0x1000))
mem->unuse ()
mem->zfree (table)
mem->arch.directory[i] = NULL
mem->unuse ()
mem->zfree (mem->arch.directory)
static void Memory_arch_unmap (Memory *mem, Page *page, void *address):
// Functions which can be called from assembly must not be mangled.
extern "C":
// Kernel entry points, called from entry.S.
@ -91,4 +32,4 @@ extern "C":
void run_idle (Thread *self)
#endif
#endif // ARCH_PART2
#endif

10
schedule.ccp Normal file
View File

@ -0,0 +1,10 @@
#pypp 0
#include "kernel.hh"
void schedule ():
if current:
current = current->schedule_next
if !current:
current = first_scheduled
if !current:
current = &idle