Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 1898 → Rev 1899

/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
/trunk/boot/genarch/ofw.h
90,7 → 90,6
 
extern uintptr_t ofw_cif;
 
 
extern phandle ofw_chosen;
extern ihandle ofw_stdout;
extern phandle ofw_root;
113,6 → 112,7
extern int ofw_package_to_path(const phandle device, char *buf, const int buflen);
 
extern int ofw(ofw_args_t *arg);
extern unsigned long ofw_call(const char *service, const int nargs, const int nret, ofw_arg_t *rets, ...);
extern unsigned int ofw_get_address_cells(const phandle device);
extern unsigned int ofw_get_size_cells(const phandle device);
extern void *ofw_translate(const void *virt);
/trunk/boot/genarch/ofw.c
83,7 → 83,7
*
* @return Return value returned by the client interface.
*/
static unsigned long ofw_call(const char *service, const int nargs, const int nret, ofw_arg_t *rets, ...)
unsigned long ofw_call(const char *service, const int nargs, const int nret, ofw_arg_t *rets, ...)
{
va_list list;
ofw_args_t args;
/trunk/boot/arch/sparc64/loader/ofwarch.h
34,8 → 34,6
#define OFW_ADDRESS_CELLS 2
#define OFW_SIZE_CELLS 2
 
extern int bpp2align[];
extern int ofw_cpu(void);
 
extern int ofw_cpu(cpu_t *cpu);
 
#endif
/trunk/boot/arch/sparc64/loader/asm.S
100,6 → 100,7
mov %o0, %l1
mov %o1, %o0
mov %o2, %o1
mov %o3, %o2
jmp %l1 ! jump to kernel
nop
 
/trunk/boot/arch/sparc64/loader/main.c
36,8 → 36,6
#include "ofwarch.h"
#include <align.h>
 
#define KERNEL_VIRTUAL_ADDRESS 0x400000
 
bootinfo_t bootinfo;
 
void bootstrap(void)
57,11 → 55,7
halt();
}
if (!ofw_cpu(&bootinfo.cpu))
printf("Error: unable to get cpu properties\n");
 
printf("\nDevice info\n");
printf(" cpu: %dMHz\n", bootinfo.cpu.clock_frequency/1000000);
printf("\nSystem info\n");
printf(" memory: %dM\n", bootinfo.memmap.total>>20);
 
printf("\nMemory statistics\n");
96,6 → 90,11
bootinfo.ofw_root = ofw_tree_build();
printf("done.\n");
 
printf("\nChecking for secondary processors...");
if (!ofw_cpu())
printf("Error: unable to get cpu properties\n");
printf("done.\n");
 
printf("\nBooting the kernel...\n");
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS, &bootinfo, sizeof(bootinfo));
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS, 1, &bootinfo, sizeof(bootinfo));
}
/trunk/boot/arch/sparc64/loader/asm.h
35,6 → 35,6
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt))
 
extern void halt(void);
extern void jump_to_kernel(void *entry, void *bootinfo, unsigned int bootinfo_size) __attribute__((noreturn));
extern void jump_to_kernel(void *entry, int bsp, void *bootinfo, unsigned int bootinfo_size) __attribute__((noreturn));
 
#endif
/trunk/boot/arch/sparc64/loader/main.h
34,6 → 34,8
#include <balloc.h>
#include <types.h>
 
#define KERNEL_VIRTUAL_ADDRESS 0x400000
 
#define TASKMAP_MAX_RECORDS 32
 
typedef struct {
47,13 → 49,8
} taskmap_t;
 
typedef struct {
uint32_t clock_frequency;
} cpu_t;
 
typedef struct {
taskmap_t taskmap;
memmap_t memmap;
cpu_t cpu;
ballocs_t ballocs;
ofw_tree_node_t *ofw_root;
} bootinfo_t;
/trunk/boot/arch/sparc64/loader/ofwarch.c
53,7 → 53,12
return flag != -1;
}
 
int ofw_cpu(cpu_t *cpu)
 
#define ASI_UPA_CONFIG 0x4a
#define UPA_CONFIG_MID_SHIFT 17
#define UPA_CONFIG_MID_MASK 0x1f
 
int ofw_cpu(void)
{
char type_name[BUF_SIZE];
 
61,22 → 66,32
node = ofw_get_child_node(ofw_root);
if (node == 0 || node == -1) {
printf("Could not find any child nodes of the root node.\n");
return;
return 0;
}
uint64_t current_mid;
__asm__ volatile ("ldxa [%1] %2, %0\n" : "=r" (current_mid) : "r" (0), "i" (ASI_UPA_CONFIG));
current_mid >>= UPA_CONFIG_MID_SHIFT;
current_mid &= UPA_CONFIG_MID_MASK;
for (; node != 0 && node != -1; node = ofw_get_peer_node(node)) {
if (ofw_get_property(node, "device_type", type_name, sizeof(type_name)) > 0) {
if (strcmp(type_name, "cpu") == 0) {
uint32_t mhz;
uint32_t mid;
if (ofw_get_property(node, "clock-frequency", &mhz, sizeof(mhz)) <= 0)
if (ofw_get_property(node, "upa-portid", &mid, sizeof(mid)) <= 0)
continue;
cpu->clock_frequency = mhz;
return 1;
if (current_mid != mid) {
/*
* Start secondary processor.
*/
(void) ofw_call("SUNW,start-cpu", 3, 1, NULL, node, KERNEL_VIRTUAL_ADDRESS, 0);
}
}
}
};
}
 
return 0;
return 1;
}