1867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* 2867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Copyright 2010 Tilera Corporation. All Rights Reserved. 3867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 4867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This program is free software; you can redistribute it and/or 5867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * modify it under the terms of the GNU General Public License 6867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * as published by the Free Software Foundation, version 2. 7867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 8867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This program is distributed in the hope that it will be useful, but 9867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * WITHOUT ANY WARRANTY; without even the implied warranty of 10867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 11867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * NON INFRINGEMENT. See the GNU General Public License for 12867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * more details. 13867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 14867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 15867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/percpu.h> 16867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/smp.h> 17867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/hardirq.h> 18867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/ptrace.h> 19867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/hv_driver.h> 20867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/irq_regs.h> 210707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf#include <asm/traps.h> 22867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <hv/hypervisor.h> 23867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <arch/interrupts.h> 24867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 25867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* All messages are stored here */ 26867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic DEFINE_PER_CPU(HV_MsgState, msg_state); 27867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 280707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalfvoid __cpuinit init_messaging(void) 29867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 30867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Allocate storage for messages in kernel space */ 31867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf HV_MsgState *state = &__get_cpu_var(msg_state); 32867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int rc = hv_register_message_state(state); 33867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (rc != HV_OK) 34867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf panic("hv_register_message_state: error %d", rc); 35867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 36867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Make sure downcall interrupts will be enabled. */ 375d966115de84c22cd4df029cb00be0e51fab6c10Chris Metcalf arch_local_irq_unmask(INT_INTCTRL_K); 38867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 39867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 40867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfvoid hv_message_intr(struct pt_regs *regs, int intnum) 41867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 42867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 43867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * We enter with interrupts disabled and leave them disabled, 44867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * to match expectations of called functions (e.g. 45867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * do_ccupdate_local() in mm/slab.c). This is also consistent 46867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * with normal call entry for device interrupts. 47867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 48867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 49867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int message[HV_MAX_MESSAGE_SIZE/sizeof(int)]; 50867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf HV_RcvMsgInfo rmi; 51867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int nmsgs = 0; 52867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 53867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Track time spent here in an interrupt context */ 54867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf struct pt_regs *old_regs = set_irq_regs(regs); 55867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf irq_enter(); 56867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 57867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#ifdef CONFIG_DEBUG_STACKOVERFLOW 58867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Debugging check for stack overflow: less than 1/8th stack free? */ 59867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf { 60867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf long sp = stack_pointer - (long) current_thread_info(); 61867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { 620707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf pr_emerg("hv_message_intr: " 63867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf "stack overflow: %ld\n", 64867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sp - sizeof(struct thread_info)); 65867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf dump_stack(); 66867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 67867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 68867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif 69867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 70867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf while (1) { 71867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf rmi = hv_receive_message(__get_cpu_var(msg_state), 72867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (HV_VirtAddr) message, 73867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sizeof(message)); 74867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (rmi.msglen == 0) 75867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 76867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 77867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (rmi.msglen < 0) 78867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf panic("hv_receive_message failed: %d", rmi.msglen); 79867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 80867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf ++nmsgs; 81867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 82867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (rmi.source == HV_MSG_TILE) { 83867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int tag; 84867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 85867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* we just send tags for now */ 86867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(rmi.msglen != sizeof(int)); 87867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 88867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf tag = message[0]; 89867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#ifdef CONFIG_SMP 90867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf evaluate_message(message[0]); 91867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#else 92867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf panic("Received IPI message %d in UP mode", tag); 93867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif 94867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else if (rmi.source == HV_MSG_INTR) { 95867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf HV_IntrMsg *him = (HV_IntrMsg *)message; 96867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf struct hv_driver_cb *cb = 97867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (struct hv_driver_cb *)him->intarg; 98867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf cb->callback(cb, him->intdata); 99867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf __get_cpu_var(irq_stat).irq_hv_msg_count++; 100867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 101867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 102867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 103867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 104867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * We shouldn't have gotten a message downcall with no 105867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * messages available. 106867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 107867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (nmsgs == 0) 108867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf panic("Message downcall invoked with no messages!"); 109867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 110867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 111867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Track time spent against the current process again and 112867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * process any softirqs if they are waiting. 113867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 114867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf irq_exit(); 115867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf set_irq_regs(old_regs); 116867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 117