Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 882 → Rev 883

/kernel/trunk/arch/sparc64/include/console.h
29,7 → 29,6
#ifndef __sparc64_CONSOLE_H__
#define __sparc64_CONSOLE_H__
 
extern void kofwinput(void *arg);
extern void ofw_sparc64_console_init(void);
extern void fb_sparc64_console_init(void);
 
#endif
/kernel/trunk/arch/sparc64/include/asm.h
249,6 → 249,18
return v;
}
 
/** Read Trap Level register.
*
* @return Current value in TL.
*/
static inline __u64 tl_read(void)
{
__u64 v;
__asm__ volatile ("rdpr %%tl, %0\n" : "=r" (v));
return v;
}
 
/** Write Trap Base Address register.
*
/kernel/trunk/arch/sparc64/include/trap/exception.h
30,11 → 30,13
#define __sparc64_EXCEPTION_H__
 
#define TT_INSTRUCTION_ACCESS_EXCEPTION 0x08
#define TT_ILLEGAL_INSTRUCTION 0x10
#define TT_MEM_ADDRESS_NOT_ALIGNED 0x34
 
#ifndef __ASM__
extern void do_instruction_access_exc(void);
extern void do_mem_address_not_aligned(void);
extern void do_illegal_instruction(void);
#endif /* !__ASM__ */
 
#endif
/kernel/trunk/arch/sparc64/include/trap/mmu.h
33,6 → 33,8
#ifndef __sparc64_MMU_TRAP_H__
#define __sparc64_MMU_TRAP_H__
 
#include <arch/stack.h>
 
#define TT_FAST_INSTRUCTION_ACCESS_MMU_MISS 0x64
#define TT_FAST_DATA_ACCESS_MMU_MISS 0x68
#define TT_FAST_DATA_ACCESS_PROTECTION 0x6c
41,20 → 43,26
 
#ifdef __ASM__
.macro FAST_INSTRUCTION_ACCESS_MMU_MISS_HANDLER
save %sp, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
call fast_instruction_access_mmu_miss
nop
restore
retry
.endm
 
.macro FAST_DATA_ACCESS_MMU_MISS_HANDLER
save %sp, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
call fast_data_access_mmu_miss
nop
restore
retry
.endm
 
.macro FAST_DATA_ACCESS_PROTECTION_HANDLER
save %sp, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
call fast_data_access_protection
nop
restore
retry
.endm
#endif /* __ASM__ */
/kernel/trunk/arch/sparc64/include/trap/trap.h
40,6 → 40,5
}
 
extern void trap_init(void);
extern void trap_install_handler(index_t tt, size_t len, bool tlnonz);
 
#endif
/kernel/trunk/arch/sparc64/include/barrier.h
47,7 → 47,12
* As such, it may trap if the address is not found in DTLB.
* However, JPS1 implementations are free to ignore the trap.
*/
__asm__ volatile ("flush %sp\n");
/*
* %i7 should provide address that is always mapped in DTLB
* as it is a pointer to kernel code.
*/
__asm__ volatile ("flush %i7\n");
}
 
/** Memory Barrier instruction. */
/kernel/trunk/arch/sparc64/Makefile.inc
57,6 → 57,8
CONFIG_ASID = y
CONFIG_ASID_FIFO = y
 
CONFIG_FB = y
 
ARCH_SOURCES = \
arch/$(ARCH)/src/cpu/cpu.c \
arch/$(ARCH)/src/asm.S \
/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();