Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4637 → Rev 4638

/branches/sparc/kernel/generic/src/main/kinit.c
190,7 → 190,7
printf("Init binary %" PRIc " not used (error %d)\n", i, rd);
}
}
 
/*
* Run user tasks with reasonable delays
*/
200,6 → 200,7
program_ready(&programs[i]);
}
}
 
#ifdef CONFIG_KCONSOLE
if (!stdin) {
printf("kinit: No stdin\nKernel alive: ");
/branches/sparc/kernel/generic/src/mm/tlb.c
84,6 → 84,7
unsigned int i;
 
CPU->tlb_active = 0;
 
spinlock_lock(&tlblock);
for (i = 0; i < config.cpu_count; i++) {
118,11 → 119,11
}
tlb_shootdown_ipi_send();
 
busy_wait:
for (i = 0; i < config.cpu_count; i++)
for (i = 0; i < config.cpu_count; i++) {
if (cpus[i].tlb_active)
goto busy_wait;
}
}
 
/** Finish TLB shootdown sequence. */
/branches/sparc/kernel/arch/sparc64/include/sun4v/md.h
54,6 → 54,8
const char *md_get_node_name(md_node_t node);
bool md_get_integer_property(md_node_t node, const char *key,
uint64_t *result);
bool md_get_string_property(md_node_t node, const char *key,
const char **result);
bool md_next_node(md_node_t *node, const char *name);
void md_init(void);
 
/branches/sparc/kernel/arch/sparc64/include/sun4v/ipi.h
0,0 → 1,47
/*
* Copyright (c) 2009 Pavel Rimsky
* 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
* @brief sun4v-specific IPI functions
*/
 
#ifndef KERN_sparc64_sun4v_IPI_H_
#define KERN_sparc64_sun4v_IPI_H_
 
uint64_t ipi_brodcast_to(void (*func)(void), uint16_t cpu_list[MAX_NUM_STRANDS],
uint64_t list_size);
uint64_t ipi_unicast_to(void (*func)(void), uint16_t cpu_id);
 
#endif
 
/** @}
*/
/branches/sparc/kernel/arch/sparc64/include/sun4v/hypercall.h
51,6 → 51,7
#define CPU_START 0x10
#define CPU_STOP 0x11
#define CPU_YIELD 0x12
#define CPU_QCONF 0x14
#define CPU_MYID 0x16
#define CPU_STATE 0x17
#define CPU_SET_RTBA 0x18
/branches/sparc/kernel/arch/sparc64/include/trap/sun4v/interrupt.h
0,0 → 1,50
/*
* Copyright (c) 2005 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 sparc64interrupt
* @{
*/
/**
* @file
* @brief This file contains interrupt vector trap handler.
*/
 
#ifndef KERN_sparc64_TRAP_SUN4V_INTERRUPT_H_
#define KERN_sparc64_TRAP_SUN4V_INTERRUPT_H_
 
#ifndef __ASM__
 
void sun4v_ipi_init(void);
void cpu_mondo(void);
 
#endif
 
#endif
 
/** @}
*/
/branches/sparc/kernel/arch/sparc64/include/trap/sun4v/mmu.h
54,6 → 54,7
#define TT_FAST_INSTRUCTION_ACCESS_MMU_MISS 0x64
#define TT_FAST_DATA_ACCESS_MMU_MISS 0x68
#define TT_FAST_DATA_ACCESS_PROTECTION 0x6c
#define TT_CPU_MONDO 0x7c
 
#define FAST_MMU_HANDLER_SIZE 128
 
/branches/sparc/kernel/arch/sparc64/include/trap/interrupt.h
31,69 → 31,12
*/
/**
* @file
* @brief This file contains interrupt vector trap handler.
* @brief This file contains level N interrupt and inter-processor interrupt
* trap handler.
*/
#ifndef KERN_sparc64_INTERRUPT_TRAP_H_
#define KERN_sparc64_INTERRUPT_TRAP_H_
 
#ifndef KERN_sparc64_TRAP_INTERRUPT_H_
#define KERN_sparc64_TRAP_INTERRUPT_H_
 
#include <arch/trap/trap_table.h>
#include <arch/stack.h>
 
/* IMAP register bits */
#define IGN_MASK 0x7c0
#define INO_MASK 0x1f
#define IMAP_V_MASK (1ULL << 31)
 
#define IGN_SHIFT 6
 
 
/* Interrupt ASI registers. */
#define ASI_INTR_W 0x77
#define ASI_INTR_DISPATCH_STATUS 0x48
#define ASI_INTR_R 0x7f
#define ASI_INTR_RECEIVE 0x49
 
/* VA's used with ASI_INTR_W register. */
#if defined (US)
#define ASI_UDB_INTR_W_DATA_0 0x40
#define ASI_UDB_INTR_W_DATA_1 0x50
#define ASI_UDB_INTR_W_DATA_2 0x60
#elif defined (US3)
#define VA_INTR_W_DATA_0 0x40
#define VA_INTR_W_DATA_1 0x48
#define VA_INTR_W_DATA_2 0x50
#define VA_INTR_W_DATA_3 0x58
#define VA_INTR_W_DATA_4 0x60
#define VA_INTR_W_DATA_5 0x68
#define VA_INTR_W_DATA_6 0x80
#define VA_INTR_W_DATA_7 0x88
#endif
#define VA_INTR_W_DISPATCH 0x70
 
/* VA's used with ASI_INTR_R register. */
#if defined(US)
#define ASI_UDB_INTR_R_DATA_0 0x40
#define ASI_UDB_INTR_R_DATA_1 0x50
#define ASI_UDB_INTR_R_DATA_2 0x60
#elif defined (US3)
#define VA_INTR_R_DATA_0 0x40
#define VA_INTR_R_DATA_1 0x48
#define VA_INTR_R_DATA_2 0x50
#define VA_INTR_R_DATA_3 0x58
#define VA_INTR_R_DATA_4 0x60
#define VA_INTR_R_DATA_5 0x68
#define VA_INTR_R_DATA_6 0x80
#define VA_INTR_R_DATA_7 0x88
#endif
 
/* Shifts in the Interrupt Vector Dispatch virtual address. */
#define INTR_VEC_DISPATCH_MID_SHIFT 14
 
/* Bits in the Interrupt Dispatch Status register. */
#define INTR_DISPATCH_STATUS_NACK 0x2
#define INTR_DISPATCH_STATUS_BUSY 0x1
 
#define TT_INTERRUPT_LEVEL_1 0x41
#define TT_INTERRUPT_LEVEL_2 0x42
#define TT_INTERRUPT_LEVEL_3 0x43
110,22 → 53,23
#define TT_INTERRUPT_LEVEL_14 0x4e
#define TT_INTERRUPT_LEVEL_15 0x4f
 
#define TT_INTERRUPT_VECTOR_TRAP 0x60
 
#define INTERRUPT_LEVEL_N_HANDLER_SIZE TRAP_TABLE_ENTRY_SIZE
#define INTERRUPT_VECTOR_TRAP_HANDLER_SIZE TRAP_TABLE_ENTRY_SIZE
 
/* IMAP register bits */
#define IGN_MASK 0x7c0
#define INO_MASK 0x1f
#define IMAP_V_MASK (1ULL << 31)
 
#define IGN_SHIFT 6
 
 
#ifdef __ASM__
.macro INTERRUPT_LEVEL_N_HANDLER n
mov \n - 1, %g2
PREEMPTIBLE_HANDLER exc_dispatch
.endm
#endif
 
.macro INTERRUPT_VECTOR_TRAP_HANDLER
PREEMPTIBLE_HANDLER interrupt
.endm
#endif /* __ASM__ */
 
#ifndef __ASM__
 
#include <arch/interrupt.h>
133,7 → 77,14
extern void interrupt(int n, istate_t *istate);
#endif /* !def __ASM__ */
 
 
#if defined (SUN4U)
#include <arch/trap/sun4u/interrupt.h>
#elif defined (SUN4V)
#include <arch/trap/sun4v/interrupt.h>
#endif
 
#endif
 
/** @}
*/
/branches/sparc/kernel/arch/sparc64/include/trap/mmu.h
34,8 → 34,8
* @brief This file contains fast MMU trap handlers.
*/
 
#ifndef KERN_sparc64_sun4u_MMU_TRAP_H_
#define KERN_sparc64_sun4u_MMU_TRAP_H_
#ifndef KERN_sparc64_MMU_TRAP_H_
#define KERN_sparc64_MMU_TRAP_H_
 
#if defined (SUN4U)
#include <arch/trap/sun4u/mmu.h>
/branches/sparc/kernel/arch/sparc64/include/trap/sun4u/interrupt.h
0,0 → 1,104
/*
* Copyright (c) 2005 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 sparc64interrupt
* @{
*/
/**
* @file
* @brief This file contains interrupt vector trap handler.
*/
 
#ifndef KERN_sparc64_TRAP_SUN4U_INTERRUPT_H_
#define KERN_sparc64_TRAP_SUN4U_INTERRUPT_H_
 
#include <arch/trap/trap_table.h>
#include <arch/stack.h>
 
 
/* Interrupt ASI registers. */
#define ASI_INTR_W 0x77
#define ASI_INTR_DISPATCH_STATUS 0x48
#define ASI_INTR_R 0x7f
#define ASI_INTR_RECEIVE 0x49
 
/* VA's used with ASI_INTR_W register. */
#if defined (US)
#define ASI_UDB_INTR_W_DATA_0 0x40
#define ASI_UDB_INTR_W_DATA_1 0x50
#define ASI_UDB_INTR_W_DATA_2 0x60
#elif defined (US3)
#define VA_INTR_W_DATA_0 0x40
#define VA_INTR_W_DATA_1 0x48
#define VA_INTR_W_DATA_2 0x50
#define VA_INTR_W_DATA_3 0x58
#define VA_INTR_W_DATA_4 0x60
#define VA_INTR_W_DATA_5 0x68
#define VA_INTR_W_DATA_6 0x80
#define VA_INTR_W_DATA_7 0x88
#endif
#define VA_INTR_W_DISPATCH 0x70
 
/* VA's used with ASI_INTR_R register. */
#if defined(US)
#define ASI_UDB_INTR_R_DATA_0 0x40
#define ASI_UDB_INTR_R_DATA_1 0x50
#define ASI_UDB_INTR_R_DATA_2 0x60
#elif defined (US3)
#define VA_INTR_R_DATA_0 0x40
#define VA_INTR_R_DATA_1 0x48
#define VA_INTR_R_DATA_2 0x50
#define VA_INTR_R_DATA_3 0x58
#define VA_INTR_R_DATA_4 0x60
#define VA_INTR_R_DATA_5 0x68
#define VA_INTR_R_DATA_6 0x80
#define VA_INTR_R_DATA_7 0x88
#endif
 
/* Shifts in the Interrupt Vector Dispatch virtual address. */
#define INTR_VEC_DISPATCH_MID_SHIFT 14
 
/* Bits in the Interrupt Dispatch Status register. */
#define INTR_DISPATCH_STATUS_NACK 0x2
#define INTR_DISPATCH_STATUS_BUSY 0x1
 
#define TT_INTERRUPT_VECTOR_TRAP 0x60
 
#define INTERRUPT_VECTOR_TRAP_HANDLER_SIZE TRAP_TABLE_ENTRY_SIZE
 
#ifdef __ASM__
.macro INTERRUPT_VECTOR_TRAP_HANDLER
PREEMPTIBLE_HANDLER interrupt
.endm
#endif /* __ASM__ */
 
 
#endif
 
/** @}
*/
/branches/sparc/kernel/arch/sparc64/Makefile.inc
99,12 → 99,29
ifeq ($(MACHINE),sun4v)
USARCH = sun4v
DEFS += -DSUN4V
DEFS += -DUS3 # TODO: do not forget to remove this line, it is here only to make the code compilable even when the sun4v port is not fully implemented yet
endif
 
 
# sources which exist in two versions - one for sun4u and one for sun4v
# common sources and sources which exist in two versions - one for sun4u and one for sun4v
ARCH_SOURCES = \
arch/$(ARCH)/src/sparc64.c \
arch/$(ARCH)/src/console.c \
arch/$(ARCH)/src/panic.S \
arch/$(ARCH)/src/trap/trap.c \
arch/$(ARCH)/src/trap/exception.c \
arch/$(ARCH)/src/asm.S \
arch/$(ARCH)/src/drivers/kbd.c \
arch/$(ARCH)/src/context.S \
arch/$(ARCH)/src/fpu_context.c \
arch/$(ARCH)/src/dummy.s \
arch/$(ARCH)/src/mm/frame.c \
arch/$(ARCH)/src/mm/page.c \
arch/$(ARCH)/src/proc/thread.c \
arch/$(ARCH)/src/trap/interrupt.c \
arch/$(ARCH)/src/ddi/ddi.c \
arch/$(ARCH)/src/drivers/tick.c \
arch/$(ARCH)/src/drivers/scr.c \
arch/$(ARCH)/src/drivers/pci.c \
arch/$(ARCH)/src/$(USARCH)/start.S \
arch/$(ARCH)/src/trap/$(USARCH)/trap_table.S \
arch/$(ARCH)/src/$(USARCH)/asm.S \
113,7 → 130,8
arch/$(ARCH)/src/mm/$(USARCH)/tlb.c \
arch/$(ARCH)/src/mm/$(USARCH)/as.c \
arch/$(ARCH)/src/cpu/$(USARCH)/cpu.c \
arch/$(ARCH)/src/proc/$(USARCH)/scheduler.c
arch/$(ARCH)/src/proc/$(USARCH)/scheduler.c \
arch/$(ARCH)/src/trap/$(USARCH)/interrupt.c
 
ifeq ($(CONFIG_TSB),y)
ARCH_SOURCES += \
122,33 → 140,13
 
# specific to machine type
 
# sun4u-specific sources
ifeq ($(USARCH),sun4u)
ARCH_SOURCES += \
arch/$(ARCH)/src/mm/sun4u/cache.S
arch/$(ARCH)/src/mm/sun4u/cache.S \
arch/$(ARCH)/src/drivers/sgcn.c
endif
 
# sun4u-specific, not #ifdef'd yet in order to make the code compilable
ARCH_SOURCES += \
arch/$(ARCH)/src/asm.S \
arch/$(ARCH)/src/panic.S \
arch/$(ARCH)/src/console.c \
arch/$(ARCH)/src/context.S \
arch/$(ARCH)/src/fpu_context.c \
arch/$(ARCH)/src/dummy.s \
arch/$(ARCH)/src/mm/frame.c \
arch/$(ARCH)/src/mm/page.c \
arch/$(ARCH)/src/proc/thread.c \
arch/$(ARCH)/src/trap/trap.c \
arch/$(ARCH)/src/trap/exception.c \
arch/$(ARCH)/src/trap/interrupt.c \
arch/$(ARCH)/src/ddi/ddi.c \
arch/$(ARCH)/src/drivers/tick.c \
arch/$(ARCH)/src/drivers/kbd.c \
arch/$(ARCH)/src/drivers/scr.c \
arch/$(ARCH)/src/drivers/sgcn.c \
arch/$(ARCH)/src/sparc64.c \
arch/$(ARCH)/src/drivers/pci.c
 
# sun4v-specific sources
ifeq ($(USARCH),sun4v)
ARCH_SOURCES += \
159,12 → 157,12
 
ifeq ($(CONFIG_SMP),y)
ARCH_SOURCES += \
arch/$(ARCH)/src/smp/ipi.c \
arch/$(ARCH)/src/smp/$(USARCH)/smp.c
arch/$(ARCH)/src/smp/$(USARCH)/smp.c \
arch/$(ARCH)/src/smp/$(USARCH)/ipi.c
endif
 
 
ifdef CONFIG_Z8530
#ifdef CONFIG_Z8530
ARCH_SOURCES += \
arch/$(ARCH)/src/drivers/fhc.c
endif
#endif
/branches/sparc/kernel/arch/sparc64/src/sun4v/asm.S
40,6 → 40,7
*/
.global switch_to_userspace
switch_to_userspace:
wrpr PSTATE_PRIV_BIT, %pstate
save %o1, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
flushw
wrpr %g0, 0, %cleanwin ! avoid information leak
/branches/sparc/kernel/arch/sparc64/src/sun4v/md.c
145,6 → 145,32
}
 
/**
* Returns the value of the string property of the given node.
*
* @param
*/
bool md_get_string_property(md_node_t node, const char *key,
const char **result)
{
md_header_t *md_header = (md_header_t *) mach_desc;
element_idx_t idx = node;
 
while (get_element(idx)->tag != NODE_END) {
idx++;
md_element_t *element = get_element(idx);
if (element->tag == PROP_DATA &&
strcmp(key, get_element_name(idx)) == 0) {
*result = (char *) mach_desc + sizeof(md_header_t) +
md_header->node_blk_sz + md_header->name_blk_sz +
element->d.y.data_offset;
return true;
}
}
 
return false;
}
 
/**
* Moves the child oterator to the next child (following sibling of the node
* the oterator currently points to).
*
/branches/sparc/kernel/arch/sparc64/src/sun4v/start.S
131,6 → 131,7
 
wrpr %g0, 0, %tl ! TL = 0, primary context
! register is used
wrpr %g0, 0, %gl
 
wrpr %g0, PSTATE_PRIV_BIT, %pstate ! disable interrupts and disable
! 32-bit address masking
296,6 → 297,25
ba 0b
nop
 
.align 8
.global temp_cpu_mondo_handler
temp_cpu_mondo_handler:
 
set 0x3c, %o0
set 0x15, %o5
ta 0x80
 
mov 0, %o0
setx before_ap_boots, %g1, %o1
setx 0x80400000, %g1, %o2
add %o1, %o2, %o1
__HYPERCALL_FAST(MMU_ENABLE)
 
before_ap_boots:
setx 0x80400000, %g0, %o0
ba kernel_image_start
nop
 
.section K_DATA_START, "aw", @progbits
 
#define INITIAL_STACK_SIZE 1024
/branches/sparc/kernel/arch/sparc64/src/cpu/sun4v/cpu.c
40,6 → 40,7
#include <print.h>
#include <arch/sun4v/md.h>
#include <arch/sun4v/hypercall.h>
#include <arch/trap/sun4v/interrupt.h>
 
/** Perform sparc64 specific initialization of the processor structure for the
* current processor.
55,7 → 56,6
 
/* walk through MD, find the current CPU node & its clock-frequency */
while (true) {
 
if (!md_next_node(&node, "cpu")) {
panic("Could not determine CPU frequency.");
}
62,6 → 62,7
 
uint64_t id = 0;
md_get_integer_property(node, "id", &id);
 
if (id == myid) {
uint64_t clock_frequency = 0;
md_get_integer_property(node, "clock-frequency",
72,6 → 73,7
}
 
tick_init();
sun4v_ipi_init();
}
 
/**
/branches/sparc/kernel/arch/sparc64/src/smp/sun4v/smp.c
34,6 → 34,7
*/
 
#include <smp/smp.h>
#include <smp/ipi.h>
#include <genarch/ofw/ofw_tree.h>
#include <cpu.h>
#include <arch/cpu.h>
47,6 → 48,7
#include <print.h>
#include <arch/sun4v/hypercall.h>
#include <arch/sun4v/md.h>
#include <arch/sun4v/ipi.h>
#include <time/delay.h>
 
#define CPU_STATE_RUNNING 2
72,6 → 74,7
/** Wake application processors up. */
void kmp(void *arg)
{
#if 1
(void) arg;
 
uint64_t myid;
111,7 → 114,67
") timed out\n", __func__, i);
}
#else
 
asm volatile (
"setx temp_cpu_mondo_handler, %g4, %g6 \n"
//"setx 0x80246ad8, %g4, %g7 \n"
"setx 0x80200f80, %g4, %g7 \n"
 
"ldx [%g6], %g4 \n"
"stxa %g4, [%g7] 0x14 \n"
"membar #Sync \n"
 
"add %g7, 0x8, %g7 \n"
"ldx [%g6 + 0x8], %g4 \n"
"stxa %g4, [%g7] 0x14 \n"
"membar #Sync \n"
 
"add %g7, 0x8, %g7 \n"
"ldx [%g6 + 0x10], %g4 \n"
"stxa %g4, [%g7] 0x14 \n"
"membar #Sync \n"
 
"add %g7, 0x8, %g7 \n"
"ldx [%g6 + 0x18], %g4 \n"
"stxa %g4, [%g7] 0x14 \n"
"membar #Sync \n"
 
"add %g7, 0x8, %g7 \n"
"ldx [%g6 + 0x20], %g4 \n"
"stxa %g4, [%g7] 0x14 \n"
"membar #Sync \n"
 
"add %g7, 0x8, %g7 \n"
"ldx [%g6 + 0x28], %g4 \n"
"stxa %g4, [%g7] 0x14 \n"
"membar #Sync \n"
 
"add %g7, 0x8, %g7 \n"
"ldx [%g6 + 0x30], %g4 \n"
"stxa %g4, [%g7] 0x14 \n"
"membar #Sync \n"
 
"add %g7, 0x8, %g7 \n"
"ldx [%g6 + 0x38], %g4 \n"
"stxa %g4, [%g7] 0x14 \n"
"membar #Sync \n"
 
"add %g7, 0x8, %g7 \n"
"ldx [%g6 + 0x40], %g4 \n"
"stxa %g4, [%g7] 0x14 \n"
"membar #Sync \n"
 
"flush %i7"
 
);
delay(1000);
printf("Result: %d\n", ipi_unicast_to((void (*)(void)) 1234, 1));
if (waitq_sleep_timeout(&ap_completion_wq, 10000000, SYNCH_FLAGS_NONE) ==
ESYNCH_TIMEOUT)
printf("%s: waiting for processor (cpuid = %" PRIu32
") timed out\n", __func__, 1);
#endif
}
 
/** @}
/branches/sparc/kernel/arch/sparc64/src/smp/sun4v/ipi.c
0,0 → 1,123
/*
* 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>
#include <cpu.h>
#include <config.h>
#include <interrupt.h>
#include <arch/asm.h>
#include <arch/cpu.h>
#include <arch/sun4v/hypercall.h>
#include <arch/sun4v/ipi.h>
 
#define IPI_MESSAGE_SIZE 8
 
static uint64_t data[MAX_NUM_STRANDS][IPI_MESSAGE_SIZE]
__attribute__ ((aligned (64)));
 
static uint16_t ipi_cpu_list[MAX_NUM_STRANDS][MAX_NUM_STRANDS];
 
/**
* Sends an inter-processor interrupt to all virtual processors whose IDs are
* listed in the list.
*
* @param func address of the function to be invoked on the recipient
* @param cpu_list list of CPU IDs (16-bit identifiers) of the recipients
* @param list_size number of recipients (number of valid cpu_list entries)
*
* @return error code returned by the CPU_MONDO_SEND hypercall
*/
uint64_t ipi_brodcast_to(void (*func)(void), uint16_t cpu_list[MAX_NUM_STRANDS],
uint64_t list_size) {
 
data[CPU->arch.id][0] = (uint64_t) func;
 
unsigned int i;
for (i = 0; i < list_size; i++) {
ipi_cpu_list[CPU->arch.id][i] = cpu_list[i];
}
 
return __hypercall_fast3(CPU_MONDO_SEND, list_size,
KA2PA(ipi_cpu_list[CPU->arch.id]), KA2PA(data[CPU->arch.id]));
}
 
/**
* Send an inter-processor interrupt to a particular CPU.
*
* @param func address of the function to be invoked on the recipient
* @param cpu_is CPU ID (16-bit identifier) of the recipient
*
* @return error code returned by the CPU_MONDO_SEND hypercall
*/
uint64_t ipi_unicast_to(void (*func)(void), uint16_t cpu_id) {
ipi_cpu_list[CPU->arch.id][0] = cpu_id;
return ipi_brodcast_to(func, ipi_cpu_list[CPU->arch.id], 1);
}
 
/*
* Deliver IPI to all processors except the current one.
*
* We assume that interrupts are disabled.
*
* @param ipi IPI number.
*/
void ipi_broadcast_arch(int ipi)
{
void (* func)(void);
switch (ipi) {
case IPI_TLB_SHOOTDOWN:
func = tlb_shootdown_ipi_recv;
break;
default:
panic("Unknown IPI (%d).\n", ipi);
break;
}
 
unsigned int i;
unsigned idx = 0;
for (i = 0; i < config.cpu_active; i++) {
if (&cpus[i] == CPU) {
continue;
}
 
ipi_cpu_list[CPU->id][idx] = (uint16_t) cpus[i].id;
idx++;
}
 
ipi_brodcast_to(func, ipi_cpu_list[CPU->arch.id], idx);
}
 
/** @}
*/
/branches/sparc/kernel/arch/sparc64/src/smp/ipi.c
File deleted
/branches/sparc/kernel/arch/sparc64/src/smp/sun4u/ipi.c
0,0 → 1,174
/*
* 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>
#include <cpu.h>
#include <arch.h>
#include <arch/cpu.h>
#include <arch/asm.h>
#include <config.h>
#include <mm/tlb.h>
#include <arch/interrupt.h>
#include <arch/trap/interrupt.h>
#include <arch/barrier.h>
#include <preemption.h>
#include <time/delay.h>
#include <panic.h>
 
/** Set the contents of the outgoing interrupt vector data.
*
* The first data item (data 0) will be set to the value of func, the
* rest of the vector will contain zeros.
*
* This is a helper function used from within the cross_call function.
*
* @param func value the first data item of the vector will be set to
*/
static inline void set_intr_w_data(void (* func)(void))
{
#if defined (US)
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_0, (uintptr_t) func);
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
#elif defined (US3)
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_0, (uintptr_t) func);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_1, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_2, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_3, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_4, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_5, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_6, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_7, 0);
#endif
}
 
/** Invoke function on another processor.
*
* Currently, only functions without arguments are supported.
* Supporting more arguments in the future should be no big deal.
*
* Interrupts must be disabled prior to this call.
*
* @param mid MID of the target processor.
* @param func Function to be invoked.
*/
static void cross_call(int mid, void (* func)(void))
{
uint64_t status;
bool done;
 
/*
* This function might enable interrupts for a while.
* In order to prevent migration to another processor,
* we explicitly disable preemption.
*/
preemption_disable();
status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
if (status & INTR_DISPATCH_STATUS_BUSY)
panic("Interrupt Dispatch Status busy bit set\n");
ASSERT(!(pstate_read() & PSTATE_IE_BIT));
do {
set_intr_w_data(func);
asi_u64_write(ASI_INTR_W,
(mid << INTR_VEC_DISPATCH_MID_SHIFT) |
VA_INTR_W_DISPATCH, 0);
membar();
do {
status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
} while (status & INTR_DISPATCH_STATUS_BUSY);
done = !(status & INTR_DISPATCH_STATUS_NACK);
if (!done) {
/*
* Prevent deadlock.
*/
(void) interrupts_enable();
delay(20 + (tick_read() & 0xff));
(void) interrupts_disable();
}
} while (done);
preemption_enable();
}
 
/*
* Deliver IPI to all processors except the current one.
*
* The sparc64 architecture does not support any group addressing
* which is found, for instance, on ia32 and amd64. Therefore we
* need to simulate the broadcast by sending the message to
* all target processors step by step.
*
* We assume that interrupts are disabled.
*
* @param ipi IPI number.
*/
void ipi_broadcast_arch(int ipi)
{
unsigned int i;
void (* func)(void);
switch (ipi) {
case IPI_TLB_SHOOTDOWN:
func = tlb_shootdown_ipi_recv;
break;
default:
panic("Unknown IPI (%d).\n", ipi);
break;
}
/*
* As long as we don't support hot-plugging
* or hot-unplugging of CPUs, we can walk
* the cpus array and read processor's MID
* without locking.
*/
for (i = 0; i < config.cpu_active; i++) {
if (&cpus[i] == CPU)
continue; /* skip the current CPU */
 
cross_call(cpus[i].arch.mid, func);
}
}
 
/** @}
*/
/branches/sparc/kernel/arch/sparc64/src/trap/sun4v/interrupt.c
0,0 → 1,123
/*
* Copyright (c) 2009 Pavel Rimsky
* 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 sparc64interrupt
* @{
*/
/** @file
*/
 
#include <arch/interrupt.h>
#include <arch/trap/interrupt.h>
#include <arch/sparc64.h>
#include <arch/trap/interrupt.h>
#include <interrupt.h>
#include <ddi/irq.h>
#include <arch/types.h>
#include <debug.h>
#include <arch/asm.h>
#include <arch/barrier.h>
#include <print.h>
#include <arch.h>
#include <mm/tlb.h>
#include <config.h>
#include <synch/spinlock.h>
#include <arch/sun4v/hypercall.h>
 
/** number of uint64_t-s in one CPU mondo message */
#define CPU_MONDO_ENTRY_SIZE 8
 
/** number of entries (messages) in the CPU mondo queue */
#define CPU_MONDO_NENTRIES 8
 
/** number of uint64_t-s in the CPU mondo queue */
#define CPU_MONDO_QUEUE_SIZE ((CPU_MONDO_NENTRIES) * (CPU_MONDO_ENTRY_SIZE))
 
/** used to identify CPU mondo queue in the hypercall */
#define CPU_MONDO_QUEUE_ID 0x3c
 
/** ASI for reading/writing CPU mondo head/tail registers */
#define ASI_QUEUE 0x25
 
/** VA for reading the CPU mondo tail */
#define VA_CPU_MONDO_QUEUE_TAIL 0x3c8
 
/** VA for reading/writing the CPU mondo head */
#define VA_CPU_MONDO_QUEUE_HEAD 0x3c0
 
/**
* array which contains CPU mondo queue for every CPU
*/
uint64_t cpu_mondo_queues[MAX_NUM_STRANDS][CPU_MONDO_QUEUE_SIZE]
__attribute__((aligned(
CPU_MONDO_QUEUE_SIZE * sizeof(uint64_t))));
 
/**
* Initializes CPU mondo queue for the current CPU.
*/
void sun4v_ipi_init(void)
{
if (__hypercall_fast3(
CPU_QCONF,
CPU_MONDO_QUEUE_ID,
KA2PA(cpu_mondo_queues[CPU->id]),
CPU_MONDO_NENTRIES) != EOK)
panic("Initializing mondo queue failed on CPU %d.\n",
CPU->arch.id);
}
 
/**
* Handler of the CPU Mondo trap. Reads the message queue, updates the head
* register and processes the message (invokes a function call).
*/
void cpu_mondo(void)
{
unsigned int tail = asi_u64_read(ASI_QUEUE, VA_CPU_MONDO_QUEUE_TAIL);
unsigned int head = asi_u64_read(ASI_QUEUE, VA_CPU_MONDO_QUEUE_HEAD);
 
while (head != tail) {
 
uint64_t data1 = cpu_mondo_queues[CPU->id][0];
 
head = (head + CPU_MONDO_ENTRY_SIZE * sizeof(uint64_t)) %
(CPU_MONDO_QUEUE_SIZE * sizeof(uint64_t));
asi_u64_write(ASI_QUEUE, VA_CPU_MONDO_QUEUE_HEAD, head);
 
if (data1 == (uint64_t) tlb_shootdown_ipi_recv) {
((void (*)(void)) data1)();
} else {
printf("Spurious interrupt on %d, data = %lx.\n",
CPU->arch.id, data1);
}
 
}
 
}
 
/** @}
*/
/branches/sparc/kernel/arch/sparc64/src/trap/sun4v/trap_table.S
321,12 → 321,6
interrupt_level_15_handler_tl0:
INTERRUPT_LEVEL_N_HANDLER 15
 
/* TT = 0x60, TL = 0, interrupt_vector_trap handler */
.org trap_table + TT_INTERRUPT_VECTOR_TRAP*ENTRY_SIZE
.global interrupt_vector_trap_handler_tl0
interrupt_vector_trap_handler_tl0:
INTERRUPT_VECTOR_TRAP_HANDLER
 
/* TT = 0x64, TL = 0, fast_instruction_access_MMU_miss */
.org trap_table + TT_FAST_INSTRUCTION_ACCESS_MMU_MISS*ENTRY_SIZE
.global fast_instruction_access_mmu_miss_handler_tl0
345,6 → 339,12
fast_data_access_protection_handler_tl0:
FAST_DATA_ACCESS_PROTECTION_HANDLER 0
 
/* TT = 0x7c, TL = 0, cpu_mondo */
.org trap_table + TT_CPU_MONDO*ENTRY_SIZE
.global cpu_mondo_handler_tl0
cpu_mondo_handler_tl0:
PREEMPTIBLE_HANDLER cpu_mondo
 
/* TT = 0x80, TL = 0, spill_0_normal handler */
.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
.global spill_0_normal_tl0
527,6 → 527,13
fast_data_access_protection_handler_tl1:
FAST_DATA_ACCESS_PROTECTION_HANDLER 1
 
/* TT = 0x7c, TL > 0, cpu_mondo */
.org trap_table + (TT_CPU_MONDO+512)*ENTRY_SIZE
.global cpu_mondo_handler_tl1
cpu_mondo_handler_tl1:
wrpr %g0, %tl
PREEMPTIBLE_HANDLER cpu_mondo
 
/* TT = 0x80, TL > 0, spill_0_normal handler */
.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
.global spill_0_normal_tl1
816,7 → 823,6
 
5:
restore
 
retry
.endm
 
/branches/sparc/kernel/arch/sparc64/src/trap/interrupt.c
1,5 → 1,6
/*
* Copyright (c) 2005 Jakub Jermar
* Copyright (c) 2009 Pavel Rimsky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
33,8 → 34,8
*/
 
#include <arch/interrupt.h>
#include <arch/trap/interrupt.h>
#include <arch/sparc64.h>
#include <arch/trap/interrupt.h>
#include <interrupt.h>
#include <ddi/irq.h>
#include <arch/types.h>
59,66 → 60,5
exc_register(n - 1, name, f);
}
 
/** Process hardware interrupt.
*
* @param n Ignored.
* @param istate Ignored.
*/
void interrupt(int n, istate_t *istate)
{
uint64_t status;
uint64_t intrcv;
uint64_t data0;
status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
if (status & (!INTR_DISPATCH_STATUS_BUSY))
panic("Interrupt Dispatch Status busy bit not set\n");
 
intrcv = asi_u64_read(ASI_INTR_RECEIVE, 0);
#if defined (US)
data0 = asi_u64_read(ASI_INTR_R, ASI_UDB_INTR_R_DATA_0);
#elif defined (US3)
data0 = asi_u64_read(ASI_INTR_R, VA_INTR_R_DATA_0);
#endif
 
irq_t *irq = irq_dispatch_and_lock(data0);
if (irq) {
/*
* The IRQ handler was found.
*/
irq->handler(irq, irq->arg);
/*
* See if there is a clear-interrupt-routine and call it.
*/
if (irq->cir) {
irq->cir(irq->cir_arg, irq->inr);
}
spinlock_unlock(&irq->lock);
} else if (data0 > config.base) {
/*
* This is a cross-call.
* data0 contains address of the kernel function.
* We call the function only after we verify
* it is one of the supported ones.
*/
#ifdef CONFIG_SMP
if (data0 == (uintptr_t) tlb_shootdown_ipi_recv) {
tlb_shootdown_ipi_recv();
}
#endif
} else {
/*
* Spurious interrupt.
*/
#ifdef CONFIG_DEBUG
printf("cpu%u: spurious interrupt (intrcv=%#" PRIx64
", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0);
#endif
}
 
membar();
asi_u64_write(ASI_INTR_RECEIVE, 0, 0);
}
 
/** @}
*/
/branches/sparc/kernel/arch/sparc64/src/trap/sun4u/interrupt.c
0,0 → 1,111
/*
* Copyright (c) 2005 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 sparc64interrupt
* @{
*/
/** @file
*/
 
#include <arch/interrupt.h>
#include <arch/sparc64.h>
#include <arch/trap/interrupt.h>
#include <interrupt.h>
#include <ddi/irq.h>
#include <arch/types.h>
#include <debug.h>
#include <arch/asm.h>
#include <arch/barrier.h>
#include <print.h>
#include <arch.h>
#include <mm/tlb.h>
#include <config.h>
#include <synch/spinlock.h>
 
/** Process hardware interrupt.
*
* @param n Ignored.
* @param istate Ignored.
*/
void interrupt(int n, istate_t *istate)
{
uint64_t status;
uint64_t intrcv;
uint64_t data0;
status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
if (status & (!INTR_DISPATCH_STATUS_BUSY))
panic("Interrupt Dispatch Status busy bit not set\n");
 
intrcv = asi_u64_read(ASI_INTR_RECEIVE, 0);
#if defined (US)
data0 = asi_u64_read(ASI_INTR_R, ASI_UDB_INTR_R_DATA_0);
#elif defined (US3)
data0 = asi_u64_read(ASI_INTR_R, VA_INTR_R_DATA_0);
#endif
 
irq_t *irq = irq_dispatch_and_lock(data0);
if (irq) {
/*
* The IRQ handler was found.
*/
irq->handler(irq, irq->arg);
/*
* See if there is a clear-interrupt-routine and call it.
*/
if (irq->cir) {
irq->cir(irq->cir_arg, irq->inr);
}
spinlock_unlock(&irq->lock);
} else if (data0 > config.base) {
/*
* This is a cross-call.
* data0 contains address of the kernel function.
* We call the function only after we verify
* it is one of the supported ones.
*/
#ifdef CONFIG_SMP
if (data0 == (uintptr_t) tlb_shootdown_ipi_recv) {
tlb_shootdown_ipi_recv();
}
#endif
} else {
/*
* Spurious interrupt.
*/
#ifdef CONFIG_DEBUG
printf("cpu%u: spurious interrupt (intrcv=%#" PRIx64
", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0);
#endif
}
 
membar();
asi_u64_write(ASI_INTR_RECEIVE, 0, 0);
}
 
/** @}
*/
/branches/sparc/kernel/arch/sparc64/src/drivers/tick.c
58,7 → 58,7
CPU->arch.next_tick_cmpr = compare.tick_cmpr;
tick_compare_write(compare.value);
 
#if defined (US3)
#if defined (US3) || defined (SUN4V)
/* disable STICK interrupts and clear any pending ones */
tick_compare_reg_t stick_compare;
softint_reg_t clear;
/branches/sparc/kernel/arch/sparc64/src/sun4u/asm.S
78,6 → 78,7
*/
.global switch_to_userspace
switch_to_userspace:
save %o1, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
flushw
wrpr %g0, 0, %cleanwin ! avoid information leak