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