/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 |