Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 1902 → Rev 1903

/trunk/kernel/kernel.config
71,7 → 71,7
! [(ARCH=ia32|ARCH=amd64)&CONFIG_FB=y] CONFIG_VESA_BPP (choice)
 
# Support for SMP
! [ARCH=ia32|ARCH=amd64|ARCH=xen32] CONFIG_SMP (y/n)
! [ARCH=ia32|ARCH=amd64|ARCH=xen32|ARCH=sparc64] CONFIG_SMP (y/n)
 
# Improved support for hyperthreading
! [(ARCH=ia32|ARCH=amd64|ARCH=xen32)&CONFIG_SMP=y] CONFIG_HT (y/n)
/trunk/kernel/arch/sparc64/include/interrupt.h
40,11 → 40,13
#include <arch/types.h>
#include <arch/regdef.h>
 
#define IRQ_COUNT 1 /* TODO */
#define IRQ_COUNT 1 /* TODO */
 
#define IVT_ITEMS 15
#define IVT_FIRST 1
 
#define VECTOR_TLB_SHOOTDOWN_IPI 0 /* TODO */
 
struct istate {
uint64_t tnpc;
uint64_t tpc;
/trunk/kernel/arch/sparc64/include/regdef.h
55,6 → 55,9
#define WSTATE_NORMAL(n) (n)
#define WSTATE_OTHER(n) ((n)<<3)
 
#define UPA_CONFIG_MID_SHIFT 17
#define UPA_CONFIG_MID_MASK 0x1f
 
#endif
 
/** @}
/trunk/kernel/arch/sparc64/include/atomic.h
96,8 → 96,9
static inline long test_and_set(atomic_t *val)
{
uint64_t v = 1;
volatile uintptr_t x = (uint64_t) &val->count;
 
__asm__ volatile ("casx %0, %2, %1\n" : "+m" (*val), "+r" (v) : "r" (0));
__asm__ volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *) x)), "+r" (v) : "r" (0));
 
return v;
}
107,6 → 108,8
uint64_t tmp1 = 1;
uint64_t tmp2;
 
volatile uintptr_t x = (uint64_t) &val->count;
 
__asm__ volatile (
"0:\n"
"casx %0, %3, %1\n"
119,7 → 122,7
"ba 1b\n"
"nop\n"
"2:\n"
: "+m" (*val), "+r" (tmp1), "+r" (tmp2) : "r" (0)
: "+m" (*((uint64_t *) x)), "+r" (tmp1), "+r" (tmp2) : "r" (0)
);
/*
/trunk/kernel/arch/sparc64/include/cpu.h
35,6 → 35,7
#ifndef KERN_sparc64_CPU_H_
#define KERN_sparc64_CPU_H_
 
#include <arch/types.h>
#include <arch/register.h>
 
#define MANUF_FUJITSU 0x04
51,8 → 52,9
#define IMPL_SPARC64V 0x5
 
struct cpu_arch {
uint32_t mid; /**< Processor ID as read from UPA_CONFIG. */
ver_reg_t ver;
uint32_t clock_frequency;
uint32_t clock_frequency; /**< Processor frequency in MHz. */
};
#endif
/trunk/kernel/arch/sparc64/Makefile.inc
70,6 → 70,10
 
CONFIG_OFW_TREE = y
 
ifeq ($(CONFIG_SMP),y)
DEFS += -DCONFIG_SMP
endif
 
ARCH_SOURCES = \
arch/$(ARCH)/src/cpu/cpu.c \
arch/$(ARCH)/src/asm.S \
98,6 → 102,12
arch/$(ARCH)/src/drivers/kbd.c \
arch/$(ARCH)/src/drivers/scr.c
 
ifeq ($(CONFIG_SMP),y)
ARCH_SOURCES += \
arch/$(ARCH)/src/smp/ipi.c \
arch/$(ARCH)/src/smp/smp.c
endif
 
ifeq ($(CONFIG_TSB),y)
ARCH_SOURCES += \
arch/$(ARCH)/src/mm/tsb.c
/trunk/kernel/arch/sparc64/src/smp/smp.c
0,0 → 1,109
/*
* Copyright (C) 2006 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.
*/
 
/** @addtogroup sparc64
* @{
*/
/** @file
*/
 
#include <smp/smp.h>
#include <genarch/ofw/ofw_tree.h>
#include <cpu.h>
#include <arch/cpu.h>
#include <arch.h>
#include <config.h>
#include <macros.h>
#include <arch/types.h>
#include <synch/synch.h>
#include <synch/waitq.h>
#include <typedefs.h>
#include <print.h>
 
/**
* This global variable is used to pick-up application processors
* from their active loop in start.S. When a processor looping in
* start.S sees that this variable contains its MID, it can
* proceed with its initialization.
*
* This variable is modified only by the bootstrap processor.
* Other processors access it read-only.
*/
volatile uint64_t waking_up_mid = (uint64_t) -1;
 
/** Determine number of processors. */
void smp_init(void)
{
ofw_tree_node_t *node;
count_t cnt = 0;
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
while (node) {
cnt++;
node = ofw_tree_find_peer_by_device_type(node, "cpu");
}
config.cpu_count = max(1, cnt);
}
 
/** Wake application processors up. */
void kmp(void *arg)
{
ofw_tree_node_t *node;
int i;
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
for (i = 0; node; node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++) {
uint32_t mid;
ofw_tree_property_t *prop;
prop = ofw_tree_getprop(node, "upa-portid");
if (!prop || !prop->value)
continue;
mid = *((uint32_t *) prop->value);
if (CPU->arch.mid == mid) {
/*
* Skip the current CPU.
*/
continue;
}
 
/*
* Processor with ID == mid can proceed with its initialization.
*/
waking_up_mid = mid;
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);
}
}
 
/** @}
*/
/trunk/kernel/arch/sparc64/src/smp/ipi.c
0,0 → 1,43
/*
* Copyright (C) 2006 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.
*/
 
/** @addtogroup sparc64
* @{
*/
/** @file
*/
 
#include <smp/ipi.h>
 
void ipi_broadcast_arch(int ipi)
{
/* TODO */
}
 
/** @}
*/
/trunk/kernel/arch/sparc64/src/sparc64.c
70,12 → 70,14
 
void arch_pre_mm_init(void)
{
trap_init();
if (config.cpu_active == 1)
trap_init();
}
 
void arch_post_mm_init(void)
{
standalone_sparc64_console_init();
if (config.cpu_active == 1)
standalone_sparc64_console_init();
}
 
void arch_post_cpu_init(void)
90,13 → 92,15
{
thread_t *t;
 
/*
* Create thread that polls keyboard.
*/
t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll");
if (!t)
panic("cannot create kkbdpoll\n");
thread_ready(t);
if (config.cpu_active == 1) {
/*
* Create thread that polls keyboard.
*/
t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll");
if (!t)
panic("cannot create kkbdpoll\n");
thread_ready(t);
}
}
 
/** Calibrate delay loop.
/trunk/kernel/arch/sparc64/src/cpu/cpu.c
50,6 → 50,8
upa_config_t upa_config;
upa_config.value = upa_config_read();
CPU->arch.mid = upa_config.mid;
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
while (node) {
ofw_tree_property_t *prop;
57,7 → 59,7
prop = ofw_tree_getprop(node, "upa-portid");
if (prop && prop->value) {
mid = *((uint32_t *) prop->value);
if (mid == upa_config.mid) {
if (mid == CPU->arch.mid) {
prop = ofw_tree_getprop(node, "clock-frequency");
if (prop && prop->value)
clock_frequency = *((uint32_t *) prop->value);
78,6 → 80,8
 
/** Print version information for a processor.
*
* This function is called by the bootstrap processor.
*
* @param m Processor structure of the CPU for which version information is to be printed.
*/
void cpu_print_report(cpu_t *m)
84,50 → 88,50
{
char *manuf, *impl;
 
switch (CPU->arch.ver.manuf) {
case MANUF_FUJITSU:
switch (m->arch.ver.manuf) {
case MANUF_FUJITSU:
manuf = "Fujitsu";
break;
case MANUF_ULTRASPARC:
case MANUF_ULTRASPARC:
manuf = "UltraSPARC";
break;
case MANUF_SUN:
case MANUF_SUN:
manuf = "Sun";
break;
default:
default:
manuf = "Unknown";
break;
}
switch (CPU->arch.ver.impl) {
case IMPL_ULTRASPARCI:
case IMPL_ULTRASPARCI:
impl = "UltraSPARC I";
break;
case IMPL_ULTRASPARCII:
case IMPL_ULTRASPARCII:
impl = "UltraSPARC II";
break;
case IMPL_ULTRASPARCII_I:
case IMPL_ULTRASPARCII_I:
impl = "UltraSPARC IIi";
break;
case IMPL_ULTRASPARCII_E:
case IMPL_ULTRASPARCII_E:
impl = "UltraSPARC IIe";
break;
case IMPL_ULTRASPARCIII:
case IMPL_ULTRASPARCIII:
impl = "UltraSPARC III";
break;
case IMPL_ULTRASPARCIV_PLUS:
case IMPL_ULTRASPARCIV_PLUS:
impl = "UltraSPARC IV+";
break;
case IMPL_SPARC64V:
case IMPL_SPARC64V:
impl = "SPARC 64V";
break;
default:
default:
impl = "Unknown";
break;
}
 
printf("cpu%d: manuf=%s, impl=%s, mask=%d (%dMHz)\n",
CPU->id, manuf, impl, CPU->arch.ver.mask, CPU->arch.clock_frequency/1000000);
m->id, manuf, impl, m->arch.ver.mask, m->arch.clock_frequency/1000000);
}
 
/** @}
/trunk/kernel/arch/sparc64/src/mm/as.c
37,6 → 37,7
#include <genarch/mm/as_ht.h>
#include <genarch/mm/asid_fifo.h>
#include <debug.h>
#include <config.h>
 
#ifdef CONFIG_TSB
#include <arch/mm/tsb.h>
51,8 → 52,10
/** Architecture dependent address space init. */
void as_arch_init(void)
{
as_operations = &as_ht_operations;
asid_fifo_init();
if (config.cpu_active == 1) {
as_operations = &as_ht_operations;
asid_fifo_init();
}
}
 
int as_constructor_arch(as_t *as, int flags)
/trunk/kernel/arch/sparc64/src/mm/frame.c
53,21 → 53,23
int i;
pfn_t confdata;
 
for (i = 0; i < bootinfo.memmap.count; i++) {
uintptr_t start = bootinfo.memmap.zones[i].start;
size_t size = bootinfo.memmap.zones[i].size;
if (config.cpu_active == 1) {
for (i = 0; i < bootinfo.memmap.count; i++) {
uintptr_t start = bootinfo.memmap.zones[i].start;
size_t size = bootinfo.memmap.zones[i].size;
 
/*
* The memmap is created by HelenOS boot loader.
* It already contains no holes.
*/
/*
* The memmap is created by HelenOS boot loader.
* It already contains no holes.
*/
confdata = ADDR2PFN(start);
if (confdata == 0)
confdata = 2;
zone_create(ADDR2PFN(start), SIZE2FRAMES(ALIGN_DOWN(size, FRAME_SIZE)), confdata, 0);
confdata = ADDR2PFN(start);
if (confdata == 0)
confdata = 2;
zone_create(ADDR2PFN(start), SIZE2FRAMES(ALIGN_DOWN(size, FRAME_SIZE)), confdata, 0);
last_frame = max(last_frame, start + ALIGN_UP(size, FRAME_SIZE));
last_frame = max(last_frame, start + ALIGN_UP(size, FRAME_SIZE));
}
}
 
}
/trunk/kernel/arch/sparc64/src/mm/page.c
40,10 → 40,45
#include <bitops.h>
#include <debug.h>
#include <align.h>
#include <config.h>
 
#ifdef CONFIG_SMP
/** Entries locked in DTLB of BSP.
*
* Application processors need to have the same locked entries
* in their DTLBs as the bootstrap processor.
*/
static struct {
uintptr_t virt_page;
uintptr_t phys_page;
int pagesize_code;
} bsp_locked_dtlb_entry[DTLB_ENTRY_COUNT];
 
/** Number of entries in bsp_locked_dtlb_entry array. */
static count_t bsp_locked_dtlb_entries = 0;
#endif /* CONFIG_SMP */
 
/** Perform sparc64 specific initialization of paging. */
void page_arch_init(void)
{
page_mapping_operations = &ht_mapping_operations;
if (config.cpu_active == 1) {
page_mapping_operations = &ht_mapping_operations;
} else {
 
#ifdef CONFIG_SMP
int i;
 
/*
* Copy locked DTLB entries from the BSP.
*/
for (i = 0; i < bsp_locked_dtlb_entries; i++) {
dtlb_insert_mapping(bsp_locked_dtlb_entry[i].virt_page,
bsp_locked_dtlb_entry[i].phys_page, bsp_locked_dtlb_entry[i].pagesize_code,
true, false);
}
#endif
 
}
}
 
/** Map memory-mapped device into virtual memory.
67,8 → 102,10
unsigned int order;
int i;
 
ASSERT(config.cpu_active == 1);
 
struct {
int pagesize;
int pagesize_code;
size_t increment;
count_t count;
} sizemap[] = {
101,11 → 138,25
uintptr_t virtaddr = ALIGN_UP(last_frame, 1<<(order + FRAME_WIDTH));
last_frame = ALIGN_UP(virtaddr + size, 1<<(order + FRAME_WIDTH));
for (i = 0; i < sizemap[order].count; i++)
for (i = 0; i < sizemap[order].count; i++) {
/*
* First, insert the mapping into DTLB.
*/
dtlb_insert_mapping(virtaddr + i*sizemap[order].increment,
physaddr + i*sizemap[order].increment,
sizemap[order].pagesize, true, false);
sizemap[order].pagesize_code, true, false);
#ifdef CONFIG_SMP
/*
* Second, save the information about the mapping for APs.
*/
bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].virt_page = virtaddr + i*sizemap[order].increment;
bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].phys_page = physaddr + i*sizemap[order].increment;
bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].pagesize_code = sizemap[order].pagesize_code;
bsp_locked_dtlb_entries++;
#endif
}
return virtaddr;
}
 
/trunk/kernel/arch/sparc64/src/start.S
26,6 → 26,7
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
#include <arch/arch.h>
#include <arch/regdef.h>
#include <arch/boot/boot.h>
 
33,6 → 34,10
#include <arch/mm/tlb.h>
#include <arch/mm/tte.h>
 
#ifdef CONFIG_SMP
#include <arch/context_offset.h>
#endif
 
.register %g2, #scratch
.register %g3, #scratch
 
226,7 → 231,8
! set TL back to 0
wrpr %g0, 0, %tl
 
brz %l7, 2f ! skip if you are not the bootstrap CPU
brz %l7, 1f ! skip if you are not the bootstrap CPU
nop
 
call arch_pre_main
nop
236,6 → 242,48
 
/* Not reached. */
 
0:
ba 0b
nop
 
 
/*
* Read MID from the processor.
*/
1:
ldxa [%g0] ASI_UPA_CONFIG, %g1
srlx %g1, UPA_CONFIG_MID_SHIFT, %g1
and %g1, UPA_CONFIG_MID_MASK, %g1
 
/*
* Active loop for APs until the BSP picks them up.
* A processor cannot leave the loop until the
* global variable 'waking_up_mid' equals its
* MID.
*/
set waking_up_mid, %g2
2:
b 2b
ldx [%g2], %g3
cmp %g3, %g1
bne 2b
nop
 
#ifdef CONFIG_SMP
/*
* Configure stack for the AP.
* The AP is expected to use the stack saved
* in the ctx global variable.
*/
set ctx, %g1
add %g1, OFFSET_SP, %g1
ldx [%g1], %o6
 
call main_ap
nop
#endif
 
/* Not reached. */
0:
ba 0b
nop