mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-03-04 00:38:20 +02:00
working again with new paging layout
This commit is contained in:
parent
e13dc897fd
commit
35fb72c239
@ -28,7 +28,9 @@ extern "C" {
|
||||
#define CAP_RECEIVER_CREATE_CAPABILITY 2
|
||||
#define CAP_RECEIVER_CREATE_CALL_CAPABILITY 3
|
||||
/* Not an operation; a capability with this bit set is a call capability. */
|
||||
#define CAP_RECEIVER_CALL 4
|
||||
#define CAP_RECEIVER_CALL 8
|
||||
/* Same thing for reply capability. */
|
||||
#define CAP_RECEIVER_REPLY 9
|
||||
|
||||
#define CAP_MEMORY_CREATE 1
|
||||
#define CAP_MEMORY_DESTROY 2
|
||||
@ -44,6 +46,8 @@ extern "C" {
|
||||
/* Flag values for processor state */
|
||||
#define THREAD_FLAG_WAITING 0x80000000
|
||||
#define THREAD_FLAG_RUNNING 0x40000000
|
||||
#define THREAD_FLAG_PRIV 0x20000000
|
||||
#define THREAD_FLAG_USER 0x1fffffff
|
||||
|
||||
#define CAP_PAGE_MAP 1
|
||||
#define CAP_PAGE_SHARE 2
|
||||
|
18
entry.S
18
entry.S
@ -11,6 +11,7 @@
|
||||
#include "arch.hh"
|
||||
|
||||
addr_000:
|
||||
#if 0
|
||||
// TLB refill
|
||||
bne $zero, $k0, slow_refill
|
||||
nop
|
||||
@ -40,8 +41,10 @@ addr_000:
|
||||
slow_refill0:
|
||||
move $k1, $zero
|
||||
slow_refill:
|
||||
#endif
|
||||
sw $ra, -0xd88($zero)
|
||||
bal save_regs
|
||||
nop
|
||||
la $t9, tlb_refill
|
||||
jr $t9
|
||||
nop
|
||||
@ -50,26 +53,33 @@ addr_100:
|
||||
// Cache error
|
||||
sw $ra, -0xd88($zero)
|
||||
bal save_regs
|
||||
nop
|
||||
la $t9, cache_error
|
||||
jr $t9
|
||||
nop
|
||||
.fill 0x180 - (. - addr_000)
|
||||
addr_180:
|
||||
// General exception
|
||||
// Allow new exceptions to update EPC and friends.
|
||||
mtc0 $zero, $CP0_STATUS
|
||||
sw $ra, -0xd88($zero)
|
||||
bal save_regs
|
||||
nop
|
||||
la $t9, exception
|
||||
jr $t9
|
||||
nop
|
||||
.fill 0x200 - (. - addr_000)
|
||||
.fill 0x200 - (. - addr_000) - 8
|
||||
.word 0x0000001e // 1f8 EntryLo data for idle page.
|
||||
.word 0x80000000 // 1fc A pointer to the current page.
|
||||
addr_200:
|
||||
// Interrupt
|
||||
sw $ra, -0xd88($zero)
|
||||
bal save_regs
|
||||
nop
|
||||
la $t9, interrupt
|
||||
jr $t9
|
||||
nop
|
||||
.fill 0x280 - (. - addr_000) - 16
|
||||
.fill 0x280 - (. - addr_000) - 20
|
||||
|
||||
directory:
|
||||
.word 0 // -d94 == directory
|
||||
@ -79,9 +89,7 @@ directory:
|
||||
.word 0 // -d88 == ra
|
||||
.word _gp // -d84 == gp
|
||||
|
||||
.word idle_page // 280
|
||||
.word 0x80000000 // 284 A pointer to the current page.
|
||||
start_idle: // 288
|
||||
start_idle: // 280
|
||||
// Wait for the next interrupt, then the first thread will be scheduled.
|
||||
// It is impractical to try to call schedule, because for that the
|
||||
// idle task would need to own capabilities.
|
||||
|
10
init.ccp
10
init.ccp
@ -24,6 +24,8 @@ static void init_idle ():
|
||||
idle_memory.limit = 0
|
||||
idle_memory.used = 0
|
||||
idle_memory.arch.directory = (unsigned **)0x80000000
|
||||
// Shadow is never used for the idle task.
|
||||
idle_memory.arch.shadow = NULL
|
||||
idle_memory.arch.asid = 0
|
||||
// initialize idle_page
|
||||
idle_page.prev = NULL
|
||||
@ -69,12 +71,16 @@ static void init_cp0 ():
|
||||
cp0_set0 (CP0_INDEX)
|
||||
__asm__ volatile ("tlbwi")
|
||||
// Fill the idle task's page in useg. Set it to non-cachable.
|
||||
cp0_set (CP0_ENTRY_HI, 0x284a0000)
|
||||
// its directory entry is at 1fc, so it's number 7f (0fe00000).
|
||||
// its table entry is at 1f8, so it's number 7e (0007e000).
|
||||
// its address is 280 (00000280), used below for EPC.
|
||||
unsigned const idle_entry_hi = 0x0fe7e000
|
||||
cp0_set (CP0_ENTRY_HI, idle_entry_hi)
|
||||
cp0_set (CP0_ENTRY_LO0, 0x16)
|
||||
cp0_set (CP0_ENTRY_LO1, 0x14)
|
||||
__asm__ volatile ("tlbwr")
|
||||
// Allow eret to be used to jump to the idle task.
|
||||
cp0_set (CP0_EPC, 0x284a0288)
|
||||
cp0_set (CP0_EPC, (idle_entry_hi & PAGE_MASK) | 0x280)
|
||||
// Wait with initializing the status register until the last moment, so that
|
||||
// exceptions in the bootup code will fill EPC and friends.
|
||||
|
||||
|
@ -41,6 +41,7 @@ Thread *interrupt ():
|
||||
Thread *exception ():
|
||||
unsigned cause
|
||||
cp0_get (CP0_CAUSE, cause)
|
||||
//dbg_send (cause >> 2, 5)
|
||||
switch (cause >> 2) & 0x1f:
|
||||
case 0:
|
||||
// Interrupt. This shouldn't happen, since CAUSE[IV] == 1.
|
||||
@ -68,10 +69,8 @@ Thread *exception ():
|
||||
panic (0x81223344, "Bus error load or store.")
|
||||
case 8:
|
||||
// Syscall.
|
||||
// DEBUG: allow new exceptions.
|
||||
//cp0_set0 (CP0_STATUS)
|
||||
arch_invoke ()
|
||||
return current
|
||||
break
|
||||
case 9:
|
||||
// Breakpoint.
|
||||
panic (0x91223344, "Breakpoint.")
|
||||
|
60
invoke.ccp
60
invoke.ccp
@ -20,6 +20,7 @@ Capability *Memory::find_capability (unsigned code, bool *copy):
|
||||
return NULL
|
||||
|
||||
static Capability *reply
|
||||
static Receiver *reply_receiver
|
||||
|
||||
static void reply_cap (unsigned target, unsigned protected_data):
|
||||
Capability r
|
||||
@ -33,19 +34,28 @@ static void reply_cap (unsigned target, unsigned protected_data):
|
||||
unsigned d[4] = { 0, 0, 0, 0 }
|
||||
Capability *caps[4] = { &r, NULL, NULL, NULL }
|
||||
bool cops[4] = { true, false, false, false }
|
||||
reply->invoke (d, caps, cops)
|
||||
if reply:
|
||||
reply->invoke (d, caps, cops)
|
||||
else:
|
||||
// TODO: send message to reply_receiver
|
||||
|
||||
static void reply_cap (Capability *cap, bool copy):
|
||||
unsigned d[4] = { 0, 0, 0, 0 }
|
||||
Capability *caps[4] = { cap, NULL, NULL, NULL }
|
||||
bool cops[4] = { copy, false, false, false }
|
||||
reply->invoke (d, caps, cops)
|
||||
if reply:
|
||||
reply->invoke (d, caps, cops)
|
||||
else:
|
||||
// TODO: send message to reply_receiver
|
||||
|
||||
static void reply_num (unsigned num):
|
||||
unsigned d[4] = { num, 0, 0, 0 }
|
||||
Capability *caps[4] = { NULL, NULL, NULL, NULL }
|
||||
bool cops[4] = { false, false, false, false }
|
||||
reply->invoke (d, caps, cops)
|
||||
if reply:
|
||||
reply->invoke (d, caps, cops)
|
||||
else:
|
||||
// TODO: send message to reply_receiver
|
||||
|
||||
static void admin_invoke (unsigned target, Capability *cap, unsigned request, unsigned data):
|
||||
switch request:
|
||||
@ -117,7 +127,32 @@ static void memory_invoke (unsigned target, unsigned protected_data, Capability
|
||||
return
|
||||
break
|
||||
case CAP_MEMORY_DESTROY:
|
||||
// TODO
|
||||
if !cap || cap->address_space != mem || (unsigned)cap->target & ~KERNEL_MASK:
|
||||
return
|
||||
switch (unsigned)cap->target & CAPTYPE_MASK:
|
||||
case CAPTYPE_ADMIN:
|
||||
// Admin capabilities don't take space, so they cannot be destroyed.
|
||||
return
|
||||
case CAPTYPE_RECEIVER:
|
||||
mem->free_receiver ((Receiver *)cap->protected_data)
|
||||
return
|
||||
case CAPTYPE_MEMORY:
|
||||
mem->free_memory ((Memory *)cap->protected_data)
|
||||
return
|
||||
case CAPTYPE_THREAD:
|
||||
mem->free_thread ((Thread *)cap->protected_data)
|
||||
return
|
||||
case CAPTYPE_PAGE:
|
||||
mem->free_page ((Page *)cap->protected_data)
|
||||
return
|
||||
case CAPTYPE_CAPABILITY:
|
||||
mem->free_capability ((Capability *)cap->protected_data)
|
||||
return
|
||||
case CAPTYPE_CAPPAGE:
|
||||
mem->free_cappage ((Cappage *)cap->protected_data)
|
||||
return
|
||||
default:
|
||||
panic (0x55228930, "invalid case")
|
||||
break
|
||||
case CAP_MEMORY_LIST:
|
||||
// TODO
|
||||
@ -205,7 +240,7 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, unsigned d[
|
||||
// other parameters' meanings depend on the operation.
|
||||
if !((1 << d[0]) & target & ~REQUEST_MASK):
|
||||
// You are not allowed to perform this operation.
|
||||
return false
|
||||
return true
|
||||
reply = c[0]
|
||||
if d[0] == CAP_DEGRADE:
|
||||
reply_cap (target & d[1], protected_data)
|
||||
@ -215,10 +250,21 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, unsigned d[
|
||||
admin_invoke (target, c[1], d[0], d[1])
|
||||
break
|
||||
case CAPTYPE_RECEIVER:
|
||||
if target & CAP_RECEIVER_CALL:
|
||||
if target & (1 << CAP_RECEIVER_CALL):
|
||||
// This is a call capability.
|
||||
protected_data = c[0]->protected_data
|
||||
target = (unsigned)c[0]->target
|
||||
if ~(unsigned)c[0]->target & ~KERNEL_MASK:
|
||||
// TODO: create reply capability.
|
||||
else:
|
||||
// Kernel call: don't create actual capablities.
|
||||
reply = NULL
|
||||
reply_receiver = (Receiver *)protected_data
|
||||
return kernel_invoke (target, protected_data, d, c, copy)
|
||||
if target & (1 << CAP_RECEIVER_REPLY):
|
||||
// This is a reply capability.
|
||||
// TODO
|
||||
return false
|
||||
return true
|
||||
receiver_invoke (target, protected_data, c[1], d[0], d[1])
|
||||
break
|
||||
case CAPTYPE_MEMORY:
|
||||
|
37
mips.ccp
37
mips.ccp
@ -139,6 +139,8 @@ bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write):
|
||||
if !mem->arch.first_page_table:
|
||||
mem->zfree ((unsigned)mem->arch.directory)
|
||||
mem->zfree ((unsigned)mem->arch.shadow)
|
||||
mem->arch.directory = NULL
|
||||
mem->arch.shadow = NULL
|
||||
return false
|
||||
t = alloc_page_table (mem)
|
||||
if !t:
|
||||
@ -146,8 +148,11 @@ bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write):
|
||||
if !mem->arch.first_page_table:
|
||||
mem->zfree ((unsigned)mem->arch.directory)
|
||||
mem->zfree ((unsigned)mem->arch.shadow)
|
||||
mem->arch.directory = NULL
|
||||
mem->arch.shadow = NULL
|
||||
return false
|
||||
mem->arch.directory[address >> 21] = table
|
||||
mem->arch.shadow[address >> 21] = t
|
||||
arch_page *p = alloc_page (mem, t)
|
||||
if !p:
|
||||
if !t->first_page:
|
||||
@ -157,7 +162,7 @@ bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write):
|
||||
unsigned idx = (address >> 12) & ((1 << 9) - 1)
|
||||
if table[idx]:
|
||||
mem->unmap ((Page *)table[idx + 0x200], address)
|
||||
table[idx] = page->physical ? (page->physical >> 6) | 0x18 | (write ? 0x4 : 0) | 0x2 : 0
|
||||
table[idx] = page->physical ? ((page->physical & ~0x80000000) >> 6) | 0x18 | (write ? 0x4 : 0) | 0x2 : 0
|
||||
table[idx + 0x200] = (unsigned)p
|
||||
p->mapping = address
|
||||
p->page = page
|
||||
@ -199,17 +204,17 @@ void arch_invoke ():
|
||||
schedule ()
|
||||
// Calling an invalid capability always fails.
|
||||
caller->arch.v0 = 0
|
||||
return
|
||||
c[0] = caller->address_space->find_capability (caller->arch.a0, ©[0])
|
||||
c[1] = caller->address_space->find_capability (caller->arch.a1, ©[1])
|
||||
c[2] = caller->address_space->find_capability (caller->arch.a2, ©[2])
|
||||
c[3] = caller->address_space->find_capability (caller->arch.a3, ©[3])
|
||||
unsigned d[4]
|
||||
d[0] = caller->arch.t0
|
||||
d[1] = caller->arch.t1
|
||||
d[2] = caller->arch.t2
|
||||
d[3] = caller->arch.t3
|
||||
caller->arch.v0 = target->invoke (d, c, copy) ? 1 : 0
|
||||
else:
|
||||
c[0] = caller->address_space->find_capability (caller->arch.a0, ©[0])
|
||||
c[1] = caller->address_space->find_capability (caller->arch.a1, ©[1])
|
||||
c[2] = caller->address_space->find_capability (caller->arch.a2, ©[2])
|
||||
c[3] = caller->address_space->find_capability (caller->arch.a3, ©[3])
|
||||
unsigned d[4]
|
||||
d[0] = caller->arch.t0
|
||||
d[1] = caller->arch.t1
|
||||
d[2] = caller->arch.t2
|
||||
d[3] = caller->arch.t3
|
||||
caller->arch.v0 = target->invoke (d, c, copy) ? 1 : 0
|
||||
if caller != current:
|
||||
if (Memory *)asids[current->address_space->arch.asid] != current->address_space:
|
||||
if asids[0]:
|
||||
@ -223,6 +228,12 @@ void arch_invoke ():
|
||||
++random
|
||||
if random >= 64:
|
||||
random = 1
|
||||
asids[current->address_space->arch.asid] = (unsigned)current
|
||||
asids[current->address_space->arch.asid] = (unsigned)current->address_space
|
||||
cp0_set (CP0_ENTRY_HI, current->address_space->arch.asid)
|
||||
directory = current->address_space->arch.directory
|
||||
unsigned status
|
||||
cp0_get (CP0_STATUS, status)
|
||||
status &= 0x0fffffff
|
||||
if current->flags & THREAD_FLAG_PRIV:
|
||||
status |= 0x10000000
|
||||
cp0_set (CP0_STATUS, status | 0x13)
|
||||
|
5
test.ccp
5
test.ccp
@ -80,7 +80,7 @@ void dbg_sleep (unsigned ms):
|
||||
__gpio_as_output (CAPSLOCKLED_IO)
|
||||
|
||||
void dbg_send (unsigned code, unsigned bits):
|
||||
for int i = bits; i >= 0; --i:
|
||||
for int i = bits - 1; i >= 0; --i:
|
||||
bool on = code & (1 << i)
|
||||
dbg_led (false, false, false)
|
||||
dbg_sleep (200)
|
||||
@ -92,5 +92,6 @@ void dbg_send (unsigned code, unsigned bits):
|
||||
dbg_led (false, false, false)
|
||||
dbg_sleep (200)
|
||||
dbg_led (true, true, false)
|
||||
dbg_sleep (200)
|
||||
dbg_sleep (500)
|
||||
dbg_led (false, false, false)
|
||||
dbg_sleep (500)
|
||||
|
Loading…
x
Reference in New Issue
Block a user