/trunk/kernel/genarch/include/ofw/ofw_tree.h |
---|
128,6 → 128,9 |
extern const char *ofw_tree_node_name(const ofw_tree_node_t *node); |
extern ofw_tree_node_t *ofw_tree_lookup(const char *path); |
extern ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *node, const char *name); |
extern ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node, const char *name); |
extern ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *device_type); |
extern ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *device_type); |
extern bool ofw_fhc_apply_ranges(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uintptr_t *pa); |
extern bool ofw_central_apply_ranges(ofw_tree_node_t *node, ofw_central_reg_t *reg, uintptr_t *pa); |
/trunk/kernel/genarch/src/ofw/ofw_tree.c |
---|
97,7 → 97,7 |
* |
* @return NULL if there is no such child or pointer to the matching child node. |
*/ |
static ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node, const char *name) |
ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node, const char *name) |
{ |
ofw_tree_node_t *cur; |
124,6 → 124,53 |
return NULL; |
} |
/** Lookup first child of given device type. |
* |
* @param node Node whose child is being looked up. |
* @param name Device type of the child being looked up. |
* |
* @return NULL if there is no such child or pointer to the matching child node. |
*/ |
ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *name) |
{ |
ofw_tree_node_t *cur; |
ofw_tree_property_t *prop; |
for (cur = node->child; cur; cur = cur->peer) { |
prop = ofw_tree_getprop(cur, "device_type"); |
if (!prop || !prop->value) |
continue; |
if (strcmp(prop->value, name) == 0) |
return cur; |
} |
return NULL; |
} |
/** Lookup first peer of given device type. |
* |
* @param node Node whose peer is being looked up. |
* @param name Device type of the child being looked up. |
* |
* @return NULL if there is no such child or pointer to the matching child node. |
*/ |
ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *name) |
{ |
ofw_tree_node_t *cur; |
ofw_tree_property_t *prop; |
for (cur = node->peer; cur; cur = cur->peer) { |
prop = ofw_tree_getprop(cur, "device_type"); |
if (!prop || !prop->value) |
continue; |
if (strcmp(prop->value, name) == 0) |
return cur; |
} |
return NULL; |
} |
/** Lookup OpenFirmware node by its path. |
* |
* @param path Path to the node. |
/trunk/kernel/arch/sparc64/include/boot/boot.h |
---|
70,10 → 70,6 |
memzone_t zones[MEMMAP_MAX_RECORDS]; |
} memmap_t; |
typedef struct { |
uint32_t clock_frequency; |
} processor_t; |
/** Bootinfo structure. |
* |
* Must be in sync with bootinfo structure used by the boot loader. |
81,7 → 77,6 |
typedef struct { |
taskmap_t taskmap; |
memmap_t memmap; |
processor_t processor; |
ballocs_t ballocs; |
ofw_tree_node_t *ofw_root; |
} bootinfo_t; |
/trunk/kernel/arch/sparc64/include/arch.h |
---|
37,10 → 37,10 |
#ifndef KERN_sparc64_ARCH_H_ |
#define KERN_sparc64_ARCH_H_ |
#define ASI_AIUP 0x10 /** Access to primary context with user privileges. */ |
#define ASI_AIUS 0x11 /** Access to secondary context with user privileges. */ |
#define ASI_AIUP 0x10 /** Access to primary context with user privileges. */ |
#define ASI_AIUS 0x11 /** Access to secondary context with user privileges. */ |
#define ASI_NUCLEUS_QUAD_LDD 0x24 /** ASI for 16-byte atomic loads. */ |
#define ASI_UPA_CONFIG 0x4a /** ASI of the UPA_CONFIG register. */ |
#define NWINDOW 8 /** Number of register window sets. */ |
/trunk/kernel/arch/sparc64/include/asm.h |
---|
358,6 → 358,15 |
__asm__ volatile ("wrpr %g0, %g0, %tl\n"); |
} |
/** Read UPA_CONFIG register. |
* |
* @return Value of the UPA_CONFIG register. |
*/ |
static inline uint64_t upa_config_read(void) |
{ |
return asi_u64_read(ASI_UPA_CONFIG, 0); |
} |
extern void cpu_halt(void); |
extern void cpu_sleep(void); |
extern void asm_delay_loop(const uint32_t usec); |
/trunk/kernel/arch/sparc64/include/register.h |
---|
117,6 → 117,23 |
}; |
typedef union fprs_reg fprs_reg_t; |
/** UPA_CONFIG register. |
* |
* Note that format of this register differs significantly from |
* processor version to version. The format defined here |
* is the common subset for all supported processor versions. |
*/ |
union upa_config { |
uint64_t value; |
struct { |
uint64_t : 34; |
unsigned pcon : 8; /**< Processor configuration. */ |
unsigned mid : 5; /**< Module (processor) ID register. */ |
unsigned pcap : 17; /**< Processor capabilities. */ |
} __attribute__ ((packed)); |
}; |
typedef union upa_config upa_config_t; |
#endif |
/** @} |
/trunk/kernel/arch/sparc64/src/sparc64.c |
---|
37,7 → 37,6 |
#include <config.h> |
#include <arch/trap/trap.h> |
#include <arch/console.h> |
#include <arch/drivers/tick.h> |
#include <proc/thread.h> |
#include <console/console.h> |
#include <arch/boot/boot.h> |
72,7 → 71,6 |
void arch_pre_mm_init(void) |
{ |
trap_init(); |
tick_init(); |
} |
void arch_post_mm_init(void) |
/trunk/kernel/arch/sparc64/src/cpu/cpu.c |
---|
35,20 → 35,51 |
#include <arch/asm.h> |
#include <cpu.h> |
#include <arch.h> |
#include <print.h> |
#include <arch/register.h> |
#include <print.h> |
#include <arch/boot/boot.h> |
#include <genarch/ofw/ofw_tree.h> |
#include <arch/types.h> |
#include <arch/drivers/tick.h> |
/** Perform sparc64 specific initialization of the processor structure for the current processor. */ |
void cpu_arch_init(void) |
{ |
CPU->arch.clock_frequency = bootinfo.processor.clock_frequency; |
ofw_tree_node_t *node; |
uint32_t mid; |
uint32_t clock_frequency = 0; |
upa_config_t upa_config; |
upa_config.value = upa_config_read(); |
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu"); |
while (node) { |
ofw_tree_property_t *prop; |
prop = ofw_tree_getprop(node, "upa-portid"); |
if (prop && prop->value) { |
mid = *((uint32_t *) prop->value); |
if (mid == upa_config.mid) { |
prop = ofw_tree_getprop(node, "clock-frequency"); |
if (prop && prop->value) |
clock_frequency = *((uint32_t *) prop->value); |
} |
} |
node = ofw_tree_find_peer_by_device_type(node, "cpu"); |
} |
CPU->arch.clock_frequency = clock_frequency; |
tick_init(); |
} |
/** Read version information from the current processor. */ |
void cpu_identify(void) |
{ |
CPU->arch.ver.value = ver_read(); |
} |
/** Print version information for a processor. |
* |
* @param m Processor structure of the CPU for which version information is to be printed. |
*/ |
void cpu_print_report(cpu_t *m) |
{ |
char *manuf, *impl; |
/trunk/kernel/arch/sparc64/src/drivers/tick.c |
---|
52,7 → 52,7 |
interrupt_register(14, "tick_int", tick_interrupt); |
compare.int_dis = false; |
compare.tick_cmpr = bootinfo.processor.clock_frequency/HZ; |
compare.tick_cmpr = CPU->arch.clock_frequency/HZ; |
tick_compare_write(compare.value); |
tick_write(0); |
} |
/trunk/kernel/arch/sparc64/src/start.S |
---|
43,8 → 43,9 |
* from the boot loader. |
* |
* The registers are expected to be in this state: |
* - %o0 bootinfo structure address |
* - %o1 bootinfo structure size |
* - %o0 non-zero for the bootstrup processor, zero for application/secondary processors |
* - %o1 bootinfo structure address |
* - %o2 bootinfo structure size |
* |
* Moreover, we depend on boot having established the |
* following environment: |
55,6 → 56,8 |
.global kernel_image_start |
kernel_image_start: |
brz %o0, kernel_image_start ! block secondary processors |
nop |
/* |
* Setup basic runtime environment. |
72,8 → 75,6 |
* Copy the bootinfo structure passed from the boot loader |
* to the kernel bootinfo structure. |
*/ |
mov %o1, %o2 |
mov %o0, %o1 |
sethi %hi(bootinfo), %o0 |
call memcpy |
or %o0, %lo(bootinfo), %o0 |