/kernel/trunk/arch/sparc64/src/console.c |
---|
27,119 → 27,12 |
*/ |
#include <arch/console.h> |
#include <genarch/ofw/ofw.h> |
#include <console/chardev.h> |
#include <console/console.h> |
#include <arch/asm.h> |
#include <arch/register.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <proc/thread.h> |
#include <synch/mutex.h> |
#include <genarch/fb/fb.h> |
#include <arch/drivers/fb.h> |
static void ofw_sparc64_putchar(chardev_t *d, const char ch); |
static char ofw_sparc64_getchar(chardev_t *d); |
static void ofw_sparc64_suspend(chardev_t *d); |
static void ofw_sparc64_resume(chardev_t *d); |
mutex_t canwork; |
static chardev_t ofw_sparc64_console; |
static chardev_operations_t ofw_sparc64_console_ops = { |
.write = ofw_sparc64_putchar, |
.read = ofw_sparc64_getchar, |
.resume = ofw_sparc64_resume, |
.suspend = ofw_sparc64_suspend |
}; |
void ofw_sparc64_console_init(void) |
void fb_sparc64_console_init(void) |
{ |
chardev_initialize("ofw_sparc64_console", &ofw_sparc64_console, &ofw_sparc64_console_ops); |
stdin = &ofw_sparc64_console; |
stdout = &ofw_sparc64_console; |
mutex_initialize(&canwork); |
fb_init(FB_VIRT_ADDRESS, FB_X_RES, FB_Y_RES, FB_COLOR_DEPTH/8); |
} |
/** Write one character. |
* |
* @param d Character device (ignored). |
* @param ch Character to be written. |
*/ |
void ofw_sparc64_putchar(chardev_t *d, const char ch) |
{ |
pstate_reg_t pstate; |
/* |
* 32-bit OpenFirmware depends on PSTATE.AM bit set. |
*/ |
pstate.value = pstate_read(); |
pstate.am = true; |
pstate_write(pstate.value); |
if (ch == '\n') |
ofw_putchar('\r'); |
ofw_putchar(ch); |
pstate.am = false; |
pstate_write(pstate.value); |
} |
/** Read one character. |
* |
* The call is non-blocking. |
* |
* @param d Character device (ignored). |
* @return Character read or zero if no character was read. |
*/ |
char ofw_sparc64_getchar(chardev_t *d) |
{ |
char ch; |
pstate_reg_t pstate; |
/* |
* 32-bit OpenFirmware depends on PSTATE.AM bit set. |
*/ |
pstate.value = pstate_read(); |
pstate.am = true; |
pstate_write(pstate.value); |
ch = ofw_getchar(); |
pstate.am = false; |
pstate_write(pstate.value); |
return ch; |
} |
void ofw_sparc64_suspend(chardev_t *d) |
{ |
mutex_lock(&canwork); |
} |
void ofw_sparc64_resume(chardev_t *d) |
{ |
mutex_unlock(&canwork); |
} |
/** Kernel thread for pushing characters read from OFW to input buffer. |
* |
* @param arg Ignored. |
*/ |
void kofwinput(void *arg) |
{ |
while (1) { |
char ch = 0; |
mutex_lock(&canwork); |
mutex_unlock(&canwork); |
ch = ofw_sparc64_getchar(NULL); |
if (ch) { |
if (ch == '\r') |
ch = '\n'; |
chardev_push_character(&ofw_sparc64_console, ch); |
} |
thread_usleep(25000); |
} |
} |
/kernel/trunk/arch/sparc64/src/sparc64.c |
---|
36,7 → 36,6 |
void arch_pre_mm_init(void) |
{ |
interrupts_disable(); |
ofw_sparc64_console_init(); |
trap_init(); |
tick_init(); |
} |
43,6 → 42,7 |
void arch_post_mm_init(void) |
{ |
fb_sparc64_console_init(); |
} |
void arch_pre_smp_init(void) |
51,15 → 51,6 |
void arch_post_smp_init(void) |
{ |
thread_t *t; |
/* |
* Create thread that reads characters from OFW's input. |
*/ |
t = thread_create(kofwinput, NULL, TASK, 0); |
if (!t) |
panic("cannot create kofwinput\n"); |
thread_ready(t); |
} |
void calibrate_delay_loop(void) |
/kernel/trunk/arch/sparc64/src/trap/exception.c |
---|
27,6 → 27,7 |
*/ |
#include <arch/trap/exception.h> |
#include <arch/asm.h> |
#include <debug.h> |
/** Handle instruction_access_exception. */ |
40,3 → 41,9 |
{ |
panic("Memory Address Not Aligned\n"); |
} |
/** Handle mem_address_not_aligned. */ |
void do_illegal_instruction(void) |
{ |
panic("Illegal Instruction: %P\n", tpc_read()); |
} |
/kernel/trunk/arch/sparc64/src/trap/trap.c |
---|
42,82 → 42,4 |
/** Initialize trap table. */ |
void trap_init(void) |
{ |
/* |
* Save kernel provided trap handlers. |
*/ |
memcpy((void *) trap_table_save, (void *) trap_table, TRAP_TABLE_SIZE); |
/* |
* Copy OFW's trap table into kernel. |
*/ |
memcpy((void *) trap_table, (void *) tba_read(), TRAP_TABLE_SIZE); |
/* |
* Install kernel-provided handlers. |
*/ |
trap_install_handler(TT_INSTRUCTION_ACCESS_EXCEPTION, TRAP_TABLE_ENTRY_SIZE, false); |
trap_install_handler(TT_CLEAN_WINDOW, CLEAN_WINDOW_HANDLER_SIZE, false); |
trap_install_handler(TT_MEM_ADDRESS_NOT_ALIGNED, TRAP_TABLE_ENTRY_SIZE, false); |
trap_install_handler(TT_SPILL_0_NORMAL, SPILL_HANDLER_SIZE, false); |
trap_install_handler(TT_FILL_0_NORMAL, FILL_HANDLER_SIZE, false); |
trap_install_handler(TT_INSTRUCTION_ACCESS_EXCEPTION, TRAP_TABLE_ENTRY_SIZE, true); |
trap_install_handler(TT_CLEAN_WINDOW, CLEAN_WINDOW_HANDLER_SIZE, true); |
trap_install_handler(TT_MEM_ADDRESS_NOT_ALIGNED, TRAP_TABLE_ENTRY_SIZE, true); |
trap_install_handler(TT_SPILL_0_NORMAL, SPILL_HANDLER_SIZE, true); |
trap_install_handler(TT_FILL_0_NORMAL, FILL_HANDLER_SIZE, true); |
trap_install_handler(TT_INTERRUPT_LEVEL_1, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_2, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_3, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_4, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_5, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_6, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_7, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_8, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_9, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_10, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_11, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_12, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_13, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_14, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_LEVEL_15, INTERRUPT_LEVEL_N_HANDLER_SIZE, false); |
trap_install_handler(TT_INTERRUPT_VECTOR_TRAP, INTERRUPT_VECTOR_TRAP_HANDLER_SIZE, false); |
/* |
* Kernel must become independent on Open Firmware calls before MMU handlers are enabled. |
*/ |
/* |
trap_install_handler(TT_FAST_INSTRUCTION_ACCESS_MMU_MISS, FAST_MMU_HANDLER_SIZE, false); |
trap_install_handler(TT_FAST_DATA_ACCESS_MMU_MISS, FAST_MMU_HANDLER_SIZE, false); |
trap_install_handler(TT_FAST_DATA_ACCESS_PROTECTION, FAST_MMU_HANDLER_SIZE, false); |
trap_install_handler(TT_FAST_INSTRUCTION_ACCESS_MMU_MISS, FAST_MMU_HANDLER_SIZE, true); |
trap_install_handler(TT_FAST_DATA_ACCESS_MMU_MISS, FAST_MMU_HANDLER_SIZE, true); |
trap_install_handler(TT_FAST_DATA_ACCESS_PROTECTION, FAST_MMU_HANDLER_SIZE, true); |
*/ |
} |
/** Copy trap handler to active trap table. |
* |
* The handler is copied from trap_table_kernel to trap_handler. |
* |
* @param tt Trap type. An index that uniquelly identifies handler code. |
* @param len Length of the handler in bytes. Must be multiple of TRAP_TABLE_ENTRY_SIZE (i.e. 32). |
* @param tlnonz If false, tt is considered from the lower half of trap table. If true, the upper half is chosen. |
*/ |
void trap_install_handler(index_t tt, size_t len, bool tlnonz) |
{ |
count_t cnt; |
int i; |
ASSERT(tt < TRAP_TABLE_ENTRY_COUNT/2); |
ASSERT(len % TRAP_TABLE_ENTRY_SIZE == 0); |
if (tlnonz) |
tt += TRAP_TABLE_ENTRY_COUNT/2; |
cnt = len/TRAP_TABLE_ENTRY_SIZE; |
for (i = tt; i < tt + cnt; i++) { |
trap_table[i] = trap_table_save[i]; |
} |
} |
/kernel/trunk/arch/sparc64/src/trap/trap_table.S |
---|
27,15 → 27,7 |
# |
/** |
* This file contains two trap tables. |
* First, trap_table, is the one wich contains handlers implemented by |
* kernel. During initialization, these handlers are copied out to |
* the second trap table, trap_table_save, and the first table is |
* overwritten with copy of OFW's own trap table. The copy is then patched |
* from the trap_table_save. |
* |
* This arrangement is beneficial because kernel handlers stay on their |
* link-time addresses which is good for debugging. |
* This file contains kernel trap table. |
*/ |
.register %g2, #scratch |
68,6 → 60,12 |
instruction_access_exception: |
SIMPLE_HANDLER do_instruction_access_exc |
/* TT = 0x10, TL = 0, illegal_instruction */ |
.org trap_table + TT_ILLEGAL_INSTRUCTION*ENTRY_SIZE |
.global illegal_instruction |
illegal_instruction: |
SIMPLE_HANDLER do_illegal_instruction |
/* TT = 0x24, TL = 0, clean_window handler */ |
.org trap_table + TT_CLEAN_WINDOW*ENTRY_SIZE |
.global clean_window_handler |
216,6 → 214,12 |
instruction_access_exception_high: |
SIMPLE_HANDLER do_instruction_access_exc |
/* TT = 0x10, TL > 0, illegal_instruction */ |
.org trap_table + (TT_ILLEGAL_INSTRUCTION+512)*ENTRY_SIZE |
.global illegal_instruction_high |
illegal_instruction_high: |
SIMPLE_HANDLER do_illegal_instruction |
/* TT = 0x24, TL > 0, clean_window handler */ |
.org trap_table + (TT_CLEAN_WINDOW+512)*ENTRY_SIZE |
.global clean_window_handler_high |
259,16 → 263,6 |
FILL_NORMAL_HANDLER |
/* |
* Save trap table. |
*/ |
.align TABLE_SIZE |
.global trap_table_save |
trap_table_save: |
.space TABLE_SIZE, 0 |
/* Preemptible trap handler. |
* |
* This trap handler makes arrangements to |
/kernel/trunk/arch/sparc64/src/mm/tlb.c |
---|
40,6 → 40,7 |
#include <panic.h> |
#include <arch/asm.h> |
#include <symtab.h> |
#include <arch/drivers/fb.h> |
char *context_encoding[] = { |
"Primary", |
110,8 → 111,8 |
/* |
* Quick hack: map frame buffer |
*/ |
fr.address = 0x1C901000000ULL; |
pg.address = 0xc0000000; |
fr.address = FB_PHYS_ADDRESS; |
pg.address = FB_VIRT_ADDRESS; |
tag.value = ASID_KERNEL; |
tag.vpn = pg.vpn; |
130,7 → 131,6 |
data.g = true; |
dtlb_data_in_write(data.value); |
} |
/** ITLB miss handler. */ |
146,7 → 146,7 |
tlb_data_t data; |
__address tpc; |
char *tpc_str; |
tag.value = dtlb_tag_access_read(); |
if (tag.context != ASID_KERNEL || tag.vpn == 0) { |
tpc = tpc_read(); |