messaging.c revision 867e359b97c970a60626d5d76bbe2a8fadbf38fb
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> 21867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <hv/hypervisor.h> 22867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <arch/interrupts.h> 23867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 24867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* All messages are stored here */ 25867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic DEFINE_PER_CPU(HV_MsgState, msg_state); 26867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 27867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfvoid __cpuinit init_messaging() 28867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 29867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Allocate storage for messages in kernel space */ 30867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf HV_MsgState *state = &__get_cpu_var(msg_state); 31867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int rc = hv_register_message_state(state); 32867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (rc != HV_OK) 33867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf panic("hv_register_message_state: error %d", rc); 34867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 35867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Make sure downcall interrupts will be enabled. */ 36867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf raw_local_irq_unmask(INT_INTCTRL_1); 37867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 38867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 39867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfvoid hv_message_intr(struct pt_regs *regs, int intnum) 40867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 41867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 42867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * We enter with interrupts disabled and leave them disabled, 43867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * to match expectations of called functions (e.g. 44867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * do_ccupdate_local() in mm/slab.c). This is also consistent 45867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * with normal call entry for device interrupts. 46867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 47867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 48867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int message[HV_MAX_MESSAGE_SIZE/sizeof(int)]; 49867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf HV_RcvMsgInfo rmi; 50867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int nmsgs = 0; 51867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 52867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Track time spent here in an interrupt context */ 53867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf struct pt_regs *old_regs = set_irq_regs(regs); 54867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf irq_enter(); 55867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 56867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#ifdef CONFIG_DEBUG_STACKOVERFLOW 57867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* Debugging check for stack overflow: less than 1/8th stack free? */ 58867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf { 59867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf long sp = stack_pointer - (long) current_thread_info(); 60867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { 61867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf printk(KERN_EMERG "hv_message_intr: " 62867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf "stack overflow: %ld\n", 63867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sp - sizeof(struct thread_info)); 64867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf dump_stack(); 65867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 66867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 67867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif 68867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 69867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf while (1) { 70867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf rmi = hv_receive_message(__get_cpu_var(msg_state), 71867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (HV_VirtAddr) message, 72867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf sizeof(message)); 73867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (rmi.msglen == 0) 74867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 75867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 76867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (rmi.msglen < 0) 77867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf panic("hv_receive_message failed: %d", rmi.msglen); 78867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 79867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf ++nmsgs; 80867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 81867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (rmi.source == HV_MSG_TILE) { 82867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int tag; 83867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 84867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* we just send tags for now */ 85867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf BUG_ON(rmi.msglen != sizeof(int)); 86867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 87867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf tag = message[0]; 88867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#ifdef CONFIG_SMP 89867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf evaluate_message(message[0]); 90867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#else 91867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf panic("Received IPI message %d in UP mode", tag); 92867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif 93867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } else if (rmi.source == HV_MSG_INTR) { 94867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf HV_IntrMsg *him = (HV_IntrMsg *)message; 95867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf struct hv_driver_cb *cb = 96867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf (struct hv_driver_cb *)him->intarg; 97867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf cb->callback(cb, him->intdata); 98867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf __get_cpu_var(irq_stat).irq_hv_msg_count++; 99867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 100867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 101867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 102867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 103867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * We shouldn't have gotten a message downcall with no 104867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * messages available. 105867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 106867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (nmsgs == 0) 107867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf panic("Message downcall invoked with no messages!"); 108867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 109867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf /* 110867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Track time spent against the current process again and 111867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * process any softirqs if they are waiting. 112867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 113867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf irq_exit(); 114867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf set_irq_regs(old_regs); 115867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 116