mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 21:38:57 +02:00
working keyboard
This commit is contained in:
parent
b39c710e87
commit
9a7abe2fd5
4
Makefile
4
Makefile
@ -17,11 +17,11 @@
|
||||
|
||||
# Define some variables.
|
||||
CXXFLAGS = -Wno-unused-parameter -fno-strict-aliasing -fno-builtin -nostdinc $(ARCH_CXXFLAGS)
|
||||
CPPFLAGS = -O5 $(ARCH_CPPFLAGS)
|
||||
CPPFLAGS = -O5 -fno-inline $(ARCH_CPPFLAGS)
|
||||
CC = $(CROSS)gcc
|
||||
LD = $(CROSS)ld
|
||||
OBJCOPY = $(CROSS)objcopy
|
||||
STRIP = $(CROSS)strip
|
||||
STRIP = : $(CROSS)strip
|
||||
|
||||
headers = kernel.hh iris.h $(arch_headers)
|
||||
kernel_sources = panic.cc data.cc alloc.cc invoke.cc schedule.cc $(arch_kernel_sources)
|
||||
|
33
alloc.ccp
33
alloc.ccp
@ -20,7 +20,7 @@
|
||||
|
||||
#define PREV(x) (((Object_base **)(x))[-2])
|
||||
#define NEXT(x) (((Object_base **)(x))[-1])
|
||||
#define SIZE (2 * sizeof (unsigned))
|
||||
#define SIZE (2 * sizeof (Object_base *))
|
||||
|
||||
bool Memory::use ():
|
||||
// Go up to parents, incrementing used.
|
||||
@ -50,6 +50,8 @@ unsigned raw_zalloc ():
|
||||
return (unsigned)ret
|
||||
|
||||
void raw_pfree (unsigned page):
|
||||
if !page:
|
||||
return
|
||||
FreePage *p = (FreePage *)page
|
||||
p->next = junk_pages
|
||||
junk_pages = p
|
||||
@ -105,7 +107,7 @@ void *Memory::search_free (unsigned size, void **first):
|
||||
PREV (f) = NULL
|
||||
s = PAGE_SIZE
|
||||
// We have a free block, possibly too large.
|
||||
if s >= size + sizeof (Free) + SIZE:
|
||||
if s >= size + sizeof (Free) + 2 * SIZE:
|
||||
// Create the new object at the end and keep the Free.
|
||||
Free *obj = (Free *)((unsigned)f + s - size - SIZE)
|
||||
NEXT (obj) = NEXT (f)
|
||||
@ -212,18 +214,30 @@ Capability *Memory::alloc_capability (Receiver *target, Capability *parent, Capa
|
||||
if !ret:
|
||||
return NULL
|
||||
ret->target = target
|
||||
ret->protected_data = protected_data
|
||||
ret->parent = parent
|
||||
ret->children = NULL
|
||||
ret->sibling_prev = NULL
|
||||
ret->sibling_next = parent_ptr ? *parent_ptr : NULL
|
||||
if parent:
|
||||
ret->sibling_next = parent->children
|
||||
parent->children = ret
|
||||
else:
|
||||
if parent_ptr:
|
||||
ret->sibling_next = *parent_ptr
|
||||
else:
|
||||
ret->sibling_next = NULL
|
||||
if ret->sibling_next:
|
||||
ret->sibling_next->sibling_prev = ret
|
||||
ret->protected_data = protected_data
|
||||
return ret
|
||||
|
||||
Capability *Memory::clone_capability (Capability *source, bool copy, Capability *ret):
|
||||
if copy:
|
||||
return alloc_capability (source->target, source->parent, source->parent ? &source->parent->children : &source->target->capabilities, source->protected_data, ret)
|
||||
if source->parent:
|
||||
return alloc_capability (source->target, source->parent, &source->parent->children, source->protected_data, ret)
|
||||
else if (unsigned)source->target & ~KERNEL_MASK:
|
||||
return alloc_capability (source->target, source->parent, &source->target->capabilities, source->protected_data, ret)
|
||||
else:
|
||||
return alloc_capability (source->target, source->parent, &((Object_base *)source->protected_data)->refs, source->protected_data, ret)
|
||||
else:
|
||||
return alloc_capability (source->target, source, &source->children, source->protected_data, ret)
|
||||
|
||||
@ -321,8 +335,10 @@ void Capability::invalidate ():
|
||||
return
|
||||
if sibling_prev:
|
||||
sibling_prev->sibling_next = sibling_next
|
||||
else if target:
|
||||
else if (unsigned)target & ~KERNEL_MASK:
|
||||
target->capabilities = sibling_next
|
||||
else:
|
||||
((Object_base *)protected_data)->refs = sibling_next
|
||||
if sibling_next:
|
||||
sibling_next->sibling_prev = sibling_prev
|
||||
parent = NULL
|
||||
@ -374,9 +390,10 @@ void Page::forget ():
|
||||
data.share_prev = NULL
|
||||
data.share_next = NULL
|
||||
else:
|
||||
raw_pfree (data.frame)
|
||||
if ~data.flags & PAGE_FLAG_PHYSICAL:
|
||||
raw_pfree (data.frame)
|
||||
data.frame = 0
|
||||
data.flags &= ~(PAGE_FLAG_FRAME | PAGE_FLAG_SHARED)
|
||||
data.flags &= ~(PAGE_FLAG_FRAME | PAGE_FLAG_SHARED | PAGE_FLAG_PHYSICAL | PAGE_FLAG_UNCACHED)
|
||||
Page_arch_update_mapping (this)
|
||||
|
||||
void Cappage::forget ():
|
||||
|
@ -14,7 +14,7 @@ GPIO control:
|
||||
|
||||
// GP ... Registers: one set for each port of 32 pins; total 128 pins means 4 groups. Total size: 4 * 0x30 == 0xc0.
|
||||
#define GPIO_GPDR(n) (GPIO_BASE + (0x00 + (n)*0x30)) // D: data
|
||||
#define GPIO_GPDIR(n) (GPIO_BASE + (0x04 + (n)*0x30)) // DI: data in: 1 is input; 0 is output. Disable interrupts on the pin before touching this.
|
||||
#define GPIO_GPDIR(n) (GPIO_BASE + (0x04 + (n)*0x30)) // DI: data in: 0 is input; 1 is output. Disable interrupts on the pin before touching this.
|
||||
#define GPIO_GPODR(n) (GPIO_BASE + (0x08 + (n)*0x30)) // OD:
|
||||
#define GPIO_GPPUR(n) (GPIO_BASE + (0x0c + (n)*0x30)) // PU: pull-up (1 is enable)
|
||||
#define GPIO_GPALR(n) (GPIO_BASE + (0x10 + (n)*0x30)) // AL: alternate lower: per 2 bit; 00 means use as gpio; other values mean use as alternate function
|
||||
@ -180,3 +180,134 @@ do { \
|
||||
REG_GPIO_GPALR(0) &= 0xFF000000; \
|
||||
REG_GPIO_GPALR(0) |= 0x00555555; \
|
||||
} while (0)
|
||||
|
||||
|
||||
// Pins on the trendtac:
|
||||
0 keyboard
|
||||
1 keyboard
|
||||
2 keyboard
|
||||
3 keyboard
|
||||
4 keyboard
|
||||
5 keyboard
|
||||
6 keyboard
|
||||
7 keyboard
|
||||
8 keyboard interrupt
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13 touchpad right button
|
||||
14
|
||||
15
|
||||
16 touchpad left button
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
26
|
||||
27
|
||||
28
|
||||
29
|
||||
30
|
||||
31
|
||||
32
|
||||
33
|
||||
34
|
||||
35
|
||||
36
|
||||
37
|
||||
38
|
||||
39
|
||||
40
|
||||
41
|
||||
42
|
||||
43
|
||||
44
|
||||
45
|
||||
46
|
||||
47
|
||||
48
|
||||
49
|
||||
50
|
||||
51
|
||||
52
|
||||
53
|
||||
54
|
||||
55
|
||||
56
|
||||
57
|
||||
58
|
||||
59
|
||||
60
|
||||
61
|
||||
62
|
||||
63
|
||||
64
|
||||
65
|
||||
66
|
||||
67
|
||||
68
|
||||
69
|
||||
70
|
||||
71
|
||||
72
|
||||
73
|
||||
74
|
||||
75
|
||||
76
|
||||
77
|
||||
78
|
||||
79
|
||||
80
|
||||
81
|
||||
82
|
||||
83
|
||||
84
|
||||
85
|
||||
86
|
||||
87
|
||||
88
|
||||
89
|
||||
90
|
||||
91
|
||||
92
|
||||
93
|
||||
94
|
||||
95
|
||||
96 keyboard
|
||||
97 keyboard
|
||||
98 keyboard
|
||||
99 keyboard
|
||||
100 keyboard
|
||||
101 keyboard
|
||||
102 keyboard
|
||||
103 keyboard
|
||||
104 keyboard
|
||||
105 keyboard
|
||||
106 keyboard
|
||||
107 keyboard
|
||||
108 keyboard
|
||||
109 keyboard
|
||||
110 keyboard
|
||||
111 keyboard
|
||||
112
|
||||
113
|
||||
114
|
||||
115
|
||||
116
|
||||
117
|
||||
118
|
||||
119
|
||||
120
|
||||
121
|
||||
122
|
||||
123
|
||||
124
|
||||
125 keyboard
|
||||
126
|
||||
127
|
||||
|
@ -16,10 +16,15 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
.globl __start
|
||||
.globl __my_receiver
|
||||
.globl __my_thread
|
||||
.globl __my_memory
|
||||
.globl __my_call
|
||||
.set noreorder
|
||||
|
||||
__start:
|
||||
bal 1f
|
||||
nop
|
||||
.word _gp
|
||||
1:
|
||||
lw $gp, 0($ra)
|
||||
|
@ -18,63 +18,101 @@
|
||||
|
||||
#include "iris.h"
|
||||
|
||||
// GPIO pins for the keyboard: Rows =
|
||||
// GPIO pins for the keyboard://
|
||||
// Rows = 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 125
|
||||
// Cols = 0, 1, 2, 3, 4, 5, 6, 7
|
||||
|
||||
// Rows: 60...6f; 7d
|
||||
|
||||
// Nicely aligned to a port: use cols as output; rows as input.
|
||||
// Nicely aligned to a port: use rows as output; cols as input.
|
||||
|
||||
// Map memory from b0010000, which is really 10010000 in kseg1.
|
||||
|
||||
#define D(n) (*(volatile unsigned *)(0x00 + 0x30 * n + address))
|
||||
#define DI(n) (*(volatile unsigned *)(0x04 + 0x30 * n + address))
|
||||
#define AL(n) (*(volatile unsigned *)(0x10 + 0x30 * n + address))
|
||||
#define AU(n) (*(volatile unsigned *)(0x14 + 0x30 * n + address))
|
||||
#define D(n) (*(volatile unsigned *)(0x00 + 0x30 * n + address))
|
||||
#define DI(n) (*(volatile unsigned *)(0x04 + 0x30 * n + address))
|
||||
#define PU(n) (*(volatile unsigned *)(0x0c + 0x30 * n + address))
|
||||
#define AL(n) (*(volatile unsigned *)(0x10 + 0x30 * n + address))
|
||||
#define AU(n) (*(volatile unsigned *)(0x14 + 0x30 * n + address))
|
||||
#define IE(n) (*(volatile unsigned *)(0x20 + 0x30 * n + address))
|
||||
|
||||
void event (bool release, unsigned col, unsigned row):
|
||||
debug_set_led ((col & 1) | (row & 2) | (release ? 4 : 0))
|
||||
unsigned const address = 0x00010000
|
||||
|
||||
static void event (bool release, unsigned row, unsigned col):
|
||||
debug_set_led (col * 2 + (release ? 1 : 0))
|
||||
|
||||
static void delay ():
|
||||
for unsigned i = 0; i < 100000; ++i:
|
||||
IE (3) &= ~0x2000ffff
|
||||
|
||||
int main ():
|
||||
// map memory
|
||||
Capability page = memory_create_page (__my_memory)
|
||||
alloc_physical (page, 0x10010000, 0)
|
||||
unsigned const address = 0x00010000
|
||||
memory_map (__my_memory, page, address)
|
||||
memory_map (__my_memory, page, address, 1)
|
||||
|
||||
#if 0
|
||||
// Keyboard stuff doesn't seem to work. Try the simpler part: touchpad buttons.
|
||||
IE (0) &= ~0x00012000
|
||||
AL (0) &= ~0x0c000000
|
||||
AU (0) &= ~0x00000003
|
||||
DI (0) &= ~0x00012000
|
||||
PU (0) &= ~0x00012000
|
||||
|
||||
unsigned old = 0
|
||||
while true:
|
||||
unsigned data = D (0) & 0x00012000
|
||||
if data == old:
|
||||
continue
|
||||
if data & ~old & 0x00010000:
|
||||
event (true, 0, 0)
|
||||
else if ~data & old & 0x00010000:
|
||||
event (false, 0, 0)
|
||||
if data & ~old & 0x00002000:
|
||||
event (true, 1, 1)
|
||||
else if ~data & old & 0x00002000:
|
||||
event (false, 1, 1)
|
||||
old = data
|
||||
#else
|
||||
// Disable all interrupts.
|
||||
IE (3) &= ~0x2000ffff
|
||||
IE (0) &= ~0x000000ff
|
||||
IE (0) &= ~0x000001ff
|
||||
|
||||
// Set all to GPIO
|
||||
// Set all to GPIO.
|
||||
AL (3) = 0
|
||||
AU (3) &= ~0x0c000000
|
||||
AL (0) &= ~0x0000ffff
|
||||
AL (0) &= ~0x0003ffff
|
||||
|
||||
// Set all to input
|
||||
// Set all rows to input and enable the pull-ups.
|
||||
DI (0) &= ~0x000000ff
|
||||
PU (0) |= 0x000000ff
|
||||
|
||||
// Set all columns to output, 0.
|
||||
DI (3) |= 0x2000ffff
|
||||
DI (0) |= 0x000000ff
|
||||
D (3) &= ~0x2000ffff
|
||||
|
||||
unsigned keys[2][8]
|
||||
for unsigned i = 0; i < 8; ++i:
|
||||
keys[1][i] = 0x2000ffff
|
||||
#define NUM_COLS 17
|
||||
unsigned keys[NUM_COLS]
|
||||
for unsigned i = 0; i < NUM_COLS; ++i:
|
||||
keys[i] = 0
|
||||
|
||||
// Pin numbers for the cols, relative to the start of the port (so minus 0x60).
|
||||
int const cols[NUM_COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29 }
|
||||
while true:
|
||||
// read keyboard
|
||||
for unsigned col = 0; col < 8; ++col:
|
||||
// set col to output, all others to input
|
||||
DI (0) = (DI (0) & ~0x000000ff) | (1 << col)
|
||||
// read input
|
||||
keys[0][col] = D (3) & ~0x2000ffff
|
||||
// Generate events
|
||||
if keys[0][col] == keys[1][col]:
|
||||
continue
|
||||
unsigned bit, b
|
||||
for bit = 1, b = 0; bit < 0x10000; bit <<= 1, ++b:
|
||||
if (keys[0][col] ^ keys[1][col]) & bit:
|
||||
event (keys[0][col] & bit, col, b)
|
||||
if (keys[0][col] ^ keys[1][col]) & 0x20000000:
|
||||
// Not really bit 16, but it's easier to handle.
|
||||
event (keys[0][col] & 0x20000000, col, 16)
|
||||
unsigned data[NUM_COLS]
|
||||
for unsigned col = 0; col < NUM_COLS; ++col:
|
||||
D (3) &= ~0x2000ffff
|
||||
delay ()
|
||||
unsigned zero = ~D (0) & 0x000000ff
|
||||
D (3) = (D (3) & ~0x2000ffff) | (1 << cols[col])
|
||||
delay ()
|
||||
data[col] = D (0) & zero
|
||||
|
||||
// Generate events.
|
||||
for unsigned col = 0; col < NUM_COLS; ++col:
|
||||
for unsigned row = 0; row < 8; ++row:
|
||||
if (data[col] ^ keys[col]) & (1 << row):
|
||||
event (data[col] & (1 << row), row, col)
|
||||
keys[col] = data[col]
|
||||
schedule ()
|
||||
#endif
|
||||
|
@ -20,4 +20,4 @@
|
||||
|
||||
int main ():
|
||||
while true:
|
||||
__asm__ volatile ("move $v0, $zero; li $a0, 1 ; move $a1, $zero ; move $a2, $a0 ; syscall")
|
||||
schedule ()
|
||||
|
317
invoke.ccp
317
invoke.ccp
@ -30,6 +30,7 @@ Capability *Memory::find_capability (unsigned code, bool *copy):
|
||||
if p->data.frame == (unsigned)page:
|
||||
return &page[num]
|
||||
else:
|
||||
code &= ~3
|
||||
// Normal capability
|
||||
for Capability *c = capabilities; c; c = c->next:
|
||||
if c == (Capability *)code:
|
||||
@ -46,36 +47,37 @@ bool Receiver::try_deliver ():
|
||||
break
|
||||
if !m:
|
||||
return false
|
||||
Capability *c[4]
|
||||
Capability::Context c
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
c.data[i] = m->data[i]
|
||||
if !m->capabilities[i]:
|
||||
c[i] = NULL
|
||||
c.cap[i] = NULL
|
||||
else:
|
||||
c[i] = owner->address_space->clone_capability (m->capabilities[i], true)
|
||||
if !c[i]:
|
||||
c.cap[i] = owner->address_space->clone_capability (m->capabilities[i], true)
|
||||
if !c.cap[i]:
|
||||
for unsigned j = 0; j < i; ++j:
|
||||
owner->address_space->free_capability (c[i])
|
||||
owner->address_space->free_capability (c.cap[i])
|
||||
return false
|
||||
Thread_arch_receive (owner, m->data, c)
|
||||
Thread_arch_receive (owner, &c)
|
||||
owner->unwait ()
|
||||
return true
|
||||
|
||||
bool Receiver::send_message (unsigned protected_data, unsigned data[4], Capability *cap[4], bool copy[4]):
|
||||
bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
||||
bool tried_direct = false
|
||||
if owner && owner->is_waiting () && (protected_data == reply_protected_data || !protected_only):
|
||||
Capability *c[4]
|
||||
Capability::Context n
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
if !cap[i]:
|
||||
c[i] = NULL
|
||||
if !c->cap[i]:
|
||||
n.cap[i] = NULL
|
||||
else:
|
||||
c[i] = owner->address_space->clone_capability (cap[i], copy[i])
|
||||
if !c[i]:
|
||||
n.cap[i] = owner->address_space->clone_capability (c->cap[i], c->copy[i])
|
||||
if !n.cap[i]:
|
||||
for unsigned j = 0; j < i; ++j:
|
||||
owner->address_space->free_capability (c[i])
|
||||
owner->address_space->free_capability (n.cap[i])
|
||||
tried_direct = true
|
||||
break
|
||||
if !tried_direct:
|
||||
Thread_arch_receive (owner, data, c)
|
||||
Thread_arch_receive (owner, &n)
|
||||
owner->unwait ()
|
||||
return true
|
||||
// The owner was not waiting, or it was not possible to deliver the message. Put it in the queue.
|
||||
@ -83,11 +85,11 @@ bool Receiver::send_message (unsigned protected_data, unsigned data[4], Capabili
|
||||
if !msg:
|
||||
return false
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
msg->data[i] = data[i]
|
||||
if !cap[i]:
|
||||
msg->data[i] = c->data[i]
|
||||
if !c->cap[i]:
|
||||
msg->capabilities[i] = NULL
|
||||
else:
|
||||
msg->capabilities[i] = address_space->clone_capability (cap[i], copy[i])
|
||||
msg->capabilities[i] = address_space->clone_capability (c->cap[i], c->copy[i])
|
||||
if !msg->capabilities[i]:
|
||||
for unsigned j = 0; j < i; ++j:
|
||||
address_space->free_capability (msg->capabilities[j])
|
||||
@ -113,106 +115,125 @@ static void fill_cap (Capability *r, unsigned target, unsigned protected_data):
|
||||
static void reply_cap (unsigned target, unsigned protected_data):
|
||||
Capability r
|
||||
fill_cap (&r, target, protected_data)
|
||||
unsigned d[4] = { 0, 0, 0, 0 }
|
||||
Capability *caps[4] = { &r, NULL, NULL, NULL }
|
||||
bool cops[4] = { true, false, false, false }
|
||||
Capability::Context c
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
c.data[i] = 0
|
||||
c.cap[0] = &r
|
||||
c.copy[0] = true
|
||||
for unsigned i = 1; i < 4; ++i:
|
||||
c.cap[i] = NULL
|
||||
c.copy[i] = false
|
||||
if reply:
|
||||
reply->invoke (d, caps, cops)
|
||||
else:
|
||||
reply_receiver->send_message (reply_receiver->reply_protected_data, d, caps, cops)
|
||||
reply->invoke (&c)
|
||||
else if reply_receiver:
|
||||
reply_receiver->send_message (reply_receiver->reply_protected_data, &c)
|
||||
r.invalidate ()
|
||||
|
||||
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 }
|
||||
Capability::Context c
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
c.data[i] = 0
|
||||
c.cap[0] = cap
|
||||
c.copy[0] = copy
|
||||
for unsigned i = 1; i < 4; ++i:
|
||||
c.cap[i] = NULL
|
||||
c.copy[i] = false
|
||||
if reply:
|
||||
reply->invoke (d, caps, cops)
|
||||
else:
|
||||
reply_receiver->send_message (reply_receiver->reply_protected_data, d, caps, cops)
|
||||
reply->invoke (&c)
|
||||
else if reply_receiver:
|
||||
reply_receiver->send_message (reply_receiver->reply_protected_data, &c)
|
||||
|
||||
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 }
|
||||
Capability::Context c
|
||||
c.data[0] = num
|
||||
for unsigned i = 1; i < 4; ++i:
|
||||
c.data[i] = 0
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
c.cap[i] = NULL
|
||||
c.copy[i] = false
|
||||
if reply:
|
||||
reply->invoke (d, caps, cops)
|
||||
else:
|
||||
reply_receiver->send_message (reply_receiver->reply_protected_data, d, caps, cops)
|
||||
reply->invoke (&c)
|
||||
else if reply_receiver:
|
||||
reply_receiver->send_message (reply_receiver->reply_protected_data, &c)
|
||||
|
||||
static void reply_nums (unsigned num1, unsigned num2):
|
||||
unsigned d[4] = { num1, num2, 0, 0 }
|
||||
Capability *caps[4] = { NULL, NULL, NULL, NULL }
|
||||
bool cops[4] = { false, false, false, false }
|
||||
Capability::Context c
|
||||
c.data[0] = num1
|
||||
c.data[1] = num2
|
||||
c.data[2] = 0
|
||||
c.data[3] = 0
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
c.cap[i] = NULL
|
||||
c.copy[i] = false
|
||||
if reply:
|
||||
reply->invoke (d, caps, cops)
|
||||
else:
|
||||
reply_receiver->send_message (reply_receiver->reply_protected_data, d, caps, cops)
|
||||
reply->invoke (&c)
|
||||
else if reply_receiver:
|
||||
reply_receiver->send_message (reply_receiver->reply_protected_data, &c)
|
||||
|
||||
static void receiver_invoke (unsigned target, unsigned protected_data, Capability *cap, unsigned data[4]):
|
||||
static void receiver_invoke (unsigned target, unsigned protected_data, Capability::Context *c):
|
||||
Receiver *receiver = (Receiver *)protected_data
|
||||
switch data[0]:
|
||||
switch c->data[0]:
|
||||
case CAP_RECEIVER_SET_OWNER:
|
||||
if ((unsigned)cap->target & (CAPTYPE_MASK | ~KERNEL_MASK)) != CAPTYPE_THREAD:
|
||||
if !c->cap[0] || ((unsigned)c->cap[0]->target & (CAPTYPE_MASK | ~KERNEL_MASK)) != CAPTYPE_THREAD:
|
||||
// FIXME: This makes it impossible to use a fake Thread capability.
|
||||
return
|
||||
receiver->own ((Thread *)cap->protected_data)
|
||||
receiver->own ((Thread *)c->cap[0]->protected_data)
|
||||
break
|
||||
case CAP_RECEIVER_CREATE_CAPABILITY:
|
||||
reply_cap ((unsigned)receiver, data[1])
|
||||
reply_cap ((unsigned)receiver, c->data[1])
|
||||
break
|
||||
case CAP_RECEIVER_CREATE_CALL_CAPABILITY:
|
||||
reply_cap (CAPTYPE_RECEIVER | CAP_RECEIVER_CALL | (data[1] ? CAP_RECEIVER_CALL_ASYNC : 0), protected_data)
|
||||
reply_cap (CAPTYPE_RECEIVER | (1 << CAP_RECEIVER_CALL) | (c->data[1] ? 1 << CAP_RECEIVER_CALL_ASYNC : 0), protected_data)
|
||||
break
|
||||
case CAP_RECEIVER_GET_REPLY_PROTECTED_DATA:
|
||||
reply_nums (receiver->reply_protected_data, receiver->protected_only ? 1 : 0)
|
||||
break
|
||||
case CAP_RECEIVER_SET_REPLY_PROTECTED_DATA:
|
||||
receiver->reply_protected_data = data[1]
|
||||
receiver->protected_only = data[2]
|
||||
receiver->reply_protected_data = c->data[1]
|
||||
receiver->protected_only = c->data[2]
|
||||
break
|
||||
default:
|
||||
break
|
||||
|
||||
static void memory_invoke (unsigned target, unsigned protected_data, Capability *cap, unsigned request, unsigned data):
|
||||
static void memory_invoke (unsigned target, unsigned protected_data, Capability::Context *c):
|
||||
Memory *mem = (Memory *)protected_data
|
||||
switch request:
|
||||
switch c->data[0]:
|
||||
case CAP_MEMORY_CREATE:
|
||||
unsigned rights = data & REQUEST_MASK
|
||||
data &= CAPTYPE_MASK
|
||||
switch data:
|
||||
unsigned rights = c->data[1] & REQUEST_MASK
|
||||
unsigned type = c->data[1] & CAPTYPE_MASK
|
||||
switch type:
|
||||
case CAPTYPE_RECEIVER:
|
||||
Receiver *ret = mem->alloc_receiver ()
|
||||
if ret:
|
||||
reply_cap (data | (rights & CAP_RECEIVER_ALL_RIGHTS), (unsigned)ret)
|
||||
reply_cap (CAPTYPE_RECEIVER | (rights & CAP_RECEIVER_ALL_RIGHTS), (unsigned)ret)
|
||||
else:
|
||||
reply_num (0)
|
||||
break
|
||||
case CAPTYPE_MEMORY:
|
||||
Memory *ret = mem->alloc_memory ()
|
||||
if ret:
|
||||
reply_cap (data | (rights & CAP_MEMORY_ALL_RIGHTS), (unsigned)ret)
|
||||
reply_cap (CAPTYPE_MEMORY | (rights & CAP_MEMORY_ALL_RIGHTS), (unsigned)ret)
|
||||
else:
|
||||
reply_num (0)
|
||||
break
|
||||
case CAPTYPE_THREAD:
|
||||
Thread *ret = mem->alloc_thread ()
|
||||
if ret:
|
||||
reply_cap (data | (rights & CAP_THREAD_ALL_RIGHTS), (unsigned)ret)
|
||||
reply_cap (CAPTYPE_THREAD | (rights & CAP_THREAD_ALL_RIGHTS), (unsigned)ret)
|
||||
else:
|
||||
reply_num (0)
|
||||
break
|
||||
case CAPTYPE_PAGE:
|
||||
Page *ret = mem->alloc_page ()
|
||||
if ret:
|
||||
reply_cap (data | (rights & CAP_PAGE_ALL_RIGHTS), (unsigned)ret)
|
||||
reply_cap (CAPTYPE_PAGE | (rights & CAP_PAGE_ALL_RIGHTS), (unsigned)ret)
|
||||
else:
|
||||
reply_num (0)
|
||||
break
|
||||
case CAPTYPE_CAPPAGE:
|
||||
Cappage *ret = mem->alloc_cappage ()
|
||||
if ret:
|
||||
reply_cap (data | (rights & CAP_CAPPAGE_ALL_RIGHTS), (unsigned)ret)
|
||||
reply_cap (CAPTYPE_CAPPAGE | (rights & CAP_CAPPAGE_ALL_RIGHTS), (unsigned)ret)
|
||||
else:
|
||||
reply_num (0)
|
||||
break
|
||||
@ -220,26 +241,26 @@ static void memory_invoke (unsigned target, unsigned protected_data, Capability
|
||||
return
|
||||
break
|
||||
case CAP_MEMORY_DESTROY:
|
||||
if !cap || cap->address_space != mem || (unsigned)cap->target & ~KERNEL_MASK:
|
||||
if !c->cap[0] || c->cap[0]->address_space != mem || (unsigned)c->cap[0]->target & ~KERNEL_MASK:
|
||||
return
|
||||
switch (unsigned)cap->target & CAPTYPE_MASK:
|
||||
switch (unsigned)c->cap[0]->target & CAPTYPE_MASK:
|
||||
case CAPTYPE_RECEIVER:
|
||||
mem->free_receiver ((Receiver *)cap->protected_data)
|
||||
mem->free_receiver ((Receiver *)c->cap[0]->protected_data)
|
||||
return
|
||||
case CAPTYPE_MEMORY:
|
||||
mem->free_memory ((Memory *)cap->protected_data)
|
||||
mem->free_memory ((Memory *)c->cap[0]->protected_data)
|
||||
return
|
||||
case CAPTYPE_THREAD:
|
||||
mem->free_thread ((Thread *)cap->protected_data)
|
||||
mem->free_thread ((Thread *)c->cap[0]->protected_data)
|
||||
return
|
||||
case CAPTYPE_PAGE:
|
||||
mem->free_page ((Page *)cap->protected_data)
|
||||
mem->free_page ((Page *)c->cap[0]->protected_data)
|
||||
return
|
||||
case CAPTYPE_CAPABILITY:
|
||||
mem->free_capability ((Capability *)cap->protected_data)
|
||||
mem->free_capability ((Capability *)c->cap[0]->protected_data)
|
||||
return
|
||||
case CAPTYPE_CAPPAGE:
|
||||
mem->free_cappage ((Cappage *)cap->protected_data)
|
||||
mem->free_cappage ((Cappage *)c->cap[0]->protected_data)
|
||||
return
|
||||
default:
|
||||
panic (0x55228930, "invalid case")
|
||||
@ -249,41 +270,42 @@ static void memory_invoke (unsigned target, unsigned protected_data, Capability
|
||||
break
|
||||
case CAP_MEMORY_MAP:
|
||||
// FIXME: this should work for fake pages as well.
|
||||
if (unsigned)cap->target & ~KERNEL_MASK || ((unsigned)cap->target & CAPTYPE_MASK) != CAPTYPE_PAGE:
|
||||
if !c->cap[0] || (unsigned)c->cap[0]->target & ~KERNEL_MASK || ((unsigned)c->cap[0]->target & CAPTYPE_MASK) != CAPTYPE_PAGE:
|
||||
break
|
||||
Page *page = (Page *)cap->protected_data
|
||||
Page *page = (Page *)c->cap[0]->protected_data
|
||||
if page->address_space != mem:
|
||||
break
|
||||
mem->map (page, data & PAGE_MASK, data & (unsigned)cap->target & (1 << CAP_PAGE_WRITE))
|
||||
bool writable = c->data[1] & (unsigned)c->cap[0]->target & (1 << CAP_PAGE_WRITE)
|
||||
mem->map (page, c->data[1] & PAGE_MASK, writable)
|
||||
break
|
||||
case CAP_MEMORY_MAPPING:
|
||||
bool write
|
||||
Page *page = mem->get_mapping (data, &write)
|
||||
Page *page = mem->get_mapping (c->data[1], &write)
|
||||
unsigned t = CAPTYPE_PAGE | REQUEST_MASK
|
||||
if !write:
|
||||
t &= ~CAP_PAGE_WRITE
|
||||
reply_cap (t, (unsigned)page)
|
||||
break
|
||||
case CAP_MEMORY_SET_LIMIT:
|
||||
mem->limit = data
|
||||
mem->limit = c->data[1]
|
||||
break
|
||||
case CAP_MEMORY_GET_LIMIT:
|
||||
reply_num (mem->limit)
|
||||
break
|
||||
case CAP_MEMORY_DROP:
|
||||
if cap->address_space != mem:
|
||||
if !c->cap[0] || c->cap[0]->address_space != mem:
|
||||
break
|
||||
mem->free_capability (cap)
|
||||
mem->free_capability (c->cap[0])
|
||||
break
|
||||
default:
|
||||
break
|
||||
|
||||
static void thread_invoke (unsigned target, unsigned protected_data, Capability *cap, unsigned data[4]):
|
||||
static void thread_invoke (unsigned target, unsigned protected_data, Capability::Context *c):
|
||||
Thread *thread = (Thread *)protected_data
|
||||
switch data[0]:
|
||||
switch c->data[0]:
|
||||
case CAP_THREAD_INFO:
|
||||
unsigned *value
|
||||
switch data[1]:
|
||||
switch c->data[1]:
|
||||
case CAP_THREAD_INFO_PC:
|
||||
value = &thread->pc
|
||||
break
|
||||
@ -292,10 +314,10 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability
|
||||
break
|
||||
case CAP_THREAD_INFO_FLAGS:
|
||||
// It is not possible to set the PRIV flag, but it can be reset.
|
||||
data[2] &= ~THREAD_FLAG_PRIV
|
||||
c->data[2] &= ~THREAD_FLAG_PRIV
|
||||
value = &thread->flags
|
||||
if data[3] & ~THREAD_FLAG_USER:
|
||||
unsigned v = (*value & data[3]) | (data[2] & data[3])
|
||||
if c->data[3] & ~THREAD_FLAG_USER:
|
||||
unsigned v = (*value & c->data[3]) | (c->data[2] & c->data[3])
|
||||
if (v & THREAD_FLAG_WAITING) != (*value & THREAD_FLAG_WAITING):
|
||||
if v & THREAD_FLAG_WAITING:
|
||||
thread->wait ()
|
||||
@ -308,11 +330,11 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability
|
||||
thread->unrun ()
|
||||
break
|
||||
default:
|
||||
value = Thread_arch_info (thread, data[1])
|
||||
value = Thread_arch_info (thread, c->data[1])
|
||||
break
|
||||
if value:
|
||||
*value &= ~data[3]
|
||||
*value |= data[2] & data[3]
|
||||
*value &= ~c->data[3]
|
||||
*value |= c->data[2] & c->data[3]
|
||||
reply_num (*value)
|
||||
else:
|
||||
reply_num (0)
|
||||
@ -321,24 +343,39 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability
|
||||
schedule ()
|
||||
break
|
||||
case CAP_THREAD_DEBUG:
|
||||
dbg_leds (data[1] & 1, data[1] & 2, data[1] & 4)
|
||||
for unsigned i = 0; i < 2; ++i:
|
||||
dbg_led (true, true, true)
|
||||
dbg_sleep (100)
|
||||
dbg_led (false, false, false)
|
||||
dbg_sleep (100)
|
||||
//dbg_send (c->data[1], 5)
|
||||
break
|
||||
case CAP_THREAD_REGISTER_INTERRUPT:
|
||||
// Threads with access to this call are trusted, so no sanity checking is done.
|
||||
arch_register_interrupt (data[1], cap ? (Receiver *)cap->protected_data : NULL)
|
||||
arch_register_interrupt (c->data[1], c->cap[0] ? (Receiver *)c->cap[0]->protected_data : NULL)
|
||||
break
|
||||
case CAP_THREAD_GET_TOP_MEMORY:
|
||||
// Threads with access to this call are trusted, so no sanity checking is done.
|
||||
reply_cap (CAPTYPE_MEMORY | (data[1] & CAP_MEMORY_ALL_RIGHTS), (unsigned)&top_memory)
|
||||
reply_cap (CAPTYPE_MEMORY | (c->data[1] & CAP_MEMORY_ALL_RIGHTS), (unsigned)&top_memory)
|
||||
break
|
||||
case CAP_THREAD_MAKE_PRIV:
|
||||
// Threads with access to this call are trusted, so no sanity checking is done.
|
||||
if data[1] & THREAD_FLAG_PRIV:
|
||||
((Thread *)cap->protected_data)->flags |= THREAD_FLAG_PRIV
|
||||
reply_cap (CAPTYPE_THREAD | (data[1] & CAP_THREAD_ALL_PRIV_RIGHTS), cap->protected_data)
|
||||
if c->data[1] & THREAD_FLAG_PRIV:
|
||||
((Thread *)c->cap[0]->protected_data)->flags |= THREAD_FLAG_PRIV
|
||||
reply_cap (CAPTYPE_THREAD | (c->data[1] & CAP_THREAD_ALL_PRIV_RIGHTS), c->cap[0]->protected_data)
|
||||
break
|
||||
case CAP_THREAD_ALLOC_PHYSICAL:
|
||||
// TODO
|
||||
// Threads with access to this call are trusted, so no sanity checking is done.
|
||||
Page *page = (Page *)c->cap[0]->protected_data
|
||||
page->forget ()
|
||||
if page->data.flags & PAGE_FLAG_PAYING:
|
||||
page->data.flags &= ~PAGE_FLAG_PAYING
|
||||
page->address_space->unuse ()
|
||||
page->data.frame = c->data[1] & PAGE_MASK
|
||||
if c->data[1] & 1:
|
||||
page->data.flags |= PAGE_FLAG_FRAME | PAGE_FLAG_PHYSICAL
|
||||
else:
|
||||
page->data.flags |= PAGE_FLAG_FRAME | PAGE_FLAG_PHYSICAL | PAGE_FLAG_UNCACHED
|
||||
break
|
||||
default:
|
||||
break
|
||||
@ -393,7 +430,7 @@ static bool cappage_check_payment (Cappage *cappage):
|
||||
p->data.flags &= ~(PAGE_FLAG_SHARED | PAGE_FLAG_FRAME)
|
||||
return false
|
||||
|
||||
static void page_invoke (unsigned target, unsigned protected_data, Capability *cap, bool copy, unsigned data[4]):
|
||||
static void page_invoke (unsigned target, unsigned protected_data, Capability::Context *c):
|
||||
Page *page
|
||||
Cappage *cappage
|
||||
ShareData *share_data
|
||||
@ -405,22 +442,22 @@ static void page_invoke (unsigned target, unsigned protected_data, Capability *c
|
||||
page = NULL
|
||||
cappage = (Cappage *)protected_data
|
||||
share_data = &cappage->data
|
||||
switch data[0]:
|
||||
switch c->data[0]:
|
||||
case CAP_PAGE_SHARE:
|
||||
if ((unsigned)cap->target & CAPTYPE_MASK) != (target & CAPTYPE_MASK):
|
||||
if !c->cap[0] || ((unsigned)c->cap[0]->target & CAPTYPE_MASK) != (target & CAPTYPE_MASK):
|
||||
// FIXME: This makes it impossible to use a fake Page capability.
|
||||
break
|
||||
if page:
|
||||
Page *t = (Page *)cap->protected_data
|
||||
Page *t = (Page *)c->cap[0]->protected_data
|
||||
t->forget ()
|
||||
if data[1] & PAGE_SHARE_READONLY:
|
||||
if c->data[1] & PAGE_SHARE_READONLY:
|
||||
t->data.flags &= ~PAGE_FLAG_WRITABLE
|
||||
if !page->data.flags & PAGE_FLAG_FRAME:
|
||||
break
|
||||
if data[1] & PAGE_SHARE_COPY:
|
||||
if c->data[1] & PAGE_SHARE_COPY:
|
||||
if ~t->data.flags & PAGE_FLAG_PAYING:
|
||||
break
|
||||
if ~data[1] & PAGE_SHARE_FORGET || page->data.flags & PAGE_FLAG_SHARED:
|
||||
if ~c->data[1] & PAGE_SHARE_FORGET || page->data.flags & PAGE_FLAG_SHARED:
|
||||
unsigned *d = (unsigned *)page->data.frame
|
||||
if t == page:
|
||||
Page *other = page->data.share_next ? (Page *)page->data.share_next : (Page *)page->data.share_prev
|
||||
@ -437,7 +474,7 @@ static void page_invoke (unsigned target, unsigned protected_data, Capability *c
|
||||
else:
|
||||
t->data.flags |= PAGE_FLAG_FRAME
|
||||
t->data.frame = raw_zalloc ()
|
||||
for unsigned i = 0; i <= (data[1] & ~PAGE_MASK); i += 4:
|
||||
for unsigned i = 0; i <= (c->data[1] & ~PAGE_MASK); i += 4:
|
||||
((unsigned *)t->data.frame)[i >> 2] = d[i >> 2]
|
||||
else:
|
||||
if t != page:
|
||||
@ -450,7 +487,7 @@ static void page_invoke (unsigned target, unsigned protected_data, Capability *c
|
||||
else:
|
||||
if t == page:
|
||||
break
|
||||
if data[1] & PAGE_SHARE_FORGET:
|
||||
if c->data[1] & PAGE_SHARE_FORGET:
|
||||
if ~page->data.flags & PAGE_FLAG_SHARED:
|
||||
if t->data.flags & PAGE_FLAG_PAYING:
|
||||
t->data.frame = page->data.frame
|
||||
@ -477,16 +514,16 @@ static void page_invoke (unsigned target, unsigned protected_data, Capability *c
|
||||
((Page *)t->data.share_prev)->data.share_next = t
|
||||
Page_arch_update_mapping (t)
|
||||
else:
|
||||
Cappage *t = (Cappage *)cap->protected_data
|
||||
Cappage *t = (Cappage *)c->cap[0]->protected_data
|
||||
t->forget ()
|
||||
if data[1] & PAGE_SHARE_READONLY:
|
||||
if c->data[1] & PAGE_SHARE_READONLY:
|
||||
t->data.flags &= ~PAGE_FLAG_WRITABLE
|
||||
if !cappage->data.flags & PAGE_FLAG_FRAME:
|
||||
break
|
||||
if data[1] & PAGE_SHARE_COPY:
|
||||
if c->data[1] & PAGE_SHARE_COPY:
|
||||
if ~t->data.flags & PAGE_FLAG_PAYING:
|
||||
break
|
||||
if ~data[1] & PAGE_SHARE_FORGET || cappage->data.flags & PAGE_FLAG_SHARED:
|
||||
if ~c->data[1] & PAGE_SHARE_FORGET || cappage->data.flags & PAGE_FLAG_SHARED:
|
||||
unsigned *d = (unsigned *)cappage->data.frame
|
||||
if t == cappage:
|
||||
Cappage *other = cappage->data.share_next ? (Cappage *)cappage->data.share_next : (Cappage *)cappage->data.share_prev
|
||||
@ -502,7 +539,7 @@ static void page_invoke (unsigned target, unsigned protected_data, Capability *c
|
||||
else:
|
||||
t->data.flags |= PAGE_FLAG_FRAME
|
||||
t->data.frame = raw_zalloc ()
|
||||
for unsigned i = 0; i < ((data[1] & ~PAGE_MASK) + 1) * sizeof (Capability); i += 4:
|
||||
for unsigned i = 0; i < ((c->data[1] & ~PAGE_MASK) + 1) * sizeof (Capability); i += 4:
|
||||
((unsigned *)t->data.frame)[i >> 2] = d[i >> 2]
|
||||
else:
|
||||
if t != cappage:
|
||||
@ -513,7 +550,7 @@ static void page_invoke (unsigned target, unsigned protected_data, Capability *c
|
||||
else:
|
||||
if t == cappage:
|
||||
break
|
||||
if data[1] & PAGE_SHARE_FORGET:
|
||||
if c->data[1] & PAGE_SHARE_FORGET:
|
||||
if ~cappage->data.flags & PAGE_FLAG_SHARED:
|
||||
if t->data.flags & PAGE_FLAG_PAYING:
|
||||
t->data.frame = cappage->data.frame
|
||||
@ -538,10 +575,12 @@ static void page_invoke (unsigned target, unsigned protected_data, Capability *c
|
||||
if t->data.share_prev:
|
||||
((Cappage *)t->data.share_prev)->data.share_next = t
|
||||
case CAP_PAGE_FLAGS:
|
||||
// Always refuse to set reserved flags.
|
||||
c->data[2] &= ~(PAGE_FLAG_PHYSICAL | PAGE_FLAG_UNCACHED)
|
||||
// Remember the old flags.
|
||||
unsigned old = share_data->flags
|
||||
// Compute the new flags.
|
||||
unsigned new_flags = (share_data->flags & ~data[2]) | (data[1] & data[2])
|
||||
unsigned new_flags = (share_data->flags & ~c->data[2]) | (c->data[1] & c->data[2])
|
||||
|
||||
// If we stop paying, see if the frame is still paid for. If not, free it.
|
||||
if ~new_flags & old & PAGE_FLAG_PAYING:
|
||||
@ -626,54 +665,54 @@ static void page_invoke (unsigned target, unsigned protected_data, Capability *c
|
||||
reply_num (share_data->flags)
|
||||
break
|
||||
case CAP_CAPPAGE_SET:
|
||||
if !cappage || data[1] >= CAPPAGE_SIZE || !(target & CAP_PAGE_WRITE):
|
||||
if !cappage || c->data[1] >= CAPPAGE_SIZE || !(target & CAP_PAGE_WRITE):
|
||||
return
|
||||
Capability *c = &((Capability *)cappage->data.frame)[data[1]]
|
||||
c->invalidate ()
|
||||
// clone_capability needs a Memory, but doesn't use it when storage is provided.
|
||||
top_memory.clone_capability (cap, copy, c)
|
||||
Capability *cap = &((Capability *)cappage->data.frame)[c->data[1]]
|
||||
if cap:
|
||||
cap->invalidate ()
|
||||
// clone_capability needs a Memory, but doesn't use it when storage is provided.
|
||||
top_memory.clone_capability (c->cap[0], c->copy[0], cap)
|
||||
break
|
||||
default:
|
||||
break
|
||||
|
||||
static void capability_invoke (unsigned target, unsigned protected_data, Capability *cap, unsigned request, unsigned data):
|
||||
static void capability_invoke (unsigned target, unsigned protected_data, Capability::Context *c):
|
||||
Capability *capability = (Capability *)protected_data
|
||||
switch request:
|
||||
switch c->data[0]:
|
||||
case CAP_CAPABILITY_GET:
|
||||
reply_cap (capability, true)
|
||||
break
|
||||
default:
|
||||
break
|
||||
|
||||
static bool kernel_invoke (unsigned target, unsigned protected_data, unsigned d[4], Capability *c[4], bool copy[4], Capability *self):
|
||||
static bool kernel_invoke (unsigned target, unsigned protected_data, Capability::Context *c, Capability *self):
|
||||
// Kernel calling convention:
|
||||
// data[0] is the request.
|
||||
// cap[0] is the reply capability
|
||||
// other parameters' meanings depend on the operation.
|
||||
if !((1 << d[0]) & target & ~REQUEST_MASK):
|
||||
// You are not allowed to perform this operation.
|
||||
return true
|
||||
if (target & (CAPTYPE_MASK | (1 << CAP_RECEIVER_CALL))) == (CAPTYPE_RECEIVER | (1 << CAP_RECEIVER_CALL)):
|
||||
// This is a call capability.
|
||||
reply_receiver = (Receiver *)protected_data
|
||||
reply_receiver->protected_only = !(target & (1 << CAP_RECEIVER_CALL_ASYNC))
|
||||
Capability r
|
||||
Capability *c0 = c[0]
|
||||
if ~(unsigned)c0->target & ~KERNEL_MASK:
|
||||
Capability *c0 = c->cap[0]
|
||||
if (unsigned)c0->target & ~KERNEL_MASK:
|
||||
// The call is not to a kernel capability.
|
||||
fill_cap (&r, protected_data, reply_receiver->reply_protected_data)
|
||||
c[0] = &r
|
||||
copy[0] = true
|
||||
bool ret = kernel_invoke ((unsigned)c0->target, c0->protected_data, d, c, copy, c0)
|
||||
c->cap[0] = &r
|
||||
c->copy[0] = true
|
||||
bool ret = c0->target->send_message (c0->protected_data, c)
|
||||
r.invalidate ()
|
||||
return ret
|
||||
else:
|
||||
// Kernel call: don't create actual capablities.
|
||||
reply = NULL
|
||||
return kernel_invoke ((unsigned)c0->target, c0->protected_data, d, c, copy, c0)
|
||||
kernel_invoke ((unsigned)c0->target, c0->protected_data, c, c0)
|
||||
return true
|
||||
if (target & (CAPTYPE_MASK | (1 << CAP_RECEIVER_REPLY))) == (CAPTYPE_RECEIVER | (1 << CAP_RECEIVER_REPLY)):
|
||||
// This is a reply capability.
|
||||
Receiver *r = (Receiver *)protected_data
|
||||
r->send_message (r->reply_protected_data, d, c, copy)
|
||||
r->send_message (r->reply_protected_data, c)
|
||||
while self->parent:
|
||||
self = self->parent
|
||||
while self->sibling_prev:
|
||||
@ -682,36 +721,42 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, unsigned d[
|
||||
self->sibling_next->invalidate ()
|
||||
self->invalidate ()
|
||||
return true
|
||||
reply = c[0]
|
||||
if d[0] == CAP_DEGRADE:
|
||||
reply_cap (target & d[1], protected_data)
|
||||
// It's a normal kernel capability; check permission.
|
||||
if !((1 << c->data[0]) & target & REQUEST_MASK):
|
||||
// You are not allowed to perform this operation.
|
||||
dbg_send (c->data[0], 5)
|
||||
schedule ()
|
||||
return true
|
||||
if c->data[0] == CAP_DEGRADE:
|
||||
reply_cap (target & (CAPTYPE_MASK | (c->data[1] & REQUEST_MASK)), protected_data)
|
||||
return true
|
||||
switch target & CAPTYPE_MASK:
|
||||
case CAPTYPE_RECEIVER:
|
||||
receiver_invoke (target, protected_data, c[1], d)
|
||||
receiver_invoke (target, protected_data, c)
|
||||
break
|
||||
case CAPTYPE_MEMORY:
|
||||
memory_invoke (target, protected_data, c[1], d[0], d[1])
|
||||
memory_invoke (target, protected_data, c)
|
||||
break
|
||||
case CAPTYPE_THREAD:
|
||||
thread_invoke (target, protected_data, c[1], d)
|
||||
thread_invoke (target, protected_data, c)
|
||||
break
|
||||
case CAPTYPE_PAGE:
|
||||
page_invoke (target, protected_data, c[1], copy[1], d)
|
||||
page_invoke (target, protected_data, c)
|
||||
break
|
||||
case CAPTYPE_CAPABILITY:
|
||||
capability_invoke (target, protected_data, c[1], d[0], d[1])
|
||||
capability_invoke (target, protected_data, c)
|
||||
break
|
||||
case CAPTYPE_CAPPAGE:
|
||||
page_invoke (target, protected_data, c[1], copy[1], d)
|
||||
break
|
||||
default:
|
||||
panic (0x99337744, "invalid capability type invoked")
|
||||
return true
|
||||
|
||||
bool Capability::invoke (unsigned data[4], Capability *cap[4], bool copy[4]):
|
||||
bool Capability::invoke (Context *c):
|
||||
if (unsigned)target & ~KERNEL_MASK:
|
||||
// This is not a kernel capability: send a message to the receiver.
|
||||
return target->send_message (protected_data, data, cap, copy)
|
||||
return target->send_message (protected_data, c)
|
||||
// This is a kernel capability. Use a function to allow optimized call capabilities.
|
||||
return kernel_invoke ((unsigned)target, protected_data, data, cap, copy, this)
|
||||
reply = c->cap[0]
|
||||
reply_receiver = NULL
|
||||
return kernel_invoke ((unsigned)target, protected_data, c, this)
|
||||
|
116
iris.h
116
iris.h
@ -22,6 +22,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PAGE_BITS (12)
|
||||
#define PAGE_SIZE (1 << PAGE_BITS)
|
||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
||||
|
||||
#define KERNEL_MASK 0xfff
|
||||
#define CAPTYPE_MASK 0xe00
|
||||
#define REQUEST_MASK (KERNEL_MASK & ~CAPTYPE_MASK)
|
||||
@ -98,12 +102,16 @@ extern "C" {
|
||||
/* Flag values for Page and Cappage objects. */
|
||||
/* A writable page can be written to. This flag can not be set while the frame is shared. */
|
||||
#define PAGE_FLAG_WRITABLE 1
|
||||
/* When paying, the memory's use is incremented if the page holds a frame. It cannot be lost. Frames are lost when the last payer forgets them. */
|
||||
/* When paying, the memory's use is incremented. If a frame is held, it cannot be lost. Frames are lost when the last payer forgets them. */
|
||||
#define PAGE_FLAG_PAYING 2
|
||||
/* Set if this page has a frame associated with it. This flag is automatically reset if the frame is lost because of payment problems. */
|
||||
#define PAGE_FLAG_FRAME 4
|
||||
/* This is a read-only flag, which is set if the Page is shared. */
|
||||
#define PAGE_FLAG_SHARED 8
|
||||
/* This is a read-only flag, saying if this is physical memory, which mustn't be freed. */
|
||||
#define PAGE_FLAG_PHYSICAL 0x10
|
||||
/* This is a read-only flag, saying if this is uncachable memory. */
|
||||
#define PAGE_FLAG_UNCACHED 0x20
|
||||
|
||||
#define CAP_CAPABILITY_GET 1
|
||||
#define CAP_CAPABILITY_ALL_RIGHTS 0x1ff
|
||||
@ -134,42 +142,70 @@ typedef struct Message
|
||||
|
||||
static int invoke (Capability target, Message *msg)
|
||||
{
|
||||
register int ret __asm__ ("v0");
|
||||
register unsigned v0 __asm__ ("v0") = target;
|
||||
register unsigned a0 __asm__ ("a0") = msg->cap[0];
|
||||
register unsigned a1 __asm__ ("a1") = msg->cap[1];
|
||||
register unsigned a2 __asm__ ("a2") = msg->cap[2];
|
||||
register unsigned a3 __asm__ ("a3") = msg->cap[3];
|
||||
register unsigned t0 __asm__ ("t0") = msg->data[0];
|
||||
register unsigned t1 __asm__ ("t1") = msg->data[1];
|
||||
register unsigned t2 __asm__ ("t2") = msg->data[2];
|
||||
register unsigned t3 __asm__ ("t3") = msg->data[3];
|
||||
__asm__ volatile ("syscall" : "+r" (v0), "=r" (a0), "=r" (a1), "=r" (a2), "=r" (a3), "=r" (t0), "=r" (t1), "=r" (t2), "=r" (t3));
|
||||
unsigned ret;
|
||||
__asm__ volatile ("lw $v0, %1\n"
|
||||
"\tlw $a3, %2\n"
|
||||
"\tlw $t0, 0($a3)\n"
|
||||
"\tlw $t1, 4($a3)\n"
|
||||
"\tlw $t2, 8($a3)\n"
|
||||
"\tlw $t3, 12($a3)\n"
|
||||
"\tlw $a0, 16($a3)\n"
|
||||
"\tlw $a1, 20($a3)\n"
|
||||
"\tlw $a2, 24($a3)\n"
|
||||
"\tlw $a3, 28($a3)\n"
|
||||
"\tsyscall\n"
|
||||
"\tmove %0, $v0"
|
||||
: "=r"(ret)
|
||||
: "m"(target), "m"(msg)
|
||||
: "v0", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wait (Message *msg)
|
||||
{
|
||||
__asm__ volatile ("li $v0, 2\n"
|
||||
"\tsyscall\n"
|
||||
"\tlw $v1, %0\n"
|
||||
"\tsw $t0, 0($v1)\n"
|
||||
"\tsw $t1, 4($v1)\n"
|
||||
"\tsw $t2, 8($v1)\n"
|
||||
"\tsw $t3, 12($v1)\n"
|
||||
"\tsw $a0, 16($v1)\n"
|
||||
"\tsw $a1, 20($v1)\n"
|
||||
"\tsw $a2, 24($v1)\n"
|
||||
"\tsw $a3, 28($v1)"
|
||||
:
|
||||
: "m"(msg)
|
||||
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
||||
}
|
||||
|
||||
static int call (Capability target, Message *msg)
|
||||
{
|
||||
register int ret __asm__ ("v0");
|
||||
register unsigned v0 __asm__ ("v0") = target;
|
||||
register unsigned a0 __asm__ ("a0") = msg->cap[0];
|
||||
register unsigned a1 __asm__ ("a1") = msg->cap[1];
|
||||
register unsigned a2 __asm__ ("a2") = msg->cap[2];
|
||||
register unsigned a3 __asm__ ("a3") = msg->cap[3];
|
||||
register unsigned t0 __asm__ ("t0") = msg->data[0];
|
||||
register unsigned t1 __asm__ ("t1") = msg->data[1];
|
||||
register unsigned t2 __asm__ ("t2") = msg->data[2];
|
||||
register unsigned t3 __asm__ ("t3") = msg->data[3];
|
||||
__asm__ volatile ("syscall" : "+r" (v0), "+r" (a0), "+r" (a1), "+r" (a2), "+r" (a3), "+r" (t0), "+r" (t1), "+r" (t2), "+r" (t3));
|
||||
msg->cap[0] = a0;
|
||||
msg->cap[1] = a1;
|
||||
msg->cap[2] = a2;
|
||||
msg->cap[3] = a3;
|
||||
msg->data[0] = t0;
|
||||
msg->data[1] = t1;
|
||||
msg->data[2] = t2;
|
||||
msg->data[3] = t3;
|
||||
return ret;
|
||||
unsigned ret;
|
||||
Capability t = cap_copy (target);
|
||||
__asm__ volatile ("lw $v0, %1\n"
|
||||
"\tlw $v1, %2\n"
|
||||
"\tlw $t0, 0($v1)\n"
|
||||
"\tlw $t1, 4($v1)\n"
|
||||
"\tlw $t2, 8($v1)\n"
|
||||
"\tlw $t3, 12($v1)\n"
|
||||
"\tlw $a0, 16($v1)\n"
|
||||
"\tlw $a1, 20($v1)\n"
|
||||
"\tlw $a2, 24($v1)\n"
|
||||
"\tlw $a3, 28($v1)\n"
|
||||
"\tsyscall\n"
|
||||
"\tmove %0, $v0\n"
|
||||
"\tsw $t0, 0($v1)\n"
|
||||
"\tsw $t1, 4($v1)\n"
|
||||
"\tsw $t2, 8($v1)\n"
|
||||
"\tsw $t3, 12($v1)\n"
|
||||
"\tsw $a0, 16($v1)\n"
|
||||
"\tsw $a1, 20($v1)\n"
|
||||
"\tsw $a2, 24($v1)\n"
|
||||
"\tsw $a3, 28($v1)"
|
||||
: "=r"(ret)
|
||||
: "m"(t), "m"(msg)
|
||||
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
||||
}
|
||||
|
||||
static int invoke_01 (Capability t, unsigned d)
|
||||
@ -330,7 +366,7 @@ static void unregister_interrupt (unsigned num)
|
||||
|
||||
static void alloc_physical (Capability page, unsigned address, int cachable)
|
||||
{
|
||||
invoke_12 (__my_thread, page, CAP_THREAD_ALLOC_PHYSICAL, address | (cachable ? 1 : 0));
|
||||
invoke_12 (__my_thread, page, CAP_THREAD_ALLOC_PHYSICAL, (address & PAGE_MASK) | (cachable ? 1 : 0));
|
||||
}
|
||||
|
||||
static int receiver_set_owner (Capability receiver, Capability owner)
|
||||
@ -370,27 +406,27 @@ static Capability memory_create (Capability memory, unsigned type)
|
||||
|
||||
static Capability memory_create_page (Capability memory)
|
||||
{
|
||||
return memory_create (memory, CAPTYPE_PAGE);
|
||||
return memory_create (memory, CAPTYPE_PAGE | REQUEST_MASK);
|
||||
}
|
||||
|
||||
static Capability memory_create_thread (Capability memory)
|
||||
{
|
||||
return memory_create (memory, CAPTYPE_THREAD);
|
||||
return memory_create (memory, CAPTYPE_THREAD | REQUEST_MASK);
|
||||
}
|
||||
|
||||
static Capability memory_create_receiver (Capability memory)
|
||||
{
|
||||
return memory_create (memory, CAPTYPE_RECEIVER);
|
||||
return memory_create (memory, CAPTYPE_RECEIVER | REQUEST_MASK);
|
||||
}
|
||||
|
||||
static Capability memory_create_memory (Capability memory)
|
||||
{
|
||||
return memory_create (memory, CAPTYPE_MEMORY);
|
||||
return memory_create (memory, CAPTYPE_MEMORY | REQUEST_MASK);
|
||||
}
|
||||
|
||||
static Capability memory_create_cappage (Capability memory)
|
||||
{
|
||||
return memory_create (memory, CAPTYPE_CAPPAGE);
|
||||
return memory_create (memory, CAPTYPE_CAPPAGE | REQUEST_MASK);
|
||||
}
|
||||
|
||||
static int memory_destroy (Capability memory, Capability target)
|
||||
@ -400,8 +436,10 @@ static int memory_destroy (Capability memory, Capability target)
|
||||
|
||||
/* TODO: #define CAP_MEMORY_LIST 3 */
|
||||
|
||||
static int memory_map (Capability memory, Capability page, unsigned address)
|
||||
static int memory_map (Capability memory, Capability page, unsigned address, int writable)
|
||||
{
|
||||
if (writable)
|
||||
address |= 1 << CAP_PAGE_WRITE;
|
||||
return invoke_12 (memory, page, CAP_MEMORY_MAP, address);
|
||||
}
|
||||
|
||||
|
26
kernel.hhp
26
kernel.hhp
@ -83,6 +83,19 @@ struct Message : public Object <Message>:
|
||||
unsigned data[4]
|
||||
unsigned protected_data
|
||||
|
||||
struct Capability : public Object <Capability>:
|
||||
struct Context:
|
||||
unsigned data[4]
|
||||
Capability *cap[4]
|
||||
bool copy[4]
|
||||
Receiver *target
|
||||
Capability *parent
|
||||
Capability *children
|
||||
Capability *sibling_prev, *sibling_next
|
||||
unsigned protected_data
|
||||
bool invoke (Context *c)
|
||||
void invalidate ()
|
||||
|
||||
struct Receiver : public Object <Receiver>:
|
||||
Thread *owner
|
||||
Receiver *prev_owned, *next_owned
|
||||
@ -93,16 +106,7 @@ struct Receiver : public Object <Receiver>:
|
||||
void own (Thread *o)
|
||||
void orphan ()
|
||||
bool try_deliver ()
|
||||
bool send_message (unsigned protected_data, unsigned data[4], Capability *cap[4], bool copy[4])
|
||||
|
||||
struct Capability : public Object <Capability>:
|
||||
Receiver *target
|
||||
Capability *parent
|
||||
Capability *children
|
||||
Capability *sibling_prev, *sibling_next
|
||||
unsigned protected_data
|
||||
bool invoke (unsigned data[4], Capability *cap[4], bool copy[4])
|
||||
void invalidate ()
|
||||
bool send_message (unsigned protected_data, Capability::Context *c)
|
||||
|
||||
struct ShareData :
|
||||
unsigned frame
|
||||
@ -194,7 +198,7 @@ void raw_pfree (unsigned page)
|
||||
|
||||
// Defined by architecture-specific files.
|
||||
void Thread_arch_init (Thread *thread)
|
||||
void Thread_arch_receive (Thread *thread, unsigned d[4], Capability *c[4])
|
||||
void Thread_arch_receive (Thread *thread, Capability::Context *c)
|
||||
void Thread_arch_receive_fail (Thread *thread)
|
||||
unsigned *Thread_arch_info (Thread *thread, unsigned num)
|
||||
void Memory_arch_init (Memory *mem)
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
load = 0x80000000
|
||||
|
||||
ARCH_CXXFLAGS = -DNUM_THREADS=2
|
||||
ARCH_CXXFLAGS = -DNUM_THREADS=1
|
||||
ARCH_CPPFLAGS = -Imips -Wa,-mips32
|
||||
CROSS = mipsel-linux-gnu-
|
||||
OBJDUMP = $(CROSS)objdump
|
||||
@ -40,9 +40,6 @@ $(boot_threads): TARGET_FLAGS = -I.
|
||||
uimage: kernel.raw.gz Makefile mips/Makefile.arch
|
||||
mkimage -A MIPS -O Linux -C gzip -a $(load) -e 0x$(shell /bin/sh -c '$(OBJDUMP) -t kernel | grep __start$$ | cut -b-8') -n "Shevek's kernel" -d $< $@ | sed -e 's/:/;/g'
|
||||
|
||||
elf.h: /usr/include/elf.h
|
||||
ln -s $< $@
|
||||
|
||||
%.o:%.S Makefile mips/Makefile.arch mips/arch.hh
|
||||
$(CC) $(CPPFLAGS) $(TARGET_FLAGS) -DKERNEL_STACK_SIZE=0x2000 -c $< -o $@
|
||||
|
||||
@ -56,4 +53,4 @@ kernel: mips/entry.o $(subst .cc,.o,$(kernel_sources)) mips/boot.o $(subst .cc,.
|
||||
%.gz: %
|
||||
gzip < $< > $@
|
||||
|
||||
ARCH_CLEAN_FILES = uimage kernel kernel.raw kernel.raw.gz elf.h $(boot_threads) mips/*.o
|
||||
ARCH_CLEAN_FILES = uimage kernel kernel.raw kernel.raw.gz $(boot_threads) mips/*.o
|
||||
|
@ -45,15 +45,15 @@ void Thread_arch_init (Thread *thread):
|
||||
thread->arch.k0 = 0
|
||||
thread->arch.k1 = 0
|
||||
|
||||
void Thread_arch_receive (Thread *thread, unsigned d[4], Capability *c[4]):
|
||||
thread->arch.a0 = (unsigned)c[0]
|
||||
thread->arch.a1 = (unsigned)c[1]
|
||||
thread->arch.a2 = (unsigned)c[2]
|
||||
thread->arch.a3 = (unsigned)c[3]
|
||||
thread->arch.t0 = d[0]
|
||||
thread->arch.t1 = d[1]
|
||||
thread->arch.t2 = d[2]
|
||||
thread->arch.t3 = d[3]
|
||||
void Thread_arch_receive (Thread *thread, Capability::Context *c):
|
||||
thread->arch.a0 = (unsigned)c->cap[0]
|
||||
thread->arch.a1 = (unsigned)c->cap[1]
|
||||
thread->arch.a2 = (unsigned)c->cap[2]
|
||||
thread->arch.a3 = (unsigned)c->cap[3]
|
||||
thread->arch.t0 = c->data[0]
|
||||
thread->arch.t1 = c->data[1]
|
||||
thread->arch.t2 = c->data[2]
|
||||
thread->arch.t3 = c->data[3]
|
||||
thread->arch.v0 = 1
|
||||
|
||||
void Thread_arch_receive_fail (Thread *thread):
|
||||
@ -222,10 +222,12 @@ static unsigned make_entry_lo (Page *page, bool write):
|
||||
if !page->data.frame:
|
||||
return 0
|
||||
unsigned flags
|
||||
if write:
|
||||
flags = 0x18 | 0x4 | 0x2
|
||||
else
|
||||
if page->data.flags & PAGE_FLAG_UNCACHED:
|
||||
flags = 0x10 | 0x2
|
||||
else:
|
||||
flags = 0x18 | 0x2
|
||||
if write:
|
||||
flags |= 0x4
|
||||
return ((page->data.frame & ~0x80000000) >> 6) | flags
|
||||
|
||||
bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write):
|
||||
@ -320,30 +322,36 @@ void Page_arch_update_mapping (Page *page):
|
||||
tlb_reset (p->mapping & ~1, as->arch.asid, t)
|
||||
|
||||
void arch_invoke ():
|
||||
Capability *target, *c[4]
|
||||
bool wait, copy[4]
|
||||
Capability *target
|
||||
bool wait
|
||||
Thread *caller = current
|
||||
target = caller->address_space->find_capability (current->arch.v0, &wait)
|
||||
if !target:
|
||||
// TODO: there must be no action here. This is just because the rest doesn't work yet.
|
||||
dbg_led (caller->arch.a0, caller->arch.a1, caller->arch.a2)
|
||||
dbg_sleep (1000)
|
||||
dbg_send (3, 2)
|
||||
schedule ()
|
||||
// Calling an invalid capability always fails.
|
||||
caller->arch.v0 = 0
|
||||
else:
|
||||
if wait:
|
||||
caller->wait ()
|
||||
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
|
||||
Capability::Context c
|
||||
c.cap[0] = caller->address_space->find_capability (caller->arch.a0, &c.copy[0])
|
||||
c.cap[1] = caller->address_space->find_capability (caller->arch.a1, &c.copy[1])
|
||||
c.cap[2] = caller->address_space->find_capability (caller->arch.a2, &c.copy[2])
|
||||
c.cap[3] = caller->address_space->find_capability (caller->arch.a3, &c.copy[3])
|
||||
c.data[0] = caller->arch.t0
|
||||
c.data[1] = caller->arch.t1
|
||||
c.data[2] = caller->arch.t2
|
||||
c.data[3] = caller->arch.t3
|
||||
caller->arch.v0 = target->invoke (&c) ? 1 : 0
|
||||
if !current:
|
||||
if caller != &idle && (caller->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING:
|
||||
current = caller
|
||||
else:
|
||||
schedule ()
|
||||
if !current:
|
||||
current = &idle
|
||||
if caller != current:
|
||||
if (Memory *)asids[current->address_space->arch.asid] != current->address_space:
|
||||
if asids[0]:
|
||||
|
@ -61,10 +61,6 @@
|
||||
#define CP0_DESAVE 31
|
||||
#endif
|
||||
|
||||
#define PAGE_BITS (12)
|
||||
#define PAGE_SIZE (1 << PAGE_BITS)
|
||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
||||
|
||||
// register save positions in Thread
|
||||
#define SAVE_PC (5 * 4)
|
||||
#define SAVE_SP (SAVE_PC + 4)
|
||||
|
@ -80,7 +80,7 @@ addr_100:
|
||||
addr_180:
|
||||
// General exception
|
||||
// Allow new exceptions to update EPC and friends.
|
||||
//mtc0 $zero, $CP0_STATUS
|
||||
mtc0 $zero, $CP0_STATUS
|
||||
sw $ra, -0xd88($zero)
|
||||
bal save_regs
|
||||
nop
|
||||
|
@ -178,10 +178,12 @@ static void init_threads ():
|
||||
if !stackpage || !mem->map (stackpage, 0x7ffff000, true):
|
||||
panic (0x13151719, "unable to map initial stack page")
|
||||
Receiver *recv = mem->alloc_receiver ()
|
||||
recv->owner = thread
|
||||
thread->receivers = recv
|
||||
thread->arch.a0 = mkcap (mem, CAPTYPE_RECEIVER | CAP_RECEIVER_ALL_RIGHTS, recv)
|
||||
thread->arch.a1 = mkcap (mem, CAPTYPE_THREAD | CAP_THREAD_ALL_PRIV_RIGHTS, thread)
|
||||
thread->arch.a2 = mkcap (mem, CAPTYPE_MEMORY | CAP_MEMORY_ALL_RIGHTS, mem)
|
||||
thread->arch.a3 = mkcap (mem, CAPTYPE_RECEIVER | CAP_RECEIVER_CALL, recv)
|
||||
thread->arch.a3 = mkcap (mem, CAPTYPE_RECEIVER | (1 << CAP_RECEIVER_CALL), recv)
|
||||
mem->pfree ((unsigned)pages)
|
||||
thread->flags = THREAD_FLAG_RUNNING | THREAD_FLAG_PRIV
|
||||
thread->schedule_next = NULL
|
||||
|
@ -30,6 +30,11 @@ Thread *tlb_refill ():
|
||||
cp0_get (CP0_ENTRY_HI, EntryHi)
|
||||
unsigned *t = directory[EntryHi >> 21]
|
||||
if !t:
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_send (a)
|
||||
cp0_get (CP0_BAD_V_ADDR, a)
|
||||
dbg_send (a)
|
||||
panic (0x99992222, "No page table")
|
||||
// - 2 instead of - 1 means reset bit 0
|
||||
unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
|
||||
@ -50,17 +55,18 @@ Thread *interrupt ():
|
||||
status &= ~(1 << (i + 8))
|
||||
// Send message to interrupt handler.
|
||||
if arch_interrupt_receiver[i]:
|
||||
unsigned data[4] = {0, 0, 0, 0}
|
||||
Capability *cap[4] = {NULL, NULL, NULL, NULL}
|
||||
bool copy[4] = {false, false, false, false}
|
||||
arch_interrupt_receiver[i]->send_message (i, data, cap, copy)
|
||||
Capability::Context c
|
||||
for unsigned j = 0; j < 4; ++j:
|
||||
c.data[j] = 0
|
||||
c.cap[j] = NULL
|
||||
c.copy[j] = false
|
||||
arch_interrupt_receiver[i]->send_message (i, &c)
|
||||
return current
|
||||
|
||||
/// A general exception has occurred.
|
||||
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.
|
||||
@ -70,6 +76,9 @@ Thread *exception ():
|
||||
panic (0x21223344, "TLB modification.")
|
||||
case 2:
|
||||
// TLB load or instruction fetch.
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_send (a)
|
||||
panic (0x31223344, "TLB load or instruction fetch.")
|
||||
case 3:
|
||||
// TLB store.
|
||||
@ -79,6 +88,9 @@ Thread *exception ():
|
||||
panic (0x51223344, "Address error load or instruction fetch.")
|
||||
case 5:
|
||||
// Address error store.
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_send (a, 16)
|
||||
panic (0x61223344, "Address error store.")
|
||||
case 6:
|
||||
// Bus error instruction fetch.
|
||||
@ -88,6 +100,7 @@ Thread *exception ():
|
||||
panic (0x81223344, "Bus error load or store.")
|
||||
case 8:
|
||||
// Syscall.
|
||||
current->pc += 4
|
||||
arch_invoke ()
|
||||
break
|
||||
case 9:
|
||||
|
40
schedule.ccp
40
schedule.ccp
@ -18,36 +18,43 @@
|
||||
|
||||
#include "kernel.hh"
|
||||
|
||||
static void run_thread (Thread *thread):
|
||||
thread->schedule_next = first_scheduled
|
||||
if thread->schedule_next:
|
||||
thread->schedule_next->schedule_prev = thread
|
||||
first_scheduled = thread
|
||||
|
||||
static void unrun_thread (Thread *thread):
|
||||
if current == thread:
|
||||
current = thread->schedule_next
|
||||
if thread->schedule_prev:
|
||||
thread->schedule_prev->schedule_next = thread->schedule_next
|
||||
else:
|
||||
first_scheduled = thread->schedule_next
|
||||
if thread->schedule_next:
|
||||
thread->schedule_next->schedule_prev = thread->schedule_prev
|
||||
|
||||
void Thread::run ():
|
||||
if flags & THREAD_FLAG_RUNNING:
|
||||
return
|
||||
flags |= THREAD_FLAG_RUNNING
|
||||
if flags & THREAD_FLAG_WAITING:
|
||||
return
|
||||
schedule_next = first_scheduled
|
||||
if schedule_next:
|
||||
schedule_next->schedule_prev = this
|
||||
first_scheduled = this
|
||||
run_thread (this)
|
||||
|
||||
void Thread::unrun ():
|
||||
if !(flags & THREAD_FLAG_RUNNING):
|
||||
return
|
||||
flags &= ~THREAD_FLAG_RUNNING
|
||||
if !(flags & THREAD_FLAG_WAITING):
|
||||
if current == this:
|
||||
current = schedule_next
|
||||
if schedule_prev:
|
||||
schedule_prev->schedule_next = schedule_next
|
||||
else:
|
||||
first_scheduled = schedule_next
|
||||
if schedule_next:
|
||||
schedule_next->schedule_prev = schedule_prev
|
||||
if flags & THREAD_FLAG_WAITING:
|
||||
return
|
||||
unrun_thread (this)
|
||||
|
||||
void Thread::wait ():
|
||||
if flags & THREAD_FLAG_WAITING:
|
||||
return
|
||||
if flags & THREAD_FLAG_RUNNING:
|
||||
unrun ()
|
||||
unrun_thread (this)
|
||||
flags |= THREAD_FLAG_WAITING
|
||||
// Try to receive a message from a Receiver immediately.
|
||||
for Receiver *r = receivers; r; r = r->next_owned:
|
||||
@ -59,8 +66,7 @@ void Thread::unwait ():
|
||||
return
|
||||
flags &= ~THREAD_FLAG_WAITING
|
||||
if flags & THREAD_FLAG_RUNNING:
|
||||
flags &= ~THREAD_FLAG_RUNNING
|
||||
run ()
|
||||
run_thread (this)
|
||||
|
||||
void schedule ():
|
||||
Thread *old = current
|
||||
@ -68,5 +74,3 @@ void schedule ():
|
||||
current = current->schedule_next
|
||||
if !current:
|
||||
current = first_scheduled
|
||||
if !current:
|
||||
current = &idle
|
||||
|
Loading…
Reference in New Issue
Block a user