//branches/rcu/contrib/conf/msim.conf |
---|
5,7 → 5,7 |
add dcpu mips1 |
add rwm mainmem 0x0 8M load "/dev/zero" |
add rom startmem 0x1fc00000 1024k load "image.boot" |
add rom startmem 0x1fc00000 2048k load "image.boot" |
add dprinter printer 0x10000000 |
add dkeyboard keyboard 0x10000000 2 |
//branches/rcu/contrib/conf/ski.conf |
---|
6,6 → 6,6 |
romload HelenOS/uspace/kbd/kbd 0x1400000 |
romload HelenOS/uspace/tetris/tetris 0x1800000 |
romload HelenOS/uspace/klog/klog 0x1c00000 |
romload HelenOS/uspace/ipcc/ipcc 0x2000000 |
romload HelenOS/uspace/tester/tester 0x2000000 |
//branches/rcu/kernel/test/synch/rwlock3.c |
---|
45,14 → 45,14 |
thread_detach(THREAD); |
if (!sh_quiet) |
printf("cpu%d, tid %d: trying to lock rwlock for reading....\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu: 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 %d: success\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %d: trying to lock rwlock for writing....\n", CPU->id, THREAD->tid); |
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); |
} |
rwlock_write_lock(&rwlock); |
59,7 → 59,7 |
rwlock_write_unlock(&rwlock); |
if (!sh_quiet) |
printf("cpu%d, tid %d: success\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu: success\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
//branches/rcu/kernel/test/synch/rwlock4.c |
---|
74,18 → 74,18 |
to = random(40000); |
if (!sh_quiet) |
printf("cpu%d, tid %d w+ (%d)\n", CPU->id, THREAD->tid, to); |
printf("cpu%d, tid %llu 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 %d w!\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu w!\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
return; |
} |
if (!sh_quiet) |
printf("cpu%d, tid %d w=\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu 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 %d w-\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu w-\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
119,24 → 119,24 |
to = random(2000); |
if (!sh_quiet) |
printf("cpu%d, tid %d r+ (%d)\n", CPU->id, THREAD->tid, to); |
printf("cpu%d, tid %llu 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 %d r!\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu r!\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
return; |
} |
if (!sh_quiet) |
printf("cpu%d, tid %d r=\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu r=\n", CPU->id, THREAD->tid); |
thread_usleep(30000); |
rwlock_read_unlock(&rwlock); |
if (!sh_quiet) |
printf("cpu%d, tid %d r-\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu r-\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
//branches/rcu/kernel/test/synch/semaphore2.c |
---|
67,18 → 67,18 |
waitq_sleep(&can_start); |
to = random(20000); |
printf("cpu%d, tid %d down+ (%d)\n", CPU->id, THREAD->tid, to); |
printf("cpu%d, tid %llu down+ (%d)\n", CPU->id, THREAD->tid, to); |
rc = semaphore_down_timeout(&sem, to); |
if (SYNCH_FAILED(rc)) { |
printf("cpu%d, tid %d down!\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu down!\n", CPU->id, THREAD->tid); |
return; |
} |
printf("cpu%d, tid %d down=\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu down=\n", CPU->id, THREAD->tid); |
thread_usleep(random(30000)); |
semaphore_up(&sem); |
printf("cpu%d, tid %d up\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu up\n", CPU->id, THREAD->tid); |
} |
char * test_semaphore2(bool quiet) |
//branches/rcu/kernel/test/tasklet/tasklet1.c |
---|
43,6 → 43,7 |
} |
bool gquiet; |
#ifdef CONFIG_SMP |
static void running_tasklet(void * data) |
{ |
102,7 → 103,7 |
if (!gquiet) |
printf("Done!\n"); |
} |
#endif |
char * test_tasklet1(bool quiet) |
{ |
gquiet = quiet; |
109,8 → 110,8 |
waitq_t wq; |
waitq_initialize(&wq); |
tasklet_descriptor_t *tasklet_desc; |
#ifdef CONFIG_SMP |
thread_t* second_thread = NULL; |
#ifdef CONFIG_SMP |
if (!quiet) |
printf("cpus:%d\n", config.cpu_active); |
//branches/rcu/kernel/test/thread/thread1.c |
---|
48,8 → 48,8 |
while (atomic_get(&finish)) { |
if (!sh_quiet) |
printf("%d\n", (int) (THREAD->tid)); |
thread_usleep(100); |
printf("%llu ", THREAD->tid); |
thread_usleep(100000); |
} |
atomic_inc(&threads_finished); |
} |
//branches/rcu/kernel/test/mm/falloc2.c |
---|
58,7 → 58,7 |
uintptr_t * frames = (uintptr_t *) malloc(MAX_FRAMES * sizeof(uintptr_t), FRAME_ATOMIC); |
if (frames == NULL) { |
if (!sh_quiet) |
printf("Thread #%d (cpu%d): Unable to allocate frames\n", THREAD->tid, CPU->id); |
printf("Thread #%llu (cpu%d): Unable to allocate frames\n", THREAD->tid, CPU->id); |
atomic_inc(&thread_fail); |
atomic_dec(&thread_count); |
return; |
69,7 → 69,7 |
for (run = 0; run < THREAD_RUNS; run++) { |
for (order = 0; order <= MAX_ORDER; order++) { |
if (!sh_quiet) |
printf("Thread #%d (cpu%d): Allocating %d frames blocks ... \n", THREAD->tid, CPU->id, 1 << order); |
printf("Thread #%llu (cpu%d): Allocating %d frames blocks ... \n", THREAD->tid, CPU->id, 1 << order); |
allocated = 0; |
for (i = 0; i < (MAX_FRAMES >> order); i++) { |
82,16 → 82,16 |
} |
if (!sh_quiet) |
printf("Thread #%d (cpu%d): %d blocks allocated.\n", THREAD->tid, CPU->id, allocated); |
printf("Thread #%llu (cpu%d): %d blocks allocated.\n", THREAD->tid, CPU->id, allocated); |
if (!sh_quiet) |
printf("Thread #%d (cpu%d): Deallocating ... \n", THREAD->tid, CPU->id); |
printf("Thread #%llu (cpu%d): Deallocating ... \n", THREAD->tid, CPU->id); |
for (i = 0; i < allocated; i++) { |
for (k = 0; k <= ((FRAME_SIZE << order) - 1); k++) { |
if (((uint8_t *) frames[i])[k] != val) { |
if (!sh_quiet) |
printf("Thread #%d (cpu%d): Unexpected data (%d) in block %p offset %#zx\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k); |
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); |
atomic_inc(&thread_fail); |
goto cleanup; |
} |
100,7 → 100,7 |
} |
if (!sh_quiet) |
printf("Thread #%d (cpu%d): Finished run.\n", THREAD->tid, CPU->id); |
printf("Thread #%llu (cpu%d): Finished run.\n", THREAD->tid, CPU->id); |
} |
} |
108,7 → 108,7 |
free(frames); |
if (!sh_quiet) |
printf("Thread #%d (cpu%d): Exiting\n", THREAD->tid, CPU->id); |
printf("Thread #%llu (cpu%d): Exiting\n", THREAD->tid, CPU->id); |
atomic_dec(&thread_count); |
} |
//branches/rcu/kernel/test/mm/slab1.c |
---|
137,7 → 137,7 |
thread_detach(THREAD); |
if (!sh_quiet) |
printf("Starting thread #%d...\n", THREAD->tid); |
printf("Starting thread #%llu...\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 #%d finished\n", THREAD->tid); |
printf("Thread #%llu finished\n", THREAD->tid); |
semaphore_up(&thr_sem); |
} |
//branches/rcu/kernel/test/mm/slab2.c |
---|
150,11 → 150,11 |
mutex_unlock(&starter_mutex); |
if (!sh_quiet) |
printf("Starting thread #%d...\n",THREAD->tid); |
printf("Starting thread #%llu...\n",THREAD->tid); |
/* Alloc all */ |
if (!sh_quiet) |
printf("Thread #%d allocating...\n", THREAD->tid); |
printf("Thread #%llu allocating...\n", THREAD->tid); |
while (1) { |
/* Call with atomic to detect end of memory */ |
166,7 → 166,7 |
} |
if (!sh_quiet) |
printf("Thread #%d releasing...\n", THREAD->tid); |
printf("Thread #%llu releasing...\n", THREAD->tid); |
while (data) { |
new = *((void **)data); |
176,7 → 176,7 |
} |
if (!sh_quiet) |
printf("Thread #%d allocating...\n", THREAD->tid); |
printf("Thread #%llu allocating...\n", THREAD->tid); |
while (1) { |
/* Call with atomic to detect end of memory */ |
188,7 → 188,7 |
} |
if (!sh_quiet) |
printf("Thread #%d releasing...\n", THREAD->tid); |
printf("Thread #%llu releasing...\n", THREAD->tid); |
while (data) { |
new = *((void **)data); |
198,7 → 198,7 |
} |
if (!sh_quiet) |
printf("Thread #%d finished\n", THREAD->tid); |
printf("Thread #%llu finished\n", THREAD->tid); |
slab_print_list(); |
semaphore_up(&thr_sem); |
//branches/rcu/kernel/test/fpu/mips2.c |
---|
72,7 → 72,7 |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("General reg tid%d: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("General reg tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
104,7 → 104,7 |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("General reg tid%d: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("General reg tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
//branches/rcu/kernel/test/fpu/fpu1.c |
---|
126,7 → 126,7 |
if ((int) (100000000 * e) != E_10e8) { |
if (!sh_quiet) |
printf("tid%d: e*10e8=%zd should be %zd\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8); |
printf("tid%llu: e*10e8=%zd should be %zd\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8); |
atomic_inc(&threads_fault); |
break; |
} |
161,7 → 161,7 |
#ifdef KERN_ia64_ARCH_H_ |
if ((int) (1000000 * pi) != PI_10e8) { |
if (!sh_quiet) |
printf("tid%d: pi*10e8=%zd should be %zd\n", THREAD->tid, (unative_t) (1000000 * pi), (unative_t) (PI_10e8 / 100)); |
printf("tid%llu: pi*10e8=%zd should be %zd\n", THREAD->tid, (unative_t) (1000000 * pi), (unative_t) (PI_10e8 / 100)); |
atomic_inc(&threads_fault); |
break; |
} |
168,7 → 168,7 |
#else |
if ((int) (100000000 * pi) != PI_10e8) { |
if (!sh_quiet) |
printf("tid%d: pi*10e8=%zd should be %zd\n", THREAD->tid, (unative_t) (100000000 * pi), (unative_t) PI_10e8); |
printf("tid%llu: pi*10e8=%zd should be %zd\n", THREAD->tid, (unative_t) (100000000 * pi), (unative_t) PI_10e8); |
atomic_inc(&threads_fault); |
break; |
} |
//branches/rcu/kernel/test/fpu/sse1.c |
---|
72,7 → 72,7 |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("tid%d: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
104,7 → 104,7 |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("tid%d: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
//branches/rcu/kernel/test/print/print1.c |
---|
25,6 → 25,7 |
* (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 <test.h> |
//branches/rcu/kernel/kernel.config |
---|
92,9 → 92,6 |
# Lazy FPU context switching |
! [(ARCH=mips32&MACHINE!=msim&MACHINE!=simics)|ARCH=amd64|ARCH=ia32|ARCH=ia64|ARCH=sparc64|ARCH=ia32xen] CONFIG_FPU_LAZY (y/n) |
# Power off on halt |
! [ARCH=ppc32] CONFIG_POWEROFF (n/y) |
# Use VHPT |
! [ARCH=ia64] CONFIG_VHPT (n/y) |
//branches/rcu/kernel/genarch/src/acpi/acpi.c |
---|
88,7 → 88,7 |
static void map_sdt(struct acpi_sdt_header *sdt) |
{ |
page_mapping_insert(AS_KERNEL, (uintptr_t) sdt, (uintptr_t) sdt, PAGE_NOT_CACHEABLE); |
page_mapping_insert(AS_KERNEL, (uintptr_t) sdt, (uintptr_t) sdt, PAGE_NOT_CACHEABLE | PAGE_WRITE); |
map_structure((uintptr_t) sdt, sdt->length); |
} |
//branches/rcu/kernel/generic/include/print.h |
---|
40,7 → 40,7 |
#include <arch/arg.h> |
/* We need this address in spinlock to avoid deadlock in deadlock detection */ |
SPINLOCK_EXTERN(printflock); |
SPINLOCK_EXTERN(printf_lock); |
#define EOF (-1) |
//branches/rcu/kernel/generic/include/time/clock.h |
---|
35,8 → 35,19 |
#ifndef KERN_CLOCK_H_ |
#define KERN_CLOCK_H_ |
#include <arch/types.h> |
#define HZ 100 |
/** Uptime structure */ |
typedef struct { |
unative_t seconds1; |
unative_t useconds; |
unative_t seconds2; |
} uptime_t; |
extern uptime_t *uptime; |
extern void clock(void); |
extern void clock_counter_init(void); |
//branches/rcu/kernel/generic/include/proc/task.h |
---|
90,10 → 90,10 |
* Active asynchronous messages. It is used for limiting uspace to |
* certain extent. |
*/ |
atomic_t active_calls; |
atomic_t active_calls; |
/** Architecture specific task data. */ |
task_arch_t arch; |
task_arch_t arch; |
/** |
* Serializes access to the B+tree of task's futexes. This mutex is |
111,6 → 111,7 |
extern btree_t tasks_btree; |
extern void task_init(void); |
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); |
//branches/rcu/kernel/generic/include/proc/thread.h |
---|
53,7 → 53,11 |
/* Thread flags */ |
/** Thread cannot be migrated to another CPU. */ |
/** Thread cannot be migrated to another CPU. |
* |
* When using this flag, the caller must set cpu in the thread_t |
* structure manually before calling thread_ready (even on uniprocessor). |
*/ |
#define THREAD_FLAG_WIRED (1 << 0) |
/** Thread was migrated to another CPU and has not run yet. */ |
#define THREAD_FLAG_STOLEN (1 << 1) |
193,7 → 197,7 |
/** Thread's priority. Implemented as index to CPU->rq */ |
int priority; |
/** Thread ID. */ |
uint32_t tid; |
thread_id_t tid; |
/** Architecture-specific data. */ |
thread_arch_t arch; |
248,8 → 252,9 |
extern slab_cache_t *fpu_context_slab; |
/* Thread syscall prototypes. */ |
unative_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name); |
unative_t sys_thread_exit(int uspace_status); |
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_exit(int uspace_status); |
extern unative_t sys_thread_get_id(thread_id_t *uspace_thread_id); |
#endif |
//branches/rcu/kernel/generic/include/interrupt.h |
---|
48,7 → 48,7 |
#define fault_if_from_uspace(istate, cmd, ...) \ |
{ \ |
if (istate_from_uspace(istate)) { \ |
klog_printf("Task %lld killed due to an exception at %p.", TASK->taskid, istate_get_pc(istate)); \ |
klog_printf("Task %llu killed due to an exception at %p.", TASK->taskid, istate_get_pc(istate)); \ |
klog_printf(" " cmd, ##__VA_ARGS__); \ |
task_kill(TASK->taskid); \ |
thread_exit(); \ |
//branches/rcu/kernel/generic/include/synch/mutex.h |
---|
44,13 → 44,11 |
} mutex_t; |
#define mutex_lock(mtx) \ |
_mutex_lock_timeout((mtx),SYNCH_NO_TIMEOUT,SYNCH_FLAGS_NONE) |
_mutex_lock_timeout((mtx), SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE) |
#define mutex_trylock(mtx) \ |
_mutex_lock_timeout((mtx),SYNCH_NO_TIMEOUT,SYNCH_FLAGS_NON_BLOCKING) |
#define mutex_lock_timeout(mtx,usec) \ |
_mutex_lock_timeout((mtx),(usec),SYNCH_FLAGS_NON_BLOCKING) |
#define mutex_lock_active(mtx) \ |
while (mutex_trylock((mtx)) != ESYNCH_OK_ATOMIC) |
_mutex_lock_timeout((mtx), SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NON_BLOCKING) |
#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); |
//branches/rcu/kernel/generic/include/synch/spinlock.h |
---|
101,8 → 101,26 |
preemption_enable(); |
} |
#ifdef CONFIG_DEBUG_SPINLOCK |
extern int printf(const char *, ...); |
#define DEADLOCK_THRESHOLD 100000000 |
#define DEADLOCK_PROBE_INIT(pname) count_t pname = 0 |
#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", \ |
#pname, (value), CPU->id, __FUNCTION__, __LINE__); \ |
} |
#else |
#define DEADLOCK_PROBE_INIT(pname) |
#define DEADLOCK_PROBE(pname, value) |
#endif |
#else |
/* On UP systems, spinlocks are effectively left out. */ |
#define SPINLOCK_DECLARE(name) |
#define SPINLOCK_EXTERN(name) |
113,6 → 131,9 |
#define spinlock_trylock(x) (preemption_disable(), 1) |
#define spinlock_unlock(x) preemption_enable() |
#define DEADLOCK_PROBE_INIT(pname) |
#define DEADLOCK_PROBE(pname, value) |
#endif |
#endif |
//branches/rcu/kernel/generic/include/ddi/irq.h |
---|
121,6 → 121,14 |
* this lock must not be taken first. |
*/ |
SPINLOCK_DECLARE(lock); |
/** Send EOI before processing the interrupt. |
* This is essential for timer interrupt which |
* has to be acknowledged before doing preemption |
* to make sure another timer interrupt will |
* be eventually generated. |
*/ |
bool preack; |
/** Unique device number. -1 if not yet assigned. */ |
devno_t devno; |
127,7 → 135,7 |
/** Actual IRQ number. -1 if not yet assigned. */ |
inr_t inr; |
/** Trigger level of the IRQ.*/ |
/** Trigger level of the IRQ. */ |
irq_trigger_t trigger; |
/** Claim ownership of the IRQ. */ |
irq_ownership_t (* claim)(void); |
//branches/rcu/kernel/generic/include/printf/printf_core.h |
---|
47,7 → 47,7 |
}; |
int printf_core(const char *fmt, struct printf_spec *ps ,va_list ap); |
int printf_core(const char *fmt, struct printf_spec *ps, va_list ap); |
#endif |
//branches/rcu/kernel/generic/include/arch.h |
---|
74,8 → 74,12 |
extern void arch_post_cpu_init(void); |
extern void arch_pre_smp_init(void); |
extern void arch_post_smp_init(void); |
extern void calibrate_delay_loop(void); |
extern void reboot(void); |
extern void arch_reboot(void); |
#endif |
/** @} |
//branches/rcu/kernel/generic/include/mm/as.h |
---|
101,11 → 101,11 |
*/ |
asid_t asid; |
/** Number of references (i.e tasks that reference this as). */ |
atomic_t refcount; |
mutex_t lock; |
/** Number of references (i.e tasks that reference this as). */ |
count_t refcount; |
/** B+tree of address space areas. */ |
btree_t as_area_btree; |
147,11 → 147,11 |
*/ |
asid_t asid; |
/** Number of references (i.e tasks that reference this as). */ |
atomic_t refcount; |
mutex_t lock; |
/** Number of references (i.e tasks that reference this as). */ |
count_t refcount; |
/** B+tree of address space areas. */ |
btree_t as_area_btree; |
//branches/rcu/kernel/generic/include/syscall/syscall.h |
---|
40,6 → 40,7 |
SYS_TLS_SET = 1, /* Hardcoded in AMD64, IA32 uspace - psthread.S */ |
SYS_THREAD_CREATE, |
SYS_THREAD_EXIT, |
SYS_THREAD_GET_ID, |
SYS_TASK_GET_ID, |
SYS_FUTEX_SLEEP, |
SYS_FUTEX_WAKEUP, |
//branches/rcu/kernel/generic/src/synch/spinlock.c |
---|
73,7 → 73,6 |
* @param sl Pointer to spinlock_t structure. |
*/ |
#ifdef CONFIG_DEBUG_SPINLOCK |
#define DEADLOCK_THRESHOLD 100000000 |
void spinlock_lock_debug(spinlock_t *sl) |
{ |
count_t i = 0; |
84,7 → 83,7 |
while (test_and_set(&sl->val)) { |
/* |
* We need to be careful about printflock and fb_lock. |
* We need to be careful about printf_lock and fb_lock. |
* Both of them are used to report deadlocks via |
* printf() and fb_putchar(). |
* |
94,13 → 93,13 |
* However, we encountered false positives caused by very |
* slow VESA framebuffer interaction (especially when |
* run in a simulator) that caused problems with both |
* printflock and fb_lock. |
* printf_lock and fb_lock. |
* |
* Possible deadlocks on both printflock and fb_lock |
* Possible deadlocks on both printf_lock and fb_lock |
* are therefore not reported as they would cause an |
* infinite recursion. |
*/ |
if (sl == &printflock) |
if (sl == &printf_lock) |
continue; |
#ifdef CONFIG_FB |
if (sl == &fb_lock) |
//branches/rcu/kernel/generic/src/main/kinit.c |
---|
118,7 → 118,7 |
#ifdef CONFIG_SMP |
if (config.cpu_count > 1) { |
unsigned int i; |
count_t i; |
/* |
* For each CPU, create its load balancing thread. |
//branches/rcu/kernel/generic/src/main/main.c |
---|
82,6 → 82,7 |
#include <smp/smp.h> |
#include <ddi/ddi.h> |
#include <proc/tasklet.h> |
#include <synch/rcu.h> |
/** Global configuration structure. */ |
config_t config; |
275,6 → 276,8 |
tasklet_run_tasklet_thread(k); |
rcu_init(); |
/* |
* This call to scheduler() will return to kinit, |
* starting the thread of kernel threads. |
//branches/rcu/kernel/generic/src/time/timeout.c |
---|
45,7 → 45,6 |
#include <arch/asm.h> |
#include <arch.h> |
/** Initialize timeouts |
* |
* Initialize kernel timeouts. |
175,6 → 174,7 |
timeout_t *hlp; |
link_t *l; |
ipl_t ipl; |
DEADLOCK_PROBE_INIT(p_tolock); |
grab_locks: |
ipl = interrupts_disable(); |
186,7 → 186,8 |
} |
if (!spinlock_trylock(&t->cpu->timeoutlock)) { |
spinlock_unlock(&t->lock); |
interrupts_restore(ipl); |
interrupts_restore(ipl); |
DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD); |
goto grab_locks; |
} |
//branches/rcu/kernel/generic/src/time/clock.c |
---|
41,7 → 41,6 |
#include <time/clock.h> |
#include <time/timeout.h> |
#include <arch/types.h> |
#include <config.h> |
#include <synch/spinlock.h> |
#include <synch/waitq.h> |
57,16 → 56,12 |
#include <mm/frame.h> |
#include <ddi/ddi.h> |
/** Physical memory area of the real time clock. */ |
/* Pointer to variable with uptime */ |
uptime_t *uptime; |
/** Physical memory area of the real time clock */ |
static parea_t clock_parea; |
/* Pointers to public variables with time */ |
struct ptime { |
unative_t seconds1; |
unative_t useconds; |
unative_t seconds2; |
}; |
struct ptime *public_time; |
/* Variable holding fragment of second, so that we would update |
* seconds correctly |
*/ |
86,15 → 81,14 |
if (!faddr) |
panic("Cannot allocate page for clock"); |
public_time = (struct ptime *) PA2KA(faddr); |
uptime = (uptime_t *) PA2KA(faddr); |
uptime->seconds1 = 0; |
uptime->seconds2 = 0; |
uptime->useconds = 0; |
/* TODO: We would need some arch dependent settings here */ |
public_time->seconds1 = 0; |
public_time->seconds2 = 0; |
public_time->useconds = 0; |
clock_parea.pbase = (uintptr_t) faddr; |
clock_parea.vbase = (uintptr_t) public_time; |
clock_parea.vbase = (uintptr_t) uptime; |
clock_parea.frames = 1; |
clock_parea.cacheable = true; |
ddi_parea_register(&clock_parea); |
116,16 → 110,16 |
static void clock_update_counters(void) |
{ |
if (CPU->id == 0) { |
secfrag += 1000000/HZ; |
secfrag += 1000000 / HZ; |
if (secfrag >= 1000000) { |
secfrag -= 1000000; |
public_time->seconds1++; |
uptime->seconds1++; |
write_barrier(); |
public_time->useconds = secfrag; |
uptime->useconds = secfrag; |
write_barrier(); |
public_time->seconds2 = public_time->seconds1; |
uptime->seconds2 = uptime->seconds1; |
} else |
public_time->useconds += 1000000/HZ; |
uptime->useconds += 1000000 / HZ; |
} |
} |
//branches/rcu/kernel/generic/src/ddi/irq.c |
---|
138,6 → 138,7 |
{ |
link_initialize(&irq->link); |
spinlock_initialize(&irq->lock, "irq.lock"); |
irq->preack = false; |
irq->inr = -1; |
irq->devno = -1; |
irq->trigger = (irq_trigger_t) 0; |
//branches/rcu/kernel/generic/src/printf/snprintf.c |
---|
50,4 → 50,3 |
/** @} |
*/ |
//branches/rcu/kernel/generic/src/printf/vprintf.c |
---|
35,7 → 35,11 |
#include <print.h> |
#include <printf/printf_core.h> |
#include <putchar.h> |
#include <synch/spinlock.h> |
#include <arch/asm.h> |
SPINLOCK_INITIALIZE(printf_lock); /**< vprintf spinlock */ |
static int vprintf_write(const char *str, size_t count, void *unused) |
{ |
size_t i; |
55,8 → 59,16 |
int vprintf(const char *fmt, va_list ap) |
{ |
struct printf_spec ps = {(int(*)(void *, size_t, void *)) vprintf_write, NULL}; |
return printf_core(fmt, &ps, ap); |
int irqpri = interrupts_disable(); |
spinlock_lock(&printf_lock); |
int ret = printf_core(fmt, &ps, ap); |
spinlock_unlock(&printf_lock); |
interrupts_restore(irqpri); |
return ret; |
} |
/** @} |
//branches/rcu/kernel/generic/src/printf/vsnprintf.c |
---|
42,8 → 42,6 |
char *string; /* destination string */ |
}; |
int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data); |
/** Write string to given buffer. |
* Write at most data->size characters including trailing zero. According to C99, snprintf() has to return number |
* of characters that would have been written if enough space had been available. Hence the return value is not |
54,7 → 52,7 |
* @param data structure with destination string, counter of used space and total string size. |
* @return number of characters to print (not characters really printed!) |
*/ |
int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
static int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
{ |
size_t i; |
i = data->size - data->len; |
//branches/rcu/kernel/generic/src/printf/printf_core.c |
---|
38,14 → 38,9 |
#include <printf/printf_core.h> |
#include <putchar.h> |
#include <print.h> |
#include <synch/spinlock.h> |
#include <arch/arg.h> |
#include <arch/asm.h> |
#include <arch.h> |
SPINLOCK_INITIALIZE(printflock); /**< printf spinlock */ |
#define __PRINTF_FLAG_PREFIX 0x00000001 /**< show prefixes 0x or 0*/ |
#define __PRINTF_FLAG_SIGNED 0x00000002 /**< signed / unsigned number */ |
#define __PRINTF_FLAG_ZEROPADDED 0x00000004 /**< print leading zeroes */ |
458,7 → 453,6 |
*/ |
int printf_core(const char *fmt, struct printf_spec *ps, va_list ap) |
{ |
int irqpri; |
int i = 0, j = 0; /**< i is index of currently processed char from fmt, j is index to the first not printed nonformating character */ |
int end; |
int counter; /**< counter of printed characters */ |
472,10 → 466,7 |
uint64_t flags; |
counter = 0; |
irqpri = interrupts_disable(); |
spinlock_lock(&printflock); |
while ((c = fmt[i])) { |
/* control character */ |
if (c == '%' ) { |
712,8 → 703,6 |
} |
out: |
spinlock_unlock(&printflock); |
interrupts_restore(irqpri); |
return counter; |
} |
//branches/rcu/kernel/generic/src/printf/vsprintf.c |
---|
36,7 → 36,7 |
int vsprintf(char *str, const char *fmt, va_list ap) |
{ |
return vsnprintf(str, (size_t)-1, fmt, ap); |
return vsnprintf(str, (size_t) - 1, fmt, ap); |
} |
/** @} |
//branches/rcu/kernel/generic/src/console/cmd.c |
---|
48,6 → 48,7 |
#include <arch/types.h> |
#include <adt/list.h> |
#include <arch.h> |
#include <config.h> |
#include <func.h> |
#include <macros.h> |
#include <debug.h> |
79,10 → 80,26 |
static cmd_info_t exit_info = { |
.name = "exit", |
.description = "Exit kconsole", |
.description = "Exit kconsole.", |
.argc = 0 |
}; |
static int cmd_reboot(cmd_arg_t *argv); |
static cmd_info_t reboot_info = { |
.name = "reboot", |
.description = "Reboot.", |
.func = cmd_reboot, |
.argc = 0 |
}; |
static int cmd_uptime(cmd_arg_t *argv); |
static cmd_info_t uptime_info = { |
.name = "uptime", |
.description = "Print uptime information.", |
.func = cmd_uptime, |
.argc = 0 |
}; |
static int cmd_continue(cmd_arg_t *argv); |
static cmd_info_t continue_info = { |
.name = "continue", |
192,10 → 209,10 |
}; |
/* Data and methods for 'call0' command. */ |
static char call0_buf[MAX_CMDLINE+1]; |
static char carg1_buf[MAX_CMDLINE+1]; |
static char carg2_buf[MAX_CMDLINE+1]; |
static char carg3_buf[MAX_CMDLINE+1]; |
static char call0_buf[MAX_CMDLINE + 1]; |
static char carg1_buf[MAX_CMDLINE + 1]; |
static char carg2_buf[MAX_CMDLINE + 1]; |
static char carg3_buf[MAX_CMDLINE + 1]; |
static int cmd_call0(cmd_arg_t *argv); |
static cmd_arg_t call0_argv = { |
211,6 → 228,21 |
.argv = &call0_argv |
}; |
/* Data and methods for 'mcall0' command. */ |
static int cmd_mcall0(cmd_arg_t *argv); |
static cmd_arg_t mcall0_argv = { |
.type = ARG_TYPE_STRING, |
.buffer = call0_buf, |
.len = sizeof(call0_buf) |
}; |
static cmd_info_t mcall0_info = { |
.name = "mcall0", |
.description = "mcall0 <function> -> call function() on each CPU.", |
.func = cmd_mcall0, |
.argc = 1, |
.argv = &mcall0_argv |
}; |
/* Data and methods for 'call1' command. */ |
static int cmd_call1(cmd_arg_t *argv); |
static cmd_arg_t call1_argv[] = { |
406,6 → 438,7 |
static cmd_info_t *basic_commands[] = { |
&call0_info, |
&mcall0_info, |
&call1_info, |
&call2_info, |
&call3_info, |
413,6 → 446,8 |
&cpus_info, |
&desc_info, |
&exit_info, |
&reboot_info, |
&uptime_info, |
&halt_info, |
&help_info, |
&ipc_task_info, |
488,6 → 523,41 |
return 1; |
} |
/** Reboot the system. |
* |
* @param argv Argument vector. |
* |
* @return 0 on failure, 1 on success. |
*/ |
int cmd_reboot(cmd_arg_t *argv) |
{ |
reboot(); |
/* Not reached */ |
return 1; |
} |
/** Print system uptime information. |
* |
* @param argv Argument vector. |
* |
* @return 0 on failure, 1 on success. |
*/ |
int cmd_uptime(cmd_arg_t *argv) |
{ |
ASSERT(uptime); |
/* This doesn't have to be very accurate */ |
unative_t sec = uptime->seconds1; |
printf("Up %u days, %u hours, %u minutes, %u seconds\n", |
sec / 86400, (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60); |
return 1; |
} |
/** Describe specified command. |
* |
* @param argv Argument vector. |
540,7 → 610,7 |
struct { |
unative_t f; |
unative_t gp; |
}fptr; |
} fptr; |
#endif |
symaddr = get_symbol_addr((char *) argv->buffer); |
551,7 → 621,7 |
printf("Duplicate symbol, be more specific.\n"); |
} else { |
symbol = get_symtab_entry(symaddr); |
printf("Calling f(): %.*p: %s\n", sizeof(uintptr_t) * 2, symaddr, symbol); |
printf("Calling %s() (%.*p)\n", symbol, sizeof(uintptr_t) * 2, symaddr); |
#ifdef ia64 |
fptr.f = symaddr; |
fptr.gp = ((unative_t *)cmd_call2)[1]; |
565,6 → 635,32 |
return 1; |
} |
/** Call function with zero parameters on each CPU */ |
int cmd_mcall0(cmd_arg_t *argv) |
{ |
/* |
* For each CPU, create a thread which will |
* call the function. |
*/ |
count_t i; |
for (i = 0; i < config.cpu_count; i++) { |
thread_t *t; |
if ((t = thread_create((void (*)(void *)) cmd_call0, (void *) argv, TASK, THREAD_FLAG_WIRED, "call0", false))) { |
spinlock_lock(&t->lock); |
t->cpu = &cpus[i]; |
spinlock_unlock(&t->lock); |
printf("cpu%u: ", i); |
thread_ready(t); |
thread_join(t); |
thread_detach(t); |
} else |
printf("Unable to create thread for cpu%u\n", i); |
} |
return 1; |
} |
/** Call function with one parameter */ |
int cmd_call1(cmd_arg_t *argv) |
{ |
713,7 → 809,7 |
/** Write 4 byte value to address */ |
int cmd_set4(cmd_arg_t *argv) |
{ |
uint32_t *addr ; |
uint32_t *addr; |
uint32_t arg1 = argv[1].intval; |
bool pointer = false; |
//branches/rcu/kernel/generic/src/proc/scheduler.c |
---|
61,6 → 61,7 |
#include <cpu.h> |
#include <print.h> |
#include <debug.h> |
#include <synch/rcu.h> |
static void before_task_runs(void); |
static void before_thread_runs(void); |
115,6 → 116,7 |
void after_thread_ran(void) |
{ |
after_thread_ran_arch(); |
rcu_run_callbacks(); |
} |
#ifdef CONFIG_FPU_LAZY |
207,7 → 209,7 |
interrupts_disable(); |
for (i = 0; i<RQ_COUNT; i++) { |
for (i = 0; i < RQ_COUNT; i++) { |
r = &CPU->rq[i]; |
spinlock_lock(&r->lock); |
if (r->n == 0) { |
377,7 → 379,8 |
void scheduler_separated_stack(void) |
{ |
int priority; |
DEADLOCK_PROBE_INIT(p_joinwq); |
ASSERT(CPU != NULL); |
if (THREAD) { |
406,6 → 409,8 |
spinlock_unlock(&THREAD->lock); |
delay(10); |
spinlock_lock(&THREAD->lock); |
DEADLOCK_PROBE(p_joinwq, |
DEADLOCK_THRESHOLD); |
goto repeat; |
} |
_waitq_wakeup_unsafe(&THREAD->join_wq, false); |
447,8 → 452,8 |
/* |
* Entering state is unexpected. |
*/ |
panic("tid%d: unexpected state %s\n", THREAD->tid, |
thread_states[THREAD->state]); |
panic("tid%llu: unexpected state %s\n", THREAD->tid, |
thread_states[THREAD->state]); |
break; |
} |
500,7 → 505,7 |
THREAD->state = Running; |
#ifdef SCHEDULER_VERBOSE |
printf("cpu%d: tid %d (priority=%d, ticks=%lld, nrdy=%ld)\n", |
printf("cpu%d: tid %llu (priority=%d, ticks=%llu, nrdy=%ld)\n", |
CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks, |
atomic_get(&CPU->nrdy)); |
#endif |
568,7 → 573,7 |
* Searching least priority queues on all CPU's first and most priority |
* queues on all CPU's last. |
*/ |
for (j= RQ_COUNT - 1; j >= 0; j--) { |
for (j = RQ_COUNT - 1; j >= 0; j--) { |
for (i = 0; i < config.cpu_active; i++) { |
link_t *l; |
runq_t *r; |
609,8 → 614,8 |
*/ |
spinlock_lock(&t->lock); |
if ((!(t->flags & (THREAD_FLAG_WIRED | |
THREAD_FLAG_STOLEN))) && |
(!(t->fpu_context_engaged)) ) { |
THREAD_FLAG_STOLEN))) && |
(!(t->fpu_context_engaged))) { |
/* |
* Remove t from r. |
*/ |
636,7 → 641,7 |
*/ |
spinlock_lock(&t->lock); |
#ifdef KCPULB_VERBOSE |
printf("kcpulb%d: TID %d -> cpu%d, nrdy=%ld, " |
printf("kcpulb%d: TID %llu -> cpu%d, nrdy=%ld, " |
"avg=%nd\n", CPU->id, t->tid, CPU->id, |
atomic_get(&CPU->nrdy), |
atomic_get(&nrdy) / config.cpu_active); |
719,7 → 724,7 |
for (cur = r->rq_head.next; cur != &r->rq_head; |
cur = cur->next) { |
t = list_get_instance(cur, thread_t, rq_link); |
printf("%d(%s) ", t->tid, |
printf("%llu(%s) ", t->tid, |
thread_states[t->state]); |
} |
printf("\n"); |
//branches/rcu/kernel/generic/src/proc/task.c |
---|
41,6 → 41,7 |
#include <proc/uarg.h> |
#include <mm/as.h> |
#include <mm/slab.h> |
#include <atomic.h> |
#include <synch/spinlock.h> |
#include <synch/waitq.h> |
#include <arch.h> |
92,6 → 93,49 |
btree_create(&tasks_btree); |
} |
/** Kill all tasks except the current task. |
* |
*/ |
void task_done(void) |
{ |
task_t *t; |
do { /* Repeat until there are any tasks except TASK */ |
/* Messing with task structures, avoid deadlock */ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&tasks_lock); |
t = NULL; |
link_t *cur; |
for (cur = tasks_btree.leaf_head.next; cur != &tasks_btree.leaf_head; cur = cur->next) { |
btree_node_t *node = list_get_instance(cur, btree_node_t, leaf_link); |
unsigned int i; |
for (i = 0; i < node->keys; i++) { |
if ((task_t *) node->value[i] != TASK) { |
t = (task_t *) node->value[i]; |
break; |
} |
} |
} |
if (t != NULL) { |
task_id_t id = t->taskid; |
spinlock_unlock(&tasks_lock); |
interrupts_restore(ipl); |
#ifdef CONFIG_DEBUG |
printf("Killing task %llu\n", id); |
#endif |
task_kill(id); |
} else { |
spinlock_unlock(&tasks_lock); |
interrupts_restore(ipl); |
} |
} while (t != NULL); |
} |
/** Create new task |
* |
140,11 → 184,8 |
/* |
* Increment address space reference count. |
* TODO: Reconsider the locking scheme. |
*/ |
mutex_lock(&as->lock); |
as->refcount++; |
mutex_unlock(&as->lock); |
atomic_inc(&as->refcount); |
spinlock_lock(&tasks_lock); |
166,15 → 207,8 |
task_destroy_arch(t); |
btree_destroy(&t->futexes); |
mutex_lock_active(&t->as->lock); |
if (--t->as->refcount == 0) { |
mutex_unlock(&t->as->lock); |
if (atomic_predec(&t->as->refcount) == 0) |
as_destroy(t->as); |
/* |
* t->as is destroyed. |
*/ |
} else |
mutex_unlock(&t->as->lock); |
free(t); |
TASK = NULL; |
382,7 → 416,7 |
link_t *cur; |
ipl_t ipl; |
/* Messing with thread structures, avoid deadlock */ |
/* Messing with task structures, avoid deadlock */ |
ipl = interrupts_disable(); |
spinlock_lock(&tasks_lock); |
408,7 → 442,7 |
char suffix; |
order(task_get_accounting(t), &cycles, &suffix); |
printf("%-6lld %-10s %-3ld %#10zx %#10zx %9llu%c %7zd " |
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)); |
495,7 → 529,7 |
ipc_cleanup(); |
futex_cleanup(); |
klog_printf("Cleanup of task %lld completed.", TASK->taskid); |
klog_printf("Cleanup of task %llu completed.", TASK->taskid); |
} |
/** Kernel thread used to kill the userspace task when its main thread exits. |
//branches/rcu/kernel/generic/src/proc/thread.c |
---|
94,7 → 94,7 |
btree_t threads_btree; |
SPINLOCK_INITIALIZE(tidlock); |
uint32_t last_tid = 0; |
thread_id_t last_tid = 0; |
static slab_cache_t *thread_slab; |
#ifdef ARCH_HAS_FPU |
238,6 → 238,7 |
cpu = CPU; |
if (t->flags & THREAD_FLAG_WIRED) { |
ASSERT(t->cpu != NULL); |
cpu = t->cpu; |
} |
t->state = Ready; |
496,7 → 497,7 |
ipl_t ipl; |
/* |
* Since the thread is expected to not be already detached, |
* Since the thread is expected not to be already detached, |
* pointer to it must be still valid. |
*/ |
ipl = interrupts_disable(); |
580,7 → 581,7 |
char suffix; |
order(t->cycles, &cycles, &suffix); |
printf("%-6zd %-10s %#10zx %-8s %#10zx %-3ld %#10zx " |
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); |
636,12 → 637,11 |
/** Process syscall to create new thread. |
* |
*/ |
unative_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name) |
unative_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name, thread_id_t *uspace_thread_id) |
{ |
thread_t *t; |
char namebuf[THREAD_NAME_BUFLEN]; |
uspace_arg_t *kernel_uarg; |
uint32_t tid; |
int rc; |
rc = copy_from_uspace(namebuf, uspace_name, THREAD_NAME_BUFLEN); |
658,12 → 658,14 |
t = thread_create(uinit, kernel_uarg, TASK, THREAD_FLAG_USPACE, namebuf, |
false); |
if (t) { |
tid = t->tid; |
thread_ready(t); |
return (unative_t) tid; |
} else { |
if (uspace_thread_id != NULL) |
return (unative_t) copy_to_uspace(uspace_thread_id, &t->tid, |
sizeof(t->tid)); |
else |
return 0; |
} else |
free(kernel_uarg); |
} |
return (unative_t) ENOMEM; |
} |
678,6 → 680,22 |
return 0; |
} |
/** Syscall for getting TID. |
* |
* @param uspace_thread_id Userspace address of 8-byte buffer where to store |
* current thread ID. |
* |
* @return 0 on success or an error code from @ref errno.h. |
*/ |
unative_t sys_thread_get_id(thread_id_t *uspace_thread_id) |
{ |
/* |
* No need to acquire lock on THREAD because tid |
* remains constant for the lifespan of the thread. |
*/ |
return (unative_t) copy_to_uspace(uspace_thread_id, &THREAD->tid, |
sizeof(THREAD->tid)); |
} |
/** @} |
*/ |
//branches/rcu/kernel/generic/src/lib/memstr.c |
---|
130,7 → 130,8 |
{ |
char *orig = dest; |
while ((*(dest++) = *(src++))); |
while ((*(dest++) = *(src++))) |
; |
return orig; |
} |
//branches/rcu/kernel/generic/src/lib/func.c |
---|
223,20 → 223,23 |
void order(const uint64_t val, uint64_t *rv, char *suffix) |
{ |
if (val > 1000000000000000000LL) { |
*rv = val / 1000000000000000LL; |
if (val > 10000000000000000000ULL) { |
*rv = val / 1000000000000000000ULL; |
*suffix = 'Z'; |
} else if (val > 1000000000000000000ULL) { |
*rv = val / 1000000000000000ULL; |
*suffix = 'E'; |
} else if (val > 1000000000000000LL) { |
*rv = val / 1000000000000LL; |
} else if (val > 1000000000000000ULL) { |
*rv = val / 1000000000000ULL; |
*suffix = 'T'; |
} else if (val > 1000000000000LL) { |
*rv = val / 1000000000LL; |
} else if (val > 1000000000000ULL) { |
*rv = val / 1000000000ULL; |
*suffix = 'G'; |
} else if (val > 1000000000LL) { |
*rv = val / 1000000LL; |
} else if (val > 1000000000ULL) { |
*rv = val / 1000000ULL; |
*suffix = 'M'; |
} else if (val > 1000000LL) { |
*rv = val / 1000LL; |
} else if (val > 1000000ULL) { |
*rv = val / 1000ULL; |
*suffix = 'k'; |
} else { |
*rv = val; |
//branches/rcu/kernel/generic/src/lib/objc.c |
---|
49,7 → 49,7 |
return class_create_instance(self); |
} |
- (id) free |
- (id) dispose |
{ |
return object_dispose(self); |
} |
//branches/rcu/kernel/generic/src/adt/btree.c |
---|
970,7 → 970,7 |
printf("("); |
for (i = 0; i < node->keys; i++) { |
printf("%lld%s", node->key[i], i < node->keys - 1 ? "," : ""); |
printf("%llu%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("%lld%s", node->key[i], i < node->keys - 1 ? "," : ""); |
printf("%llu%s", node->key[i], i < node->keys - 1 ? "," : ""); |
printf(")"); |
} |
printf("\n"); |
//branches/rcu/kernel/generic/src/mm/as.c |
---|
57,6 → 57,7 |
#include <genarch/mm/page_ht.h> |
#include <mm/asid.h> |
#include <arch/mm/asid.h> |
#include <preemption.h> |
#include <synch/spinlock.h> |
#include <synch/mutex.h> |
#include <adt/list.h> |
181,7 → 182,7 |
else |
as->asid = ASID_INVALID; |
as->refcount = 0; |
atomic_set(&as->refcount, 0); |
as->cpu_refcount = 0; |
#ifdef AS_PAGE_TABLE |
as->genarch.page_table = page_table_create(flags); |
196,13 → 197,16 |
* |
* When there are no tasks referencing this address space (i.e. its refcount is |
* zero), the address space can be destroyed. |
* |
* We know that we don't hold any spinlock. |
*/ |
void as_destroy(as_t *as) |
{ |
ipl_t ipl; |
bool cond; |
DEADLOCK_PROBE_INIT(p_asidlock); |
ASSERT(as->refcount == 0); |
ASSERT(atomic_get(&as->refcount) == 0); |
/* |
* Since there is no reference to this area, |
209,8 → 213,23 |
* it is safe not to lock its mutex. |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&asidlock); |
/* |
* We need to avoid deadlock between TLB shootdown and asidlock. |
* We therefore try to take asid conditionally and if we don't succeed, |
* we enable interrupts and try again. This is done while preemption is |
* disabled to prevent nested context switches. We also depend on the |
* fact that so far no spinlocks are held. |
*/ |
preemption_disable(); |
ipl = interrupts_read(); |
retry: |
interrupts_disable(); |
if (!spinlock_trylock(&asidlock)) { |
interrupts_enable(); |
DEADLOCK_PROBE(p_asidlock, DEADLOCK_THRESHOLD); |
goto retry; |
} |
preemption_enable(); /* Interrupts disabled, enable preemption */ |
if (as->asid != ASID_INVALID && as != AS_KERNEL) { |
if (as != AS && as->cpu_refcount == 0) |
list_remove(&as->inactive_as_with_asid_link); |
472,15 → 491,16 |
/* |
* Finish TLB shootdown sequence. |
*/ |
tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE, |
area->pages - pages); |
tlb_shootdown_finalize(); |
/* |
* Invalidate software translation caches (e.g. TSB on sparc64). |
*/ |
as_invalidate_translation_cache(as, area->base + |
pages * PAGE_SIZE, area->pages - pages); |
tlb_shootdown_finalize(); |
} else { |
/* |
* Growing the area. |
568,14 → 588,14 |
/* |
* Finish TLB shootdown sequence. |
*/ |
tlb_invalidate_pages(as->asid, area->base, area->pages); |
tlb_shootdown_finalize(); |
/* |
* Invalidate potential software translation caches (e.g. TSB on |
* sparc64). |
*/ |
as_invalidate_translation_cache(as, area->base, area->pages); |
tlb_shootdown_finalize(); |
btree_destroy(&area->used_space); |
867,12 → 887,29 |
* scheduling. Sleeping here would lead to deadlock on wakeup. Another |
* thing which is forbidden in this context is locking the address space. |
* |
* When this function is enetered, no spinlocks may be held. |
* |
* @param old Old address space or NULL. |
* @param new New address space. |
*/ |
void as_switch(as_t *old_as, as_t *new_as) |
{ |
spinlock_lock(&asidlock); |
DEADLOCK_PROBE_INIT(p_asidlock); |
preemption_disable(); |
retry: |
(void) interrupts_disable(); |
if (!spinlock_trylock(&asidlock)) { |
/* |
* Avoid deadlock with TLB shootdown. |
* We can enable interrupts here because |
* preemption is disabled. We should not be |
* holding any other lock. |
*/ |
(void) interrupts_enable(); |
DEADLOCK_PROBE(p_asidlock, DEADLOCK_THRESHOLD); |
goto retry; |
} |
preemption_enable(); |
/* |
* First, take care of the old address space. |
//branches/rcu/kernel/generic/src/mm/page.c |
---|
76,7 → 76,7 |
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_mapping_insert(AS_KERNEL, s + i * PAGE_SIZE, s + i * PAGE_SIZE, PAGE_NOT_CACHEABLE | PAGE_WRITE); |
} |
//branches/rcu/kernel/generic/src/syscall/syscall.c |
---|
100,7 → 100,7 |
if (id < SYSCALL_END) |
rc = syscall_table[id](a1, a2, a3, a4); |
else { |
klog_printf("TASK %lld: Unknown syscall id %d",TASK->taskid,id); |
klog_printf("TASK %llu: Unknown syscall id %d",TASK->taskid,id); |
task_kill(TASK->taskid); |
thread_exit(); |
} |
118,6 → 118,7 |
/* Thread and task related syscalls. */ |
(syshandler_t) sys_thread_create, |
(syshandler_t) sys_thread_exit, |
(syshandler_t) sys_thread_get_id, |
(syshandler_t) sys_task_get_id, |
/* Synchronization related syscalls. */ |
//branches/rcu/kernel/generic/src/ipc/ipc.c |
---|
374,6 → 374,7 |
int i; |
call_t *call; |
phone_t *phone; |
DEADLOCK_PROBE_INIT(p_phonelck); |
/* Disconnect all our phones ('ipc_phone_hangup') */ |
for (i=0;i < IPC_MAX_PHONES; i++) |
387,9 → 388,10 |
spinlock_lock(&TASK->answerbox.lock); |
while (!list_empty(&TASK->answerbox.connected_phones)) { |
phone = list_get_instance(TASK->answerbox.connected_phones.next, |
phone_t, link); |
phone_t, link); |
if (! spinlock_trylock(&phone->lock)) { |
spinlock_unlock(&TASK->answerbox.lock); |
DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); |
goto restart_phones; |
} |
500,7 → 502,7 |
printf("ABOX - CALLS:\n"); |
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:%lld M:%d A1:%d A2:%d A3:%d Flags:%x\n",call, |
printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d 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), call->flags); |
} |
510,7 → 512,7 |
tmp != &task->answerbox.dispatched_calls; |
tmp = tmp->next) { |
call = list_get_instance(tmp, call_t, link); |
printf("Callid: %p Srctask:%lld M:%d A1:%d A2:%d A3:%d Flags:%x\n",call, |
printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d 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), call->flags); |
} |
//branches/rcu/kernel/generic/src/ipc/irq.c |
---|
336,6 → 336,7 |
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)) { |
344,6 → 345,7 |
*/ |
spinlock_unlock(&box->irq_lock); |
interrupts_restore(ipl); |
DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD); |
goto loop; |
} |
//branches/rcu/kernel/Makefile |
---|
156,6 → 156,7 |
generic/src/main/kinit.c \ |
generic/src/main/uinit.c \ |
generic/src/main/version.c \ |
generic/src/main/shutdown.c \ |
generic/src/proc/scheduler.c \ |
generic/src/proc/thread.c \ |
generic/src/proc/task.c \ |
227,6 → 228,7 |
test/mm/slab1.c \ |
test/mm/slab2.c \ |
test/mm/purge1.c \ |
test/synch/rcu1.c \ |
test/synch/rwlock1.c \ |
test/synch/rwlock2.c \ |
test/synch/rwlock3.c \ |
235,9 → 237,9 |
test/synch/semaphore1.c \ |
test/synch/semaphore2.c \ |
test/print/print1.c \ |
test/tasklet/tasklet1.c \ |
test/thread/thread1.c \ |
test/sysinfo/sysinfo1.c \ |
test/tasklet/tasklet1.c |
test/sysinfo/sysinfo1.c |
endif |
## Experimental features |
//branches/rcu/kernel/arch/sparc64/include/types.h |
---|
62,6 → 62,7 |
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; |
//branches/rcu/kernel/arch/sparc64/include/trap/mmu.h |
---|
129,7 → 129,21 |
wrpr %g0, 1, %tl |
.endif |
/* |
* Switch from the MM globals. |
*/ |
wrpr %g0, PSTATE_PRIV_BIT | PSTATE_AG_BIT, %pstate |
/* |
* Read the Tag Access register for the higher-level handler. |
* This is necessary to survive nested DTLB misses. |
*/ |
mov VA_DMMU_TAG_ACCESS, %g2 |
ldxa [%g2] ASI_DMMU, %g2 |
/* |
* g2 will be passed as an argument to fast_data_access_mmu_miss(). |
*/ |
PREEMPTIBLE_HANDLER fast_data_access_mmu_miss |
.endm |
142,7 → 156,21 |
wrpr %g0, 1, %tl |
.endif |
/* |
* Switch from the MM globals. |
*/ |
wrpr %g0, PSTATE_PRIV_BIT | PSTATE_AG_BIT, %pstate |
/* |
* Read the Tag Access register for the higher-level handler. |
* This is necessary to survive nested DTLB misses. |
*/ |
mov VA_DMMU_TAG_ACCESS, %g2 |
ldxa [%g2] ASI_DMMU, %g2 |
/* |
* g2 will be passed as an argument to fast_data_access_mmu_miss(). |
*/ |
PREEMPTIBLE_HANDLER fast_data_access_protection |
.endm |
//branches/rcu/kernel/arch/sparc64/include/mm/tlb.h |
---|
428,9 → 428,9 |
membar(); |
} |
extern void fast_instruction_access_mmu_miss(int n, istate_t *istate); |
extern void fast_data_access_mmu_miss(int n, istate_t *istate); |
extern void fast_data_access_protection(int n, istate_t *istate); |
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 dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, bool locked, bool cacheable); |
//branches/rcu/kernel/arch/sparc64/include/barrier.h |
---|
39,12 → 39,12 |
* Our critical section barriers are prepared for the weakest RMO memory model. |
*/ |
#define CS_ENTER_BARRIER() \ |
asm volatile ( \ |
asm volatile ( \ |
"membar #LoadLoad | #LoadStore\n" \ |
::: "memory" \ |
) |
#define CS_LEAVE_BARRIER() \ |
asm volatile ( \ |
asm volatile ( \ |
"membar #StoreStore\n" \ |
"membar #LoadStore\n" \ |
::: "memory" \ |
//branches/rcu/kernel/arch/sparc64/src/smp/smp.c |
---|
100,7 → 100,7 |
if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT) |
printf("%s: waiting for processor (mid = %d) timed out\n", |
__FUNCTION__, mid); |
__FUNCTION__, mid); |
} |
} |
//branches/rcu/kernel/arch/sparc64/src/smp/ipi.c |
---|
74,8 → 74,8 |
panic("Interrupt Dispatch Status busy bit set\n"); |
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_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, |
//branches/rcu/kernel/arch/sparc64/src/asm.S |
---|
273,7 → 273,7 |
flushw |
wrpr %g0, 0, %cleanwin ! avoid information leak |
mov %i3, %o0 ! uarg |
mov %i2, %o0 ! uarg |
clr %i2 |
clr %i3 |
//branches/rcu/kernel/arch/sparc64/src/proc/scheduler.c |
---|
62,9 → 62,8 |
* - preemptible trap handler switches to alternate globals |
* before it explicitly uses %g7. |
*/ |
uint64_t sp = (uintptr_t) THREAD->kstack + STACK_SIZE |
- (STACK_BIAS + ALIGN_UP(STACK_ITEM_SIZE, |
STACK_ALIGNMENT)); |
uint64_t sp = (uintptr_t) THREAD->kstack + STACK_SIZE - |
(STACK_BIAS + ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT)); |
write_to_ig_g6(sp); |
write_to_ag_g6(sp); |
write_to_ag_g7((uintptr_t) THREAD->arch.uspace_window_buffer); |
//branches/rcu/kernel/arch/sparc64/src/proc/thread.c |
---|
55,7 → 55,7 |
* belonging to a killed thread. |
*/ |
frame_free(KA2PA(ALIGN_DOWN((uintptr_t) |
t->arch.uspace_window_buffer, PAGE_SIZE))); |
t->arch.uspace_window_buffer, PAGE_SIZE))); |
} |
} |
75,8 → 75,8 |
* Mind the possible alignment of the userspace window buffer |
* belonging to a killed thread. |
*/ |
t->arch.uspace_window_buffer = (uint8_t *) ALIGN_DOWN(uw_buf, |
PAGE_SIZE); |
t->arch.uspace_window_buffer = (uint8_t *) ALIGN_DOWN(uw_buf, |
PAGE_SIZE); |
} |
} |
//branches/rcu/kernel/arch/sparc64/src/sparc64.c |
---|
155,5 → 155,11 |
/* not reached */ |
} |
void arch_reboot(void) |
{ |
// TODO |
while (1); |
} |
/** @} |
*/ |
//branches/rcu/kernel/arch/sparc64/src/cpu/cpu.c |
---|
63,10 → 63,10 |
mid = *((uint32_t *) prop->value); |
if (mid == CPU->arch.mid) { |
prop = ofw_tree_getprop(node, |
"clock-frequency"); |
"clock-frequency"); |
if (prop && prop->value) |
clock_frequency = *((uint32_t *) |
prop->value); |
prop->value); |
} |
} |
node = ofw_tree_find_peer_by_device_type(node, "cpu"); |
//branches/rcu/kernel/arch/sparc64/src/mm/tlb.c |
---|
198,7 → 198,7 |
} |
/** ITLB miss handler. */ |
void fast_instruction_access_mmu_miss(int n, istate_t *istate) |
void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate) |
{ |
uintptr_t va = ALIGN_DOWN(istate->tpc, PAGE_SIZE); |
index_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE; |
234,15 → 234,18 |
* |
* 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. |
*/ |
void fast_data_access_mmu_miss(int n, istate_t *istate) |
void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate) |
{ |
tlb_tag_access_reg_t tag; |
uintptr_t va; |
index_t index; |
pte_t *t; |
tag.value = dtlb_tag_access_read(); |
va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
index = tag.vpn % MMU_PAGES_PER_PAGE; |
282,15 → 285,19 |
} |
} |
/** DTLB protection fault handler. */ |
void fast_data_access_protection(int n, istate_t *istate) |
/** 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. |
*/ |
void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate) |
{ |
tlb_tag_access_reg_t tag; |
uintptr_t va; |
index_t index; |
pte_t *t; |
tag.value = dtlb_tag_access_read(); |
va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
index = tag.vpn % MMU_PAGES_PER_PAGE; /* 16K-page emulation */ |
371,9 → 378,10 |
uintptr_t va; |
va = tag.vpn << MMU_PAGE_WIDTH; |
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va, |
tag.context); |
if (tag.context) { |
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va, |
tag.context); |
} |
dump_istate(istate); |
printf("Faulting page: %p, ASID=%d\n", va, tag.context); |
panic("%s\n", str); |
386,8 → 394,10 |
va = tag.vpn << MMU_PAGE_WIDTH; |
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va, |
tag.context); |
if (tag.context) { |
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va, |
tag.context); |
} |
printf("Faulting page: %p, ASID=%d\n", va, tag.context); |
dump_istate(istate); |
panic("%s\n", str); |
//branches/rcu/kernel/arch/sparc64/src/mm/as.c |
---|
66,6 → 66,7 |
*/ |
int order = fnzb32(((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * |
sizeof(tsb_entry_t)) >> FRAME_WIDTH); |
uintptr_t tsb = (uintptr_t) frame_alloc(order, flags | FRAME_KA); |
if (!tsb) |
74,6 → 75,7 |
as->arch.itsb = (tsb_entry_t *) tsb; |
as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT * |
sizeof(tsb_entry_t)); |
memsetb((uintptr_t) as->arch.itsb, |
(ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0); |
#endif |
//branches/rcu/kernel/arch/sparc64/src/mm/cache.S |
---|
45,8 → 45,10 |
subcc %g1, DCACHE_LINE_SIZE, %g1 |
bnz,pt %xcc, 0b |
stxa %g0, [%g1] ASI_DCACHE_TAG |
membar #Sync |
retl |
membar #Sync |
! beware SF Erratum #51, do not put the MEMBAR here |
nop |
/** Flush only D-cache lines of one virtual color. |
* |
//branches/rcu/kernel/arch/sparc64/src/mm/tsb.c |
---|
61,6 → 61,8 |
ASSERT(as->arch.itsb && as->arch.dtsb); |
i0 = (page >> MMU_PAGE_WIDTH) & TSB_INDEX_MASK; |
ASSERT(i0 < ITSB_ENTRY_COUNT && i0 < DTSB_ENTRY_COUNT); |
if (pages == (count_t) -1 || (pages * 2) > ITSB_ENTRY_COUNT) |
cnt = ITSB_ENTRY_COUNT; |
else |
84,9 → 86,12 |
as_t *as; |
tsb_entry_t *tsb; |
index_t entry; |
ASSERT(index <= 1); |
as = t->as; |
entry = ((t->page >> MMU_PAGE_WIDTH) + index) & TSB_INDEX_MASK; |
ASSERT(entry < ITSB_ENTRY_COUNT); |
tsb = &as->arch.itsb[entry]; |
/* |
102,8 → 107,8 |
write_barrier(); |
tsb->tag.context = as->asid; |
tsb->tag.va_tag = (t->page + (index << MMU_PAGE_WIDTH)) >> |
VA_TAG_PAGE_SHIFT; |
/* the shift is bigger than PAGE_WIDTH, do not bother with index */ |
tsb->tag.va_tag = t->page >> VA_TAG_PAGE_SHIFT; |
tsb->data.value = 0; |
tsb->data.size = PAGESIZE_8K; |
tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index; |
128,8 → 133,11 |
tsb_entry_t *tsb; |
index_t entry; |
ASSERT(index <= 1); |
as = t->as; |
entry = ((t->page >> MMU_PAGE_WIDTH) + index) & TSB_INDEX_MASK; |
ASSERT(entry < DTSB_ENTRY_COUNT); |
tsb = &as->arch.dtsb[entry]; |
/* |
145,8 → 153,8 |
write_barrier(); |
tsb->tag.context = as->asid; |
tsb->tag.va_tag = (t->page + (index << MMU_PAGE_WIDTH)) >> |
VA_TAG_PAGE_SHIFT; |
/* the shift is bigger than PAGE_WIDTH, do not bother with index */ |
tsb->tag.va_tag = t->page >> VA_TAG_PAGE_SHIFT; |
tsb->data.value = 0; |
tsb->data.size = PAGESIZE_8K; |
tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index; |
//branches/rcu/kernel/arch/sparc64/src/mm/frame.c |
---|
65,10 → 65,10 |
if (confdata == ADDR2PFN(KA2PA(PFN2ADDR(0)))) |
confdata = ADDR2PFN(KA2PA(PFN2ADDR(2))); |
zone_create(ADDR2PFN(start), |
SIZE2FRAMES(ALIGN_DOWN(size, FRAME_SIZE)), |
confdata, 0); |
SIZE2FRAMES(ALIGN_DOWN(size, FRAME_SIZE)), |
confdata, 0); |
last_frame = max(last_frame, start + ALIGN_UP(size, |
FRAME_SIZE)); |
FRAME_SIZE)); |
} |
/* |
//branches/rcu/kernel/arch/ia64/include/types.h |
---|
70,6 → 70,7 |
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; |
//branches/rcu/kernel/arch/ia64/src/ia64.c |
---|
176,5 → 176,11 |
#endif |
} |
void arch_reboot(void) |
{ |
// TODO |
while (1); |
} |
/** @} |
*/ |
//branches/rcu/kernel/arch/arm32/include/types.h |
---|
62,6 → 62,7 |
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; |
//branches/rcu/kernel/arch/arm32/src/arm32.c |
---|
82,5 → 82,11 |
/* TODO */ |
} |
void arch_reboot(void) |
{ |
// TODO |
while (1); |
} |
/** @} |
*/ |
//branches/rcu/kernel/arch/ppc32/include/types.h |
---|
62,6 → 62,7 |
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; |
//branches/rcu/kernel/arch/ppc32/src/mm/page.c |
---|
53,7 → 53,7 |
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_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/rcu/kernel/arch/ppc32/src/interrupt.c |
---|
60,11 → 60,19 |
int inum; |
while ((inum = pic_get_pending()) != -1) { |
bool ack = false; |
irq_t *irq = irq_dispatch_and_lock(inum); |
if (irq) { |
/* |
* The IRQ handler was found. |
*/ |
if (irq->preack) { |
/* Acknowledge the interrupt before processing */ |
pic_ack_interrupt(inum); |
ack = true; |
} |
irq->handler(irq, irq->arg); |
spinlock_unlock(&irq->lock); |
} else { |
75,7 → 83,9 |
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum); |
#endif |
} |
pic_ack_interrupt(inum); |
if (!ack) |
pic_ack_interrupt(inum); |
} |
} |
//branches/rcu/kernel/arch/ppc32/src/drivers/cuda.c |
---|
48,7 → 48,8 |
#define PACKET_ADB 0x00 |
#define PACKET_CUDA 0x01 |
#define CUDA_POWERDOWN 0x0a |
#define CUDA_POWERDOWN 0x0a |
#define CUDA_RESET 0x11 |
#define RS 0x200 |
#define B (0 * RS) |
191,9 → 192,6 |
}; |
void send_packet(const uint8_t kind, index_t count, ...); |
static void receive_packet(uint8_t *kind, index_t count, uint8_t data[]) |
{ |
cuda[B] = cuda[B] & ~TIP; |
316,7 → 314,7 |
} |
void send_packet(const uint8_t kind, index_t count, ...) |
static void send_packet(const uint8_t kind, count_t count, ...) |
{ |
index_t i; |
va_list va; |
341,13 → 339,17 |
void cpu_halt(void) { |
#ifdef CONFIG_POWEROFF |
send_packet(PACKET_CUDA, 1, CUDA_POWERDOWN); |
#endif |
asm volatile ( |
"b 0\n" |
); |
} |
void arch_reboot(void) { |
send_packet(PACKET_CUDA, 1, CUDA_RESET); |
asm volatile ( |
"b 0\n" |
); |
} |
/** @} |
*/ |
//branches/rcu/kernel/arch/ia32xen/include/types.h |
---|
62,6 → 62,7 |
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; |
//branches/rcu/kernel/arch/ia32xen/src/ia32xen.c |
---|
211,5 → 211,11 |
{ |
} |
void arch_reboot(void) |
{ |
// TODO |
while (1); |
} |
/** @} |
*/ |
//branches/rcu/kernel/arch/ia32xen/src/smp/smp.c |
---|
80,13 → 80,13 |
if (config.cpu_count > 1) { |
page_mapping_insert(AS_KERNEL, l_apic_address, (uintptr_t) l_apic, |
PAGE_NOT_CACHEABLE); |
PAGE_NOT_CACHEABLE | PAGE_WRITE); |
page_mapping_insert(AS_KERNEL, io_apic_address, (uintptr_t) io_apic, |
PAGE_NOT_CACHEABLE); |
PAGE_NOT_CACHEABLE | PAGE_WRITE); |
l_apic = (uint32_t *) l_apic_address; |
io_apic = (uint32_t *) io_apic_address; |
} |
} |
} |
/* |
//branches/rcu/kernel/arch/ia32xen/src/interrupt.c |
---|
176,14 → 176,21 |
ASSERT(n >= IVT_IRQBASE); |
int inum = n - IVT_IRQBASE; |
bool ack = false; |
ASSERT(inum < IRQ_COUNT); |
ASSERT((inum != IRQ_PIC_SPUR) && (inum != IRQ_PIC1)); |
irq_t *irq = irq_dispatch_and_lock(inum); |
if (irq) { |
/* |
* The IRQ handler was found. |
*/ |
if (irq->preack) { |
/* Send EOI before processing the interrupt */ |
trap_virtual_eoi(); |
ack = true; |
} |
irq->handler(irq, irq->arg); |
spinlock_unlock(&irq->lock); |
} else { |
194,7 → 201,9 |
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum); |
#endif |
} |
trap_virtual_eoi(); |
if (!ack) |
trap_virtual_eoi(); |
} |
void interrupt_init(void) |
//branches/rcu/kernel/arch/amd64/include/types.h |
---|
62,6 → 62,7 |
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; |
//branches/rcu/kernel/arch/amd64/include/asm.h |
---|
55,10 → 55,17 |
return v; |
} |
static inline void cpu_sleep(void) { __asm__ volatile ("hlt\n"); }; |
static inline void cpu_halt(void) { __asm__ volatile ("hlt\n"); }; |
static inline void cpu_sleep(void) |
{ |
asm volatile ("hlt\n"); |
}; |
static inline void cpu_halt(void) |
{ |
asm volatile ("hlt\n"); |
}; |
/** Byte from port |
* |
* Get byte from port |
//branches/rcu/kernel/arch/amd64/src/pm.c |
---|
33,6 → 33,7 |
/** @file |
*/ |
#include <arch.h> |
#include <arch/pm.h> |
#include <arch/asm.h> |
#include <mm/as.h> |
227,5 → 228,24 |
tr_load(gdtselector(TSS_DES)); |
} |
/* Reboot the machine by initiating |
* a triple fault |
*/ |
void arch_reboot(void) |
{ |
preemption_disable(); |
ipl_t ipl = interrupts_disable(); |
memsetb((uintptr_t) idt, sizeof(idt), 0); |
idtr_load(&idtr); |
interrupts_restore(ipl); |
asm volatile ( |
"int $0x03\n" |
"cli\n" |
"hlt\n" |
); |
} |
/** @} |
*/ |
//branches/rcu/kernel/arch/amd64/src/boot/vga323.pal |
---|
0,0 → 1,0 |
link ../../../ia32/src/boot/vga323.pal |
//branches/rcu/kernel/arch/amd64/src/boot/boot.S |
---|
72,8 → 72,26 |
movl %eax, grub_eax # save parameters from GRUB |
movl %ebx, grub_ebx |
# Protected 32-bit. We want to reuse the code-seg descriptor, |
# the Default operand size must not be 1 when entering long mode |
movl $0x80000000, %eax |
cpuid |
cmp $0x80000000, %eax # any function > 80000000h? |
jbe long_mode_unsupported |
movl $(AMD_CPUID_EXTENDED), %eax # Extended function code 80000001 |
cpuid |
bt $29, %edx # Test if long mode is supported. |
jc long_mode_supported |
long_mode_unsupported: |
movl $long_mode_msg, %esi |
jmp error_halt |
long_mode_supported: |
#ifdef CONFIG_FB |
mov $vesa_init, %esi; |
mov $vesa_init, %esi |
mov $VESA_INIT_SEGMENT << 4, %edi |
mov $e_vesa_init - vesa_init, %ecx |
cld |
92,25 → 110,7 |
shr $16, %ebx |
mov %bx, KA2PA(vesa_bpp) |
#endif |
# Protected 32-bit. We want to reuse the code-seg descriptor, |
# the Default operand size must not be 1 when entering long mode |
movl $0x80000000, %eax |
cpuid |
cmp $0x80000000, %eax # any function > 80000000h? |
jbe long_mode_unsupported |
movl $(AMD_CPUID_EXTENDED), %eax # Extended function code 80000001 |
cpuid |
bt $29, %edx # Test if long mode is supported. |
jc long_mode_supported |
long_mode_unsupported: |
cli |
hlt |
long_mode_supported: |
# Enable 64-bit page transaltion entries - CR4.PAE = 1. |
# Paging is not enabled until after long mode is enabled |
303,11 → 303,12 |
#define VESA_INFO_SIZE 1024 |
#define VESA_MODE_ATTRIBUTES_OFFSET 0 |
#define VESA_MODE_LIST_PTR_OFFSET 14 |
#define VESA_MODE_SCANLINE_OFFSET 16 |
#define VESA_MODE_WIDTH_OFFSET 18 |
#define VESA_MODE_HEIGHT_OFFSET 20 |
#define VESA_MODE_BPP_OFFSET 25 |
#define VESA_MODE_SCANLINE_OFFSET 16 |
#define VESA_MODE_PHADDR_OFFSET 40 |
#define VESA_END_OF_MODES 0xffff |
317,14 → 318,14 |
#define VESA_GET_INFO 0x4f00 |
#define VESA_GET_MODE_INFO 0x4f01 |
#define VESA_SET_MODE 0x4f02 |
#define VESA_SET_PALETTE 0x4f09 |
#define CONFIG_VESA_BPP_a 255 |
#if CONFIG_VESA_BPP == 24 |
#undef CONFIG_VESA_BPP_a |
#define CONFIG_VESA_BPP_a 32 |
#define CONFIG_VESA_BPP_VARIANT 32 |
#endif |
mov $VESA_GET_INFO, %ax |
mov $e_vesa_init - vesa_init, %di |
push %di |
339,7 → 340,7 |
mov VESA_MODE_LIST_PTR_OFFSET(%di), %si |
add $VESA_INFO_SIZE, %di |
1:# Try next mode |
mov %gs:(%si), %cx |
cmp $VESA_END_OF_MODES, %cx |
369,10 → 370,13 |
mov $CONFIG_VESA_BPP, %al |
cmp VESA_MODE_BPP_OFFSET(%di), %al |
#ifdef CONFIG_VESA_BPP_VARIANT |
jz 2f |
mov $CONFIG_VESA_BPP_a, %al |
mov $CONFIG_VESA_BPP_VARIANT, %al |
cmp VESA_MODE_BPP_OFFSET(%di), %al |
#endif |
jnz 1b |
2: |
386,7 → 390,60 |
pop %di |
cmp $VESA_OK, %al |
jnz 0f |
#if CONFIG_VESA_BPP == 8 |
# Set 3:2:3 VGA palette |
mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax |
push %di |
mov $vga323 - vesa_init, %di |
mov $0x100, %ecx |
bt $5, %ax # Test if VGA compatible registers are present |
jnc vga_compat |
# Try VESA routine to set palette |
mov $VESA_SET_PALETTE, %ax |
xor %bl, %bl |
xor %dx, %dx |
int $0x10 |
jmp vga_not_compat |
vga_compat: |
# Try VGA registers to set palette |
movw $0x3c6, %dx # Set palette mask |
movb $0xff, %al |
outb %al, %dx |
movw $0x3c8, %dx # First index to set |
xor %al, %al |
outb %al, %dx |
movw $0x3c9, %dx # Data port |
vga_loop: |
movb %es:2(%di), %al |
outb %al, %dx |
movb %es:1(%di), %al |
outb %al, %dx |
movb %es:(%di), %al |
outb %al, %dx |
addw $4, %di |
loop vga_loop |
vga_not_compat: |
pop %di |
#endif |
mov VESA_MODE_PHADDR_OFFSET(%di), %esi |
mov VESA_MODE_WIDTH_OFFSET(%di), %ax |
shl $16, %eax |
427,8 → 484,10 |
mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA |
xor %ax, %ax |
jz 8b # Force relative jump |
vga323: |
#include "vga323.pal" |
.code32 |
vesa_init_protect: |
movw $gdtselector(KDATA_DES), %cx |
441,11 → 500,73 |
movw %cx, %fs |
movw %cx, %gs |
movl $START_STACK, %esp # initialize stack pointer |
jmpl $gdtselector(KTEXT32_DES), $vesa_meeting_point |
.align 4 |
e_vesa_init: |
#endif |
#endif |
# Print string from %esi to EGA display (in red) and halt |
error_halt: |
movl $0xb8000, %edi # base of EGA text mode memory |
xorl %eax, %eax |
movw $0x3d4, %dx # read bits 8 - 15 of the cursor address |
movb $0xe, %al |
outb %al, %dx |
movw $0x3d5, %dx |
inb %dx, %al |
shl $8, %ax |
movw $0x3d4, %dx # read bits 0 - 7 of the cursor address |
movb $0xf, %al |
outb %al, %dx |
movw $0x3d5, %dx |
inb %dx, %al |
cmp $1920, %ax |
jbe cursor_ok |
movw $1920, %ax # sanity check for the cursor on the last line |
cursor_ok: |
movw %ax, %bx |
shl $1, %eax |
addl %eax, %edi |
movw $0x0c00, %ax # black background, light red foreground |
cld |
ploop: |
lodsb |
cmp $0, %al |
je ploop_end |
stosw |
inc %bx |
jmp ploop |
ploop_end: |
movw $0x3d4, %dx # write bits 8 - 15 of the cursor address |
movb $0xe, %al |
outb %al, %dx |
movw $0x3d5, %dx |
movb %bh, %al |
outb %al, %dx |
movw $0x3d4, %dx # write bits 0 - 7 of the cursor address |
movb $0xf, %al |
outb %al, %dx |
movw $0x3d5, %dx |
movb %bl, %al |
outb %al, %dx |
cli |
hlt |
.section K_DATA_START, "aw", @progbits |
.align 4096 |
513,3 → 634,6 |
grub_ebx: |
.long 0 |
long_mode_msg: |
.asciz "64 bit long mode not supported. System halted." |
//branches/rcu/kernel/arch/amd64/src/mm/page.c |
---|
83,7 → 83,7 |
{ |
uintptr_t cur; |
int i; |
int identity_flags = PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL; |
int identity_flags = PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL | PAGE_WRITE; |
if (config.cpu_active == 1) { |
page_mapping_operations = &pt_mapping_operations; |
112,10 → 112,8 |
exc_register(14, "page_fault", (iroutine) page_fault); |
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table); |
} |
else { |
} else |
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table); |
} |
} |
208,7 → 206,7 |
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_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/rcu/kernel/arch/amd64/src/interrupt.c |
---|
156,14 → 156,21 |
ASSERT(n >= IVT_IRQBASE); |
int inum = n - IVT_IRQBASE; |
bool ack = false; |
ASSERT(inum < IRQ_COUNT); |
ASSERT((inum != IRQ_PIC_SPUR) && (inum != IRQ_PIC1)); |
irq_t *irq = irq_dispatch_and_lock(inum); |
if (irq) { |
/* |
* The IRQ handler was found. |
*/ |
if (irq->preack) { |
/* Send EOI before processing the interrupt */ |
trap_virtual_eoi(); |
ack = true; |
} |
irq->handler(irq, irq->arg); |
spinlock_unlock(&irq->lock); |
} else { |
174,7 → 181,9 |
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum); |
#endif |
} |
trap_virtual_eoi(); |
if (!ack) |
trap_virtual_eoi(); |
} |
void interrupt_init(void) |
//branches/rcu/kernel/arch/ppc64/include/types.h |
---|
62,6 → 62,7 |
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; |
//branches/rcu/kernel/arch/ppc64/src/mm/page.c |
---|
264,10 → 264,8 |
uintptr_t cur; |
int flags; |
/* Frames below 128 MB are mapped using BAT, |
map rest of the physical memory */ |
for (cur = 128 << 20; cur < last_frame; cur += FRAME_SIZE) { |
flags = PAGE_CACHEABLE; |
flags = PAGE_CACHEABLE | PAGE_WRITE; |
if ((PA2KA(cur) >= config.base) && (PA2KA(cur) < config.base + config.kernel_size)) |
flags |= PAGE_GLOBAL; |
page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags); |
296,7 → 294,7 |
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_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/rcu/kernel/arch/ppc64/src/interrupt.c |
---|
60,11 → 60,19 |
int inum; |
while ((inum = pic_get_pending()) != -1) { |
bool ack = false; |
irq_t *irq = irq_dispatch_and_lock(inum); |
if (irq) { |
/* |
* The IRQ handler was found. |
*/ |
if (irq->preack) { |
/* Acknowledge the interrupt before processing */ |
pic_ack_interrupt(inum); |
ack = true; |
} |
irq->handler(irq, irq->arg); |
spinlock_unlock(&irq->lock); |
} else { |
75,7 → 83,9 |
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum); |
#endif |
} |
pic_ack_interrupt(inum); |
if (!ack) |
pic_ack_interrupt(inum); |
} |
} |
//branches/rcu/kernel/arch/ppc64/src/ppc64.c |
---|
128,6 → 128,7 |
void arch_grab_console(void) |
{ |
} |
/** Return console to userspace |
* |
*/ |
135,5 → 136,11 |
{ |
} |
void arch_reboot(void) |
{ |
// TODO |
while (1); |
} |
/** @} |
*/ |
//branches/rcu/kernel/arch/mips32/_link.ld.in |
---|
10,7 → 10,7 |
OUTPUT_ARCH(mips) |
ENTRY(kernel_image_start) |
ENTRY(kernel_image_start) |
SECTIONS { |
. = KERNEL_LOAD_ADDRESS; |
31,9 → 31,10 |
*(.rodata*); |
*(.sdata); |
*(.reginfo); |
/* Unfortunately IRIX does not allow us |
* to include this as a last section :-( |
* BSS/SBSS addresses will be wrong */ |
*(.sbss); |
*(.scommon); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
symbol_table = .; |
*(symtab.*); |
} |
40,14 → 41,6 |
_gp = . + 0x8000; |
.lit8 : { *(.lit8) } |
.lit4 : { *(.lit4) } |
.sbss : { |
*(.sbss); |
*(.scommon); |
} |
.bss : { |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
} |
kdata_end = .; |
//branches/rcu/kernel/arch/mips32/include/types.h |
---|
62,6 → 62,7 |
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; |
//branches/rcu/kernel/arch/mips32/src/mips32.c |
---|
178,5 → 178,11 |
return 0; |
} |
void arch_reboot(void) |
{ |
___halt(); |
while (1); |
} |
/** @} |
*/ |
//branches/rcu/kernel/arch/ia32/include/types.h |
---|
62,6 → 62,7 |
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; |
//branches/rcu/kernel/arch/ia32/include/asm.h |
---|
59,12 → 59,12 |
*/ |
static inline void cpu_halt(void) |
{ |
asm("hlt\n"); |
asm volatile ("hlt\n"); |
}; |
static inline void cpu_sleep(void) |
{ |
asm("hlt\n"); |
asm volatile ("hlt\n"); |
}; |
#define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \ |
//branches/rcu/kernel/arch/ia32/src/pm.c |
---|
121,7 → 121,7 |
void idt_init(void) |
{ |
idescriptor_t *d; |
int i; |
unsigned int i; |
for (i = 0; i < IDT_ITEMS; i++) { |
d = &idt[i]; |
230,5 → 230,28 |
gdtr_load(&cpugdtr); |
} |
/* Reboot the machine by initiating |
* a triple fault |
*/ |
void arch_reboot(void) |
{ |
preemption_disable(); |
ipl_t ipl = interrupts_disable(); |
memsetb((uintptr_t) idt, sizeof(idt), 0); |
ptr_16_32_t idtr; |
idtr.limit = sizeof(idt); |
idtr.base = (uintptr_t) idt; |
idtr_load(&idtr); |
interrupts_restore(ipl); |
asm volatile ( |
"int $0x03\n" |
"cli\n" |
"hlt\n" |
); |
} |
/** @} |
*/ |
//branches/rcu/kernel/arch/ia32/src/smp/smp.c |
---|
82,13 → 82,13 |
if (config.cpu_count > 1) { |
page_mapping_insert(AS_KERNEL, l_apic_address, (uintptr_t) l_apic, |
PAGE_NOT_CACHEABLE); |
PAGE_NOT_CACHEABLE | PAGE_WRITE); |
page_mapping_insert(AS_KERNEL, io_apic_address, (uintptr_t) io_apic, |
PAGE_NOT_CACHEABLE); |
PAGE_NOT_CACHEABLE | PAGE_WRITE); |
l_apic = (uint32_t *) l_apic_address; |
io_apic = (uint32_t *) io_apic_address; |
} |
} |
} |
/* |
//branches/rcu/kernel/arch/ia32/src/smp/apic.c |
---|
139,7 → 139,14 |
static void l_apic_timer_irq_handler(irq_t *irq, void *arg, ...) |
{ |
/* |
* Holding a spinlock could prevent clock() from preempting |
* the current thread. In this case, we don't need to hold the |
* irq->lock so we just unlock it and then lock it again. |
*/ |
spinlock_unlock(&irq->lock); |
clock(); |
spinlock_lock(&irq->lock); |
} |
/** Initialize APIC on BSP. */ |
162,6 → 169,7 |
io_apic_disable_irqs(0xffff); |
irq_initialize(&l_apic_timer_irq); |
l_apic_timer_irq.preack = true; |
l_apic_timer_irq.devno = device_assign_devno(); |
l_apic_timer_irq.inr = IRQ_CLK; |
l_apic_timer_irq.claim = l_apic_timer_claim; |
//branches/rcu/kernel/arch/ia32/src/boot/vga323.pal |
---|
0,0 → 1,256 |
.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/rcu/kernel/arch/ia32/src/boot/boot.S |
---|
63,9 → 63,24 |
jmpl $selector(KTEXT_DES), $multiboot_meeting_point |
multiboot_meeting_point: |
pushl %ebx # save parameters from GRUB |
pushl %eax |
movl %eax, grub_eax # save parameters from GRUB |
movl %ebx, grub_ebx |
xorl %eax, %eax |
cpuid |
cmp $0x0, %eax # any function > 0? |
jbe pse_unsupported |
movl $0x1, %eax # Basic function code 1 |
cpuid |
bt $3, %edx # Test if PSE is supported |
jc pse_supported |
pse_unsupported: |
movl $pse_msg, %esi |
jmp error_halt |
pse_supported: |
#ifdef CONFIG_FB |
mov $vesa_init, %esi |
mov $VESA_INIT_SEGMENT << 4, %edi |
89,8 → 104,8 |
call map_kernel # map kernel and turn paging on |
popl %eax |
popl %ebx |
movl grub_eax, %eax |
movl grub_ebx, %ebx |
cmpl $MULTIBOOT_LOADER_MAGIC, %eax # compare GRUB signature |
je valid_boot |
209,7 → 224,7 |
rep movsb |
#endif |
call main_bsp # never returns |
cli |
222,19 → 237,20 |
# For simplicity, we map the entire 4G space. |
# |
movl %cr4, %ecx |
orl $(1<<4), %ecx |
movl %ecx, %cr4 # turn PSE on |
orl $(1 << 4), %ecx # turn PSE on |
andl $(~(1 << 5)), %ecx # turn PAE off |
movl %ecx, %cr4 |
movl $(page_directory+0), %esi |
movl $(page_directory+2048), %edi |
movl $(page_directory + 0), %esi |
movl $(page_directory + 2048), %edi |
xorl %ecx, %ecx |
xorl %ebx, %ebx |
0: |
movl $((1<<7)|(1<<0)), %eax |
movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax |
orl %ebx, %eax |
movl %eax, (%esi,%ecx,4) # mapping 0x00000000+%ecx*4M => 0x00000000+%ecx*4M |
movl %eax, (%edi,%ecx,4) # mapping 0x80000000+%ecx*4M => 0x00000000+%ecx*4M |
addl $(4*1024*1024), %ebx |
movl %eax, (%esi, %ecx, 4) # mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M |
movl %eax, (%edi, %ecx, 4) # mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M |
addl $(4 * 1024 * 1024), %ebx |
incl %ecx |
cmpl $512, %ecx |
242,12 → 258,71 |
movl %esi, %cr3 |
# turn paging on |
movl %cr0, %ebx |
orl $(1<<31), %ebx |
orl $(1 << 31), %ebx # turn paging on |
movl %ebx, %cr0 |
ret |
# Print string from %esi to EGA display (in red) and halt |
error_halt: |
movl $0xb8000, %edi # base of EGA text mode memory |
xorl %eax, %eax |
movw $0x3d4, %dx # read bits 8 - 15 of the cursor address |
movb $0xe, %al |
outb %al, %dx |
movw $0x3d5, %dx |
inb %dx, %al |
shl $8, %ax |
movw $0x3d4, %dx # read bits 0 - 7 of the cursor address |
movb $0xf, %al |
outb %al, %dx |
movw $0x3d5, %dx |
inb %dx, %al |
cmp $1920, %ax |
jbe cursor_ok |
movw $1920, %ax # sanity check for the cursor on the last line |
cursor_ok: |
movw %ax, %bx |
shl $1, %eax |
addl %eax, %edi |
movw $0x0c00, %ax # black background, light red foreground |
cld |
ploop: |
lodsb |
cmp $0, %al |
je ploop_end |
stosw |
inc %bx |
jmp ploop |
ploop_end: |
movw $0x3d4, %dx # write bits 8 - 15 of the cursor address |
movb $0xe, %al |
outb %al, %dx |
movw $0x3d5, %dx |
movb %bh, %al |
outb %al, %dx |
movw $0x3d4, %dx # write bits 0 - 7 of the cursor address |
movb $0xf, %al |
outb %al, %dx |
movw $0x3d5, %dx |
movb %bl, %al |
outb %al, %dx |
cli |
hlt |
#ifdef CONFIG_FB |
vesa_init: |
jmp $selector(VESA_INIT_DES), $vesa_init_real - vesa_init |
278,11 → 353,12 |
#define VESA_INFO_SIZE 1024 |
#define VESA_MODE_ATTRIBUTES_OFFSET 0 |
#define VESA_MODE_LIST_PTR_OFFSET 14 |
#define VESA_MODE_SCANLINE_OFFSET 16 |
#define VESA_MODE_WIDTH_OFFSET 18 |
#define VESA_MODE_HEIGHT_OFFSET 20 |
#define VESA_MODE_BPP_OFFSET 25 |
#define VESA_MODE_SCANLINE_OFFSET 16 |
#define VESA_MODE_PHADDR_OFFSET 40 |
#define VESA_END_OF_MODES 0xffff |
292,12 → 368,10 |
#define VESA_GET_INFO 0x4f00 |
#define VESA_GET_MODE_INFO 0x4f01 |
#define VESA_SET_MODE 0x4f02 |
#define VESA_SET_PALETTE 0x4f09 |
#define CONFIG_VESA_BPP_a 255 |
#if CONFIG_VESA_BPP == 24 |
#undef CONFIG_VESA_BPP_a |
#define CONFIG_VESA_BPP_a 32 |
#define CONFIG_VESA_BPP_VARIANT 32 |
#endif |
mov $VESA_GET_INFO, %ax |
338,18 → 412,21 |
cmp VESA_MODE_WIDTH_OFFSET(%di), %ax |
jnz 1b |
mov $CONFIG_VESA_HEIGHT,%ax |
mov $CONFIG_VESA_HEIGHT, %ax |
cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax |
jnz 1b |
mov $CONFIG_VESA_BPP, %al |
cmp VESA_MODE_BPP_OFFSET(%di), %al |
#ifdef CONFIG_VESA_BPP_VARIANT |
jz 2f |
mov $CONFIG_VESA_BPP_a, %al |
mov $CONFIG_VESA_BPP_VARIANT, %al |
cmp VESA_MODE_BPP_OFFSET(%di), %al |
#endif |
jnz 1b |
2: |
mov %cx, %bx |
361,7 → 438,60 |
pop %di |
cmp $VESA_OK, %al |
jnz 0f |
#if CONFIG_VESA_BPP == 8 |
# Set 3:2:3 VGA palette |
mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax |
push %di |
mov $vga323 - vesa_init, %di |
mov $0x100, %ecx |
bt $5, %ax # Test if VGA compatible registers are present |
jnc vga_compat |
# Try VESA routine to set palette |
mov $VESA_SET_PALETTE, %ax |
xor %bl, %bl |
xor %dx, %dx |
int $0x10 |
jmp vga_not_compat |
vga_compat: |
# Try VGA registers to set palette |
movw $0x3c6, %dx # Set palette mask |
movb $0xff, %al |
outb %al, %dx |
movw $0x3c8, %dx # First index to set |
xor %al, %al |
outb %al, %dx |
movw $0x3c9, %dx # Data port |
vga_loop: |
movb %es:2(%di), %al |
outb %al, %dx |
movb %es:1(%di), %al |
outb %al, %dx |
movb %es:(%di), %al |
outb %al, %dx |
addw $4, %di |
loop vga_loop |
vga_not_compat: |
pop %di |
#endif |
mov VESA_MODE_PHADDR_OFFSET(%di), %esi |
mov VESA_MODE_WIDTH_OFFSET(%di), %ax |
shl $16, %eax |
402,12 → 532,12 |
mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA |
xor %ax, %ax |
jz 8b # Force relative jump |
vga323: |
#include "vga323.pal" |
.code32 |
vesa_init_protect: |
popl %esp |
movw $selector(KDATA_DES), %cx |
movw %cx, %es |
movw %cx, %fs |
415,6 → 545,8 |
movw %cx, %ds # kernel data + stack |
movw %cx, %ss |
movl $START_STACK, %esp # initialize stack pointer |
jmpl $selector(KTEXT_DES), $vesa_meeting_point |
.align 4 |
426,3 → 558,12 |
.align 4096 |
page_directory: |
.space 4096, 0 |
grub_eax: |
.long 0 |
grub_ebx: |
.long 0 |
pse_msg: |
.asciz "Page Size Extension not supported. System halted." |
//branches/rcu/kernel/arch/ia32/src/mm/page.c |
---|
61,7 → 61,7 |
* PA2KA(identity) mapping for all frames until last_frame. |
*/ |
for (cur = 0; cur < last_frame; cur += FRAME_SIZE) { |
flags = PAGE_CACHEABLE; |
flags = PAGE_CACHEABLE | PAGE_WRITE; |
if ((PA2KA(cur) >= config.base) && (PA2KA(cur) < config.base + config.kernel_size)) |
flags |= PAGE_GLOBAL; |
page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags); |
69,10 → 69,8 |
exc_register(14, "page_fault", (iroutine) page_fault); |
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table); |
} |
else { |
} else |
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table); |
} |
paging_on(); |
} |
86,7 → 84,7 |
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_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE); |
last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE); |
95,12 → 93,12 |
void page_fault(int n, istate_t *istate) |
{ |
uintptr_t page; |
uintptr_t page; |
pf_access_t access; |
page = read_cr2(); |
page = read_cr2(); |
if (istate->error_word & PFERR_CODE_RSVD) |
if (istate->error_word & PFERR_CODE_RSVD) |
panic("Reserved bit set in page directory.\n"); |
if (istate->error_word & PFERR_CODE_RW) |
107,14 → 105,14 |
access = PF_ACCESS_WRITE; |
else |
access = PF_ACCESS_READ; |
if (as_page_fault(page, access, istate) == AS_PF_FAULT) { |
if (as_page_fault(page, access, istate) == AS_PF_FAULT) { |
fault_if_from_uspace(istate, "Page fault: %#x", page); |
decode_istate(istate); |
printf("page fault address: %#x\n", page); |
panic("page fault\n"); |
} |
decode_istate(istate); |
printf("page fault address: %#x\n", page); |
panic("page fault\n"); |
} |
} |
/** @} |
//branches/rcu/kernel/arch/ia32/src/interrupt.c |
---|
176,14 → 176,21 |
ASSERT(n >= IVT_IRQBASE); |
int inum = n - IVT_IRQBASE; |
bool ack = false; |
ASSERT(inum < IRQ_COUNT); |
ASSERT((inum != IRQ_PIC_SPUR) && (inum != IRQ_PIC1)); |
irq_t *irq = irq_dispatch_and_lock(inum); |
if (irq) { |
/* |
* The IRQ handler was found. |
*/ |
if (irq->preack) { |
/* Send EOI before processing the interrupt */ |
trap_virtual_eoi(); |
ack = true; |
} |
irq->handler(irq, irq->arg); |
spinlock_unlock(&irq->lock); |
} else { |
194,7 → 201,9 |
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum); |
#endif |
} |
trap_virtual_eoi(); |
if (!ack) |
trap_virtual_eoi(); |
} |
void interrupt_init(void) |
//branches/rcu/kernel/arch/ia32/src/drivers/i8254.c |
---|
82,6 → 82,7 |
void i8254_init(void) |
{ |
irq_initialize(&i8254_irq); |
i8254_irq.preack = true; |
i8254_irq.devno = device_assign_devno(); |
i8254_irq.inr = IRQ_CLK; |
i8254_irq.claim = i8254_claim; |
//branches/rcu/uspace/fb/fb.c |
---|
833,23 → 833,27 |
copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap) |
{ |
int y; |
int rowsize; |
int tmp; |
int tmp, srcrowsize; |
int realwidth, realheight, realrowsize; |
int width = vport->width; |
int height = vport->height; |
if (width + vport->x > screen.xres) |
width = screen.xres - vport->x; |
if (height + vport->y > screen.yres) |
if (height + vport->y > screen.yres) |
height = screen.yres - vport->y; |
realwidth = pmap->width <= width ? pmap->width : width; |
realheight = pmap->height <= height ? pmap->height : height; |
rowsize = width * screen.pixelbytes; |
for (y = 0; y < height; y++) { |
srcrowsize = vport->width * screen.pixelbytes; |
realrowsize = realwidth * screen.pixelbytes; |
for (y = 0; y < realheight; y++) { |
tmp = (vport->y + y) * screen.scanline + |
vport->x * screen.pixelbytes; |
memcpy(pmap->data + rowsize * y, screen.fbaddress + tmp, |
rowsize); |
memcpy(pmap->data + srcrowsize * y, screen.fbaddress + tmp, |
realrowsize); |
} |
} |
//branches/rcu/uspace/kbd/generic/key_buffer.c |
---|
111,4 → 111,3 |
/** |
* @} |
*/ |
//branches/rcu/uspace/tester/tester.c |
---|
0,0 → 1,121 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* 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 tester User space Tester |
* @brief User space testing infrastructure. |
* @{ |
*/ |
/** |
* @file |
*/ |
#include <unistd.h> |
#include <stdio.h> |
#include "tester.h" |
int myservice = 0; |
int phones[MAX_PHONES]; |
int connections[MAX_CONNECTIONS]; |
ipc_callid_t callids[MAX_CONNECTIONS]; |
test_t tests[] = { |
#include "thread/thread1.def" |
#include "print/print1.def" |
#include "fault/fault1.def" |
#include "fault/fault2.def" |
#include "ipc/register.def" |
#include "ipc/connect.def" |
#include "ipc/send_async.def" |
#include "ipc/send_sync.def" |
#include "ipc/answer.def" |
#include "ipc/hangup.def" |
{NULL, NULL, NULL} |
}; |
static bool run_test(test_t *test) |
{ |
printf("%s\t\t%s\n", test->name, test->desc); |
/* Execute the test */ |
char * ret = test->entry(false); |
if (ret == NULL) { |
printf("Test passed\n\n"); |
return true; |
} |
printf("%s\n\n", ret); |
return false; |
} |
static void run_safe_tests(void) |
{ |
} |
static void list_tests(void) |
{ |
test_t *test; |
char c = 'a'; |
for (test = tests; test->name != NULL; test++, c++) |
printf("%c\t%s\t\t%s%s\n", c, test->name, test->desc, (test->safe ? "" : " (unsafe)")); |
printf("*\t\t\tRun all safe tests\n"); |
} |
int main(void) |
{ |
while (1) { |
char c; |
test_t *test; |
list_tests(); |
printf("> "); |
c = getchar(); |
printf("%c\n", c); |
if ((c >= 'a') && (c <= 'z')) { |
for (test = tests; test->name != NULL; test++, c--) |
if (c == 'a') |
break; |
if (c > 'a') |
printf("Unknown test\n\n"); |
else |
run_test(test); |
} else if (c == '*') |
run_safe_tests(); |
else |
printf("Invalid test\n\n"); |
} |
} |
/** @} |
*/ |
//branches/rcu/uspace/tester/thread/thread1.def |
---|
0,0 → 1,6 |
{ |
"thread1", |
"Thread test", |
&test_thread1, |
true |
}, |
//branches/rcu/uspace/tester/thread/thread1.c |
---|
0,0 → 1,83 |
/* |
* 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. |
*/ |
#define THREADS 5 |
#include <atomic.h> |
#include <thread.h> |
#include <stdio.h> |
#include <unistd.h> |
#include "../tester.h" |
static atomic_t finish; |
static atomic_t threads_finished; |
static bool sh_quiet; |
static void threadtest(void *data) |
{ |
thread_detach(thread_get_id()); |
while (atomic_get(&finish)) { |
if (!sh_quiet) |
printf("%llu ", thread_get_id()); |
usleep(100000); |
} |
atomic_inc(&threads_finished); |
} |
char * test_thread1(bool quiet) |
{ |
unsigned int i, total = 0; |
sh_quiet = quiet; |
atomic_set(&finish, 1); |
atomic_set(&threads_finished, 0); |
for (i = 0; i < THREADS; i++) { |
if (thread_create(threadtest, NULL, "threadtest", NULL) < 0) { |
if (!quiet) |
printf("Could not create thread %d\n", i); |
break; |
} |
total++; |
} |
if (!quiet) |
printf("Running threads for 10 seconds...\n"); |
sleep(10); |
atomic_set(&finish, 0); |
while (atomic_get(&threads_finished) < total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_finished)); |
sleep(1); |
} |
return NULL; |
} |
//branches/rcu/uspace/tester/fault/fault1.def |
---|
0,0 → 1,6 |
{ |
"fault1", |
"Write to NULL", |
&test_fault1, |
false |
}, |
//branches/rcu/uspace/tester/fault/fault2.def |
---|
0,0 → 1,6 |
{ |
"fault2", |
"Unaligned read", |
&test_fault2, |
false |
}, |
//branches/rcu/uspace/tester/fault/fault1.c |
---|
0,0 → 1,37 |
/* |
* 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 "../tester.h" |
char * test_fault1(bool quiet) |
{ |
((int *)(0))[1] = 0; |
return "Survived write to NULL"; |
} |
//branches/rcu/uspace/tester/fault/fault2.c |
---|
0,0 → 1,40 |
/* |
* 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 "../tester.h" |
char * test_fault2(bool quiet) |
{ |
volatile long long var; |
volatile int var1; |
var1 = *((int *) (((char *) (&var)) + 1)); |
return "Survived unaligned read"; |
} |
//branches/rcu/uspace/tester/ipc/hangup.def |
---|
0,0 → 1,6 |
{ |
"hangup", |
"IPC hangup test", |
&test_hangup, |
true |
}, |
//branches/rcu/uspace/tester/ipc/answer.c |
---|
0,0 → 1,76 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* 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 <stdio.h> |
#include <unistd.h> |
#include <errno.h> |
#include "../tester.h" |
char * test_answer(bool quiet) |
{ |
int i,cnt, errn = 0; |
char c; |
cnt = 0; |
for (i = 0;i < 50; i++) { |
if (callids[i]) { |
printf("%d: %P\n", cnt, callids[i]); |
cnt++; |
} |
if (cnt >= 10) |
break; |
} |
if (!cnt) |
return; |
printf("Choose message:\n"); |
do { |
c = getchar(); |
} while (c < '0' || (c-'0') >= cnt); |
cnt = c - '0' + 1; |
for (i = 0; cnt; i++) |
if (callids[i]) |
cnt--; |
i -= 1; |
printf("Normal (n) or hangup (h) or error(e) message?\n"); |
do { |
c = getchar(); |
} while (c != 'n' && c != 'h' && c != 'e'); |
if (c == 'n') |
errn = 0; |
else if (c == 'h') |
errn = EHANGUP; |
else if (c == 'e') |
errn = ENOENT; |
printf("Answering %P\n", callids[i]); |
ipc_answer_fast(callids[i], errn, 0, 0); |
callids[i] = 0; |
return NULL; |
} |
//branches/rcu/uspace/tester/ipc/register.def |
---|
0,0 → 1,6 |
{ |
"register", |
"IPC registration test", |
&test_register, |
true |
}, |
//branches/rcu/uspace/tester/ipc/send_sync.def |
---|
0,0 → 1,6 |
{ |
"send_sync", |
"IPC send sync message test", |
&test_send_sync, |
true |
}, |
//branches/rcu/uspace/tester/ipc/hangup.c |
---|
0,0 → 1,51 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* 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 <stdio.h> |
#include <unistd.h> |
#include <errno.h> |
#include "../tester.h" |
char * test_hangup(bool quiet) |
{ |
char c; |
int res; |
int phoneid; |
printf("Select phoneid to hangup: 2-9\n"); |
do { |
c = getchar(); |
} while (c < '2' || c > '9'); |
phoneid = c - '0'; |
printf("Hanging up..."); |
res = ipc_hangup(phoneid); |
printf("done: %d\n", phoneid); |
return NULL; |
} |
//branches/rcu/uspace/tester/ipc/send_async.def |
---|
0,0 → 1,6 |
{ |
"send_async", |
"IPC send async message test", |
&test_send_async, |
true |
}, |
//branches/rcu/uspace/tester/ipc/register.c |
---|
0,0 → 1,87 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* 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 <stdio.h> |
#include <unistd.h> |
#include <async.h> |
#include "../tester.h" |
static void client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
ipcarg_t phonehash = icall->in_phone_hash; |
int retval; |
int i; |
printf("Connected phone: %P, accepting\n", icall->in_phone_hash); |
ipc_answer_fast(iid, 0, 0, 0); |
for (i = 0; i < 1024; i++) |
if (!connections[i]) { |
connections[i] = phonehash; |
break; |
} |
while (1) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
printf("Phone (%P) hung up.\n", phonehash); |
retval = 0; |
break; |
default: |
printf("Received message from %P: %X\n", phonehash,callid); |
for (i = 0; i < 1024; i++) |
if (!callids[i]) { |
callids[i] = callid; |
break; |
} |
continue; |
} |
ipc_answer_fast(callid, retval, 0, 0); |
} |
} |
char * test_register(bool quiet) |
{ |
int i; |
async_set_client_connection(client_connection); |
for (i = IPC_TEST_START; i < IPC_TEST_START + 10; i++) { |
ipcarg_t phonead; |
int res = ipc_connect_to_me(PHONE_NS, i, 0, &phonead); |
if (!res) |
break; |
printf("Failed registering as %d..:%d\n", i, res); |
} |
printf("Registered as service: %d\n", i); |
myservice = i; |
return NULL; |
} |
//branches/rcu/uspace/tester/ipc/connect.def |
---|
0,0 → 1,6 |
{ |
"connect", |
"IPC connection test (connect to other service)", |
&test_connect, |
true |
}, |
//branches/rcu/uspace/tester/ipc/send_sync.c |
---|
0,0 → 1,51 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* 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 <stdio.h> |
#include <unistd.h> |
#include "../tester.h" |
char * test_send_sync(bool quiet) |
{ |
int phoneid; |
int res; |
static int msgid = 1; |
char c; |
printf("Select phoneid to send msg: 2-9\n"); |
do { |
c = getchar(); |
} while (c < '2' || c > '9'); |
phoneid = c - '0'; |
printf("Sending msg..."); |
res = ipc_call_sync_2(phoneid, 2000, 0, 0, NULL, NULL); |
printf("done: %d\n", res); |
return NULL; |
} |
//branches/rcu/uspace/tester/ipc/send_async.c |
---|
0,0 → 1,56 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* 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 <stdio.h> |
#include <unistd.h> |
#include "../tester.h" |
static void callback(void *_private, int retval, ipc_call_t *data) |
{ |
printf("Received response to msg %d - retval: %d.\n", _private, retval); |
} |
char * test_send_async(bool quiet) |
{ |
int phoneid; |
int res; |
static int msgid = 1; |
char c; |
printf("Select phoneid to send msg: 2-9\n"); |
do { |
c = getchar(); |
} while (c < '2' || c > '9'); |
phoneid = c - '0'; |
ipc_call_async(phoneid, 2000, 0, (void *) msgid, callback, 1); |
printf("Async sent - msg %d\n", msgid); |
msgid++; |
return NULL; |
} |
//branches/rcu/uspace/tester/ipc/connect.c |
---|
0,0 → 1,57 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* 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 <stdio.h> |
#include <unistd.h> |
#include "../tester.h" |
char * test_connect(bool quiet) |
{ |
char c; |
int svc; |
int phid; |
printf("Choose one service: 0:10000....9:10009\n"); |
do { |
c = getchar(); |
} while (c < '0' || c > '9'); |
svc = IPC_TEST_START + c - '0'; |
if (svc == myservice) |
return "Currently cannot connect to myself, update test"; |
printf("Connecting to %d..", svc); |
phid = ipc_connect_me_to(PHONE_NS, svc, 0); |
if (phid > 0) { |
printf("phoneid: %d\n", phid); |
phones[phid] = 1; |
} else |
return "Error"; |
return NULL; |
} |
//branches/rcu/uspace/tester/ipc/answer.def |
---|
0,0 → 1,6 |
{ |
"answer", |
"IPC answer message test", |
&test_answer, |
true |
}, |
//branches/rcu/uspace/tester/print/print1.def |
---|
0,0 → 1,6 |
{ |
"print1", |
"Printf test", |
&test_print1, |
true |
}, |
//branches/rcu/uspace/tester/print/print1.c |
---|
0,0 → 1,73 |
/* |
* Copyright (c) 2005 Josef Cejka |
* 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 <stdio.h> |
#include <unistd.h> |
#include "../tester.h" |
#define BUFFER_SIZE 32 |
char * test_print1(bool quiet) |
{ |
if (!quiet) { |
int retval; |
unsigned int nat = 0x12345678u; |
char buffer[BUFFER_SIZE]; |
printf(" text 10.8s %*.*s \n", 5, 3, "text"); |
printf(" very long text 10.8s %10.8s \n", "very long text"); |
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("'%#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(" Print to NULL '%s'\n", NULL); |
retval = snprintf(buffer, BUFFER_SIZE, "Short text without parameters."); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
retval = snprintf(buffer, BUFFER_SIZE, "Very very very long text without parameters."); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
printf("Print short text to %d char long buffer via snprintf.\n", BUFFER_SIZE); |
retval = snprintf(buffer, BUFFER_SIZE, "Short %s", "text"); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
printf("Print long text to %d char long buffer via snprintf.\n", BUFFER_SIZE); |
retval = snprintf(buffer, BUFFER_SIZE, "Very long %s. This text`s length is more than %d. We are interested in the result.", "text" , BUFFER_SIZE); |
printf("Result is: '%s', retval = %d\n", buffer, retval); |
} |
return NULL; |
} |
//branches/rcu/uspace/tester/tester.h |
---|
0,0 → 1,76 |
/* |
* 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 tester |
* @{ |
*/ |
/** @file |
*/ |
#ifndef TESTER_H_ |
#define TESTER_H_ |
#include <types.h> |
#include <bool.h> |
#include <ipc/ipc.h> |
#define IPC_TEST_START 10000 |
#define MAX_PHONES 20 |
#define MAX_CONNECTIONS 50 |
extern int myservice; |
extern int phones[MAX_PHONES]; |
extern int connections[MAX_CONNECTIONS]; |
extern ipc_callid_t callids[MAX_CONNECTIONS]; |
typedef char * (* test_entry_t)(bool); |
typedef struct { |
char * name; |
char * desc; |
test_entry_t entry; |
bool safe; |
} test_t; |
extern char * test_thread1(bool quiet); |
extern char * test_print1(bool quiet); |
extern char * test_fault1(bool quiet); |
extern char * test_fault2(bool quiet); |
extern char * test_register(bool quiet); |
extern char * test_connect(bool quiet); |
extern char * test_send_async(bool quiet); |
extern char * test_send_sync(bool quiet); |
extern char * test_answer(bool quiet); |
extern char * test_hangup(bool quiet); |
extern test_t tests[]; |
#endif |
/** @} |
*/ |
//branches/rcu/uspace/tester/Makefile |
---|
0,0 → 1,83 |
# |
# Copyright (c) 2005 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. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../libc |
SOFTINT_PREFIX = ../softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../kbd/include |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = tester |
SOURCES = tester.c \ |
thread/thread1.c \ |
print/print1.c \ |
fault/fault1.c \ |
fault/fault2.c \ |
ipc/register.c \ |
ipc/connect.c \ |
ipc/send_async.c \ |
ipc/send_sync.c \ |
ipc/answer.c \ |
ipc/hangup.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
//branches/rcu/uspace/libc/include/async.h |
---|
116,12 → 116,13 |
void async_msg_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
ipcarg_t arg3); |
void async_msg_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2); |
#define async_msg(ph,m,a1) async_msg_2(ph,m,a1,0) |
#define async_msg(ph, m, a1) async_msg_2(ph, m, a1, 0) |
static inline void async_serialize_start(void) |
{ |
psthread_inc_sercount(); |
} |
static inline void async_serialize_end(void) |
{ |
psthread_dec_sercount(); |
//branches/rcu/uspace/libc/include/unistd.h |
---|
44,8 → 44,9 |
extern ssize_t write(int fd, const void * buf, size_t count); |
extern ssize_t read(int fd, void * buf, size_t count); |
extern void _exit(int status); |
void *sbrk(ssize_t incr); |
void usleep(unsigned long usec); |
extern void *sbrk(ssize_t incr); |
extern void usleep(unsigned long usec); |
extern unsigned int sleep(unsigned int seconds); |
#endif |
//branches/rcu/uspace/libc/include/thread.h |
---|
39,11 → 39,16 |
#include <libarch/thread.h> |
#include <types.h> |
typedef uint64_t thread_id_t; |
extern void __thread_entry(void); |
extern void __thread_main(uspace_arg_t *uarg); |
extern int thread_create(void (* function)(void *arg), void *arg, char *name); |
extern int thread_create(void (* function)(void *), void *arg, char *name, thread_id_t *tid); |
extern void thread_exit(int status); |
extern void thread_detach(thread_id_t thread); |
extern int thread_join(thread_id_t thread); |
extern thread_id_t thread_get_id(void); |
extern tcb_t * __make_tls(void); |
extern tcb_t * __alloc_tls(void **data, size_t size); |
extern void __free_tls(tcb_t *); |
//branches/rcu/uspace/libc/generic/time.c |
---|
108,14 → 108,31 |
return 0; |
} |
/** Wait unconditionally for specified microseconds */ |
/** Wait unconditionally for specified number of microseconds */ |
void usleep(unsigned long usec) |
{ |
atomic_t futex = FUTEX_INITIALIZER; |
futex_initialize(&futex,0); |
futex_initialize(&futex, 0); |
futex_down_timeout(&futex, usec, 0); |
} |
/** Wait unconditionally for specified number of seconds */ |
unsigned int sleep(unsigned int seconds) |
{ |
atomic_t futex = FUTEX_INITIALIZER; |
futex_initialize(&futex, 0); |
/* Sleep in 1000 second steps to support |
full argument range */ |
while (seconds > 0) { |
unsigned int period = (seconds > 1000) ? 1000 : seconds; |
futex_down_timeout(&futex, period * 1000000, 0); |
seconds -= period; |
} |
} |
/** @} |
*/ |
//branches/rcu/uspace/libc/generic/thread.c |
---|
124,10 → 124,11 |
* @param function Function implementing the thread. |
* @param arg Argument to be passed to thread. |
* @param name Symbolic name of the thread. |
* @param tid Thread ID of the newly created thread. |
* |
* @return TID of the new thread on success or -1 on failure. |
* @return Zero on success or a code from @ref errno.h on failure. |
*/ |
int thread_create(void (* function)(void *), void *arg, char *name) |
int thread_create(void (* function)(void *), void *arg, char *name, thread_id_t *tid) |
{ |
char *stack; |
uspace_arg_t *uarg; |
148,7 → 149,7 |
uarg->uspace_thread_arg = arg; |
uarg->uspace_uarg = uarg; |
return __SYSCALL2(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name); |
return __SYSCALL3(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name, (sysarg_t) tid); |
} |
/** Terminate current thread. |
160,5 → 161,40 |
__SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status); |
} |
/** Detach thread. |
* |
* Currently not implemented. |
* |
* @param thread TID. |
*/ |
void thread_detach(thread_id_t thread) |
{ |
} |
/** Join thread. |
* |
* Currently not implemented. |
* |
* @param thread TID. |
* |
* @return Thread exit status. |
*/ |
int thread_join(thread_id_t thread) |
{ |
} |
/** Get current thread ID. |
* |
* @return Current thread ID. |
*/ |
thread_id_t thread_get_id(void) |
{ |
thread_id_t thread_id; |
(void) __SYSCALL1(SYS_THREAD_GET_ID, (sysarg_t) &thread_id); |
return thread_id; |
} |
/** @} |
*/ |
//branches/rcu/uspace/libc/generic/io/printf.c |
---|
56,5 → 56,3 |
/** @} |
*/ |
//branches/rcu/uspace/libc/generic/io/io.c |
---|
37,18 → 37,17 |
#include <stdio.h> |
#include <io/io.h> |
static char nl = '\n'; |
const static char nl = '\n'; |
int puts(const char * str) |
int puts(const char *str) |
{ |
size_t count; |
if (str == NULL) { |
return putnchars("(NULL)",6 ); |
} |
if (str == NULL) |
return putnchars("(NULL)", 6); |
for (count = 0; str[count] != 0; count++); |
if (write(1, (void * ) str, count) == count) { |
if (write(1, (void *) str, count) == count) { |
if (write(1, &nl, 1) == 1) |
return 0; |
} |
61,11 → 60,10 |
* @param count |
* @return 0 on succes, EOF on fail |
*/ |
int putnchars(const char * buf, size_t count) |
int putnchars(const char *buf, size_t count) |
{ |
if (write(1, (void * ) buf, count) == count) { |
if (write(1, (void *) buf, count) == count) |
return 0; |
} |
return EOF; |
} |
73,18 → 71,16 |
/** Same as puts, but does not print newline at end |
* |
*/ |
int putstr(const char * str) |
int putstr(const char *str) |
{ |
size_t count; |
if (str == NULL) { |
return putnchars("(NULL)",6 ); |
} |
if (str == NULL) |
return putnchars("(NULL)", 6); |
for (count = 0; str[count] != 0; count++); |
if (write(1, (void * ) str, count) == count) { |
if (write(1, (void *) str, count) == count) |
return 0; |
} |
return EOF; |
} |
92,9 → 88,8 |
int putchar(int c) |
{ |
unsigned char ch = c; |
if (write(1, (void *)&ch , 1) == 1) { |
if (write(1, (void *) &ch, 1) == 1) |
return c; |
} |
return EOF; |
} |
102,9 → 97,8 |
int getchar(void) |
{ |
unsigned char c; |
if (read(0, (void *)&c , 1) == 1) { |
if (read(0, (void *) &c, 1) == 1) |
return c; |
} |
return EOF; |
} |
//branches/rcu/uspace/libc/generic/io/vprintf.c |
---|
36,10 → 36,12 |
#include <stdio.h> |
#include <unistd.h> |
#include <io/printf_core.h> |
#include <futex.h> |
#include <async.h> |
int vprintf_write(const char *str, size_t count, void *unused); |
static atomic_t printf_futex = FUTEX_INITIALIZER; |
int vprintf_write(const char *str, size_t count, void *unused) |
static int vprintf_write(const char *str, size_t count, void *unused) |
{ |
return write(1, str, count); |
} |
51,9 → 53,23 |
*/ |
int vprintf(const char *fmt, va_list ap) |
{ |
struct printf_spec ps = {(int(*)(void *, size_t, void *))vprintf_write, NULL}; |
return printf_core(fmt, &ps, ap); |
struct printf_spec ps = { |
(int (*)(void *, size_t, void *)) vprintf_write, |
NULL |
}; |
/* |
* Prevent other threads to execute printf_core() |
*/ |
futex_down(&printf_futex); |
/* |
* Prevent other pseudo threads of the same thread |
* to execute printf_core() |
*/ |
async_serialize_start(); |
int ret = printf_core(fmt, &ps, ap); |
async_serialize_end(); |
futex_up(&printf_futex); |
return ret; |
} |
/** @} |
//branches/rcu/uspace/libc/generic/io/vsnprintf.c |
---|
43,8 → 43,6 |
char *string; /* destination string */ |
}; |
int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data); |
/** Write string to given buffer. |
* Write at most data->size characters including trailing zero. According to C99 has snprintf to return number |
* of characters that would have been written if enough space had been available. Hence the return value is not |
55,7 → 53,7 |
* @param data structure with destination string, counter of used space and total string size. |
* @return number of characters to print (not characters really printed!) |
*/ |
int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
static int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
{ |
size_t i; |
i = data->size - data->len; |
97,7 → 95,7 |
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) |
{ |
struct vsnprintf_data data = {size, 0, str}; |
struct printf_spec ps = {(int(*)(void *, size_t, void *))vsnprintf_write, &data}; |
struct printf_spec ps = {(int(*)(void *, size_t, void *)) vsnprintf_write, &data}; |
/* Print 0 at end of string - fix the case that nothing will be printed */ |
if (size > 0) |
//branches/rcu/uspace/libc/generic/io/printf_core.c |
---|
40,8 → 40,6 |
#include <io/printf_core.h> |
#include <ctype.h> |
#include <string.h> |
/* For serialization */ |
#include <async.h> |
#define __PRINTF_FLAG_PREFIX 0x00000001 /**< show prefixes 0x or 0*/ |
#define __PRINTF_FLAG_SIGNED 0x00000002 /**< signed / unsigned number */ |
92,15 → 90,13 |
{ |
size_t count; |
if (str == NULL) { |
if (str == NULL) |
return printf_putnchars("(NULL)", 6, ps); |
} |
for (count = 0; str[count] != 0; count++); |
if (ps->write((void *) str, count, ps->data) == count) { |
if (ps->write((void *) str, count, ps->data) == count) |
return 0; |
} |
return EOF; |
} |
447,9 → 443,6 |
int width, precision; |
uint64_t flags; |
/* Don't let other threads interfere */ |
async_serialize_start(); |
counter = 0; |
while ((c = fmt[i])) { |
681,10 → 674,8 |
counter += retval; |
} |
async_serialize_end(); |
return counter; |
minus_out: |
async_serialize_end(); |
return -counter; |
} |
//branches/rcu/uspace/libc/generic/io/vsprintf.c |
---|
44,7 → 44,7 |
*/ |
int vsprintf(char *str, const char *fmt, va_list ap) |
{ |
return vsnprintf(str, (size_t)-1, fmt, ap); |
return vsnprintf(str, (size_t) - 1, fmt, ap); |
} |
/** @} |
//branches/rcu/uspace/libc/arch/sparc64/include/atomic.h |
---|
51,9 → 51,11 |
uint64_t a, b; |
do { |
a = val->count; |
volatile uintptr_t x = (uint64_t) &val->count; |
a = *((uint64_t *) x); |
b = a + i; |
asm volatile ("casx %0, %2, %1\n" : "+m" (*val), "+r" (b) : "r" (a)); |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)), "+r" (b) : "r" (a)); |
} while (a != b); |
return a; |
//branches/rcu/uspace/libc/arch/sparc64/src/thread_entry.s |
---|
34,7 → 34,7 |
# |
# |
__thread_entry: |
sethi %hi(_gp), %l7 |
sethi %hi(_gp), %l7 |
call __thread_main ! %o0 contains address of uarg |
or %l7, %lo(_gp), %l7 |
//branches/rcu/uspace/Makefile |
---|
41,7 → 41,7 |
kbd \ |
console \ |
tetris \ |
ipcc \ |
tester \ |
klog \ |
rd \ |
fs |
//branches/rcu/boot/tools/ia32/gen_vga323.c |
---|
0,0 → 1,14 |
#include <stdio.h> |
#define RED(i) ((i >> 5) & ((1 << 3) - 1)) |
#define GREEN(i) ((i >> 3) & ((1 << 2) - 1)) |
#define BLUE(i) (i & ((1 << 3) - 1)) |
int main(int argc, char *argv[]) { |
unsigned int i; |
for (i = 0; i < 256; i++) |
printf("\t.byte 0x%02x, 0x%02x, 0x%02x, 0x00\n", BLUE(i) * 9, GREEN(i) * 21, RED(i) * 9); |
return 0; |
} |
//branches/rcu/boot/genarch/ofw.h |
---|
117,7 → 117,8 |
extern unsigned int ofw_get_size_cells(const phandle device); |
extern void *ofw_translate(const void *virt); |
extern int ofw_translate_failed(ofw_arg_t flag); |
extern void *ofw_claim(const void *virt, const int len); |
extern void *ofw_claim_virt(const void *virt, const int len); |
extern void *ofw_claim_phys(const void *virt, const int len); |
extern int ofw_map(const void *phys, const void *virt, const int size, const int mode); |
extern int ofw_memmap(memmap_t *map); |
extern int ofw_screen(screen_t *screen); |
//branches/rcu/boot/genarch/balloc.h |
---|
31,6 → 31,8 |
#include <types.h> |
#define BALLOC_MAX_SIZE (1024 * 1024) |
typedef struct { |
uintptr_t base; |
size_t size; |
//branches/rcu/boot/genarch/ofw.c |
---|
38,6 → 38,7 |
ihandle ofw_stdout; |
phandle ofw_root; |
ihandle ofw_mmu; |
ihandle ofw_memory_prop; |
phandle ofw_memory; |
phandle ofw_aliases; |
47,7 → 48,7 |
if (ofw_chosen == -1) |
halt(); |
if (ofw_get_property(ofw_chosen, "stdout", &ofw_stdout, sizeof(ofw_stdout)) <= 0) |
if (ofw_get_property(ofw_chosen, "stdout", &ofw_stdout, sizeof(ofw_stdout)) <= 0) |
ofw_stdout = 0; |
ofw_root = ofw_find_device("/"); |
56,10 → 57,14 |
halt(); |
} |
if (ofw_get_property(ofw_chosen, "mmu", &ofw_mmu, sizeof(ofw_mmu)) <= 0) { |
if (ofw_get_property(ofw_chosen, "mmu", &ofw_mmu, sizeof(ofw_mmu)) <= 0) { |
puts("\r\nError: Unable to get mmu property, halted.\r\n"); |
halt(); |
} |
if (ofw_get_property(ofw_chosen, "memory", &ofw_memory_prop, sizeof(ofw_memory_prop)) <= 0) { |
puts("\r\nError: Unable to get memory property, halted.\r\n"); |
halt(); |
} |
ofw_memory = ofw_find_device("/memory"); |
if (ofw_memory == -1) { |
200,13 → 205,12 |
else |
shift = 0; |
return (void *) ((result[2]<<shift)|result[3]); |
return (void *) ((result[2] << shift) | result[3]); |
} |
void *ofw_claim(const void *virt, const int len) |
void *ofw_claim_virt(const void *virt, const int len) |
{ |
ofw_arg_t retaddr; |
int shift; |
if (ofw_call("call-method", 5, 2, &retaddr, "claim", ofw_mmu, 0, len, virt) != 0) { |
puts("Error: MMU method claim() failed, halting.\n"); |
216,6 → 220,42 |
return (void *) retaddr; |
} |
void *ofw_claim_phys(const void *phys, const int len) |
{ |
ofw_arg_t retaddr[2]; |
int shift; |
if (sizeof(unative_t) == 8) { |
shift = 32; |
if (ofw_call("call-method", 6, 3, retaddr, "claim", |
ofw_memory_prop, 0, len, ((uintptr_t) phys) >> shift, |
((uintptr_t) phys) & ((uint32_t) -1)) != 0) { |
/* |
* Note that this will help us to discover |
* conflicts between OpenFirmware allocations |
* and our use of physical memory. |
* It is better to detect collisions here |
* than to cope with weird errors later. |
* |
* So this is really not to make the loader |
* more generic; it is here for debugging |
* purposes. |
*/ |
puts("Error: memory method claim() failed, halting.\n"); |
halt(); |
} |
} else { |
shift = 0; |
/* |
* FIXME: the number of arguments is probably different... |
*/ |
puts("Error: 32-bit ofw_claim_phys not implemented.\n"); |
halt(); |
} |
return (void *) ((retaddr[0] << shift) | retaddr[1]); |
} |
int ofw_map(const void *phys, const void *virt, const int size, const int mode) |
{ |
uintptr_t phys_hi, phys_lo; |
230,7 → 270,7 |
} |
return ofw_call("call-method", 7, 1, NULL, "map", ofw_mmu, mode, size, virt, |
phys_hi, phys_lo); |
phys_hi, phys_lo); |
} |
/** Save OpenFirmware physical memory map. |
252,8 → 292,8 |
int pos; |
map->total = 0; |
map->count = 0; |
for (pos = 0; (pos < ret / sizeof(uint32_t)) && (map->count < |
MEMMAP_MAX_RECORDS); pos += ac + sc) { |
for (pos = 0; (pos < ret / sizeof(uint32_t)) && |
(map->count < MEMMAP_MAX_RECORDS); pos += ac + sc) { |
void * start = (void *) ((uintptr_t) buf[pos + ac - 1]); |
unsigned int size = buf[pos + ac + sc - 1]; |
//branches/rcu/boot/genarch/balloc.c |
---|
47,7 → 47,10 |
alignment = ALIGN_UP(alignment, 4); |
addr = ballocs->base + ALIGN_UP(ballocs->size, alignment); |
if (ALIGN_UP(ballocs->size, alignment) + size > BALLOC_MAX_SIZE) |
return NULL; |
ballocs->size = ALIGN_UP(ballocs->size, alignment) + size; |
return (void *) addr; |
//branches/rcu/boot/arch/sparc64/loader/main.c |
---|
92,7 → 92,7 |
unsigned int i; |
for (i = 0; i < COMPONENTS; i++) |
printf(" %P: %s image (size %d bytes)\n", components[i].start, |
components[i].name, components[i].size); |
components[i].name, components[i].size); |
void * base = (void *) KERNEL_VIRTUAL_ADDRESS; |
unsigned int top = 0; |
102,10 → 102,24 |
for (i = 0; i < COMPONENTS; i++) { |
printf(" %s...", components[i].name); |
top = ALIGN_UP(top, PAGE_SIZE); |
/* |
* At this point, we claim the physical memory that we are |
* going to use. We should be safe in case of the virtual |
* address space because the OpenFirmware, according to its |
* SPARC binding, should restrict its use of virtual memory |
* to addresses from [0xffd00000; 0xffefffff] and |
* [0xfe000000; 0xfeffffff]. |
*/ |
(void) ofw_claim_phys(bootinfo.physmem_start + base + top, |
ALIGN_UP(components[i].size, PAGE_SIZE)); |
memcpy(base + top, components[i].start, components[i].size); |
if (i > 0) { |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr = base + top; |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].size = components[i].size; |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr = |
base + top; |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].size = |
components[i].size; |
bootinfo.taskmap.count++; |
} |
top += components[i].size; |
112,7 → 126,14 |
printf("done.\n"); |
} |
balloc_init(&bootinfo.ballocs, ALIGN_UP(((uintptr_t) base) + top, PAGE_SIZE)); |
/* |
* Claim the physical memory for the boot allocator. |
* Initialize the boot allocator. |
*/ |
(void) ofw_claim_phys(bootinfo.physmem_start + |
base + ALIGN_UP(top, PAGE_SIZE), BALLOC_MAX_SIZE); |
balloc_init(&bootinfo.ballocs, ALIGN_UP(((uintptr_t) base) + top, |
PAGE_SIZE)); |
printf("\nCanonizing OpenFirmware device tree..."); |
bootinfo.ofw_root = ofw_tree_build(); |
127,5 → 148,7 |
printf("\nBooting the kernel...\n"); |
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS, |
bootinfo.physmem_start | BSP_PROCESSOR, &bootinfo, sizeof(bootinfo)); |
bootinfo.physmem_start | BSP_PROCESSOR, &bootinfo, |
sizeof(bootinfo)); |
} |
//branches/rcu/boot/arch/sparc64/loader/Makefile |
---|
78,7 → 78,7 |
$(USPACEDIR)/kbd/kbd \ |
$(USPACEDIR)/console/console \ |
$(USPACEDIR)/tetris/tetris \ |
$(USPACEDIR)/ipcc/ipcc \ |
$(USPACEDIR)/tester/tester \ |
$(USPACEDIR)/klog/klog |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
//branches/rcu/boot/arch/sparc64/silo/silo.tar.gz |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
//branches/rcu/boot/arch/ppc32/loader/Makefile |
---|
75,7 → 75,7 |
$(USPACEDIR)/kbd/kbd \ |
$(USPACEDIR)/console/console \ |
$(USPACEDIR)/tetris/tetris \ |
$(USPACEDIR)/ipcc/ipcc \ |
$(USPACEDIR)/tester/tester \ |
$(USPACEDIR)/klog/klog |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
//branches/rcu/boot/arch/ia32xen/grub/menu.lst |
---|
12,5 → 12,5 |
module /boot/kbd |
module /boot/console |
module /boot/tetris |
module /boot/ipcc |
module /boot/tester |
module /boot/klog |
//branches/rcu/boot/arch/ia32xen/grub/menu.debug.lst |
---|
12,5 → 12,5 |
module /boot/kbd |
module /boot/console |
module /boot/tetris |
module /boot/ipcc |
module /boot/tester |
module /boot/klog |
//branches/rcu/boot/arch/ia32xen/Makefile.inc |
---|
34,7 → 34,7 |
$(USPACEDIR)/kbd/kbd \ |
$(USPACEDIR)/console/console \ |
$(USPACEDIR)/tetris/tetris \ |
$(USPACEDIR)/ipcc/ipcc \ |
$(USPACEDIR)/tester/tester \ |
$(USPACEDIR)/klog/klog |
build: $(BASE)/image.iso |
//branches/rcu/boot/arch/amd64/grub/menu.lst |
---|
11,5 → 11,5 |
module /boot/kbd |
module /boot/console |
module /boot/tetris |
module /boot/ipcc |
module /boot/tester |
module /boot/klog |
//branches/rcu/boot/arch/amd64/Makefile.inc |
---|
34,7 → 34,7 |
$(USPACEDIR)/kbd/kbd \ |
$(USPACEDIR)/console/console \ |
$(USPACEDIR)/tetris/tetris \ |
$(USPACEDIR)/ipcc/ipcc \ |
$(USPACEDIR)/tester/tester \ |
$(USPACEDIR)/klog/klog |
build: $(BASE)/image.iso |
//branches/rcu/boot/arch/ppc64/loader/Makefile |
---|
75,7 → 75,7 |
$(USPACEDIR)/kbd/kbd \ |
$(USPACEDIR)/console/console \ |
$(USPACEDIR)/tetris/tetris \ |
$(USPACEDIR)/ipcc/ipcc \ |
$(USPACEDIR)/tester/tester \ |
$(USPACEDIR)/klog/klog |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
//branches/rcu/boot/arch/mips32/loader/Makefile |
---|
74,7 → 74,7 |
$(USPACEDIR)/kbd/kbd \ |
$(USPACEDIR)/console/console \ |
$(USPACEDIR)/tetris/tetris \ |
$(USPACEDIR)/ipcc/ipcc \ |
$(USPACEDIR)/tester/tester \ |
$(USPACEDIR)/klog/klog |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
//branches/rcu/boot/arch/ia32/grub/menu.lst |
---|
11,5 → 11,5 |
module /boot/kbd |
module /boot/console |
module /boot/tetris |
module /boot/ipcc |
module /boot/tester |
module /boot/klog |
//branches/rcu/boot/arch/ia32/Makefile.inc |
---|
34,7 → 34,7 |
$(USPACEDIR)/kbd/kbd \ |
$(USPACEDIR)/console/console \ |
$(USPACEDIR)/tetris/tetris \ |
$(USPACEDIR)/ipcc/ipcc \ |
$(USPACEDIR)/tester/tester \ |
$(USPACEDIR)/klog/klog |
build: $(BASE)/image.iso |