Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 4054 → Rev 4055

/branches/dd/kernel/kernel.config
File deleted
/branches/dd/kernel/test/avltree/avltree1.def
1,6 → 1,6
{
"avltree1",
"Test Avl tree operations",
"Test AVL tree operations",
&test_avltree1,
true
},
/branches/dd/kernel/test/avltree/avltree1.c
48,7 → 48,8
 
static int test_tree_balance(avltree_node_t *node);
static avltree_node_t *test_tree_parents(avltree_node_t *node);
static void print_tree_structure_flat (avltree_node_t *node, int level);
static void print_tree_structure_flat (avltree_node_t *node, int level)
__attribute__ ((used));
static avltree_node_t *alloc_avltree_node(void);
 
static avltree_node_t *test_tree_parents(avltree_node_t *node)
61,14 → 62,15
if (node->lft) {
tmp = test_tree_parents(node->lft);
if (tmp != node) {
printf("Bad parent pointer key: %d, address: %p\n",
tmp->key, node->lft);
printf("Bad parent pointer key: %" PRIu64
", address: %p\n", tmp->key, node->lft);
}
}
if (node->rgt) {
tmp = test_tree_parents(node->rgt);
if (tmp != node) {
printf("Bad parent pointer key: %d, address: %p\n",
printf("Bad parent pointer key: %" PRIu64
", address: %p\n",
tmp->key,node->rgt);
}
}
94,7 → 96,8
* Prints the structure of the node, which is level levels from the top of the
* tree.
*/
static void print_tree_structure_flat(avltree_node_t *node, int level)
static void
print_tree_structure_flat(avltree_node_t *node, int level)
{
/*
* You can set the maximum level as high as you like.
109,7 → 112,7
if (node == NULL)
return;
 
printf("%d[%d]", node->key, node->balance);
printf("%" PRIu64 "[%" PRIu8 "]", node->key, node->balance);
if (node->lft != NULL || node->rgt != NULL) {
printf("(");
 
130,6 → 133,7
for (i = 0; i < NODE_COUNT - 1; i++) {
avltree_nodes[i].par = &avltree_nodes[i + 1];
}
avltree_nodes[i].par = NULL;
/*
* Node keys which will be used for insertion. Up to NODE_COUNT size of
169,7 → 173,6
for (i = 21; i < NODE_COUNT; i++)
avltree_nodes[i].key = i * 3;
avltree_nodes[i].par = NULL;
first_free_node = &avltree_nodes[0];
}
 
191,7 → 194,7
avltree_create(tree);
if (!quiet)
printf("Inserting %d nodes...", node_count);
printf("Inserting %" PRIc " nodes...", node_count);
 
for (i = 0; i < node_count; i++) {
newnode = alloc_avltree_node();
/branches/dd/kernel/test/synch/rwlock3.c
45,14 → 45,14
thread_detach(THREAD);
if (!sh_quiet)
printf("cpu%d, tid %llu: trying to lock rwlock for reading....\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 ": trying to lock rwlock for reading....\n", CPU->id, THREAD->tid);
rwlock_read_lock(&rwlock);
rwlock_read_unlock(&rwlock);
if (!sh_quiet) {
printf("cpu%d, tid %llu: success\n", CPU->id, THREAD->tid);
printf("cpu%d, tid %llu: trying to lock rwlock for writing....\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 ": success\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 ": trying to lock rwlock for writing....\n", CPU->id, THREAD->tid);
}
 
rwlock_write_lock(&rwlock);
59,7 → 59,7
rwlock_write_unlock(&rwlock);
if (!sh_quiet)
printf("cpu%d, tid %llu: success\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 ": success\n", CPU->id, THREAD->tid);
atomic_dec(&thread_count);
}
88,7 → 88,7
while (atomic_get(&thread_count) > 0) {
if (!quiet)
printf("Threads left: %d\n", atomic_get(&thread_count));
printf("Threads left: %ld\n", atomic_get(&thread_count));
thread_sleep(1);
}
/branches/dd/kernel/test/synch/rwlock4.c
60,7 → 60,7
 
spinlock_lock(&rw_lock);
rc = seed % max;
seed = (((seed<<2) ^ (seed>>2)) * 487) + rc;
seed = (((seed << 2) ^ (seed >> 2)) * 487) + rc;
spinlock_unlock(&rw_lock);
return rc;
}
74,18 → 74,18
to = random(40000);
if (!sh_quiet)
printf("cpu%d, tid %llu w+ (%d)\n", CPU->id, THREAD->tid, to);
printf("cpu%u, tid %" PRIu64 " w+ (%d)\n", CPU->id, THREAD->tid, to);
rc = rwlock_write_lock_timeout(&rwlock, to);
if (SYNCH_FAILED(rc)) {
if (!sh_quiet)
printf("cpu%d, tid %llu w!\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 " w!\n", CPU->id, THREAD->tid);
atomic_dec(&thread_count);
return;
}
if (!sh_quiet)
printf("cpu%d, tid %llu w=\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 " w=\n", CPU->id, THREAD->tid);
 
if (rwlock.readers_in) {
if (!sh_quiet)
106,7 → 106,7
rwlock_write_unlock(&rwlock);
if (!sh_quiet)
printf("cpu%d, tid %llu w-\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 " w-\n", CPU->id, THREAD->tid);
atomic_dec(&thread_count);
}
 
119,24 → 119,24
to = random(2000);
if (!sh_quiet)
printf("cpu%d, tid %llu r+ (%d)\n", CPU->id, THREAD->tid, to);
printf("cpu%u, tid %" PRIu64 " r+ (%d)\n", CPU->id, THREAD->tid, to);
rc = rwlock_read_lock_timeout(&rwlock, to);
if (SYNCH_FAILED(rc)) {
if (!sh_quiet)
printf("cpu%d, tid %llu r!\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 " r!\n", CPU->id, THREAD->tid);
atomic_dec(&thread_count);
return;
}
if (!sh_quiet)
printf("cpu%d, tid %llu r=\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 " r=\n", CPU->id, THREAD->tid);
thread_usleep(30000);
rwlock_read_unlock(&rwlock);
if (!sh_quiet)
printf("cpu%d, tid %llu r-\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 " r-\n", CPU->id, THREAD->tid);
atomic_dec(&thread_count);
}
 
159,8 → 159,8
context_save(&ctx);
if (!quiet) {
printf("sp=%#x, readers_in=%d\n", ctx.sp, rwlock.readers_in);
printf("Creating %d readers\n", rd);
printf("sp=%#x, readers_in=%" PRIc "\n", ctx.sp, rwlock.readers_in);
printf("Creating %" PRIu32 " readers\n", rd);
}
for (i = 0; i < rd; i++) {
168,11 → 168,11
if (thrd)
thread_ready(thrd);
else if (!quiet)
printf("Could not create reader %d\n", i);
printf("Could not create reader %" PRIu32 "\n", i);
}
 
if (!quiet)
printf("Creating %d writers\n", wr);
printf("Creating %" PRIu32 " writers\n", wr);
for (i = 0; i < wr; i++) {
thrd = thread_create(writer, NULL, TASK, 0, "writer", false);
179,7 → 179,7
if (thrd)
thread_ready(thrd);
else if (!quiet)
printf("Could not create writer %d\n", i);
printf("Could not create writer %" PRIu32 "\n", i);
}
thread_usleep(20000);
187,7 → 187,7
while (atomic_get(&thread_count) > 0) {
if (!quiet)
printf("Threads left: %d\n", atomic_get(&thread_count));
printf("Threads left: %ld\n", atomic_get(&thread_count));
thread_sleep(1);
}
/branches/dd/kernel/test/synch/semaphore2.c
53,7 → 53,7
 
spinlock_lock(&sem_lock);
rc = seed % max;
seed = (((seed<<2) ^ (seed>>2)) * 487) + rc;
seed = (((seed << 2) ^ (seed >> 2)) * 487) + rc;
spinlock_unlock(&sem_lock);
return rc;
}
67,18 → 67,18
waitq_sleep(&can_start);
to = random(20000);
printf("cpu%d, tid %llu down+ (%d)\n", CPU->id, THREAD->tid, to);
printf("cpu%u, tid %" PRIu64 " down+ (%d)\n", CPU->id, THREAD->tid, to);
rc = semaphore_down_timeout(&sem, to);
if (SYNCH_FAILED(rc)) {
printf("cpu%d, tid %llu down!\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 " down!\n", CPU->id, THREAD->tid);
return;
}
printf("cpu%d, tid %llu down=\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 " down=\n", CPU->id, THREAD->tid);
thread_usleep(random(30000));
semaphore_up(&sem);
printf("cpu%d, tid %llu up\n", CPU->id, THREAD->tid);
printf("cpu%u, tid %" PRIu64 " up\n", CPU->id, THREAD->tid);
}
 
char * test_semaphore2(bool quiet)
91,7 → 91,7
thread_t *thrd;
k = random(7) + 1;
printf("Creating %d consumers\n", k);
printf("Creating %" PRIu32 " consumers\n", k);
for (i = 0; i < k; i++) {
thrd = thread_create(consumer, NULL, TASK, 0, "consumer", false);
if (thrd)
/branches/dd/kernel/test/synch/rwlock5.c
108,7 → 108,7
waitq_wakeup(&can_start, WAKEUP_ALL);
while ((items_read.count != readers) || (items_written.count != writers)) {
printf("%zd readers remaining, %zd writers remaining, readers_in=%zd\n", readers - items_read.count, writers - items_written.count, rwlock.readers_in);
printf("%d readers remaining, %d writers remaining, readers_in=%d\n", readers - items_read.count, writers - items_written.count, rwlock.readers_in);
thread_usleep(100000);
}
}
/branches/dd/kernel/test/test.h
36,12 → 36,13
#define KERN_TEST_H_
 
#include <arch/types.h>
#include <typedefs.h>
 
typedef char * (* test_entry_t)(bool);
typedef char *(*test_entry_t)(bool);
 
typedef struct {
char * name;
char * desc;
char *name;
char *desc;
test_entry_t entry;
bool safe;
} test_t;
/branches/dd/kernel/test/debug/mips1_skip.c
0,0 → 1,34
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <test.h>
 
char *test_mips1(bool quiet)
{
return NULL;
}
/branches/dd/kernel/test/debug/mips1.def
1,4 → 1,3
#ifdef mips32
{
"mips1",
"MIPS debug test",
5,4 → 4,3
&test_mips1,
false
},
#endif
/branches/dd/kernel/test/debug/mips1.c
25,8 → 25,6
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef mips32
 
#include <print.h>
#include <debug.h>
38,10 → 36,10
 
#include <arch.h>
 
char * test_mips1(bool quiet)
char *test_mips1(bool quiet)
{
if (!quiet)
printf("You should enter kconsole debug mode now.\n");
printf("If kconsole is compiled in, you should enter debug mode now.\n");
asm volatile (
"break\n"
49,5 → 47,3
return "Back from debug mode";
}
 
#endif
/branches/dd/kernel/test/thread/thread1.c
48,7 → 48,7
 
while (atomic_get(&finish)) {
if (!sh_quiet)
printf("%llu ", THREAD->tid);
printf("%" PRIu64 " ", THREAD->tid);
thread_usleep(100000);
}
atomic_inc(&threads_finished);
/branches/dd/kernel/test/mm/purge1.def
1,4 → 1,3
#ifdef ia64
{
"purge1",
"Itanium TLB purge test",
5,4 → 4,3
&test_purge1,
true
},
#endif
/branches/dd/kernel/test/mm/falloc2.c
55,10 → 55,10
uint8_t val = THREAD->tid % THREADS;
index_t k;
uintptr_t * frames = (uintptr_t *) malloc(MAX_FRAMES * sizeof(uintptr_t), FRAME_ATOMIC);
void **frames = (void **) malloc(MAX_FRAMES * sizeof(void *), FRAME_ATOMIC);
if (frames == NULL) {
if (!sh_quiet)
printf("Thread #%llu (cpu%d): Unable to allocate frames\n", THREAD->tid, CPU->id);
printf("Thread #%" PRIu64 " (cpu%u): Unable to allocate frames\n", THREAD->tid, CPU->id);
atomic_inc(&thread_fail);
atomic_dec(&thread_count);
return;
69,11 → 69,11
for (run = 0; run < THREAD_RUNS; run++) {
for (order = 0; order <= MAX_ORDER; order++) {
if (!sh_quiet)
printf("Thread #%llu (cpu%d): Allocating %d frames blocks ... \n", THREAD->tid, CPU->id, 1 << order);
printf("Thread #%" PRIu64 " (cpu%u): Allocating %d frames blocks ... \n", THREAD->tid, CPU->id, 1 << order);
allocated = 0;
for (i = 0; i < (MAX_FRAMES >> order); i++) {
frames[allocated] = (uintptr_t)frame_alloc(order, FRAME_ATOMIC | FRAME_KA);
frames[allocated] = frame_alloc(order, FRAME_ATOMIC | FRAME_KA);
if (frames[allocated]) {
memsetb(frames[allocated], FRAME_SIZE << order, val);
allocated++;
82,16 → 82,16
}
if (!sh_quiet)
printf("Thread #%llu (cpu%d): %d blocks allocated.\n", THREAD->tid, CPU->id, allocated);
printf("Thread #%" PRIu64 " (cpu%u): %d blocks allocated.\n", THREAD->tid, CPU->id, allocated);
if (!sh_quiet)
printf("Thread #%llu (cpu%d): Deallocating ... \n", THREAD->tid, CPU->id);
printf("Thread #%" PRIu64 " (cpu%u): Deallocating ... \n", THREAD->tid, CPU->id);
for (i = 0; i < allocated; i++) {
for (k = 0; k <= (((index_t) FRAME_SIZE << order) - 1); k++) {
if (((uint8_t *) frames[i])[k] != val) {
if (!sh_quiet)
printf("Thread #%llu (cpu%d): Unexpected data (%d) in block %p offset %#zx\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k);
printf("Thread #%" PRIu64 " (cpu%u): Unexpected data (%c) in block %p offset %#" PRIi "\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k);
atomic_inc(&thread_fail);
goto cleanup;
}
100,7 → 100,7
}
if (!sh_quiet)
printf("Thread #%llu (cpu%d): Finished run.\n", THREAD->tid, CPU->id);
printf("Thread #%" PRIu64 " (cpu%u): Finished run.\n", THREAD->tid, CPU->id);
}
}
 
108,7 → 108,7
free(frames);
if (!sh_quiet)
printf("Thread #%llu (cpu%d): Exiting\n", THREAD->tid, CPU->id);
printf("Thread #%" PRIu64 " (cpu%u): Exiting\n", THREAD->tid, CPU->id);
atomic_dec(&thread_count);
}
 
124,7 → 124,7
thread_t * thrd = thread_create(falloc, NULL, TASK, 0, "falloc", false);
if (!thrd) {
if (!quiet)
printf("Could not create thread %d\n", i);
printf("Could not create thread %u\n", i);
break;
}
thread_ready(thrd);
132,7 → 132,7
while (atomic_get(&thread_count) > 0) {
if (!quiet)
printf("Threads left: %d\n", atomic_get(&thread_count));
printf("Threads left: %ld\n", atomic_get(&thread_count));
thread_sleep(1);
}
/branches/dd/kernel/test/mm/slab1.c
53,7 → 53,7
for (i = 0; i < count; i++) {
data[i] = slab_alloc(cache, 0);
memsetb((uintptr_t) data[i], size, 0);
memsetb(data[i], size, 0);
}
if (!quiet) {
71,7 → 71,7
for (i = 0; i < count; i++) {
data[i] = slab_alloc(cache, 0);
memsetb((uintptr_t) data[i], size, 0);
memsetb(data[i], size, 0);
}
if (!quiet) {
89,7 → 89,7
for (i = count / 2; i < count; i++) {
data[i] = slab_alloc(cache, 0);
memsetb((uintptr_t) data[i], size, 0);
memsetb(data[i], size, 0);
}
if (!quiet) {
137,7 → 137,7
thread_detach(THREAD);
if (!sh_quiet)
printf("Starting thread #%llu...\n", THREAD->tid);
printf("Starting thread #%" PRIu64 "...\n", THREAD->tid);
for (j = 0; j < 10; j++) {
for (i = 0; i < THR_MEM_COUNT; i++)
151,7 → 151,7
}
if (!sh_quiet)
printf("Thread #%llu finished\n", THREAD->tid);
printf("Thread #%" PRIu64 " finished\n", THREAD->tid);
semaphore_up(&thr_sem);
}
/branches/dd/kernel/test/mm/purge1.c
26,8 → 26,6
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#ifdef ia64
 
#include <print.h>
#include <test.h>
#include <mm/page.h>
47,10 → 45,10
tlb_entry_t entryd;
int i;
entryd.word[0] = 0;
entryd.word[1] = 0;
entryd.p = true; /* present */
entryd.ma = MA_WRITEBACK;
entryd.a = true; /* already accessed */
77,11 → 75,9
dtc_mapping_insert(0 + i * (1 << PAGE_WIDTH), 9, entryd);
}
tlb_invalidate_pages(8,0x0c000,14);
tlb_invalidate_pages(8, 0x0c000, 14);
/*tlb_invalidate_all();*/
/* tlb_invalidate_all(); */
return NULL;
}
 
#endif
/branches/dd/kernel/test/mm/slab2.c
68,8 → 68,8
slab_free(cache2, data2);
break;
}
memsetb((uintptr_t) data1, ITEM_SIZE, 0);
memsetb((uintptr_t) data2, ITEM_SIZE, 0);
memsetb(data1, ITEM_SIZE, 0);
memsetb(data2, ITEM_SIZE, 0);
*((void **) data1) = olddata1;
*((void **) data2) = olddata2;
olddata1 = data1;
100,7 → 100,7
printf("Incorrect memory size - use another test.");
return;
}
memsetb((uintptr_t) data1, ITEM_SIZE, 0);
memsetb(data1, ITEM_SIZE, 0);
*((void **) data1) = olddata1;
olddata1 = data1;
}
108,7 → 108,7
data1 = slab_alloc(cache1, FRAME_ATOMIC);
if (!data1)
break;
memsetb((uintptr_t) data1, ITEM_SIZE, 0);
memsetb(data1, ITEM_SIZE, 0);
*((void **) data1) = olddata1;
olddata1 = data1;
}
150,11 → 150,11
mutex_unlock(&starter_mutex);
if (!sh_quiet)
printf("Starting thread #%llu...\n",THREAD->tid);
printf("Starting thread #%" PRIu64 "...\n", THREAD->tid);
 
/* Alloc all */
if (!sh_quiet)
printf("Thread #%llu allocating...\n", THREAD->tid);
printf("Thread #%" PRIu64 " allocating...\n", THREAD->tid);
while (1) {
/* Call with atomic to detect end of memory */
166,7 → 166,7
}
if (!sh_quiet)
printf("Thread #%llu releasing...\n", THREAD->tid);
printf("Thread #%" PRIu64 " releasing...\n", THREAD->tid);
while (data) {
new = *((void **)data);
176,7 → 176,7
}
if (!sh_quiet)
printf("Thread #%llu allocating...\n", THREAD->tid);
printf("Thread #%" PRIu64 " allocating...\n", THREAD->tid);
while (1) {
/* Call with atomic to detect end of memory */
188,7 → 188,7
}
if (!sh_quiet)
printf("Thread #%llu releasing...\n", THREAD->tid);
printf("Thread #%" PRIu64 " releasing...\n", THREAD->tid);
while (data) {
new = *((void **)data);
198,7 → 198,7
}
if (!sh_quiet)
printf("Thread #%llu finished\n", THREAD->tid);
printf("Thread #%" PRIu64 " finished\n", THREAD->tid);
slab_print_list();
semaphore_up(&thr_sem);
216,7 → 216,7
printf("Running stress test with size %d\n", size);
condvar_initialize(&thread_starter);
mutex_initialize(&starter_mutex);
mutex_initialize(&starter_mutex, MUTEX_PASSIVE);
 
thr_cache = slab_cache_create("thread_cache", size, 0, NULL, NULL, 0);
semaphore_initialize(&thr_sem,0);
/branches/dd/kernel/test/mm/purge1_skip.c
0,0 → 1,34
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <test.h>
 
char *test_purge1(bool quiet)
{
return NULL;
}
/branches/dd/kernel/test/fpu/fpu1.c
File deleted
/branches/dd/kernel/test/fpu/fpu1_ia64.c
0,0 → 1,179
/*
* Copyright (c) 2005 Jakub Vana
* Copyright (c) 2005 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <print.h>
#include <debug.h>
 
#include <test.h>
#include <atomic.h>
#include <proc/thread.h>
 
#include <arch.h>
#include <arch/arch.h>
 
 
#define THREADS 150
#define ATTEMPTS 100
 
#define E_10e8 271828182
#define PI_10e8 3141592
 
static inline long double sqrt(long double a)
{
long double x = 1;
long double lx = 0;
if (a < 0.00000000000000001)
return 0;
while (x != lx) {
lx = x;
x = (x + (a / x)) / 2;
}
return x;
}
 
static atomic_t threads_ok;
static atomic_t threads_fault;
static waitq_t can_start;
static bool sh_quiet;
 
static void e(void *data)
{
int i;
double e, d, le, f;
thread_detach(THREAD);
waitq_sleep(&can_start);
for (i = 0; i<ATTEMPTS; i++) {
le = -1;
e = 0;
f = 1;
for (d = 1; e != le; d *= f, f += 1) {
le = e;
e = e + 1 / d;
}
if ((int) (100000000 * e) != E_10e8) {
if (!sh_quiet)
printf("tid%" PRIu64 ": e*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8);
atomic_inc(&threads_fault);
break;
}
}
atomic_inc(&threads_ok);
}
 
static void pi(void *data)
{
int i;
double lpi, pi;
double n, ab, ad;
thread_detach(THREAD);
waitq_sleep(&can_start);
for (i = 0; i < ATTEMPTS; i++) {
lpi = -1;
pi = 0;
for (n = 2, ab = sqrt(2); lpi != pi; n *= 2, ab = ad) {
double sc, cd;
sc = sqrt(1 - (ab * ab / 4));
cd = 1 - sc;
ad = sqrt(ab * ab / 4 + cd * cd);
lpi = pi;
pi = 2 * n * ad;
}
if ((int) (1000000 * pi) != PI_10e8) {
if (!sh_quiet)
printf("tid%" PRIu64 ": pi*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (1000000 * pi), (unative_t) (PI_10e8 / 100));
atomic_inc(&threads_fault);
break;
}
}
atomic_inc(&threads_ok);
}
 
char * test_fpu1(bool quiet)
{
unsigned int i, total = 0;
sh_quiet = quiet;
waitq_initialize(&can_start);
atomic_set(&threads_ok, 0);
atomic_set(&threads_fault, 0);
if (!quiet)
printf("Creating %u threads... ", 2 * THREADS);
for (i = 0; i < THREADS; i++) {
thread_t *t;
if (!(t = thread_create(e, NULL, TASK, 0, "e", false))) {
if (!quiet)
printf("could not create thread %u\n", 2 * i);
break;
}
thread_ready(t);
total++;
if (!(t = thread_create(pi, NULL, TASK, 0, "pi", false))) {
if (!quiet)
printf("could not create thread %u\n", 2 * i + 1);
break;
}
thread_ready(t);
total++;
}
if (!quiet)
printf("ok\n");
thread_sleep(1);
waitq_wakeup(&can_start, WAKEUP_ALL);
while (atomic_get(&threads_ok) != (long) total) {
if (!quiet)
printf("Threads left: %d\n", total - atomic_get(&threads_ok));
thread_sleep(1);
}
if (atomic_get(&threads_fault) == 0)
return NULL;
return "Test failed";
}
/branches/dd/kernel/test/fpu/fpu1_x86.c
0,0 → 1,176
/*
* Copyright (c) 2005 Jakub Vana
* Copyright (c) 2005 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <print.h>
#include <debug.h>
 
#include <test.h>
#include <atomic.h>
#include <proc/thread.h>
 
#include <arch.h>
#include <arch/arch.h>
 
 
#define THREADS 150
#define ATTEMPTS 100
 
#define E_10e8 271828182
#define PI_10e8 314159265
 
static inline double sqrt(double x)
{
double v;
asm (
"fsqrt\n"
: "=t" (v)
: "0" (x)
);
return v;
}
 
static atomic_t threads_ok;
static atomic_t threads_fault;
static waitq_t can_start;
static bool sh_quiet;
 
static void e(void *data)
{
int i;
double e, d, le, f;
thread_detach(THREAD);
waitq_sleep(&can_start);
for (i = 0; i<ATTEMPTS; i++) {
le = -1;
e = 0;
f = 1;
for (d = 1; e != le; d *= f, f += 1) {
le = e;
e = e + 1 / d;
}
if ((int) (100000000 * e) != E_10e8) {
if (!sh_quiet)
printf("tid%" PRIu64 ": e*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8);
atomic_inc(&threads_fault);
break;
}
}
atomic_inc(&threads_ok);
}
 
static void pi(void *data)
{
int i;
double lpi, pi;
double n, ab, ad;
thread_detach(THREAD);
waitq_sleep(&can_start);
for (i = 0; i < ATTEMPTS; i++) {
lpi = -1;
pi = 0;
for (n = 2, ab = sqrt(2); lpi != pi; n *= 2, ab = ad) {
double sc, cd;
sc = sqrt(1 - (ab * ab / 4));
cd = 1 - sc;
ad = sqrt(ab * ab / 4 + cd * cd);
lpi = pi;
pi = 2 * n * ad;
}
if ((int) (100000000 * pi) != PI_10e8) {
if (!sh_quiet)
printf("tid%" PRIu64 ": pi*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * pi), (unative_t) PI_10e8);
atomic_inc(&threads_fault);
break;
}
}
atomic_inc(&threads_ok);
}
 
char * test_fpu1(bool quiet)
{
unsigned int i, total = 0;
sh_quiet = quiet;
waitq_initialize(&can_start);
atomic_set(&threads_ok, 0);
atomic_set(&threads_fault, 0);
if (!quiet)
printf("Creating %u threads... ", 2 * THREADS);
for (i = 0; i < THREADS; i++) {
thread_t *t;
if (!(t = thread_create(e, NULL, TASK, 0, "e", false))) {
if (!quiet)
printf("could not create thread %u\n", 2 * i);
break;
}
thread_ready(t);
total++;
if (!(t = thread_create(pi, NULL, TASK, 0, "pi", false))) {
if (!quiet)
printf("could not create thread %u\n", 2 * i + 1);
break;
}
thread_ready(t);
total++;
}
if (!quiet)
printf("ok\n");
thread_sleep(1);
waitq_wakeup(&can_start, WAKEUP_ALL);
while (atomic_get(&threads_ok) != (long) total) {
if (!quiet)
printf("Threads left: %d\n", total - atomic_get(&threads_ok));
thread_sleep(1);
}
if (atomic_get(&threads_fault) == 0)
return NULL;
return "Test failed";
}
/branches/dd/kernel/test/fpu/mips2_skip.c
0,0 → 1,34
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <test.h>
 
char * test_mips2(bool quiet)
{
return NULL;
}
/branches/dd/kernel/test/fpu/fpu1_skip.c
0,0 → 1,34
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <test.h>
 
char * test_fpu1(bool quiet)
{
return NULL;
}
/branches/dd/kernel/test/fpu/sse1_skip.c
0,0 → 1,34
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <test.h>
 
char * test_sse1(bool quiet)
{
return NULL;
}
/branches/dd/kernel/test/fpu/mips2.def
1,4 → 1,3
#ifdef mips32
{
"mips2",
"MIPS FPU test",
5,4 → 4,3
&test_mips2,
true
},
#endif
/branches/dd/kernel/test/fpu/fpu1.def
1,4 → 1,3
#if (defined(ia32) || defined(amd64) || defined(ia64) || defined(ia32xen))
{
"fpu1",
"Intel FPU test",
5,4 → 4,3
&test_fpu1,
true
},
#endif
/branches/dd/kernel/test/fpu/sse1.def
1,4 → 1,3
#if (defined(ia32) || defined(amd64) || defined(ia32xen))
{
"sse1",
"Intel SEE test",
5,4 → 4,3
&test_sse1,
true
},
#endif
/branches/dd/kernel/test/fpu/mips2.c
26,8 → 26,6
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#ifdef mips32
 
#include <print.h>
#include <debug.h>
 
38,9 → 36,9
 
#include <arch.h>
 
#define THREADS 50
#define DELAY 10000L
#define ATTEMPTS 5
#define THREADS 50
#define DELAY 10000L
#define ATTEMPTS 5
 
static atomic_t threads_ok;
static atomic_t threads_fault;
56,7 → 54,7
thread_detach(THREAD);
waitq_sleep(&can_start);
 
for (i = 0; i < ATTEMPTS; i++) {
asm volatile (
"mtc1 %0,$1"
72,7 → 70,7
if (arg != after_arg) {
if (!sh_quiet)
printf("General reg tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg);
printf("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg);
atomic_inc(&threads_fault);
break;
}
89,13 → 87,13
thread_detach(THREAD);
waitq_sleep(&can_start);
 
for (i = 0; i < ATTEMPTS; i++) {
asm volatile (
"mtc1 %0,$1"
: "=r" (arg)
);
 
scheduler();
asm volatile (
"mfc1 %0,$1"
104,7 → 102,7
if (arg != after_arg) {
if (!sh_quiet)
printf("General reg tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg);
printf("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg);
atomic_inc(&threads_fault);
break;
}
123,14 → 121,14
atomic_set(&threads_fault, 0);
if (!quiet)
printf("Creating %d threads... ", 2 * THREADS);
 
printf("Creating %u threads... ", 2 * THREADS);
for (i = 0; i < THREADS; i++) {
thread_t *t;
if (!(t = thread_create(testit1, (void *) ((unative_t) 2 * i), TASK, 0, "testit1", false))) {
if (!quiet)
printf("could not create thread %d\n", 2 * i);
printf("could not create thread %u\n", 2 * i);
break;
}
thread_ready(t);
138,7 → 136,7
if (!(t = thread_create(testit2, (void *) ((unative_t) 2 * i + 1), TASK, 0, "testit2", false))) {
if (!quiet)
printf("could not create thread %d\n", 2 * i + 1);
printf("could not create thread %u\n", 2 * i + 1);
break;
}
thread_ready(t);
162,5 → 160,3
return "Test failed";
}
 
#endif
/branches/dd/kernel/test/fpu/sse1.c
26,8 → 26,6
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#if (defined(ia32) || defined(amd64) || defined(ia32xen))
 
#include <print.h>
#include <debug.h>
 
38,9 → 36,9
 
#include <arch.h>
 
#define THREADS 25
#define DELAY 10000L
#define ATTEMPTS 5
#define THREADS 25
#define DELAY 10000L
#define ATTEMPTS 5
 
static atomic_t threads_ok;
static atomic_t threads_fault;
60,19 → 58,19
 
for (i = 0; i < ATTEMPTS; i++) {
asm volatile (
"movlpd %0, %%xmm2\n"
: "=m" (arg)
"movlpd %[arg], %%xmm2\n"
: [arg] "=m" (arg)
);
 
delay(DELAY);
asm volatile (
"movlpd %%xmm2, %0\n"
: "=m" (after_arg)
"movlpd %%xmm2, %[after_arg]\n"
: [after_arg] "=m" (after_arg)
);
if (arg != after_arg) {
if (!sh_quiet)
printf("tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg);
printf("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg);
atomic_inc(&threads_fault);
break;
}
92,19 → 90,19
 
for (i = 0; i < ATTEMPTS; i++) {
asm volatile (
"movlpd %0, %%xmm2\n"
: "=m" (arg)
"movlpd %[arg], %%xmm2\n"
: [arg] "=m" (arg)
);
 
scheduler();
asm volatile (
"movlpd %%xmm2, %0\n"
: "=m" (after_arg)
"movlpd %%xmm2, %[after_arg]\n"
: [after_arg] "=m" (after_arg)
);
if (arg != after_arg) {
if (!sh_quiet)
printf("tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg);
printf("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg);
atomic_inc(&threads_fault);
break;
}
123,7 → 121,7
atomic_set(&threads_fault, 0);
if (!quiet)
printf("Creating %d threads... ", 2 * THREADS);
printf("Creating %u threads... ", 2 * THREADS);
 
for (i = 0; i < THREADS; i++) {
thread_t *t;
130,7 → 128,7
if (!(t = thread_create(testit1, (void *) ((unative_t) 2 * i), TASK, 0, "testit1", false))) {
if (!quiet)
printf("could not create thread %d\n", 2 * i);
printf("could not create thread %u\n", 2 * i);
break;
}
thread_ready(t);
138,7 → 136,7
if (!(t = thread_create(testit2, (void *) ((unative_t) 2 * i + 1), TASK, 0, "testit2", false))) {
if (!quiet)
printf("could not create thread %d\n", 2 * i + 1);
printf("could not create thread %u\n", 2 * i + 1);
break;
}
thread_ready(t);
162,5 → 160,3
return "Test failed";
}
 
#endif
/branches/dd/kernel/test/print/print1.c
44,12 → 44,12
printf(" text 8.10s %8.10s \n", "text");
printf(" very long text 8.10s %8.10s \n", "very long text");
printf(" char: c '%c', 3.2c '%3.2c', -3.2c '%-3.2c', 2.3c '%2.3c', -2.3c '%-2.3c' \n",'a', 'b', 'c', 'd', 'e' );
printf(" int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n",1, 1, 1, 1, 1 );
printf(" -int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n",-1, -1, -1, -1, -1 );
printf(" 0xint: x '%#x', 5.3x '%#5.3x', -5.3x '%#-5.3x', 3.5x '%#3.5x', -3.5x '%#-3.5x' \n",17, 17, 17, 17, 17 );
printf(" char: c '%c', 3.2c '%3.2c', -3.2c '%-3.2c', 2.3c '%2.3c', -2.3c '%-2.3c' \n", 'a', 'b', 'c', 'd', 'e');
printf(" int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n", 1, 1, 1, 1, 1);
printf(" -int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n", -1, -1, -1, -1, -1);
printf(" 0xint: x '%#x', 5.3x '%#5.3x', -5.3x '%#-5.3x', 3.5x '%#3.5x', -3.5x '%#-3.5x' \n", 17, 17, 17, 17, 17);
printf("'%#llx' 64bit, '%#x' 32bit, '%#hhx' 8bit, '%#hx' 16bit, unative_t '%#zx'. '%#llx' 64bit and '%s' string.\n", 0x1234567887654321ll, 0x12345678, 0x12, 0x1234, nat, 0x1234567887654321ull, "Lovely string" );
printf("'%#llx' 64bit, '%#x' 32bit, '%#hhx' 8bit, '%#hx' 16bit, unative_t '%#" PRIxn "'. '%#llx' 64bit and '%s' string.\n", 0x1234567887654321ll, 0x12345678, 0x12, 0x1234, nat, 0x1234567887654321ull, "Lovely string" );
printf(" Print to NULL '%s'\n", NULL);
/branches/dd/kernel/doc/BUGS_FOUND
File deleted
/branches/dd/kernel/doc/AUTHORS
1,12 → 1,12
Jakub Jermar <jermar@helenos.eu>
Martin Decky <decky@helenos.eu>
Ondrej Palkovsky <palkovsky@helenos.eu>
Jakub Vana <vana@helenos.eu>
Josef Cejka <cejka@helenos.eu>
Michal Kebrt <michalek.k@seznam.cz>
Sergey Bondari <bondari@helenos.eu>
Pavel Jancik <alfik.009@seznam.cz>
Petr Stepan <stepan.petr@volny.cz>
Michal Konopa <mkonopa@seznam.cz>
Jakub Jermar
Martin Decky
Ondrej Palkovsky
Jiri Svoboda
Jakub Vana
Josef Cejka
Michal Kebrt
Sergey Bondari
Pavel Jancik
Petr Stepan
Michal Konopa
Vojtech Mencl
 
/branches/dd/kernel/doc/arch/mips32
3,11 → 3,9
 
mips32 is the second port of SPARTAN kernel originally written by Jakub Jermar.
It was first developed to run on MIPS R4000 32-bit simulator.
Now it can run on real hardware as well.
It can be compiled and run either as little- or big-endian.
 
HARDWARE REQUIREMENTS
o SGI Indy R4600
o emulated MIPS 4K CPU
 
CPU
/branches/dd/kernel/genarch/include/kbd/ns16550.h
File deleted
/branches/dd/kernel/genarch/include/kbd/i8042.h
File deleted
/branches/dd/kernel/genarch/include/kbd/scanc.h
File deleted
/branches/dd/kernel/genarch/include/kbd/key.h
File deleted
/branches/dd/kernel/genarch/include/kbd/scanc_pc.h
File deleted
/branches/dd/kernel/genarch/include/kbd/z8530.h
File deleted
/branches/dd/kernel/genarch/include/kbd/scanc_sun.h
File deleted
/branches/dd/kernel/genarch/include/kbrd/kbrd.h
0,0 → 1,48
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
*/
 
#ifndef KERN_KBD_H_
#define KERN_KBD_H_
 
#include <console/chardev.h>
 
extern chardev_t kbrdin;
 
extern void kbrd_init(chardev_t *);
 
#endif
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/include/kbrd/scanc_pc.h
0,0 → 1,57
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
* @brief Scan codes for pc keyboards.
*/
 
#ifndef KERN_SCANC_PC_H_
#define KERN_SCANC_PC_H_
 
#define SC_ESC 0x01
#define SC_BACKSPACE 0x0e
#define SC_LSHIFT 0x2a
#define SC_RSHIFT 0x36
#define SC_CAPSLOCK 0x3a
#define SC_SPEC_ESCAPE 0xe0
#define SC_LEFTARR 0x4b
#define SC_RIGHTARR 0x4d
#define SC_UPARR 0x48
#define SC_DOWNARR 0x50
#define SC_DELETE 0x53
#define SC_HOME 0x47
#define SC_END 0x4f
 
#endif
 
/** @}
*/
/branches/dd/kernel/genarch/include/kbrd/scanc_sun.h
0,0 → 1,57
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
* @brief Scan codes for sun keyboards.
*/
 
#ifndef KERN_SCANC_SUN_H_
#define KERN_SCANC_SUN_H_
 
#define SC_ESC 0x1d
#define SC_BACKSPACE 0x2b
#define SC_LSHIFT 0x63
#define SC_RSHIFT 0x6e
#define SC_CAPSLOCK 0x77
#define SC_SPEC_ESCAPE 0xe0 /* ??? */
#define SC_LEFTARR 0x18
#define SC_RIGHTARR 0x1c
#define SC_UPARR 0x14
#define SC_DOWNARR 0x1b
#define SC_DELETE 0x42
#define SC_HOME 0x34
#define SC_END 0x4a
 
#endif
 
/** @}
*/
/branches/dd/kernel/genarch/include/kbrd/scanc.h
0,0 → 1,47
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
*/
 
#ifndef KERN_SCANC_H_
#define KERN_SCANC_H_
 
#define SPECIAL '?'
 
extern char sc_primary_map[];
extern char sc_secondary_map[];
 
#endif
 
/** @}
*/
/branches/dd/kernel/genarch/include/kbrd
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/include/fb/font-8x16.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
/** @addtogroup genarch
* @{
*/
/** @file
35,11 → 35,14
#ifndef KERN_FONT_8X16_H_
#define KERN_FONT_8X16_H_
 
#define FONT_GLIPHS 256
#define FONT_SCANLINES 16
#define FONT_GLYPHS 256
#define FONT_WIDTH 8
#define FONT_SCANLINES 16
 
extern unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES];
#include <arch/types.h>
 
extern uint8_t fb_font[FONT_GLYPHS * FONT_SCANLINES];
 
#endif
 
/** @}
/branches/dd/kernel/genarch/include/fb/logo-196x66.h
0,0 → 1,49
/*
* Copyright (c) 2008 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/** @file
*/
 
#ifndef KERN_LOGO_196X66_H_
#define KERN_LOGO_196X66_H_
 
#define LOGO_WIDTH 196
#define LOGO_HEIGHT 66
#define LOGO_COLOR 0xffffff
 
#include <arch/types.h>
 
extern uint32_t fb_logo[LOGO_WIDTH * LOGO_HEIGHT];
 
#endif
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/include/fb/visuals.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
/** @addtogroup genarch
* @{
*/
/** @file
35,15 → 35,16
#ifndef KERN_VISUALS_H_
#define KERN_VISUALS_H_
 
#define VISUAL_INDIRECT_8 0
#define VISUAL_INDIRECT_8 0
 
#define VISUAL_RGB_5_5_5 1
#define VISUAL_RGB_5_6_5 2
#define VISUAL_RGB_8_8_8 3
#define VISUAL_RGB_8_8_8_0 4
#define VISUAL_RGB_0_8_8_8 5
#define VISUAL_RGB_5_5_5 1
#define VISUAL_RGB_5_6_5 2
#define VISUAL_RGB_8_8_8 3
#define VISUAL_RGB_8_8_8_0 4
#define VISUAL_RGB_0_8_8_8 5
 
#define VISUAL_BGR_0_8_8_8 6
#define VISUAL_BGR_0_8_8_8 6
#define VISUAL_BGR_8_8_8 7
 
#endif
 
/branches/dd/kernel/genarch/include/fb/fb.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
/** @addtogroup genarch
* @{
*/
/** @file
38,9 → 38,37
#include <arch/types.h>
#include <synch/spinlock.h>
 
/**
* Properties of the framebuffer device.
*/
typedef struct fb_properties {
/** Physical address of the framebuffer device. */
uintptr_t addr;
 
/**
* Address where the first (top left) pixel is mapped,
* relative to "addr".
*/
unsigned int offset;
 
/** Screen width in pixels. */
unsigned int x;
 
/** Screen height in pixels. */
unsigned int y;
 
/** Bytes per one scanline. */
unsigned int scan;
 
/** Color model. */
unsigned int visual;
} fb_properties_t;
 
SPINLOCK_EXTERN(fb_lock);
void fb_init(uintptr_t addr, unsigned int x, unsigned int y, unsigned int scan, unsigned int visual);
 
void fb_redraw(void);
void fb_init(fb_properties_t *props);
 
#endif
 
/** @}
/branches/dd/kernel/genarch/include/mm/page_pt.h
116,9 → 116,7
#define PTE_WRITABLE(p) PTE_WRITABLE_ARCH((p))
#define PTE_EXECUTABLE(p) PTE_EXECUTABLE_ARCH((p))
 
#ifndef __OBJC__
extern as_operations_t as_pt_operations;
#endif
extern page_mapping_operations_t pt_mapping_operations;
 
extern void page_mapping_insert_pt(as_t *as, uintptr_t page, uintptr_t frame,
/branches/dd/kernel/genarch/include/ofw/ofw_tree.h
30,6 → 30,8
#define KERN_OFW_TREE_H_
 
#include <arch/types.h>
#include <ddi/irq.h>
#include <typedefs.h>
 
#define OFW_TREE_PROPERTY_MAX_NAMELEN 32
 
42,11 → 44,11
ofw_tree_node_t *peer;
ofw_tree_node_t *child;
 
uint32_t node_handle; /**< Old OpenFirmware node handle. */
uint32_t node_handle; /**< Old OpenFirmware node handle. */
 
char *da_name; /**< Disambigued name. */
char *da_name; /**< Disambigued name. */
 
unsigned properties; /**< Number of properties. */
unsigned properties; /**< Number of properties. */
ofw_tree_property_t *property;
/**
104,7 → 106,7
uint32_t child_space;
uint32_t child_base;
uint32_t parent_space;
uint64_t parent_base; /* group phys.mid and phys.lo together */
uint64_t parent_base; /* group phys.mid and phys.lo together */
uint32_t size;
} __attribute__ ((packed));
typedef struct ofw_ebus_range ofw_ebus_range_t;
126,8 → 128,8
typedef struct ofw_ebus_intr_mask ofw_ebus_intr_mask_t;
 
struct ofw_pci_reg {
uint32_t space; /* needs to be masked to obtain pure space id */
uint64_t addr; /* group phys.mid and phys.lo together */
uint32_t space; /* needs to be masked to obtain pure space id */
uint64_t addr; /* group phys.mid and phys.lo together */
uint64_t size;
} __attribute__ ((packed));
typedef struct ofw_pci_reg ofw_pci_reg_t;
134,7 → 136,7
 
struct ofw_pci_range {
uint32_t space;
uint64_t child_base; /* group phys.mid and phys.lo together */
uint64_t child_base; /* group phys.mid and phys.lo together */
uint64_t parent_base;
uint64_t size;
} __attribute__ ((packed));
159,27 → 161,43
} __attribute__ ((packed));
typedef struct ofw_upa_reg ofw_upa_reg_t;
 
extern void ofw_tree_init(ofw_tree_node_t *root);
extern void ofw_tree_init(ofw_tree_node_t *);
extern void ofw_tree_print(void);
extern const char *ofw_tree_node_name(const ofw_tree_node_t *node);
extern ofw_tree_node_t *ofw_tree_lookup(const char *path);
extern ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *node, const char *name);
extern ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node, const char *name);
extern ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *device_type);
extern ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *device_type);
extern ofw_tree_node_t *ofw_tree_find_node_by_handle(ofw_tree_node_t *root, uint32_t handle);
extern const char *ofw_tree_node_name(const ofw_tree_node_t *);
extern ofw_tree_node_t *ofw_tree_lookup(const char *);
extern ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *,
const char *);
extern ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *, const char *);
extern ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *,
const char *);
extern ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *,
const char *);
extern ofw_tree_node_t *ofw_tree_find_peer_by_name(ofw_tree_node_t *node,
const char *name);
extern ofw_tree_node_t *ofw_tree_find_node_by_handle(ofw_tree_node_t *,
uint32_t);
 
extern bool ofw_fhc_apply_ranges(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uintptr_t *pa);
extern bool ofw_central_apply_ranges(ofw_tree_node_t *node, ofw_central_reg_t *reg, uintptr_t *pa);
extern bool ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa);
extern bool ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa);
extern bool ofw_sbus_apply_ranges(ofw_tree_node_t *node, ofw_sbus_reg_t *reg, uintptr_t *pa);
extern bool ofw_upa_apply_ranges(ofw_tree_node_t *node, ofw_upa_reg_t *reg, uintptr_t *pa);
extern bool ofw_fhc_apply_ranges(ofw_tree_node_t *, ofw_fhc_reg_t *,
uintptr_t *);
extern bool ofw_central_apply_ranges(ofw_tree_node_t *, ofw_central_reg_t *,
uintptr_t *);
extern bool ofw_ebus_apply_ranges(ofw_tree_node_t *, ofw_ebus_reg_t *,
uintptr_t *);
extern bool ofw_pci_apply_ranges(ofw_tree_node_t *, ofw_pci_reg_t *,
uintptr_t *);
extern bool ofw_sbus_apply_ranges(ofw_tree_node_t *, ofw_sbus_reg_t *,
uintptr_t *);
extern bool ofw_upa_apply_ranges(ofw_tree_node_t *, ofw_upa_reg_t *,
uintptr_t *);
 
extern bool ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg, ofw_pci_reg_t *out);
extern bool ofw_pci_reg_absolutize(ofw_tree_node_t *, ofw_pci_reg_t *,
ofw_pci_reg_t *);
 
extern bool ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uint32_t interrupt, int *inr);
extern bool ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uint32_t interrupt, int *inr);
extern bool ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino, int *inr);
extern bool ofw_fhc_map_interrupt(ofw_tree_node_t *, ofw_fhc_reg_t *,
uint32_t, int *, cir_t *, void **);
extern bool ofw_ebus_map_interrupt(ofw_tree_node_t *, ofw_ebus_reg_t *,
uint32_t, int *, cir_t *, void **);
extern bool ofw_pci_map_interrupt(ofw_tree_node_t *, ofw_pci_reg_t *,
int, int *, cir_t *, void **);
 
#endif
/branches/dd/kernel/genarch/include/drivers/ns16550/ns16550.h
0,0 → 1,80
/*
* Copyright (c) 2001-2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
* @brief Headers for NS 16550 serial controller.
*/
 
#ifndef KERN_NS16550_H_
#define KERN_NS16550_H_
 
#include <ddi/irq.h>
#include <arch/types.h>
#include <console/chardev.h>
 
#define IER_ERBFI 0x01 /** Enable Receive Buffer Full Interrupt. */
 
#define LCR_DLAB 0x80 /** Divisor Latch Access bit. */
 
#define MCR_OUT2 0x08 /** OUT2. */
 
/** NS16550 registers. */
struct ns16550 {
ioport8_t rbr; /**< Receiver Buffer Register. */
ioport8_t ier; /**< Interrupt Enable Register. */
union {
ioport8_t iir; /**< Interrupt Ident Register (read). */
ioport8_t fcr; /**< FIFO control register (write). */
} __attribute__ ((packed));
ioport8_t lcr; /**< Line Control register. */
ioport8_t mcr; /**< Modem Control Register. */
ioport8_t lsr; /**< Line Status Register. */
} __attribute__ ((packed));
typedef struct ns16550 ns16550_t;
 
/** Structure representing the ns16550 device. */
typedef struct ns16550_instance {
devno_t devno;
ns16550_t *ns16550;
irq_t irq;
chardev_t *devout;
} ns16550_instance_t;
 
extern bool ns16550_init(ns16550_t *, devno_t, inr_t, cir_t, void *,
chardev_t *);
extern irq_ownership_t ns16550_claim(irq_t *);
extern void ns16550_irq_handler(irq_t *);
 
#endif
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/include/drivers/i8042/i8042.h
0,0 → 1,62
/*
* Copyright (c) 2001-2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/** @file
*/
 
#ifndef KERN_I8042_H_
#define KERN_I8042_H_
 
#include <ddi/irq.h>
#include <arch/types.h>
#include <console/chardev.h>
#include <typedefs.h>
 
struct i8042 {
ioport8_t data;
uint8_t pad[3];
ioport8_t status;
} __attribute__ ((packed));
typedef struct i8042 i8042_t;
 
typedef struct i8042_instance {
devno_t devno;
irq_t irq;
i8042_t *i8042;
chardev_t *devout;
} i8042_instance_t;
 
extern bool i8042_init(i8042_t *, devno_t, inr_t, chardev_t *);
 
#endif
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/include/drivers/z8530/z8530.h
0,0 → 1,131
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
* @brief Headers for Zilog 8530 serial controller.
*/
 
#ifndef KERN_Z8530_H_
#define KERN_Z8530_H_
 
#include <ddi/irq.h>
#include <arch/types.h>
#include <console/chardev.h>
 
#define WR0 0
#define WR1 1
#define WR2 2
#define WR3 3
#define WR4 4
#define WR5 5
#define WR6 6
#define WR7 7
#define WR8 8
#define WR9 9
#define WR10 10
#define WR11 11
#define WR12 12
#define WR13 13
#define WR14 14
#define WR15 15
 
#define RR0 0
#define RR1 1
#define RR2 2
#define RR3 3
#define RR8 8
#define RR10 10
#define RR12 12
#define RR13 13
#define RR14 14
#define RR15 15
 
/** Reset pending TX interrupt. */
#define WR0_TX_IP_RST (0x5 << 3)
#define WR0_ERR_RST (0x6 << 3)
 
/** Receive Interrupts Disabled. */
#define WR1_RID (0x0 << 3)
/** Receive Interrupt on First Character or Special Condition. */
#define WR1_RIFCSC (0x1 << 3)
/** Interrupt on All Receive Characters or Special Conditions. */
#define WR1_IARCSC (0x2 << 3)
/** Receive Interrupt on Special Condition. */
#define WR1_RISC (0x3 << 3)
/** Parity Is Special Condition. */
#define WR1_PISC (0x1 << 2)
 
/** Rx Enable. */
#define WR3_RX_ENABLE (0x1 << 0)
/** 8-bits per character. */
#define WR3_RX8BITSCH (0x3 << 6)
 
/** Master Interrupt Enable. */
#define WR9_MIE (0x1 << 3)
 
/** Receive Character Available. */
#define RR0_RCA (0x1 << 0)
 
/** z8530's registers. */
struct z8530 {
union {
ioport8_t ctl_b;
ioport8_t status_b;
} __attribute__ ((packed));
uint8_t pad1;
ioport8_t data_b;
uint8_t pad2;
union {
ioport8_t ctl_a;
ioport8_t status_a;
} __attribute__ ((packed));
uint8_t pad3;
ioport8_t data_a;
} __attribute__ ((packed));
typedef struct z8530 z8530_t;
 
/** Structure representing the z8530 device. */
typedef struct {
devno_t devno;
irq_t irq;
z8530_t *z8530;
chardev_t *devout;
} z8530_instance_t;
 
extern bool z8530_init(z8530_t *, devno_t, inr_t, cir_t, void *, chardev_t *);
extern irq_ownership_t z8530_claim(irq_t *);
extern void z8530_irq_handler(irq_t *);
 
#endif
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/include/drivers/ega/ega.h
0,0 → 1,56
/*
* Copyright (c) 2001-2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch_drivers
* @{
*/
/** @file
*/
 
#ifndef KERN_EGA_H_
#define KERN_EGA_H_
 
#include <arch/types.h>
#include <typedefs.h>
 
#define EGA_COLS 80
#define EGA_ROWS 25
#define EGA_SCREEN (EGA_COLS * EGA_ROWS)
#define EGA_VRAM_SIZE (2 * EGA_SCREEN)
 
/* EGA device registers. */
#define EGA_INDEX_REG 0
#define EGA_DATA_REG 1
 
extern void ega_redraw(void);
extern void ega_init(ioport8_t *, uintptr_t);
 
#endif
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/include/drivers/legacy/ia32/io.h
0,0 → 1,51
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
* @{
*/
/** @file
* @brief This file contains definitions used by architectures with the
* ia32 legacy I/O space (i.e. ia32, amd64 and ia64).
*/
 
#ifndef KERN_LEGACY_IA32_IO_H
#define KERN_LEGACY_IA32_IO_H
 
#include <arch/types.h>
 
#define I8042_BASE ((ioport8_t *) 0x60)
#define EGA_BASE ((ioport8_t *) 0x3d4)
#define NS16550_BASE ((ioport8_t *) 0x3f8)
 
#define EGA_VIDEORAM 0xb8000
 
#endif
 
/** @}
*/
/branches/dd/kernel/genarch/include/multiboot/multiboot.h
0,0 → 1,100
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/** @file
*/
 
#ifndef KERN_MULTIBOOT_H_
#define KERN_MULTIBOOT_H_
 
#include <arch/types.h>
#include <arch/boot/memmap.h>
 
/** Multiboot 32-bit address. */
typedef uint32_t mbaddr_t;
 
/** Multiboot mod structure */
typedef struct {
mbaddr_t start;
mbaddr_t end;
mbaddr_t string;
uint32_t reserved;
} __attribute__ ((packed)) multiboot_mod_t;
 
/** Multiboot mmap structure */
typedef struct {
uint32_t size;
e820memmap_t mm_info;
} __attribute__ ((packed)) multiboot_mmap_t;
 
/** Multiboot information structure */
typedef struct {
uint32_t flags;
uint32_t mem_lower;
uint32_t mem_upper;
uint32_t boot_device;
uint32_t cmdline;
uint32_t mods_count;
mbaddr_t mods_addr;
uint32_t syms[4];
uint32_t mmap_length;
mbaddr_t mmap_addr;
/* ... */
} __attribute__ ((packed)) multiboot_info_t;
 
enum multiboot_info_flags {
MBINFO_FLAGS_MEM = 0x01,
MBINFO_FLAGS_BOOT = 0x02,
MBINFO_FLAGS_CMDLINE = 0x04,
MBINFO_FLAGS_MODS = 0x08,
MBINFO_FLAGS_SYMS1 = 0x10,
MBINFO_FLAGS_SYMS2 = 0x20,
MBINFO_FLAGS_MMAP = 0x40
/* ... */
};
 
#define MULTIBOOT_LOADER_MAGIC 0x2BADB002
 
/** Convert 32-bit multiboot address to a pointer. */
#define MULTIBOOT_PTR(mba) ((void *)(uintptr_t) (mba))
 
extern void multiboot_info_parse(uint32_t, const multiboot_info_t *);
 
#endif
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/include/srln/srln.h
0,0 → 1,48
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
*/
 
#ifndef KERN_SRLN_H_
#define KERN_SRLN_H_
 
#include <console/chardev.h>
 
extern chardev_t srlnin;
 
extern void srln_init(chardev_t *);
 
#endif
 
/** @}
*/
/branches/dd/kernel/genarch/Makefile.inc
33,68 → 33,75
genarch/src/acpi/acpi.c \
genarch/src/acpi/madt.c
endif
 
ifeq ($(CONFIG_PAGE_PT),y)
GENARCH_SOURCES += \
genarch/src/mm/page_pt.c \
genarch/src/mm/as_pt.c
endif
 
ifeq ($(CONFIG_PAGE_HT),y)
GENARCH_SOURCES += \
genarch/src/mm/page_ht.c \
genarch/src/mm/as_ht.c
endif
 
ifeq ($(CONFIG_ASID),y)
GENARCH_SOURCES += \
genarch/src/mm/asid.c
endif
 
ifeq ($(CONFIG_ASID_FIFO),y)
GENARCH_SOURCES += \
genarch/src/mm/asid_fifo.c
endif
 
ifeq ($(CONFIG_SOFTINT),y)
GENARCH_SOURCES += \
genarch/src/softint/division.c
endif
 
## Framebuffer
ifeq ($(CONFIG_FB),y)
GENARCH_SOURCES += \
genarch/src/fb/font-8x16.c \
genarch/src/fb/logo-196x66.c \
genarch/src/fb/fb.c
DEFS += -DCONFIG_FB
endif
 
## i8042 controller
ifeq ($(CONFIG_I8042),y)
GENARCH_SOURCES += \
genarch/src/kbd/i8042.c \
genarch/src/kbd/key.c \
genarch/src/kbd/scanc_pc.c
genarch/src/drivers/i8042/i8042.c
endif
 
## Sun keyboard
ifeq ($(CONFIG_SUN_KBD),y)
ifeq ($(CONFIG_NS16550),y)
GENARCH_SOURCES += \
genarch/src/kbd/key.c \
genarch/src/kbd/scanc_sun.c
genarch/src/drivers/ns16550/ns16550.c
endif
 
## z8530 controller
ifeq ($(CONFIG_Z8530),y)
GENARCH_SOURCES += \
genarch/src/kbd/z8530.c
genarch/src/drivers/z8530/z8530.c
endif
 
## ns16550 controller
ifeq ($(CONFIG_NS16550),y)
ifeq ($(CONFIG_PC_KBD),y)
GENARCH_SOURCES += \
genarch/src/kbd/ns16550.c
genarch/src/kbrd/kbrd.c \
genarch/src/kbrd/scanc_pc.c
endif
 
ifeq ($(CONFIG_SUN_KBD),y)
GENARCH_SOURCES += \
genarch/src/kbrd/kbrd.c \
genarch/src/kbrd/scanc_sun.c
endif
 
## OpenFirmware Device Tree
ifeq ($(CONFIG_OFW_TREE), y)
ifeq ($(CONFIG_SRLN),y)
GENARCH_SOURCES += \
genarch/src/srln/srln.c
endif
 
ifeq ($(CONFIG_OFW_TREE),y)
GENARCH_SOURCES += \
genarch/src/ofw/ofw_tree.c \
genarch/src/ofw/ebus.c \
genarch/src/ofw/fhc.c \
102,3 → 109,13
genarch/src/ofw/sbus.c \
genarch/src/ofw/upa.c
endif
 
ifeq ($(CONFIG_MULTIBOOT), y)
GENARCH_SOURCES += \
genarch/src/multiboot/multiboot.c
endif
 
ifeq ($(CONFIG_EGA), y)
GENARCH_SOURCES += \
genarch/src/drivers/ega/ega.c
endif
/branches/dd/kernel/genarch/src/kbd/scanc_sun.c
File deleted
/branches/dd/kernel/genarch/src/kbd/ns16550.c
File deleted
/branches/dd/kernel/genarch/src/kbd/i8042.c
File deleted
/branches/dd/kernel/genarch/src/kbd/key.c
File deleted
/branches/dd/kernel/genarch/src/kbd/z8530.c
File deleted
/branches/dd/kernel/genarch/src/kbd/scanc_pc.c
File deleted
/branches/dd/kernel/genarch/src/kbrd/kbrd.c
0,0 → 1,220
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
* @brief Keyboard processing.
*/
 
#include <genarch/kbrd/kbrd.h>
#include <genarch/kbrd/scanc.h>
 
#ifdef CONFIG_PC_KBD
#include <genarch/kbrd/scanc_pc.h>
#endif
 
#ifdef CONFIG_SUN_KBD
#include <genarch/kbrd/scanc_sun.h>
#endif
 
#include <synch/spinlock.h>
#include <console/chardev.h>
#include <console/console.h>
#include <proc/thread.h>
#include <arch.h>
#include <macros.h>
 
#ifdef CONFIG_SUN_KBD
# define IGNORE_CODE 0x7f
#endif
 
#define KEY_RELEASE 0x80
 
#define PRESSED_SHIFT (1 << 0)
#define PRESSED_CAPSLOCK (1 << 1)
#define LOCKED_CAPSLOCK (1 << 0)
 
chardev_t kbrdin;
static chardev_t *kbdout;
 
static void kbrdin_suspend(chardev_t *d)
{
}
 
static void kbrdin_resume(chardev_t *d)
{
}
 
chardev_operations_t kbrdin_ops = {
.suspend = kbrdin_suspend,
.resume = kbrdin_resume,
};
 
SPINLOCK_INITIALIZE(keylock); /**< keylock protects keyflags and lockflags. */
static volatile int keyflags; /**< Tracking of multiple keypresses. */
static volatile int lockflags; /**< Tracking of multiple keys lockings. */
 
static void key_released(uint8_t);
static void key_pressed(uint8_t);
 
static void kkbrd(void *arg)
{
chardev_t *in = (chardev_t *) arg;
uint8_t sc;
 
while (1) {
sc = _getc(in);
 
#ifdef CONFIG_SUN_KBD
if (sc == IGNORE_CODE)
continue;
#endif
if (sc & KEY_RELEASE)
key_released(sc ^ KEY_RELEASE);
else
key_pressed(sc);
}
}
 
 
void kbrd_init(chardev_t *devout)
{
thread_t *t;
 
chardev_initialize("kbrd", &kbrdin, &kbrdin_ops);
kbdout = devout;
t = thread_create(kkbrd, &kbrdin, TASK, 0, "kkbrd", false);
ASSERT(t);
thread_ready(t);
}
 
/** Process release of key.
*
* @param sc Scancode of the key being released.
*/
void key_released(uint8_t sc)
{
spinlock_lock(&keylock);
switch (sc) {
case SC_LSHIFT:
case SC_RSHIFT:
keyflags &= ~PRESSED_SHIFT;
break;
case SC_CAPSLOCK:
keyflags &= ~PRESSED_CAPSLOCK;
if (lockflags & LOCKED_CAPSLOCK)
lockflags &= ~LOCKED_CAPSLOCK;
else
lockflags |= LOCKED_CAPSLOCK;
break;
default:
break;
}
spinlock_unlock(&keylock);
}
 
/** Process keypress.
*
* @param sc Scancode of the key being pressed.
*/
void key_pressed(uint8_t sc)
{
char *map = sc_primary_map;
char ascii = sc_primary_map[sc];
bool shift, capslock;
bool letter = false;
 
spinlock_lock(&keylock);
switch (sc) {
case SC_LSHIFT:
case SC_RSHIFT:
keyflags |= PRESSED_SHIFT;
break;
case SC_CAPSLOCK:
keyflags |= PRESSED_CAPSLOCK;
break;
case SC_SPEC_ESCAPE:
break;
case SC_LEFTARR:
chardev_push_character(kbdout, 0x1b);
chardev_push_character(kbdout, 0x5b);
chardev_push_character(kbdout, 0x44);
break;
case SC_RIGHTARR:
chardev_push_character(kbdout, 0x1b);
chardev_push_character(kbdout, 0x5b);
chardev_push_character(kbdout, 0x43);
break;
case SC_UPARR:
chardev_push_character(kbdout, 0x1b);
chardev_push_character(kbdout, 0x5b);
chardev_push_character(kbdout, 0x41);
break;
case SC_DOWNARR:
chardev_push_character(kbdout, 0x1b);
chardev_push_character(kbdout, 0x5b);
chardev_push_character(kbdout, 0x42);
break;
case SC_HOME:
chardev_push_character(kbdout, 0x1b);
chardev_push_character(kbdout, 0x4f);
chardev_push_character(kbdout, 0x48);
break;
case SC_END:
chardev_push_character(kbdout, 0x1b);
chardev_push_character(kbdout, 0x4f);
chardev_push_character(kbdout, 0x46);
break;
case SC_DELETE:
chardev_push_character(kbdout, 0x1b);
chardev_push_character(kbdout, 0x5b);
chardev_push_character(kbdout, 0x33);
chardev_push_character(kbdout, 0x7e);
break;
default:
letter = islower(ascii);
capslock = (keyflags & PRESSED_CAPSLOCK) ||
(lockflags & LOCKED_CAPSLOCK);
shift = keyflags & PRESSED_SHIFT;
if (letter && capslock)
shift = !shift;
if (shift)
map = sc_secondary_map;
chardev_push_character(kbdout, map[sc]);
break;
}
spinlock_unlock(&keylock);
}
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/src/kbrd/scanc_pc.c
0,0 → 1,200
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
* @brief Scan codes for pc keyboards.
*/
 
#include <genarch/kbrd/scanc.h>
 
/** Primary meaning of scancodes. */
char sc_primary_map[] = {
SPECIAL, /* 0x00 */
SPECIAL, /* 0x01 - Esc */
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',
'\b', /* 0x0e - Backspace */
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
SPECIAL, /* 0x1d - LCtrl */
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'',
'`',
SPECIAL, /* 0x2a - LShift */
'\\',
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
SPECIAL, /* 0x36 - RShift */
'*',
SPECIAL, /* 0x38 - LAlt */
' ',
SPECIAL, /* 0x3a - CapsLock */
SPECIAL, /* 0x3b - F1 */
SPECIAL, /* 0x3c - F2 */
SPECIAL, /* 0x3d - F3 */
SPECIAL, /* 0x3e - F4 */
SPECIAL, /* 0x3f - F5 */
SPECIAL, /* 0x40 - F6 */
SPECIAL, /* 0x41 - F7 */
SPECIAL, /* 0x42 - F8 */
SPECIAL, /* 0x43 - F9 */
SPECIAL, /* 0x44 - F10 */
SPECIAL, /* 0x45 - NumLock */
SPECIAL, /* 0x46 - ScrollLock */
'7', '8', '9', '-',
'4', '5', '6', '+',
'1', '2', '3',
'0', '.',
SPECIAL, /* 0x54 - Alt-SysRq */
SPECIAL, /* 0x55 - F11/F12/PF1/FN */
SPECIAL, /* 0x56 - unlabelled key next to LAlt */
SPECIAL, /* 0x57 - F11 */
SPECIAL, /* 0x58 - F12 */
SPECIAL, /* 0x59 */
SPECIAL, /* 0x5a */
SPECIAL, /* 0x5b */
SPECIAL, /* 0x5c */
SPECIAL, /* 0x5d */
SPECIAL, /* 0x5e */
SPECIAL, /* 0x5f */
SPECIAL, /* 0x60 */
SPECIAL, /* 0x61 */
SPECIAL, /* 0x62 */
SPECIAL, /* 0x63 */
SPECIAL, /* 0x64 */
SPECIAL, /* 0x65 */
SPECIAL, /* 0x66 */
SPECIAL, /* 0x67 */
SPECIAL, /* 0x68 */
SPECIAL, /* 0x69 */
SPECIAL, /* 0x6a */
SPECIAL, /* 0x6b */
SPECIAL, /* 0x6c */
SPECIAL, /* 0x6d */
SPECIAL, /* 0x6e */
SPECIAL, /* 0x6f */
SPECIAL, /* 0x70 */
SPECIAL, /* 0x71 */
SPECIAL, /* 0x72 */
SPECIAL, /* 0x73 */
SPECIAL, /* 0x74 */
SPECIAL, /* 0x75 */
SPECIAL, /* 0x76 */
SPECIAL, /* 0x77 */
SPECIAL, /* 0x78 */
SPECIAL, /* 0x79 */
SPECIAL, /* 0x7a */
SPECIAL, /* 0x7b */
SPECIAL, /* 0x7c */
SPECIAL, /* 0x7d */
SPECIAL, /* 0x7e */
SPECIAL, /* 0x7f */
};
 
/** Secondary meaning of scancodes. */
char sc_secondary_map[] = {
SPECIAL, /* 0x00 */
SPECIAL, /* 0x01 - Esc */
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',
SPECIAL, /* 0x0e - Backspace */
'\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
SPECIAL, /* 0x1d - LCtrl */
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"',
'~',
SPECIAL, /* 0x2a - LShift */
'|',
'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
SPECIAL, /* 0x36 - RShift */
'*',
SPECIAL, /* 0x38 - LAlt */
' ',
SPECIAL, /* 0x3a - CapsLock */
SPECIAL, /* 0x3b - F1 */
SPECIAL, /* 0x3c - F2 */
SPECIAL, /* 0x3d - F3 */
SPECIAL, /* 0x3e - F4 */
SPECIAL, /* 0x3f - F5 */
SPECIAL, /* 0x40 - F6 */
SPECIAL, /* 0x41 - F7 */
SPECIAL, /* 0x42 - F8 */
SPECIAL, /* 0x43 - F9 */
SPECIAL, /* 0x44 - F10 */
SPECIAL, /* 0x45 - NumLock */
SPECIAL, /* 0x46 - ScrollLock */
'7', '8', '9', '-',
'4', '5', '6', '+',
'1', '2', '3',
'0', '.',
SPECIAL, /* 0x54 - Alt-SysRq */
SPECIAL, /* 0x55 - F11/F12/PF1/FN */
SPECIAL, /* 0x56 - unlabelled key next to LAlt */
SPECIAL, /* 0x57 - F11 */
SPECIAL, /* 0x58 - F12 */
SPECIAL, /* 0x59 */
SPECIAL, /* 0x5a */
SPECIAL, /* 0x5b */
SPECIAL, /* 0x5c */
SPECIAL, /* 0x5d */
SPECIAL, /* 0x5e */
SPECIAL, /* 0x5f */
SPECIAL, /* 0x60 */
SPECIAL, /* 0x61 */
SPECIAL, /* 0x62 */
SPECIAL, /* 0x63 */
SPECIAL, /* 0x64 */
SPECIAL, /* 0x65 */
SPECIAL, /* 0x66 */
SPECIAL, /* 0x67 */
SPECIAL, /* 0x68 */
SPECIAL, /* 0x69 */
SPECIAL, /* 0x6a */
SPECIAL, /* 0x6b */
SPECIAL, /* 0x6c */
SPECIAL, /* 0x6d */
SPECIAL, /* 0x6e */
SPECIAL, /* 0x6f */
SPECIAL, /* 0x70 */
SPECIAL, /* 0x71 */
SPECIAL, /* 0x72 */
SPECIAL, /* 0x73 */
SPECIAL, /* 0x74 */
SPECIAL, /* 0x75 */
SPECIAL, /* 0x76 */
SPECIAL, /* 0x77 */
SPECIAL, /* 0x78 */
SPECIAL, /* 0x79 */
SPECIAL, /* 0x7a */
SPECIAL, /* 0x7b */
SPECIAL, /* 0x7c */
SPECIAL, /* 0x7d */
SPECIAL, /* 0x7e */
SPECIAL, /* 0x7f */
};
 
/** @}
*/
/branches/dd/kernel/genarch/src/kbrd/scanc_sun.c
0,0 → 1,304
/*
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
* @brief Scan codes for Sun keyboards.
*/
 
#include <genarch/kbrd/scanc.h>
 
/** Primary meaning of scancodes. */
char sc_primary_map[] = {
[0x00] = SPECIAL,
[0x01] = SPECIAL,
[0x02] = SPECIAL,
[0x03] = SPECIAL,
[0x04] = SPECIAL,
[0x05] = SPECIAL, /* F1 */
[0x06] = SPECIAL, /* F2 */
[0x07] = SPECIAL, /* F10 */
[0x08] = SPECIAL, /* F3 */
[0x09] = SPECIAL, /* F11 */
[0x0a] = SPECIAL, /* F4 */
[0x0b] = SPECIAL, /* F12 */
[0x0c] = SPECIAL, /* F5 */
[0x0d] = SPECIAL, /* RAlt */
[0x0e] = SPECIAL, /* F6 */
[0x0f] = SPECIAL,
[0x10] = SPECIAL, /* F7 */
[0x11] = SPECIAL, /* F8 */
[0x12] = SPECIAL, /* F9 */
[0x13] = SPECIAL, /* LAlt */
[0x14] = SPECIAL, /* Up Arrow */
[0x15] = SPECIAL, /* Pause */
[0x16] = SPECIAL,
[0x17] = SPECIAL, /* Scroll Lock */
[0x18] = SPECIAL, /* Left Arrow */
[0x19] = SPECIAL,
[0x1a] = SPECIAL,
[0x1b] = SPECIAL, /* Down Arrow */
[0x1c] = SPECIAL, /* Right Arrow */
[0x1d] = SPECIAL, /* Esc */
[0x1e] = '1',
[0x1f] = '2',
[0x20] = '3',
[0x21] = '4',
[0x22] = '5',
[0x23] = '6',
[0x24] = '7',
[0x25] = '8',
[0x26] = '9',
[0x27] = '0',
[0x28] = '-',
[0x29] = '=',
[0x2a] = '`',
[0x2b] = '\b', /* Backspace */
[0x2c] = SPECIAL, /* Insert */
[0x2d] = SPECIAL,
[0x2e] = '/', /* numeric keypad */
[0x2f] = '*', /* numeric keypad */
[0x30] = SPECIAL,
[0x31] = SPECIAL,
[0x32] = '.', /* numeric keypad */
[0x33] = SPECIAL,
[0x34] = SPECIAL, /* Home */
[0x35] = '\t', /* Tab */
[0x36] = 'q',
[0x37] = 'w',
[0x38] = 'e',
[0x39] = 'r',
[0x3a] = 't',
[0x3b] = 'y',
[0x3c] = 'u',
[0x3d] = 'i',
[0x3e] = 'o',
[0x3f] = 'p',
[0x40] = '[',
[0x41] = ']',
[0x42] = SPECIAL, /* Del */
[0x43] = SPECIAL,
[0x44] = '7', /* numeric keypad */
[0x45] = '8', /* numeric keypad */
[0x46] = '9', /* numeric keypad */
[0x47] = '-', /* numeric keypad */
[0x48] = SPECIAL,
[0x49] = SPECIAL,
[0x4a] = SPECIAL, /* End */
[0x4b] = SPECIAL,
[0x4c] = SPECIAL, /* Control */
[0x4d] = 'a',
[0x4e] = 's',
[0x4f] = 'd',
[0x50] = 'f',
[0x51] = 'g',
[0x52] = 'h',
[0x53] = 'j',
[0x54] = 'k',
[0x55] = 'l',
[0x56] = ';',
[0x57] = '\'',
[0x58] = '\\',
[0x59] = '\n', /* Enter */
[0x5a] = '\n', /* Enter on numeric keypad */
[0x5b] = '4', /* numeric keypad */
[0x5c] = '5', /* numeric keypad */
[0x5d] = '6', /* numeric keypad */
[0x5e] = '0', /* numeric keypad */
[0x5f] = SPECIAL,
[0x60] = SPECIAL, /* Page Up */
[0x61] = SPECIAL,
[0x62] = SPECIAL, /* Num Lock */
[0x63] = SPECIAL, /* LShift */
[0x64] = 'z',
[0x65] = 'x',
[0x66] = 'c',
[0x67] = 'v',
[0x68] = 'b',
[0x69] = 'n',
[0x6a] = 'm',
[0x6b] = ',',
[0x6c] = '.',
[0x6d] = '/',
[0x6e] = SPECIAL, /* RShift */
[0x6f] = SPECIAL,
[0x70] = '1', /* numeric keypad */
[0x71] = '2', /* numeric keypad */
[0x72] = '3', /* numeric keypad */
[0x73] = SPECIAL,
[0x74] = SPECIAL,
[0x75] = SPECIAL,
[0x76] = SPECIAL,
[0x77] = SPECIAL, /* Caps Lock */
[0x78] = SPECIAL,
[0x79] = ' ',
[0x7a] = SPECIAL,
[0x7b] = SPECIAL, /* Page Down */
[0x7c] = SPECIAL,
[0x7d] = '+', /* numeric key pad */
[0x7e] = SPECIAL,
[0x7f] = SPECIAL
};
 
/** Secondary meaning of scancodes. */
char sc_secondary_map[] = {
[0x00] = SPECIAL,
[0x01] = SPECIAL,
[0x02] = SPECIAL,
[0x03] = SPECIAL,
[0x04] = SPECIAL,
[0x05] = SPECIAL, /* F1 */
[0x06] = SPECIAL, /* F2 */
[0x07] = SPECIAL, /* F10 */
[0x08] = SPECIAL, /* F3 */
[0x09] = SPECIAL, /* F11 */
[0x0a] = SPECIAL, /* F4 */
[0x0b] = SPECIAL, /* F12 */
[0x0c] = SPECIAL, /* F5 */
[0x0d] = SPECIAL, /* RAlt */
[0x0e] = SPECIAL, /* F6 */
[0x0f] = SPECIAL,
[0x10] = SPECIAL, /* F7 */
[0x11] = SPECIAL, /* F8 */
[0x12] = SPECIAL, /* F9 */
[0x13] = SPECIAL, /* LAlt */
[0x14] = SPECIAL, /* Up Arrow */
[0x15] = SPECIAL, /* Pause */
[0x16] = SPECIAL,
[0x17] = SPECIAL, /* Scroll Lock */
[0x18] = SPECIAL, /* Left Arrow */
[0x19] = SPECIAL,
[0x1a] = SPECIAL,
[0x1b] = SPECIAL, /* Down Arrow */
[0x1c] = SPECIAL, /* Right Arrow */
[0x1d] = SPECIAL, /* Esc */
[0x1e] = '!',
[0x1f] = '@',
[0x20] = '#',
[0x21] = '$',
[0x22] = '%',
[0x23] = '^',
[0x24] = '&',
[0x25] = '*',
[0x26] = '(',
[0x27] = ')',
[0x28] = '_',
[0x29] = '+',
[0x2a] = '~',
[0x2b] = SPECIAL, /* Backspace */
[0x2c] = SPECIAL, /* Insert */
[0x2d] = SPECIAL,
[0x2e] = '/', /* numeric keypad */
[0x2f] = '*', /* numeric keypad */
[0x30] = SPECIAL,
[0x31] = SPECIAL,
[0x32] = '.', /* numeric keypad */
[0x33] = SPECIAL,
[0x34] = SPECIAL, /* Home */
[0x35] = SPECIAL, /* Tab */
[0x36] = 'Q',
[0x37] = 'W',
[0x38] = 'E',
[0x39] = 'R',
[0x3a] = 'T',
[0x3b] = 'Y',
[0x3c] = 'U',
[0x3d] = 'I',
[0x3e] = 'O',
[0x3f] = 'P',
[0x40] = '{',
[0x41] = '}',
[0x42] = SPECIAL, /* Del */
[0x43] = SPECIAL,
[0x44] = '7', /* numeric keypad */
[0x45] = '8', /* numeric keypad */
[0x46] = '9', /* numeric keypad */
[0x47] = '-', /* numeric keypad */
[0x48] = SPECIAL,
[0x49] = SPECIAL,
[0x4a] = SPECIAL, /* End */
[0x4b] = SPECIAL,
[0x4c] = SPECIAL, /* Control */
[0x4d] = 'A',
[0x4e] = 'S',
[0x4f] = 'D',
[0x50] = 'F',
[0x51] = 'G',
[0x52] = 'H',
[0x53] = 'J',
[0x54] = 'K',
[0x55] = 'L',
[0x56] = ':',
[0x57] = '"',
[0x58] = '|',
[0x59] = SPECIAL, /* Enter */
[0x5a] = SPECIAL, /* Enter on numeric keypad */
[0x5b] = '4', /* numeric keypad */
[0x5c] = '5', /* numeric keypad */
[0x5d] = '6', /* numeric keypad */
[0x5e] = '0', /* numeric keypad */
[0x5f] = SPECIAL,
[0x60] = SPECIAL, /* Page Up */
[0x61] = SPECIAL,
[0x62] = SPECIAL, /* Num Lock */
[0x63] = SPECIAL, /* LShift */
[0x64] = 'Z',
[0x65] = 'X',
[0x66] = 'C',
[0x67] = 'V',
[0x68] = 'B',
[0x69] = 'N',
[0x6a] = 'M',
[0x6b] = '<',
[0x6c] = '>',
[0x6d] = '?',
[0x6e] = SPECIAL, /* RShift */
[0x6f] = SPECIAL,
[0x70] = '1', /* numeric keypad */
[0x71] = '2', /* numeric keypad */
[0x72] = '3', /* numeric keypad */
[0x73] = SPECIAL,
[0x74] = SPECIAL,
[0x75] = SPECIAL,
[0x76] = SPECIAL,
[0x77] = SPECIAL, /* Caps Lock */
[0x78] = SPECIAL,
[0x79] = ' ',
[0x7a] = SPECIAL,
[0x7b] = SPECIAL, /* Page Down */
[0x7c] = SPECIAL,
[0x7d] = '+', /* numeric key pad */
[0x7e] = SPECIAL,
[0x7f] = SPECIAL
};
 
/** @}
*/
/branches/dd/kernel/genarch/src/kbrd
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/src/fb/helenos.xbm
File deleted
/branches/dd/kernel/genarch/src/fb/logo-196x66.c
0,0 → 1,13110
/*
* Copyright (c) 2008 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/** @file
*/
 
#include <genarch/fb/logo-196x66.h>
 
uint32_t fb_logo[LOGO_WIDTH * LOGO_HEIGHT] = {
 
/* Scanline 0 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 1 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 2 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 3 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xf9f9f8,
0xf5f3f1,
0xf3f1ee,
0xf3f2ef,
0xf7f7f6,
0xfbfbfb,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 4 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefd,
0xf9f9f8,
0xf3f1ed,
0xeeeae4,
0xece8df,
0xebe6de,
0xeae5dd,
0xeae5dd,
0xeae5de,
0xeae8e4,
0xf1f1f0,
0xfbfbfb,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 5 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefd,
0xf9f9f8,
0xf4f2ef,
0xefebe5,
0xf0ece5,
0xeeeae4,
0xe3e0db,
0xdfdcd8,
0xe2e0db,
0xeeebe6,
0xeeebe5,
0xeae5dd,
0xe8e4db,
0xe5e1db,
0xe9e9e8,
0xfafafa,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 6 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefd,
0xfaf9f9,
0xf4f3ef,
0xefece6,
0xf0ece5,
0xeeebe5,
0xdfdcd7,
0xc6c4bd,
0xbebcb5,
0xcfcdc8,
0xd3d2cd,
0xd1cfca,
0xc0beb7,
0xcccac3,
0xeae7e3,
0xe9e5dd,
0xe7e3da,
0xdedbd8,
0xe8e8e7,
0xfbfbfb,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 7 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xfafafa,
0xf5f4f0,
0xf1eee8,
0xf0ece4,
0xf0ede7,
0xe1ded9,
0xc9c7c1,
0xbebcb4,
0xd1cfca,
0xecebe8,
0xf9f9f7,
0xfaf9f7,
0xf8f6f4,
0xf7f5f2,
0xf4f3f1,
0xdcdad6,
0xc2c0b9,
0xe6e4de,
0xe5e2dc,
0xe2ddd8,
0xd7d5d4,
0xf2f2f1,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 8 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xfbfbfb,
0xf6f5f2,
0xf1eee9,
0xf1ede5,
0xf1ede6,
0xe4e1db,
0xcecbc4,
0xbebcb5,
0xcfcdc8,
0xe7e6e4,
0xf8f8f6,
0xfafaf8,
0xf9f7f5,
0xf7f5f2,
0xf5f3f0,
0xf5f3f0,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xd9d7d2,
0xc8c5bf,
0xe9e5e0,
0xe4dfd8,
0xd5d2ce,
0xe1e1e1,
0xfbfbfb,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 9 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xfbfbfb,
0xf7f6f3,
0xf2efea,
0xf1ede6,
0xf1eee7,
0xe5e3de,
0xd0cec7,
0xbfbdb5,
0xcdcbc5,
0xe4e3e0,
0xf7f7f6,
0xfbfaf9,
0xf9f8f6,
0xf8f6f3,
0xf7f5f2,
0xf6f4f1,
0xf5f3f0,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xf1efeb,
0xc5c2bb,
0xe2dfdb,
0xe5e0da,
0xded9d3,
0xd3d2d1,
0xf4f4f4,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 10 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xfcfcfb,
0xf8f6f4,
0xf3f0eb,
0xf1eee7,
0xf2efe8,
0xe8e5df,
0xd3d1cb,
0xc0beb6,
0xcbc9c3,
0xe1e0dc,
0xf5f4f3,
0xfbfaf8,
0xfaf9f7,
0xf8f7f4,
0xf8f6f3,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf5f3f0,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xf2f0ec,
0xf2efec,
0xdbd9d4,
0xcdcbc4,
0xe8e4de,
0xe3ded7,
0xd0cecb,
0xe7e7e6,
0xfdfdfc,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 11 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xfcfcfb,
0xf8f7f4,
0xf4f1ed,
0xf2eee8,
0xf3efe9,
0xeae7e1,
0xd6d4cd,
0xc3c1b9,
0xcac8c2,
0xdddcd8,
0xf3f2f1,
0xfafaf8,
0xfbfaf7,
0xf9f7f5,
0xf8f6f4,
0xf8f6f3,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf6f4f1,
0xf5f3f0,
0xf5f3f0,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xf3f1ed,
0xf2f0ec,
0xf1efeb,
0xf1eeeb,
0xece9e5,
0xc3c1ba,
0xe5e3de,
0xe3ded7,
0xd9d5d0,
0xd6d5d5,
0xf7f7f7,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 12 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xfcfcfc,
0xf9f8f5,
0xf5f2ee,
0xf3efe8,
0xf4f0e9,
0xece9e3,
0xd9d7d1,
0xc4c2bb,
0xc8c6c0,
0xd9d8d4,
0xf1f0ef,
0xfaf9f8,
0xfbfaf8,
0xfaf8f5,
0xf9f7f4,
0xf8f6f4,
0xf8f6f3,
0xf8f6f3,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf5f3f0,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xf2f0ec,
0xf2efec,
0xf1eeeb,
0xf1eeeb,
0xf0edea,
0xf0ede9,
0xd2cfc9,
0xd3d2cc,
0xe4e0db,
0xded9d3,
0xcfccca,
0xededec,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 13 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xf9f9f7,
0xf5f3f0,
0xf3efe8,
0xf4f0e9,
0xeeeae5,
0xdddad4,
0xc7c4bd,
0xc7c6bf,
0xd7d6d1,
0xeeedeb,
0xf9f9f8,
0xfcfbfa,
0xfaf9f6,
0xf9f7f4,
0xf9f7f4,
0xf9f7f4,
0xf8f6f4,
0xf8f6f3,
0xf7f5f2,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf5f3f0,
0xf5f3f0,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xf3f1ed,
0xf2f0ec,
0xf1efeb,
0xf1eeeb,
0xf1eeea,
0xf0ede9,
0xefece8,
0xefece8,
0xe4e2dd,
0xc4c2bb,
0xe5e2de,
0xdfdad3,
0xd3d0cb,
0xdbdbdb,
0xfafafa,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 14 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xfaf9f7,
0xf6f4f0,
0xf3f0e9,
0xf4f0ea,
0xefece6,
0xdfddd7,
0xcbc8c1,
0xc7c5be,
0xd4d3ce,
0xebebe8,
0xf8f8f6,
0xfcfcfa,
0xfbfaf7,
0xfaf9f6,
0xf9f7f5,
0xf9f7f4,
0xf9f7f4,
0xf9f7f4,
0xf8f6f4,
0xf7f5f2,
0xf7f5f2,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xf3f1ed,
0xf2f0ec,
0xf2efec,
0xf1eeeb,
0xf1eeeb,
0xf0edea,
0xf0ede9,
0xefece8,
0xefece8,
0xeeebe7,
0xedeae6,
0xc8c6bf,
0xdcdad5,
0xe1dcd6,
0xdbd7d0,
0xd0cfcd,
0xf1f0f0,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 15 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xfafaf9,
0xf7f5f1,
0xf4f1ea,
0xf5f1ea,
0xf1ede7,
0xe2e0da,
0xcccac3,
0xc6c5be,
0xd1cfca,
0xe9e8e6,
0xf8f7f6,
0xfcfcfb,
0xfbfaf8,
0xfaf9f6,
0xfaf9f6,
0xf9f8f5,
0xf9f7f4,
0xf9f7f4,
0xf9f7f4,
0xf8f6f4,
0xf8f6f3,
0xf7f5f2,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xf2f0ed,
0xf2f0ec,
0xf2efec,
0xf1eeeb,
0xf1eeeb,
0xf0edea,
0xf0ede9,
0xefece8,
0xeeebe7,
0xeeebe7,
0xedeae6,
0xedeae5,
0xdedbd5,
0xc7c6bf,
0xe5e2dd,
0xded9d3,
0xcfcdc9,
0xe2e2e2,
0xfbfbfb,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 16 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xfbfbf9,
0xf6f3ed,
0xf4f1e9,
0xf4f1eb,
0xe7e4df,
0xcfcdc6,
0xc7c5be,
0xceccc7,
0xe6e5e2,
0xf7f6f5,
0xfdfcfb,
0xfcfbf9,
0xfaf9f7,
0xfaf9f6,
0xfaf9f6,
0xfaf9f6,
0xf9f8f5,
0xf9f7f4,
0xf9f7f4,
0xf9f7f4,
0xf8f6f4,
0xf8f6f3,
0xf7f5f2,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xe0dedb,
0xb4b2b1,
0xb6b5b4,
0xe0dddb,
0xf1eeeb,
0xf1eeea,
0xf0ede9,
0xefece8,
0xefece8,
0xeeebe7,
0xeeebe7,
0xedeae6,
0xece9e5,
0xece9e4,
0xe8e6e1,
0xc3c1ba,
0xdfddd9,
0xddd9d3,
0xd6d3cd,
0xd3d2d1,
0xf5f5f4,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 17 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfafaf9,
0xf4f0e8,
0xf5f1ea,
0xf3f1ed,
0xcbc9c3,
0xcac8c2,
0xe3e2df,
0xf5f4f3,
0xfdfcfb,
0xfdfbfa,
0xfcfaf8,
0xfbf9f7,
0xfaf9f6,
0xfaf9f6,
0xfaf9f6,
0xf9f8f5,
0xf9f7f4,
0xf9f7f4,
0xf9f7f4,
0xf8f6f4,
0xf8f6f4,
0xf7f5f2,
0xf7f5f2,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xe1dedc,
0x7f7e7e,
0x706f6f,
0x757374,
0x8c8c8b,
0xe1dedb,
0xf0ede9,
0xefece8,
0xefece8,
0xeeebe7,
0xedeae6,
0xedeae5,
0xece9e4,
0xebe9e4,
0xeae8e3,
0xeae8e3,
0xd4d2cb,
0xcdcbc5,
0xe1ded8,
0xdad6cf,
0xcdcbc8,
0xe8e8e8,
0xfdfdfd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 18 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfcfcfc,
0xf4f0eb,
0xf4f0e7,
0xf8f6f3,
0xc6c4bd,
0xdcdad7,
0xfbfbfa,
0xfdfcfb,
0xfcfaf8,
0xfcfaf8,
0xfbfaf7,
0xfaf9f6,
0xfaf9f6,
0xfaf9f6,
0xfaf9f6,
0xf9f7f5,
0xf9f7f4,
0xf9f7f4,
0xf8f6f4,
0xf8f6f4,
0xf8f6f3,
0xf7f5f2,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xf3f1ed,
0xb3b1af,
0x716f70,
0x7c7b7b,
0x898989,
0x8f8e8e,
0xbdbbba,
0xeeebe7,
0xeeebe7,
0xeeebe7,
0xedeae6,
0xece9e5,
0xece9e4,
0xebe8e3,
0xeae8e3,
0xe9e7e2,
0xe8e6e1,
0xe2e0db,
0xc1bfb8,
0xe2dfdb,
0xdad7d0,
0xd2d0cb,
0xd7d7d7,
0xf8f8f7,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 19 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf0f0ef,
0xf1ede4,
0xf8f6f0,
0xdbd9d4,
0xd3d2cd,
0xfdfcfb,
0xfcfbf9,
0xfcfaf8,
0xfcfaf8,
0xfbfaf7,
0xfaf9f6,
0xfaf9f6,
0xfaf9f6,
0xf9f8f5,
0xf9f7f5,
0xf9f7f4,
0xf9f7f4,
0xf8f6f4,
0xf8f6f4,
0xf8f6f3,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xf2f0ed,
0xf2f0ec,
0xaeacab,
0x7a7979,
0x8f8e8e,
0xa3a2a2,
0xabaaab,
0xafaead,
0xe8e5e1,
0xeeebe7,
0xedeae6,
0xece9e4,
0xebe8e4,
0xeae8e3,
0xe9e7e2,
0xe9e7e2,
0xe8e6e1,
0xe7e5e0,
0xe7e4df,
0xcac8c1,
0xd4d2cc,
0xdcd9d3,
0xd6d3ce,
0xcdccca,
0xeeeeed,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 20 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefd,
0xe1e0dd,
0xf0ebe2,
0xfbfaf7,
0xc3c1ba,
0xf3f2f0,
0xfcfbf9,
0xfcfaf8,
0xfcfaf8,
0xfbf9f7,
0xfaf9f6,
0xfaf9f6,
0xfaf9f6,
0xf9f8f5,
0xf9f7f4,
0xf9f7f4,
0xf8f6f4,
0xf8f6f4,
0xf8f6f4,
0xf7f5f2,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xf3f1ee,
0xf2f0ec,
0xf2f0ec,
0xf1eeeb,
0xd5d3d1,
0x838282,
0x9d9c9c,
0xb4b3b3,
0xbdbcbd,
0xb6b5b5,
0xd7d4d1,
0xedeae6,
0xece9e5,
0xeae8e3,
0xeae8e3,
0xe9e7e2,
0xe9e7e2,
0xe7e5e0,
0xe7e4df,
0xe6e3de,
0xe5e2dd,
0xdbd8d3,
0xc3c0ba,
0xe1ded9,
0xd8d4ce,
0xcdcac6,
0xdedddd,
0xfafafa,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 21 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfcfcfc,
0xd2d1cd,
0xefeae1,
0xfcfaf8,
0xc3c1ba,
0xf9f8f7,
0xfcfaf8,
0xfcfaf8,
0xfbf9f7,
0xfaf9f6,
0xfaf9f6,
0xfaf9f6,
0xf9f7f5,
0xf9f7f4,
0xf9f7f4,
0xf8f6f4,
0xf8f6f4,
0xf8f6f3,
0xf7f5f2,
0xf7f5f2,
0xf0eeeb,
0xebe9e6,
0xf3f1ee,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xf3f1ed,
0xf2f0ec,
0xf2efec,
0xf1eeeb,
0xf1eeea,
0xefece9,
0x9c9b9a,
0xa1a0a0,
0xb9b7b8,
0xc2c0c1,
0xbfbdbe,
0xc2c1c0,
0xe9e6e2,
0xeae8e3,
0xe9e7e2,
0xe9e7e2,
0xe8e6e1,
0xe7e5e0,
0xe7e4df,
0xe6e3de,
0xe5e2dd,
0xe4e1dc,
0xe3dfda,
0xc4c1ba,
0xdbd9d4,
0xd8d5ce,
0xd4d0cb,
0xcfcecd,
0xf2f2f2,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xe3e3e3,
0xbbbbbb,
0x9d9d9d,
0x989898,
0xa4a4a4,
0xbfbfbf,
0xeaeaea,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf1f1f1,
0xc4c4c4,
0xa6a6a6,
0x989898,
0xa2a2a2,
0xc5c5c5,
0xf1f0f0,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 22 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfbfbfb,
0xb9b8b6,
0xeae5dd,
0xf9f6f3,
0xc4c2bb,
0xf2f2f0,
0xfbfaf7,
0xfaf9f6,
0xfaf9f6,
0xfaf9f6,
0xf9f8f5,
0xf9f7f5,
0xf9f7f4,
0xf8f6f4,
0xf8f6f4,
0xf8f6f4,
0xf8f6f3,
0xf7f5f2,
0xf6f4f1,
0xd2d0ce,
0x908f8e,
0x888686,
0xb3b1b0,
0xedebe8,
0xf3f1ee,
0xf3f1ee,
0xf3f1ed,
0xf2f0ec,
0xf2efec,
0xf1eeeb,
0xf0edea,
0xf0ede9,
0xefece8,
0xc6c4c2,
0x9c9b9b,
0xb4b3b3,
0xc1bfc0,
0xc1c0c0,
0xbab9b9,
0xdeddd9,
0xe9e7e2,
0xe9e7e2,
0xe7e5e0,
0xe7e4df,
0xe7e4df,
0xe5e2dd,
0xe4e1dc,
0xe4e0db,
0xe4e0db,
0xe3dfda,
0xd4d1cb,
0xc6c4bd,
0xdfdcd7,
0xd7d3cc,
0xcbc9c6,
0xe4e4e4,
0xfcfcfc,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xcbcbcb,
0x5f5f5f,
0x343434,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x363636,
0x737272,
0xdedede,
0xffffff,
0xffffff,
0xffffff,
0xf2f1f1,
0x8e8e8e,
0x3b3b3b,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x393939,
0x8a8a8a,
0xf2f2f2,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 23 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfbfbfb,
0xbbbbba,
0xc8c4bd,
0xf4f1eb,
0xd6d4cf,
0xdbd9d5,
0xfaf9f6,
0xfaf9f6,
0xfaf9f6,
0xf9f8f5,
0xf9f7f4,
0xf9f7f4,
0xf8f6f4,
0xf8f6f4,
0xf8f6f4,
0xf7f5f3,
0xf7f5f2,
0xf6f4f1,
0xe4e2df,
0x7f7e7e,
0x717071,
0x7a7878,
0x807f7f,
0xbbbab9,
0xf3f1ee,
0xf2f0ec,
0xf2f0ec,
0xf1eeeb,
0xf1eeeb,
0xf0edea,
0xf0ede9,
0xefece8,
0xefece8,
0xe7e4e0,
0x999897,
0xacabab,
0xbebcbd,
0xc3c1c2,
0xbebcbd,
0xc9c8c7,
0xe7e5e0,
0xe7e5e0,
0xe7e4df,
0xe6e3de,
0xe5e2dd,
0xe4e1dc,
0xe4e0db,
0xe3dfda,
0xe3dfda,
0xe2ded9,
0xdedad5,
0xc0beb6,
0xdedad5,
0xd6d2cb,
0xd1cec8,
0xd2d2d2,
0xf6f6f6,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb0afaf,
0x383838,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x414141,
0xc8c8c8,
0xffffff,
0xefefef,
0x626262,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x575656,
0xefefef,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 24 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfc,
0xd9d9d9,
0x9a9893,
0xede9e0,
0xefede8,
0xc3c1bb,
0xf7f6f3,
0xfaf9f6,
0xf9f8f5,
0xf9f7f4,
0xf8f6f4,
0xf8f6f4,
0xf8f6f4,
0xf8f6f3,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf5f3f0,
0xcac9c7,
0x717071,
0x7e7e7e,
0x908f8f,
0x9a9998,
0xa5a4a3,
0xebeae6,
0xf2efec,
0xf1eeeb,
0xf0edea,
0xf0ede9,
0xefece8,
0xefece8,
0xeeebe7,
0xeeebe7,
0xedeae6,
0xb5b3b1,
0xa2a1a1,
0xb8b7b7,
0xc2c0c1,
0xc1bfc0,
0xbcbaba,
0xe1dfda,
0xe7e4df,
0xe6e3de,
0xe5e1dc,
0xe4e0db,
0xe4e0db,
0xe3dfda,
0xe2deda,
0xe1ddd8,
0xe1ddd8,
0xe0dbd6,
0xcbc8c1,
0xceccc7,
0xdad7d1,
0xd4d0ca,
0xcbc9c7,
0xeaeae9,
0xfdfdfd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xd6d6d6,
0x3b3b3b,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x555555,
0xececec,
0x919191,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x7e7e7e,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 25 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xe9e9e9,
0x989694,
0xd8d4cc,
0xf5f3ed,
0xc8c6bf,
0xe8e6e2,
0xf9f7f5,
0xf9f7f4,
0xf8f6f4,
0xf8f6f4,
0xf8f6f4,
0xf7f5f3,
0xf7f5f2,
0xf6f4f1,
0xf6f4f1,
0xf5f3f0,
0xf4f2ef,
0xd8d6d4,
0x7d7d7c,
0x8f8e8e,
0xa6a5a6,
0xb3b2b3,
0xb1b0b0,
0xd7d5d2,
0xf1eeeb,
0xf0edea,
0xf0ede9,
0xefece8,
0xefece8,
0xeeebe7,
0xedeae6,
0xedeae6,
0xece9e5,
0xd3d0cd,
0x999897,
0xb1afb0,
0xc0bebf,
0xc3c1c2,
0xbbbabb,
0xd2d0cc,
0xe5e2dd,
0xe4e1dc,
0xe4e0db,
0xe3dfda,
0xe3dfda,
0xe2ded9,
0xe1ddd8,
0xe0dcd7,
0xe0dbd6,
0xdfdad5,
0xd9d5cf,
0xbfbdb6,
0xdedcd8,
0xd4d0ca,
0xcccac6,
0xd9d8d8,
0xf9f9f9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7a7a7a,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x494949,
0x666565,
0x3f3f3f,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x939392,
0x4e4e4e,
0x323232,
0x323232,
0x323232,
0x323232,
0x3f3f3f,
0x686868,
0x4c4c4c,
0x323232,
0x323232,
0x323232,
0x323232,
0x343434,
0xe8e7e7,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 26 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf5f5f4,
0xbcbbba,
0xaaa7a2,
0xbebcb6,
0xa19f9c,
0xa5a4a1,
0xf4f2f0,
0xf8f6f4,
0xf8f6f4,
0xf8f6f3,
0xf7f5f2,
0xf7f5f2,
0xf6f4f1,
0xf6f4f1,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xedebe8,
0x9c9b9a,
0x999898,
0xb3b1b2,
0xc0bebf,
0xbebcbd,
0xc2c0c0,
0xefece9,
0xefece8,
0xefece8,
0xeeebe7,
0xeeebe7,
0xedeae6,
0xedeae6,
0xe4e1de,
0xc7c5c2,
0x9b9a99,
0x8d8c8c,
0xa9a8a8,
0xbdbbbb,
0xc3c1c2,
0xc0bebe,
0xc1bfbe,
0xe1ded9,
0xe4e0db,
0xe3dfda,
0xe2deda,
0xe1ddd9,
0xe1ddd8,
0xe0dbd6,
0xe0dbd6,
0xdedad5,
0xdddad5,
0xdcd8d3,
0xc4c1bb,
0xd5d3ce,
0xd6d2cc,
0xd2cec9,
0xcbcac9,
0xefefef,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf6f6f6,
0x424242,
0x323232,
0x323232,
0x323232,
0x323232,
0x565656,
0xebebeb,
0xffffff,
0xd4d4d4,
0x414141,
0x323232,
0x323232,
0x323232,
0x323232,
0x414141,
0x343434,
0x323232,
0x323232,
0x323232,
0x434343,
0xe1e1e0,
0xffffff,
0xf1f1f1,
0x575757,
0x323232,
0x323232,
0x323232,
0x333333,
0xaeaeae,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 27 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfcfcfc,
0xe0e0e0,
0x8e8c89,
0x696865,
0x343434,
0x343434,
0xc8c7c7,
0xf8f6f4,
0xf7f5f3,
0xf7f5f2,
0xf6f4f1,
0xf6f4f1,
0xf6f4f1,
0xf5f3f0,
0xf4f2ef,
0xf4f2ef,
0xf3f1ee,
0xf3f1ed,
0xc4c2c1,
0x989797,
0xb3b1b2,
0xc1bfc0,
0xc2c0c1,
0xbcbabb,
0xe1dfdc,
0xeeebe7,
0xeeebe7,
0xedeae6,
0xebe8e4,
0xdedbd8,
0xb0aeac,
0x828181,
0x6f6e6f,
0x797877,
0x8c8c8c,
0xa7a6a6,
0xbab9ba,
0xc3c1c2,
0xc2c0c1,
0xb9b8b8,
0xd7d4d0,
0xe3dfda,
0xe2deda,
0xe1ddd8,
0xe0dcd7,
0xe0dbd6,
0xdfdad5,
0xdedad5,
0xddd9d4,
0xdbd8d3,
0xdad7d2,
0xd2cfca,
0xc0beb7,
0xdddad6,
0xd4d0ca,
0xcbc8c5,
0xdfdfdf,
0xfbfbfb,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xdedede,
0x3b3b3b,
0x323232,
0x323232,
0x323232,
0x323232,
0x929291,
0xffffff,
0xffffff,
0xfdfdfd,
0x616161,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x5c5c5c,
0xffffff,
0xffffff,
0xfefefe,
0x848484,
0x323232,
0x323232,
0x323232,
0x323232,
0x858585,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 28 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xefefef,
0xacaaaa,
0x83807c,
0x403f3f,
0x323232,
0x7d7c7c,
0xf4f2f0,
0xf7f5f2,
0xf6f4f1,
0xf6f4f1,
0xf5f3f0,
0xf5f3f0,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xf2f0ed,
0xf2f0ec,
0xe5e2e0,
0x9e9d9d,
0xacabab,
0xbebcbd,
0xc2c1c1,
0xbdbcbc,
0xcccac8,
0xedeae6,
0xe8e5e2,
0xcdcbc9,
0x9b9a98,
0x767575,
0x717070,
0x777676,
0x7e7e7d,
0x8b8a8a,
0x9c9b9b,
0xafaeae,
0xbdbcbc,
0xc3c1c2,
0xc3c1c2,
0xbebdbd,
0xc6c4c2,
0xe1ddd9,
0xe1dcd7,
0xe0dbd6,
0xe0dbd6,
0xdfdad5,
0xddd9d4,
0xddd9d4,
0xdbd8d3,
0xdad7d2,
0xd9d6d1,
0xd8d5cf,
0xc0bdb6,
0xdbd9d4,
0xd4d0ca,
0xd1cdc8,
0xcecdcc,
0xf3f3f3,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xe0e0e0,
0xbfbfbf,
0xb4b4b4,
0xc0c0c0,
0xdfdfdf,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xebebeb,
0xc8c8c8,
0xb4b4b4,
0xbababa,
0xd5d4d4,
0xfafafa,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf1f1f1,
0xc7c7c7,
0xb4b4b4,
0xbfbfbf,
0xdddddd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xd5d5d5,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0xb1b1b1,
0xffffff,
0xffffff,
0xffffff,
0x787878,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x474747,
0xebebeb,
0xffffff,
0xffffff,
0xa3a3a3,
0x323232,
0x323232,
0x323232,
0x323232,
0x747474,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 29 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf9f9f9,
0xd0d0d0,
0x8c8a85,
0x595958,
0x333333,
0x414141,
0xe0dfdc,
0xf6f4f1,
0xf6f4f1,
0xf5f3f0,
0xf5f3f0,
0xf4f2ef,
0xf3f1ee,
0xf3f1ed,
0xf2f0ec,
0xf2efec,
0xf1eeeb,
0xf0edea,
0xb7b5b4,
0xa2a1a1,
0xb9b8b8,
0xc2c0c1,
0xc1c0c0,
0xbbb9ba,
0xcac8c5,
0x999797,
0x747373,
0x737272,
0x7a7979,
0x848382,
0x8f8e8e,
0x9a9999,
0xa6a5a5,
0xb1b0b1,
0xbbb9ba,
0xc1bfc0,
0xc4c2c3,
0xc4c2c3,
0xc1bfc0,
0xbbb9b9,
0xdad6d2,
0xe0dbd6,
0xdfdbd6,
0xdedad5,
0xddd9d4,
0xdcd8d3,
0xdad7d2,
0xdad7d2,
0xd9d6d1,
0xd9d6d0,
0xd9d6d0,
0xccc9c3,
0xc6c4be,
0xdbd8d3,
0xd4d0ca,
0xcac8c5,
0xe6e6e6,
0xfdfdfc,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xffffff,
0xffffff,
0xfafafa,
0xb1b0b0,
0x505050,
0x323232,
0x323232,
0x323232,
0x323232,
0x333333,
0x5c5c5c,
0xd1d1d1,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xffffff,
0xffffff,
0xffffff,
0xcfcfcf,
0x676767,
0x363636,
0x323232,
0x323232,
0x323232,
0x323232,
0x484847,
0xacacac,
0xfbfbfb,
0xffffff,
0xffffff,
0xe2e2e2,
0x4d4d4d,
0x4e4e4e,
0xa4a4a4,
0xfaf9f9,
0x979797,
0x3b3b3b,
0x323232,
0x323232,
0x323232,
0x323232,
0x585857,
0xcbcbcb,
0xffffff,
0xffffff,
0xd5d5d5,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0xb1b1b1,
0xffffff,
0xffffff,
0xffffff,
0x787878,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x757575,
0xf4f4f4,
0xffffff,
0xf2f2f2,
0xe3e3e3,
0xe3e3e3,
0xe3e3e3,
0xe4e4e4,
0xebebeb,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 30 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xe9e9e9,
0x9f9d9a,
0x787672,
0x393939,
0x323232,
0xa2a1a0,
0xf6f4f1,
0xf5f3f0,
0xf4f2ef,
0xf3f1ee,
0xf3f1ee,
0xf2f0ed,
0xf2f0ec,
0xf1efec,
0xf1eeeb,
0xf0edea,
0xf0ede9,
0xd8d6d3,
0x999898,
0xb1b0b0,
0xbfbebe,
0xc2c0c1,
0xbbbabb,
0xa9a8a8,
0x929191,
0x868585,
0x8a8888,
0x939292,
0xa09f9f,
0xabaaaa,
0xb4b2b3,
0xbbb9ba,
0xc3c1c2,
0xceccca,
0xc3c1c2,
0xc3c1c2,
0xc3c1c2,
0xc3c1c2,
0xbcbbbb,
0xcbc8c6,
0xdfdad5,
0xddd9d4,
0xddd9d4,
0xdbd8d3,
0xdad7d2,
0xdad7d2,
0xd9d6d0,
0xd9d6d0,
0xd8d5cf,
0xd8d5cf,
0xd5d1cb,
0xbdbbb3,
0xdcd9d6,
0xd4d0ca,
0xd0cdc7,
0xd3d3d3,
0xf7f7f7,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xffffff,
0xf4f4f4,
0x7b7a7a,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x373737,
0xbcbcbc,
0xffffff,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xffffff,
0xffffff,
0xa7a7a7,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x343434,
0x888888,
0xf9f9f9,
0xffffff,
0xdedede,
0x323232,
0x323232,
0x8f8f8f,
0x7f7f7f,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x353535,
0xc4c4c4,
0xffffff,
0xd5d5d5,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0xb1b1b1,
0xffffff,
0xffffff,
0xffffff,
0x787878,
0x323232,
0x323232,
0x323232,
0x323232,
0x424242,
0x484848,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x595959,
0xc7c7c7,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 31 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf4f4f4,
0xbdbcbb,
0x898782,
0x4b4a4a,
0x323232,
0x5d5d5d,
0xebe9e7,
0xf4f2ef,
0xf3f1ee,
0xf2f0ed,
0xf2f0ec,
0xf1efec,
0xf1eeeb,
0xf0eeea,
0xf0edea,
0xf0ede9,
0xefece8,
0xe9e6e3,
0xa7a6a5,
0xa7a6a6,
0xbcbabb,
0xc3c1c2,
0xc0bebf,
0xb6b4b5,
0xa8a7a7,
0xa2a0a0,
0xa5a5a5,
0xafaeae,
0xb8b6b6,
0xbdbcbc,
0xc9c7c6,
0xd7d5d2,
0xe2deda,
0xe3dfda,
0xc6c4c3,
0xbdbbbc,
0xc1bfc0,
0xc3c1c2,
0xc0bebf,
0xbebcbc,
0xdad7d2,
0xdcd9d4,
0xdbd8d3,
0xdad7d2,
0xdad7d1,
0xd9d6d0,
0xd9d6d0,
0xd8d5cf,
0xd8d4cf,
0xd7d3cd,
0xd7d3cd,
0xc4c2ba,
0xd0cec8,
0xd7d3cd,
0xd3cfc9,
0xc9c8c6,
0xececec,
0xfefefd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xfafafa,
0x838383,
0x323232,
0x323232,
0x424242,
0x9f9f9f,
0xdbdbdb,
0xe3e3e3,
0xcfcfcf,
0x858585,
0x353535,
0x323232,
0x3a3a39,
0xe3e3e3,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xffffff,
0xb6b6b6,
0x383838,
0x323232,
0x363636,
0x818181,
0xcfcfcf,
0xe4e4e4,
0xd9d9d9,
0xa1a0a0,
0x454545,
0x323232,
0x353535,
0xaaaaaa,
0xffffff,
0xdedede,
0x323232,
0x323232,
0x444343,
0x323232,
0x4b4b4b,
0xa9a8a8,
0xdedede,
0xe3e3e3,
0xc3c3c2,
0x5d5d5d,
0x323232,
0x323232,
0x525252,
0xfafafa,
0xd5d5d5,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0xb1b1b1,
0xffffff,
0xffffff,
0xffffff,
0x787878,
0x323232,
0x323232,
0x323232,
0x323232,
0x4f4f4f,
0x6f6f6f,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x353535,
0x777777,
0xe7e7e7,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 32 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfcfcfb,
0xe0e0e0,
0x92908b,
0x6a6966,
0x353535,
0x343434,
0xc7c6c6,
0xf3f1ee,
0xf2f0ed,
0xf2f0ec,
0xf1efec,
0xf1eeeb,
0xf0edea,
0xf0edea,
0xefece9,
0xefece8,
0xeeebe7,
0xeeebe7,
0xc8c7c4,
0x9c9b9b,
0xb5b4b4,
0xc1bfc0,
0xc3c1c2,
0xbfbdbe,
0xbab8b9,
0xb8b6b7,
0xbab9ba,
0xc1c0c0,
0xd0cecc,
0xdfdcd8,
0xe4e0db,
0xe3dfda,
0xe3dfda,
0xe2deda,
0xcfccc9,
0xafaeae,
0xbab8b9,
0xc1c0c0,
0xc2c0c1,
0xbab9b9,
0xcfcdc9,
0xdad7d2,
0xdad7d2,
0xd9d6d1,
0xd9d6d0,
0xd9d6d0,
0xd8d5cf,
0xd8d4cf,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd2cec8,
0xbdbbb3,
0xdedbd7,
0xd4d0ca,
0xcbc9c5,
0xdbdbda,
0xfafafa,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0x515151,
0x686868,
0x686868,
0x686868,
0x686868,
0x686868,
0x686868,
0x686868,
0x686868,
0x686868,
0x686868,
0x686868,
0x454545,
0x323232,
0x323232,
0xababab,
0xffffff,
0xc6c6c6,
0x363636,
0x323232,
0x4e4e4e,
0xdddddd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xadacad,
0x323232,
0x323232,
0x808080,
0xfefefe,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xefefef,
0x4c4c4c,
0x323232,
0x393939,
0xb5b5b5,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xd6d6d6,
0x464646,
0x323232,
0x525252,
0xeeeeee,
0xdedede,
0x323232,
0x323232,
0x323232,
0x575757,
0xececec,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf3f3f3,
0x464646,
0x323232,
0x323232,
0xd5d5d5,
0xd5d5d5,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0xb1b1b1,
0xffffff,
0xffffff,
0xffffff,
0x787878,
0x323232,
0x323232,
0x323232,
0x323232,
0x525252,
0xd3d3d3,
0x4b4b4b,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x3d3d3d,
0x9f9f9f,
0xfcfcfc,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 33 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xefefef,
0xacaba9,
0x83807c,
0x424141,
0x323232,
0x7c7c7b,
0xf0efec,
0xf2f0ec,
0xf1eeec,
0xf1eeeb,
0xf0edea,
0xf0edea,
0xefece8,
0xefece8,
0xeeebe7,
0xedeae6,
0xedeae6,
0xe2e0dc,
0x9f9d9d,
0xacabab,
0xbebcbd,
0xc3c1c2,
0xc3c1c2,
0xc3c1c2,
0xc9c7c6,
0xd8d6d3,
0xe3e0dc,
0xe5e2dd,
0xe4e0db,
0xe3dfda,
0xe2deda,
0xe2deda,
0xe1ddd8,
0xdcd8d4,
0xa3a1a1,
0xadacac,
0xbdbcbc,
0xc2c0c1,
0xbebcbd,
0xc1bfbe,
0xd9d6d1,
0xd9d6d0,
0xd9d6d0,
0xd8d5cf,
0xd8d5cf,
0xd8d4ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xc0bdb5,
0xd6d4d0,
0xd4d0cb,
0xd2cfc9,
0xcbcac9,
0xf1f1f0,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0xababab,
0xfbfbfb,
0x757575,
0x323232,
0x3c3c3c,
0xc6c6c6,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfbfbfb,
0x605f5f,
0x323232,
0x393938,
0xf3f3f3,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xacacac,
0x343434,
0x323232,
0x939393,
0xfdfdfd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x9a9a9a,
0x323232,
0x353535,
0xb8b8b8,
0xdedede,
0x323232,
0x323232,
0x3a3a3a,
0xc6c6c6,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x8a8a8a,
0x323232,
0x323232,
0xb2b2b2,
0xd5d5d5,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0xb1b1b1,
0xffffff,
0xffffff,
0xffffff,
0x787878,
0x323232,
0x323232,
0x323232,
0x323232,
0x525252,
0xefefef,
0xd4d4d4,
0x505050,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x333333,
0x6e6e6e,
0xf9f9f9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 34 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf8f8f7,
0xcecdcd,
0x8d8b86,
0x5c5b59,
0x333333,
0x434343,
0xdcdbd9,
0xf1eeeb,
0xf0eeea,
0xf0edea,
0xefece9,
0xefece8,
0xeeebe7,
0xeeebe7,
0xedeae6,
0xece9e5,
0xece9e5,
0xeae8e3,
0xb5b4b2,
0xa1a0a0,
0xb7b6b7,
0xc2c1c1,
0xc4c2c3,
0xc6c4c5,
0xe2dfdb,
0xe5e2dd,
0xe4e1dc,
0xe3dfda,
0xe3dfda,
0xe2deda,
0xe1ddd9,
0xe0dcd7,
0xe0dbd6,
0xe0dbd6,
0xb4b2b0,
0xa09f9f,
0xb7b6b7,
0xc2c0c1,
0xc1c0c0,
0xbbb9b9,
0xd3d1cc,
0xd9d6d0,
0xd8d5cf,
0xd8d4cf,
0xd7d3ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xcdcac3,
0xc0beb7,
0xdddad5,
0xd4d0ca,
0xc9c7c4,
0xe1e1e1,
0xfcfcfc,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0xababab,
0xe6e6e6,
0x4b4b4b,
0x323232,
0x5b5b5b,
0xfafafa,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xa8a8a7,
0x323232,
0x323232,
0xbebebe,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0x707070,
0x323232,
0x393939,
0xdddddd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xdadada,
0x3e3e3e,
0x323232,
0x808080,
0xdedede,
0x323232,
0x323232,
0x535353,
0xfafafa,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb0b0b0,
0x323232,
0x323232,
0xacacac,
0xd5d5d5,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0xb1b1b1,
0xffffff,
0xffffff,
0xffffff,
0x787878,
0x323232,
0x323232,
0x323232,
0x323232,
0x525252,
0xefefef,
0xffffff,
0xececec,
0x7a7a7a,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x333333,
0x8b8b8b,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 35 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xe8e7e7,
0x9c9a96,
0x797873,
0x3a3a3a,
0x323232,
0xa2a1a0,
0xf2efec,
0xf0edea,
0xefece9,
0xefece8,
0xeeebe7,
0xeeebe7,
0xedeae6,
0xece9e5,
0xece9e5,
0xebe8e4,
0xe9e7e2,
0xd6d5d1,
0x999898,
0xb0afaf,
0xbfbebe,
0xc4c2c3,
0xc3c1c2,
0xd6d3d0,
0xe4e0db,
0xe3dfda,
0xe2deda,
0xe2deda,
0xe1ddd8,
0xe0dcd7,
0xe0dbd6,
0xdfdbd6,
0xddd9d4,
0xcecbc7,
0x999999,
0xaeadae,
0xbebdbe,
0xc3c1c2,
0xbcbbbb,
0xc9c7c3,
0xd8d5cf,
0xd8d4cf,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd3cfc9,
0xbdbab3,
0xdbd8d4,
0xd4d0ca,
0xd1cec8,
0xcececd,
0xf5f4f4,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xcbcbcb,
0x323232,
0x323232,
0x878686,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xcacaca,
0x323232,
0x323232,
0x9c9c9b,
0xffffff,
0x565656,
0x323232,
0x494949,
0xeaeaea,
0x454545,
0x323232,
0x575757,
0xf0f0f0,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xeaeaea,
0x515151,
0x323232,
0x5d5d5d,
0xdedede,
0x323232,
0x323232,
0x777777,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb4b4b4,
0x323232,
0x323232,
0xacacac,
0xd5d5d5,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0xb1b1b1,
0xffffff,
0xffffff,
0xffffff,
0x787878,
0x323232,
0x323232,
0x323232,
0x323232,
0x525252,
0xefefef,
0xffffff,
0xffffff,
0xfdfdfd,
0xc1c1c1,
0x525252,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x343434,
0xe1e1e1,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 36 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf4f4f3,
0xbabab9,
0x898782,
0x4e4d4c,
0x323232,
0x5e5e5e,
0xe7e5e3,
0xefece8,
0xefece8,
0xeeebe7,
0xedeae6,
0xedeae6,
0xece9e5,
0xebe8e4,
0xeae8e3,
0xe9e7e2,
0xe9e7e2,
0xe4e3de,
0xa8a7a5,
0xa6a5a5,
0xbbb9ba,
0xc3c1c2,
0xc3c1c2,
0xc4c1c1,
0xe1ded9,
0xe2deda,
0xe1ddd9,
0xe1ddd8,
0xe0dbd6,
0xe0dbd6,
0xdedad5,
0xddd9d4,
0xdbd8d3,
0xdad7d2,
0xa4a3a2,
0xa5a4a4,
0xbab9b9,
0xc2c0c1,
0xc0bebf,
0xcbc8c6,
0xd8d4ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xc7c5be,
0xc9c6c0,
0xd9d5d0,
0xd4d0ca,
0xc9c8c5,
0xe8e8e7,
0xfdfdfd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xb3b3b3,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x7e7e7e,
0xfefefe,
0x565656,
0x323232,
0x494949,
0xd6d6d6,
0x404040,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x4e4e4e,
0xcecece,
0x323232,
0x323232,
0x818181,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb4b4b4,
0x323232,
0x323232,
0xacacac,
0xd5d5d5,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0xb1b1b1,
0xffffff,
0xffffff,
0xffffff,
0x787878,
0x323232,
0x323232,
0x323232,
0x323232,
0x525252,
0xefefef,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf5f5f5,
0x949494,
0x373737,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x9d9d9d,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 37 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfbfbfb,
0xdddddd,
0x8f8d8a,
0x6c6a68,
0x363636,
0x363636,
0xc5c4c3,
0xefece8,
0xeeebe7,
0xedeae6,
0xece9e5,
0xece9e5,
0xebe8e4,
0xeae7e3,
0xe9e7e2,
0xe8e6e1,
0xe8e6e1,
0xe7e5e0,
0xc7c5c2,
0x9a9a9a,
0xb4b3b3,
0xc1bfc0,
0xc3c1c2,
0xbdbbbc,
0xd5d2ce,
0xe1ddd9,
0xe0dcd7,
0xe0dbd6,
0xdfdad5,
0xdedad5,
0xdcd8d3,
0xdbd8d3,
0xdad7d2,
0xdad7d2,
0xc6c3c0,
0x9f9d9d,
0xb2b1b2,
0xc1bfc0,
0xc5c3c3,
0xd4d0cc,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd1cec7,
0xbbb8b1,
0xdddad6,
0xd4d0ca,
0xcfcbc6,
0xd4d4d4,
0xf8f8f8,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xa5a5a5,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x7a7a7a,
0xfefefe,
0x565656,
0x323232,
0x494949,
0xcbcbcb,
0x3d3d3d,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x4d4d4d,
0xcccccc,
0x323232,
0x323232,
0x818181,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb4b4b4,
0x323232,
0x323232,
0xacacac,
0xd5d5d5,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0xb1b1b1,
0xffffff,
0xffffff,
0xffffff,
0x787878,
0x323232,
0x323232,
0x323232,
0x323232,
0x424242,
0xa4a4a4,
0xb4b4b4,
0xb4b4b4,
0xb4b4b4,
0xdadada,
0xffffff,
0xfefefe,
0xc6c6c6,
0x3d3d3d,
0x323232,
0x323232,
0x323232,
0x323232,
0x7b7b7b,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 38 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xefeeee,
0xaaa8a7,
0x827f7b,
0x434242,
0x323232,
0x7d7d7c,
0xeeece9,
0xedeae6,
0xece9e5,
0xebe8e4,
0xeae8e3,
0xe9e7e2,
0xe9e7e2,
0xe8e6e1,
0xe8e5e0,
0xe7e4df,
0xe6e3de,
0xdddad6,
0x9d9c9b,
0xabaaaa,
0xbdbcbc,
0xc3c1c2,
0xbfbdbe,
0xc3c1c0,
0xe0dcd7,
0xe0dbd6,
0xdedad5,
0xddd9d4,
0xdbd8d3,
0xdbd8d3,
0xdad7d2,
0xdad7d2,
0xd9d6d1,
0xd8d5d0,
0xcac8c3,
0xc0bebc,
0xc9c7c5,
0xd4d0cc,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd2cfc8,
0xc1beb8,
0xc7c4be,
0xd5d1cb,
0xd4d0ca,
0xc3c0b9,
0xd3d1cc,
0xd6d2cc,
0xd3cfca,
0xc8c7c6,
0xeeeeed,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xa8a8a8,
0x323232,
0x323232,
0x747474,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xe0e0e0,
0xffffff,
0x565656,
0x323232,
0x494949,
0xcecece,
0x3e3e3e,
0x323232,
0x505050,
0xc4c4c4,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xcfcfcf,
0xd5d5d5,
0xd9d9d9,
0x323232,
0x323232,
0x818181,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb4b4b4,
0x323232,
0x323232,
0xacacac,
0xd5d5d5,
0x393939,
0x323232,
0x323232,
0x323232,
0x323232,
0xb1b1b1,
0xffffff,
0xffffff,
0xffffff,
0x787878,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x9a9a9a,
0xffffff,
0xffffff,
0xfefefe,
0x898988,
0x323232,
0x323232,
0x323232,
0x323232,
0x696969,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 39 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf8f8f7,
0xcbcbcb,
0x8d8a86,
0x5e5d5b,
0x343433,
0x454545,
0xd9d8d6,
0xece9e5,
0xebe8e4,
0xe9e7e2,
0xe9e7e2,
0xe8e6e1,
0xe8e6e1,
0xe7e5e0,
0xe6e4df,
0xe5e2dd,
0xe5e2dd,
0xe4e0db,
0xb7b5b3,
0xa09fa0,
0xb7b6b6,
0xc2c0c1,
0xc1c0c0,
0xbab8b8,
0xd9d5d1,
0xdedad5,
0xdcd9d4,
0xdbd8d3,
0xdbd8d3,
0xdad7d2,
0xdad7d2,
0xd9d6d0,
0xd9d6d0,
0xd8d5cf,
0xd8d5cf,
0xd7d4ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xacaaa3,
0x817f7b,
0x93918e,
0xd7d4d0,
0xd4d0ca,
0xcecac4,
0xc3c1ba,
0xe1deda,
0xd4d0ca,
0xcac8c4,
0xdcdcdc,
0xfafafa,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xc1c1c1,
0x323232,
0x323232,
0x7c7c7c,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xe1e1e1,
0x434343,
0x323232,
0x505050,
0xededed,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xdedede,
0x323232,
0x323232,
0x818181,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb4b4b4,
0x323232,
0x323232,
0xacacac,
0xdedede,
0x3b3b3b,
0x323232,
0x323232,
0x323232,
0x323232,
0xa3a3a3,
0xffffff,
0xffffff,
0xffffff,
0x6d6d6d,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x9a9a9a,
0xffffff,
0xffffff,
0xffffff,
0xa3a3a3,
0x323232,
0x323232,
0x323232,
0x323232,
0x696969,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 40 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xe7e7e7,
0x9a9896,
0x797773,
0x3b3b3b,
0x323232,
0xa2a1a0,
0xedeae6,
0xe9e7e2,
0xe8e6e1,
0xe8e6e1,
0xe8e5e0,
0xe7e4df,
0xe6e3de,
0xe5e2dd,
0xe4e1dc,
0xe4e0db,
0xe3dfda,
0xd3d0cd,
0x999898,
0xafaeae,
0xbfbebe,
0xc3c1c2,
0xbcbbbb,
0xc9c6c4,
0xdcd8d3,
0xdbd8d3,
0xdad7d2,
0xdad7d2,
0xdad7d1,
0xd9d6d0,
0xd9d6d0,
0xd8d5cf,
0xd8d4cf,
0xd7d3ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xb5b3ae,
0xadaba4,
0xd2d0ca,
0xe6e4e2,
0xd4d0ca,
0xd1cdc7,
0xc2c0b9,
0xe9e6e4,
0xd4d0ca,
0xd2cfc9,
0xcac9c9,
0xf3f3f3,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xdfdfdf,
0x414141,
0x323232,
0x535353,
0xf8f8f8,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xcfcfcf,
0x7d7d7d,
0x7d7d7d,
0xcacaca,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0x5f5f5f,
0x323232,
0x353535,
0xd7d7d7,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xebebeb,
0x898989,
0x7d7d7d,
0xa2a2a2,
0xdedede,
0x323232,
0x323232,
0x818181,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb4b4b4,
0x323232,
0x323232,
0xacacac,
0xf6f6f6,
0x3e3e3e,
0x323232,
0x323232,
0x323232,
0x323232,
0x747474,
0xfbfbfb,
0xffffff,
0xefeeee,
0x515151,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x717170,
0xffffff,
0xffffff,
0xfcfcfc,
0x7f7f7f,
0x323232,
0x323232,
0x323232,
0x323232,
0x828282,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 41 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf4f4f3,
0xb9b9b8,
0x898781,
0x4f4e4d,
0x323232,
0x5f5f5f,
0xe5e3e1,
0xe8e6e1,
0xe8e6e1,
0xe7e5e0,
0xe7e4df,
0xe6e3de,
0xe5e2dd,
0xe4e1dc,
0xe4e0db,
0xe3dfda,
0xe2deda,
0xdedad7,
0xa8a6a5,
0xa5a4a4,
0xbbb9ba,
0xc2c0c1,
0xc0bebf,
0xc1bfbe,
0xdbd8d3,
0xdad7d2,
0xdad7d2,
0xd9d6d1,
0xd9d6d0,
0xd8d5cf,
0xd8d5cf,
0xd8d4cf,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd6d2cc,
0xe5e3e0,
0xecebe8,
0xdad6d1,
0xd4d0ca,
0xcbc8c2,
0xc7c5bf,
0xeae8e6,
0xd4d0ca,
0xd3cfc9,
0xbfbebc,
0xeaeaea,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xf8f8f8,
0x6a696a,
0x323232,
0x383838,
0xb8b8b8,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfcfcfc,
0x6c6c6c,
0x323232,
0x323232,
0xe1e1e1,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xa1a0a0,
0x333333,
0x323232,
0x848484,
0xfbfbfb,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xa8a8a7,
0x323232,
0x323232,
0xa3a3a3,
0xdedede,
0x323232,
0x323232,
0x818181,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb4b4b4,
0x323232,
0x323232,
0xacacac,
0xffffff,
0x696969,
0x323232,
0x323232,
0x323232,
0x323232,
0x373737,
0x9b9b9a,
0xcccccc,
0x878686,
0x353535,
0x323232,
0x323232,
0x323232,
0x323232,
0x5c5c5c,
0x323232,
0x323232,
0x323232,
0x323232,
0x393939,
0x969595,
0xcecece,
0xa4a4a4,
0x3b3b3b,
0x323232,
0x323232,
0x323232,
0x333333,
0xaeaeae,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 42 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfbfbfa,
0xdbdbdb,
0x918e8b,
0x6d6c68,
0x363636,
0x363636,
0xbfbebd,
0xe9e7e2,
0xe7e5e0,
0xe6e4df,
0xe5e2dd,
0xe4e1dc,
0xe4e1dc,
0xe3dfda,
0xe2deda,
0xe1ddd9,
0xe1ddd9,
0xe0dcd7,
0xc5c2bf,
0x9a9999,
0xb3b2b3,
0xc1bfc0,
0xc3c1c2,
0xcac8c6,
0xdad7d2,
0xdad7d2,
0xd9d6d1,
0xd9d6d0,
0xd8d5cf,
0xd8d5cf,
0xd7d4ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0cb,
0xd5d1cb,
0xd4d0ca,
0xd3cfc9,
0xbdbbb3,
0xdeddd9,
0xe3e0dc,
0xd4d0ca,
0xd3cfc9,
0xb5b4b3,
0xe4e4e4,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xc3c3c3,
0x363636,
0x323232,
0x494949,
0xd4d4d4,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf8f8f8,
0x8f8f8f,
0x323232,
0x323232,
0x767676,
0xfefefe,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xececec,
0x4b4b4b,
0x323232,
0x373736,
0xacacac,
0xfbfbfb,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xbababa,
0x414141,
0x323232,
0x4f4f4f,
0xe7e7e7,
0xdedede,
0x323232,
0x323232,
0x818181,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb4b4b4,
0x323232,
0x323232,
0xacacac,
0xffffff,
0xacacac,
0x343434,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x3d3d3d,
0xa3a3a3,
0x3a3a3a,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x3b3b3b,
0xefeeee,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 43 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xeeeeee,
0xa9a8a7,
0x82807b,
0x454544,
0x323232,
0x787877,
0xeae8e4,
0xe6e3de,
0xe5e2dd,
0xe4e1dc,
0xe4e0db,
0xe3dfda,
0xe2deda,
0xe1ddd9,
0xe1dcd8,
0xe0dbd6,
0xdfdad5,
0xdbd7d2,
0xb5b3b1,
0xadabac,
0xbdbcbc,
0xc8c6c6,
0xd7d4d0,
0xdad7d2,
0xd9d6d0,
0xd9d6d0,
0xd8d5cf,
0xd8d4cf,
0xd7d4ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd2cec8,
0xc1beb6,
0xc5c4bd,
0xf4f3f1,
0xd7d3cd,
0xd4d0ca,
0xccc9c3,
0xadacac,
0xe4e4e4,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xfbfbfb,
0x8c8c8c,
0x323232,
0x323232,
0x373737,
0x777777,
0xa9a9a9,
0xb3b3b3,
0x9b9b9b,
0x545454,
0x323232,
0x323232,
0x484848,
0xe7e7e7,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xffffff,
0xbfbfbf,
0x3a3a3a,
0x323232,
0x323232,
0x616161,
0x9d9d9d,
0xb4b4b4,
0xa7a7a7,
0x6c6b6b,
0x353535,
0x323232,
0x3b3b3b,
0xb6b6b6,
0xffffff,
0xdedede,
0x323232,
0x323232,
0x818181,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb4b4b4,
0x323232,
0x323232,
0xacacac,
0xffffff,
0xf3f3f3,
0x5c5c5c,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x868586,
0xfafafa,
0x8a8a8a,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x333333,
0xa09f9f,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 44 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf7f7f7,
0xcacaca,
0x8b8984,
0x5f5e5c,
0x343434,
0x454545,
0xd5d4d2,
0xe5e2dd,
0xe4e1dc,
0xe3e0db,
0xe3dfda,
0xe1ddd9,
0xe1ddd9,
0xe0dcd7,
0xe0dbd6,
0xdfdad5,
0xddd9d4,
0xddd9d4,
0xdad7d2,
0xd2d0cc,
0xd4d2ce,
0xd8d6d1,
0xd9d6d1,
0xd9d6d0,
0xd8d5cf,
0xd8d5cf,
0xd8d4cf,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd3cfc9,
0xcecac3,
0xc3c0b8,
0xbbb9b1,
0xcfcdc7,
0xf2f1ef,
0xdfdcd8,
0xd4d0ca,
0xd3cfc9,
0x9c9a96,
0xb4b3b3,
0xeaeae9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7e7e7e,
0x323232,
0x323232,
0xa9a9a9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0x7d7d7d,
0x323232,
0x323232,
0xababab,
0xffffff,
0xffffff,
0xf8f8f8,
0x919191,
0x373737,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x545454,
0xe1e1e1,
0xffffff,
0xffffff,
0xffffff,
0x565656,
0x323232,
0x494949,
0xf2f2f2,
0xffffff,
0xffffff,
0xbcbbbb,
0x444444,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x424242,
0xb5b5b5,
0xffffff,
0xffffff,
0xdedede,
0x323232,
0x323232,
0x818181,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xb4b4b4,
0x323232,
0x323232,
0xacacac,
0xffffff,
0xffffff,
0xe6e6e6,
0x626262,
0x333333,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x343434,
0x7f7e7e,
0xf4f4f4,
0xffffff,
0xf7f7f7,
0x898989,
0x343434,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x323232,
0x343434,
0x9a9a9a,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 45 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xe7e6e6,
0x989795,
0x797873,
0x3c3c3c,
0x323232,
0x9c9c9b,
0xe8e5e1,
0xe3dfda,
0xe2deda,
0xe1ddd9,
0xe1ddd8,
0xe0dcd7,
0xdfdbd6,
0xdedad5,
0xddd9d4,
0xdcd8d3,
0xdbd8d3,
0xdbd8d3,
0xdad7d2,
0xdad7d2,
0xd9d6d1,
0xd9d6d0,
0xd8d5cf,
0xd8d5cf,
0xd7d4ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xcecbc5,
0xc5c3bb,
0xbdbab2,
0xc2c0ba,
0xd7d6d1,
0xecebe9,
0xeeedea,
0xdcd9d4,
0xd4d0ca,
0xd3cfc9,
0x9d9b97,
0x6f6f6e,
0xc3c2c2,
0xf2f2f1,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xbfbfbf,
0x989898,
0x989898,
0xd4d4d4,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xbebebe,
0x989898,
0x989898,
0xd5d5d5,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xd8d8d7,
0x868585,
0x535353,
0x353535,
0x333333,
0x454545,
0x666565,
0xadadad,
0xf9f9f9,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xababab,
0x989898,
0xa4a4a4,
0xf9f9f9,
0xffffff,
0xffffff,
0xffffff,
0xebebeb,
0x9d9d9d,
0x605f5f,
0x3b3b3b,
0x323232,
0x3d3d3d,
0x5a5959,
0x949494,
0xe8e8e8,
0xffffff,
0xffffff,
0xffffff,
0xeeeeee,
0x989898,
0x989898,
0xc0c0c0,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xd9d9d9,
0x999999,
0x989898,
0xd5d5d5,
0xffffff,
0xffffff,
0xffffff,
0xfcfcfc,
0xc1c1c1,
0x7a7a7a,
0x555554,
0x363636,
0x323232,
0x3a3a3a,
0x595958,
0x878787,
0xd0d0d0,
0xfdfdfd,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xd5d5d5,
0x8b8b8b,
0x5b5a5a,
0x3c3c3c,
0x323232,
0x383838,
0x5b5b5b,
0x898989,
0xdddddd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 46 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf4f3f3,
0xb9b8b8,
0x878580,
0x51514f,
0x323232,
0x5c5c5c,
0xe2e0dd,
0xe2deda,
0xe1ddd9,
0xe1dcd7,
0xe0dbd6,
0xdfdad5,
0xded9d4,
0xddd9d4,
0xdcd8d3,
0xdbd8d3,
0xdad7d2,
0xdad7d2,
0xdad7d2,
0xd9d6d0,
0xd9d6d0,
0xd8d5cf,
0xd8d4cf,
0xd7d4ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd0ccc6,
0xc7c4be,
0xbcbab2,
0xc0bfb8,
0xd1d0cb,
0xe9e8e6,
0xeeedeb,
0xe7e5e1,
0xdbd8d3,
0xd5d1cb,
0xd1cdc7,
0xb5b2ae,
0x7a7978,
0x4b4b4b,
0x969595,
0xd6d6d6,
0xf8f8f8,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 47 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfafafa,
0xdadada,
0x8f8d8a,
0x6e6c69,
0x373636,
0x373737,
0xbebdbc,
0xe4e0db,
0xe0dcd7,
0xdfdbd6,
0xdedad5,
0xddd9d4,
0xdcd9d4,
0xdbd8d3,
0xdbd8d3,
0xdad7d2,
0xdad7d2,
0xd9d6d1,
0xd9d6d0,
0xd8d5cf,
0xd8d5cf,
0xd8d4cf,
0xd7d3cd,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd1cdc7,
0xcac6c0,
0xbfbcb5,
0xbebcb5,
0xceccc7,
0xe5e4e1,
0xefeeec,
0xeae8e4,
0xdddad5,
0xd6d2cc,
0xd2cec8,
0xbdbab4,
0x94928f,
0x626160,
0x424141,
0x444343,
0x807f7f,
0xbcbbbc,
0xeaeaea,
0xfdfdfd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 48 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xeeeeee,
0xa8a7a5,
0x817f7a,
0x464544,
0x333333,
0xa6a5a5,
0xe6e3e0,
0xdfdbd6,
0xded9d4,
0xddd9d4,
0xdcd8d3,
0xdbd8d3,
0xdbd8d3,
0xdad7d2,
0xdad7d2,
0xd9d6d1,
0xd9d6d0,
0xd8d5cf,
0xd8d5cf,
0xd7d4ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd2cec8,
0xcbc8c1,
0xc0bdb5,
0xbebcb5,
0xc9c7c1,
0xe2e1de,
0xeeedeb,
0xeceae8,
0xdfdcd8,
0xd7d3cd,
0xd3cfc9,
0xc2beb9,
0x9f9d98,
0x6b6a67,
0x4a4948,
0x3b3b3b,
0x474746,
0x626161,
0x8b8a8a,
0xb7b6b6,
0xe0e0df,
0xf8f8f8,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 49 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf7f7f7,
0xc9c8c8,
0x8b8884,
0x5f5f5d,
0x5d5c5c,
0xd3d2d0,
0xe2dfdb,
0xddd9d4,
0xddd9d4,
0xdcd8d3,
0xdbd8d3,
0xd0cdc8,
0xc7c4c0,
0xd4d2cd,
0xd9d6d0,
0xd9d6d0,
0xd8d5cf,
0xd8d4cf,
0xd7d4ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd4d0ca,
0xd4d0ca,
0xd3cfc9,
0xcdc9c3,
0xc2bfb8,
0xbdbbb3,
0xc5c3bd,
0xdddcd8,
0xedecea,
0xeeedeb,
0xe1deda,
0xd8d4cf,
0xd3d0ca,
0xc6c2bd,
0xa8a5a1,
0x747371,
0x4f4f4f,
0x3d3d3d,
0x444444,
0x5b5b5a,
0x777777,
0x939392,
0xababab,
0xc8c7c7,
0xe4e4e4,
0xf7f7f7,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 50 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xe6e6e6,
0x989794,
0x83817d,
0xc4c3c2,
0xcbc9c2,
0xd5d3ce,
0xdfdbd6,
0xdbd8d3,
0xdbd8d3,
0xd5d2cd,
0x94928d,
0x85837e,
0xaaa8a4,
0xe1deda,
0xd8d5cf,
0xd8d4cf,
0xd7d3ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd3cfc9,
0xcfcbc5,
0xc5c2ba,
0xbebbb3,
0xc2c0b9,
0xd8d7d3,
0xebeae8,
0xefeeec,
0xe4e1dd,
0xd9d6d0,
0xd4d0ca,
0xcac6c0,
0xafaca8,
0x807f7c,
0x565655,
0x3e3e3e,
0x444343,
0x555454,
0x717070,
0x8d8b8c,
0xa6a5a5,
0xbcbbbb,
0xd0d0d0,
0xe2e2e2,
0xf1f1f1,
0xfafafa,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 51 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf4f3f3,
0xb8b8b7,
0x9d9b96,
0xd8d5d1,
0xd3d0ca,
0xc2c0ba,
0xe1deda,
0xdbd8d3,
0xdad7d2,
0xd5d3ce,
0xa7a5a2,
0xc2c0b9,
0xd8d7d5,
0xe3e1dd,
0xd8d4cf,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xcfccc5,
0xc7c4be,
0xbdbbb3,
0xc0beb7,
0xd3d2cd,
0xe8e8e5,
0xf1f0ef,
0xe6e4e0,
0xdbd8d3,
0xd4d1cb,
0xccc8c3,
0xb8b5b0,
0x898785,
0x5f5e5c,
0x444343,
0x444443,
0x515151,
0x6b6b6a,
0x868685,
0xa09f9f,
0xb6b5b5,
0xcccbcb,
0xdedede,
0xececec,
0xf6f6f6,
0xfcfcfc,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 52 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfafafa,
0xd9d9d9,
0x8c8a87,
0xbfbcb7,
0xd8d4ce,
0xc0beb7,
0xdcd9d4,
0xdbd8d3,
0xdad7d2,
0xd9d6d0,
0xe0ddd9,
0xebeae7,
0xeae9e6,
0xd9d5d0,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd6d2cc,
0xd5d1cb,
0xd2cec8,
0xc9c7c0,
0xbebbb4,
0xbdbbb4,
0xceccc7,
0xe6e5e2,
0xf1f0ee,
0xe9e7e4,
0xdcd9d4,
0xd5d1cb,
0xd0ccc6,
0xbdbab4,
0x95938f,
0x656463,
0x474747,
0x444443,
0x4f4f4e,
0x646464,
0x807f7e,
0x9b9a9a,
0xb1b0b0,
0xc7c6c6,
0xdadada,
0xe9e9e9,
0xf4f4f4,
0xfbfbfb,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 53 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xeeeeed,
0x9c9b9a,
0x92908d,
0xd5d2cc,
0xceccc6,
0xc4c2bb,
0xdcd9d4,
0xd9d6d0,
0xd9d6d0,
0xd8d5cf,
0xd8d4cf,
0xd7d3ce,
0xd7d3cd,
0xd7d3cd,
0xd6d2cc,
0xd3cfc9,
0xcdc9c3,
0xc0beb6,
0xbdbbb3,
0xc9c8c1,
0xe2e1de,
0xf1f1ef,
0xebe9e6,
0xdfdcd7,
0xd5d1cb,
0xd1cdc7,
0xc2bfba,
0x9d9a96,
0x6f6e6b,
0x4d4c4b,
0x464544,
0x4c4c4b,
0x60605f,
0x7a7a79,
0x959595,
0xababab,
0xc1c1c1,
0xd6d5d5,
0xe7e7e6,
0xf3f2f2,
0xfafaf9,
0xfdfdfd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 54 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf7f7f7,
0xc7c7c6,
0x787775,
0xc8c4be,
0xd7d4cf,
0xc3c1b9,
0xc4c2ba,
0xd4d1cb,
0xd8d5cf,
0xd8d4cf,
0xd7d3cd,
0xd7d3cd,
0xd5d1cb,
0xcfcbc5,
0xc3c0b8,
0xbdbbb4,
0xc3c1bb,
0xdfdedb,
0xefeeed,
0xefedeb,
0xe0deda,
0xd7d3cd,
0xd2cec8,
0xc7c3bd,
0xa6a39e,
0x757371,
0x525150,
0x454544,
0x4b4a49,
0x5c5b5a,
0x767575,
0x909090,
0xa7a6a6,
0xbdbdbd,
0xd1d1d1,
0xe2e2e1,
0xf0efef,
0xf8f8f8,
0xfdfdfd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 55 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfc,
0xe6e6e5,
0x848382,
0xa5a39e,
0xd6d2cc,
0xd7d4ce,
0xc8c5be,
0xbcbab2,
0xc4c1ba,
0xcbc8c1,
0xccc9c2,
0xc4c1ba,
0xbdbbb3,
0xc1bfb8,
0xd8d7d3,
0xededeb,
0xf1f0ee,
0xe3e1dd,
0xd8d4cf,
0xd3cfca,
0xcac6c1,
0xafaca7,
0x7d7b78,
0x555452,
0x454443,
0x494847,
0x575555,
0x706f6f,
0x8a8989,
0xa2a1a1,
0xb8b7b8,
0xcecdcd,
0xe0e0df,
0xeeeeed,
0xf7f7f7,
0xfcfcfc,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 56 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf4f3f3,
0xb2b2b2,
0x797875,
0xcdc9c3,
0xd6d3cd,
0xd9d6d0,
0xdcd9d5,
0xd8d7d2,
0xcfcdc7,
0xd0cec9,
0xdcdad7,
0xeae9e6,
0xf3f2f1,
0xe6e3e0,
0xdad6d0,
0xd4d0ca,
0xcdc9c3,
0xb5b2ad,
0x878581,
0x5d5c5a,
0x464544,
0x474645,
0x515050,
0x696968,
0x848483,
0x9d9c9c,
0xb3b2b2,
0xc8c8c8,
0xdcdcdc,
0xebebeb,
0xf6f6f5,
0xfbfbfb,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 57 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfafafa,
0xd8d8d8,
0x71706f,
0x92908c,
0xd1cec8,
0xd6d2cc,
0xd7d3cd,
0xd8d4ce,
0xdfdbd6,
0xe2dfdb,
0xe1deda,
0xdbd7d2,
0xd4d0ca,
0xcfcbc5,
0xbfbcb6,
0x8e8c89,
0x646260,
0x494847,
0x494847,
0x504f4e,
0x646362,
0x7e7d7d,
0x979696,
0xadacac,
0xc4c3c3,
0xd8d7d7,
0xe8e8e8,
0xf3f3f3,
0xfafafa,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 58 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfefefe,
0xeeeeed,
0x9f9e9e,
0x5a5958,
0x878683,
0xc6c2bd,
0xd3cfc9,
0xd5d1cb,
0xd5d1cb,
0xd4d0ca,
0xd1cdc7,
0xc4c0bb,
0x9a9894,
0x6c6b68,
0x4d4c4b,
0x494847,
0x4d4c4b,
0x5f5e5d,
0x777776,
0x929292,
0xa8a7a7,
0xbebdbe,
0xd4d3d2,
0xe5e5e5,
0xf1f1f1,
0xf9f9f9,
0xfdfdfd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 59 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xf8f8f7,
0xd5d4d4,
0x7c7c7b,
0x555452,
0x5f5e5c,
0x82807c,
0x989692,
0x9a9894,
0x92908c,
0x747371,
0x525251,
0x4a4948,
0x4e4d4c,
0x5a5a59,
0x717171,
0x8c8b8c,
0xa3a2a2,
0xb9b9b9,
0xd0cfcf,
0xe1e1e1,
0xeeeeee,
0xf7f7f7,
0xfcfcfc,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 60 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfdfdfd,
0xefefef,
0xc5c5c5,
0x807f7e,
0x585755,
0x525150,
0x51504f,
0x4f4f4e,
0x4e4e4d,
0x4f4f4e,
0x595857,
0x6d6c6b,
0x878787,
0x9e9d9d,
0xb4b3b4,
0xcacaca,
0xdddddd,
0xededec,
0xf7f7f6,
0xfcfcfc,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 61 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfcfcfb,
0xebebea,
0xcacaca,
0xa09f9f,
0x7b7b7a,
0x6b6b6a,
0x686868,
0x6f6f6e,
0x838281,
0x9a9999,
0xafaeae,
0xc5c5c5,
0xdadad9,
0xe9e9e9,
0xf4f4f3,
0xfbfbfb,
0xfefefe,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 62 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xfcfcfb,
0xf0f0f0,
0xdcdcdb,
0xc7c7c7,
0xb8b7b7,
0xb2b2b2,
0xb6b6b6,
0xc4c3c3,
0xd5d5d5,
0xe6e6e6,
0xf3f3f2,
0xfafafa,
0xfefefd,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 63 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 64 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
/* Scanline 65 */
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
0xffffff,
 
};
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/src/fb/fb.c
1,4 → 1,5
/*
* Copyright (c) 2008 Martin Decky
* Copyright (c) 2006 Ondrej Palkovsky
* All rights reserved.
*
26,7 → 27,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
/** @addtogroup genarch
* @{
*/
/** @file
33,6 → 34,7
*/
 
#include <genarch/fb/font-8x16.h>
#include <genarch/fb/logo-196x66.h>
#include <genarch/fb/visuals.h>
#include <genarch/fb/fb.h>
#include <console/chardev.h>
39,6 → 41,7
#include <console/console.h>
#include <sysinfo/sysinfo.h>
#include <mm/slab.h>
#include <align.h>
#include <panic.h>
#include <memstr.h>
#include <config.h>
47,137 → 50,116
#include <ddi/ddi.h>
#include <arch/types.h>
 
#include "helenos.xbm"
SPINLOCK_INITIALIZE(fb_lock);
 
static parea_t fb_parea; /**< Physical memory area for fb. */
static uint8_t *fb_addr;
static uint8_t *backbuf;
static uint8_t *glyphs;
static uint8_t *bgscan;
 
SPINLOCK_INITIALIZE(fb_lock);
static unsigned int xres;
static unsigned int yres;
 
static uint8_t *fbaddress = NULL;
static unsigned int ylogo;
static unsigned int ytrim;
static unsigned int rowtrim;
 
static uint8_t *blankline = NULL;
static uint8_t *dbbuffer = NULL; /* Buffer for fast scrolling console */
static index_t dboffset;
static unsigned int scanline;
static unsigned int glyphscanline;
 
static unsigned int xres = 0;
static unsigned int yres = 0;
static unsigned int scanline = 0;
static unsigned int pixelbytes = 0;
#ifdef FB_INVERT_COLORS
static bool invert_colors = true;
#else
static bool invert_colors = false;
#endif
static unsigned int pixelbytes;
static unsigned int glyphbytes;
static unsigned int bgscanbytes;
 
static unsigned int cols;
static unsigned int rows;
static unsigned int position = 0;
static unsigned int columns = 0;
static unsigned int rows = 0;
 
#define COL_WIDTH 8
#define ROW_BYTES (scanline * FONT_SCANLINES)
#define BG_COLOR 0x000080
#define FG_COLOR 0xffff00
 
#define BGCOLOR 0x000080
#define FGCOLOR 0xffff00
#define LOGOCOLOR 0x2020b0
#define CURSOR 219
 
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1))
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1))
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
 
#define POINTPOS(x, y) ((y) * scanline + (x) * pixelbytes)
#define COL2X(col) ((col) * FONT_WIDTH)
#define ROW2Y(row) ((row) * FONT_SCANLINES)
 
/***************************************************************/
/* Pixel specific fuctions */
#define X2COL(x) ((x) / FONT_WIDTH)
#define Y2ROW(y) ((y) / FONT_SCANLINES)
 
static void (*rgb2scr)(void *, int);
static int (*scr2rgb)(void *);
#define FB_POS(x, y) ((y) * scanline + (x) * pixelbytes)
#define BB_POS(col, row) ((row) * cols + (col))
#define GLYPH_POS(glyph, y) ((glyph) * glyphbytes + (y) * glyphscanline)
 
static inline int COLOR(int color)
{
return invert_colors ? ~color : color;
}
 
/* Conversion routines between different color representations */
static void rgb_byte0888(void *dst, int rgb)
{
*((int *) dst) = rgb;
}
static void (*rgb_conv)(void *, uint32_t);
 
static int byte0888_rgb(void *src)
{
return (*((int *) src)) & 0xffffff;
}
 
static void bgr_byte0888(void *dst, int rgb)
/** ARGB 8:8:8:8 conversion
*
*/
static void rgb_0888(void *dst, uint32_t rgb)
{
*((uint32_t *) dst) = BLUE(rgb, 8) << 16 | GREEN(rgb, 8) << 8 |
RED(rgb, 8);
*((uint32_t *) dst) = rgb & 0xffffff;
}
 
static int byte0888_bgr(void *src)
{
int color = *(uint32_t *)(src);
return ((color & 0xff) << 16) | (((color >> 8) & 0xff) << 8) |
((color >> 16) & 0xff);
}
 
static void rgb_byte888(void *dst, int rgb)
/** ABGR 8:8:8:8 conversion
*
*/
static void bgr_0888(void *dst, uint32_t rgb)
{
uint8_t *scr = (uint8_t *) dst;
#if defined(FB_INVERT_ENDIAN)
scr[0] = RED(rgb, 8);
scr[1] = GREEN(rgb, 8);
scr[2] = BLUE(rgb, 8);
#else
scr[2] = RED(rgb, 8);
scr[1] = GREEN(rgb, 8);
scr[0] = BLUE(rgb, 8);
#endif
*((uint32_t *) dst)
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8);
}
 
static int byte888_rgb(void *src)
{
uint8_t *scr = (uint8_t *) src;
#if defined(FB_INVERT_ENDIAN)
return scr[0] << 16 | scr[1] << 8 | scr[2];
#else
return scr[2] << 16 | scr[1] << 8 | scr[0];
#endif
}
 
/** 16-bit depth (5:5:5) */
static void rgb_byte555(void *dst, int rgb)
/** RGB 8:8:8 conversion
*
*/
static void rgb_888(void *dst, uint32_t rgb)
{
/* 5-bit, 5-bits, 5-bits */
*((uint16_t *) dst) = RED(rgb, 5) << 10 | GREEN(rgb, 5) << 5 |
BLUE(rgb, 5);
((uint8_t *) dst)[0] = BLUE(rgb, 8);
((uint8_t *) dst)[1] = GREEN(rgb, 8);
((uint8_t *) dst)[2] = RED(rgb, 8);
}
 
/** 16-bit depth (5:5:5) */
static int byte555_rgb(void *src)
 
/** BGR 8:8:8 conversion
*
*/
static void bgr_888(void *dst, uint32_t rgb)
{
int color = *(uint16_t *)(src);
return (((color >> 10) & 0x1f) << (16 + 3)) |
(((color >> 5) & 0x1f) << (8 + 3)) | ((color & 0x1f) << 3);
((uint8_t *) dst)[0] = RED(rgb, 8);
((uint8_t *) dst)[1] = GREEN(rgb, 8);
((uint8_t *) dst)[2] = BLUE(rgb, 8);
}
 
/** 16-bit depth (5:6:5) */
static void rgb_byte565(void *dst, int rgb)
 
/** RGB 5:5:5 conversion
*
*/
static void rgb_555(void *dst, uint32_t rgb)
{
/* 5-bit, 6-bits, 5-bits */
*((uint16_t *) dst) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 |
BLUE(rgb, 5);
*((uint16_t *) dst)
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5);
}
 
/** 16-bit depth (5:6:5) */
static int byte565_rgb(void *src)
 
/** RGB 5:6:5 conversion
*
*/
static void rgb_565(void *dst, uint32_t rgb)
{
int color = *(uint16_t *)(src);
return (((color >> 11) & 0x1f) << (16 + 3)) |
(((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
*((uint16_t *) dst)
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5);
}
 
/** Put pixel - 8-bit depth (color palette/3:2:3)
 
/** RGB 3:2:3
*
* Even though we try 3:2:3 color scheme here, an 8-bit framebuffer
* will most likely use a color palette. The color appearance
184,246 → 166,162
* will be pretty random and depend on the default installed
* palette. This could be fixed by supporting custom palette
* and setting it to simulate the 8-bit truecolor.
*
* Currently we set the palette on the ia32, amd64 and sparc64 port.
*
* Note that the byte is being inverted by this function. The reason is
* that we would like to use a color palette where the white color code
* is 0 and the black color code is 255, as some machines (Sun Blade 1500)
* use these codes for black and white and prevent to set codes
* 0 and 255 to other colors.
*
*/
static void rgb_byte8(void *dst, int rgb)
static void rgb_323(void *dst, uint32_t rgb)
{
*((uint8_t *) dst) = RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 |
BLUE(rgb, 3);
*((uint8_t *) dst)
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
}
 
/** Return pixel color - 8-bit depth (color palette/3:2:3)
 
/** Hide logo and refresh screen
*
* See the comment for rgb_byte().
*/
static int byte8_rgb(void *src)
static void logo_hide(bool silent)
{
int color = *(uint8_t *)src;
return (((color >> 5) & 0x7) << (16 + 5)) |
(((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
ylogo = 0;
ytrim = yres;
rowtrim = rows;
if (!silent)
fb_redraw();
}
 
static void putpixel(unsigned int x, unsigned int y, int color)
{
(*rgb2scr)(&fbaddress[POINTPOS(x, y)], COLOR(color));
 
if (dbbuffer) {
int dline = (y + dboffset) % yres;
(*rgb2scr)(&dbbuffer[POINTPOS(x, dline)], COLOR(color));
}
}
 
/** Get pixel from viewport */
static int getpixel(unsigned int x, unsigned int y)
/** Draw character at given position
*
*/
static void glyph_draw(uint8_t glyph, unsigned int col, unsigned int row, bool silent)
{
if (dbbuffer) {
int dline = (y + dboffset) % yres;
return COLOR((*scr2rgb)(&dbbuffer[POINTPOS(x, dline)]));
unsigned int x = COL2X(col);
unsigned int y = ROW2Y(row);
unsigned int yd;
if (y >= ytrim)
logo_hide(silent);
backbuf[BB_POS(col, row)] = glyph;
if (!silent) {
for (yd = 0; yd < FONT_SCANLINES; yd++)
memcpy(&fb_addr[FB_POS(x, y + yd + ylogo)],
&glyphs[GLYPH_POS(glyph, yd)], glyphscanline);
}
return COLOR((*scr2rgb)(&fbaddress[POINTPOS(x, y)]));
}
 
 
/** Fill screen with background color */
static void clear_screen(void)
/** Scroll screen down by one row
*
*
*/
static void screen_scroll(bool silent)
{
unsigned int y;
 
for (y = 0; y < yres; y++) {
memcpy(&fbaddress[scanline * y], blankline, xres * pixelbytes);
if (dbbuffer)
memcpy(&dbbuffer[scanline * y], blankline,
xres * pixelbytes);
if (ylogo > 0) {
logo_hide(silent);
return;
}
}
 
 
/** Scroll screen one row up */
static void scroll_screen(void)
{
if (dbbuffer) {
count_t first;
if (!silent) {
unsigned int row;
/* Clear the last row */
memcpy(&dbbuffer[dboffset * scanline], blankline, ROW_BYTES);
dboffset = (dboffset + FONT_SCANLINES) % yres;
first = yres - dboffset;
/* Move all rows one row up */
if (xres * pixelbytes == scanline) {
memcpy(fbaddress, &dbbuffer[dboffset * scanline],
first * scanline);
memcpy(&fbaddress[first * scanline], dbbuffer,
dboffset * scanline);
} else {
/*
* When the scanline is bigger than number of bytes
* in the X-resolution, chances are that the
* frame buffer memory past the X-resolution is special
* in some way. For example, the SUNW,ffb framebuffer
* wraps this area around the beginning of the same
* line. To avoid troubles, copy only memory as
* specified by the resolution.
*/
unsigned int i;
 
for (i = 0; i < first; i++)
memcpy(&fbaddress[i * scanline],
&dbbuffer[(dboffset + i) * scanline],
xres * pixelbytes);
for (i = 0; i < dboffset; i++)
memcpy(&fbaddress[(first + i) * scanline],
&dbbuffer[i * scanline], xres * pixelbytes);
for (row = 0; row < rows; row++) {
unsigned int y = ROW2Y(row);
unsigned int yd;
for (yd = 0; yd < FONT_SCANLINES; yd++) {
unsigned int x;
unsigned int col;
for (col = 0, x = 0; col < cols; col++,
x += FONT_WIDTH) {
uint8_t glyph;
if (row < rows - 1) {
if (backbuf[BB_POS(col, row)] ==
backbuf[BB_POS(col, row + 1)])
continue;
glyph = backbuf[BB_POS(col, row + 1)];
} else
glyph = 0;
memcpy(&fb_addr[FB_POS(x, y + yd)],
&glyphs[GLYPH_POS(glyph, yd)],
glyphscanline);
}
}
}
} else {
uint8_t *lastline = &fbaddress[(rows - 1) * ROW_BYTES];
if (xres * pixelbytes == scanline) {
/* Move all rows one row up */
memcpy((void *) fbaddress,
(void *) &fbaddress[ROW_BYTES],
scanline * yres - ROW_BYTES);
/* Clear the last row */
memcpy((void *) lastline, (void *) blankline,
ROW_BYTES);
} else {
/*
* See the comment in the dbbuffer case.
*/
unsigned int i;
 
/* Move all rows one row up */
for (i = 0; i < yres - FONT_SCANLINES; i++)
memcpy(&fbaddress[i * scanline],
&fbaddress[(i + FONT_SCANLINES) * scanline],
xres * pixelbytes);
/* Clear the last row */
for (i = 0; i < FONT_SCANLINES; i++)
memcpy(&lastline[i * scanline],
&blankline[i * scanline],
xres * pixelbytes);
}
}
memmove(backbuf, backbuf + cols, cols * (rows - 1));
memsetb(&backbuf[BB_POS(0, rows - 1)], cols, 0);
}
 
 
static void invert_pixel(unsigned int x, unsigned int y)
static void cursor_put(bool silent)
{
putpixel(x, y, ~getpixel(x, y));
glyph_draw(CURSOR, position % cols, position / cols, silent);
}
 
 
/** Draw one line of glyph at a given position */
static void draw_glyph_line(unsigned int glline, unsigned int x, unsigned int y)
static void cursor_remove(bool silent)
{
unsigned int i;
 
for (i = 0; i < 8; i++)
if (glline & (1 << (7 - i))) {
putpixel(x + i, y, FGCOLOR);
} else
putpixel(x + i, y, BGCOLOR);
glyph_draw(0, position % cols, position / cols, silent);
}
 
/***************************************************************/
/* Character-console functions */
 
/** Draw character at given position */
static void draw_glyph(uint8_t glyph, unsigned int col, unsigned int row)
{
unsigned int y;
 
for (y = 0; y < FONT_SCANLINES; y++)
draw_glyph_line(fb_font[glyph * FONT_SCANLINES + y],
col * COL_WIDTH, row * FONT_SCANLINES + y);
}
 
/** Invert character at given position */
static void invert_char(unsigned int col, unsigned int row)
{
unsigned int x;
unsigned int y;
 
for (x = 0; x < COL_WIDTH; x++)
for (y = 0; y < FONT_SCANLINES; y++)
invert_pixel(col * COL_WIDTH + x,
row * FONT_SCANLINES + y);
}
 
/** Draw character at default position */
static void draw_char(char chr)
{
draw_glyph(chr, position % columns, position / columns);
}
 
static void draw_logo(unsigned int startx, unsigned int starty)
{
unsigned int x;
unsigned int y;
unsigned int byte;
unsigned int rowbytes;
 
rowbytes = (helenos_width - 1) / 8 + 1;
 
for (y = 0; y < helenos_height; y++)
for (x = 0; x < helenos_width; x++) {
byte = helenos_bits[rowbytes * y + x / 8];
byte >>= x % 8;
if (byte & 1)
putpixel(startx + x, starty + y,
COLOR(LOGOCOLOR));
}
}
 
/***************************************************************/
/* Stdout specific functions */
 
static void invert_cursor(void)
{
invert_char(position % columns, position / columns);
}
 
/** Print character to screen
*
* Emulate basic terminal commands
* Emulate basic terminal commands.
*
*/
static void fb_putchar(chardev_t *dev, char ch)
static void fb_putchar(chardev_t *dev, char ch, bool silent)
{
spinlock_lock(&fb_lock);
switch (ch) {
case '\n':
invert_cursor();
position += columns;
position -= position % columns;
cursor_remove(silent);
position += cols;
position -= position % cols;
break;
case '\r':
invert_cursor();
position -= position % columns;
cursor_remove(silent);
position -= position % cols;
break;
case '\b':
invert_cursor();
if (position % columns)
cursor_remove(silent);
if (position % cols)
position--;
break;
case '\t':
invert_cursor();
cursor_remove(silent);
do {
draw_char(' ');
glyph_draw((uint8_t) ' ', position % cols,
position / cols, silent);
position++;
} while ((position % 8) && position < columns * rows);
} while ((position % 8) && (position < cols * rows));
break;
default:
draw_char(ch);
glyph_draw((uint8_t) ch, position % cols,
position / cols, silent);
position++;
}
if (position >= columns * rows) {
position -= columns;
scroll_screen();
if (position >= cols * rows) {
position -= cols;
screen_scroll(silent);
}
invert_cursor();
cursor_put(silent);
spinlock_unlock(&fb_lock);
}
434,6 → 332,97
};
 
 
/** Render glyphs
*
* Convert glyphs from device independent font
* description to current visual representation.
*
*/
static void glyphs_render(void)
{
/* Prerender glyphs */
unsigned int glyph;
for (glyph = 0; glyph < FONT_GLYPHS; glyph++) {
unsigned int y;
for (y = 0; y < FONT_SCANLINES; y++) {
unsigned int x;
for (x = 0; x < FONT_WIDTH; x++) {
void *dst = &glyphs[GLYPH_POS(glyph, y) +
x * pixelbytes];
uint32_t rgb = (fb_font[ROW2Y(glyph) + y] &
(1 << (7 - x))) ? FG_COLOR : BG_COLOR;
rgb_conv(dst, rgb);
}
}
}
/* Prerender background scanline */
unsigned int x;
for (x = 0; x < xres; x++)
rgb_conv(&bgscan[x * pixelbytes], BG_COLOR);
}
 
 
/** Refresh the screen
*
*/
void fb_redraw(void)
{
if (ylogo > 0) {
unsigned int y;
for (y = 0; y < LOGO_HEIGHT; y++) {
unsigned int x;
for (x = 0; x < xres; x++)
rgb_conv(&fb_addr[FB_POS(x, y)],
(x < LOGO_WIDTH) ?
fb_logo[y * LOGO_WIDTH + x] :
LOGO_COLOR);
}
}
unsigned int row;
for (row = 0; row < rowtrim; row++) {
unsigned int y = ylogo + ROW2Y(row);
unsigned int yd;
for (yd = 0; yd < FONT_SCANLINES; yd++) {
unsigned int x;
unsigned int col;
for (col = 0, x = 0; col < cols;
col++, x += FONT_WIDTH) {
void *d = &fb_addr[FB_POS(x, y + yd)];
void *s = &glyphs[GLYPH_POS(backbuf[BB_POS(col,
row)], yd)];
memcpy(d, s, glyphscanline);
}
}
}
if (COL2X(cols) < xres) {
unsigned int y;
unsigned int size = (xres - COL2X(cols)) * pixelbytes;
for (y = ylogo; y < yres; y++)
memcpy(&fb_addr[FB_POS(COL2X(cols), y)], bgscan, size);
}
if (ROW2Y(rowtrim) + ylogo < yres) {
unsigned int y;
for (y = ROW2Y(rowtrim) + ylogo; y < yres; y++)
memcpy(&fb_addr[FB_POS(0, y)], bgscan, bgscanbytes);
}
}
 
 
/** Initialize framebuffer as a chardev output device
*
* @param addr Physical address of the framebuffer
443,99 → 432,100
* @param visual Color model
*
*/
void fb_init(uintptr_t addr, unsigned int x, unsigned int y, unsigned int scan,
unsigned int visual)
void fb_init(fb_properties_t *props)
{
switch (visual) {
switch (props->visual) {
case VISUAL_INDIRECT_8:
rgb2scr = rgb_byte8;
scr2rgb = byte8_rgb;
rgb_conv = rgb_323;
pixelbytes = 1;
break;
case VISUAL_RGB_5_5_5:
rgb2scr = rgb_byte555;
scr2rgb = byte555_rgb;
rgb_conv = rgb_555;
pixelbytes = 2;
break;
case VISUAL_RGB_5_6_5:
rgb2scr = rgb_byte565;
scr2rgb = byte565_rgb;
rgb_conv = rgb_565;
pixelbytes = 2;
break;
case VISUAL_RGB_8_8_8:
rgb2scr = rgb_byte888;
scr2rgb = byte888_rgb;
rgb_conv = rgb_888;
pixelbytes = 3;
break;
case VISUAL_BGR_8_8_8:
rgb_conv = bgr_888;
pixelbytes = 3;
break;
case VISUAL_RGB_8_8_8_0:
rgb2scr = rgb_byte888;
scr2rgb = byte888_rgb;
rgb_conv = rgb_888;
pixelbytes = 4;
break;
case VISUAL_RGB_0_8_8_8:
rgb2scr = rgb_byte0888;
scr2rgb = byte0888_rgb;
rgb_conv = rgb_0888;
pixelbytes = 4;
break;
case VISUAL_BGR_0_8_8_8:
rgb2scr = bgr_byte0888;
scr2rgb = byte0888_bgr;
rgb_conv = bgr_0888;
pixelbytes = 4;
break;
default:
panic("Unsupported visual.\n");
panic("Unsupported visual.");
}
unsigned int fbsize = scan * y;
xres = props->x;
yres = props->y;
scanline = props->scan;
/* Map the framebuffer */
fbaddress = (uint8_t *) hw_map((uintptr_t) addr, fbsize);
cols = X2COL(xres);
rows = Y2ROW(yres);
xres = x;
yres = y;
scanline = scan;
if (yres > ylogo) {
ylogo = LOGO_HEIGHT;
rowtrim = rows - Y2ROW(ylogo);
if (ylogo % FONT_SCANLINES > 0)
rowtrim--;
ytrim = ROW2Y(rowtrim);
} else {
ylogo = 0;
ytrim = yres;
rowtrim = rows;
}
rows = y / FONT_SCANLINES;
columns = x / COL_WIDTH;
 
fb_parea.pbase = (uintptr_t) addr;
fb_parea.vbase = (uintptr_t) fbaddress;
fb_parea.frames = SIZE2FRAMES(fbsize);
fb_parea.cacheable = false;
ddi_parea_register(&fb_parea);
 
glyphscanline = FONT_WIDTH * pixelbytes;
glyphbytes = ROW2Y(glyphscanline);
bgscanbytes = xres * pixelbytes;
unsigned int fbsize = scanline * yres;
unsigned int bbsize = cols * rows;
unsigned int glyphsize = FONT_GLYPHS * glyphbytes;
backbuf = (uint8_t *) malloc(bbsize, 0);
if (!backbuf)
panic("Unable to allocate backbuffer.");
glyphs = (uint8_t *) malloc(glyphsize, 0);
if (!glyphs)
panic("Unable to allocate glyphs.");
bgscan = malloc(bgscanbytes, 0);
if (!bgscan)
panic("Unable to allocate background pixel.");
memsetb(backbuf, bbsize, 0);
glyphs_render();
fb_addr = (uint8_t *) hw_map((uintptr_t) props->addr, fbsize);
sysinfo_set_item_val("fb", NULL, true);
sysinfo_set_item_val("fb.kind", NULL, 1);
sysinfo_set_item_val("fb.width", NULL, xres);
sysinfo_set_item_val("fb.height", NULL, yres);
sysinfo_set_item_val("fb.scanline", NULL, scan);
sysinfo_set_item_val("fb.visual", NULL, visual);
sysinfo_set_item_val("fb.address.physical", NULL, addr);
sysinfo_set_item_val("fb.invert-colors", NULL, invert_colors);
 
/* Allocate double buffer */
unsigned int order = fnzb(SIZE2FRAMES(fbsize) - 1) + 1;
dbbuffer = (uint8_t *) frame_alloc(order, FRAME_ATOMIC | FRAME_KA);
if (!dbbuffer)
printf("Failed to allocate scroll buffer.\n");
dboffset = 0;
 
/* Initialized blank line */
blankline = (uint8_t *) malloc(ROW_BYTES, FRAME_ATOMIC);
if (!blankline)
panic("Failed to allocate blank line for framebuffer.");
for (y = 0; y < FONT_SCANLINES; y++)
for (x = 0; x < xres; x++)
(*rgb2scr)(&blankline[POINTPOS(x, y)], COLOR(BGCOLOR));
sysinfo_set_item_val("fb.scanline", NULL, scanline);
sysinfo_set_item_val("fb.visual", NULL, props->visual);
sysinfo_set_item_val("fb.address.physical", NULL, props->addr);
clear_screen();
 
/* Update size of screen to match text area */
yres = rows * FONT_SCANLINES;
 
draw_logo(xres - helenos_width, 0);
invert_cursor();
 
fb_redraw();
chardev_initialize("fb", &framebuffer, &fb_ops);
stdout = &framebuffer;
}
/branches/dd/kernel/genarch/src/fb/font-8x16.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
/** @addtogroup genarch
* @{
*/
/** @file
34,7 → 34,7
 
#include <genarch/fb/font-8x16.h>
 
unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES] = {
uint8_t fb_font[FONT_GLYPHS * FONT_SCANLINES] = {
 
/* 0 0x00 '^@' */
0x00, /* 00000000 */
/branches/dd/kernel/genarch/src/mm/as_ht.c
72,7 → 72,7
{
if (flags & FLAG_AS_KERNEL) {
hash_table_create(&page_ht, PAGE_HT_ENTRIES, 2, &ht_operations);
mutex_initialize(&page_ht_lock);
mutex_initialize(&page_ht_lock, MUTEX_PASSIVE);
}
return NULL;
}
/branches/dd/kernel/genarch/src/mm/page_pt.c
76,7 → 76,7
 
if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
newpt = (pte_t *)frame_alloc(PTL1_SIZE, FRAME_KA);
memsetb((uintptr_t)newpt, FRAME_SIZE << PTL1_SIZE, 0);
memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0);
SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
}
85,7 → 85,7
 
if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
newpt = (pte_t *)frame_alloc(PTL2_SIZE, FRAME_KA);
memsetb((uintptr_t)newpt, FRAME_SIZE << PTL2_SIZE, 0);
memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0);
SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
}
94,7 → 94,7
 
if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
newpt = (pte_t *)frame_alloc(PTL3_SIZE, FRAME_KA);
memsetb((uintptr_t)newpt, FRAME_SIZE << PTL3_SIZE, 0);
memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0);
SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
}
146,7 → 146,7
ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
 
/* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */
memsetb((uintptr_t) &ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0);
memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0);
 
/*
* Second, free all empty tables along the way from PTL3 down to PTL0.
166,11 → 166,11
*/
frame_free(KA2PA((uintptr_t) ptl3));
if (PTL2_ENTRIES)
memsetb((uintptr_t) &ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0);
memsetb(&ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0);
else if (PTL1_ENTRIES)
memsetb((uintptr_t) &ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
else
memsetb((uintptr_t) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
} else {
/*
* PTL3 is not empty.
195,9 → 195,9
*/
frame_free(KA2PA((uintptr_t) ptl2));
if (PTL1_ENTRIES)
memsetb((uintptr_t) &ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
else
memsetb((uintptr_t) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
}
else {
/*
223,7 → 223,7
* Release the frame and remove PTL1 pointer from preceding table.
*/
frame_free(KA2PA((uintptr_t) ptl1));
memsetb((uintptr_t) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
}
}
 
/branches/dd/kernel/genarch/src/mm/asid.c
32,7 → 32,7
 
/**
* @file
* @brief ASID management.
* @brief ASID management.
*
* Modern processor architectures optimize TLB utilization
* by using ASIDs (a.k.a. memory contexts on sparc64 and
/branches/dd/kernel/genarch/src/mm/as_pt.c
52,31 → 52,6
static void pt_lock(as_t *as, bool lock);
static void pt_unlock(as_t *as, bool unlock);
 
#ifdef __OBJC__
@implementation as_t
 
+ (pte_t *) page_table_create: (int) flags
{
return ptl0_create(flags);
}
 
+ (void) page_table_destroy: (pte_t *) page_table
{
ptl0_destroy(page_table);
}
 
- (void) page_table_lock: (bool) _lock
{
pt_lock(self, _lock);
}
 
- (void) page_table_unlock: (bool) unlock
{
pt_unlock(self, unlock);
}
 
@end
#else
as_operations_t as_pt_operations = {
.page_table_create = ptl0_create,
.page_table_destroy = ptl0_destroy,
83,7 → 58,6
.page_table_lock = pt_lock,
.page_table_unlock = pt_unlock
};
#endif
 
/** Create PTL0.
*
103,7 → 77,7
table_size = FRAME_SIZE << PTL0_SIZE;
 
if (flags & FLAG_AS_KERNEL) {
memsetb((uintptr_t) dst_ptl0, table_size, 0);
memsetb(dst_ptl0, table_size, 0);
} else {
uintptr_t src, dst;
118,7 → 92,7
src = (uintptr_t) &src_ptl0[PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)];
dst = (uintptr_t) &dst_ptl0[PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)];
 
memsetb((uintptr_t) dst_ptl0, table_size, 0);
memsetb(dst_ptl0, table_size, 0);
memcpy((void *) dst, (void *) src, table_size - (src - (uintptr_t) src_ptl0));
mutex_unlock(&AS_KERNEL->lock);
interrupts_restore(ipl);
/branches/dd/kernel/genarch/src/ofw/ebus.c
38,13 → 38,14
#include <genarch/ofw/ofw_tree.h>
#include <arch/memstr.h>
#include <arch/trap/interrupt.h>
#include <func.h>
#include <string.h>
#include <panic.h>
#include <debug.h>
#include <macros.h>
 
/** Apply EBUS ranges to EBUS register. */
bool ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa)
bool
ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa)
{
ofw_tree_property_t *prop;
ofw_ebus_range_t *range;
62,11 → 63,13
for (i = 0; i < ranges; i++) {
if (reg->space != range[i].child_space)
continue;
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) {
if (overlaps(reg->addr, reg->size, range[i].child_base,
range[i].size)) {
ofw_pci_reg_t pci_reg;
pci_reg.space = range[i].parent_space;
pci_reg.addr = range[i].parent_base + (reg->addr - range[i].child_base);
pci_reg.addr = range[i].parent_base +
(reg->addr - range[i].child_base);
pci_reg.size = reg->size;
return ofw_pci_apply_ranges(node->parent, &pci_reg, pa);
76,7 → 79,9
return false;
}
 
bool ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uint32_t interrupt, int *inr)
bool
ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg,
uint32_t interrupt, int *inr, cir_t *cir, void **cir_arg)
{
ofw_tree_property_t *prop;
ofw_tree_node_t *controller;
104,8 → 109,8
unsigned int i;
for (i = 0; i < count; i++) {
if ((intr_map[i].space == space) && (intr_map[i].addr == addr)
&& (intr_map[i].intr == intr))
if ((intr_map[i].space == space) &&
(intr_map[i].addr == addr) && (intr_map[i].intr == intr))
goto found;
}
return false;
113,10 → 118,12
found:
/*
* We found the device that functions as an interrupt controller
* for the interrupt. We also found partial mapping from interrupt to INO.
* for the interrupt. We also found partial mapping from interrupt to
* INO.
*/
 
controller = ofw_tree_find_node_by_handle(ofw_tree_lookup("/"), intr_map[i].controller_handle);
controller = ofw_tree_find_node_by_handle(ofw_tree_lookup("/"),
intr_map[i].controller_handle);
if (!controller)
return false;
130,7 → 137,8
/*
* Let the PCI do the next step in mapping the interrupt.
*/
if (!ofw_pci_map_interrupt(controller, NULL, intr_map[i].controller_ino, inr))
if (!ofw_pci_map_interrupt(controller, NULL, intr_map[i].controller_ino,
inr, cir, cir_arg))
return false;
 
return true;
/branches/dd/kernel/genarch/src/ofw/fhc.c
38,7 → 38,7
#include <genarch/ofw/ofw_tree.h>
#include <arch/drivers/fhc.h>
#include <arch/memstr.h>
#include <func.h>
#include <string.h>
#include <panic.h>
#include <macros.h>
 
67,7 → 67,7
return true;
}
if (strcmp(ofw_tree_node_name(node->parent), "central") != 0)
panic("Unexpected parent node: %s.\n", ofw_tree_node_name(node->parent));
panic("Unexpected parent node: %s.", ofw_tree_node_name(node->parent));
ofw_central_reg_t central_reg;
84,7 → 84,7
bool ofw_central_apply_ranges(ofw_tree_node_t *node, ofw_central_reg_t *reg, uintptr_t *pa)
{
if (node->parent->parent)
panic("Unexpected parent node: %s.\n", ofw_tree_node_name(node->parent));
panic("Unexpected parent node: %s.", ofw_tree_node_name(node->parent));
ofw_tree_property_t *prop;
ofw_central_range_t *range;
109,7 → 109,9
return false;
}
 
bool ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uint32_t interrupt, int *inr)
bool
ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg,
uint32_t interrupt, int *inr, cir_t *cir, void **cir_arg)
{
fhc_t *fhc = NULL;
if (!node->device) {
126,6 → 128,8
fhc_enable_interrupt(fhc, interrupt);
*inr = interrupt;
*cir = fhc_clear_interrupt;
*cir_arg = fhc;
return true;
}
 
/branches/dd/kernel/genarch/src/ofw/ofw_tree.c
38,7 → 38,7
#include <genarch/ofw/ofw_tree.h>
#include <arch/memstr.h>
#include <mm/slab.h>
#include <func.h>
#include <string.h>
#include <print.h>
#include <panic.h>
 
54,12 → 54,14
 
/** Get OpenFirmware node property.
*
* @param node Node in which to lookup the property.
* @param name Name of the property.
* @param node Node in which to lookup the property.
* @param name Name of the property.
*
* @return Pointer to the property structure or NULL if no such property.
* @return Pointer to the property structure or NULL if no such
* property.
*/
ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *node, const char *name)
ofw_tree_property_t *
ofw_tree_getprop(const ofw_tree_node_t *node, const char *name)
{
unsigned int i;
73,9 → 75,9
 
/** Return value of the 'name' property.
*
* @param node Node of interest.
* @param node Node of interest.
*
* @return Value of the 'name' property belonging to the node.
* @return Value of the 'name' property belonging to the node.
*/
const char *ofw_tree_node_name(const ofw_tree_node_t *node)
{
83,10 → 85,10
prop = ofw_tree_getprop(node, "name");
if (!prop)
panic("Node without name property.\n");
panic("Node without name property.");
if (prop->size < 2)
panic("Invalid name property.\n");
panic("Invalid name property.");
return prop->value;
}
93,10 → 95,11
 
/** Lookup child of given name.
*
* @param node Node whose child is being looked up.
* @param name Name of the child being looked up.
* @param node Node whose child is being looked up.
* @param name Name of the child being looked up.
*
* @return NULL if there is no such child or pointer to the matching child node.
* @return NULL if there is no such child or pointer to the
* matching child node.
*/
ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node, const char *name)
{
127,12 → 130,14
 
/** Lookup first child of given device type.
*
* @param node Node whose child is being looked up.
* @param name Device type of the child being looked up.
* @param node Node whose child is being looked up.
* @param name Device type of the child being looked up.
*
* @return NULL if there is no such child or pointer to the matching child node.
* @return NULL if there is no such child or pointer to the
* matching child node.
*/
ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *name)
ofw_tree_node_t *
ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *name)
{
ofw_tree_node_t *cur;
ofw_tree_property_t *prop;
153,12 → 158,14
* Child nodes are looked up recursively contrary to peer nodes that
* are looked up iteratively to avoid stack overflow.
*
* @param root Root of the searched subtree.
* @param handle OpenFirmware handle.
* @param root Root of the searched subtree.
* @param handle OpenFirmware handle.
*
* @return NULL if there is no such node or pointer to the matching node.
* @return NULL if there is no such node or pointer to the matching
* node.
*/
ofw_tree_node_t *ofw_tree_find_node_by_handle(ofw_tree_node_t *root, uint32_t handle)
ofw_tree_node_t *
ofw_tree_find_node_by_handle(ofw_tree_node_t *root, uint32_t handle)
{
ofw_tree_node_t *cur;
 
180,12 → 187,14
 
/** Lookup first peer of given device type.
*
* @param node Node whose peer is being looked up.
* @param name Device type of the child being looked up.
* @param node Node whose peer is being looked up.
* @param name Device type of the child being looked up.
*
* @return NULL if there is no such child or pointer to the matching child node.
* @return NULL if there is no such child or pointer to the
* matching child node.
*/
ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *name)
ofw_tree_node_t *
ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *name)
{
ofw_tree_node_t *cur;
ofw_tree_property_t *prop;
202,15 → 211,41
}
 
 
/** Lookup first peer of given name.
*
* @param node Node whose peer is being looked up.
* @param name Name of the child being looked up.
*
* @return NULL if there is no such peer or pointer to the matching
* peer node.
*/
ofw_tree_node_t *
ofw_tree_find_peer_by_name(ofw_tree_node_t *node, const char *name)
{
ofw_tree_node_t *cur;
ofw_tree_property_t *prop;
for (cur = node->peer; cur; cur = cur->peer) {
prop = ofw_tree_getprop(cur, "name");
if (!prop || !prop->value)
continue;
if (strcmp(prop->value, name) == 0)
return cur;
}
return NULL;
}
 
/** Lookup OpenFirmware node by its path.
*
* @param path Path to the node.
* @param path Path to the node.
*
* @return NULL if there is no such node or pointer to the leaf node.
* @return NULL if there is no such node or pointer to the leaf
* node.
*/
ofw_tree_node_t *ofw_tree_lookup(const char *path)
{
char buf[NAME_BUF_LEN+1];
char buf[NAME_BUF_LEN + 1];
ofw_tree_node_t *node = ofw_root;
index_t i, j;
236,8 → 271,8
* Child nodes are processed recursively and peer nodes are processed
* iteratively in order to avoid stack overflow.
*
* @param node Root of the subtree.
* @param path Current path, NULL for the very root of the entire tree.
* @param node Root of the subtree.
* @param path Current path, NULL for the very root of the entire tree.
*/
static void ofw_tree_node_print(const ofw_tree_node_t *node, const char *path)
{
/branches/dd/kernel/genarch/src/ofw/pci.c
39,7 → 39,7
#include <arch/drivers/pci.h>
#include <arch/trap/interrupt.h>
#include <arch/memstr.h>
#include <func.h>
#include <string.h>
#include <panic.h>
#include <macros.h>
 
49,7 → 49,8
 
#define PCI_IGN 0x1f
 
bool ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa)
bool
ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa)
{
ofw_tree_property_t *prop;
ofw_pci_range_t *range;
68,10 → 69,13
unsigned int i;
for (i = 0; i < ranges; i++) {
if ((reg->space & PCI_SPACE_MASK) != (range[i].space & PCI_SPACE_MASK))
if ((reg->space & PCI_SPACE_MASK) !=
(range[i].space & PCI_SPACE_MASK))
continue;
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) {
*pa = range[i].parent_base + (reg->addr - range[i].child_base);
if (overlaps(reg->addr, reg->size, range[i].child_base,
range[i].size)) {
*pa = range[i].parent_base +
(reg->addr - range[i].child_base);
return true;
}
}
79,7 → 83,9
return false;
}
 
bool ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg, ofw_pci_reg_t *out)
bool
ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg,
ofw_pci_reg_t *out)
{
if (reg->space & PCI_ABS_MASK) {
/* already absolute */
95,7 → 101,7
prop = ofw_tree_getprop(node, "assigned-addresses");
if (!prop)
panic("Can't find \"assigned-addresses\" property.\n");
panic("Cannot find 'assigned-addresses' property.");
assigned_addresses = prop->size / sizeof(ofw_pci_reg_t);
assigned_address = prop->value;
103,7 → 109,8
unsigned int i;
for (i = 0; i < assigned_addresses; i++) {
if ((assigned_address[i].space & PCI_REG_MASK) == (reg->space & PCI_REG_MASK)) {
if ((assigned_address[i].space & PCI_REG_MASK) ==
(reg->space & PCI_REG_MASK)) {
out->space = assigned_address[i].space;
out->addr = reg->addr + assigned_address[i].addr;
out->size = reg->size;
119,7 → 126,9
* So far, we only know how to map interrupts of non-PCI devices connected
* to a PCI bridge.
*/
bool ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino, int *inr)
bool
ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino,
int *inr, cir_t *cir, void **cir_arg)
{
pci_t *pci = node->device;
if (!pci) {
132,6 → 141,8
pci_enable_interrupt(pci, ino);
 
*inr = (PCI_IGN << IGN_SHIFT) | ino;
*cir = pci_clear_interrupt;
*cir_arg = pci;
 
return true;
}
/branches/dd/kernel/genarch/src/acpi/madt.c
126,7 → 126,7
 
int madt_irq_to_pin(unsigned int irq)
{
ASSERT(irq < sizeof(isa_irq_map)/sizeof(int));
ASSERT(irq < sizeof(isa_irq_map) / sizeof(int));
return isa_irq_map[irq];
}
 
184,15 → 184,15
case MADT_IO_SAPIC:
case MADT_L_SAPIC:
case MADT_PLATFORM_INTR_SRC:
printf("MADT: skipping %s entry (type=%zd)\n", entry[h->type], h->type);
printf("MADT: skipping %s entry (type=%" PRIu8 ")\n", entry[h->type], h->type);
break;
default:
if (h->type >= MADT_RESERVED_SKIP_BEGIN && h->type <= MADT_RESERVED_SKIP_END) {
printf("MADT: skipping reserved entry (type=%zd)\n", h->type);
printf("MADT: skipping reserved entry (type=%" PRIu8 ")\n", h->type);
}
if (h->type >= MADT_RESERVED_OEM_BEGIN) {
printf("MADT: skipping OEM entry (type=%zd)\n", h->type);
printf("MADT: skipping OEM entry (type=%" PRIu8 ")\n", h->type);
}
break;
}
233,8 → 233,8
 
void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index)
{
ASSERT(override->source < sizeof(isa_irq_map)/sizeof(int));
printf("MADT: ignoring %s entry: bus=%zd, source=%zd, global_int=%zd, flags=%#hx\n",
ASSERT(override->source < sizeof(isa_irq_map) / sizeof(int));
printf("MADT: ignoring %s entry: bus=%" PRIu8 ", source=%" PRIu8 ", global_int=%" PRIu32 ", flags=%#" PRIx16 "\n",
entry[override->header.type], override->bus, override->source,
override->global_int, override->flags);
}
/branches/dd/kernel/genarch/src/acpi/acpi.c
49,8 → 49,12
struct acpi_rsdt *acpi_rsdt = NULL;
struct acpi_xsdt *acpi_xsdt = NULL;
 
struct acpi_signature_map signature_map[] = {
{ (uint8_t *)"APIC", (void *) &acpi_madt, "Multiple APIC Description Table" }
struct acpi_signature_map signature_map[] = {
{
(uint8_t *) "APIC",
(void *) &acpi_madt,
"Multiple APIC Description Table"
}
};
 
static int rsdp_check(uint8_t *rsdp) {
105,7 → 109,7
if (!acpi_sdt_check((uint8_t *) h))
goto next;
*signature_map[j].sdt_ptr = h;
printf("%#zp: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description);
LOG("%p: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description);
}
}
next:
126,7 → 130,7
if (!acpi_sdt_check((uint8_t *) h))
goto next;
*signature_map[j].sdt_ptr = h;
printf("%#zp: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description);
LOG("%p: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description);
}
}
next:
160,7 → 164,7
return;
 
rsdp_found:
printf("%#zp: ACPI Root System Description Pointer\n", acpi_rsdp);
LOG("%p: ACPI Root System Description Pointer\n", acpi_rsdp);
 
acpi_rsdt = (struct acpi_rsdt *) (unative_t) acpi_rsdp->rsdt_address;
if (acpi_rsdp->revision) acpi_xsdt = (struct acpi_xsdt *) ((uintptr_t) acpi_rsdp->xsdt_address);
169,11 → 173,11
if (acpi_xsdt) map_sdt((struct acpi_sdt_header *) acpi_xsdt);
 
if (acpi_rsdt && !acpi_sdt_check((uint8_t *) acpi_rsdt)) {
printf("RSDT: %s\n", "bad checksum");
printf("RSDT: bad checksum\n");
return;
}
if (acpi_xsdt && !acpi_sdt_check((uint8_t *) acpi_xsdt)) {
printf("XSDT: %s\n", "bad checksum");
printf("XSDT: bad checksum\n");
return;
}
 
/branches/dd/kernel/genarch/src/drivers/ns16550/ns16550.c
0,0 → 1,116
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
* @brief NS 16550 serial controller driver.
*/
 
#include <genarch/drivers/ns16550/ns16550.h>
#include <ddi/irq.h>
#include <arch/asm.h>
#include <console/chardev.h>
#include <mm/slab.h>
 
#define LSR_DATA_READY 0x01
 
/** Initialize ns16550.
*
* @param dev Addrress of the beginning of the device in I/O space.
* @param devno Device number.
* @param inr Interrupt number.
* @param cir Clear interrupt function.
* @param cir_arg First argument to cir.
* @param devout Output character device.
*
* @return True on success, false on failure.
*/
bool
ns16550_init(ns16550_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg,
chardev_t *devout)
{
ns16550_instance_t *instance;
instance = malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC);
if (!instance)
return false;
 
instance->devno = devno;
instance->ns16550 = dev;
instance->devout = devout;
irq_initialize(&instance->irq);
instance->irq.devno = devno;
instance->irq.inr = inr;
instance->irq.claim = ns16550_claim;
instance->irq.handler = ns16550_irq_handler;
instance->irq.instance = instance;
instance->irq.cir = cir;
instance->irq.cir_arg = cir_arg;
irq_register(&instance->irq);
 
while ((pio_read_8(&dev->lsr) & LSR_DATA_READY))
(void) pio_read_8(&dev->rbr);
/* Enable interrupts */
pio_write_8(&dev->ier, IER_ERBFI);
pio_write_8(&dev->mcr, MCR_OUT2);
return true;
}
 
irq_ownership_t ns16550_claim(irq_t *irq)
{
ns16550_instance_t *instance = irq->instance;
ns16550_t *dev = instance->ns16550;
 
if (pio_read_8(&dev->lsr) & LSR_DATA_READY)
return IRQ_ACCEPT;
else
return IRQ_DECLINE;
}
 
void ns16550_irq_handler(irq_t *irq)
{
ns16550_instance_t *instance = irq->instance;
ns16550_t *dev = instance->ns16550;
 
if (pio_read_8(&dev->lsr) & LSR_DATA_READY) {
uint8_t x;
x = pio_read_8(&dev->rbr);
if (instance->devout)
chardev_push_character(instance->devout, x);
}
}
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/src/drivers/i8042/i8042.c
0,0 → 1,109
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
* @brief i8042 processor driver
*
* It takes care of the i8042 serial communication.
*/
 
#include <genarch/drivers/i8042/i8042.h>
#include <genarch/drivers/legacy/ia32/io.h>
#include <arch/asm.h>
#include <console/chardev.h>
#include <mm/slab.h>
 
#define i8042_SET_COMMAND 0x60
#define i8042_COMMAND 0x69
 
#define i8042_BUFFER_FULL_MASK 0x01
#define i8042_WAIT_MASK 0x02
 
static irq_ownership_t i8042_claim(irq_t *irq)
{
i8042_instance_t *i8042_instance = irq->instance;
i8042_t *dev = i8042_instance->i8042;
if (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK)
return IRQ_ACCEPT;
else
return IRQ_DECLINE;
}
 
static void i8042_irq_handler(irq_t *irq)
{
i8042_instance_t *instance = irq->instance;
i8042_t *dev = instance->i8042;
 
uint8_t data;
uint8_t status;
if (((status = pio_read_8(&dev->status)) & i8042_BUFFER_FULL_MASK)) {
data = pio_read_8(&dev->data);
if (instance->devout)
chardev_push_character(instance->devout, data);
}
}
 
/** Initialize i8042. */
bool
i8042_init(i8042_t *dev, devno_t devno, inr_t inr, chardev_t *devout)
{
i8042_instance_t *instance;
 
instance = malloc(sizeof(i8042_instance_t), FRAME_ATOMIC);
if (!instance)
return false;
instance->devno = devno;
instance->i8042 = dev;
instance->devout = devout;
irq_initialize(&instance->irq);
instance->irq.devno = devno;
instance->irq.inr = inr;
instance->irq.claim = i8042_claim;
instance->irq.handler = i8042_irq_handler;
instance->irq.instance = instance;
irq_register(&instance->irq);
/*
* Clear input buffer.
*/
while (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK)
(void) pio_read_8(&dev->data);
return true;
}
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/src/drivers/z8530/z8530.c
0,0 → 1,133
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
* @brief Zilog 8530 serial controller driver.
*/
 
#include <genarch/drivers/z8530/z8530.h>
#include <console/chardev.h>
#include <ddi/irq.h>
#include <arch/asm.h>
#include <mm/slab.h>
 
static inline void z8530_write(ioport8_t *ctl, uint8_t reg, uint8_t val)
{
/*
* Registers 8-15 will automatically issue the Point High
* command as their bit 3 is 1.
*/
pio_write_8(ctl, reg); /* select register */
pio_write_8(ctl, val); /* write value */
}
 
static inline uint8_t z8530_read(ioport8_t *ctl, uint8_t reg)
{
/*
* Registers 8-15 will automatically issue the Point High
* command as their bit 3 is 1.
*/
pio_write_8(ctl, reg); /* select register */
return pio_read_8(ctl);
}
 
/** Initialize z8530. */
bool
z8530_init(z8530_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg,
chardev_t *devout)
{
z8530_instance_t *instance;
 
instance = malloc(sizeof(z8530_instance_t), FRAME_ATOMIC);
if (!instance)
return false;
 
instance->devno = devno;
instance->z8530 = dev;
instance->devout = devout;
 
irq_initialize(&instance->irq);
instance->irq.devno = devno;
instance->irq.inr = inr;
instance->irq.claim = z8530_claim;
instance->irq.handler = z8530_irq_handler;
instance->irq.instance = instance;
instance->irq.cir = cir;
instance->irq.cir_arg = cir_arg;
irq_register(&instance->irq);
 
(void) z8530_read(&dev->ctl_a, RR8);
 
/*
* Clear any pending TX interrupts or we never manage
* to set FHC UART interrupt state to idle.
*/
z8530_write(&dev->ctl_a, WR0, WR0_TX_IP_RST);
 
/* interrupt on all characters */
z8530_write(&dev->ctl_a, WR1, WR1_IARCSC);
 
/* 8 bits per character and enable receiver */
z8530_write(&dev->ctl_a, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE);
/* Master Interrupt Enable. */
z8530_write(&dev->ctl_a, WR9, WR9_MIE);
 
return true;
}
 
irq_ownership_t z8530_claim(irq_t *irq)
{
z8530_instance_t *instance = irq->instance;
z8530_t *dev = instance->z8530;
 
if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA)
return IRQ_ACCEPT;
else
return IRQ_DECLINE;
}
 
void z8530_irq_handler(irq_t *irq)
{
z8530_instance_t *instance = irq->instance;
z8530_t *dev = instance->z8530;
uint8_t x;
 
if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA) {
x = z8530_read(&dev->ctl_a, RR8);
if (instance->devout)
chardev_push_character(instance->devout, x);
}
}
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/src/drivers/ega/ega.c
0,0 → 1,201
/*
* Copyright (c) 2001-2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch_drivers
* @{
*/
/**
* @file
* @brief EGA driver.
*/
 
#include <genarch/drivers/ega/ega.h>
#include <putchar.h>
#include <mm/page.h>
#include <mm/as.h>
#include <mm/slab.h>
#include <arch/mm/page.h>
#include <synch/spinlock.h>
#include <arch/types.h>
#include <arch/asm.h>
#include <memstr.h>
#include <console/chardev.h>
#include <console/console.h>
#include <sysinfo/sysinfo.h>
#include <ddi/ddi.h>
 
/*
* The EGA driver.
* Simple and short. Function for displaying characters and "scrolling".
*/
 
SPINLOCK_INITIALIZE(egalock);
static uint32_t ega_cursor;
static uint8_t *videoram;
static uint8_t *backbuf;
static ioport8_t *ega_base;
 
#define EMPTY_CHAR 0x0720
 
chardev_t ega_console;
 
/*
* This function takes care of scrolling.
*/
static void ega_check_cursor(void)
{
if (ega_cursor < EGA_SCREEN)
return;
memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2),
(EGA_SCREEN - EGA_COLS) * 2);
memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2),
(EGA_SCREEN - EGA_COLS) * 2);
memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
ega_cursor = ega_cursor - EGA_COLS;
}
 
static void ega_show_cursor(void)
{
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG);
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5)));
}
 
static void ega_move_cursor(void)
{
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff));
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff));
}
 
static void ega_sync_cursor(void)
{
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG);
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG);
ega_cursor = (hi << 8) | lo;
if (ega_cursor >= EGA_SCREEN)
ega_cursor = 0;
if ((ega_cursor % EGA_COLS) != 0)
ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
memsetw(backbuf + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
ega_check_cursor();
ega_move_cursor();
ega_show_cursor();
}
 
static void ega_display_char(char ch, bool silent)
{
backbuf[ega_cursor * 2] = ch;
if (!silent)
videoram[ega_cursor * 2] = ch;
}
 
static void ega_putchar(chardev_t *dev __attribute__((unused)), const char ch, bool silent)
{
ipl_t ipl;
ipl = interrupts_disable();
spinlock_lock(&egalock);
switch (ch) {
case '\n':
ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
break;
case '\t':
ega_cursor = (ega_cursor + 8) - ega_cursor % 8;
break;
case '\b':
if (ega_cursor % EGA_COLS)
ega_cursor--;
break;
default:
ega_display_char(ch, silent);
ega_cursor++;
break;
}
ega_check_cursor();
if (!silent)
ega_move_cursor();
spinlock_unlock(&egalock);
interrupts_restore(ipl);
}
 
static chardev_operations_t ega_ops = {
.write = ega_putchar
};
 
void ega_init(ioport8_t *base, uintptr_t videoram_phys)
{
/* Initialize the software structure. */
ega_base = base;
backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
if (!backbuf)
panic("Unable to allocate backbuffer.");
videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE);
/* Synchronize the back buffer and cursor position. */
memcpy(backbuf, videoram, EGA_VRAM_SIZE);
ega_sync_cursor();
chardev_initialize("ega_out", &ega_console, &ega_ops);
stdout = &ega_console;
sysinfo_set_item_val("fb", NULL, true);
sysinfo_set_item_val("fb.kind", NULL, 2);
sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
sysinfo_set_item_val("fb.blinking", NULL, true);
sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys);
}
 
void ega_redraw(void)
{
memcpy(videoram, backbuf, EGA_VRAM_SIZE);
ega_move_cursor();
ega_show_cursor();
}
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/src/multiboot/multiboot.c
0,0 → 1,148
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/** @file
*/
 
#include <genarch/multiboot/multiboot.h>
#include <arch/types.h>
#include <typedefs.h>
#include <config.h>
#include <string.h>
#include <macros.h>
 
/** Extract command name from the multiboot module command line.
*
* @param buf Destination buffer (will always null-terminate).
* @param n Size of destination buffer.
* @param cmd_line Input string (the command line).
*
*/
static void extract_command(char *buf, size_t n, const char *cmd_line)
{
const char *start, *end, *cp;
size_t max_len;
/* Find the first space. */
end = strchr(cmd_line, ' ');
if (end == NULL)
end = cmd_line + strlen(cmd_line);
/*
* Find last occurence of '/' before 'end'. If found, place start at
* next character. Otherwise, place start at beginning of buffer.
*/
cp = end;
start = buf;
while (cp != start) {
if (*cp == '/') {
start = cp + 1;
break;
}
--cp;
}
/* Copy the command and null-terminate the string. */
max_len = min(n - 1, (size_t) (end - start));
strncpy(buf, start, max_len + 1);
buf[max_len] = '\0';
}
 
/** Parse multiboot information structure.
*
* If @a signature does not contain a valid multiboot signature,
* assumes no multiboot information is available.
*
* @param signature Should contain the multiboot signature.
* @param mi Pointer to the multiboot information structure.
*/
void multiboot_info_parse(uint32_t signature, const multiboot_info_t *mi)
{
uint32_t flags;
multiboot_mod_t *mods;
uint32_t i;
if (signature == MULTIBOOT_LOADER_MAGIC)
flags = mi->flags;
else {
/* No multiboot info available. */
flags = 0;
}
/* Copy module information. */
if ((flags & MBINFO_FLAGS_MODS) != 0) {
init.cnt = mi->mods_count;
mods = (multiboot_mod_t *) MULTIBOOT_PTR(mi->mods_addr);
for (i = 0; i < init.cnt; i++) {
init.tasks[i].addr = PA2KA(mods[i].start);
init.tasks[i].size = mods[i].end - mods[i].start;
/* Copy command line, if available. */
if (mods[i].string) {
extract_command(init.tasks[i].name,
CONFIG_TASK_NAME_BUFLEN,
MULTIBOOT_PTR(mods[i].string));
} else
init.tasks[i].name[0] = '\0';
}
} else
init.cnt = 0;
/* Copy memory map. */
int32_t mmap_length;
multiboot_mmap_t *mme;
uint32_t size;
if ((flags & MBINFO_FLAGS_MMAP) != 0) {
mmap_length = mi->mmap_length;
mme = MULTIBOOT_PTR(mi->mmap_addr);
e820counter = 0;
i = 0;
while (mmap_length > 0) {
e820table[i++] = mme->mm_info;
/* Compute address of next structure. */
size = sizeof(mme->size) + mme->size;
mme = ((void *) mme) + size;
mmap_length -= size;
}
e820counter = i;
} else
e820counter = 0;
}
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dd/kernel/genarch/src/srln/srln.c
0,0 → 1,89
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
* @{
*/
/**
* @file
* @brief Serial line processing.
*/
 
#include <genarch/srln/srln.h>
#include <console/chardev.h>
#include <console/console.h>
#include <proc/thread.h>
#include <arch.h>
 
chardev_t srlnin;
static chardev_t *srlnout;
 
static void srlnin_suspend(chardev_t *d)
{
}
 
static void srlnin_resume(chardev_t *d)
{
}
 
chardev_operations_t srlnin_ops = {
.suspend = srlnin_suspend,
.resume = srlnin_resume,
};
 
static void ksrln(void *arg)
{
chardev_t *in = (chardev_t *) arg;
uint8_t ch;
 
while (1) {
ch = _getc(in);
if (ch == '\r')
continue;
chardev_push_character(srlnout, ch);
}
}
 
 
void srln_init(chardev_t *devout)
{
thread_t *t;
 
chardev_initialize("srln", &srlnin, &srlnin_ops);
srlnout = devout;
t = thread_create(ksrln, &srlnin, TASK, 0, "ksrln", false);
ASSERT(t);
thread_ready(t);
}
 
/** @}
*/
 
/branches/dd/kernel/generic/include/align.h
26,13 → 26,13
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
/** @addtogroup generic
* @ingroup others
* @{
*/
/**
* @file
* @brief Macros for making values and addresses aligned.
* @brief Macros for making values and addresses aligned.
*/
 
#ifndef KERN_ALIGN_H_
43,7 → 43,7
* @param s Address or size to be aligned.
* @param a Size of alignment, must be power of 2.
*/
#define ALIGN_DOWN(s, a) ((s) & ~((a) - 1))
#define ALIGN_DOWN(s, a) ((s) & ~((a) - 1))
 
 
/** Align to the nearest higher address.
51,7 → 51,7
* @param s Address or size to be aligned.
* @param a Size of alignment, must be power of 2.
*/
#define ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1))
#define ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1))
 
#endif
 
/branches/dd/kernel/generic/include/func.h
41,11 → 41,6
extern atomic_t haltstate;
 
extern void halt(void);
 
extern size_t strlen(const char *str);
extern int strcmp(const char *src, const char *dst);
extern int strncmp(const char *src, const char *dst, size_t len);
extern void strncpy(char *dest, const char *src, size_t len);
extern unative_t atoi(const char *text);
extern void order(const uint64_t val, uint64_t *rv, char *suffix);
 
/branches/dd/kernel/generic/include/fpu_context.h
37,10 → 37,6
 
#include <arch/fpu_context.h>
 
#if defined(CONFIG_FPU_LAZY) && !defined(ARCH_HAS_FPU)
# error "CONFIG_FPU_LAZY defined, but no ARCH_HAS_FPU"
#endif
 
extern void fpu_context_save(fpu_context_t *);
extern void fpu_context_restore(fpu_context_t *);
extern void fpu_init(void);
/branches/dd/kernel/generic/include/stackarg.h
52,9 → 52,9
(ap).last = (uint8_t *) &(lst)
 
#define va_arg(ap, type) \
(*((type *)((ap).last + ((ap).pos += sizeof(type) ) - sizeof(type))))
(*((type *)((ap).last + ((ap).pos += sizeof(type)) - sizeof(type))))
 
#define va_copy(dst,src) dst=src
#define va_copy(dst, src) dst = src
#define va_end(ap)
 
 
/branches/dd/kernel/generic/include/byteorder.h
51,6 → 51,14
#define uint32_t_be2host(n) (n)
#define uint64_t_be2host(n) (n)
 
#define host2uint16_t_le(n) uint16_t_byteorder_swap(n)
#define host2uint32_t_le(n) uint32_t_byteorder_swap(n)
#define host2uint64_t_le(n) uint64_t_byteorder_swap(n)
 
#define host2uint16_t_be(n) (n)
#define host2uint32_t_be(n) (n)
#define host2uint64_t_be(n) (n)
 
#else
 
#define uint16_t_le2host(n) (n)
61,6 → 69,14
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n)
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n)
 
#define host2uint16_t_le(n) (n)
#define host2uint32_t_le(n) (n)
#define host2uint64_t_le(n) (n)
 
#define host2uint16_t_be(n) uint16_t_byteorder_swap(n)
#define host2uint32_t_be(n) uint32_t_byteorder_swap(n)
#define host2uint64_t_be(n) uint64_t_byteorder_swap(n)
 
#endif
 
static inline uint64_t uint64_t_byteorder_swap(uint64_t n)
/branches/dd/kernel/generic/include/config.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
/** @addtogroup generic
* @{
*/
/** @file
38,15 → 38,16
#include <arch/types.h>
#include <arch/mm/page.h>
 
#define STACK_SIZE PAGE_SIZE
#define STACK_SIZE PAGE_SIZE
 
#define CONFIG_MEMORY_SIZE (8 * 1024 * 1024)
#define CONFIG_INIT_TASKS 32
 
#define CONFIG_INIT_TASKS 32
#define CONFIG_TASK_NAME_BUFLEN 32
 
typedef struct {
uintptr_t addr;
size_t size;
char name[CONFIG_TASK_NAME_BUFLEN];
} init_task_t;
 
typedef struct {
65,14 → 66,14
} ballocs_t;
 
typedef struct {
count_t cpu_count; /**< Number of processors detected. */
volatile count_t cpu_active; /**< Number of processors that are up and running. */
 
count_t cpu_count; /**< Number of processors detected. */
volatile count_t cpu_active; /**< Number of processors that are up and running. */
uintptr_t base;
size_t kernel_size; /**< Size of memory in bytes taken by kernel and stack */
size_t kernel_size; /**< Size of memory in bytes taken by kernel and stack */
uintptr_t stack_base; /**< Base adddress of initial stack */
size_t stack_size; /**< Size of initial stack */
uintptr_t stack_base; /**< Base adddress of initial stack */
size_t stack_size; /**< Size of initial stack */
} config_t;
 
extern config_t config;
/branches/dd/kernel/generic/include/string.h
0,0 → 1,50
/*
* Copyright (c) 2001-2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
* @{
*/
/** @file
*/
 
#ifndef KERN_STRING_H_
#define KERN_STRING_H_
 
#include <arch/types.h>
 
extern size_t strlen(const char *str);
extern int strcmp(const char *src, const char *dst);
extern int strncmp(const char *src, const char *dst, size_t len);
extern void strncpy(char *dest, const char *src, size_t len);
 
extern char *strchr(const char *s, int i);
 
#endif
 
/** @}
*/
/branches/dd/kernel/generic/include/proc/task.h
52,7 → 52,11
#include <arch/cpu.h>
#include <mm/tlb.h>
#include <proc/scheduler.h>
#include <udebug/udebug.h>
#include <ipc/kbox.h>
 
#define TASK_NAME_BUFLEN 20
 
struct thread;
 
/** Task structure. */
66,8 → 70,8
* threads.
*/
SPINLOCK_DECLARE(lock);
char *name;
 
char name[TASK_NAME_BUFLEN];
/** List of threads contained in this task. */
link_t th_head;
/** Address space. */
93,7 → 97,15
* certain extent.
*/
atomic_t active_calls;
 
#ifdef CONFIG_UDEBUG
/** Debugging stuff. */
udebug_task_t udebug;
 
/** Kernel answerbox. */
kbox_t kb;
#endif
 
/** Architecture specific task data. */
task_arch_t arch;
116,7 → 128,6
extern void task_done(void);
extern task_t *task_create(as_t *as, char *name);
extern void task_destroy(task_t *t);
extern task_t *task_run_program(void *program_addr, char *name);
extern task_t *task_find_by_id(task_id_t id);
extern int task_kill(task_id_t id);
extern uint64_t task_get_accounting(task_t *t);
133,6 → 144,7
#endif
 
extern unative_t sys_task_get_id(task_id_t *uspace_task_id);
extern unative_t sys_task_set_name(const char *uspace_name, size_t name_len);
 
#endif
 
/branches/dd/kernel/generic/include/proc/thread.h
46,6 → 46,7
#include <arch/cpu.h>
#include <mm/tlb.h>
#include <proc/uarg.h>
#include <udebug/udebug.h>
 
#define THREAD_STACK_SIZE STACK_SIZE
#define THREAD_NAME_BUFLEN 20
203,6 → 204,12
 
/** Thread's kernel stack. */
uint8_t *kstack;
 
#ifdef CONFIG_UDEBUG
/** Debugging stuff */
udebug_thread_t udebug;
#endif
 
} thread_t;
 
/** Thread list lock.
252,7 → 259,8
extern slab_cache_t *fpu_context_slab;
 
/* Thread syscall prototypes. */
extern unative_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name, thread_id_t *uspace_thread_id);
extern unative_t sys_thread_create(uspace_arg_t *uspace_uarg,
char *uspace_name, size_t name_len, thread_id_t *uspace_thread_id);
extern unative_t sys_thread_exit(int uspace_status);
extern unative_t sys_thread_get_id(thread_id_t *uspace_thread_id);
 
/branches/dd/kernel/generic/include/proc/program.h
0,0 → 1,67
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genericproc
* @{
*/
/** @file
*/
 
#ifndef KERN_PROGRAM_H_
#define KERN_PROGRAM_H_
 
#include <arch/types.h>
 
struct task;
struct thread;
 
/** Program info structure.
*
* A program is an abstraction of a freshly created (not yet running)
* userspace task containing a main thread along with its userspace stack.
*/
typedef struct program {
struct task *task; /**< Program task */
struct thread *main_thread; /**< Program main thread */
} program_t;
 
extern void *program_loader;
 
extern void program_create(as_t *as, uintptr_t entry_addr, char *name,
program_t *p);
extern int program_create_from_image(void *image_addr, char *name,
program_t *p);
extern int program_create_loader(program_t *p, char *name);
extern void program_ready(program_t *p);
 
extern unative_t sys_program_spawn_loader(char *uspace_name, size_t name_len);
 
#endif
 
/** @}
*/
/branches/dd/kernel/generic/include/lib/objc_ext.h
File deleted
/branches/dd/kernel/generic/include/lib/objc.h
File deleted
/branches/dd/kernel/generic/include/lib/rd.h
66,16 → 66,18
#define RE_UNSUPPORTED 2 /* Non-supported image (e.g. wrong version) */
 
/** RAM disk header */
typedef struct {
struct rd_header {
uint8_t magic[RD_MAGIC_SIZE];
uint8_t version;
uint8_t data_type;
uint32_t header_size;
uint64_t data_size;
} rd_header;
} __attribute__ ((packed));
 
extern int init_rd(rd_header * addr, size_t size);
typedef struct rd_header rd_header_t;
 
extern int init_rd(rd_header_t *addr, size_t size);
 
#endif
 
/** @}
/branches/dd/kernel/generic/include/lib/elf.h
114,7 → 114,8
#define EE_MEMORY 2 /* Cannot allocate address space */
#define EE_INCOMPATIBLE 3 /* ELF image is not compatible with current architecture */
#define EE_UNSUPPORTED 4 /* Non-supported ELF (e.g. dynamic ELFs) */
#define EE_IRRECOVERABLE 5
#define EE_LOADER 5 /* The image is actually a program loader */
#define EE_IRRECOVERABLE 6
 
/**
* ELF section types
338,6 → 339,10
 
extern char *elf_error(unsigned int rc);
 
/* Interpreter string used to recognize the program loader */
#define ELF_INTERP_ZSTR "kernel"
#define ELF_INTERP_ZLEN sizeof(ELF_INTERP_ZSTR)
 
#endif
 
/** @}
/branches/dd/kernel/generic/include/udebug/udebug.h
0,0 → 1,210
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
* @{
*/
/** @file
*/
 
#ifndef KERN_UDEBUG_H_
#define KERN_UDEBUG_H_
 
#include <ipc/ipc.h>
 
typedef enum { /* udebug_method_t */
 
/** Start debugging the recipient.
* Causes all threads in the receiving task to stop. When they
* are all stoped, an answer with retval 0 is generated.
*/
UDEBUG_M_BEGIN = 1,
 
/** Finish debugging the recipient.
* Answers all pending GO and GUARD messages.
*/
UDEBUG_M_END,
 
/** Set which events should be captured.
*/
UDEBUG_M_SET_EVMASK,
 
/** Make sure the debugged task is still there.
* This message is answered when the debugged task dies
* or the debugging session ends.
*/
UDEBUG_M_GUARD,
 
/** Run a thread until a debugging event occurs.
* This message is answered when the thread stops
* in a debugging event.
*
* - ARG2 - id of the thread to run
*/
UDEBUG_M_GO,
 
/** Stop a thread being debugged.
* Creates a special STOP event in the thread, causing
* it to answer a pending GO message (if any).
*/
UDEBUG_M_STOP,
 
/** Read arguments of a syscall.
*
* - ARG2 - thread identification
* - ARG3 - destination address in the caller's address space
*
*/
UDEBUG_M_ARGS_READ,
 
/** Read the list of the debugged tasks's threads.
*
* - ARG2 - destination address in the caller's address space
* - ARG3 - size of receiving buffer in bytes
*
* The kernel fills the buffer with a series of sysarg_t values
* (thread ids). On answer, the kernel will set:
*
* - ARG2 - number of bytes that were actually copied
* - ARG3 - number of bytes of the complete data
*
*/
UDEBUG_M_THREAD_READ,
 
/** Read the debugged tasks's memory.
*
* - ARG2 - destination address in the caller's address space
* - ARG3 - source address in the recipient's address space
* - ARG4 - size of receiving buffer in bytes
*
*/
UDEBUG_M_MEM_READ,
 
} udebug_method_t;
 
typedef enum {
UDEBUG_EVENT_FINISHED = 1, /**< Debuging session has finished */
UDEBUG_EVENT_STOP, /**< Stopped on DEBUG_STOP request */
UDEBUG_EVENT_SYSCALL_B, /**< Before beginning syscall execution */
UDEBUG_EVENT_SYSCALL_E, /**< After finishing syscall execution */
UDEBUG_EVENT_THREAD_B, /**< The task created a new thread */
UDEBUG_EVENT_THREAD_E /**< A thread exited */
} udebug_event_t;
 
#define UDEBUG_EVMASK(event) (1 << ((event) - 1))
 
typedef enum {
UDEBUG_EM_FINISHED = UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED),
UDEBUG_EM_STOP = UDEBUG_EVMASK(UDEBUG_EVENT_STOP),
UDEBUG_EM_SYSCALL_B = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B),
UDEBUG_EM_SYSCALL_E = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E),
UDEBUG_EM_THREAD_B = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B),
UDEBUG_EM_THREAD_E = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E),
UDEBUG_EM_ALL =
UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED) |
UDEBUG_EVMASK(UDEBUG_EVENT_STOP) |
UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B) |
UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E) |
UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B) |
UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E)
} udebug_evmask_t;
 
#ifdef KERNEL
 
#include <synch/mutex.h>
#include <arch/interrupt.h>
#include <atomic.h>
 
typedef enum {
/** Task is not being debugged */
UDEBUG_TS_INACTIVE,
/** BEGIN operation in progress (waiting for threads to stop) */
UDEBUG_TS_BEGINNING,
/** Debugger fully connected */
UDEBUG_TS_ACTIVE
} udebug_task_state_t;
 
/** Debugging part of task_t structure.
*/
typedef struct {
/** Synchronize debug ops on this task / access to this structure */
mutex_t lock;
char *lock_owner;
 
udebug_task_state_t dt_state;
call_t *begin_call;
int not_stoppable_count;
struct task *debugger;
udebug_evmask_t evmask;
} udebug_task_t;
 
/** Debugging part of thread_t structure.
*/
typedef struct {
/** Synchronize debug ops on this thread / access to this structure. */
mutex_t lock;
 
waitq_t go_wq;
call_t *go_call;
unative_t syscall_args[6];
istate_t *uspace_state;
 
/** What type of event are we stopped in or 0 if none. */
udebug_event_t cur_event;
bool go; /**< thread is GO */
bool stoppable; /**< thread is stoppable */
bool active; /**< thread is in a debugging session */
} udebug_thread_t;
 
struct task;
struct thread;
 
void udebug_task_init(udebug_task_t *ut);
void udebug_thread_initialize(udebug_thread_t *ut);
 
void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3,
unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc,
bool end_variant);
 
void udebug_thread_b_event_attach(struct thread *t, struct task *ta);
void udebug_thread_e_event(void);
 
void udebug_stoppable_begin(void);
void udebug_stoppable_end(void);
 
void udebug_before_thread_runs(void);
 
int udebug_task_cleanup(struct task *ta);
 
#endif
 
#endif
 
/** @}
*/
/branches/dd/kernel/generic/include/udebug/udebug_ops.h
0,0 → 1,55
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
* @{
*/
/** @file
*/
 
#ifndef KERN_UDEBUG_OPS_H_
#define KERN_UDEBUG_OPS_H_
 
#include <ipc/ipc.h>
 
int udebug_begin(call_t *call);
int udebug_end(void);
int udebug_set_evmask(udebug_evmask_t mask);
 
int udebug_go(thread_t *t, call_t *call);
int udebug_stop(thread_t *t, call_t *call);
 
int udebug_thread_read(void **buffer, size_t buf_size, size_t *n);
int udebug_args_read(thread_t *t, void **buffer);
 
int udebug_mem_read(unative_t uspace_addr, size_t n, void **buffer);
 
#endif
 
/** @}
*/
/branches/dd/kernel/generic/include/udebug/udebug_ipc.h
0,0 → 1,47
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
* @{
*/
/** @file
*/
 
#ifndef KERN_UDEBUG_IPC_H_
#define KERN_UDEBUG_IPC_H_
 
#include <ipc/ipc.h>
 
int udebug_request_preprocess(call_t *call, phone_t *phone);
void udebug_call_receive(call_t *call);
 
 
#endif
 
/** @}
*/
/branches/dd/kernel/generic/include/debug.h
38,11 → 38,11
#include <panic.h>
#include <arch/debug.h>
 
#define CALLER ((uintptr_t)__builtin_return_address(0))
#define CALLER ((uintptr_t) __builtin_return_address(0))
 
#ifndef HERE
/** Current Instruction Pointer address */
# define HERE ((uintptr_t *) 0)
# define HERE ((uintptr_t *) 0)
#endif
 
/** Debugging ASSERT macro
55,12 → 55,51
*
*/
#ifdef CONFIG_DEBUG
# define ASSERT(expr) if (!(expr)) { panic("assertion failed (%s), caller=%.*p\n", #expr, sizeof(uintptr_t) * 2, CALLER); }
# define ASSERT(expr) \
if (!(expr)) { \
panic("Assertion failed (%s), caller=%p.", #expr, CALLER); \
}
#else
# define ASSERT(expr)
#endif
 
/** Extensive logging output macro
*
* If CONFIG_LOG is set, the LOG() macro
* will print whatever message is indicated plus
* an information about the location.
*
*/
 
#ifdef CONFIG_LOG
# define LOG(format, ...) \
printf("%s() at %s:%u: " format "\n", __func__, __FILE__, \
__LINE__, ##__VA_ARGS__);
#else
# define LOG(format, ...)
#endif
 
/** Extensive logging execute macro
*
* If CONFIG_LOG is set, the LOG_EXEC() macro
* will print an information about calling a given
* function and call it.
*
*/
 
#ifdef CONFIG_LOG
# define LOG_EXEC(fnc) \
{ \
printf("%s() at %s:%u: " #fnc "\n", __func__, __FILE__, \
__LINE__); \
fnc; \
}
#else
# define LOG_EXEC(fnc) fnc
#endif
 
 
#endif
 
/** @}
*/
/branches/dd/kernel/generic/include/panic.h
36,15 → 36,15
#define KERN_PANIC_H_
 
#ifdef CONFIG_DEBUG
#define panic(format, ...) \
panic_printf("Kernel panic in %s() at %s on line %d: " format, __func__, \
__FILE__, __LINE__, ##__VA_ARGS__);
# define panic(format, ...) \
panic_printf("Kernel panic in %s() at %s:%u: " format "\n", \
__func__, __FILE__, __LINE__, ##__VA_ARGS__);
#else
#define panic(format, ...) \
panic_printf("Kernel panic: " format, ##__VA_ARGS__);
# define panic(format, ...) \
panic_printf("Kernel panic: " format "\n", ##__VA_ARGS__);
#endif
 
extern void panic_printf(char *fmt, ...) __attribute__((noreturn)) ;
extern void panic_printf(char *fmt, ...) __attribute__((noreturn));
 
#endif
 
/branches/dd/kernel/generic/include/interrupt.h
40,17 → 40,16
#include <proc/task.h>
#include <proc/thread.h>
#include <arch.h>
#include <console/klog.h>
#include <ddi/irq.h>
 
typedef void (* iroutine)(int n, istate_t *istate);
 
#define fault_if_from_uspace(istate, cmd, ...) \
#define fault_if_from_uspace(istate, fmt, ...) \
{ \
if (istate_from_uspace(istate)) { \
task_t *task = TASK; \
klog_printf("Task %llu killed due to an exception at %p.", task->taskid, istate_get_pc(istate)); \
klog_printf(" " cmd, ##__VA_ARGS__); \
printf("Task %s (%" PRIu64 ") killed due to an exception at %p: ", task->name, task->taskid, istate_get_pc(istate)); \
printf(fmt "\n", ##__VA_ARGS__); \
task_kill(task->taskid); \
thread_exit(); \
} \
/branches/dd/kernel/generic/include/main/main.h
35,8 → 35,13
#ifndef KERN_MAIN_H_
#define KERN_MAIN_H_
 
#include <arch/types.h>
 
extern uintptr_t stack_safe;
 
extern void main_bsp(void);
extern void main_ap(void);
 
#endif
 
/** @}
/branches/dd/kernel/generic/include/synch/mutex.h
39,20 → 39,26
#include <synch/semaphore.h>
#include <synch/synch.h>
 
typedef enum {
MUTEX_PASSIVE,
MUTEX_ACTIVE
} mutex_type_t;
 
typedef struct {
mutex_type_t type;
semaphore_t sem;
} mutex_t;
 
#define mutex_lock(mtx) \
#define mutex_lock(mtx) \
_mutex_lock_timeout((mtx), SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE)
#define mutex_trylock(mtx) \
#define mutex_trylock(mtx) \
_mutex_lock_timeout((mtx), SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NON_BLOCKING)
#define mutex_lock_timeout(mtx, usec) \
#define mutex_lock_timeout(mtx, usec) \
_mutex_lock_timeout((mtx), (usec), SYNCH_FLAGS_NON_BLOCKING)
 
extern void mutex_initialize(mutex_t *mtx);
extern int _mutex_lock_timeout(mutex_t *mtx, uint32_t usec, int flags);
extern void mutex_unlock(mutex_t *mtx);
extern void mutex_initialize(mutex_t *, mutex_type_t);
extern int _mutex_lock_timeout(mutex_t *, uint32_t, int);
extern void mutex_unlock(mutex_t *);
 
#endif
 
/branches/dd/kernel/generic/include/synch/spinlock.h
36,6 → 36,7
#define KERN_SPINLOCK_H_
 
#include <arch/types.h>
#include <arch/barrier.h>
#include <preemption.h>
#include <atomic.h>
#include <debug.h>
110,8 → 111,8
#define DEADLOCK_PROBE(pname, value) \
if ((pname)++ > (value)) { \
(pname) = 0; \
printf("Deadlock probe %s: exceeded threshold %d\n", \
"cpu%d: function=%s, line=%d\n", \
printf("Deadlock probe %s: exceeded threshold %u\n", \
"cpu%u: function=%s, line=%u\n", \
#pname, (value), CPU->id, __func__, __LINE__); \
}
#else
/branches/dd/kernel/generic/include/synch/smc.h
0,0 → 1,43
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sync
* @{
*/
/** @file
*/
 
#ifndef KERN_SMC_H_
#define KERN_SMC_H_
 
extern unative_t sys_smc_coherence(uintptr_t va, size_t size);
 
#endif
 
/** @}
*/
/branches/dd/kernel/generic/include/memstr.h
42,9 → 42,9
* Architecture independent variants.
*/
extern void *_memcpy(void *dst, const void *src, size_t cnt);
extern void _memsetb(uintptr_t dst, size_t cnt, uint8_t x);
extern void _memsetw(uintptr_t dst, size_t cnt, uint16_t x);
extern char *strcpy(char *dest, const char *src);
extern void _memsetb(void *dst, size_t cnt, uint8_t x);
extern void _memsetw(void *dst, size_t cnt, uint16_t x);
extern void *memmove(void *dst, const void *src, size_t cnt);
 
#endif
 
/branches/dd/kernel/generic/include/ddi/irq.h
36,18 → 36,16
#define KERN_IRQ_H_
 
typedef enum {
CMD_MEM_READ_1 = 0,
CMD_MEM_READ_2,
CMD_MEM_READ_4,
CMD_MEM_READ_8,
CMD_MEM_WRITE_1,
CMD_MEM_WRITE_2,
CMD_MEM_WRITE_4,
CMD_MEM_WRITE_8,
CMD_PORT_READ_1,
CMD_PORT_WRITE_1,
CMD_IA64_GETCHAR,
CMD_PPC32_GETCHAR,
CMD_PIO_READ_8 = 1,
CMD_PIO_READ_16,
CMD_PIO_READ_32,
CMD_PIO_WRITE_8,
CMD_PIO_WRITE_16,
CMD_PIO_WRITE_32,
CMD_BTEST,
CMD_PREDICATE,
CMD_ACCEPT,
CMD_DECLINE,
CMD_LAST
} irq_cmd_type;
 
54,8 → 52,9
typedef struct {
irq_cmd_type cmd;
void *addr;
unsigned long long value;
int dstarg;
unsigned long long value;
unsigned int srcarg;
unsigned int dstarg;
} irq_cmd_t;
 
typedef struct {
67,8 → 66,10
 
#include <arch/types.h>
#include <adt/list.h>
#include <adt/hash_table.h>
#include <synch/spinlock.h>
#include <proc/task.h>
#include <ipc/ipc.h>
 
typedef enum {
IRQ_DECLINE, /**< Decline to service. */
81,8 → 82,11
} irq_trigger_t;
 
struct irq;
typedef void (* irq_handler_t)(struct irq *irq, void *arg, ...);
typedef void (* irq_handler_t)(struct irq *);
 
/** Type for function used to clear the interrupt. */
typedef void (* cir_t)(void *, inr_t);
 
/** IPC notification config structure.
*
* Primarily, this structure is encapsulated in the irq_t structure.
95,6 → 99,8
answerbox_t *answerbox;
/** Method to be used for the notification. */
unative_t method;
/** Arguments that will be sent if the IRQ is claimed. */
unative_t scratch[IPC_CALL_LEN];
/** Top-half pseudocode. */
irq_code_t *code;
/** Counter. */
138,22 → 144,29
/** Trigger level of the IRQ. */
irq_trigger_t trigger;
/** Claim ownership of the IRQ. */
irq_ownership_t (* claim)(void);
irq_ownership_t (* claim)(struct irq *);
/** Handler for this IRQ and device. */
irq_handler_t handler;
/** Argument for the handler. */
void *arg;
/** Instance argument for the handler and the claim function. */
void *instance;
 
/** Clear interrupt routine. */
cir_t cir;
/** First argument to the clear interrupt routine. */
void *cir_arg;
 
/** Notification configuration structure. */
ipc_notif_cfg_t notif_cfg;
} irq_t;
 
extern void irq_init(count_t inrs, count_t chains);
extern void irq_initialize(irq_t *irq);
extern void irq_register(irq_t *irq);
extern irq_t *irq_dispatch_and_lock(inr_t inr);
extern irq_t *irq_find_and_lock(inr_t inr, devno_t devno);
SPINLOCK_EXTERN(irq_uspace_hash_table_lock);
extern hash_table_t irq_uspace_hash_table;
 
extern void irq_init(count_t, count_t);
extern void irq_initialize(irq_t *);
extern void irq_register(irq_t *);
extern irq_t *irq_dispatch_and_lock(inr_t);
 
#endif
 
#endif
/branches/dd/kernel/generic/include/ddi/device.h
35,6 → 35,9
#ifndef KERN_DEVICE_H_
#define KERN_DEVICE_H_
 
#include <arch/types.h>
#include <typedefs.h>
 
extern devno_t device_assign_devno(void);
 
#endif
/branches/dd/kernel/generic/include/ddi/ddi.h
38,13 → 38,14
#include <ddi/ddi_arg.h>
#include <arch/types.h>
#include <proc/task.h>
#include <adt/list.h>
 
/** Structure representing contiguous physical memory area. */
typedef struct {
uintptr_t pbase; /**< Physical base of the area. */
uintptr_t vbase; /**< Virtual base of the area. */
count_t frames; /**< Number of frames in the area. */
bool cacheable; /**< Cacheability. */
uintptr_t pbase; /**< Physical base of the area. */
pfn_t frames; /**< Number of frames in the area. */
link_t link; /**< Linked list link */
} parea_t;
 
extern void ddi_init(void);
/branches/dd/kernel/generic/include/console/klog.h
File deleted
/branches/dd/kernel/generic/include/console/chardev.h
50,7 → 50,7
/** Resume pushing characters. */
void (* resume)(struct chardev *);
/** Write character to stream. */
void (* write)(struct chardev *, char c);
void (* write)(struct chardev *, char c, bool silent);
/** Read character directly from device, assume interrupts disabled. */
char (* read)(struct chardev *);
} chardev_operations_t;
/branches/dd/kernel/generic/include/console/kconsole.h
37,6 → 37,7
 
#include <adt/list.h>
#include <synch/spinlock.h>
#include <ipc/irq.h>
 
#define MAX_CMDLINE 256
#define KCONSOLE_HISTORY 10
83,11 → 84,16
void (* help)(void);
} cmd_info_t;
 
extern bool kconsole_notify;
extern irq_t kconsole_irq;
 
SPINLOCK_EXTERN(cmd_lock);
extern link_t cmd_head;
 
extern void kconsole_init(void);
extern void kconsole(void *prompt);
extern void kconsole_notify_init(void);
extern void kconsole(char *prompt, char *msg, bool kcon);
extern void kconsole_thread(void *data);
 
extern int cmd_register(cmd_info_t *cmd);
 
/branches/dd/kernel/generic/include/console/console.h
41,11 → 41,21
extern chardev_t *stdin;
extern chardev_t *stdout;
 
extern bool silent;
 
extern void console_init(void);
 
extern void klog_init(void);
extern void klog_update(void);
 
extern uint8_t getc(chardev_t *chardev);
uint8_t _getc(chardev_t *chardev);
extern uint8_t _getc(chardev_t *chardev);
extern count_t gets(chardev_t *chardev, char *buf, size_t buflen);
extern void putchar(char c);
 
extern void grab_console(void);
extern void release_console(void);
 
extern void arch_grab_console(void);
extern void arch_release_console(void);
 
/branches/dd/kernel/generic/include/arch.h
63,12 → 63,11
as_t *as; /**< Current address space. */
} the_t;
 
#define THE ((the_t *)(get_stack_base()))
#define THE ((the_t * )(get_stack_base()))
 
extern void the_initialize(the_t *the);
extern void the_copy(the_t *src, the_t *dst);
 
extern void arch_pre_main(void);
extern void arch_pre_mm_init(void);
extern void arch_post_mm_init(void);
extern void arch_post_cpu_init(void);
79,6 → 78,7
 
extern void reboot(void);
extern void arch_reboot(void);
extern void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller);
 
#endif
 
/branches/dd/kernel/generic/include/adt/list.h
36,6 → 36,7
#define KERN_LIST_H_
 
#include <arch/types.h>
#include <typedefs.h>
 
/** Doubly linked list head and link type. */
typedef struct link {
/branches/dd/kernel/generic/include/adt/bitmap.h
49,6 → 49,14
extern void bitmap_clear_range(bitmap_t *bitmap, index_t start, count_t bits);
extern void bitmap_copy(bitmap_t *dst, bitmap_t *src, count_t bits);
 
static inline int bitmap_get(bitmap_t *bitmap,index_t bit)
{
if(bit >= bitmap->bits)
return 0;
return !! ((bitmap->map)[bit/8] & (1 << (bit & 7)));
}
 
 
#endif
 
/** @}
/branches/dd/kernel/generic/include/adt/avl.h
36,6 → 36,7
#define KERN_AVLTREE_H_
 
#include <arch/types.h>
#include <typedefs.h>
 
/**
* Macro for getting a pointer to the structure which contains the avltree
/branches/dd/kernel/generic/include/mm/frame.h
38,35 → 38,82
 
#include <arch/types.h>
#include <adt/list.h>
#include <mm/buddy.h>
#include <synch/spinlock.h>
#include <mm/buddy.h>
#include <arch/mm/page.h>
#include <arch/mm/frame.h>
 
#define ONE_FRAME 0
#define TWO_FRAMES 1
#define FOUR_FRAMES 2
#define ONE_FRAME 0
#define TWO_FRAMES 1
#define FOUR_FRAMES 2
 
 
#ifdef ARCH_STACK_FRAMES
#define STACK_FRAMES ARCH_STACK_FRAMES
#define STACK_FRAMES ARCH_STACK_FRAMES
#else
#define STACK_FRAMES ONE_FRAME
#define STACK_FRAMES ONE_FRAME
#endif
 
/** Maximum number of zones in system. */
#define ZONES_MAX 16
/** Maximum number of zones in the system. */
#define ZONES_MAX 32
 
/** If possible, merge with neighbouring zones. */
#define ZONE_JOIN 0x1
typedef uint8_t frame_flags_t;
 
/** Convert the frame address to kernel va. */
#define FRAME_KA 0x1
/** Convert the frame address to kernel VA. */
#define FRAME_KA 0x01
/** Do not panic and do not sleep on failure. */
#define FRAME_ATOMIC 0x2
#define FRAME_ATOMIC 0x02
/** Do not start reclaiming when no free memory. */
#define FRAME_NO_RECLAIM 0x4
#define FRAME_NO_RECLAIM 0x04
 
typedef uint8_t zone_flags_t;
 
/** Available zone (free for allocation) */
#define ZONE_AVAILABLE 0x00
/** Zone is reserved (not available for allocation) */
#define ZONE_RESERVED 0x08
/** Zone is used by firmware (not available for allocation) */
#define ZONE_FIRMWARE 0x10
 
/** Currently there is no equivalent zone flags
for frame flags */
#define FRAME_TO_ZONE_FLAGS(frame_flags) 0
 
typedef struct {
count_t refcount; /**< Tracking of shared frames */
uint8_t buddy_order; /**< Buddy system block order */
link_t buddy_link; /**< Link to the next free block inside
one order */
void *parent; /**< If allocated by slab, this points there */
} frame_t;
 
typedef struct {
pfn_t base; /**< Frame_no of the first frame
in the frames array */
count_t count; /**< Size of zone */
count_t free_count; /**< Number of free frame_t
structures */
count_t busy_count; /**< Number of busy frame_t
structures */
zone_flags_t flags; /**< Type of the zone */
frame_t *frames; /**< Array of frame_t structures
in this zone */
buddy_system_t *buddy_system; /**< Buddy system for the zone */
} zone_t;
 
/*
* The zoneinfo.lock must be locked when accessing zoneinfo structure.
* Some of the attributes in zone_t structures are 'read-only'
*/
typedef struct {
SPINLOCK_DECLARE(lock);
count_t count;
zone_t info[ZONES_MAX];
} zones_t;
 
extern zones_t zones;
 
static inline uintptr_t PFN2ADDR(pfn_t frame)
{
return (uintptr_t) (frame << FRAME_WIDTH);
89,31 → 136,37
return (size_t) (frames << FRAME_WIDTH);
}
 
#define IS_BUDDY_ORDER_OK(index, order) \
((~(((unative_t) -1) << (order)) & (index)) == 0)
#define IS_BUDDY_LEFT_BLOCK(zone, frame) \
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
#define IS_BUDDY_RIGHT_BLOCK(zone, frame) \
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
static inline bool zone_flags_available(zone_flags_t flags)
{
return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0);
}
 
#define frame_alloc(order, flags) \
frame_alloc_generic(order, flags, NULL)
#define IS_BUDDY_ORDER_OK(index, order) \
((~(((unative_t) -1) << (order)) & (index)) == 0)
#define IS_BUDDY_LEFT_BLOCK(zone, frame) \
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0)
#define IS_BUDDY_RIGHT_BLOCK(zone, frame) \
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1)
#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0)
#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1)
 
#define frame_alloc(order, flags) \
frame_alloc_generic(order, flags, NULL)
 
extern void frame_init(void);
extern void *frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone);
extern void frame_free(uintptr_t frame);
extern void frame_reference_add(pfn_t pfn);
extern void *frame_alloc_generic(uint8_t, frame_flags_t, count_t *);
extern void frame_free(uintptr_t);
extern void frame_reference_add(pfn_t);
 
extern int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags);
extern void *frame_get_parent(pfn_t frame, unsigned int hint);
extern void frame_set_parent(pfn_t frame, void *data, unsigned int hint);
extern void frame_mark_unavailable(pfn_t start, count_t count);
extern uintptr_t zone_conf_size(count_t count);
extern void zone_merge(unsigned int z1, unsigned int z2);
extern count_t find_zone(pfn_t frame, count_t count, count_t hint);
extern count_t zone_create(pfn_t, count_t, pfn_t, zone_flags_t);
extern void *frame_get_parent(pfn_t, count_t);
extern void frame_set_parent(pfn_t, void *, count_t);
extern void frame_mark_unavailable(pfn_t, count_t);
extern uintptr_t zone_conf_size(count_t);
extern bool zone_merge(count_t, count_t);
extern void zone_merge_all(void);
extern uint64_t zone_total_size(void);
 
121,7 → 174,7
* Console functions
*/
extern void zone_print_list(void);
extern void zone_print_one(unsigned int znum);
extern void zone_print_one(count_t);
 
#endif
 
/branches/dd/kernel/generic/include/mm/page.h
39,15 → 39,10
#include <mm/as.h>
#include <memstr.h>
 
/**
* Macro for computing page color.
*/
#define PAGE_COLOR(va) (((va) >> PAGE_WIDTH) & ((1 << PAGE_COLOR_BITS) - 1))
 
/** Operations to manipulate page mappings. */
typedef struct {
void (* mapping_insert)(as_t *as, uintptr_t page, uintptr_t frame,
int flags);
int flags);
void (* mapping_remove)(as_t *as, uintptr_t page);
pte_t *(* mapping_find)(as_t *as, uintptr_t page);
} page_mapping_operations_t;
64,6 → 59,7
extern pte_t *page_table_create(int flags);
extern void page_table_destroy(pte_t *page_table);
extern void map_structure(uintptr_t s, size_t size);
 
extern uintptr_t hw_map(uintptr_t physaddr, size_t size);
 
#endif
/branches/dd/kernel/generic/include/mm/slab.h
53,12 → 53,13
#define SLAB_INSIDE_SIZE (PAGE_SIZE >> 3)
 
/** Maximum wasted space we allow for cache */
#define SLAB_MAX_BADNESS(cache) (((unsigned int) PAGE_SIZE << (cache)->order) >> 2)
#define SLAB_MAX_BADNESS(cache) \
(((unsigned int) PAGE_SIZE << (cache)->order) >> 2)
 
/* slab_reclaim constants */
 
/** Reclaim all possible memory, because we are in memory stress */
#define SLAB_RECLAIM_ALL 0x1
#define SLAB_RECLAIM_ALL 0x01
 
/* cache_create flags */
 
99,7 → 100,7
int flags;
 
/* Computed values */
uint8_t order; /**< Order of frames to be allocated */
uint8_t order; /**< Order of frames to be allocated */
unsigned int objects; /**< Number of objects that fit in */
 
/* Statistics */
121,14 → 122,13
slab_mag_cache_t *mag_cache;
} slab_cache_t;
 
extern slab_cache_t * slab_cache_create(char *name, size_t size, size_t align,
int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj),
int flags);
extern void slab_cache_destroy(slab_cache_t *cache);
extern slab_cache_t *slab_cache_create(char *, size_t, size_t,
int (*)(void *, int), int (*)(void *), int);
extern void slab_cache_destroy(slab_cache_t *);
 
extern void * slab_alloc(slab_cache_t *cache, int flags);
extern void slab_free(slab_cache_t *cache, void *obj);
extern count_t slab_reclaim(int flags);
extern void * slab_alloc(slab_cache_t *, int);
extern void slab_free(slab_cache_t *, void *);
extern count_t slab_reclaim(int);
 
/* slab subsytem initialization */
extern void slab_cache_init(void);
138,9 → 138,9
extern void slab_print_list(void);
 
/* malloc support */
extern void * malloc(unsigned int size, int flags);
extern void * realloc(void *ptr, unsigned int size, int flags);
extern void free(void *ptr);
extern void *malloc(unsigned int, int);
extern void *realloc(void *, unsigned int, int);
extern void free(void *);
#endif
 
/** @}
/branches/dd/kernel/generic/include/mm/as.h
53,10 → 53,6
#include <adt/btree.h>
#include <lib/elf.h>
 
#ifdef __OBJC__
#include <lib/objc.h>
#endif
 
/**
* Defined to be true if user address space and kernel address space shadow each
* other.
84,47 → 80,6
/** The page fault was caused by memcpy_from_uspace() or memcpy_to_uspace(). */
#define AS_PF_DEFER 2
 
#ifdef __OBJC__
@interface as_t : base_t {
@public
/** Protected by asidlock. */
link_t inactive_as_with_asid_link;
/**
* Number of processors on wich is this address space active.
* Protected by asidlock.
*/
count_t cpu_refcount;
/**
* Address space identifier.
* Constant on architectures that do not support ASIDs.
* Protected by asidlock.
*/
asid_t asid;
/** Number of references (i.e tasks that reference this as). */
atomic_t refcount;
 
mutex_t lock;
/** B+tree of address space areas. */
btree_t as_area_btree;
/** Non-generic content. */
as_genarch_t genarch;
/** Architecture specific content. */
as_arch_t arch;
}
 
+ (pte_t *) page_table_create: (int) flags;
+ (void) page_table_destroy: (pte_t *) page_table;
- (void) page_table_lock: (bool) _lock;
- (void) page_table_unlock: (bool) unlock;
 
@end
 
#else
 
/** Address space structure.
*
* as_t contains the list of as_areas of userspace accessible
168,7 → 123,6
void (* page_table_lock)(as_t *as, bool lock);
void (* page_table_unlock)(as_t *as, bool unlock);
} as_operations_t;
#endif
 
/**
* This structure contains information associated with the shared address space
249,10 → 203,7
 
extern as_t *AS_KERNEL;
 
#ifndef __OBJC__
extern as_operations_t *as_operations;
#endif
 
extern link_t inactive_as_with_asid_head;
 
extern void as_init(void);
269,6 → 220,7
extern int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags);
int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
as_t *dst_as, uintptr_t dst_base, int dst_flags_mask);
extern int as_area_change_flags(as_t *as, int flags, uintptr_t address);
 
extern int as_area_get_flags(as_area_t *area);
extern bool as_area_check_access(as_area_t *area, pf_access_t access);
299,11 → 251,19
extern mem_backend_t elf_backend;
extern mem_backend_t phys_backend;
 
extern unsigned int elf_load(elf_header_t *header, as_t *as);
/**
* This flags is passed when running the loader, otherwise elf_load()
* would return with a EE_LOADER error code.
*/
#define ELD_F_NONE 0
#define ELD_F_LOADER 1
 
extern unsigned int elf_load(elf_header_t *header, as_t *as, int flags);
 
/* Address space area related syscalls. */
extern unative_t sys_as_area_create(uintptr_t address, size_t size, int flags);
extern unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags);
extern unative_t sys_as_area_change_flags(uintptr_t address, int flags);
extern unative_t sys_as_area_destroy(uintptr_t address);
 
/* Introspection functions. */
/branches/dd/kernel/generic/include/mm/buddy.h
66,7 → 66,6
void (*mark_available)(struct buddy_system *, link_t *);
/** Find parent of block that has given order */
link_t *(* find_block)(struct buddy_system *, link_t *, uint8_t);
void (* print_id)(struct buddy_system *, link_t *);
} buddy_system_operations_t;
 
typedef struct buddy_system {
78,14 → 77,13
void *data;
} buddy_system_t;
 
extern void buddy_system_create(buddy_system_t *b, uint8_t max_order,
buddy_system_operations_t *op, void *data);
extern link_t *buddy_system_alloc(buddy_system_t *b, uint8_t i);
extern bool buddy_system_can_alloc(buddy_system_t *b, uint8_t order);
extern void buddy_system_free(buddy_system_t *b, link_t *block);
extern void buddy_system_structure_print(buddy_system_t *b, size_t elem_size);
extern size_t buddy_conf_size(int max_order);
extern link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block);
extern void buddy_system_create(buddy_system_t *, uint8_t,
buddy_system_operations_t *, void *);
extern link_t *buddy_system_alloc(buddy_system_t *, uint8_t);
extern bool buddy_system_can_alloc(buddy_system_t *, uint8_t);
extern void buddy_system_free(buddy_system_t *, link_t *);
extern size_t buddy_conf_size(size_t);
extern link_t *buddy_system_alloc_block(buddy_system_t *, link_t *);
 
#endif
 
/branches/dd/kernel/generic/include/typedefs.h
35,8 → 35,26
#ifndef KERN_TYPEDEFS_H_
#define KERN_TYPEDEFS_H_
 
#include <arch/types.h>
 
#define NULL 0
#define false 0
#define true 1
 
typedef void (* function)();
 
typedef uint8_t bool;
typedef uint64_t thread_id_t;
typedef uint64_t task_id_t;
typedef uint32_t context_id_t;
 
typedef int32_t inr_t;
typedef int32_t devno_t;
 
typedef volatile uint8_t ioport8_t;
typedef volatile uint16_t ioport16_t;
typedef volatile uint32_t ioport32_t;
 
#endif
 
/** @}
/branches/dd/kernel/generic/include/macros.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
/** @addtogroup generic
* @{
*/
/** @file
37,22 → 37,25
 
#include <arch/types.h>
 
#define isdigit(d) (((d) >= '0') && ((d) <= '9'))
#define islower(c) (((c) >= 'a') && ((c) <= 'z'))
#define isupper(c) (((c) >= 'A') && ((c) <= 'Z'))
#define isalpha(c) (is_lower(c) || is_upper(c))
#define isalphanum(c) (is_alpha(c) || is_digit(c))
#define isspace(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || \
((c) == '\r'))
#define isdigit(d) (((d) >= '0') && ((d) <= '9'))
#define islower(c) (((c) >= 'a') && ((c) <= 'z'))
#define isupper(c) (((c) >= 'A') && ((c) <= 'Z'))
#define isalpha(c) (is_lower((c)) || is_upper((c)))
#define isalphanum(c) (is_alpha((c)) || is_digit((c)))
#define isspace(c) \
(((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r'))
 
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
 
/** Return true if the interlvals overlap.
#define min3(a, b, c) ((a) < (b) ? (min(a, c)) : (min(b, c)))
#define max3(a, b, c) ((a) > (b) ? (max(a, c)) : (max(b, c)))
 
/** Return true if the intervals overlap.
*
* @param s1 Start address of the first interval.
* @param s1 Start address of the first interval.
* @param sz1 Size of the first interval.
* @param s2 Start address of the second interval.
* @param s2 Start address of the second interval.
* @param sz2 Size of the second interval.
*/
static inline int overlaps(uintptr_t s1, size_t sz1, uintptr_t s2, size_t sz2)
59,19 → 62,35
{
uintptr_t e1 = s1 + sz1;
uintptr_t e2 = s2 + sz2;
 
return (s1 < e2) && (s2 < e1);
return ((s1 < e2) && (s2 < e1));
}
 
/* Compute overlapping of physical addresses */
#define PA_overlaps(x, szx, y, szy) overlaps(KA2PA(x), szx, KA2PA(y), szy)
#define PA_overlaps(x, szx, y, szy) \
overlaps(KA2PA((x)), (szx), KA2PA((y)), (szy))
 
#define SIZE2KB(size) (size >> 10)
#define SIZE2MB(size) (size >> 20)
#define SIZE2KB(size) ((size) >> 10)
#define SIZE2MB(size) ((size) >> 20)
 
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
 
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
 
/** Pseudorandom generator
*
* A pretty standard linear congruential pseudorandom
* number generator (m = 2^32 or 2^64 depending on architecture).
*
*/
#define RANDI(seed) \
({ \
(seed) = 1103515245 * (seed) + 12345; \
(seed); \
})
 
#endif
 
/** @}
/branches/dd/kernel/generic/include/stdarg.h
45,7 → 45,7
#define va_start(ap, last) __builtin_va_start(ap, last)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
#define va_end(ap) __builtin_va_end(ap)
#define va_copy(dst,src) __builtin_va_copy(dst,src)
#define va_copy(dst, src) __builtin_va_copy(dst, src)
 
#endif
 
/branches/dd/kernel/generic/include/syscall/syscall.h
36,17 → 36,26
#define KERN_SYSCALL_H_
 
typedef enum {
SYS_IO = 0,
SYS_KLOG = 0,
SYS_TLS_SET = 1, /* Hardcoded in AMD64, IA32 uspace - fibril.S */
SYS_THREAD_CREATE,
SYS_THREAD_EXIT,
SYS_THREAD_GET_ID,
SYS_TASK_GET_ID,
SYS_TASK_SET_NAME,
SYS_PROGRAM_SPAWN_LOADER,
SYS_FUTEX_SLEEP,
SYS_FUTEX_WAKEUP,
SYS_SMC_COHERENCE,
SYS_AS_AREA_CREATE,
SYS_AS_AREA_RESIZE,
SYS_AS_AREA_CHANGE_FLAGS,
SYS_AS_AREA_DESTROY,
SYS_IPC_CALL_SYNC_FAST,
SYS_IPC_CALL_SYNC_SLOW,
SYS_IPC_CALL_ASYNC_FAST,
54,18 → 63,25
SYS_IPC_ANSWER_FAST,
SYS_IPC_ANSWER_SLOW,
SYS_IPC_FORWARD_FAST,
SYS_IPC_FORWARD_SLOW,
SYS_IPC_WAIT,
SYS_IPC_HANGUP,
SYS_IPC_REGISTER_IRQ,
SYS_IPC_UNREGISTER_IRQ,
SYS_CAP_GRANT,
SYS_CAP_REVOKE,
SYS_PHYSMEM_MAP,
SYS_IOSPACE_ENABLE,
SYS_PREEMPT_CONTROL,
SYS_SYSINFO_VALID,
SYS_SYSINFO_VALUE,
SYS_DEBUG_ENABLE_CONSOLE,
SYS_DEBUG_DISABLE_CONSOLE,
SYS_IPC_CONNECT_KBOX,
SYSCALL_END
} syscall_t;
 
/branches/dd/kernel/generic/include/ipc/sysipc.h
53,10 → 53,13
int nonblocking);
unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid,
unative_t method, unative_t arg1, unative_t arg2, int mode);
unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid,
ipc_data_t *data, int mode);
unative_t sys_ipc_hangup(int phoneid);
unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method,
irq_code_t *ucode);
unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno);
unative_t sys_ipc_connect_kbox(sysarg64_t *task_id);
 
#endif
 
/branches/dd/kernel/generic/include/ipc/ipc.h
195,6 → 195,12
*/
#define IPC_M_DATA_READ 7
 
/** Debug the recipient.
* - ARG1 - specifies the debug method (from udebug_method_t)
* - other arguments are specific to the debug method
*/
#define IPC_M_DEBUG_ALL 8
 
/* Well-known methods */
#define IPC_M_LAST_SYSTEM 511
#define IPC_M_PING 512
281,6 → 287,13
 
/** Buffer for IPC_M_DATA_WRITE and IPC_M_DATA_READ. */
uint8_t *buffer;
 
/*
* The forward operation can masquerade the caller phone. For those
* cases, we must keep it aside so that the answer is processed
* correctly.
*/
phone_t *caller_phone;
} call_t;
 
extern void ipc_init(void);
287,7 → 300,7
extern call_t * ipc_wait_for_call(answerbox_t *, uint32_t, int);
extern void ipc_answer(answerbox_t *, call_t *);
extern int ipc_call(phone_t *, call_t *);
extern void ipc_call_sync(phone_t *, call_t *);
extern int ipc_call_sync(phone_t *, call_t *);
extern void ipc_phone_init(phone_t *);
extern void ipc_phone_connect(phone_t *, answerbox_t *);
extern void ipc_call_free(call_t *);
300,6 → 313,8
extern int ipc_phone_hangup(phone_t *);
extern void ipc_backsend_err(phone_t *, call_t *, unative_t);
extern void ipc_print_task(task_id_t);
extern void ipc_answerbox_slam_phones(answerbox_t *, bool);
extern void ipc_cleanup_call_list(link_t *);
 
extern answerbox_t *ipc_phone_0;
 
/branches/dd/kernel/generic/include/ipc/irq.h
36,7 → 36,7
#define KERN_IPC_IRQ_H_
 
/** Maximum length of IPC IRQ program */
#define IRQ_MAX_PROG_SIZE 10
#define IRQ_MAX_PROG_SIZE 20
 
#include <ipc/ipc.h>
#include <ddi/irq.h>
43,16 → 43,21
#include <arch/types.h>
#include <adt/list.h>
 
extern int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno,
unative_t method, irq_code_t *ucode);
extern void ipc_irq_send_notif(irq_t *irq);
extern void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno);
extern void ipc_irq_cleanup(answerbox_t *box);
extern int ipc_irq_register(answerbox_t *, inr_t, devno_t, unative_t,
irq_code_t *);
 
extern irq_ownership_t ipc_irq_top_half_claim(irq_t *);
extern void ipc_irq_top_half_handler(irq_t *);
 
extern int ipc_irq_unregister(answerbox_t *, inr_t, devno_t);
extern void ipc_irq_cleanup(answerbox_t *);
 
/*
* User friendly wrappers for ipc_irq_send_msg(). They are in the form
* ipc_irq_send_msg_m(), where m is the number of payload arguments.
*/
#define ipc_irq_send_msg_0(irq) \
ipc_irq_send_msg((irq), 0, 0, 0, 0, 0)
#define ipc_irq_send_msg_1(irq, a1) \
ipc_irq_send_msg((irq), (a1), 0, 0, 0, 0)
#define ipc_irq_send_msg_2(irq, a1, a2) \
64,8 → 69,8
#define ipc_irq_send_msg_5(irq, a1, a2, a3, a4, a5) \
ipc_irq_send_msg((irq), (a1), (a2), (a3), (a4), (a5))
 
extern void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2,
unative_t a3, unative_t a4, unative_t a5);
extern void ipc_irq_send_msg(irq_t *, unative_t, unative_t, unative_t, unative_t,
unative_t);
 
#endif
 
/branches/dd/kernel/generic/include/ipc/kbox.h
0,0 → 1,58
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genericipc
* @{
*/
/** @file
*/
 
#ifndef KERN_IPC_KBOX_H_
#define KERN_IPC_KBOX_H_
 
#include <typedefs.h>
 
/** Kernel answerbox structure. */
typedef struct kbox {
/** The answerbox itself. */
answerbox_t box;
/** Thread used to service the answerbox. */
struct thread *thread;
/** Kbox thread creation vs. begin of cleanup mutual exclusion. */
mutex_t cleanup_lock;
/** True if cleanup of kbox has already started. */
bool finished;
} kbox_t;
 
extern int ipc_connect_kbox(task_id_t);
extern void ipc_kbox_cleanup(void);
 
#endif
 
/** @}
*/
/branches/dd/kernel/generic/include/errno.h
48,14 → 48,18
* sys_ipc_hangup() to close the connection.
* Used by answerbox to close the connection.
*/
#define EEXISTS -8 /* Entry already exists */
#define EBADMEM -9 /* Bad memory pointer */
#define ENOTSUP -10 /* Not supported */
#define EADDRNOTAVAIL -11 /* Address not available. */
#define ETIMEOUT -12 /* Timeout expired */
#define EINVAL -13 /* Invalid value */
#define EBUSY -14 /* Resource is busy */
#define EOVERFLOW -15 /* The result does not fit its size. */
#define EPARTY -8 /* The other party encountered an error when
* receiving the call.
*/
#define EEXISTS -9 /* Entry already exists */
#define EBADMEM -10 /* Bad memory pointer */
#define ENOTSUP -11 /* Not supported */
#define EADDRNOTAVAIL -12 /* Address not available. */
#define ETIMEOUT -13 /* Timeout expired */
#define EINVAL -14 /* Invalid value */
#define EBUSY -15 /* Resource is busy */
#define EOVERFLOW -16 /* The result does not fit its size. */
#define EINTR -17 /* Operation was interrupted. */
 
#endif
 
/branches/dd/kernel/generic/src/synch/rwlock.c
82,7 → 82,7
*/
void rwlock_initialize(rwlock_t *rwl) {
spinlock_initialize(&rwl->lock, "rwlock_t");
mutex_initialize(&rwl->exclusive);
mutex_initialize(&rwl->exclusive, MUTEX_PASSIVE);
rwl->readers_in = 0;
}
 
231,10 → 231,10
interrupts_restore(ipl);
break;
case ESYNCH_OK_ATOMIC:
panic("_mutex_lock_timeout()==ESYNCH_OK_ATOMIC\n");
panic("_mutex_lock_timeout() == ESYNCH_OK_ATOMIC.");
break;
default:
panic("invalid ESYNCH\n");
panic("Invalid ESYNCH.");
break;
}
return rc;
/branches/dd/kernel/generic/src/synch/mutex.c
38,42 → 38,54
#include <synch/mutex.h>
#include <synch/semaphore.h>
#include <synch/synch.h>
#include <debug.h>
 
/** Initialize mutex
/** Initialize mutex.
*
* Initialize mutex.
*
* @param mtx Mutex.
* @param mtx Mutex.
* @param type Type of the mutex.
*/
void mutex_initialize(mutex_t *mtx)
void mutex_initialize(mutex_t *mtx, mutex_type_t type)
{
mtx->type = type;
semaphore_initialize(&mtx->sem, 1);
}
 
/** Acquire mutex
/** Acquire mutex.
*
* Acquire mutex.
* Timeout mode and non-blocking mode can be requested.
*
* @param mtx Mutex.
* @param usec Timeout in microseconds.
* @param flags Specify mode of operation.
* @param mtx Mutex.
* @param usec Timeout in microseconds.
* @param flags Specify mode of operation.
*
* For exact description of possible combinations of
* usec and flags, see comment for waitq_sleep_timeout().
*
* @return See comment for waitq_sleep_timeout().
* @return See comment for waitq_sleep_timeout().
*/
int _mutex_lock_timeout(mutex_t *mtx, uint32_t usec, int flags)
{
return _semaphore_down_timeout(&mtx->sem, usec, flags);
int rc;
 
if (mtx->type == MUTEX_PASSIVE) {
rc = _semaphore_down_timeout(&mtx->sem, usec, flags);
} else {
ASSERT(mtx->type == MUTEX_ACTIVE);
ASSERT(usec == SYNCH_NO_TIMEOUT);
ASSERT(!(flags & SYNCH_FLAGS_INTERRUPTIBLE));
do {
rc = semaphore_trydown(&mtx->sem);
} while (SYNCH_FAILED(rc) &&
!(flags & SYNCH_FLAGS_NON_BLOCKING));
}
 
return rc;
}
 
/** Release mutex
/** Release mutex.
*
* Release mutex.
*
* @param mtx Mutex.
* @param mtx Mutex.
*/
void mutex_unlock(mutex_t *mtx)
{
/branches/dd/kernel/generic/src/synch/spinlock.c
106,9 → 106,8
continue;
#endif
if (i++ > DEADLOCK_THRESHOLD) {
printf("cpu%d: looping on spinlock %.*p:%s, "
"caller=%.*p", CPU->id, sizeof(uintptr_t) * 2, sl,
sl->name, sizeof(uintptr_t) * 2, CALLER);
printf("cpu%u: looping on spinlock %" PRIp ":%s, caller=%" PRIp,
CPU->id, sl, sl->name, CALLER);
symbol = get_symtab_entry(CALLER);
if (symbol)
printf("(%s)", symbol);
119,7 → 118,7
}
 
if (deadlock_reported)
printf("cpu%d: not deadlocked\n", CPU->id);
printf("cpu%u: not deadlocked\n", CPU->id);
 
/*
* Prevent critical section code from bleeding out this way up.
/branches/dd/kernel/generic/src/synch/smc.c
0,0 → 1,60
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sync
* @{
*/
 
/**
* @file
* @brief Self-modifying code barriers.
*/
 
#include <arch.h>
#include <macros.h>
#include <errno.h>
#include <arch/barrier.h>
#include <synch/smc.h>
 
unative_t sys_smc_coherence(uintptr_t va, size_t size)
{
if (overlaps(va, size, NULL, PAGE_SIZE))
return EINVAL;
 
if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
if (overlaps(va, size, KERNEL_ADDRESS_SPACE_START,
KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START))
return EINVAL;
}
 
smc_coherence_block((void *) va, size);
return 0;
}
 
/** @}
*/
/branches/dd/kernel/generic/src/synch/futex.c
115,6 → 115,7
uintptr_t paddr;
pte_t *t;
ipl_t ipl;
int rc;
ipl = interrupts_disable();
 
134,9 → 135,17
interrupts_restore(ipl);
 
futex = futex_find(paddr);
return (unative_t) waitq_sleep_timeout(&futex->wq, usec, flags |
 
#ifdef CONFIG_UDEBUG
udebug_stoppable_begin();
#endif
rc = waitq_sleep_timeout(&futex->wq, usec, flags |
SYNCH_FLAGS_INTERRUPTIBLE);
 
#ifdef CONFIG_UDEBUG
udebug_stoppable_end();
#endif
return (unative_t) rc;
}
 
/** Wakeup one thread waiting in futex wait queue.
/branches/dd/kernel/generic/src/synch/condvar.c
43,7 → 43,7
 
/** Initialize condition variable.
*
* @param cv Condition variable.
* @param cv Condition variable.
*/
void condvar_initialize(condvar_t *cv)
{
50,11 → 50,10
waitq_initialize(&cv->wq);
}
 
/**
* Signal the condition has become true
* to the first waiting thread by waking it up.
/** Signal the condition has become true to the first waiting thread by waking
* it up.
*
* @param cv Condition variable.
* @param cv Condition variable.
*/
void condvar_signal(condvar_t *cv)
{
61,11 → 60,10
waitq_wakeup(&cv->wq, WAKEUP_FIRST);
}
 
/**
* Signal the condition has become true
* to all waiting threads by waking them up.
/** Signal the condition has become true to all waiting threads by waking
* them up.
*
* @param cv Condition variable.
* @param cv Condition variable.
*/
void condvar_broadcast(condvar_t *cv)
{
74,17 → 72,17
 
/** Wait for the condition becoming true.
*
* @param cv Condition variable.
* @param mtx Mutex.
* @param usec Timeout value in microseconds.
* @param flags Select mode of operation.
* @param cv Condition variable.
* @param mtx Mutex.
* @param usec Timeout value in microseconds.
* @param flags Select mode of operation.
*
* For exact description of meaning of possible combinations
* of usec and flags, see comment for waitq_sleep_timeout().
* Note that when SYNCH_FLAGS_NON_BLOCKING is specified here,
* ESYNCH_WOULD_BLOCK is always returned.
* For exact description of meaning of possible combinations of usec and flags,
* see comment for waitq_sleep_timeout(). Note that when
* SYNCH_FLAGS_NON_BLOCKING is specified here, ESYNCH_WOULD_BLOCK is always
* returned.
*
* @return See comment for waitq_sleep_timeout().
* @return See comment for waitq_sleep_timeout().
*/
int _condvar_wait_timeout(condvar_t *cv, mutex_t *mtx, uint32_t usec, int flags)
{
/branches/dd/kernel/generic/src/main/kinit.c
32,7 → 32,7
 
/**
* @file
* @brief Kernel initialization thread.
* @brief Kernel initialization thread.
*
* This file contains kinit kernel thread which carries out
* high level system initialization.
47,6 → 47,7
#include <proc/scheduler.h>
#include <proc/task.h>
#include <proc/thread.h>
#include <proc/program.h>
#include <panic.h>
#include <func.h>
#include <cpu.h>
63,6 → 64,8
#include <security/cap.h>
#include <lib/rd.h>
#include <ipc/ipc.h>
#include <debug.h>
#include <string.h>
 
#ifdef CONFIG_SMP
#include <smp/smp.h>
71,6 → 74,15
#include <synch/waitq.h>
#include <synch/spinlock.h>
 
#define ALIVE_CHARS 4
 
#ifdef CONFIG_KCONSOLE
static char alive[ALIVE_CHARS] = "-\\|/";
#endif
 
#define INIT_PREFIX "init:"
#define INIT_PREFIX_LEN 5
 
/** Kernel initialization thread.
*
* kinit takes care of higher level kernel
81,16 → 93,19
*/
void kinit(void *arg)
{
thread_t *t;
 
#if defined(CONFIG_SMP) || defined(CONFIG_KCONSOLE)
thread_t *thread;
#endif
/*
* Detach kinit as nobody will call thread_join_timeout() on it.
*/
thread_detach(THREAD);
 
interrupts_disable();
 
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
if (config.cpu_count > 1) {
waitq_initialize(&ap_completion_wq);
/*
99,24 → 114,18
* not mess together with kcpulb threads.
* Just a beautification.
*/
if ((t = thread_create(kmp, NULL, TASK, THREAD_FLAG_WIRED,
"kmp", true))) {
spinlock_lock(&t->lock);
t->cpu = &cpus[0];
spinlock_unlock(&t->lock);
thread_ready(t);
thread = thread_create(kmp, NULL, TASK, THREAD_FLAG_WIRED, "kmp", true);
if (thread != NULL) {
spinlock_lock(&thread->lock);
thread->cpu = &cpus[0];
spinlock_unlock(&thread->lock);
thread_ready(thread);
} else
panic("thread_create/kmp\n");
thread_join(t);
thread_detach(t);
panic("Unable to create kmp thread.");
thread_join(thread);
thread_detach(thread);
}
#endif /* CONFIG_SMP */
/*
* Now that all CPUs are up, we can report what we've found.
*/
cpu_list();
 
#ifdef CONFIG_SMP
if (config.cpu_count > 1) {
count_t i;
124,75 → 133,119
* For each CPU, create its load balancing thread.
*/
for (i = 0; i < config.cpu_count; i++) {
 
if ((t = thread_create(kcpulb, NULL, TASK,
THREAD_FLAG_WIRED, "kcpulb", true))) {
spinlock_lock(&t->lock);
t->cpu = &cpus[i];
spinlock_unlock(&t->lock);
thread_ready(t);
thread = thread_create(kcpulb, NULL, TASK, THREAD_FLAG_WIRED, "kcpulb", true);
if (thread != NULL) {
spinlock_lock(&thread->lock);
thread->cpu = &cpus[i];
spinlock_unlock(&thread->lock);
thread_ready(thread);
} else
panic("thread_create/kcpulb\n");
 
printf("Unable to create kcpulb thread for cpu" PRIc "\n", i);
}
}
#endif /* CONFIG_SMP */
 
/*
* At this point SMP, if present, is configured.
*/
arch_post_smp_init();
 
#ifdef CONFIG_KCONSOLE
if (stdin) {
/*
* Create kernel console.
*/
thread = thread_create(kconsole_thread, NULL, TASK, 0, "kconsole", false);
if (thread != NULL)
thread_ready(thread);
else
printf("Unable to create kconsole thread\n");
}
#endif /* CONFIG_KCONSOLE */
interrupts_enable();
/*
* Create kernel console.
* Create user tasks, load RAM disk images.
*/
t = thread_create(kconsole, (void *) "kconsole", TASK, 0, "kconsole", false);
if (t)
thread_ready(t);
else
panic("thread_create/kconsole\n");
 
interrupts_enable();
 
count_t i;
program_t programs[CONFIG_INIT_TASKS];
for (i = 0; i < init.cnt; i++) {
/*
* Run user tasks, load RAM disk images.
*/
if (init.tasks[i].addr % FRAME_SIZE) {
printf("init[%d].addr is not frame aligned", i);
printf("init[%" PRIc "].addr is not frame aligned\n", i);
continue;
}
 
task_t *utask = task_run_program((void *) init.tasks[i].addr,
"uspace");
if (utask) {
/*
* Construct task name from the 'init:' prefix and the
* name stored in the init structure (if any).
*/
char namebuf[TASK_NAME_BUFLEN];
char *name;
name = init.tasks[i].name;
if (name[0] == '\0')
name = "<unknown>";
ASSERT(TASK_NAME_BUFLEN >= INIT_PREFIX_LEN);
strncpy(namebuf, INIT_PREFIX, TASK_NAME_BUFLEN);
strncpy(namebuf + INIT_PREFIX_LEN, name,
TASK_NAME_BUFLEN - INIT_PREFIX_LEN);
int rc = program_create_from_image((void *) init.tasks[i].addr,
namebuf, &programs[i]);
if ((rc == 0) && (programs[i].task != NULL)) {
/*
* Set capabilities to init userspace tasks.
*/
cap_set(utask, CAP_CAP | CAP_MEM_MANAGER |
cap_set(programs[i].task, CAP_CAP | CAP_MEM_MANAGER |
CAP_IO_MANAGER | CAP_PREEMPT_CONTROL | CAP_IRQ_REG);
if (!ipc_phone_0)
ipc_phone_0 = &utask->answerbox;
if (!ipc_phone_0)
ipc_phone_0 = &programs[i].task->answerbox;
} else if (rc == 0) {
/* It was the program loader and was registered */
} else {
int rd = init_rd((rd_header *) init.tasks[i].addr,
init.tasks[i].size);
/* RAM disk image */
int rd = init_rd((rd_header_t *) init.tasks[i].addr, init.tasks[i].size);
if (rd != RE_OK)
printf("Init binary %zd not used, error code %d.\n", i, rd);
printf("Init binary %" PRIc " not used (error %d)\n", i, rd);
}
}
 
 
/*
* Run user tasks with small delays
* to avoid intermixed klog output.
*
* TODO: This certainly does not guarantee
* anything, it just works in most of the
* cases. Some better way how to achieve
* nice klog output should be found.
*/
for (i = 0; i < init.cnt; i++) {
if (programs[i].task != NULL) {
program_ready(&programs[i]);
thread_usleep(10000);
}
}
#ifdef CONFIG_KCONSOLE
if (!stdin) {
while (1) {
thread_sleep(10);
printf("kinit: No stdin\nKernel alive: .");
unsigned int i = 0;
while (true) {
printf("\b%c", alive[i % ALIVE_CHARS]);
thread_sleep(1);
printf("kinit... ");
i++;
}
}
#endif /* CONFIG_KCONSOLE */
}
 
/** @}
/branches/dd/kernel/generic/src/main/main.c
61,6 → 61,7
#include <main/kinit.h>
#include <main/version.h>
#include <console/kconsole.h>
#include <console/console.h>
#include <cpu.h>
#include <align.h>
#include <interrupt.h>
78,9 → 79,9
#include <ipc/ipc.h>
#include <macros.h>
#include <adt/btree.h>
#include <console/klog.h>
#include <smp/smp.h>
#include <ddi/ddi.h>
#include <main/main.h>
 
/** Global configuration structure. */
config_t config;
104,18 → 105,15
* appropriate sizes and addresses.
*/
 
/**< Virtual address of where the kernel is loaded. */
/** Virtual address of where the kernel is loaded. */
uintptr_t hardcoded_load_address = 0;
/**< Size of the kernel code in bytes. */
/** Size of the kernel code in bytes. */
size_t hardcoded_ktext_size = 0;
/**< Size of the kernel data in bytes. */
/** Size of the kernel data in bytes. */
size_t hardcoded_kdata_size = 0;
/**< Lowest safe stack virtual address. */
/** Lowest safe stack virtual address. */
uintptr_t stack_safe = 0;
 
void main_bsp(void);
void main_ap(void);
 
/*
* These two functions prevent stack from underflowing during the
* kernel boot phase when SP is set to the very top of the reserved
131,9 → 129,11
 
/** Main kernel routine for bootstrap CPU.
*
* Initializes the kernel by bootstrap CPU.
* This function passes control directly to
* main_bsp_separated_stack().
* The code here still runs on the boot stack, which knows nothing about
* preemption counts. Because of that, this function cannot directly call
* functions that disable or enable preemption (e.g. spinlock_lock()). The
* primary task of this function is to calculate address of a new stack and
* switch to it.
*
* Assuming interrupts_disable().
*
186,90 → 186,97
*/
void main_bsp_separated_stack(void)
{
task_t *k;
thread_t *t;
count_t i;
/* Keep this the first thing. */
the_initialize(THE);
the_initialize(THE);
 
version_print();
LOG("\nconfig.base=%#" PRIp " config.kernel_size=%" PRIs
"\nconfig.stack_base=%#" PRIp " config.stack_size=%" PRIs,
config.base, config.kernel_size, config.stack_base,
config.stack_size);
#ifdef CONFIG_KCONSOLE
/*
* kconsole data structures must be initialized very early
* because other subsystems will register their respective
* commands.
*/
kconsole_init();
LOG_EXEC(kconsole_init());
#endif
/*
* Exception handler initialization, before architecture
* starts adding its own handlers
*/
exc_init();
 
LOG_EXEC(exc_init());
/*
* Memory management subsystems initialization.
*/
arch_pre_mm_init();
frame_init();
*/
LOG_EXEC(arch_pre_mm_init());
LOG_EXEC(frame_init());
/* Initialize at least 1 memory segment big enough for slab to work. */
slab_cache_init();
btree_init();
as_init();
page_init();
tlb_init();
ddi_init();
tasklet_init();
arch_post_mm_init();
LOG_EXEC(slab_cache_init());
LOG_EXEC(btree_init());
LOG_EXEC(as_init());
LOG_EXEC(page_init());
LOG_EXEC(tlb_init());
LOG_EXEC(ddi_init());
LOG_EXEC(tasklet_init());
LOG_EXEC(arch_post_mm_init());
LOG_EXEC(arch_pre_smp_init());
LOG_EXEC(smp_init());
version_print();
printf("kernel: %.*p hardcoded_ktext_size=%zd KB, "
"hardcoded_kdata_size=%zd KB\n", sizeof(uintptr_t) * 2,
config.base, SIZE2KB(hardcoded_ktext_size),
SIZE2KB(hardcoded_kdata_size));
printf("stack: %.*p size=%zd KB\n", sizeof(uintptr_t) * 2,
config.stack_base, SIZE2KB(config.stack_size));
arch_pre_smp_init();
smp_init();
/* Slab must be initialized after we know the number of processors. */
slab_enable_cpucache();
LOG_EXEC(slab_enable_cpucache());
printf("Detected %zu CPU(s), %llu MB free memory\n",
config.cpu_count, SIZE2MB(zone_total_size()));
cpu_init();
printf("Detected %" PRIc " CPU(s), %" PRIu64" MiB free memory\n",
config.cpu_count, SIZE2MB(zone_total_size()));
calibrate_delay_loop();
clock_counter_init();
timeout_init();
scheduler_init();
task_init();
thread_init();
futex_init();
klog_init();
LOG_EXEC(cpu_init());
LOG_EXEC(calibrate_delay_loop());
LOG_EXEC(clock_counter_init());
LOG_EXEC(timeout_init());
LOG_EXEC(scheduler_init());
LOG_EXEC(task_init());
LOG_EXEC(thread_init());
LOG_EXEC(futex_init());
if (init.cnt > 0) {
count_t i;
for (i = 0; i < init.cnt; i++)
printf("init[%zd].addr=%.*p, init[%zd].size=%zd\n", i,
sizeof(uintptr_t) * 2, init.tasks[i].addr, i,
LOG("init[%" PRIc "].addr=%#" PRIp ", init[%" PRIc
"].size=%#" PRIs "\n", i, init.tasks[i].addr, i,
init.tasks[i].size);
} else
printf("No init binaries found\n");
ipc_init();
 
LOG_EXEC(ipc_init());
LOG_EXEC(klog_init());
LOG_EXEC(console_init());
#ifdef CONFIG_KCONSOLE
LOG_EXEC(kconsole_notify_init());
#endif
/*
* Create kernel task.
*/
k = task_create(AS_KERNEL, "kernel");
if (!k)
panic("can't create kernel task\n");
task_t *kernel = task_create(AS_KERNEL, "kernel");
if (!kernel)
panic("Cannot create kernel task.");
/*
* Create the first thread.
*/
t = thread_create(kinit, NULL, k, 0, "kinit", true);
if (!t)
panic("can't create kinit thread\n");
thread_ready(t);
thread_t *kinit_thread
= thread_create(kinit, NULL, kernel, 0, "kinit", true);
if (!kinit_thread)
panic("Cannot create kinit thread.");
LOG_EXEC(thread_ready(kinit_thread));
/*
* This call to scheduler() will return to kinit,
322,6 → 329,7
* collide with another CPU coming up. To prevent this, we
* switch to this cpu's private stack prior to waking kmp up.
*/
context_save(&CPU->saved_context);
context_set(&CPU->saved_context, FADDR(main_ap_separated_stack),
(uintptr_t) CPU->stack, CPU_STACK_SIZE);
context_restore(&CPU->saved_context);
/branches/dd/kernel/generic/src/main/version.c
34,21 → 34,22
 
#include <main/version.h>
#include <print.h>
#include <macros.h>
 
char *project = "SPARTAN kernel";
char *copyright = "Copyright (c) 2001-2008 HelenOS project";
char *release = RELEASE;
char *name = NAME;
char *arch = ARCH;
char *copyright = "Copyright (c) 2001-2009 HelenOS project";
char *release = STRING(RELEASE);
char *name = STRING(NAME);
char *arch = STRING(KARCH);
 
#ifdef REVISION
char *revision = ", revision " REVISION;
char *revision = ", revision " STRING(REVISION);
#else
char *revision = "";
#endif
 
#ifdef TIMESTAMP
char *timestamp = " on " TIMESTAMP;
char *timestamp = " on " STRING(TIMESTAMP);
#else
char *timestamp = "";
#endif
/branches/dd/kernel/generic/src/main/uinit.c
46,7 → 46,9
#include <userspace.h>
#include <mm/slab.h>
#include <arch.h>
#include <udebug/udebug.h>
 
 
/** Thread used to bring up userspace thread.
*
* @param arg Pointer to structure containing userspace entry and stack
65,6 → 67,10
* deployed for the event of forceful task termination.
*/
thread_detach(THREAD);
 
#ifdef CONFIG_UDEBUG
udebug_stoppable_end();
#endif
uarg.uspace_entry = ((uspace_arg_t *) arg)->uspace_entry;
uarg.uspace_stack = ((uspace_arg_t *) arg)->uspace_stack;
/branches/dd/kernel/generic/src/debug/symtab.c
37,8 → 37,10
 
#include <symtab.h>
#include <byteorder.h>
#include <func.h>
#include <string.h>
#include <print.h>
#include <arch/types.h>
#include <typedefs.h>
 
/** Return entry that seems most likely to correspond to argument.
*
139,7 → 141,7
while (symtab_search_one(name, &i)) {
addr = uint64_t_le2host(symbol_table[i].address_le);
realname = symbol_table[i].symbol_name;
printf("%.*p: %s\n", sizeof(uintptr_t) * 2, addr, realname);
printf("%p: %s\n", addr, realname);
i++;
}
}
/branches/dd/kernel/generic/src/cpu/cpu.c
64,10 → 64,10
cpus = (cpu_t *) malloc(sizeof(cpu_t) * config.cpu_count,
FRAME_ATOMIC);
if (!cpus)
panic("malloc/cpus");
panic("Cannot allocate CPU structures.");
 
/* initialize everything */
memsetb((uintptr_t) cpus, sizeof(cpu_t) * config.cpu_count, 0);
memsetb(cpus, sizeof(cpu_t) * config.cpu_count, 0);
 
for (i = 0; i < config.cpu_count; i++) {
cpus[i].stack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | FRAME_ATOMIC);
86,7 → 86,7
}
#endif /* CONFIG_SMP */
 
CPU = &cpus[config.cpu_active-1];
CPU = &cpus[config.cpu_active - 1];
CPU->active = 1;
CPU->tlb_active = 1;
104,7 → 104,7
if (cpus[i].active)
cpu_print_report(&cpus[i]);
else
printf("cpu%d: not active\n", i);
printf("cpu%u: not active\n", i);
}
}
 
/branches/dd/kernel/generic/src/sysinfo/sysinfo.c
163,7 → 163,8
i = 0;
}
}
panic("Not reached\n");
 
panic("Not reached.");
return NULL;
}
 
177,7 → 178,7
sysinfo_item_t *item = sysinfo_create_path(name, root);
if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */
item->val.val=val;
item->val.val = val;
item->val_type = SYSINFO_VAL_VAL;
}
}
192,7 → 193,7
sysinfo_item_t *item = sysinfo_create_path(name, root);
if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */
item->val.fn=fn;
item->val.fn = fn;
item->val_type = SYSINFO_VAL_FUNCTION;
}
}
244,7 → 245,7
break;
}
printf("%s %s val:%d(%x) sub:%s\n", root->name, vtype, val,
printf("%s %s val:%" PRIun "(%" PRIxn ") sub:%s\n", root->name, vtype, val,
val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ?
"NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ?
"TAB" : "FUN"));
281,10 → 282,15
return ret;
}
 
#define SYSINFO_MAX_LEN 1024
 
unative_t sys_sysinfo_valid(unative_t ptr, unative_t len)
{
char *str;
sysinfo_rettype_t ret = {0, 0};
 
if (len > SYSINFO_MAX_LEN)
return ret.valid;
str = malloc(len + 1, 0);
ASSERT(str);
299,6 → 305,9
{
char *str;
sysinfo_rettype_t ret = {0, 0};
if (len > SYSINFO_MAX_LEN)
return ret.val;
str = malloc(len + 1, 0);
ASSERT(str);
/branches/dd/kernel/generic/src/interrupt/interrupt.c
86,8 → 86,17
void exc_dispatch(int n, istate_t *istate)
{
ASSERT(n < IVT_ITEMS);
 
#ifdef CONFIG_UDEBUG
if (THREAD) THREAD->udebug.uspace_state = istate;
#endif
exc_table[n].f(n + IVT_FIRST, istate);
 
#ifdef CONFIG_UDEBUG
if (THREAD) THREAD->udebug.uspace_state = NULL;
#endif
 
/* This is a safe place to exit exiting thread */
if (THREAD && THREAD->interrupted && istate_from_uspace(istate))
thread_exit();
100,8 → 109,10
panic("Unhandled exception %d.", n);
}
 
#ifdef CONFIG_KCONSOLE
 
/** kconsole cmd - print all exceptions */
static int exc_print_cmd(cmd_arg_t *argv)
static int cmd_exc_print(cmd_arg_t *argv)
{
#if (IVT_ITEMS > 0)
unsigned int i;
108,27 → 119,32
char *symbol;
 
spinlock_lock(&exctbl_lock);
 
#ifdef __32_BITS__
printf("Exc Description Handler Symbol\n");
printf("--- -------------------- ---------- --------\n");
#endif
 
#ifdef __64_BITS__
printf("Exc Description Handler Symbol\n");
printf("--- -------------------- ------------------ --------\n");
#endif
if (sizeof(void *) == 4) {
printf("Exc Description Handler Symbol\n");
printf("--- -------------------- ---------- --------\n");
} else {
printf("Exc Description Handler Symbol\n");
printf("--- -------------------- ------------------ --------\n");
}
for (i = 0; i < IVT_ITEMS; i++) {
symbol = get_symtab_entry((unative_t) exc_table[i].f);
if (!symbol)
symbol = "not found";
 
#ifdef __32_BITS__
printf("%-3u %-20s %10p %s\n", i + IVT_FIRST, exc_table[i].name,
exc_table[i].f, symbol);
#endif
 
#ifdef __64_BITS__
printf("%-3u %-20s %18p %s\n", i + IVT_FIRST, exc_table[i].name,
exc_table[i].f, symbol);
#endif
if (sizeof(void *) == 4)
printf("%-3u %-20s %#10zx %s\n", i + IVT_FIRST, exc_table[i].name,
exc_table[i].f, symbol);
else
printf("%-3u %-20s %#18zx %s\n", i + IVT_FIRST, exc_table[i].name,
exc_table[i].f, symbol);
if (((i + 1) % 20) == 0) {
printf(" -- Press any key to continue -- ");
spinlock_unlock(&exctbl_lock);
144,26 → 160,31
return 1;
}
 
 
static cmd_info_t exc_info = {
.name = "exc",
.description = "Print exception table.",
.func = exc_print_cmd,
.func = cmd_exc_print,
.help = NULL,
.argc = 0,
.argv = NULL
};
 
#endif
 
/** Initialize generic exception handling support */
void exc_init(void)
{
int i;
 
for (i=0;i < IVT_ITEMS; i++)
for (i = 0; i < IVT_ITEMS; i++)
exc_register(i, "undef", (iroutine) exc_undef);
 
#ifdef CONFIG_KCONSOLE
cmd_initialize(&exc_info);
if (!cmd_register(&exc_info))
panic("could not register command %s\n", exc_info.name);
printf("Cannot register command %s\n", exc_info.name);
#endif
}
 
/** @}
/branches/dd/kernel/generic/src/time/timeout.c
113,7 → 113,7
spinlock_lock(&t->lock);
 
if (t->cpu)
panic("t->cpu != 0");
panic("Unexpected: t->cpu != 0.");
 
t->cpu = CPU;
t->ticks = us2ticks(time);
/branches/dd/kernel/generic/src/time/clock.c
79,7 → 79,7
 
faddr = frame_alloc(ONE_FRAME, FRAME_ATOMIC);
if (!faddr)
panic("Cannot allocate page for clock");
panic("Cannot allocate page for clock.");
uptime = (uptime_t *) PA2KA(faddr);
88,9 → 88,7
uptime->useconds = 0;
 
clock_parea.pbase = (uintptr_t) faddr;
clock_parea.vbase = (uintptr_t) uptime;
clock_parea.frames = 1;
clock_parea.cacheable = true;
ddi_parea_register(&clock_parea);
 
/*
189,7 → 187,19
spinlock_unlock(&THREAD->lock);
if (!ticks && !PREEMPTION_DISABLED) {
#ifdef CONFIG_UDEBUG
istate_t *istate;
#endif
scheduler();
#ifdef CONFIG_UDEBUG
/*
* Give udebug chance to stop the thread
* before it begins executing userspace code.
*/
istate = THREAD->udebug.uspace_state;
if (istate && istate_from_uspace(istate))
udebug_before_thread_runs();
#endif
}
}
 
/branches/dd/kernel/generic/src/ddi/ddi.c
29,10 → 29,10
/** @addtogroup genericddi
* @{
*/
 
/**
* @file
* @brief Device Driver Interface functions.
* @brief Device Driver Interface functions.
*
* This file contains functions that comprise the Device Driver Interface.
* These are the functions for mapping physical memory and enabling I/O
68,82 → 68,100
*
* @param parea Pointer to physical area structure.
*
* @todo This function doesn't check for overlaps. It depends on the kernel to
* create disjunct physical memory areas.
*/
void ddi_parea_register(parea_t *parea)
{
ipl_t ipl;
 
ipl = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&parea_lock);
/*
* TODO: we should really check for overlaps here.
* However, we should be safe because the kernel is pretty sane and
* memory of different devices doesn't overlap.
* We don't check for overlaps here as the kernel is pretty sane.
*/
btree_insert(&parea_btree, (btree_key_t) parea->pbase, parea, NULL);
 
spinlock_unlock(&parea_lock);
interrupts_restore(ipl);
interrupts_restore(ipl);
}
 
/** Map piece of physical memory into virtual address space of current task.
*
* @param pf Physical address of the starting frame.
* @param vp Virtual address of the starting page.
* @param pf Physical address of the starting frame.
* @param vp Virtual address of the starting page.
* @param pages Number of pages to map.
* @param flags Address space area flags for the mapping.
*
* @return 0 on success, EPERM if the caller lacks capabilities to use this
* syscall, ENOENT if there is no task matching the specified ID or the
* physical address space is not enabled for mapping and ENOMEM if there
* was a problem in creating address space area.
* syscall, EBADMEM if pf or vf is not page aligned, ENOENT if there
* is no task matching the specified ID or the physical address space
* is not enabled for mapping and ENOMEM if there was a problem in
* creating address space area.
*
*/
static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, count_t pages, int flags)
{
ipl_t ipl;
cap_t caps;
mem_backend_data_t backend_data;
 
backend_data.base = pf;
backend_data.frames = pages;
ASSERT(TASK);
ASSERT((pf % FRAME_SIZE) == 0);
ASSERT((vp % PAGE_SIZE) == 0);
/*
* Make sure the caller is authorised to make this syscall.
*/
caps = cap_get(TASK);
cap_t caps = cap_get(TASK);
if (!(caps & CAP_MEM_MANAGER))
return EPERM;
 
ipl = interrupts_disable();
 
/*
* Check if the physical memory area is enabled for mapping.
* If the architecture supports virtually indexed caches, intercept
* attempts to create an illegal address alias.
*/
spinlock_lock(&parea_lock);
parea_t *parea;
btree_node_t *nodep;
parea = (parea_t *) btree_search(&parea_btree, (btree_key_t) pf, &nodep);
if (!parea || parea->frames < pages || ((flags & AS_AREA_CACHEABLE) &&
!parea->cacheable) || (!(flags & AS_AREA_CACHEABLE) &&
parea->cacheable)) {
/*
* This physical memory area cannot be mapped.
mem_backend_data_t backend_data;
backend_data.base = pf;
backend_data.frames = pages;
ipl_t ipl = interrupts_disable();
/* Find the zone of the physical memory */
spinlock_lock(&zones.lock);
count_t znum = find_zone(ADDR2PFN(pf), pages, 0);
if (znum == (count_t) -1) {
/* Frames not found in any zones
* -> assume it is hardware device and allow mapping
*/
spinlock_unlock(&zones.lock);
goto map;
}
if (zones.info[znum].flags & ZONE_FIRMWARE) {
/* Frames are part of firmware */
spinlock_unlock(&zones.lock);
goto map;
}
if (zone_flags_available(zones.info[znum].flags)) {
/* Frames are part of physical memory, check if the memory
* region is enabled for mapping.
*/
spinlock_unlock(&zones.lock);
spinlock_lock(&parea_lock);
btree_node_t *nodep;
parea_t *parea = (parea_t *) btree_search(&parea_btree,
(btree_key_t) pf, &nodep);
if ((!parea) || (parea->frames < pages))
goto err;
spinlock_unlock(&parea_lock);
interrupts_restore(ipl);
return ENOENT;
goto map;
}
spinlock_unlock(&parea_lock);
 
err:
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return ENOENT;
map:
spinlock_lock(&TASK->lock);
if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp, AS_AREA_ATTR_NONE,
&phys_backend, &backend_data)) {
if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp,
AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) {
/*
* The address space area could not have been created.
* We report it using ENOMEM.
169,28 → 187,24
* @param size Size of the enabled I/O space..
*
* @return 0 on success, EPERM if the caller lacks capabilities to use this
* syscall, ENOENT if there is no task matching the specified ID.
* syscall, ENOENT if there is no task matching the specified ID.
*
*/
static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size)
{
ipl_t ipl;
cap_t caps;
task_t *t;
int rc;
/*
* Make sure the caller is authorised to make this syscall.
*/
caps = cap_get(TASK);
cap_t caps = cap_get(TASK);
if (!(caps & CAP_IO_MANAGER))
return EPERM;
ipl = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&tasks_lock);
t = task_find_by_id(id);
task_t *task = task_find_by_id(id);
if ((!t) || (!context_check(CONTEXT, t->context))) {
if ((!task) || (!context_check(CONTEXT, task->context))) {
/*
* There is no task with the specified ID
* or the task belongs to a different security
200,15 → 214,16
interrupts_restore(ipl);
return ENOENT;
}
 
/* Lock the task and release the lock protecting tasks_btree. */
spinlock_lock(&t->lock);
spinlock_lock(&task->lock);
spinlock_unlock(&tasks_lock);
 
rc = ddi_iospace_enable_arch(t, ioaddr, size);
spinlock_unlock(&t->lock);
int rc = ddi_iospace_enable_arch(task, ioaddr, size);
spinlock_unlock(&task->lock);
interrupts_restore(ipl);
return rc;
}
 
220,7 → 235,8
* @param flags Flags of newly mapped pages
*
* @return 0 on success, otherwise it returns error code found in errno.h
*/
*
*/
unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base,
unative_t pages, unative_t flags)
{
234,16 → 250,15
* @param uspace_io_arg User space address of DDI argument structure.
*
* @return 0 on success, otherwise it returns error code found in errno.h
*/
*
*/
unative_t sys_iospace_enable(ddi_ioarg_t *uspace_io_arg)
{
ddi_ioarg_t arg;
int rc;
rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
int rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
if (rc != 0)
return (unative_t) rc;
return (unative_t) ddi_iospace_enable((task_id_t) arg.task_id,
(uintptr_t) arg.ioaddr, (size_t) arg.size);
}
251,20 → 266,24
/** Disable or enable preemption.
*
* @param enable If non-zero, the preemption counter will be decremented,
* leading to potential enabling of preemption. Otherwise the preemption
* counter will be incremented, preventing preemption from occurring.
* leading to potential enabling of preemption. Otherwise
* the preemption counter will be incremented, preventing
* preemption from occurring.
*
* @return Zero on success or EPERM if callers capabilities are not sufficient.
*/
*
*/
unative_t sys_preempt_control(int enable)
{
if (!cap_get(TASK) & CAP_PREEMPT_CONTROL)
return EPERM;
if (enable)
preemption_enable();
else
preemption_disable();
return 0;
if (!cap_get(TASK) & CAP_PREEMPT_CONTROL)
return EPERM;
if (enable)
preemption_enable();
else
preemption_disable();
return 0;
}
 
/** @}
/branches/dd/kernel/generic/src/ddi/irq.c
39,7 → 39,8
*
* This code is designed to support:
* - multiple devices sharing single IRQ
* - multiple IRQs per signle device
* - multiple IRQs per single device
* - multiple instances of the same device
*
*
* Note about architectures.
68,8 → 69,11
 
#include <ddi/irq.h>
#include <adt/hash_table.h>
#include <mm/slab.h>
#include <arch/types.h>
#include <synch/spinlock.h>
#include <console/console.h>
#include <memstr.h>
#include <arch.h>
 
#define KEY_INR 0
76,13 → 80,22
#define KEY_DEVNO 1
 
/**
* Spinlock protecting the hash table.
* Spinlock protecting the kernel IRQ hash table.
* This lock must be taken only when interrupts are disabled.
*/
SPINLOCK_INITIALIZE(irq_hash_table_lock);
static hash_table_t irq_hash_table;
SPINLOCK_INITIALIZE(irq_kernel_hash_table_lock);
/** The kernel IRQ hash table. */
static hash_table_t irq_kernel_hash_table;
 
/**
* Spinlock protecting the uspace IRQ hash table.
* This lock must be taken only when interrupts are disabled.
*/
SPINLOCK_INITIALIZE(irq_uspace_hash_table_lock);
/** The uspace IRQ hash table. */
hash_table_t irq_uspace_hash_table;
 
/**
* Hash table operations for cases when we know that
* there will be collisions between different keys.
*/
110,6 → 123,9
.remove_callback = NULL /* not used */
};
 
/** Number of buckets in either of the hash tables. */
static count_t buckets;
 
/** Initialize IRQ subsystem.
*
* @param inrs Numbers of unique IRQ numbers or INRs.
117,6 → 133,7
*/
void irq_init(count_t inrs, count_t chains)
{
buckets = chains;
/*
* Be smart about the choice of the hash table operations.
* In cases in which inrs equals the requested number of
123,10 → 140,17
* chains (i.e. where there is no collision between
* different keys), we can use optimized set of operations.
*/
if (inrs == chains)
hash_table_create(&irq_hash_table, chains, 2, &irq_lin_ops);
else
hash_table_create(&irq_hash_table, chains, 2, &irq_ht_ops);
if (inrs == chains) {
hash_table_create(&irq_uspace_hash_table, chains, 2,
&irq_lin_ops);
hash_table_create(&irq_kernel_hash_table, chains, 2,
&irq_lin_ops);
} else {
hash_table_create(&irq_uspace_hash_table, chains, 2,
&irq_ht_ops);
hash_table_create(&irq_kernel_hash_table, chains, 2,
&irq_ht_ops);
}
}
 
/** Initialize one IRQ structure.
136,21 → 160,12
*/
void irq_initialize(irq_t *irq)
{
memsetb(irq, sizeof(irq_t), 0);
link_initialize(&irq->link);
spinlock_initialize(&irq->lock, "irq.lock");
irq->preack = false;
link_initialize(&irq->notif_cfg.link);
irq->inr = -1;
irq->devno = -1;
irq->trigger = (irq_trigger_t) 0;
irq->claim = NULL;
irq->handler = NULL;
irq->arg = NULL;
irq->notif_cfg.notify = false;
irq->notif_cfg.answerbox = NULL;
irq->notif_cfg.code = NULL;
irq->notif_cfg.method = 0;
irq->notif_cfg.counter = 0;
link_initialize(&irq->notif_cfg.link);
}
 
/** Register IRQ for device.
157,9 → 172,10
*
* The irq structure must be filled with information
* about the interrupt source and with the claim()
* function pointer and irq_handler() function pointer.
* function pointer and handler() function pointer.
*
* @param irq IRQ structure belonging to a device.
* @param irq IRQ structure belonging to a device.
* @return True on success, false on failure.
*/
void irq_register(irq_t *irq)
{
170,88 → 186,101
};
ipl = interrupts_disable();
spinlock_lock(&irq_hash_table_lock);
hash_table_insert(&irq_hash_table, key, &irq->link);
spinlock_unlock(&irq_hash_table_lock);
spinlock_lock(&irq_kernel_hash_table_lock);
spinlock_lock(&irq->lock);
hash_table_insert(&irq_kernel_hash_table, key, &irq->link);
spinlock_unlock(&irq->lock);
spinlock_unlock(&irq_kernel_hash_table_lock);
interrupts_restore(ipl);
}
 
/** Dispatch the IRQ.
/** Search and lock the uspace IRQ hash table.
*
* We assume this function is only called from interrupt
* context (i.e. that interrupts are disabled prior to
* this call).
*
* This function attempts to lookup a fitting IRQ
* structure. In case of success, return with interrupts
* disabled and holding the respective structure.
*
* @param inr Interrupt number (aka inr or irq).
*
* @return IRQ structure of the respective device or NULL.
*/
irq_t *irq_dispatch_and_lock(inr_t inr)
static irq_t *irq_dispatch_and_lock_uspace(inr_t inr)
{
link_t *lnk;
unative_t key[] = {
(unative_t) inr,
(unative_t) -1 /* search will use claim() instead of devno */
(unative_t) -1 /* search will use claim() instead of devno */
};
spinlock_lock(&irq_hash_table_lock);
 
lnk = hash_table_find(&irq_hash_table, key);
spinlock_lock(&irq_uspace_hash_table_lock);
lnk = hash_table_find(&irq_uspace_hash_table, key);
if (lnk) {
irq_t *irq;
irq = hash_table_get_instance(lnk, irq_t, link);
 
spinlock_unlock(&irq_hash_table_lock);
spinlock_unlock(&irq_uspace_hash_table_lock);
return irq;
}
spinlock_unlock(&irq_uspace_hash_table_lock);
spinlock_unlock(&irq_hash_table_lock);
 
return NULL;
return NULL;
}
 
/** Find the IRQ structure corresponding to inr and devno.
/** Search and lock the kernel IRQ hash table.
*
* This functions attempts to lookup the IRQ structure
* corresponding to its arguments. On success, this
* function returns with interrups disabled, holding
* the lock of the respective IRQ structure.
*
* This function assumes interrupts are already disabled.
*
* @param inr INR being looked up.
* @param devno Devno being looked up.
*
* @return Locked IRQ structure on success or NULL on failure.
*/
irq_t *irq_find_and_lock(inr_t inr, devno_t devno)
static irq_t *irq_dispatch_and_lock_kernel(inr_t inr)
{
link_t *lnk;
unative_t keys[] = {
unative_t key[] = {
(unative_t) inr,
(unative_t) devno
(unative_t) -1 /* search will use claim() instead of devno */
};
spinlock_lock(&irq_hash_table_lock);
 
lnk = hash_table_find(&irq_hash_table, keys);
spinlock_lock(&irq_kernel_hash_table_lock);
lnk = hash_table_find(&irq_kernel_hash_table, key);
if (lnk) {
irq_t *irq;
irq = hash_table_get_instance(lnk, irq_t, link);
 
spinlock_unlock(&irq_hash_table_lock);
spinlock_unlock(&irq_kernel_hash_table_lock);
return irq;
}
spinlock_unlock(&irq_kernel_hash_table_lock);
spinlock_unlock(&irq_hash_table_lock);
return NULL;
}
 
return NULL;
/** Dispatch the IRQ.
*
* We assume this function is only called from interrupt
* context (i.e. that interrupts are disabled prior to
* this call).
*
* This function attempts to lookup a fitting IRQ
* structure. In case of success, return with interrupts
* disabled and holding the respective structure.
*
* @param inr Interrupt number (aka inr or irq).
*
* @return IRQ structure of the respective device or NULL.
*/
irq_t *irq_dispatch_and_lock(inr_t inr)
{
irq_t *irq;
/*
* If the kernel console is silenced,
* then try first the uspace handlers,
* eventually fall back to kernel handlers.
*
* If the kernel console is active,
* then do it the other way around.
*/
if (silent) {
irq = irq_dispatch_and_lock_uspace(inr);
if (irq)
return irq;
return irq_dispatch_and_lock_kernel(inr);
}
irq = irq_dispatch_and_lock_kernel(inr);
if (irq)
return irq;
return irq_dispatch_and_lock_uspace(inr);
}
 
/** Compute hash index for the key.
270,7 → 299,7
index_t irq_ht_hash(unative_t key[])
{
inr_t inr = (inr_t) key[KEY_INR];
return inr % irq_hash_table.entries;
return inr % buckets;
}
 
/** Compare hash table element with a key.
304,7 → 333,8
spinlock_lock(&irq->lock);
if (devno == -1) {
/* Invoked by irq_dispatch_and_lock(). */
rv = ((irq->inr == inr) && (irq->claim() == IRQ_ACCEPT));
rv = ((irq->inr == inr) &&
(irq->claim(irq) == IRQ_ACCEPT));
} else {
/* Invoked by irq_find_and_lock(). */
rv = ((irq->inr == inr) && (irq->devno == devno));
363,7 → 393,7
spinlock_lock(&irq->lock);
if (devno == -1) {
/* Invoked by irq_dispatch_and_lock() */
rv = (irq->claim() == IRQ_ACCEPT);
rv = (irq->claim(irq) == IRQ_ACCEPT);
} else {
/* Invoked by irq_find_and_lock() */
rv = (irq->devno == devno);
/branches/dd/kernel/generic/src/printf/vprintf.c
37,6 → 37,8
#include <putchar.h>
#include <synch/spinlock.h>
#include <arch/asm.h>
#include <arch/types.h>
#include <typedefs.h>
 
SPINLOCK_INITIALIZE(printf_lock); /**< vprintf spinlock */
 
60,13 → 62,13
{
struct printf_spec ps = {(int(*)(void *, size_t, void *)) vprintf_write, NULL};
int irqpri = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&printf_lock);
int ret = printf_core(fmt, &ps, ap);
spinlock_unlock(&printf_lock);
interrupts_restore(irqpri);
interrupts_restore(ipl);
return ret;
}
/branches/dd/kernel/generic/src/printf/printf_core.c
40,7 → 40,7
#include <print.h>
#include <arch/arg.h>
#include <macros.h>
#include <func.h>
#include <string.h>
#include <arch.h>
 
/** show prefixes 0x or 0 */
75,7 → 75,6
PrintfQualifierInt,
PrintfQualifierLong,
PrintfQualifierLongLong,
PrintfQualifierNative,
PrintfQualifierPointer
} qualifier_t;
 
432,7 → 431,6
* - "" Signed or unsigned int (default value).@n
* - "l" Signed or unsigned long int.@n
* - "ll" Signed or unsigned long long int.@n
* - "z" unative_t (non-standard extension).@n
*
*
* CONVERSION:@n
486,7 → 484,7
while ((c = fmt[i])) {
/* control character */
if (c == '%' ) {
if (c == '%') {
/* print common characters if any processed */
if (i > j) {
if ((retval = printf_putnchars(&fmt[j],
536,7 → 534,7
} else if (fmt[i] == '*') {
/* get width value from argument list */
i++;
width = (int)va_arg(ap, int);
width = (int) va_arg(ap, int);
if (width < 0) {
/* negative width sets '-' flag */
width *= -1;
559,7 → 557,7
* list.
*/
i++;
precision = (int)va_arg(ap, int);
precision = (int) va_arg(ap, int);
if (precision < 0) {
/* ignore negative precision */
precision = 0;
585,9 → 583,6
qualifier = PrintfQualifierLongLong;
}
break;
case 'z': /* unative_t */
qualifier = PrintfQualifierNative;
break;
default:
/* default type */
qualifier = PrintfQualifierInt;
627,7 → 622,7
* Integer values
*/
case 'P': /* pointer */
flags |= __PRINTF_FLAG_BIGCHARS;
flags |= __PRINTF_FLAG_BIGCHARS;
case 'p':
flags |= __PRINTF_FLAG_PREFIX;
base = 16;
670,34 → 665,28
switch (qualifier) {
case PrintfQualifierByte:
size = sizeof(unsigned char);
number = (uint64_t)va_arg(ap, unsigned int);
number = (uint64_t) va_arg(ap, unsigned int);
break;
case PrintfQualifierShort:
size = sizeof(unsigned short);
number = (uint64_t)va_arg(ap, unsigned int);
number = (uint64_t) va_arg(ap, unsigned int);
break;
case PrintfQualifierInt:
size = sizeof(unsigned int);
number = (uint64_t)va_arg(ap, unsigned int);
number = (uint64_t) va_arg(ap, unsigned int);
break;
case PrintfQualifierLong:
size = sizeof(unsigned long);
number = (uint64_t)va_arg(ap, unsigned long);
number = (uint64_t) va_arg(ap, unsigned long);
break;
case PrintfQualifierLongLong:
size = sizeof(unsigned long long);
number = (uint64_t)va_arg(ap,
unsigned long long);
number = (uint64_t) va_arg(ap, unsigned long long);
break;
case PrintfQualifierPointer:
size = sizeof(void *);
number = (uint64_t)(unsigned long)va_arg(ap,
void *);
number = (uint64_t) (unsigned long) va_arg(ap, void *);
break;
case PrintfQualifierNative:
size = sizeof(unative_t);
number = (uint64_t)va_arg(ap, unative_t);
break;
default: /* Unknown qualifier */
counter = -counter;
goto out;
708,7 → 697,7
flags |= __PRINTF_FLAG_NEGATIVE;
if (size == sizeof(uint64_t)) {
number = -((int64_t)number);
number = -((int64_t) number);
} else {
number = ~number;
number &=
734,7 → 723,7
}
if (i > j) {
if ((retval = printf_putnchars(&fmt[j], (unative_t)(i - j),
if ((retval = printf_putnchars(&fmt[j], (unative_t) (i - j),
ps)) < 0) { /* error */
counter = -counter;
goto out;
744,7 → 733,6
}
 
out:
return counter;
}
 
/branches/dd/kernel/generic/src/console/klog.c
File deleted
/branches/dd/kernel/generic/src/console/console.c
35,30 → 35,59
 
#include <console/console.h>
#include <console/chardev.h>
#include <sysinfo/sysinfo.h>
#include <synch/waitq.h>
#include <synch/spinlock.h>
#include <arch/types.h>
#include <ddi/device.h>
#include <ddi/irq.h>
#include <ddi/ddi.h>
#include <ipc/irq.h>
#include <arch.h>
#include <func.h>
#include <print.h>
#include <atomic.h>
 
#define BUFLEN 2048
static char debug_buffer[BUFLEN];
static size_t offset = 0;
/** Initialize stdout to something that does not print, but does not fail
*
* Save data in some buffer so that it could be retrieved in the debugger
#define KLOG_SIZE PAGE_SIZE
#define KLOG_LATENCY 8
 
/** Kernel log cyclic buffer */
static char klog[KLOG_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
 
/** Kernel log initialized */
static bool klog_inited = false;
/** First kernel log characters */
static index_t klog_start = 0;
/** Number of valid kernel log characters */
static size_t klog_len = 0;
/** Number of stored (not printed) kernel log characters */
static size_t klog_stored = 0;
/** Number of stored kernel log characters for uspace */
static size_t klog_uspace = 0;
 
/** Silence output */
bool silent = false;
 
/** Kernel log spinlock */
SPINLOCK_INITIALIZE(klog_lock);
 
/** Physical memory area used for klog buffer */
static parea_t klog_parea;
 
/*
* For now, we use 0 as INR.
* However, it is therefore desirable to have architecture specific
* definition of KLOG_VIRT_INR in the future.
*/
static void null_putchar(chardev_t *d, const char ch)
{
if (offset >= BUFLEN)
offset = 0;
debug_buffer[offset++] = ch;
}
#define KLOG_VIRT_INR 0
 
static irq_t klog_irq;
 
static chardev_operations_t null_stdout_ops = {
.write = null_putchar
.suspend = NULL,
.resume = NULL,
.write = NULL,
.read = NULL
};
 
chardev_t null_stdout = {
66,10 → 95,88
.op = &null_stdout_ops
};
 
/** Standard input character device. */
/** Allways refuse IRQ ownership.
*
* This is not a real IRQ, so we always decline.
*
* @return Always returns IRQ_DECLINE.
*/
static irq_ownership_t klog_claim(irq_t *irq)
{
return IRQ_DECLINE;
}
 
static void stdin_suspend(chardev_t *d)
{
}
 
static void stdin_resume(chardev_t *d)
{
}
 
static chardev_operations_t stdin_ops = {
.suspend = stdin_suspend,
.resume = stdin_resume,
};
 
/** Standard input character device */
static chardev_t _stdin;
chardev_t *stdin = NULL;
chardev_t *stdout = &null_stdout;
 
void console_init(void)
{
chardev_initialize("stdin", &_stdin, &stdin_ops);
stdin = &_stdin;
}
 
/** Initialize kernel logging facility
*
* The shared area contains kernel cyclic buffer. Userspace application may
* be notified on new data with indication of position and size
* of the data within the circular buffer.
*/
void klog_init(void)
{
void *faddr = (void *) KA2PA(klog);
ASSERT((uintptr_t) faddr % FRAME_SIZE == 0);
ASSERT(KLOG_SIZE % FRAME_SIZE == 0);
 
devno_t devno = device_assign_devno();
klog_parea.pbase = (uintptr_t) faddr;
klog_parea.frames = SIZE2FRAMES(KLOG_SIZE);
ddi_parea_register(&klog_parea);
 
sysinfo_set_item_val("klog.faddr", NULL, (unative_t) faddr);
sysinfo_set_item_val("klog.pages", NULL, SIZE2FRAMES(KLOG_SIZE));
sysinfo_set_item_val("klog.devno", NULL, devno);
sysinfo_set_item_val("klog.inr", NULL, KLOG_VIRT_INR);
 
irq_initialize(&klog_irq);
klog_irq.devno = devno;
klog_irq.inr = KLOG_VIRT_INR;
klog_irq.claim = klog_claim;
irq_register(&klog_irq);
spinlock_lock(&klog_lock);
klog_inited = true;
spinlock_unlock(&klog_lock);
}
 
void grab_console(void)
{
silent = false;
arch_grab_console();
}
 
void release_console(void)
{
silent = true;
arch_release_console();
}
 
/** Get character from character device. Do not echo character.
*
* @param chardev Character device.
90,10 → 197,10
return chardev->op->read(chardev);
/* no other way of interacting with user, halt */
if (CPU)
printf("cpu%d: ", CPU->id);
printf("cpu%u: ", CPU->id);
else
printf("cpu: ");
printf("halted - no kconsole\n");
printf("halted (no kconsole)\n");
cpu_halt();
}
 
125,7 → 232,7
{
index_t index = 0;
char ch;
 
while (index < buflen) {
ch = _getc(chardev);
if (ch == '\b') {
139,7 → 246,7
continue;
}
putchar(ch);
 
if (ch == '\n') { /* end of string => write 0, return */
buf[index] = '\0';
return (count_t) index;
159,10 → 266,60
return ch;
}
 
void klog_update(void)
{
spinlock_lock(&klog_lock);
if ((klog_inited) && (klog_irq.notif_cfg.notify) && (klog_uspace > 0)) {
ipc_irq_send_msg_3(&klog_irq, klog_start, klog_len, klog_uspace);
klog_uspace = 0;
}
spinlock_unlock(&klog_lock);
}
 
void putchar(char c)
{
spinlock_lock(&klog_lock);
if ((klog_stored > 0) && (stdout->op->write)) {
/* Print charaters stored in kernel log */
index_t i;
for (i = klog_len - klog_stored; i < klog_len; i++)
stdout->op->write(stdout, klog[(klog_start + i) % KLOG_SIZE], silent);
klog_stored = 0;
}
/* Store character in the cyclic kernel log */
klog[(klog_start + klog_len) % KLOG_SIZE] = c;
if (klog_len < KLOG_SIZE)
klog_len++;
else
klog_start = (klog_start + 1) % KLOG_SIZE;
if (stdout->op->write)
stdout->op->write(stdout, c);
stdout->op->write(stdout, c, silent);
else {
/* The character is just in the kernel log */
if (klog_stored < klog_len)
klog_stored++;
}
/* The character is stored for uspace */
if (klog_uspace < klog_len)
klog_uspace++;
/* Check notify uspace to update */
bool update;
if ((klog_uspace > KLOG_LATENCY) || (c == '\n'))
update = true;
else
update = false;
spinlock_unlock(&klog_lock);
if (update)
klog_update();
}
 
/** @}
/branches/dd/kernel/generic/src/console/cmd.c
50,6 → 50,7
#include <arch.h>
#include <config.h>
#include <func.h>
#include <string.h>
#include <macros.h>
#include <debug.h>
#include <symtab.h>
398,17 → 399,17
.argc = 0
};
 
/* Data and methods for 'ipc_task' command */
static int cmd_ipc_task(cmd_arg_t *argv);
static cmd_arg_t ipc_task_argv = {
/* Data and methods for 'ipc' command */
static int cmd_ipc(cmd_arg_t *argv);
static cmd_arg_t ipc_argv = {
.type = ARG_TYPE_INT,
};
static cmd_info_t ipc_task_info = {
.name = "ipc_task",
.description = "ipc_task <taskid> Show IPC information of given task.",
.func = cmd_ipc_task,
static cmd_info_t ipc_info = {
.name = "ipc",
.description = "ipc <taskid> Show IPC information of given task.",
.func = cmd_ipc,
.argc = 1,
.argv = &ipc_task_argv
.argv = &ipc_argv
};
 
/* Data and methods for 'zone' command */
461,7 → 462,7
&uptime_info,
&halt_info,
&help_info,
&ipc_task_info,
&ipc_info,
&set4_info,
&slabs_info,
&symaddr_info,
501,7 → 502,7
for (i = 0; basic_commands[i]; i++) {
cmd_initialize(basic_commands[i]);
if (!cmd_register(basic_commands[i]))
panic("could not register command %s\n", basic_commands[i]->name);
printf("Cannot register command %s\n", basic_commands[i]->name);
}
}
 
514,23 → 515,31
*/
int cmd_help(cmd_arg_t *argv)
{
link_t *cur;
 
spinlock_lock(&cmd_lock);
link_t *cur;
size_t len = 0;
for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
cmd_info_t *hlp;
hlp = list_get_instance(cur, cmd_info_t, link);
spinlock_lock(&hlp->lock);
if (strlen(hlp->name) > len)
len = strlen(hlp->name);
spinlock_unlock(&hlp->lock);
}
for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
cmd_info_t *hlp;
hlp = list_get_instance(cur, cmd_info_t, link);
spinlock_lock(&hlp->lock);
printf("%s - %s\n", hlp->name, hlp->description);
 
printf("%-*s %s\n", len, hlp->name, hlp->description);
spinlock_unlock(&hlp->lock);
}
spinlock_unlock(&cmd_lock);
 
spinlock_unlock(&cmd_lock);
return 1;
}
 
563,7 → 572,7
/* This doesn't have to be very accurate */
unative_t sec = uptime->seconds1;
printf("Up %u days, %u hours, %u minutes, %u seconds\n",
printf("Up %" PRIun " days, %" PRIun " hours, %" PRIun " minutes, %" PRIun " seconds\n",
sec / 86400, (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60);
return 1;
616,14 → 625,9
{
uintptr_t symaddr;
char *symbol;
unative_t (*f)(void);
#ifdef ia64
struct {
unative_t f;
unative_t gp;
} fptr;
#endif
 
unative_t (*fnc)(void);
fncptr_t fptr;
symaddr = get_symbol_addr((char *) argv->buffer);
if (!symaddr)
printf("Symbol %s not found.\n", argv->buffer);
632,15 → 636,9
printf("Duplicate symbol, be more specific.\n");
} else {
symbol = get_symtab_entry(symaddr);
printf("Calling %s() (%.*p)\n", symbol, sizeof(uintptr_t) * 2, symaddr);
#ifdef ia64
fptr.f = symaddr;
fptr.gp = ((unative_t *)cmd_call2)[1];
f = (unative_t (*)(void)) &fptr;
#else
f = (unative_t (*)(void)) symaddr;
#endif
printf("Result: %#zx\n", f());
fnc = (unative_t (*)(void)) arch_construct_function(&fptr, (void *) symaddr, (void *) cmd_call0);
printf("Calling %s() (%p)\n", symbol, symaddr);
printf("Result: %#" PRIxn "\n", fnc());
}
return 1;
680,15 → 678,10
{
uintptr_t symaddr;
char *symbol;
unative_t (*f)(unative_t,...);
unative_t (*fnc)(unative_t, ...);
unative_t arg1 = argv[1].intval;
#ifdef ia64
struct {
unative_t f;
unative_t gp;
}fptr;
#endif
 
fncptr_t fptr;
symaddr = get_symbol_addr((char *) argv->buffer);
if (!symaddr)
printf("Symbol %s not found.\n", argv->buffer);
697,16 → 690,9
printf("Duplicate symbol, be more specific.\n");
} else {
symbol = get_symtab_entry(symaddr);
 
printf("Calling f(%#zx): %.*p: %s\n", arg1, sizeof(uintptr_t) * 2, symaddr, symbol);
#ifdef ia64
fptr.f = symaddr;
fptr.gp = ((unative_t *)cmd_call2)[1];
f = (unative_t (*)(unative_t,...)) &fptr;
#else
f = (unative_t (*)(unative_t,...)) symaddr;
#endif
printf("Result: %#zx\n", f(arg1));
fnc = (unative_t (*)(unative_t, ...)) arch_construct_function(&fptr, (void *) symaddr, (void *) cmd_call1);
printf("Calling f(%#" PRIxn "): %p: %s\n", arg1, symaddr, symbol);
printf("Result: %#" PRIxn "\n", fnc(arg1));
}
return 1;
717,16 → 703,11
{
uintptr_t symaddr;
char *symbol;
unative_t (*f)(unative_t,unative_t,...);
unative_t (*fnc)(unative_t, unative_t, ...);
unative_t arg1 = argv[1].intval;
unative_t arg2 = argv[2].intval;
#ifdef ia64
struct {
unative_t f;
unative_t gp;
}fptr;
#endif
 
fncptr_t fptr;
symaddr = get_symbol_addr((char *) argv->buffer);
if (!symaddr)
printf("Symbol %s not found.\n", argv->buffer);
735,16 → 716,10
printf("Duplicate symbol, be more specific.\n");
} else {
symbol = get_symtab_entry(symaddr);
printf("Calling f(0x%zx,0x%zx): %.*p: %s\n",
arg1, arg2, sizeof(uintptr_t) * 2, symaddr, symbol);
#ifdef ia64
fptr.f = symaddr;
fptr.gp = ((unative_t *)cmd_call2)[1];
f = (unative_t (*)(unative_t,unative_t,...)) &fptr;
#else
f = (unative_t (*)(unative_t,unative_t,...)) symaddr;
#endif
printf("Result: %#zx\n", f(arg1, arg2));
fnc = (unative_t (*)(unative_t, unative_t, ...)) arch_construct_function(&fptr, (void *) symaddr, (void *) cmd_call2);
printf("Calling f(%#" PRIxn ", %#" PRIxn "): %p: %s\n",
arg1, arg2, symaddr, symbol);
printf("Result: %#" PRIxn "\n", fnc(arg1, arg2));
}
return 1;
755,17 → 730,12
{
uintptr_t symaddr;
char *symbol;
unative_t (*f)(unative_t,unative_t,unative_t,...);
unative_t (*fnc)(unative_t, unative_t, unative_t, ...);
unative_t arg1 = argv[1].intval;
unative_t arg2 = argv[2].intval;
unative_t arg3 = argv[3].intval;
#ifdef ia64
struct {
unative_t f;
unative_t gp;
}fptr;
#endif
 
fncptr_t fptr;
symaddr = get_symbol_addr((char *) argv->buffer);
if (!symaddr)
printf("Symbol %s not found.\n", argv->buffer);
774,16 → 744,10
printf("Duplicate symbol, be more specific.\n");
} else {
symbol = get_symtab_entry(symaddr);
printf("Calling f(0x%zx,0x%zx, 0x%zx): %.*p: %s\n",
arg1, arg2, arg3, sizeof(uintptr_t) * 2, symaddr, symbol);
#ifdef ia64
fptr.f = symaddr;
fptr.gp = ((unative_t *)cmd_call2)[1];
f = (unative_t (*)(unative_t,unative_t,unative_t,...)) &fptr;
#else
f = (unative_t (*)(unative_t,unative_t,unative_t,...)) symaddr;
#endif
printf("Result: %#zx\n", f(arg1, arg2, arg3));
fnc = (unative_t (*)(unative_t, unative_t, unative_t, ...)) arch_construct_function(&fptr, (void *) symaddr, (void *) cmd_call3);
printf("Calling f(%#" PRIxn ",%#" PRIxn ", %#" PRIxn "): %p: %s\n",
arg1, arg2, arg3, symaddr, symbol);
printf("Result: %#" PRIxn "\n", fnc(arg1, arg2, arg3));
}
return 1;
856,7 → 820,7
} else {
if (pointer)
addr = (uint32_t *)(*(unative_t *)addr);
printf("Writing 0x%x -> %.*p\n", arg1, sizeof(uintptr_t) * 2, addr);
printf("Writing %#" PRIx64 " -> %p\n", arg1, addr);
*addr = arg1;
}
937,7 → 901,7
*
* return Always 1
*/
int cmd_ipc_task(cmd_arg_t * argv) {
int cmd_ipc(cmd_arg_t * argv) {
ipc_print_task(argv[0].intval);
return 1;
}
976,8 → 940,11
int cmd_continue(cmd_arg_t *argv)
{
printf("The kernel will now relinquish the console.\n");
printf("Use userspace controls to redraw the screen.\n");
arch_release_console();
release_console();
if ((kconsole_notify) && (kconsole_irq.notif_cfg.notify))
ipc_irq_send_msg_0(&kconsole_irq);
return 1;
}
 
990,18 → 957,23
*/
int cmd_tests(cmd_arg_t *argv)
{
size_t len = 0;
test_t *test;
for (test = tests; test->name != NULL; test++) {
if (strlen(test->name) > len)
len = strlen(test->name);
}
for (test = tests; test->name != NULL; test++)
printf("%s\t\t%s%s\n", test->name, test->desc, (test->safe ? "" : " (unsafe)"));
printf("%-*s %s%s\n", len, test->name, test->desc, (test->safe ? "" : " (unsafe)"));
printf("*\t\tRun all safe tests\n");
printf("%-*s Run all safe tests\n", len, "*");
return 1;
}
 
static bool run_test(const test_t *test)
{
printf("%s\t\t%s\n", test->name, test->desc);
printf("%s (%s)\n", test->name, test->desc);
/* Update and read thread accounting
for benchmarking */
1025,7 → 997,7
char suffix;
order(dt, &cycles, &suffix);
printf("Time: %llu%c cycles\n", cycles, suffix);
printf("Time: %" PRIu64 "%c cycles\n", cycles, suffix);
if (ret == NULL) {
printf("Test passed\n");
1053,7 → 1025,7
}
for (i = 0; i < cnt; i++) {
printf("%s (%d/%d) ... ", test->name, i + 1, cnt);
printf("%s (%u/%u) ... ", test->name, i + 1, cnt);
/* Update and read thread accounting
for benchmarking */
1081,7 → 1053,7
data[i] = dt;
order(dt, &cycles, &suffix);
printf("OK (%llu%c cycles)\n", cycles, suffix);
printf("OK (%" PRIu64 "%c cycles)\n", cycles, suffix);
}
if (ret) {
1094,7 → 1066,7
}
order(sum / (uint64_t) cnt, &cycles, &suffix);
printf("Average\t\t%llu%c\n", cycles, suffix);
printf("Average\t\t%" PRIu64 "%c\n", cycles, suffix);
}
free(data);
/branches/dd/kernel/generic/src/console/chardev.c
42,7 → 42,7
* @param chardev Character device.
* @param op Implementation of character device operations.
*/
void chardev_initialize(char *name,chardev_t *chardev,
void chardev_initialize(char *name, chardev_t *chardev,
chardev_operations_t *op)
{
chardev->name = name;
/branches/dd/kernel/generic/src/console/kconsole.c
49,8 → 49,11
#include <macros.h>
#include <debug.h>
#include <func.h>
#include <string.h>
#include <symtab.h>
#include <macros.h>
#include <sysinfo/sysinfo.h>
#include <ddi/device.h>
 
/** Simple kernel console.
*
83,10 → 86,39
index_t *end);
static char history[KCONSOLE_HISTORY][MAX_CMDLINE] = {};
 
/** Initialize kconsole data structures. */
/*
* For now, we use 0 as INR.
* However, it is therefore desirable to have architecture specific
* definition of KCONSOLE_VIRT_INR in the future.
*/
#define KCONSOLE_VIRT_INR 0
 
bool kconsole_notify = false;
irq_t kconsole_irq;
 
 
/** Allways refuse IRQ ownership.
*
* This is not a real IRQ, so we always decline.
*
* @return Always returns IRQ_DECLINE.
*
*/
static irq_ownership_t kconsole_claim(irq_t *irq)
{
return IRQ_DECLINE;
}
 
 
/** Initialize kconsole data structures
*
* This is the most basic initialization, almost no
* other kernel subsystem is ready yet.
*
*/
void kconsole_init(void)
{
int i;
unsigned int i;
 
cmd_init();
for (i = 0; i < KCONSOLE_HISTORY; i++)
94,6 → 126,29
}
 
 
/** Initialize kconsole notification mechanism
*
* Initialize the virtual IRQ notification mechanism.
*
*/
void kconsole_notify_init(void)
{
devno_t devno = device_assign_devno();
sysinfo_set_item_val("kconsole.present", NULL, true);
sysinfo_set_item_val("kconsole.devno", NULL, devno);
sysinfo_set_item_val("kconsole.inr", NULL, KCONSOLE_VIRT_INR);
irq_initialize(&kconsole_irq);
kconsole_irq.devno = devno;
kconsole_irq.inr = KCONSOLE_VIRT_INR;
kconsole_irq.claim = kconsole_claim;
irq_register(&kconsole_irq);
kconsole_notify = true;
}
 
 
/** Register kconsole command.
*
* @param cmd Structure describing the command.
169,7 → 224,7
}
 
/** Try to find a command beginning with prefix */
static const char * cmdtab_search_one(const char *name,link_t **startpos)
static const char *cmdtab_search_one(const char *name,link_t **startpos)
{
size_t namelen = strlen(name);
const char *curname;
203,7 → 258,7
*/
static int cmdtab_compl(char *name)
{
static char output[MAX_SYMBOL_NAME+1];
static char output[MAX_SYMBOL_NAME + 1];
link_t *startpos = NULL;
const char *foundtxt;
int found = 0;
213,7 → 268,7
while ((foundtxt = cmdtab_search_one(name, &startpos))) {
startpos = startpos->next;
if (!found)
strncpy(output, foundtxt, strlen(foundtxt)+1);
strncpy(output, foundtxt, strlen(foundtxt) + 1);
else {
for (i = 0; output[i] && foundtxt[i] &&
output[i] == foundtxt[i]; i++)
240,11 → 295,11
}
 
static char * clever_readline(const char *prompt, chardev_t *input)
static char *clever_readline(const char *prompt, chardev_t *input)
{
static int histposition = 0;
 
static char tmp[MAX_CMDLINE+1];
static char tmp[MAX_CMDLINE + 1];
int curlen = 0, position = 0;
char *current = history[histposition];
int i;
257,7 → 312,8
if (c == '\n') {
putchar(c);
break;
} if (c == '\b') { /* Backspace */
}
if (c == '\b') { /* Backspace */
if (position == 0)
continue;
for (i = position; i < curlen; i++)
400,11 → 456,15
return current;
}
 
/** Kernel console managing thread.
/** Kernel console prompt.
*
* @param prompt Kernel console prompt (e.g kconsole/panic).
* @param msg Message to display in the beginning.
* @param kcon Wait for keypress to show the prompt
* and never exit.
*
*/
void kconsole(void *prompt)
void kconsole(char *prompt, char *msg, bool kcon)
{
cmd_info_t *cmd_info;
count_t len;
411,25 → 471,42
char *cmdline;
 
if (!stdin) {
printf("%s: no stdin\n", __func__);
LOG("No stdin for kernel console");
return;
}
if (msg)
printf("%s", msg);
if (kcon)
_getc(stdin);
while (true) {
cmdline = clever_readline((char *) prompt, stdin);
len = strlen(cmdline);
if (!len)
continue;
cmd_info = parse_cmdline(cmdline, len);
if (!cmd_info)
continue;
if (strncmp(cmd_info->name, "exit",
min(strlen(cmd_info->name), 5)) == 0)
if ((!kcon)
&& (strncmp(cmd_info->name, "exit", min(strlen(cmd_info->name), 5)) == 0))
break;
(void) cmd_info->func(cmd_info->argv);
}
}
 
/** Kernel console managing thread.
*
*/
void kconsole_thread(void *data)
{
kconsole("kconsole", "Kernel console ready (press any key to activate)\n", true);
}
 
static int parse_int_arg(char *text, size_t len, unative_t *result)
{
static char symname[MAX_SYMBOL_NAME];
543,7 → 620,8
buf = (char *) cmd->argv[i].buffer;
strncpy(buf, (const char *) &cmdline[start],
min((end - start) + 2, cmd->argv[i].len));
buf[min((end - start) + 1, cmd->argv[i].len - 1)] = '\0';
buf[min((end - start) + 1, cmd->argv[i].len - 1)] =
'\0';
break;
case ARG_TYPE_INT:
if (parse_int_arg(cmdline + start, end - start + 1,
560,8 → 638,8
'\0';
cmd->argv[i].intval = (unative_t) buf;
cmd->argv[i].vartype = ARG_TYPE_STRING;
} else if (!parse_int_arg(cmdline + start, end - start + 1,
&cmd->argv[i].intval)) {
} else if (!parse_int_arg(cmdline + start,
end - start + 1, &cmd->argv[i].intval)) {
cmd->argv[i].vartype = ARG_TYPE_INT;
} else {
printf("Unrecognized variable argument.\n");
/branches/dd/kernel/generic/src/proc/scheduler.c
451,8 → 451,8
/*
* Entering state is unexpected.
*/
panic("tid%llu: unexpected state %s\n", THREAD->tid,
thread_states[THREAD->state]);
panic("tid%" PRIu64 ": unexpected state %s.",
THREAD->tid, thread_states[THREAD->state]);
break;
}
 
504,9 → 504,9
THREAD->state = Running;
 
#ifdef SCHEDULER_VERBOSE
printf("cpu%d: tid %llu (priority=%d, ticks=%llu, nrdy=%ld)\n",
CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks,
atomic_get(&CPU->nrdy));
printf("cpu%u: tid %" PRIu64 " (priority=%d, ticks=%" PRIu64
", nrdy=%ld)\n", CPU->id, THREAD->tid, THREAD->priority,
THREAD->ticks, atomic_get(&CPU->nrdy));
#endif
 
/*
640,9 → 640,9
*/
spinlock_lock(&t->lock);
#ifdef KCPULB_VERBOSE
printf("kcpulb%d: TID %llu -> cpu%d, nrdy=%ld, "
"avg=%nd\n", CPU->id, t->tid, CPU->id,
atomic_get(&CPU->nrdy),
printf("kcpulb%u: TID %" PRIu64 " -> cpu%u, "
"nrdy=%ld, avg=%ld\n", CPU->id, t->tid,
CPU->id, atomic_get(&CPU->nrdy),
atomic_get(&nrdy) / config.cpu_active);
#endif
t->flags |= THREAD_FLAG_STOLEN;
708,7 → 708,7
continue;
 
spinlock_lock(&cpus[cpu].lock);
printf("cpu%d: address=%p, nrdy=%ld, needs_relink=%ld\n",
printf("cpu%u: address=%p, nrdy=%ld, needs_relink=%" PRIc "\n",
cpus[cpu].id, &cpus[cpu], atomic_get(&cpus[cpu].nrdy),
cpus[cpu].needs_relink);
719,11 → 719,11
spinlock_unlock(&r->lock);
continue;
}
printf("\trq[%d]: ", i);
printf("\trq[%u]: ", i);
for (cur = r->rq_head.next; cur != &r->rq_head;
cur = cur->next) {
t = list_get_instance(cur, thread_t, rq_link);
printf("%llu(%s) ", t->tid,
printf("%" PRIu64 "(%s) ", t->tid,
thread_states[t->state]);
}
printf("\n");
/branches/dd/kernel/generic/src/proc/task.c
35,10 → 35,8
* @brief Task management.
*/
 
#include <main/uinit.h>
#include <proc/thread.h>
#include <proc/task.h>
#include <proc/uarg.h>
#include <mm/as.h>
#include <mm/slab.h>
#include <atomic.h>
45,23 → 43,18
#include <synch/spinlock.h>
#include <synch/waitq.h>
#include <arch.h>
#include <panic.h>
#include <arch/barrier.h>
#include <adt/avl.h>
#include <adt/btree.h>
#include <adt/list.h>
#include <ipc/ipc.h>
#include <security/cap.h>
#include <memstr.h>
#include <ipc/ipcrsc.h>
#include <print.h>
#include <lib/elf.h>
#include <errno.h>
#include <func.h>
#include <string.h>
#include <syscall/copy.h>
 
#ifndef LOADED_PROG_STACK_PAGES_NO
#define LOADED_PROG_STACK_PAGES_NO 1
#endif
 
/** Spinlock protecting the tasks_tree AVL tree. */
SPINLOCK_INITIALIZE(tasks_lock);
 
79,11 → 72,7
 
static task_id_t task_counter = 0;
 
/** Initialize tasks
*
* Initialize kernel tasks support.
*
*/
/** Initialize kernel tasks support. */
void task_init(void)
{
TASK = NULL;
91,7 → 80,8
}
 
/*
* The idea behind this walker is to remember a single task different from TASK.
* The idea behind this walker is to remember a single task different from
* TASK.
*/
static bool task_done_walker(avltree_node_t *node, void *arg)
{
106,9 → 96,7
return true; /* continue the walk */
}
 
/** Kill all tasks except the current task.
*
*/
/** Kill all tasks except the current task. */
void task_done(void)
{
task_t *t;
128,7 → 116,7
interrupts_restore(ipl);
#ifdef CONFIG_DEBUG
printf("Killing task %llu\n", id);
printf("Killing task %" PRIu64 "\n", id);
#endif
task_kill(id);
thread_usleep(10000);
140,15 → 128,13
} while (t != NULL);
}
 
/** Create new task
/** Create new task with no threads.
*
* Create new task with no threads.
* @param as Task's address space.
* @param name Symbolic name (a copy is made).
*
* @param as Task's address space.
* @param name Symbolic name.
* @return New task's structure.
*
* @return New task's structure
*
*/
task_t *task_create(as_t *as, char *name)
{
163,7 → 149,10
spinlock_initialize(&ta->lock, "task_ta_lock");
list_initialize(&ta->th_head);
ta->as = as;
ta->name = name;
 
memcpy(ta->name, name, TASK_NAME_BUFLEN);
ta->name[TASK_NAME_BUFLEN - 1] = '\0';
 
atomic_set(&ta->refcount, 0);
atomic_set(&ta->lifecount, 0);
ta->context = CONTEXT;
170,7 → 159,18
 
ta->capabilities = 0;
ta->cycles = 0;
 
#ifdef CONFIG_UDEBUG
/* Init debugging stuff */
udebug_task_init(&ta->udebug);
 
/* Init kbox stuff */
ipc_answerbox_init(&ta->kb.box, ta);
ta->kb.thread = NULL;
mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE);
ta->kb.finished = false;
#endif
 
ipc_answerbox_init(&ta->answerbox, ta);
for (i = 0; i < IPC_MAX_PHONES; i++)
ipc_phone_init(&ta->phones[i]);
179,7 → 179,7
ipc_phone_connect(&ta->phones[0], ipc_phone_0);
atomic_set(&ta->active_calls, 0);
 
mutex_initialize(&ta->futexes_lock);
mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE);
btree_create(&ta->futexes);
ipl = interrupts_disable();
202,7 → 202,7
 
/** Destroy task.
*
* @param t Task to be destroyed.
* @param t Task to be destroyed.
*/
void task_destroy(task_t *t)
{
233,90 → 233,63
TASK = NULL;
}
 
/** Create new task with 1 thread and run it
/** Syscall for reading task ID from userspace.
*
* @param program_addr Address of program executable image.
* @param name Program name.
* @param uspace_task_id userspace address of 8-byte buffer
* where to store current task ID.
*
* @return Task of the running program or NULL on error.
* @return Zero on success or an error code from @ref errno.h.
*/
task_t *task_run_program(void *program_addr, char *name)
unative_t sys_task_get_id(task_id_t *uspace_task_id)
{
as_t *as;
as_area_t *a;
unsigned int rc;
thread_t *t;
task_t *task;
uspace_arg_t *kernel_uarg;
 
as = as_create(0);
ASSERT(as);
 
rc = elf_load((elf_header_t *) program_addr, as);
if (rc != EE_OK) {
as_destroy(as);
return NULL;
}
kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
kernel_uarg->uspace_entry =
(void *) ((elf_header_t *) program_addr)->e_entry;
kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS;
kernel_uarg->uspace_thread_function = NULL;
kernel_uarg->uspace_thread_arg = NULL;
kernel_uarg->uspace_uarg = NULL;
task = task_create(as, name);
ASSERT(task);
 
/*
* Create the data as_area.
* No need to acquire lock on TASK because taskid remains constant for
* the lifespan of the task.
*/
a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS,
AS_AREA_ATTR_NONE, &anon_backend, NULL);
 
/*
* Create the main thread.
*/
t = thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE,
"uinit", false);
ASSERT(t);
thread_ready(t);
 
return task;
return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid,
sizeof(TASK->taskid));
}
 
/** Syscall for reading task ID from userspace.
/** Syscall for setting the task name.
*
* @param uspace_task_id Userspace address of 8-byte buffer where to store
* current task ID.
* The name simplifies identifying the task in the task list.
*
* @param name The new name for the task. (typically the same
* as the command used to execute it).
*
* @return 0 on success or an error code from @ref errno.h.
*/
unative_t sys_task_get_id(task_id_t *uspace_task_id)
unative_t sys_task_set_name(const char *uspace_name, size_t name_len)
{
/*
* No need to acquire lock on TASK because taskid
* remains constant for the lifespan of the task.
*/
return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid,
sizeof(TASK->taskid));
int rc;
char namebuf[TASK_NAME_BUFLEN];
 
/* Cap length of name and copy it from userspace. */
 
if (name_len > TASK_NAME_BUFLEN - 1)
name_len = TASK_NAME_BUFLEN - 1;
 
rc = copy_from_uspace(namebuf, uspace_name, name_len);
if (rc != 0)
return (unative_t) rc;
 
namebuf[name_len] = '\0';
strncpy(TASK->name, namebuf, TASK_NAME_BUFLEN);
 
return EOK;
}
 
/** Find task structure corresponding to task ID.
*
* The tasks_lock must be already held by the caller of this function
* and interrupts must be disabled.
* The tasks_lock must be already held by the caller of this function and
* interrupts must be disabled.
*
* @param id Task ID.
* @param id Task ID.
*
* @return Task structure address or NULL if there is no such task ID.
* @return Task structure address or NULL if there is no such task
* ID.
*/
task_t *task_find_by_id(task_id_t id)
{
avltree_node_t *node;
task_t *task_find_by_id(task_id_t id) { avltree_node_t *node;
node = avltree_search(&tasks_tree, (avltree_key_t) id);
 
327,11 → 300,13
 
/** Get accounting data of given task.
*
* Note that task lock of 't' must be already held and
* interrupts must be already disabled.
* Note that task lock of 't' must be already held and interrupts must be
* already disabled.
*
* @param t Pointer to thread.
* @param t Pointer to thread.
*
* @return Number of cycles used by the task and all its threads
* so far.
*/
uint64_t task_get_accounting(task_t *t)
{
363,9 → 338,9
* This function is idempotent.
* It signals all the task's threads to bail it out.
*
* @param id ID of the task to be killed.
* @param id ID of the task to be killed.
*
* @return 0 on success or an error code from errno.h
* @return Zero on success or an error code from errno.h.
*/
int task_kill(task_id_t id)
{
386,7 → 361,7
spinlock_unlock(&tasks_lock);
/*
* Interrupt all threads except ktaskclnp.
* Interrupt all threads.
*/
spinlock_lock(&ta->lock);
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
394,7 → 369,7
bool sleeping = false;
thr = list_get_instance(cur, thread_t, th_link);
spinlock_lock(&thr->lock);
thr->interrupted = true;
if (thr->state == Sleeping)
420,18 → 395,22
uint64_t cycles;
char suffix;
order(task_get_accounting(t), &cycles, &suffix);
if (sizeof(void *) == 4)
printf("%-6llu %-10s %-3ld %#10zx %#10zx %9llu%c %7zd %6zd",
t->taskid, t->name, t->context, t, t->as, cycles, suffix,
t->refcount, atomic_get(&t->active_calls));
else
printf("%-6llu %-10s %-3ld %#18zx %#18zx %9llu%c %7zd %6zd",
t->taskid, t->name, t->context, t, t->as, cycles, suffix,
t->refcount, atomic_get(&t->active_calls));
 
#ifdef __32_BITS__
printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64
"%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles,
suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls));
#endif
 
#ifdef __64_BITS__
printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64
"%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles,
suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls));
#endif
 
for (j = 0; j < IPC_MAX_PHONES; j++) {
if (t->phones[j].callee)
printf(" %zd:%#zx", j, t->phones[j].callee);
printf(" %d:%p", j, t->phones[j].callee);
}
printf("\n");
447,19 → 426,21
/* Messing with task structures, avoid deadlock */
ipl = interrupts_disable();
spinlock_lock(&tasks_lock);
if (sizeof(void *) == 4) {
printf("taskid name ctx address as "
"cycles threads calls callee\n");
printf("------ ---------- --- ---------- ---------- "
"---------- ------- ------ ------>\n");
} else {
printf("taskid name ctx address as "
"cycles threads calls callee\n");
printf("------ ---------- --- ------------------ ------------------ "
"---------- ------- ------ ------>\n");
}
 
#ifdef __32_BITS__
printf("taskid name ctx address as "
"cycles threads calls callee\n");
printf("------ ------------ --- ---------- ---------- "
"---------- ------- ------ ------>\n");
#endif
 
#ifdef __64_BITS__
printf("taskid name ctx address as "
"cycles threads calls callee\n");
printf("------ ------------ --- ------------------ ------------------ "
"---------- ------- ------ ------>\n");
#endif
 
avltree_walk(&tasks_tree, task_print_walker, NULL);
 
spinlock_unlock(&tasks_lock);
/branches/dd/kernel/generic/src/proc/tasklet.c
51,7 → 51,7
tasklet_list = malloc(sizeof(tasklet_descriptor_t *) * config.cpu_count, 0);
if (!tasklet_list)
panic("Error initializing tasklets");
panic("Error initializing tasklets.");
for (i = 0; i < config.cpu_count; i++)
tasklet_list[i] = NULL;
/branches/dd/kernel/generic/src/proc/thread.c
67,9 → 67,13
#include <main/uinit.h>
#include <syscall/copy.h>
#include <errno.h>
#include <console/klog.h>
 
 
#ifndef LOADED_PROG_STACK_PAGES_NO
#define LOADED_PROG_STACK_PAGES_NO 1
#endif
 
 
/** Thread states */
char *thread_states[] = {
"Invalid",
98,7 → 102,7
thread_id_t last_tid = 0;
 
static slab_cache_t *thread_slab;
#ifdef ARCH_HAS_FPU
#ifdef CONFIG_FPU
slab_cache_t *fpu_context_slab;
#endif
 
157,7 → 161,7
/* call the architecture-specific part of the constructor */
thr_constructor_arch(t);
#ifdef ARCH_HAS_FPU
#ifdef CONFIG_FPU
#ifdef CONFIG_FPU_LAZY
t->saved_fpu_context = NULL;
#else
165,11 → 169,11
if (!t->saved_fpu_context)
return -1;
#endif
#endif
#endif
 
t->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags);
if (!t->kstack) {
#ifdef ARCH_HAS_FPU
#ifdef CONFIG_FPU
if (t->saved_fpu_context)
slab_free(fpu_context_slab, t->saved_fpu_context);
#endif
176,6 → 180,10
return -1;
}
 
#ifdef CONFIG_UDEBUG
mutex_initialize(&t->udebug.lock, MUTEX_PASSIVE);
#endif
 
return 0;
}
 
188,7 → 196,7
thr_destructor_arch(t);
 
frame_free(KA2PA(t->kstack));
#ifdef ARCH_HAS_FPU
#ifdef CONFIG_FPU
if (t->saved_fpu_context)
slab_free(fpu_context_slab, t->saved_fpu_context);
#endif
203,11 → 211,11
void thread_init(void)
{
THREAD = NULL;
atomic_set(&nrdy,0);
atomic_set(&nrdy, 0);
thread_slab = slab_cache_create("thread_slab", sizeof(thread_t), 0,
thr_constructor, thr_destructor, 0);
 
#ifdef ARCH_HAS_FPU
#ifdef CONFIG_FPU
fpu_context_slab = slab_cache_create("fpu_slab", sizeof(fpu_context_t),
FPU_CONTEXT_ALIGN, NULL, NULL, 0);
#endif
271,7 → 279,7
* guarantee that the task won't cease to exist during the
* call. The task's lock may not be held.
* @param flags Thread flags.
* @param name Symbolic name.
* @param name Symbolic name (a copy is made).
* @param uncounted Thread's accounting doesn't affect accumulated task
* accounting.
*
289,8 → 297,7
return NULL;
/* Not needed, but good for debugging */
memsetb((uintptr_t) t->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES,
0);
memsetb(t->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, 0);
ipl = interrupts_disable();
spinlock_lock(&tidlock);
309,6 → 316,7
interrupts_restore(ipl);
memcpy(t->name, name, THREAD_NAME_BUFLEN);
t->name[THREAD_NAME_BUFLEN - 1] = '\0';
t->thread_code = func;
t->thread_arg = arg;
344,6 → 352,11
avltree_node_initialize(&t->threads_tree_node);
t->threads_tree_node.key = (uintptr_t) t;
 
#ifdef CONFIG_UDEBUG
/* Init debugging stuff */
udebug_thread_initialize(&t->udebug);
#endif
 
/* might depend on previous initialization */
thread_create_arch(t);
 
406,12 → 419,17
ipl_t ipl;
 
/*
* Attach to the current task.
* Attach to the specified task.
*/
ipl = interrupts_disable();
spinlock_lock(&task->lock);
 
atomic_inc(&task->refcount);
atomic_inc(&task->lifecount);
 
/* Must not count kbox thread into lifecount */
if (t->flags & THREAD_FLAG_USPACE)
atomic_inc(&task->lifecount);
 
list_append(&t->th_link, &task->th_head);
spinlock_unlock(&task->lock);
 
434,18 → 452,22
{
ipl_t ipl;
 
if (atomic_predec(&TASK->lifecount) == 0) {
/*
* We are the last thread in the task that still has not exited.
* With the exception of the moment the task was created, new
* threads can only be created by threads of the same task.
* We are safe to perform cleanup.
*/
if (THREAD->flags & THREAD_FLAG_USPACE) {
if (THREAD->flags & THREAD_FLAG_USPACE) {
#ifdef CONFIG_UDEBUG
/* Generate udebug THREAD_E event */
udebug_thread_e_event();
#endif
if (atomic_predec(&TASK->lifecount) == 0) {
/*
* We are the last userspace thread in the task that
* still has not exited. With the exception of the
* moment the task was created, new userspace threads
* can only be created by threads of the same task.
* We are safe to perform cleanup.
*/
ipc_cleanup();
futex_cleanup();
klog_printf("Cleanup of task %llu completed.",
TASK->taskid);
futex_cleanup();
LOG("Cleanup of task %" PRIu64" completed.", TASK->taskid);
}
}
 
581,33 → 603,37
 
static bool thread_walker(avltree_node_t *node, void *arg)
{
thread_t *t;
t = avltree_get_instance(node, thread_t, threads_tree_node);
 
thread_t *t = avltree_get_instance(node, thread_t, threads_tree_node);
uint64_t cycles;
char suffix;
order(t->cycles, &cycles, &suffix);
if (sizeof(void *) == 4)
printf("%-6llu %-10s %#10zx %-8s %#10zx %-3ld %#10zx %#10zx %9llu%c ",
t->tid, t->name, t, thread_states[t->state], t->task,
t->task->context, t->thread_code, t->kstack, cycles, suffix);
else
printf("%-6llu %-10s %#18zx %-8s %#18zx %-3ld %#18zx %#18zx %9llu%c ",
t->tid, t->name, t, thread_states[t->state], t->task,
t->task->context, t->thread_code, t->kstack, cycles, suffix);
 
#ifdef __32_BITS__
printf("%-6" PRIu64" %-10s %10p %-8s %10p %-3" PRIu32 " %10p %10p %9" PRIu64 "%c ",
t->tid, t->name, t, thread_states[t->state], t->task,
t->task->context, t->thread_code, t->kstack, cycles, suffix);
#endif
 
#ifdef __64_BITS__
printf("%-6" PRIu64" %-10s %18p %-8s %18p %-3" PRIu32 " %18p %18p %9" PRIu64 "%c ",
t->tid, t->name, t, thread_states[t->state], t->task,
t->task->context, t->thread_code, t->kstack, cycles, suffix);
#endif
if (t->cpu)
printf("%-4zd", t->cpu->id);
printf("%-4u", t->cpu->id);
else
printf("none");
if (t->state == Sleeping) {
if (sizeof(uintptr_t) == 4)
printf(" %#10zx", t->sleep_queue);
else
printf(" %#18zx", t->sleep_queue);
#ifdef __32_BITS__
printf(" %10p", t->sleep_queue);
#endif
 
#ifdef __64_BITS__
printf(" %18p", t->sleep_queue);
#endif
}
printf("\n");
623,23 → 649,25
/* Messing with thread structures, avoid deadlock */
ipl = interrupts_disable();
spinlock_lock(&threads_lock);
if (sizeof(uintptr_t) == 4) {
printf("tid name address state task "
"ctx code stack cycles cpu "
"waitqueue\n");
printf("------ ---------- ---------- -------- ---------- "
"--- ---------- ---------- ---------- ---- "
"----------\n");
} else {
printf("tid name address state task "
"ctx code stack cycles cpu "
"waitqueue\n");
printf("------ ---------- ------------------ -------- ------------------ "
"--- ------------------ ------------------ ---------- ---- "
"------------------\n");
}
 
#ifdef __32_BITS__
printf("tid name address state task "
"ctx code stack cycles cpu "
"waitqueue\n");
printf("------ ---------- ---------- -------- ---------- "
"--- ---------- ---------- ---------- ---- "
"----------\n");
#endif
 
#ifdef __64_BITS__
printf("tid name address state task "
"ctx code stack cycles cpu "
"waitqueue\n");
printf("------ ---------- ------------------ -------- ------------------ "
"--- ------------------ ------------------ ---------- ---- "
"------------------\n");
#endif
 
avltree_walk(&threads_tree, thread_walker, NULL);
 
spinlock_unlock(&threads_lock);
664,7 → 692,6
return node != NULL;
}
 
 
/** Update accounting of current thread.
*
* Note that thread_lock on THREAD must be already held and
682,7 → 709,7
*
*/
unative_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name,
thread_id_t *uspace_thread_id)
size_t name_len, thread_id_t *uspace_thread_id)
{
thread_t *t;
char namebuf[THREAD_NAME_BUFLEN];
689,10 → 716,15
uspace_arg_t *kernel_uarg;
int rc;
 
rc = copy_from_uspace(namebuf, uspace_name, THREAD_NAME_BUFLEN);
if (name_len > THREAD_NAME_BUFLEN - 1)
name_len = THREAD_NAME_BUFLEN - 1;
 
rc = copy_from_uspace(namebuf, uspace_name, name_len);
if (rc != 0)
return (unative_t) rc;
 
namebuf[name_len] = '\0';
 
/*
* In case of failure, kernel_uarg will be deallocated in this function.
* In case of success, kernel_uarg will be freed in uinit().
731,7 → 763,18
return (unative_t) rc;
}
}
#ifdef CONFIG_UDEBUG
/*
* Generate udebug THREAD_B event and attach the thread.
* This must be done atomically (with the debug locks held),
* otherwise we would either miss some thread or receive
* THREAD_B events for threads that already existed
* and could be detected with THREAD_READ before.
*/
udebug_thread_b_event_attach(t, TASK);
#else
thread_attach(t, TASK);
#endif
thread_ready(t);
 
return 0;
/branches/dd/kernel/generic/src/proc/program.c
0,0 → 1,233
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genericproc
* @{
*/
 
/**
* @file
* @brief Running userspace programs.
*/
 
#include <main/uinit.h>
#include <proc/thread.h>
#include <proc/task.h>
#include <proc/uarg.h>
#include <mm/as.h>
#include <mm/slab.h>
#include <arch.h>
#include <adt/list.h>
#include <ipc/ipc.h>
#include <ipc/ipcrsc.h>
#include <security/cap.h>
#include <lib/elf.h>
#include <errno.h>
#include <print.h>
#include <syscall/copy.h>
#include <proc/program.h>
 
#ifndef LOADED_PROG_STACK_PAGES_NO
#define LOADED_PROG_STACK_PAGES_NO 1
#endif
 
/**
* Points to the binary image used as the program loader. All non-initial
* tasks are created from this executable image.
*/
void *program_loader = NULL;
 
/** Create a program using an existing address space.
*
* @param as Address space containing a binary program image.
* @param entry_addr Program entry-point address in program address space.
* @param name Name to set for the program's task.
* @param p Buffer for storing program information.
*/
void program_create(as_t *as, uintptr_t entry_addr, char *name, program_t *p)
{
as_area_t *a;
uspace_arg_t *kernel_uarg;
 
kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
kernel_uarg->uspace_entry = (void *) entry_addr;
kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS;
kernel_uarg->uspace_thread_function = NULL;
kernel_uarg->uspace_thread_arg = NULL;
kernel_uarg->uspace_uarg = NULL;
p->task = task_create(as, name);
ASSERT(p->task);
 
/*
* Create the data as_area.
*/
a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS,
AS_AREA_ATTR_NONE, &anon_backend, NULL);
 
/*
* Create the main thread.
*/
p->main_thread = thread_create(uinit, kernel_uarg, p->task,
THREAD_FLAG_USPACE, "uinit", false);
ASSERT(p->main_thread);
}
 
/** Parse an executable image in the kernel memory.
*
* If the image belongs to a program loader, it is registered as such,
* (and *task is set to NULL). Otherwise a task is created from the
* executable image. The task is returned in *task.
*
* @param image_addr Address of an executable program image.
* @param name Name to set for the program's task.
* @param p Buffer for storing program info. If image_addr
* points to a loader image, p->task will be set to
* NULL and EOK will be returned.
*
* @return EOK on success or negative error code.
*/
int program_create_from_image(void *image_addr, char *name, program_t *p)
{
as_t *as;
unsigned int rc;
 
as = as_create(0);
ASSERT(as);
 
rc = elf_load((elf_header_t *) image_addr, as, 0);
if (rc != EE_OK) {
as_destroy(as);
p->task = NULL;
p->main_thread = NULL;
if (rc != EE_LOADER)
return ENOTSUP;
/* Register image as the program loader */
ASSERT(program_loader == NULL);
program_loader = image_addr;
printf("Registered program loader at 0x%" PRIp "\n",
image_addr);
return EOK;
}
 
program_create(as, ((elf_header_t *) image_addr)->e_entry, name, p);
 
return EOK;
}
 
/** Create a task from the program loader image.
*
* @param p Buffer for storing program info.
* @param name Name to set for the program's task.
*
* @return EOK on success or negative error code.
*/
int program_create_loader(program_t *p, char *name)
{
as_t *as;
unsigned int rc;
void *loader;
 
as = as_create(0);
ASSERT(as);
 
loader = program_loader;
if (!loader) {
printf("Cannot spawn loader as none was registered\n");
return ENOENT;
}
 
rc = elf_load((elf_header_t *) program_loader, as, ELD_F_LOADER);
if (rc != EE_OK) {
as_destroy(as);
return ENOENT;
}
 
program_create(as, ((elf_header_t *) program_loader)->e_entry,
name, p);
 
return EOK;
}
 
/** Make program ready.
*
* Switch program's main thread to the ready state.
*
* @param p Program to make ready.
*/
void program_ready(program_t *p)
{
thread_ready(p->main_thread);
}
 
/** Syscall for creating a new loader instance from userspace.
*
* Creates a new task from the program loader image and sets
* the task name.
*
* @param name Name to set on the new task (typically the same
* as the command used to execute it).
*
* @return 0 on success or an error code from @ref errno.h.
*/
unative_t sys_program_spawn_loader(char *uspace_name, size_t name_len)
{
program_t p;
int rc;
char namebuf[TASK_NAME_BUFLEN];
 
/* Cap length of name and copy it from userspace. */
 
if (name_len > TASK_NAME_BUFLEN - 1)
name_len = TASK_NAME_BUFLEN - 1;
 
rc = copy_from_uspace(namebuf, uspace_name, name_len);
if (rc != 0)
return (unative_t) rc;
 
namebuf[name_len] = '\0';
 
/* Spawn the new task. */
 
rc = program_create_loader(&p, namebuf);
if (rc != 0)
return rc;
 
// FIXME: control the capabilities
cap_set(p.task, cap_get(TASK));
 
program_ready(&p);
 
return EOK;
}
 
/** @}
*/
/branches/dd/kernel/generic/src/lib/objc_ext.c
File deleted
/branches/dd/kernel/generic/src/lib/objc.c
File deleted
/branches/dd/kernel/generic/src/lib/rd.c
42,7 → 42,6
#include <mm/frame.h>
#include <sysinfo/sysinfo.h>
#include <ddi/ddi.h>
#include <print.h>
#include <align.h>
 
static parea_t rd_parea; /**< Physical memory area for rd. */
49,14 → 48,14
 
/**
* RAM disk initialization routine. At this point, the RAM disk memory is shared
* and information about the share is provided as sysinfo values to the userspace
* tasks.
* and information about the share is provided as sysinfo values to the
* userspace tasks.
*/
int init_rd(rd_header * header, size_t size)
int init_rd(rd_header_t *header, size_t size)
{
/* Identify RAM disk */
if ((header->magic[0] != RD_MAG0) || (header->magic[1] != RD_MAG1) ||
(header->magic[2] != RD_MAG2) || (header->magic[3] != RD_MAG3))
(header->magic[2] != RD_MAG2) || (header->magic[3] != RD_MAG3))
return RE_INVALID;
/* Identify version */
80,10 → 79,7
if ((hsize % FRAME_SIZE) || (dsize % FRAME_SIZE))
return RE_UNSUPPORTED;
if (dsize % FRAME_SIZE)
return RE_UNSUPPORTED;
 
if (hsize > size)
return RE_INVALID;
90,17 → 86,16
if ((uint64_t) hsize + dsize > size)
dsize = size - hsize;
rd_parea.pbase = ALIGN_DOWN((uintptr_t) KA2PA((void *) header + hsize), FRAME_SIZE);
rd_parea.vbase = (uintptr_t) ((void *) header + hsize);
rd_parea.pbase = ALIGN_DOWN((uintptr_t) KA2PA((void *) header + hsize),
FRAME_SIZE);
rd_parea.frames = SIZE2FRAMES(dsize);
rd_parea.cacheable = true;
ddi_parea_register(&rd_parea);
 
sysinfo_set_item_val("rd", NULL, true);
sysinfo_set_item_val("rd.header_size", NULL, hsize);
sysinfo_set_item_val("rd.size", NULL, dsize);
sysinfo_set_item_val("rd.address.physical", NULL, (unative_t)
KA2PA((void *) header + hsize));
sysinfo_set_item_val("rd.address.physical", NULL,
(unative_t) KA2PA((void *) header + hsize));
 
return RE_OK;
}
/branches/dd/kernel/generic/src/lib/elf.c
57,7 → 57,7
};
 
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf,
as_t *as);
as_t *as, int flags);
static int section_header(elf_section_header_t *entry, elf_header_t *elf,
as_t *as);
static int load_segment(elf_segment_header_t *entry, elf_header_t *elf,
67,9 → 67,10
*
* @param header Pointer to ELF header in memory
* @param as Created and properly mapped address space
* @param flags A combination of ELD_F_*
* @return EE_OK on success
*/
unsigned int elf_load(elf_header_t *header, as_t * as)
unsigned int elf_load(elf_header_t *header, as_t * as, int flags)
{
int i, rc;
 
110,7 → 111,7
 
seghdr = &((elf_segment_header_t *)(((uint8_t *) header) +
header->e_phoff))[i];
rc = segment_header(seghdr, header, as);
rc = segment_header(seghdr, header, as, flags);
if (rc != EE_OK)
return rc;
}
151,8 → 152,10
* @return EE_OK on success, error code otherwise.
*/
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf,
as_t *as)
as_t *as, int flags)
{
char *interp;
 
switch (entry->p_type) {
case PT_NULL:
case PT_PHDR:
162,6 → 165,16
break;
case PT_DYNAMIC:
case PT_INTERP:
interp = (char *)elf + entry->p_offset;
/* FIXME */
/*if (memcmp((uintptr_t)interp, (uintptr_t)ELF_INTERP_ZSTR,
ELF_INTERP_ZLEN) != 0) {
return EE_UNSUPPORTED;
}*/
if ((flags & ELD_F_LOADER) == 0) {
return EE_LOADER;
}
break;
case PT_SHLIB:
case PT_NOTE:
case PT_LOPROC:
/branches/dd/kernel/generic/src/lib/string.c
0,0 → 1,170
/*
* Copyright (c) 2001-2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
* @{
*/
 
/**
* @file
* @brief Miscellaneous functions.
*/
 
#include <string.h>
#include <print.h>
#include <cpu.h>
#include <arch/asm.h>
#include <arch.h>
#include <console/kconsole.h>
 
/** Return number of characters in a string.
*
* @param str NULL terminated string.
*
* @return Number of characters in str.
*
*/
size_t strlen(const char *str)
{
int i;
for (i = 0; str[i]; i++);
return i;
}
 
/** Compare two NULL terminated strings
*
* Do a char-by-char comparison of two NULL terminated strings.
* The strings are considered equal iff they consist of the same
* characters on the minimum of their lengths.
*
* @param src First string to compare.
* @param dst Second string to compare.
*
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
*
*/
int strcmp(const char *src, const char *dst)
{
for (; *src && *dst; src++, dst++) {
if (*src < *dst)
return -1;
if (*src > *dst)
return 1;
}
if (*src == *dst)
return 0;
if (!*src)
return -1;
return 1;
}
 
 
/** Compare two NULL terminated strings
*
* Do a char-by-char comparison of two NULL terminated strings.
* The strings are considered equal iff they consist of the same
* characters on the minimum of their lengths and specified maximal
* length.
*
* @param src First string to compare.
* @param dst Second string to compare.
* @param len Maximal length for comparison.
*
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
*
*/
int strncmp(const char *src, const char *dst, size_t len)
{
unsigned int i;
for (i = 0; (*src) && (*dst) && (i < len); src++, dst++, i++) {
if (*src < *dst)
return -1;
if (*src > *dst)
return 1;
}
if (i == len || *src == *dst)
return 0;
if (!*src)
return -1;
return 1;
}
 
 
 
/** Copy NULL terminated string.
*
* Copy at most 'len' characters from string 'src' to 'dest'.
* If 'src' is shorter than 'len', '\0' is inserted behind the
* last copied character.
*
* @param src Source string.
* @param dest Destination buffer.
* @param len Size of destination buffer.
*
*/
void strncpy(char *dest, const char *src, size_t len)
{
unsigned int i;
for (i = 0; i < len; i++) {
if (!(dest[i] = src[i]))
return;
}
dest[i - 1] = '\0';
}
 
/** Find first occurence of character in string.
*
* @param s String to search.
* @param i Character to look for.
*
* @return Pointer to character in @a s or NULL if not found.
*/
extern char *strchr(const char *s, int i)
{
while (*s != '\0') {
if (*s == i)
return (char *) s;
++s;
}
return NULL;
}
 
/** @}
*/
/branches/dd/kernel/generic/src/lib/memstr.c
1,5 → 1,6
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
34,12 → 35,10
* @file
* @brief Memory string operations.
*
* This file provides architecture independent functions
* to manipulate blocks of memory. These functions
* are optimized as much as generic functions of
* this type can be. However, architectures are
* free to provide even more optimized versions of these
* functions.
* This file provides architecture independent functions to manipulate blocks of
* memory. These functions are optimized as much as generic functions of this
* type can be. However, architectures are free to provide even more optimized
* versions of these functions.
*/
 
#include <memstr.h>
46,93 → 45,119
#include <arch/types.h>
#include <align.h>
 
/** Copy block of memory
/** Copy block of memory.
*
* Copy cnt bytes from src address to dst address.
* The copying is done word-by-word and then byte-by-byte.
* The source and destination memory areas cannot overlap.
* Copy cnt bytes from src address to dst address. The copying is done
* word-by-word and then byte-by-byte. The source and destination memory areas
* cannot overlap.
*
* @param src Origin address to copy from.
* @param dst Origin address to copy to.
* @param cnt Number of bytes to copy.
* @param src Source address to copy from.
* @param dst Destination address to copy to.
* @param cnt Number of bytes to copy.
*
* @return Destination address.
*/
void *_memcpy(void * dst, const void *src, size_t cnt)
void *_memcpy(void *dst, const void *src, size_t cnt)
{
unsigned int i, j;
if (ALIGN_UP((uintptr_t) src, sizeof(unative_t)) != (uintptr_t) src ||
ALIGN_UP((uintptr_t) dst, sizeof(unative_t)) != (uintptr_t) dst) {
ALIGN_UP((uintptr_t) dst, sizeof(unative_t)) != (uintptr_t) dst) {
for (i = 0; i < cnt; i++)
((uint8_t *) dst)[i] = ((uint8_t *) src)[i];
} else {
for (i = 0; i < cnt/sizeof(unative_t); i++)
for (i = 0; i < cnt / sizeof(unative_t); i++)
((unative_t *) dst)[i] = ((unative_t *) src)[i];
for (j = 0; j < cnt%sizeof(unative_t); j++)
((uint8_t *)(((unative_t *) dst) + i))[j] = ((uint8_t *)(((unative_t *) src) + i))[j];
for (j = 0; j < cnt % sizeof(unative_t); j++)
((uint8_t *)(((unative_t *) dst) + i))[j] =
((uint8_t *)(((unative_t *) src) + i))[j];
}
return (char *) src;
return (char *) dst;
}
 
/** Fill block of memory
/** Move memory block with possible overlapping.
*
* Fill cnt bytes at dst address with the value x.
* The filling is done byte-by-byte.
* Copy cnt bytes from src address to dst address. The source and destination
* memory areas may overlap.
*
* @param dst Origin address to fill.
* @param cnt Number of bytes to fill.
* @param x Value to fill.
* @param src Source address to copy from.
* @param dst Destination address to copy to.
* @param cnt Number of bytes to copy.
*
* @return Destination address.
*/
void _memsetb(uintptr_t dst, size_t cnt, uint8_t x)
void *memmove(void *dst, const void *src, size_t n)
{
unsigned int i;
uint8_t *p = (uint8_t *) dst;
for (i = 0; i < cnt; i++)
p[i] = x;
const uint8_t *sp;
uint8_t *dp;
 
/* Nothing to do? */
if (src == dst)
return dst;
 
/* Non-overlapping? */
if (dst >= src + n || src >= dst + n) {
return memcpy(dst, src, n);
}
 
/* Which direction? */
if (src > dst) {
/* Forwards. */
sp = src;
dp = dst;
 
while (n-- != 0)
*dp++ = *sp++;
} else {
/* Backwards. */
sp = src + (n - 1);
dp = dst + (n - 1);
 
while (n-- != 0)
*dp-- = *sp--;
}
 
return dst;
}
 
/** Fill block of memory
*
* Fill cnt words at dst address with the value x.
* The filling is done word-by-word.
* Fill cnt bytes at dst address with the value x. The filling is done
* byte-by-byte.
*
* @param dst Origin address to fill.
* @param cnt Number of words to fill.
* @param x Value to fill.
* @param dst Destination address to fill.
* @param cnt Number of bytes to fill.
* @param x Value to fill.
*
*/
void _memsetw(uintptr_t dst, size_t cnt, uint16_t x)
void _memsetb(void *dst, size_t cnt, uint8_t x)
{
unsigned int i;
uint16_t *p = (uint16_t *) dst;
uint8_t *p = (uint8_t *) dst;
for (i = 0; i < cnt; i++)
p[i] = x;
p[i] = x;
}
 
/** Copy string
/** Fill block of memory.
*
* Copy string from src address to dst address.
* The copying is done char-by-char until the null
* character. The source and destination memory areas
* cannot overlap.
* Fill cnt words at dst address with the value x. The filling is done
* word-by-word.
*
* @param src Origin string to copy from.
* @param dst Origin string to copy to.
* @param dst Destination address to fill.
* @param cnt Number of words to fill.
* @param x Value to fill.
*
*/
char *strcpy(char *dest, const char *src)
void _memsetw(void *dst, size_t cnt, uint16_t x)
{
char *orig = dest;
unsigned int i;
uint16_t *p = (uint16_t *) dst;
while ((*(dest++) = *(src++)))
;
return orig;
for (i = 0; i < cnt; i++)
p[i] = x;
}
 
/** @}
/branches/dd/kernel/generic/src/lib/func.c
55,8 → 55,6
#ifdef CONFIG_DEBUG
bool rundebugger = false;
 
// TODO test_and_set not defined on all arches
// if (!test_and_set(&haltstate))
if (!atomic_get(&haltstate)) {
atomic_set(&haltstate, 1);
rundebugger = true;
66,116 → 64,19
#endif
 
interrupts_disable();
#ifdef CONFIG_DEBUG
if (rundebugger) {
printf("\n");
kconsole("panic"); /* Run kconsole as a last resort to user */
}
#endif
#if (defined(CONFIG_DEBUG)) && (defined(CONFIG_KCONSOLE))
if (rundebugger)
kconsole("panic", "\nLast resort kernel console ready\n", false);
#endif
if (CPU)
printf("cpu%d: halted\n", CPU->id);
printf("cpu%u: halted\n", CPU->id);
else
printf("cpu: halted\n");
cpu_halt();
}
 
/** Return number of characters in a string.
*
* @param str NULL terminated string.
*
* @return Number of characters in str.
*/
size_t strlen(const char *str)
{
int i;
for (i = 0; str[i]; i++)
;
return i;
}
 
/** Compare two NULL terminated strings
*
* Do a char-by-char comparison of two NULL terminated strings.
* The strings are considered equal iff they consist of the same
* characters on the minimum of their lengths.
*
* @param src First string to compare.
* @param dst Second string to compare.
*
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
*
*/
int strcmp(const char *src, const char *dst)
{
for (; *src && *dst; src++, dst++) {
if (*src < *dst)
return -1;
if (*src > *dst)
return 1;
}
if (*src == *dst)
return 0;
if (!*src)
return -1;
return 1;
}
 
 
/** Compare two NULL terminated strings
*
* Do a char-by-char comparison of two NULL terminated strings.
* The strings are considered equal iff they consist of the same
* characters on the minimum of their lengths and specified maximal
* length.
*
* @param src First string to compare.
* @param dst Second string to compare.
* @param len Maximal length for comparison.
*
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
*
*/
int strncmp(const char *src, const char *dst, size_t len)
{
unsigned int i;
for (i = 0; (*src) && (*dst) && (i < len); src++, dst++, i++) {
if (*src < *dst)
return -1;
if (*src > *dst)
return 1;
}
if (i == len || *src == *dst)
return 0;
if (!*src)
return -1;
return 1;
}
 
 
 
/** Copy NULL terminated string.
*
* Copy at most 'len' characters from string 'src' to 'dest'.
* If 'src' is shorter than 'len', '\0' is inserted behind the
* last copied character.
*
* @param src Source string.
* @param dest Destination buffer.
* @param len Size of destination buffer.
*/
void strncpy(char *dest, const char *src, size_t len)
{
unsigned int i;
for (i = 0; i < len; i++) {
if (!(dest[i] = src[i]))
return;
}
dest[i-1] = '\0';
}
 
/** Convert ascii representation to unative_t
*
* Supports 0x for hexa & 0 for octal notation.
/branches/dd/kernel/generic/src/adt/btree.c
124,7 → 124,7
lnode = leaf_node;
if (!lnode) {
if (btree_search(t, key, &lnode)) {
panic("B-tree %p already contains key %d\n", t, key);
panic("B-tree %p already contains key %" PRIu64 ".", t, key);
}
}
224,7 → 224,7
lnode = leaf_node;
if (!lnode) {
if (!btree_search(t, key, &lnode)) {
panic("B-tree %p does not contain key %d\n", t, key);
panic("B-tree %p does not contain key %" PRIu64 ".", t, key);
}
}
524,7 → 524,7
return;
}
}
panic("node %p does not contain key %d\n", node, key);
panic("Node %p does not contain key %" PRIu64 ".", node, key);
}
 
/** Remove key and its right subtree pointer from B-tree node.
551,7 → 551,7
return;
}
}
panic("node %p does not contain key %d\n", node, key);
panic("Node %p does not contain key %" PRIu64 ".", node, key);
}
 
/** Split full B-tree node and insert new key-value-right-subtree triplet.
693,7 → 693,7
if (subtree == node->subtree[i])
return i - (int) (right != false);
}
panic("node %p does not contain subtree %p\n", node, subtree);
panic("Node %p does not contain subtree %p.", node, subtree);
}
 
/** Rotate one key-value-rsubtree triplet from the left sibling to the right sibling.
970,7 → 970,7
 
printf("(");
for (i = 0; i < node->keys; i++) {
printf("%llu%s", node->key[i], i < node->keys - 1 ? "," : "");
printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : "");
if (node->depth && node->subtree[i]) {
list_append(&node->subtree[i]->bfs_link, &head);
}
992,7 → 992,7
 
printf("(");
for (i = 0; i < node->keys; i++)
printf("%llu%s", node->key[i], i < node->keys - 1 ? "," : "");
printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : "");
printf(")");
}
printf("\n");
/branches/dd/kernel/generic/src/adt/avl.c
43,7 → 43,7
*
* Every node has a pointer to its parent which allows insertion of multiple
* identical keys into the tree.
*
*
* Be careful when using this tree because of the base atribute which is added
* to every inserted node key. There is no rule in which order nodes with the
* same key are visited.
/branches/dd/kernel/generic/src/adt/hash_table.c
61,9 → 61,9
h->entry = (link_t *) malloc(m * sizeof(link_t), 0);
if (!h->entry) {
panic("cannot allocate memory for hash table\n");
panic("Cannot allocate memory for hash table.");
}
memsetb((uintptr_t) h->entry, m * sizeof(link_t), 0);
memsetb(h->entry, m * sizeof(link_t), 0);
for (i = 0; i < m; i++)
list_initialize(&h->entry[i]);
/branches/dd/kernel/generic/src/mm/slab.c
167,19 → 167,19
* Allocate frames for slab space and initialize
*
*/
static slab_t * slab_space_alloc(slab_cache_t *cache, int flags)
static slab_t *slab_space_alloc(slab_cache_t *cache, int flags)
{
void *data;
slab_t *slab;
size_t fsize;
unsigned int i;
unsigned int zone = 0;
count_t zone = 0;
data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
if (!data) {
return NULL;
}
if (! (cache->flags & SLAB_CACHE_SLINSIDE)) {
if (!(cache->flags & SLAB_CACHE_SLINSIDE)) {
slab = slab_alloc(slab_extern_cache, flags);
if (!slab) {
frame_free(KA2PA(data));
200,7 → 200,7
slab->cache = cache;
 
for (i = 0; i < cache->objects; i++)
*((int *) (slab->start + i*cache->size)) = i+1;
*((int *) (slab->start + i*cache->size)) = i + 1;
 
atomic_inc(&cache->allocated_slabs);
return slab;
239,8 → 239,7
*
* @return Number of freed pages
*/
static count_t slab_obj_destroy(slab_cache_t *cache, void *obj,
slab_t *slab)
static count_t slab_obj_destroy(slab_cache_t *cache, void *obj, slab_t *slab)
{
int freed = 0;
 
256,7 → 255,7
ASSERT(slab->available < cache->objects);
 
*((int *)obj) = slab->nextavail;
slab->nextavail = (obj - slab->start)/cache->size;
slab->nextavail = (obj - slab->start) / cache->size;
slab->available++;
 
/* Move it to correct list */
281,7 → 280,7
*
* @return Object address or null
*/
static void * slab_obj_create(slab_cache_t *cache, int flags)
static void *slab_obj_create(slab_cache_t *cache, int flags)
{
slab_t *slab;
void *obj;
301,7 → 300,8
return NULL;
spinlock_lock(&cache->slablock);
} else {
slab = list_get_instance(cache->partial_slabs.next, slab_t, link);
slab = list_get_instance(cache->partial_slabs.next, slab_t,
link);
list_remove(&slab->link);
}
obj = slab->start + slab->nextavail * cache->size;
332,8 → 332,7
*
* @param first If true, return first, else last mag
*/
static slab_magazine_t * get_mag_from_cache(slab_cache_t *cache,
int first)
static slab_magazine_t *get_mag_from_cache(slab_cache_t *cache, int first)
{
slab_magazine_t *mag = NULL;
link_t *cur;
368,8 → 367,7
*
* @return Number of freed pages
*/
static count_t magazine_destroy(slab_cache_t *cache,
slab_magazine_t *mag)
static count_t magazine_destroy(slab_cache_t *cache, slab_magazine_t *mag)
{
unsigned int i;
count_t frames = 0;
389,7 → 387,7
*
* Assume cpu_magazine lock is held
*/
static slab_magazine_t * get_full_current_mag(slab_cache_t *cache)
static slab_magazine_t *get_full_current_mag(slab_cache_t *cache)
{
slab_magazine_t *cmag, *lastmag, *newmag;
 
423,7 → 421,7
*
* @return Pointer to object or NULL if not available
*/
static void * magazine_obj_get(slab_cache_t *cache)
static void *magazine_obj_get(slab_cache_t *cache)
{
slab_magazine_t *mag;
void *obj;
458,7 → 456,7
* allocate new, exchange last & current
*
*/
static slab_magazine_t * make_empty_current_mag(slab_cache_t *cache)
static slab_magazine_t *make_empty_current_mag(slab_cache_t *cache)
{
slab_magazine_t *cmag,*lastmag,*newmag;
 
530,7 → 528,8
static unsigned int comp_objects(slab_cache_t *cache)
{
if (cache->flags & SLAB_CACHE_SLINSIDE)
return ((PAGE_SIZE << cache->order) - sizeof(slab_t)) / cache->size;
return ((PAGE_SIZE << cache->order) - sizeof(slab_t)) /
cache->size;
else
return (PAGE_SIZE << cache->order) / cache->size;
}
557,28 → 556,25
ASSERT(_slab_initialized >= 2);
 
cache->mag_cache = malloc(sizeof(slab_mag_cache_t)*config.cpu_count,0);
cache->mag_cache = malloc(sizeof(slab_mag_cache_t) * config.cpu_count,
0);
for (i = 0; i < config.cpu_count; i++) {
memsetb((uintptr_t)&cache->mag_cache[i],
sizeof(cache->mag_cache[i]), 0);
spinlock_initialize(&cache->mag_cache[i].lock, "slab_maglock_cpu");
memsetb(&cache->mag_cache[i], sizeof(cache->mag_cache[i]), 0);
spinlock_initialize(&cache->mag_cache[i].lock,
"slab_maglock_cpu");
}
}
 
/** Initialize allocated memory as a slab cache */
static void
_slab_cache_create(slab_cache_t *cache,
char *name,
size_t size,
size_t align,
int (*constructor)(void *obj, int kmflag),
int (*destructor)(void *obj),
int flags)
_slab_cache_create(slab_cache_t *cache, char *name, size_t size, size_t align,
int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj),
int flags)
{
int pages;
ipl_t ipl;
 
memsetb((uintptr_t)cache, sizeof(*cache), 0);
memsetb(cache, sizeof(*cache), 0);
cache->name = name;
 
if (align < sizeof(unative_t))
596,7 → 592,7
list_initialize(&cache->magazines);
spinlock_initialize(&cache->slablock, "slab_lock");
spinlock_initialize(&cache->maglock, "slab_maglock");
if (! (cache->flags & SLAB_CACHE_NOMAGAZINE))
if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
make_magcache(cache);
 
/* Compute slab sizes, object counts in slabs etc. */
609,7 → 605,7
if (pages == 1)
cache->order = 0;
else
cache->order = fnzb(pages-1)+1;
cache->order = fnzb(pages - 1) + 1;
 
while (badness(cache) > SLAB_MAX_BADNESS(cache)) {
cache->order += 1;
630,18 → 626,16
}
 
/** Create slab cache */
slab_cache_t * slab_cache_create(char *name,
size_t size,
size_t align,
int (*constructor)(void *obj, int kmflag),
int (*destructor)(void *obj),
int flags)
slab_cache_t *
slab_cache_create(char *name, size_t size, size_t align,
int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj),
int flags)
{
slab_cache_t *cache;
 
cache = slab_alloc(&slab_cache_cache, 0);
_slab_cache_create(cache, name, size, align, constructor, destructor,
flags);
flags);
return cache;
}
 
665,7 → 659,7
* endless loop
*/
magcount = atomic_get(&cache->magazine_counter);
while (magcount-- && (mag=get_mag_from_cache(cache,0))) {
while (magcount-- && (mag=get_mag_from_cache(cache, 0))) {
frames += magazine_destroy(cache,mag);
if (!(flags & SLAB_RECLAIM_ALL) && frames)
break;
718,8 → 712,8
_slab_reclaim(cache, SLAB_RECLAIM_ALL);
 
/* All slabs must be empty */
if (!list_empty(&cache->full_slabs) \
|| !list_empty(&cache->partial_slabs))
if (!list_empty(&cache->full_slabs) ||
!list_empty(&cache->partial_slabs))
panic("Destroying cache that is not empty.");
 
if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
727,9 → 721,8
slab_free(&slab_cache_cache, cache);
}
 
/** Allocate new object from cache - if no flags given, always returns
memory */
void * slab_alloc(slab_cache_t *cache, int flags)
/** Allocate new object from cache - if no flags given, always returns memory */
void *slab_alloc(slab_cache_t *cache, int flags)
{
ipl_t ipl;
void *result = NULL;
758,9 → 751,8
 
ipl = interrupts_disable();
 
if ((cache->flags & SLAB_CACHE_NOMAGAZINE) \
|| magazine_obj_put(cache, obj)) {
 
if ((cache->flags & SLAB_CACHE_NOMAGAZINE) ||
magazine_obj_put(cache, obj)) {
slab_obj_destroy(cache, obj, slab);
 
}
787,7 → 779,8
* memory allocation from interrupts can deadlock.
*/
 
for (cur = slab_cache_list.next;cur!=&slab_cache_list; cur=cur->next) {
for (cur = slab_cache_list.next; cur != &slab_cache_list;
cur = cur->next) {
cache = list_get_instance(cur, slab_cache_t, link);
frames += _slab_reclaim(cache, flags);
}
801,22 → 794,77
/* Print list of slabs */
void slab_print_list(void)
{
slab_cache_t *cache;
link_t *cur;
ipl_t ipl;
ipl = interrupts_disable();
spinlock_lock(&slab_cache_lock);
printf("slab name size pages obj/pg slabs cached allocated ctl\n");
printf("---------------- -------- ------ ------ ------ ------ --------- ---\n");
for (cur = slab_cache_list.next; cur != &slab_cache_list; cur = cur->next) {
int skip = 0;
 
printf("slab name size pages obj/pg slabs cached allocated"
" ctl\n");
printf("---------------- -------- ------ ------ ------ ------ ---------"
" ---\n");
 
while (true) {
slab_cache_t *cache;
link_t *cur;
ipl_t ipl;
int i;
 
/*
* We must not hold the slab_cache_lock spinlock when printing
* the statistics. Otherwise we can easily deadlock if the print
* needs to allocate memory.
*
* Therefore, we walk through the slab cache list, skipping some
* amount of already processed caches during each iteration and
* gathering statistics about the first unprocessed cache. For
* the sake of printing the statistics, we realese the
* slab_cache_lock and reacquire it afterwards. Then the walk
* starts again.
*
* This limits both the efficiency and also accuracy of the
* obtained statistics. The efficiency is decreased because the
* time complexity of the algorithm is quadratic instead of
* linear. The accuracy is impacted because we drop the lock
* after processing one cache. If there is someone else
* manipulating the cache list, we might omit an arbitrary
* number of caches or process one cache multiple times.
* However, we don't bleed for this algorithm for it is only
* statistics.
*/
 
ipl = interrupts_disable();
spinlock_lock(&slab_cache_lock);
 
for (i = 0, cur = slab_cache_list.next;
i < skip && cur != &slab_cache_list;
i++, cur = cur->next)
;
 
if (cur == &slab_cache_list) {
spinlock_unlock(&slab_cache_lock);
interrupts_restore(ipl);
break;
}
 
skip++;
 
cache = list_get_instance(cur, slab_cache_t, link);
 
char *name = cache->name;
uint8_t order = cache->order;
size_t size = cache->size;
unsigned int objects = cache->objects;
long allocated_slabs = atomic_get(&cache->allocated_slabs);
long cached_objs = atomic_get(&cache->cached_objs);
long allocated_objs = atomic_get(&cache->allocated_objs);
int flags = cache->flags;
printf("%-16s %8zd %6zd %6zd %6zd %6zd %9zd %-3s\n", cache->name, cache->size, (1 << cache->order), cache->objects, atomic_get(&cache->allocated_slabs), atomic_get(&cache->cached_objs), atomic_get(&cache->allocated_objs), cache->flags & SLAB_CACHE_SLINSIDE ? "in" : "out");
spinlock_unlock(&slab_cache_lock);
interrupts_restore(ipl);
printf("%-16s %8" PRIs " %6d %6u %6ld %6ld %9ld %-3s\n",
name, size, (1 << order), objects, allocated_slabs,
cached_objs, allocated_objs,
flags & SLAB_CACHE_SLINSIDE ? "in" : "out");
}
spinlock_unlock(&slab_cache_lock);
interrupts_restore(ipl);
}
 
void slab_cache_init(void)
824,32 → 872,24
int i, size;
 
/* Initialize magazine cache */
_slab_cache_create(&mag_cache,
"slab_magazine",
sizeof(slab_magazine_t)+SLAB_MAG_SIZE*sizeof(void*),
sizeof(uintptr_t),
NULL, NULL,
SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE);
_slab_cache_create(&mag_cache, "slab_magazine",
sizeof(slab_magazine_t) + SLAB_MAG_SIZE * sizeof(void*),
sizeof(uintptr_t), NULL, NULL, SLAB_CACHE_NOMAGAZINE |
SLAB_CACHE_SLINSIDE);
/* Initialize slab_cache cache */
_slab_cache_create(&slab_cache_cache,
"slab_cache",
sizeof(slab_cache_cache),
sizeof(uintptr_t),
NULL, NULL,
SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE);
_slab_cache_create(&slab_cache_cache, "slab_cache",
sizeof(slab_cache_cache), sizeof(uintptr_t), NULL, NULL,
SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE);
/* Initialize external slab cache */
slab_extern_cache = slab_cache_create("slab_extern",
sizeof(slab_t),
0, NULL, NULL,
SLAB_CACHE_SLINSIDE | SLAB_CACHE_MAGDEFERRED);
slab_extern_cache = slab_cache_create("slab_extern", sizeof(slab_t), 0,
NULL, NULL, SLAB_CACHE_SLINSIDE | SLAB_CACHE_MAGDEFERRED);
 
/* Initialize structures for malloc */
for (i=0, size=(1<<SLAB_MIN_MALLOC_W);
i < (SLAB_MAX_MALLOC_W-SLAB_MIN_MALLOC_W+1);
i++, size <<= 1) {
malloc_caches[i] = slab_cache_create(malloc_names[i],
size, 0,
NULL,NULL, SLAB_CACHE_MAGDEFERRED);
for (i = 0, size = (1 << SLAB_MIN_MALLOC_W);
i < (SLAB_MAX_MALLOC_W - SLAB_MIN_MALLOC_W + 1);
i++, size <<= 1) {
malloc_caches[i] = slab_cache_create(malloc_names[i], size, 0,
NULL, NULL, SLAB_CACHE_MAGDEFERRED);
}
#ifdef CONFIG_DEBUG
_slab_initialized = 1;
874,9 → 914,11
 
spinlock_lock(&slab_cache_lock);
for (cur=slab_cache_list.next; cur != &slab_cache_list;cur=cur->next){
for (cur = slab_cache_list.next; cur != &slab_cache_list;
cur = cur->next){
s = list_get_instance(cur, slab_cache_t, link);
if ((s->flags & SLAB_CACHE_MAGDEFERRED) != SLAB_CACHE_MAGDEFERRED)
if ((s->flags & SLAB_CACHE_MAGDEFERRED) !=
SLAB_CACHE_MAGDEFERRED)
continue;
make_magcache(s);
s->flags &= ~SLAB_CACHE_MAGDEFERRED;
887,7 → 929,7
 
/**************************************/
/* kalloc/kfree functions */
void * malloc(unsigned int size, int flags)
void *malloc(unsigned int size, int flags)
{
ASSERT(_slab_initialized);
ASSERT(size && size <= (1 << SLAB_MAX_MALLOC_W));
900,7 → 942,7
return slab_alloc(malloc_caches[idx], flags);
}
 
void * realloc(void *ptr, unsigned int size, int flags)
void *realloc(void *ptr, unsigned int size, int flags)
{
ASSERT(_slab_initialized);
ASSERT(size <= (1 << SLAB_MAX_MALLOC_W));
/branches/dd/kernel/generic/src/mm/tlb.c
173,7 → 173,7
tlb_invalidate_pages(asid, page, count);
break;
default:
panic("unknown type (%d)\n", type);
panic("Unknown type (%d).", type);
break;
}
if (type == TLB_INVL_ALL)
/branches/dd/kernel/generic/src/mm/backend_anon.c
78,7 → 78,6
int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access)
{
uintptr_t frame;
bool dirty = false;
 
if (!as_area_check_access(area, access))
return AS_PF_FAULT;
106,7 → 105,7
*/
for (i = 0; i < leaf->keys; i++) {
if (leaf->key[i] ==
ALIGN_DOWN(addr, PAGE_SIZE)) {
ALIGN_DOWN(addr, PAGE_SIZE) - area->base) {
allocate = false;
break;
}
113,8 → 112,7
}
if (allocate) {
frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
memsetb(PA2KA(frame), FRAME_SIZE, 0);
dirty = true;
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
/*
* Insert the address of the newly allocated
144,8 → 142,7
* the different causes
*/
frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
memsetb(PA2KA(frame), FRAME_SIZE, 0);
dirty = true;
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
}
/*
155,7 → 152,7
*/
page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
panic("Could not insert used space.\n");
panic("Cannot insert used space.");
return AS_PF_OK;
}
/branches/dd/kernel/generic/src/mm/as.c
82,7 → 82,6
#include <arch/mm/cache.h>
#endif /* CONFIG_VIRT_IDX_DCACHE */
 
#ifndef __OBJC__
/**
* Each architecture decides what functions will be used to carry out
* address space operations such as creating or locking page tables.
93,7 → 92,6
* Slab for as_t objects.
*/
static slab_cache_t *as_slab;
#endif
 
/**
* This lock serializes access to the ASID subsystem.
113,13 → 111,11
/** Kernel address space. */
as_t *AS_KERNEL = NULL;
 
static int area_flags_to_page_flags(int aflags);
static as_area_t *find_area_and_lock(as_t *as, uintptr_t va);
static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
as_area_t *avoid_area);
static void sh_info_remove_reference(share_info_t *sh_info);
static int area_flags_to_page_flags(int);
static as_area_t *find_area_and_lock(as_t *, uintptr_t);
static bool check_area_conflicts(as_t *, uintptr_t, size_t, as_area_t *);
static void sh_info_remove_reference(share_info_t *);
 
#ifndef __OBJC__
static int as_constructor(void *obj, int flags)
{
as_t *as = (as_t *) obj;
126,7 → 122,7
int rc;
 
link_initialize(&as->inactive_as_with_asid_link);
mutex_initialize(&as->lock);
mutex_initialize(&as->lock, MUTEX_PASSIVE);
rc = as_constructor_arch(as, flags);
139,7 → 135,6
 
return as_destructor_arch(as);
}
#endif
 
/** Initialize address space subsystem. */
void as_init(void)
146,33 → 141,29
{
as_arch_init();
 
#ifndef __OBJC__
as_slab = slab_cache_create("as_slab", sizeof(as_t), 0,
as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
#endif
AS_KERNEL = as_create(FLAG_AS_KERNEL);
if (!AS_KERNEL)
panic("can't create kernel address space\n");
panic("Cannot create kernel address space.");
/* Make sure the kernel address space
* reference count never drops to zero.
*/
atomic_set(&AS_KERNEL->refcount, 1);
}
 
/** Create address space.
*
* @param flags Flags that influence way in wich the address space is created.
* @param flags Flags that influence the way in wich the address space
* is created.
*/
as_t *as_create(int flags)
{
as_t *as;
 
#ifdef __OBJC__
as = [as_t new];
link_initialize(&as->inactive_as_with_asid_link);
mutex_initialize(&as->lock);
(void) as_constructor_arch(as, flags);
#else
as = (as_t *) slab_alloc(as_slab, 0);
#endif
(void) as_create_arch(as, 0);
btree_create(&as->as_area_btree);
189,7 → 180,7
#else
page_table_create(flags);
#endif
 
return as;
}
 
199,6 → 190,8
* zero), the address space can be destroyed.
*
* We know that we don't hold any spinlock.
*
* @param as Address space to be destroyed.
*/
void as_destroy(as_t *as)
{
263,11 → 256,7
 
interrupts_restore(ipl);
 
#ifdef __OBJC__
[as free];
#else
slab_free(as_slab, as);
#endif
}
 
/** Create address space area of common attributes.
274,19 → 263,19
*
* The created address space area is added to the target address space.
*
* @param as Target address space.
* @param flags Flags of the area memory.
* @param size Size of area.
* @param base Base address of area.
* @param attrs Attributes of the area.
* @param backend Address space area backend. NULL if no backend is used.
* @param backend_data NULL or a pointer to an array holding two void *.
* @param as Target address space.
* @param flags Flags of the area memory.
* @param size Size of area.
* @param base Base address of area.
* @param attrs Attributes of the area.
* @param backend Address space area backend. NULL if no backend is used.
* @param backend_data NULL or a pointer to an array holding two void *.
*
* @return Address space area on success or NULL on failure.
* @return Address space area on success or NULL on failure.
*/
as_area_t *
as_area_create(as_t *as, int flags, size_t size, uintptr_t base, int attrs,
mem_backend_t *backend, mem_backend_data_t *backend_data)
mem_backend_t *backend, mem_backend_data_t *backend_data)
{
ipl_t ipl;
as_area_t *a;
312,7 → 301,7
a = (as_area_t *) malloc(sizeof(as_area_t), 0);
 
mutex_initialize(&a->lock);
mutex_initialize(&a->lock, MUTEX_PASSIVE);
a->as = as;
a->flags = flags;
324,8 → 313,7
if (backend_data)
a->backend_data = *backend_data;
else
memsetb((uintptr_t) &a->backend_data, sizeof(a->backend_data),
0);
memsetb(&a->backend_data, sizeof(a->backend_data), 0);
 
btree_create(&a->used_space);
339,13 → 327,14
 
/** Find address space area and change it.
*
* @param as Address space.
* @param address Virtual address belonging to the area to be changed. Must be
* page-aligned.
* @param size New size of the virtual memory block starting at address.
* @param flags Flags influencing the remap operation. Currently unused.
* @param as Address space.
* @param address Virtual address belonging to the area to be changed.
* Must be page-aligned.
* @param size New size of the virtual memory block starting at
* address.
* @param flags Flags influencing the remap operation. Currently unused.
*
* @return Zero on success or a value from @ref errno.h otherwise.
* @return Zero on success or a value from @ref errno.h otherwise.
*/
int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags)
{
400,7 → 389,7
if (pages < area->pages) {
bool cond;
uintptr_t start_free = area->base + pages*PAGE_SIZE;
uintptr_t start_free = area->base + pages * PAGE_SIZE;
 
/*
* Shrinking the area.
410,7 → 399,7
/*
* Start TLB shootdown sequence.
*/
tlb_shootdown_start(TLB_INVL_PAGES, AS->asid, area->base +
tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base +
pages * PAGE_SIZE, area->pages - pages);
 
/*
455,8 → 444,8
i = (start_free - b) >> PAGE_WIDTH;
if (!used_space_remove(area, start_free,
c - i))
panic("Could not remove used "
"space.\n");
panic("Cannot remove used "
"space.");
} else {
/*
* The interval of used space can be
463,8 → 452,8
* completely removed.
*/
if (!used_space_remove(area, b, c))
panic("Could not remove used "
"space.\n");
panic("Cannot remove used "
"space.");
}
for (; i < c; i++) {
526,10 → 515,10
 
/** Destroy address space area.
*
* @param as Address space.
* @param address Address withing the area to be deleted.
* @param as Address space.
* @param address Address within the area to be deleted.
*
* @return Zero on success or a value from @ref errno.h on failure.
* @return Zero on success or a value from @ref errno.h on failure.
*/
int as_area_destroy(as_t *as, uintptr_t address)
{
626,18 → 615,19
* sh_info of the source area. The process of duplicating the
* mapping is done through the backend share function.
*
* @param src_as Pointer to source address space.
* @param src_base Base address of the source address space area.
* @param acc_size Expected size of the source area.
* @param dst_as Pointer to destination address space.
* @param dst_base Target base address.
* @param src_as Pointer to source address space.
* @param src_base Base address of the source address space area.
* @param acc_size Expected size of the source area.
* @param dst_as Pointer to destination address space.
* @param dst_base Target base address.
* @param dst_flags_mask Destination address space area flags mask.
*
* @return Zero on success or ENOENT if there is no such task or if there is no
* such address space area, EPERM if there was a problem in accepting the area
* or ENOMEM if there was a problem in allocating destination address space
* area. ENOTSUP is returned if the address space area backend does not support
* sharing.
* @return Zero on success or ENOENT if there is no such task or if
* there is no such address space area, EPERM if there was
* a problem in accepting the area or ENOMEM if there was a
* problem in allocating destination address space area.
* ENOTSUP is returned if the address space area backend
* does not support sharing.
*/
int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
as_t *dst_as, uintptr_t dst_base, int dst_flags_mask)
698,7 → 688,7
sh_info = src_area->sh_info;
if (!sh_info) {
sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0);
mutex_initialize(&sh_info->lock);
mutex_initialize(&sh_info->lock, MUTEX_PASSIVE);
sh_info->refcount = 2;
btree_create(&sh_info->pagemap);
src_area->sh_info = sh_info;
756,10 → 746,11
*
* The address space area must be locked prior to this call.
*
* @param area Address space area.
* @param access Access mode.
* @param area Address space area.
* @param access Access mode.
*
* @return False if access violates area's permissions, true otherwise.
* @return False if access violates area's permissions, true
* otherwise.
*/
bool as_area_check_access(as_area_t *area, pf_access_t access)
{
775,21 → 766,183
return true;
}
 
/** Change adress space area flags.
*
* The idea is to have the same data, but with a different access mode.
* This is needed e.g. for writing code into memory and then executing it.
* In order for this to work properly, this may copy the data
* into private anonymous memory (unless it's already there).
*
* @param as Address space.
* @param flags Flags of the area memory.
* @param address Address within the area to be changed.
*
* @return Zero on success or a value from @ref errno.h on failure.
*
*/
int as_area_change_flags(as_t *as, int flags, uintptr_t address)
{
as_area_t *area;
uintptr_t base;
link_t *cur;
ipl_t ipl;
int page_flags;
uintptr_t *old_frame;
index_t frame_idx;
count_t used_pages;
/* Flags for the new memory mapping */
page_flags = area_flags_to_page_flags(flags);
 
ipl = interrupts_disable();
mutex_lock(&as->lock);
 
area = find_area_and_lock(as, address);
if (!area) {
mutex_unlock(&as->lock);
interrupts_restore(ipl);
return ENOENT;
}
 
if ((area->sh_info) || (area->backend != &anon_backend)) {
/* Copying shared areas not supported yet */
/* Copying non-anonymous memory not supported yet */
mutex_unlock(&area->lock);
mutex_unlock(&as->lock);
interrupts_restore(ipl);
return ENOTSUP;
}
 
base = area->base;
 
/*
* Compute total number of used pages in the used_space B+tree
*/
used_pages = 0;
 
for (cur = area->used_space.leaf_head.next;
cur != &area->used_space.leaf_head; cur = cur->next) {
btree_node_t *node;
unsigned int i;
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
used_pages += (count_t) node->value[i];
}
}
 
/* An array for storing frame numbers */
old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
 
/*
* Start TLB shootdown sequence.
*/
tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
 
/*
* Remove used pages from page tables and remember their frame
* numbers.
*/
frame_idx = 0;
 
for (cur = area->used_space.leaf_head.next;
cur != &area->used_space.leaf_head; cur = cur->next) {
btree_node_t *node;
unsigned int i;
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t b = node->key[i];
count_t j;
pte_t *pte;
for (j = 0; j < (count_t) node->value[i]; j++) {
page_table_lock(as, false);
pte = page_mapping_find(as, b + j * PAGE_SIZE);
ASSERT(pte && PTE_VALID(pte) &&
PTE_PRESENT(pte));
old_frame[frame_idx++] = PTE_GET_FRAME(pte);
 
/* Remove old mapping */
page_mapping_remove(as, b + j * PAGE_SIZE);
page_table_unlock(as, false);
}
}
}
 
/*
* Finish TLB shootdown sequence.
*/
 
tlb_invalidate_pages(as->asid, area->base, area->pages);
/*
* Invalidate potential software translation caches (e.g. TSB on
* sparc64).
*/
as_invalidate_translation_cache(as, area->base, area->pages);
tlb_shootdown_finalize();
 
/*
* Set the new flags.
*/
area->flags = flags;
 
/*
* Map pages back in with new flags. This step is kept separate
* so that the memory area could not be accesed with both the old and
* the new flags at once.
*/
frame_idx = 0;
 
for (cur = area->used_space.leaf_head.next;
cur != &area->used_space.leaf_head; cur = cur->next) {
btree_node_t *node;
unsigned int i;
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t b = node->key[i];
count_t j;
for (j = 0; j < (count_t) node->value[i]; j++) {
page_table_lock(as, false);
 
/* Insert the new mapping */
page_mapping_insert(as, b + j * PAGE_SIZE,
old_frame[frame_idx++], page_flags);
 
page_table_unlock(as, false);
}
}
}
 
free(old_frame);
 
mutex_unlock(&area->lock);
mutex_unlock(&as->lock);
interrupts_restore(ipl);
 
return 0;
}
 
 
/** Handle page fault within the current address space.
*
* This is the high-level page fault handler. It decides
* whether the page fault can be resolved by any backend
* and if so, it invokes the backend to resolve the page
* fault.
* This is the high-level page fault handler. It decides whether the page fault
* can be resolved by any backend and if so, it invokes the backend to resolve
* the page fault.
*
* Interrupts are assumed disabled.
*
* @param page Faulting page.
* @param access Access mode that caused the fault (i.e. read/write/exec).
* @param istate Pointer to interrupted state.
* @param page Faulting page.
* @param access Access mode that caused the page fault (i.e.
* read/write/exec).
* @param istate Pointer to the interrupted state.
*
* @return AS_PF_FAULT on page fault, AS_PF_OK on success or AS_PF_DEFER if the
* fault was caused by copy_to_uspace() or copy_from_uspace().
* @return AS_PF_FAULT on page fault, AS_PF_OK on success or
* AS_PF_DEFER if the fault was caused by copy_to_uspace()
* or copy_from_uspace().
*/
int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate)
{
835,9 → 988,8
page_table_lock(AS, false);
/*
* To avoid race condition between two page faults
* on the same address, we need to make sure
* the mapping has not been already inserted.
* To avoid race condition between two page faults on the same address,
* we need to make sure the mapping has not been already inserted.
*/
if ((pte = page_mapping_find(AS, page))) {
if (PTE_PRESENT(pte)) {
891,8 → 1043,8
*
* When this function is enetered, no spinlocks may be held.
*
* @param old Old address space or NULL.
* @param new New address space.
* @param old Old address space or NULL.
* @param new New address space.
*/
void as_switch(as_t *old_as, as_t *new_as)
{
963,9 → 1115,9
 
/** Convert address space area flags to page flags.
*
* @param aflags Flags of some address space area.
* @param aflags Flags of some address space area.
*
* @return Flags to be passed to page_mapping_insert().
* @return Flags to be passed to page_mapping_insert().
*/
int area_flags_to_page_flags(int aflags)
{
993,9 → 1145,9
* The address space area must be locked.
* Interrupts must be disabled.
*
* @param a Address space area.
* @param a Address space area.
*
* @return Flags to be used in page_mapping_insert().
* @return Flags to be used in page_mapping_insert().
*/
int as_area_get_flags(as_area_t *a)
{
1004,23 → 1156,20
 
/** Create page table.
*
* Depending on architecture, create either address space
* private or global page table.
* Depending on architecture, create either address space private or global page
* table.
*
* @param flags Flags saying whether the page table is for kernel address space.
* @param flags Flags saying whether the page table is for the kernel
* address space.
*
* @return First entry of the page table.
* @return First entry of the page table.
*/
pte_t *page_table_create(int flags)
{
#ifdef __OBJC__
return [as_t page_table_create: flags];
#else
ASSERT(as_operations);
ASSERT(as_operations->page_table_create);
return as_operations->page_table_create(flags);
#endif
}
 
/** Destroy page table.
1027,18 → 1176,14
*
* Destroy page table in architecture specific way.
*
* @param page_table Physical address of PTL0.
* @param page_table Physical address of PTL0.
*/
void page_table_destroy(pte_t *page_table)
{
#ifdef __OBJC__
return [as_t page_table_destroy: page_table];
#else
ASSERT(as_operations);
ASSERT(as_operations->page_table_destroy);
as_operations->page_table_destroy(page_table);
#endif
}
 
/** Lock page table.
1050,36 → 1195,28
* prior to this call. Address space can be locked prior to this
* call in which case the lock argument is false.
*
* @param as Address space.
* @param lock If false, do not attempt to lock as->lock.
* @param as Address space.
* @param lock If false, do not attempt to lock as->lock.
*/
void page_table_lock(as_t *as, bool lock)
{
#ifdef __OBJC__
[as page_table_lock: lock];
#else
ASSERT(as_operations);
ASSERT(as_operations->page_table_lock);
as_operations->page_table_lock(as, lock);
#endif
}
 
/** Unlock page table.
*
* @param as Address space.
* @param unlock If false, do not attempt to unlock as->lock.
* @param as Address space.
* @param unlock If false, do not attempt to unlock as->lock.
*/
void page_table_unlock(as_t *as, bool unlock)
{
#ifdef __OBJC__
[as page_table_unlock: unlock];
#else
ASSERT(as_operations);
ASSERT(as_operations->page_table_unlock);
as_operations->page_table_unlock(as, unlock);
#endif
}
 
 
1087,11 → 1224,11
*
* The address space must be locked and interrupts must be disabled.
*
* @param as Address space.
* @param va Virtual address.
* @param as Address space.
* @param va Virtual address.
*
* @return Locked address space area containing va on success or NULL on
* failure.
* @return Locked address space area containing va on success or
* NULL on failure.
*/
as_area_t *find_area_and_lock(as_t *as, uintptr_t va)
{
1143,15 → 1280,15
*
* The address space must be locked and interrupts must be disabled.
*
* @param as Address space.
* @param va Starting virtual address of the area being tested.
* @param size Size of the area being tested.
* @param avoid_area Do not touch this area.
* @param as Address space.
* @param va Starting virtual address of the area being tested.
* @param size Size of the area being tested.
* @param avoid_area Do not touch this area.
*
* @return True if there is no conflict, false otherwise.
* @return True if there is no conflict, false otherwise.
*/
bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
as_area_t *avoid_area)
bool
check_area_conflicts(as_t *as, uintptr_t va, size_t size, as_area_t *avoid_area)
{
as_area_t *a;
btree_node_t *leaf, *node;
1240,7 → 1377,7
 
ipl = interrupts_disable();
src_area = find_area_and_lock(AS, base);
if (src_area){
if (src_area) {
size = src_area->pages * PAGE_SIZE;
mutex_unlock(&src_area->lock);
} else {
1254,11 → 1391,11
*
* The address space area must be already locked.
*
* @param a Address space area.
* @param page First page to be marked.
* @param count Number of page to be marked.
* @param a Address space area.
* @param page First page to be marked.
* @param count Number of page to be marked.
*
* @return 0 on failure and 1 on success.
* @return Zero on failure and non-zero on success.
*/
int used_space_insert(as_area_t *a, uintptr_t page, count_t count)
{
1528,8 → 1665,8
}
}
 
panic("Inconsistency detected while adding %d pages of used space at "
"%p.\n", count, page);
panic("Inconsistency detected while adding %" PRIc " pages of used "
"space at %p.", count, page);
}
 
/** Mark portion of address space area as unused.
1536,11 → 1673,11
*
* The address space area must be already locked.
*
* @param a Address space area.
* @param page First page to be marked.
* @param count Number of page to be marked.
* @param a Address space area.
* @param page First page to be marked.
* @param count Number of page to be marked.
*
* @return 0 on failure and 1 on success.
* @return Zero on failure and non-zero on success.
*/
int used_space_remove(as_area_t *a, uintptr_t page, count_t count)
{
1707,8 → 1844,8
}
 
error:
panic("Inconsistency detected while removing %d pages of used space "
"from %p.\n", count, page);
panic("Inconsistency detected while removing %" PRIc " pages of used "
"space from %p.", count, page);
}
 
/** Remove reference to address space area share info.
1715,7 → 1852,7
*
* If the reference count drops to 0, the sh_info is deallocated.
*
* @param sh_info Pointer to address space area share info.
* @param sh_info Pointer to address space area share info.
*/
void sh_info_remove_reference(share_info_t *sh_info)
{
1770,6 → 1907,12
return (unative_t) as_area_resize(AS, address, size, 0);
}
 
/** Wrapper for as_area_change_flags(). */
unative_t sys_as_area_change_flags(uintptr_t address, int flags)
{
return (unative_t) as_area_change_flags(AS, flags, address);
}
 
/** Wrapper for as_area_destroy(). */
unative_t sys_as_area_destroy(uintptr_t address)
{
1778,7 → 1921,7
 
/** Print out information about address space.
*
* @param as Address space.
* @param as Address space.
*/
void as_print(as_t *as)
{
1800,9 → 1943,9
as_area_t *area = node->value[i];
mutex_lock(&area->lock);
printf("as_area: %p, base=%p, pages=%d (%p - %p)\n",
area, area->base, area->pages, area->base,
area->base + area->pages*PAGE_SIZE);
printf("as_area: %p, base=%p, pages=%" PRIc
" (%p - %p)\n", area, area->base, area->pages,
area->base, area->base + FRAMES2SIZE(area->pages));
mutex_unlock(&area->lock);
}
}
/branches/dd/kernel/generic/src/mm/buddy.c
35,8 → 35,7
* @brief Buddy allocator framework.
*
* This file contains buddy system allocator framework.
* Specialized functions are needed for this abstract framework
* to be useful.
* Specialized functions are needed for this abstract framework to be useful.
*/
 
#include <mm/buddy.h>
44,29 → 43,29
#include <arch/types.h>
#include <debug.h>
#include <print.h>
#include <macros.h>
 
/** Return size needed for the buddy configuration data */
size_t buddy_conf_size(int max_order)
/** Return size needed for the buddy configuration data. */
size_t buddy_conf_size(size_t max_order)
{
return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t);
}
 
 
/** Create buddy system
/** Create buddy system.
*
* Allocate memory for and initialize new buddy system.
*
* @param b Preallocated buddy system control data.
* @param max_order The biggest allocable size will be 2^max_order.
* @param op Operations for new buddy system.
* @param data Pointer to be used by implementation.
* @param b Preallocated buddy system control data.
* @param max_order The biggest allocable size will be 2^max_order.
* @param op Operations for new buddy system.
* @param data Pointer to be used by implementation.
*
* @return New buddy system.
* @return New buddy system.
*/
void buddy_system_create(buddy_system_t *b,
uint8_t max_order,
buddy_system_operations_t *op,
void *data)
void
buddy_system_create(buddy_system_t *b, uint8_t max_order,
buddy_system_operations_t *op, void *data)
{
int i;
 
80,7 → 79,7
ASSERT(op->mark_busy);
 
/*
* Use memory after our own structure
* Use memory after our own structure.
*/
b->order = (link_t *) (&b[1]);
92,14 → 91,15
b->data = data;
}
 
/** Check if buddy system can allocate block
/** Check if buddy system can allocate block.
*
* @param b Buddy system pointer
* @param i Size of the block (2^i)
* @param b Buddy system pointer.
* @param i Size of the block (2^i).
*
* @return True if block can be allocated
* @return True if block can be allocated.
*/
bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i) {
bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i)
{
uint8_t k;
/*
106,12 → 106,13
* If requested block is greater then maximal block
* we know immediatly that we cannot satisfy the request.
*/
if (i > b->max_order) return false;
if (i > b->max_order)
return false;
 
/*
* Check if any bigger or equal order has free elements
*/
for (k=i; k <= b->max_order; k++) {
for (k = i; k <= b->max_order; k++) {
if (!list_empty(&b->order[k])) {
return true;
}
118,12 → 119,11
}
return false;
}
 
/** Allocate PARTICULAR block from buddy system
/** Allocate PARTICULAR block from buddy system.
*
* @ return Block of data or NULL if no such block was found
* @return Block of data or NULL if no such block was found.
*/
link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block)
{
134,7 → 134,7
ASSERT(left);
list_remove(left);
while (1) {
if (! b->op->get_order(b,left)) {
if (!b->op->get_order(b, left)) {
b->op->mark_busy(b, left);
return left;
}
142,8 → 142,8
order = b->op->get_order(b, left);
 
right = b->op->bisect(b, left);
b->op->set_order(b, left, order-1);
b->op->set_order(b, right, order-1);
b->op->set_order(b, left, order - 1);
b->op->set_order(b, right, order - 1);
 
tmp = b->op->find_block(b, block, BUDDY_SYSTEM_INNER_BLOCK);
 
160,10 → 160,10
 
/** Allocate block from buddy system.
*
* @param b Buddy system pointer.
* @param i Returned block will be 2^i big.
* @param b Buddy system pointer.
* @param i Returned block will be 2^i big.
*
* @return Block of data represented by link_t.
* @return Block of data represented by link_t.
*/
link_t *buddy_system_alloc(buddy_system_t *b, uint8_t i)
{
217,13 → 217,12
buddy_system_free(b, hlp);
return res;
}
 
/** Return block to buddy system.
*
* @param b Buddy system pointer.
* @param block Block to return.
* @param b Buddy system pointer.
* @param block Block to return.
*/
void buddy_system_free(buddy_system_t *b, link_t *block)
{
267,7 → 266,8
b->op->set_order(b, hlp, i + 1);
 
/*
* Recursively add the coalesced block to the list of order i + 1.
* Recursively add the coalesced block to the list of
* order i + 1.
*/
buddy_system_free(b, hlp);
return;
278,46 → 278,7
* Insert block into the list of order i.
*/
list_append(block, &b->order[i]);
 
}
 
/** Prints out structure of buddy system
*
* @param b Pointer to buddy system
* @param elem_size Element size
*/
void buddy_system_structure_print(buddy_system_t *b, size_t elem_size) {
index_t i;
count_t cnt, elem_count = 0, block_count = 0;
link_t * cur;
 
printf("Order\tBlocks\tSize \tBlock size\tElems per block\n");
printf("-----\t------\t--------\t----------\t---------------\n");
for (i=0;i <= b->max_order; i++) {
cnt = 0;
if (!list_empty(&b->order[i])) {
for (cur = b->order[i].next; cur != &b->order[i]; cur = cur->next)
cnt++;
}
printf("#%zd\t%5zd\t%7zdK\t%8zdK\t%6zd\t", i, cnt, (cnt * (1 << i) * elem_size) >> 10, ((1 << i) * elem_size) >> 10, 1 << i);
if (!list_empty(&b->order[i])) {
for (cur = b->order[i].next; cur != &b->order[i]; cur = cur->next) {
b->op->print_id(b, cur);
printf(" ");
}
}
printf("\n");
block_count += cnt;
elem_count += (1 << i) * cnt;
}
printf("-----\t------\t--------\t----------\t---------------\n");
printf("Buddy system contains %zd free elements (%zd blocks)\n" , elem_count, block_count);
 
}
 
/** @}
*/
/branches/dd/kernel/generic/src/mm/backend_phys.c
77,7 → 77,7
page_mapping_insert(AS, addr, base + (addr - area->base),
as_area_get_flags(area));
if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
panic("Could not insert used space.\n");
panic("Cannot insert used space.");
 
return AS_PF_OK;
}
/branches/dd/kernel/generic/src/mm/frame.c
1,6 → 1,7
/*
* Copyright (c) 2001-2005 Jakub Jermar
* Copyright (c) 2005 Sergey Bondari
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
33,7 → 34,7
 
/**
* @file
* @brief Physical frame allocator.
* @brief Physical frame allocator.
*
* This file contains the physical frame allocator and memory zone management.
* The frame allocator is built on top of the buddy allocator.
41,16 → 42,6
* @see buddy.c
*/
 
/*
* Locking order
*
* In order to access particular zone, the process must first lock
* the zones.lock, then lock the zone and then unlock the zones.lock.
* This insures, that we can fiddle with the zones in runtime without
* affecting the processes.
*
*/
 
#include <arch/types.h>
#include <mm/frame.h>
#include <mm/as.h>
57,7 → 48,8
#include <panic.h>
#include <debug.h>
#include <adt/list.h>
#include <synch/spinlock.h>
#include <synch/mutex.h>
#include <synch/condvar.h>
#include <arch/asm.h>
#include <arch.h>
#include <print.h>
67,43 → 59,17
#include <macros.h>
#include <config.h>
 
typedef struct {
count_t refcount; /**< tracking of shared frames */
uint8_t buddy_order; /**< buddy system block order */
link_t buddy_link; /**< link to the next free block inside one
order */
void *parent; /**< If allocated by slab, this points there */
} frame_t;
zones_t zones;
 
typedef struct {
SPINLOCK_DECLARE(lock); /**< this lock protects everything below */
pfn_t base; /**< frame_no of the first frame in the frames
array */
count_t count; /**< Size of zone */
 
frame_t *frames; /**< array of frame_t structures in this
zone */
count_t free_count; /**< number of free frame_t structures */
count_t busy_count; /**< number of busy frame_t structures */
buddy_system_t *buddy_system; /**< buddy system for the zone */
int flags;
} zone_t;
 
/*
* The zoneinfo.lock must be locked when accessing zoneinfo structure.
* Some of the attributes in zone_t structures are 'read-only'
* Synchronization primitives used to sleep when there is no memory
* available.
*/
mutex_t mem_avail_mtx;
condvar_t mem_avail_cv;
count_t mem_avail_req = 0; /**< Number of frames requested. */
count_t mem_avail_gen = 0; /**< Generation counter. */
 
typedef struct {
SPINLOCK_DECLARE(lock);
unsigned int count;
zone_t *info[ZONES_MAX];
} zones_t;
 
static zones_t zones;
 
 
/********************/
/* Helper functions */
/********************/
118,22 → 84,20
return (index_t) (frame - zone->frames) + zone->base;
}
 
static inline int frame_index_valid(zone_t *zone, index_t index)
static inline bool frame_index_valid(zone_t *zone, index_t index)
{
return (index < zone->count);
}
 
/** Compute pfn_t from frame_t pointer & zone pointer */
static index_t make_frame_index(zone_t *zone, frame_t *frame)
static inline index_t make_frame_index(zone_t *zone, frame_t *frame)
{
return (frame - zone->frames);
}
 
/** Initialize frame structure
/** Initialize frame structure.
*
* Initialize frame structure.
* @param frame Frame structure to be initialized.
*
* @param frame Frame structure to be initialized.
*/
static void frame_initialize(frame_t *frame)
{
141,142 → 105,145
frame->buddy_order = 0;
}
 
/**********************/
/* Zoneinfo functions */
/**********************/
/*******************/
/* Zones functions */
/*******************/
 
/**
* Insert-sort zone into zones list
/** Insert-sort zone into zones list.
*
* @param newzone New zone to be inserted into zone list
* @return zone number on success, -1 on error
* Assume interrupts are disabled and zones lock is
* locked.
*
* @param base Base frame of the newly inserted zone.
* @param count Number of frames of the newly inserted zone.
*
* @return Zone number on success, -1 on error.
*
*/
static int zones_add_zone(zone_t *newzone)
static count_t zones_insert_zone(pfn_t base, count_t count)
{
unsigned int i, j;
ipl_t ipl;
zone_t *z;
 
ipl = interrupts_disable();
spinlock_lock(&zones.lock);
/* Try to merge */
if (zones.count + 1 == ZONES_MAX) {
printf("Maximum zone count %u exceeded!\n", ZONES_MAX);
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return -1;
return (count_t) -1;
}
count_t i;
for (i = 0; i < zones.count; i++) {
/* Check for overflow */
z = zones.info[i];
if (overlaps(newzone->base, newzone->count, z->base, z->count)) {
/* Check for overlap */
if (overlaps(base, count,
zones.info[i].base, zones.info[i].count)) {
printf("Zones overlap!\n");
return -1;
return (count_t) -1;
}
if (newzone->base < z->base)
if (base < zones.info[i].base)
break;
}
/* Move other zones up */
for (j = i; j < zones.count; j++)
zones.info[j + 1] = zones.info[j];
count_t j;
for (j = zones.count; j > i; j--) {
zones.info[j] = zones.info[j - 1];
zones.info[j].buddy_system->data =
(void *) &zones.info[j - 1];
}
zones.info[i] = newzone;
zones.count++;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
 
return i;
}
 
/**
* Try to find a zone where can we find the frame
/** Get total available frames.
*
* Assume interrupts are disabled.
* Assume interrupts are disabled and zones lock is
* locked.
*
* @param frame Frame number contained in zone
* @param pzone If not null, it is used as zone hint. Zone index
* is filled into the variable on success.
* @return Pointer to locked zone containing frame
* @return Total number of available frames.
*
*/
static zone_t * find_zone_and_lock(pfn_t frame, unsigned int *pzone)
#ifdef CONFIG_DEBUG
static count_t total_frames_free(void)
{
unsigned int i;
unsigned int hint = pzone ? *pzone : 0;
zone_t *z;
count_t total = 0;
count_t i;
for (i = 0; i < zones.count; i++)
total += zones.info[i].free_count;
spinlock_lock(&zones.lock);
return total;
}
#endif
 
/** Find a zone with a given frames.
*
* Assume interrupts are disabled and zones lock is
* locked.
*
* @param frame Frame number contained in zone.
* @param count Number of frames to look for.
* @param hint Used as zone hint.
*
* @return Zone index or -1 if not found.
*
*/
count_t find_zone(pfn_t frame, count_t count, count_t hint)
{
if (hint >= zones.count)
hint = 0;
i = hint;
count_t i = hint;
do {
z = zones.info[i];
spinlock_lock(&z->lock);
if (z->base <= frame && z->base + z->count > frame) {
/* Unlock the global lock */
spinlock_unlock(&zones.lock);
if (pzone)
*pzone = i;
return z;
}
spinlock_unlock(&z->lock);
 
if ((zones.info[i].base <= frame)
&& (zones.info[i].base + zones.info[i].count >= frame + count))
return i;
i++;
if (i >= zones.count)
i = 0;
} while(i != hint);
 
spinlock_unlock(&zones.lock);
return NULL;
} while (i != hint);
return (count_t) -1;
}
 
/** @return True if zone can allocate specified order */
static int zone_can_alloc(zone_t *z, uint8_t order)
static bool zone_can_alloc(zone_t *zone, uint8_t order)
{
return buddy_system_can_alloc(z->buddy_system, order);
return (zone_flags_available(zone->flags)
&& buddy_system_can_alloc(zone->buddy_system, order));
}
 
/** Find and lock zone that can allocate order frames.
/** Find a zone that can allocate order frames.
*
* Assume interrupts are disabled.
* Assume interrupts are disabled and zones lock is
* locked.
*
* @param order Size (2^order) of free space we are trying to find
* @param pzone Pointer to preferred zone or NULL, on return contains zone
* number
* @param order Size (2^order) of free space we are trying to find.
* @param flags Required flags of the target zone.
* @param hind Preferred zone.
*
*/
static zone_t * find_free_zone_and_lock(uint8_t order, unsigned int *pzone)
static count_t find_free_zone(uint8_t order, zone_flags_t flags, count_t hint)
{
unsigned int i;
zone_t *z;
unsigned int hint = pzone ? *pzone : 0;
spinlock_lock(&zones.lock);
if (hint >= zones.count)
hint = 0;
i = hint;
count_t i = hint;
do {
z = zones.info[i];
/*
* Check whether the zone meets the search criteria.
*/
if ((zones.info[i].flags & flags) == flags) {
/*
* Check if the zone has 2^order frames area available.
*/
if (zone_can_alloc(&zones.info[i], order))
return i;
}
spinlock_lock(&z->lock);
 
/* Check if the zone has 2^order frames area available */
if (zone_can_alloc(z, order)) {
spinlock_unlock(&zones.lock);
if (pzone)
*pzone = i;
return z;
}
spinlock_unlock(&z->lock);
if (++i >= zones.count)
i++;
if (i >= zones.count)
i = 0;
} while(i != hint);
spinlock_unlock(&zones.lock);
return NULL;
} while (i != hint);
return (count_t) -1;
}
 
/**************************/
283,167 → 250,146
/* Buddy system functions */
/**************************/
 
/** Buddy system find_block implementation
/** Buddy system find_block implementation.
*
* Find block that is parent of current list.
* That means go to lower addresses, until such block is found
*
* @param order - Order of parent must be different then this parameter!!
* @param order Order of parent must be different then this
* parameter!!
*
*/
static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child,
static link_t *zone_buddy_find_block(buddy_system_t *buddy, link_t *child,
uint8_t order)
{
frame_t *frame;
zone_t *zone;
index_t index;
frame_t *frame = list_get_instance(child, frame_t, buddy_link);
zone_t *zone = (zone_t *) buddy->data;
frame = list_get_instance(child, frame_t, buddy_link);
zone = (zone_t *) b->data;
 
index = frame_index(zone, frame);
index_t index = frame_index(zone, frame);
do {
if (zone->frames[index].buddy_order != order) {
if (zone->frames[index].buddy_order != order)
return &zone->frames[index].buddy_link;
}
} while(index-- > 0);
} while (index-- > 0);
return NULL;
}
 
static void zone_buddy_print_id(buddy_system_t *b, link_t *block)
{
frame_t *frame;
zone_t *zone;
index_t index;
 
frame = list_get_instance(block, frame_t, buddy_link);
zone = (zone_t *) b->data;
index = frame_index(zone, frame);
printf("%zd", index);
}
 
/** Buddy system find_buddy implementation
/** Buddy system find_buddy implementation.
*
* @param b Buddy system.
* @param block Block for which buddy should be found
* @param buddy Buddy system.
* @param block Block for which buddy should be found.
*
* @return Buddy for given block if found
* @return Buddy for given block if found.
*
*/
static link_t *zone_buddy_find_buddy(buddy_system_t *b, link_t *block)
static link_t *zone_buddy_find_buddy(buddy_system_t *buddy, link_t *block)
{
frame_t *frame;
zone_t *zone;
index_t index;
bool is_left, is_right;
 
frame = list_get_instance(block, frame_t, buddy_link);
zone = (zone_t *) b->data;
frame_t *frame = list_get_instance(block, frame_t, buddy_link);
zone_t *zone = (zone_t *) buddy->data;
ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame),
frame->buddy_order));
is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame);
 
ASSERT(is_left ^ is_right);
bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
index_t index;
if (is_left) {
index = (frame_index(zone, frame)) + (1 << frame->buddy_order);
} else { /* if (is_right) */
index = (frame_index(zone, frame)) - (1 << frame->buddy_order);
index = (frame_index(zone, frame)) +
(1 << frame->buddy_order);
} else { /* is_right */
index = (frame_index(zone, frame)) -
(1 << frame->buddy_order);
}
if (frame_index_valid(zone, index)) {
if (zone->frames[index].buddy_order == frame->buddy_order &&
zone->frames[index].refcount == 0) {
if ((zone->frames[index].buddy_order == frame->buddy_order) &&
(zone->frames[index].refcount == 0)) {
return &zone->frames[index].buddy_link;
}
}
 
return NULL;
return NULL;
}
 
/** Buddy system bisect implementation
/** Buddy system bisect implementation.
*
* @param b Buddy system.
* @param block Block to bisect
* @param buddy Buddy system.
* @param block Block to bisect.
*
* @return right block
* @return Right block.
*
*/
static link_t * zone_buddy_bisect(buddy_system_t *b, link_t *block) {
frame_t *frame_l, *frame_r;
 
frame_l = list_get_instance(block, frame_t, buddy_link);
frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
static link_t *zone_buddy_bisect(buddy_system_t *buddy, link_t *block)
{
frame_t *frame_l = list_get_instance(block, frame_t, buddy_link);
frame_t *frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
return &frame_r->buddy_link;
}
 
/** Buddy system coalesce implementation
/** Buddy system coalesce implementation.
*
* @param b Buddy system.
* @param block_1 First block
* @param block_2 First block's buddy
* @param buddy Buddy system.
* @param block_1 First block.
* @param block_2 First block's buddy.
*
* @return Coalesced block (actually block that represents lower address)
* @return Coalesced block (actually block that represents lower
* address).
*
*/
static link_t *zone_buddy_coalesce(buddy_system_t *b, link_t *block_1,
link_t *block_2)
static link_t *zone_buddy_coalesce(buddy_system_t *buddy, link_t *block_1,
link_t *block_2)
{
frame_t *frame1, *frame2;
frame_t *frame1 = list_get_instance(block_1, frame_t, buddy_link);
frame_t *frame2 = list_get_instance(block_2, frame_t, buddy_link);
frame1 = list_get_instance(block_1, frame_t, buddy_link);
frame2 = list_get_instance(block_2, frame_t, buddy_link);
return frame1 < frame2 ? block_1 : block_2;
return ((frame1 < frame2) ? block_1 : block_2);
}
 
/** Buddy system set_order implementation
/** Buddy system set_order implementation.
*
* @param b Buddy system.
* @param block Buddy system block
* @param order Order to set
* @param buddy Buddy system.
* @param block Buddy system block.
* @param order Order to set.
*
*/
static void zone_buddy_set_order(buddy_system_t *b, link_t *block,
uint8_t order) {
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->buddy_order = order;
static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block,
uint8_t order)
{
list_get_instance(block, frame_t, buddy_link)->buddy_order = order;
}
 
/** Buddy system get_order implementation
/** Buddy system get_order implementation.
*
* @param b Buddy system.
* @param block Buddy system block
* @param buddy Buddy system.
* @param block Buddy system block.
*
* @return Order of block
* @return Order of block.
*
*/
static uint8_t zone_buddy_get_order(buddy_system_t *b, link_t *block) {
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
return frame->buddy_order;
static uint8_t zone_buddy_get_order(buddy_system_t *buddy, link_t *block)
{
return list_get_instance(block, frame_t, buddy_link)->buddy_order;
}
 
/** Buddy system mark_busy implementation
/** Buddy system mark_busy implementation.
*
* @param b Buddy system
* @param block Buddy system block
* @param buddy Buddy system.
* @param block Buddy system block.
*
*/
static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) {
frame_t * frame;
 
frame = list_get_instance(block, frame_t, buddy_link);
frame->refcount = 1;
static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t * block)
{
list_get_instance(block, frame_t, buddy_link)->refcount = 1;
}
 
/** Buddy system mark_available implementation
/** Buddy system mark_available implementation.
*
* @param b Buddy system
* @param block Buddy system block
*
* @param buddy Buddy system.
* @param block Buddy system block.
*/
static void zone_buddy_mark_available(buddy_system_t *b, link_t *block) {
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->refcount = 0;
static void zone_buddy_mark_available(buddy_system_t *buddy, link_t *block)
{
list_get_instance(block, frame_t, buddy_link)->refcount = 0;
}
 
static buddy_system_operations_t zone_buddy_system_operations = {
454,8 → 400,7
.get_order = zone_buddy_get_order,
.mark_busy = zone_buddy_mark_busy,
.mark_available = zone_buddy_mark_available,
.find_block = zone_buddy_find_block,
.print_id = zone_buddy_print_id
.find_block = zone_buddy_find_block
};
 
/******************/
462,62 → 407,59
/* Zone functions */
/******************/
 
/** Allocate frame in particular zone
/** Allocate frame in particular zone.
*
* Assume zone is locked
* Assume zone is locked and is available for allocation.
* Panics if allocation is impossible.
*
* @param zone Zone to allocate from.
* @param order Allocate exactly 2^order frames.
*
* @return Frame index in zone
* @return Frame index in zone.
*
*/
static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order)
{
pfn_t v;
link_t *tmp;
frame_t *frame;
 
ASSERT(zone_flags_available(zone->flags));
/* Allocate frames from zone buddy system */
tmp = buddy_system_alloc(zone->buddy_system, order);
link_t *link = buddy_system_alloc(zone->buddy_system, order);
ASSERT(tmp);
ASSERT(link);
/* Update zone information. */
zone->free_count -= (1 << order);
zone->busy_count += (1 << order);
 
/* Frame will be actually a first frame of the block. */
frame = list_get_instance(tmp, frame_t, buddy_link);
frame_t *frame = list_get_instance(link, frame_t, buddy_link);
/* get frame address */
v = make_frame_index(zone, frame);
return v;
/* Get frame address */
return make_frame_index(zone, frame);
}
 
/** Free frame from zone
/** Free frame from zone.
*
* Assume zone is locked
* Assume zone is locked and is available for deallocation.
*
* @param zone Pointer to zone from which the frame is to be freed
* @param frame_idx Frame index relative to zone
* @param zone Pointer to zone from which the frame is to be freed.
* @param frame_idx Frame index relative to zone.
*
*/
static void zone_frame_free(zone_t *zone, index_t frame_idx)
{
frame_t *frame;
uint8_t order;
 
frame = &zone->frames[frame_idx];
ASSERT(zone_flags_available(zone->flags));
/* remember frame order */
order = frame->buddy_order;
 
frame_t *frame = &zone->frames[frame_idx];
/* Remember frame order */
uint8_t order = frame->buddy_order;
ASSERT(frame->refcount);
 
if (!--frame->refcount) {
buddy_system_free(zone->buddy_system, &frame->buddy_link);
/* Update zone information. */
zone->free_count += (1 << order);
zone->busy_count -= (1 << order);
524,521 → 466,643
}
}
 
/** Return frame from zone */
static frame_t * zone_get_frame(zone_t *zone, index_t frame_idx)
/** Return frame from zone. */
static frame_t *zone_get_frame(zone_t *zone, index_t frame_idx)
{
ASSERT(frame_idx < zone->count);
return &zone->frames[frame_idx];
}
 
/** Mark frame in zone unavailable to allocation */
/** Mark frame in zone unavailable to allocation. */
static void zone_mark_unavailable(zone_t *zone, index_t frame_idx)
{
frame_t *frame;
link_t *link;
 
frame = zone_get_frame(zone, frame_idx);
ASSERT(zone_flags_available(zone->flags));
frame_t *frame = zone_get_frame(zone, frame_idx);
if (frame->refcount)
return;
link_t *link __attribute__ ((unused));
link = buddy_system_alloc_block(zone->buddy_system,
&frame->buddy_link);
ASSERT(link);
zone->free_count--;
}
 
/**
* Join 2 zones
/** Merge two zones.
*
* Expect zone_t *z to point to space at least zone_conf_size large
* Expect buddy to point to space at least zone_conf_size large.
* Assume z1 & z2 are locked and compatible and zones lock is
* locked.
*
* Assume z1 & z2 are locked
* @param z1 First zone to merge.
* @param z2 Second zone to merge.
* @param old_z1 Original date of the first zone.
* @param buddy Merged zone buddy.
*
* @param z Target zone structure pointer
* @param z1 Zone to merge
* @param z2 Zone to merge
*/
static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2)
static void zone_merge_internal(count_t z1, count_t z2, zone_t *old_z1, buddy_system_t *buddy)
{
uint8_t max_order;
unsigned int i;
int z2idx;
pfn_t frame_idx;
frame_t *frame;
 
ASSERT(!overlaps(z1->base, z1->count, z2->base, z2->count));
ASSERT(z1->base < z2->base);
 
spinlock_initialize(&z->lock, "zone_lock");
z->base = z1->base;
z->count = z2->base + z2->count - z1->base;
z->flags = z1->flags & z2->flags;
 
z->free_count = z1->free_count + z2->free_count;
z->busy_count = z1->busy_count + z2->busy_count;
ASSERT(zone_flags_available(zones.info[z1].flags));
ASSERT(zone_flags_available(zones.info[z2].flags));
ASSERT(zones.info[z1].flags == zones.info[z2].flags);
ASSERT(zones.info[z1].base < zones.info[z2].base);
ASSERT(!overlaps(zones.info[z1].base, zones.info[z1].count,
zones.info[z2].base, zones.info[z2].count));
max_order = fnzb(z->count);
 
z->buddy_system = (buddy_system_t *) &z[1];
buddy_system_create(z->buddy_system, max_order,
&zone_buddy_system_operations, (void *) z);
 
z->frames = (frame_t *)((uint8_t *) z->buddy_system +
buddy_conf_size(max_order));
for (i = 0; i < z->count; i++) {
/* This marks all frames busy */
frame_initialize(&z->frames[i]);
}
/* Difference between zone bases */
pfn_t base_diff = zones.info[z2].base - zones.info[z1].base;
zones.info[z1].count = base_diff + zones.info[z2].count;
zones.info[z1].free_count += zones.info[z2].free_count;
zones.info[z1].busy_count += zones.info[z2].busy_count;
zones.info[z1].buddy_system = buddy;
uint8_t order = fnzb(zones.info[z1].count);
buddy_system_create(zones.info[z1].buddy_system, order,
&zone_buddy_system_operations, (void *) &zones.info[z1]);
zones.info[z1].frames =
(frame_t *) ((uint8_t *) zones.info[z1].buddy_system
+ buddy_conf_size(order));
/* This marks all frames busy */
count_t i;
for (i = 0; i < zones.info[z1].count; i++)
frame_initialize(&zones.info[z1].frames[i]);
/* Copy frames from both zones to preserve full frame orders,
* parents etc. Set all free frames with refcount=0 to 1, because
* we add all free frames to buddy allocator later again, clear
* order to 0. Don't set busy frames with refcount=0, as they
* parents etc. Set all free frames with refcount = 0 to 1, because
* we add all free frames to buddy allocator later again, clearing
* order to 0. Don't set busy frames with refcount = 0, as they
* will not be reallocated during merge and it would make later
* problems with allocation/free.
*/
for (i = 0; i < z1->count; i++)
z->frames[i] = z1->frames[i];
for (i = 0; i < z2->count; i++) {
z2idx = i + (z2->base - z1->base);
z->frames[z2idx] = z2->frames[i];
}
for (i = 0; i < old_z1->count; i++)
zones.info[z1].frames[i] = old_z1->frames[i];
for (i = 0; i < zones.info[z2].count; i++)
zones.info[z1].frames[base_diff + i]
= zones.info[z2].frames[i];
i = 0;
while (i < z->count) {
if (z->frames[i].refcount) {
/* skip busy frames */
i += 1 << z->frames[i].buddy_order;
} else { /* Free frames, set refcount=1 */
/* All free frames have refcount=0, we need not
* to check the order */
z->frames[i].refcount = 1;
z->frames[i].buddy_order = 0;
while (i < zones.info[z1].count) {
if (zones.info[z1].frames[i].refcount) {
/* Skip busy frames */
i += 1 << zones.info[z1].frames[i].buddy_order;
} else {
/* Free frames, set refcount = 1
* (all free frames have refcount == 0, we need not
* to check the order)
*/
zones.info[z1].frames[i].refcount = 1;
zones.info[z1].frames[i].buddy_order = 0;
i++;
}
}
/* Add free blocks from the 2 original zones */
while (zone_can_alloc(z1, 0)) {
frame_idx = zone_frame_alloc(z1, 0);
frame = &z->frames[frame_idx];
/* Add free blocks from the original zone z1 */
while (zone_can_alloc(old_z1, 0)) {
/* Allocate from the original zone */
pfn_t frame_idx = zone_frame_alloc(old_z1, 0);
/* Free the frame from the merged zone */
frame_t *frame = &zones.info[z1].frames[frame_idx];
frame->refcount = 0;
buddy_system_free(z->buddy_system, &frame->buddy_link);
buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
}
while (zone_can_alloc(z2, 0)) {
frame_idx = zone_frame_alloc(z2, 0);
frame = &z->frames[frame_idx + (z2->base - z1->base)];
/* Add free blocks from the original zone z2 */
while (zone_can_alloc(&zones.info[z2], 0)) {
/* Allocate from the original zone */
pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0);
/* Free the frame from the merged zone */
frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx];
frame->refcount = 0;
buddy_system_free(z->buddy_system, &frame->buddy_link);
buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
}
}
 
/** Return old configuration frames into the zone
/** Return old configuration frames into the zone.
*
* We have several cases
* - the conf. data is outside of zone -> exit, shall we call frame_free??
* - the conf. data was created by zone_create or
* updated with reduce_region -> free every frame
* We have two cases:
* - The configuration data is outside the zone
* -> do nothing (perhaps call frame_free?)
* - The configuration data was created by zone_create
* or updated by reduce_region -> free every frame
*
* @param newzone The actual zone where freeing should occur
* @param oldzone Pointer to old zone configuration data that should
* be freed from new zone
* @param znum The actual zone where freeing should occur.
* @param pfn Old zone configuration frame.
* @param count Old zone frame count.
*
*/
static void return_config_frames(zone_t *newzone, zone_t *oldzone)
static void return_config_frames(count_t znum, pfn_t pfn, count_t count)
{
pfn_t pfn;
frame_t *frame;
count_t cframes;
unsigned int i;
 
pfn = ADDR2PFN((uintptr_t)KA2PA(oldzone));
cframes = SIZE2FRAMES(zone_conf_size(oldzone->count));
ASSERT(zone_flags_available(zones.info[znum].flags));
if (pfn < newzone->base || pfn >= newzone->base + newzone->count)
count_t cframes = SIZE2FRAMES(zone_conf_size(count));
if ((pfn < zones.info[znum].base)
|| (pfn >= zones.info[znum].base + zones.info[znum].count))
return;
frame_t *frame __attribute__ ((unused));
 
frame = &newzone->frames[pfn - newzone->base];
frame = &zones.info[znum].frames[pfn - zones.info[znum].base];
ASSERT(!frame->buddy_order);
 
count_t i;
for (i = 0; i < cframes; i++) {
newzone->busy_count++;
zone_frame_free(newzone, pfn+i-newzone->base);
zones.info[znum].busy_count++;
zone_frame_free(&zones.info[znum],
pfn - zones.info[znum].base + i);
}
}
 
/** Reduce allocated block to count of order 0 frames
/** Reduce allocated block to count of order 0 frames.
*
* The allocated block need 2^order frames of space. Reduce all frames
* in block to order 0 and free the unneeded frames. This means, that
* when freeing the previously allocated block starting with frame_idx,
* The allocated block needs 2^order frames. Reduce all frames
* in the block to order 0 and free the unneeded frames. This means that
* when freeing the previously allocated block starting with frame_idx,
* you have to free every frame.
*
* @param zone
* @param frame_idx Index to block
* @param count Allocated space in block
* @param znum Zone.
* @param frame_idx Index the first frame of the block.
* @param count Allocated frames in block.
*
*/
static void zone_reduce_region(zone_t *zone, pfn_t frame_idx, count_t count)
static void zone_reduce_region(count_t znum, pfn_t frame_idx, count_t count)
{
count_t i;
uint8_t order;
frame_t *frame;
ASSERT(zone_flags_available(zones.info[znum].flags));
ASSERT(frame_idx + count < zones.info[znum].count);
ASSERT(frame_idx + count < zone->count);
 
order = zone->frames[frame_idx].buddy_order;
uint8_t order = zones.info[znum].frames[frame_idx].buddy_order;
ASSERT((count_t) (1 << order) >= count);
 
/* Reduce all blocks to order 0 */
count_t i;
for (i = 0; i < (count_t) (1 << order); i++) {
frame = &zone->frames[i + frame_idx];
frame_t *frame = &zones.info[znum].frames[i + frame_idx];
frame->buddy_order = 0;
if (!frame->refcount)
frame->refcount = 1;
ASSERT(frame->refcount == 1);
}
/* Free unneeded frames */
for (i = count; i < (count_t) (1 << order); i++) {
zone_frame_free(zone, i + frame_idx);
}
for (i = count; i < (count_t) (1 << order); i++)
zone_frame_free(&zones.info[znum], i + frame_idx);
}
 
/** Merge zones z1 and z2
/** Merge zones z1 and z2.
*
* - the zones must be 2 zones with no zone existing in between,
* which means that z2 = z1+1
* The merged zones must be 2 zones with no zone existing in between
* (which means that z2 = z1 + 1). Both zones must be available zones
* with the same flags.
*
* - When you create a new zone, the frame allocator configuration does
* not to be 2^order size. Once the allocator is running it is no longer
* possible, merged configuration data occupies more space :-/
* When you create a new zone, the frame allocator configuration does
* not to be 2^order size. Once the allocator is running it is no longer
* possible, merged configuration data occupies more space :-/
*
* The function uses
*
*/
void zone_merge(unsigned int z1, unsigned int z2)
bool zone_merge(count_t z1, count_t z2)
{
ipl_t ipl;
zone_t *zone1, *zone2, *newzone;
unsigned int cframes;
uint8_t order;
unsigned int i;
pfn_t pfn;
 
ipl = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
 
if ((z1 >= zones.count) || (z2 >= zones.count))
bool ret = true;
/* We can join only 2 zones with none existing inbetween,
* the zones have to be available and with the same
* set of flags
*/
if ((z1 >= zones.count) || (z2 >= zones.count)
|| (z2 - z1 != 1)
|| (!zone_flags_available(zones.info[z1].flags))
|| (!zone_flags_available(zones.info[z2].flags))
|| (zones.info[z1].flags != zones.info[z2].flags)) {
ret = false;
goto errout;
/* We can join only 2 zones with none existing inbetween */
if (z2-z1 != 1)
goto errout;
 
zone1 = zones.info[z1];
zone2 = zones.info[z2];
spinlock_lock(&zone1->lock);
spinlock_lock(&zone2->lock);
 
cframes = SIZE2FRAMES(zone_conf_size(zone2->base + zone2->count -
zone1->base));
}
pfn_t cframes = SIZE2FRAMES(zone_conf_size(
zones.info[z2].base - zones.info[z1].base
+ zones.info[z2].count));
uint8_t order;
if (cframes == 1)
order = 0;
else
else
order = fnzb(cframes - 1) + 1;
 
/* Allocate zonedata inside one of the zones */
if (zone_can_alloc(zone1, order))
pfn = zone1->base + zone_frame_alloc(zone1, order);
else if (zone_can_alloc(zone2, order))
pfn = zone2->base + zone_frame_alloc(zone2, order);
else
goto errout2;
 
newzone = (zone_t *) PA2KA(PFN2ADDR(pfn));
 
_zone_merge(newzone, zone1, zone2);
 
/* Allocate merged zone data inside one of the zones */
pfn_t pfn;
if (zone_can_alloc(&zones.info[z1], order)) {
pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order);
} else if (zone_can_alloc(&zones.info[z2], order)) {
pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order);
} else {
ret = false;
goto errout;
}
/* Preserve original data from z1 */
zone_t old_z1 = zones.info[z1];
old_z1.buddy_system->data = (void *) &old_z1;
/* Do zone merging */
buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn));
zone_merge_internal(z1, z2, &old_z1, buddy);
/* Free unneeded config frames */
zone_reduce_region(newzone, pfn - newzone->base, cframes);
zone_reduce_region(z1, pfn - zones.info[z1].base, cframes);
/* Subtract zone information from busy frames */
newzone->busy_count -= cframes;
 
/* Replace existing zones in zoneinfo list */
zones.info[z1] = newzone;
for (i = z2 + 1; i < zones.count; i++)
zones.info[z1].busy_count -= cframes;
/* Free old zone information */
return_config_frames(z1,
ADDR2PFN(KA2PA((uintptr_t) old_z1.frames)), old_z1.count);
return_config_frames(z1,
ADDR2PFN(KA2PA((uintptr_t) zones.info[z2].frames)),
zones.info[z2].count);
/* Move zones down */
count_t i;
for (i = z2 + 1; i < zones.count; i++) {
zones.info[i - 1] = zones.info[i];
zones.info[i - 1].buddy_system->data =
(void *) &zones.info[i - 1];
}
zones.count--;
 
/* Free old zone information */
return_config_frames(newzone, zone1);
return_config_frames(newzone, zone2);
errout2:
/* Nobody is allowed to enter to zone, so we are safe
* to touch the spinlocks last time */
spinlock_unlock(&zone1->lock);
spinlock_unlock(&zone2->lock);
errout:
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return ret;
}
 
/**
* Merge all zones into one big zone
/** Merge all mergeable zones into one big zone.
*
* It is reasonable to do this on systems whose bios reports parts in chunks,
* so that we could have 1 zone (it's faster).
* It is reasonable to do this on systems where
* BIOS reports parts in chunks, so that we could
* have 1 zone (it's faster).
*
*/
void zone_merge_all(void)
{
int count = zones.count;
 
while (zones.count > 1 && --count) {
zone_merge(0,1);
break;
count_t i = 0;
while (i < zones.count) {
if (!zone_merge(i, i + 1))
i++;
}
}
 
/** Create frame zone
/** Create new frame zone.
*
* Create new frame zone.
*
* @param zone Zone to construct.
* @param buddy Address of buddy system configuration information.
* @param start Physical address of the first frame within the zone.
* @param count Count of frames in zone
* @param z Address of configuration information of zone
* @param count Count of frames in zone.
* @param flags Zone flags.
*
* @return Initialized zone.
*
*/
static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags)
static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start, count_t count, zone_flags_t flags)
{
unsigned int i;
uint8_t max_order;
 
spinlock_initialize(&z->lock, "zone_lock");
z->base = start;
z->count = count;
z->flags = flags;
z->free_count = count;
z->busy_count = 0;
 
/*
* Compute order for buddy system, initialize
*/
max_order = fnzb(count);
z->buddy_system = (buddy_system_t *)&z[1];
zone->base = start;
zone->count = count;
zone->flags = flags;
zone->free_count = count;
zone->busy_count = 0;
zone->buddy_system = buddy;
buddy_system_create(z->buddy_system, max_order,
&zone_buddy_system_operations,
(void *) z);
/* Allocate frames _after_ the conframe */
/* Check sizes */
z->frames = (frame_t *)((uint8_t *) z->buddy_system +
buddy_conf_size(max_order));
for (i = 0; i < count; i++) {
frame_initialize(&z->frames[i]);
}
/* Stuffing frames */
for (i = 0; i < count; i++) {
z->frames[i].refcount = 0;
buddy_system_free(z->buddy_system, &z->frames[i].buddy_link);
}
if (zone_flags_available(flags)) {
/*
* Compute order for buddy system and initialize
*/
uint8_t order = fnzb(count);
buddy_system_create(zone->buddy_system, order,
&zone_buddy_system_operations, (void *) zone);
/* Allocate frames _after_ the confframe */
/* Check sizes */
zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system +
buddy_conf_size(order));
count_t i;
for (i = 0; i < count; i++)
frame_initialize(&zone->frames[i]);
/* Stuffing frames */
for (i = 0; i < count; i++) {
zone->frames[i].refcount = 0;
buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link);
}
} else
zone->frames = NULL;
}
 
/** Compute configuration data size for zone
/** Compute configuration data size for zone.
*
* @param count Size of zone in frames
* @return Size of zone configuration info (in bytes)
* @param count Size of zone in frames.
*
* @return Size of zone configuration info (in bytes).
*
*/
uintptr_t zone_conf_size(count_t count)
{
int size = sizeof(zone_t) + count*sizeof(frame_t);
int max_order;
 
max_order = fnzb(count);
size += buddy_conf_size(max_order);
return size;
return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
}
 
/** Create and add zone to system
/** Create and add zone to system.
*
* @param start First frame number (absolute)
* @param count Size of zone in frames
* @param start First frame number (absolute).
* @param count Size of zone in frames.
* @param confframe Where configuration frames are supposed to be.
* Automatically checks, that we will not disturb the
* kernel and possibly init.
* If confframe is given _outside_ this zone, it is expected,
* that the area is already marked BUSY and big enough
* to contain zone_conf_size() amount of data.
* If the confframe is inside the area, the zone free frame
* information is modified not to include it.
* Automatically checks, that we will not disturb the
* kernel and possibly init. If confframe is given
* _outside_ this zone, it is expected, that the area is
* already marked BUSY and big enough to contain
* zone_conf_size() amount of data. If the confframe is
* inside the area, the zone free frame information is
* modified not to include it.
*
* @return Zone number or -1 on error
* @return Zone number or -1 on error.
*
*/
int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags)
count_t zone_create(pfn_t start, count_t count, pfn_t confframe, zone_flags_t flags)
{
zone_t *z;
uintptr_t addr;
count_t confcount;
unsigned int i;
int znum;
 
/* Theoretically we could have here 0, practically make sure
* nobody tries to do that. If some platform requires, remove
* the assert
*/
ASSERT(confframe);
/* If conframe is supposed to be inside our zone, then make sure
* it does not span kernel & init
*/
confcount = SIZE2FRAMES(zone_conf_size(count));
if (confframe >= start && confframe < start+count) {
for (;confframe < start + count; confframe++) {
addr = PFN2ADDR(confframe);
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(config.base), config.kernel_size))
continue;
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(config.stack_base), config.stack_size))
continue;
bool overlap = false;
count_t i;
for (i = 0; i < init.cnt; i++)
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
if (zone_flags_available(flags)) { /* Create available zone */
/* Theoretically we could have NULL here, practically make sure
* nobody tries to do that. If some platform requires, remove
* the assert
*/
ASSERT(confframe != NULL);
/* If confframe is supposed to be inside our zone, then make sure
* it does not span kernel & init
*/
count_t confcount = SIZE2FRAMES(zone_conf_size(count));
if ((confframe >= start) && (confframe < start + count)) {
for (; confframe < start + count; confframe++) {
uintptr_t addr = PFN2ADDR(confframe);
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(init.tasks[i].addr),
init.tasks[i].size)) {
overlap = true;
break;
}
if (overlap)
continue;
KA2PA(config.base), config.kernel_size))
continue;
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(config.stack_base), config.stack_size))
continue;
bool overlap = false;
count_t i;
for (i = 0; i < init.cnt; i++)
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(init.tasks[i].addr),
init.tasks[i].size)) {
overlap = true;
break;
}
if (overlap)
continue;
break;
}
break;
if (confframe >= start + count)
panic("Cannot find configuration data for zone.");
}
if (confframe >= start + count)
panic("Cannot find configuration data for zone.");
count_t znum = zones_insert_zone(start, count);
if (znum == (count_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return (count_t) -1;
}
buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe));
zone_construct(&zones.info[znum], buddy, start, count, flags);
/* If confdata in zone, mark as unavailable */
if ((confframe >= start) && (confframe < start + count)) {
count_t i;
for (i = confframe; i < confframe + confcount; i++)
zone_mark_unavailable(&zones.info[znum],
i - zones.info[znum].base);
}
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return znum;
}
 
z = (zone_t *) PA2KA(PFN2ADDR(confframe));
zone_construct(start, count, z, flags);
znum = zones_add_zone(z);
if (znum == -1)
return -1;
 
/* If confdata in zone, mark as unavailable */
if (confframe >= start && confframe < start + count)
for (i = confframe; i < confframe + confcount; i++) {
zone_mark_unavailable(z, i - z->base);
}
/* Non-available zone */
count_t znum = zones_insert_zone(start, count);
if (znum == (count_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return (count_t) -1;
}
zone_construct(&zones.info[znum], NULL, start, count, flags);
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return znum;
}
 
/***************************************/
/*******************/
/* Frame functions */
/*******************/
 
/** Set parent of frame */
void frame_set_parent(pfn_t pfn, void *data, unsigned int hint)
/** Set parent of frame. */
void frame_set_parent(pfn_t pfn, void *data, count_t hint)
{
zone_t *zone = find_zone_and_lock(pfn, &hint);
 
ASSERT(zone);
 
zone_get_frame(zone, pfn-zone->base)->parent = data;
spinlock_unlock(&zone->lock);
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
count_t znum = find_zone(pfn, 1, hint);
ASSERT(znum != (count_t) -1);
zone_get_frame(&zones.info[znum],
pfn - zones.info[znum].base)->parent = data;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
}
 
void *frame_get_parent(pfn_t pfn, unsigned int hint)
void *frame_get_parent(pfn_t pfn, count_t hint)
{
zone_t *zone = find_zone_and_lock(pfn, &hint);
void *res;
 
ASSERT(zone);
res = zone_get_frame(zone, pfn - zone->base)->parent;
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
spinlock_unlock(&zone->lock);
count_t znum = find_zone(pfn, 1, hint);
ASSERT(znum != (count_t) -1);
void *res = zone_get_frame(&zones.info[znum],
pfn - zones.info[znum].base)->parent;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return res;
}
 
/** Allocate power-of-two frames of physical memory.
*
* @param order Allocate exactly 2^order frames.
* @param flags Flags for host zone selection and address processing.
* @param pzone Preferred zone
* @param order Allocate exactly 2^order frames.
* @param flags Flags for host zone selection and address processing.
* @param pzone Preferred zone.
*
* @return Physical address of the allocated frame.
*
*/
void * frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone)
void *frame_alloc_generic(uint8_t order, frame_flags_t flags, count_t *pzone)
{
count_t size = ((count_t) 1) << order;
ipl_t ipl;
int freed;
pfn_t v;
zone_t *zone;
count_t hint = pzone ? (*pzone) : 0;
loop:
ipl = interrupts_disable();
spinlock_lock(&zones.lock);
/*
* First, find suitable frame zone.
*/
zone = find_free_zone_and_lock(order, pzone);
count_t znum = find_free_zone(order,
FRAME_TO_ZONE_FLAGS(flags), hint);
/* If no memory, reclaim some slab memory,
if it does not help, reclaim all */
if (!zone && !(flags & FRAME_NO_RECLAIM)) {
freed = slab_reclaim(0);
if (freed)
zone = find_free_zone_and_lock(order, pzone);
if (!zone) {
if ((znum == (count_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
count_t freed = slab_reclaim(0);
if (freed > 0)
znum = find_free_zone(order,
FRAME_TO_ZONE_FLAGS(flags), hint);
if (znum == (count_t) -1) {
freed = slab_reclaim(SLAB_RECLAIM_ALL);
if (freed)
zone = find_free_zone_and_lock(order, pzone);
if (freed > 0)
znum = find_free_zone(order,
FRAME_TO_ZONE_FLAGS(flags), hint);
}
}
if (!zone) {
if (znum == (count_t) -1) {
if (flags & FRAME_ATOMIC) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return NULL;
}
#ifdef CONFIG_DEBUG
count_t avail = total_frames_free();
#endif
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
/*
* TODO: Sleep until frames are available again.
* Sleep until some frames are available again.
*/
interrupts_restore(ipl);
 
if (flags & FRAME_ATOMIC)
return 0;
panic("Sleep not implemented.\n");
#ifdef CONFIG_DEBUG
printf("Thread %" PRIu64 " waiting for %" PRIc " frames, "
"%" PRIc " available.\n", THREAD->tid, size, avail);
#endif
mutex_lock(&mem_avail_mtx);
if (mem_avail_req > 0)
mem_avail_req = min(mem_avail_req, size);
else
mem_avail_req = size;
count_t gen = mem_avail_gen;
while (gen == mem_avail_gen)
condvar_wait(&mem_avail_cv, &mem_avail_mtx);
mutex_unlock(&mem_avail_mtx);
#ifdef CONFIG_DEBUG
printf("Thread %" PRIu64 " woken up.\n", THREAD->tid);
#endif
goto loop;
}
v = zone_frame_alloc(zone, order);
v += zone->base;
 
spinlock_unlock(&zone->lock);
pfn_t pfn = zone_frame_alloc(&zones.info[znum], order)
+ zones.info[znum].base;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
 
if (pzone)
*pzone = znum;
if (flags & FRAME_KA)
return (void *)PA2KA(PFN2ADDR(v));
return (void *)PFN2ADDR(v);
return (void *) PA2KA(PFN2ADDR(pfn));
return (void *) PFN2ADDR(pfn);
}
 
/** Free a frame.
*
* Find respective frame structure for supplied physical frame address.
* Decrement frame reference count.
* If it drops to zero, move the frame structure to free list.
* Decrement frame reference count. If it drops to zero, move the frame
* structure to free list.
*
* @param Frame Physical Address of of the frame to be freed.
* @param frame Physical Address of of the frame to be freed.
*
*/
void frame_free(uintptr_t frame)
{
ipl_t ipl;
zone_t *zone;
pfn_t pfn = ADDR2PFN(frame);
 
ipl = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
/*
* First, find host frame zone for addr.
*/
zone = find_zone_and_lock(pfn,NULL);
ASSERT(zone);
pfn_t pfn = ADDR2PFN(frame);
count_t znum = find_zone(pfn, 1, NULL);
zone_frame_free(zone, pfn-zone->base);
ASSERT(znum != (count_t) -1);
spinlock_unlock(&zone->lock);
zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
/*
* Signal that some memory has been freed.
*/
mutex_lock(&mem_avail_mtx);
if (mem_avail_req > 0)
mem_avail_req--;
if (mem_avail_req == 0) {
mem_avail_gen++;
condvar_broadcast(&mem_avail_cv);
}
mutex_unlock(&mem_avail_mtx);
}
 
/** Add reference to frame.
1047,55 → 1111,56
* increment frame reference count.
*
* @param pfn Frame number of the frame to be freed.
*
*/
void frame_reference_add(pfn_t pfn)
{
ipl_t ipl;
zone_t *zone;
frame_t *frame;
 
ipl = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
/*
* First, find host frame zone for addr.
*/
zone = find_zone_and_lock(pfn,NULL);
ASSERT(zone);
count_t znum = find_zone(pfn, 1, NULL);
frame = &zone->frames[pfn-zone->base];
frame->refcount++;
ASSERT(znum != (count_t) -1);
spinlock_unlock(&zone->lock);
zones.info[znum].frames[pfn - zones.info[znum].base].refcount++;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
}
 
/** Mark given range unavailable in frame zones */
/** Mark given range unavailable in frame zones. */
void frame_mark_unavailable(pfn_t start, count_t count)
{
unsigned int i;
zone_t *zone;
unsigned int prefzone = 0;
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
count_t i;
for (i = 0; i < count; i++) {
zone = find_zone_and_lock(start + i, &prefzone);
if (!zone) /* PFN not found */
count_t znum = find_zone(start + i, 1, 0);
if (znum == (count_t) -1) /* PFN not found */
continue;
zone_mark_unavailable(zone, start + i - zone->base);
 
spinlock_unlock(&zone->lock);
zone_mark_unavailable(&zones.info[znum],
start + i - zones.info[znum].base);
}
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
}
 
/** Initialize physical memory management
*
* Initialize physical memory managemnt.
*/
/** Initialize physical memory management. */
void frame_init(void)
{
if (config.cpu_active == 1) {
zones.count = 0;
spinlock_initialize(&zones.lock, "zones.lock");
mutex_initialize(&mem_avail_mtx, MUTEX_ACTIVE);
condvar_initialize(&mem_avail_cv);
}
/* Tell the architecture to create some memory */
frame_arch_init();
if (config.cpu_active == 1) {
1110,36 → 1175,28
frame_mark_unavailable(pfn,
SIZE2FRAMES(init.tasks[i].size));
}
 
if (ballocs.size)
frame_mark_unavailable(ADDR2PFN(KA2PA(ballocs.base)),
SIZE2FRAMES(ballocs.size));
 
/* Black list first frame, as allocating NULL would
* fail in some places */
* fail in some places
*/
frame_mark_unavailable(0, 1);
}
}
 
 
/** Return total size of all zones
*
*/
uint64_t zone_total_size(void) {
zone_t *zone = NULL;
unsigned int i;
ipl_t ipl;
uint64_t total = 0;
 
ipl = interrupts_disable();
/** Return total size of all zones. */
uint64_t zone_total_size(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
for (i = 0; i < zones.count; i++) {
zone = zones.info[i];
spinlock_lock(&zone->lock);
total += (uint64_t) FRAMES2SIZE(zone->count);
spinlock_unlock(&zone->lock);
}
uint64_t total = 0;
count_t i;
for (i = 0; i < zones.count; i++)
total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
1147,86 → 1204,128
return total;
}
 
/** Prints list of zones. */
void zone_print_list(void)
{
#ifdef __32_BITS__
printf("# base address frames flags free frames busy frames\n");
printf("-- ------------ ------------ -------- ------------ ------------\n");
#endif
 
 
/** Prints list of zones
*
*/
void zone_print_list(void) {
zone_t *zone = NULL;
unsigned int i;
ipl_t ipl;
 
ipl = interrupts_disable();
spinlock_lock(&zones.lock);
#ifdef __64_BITS__
printf("# base address frames flags free frames busy frames\n");
printf("-- -------------------- ------------ -------- ------------ ------------\n");
#endif
if (sizeof(void *) == 4) {
printf("# base address free frames busy frames\n");
printf("-- ------------ ------------ ------------\n");
} else {
printf("# base address free frames busy frames\n");
printf("-- -------------------- ------------ ------------\n");
}
/*
* Because printing may require allocation of memory, we may not hold
* the frame allocator locks when printing zone statistics. Therefore,
* we simply gather the statistics under the protection of the locks and
* print the statistics when the locks have been released.
*
* When someone adds/removes zones while we are printing the statistics,
* we may end up with inaccurate output (e.g. a zone being skipped from
* the listing).
*/
for (i = 0; i < zones.count; i++) {
zone = zones.info[i];
spinlock_lock(&zone->lock);
count_t i;
for (i = 0;; i++) {
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
if (sizeof(void *) == 4)
printf("%-2d %#10zx %12zd %12zd\n", i, PFN2ADDR(zone->base),
zone->free_count, zone->busy_count);
else
printf("%-2d %#18zx %12zd %12zd\n", i, PFN2ADDR(zone->base),
zone->free_count, zone->busy_count);
if (i >= zones.count) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
break;
}
spinlock_unlock(&zone->lock);
uintptr_t base = PFN2ADDR(zones.info[i].base);
count_t count = zones.info[i].count;
zone_flags_t flags = zones.info[i].flags;
count_t free_count = zones.info[i].free_count;
count_t busy_count = zones.info[i].busy_count;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
bool available = zone_flags_available(flags);
printf("%-2" PRIc, i);
#ifdef __32_BITS__
printf(" %10p", base);
#endif
#ifdef __64_BITS__
printf(" %18p", base);
#endif
printf(" %12" PRIc " %c%c%c ", count,
available ? 'A' : ' ',
(flags & ZONE_RESERVED) ? 'R' : ' ',
(flags & ZONE_FIRMWARE) ? 'F' : ' ');
if (available)
printf("%12" PRIc " %12" PRIc,
free_count, busy_count);
printf("\n");
}
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
}
 
/** Prints zone details.
*
* @param num Zone base address or zone number.
*
*/
void zone_print_one(unsigned int num) {
zone_t *zone = NULL;
ipl_t ipl;
unsigned int i;
 
ipl = interrupts_disable();
void zone_print_one(count_t num)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
 
count_t znum = (count_t) -1;
count_t i;
for (i = 0; i < zones.count; i++) {
if ((i == num) || (PFN2ADDR(zones.info[i]->base) == num)) {
zone = zones.info[i];
if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) {
znum = i;
break;
}
}
if (!zone) {
if (znum == (count_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
printf("Zone not found.\n");
goto out;
return;
}
spinlock_lock(&zone->lock);
printf("Memory zone information\n");
printf("Zone base address: %#.*p\n", sizeof(uintptr_t) * 2,
PFN2ADDR(zone->base));
printf("Zone size: %zd frames (%zd KB)\n", zone->count,
SIZE2KB(FRAMES2SIZE(zone->count)));
printf("Allocated space: %zd frames (%zd KB)\n", zone->busy_count,
SIZE2KB(FRAMES2SIZE(zone->busy_count)));
printf("Available space: %zd frames (%zd KB)\n", zone->free_count,
SIZE2KB(FRAMES2SIZE(zone->free_count)));
buddy_system_structure_print(zone->buddy_system, FRAME_SIZE);
spinlock_unlock(&zone->lock);
uintptr_t base = PFN2ADDR(zones.info[i].base);
zone_flags_t flags = zones.info[i].flags;
count_t count = zones.info[i].count;
count_t free_count = zones.info[i].free_count;
count_t busy_count = zones.info[i].busy_count;
out:
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
bool available = zone_flags_available(flags);
printf("Zone number: %" PRIc "\n", znum);
printf("Zone base address: %p\n", base);
printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count,
SIZE2KB(FRAMES2SIZE(count)));
printf("Zone flags: %c%c%c\n",
available ? 'A' : ' ',
(flags & ZONE_RESERVED) ? 'R' : ' ',
(flags & ZONE_FIRMWARE) ? 'F' : ' ');
if (available) {
printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n",
busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n",
free_count, SIZE2KB(FRAMES2SIZE(free_count)));
}
}
 
/** @}
*/
 
/branches/dd/kernel/generic/src/mm/page.c
40,11 → 40,28
* They however, define the single interface.
*/
 
/*
* Note on memory prefetching and updating memory mappings, also described in:
* AMD x86-64 Architecture Programmer's Manual, Volume 2, System Programming,
* 7.2.1 Special Coherency Considerations.
*
* The processor which modifies a page table mapping can access prefetched data
* from the old mapping. In order to prevent this, we place a memory barrier
* after a mapping is updated.
*
* We assume that the other processors are either not using the mapping yet
* (i.e. during the bootstrap) or are executing the TLB shootdown code. While
* we don't care much about the former case, the processors in the latter case
* will do an implicit serialization by virtue of running the TLB shootdown
* interrupt handler.
*/
 
#include <mm/page.h>
#include <arch/mm/page.h>
#include <arch/mm/asid.h>
#include <mm/as.h>
#include <mm/frame.h>
#include <arch/barrier.h>
#include <arch/types.h>
#include <arch/asm.h>
#include <memstr.h>
65,8 → 82,8
* considering possible crossings
* of page boundaries.
*
* @param s Address of the structure.
* @param size Size of the structure.
* @param s Address of the structure.
* @param size Size of the structure.
*/
void map_structure(uintptr_t s, size_t size)
{
76,8 → 93,11
cnt = length / PAGE_SIZE + (length % PAGE_SIZE > 0);
 
for (i = 0; i < cnt; i++)
page_mapping_insert(AS_KERNEL, s + i * PAGE_SIZE, s + i * PAGE_SIZE, PAGE_NOT_CACHEABLE | PAGE_WRITE);
page_mapping_insert(AS_KERNEL, s + i * PAGE_SIZE,
s + i * PAGE_SIZE, PAGE_NOT_CACHEABLE | PAGE_WRITE);
 
/* Repel prefetched accesses to the old mapping. */
memory_barrier();
}
 
/** Insert mapping of page to frame.
87,10 → 107,11
*
* The page table must be locked and interrupts must be disabled.
*
* @param as Address space to wich page belongs.
* @param page Virtual address of the page to be mapped.
* @param frame Physical address of memory frame to which the mapping is done.
* @param flags Flags to be used for mapping.
* @param as Address space to wich page belongs.
* @param page Virtual address of the page to be mapped.
* @param frame Physical address of memory frame to which the mapping is
* done.
* @param flags Flags to be used for mapping.
*/
void page_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, int flags)
{
98,6 → 119,9
ASSERT(page_mapping_operations->mapping_insert);
page_mapping_operations->mapping_insert(as, page, frame, flags);
/* Repel prefetched accesses to the old mapping. */
memory_barrier();
}
 
/** Remove mapping of page.
108,8 → 132,8
*
* The page table must be locked and interrupts must be disabled.
*
* @param as Address space to wich page belongs.
* @param page Virtual address of the page to be demapped.
* @param as Address space to wich page belongs.
* @param page Virtual address of the page to be demapped.
*/
void page_mapping_remove(as_t *as, uintptr_t page)
{
117,6 → 141,9
ASSERT(page_mapping_operations->mapping_remove);
page_mapping_operations->mapping_remove(as, page);
 
/* Repel prefetched accesses to the old mapping. */
memory_barrier();
}
 
/** Find mapping for virtual page
125,10 → 152,11
*
* The page table must be locked and interrupts must be disabled.
*
* @param as Address space to wich page belongs.
* @param page Virtual page.
* @param as Address space to wich page belongs.
* @param page Virtual page.
*
* @return NULL if there is no such mapping; requested mapping otherwise.
* @return NULL if there is no such mapping; requested mapping
* otherwise.
*/
pte_t *page_mapping_find(as_t *as, uintptr_t page)
{
/branches/dd/kernel/generic/src/mm/backend_elf.c
48,6 → 48,7
#include <memstr.h>
#include <macros.h>
#include <arch.h>
#include <arch/barrier.h>
 
#ifdef CONFIG_VIRT_IDX_DCACHE
#include <arch/mm/cache.h>
67,12 → 68,13
*
* The address space area and page tables must be already locked.
*
* @param area Pointer to the address space area.
* @param addr Faulting virtual address.
* @param access Access mode that caused the fault (i.e. read/write/exec).
* @param area Pointer to the address space area.
* @param addr Faulting virtual address.
* @param access Access mode that caused the fault (i.e.
* read/write/exec).
*
* @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK on success (i.e.
* serviced).
* @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK
* on success (i.e. serviced).
*/
int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access)
{
116,7 → 118,7
*/
 
for (i = 0; i < leaf->keys; i++) {
if (leaf->key[i] == page) {
if (leaf->key[i] == page - area->base) {
found = true;
break;
}
127,7 → 129,7
page_mapping_insert(AS, addr, frame,
as_area_get_flags(area));
if (!used_space_insert(area, page, 1))
panic("Could not insert used space.\n");
panic("Cannot insert used space.");
mutex_unlock(&area->sh_info->lock);
return AS_PF_OK;
}
150,6 → 152,10
frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
memcpy((void *) PA2KA(frame),
(void *) (base + i * FRAME_SIZE), FRAME_SIZE);
if (entry->p_flags & PF_X) {
smc_coherence_block((void *) PA2KA(frame),
FRAME_SIZE);
}
dirty = true;
} else {
frame = KA2PA(base + i * FRAME_SIZE);
162,7 → 168,7
* and cleared.
*/
frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
memsetb(PA2KA(frame), FRAME_SIZE, 0);
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
dirty = true;
} else {
size_t pad_lo, pad_hi;
187,8 → 193,13
memcpy((void *) (PA2KA(frame) + pad_lo),
(void *) (base + i * FRAME_SIZE + pad_lo),
FRAME_SIZE - pad_lo - pad_hi);
memsetb(PA2KA(frame), pad_lo, 0);
memsetb(PA2KA(frame) + FRAME_SIZE - pad_hi, pad_hi, 0);
if (entry->p_flags & PF_X) {
smc_coherence_block((void *) (PA2KA(frame) + pad_lo),
FRAME_SIZE - pad_lo - pad_hi);
}
memsetb((void *) PA2KA(frame), pad_lo, 0);
memsetb((void *) (PA2KA(frame) + FRAME_SIZE - pad_hi), pad_hi,
0);
dirty = true;
}
 
203,7 → 214,7
 
page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
if (!used_space_insert(area, page, 1))
panic("Could not insert used space.\n");
panic("Cannot insert used space.");
 
return AS_PF_OK;
}
212,9 → 223,10
*
* The address space area and page tables must be already locked.
*
* @param area Pointer to the address space area.
* @param page Page that is mapped to frame. Must be aligned to PAGE_SIZE.
* @param frame Frame to be released.
* @param area Pointer to the address space area.
* @param page Page that is mapped to frame. Must be aligned to
* PAGE_SIZE.
* @param frame Frame to be released.
*
*/
void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame)
257,7 → 269,7
*
* The address space and address space area must be locked prior to the call.
*
* @param area Address space area.
* @param area Address space area.
*/
void elf_share(as_area_t *area)
{
/branches/dd/kernel/generic/src/syscall/syscall.c
38,6 → 38,7
#include <syscall/syscall.h>
#include <proc/thread.h>
#include <proc/task.h>
#include <proc/program.h>
#include <mm/as.h>
#include <print.h>
#include <putchar.h>
46,40 → 47,43
#include <debug.h>
#include <ipc/sysipc.h>
#include <synch/futex.h>
#include <synch/smc.h>
#include <ddi/ddi.h>
#include <security/cap.h>
#include <syscall/copy.h>
#include <sysinfo/sysinfo.h>
#include <console/console.h>
#include <console/klog.h>
#include <udebug/udebug.h>
 
/** Print using kernel facility
*
* Some simulators can print only through kernel. Userspace can use
* this syscall to facilitate it.
* Print to kernel log.
*
*/
static unative_t sys_io(int fd, const void * buf, size_t count)
static unative_t sys_klog(int fd, const void * buf, size_t count)
{
size_t i;
char *data;
int rc;
 
if (count > PAGE_SIZE)
return ELIMIT;
 
data = (char *) malloc(count, 0);
if (!data)
return ENOMEM;
rc = copy_from_uspace(data, buf, count);
if (rc) {
if (count > 0) {
data = (char *) malloc(count + 1, 0);
if (!data)
return ENOMEM;
rc = copy_from_uspace(data, buf, count);
if (rc) {
free(data);
return rc;
}
data[count] = 0;
printf("%s", data);
free(data);
return rc;
}
 
for (i = 0; i < count; i++)
putchar(data[i]);
free(data);
} else
klog_update();
return count;
}
87,10 → 91,21
/** Tell kernel to get keyboard/console access again */
static unative_t sys_debug_enable_console(void)
{
arch_grab_console();
return 0;
#ifdef CONFIG_KCONSOLE
grab_console();
return true;
#else
return false;
#endif
}
 
/** Tell kernel to relinquish keyboard/console access */
static unative_t sys_debug_disable_console(void)
{
release_console();
return true;
}
 
/** Dispatch system call */
unative_t syscall_handler(unative_t a1, unative_t a2, unative_t a3,
unative_t a4, unative_t a5, unative_t a6, unative_t id)
97,11 → 112,13
{
unative_t rc;
 
if (id < SYSCALL_END)
#ifdef CONFIG_UDEBUG
udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, 0, false);
#endif
if (id < SYSCALL_END) {
rc = syscall_table[id](a1, a2, a3, a4, a5, a6);
else {
klog_printf("TASK %llu: Unknown syscall id %llx", TASK->taskid,
id);
} else {
printf("Task %" PRIu64": Unknown syscall %#" PRIxn, TASK->taskid, id);
task_kill(TASK->taskid);
thread_exit();
}
108,12 → 125,22
if (THREAD->interrupted)
thread_exit();
 
#ifdef CONFIG_UDEBUG
udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, rc, true);
 
/*
* Stopping point needed for tasks that only invoke non-blocking
* system calls.
*/
udebug_stoppable_begin();
udebug_stoppable_end();
#endif
return rc;
}
 
syshandler_t syscall_table[SYSCALL_END] = {
(syshandler_t) sys_io,
(syshandler_t) sys_klog,
(syshandler_t) sys_tls_set,
/* Thread and task related syscalls. */
120,15 → 147,20
(syshandler_t) sys_thread_create,
(syshandler_t) sys_thread_exit,
(syshandler_t) sys_thread_get_id,
(syshandler_t) sys_task_get_id,
(syshandler_t) sys_task_set_name,
(syshandler_t) sys_program_spawn_loader,
/* Synchronization related syscalls. */
(syshandler_t) sys_futex_sleep_timeout,
(syshandler_t) sys_futex_wakeup,
(syshandler_t) sys_smc_coherence,
/* Address space related syscalls. */
(syshandler_t) sys_as_area_create,
(syshandler_t) sys_as_area_resize,
(syshandler_t) sys_as_area_change_flags,
(syshandler_t) sys_as_area_destroy,
/* IPC related syscalls. */
139,6 → 171,7
(syshandler_t) sys_ipc_answer_fast,
(syshandler_t) sys_ipc_answer_slow,
(syshandler_t) sys_ipc_forward_fast,
(syshandler_t) sys_ipc_forward_slow,
(syshandler_t) sys_ipc_wait_for_call,
(syshandler_t) sys_ipc_hangup,
(syshandler_t) sys_ipc_register_irq,
158,7 → 191,10
(syshandler_t) sys_sysinfo_value,
/* Debug calls */
(syshandler_t) sys_debug_enable_console
(syshandler_t) sys_debug_enable_console,
(syshandler_t) sys_debug_disable_console,
(syshandler_t) sys_ipc_connect_kbox
};
 
/** @}
/branches/dd/kernel/generic/src/ipc/ipcrsc.c
170,7 → 170,6
int i;
 
spinlock_lock(&TASK->lock);
for (i = 0; i < IPC_MAX_PHONES; i++) {
if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
atomic_get(&TASK->phones[i].active_calls) == 0)
183,8 → 182,9
}
spinlock_unlock(&TASK->lock);
 
if (i >= IPC_MAX_PHONES)
if (i == IPC_MAX_PHONES)
return -1;
 
return i;
}
 
/branches/dd/kernel/generic/src/ipc/kbox.c
0,0 → 1,284
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genericipc
* @{
*/
/** @file
*/
 
#include <synch/synch.h>
#include <synch/spinlock.h>
#include <synch/mutex.h>
#include <ipc/ipc.h>
#include <ipc/ipcrsc.h>
#include <arch.h>
#include <errno.h>
#include <debug.h>
#include <udebug/udebug_ipc.h>
#include <ipc/kbox.h>
#include <print.h>
 
void ipc_kbox_cleanup(void)
{
ipl_t ipl;
bool have_kb_thread;
 
/*
* Only hold kb.cleanup_lock while setting kb.finished -
* this is enough.
*/
mutex_lock(&TASK->kb.cleanup_lock);
TASK->kb.finished = true;
mutex_unlock(&TASK->kb.cleanup_lock);
 
have_kb_thread = (TASK->kb.thread != NULL);
 
/*
* From now on nobody will try to connect phones or attach
* kbox threads
*/
 
/*
* Disconnect all phones connected to our kbox. Passing true for
* notify_box causes a HANGUP message to be inserted for each
* disconnected phone. This ensures the kbox thread is going to
* wake up and terminate.
*/
ipc_answerbox_slam_phones(&TASK->kb.box, have_kb_thread);
 
/*
* If the task was being debugged, clean up debugging session.
* This is necessarry as slamming the phones won't force
* kbox thread to clean it up since sender != debugger.
*/
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
udebug_task_cleanup(TASK);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
if (have_kb_thread) {
LOG("join kb.thread..\n");
thread_join(TASK->kb.thread);
thread_detach(TASK->kb.thread);
LOG("join done\n");
TASK->kb.thread = NULL;
}
 
/* Answer all messages in 'calls' and 'dispatched_calls' queues. */
spinlock_lock(&TASK->kb.box.lock);
ipc_cleanup_call_list(&TASK->kb.box.dispatched_calls);
ipc_cleanup_call_list(&TASK->kb.box.calls);
spinlock_unlock(&TASK->kb.box.lock);
}
 
/** Handle hangup message in kbox.
*
* @param call The IPC_M_PHONE_HUNGUP call structure.
* @param last Output, the function stores @c true here if
* this was the last phone, @c false otherwise.
**/
static void kbox_proc_phone_hungup(call_t *call, bool *last)
{
ipl_t ipl;
 
LOG("kbox_proc_phone_hungup()\n");
 
/* Was it our debugger, who hung up? */
if (call->sender == TASK->udebug.debugger) {
/* Terminate debugging session (if any). */
LOG("kbox: terminate debug session\n");
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
udebug_task_cleanup(TASK);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
} else {
LOG("kbox: was not debugger\n");
}
 
LOG("kbox: continue with hangup message\n");
IPC_SET_RETVAL(call->data, 0);
ipc_answer(&TASK->kb.box, call);
 
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
spinlock_lock(&TASK->kb.box.lock);
if (list_empty(&TASK->kb.box.connected_phones)) {
/*
* Last phone has been disconnected. Detach this thread so it
* gets freed and signal to the caller.
*/
 
/* Only detach kbox thread unless already terminating. */
mutex_lock(&TASK->kb.cleanup_lock);
if (&TASK->kb.finished == false) {
/* Detach kbox thread so it gets freed from memory. */
thread_detach(TASK->kb.thread);
TASK->kb.thread = NULL;
}
mutex_unlock(&TASK->kb.cleanup_lock);
 
LOG("phone list is empty\n");
*last = true;
} else {
*last = false;
}
 
spinlock_unlock(&TASK->kb.box.lock);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
}
 
/** Implementing function for the kbox thread.
*
* This function listens for debug requests. It terminates
* when all phones are disconnected from the kbox.
*
* @param arg Ignored.
*/
static void kbox_thread_proc(void *arg)
{
call_t *call;
bool done;
 
(void)arg;
LOG("kbox_thread_proc()\n");
done = false;
 
while (!done) {
call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT,
SYNCH_FLAGS_NONE);
 
if (call == NULL)
continue; /* Try again. */
 
switch (IPC_GET_METHOD(call->data)) {
 
case IPC_M_DEBUG_ALL:
/* Handle debug call. */
udebug_call_receive(call);
break;
 
case IPC_M_PHONE_HUNGUP:
/*
* Process the hangup call. If this was the last
* phone, done will be set to true and the
* while loop will terminate.
*/
kbox_proc_phone_hungup(call, &done);
break;
 
default:
/* Ignore */
break;
}
}
 
LOG("kbox: finished\n");
}
 
 
/**
* Connect phone to a task kernel-box specified by id.
*
* Note that this is not completely atomic. For optimisation reasons, the task
* might start cleaning up kbox after the phone has been connected and before
* a kbox thread has been created. This must be taken into account in the
* cleanup code.
*
* @return Phone id on success, or negative error code.
*/
int ipc_connect_kbox(task_id_t taskid)
{
int newphid;
task_t *ta;
thread_t *kb_thread;
ipl_t ipl;
 
ipl = interrupts_disable();
spinlock_lock(&tasks_lock);
 
ta = task_find_by_id(taskid);
if (ta == NULL) {
spinlock_unlock(&tasks_lock);
interrupts_restore(ipl);
return ENOENT;
}
 
atomic_inc(&ta->refcount);
 
spinlock_unlock(&tasks_lock);
interrupts_restore(ipl);
 
mutex_lock(&ta->kb.cleanup_lock);
 
if (atomic_predec(&ta->refcount) == 0) {
mutex_unlock(&ta->kb.cleanup_lock);
task_destroy(ta);
return ENOENT;
}
 
if (ta->kb.finished != false) {
mutex_unlock(&ta->kb.cleanup_lock);
return EINVAL;
}
 
newphid = phone_alloc();
if (newphid < 0) {
mutex_unlock(&ta->kb.cleanup_lock);
return ELIMIT;
}
 
/* Connect the newly allocated phone to the kbox */
ipc_phone_connect(&TASK->phones[newphid], &ta->kb.box);
 
if (ta->kb.thread != NULL) {
mutex_unlock(&ta->kb.cleanup_lock);
return newphid;
}
 
/* Create a kbox thread */
kb_thread = thread_create(kbox_thread_proc, NULL, ta, 0,
"kbox", false);
if (!kb_thread) {
mutex_unlock(&ta->kb.cleanup_lock);
return ENOMEM;
}
 
ta->kb.thread = kb_thread;
thread_ready(kb_thread);
 
mutex_unlock(&ta->kb.cleanup_lock);
 
return newphid;
}
 
/** @}
*/
/branches/dd/kernel/generic/src/ipc/sysipc.c
42,8 → 42,9
#include <ipc/sysipc.h>
#include <ipc/irq.h>
#include <ipc/ipcrsc.h>
#include <ipc/kbox.h>
#include <udebug/udebug_ipc.h>
#include <arch/interrupt.h>
#include <print.h>
#include <syscall/copy.h>
#include <security/cap.h>
#include <mm/as.h>
270,12 → 271,12
/* The recipient agreed to receive data. */
int rc;
uintptr_t dst;
uintptr_t size;
uintptr_t max_size;
size_t size;
size_t max_size;
 
dst = IPC_GET_ARG1(answer->data);
size = IPC_GET_ARG2(answer->data);
max_size = IPC_GET_ARG2(*olddata);
dst = (uintptr_t)IPC_GET_ARG1(answer->data);
size = (size_t)IPC_GET_ARG2(answer->data);
max_size = (size_t)IPC_GET_ARG2(*olddata);
 
if (size <= max_size) {
rc = copy_to_uspace((void *) dst,
295,10 → 296,11
/** Called before the request is sent.
*
* @param call Call structure with the request.
* @param phone Phone that the call will be sent through.
*
* @return Return 0 on success, ELIMIT or EPERM on error.
*/
static int request_preprocess(call_t *call)
static int request_preprocess(call_t *call, phone_t *phone)
{
int newphid;
size_t size;
340,6 → 342,10
return rc;
}
break;
#ifdef CONFIG_UDEBUG
case IPC_M_DEBUG_ALL:
return udebug_request_preprocess(call, phone);
#endif
default:
break;
}
369,6 → 375,7
 
if (call->buffer) {
/* This must be an affirmative answer to IPC_M_DATA_READ. */
/* or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ... */
uintptr_t dst = IPC_GET_ARG1(call->data);
size_t size = IPC_GET_ARG2(call->data);
int rc = copy_to_uspace((void *) dst, call->buffer, size);
399,7 → 406,13
return -1;
}
IPC_SET_ARG5(call->data, phoneid);
}
}
switch (IPC_GET_METHOD(call->data)) {
case IPC_M_DEBUG_ALL:
return -1;
default:
break;
}
return 0;
}
 
426,7 → 439,7
phone_t *phone;
int res;
int rc;
 
GET_CHECK_PHONE(phone, phoneid, return ENOENT);
 
ipc_call_static_init(&call);
441,9 → 454,18
IPC_SET_ARG4(call.data, 0);
IPC_SET_ARG5(call.data, 0);
 
if (!(res = request_preprocess(&call))) {
ipc_call_sync(phone, &call);
if (!(res = request_preprocess(&call, phone))) {
#ifdef CONFIG_UDEBUG
udebug_stoppable_begin();
#endif
rc = ipc_call_sync(phone, &call);
#ifdef CONFIG_UDEBUG
udebug_stoppable_end();
#endif
if (rc != EOK)
return rc;
process_answer(&call);
 
} else {
IPC_SET_RETVAL(call.data, res);
}
479,8 → 501,16
 
GET_CHECK_PHONE(phone, phoneid, return ENOENT);
 
if (!(res = request_preprocess(&call))) {
ipc_call_sync(phone, &call);
if (!(res = request_preprocess(&call, phone))) {
#ifdef CONFIG_UDEBUG
udebug_stoppable_begin();
#endif
rc = ipc_call_sync(phone, &call);
#ifdef CONFIG_UDEBUG
udebug_stoppable_end();
#endif
if (rc != EOK)
return rc;
process_answer(&call);
} else
IPC_SET_RETVAL(call.data, res);
546,7 → 576,7
*/
IPC_SET_ARG5(call->data, 0);
 
if (!(res = request_preprocess(call)))
if (!(res = request_preprocess(call, phone)))
ipc_call(phone, call);
else
ipc_backsend_err(phone, call, res);
580,7 → 610,7
ipc_call_free(call);
return (unative_t) rc;
}
if (!(res = request_preprocess(call)))
if (!(res = request_preprocess(call, phone)))
ipc_call(phone, call);
else
ipc_backsend_err(phone, call, res);
588,7 → 618,8
return (unative_t) call;
}
 
/** Forward a received call to another destination.
/** Forward a received call to another destination - common code for both the
* fast and the slow version.
*
* @param callid Hash of the call to forward.
* @param phoneid Phone handle to use for forwarding.
595,23 → 626,21
* @param method New method to use for the forwarded call.
* @param arg1 New value of the first argument for the forwarded call.
* @param arg2 New value of the second argument for the forwarded call.
* @param arg3 New value of the third argument for the forwarded call.
* @param arg4 New value of the fourth argument for the forwarded call.
* @param arg5 New value of the fifth argument for the forwarded call.
* @param mode Flags that specify mode of the forward operation.
* @param slow If true, arg3, arg4 and arg5 are considered. Otherwise
* the function considers only the fast version arguments:
* i.e. arg1 and arg2.
*
* @return Return 0 on succes, otherwise return an error code.
*
* In case the original method is a system method, ARG1, ARG2 and ARG3 are
* overwritten in the forwarded message with the new method and the new arg1 and
* arg2, respectively. Otherwise the METHOD, ARG1 and ARG2 are rewritten with
* the new method, arg1 and arg2, respectively. Also note there is a set of
* immutable methods, for which the new method and argument is not set and
* these values are ignored.
*
* Warning: When implementing support for changing additional payload
* arguments, make sure that ARG5 is not rewritten for certain
* system IPC
* Warning: Make sure that ARG5 is not rewritten for certain system IPC
*/
unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid,
unative_t method, unative_t arg1, unative_t arg2, int mode)
static unative_t sys_ipc_forward_common(unative_t callid, unative_t phoneid,
unative_t method, unative_t arg1, unative_t arg2, unative_t arg3,
unative_t arg4, unative_t arg5, int mode, bool slow)
{
call_t *call;
phone_t *phone;
619,7 → 648,7
call = get_call(callid);
if (!call)
return ENOENT;
 
call->flags |= IPC_CALL_FORWARDED;
 
GET_CHECK_PHONE(phone, phoneid, {
626,7 → 655,7
IPC_SET_RETVAL(call->data, EFORWARD);
ipc_answer(&TASK->answerbox, call);
return ENOENT;
});
});
 
if (!method_is_forwardable(IPC_GET_METHOD(call->data))) {
IPC_SET_RETVAL(call->data, EFORWARD);
636,8 → 665,8
 
/*
* Userspace is not allowed to change method of system methods on
* forward, allow changing ARG1, ARG2 and ARG3 by means of method,
* arg1 and arg2.
* forward, allow changing ARG1, ARG2, ARG3 and ARG4 by means of method,
* arg1, arg2 and arg3.
* If the method is immutable, don't change anything.
*/
if (!method_is_immutable(IPC_GET_METHOD(call->data))) {
648,10 → 677,22
IPC_SET_ARG1(call->data, method);
IPC_SET_ARG2(call->data, arg1);
IPC_SET_ARG3(call->data, arg2);
if (slow) {
IPC_SET_ARG4(call->data, arg3);
/*
* For system methods we deliberately don't
* overwrite ARG5.
*/
}
} else {
IPC_SET_METHOD(call->data, method);
IPC_SET_ARG1(call->data, arg1);
IPC_SET_ARG2(call->data, arg2);
if (slow) {
IPC_SET_ARG3(call->data, arg3);
IPC_SET_ARG4(call->data, arg4);
IPC_SET_ARG5(call->data, arg5);
}
}
}
 
658,6 → 699,64
return ipc_forward(call, phone, &TASK->answerbox, mode);
}
 
/** Forward a received call to another destination - fast version.
*
* @param callid Hash of the call to forward.
* @param phoneid Phone handle to use for forwarding.
* @param method New method to use for the forwarded call.
* @param arg1 New value of the first argument for the forwarded call.
* @param arg2 New value of the second argument for the forwarded call.
* @param mode Flags that specify mode of the forward operation.
*
* @return Return 0 on succes, otherwise return an error code.
*
* In case the original method is a system method, ARG1, ARG2 and ARG3 are
* overwritten in the forwarded message with the new method and the new
* arg1 and arg2, respectively. Otherwise the METHOD, ARG1 and ARG2 are
* rewritten with the new method, arg1 and arg2, respectively. Also note there
* is a set of immutable methods, for which the new method and arguments are not
* set and these values are ignored.
*/
unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid,
unative_t method, unative_t arg1, unative_t arg2, int mode)
{
return sys_ipc_forward_common(callid, phoneid, method, arg1, arg2, 0, 0,
0, mode, false);
}
 
/** Forward a received call to another destination - slow version.
*
* @param callid Hash of the call to forward.
* @param phoneid Phone handle to use for forwarding.
* @param data Userspace address of the new IPC data.
* @param mode Flags that specify mode of the forward operation.
*
* @return Return 0 on succes, otherwise return an error code.
*
* This function is the slow verision of the sys_ipc_forward_fast interface.
* It can copy all five new arguments and the new method from the userspace.
* It naturally extends the functionality of the fast version. For system
* methods, it additionally stores the new value of arg3 to ARG4. For non-system
* methods, it additionally stores the new value of arg3, arg4 and arg5,
* respectively, to ARG3, ARG4 and ARG5, respectively.
*/
unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid,
ipc_data_t *data, int mode)
{
ipc_data_t newdata;
int rc;
 
rc = copy_from_uspace(&newdata.args, &data->args,
sizeof(newdata.args));
if (rc != 0)
return (unative_t) rc;
 
return sys_ipc_forward_common(callid, phoneid,
IPC_GET_METHOD(newdata), IPC_GET_ARG1(newdata),
IPC_GET_ARG2(newdata), IPC_GET_ARG3(newdata),
IPC_GET_ARG4(newdata), IPC_GET_ARG5(newdata), mode, true);
}
 
/** Answer an IPC call - fast version.
*
* This function can handle only two return arguments of payload, but is faster
781,9 → 880,17
{
call_t *call;
 
restart:
restart:
 
#ifdef CONFIG_UDEBUG
udebug_stoppable_begin();
#endif
call = ipc_wait_for_call(&TASK->answerbox, usec,
flags | SYNCH_FLAGS_INTERRUPTIBLE);
 
#ifdef CONFIG_UDEBUG
udebug_stoppable_end();
#endif
if (!call)
return 0;
 
805,11 → 912,16
 
ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
 
atomic_dec(&TASK->active_calls);
 
if (call->flags & IPC_CALL_DISCARD_ANSWER) {
ipc_call_free(call);
goto restart;
} else {
/*
* Decrement the counter of active calls only if the
* call is not an answer to IPC_M_PHONE_HUNGUP,
* which doesn't contribute to the counter.
*/
atomic_dec(&TASK->active_calls);
}
 
STRUCT_TO_USPACE(&calldata->args, &call->data.args);
824,6 → 936,21
/* Include phone address('id') of the caller in the request,
* copy whole call->data, not only call->data.args */
if (STRUCT_TO_USPACE(calldata, &call->data)) {
/*
* The callee will not receive this call and no one else has
* a chance to answer it. Reply with the EPARTY error code.
*/
ipc_data_t saved_data;
int saveddata = 0;
 
if (answer_need_old(call)) {
memcpy(&saved_data, &call->data, sizeof(call->data));
saveddata = 1;
}
IPC_SET_RETVAL(call->data, EPARTY);
(void) answer_preprocess(call, saveddata ? &saved_data : NULL);
ipc_answer(&TASK->answerbox, call);
return 0;
}
return (unative_t)call;
864,5 → 991,30
return 0;
}
 
#include <console/console.h>
 
/**
* Syscall connect to a task by id.
*
* @return Phone id on success, or negative error code.
*/
unative_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid_arg)
{
#ifdef CONFIG_UDEBUG
sysarg64_t taskid_arg;
int rc;
rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t));
if (rc != 0)
return (unative_t) rc;
 
LOG("sys_ipc_connect_kbox(%" PRIu64 ")\n", taskid_arg.value);
 
return ipc_connect_kbox(taskid_arg.value);
#else
return (unative_t) ENOTSUP;
#endif
}
 
/** @}
*/
/branches/dd/kernel/generic/src/ipc/ipc.c
43,6 → 43,7
#include <synch/waitq.h>
#include <synch/synch.h>
#include <ipc/ipc.h>
#include <ipc/kbox.h>
#include <errno.h>
#include <mm/slab.h>
#include <arch.h>
51,6 → 52,7
#include <debug.h>
 
#include <print.h>
#include <console/console.h>
#include <proc/thread.h>
#include <arch/interrupt.h>
#include <ipc/irq.h>
66,7 → 68,7
*/
static void _ipc_call_init(call_t *call)
{
memsetb((uintptr_t) call, sizeof(*call), 0);
memsetb(call, sizeof(*call), 0);
call->callerbox = &TASK->answerbox;
call->sender = TASK;
call->buffer = NULL;
87,7 → 89,8
call_t *call;
 
call = slab_alloc(ipc_call_slab, flags);
_ipc_call_init(call);
if (call)
_ipc_call_init(call);
 
return call;
}
160,7 → 163,7
*/
void ipc_phone_init(phone_t *phone)
{
mutex_initialize(&phone->lock);
mutex_initialize(&phone->lock, MUTEX_PASSIVE);
phone->callee = NULL;
phone->state = IPC_PHONE_FREE;
atomic_set(&phone->active_calls, 0);
170,8 → 173,10
*
* @param phone Destination kernel phone structure.
* @param request Call structure with request.
*
* @return EOK on success or EINTR if the sleep was interrupted.
*/
void ipc_call_sync(phone_t *phone, call_t *request)
int ipc_call_sync(phone_t *phone, call_t *request)
{
answerbox_t sync_box;
 
181,7 → 186,10
request->callerbox = &sync_box;
 
ipc_call(phone, request);
ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT,
SYNCH_FLAGS_INTERRUPTIBLE))
return EINTR;
return EOK;
}
 
/** Answer a message which was not dispatched and is not listed in any queue.
194,6 → 202,13
 
call->flags |= IPC_CALL_ANSWERED;
 
if (call->flags & IPC_CALL_FORWARDED) {
if (call->caller_phone) {
/* Demasquerade the caller phone. */
call->data.phone = call->caller_phone;
}
}
 
spinlock_lock(&callerbox->lock);
list_append(&call->link, &callerbox->answers);
spinlock_unlock(&callerbox->lock);
346,8 → 361,11
list_remove(&call->link);
spinlock_unlock(&oldbox->lock);
 
if (mode & IPC_FF_ROUTE_FROM_ME)
if (mode & IPC_FF_ROUTE_FROM_ME) {
if (!call->caller_phone)
call->caller_phone = call->data.phone;
call->data.phone = newphone;
}
 
return ipc_call(newphone, call);
}
411,7 → 429,7
*
* @param lst Head of the list to be cleaned up.
*/
static void ipc_cleanup_call_list(link_t *lst)
void ipc_cleanup_call_list(link_t *lst)
{
call_t *call;
 
426,33 → 444,31
}
}
 
/** Cleans up all IPC communication of the current task.
/** Disconnects all phones connected to an answerbox.
*
* Note: ipc_hangup sets returning answerbox to TASK->answerbox, you
* have to change it as well if you want to cleanup other tasks than TASK.
* @param box Answerbox to disconnect phones from.
* @param notify_box If true, the answerbox will get a hangup message for
* each disconnected phone.
*/
void ipc_cleanup(void)
void ipc_answerbox_slam_phones(answerbox_t *box, bool notify_box)
{
int i;
call_t *call;
phone_t *phone;
DEADLOCK_PROBE_INIT(p_phonelck);
ipl_t ipl;
call_t *call;
 
/* Disconnect all our phones ('ipc_phone_hangup') */
for (i = 0; i < IPC_MAX_PHONES; i++)
ipc_phone_hangup(&TASK->phones[i]);
call = notify_box ? ipc_call_alloc(0) : NULL;
 
/* Disconnect all connected irqs */
ipc_irq_cleanup(&TASK->answerbox);
 
/* Disconnect all phones connected to our answerbox */
restart_phones:
spinlock_lock(&TASK->answerbox.lock);
while (!list_empty(&TASK->answerbox.connected_phones)) {
phone = list_get_instance(TASK->answerbox.connected_phones.next,
ipl = interrupts_disable();
spinlock_lock(&box->lock);
while (!list_empty(&box->connected_phones)) {
phone = list_get_instance(box->connected_phones.next,
phone_t, link);
if (SYNCH_FAILED(mutex_trylock(&phone->lock))) {
spinlock_unlock(&TASK->answerbox.lock);
spinlock_unlock(&box->lock);
interrupts_restore(ipl);
DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD);
goto restart_phones;
}
459,13 → 475,70
/* Disconnect phone */
ASSERT(phone->state == IPC_PHONE_CONNECTED);
 
list_remove(&phone->link);
phone->state = IPC_PHONE_SLAMMED;
list_remove(&phone->link);
 
if (notify_box) {
mutex_unlock(&phone->lock);
spinlock_unlock(&box->lock);
interrupts_restore(ipl);
 
/*
* Send one message to the answerbox for each
* phone. Used to make sure the kbox thread
* wakes up after the last phone has been
* disconnected.
*/
IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
call->flags |= IPC_CALL_DISCARD_ANSWER;
_ipc_call(phone, box, call);
 
/* Allocate another call in advance */
call = ipc_call_alloc(0);
 
/* Must start again */
goto restart_phones;
}
 
mutex_unlock(&phone->lock);
}
 
spinlock_unlock(&box->lock);
interrupts_restore(ipl);
 
/* Free unused call */
if (call)
ipc_call_free(call);
}
 
/** Cleans up all IPC communication of the current task.
*
* Note: ipc_hangup sets returning answerbox to TASK->answerbox, you
* have to change it as well if you want to cleanup other tasks than TASK.
*/
void ipc_cleanup(void)
{
int i;
call_t *call;
 
/* Disconnect all our phones ('ipc_phone_hangup') */
for (i = 0; i < IPC_MAX_PHONES; i++)
ipc_phone_hangup(&TASK->phones[i]);
 
/* Disconnect all connected irqs */
ipc_irq_cleanup(&TASK->answerbox);
 
/* Disconnect all phones connected to our regular answerbox */
ipc_answerbox_slam_phones(&TASK->answerbox, false);
 
#ifdef CONFIG_UDEBUG
/* Clean up kbox thread and communications */
ipc_kbox_cleanup();
#endif
 
/* Answer all messages in 'calls' and 'dispatched_calls' queues */
spinlock_lock(&TASK->answerbox.lock);
ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls);
ipc_cleanup_call_list(&TASK->answerbox.calls);
spinlock_unlock(&TASK->answerbox.lock);
501,7 → 574,13
(call->flags & IPC_CALL_NOTIF));
ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
atomic_dec(&TASK->active_calls);
/*
* Record the receipt of this call in the current task's counter
* of active calls. IPC_M_PHONE_HUNGUP calls do not contribute
* to this counter so do not record answers to them either.
*/
if (!(call->flags & IPC_CALL_DISCARD_ANSWER))
atomic_dec(&TASK->active_calls);
ipc_call_free(call);
}
}
562,7 → 641,7
default:
break;
}
printf("active: %d\n",
printf("active: %ld\n",
atomic_get(&task->phones[i].active_calls));
}
mutex_unlock(&task->phones[i].lock);
575,8 → 654,10
for (tmp = task->answerbox.calls.next; tmp != &task->answerbox.calls;
tmp = tmp->next) {
call = list_get_instance(tmp, call_t, link);
printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d "
"A4:%d A5:%d Flags:%x\n", call, call->sender->taskid,
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call,
call->sender->taskid,
IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data),
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
584,12 → 665,14
}
/* Print answerbox - calls */
printf("ABOX - DISPATCHED CALLS:\n");
for (tmp = task->answerbox.dispatched_calls.next;
tmp != &task->answerbox.dispatched_calls;
tmp = tmp->next) {
for (tmp = task->answerbox.dispatched_calls.next;
tmp != &task->answerbox.dispatched_calls;
tmp = tmp->next) {
call = list_get_instance(tmp, call_t, link);
printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d "
"A4:%d A5:%d Flags:%x\n", call, call->sender->taskid,
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call,
call->sender->taskid,
IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data),
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
597,10 → 680,12
}
/* Print answerbox - calls */
printf("ABOX - ANSWERS:\n");
for (tmp = task->answerbox.answers.next; tmp != &task->answerbox.answers;
for (tmp = task->answerbox.answers.next;
tmp != &task->answerbox.answers;
tmp = tmp->next) {
call = list_get_instance(tmp, call_t, link);
printf("Callid:%p M:%d A1:%d A2:%d A3:%d A4:%d A5:%d Flags:%x\n",
printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun
" A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n",
call, IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data),
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
/branches/dd/kernel/generic/src/ipc/irq.c
44,8 → 44,28
* - ARG1: payload modified by a 'top-half' handler
* - ARG2: payload modified by a 'top-half' handler
* - ARG3: payload modified by a 'top-half' handler
* - ARG4: payload modified by a 'top-half' handler
* - ARG5: payload modified by a 'top-half' handler
* - in_phone_hash: interrupt counter (may be needed to assure correct order
* in multithreaded drivers)
*
* Note on synchronization for ipc_irq_register(), ipc_irq_unregister(),
* ipc_irq_cleanup() and IRQ handlers:
*
* By always taking all of the uspace IRQ hash table lock, IRQ structure lock
* and answerbox lock, we can rule out race conditions between the
* registration functions and also the cleanup function. Thus the observer can
* either see the IRQ structure present in both the hash table and the
* answerbox list or absent in both. Views in which the IRQ structure would be
* linked in the hash table but not in the answerbox list, or vice versa, are
* not possible.
*
* By always taking the hash table lock and the IRQ structure lock, we can
* rule out a scenario in which we would free up an IRQ structure, which is
* still referenced by, for example, an IRQ handler. The locking scheme forces
* us to lock the IRQ structure only after any progressing IRQs on that
* structure are finished. Because we hold the hash table lock, we prevent new
* IRQs from taking new references to the IRQ structure.
*/
 
#include <arch.h>
58,78 → 78,8
#include <console/console.h>
#include <print.h>
 
/** Execute code associated with IRQ notification.
/** Free the top-half pseudocode.
*
* @param call Notification call.
* @param code Top-half pseudocode.
*/
static void code_execute(call_t *call, irq_code_t *code)
{
unsigned int i;
unative_t dstval = 0;
if (!code)
return;
for (i = 0; i < code->cmdcount; i++) {
switch (code->cmds[i].cmd) {
case CMD_MEM_READ_1:
dstval = *((uint8_t *) code->cmds[i].addr);
break;
case CMD_MEM_READ_2:
dstval = *((uint16_t *) code->cmds[i].addr);
break;
case CMD_MEM_READ_4:
dstval = *((uint32_t *) code->cmds[i].addr);
break;
case CMD_MEM_READ_8:
dstval = *((uint64_t *) code->cmds[i].addr);
break;
case CMD_MEM_WRITE_1:
*((uint8_t *) code->cmds[i].addr) = code->cmds[i].value;
break;
case CMD_MEM_WRITE_2:
*((uint16_t *) code->cmds[i].addr) =
code->cmds[i].value;
break;
case CMD_MEM_WRITE_4:
*((uint32_t *) code->cmds[i].addr) =
code->cmds[i].value;
break;
case CMD_MEM_WRITE_8:
*((uint64_t *) code->cmds[i].addr) =
code->cmds[i].value;
break;
#if defined(ia32) || defined(amd64)
case CMD_PORT_READ_1:
dstval = inb((long) code->cmds[i].addr);
break;
case CMD_PORT_WRITE_1:
outb((long) code->cmds[i].addr, code->cmds[i].value);
break;
#endif
#if defined(ia64) && defined(SKI)
case CMD_IA64_GETCHAR:
dstval = _getc(&ski_uconsole);
break;
#endif
#if defined(ppc32)
case CMD_PPC32_GETCHAR:
dstval = cuda_get_scancode();
break;
#endif
default:
break;
}
if (code->cmds[i].dstarg && code->cmds[i].dstarg <
IPC_CALL_LEN) {
call->data.args[code->cmds[i].dstarg] = dstval;
}
}
}
 
/** Free top-half pseudocode.
*
* @param code Pointer to the top-half pseudocode.
*/
static void code_free(irq_code_t *code)
140,7 → 90,7
}
}
 
/** Copy top-half pseudocode from userspace into the kernel.
/** Copy the top-half pseudocode from userspace into the kernel.
*
* @param ucode Userspace address of the top-half pseudocode.
*
176,38 → 126,6
return code;
}
 
/** Unregister task from IRQ notification.
*
* @param box Answerbox associated with the notification.
* @param inr IRQ number.
* @param devno Device number.
*/
void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno)
{
ipl_t ipl;
irq_t *irq;
 
ipl = interrupts_disable();
irq = irq_find_and_lock(inr, devno);
if (irq) {
if (irq->notif_cfg.answerbox == box) {
code_free(irq->notif_cfg.code);
irq->notif_cfg.notify = false;
irq->notif_cfg.answerbox = NULL;
irq->notif_cfg.code = NULL;
irq->notif_cfg.method = 0;
irq->notif_cfg.counter = 0;
 
spinlock_lock(&box->irq_lock);
list_remove(&irq->notif_cfg.link);
spinlock_unlock(&box->irq_lock);
spinlock_unlock(&irq->lock);
}
}
interrupts_restore(ipl);
}
 
/** Register an answerbox as a receiving end for IRQ notifications.
*
* @param box Receiving answerbox.
224,6 → 142,10
ipl_t ipl;
irq_code_t *code;
irq_t *irq;
unative_t key[] = {
(unative_t) inr,
(unative_t) devno
};
 
if (ucode) {
code = code_from_uspace(ucode);
233,21 → 155,15
code = NULL;
}
 
ipl = interrupts_disable();
irq = irq_find_and_lock(inr, devno);
if (!irq) {
interrupts_restore(ipl);
code_free(code);
return ENOENT;
}
if (irq->notif_cfg.answerbox) {
spinlock_unlock(&irq->lock);
interrupts_restore(ipl);
code_free(code);
return EEXISTS;
}
/*
* Allocate and populate the IRQ structure.
*/
irq = malloc(sizeof(irq_t), 0);
irq_initialize(irq);
irq->devno = devno;
irq->inr = inr;
irq->claim = ipc_irq_top_half_claim;
irq->handler = ipc_irq_top_half_handler;
irq->notif_cfg.notify = true;
irq->notif_cfg.answerbox = box;
irq->notif_cfg.method = method;
254,14 → 170,140
irq->notif_cfg.code = code;
irq->notif_cfg.counter = 0;
 
/*
* Enlist the IRQ structure in the uspace IRQ hash table and the
* answerbox's list.
*/
ipl = interrupts_disable();
spinlock_lock(&irq_uspace_hash_table_lock);
spinlock_lock(&irq->lock);
spinlock_lock(&box->irq_lock);
if (hash_table_find(&irq_uspace_hash_table, key)) {
code_free(code);
spinlock_unlock(&box->irq_lock);
spinlock_unlock(&irq->lock);
spinlock_unlock(&irq_uspace_hash_table_lock);
free(irq);
interrupts_restore(ipl);
return EEXISTS;
}
hash_table_insert(&irq_uspace_hash_table, key, &irq->link);
list_append(&irq->notif_cfg.link, &box->irq_head);
spinlock_unlock(&box->irq_lock);
spinlock_unlock(&irq->lock);
spinlock_unlock(&irq_uspace_hash_table_lock);
 
interrupts_restore(ipl);
return EOK;
}
 
/** Unregister task from IRQ notification.
*
* @param box Answerbox associated with the notification.
* @param inr IRQ number.
* @param devno Device number.
*/
int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno)
{
ipl_t ipl;
unative_t key[] = {
(unative_t) inr,
(unative_t) devno
};
link_t *lnk;
irq_t *irq;
 
ipl = interrupts_disable();
spinlock_lock(&irq_uspace_hash_table_lock);
lnk = hash_table_find(&irq_uspace_hash_table, key);
if (!lnk) {
spinlock_unlock(&irq_uspace_hash_table_lock);
interrupts_restore(ipl);
return ENOENT;
}
irq = hash_table_get_instance(lnk, irq_t, link);
spinlock_lock(&irq->lock);
spinlock_lock(&box->irq_lock);
ASSERT(irq->notif_cfg.answerbox == box);
/* Free up the pseudo code and associated structures. */
code_free(irq->notif_cfg.code);
 
/* Remove the IRQ from the answerbox's list. */
list_remove(&irq->notif_cfg.link);
 
/* Remove the IRQ from the uspace IRQ hash table. */
hash_table_remove(&irq_uspace_hash_table, key, 2);
spinlock_unlock(&irq_uspace_hash_table_lock);
spinlock_unlock(&irq->lock);
spinlock_unlock(&box->irq_lock);
/* Free up the IRQ structure. */
free(irq);
interrupts_restore(ipl);
return EOK;
}
 
return 0;
 
/** Disconnect all IRQ notifications from an answerbox.
*
* This function is effective because the answerbox contains
* list of all irq_t structures that are registered to
* send notifications to it.
*
* @param box Answerbox for which we want to carry out the cleanup.
*/
void ipc_irq_cleanup(answerbox_t *box)
{
ipl_t ipl;
loop:
ipl = interrupts_disable();
spinlock_lock(&irq_uspace_hash_table_lock);
spinlock_lock(&box->irq_lock);
while (box->irq_head.next != &box->irq_head) {
link_t *cur = box->irq_head.next;
irq_t *irq;
DEADLOCK_PROBE_INIT(p_irqlock);
unative_t key[2];
irq = list_get_instance(cur, irq_t, notif_cfg.link);
if (!spinlock_trylock(&irq->lock)) {
/*
* Avoid deadlock by trying again.
*/
spinlock_unlock(&box->irq_lock);
spinlock_unlock(&irq_uspace_hash_table_lock);
interrupts_restore(ipl);
DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD);
goto loop;
}
key[0] = irq->inr;
key[1] = irq->devno;
ASSERT(irq->notif_cfg.answerbox == box);
/* Unlist from the answerbox. */
list_remove(&irq->notif_cfg.link);
/* Remove from the hash table. */
hash_table_remove(&irq_uspace_hash_table, key, 2);
/* Free up the pseudo code and associated structures. */
code_free(irq->notif_cfg.code);
spinlock_unlock(&irq->lock);
free(irq);
}
spinlock_unlock(&box->irq_lock);
spinlock_unlock(&irq_uspace_hash_table_lock);
interrupts_restore(ipl);
}
 
/** Add a call to the proper answerbox queue.
280,125 → 322,158
waitq_wakeup(&irq->notif_cfg.answerbox->wq, WAKEUP_FIRST);
}
 
/** Send notification message.
/** Apply the top-half pseudo code to find out whether to accept the IRQ or not.
*
* @param irq IRQ structure.
* @param a1 Driver-specific payload argument.
* @param a2 Driver-specific payload argument.
* @param a3 Driver-specific payload argument.
* @param a4 Driver-specific payload argument.
* @param a5 Driver-specific payload argument.
*
* @return IRQ_ACCEPT if the interrupt is accepted by the
* pseudocode. IRQ_DECLINE otherwise.
*/
void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3,
unative_t a4, unative_t a5)
irq_ownership_t ipc_irq_top_half_claim(irq_t *irq)
{
call_t *call;
unsigned int i;
unative_t dstval;
irq_code_t *code = irq->notif_cfg.code;
unative_t *scratch = irq->notif_cfg.scratch;
 
spinlock_lock(&irq->lock);
 
if (irq->notif_cfg.answerbox) {
call = ipc_call_alloc(FRAME_ATOMIC);
if (!call) {
spinlock_unlock(&irq->lock);
return;
if (!irq->notif_cfg.notify)
return IRQ_DECLINE;
if (!code)
return IRQ_DECLINE;
for (i = 0; i < code->cmdcount; i++) {
unsigned int srcarg = code->cmds[i].srcarg;
unsigned int dstarg = code->cmds[i].dstarg;
if (srcarg >= IPC_CALL_LEN)
break;
if (dstarg >= IPC_CALL_LEN)
break;
switch (code->cmds[i].cmd) {
case CMD_PIO_READ_8:
dstval = pio_read_8((ioport8_t *) code->cmds[i].addr);
if (dstarg)
scratch[dstarg] = dstval;
break;
case CMD_PIO_READ_16:
dstval = pio_read_16((ioport16_t *) code->cmds[i].addr);
if (dstarg)
scratch[dstarg] = dstval;
break;
case CMD_PIO_READ_32:
dstval = pio_read_32((ioport32_t *) code->cmds[i].addr);
if (dstarg)
scratch[dstarg] = dstval;
break;
case CMD_PIO_WRITE_8:
pio_write_8((ioport8_t *) code->cmds[i].addr,
(uint8_t) code->cmds[i].value);
break;
case CMD_PIO_WRITE_16:
pio_write_16((ioport16_t *) code->cmds[i].addr,
(uint16_t) code->cmds[i].value);
break;
case CMD_PIO_WRITE_32:
pio_write_32((ioport32_t *) code->cmds[i].addr,
(uint32_t) code->cmds[i].value);
break;
case CMD_BTEST:
if (srcarg && dstarg) {
dstval = scratch[srcarg] & code->cmds[i].value;
scratch[dstarg] = dstval;
}
break;
case CMD_PREDICATE:
if (srcarg && !scratch[srcarg]) {
i += code->cmds[i].value;
continue;
}
break;
case CMD_ACCEPT:
return IRQ_ACCEPT;
break;
case CMD_DECLINE:
default:
return IRQ_DECLINE;
}
call->flags |= IPC_CALL_NOTIF;
IPC_SET_METHOD(call->data, irq->notif_cfg.method);
IPC_SET_ARG1(call->data, a1);
IPC_SET_ARG2(call->data, a2);
IPC_SET_ARG3(call->data, a3);
IPC_SET_ARG4(call->data, a4);
IPC_SET_ARG5(call->data, a5);
/* Put a counter to the message */
call->priv = ++irq->notif_cfg.counter;
send_call(irq, call);
}
spinlock_unlock(&irq->lock);
return IRQ_DECLINE;
}
 
/** Notify a task that an IRQ had occurred.
 
/* IRQ top-half handler.
*
* We expect interrupts to be disabled and the irq->lock already held.
*
* @param irq IRQ structure.
*/
void ipc_irq_send_notif(irq_t *irq)
void ipc_irq_top_half_handler(irq_t *irq)
{
call_t *call;
 
ASSERT(irq);
 
if (irq->notif_cfg.answerbox) {
call_t *call;
 
call = ipc_call_alloc(FRAME_ATOMIC);
if (!call) {
if (!call)
return;
}
call->flags |= IPC_CALL_NOTIF;
/* Put a counter to the message */
call->priv = ++irq->notif_cfg.counter;
 
/* Set up args */
IPC_SET_METHOD(call->data, irq->notif_cfg.method);
IPC_SET_ARG1(call->data, irq->notif_cfg.scratch[1]);
IPC_SET_ARG2(call->data, irq->notif_cfg.scratch[2]);
IPC_SET_ARG3(call->data, irq->notif_cfg.scratch[3]);
IPC_SET_ARG4(call->data, irq->notif_cfg.scratch[4]);
IPC_SET_ARG5(call->data, irq->notif_cfg.scratch[5]);
 
/* Execute code to handle irq */
code_execute(call, irq->notif_cfg.code);
send_call(irq, call);
}
}
 
/** Disconnect all IRQ notifications from an answerbox.
/** Send notification message.
*
* This function is effective because the answerbox contains
* list of all irq_t structures that are registered to
* send notifications to it.
*
* @param box Answerbox for which we want to carry out the cleanup.
* @param irq IRQ structure.
* @param a1 Driver-specific payload argument.
* @param a2 Driver-specific payload argument.
* @param a3 Driver-specific payload argument.
* @param a4 Driver-specific payload argument.
* @param a5 Driver-specific payload argument.
*/
void ipc_irq_cleanup(answerbox_t *box)
void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3,
unative_t a4, unative_t a5)
{
ipl_t ipl;
loop:
ipl = interrupts_disable();
spinlock_lock(&box->irq_lock);
while (box->irq_head.next != &box->irq_head) {
link_t *cur = box->irq_head.next;
irq_t *irq;
DEADLOCK_PROBE_INIT(p_irqlock);
irq = list_get_instance(cur, irq_t, notif_cfg.link);
if (!spinlock_trylock(&irq->lock)) {
/*
* Avoid deadlock by trying again.
*/
spinlock_unlock(&box->irq_lock);
interrupts_restore(ipl);
DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD);
goto loop;
call_t *call;
 
spinlock_lock(&irq->lock);
 
if (irq->notif_cfg.answerbox) {
call = ipc_call_alloc(FRAME_ATOMIC);
if (!call) {
spinlock_unlock(&irq->lock);
return;
}
call->flags |= IPC_CALL_NOTIF;
/* Put a counter to the message */
call->priv = ++irq->notif_cfg.counter;
 
IPC_SET_METHOD(call->data, irq->notif_cfg.method);
IPC_SET_ARG1(call->data, a1);
IPC_SET_ARG2(call->data, a2);
IPC_SET_ARG3(call->data, a3);
IPC_SET_ARG4(call->data, a4);
IPC_SET_ARG5(call->data, a5);
ASSERT(irq->notif_cfg.answerbox == box);
list_remove(&irq->notif_cfg.link);
/*
* Don't forget to free any top-half pseudocode.
*/
code_free(irq->notif_cfg.code);
irq->notif_cfg.notify = false;
irq->notif_cfg.answerbox = NULL;
irq->notif_cfg.code = NULL;
irq->notif_cfg.method = 0;
irq->notif_cfg.counter = 0;
 
spinlock_unlock(&irq->lock);
send_call(irq, call);
}
spinlock_unlock(&box->irq_lock);
interrupts_restore(ipl);
spinlock_unlock(&irq->lock);
}
 
/** @}
/branches/dd/kernel/generic/src/udebug/udebug.c
0,0 → 1,504
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
* @{
*/
 
/**
* @file
* @brief Udebug hooks and data structure management.
*
* Udebug is an interface that makes userspace debuggers possible.
*/
#include <synch/waitq.h>
#include <debug.h>
#include <udebug/udebug.h>
#include <errno.h>
#include <print.h>
#include <arch.h>
 
 
/** Initialize udebug part of task structure.
*
* Called as part of task structure initialization.
* @param ut Pointer to the structure to initialize.
*/
void udebug_task_init(udebug_task_t *ut)
{
mutex_initialize(&ut->lock, MUTEX_PASSIVE);
ut->dt_state = UDEBUG_TS_INACTIVE;
ut->begin_call = NULL;
ut->not_stoppable_count = 0;
ut->evmask = 0;
}
 
/** Initialize udebug part of thread structure.
*
* Called as part of thread structure initialization.
* @param ut Pointer to the structure to initialize.
*/
void udebug_thread_initialize(udebug_thread_t *ut)
{
mutex_initialize(&ut->lock, MUTEX_PASSIVE);
waitq_initialize(&ut->go_wq);
 
ut->go_call = NULL;
ut->uspace_state = NULL;
ut->go = false;
ut->stoppable = true;
ut->active = false;
ut->cur_event = 0; /* none */
}
 
/** Wait for a GO message.
*
* When a debugging event occurs in a thread or the thread is stopped,
* this function is called to block the thread until a GO message
* is received.
*
* @param wq The wait queue used by the thread to wait for GO messages.
*/
static void udebug_wait_for_go(waitq_t *wq)
{
int rc;
ipl_t ipl;
 
ipl = waitq_sleep_prepare(wq);
 
wq->missed_wakeups = 0; /* Enforce blocking. */
rc = waitq_sleep_timeout_unsafe(wq, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
 
waitq_sleep_finish(wq, rc, ipl);
}
 
/** Do a preliminary check that a debugging session is in progress.
*
* This only requires the THREAD->udebug.lock mutex (and not TASK->udebug.lock
* mutex). For an undebugged task, this will never block (while there could be
* collisions by different threads on the TASK mutex), thus improving SMP
* perormance for undebugged tasks.
*
* @return True if the thread was in a debugging session when the function
* checked, false otherwise.
*/
static bool udebug_thread_precheck(void)
{
bool res;
 
mutex_lock(&THREAD->udebug.lock);
res = THREAD->udebug.active;
mutex_unlock(&THREAD->udebug.lock);
 
return res;
}
 
/** Start of stoppable section.
*
* A stoppable section is a section of code where if the thread can be stoped. In other words,
* if a STOP operation is issued, the thread is guaranteed not to execute
* any userspace instructions until the thread is resumed.
*
* Having stoppable sections is better than having stopping points, since
* a thread can be stopped even when it is blocked indefinitely in a system
* call (whereas it would not reach any stopping point).
*/
void udebug_stoppable_begin(void)
{
int nsc;
call_t *db_call, *go_call;
 
ASSERT(THREAD);
ASSERT(TASK);
 
/* Early check for undebugged tasks */
if (!udebug_thread_precheck()) {
return;
}
 
mutex_lock(&TASK->udebug.lock);
 
nsc = --TASK->udebug.not_stoppable_count;
 
/* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */
mutex_lock(&THREAD->udebug.lock);
ASSERT(THREAD->udebug.stoppable == false);
THREAD->udebug.stoppable = true;
 
if (TASK->udebug.dt_state == UDEBUG_TS_BEGINNING && nsc == 0) {
/*
* This was the last non-stoppable thread. Reply to
* DEBUG_BEGIN call.
*/
 
db_call = TASK->udebug.begin_call;
ASSERT(db_call);
 
TASK->udebug.dt_state = UDEBUG_TS_ACTIVE;
TASK->udebug.begin_call = NULL;
 
IPC_SET_RETVAL(db_call->data, 0);
ipc_answer(&TASK->answerbox, db_call);
 
} else if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) {
/*
* Active debugging session
*/
 
if (THREAD->udebug.active == true &&
THREAD->udebug.go == false) {
/*
* Thread was requested to stop - answer go call
*/
 
/* Make sure nobody takes this call away from us */
go_call = THREAD->udebug.go_call;
THREAD->udebug.go_call = NULL;
ASSERT(go_call);
 
IPC_SET_RETVAL(go_call->data, 0);
IPC_SET_ARG1(go_call->data, UDEBUG_EVENT_STOP);
 
THREAD->udebug.cur_event = UDEBUG_EVENT_STOP;
 
ipc_answer(&TASK->answerbox, go_call);
}
}
 
mutex_unlock(&THREAD->udebug.lock);
mutex_unlock(&TASK->udebug.lock);
}
 
/** End of a stoppable section.
*
* This is the point where the thread will block if it is stopped.
* (As, by definition, a stopped thread must not leave its stoppable section).
*/
void udebug_stoppable_end(void)
{
/* Early check for undebugged tasks */
if (!udebug_thread_precheck()) {
return;
}
 
restart:
mutex_lock(&TASK->udebug.lock);
mutex_lock(&THREAD->udebug.lock);
 
if (THREAD->udebug.active && THREAD->udebug.go == false) {
TASK->udebug.begin_call = NULL;
mutex_unlock(&THREAD->udebug.lock);
mutex_unlock(&TASK->udebug.lock);
 
udebug_wait_for_go(&THREAD->udebug.go_wq);
 
goto restart;
/* Must try again - have to lose stoppability atomically. */
} else {
++TASK->udebug.not_stoppable_count;
ASSERT(THREAD->udebug.stoppable == true);
THREAD->udebug.stoppable = false;
 
mutex_unlock(&THREAD->udebug.lock);
mutex_unlock(&TASK->udebug.lock);
}
}
 
/** Upon being scheduled to run, check if the current thread should stop.
*
* This function is called from clock().
*/
void udebug_before_thread_runs(void)
{
/* Check if we're supposed to stop */
udebug_stoppable_begin();
udebug_stoppable_end();
}
 
/** Syscall event hook.
*
* Must be called before and after servicing a system call. This generates
* a SYSCALL_B or SYSCALL_E event, depending on the value of @a end_variant.
*/
void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3,
unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc,
bool end_variant)
{
call_t *call;
udebug_event_t etype;
 
etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B;
 
/* Early check for undebugged tasks */
if (!udebug_thread_precheck()) {
return;
}
 
mutex_lock(&TASK->udebug.lock);
mutex_lock(&THREAD->udebug.lock);
 
/* Must only generate events when in debugging session and is go. */
if (THREAD->udebug.active != true || THREAD->udebug.go == false ||
(TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) {
mutex_unlock(&THREAD->udebug.lock);
mutex_unlock(&TASK->udebug.lock);
return;
}
 
//printf("udebug_syscall_event\n");
call = THREAD->udebug.go_call;
THREAD->udebug.go_call = NULL;
 
IPC_SET_RETVAL(call->data, 0);
IPC_SET_ARG1(call->data, etype);
IPC_SET_ARG2(call->data, id);
IPC_SET_ARG3(call->data, rc);
//printf("udebug_syscall_event/ipc_answer\n");
 
THREAD->udebug.syscall_args[0] = a1;
THREAD->udebug.syscall_args[1] = a2;
THREAD->udebug.syscall_args[2] = a3;
THREAD->udebug.syscall_args[3] = a4;
THREAD->udebug.syscall_args[4] = a5;
THREAD->udebug.syscall_args[5] = a6;
 
/*
* Make sure udebug.go is false when going to sleep
* in case we get woken up by DEBUG_END. (At which
* point it must be back to the initial true value).
*/
THREAD->udebug.go = false;
THREAD->udebug.cur_event = etype;
 
ipc_answer(&TASK->answerbox, call);
 
mutex_unlock(&THREAD->udebug.lock);
mutex_unlock(&TASK->udebug.lock);
 
udebug_wait_for_go(&THREAD->udebug.go_wq);
}
 
/** Thread-creation event hook combined with attaching the thread.
*
* Must be called when a new userspace thread is created in the debugged
* task. Generates a THREAD_B event. Also attaches the thread @a t
* to the task @a ta.
*
* This is necessary to avoid a race condition where the BEGIN and THREAD_READ
* requests would be handled inbetween attaching the thread and checking it
* for being in a debugging session to send the THREAD_B event. We could then
* either miss threads or get some threads both in the thread list
* and get a THREAD_B event for them.
*
* @param t Structure of the thread being created. Not locked, as the
* thread is not executing yet.
* @param ta Task to which the thread should be attached.
*/
void udebug_thread_b_event_attach(struct thread *t, struct task *ta)
{
call_t *call;
 
mutex_lock(&TASK->udebug.lock);
mutex_lock(&THREAD->udebug.lock);
 
thread_attach(t, ta);
 
LOG("udebug_thread_b_event\n");
LOG("- check state\n");
 
/* Must only generate events when in debugging session */
if (THREAD->udebug.active != true) {
LOG("- udebug.active: %s, udebug.go: %s\n",
THREAD->udebug.active ? "yes(+)" : "no(-)",
THREAD->udebug.go ? "yes(-)" : "no(+)");
mutex_unlock(&THREAD->udebug.lock);
mutex_unlock(&TASK->udebug.lock);
return;
}
 
LOG("- trigger event\n");
 
call = THREAD->udebug.go_call;
THREAD->udebug.go_call = NULL;
IPC_SET_RETVAL(call->data, 0);
IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B);
IPC_SET_ARG2(call->data, (unative_t)t);
 
/*
* Make sure udebug.go is false when going to sleep
* in case we get woken up by DEBUG_END. (At which
* point it must be back to the initial true value).
*/
THREAD->udebug.go = false;
THREAD->udebug.cur_event = UDEBUG_EVENT_THREAD_B;
 
ipc_answer(&TASK->answerbox, call);
 
mutex_unlock(&THREAD->udebug.lock);
mutex_unlock(&TASK->udebug.lock);
 
LOG("- sleep\n");
udebug_wait_for_go(&THREAD->udebug.go_wq);
}
 
/** Thread-termination event hook.
*
* Must be called when the current thread is terminating.
* Generates a THREAD_E event.
*/
void udebug_thread_e_event(void)
{
call_t *call;
 
mutex_lock(&TASK->udebug.lock);
mutex_lock(&THREAD->udebug.lock);
 
LOG("udebug_thread_e_event\n");
LOG("- check state\n");
 
/* Must only generate events when in debugging session. */
if (THREAD->udebug.active != true) {
/* printf("- udebug.active: %s, udebug.go: %s\n",
THREAD->udebug.active ? "yes(+)" : "no(-)",
THREAD->udebug.go ? "yes(-)" : "no(+)");*/
mutex_unlock(&THREAD->udebug.lock);
mutex_unlock(&TASK->udebug.lock);
return;
}
 
LOG("- trigger event\n");
 
call = THREAD->udebug.go_call;
THREAD->udebug.go_call = NULL;
IPC_SET_RETVAL(call->data, 0);
IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E);
 
/* Prevent any further debug activity in thread. */
THREAD->udebug.active = false;
THREAD->udebug.cur_event = 0; /* none */
THREAD->udebug.go = false; /* set to initial value */
 
ipc_answer(&TASK->answerbox, call);
 
mutex_unlock(&THREAD->udebug.lock);
mutex_unlock(&TASK->udebug.lock);
 
/*
* This event does not sleep - debugging has finished
* in this thread.
*/
}
 
/**
* Terminate task debugging session.
*
* Gracefully terminates the debugging session for a task. If the debugger
* is still waiting for events on some threads, it will receive a
* FINISHED event for each of them.
*
* @param ta Task structure. ta->udebug.lock must be already locked.
* @return Zero on success or negative error code.
*/
int udebug_task_cleanup(struct task *ta)
{
thread_t *t;
link_t *cur;
int flags;
ipl_t ipl;
 
LOG("udebug_task_cleanup()\n");
LOG("task %" PRIu64 "\n", ta->taskid);
 
if (ta->udebug.dt_state != UDEBUG_TS_BEGINNING &&
ta->udebug.dt_state != UDEBUG_TS_ACTIVE) {
LOG("udebug_task_cleanup(): task not being debugged\n");
return EINVAL;
}
 
/* Finish debugging of all userspace threads */
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
t = list_get_instance(cur, thread_t, th_link);
 
mutex_lock(&t->udebug.lock);
 
ipl = interrupts_disable();
spinlock_lock(&t->lock);
 
flags = t->flags;
 
spinlock_unlock(&t->lock);
interrupts_restore(ipl);
 
/* Only process userspace threads. */
if ((flags & THREAD_FLAG_USPACE) != 0) {
/* Prevent any further debug activity in thread. */
t->udebug.active = false;
t->udebug.cur_event = 0; /* none */
 
/* Is the thread still go? */
if (t->udebug.go == true) {
/*
* Yes, so clear go. As active == false,
* this doesn't affect anything.
*/
t->udebug.go = false;
 
/* Answer GO call */
LOG("answer GO call with EVENT_FINISHED\n");
IPC_SET_RETVAL(t->udebug.go_call->data, 0);
IPC_SET_ARG1(t->udebug.go_call->data,
UDEBUG_EVENT_FINISHED);
 
ipc_answer(&ta->answerbox, t->udebug.go_call);
t->udebug.go_call = NULL;
} else {
/*
* Debug_stop is already at initial value.
* Yet this means the thread needs waking up.
*/
 
/*
* t's lock must not be held when calling
* waitq_wakeup.
*/
waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST);
}
}
mutex_unlock(&t->udebug.lock);
}
 
ta->udebug.dt_state = UDEBUG_TS_INACTIVE;
ta->udebug.debugger = NULL;
 
return 0;
}
 
 
/** @}
*/
/branches/dd/kernel/generic/src/udebug/udebug_ops.c
0,0 → 1,524
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
* @{
*/
 
/**
* @file
* @brief Udebug operations.
*
* Udebug operations on tasks and threads are implemented here. The
* functions defined here are called from the udebug_ipc module
* when servicing udebug IPC messages.
*/
#include <debug.h>
#include <proc/task.h>
#include <proc/thread.h>
#include <arch.h>
#include <errno.h>
#include <print.h>
#include <syscall/copy.h>
#include <ipc/ipc.h>
#include <udebug/udebug.h>
#include <udebug/udebug_ops.h>
 
/**
* Prepare a thread for a debugging operation.
*
* Simply put, return thread t with t->udebug.lock held,
* but only if it verifies all conditions.
*
* Specifically, verifies that thread t exists, is a userspace thread,
* and belongs to the current task (TASK). Verifies, that the thread
* is (or is not) go according to being_go (typically false).
* It also locks t->udebug.lock, making sure that t->udebug.active
* is true - that the thread is in a valid debugging session.
*
* With this verified and the t->udebug.lock mutex held, it is ensured
* that the thread cannot leave the debugging session, let alone cease
* to exist.
*
* In this function, holding the TASK->udebug.lock mutex prevents the
* thread from leaving the debugging session, while relaxing from
* the t->lock spinlock to the t->udebug.lock mutex.
*
* @param t Pointer, need not at all be valid.
* @param being_go Required thread state.
*
* Returns EOK if all went well, or an error code otherwise.
*/
static int _thread_op_begin(thread_t *t, bool being_go)
{
task_id_t taskid;
ipl_t ipl;
 
taskid = TASK->taskid;
 
mutex_lock(&TASK->udebug.lock);
 
/* thread_exists() must be called with threads_lock held */
ipl = interrupts_disable();
spinlock_lock(&threads_lock);
 
if (!thread_exists(t)) {
spinlock_unlock(&threads_lock);
interrupts_restore(ipl);
mutex_unlock(&TASK->udebug.lock);
return ENOENT;
}
 
/* t->lock is enough to ensure the thread's existence */
spinlock_lock(&t->lock);
spinlock_unlock(&threads_lock);
 
/* Verify that 't' is a userspace thread. */
if ((t->flags & THREAD_FLAG_USPACE) == 0) {
/* It's not, deny its existence */
spinlock_unlock(&t->lock);
interrupts_restore(ipl);
mutex_unlock(&TASK->udebug.lock);
return ENOENT;
}
 
/* Verify debugging state. */
if (t->udebug.active != true) {
/* Not in debugging session or undesired GO state */
spinlock_unlock(&t->lock);
interrupts_restore(ipl);
mutex_unlock(&TASK->udebug.lock);
return ENOENT;
}
 
/*
* Since the thread has active == true, TASK->udebug.lock
* is enough to ensure its existence and that active remains
* true.
*/
spinlock_unlock(&t->lock);
interrupts_restore(ipl);
 
/* Only mutex TASK->udebug.lock left. */
/* Now verify that the thread belongs to the current task. */
if (t->task != TASK) {
/* No such thread belonging this task*/
mutex_unlock(&TASK->udebug.lock);
return ENOENT;
}
 
/*
* Now we need to grab the thread's debug lock for synchronization
* of the threads stoppability/stop state.
*/
mutex_lock(&t->udebug.lock);
 
/* The big task mutex is no longer needed. */
mutex_unlock(&TASK->udebug.lock);
 
if (t->udebug.go != being_go) {
/* Not in debugging session or undesired GO state. */
mutex_unlock(&t->udebug.lock);
return EINVAL;
}
 
/* Only t->udebug.lock left. */
 
return EOK; /* All went well. */
}
 
/** End debugging operation on a thread. */
static void _thread_op_end(thread_t *t)
{
mutex_unlock(&t->udebug.lock);
}
 
/** Begin debugging the current task.
*
* Initiates a debugging session for the current task (and its threads).
* When the debugging session has started a reply will be sent to the
* UDEBUG_BEGIN call. This may happen immediately in this function if
* all the threads in this task are stoppable at the moment and in this
* case the function returns 1.
*
* Otherwise the function returns 0 and the reply will be sent as soon as
* all the threads become stoppable (i.e. they can be considered stopped).
*
* @param call The BEGIN call we are servicing.
* @return 0 (OK, but not done yet), 1 (done) or negative error code.
*/
int udebug_begin(call_t *call)
{
int reply;
 
thread_t *t;
link_t *cur;
 
LOG("udebug_begin()\n");
 
mutex_lock(&TASK->udebug.lock);
LOG("debugging task %llu\n", TASK->taskid);
 
if (TASK->udebug.dt_state != UDEBUG_TS_INACTIVE) {
mutex_unlock(&TASK->udebug.lock);
LOG("udebug_begin(): busy error\n");
 
return EBUSY;
}
 
TASK->udebug.dt_state = UDEBUG_TS_BEGINNING;
TASK->udebug.begin_call = call;
TASK->udebug.debugger = call->sender;
 
if (TASK->udebug.not_stoppable_count == 0) {
TASK->udebug.dt_state = UDEBUG_TS_ACTIVE;
TASK->udebug.begin_call = NULL;
reply = 1; /* immediate reply */
} else {
reply = 0; /* no reply */
}
/* Set udebug.active on all of the task's userspace threads. */
 
for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
t = list_get_instance(cur, thread_t, th_link);
 
mutex_lock(&t->udebug.lock);
if ((t->flags & THREAD_FLAG_USPACE) != 0)
t->udebug.active = true;
mutex_unlock(&t->udebug.lock);
}
 
mutex_unlock(&TASK->udebug.lock);
 
LOG("udebug_begin() done (%s)\n",
reply ? "reply" : "stoppability wait");
 
return reply;
}
 
/** Finish debugging the current task.
*
* Closes the debugging session for the current task.
* @return Zero on success or negative error code.
*/
int udebug_end(void)
{
int rc;
 
LOG("udebug_end()\n");
 
mutex_lock(&TASK->udebug.lock);
LOG("task %" PRIu64 "\n", TASK->taskid);
 
rc = udebug_task_cleanup(TASK);
 
mutex_unlock(&TASK->udebug.lock);
 
return rc;
}
 
/** Set the event mask.
*
* Sets the event mask that determines which events are enabled.
*
* @param mask Or combination of events that should be enabled.
* @return Zero on success or negative error code.
*/
int udebug_set_evmask(udebug_evmask_t mask)
{
LOG("udebug_set_mask()\n");
 
mutex_lock(&TASK->udebug.lock);
 
if (TASK->udebug.dt_state != UDEBUG_TS_ACTIVE) {
mutex_unlock(&TASK->udebug.lock);
LOG("udebug_set_mask(): not active debuging session\n");
 
return EINVAL;
}
 
TASK->udebug.evmask = mask;
 
mutex_unlock(&TASK->udebug.lock);
 
return 0;
}
 
/** Give thread GO.
*
* Upon recieving a go message, the thread is given GO. Being GO
* means the thread is allowed to execute userspace code (until
* a debugging event or STOP occurs, at which point the thread loses GO.
*
* @param t The thread to operate on (unlocked and need not be valid).
* @param call The GO call that we are servicing.
*/
int udebug_go(thread_t *t, call_t *call)
{
int rc;
 
/* On success, this will lock t->udebug.lock. */
rc = _thread_op_begin(t, false);
if (rc != EOK) {
return rc;
}
 
t->udebug.go_call = call;
t->udebug.go = true;
t->udebug.cur_event = 0; /* none */
 
/*
* Neither t's lock nor threads_lock may be held during wakeup.
*/
waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST);
 
_thread_op_end(t);
 
return 0;
}
 
/** Stop a thread (i.e. take its GO away)
*
* Generates a STOP event as soon as the thread becomes stoppable (i.e.
* can be considered stopped).
*
* @param t The thread to operate on (unlocked and need not be valid).
* @param call The GO call that we are servicing.
*/
int udebug_stop(thread_t *t, call_t *call)
{
int rc;
 
LOG("udebug_stop()\n");
 
/*
* On success, this will lock t->udebug.lock. Note that this makes sure
* the thread is not stopped.
*/
rc = _thread_op_begin(t, true);
if (rc != EOK) {
return rc;
}
 
/* Take GO away from the thread. */
t->udebug.go = false;
 
if (t->udebug.stoppable != true) {
/* Answer will be sent when the thread becomes stoppable. */
_thread_op_end(t);
return 0;
}
 
/*
* Answer GO call.
*/
LOG("udebug_stop - answering go call\n");
 
/* Make sure nobody takes this call away from us. */
call = t->udebug.go_call;
t->udebug.go_call = NULL;
 
IPC_SET_RETVAL(call->data, 0);
IPC_SET_ARG1(call->data, UDEBUG_EVENT_STOP);
LOG("udebug_stop/ipc_answer\n");
 
THREAD->udebug.cur_event = UDEBUG_EVENT_STOP;
 
_thread_op_end(t);
 
mutex_lock(&TASK->udebug.lock);
ipc_answer(&TASK->answerbox, call);
mutex_unlock(&TASK->udebug.lock);
 
LOG("udebog_stop/done\n");
return 0;
}
 
/** Read the list of userspace threads in the current task.
*
* The list takes the form of a sequence of thread hashes (i.e. the pointers
* to thread structures). A buffer of size @a buf_size is allocated and
* a pointer to it written to @a buffer. The sequence of hashes is written
* into this buffer.
*
* If the sequence is longer than @a buf_size bytes, only as much hashes
* as can fit are copied. The number of thread hashes copied is stored
* in @a n.
*
* The rationale for having @a buf_size is that this function is only
* used for servicing the THREAD_READ message, which always specifies
* a maximum size for the userspace buffer.
*
* @param buffer The buffer for storing thread hashes.
* @param buf_size Buffer size in bytes.
* @param n The actual number of hashes copied will be stored here.
*/
int udebug_thread_read(void **buffer, size_t buf_size, size_t *n)
{
thread_t *t;
link_t *cur;
unative_t tid;
unsigned copied_ids;
ipl_t ipl;
unative_t *id_buffer;
int flags;
size_t max_ids;
 
LOG("udebug_thread_read()\n");
 
/* Allocate a buffer to hold thread IDs */
id_buffer = malloc(buf_size, 0);
 
mutex_lock(&TASK->udebug.lock);
 
/* Verify task state */
if (TASK->udebug.dt_state != UDEBUG_TS_ACTIVE) {
mutex_unlock(&TASK->udebug.lock);
return EINVAL;
}
 
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
/* Copy down the thread IDs */
 
max_ids = buf_size / sizeof(unative_t);
copied_ids = 0;
 
/* FIXME: make sure the thread isn't past debug shutdown... */
for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
/* Do not write past end of buffer */
if (copied_ids >= max_ids) break;
 
t = list_get_instance(cur, thread_t, th_link);
 
spinlock_lock(&t->lock);
flags = t->flags;
spinlock_unlock(&t->lock);
 
/* Not interested in kernel threads. */
if ((flags & THREAD_FLAG_USPACE) != 0) {
/* Using thread struct pointer as identification hash */
tid = (unative_t) t;
id_buffer[copied_ids++] = tid;
}
}
 
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
 
mutex_unlock(&TASK->udebug.lock);
 
*buffer = id_buffer;
*n = copied_ids * sizeof(unative_t);
 
return 0;
}
 
/** Read the arguments of a system call.
*
* The arguments of the system call being being executed are copied
* to an allocated buffer and a pointer to it is written to @a buffer.
* The size of the buffer is exactly such that it can hold the maximum number
* of system-call arguments.
*
* Unless the thread is currently blocked in a SYSCALL_B or SYSCALL_E event,
* this function will fail with an EINVAL error code.
*
* @param buffer The buffer for storing thread hashes.
*/
int udebug_args_read(thread_t *t, void **buffer)
{
int rc;
unative_t *arg_buffer;
 
/* Prepare a buffer to hold the arguments. */
arg_buffer = malloc(6 * sizeof(unative_t), 0);
 
/* On success, this will lock t->udebug.lock. */
rc = _thread_op_begin(t, false);
if (rc != EOK) {
return rc;
}
 
/* Additionally we need to verify that we are inside a syscall. */
if (t->udebug.cur_event != UDEBUG_EVENT_SYSCALL_B &&
t->udebug.cur_event != UDEBUG_EVENT_SYSCALL_E) {
_thread_op_end(t);
return EINVAL;
}
 
/* Copy to a local buffer before releasing the lock. */
memcpy(arg_buffer, t->udebug.syscall_args, 6 * sizeof(unative_t));
 
_thread_op_end(t);
 
*buffer = arg_buffer;
return 0;
}
 
/** Read the memory of the debugged task.
*
* Reads @a n bytes from the address space of the debugged task, starting
* from @a uspace_addr. The bytes are copied into an allocated buffer
* and a pointer to it is written into @a buffer.
*
* @param uspace_addr Address from where to start reading.
* @param n Number of bytes to read.
* @param buffer For storing a pointer to the allocated buffer.
*/
int udebug_mem_read(unative_t uspace_addr, size_t n, void **buffer)
{
void *data_buffer;
int rc;
 
/* Verify task state */
mutex_lock(&TASK->udebug.lock);
 
if (TASK->udebug.dt_state != UDEBUG_TS_ACTIVE) {
mutex_unlock(&TASK->udebug.lock);
return EBUSY;
}
 
data_buffer = malloc(n, 0);
 
/* NOTE: this is not strictly from a syscall... but that shouldn't
* be a problem */
rc = copy_from_uspace(data_buffer, (void *)uspace_addr, n);
mutex_unlock(&TASK->udebug.lock);
 
if (rc != 0) return rc;
 
*buffer = data_buffer;
return 0;
}
 
/** @}
*/
/branches/dd/kernel/generic/src/udebug/udebug_ipc.c
0,0 → 1,343
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
* @{
*/
 
/**
* @file
* @brief Udebug IPC message handling.
*
* This module handles udebug IPC messages and calls the appropriate
* functions from the udebug_ops module which implement them.
*/
#include <proc/task.h>
#include <proc/thread.h>
#include <arch.h>
#include <errno.h>
#include <ipc/ipc.h>
#include <syscall/copy.h>
#include <udebug/udebug.h>
#include <udebug/udebug_ops.h>
#include <udebug/udebug_ipc.h>
 
int udebug_request_preprocess(call_t *call, phone_t *phone)
{
switch (IPC_GET_ARG1(call->data)) {
/* future UDEBUG_M_REGS_WRITE, UDEBUG_M_MEM_WRITE: */
default:
break;
}
 
return 0;
}
 
/** Process a BEGIN call.
*
* Initiates a debugging session for the current task. The reply
* to this call may or may not be sent before this function returns.
*
* @param call The call structure.
*/
static void udebug_receive_begin(call_t *call)
{
int rc;
 
rc = udebug_begin(call);
if (rc < 0) {
IPC_SET_RETVAL(call->data, rc);
ipc_answer(&TASK->kb.box, call);
return;
}
 
/*
* If the initialization of the debugging session has finished,
* send a reply.
*/
if (rc != 0) {
IPC_SET_RETVAL(call->data, 0);
ipc_answer(&TASK->kb.box, call);
}
}
 
/** Process an END call.
*
* Terminates the debugging session for the current task.
* @param call The call structure.
*/
static void udebug_receive_end(call_t *call)
{
int rc;
 
rc = udebug_end();
 
IPC_SET_RETVAL(call->data, rc);
ipc_answer(&TASK->kb.box, call);
}
 
/** Process a SET_EVMASK call.
*
* Sets an event mask for the current debugging session.
* @param call The call structure.
*/
static void udebug_receive_set_evmask(call_t *call)
{
int rc;
udebug_evmask_t mask;
 
mask = IPC_GET_ARG2(call->data);
rc = udebug_set_evmask(mask);
 
IPC_SET_RETVAL(call->data, rc);
ipc_answer(&TASK->kb.box, call);
}
 
 
/** Process a GO call.
*
* Resumes execution of the specified thread.
* @param call The call structure.
*/
static void udebug_receive_go(call_t *call)
{
thread_t *t;
int rc;
 
t = (thread_t *)IPC_GET_ARG2(call->data);
 
rc = udebug_go(t, call);
if (rc < 0) {
IPC_SET_RETVAL(call->data, rc);
ipc_answer(&TASK->kb.box, call);
return;
}
}
 
/** Process a STOP call.
*
* Suspends execution of the specified thread.
* @param call The call structure.
*/
static void udebug_receive_stop(call_t *call)
{
thread_t *t;
int rc;
 
t = (thread_t *)IPC_GET_ARG2(call->data);
 
rc = udebug_stop(t, call);
IPC_SET_RETVAL(call->data, rc);
ipc_answer(&TASK->kb.box, call);
}
 
/** Process a THREAD_READ call.
*
* Reads the list of hashes of the (userspace) threads in the current task.
* @param call The call structure.
*/
static void udebug_receive_thread_read(call_t *call)
{
unative_t uspace_addr;
unative_t to_copy;
unsigned total_bytes;
unsigned buf_size;
void *buffer;
size_t n;
int rc;
 
uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
buf_size = IPC_GET_ARG3(call->data); /* Dest. buffer size */
 
/*
* Read thread list. Variable n will be filled with actual number
* of threads times thread-id size.
*/
rc = udebug_thread_read(&buffer, buf_size, &n);
if (rc < 0) {
IPC_SET_RETVAL(call->data, rc);
ipc_answer(&TASK->kb.box, call);
return;
}
 
total_bytes = n;
 
/* Copy MAX(buf_size, total_bytes) bytes */
 
if (buf_size > total_bytes)
to_copy = total_bytes;
else
to_copy = buf_size;
 
/*
* Make use of call->buffer to transfer data to caller's userspace
*/
 
IPC_SET_RETVAL(call->data, 0);
/* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
same code in process_answer() can be used
(no way to distinguish method in answer) */
IPC_SET_ARG1(call->data, uspace_addr);
IPC_SET_ARG2(call->data, to_copy);
 
IPC_SET_ARG3(call->data, total_bytes);
call->buffer = buffer;
 
ipc_answer(&TASK->kb.box, call);
}
 
/** Process an ARGS_READ call.
*
* Reads the argument of a current syscall event (SYSCALL_B or SYSCALL_E).
* @param call The call structure.
*/
static void udebug_receive_args_read(call_t *call)
{
thread_t *t;
unative_t uspace_addr;
int rc;
void *buffer;
 
t = (thread_t *)IPC_GET_ARG2(call->data);
 
rc = udebug_args_read(t, &buffer);
if (rc != EOK) {
IPC_SET_RETVAL(call->data, rc);
ipc_answer(&TASK->kb.box, call);
return;
}
 
/*
* Make use of call->buffer to transfer data to caller's userspace
*/
 
uspace_addr = IPC_GET_ARG3(call->data);
 
IPC_SET_RETVAL(call->data, 0);
/* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
same code in process_answer() can be used
(no way to distinguish method in answer) */
IPC_SET_ARG1(call->data, uspace_addr);
IPC_SET_ARG2(call->data, 6 * sizeof(unative_t));
call->buffer = buffer;
 
ipc_answer(&TASK->kb.box, call);
}
 
/** Process an MEM_READ call.
*
* Reads memory of the current (debugged) task.
* @param call The call structure.
*/
static void udebug_receive_mem_read(call_t *call)
{
unative_t uspace_dst;
unative_t uspace_src;
unsigned size;
void *buffer;
int rc;
 
uspace_dst = IPC_GET_ARG2(call->data);
uspace_src = IPC_GET_ARG3(call->data);
size = IPC_GET_ARG4(call->data);
 
rc = udebug_mem_read(uspace_src, size, &buffer);
if (rc < 0) {
IPC_SET_RETVAL(call->data, rc);
ipc_answer(&TASK->kb.box, call);
return;
}
 
IPC_SET_RETVAL(call->data, 0);
/* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
same code in process_answer() can be used
(no way to distinguish method in answer) */
IPC_SET_ARG1(call->data, uspace_dst);
IPC_SET_ARG2(call->data, size);
call->buffer = buffer;
 
ipc_answer(&TASK->kb.box, call);
}
 
/** Handle a debug call received on the kernel answerbox.
*
* This is called by the kbox servicing thread. Verifies that the sender
* is indeed the debugger and calls the appropriate processing function.
*/
void udebug_call_receive(call_t *call)
{
int debug_method;
 
debug_method = IPC_GET_ARG1(call->data);
 
if (debug_method != UDEBUG_M_BEGIN) {
/*
* Verify that the sender is this task's debugger.
* Note that this is the only thread that could change
* TASK->debugger. Therefore no locking is necessary
* and the sender can be safely considered valid until
* control exits this function.
*/
if (TASK->udebug.debugger != call->sender) {
IPC_SET_RETVAL(call->data, EINVAL);
ipc_answer(&TASK->kb.box, call);
return;
}
}
 
switch (debug_method) {
case UDEBUG_M_BEGIN:
udebug_receive_begin(call);
break;
case UDEBUG_M_END:
udebug_receive_end(call);
break;
case UDEBUG_M_SET_EVMASK:
udebug_receive_set_evmask(call);
break;
case UDEBUG_M_GO:
udebug_receive_go(call);
break;
case UDEBUG_M_STOP:
udebug_receive_stop(call);
break;
case UDEBUG_M_THREAD_READ:
udebug_receive_thread_read(call);
break;
case UDEBUG_M_ARGS_READ:
udebug_receive_args_read(call);
break;
case UDEBUG_M_MEM_READ:
udebug_receive_mem_read(call);
break;
}
}
 
/** @}
*/
/branches/dd/kernel/Makefile
30,24 → 30,28
## Include configuration
#
 
-include ../version
-include Makefile.config
include ../version
-include ../Makefile.config
-include ../config.defs
 
INCLUDES = generic/include
OPTIMIZATION = 3
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
## Common compiler flags
#
 
DEFS = -D$(ARCH) -DARCH=\"$(ARCH)\" -DRELEASE=\"$(RELEASE)\" "-DNAME=\"$(NAME)\"" \
-DKERNEL
DEFS = -DKERNEL -DRELEASE=$(RELEASE) "-DNAME=$(NAME)"
 
GCC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) \
-fno-builtin -fomit-frame-pointer -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -Werror \
-nostdlib -nostdinc
GCC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) -imacros ../config.h \
-fno-builtin -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -Werror \
-nostdlib -nostdinc -pipe
 
ICC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) \
-fno-builtin -fomit-frame-pointer -Wall -Wmissing-prototypes -Werror \
ICC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) -imacros ../config.h \
-fno-builtin -Wall -Wmissing-prototypes -Werror \
-nostdlib -nostdinc \
-wd170
 
58,15 → 62,7
LFLAGS = -M
AFLAGS =
 
ifdef REVISION
DEFS += "-DREVISION=\"$(REVISION)\""
endif
 
ifdef TIMESTAMP
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\""
endif
 
-include arch/$(ARCH)/Makefile.inc
-include arch/$(KARCH)/Makefile.inc
-include genarch/Makefile.inc
 
## The at-sign
84,68 → 80,6
#
SYMTAB_SECTION=".section symtab.data, \"a\", $(ATSIGN)progbits;"
 
## Setup kernel configuration
#
ifeq ($(CONFIG_DEBUG),y)
DEFS += -DCONFIG_DEBUG
endif
 
ifeq ($(CONFIG_DEBUG_SPINLOCK),y)
DEFS += -DCONFIG_DEBUG_SPINLOCK
endif
 
ifeq ($(CONFIG_DEBUG_AS_WATCHPOINT),y)
DEFS += -DCONFIG_DEBUG_AS_WATCHPOINT
endif
 
ifeq ($(CONFIG_FPU_LAZY),y)
DEFS += -DCONFIG_FPU_LAZY
endif
 
ifeq ($(CONFIG_DEBUG_ALLREGS),y)
DEFS += -DCONFIG_DEBUG_ALLREGS
endif
 
ifeq ($(CONFIG_VHPT),y)
DEFS += -DCONFIG_VHPT
endif
 
ifeq ($(CONFIG_TSB),y)
DEFS += -DCONFIG_TSB
endif
 
ifeq ($(CONFIG_Z8530),y)
DEFS += -DCONFIG_Z8530
endif
 
ifeq ($(CONFIG_NS16550),y)
DEFS += -DCONFIG_NS16550
endif
 
ifeq ($(CONFIG_VIRT_IDX_DCACHE),y)
DEFS += -DCONFIG_VIRT_IDX_DCACHE
endif
 
ifeq ($(CONFIG_FB),y)
ifeq ($(ARCH),ia32)
DEFS += -DCONFIG_VESA_WIDTH=$(CONFIG_VESA_WIDTH)
DEFS += -DCONFIG_VESA_HEIGHT=$(CONFIG_VESA_HEIGHT)
DEFS += -DCONFIG_VESA_BPP=$(CONFIG_VESA_BPP)
endif
ifeq ($(ARCH),amd64)
DEFS += -DCONFIG_VESA_WIDTH=$(CONFIG_VESA_WIDTH)
DEFS += -DCONFIG_VESA_HEIGHT=$(CONFIG_VESA_HEIGHT)
DEFS += -DCONFIG_VESA_BPP=$(CONFIG_VESA_BPP)
endif
ifeq ($(ARCH),ia32xen)
DEFS += -DCONFIG_VESA_WIDTH=$(CONFIG_VESA_WIDTH)
DEFS += -DCONFIG_VESA_HEIGHT=$(CONFIG_VESA_HEIGHT)
DEFS += -DCONFIG_VESA_BPP=$(CONFIG_VESA_BPP)
endif
endif
 
## Simple detection for the type of the host system
#
HOST = $(shell uname)
170,6 → 104,7
OBJDUMP = $(BINUTILS_PREFIX)objdump
LIBDIR = /usr/lib
CFLAGS = $(GCC_CFLAGS)
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
endif
 
ifeq ($(COMPILER),icc_native)
181,6 → 116,7
OBJDUMP = objdump
LIBDIR = /usr/lib
CFLAGS = $(ICC_CFLAGS)
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
endif
 
ifeq ($(COMPILER),suncc_native)
192,6 → 128,8
OBJDUMP = $(BINUTILS_PREFIX)objdump
LIBDIR = /usr/lib
CFLAGS = $(SUNCC_CFLAGS)
DEFS += $(CONFIG_DEFS)
DEPEND_DEFS = $(DEFS)
endif
 
ifeq ($(COMPILER),gcc_cross)
203,6 → 141,7
OBJDUMP = $(TOOLCHAIN_DIR)/bin/$(TARGET)-objdump
LIBDIR = $(TOOLCHAIN_DIR)/lib
CFLAGS = $(GCC_CFLAGS)
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
endif
 
## Generic kernel sources
216,9 → 155,6
generic/src/adt/list.c \
generic/src/console/chardev.c \
generic/src/console/console.c \
generic/src/console/kconsole.c \
generic/src/console/klog.c \
generic/src/console/cmd.c \
generic/src/cpu/cpu.c \
generic/src/ddi/ddi.c \
generic/src/ddi/irq.c \
229,6 → 165,7
generic/src/main/uinit.c \
generic/src/main/version.c \
generic/src/main/shutdown.c \
generic/src/proc/program.c \
generic/src/proc/scheduler.c \
generic/src/proc/thread.c \
generic/src/proc/task.c \
248,6 → 185,7
generic/src/lib/func.c \
generic/src/lib/memstr.c \
generic/src/lib/sort.c \
generic/src/lib/string.c \
generic/src/lib/elf.c \
generic/src/lib/rd.c \
generic/src/printf/printf_core.c \
267,6 → 205,7
generic/src/synch/rwlock.c \
generic/src/synch/mutex.c \
generic/src/synch/semaphore.c \
generic/src/synch/smc.c \
generic/src/synch/waitq.c \
generic/src/synch/futex.c \
generic/src/smp/ipi.c \
278,11 → 217,30
generic/src/security/cap.c \
generic/src/sysinfo/sysinfo.c
 
## Kernel console support
#
 
ifeq ($(CONFIG_KCONSOLE),y)
GENERIC_SOURCES += \
generic/src/console/kconsole.c \
generic/src/console/cmd.c
endif
 
## Udebug interface sources
#
 
ifeq ($(CONFIG_UDEBUG),y)
GENERIC_SOURCES += \
generic/src/ipc/kbox.c \
generic/src/udebug/udebug.c \
generic/src/udebug/udebug_ops.c \
generic/src/udebug/udebug_ipc.c
endif
 
## Test sources
#
 
ifeq ($(CONFIG_TEST),y)
DEFS += -DCONFIG_TEST
CFLAGS += -Itest/
GENERIC_SOURCES += \
test/test.c \
289,17 → 247,12
test/atomic/atomic1.c \
test/btree/btree1.c \
test/avltree/avltree1.c \
test/debug/mips1.c \
test/fault/fault1.c \
test/fpu/fpu1.c \
test/fpu/sse1.c \
test/fpu/mips2.c \
test/mm/falloc1.c \
test/mm/falloc2.c \
test/mm/mapping1.c \
test/mm/slab1.c \
test/mm/slab2.c \
test/mm/purge1.c \
test/synch/rwlock1.c \
test/synch/rwlock2.c \
test/synch/rwlock3.c \
310,41 → 263,76
test/print/print1.c \
test/thread/thread1.c \
test/sysinfo/sysinfo1.c
ifeq ($(KARCH),mips32)
GENERIC_SOURCES += test/debug/mips1.c
else
GENERIC_SOURCES += test/debug/mips1_skip.c
endif
ifeq ($(KARCH),ia64)
GENERIC_SOURCES += test/mm/purge1.c
else
GENERIC_SOURCES += test/mm/purge1_skip.c
endif
ifeq ($(CONFIG_FPU),y)
ifeq ($(KARCH),ia32)
TEST_FPU1 = y
TEST_SSE1 = y
GENERIC_SOURCES += test/fpu/fpu1_x86.c
endif
ifeq ($(KARCH),amd64)
TEST_FPU1 = y
TEST_SSE1 = y
GENERIC_SOURCES += test/fpu/fpu1_x86.c
endif
ifeq ($(KARCH),ia64)
TEST_FPU1 = y
GENERIC_SOURCES += test/fpu/fpu1_ia64.c
endif
ifeq ($(KARCH),mips32)
TEST_MIPS2 = y
endif
endif
ifneq ($(TEST_FPU1),y)
GENERIC_SOURCES += test/fpu/fpu1_skip.c
endif
ifeq ($(TEST_SSE1),y)
GENERIC_SOURCES += test/fpu/sse1.c
else
GENERIC_SOURCES += test/fpu/sse1_skip.c
endif
ifeq ($(TEST_MIPS2),y)
GENERIC_SOURCES += test/fpu/mips2.c
else
GENERIC_SOURCES += test/fpu/mips2_skip.c
endif
endif
 
## Experimental features
#
 
ifeq ($(CONFIG_EXPERIMENTAL),y)
GENERIC_SOURCES += generic/src/lib/objc_ext.c \
generic/src/lib/objc.c
EXTRA_OBJECTS = $(LIBDIR)/libobjc.a
EXTRA_FLAGS += -x objective-c
endif
 
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES)))
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES)))
GENARCH_OBJECTS := $(addsuffix .o,$(basename $(GENARCH_SOURCES)))
 
.PHONY: all build config distclean clean archlinks depend disasm
.PHONY: all build clean archlinks depend disasm
 
all:
../tools/config.py kernel.config default $(ARCH) $(COMPILER) $(CONFIG_DEBUG) $(MACHINE)
all: ../Makefile.config ../config.h ../config.defs
-rm Makefile.depend
$(MAKE) -C . build
 
build: kernel.bin disasm
 
config:
-rm Makefile.depend
../tools/config.py kernel.config
 
-include Makefile.depend
 
distclean: clean
-rm Makefile.config
 
clean:
-rm -f kernel.bin kernel.raw kernel.map kernel.map.pre kernel.objdump kernel.disasm generic/src/debug/real_map.bin Makefile.depend* generic/include/arch generic/include/genarch arch/$(ARCH)/_link.ld
-rm -f kernel.bin kernel.raw kernel.map kernel.map.pre kernel.objdump kernel.disasm generic/src/debug/real_map.bin Makefile.depend* generic/include/arch generic/include/genarch arch/$(KARCH)/_link.ld
find generic/src/ arch/*/src/ genarch/src/ test/ -name '*.o' -follow -exec rm \{\} \;
for arch in arch/* ; do \
[ -e $$arch/_link.ld ] && rm $$arch/_link.ld 2>/dev/null ; \
351,24 → 339,24
done ; exit 0
 
archlinks:
ln -sfn ../../arch/$(ARCH)/include/ generic/include/arch
ln -sfn ../../arch/$(KARCH)/include/ generic/include/arch
ln -sfn ../../genarch/include/ generic/include/genarch
 
depend: archlinks
-makedepend $(DEFS) $(CFLAGS) -f - $(ARCH_SOURCES) $(GENARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
 
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in
arch/$(KARCH)/_link.ld: arch/$(KARCH)/_link.ld.in
$(GCC) $(DEFS) $(GCC_CFLAGS) -D__ASM__ -D__LINKER__ -E -x c $< | grep -v "^\#" > $@
 
generic/src/debug/real_map.bin: depend arch/$(ARCH)/_link.ld $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS)
generic/src/debug/real_map.bin: depend arch/$(KARCH)/_link.ld $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS)
echo $(SYMTAB_SECTION) | $(AS) $(AFLAGS) -o generic/src/debug/empty_map.o
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/empty_map.o -o $@ -Map kernel.map.pre
$(LD) -T arch/$(KARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/empty_map.o -o $@ -Map kernel.map.pre
$(OBJDUMP) -t $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) > kernel.objdump
tools/genmap.py kernel.map.pre kernel.objdump generic/src/debug/real_map.bin
# Do it once again, this time to get correct even the symbols
# on architectures, that have bss after symtab
echo $(SYMTAB_SECTION)" .incbin \"$@\"" | $(AS) $(AFLAGS) -o generic/src/debug/sizeok_map.o
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/sizeok_map.o -o $@ -Map kernel.map.pre
$(LD) -T arch/$(KARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/sizeok_map.o -o $@ -Map kernel.map.pre
$(OBJDUMP) -t $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) > kernel.objdump
tools/genmap.py kernel.map.pre kernel.objdump generic/src/debug/real_map.bin
 
375,8 → 363,8
generic/src/debug/real_map.o: generic/src/debug/real_map.bin
echo $(SYMTAB_SECTION)" .incbin \"$<\"" | $(AS) $(AFLAGS) -o $@
 
kernel.raw: depend arch/$(ARCH)/_link.ld $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) generic/src/debug/real_map.o
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/real_map.o -o $@ -Map kernel.map
kernel.raw: depend arch/$(KARCH)/_link.ld $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) generic/src/debug/real_map.o
$(LD) -T arch/$(KARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/real_map.o -o $@ -Map kernel.map
 
kernel.bin: kernel.raw
$(OBJCOPY) -O $(BFD) kernel.raw kernel.bin
390,5 → 378,15
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
#
# The FPU tests are the only objects for which we allow the compiler to generate
# FPU instructions.
#
test/fpu/%.o: test/fpu/%.c
$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) -c $< -o $@
 
#
# Ordinary objects.
#
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) -c $< -o $@
$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) $(FPU_NO_CFLAGS) -c $< -o $@
/branches/dd/kernel/arch/ppc64/_link.ld.in
File deleted
/branches/dd/kernel/arch/ppc64/include/arg.h
File deleted
/branches/dd/kernel/arch/ppc64/include/atomic.h
File deleted
/branches/dd/kernel/arch/ppc64/include/arch.h
File deleted
/branches/dd/kernel/arch/ppc64/include/proc/task.h
File deleted
/branches/dd/kernel/arch/ppc64/include/proc/thread.h
File deleted
/branches/dd/kernel/arch/ppc64/include/boot/boot.h
File deleted
/branches/dd/kernel/arch/ppc64/include/faddr.h
File deleted
/branches/dd/kernel/arch/ppc64/include/asm.h
File deleted
/branches/dd/kernel/arch/ppc64/include/mm/page.h
File deleted
/branches/dd/kernel/arch/ppc64/include/mm/asid.h
File deleted
/branches/dd/kernel/arch/ppc64/include/mm/tlb.h
File deleted
/branches/dd/kernel/arch/ppc64/include/mm/as.h
File deleted
/branches/dd/kernel/arch/ppc64/include/mm/frame.h
File deleted
/branches/dd/kernel/arch/ppc64/include/context.h
File deleted
/branches/dd/kernel/arch/ppc64/include/debug.h
File deleted
/branches/dd/kernel/arch/ppc64/include/barrier.h
File deleted
/branches/dd/kernel/arch/ppc64/include/cpu.h
File deleted
/branches/dd/kernel/arch/ppc64/include/drivers/pic.h
File deleted
/branches/dd/kernel/arch/ppc64/include/asm/regname.h
File deleted
/branches/dd/kernel/arch/ppc64/include/context_offset.h
File deleted
/branches/dd/kernel/arch/ppc64/include/interrupt.h
File deleted
/branches/dd/kernel/arch/ppc64/include/fpu_context.h
File deleted
/branches/dd/kernel/arch/ppc64/include/exception.h
File deleted
/branches/dd/kernel/arch/ppc64/include/cycle.h
File deleted
/branches/dd/kernel/arch/ppc64/include/byteorder.h
File deleted
/branches/dd/kernel/arch/ppc64/include/cpuid.h
File deleted
/branches/dd/kernel/arch/ppc64/include/types.h
File deleted
/branches/dd/kernel/arch/ppc64/include/elf.h
File deleted
/branches/dd/kernel/arch/ppc64/include/memstr.h
File deleted
/branches/dd/kernel/arch/ppc64/Makefile.inc
File deleted
/branches/dd/kernel/arch/ppc64/src/context.S
File deleted
/branches/dd/kernel/arch/ppc64/src/debug/panic.s
File deleted
/branches/dd/kernel/arch/ppc64/src/cpu/cpu.c
File deleted
/branches/dd/kernel/arch/ppc64/src/mm/tlb.c
File deleted
/branches/dd/kernel/arch/ppc64/src/mm/as.c
File deleted
/branches/dd/kernel/arch/ppc64/src/mm/frame.c
File deleted
/branches/dd/kernel/arch/ppc64/src/mm/page.c
File deleted
/branches/dd/kernel/arch/ppc64/src/dummy.s
File deleted
/branches/dd/kernel/arch/ppc64/src/interrupt.c
File deleted
/branches/dd/kernel/arch/ppc64/src/ppc64.c
File deleted
/branches/dd/kernel/arch/ppc64/src/drivers/pic.c
File deleted
/branches/dd/kernel/arch/ppc64/src/exception.S
File deleted
/branches/dd/kernel/arch/ppc64/src/fpu_context.S
File deleted
/branches/dd/kernel/arch/ppc64/src/ddi/ddi.c
File deleted
/branches/dd/kernel/arch/ppc64/src/asm.S
File deleted
/branches/dd/kernel/arch/ppc64/src/proc/scheduler.c
File deleted
/branches/dd/kernel/arch/ppc64/src/boot/boot.S
File deleted
/branches/dd/kernel/arch/ia32xen/_link.ld.in
File deleted
/branches/dd/kernel/arch/ia32xen/include/hypercall.h
File deleted
/branches/dd/kernel/arch/ia32xen/include/mm/asid.h
File deleted
/branches/dd/kernel/arch/ia32xen/include/mm/tlb.h
File deleted
/branches/dd/kernel/arch/ia32xen/include/mm/as.h
File deleted
/branches/dd/kernel/arch/ia32xen/include/mm/frame.h
File deleted
/branches/dd/kernel/arch/ia32xen/include/mm/page.h
File deleted
/branches/dd/kernel/arch/ia32xen/include/debugger.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/context.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/barrier.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/debug.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/cpu.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/drivers/xconsole.h
File deleted
/branches/dd/kernel/arch/ia32xen/include/context_offset.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/interrupt.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/fpu_context.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/cycle.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/byteorder.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/types.h
File deleted
/branches/dd/kernel/arch/ia32xen/include/cpuid.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/elf.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/bios
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/memstr.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/smp
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/arg.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/ddi
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/pm.h
File deleted
/branches/dd/kernel/arch/ia32xen/include/atomic.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/arch.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/proc
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/faddr.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/include/asm.h
File deleted
/branches/dd/kernel/arch/ia32xen/Makefile.inc
File deleted
/branches/dd/kernel/arch/ia32xen/src/mm/tlb.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/mm/as.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/mm/frame.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/mm/page.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/userspace.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/atomic.S
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/src/interrupt.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/drivers/xconsole.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/fpu_context.c
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/src/asm.S
File deleted
/branches/dd/kernel/arch/ia32xen/src/context.S
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/src/debug
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/src/cpu
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/src/ia32xen.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/bios
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/src/pm.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/delay.s
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/src/smp/apic.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/smp/mps.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/smp/smp.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/smp/ipi.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/ddi
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/ia32xen/src/boot/boot.S
File deleted
/branches/dd/kernel/arch/ia32xen/src/proc/task.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/proc/thread.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/proc/scheduler.c
File deleted
/branches/dd/kernel/arch/ia32xen/src/debugger.c
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/sparc64/_link.ld.in
1,8 → 1,8
/** SPARC64 linker script
*
* It is ELF format, but its only section looks like this:
* kernel text
* kernel data
* kernel text
* kernel data
*
*/
 
11,7 → 11,7
ENTRY(kernel_image_start)
 
SECTIONS {
.image VMA: AT (LMA) {
.image VMA: AT (LMA) {
ktext_start = .;
*(K_TEXT_START)
*(.text);
21,23 → 21,23
*(K_DATA_START)
*(.rodata);
*(.rodata.*);
*(.data); /* initialized data */
*(.data); /* initialized data */
*(.sdata);
*(.sdata2);
*(.sbss);
. = ALIGN(8);
hardcoded_ktext_size = .;
QUAD(ktext_end - ktext_start);
QUAD(ktext_end - ktext_start);
hardcoded_kdata_size = .;
QUAD(kdata_end - kdata_start);
hardcoded_load_address = .;
QUAD(VMA);
*(.bss); /* uninitialized static variables */
*(COMMON); /* global variables */
 
*(.bss); /* uninitialized static variables */
*(COMMON); /* global variables */
symbol_table = .;
*(symtab.*); /* Symbol table, must be LAST symbol!*/
 
*(symtab.*); /* Symbol table, must be LAST symbol!*/
kdata_end = .;
}
44,5 → 44,5
/DISCARD/ : {
*(*);
}
 
}
/branches/dd/kernel/arch/sparc64/include/regdef.h
55,8 → 55,11
#define WSTATE_NORMAL(n) (n)
#define WSTATE_OTHER(n) ((n) << 3)
 
#define UPA_CONFIG_MID_SHIFT 17
#define UPA_CONFIG_MID_MASK 0x1f
/*
* The following definitions concern the UPA_CONFIG register on US and the
* FIREPLANE_CONFIG register on US3.
*/
#define ICBUS_CONFIG_MID_SHIFT 17
 
#endif
 
/branches/dd/kernel/arch/sparc64/include/cpu_node.h
0,0 → 1,59
/*
* Copyright (c) 2005 Pavel Rimsky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64
* @{
*/
/** @file
*/
 
#ifndef KERN_sparc64_CPU_NODE_H_
#define KERN_sparc64_CPU_NODE_H_
 
#include <genarch/ofw/ofw_tree.h>
 
 
/** Finds the parent node of all the CPU nodes (nodes named "cpu" or "cmp").
*
* Depending on the machine type (and possibly the OFW version), CPUs can be
* at "/" or at "/ssm@0,0".
*/
static inline ofw_tree_node_t *cpus_parent(void)
{
ofw_tree_node_t *parent;
parent = ofw_tree_find_child(ofw_tree_lookup("/"), "ssm@0,0");
if (parent == NULL)
parent = ofw_tree_lookup("/");
return parent;
}
 
#endif
 
/** @}
*/
 
/branches/dd/kernel/arch/sparc64/include/fpu_context.h
37,7 → 37,6
 
#include <arch/types.h>
 
#define ARCH_HAS_FPU
#define FPU_CONTEXT_ALIGN 8
 
typedef struct {
/branches/dd/kernel/arch/sparc64/include/types.h
35,10 → 35,6
#ifndef KERN_sparc64_TYPES_H_
#define KERN_sparc64_TYPES_H_
 
#define NULL 0
#define false 0
#define true 1
 
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
61,13 → 57,34
typedef uint64_t unative_t;
typedef int64_t native_t;
 
typedef uint8_t bool;
typedef uint64_t thread_id_t;
typedef uint64_t task_id_t;
typedef uint32_t context_id_t;
typedef struct {
} fncptr_t;
 
typedef int32_t inr_t;
typedef int32_t devno_t;
/**< Formats for uintptr_t, size_t, count_t and index_t */
#define PRIp "llx"
#define PRIs "llu"
#define PRIc "llu"
#define PRIi "llu"
 
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */
#define PRId8 "d"
#define PRId16 "d"
#define PRId32 "d"
#define PRId64 "lld"
#define PRIdn "lld"
 
#define PRIu8 "u"
#define PRIu16 "u"
#define PRIu32 "u"
#define PRIu64 "llu"
#define PRIun "llu"
 
#define PRIx8 "x"
#define PRIx16 "x"
#define PRIx32 "x"
#define PRIx64 "llx"
#define PRIxn "llx"
 
typedef uint8_t asi_t;
 
#endif
/branches/dd/kernel/arch/sparc64/include/memstr.h
37,10 → 37,10
 
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt))
 
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x);
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x);
extern void memsetw(void *dst, size_t cnt, uint16_t x);
extern void memsetb(void *dst, size_t cnt, uint8_t x);
 
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt);
extern int memcmp(const void *a, const void *b, size_t cnt);
 
#endif
 
/branches/dd/kernel/arch/sparc64/include/atomic.h
37,6 → 37,7
 
#include <arch/barrier.h>
#include <arch/types.h>
#include <preemption.h>
 
/** Atomic add operation.
*
56,7 → 57,8
 
a = *((uint64_t *) x);
b = a + i;
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)), "+r" (b) : "r" (a));
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)),
"+r" (b) : "r" (a));
} while (a != b);
 
return a;
97,7 → 99,8
uint64_t v = 1;
volatile uintptr_t x = (uint64_t) &val->count;
 
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *) x)), "+r" (v) : "r" (0));
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *) x)),
"+r" (v) : "r" (0));
 
return v;
}
109,6 → 112,8
 
volatile uintptr_t x = (uint64_t) &val->count;
 
preemption_disable();
 
asm volatile (
"0:\n"
"casx %0, %3, %1\n"
/branches/dd/kernel/arch/sparc64/include/boot/boot.h
48,9 → 48,12
#define TASKMAP_MAX_RECORDS 32
#define MEMMAP_MAX_RECORDS 32
 
#define BOOTINFO_TASK_NAME_BUFLEN 32
 
typedef struct {
void * addr;
uint32_t size;
char name[BOOTINFO_TASK_NAME_BUFLEN];
} utask_t;
 
typedef struct {
/branches/dd/kernel/arch/sparc64/include/arch.h
41,10 → 41,16
#define ASI_AIUS 0x11 /** Access to secondary context with user privileges. */
#define ASI_NUCLEUS_QUAD_LDD 0x24 /** ASI for 16-byte atomic loads. */
#define ASI_DCACHE_TAG 0x47 /** ASI D-Cache Tag. */
#define ASI_UPA_CONFIG 0x4a /** ASI of the UPA_CONFIG register. */
#define ASI_ICBUS_CONFIG 0x4a /** ASI of the UPA_CONFIG/FIREPLANE_CONFIG register. */
 
#define NWINDOWS 8 /** Number of register window sets. */
 
#ifndef __ASM__
 
extern void arch_pre_main(void);
 
#endif /* __ASM__ */
 
#endif
 
/** @}
/branches/dd/kernel/arch/sparc64/include/asm.h
37,11 → 37,61
 
#include <arch/arch.h>
#include <arch/types.h>
#include <typedefs.h>
#include <align.h>
#include <arch/register.h>
#include <config.h>
#include <arch/stack.h>
#include <arch/barrier.h>
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
memory_barrier();
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
memory_barrier();
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
memory_barrier();
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
uint8_t rv;
 
rv = *port;
memory_barrier();
 
return rv;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
uint16_t rv;
 
rv = *port;
memory_barrier();
 
return rv;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
uint32_t rv;
 
rv = *port;
memory_barrier();
 
return rv;
}
 
/** Read Processor State register.
*
* @return Value of PSTATE register.
86,6 → 136,28
asm volatile ("wr %0, %1, %%tick_cmpr\n" : : "r" (v), "i" (0));
}
 
/** Read STICK_compare Register.
*
* @return Value of STICK_compare register.
*/
static inline uint64_t stick_compare_read(void)
{
uint64_t v;
asm volatile ("rd %%asr25, %0\n" : "=r" (v));
return v;
}
 
/** Write STICK_compare Register.
*
* @param v New value of STICK_comapre register.
*/
static inline void stick_compare_write(uint64_t v)
{
asm volatile ("wr %0, %1, %%asr25\n" : : "r" (v), "i" (0));
}
 
/** Read TICK Register.
*
* @return Value of TICK register.
357,15 → 429,6
asm volatile ("wrpr %g0, %g0, %tl\n");
}
 
/** Read UPA_CONFIG register.
*
* @return Value of the UPA_CONFIG register.
*/
static inline uint64_t upa_config_read(void)
{
return asi_u64_read(ASI_UPA_CONFIG, 0);
}
 
extern void cpu_halt(void);
extern void cpu_sleep(void);
extern void asm_delay_loop(const uint32_t usec);
/branches/dd/kernel/arch/sparc64/include/trap/syscall.h
31,26 → 31,14
*/
/**
* @file
* @brief This file contains the trap_instruction handler.
*
* The trap_instruction trap is used to implement syscalls.
* @brief
*/
 
#ifndef KERN_sparc64_SYSCALL_TRAP_H_
#define KERN_sparc64_SYSCALL_TRAP_H_
 
#define TT_TRAP_INSTRUCTION(n) (0x100 + (n))
#define TT_TRAP_INSTRUCTION_LAST TT_TRAP_INSTRUCTION(127)
#define TT_TRAP_INSTRUCTION_0 0x100
 
#ifdef __ASM__
 
.macro TRAP_INSTRUCTION n
ba trap_instruction_handler
mov TT_TRAP_INSTRUCTION(\n) - TT_TRAP_INSTRUCTION(0), %g2
.endm
 
#endif /* __ASM__ */
 
#endif
 
/** @}
/branches/dd/kernel/arch/sparc64/include/trap/regwin.h
39,6 → 39,7
 
#include <arch/stack.h>
#include <arch/arch.h>
#include <align.h>
 
#define TT_CLEAN_WINDOW 0x24
#define TT_SPILL_0_NORMAL 0x80 /* kernel spills */
72,6 → 73,11
#define I6_OFFSET 112
#define I7_OFFSET 120
 
/* Uspace Window Buffer constants. */
#define UWB_SIZE ((NWINDOWS - 1) * STACK_WINDOW_SAVE_AREA_SIZE)
#define UWB_ALIGNMENT 1024
#define UWB_ASIZE ALIGN_UP(UWB_SIZE, UWB_ALIGNMENT)
 
#ifdef __ASM__
 
/*
/branches/dd/kernel/arch/sparc64/include/trap/interrupt.h
49,21 → 49,43
 
 
/* Interrupt ASI registers. */
#define ASI_UDB_INTR_W 0x77
#define ASI_INTR_W 0x77
#define ASI_INTR_DISPATCH_STATUS 0x48
#define ASI_UDB_INTR_R 0x7f
#define ASI_INTR_R 0x7f
#define ASI_INTR_RECEIVE 0x49
 
/* VA's used with ASI_UDB_INTR_W register. */
/* VA's used with ASI_INTR_W register. */
#if defined (US)
#define ASI_UDB_INTR_W_DATA_0 0x40
#define ASI_UDB_INTR_W_DATA_1 0x50
#define ASI_UDB_INTR_W_DATA_2 0x60
#define ASI_UDB_INTR_W_DISPATCH 0x70
#elif defined (US3)
#define VA_INTR_W_DATA_0 0x40
#define VA_INTR_W_DATA_1 0x48
#define VA_INTR_W_DATA_2 0x50
#define VA_INTR_W_DATA_3 0x58
#define VA_INTR_W_DATA_4 0x60
#define VA_INTR_W_DATA_5 0x68
#define VA_INTR_W_DATA_6 0x80
#define VA_INTR_W_DATA_7 0x88
#endif
#define VA_INTR_W_DISPATCH 0x70
 
/* VA's used with ASI_UDB_INTR_R register. */
/* VA's used with ASI_INTR_R register. */
#if defined(US)
#define ASI_UDB_INTR_R_DATA_0 0x40
#define ASI_UDB_INTR_R_DATA_1 0x50
#define ASI_UDB_INTR_R_DATA_2 0x60
#elif defined (US3)
#define VA_INTR_R_DATA_0 0x40
#define VA_INTR_R_DATA_1 0x48
#define VA_INTR_R_DATA_2 0x50
#define VA_INTR_R_DATA_3 0x58
#define VA_INTR_R_DATA_4 0x60
#define VA_INTR_R_DATA_5 0x68
#define VA_INTR_R_DATA_6 0x80
#define VA_INTR_R_DATA_7 0x88
#endif
 
/* Shifts in the Interrupt Vector Dispatch virtual address. */
#define INTR_VEC_DISPATCH_MID_SHIFT 14
/branches/dd/kernel/arch/sparc64/include/mm/frame.h
59,8 → 59,13
union frame_address {
uintptr_t address;
struct {
#if defined (US)
unsigned : 23;
uint64_t pfn : 28; /**< Physical Frame Number. */
#elif defined (US3)
unsigned : 21;
uint64_t pfn : 30; /**< Physical Frame Number. */
#endif
unsigned offset : 13; /**< Offset. */
} __attribute__ ((packed));
};
/branches/dd/kernel/arch/sparc64/include/mm/page.h
53,11 → 53,6
 
#define MMU_PAGES_PER_PAGE (1 << (PAGE_WIDTH - MMU_PAGE_WIDTH))
 
/*
* With 16K pages, there is only one page color.
*/
#define PAGE_COLOR_BITS 0 /**< 14 - 14; 2^14 == 16K == alias boundary. */
 
#ifdef KERNEL
 
#ifndef __ASM__
/branches/dd/kernel/arch/sparc64/include/mm/tte.h
50,6 → 50,7
 
#include <arch/types.h>
 
/* TTE tag's VA_tag field contains bits <63:VA_TAG_PAGE_SHIFT> of the VA */
#define VA_TAG_PAGE_SHIFT 22
 
/** Translation Table Entry - Tag. */
75,8 → 76,13
unsigned nfo : 1; /**< No-Fault-Only. */
unsigned ie : 1; /**< Invert Endianness. */
unsigned soft2 : 9; /**< Software defined field. */
#if defined (US)
unsigned diag : 9; /**< Diagnostic data. */
unsigned pfn : 28; /**< Physical Address bits, bits 40:13. */
#elif defined (US3)
unsigned : 7; /**< Reserved. */
unsigned pfn : 30; /**< Physical Address bits, bits 42:13 */
#endif
unsigned soft : 6; /**< Software defined field. */
unsigned l : 1; /**< Lock. */
unsigned cp : 1; /**< Cacheable in physically indexed cache. */
/branches/dd/kernel/arch/sparc64/include/mm/cache_spec.h
0,0 → 1,58
/*
* Copyright (c) 2008 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64mm
* @{
*/
/** @file
*/
 
#ifndef KERN_sparc64_CACHE_SPEC_H_
#define KERN_sparc64_CACHE_SPEC_H_
 
/*
* The following macros are valid for the following processors:
*
* UltraSPARC, UltraSPARC II, UltraSPARC IIi, UltraSPARC III,
* UltraSPARC III+, UltraSPARC IV, UltraSPARC IV+
*
* Should we support other UltraSPARC processors, we need to make sure that
* the macros are defined correctly for them.
*/
#if defined (US)
#define DCACHE_SIZE (16 * 1024)
#elif defined (US3)
#define DCACHE_SIZE (64 * 1024)
#endif
#define DCACHE_LINE_SIZE 32
 
#endif
 
/** @}
*/
/branches/dd/kernel/arch/sparc64/include/mm/mmu.h
35,8 → 35,10
#ifndef KERN_sparc64_MMU_H_
#define KERN_sparc64_MMU_H_
 
#if defined(US)
/* LSU Control Register ASI. */
#define ASI_LSU_CONTROL_REG 0x45 /**< Load/Store Unit Control Register. */
#endif
 
/* I-MMU ASIs. */
#define ASI_IMMU 0x50
52,7 → 54,12
#define VA_IMMU_SFSR 0x18 /**< IMMU sync fault status register. */
#define VA_IMMU_TSB_BASE 0x28 /**< IMMU TSB base register. */
#define VA_IMMU_TAG_ACCESS 0x30 /**< IMMU TLB tag access register. */
#if defined (US3)
#define VA_IMMU_PRIMARY_EXTENSION 0x48 /**< IMMU TSB primary extension register */
#define VA_IMMU_NUCLEUS_EXTENSION 0x58 /**< IMMU TSB nucleus extension register */
#endif
 
 
/* D-MMU ASIs. */
#define ASI_DMMU 0x58
#define ASI_DMMU_TSB_8KB_PTR_REG 0x59
73,6 → 80,11
#define VA_DMMU_TAG_ACCESS 0x30 /**< DMMU TLB tag access register. */
#define VA_DMMU_VA_WATCHPOINT_REG 0x38 /**< DMMU VA data watchpoint register. */
#define VA_DMMU_PA_WATCHPOINT_REG 0x40 /**< DMMU PA data watchpoint register. */
#if defined (US3)
#define VA_DMMU_PRIMARY_EXTENSION 0x48 /**< DMMU TSB primary extension register */
#define VA_DMMU_SECONDARY_EXTENSION 0x50 /**< DMMU TSB secondary extension register */
#define VA_DMMU_NUCLEUS_EXTENSION 0x58 /**< DMMU TSB nucleus extension register */
#endif
 
#ifndef __ASM__
 
80,6 → 92,7
#include <arch/barrier.h>
#include <arch/types.h>
 
#if defined(US)
/** LSU Control Register. */
typedef union {
uint64_t value;
100,6 → 113,7
} __attribute__ ((packed));
} lsu_cr_reg_t;
#endif /* US */
 
#endif /* !def __ASM__ */
 
/branches/dd/kernel/arch/sparc64/include/mm/tlb.h
35,9 → 35,17
#ifndef KERN_sparc64_TLB_H_
#define KERN_sparc64_TLB_H_
 
#if defined (US)
#define ITLB_ENTRY_COUNT 64
#define DTLB_ENTRY_COUNT 64
#define DTLB_MAX_LOCKED_ENTRIES DTLB_ENTRY_COUNT
#endif
 
/** TLB_DSMALL is the only of the three DMMUs that can hold locked entries. */
#if defined (US3)
#define DTLB_MAX_LOCKED_ENTRIES 16
#endif
 
#define MEM_CONTEXT_KERNEL 0
#define MEM_CONTEXT_TEMP 1
 
53,6 → 61,9
/* TLB Demap Operation types. */
#define TLB_DEMAP_PAGE 0
#define TLB_DEMAP_CONTEXT 1
#if defined (US3)
#define TLB_DEMAP_ALL 2
#endif
 
#define TLB_DEMAP_TYPE_SHIFT 6
 
61,6 → 72,18
#define TLB_DEMAP_SECONDARY 1
#define TLB_DEMAP_NUCLEUS 2
 
/* There are more TLBs in one MMU in US3, their codes are defined here. */
#if defined (US3)
/* D-MMU: one small (16-entry) TLB and two big (512-entry) TLBs */
#define TLB_DSMALL 0
#define TLB_DBIG_0 2
#define TLB_DBIG_1 3
/* I-MMU: one small (16-entry) TLB and one big TLB */
#define TLB_ISMALL 0
#define TLB_IBIG 2
#endif
 
#define TLB_DEMAP_CONTEXT_SHIFT 4
 
/* TLB Tag Access shifts */
76,6 → 99,8
#include <arch/asm.h>
#include <arch/barrier.h>
#include <arch/types.h>
#include <arch/register.h>
#include <arch/cpu.h>
 
union tlb_context_reg {
uint64_t v;
90,6 → 115,9
typedef tte_data_t tlb_data_t;
 
/** I-/D-TLB Data Access Address in Alternate Space. */
 
#if defined (US)
 
union tlb_data_access_addr {
uint64_t value;
struct {
98,9 → 126,54
unsigned : 3;
} __attribute__ ((packed));
};
typedef union tlb_data_access_addr tlb_data_access_addr_t;
typedef union tlb_data_access_addr tlb_tag_read_addr_t;
typedef union tlb_data_access_addr dtlb_data_access_addr_t;
typedef union tlb_data_access_addr dtlb_tag_read_addr_t;
typedef union tlb_data_access_addr itlb_data_access_addr_t;
typedef union tlb_data_access_addr itlb_tag_read_addr_t;
 
#elif defined (US3)
 
/*
* In US3, I-MMU and D-MMU have different formats of the data
* access register virtual address. In the corresponding
* structures the member variable for the entry number is
* called "local_tlb_entry" - it contrasts with the "tlb_entry"
* for the US data access register VA structure. The rationale
* behind this is to prevent careless mistakes in the code
* caused by setting only the entry number and not the TLB
* number in the US3 code (when taking the code from US).
*/
 
union dtlb_data_access_addr {
uint64_t value;
struct {
uint64_t : 45;
unsigned : 1;
unsigned tlb_number : 2;
unsigned : 4;
unsigned local_tlb_entry : 9;
unsigned : 3;
} __attribute__ ((packed));
};
typedef union dtlb_data_access_addr dtlb_data_access_addr_t;
typedef union dtlb_data_access_addr dtlb_tag_read_addr_t;
 
union itlb_data_access_addr {
uint64_t value;
struct {
uint64_t : 45;
unsigned : 1;
unsigned tlb_number : 2;
unsigned : 6;
unsigned local_tlb_entry : 7;
unsigned : 3;
} __attribute__ ((packed));
};
typedef union itlb_data_access_addr itlb_data_access_addr_t;
typedef union itlb_data_access_addr itlb_tag_read_addr_t;
 
#endif
 
/** I-/D-TLB Tag Read Register. */
union tlb_tag_read_reg {
uint64_t value;
118,8 → 191,13
uint64_t value;
struct {
uint64_t vpn: 51; /**< Virtual Address bits 63:13. */
#if defined (US)
unsigned : 6; /**< Ignored. */
unsigned type : 1; /**< The type of demap operation. */
#elif defined (US3)
unsigned : 5; /**< Ignored. */
unsigned type: 2; /**< The type of demap operation. */
#endif
unsigned context : 2; /**< Context register selection. */
unsigned : 4; /**< Zero. */
} __attribute__ ((packed));
130,10 → 208,19
union tlb_sfsr_reg {
uint64_t value;
struct {
#if defined (US)
unsigned long : 40; /**< Implementation dependent. */
unsigned asi : 8; /**< ASI. */
unsigned : 2;
unsigned ft : 7; /**< Fault type. */
#elif defined (US3)
unsigned long : 39; /**< Implementation dependent. */
unsigned nf : 1; /**< Non-faulting load. */
unsigned asi : 8; /**< ASI. */
unsigned tm : 1; /**< I-TLB miss. */
unsigned : 3; /**< Reserved. */
unsigned ft : 5; /**< Fault type. */
#endif
unsigned e : 1; /**< Side-effect bit. */
unsigned ct : 2; /**< Context Register selection. */
unsigned pr : 1; /**< Privilege bit. */
144,9 → 231,53
};
typedef union tlb_sfsr_reg tlb_sfsr_reg_t;
 
#if defined (US3)
 
/*
* Functions for determining the number of entries in TLBs. They either return
* a constant value or a value based on the CPU autodetection.
*/
 
/**
* Determine the number of entries in the DMMU's small TLB.
*/
static inline uint16_t tlb_dsmall_size(void)
{
return 16;
}
 
/**
* Determine the number of entries in each DMMU's big TLB.
*/
static inline uint16_t tlb_dbig_size(void)
{
return 512;
}
 
/**
* Determine the number of entries in the IMMU's small TLB.
*/
static inline uint16_t tlb_ismall_size(void)
{
return 16;
}
 
/**
* Determine the number of entries in the IMMU's big TLB.
*/
static inline uint16_t tlb_ibig_size(void)
{
if (((ver_reg_t) ver_read()).impl == IMPL_ULTRASPARCIV_PLUS)
return 512;
else
return 128;
}
 
#endif
 
/** Read MMU Primary Context Register.
*
* @return Current value of Primary Context Register.
* @return Current value of Primary Context Register.
*/
static inline uint64_t mmu_primary_context_read(void)
{
155,17 → 286,17
 
/** Write MMU Primary Context Register.
*
* @param v New value of Primary Context Register.
* @param v New value of Primary Context Register.
*/
static inline void mmu_primary_context_write(uint64_t v)
{
asi_u64_write(ASI_DMMU, VA_PRIMARY_CONTEXT_REG, v);
flush();
flush_pipeline();
}
 
/** Read MMU Secondary Context Register.
*
* @return Current value of Secondary Context Register.
* @return Current value of Secondary Context Register.
*/
static inline uint64_t mmu_secondary_context_read(void)
{
174,23 → 305,26
 
/** Write MMU Primary Context Register.
*
* @param v New value of Primary Context Register.
* @param v New value of Primary Context Register.
*/
static inline void mmu_secondary_context_write(uint64_t v)
{
asi_u64_write(ASI_DMMU, VA_SECONDARY_CONTEXT_REG, v);
flush();
flush_pipeline();
}
 
#if defined (US)
 
/** Read IMMU TLB Data Access Register.
*
* @param entry TLB Entry index.
* @param entry TLB Entry index.
*
* @return Current value of specified IMMU TLB Data Access Register.
* @return Current value of specified IMMU TLB Data Access
* Register.
*/
static inline uint64_t itlb_data_access_read(index_t entry)
{
tlb_data_access_addr_t reg;
itlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_entry = entry;
199,28 → 333,29
 
/** Write IMMU TLB Data Access Register.
*
* @param entry TLB Entry index.
* @param value Value to be written.
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void itlb_data_access_write(index_t entry, uint64_t value)
{
tlb_data_access_addr_t reg;
itlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_entry = entry;
asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value);
flush();
flush_pipeline();
}
 
/** Read DMMU TLB Data Access Register.
*
* @param entry TLB Entry index.
* @param entry TLB Entry index.
*
* @return Current value of specified DMMU TLB Data Access Register.
* @return Current value of specified DMMU TLB Data Access
* Register.
*/
static inline uint64_t dtlb_data_access_read(index_t entry)
{
tlb_data_access_addr_t reg;
dtlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_entry = entry;
229,12 → 364,12
 
/** Write DMMU TLB Data Access Register.
*
* @param entry TLB Entry index.
* @param value Value to be written.
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void dtlb_data_access_write(index_t entry, uint64_t value)
{
tlb_data_access_addr_t reg;
dtlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_entry = entry;
244,13 → 379,13
 
/** Read IMMU TLB Tag Read Register.
*
* @param entry TLB Entry index.
* @param entry TLB Entry index.
*
* @return Current value of specified IMMU TLB Tag Read Register.
* @return Current value of specified IMMU TLB Tag Read Register.
*/
static inline uint64_t itlb_tag_read_read(index_t entry)
{
tlb_tag_read_addr_t tag;
itlb_tag_read_addr_t tag;
 
tag.value = 0;
tag.tlb_entry = entry;
259,13 → 394,13
 
/** Read DMMU TLB Tag Read Register.
*
* @param entry TLB Entry index.
* @param entry TLB Entry index.
*
* @return Current value of specified DMMU TLB Tag Read Register.
* @return Current value of specified DMMU TLB Tag Read Register.
*/
static inline uint64_t dtlb_tag_read_read(index_t entry)
{
tlb_tag_read_addr_t tag;
dtlb_tag_read_addr_t tag;
 
tag.value = 0;
tag.tlb_entry = entry;
272,19 → 407,130
return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value);
}
 
#elif defined (US3)
 
 
/** Read IMMU TLB Data Access Register.
*
* @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG)
* @param entry TLB Entry index.
*
* @return Current value of specified IMMU TLB Data Access
* Register.
*/
static inline uint64_t itlb_data_access_read(int tlb, index_t entry)
{
itlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_number = tlb;
reg.local_tlb_entry = entry;
return asi_u64_read(ASI_ITLB_DATA_ACCESS_REG, reg.value);
}
 
/** Write IMMU TLB Data Access Register.
* @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG)
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void itlb_data_access_write(int tlb, index_t entry,
uint64_t value)
{
itlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_number = tlb;
reg.local_tlb_entry = entry;
asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value);
flush_pipeline();
}
 
/** Read DMMU TLB Data Access Register.
*
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG, TLB_DBIG)
* @param entry TLB Entry index.
*
* @return Current value of specified DMMU TLB Data Access
* Register.
*/
static inline uint64_t dtlb_data_access_read(int tlb, index_t entry)
{
dtlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_number = tlb;
reg.local_tlb_entry = entry;
return asi_u64_read(ASI_DTLB_DATA_ACCESS_REG, reg.value);
}
 
/** Write DMMU TLB Data Access Register.
*
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1)
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void dtlb_data_access_write(int tlb, index_t entry,
uint64_t value)
{
dtlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_number = tlb;
reg.local_tlb_entry = entry;
asi_u64_write(ASI_DTLB_DATA_ACCESS_REG, reg.value, value);
membar();
}
 
/** Read IMMU TLB Tag Read Register.
*
* @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG)
* @param entry TLB Entry index.
*
* @return Current value of specified IMMU TLB Tag Read Register.
*/
static inline uint64_t itlb_tag_read_read(int tlb, index_t entry)
{
itlb_tag_read_addr_t tag;
 
tag.value = 0;
tag.tlb_number = tlb;
tag.local_tlb_entry = entry;
return asi_u64_read(ASI_ITLB_TAG_READ_REG, tag.value);
}
 
/** Read DMMU TLB Tag Read Register.
*
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1)
* @param entry TLB Entry index.
*
* @return Current value of specified DMMU TLB Tag Read Register.
*/
static inline uint64_t dtlb_tag_read_read(int tlb, index_t entry)
{
dtlb_tag_read_addr_t tag;
 
tag.value = 0;
tag.tlb_number = tlb;
tag.local_tlb_entry = entry;
return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value);
}
 
#endif
 
 
/** Write IMMU TLB Tag Access Register.
*
* @param v Value to be written.
* @param v Value to be written.
*/
static inline void itlb_tag_access_write(uint64_t v)
{
asi_u64_write(ASI_IMMU, VA_IMMU_TAG_ACCESS, v);
flush();
flush_pipeline();
}
 
/** Read IMMU TLB Tag Access Register.
*
* @return Current value of IMMU TLB Tag Access Register.
* @return Current value of IMMU TLB Tag Access Register.
*/
static inline uint64_t itlb_tag_access_read(void)
{
293,7 → 539,7
 
/** Write DMMU TLB Tag Access Register.
*
* @param v Value to be written.
* @param v Value to be written.
*/
static inline void dtlb_tag_access_write(uint64_t v)
{
303,7 → 549,7
 
/** Read DMMU TLB Tag Access Register.
*
* @return Current value of DMMU TLB Tag Access Register.
* @return Current value of DMMU TLB Tag Access Register.
*/
static inline uint64_t dtlb_tag_access_read(void)
{
313,17 → 559,17
 
/** Write IMMU TLB Data in Register.
*
* @param v Value to be written.
* @param v Value to be written.
*/
static inline void itlb_data_in_write(uint64_t v)
{
asi_u64_write(ASI_ITLB_DATA_IN_REG, 0, v);
flush();
flush_pipeline();
}
 
/** Write DMMU TLB Data in Register.
*
* @param v Value to be written.
* @param v Value to be written.
*/
static inline void dtlb_data_in_write(uint64_t v)
{
333,7 → 579,7
 
/** Read ITLB Synchronous Fault Status Register.
*
* @return Current content of I-SFSR register.
* @return Current content of I-SFSR register.
*/
static inline uint64_t itlb_sfsr_read(void)
{
342,17 → 588,17
 
/** Write ITLB Synchronous Fault Status Register.
*
* @param v New value of I-SFSR register.
* @param v New value of I-SFSR register.
*/
static inline void itlb_sfsr_write(uint64_t v)
{
asi_u64_write(ASI_IMMU, VA_IMMU_SFSR, v);
flush();
flush_pipeline();
}
 
/** Read DTLB Synchronous Fault Status Register.
*
* @return Current content of D-SFSR register.
* @return Current content of D-SFSR register.
*/
static inline uint64_t dtlb_sfsr_read(void)
{
361,7 → 607,7
 
/** Write DTLB Synchronous Fault Status Register.
*
* @param v New value of D-SFSR register.
* @param v New value of D-SFSR register.
*/
static inline void dtlb_sfsr_write(uint64_t v)
{
371,7 → 617,7
 
/** Read DTLB Synchronous Fault Address Register.
*
* @return Current content of D-SFAR register.
* @return Current content of D-SFAR register.
*/
static inline uint64_t dtlb_sfar_read(void)
{
380,10 → 626,11
 
/** Perform IMMU TLB Demap Operation.
*
* @param type Selects between context and page demap.
* @param type Selects between context and page demap (and entire MMU
* demap on US3).
* @param context_encoding Specifies which Context register has Context ID for
* demap.
* @param page Address which is on the page to be demapped.
* demap.
* @param page Address which is on the page to be demapped.
*/
static inline void itlb_demap(int type, int context_encoding, uintptr_t page)
{
397,18 → 644,19
da.context = context_encoding;
da.vpn = pg.vpn;
asi_u64_write(ASI_IMMU_DEMAP, da.value, 0); /* da.value is the
* address within the
* ASI */
flush();
/* da.value is the address within the ASI */
asi_u64_write(ASI_IMMU_DEMAP, da.value, 0);
 
flush_pipeline();
}
 
/** Perform DMMU TLB Demap Operation.
*
* @param type Selects between context and page demap.
* @param type Selects between context and page demap (and entire MMU
* demap on US3).
* @param context_encoding Specifies which Context register has Context ID for
* demap.
* @param page Address which is on the page to be demapped.
* demap.
* @param page Address which is on the page to be demapped.
*/
static inline void dtlb_demap(int type, int context_encoding, uintptr_t page)
{
422,17 → 670,17
da.context = context_encoding;
da.vpn = pg.vpn;
asi_u64_write(ASI_DMMU_DEMAP, da.value, 0); /* da.value is the
* address within the
* ASI */
/* da.value is the address within the ASI */
asi_u64_write(ASI_DMMU_DEMAP, da.value, 0);
 
membar();
}
 
extern void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate);
extern void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate);
extern void fast_data_access_protection(tlb_tag_access_reg_t tag , istate_t *istate);
extern void fast_instruction_access_mmu_miss(unative_t, istate_t *);
extern void fast_data_access_mmu_miss(tlb_tag_access_reg_t, istate_t *);
extern void fast_data_access_protection(tlb_tag_access_reg_t , istate_t *);
 
extern void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, bool locked, bool cacheable);
extern void dtlb_insert_mapping(uintptr_t, uintptr_t, int, bool, bool);
 
extern void dump_sfsr_and_sfar(void);
 
/branches/dd/kernel/arch/sparc64/include/mm/cache.h
38,15 → 38,6
#include <mm/page.h>
#include <mm/frame.h>
 
#define dcache_flush_page(p) \
dcache_flush_color(PAGE_COLOR((p)))
#define dcache_flush_frame(p, f) \
dcache_flush_tag(PAGE_COLOR((p)), ADDR2PFN((f)));
 
extern void dcache_flush(void);
extern void dcache_flush_color(int c);
extern void dcache_flush_tag(int c, pfn_t tag);
 
#endif
 
/** @}
/branches/dd/kernel/arch/sparc64/include/mm/tsb.h
107,6 → 107,55
asi_u64_write(ASI_DMMU, VA_DMMU_TSB_BASE, v);
}
 
#if defined (US3)
 
/** Write DTSB Primary Extension register.
*
* @param v New content of the DTSB Primary Extension register.
*/
static inline void dtsb_primary_extension_write(uint64_t v)
{
asi_u64_write(ASI_DMMU, VA_DMMU_PRIMARY_EXTENSION, v);
}
 
/** Write DTSB Secondary Extension register.
*
* @param v New content of the DTSB Secondary Extension register.
*/
static inline void dtsb_secondary_extension_write(uint64_t v)
{
asi_u64_write(ASI_DMMU, VA_DMMU_SECONDARY_EXTENSION, v);
}
 
/** Write DTSB Nucleus Extension register.
*
* @param v New content of the DTSB Nucleus Extension register.
*/
static inline void dtsb_nucleus_extension_write(uint64_t v)
{
asi_u64_write(ASI_DMMU, VA_DMMU_NUCLEUS_EXTENSION, v);
}
 
/** Write ITSB Primary Extension register.
*
* @param v New content of the ITSB Primary Extension register.
*/
static inline void itsb_primary_extension_write(uint64_t v)
{
asi_u64_write(ASI_IMMU, VA_IMMU_PRIMARY_EXTENSION, v);
}
 
/** Write ITSB Nucleus Extension register.
*
* @param v New content of the ITSB Nucleus Extension register.
*/
static inline void itsb_nucleus_extension_write(uint64_t v)
{
asi_u64_write(ASI_IMMU, VA_IMMU_NUCLEUS_EXTENSION, v);
}
 
#endif
 
/* Forward declarations. */
struct as;
struct pte;
/branches/dd/kernel/arch/sparc64/include/register.h
117,23 → 117,6
};
typedef union fprs_reg fprs_reg_t;
 
/** UPA_CONFIG register.
*
* Note that format of this register differs significantly from
* processor version to version. The format defined here
* is the common subset for all supported processor versions.
*/
union upa_config {
uint64_t value;
struct {
uint64_t : 34;
unsigned pcon : 8; /**< Processor configuration. */
unsigned mid : 5; /**< Module (processor) ID register. */
unsigned pcap : 17; /**< Processor capabilities. */
} __attribute__ ((packed));
};
typedef union upa_config upa_config_t;
 
#endif
 
/** @}
/branches/dd/kernel/arch/sparc64/include/barrier.h
57,8 → 57,11
#define write_barrier() \
asm volatile ("membar #StoreStore\n" ::: "memory")
 
/** Flush Instruction Memory instruction. */
static inline void flush(void)
#define flush(a) \
asm volatile ("flush %0\n" :: "r" ((a)) : "memory")
 
/** Flush Instruction pipeline. */
static inline void flush_pipeline(void)
{
/*
* The FLUSH instruction takes address parameter.
79,6 → 82,39
asm volatile ("membar #Sync\n");
}
 
#if defined (US)
 
#define smc_coherence(a) \
{ \
write_barrier(); \
flush((a)); \
}
 
#define FLUSH_INVAL_MIN 4
#define smc_coherence_block(a, l) \
{ \
unsigned long i; \
write_barrier(); \
for (i = 0; i < (l); i += FLUSH_INVAL_MIN) \
flush((void *)(a) + i); \
}
 
#elif defined (US3)
 
#define smc_coherence(a) \
{ \
write_barrier(); \
flush_pipeline(); \
}
 
#define smc_coherence_block(a, l) \
{ \
write_barrier(); \
flush_pipeline(); \
}
 
#endif /* defined(US3) */
 
#endif
 
/** @}
/branches/dd/kernel/arch/sparc64/include/cpu.h
35,14 → 35,6
#ifndef KERN_sparc64_CPU_H_
#define KERN_sparc64_CPU_H_
 
#include <arch/types.h>
#include <arch/register.h>
#include <arch/asm.h>
 
#ifdef CONFIG_SMP
#include <arch/mm/cache.h>
#endif
 
#define MANUF_FUJITSU 0x04
#define MANUF_ULTRASPARC 0x17 /**< UltraSPARC I, UltraSPARC II */
#define MANUF_SUN 0x3e
51,14 → 43,29
#define IMPL_ULTRASPARCII 0x11
#define IMPL_ULTRASPARCII_I 0x12
#define IMPL_ULTRASPARCII_E 0x13
#define IMPL_ULTRASPARCIII 0x15
#define IMPL_ULTRASPARCIII 0x14
#define IMPL_ULTRASPARCIII_PLUS 0x15
#define IMPL_ULTRASPARCIII_I 0x16
#define IMPL_ULTRASPARCIV 0x18
#define IMPL_ULTRASPARCIV_PLUS 0x19
 
#define IMPL_SPARC64V 0x5
 
#ifndef __ASM__
 
#include <arch/types.h>
#include <typedefs.h>
#include <arch/register.h>
#include <arch/regdef.h>
#include <arch/asm.h>
 
#ifdef CONFIG_SMP
#include <arch/mm/cache.h>
#endif
 
typedef struct {
uint32_t mid; /**< Processor ID as read from
UPA_CONFIG. */
UPA_CONFIG/FIREPLANE_CONFIG. */
ver_reg_t ver;
uint32_t clock_frequency; /**< Processor frequency in Hz. */
uint64_t next_tick_cmpr; /**< Next clock interrupt should be
65,8 → 72,28
generated when the TICK register
matches this value. */
} cpu_arch_t;
 
 
/**
* Reads the module ID (agent ID/CPUID) of the current CPU.
*/
static inline uint32_t read_mid(void)
{
uint64_t icbus_config = asi_u64_read(ASI_ICBUS_CONFIG, 0);
icbus_config = icbus_config >> ICBUS_CONFIG_MID_SHIFT;
#if defined (US)
return icbus_config & 0x1f;
#elif defined (US3)
if (((ver_reg_t) ver_read()).impl == IMPL_ULTRASPARCIII_I)
return icbus_config & 0x1f;
else
return icbus_config & 0x3ff;
#endif
}
 
#endif
 
#endif
 
/** @}
*/
/branches/dd/kernel/arch/sparc64/include/drivers/z8530.h
File deleted
/branches/dd/kernel/arch/sparc64/include/drivers/ns16550.h
File deleted
/branches/dd/kernel/arch/sparc64/include/drivers/sgcn.h
0,0 → 1,126
/*
* Copyright (c) 2008 Pavel Rimsky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64
* @{
*/
/** @file
*/
 
#ifndef KERN_sparc64_SGCN_H_
#define KERN_sparc64_SGCN_H_
 
#include <arch/types.h>
 
/* number of bytes in the TOC magic, including the terminating '\0' */
#define TOC_MAGIC_BYTES 8
 
/* number of bytes in the TOC key, including the terminating '\0' */
#define TOC_KEY_SIZE 8
 
/* maximum number of entries in the SRAM table of contents */
#define MAX_TOC_ENTRIES 32
 
/* number of bytes in the SGCN buffer magic, including the terminating '\0' */
#define SGCN_MAGIC_BYTES 4
 
/**
* Entry in the SRAM table of contents. Describes one segment of the SRAM
* which serves a particular purpose (e.g. OBP serial console, Solaris serial
* console, Solaris mailbox,...).
*/
typedef struct {
/** key (e.g. "OBPCONS", "SOLCONS", "SOLMBOX",...) */
char key[TOC_KEY_SIZE];
/** size of the segment in bytes */
uint32_t size;
/** offset of the segment within SRAM */
uint32_t offset;
} __attribute ((packed)) toc_entry_t;
 
/**
* SRAM table of contents. Describes all segments within the SRAM.
*/
typedef struct {
/** hard-wired to "TOCSRAM" */
char magic[TOC_MAGIC_BYTES];
/** we don't need this */
char unused[8];
/** TOC entries */
toc_entry_t keys[MAX_TOC_ENTRIES];
} __attribute__ ((packed)) iosram_toc_t;
 
/**
* SGCN buffer header. It is placed at the very beginning of the SGCN
* buffer.
*/
typedef struct {
/** hard-wired to "CON" */
char magic[SGCN_MAGIC_BYTES];
/** we don't need this */
char unused[8];
/** offset within the SGCN buffer of the input buffer start */
uint32_t in_begin;
/** offset within the SGCN buffer of the input buffer end */
uint32_t in_end;
/** offset within the SGCN buffer of the input buffer read pointer */
uint32_t in_rdptr;
/** offset within the SGCN buffer of the input buffer write pointer */
uint32_t in_wrptr;
 
/** offset within the SGCN buffer of the output buffer start */
uint32_t out_begin;
/** offset within the SGCN buffer of the output buffer end */
uint32_t out_end;
/** offset within the SGCN buffer of the output buffer read pointer */
uint32_t out_rdptr;
/** offset within the SGCN buffer of the output buffer write pointer */
uint32_t out_wrptr;
} __attribute__ ((packed)) sgcn_buffer_header_t;
 
void sgcn_grab(void);
void sgcn_release(void);
void sgcn_poll(void);
void sgcn_init(void);
 
#endif
 
/** @}
*/
/branches/dd/kernel/arch/sparc64/include/drivers/pci.h
51,8 → 51,8
};
 
struct pci_operations {
void (* enable_interrupt)(pci_t *pci, int inr);
void (* clear_interrupt)(pci_t *pci, int inr);
void (* enable_interrupt)(pci_t *, int);
void (* clear_interrupt)(pci_t *, int);
};
 
struct pci {
61,9 → 61,9
volatile uint64_t *reg; /**< Registers including interrupt registers. */
};
 
extern pci_t *pci_init(ofw_tree_node_t *node);
extern void pci_enable_interrupt(pci_t *pci, int inr);
extern void pci_clear_interrupt(pci_t *pci, int inr);
extern pci_t *pci_init(ofw_tree_node_t *);
extern void pci_enable_interrupt(pci_t *, int);
extern void pci_clear_interrupt(void *, int);
 
#endif
 
/branches/dd/kernel/arch/sparc64/include/drivers/fhc.h
44,9 → 44,9
 
extern fhc_t *central_fhc;
 
extern fhc_t *fhc_init(ofw_tree_node_t *node);
extern void fhc_enable_interrupt(fhc_t *fhc, int inr);
extern void fhc_clear_interrupt(fhc_t *fhc, int inr);
extern fhc_t *fhc_init(ofw_tree_node_t *);
extern void fhc_enable_interrupt(fhc_t *, int);
extern void fhc_clear_interrupt(void *, int);
 
#endif
 
/branches/dd/kernel/arch/sparc64/include/drivers/kbd.h
41,7 → 41,8
typedef enum {
KBD_UNKNOWN,
KBD_Z8530,
KBD_NS16550
KBD_NS16550,
KBD_SGCN
} kbd_type_t;
 
extern kbd_type_t kbd_type;
/branches/dd/kernel/arch/sparc64/include/drivers/scr.h
42,12 → 42,14
SCR_UNKNOWN,
SCR_ATYFB,
SCR_FFB,
SCR_CGSIX
SCR_CGSIX,
SCR_XVR
} scr_type_t;
 
extern scr_type_t scr_type;
 
extern void scr_init(ofw_tree_node_t *node);
extern void scr_redraw(void);
 
#endif
 
/branches/dd/kernel/arch/sparc64/include/cpu_family.h
0,0 → 1,83
/*
* Copyright (c) 2008 Pavel Rimsky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64
* @{
*/
/** @file
*/
 
#ifndef KERN_sparc64_CPU_FAMILY_H_
#define KERN_sparc64_CPU_FAMILY_H_
 
#include <arch.h>
#include <cpu.h>
#include <arch/register.h>
#include <arch/asm.h>
 
/**
* Find the processor (sub)family.
*
* @return true iff the CPU belongs to the US family
*/
static inline bool is_us(void)
{
int impl = ((ver_reg_t) ver_read()).impl;
return (impl == IMPL_ULTRASPARCI) || (impl == IMPL_ULTRASPARCII) ||
(impl == IMPL_ULTRASPARCII_I) || (impl == IMPL_ULTRASPARCII_E);
}
 
/**
* Find the processor (sub)family.
*
* @return true iff the CPU belongs to the US-III subfamily
*/
static inline bool is_us_iii(void)
{
int impl = ((ver_reg_t) ver_read()).impl;
return (impl == IMPL_ULTRASPARCIII) ||
(impl == IMPL_ULTRASPARCIII_PLUS) ||
(impl == IMPL_ULTRASPARCIII_I);
}
 
/**
* Find the processor (sub)family.
*
* @return true iff the CPU belongs to the US-IV subfamily
*/
static inline bool is_us_iv(void)
{
int impl = ((ver_reg_t) ver_read()).impl;
return (impl == IMPL_ULTRASPARCIV) || (impl == IMPL_ULTRASPARCIV_PLUS);
}
#endif
 
/** @}
*/
 
/branches/dd/kernel/arch/sparc64/Makefile.inc
33,7 → 33,7
BFD_ARCH = sparc
BFD = binary
TARGET = sparc64-linux-gnu
TOOLCHAIN_DIR = /usr/local/sparc64
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64
 
GCC_CFLAGS += -m64 -mcpu=ultrasparc
SUNCC_CFLAGS += -m64 -xarch=sparc -xregs=appl,no%float
42,80 → 42,59
 
DEFS += -D__64_BITS__
 
## Own configuration directives
#
ifeq ($(PROCESSOR),us)
DEFS += -DUS
endif
 
## Compile with page hash table support.
#
ifeq ($(PROCESSOR),us3)
DEFS += -DUS3
endif
 
CONFIG_PAGE_HT = y
DEFS += -DCONFIG_PAGE_HT
ARCH_SOURCES = \
arch/$(KARCH)/src/cpu/cpu.c \
arch/$(KARCH)/src/asm.S \
arch/$(KARCH)/src/panic.S \
arch/$(KARCH)/src/console.c \
arch/$(KARCH)/src/context.S \
arch/$(KARCH)/src/fpu_context.c \
arch/$(KARCH)/src/dummy.s \
arch/$(KARCH)/src/mm/as.c \
arch/$(KARCH)/src/mm/cache.S \
arch/$(KARCH)/src/mm/frame.c \
arch/$(KARCH)/src/mm/page.c \
arch/$(KARCH)/src/mm/tlb.c \
arch/$(KARCH)/src/sparc64.c \
arch/$(KARCH)/src/start.S \
arch/$(KARCH)/src/proc/scheduler.c \
arch/$(KARCH)/src/proc/thread.c \
arch/$(KARCH)/src/trap/mmu.S \
arch/$(KARCH)/src/trap/trap_table.S \
arch/$(KARCH)/src/trap/trap.c \
arch/$(KARCH)/src/trap/exception.c \
arch/$(KARCH)/src/trap/interrupt.c \
arch/$(KARCH)/src/ddi/ddi.c \
arch/$(KARCH)/src/drivers/tick.c \
arch/$(KARCH)/src/drivers/kbd.c \
arch/$(KARCH)/src/drivers/sgcn.c \
arch/$(KARCH)/src/drivers/pci.c
 
## Compile with support for address space identifiers.
#
 
CONFIG_ASID = y
CONFIG_ASID_FIFO = y
 
## Compile with support for framebuffer.
#
 
CONFIG_FB = y
 
## Compile with support for Sun keyboard.
#
 
CONFIG_SUN_KBD = y
 
## Compile with support for OpenFirmware device tree.
#
 
CONFIG_OFW_TREE = y
 
ifeq ($(CONFIG_SMP),y)
DEFS += -DCONFIG_SMP
ifeq ($(CONFIG_FB),y)
ARCH_SOURCES += \
arch/$(KARCH)/src/drivers/scr.c
endif
 
ARCH_SOURCES = \
arch/$(ARCH)/src/cpu/cpu.c \
arch/$(ARCH)/src/asm.S \
arch/$(ARCH)/src/panic.S \
arch/$(ARCH)/src/console.c \
arch/$(ARCH)/src/context.S \
arch/$(ARCH)/src/fpu_context.c \
arch/$(ARCH)/src/dummy.s \
arch/$(ARCH)/src/mm/as.c \
arch/$(ARCH)/src/mm/cache.S \
arch/$(ARCH)/src/mm/frame.c \
arch/$(ARCH)/src/mm/page.c \
arch/$(ARCH)/src/mm/tlb.c \
arch/$(ARCH)/src/sparc64.c \
arch/$(ARCH)/src/start.S \
arch/$(ARCH)/src/proc/scheduler.c \
arch/$(ARCH)/src/proc/thread.c \
arch/$(ARCH)/src/trap/mmu.S \
arch/$(ARCH)/src/trap/trap_table.S \
arch/$(ARCH)/src/trap/trap.c \
arch/$(ARCH)/src/trap/exception.c \
arch/$(ARCH)/src/trap/interrupt.c \
arch/$(ARCH)/src/ddi/ddi.c \
arch/$(ARCH)/src/drivers/tick.c \
arch/$(ARCH)/src/drivers/kbd.c \
arch/$(ARCH)/src/drivers/scr.c \
arch/$(ARCH)/src/drivers/pci.c
 
ifeq ($(CONFIG_SMP),y)
ARCH_SOURCES += \
arch/$(ARCH)/src/smp/ipi.c \
arch/$(ARCH)/src/smp/smp.c
ARCH_SOURCES += \
arch/$(KARCH)/src/smp/ipi.c \
arch/$(KARCH)/src/smp/smp.c
endif
 
ifeq ($(CONFIG_TSB),y)
ARCH_SOURCES += \
arch/$(ARCH)/src/mm/tsb.c
ARCH_SOURCES += \
arch/$(KARCH)/src/mm/tsb.c
endif
 
ifdef CONFIG_Z8530
ARCH_SOURCES += \
arch/$(ARCH)/src/drivers/fhc.c
ARCH_SOURCES += \
arch/$(KARCH)/src/drivers/fhc.c
endif
/branches/dd/kernel/arch/sparc64/src/smp/smp.c
35,6 → 35,7
#include <smp/smp.h>
#include <genarch/ofw/ofw_tree.h>
#include <cpu.h>
#include <arch/cpu_family.h>
#include <arch/cpu.h>
#include <arch.h>
#include <config.h>
43,6 → 44,7
#include <synch/synch.h>
#include <synch/waitq.h>
#include <print.h>
#include <arch/cpu_node.h>
 
/**
* This global variable is used to pick-up application processors
61,15 → 63,55
ofw_tree_node_t *node;
count_t cnt = 0;
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
while (node) {
cnt++;
node = ofw_tree_find_peer_by_device_type(node, "cpu");
if (is_us() || is_us_iii()) {
node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
while (node) {
cnt++;
node = ofw_tree_find_peer_by_device_type(node, "cpu");
}
} else if (is_us_iv()) {
node = ofw_tree_find_child(cpus_parent(), "cmp");
while (node) {
cnt += 2;
node = ofw_tree_find_peer_by_name(node, "cmp");
}
}
config.cpu_count = max(1, cnt);
}
 
/**
* Wakes up the CPU which is represented by the "node" OFW tree node.
* If "node" represents the current CPU, calling the function has
* no effect.
*/
static void wakeup_cpu(ofw_tree_node_t *node)
{
uint32_t mid;
ofw_tree_property_t *prop;
/* 'upa-portid' for US, 'portid' for US-III, 'cpuid' for US-IV */
prop = ofw_tree_getprop(node, "upa-portid");
if ((!prop) || (!prop->value))
prop = ofw_tree_getprop(node, "portid");
if ((!prop) || (!prop->value))
prop = ofw_tree_getprop(node, "cpuid");
if (!prop || prop->value == NULL)
return;
mid = *((uint32_t *) prop->value);
if (CPU->arch.mid == mid)
return;
 
waking_up_mid = mid;
if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) ==
ESYNCH_TIMEOUT)
printf("%s: waiting for processor (mid = %" PRIu32
") timed out\n", __func__, mid);
}
 
/** Wake application processors up. */
void kmp(void *arg)
{
76,31 → 118,18
ofw_tree_node_t *node;
int i;
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
for (i = 0; node; node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++) {
uint32_t mid;
ofw_tree_property_t *prop;
prop = ofw_tree_getprop(node, "upa-portid");
if (!prop || !prop->value)
continue;
mid = *((uint32_t *) prop->value);
if (CPU->arch.mid == mid) {
/*
* Skip the current CPU.
*/
continue;
if (is_us() || is_us_iii()) {
node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
for (i = 0; node;
node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++)
wakeup_cpu(node);
} else if (is_us_iv()) {
node = ofw_tree_find_child(cpus_parent(), "cmp");
while (node) {
wakeup_cpu(ofw_tree_find_child(node, "cpu@0"));
wakeup_cpu(ofw_tree_find_child(node, "cpu@1"));
node = ofw_tree_find_peer_by_name(node, "cmp");
}
 
/*
* Processor with ID == mid can proceed with its initialization.
*/
waking_up_mid = mid;
if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT)
printf("%s: waiting for processor (mid = %d) timed out\n",
__func__, mid);
}
}
 
/branches/dd/kernel/arch/sparc64/src/smp/ipi.c
46,6 → 46,33
#include <time/delay.h>
#include <panic.h>
 
/** Set the contents of the outgoing interrupt vector data.
*
* The first data item (data 0) will be set to the value of func, the
* rest of the vector will contain zeros.
*
* This is a helper function used from within the cross_call function.
*
* @param func value the first data item of the vector will be set to
*/
static inline void set_intr_w_data(void (* func)(void))
{
#if defined (US)
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_0, (uintptr_t) func);
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
#elif defined (US3)
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_0, (uintptr_t) func);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_1, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_2, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_3, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_4, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_5, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_6, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_7, 0);
#endif
}
 
/** Invoke function on another processor.
*
* Currently, only functions without arguments are supported.
71,16 → 98,15
status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
if (status & INTR_DISPATCH_STATUS_BUSY)
panic("Interrupt Dispatch Status busy bit set\n");
panic("Interrupt Dispatch Status busy bit set.");
ASSERT(!(pstate_read() & PSTATE_IE_BIT));
do {
asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_0,
(uintptr_t) func);
asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
asi_u64_write(ASI_UDB_INTR_W,
set_intr_w_data(func);
asi_u64_write(ASI_INTR_W,
(mid << INTR_VEC_DISPATCH_MID_SHIFT) |
ASI_UDB_INTR_W_DISPATCH, 0);
VA_INTR_W_DISPATCH, 0);
membar();
125,7 → 151,7
func = tlb_shootdown_ipi_recv;
break;
default:
panic("Unknown IPI (%d).\n", ipi);
panic("Unknown IPI (%d).", ipi);
break;
}
/branches/dd/kernel/arch/sparc64/src/ddi/ddi.c
41,7 → 41,7
* Interrupts are disabled and task is locked.
*
* @param task Task.
* @param ioaddr Startign I/O space address.
* @param ioaddr Starting I/O space address.
* @param size Size of the enabled I/O range.
*
* @return 0 on success or an error code from errno.h.
/branches/dd/kernel/arch/sparc64/src/asm.S
41,6 → 41,7
*/
.global memcpy
memcpy:
mov %o0, %o3 ! save dst
add %o1, 7, %g1
and %g1, -8, %g1
cmp %o1, %g1
59,7 → 60,7
mov %g2, %g3
2:
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
3:
and %g1, -8, %g1
cmp %o0, %g1
93,7 → 94,7
mov %g2, %g3
 
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
 
/*
* Almost the same as memcpy() except the loads are from userspace.
100,6 → 101,7
*/
.global memcpy_from_uspace
memcpy_from_uspace:
mov %o0, %o3 ! save dst
add %o1, 7, %g1
and %g1, -8, %g1
cmp %o1, %g1
118,7 → 120,7
mov %g2, %g3
2:
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
3:
and %g1, -8, %g1
cmp %o0, %g1
152,7 → 154,7
mov %g2, %g3
 
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
 
/*
* Almost the same as memcpy() except the stores are to userspace.
159,6 → 161,7
*/
.global memcpy_to_uspace
memcpy_to_uspace:
mov %o0, %o3 ! save dst
add %o1, 7, %g1
and %g1, -8, %g1
cmp %o1, %g1
177,7 → 180,7
mov %g2, %g3
2:
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
3:
and %g1, -8, %g1
cmp %o0, %g1
211,7 → 214,7
mov %g2, %g3
 
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
 
.global memcpy_from_uspace_failover_address
.global memcpy_to_uspace_failover_address
274,6 → 277,8
wrpr %g0, 0, %cleanwin ! avoid information leak
 
mov %i2, %o0 ! uarg
xor %o1, %o1, %o1 ! %o1 is defined to hold pcb_ptr
! set it to 0
 
clr %i2
clr %i3
/branches/dd/kernel/arch/sparc64/src/console.c
38,12 → 38,7
#include <arch/drivers/scr.h>
#include <arch/drivers/kbd.h>
 
#ifdef CONFIG_Z8530
#include <genarch/kbd/z8530.h>
#endif
#ifdef CONFIG_NS16550
#include <genarch/kbd/ns16550.h>
#endif
#include <arch/drivers/sgcn.h>
 
#include <console/chardev.h>
#include <console/console.h>
54,47 → 49,81
#include <genarch/ofw/ofw_tree.h>
#include <arch.h>
#include <panic.h>
#include <string.h>
#include <print.h>
 
#define KEYBOARD_POLL_PAUSE 50000 /* 50ms */
 
/** Initialize kernel console to use framebuffer and keyboard directly. */
void standalone_sparc64_console_init(void)
/**
* Initialize kernel console to use framebuffer and keyboard directly.
* Called on UltraSPARC machines with standard keyboard and framebuffer.
*
* @param aliases the "/aliases" OBP node
*/
static void standard_console_init(ofw_tree_node_t *aliases)
{
stdin = NULL;
 
ofw_tree_node_t *aliases;
#ifdef CONFIG_FB
ofw_tree_property_t *prop;
ofw_tree_node_t *screen;
ofw_tree_node_t *keyboard;
aliases = ofw_tree_lookup("/aliases");
if (!aliases)
panic("Can't find /aliases.\n");
prop = ofw_tree_getprop(aliases, "screen");
if (!prop)
panic("Can't find property \"screen\".\n");
panic("Cannot find property 'screen'.");
if (!prop->value)
panic("Can't find screen alias.\n");
panic("Cannot find screen alias.");
screen = ofw_tree_lookup(prop->value);
if (!screen)
panic("Can't find %s\n", prop->value);
panic("Cannot find %s.", prop->value);
 
scr_init(screen);
 
prop = ofw_tree_getprop(aliases, "keyboard");
if (!prop)
panic("Can't find property \"keyboard\".\n");
panic("Cannot find property 'keyboard'.");
if (!prop->value)
panic("Can't find keyboard alias.\n");
panic("Cannot find keyboard alias.");
keyboard = ofw_tree_lookup(prop->value);
if (!keyboard)
panic("Can't find %s\n", prop->value);
panic("Cannot find %s.", prop->value);
 
kbd_init(keyboard);
#else
panic("Standard console requires FB, "
"but the kernel is not compiled with FB support.");
#endif
}
 
/** Initilize I/O on the Serengeti machine. */
static void serengeti_init(void)
{
sgcn_init();
}
 
/**
* Initialize input/output. Auto-detects the type of machine
* and calls the appropriate I/O init routine.
*/
void standalone_sparc64_console_init(void)
{
ofw_tree_node_t *aliases;
ofw_tree_property_t *prop;
aliases = ofw_tree_lookup("/aliases");
if (!aliases)
panic("Cannot find '/aliases'.");
/* "def-cn" = "default console" */
prop = ofw_tree_getprop(aliases, "def-cn");
if ((!prop) || (!prop->value) || (strcmp(prop->value, "/sgcn") != 0)) {
standard_console_init(aliases);
} else {
serengeti_init();
}
}
 
 
/** Kernel thread for polling keyboard.
*
* @param arg Ignored.
103,19 → 132,13
{
thread_detach(THREAD);
 
#ifdef CONFIG_Z8530
if (kbd_type == KBD_Z8530) {
/*
* The z8530 driver is interrupt-driven.
*/
if (kbd_type != KBD_SGCN)
return;
}
#endif
 
while (1) {
#ifdef CONFIG_NS16550
if (kbd_type == KBD_NS16550)
ns16550_poll();
#ifdef CONFIG_SGCN
if (kbd_type == KBD_SGCN)
sgcn_poll();
#endif
thread_usleep(KEYBOARD_POLL_PAUSE);
}
126,17 → 149,15
*/
void arch_grab_console(void)
{
#ifdef CONFIG_FB
scr_redraw();
#endif
switch (kbd_type) {
#ifdef CONFIG_Z8530
case KBD_Z8530:
z8530_grab();
#ifdef CONFIG_SGCN
case KBD_SGCN:
sgcn_grab();
break;
#endif
#ifdef CONFIG_NS16550
case KBD_NS16550:
ns16550_grab();
break;
#endif
default:
break;
}
148,16 → 169,11
void arch_release_console(void)
{
switch (kbd_type) {
#ifdef CONFIG_Z8530
case KBD_Z8530:
z8530_release();
#ifdef CONFIG_SGCN
case KBD_SGCN:
sgcn_release();
break;
#endif
#ifdef CONFIG_NS16550
case KBD_NS16550:
ns16550_release();
break;
#endif
default:
break;
}
/branches/dd/kernel/arch/sparc64/src/proc/thread.c
34,9 → 34,8
 
#include <proc/thread.h>
#include <arch/proc/thread.h>
#include <mm/frame.h>
#include <mm/page.h>
#include <arch/mm/page.h>
#include <mm/slab.h>
#include <arch/trap/regwin.h>
#include <align.h>
 
void thr_constructor_arch(thread_t *t)
50,12 → 49,12
void thr_destructor_arch(thread_t *t)
{
if (t->arch.uspace_window_buffer) {
uintptr_t uw_buf = (uintptr_t) t->arch.uspace_window_buffer;
/*
* Mind the possible alignment of the userspace window buffer
* belonging to a killed thread.
*/
frame_free(KA2PA(ALIGN_DOWN((uintptr_t)
t->arch.uspace_window_buffer, PAGE_SIZE)));
free((uint8_t *) ALIGN_DOWN(uw_buf, UWB_ALIGNMENT));
}
}
 
67,7 → 66,7
* The thread needs userspace window buffer and the object
* returned from the slab allocator doesn't have any.
*/
t->arch.uspace_window_buffer = frame_alloc(ONE_FRAME, FRAME_KA);
t->arch.uspace_window_buffer = malloc(UWB_ASIZE, 0);
} else {
uintptr_t uw_buf = (uintptr_t) t->arch.uspace_window_buffer;
 
76,7 → 75,7
* belonging to a killed thread.
*/
t->arch.uspace_window_buffer = (uint8_t *) ALIGN_DOWN(uw_buf,
PAGE_SIZE);
UWB_ASIZE);
}
}
 
/branches/dd/kernel/arch/sparc64/src/sparc64.c
47,10 → 47,11
#include <genarch/ofw/ofw_tree.h>
#include <userspace.h>
#include <ddi/irq.h>
#include <string.h>
 
bootinfo_t bootinfo;
 
/** Perform sparc64 specific initialization before main_bsp() is called. */
/** Perform sparc64-specific initialization before main_bsp() is called. */
void arch_pre_main(void)
{
/* Copy init task info. */
61,6 → 62,8
for (i = 0; i < bootinfo.taskmap.count; i++) {
init.tasks[i].addr = (uintptr_t) bootinfo.taskmap.tasks[i].addr;
init.tasks[i].size = bootinfo.taskmap.tasks[i].size;
strncpy(init.tasks[i].name, bootinfo.taskmap.tasks[i].name,
CONFIG_TASK_NAME_BUFLEN);
}
/* Copy boot allocations info. */
86,8 → 89,6
* But we only create 128 buckets.
*/
irq_init(1 << 11, 128);
standalone_sparc64_console_init();
}
}
 
101,16 → 102,16
 
void arch_post_smp_init(void)
{
static thread_t *t = NULL;
if (config.cpu_active == 1) {
standalone_sparc64_console_init();
 
 
if (!t) {
/*
* Create thread that polls keyboard.
*/
t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
/* Create thread that polls keyboard.
* XXX: this is only used by sgcn now
*/
thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll",
true);
if (!t)
panic("cannot create kkbdpoll\n");
panic("Cannot create kkbdpoll.");
thread_ready(t);
}
}
161,5 → 162,19
while (1);
}
 
/** Construct function pointer
*
* @param fptr function pointer structure
* @param addr function address
* @param caller calling function address
*
* @return address of the function pointer
*
*/
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
{
return addr;
}
 
/** @}
*/
/branches/dd/kernel/arch/sparc64/src/trap/exception.c
45,57 → 45,57
 
void dump_istate(istate_t *istate)
{
printf("TSTATE=%#llx\n", istate->tstate);
printf("TPC=%#llx (%s)\n", istate->tpc, get_symtab_entry(istate->tpc));
printf("TNPC=%#llx (%s)\n", istate->tnpc, get_symtab_entry(istate->tnpc));
printf("TSTATE=%#" PRIx64 "\n", istate->tstate);
printf("TPC=%#" PRIx64 " (%s)\n", istate->tpc, get_symtab_entry(istate->tpc));
printf("TNPC=%#" PRIx64 " (%s)\n", istate->tnpc, get_symtab_entry(istate->tnpc));
}
 
/** Handle instruction_access_exception. (0x8) */
void instruction_access_exception(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle instruction_access_error. (0xa) */
void instruction_access_error(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle illegal_instruction. (0x10) */
void illegal_instruction(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle privileged_opcode. (0x11) */
void privileged_opcode(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle unimplemented_LDD. (0x12) */
void unimplemented_LDD(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle unimplemented_STD. (0x13) */
void unimplemented_STD(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle fp_disabled. (0x20) */
113,9 → 113,9
#ifdef CONFIG_FPU_LAZY
scheduler_fpu_lazy_request();
#else
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
#endif
}
 
122,98 → 122,98
/** Handle fp_exception_ieee_754. (0x21) */
void fp_exception_ieee_754(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle fp_exception_other. (0x22) */
void fp_exception_other(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle tag_overflow. (0x23) */
void tag_overflow(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle division_by_zero. (0x28) */
void division_by_zero(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle data_access_exception. (0x30) */
void data_access_exception(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
dump_sfsr_and_sfar();
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle data_access_error. (0x32) */
void data_access_error(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle mem_address_not_aligned. (0x34) */
void mem_address_not_aligned(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle LDDF_mem_address_not_aligned. (0x35) */
void LDDF_mem_address_not_aligned(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle STDF_mem_address_not_aligned. (0x36) */
void STDF_mem_address_not_aligned(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle privileged_action. (0x37) */
void privileged_action(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle LDQF_mem_address_not_aligned. (0x38) */
void LDQF_mem_address_not_aligned(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Handle STQF_mem_address_not_aligned. (0x39) */
void STQF_mem_address_not_aligned(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "%s\n", __func__);
fault_if_from_uspace(istate, "%s.", __func__);
dump_istate(istate);
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** @}
/branches/dd/kernel/arch/sparc64/src/trap/interrupt.c
67,11 → 67,19
*/
void interrupt(int n, istate_t *istate)
{
uint64_t status;
uint64_t intrcv;
uint64_t data0;
status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
if (status & (!INTR_DISPATCH_STATUS_BUSY))
panic("Interrupt Dispatch Status busy bit not set.");
 
intrcv = asi_u64_read(ASI_INTR_RECEIVE, 0);
data0 = asi_u64_read(ASI_UDB_INTR_R, ASI_UDB_INTR_R_DATA_0);
#if defined (US)
data0 = asi_u64_read(ASI_INTR_R, ASI_UDB_INTR_R_DATA_0);
#elif defined (US3)
data0 = asi_u64_read(ASI_INTR_R, VA_INTR_R_DATA_0);
#endif
 
irq_t *irq = irq_dispatch_and_lock(data0);
if (irq) {
78,7 → 86,13
/*
* The IRQ handler was found.
*/
irq->handler(irq, irq->arg);
irq->handler(irq);
/*
* See if there is a clear-interrupt-routine and call it.
*/
if (irq->cir) {
irq->cir(irq->cir_arg, irq->inr);
}
spinlock_unlock(&irq->lock);
} else if (data0 > config.base) {
/*
97,8 → 111,8
* Spurious interrupt.
*/
#ifdef CONFIG_DEBUG
printf("cpu%d: spurious interrupt (intrcv=%#llx, "
"data0=%#llx)\n", CPU->id, intrcv, data0);
printf("cpu%u: spurious interrupt (intrcv=%#" PRIx64
", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0);
#endif
}
 
/branches/dd/kernel/arch/sparc64/src/trap/trap_table.S
329,198 → 329,22
fill_1_normal_tl0:
FILL_NORMAL_HANDLER_USERSPACE
 
/* TT = 0x100, TL = 0, trap_instruction_0 */
.org trap_table + TT_TRAP_INSTRUCTION(0)*ENTRY_SIZE
.global trap_instruction_0_tl0
trap_instruction_0_tl0:
TRAP_INSTRUCTION 0
/* TT = 0x100 - 0x17f, TL = 0, trap_instruction_0 - trap_instruction_7f */
.irp cur, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 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, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,\
127
.org trap_table + (TT_TRAP_INSTRUCTION_0+\cur)*ENTRY_SIZE
.global trap_instruction_\cur\()_tl0
trap_instruction_\cur\()_tl0:
ba trap_instruction_handler
mov \cur, %g2
.endr
 
/* TT = 0x101, TL = 0, trap_instruction_1 */
.org trap_table + TT_TRAP_INSTRUCTION(1)*ENTRY_SIZE
.global trap_instruction_1_tl0
trap_instruction_1_tl0:
TRAP_INSTRUCTION 1
 
/* TT = 0x102, TL = 0, trap_instruction_2 */
.org trap_table + TT_TRAP_INSTRUCTION(2)*ENTRY_SIZE
.global trap_instruction_2_tl0
trap_instruction_2_tl0:
TRAP_INSTRUCTION 2
 
/* TT = 0x103, TL = 0, trap_instruction_3 */
.org trap_table + TT_TRAP_INSTRUCTION(3)*ENTRY_SIZE
.global trap_instruction_3_tl0
trap_instruction_3_tl0:
TRAP_INSTRUCTION 3
 
/* TT = 0x104, TL = 0, trap_instruction_4 */
.org trap_table + TT_TRAP_INSTRUCTION(4)*ENTRY_SIZE
.global trap_instruction_4_tl0
trap_instruction_4_tl0:
TRAP_INSTRUCTION 4
 
/* TT = 0x105, TL = 0, trap_instruction_5 */
.org trap_table + TT_TRAP_INSTRUCTION(5)*ENTRY_SIZE
.global trap_instruction_5_tl0
trap_instruction_5_tl0:
TRAP_INSTRUCTION 5
 
/* TT = 0x106, TL = 0, trap_instruction_6 */
.org trap_table + TT_TRAP_INSTRUCTION(6)*ENTRY_SIZE
.global trap_instruction_6_tl0
trap_instruction_6_tl0:
TRAP_INSTRUCTION 6
 
/* TT = 0x107, TL = 0, trap_instruction_7 */
.org trap_table + TT_TRAP_INSTRUCTION(7)*ENTRY_SIZE
.global trap_instruction_7_tl0
trap_instruction_7_tl0:
TRAP_INSTRUCTION 7
 
/* TT = 0x108, TL = 0, trap_instruction_8 */
.org trap_table + TT_TRAP_INSTRUCTION(8)*ENTRY_SIZE
.global trap_instruction_8_tl0
trap_instruction_8_tl0:
TRAP_INSTRUCTION 8
 
/* TT = 0x109, TL = 0, trap_instruction_9 */
.org trap_table + TT_TRAP_INSTRUCTION(9)*ENTRY_SIZE
.global trap_instruction_9_tl0
trap_instruction_9_tl0:
TRAP_INSTRUCTION 9
 
/* TT = 0x10a, TL = 0, trap_instruction_10 */
.org trap_table + TT_TRAP_INSTRUCTION(10)*ENTRY_SIZE
.global trap_instruction_10_tl0
trap_instruction_10_tl0:
TRAP_INSTRUCTION 10
 
/* TT = 0x10b, TL = 0, trap_instruction_11 */
.org trap_table + TT_TRAP_INSTRUCTION(11)*ENTRY_SIZE
.global trap_instruction_11_tl0
trap_instruction_11_tl0:
TRAP_INSTRUCTION 11
 
/* TT = 0x10c, TL = 0, trap_instruction_12 */
.org trap_table + TT_TRAP_INSTRUCTION(12)*ENTRY_SIZE
.global trap_instruction_12_tl0
trap_instruction_12_tl0:
TRAP_INSTRUCTION 12
 
/* TT = 0x10d, TL = 0, trap_instruction_13 */
.org trap_table + TT_TRAP_INSTRUCTION(13)*ENTRY_SIZE
.global trap_instruction_13_tl0
trap_instruction_13_tl0:
TRAP_INSTRUCTION 13
 
/* TT = 0x10e, TL = 0, trap_instruction_14 */
.org trap_table + TT_TRAP_INSTRUCTION(14)*ENTRY_SIZE
.global trap_instruction_14_tl0
trap_instruction_14_tl0:
TRAP_INSTRUCTION 14
 
/* TT = 0x10f, TL = 0, trap_instruction_15 */
.org trap_table + TT_TRAP_INSTRUCTION(15)*ENTRY_SIZE
.global trap_instruction_15_tl0
trap_instruction_15_tl0:
TRAP_INSTRUCTION 15
 
/* TT = 0x110, TL = 0, trap_instruction_16 */
.org trap_table + TT_TRAP_INSTRUCTION(16)*ENTRY_SIZE
.global trap_instruction_16_tl0
trap_instruction_16_tl0:
TRAP_INSTRUCTION 16
 
/* TT = 0x111, TL = 0, trap_instruction_17 */
.org trap_table + TT_TRAP_INSTRUCTION(17)*ENTRY_SIZE
.global trap_instruction_17_tl0
trap_instruction_17_tl0:
TRAP_INSTRUCTION 17
 
/* TT = 0x112, TL = 0, trap_instruction_18 */
.org trap_table + TT_TRAP_INSTRUCTION(18)*ENTRY_SIZE
.global trap_instruction_18_tl0
trap_instruction_18_tl0:
TRAP_INSTRUCTION 18
 
/* TT = 0x113, TL = 0, trap_instruction_19 */
.org trap_table + TT_TRAP_INSTRUCTION(19)*ENTRY_SIZE
.global trap_instruction_19_tl0
trap_instruction_19_tl0:
TRAP_INSTRUCTION 19
 
/* TT = 0x114, TL = 0, trap_instruction_20 */
.org trap_table + TT_TRAP_INSTRUCTION(20)*ENTRY_SIZE
.global trap_instruction_20_tl0
trap_instruction_20_tl0:
TRAP_INSTRUCTION 20
 
/* TT = 0x115, TL = 0, trap_instruction_21 */
.org trap_table + TT_TRAP_INSTRUCTION(21)*ENTRY_SIZE
.global trap_instruction_21_tl0
trap_instruction_21_tl0:
TRAP_INSTRUCTION 21
 
/* TT = 0x116, TL = 0, trap_instruction_22 */
.org trap_table + TT_TRAP_INSTRUCTION(22)*ENTRY_SIZE
.global trap_instruction_22_tl0
trap_instruction_22_tl0:
TRAP_INSTRUCTION 22
 
/* TT = 0x117, TL = 0, trap_instruction_23 */
.org trap_table + TT_TRAP_INSTRUCTION(23)*ENTRY_SIZE
.global trap_instruction_23_tl0
trap_instruction_23_tl0:
TRAP_INSTRUCTION 23
 
/* TT = 0x118, TL = 0, trap_instruction_24 */
.org trap_table + TT_TRAP_INSTRUCTION(24)*ENTRY_SIZE
.global trap_instruction_24_tl0
trap_instruction_24_tl0:
TRAP_INSTRUCTION 24
 
/* TT = 0x119, TL = 0, trap_instruction_25 */
.org trap_table + TT_TRAP_INSTRUCTION(25)*ENTRY_SIZE
.global trap_instruction_25_tl0
trap_instruction_25_tl0:
TRAP_INSTRUCTION 25
 
/* TT = 0x11a, TL = 0, trap_instruction_26 */
.org trap_table + TT_TRAP_INSTRUCTION(26)*ENTRY_SIZE
.global trap_instruction_26_tl0
trap_instruction_26_tl0:
TRAP_INSTRUCTION 26
 
/* TT = 0x11b, TL = 0, trap_instruction_27 */
.org trap_table + TT_TRAP_INSTRUCTION(27)*ENTRY_SIZE
.global trap_instruction_27_tl0
trap_instruction_27_tl0:
TRAP_INSTRUCTION 27
 
/* TT = 0x11c, TL = 0, trap_instruction_28 */
.org trap_table + TT_TRAP_INSTRUCTION(28)*ENTRY_SIZE
.global trap_instruction_28_tl0
trap_instruction_28_tl0:
TRAP_INSTRUCTION 28
 
/* TT = 0x11d, TL = 0, trap_instruction_29 */
.org trap_table + TT_TRAP_INSTRUCTION(29)*ENTRY_SIZE
.global trap_instruction_29_tl0
trap_instruction_29_tl0:
TRAP_INSTRUCTION 29
 
/* TT = 0x11e, TL = 0, trap_instruction_30 */
.org trap_table + TT_TRAP_INSTRUCTION(30)*ENTRY_SIZE
.global trap_instruction_30_tl0
trap_instruction_30_tl0:
TRAP_INSTRUCTION 30
 
/* TT = 0x11f, TL = 0, trap_instruction_31 */
.org trap_table + TT_TRAP_INSTRUCTION(31)*ENTRY_SIZE
.global trap_instruction_31_tl0
trap_instruction_31_tl0:
TRAP_INSTRUCTION 31
 
/*
* Handlers for TL>0.
*/
782,10 → 606,10
add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
.else
/*
* Call the higher-level syscall handler.
* Call the higher-level syscall handler and enable interrupts.
*/
call syscall_handler
nop
wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT | PSTATE_IE_BIT, %pstate
mov %o0, %i0 ! copy the value returned by the syscall
.endif
 
924,9 → 748,8
* Fill all windows stored in the buffer.
*/
clr %g4
set PAGE_SIZE - 1, %g5
0: andcc %g7, %g5, %g0 ! PAGE_SIZE alignment check
bz 0f ! %g7 is page-aligned, no more windows to refill
0: andcc %g7, UWB_ALIGNMENT - 1, %g0 ! alignment check
bz 0f ! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
nop
 
add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
/branches/dd/kernel/arch/sparc64/src/cpu/cpu.c
32,12 → 32,46
/** @file
*/
 
#include <arch/cpu_family.h>
#include <cpu.h>
#include <arch.h>
#include <genarch/ofw/ofw_tree.h>
#include <arch/drivers/tick.h>
#include <print.h>
#include <arch/cpu_node.h>
 
/**
* Finds out the clock frequency of the current CPU.
*
* @param node node representing the current CPU in the OFW tree
* @return clock frequency if "node" is the current CPU and no error
* occurs, -1 if "node" is not the current CPU or on error
*/
static int find_cpu_frequency(ofw_tree_node_t *node)
{
ofw_tree_property_t *prop;
uint32_t mid;
 
/* 'upa-portid' for US, 'portid' for US-III, 'cpuid' for US-IV */
prop = ofw_tree_getprop(node, "upa-portid");
if ((!prop) || (!prop->value))
prop = ofw_tree_getprop(node, "portid");
if ((!prop) || (!prop->value))
prop = ofw_tree_getprop(node, "cpuid");
if (prop && prop->value) {
mid = *((uint32_t *) prop->value);
if (mid == CPU->arch.mid) {
prop = ofw_tree_getprop(node, "clock-frequency");
if (prop && prop->value) {
return *((uint32_t *) prop->value);
}
}
}
return -1;
}
 
/** Perform sparc64 specific initialization of the processor structure for the
* current processor.
*/
44,34 → 78,37
void cpu_arch_init(void)
{
ofw_tree_node_t *node;
uint32_t mid;
uint32_t clock_frequency = 0;
upa_config_t upa_config;
upa_config.value = upa_config_read();
CPU->arch.mid = upa_config.mid;
CPU->arch.mid = read_mid();
/*
* Detect processor frequency.
*/
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
while (node) {
ofw_tree_property_t *prop;
prop = ofw_tree_getprop(node, "upa-portid");
if (prop && prop->value) {
mid = *((uint32_t *) prop->value);
if (mid == CPU->arch.mid) {
prop = ofw_tree_getprop(node,
"clock-frequency");
if (prop && prop->value)
clock_frequency = *((uint32_t *)
prop->value);
}
if (is_us() || is_us_iii()) {
node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
while (node) {
int f = find_cpu_frequency(node);
if (f != -1)
clock_frequency = (uint32_t) f;
node = ofw_tree_find_peer_by_device_type(node, "cpu");
}
node = ofw_tree_find_peer_by_device_type(node, "cpu");
} else if (is_us_iv()) {
node = ofw_tree_find_child(cpus_parent(), "cmp");
while (node) {
int f;
f = find_cpu_frequency(
ofw_tree_find_child(node, "cpu@0"));
if (f != -1)
clock_frequency = (uint32_t) f;
f = find_cpu_frequency(
ofw_tree_find_child(node, "cpu@1"));
if (f != -1)
clock_frequency = (uint32_t) f;
node = ofw_tree_find_peer_by_name(node, "cmp");
}
}
 
CPU->arch.clock_frequency = clock_frequency;
tick_init();
}
124,6 → 161,15
case IMPL_ULTRASPARCIII:
impl = "UltraSPARC III";
break;
case IMPL_ULTRASPARCIII_PLUS:
impl = "UltraSPARC III+";
break;
case IMPL_ULTRASPARCIII_I:
impl = "UltraSPARC IIIi";
break;
case IMPL_ULTRASPARCIV:
impl = "UltraSPARC IV";
break;
case IMPL_ULTRASPARCIV_PLUS:
impl = "UltraSPARC IV+";
break;
135,7 → 181,7
break;
}
 
printf("cpu%d: manuf=%s, impl=%s, mask=%d (%dMHz)\n", m->id, manuf,
printf("cpu%d: manuf=%s, impl=%s, mask=%d (%d MHz)\n", m->id, manuf,
impl, m->arch.ver.mask, m->arch.clock_frequency / 1000000);
}
 
/branches/dd/kernel/arch/sparc64/src/mm/tlb.c
54,14 → 54,13
#include <arch/mm/tsb.h>
#endif
 
static void dtlb_pte_copy(pte_t *t, index_t index, bool ro);
static void itlb_pte_copy(pte_t *t, index_t index);
static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate,
const char *str);
static void do_fast_data_access_mmu_miss_fault(istate_t *istate,
tlb_tag_access_reg_t tag, const char *str);
static void do_fast_data_access_protection_fault(istate_t *istate,
tlb_tag_access_reg_t tag, const char *str);
static void dtlb_pte_copy(pte_t *, index_t, bool);
static void itlb_pte_copy(pte_t *, index_t);
static void do_fast_instruction_access_mmu_miss_fault(istate_t *, const char *);
static void do_fast_data_access_mmu_miss_fault(istate_t *, tlb_tag_access_reg_t,
const char *);
static void do_fast_data_access_protection_fault(istate_t *,
tlb_tag_access_reg_t, const char *);
 
char *context_encoding[] = {
"Primary",
86,11 → 85,11
 
/** Insert privileged mapping into DMMU TLB.
*
* @param page Virtual page address.
* @param frame Physical frame address.
* @param pagesize Page size.
* @param locked True for permanent mappings, false otherwise.
* @param cacheable True if the mapping is cacheable, false otherwise.
* @param page Virtual page address.
* @param frame Physical frame address.
* @param pagesize Page size.
* @param locked True for permanent mappings, false otherwise.
* @param cacheable True if the mapping is cacheable, false otherwise.
*/
void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize,
bool locked, bool cacheable)
103,7 → 102,7
pg.address = page;
fr.address = frame;
 
tag.value = ASID_KERNEL;
tag.context = ASID_KERNEL;
tag.vpn = pg.vpn;
 
dtlb_tag_access_write(tag.value);
126,10 → 125,10
 
/** Copy PTE to TLB.
*
* @param t Page Table Entry to be copied.
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
* @param ro If true, the entry will be created read-only, regardless of its
* w field.
* @param t Page Table Entry to be copied.
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
* @param ro If true, the entry will be created read-only, regardless
* of its w field.
*/
void dtlb_pte_copy(pte_t *t, index_t index, bool ro)
{
165,8 → 164,8
 
/** Copy PTE to ITLB.
*
* @param t Page Table Entry to be copied.
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
* @param t Page Table Entry to be copied.
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
*/
void itlb_pte_copy(pte_t *t, index_t index)
{
235,10 → 234,11
* Note that some faults (e.g. kernel faults) were already resolved by the
* low-level, assembly language part of the fast_data_access_mmu_miss handler.
*
* @param tag Content of the TLB Tag Access register as it existed when the
* trap happened. This is to prevent confusion created by clobbered
* Tag Access register during a nested DTLB miss.
* @param istate Interrupted state saved on the stack.
* @param tag Content of the TLB Tag Access register as it existed
* when the trap happened. This is to prevent confusion
* created by clobbered Tag Access register during a nested
* DTLB miss.
* @param istate Interrupted state saved on the stack.
*/
void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate)
{
287,10 → 287,11
 
/** DTLB protection fault handler.
*
* @param tag Content of the TLB Tag Access register as it existed when the
* trap happened. This is to prevent confusion created by clobbered
* Tag Access register during a nested DTLB miss.
* @param istate Interrupted state saved on the stack.
* @param tag Content of the TLB Tag Access register as it existed
* when the trap happened. This is to prevent confusion
* created by clobbered Tag Access register during a nested
* DTLB miss.
* @param istate Interrupted state saved on the stack.
*/
void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate)
{
331,6 → 332,26
}
}
 
/** Print TLB entry (for debugging purposes).
*
* The diag field has been left out in order to make this function more generic
* (there is no diag field in US3 architeture).
*
* @param i TLB entry number
* @param t TLB entry tag
* @param d TLB entry data
*/
static void print_tlb_entry(int i, tlb_tag_read_reg_t t, tlb_data_t d)
{
printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, "
"ie=%d, soft2=%#x, pfn=%#x, soft=%#x, l=%d, "
"cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
t.context, d.v, d.size, d.nfo, d.ie, d.soft2,
d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
}
 
#if defined (US)
 
/** Print contents of both TLBs. */
void tlb_print(void)
{
342,12 → 363,7
for (i = 0; i < ITLB_ENTRY_COUNT; i++) {
d.value = itlb_data_access_read(i);
t.value = itlb_tag_read_read(i);
 
printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, "
"ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, "
"cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag,
d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
print_tlb_entry(i, t, d);
}
 
printf("D-TLB contents:\n");
354,22 → 370,63
for (i = 0; i < DTLB_ENTRY_COUNT; i++) {
d.value = dtlb_data_access_read(i);
t.value = dtlb_tag_read_read(i);
printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, "
"ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, "
"cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag,
d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
print_tlb_entry(i, t, d);
}
}
 
#elif defined (US3)
 
/** Print contents of all TLBs. */
void tlb_print(void)
{
int i;
tlb_data_t d;
tlb_tag_read_reg_t t;
printf("TLB_ISMALL contents:\n");
for (i = 0; i < tlb_ismall_size(); i++) {
d.value = dtlb_data_access_read(TLB_ISMALL, i);
t.value = dtlb_tag_read_read(TLB_ISMALL, i);
print_tlb_entry(i, t, d);
}
printf("TLB_IBIG contents:\n");
for (i = 0; i < tlb_ibig_size(); i++) {
d.value = dtlb_data_access_read(TLB_IBIG, i);
t.value = dtlb_tag_read_read(TLB_IBIG, i);
print_tlb_entry(i, t, d);
}
printf("TLB_DSMALL contents:\n");
for (i = 0; i < tlb_dsmall_size(); i++) {
d.value = dtlb_data_access_read(TLB_DSMALL, i);
t.value = dtlb_tag_read_read(TLB_DSMALL, i);
print_tlb_entry(i, t, d);
}
printf("TLB_DBIG_1 contents:\n");
for (i = 0; i < tlb_dbig_size(); i++) {
d.value = dtlb_data_access_read(TLB_DBIG_0, i);
t.value = dtlb_tag_read_read(TLB_DBIG_0, i);
print_tlb_entry(i, t, d);
}
printf("TLB_DBIG_2 contents:\n");
for (i = 0; i < tlb_dbig_size(); i++) {
d.value = dtlb_data_access_read(TLB_DBIG_1, i);
t.value = dtlb_tag_read_read(TLB_DBIG_1, i);
print_tlb_entry(i, t, d);
}
}
 
#endif
 
void do_fast_instruction_access_mmu_miss_fault(istate_t *istate,
const char *str)
{
fault_if_from_uspace(istate, "%s\n", str);
fault_if_from_uspace(istate, "%s.", str);
dump_istate(istate);
panic("%s\n", str);
panic("%s.", str);
}
 
void do_fast_data_access_mmu_miss_fault(istate_t *istate,
379,12 → 436,12
 
va = tag.vpn << MMU_PAGE_WIDTH;
if (tag.context) {
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d).", str, va,
tag.context);
}
dump_istate(istate);
printf("Faulting page: %p, ASID=%d\n", va, tag.context);
panic("%s\n", str);
printf("Faulting page: %p, ASID=%d.\n", va, tag.context);
panic("%s.", str);
}
 
void do_fast_data_access_protection_fault(istate_t *istate,
395,12 → 452,12
va = tag.vpn << MMU_PAGE_WIDTH;
 
if (tag.context) {
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d).", str, va,
tag.context);
}
printf("Faulting page: %p, ASID=%d\n", va, tag.context);
dump_istate(istate);
panic("%s\n", str);
panic("%s.", str);
}
 
void dump_sfsr_and_sfar(void)
411,30 → 468,71
sfsr.value = dtlb_sfsr_read();
sfar = dtlb_sfar_read();
#if defined (US)
printf("DTLB SFSR: asi=%#x, ft=%#x, e=%d, ct=%d, pr=%d, w=%d, ow=%d, "
"fv=%d\n", sfsr.asi, sfsr.ft, sfsr.e, sfsr.ct, sfsr.pr, sfsr.w,
sfsr.ow, sfsr.fv);
#elif defined (US3)
printf("DTLB SFSR: nf=%d, asi=%#x, tm=%d, ft=%#x, e=%d, ct=%d, pr=%d, "
"w=%d, ow=%d, fv=%d\n", sfsr.nf, sfsr.asi, sfsr.tm, sfsr.ft,
sfsr.e, sfsr.ct, sfsr.pr, sfsr.w, sfsr.ow, sfsr.fv);
#endif
printf("DTLB SFAR: address=%p\n", sfar);
dtlb_sfsr_write(0);
}
 
#if defined (US3)
/** Invalidates given TLB entry if and only if it is non-locked or global.
*
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1,
* TLB_ISMALL, TLB_IBIG).
* @param entry Entry index within the given TLB.
*/
static void tlb_invalidate_entry(int tlb, index_t entry)
{
tlb_data_t d;
tlb_tag_read_reg_t t;
if (tlb == TLB_DSMALL || tlb == TLB_DBIG_0 || tlb == TLB_DBIG_1) {
d.value = dtlb_data_access_read(tlb, entry);
if (!d.l || d.g) {
t.value = dtlb_tag_read_read(tlb, entry);
d.v = false;
dtlb_tag_access_write(t.value);
dtlb_data_access_write(tlb, entry, d.value);
}
} else if (tlb == TLB_ISMALL || tlb == TLB_IBIG) {
d.value = itlb_data_access_read(tlb, entry);
if (!d.l || d.g) {
t.value = itlb_tag_read_read(tlb, entry);
d.v = false;
itlb_tag_access_write(t.value);
itlb_data_access_write(tlb, entry, d.value);
}
}
}
#endif
 
/** Invalidate all unlocked ITLB and DTLB entries. */
void tlb_invalidate_all(void)
{
int i;
tlb_data_t d;
tlb_tag_read_reg_t t;
 
/*
* Walk all ITLB and DTLB entries and remove all unlocked mappings.
*
* The kernel doesn't use global mappings so any locked global mappings
* found must have been created by someone else. Their only purpose now
* found must have been created by someone else. Their only purpose now
* is to collide with proper mappings. Invalidate immediately. It should
* be safe to invalidate them as late as now.
*/
 
#if defined (US)
tlb_data_t d;
tlb_tag_read_reg_t t;
 
for (i = 0; i < ITLB_ENTRY_COUNT; i++) {
d.value = itlb_data_access_read(i);
if (!d.l || d.g) {
444,7 → 542,7
itlb_data_access_write(i, d.value);
}
}
 
for (i = 0; i < DTLB_ENTRY_COUNT; i++) {
d.value = dtlb_data_access_read(i);
if (!d.l || d.g) {
454,7 → 552,21
dtlb_data_access_write(i, d.value);
}
}
 
#elif defined (US3)
 
for (i = 0; i < tlb_ismall_size(); i++)
tlb_invalidate_entry(TLB_ISMALL, i);
for (i = 0; i < tlb_ibig_size(); i++)
tlb_invalidate_entry(TLB_IBIG, i);
for (i = 0; i < tlb_dsmall_size(); i++)
tlb_invalidate_entry(TLB_DSMALL, i);
for (i = 0; i < tlb_dbig_size(); i++)
tlb_invalidate_entry(TLB_DBIG_0, i);
for (i = 0; i < tlb_dbig_size(); i++)
tlb_invalidate_entry(TLB_DBIG_1, i);
#endif
 
}
 
/** Invalidate all ITLB and DTLB entries that belong to specified ASID
484,9 → 596,9
/** Invalidate all ITLB and DTLB entries for specified page range in specified
* address space.
*
* @param asid Address Space ID.
* @param page First page which to sweep out from ITLB and DTLB.
* @param cnt Number of ITLB and DTLB entries to invalidate.
* @param asid Address Space ID.
* @param page First page which to sweep out from ITLB and DTLB.
* @param cnt Number of ITLB and DTLB entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
{
/branches/dd/kernel/arch/sparc64/src/mm/as.c
76,7 → 76,7
as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT *
sizeof(tsb_entry_t));
 
memsetb((uintptr_t) as->arch.itsb,
memsetb(as->arch.itsb,
(ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0);
#endif
return 0;
164,7 → 164,25
itsb_base_write(tsb_base.value);
tsb_base.base = ((uintptr_t) as->arch.dtsb) >> MMU_PAGE_WIDTH;
dtsb_base_write(tsb_base.value);
#if defined (US3)
/*
* Clear the extension registers.
* In HelenOS, primary and secondary context registers contain
* equal values and kernel misses (context 0, ie. the nucleus context)
* are excluded from the TSB miss handler, so it makes no sense
* to have separate TSBs for primary, secondary and nucleus contexts.
* Clearing the extension registers will ensure that the value of the
* TSB Base register will be used as an address of TSB, making the code
* compatible with the US port.
*/
itsb_primary_extension_write(0);
itsb_nucleus_extension_write(0);
dtsb_primary_extension_write(0);
dtsb_secondary_extension_write(0);
dtsb_nucleus_extension_write(0);
#endif
#endif
}
 
/** Perform sparc64-specific tasks when an address space is removed from the
/branches/dd/kernel/arch/sparc64/src/mm/cache.S
27,10 → 27,8
*/
 
#include <arch/arch.h>
#include <arch/mm/cache_spec.h>
 
#define DCACHE_SIZE (16 * 1024)
#define DCACHE_LINE_SIZE 32
 
#define DCACHE_TAG_SHIFT 2
 
.register %g2, #scratch
49,45 → 47,3
retl
! beware SF Erratum #51, do not put the MEMBAR here
nop
 
/** Flush only D-cache lines of one virtual color.
*
* @param o0 Virtual color to be flushed.
*/
.global dcache_flush_color
dcache_flush_color:
mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1
set DCACHE_SIZE / 2, %g2
sllx %g2, %o0, %g2
sub %g2, DCACHE_LINE_SIZE, %g2
0: stxa %g0, [%g2] ASI_DCACHE_TAG
membar #Sync
subcc %g1, 1, %g1
bnz,pt %xcc, 0b
sub %g2, DCACHE_LINE_SIZE, %g2
retl
nop
 
/** Flush only D-cache lines of one virtual color and one tag.
*
* @param o0 Virtual color to lookup the tag.
* @param o1 Tag of the cachelines to be flushed.
*/
.global dcache_flush_tag
dcache_flush_tag:
mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1
set DCACHE_SIZE / 2, %g2
sllx %g2, %o0, %g2
sub %g2, DCACHE_LINE_SIZE, %g2
0: ldxa [%g2] ASI_DCACHE_TAG, %g3
srlx %g3, DCACHE_TAG_SHIFT, %g3
cmp %g3, %o1
bnz 1f
nop
stxa %g0, [%g2] ASI_DCACHE_TAG
membar #Sync
1: subcc %g1, 1, %g1
bnz,pt %xcc, 0b
sub %g2, DCACHE_LINE_SIZE, %g2
retl
nop
/branches/dd/kernel/arch/sparc64/src/mm/tsb.c
112,9 → 112,9
tsb->data.value = 0;
tsb->data.size = PAGESIZE_8K;
tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index;
tsb->data.cp = t->c;
tsb->data.p = t->k; /* p as privileged */
tsb->data.v = t->p;
tsb->data.cp = t->c; /* cp as cache in phys.-idxed, c as cacheable */
tsb->data.p = t->k; /* p as privileged, k as kernel */
tsb->data.v = t->p; /* v as valid, p as present */
write_barrier();
173,3 → 173,4
 
/** @}
*/
 
/branches/dd/kernel/arch/sparc64/src/mm/frame.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64mm
/** @addtogroup sparc64mm
* @{
*/
/** @file
79,7 → 79,6
*/
frame_mark_unavailable(ADDR2PFN(KA2PA(PFN2ADDR(0))), 1);
}
}
 
/** @}
/branches/dd/kernel/arch/sparc64/src/mm/page.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64mm
/** @addtogroup sparc64mm
* @{
*/
/** @file
52,7 → 52,7
uintptr_t virt_page;
uintptr_t phys_page;
int pagesize_code;
} bsp_locked_dtlb_entry[DTLB_ENTRY_COUNT];
} bsp_locked_dtlb_entry[DTLB_MAX_LOCKED_ENTRIES];
 
/** Number of entries in bsp_locked_dtlb_entry array. */
static count_t bsp_locked_dtlb_entries = 0;
147,7 → 147,7
physaddr + i * sizemap[order].increment,
sizemap[order].pagesize_code, true, false);
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
/*
* Second, save the information about the mapping for APs.
*/
/branches/dd/kernel/arch/sparc64/src/drivers/fhc.c
45,6 → 45,7
#include <mm/slab.h>
#include <arch/types.h>
#include <genarch/ofw/ofw_tree.h>
#include <sysinfo/sysinfo.h>
 
fhc_t *central_fhc = NULL;
 
86,6 → 87,13
 
fhc->uart_imap = (uint32_t *) hw_map(paddr, reg->size);
/*
* Set sysinfo data needed by the uspace FHC driver.
*/
sysinfo_set_item_val("fhc.uart.size", NULL, reg->size);
sysinfo_set_item_val("fhc.uart.physical", NULL, paddr);
sysinfo_set_item_val("kbd.cir.fhc", NULL, 1);
 
return fhc;
}
 
96,13 → 104,14
fhc->uart_imap[FHC_UART_IMAP] |= IMAP_V_MASK;
break;
default:
panic("Unexpected INR (%d)\n", inr);
panic("Unexpected INR (%d).", inr);
break;
}
}
 
void fhc_clear_interrupt(fhc_t *fhc, int inr)
void fhc_clear_interrupt(void *fhcp, int inr)
{
fhc_t *fhc = (fhc_t *)fhcp;
ASSERT(fhc->uart_imap);
 
switch (inr) {
110,7 → 119,7
fhc->uart_imap[FHC_UART_ICLR] = 0;
break;
default:
panic("Unexpected INR (%d)\n", inr);
panic("Unexpected INR (%d).", inr);
break;
}
}
/branches/dd/kernel/arch/sparc64/src/drivers/kbd.c
34,19 → 34,26
 
#include <arch/drivers/kbd.h>
#include <genarch/ofw/ofw_tree.h>
 
#ifdef CONFIG_SUN_KBD
#include <genarch/kbrd/kbrd.h>
#endif
#ifdef CONFIG_Z8530
#include <genarch/kbd/z8530.h>
#include <genarch/drivers/z8530/z8530.h>
#endif
#ifdef CONFIG_NS16550
#include <genarch/kbd/ns16550.h>
#include <genarch/drivers/ns16550/ns16550.h>
#endif
 
#include <console/console.h>
#include <ddi/device.h>
#include <ddi/irq.h>
#include <arch/mm/page.h>
#include <arch/types.h>
#include <align.h>
#include <func.h>
#include <string.h>
#include <print.h>
#include <sysinfo/sysinfo.h>
 
kbd_type_t kbd_type = KBD_UNKNOWN;
 
63,6 → 70,15
uintptr_t aligned_addr;
ofw_tree_property_t *prop;
const char *name;
cir_t cir;
void *cir_arg;
 
#ifdef CONFIG_NS16550
ns16550_t *ns16550;
#endif
#ifdef CONFIG_Z8530
z8530_t *z8530;
#endif
name = ofw_tree_node_name(node);
84,30 → 100,33
*/
uint32_t interrupts;
prop = ofw_tree_getprop(node, "interrupts");
if (!prop || !prop->value)
panic("Can't find \"interrupts\" property.\n");
if ((!prop) || (!prop->value))
panic("Cannot find 'interrupt' property.");
interrupts = *((uint32_t *) prop->value);
 
/*
* Read 'reg' property.
*/
prop = ofw_tree_getprop(node, "reg");
if (!prop || !prop->value)
panic("Can't find \"reg\" property.\n");
if ((!prop) || (!prop->value))
panic("Cannot find 'reg' property.");
uintptr_t pa;
size_t size;
devno_t devno;
inr_t inr;
devno_t devno = device_assign_devno();
switch (kbd_type) {
case KBD_Z8530:
size = ((ofw_fhc_reg_t *) prop->value)->size;
if (!ofw_fhc_apply_ranges(node->parent, ((ofw_fhc_reg_t *) prop->value) , &pa)) {
if (!ofw_fhc_apply_ranges(node->parent,
((ofw_fhc_reg_t *) prop->value), &pa)) {
printf("Failed to determine keyboard address.\n");
return;
}
if (!ofw_fhc_map_interrupt(node->parent, ((ofw_fhc_reg_t *) prop->value), interrupts, &inr)) {
if (!ofw_fhc_map_interrupt(node->parent,
((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
&cir_arg)) {
printf("Failed to determine keyboard interrupt.\n");
return;
}
115,18 → 134,20
case KBD_NS16550:
size = ((ofw_ebus_reg_t *) prop->value)->size;
if (!ofw_ebus_apply_ranges(node->parent, ((ofw_ebus_reg_t *) prop->value) , &pa)) {
if (!ofw_ebus_apply_ranges(node->parent,
((ofw_ebus_reg_t *) prop->value), &pa)) {
printf("Failed to determine keyboard address.\n");
return;
}
if (!ofw_ebus_map_interrupt(node->parent, ((ofw_ebus_reg_t *) prop->value), interrupts, &inr)) {
if (!ofw_ebus_map_interrupt(node->parent,
((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
&cir_arg)) {
printf("Failed to determine keyboard interrupt.\n");
return;
};
break;
 
default:
panic("Unexpected type.\n");
panic("Unexpected keyboard type.");
}
/*
137,21 → 158,53
*/
aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
offset = pa - aligned_addr;
uintptr_t vaddr = hw_map(aligned_addr, offset + size) + offset;
 
switch (kbd_type) {
#ifdef CONFIG_Z8530
case KBD_Z8530:
z8530_init(devno, inr, vaddr);
devno = device_assign_devno();
z8530 = (z8530_t *) hw_map(aligned_addr, offset + size) +
offset;
kbrd_init(stdin);
(void) z8530_init(z8530, devno, inr, cir, cir_arg, &kbrdin);
/*
* This is the necessary evil until the userspace drivers are
* entirely self-sufficient.
*/
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, inr);
sysinfo_set_item_val("kbd.address.kernel", NULL,
(uintptr_t) z8530);
sysinfo_set_item_val("kbd.address.physical", NULL, pa);
break;
#endif
#ifdef CONFIG_NS16550
case KBD_NS16550:
ns16550_init(devno, inr, vaddr);
devno = device_assign_devno();
ns16550 = (ns16550_t *) hw_map(aligned_addr, offset + size) +
offset;
kbrd_init(stdin);
(void) ns16550_init(ns16550, devno, inr, cir, cir_arg, &kbrdin);
/*
* This is the necessary evil until the userspace driver is
* entirely self-sufficient.
*/
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, inr);
sysinfo_set_item_val("kbd.address.kernel", NULL,
(uintptr_t) ns16550);
sysinfo_set_item_val("kbd.address.physical", NULL, pa);
break;
#endif
default:
printf("Kernel is not compiled with the necessary keyboard driver this machine requires.\n");
printf("Kernel is not compiled with the necessary keyboard "
"driver this machine requires.\n");
}
}
 
/branches/dd/kernel/arch/sparc64/src/drivers/scr.c
37,7 → 37,7
#include <genarch/fb/fb.h>
#include <genarch/fb/visuals.h>
#include <arch/types.h>
#include <func.h>
#include <string.h>
#include <align.h>
#include <print.h>
 
55,6 → 55,10
void scr_init(ofw_tree_node_t *node)
{
ofw_tree_property_t *prop;
ofw_pci_reg_t *pci_reg;
ofw_pci_reg_t pci_abs_reg;
ofw_upa_reg_t *upa_reg;
ofw_sbus_reg_t *sbus_reg;
const char *name;
name = ofw_tree_node_name(node);
61,6 → 65,8
if (strcmp(name, "SUNW,m64B") == 0)
scr_type = SCR_ATYFB;
else if (strcmp(name, "SUNW,XVR-100") == 0)
scr_type = SCR_XVR;
else if (strcmp(name, "SUNW,ffb") == 0)
scr_type = SCR_FFB;
else if (strcmp(name, "cgsix") == 0)
67,11 → 73,12
scr_type = SCR_CGSIX;
if (scr_type == SCR_UNKNOWN) {
printf("Unknown keyboard device.\n");
printf("Unknown screen device.\n");
return;
}
uintptr_t fb_addr;
unsigned int fb_offset = 0;
uint32_t fb_width = 0;
uint32_t fb_height = 0;
uint32_t fb_depth = 0;
97,7 → 104,7
 
prop = ofw_tree_getprop(node, "reg");
if (!prop)
panic("Can't find \"reg\" property.\n");
panic("Cannot find 'reg' property.");
 
switch (scr_type) {
case SCR_ATYFB:
106,15 → 113,15
return;
}
ofw_pci_reg_t *fb_reg = &((ofw_pci_reg_t *) prop->value)[1];
ofw_pci_reg_t abs_reg;
pci_reg = &((ofw_pci_reg_t *) prop->value)[1];
if (!ofw_pci_reg_absolutize(node, fb_reg, &abs_reg)) {
if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
printf("Failed to absolutize fb register.\n");
return;
}
if (!ofw_pci_apply_ranges(node->parent, &abs_reg , &fb_addr)) {
if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
&fb_addr)) {
printf("Failed to determine screen address.\n");
return;
}
142,12 → 149,56
}
break;
case SCR_XVR:
if (prop->size / sizeof(ofw_pci_reg_t) < 2) {
printf("Too few screen registers.\n");
return;
}
pci_reg = &((ofw_pci_reg_t *) prop->value)[1];
if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
printf("Failed to absolutize fb register.\n");
return;
}
if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
&fb_addr)) {
printf("Failed to determine screen address.\n");
return;
}
 
fb_offset = 4 * 0x2000;
 
switch (fb_depth) {
case 8:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_INDIRECT_8;
break;
case 16:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_5_6_5;
break;
case 24:
fb_scanline = fb_linebytes * 4;
visual = VISUAL_RGB_8_8_8_0;
break;
case 32:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_0_8_8_8;
break;
default:
printf("Unsupported bits per pixel.\n");
return;
}
break;
case SCR_FFB:
fb_scanline = 8192;
visual = VISUAL_BGR_0_8_8_8;
 
ofw_upa_reg_t *reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP];
if (!ofw_upa_apply_ranges(node->parent, reg, &fb_addr)) {
upa_reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP];
if (!ofw_upa_apply_ranges(node->parent, upa_reg, &fb_addr)) {
printf("Failed to determine screen address.\n");
return;
}
164,8 → 215,8
return;
}
ofw_sbus_reg_t *cg6_reg = &((ofw_sbus_reg_t *) prop->value)[0];
if (!ofw_sbus_apply_ranges(node->parent, cg6_reg, &fb_addr)) {
sbus_reg = &((ofw_sbus_reg_t *) prop->value)[0];
if (!ofw_sbus_apply_ranges(node->parent, sbus_reg, &fb_addr)) {
printf("Failed to determine screen address.\n");
return;
}
172,11 → 223,24
break;
default:
panic("Unexpected type.\n");
panic("Unexpected type.");
}
 
fb_init(fb_addr, fb_width, fb_height, fb_scanline, visual);
fb_properties_t props = {
.addr = fb_addr,
.offset = fb_offset,
.x = fb_width,
.y = fb_height,
.scan = fb_scanline,
.visual = visual,
};
fb_init(&props);
}
 
void scr_redraw(void)
{
fb_redraw();
}
 
/** @}
*/
/branches/dd/kernel/arch/sparc64/src/drivers/tick.c
45,11 → 45,12
 
#define TICK_RESTART_TIME 50 /* Worst case estimate. */
 
/** Initialize tick interrupt. */
/** Initialize tick and stick interrupt. */
void tick_init(void)
{
/* initialize TICK interrupt */
tick_compare_reg_t compare;
 
interrupt_register(14, "tick_int", tick_interrupt);
compare.int_dis = false;
compare.tick_cmpr = CPU->arch.clock_frequency / HZ;
56,6 → 57,21
CPU->arch.next_tick_cmpr = compare.tick_cmpr;
tick_compare_write(compare.value);
tick_write(0);
 
#if defined (US3)
/* disable STICK interrupts and clear any pending ones */
tick_compare_reg_t stick_compare;
softint_reg_t clear;
 
stick_compare.value = stick_compare_read();
stick_compare.int_dis = true;
stick_compare.tick_cmpr = 0;
stick_compare_write(stick_compare.value);
 
clear.value = 0;
clear.stick_int = 1;
clear_softint_write(clear.value);
#endif
}
 
/** Process tick interrupt.
67,7 → 83,7
{
softint_reg_t softint, clear;
uint64_t drift;
 
softint.value = softint_read();
/*
/branches/dd/kernel/arch/sparc64/src/drivers/sgcn.c
0,0 → 1,436
/*
* Copyright (c) 2008 Pavel Rimsky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64
* @{
*/
/**
* @file
* @brief SGCN driver.
*/
 
#include <arch/drivers/sgcn.h>
#include <arch/drivers/kbd.h>
#include <genarch/ofw/ofw_tree.h>
#include <debug.h>
#include <string.h>
#include <print.h>
#include <mm/page.h>
#include <ipc/irq.h>
#include <ddi/ddi.h>
#include <ddi/device.h>
#include <console/chardev.h>
#include <console/console.h>
#include <ddi/device.h>
#include <sysinfo/sysinfo.h>
#include <synch/spinlock.h>
 
/*
* Physical address at which the SBBC starts. This value has been obtained
* by inspecting (using Simics) memory accesses made by OBP. It is valid
* for the Simics-simulated Serengeti machine. The author of this code is
* not sure whether this value is valid generally.
*/
#define SBBC_START 0x63000000000
 
/* offset of SRAM within the SBBC memory */
#define SBBC_SRAM_OFFSET 0x900000
 
/* size (in bytes) of the physical memory area which will be mapped */
#define MAPPED_AREA_SIZE (128 * 1024)
 
/* magic string contained at the beginning of SRAM */
#define SRAM_TOC_MAGIC "TOCSRAM"
 
/*
* Key into the SRAM table of contents which identifies the entry
* describing the OBP console buffer. It is worth mentioning
* that the OBP console buffer is not the only console buffer
* which can be used. It is, however, used because when the kernel
* is running, the OBP buffer is not used by OBP any more but OBP
* has already made neccessary arangements so that the output will
* be read from the OBP buffer and input will go to the OBP buffer.
* Therefore HelenOS needs to make no such arrangements any more.
*/
#define CONSOLE_KEY "OBPCONS"
 
/* magic string contained at the beginning of the console buffer */
#define SGCN_BUFFER_MAGIC "CON"
 
/**
* The driver is polling based, but in order to notify the userspace
* of a key being pressed, we need to supply the interface with some
* interrupt number. The interrupt number can be arbitrary as it it
* will never be used for identifying HW interrupts, but only in
* notifying the userspace.
*/
#define FICTIONAL_INR 1
 
 
/*
* Returns a pointer to the object of a given type which is placed at the given
* offset from the SRAM beginning.
*/
#define SRAM(type, offset) ((type *) (sram_begin + (offset)))
 
/* Returns a pointer to the SRAM table of contents. */
#define SRAM_TOC (SRAM(iosram_toc_t, 0))
 
/*
* Returns a pointer to the object of a given type which is placed at the given
* offset from the console buffer beginning.
*/
#define SGCN_BUFFER(type, offset) \
((type *) (sgcn_buffer_begin + (offset)))
 
/** Returns a pointer to the console buffer header. */
#define SGCN_BUFFER_HEADER (SGCN_BUFFER(sgcn_buffer_header_t, 0))
 
/** defined in drivers/kbd.c */
extern kbd_type_t kbd_type;
 
/** starting address of SRAM, will be set by the init_sram_begin function */
static uintptr_t sram_begin;
 
/**
* starting address of the SGCN buffer, will be set by the
* init_sgcn_buffer_begin function
*/
static uintptr_t sgcn_buffer_begin;
 
/**
* SGCN IRQ structure. So far used only for notifying the userspace of the
* key being pressed, not for kernel being informed about keyboard interrupts.
*/
static irq_t sgcn_irq;
 
// TODO think of a way how to synchronize accesses to SGCN buffer between the kernel and the userspace
 
/*
* Ensures that writing to the buffer and consequent update of the write pointer
* are together one atomic operation.
*/
SPINLOCK_INITIALIZE(sgcn_output_lock);
 
/*
* Prevents the input buffer read/write pointers from getting to inconsistent
* state.
*/
SPINLOCK_INITIALIZE(sgcn_input_lock);
 
 
/* functions referenced from definitions of I/O operations structures */
static void sgcn_noop(chardev_t *);
static void sgcn_putchar(chardev_t *, const char, bool);
static char sgcn_key_read(chardev_t *);
 
/** character device operations */
static chardev_operations_t sgcn_ops = {
.suspend = sgcn_noop,
.resume = sgcn_noop,
.read = sgcn_key_read,
.write = sgcn_putchar
};
 
/** SGCN character device */
chardev_t sgcn_io;
 
/**
* Set some sysinfo values (SRAM address and SRAM size).
*/
static void register_sram(uintptr_t sram_begin_physical)
{
sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE);
sysinfo_set_item_val("sram.address.physical", NULL,
sram_begin_physical);
}
 
/**
* Initializes the starting address of SRAM.
*
* The SRAM starts 0x900000 + C bytes behind the SBBC start in the
* physical memory, where C is the value read from the "iosram-toc"
* property of the "/chosen" OBP node. The sram_begin variable will
* be set to the virtual address which maps to the SRAM physical
* address.
*
* It also registers the physical area of SRAM and sets some sysinfo
* values (SRAM address and SRAM size).
*/
static void init_sram_begin(void)
{
ofw_tree_node_t *chosen;
ofw_tree_property_t *iosram_toc;
uintptr_t sram_begin_physical;
 
chosen = ofw_tree_lookup("/chosen");
if (!chosen)
panic("Cannot find '/chosen'.");
 
iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
if (!iosram_toc)
panic("Cannot find property 'iosram-toc'.");
if (!iosram_toc->value)
panic("Cannot find SRAM TOC.");
 
sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
+ *((uint32_t *) iosram_toc->value);
sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
register_sram(sram_begin_physical);
}
 
/**
* Initializes the starting address of the SGCN buffer.
*
* The offset of the SGCN buffer within SRAM is obtained from the
* SRAM table of contents. The table of contents contains
* information about several buffers, among which there is an OBP
* console buffer - this one will be used as the SGCN buffer.
*
* This function also writes the offset of the SGCN buffer within SRAM
* under the sram.buffer.offset sysinfo key.
*/
static void sgcn_buffer_begin_init(void)
{
init_sram_begin();
ASSERT(strcmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
/* lookup TOC entry with the correct key */
uint32_t i;
for (i = 0; i < MAX_TOC_ENTRIES; i++) {
if (strcmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
break;
}
ASSERT(i < MAX_TOC_ENTRIES);
sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset;
sysinfo_set_item_val("sram.buffer.offset", NULL,
SRAM_TOC->keys[i].offset);
}
 
/**
* Default suspend/resume operation for the input device.
*/
static void sgcn_noop(chardev_t *d)
{
}
 
/**
* Writes a single character to the SGCN (circular) output buffer
* and updates the output write pointer so that SGCN gets to know
* that the character has been written.
*/
static void sgcn_do_putchar(const char c)
{
uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
uint32_t end = SGCN_BUFFER_HEADER->out_end;
uint32_t size = end - begin;
/* we need pointers to volatile variables */
volatile char *buf_ptr = (volatile char *)
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
 
/*
* Write the character and increment the write pointer modulo the
* output buffer size. Note that if we are to rewrite a character
* which has not been read by the SGCN controller yet (i.e. the output
* buffer is full), we need to wait until the controller reads some more
* characters. We wait actively, which means that all threads waiting
* for the lock are blocked. However, this situation is
* 1) rare - the output buffer is big, so filling the whole
* output buffer is improbable
* 2) short-lasting - it will take the controller only a fraction
* of millisecond to pick the unread characters up
* 3) not serious - the blocked threads are those that print something
* to user console, which is not a time-critical operation
*/
uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
while (*out_rdptr_ptr == new_wrptr)
;
*buf_ptr = c;
*out_wrptr_ptr = new_wrptr;
}
 
/**
* SGCN output operation. Prints a single character to the SGCN. If the line
* feed character is written ('\n'), the carriage return character ('\r') is
* written straight away.
*/
static void sgcn_putchar(struct chardev * cd, const char c, bool silent)
{
if (!silent) {
spinlock_lock(&sgcn_output_lock);
sgcn_do_putchar(c);
if (c == '\n')
sgcn_do_putchar('\r');
spinlock_unlock(&sgcn_output_lock);
}
}
 
/**
* Called when actively reading the character. Not implemented yet.
*/
static char sgcn_key_read(chardev_t *d)
{
return (char) 0;
}
 
/**
* The driver works in polled mode, so no interrupt should be handled by it.
*/
static irq_ownership_t sgcn_claim(irq_t *irq)
{
return IRQ_DECLINE;
}
 
/**
* The driver works in polled mode, so no interrupt should be handled by it.
*/
static void sgcn_irq_handler(irq_t *irq)
{
panic("Not yet implemented, SGCN works in polled mode.");
}
 
/**
* Grabs the input for kernel.
*/
void sgcn_grab(void)
{
ipl_t ipl = interrupts_disable();
volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
/* skip all the user typed before the grab and hasn't been processed */
spinlock_lock(&sgcn_input_lock);
*in_rdptr_ptr = *in_wrptr_ptr;
spinlock_unlock(&sgcn_input_lock);
 
spinlock_lock(&sgcn_irq.lock);
sgcn_irq.notif_cfg.notify = false;
spinlock_unlock(&sgcn_irq.lock);
interrupts_restore(ipl);
}
 
/**
* Releases the input so that userspace can use it.
*/
void sgcn_release(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&sgcn_irq.lock);
if (sgcn_irq.notif_cfg.answerbox)
sgcn_irq.notif_cfg.notify = true;
spinlock_unlock(&sgcn_irq.lock);
interrupts_restore(ipl);
}
 
/**
* Function regularly called by the keyboard polling thread. Finds out whether
* there are some unread characters in the input queue. If so, it picks them up
* and sends them to the upper layers of HelenOS.
*/
void sgcn_poll(void)
{
uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
uint32_t end = SGCN_BUFFER_HEADER->in_end;
uint32_t size = end - begin;
spinlock_lock(&sgcn_input_lock);
ipl_t ipl = interrupts_disable();
spinlock_lock(&sgcn_irq.lock);
/* we need pointers to volatile variables */
volatile char *buf_ptr = (volatile char *)
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
if (*in_rdptr_ptr != *in_wrptr_ptr) {
/* XXX: send notification to userspace */
}
spinlock_unlock(&sgcn_irq.lock);
interrupts_restore(ipl);
 
while (*in_rdptr_ptr != *in_wrptr_ptr) {
buf_ptr = (volatile char *)
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
char c = *buf_ptr;
*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
if (c == '\r') {
c = '\n';
}
chardev_push_character(&sgcn_io, c);
}
spinlock_unlock(&sgcn_input_lock);
}
 
/**
* A public function which initializes I/O from/to Serengeti console
* and sets it as a default input/output.
*/
void sgcn_init(void)
{
sgcn_buffer_begin_init();
 
kbd_type = KBD_SGCN;
 
devno_t devno = device_assign_devno();
irq_initialize(&sgcn_irq);
sgcn_irq.devno = devno;
sgcn_irq.inr = FICTIONAL_INR;
sgcn_irq.claim = sgcn_claim;
sgcn_irq.handler = sgcn_irq_handler;
irq_register(&sgcn_irq);
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, FICTIONAL_INR);
sysinfo_set_item_val("fb.kind", NULL, 4);
chardev_initialize("sgcn_io", &sgcn_io, &sgcn_ops);
stdin = &sgcn_io;
stdout = &sgcn_io;
}
 
/** @}
*/
/branches/dd/kernel/arch/sparc64/src/drivers/pci.c
42,43 → 42,41
#include <arch/types.h>
#include <debug.h>
#include <print.h>
#include <func.h>
#include <string.h>
#include <arch/asm.h>
#include <sysinfo/sysinfo.h>
 
#define PCI_SABRE_REGS_REG 0
#define SABRE_INTERNAL_REG 0
#define PSYCHO_INTERNAL_REG 2
 
#define PCI_SABRE_IMAP_BASE 0x200
#define PCI_SABRE_ICLR_BASE 0x300
#define OBIO_IMR_BASE 0x200
#define OBIO_IMR(ino) (OBIO_IMR_BASE + ((ino) & INO_MASK))
 
#define PCI_PSYCHO_REGS_REG 2
#define OBIO_CIR_BASE 0x300
#define OBIO_CIR(ino) (OBIO_CIR_BASE + ((ino) & INO_MASK))
 
#define PCI_PSYCHO_IMAP_BASE 0x200
#define PCI_PSYCHO_ICLR_BASE 0x300
static void obio_enable_interrupt(pci_t *, int);
static void obio_clear_interrupt(pci_t *, int);
 
static pci_t *pci_sabre_init(ofw_tree_node_t *node);
static void pci_sabre_enable_interrupt(pci_t *pci, int inr);
static void pci_sabre_clear_interrupt(pci_t *pci, int inr);
static pci_t *pci_sabre_init(ofw_tree_node_t *);
static pci_t *pci_psycho_init(ofw_tree_node_t *);
 
static pci_t *pci_psycho_init(ofw_tree_node_t *node);
static void pci_psycho_enable_interrupt(pci_t *pci, int inr);
static void pci_psycho_clear_interrupt(pci_t *pci, int inr);
 
/** PCI operations for Sabre model. */
static pci_operations_t pci_sabre_ops = {
.enable_interrupt = pci_sabre_enable_interrupt,
.clear_interrupt = pci_sabre_clear_interrupt
.enable_interrupt = obio_enable_interrupt,
.clear_interrupt = obio_clear_interrupt
};
/** PCI operations for Psycho model. */
static pci_operations_t pci_psycho_ops = {
.enable_interrupt = pci_psycho_enable_interrupt,
.clear_interrupt = pci_psycho_clear_interrupt
.enable_interrupt = obio_enable_interrupt,
.clear_interrupt = obio_clear_interrupt
};
 
/** Initialize PCI controller (model Sabre).
*
* @param node OpenFirmware device tree node of the Sabre.
* @param node OpenFirmware device tree node of the Sabre.
*
* @return Address of the initialized PCI structure.
* @return Address of the initialized PCI structure.
*/
pci_t *pci_sabre_init(ofw_tree_node_t *node)
{
95,11 → 93,12
ofw_upa_reg_t *reg = prop->value;
count_t regs = prop->size / sizeof(ofw_upa_reg_t);
 
if (regs < PCI_SABRE_REGS_REG + 1)
if (regs < SABRE_INTERNAL_REG + 1)
return NULL;
 
uintptr_t paddr;
if (!ofw_upa_apply_ranges(node->parent, &reg[PCI_SABRE_REGS_REG], &paddr))
if (!ofw_upa_apply_ranges(node->parent, &reg[SABRE_INTERNAL_REG],
&paddr))
return NULL;
 
pci = (pci_t *) malloc(sizeof(pci_t), FRAME_ATOMIC);
108,8 → 107,14
 
pci->model = PCI_SABRE;
pci->op = &pci_sabre_ops;
pci->reg = (uint64_t *) hw_map(paddr, reg[PCI_SABRE_REGS_REG].size);
pci->reg = (uint64_t *) hw_map(paddr, reg[SABRE_INTERNAL_REG].size);
 
/*
* Set sysinfo data needed by the uspace OBIO driver.
*/
sysinfo_set_item_val("obio.base.physical", NULL, paddr);
sysinfo_set_item_val("kbd.cir.obio", NULL, 1);
 
return pci;
}
 
116,9 → 121,9
 
/** Initialize the Psycho PCI controller.
*
* @param node OpenFirmware device tree node of the Psycho.
* @param node OpenFirmware device tree node of the Psycho.
*
* @return Address of the initialized PCI structure.
* @return Address of the initialized PCI structure.
*/
pci_t *pci_psycho_init(ofw_tree_node_t *node)
{
135,11 → 140,12
ofw_upa_reg_t *reg = prop->value;
count_t regs = prop->size / sizeof(ofw_upa_reg_t);
 
if (regs < PCI_PSYCHO_REGS_REG + 1)
if (regs < PSYCHO_INTERNAL_REG + 1)
return NULL;
 
uintptr_t paddr;
if (!ofw_upa_apply_ranges(node->parent, &reg[PCI_PSYCHO_REGS_REG], &paddr))
if (!ofw_upa_apply_ranges(node->parent, &reg[PSYCHO_INTERNAL_REG],
&paddr))
return NULL;
 
pci = (pci_t *) malloc(sizeof(pci_t), FRAME_ATOMIC);
148,31 → 154,27
 
pci->model = PCI_PSYCHO;
pci->op = &pci_psycho_ops;
pci->reg = (uint64_t *) hw_map(paddr, reg[PCI_PSYCHO_REGS_REG].size);
pci->reg = (uint64_t *) hw_map(paddr, reg[PSYCHO_INTERNAL_REG].size);
 
/*
* Set sysinfo data needed by the uspace OBIO driver.
*/
sysinfo_set_item_val("obio.base.physical", NULL, paddr);
sysinfo_set_item_val("kbd.cir.obio", NULL, 1);
 
return pci;
}
 
void pci_sabre_enable_interrupt(pci_t *pci, int inr)
void obio_enable_interrupt(pci_t *pci, int inr)
{
pci->reg[PCI_SABRE_IMAP_BASE + (inr & INO_MASK)] |= IMAP_V_MASK;
pci->reg[OBIO_IMR(inr & INO_MASK)] |= IMAP_V_MASK;
}
 
void pci_sabre_clear_interrupt(pci_t *pci, int inr)
void obio_clear_interrupt(pci_t *pci, int inr)
{
pci->reg[PCI_SABRE_ICLR_BASE + (inr & INO_MASK)] = 0;
pci->reg[OBIO_CIR(inr & INO_MASK)] = 0; /* set IDLE */
}
 
void pci_psycho_enable_interrupt(pci_t *pci, int inr)
{
pci->reg[PCI_PSYCHO_IMAP_BASE + (inr & INO_MASK)] |= IMAP_V_MASK;
}
 
void pci_psycho_clear_interrupt(pci_t *pci, int inr)
{
pci->reg[PCI_PSYCHO_ICLR_BASE + (inr & INO_MASK)] = 0;
}
 
/** Initialize PCI controller. */
pci_t *pci_init(ofw_tree_node_t *node)
{
215,14 → 217,14
 
void pci_enable_interrupt(pci_t *pci, int inr)
{
ASSERT(pci->model);
ASSERT(pci->op && pci->op->enable_interrupt);
pci->op->enable_interrupt(pci, inr);
}
 
void pci_clear_interrupt(pci_t *pci, int inr)
void pci_clear_interrupt(void *pcip, int inr)
{
ASSERT(pci->model);
pci_t *pci = (pci_t *)pcip;
 
ASSERT(pci->op && pci->op->clear_interrupt);
pci->op->clear_interrupt(pci, inr);
}
/branches/dd/kernel/arch/sparc64/src/start.S
27,6 → 27,7
#
 
#include <arch/arch.h>
#include <arch/cpu.h>
#include <arch/regdef.h>
#include <arch/boot/boot.h>
#include <arch/stack.h>
47,6 → 48,16
#define BSP_FLAG 1
 
/*
* 2^PHYSMEM_ADDR_SIZE is the size of the physical address space on
* a given processor.
*/
#if defined (US)
#define PHYSMEM_ADDR_SIZE 41
#elif defined (US3)
#define PHYSMEM_ADDR_SIZE 43
#endif
 
/*
* Here is where the kernel is passed control from the boot loader.
*
* The registers are expected to be in this state:
67,11 → 78,13
and %o0, %l0, %l7 ! l7 <= bootstrap processor?
andn %o0, %l0, %l6 ! l6 <= start of physical memory
 
! Get bits 40:13 of physmem_base.
! Get bits (PHYSMEM_ADDR_SIZE - 1):13 of physmem_base.
srlx %l6, 13, %l5
sllx %l5, 13 + (63 - 40), %l5
srlx %l5, 63 - 40, %l5 ! l5 <= physmem_base[40:13]
! l5 <= physmem_base[(PHYSMEM_ADDR_SIZE - 1):13]
sllx %l5, 13 + (63 - (PHYSMEM_ADDR_SIZE - 1)), %l5
srlx %l5, 63 - (PHYSMEM_ADDR_SIZE - 1), %l5
/*
* Setup basic runtime environment.
*/
83,6 → 96,8
! consistent
wrpr %g0, NWINDOWS - 1, %cleanwin ! prevent needless clean_window
! traps for kernel
wrpr %g0, 0, %wstate ! use default spill/fill trap
 
wrpr %g0, 0, %tl ! TL = 0, primary context
! register is used
244,7 → 259,8
 
/*
* Precompute kernel 8K TLB data template.
* %l5 contains starting physical address bits [40:13]
* %l5 contains starting physical address
* bits [(PHYSMEM_ADDR_SIZE - 1):13]
*/
sethi %hi(kernel_8k_tlb_data_template), %l4
ldx [%l4 + %lo(kernel_8k_tlb_data_template)], %l3
282,15 → 298,32
nop
 
 
1:
#ifdef CONFIG_SMP
/*
* Determine the width of the MID and save its mask to %g3. The width
* is
* * 5 for US and US-IIIi,
* * 10 for US3 except US-IIIi.
*/
#if defined(US)
mov 0x1f, %g3
#elif defined(US3)
mov 0x3ff, %g3
rdpr %ver, %g2
sllx %g2, 16, %g2
srlx %g2, 48, %g2
cmp %g2, IMPL_ULTRASPARCIII_I
move %xcc, 0x1f, %g3
#endif
 
/*
* Read MID from the processor.
*/
1:
ldxa [%g0] ASI_UPA_CONFIG, %g1
srlx %g1, UPA_CONFIG_MID_SHIFT, %g1
and %g1, UPA_CONFIG_MID_MASK, %g1
ldxa [%g0] ASI_ICBUS_CONFIG, %g1
srlx %g1, ICBUS_CONFIG_MID_SHIFT, %g1
and %g1, %g3, %g1
 
#ifdef CONFIG_SMP
/*
* Active loop for APs until the BSP picks them up. A processor cannot
* leave the loop until the global variable 'waking_up_mid' equals its
/branches/dd/kernel/arch/ia64/include/interrupt.h
50,10 → 50,13
#define IVT_FIRST 0
 
/** External Interrupt vectors. */
 
#define VECTOR_TLB_SHOOTDOWN_IPI 0xf0
#define INTERRUPT_TIMER 255
#define IRQ_KBD 241
#define IRQ_MOUSE 252
#define IRQ_KBD (0x01 + LEGACY_INTERRUPT_BASE)
#define IRQ_MOUSE (0x0c + LEGACY_INTERRUPT_BASE)
#define INTERRUPT_SPURIOUS 15
#define LEGACY_INTERRUPT_BASE 0x20
 
/** General Exception codes. */
#define GE_ILLEGALOP 0
114,7 → 117,7
/*
* The following variables are defined only for break_instruction
* handler.
* handler.
*/
uint64_t in0;
uint64_t in1;
150,6 → 153,8
extern void external_interrupt(uint64_t vector, istate_t *istate);
extern void disabled_fp_register(uint64_t vector, istate_t *istate);
 
extern void trap_virtual_enable_irqs(uint16_t irqmask);
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia64/include/fpu_context.h
35,7 → 35,6
#ifndef KERN_ia64_FPU_CONTEXT_H_
#define KERN_ia64_FPU_CONTEXT_H_
 
#define ARCH_HAS_FPU 1
#define FPU_CONTEXT_ALIGN 16
 
#include <arch/types.h>
/branches/dd/kernel/arch/ia64/include/types.h
35,10 → 35,6
#ifndef KERN_ia64_TYPES_H_
#define KERN_ia64_TYPES_H_
 
#define NULL 0
#define false 0
#define true 1
 
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
69,14 → 65,34
typedef uint64_t unative_t;
typedef int64_t native_t;
 
typedef uint8_t bool;
typedef uint64_t thread_id_t;
typedef uint64_t task_id_t;
typedef uint32_t context_id_t;
typedef struct {
unative_t fnc;
unative_t gp;
} fncptr_t;
 
typedef int32_t inr_t;
typedef int32_t devno_t;
#define PRIp "lx" /**< Format for uintptr_t. */
#define PRIs "lu" /**< Format for size_t. */
#define PRIc "lu" /**< Format for count_t. */
#define PRIi "lu" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
#define PRId32 "d" /**< Format for int32_t. */
#define PRId64 "ld" /**< Format for int64_t. */
#define PRIdn "d" /**< Format for native_t. */
 
#define PRIu8 "u" /**< Format for uint8_t. */
#define PRIu16 "u" /**< Format for uint16_t. */
#define PRIu32 "u" /**< Format for uint32_t. */
#define PRIu64 "lu" /**< Format for uint64_t. */
#define PRIun "u" /**< Format for unative_t. */
 
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */
#define PRIx64 "lx" /**< Format for hexadecimal (u)int64_t. */
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia64/include/memstr.h
37,10 → 37,10
 
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt))
 
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x);
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x);
extern void memsetw(void *dst, size_t cnt, uint16_t x);
extern void memsetb(void *dst, size_t cnt, uint8_t x);
 
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt);
extern int memcmp(const void *a, const void *b, size_t cnt);
 
#endif
 
/branches/dd/kernel/arch/ia64/include/atomic.h
37,29 → 37,65
 
/** Atomic addition.
*
* @param val Atomic value.
* @param imm Value to add.
* @param val Atomic value.
* @param imm Value to add.
*
* @return Value before addition.
* @return Value before addition.
*/
static inline long atomic_add(atomic_t *val, int imm)
{
long v;
 
asm volatile ("fetchadd8.rel %0 = %1, %2\n" : "=r" (v), "+m" (val->count) : "i" (imm));
asm volatile ("fetchadd8.rel %0 = %1, %2\n" : "=r" (v),
"+m" (val->count) : "i" (imm));
return v;
}
 
static inline void atomic_inc(atomic_t *val) { atomic_add(val, 1); }
static inline void atomic_dec(atomic_t *val) { atomic_add(val, -1); }
 
static inline long atomic_preinc(atomic_t *val) { return atomic_add(val, 1) + 1; }
static inline long atomic_predec(atomic_t *val) { return atomic_add(val, -1) - 1; }
static inline uint64_t test_and_set(atomic_t *val) {
uint64_t v;
asm volatile (
"movl %0 = 0x01;;\n"
"xchg8 %0 = %1, %0;;\n"
: "=r" (v), "+m" (val->count)
);
return v;
}
 
static inline long atomic_postinc(atomic_t *val) { return atomic_add(val, 1); }
static inline long atomic_postdec(atomic_t *val) { return atomic_add(val, -1); }
 
static inline void atomic_inc(atomic_t *val)
{
atomic_add(val, 1);
}
 
static inline void atomic_dec(atomic_t *val)
{
atomic_add(val, -1);
}
 
static inline long atomic_preinc(atomic_t *val)
{
return atomic_add(val, 1) + 1;
}
 
static inline long atomic_predec(atomic_t *val)
{
return atomic_add(val, -1) - 1;
}
 
static inline long atomic_postinc(atomic_t *val)
{
return atomic_add(val, 1);
}
 
static inline long atomic_postdec(atomic_t *val)
{
return atomic_add(val, -1);
}
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia64/include/arch.h
39,6 → 39,8
 
#include <arch/ski/ski.h>
 
extern void arch_pre_main(void);
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia64/include/proc/task.h
31,14 → 31,19
*/
/** @file
*/
#include <proc/task.h>
 
#ifndef KERN_ia64_TASK_H_
#define KERN_ia64_TASK_H_
 
#include <adt/bitmap.h>
 
typedef struct {
bitmap_t *iomap;
} task_arch_t;
 
#define task_create_arch(t)
 
#define task_create_arch(t) { (t)->arch.iomap = NULL; }
#define task_destroy_arch(t)
 
#endif
/branches/dd/kernel/arch/ia64/include/bootinfo.h
29,13 → 29,23
#ifndef KERN_ia64_BOOTINFO_H_
#define KERN_ia64_BOOTINFO_H_
 
#define BOOTINFO_ADDRESS 0x4401000
 
 
#define CONFIG_INIT_TASKS 32
 
#define MEMMAP_ITEMS 128
 
#define EFI_MEMMAP_FREE_MEM 0
#define EFI_MEMMAP_IO 1
#define EFI_MEMMAP_IO_PORTS 2
 
/** Size of buffer for storing task name in binit_task_t. */
#define BOOTINFO_TASK_NAME_BUFLEN 32
 
typedef struct {
void *addr;
unsigned long size;
char name[BOOTINFO_TASK_NAME_BUFLEN];
} binit_task_t;
typedef struct {
43,9 → 53,24
binit_task_t tasks[CONFIG_INIT_TASKS];
} binit_t;
 
typedef struct {
unsigned int type;
unsigned long base;
unsigned long size;
}efi_memmap_item_t;
 
 
typedef struct {
binit_t taskmap;
 
efi_memmap_item_t memmap[MEMMAP_ITEMS];
unsigned int memmap_items;
 
unsigned long * sapic;
unsigned long sys_freq;
unsigned long freq_scale;
unsigned int wakeup_intno;
int hello_configured;
} bootinfo_t;
 
extern bootinfo_t *bootinfo;
/branches/dd/kernel/arch/ia64/include/asm.h
36,29 → 36,72
#define KERN_ia64_ASM_H_
 
#include <config.h>
#include <typedefs.h>
#include <arch/types.h>
#include <arch/register.h>
 
 
#define IA64_IOSPACE_ADDRESS 0xE001000000000000ULL
 
static inline void outb(uint64_t port,uint8_t v)
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*((char *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
uintptr_t prt = (uintptr_t) port;
 
*((uint8_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
uintptr_t prt = (uintptr_t) port;
 
static inline uint8_t inb(uint64_t port)
*((uint16_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
uintptr_t prt = (uintptr_t) port;
 
*((uint32_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
return *((char *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
static inline uint8_t pio_read_8(ioport8_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
asm volatile ("mf\n" ::: "memory");
 
return *((uint8_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12))));
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
asm volatile ("mf\n" ::: "memory");
 
return *((uint16_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12))));
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
asm volatile ("mf\n" ::: "memory");
 
return *((uint32_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12))));
}
 
/** Return base address of current stack
*
* Return the base address of the current stack.
69,9 → 112,14
{
uint64_t v;
 
asm volatile ("and %0 = %1, r12" : "=r" (v) : "r" (~(STACK_SIZE-1)));
//I'm not sure why but this code bad inlines in scheduler,
//so THE shifts about 16B and causes kernel panic
//asm volatile ("and %0 = %1, r12" : "=r" (v) : "r" (~(STACK_SIZE-1)));
//return v;
return v;
//this code have the same meaning but inlines well
asm volatile ("mov %0 = r12" : "=r" (v) );
return v & (~(STACK_SIZE-1));
}
 
/** Return Processor State Register.
123,6 → 171,16
return v;
}
 
static inline uint64_t cr64_read(void)
{
uint64_t v;
asm volatile ("mov %0 = cr64\n" : "=r" (v));
return v;
}
 
 
/** Write ITC (Interval Timer Counter) register.
*
* @param v New counter value.
297,7 → 355,8
extern void cpu_sleep(void);
extern void asm_delay_loop(uint32_t t);
 
extern void switch_to_userspace(uintptr_t entry, uintptr_t sp, uintptr_t bsp, uintptr_t uspace_uarg, uint64_t ipsr, uint64_t rsc);
extern void switch_to_userspace(uintptr_t, uintptr_t, uintptr_t, uintptr_t,
uint64_t, uint64_t);
 
#endif
 
/branches/dd/kernel/arch/ia64/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia64mm
/** @addtogroup ia64mm
* @{
*/
/** @file
35,12 → 35,16
#ifndef KERN_ia64_FRAME_H_
#define KERN_ia64_FRAME_H_
 
#define FRAME_WIDTH 14 /* 16K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
#define FRAME_WIDTH 14 /* 16K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
 
#ifdef KERNEL
#ifndef __ASM__
 
#include <arch/types.h>
 
extern uintptr_t last_frame;
 
extern void frame_arch_init(void);
#define physmem_print()
 
/branches/dd/kernel/arch/ia64/include/mm/page.h
41,15 → 41,30
#define PAGE_SIZE FRAME_SIZE
#define PAGE_WIDTH FRAME_WIDTH
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifdef KERNEL
 
/** Bit width of the TLB-locked portion of kernel address space. */
#define KERNEL_PAGE_WIDTH 28 /* 256M */
#define IO_PAGE_WIDTH 26 /* 64M */
#define FW_PAGE_WIDTH 28 /* 256M */
 
#define USPACE_IO_PAGE_WIDTH 12 /* 4K */
 
 
/*
* Statically mapped IO spaces - offsets to 0xe...00 of virtual addresses
* because of "minimal virtual bits implemented is 51" it is possible to
* have values up to 0x0007000000000000
*/
 
/* Firmware area (bellow 4GB in phys mem) */
#define FW_OFFSET 0x00000000F0000000
/* Legacy IO space */
#define IO_OFFSET 0x0001000000000000
/* Videoram - now mapped to 0 as VGA text mode vram on 0xb8000 */
#define VIO_OFFSET 0x0002000000000000
 
 
#define PPN_SHIFT 12
 
#define VRN_SHIFT 61
64,8 → 79,8
 
#define REGION_REGISTERS 8
 
#define KA2PA(x) ((uintptr_t) (x-(VRN_KERNEL<<VRN_SHIFT)))
#define PA2KA(x) ((uintptr_t) (x+(VRN_KERNEL<<VRN_SHIFT)))
#define KA2PA(x) ((uintptr_t) (x - (VRN_KERNEL << VRN_SHIFT)))
#define PA2KA(x) ((uintptr_t) (x + (VRN_KERNEL << VRN_SHIFT)))
 
#define VHPT_WIDTH 20 /* 1M */
#define VHPT_SIZE (1 << VHPT_WIDTH)
/branches/dd/kernel/arch/ia64/include/mm/tlb.h
35,9 → 35,6
#ifndef KERN_ia64_TLB_H_
#define KERN_ia64_TLB_H_
 
#define tlb_arch_init()
#define tlb_print()
 
#include <arch/mm/page.h>
#include <arch/mm/asid.h>
#include <arch/interrupt.h>
46,8 → 43,8
/** Data and instruction Translation Register indices. */
#define DTR_KERNEL 0
#define ITR_KERNEL 0
#define DTR_KSTACK1 1
#define DTR_KSTACK2 2
#define DTR_KSTACK1 4
#define DTR_KSTACK2 5
 
/** Portion of TLB insertion format data structure. */
union tlb_entry {
/branches/dd/kernel/arch/ia64/include/mm/vhpt.h
44,8 → 44,8
{
vhpt_entry_t ventry;
ventry.word[0]=tentry.word[0];
ventry.word[1]=tentry.word[1];
ventry.word[0] = tentry.word[0];
ventry.word[1] = tentry.word[1];
return ventry;
}
/branches/dd/kernel/arch/ia64/include/register.h
40,11 → 40,11
#define PSR_I_MASK 0x4000
#define PSR_PK_MASK 0x8000
 
#define PSR_DT_MASK (1<<17)
#define PSR_RT_MASK (1<<27)
#define PSR_DT_MASK (1 << 17)
#define PSR_RT_MASK (1 << 27)
 
#define PSR_DFL_MASK (1<<18)
#define PSR_DFH_MASK (1<<19)
#define PSR_DFL_MASK (1 << 18)
#define PSR_DFH_MASK (1 << 19)
 
#define PSR_IT_MASK 0x0000001000000000
 
/branches/dd/kernel/arch/ia64/include/debug.h
1,5 → 1,5
/*
* Copyright (c) 2005
* Copyright (c) 2005 Ondrej Palkovsky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/branches/dd/kernel/arch/ia64/include/barrier.h
45,9 → 45,33
#define read_barrier() memory_barrier()
#define write_barrier() memory_barrier()
 
#define srlz_i() asm volatile (";; srlz.i ;;\n" ::: "memory")
#define srlz_d() asm volatile (";; srlz.d\n" ::: "memory")
#define srlz_i() \
asm volatile (";; srlz.i ;;\n" ::: "memory")
#define srlz_d() \
asm volatile (";; srlz.d\n" ::: "memory")
 
#define fc_i(a) \
asm volatile ("fc.i %0\n" :: "r" ((a)) : "memory")
#define sync_i() \
asm volatile (";; sync.i\n" ::: "memory")
 
#define smc_coherence(a) \
{ \
fc_i((a)); \
sync_i(); \
srlz_i(); \
}
 
#define FC_INVAL_MIN 32
#define smc_coherence_block(a, l) \
{ \
unsigned long i; \
for (i = 0; i < (l); i += FC_INVAL_MIN) \
fc_i((void *)(a) + i); \
sync_i(); \
srlz_i(); \
}
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia64/include/cpu.h
38,6 → 38,7
#include <arch/types.h>
#include <arch/register.h>
#include <arch/asm.h>
#include <arch/bootinfo.h>
 
#define FAMILY_ITANIUM 0x7
#define FAMILY_ITANIUM2 0x1f
63,6 → 64,32
return v;
}
 
 
#define CR64_ID_SHIFT 24
#define CR64_ID_MASK 0xff000000
#define CR64_EID_SHIFT 16
#define CR64_EID_MASK 0xff0000
 
static inline int ia64_get_cpu_id(void)
{
uint64_t cr64=cr64_read();
return ((CR64_ID_MASK)&cr64)>>CR64_ID_SHIFT;
}
 
static inline int ia64_get_cpu_eid(void)
{
uint64_t cr64=cr64_read();
return ((CR64_EID_MASK)&cr64)>>CR64_EID_SHIFT;
}
 
 
static inline void ipi_send_ipi(int id, int eid, int intno)
{
(bootinfo->sapic)[2 * (id * 256 + eid)] = intno;
srlz_d();
 
}
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia64/include/drivers/i8042.h
File deleted
/branches/dd/kernel/arch/ia64/include/drivers/ega.h
File deleted
/branches/dd/kernel/arch/ia64/include/drivers/it.h
41,7 → 41,7
* from firmware.
*
*/
#define IT_DELTA 100000
#define IT_DELTA it_delta
 
extern void it_init(void);
 
/branches/dd/kernel/arch/ia64/include/drivers/kbd.h
0,0 → 1,46
/*
* Copyright (c) 2006 Jakub Jermar, Jakub Vana
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia6464
* @{
*/
/** @file
*/
 
#ifndef KERN_ia64_KBD_H_
#define KERN_ia64_KBD_H_
 
#define KBD_UNKNOWN 0
#define KBD_SKI 1
#define KBD_LEGACY 2
#define KBD_NS16550 3
 
#endif
 
/** @}
*/
/branches/dd/kernel/arch/ia64/Makefile.inc
32,11 → 32,8
BFD_NAME = elf64-little
BFD_ARCH = ia64-elf64
TARGET = ia64-pc-linux-gnu
TOOLCHAIN_DIR = /usr/local/ia64
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64
 
INIT0_ADDRESS = 0xe000000004404000
INIT0_SIZE = 0x100000
 
CMN1 = -mconstant-gp -fno-unwind-tables -mfixed-range=f32-f127
GCC_CFLAGS += $(CMN1)
ICC_CFLAGS += $(CMN1)
44,58 → 41,35
LFLAGS += -EL
AFLAGS += -mconstant-gp
 
DEFS += -D__64_BITS__ -DINIT0_ADDRESS=$(INIT0_ADDRESS) -DINIT0_SIZE=$(INIT0_SIZE) -D$(MACHINE)
DEFS += -D__64_BITS__
 
 
## Compile with page hash table support.
#
 
CONFIG_PAGE_HT = y
DEFS += -DCONFIG_PAGE_HT
 
## Compile with support for address space identifiers.
#
 
CONFIG_ASID = y
CONFIG_ASID_FIFO = y
 
 
## Compile with support for software integer division.
#
 
CONFIG_SOFTINT = y
 
ARCH_SOURCES = \
arch/$(ARCH)/src/start.S \
arch/$(ARCH)/src/asm.S \
arch/$(ARCH)/src/dummy.s \
arch/$(ARCH)/src/ia64.c \
arch/$(ARCH)/src/fpu_context.c \
arch/$(ARCH)/src/context.S \
arch/$(ARCH)/src/cpu/cpu.c \
arch/$(ARCH)/src/ivt.S \
arch/$(ARCH)/src/interrupt.c \
arch/$(ARCH)/src/mm/as.c \
arch/$(ARCH)/src/mm/frame.c \
arch/$(ARCH)/src/mm/page.c \
arch/$(ARCH)/src/mm/tlb.c \
arch/$(ARCH)/src/mm/vhpt.c \
arch/$(ARCH)/src/proc/scheduler.c \
arch/$(ARCH)/src/ddi/ddi.c \
arch/$(ARCH)/src/drivers/it.c
arch/$(KARCH)/src/start.S \
arch/$(KARCH)/src/asm.S \
arch/$(KARCH)/src/dummy.s \
arch/$(KARCH)/src/ia64.c \
arch/$(KARCH)/src/fpu_context.c \
arch/$(KARCH)/src/context.S \
arch/$(KARCH)/src/cpu/cpu.c \
arch/$(KARCH)/src/ivt.S \
arch/$(KARCH)/src/interrupt.c \
arch/$(KARCH)/src/mm/as.c \
arch/$(KARCH)/src/mm/frame.c \
arch/$(KARCH)/src/mm/page.c \
arch/$(KARCH)/src/mm/tlb.c \
arch/$(KARCH)/src/mm/vhpt.c \
arch/$(KARCH)/src/proc/scheduler.c \
arch/$(KARCH)/src/ddi/ddi.c \
arch/$(KARCH)/src/smp/smp.c \
arch/$(KARCH)/src/drivers/it.c
 
ifeq ($(MACHINE),ski)
ARCH_SOURCES += arch/$(ARCH)/src/ski/ski.c
ARCH_SOURCES += arch/$(KARCH)/src/ski/ski.c
DEFS += -DSKI
# BFD = elf64-ia64-little
BFD = binary
endif
 
ifeq ($(MACHINE),i460GX)
ARCH_SOURCES += arch/$(ARCH)/src/drivers/ega.c
CONFIG_I8042 = y
DEFS += -DI460GX -DCONFIG_I8042
DEFS += -DI460GX
BFD = binary
 
endif
 
/branches/dd/kernel/arch/ia64/src/putchar.c
File deleted
/branches/dd/kernel/arch/ia64/src/fpu_context.c
149,8 → 149,10
"stf.spill [%7] = f127, 0x80\n;;"
 
:
: "r" (&((fctx->fr)[0])), "r" (&((fctx->fr)[1])), "r" (&((fctx->fr)[2])), "r" (&((fctx->fr)[3])),
"r" (&((fctx->fr)[4])), "r" (&((fctx->fr)[5])), "r" (&((fctx->fr)[6])), "r" (&((fctx->fr)[7]))
: "r" (&((fctx->fr)[0])), "r" (&((fctx->fr)[1])),
"r" (&((fctx->fr)[2])), "r" (&((fctx->fr)[3])),
"r" (&((fctx->fr)[4])), "r" (&((fctx->fr)[5])),
"r" (&((fctx->fr)[6])), "r" (&((fctx->fr)[7]))
);
}
267,14 → 269,16
"ldf.fill f127 = [%7], 0x80\n;;"
 
:
: "r" (&((fctx->fr)[0])), "r" (&((fctx->fr)[1])), "r" (&((fctx->fr)[2])), "r" (&((fctx->fr)[3])),
"r" (&((fctx->fr)[4])), "r" (&((fctx->fr)[5])), "r" (&((fctx->fr)[6])), "r" (&((fctx->fr)[7]))
: "r" (&((fctx->fr)[0])), "r" (&((fctx->fr)[1])),
"r" (&((fctx->fr)[2])), "r" (&((fctx->fr)[3])),
"r" (&((fctx->fr)[4])), "r" (&((fctx->fr)[5])),
"r" (&((fctx->fr)[6])), "r" (&((fctx->fr)[7]))
);
}
 
void fpu_enable(void)
{
uint64_t a = 0 ;
uint64_t a = 0;
 
asm volatile (
"rsm %0 ;;"
/branches/dd/kernel/arch/ia64/src/smp/smp.c
0,0 → 1,167
/*
* Copyright (c) 2005 Jakub Vana
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia64
* @{
*/
/** @file
*/
 
#include <arch.h>
#include <arch/ski/ski.h>
#include <arch/drivers/it.h>
#include <arch/interrupt.h>
#include <arch/barrier.h>
#include <arch/asm.h>
#include <arch/register.h>
#include <arch/types.h>
#include <arch/context.h>
#include <arch/stack.h>
#include <arch/mm/page.h>
#include <mm/as.h>
#include <config.h>
#include <userspace.h>
#include <console/console.h>
#include <proc/uarg.h>
#include <syscall/syscall.h>
#include <ddi/irq.h>
#include <ddi/device.h>
#include <arch/bootinfo.h>
#include <smp/smp.h>
#include <smp/ipi.h>
#include <arch/atomic.h>
#include <panic.h>
#include <print.h>
 
#ifdef CONFIG_SMP
 
extern char cpu_by_id_eid_list[256][256];
 
static void sapic_init(void)
{
bootinfo->sapic = (unative_t *)(PA2KA((unative_t)(bootinfo->sapic)) |
FW_OFFSET);
}
 
static void ipi_broadcast_arch_all(int ipi)
{
int id, eid;
int myid, myeid;
myid = ia64_get_cpu_id();
myeid = ia64_get_cpu_eid();
for (id = 0; id < 256; id++)
for (eid = 0; eid < 256; eid++)
if ((id != myid) || (eid != myeid))
ipi_send_ipi(id, eid, ipi);
}
 
void ipi_broadcast_arch(int ipi )
{
int id, eid;
int myid, myeid;
myid = ia64_get_cpu_id();
myeid = ia64_get_cpu_eid();
 
for (id = 0; id < 256; id++)
for (eid = 0; eid < 256; eid++)
if ((id != myid) || (eid != myeid))
if (cpu_by_id_eid_list[id][eid])
ipi_send_ipi(id, eid, ipi);
}
 
void smp_init(void)
{
if (!bootinfo->hello_configured)
return;
/*
* If we have not got system prepared by hello, we are not able to start
* AP's. This means we are running on a simulator.
*/
sapic_init();
ipi_broadcast_arch_all(bootinfo->wakeup_intno);
volatile long long brk;
for (brk = 0; brk < 100LL * 1024LL * 1024LL; brk++)
; /* wait a while before CPUs starts */
 
config.cpu_count = 0;
int id, eid;
for (id = 0; id < 256; id++)
for (eid = 0; eid < 256; eid++)
if (cpu_by_id_eid_list[id][eid] == 1) {
config.cpu_count++;
cpu_by_id_eid_list[id][eid] = 2;
}
}
 
void kmp(void *arg __attribute__((unused)))
{
int id, eid;
int myid, myeid;
myid = ia64_get_cpu_id();
myeid = ia64_get_cpu_eid();
 
for (id = 0; id < 256; id++)
for (eid = 0; eid < 256; eid++)
if ((id != myid) || (eid != myeid))
if (cpu_by_id_eid_list[id][eid] != 0) {
if (cpu_by_id_eid_list[id][eid] == 1) {
printf("Found Late CPU ID:%d "
"EDI:%d Not added to "
"system!!!\n", id, eid);
continue;
}
cpu_by_id_eid_list[id][eid] = 3;
/*
* There may be just one AP being
* initialized at the time. After
* it comes completely up, it is
* supposed to wake us up.
*/
if (waitq_sleep_timeout(
&ap_completion_wq, 1000000,
SYNCH_FLAGS_NONE) ==
ESYNCH_TIMEOUT) {
printf("%s: waiting for cpu "
"ID:%d EID:%d timed out\n",
__FUNCTION__, id, eid);
}
}
}
 
#endif
 
/** @}
*/
 
/branches/dd/kernel/arch/ia64/src/ddi/ddi.c
1,5 → 1,6
/*
* Copyright (c) 2006 Jakub Jermar
* Copyright (c) 2008 Jakub vana
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
35,19 → 36,39
#include <ddi/ddi.h>
#include <proc/task.h>
#include <arch/types.h>
#include <mm/slab.h>
#include <errno.h>
 
#define IO_MEMMAP_PAGES 16384
#define PORTS_PER_PAGE 4
 
/** Enable I/O space range for task.
*
* Interrupts are disabled and task is locked.
*
* @param task Task.
* @param ioaddr Startign I/O space address.
* @param size Size of the enabled I/O range.
* @param task Task.
* @param ioaddr Starting I/O space address.
* @param size Size of the enabled I/O range.
*
* @return 0 on success or an error code from errno.h.
*/
int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
{
if (!task->arch.iomap) {
uint8_t *map;
 
task->arch.iomap = malloc(sizeof(bitmap_t), 0);
map = malloc(BITS2BYTES(IO_MEMMAP_PAGES), 0);
if(!map)
return ENOMEM;
bitmap_initialize(task->arch.iomap, map, IO_MEMMAP_PAGES);
bitmap_clear_range(task->arch.iomap, 0, IO_MEMMAP_PAGES);
}
uintptr_t iopage = ioaddr / PORTS_PER_PAGE;
size = ALIGN_UP(size + ioaddr - 4 * iopage, PORTS_PER_PAGE);
bitmap_set_range(task->arch.iomap, iopage, size / 4);
 
return 0;
}
 
/branches/dd/kernel/arch/ia64/src/asm.S
51,7 → 51,7
 
adds r14 = 7, in1
mov r2 = ar.lc
mov r8 = in1 ;;
mov r8 = in0
and r14 = -8, r14 ;;
cmp.ne p6, p7 = r14, in1
(p7) br.cond.dpnt 3f ;;
63,7 → 63,7
(p6) mov r17 = r0 ;;
(p6) mov ar.lc = r14
1:
add r14 = r16, r8
add r14 = r16, in1
add r15 = r16, in0
adds r17 = 1, r17 ;;
ld1 r14 = [r14]
72,7 → 72,6
br.cloop.sptk.few 1b ;;
2:
mov ar.lc = r2
 
mov ar.pfs = loc0
br.ret.sptk.many rp
3:
90,7 → 89,7
4:
shladd r14 = r16, 3, r0
adds r16 = 1, r17 ;;
add r15 = r8, r14
add r15 = in1, r14
add r14 = in0, r14
mov r17 = r16 ;;
ld8 r15 = [r15] ;;
104,7 → 103,7
cmp.eq p6, p7 = 0, r15
add in0 = r14, in0
adds r15 = -1, r15
add r17 = r14, r8
add r17 = r14, in1
(p6) br.cond.dpnt 2b ;;
mov ar.lc = r15
6:
116,7 → 115,6
st1 [r15] = r14
br.cloop.sptk.few 6b ;;
mov ar.lc = r2
 
mov ar.pfs = loc0
br.ret.sptk.many rp
130,6 → 128,10
memsetb:
br _memsetb
 
.global memsetw
memsetw:
br _memsetw
 
.global cpu_halt
cpu_halt:
br cpu_halt
163,6 → 165,9
 
xor r1 = r1, r1
/* r2 is defined to hold pcb_ptr - set it to 0 */
xor r2 = r2, r2
mov loc1 = cr.ifs
movl loc2 = PFM_MASK ;;
and loc1 = loc2, loc1 ;;
/branches/dd/kernel/arch/ia64/src/proc/scheduler.c
47,14 → 47,17
{
}
 
/** Prepare kernel stack pointers in bank 0 r22 and r23 and make sure the stack is mapped in DTR. */
/** Prepare kernel stack pointers in bank 0 r22 and r23 and make sure the stack
* is mapped in DTR.
*/
void before_thread_runs_arch(void)
{
uintptr_t base;
base = ALIGN_DOWN(config.base, 1<<KERNEL_PAGE_WIDTH);
base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
 
if ((uintptr_t) THREAD->kstack < base || (uintptr_t) THREAD->kstack > base + (1<<(KERNEL_PAGE_WIDTH))) {
if ((uintptr_t) THREAD->kstack < base ||
(uintptr_t) THREAD->kstack > base + (1 << (KERNEL_PAGE_WIDTH))) {
/*
* Kernel stack of this thread is not mapped by DTR[TR_KERNEL].
* Use DTR[TR_KSTACK1] and DTR[TR_KSTACK2] to map it.
64,8 → 67,11
dtr_purge((uintptr_t) THREAD->kstack, PAGE_WIDTH+1);
/* insert DTR[TR_STACK1] and DTR[TR_STACK2] */
dtlb_kernel_mapping_insert((uintptr_t) THREAD->kstack, KA2PA(THREAD->kstack), true, DTR_KSTACK1);
dtlb_kernel_mapping_insert((uintptr_t) THREAD->kstack + PAGE_SIZE, KA2PA(THREAD->kstack) + FRAME_SIZE, true, DTR_KSTACK2);
dtlb_kernel_mapping_insert((uintptr_t) THREAD->kstack,
KA2PA(THREAD->kstack), true, DTR_KSTACK1);
dtlb_kernel_mapping_insert((uintptr_t) THREAD->kstack +
PAGE_SIZE, KA2PA(THREAD->kstack) + FRAME_SIZE, true,
DTR_KSTACK2);
}
/*
/branches/dd/kernel/arch/ia64/src/ia64.c
51,64 → 51,99
#include <syscall/syscall.h>
#include <ddi/irq.h>
#include <ddi/device.h>
#include <arch/drivers/ega.h>
#include <arch/bootinfo.h>
#include <genarch/kbd/i8042.h>
#include <genarch/drivers/legacy/ia32/io.h>
#include <genarch/drivers/ega/ega.h>
#include <genarch/kbrd/kbrd.h>
#include <genarch/srln/srln.h>
#include <genarch/drivers/i8042/i8042.h>
#include <genarch/drivers/ns16550/ns16550.h>
#include <arch/drivers/kbd.h>
#include <smp/smp.h>
#include <smp/ipi.h>
#include <arch/atomic.h>
#include <panic.h>
#include <print.h>
#include <sysinfo/sysinfo.h>
#include <string.h>
 
/* NS16550 as a COM 1 */
#define NS16550_IRQ (4 + LEGACY_INTERRUPT_BASE)
 
bootinfo_t *bootinfo;
 
static uint64_t iosapic_base = 0xfec00000;
 
/** Performs ia64-specific initialization before main_bsp() is called. */
void arch_pre_main(void)
{
/* Setup usermode init tasks. */
 
//#ifdef I460GX
unsigned int i;
init.cnt = bootinfo->taskmap.count;
for (i = 0; i < init.cnt; i++) {
init.tasks[i].addr = ((unsigned long) bootinfo->taskmap.tasks[i].addr) | VRN_MASK;
init.tasks[i].addr =
((unsigned long) bootinfo->taskmap.tasks[i].addr) |
VRN_MASK;
init.tasks[i].size = bootinfo->taskmap.tasks[i].size;
strncpy(init.tasks[i].name, bootinfo->taskmap.tasks[i].name,
CONFIG_TASK_NAME_BUFLEN);
}
/*
#else
init.cnt = 8;
init.tasks[0].addr = INIT0_ADDRESS;
init.tasks[0].size = INIT0_SIZE;
init.tasks[1].addr = INIT0_ADDRESS + 0x400000;
init.tasks[1].size = INIT0_SIZE;
init.tasks[2].addr = INIT0_ADDRESS + 0x800000;
init.tasks[2].size = INIT0_SIZE;
init.tasks[3].addr = INIT0_ADDRESS + 0xc00000;
init.tasks[3].size = INIT0_SIZE;
init.tasks[4].addr = INIT0_ADDRESS + 0x1000000;
init.tasks[4].size = INIT0_SIZE;
init.tasks[5].addr = INIT0_ADDRESS + 0x1400000;
init.tasks[5].size = INIT0_SIZE;
init.tasks[6].addr = INIT0_ADDRESS + 0x1800000;
init.tasks[6].size = INIT0_SIZE;
init.tasks[7].addr = INIT0_ADDRESS + 0x1c00000;
init.tasks[7].size = INIT0_SIZE;
#endif*/
}
 
void arch_pre_mm_init(void)
{
/* Set Interruption Vector Address (i.e. location of interruption vector table). */
/*
* Set Interruption Vector Address (i.e. location of interruption vector
* table).
*/
iva_write((uintptr_t) &ivt);
srlz_d();
}
 
static void iosapic_init(void)
{
uint64_t IOSAPIC = PA2KA((unative_t)(iosapic_base)) | FW_OFFSET;
int i;
int myid, myeid;
myid = ia64_get_cpu_id();
myeid = ia64_get_cpu_eid();
 
for (i = 0; i < 16; i++) {
if (i == 2)
continue; /* Disable Cascade interrupt */
((uint32_t *)(IOSAPIC + 0x00))[0] = 0x10 + 2 * i;
srlz_d();
((uint32_t *)(IOSAPIC + 0x10))[0] = LEGACY_INTERRUPT_BASE + i;
srlz_d();
((uint32_t *)(IOSAPIC + 0x00))[0] = 0x10 + 2 * i + 1;
srlz_d();
((uint32_t *)(IOSAPIC + 0x10))[0] = myid << (56 - 32) |
myeid << (48 - 32);
srlz_d();
}
 
}
 
 
void arch_post_mm_init(void)
{
irq_init(INR_COUNT, INR_COUNT);
if (config.cpu_active == 1) {
iosapic_init();
irq_init(INR_COUNT, INR_COUNT);
#ifdef SKI
ski_init_console();
#else
ega_init();
#endif
it_init();
ski_init_console();
#else
ega_init(EGA_BASE, EGA_VIDEORAM);
#endif
}
it_init();
}
 
void arch_post_cpu_init(void)
119,51 → 154,54
{
}
 
 
#ifdef I460GX
#define POLL_INTERVAL 50000 /* 50 ms */
/** Kernel thread for polling keyboard. */
static void i8042_kkbdpoll(void *arg)
{
while (1) {
i8042_poll();
thread_usleep(POLL_INTERVAL);
}
}
#endif
 
void arch_post_smp_init(void)
{
 
if (config.cpu_active == 1) {
/*
* Create thread that polls keyboard.
*/
/*
* Create thread that polls keyboard.
*/
#ifdef SKI
thread_t *t;
t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
if (!t)
panic("cannot create kkbdpoll\n");
thread_ready(t);
thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
if (!t)
panic("Cannot create kkbdpoll.");
thread_ready(t);
#endif
 
#ifdef I460GX
devno_t kbd = device_assign_devno();
devno_t mouse = device_assign_devno();
/* keyboard controller */
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE);
devno_t devno = device_assign_devno();
inr_t inr;
 
thread_t *t;
t = thread_create(i8042_kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
if (!t)
panic("cannot create kkbdpoll\n");
thread_ready(t);
 
#ifdef CONFIG_NS16550
inr = NS16550_IRQ;
srln_init(stdin);
(void) ns16550_init((ns16550_t *)NS16550_BASE, devno, inr, NULL, NULL,
&srlnin);
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
sysinfo_set_item_val("kbd.address.physical", NULL,
(uintptr_t) NS16550_BASE);
sysinfo_set_item_val("kbd.address.kernel", NULL,
(uintptr_t) NS16550_BASE);
#else
inr = IRQ_KBD;
kbrd_init(stdin);
(void) i8042_init((i8042_t *)I8042_BASE, devno, inr, &kbrdin);
trap_virtual_enable_irqs(1 << inr);
sysinfo_set_item_val("kbd.type", NULL, KBD_LEGACY);
sysinfo_set_item_val("kbd.address.physical", NULL,
(uintptr_t) I8042_BASE);
sysinfo_set_item_val("kbd.address.kernel", NULL,
(uintptr_t) I8042_BASE);
#endif
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, inr);
#endif
 
}
sysinfo_set_item_val("ia64_iospace", NULL, true);
sysinfo_set_item_val("ia64_iospace.address", NULL, true);
sysinfo_set_item_val("ia64_iospace.address.virtual", NULL, IO_OFFSET);
}
 
 
/** Enter userspace and never return. */
void userspace(uspace_arg_t *kernel_uarg)
{
172,26 → 210,25
 
psr.value = psr_read();
psr.cpl = PL_USER;
psr.i = true; /* start with interrupts enabled */
psr.i = true; /* start with interrupts enabled */
psr.ic = true;
psr.ri = 0; /* start with instruction #0 */
psr.bn = 1; /* start in bank 0 */
psr.ri = 0; /* start with instruction #0 */
psr.bn = 1; /* start in bank 0 */
 
asm volatile ("mov %0 = ar.rsc\n" : "=r" (rsc.value));
rsc.loadrs = 0;
rsc.be = false;
rsc.pl = PL_USER;
rsc.mode = 3; /* eager mode */
rsc.mode = 3; /* eager mode */
 
switch_to_userspace((uintptr_t) kernel_uarg->uspace_entry,
((uintptr_t) kernel_uarg->uspace_stack)+PAGE_SIZE-ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT),
((uintptr_t) kernel_uarg->uspace_stack)+PAGE_SIZE,
(uintptr_t) kernel_uarg->uspace_uarg,
psr.value, rsc.value);
((uintptr_t) kernel_uarg->uspace_stack) + PAGE_SIZE -
ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT),
((uintptr_t) kernel_uarg->uspace_stack) + PAGE_SIZE,
(uintptr_t) kernel_uarg->uspace_uarg, psr.value, rsc.value);
 
while (1) {
while (1)
;
}
}
 
/** Set thread-local-storage pointer.
210,8 → 247,9
{
#ifdef SKI
ski_kbd_grab();
#endif
#endif
}
 
/** Return console to userspace
*
*/
224,9 → 262,27
 
void arch_reboot(void)
{
// TODO
while (1);
pio_write_8((ioport8_t *)0x64, 0xfe);
while (1)
;
}
 
/** Construct function pointer
*
* @param fptr function pointer structure
* @param addr function address
* @param caller calling function address
*
* @return address of the function pointer
*
*/
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
{
fptr->fnc = (unative_t) addr;
fptr->gp = ((unative_t *) caller)[1];
return (void *) fptr;
}
 
/** @}
*/
/branches/dd/kernel/arch/ia64/src/ski/ski.c
44,8 → 44,9
#include <proc/thread.h>
#include <synch/spinlock.h>
#include <arch/asm.h>
#include <arch/drivers/kbd.h>
 
#define SKI_KBD_INR 0
#define SKI_KBD_INR 0
 
static irq_t ski_kbd_irq;
static devno_t ski_kbd_devno;
55,9 → 56,6
 
static bool kbd_disabled;
 
static void ski_putchar(chardev_t *d, const char ch);
static int32_t ski_getchar(void);
 
/** Display character on debug console
*
* Use SSC (Simulator System Call) to
66,19 → 64,21
* @param d Character device.
* @param ch Character to be printed.
*/
void ski_putchar(chardev_t *d, const char ch)
static void ski_putchar(chardev_t *d, const char ch, bool silent)
{
asm volatile (
"mov r15 = %0\n"
"mov r32 = %1\n" /* r32 is in0 */
"break 0x80000\n" /* modifies r8 */
:
: "i" (SKI_PUTCHAR), "r" (ch)
: "r15", "in0", "r8"
);
if (ch == '\n')
ski_putchar(d, '\r');
if (!silent) {
asm volatile (
"mov r15 = %0\n"
"mov r32 = %1\n" /* r32 is in0 */
"break 0x80000\n" /* modifies r8 */
:
: "i" (SKI_PUTCHAR), "r" (ch)
: "r15", "in0", "r8"
);
if (ch == '\n')
ski_putchar(d, '\r', false);
}
}
 
/** Ask debug console if a key was pressed.
90,7 → 90,7
*
* @return ASCII code of pressed key or 0 if no key pressed.
*/
int32_t ski_getchar(void)
static int32_t ski_getchar(void)
{
uint64_t ch;
114,10 → 114,10
static char ski_getchar_blocking(chardev_t *d)
{
int ch;
 
while(!(ch = ski_getchar()))
;
if(ch == '\r')
while(!(ch = ski_getchar()));
if (ch == '\r')
ch = '\n';
return (char) ch;
}
128,23 → 128,24
char ch;
static char last;
ipl_t ipl;
 
ipl = interrupts_disable();
 
if (kbd_disabled) {
interrupts_restore(ipl);
return;
}
spinlock_lock(&ski_kbd_irq.lock);
 
ch = ski_getchar();
if(ch == '\r')
ch = '\n';
if (ch) {
if (ski_kbd_irq.notif_cfg.notify && ski_kbd_irq.notif_cfg.answerbox) {
if (ski_kbd_irq.notif_cfg.notify &&
ski_kbd_irq.notif_cfg.answerbox) {
chardev_push_character(&ski_uconsole, ch);
ipc_irq_send_notif(&ski_kbd_irq);
/* XXX: send notification to userspace */
} else {
chardev_push_character(&ski_console, ch);
}
155,9 → 156,10
}
 
if (last) {
if (ski_kbd_irq.notif_cfg.notify && ski_kbd_irq.notif_cfg.answerbox) {
if (ski_kbd_irq.notif_cfg.notify &&
ski_kbd_irq.notif_cfg.answerbox) {
chardev_push_character(&ski_uconsole, 0);
ipc_irq_send_notif(&ski_kbd_irq);
/* XXX: send notification to userspace */
}
last = 0;
}
175,7 → 177,7
/* Called from getc(). */
static void ski_kbd_disable(chardev_t *d)
{
kbd_disabled = true;
kbd_disabled = true;
}
 
/** Decline to service hardware IRQ.
184,7 → 186,7
*
* @return Always IRQ_DECLINE.
*/
static irq_ownership_t ski_kbd_claim(void)
static irq_ownership_t ski_kbd_claim(irq_t *irq)
{
return IRQ_DECLINE;
}
227,6 → 229,9
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.inr", NULL, SKI_KBD_INR);
sysinfo_set_item_val("kbd.devno", NULL, ski_kbd_devno);
sysinfo_set_item_val("kbd.type", NULL, KBD_SKI);
 
sysinfo_set_item_val("fb", NULL, false);
}
 
void ski_kbd_grab(void)
255,7 → 260,9
void kkbdpoll(void *arg)
{
while (1) {
poll_keyboard();
if (!silent) {
poll_keyboard();
}
thread_usleep(POLL_INTERVAL);
}
}
/branches/dd/kernel/arch/ia64/src/cpu/cpu.c
70,8 → 70,8
}
printf("cpu%d: %s (%s), archrev=%d, model=%d, revision=%d\n", CPU->id,
family_str, vendor, CPU->arch.cpuid3.archrev, CPU->arch.cpuid3.model,
CPU->arch.cpuid3.revision);
family_str, vendor, CPU->arch.cpuid3.archrev,
CPU->arch.cpuid3.model, CPU->arch.cpuid3.revision);
}
 
/** @}
/branches/dd/kernel/arch/ia64/src/mm/tlb.c
92,7 → 92,7
 
/** Invalidate entries belonging to an address space.
*
* @param asid Address space identifier.
* @param asid Address space identifier.
*/
void tlb_invalidate_asid(asid_t asid)
{
131,59 → 131,45
uint64_t ps;
switch (b) {
case 0: /*cnt 1-3*/
case 0: /* cnt 1 - 3 */
ps = PAGE_WIDTH;
break;
case 1: /*cnt 4-15*/
/*cnt=((cnt-1)/4)+1;*/
ps = PAGE_WIDTH+2;
va &= ~((1<<ps)-1);
case 1: /* cnt 4 - 15 */
ps = PAGE_WIDTH + 2;
va &= ~((1 << ps) - 1);
break;
case 2: /*cnt 16-63*/
/*cnt=((cnt-1)/16)+1;*/
ps = PAGE_WIDTH+4;
va &= ~((1<<ps)-1);
case 2: /* cnt 16 - 63 */
ps = PAGE_WIDTH + 4;
va &= ~((1 << ps) - 1);
break;
case 3: /*cnt 64-255*/
/*cnt=((cnt-1)/64)+1;*/
ps = PAGE_WIDTH+6;
va &= ~((1<<ps)-1);
case 3: /* cnt 64 - 255 */
ps = PAGE_WIDTH + 6;
va &= ~((1 << ps) - 1);
break;
case 4: /*cnt 256-1023*/
/*cnt=((cnt-1)/256)+1;*/
ps = PAGE_WIDTH+8;
va &= ~((1<<ps)-1);
case 4: /* cnt 256 - 1023 */
ps = PAGE_WIDTH + 8;
va &= ~((1 << ps) - 1);
break;
case 5: /*cnt 1024-4095*/
/*cnt=((cnt-1)/1024)+1;*/
ps = PAGE_WIDTH+10;
va &= ~((1<<ps)-1);
case 5: /* cnt 1024 - 4095 */
ps = PAGE_WIDTH + 10;
va &= ~((1 << ps) - 1);
break;
case 6: /*cnt 4096-16383*/
/*cnt=((cnt-1)/4096)+1;*/
ps = PAGE_WIDTH+12;
va &= ~((1<<ps)-1);
case 6: /* cnt 4096 - 16383 */
ps = PAGE_WIDTH + 12;
va &= ~((1 << ps) - 1);
break;
case 7: /*cnt 16384-65535*/
case 8: /*cnt 65536-(256K-1)*/
/*cnt=((cnt-1)/16384)+1;*/
ps = PAGE_WIDTH+14;
va &= ~((1<<ps)-1);
case 7: /* cnt 16384 - 65535 */
case 8: /* cnt 65536 - (256K - 1) */
ps = PAGE_WIDTH + 14;
va &= ~((1 << ps) - 1);
break;
default:
/*cnt=((cnt-1)/(16384*16))+1;*/
ps=PAGE_WIDTH+18;
va&=~((1<<ps)-1);
ps = PAGE_WIDTH + 18;
va &= ~((1 << ps) - 1);
break;
}
/*cnt+=(page!=va);*/
for(; va<(page+cnt*(PAGE_SIZE)); va += (1<<ps)) {
asm volatile (
"ptc.l %0,%1;;"
:
: "r" (va), "r" (ps<<2)
);
}
for(; va < (page + cnt * PAGE_SIZE); va += (1 << ps))
asm volatile ("ptc.l %0, %1;;" :: "r" (va), "r" (ps << 2));
srlz_d();
srlz_i();
196,9 → 182,10
 
/** Insert data into data translation cache.
*
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion format.
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion
* format.
*/
void dtc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
{
207,9 → 194,10
 
/** Insert data into instruction translation cache.
*
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion format.
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion
* format.
*/
void itc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
{
218,10 → 206,12
 
/** Insert data into instruction or data translation cache.
*
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion format.
* @param dtc If true, insert into data translation cache, use instruction translation cache otherwise.
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion
* format.
* @param dtc If true, insert into data translation cache, use
* instruction translation cache otherwise.
*/
void tc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtc)
{
244,19 → 234,20
}
asm volatile (
"mov r8=psr;;\n"
"mov r8 = psr;;\n"
"rsm %0;;\n" /* PSR_IC_MASK */
"srlz.d;;\n"
"srlz.i;;\n"
"mov cr.ifa=%1\n" /* va */
"mov cr.itir=%2;;\n" /* entry.word[1] */
"cmp.eq p6,p7 = %4,r0;;\n" /* decide between itc and dtc */
"mov cr.ifa = %1\n" /* va */
"mov cr.itir = %2;;\n" /* entry.word[1] */
"cmp.eq p6,p7 = %4,r0;;\n" /* decide between itc and dtc */
"(p6) itc.i %3;;\n"
"(p7) itc.d %3;;\n"
"mov psr.l=r8;;\n"
"mov psr.l = r8;;\n"
"srlz.d;;\n"
:
: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (dtc)
: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]),
"r" (entry.word[0]), "r" (dtc)
: "p6", "p7", "r8"
);
269,12 → 260,14
 
/** Insert data into instruction translation register.
*
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion format.
* @param tr Translation register.
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion
* format.
* @param tr Translation register.
*/
void itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
void
itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
{
tr_mapping_insert(va, asid, entry, false, tr);
}
281,12 → 274,14
 
/** Insert data into data translation register.
*
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion format.
* @param tr Translation register.
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion
* format.
* @param tr Translation register.
*/
void dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
void
dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
{
tr_mapping_insert(va, asid, entry, true, tr);
}
293,13 → 288,17
 
/** Insert data into instruction or data translation register.
*
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion format.
* @param dtr If true, insert into data translation register, use instruction translation register otherwise.
* @param tr Translation register.
* @param va Virtual page address.
* @param asid Address space identifier.
* @param entry The rest of TLB entry as required by TLB insertion
* format.
* @param dtr If true, insert into data translation register, use
* instruction translation register otherwise.
* @param tr Translation register.
*/
void tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr)
void
tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr,
index_t tr)
{
region_register rr;
bool restore_rr = false;
320,19 → 319,20
}
 
asm volatile (
"mov r8=psr;;\n"
"mov r8 = psr;;\n"
"rsm %0;;\n" /* PSR_IC_MASK */
"srlz.d;;\n"
"srlz.i;;\n"
"mov cr.ifa=%1\n" /* va */
"mov cr.itir=%2;;\n" /* entry.word[1] */
"cmp.eq p6,p7=%5,r0;;\n" /* decide between itr and dtr */
"(p6) itr.i itr[%4]=%3;;\n"
"(p7) itr.d dtr[%4]=%3;;\n"
"mov psr.l=r8;;\n"
"mov cr.ifa = %1\n" /* va */
"mov cr.itir = %2;;\n" /* entry.word[1] */
"cmp.eq p6,p7 = %5,r0;;\n" /* decide between itr and dtr */
"(p6) itr.i itr[%4] = %3;;\n"
"(p7) itr.d dtr[%4] = %3;;\n"
"mov psr.l = r8;;\n"
"srlz.d;;\n"
:
: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (tr), "r" (dtr)
: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]),
"r" (entry.word[0]), "r" (tr), "r" (dtr)
: "p6", "p7", "r8"
);
345,12 → 345,15
 
/** Insert data into DTLB.
*
* @param page Virtual page address including VRN bits.
* @param frame Physical frame address.
* @param dtr If true, insert into data translation register, use data translation cache otherwise.
* @param tr Translation register if dtr is true, ignored otherwise.
* @param page Virtual page address including VRN bits.
* @param frame Physical frame address.
* @param dtr If true, insert into data translation register, use data
* translation cache otherwise.
* @param tr Translation register if dtr is true, ignored otherwise.
*/
void dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr, index_t tr)
void
dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr,
index_t tr)
{
tlb_entry_t entry;
376,18 → 379,18
*
* Purge DTR entries used by the kernel.
*
* @param page Virtual page address including VRN bits.
* @param width Width of the purge in bits.
* @param page Virtual page address including VRN bits.
* @param width Width of the purge in bits.
*/
void dtr_purge(uintptr_t page, count_t width)
{
asm volatile ("ptr.d %0, %1\n" : : "r" (page), "r" (width<<2));
asm volatile ("ptr.d %0, %1\n" : : "r" (page), "r" (width << 2));
}
 
 
/** Copy content of PTE into data translation cache.
*
* @param t PTE.
* @param t PTE.
*/
void dtc_pte_copy(pte_t *t)
{
413,7 → 416,7
 
/** Copy content of PTE into instruction translation cache.
*
* @param t PTE.
* @param t PTE.
*/
void itc_pte_copy(pte_t *t)
{
440,8 → 443,8
 
/** Instruction TLB fault handler for faults with VHPT turned off.
*
* @param vector Interruption vector.
* @param istate Structure with saved interruption state.
* @param vector Interruption vector.
* @param istate Structure with saved interruption state.
*/
void alternate_instruction_tlb_fault(uint64_t vector, istate_t *istate)
{
469,16 → 472,77
*/
page_table_unlock(AS, true);
if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate,"Page fault at %p",va);
panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
fault_if_from_uspace(istate,"Page fault at %p.",va);
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid,
istate->cr_iip);
}
}
}
 
static int is_io_page_accessible(int page)
{
if (TASK->arch.iomap)
return bitmap_get(TASK->arch.iomap, page);
else
return 0;
}
 
#define IO_FRAME_BASE 0xFFFFC000000
 
/**
* There is special handling of memory mapped legacy io, because of 4KB sized
* access for userspace.
*
* @param va Virtual address of page fault.
* @param istate Structure with saved interruption state.
*
* @return One on success, zero on failure.
*/
static int try_memmap_io_insertion(uintptr_t va, istate_t *istate)
{
if ((va >= IO_OFFSET ) && (va < IO_OFFSET + (1 << IO_PAGE_WIDTH))) {
if (TASK) {
uint64_t io_page = (va & ((1 << IO_PAGE_WIDTH) - 1)) >>
USPACE_IO_PAGE_WIDTH;
 
if (is_io_page_accessible(io_page)) {
uint64_t page, frame;
 
page = IO_OFFSET +
(1 << USPACE_IO_PAGE_WIDTH) * io_page;
frame = IO_FRAME_BASE +
(1 << USPACE_IO_PAGE_WIDTH) * io_page;
 
tlb_entry_t entry;
entry.word[0] = 0;
entry.word[1] = 0;
entry.p = true; /* present */
entry.ma = MA_UNCACHEABLE;
entry.a = true; /* already accessed */
entry.d = true; /* already dirty */
entry.pl = PL_USER;
entry.ar = AR_READ | AR_WRITE;
entry.ppn = frame >> PPN_SHIFT;
entry.ps = USPACE_IO_PAGE_WIDTH;
dtc_mapping_insert(page, TASK->as->asid, entry);
return 1;
} else {
fault_if_from_uspace(istate,
"IO access fault at %p.", va);
}
}
}
return 0;
}
 
/** Data TLB fault handler for faults with VHPT turned off.
*
* @param vector Interruption vector.
* @param istate Structure with saved interruption state.
* @param vector Interruption vector.
* @param istate Structure with saved interruption state.
*/
void alternate_data_tlb_fault(uint64_t vector, istate_t *istate)
{
511,13 → 575,17
dtc_pte_copy(t);
page_table_unlock(AS, true);
} else {
page_table_unlock(AS, true);
if (try_memmap_io_insertion(va, istate))
return;
/*
* Forward the page fault to the address space page fault handler.
* Forward the page fault to the address space page fault
* handler.
*/
page_table_unlock(AS, true);
if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate,"Page fault at %p",va);
panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
fault_if_from_uspace(istate,"Page fault at %p.",va);
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid,
istate->cr_iip);
}
}
}
526,18 → 594,18
*
* This fault should not occur.
*
* @param vector Interruption vector.
* @param istate Structure with saved interruption state.
* @param vector Interruption vector.
* @param istate Structure with saved interruption state.
*/
void data_nested_tlb_fault(uint64_t vector, istate_t *istate)
{
panic("%s\n", __func__);
panic("%s.", __func__);
}
 
/** Data Dirty bit fault handler.
*
* @param vector Interruption vector.
* @param istate Structure with saved interruption state.
* @param vector Interruption vector.
* @param istate Structure with saved interruption state.
*/
void data_dirty_bit_fault(uint64_t vector, istate_t *istate)
{
562,10 → 630,9
dtc_pte_copy(t);
} else {
if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate,"Page fault at %p",va);
panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
t->d = true;
dtc_pte_copy(t);
fault_if_from_uspace(istate,"Page fault at %p.",va);
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid,
istate->cr_iip);
}
}
page_table_unlock(AS, true);
573,8 → 640,8
 
/** Instruction access bit fault handler.
*
* @param vector Interruption vector.
* @param istate Structure with saved interruption state.
* @param vector Interruption vector.
* @param istate Structure with saved interruption state.
*/
void instruction_access_bit_fault(uint64_t vector, istate_t *istate)
{
599,10 → 666,9
itc_pte_copy(t);
} else {
if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate,"Page fault at %p",va);
panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
t->a = true;
itc_pte_copy(t);
fault_if_from_uspace(istate, "Page fault at %p.", va);
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid,
istate->cr_iip);
}
}
page_table_unlock(AS, true);
636,10 → 702,9
dtc_pte_copy(t);
} else {
if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate,"Page fault at %p",va);
panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
t->a = true;
itc_pte_copy(t);
fault_if_from_uspace(istate, "Page fault at %p.", va);
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid,
istate->cr_iip);
}
}
page_table_unlock(AS, true);
678,11 → 743,19
} else {
page_table_unlock(AS, true);
if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate,"Page fault at %p",va);
panic("%s: va=%p, rid=%d\n", __func__, va, rid);
fault_if_from_uspace(istate, "Page fault at %p.", va);
panic("%s: va=%p, rid=%d.", __func__, va, rid);
}
}
}
 
void tlb_arch_init(void)
{
}
 
void tlb_print(void)
{
}
 
/** @}
*/
/branches/dd/kernel/arch/ia64/src/mm/vhpt.c
41,7 → 41,8
 
uintptr_t vhpt_set_up(void)
{
vhpt_base = frame_alloc(VHPT_WIDTH - FRAME_WIDTH, FRAME_KA | FRAME_ATOMIC);
vhpt_base = frame_alloc(VHPT_WIDTH - FRAME_WIDTH,
FRAME_KA | FRAME_ATOMIC);
if (!vhpt_base)
panic("Kernel configured with VHPT but no memory for table.");
vhpt_invalidate_all();
81,7 → 82,7
 
void vhpt_invalidate_all()
{
memsetb((uintptr_t) vhpt_base, 1 << VHPT_WIDTH, 0);
memsetb(vhpt_base, 1 << VHPT_WIDTH, 0);
}
 
void vhpt_invalidate_asid(asid_t asid)
/branches/dd/kernel/arch/ia64/src/mm/as.c
68,7 → 68,7
continue;
rr.word = rr_read(i);
rr.map.ve = false; /* disable VHPT walker */
rr.map.ve = false; /* disable VHPT walker */
rr.map.rid = ASID2RID(as->asid, i);
rr.map.ps = PAGE_WIDTH;
rr_write(i, rr.word);
/branches/dd/kernel/arch/ia64/src/mm/frame.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia64mm
/** @addtogroup ia64mm
* @{
*/
/** @file
36,26 → 36,55
#include <mm/frame.h>
#include <config.h>
#include <panic.h>
#include <arch/bootinfo.h>
#include <align.h>
#include <macros.h>
 
/*
* This is Ski-specific and certainly not sufficient
* for real ia64 systems that provide memory map.
*/
#define MEMORY_SIZE (64 * 1024 * 1024)
#define MEMORY_BASE (64 * 1024 * 1024)
#define KERNEL_RESERVED_AREA_BASE (0x4400000)
#define KERNEL_RESERVED_AREA_SIZE (16 * 1024 * 1024)
 
#define ROM_BASE 0xa0000 //For ski
#define ROM_SIZE (384 * 1024) //For ski
void poke_char(int x,int y,char ch, char c);
#define ROM_BASE 0xa0000 /* for simulators */
#define ROM_SIZE (384 * 1024) /* for simulators */
 
#define MIN_ZONE_SIZE (64 * 1024)
 
#define MINCONF 1
 
uintptr_t last_frame = 0;
 
void frame_arch_init(void)
{
zone_create(MEMORY_BASE >> FRAME_WIDTH, SIZE2FRAMES(MEMORY_SIZE), (MEMORY_SIZE) >> FRAME_WIDTH, 0);
/*
* Blacklist ROM regions.
*/
frame_mark_unavailable(ADDR2PFN(ROM_BASE), SIZE2FRAMES(ROM_SIZE));
if (config.cpu_active == 1) {
unsigned int i;
for (i = 0; i < bootinfo->memmap_items; i++) {
if (bootinfo->memmap[i].type == EFI_MEMMAP_FREE_MEM) {
uint64_t base = bootinfo->memmap[i].base;
uint64_t size = bootinfo->memmap[i].size;
uint64_t abase = ALIGN_UP(base, FRAME_SIZE);
 
if (size > FRAME_SIZE)
size -= abase - base;
 
if (size > MIN_ZONE_SIZE) {
zone_create(abase >> FRAME_WIDTH,
size >> FRAME_WIDTH,
max(MINCONF, abase >> FRAME_WIDTH),
0);
}
if (abase + size > last_frame)
last_frame = abase + size;
}
}
/*
* Blacklist ROM regions.
*/
frame_mark_unavailable(ADDR2PFN(ROM_BASE),
SIZE2FRAMES(ROM_SIZE));
 
frame_mark_unavailable(ADDR2PFN(KERNEL_RESERVED_AREA_BASE),
SIZE2FRAMES(KERNEL_RESERVED_AREA_SIZE));
}
}
 
/** @}
/branches/dd/kernel/arch/ia64/src/mm/page.c
27,7 → 27,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia64mm
/** @addtogroup ia64mm
* @{
*/
/** @file
47,6 → 47,7
#include <arch/asm.h>
#include <arch/barrier.h>
#include <memstr.h>
#include <align.h>
 
static void set_environment(void);
 
62,9 → 63,9
void set_environment(void)
{
region_register rr;
pta_register pta;
pta_register pta;
int i;
#ifdef CONFIG_VHPT
#ifdef CONFIG_VHPT
uintptr_t vhpt_base;
#endif
 
122,10 → 123,10
*
* Interrupts must be disabled.
*
* @param page Address of virtual page including VRN bits.
* @param asid Address space identifier.
* @param page Address of virtual page including VRN bits.
* @param asid Address space identifier.
*
* @return VHPT entry address.
* @return VHPT entry address.
*/
vhpt_entry_t *vhpt_hash(uintptr_t page, asid_t asid)
{
166,10 → 167,11
*
* Interrupts must be disabled.
*
* @param page Address of virtual page including VRN bits.
* @param asid Address space identifier.
* @param page Address of virtual page including VRN bits.
* @param asid Address space identifier.
*
* @return True if page and asid match the page and asid of t, false otherwise.
* @return True if page and asid match the page and asid of t,
* false otherwise.
*/
bool vhpt_compare(uintptr_t page, asid_t asid, vhpt_entry_t *v)
{
210,12 → 212,15
/** Set up one VHPT entry.
*
* @param v VHPT entry to be set up.
* @param page Virtual address of the page mapped by the entry.
* @param asid Address space identifier of the address space to which page belongs.
* @param frame Physical address of the frame to wich page is mapped.
* @param flags Different flags for the mapping.
* @param page Virtual address of the page mapped by the entry.
* @param asid Address space identifier of the address space to which
* page belongs.
* @param frame Physical address of the frame to wich page is mapped.
* @param flags Different flags for the mapping.
*/
void vhpt_set_record(vhpt_entry_t *v, uintptr_t page, asid_t asid, uintptr_t frame, int flags)
void
vhpt_set_record(vhpt_entry_t *v, uintptr_t page, asid_t asid, uintptr_t frame,
int flags)
{
region_register rr_save, rr;
index_t vrn;
249,7 → 254,8
v->word[3] = 0;
v->present.p = true;
v->present.ma = (flags & PAGE_CACHEABLE) ? MA_WRITEBACK : MA_UNCACHEABLE;
v->present.ma = (flags & PAGE_CACHEABLE) ?
MA_WRITEBACK : MA_UNCACHEABLE;
v->present.a = false; /* not accessed */
v->present.d = false; /* not dirty */
v->present.pl = (flags & PAGE_USER) ? PL_USER : PL_KERNEL;
262,5 → 268,11
v->present.tag.tag_word = tag;
}
 
uintptr_t hw_map(uintptr_t physaddr, size_t size __attribute__ ((unused)))
{
/* THIS is a dirty hack. */
return (uintptr_t)((uint64_t)(PA2KA(physaddr)) + VIO_OFFSET);
}
 
/** @}
*/
/branches/dd/kernel/arch/ia64/src/interrupt.c
53,6 → 53,7
#include <ipc/irq.h>
#include <ipc/ipc.h>
#include <synch/spinlock.h>
#include <mm/tlb.h>
 
#define VECTORS_64_BUNDLE 20
#define VECTORS_16_BUNDLE 48
185,21 → 186,21
break;
}
 
fault_if_from_uspace(istate, "General Exception (%s)", desc);
fault_if_from_uspace(istate, "General Exception (%s).", desc);
 
dump_interrupted_context(istate);
panic("General Exception (%s)\n", desc);
panic("General Exception (%s).", desc);
}
 
void disabled_fp_register(uint64_t vector, istate_t *istate)
{
#ifdef CONFIG_FPU_LAZY
scheduler_fpu_lazy_request();
#ifdef CONFIG_FPU_LAZY
scheduler_fpu_lazy_request();
#else
fault_if_from_uspace(istate, "Interruption: %#hx (%s)",
fault_if_from_uspace(istate, "Interruption: %#hx (%s).",
(uint16_t) vector, vector_to_string(vector));
dump_interrupted_context(istate);
panic("Interruption: %#hx (%s)\n", (uint16_t) vector,
panic("Interruption: %#hx (%s).", (uint16_t) vector,
vector_to_string(vector));
#endif
}
227,40 → 228,82
 
void universal_handler(uint64_t vector, istate_t *istate)
{
fault_if_from_uspace(istate, "Interruption: %#hx (%s)\n",
fault_if_from_uspace(istate, "Interruption: %#hx (%s).",
(uint16_t) vector, vector_to_string(vector));
dump_interrupted_context(istate);
panic("Interruption: %#hx (%s)\n", (uint16_t) vector,
panic("Interruption: %#hx (%s).", (uint16_t) vector,
vector_to_string(vector));
}
 
static void end_of_local_irq(void)
{
asm volatile ("mov cr.eoi=r0;;");
}
 
 
void external_interrupt(uint64_t vector, istate_t *istate)
{
cr_ivr_t ivr;
irq_t *irq;
cr_ivr_t ivr;
ivr.value = ivr_read();
srlz_d();
 
irq = irq_dispatch_and_lock(ivr.vector);
if (irq) {
irq->handler(irq, irq->arg);
spinlock_unlock(&irq->lock);
} else {
switch (ivr.vector) {
case INTERRUPT_SPURIOUS:
switch (ivr.vector) {
case INTERRUPT_SPURIOUS:
#ifdef CONFIG_DEBUG
printf("cpu%d: spurious interrupt\n", CPU->id);
printf("cpu%d: spurious interrupt\n", CPU->id);
#endif
break;
break;
 
default:
panic("\nUnhandled External Interrupt Vector %d\n",
#ifdef CONFIG_SMP
case VECTOR_TLB_SHOOTDOWN_IPI:
tlb_shootdown_ipi_recv();
end_of_local_irq();
break;
#endif
 
case INTERRUPT_TIMER:
irq = irq_dispatch_and_lock(ivr.vector);
if (irq) {
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
panic("Unhandled Internal Timer Interrupt (%d).",
ivr.vector);
break;
}
break;
default:
irq = irq_dispatch_and_lock(ivr.vector);
if (irq) {
/*
* The IRQ handler was found.
*/
if (irq->preack) {
/* Send EOI before processing the interrupt */
end_of_local_irq();
}
irq->handler(irq);
if (!irq->preack)
end_of_local_irq();
spinlock_unlock(&irq->lock);
} else {
/*
* Unhandled interrupt.
*/
end_of_local_irq();
#ifdef CONFIG_DEBUG
printf("\nUnhandled External Interrupt Vector %d\n",
ivr.vector);
#endif
}
break;
}
}
 
void trap_virtual_enable_irqs(uint16_t irqmask)
{
}
 
/** @}
*/
/branches/dd/kernel/arch/ia64/src/drivers/ega.c
File deleted
/branches/dd/kernel/arch/ia64/src/drivers/it.c
44,25 → 44,44
#include <ddi/device.h>
#include <arch.h>
 
#define IT_SERVICE_CLOCKS 64
#define IT_SERVICE_CLOCKS 64
 
#define FREQ_NUMERATOR_SHIFT 32
#define FREQ_NUMERATOR_MASK 0xffffffff00000000ULL
 
#define FREQ_DENOMINATOR_SHIFT 0
#define FREQ_DENOMINATOR_MASK 0xffffffffULL
 
uint64_t it_delta;
 
static irq_t it_irq;
 
static irq_ownership_t it_claim(void);
static void it_interrupt(irq_t *irq, void *arg, ...);
static irq_ownership_t it_claim(irq_t *);
static void it_interrupt(irq_t *);
 
/** Initialize Interval Timer. */
void it_init(void)
{
cr_itv_t itv;
 
irq_initialize(&it_irq);
it_irq.inr = INTERRUPT_TIMER;
it_irq.devno = device_assign_devno();
it_irq.claim = it_claim;
it_irq.handler = it_interrupt;
irq_register(&it_irq);
 
if (config.cpu_active == 1) {
irq_initialize(&it_irq);
it_irq.inr = INTERRUPT_TIMER;
it_irq.devno = device_assign_devno();
it_irq.claim = it_claim;
it_irq.handler = it_interrupt;
irq_register(&it_irq);
uint64_t base_freq;
base_freq = ((bootinfo->freq_scale) & FREQ_NUMERATOR_MASK) >>
FREQ_NUMERATOR_SHIFT;
base_freq *= bootinfo->sys_freq;
base_freq /= ((bootinfo->freq_scale) & FREQ_DENOMINATOR_MASK) >>
FREQ_DENOMINATOR_SHIFT;
it_delta = base_freq / HZ;
}
/* initialize Interval Timer external interrupt vector */
itv.value = itv_read();
itv.vector = INTERRUPT_TIMER;
85,13 → 104,13
*
* @return Always IRQ_ACCEPT.
*/
irq_ownership_t it_claim(void)
irq_ownership_t it_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
/** Process Interval Timer interrupt. */
void it_interrupt(irq_t *irq, void *arg, ...)
void it_interrupt(irq_t *irq)
{
int64_t c;
int64_t m;
/branches/dd/kernel/arch/ia64/src/start.S
32,19 → 32,15
#include <mm/asid.h>
 
#define RR_MASK (0xFFFFFFFF00000002)
#define RID_SHIFT 8
#define PS_SHIFT 2
#define RID_SHIFT 8
#define PS_SHIFT 2
 
#define KERNEL_TRANSLATION_I 0x0010000000000661
#define KERNEL_TRANSLATION_D 0x0010000000000661
#define KERNEL_TRANSLATION_VIO 0x0010000000000671
#define KERNEL_TRANSLATION_IO 0x00100FFFFC000671
#define VIO_OFFSET 0x0002000000000000
#define KERNEL_TRANSLATION_I 0x0010000000000661
#define KERNEL_TRANSLATION_D 0x0010000000000661
#define KERNEL_TRANSLATION_VIO 0x0010000000000671
#define KERNEL_TRANSLATION_IO 0x00100FFFFC000671
#define KERNEL_TRANSLATION_FW 0x00100000F0000671
 
#define IO_OFFSET 0x0001000000000000
 
 
 
.section K_TEXT_START, "ax"
 
.global kernel_image_start
53,6 → 49,19
kernel_image_start:
.auto
 
#ifdef CONFIG_SMP
# Identify self(CPU) in OS structures by ID / EID
 
mov r9 = cr64
mov r10 = 1
movl r12 = 0xffffffff
movl r8 = cpu_by_id_eid_list
and r8 = r8, r12
shr r9 = r9, 16
add r8 = r8, r9
st1 [r8] = r10
#endif
 
mov psr.l = r0
srlz.i
srlz.d
59,39 → 68,29
 
# Fill TR.i and TR.d using Region Register #VRN_KERNEL
 
 
movl r8 = (VRN_KERNEL << VRN_SHIFT)
mov r9 = rr[r8]
 
 
movl r10 = (RR_MASK)
and r9 = r10, r9
movl r10 = ((RID_KERNEL << RID_SHIFT) | (KERNEL_PAGE_WIDTH << PS_SHIFT))
or r9 = r10, r9
 
 
mov rr[r8] = r9
 
 
 
movl r8 = (VRN_KERNEL << VRN_SHIFT)
mov cr.ifa = r8
 
mov r11 = cr.itir ;;
movl r10 = (KERNEL_PAGE_WIDTH << PS_SHIFT);;
or r10 =r10 , r11 ;;
mov cr.itir = r10;;
mov r11 = cr.itir
movl r10 = (KERNEL_PAGE_WIDTH << PS_SHIFT)
or r10 = r10, r11
mov cr.itir = r10
 
movl r10 = (KERNEL_TRANSLATION_I)
itr.i itr[r0] = r10
 
movl r10 = (KERNEL_TRANSLATION_D)
itr.d dtr[r0] = r10
 
 
movl r7 = 1
movl r8 = (VRN_KERNEL << VRN_SHIFT) | VIO_OFFSET
mov cr.ifa = r8
98,15 → 97,13
movl r10 = (KERNEL_TRANSLATION_VIO)
itr.d dtr[r7] = r10
 
mov r11 = cr.itir
movl r10 = ~0xfc
and r10 = r10, r11
movl r11 = (IO_PAGE_WIDTH << PS_SHIFT)
or r10 = r10, r11
mov cr.itir = r10
 
mov r11 = cr.itir ;;
movl r10 = ~0xfc;;
and r10 =r10 , r11 ;;
movl r11 = (IO_PAGE_WIDTH << PS_SHIFT);;
or r10 =r10 , r11 ;;
mov cr.itir = r10;;
 
 
movl r7 = 2
movl r8 = (VRN_KERNEL << VRN_SHIFT) | IO_OFFSET
mov cr.ifa = r8
113,12 → 110,26
movl r10 = (KERNEL_TRANSLATION_IO)
itr.d dtr[r7] = r10
 
# Setup mapping for fimware arrea (also SAPIC)
 
mov r11 = cr.itir
movl r10 = ~0xfc
and r10 = r10, r11
movl r11 = (FW_PAGE_WIDTH << PS_SHIFT)
or r10 = r10, r11
mov cr.itir = r10
 
movl r7 = 3
movl r8 = (VRN_KERNEL << VRN_SHIFT) | FW_OFFSET
mov cr.ifa = r8
movl r10 = (KERNEL_TRANSLATION_FW)
itr.d dtr[r7] = r10
 
# initialize PSR
# Initialize PSR
 
movl r10 = (PSR_DT_MASK | PSR_RT_MASK | PSR_IT_MASK | PSR_IC_MASK) /* Enable paging */
mov r9 = psr
 
or r10 = r10, r9
mov cr.ipsr = r10
mov cr.ifs = r0
128,11 → 139,14
srlz.i
 
.explicit
 
/*
* Return From Interupt is the only the way to fill upper half word of PSR.
* Return From Interrupt is the only way to
* fill the upper half word of PSR.
*/
rfi;;
rfi ;;
 
 
.global paging_start
paging_start:
 
140,45 → 154,64
* Now we are paging.
*/
 
# switch to register bank 1
# Switch to register bank 1
bsw.1
 
#ifdef CONFIG_SMP
# Am I BSP or AP?
movl r20 = bsp_started ;;
ld8 r20 = [r20] ;;
cmp.eq p3, p2 = r20, r0 ;;
#else
cmp.eq p3, p2 = r0, r0 ;; /* you are BSP */
#endif /* CONFIG_SMP */
# initialize register stack
# Initialize register stack
mov ar.rsc = r0
movl r8 = (VRN_KERNEL << VRN_SHIFT) ;;
mov ar.bspstore = r8
loadrs
 
# initialize memory stack to some sane value
# Initialize memory stack to some sane value
movl r12 = stack0 ;;
add r12 = -16, r12 /* allocate a scratch area on the stack */
 
# initialize gp (Global Pointer) register
# Initialize gp (Global Pointer) register
movl r20 = (VRN_KERNEL << VRN_SHIFT);;
or r20 = r20,r1;;
movl r1 = _hardcoded_load_address
/*
* Initialize hardcoded_* variables.
* Initialize hardcoded_* variables. Do only BSP
*/
movl r14 = _hardcoded_ktext_size
movl r15 = _hardcoded_kdata_size
movl r16 = _hardcoded_load_address ;;
addl r17 = @gprel(hardcoded_ktext_size), gp
addl r18 = @gprel(hardcoded_kdata_size), gp
addl r19 = @gprel(hardcoded_load_address), gp
addl r21 = @gprel(bootinfo), gp
(p3) movl r14 = _hardcoded_ktext_size
(p3) movl r15 = _hardcoded_kdata_size
(p3) movl r16 = _hardcoded_load_address ;;
(p3) addl r17 = @gprel(hardcoded_ktext_size), gp
(p3) addl r18 = @gprel(hardcoded_kdata_size), gp
(p3) addl r19 = @gprel(hardcoded_load_address), gp
(p3) addl r21 = @gprel(bootinfo), gp
;;
st8 [r17] = r14
st8 [r18] = r15
st8 [r19] = r16
st8 [r21] = r20
(p3) st8 [r17] = r14
(p3) st8 [r18] = r15
(p3) st8 [r19] = r16
(p3) st8 [r21] = r20
 
ssm (1 << 19) ;; /* Disable f32 - f127 */
srlz.i
srlz.d ;;
 
#ifdef CONFIG_SMP
(p2) movl r18 = main_ap ;;
(p2) mov b1 = r18 ;;
(p2) br.call.sptk.many b0 = b1
 
# Mark that BSP is on
mov r20 = 1 ;;
movl r21 = bsp_started ;;
st8 [r21] = r20 ;;
#endif
 
br.call.sptk.many b0 = arch_pre_main
 
movl r18 = main_bsp ;;
185,6 → 218,51
mov b1 = r18 ;;
br.call.sptk.many b0 = b1
 
 
0:
br 0b
 
#ifdef CONFIG_SMP
 
.align 4096
kernel_image_ap_start:
.auto
 
# Identify self(CPU) in OS structures by ID / EID
 
mov r9 = cr64
mov r10 = 1
movl r12 = 0xffffffff
movl r8 = cpu_by_id_eid_list
and r8 = r8, r12
shr r9 = r9, 16
add r8 = r8, r9
st1 [r8] = r10
# Wait for wakeup synchro signal (#3 in cpu_by_id_eid_list)
kernel_image_ap_start_loop:
movl r11 = kernel_image_ap_start_loop
and r11 = r11, r12
mov b1 = r11
 
ld1 r20 = [r8] ;;
movl r21 = 3 ;;
cmp.eq p2, p3 = r20, r21 ;;
(p3) br.call.sptk.many b0 = b1
 
movl r11 = kernel_image_start
and r11 = r11, r12
mov b1 = r11
br.call.sptk.many b0 = b1
 
.align 16
.global bsp_started
bsp_started:
.space 8
 
.align 4096
.global cpu_by_id_eid_list
cpu_by_id_eid_list:
.space 65536
 
#endif /* CONFIG_SMP */
/branches/dd/kernel/arch/arm32/_link.ld.in
1,15 → 1,16
/*
* ARM linker script
*
* ARM linker script
*
* kernel text
* kernel data
*
*
*/
 
#define KERNEL_LOAD_ADDRESS 0x80200000
 
OUTPUT_ARCH(arm)
ENTRY(kernel_image_start)
ENTRY(kernel_image_start)
 
 
SECTIONS {
. = KERNEL_LOAD_ADDRESS;
.text : {
19,29 → 20,29
}
.data : {
kdata_start = .;
*(.data); /* initialized data */
*(.data); /* initialized data */
hardcoded_ktext_size = .;
LONG(ktext_end - ktext_start);
LONG(ktext_end - ktext_start);
hardcoded_kdata_size = .;
LONG(kdata_end - kdata_start);
hardcoded_load_address = .;
LONG(KERNEL_LOAD_ADDRESS);
*(.bss); /* uninitialized static variables */
*(COMMON); /* global variables */
 
*(.bss); /* uninitialized static variables */
*(COMMON); /* global variables */
*(.rodata*);
*(.sdata);
*(.reginfo);
symbol_table = .;
*(symtab.*);
*(symtab.*);
}
.sbss : {
*(.sbss);
*(.scommon);
}
 
kdata_end = .;
 
/DISCARD/ : {
*(.mdebug*);
*(.pdr);
48,5 → 49,4
*(.comment);
*(.note);
}
 
}
/branches/dd/kernel/arch/arm32/include/boot.h
File deleted
/branches/dd/kernel/arch/arm32/include/asm/boot.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup arm32
/** @addtogroup arm32
* @{
*/
/** @file
39,24 → 39,7
/** Size of a temporary stack used for initial kernel start. */
#define TEMP_STACK_SIZE 0x100
 
#ifndef __ASM__
 
/** Kernel entry point.
*
* Implemented in assembly. Copies boot_bootinfo (declared as bootinfo in
* boot/arch/arm32/loader/main.c) to #bootinfo struct. Then jumps to
* #arch_pre_main and #main_bsp.
*
* @param entry Entry point address (not used).
* @param boot_bootinfo Struct holding information about loaded tasks.
* @param bootinfo_size Size of the bootinfo structure.
*/
extern void kernel_image_start(void *entry, void *boot_bootinfo,
unsigned int bootinfo_size);
 
#endif
 
#endif
 
/** @}
*/
/branches/dd/kernel/arch/arm32/include/interrupt.h
37,6 → 37,7
#define KERN_arm32_INTERRUPT_H_
 
#include <arch/types.h>
#include <arch/exception.h>
 
/** Initial size of exception dispatch table. */
#define IVT_ITEMS 6
/branches/dd/kernel/arch/arm32/include/regutils.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup arm32
/** @addtogroup arm32
* @{
*/
/**
57,7 → 57,10
static inline uint32_t nm## _status_reg_read(void) \
{ \
uint32_t retval; \
asm volatile("mrs %0, " #reg : "=r" (retval)); \
asm volatile( \
"mrs %[retval], " #reg \
: [retval] "=r" (retval) \
); \
return retval; \
}
 
64,7 → 67,10
#define GEN_STATUS_WRITE(nm,reg,fieldname, field) \
static inline void nm## _status_reg_ ##fieldname## _write(uint32_t value) \
{ \
asm volatile("msr " #reg "_" #field ", %0" : : "r" (value)); \
asm volatile( \
"msr " #reg "_" #field ", %[value]" \
:: [value] "r" (value) \
); \
}
 
 
/branches/dd/kernel/arch/arm32/include/console.h
36,13 → 36,6
#ifndef KERN_arm32_CONSOLE_H_
#define KERN_arm32_CONSOLE_H_
 
 
/** Initializes console.
*
* @param devno Console device number.
*/
extern void console_init(devno_t devno);
 
#endif
 
/** @}
/branches/dd/kernel/arch/arm32/include/machine.h
102,18 → 102,15
extern uintptr_t machine_get_fb_address(void);
 
 
#ifdef MACHINE_GXEMUL_TESTARM
#define machine_console_init(devno) gxemul_console_init(devno)
#define machine_grab_console gxemul_grab_console
#define machine_release_console gxemul_release_console
#define machine_hw_map_init gxemul_hw_map_init
#define machine_timer_irq_start gxemul_timer_irq_start
#define machine_cpu_halt gxemul_cpu_halt
#define machine_get_memory_size gxemul_get_memory_size
#define machine_debug_putc(ch) gxemul_debug_putc(ch)
#define machine_irq_exception(exc_no, istate) \
gxemul_irq_exception(exc_no, istate)
#define machine_get_fb_address gxemul_get_fb_address
#ifdef MACHINE_gxemul
#define machine_console_init(devno) gxemul_console_init(devno)
#define machine_hw_map_init gxemul_hw_map_init
#define machine_timer_irq_start gxemul_timer_irq_start
#define machine_cpu_halt gxemul_cpu_halt
#define machine_get_memory_size gxemul_get_memory_size
#define machine_debug_putc(ch) gxemul_debug_putc(ch)
#define machine_irq_exception(exc_no, istate) gxemul_irq_exception(exc_no, istate)
#define machine_get_fb_address gxemul_get_fb_address
#endif
 
#endif
/branches/dd/kernel/arch/arm32/include/types.h
42,10 → 42,6
# define ATTRIBUTE_PACKED
#endif
 
#define NULL 0
#define false 0
#define true 1
 
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed long int32_t;
68,15 → 64,32
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef uint8_t bool;
typedef uint64_t thread_id_t;
typedef uint64_t task_id_t;
typedef uint32_t context_id_t;
typedef struct {
} fncptr_t;
 
typedef int32_t inr_t;
typedef int32_t devno_t;
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
#define PRIi "u" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
#define PRId32 "d" /**< Format for int32_t. */
#define PRId64 "lld" /**< Format for int64_t. */
#define PRIdn "d" /**< Format for native_t. */
 
#define PRIu8 "u" /**< Format for uint8_t. */
#define PRIu16 "u" /**< Format for uint16_t. */
#define PRIu32 "u" /**< Format for uint32_t. */
#define PRIu64 "llu" /**< Format for uint64_t. */
#define PRIun "u" /**< Format for unative_t. */
 
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */
#define PRIx64 "llx" /**< Format for hexadecimal (u)int64_t. */
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */
 
/** Page table entry.
*
* We have different structs for level 0 and level 1 page table entries.
/branches/dd/kernel/arch/arm32/include/memstr.h
38,10 → 38,10
 
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt))
 
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x);
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x);
extern void memsetw(void *dst, size_t cnt, uint16_t x);
extern void memsetb(void *dst, size_t cnt, uint8_t x);
 
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt);
extern int memcmp(const void *a, const void *b, size_t cnt);
 
#endif
 
/branches/dd/kernel/arch/arm32/include/atomic.h
26,10 → 26,10
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup arm32
/** @addtogroup arm32
* @{
*/
/** @file
/** @file
* @brief Atomic operations.
*/
 
42,26 → 42,26
* @param i Value to be added.
*
* @return Value after addition.
*
*/
static inline long atomic_add(atomic_t *val, int i)
{
int ret;
volatile long *mem = &(val->count);
 
asm volatile (
"1:\n"
"ldr r2, [%1] \n"
"add r3, r2, %2 \n"
"str r3, %0 \n"
"swp r3, r3, [%1] \n"
"cmp r3, r2 \n"
"bne 1b \n"
 
: "=m" (ret)
: "r" (mem), "r" (i)
"1:\n"
"ldr r2, [%[mem]]\n"
"add r3, r2, %[i]\n"
"str r3, %[ret]\n"
"swp r3, r3, [%[mem]]\n"
"cmp r3, r2\n"
"bne 1b\n"
: [ret] "=m" (ret)
: [mem] "r" (mem), [i] "r" (i)
: "r3", "r2"
);
 
return ret;
}
 
/branches/dd/kernel/arch/arm32/include/arch.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup arm32
/** @addtogroup arm32
* @{
*/
/** @file
36,6 → 36,26
#ifndef KERN_arm32_ARCH_H_
#define KERN_arm32_ARCH_H_
 
#define TASKMAP_MAX_RECORDS 32
#define CPUMAP_MAX_RECORDS 32
 
#define BOOTINFO_TASK_NAME_BUFLEN 32
 
#include <typedefs.h>
 
typedef struct {
uintptr_t addr;
uint32_t size;
char name[BOOTINFO_TASK_NAME_BUFLEN];
} utask_t;
 
typedef struct {
uint32_t cnt;
utask_t tasks[TASKMAP_MAX_RECORDS];
} bootinfo_t;
 
extern void arch_pre_main(void *entry, bootinfo_t *bootinfo);
 
#endif
 
/** @}
/branches/dd/kernel/arch/arm32/include/asm.h
26,10 → 26,10
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup arm32
/** @addtogroup arm32
* @{
*/
/** @file
/** @file
* @brief Declarations of functions implemented in assembly.
*/
 
36,6 → 36,7
#ifndef KERN_arm32_ASM_H_
#define KERN_arm32_ASM_H_
 
#include <typedefs.h>
#include <arch/types.h>
#include <arch/stack.h>
#include <config.h>
46,19 → 47,50
{
}
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
/** Return base address of current stack.
*
*
* Return the base address of the current stack.
* The stack is assumed to be STACK_SIZE bytes long.
* The stack must start on page boundary.
*
*/
static inline uintptr_t get_stack_base(void)
{
uintptr_t v;
asm volatile (
"and %0, sp, %1\n"
: "=r" (v)
: "r" (~(STACK_SIZE - 1))
"and %[v], sp, %[size]\n"
: [v] "=r" (v)
: [size] "r" (~(STACK_SIZE - 1))
);
return v;
}
/branches/dd/kernel/arch/arm32/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup arm32mm
/** @addtogroup arm32mm
* @{
*/
/** @file
36,8 → 36,8
#ifndef KERN_arm32_FRAME_H_
#define KERN_arm32_FRAME_H_
 
#define FRAME_WIDTH 12 /* 4KB frames */
#define FRAME_SIZE (1 << FRAME_WIDTH)
#define FRAME_WIDTH 12 /* 4KB frames */
#define FRAME_SIZE (1 << FRAME_WIDTH)
 
#ifdef KERNEL
#ifndef __ASM__
44,8 → 44,8
 
#include <arch/types.h>
 
#define BOOT_PAGE_TABLE_SIZE 0x4000
#define BOOT_PAGE_TABLE_ADDRESS 0x4000
#define BOOT_PAGE_TABLE_SIZE 0x4000
#define BOOT_PAGE_TABLE_ADDRESS 0x4000
 
#define BOOT_PAGE_TABLE_START_FRAME (BOOT_PAGE_TABLE_ADDRESS >> FRAME_WIDTH)
#define BOOT_PAGE_TABLE_SIZE_IN_FRAMES (BOOT_PAGE_TABLE_SIZE >> FRAME_WIDTH)
/branches/dd/kernel/arch/arm32/include/mm/page.h
43,8 → 43,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifndef __ASM__
# define KA2PA(x) (((uintptr_t) (x)) - 0x80000000)
# define PA2KA(x) (((uintptr_t) (x)) + 0x80000000)
195,9 → 193,8
static inline void set_ptl0_addr(pte_level0_t *pt)
{
asm volatile (
"mcr p15, 0, %0, c2, c0, 0 \n"
:
: "r"(pt)
"mcr p15, 0, %[pt], c2, c0, 0\n"
:: [pt] "r" (pt)
);
}
 
/branches/dd/kernel/arch/arm32/include/mm/tlb.h
36,9 → 36,6
#ifndef KERN_arm32_TLB_H_
#define KERN_arm32_TLB_H_
 
#define tlb_arch_init()
#define tlb_print()
 
#endif
 
/** @}
/branches/dd/kernel/arch/arm32/include/barrier.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup arm32
/** @addtogroup arm32
* @{
*/
/** @file
39,13 → 39,16
/*
* TODO: implement true ARM memory barriers for macros below.
*/
#define CS_ENTER_BARRIER() asm volatile ("" ::: "memory")
#define CS_LEAVE_BARRIER() asm volatile ("" ::: "memory")
#define CS_ENTER_BARRIER() asm volatile ("" ::: "memory")
#define CS_LEAVE_BARRIER() asm volatile ("" ::: "memory")
 
#define memory_barrier() asm volatile ("" ::: "memory")
#define read_barrier() asm volatile ("" ::: "memory")
#define write_barrier() asm volatile ("" ::: "memory")
#define memory_barrier() asm volatile ("" ::: "memory")
#define read_barrier() asm volatile ("" ::: "memory")
#define write_barrier() asm volatile ("" ::: "memory")
 
#define smc_coherence(a)
#define smc_coherence_block(a, l)
 
#endif
 
/** @}
/branches/dd/kernel/arch/arm32/Makefile.inc
33,64 → 33,31
BFD_ARCH = arm
BFD = binary
TARGET = arm-linux-gnu
TOOLCHAIN_DIR = /usr/local/arm
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm
 
KERNEL_LOAD_ADDRESS = 0x80200000
 
ifeq ($(MACHINE), gxemul_testarm)
DMACHINE = MACHINE_GXEMUL_TESTARM
endif
 
ATSIGN = %
 
GCC_CFLAGS += -fno-zero-initialized-in-bss
 
DEFS += -D__32_BITS__ -DKERNEL_LOAD_ADDRESS=$(KERNEL_LOAD_ADDRESS) -D$(DMACHINE)
DEFS += -D__32_BITS__
 
# Compile with framebuffer support
 
ifeq ($(CONFIG_FB), y)
DEFS += -DCONFIG_FB -DFB_INVERT_ENDIAN
endif
 
## Compile with hierarchical page tables support.
#
 
CONFIG_PAGE_PT = y
DEFS += -DCONFIG_PAGE_PT
 
## Compile with support for address space identifiers.
#
# no HW support for ASIDs
#CONFIG_ASID = y
#CONFIG_ASID_FIFO = y
 
## Compile with support with software division and multiplication.
#
 
CONFIG_SOFTINT = y
 
ARCH_SOURCES = \
arch/$(ARCH)/src/start.S \
arch/$(ARCH)/src/asm.S \
arch/$(ARCH)/src/arm32.c \
arch/$(ARCH)/src/context.S \
arch/$(ARCH)/src/dummy.S \
arch/$(ARCH)/src/panic.S \
arch/$(ARCH)/src/cpu/cpu.c \
arch/$(ARCH)/src/ddi/ddi.c \
arch/$(ARCH)/src/interrupt.c \
arch/$(ARCH)/src/debug/print.c \
arch/$(ARCH)/src/console.c \
arch/$(ARCH)/src/exception.c \
arch/$(ARCH)/src/userspace.c \
arch/$(ARCH)/src/mm/as.c \
arch/$(ARCH)/src/mm/frame.c \
arch/$(ARCH)/src/mm/page.c \
arch/$(ARCH)/src/mm/tlb.c \
arch/$(ARCH)/src/mm/page_fault.c
 
ifeq ($(MACHINE), gxemul_testarm)
ARCH_SOURCES += arch/$(ARCH)/src/drivers/gxemul.c
endif
 
arch/$(KARCH)/src/start.S \
arch/$(KARCH)/src/asm.S \
arch/$(KARCH)/src/arm32.c \
arch/$(KARCH)/src/context.S \
arch/$(KARCH)/src/dummy.S \
arch/$(KARCH)/src/panic.S \
arch/$(KARCH)/src/cpu/cpu.c \
arch/$(KARCH)/src/ddi/ddi.c \
arch/$(KARCH)/src/interrupt.c \
arch/$(KARCH)/src/debug/print.c \
arch/$(KARCH)/src/console.c \
arch/$(KARCH)/src/exception.c \
arch/$(KARCH)/src/userspace.c \
arch/$(KARCH)/src/mm/as.c \
arch/$(KARCH)/src/mm/frame.c \
arch/$(KARCH)/src/mm/page.c \
arch/$(KARCH)/src/mm/tlb.c \
arch/$(KARCH)/src/mm/page_fault.c \
arch/$(KARCH)/src/drivers/gxemul.c
/branches/dd/kernel/arch/arm32/src/exception.c
40,6 → 40,7
#include <interrupt.h>
#include <arch/machine.h>
#include <arch/mm/page_fault.h>
#include <arch/barrier.h>
#include <print.h>
#include <syscall/syscall.h>
 
62,57 → 63,60
*
* Temporary exception stack is used to save a few registers
* before stack switch takes place.
*
*/
inline static void setup_stack_and_save_regs()
{
asm volatile(
"ldr r13, =exc_stack \n"
"stmfd r13!, {r0} \n"
"mrs r0, spsr \n"
"and r0, r0, #0x1f \n"
"cmp r0, #0x10 \n"
"bne 1f \n"
 
asm volatile (
"ldr r13, =exc_stack\n"
"stmfd r13!, {r0}\n"
"mrs r0, spsr\n"
"and r0, r0, #0x1f\n"
"cmp r0, #0x10\n"
"bne 1f\n"
/* prev mode was usermode */
"ldmfd r13!, {r0} \n"
"ldr r13, =supervisor_sp \n"
"ldr r13, [r13] \n"
"stmfd r13!, {lr} \n"
"stmfd r13!, {r0-r12} \n"
"stmfd r13!, {r13, lr}^ \n"
"mrs r0, spsr \n"
"stmfd r13!, {r0} \n"
"b 2f \n"
 
"ldmfd r13!, {r0}\n"
"ldr r13, =supervisor_sp\n"
"ldr r13, [r13]\n"
"stmfd r13!, {lr}\n"
"stmfd r13!, {r0-r12}\n"
"stmfd r13!, {r13, lr}^\n"
"mrs r0, spsr\n"
"stmfd r13!, {r0}\n"
"b 2f\n"
/* mode was not usermode */
"1:\n"
"stmfd r13!, {r1, r2, r3} \n"
"mrs r1, cpsr \n"
"mov r2, lr \n"
"bic r1, r1, #0x1f \n"
"orr r1, r1, r0 \n"
"mrs r0, cpsr \n"
"msr cpsr_c, r1 \n"
 
"mov r3, r13 \n"
"stmfd r13!, {r2} \n"
"mov r2, lr \n"
"stmfd r13!, {r4-r12} \n"
"mov r1, r13 \n"
/* the following two lines are for debugging */
"mov sp, #0 \n"
"mov lr, #0 \n"
"msr cpsr_c, r0 \n"
 
"ldmfd r13!, {r4, r5, r6, r7} \n"
"stmfd r1!, {r4, r5, r6} \n"
"stmfd r1!, {r7} \n"
"stmfd r1!, {r2} \n"
"stmfd r1!, {r3} \n"
"mrs r0, spsr \n"
"stmfd r1!, {r0} \n"
"mov r13, r1 \n"
"2:\n"
"1:\n"
"stmfd r13!, {r1, r2, r3}\n"
"mrs r1, cpsr\n"
"mov r2, lr\n"
"bic r1, r1, #0x1f\n"
"orr r1, r1, r0\n"
"mrs r0, cpsr\n"
"msr cpsr_c, r1\n"
"mov r3, r13\n"
"stmfd r13!, {r2}\n"
"mov r2, lr\n"
"stmfd r13!, {r4-r12}\n"
"mov r1, r13\n"
/* the following two lines are for debugging */
"mov sp, #0\n"
"mov lr, #0\n"
"msr cpsr_c, r0\n"
"ldmfd r13!, {r4, r5, r6, r7}\n"
"stmfd r1!, {r4, r5, r6}\n"
"stmfd r1!, {r7}\n"
"stmfd r1!, {r2}\n"
"stmfd r1!, {r3}\n"
"mrs r0, spsr\n"
"stmfd r1!, {r0}\n"
"mov r13, r1\n"
"2:\n"
);
}
 
188,10 → 192,13
}
 
/** Calls exception dispatch routine. */
#define CALL_EXC_DISPATCH(exception) \
asm("mov r0, %0" : : "i" (exception)); \
asm("mov r1, r13"); \
asm("bl exc_dispatch");
#define CALL_EXC_DISPATCH(exception) \
asm volatile ( \
"mov r0, %[exc]\n" \
"mov r1, r13\n" \
"bl exc_dispatch\n" \
:: [exc] "i" (exception) \
);\
 
/** General exception handler.
*
200,9 → 207,9
*
* @param exception Exception number.
*/
#define PROCESS_EXCEPTION(exception) \
setup_stack_and_save_regs(); \
CALL_EXC_DISPATCH(exception) \
#define PROCESS_EXCEPTION(exception) \
setup_stack_and_save_regs(); \
CALL_EXC_DISPATCH(exception) \
load_regs();
 
/** Updates specified exception vector to jump to given handler.
209,7 → 216,7
*
* Addresses of handlers are stored in memory following exception vectors.
*/
static void install_handler (unsigned handler_addr, unsigned* vector)
static void install_handler(unsigned handler_addr, unsigned *vector)
{
/* relative address (related to exc. vector) of the word
* where handler's address is stored
219,6 → 226,7
/* make it LDR instruction and store at exception vector */
*vector = handler_address_ptr | LDR_OPCODE;
smc_coherence(*vector);
/* store handler's address */
*(vector + EXC_VECTORS) = handler_addr;
226,31 → 234,31
}
 
/** Low-level Reset Exception handler. */
static void reset_exception_entry()
static void reset_exception_entry(void)
{
PROCESS_EXCEPTION(EXC_RESET);
}
 
/** Low-level Software Interrupt Exception handler. */
static void swi_exception_entry()
static void swi_exception_entry(void)
{
PROCESS_EXCEPTION(EXC_SWI);
}
 
/** Low-level Undefined Instruction Exception handler. */
static void undef_instr_exception_entry()
static void undef_instr_exception_entry(void)
{
PROCESS_EXCEPTION(EXC_UNDEF_INSTR);
}
 
/** Low-level Fast Interrupt Exception handler. */
static void fiq_exception_entry()
static void fiq_exception_entry(void)
{
PROCESS_EXCEPTION(EXC_FIQ);
}
 
/** Low-level Prefetch Abort Exception handler. */
static void prefetch_abort_exception_entry()
static void prefetch_abort_exception_entry(void)
{
asm("sub lr, lr, #4");
PROCESS_EXCEPTION(EXC_PREFETCH_ABORT);
257,7 → 265,7
}
 
/** Low-level Data Abort Exception handler. */
static void data_abort_exception_entry()
static void data_abort_exception_entry(void)
{
asm("sub lr, lr, #8");
PROCESS_EXCEPTION(EXC_DATA_ABORT);
269,7 → 277,7
* because of possible occurence of nested interrupt exception, which
* would overwrite (and thus spoil) stack pointer.
*/
static void irq_exception_entry()
static void irq_exception_entry(void)
{
asm("sub lr, lr, #4");
setup_stack_and_save_regs();
331,17 → 339,23
{
uint32_t control_reg;
asm volatile("mrc p15, 0, %0, c1, c1" : "=r" (control_reg));
asm volatile (
"mrc p15, 0, %[control_reg], c1, c1"
: [control_reg] "=r" (control_reg)
);
/* switch on the high vectors bit */
control_reg |= CP15_R1_HIGH_VECTORS_BIT;
asm volatile("mcr p15, 0, %0, c1, c1" : : "r" (control_reg));
asm volatile (
"mcr p15, 0, %[control_reg], c1, c1"
:: [control_reg] "r" (control_reg)
);
}
#endif
 
/** Initializes exception handling.
*
*
* Installs low-level exception handlers and then registers
* exceptions and their handlers to kernel exception dispatcher.
*/
/branches/dd/kernel/arch/arm32/src/asm.S
45,7 → 45,8
add r3, r1, #3
bic r3, r3, #3
cmp r1, r3
stmdb sp!, {r4, lr}
stmdb sp!, {r4, r5, lr}
mov r5, r0 /* save dst */
beq 4f
1:
cmp r2, #0
58,8 → 59,8
cmp ip, r2
bne 2b
3:
mov r0, r1
ldmia sp!, {r4, pc}
mov r0, r5
ldmia sp!, {r4, r5, pc}
4:
add r3, r0, #3
bic r3, r3, #3
94,5 → 95,5
 
memcpy_from_uspace_failover_address:
memcpy_to_uspace_failover_address:
mov r0, #0
ldmia sp!, {r4, pc}
mov r0, #0
ldmia sp!, {r4, r5, pc}
/branches/dd/kernel/arch/arm32/src/console.c
37,21 → 37,19
#include <arch/console.h>
#include <arch/machine.h>
 
void console_init(devno_t devno)
{
machine_console_init(devno);
}
#include <genarch/fb/fb.h>
 
/** Acquire console back for kernel. */
void arch_grab_console(void)
{
machine_grab_console();
#ifdef CONFIG_FB
fb_redraw();
#endif
}
 
/** Return console to userspace. */
void arch_release_console(void)
{
machine_release_console();
}
 
/** @}
/branches/dd/kernel/arch/arm32/src/arm32.c
34,7 → 34,6
*/
 
#include <arch.h>
#include <arch/boot.h>
#include <config.h>
#include <arch/console.h>
#include <ddi/device.h>
48,22 → 47,22
#include <arch/regutils.h>
#include <arch/machine.h>
#include <userspace.h>
#include <macros.h>
#include <string.h>
 
/** Information about loaded tasks. */
bootinfo_t bootinfo;
 
/** Performs arm32 specific initialization before main_bsp() is called. */
void arch_pre_main(void)
/** Performs arm32-specific initialization before main_bsp() is called. */
void arch_pre_main(void *entry __attribute__((unused)), bootinfo_t *bootinfo)
{
unsigned int i;
 
init.cnt = bootinfo.cnt;
 
for (i = 0; i < bootinfo.cnt; ++i) {
init.tasks[i].addr = bootinfo.tasks[i].addr;
init.tasks[i].size = bootinfo.tasks[i].size;
init.cnt = bootinfo->cnt;
for (i = 0; i < min3(bootinfo->cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS); ++i) {
init.tasks[i].addr = bootinfo->tasks[i].addr;
init.tasks[i].size = bootinfo->tasks[i].size;
strncpy(init.tasks[i].name, bootinfo->tasks[i].name,
CONFIG_TASK_NAME_BUFLEN);
}
}
 
/** Performs arm32 specific initialization before mm is initialized. */
83,10 → 82,18
 
interrupt_init();
console_init(device_assign_devno());
machine_console_init(device_assign_devno());
 
#ifdef CONFIG_FB
fb_init(machine_get_fb_address(), 640, 480, 1920, VISUAL_RGB_8_8_8);
fb_properties_t prop = {
.addr = machine_get_fb_address(),
.offset = 0,
.x = 640,
.y = 480,
.scan = 1920,
.visual = VISUAL_BGR_8_8_8,
};
fb_init(&prop);
#endif
}
 
156,9 → 163,22
void arch_reboot()
{
/* not implemented */
for (;;)
;
while (1);
}
 
/** Construct function pointer
*
* @param fptr function pointer structure
* @param addr function address
* @param caller calling function address
*
* @return address of the function pointer
*
*/
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
{
return addr;
}
 
/** @}
*/
/branches/dd/kernel/arch/arm32/src/cpu/cpu.c
36,7 → 36,7
#include <arch/cpu.h>
#include <cpu.h>
#include <arch.h>
#include <print.h>
#include <print.h>
 
/** Number of indexes left out in the #imp_data array */
#define IMP_DATA_START_OFFSET 0x40
82,10 → 82,10
{
uint32_t ident;
asm volatile (
"mrc p15, 0, %0, c0, c0, 0\n"
: "=r" (ident)
"mrc p15, 0, %[ident], c0, c0, 0\n"
: [ident] "=r" (ident)
);
 
cpu->imp_num = ident >> 24;
cpu->variant_num = (ident << 8) >> 28;
cpu->arch_num = (ident << 12) >> 28;
/branches/dd/kernel/arch/arm32/src/mm/tlb.c
48,7 → 48,7
asm volatile (
"eor r1, r1\n"
"mcr p15, 0, r1, c8, c7, 0\n"
: : : "r1"
::: "r1"
);
}
 
68,9 → 68,8
static inline void invalidate_page(uintptr_t page)
{
asm volatile (
"mcr p15, 0, %0, c8, c7, 1"
:
: "r" (page)
"mcr p15, 0, %[page], c8, c7, 1\n"
:: [page] "r" (page)
);
}
 
81,7 → 80,7
* @param page Address of the first page whose entry is to be invalidated.
* @param cnt Number of entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
void tlb_invalidate_pages(asid_t asid __attribute__((unused)), uintptr_t page, count_t cnt)
{
unsigned int i;
 
89,5 → 88,13
invalidate_page(page + i * PAGE_SIZE);
}
 
void tlb_arch_init(void)
{
}
 
void tlb_print(void)
{
}
 
/** @}
*/
/branches/dd/kernel/arch/arm32/src/mm/page_fault.c
40,6 → 40,7
#include <genarch/mm/page_pt.h>
#include <arch.h>
#include <interrupt.h>
#include <print.h>
 
/** Returns value stored in fault status register.
*
48,12 → 49,13
static inline fault_status_t read_fault_status_register(void)
{
fault_status_union_t fsu;
 
/* fault status is stored in CP15 register 5 */
asm volatile (
"mrc p15, 0, %0, c5, c0, 0"
: "=r"(fsu.dummy)
"mrc p15, 0, %[dummy], c5, c0, 0"
: [dummy] "=r" (fsu.dummy)
);
return fsu.fs;
}
 
60,17 → 62,18
/** Returns FAR (fault address register) content.
*
* @return FAR (fault address register) content (address that caused a page
* fault)
* fault)
*/
static inline uintptr_t read_fault_address_register(void)
{
uintptr_t ret;
 
/* fault adress is stored in CP15 register 6 */
asm volatile (
"mrc p15, 0, %0, c6, c0, 0"
: "=r"(ret)
"mrc p15, 0, %[ret], c6, c0, 0"
: [ret] "=r" (ret)
);
return ret;
}
 
79,29 → 82,26
* @param instr Instruction
*
* @return true when instruction is load/store, false otherwise
*
*/
static inline bool is_load_store_instruction(instruction_t instr)
{
/* load store immediate offset */
if (instr.type == 0x2) {
if (instr.type == 0x2)
return true;
}
 
/* load store register offset */
if (instr.type == 0x3 && instr.bit4 == 0) {
if ((instr.type == 0x3) && (instr.bit4 == 0))
return true;
}
 
/* load store multiple */
if (instr.type == 0x4) {
if (instr.type == 0x4)
return true;
}
 
/* oprocessor load/store */
if (instr.type == 0x6) {
if (instr.type == 0x6)
return true;
}
 
return false;
}
 
114,12 → 114,11
static inline bool is_swap_instruction(instruction_t instr)
{
/* swap, swapb instruction */
if (instr.type == 0x0 &&
(instr.opcode == 0x8 || instr.opcode == 0xa) &&
instr.access == 0x0 && instr.bits567 == 0x4 && instr.bit4 == 1) {
if ((instr.type == 0x0) &&
((instr.opcode == 0x8) || (instr.opcode == 0xa)) &&
(instr.access == 0x0) && (instr.bits567 == 0x4) && (instr.bit4 == 1))
return true;
}
 
return false;
}
 
141,8 → 140,8
 
/* undefined instructions */
if (instr.condition == 0xf) {
panic("page_fault - instruction doesn't access memory "
"(instr_code: %x, badvaddr:%x)", instr, badvaddr);
panic("page_fault - instruction does not access memory "
"(instr_code: %x, badvaddr:%x).", instr, badvaddr);
return PF_ACCESS_EXEC;
}
 
161,7 → 160,7
}
 
panic("page_fault - instruction doesn't access memory "
"(instr_code: %x, badvaddr:%x)", instr, badvaddr);
"(instr_code: %x, badvaddr:%x).", instr, badvaddr);
 
return PF_ACCESS_EXEC;
}
187,8 → 186,8
"access:%d\n", istate->pc, badvaddr, fsr.status, fsr,
access);
 
fault_if_from_uspace(istate, "Page fault: %#x", badvaddr);
panic("page fault\n");
fault_if_from_uspace(istate, "Page fault: %#x.", badvaddr);
panic("Page fault.");
}
}
 
204,7 → 203,7
if (ret == AS_PF_FAULT) {
dprintf("prefetch_abort\n");
print_istate(istate);
panic("page fault - prefetch_abort at address: %x\n",
panic("page fault - prefetch_abort at address: %x.",
istate->pc);
}
}
/branches/dd/kernel/arch/arm32/src/mm/frame.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup arm32mm
/** @addtogroup arm32mm
* @{
*/
/** @file
49,7 → 49,7
zone_create(0, ADDR2PFN(machine_get_memory_size()),
BOOT_PAGE_TABLE_START_FRAME + BOOT_PAGE_TABLE_SIZE_IN_FRAMES, 0);
last_frame = machine_get_memory_size();
 
/* blacklist boot page table */
frame_mark_unavailable(BOOT_PAGE_TABLE_START_FRAME,
BOOT_PAGE_TABLE_SIZE_IN_FRAMES);
/branches/dd/kernel/arch/arm32/src/mm/page.c
90,7 → 90,7
{
if (last_frame + ALIGN_UP(size, PAGE_SIZE) >
KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) {
panic("Unable to map physical memory %p (%d bytes)",
panic("Unable to map physical memory %p (%d bytes).",
physaddr, size)
}
 
/branches/dd/kernel/arch/arm32/src/userspace.c
70,8 → 70,11
/* set first parameter */
ustate.r0 = (uintptr_t) kernel_uarg->uspace_uarg;
 
/* %r1 is defined to hold pcb_ptr - set it to 0 */
ustate.r1 = 0;
 
/* clear other registers */
ustate.r1 = ustate.r2 = ustate.r3 = ustate.r4 = ustate.r5 =
ustate.r2 = ustate.r3 = ustate.r4 = ustate.r5 =
ustate.r6 = ustate.r7 = ustate.r8 = ustate.r9 = ustate.r10 =
ustate.r11 = ustate.r12 = ustate.lr = 0;
 
87,12 → 90,11
 
/* set user mode, set registers, jump */
asm volatile (
"mov sp, %0 \n"
"msr spsr_c, %1 \n"
"ldmfd sp!, {r0-r12, sp, lr}^ \n"
"mov sp, %[ustate]\n"
"msr spsr_c, %[user_mode]\n"
"ldmfd sp!, {r0-r12, sp, lr}^\n"
"ldmfd sp!, {pc}^\n"
:
: "r" (&ustate), "r" (user_mode)
:: [ustate] "r" (&ustate), [user_mode] "r" (user_mode)
);
 
/* unreachable */
/branches/dd/kernel/arch/arm32/src/drivers/gxemul.c
34,7 → 34,6
*/
 
#include <interrupt.h>
#include <ipc/irq.h>
#include <console/chardev.h>
#include <arch/drivers/gxemul.h>
#include <console/console.h>
72,7 → 71,7
 
static void gxemul_kbd_enable(chardev_t *dev);
static void gxemul_kbd_disable(chardev_t *dev);
static void gxemul_write(chardev_t *dev, const char ch);
static void gxemul_write(chardev_t *dev, const char ch, bool silent);
static char gxemul_do_read(chardev_t *dev);
 
static chardev_operations_t gxemul_ops = {
133,9 → 132,10
* @param dev Not used.
* @param ch Characted to be printed.
*/
static void gxemul_write(chardev_t *dev, const char ch)
static void gxemul_write(chardev_t *dev, const char ch, bool silent)
{
*((char *) gxemul_hw_map.videoram) = ch;
if (!silent)
*((char *) gxemul_hw_map.videoram) = ch;
}
 
/** Enables gxemul keyboard (interrupt unmasked).
183,54 → 183,26
/** Process keyboard interrupt.
*
* @param irq IRQ information.
* @param arg Not used.
*/
static void gxemul_irq_handler(irq_t *irq, void *arg, ...)
static void gxemul_irq_handler(irq_t *irq)
{
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) {
ipc_irq_send_notif(irq);
} else {
char ch = 0;
char ch = 0;
ch = *((char *) gxemul_hw_map.kbd);
if (ch == '\r') {
ch = '\n';
}
if (ch == 0x7f) {
ch = '\b';
}
chardev_push_character(&console, ch);
ch = *((char *) gxemul_hw_map.kbd);
if (ch == '\r') {
ch = '\n';
}
if (ch == 0x7f) {
ch = '\b';
}
chardev_push_character(&console, ch);
}
 
static irq_ownership_t gxemul_claim(void)
static irq_ownership_t gxemul_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
 
/** Acquire console back for kernel. */
void gxemul_grab_console(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&gxemul_console_irq.lock);
gxemul_console_irq.notif_cfg.notify = false;
spinlock_unlock(&gxemul_console_irq.lock);
interrupts_restore(ipl);
}
 
/** Return console to userspace. */
void gxemul_release_console(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&gxemul_console_irq.lock);
if (gxemul_console_irq.notif_cfg.answerbox) {
gxemul_console_irq.notif_cfg.notify = true;
}
spinlock_unlock(&gxemul_console_irq.lock);
interrupts_restore(ipl);
}
 
/** Initializes console object representing gxemul console.
*
* @param devno device number.
265,7 → 237,7
*((uint32_t*) gxemul_hw_map.rtc_freq) = frequency;
}
 
static irq_ownership_t gxemul_timer_claim(void)
static irq_ownership_t gxemul_timer_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
275,7 → 247,7
* @param irq Interrupt information.
* @param arg Not used.
*/
static void gxemul_timer_irq_handler(irq_t *irq, void *arg, ...)
static void gxemul_timer_irq_handler(irq_t *irq)
{
/*
* We are holding a lock which prevents preemption.
369,7 → 341,7
irq_t *irq = irq_dispatch_and_lock(i);
if (irq) {
/* The IRQ handler was found. */
irq->handler(irq, irq->arg);
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
/* Spurious interrupt.*/
/branches/dd/kernel/arch/arm32/src/start.S
40,30 → 40,12
mrs r3, cpsr
bic r3, r3, #0x1f
orr r3, r3, #0x13
msr cpsr_c, r3
msr cpsr_c, r3
ldr sp, =temp_stack
 
cmp r2, #0
beq bootinfo_end
 
ldr r3, =bootinfo
 
bootinfo_loop:
ldr r4, [r1]
str r4, [r3]
 
add r1, r1, #4
add r3, r3, #4
add r2, r2, #-4
 
cmp r2, #0
bne bootinfo_loop
bootinfo_end:
 
bl arch_pre_main
 
bl main_bsp
 
.space TEMP_STACK_SIZE
74,4 → 56,3
 
supervisor_sp:
.space 4
 
/branches/dd/kernel/arch/ppc32/_link.ld.in
1,11 → 1,11
/** PPC32 linker script
*
* umapped section:
* kernel text
* kernel data
* kernel text
* kernel data
* mapped section:
* kernel text
* kernel data
* kernel text
* kernel data
*
*/
 
27,7 → 27,7
unmapped_kdata_start = .;
}
.mapped PA2KA(BOOT_OFFSET): AT (BOOT_OFFSET) {
.mapped PA2KA(BOOT_OFFSET): AT (BOOT_OFFSET) {
ktext_start = .;
*(K_TEXT_START);
*(.text);
37,22 → 37,22
*(K_DATA_START);
*(.rodata);
*(.rodata.*);
*(.data); /* initialized data */
*(.data); /* initialized data */
*(.sdata);
*(.sdata2);
*(.sbss);
hardcoded_ktext_size = .;
LONG(ktext_end - ktext_start);
LONG(ktext_end - ktext_start);
hardcoded_kdata_size = .;
LONG(kdata_end - kdata_start);
hardcoded_load_address = .;
LONG(PA2KA(BOOT_OFFSET));
*(.bss); /* uninitialized static variables */
*(COMMON); /* global variables */
 
*(.bss); /* uninitialized static variables */
*(COMMON); /* global variables */
symbol_table = .;
*(symtab.*); /* Symbol table, must be LAST symbol!*/
 
*(symtab.*); /* Symbol table, must be LAST symbol!*/
kdata_end = .;
}
}
/branches/dd/kernel/arch/ppc32/include/asm/regname.h
211,15 → 211,19
#define dbat2l 541
#define dbat3u 542
#define dbat3l 543
#define tlbmiss 980
#define ptehi 981
#define ptelo 982
#define hid0 1008
 
/* MSR bits */
#define msr_ir (1 << 4)
#define msr_dr (1 << 5)
#define msr_dr (1 << 4)
#define msr_ir (1 << 5)
#define msr_pr (1 << 14)
#define msr_ee (1 << 15)
 
/* HID0 bits */
#define hid0_sten (1 << 24)
#define hid0_ice (1 << 15)
#define hid0_dce (1 << 14)
#define hid0_icfi (1 << 11)
/branches/dd/kernel/arch/ppc32/include/exception.h
36,6 → 36,7
#define KERN_ppc32_EXCEPTION_H_
 
#include <arch/types.h>
#include <arch/regutils.h>
 
typedef struct {
uint32_t r0;
74,6 → 75,7
uint32_t lr;
uint32_t ctr;
uint32_t xer;
uint32_t dar;
uint32_t r12;
uint32_t sp;
} istate_t;
82,13 → 84,14
{
istate->pc = retaddr;
}
 
/** Return true if exception happened while in userspace */
#include <panic.h>
static inline int istate_from_uspace(istate_t *istate)
{
panic("istate_from_uspace not yet implemented");
return 0;
/* true if privilege level PR (copied from MSR) == 1 */
return (istate->srr1 & MSR_PR) != 0;
}
 
static inline unative_t istate_get_pc(istate_t *istate)
{
return istate->pc;
/branches/dd/kernel/arch/ppc32/include/regutils.h
0,0 → 1,45
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ppc32
* @{
*/
/**
* @file
* @brief Utilities for convenient manipulation with ppc32 registers.
*/
 
#ifndef KERN_ppc32_REGUTILS_H_
#define KERN_ppc32_REGUTILS_H_
 
#define MSR_PR (1 << 14)
 
#endif
 
/** @}
*/
/branches/dd/kernel/arch/ppc32/include/types.h
35,10 → 35,6
#ifndef KERN_ppc32_TYPES_H_
#define KERN_ppc32_TYPES_H_
 
#define NULL 0
#define false 0
#define true 1
 
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
61,21 → 57,43
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef uint8_t bool;
typedef uint64_t thread_id_t;
typedef uint64_t task_id_t;
typedef uint32_t context_id_t;
typedef struct {
} fncptr_t;
 
typedef int32_t inr_t;
typedef int32_t devno_t;
/**< Formats for uintptr_t, size_t, count_t and index_t */
#define PRIp "x"
#define PRIs "u"
#define PRIc "u"
#define PRIi "u"
 
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */
#define PRId8 "d"
#define PRId16 "d"
#define PRId32 "d"
#define PRId64 "lld"
#define PRIdn "d"
 
#define PRIu8 "u"
#define PRIu16 "u"
#define PRIu32 "u"
#define PRIu64 "llu"
#define PRIun "u"
 
#define PRIx8 "x"
#define PRIx16 "x"
#define PRIx32 "x"
#define PRIx64 "llx"
#define PRIxn "x"
 
/** Page Table Entry. */
typedef struct {
unsigned p : 1; /**< Present bit. */
unsigned a : 1; /**< Accessed bit. */
unsigned g : 1; /**< Global bit. */
unsigned valid : 1; /**< Valid content even if not present. */
unsigned pfn : 20; /**< Physical frame number. */
unsigned present : 1; /**< Present bit. */
unsigned page_write_through : 1; /**< Write thought caching. */
unsigned page_cache_disable : 1; /**< No caching. */
unsigned accessed : 1; /**< Accessed bit. */
unsigned global : 1; /**< Global bit. */
unsigned valid : 1; /**< Valid content even if not present. */
unsigned pfn : 20; /**< Physical frame number. */
} pte_t;
 
#endif
/branches/dd/kernel/arch/ppc32/include/memstr.h
37,10 → 37,10
 
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt))
 
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x);
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x);
extern void memsetw(void *dst, size_t cnt, uint16_t x);
extern void memsetb(void *dst, size_t cnt, uint8_t x);
 
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt);
extern int memcmp(const void *a, const void *b, size_t cnt);
 
#endif
 
/branches/dd/kernel/arch/ppc32/include/boot/boot.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ppc32
/** @addtogroup ppc32
* @{
*/
/** @file
35,21 → 35,24
#ifndef KERN_ppc32_BOOT_H_
#define KERN_ppc32_BOOT_H_
 
#define BOOT_OFFSET 0x8000
#define BOOT_OFFSET 0x8000
 
/* Temporary stack size for boot process */
#define TEMP_STACK_SIZE 0x100
#define TEMP_STACK_SIZE 0x1000
 
#define TASKMAP_MAX_RECORDS 32
#define MEMMAP_MAX_RECORDS 32
#define TASKMAP_MAX_RECORDS 32
#define MEMMAP_MAX_RECORDS 32
 
#ifndef __ASM__
 
#define BOOTINFO_TASK_NAME_BUFLEN 32
 
#include <arch/types.h>
 
typedef struct {
uintptr_t addr;
uint32_t size;
char name[BOOTINFO_TASK_NAME_BUFLEN];
} utask_t;
 
typedef struct {
79,13 → 82,13
typedef struct {
uintptr_t addr;
unsigned int size;
} keyboard_t;
} macio_t;
 
typedef struct {
memmap_t memmap;
taskmap_t taskmap;
screen_t screen;
keyboard_t keyboard;
macio_t macio;
} bootinfo_t;
 
extern bootinfo_t bootinfo;
/branches/dd/kernel/arch/ppc32/include/arch.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ppc32
/** @addtogroup ppc32
* @{
*/
/** @file
35,7 → 35,7
#ifndef KERN_ppc32_ARCH_H_
#define KERN_ppc32_ARCH_H_
 
#include <arch/drivers/cuda.h>
extern void arch_pre_main(void);
 
#endif
 
/branches/dd/kernel/arch/ppc32/include/asm.h
36,6 → 36,7
#define KERN_ppc32_ASM_H_
 
#include <arch/types.h>
#include <typedefs.h>
#include <config.h>
 
/** Enable interrupts.
149,6 → 150,36
 
extern void userspace_asm(uintptr_t uspace_uarg, uintptr_t stack, uintptr_t entry);
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
#endif
 
/** @}
/branches/dd/kernel/arch/ppc32/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ppc32mm
/** @addtogroup ppc32mm
* @{
*/
/** @file
35,13 → 35,13
#ifndef KERN_ppc32_FRAME_H_
#define KERN_ppc32_FRAME_H_
 
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
 
#ifdef KERNEL
#ifndef __ASM__
 
#include <arch/types.h>
#include <arch/types.h>
 
extern uintptr_t last_frame;
 
/branches/dd/kernel/arch/ppc32/include/mm/page.h
40,8 → 40,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifdef KERNEL
 
#ifndef __ASM__
122,7 → 120,7
 
/* Macros for querying the last-level PTEs. */
#define PTE_VALID_ARCH(pte) (*((uint32_t *) (pte)) != 0)
#define PTE_PRESENT_ARCH(pte) ((pte)->p != 0)
#define PTE_PRESENT_ARCH(pte) ((pte)->present != 0)
#define PTE_GET_FRAME_ARCH(pte) ((pte)->pfn << 12)
#define PTE_WRITABLE_ARCH(pte) 1
#define PTE_EXECUTABLE_ARCH(pte) 1
136,13 → 134,13
{
pte_t *p = &pt[i];
return ((1 << PAGE_CACHEABLE_SHIFT) |
((!p->p) << PAGE_PRESENT_SHIFT) |
return (((!p->page_cache_disable) << PAGE_CACHEABLE_SHIFT) |
((!p->present) << PAGE_PRESENT_SHIFT) |
(1 << PAGE_USER_SHIFT) |
(1 << PAGE_READ_SHIFT) |
(1 << PAGE_WRITE_SHIFT) |
(1 << PAGE_EXEC_SHIFT) |
(p->g << PAGE_GLOBAL_SHIFT));
(p->global << PAGE_GLOBAL_SHIFT));
}
 
static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
149,8 → 147,9
{
pte_t *p = &pt[i];
p->p = !(flags & PAGE_NOT_PRESENT);
p->g = (flags & PAGE_GLOBAL) != 0;
p->page_cache_disable = !(flags & PAGE_CACHEABLE);
p->present = !(flags & PAGE_NOT_PRESENT);
p->global = (flags & PAGE_GLOBAL) != 0;
p->valid = 1;
}
 
/branches/dd/kernel/arch/ppc32/include/mm/tlb.h
36,7 → 36,14
#define KERN_ppc32_TLB_H_
 
#include <arch/interrupt.h>
#include <arch/types.h>
#include <typedefs.h>
 
#define WIMG_GUARDED 0x01
#define WIMG_COHERENT 0x02
#define WIMG_NO_CACHE 0x04
#define WIMG_WRITETHRU 0x08
 
typedef struct {
unsigned v : 1; /**< Valid */
unsigned vsid : 24; /**< Virtual Segment ID */
51,9 → 58,27
unsigned pp : 2; /**< Page protection */
} phte_t;
 
typedef struct {
unsigned v : 1;
unsigned vsid : 24;
unsigned reserved0 : 1;
unsigned api : 6;
} ptehi_t;
 
typedef struct {
unsigned rpn : 20;
unsigned xpn : 3;
unsigned reserved0 : 1;
unsigned c : 1;
unsigned wimg : 4;
unsigned x : 1;
unsigned pp : 2;
} ptelo_t;
 
extern void pht_init(void);
extern void pht_refill(int n, istate_t *istate);
extern bool pht_real_refill(int n, istate_t *istate) __attribute__ ((section("K_UNMAPPED_TEXT_START")));
extern void pht_init(void);
extern bool pht_refill_real(int n, istate_t *istate) __attribute__ ((section("K_UNMAPPED_TEXT_START")));
extern void tlb_refill_real(int n, uint32_t tlbmiss, ptehi_t ptehi, ptelo_t ptelo, istate_t *istate) __attribute__ ((section("K_UNMAPPED_TEXT_START")));
 
#endif
 
/branches/dd/kernel/arch/ppc32/include/barrier.h
42,6 → 42,47
#define read_barrier() asm volatile ("sync" ::: "memory")
#define write_barrier() asm volatile ("eieio" ::: "memory")
 
/*
* The IMB sequence used here is valid for all possible cache models
* on uniprocessor. SMP might require a different sequence.
* See PowerPC Programming Environment for 32-Bit Microprocessors,
* chapter 5.1.5.2
*/
 
static inline void smc_coherence(void *addr)
{
asm volatile (
"dcbst 0, %0\n"
"sync\n"
"icbi 0, %0\n"
"sync\n"
"isync\n"
:: "r" (addr)
);
}
 
#define COHERENCE_INVAL_MIN 4
 
static inline void smc_coherence_block(void *addr, unsigned long len)
{
unsigned long i;
 
for (i = 0; i < len; i += COHERENCE_INVAL_MIN) {
asm volatile ("dcbst 0, %0\n" :: "r" (addr + i));
}
 
asm volatile ("sync");
 
for (i = 0; i < len; i += COHERENCE_INVAL_MIN) {
asm volatile ("icbi 0, %0\n" :: "r" (addr + i));
}
 
asm volatile (
"sync\n"
"isync\n"
);
}
 
#endif
 
/** @}
/branches/dd/kernel/arch/ppc32/include/drivers/cuda.h
36,11 → 36,10
#define KERN_ppc32_CUDA_H_
 
#include <arch/types.h>
#include <typedefs.h>
 
extern void cuda_init(devno_t devno, uintptr_t base, size_t size);
extern int cuda_get_scancode(void);
extern void cuda_grab(void);
extern void cuda_release(void);
 
#endif
 
/branches/dd/kernel/arch/ppc32/Makefile.inc
33,7 → 33,7
BFD_ARCH = powerpc:common
BFD = binary
TARGET = ppc-linux-gnu
TOOLCHAIN_DIR = /usr/local/ppc
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc
 
GCC_CFLAGS += -mcpu=powerpc -msoft-float -m32
AFLAGS += -a32
41,44 → 41,22
 
DEFS += -D__32_BITS__
 
## Own configuration directives
#
 
CONFIG_FB = y
 
## Compile with hierarchical page tables support.
#
 
CONFIG_PAGE_PT = y
DEFS += -DCONFIG_PAGE_PT
 
## Compile with support for address space identifiers.
#
 
CONFIG_ASID = y
CONFIG_ASID_FIFO = y
 
## Compile with support for software integer division.
#
 
CONFIG_SOFTINT = y
 
ARCH_SOURCES = \
arch/$(ARCH)/src/context.S \
arch/$(ARCH)/src/debug/panic.s \
arch/$(ARCH)/src/fpu_context.S \
arch/$(ARCH)/src/boot/boot.S \
arch/$(ARCH)/src/ppc32.c \
arch/$(ARCH)/src/dummy.s \
arch/$(ARCH)/src/exception.S \
arch/$(ARCH)/src/interrupt.c \
arch/$(ARCH)/src/asm.S \
arch/$(ARCH)/src/cpu/cpu.c \
arch/$(ARCH)/src/proc/scheduler.c \
arch/$(ARCH)/src/ddi/ddi.c \
arch/$(ARCH)/src/drivers/cuda.c \
arch/$(ARCH)/src/mm/as.c \
arch/$(ARCH)/src/mm/frame.c \
arch/$(ARCH)/src/mm/page.c \
arch/$(ARCH)/src/mm/tlb.c \
arch/$(ARCH)/src/drivers/pic.c
arch/$(KARCH)/src/context.S \
arch/$(KARCH)/src/debug/panic.s \
arch/$(KARCH)/src/fpu_context.S \
arch/$(KARCH)/src/boot/boot.S \
arch/$(KARCH)/src/ppc32.c \
arch/$(KARCH)/src/dummy.s \
arch/$(KARCH)/src/exception.S \
arch/$(KARCH)/src/interrupt.c \
arch/$(KARCH)/src/asm.S \
arch/$(KARCH)/src/cpu/cpu.c \
arch/$(KARCH)/src/proc/scheduler.c \
arch/$(KARCH)/src/ddi/ddi.c \
arch/$(KARCH)/src/drivers/cuda.c \
arch/$(KARCH)/src/mm/as.c \
arch/$(KARCH)/src/mm/frame.c \
arch/$(KARCH)/src/mm/page.c \
arch/$(KARCH)/src/mm/tlb.c \
arch/$(KARCH)/src/drivers/pic.c
/branches/dd/kernel/arch/ppc32/src/exception.S
60,7 → 60,7
2:
subi sp, sp, 160
subi sp, sp, 164
stw r0, 8(sp)
stw r2, 12(sp)
stw r3, 16(sp)
109,11 → 109,14
mfxer r12
stw r12, 148(sp)
mfsprg1 r12
mfdar r12
stw r12, 152(sp)
mfsprg1 r12
stw r12, 156(sp)
mfsprg2 r12
stw r12, 156(sp)
stw r12, 160(sp)
.endm
 
.org 0x100
137,16 → 140,7
exc_data_storage:
CONTEXT_STORE
li r3, 2
mr r4, sp
addi r4, r4, 8
bl pht_real_refill
cmpwi r3, 0
bne iret_real
li r3, 2
b jump_to_kernel
b data_storage
 
.org 0x400
.global exc_instruction_storage
153,17 → 147,8
exc_instruction_storage:
CONTEXT_STORE
li r3, 3
mr r4, sp
addi r4, r4, 8
bl pht_real_refill
cmpwi r3, 0
bne iret_real
b instruction_storage
 
li r3, 3
b jump_to_kernel
 
.org 0x500
.global exc_external
exc_external:
223,7 → 208,7
.org 0xc00
.global exc_syscall
exc_syscall:
CONTEXT_STORE
CONTEXT_STORE
b jump_to_kernel_syscall
 
235,7 → 220,63
li r3, 12
b jump_to_kernel
 
.org 0x1000
.global exc_itlb_miss
exc_itlb_miss:
CONTEXT_STORE
b tlb_miss
 
.org 0x1100
.global exc_dtlb_miss_load
exc_dtlb_miss_load:
CONTEXT_STORE
b tlb_miss
 
.org 0x1200
.global exc_dtlb_miss_store
exc_dtlb_miss_store:
CONTEXT_STORE
b tlb_miss
 
.org 0x4000
data_storage:
li r3, 2
mr r4, sp
addi r4, r4, 8
bl pht_refill_real
cmpwi r3, 0
bne iret_real
li r3, 2
b jump_to_kernel
 
instruction_storage:
li r3, 3
mr r4, sp
addi r4, r4, 8
bl pht_refill_real
cmpwi r3, 0
bne iret_real
li r3, 3
b jump_to_kernel
 
tlb_miss:
li r3, 16
mfspr r4, tlbmiss
mfspr r5, ptehi
mfspr r6, ptelo
mr r7, sp
addi r7, r7, 20
bl tlb_refill_real
b iret_real
 
jump_to_kernel:
lis r12, iret@ha
addi r12, r12, iret@l
272,7 → 313,6
rfi
 
iret_real:
lwz r0, 8(sp)
lwz r2, 12(sp)
lwz r3, 16(sp)
322,7 → 362,7
lwz r12, 148(sp)
mtxer r12
lwz r12, 152(sp)
lwz sp, 156(sp)
lwz r12, 156(sp)
lwz sp, 160(sp)
rfi
/branches/dd/kernel/arch/ppc32/src/asm.S
65,6 → 65,10
# set stack
mr sp, r4
 
# %r6 is defined to hold pcb_ptr - set it to 0
 
xor r6, r6, r6
# jump to userspace
127,8 → 131,8
lwz r12, 148(sp)
mtxer r12
lwz r12, 152(sp)
lwz sp, 156(sp)
lwz r12, 156(sp)
lwz sp, 160(sp)
rfi
 
193,53 → 197,13
lwz r12, 148(sp)
mtxer r12
lwz r12, 152(sp)
lwz sp, 156(sp)
lwz r12, 156(sp)
lwz sp, 160(sp)
 
rfi
memsetb:
rlwimi r5, r5, 8, 16, 23
rlwimi r5, r5, 16, 0, 15
addi r14, r3, -4
cmplwi 0, r4, 4
blt 7f
stwu r5, 4(r14)
beqlr
andi. r15, r14, 3
add r4, r15, r4
subf r14, r15, r14
srwi r15, r4, 2
mtctr r15
bdz 6f
1:
stwu r5, 4(r14)
bdnz 1b
6:
andi. r4, r4, 3
7:
cmpwi 0, r4, 0
beqlr
mtctr r4
addi r6, r6, 3
8:
stbu r5, 1(r14)
bdnz 8b
blr
b _memsetb
 
memcpy:
memcpy_from_uspace:
308,4 → 272,6
 
memcpy_from_uspace_failover_address:
memcpy_to_uspace_failover_address:
b memcpy_from_uspace_failover_address
# return zero, failure
xor r3, r3, r3
blr
/branches/dd/kernel/arch/ppc32/src/boot/boot.S
33,7 → 33,7
 
.global kernel_image_start
kernel_image_start:
 
# load temporal kernel stack
lis sp, kernel_stack@ha
52,7 → 52,7
beq bootinfo_end
addis r3, r3, 0x8000
 
lis r31, bootinfo@ha
addi r31, r31, bootinfo@l # r31 = bootinfo
/branches/dd/kernel/arch/ppc32/src/ppc32.c
45,21 → 45,25
#include <ddi/device.h>
#include <ddi/irq.h>
#include <arch/drivers/pic.h>
#include <macros.h>
#include <string.h>
 
#define IRQ_COUNT 64
#define IRQ_COUNT 64
 
bootinfo_t bootinfo;
 
/** Performs ppc32-specific initialization before main_bsp() is called. */
void arch_pre_main(void)
{
/* Setup usermode */
init.cnt = bootinfo.taskmap.count;
uint32_t i;
for (i = 0; i < bootinfo.taskmap.count; i++) {
for (i = 0; i < min3(bootinfo.taskmap.count, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS); i++) {
init.tasks[i].addr = PA2KA(bootinfo.taskmap.tasks[i].addr);
init.tasks[i].size = bootinfo.taskmap.tasks[i].size;
strncpy(init.tasks[i].name, bootinfo.taskmap.tasks[i].name,
CONFIG_TASK_NAME_BUFLEN);
}
}
 
76,34 → 80,47
{
if (config.cpu_active == 1) {
/* Initialize framebuffer */
unsigned int visual;
switch (bootinfo.screen.bpp) {
case 8:
visual = VISUAL_INDIRECT_8;
break;
case 16:
visual = VISUAL_RGB_5_5_5;
break;
case 24:
visual = VISUAL_RGB_8_8_8;
break;
case 32:
visual = VISUAL_RGB_0_8_8_8;
break;
default:
panic("Unsupported bits per pixel");
if (bootinfo.screen.addr) {
unsigned int visual;
switch (bootinfo.screen.bpp) {
case 8:
visual = VISUAL_INDIRECT_8;
break;
case 16:
visual = VISUAL_RGB_5_5_5;
break;
case 24:
visual = VISUAL_RGB_8_8_8;
break;
case 32:
visual = VISUAL_RGB_0_8_8_8;
break;
default:
panic("Unsupported bits per pixel.");
}
fb_properties_t prop = {
.addr = bootinfo.screen.addr,
.offset = 0,
.x = bootinfo.screen.width,
.y = bootinfo.screen.height,
.scan = bootinfo.screen.scanline,
.visual = visual,
};
fb_init(&prop);
}
fb_init(bootinfo.screen.addr, bootinfo.screen.width, bootinfo.screen.height, bootinfo.screen.scanline, visual);
/* Initialize IRQ routing */
irq_init(IRQ_COUNT, IRQ_COUNT);
/* Initialize PIC */
pic_init(bootinfo.keyboard.addr, PAGE_SIZE);
/* Initialize I/O controller */
cuda_init(device_assign_devno(), bootinfo.keyboard.addr + 0x16000, 2 * PAGE_SIZE);
if (bootinfo.macio.addr) {
/* Initialize PIC */
pic_init(bootinfo.macio.addr, PAGE_SIZE);
/* Initialize I/O controller */
cuda_init(device_assign_devno(),
bootinfo.macio.addr + 0x16000, 2 * PAGE_SIZE);
}
/* Merge all zones to 1 big zone */
zone_merge_all();
128,11 → 145,13
 
void userspace(uspace_arg_t *kernel_uarg)
{
userspace_asm((uintptr_t) kernel_uarg->uspace_uarg, (uintptr_t) kernel_uarg->uspace_stack + THREAD_STACK_SIZE - SP_DELTA, (uintptr_t) kernel_uarg->uspace_entry);
userspace_asm((uintptr_t) kernel_uarg->uspace_uarg,
(uintptr_t) kernel_uarg->uspace_stack +
THREAD_STACK_SIZE - SP_DELTA,
(uintptr_t) kernel_uarg->uspace_entry);
/* Unreachable */
for (;;)
;
while (true);
}
 
/** Acquire console back for kernel
140,7 → 159,7
*/
void arch_grab_console(void)
{
cuda_grab();
fb_redraw();
}
 
/** Return console to userspace
148,8 → 167,21
*/
void arch_release_console(void)
{
cuda_release();
}
 
/** Construct function pointer
*
* @param fptr function pointer structure
* @param addr function address
* @param caller calling function address
*
* @return address of the function pointer
*
*/
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
{
return addr;
}
 
/** @}
*/
/branches/dd/kernel/arch/ppc32/src/mm/tlb.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ppc32mm
/** @addtogroup ppc32mm
* @{
*/
/** @file
35,12 → 35,23
#include <mm/tlb.h>
#include <arch/mm/tlb.h>
#include <arch/interrupt.h>
#include <interrupt.h>
#include <mm/as.h>
#include <arch.h>
#include <print.h>
#include <symtab.h>
#include <macros.h>
 
 
static unsigned int seed = 10;
static unsigned int seed_real __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
 
 
#define TLB_FLUSH \
"tlbie %0\n" \
"addi %0, %0, 0x1000\n"
 
 
/** Try to find PTE for faulting address
*
* Try to find PTE for faulting address.
47,22 → 58,25
* The as->lock must be held on entry to this function
* if lock is true.
*
* @param as Address space.
* @param lock Lock/unlock the address space.
* @param badvaddr Faulting virtual address.
* @param access Access mode that caused the fault.
* @param istate Pointer to interrupted state.
* @param pfrc Pointer to variable where as_page_fault() return code will be stored.
* @return PTE on success, NULL otherwise.
* @param as Address space.
* @param lock Lock/unlock the address space.
* @param badvaddr Faulting virtual address.
* @param access Access mode that caused the fault.
* @param istate Pointer to interrupted state.
* @param pfrc Pointer to variable where as_page_fault() return code
* will be stored.
* @return PTE on success, NULL otherwise.
*
*/
static pte_t *find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access, istate_t *istate, int *pfrc)
static pte_t *
find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access,
istate_t *istate, int *pfrc)
{
/*
* Check if the mapping exists in page tables.
*/
pte_t *pte = page_mapping_find(as, badvaddr);
if ((pte) && (pte->p)) {
if ((pte) && (pte->present)) {
/*
* Mapping found in page tables.
* Immediately succeed.
77,27 → 91,26
*/
page_table_unlock(as, lock);
switch (rc = as_page_fault(badvaddr, access, istate)) {
case AS_PF_OK:
/*
* The higher-level page fault handler succeeded,
* The mapping ought to be in place.
*/
page_table_lock(as, lock);
pte = page_mapping_find(as, badvaddr);
ASSERT((pte) && (pte->p));
*pfrc = 0;
return pte;
case AS_PF_DEFER:
page_table_lock(as, lock);
*pfrc = rc;
return NULL;
case AS_PF_FAULT:
page_table_lock(as, lock);
printf("Page fault.\n");
*pfrc = rc;
return NULL;
default:
panic("unexpected rc (%d)\n", rc);
case AS_PF_OK:
/*
* The higher-level page fault handler succeeded,
* The mapping ought to be in place.
*/
page_table_lock(as, lock);
pte = page_mapping_find(as, badvaddr);
ASSERT((pte) && (pte->present));
*pfrc = 0;
return pte;
case AS_PF_DEFER:
page_table_lock(as, lock);
*pfrc = rc;
return NULL;
case AS_PF_FAULT:
page_table_lock(as, lock);
*pfrc = rc;
return NULL;
default:
panic("Unexpected rc (%d).", rc);
}
}
}
108,17 → 121,21
char *symbol = "";
char *sym2 = "";
 
char *s = get_symtab_entry(istate->pc);
if (s)
symbol = s;
s = get_symtab_entry(istate->lr);
if (s)
sym2 = s;
panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2);
char *str = get_symtab_entry(istate->pc);
if (str)
symbol = str;
str = get_symtab_entry(istate->lr);
if (str)
sym2 = str;
 
fault_if_from_uspace(istate,
"PHT Refill Exception on %p.", badvaddr);
panic("%p: PHT Refill Exception at %p (%s<-%s).", badvaddr,
istate->pc, symbol, sym2);
}
 
 
static void pht_insert(const uintptr_t vaddr, const pfn_t pfn)
static void pht_insert(const uintptr_t vaddr, const pte_t *pte)
{
uint32_t page = (vaddr >> 12) & 0xffff;
uint32_t api = (vaddr >> 22) & 0x3f;
144,10 → 161,12
uint32_t i;
bool found = false;
/* Find unused or colliding
PTE in PTEG */
/* Find colliding PTE in PTEG */
for (i = 0; i < 8; i++) {
if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && (phte[base + i].api == api))) {
if ((phte[base + i].v)
&& (phte[base + i].vsid == vsid)
&& (phte[base + i].api == api)
&& (phte[base + i].h == 0)) {
found = true;
break;
}
154,13 → 173,25
}
if (!found) {
/* Find unused PTE in PTEG */
for (i = 0; i < 8; i++) {
if (!phte[base + i].v) {
found = true;
break;
}
}
}
if (!found) {
/* Secondary hash (not) */
uint32_t base2 = (~hash & 0x3ff) << 3;
/* Find unused or colliding
PTE in PTEG */
/* Find colliding PTE in PTEG */
for (i = 0; i < 8; i++) {
if ((!phte[base2 + i].v) || ((phte[base2 + i].vsid == vsid) && (phte[base2 + i].api == api))) {
if ((phte[base2 + i].v)
&& (phte[base2 + i].vsid == vsid)
&& (phte[base2 + i].api == api)
&& (phte[base2 + i].h == 1)) {
found = true;
base = base2;
h = 1;
169,9 → 200,19
}
if (!found) {
// TODO: A/C precedence groups
i = page % 8;
/* Find unused PTE in PTEG */
for (i = 0; i < 8; i++) {
if (!phte[base2 + i].v) {
found = true;
base = base2;
h = 1;
break;
}
}
}
if (!found)
i = RANDI(seed) % 8;
}
phte[base + i].v = 1;
178,23 → 219,106
phte[base + i].vsid = vsid;
phte[base + i].h = h;
phte[base + i].api = api;
phte[base + i].rpn = pfn;
phte[base + i].rpn = pte->pfn;
phte[base + i].r = 0;
phte[base + i].c = 0;
phte[base + i].wimg = (pte->page_cache_disable ? WIMG_NO_CACHE : 0);
phte[base + i].pp = 2; // FIXME
}
 
 
static void pht_real_insert(const uintptr_t vaddr, const pfn_t pfn)
/** Process Instruction/Data Storage Exception
*
* @param n Exception vector number.
* @param istate Interrupted register context.
*
*/
void pht_refill(int n, istate_t *istate)
{
uint32_t page = (vaddr >> 12) & 0xffff;
uint32_t api = (vaddr >> 22) & 0x3f;
uintptr_t badvaddr;
pte_t *pte;
int pfrc;
as_t *as;
bool lock;
if (AS == NULL) {
as = AS_KERNEL;
lock = false;
} else {
as = AS;
lock = true;
}
if (n == VECTOR_DATA_STORAGE)
badvaddr = istate->dar;
else
badvaddr = istate->pc;
page_table_lock(as, lock);
pte = find_mapping_and_check(as, lock, badvaddr,
PF_ACCESS_READ /* FIXME */, istate, &pfrc);
if (!pte) {
switch (pfrc) {
case AS_PF_FAULT:
goto fail;
break;
case AS_PF_DEFER:
/*
* The page fault came during copy_from_uspace()
* or copy_to_uspace().
*/
page_table_unlock(as, lock);
return;
default:
panic("Unexpected pfrc (%d).", pfrc);
}
}
pte->accessed = 1; /* Record access to PTE */
pht_insert(badvaddr, pte);
page_table_unlock(as, lock);
return;
fail:
page_table_unlock(as, lock);
pht_refill_fail(badvaddr, istate);
}
 
 
/** Process Instruction/Data Storage Exception in Real Mode
*
* @param n Exception vector number.
* @param istate Interrupted register context.
*
*/
bool pht_refill_real(int n, istate_t *istate)
{
uintptr_t badvaddr;
if (n == VECTOR_DATA_STORAGE)
badvaddr = istate->dar;
else
badvaddr = istate->pc;
uint32_t physmem;
asm volatile (
"mfsprg3 %0\n"
: "=r" (physmem)
);
if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
return false;
uint32_t page = (badvaddr >> 12) & 0xffff;
uint32_t api = (badvaddr >> 22) & 0x3f;
uint32_t vsid;
asm volatile (
"mfsrin %0, %1\n"
: "=r" (vsid)
: "r" (vaddr)
: "r" (badvaddr)
);
uint32_t sdr1;
202,7 → 326,7
"mfsdr1 %0\n"
: "=r" (sdr1)
);
phte_t *phte_physical = (phte_t *) (sdr1 & 0xffff0000);
phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000);
/* Primary hash (xor) */
uint32_t h = 0;
211,10 → 335,12
uint32_t i;
bool found = false;
/* Find unused or colliding
PTE in PTEG */
/* Find colliding PTE in PTEG */
for (i = 0; i < 8; i++) {
if ((!phte_physical[base + i].v) || ((phte_physical[base + i].vsid == vsid) && (phte_physical[base + i].api == api))) {
if ((phte_real[base + i].v)
&& (phte_real[base + i].vsid == vsid)
&& (phte_real[base + i].api == api)
&& (phte_real[base + i].h == 0)) {
found = true;
break;
}
221,13 → 347,25
}
if (!found) {
/* Find unused PTE in PTEG */
for (i = 0; i < 8; i++) {
if (!phte_real[base + i].v) {
found = true;
break;
}
}
}
if (!found) {
/* Secondary hash (not) */
uint32_t base2 = (~hash & 0x3ff) << 3;
/* Find unused or colliding
PTE in PTEG */
/* Find colliding PTE in PTEG */
for (i = 0; i < 8; i++) {
if ((!phte_physical[base2 + i].v) || ((phte_physical[base2 + i].vsid == vsid) && (phte_physical[base2 + i].api == api))) {
if ((phte_real[base2 + i].v)
&& (phte_real[base2 + i].vsid == vsid)
&& (phte_real[base2 + i].api == api)
&& (phte_real[base2 + i].h == 1)) {
found = true;
base = base2;
h = 1;
236,102 → 374,48
}
if (!found) {
// TODO: A/C precedence groups
i = page % 8;
/* Find unused PTE in PTEG */
for (i = 0; i < 8; i++) {
if (!phte_real[base2 + i].v) {
found = true;
base = base2;
h = 1;
break;
}
}
}
}
phte_physical[base + i].v = 1;
phte_physical[base + i].vsid = vsid;
phte_physical[base + i].h = h;
phte_physical[base + i].api = api;
phte_physical[base + i].rpn = pfn;
phte_physical[base + i].r = 0;
phte_physical[base + i].c = 0;
phte_physical[base + i].pp = 2; // FIXME
}
 
 
/** Process Instruction/Data Storage Interrupt
*
* @param n Interrupt vector number.
* @param istate Interrupted register context.
*
*/
void pht_refill(int n, istate_t *istate)
{
uintptr_t badvaddr;
pte_t *pte;
int pfrc;
as_t *as;
bool lock;
if (AS == NULL) {
as = AS_KERNEL;
lock = false;
} else {
as = AS;
lock = true;
}
if (n == VECTOR_DATA_STORAGE) {
asm volatile (
"mfdar %0\n"
: "=r" (badvaddr)
);
} else
badvaddr = istate->pc;
page_table_lock(as, lock);
pte = find_mapping_and_check(as, lock, badvaddr, PF_ACCESS_READ /* FIXME */, istate, &pfrc);
if (!pte) {
switch (pfrc) {
case AS_PF_FAULT:
goto fail;
break;
case AS_PF_DEFER:
/*
* The page fault came during copy_from_uspace()
* or copy_to_uspace().
*/
page_table_unlock(as, lock);
return;
default:
panic("Unexpected pfrc (%d)\n", pfrc);
if (!found) {
/* Use secondary hash to avoid collisions
with usual PHT refill handler. */
i = RANDI(seed_real) % 8;
base = base2;
h = 1;
}
}
pte->a = 1; /* Record access to PTE */
pht_insert(badvaddr, pte->pfn);
phte_real[base + i].v = 1;
phte_real[base + i].vsid = vsid;
phte_real[base + i].h = h;
phte_real[base + i].api = api;
phte_real[base + i].rpn = KA2PA(badvaddr) >> 12;
phte_real[base + i].r = 0;
phte_real[base + i].c = 0;
phte_real[base + i].wimg = 0;
phte_real[base + i].pp = 2; // FIXME
page_table_unlock(as, lock);
return;
fail:
page_table_unlock(as, lock);
pht_refill_fail(badvaddr, istate);
return true;
}
 
 
/** Process Instruction/Data Storage Interrupt in Real Mode
/** Process ITLB/DTLB Miss Exception in Real Mode
*
* @param n Interrupt vector number.
* @param istate Interrupted register context.
*
*/
bool pht_real_refill(int n, istate_t *istate)
void tlb_refill_real(int n, uint32_t tlbmiss, ptehi_t ptehi, ptelo_t ptelo, istate_t *istate)
{
uintptr_t badvaddr;
uint32_t badvaddr = tlbmiss & 0xfffffffc;
if (n == VECTOR_DATA_STORAGE) {
asm volatile (
"mfdar %0\n"
: "=r" (badvaddr)
);
} else
badvaddr = istate->pc;
uint32_t physmem;
asm volatile (
"mfsprg3 %0\n"
338,12 → 422,23
: "=r" (physmem)
);
if ((badvaddr >= PA2KA(0)) && (badvaddr < PA2KA(physmem))) {
pht_real_insert(badvaddr, KA2PA(badvaddr) >> 12);
return true;
}
if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
return; // FIXME
return false;
ptelo.rpn = KA2PA(badvaddr) >> 12;
ptelo.wimg = 0;
ptelo.pp = 2; // FIXME
uint32_t index = 0;
asm volatile (
"mtspr 981, %0\n"
"mtspr 982, %1\n"
"tlbld %2\n"
"tlbli %2\n"
: "=r" (index)
: "r" (ptehi),
"r" (ptelo)
);
}
 
 
355,9 → 450,87
 
void tlb_invalidate_all(void)
{
uint32_t index;
asm volatile (
"tlbia\n"
"li %0, 0\n"
"sync\n"
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
TLB_FLUSH
"eieio\n"
"tlbsync\n"
"sync\n"
: "=r" (index)
);
}
 
373,7 → 546,8
uint32_t i;
for (i = 0; i < 8192; i++) {
if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) && (phte[i].vsid < ((asid << 4) + 16)))
if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&
(phte[i].vsid < ((asid << 4) + 16)))
phte[i].v = 0;
}
tlb_invalidate_all();
407,7 → 581,11
} \
} else \
length = 0; \
printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, lower & 0xffff0000, length, mask, ((upper >> 1) & 1) ? " supervisor" : "", (upper & 1) ? " user" : "");
printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \
sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \
lower & 0xffff0000, length, mask, \
((upper >> 1) & 1) ? " supervisor" : "", \
(upper & 1) ? " user" : "");
 
 
void tlb_print(void)
421,7 → 599,10
: "=r" (vsid)
: "r" (sr << 28)
);
printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr, sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4, ((vsid >> 30) & 1) ? " supervisor" : "", ((vsid >> 29) & 1) ? " user" : "");
printf("sr[%02u]: vsid=%.*p (asid=%u)%s%s\n", sr,
sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4,
((vsid >> 30) & 1) ? " supervisor" : "",
((vsid >> 29) & 1) ? " user" : "");
}
uint32_t upper;
/branches/dd/kernel/arch/ppc32/src/mm/frame.c
74,7 → 74,7
if (last_frame < ALIGN_UP(bootinfo.memmap.zones[i].start + bootinfo.memmap.zones[i].size, FRAME_SIZE))
last_frame = ALIGN_UP(bootinfo.memmap.zones[i].start + bootinfo.memmap.zones[i].size, FRAME_SIZE);
}
 
/* First is exception vector, second is 'implementation specific',
third and fourth is reserved, other contain real mode code */
frame_mark_unavailable(0, 8);
/branches/dd/kernel/arch/ppc32/src/mm/page.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ppc32mm
/** @addtogroup ppc32mm
* @{
*/
/** @file
47,13 → 47,16
 
uintptr_t hw_map(uintptr_t physaddr, size_t size)
{
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
panic("Unable to map physical memory %p (%d bytes)", physaddr, size)
if (last_frame + ALIGN_UP(size, PAGE_SIZE) >
KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
panic("Unable to map physical memory %p (%" PRIs " bytes).",
physaddr, size)
uintptr_t virtaddr = PA2KA(last_frame);
pfn_t i;
for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++)
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE);
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i),
physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE);
last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
/branches/dd/kernel/arch/ppc32/src/interrupt.c
73,7 → 73,7
ack = true;
}
irq->handler(irq, irq->arg);
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
/*
80,7 → 80,7
* Spurious interrupt.
*/
#ifdef CONFIG_DEBUG
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum);
printf("cpu%u: spurious interrupt (inum=%d)\n", CPU->id, inum);
#endif
}
92,8 → 92,8
 
static void exception_decrementer(int n, istate_t *istate)
{
start_decrementer();
clock();
start_decrementer();
}
 
 
/branches/dd/kernel/arch/ppc32/src/drivers/pic.c
38,7 → 38,7
#include <byteorder.h>
#include <bitops.h>
 
static volatile uint32_t *pic;
static volatile uint32_t *pic = NULL;
 
void pic_init(uintptr_t base, size_t size)
{
47,10 → 47,11
 
void pic_enable_interrupt(int intnum)
{
if (intnum < 32) {
pic[PIC_MASK_LOW] = pic[PIC_MASK_LOW] | (1 << intnum);
} else {
pic[PIC_MASK_HIGH] = pic[PIC_MASK_HIGH] | (1 << (intnum - 32));
if (pic) {
if (intnum < 32)
pic[PIC_MASK_LOW] = pic[PIC_MASK_LOW] | (1 << intnum);
else
pic[PIC_MASK_HIGH] = pic[PIC_MASK_HIGH] | (1 << (intnum - 32));
}
}
57,34 → 58,39
 
void pic_disable_interrupt(int intnum)
{
if (intnum < 32) {
pic[PIC_MASK_LOW] = pic[PIC_MASK_LOW] & (~(1 << intnum));
} else {
pic[PIC_MASK_HIGH] = pic[PIC_MASK_HIGH] & (~(1 << (intnum - 32)));
if (pic) {
if (intnum < 32)
pic[PIC_MASK_LOW] = pic[PIC_MASK_LOW] & (~(1 << intnum));
else
pic[PIC_MASK_HIGH] = pic[PIC_MASK_HIGH] & (~(1 << (intnum - 32)));
}
}
 
void pic_ack_interrupt(int intnum)
{
if (intnum < 32)
pic[PIC_ACK_LOW] = 1 << intnum;
else
pic[PIC_ACK_HIGH] = 1 << (intnum - 32);
if (pic) {
if (intnum < 32)
pic[PIC_ACK_LOW] = 1 << intnum;
else
pic[PIC_ACK_HIGH] = 1 << (intnum - 32);
}
}
 
/** Return number of pending interrupt */
int pic_get_pending(void)
{
int pending;
 
pending = pic[PIC_PENDING_LOW];
if (pending)
return fnzb32(pending);
if (pic) {
int pending;
pending = pic[PIC_PENDING_LOW];
if (pending)
return fnzb32(pending);
pending = pic[PIC_PENDING_HIGH];
if (pending)
return fnzb32(pending) + 32;
}
pending = pic[PIC_PENDING_HIGH];
if (pending)
return fnzb32(pending) + 32;
return -1;
}
 
/branches/dd/kernel/arch/ppc32/src/drivers/cuda.c
33,7 → 33,6
*/
 
#include <arch/drivers/cuda.h>
#include <ipc/irq.h>
#include <arch/asm.h>
#include <console/console.h>
#include <console/chardev.h>
236,64 → 235,38
 
int cuda_get_scancode(void)
{
uint8_t kind;
uint8_t data[4];
if (cuda) {
uint8_t kind;
uint8_t data[4];
receive_packet(&kind, 4, data);
if ((kind == PACKET_ADB) && (data[0] == 0x40) && (data[1] == 0x2c))
return data[2];
}
receive_packet(&kind, 4, data);
if ((kind == PACKET_ADB) && (data[0] == 0x40) && (data[1] == 0x2c))
return data[2];
return -1;
}
 
static void cuda_irq_handler(irq_t *irq, void *arg, ...)
static void cuda_irq_handler(irq_t *irq)
{
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox))
ipc_irq_send_notif(irq);
else {
int scan_code = cuda_get_scancode();
int scan_code = cuda_get_scancode();
if (scan_code != -1) {
uint8_t scancode = (uint8_t) scan_code;
if ((scancode & 0x80) != 0x80)
chardev_push_character(&kbrd, lchars[scancode & 0x7f]);
}
if (scan_code != -1) {
uint8_t scancode = (uint8_t) scan_code;
if ((scancode & 0x80) != 0x80)
chardev_push_character(&kbrd, lchars[scancode & 0x7f]);
}
}
 
static irq_ownership_t cuda_claim(void)
static irq_ownership_t cuda_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
 
/** Initialize keyboard and service interrupts using kernel routine */
void cuda_grab(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&cuda_irq.lock);
cuda_irq.notif_cfg.notify = false;
spinlock_unlock(&cuda_irq.lock);
interrupts_restore(ipl);
}
 
 
/** Resume the former interrupt vector */
void cuda_release(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&cuda_irq.lock);
if (cuda_irq.notif_cfg.answerbox)
cuda_irq.notif_cfg.notify = true;
spinlock_unlock(&cuda_irq.unlock);
interrupts_restore(ipl);
}
 
 
void cuda_init(devno_t devno, uintptr_t base, size_t size)
{
cuda = (uint8_t *) hw_map(base, size);
cuda = (uint8_t *) hw_map(base, size);
chardev_initialize("cuda_kbd", &kbrd, &ops);
stdin = &kbrd;
306,7 → 279,7
irq_register(&cuda_irq);
pic_enable_interrupt(CUDA_IRQ);
 
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, CUDA_IRQ);
345,7 → 318,9
}
 
void arch_reboot(void) {
send_packet(PACKET_CUDA, 1, CUDA_RESET);
if (cuda)
send_packet(PACKET_CUDA, 1, CUDA_RESET);
asm volatile (
"b 0\n"
);
/branches/dd/kernel/arch/amd64/include/drivers/i8259.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/amd64/include/drivers/i8042.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/amd64/include/drivers/i8254.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/amd64/include/drivers/ega.h
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:special
-*
\ No newline at end of property
/branches/dd/kernel/arch/amd64/include/drivers/vesa.h
File deleted
/branches/dd/kernel/arch/amd64/include/interrupt.h
71,7 → 71,6
/** This is passed to interrupt handlers */
typedef struct {
uint64_t rax;
uint64_t rbx;
uint64_t rcx;
uint64_t rdx;
uint64_t rsi;
80,11 → 79,6
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t rbp;
uint64_t error_word;
uint64_t rip;
uint64_t cs;
/branches/dd/kernel/arch/amd64/include/types.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup amd64
/** @addtogroup amd64
* @{
*/
/** @file
35,10 → 35,6
#ifndef KERN_amd64_TYPES_H_
#define KERN_amd64_TYPES_H_
 
#define NULL 0
#define false 0
#define true 1
 
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
61,14 → 57,34
typedef uint64_t unative_t;
typedef int64_t native_t;
 
typedef uint8_t bool;
typedef uint64_t thread_id_t;
typedef uint64_t task_id_t;
typedef uint32_t context_id_t;
typedef struct {
} fncptr_t;
 
typedef int32_t inr_t;
typedef int32_t devno_t;
/**< Formats for uintptr_t, size_t, count_t and index_t */
#define PRIp "llx"
#define PRIs "llu"
#define PRIc "llu"
#define PRIi "llu"
 
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */
#define PRId8 "d"
#define PRId16 "d"
#define PRId32 "d"
#define PRId64 "lld"
#define PRIdn "lld"
 
#define PRIu8 "u"
#define PRIu16 "u"
#define PRIu32 "u"
#define PRIu64 "llu"
#define PRIun "llu"
 
#define PRIx8 "x"
#define PRIx16 "x"
#define PRIx32 "x"
#define PRIx64 "llx"
#define PRIxn "llx"
 
/** Page Table Entry. */
typedef struct {
unsigned present : 1;
/branches/dd/kernel/arch/amd64/include/memstr.h
35,110 → 35,13
#ifndef KERN_amd64_MEMSTR_H_
#define KERN_amd64_MEMSTR_H_
 
/** Copy memory
*
* Copy a given number of bytes (3rd argument)
* from the memory location defined by 2nd argument
* to the memory location defined by 1st argument.
* The memory areas cannot overlap.
*
* @param dst Destination
* @param src Source
* @param cnt Number of bytes
* @return Destination
*/
static inline void * memcpy(void * dst, const void * src, size_t cnt)
{
unative_t d0, d1, d2;
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt))
 
asm volatile(
"rep movsq\n\t"
"movq %4, %%rcx\n\t"
"andq $7, %%rcx\n\t"
"jz 1f\n\t"
"rep movsb\n\t"
"1:\n"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
: "0" ((unative_t)(cnt / 8)), "g" ((unative_t)cnt), "1" ((unative_t) dst), "2" ((unative_t) src)
: "memory");
extern void memsetw(void *dst, size_t cnt, uint16_t x);
extern void memsetb(void *dst, size_t cnt, uint8_t x);
 
return dst;
}
extern int memcmp(const void *a, const void *b, size_t cnt);
 
 
/** Compare memory regions for equality
*
* Compare a given number of bytes (3rd argument)
* at memory locations defined by 1st and 2nd argument
* for equality. If bytes are equal function returns 0.
*
* @param src Region 1
* @param dst Region 2
* @param cnt Number of bytes
* @return Zero if bytes are equal, non-zero otherwise
*/
static inline int memcmp(const void * src, const void * dst, size_t cnt)
{
unative_t d0, d1, d2;
unative_t ret;
asm (
"repe cmpsb\n\t"
"je 1f\n\t"
"movq %3, %0\n\t"
"addq $1, %0\n\t"
"1:\n"
: "=a" (ret), "=%S" (d0), "=&D" (d1), "=&c" (d2)
: "0" (0), "1" (src), "2" (dst), "3" ((unative_t)cnt)
);
return ret;
}
 
/** Fill memory with words
* Fill a given number of words (2nd argument)
* at memory defined by 1st argument with the
* word value defined by 3rd argument.
*
* @param dst Destination
* @param cnt Number of words
* @param x Value to fill
*/
static inline void memsetw(uintptr_t dst, size_t cnt, uint16_t x)
{
unative_t d0, d1;
asm volatile (
"rep stosw\n\t"
: "=&D" (d0), "=&c" (d1), "=a" (x)
: "0" (dst), "1" ((unative_t)cnt), "2" (x)
: "memory"
);
 
}
 
/** Fill memory with bytes
* Fill a given number of bytes (2nd argument)
* at memory defined by 1st argument with the
* word value defined by 3rd argument.
*
* @param dst Destination
* @param cnt Number of bytes
* @param x Value to fill
*/
static inline void memsetb(uintptr_t dst, size_t cnt, uint8_t x)
{
unative_t d0, d1;
asm volatile (
"rep stosb\n\t"
: "=&D" (d0), "=&c" (d1), "=a" (x)
: "0" (dst), "1" ((unative_t)cnt), "2" (x)
: "memory"
);
 
}
 
#endif
 
/** @}
/branches/dd/kernel/arch/amd64/include/syscall.h
35,8 → 35,6
#ifndef KERN_amd64_SYSCALL_H_
#define KERN_amd64_SYSCALL_H_
 
#include <arch/types.h>
 
extern void syscall_setup_cpu(void);
 
#endif
/branches/dd/kernel/arch/amd64/include/atomic.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup amd64
/** @addtogroup amd64
* @{
*/
/** @file
41,17 → 41,29
 
static inline void atomic_inc(atomic_t *val) {
#ifdef CONFIG_SMP
asm volatile ("lock incq %0\n" : "=m" (val->count));
asm volatile (
"lock incq %[count]\n"
: [count] "+m" (val->count)
);
#else
asm volatile ("incq %0\n" : "=m" (val->count));
asm volatile (
"incq %[count]\n"
: [count] "+m" (val->count)
);
#endif /* CONFIG_SMP */
}
 
static inline void atomic_dec(atomic_t *val) {
#ifdef CONFIG_SMP
asm volatile ("lock decq %0\n" : "=m" (val->count));
asm volatile (
"lock decq %[count]\n"
: [count] "+m" (val->count)
);
#else
asm volatile ("decq %0\n" : "=m" (val->count));
asm volatile (
"decq %[count]\n"
: [count] "+m" (val->count)
);
#endif /* CONFIG_SMP */
}
 
58,12 → 70,12
static inline long atomic_postinc(atomic_t *val)
{
long r = 1;
 
asm volatile (
"lock xaddq %1, %0\n"
: "=m" (val->count), "+r" (r)
"lock xaddq %[r], %[count]\n"
: [count] "+m" (val->count), [r] "+r" (r)
);
 
return r;
}
 
72,23 → 84,23
long r = -1;
asm volatile (
"lock xaddq %1, %0\n"
: "=m" (val->count), "+r" (r)
"lock xaddq %[r], %[count]\n"
: [count] "+m" (val->count), [r] "+r" (r)
);
return r;
}
 
#define atomic_preinc(val) (atomic_postinc(val)+1)
#define atomic_predec(val) (atomic_postdec(val)-1)
#define atomic_preinc(val) (atomic_postinc(val) + 1)
#define atomic_predec(val) (atomic_postdec(val) - 1)
 
static inline uint64_t test_and_set(atomic_t *val) {
uint64_t v;
asm volatile (
"movq $1, %0\n"
"xchgq %0, %1\n"
: "=r" (v),"=m" (val->count)
"movq $1, %[v]\n"
"xchgq %[v], %[count]\n"
: [v] "=r" (v), [count] "+m" (val->count)
);
return v;
99,23 → 111,23
static inline void atomic_lock_arch(atomic_t *val)
{
uint64_t tmp;
 
preemption_disable();
asm volatile (
"0:;"
"0:\n"
#ifdef CONFIG_HT
"pause;"
"pause\n"
#endif
"mov %0, %1;"
"testq %1, %1;"
"jnz 0b;" /* Lightweight looping on locked spinlock */
"mov %[count], %[tmp]\n"
"testq %[tmp], %[tmp]\n"
"jnz 0b\n" /* lightweight looping on locked spinlock */
"incq %1;" /* now use the atomic operation */
"xchgq %0, %1;"
"testq %1, %1;"
"jnz 0b;"
: "=m"(val->count),"=r"(tmp)
);
"incq %[tmp]\n" /* now use the atomic operation */
"xchgq %[count], %[tmp]\n"
"testq %[tmp], %[tmp]\n"
"jnz 0b\n"
: [count] "+m" (val->count), [tmp] "=&r" (tmp)
);
/*
* Prevent critical section code from bleeding out this way up.
*/
/branches/dd/kernel/arch/amd64/include/boot/boot.h
42,8 → 42,17
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
#define MULTIBOOT_HEADER_FLAGS 0x00010003
 
#define MULTIBOOT_LOADER_MAGIC 0x2BADB002
#ifndef __ASM__
 
#ifdef CONFIG_SMP
 
/* This is only a symbol so the type is dummy. Obtain the value using &. */
extern int _hardcoded_unmapped_size;
 
#endif /* CONFIG_SMP */
 
#endif /* __ASM__ */
 
#endif
 
/** @}
/branches/dd/kernel/arch/amd64/include/arch.h
35,6 → 35,10
#ifndef KERN_amd64_ARCH_H_
#define KERN_amd64_ARCH_H_
 
#include <genarch/multiboot/multiboot.h>
 
extern void arch_pre_main(uint32_t, const multiboot_info_t *);
 
#endif
 
/** @}
/branches/dd/kernel/arch/amd64/include/asm.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup amd64
/** @addtogroup amd64
* @{
*/
/** @file
36,6 → 36,8
#define KERN_amd64_ASM_H_
 
#include <config.h>
#include <arch/types.h>
#include <typedefs.h>
 
extern void asm_delay_loop(uint32_t t);
extern void asm_fake_loop(uint32_t t);
45,12 → 47,17
* Return the base address of the current stack.
* The stack is assumed to be STACK_SIZE bytes long.
* The stack must start on page boundary.
*
*/
static inline uintptr_t get_stack_base(void)
{
uintptr_t v;
asm volatile ("andq %%rsp, %0\n" : "=r" (v) : "0" (~((uint64_t)STACK_SIZE-1)));
asm volatile (
"andq %%rsp, %[v]\n"
: [v] "=r" (v)
: "0" (~((uint64_t) STACK_SIZE-1))
);
return v;
}
72,15 → 79,63
*
* @param port Port to read from
* @return Value read
*
*/
static inline uint8_t inb(uint16_t port)
static inline uint8_t pio_read_8(ioport8_t *port)
{
uint8_t val;
asm volatile (
"inb %w[port], %b[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
asm volatile ("inb %w1, %b0 \n" : "=a" (val) : "d" (port));
/** Word from port
*
* Get word from port
*
* @param port Port to read from
* @return Value read
*
*/
static inline uint16_t pio_read_16(ioport16_t *port)
{
uint16_t val;
asm volatile (
"inw %w[port], %w[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
/** Double word from port
*
* Get double word from port
*
* @param port Port to read from
* @return Value read
*
*/
static inline uint32_t pio_read_32(ioport32_t *port)
{
uint32_t val;
asm volatile (
"inl %w[port], %[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
/** Byte to port
*
* Output byte to port
87,12 → 142,48
*
* @param port Port to write to
* @param val Value to write
*
*/
static inline void outb(uint16_t port, uint8_t val)
static inline void pio_write_8(ioport8_t *port, uint8_t val)
{
asm volatile ("outb %b0, %w1\n" : : "a" (val), "d" (port));
asm volatile (
"outb %b[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
/** Word to port
*
* Output word to port
*
* @param port Port to write to
* @param val Value to write
*
*/
static inline void pio_write_16(ioport16_t *port, uint16_t val)
{
asm volatile (
"outw %w[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
/** Double word to port
*
* Output double word to port
*
* @param port Port to write to
* @param val Value to write
*
*/
static inline void pio_write_32(ioport32_t *port, uint32_t val)
{
asm volatile (
"outl %[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
/** Swap Hidden part of GS register with visible one */
static inline void swapgs(void)
{
105,15 → 196,18
* value of EFLAGS.
*
* @return Old interrupt priority level.
*
*/
static inline ipl_t interrupts_enable(void) {
ipl_t v;
__asm__ volatile (
asm volatile (
"pushfq\n"
"popq %0\n"
"popq %[v]\n"
"sti\n"
: "=r" (v)
: [v] "=r" (v)
);
return v;
}
 
123,15 → 217,18
* value of EFLAGS.
*
* @return Old interrupt priority level.
*
*/
static inline ipl_t interrupts_disable(void) {
ipl_t v;
__asm__ volatile (
asm volatile (
"pushfq\n"
"popq %0\n"
"popq %[v]\n"
"cli\n"
: "=r" (v)
);
: [v] "=r" (v)
);
return v;
}
 
140,13 → 237,14
* Restore EFLAGS.
*
* @param ipl Saved interrupt priority level.
*
*/
static inline void interrupts_restore(ipl_t ipl) {
__asm__ volatile (
"pushq %0\n"
asm volatile (
"pushq %[ipl]\n"
"popfq\n"
: : "r" (ipl)
);
:: [ipl] "r" (ipl)
);
}
 
/** Return interrupt priority level.
154,14 → 252,17
* Return EFLAFS.
*
* @return Current interrupt priority level.
*
*/
static inline ipl_t interrupts_read(void) {
ipl_t v;
__asm__ volatile (
asm volatile (
"pushfq\n"
"popq %0\n"
: "=r" (v)
"popq %[v]\n"
: [v] "=r" (v)
);
return v;
}
 
168,21 → 269,25
/** Write to MSR */
static inline void write_msr(uint32_t msr, uint64_t value)
{
__asm__ volatile (
"wrmsr;" : : "c" (msr),
"a" ((uint32_t)(value)),
"d" ((uint32_t)(value >> 32))
);
asm volatile (
"wrmsr\n"
:: "c" (msr),
"a" ((uint32_t) (value)),
"d" ((uint32_t) (value >> 32))
);
}
 
static inline unative_t read_msr(uint32_t msr)
{
uint32_t ax, dx;
 
__asm__ volatile (
"rdmsr;" : "=a"(ax), "=d"(dx) : "c" (msr)
);
return ((uint64_t)dx << 32) | ax;
asm volatile (
"rdmsr\n"
: "=a" (ax), "=d" (dx)
: "c" (msr)
);
return ((uint64_t) dx << 32) | ax;
}
 
 
189,29 → 294,29
/** Enable local APIC
*
* Enable local APIC in MSR.
*
*/
static inline void enable_l_apic_in_msr()
{
__asm__ volatile (
asm volatile (
"movl $0x1b, %%ecx\n"
"rdmsr\n"
"orl $(1<<11),%%eax\n"
"orl $(1 << 11),%%eax\n"
"orl $(0xfee00000),%%eax\n"
"wrmsr\n"
:
:
:"%eax","%ecx","%edx"
);
::: "%eax","%ecx","%edx"
);
}
 
static inline uintptr_t * get_ip()
{
uintptr_t *ip;
 
__asm__ volatile (
"mov %%rip, %0"
: "=r" (ip)
);
asm volatile (
"mov %%rip, %[ip]"
: [ip] "=r" (ip)
);
return ip;
}
 
218,59 → 323,84
/** Invalidate TLB Entry.
*
* @param addr Address on a page whose TLB entry is to be invalidated.
*
*/
static inline void invlpg(uintptr_t addr)
{
__asm__ volatile ("invlpg %0\n" :: "m" (*((unative_t *)addr)));
asm volatile (
"invlpg %[addr]\n"
:: [addr] "m" (*((unative_t *) addr))
);
}
 
/** Load GDTR register from memory.
*
* @param gdtr_reg Address of memory from where to load GDTR.
*
*/
static inline void gdtr_load(struct ptr_16_64 *gdtr_reg)
{
__asm__ volatile ("lgdtq %0\n" : : "m" (*gdtr_reg));
asm volatile (
"lgdtq %[gdtr_reg]\n"
:: [gdtr_reg] "m" (*gdtr_reg)
);
}
 
/** Store GDTR register to memory.
*
* @param gdtr_reg Address of memory to where to load GDTR.
*
*/
static inline void gdtr_store(struct ptr_16_64 *gdtr_reg)
{
__asm__ volatile ("sgdtq %0\n" : : "m" (*gdtr_reg));
asm volatile (
"sgdtq %[gdtr_reg]\n"
:: [gdtr_reg] "m" (*gdtr_reg)
);
}
 
/** Load IDTR register from memory.
*
* @param idtr_reg Address of memory from where to load IDTR.
*
*/
static inline void idtr_load(struct ptr_16_64 *idtr_reg)
{
__asm__ volatile ("lidtq %0\n" : : "m" (*idtr_reg));
asm volatile (
"lidtq %[idtr_reg]\n"
:: [idtr_reg] "m" (*idtr_reg));
}
 
/** Load TR from descriptor table.
*
* @param sel Selector specifying descriptor of TSS segment.
*
*/
static inline void tr_load(uint16_t sel)
{
__asm__ volatile ("ltr %0" : : "r" (sel));
asm volatile (
"ltr %[sel]"
:: [sel] "r" (sel)
);
}
 
#define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \
{ \
unative_t res; \
__asm__ volatile ("movq %%" #reg ", %0" : "=r" (res) ); \
return res; \
}
{ \
unative_t res; \
asm volatile ( \
"movq %%" #reg ", %[res]" \
: [res] "=r" (res) \
); \
return res; \
}
 
#define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \
{ \
__asm__ volatile ("movq %0, %%" #reg : : "r" (regn)); \
}
{ \
asm volatile ( \
"movq %[regn], %%" #reg \
:: [regn] "r" (regn) \
); \
}
 
GEN_READ_REG(cr0)
GEN_READ_REG(cr2)
/branches/dd/kernel/arch/amd64/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup amd64mm
/** @addtogroup amd64mm
* @{
*/
/** @file
39,8 → 39,8
#include <arch/types.h>
#endif /* __ASM__ */
 
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
 
#ifndef __ASM__
extern uintptr_t last_frame;
/branches/dd/kernel/arch/amd64/include/mm/page.h
52,8 → 52,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifdef KERNEL
 
#ifndef __ASM__
/branches/dd/kernel/arch/amd64/include/mm/tlb.h
35,9 → 35,6
#ifndef KERN_amd64_TLB_H_
#define KERN_amd64_TLB_H_
 
#define tlb_arch_init()
#define tlb_print()
 
#endif
 
/** @}
/branches/dd/kernel/arch/amd64/Makefile.inc
33,90 → 33,58
BFD_ARCH = i386:x86-64
BFD = binary
TARGET = amd64-linux-gnu
TOOLCHAIN_DIR = /usr/local/amd64
TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64
 
FPU_NO_CFLAGS = -mno-sse -mno-sse2
CMN1 = -m64 -mcmodel=kernel -mno-red-zone -fno-unwind-tables
GCC_CFLAGS += $(CMN1)
ICC_CFLAGS += $(CMN1)
SUNCC_CFLAGS += -m64 -xmodel=kernel
 
DEFS += -DMACHINE=$(MACHINE) -D__64_BITS__
DEFS += -D__64_BITS__
 
## Accepted CPUs
#
 
ifeq ($(MACHINE),opteron)
ifeq ($(PROCESSOR),opteron)
CMN2 := -march=opteron
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
SUNCC_CFLAGS += -xtarget=opteron
DEFS += -DFENCES=p4
endif
 
## Own configuration directives
#
 
CONFIG_ACPI = y
 
## Compile with hierarchical page tables support.
#
 
CONFIG_PAGE_PT = y
DEFS += -DCONFIG_PAGE_PT
 
## Compile with i8042 support.
#
 
CONFIG_I8042 = y
DEFS += -DCONFIG_I8042
 
## Accepted configuration directives
#
 
ifeq ($(CONFIG_SMP),y)
DEFS += -DCONFIG_SMP
endif
ifeq ($(CONFIG_HT),y)
DEFS += -DCONFIG_HT
endif
 
ifeq ($(CONFIG_SIMICS_FIX),y)
DEFS += -DCONFIG_SIMICS_FIX
endif
 
ARCH_SOURCES = \
arch/$(ARCH)/src/fpu_context.c \
arch/$(ARCH)/src/boot/boot.S \
arch/$(ARCH)/src/boot/memmap.c \
arch/$(ARCH)/src/pm.c \
arch/$(ARCH)/src/context.S \
arch/$(ARCH)/src/ddi/ddi.c \
arch/$(ARCH)/src/drivers/ega.c \
arch/$(ARCH)/src/drivers/vesa.c \
arch/$(ARCH)/src/drivers/i8254.c \
arch/$(ARCH)/src/drivers/i8259.c \
arch/$(ARCH)/src/delay.S \
arch/$(ARCH)/src/amd64.c \
arch/$(ARCH)/src/bios/bios.c \
arch/$(ARCH)/src/interrupt.c \
arch/$(ARCH)/src/mm/as.c \
arch/$(ARCH)/src/mm/frame.c \
arch/$(ARCH)/src/mm/page.c \
arch/$(ARCH)/src/mm/tlb.c \
arch/$(ARCH)/src/asm_utils.S \
arch/$(ARCH)/src/cpu/cpu.c \
arch/$(ARCH)/src/proc/scheduler.c \
arch/$(ARCH)/src/proc/task.c \
arch/$(ARCH)/src/proc/thread.c \
arch/$(ARCH)/src/userspace.c \
arch/$(ARCH)/src/syscall.c \
arch/$(ARCH)/src/debugger.c
arch/$(KARCH)/src/fpu_context.c \
arch/$(KARCH)/src/boot/boot.S \
arch/$(KARCH)/src/boot/memmap.c \
arch/$(KARCH)/src/pm.c \
arch/$(KARCH)/src/context.S \
arch/$(KARCH)/src/ddi/ddi.c \
arch/$(KARCH)/src/drivers/vesa.c \
arch/$(KARCH)/src/drivers/i8254.c \
arch/$(KARCH)/src/drivers/i8259.c \
arch/$(KARCH)/src/delay.S \
arch/$(KARCH)/src/amd64.c \
arch/$(KARCH)/src/bios/bios.c \
arch/$(KARCH)/src/interrupt.c \
arch/$(KARCH)/src/mm/as.c \
arch/$(KARCH)/src/mm/frame.c \
arch/$(KARCH)/src/mm/page.c \
arch/$(KARCH)/src/mm/tlb.c \
arch/$(KARCH)/src/asm_utils.S \
arch/$(KARCH)/src/cpu/cpu.c \
arch/$(KARCH)/src/proc/scheduler.c \
arch/$(KARCH)/src/proc/task.c \
arch/$(KARCH)/src/proc/thread.c \
arch/$(KARCH)/src/userspace.c \
arch/$(KARCH)/src/syscall.c \
arch/$(KARCH)/src/debugger.c
 
ifeq ($(CONFIG_SMP),y)
ARCH_SOURCES += \
arch/$(ARCH)/src/smp/ap.S \
arch/$(ARCH)/src/smp/apic.c \
arch/$(ARCH)/src/smp/ipi.c \
arch/$(ARCH)/src/smp/mps.c \
arch/$(ARCH)/src/smp/smp.c
arch/$(KARCH)/src/smp/ap.S \
arch/$(KARCH)/src/smp/apic.c \
arch/$(KARCH)/src/smp/ipi.c \
arch/$(KARCH)/src/smp/mps.c \
arch/$(KARCH)/src/smp/smp.c
endif
/branches/dd/kernel/arch/amd64/src/fpu_context.c
39,9 → 39,9
void fpu_context_save(fpu_context_t *fctx)
{
asm volatile (
"fxsave %0"
: "=m"(*fctx)
);
"fxsave %[fctx]\n"
: [fctx] "=m" (*fctx)
);
}
 
/** Restore FPU (mmx,sse) context using fxrstor instruction */
48,9 → 48,9
void fpu_context_restore(fpu_context_t *fctx)
{
asm volatile (
"fxrstor %0"
: "=m"(*fctx)
);
"fxrstor %[fctx]\n"
: [fctx] "=m" (*fctx)
);
}
 
void fpu_init()
57,7 → 57,7
{
/* TODO: Zero all SSE, MMX etc. registers */
asm volatile (
"fninit;"
"fninit\n"
);
}
 
/branches/dd/kernel/arch/amd64/src/cpu/cpu.c
77,21 → 77,19
void cpu_setup_fpu(void)
{
asm volatile (
"movq %%cr0, %%rax;"
"btsq $1, %%rax;" /* cr0.mp */
"btrq $2, %%rax;" /* cr0.em */
"movq %%rax, %%cr0;"
 
"movq %%cr4, %%rax;"
"bts $9, %%rax;" /* cr4.osfxsr */
"movq %%rax, %%cr4;"
:
:
:"%rax"
);
"movq %%cr0, %%rax\n"
"btsq $1, %%rax\n" /* cr0.mp */
"btrq $2, %%rax\n" /* cr0.em */
"movq %%rax, %%cr0\n"
"movq %%cr4, %%rax\n"
"bts $9, %%rax\n" /* cr4.osfxsr */
"movq %%rax, %%cr4\n"
::: "%rax"
);
}
 
/** Set the TS flag to 1.
/** Set the TS flag to 1.
*
* If a thread accesses coprocessor, exception is run, which
* does a lazy fpu context switch.
99,26 → 97,22
*/
void fpu_disable(void)
{
asm volatile (
"mov %%cr0,%%rax;"
"bts $3,%%rax;"
"mov %%rax,%%cr0;"
:
:
:"%rax"
);
asm volatile (
"mov %%cr0, %%rax\n"
"bts $3, %%rax\n"
"mov %%rax, %%cr0\n"
::: "%rax"
);
}
 
void fpu_enable(void)
{
asm volatile (
"mov %%cr0,%%rax;"
"btr $3,%%rax;"
"mov %%rax,%%cr0;"
:
:
:"%rax"
);
asm volatile (
"mov %%cr0, %%rax\n"
"btr $3, %%rax\n"
"mov %%rax, %%cr0\n"
::: "%rax"
);
}
 
void cpu_arch_init(void)
/branches/dd/kernel/arch/amd64/src/amd64.c
39,11 → 39,15
#include <config.h>
 
#include <proc/thread.h>
#include <arch/drivers/ega.h>
#include <genarch/multiboot/multiboot.h>
#include <genarch/drivers/legacy/ia32/io.h>
#include <genarch/drivers/ega/ega.h>
#include <arch/drivers/vesa.h>
#include <genarch/kbd/i8042.h>
#include <genarch/drivers/i8042/i8042.h>
#include <genarch/kbrd/kbrd.h>
#include <arch/drivers/i8254.h>
#include <arch/drivers/i8259.h>
#include <arch/boot/boot.h>
 
#ifdef CONFIG_SMP
#include <arch/smp/apic.h>
62,8 → 66,8
#include <console/console.h>
#include <ddi/irq.h>
#include <ddi/device.h>
#include <sysinfo/sysinfo.h>
 
 
/** Disable I/O on non-privileged levels
*
* Clean IOPL(12,13) and NT(14) flags in EFLAGS register
70,15 → 74,13
*/
static void clean_IOPL_NT_flags(void)
{
asm (
asm volatile (
"pushfq\n"
"pop %%rax\n"
"and $~(0x7000), %%rax\n"
"pushq %%rax\n"
"popfq\n"
:
:
: "%rax"
::: "%rax"
);
}
 
88,16 → 90,31
*/
static void clean_AM_flag(void)
{
asm (
asm volatile (
"mov %%cr0, %%rax\n"
"and $~(0x40000), %%rax\n"
"mov %%rax, %%cr0\n"
:
:
: "%rax"
::: "%rax"
);
}
 
/** Perform amd64-specific initialization before main_bsp() is called.
*
* @param signature Should contain the multiboot signature.
* @param mi Pointer to the multiboot information structure.
*/
void arch_pre_main(uint32_t signature, const multiboot_info_t *mi)
{
/* Parse multiboot information obtained from the bootloader. */
multiboot_info_parse(signature, mi);
#ifdef CONFIG_SMP
/* Copy AP bootstrap routines below 1 MB. */
memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET,
(size_t) &_hardcoded_unmapped_size);
#endif
}
 
void arch_pre_mm_init(void)
{
/* Enable no-execute pages */
139,7 → 156,7
vesa_init();
else
#endif
ega_init(); /* video */
ega_init(EGA_BASE, EGA_VIDEORAM); /* video */
/* Enable debugger */
debugger_init();
172,8 → 189,28
 
void arch_post_smp_init(void)
{
/* keyboard controller */
i8042_init(device_assign_devno(), IRQ_KBD, device_assign_devno(), IRQ_MOUSE);
devno_t devno = device_assign_devno();
 
/*
* Initialize the keyboard module and conect it to stdin. Then
* initialize the i8042 controller and connect it to kbrdin. Enable
* keyboard interrupts.
*/
kbrd_init(stdin);
(void) i8042_init((i8042_t *) I8042_BASE, devno, IRQ_KBD, &kbrdin);
trap_virtual_enable_irqs(1 << IRQ_KBD);
 
/*
* This is the necessary evil until the userspace driver is entirely
* self-sufficient.
*/
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD);
sysinfo_set_item_val("kbd.address.physical", NULL,
(uintptr_t) I8042_BASE);
sysinfo_set_item_val("kbd.address.kernel", NULL,
(uintptr_t) I8042_BASE);
}
 
void calibrate_delay_loop(void)
208,15 → 245,33
*/
void arch_grab_console(void)
{
i8042_grab();
#ifdef CONFIG_FB
vesa_redraw();
#else
ega_redraw();
#endif
}
 
/** Return console to userspace
*
*/
void arch_release_console(void)
{
i8042_release();
}
 
/** Construct function pointer
*
* @param fptr function pointer structure
* @param addr function address
* @param caller calling function address
*
* @return address of the function pointer
*
*/
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
{
return addr;
}
 
/** @}
*/
/branches/dd/kernel/arch/amd64/src/pm.c
155,7 → 155,7
 
void tss_initialize(tss_t *t)
{
memsetb((uintptr_t) t, sizeof(tss_t), 0);
memsetb(t, sizeof(tss_t), 0);
}
 
/*
209,7 → 209,7
 
tss_p = (struct tss *) malloc(sizeof(tss_t), FRAME_ATOMIC);
if (!tss_p)
panic("could not allocate TSS\n");
panic("Cannot allocate TSS.");
}
 
tss_initialize(tss_p);
239,7 → 239,7
preemption_disable();
ipl_t ipl = interrupts_disable();
memsetb((uintptr_t) idt, sizeof(idt), 0);
memsetb(idt, sizeof(idt), 0);
idtr_load(&idtr);
interrupts_restore(ipl);
/branches/dd/kernel/arch/amd64/src/asm_utils.S
26,23 → 26,17
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
#define IREGISTER_SPACE 120
#define IREGISTER_SPACE 72
 
#define IOFFSET_RAX 0x0
#define IOFFSET_RBX 0x8
#define IOFFSET_RCX 0x10
#define IOFFSET_RDX 0x18
#define IOFFSET_RSI 0x20
#define IOFFSET_RDI 0x28
#define IOFFSET_R8 0x30
#define IOFFSET_R9 0x38
#define IOFFSET_R10 0x40
#define IOFFSET_R11 0x48
#define IOFFSET_R12 0x50
#define IOFFSET_R13 0x58
#define IOFFSET_R14 0x60
#define IOFFSET_R15 0x68
#define IOFFSET_RBP 0x70
#define IOFFSET_RAX 0x0
#define IOFFSET_RCX 0x8
#define IOFFSET_RDX 0x10
#define IOFFSET_RSI 0x18
#define IOFFSET_RDI 0x20
#define IOFFSET_R8 0x28
#define IOFFSET_R9 0x30
#define IOFFSET_R10 0x38
#define IOFFSET_R11 0x40
 
# Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error word
# and 1 means interrupt with error word
65,6 → 59,8
.global get_cycle
.global read_efer_flag
.global set_efer_flag
.global memsetb
.global memsetw
.global memcpy
.global memcpy_from_uspace
.global memcpy_to_uspace
71,6 → 67,14
.global memcpy_from_uspace_failover_address
.global memcpy_to_uspace_failover_address
 
# Wrapper for generic memsetb
memsetb:
jmp _memsetb
 
# Wrapper for generic memsetw
memsetw:
jmp _memsetw
 
#define MEMCPY_DST %rdi
#define MEMCPY_SRC %rsi
#define MEMCPY_SIZE %rdx
88,12 → 92,12
* @param MEMCPY_SRC Source address.
* @param MEMCPY_SIZE Number of bytes to copy.
*
* @retrun MEMCPY_SRC on success, 0 on failure.
* @retrun MEMCPY_DST on success, 0 on failure.
*/
memcpy:
memcpy_from_uspace:
memcpy_to_uspace:
movq MEMCPY_SRC, %rax
movq MEMCPY_DST, %rax
 
movq MEMCPY_SIZE, %rcx
shrq $3, %rcx /* size / 8 */
163,7 → 167,7
rdmsr
ret
 
# Push all general purpose registers on stack except %rbp, %rsp
# Push all volatile general purpose registers on stack
.macro save_all_gpr
movq %rax, IOFFSET_RAX(%rsp)
movq %rcx, IOFFSET_RCX(%rsp)
174,14 → 178,6
movq %r9, IOFFSET_R9(%rsp)
movq %r10, IOFFSET_R10(%rsp)
movq %r11, IOFFSET_R11(%rsp)
#ifdef CONFIG_DEBUG_ALLREGS
movq %rbx, IOFFSET_RBX(%rsp)
movq %rbp, IOFFSET_RBP(%rsp)
movq %r12, IOFFSET_R12(%rsp)
movq %r13, IOFFSET_R13(%rsp)
movq %r14, IOFFSET_R14(%rsp)
movq %r15, IOFFSET_R15(%rsp)
#endif
.endm
 
.macro restore_all_gpr
194,21 → 190,9
movq IOFFSET_R9(%rsp), %r9
movq IOFFSET_R10(%rsp), %r10
movq IOFFSET_R11(%rsp), %r11
#ifdef CONFIG_DEBUG_ALLREGS
movq IOFFSET_RBX(%rsp), %rbx
movq IOFFSET_RBP(%rsp), %rbp
movq IOFFSET_R12(%rsp), %r12
movq IOFFSET_R13(%rsp), %r13
movq IOFFSET_R14(%rsp), %r14
movq IOFFSET_R15(%rsp), %r15
#endif
.endm
 
#ifdef CONFIG_DEBUG_ALLREGS
# define INTERRUPT_ALIGN 256
#else
# define INTERRUPT_ALIGN 128
#endif
#define INTERRUPT_ALIGN 128
## Declare interrupt handlers
#
/branches/dd/kernel/arch/amd64/src/proc/scheduler.c
39,7 → 39,6
#include <arch.h>
#include <arch/context.h> /* SP_DELTA */
#include <arch/asm.h>
#include <arch/debugger.h>
#include <print.h>
#include <arch/pm.h>
#include <arch/ddi/ddi.h>
68,13 → 67,6
 
/* TLS support - set FS to thread local storage */
write_msr(AMD_MSR_FS, THREAD->arch.tls);
 
#ifdef CONFIG_DEBUG_AS_WATCHPOINT
/* Set watchpoint on AS to ensure that nobody sets it to zero */
if (CPU->id < BKPOINTS_MAX)
breakpoint_add(&((the_t *) THREAD->kstack)->as,
BKPOINT_WRITE | BKPOINT_CHECK_ZERO, CPU->id);
#endif
}
 
void after_thread_ran_arch(void)
/branches/dd/kernel/arch/amd64/src/proc/thread.c
46,7 → 46,7
* Kernel RSP can be precalculated at thread creation time.
*/
t->arch.syscall_rsp[SYSCALL_KSTACK_RSP] =
(uintptr_t)&t->kstack[PAGE_SIZE - sizeof(uint64_t)];
(uintptr_t) &t->kstack[PAGE_SIZE - sizeof(uint64_t)];
}
 
/** @}
/branches/dd/kernel/arch/amd64/src/boot/boot.S
1,4 → 1,4
 
#
# Copyright (c) 2005 Ondrej Palkovsky
# Copyright (c) 2006 Martin Decky
# Copyright (c) 2008 Jakub Jermar
175,119 → 175,18
.code64
start64:
movq $(PA2KA(START_STACK)), %rsp
movl grub_eax, %eax
movl grub_ebx, %ebx
 
# arch_pre_main(grub_eax, grub_ebx)
xorq %rdi, %rdi
movl grub_eax, %edi
xorq %rsi, %rsi
movl grub_ebx, %esi
call arch_pre_main
 
call main_bsp
 
# Not reached.
cmpl $MULTIBOOT_LOADER_MAGIC, %eax # compare GRUB signature
je valid_boot
xorl %ecx, %ecx # no memory size or map available
movl %ecx, e820counter
jmp invalid_boot
valid_boot:
movl (%ebx), %eax # ebx = physical address of struct multiboot_info
bt $3, %eax # mbi->flags[3] (mods_count, mods_addr valid)
jc mods_valid
xorq %rcx, %rcx
movq %rcx, init
jmp mods_end
mods_valid:
xorq %rcx, %rcx
movl 20(%ebx), %ecx # mbi->mods_count
movq %rcx, init
cmpl $0, %ecx
je mods_end
movl 24(%ebx), %esi # mbi->mods_addr
movq $init, %rdi
mods_loop:
xorq %rdx, %rdx
movl 0(%esi), %edx # mods->mod_start
movq $0xffff800000000000, %r10
addq %r10, %rdx
movq %rdx, 8(%rdi)
xorq %rdx, %rdx
movl 4(%esi), %edx
subl 0(%esi), %edx # mods->mod_end - mods->mod_start
movq %rdx, 16(%rdi)
addl $16, %esi
addq $16, %rdi
loop mods_loop
mods_end:
bt $6, %eax # mbi->flags[6] (mmap_length, mmap_addr valid)
jc mmap_valid
xorl %edx, %edx
jmp mmap_invalid
mmap_valid:
movl 44(%ebx), %ecx # mbi->mmap_length
movl 48(%ebx), %esi # mbi->mmap_addr
movq $e820table, %rdi
xorl %edx, %edx
mmap_loop:
cmpl $0, %ecx
jle mmap_end
movl 4(%esi), %eax # mmap->base_addr_low
movl %eax, (%rdi)
movl 8(%esi), %eax # mmap->base_addr_high
movl %eax, 4(%rdi)
movl 12(%esi), %eax # mmap->length_low
movl %eax, 8(%rdi)
movl 16(%esi), %eax # mmap->length_high
movl %eax, 12(%rdi)
movl 20(%esi), %eax # mmap->type
movl %eax, 16(%rdi)
movl (%esi), %eax # mmap->size
addl $0x4, %eax
addl %eax, %esi
subl %eax, %ecx
addq $MEMMAP_E820_RECORD_SIZE, %rdi
incl %edx
jmp mmap_loop
mmap_end:
mmap_invalid:
movl %edx, e820counter
invalid_boot:
#ifdef CONFIG_SMP
# copy AP bootstrap routines below 1 MB
movq $BOOT_OFFSET, %rsi
movq $AP_BOOT_OFFSET, %rdi
movq $_hardcoded_unmapped_size, %rcx
rep movsb
#endif
call main_bsp # never returns
cli
hlt
 
427,7 → 326,8
xor %dx, %dx
int $0x10
jmp vga_not_compat
cmp $0x00, %ah
je vga_not_compat
vga_compat:
/branches/dd/kernel/arch/amd64/src/debugger.c
54,6 → 54,8
static bpinfo_t breakpoints[BKPOINTS_MAX];
SPINLOCK_INITIALIZE(bkpoint_lock);
 
#ifdef CONFIG_KCONSOLE
 
static int cmd_print_breakpoints(cmd_arg_t *argv);
static cmd_info_t bkpts_info = {
.name = "bkpts",
62,8 → 64,6
.argc = 0,
};
 
#ifndef CONFIG_DEBUG_AS_WATCHPOINT
 
static int cmd_del_breakpoint(cmd_arg_t *argv);
static cmd_arg_t del_argv = {
.type = ARG_TYPE_INT
99,36 → 99,8
.argv = &addw_argv
};
 
#endif
#endif /* CONFIG_KCONSOLE */
 
/** Print table of active breakpoints */
int cmd_print_breakpoints(cmd_arg_t *argv __attribute__((unused)))
{
unsigned int i;
char *symbol;
if (sizeof(void *) == 4) {
printf("# Count Address In symbol\n");
printf("-- ----- ---------- ---------\n");
} else {
printf("# Count Address In symbol\n");
printf("-- ----- ------------------ ---------\n");
}
for (i = 0; i < BKPOINTS_MAX; i++)
if (breakpoints[i].address) {
symbol = get_symtab_entry(breakpoints[i].address);
if (sizeof(void *) == 4)
printf("%-2u %-5d %#10zx %s\n", i, breakpoints[i].counter,
breakpoints[i].address, symbol);
else
printf("%-2u %-5d %#18zx %s\n", i, breakpoints[i].counter,
breakpoints[i].address, symbol);
}
return 1;
}
 
/* Setup DR register according to table */
static void setup_dr(int curidx)
{
162,19 → 134,23
if ((flags & BKPOINT_INSTR)) {
;
} else {
if (sizeof(int) == 4)
dr7 |= ((unative_t) 0x3) << (18 + 4*curidx);
else /* 8 */
dr7 |= ((unative_t) 0x2) << (18 + 4*curidx);
#ifdef __32_BITS__
dr7 |= ((unative_t) 0x3) << (18 + 4 * curidx);
#endif
 
#ifdef __64_BITS__
dr7 |= ((unative_t) 0x2) << (18 + 4 * curidx);
#endif
if ((flags & BKPOINT_WRITE))
dr7 |= ((unative_t) 0x1) << (16 + 4*curidx);
dr7 |= ((unative_t) 0x1) << (16 + 4 * curidx);
else if ((flags & BKPOINT_READ_WRITE))
dr7 |= ((unative_t) 0x3) << (16 + 4*curidx);
dr7 |= ((unative_t) 0x3) << (16 + 4 * curidx);
}
 
/* Enable global breakpoint */
dr7 |= 0x2 << (curidx*2);
dr7 |= 0x2 << (curidx * 2);
 
write_dr7(dr7);
225,16 → 201,16
 
/* Send IPI */
#ifdef CONFIG_SMP
// ipi_broadcast(VECTOR_DEBUG_IPI);
// ipi_broadcast(VECTOR_DEBUG_IPI);
#endif
 
return curidx;
}
 
#ifdef amd64
# define getip(x) ((x)->rip)
#ifdef __64_BITS__
#define getip(x) ((x)->rip)
#else
# define getip(x) ((x)->eip)
#define getip(x) ((x)->eip)
#endif
 
static void handle_exception(int slot, istate_t *istate)
246,19 → 222,21
if ((breakpoints[slot].flags & BKPOINT_CHECK_ZERO)) {
if (*((unative_t *) breakpoints[slot].address) != 0)
return;
printf("**** Found ZERO on address %lx (slot %d) ****\n",
breakpoints[slot].address, slot);
printf("*** Found ZERO on address %lx (slot %d) ***\n",
breakpoints[slot].address, slot);
} else {
printf("Data watchpoint - new data: %lx\n",
*((unative_t *) breakpoints[slot].address));
*((unative_t *) breakpoints[slot].address));
}
}
printf("Reached breakpoint %d:%lx(%s)\n", slot, getip(istate),
get_symtab_entry(getip(istate)));
printf("***Type 'exit' to exit kconsole.\n");
atomic_set(&haltstate,1);
kconsole((void *) "debug");
atomic_set(&haltstate,0);
get_symtab_entry(getip(istate)));
 
#ifdef CONFIG_KCONSOLE
atomic_set(&haltstate, 1);
kconsole("debug", "Debug console ready (type 'exit' to continue)\n", false);
atomic_set(&haltstate, 0);
#endif
}
 
void breakpoint_del(int slot)
287,42 → 265,8
#endif
}
 
#ifndef CONFIG_DEBUG_AS_WATCHPOINT
 
/** Remove breakpoint from table */
int cmd_del_breakpoint(cmd_arg_t *argv)
{
unative_t bpno = argv->intval;
if (bpno > BKPOINTS_MAX) {
printf("Invalid breakpoint number.\n");
return 0;
}
breakpoint_del(argv->intval);
return 1;
}
 
/** Add new breakpoint to table */
static int cmd_add_breakpoint(cmd_arg_t *argv)
{
int flags;
int id;
 
if (argv == &add_argv) {
flags = BKPOINT_INSTR;
} else { /* addwatchp */
flags = BKPOINT_WRITE;
}
printf("Adding breakpoint on address: %p\n", argv->intval);
id = breakpoint_add((void *)argv->intval, flags, -1);
if (id < 0)
printf("Add breakpoint failed.\n");
else
printf("Added breakpoint %d.\n", id);
return 1;
}
#endif
 
static void debug_exception(int n __attribute__((unused)), istate_t *istate)
{
unative_t dr6;
329,7 → 273,7
int i;
/* Set RF to restart the instruction */
#ifdef amd64
#ifdef __64_BITS__
istate->rflags |= RFLAGS_RF;
#else
istate->eflags |= EFLAGS_RF;
347,7 → 291,9
}
 
#ifdef CONFIG_SMP
static void debug_ipi(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
static void
debug_ipi(int n __attribute__((unused)),
istate_t *istate __attribute__((unused)))
{
int i;
 
363,34 → 309,103
{
int i;
 
for (i=0; i<BKPOINTS_MAX; i++)
for (i = 0; i < BKPOINTS_MAX; i++)
breakpoints[i].address = NULL;
 
#ifdef CONFIG_KCONSOLE
cmd_initialize(&bkpts_info);
if (!cmd_register(&bkpts_info))
panic("could not register command %s\n", bkpts_info.name);
printf("Cannot register command %s\n", bkpts_info.name);
 
#ifndef CONFIG_DEBUG_AS_WATCHPOINT
cmd_initialize(&delbkpt_info);
if (!cmd_register(&delbkpt_info))
panic("could not register command %s\n", delbkpt_info.name);
printf("Cannot register command %s\n", delbkpt_info.name);
 
cmd_initialize(&addbkpt_info);
if (!cmd_register(&addbkpt_info))
panic("could not register command %s\n", addbkpt_info.name);
printf("Cannot register command %s\n", addbkpt_info.name);
 
cmd_initialize(&addwatchp_info);
if (!cmd_register(&addwatchp_info))
panic("could not register command %s\n", addwatchp_info.name);
#endif
printf("Cannot register command %s\n", addwatchp_info.name);
#endif /* CONFIG_KCONSOLE */
exc_register(VECTOR_DEBUG, "debugger",
debug_exception);
exc_register(VECTOR_DEBUG, "debugger", debug_exception);
#ifdef CONFIG_SMP
exc_register(VECTOR_DEBUG_IPI, "debugger_smp",
debug_ipi);
exc_register(VECTOR_DEBUG_IPI, "debugger_smp", debug_ipi);
#endif
}
 
#ifdef CONFIG_KCONSOLE
/** Print table of active breakpoints */
int cmd_print_breakpoints(cmd_arg_t *argv __attribute__((unused)))
{
unsigned int i;
char *symbol;
 
#ifdef __32_BITS__
printf("# Count Address In symbol\n");
printf("-- ----- ---------- ---------\n");
#endif
 
#ifdef __64_BITS__
printf("# Count Address In symbol\n");
printf("-- ----- ------------------ ---------\n");
#endif
for (i = 0; i < BKPOINTS_MAX; i++)
if (breakpoints[i].address) {
symbol = get_symtab_entry(breakpoints[i].address);
 
#ifdef __32_BITS__
printf("%-2u %-5d %#10zx %s\n", i,
breakpoints[i].counter, breakpoints[i].address,
symbol);
#endif
 
#ifdef __64_BITS__
printf("%-2u %-5d %#18zx %s\n", i,
breakpoints[i].counter, breakpoints[i].address,
symbol);
#endif
 
}
return 1;
}
 
/** Remove breakpoint from table */
int cmd_del_breakpoint(cmd_arg_t *argv)
{
unative_t bpno = argv->intval;
if (bpno > BKPOINTS_MAX) {
printf("Invalid breakpoint number.\n");
return 0;
}
breakpoint_del(argv->intval);
return 1;
}
 
/** Add new breakpoint to table */
static int cmd_add_breakpoint(cmd_arg_t *argv)
{
int flags;
int id;
 
if (argv == &add_argv) {
flags = BKPOINT_INSTR;
} else { /* addwatchp */
flags = BKPOINT_WRITE;
}
printf("Adding breakpoint on address: %p\n", argv->intval);
id = breakpoint_add((void *)argv->intval, flags, -1);
if (id < 0)
printf("Add breakpoint failed.\n");
else
printf("Added breakpoint %d.\n", id);
return 1;
}
#endif /* CONFIG_KCONSOLE */
 
/** @}
*/
/branches/dd/kernel/arch/amd64/src/mm/page.c
180,7 → 180,7
page = read_cr2();
if (istate->error_word & PFERR_CODE_RSVD)
panic("Reserved bit set in page table entry.\n");
panic("Reserved bit set in page table entry.");
if (istate->error_word & PFERR_CODE_RW)
access = PF_ACCESS_WRITE;
190,11 → 190,11
access = PF_ACCESS_READ;
if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate, "Page fault: %#x", page);
fault_if_from_uspace(istate, "Page fault: %#x.", page);
 
decode_istate(n, istate);
printf("Page fault address: %llx\n", page);
panic("page fault\n");
printf("Page fault address: %llx.\n", page);
panic("Page fault.");
}
}
 
202,7 → 202,7
uintptr_t hw_map(uintptr_t physaddr, size_t size)
{
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
panic("Unable to map physical memory %p (%d bytes)", physaddr, size)
panic("Unable to map physical memory %p (%d bytes).", physaddr, size)
uintptr_t virtaddr = PA2KA(last_frame);
pfn_t i;
/branches/dd/kernel/arch/amd64/src/userspace.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup amd64
/** @addtogroup amd64
* @{
*/
/** @file
47,34 → 47,33
*/
void userspace(uspace_arg_t *kernel_uarg)
{
ipl_t ipl;
ipl_t ipl = interrupts_disable();
ipl = interrupts_disable();
 
/* Clear CF,PF,AF,ZF,SF,DF,OF */
/* Clear CF, PF, AF, ZF, SF, DF, OF */
ipl &= ~(0xcd4);
 
asm volatile (""
"pushq %0\n"
"pushq %1\n"
"pushq %2\n"
"pushq %3\n"
"pushq %4\n"
"movq %5, %%rax\n"
"iretq\n"
: :
"i" (gdtselector(UDATA_DES) | PL_USER),
"r" (kernel_uarg->uspace_stack+THREAD_STACK_SIZE),
"r" (ipl),
"i" (gdtselector(UTEXT_DES) | PL_USER),
"r" (kernel_uarg->uspace_entry),
"r" (kernel_uarg->uspace_uarg)
: "rax"
);
asm volatile (
"pushq %[udata_des]\n"
"pushq %[stack_size]\n"
"pushq %[ipl]\n"
"pushq %[utext_des]\n"
"pushq %[entry]\n"
"movq %[uarg], %%rax\n"
/* %rdi is defined to hold pcb_ptr - set it to 0 */
"xorq %%rdi, %%rdi\n"
"iretq\n"
:: [udata_des] "i" (gdtselector(UDATA_DES) | PL_USER),
[stack_size] "r" (kernel_uarg->uspace_stack + THREAD_STACK_SIZE),
[ipl] "r" (ipl),
[utext_des] "i" (gdtselector(UTEXT_DES) | PL_USER),
[entry] "r" (kernel_uarg->uspace_entry),
[uarg] "r" (kernel_uarg->uspace_uarg)
: "rax"
);
/* Unreachable */
for(;;)
;
while (1);
}
 
/** @}
/branches/dd/kernel/arch/amd64/src/interrupt.c
80,12 → 80,6
istate->rdi, istate->r8);
printf("%%r9=%#llx, %%r10=%#llx, %%r11=%#llx\n", istate->r9,
istate->r10, istate->r11);
#ifdef CONFIG_DEBUG_ALLREGS
printf("%%r12=%#llx, %%r13=%#llx, %%r14=%#llx\n", istate->r12,
istate->r13, istate->r14);
printf("%%r15=%#llx, %%rbx=%#llx, %%rbp=%#llx\n", istate->r15,
istate->rbx, &istate->rbp);
#endif
printf("%%rsp=%#llx\n", &istate->stack[0]);
}
 
94,15 → 88,15
if (eoi_function)
eoi_function();
else
panic("no eoi_function\n");
panic("No eoi_function.");
 
}
 
static void null_interrupt(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "unserviced interrupt: %d", n);
fault_if_from_uspace(istate, "Unserviced interrupt: %d.", n);
decode_istate(n, istate);
panic("unserviced interrupt\n");
panic("Unserviced interrupt.");
}
 
/** General Protection Fault. */
126,35 → 120,37
io_perm_bitmap_install();
return;
}
fault_if_from_uspace(istate, "general protection fault");
fault_if_from_uspace(istate, "General protection fault.");
}
 
decode_istate(n, istate);
panic("general protection fault\n");
panic("General protection fault.");
}
 
static void ss_fault(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "stack fault");
fault_if_from_uspace(istate, "Stack fault.");
decode_istate(n, istate);
panic("stack fault\n");
panic("Stack fault.");
}
 
static void nm_fault(int n, istate_t *istate)
{
#ifdef CONFIG_FPU_LAZY
#ifdef CONFIG_FPU_LAZY
scheduler_fpu_lazy_request();
#else
fault_if_from_uspace(istate, "fpu fault");
panic("fpu fault");
fault_if_from_uspace(istate, "FPU fault.");
panic("FPU fault.");
#endif
}
 
#ifdef CONFIG_SMP
static void tlb_shootdown_ipi(int n, istate_t *istate)
{
trap_virtual_eoi();
tlb_shootdown_ipi_recv();
}
#endif
 
/** Handler of IRQ exceptions */
static void irq_interrupt(int n, istate_t *istate)
177,7 → 173,7
trap_virtual_eoi();
ack = true;
}
irq->handler(irq, irq->arg);
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
/*
221,7 → 217,7
if (enable_irqs_function)
enable_irqs_function(irqmask);
else
panic("no enable_irqs_function\n");
panic("No enable_irqs_function.");
}
 
void trap_virtual_disable_irqs(uint16_t irqmask)
229,7 → 225,7
if (disable_irqs_function)
disable_irqs_function(irqmask);
else
panic("no disable_irqs_function\n");
panic("No disable_irqs_function.");
}
 
/** @}
/branches/dd/kernel/arch/mips32/_link.ld.in
1,15 → 1,17
/*
* MIPS32 linker script
*
* MIPS32 linker script
*
* kernel text
* kernel data
*
*
*/
 
#undef mips
#define mips mips
 
#define KERNEL_LOAD_ADDRESS 0x80100000
 
OUTPUT_ARCH(mips)
 
ENTRY(kernel_image_start)
 
SECTIONS {
21,9 → 23,9
}
.data : {
kdata_start = .;
*(.data); /* initialized data */
*(.data); /* initialized data */
hardcoded_ktext_size = .;
LONG(ktext_end - ktext_start);
LONG(ktext_end - ktext_start);
hardcoded_kdata_size = .;
LONG(kdata_end - kdata_start);
hardcoded_load_address = .;
33,21 → 35,21
*(.reginfo);
*(.sbss);
*(.scommon);
*(.bss); /* uninitialized static variables */
*(COMMON); /* global variables */
*(.bss); /* uninitialized static variables */
*(COMMON); /* global variables */
symbol_table = .;
*(symtab.*);
*(symtab.*);
}
_gp = . + 0x8000;
.lit8 : { *(.lit8) }
.lit4 : { *(.lit4) }
 
kdata_end = .;
 
/DISCARD/ : {
*(.mdebug*);
*(.pdr);
*(.comment);
*(.note);
*(.mdebug*);
*(.pdr);
*(.comment);
*(.note);
}
}
/branches/dd/kernel/arch/mips32/include/boot.h
File deleted
/branches/dd/kernel/arch/mips32/include/context_offset.h
76,26 → 76,17
#define EOFFSET_T5 0x30
#define EOFFSET_T6 0x34
#define EOFFSET_T7 0x38
#define EOFFSET_S0 0x3c
#define EOFFSET_S1 0x40
#define EOFFSET_S2 0x44
#define EOFFSET_S3 0x48
#define EOFFSET_S4 0x4c
#define EOFFSET_S5 0x50
#define EOFFSET_S6 0x54
#define EOFFSET_S7 0x58
#define EOFFSET_T8 0x5c
#define EOFFSET_T9 0x60
#define EOFFSET_GP 0x64
#define EOFFSET_SP 0x68
#define EOFFSET_S8 0x6c
#define EOFFSET_RA 0x70
#define EOFFSET_LO 0x74
#define EOFFSET_HI 0x78
#define EOFFSET_STATUS 0x7c
#define EOFFSET_EPC 0x80
#define EOFFSET_K1 0x84
#define REGISTER_SPACE 136
#define EOFFSET_T8 0x3c
#define EOFFSET_T9 0x40
#define EOFFSET_GP 0x44
#define EOFFSET_SP 0x48
#define EOFFSET_RA 0x4c
#define EOFFSET_LO 0x50
#define EOFFSET_HI 0x54
#define EOFFSET_STATUS 0x58
#define EOFFSET_EPC 0x5c
#define EOFFSET_K1 0x60
#define REGISTER_SPACE 100
 
#ifdef __ASM__
 
114,10 → 105,10
sw $s8,OFFSET_S8(\ctx)
sw $gp,OFFSET_GP(\ctx)
 
#ifndef KERNEL
#ifndef KERNEL
sw $k1,OFFSET_TLS(\ctx)
 
# ifdef CONFIG_MIPS_FPU
#ifdef CONFIG_FPU
mfc1 $t0,$20
sw $t0, OFFSET_F20(\ctx)
 
150,7 → 141,7
mfc1 $t0,$30
sw $t0, OFFSET_F30(\ctx)
# endif /* CONFIG_MIPS_FPU */
#endif /* CONFIG_FPU */
#endif /* KERNEL */
 
sw $ra,OFFSET_PC(\ctx)
172,7 → 163,7
#ifndef KERNEL
lw $k1,OFFSET_TLS(\ctx)
 
# ifdef CONFIG_MIPS_FPU
#ifdef CONFIG_FPU
lw $t0, OFFSET_F20(\ctx)
mtc1 $t0,$20
 
205,9 → 196,9
 
lw $t0, OFFSET_F30(\ctx)
mtc1 $t0,$30
# endif /* CONFIG_MIPS_FPU */
#endif /* CONFIG_FPU */
#endif /* KERNEL */
 
lw $ra,OFFSET_PC(\ctx)
lw $sp,OFFSET_SP(\ctx)
.endm
/branches/dd/kernel/arch/mips32/include/asm/boot.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32
/** @addtogroup mips32
* @{
*/
/** @file
/branches/dd/kernel/arch/mips32/include/interrupt.h
38,9 → 38,11
#include <typedefs.h>
#include <arch/exception.h>
 
#define IVT_ITEMS 32
#define IVT_FIRST 0
#define IVT_ITEMS 32
#define IVT_FIRST 0
 
#define VECTOR_TLB_SHOOTDOWN_IPI EXC_Int
 
extern function virtual_timer_fnc;
extern uint32_t count_hi;
 
/branches/dd/kernel/arch/mips32/include/exception.h
73,19 → 73,10
uint32_t t5;
uint32_t t6;
uint32_t t7;
uint32_t s0;
uint32_t s1;
uint32_t s2;
uint32_t s3;
uint32_t s4;
uint32_t s5;
uint32_t s6;
uint32_t s7;
uint32_t t8;
uint32_t t9;
uint32_t gp;
uint32_t sp;
uint32_t s8;
uint32_t ra;
uint32_t lo;
/branches/dd/kernel/arch/mips32/include/console.h
35,8 → 35,6
#ifndef KERN_mips32_CONSOLE_H_
#define KERN_mips32_CONSOLE_H_
 
extern void console_init(devno_t devno);
 
#endif
 
/** @}
/branches/dd/kernel/arch/mips32/include/types.h
35,10 → 35,6
#ifndef KERN_mips32_TYPES_H_
#define KERN_mips32_TYPES_H_
 
#define NULL 0
#define false 0
#define true 1
 
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed long int32_t;
61,14 → 57,32
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef uint8_t bool;
typedef uint64_t thread_id_t;
typedef uint64_t task_id_t;
typedef uint32_t context_id_t;
typedef struct {
} fncptr_t;
 
typedef int32_t inr_t;
typedef int32_t devno_t;
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
#define PRIi "u" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
#define PRId32 "ld" /**< Format for int32_t. */
#define PRId64 "lld" /**< Format for int64_t. */
#define PRIdn "d" /**< Format for native_t. */
 
#define PRIu8 "u" /**< Format for uint8_t. */
#define PRIu16 "u" /**< Format for uint16_t. */
#define PRIu32 "u" /**< Format for uint32_t. */
#define PRIu64 "llu" /**< Format for uint64_t. */
#define PRIun "u" /**< Format for unative_t. */
 
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */
#define PRIx64 "llx" /**< Format for hexadecimal (u)int64_t. */
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */
 
/** Page Table Entry. */
typedef struct {
unsigned g : 1; /**< Global bit. */
/branches/dd/kernel/arch/mips32/include/memstr.h
37,10 → 37,10
 
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt))
 
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x);
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x);
extern void memsetw(void *dst, size_t cnt, uint16_t x);
extern void memsetb(void *dst, size_t cnt, uint8_t x);
 
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt);
extern int memcmp(const void *a, const void *b, size_t cnt);
 
#endif
 
/branches/dd/kernel/arch/mips32/include/smp/order.h
File deleted
/branches/dd/kernel/arch/mips32/include/smp/dorder.h
0,0 → 1,34
/*
* Copyright (c) 2007 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#ifndef KERN_mips32_DORDER_H_
#define KERN_mips32_DORDER_H_
 
extern void ipi_broadcast_arch(int ipi);
 
#endif
/branches/dd/kernel/arch/mips32/include/atomic.h
35,14 → 35,14
#ifndef KERN_mips32_ATOMIC_H_
#define KERN_mips32_ATOMIC_H_
 
#define atomic_inc(x) ((void) atomic_add(x, 1))
#define atomic_dec(x) ((void) atomic_add(x, -1))
#define atomic_inc(x) ((void) atomic_add(x, 1))
#define atomic_dec(x) ((void) atomic_add(x, -1))
 
#define atomic_postinc(x) (atomic_add(x, 1) - 1)
#define atomic_postdec(x) (atomic_add(x, -1) + 1)
#define atomic_postinc(x) (atomic_add(x, 1) - 1)
#define atomic_postdec(x) (atomic_add(x, -1) + 1)
 
#define atomic_preinc(x) atomic_add(x, 1)
#define atomic_predec(x) atomic_add(x, -1)
#define atomic_preinc(x) atomic_add(x, 1)
#define atomic_predec(x) atomic_add(x, -1)
 
/* Atomic addition of immediate value.
*
54,19 → 54,37
static inline long atomic_add(atomic_t *val, int i)
{
long tmp, v;
 
asm volatile (
"1:\n"
" ll %0, %1\n"
" addiu %0, %0, %3\n" /* same as addi, but never traps on overflow */
" move %2, %0\n"
" addu %0, %0, %3\n" /* same as addi, but never traps on overflow */
" move %2, %0\n"
" sc %0, %1\n"
" beq %0, %4, 1b\n" /* if the atomic operation failed, try again */
" beq %0, %4, 1b\n" /* if the atomic operation failed, try again */
" nop\n"
: "=r" (tmp), "=m" (val->count), "=r" (v)
: "i" (i), "i" (0)
);
: "=&r" (tmp), "+m" (val->count), "=&r" (v)
: "r" (i), "i" (0)
);
return v;
}
 
static inline uint32_t test_and_set(atomic_t *val) {
uint32_t tmp, v;
asm volatile (
"1:\n"
" ll %2, %1\n"
" bnez %2, 2f\n"
" li %0, %3\n"
" sc %0, %1\n"
" beqz %0, 1b\n"
"2:\n"
: "=&r" (tmp), "+m" (val->count), "=&r" (v)
: "i" (1)
);
return v;
}
 
/branches/dd/kernel/arch/mips32/include/arch.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32
/** @addtogroup mips32
* @{
*/
/** @file
35,6 → 35,29
#ifndef KERN_mips32_ARCH_H_
#define KERN_mips32_ARCH_H_
 
#define TASKMAP_MAX_RECORDS 32
#define CPUMAP_MAX_RECORDS 32
 
#define BOOTINFO_TASK_NAME_BUFLEN 32
 
#include <typedefs.h>
 
extern count_t cpu_count;
 
typedef struct {
uintptr_t addr;
uint32_t size;
char name[BOOTINFO_TASK_NAME_BUFLEN];
} utask_t;
 
typedef struct {
uint32_t cpumap;
uint32_t cnt;
utask_t tasks[TASKMAP_MAX_RECORDS];
} bootinfo_t;
 
extern void arch_pre_main(void *entry, bootinfo_t *bootinfo);
 
#endif
 
/** @}
/branches/dd/kernel/arch/mips32/include/asm.h
36,6 → 36,7
#define KERN_mips32_ASM_H_
 
#include <arch/types.h>
#include <typedefs.h>
#include <config.h>
 
 
55,7 → 56,11
{
uintptr_t v;
asm volatile ("and %0, $29, %1\n" : "=r" (v) : "r" (~(STACK_SIZE-1)));
asm volatile (
"and %0, $29, %1\n"
: "=r" (v)
: "r" (~(STACK_SIZE-1))
);
return v;
}
63,13 → 68,44
extern void cpu_halt(void);
extern void asm_delay_loop(uint32_t t);
extern void userspace_asm(uintptr_t ustack, uintptr_t uspace_uarg,
uintptr_t entry);
uintptr_t entry);
 
extern ipl_t interrupts_disable(void);
extern ipl_t interrupts_enable(void);
extern void interrupts_restore(ipl_t ipl);
extern ipl_t interrupts_read(void);
extern void asm_delay_loop(uint32_t t);
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
#endif
 
/** @}
/branches/dd/kernel/arch/mips32/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32mm
/** @addtogroup mips32mm
* @{
*/
/** @file
35,12 → 35,14
#ifndef KERN_mips32_FRAME_H_
#define KERN_mips32_FRAME_H_
 
#define FRAME_WIDTH 14 /* 16K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
#define FRAME_WIDTH 14 /* 16K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
 
#ifdef KERNEL
#ifndef __ASM__
 
#include <typedefs.h>
 
extern void frame_arch_init(void);
extern void physmem_print(void);
 
/branches/dd/kernel/arch/mips32/include/mm/page.h
40,8 → 40,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifndef __ASM__
# define KA2PA(x) (((uintptr_t) (x)) - 0x80000000)
# define PA2KA(x) (((uintptr_t) (x)) + 0x80000000)
/branches/dd/kernel/arch/mips32/include/mm/asid.h
37,7 → 37,7
 
#include <arch/types.h>
 
#define ASID_MAX_ARCH 255 /* 2^8 - 1 */
#define ASID_MAX_ARCH 255 /* 2^8 - 1 */
 
typedef uint8_t asid_t;
 
/branches/dd/kernel/arch/mips32/include/mm/tlb.h
35,6 → 35,9
#ifndef KERN_mips32_TLB_H_
#define KERN_mips32_TLB_H_
 
#include <arch/types.h>
#include <typedefs.h>
#include <arch/mm/asid.h>
#include <arch/exception.h>
 
#ifdef TLBCNT
46,7 → 49,13
#define TLB_WIRED 1
#define TLB_KSTACK_WIRED_INDEX 0
 
#define TLB_PAGE_MASK_16K (0x3<<13)
#define TLB_PAGE_MASK_4K (0x000 << 13)
#define TLB_PAGE_MASK_16K (0x003 << 13)
#define TLB_PAGE_MASK_64K (0x00f << 13)
#define TLB_PAGE_MASK_256K (0x03f << 13)
#define TLB_PAGE_MASK_1M (0x0ff << 13)
#define TLB_PAGE_MASK_4M (0x3ff << 13)
#define TLB_PAGE_MASK_16M (0xfff << 13)
 
#define PAGE_UNCACHED 2
#define PAGE_CACHEABLE_EXC_WRITE 5
159,6 → 168,8
extern void tlb_invalid(istate_t *istate);
extern void tlb_refill(istate_t *istate);
extern void tlb_modified(istate_t *istate);
extern void tlb_prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn);
extern void tlb_prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr);
 
#endif
 
/branches/dd/kernel/arch/mips32/include/mm/as.h
38,7 → 38,7
#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH 0
 
#define KERNEL_ADDRESS_SPACE_START_ARCH (unsigned long) 0x80000000
#define KERNEL_ADDRESS_SPACE_END_ARCH (unsigned long) 0xffffffff
#define KERNEL_ADDRESS_SPACE_END_ARCH (unsigned long) 0x9fffffff
#define USER_ADDRESS_SPACE_START_ARCH (unsigned long) 0x00000000
#define USER_ADDRESS_SPACE_END_ARCH (unsigned long) 0x7fffffff
 
/branches/dd/kernel/arch/mips32/include/barrier.h
45,6 → 45,9
#define read_barrier() asm volatile ("" ::: "memory")
#define write_barrier() asm volatile ("" ::: "memory")
 
#define smc_coherence(a)
#define smc_coherence_block(a, l)
 
#endif
 
/** @}
/branches/dd/kernel/arch/mips32/include/cpu.h
42,7 → 42,7
uint32_t imp_num;
uint32_t rev_num;
} cpu_arch_t;
 
#endif
 
/** @}
/branches/dd/kernel/arch/mips32/include/drivers/arc.h
File deleted
/branches/dd/kernel/arch/mips32/include/drivers/serial.h
35,36 → 35,8
#ifndef KERN_mips32_SERIAL_H_
#define KERN_mips32_SERIAL_H_
 
#include <console/chardev.h>
#define SERIAL_ADDRESS 0x98000000
 
#define SERIAL_MAX 4
#define SERIAL_COM1 0x3f8
#define SERIAL_COM1_IRQ 4
#define SERIAL_COM2 0x2f8
#define SERIAL_COM2_IRQ 3
 
#define P_WRITEB(where,what) (*((volatile char *) (0xB8000000+where))=what)
#define P_READB(where) (*((volatile char *)(0xB8000000+where)))
 
#define SERIAL_READ(x) P_READB(x)
#define SERIAL_WRITE(x,c) P_WRITEB(x,c)
/* Interrupt enable register */
#define SERIAL_READ_IER(x) (P_READB((x) + 1))
#define SERIAL_WRITE_IER(x,c) (P_WRITEB((x)+1,c))
/* Interrupt identification register */
#define SERIAL_READ_IIR(x) (P_READB((x) + 2))
/* Line status register */
#define SERIAL_READ_LSR(x) (P_READB((x) + 5))
#define TRANSMIT_EMPTY_BIT 5
 
typedef struct {
int port;
int irq;
}serial_t;
 
extern void serial_console(devno_t devno);
extern int serial_init(void);
 
#endif
 
/** @}
/branches/dd/kernel/arch/mips32/include/drivers/msim.h
35,6 → 35,11
#ifndef KERN_mips32_MSIM_H_
#define KERN_mips32_MSIM_H_
 
/** Address of devices. */
#define MSIM_VIDEORAM 0x90000000
#define MSIM_KBD_ADDRESS 0x90000000
#define MSIM_KBD_IRQ 2
 
#include <console/chardev.h>
 
void msim_console(devno_t devno);
/branches/dd/kernel/arch/mips32/Makefile.inc
31,57 → 31,26
 
BFD_ARCH = mips
TARGET = mipsel-linux-gnu
TOOLCHAIN_DIR = /usr/local/mipsel
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel
 
KERNEL_LOAD_ADDRESS = 0x80100000
INIT_ADDRESS = 0x81000000
INIT_SIZE = 262144
 
GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss
 
DEFS += -D__32_BITS__ -DMACHINE=$(MACHINE) -DKERNEL_LOAD_ADDRESS=${KERNEL_LOAD_ADDRESS} -DINIT_ADDRESS=${INIT_ADDRESS} -DINIT_SIZE=${INIT_SIZE}
DEFS += -D__32_BITS__
 
## Compile with hierarchical page tables support.
#
 
CONFIG_PAGE_PT = y
DEFS += -DCONFIG_PAGE_PT
 
## Compile with support for address space identifiers.
#
 
CONFIG_ASID = y
CONFIG_ASID_FIFO = y
 
## Accepted MACHINEs
#
 
ifeq ($(MACHINE),indy)
# GCC 4.0.1 compiled for mipsEL has problems compiling in
# BigEndian mode with the swl/swr/lwl/lwr instructions.
# We have to compile it with mips-sgi-irix5 to get it right.
BFD_NAME = elf32-bigmips
BFD = ecoff-bigmips --impure
TARGET = mips-sgi-irix5
TOOLCHAIN_DIR = /usr/local/mips/bin
KERNEL_LOAD_ADDRESS = 0x88002000
GCC_CFLAGS += -EB -DBIG_ENDIAN -DARCH_HAS_FPU -march=r4600
INIT_ADDRESS = 0
INIT_SIZE = 0
endif
ifeq ($(MACHINE),lgxemul)
BFD_NAME = elf32-tradlittlemips
BFD = binary
GCC_CFLAGS += -DFB_INVERT_ENDIAN -DARCH_HAS_FPU -mips3
GCC_CFLAGS += -mips3
endif
ifeq ($(MACHINE),bgxemul)
BFD_NAME = elf32-bigmips
BFD = ecoff-bigmips
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips
TARGET = mips-sgi-irix5
TOOLCHAIN_DIR = /usr/local/mips/bin
GCC_CFLAGS += -EB -DBIG_ENDIAN -DARCH_HAS_FPU -mips3
INIT_ADDRESS = 0x81800000
GCC_CFLAGS += -EB -DBIG_ENDIAN -mips3
endif
ifeq ($(MACHINE),simics)
# SIMICS 4kc emulation is broken, although for instructions
98,32 → 67,24
GCC_CFLAGS += -mhard-float -mips3
endif
 
## Compile with support for software integer division.
#
 
CONFIG_SOFTINT = y
 
 
ARCH_SOURCES = \
arch/$(ARCH)/src/start.S \
arch/$(ARCH)/src/context.S \
arch/$(ARCH)/src/panic.S \
arch/$(ARCH)/src/mips32.c \
arch/$(ARCH)/src/dummy.S \
arch/$(ARCH)/src/console.c \
arch/$(ARCH)/src/asm.S \
arch/$(ARCH)/src/exception.c \
arch/$(ARCH)/src/interrupt.c \
arch/$(ARCH)/src/cache.c \
arch/$(ARCH)/src/debugger.c \
arch/$(ARCH)/src/cpu/cpu.c \
arch/$(ARCH)/src/mm/frame.c \
arch/$(ARCH)/src/mm/page.c \
arch/$(ARCH)/src/mm/tlb.c \
arch/$(ARCH)/src/mm/as.c \
arch/$(ARCH)/src/fpu_context.c \
arch/$(ARCH)/src/ddi/ddi.c \
arch/$(ARCH)/src/drivers/arc.c \
arch/$(ARCH)/src/drivers/msim.c \
arch/$(ARCH)/src/drivers/serial.c \
arch/$(ARCH)/src/smp/order.c
arch/$(KARCH)/src/start.S \
arch/$(KARCH)/src/context.S \
arch/$(KARCH)/src/panic.S \
arch/$(KARCH)/src/mips32.c \
arch/$(KARCH)/src/console.c \
arch/$(KARCH)/src/asm.S \
arch/$(KARCH)/src/exception.c \
arch/$(KARCH)/src/interrupt.c \
arch/$(KARCH)/src/cache.c \
arch/$(KARCH)/src/debugger.c \
arch/$(KARCH)/src/cpu/cpu.c \
arch/$(KARCH)/src/mm/frame.c \
arch/$(KARCH)/src/mm/page.c \
arch/$(KARCH)/src/mm/tlb.c \
arch/$(KARCH)/src/mm/as.c \
arch/$(KARCH)/src/fpu_context.c \
arch/$(KARCH)/src/ddi/ddi.c \
arch/$(KARCH)/src/drivers/msim.c \
arch/$(KARCH)/src/smp/dorder.c \
arch/$(KARCH)/src/smp/smp.c
/branches/dd/kernel/arch/mips32/src/dummy.S
File deleted
/branches/dd/kernel/arch/mips32/src/fpu_context.c
40,7 → 40,7
 
void fpu_disable(void)
{
#ifdef ARCH_HAS_FPU
#ifdef CONFIG_FPU
cp0_status_write(cp0_status_read() & ~cp0_status_fpu_bit);
#endif
}
47,7 → 47,7
 
void fpu_enable(void)
{
#ifdef ARCH_HAS_FPU
#ifdef CONFIG_FPU
cp0_status_write(cp0_status_read() | cp0_status_fpu_bit);
#endif
}
/branches/dd/kernel/arch/mips32/src/exception.c
45,7 → 45,6
#include <print.h>
#include <interrupt.h>
#include <func.h>
#include <console/kconsole.h>
#include <ddi/irq.h>
#include <arch/debugger.h>
 
89,10 → 88,10
 
static void unhandled_exception(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "unhandled exception %s", exctable[n]);
fault_if_from_uspace(istate, "Unhandled exception %s.", exctable[n]);
print_regdump(istate);
panic("unhandled exception %s\n", exctable[n]);
panic("Unhandled exception %s.", exctable[n]);
}
 
static void reserved_instr_exception(int n, istate_t *istate)
133,8 → 132,8
if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id)
scheduler_fpu_lazy_request();
else {
fault_if_from_uspace(istate, "unhandled Coprocessor Unusable Exception");
panic("unhandled Coprocessor Unusable Exception\n");
fault_if_from_uspace(istate, "Unhandled Coprocessor Unusable Exception.");
panic("Unhandled Coprocessor Unusable Exception.");
}
}
#endif
145,7 → 144,7
int i;
/* decode interrupt number and process the interrupt */
cause = (cp0_cause_read() >> 8) &0xff;
cause = (cp0_cause_read() >> 8) & 0xff;
for (i = 0; i < 8; i++) {
if (cause & (1 << i)) {
154,7 → 153,7
/*
* The IRQ handler was found.
*/
irq->handler(irq, irq->arg);
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
/*
161,7 → 160,8
* Spurious interrupt.
*/
#ifdef CONFIG_DEBUG
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, i);
printf("cpu%u: spurious interrupt (inum=%d)\n",
CPU->id, i);
#endif
}
}
171,7 → 171,7
/** Handle syscall userspace call */
static void syscall_exception(int n, istate_t *istate)
{
panic("Syscall is handled through shortcut");
panic("Syscall is handled through shortcut.");
}
 
void exception_init(void)
/branches/dd/kernel/arch/mips32/src/asm.S
27,17 → 27,17
#
 
#include <arch/asm/regname.h>
 
.text
 
.macro cp0_read reg
mfc0 $2,\reg
mfc0 $2, \reg
j $31
nop
.endm
 
.macro cp0_write reg
mtc0 $4,\reg
mtc0 $4, \reg
j $31
nop
.endm
46,6 → 46,11
.set noreorder
.set nomacro
 
.global asm_delay_loop
asm_delay_loop:
j $31
nop
 
.global cpu_halt
cpu_halt:
j cpu_halt
66,234 → 71,238
memcpy:
memcpy_from_uspace:
memcpy_to_uspace:
addiu $v0,$a1,3
li $v1,-4 # 0xfffffffffffffffc
and $v0,$v0,$v1
beq $a1,$v0,3f
move $t0,$a0
move $t2, $a0 # save dst
addiu $v0, $a1, 3
li $v1, -4 # 0xfffffffffffffffc
and $v0, $v0, $v1
beq $a1, $v0, 3f
move $t0, $a0
0:
beq $a2, $zero, 2f
move $a3, $zero
1:
addu $v0, $a1, $a3
lbu $a0, 0($v0)
addu $v1, $t0, $a3
addiu $a3, $a3, 1
bne $a3, $a2, 1b
sb $a0, 0($v1)
2:
jr $ra
move $v0, $t2
3:
addiu $v0, $a0, 3
and $v0, $v0, $v1
bne $a0, $v0, 0b
srl $t1, $a2, 2
beq $t1, $zero, 5f
move $a3, $zero
move $a3, $zero
move $a0, $zero
4:
addu $v0, $a1, $a0
lw $v1, 0($v0)
addiu $a3, $a3, 1
addu $v0, $t0, $a0
sw $v1, 0($v0)
bne $a3, $t1, 4b
addiu $a0, $a0, 4
5:
andi $a2, $a2, 0x3
beq $a2, $zero, 2b
nop
sll $v0, $a3, 2
addu $t1, $v0, $t0
move $a3, $zero
addu $t0, $v0, $a1
6:
addu $v0, $t0, $a3
lbu $a0, 0($v0)
addu $v1, $t1, $a3
addiu $a3, $a3, 1
bne $a3, $a2, 6b
sb $a0, 0($v1)
jr $ra
move $v0, $t2
 
0:
beq $a2,$zero,2f
move $a3,$zero
 
1:
addu $v0,$a1,$a3
lbu $a0,0($v0)
addu $v1,$t0,$a3
addiu $a3,$a3,1
bne $a3,$a2,1b
sb $a0,0($v1)
 
2:
jr $ra
move $v0,$a1
 
3:
addiu $v0,$a0,3
and $v0,$v0,$v1
bne $a0,$v0,0b
srl $t1,$a2,2
 
beq $t1,$zero,5f
move $a3,$zero
 
move $a3,$zero
move $a0,$zero
4:
addu $v0,$a1,$a0
lw $v1,0($v0)
addiu $a3,$a3,1
addu $v0,$t0,$a0
sw $v1,0($v0)
bne $a3,$t1,4b
addiu $a0,$a0,4
 
5:
andi $a2,$a2,0x3
beq $a2,$zero,2b
nop
 
sll $v0,$a3,2
addu $t1,$v0,$t0
move $a3,$zero
addu $t0,$v0,$a1
6:
addu $v0,$t0,$a3
lbu $a0,0($v0)
addu $v1,$t1,$a3
addiu $a3,$a3,1
bne $a3,$a2,6b
sb $a0,0($v1)
 
jr $ra
move $v0,$a1
 
memcpy_from_uspace_failover_address:
memcpy_to_uspace_failover_address:
jr $ra
move $v0, $zero
jr $ra
move $v0, $zero
 
 
 
.macro fpu_gp_save reg ctx
mfc1 $t0,$\reg
sw $t0, \reg*4(\ctx)
mfc1 $t0, $\reg
sw $t0, \reg * 4(\ctx)
.endm
 
.macro fpu_gp_restore reg ctx
lw $t0, \reg*4(\ctx)
mtc1 $t0,$\reg
lw $t0, \reg * 4(\ctx)
mtc1 $t0, $\reg
.endm
 
.macro fpu_ct_save reg ctx
cfc1 $t0,$1
sw $t0, (\reg+32)*4(\ctx)
cfc1 $t0, $1
sw $t0, (\reg + 32) * 4(\ctx)
.endm
 
.macro fpu_ct_restore reg ctx
lw $t0, (\reg+32)*4(\ctx)
ctc1 $t0,$\reg
lw $t0, (\reg + 32) * 4(\ctx)
ctc1 $t0, $\reg
.endm
 
 
.global fpu_context_save
fpu_context_save:
#ifdef ARCH_HAS_FPU
fpu_gp_save 0,$a0
fpu_gp_save 1,$a0
fpu_gp_save 2,$a0
fpu_gp_save 3,$a0
fpu_gp_save 4,$a0
fpu_gp_save 5,$a0
fpu_gp_save 6,$a0
fpu_gp_save 7,$a0
fpu_gp_save 8,$a0
fpu_gp_save 9,$a0
fpu_gp_save 10,$a0
fpu_gp_save 11,$a0
fpu_gp_save 12,$a0
fpu_gp_save 13,$a0
fpu_gp_save 14,$a0
fpu_gp_save 15,$a0
fpu_gp_save 16,$a0
fpu_gp_save 17,$a0
fpu_gp_save 18,$a0
fpu_gp_save 19,$a0
fpu_gp_save 20,$a0
fpu_gp_save 21,$a0
fpu_gp_save 22,$a0
fpu_gp_save 23,$a0
fpu_gp_save 24,$a0
fpu_gp_save 25,$a0
fpu_gp_save 26,$a0
fpu_gp_save 27,$a0
fpu_gp_save 28,$a0
fpu_gp_save 29,$a0
fpu_gp_save 30,$a0
fpu_gp_save 31,$a0
 
fpu_ct_save 1,$a0
fpu_ct_save 2,$a0
fpu_ct_save 3,$a0
fpu_ct_save 4,$a0
fpu_ct_save 5,$a0
fpu_ct_save 6,$a0
fpu_ct_save 7,$a0
fpu_ct_save 8,$a0
fpu_ct_save 9,$a0
fpu_ct_save 10,$a0
fpu_ct_save 11,$a0
fpu_ct_save 12,$a0
fpu_ct_save 13,$a0
fpu_ct_save 14,$a0
fpu_ct_save 15,$a0
fpu_ct_save 16,$a0
fpu_ct_save 17,$a0
fpu_ct_save 18,$a0
fpu_ct_save 19,$a0
fpu_ct_save 20,$a0
fpu_ct_save 21,$a0
fpu_ct_save 22,$a0
fpu_ct_save 23,$a0
fpu_ct_save 24,$a0
fpu_ct_save 25,$a0
fpu_ct_save 26,$a0
fpu_ct_save 27,$a0
fpu_ct_save 28,$a0
fpu_ct_save 29,$a0
fpu_ct_save 30,$a0
fpu_ct_save 31,$a0
#endif
#ifdef CONFIG_FPU
fpu_gp_save 0, $a0
fpu_gp_save 1, $a0
fpu_gp_save 2, $a0
fpu_gp_save 3, $a0
fpu_gp_save 4, $a0
fpu_gp_save 5, $a0
fpu_gp_save 6, $a0
fpu_gp_save 7, $a0
fpu_gp_save 8, $a0
fpu_gp_save 9, $a0
fpu_gp_save 10, $a0
fpu_gp_save 11, $a0
fpu_gp_save 12, $a0
fpu_gp_save 13, $a0
fpu_gp_save 14, $a0
fpu_gp_save 15, $a0
fpu_gp_save 16, $a0
fpu_gp_save 17, $a0
fpu_gp_save 18, $a0
fpu_gp_save 19, $a0
fpu_gp_save 20, $a0
fpu_gp_save 21, $a0
fpu_gp_save 22, $a0
fpu_gp_save 23, $a0
fpu_gp_save 24, $a0
fpu_gp_save 25, $a0
fpu_gp_save 26, $a0
fpu_gp_save 27, $a0
fpu_gp_save 28, $a0
fpu_gp_save 29, $a0
fpu_gp_save 30, $a0
fpu_gp_save 31, $a0
fpu_ct_save 1, $a0
fpu_ct_save 2, $a0
fpu_ct_save 3, $a0
fpu_ct_save 4, $a0
fpu_ct_save 5, $a0
fpu_ct_save 6, $a0
fpu_ct_save 7, $a0
fpu_ct_save 8, $a0
fpu_ct_save 9, $a0
fpu_ct_save 10, $a0
fpu_ct_save 11, $a0
fpu_ct_save 12, $a0
fpu_ct_save 13, $a0
fpu_ct_save 14, $a0
fpu_ct_save 15, $a0
fpu_ct_save 16, $a0
fpu_ct_save 17, $a0
fpu_ct_save 18, $a0
fpu_ct_save 19, $a0
fpu_ct_save 20, $a0
fpu_ct_save 21, $a0
fpu_ct_save 22, $a0
fpu_ct_save 23, $a0
fpu_ct_save 24, $a0
fpu_ct_save 25, $a0
fpu_ct_save 26, $a0
fpu_ct_save 27, $a0
fpu_ct_save 28, $a0
fpu_ct_save 29, $a0
fpu_ct_save 30, $a0
fpu_ct_save 31, $a0
#endif
j $ra
nop
 
.global fpu_context_restore
fpu_context_restore:
#ifdef ARCH_HAS_FPU
fpu_gp_restore 0,$a0
fpu_gp_restore 1,$a0
fpu_gp_restore 2,$a0
fpu_gp_restore 3,$a0
fpu_gp_restore 4,$a0
fpu_gp_restore 5,$a0
fpu_gp_restore 6,$a0
fpu_gp_restore 7,$a0
fpu_gp_restore 8,$a0
fpu_gp_restore 9,$a0
fpu_gp_restore 10,$a0
fpu_gp_restore 11,$a0
fpu_gp_restore 12,$a0
fpu_gp_restore 13,$a0
fpu_gp_restore 14,$a0
fpu_gp_restore 15,$a0
fpu_gp_restore 16,$a0
fpu_gp_restore 17,$a0
fpu_gp_restore 18,$a0
fpu_gp_restore 19,$a0
fpu_gp_restore 20,$a0
fpu_gp_restore 21,$a0
fpu_gp_restore 22,$a0
fpu_gp_restore 23,$a0
fpu_gp_restore 24,$a0
fpu_gp_restore 25,$a0
fpu_gp_restore 26,$a0
fpu_gp_restore 27,$a0
fpu_gp_restore 28,$a0
fpu_gp_restore 29,$a0
fpu_gp_restore 30,$a0
fpu_gp_restore 31,$a0
 
fpu_ct_restore 1,$a0
fpu_ct_restore 2,$a0
fpu_ct_restore 3,$a0
fpu_ct_restore 4,$a0
fpu_ct_restore 5,$a0
fpu_ct_restore 6,$a0
fpu_ct_restore 7,$a0
fpu_ct_restore 8,$a0
fpu_ct_restore 9,$a0
fpu_ct_restore 10,$a0
fpu_ct_restore 11,$a0
fpu_ct_restore 12,$a0
fpu_ct_restore 13,$a0
fpu_ct_restore 14,$a0
fpu_ct_restore 15,$a0
fpu_ct_restore 16,$a0
fpu_ct_restore 17,$a0
fpu_ct_restore 18,$a0
fpu_ct_restore 19,$a0
fpu_ct_restore 20,$a0
fpu_ct_restore 21,$a0
fpu_ct_restore 22,$a0
fpu_ct_restore 23,$a0
fpu_ct_restore 24,$a0
fpu_ct_restore 25,$a0
fpu_ct_restore 26,$a0
fpu_ct_restore 27,$a0
fpu_ct_restore 28,$a0
fpu_ct_restore 29,$a0
fpu_ct_restore 30,$a0
fpu_ct_restore 31,$a0
#endif
#ifdef CONFIG_FPU
fpu_gp_restore 0, $a0
fpu_gp_restore 1, $a0
fpu_gp_restore 2, $a0
fpu_gp_restore 3, $a0
fpu_gp_restore 4, $a0
fpu_gp_restore 5, $a0
fpu_gp_restore 6, $a0
fpu_gp_restore 7, $a0
fpu_gp_restore 8, $a0
fpu_gp_restore 9, $a0
fpu_gp_restore 10, $a0
fpu_gp_restore 11, $a0
fpu_gp_restore 12, $a0
fpu_gp_restore 13, $a0
fpu_gp_restore 14, $a0
fpu_gp_restore 15, $a0
fpu_gp_restore 16, $a0
fpu_gp_restore 17, $a0
fpu_gp_restore 18, $a0
fpu_gp_restore 19, $a0
fpu_gp_restore 20, $a0
fpu_gp_restore 21, $a0
fpu_gp_restore 22, $a0
fpu_gp_restore 23, $a0
fpu_gp_restore 24, $a0
fpu_gp_restore 25, $a0
fpu_gp_restore 26, $a0
fpu_gp_restore 27, $a0
fpu_gp_restore 28, $a0
fpu_gp_restore 29, $a0
fpu_gp_restore 30, $a0
fpu_gp_restore 31, $a0
fpu_ct_restore 1, $a0
fpu_ct_restore 2, $a0
fpu_ct_restore 3, $a0
fpu_ct_restore 4, $a0
fpu_ct_restore 5, $a0
fpu_ct_restore 6, $a0
fpu_ct_restore 7, $a0
fpu_ct_restore 8, $a0
fpu_ct_restore 9, $a0
fpu_ct_restore 10, $a0
fpu_ct_restore 11, $a0
fpu_ct_restore 12, $a0
fpu_ct_restore 13, $a0
fpu_ct_restore 14, $a0
fpu_ct_restore 15, $a0
fpu_ct_restore 16, $a0
fpu_ct_restore 17, $a0
fpu_ct_restore 18, $a0
fpu_ct_restore 19, $a0
fpu_ct_restore 20, $a0
fpu_ct_restore 21, $a0
fpu_ct_restore 22, $a0
fpu_ct_restore 23, $a0
fpu_ct_restore 24, $a0
fpu_ct_restore 25, $a0
fpu_ct_restore 26, $a0
fpu_ct_restore 27, $a0
fpu_ct_restore 28, $a0
fpu_ct_restore 29, $a0
fpu_ct_restore 30, $a0
fpu_ct_restore 31, $a0
#endif
j $ra
nop
/branches/dd/kernel/arch/mips32/src/console.c
34,25 → 34,18
 
#include <console/console.h>
#include <arch/console.h>
#include <arch/drivers/arc.h>
#include <arch/drivers/serial.h>
#include <arch/drivers/msim.h>
#include <genarch/fb/fb.h>
 
void console_init(devno_t devno)
{
if (!arc_console()) {
if (serial_init())
serial_console(devno);
else
msim_console(devno);
}
}
 
/** Acquire console back for kernel
*
*/
void arch_grab_console(void)
{
#ifdef CONFIG_FB
fb_redraw();
#endif
msim_kbd_grab();
}
 
/branches/dd/kernel/arch/mips32/src/cache.c
38,7 → 38,7
 
void cache_error(istate_t *istate)
{
panic("cache_error exception (epc=%p)\n", istate->epc);
panic("cache_error exception (epc=%p).", istate->epc);
}
 
/** @}
/branches/dd/kernel/arch/mips32/src/cpu/cpu.c
48,7 → 48,7
{ "MIPS", "R2000" }, /* 0x01 */
{ "MIPS", "R3000" }, /* 0x02 */
{ "MIPS", "R6000" }, /* 0x03 */
{ "MIPS", " R4000/R4400" }, /* 0x04 */
{ "MIPS", "R4000/R4400" }, /* 0x04 */
{ "LSI Logic", "R3000" }, /* 0x05 */
{ "MIPS", "R6000A" }, /* 0x06 */
{ "IDT", "3051/3052" }, /* 0x07 */
123,9 → 123,9
data = &imp_data[m->arch.imp_num];
}
 
printf("cpu%d: %s %s (rev=%d.%d, imp=%d)\n",
printf("cpu%u: %s %s (rev=%d.%d, imp=%d)\n",
m->id, data->vendor, data->model, m->arch.rev_num >> 4,
m->arch.rev_num & 0xf, m->arch.imp_num);
m->arch.rev_num & 0x0f, m->arch.imp_num);
}
 
/** @}
/branches/dd/kernel/arch/mips32/src/mips32.c
33,7 → 33,6
*/
 
#include <arch.h>
#include <arch/boot.h>
#include <arch/cp0.h>
#include <arch/exception.h>
#include <mm/as.h>
48,44 → 47,55
#include <sysinfo/sysinfo.h>
 
#include <arch/interrupt.h>
#include <arch/drivers/arc.h>
#include <console/chardev.h>
#include <arch/barrier.h>
#include <arch/debugger.h>
#include <genarch/fb/fb.h>
#include <genarch/fb/visuals.h>
#include <macros.h>
#include <ddi/device.h>
#include <config.h>
#include <string.h>
#include <arch/drivers/msim.h>
 
#include <arch/asm/regname.h>
 
/* Size of the code jumping to the exception handler code
* - J+NOP
/* Size of the code jumping to the exception handler code
* - J+NOP
*/
#define EXCEPTION_JUMP_SIZE 8
#define EXCEPTION_JUMP_SIZE 8
 
#define TLB_EXC ((char *) 0x80000000)
#define NORM_EXC ((char *) 0x80000180)
#define CACHE_EXC ((char *) 0x80000100)
#define TLB_EXC ((char *) 0x80000000)
#define NORM_EXC ((char *) 0x80000180)
#define CACHE_EXC ((char *) 0x80000100)
 
 
/* Why the linker moves the variable 64K away in assembler
* when not in .text section ????????
* when not in .text section?
*/
 
/* Stack pointer saved when entering user mode */
uintptr_t supervisor_sp __attribute__ ((section (".text")));
/* Stack pointer saved when entering user mode */
/* TODO: How do we do it on SMP system???? */
bootinfo_t bootinfo __attribute__ ((section (".text")));
 
void arch_pre_main(void)
count_t cpu_count = 0;
 
/** Performs mips32-specific initialization before main_bsp() is called. */
void arch_pre_main(void *entry __attribute__((unused)), bootinfo_t *bootinfo)
{
/* Setup usermode */
init.cnt = bootinfo.cnt;
init.cnt = bootinfo->cnt;
uint32_t i;
count_t i;
for (i = 0; i < min3(bootinfo->cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS); i++) {
init.tasks[i].addr = bootinfo->tasks[i].addr;
init.tasks[i].size = bootinfo->tasks[i].size;
strncpy(init.tasks[i].name, bootinfo->tasks[i].name,
CONFIG_TASK_NAME_BUFLEN);
}
for (i = 0; i < bootinfo.cnt; i++) {
init.tasks[i].addr = bootinfo.tasks[i].addr;
init.tasks[i].size = bootinfo.tasks[i].size;
for (i = 0; i < CPUMAP_MAX_RECORDS; i++) {
if ((bootinfo->cpumap & (1 << i)) != 0)
cpu_count++;
}
}
 
96,24 → 106,27
/* Initialize dispatch table */
exception_init();
arc_init();
 
/* Copy the exception vectors to the right places */
memcpy(TLB_EXC, (char *) tlb_refill_entry, EXCEPTION_JUMP_SIZE);
smc_coherence_block(TLB_EXC, EXCEPTION_JUMP_SIZE);
memcpy(NORM_EXC, (char *) exception_entry, EXCEPTION_JUMP_SIZE);
smc_coherence_block(NORM_EXC, EXCEPTION_JUMP_SIZE);
memcpy(CACHE_EXC, (char *) cache_error_entry, EXCEPTION_JUMP_SIZE);
smc_coherence_block(CACHE_EXC, EXCEPTION_JUMP_SIZE);
/*
* Switch to BEV normal level so that exception vectors point to the kernel.
* Clear the error level.
* Switch to BEV normal level so that exception vectors point to the
* kernel. Clear the error level.
*/
cp0_status_write(cp0_status_read() & ~(cp0_status_bev_bootstrap_bit|cp0_status_erl_error_bit));
 
/*
* Mask all interrupts
cp0_status_write(cp0_status_read() &
~(cp0_status_bev_bootstrap_bit | cp0_status_erl_error_bit));
/*
* Mask all interrupts
*/
cp0_mask_all_int();
debugger_init();
}
 
120,11 → 133,35
void arch_post_mm_init(void)
{
interrupt_init();
console_init(device_assign_devno());
msim_console(device_assign_devno());
#ifdef CONFIG_FB
fb_init(0x12000000, 640, 480, 1920, VISUAL_RGB_8_8_8); // gxemul framebuffer
/* GXemul framebuffer */
fb_properties_t gxemul_prop = {
.addr = 0x12000000,
.offset = 0,
.x = 640,
.y = 480,
.scan = 1920,
.visual = VISUAL_BGR_8_8_8,
};
fb_init(&gxemul_prop);
#endif
sysinfo_set_item_val("machine." STRING(MACHINE), NULL, 1);
 
#ifdef MACHINE_msim
sysinfo_set_item_val("machine.msim", NULL, 1);
#endif
 
#ifdef MACHINE_simics
sysinfo_set_item_val("machine.simics", NULL, 1);
#endif
 
#ifdef MACHINE_bgxemul
sysinfo_set_item_val("machine.bgxemul", NULL, 1);
#endif
 
#ifdef MACHINE_lgxemul
sysinfo_set_item_val("machine.lgxemul", NULL, 1);
#endif
}
 
void arch_post_cpu_init(void)
139,15 → 176,19
{
}
 
void calibrate_delay_loop(void)
{
}
 
void userspace(uspace_arg_t *kernel_uarg)
{
/* EXL = 1, UM = 1, IE = 1 */
cp0_status_write(cp0_status_read() | (cp0_status_exl_exception_bit |
cp0_status_um_bit | cp0_status_ie_enabled_bit));
cp0_status_um_bit | cp0_status_ie_enabled_bit));
cp0_epc_write((uintptr_t) kernel_uarg->uspace_entry);
userspace_asm(((uintptr_t) kernel_uarg->uspace_stack + PAGE_SIZE),
(uintptr_t) kernel_uarg->uspace_uarg,
(uintptr_t) kernel_uarg->uspace_entry);
(uintptr_t) kernel_uarg->uspace_uarg,
(uintptr_t) kernel_uarg->uspace_entry);
while (1);
}
160,7 → 201,8
/** Perform mips32 specific tasks needed before the new thread is scheduled. */
void before_thread_runs_arch(void)
{
supervisor_sp = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE-SP_DELTA];
supervisor_sp = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE -
SP_DELTA];
}
 
void after_thread_ran_arch(void)
179,11 → 221,24
 
void arch_reboot(void)
{
if (!arc_reboot())
___halt();
___halt();
while (1);
}
 
/** Construct function pointer
*
* @param fptr function pointer structure
* @param addr function address
* @param caller calling function address
*
* @return address of the function pointer
*
*/
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
{
return addr;
}
 
/** @}
*/
/branches/dd/kernel/arch/mips32/src/start.S
31,7 → 31,7
#include <arch/asm/boot.h>
#include <arch/context_offset.h>
#include <arch/stack.h>
 
.text
 
.set noat
75,18 → 75,6
mfhi $at
sw $at, EOFFSET_HI(\r)
#ifdef CONFIG_DEBUG_ALLREGS
sw $s0, EOFFSET_S0(\r)
sw $s1, EOFFSET_S1(\r)
sw $s2, EOFFSET_S2(\r)
sw $s3, EOFFSET_S3(\r)
sw $s4, EOFFSET_S4(\r)
sw $s5, EOFFSET_S5(\r)
sw $s6, EOFFSET_S6(\r)
sw $s7, EOFFSET_S7(\r)
sw $s8, EOFFSET_S8(\r)
#endif
sw $gp, EOFFSET_GP(\r)
sw $ra, EOFFSET_RA(\r)
sw $k1, EOFFSET_K1(\r)
132,17 → 120,6
lw $t8, EOFFSET_T8(\r)
lw $t9, EOFFSET_T9(\r)
#ifdef CONFIG_DEBUG_ALLREGS
lw $s0, EOFFSET_S0(\r)
lw $s1, EOFFSET_S1(\r)
lw $s2, EOFFSET_S2(\r)
lw $s3, EOFFSET_S3(\r)
lw $s4, EOFFSET_S4(\r)
lw $s5, EOFFSET_S5(\r)
lw $s6, EOFFSET_S6(\r)
lw $s7, EOFFSET_S7(\r)
lw $s8, EOFFSET_S8(\r)
#endif
lw $gp, EOFFSET_GP(\r)
lw $ra, EOFFSET_RA(\r)
lw $k1, EOFFSET_K1(\r)
175,9 → 152,9
ori $k0, $k0, %lo(supervisor_sp)
# Move $k0 (superveisor_sp)
lw $k0, 0($k0)
1:
1:
.endm
 
.org 0x0
kernel_image_start:
/* Load temporary stack */
184,31 → 161,12
lui $sp, %hi(end_stack)
ori $sp, $sp, %lo(end_stack)
/* $a1 contains physical address of bootinfo_t */
/* $a2 contains size of bootinfo_t */
beq $a2, $0, bootinfo_end
/* Not sure about this, but might be needed for PIC code???? */
/* Not sure about this, but might
be needed for PIC code */
lui $gp, 0x8000
lui $a3, %hi(bootinfo)
ori $a3, $a3, %lo(bootinfo)
/* $a1 contains physical address of bootinfo_t */
bootinfo_loop:
lw $v0, 0($a1)
sw $v0, 0($a3)
addi $a1, $a1, 4
addi $a3, $a3, 4
addi $a2, $a2, -4
bgtz $a2, bootinfo_loop
nop
bootinfo_end:
jal arch_pre_main
nop
228,8 → 186,8
 
exception_entry:
j exception_handler
nop
nop
 
exception_handler:
KERNEL_STACK_TO_K0
sub $k0, REGISTER_SPACE
238,17 → 196,17
mfc0 $k0, $cause
sra $k0, $k0, 0x2 # cp0_exc_cause() part 1
andi $k0, $k0, 0x1f # cp0_exc_cause() part 2
sub $k0, 8 # 8 = SYSCALL
sra $k0, $k0, 0x2 # cp0_exc_cause() part 1
andi $k0, $k0, 0x1f # cp0_exc_cause() part 2
sub $k0, 8 # 8 = SYSCALL
beqz $k0, syscall_shortcut
add $k0, 8 # Revert $k0 back to correct exc number
add $k0, 8 # Revert $k0 back to correct exc number
REGISTERS_STORE_AND_EXC_RESET $sp
move $a1, $sp
jal exc_dispatch # exc_dispatch(excno, register_space)
jal exc_dispatch # exc_dispatch(excno, register_space)
move $a0, $k0
 
REGISTERS_LOAD $sp
349,5 → 307,7
userspace_asm:
add $sp, $a0, 0
add $v0, $a1, 0
add $t9, $a2, 0 # Set up correct entry into PIC code
add $t9, $a2, 0 # Set up correct entry into PIC code
xor $a0, $a0, $a0 # $a0 is defined to hold pcb_ptr
# set it to 0
eret
/branches/dd/kernel/arch/mips32/src/smp/order.c
File deleted
/branches/dd/kernel/arch/mips32/src/smp/dorder.c
0,0 → 1,47
/*
* Copyright (c) 2007 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32
* @{
*/
/** @file
*/
 
#include <arch/smp/dorder.h>
 
#define MSIM_DORDER_ADDRESS 0xB0000004
 
void ipi_broadcast_arch(int ipi)
{
#ifdef CONFIG_SMP
*((volatile unsigned int *) MSIM_DORDER_ADDRESS) = 0x7FFFFFFF;
#endif
}
 
/** @}
*/
/branches/dd/kernel/arch/mips32/src/smp/smp.c
0,0 → 1,53
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32
* @{
*/
/** @file
*/
 
#include <config.h>
#include <smp/smp.h>
#include <arch/arch.h>
 
#ifdef CONFIG_SMP
 
void smp_init(void)
{
config.cpu_count = cpu_count;
}
 
void kmp(void *arg __attribute__((unused)))
{
}
 
#endif /* CONFIG_SMP */
 
/** @}
*/
/branches/dd/kernel/arch/mips32/src/debugger.c
33,6 → 33,7
*/
 
#include <arch/debugger.h>
#include <arch/barrier.h>
#include <memstr.h>
#include <console/kconsole.h>
#include <console/cmd.h>
46,6 → 47,8
bpinfo_t breakpoints[BKPOINTS_MAX];
SPINLOCK_INITIALIZE(bkpoint_lock);
 
#ifdef CONFIG_KCONSOLE
 
static int cmd_print_breakpoints(cmd_arg_t *argv);
static cmd_info_t bkpts_info = {
.name = "bkpts",
72,7 → 75,8
};
static cmd_info_t addbkpt_info = {
.name = "addbkpt",
.description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch insts unsupported.",
.description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch "
"insts unsupported.",
.func = cmd_add_breakpoint,
.argc = 1,
.argv = &add_argv
84,7 → 88,8
};
static cmd_info_t addbkpte_info = {
.name = "addbkpte",
.description = "addebkpte <&symbol> <&func> - new bkpoint. Call func(or Nothing if 0).",
.description = "addebkpte <&symbol> <&func> - new bkpoint. Call "
"func(or Nothing if 0).",
.func = cmd_add_breakpoint,
.argc = 2,
.argv = adde_argv
93,7 → 98,7
static struct {
uint32_t andmask;
uint32_t value;
}jmpinstr[] = {
} jmpinstr[] = {
{0xf3ff0000, 0x41000000}, /* BCzF */
{0xf3ff0000, 0x41020000}, /* BCzFL */
{0xf3ff0000, 0x41010000}, /* BCzT */
117,19 → 122,21
{0xfc000000, 0x08000000}, /* J */
{0xfc000000, 0x0c000000}, /* JAL */
{0xfc1f07ff, 0x00000009}, /* JALR */
{0,0} /* EndOfTable */
{0, 0} /* EndOfTable */
};
 
 
/** Test, if the given instruction is a jump or branch instruction
*
* @param instr Instruction code
* @return true - it is jump instruction, false otherwise
*
*/
static bool is_jump(unative_t instr)
{
int i;
 
for (i=0;jmpinstr[i].andmask;i++) {
for (i = 0; jmpinstr[i].andmask; i++) {
if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value)
return true;
}
152,21 → 159,23
spinlock_lock(&bkpoint_lock);
 
/* Check, that the breakpoints do not conflict */
for (i=0; i<BKPOINTS_MAX; i++) {
for (i = 0; i < BKPOINTS_MAX; i++) {
if (breakpoints[i].address == (uintptr_t)argv->intval) {
printf("Duplicate breakpoint %d.\n", i);
spinlock_unlock(&bkpoints_lock);
spinlock_unlock(&bkpoint_lock);
return 0;
} else if (breakpoints[i].address == (uintptr_t)argv->intval + sizeof(unative_t) || \
breakpoints[i].address == (uintptr_t)argv->intval - sizeof(unative_t)) {
printf("Adjacent breakpoints not supported, conflict with %d.\n", i);
spinlock_unlock(&bkpoints_lock);
} else if (breakpoints[i].address == (uintptr_t)argv->intval +
sizeof(unative_t) || breakpoints[i].address ==
(uintptr_t)argv->intval - sizeof(unative_t)) {
printf("Adjacent breakpoints not supported, conflict "
"with %d.\n", i);
spinlock_unlock(&bkpoint_lock);
return 0;
}
}
 
for (i=0; i<BKPOINTS_MAX; i++)
for (i = 0; i < BKPOINTS_MAX; i++)
if (!breakpoints[i].address) {
cur = &breakpoints[i];
break;
185,7 → 194,7
cur->flags = 0;
} else { /* We are add extended */
cur->flags = BKPOINT_FUNCCALL;
cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval;
cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval;
}
if (is_jump(cur->instruction))
cur->flags |= BKPOINT_ONESHOT;
193,6 → 202,7
 
/* Set breakpoint */
*((unative_t *)cur->address) = 0x0d;
smc_coherence(cur->address);
 
spinlock_unlock(&bkpoint_lock);
interrupts_restore(ipl);
200,8 → 210,6
return 1;
}
 
 
 
/** Remove breakpoint from table */
int cmd_del_breakpoint(cmd_arg_t *argv)
{
229,7 → 237,9
return 0;
}
((uint32_t *)cur->address)[0] = cur->instruction;
smc_coherence(((uint32_t *)cur->address)[0]);
((uint32_t *)cur->address)[1] = cur->nextinstruction;
smc_coherence(((uint32_t *)cur->address)[1]);
 
cur->address = NULL;
 
252,38 → 262,42
symbol = get_symtab_entry(breakpoints[i].address);
printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i,
breakpoints[i].counter, breakpoints[i].address,
((breakpoints[i].flags & BKPOINT_INPROG) ? "true" : "false"),
((breakpoints[i].flags & BKPOINT_ONESHOT) ? "true" : "false"),
((breakpoints[i].flags & BKPOINT_FUNCCALL) ? "true" : "false"),
symbol);
breakpoints[i].counter, breakpoints[i].address,
((breakpoints[i].flags & BKPOINT_INPROG) ? "true" :
"false"), ((breakpoints[i].flags & BKPOINT_ONESHOT)
? "true" : "false"), ((breakpoints[i].flags &
BKPOINT_FUNCCALL) ? "true" : "false"), symbol);
}
return 1;
}
 
#endif
 
/** Initialize debugger */
void debugger_init()
{
int i;
 
for (i=0; i<BKPOINTS_MAX; i++)
for (i = 0; i < BKPOINTS_MAX; i++)
breakpoints[i].address = NULL;
 
#ifdef CONFIG_KCONSOLE
cmd_initialize(&bkpts_info);
if (!cmd_register(&bkpts_info))
panic("could not register command %s\n", bkpts_info.name);
printf("Cannot register command %s\n", bkpts_info.name);
 
cmd_initialize(&delbkpt_info);
if (!cmd_register(&delbkpt_info))
panic("could not register command %s\n", delbkpt_info.name);
printf("Cannot register command %s\n", delbkpt_info.name);
 
cmd_initialize(&addbkpt_info);
if (!cmd_register(&addbkpt_info))
panic("could not register command %s\n", addbkpt_info.name);
printf("Cannot register command %s\n", addbkpt_info.name);
 
cmd_initialize(&addbkpte_info);
if (!cmd_register(&addbkpte_info))
panic("could not register command %s\n", addbkpte_info.name);
printf("Cannot register command %s\n", addbkpte_info.name);
#endif
}
 
/** Handle breakpoint
302,19 → 316,19
 
/* test branch delay slot */
if (cp0_cause_read() & 0x80000000)
panic("Breakpoint in branch delay slot not supported.\n");
panic("Breakpoint in branch delay slot not supported.");
 
spinlock_lock(&bkpoint_lock);
for (i=0; i<BKPOINTS_MAX; i++) {
for (i = 0; i < BKPOINTS_MAX; i++) {
/* Normal breakpoint */
if (fireaddr == breakpoints[i].address \
&& !(breakpoints[i].flags & BKPOINT_REINST)) {
if (fireaddr == breakpoints[i].address &&
!(breakpoints[i].flags & BKPOINT_REINST)) {
cur = &breakpoints[i];
break;
}
/* Reinst only breakpoint */
if ((breakpoints[i].flags & BKPOINT_REINST) \
&& (fireaddr ==breakpoints[i].address+sizeof(unative_t))) {
if ((breakpoints[i].flags & BKPOINT_REINST) &&
(fireaddr == breakpoints[i].address + sizeof(unative_t))) {
cur = &breakpoints[i];
break;
}
323,8 → 337,10
if (cur->flags & BKPOINT_REINST) {
/* Set breakpoint on first instruction */
((uint32_t *)cur->address)[0] = 0x0d;
smc_coherence(((uint32_t *)cur->address)[0]);
/* Return back the second */
((uint32_t *)cur->address)[1] = cur->nextinstruction;
smc_coherence(((uint32_t *)cur->address)[1]);
cur->flags &= ~BKPOINT_REINST;
spinlock_unlock(&bkpoint_lock);
return;
333,11 → 349,12
printf("Warning: breakpoint recursion\n");
if (!(cur->flags & BKPOINT_FUNCCALL))
printf("***Breakpoint %d: %p in %s.\n", i,
fireaddr, get_symtab_entry(istate->epc));
printf("***Breakpoint %d: %p in %s.\n", i, fireaddr,
get_symtab_entry(istate->epc));
 
/* Return first instruction back */
((uint32_t *)cur->address)[0] = cur->instruction;
smc_coherence(cur->address);
 
if (! (cur->flags & BKPOINT_ONESHOT)) {
/* Set Breakpoint on next instruction */
358,19 → 375,20
if (cur->bkfunc)
cur->bkfunc(cur, istate);
} else {
printf("***Type 'exit' to exit kconsole.\n");
#ifdef CONFIG_KCONSOLE
/* This disables all other processors - we are not SMP,
* actually this gets us to cpu_halt, if scheduler() is run
* - we generally do not want scheduler to be run from debug,
* so this is a good idea
*/
atomic_set(&haltstate,1);
atomic_set(&haltstate, 1);
spinlock_unlock(&bkpoint_lock);
 
kconsole("debug");
 
kconsole("debug", "Debug console ready (type 'exit' to continue)\n", false);
spinlock_lock(&bkpoint_lock);
atomic_set(&haltstate,0);
atomic_set(&haltstate, 0);
#endif
}
if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) {
/* Remove one-shot breakpoint */
/branches/dd/kernel/arch/mips32/src/mm/tlb.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32mm
/** @addtogroup mips32mm
* @{
*/
/** @file
41,24 → 41,20
#include <panic.h>
#include <arch.h>
#include <symtab.h>
#include <synch/spinlock.h>
#include <synch/mutex.h>
#include <print.h>
#include <debug.h>
#include <align.h>
#include <interrupt.h>
 
static void tlb_refill_fail(istate_t *istate);
static void tlb_invalid_fail(istate_t *istate);
static void tlb_modified_fail(istate_t *istate);
static void tlb_refill_fail(istate_t *);
static void tlb_invalid_fail(istate_t *);
static void tlb_modified_fail(istate_t *);
 
static pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc);
static pte_t *find_mapping_and_check(uintptr_t, int, istate_t *, int *);
 
static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn);
static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr);
 
/** Initialize TLB
/** Initialize TLB.
*
* Initialize TLB.
* Invalidate all entries and mark wired entries.
*/
void tlb_arch_init(void)
76,7 → 72,6
cp0_index_write(i);
tlbwi();
}
 
/*
* The kernel is going to make use of some wired
85,11 → 80,9
cp0_wired_write(TLB_WIRED);
}
 
/** Process TLB Refill Exception
/** Process TLB Refill Exception.
*
* Process TLB Refill Exception.
*
* @param istate Interrupted register context.
* @param istate Interrupted register context.
*/
void tlb_refill(istate_t *istate)
{
99,15 → 92,15
uintptr_t badvaddr;
pte_t *pte;
int pfrc;
 
badvaddr = cp0_badvaddr_read();
 
spinlock_lock(&AS->lock);
mutex_lock(&AS->lock);
asid = AS->asid;
spinlock_unlock(&AS->lock);
 
mutex_unlock(&AS->lock);
page_table_lock(AS, true);
 
pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate, &pfrc);
if (!pte) {
switch (pfrc) {
122,7 → 115,7
page_table_unlock(AS, true);
return;
default:
panic("unexpected pfrc (%d)\n", pfrc);
panic("Unexpected pfrc (%d).", pfrc);
}
}
 
131,14 → 124,15
*/
pte->a = 1;
 
prepare_entry_hi(&hi, asid, badvaddr);
prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn);
tlb_prepare_entry_hi(&hi, asid, badvaddr);
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable,
pte->pfn);
 
/*
* New entry is to be inserted into TLB
*/
cp0_entry_hi_write(hi.value);
if ((badvaddr/PAGE_SIZE) % 2 == 0) {
if ((badvaddr / PAGE_SIZE) % 2 == 0) {
cp0_entry_lo0_write(lo.value);
cp0_entry_lo1_write(0);
}
157,11 → 151,9
tlb_refill_fail(istate);
}
 
/** Process TLB Invalid Exception
/** Process TLB Invalid Exception.
*
* Process TLB Invalid Exception.
*
* @param istate Interrupted register context.
* @param istate Interrupted register context.
*/
void tlb_invalid(istate_t *istate)
{
178,7 → 170,7
* Locate the faulting entry in TLB.
*/
hi.value = cp0_entry_hi_read();
prepare_entry_hi(&hi, hi.asid, badvaddr);
tlb_prepare_entry_hi(&hi, hi.asid, badvaddr);
cp0_entry_hi_write(hi.value);
tlbp();
index.value = cp0_index_read();
207,7 → 199,7
page_table_unlock(AS, true);
return;
default:
panic("unexpected pfrc (%d)\n", pfrc);
panic("Unexpected pfrc (%d).", pfrc);
}
}
 
221,12 → 213,13
*/
pte->a = 1;
 
prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn);
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable,
pte->pfn);
 
/*
* The entry is to be updated in TLB.
*/
if ((badvaddr/PAGE_SIZE) % 2 == 0)
if ((badvaddr / PAGE_SIZE) % 2 == 0)
cp0_entry_lo0_write(lo.value);
else
cp0_entry_lo1_write(lo.value);
241,11 → 234,9
tlb_invalid_fail(istate);
}
 
/** Process TLB Modified Exception
/** Process TLB Modified Exception.
*
* Process TLB Modified Exception.
*
* @param istate Interrupted register context.
* @param istate Interrupted register context.
*/
void tlb_modified(istate_t *istate)
{
262,7 → 253,7
* Locate the faulting entry in TLB.
*/
hi.value = cp0_entry_hi_read();
prepare_entry_hi(&hi, hi.asid, badvaddr);
tlb_prepare_entry_hi(&hi, hi.asid, badvaddr);
cp0_entry_hi_write(hi.value);
tlbp();
index.value = cp0_index_read();
291,17 → 282,11
page_table_unlock(AS, true);
return;
default:
panic("unexpected pfrc (%d)\n", pfrc);
panic("Unexpected pfrc (%d).", pfrc);
}
}
 
/*
* Fail if the page is not writable.
*/
if (!pte->w)
goto fail;
 
/*
* Read the faulting TLB entry.
*/
tlbr();
312,12 → 297,13
pte->a = 1;
pte->d = 1;
 
prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable, pte->pfn);
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable,
pte->pfn);
 
/*
* The entry is to be updated in TLB.
*/
if ((badvaddr/PAGE_SIZE) % 2 == 0)
if ((badvaddr / PAGE_SIZE) % 2 == 0)
cp0_entry_lo0_write(lo.value);
else
cp0_entry_lo1_write(lo.value);
344,8 → 330,10
if (s)
sym2 = s;
 
fault_if_from_uspace(istate, "TLB Refill Exception on %p", cp0_badvaddr_read());
panic("%x: TLB Refill Exception at %x(%s<-%s)\n", cp0_badvaddr_read(), istate->epc, symbol, sym2);
fault_if_from_uspace(istate, "TLB Refill Exception on %p.",
cp0_badvaddr_read());
panic("%x: TLB Refill Exception at %x(%s<-%s).", cp0_badvaddr_read(),
istate->epc, symbol, sym2);
}
 
 
356,8 → 344,10
char *s = get_symtab_entry(istate->epc);
if (s)
symbol = s;
fault_if_from_uspace(istate, "TLB Invalid Exception on %p", cp0_badvaddr_read());
panic("%x: TLB Invalid Exception at %x(%s)\n", cp0_badvaddr_read(), istate->epc, symbol);
fault_if_from_uspace(istate, "TLB Invalid Exception on %p.",
cp0_badvaddr_read());
panic("%x: TLB Invalid Exception at %x(%s).", cp0_badvaddr_read(),
istate->epc, symbol);
}
 
void tlb_modified_fail(istate_t *istate)
367,23 → 357,27
char *s = get_symtab_entry(istate->epc);
if (s)
symbol = s;
fault_if_from_uspace(istate, "TLB Modified Exception on %p", cp0_badvaddr_read());
panic("%x: TLB Modified Exception at %x(%s)\n", cp0_badvaddr_read(), istate->epc, symbol);
fault_if_from_uspace(istate, "TLB Modified Exception on %p.",
cp0_badvaddr_read());
panic("%x: TLB Modified Exception at %x(%s).", cp0_badvaddr_read(),
istate->epc, symbol);
}
 
/** Try to find PTE for faulting address
/** Try to find PTE for faulting address.
*
* Try to find PTE for faulting address.
* The AS->lock must be held on entry to this function.
*
* @param badvaddr Faulting virtual address.
* @param access Access mode that caused the fault.
* @param istate Pointer to interrupted state.
* @param pfrc Pointer to variable where as_page_fault() return code will be stored.
* @param badvaddr Faulting virtual address.
* @param access Access mode that caused the fault.
* @param istate Pointer to interrupted state.
* @param pfrc Pointer to variable where as_page_fault() return code
* will be stored.
*
* @return PTE on success, NULL otherwise.
* @return PTE on success, NULL otherwise.
*/
pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc)
pte_t *
find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate,
int *pfrc)
{
entry_hi_t hi;
pte_t *pte;
402,7 → 396,7
* Check if the mapping exists in page tables.
*/
pte = page_mapping_find(AS, badvaddr);
if (pte && pte->p) {
if (pte && pte->p && (pte->w || access != PF_ACCESS_WRITE)) {
/*
* Mapping found in page tables.
* Immediately succeed.
425,6 → 419,7
page_table_lock(AS, true);
pte = page_mapping_find(AS, badvaddr);
ASSERT(pte && pte->p);
ASSERT(pte->w || access != PF_ACCESS_WRITE);
return pte;
break;
case AS_PF_DEFER:
434,18 → 429,19
break;
case AS_PF_FAULT:
page_table_lock(AS, true);
printf("Page fault.\n");
*pfrc = AS_PF_FAULT;
return NULL;
break;
default:
panic("unexpected rc (%d)\n", rc);
panic("Unexpected rc (%d).", rc);
}
}
}
 
void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn)
void
tlb_prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable,
uintptr_t pfn)
{
lo->value = 0;
lo->g = g;
455,7 → 451,7
lo->pfn = pfn;
}
 
void prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr)
void tlb_prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr)
{
hi->value = ALIGN_DOWN(addr, PAGE_SIZE * 2);
hi->asid = asid;
484,10 → 480,10
lo1.value = cp0_entry_lo1_read();
printf("%-2u %-4u %#6x %#4x %1u %1u %1u %1u %#6x\n",
i, hi.asid, hi.vpn2, mask.mask,
lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn);
i, hi.asid, hi.vpn2, mask.mask,
lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn);
printf(" %1u %1u %1u %1u %#6x\n",
lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn);
lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn);
}
cp0_entry_hi_write(hi_save.value);
564,11 → 560,12
cp0_entry_hi_write(hi_save.value);
}
 
/** Invalidate TLB entries for specified page range belonging to specified address space.
/** Invalidate TLB entries for specified page range belonging to specified
* address space.
*
* @param asid Address space identifier.
* @param page First page whose TLB entry is to be invalidated.
* @param cnt Number of entries to invalidate.
* @param asid Address space identifier.
* @param page First page whose TLB entry is to be invalidated.
* @param cnt Number of entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
{
585,7 → 582,7
 
for (i = 0; i < cnt + 1; i += 2) {
hi.value = 0;
prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE);
tlb_prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE);
cp0_entry_hi_write(hi.value);
 
tlbp();
592,7 → 589,10
index.value = cp0_index_read();
 
if (!index.p) {
/* Entry was found, index register contains valid index. */
/*
* Entry was found, index register contains valid
* index.
*/
tlbr();
 
lo0.value = cp0_entry_lo0_read();
/branches/dd/kernel/arch/mips32/src/mm/as.c
44,7 → 44,7
/** Architecture dependent address space init. */
void as_arch_init(void)
{
as_operations = &as_pt_operations;
as_operations = &as_pt_operations;
asid_fifo_init();
}
 
/branches/dd/kernel/arch/mips32/src/mm/frame.c
26,33 → 26,244
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32mm
/** @addtogroup mips32mm
* @{
*/
/** @file
*/
 
#include <macros.h>
#include <arch/mm/frame.h>
#include <arch/mm/tlb.h>
#include <interrupt.h>
#include <mm/frame.h>
#include <mm/asid.h>
#include <config.h>
#include <arch/drivers/arc.h>
#include <arch/drivers/msim.h>
#include <arch/drivers/serial.h>
#include <print.h>
 
#define ZERO_PAGE_MASK TLB_PAGE_MASK_256K
#define ZERO_FRAMES 2048
#define ZERO_PAGE_WIDTH 18 /* 256K */
#define ZERO_PAGE_SIZE (1 << ZERO_PAGE_WIDTH)
#define ZERO_PAGE_ASID ASID_INVALID
#define ZERO_PAGE_TLBI 0
#define ZERO_PAGE_ADDR 0
#define ZERO_PAGE_OFFSET (ZERO_PAGE_SIZE / sizeof(uint32_t) - 1)
#define ZERO_PAGE_VALUE (((volatile uint32_t *) ZERO_PAGE_ADDR)[ZERO_PAGE_OFFSET])
 
#define ZERO_PAGE_VALUE_KSEG1(frame) (((volatile uint32_t *) (0xa0000000 + (frame << ZERO_PAGE_WIDTH)))[ZERO_PAGE_OFFSET])
 
#define MAX_REGIONS 32
 
typedef struct {
pfn_t start;
pfn_t count;
} phys_region_t;
 
static count_t phys_regions_count = 0;
static phys_region_t phys_regions[MAX_REGIONS];
 
 
/** Check whether frame is available
*
* Returns true if given frame is generally available for use.
* Returns false if given frame is used for physical memory
* mapped devices and cannot be used.
*
*/
static bool frame_available(pfn_t frame)
{
#ifdef MACHINE_msim
/* MSIM device (dprinter) */
if (frame == (KA2PA(MSIM_VIDEORAM) >> ZERO_PAGE_WIDTH))
return false;
/* MSIM device (dkeyboard) */
if (frame == (KA2PA(MSIM_KBD_ADDRESS) >> ZERO_PAGE_WIDTH))
return false;
#endif
 
#ifdef MACHINE_simics
/* Simics device (serial line) */
if (frame == (KA2PA(SERIAL_ADDRESS) >> ZERO_PAGE_WIDTH))
return false;
#endif
 
#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)
/* gxemul devices */
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
0x10000000, MB2SIZE(256)))
return false;
#endif
return true;
}
 
 
/** Check whether frame is safe to write
*
* Returns true if given frame is safe for read/write test.
* Returns false if given frame should not be touched.
*
*/
static bool frame_safe(pfn_t frame)
{
/* Kernel structures */
if ((frame << ZERO_PAGE_WIDTH) < KA2PA(config.base))
return false;
/* Kernel */
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
KA2PA(config.base), config.kernel_size))
return false;
/* Kernel stack */
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
KA2PA(config.stack_base), config.stack_size))
return false;
/* Init tasks */
bool safe = true;
count_t i;
for (i = 0; i < init.cnt; i++)
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
KA2PA(init.tasks[i].addr), init.tasks[i].size)) {
safe = false;
break;
}
return safe;
}
 
static void frame_add_region(pfn_t start_frame, pfn_t end_frame)
{
if (end_frame > start_frame) {
/* Convert 1M frames to 16K frames */
pfn_t first = ADDR2PFN(start_frame << ZERO_PAGE_WIDTH);
pfn_t count = ADDR2PFN((end_frame - start_frame) << ZERO_PAGE_WIDTH);
/* Interrupt vector frame is blacklisted */
pfn_t conf_frame;
if (first == 0)
conf_frame = 1;
else
conf_frame = first;
zone_create(first, count, conf_frame, 0);
if (phys_regions_count < MAX_REGIONS) {
phys_regions[phys_regions_count].start = first;
phys_regions[phys_regions_count].count = count;
phys_regions_count++;
}
}
}
 
 
/** Create memory zones
*
* If ARC is known, read information from ARC, otherwise
* assume some defaults.
* - blacklist first FRAME because there is an exception vector
* Walk through available 256 KB chunks of physical
* memory and create zones.
*
* Note: It is assumed that the TLB is not yet being
* used in any way, thus there is no interference.
*
*/
void frame_arch_init(void)
{
if (!arc_frame_init()) {
zone_create(0, ADDR2PFN(CONFIG_MEMORY_SIZE), 1, 0);
/*
* Blacklist interrupt vector
*/
frame_mark_unavailable(0, 1);
ipl_t ipl = interrupts_disable();
/* Clear and initialize TLB */
cp0_pagemask_write(ZERO_PAGE_MASK);
cp0_entry_lo0_write(0);
cp0_entry_lo1_write(0);
cp0_entry_hi_write(0);
 
count_t i;
for (i = 0; i < TLB_ENTRY_COUNT; i++) {
cp0_index_write(i);
tlbwi();
}
pfn_t start_frame = 0;
pfn_t frame;
bool avail = true;
/* Walk through all 1 MB frames */
for (frame = 0; frame < ZERO_FRAMES; frame++) {
if (!frame_available(frame))
avail = false;
else {
if (frame_safe(frame)) {
entry_lo_t lo0;
entry_lo_t lo1;
entry_hi_t hi;
tlb_prepare_entry_lo(&lo0, false, true, true, false, frame << (ZERO_PAGE_WIDTH - 12));
tlb_prepare_entry_lo(&lo1, false, false, false, false, 0);
tlb_prepare_entry_hi(&hi, ZERO_PAGE_ASID, ZERO_PAGE_ADDR);
cp0_pagemask_write(ZERO_PAGE_MASK);
cp0_entry_lo0_write(lo0.value);
cp0_entry_lo1_write(lo1.value);
cp0_entry_hi_write(hi.value);
cp0_index_write(ZERO_PAGE_TLBI);
tlbwi();
ZERO_PAGE_VALUE = 0;
if (ZERO_PAGE_VALUE != 0)
avail = false;
else {
ZERO_PAGE_VALUE = 0xdeadbeef;
if (ZERO_PAGE_VALUE != 0xdeadbeef)
avail = false;
#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)
else {
ZERO_PAGE_VALUE_KSEG1(frame) = 0xaabbccdd;
if (ZERO_PAGE_VALUE_KSEG1(frame) != 0xaabbccdd)
avail = false;
}
#endif
}
}
}
if (!avail) {
frame_add_region(start_frame, frame);
start_frame = frame + 1;
avail = true;
}
}
frame_add_region(start_frame, frame);
/* Blacklist interrupt vector frame */
frame_mark_unavailable(0, 1);
/* Cleanup */
cp0_pagemask_write(ZERO_PAGE_MASK);
cp0_entry_lo0_write(0);
cp0_entry_lo1_write(0);
cp0_entry_hi_write(0);
cp0_index_write(ZERO_PAGE_TLBI);
tlbwi();
interrupts_restore(ipl);
}
 
 
void physmem_print(void)
{
printf("Base Size\n");
printf("---------- ----------\n");
count_t i;
for (i = 0; i < phys_regions_count; i++) {
printf("%#010x %10u\n",
PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count));
}
}
 
/** @}
*/
/branches/dd/kernel/arch/mips32/src/mm/page.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32mm
/** @addtogroup mips32mm
* @{
*/
/** @file
35,6 → 35,7
#include <arch/mm/page.h>
#include <genarch/mm/page_pt.h>
#include <mm/page.h>
#include <mm/frame.h>
 
void page_arch_init(void)
{
/branches/dd/kernel/arch/mips32/src/interrupt.c
38,12 → 38,12
#include <arch.h>
#include <arch/cp0.h>
#include <time/clock.h>
#include <arch/drivers/arc.h>
#include <ipc/sysipc.h>
#include <ddi/device.h>
 
#define IRQ_COUNT 8
#define TIMER_IRQ 7
#define IRQ_COUNT 8
#define TIMER_IRQ 7
#define DORDER_IRQ 5
 
function virtual_timer_fnc = NULL;
static irq_t timer_irq;
101,12 → 101,12
cp0_compare_write(nextcount);
}
 
static irq_ownership_t timer_claim(void)
static irq_ownership_t timer_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
static void timer_irq_handler(irq_t *irq, void *arg, ...)
static void timer_irq_handler(irq_t *irq)
{
unsigned long drift;
/branches/dd/kernel/arch/mips32/src/drivers/serial.c
File deleted
/branches/dd/kernel/arch/mips32/src/drivers/arc.c
File deleted
/branches/dd/kernel/arch/mips32/src/drivers/msim.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32
/** @addtogroup mips32
* @{
*/
/** @file
33,22 → 33,17
*/
 
#include <interrupt.h>
#include <ipc/irq.h>
#include <console/chardev.h>
#include <arch/drivers/msim.h>
#include <arch/cp0.h>
#include <console/console.h>
#include <sysinfo/sysinfo.h>
#include <ddi/ddi.h>
 
/** Address of devices. */
#define MSIM_VIDEORAM 0xB0000000
#define MSIM_KBD_ADDRESS 0xB0000000
#define MSIM_KBD_IRQ 2
 
static chardev_t console;
static irq_t msim_irq;
 
static void msim_write(chardev_t *dev, const char ch);
static void msim_write(chardev_t *dev, const char ch, bool silent);
static void msim_enable(chardev_t *dev);
static void msim_disable(chardev_t *dev);
static char msim_do_read(chardev_t *dev);
61,9 → 56,10
};
 
/** Putchar that works with MSIM & gxemul */
void msim_write(chardev_t *dev, const char ch)
void msim_write(chardev_t *dev, const char ch, bool silent)
{
*((char *) MSIM_VIDEORAM) = ch;
if (!silent)
*((char *) MSIM_VIDEORAM) = ch;
}
 
/* Called from getc(). */
78,12 → 74,11
cp0_mask_int(MSIM_KBD_IRQ);
}
 
#include <print.h>
/** Read character using polling, assume interrupts disabled */
static char msim_do_read(chardev_t *dev)
{
char ch;
 
while (1) {
ch = *((volatile char *) MSIM_KBD_ADDRESS);
if (ch) {
97,23 → 92,19
}
 
/** Process keyboard interrupt. */
static void msim_irq_handler(irq_t *irq, void *arg, ...)
static void msim_irq_handler(irq_t *irq)
{
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox))
ipc_irq_send_notif(irq);
else {
char ch = 0;
char ch = 0;
ch = *((char *) MSIM_KBD_ADDRESS);
if (ch =='\r')
ch = '\n';
if (ch == 0x7f)
ch = '\b';
chardev_push_character(&console, ch);
}
ch = *((char *) MSIM_KBD_ADDRESS);
if (ch =='\r')
ch = '\n';
if (ch == 0x7f)
ch = '\b';
chardev_push_character(&console, ch);
}
 
static irq_ownership_t msim_claim(void)
static irq_ownership_t msim_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
158,6 → 149,10
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, MSIM_KBD_IRQ);
sysinfo_set_item_val("kbd.address.virtual", NULL, MSIM_KBD_ADDRESS);
sysinfo_set_item_val("fb", NULL, true);
sysinfo_set_item_val("fb.kind", NULL, 3);
sysinfo_set_item_val("fb.address.physical", NULL, KA2PA(MSIM_VIDEORAM));
}
 
/** @}
/branches/dd/kernel/arch/ia32/_link.ld.in
1,11 → 1,11
/** IA-32 linker script
*
*
* umapped section:
* kernel text
* kernel data
* kernel text
* kernel data
* mapped section:
* kernel text
* kernel data
* kernel text
* kernel data
*/
 
#include <arch/boot/boot.h>
28,9 → 28,9
ktext_end = .;
kdata_start = .;
*(.data); /* initialized data */
*(.rodata*); /* string literals */
*(COMMON); /* global variables */
*(.data); /* initialized data */
*(.rodata*); /* string literals */
*(COMMON); /* global variables */
hardcoded_load_address = .;
LONG(PA2KA(BOOT_OFFSET));
hardcoded_ktext_size = .;
42,23 → 42,23
hardcoded_unmapped_kdata_size = .;
LONG(unmapped_kdata_end - unmapped_kdata_start);
symbol_table = .;
*(symtab.*); /* Symbol table, must be LAST symbol! */
*(.bss); /* uninitialized static variables */
*(symtab.*); /* Symbol table, must be LAST symbol! */
*(.bss); /* uninitialized static variables */
kdata_end = .;
}
 
/DISCARD/ : {
*(.note.GNU-stack);
*(.note.GNU-stack);
*(.comment);
}
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
_hardcoded_unmapped_size = (unmapped_ktext_end - unmapped_ktext_start) + (unmapped_kdata_end - unmapped_kdata_start);
ap_boot = unmapped_ap_boot - BOOT_OFFSET + AP_BOOT_OFFSET;
ap_gdtr = unmapped_ap_gdtr - BOOT_OFFSET + AP_BOOT_OFFSET;
protected_ap_gdtr = PA2KA(ap_gdtr);
 
#endif /* CONFIG_SMP */
 
}
/branches/dd/kernel/arch/ia32/include/interrupt.h
72,10 → 72,6
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t esi;
uint32_t edi;
uint32_t ebp;
uint32_t ebx;
 
uint32_t gs;
uint32_t fs;
/branches/dd/kernel/arch/ia32/include/fpu_context.h
37,7 → 37,6
 
#include <arch/types.h>
 
#define ARCH_HAS_FPU
#define FPU_CONTEXT_ALIGN 16
 
void fpu_fxsr(void);
/branches/dd/kernel/arch/ia32/include/cpuid.h
74,21 → 74,21
uint32_t val, ret;
asm volatile (
"pushf\n" /* read flags */
"popl %0\n"
"movl %0, %1\n"
"pushf\n" /* read flags */
"popl %[ret]\n"
"movl %[ret], %[val]\n"
"btcl $21, %1\n" /* swap the ID bit */
"btcl $21, %[val]\n" /* swap the ID bit */
"pushl %1\n" /* propagate the change into flags */
"pushl %[val]\n" /* propagate the change into flags */
"popf\n"
"pushf\n"
"popl %1\n"
"popl %[val]\n"
"andl $(1 << 21), %0\n" /* interrested only in ID bit */
"andl $(1 << 21), %1\n"
"xorl %1, %0\n"
: "=r" (ret), "=r" (val)
"andl $(1 << 21), %[ret]\n" /* interrested only in ID bit */
"andl $(1 << 21), %[val]\n"
"xorl %[val], %[ret]\n"
: [ret] "=r" (ret), [val] "=r" (val)
);
return ret;
98,7 → 98,8
{
asm volatile (
"cpuid\n"
: "=a" (info->cpuid_eax), "=b" (info->cpuid_ebx), "=c" (info->cpuid_ecx), "=d" (info->cpuid_edx)
: "=a" (info->cpuid_eax), "=b" (info->cpuid_ebx),
"=c" (info->cpuid_ecx), "=d" (info->cpuid_edx)
: "a" (cmd)
);
}
/branches/dd/kernel/arch/ia32/include/types.h
35,10 → 35,6
#ifndef KERN_ia32_TYPES_H_
#define KERN_ia32_TYPES_H_
 
#define NULL 0
#define false 0
#define true 1
 
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed long int32_t;
61,14 → 57,32
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef uint8_t bool;
typedef uint64_t thread_id_t;
typedef uint64_t task_id_t;
typedef uint32_t context_id_t;
typedef struct {
} fncptr_t;
 
typedef int32_t inr_t;
typedef int32_t devno_t;
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
#define PRIi "u" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
#define PRId32 "d" /**< Format for int32_t. */
#define PRId64 "lld" /**< Format for int64_t. */
#define PRIdn "d" /**< Format for native_t. */
 
#define PRIu8 "u" /**< Format for uint8_t. */
#define PRIu16 "u" /**< Format for uint16_t. */
#define PRIu32 "u" /**< Format for uint32_t. */
#define PRIu64 "llu" /**< Format for uint64_t. */
#define PRIun "u" /**< Format for unative_t. */
 
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */
#define PRIx64 "llx" /**< Format for hexadecimal (u)int64_t. */
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */
 
/** Page Table Entry. */
typedef struct {
unsigned present : 1;
/branches/dd/kernel/arch/ia32/include/memstr.h
35,116 → 35,13
#ifndef KERN_ia32_MEMSTR_H_
#define KERN_ia32_MEMSTR_H_
 
/** Copy memory
*
* Copy a given number of bytes (3rd argument)
* from the memory location defined by 2nd argument
* to the memory location defined by 1st argument.
* The memory areas cannot overlap.
*
* @param dst Destination
* @param src Source
* @param cnt Number of bytes
* @return Destination
*/
static inline void * memcpy(void * dst, const void * src, size_t cnt)
{
unative_t d0, d1, d2;
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt))
 
asm volatile(
/* copy all full dwords */
"rep movsl\n\t"
/* load count again */
"movl %4, %%ecx\n\t"
/* ecx = ecx mod 4 */
"andl $3, %%ecx\n\t"
/* are there last <=3 bytes? */
"jz 1f\n\t"
/* copy last <=3 bytes */
"rep movsb\n\t"
/* exit from asm block */
"1:\n"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
: "0" ((unative_t) (cnt / 4)), "g" ((unative_t) cnt), "1" ((unative_t) dst), "2" ((unative_t) src)
: "memory");
extern void memsetw(void *dst, size_t cnt, uint16_t x);
extern void memsetb(void *dst, size_t cnt, uint8_t x);
 
return dst;
}
extern int memcmp(const void *a, const void *b, size_t cnt);
 
 
/** Compare memory regions for equality
*
* Compare a given number of bytes (3rd argument)
* at memory locations defined by 1st and 2nd argument
* for equality. If bytes are equal function returns 0.
*
* @param src Region 1
* @param dst Region 2
* @param cnt Number of bytes
* @return Zero if bytes are equal, non-zero otherwise
*/
static inline int memcmp(const void * src, const void * dst, size_t cnt)
{
uint32_t d0, d1, d2;
int ret;
asm (
"repe cmpsb\n\t"
"je 1f\n\t"
"movl %3, %0\n\t"
"addl $1, %0\n\t"
"1:\n"
: "=a" (ret), "=%S" (d0), "=&D" (d1), "=&c" (d2)
: "0" (0), "1" ((unative_t) src), "2" ((unative_t) dst), "3" ((unative_t) cnt)
);
return ret;
}
 
/** Fill memory with words
* Fill a given number of words (2nd argument)
* at memory defined by 1st argument with the
* word value defined by 3rd argument.
*
* @param dst Destination
* @param cnt Number of words
* @param x Value to fill
*/
static inline void memsetw(uintptr_t dst, size_t cnt, uint16_t x)
{
uint32_t d0, d1;
asm volatile (
"rep stosw\n\t"
: "=&D" (d0), "=&c" (d1), "=a" (x)
: "0" (dst), "1" (cnt), "2" (x)
: "memory"
);
 
}
 
/** Fill memory with bytes
* Fill a given number of bytes (2nd argument)
* at memory defined by 1st argument with the
* word value defined by 3rd argument.
*
* @param dst Destination
* @param cnt Number of bytes
* @param x Value to fill
*/
static inline void memsetb(uintptr_t dst, size_t cnt, uint8_t x)
{
uint32_t d0, d1;
asm volatile (
"rep stosb\n\t"
: "=&D" (d0), "=&c" (d1), "=a" (x)
: "0" (dst), "1" (cnt), "2" (x)
: "memory"
);
 
}
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia32/include/smp/apic.h
105,8 → 105,8
#define MODEL_CLUSTER 0x0
 
/** Interrupt Command Register. */
#define ICRlo (0x300/sizeof(uint32_t))
#define ICRhi (0x310/sizeof(uint32_t))
#define ICRlo (0x300 / sizeof(uint32_t))
#define ICRhi (0x310 / sizeof(uint32_t))
typedef struct {
union {
uint32_t lo;
133,10 → 133,10
} __attribute__ ((packed)) icr_t;
 
/* End Of Interrupt. */
#define EOI (0x0b0/sizeof(uint32_t))
#define EOI (0x0b0 / sizeof(uint32_t))
 
/** Error Status Register. */
#define ESR (0x280/sizeof(uint32_t))
#define ESR (0x280 / sizeof(uint32_t))
typedef union {
uint32_t value;
uint8_t err_bitmap;
154,7 → 154,7
} esr_t;
 
/* Task Priority Register */
#define TPR (0x080/sizeof(uint32_t))
#define TPR (0x080 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
164,7 → 164,7
} tpr_t;
 
/** Spurious-Interrupt Vector Register. */
#define SVR (0x0f0/sizeof(uint32_t))
#define SVR (0x0f0 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
176,7 → 176,7
} svr_t;
 
/** Time Divide Configuration Register. */
#define TDCR (0x3e0/sizeof(uint32_t))
#define TDCR (0x3e0 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
186,13 → 186,13
} tdcr_t;
 
/* Initial Count Register for Timer */
#define ICRT (0x380/sizeof(uint32_t))
#define ICRT (0x380 / sizeof(uint32_t))
 
/* Current Count Register for Timer */
#define CCRT (0x390/sizeof(uint32_t))
#define CCRT (0x390 / sizeof(uint32_t))
 
/** LVT Timer register. */
#define LVT_Tm (0x320/sizeof(uint32_t))
#define LVT_Tm (0x320 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
207,8 → 207,8
} lvt_tm_t;
 
/** LVT LINT registers. */
#define LVT_LINT0 (0x350/sizeof(uint32_t))
#define LVT_LINT1 (0x360/sizeof(uint32_t))
#define LVT_LINT0 (0x350 / sizeof(uint32_t))
#define LVT_LINT1 (0x360 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
225,7 → 225,7
} lvt_lint_t;
 
/** LVT Error register. */
#define LVT_Err (0x370/sizeof(uint32_t))
#define LVT_Err (0x370 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
239,7 → 239,7
} lvt_error_t;
 
/** Local APIC ID Register. */
#define L_APIC_ID (0x020/sizeof(uint32_t))
#define L_APIC_ID (0x020 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
249,14 → 249,14
} l_apic_id_t;
 
/** Local APIC Version Register */
#define LAVR (0x030/sizeof(uint32_t))
#define LAVR (0x030 / sizeof(uint32_t))
#define LAVR_Mask 0xff
#define is_local_apic(x) (((x)&LAVR_Mask&0xf0)==0x1)
#define is_82489DX_apic(x) ((((x)&LAVR_Mask&0xf0)==0x0))
#define is_local_xapic(x) (((x)&LAVR_Mask)==0x14)
#define is_local_apic(x) (((x) & LAVR_Mask & 0xf0) == 0x1)
#define is_82489DX_apic(x) ((((x) & LAVR_Mask & 0xf0) == 0x0))
#define is_local_xapic(x) (((x) & LAVR_Mask) == 0x14)
 
/** Logical Destination Register. */
#define LDR (0x0d0/sizeof(uint32_t))
#define LDR (0x0d0 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
266,7 → 266,7
} ldr_t;
 
/** Destination Format Register. */
#define DFR (0x0e0/sizeof(uint32_t))
#define DFR (0x0e0 / sizeof(uint32_t))
typedef union {
uint32_t value;
struct {
276,8 → 276,8
} dfr_t;
 
/* IO APIC */
#define IOREGSEL (0x00/sizeof(uint32_t))
#define IOWIN (0x10/sizeof(uint32_t))
#define IOREGSEL (0x00 / sizeof(uint32_t))
#define IOWIN (0x10 / sizeof(uint32_t))
 
#define IOAPICID 0x00
#define IOAPICVER 0x01
/branches/dd/kernel/arch/ia32/include/syscall.h
0,0 → 1,0
link ../../amd64/include/syscall.h
Property changes:
Added: svn:special
+*
\ No newline at end of property
/branches/dd/kernel/arch/ia32/include/atomic.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
41,17 → 41,29
 
static inline void atomic_inc(atomic_t *val) {
#ifdef CONFIG_SMP
asm volatile ("lock incl %0\n" : "=m" (val->count));
asm volatile (
"lock incl %[count]\n"
: [count] "+m" (val->count)
);
#else
asm volatile ("incl %0\n" : "=m" (val->count));
asm volatile (
"incl %[count]\n"
: [count] "+m" (val->count)
);
#endif /* CONFIG_SMP */
}
 
static inline void atomic_dec(atomic_t *val) {
#ifdef CONFIG_SMP
asm volatile ("lock decl %0\n" : "=m" (val->count));
asm volatile (
"lock decl %[count]\n"
: [count] "+m" (val->count)
);
#else
asm volatile ("decl %0\n" : "=m" (val->count));
asm volatile (
"decl %[count]\n"
: "+m" (val->count)
);
#endif /* CONFIG_SMP */
}
 
58,12 → 70,12
static inline long atomic_postinc(atomic_t *val)
{
long r = 1;
 
asm volatile (
"lock xaddl %1, %0\n"
: "=m" (val->count), "+r" (r)
"lock xaddl %[r], %[count]\n"
: [count] "+m" (val->count), [r] "+r" (r)
);
 
return r;
}
 
72,23 → 84,23
long r = -1;
asm volatile (
"lock xaddl %1, %0\n"
: "=m" (val->count), "+r"(r)
"lock xaddl %[r], %[count]\n"
: [count] "+m" (val->count), [r] "+r"(r)
);
return r;
}
 
#define atomic_preinc(val) (atomic_postinc(val)+1)
#define atomic_predec(val) (atomic_postdec(val)-1)
#define atomic_preinc(val) (atomic_postinc(val) + 1)
#define atomic_predec(val) (atomic_postdec(val) - 1)
 
static inline uint32_t test_and_set(atomic_t *val) {
uint32_t v;
asm volatile (
"movl $1, %0\n"
"xchgl %0, %1\n"
: "=r" (v),"=m" (val->count)
"movl $1, %[v]\n"
"xchgl %[v], %[count]\n"
: [v] "=r" (v), [count] "+m" (val->count)
);
return v;
98,23 → 110,23
static inline void atomic_lock_arch(atomic_t *val)
{
uint32_t tmp;
 
preemption_disable();
asm volatile (
"0:;"
"0:\n"
#ifdef CONFIG_HT
"pause;" /* Pentium 4's HT love this instruction */
"pause\n" /* Pentium 4's HT love this instruction */
#endif
"mov %0, %1;"
"testl %1, %1;"
"jnz 0b;" /* Lightweight looping on locked spinlock */
"mov %[count], %[tmp]\n"
"testl %[tmp], %[tmp]\n"
"jnz 0b\n" /* lightweight looping on locked spinlock */
"incl %1;" /* now use the atomic operation */
"xchgl %0, %1;"
"testl %1, %1;"
"jnz 0b;"
: "=m"(val->count),"=r"(tmp)
);
"incl %[tmp]\n" /* now use the atomic operation */
"xchgl %[count], %[tmp]\n"
"testl %[tmp], %[tmp]\n"
"jnz 0b\n"
: [count] "+m" (val->count), [tmp] "=&r" (tmp)
);
/*
* Prevent critical section code from bleeding out this way up.
*/
/branches/dd/kernel/arch/ia32/include/boot/memmap.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
35,24 → 35,29
#ifndef KERN_ia32_MEMMAP_H_
#define KERN_ia32_MEMMAP_H_
 
/* E820h memory range types - other values*/
/* Free memory */
#define MEMMAP_MEMORY_AVAILABLE 1
/* Not available for OS */
#define MEMMAP_MEMORY_RESERVED 2
/* OS may use it after reading ACPI table */
#define MEMMAP_MEMORY_ACPI 3
/* Unusable, required to be saved and restored across an NVS sleep */
#define MEMMAP_MEMORY_NVS 4
/* Corrupted memory */
#define MEMMAP_MEMORY_UNUSABLE 5
/* E820h memory range types */
 
/* size of one entry */
#define MEMMAP_E820_RECORD_SIZE 20
/* maximum entries */
#define MEMMAP_E820_MAX_RECORDS 32
/* Free memory */
#define MEMMAP_MEMORY_AVAILABLE 1
 
/* Not available for OS */
#define MEMMAP_MEMORY_RESERVED 2
 
/* OS may use it after reading ACPI table */
#define MEMMAP_MEMORY_ACPI 3
 
/* Unusable, required to be saved and restored across an NVS sleep */
#define MEMMAP_MEMORY_NVS 4
 
/* Corrupted memory */
#define MEMMAP_MEMORY_UNUSABLE 5
 
/* Size of one entry */
#define MEMMAP_E820_RECORD_SIZE 20
 
/* Maximum entries */
#define MEMMAP_E820_MAX_RECORDS 32
 
#ifndef __ASM__
 
#include <arch/types.h>
/branches/dd/kernel/arch/ia32/include/boot/boot.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
35,15 → 35,24
#ifndef KERN_ia32_BOOT_H_
#define KERN_ia32_BOOT_H_
 
#define BOOT_OFFSET 0x108000
#define AP_BOOT_OFFSET 0x8000
#define BOOT_STACK_SIZE 0x400
#define BOOT_OFFSET 0x108000
#define AP_BOOT_OFFSET 0x8000
#define BOOT_STACK_SIZE 0x400
 
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
#define MULTIBOOT_HEADER_FLAGS 0x00010003
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
#define MULTIBOOT_HEADER_FLAGS 0x00010003
 
#define MULTIBOOT_LOADER_MAGIC 0x2BADB002
#ifndef __ASM__
 
#ifdef CONFIG_SMP
 
/* This is only a symbol so the type is dummy. Obtain the value using &. */
extern int _hardcoded_unmapped_size;
 
#endif /* CONFIG_SMP */
 
#endif /* __ASM__ */
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia32/include/arch.h
1,5 → 1,5
/*
* Copyright (c) 2005 Martin Decky
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
35,6 → 35,10
#ifndef KERN_ia32_ARCH_H_
#define KERN_ia32_ARCH_H_
 
#include <genarch/multiboot/multiboot.h>
 
extern void arch_pre_main(uint32_t, const multiboot_info_t *);
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia32/include/asm.h
27,7 → 27,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
38,6 → 38,7
 
#include <arch/pm.h>
#include <arch/types.h>
#include <typedefs.h>
#include <config.h>
 
extern uint32_t interrupt_handler_size;
56,6 → 57,7
/** Halt CPU
*
* Halt the current CPU until interrupt event.
*
*/
static inline void cpu_halt(void)
{
68,16 → 70,22
}
 
#define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \
{ \
unative_t res; \
asm volatile ("movl %%" #reg ", %0" : "=r" (res) ); \
return res; \
}
{ \
unative_t res; \
asm volatile ( \
"movl %%" #reg ", %[res]" \
: [res] "=r" (res) \
); \
return res; \
}
 
#define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \
{ \
asm volatile ("movl %0, %%" #reg : : "r" (regn)); \
}
{ \
asm volatile ( \
"movl %[regn], %%" #reg \
:: [regn] "r" (regn) \
); \
}
 
GEN_READ_REG(cr0)
GEN_READ_REG(cr2)
104,10 → 112,14
*
* @param port Port to write to
* @param val Value to write
*
*/
static inline void outb(uint16_t port, uint8_t val)
static inline void pio_write_8(ioport8_t *port, uint8_t val)
{
asm volatile ("outb %b0, %w1\n" : : "a" (val), "d" (port) );
asm volatile (
"outb %b[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
/** Word to port
116,10 → 128,14
*
* @param port Port to write to
* @param val Value to write
*
*/
static inline void outw(uint16_t port, uint16_t val)
static inline void pio_write_16(ioport16_t *port, uint16_t val)
{
asm volatile ("outw %w0, %w1\n" : : "a" (val), "d" (port) );
asm volatile (
"outw %w[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
/** Double word to port
128,10 → 144,14
*
* @param port Port to write to
* @param val Value to write
*
*/
static inline void outl(uint16_t port, uint32_t val)
static inline void pio_write_32(ioport32_t *port, uint32_t val)
{
asm volatile ("outl %l0, %w1\n" : : "a" (val), "d" (port) );
asm volatile (
"outl %[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
/** Byte from port
140,12 → 160,18
*
* @param port Port to read from
* @return Value read
*
*/
static inline uint8_t inb(uint16_t port)
static inline uint8_t pio_read_8(ioport8_t *port)
{
uint8_t val;
asm volatile ("inb %w1, %b0 \n" : "=a" (val) : "d" (port) );
asm volatile (
"inb %w[port], %b[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
155,12 → 181,18
*
* @param port Port to read from
* @return Value read
*
*/
static inline uint16_t inw(uint16_t port)
static inline uint16_t pio_read_16(ioport16_t *port)
{
uint16_t val;
asm volatile ("inw %w1, %w0 \n" : "=a" (val) : "d" (port) );
asm volatile (
"inw %w[port], %w[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
170,12 → 202,18
*
* @param port Port to read from
* @return Value read
*
*/
static inline uint32_t inl(uint16_t port)
static inline uint32_t pio_read_32(ioport32_t *port)
{
uint32_t val;
asm volatile ("inl %w1, %l0 \n" : "=a" (val) : "d" (port) );
asm volatile (
"inl %w[port], %[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
185,16 → 223,19
* value of EFLAGS.
*
* @return Old interrupt priority level.
*
*/
static inline ipl_t interrupts_enable(void)
{
ipl_t v;
asm volatile (
"pushf\n\t"
"popl %0\n\t"
"pushf\n"
"popl %[v]\n"
"sti\n"
: "=r" (v)
: [v] "=r" (v)
);
return v;
}
 
204,16 → 245,19
* value of EFLAGS.
*
* @return Old interrupt priority level.
*
*/
static inline ipl_t interrupts_disable(void)
{
ipl_t v;
asm volatile (
"pushf\n\t"
"popl %0\n\t"
"pushf\n"
"popl %[v]\n"
"cli\n"
: "=r" (v)
: [v] "=r" (v)
);
return v;
}
 
222,13 → 266,14
* Restore EFLAGS.
*
* @param ipl Saved interrupt priority level.
*
*/
static inline void interrupts_restore(ipl_t ipl)
{
asm volatile (
"pushl %0\n\t"
"pushl %[ipl]\n"
"popf\n"
: : "r" (ipl)
:: [ipl] "r" (ipl)
);
}
 
235,23 → 280,51
/** Return interrupt priority level.
*
* @return EFLAFS.
*
*/
static inline ipl_t interrupts_read(void)
{
ipl_t v;
asm volatile (
"pushf\n\t"
"popl %0\n"
: "=r" (v)
"pushf\n"
"popl %[v]\n"
: [v] "=r" (v)
);
return v;
}
 
/** Write to MSR */
static inline void write_msr(uint32_t msr, uint64_t value)
{
asm volatile (
"wrmsr"
:: "c" (msr), "a" ((uint32_t) (value)),
"d" ((uint32_t) (value >> 32))
);
}
 
static inline uint64_t read_msr(uint32_t msr)
{
uint32_t ax, dx;
asm volatile (
"rdmsr"
: "=a" (ax), "=d" (dx)
: "c" (msr)
);
return ((uint64_t) dx << 32) | ax;
}
 
 
/** Return base address of current stack
*
* Return the base address of the current stack.
* The stack is assumed to be STACK_SIZE bytes long.
* The stack must start on page boundary.
*
*/
static inline uintptr_t get_stack_base(void)
{
258,8 → 331,8
uintptr_t v;
asm volatile (
"andl %%esp, %0\n"
: "=r" (v)
"andl %%esp, %[v]\n"
: [v] "=r" (v)
: "0" (~(STACK_SIZE - 1))
);
270,11 → 343,12
static inline uintptr_t * get_ip()
{
uintptr_t *ip;
 
asm volatile (
"mov %%eip, %0"
: "=r" (ip)
);
"mov %%eip, %[ip]"
: [ip] "=r" (ip)
);
return ip;
}
 
281,46 → 355,66
/** Invalidate TLB Entry.
*
* @param addr Address on a page whose TLB entry is to be invalidated.
*
*/
static inline void invlpg(uintptr_t addr)
{
asm volatile ("invlpg %0\n" :: "m" (*(unative_t *)addr));
asm volatile (
"invlpg %[addr]\n"
:: [addr] "m" (*(unative_t *) addr)
);
}
 
/** Load GDTR register from memory.
*
* @param gdtr_reg Address of memory from where to load GDTR.
*
*/
static inline void gdtr_load(ptr_16_32_t *gdtr_reg)
{
asm volatile ("lgdtl %0\n" : : "m" (*gdtr_reg));
asm volatile (
"lgdtl %[gdtr_reg]\n"
:: [gdtr_reg] "m" (*gdtr_reg)
);
}
 
/** Store GDTR register to memory.
*
* @param gdtr_reg Address of memory to where to load GDTR.
*
*/
static inline void gdtr_store(ptr_16_32_t *gdtr_reg)
{
asm volatile ("sgdtl %0\n" : : "m" (*gdtr_reg));
asm volatile (
"sgdtl %[gdtr_reg]\n"
:: [gdtr_reg] "m" (*gdtr_reg)
);
}
 
/** Load IDTR register from memory.
*
* @param idtr_reg Address of memory from where to load IDTR.
*
*/
static inline void idtr_load(ptr_16_32_t *idtr_reg)
{
asm volatile ("lidtl %0\n" : : "m" (*idtr_reg));
asm volatile (
"lidtl %[idtr_reg]\n"
:: [idtr_reg] "m" (*idtr_reg)
);
}
 
/** Load TR from descriptor table.
*
* @param sel Selector specifying descriptor of TSS segment.
*
*/
static inline void tr_load(uint16_t sel)
{
asm volatile ("ltr %0" : : "r" (sel));
asm volatile (
"ltr %[sel]"
:: [sel] "r" (sel)
);
}
 
#endif
/branches/dd/kernel/arch/ia32/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32mm
/** @addtogroup ia32mm
* @{
*/
/** @file
35,8 → 35,8
#ifndef KERN_ia32_FRAME_H_
#define KERN_ia32_FRAME_H_
 
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
 
#ifdef KERNEL
#ifndef __ASM__
/branches/dd/kernel/arch/ia32/include/mm/page.h
40,8 → 40,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifdef KERNEL
 
#ifndef __ASM__
128,6 → 126,8
 
#include <mm/mm.h>
#include <arch/interrupt.h>
#include <arch/types.h>
#include <typedefs.h>
 
/* Page fault error codes. */
 
/branches/dd/kernel/arch/ia32/include/mm/tlb.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32mm
/** @addtogroup ia32mm
* @{
*/
/** @file
35,9 → 35,6
#ifndef KERN_ia32_TLB_H_
#define KERN_ia32_TLB_H_
 
#define tlb_arch_init()
#define tlb_print()
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia32/include/mm/as.h
42,7 → 42,7
#define USER_ADDRESS_SPACE_START_ARCH ((unsigned long) 0x00000000)
#define USER_ADDRESS_SPACE_END_ARCH ((unsigned long) 0x7fffffff)
 
#define USTACK_ADDRESS_ARCH (USER_ADDRESS_SPACE_END_ARCH-(PAGE_SIZE-1))
#define USTACK_ADDRESS_ARCH (USER_ADDRESS_SPACE_END_ARCH - (PAGE_SIZE - 1))
 
typedef struct {
} as_arch_t;
/branches/dd/kernel/arch/ia32/include/barrier.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
46,8 → 46,8
* Provisions are made to prevent compiler from reordering instructions itself.
*/
 
#define CS_ENTER_BARRIER() asm volatile ("" ::: "memory")
#define CS_LEAVE_BARRIER() asm volatile ("" ::: "memory")
#define CS_ENTER_BARRIER() asm volatile ("" ::: "memory")
#define CS_LEAVE_BARRIER() asm volatile ("" ::: "memory")
 
static inline void cpuid_serialization(void)
{
58,32 → 58,41
);
}
 
#ifdef CONFIG_FENCES_P4
# define memory_barrier() asm volatile ("mfence\n" ::: "memory")
# define read_barrier() asm volatile ("lfence\n" ::: "memory")
# ifdef CONFIG_WEAK_MEMORY
# define write_barrier() asm volatile ("sfence\n" ::: "memory")
# else
# define write_barrier() asm volatile( "" ::: "memory");
# endif
#elif CONFIG_FENCES_P3
# define memory_barrier() cpuid_serialization()
# define read_barrier() cpuid_serialization()
# ifdef CONFIG_WEAK_MEMORY
# define write_barrier() asm volatile ("sfence\n" ::: "memory")
# else
# define write_barrier() asm volatile( "" ::: "memory");
# endif
#if defined(CONFIG_FENCES_P4)
#define memory_barrier() asm volatile ("mfence\n" ::: "memory")
#define read_barrier() asm volatile ("lfence\n" ::: "memory")
#ifdef CONFIG_WEAK_MEMORY
#define write_barrier() asm volatile ("sfence\n" ::: "memory")
#else
#define write_barrier() asm volatile ("" ::: "memory");
#endif
#elif defined(CONFIG_FENCES_P3)
#define memory_barrier() cpuid_serialization()
#define read_barrier() cpuid_serialization()
#ifdef CONFIG_WEAK_MEMORY
#define write_barrier() asm volatile ("sfence\n" ::: "memory")
#else
#define write_barrier() asm volatile ("" ::: "memory");
#endif
#else
# define memory_barrier() cpuid_serialization()
# define read_barrier() cpuid_serialization()
# ifdef CONFIG_WEAK_MEMORY
# define write_barrier() cpuid_serialization()
# else
# define write_barrier() asm volatile( "" ::: "memory");
# endif
#define memory_barrier() cpuid_serialization()
#define read_barrier() cpuid_serialization()
#ifdef CONFIG_WEAK_MEMORY
#define write_barrier() cpuid_serialization()
#else
#define write_barrier() asm volatile ("" ::: "memory");
#endif
#endif
 
/*
* On ia32, the hardware takes care about instruction and data cache coherence,
* even on SMP systems. We issue a write barrier to be sure that writes
* queueing in the store buffer drain to the memory (even though it would be
* sufficient for them to drain to the D-cache).
*/
#define smc_coherence(a) write_barrier()
#define smc_coherence_block(a, l) write_barrier()
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia32/include/cpu.h
35,25 → 35,33
#ifndef KERN_ia32_CPU_H_
#define KERN_ia32_CPU_H_
 
#define EFLAGS_IF (1 << 9)
#define EFLAGS_RF (1 << 16)
 
#define CR4_OSFXSR_MASK (1<<9)
 
/* Support for SYSENTER and SYSEXIT */
#define IA32_MSR_SYSENTER_CS 0x174
#define IA32_MSR_SYSENTER_ESP 0x175
#define IA32_MSR_SYSENTER_EIP 0x176
 
#ifndef __ASM__
 
#include <arch/pm.h>
#include <arch/asm.h>
 
#define EFLAGS_IF (1 << 9)
#define EFLAGS_RF (1 << 16)
 
typedef struct {
int vendor;
int family;
int model;
int stepping;
unsigned int vendor;
unsigned int family;
unsigned int model;
unsigned int stepping;
struct tss *tss;
count_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
} cpu_arch_t;
 
#endif
 
#define CR4_OSFXSR_MASK (1<<9)
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia32/include/drivers/i8042.h
File deleted
/branches/dd/kernel/arch/ia32/include/drivers/ega.h
File deleted
/branches/dd/kernel/arch/ia32/include/drivers/vesa.h
36,6 → 36,7
#define KERN_ia32_VESA_H_
 
extern int vesa_present(void);
extern void vesa_redraw(void);
extern void vesa_init(void);
 
#endif
/branches/dd/kernel/arch/ia32/include/drivers/i8259.h
38,10 → 38,10
#include <arch/types.h>
#include <arch/interrupt.h>
 
#define PIC_PIC0PORT1 0x20
#define PIC_PIC0PORT2 0x21
#define PIC_PIC1PORT1 0xa0
#define PIC_PIC1PORT2 0xa1
#define PIC_PIC0PORT1 ((ioport8_t *) 0x20)
#define PIC_PIC0PORT2 ((ioport8_t *) 0x21)
#define PIC_PIC1PORT1 ((ioport8_t *) 0xa0)
#define PIC_PIC1PORT2 ((ioport8_t *) 0xa1)
 
#define PIC_NEEDICW4 (1<<0)
#define PIC_ICW1 (1<<4)
/branches/dd/kernel/arch/ia32/include/drivers/kbd.h
0,0 → 1,41
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
* @{
*/
/** @file
*/
 
#ifndef KERN_ia32_KBD_H_
#define KERN_ia32_KBD_H_
 
#endif
 
/** @}
*/
/branches/dd/kernel/arch/ia32/Makefile.inc
33,9 → 33,9
BFD_ARCH = i386
BFD = binary
TARGET = i686-pc-linux-gnu
TOOLCHAIN_DIR = /usr/local/i686
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686
 
DEFS += -DMACHINE=$(MACHINE) -D__32_BITS__
DEFS += -D__32_BITS__
 
CMN1 = -m32
GCC_CFLAGS += $(CMN1)
45,110 → 45,61
## Accepted CPUs
#
 
ifeq ($(MACHINE),athlon-xp)
CMN2 = -march=athlon-xp -mmmx -msse -m3dnow
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
ifeq ($(PROCESSOR),athlon_xp)
CMN2 = -march=athlon-xp
SUNCC_CFLAGS += -xarch=ssea
DEFS += -DCONFIG_FENCES_P3
CONFIG_SMP = n
CONFIG_HT = n
endif
ifeq ($(MACHINE),athlon-mp)
CMN2 = -march=athlon-mp -mmmx -msse -m3dnow
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
ifeq ($(PROCESSOR),athlon_mp)
CMN2 = -march=athlon-mp
SUNCC_CFLAGS += xarch=ssea
DEFS += -DCONFIG_FENCES_P3
CONFIG_HT = n
endif
ifeq ($(MACHINE),pentium3)
CMN2 = -march=pentium3 -mmmx -msse
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
ifeq ($(PROCESSOR),pentium3)
CMN2 = -march=pentium3
SUNCC_CFLAGS += -xarch=sse
DEFS += -DCONFIG_FENCES_P3
CONFIG_HT = n
endif
ifeq ($(MACHINE),core)
CMN2 = -march=prescott -mfpmath=sse -mmmx -msse -msse2 -msse3
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
SUNCC_CFLAGS += -xarch=sse3
DEFS += -DCONFIG_FENCES_P4
endif
ifeq ($(MACHINE),pentium4)
GCC_CFLAGS += -march=pentium4 -mfpmath=sse -mmmx -msse -msse2
ICC_CFLAGS += -march=pentium4
ifeq ($(PROCESSOR),pentium4)
CMN2 = -march=pentium4
SUNCC_CFLAGS += -xarch=sse2
DEFS += -DCONFIG_FENCES_P4
endif
 
## Own configuration directives
#
 
CONFIG_ACPI = y
 
## Compile with hierarchical page tables support.
#
 
CONFIG_PAGE_PT = y
DEFS += -DCONFIG_PAGE_PT
 
## Compile with i8042 controller support
#
 
CONFIG_I8042 = y
DEFS += -DCONFIG_I8042
 
## Accepted configuration directives
#
 
ifeq ($(CONFIG_SMP),y)
DEFS += -DCONFIG_SMP
ifeq ($(PROCESSOR),core)
CMN2 = -march=prescott
SUNCC_CFLAGS += -xarch=sse3
endif
ifeq ($(CONFIG_HT),y)
DEFS += -DCONFIG_HT
endif
ifeq ($(CONFIG_SIMICS_FIX),y)
DEFS += -DCONFIG_SIMICS_FIX
endif
 
## Compile with support for software integer division.
#
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
 
CONFIG_SOFTINT = y
 
ARCH_SOURCES = \
arch/$(ARCH)/src/context.S \
arch/$(ARCH)/src/debug/panic.s \
arch/$(ARCH)/src/delay.s \
arch/$(ARCH)/src/asm.S \
arch/$(ARCH)/src/proc/scheduler.c \
arch/$(ARCH)/src/proc/task.c \
arch/$(ARCH)/src/proc/thread.c \
arch/$(ARCH)/src/bios/bios.c \
arch/$(ARCH)/src/smp/ap.S \
arch/$(ARCH)/src/smp/apic.c \
arch/$(ARCH)/src/smp/mps.c \
arch/$(ARCH)/src/smp/smp.c \
arch/$(ARCH)/src/atomic.S \
arch/$(ARCH)/src/smp/ipi.c \
arch/$(ARCH)/src/ia32.c \
arch/$(ARCH)/src/interrupt.c \
arch/$(ARCH)/src/pm.c \
arch/$(ARCH)/src/userspace.c \
arch/$(ARCH)/src/cpu/cpu.c \
arch/$(ARCH)/src/mm/as.c \
arch/$(ARCH)/src/mm/frame.c \
arch/$(ARCH)/src/mm/page.c \
arch/$(ARCH)/src/mm/tlb.c \
arch/$(ARCH)/src/ddi/ddi.c \
arch/$(ARCH)/src/drivers/i8254.c \
arch/$(ARCH)/src/drivers/i8259.c \
arch/$(ARCH)/src/drivers/ega.c \
arch/$(ARCH)/src/drivers/vesa.c \
arch/$(ARCH)/src/boot/boot.S \
arch/$(ARCH)/src/boot/memmap.c \
arch/$(ARCH)/src/fpu_context.c \
arch/$(ARCH)/src/debugger.c
arch/$(KARCH)/src/context.S \
arch/$(KARCH)/src/debug/panic.s \
arch/$(KARCH)/src/delay.s \
arch/$(KARCH)/src/asm.S \
arch/$(KARCH)/src/proc/scheduler.c \
arch/$(KARCH)/src/proc/task.c \
arch/$(KARCH)/src/proc/thread.c \
arch/$(KARCH)/src/bios/bios.c \
arch/$(KARCH)/src/smp/ap.S \
arch/$(KARCH)/src/smp/apic.c \
arch/$(KARCH)/src/smp/mps.c \
arch/$(KARCH)/src/smp/smp.c \
arch/$(KARCH)/src/atomic.S \
arch/$(KARCH)/src/smp/ipi.c \
arch/$(KARCH)/src/ia32.c \
arch/$(KARCH)/src/interrupt.c \
arch/$(KARCH)/src/pm.c \
arch/$(KARCH)/src/userspace.c \
arch/$(KARCH)/src/cpu/cpu.c \
arch/$(KARCH)/src/mm/as.c \
arch/$(KARCH)/src/mm/frame.c \
arch/$(KARCH)/src/mm/page.c \
arch/$(KARCH)/src/mm/tlb.c \
arch/$(KARCH)/src/ddi/ddi.c \
arch/$(KARCH)/src/drivers/i8254.c \
arch/$(KARCH)/src/drivers/i8259.c \
arch/$(KARCH)/src/drivers/vesa.c \
arch/$(KARCH)/src/boot/boot.S \
arch/$(KARCH)/src/boot/memmap.c \
arch/$(KARCH)/src/fpu_context.c \
arch/$(KARCH)/src/debugger.c \
arch/$(KARCH)/src/syscall.c
/branches/dd/kernel/arch/ia32/src/ia32.c
1,5 → 1,7
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2009 Jiri Svoboda
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
38,9 → 40,12
 
#include <arch/pm.h>
 
#include <arch/drivers/ega.h>
#include <genarch/multiboot/multiboot.h>
#include <genarch/drivers/legacy/ia32/io.h>
#include <genarch/drivers/ega/ega.h>
#include <arch/drivers/vesa.h>
#include <genarch/kbd/i8042.h>
#include <genarch/drivers/i8042/i8042.h>
#include <genarch/kbrd/kbrd.h>
#include <arch/drivers/i8254.h>
#include <arch/drivers/i8259.h>
 
61,11 → 66,30
#include <syscall/syscall.h>
#include <console/console.h>
#include <ddi/device.h>
#include <sysinfo/sysinfo.h>
#include <arch/boot/boot.h>
 
#ifdef CONFIG_SMP
#include <arch/smp/apic.h>
#endif
 
/** Perform ia32-specific initialization before main_bsp() is called.
*
* @param signature Should contain the multiboot signature.
* @param mi Pointer to the multiboot information structure.
*/
void arch_pre_main(uint32_t signature, const multiboot_info_t *mi)
{
/* Parse multiboot information obtained from the bootloader. */
multiboot_info_parse(signature, mi);
#ifdef CONFIG_SMP
/* Copy AP bootstrap routines below 1 MB. */
memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET,
(size_t) &_hardcoded_unmapped_size);
#endif
}
 
void arch_pre_mm_init(void)
{
pm_init();
93,7 → 117,7
vesa_init();
else
#endif
ega_init(); /* video */
ega_init(EGA_BASE, EGA_VIDEORAM); /* video */
/* Enable debugger */
debugger_init();
123,10 → 147,28
 
void arch_post_smp_init(void)
{
devno_t kbd = device_assign_devno();
devno_t mouse = device_assign_devno();
/* keyboard controller */
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE);
devno_t devno = device_assign_devno();
 
/*
* Initialize the keyboard module and conect it to stdin. Then
* initialize the i8042 controller and connect it to kbrdin. Enable
* keyboard interrupts.
*/
kbrd_init(stdin);
(void) i8042_init((i8042_t *) I8042_BASE, devno, IRQ_KBD, &kbrdin);
trap_virtual_enable_irqs(1 << IRQ_KBD);
 
/*
* This is the necessary evil until the userspace driver is entirely
* self-sufficient.
*/
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD);
sysinfo_set_item_val("kbd.address.physical", NULL,
(uintptr_t) I8042_BASE);
sysinfo_set_item_val("kbd.address.kernel", NULL,
(uintptr_t) I8042_BASE);
}
 
void calibrate_delay_loop(void)
159,15 → 201,33
*/
void arch_grab_console(void)
{
i8042_grab();
#ifdef CONFIG_FB
vesa_redraw();
#else
ega_redraw();
#endif
}
 
/** Return console to userspace
*
*/
void arch_release_console(void)
{
i8042_release();
}
 
/** Construct function pointer
*
* @param fptr function pointer structure
* @param addr function address
* @param caller calling function address
*
* @return address of the function pointer
*
*/
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
{
return addr;
}
 
/** @}
*/
/branches/dd/kernel/arch/ia32/src/fpu_context.c
44,46 → 44,43
static void fpu_context_f_save(fpu_context_t *fctx)
{
asm volatile (
"fnsave %0"
: "=m"(*fctx)
);
"fnsave %[fctx]"
: [fctx] "=m" (*fctx)
);
}
 
static void fpu_context_f_restore(fpu_context_t *fctx)
{
asm volatile (
"frstor %0"
: "=m"(*fctx)
);
"frstor %[fctx]"
: [fctx] "=m" (*fctx)
);
}
 
static void fpu_context_fx_save(fpu_context_t *fctx)
{
asm volatile (
"fxsave %0"
: "=m"(*fctx)
);
"fxsave %[fctx]"
: [fctx] "=m" (*fctx)
);
}
 
static void fpu_context_fx_restore(fpu_context_t *fctx)
{
asm volatile (
"fxrstor %0"
: "=m"(*fctx)
);
"fxrstor %[fctx]"
: [fctx] "=m" (*fctx)
);
}
 
/*
Setup using fxsr instruction
*/
/* Setup using fxsr instruction */
void fpu_fxsr(void)
{
fpu_save=fpu_context_fx_save;
fpu_restore=fpu_context_fx_restore;
}
/*
Setup using not fxsr instruction
*/
 
/* Setup using not fxsr instruction */
void fpu_fsr(void)
{
fpu_save = fpu_context_f_save;
102,16 → 99,18
 
void fpu_init()
{
uint32_t help0 = 0, help1 = 0;
uint32_t help0 = 0;
uint32_t help1 = 0;
asm volatile (
"fninit;\n"
"stmxcsr %0\n"
"mov %0,%1;\n"
"or %2,%1;\n"
"mov %1,%0;\n"
"ldmxcsr %0;\n"
: "+m" (help0), "+r" (help1)
: "i" (0x1f80)
"fninit\n"
"stmxcsr %[help0]\n"
"mov %[help0], %[help1]\n"
"or %[magic], %[help1]\n"
"mov %[help1], %[help0]\n"
"ldmxcsr %[help0]\n"
: [help0] "+m" (help0), [help1] "+r" (help1)
: [magic] "i" (0x1f80)
);
}
 
/branches/dd/kernel/arch/ia32/src/asm.S
37,6 → 37,8
.global paging_on
.global enable_l_apic_in_msr
.global interrupt_handlers
.global memsetb
.global memsetw
.global memcpy
.global memcpy_from_uspace
.global memcpy_from_uspace_failover_address
44,6 → 46,15
.global memcpy_to_uspace_failover_address
 
 
# Wrapper for generic memsetb
memsetb:
jmp _memsetb
 
# Wrapper for generic memsetw
memsetw:
jmp _memsetw
 
 
#define MEMCPY_DST 4
#define MEMCPY_SRC 8
#define MEMCPY_SIZE 12
60,7 → 71,7
* @param MEMCPY_SRC(%esp) Source address.
* @param MEMCPY_SIZE(%esp) Size.
*
* @return MEMCPY_SRC(%esp) on success and 0 on failure.
* @return MEMCPY_DST(%esp) on success and 0 on failure.
*/
memcpy:
memcpy_from_uspace:
85,7 → 96,7
0:
movl %edx, %edi
movl %eax, %esi
movl MEMCPY_SRC(%esp), %eax /* MEMCPY_SRC(%esp), success */
movl MEMCPY_DST(%esp), %eax /* MEMCPY_DST(%esp), success */
ret
/*
136,6 → 147,46
popfl
.endm
 
/*
* The SYSENTER syscall mechanism can be used for syscalls with
* four or fewer arguments. To pass these four arguments, we
* use four registers: EDX, ECX, EBX, ESI. The syscall number
* is passed in EAX. We use EDI to remember the return address
* and EBP to remember the stack. The INT-based syscall mechanism
* can actually handle six arguments plus the syscall number
* entirely in registers.
*/
.global sysenter_handler
sysenter_handler:
sti
pushl %ebp # remember user stack
pushl %edi # remember return user address
 
pushl %gs # remember TLS
 
pushl %eax # syscall number
subl $8, %esp # unused sixth and fifth argument
pushl %esi # fourth argument
pushl %ebx # third argument
pushl %ecx # second argument
pushl %edx # first argument
 
movw $16, %ax
movw %ax, %ds
movw %ax, %es
 
cld
call syscall_handler
addl $28, %esp # remove arguments from stack
 
pop %gs # restore TLS
 
pop %edx # prepare return EIP for SYSEXIT
pop %ecx # prepare userspace ESP for SYSEXIT
 
sysexit # return to userspace
 
 
## Declare interrupt handlers
#
# Declare interrupt handlers for n interrupt
217,14 → 268,6
pushl %fs
pushl %gs
 
#ifdef CONFIG_DEBUG_ALLREGS
pushl %ebx
pushl %ebp
pushl %edi
pushl %esi
#else
subl $16, %esp
#endif
pushl %edx
pushl %ecx
pushl %eax
246,14 → 289,6
popl %eax
popl %ecx
popl %edx
#ifdef CONFIG_DEBUG_ALLREGS
popl %esi
popl %edi
popl %ebp
popl %ebx
#else
addl $16, %esp
#endif
popl %gs
popl %fs
/branches/dd/kernel/arch/ia32/src/debug/panic.s
30,5 → 30,5
.global panic_printf
 
panic_printf:
movl $halt,(%esp) # fake stack to make printf return to halt
movl $halt, (%esp) # fake stack to make printf return to halt
jmp printf
/branches/dd/kernel/arch/ia32/src/cpu/cpu.c
42,22 → 42,23
#include <fpu_context.h>
 
#include <arch/smp/apic.h>
#include <arch/syscall.h>
 
/*
* Identification of CPUs.
* Contains only non-MP-Specification specific SMP code.
*/
#define AMD_CPUID_EBX 0x68747541
#define AMD_CPUID_ECX 0x444d4163
#define AMD_CPUID_EDX 0x69746e65
#define AMD_CPUID_EBX 0x68747541
#define AMD_CPUID_ECX 0x444d4163
#define AMD_CPUID_EDX 0x69746e65
 
#define INTEL_CPUID_EBX 0x756e6547
#define INTEL_CPUID_ECX 0x6c65746e
#define INTEL_CPUID_EDX 0x49656e69
#define INTEL_CPUID_EBX 0x756e6547
#define INTEL_CPUID_ECX 0x6c65746e
#define INTEL_CPUID_EDX 0x49656e69
 
 
enum vendor {
VendorUnknown=0,
VendorUnknown = 0,
VendorAMD,
VendorIntel
};
64,19 → 65,17
 
static char *vendor_str[] = {
"Unknown Vendor",
"AuthenticAMD",
"GenuineIntel"
"AMD",
"Intel"
};
 
void fpu_disable(void)
{
asm volatile (
"mov %%cr0,%%eax;"
"or $8,%%eax;"
"mov %%eax,%%cr0;"
:
:
:"%eax"
"mov %%cr0, %%eax\n"
"or $8, %%eax\n"
"mov %%eax, %%cr0\n"
::: "%eax"
);
}
 
83,13 → 82,11
void fpu_enable(void)
{
asm volatile (
"mov %%cr0,%%eax;"
"and $0xffFFffF7,%%eax;"
"mov %%eax,%%cr0;"
:
:
:"%eax"
);
"mov %%cr0, %%eax\n"
"and $0xffFFffF7, %%eax\n"
"mov %%eax,%%cr0\n"
::: "%eax"
);
}
 
void cpu_arch_init(void)
101,11 → 98,11
CPU->arch.tss = tss_p;
CPU->arch.tss->iomap_base = &CPU->arch.tss->iomap[0] - ((uint8_t *) CPU->arch.tss);
 
CPU->fpu_owner = NULL;
 
cpuid(1, &info);
 
fi.word = info.cpuid_edx;
efi.word = info.cpuid_ecx;
112,17 → 109,20
if (fi.bits.fxsr)
fpu_fxsr();
else
fpu_fsr();
fpu_fsr();
if (fi.bits.sse) {
asm volatile (
"mov %%cr4,%0\n"
"or %1,%0\n"
"mov %0,%%cr4\n"
: "+r" (help)
: "i" (CR4_OSFXSR_MASK|(1<<10))
"mov %%cr4, %[help]\n"
"or %[mask], %[help]\n"
"mov %[help], %%cr4\n"
: [help] "+r" (help)
: [mask] "i" (CR4_OSFXSR_MASK | (1 << 10))
);
}
/* Setup fast SYSENTER/SYSEXIT syscalls */
syscall_setup_cpu();
}
 
void cpu_identify(void)
136,29 → 136,31
/*
* Check for AMD processor.
*/
if (info.cpuid_ebx==AMD_CPUID_EBX && info.cpuid_ecx==AMD_CPUID_ECX && info.cpuid_edx==AMD_CPUID_EDX) {
if ((info.cpuid_ebx == AMD_CPUID_EBX)
&& (info.cpuid_ecx == AMD_CPUID_ECX)
&& (info.cpuid_edx == AMD_CPUID_EDX))
CPU->arch.vendor = VendorAMD;
}
 
/*
* Check for Intel processor.
*/
if (info.cpuid_ebx==INTEL_CPUID_EBX && info.cpuid_ecx==INTEL_CPUID_ECX && info.cpuid_edx==INTEL_CPUID_EDX) {
if ((info.cpuid_ebx == INTEL_CPUID_EBX)
&& (info.cpuid_ecx == INTEL_CPUID_ECX)
&& (info.cpuid_edx == INTEL_CPUID_EDX))
CPU->arch.vendor = VendorIntel;
}
cpuid(1, &info);
CPU->arch.family = (info.cpuid_eax>>8)&0xf;
CPU->arch.model = (info.cpuid_eax>>4)&0xf;
CPU->arch.stepping = (info.cpuid_eax>>0)&0xf;
CPU->arch.family = (info.cpuid_eax >> 8) & 0x0f;
CPU->arch.model = (info.cpuid_eax >> 4) & 0x0f;
CPU->arch.stepping = (info.cpuid_eax >> 0) & 0x0f;
}
}
 
void cpu_print_report(cpu_t* m)
void cpu_print_report(cpu_t* cpu)
{
printf("cpu%d: (%s family=%d model=%d stepping=%d) %dMHz\n",
m->id, vendor_str[m->arch.vendor], m->arch.family, m->arch.model, m->arch.stepping,
m->frequency_mhz);
printf("cpu%u: (%s family=%u model=%u stepping=%u) %" PRIu16 " MHz\n",
cpu->id, vendor_str[cpu->arch.vendor], cpu->arch.family,
cpu->arch.model, cpu->arch.stepping, cpu->frequency_mhz);
}
 
/** @}
/branches/dd/kernel/arch/ia32/src/syscall.c
0,0 → 1,53
/*
* Copyright (c) 2008 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
* @{
*/
/** @file
*/
 
#include <arch/syscall.h>
#include <arch/cpu.h>
#include <arch/asm.h>
#include <arch/types.h>
#include <arch/pm.h>
 
/** Enable & setup support for SYSENTER/SYSEXIT */
void syscall_setup_cpu(void)
{
extern void sysenter_handler(void);
 
/* set kernel mode CS selector */
write_msr(IA32_MSR_SYSENTER_CS, selector(KTEXT_DES));
/* set kernel mode entry point */
write_msr(IA32_MSR_SYSENTER_EIP, (uint32_t) sysenter_handler);
}
 
/** @}
*/
/branches/dd/kernel/arch/ia32/src/pm.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
112,7 → 112,7
 
void tss_initialize(tss_t *t)
{
memsetb((uintptr_t) t, sizeof(struct tss), 0);
memsetb(t, sizeof(struct tss), 0);
}
 
/*
154,7 → 154,7
"and $0xffff8fff, %%eax\n"
"push %%eax\n"
"popfl\n"
: : : "eax"
::: "eax"
);
}
 
165,7 → 165,7
"mov %%cr0, %%eax\n"
"and $0xfffbffff, %%eax\n"
"mov %%eax, %%cr0\n"
: : : "eax"
::: "eax"
);
}
 
198,7 → 198,7
else {
tss_p = (tss_t *) malloc(sizeof(tss_t), FRAME_ATOMIC);
if (!tss_p)
panic("could not allocate TSS\n");
panic("Cannot allocate TSS.");
}
 
tss_initialize(tss_p);
240,7 → 240,7
preemption_disable();
ipl_t ipl = interrupts_disable();
memsetb((uintptr_t) idt, sizeof(idt), 0);
memsetb(idt, sizeof(idt), 0);
ptr_16_32_t idtr;
idtr.limit = sizeof(idt);
/branches/dd/kernel/arch/ia32/src/smp/smp.c
75,12 → 75,12
l_apic_address = (uintptr_t) frame_alloc(ONE_FRAME,
FRAME_ATOMIC | FRAME_KA);
if (!l_apic_address)
panic("cannot allocate address for l_apic\n");
panic("Cannot allocate address for l_apic.");
 
io_apic_address = (uintptr_t) frame_alloc(ONE_FRAME,
FRAME_ATOMIC | FRAME_KA);
if (!io_apic_address)
panic("cannot allocate address for io_apic\n");
panic("Cannot allocate address for io_apic.");
 
if (config.cpu_count > 1) {
page_mapping_insert(AS_KERNEL, l_apic_address,
122,8 → 122,8
* Save 0xa to address 0xf of the CMOS RAM.
* BIOS will not do the POST after the INIT signal.
*/
outb(0x70, 0xf);
outb(0x71, 0xa);
pio_write_8((ioport8_t *)0x70, 0xf);
pio_write_8((ioport8_t *)0x71, 0xa);
 
pic_disable_irqs(0xffff);
apic_init();
154,14 → 154,18
/*
* Prepare new GDT for CPU in question.
*/
/* XXX Flag FRAME_LOW_4_GiB was removed temporarily,
* it needs to be replaced by a generic fuctionality of
* the memory subsystem
*/
gdt_new = (struct descriptor *) malloc(GDT_ITEMS *
sizeof(struct descriptor), FRAME_ATOMIC);
if (!gdt_new)
panic("couldn't allocate memory for GDT\n");
panic("Cannot allocate memory for GDT.");
 
memcpy(gdt_new, gdt, GDT_ITEMS * sizeof(struct descriptor));
memsetb((uintptr_t)(&gdt_new[TSS_DES]),
sizeof(struct descriptor), 0);
memsetb(&gdt_new[TSS_DES], sizeof(struct descriptor), 0);
protected_ap_gdtr.limit = GDT_ITEMS * sizeof(struct descriptor);
protected_ap_gdtr.base = KA2PA((uintptr_t) gdt_new);
gdtr.base = (uintptr_t) gdt_new;
/branches/dd/kernel/arch/ia32/src/smp/ap.S
45,7 → 45,7
KTEXT=8
KDATA=16
 
# This piece of code is real-mode and is meant to be alligned at 4K boundary.
# This piece of code is real-mode and is meant to be aligned at 4K boundary.
# The requirement for such an alignment comes from MP Specification's STARTUP IPI
# requirements.
 
/branches/dd/kernel/arch/ia32/src/smp/apic.c
132,12 → 132,12
#endif
}
 
static irq_ownership_t l_apic_timer_claim(void)
static irq_ownership_t l_apic_timer_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
static void l_apic_timer_irq_handler(irq_t *irq, void *arg __attribute__((unused)), ...)
static void l_apic_timer_irq_handler(irq_t *irq)
{
/*
* Holding a spinlock could prevent clock() from preempting
/branches/dd/kernel/arch/ia32/src/boot/vga323.pal
1,256 → 1,256
.byte 0x3f, 0x3f, 0x3f, 0x00
.byte 0x36, 0x3f, 0x3f, 0x00
.byte 0x2d, 0x3f, 0x3f, 0x00
.byte 0x24, 0x3f, 0x3f, 0x00
.byte 0x1b, 0x3f, 0x3f, 0x00
.byte 0x12, 0x3f, 0x3f, 0x00
.byte 0x09, 0x3f, 0x3f, 0x00
.byte 0x00, 0x3f, 0x3f, 0x00
.byte 0x3f, 0x2a, 0x3f, 0x00
.byte 0x36, 0x2a, 0x3f, 0x00
.byte 0x2d, 0x2a, 0x3f, 0x00
.byte 0x24, 0x2a, 0x3f, 0x00
.byte 0x1b, 0x2a, 0x3f, 0x00
.byte 0x12, 0x2a, 0x3f, 0x00
.byte 0x09, 0x2a, 0x3f, 0x00
.byte 0x00, 0x2a, 0x3f, 0x00
.byte 0x3f, 0x15, 0x3f, 0x00
.byte 0x36, 0x15, 0x3f, 0x00
.byte 0x2d, 0x15, 0x3f, 0x00
.byte 0x24, 0x15, 0x3f, 0x00
.byte 0x1b, 0x15, 0x3f, 0x00
.byte 0x12, 0x15, 0x3f, 0x00
.byte 0x09, 0x15, 0x3f, 0x00
.byte 0x00, 0x15, 0x3f, 0x00
.byte 0x3f, 0x00, 0x3f, 0x00
.byte 0x36, 0x00, 0x3f, 0x00
.byte 0x2d, 0x00, 0x3f, 0x00
.byte 0x24, 0x00, 0x3f, 0x00
.byte 0x1b, 0x00, 0x3f, 0x00
.byte 0x12, 0x00, 0x3f, 0x00
.byte 0x09, 0x00, 0x3f, 0x00
.byte 0x00, 0x00, 0x3f, 0x00
.byte 0x3f, 0x3f, 0x36, 0x00
.byte 0x36, 0x3f, 0x36, 0x00
.byte 0x2d, 0x3f, 0x36, 0x00
.byte 0x24, 0x3f, 0x36, 0x00
.byte 0x1b, 0x3f, 0x36, 0x00
.byte 0x12, 0x3f, 0x36, 0x00
.byte 0x09, 0x3f, 0x36, 0x00
.byte 0x00, 0x3f, 0x36, 0x00
.byte 0x3f, 0x2a, 0x36, 0x00
.byte 0x36, 0x2a, 0x36, 0x00
.byte 0x2d, 0x2a, 0x36, 0x00
.byte 0x24, 0x2a, 0x36, 0x00
.byte 0x1b, 0x2a, 0x36, 0x00
.byte 0x12, 0x2a, 0x36, 0x00
.byte 0x09, 0x2a, 0x36, 0x00
.byte 0x00, 0x2a, 0x36, 0x00
.byte 0x3f, 0x15, 0x36, 0x00
.byte 0x36, 0x15, 0x36, 0x00
.byte 0x2d, 0x15, 0x36, 0x00
.byte 0x24, 0x15, 0x36, 0x00
.byte 0x1b, 0x15, 0x36, 0x00
.byte 0x12, 0x15, 0x36, 0x00
.byte 0x09, 0x15, 0x36, 0x00
.byte 0x00, 0x15, 0x36, 0x00
.byte 0x3f, 0x00, 0x36, 0x00
.byte 0x36, 0x00, 0x36, 0x00
.byte 0x2d, 0x00, 0x36, 0x00
.byte 0x24, 0x00, 0x36, 0x00
.byte 0x1b, 0x00, 0x36, 0x00
.byte 0x12, 0x00, 0x36, 0x00
.byte 0x09, 0x00, 0x36, 0x00
.byte 0x00, 0x00, 0x36, 0x00
.byte 0x3f, 0x3f, 0x2d, 0x00
.byte 0x36, 0x3f, 0x2d, 0x00
.byte 0x2d, 0x3f, 0x2d, 0x00
.byte 0x24, 0x3f, 0x2d, 0x00
.byte 0x1b, 0x3f, 0x2d, 0x00
.byte 0x12, 0x3f, 0x2d, 0x00
.byte 0x09, 0x3f, 0x2d, 0x00
.byte 0x00, 0x3f, 0x2d, 0x00
.byte 0x3f, 0x2a, 0x2d, 0x00
.byte 0x36, 0x2a, 0x2d, 0x00
.byte 0x2d, 0x2a, 0x2d, 0x00
.byte 0x24, 0x2a, 0x2d, 0x00
.byte 0x1b, 0x2a, 0x2d, 0x00
.byte 0x12, 0x2a, 0x2d, 0x00
.byte 0x09, 0x2a, 0x2d, 0x00
.byte 0x00, 0x2a, 0x2d, 0x00
.byte 0x3f, 0x15, 0x2d, 0x00
.byte 0x36, 0x15, 0x2d, 0x00
.byte 0x2d, 0x15, 0x2d, 0x00
.byte 0x24, 0x15, 0x2d, 0x00
.byte 0x1b, 0x15, 0x2d, 0x00
.byte 0x12, 0x15, 0x2d, 0x00
.byte 0x09, 0x15, 0x2d, 0x00
.byte 0x00, 0x15, 0x2d, 0x00
.byte 0x3f, 0x00, 0x2d, 0x00
.byte 0x36, 0x00, 0x2d, 0x00
.byte 0x2d, 0x00, 0x2d, 0x00
.byte 0x24, 0x00, 0x2d, 0x00
.byte 0x1b, 0x00, 0x2d, 0x00
.byte 0x12, 0x00, 0x2d, 0x00
.byte 0x09, 0x00, 0x2d, 0x00
.byte 0x00, 0x00, 0x2d, 0x00
.byte 0x3f, 0x3f, 0x24, 0x00
.byte 0x36, 0x3f, 0x24, 0x00
.byte 0x2d, 0x3f, 0x24, 0x00
.byte 0x24, 0x3f, 0x24, 0x00
.byte 0x1b, 0x3f, 0x24, 0x00
.byte 0x12, 0x3f, 0x24, 0x00
.byte 0x09, 0x3f, 0x24, 0x00
.byte 0x00, 0x3f, 0x24, 0x00
.byte 0x3f, 0x2a, 0x24, 0x00
.byte 0x36, 0x2a, 0x24, 0x00
.byte 0x2d, 0x2a, 0x24, 0x00
.byte 0x24, 0x2a, 0x24, 0x00
.byte 0x1b, 0x2a, 0x24, 0x00
.byte 0x12, 0x2a, 0x24, 0x00
.byte 0x09, 0x2a, 0x24, 0x00
.byte 0x00, 0x2a, 0x24, 0x00
.byte 0x3f, 0x15, 0x24, 0x00
.byte 0x36, 0x15, 0x24, 0x00
.byte 0x2d, 0x15, 0x24, 0x00
.byte 0x24, 0x15, 0x24, 0x00
.byte 0x1b, 0x15, 0x24, 0x00
.byte 0x12, 0x15, 0x24, 0x00
.byte 0x09, 0x15, 0x24, 0x00
.byte 0x00, 0x15, 0x24, 0x00
.byte 0x3f, 0x00, 0x24, 0x00
.byte 0x36, 0x00, 0x24, 0x00
.byte 0x2d, 0x00, 0x24, 0x00
.byte 0x24, 0x00, 0x24, 0x00
.byte 0x1b, 0x00, 0x24, 0x00
.byte 0x12, 0x00, 0x24, 0x00
.byte 0x09, 0x00, 0x24, 0x00
.byte 0x00, 0x00, 0x24, 0x00
.byte 0x3f, 0x3f, 0x1b, 0x00
.byte 0x36, 0x3f, 0x1b, 0x00
.byte 0x2d, 0x3f, 0x1b, 0x00
.byte 0x24, 0x3f, 0x1b, 0x00
.byte 0x1b, 0x3f, 0x1b, 0x00
.byte 0x12, 0x3f, 0x1b, 0x00
.byte 0x09, 0x3f, 0x1b, 0x00
.byte 0x00, 0x3f, 0x1b, 0x00
.byte 0x3f, 0x2a, 0x1b, 0x00
.byte 0x36, 0x2a, 0x1b, 0x00
.byte 0x2d, 0x2a, 0x1b, 0x00
.byte 0x24, 0x2a, 0x1b, 0x00
.byte 0x1b, 0x2a, 0x1b, 0x00
.byte 0x12, 0x2a, 0x1b, 0x00
.byte 0x09, 0x2a, 0x1b, 0x00
.byte 0x00, 0x2a, 0x1b, 0x00
.byte 0x3f, 0x15, 0x1b, 0x00
.byte 0x36, 0x15, 0x1b, 0x00
.byte 0x2d, 0x15, 0x1b, 0x00
.byte 0x24, 0x15, 0x1b, 0x00
.byte 0x1b, 0x15, 0x1b, 0x00
.byte 0x12, 0x15, 0x1b, 0x00
.byte 0x09, 0x15, 0x1b, 0x00
.byte 0x00, 0x15, 0x1b, 0x00
.byte 0x3f, 0x00, 0x1b, 0x00
.byte 0x36, 0x00, 0x1b, 0x00
.byte 0x2d, 0x00, 0x1b, 0x00
.byte 0x24, 0x00, 0x1b, 0x00
.byte 0x1b, 0x00, 0x1b, 0x00
.byte 0x12, 0x00, 0x1b, 0x00
.byte 0x09, 0x00, 0x1b, 0x00
.byte 0x00, 0x00, 0x1b, 0x00
.byte 0x3f, 0x3f, 0x12, 0x00
.byte 0x36, 0x3f, 0x12, 0x00
.byte 0x2d, 0x3f, 0x12, 0x00
.byte 0x24, 0x3f, 0x12, 0x00
.byte 0x1b, 0x3f, 0x12, 0x00
.byte 0x12, 0x3f, 0x12, 0x00
.byte 0x09, 0x3f, 0x12, 0x00
.byte 0x00, 0x3f, 0x12, 0x00
.byte 0x3f, 0x2a, 0x12, 0x00
.byte 0x36, 0x2a, 0x12, 0x00
.byte 0x2d, 0x2a, 0x12, 0x00
.byte 0x24, 0x2a, 0x12, 0x00
.byte 0x1b, 0x2a, 0x12, 0x00
.byte 0x12, 0x2a, 0x12, 0x00
.byte 0x09, 0x2a, 0x12, 0x00
.byte 0x00, 0x2a, 0x12, 0x00
.byte 0x3f, 0x15, 0x12, 0x00
.byte 0x36, 0x15, 0x12, 0x00
.byte 0x2d, 0x15, 0x12, 0x00
.byte 0x24, 0x15, 0x12, 0x00
.byte 0x1b, 0x15, 0x12, 0x00
.byte 0x12, 0x15, 0x12, 0x00
.byte 0x09, 0x15, 0x12, 0x00
.byte 0x00, 0x15, 0x12, 0x00
.byte 0x3f, 0x00, 0x12, 0x00
.byte 0x36, 0x00, 0x12, 0x00
.byte 0x2d, 0x00, 0x12, 0x00
.byte 0x24, 0x00, 0x12, 0x00
.byte 0x1b, 0x00, 0x12, 0x00
.byte 0x12, 0x00, 0x12, 0x00
.byte 0x09, 0x00, 0x12, 0x00
.byte 0x00, 0x00, 0x12, 0x00
.byte 0x3f, 0x3f, 0x09, 0x00
.byte 0x36, 0x3f, 0x09, 0x00
.byte 0x2d, 0x3f, 0x09, 0x00
.byte 0x24, 0x3f, 0x09, 0x00
.byte 0x1b, 0x3f, 0x09, 0x00
.byte 0x12, 0x3f, 0x09, 0x00
.byte 0x09, 0x3f, 0x09, 0x00
.byte 0x00, 0x3f, 0x09, 0x00
.byte 0x3f, 0x2a, 0x09, 0x00
.byte 0x36, 0x2a, 0x09, 0x00
.byte 0x2d, 0x2a, 0x09, 0x00
.byte 0x24, 0x2a, 0x09, 0x00
.byte 0x1b, 0x2a, 0x09, 0x00
.byte 0x12, 0x2a, 0x09, 0x00
.byte 0x09, 0x2a, 0x09, 0x00
.byte 0x00, 0x2a, 0x09, 0x00
.byte 0x3f, 0x15, 0x09, 0x00
.byte 0x36, 0x15, 0x09, 0x00
.byte 0x2d, 0x15, 0x09, 0x00
.byte 0x24, 0x15, 0x09, 0x00
.byte 0x1b, 0x15, 0x09, 0x00
.byte 0x12, 0x15, 0x09, 0x00
.byte 0x09, 0x15, 0x09, 0x00
.byte 0x00, 0x15, 0x09, 0x00
.byte 0x3f, 0x00, 0x09, 0x00
.byte 0x36, 0x00, 0x09, 0x00
.byte 0x2d, 0x00, 0x09, 0x00
.byte 0x24, 0x00, 0x09, 0x00
.byte 0x1b, 0x00, 0x09, 0x00
.byte 0x12, 0x00, 0x09, 0x00
.byte 0x09, 0x00, 0x09, 0x00
.byte 0x00, 0x00, 0x09, 0x00
.byte 0x3f, 0x3f, 0x00, 0x00
.byte 0x36, 0x3f, 0x00, 0x00
.byte 0x2d, 0x3f, 0x00, 0x00
.byte 0x24, 0x3f, 0x00, 0x00
.byte 0x1b, 0x3f, 0x00, 0x00
.byte 0x12, 0x3f, 0x00, 0x00
.byte 0x09, 0x3f, 0x00, 0x00
.byte 0x00, 0x3f, 0x00, 0x00
.byte 0x3f, 0x2a, 0x00, 0x00
.byte 0x36, 0x2a, 0x00, 0x00
.byte 0x2d, 0x2a, 0x00, 0x00
.byte 0x24, 0x2a, 0x00, 0x00
.byte 0x1b, 0x2a, 0x00, 0x00
.byte 0x12, 0x2a, 0x00, 0x00
.byte 0x09, 0x2a, 0x00, 0x00
.byte 0x00, 0x2a, 0x00, 0x00
.byte 0x3f, 0x15, 0x00, 0x00
.byte 0x36, 0x15, 0x00, 0x00
.byte 0x2d, 0x15, 0x00, 0x00
.byte 0x24, 0x15, 0x00, 0x00
.byte 0x1b, 0x15, 0x00, 0x00
.byte 0x12, 0x15, 0x00, 0x00
.byte 0x09, 0x15, 0x00, 0x00
.byte 0x00, 0x15, 0x00, 0x00
.byte 0x3f, 0x00, 0x00, 0x00
.byte 0x36, 0x00, 0x00, 0x00
.byte 0x2d, 0x00, 0x00, 0x00
.byte 0x24, 0x00, 0x00, 0x00
.byte 0x1b, 0x00, 0x00, 0x00
.byte 0x12, 0x00, 0x00, 0x00
.byte 0x09, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00
.byte 0x09, 0x00, 0x00, 0x00
.byte 0x12, 0x00, 0x00, 0x00
.byte 0x1b, 0x00, 0x00, 0x00
.byte 0x24, 0x00, 0x00, 0x00
.byte 0x2d, 0x00, 0x00, 0x00
.byte 0x36, 0x00, 0x00, 0x00
.byte 0x3f, 0x00, 0x00, 0x00
.byte 0x00, 0x15, 0x00, 0x00
.byte 0x09, 0x15, 0x00, 0x00
.byte 0x12, 0x15, 0x00, 0x00
.byte 0x1b, 0x15, 0x00, 0x00
.byte 0x24, 0x15, 0x00, 0x00
.byte 0x2d, 0x15, 0x00, 0x00
.byte 0x36, 0x15, 0x00, 0x00
.byte 0x3f, 0x15, 0x00, 0x00
.byte 0x00, 0x2a, 0x00, 0x00
.byte 0x09, 0x2a, 0x00, 0x00
.byte 0x12, 0x2a, 0x00, 0x00
.byte 0x1b, 0x2a, 0x00, 0x00
.byte 0x24, 0x2a, 0x00, 0x00
.byte 0x2d, 0x2a, 0x00, 0x00
.byte 0x36, 0x2a, 0x00, 0x00
.byte 0x3f, 0x2a, 0x00, 0x00
.byte 0x00, 0x3f, 0x00, 0x00
.byte 0x09, 0x3f, 0x00, 0x00
.byte 0x12, 0x3f, 0x00, 0x00
.byte 0x1b, 0x3f, 0x00, 0x00
.byte 0x24, 0x3f, 0x00, 0x00
.byte 0x2d, 0x3f, 0x00, 0x00
.byte 0x36, 0x3f, 0x00, 0x00
.byte 0x3f, 0x3f, 0x00, 0x00
.byte 0x00, 0x00, 0x09, 0x00
.byte 0x09, 0x00, 0x09, 0x00
.byte 0x12, 0x00, 0x09, 0x00
.byte 0x1b, 0x00, 0x09, 0x00
.byte 0x24, 0x00, 0x09, 0x00
.byte 0x2d, 0x00, 0x09, 0x00
.byte 0x36, 0x00, 0x09, 0x00
.byte 0x3f, 0x00, 0x09, 0x00
.byte 0x00, 0x15, 0x09, 0x00
.byte 0x09, 0x15, 0x09, 0x00
.byte 0x12, 0x15, 0x09, 0x00
.byte 0x1b, 0x15, 0x09, 0x00
.byte 0x24, 0x15, 0x09, 0x00
.byte 0x2d, 0x15, 0x09, 0x00
.byte 0x36, 0x15, 0x09, 0x00
.byte 0x3f, 0x15, 0x09, 0x00
.byte 0x00, 0x2a, 0x09, 0x00
.byte 0x09, 0x2a, 0x09, 0x00
.byte 0x12, 0x2a, 0x09, 0x00
.byte 0x1b, 0x2a, 0x09, 0x00
.byte 0x24, 0x2a, 0x09, 0x00
.byte 0x2d, 0x2a, 0x09, 0x00
.byte 0x36, 0x2a, 0x09, 0x00
.byte 0x3f, 0x2a, 0x09, 0x00
.byte 0x00, 0x3f, 0x09, 0x00
.byte 0x09, 0x3f, 0x09, 0x00
.byte 0x12, 0x3f, 0x09, 0x00
.byte 0x1b, 0x3f, 0x09, 0x00
.byte 0x24, 0x3f, 0x09, 0x00
.byte 0x2d, 0x3f, 0x09, 0x00
.byte 0x36, 0x3f, 0x09, 0x00
.byte 0x3f, 0x3f, 0x09, 0x00
.byte 0x00, 0x00, 0x12, 0x00
.byte 0x09, 0x00, 0x12, 0x00
.byte 0x12, 0x00, 0x12, 0x00
.byte 0x1b, 0x00, 0x12, 0x00
.byte 0x24, 0x00, 0x12, 0x00
.byte 0x2d, 0x00, 0x12, 0x00
.byte 0x36, 0x00, 0x12, 0x00
.byte 0x3f, 0x00, 0x12, 0x00
.byte 0x00, 0x15, 0x12, 0x00
.byte 0x09, 0x15, 0x12, 0x00
.byte 0x12, 0x15, 0x12, 0x00
.byte 0x1b, 0x15, 0x12, 0x00
.byte 0x24, 0x15, 0x12, 0x00
.byte 0x2d, 0x15, 0x12, 0x00
.byte 0x36, 0x15, 0x12, 0x00
.byte 0x3f, 0x15, 0x12, 0x00
.byte 0x00, 0x2a, 0x12, 0x00
.byte 0x09, 0x2a, 0x12, 0x00
.byte 0x12, 0x2a, 0x12, 0x00
.byte 0x1b, 0x2a, 0x12, 0x00
.byte 0x24, 0x2a, 0x12, 0x00
.byte 0x2d, 0x2a, 0x12, 0x00
.byte 0x36, 0x2a, 0x12, 0x00
.byte 0x3f, 0x2a, 0x12, 0x00
.byte 0x00, 0x3f, 0x12, 0x00
.byte 0x09, 0x3f, 0x12, 0x00
.byte 0x12, 0x3f, 0x12, 0x00
.byte 0x1b, 0x3f, 0x12, 0x00
.byte 0x24, 0x3f, 0x12, 0x00
.byte 0x2d, 0x3f, 0x12, 0x00
.byte 0x36, 0x3f, 0x12, 0x00
.byte 0x3f, 0x3f, 0x12, 0x00
.byte 0x00, 0x00, 0x1b, 0x00
.byte 0x09, 0x00, 0x1b, 0x00
.byte 0x12, 0x00, 0x1b, 0x00
.byte 0x1b, 0x00, 0x1b, 0x00
.byte 0x24, 0x00, 0x1b, 0x00
.byte 0x2d, 0x00, 0x1b, 0x00
.byte 0x36, 0x00, 0x1b, 0x00
.byte 0x3f, 0x00, 0x1b, 0x00
.byte 0x00, 0x15, 0x1b, 0x00
.byte 0x09, 0x15, 0x1b, 0x00
.byte 0x12, 0x15, 0x1b, 0x00
.byte 0x1b, 0x15, 0x1b, 0x00
.byte 0x24, 0x15, 0x1b, 0x00
.byte 0x2d, 0x15, 0x1b, 0x00
.byte 0x36, 0x15, 0x1b, 0x00
.byte 0x3f, 0x15, 0x1b, 0x00
.byte 0x00, 0x2a, 0x1b, 0x00
.byte 0x09, 0x2a, 0x1b, 0x00
.byte 0x12, 0x2a, 0x1b, 0x00
.byte 0x1b, 0x2a, 0x1b, 0x00
.byte 0x24, 0x2a, 0x1b, 0x00
.byte 0x2d, 0x2a, 0x1b, 0x00
.byte 0x36, 0x2a, 0x1b, 0x00
.byte 0x3f, 0x2a, 0x1b, 0x00
.byte 0x00, 0x3f, 0x1b, 0x00
.byte 0x09, 0x3f, 0x1b, 0x00
.byte 0x12, 0x3f, 0x1b, 0x00
.byte 0x1b, 0x3f, 0x1b, 0x00
.byte 0x24, 0x3f, 0x1b, 0x00
.byte 0x2d, 0x3f, 0x1b, 0x00
.byte 0x36, 0x3f, 0x1b, 0x00
.byte 0x3f, 0x3f, 0x1b, 0x00
.byte 0x00, 0x00, 0x24, 0x00
.byte 0x09, 0x00, 0x24, 0x00
.byte 0x12, 0x00, 0x24, 0x00
.byte 0x1b, 0x00, 0x24, 0x00
.byte 0x24, 0x00, 0x24, 0x00
.byte 0x2d, 0x00, 0x24, 0x00
.byte 0x36, 0x00, 0x24, 0x00
.byte 0x3f, 0x00, 0x24, 0x00
.byte 0x00, 0x15, 0x24, 0x00
.byte 0x09, 0x15, 0x24, 0x00
.byte 0x12, 0x15, 0x24, 0x00
.byte 0x1b, 0x15, 0x24, 0x00
.byte 0x24, 0x15, 0x24, 0x00
.byte 0x2d, 0x15, 0x24, 0x00
.byte 0x36, 0x15, 0x24, 0x00
.byte 0x3f, 0x15, 0x24, 0x00
.byte 0x00, 0x2a, 0x24, 0x00
.byte 0x09, 0x2a, 0x24, 0x00
.byte 0x12, 0x2a, 0x24, 0x00
.byte 0x1b, 0x2a, 0x24, 0x00
.byte 0x24, 0x2a, 0x24, 0x00
.byte 0x2d, 0x2a, 0x24, 0x00
.byte 0x36, 0x2a, 0x24, 0x00
.byte 0x3f, 0x2a, 0x24, 0x00
.byte 0x00, 0x3f, 0x24, 0x00
.byte 0x09, 0x3f, 0x24, 0x00
.byte 0x12, 0x3f, 0x24, 0x00
.byte 0x1b, 0x3f, 0x24, 0x00
.byte 0x24, 0x3f, 0x24, 0x00
.byte 0x2d, 0x3f, 0x24, 0x00
.byte 0x36, 0x3f, 0x24, 0x00
.byte 0x3f, 0x3f, 0x24, 0x00
.byte 0x00, 0x00, 0x2d, 0x00
.byte 0x09, 0x00, 0x2d, 0x00
.byte 0x12, 0x00, 0x2d, 0x00
.byte 0x1b, 0x00, 0x2d, 0x00
.byte 0x24, 0x00, 0x2d, 0x00
.byte 0x2d, 0x00, 0x2d, 0x00
.byte 0x36, 0x00, 0x2d, 0x00
.byte 0x3f, 0x00, 0x2d, 0x00
.byte 0x00, 0x15, 0x2d, 0x00
.byte 0x09, 0x15, 0x2d, 0x00
.byte 0x12, 0x15, 0x2d, 0x00
.byte 0x1b, 0x15, 0x2d, 0x00
.byte 0x24, 0x15, 0x2d, 0x00
.byte 0x2d, 0x15, 0x2d, 0x00
.byte 0x36, 0x15, 0x2d, 0x00
.byte 0x3f, 0x15, 0x2d, 0x00
.byte 0x00, 0x2a, 0x2d, 0x00
.byte 0x09, 0x2a, 0x2d, 0x00
.byte 0x12, 0x2a, 0x2d, 0x00
.byte 0x1b, 0x2a, 0x2d, 0x00
.byte 0x24, 0x2a, 0x2d, 0x00
.byte 0x2d, 0x2a, 0x2d, 0x00
.byte 0x36, 0x2a, 0x2d, 0x00
.byte 0x3f, 0x2a, 0x2d, 0x00
.byte 0x00, 0x3f, 0x2d, 0x00
.byte 0x09, 0x3f, 0x2d, 0x00
.byte 0x12, 0x3f, 0x2d, 0x00
.byte 0x1b, 0x3f, 0x2d, 0x00
.byte 0x24, 0x3f, 0x2d, 0x00
.byte 0x2d, 0x3f, 0x2d, 0x00
.byte 0x36, 0x3f, 0x2d, 0x00
.byte 0x3f, 0x3f, 0x2d, 0x00
.byte 0x00, 0x00, 0x36, 0x00
.byte 0x09, 0x00, 0x36, 0x00
.byte 0x12, 0x00, 0x36, 0x00
.byte 0x1b, 0x00, 0x36, 0x00
.byte 0x24, 0x00, 0x36, 0x00
.byte 0x2d, 0x00, 0x36, 0x00
.byte 0x36, 0x00, 0x36, 0x00
.byte 0x3f, 0x00, 0x36, 0x00
.byte 0x00, 0x15, 0x36, 0x00
.byte 0x09, 0x15, 0x36, 0x00
.byte 0x12, 0x15, 0x36, 0x00
.byte 0x1b, 0x15, 0x36, 0x00
.byte 0x24, 0x15, 0x36, 0x00
.byte 0x2d, 0x15, 0x36, 0x00
.byte 0x36, 0x15, 0x36, 0x00
.byte 0x3f, 0x15, 0x36, 0x00
.byte 0x00, 0x2a, 0x36, 0x00
.byte 0x09, 0x2a, 0x36, 0x00
.byte 0x12, 0x2a, 0x36, 0x00
.byte 0x1b, 0x2a, 0x36, 0x00
.byte 0x24, 0x2a, 0x36, 0x00
.byte 0x2d, 0x2a, 0x36, 0x00
.byte 0x36, 0x2a, 0x36, 0x00
.byte 0x3f, 0x2a, 0x36, 0x00
.byte 0x00, 0x3f, 0x36, 0x00
.byte 0x09, 0x3f, 0x36, 0x00
.byte 0x12, 0x3f, 0x36, 0x00
.byte 0x1b, 0x3f, 0x36, 0x00
.byte 0x24, 0x3f, 0x36, 0x00
.byte 0x2d, 0x3f, 0x36, 0x00
.byte 0x36, 0x3f, 0x36, 0x00
.byte 0x3f, 0x3f, 0x36, 0x00
.byte 0x00, 0x00, 0x3f, 0x00
.byte 0x09, 0x00, 0x3f, 0x00
.byte 0x12, 0x00, 0x3f, 0x00
.byte 0x1b, 0x00, 0x3f, 0x00
.byte 0x24, 0x00, 0x3f, 0x00
.byte 0x2d, 0x00, 0x3f, 0x00
.byte 0x36, 0x00, 0x3f, 0x00
.byte 0x3f, 0x00, 0x3f, 0x00
.byte 0x00, 0x15, 0x3f, 0x00
.byte 0x09, 0x15, 0x3f, 0x00
.byte 0x12, 0x15, 0x3f, 0x00
.byte 0x1b, 0x15, 0x3f, 0x00
.byte 0x24, 0x15, 0x3f, 0x00
.byte 0x2d, 0x15, 0x3f, 0x00
.byte 0x36, 0x15, 0x3f, 0x00
.byte 0x3f, 0x15, 0x3f, 0x00
.byte 0x00, 0x2a, 0x3f, 0x00
.byte 0x09, 0x2a, 0x3f, 0x00
.byte 0x12, 0x2a, 0x3f, 0x00
.byte 0x1b, 0x2a, 0x3f, 0x00
.byte 0x24, 0x2a, 0x3f, 0x00
.byte 0x2d, 0x2a, 0x3f, 0x00
.byte 0x36, 0x2a, 0x3f, 0x00
.byte 0x3f, 0x2a, 0x3f, 0x00
.byte 0x00, 0x3f, 0x3f, 0x00
.byte 0x09, 0x3f, 0x3f, 0x00
.byte 0x12, 0x3f, 0x3f, 0x00
.byte 0x1b, 0x3f, 0x3f, 0x00
.byte 0x24, 0x3f, 0x3f, 0x00
.byte 0x2d, 0x3f, 0x3f, 0x00
.byte 0x36, 0x3f, 0x3f, 0x00
.byte 0x3f, 0x3f, 0x3f, 0x00
/branches/dd/kernel/arch/ia32/src/boot/boot.S
101,117 → 101,18
shr $16, %ebx
mov %bx, KA2PA(vesa_bpp)
#endif
 
call map_kernel # map kernel and turn paging on
 
# arch_pre_main(grub_eax, grub_ebx)
pushl grub_ebx
pushl grub_eax
call arch_pre_main
movl grub_eax, %eax
movl grub_ebx, %ebx
cmpl $MULTIBOOT_LOADER_MAGIC, %eax # compare GRUB signature
je valid_boot
xorl %ecx, %ecx # no memory map available
movl %ecx, e820counter
jmp invalid_boot
valid_boot:
movl (%ebx), %eax # ebx = physical address of struct multiboot_info
bt $3, %eax # mbi->flags[3] (mods_count, mods_addr valid)
jc mods_valid
xorl %ecx, %ecx
movl %ecx, init
jmp mods_end
mods_valid:
movl 20(%ebx), %ecx # mbi->mods_count
movl %ecx, init
cmpl $0, %ecx
je mods_end
movl 24(%ebx), %esi # mbi->mods_addr
movl $init, %edi
mods_loop:
movl 0(%esi), %edx # mods->mod_start
addl $0x80000000, %edx
movl %edx, 4(%edi)
movl 4(%esi), %edx
subl 0(%esi), %edx # mods->mod_end - mods->mod_start
movl %edx, 8(%edi)
addl $16, %esi
addl $8 , %edi
loop mods_loop
mods_end:
bt $6, %eax # mbi->flags[6] (mmap_length, mmap_addr valid)
jc mmap_valid
xorl %edx, %edx
jmp mmap_invalid
mmap_valid:
movl 44(%ebx), %ecx # mbi->mmap_length
movl 48(%ebx), %esi # mbi->mmap_addr
movl $e820table, %edi
xorl %edx, %edx
mmap_loop:
cmpl $0, %ecx
jle mmap_end
movl 4(%esi), %eax # mmap->base_addr_low
movl %eax, (%edi)
movl 8(%esi), %eax # mmap->base_addr_high
movl %eax, 4(%edi)
movl 12(%esi), %eax # mmap->length_low
movl %eax, 8(%edi)
movl 16(%esi), %eax # mmap->length_high
movl %eax, 12(%edi)
movl 20(%esi), %eax # mmap->type
movl %eax, 16(%edi)
movl (%esi), %eax # mmap->size
addl $0x4, %eax
addl %eax, %esi
subl %eax, %ecx
addl $MEMMAP_E820_RECORD_SIZE, %edi
incl %edx
jmp mmap_loop
mmap_end:
mmap_invalid:
movl %edx, e820counter
invalid_boot:
call main_bsp
#ifdef CONFIG_SMP
# Not reached.
# copy AP bootstrap routines below 1 MB
movl $BOOT_OFFSET, %esi
movl $AP_BOOT_OFFSET, %edi
movl $_hardcoded_unmapped_size, %ecx
rep movsb
#endif
 
call main_bsp # never returns
 
cli
hlt
 
442,7 → 343,8
xor %dx, %dx
int $0x10
jmp vga_not_compat
cmp $0x00, %ah
je vga_not_compat
vga_compat:
/branches/dd/kernel/arch/ia32/src/proc/scheduler.c
38,7 → 38,6
#include <proc/thread.h>
#include <arch.h>
#include <arch/context.h> /* SP_DELTA */
#include <arch/debugger.h>
#include <arch/pm.h>
#include <arch/asm.h>
#include <arch/ddi/ddi.h>
58,21 → 57,18
*/
void before_thread_runs_arch(void)
{
CPU->arch.tss->esp0 = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE -
uintptr_t kstk = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE -
SP_DELTA];
 
/* Set kernel stack for CP3 -> CPL0 switch via SYSENTER */
write_msr(IA32_MSR_SYSENTER_ESP, kstk);
 
/* Set kernel stack for CPL3 -> CPL0 switch via interrupt */
CPU->arch.tss->esp0 = kstk;
CPU->arch.tss->ss0 = selector(KDATA_DES);
 
/* Set up TLS in GS register */
set_tls_desc(THREAD->arch.tls);
 
#ifdef CONFIG_DEBUG_AS_WATCHPOINT
/* Set watchpoint on AS to ensure that nobody sets it to zero */
if (CPU->id < BKPOINTS_MAX) {
the_t *the = THE;
breakpoint_add(&((the_t *) the->thread->kstack)->as,
BKPOINT_WRITE | BKPOINT_CHECK_ZERO, the->cpu->id);
}
#endif
}
 
void after_thread_ran_arch(void)
/branches/dd/kernel/arch/ia32/src/mm/tlb.c
67,5 → 67,13
invlpg(page + i * PAGE_SIZE);
}
 
void tlb_arch_init(void)
{
}
 
void tlb_print(void)
{
}
 
/** @}
*/
/branches/dd/kernel/arch/ia32/src/mm/as.c
39,9 → 39,7
/** Architecture dependent address space init. */
void as_arch_init(void)
{
#ifndef __OBJC__
as_operations = &as_pt_operations;
#endif
}
 
/** @}
/branches/dd/kernel/arch/ia32/src/mm/frame.c
54,26 → 54,57
static void init_e820_memory(pfn_t minconf)
{
unsigned int i;
pfn_t start, conf;
size_t size;
 
for (i = 0; i < e820counter; i++) {
uint64_t base = e820table[i].base_address;
uint64_t size = e820table[i].size;
#ifdef __32_BITS__
/* Ignore physical memory above 4 GB */
if ((base >> 32) != 0)
continue;
/* Clip regions above 4 GB */
if (((base + size) >> 32) != 0)
size = 0xffffffff - base;
#endif
pfn_t pfn;
count_t count;
if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) {
start = ADDR2PFN(ALIGN_UP(e820table[i].base_address, FRAME_SIZE));
size = SIZE2FRAMES(ALIGN_DOWN(e820table[i].size, FRAME_SIZE));
/* To be safe, make available zone possibly smaller */
pfn = ADDR2PFN(ALIGN_UP(base, FRAME_SIZE));
count = SIZE2FRAMES(ALIGN_DOWN(size, FRAME_SIZE));
if ((minconf < start) || (minconf >= start + size))
conf = start;
pfn_t conf;
if ((minconf < pfn) || (minconf >= pfn + count))
conf = pfn;
else
conf = minconf;
zone_create(start, size, conf, 0);
zone_create(pfn, count, conf, ZONE_AVAILABLE);
if (last_frame < ALIGN_UP(e820table[i].base_address +
e820table[i].size, FRAME_SIZE))
last_frame =
ALIGN_UP(e820table[i].base_address + e820table[i].size, FRAME_SIZE);
}
// XXX this has to be removed
if (last_frame < ALIGN_UP(base + size, FRAME_SIZE))
last_frame = ALIGN_UP(base + size, FRAME_SIZE);
}
if (e820table[i].type == MEMMAP_MEMORY_RESERVED) {
/* To be safe, make reserved zone possibly larger */
pfn = ADDR2PFN(ALIGN_DOWN(base, FRAME_SIZE));
count = SIZE2FRAMES(ALIGN_UP(size, FRAME_SIZE));
zone_create(pfn, count, 0, ZONE_RESERVED);
}
if (e820table[i].type == MEMMAP_MEMORY_ACPI) {
/* To be safe, make firmware zone possibly larger */
pfn = ADDR2PFN(ALIGN_DOWN(base, (uintptr_t) FRAME_SIZE));
count = SIZE2FRAMES(ALIGN_UP(size, (uintptr_t) FRAME_SIZE));
zone_create(pfn, count, 0, ZONE_FIRMWARE);
}
}
}
 
113,16 → 144,14
if (config.cpu_active == 1) {
minconf = 1;
#ifdef CONFIG_SMP
minconf = max(minconf,
ADDR2PFN(AP_BOOT_OFFSET + hardcoded_unmapped_ktext_size +
hardcoded_unmapped_kdata_size));
#endif
#ifdef CONFIG_SIMICS_FIX
minconf = max(minconf, ADDR2PFN(0x10000));
#endif
init_e820_memory(minconf);
 
/* Reserve frame 0 (BIOS data) */
frame_mark_unavailable(0, 1);
131,12 → 160,7
frame_mark_unavailable(AP_BOOT_OFFSET >> FRAME_WIDTH,
(hardcoded_unmapped_ktext_size +
hardcoded_unmapped_kdata_size) >> FRAME_WIDTH);
#ifdef CONFIG_SIMICS_FIX
/* Don't know why, but these addresses help */
frame_mark_unavailable(0xd000 >> FRAME_WIDTH, 3);
#endif
#endif
}
}
 
/branches/dd/kernel/arch/ia32/src/mm/page.c
53,7 → 53,7
{
uintptr_t cur;
int flags;
 
if (config.cpu_active == 1) {
page_mapping_operations = &pt_mapping_operations;
66,12 → 66,12
flags |= PAGE_GLOBAL;
page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
}
 
exc_register(14, "page_fault", (iroutine) page_fault);
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
} else
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
 
paging_on();
}
 
79,7 → 79,7
uintptr_t hw_map(uintptr_t physaddr, size_t size)
{
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
panic("Unable to map physical memory %p (%d bytes)", physaddr, size)
panic("Unable to map physical memory %p (%d bytes).", physaddr, size)
uintptr_t virtaddr = PA2KA(last_frame);
pfn_t i;
101,8 → 101,8
page = read_cr2();
if (istate->error_word & PFERR_CODE_RSVD)
panic("Reserved bit set in page directory.\n");
 
panic("Reserved bit set in page directory.");
if (istate->error_word & PFERR_CODE_RW)
access = PF_ACCESS_WRITE;
else
109,11 → 109,11
access = PF_ACCESS_READ;
if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate, "Page fault: %#x", page);
fault_if_from_uspace(istate, "Page fault: %#x.", page);
decode_istate(istate);
printf("page fault address: %#lx\n", page);
panic("page fault\n");
panic("Page fault.");
}
}
 
/branches/dd/kernel/arch/ia32/src/userspace.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
47,10 → 47,8
*/
void userspace(uspace_arg_t *kernel_uarg)
{
ipl_t ipl;
 
ipl = interrupts_disable();
 
ipl_t ipl = interrupts_disable();
asm volatile (
/*
* Clear nested task flag.
60,31 → 58,33
"and $0xffffbfff, %%eax\n"
"push %%eax\n"
"popfl\n"
 
/* Set up GS register (TLS) */
"movl %6, %%gs\n"
 
"pushl %0\n"
"pushl %1\n"
"pushl %2\n"
"pushl %3\n"
"pushl %4\n"
"movl %5, %%eax\n"
"movl %[tls_des], %%gs\n"
"pushl %[udata_des]\n"
"pushl %[stack_size]\n"
"pushl %[ipl]\n"
"pushl %[utext_des]\n"
"pushl %[entry]\n"
"movl %[uarg], %%eax\n"
/* %ebx is defined to hold pcb_ptr - set it to 0 */
"xorl %%ebx, %%ebx\n"
"iret\n"
:
: "i" (selector(UDATA_DES) | PL_USER),
"r" ((uint8_t *) kernel_uarg->uspace_stack +
THREAD_STACK_SIZE),
"r" (ipl),
"i" (selector(UTEXT_DES) | PL_USER),
"r" (kernel_uarg->uspace_entry),
"r" (kernel_uarg->uspace_uarg),
"r" (selector(TLS_DES))
:
: [udata_des] "i" (selector(UDATA_DES) | PL_USER),
[stack_size] "r" ((uint8_t *) kernel_uarg->uspace_stack + THREAD_STACK_SIZE),
[ipl] "r" (ipl),
[utext_des] "i" (selector(UTEXT_DES) | PL_USER),
[entry] "r" (kernel_uarg->uspace_entry),
[uarg] "r" (kernel_uarg->uspace_uarg),
[tls_des] "r" (selector(TLS_DES))
: "eax");
/* Unreachable */
for(;;)
;
while (1);
}
 
/** @}
/branches/dd/kernel/arch/ia32/src/interrupt.c
77,9 → 77,6
printf("ERROR_WORD=%#lx\n", istate->error_word);
printf("%%cs=%#lx,flags=%#lx\n", istate->cs, istate->eflags);
printf("%%eax=%#lx, %%ecx=%#lx, %%edx=%#lx, %%esp=%p\n", istate->eax, istate->ecx, istate->edx, &istate->stack[0]);
#ifdef CONFIG_DEBUG_ALLREGS
printf("%%esi=%#lx, %%edi=%#lx, %%ebp=%#lx, %%ebx=%#lx\n", istate->esi, istate->edi, istate->ebp, istate->ebx);
#endif
printf("stack: %#lx, %#lx, %#lx, %#lx\n", istate->stack[0], istate->stack[1], istate->stack[2], istate->stack[3]);
printf(" %#lx, %#lx, %#lx, %#lx\n", istate->stack[4], istate->stack[5], istate->stack[6], istate->stack[7]);
}
89,16 → 86,16
if (eoi_function)
eoi_function();
else
panic("no eoi_function\n");
panic("No eoi_function.");
 
}
 
static void null_interrupt(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "unserviced interrupt: %d", n);
fault_if_from_uspace(istate, "Unserviced interrupt: %d.", n);
 
decode_istate(istate);
panic("unserviced interrupt: %d\n", n);
panic("Unserviced interrupt: %d.", n);
}
 
/** General Protection Fault. */
122,19 → 119,19
io_perm_bitmap_install();
return;
}
fault_if_from_uspace(istate, "general protection fault");
fault_if_from_uspace(istate, "General protection fault.");
}
 
decode_istate(istate);
panic("general protection fault\n");
panic("General protection fault.");
}
 
static void ss_fault(int n __attribute__((unused)), istate_t *istate)
{
fault_if_from_uspace(istate, "stack fault");
fault_if_from_uspace(istate, "Stack fault.");
 
decode_istate(istate);
panic("stack fault\n");
panic("Stack fault.");
}
 
static void simd_fp_exception(int n __attribute__((unused)), istate_t *istate)
141,15 → 138,15
{
uint32_t mxcsr;
asm (
"stmxcsr %0;\n"
: "=m" (mxcsr)
"stmxcsr %[mxcsr]\n"
: [mxcsr] "=m" (mxcsr)
);
fault_if_from_uspace(istate, "SIMD FP exception(19), MXCSR: %#zx",
fault_if_from_uspace(istate, "SIMD FP exception(19), MXCSR: %#zx.",
(unative_t) mxcsr);
 
decode_istate(istate);
printf("MXCSR: %#lx\n", mxcsr);
panic("SIMD FP exception(19)\n");
panic("SIMD FP exception(19).");
}
 
static void nm_fault(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
157,8 → 154,8
#ifdef CONFIG_FPU_LAZY
scheduler_fpu_lazy_request();
#else
fault_if_from_uspace(istate, "fpu fault");
panic("fpu fault");
fault_if_from_uspace(istate, "FPU fault.");
panic("FPU fault.");
#endif
}
 
191,7 → 188,7
trap_virtual_eoi();
ack = true;
}
irq->handler(irq, irq->arg);
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
/*
233,7 → 230,7
if (enable_irqs_function)
enable_irqs_function(irqmask);
else
panic("no enable_irqs_function\n");
panic("No enable_irqs_function.");
}
 
void trap_virtual_disable_irqs(uint16_t irqmask)
241,7 → 238,7
if (disable_irqs_function)
disable_irqs_function(irqmask);
else
panic("no disable_irqs_function\n");
panic("No disable_irqs_function.");
}
 
/** @}
/branches/dd/kernel/arch/ia32/src/drivers/ega.c
File deleted
/branches/dd/kernel/arch/ia32/src/drivers/vesa.c
83,12 → 83,25
visual = VISUAL_RGB_0_8_8_8;
break;
default:
panic("Unsupported bits per pixel");
panic("Unsupported bits per pixel.");
}
fb_init(vesa_ph_addr, vesa_width, vesa_height, vesa_scanline, visual);
fb_properties_t vesa_props = {
.addr = vesa_ph_addr,
.offset = 0,
.x = vesa_width,
.y = vesa_height,
.scan = vesa_scanline,
.visual = visual,
};
fb_init(&vesa_props);
}
 
void vesa_redraw(void)
{
fb_redraw();
}
 
#endif
 
/** @}
/branches/dd/kernel/arch/ia32/src/drivers/i8259.c
49,28 → 49,28
void i8259_init(void)
{
/* ICW1: this is ICW1, ICW4 to follow */
outb(PIC_PIC0PORT1, PIC_ICW1 | PIC_NEEDICW4);
pio_write_8(PIC_PIC0PORT1, PIC_ICW1 | PIC_NEEDICW4);
 
/* ICW2: IRQ 0 maps to INT IRQBASE */
outb(PIC_PIC0PORT2, IVT_IRQBASE);
pio_write_8(PIC_PIC0PORT2, IVT_IRQBASE);
 
/* ICW3: pic1 using IRQ IRQ_PIC1 */
outb(PIC_PIC0PORT2, 1 << IRQ_PIC1);
pio_write_8(PIC_PIC0PORT2, 1 << IRQ_PIC1);
 
/* ICW4: i8086 mode */
outb(PIC_PIC0PORT2, 1);
pio_write_8(PIC_PIC0PORT2, 1);
 
/* ICW1: ICW1, ICW4 to follow */
outb(PIC_PIC1PORT1, PIC_ICW1 | PIC_NEEDICW4);
pio_write_8(PIC_PIC1PORT1, PIC_ICW1 | PIC_NEEDICW4);
 
/* ICW2: IRQ 8 maps to INT (IVT_IRQBASE + 8) */
outb(PIC_PIC1PORT2, IVT_IRQBASE + 8);
pio_write_8(PIC_PIC1PORT2, IVT_IRQBASE + 8);
 
/* ICW3: pic1 is known as IRQ_PIC1 */
outb(PIC_PIC1PORT2, IRQ_PIC1);
pio_write_8(PIC_PIC1PORT2, IRQ_PIC1);
 
/* ICW4: i8086 mode */
outb(PIC_PIC1PORT2, 1);
pio_write_8(PIC_PIC1PORT2, 1);
 
/*
* Register interrupt handler for the PIC spurious interrupt.
94,12 → 94,12
uint8_t x;
 
if (irqmask & 0xff) {
x = inb(PIC_PIC0PORT2);
outb(PIC_PIC0PORT2, (uint8_t) (x & (~(irqmask & 0xff))));
x = pio_read_8(PIC_PIC0PORT2);
pio_write_8(PIC_PIC0PORT2, (uint8_t) (x & (~(irqmask & 0xff))));
}
if (irqmask >> 8) {
x = inb(PIC_PIC1PORT2);
outb(PIC_PIC1PORT2, (uint8_t) (x & (~(irqmask >> 8))));
x = pio_read_8(PIC_PIC1PORT2);
pio_write_8(PIC_PIC1PORT2, (uint8_t) (x & (~(irqmask >> 8))));
}
}
 
108,19 → 108,19
uint8_t x;
 
if (irqmask & 0xff) {
x = inb(PIC_PIC0PORT2);
outb(PIC_PIC0PORT2, (uint8_t) (x | (irqmask & 0xff)));
x = pio_read_8(PIC_PIC0PORT2);
pio_write_8(PIC_PIC0PORT2, (uint8_t) (x | (irqmask & 0xff)));
}
if (irqmask >> 8) {
x = inb(PIC_PIC1PORT2);
outb(PIC_PIC1PORT2, (uint8_t) (x | (irqmask >> 8)));
x = pio_read_8(PIC_PIC1PORT2);
pio_write_8(PIC_PIC1PORT2, (uint8_t) (x | (irqmask >> 8)));
}
}
 
void pic_eoi(void)
{
outb(0x20, 0x20);
outb(0xa0, 0x20);
pio_write_8((ioport8_t *)0x20, 0x20);
pio_write_8((ioport8_t *)0xa0, 0x20);
}
 
void pic_spurious(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
/branches/dd/kernel/arch/ia32/src/drivers/i8254.c
53,8 → 53,8
#include <ddi/irq.h>
#include <ddi/device.h>
 
#define CLK_PORT1 0x40
#define CLK_PORT4 0x43
#define CLK_PORT1 ((ioport8_t *)0x40)
#define CLK_PORT4 ((ioport8_t *)0x43)
 
#define CLK_CONST 1193180
#define MAGIC_NUMBER 1194
61,12 → 61,12
 
static irq_t i8254_irq;
 
static irq_ownership_t i8254_claim(void)
static irq_ownership_t i8254_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
static void i8254_irq_handler(irq_t *irq, void *arg __attribute__((unused)), ...)
static void i8254_irq_handler(irq_t *irq)
{
/*
* This IRQ is responsible for kernel preemption.
94,10 → 94,10
 
void i8254_normal_operation(void)
{
outb(CLK_PORT4, 0x36);
pio_write_8(CLK_PORT4, 0x36);
pic_disable_irqs(1 << IRQ_CLK);
outb(CLK_PORT1, (CLK_CONST / HZ) & 0xf);
outb(CLK_PORT1, (CLK_CONST / HZ) >> 8);
pio_write_8(CLK_PORT1, (CLK_CONST / HZ) & 0xf);
pio_write_8(CLK_PORT1, (CLK_CONST / HZ) >> 8);
pic_enable_irqs(1 << IRQ_CLK);
}
 
114,36 → 114,36
* One-shot timer. Count-down from 0xffff at 1193180Hz
* MAGIC_NUMBER is the magic value for 1ms.
*/
outb(CLK_PORT4, 0x30);
outb(CLK_PORT1, 0xff);
outb(CLK_PORT1, 0xff);
pio_write_8(CLK_PORT4, 0x30);
pio_write_8(CLK_PORT1, 0xff);
pio_write_8(CLK_PORT1, 0xff);
 
do {
/* will read both status and count */
outb(CLK_PORT4, 0xc2);
not_ok = (uint8_t) ((inb(CLK_PORT1) >> 6) & 1);
t1 = inb(CLK_PORT1);
t1 |= inb(CLK_PORT1) << 8;
pio_write_8(CLK_PORT4, 0xc2);
not_ok = (uint8_t) ((pio_read_8(CLK_PORT1) >> 6) & 1);
t1 = pio_read_8(CLK_PORT1);
t1 |= pio_read_8(CLK_PORT1) << 8;
} while (not_ok);
 
asm_delay_loop(LOOPS);
 
outb(CLK_PORT4, 0xd2);
t2 = inb(CLK_PORT1);
t2 |= inb(CLK_PORT1) << 8;
pio_write_8(CLK_PORT4, 0xd2);
t2 = pio_read_8(CLK_PORT1);
t2 |= pio_read_8(CLK_PORT1) << 8;
 
/*
* We want to determine the overhead of the calibrating mechanism.
*/
outb(CLK_PORT4, 0xd2);
o1 = inb(CLK_PORT1);
o1 |= inb(CLK_PORT1) << 8;
pio_write_8(CLK_PORT4, 0xd2);
o1 = pio_read_8(CLK_PORT1);
o1 |= pio_read_8(CLK_PORT1) << 8;
 
asm_fake_loop(LOOPS);
 
outb(CLK_PORT4, 0xd2);
o2 = inb(CLK_PORT1);
o2 |= inb(CLK_PORT1) << 8;
pio_write_8(CLK_PORT4, 0xd2);
o2 = pio_read_8(CLK_PORT1);
o2 |= pio_read_8(CLK_PORT1) << 8;
 
CPU->delay_loop_const =
((MAGIC_NUMBER * LOOPS) / 1000) / ((t1 - t2) - (o1 - o2)) +