messaging.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Copyright 2010 Tilera Corporation. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation, version 2.
  7. *
  8. * This program is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  11. * NON INFRINGEMENT. See the GNU General Public License for
  12. * more details.
  13. */
  14. #include <linux/percpu.h>
  15. #include <linux/smp.h>
  16. #include <linux/hardirq.h>
  17. #include <linux/ptrace.h>
  18. #include <asm/hv_driver.h>
  19. #include <asm/irq_regs.h>
  20. #include <asm/traps.h>
  21. #include <hv/hypervisor.h>
  22. #include <arch/interrupts.h>
  23. /* All messages are stored here */
  24. static DEFINE_PER_CPU(HV_MsgState, msg_state);
  25. void init_messaging(void)
  26. {
  27. /* Allocate storage for messages in kernel space */
  28. HV_MsgState *state = this_cpu_ptr(&msg_state);
  29. int rc = hv_register_message_state(state);
  30. if (rc != HV_OK)
  31. panic("hv_register_message_state: error %d", rc);
  32. /* Make sure downcall interrupts will be enabled. */
  33. arch_local_irq_unmask(INT_INTCTRL_K);
  34. }
  35. void hv_message_intr(struct pt_regs *regs, int intnum)
  36. {
  37. /*
  38. * We enter with interrupts disabled and leave them disabled,
  39. * to match expectations of called functions (e.g.
  40. * do_ccupdate_local() in mm/slab.c). This is also consistent
  41. * with normal call entry for device interrupts.
  42. */
  43. int message[HV_MAX_MESSAGE_SIZE/sizeof(int)];
  44. HV_RcvMsgInfo rmi;
  45. int nmsgs = 0;
  46. /* Track time spent here in an interrupt context */
  47. struct pt_regs *old_regs = set_irq_regs(regs);
  48. irq_enter();
  49. #ifdef CONFIG_DEBUG_STACKOVERFLOW
  50. /* Debugging check for stack overflow: less than 1/8th stack free? */
  51. {
  52. long sp = stack_pointer - (long) current_thread_info();
  53. if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
  54. pr_emerg("%s: stack overflow: %ld\n",
  55. __func__, sp - sizeof(struct thread_info));
  56. dump_stack();
  57. }
  58. }
  59. #endif
  60. while (1) {
  61. HV_MsgState *state = this_cpu_ptr(&msg_state);
  62. rmi = hv_receive_message(*state, (HV_VirtAddr) message,
  63. sizeof(message));
  64. if (rmi.msglen == 0)
  65. break;
  66. if (rmi.msglen < 0)
  67. panic("hv_receive_message failed: %d", rmi.msglen);
  68. ++nmsgs;
  69. if (rmi.source == HV_MSG_TILE) {
  70. int tag;
  71. /* we just send tags for now */
  72. BUG_ON(rmi.msglen != sizeof(int));
  73. tag = message[0];
  74. #ifdef CONFIG_SMP
  75. evaluate_message(message[0]);
  76. #else
  77. panic("Received IPI message %d in UP mode", tag);
  78. #endif
  79. } else if (rmi.source == HV_MSG_INTR) {
  80. HV_IntrMsg *him = (HV_IntrMsg *)message;
  81. struct hv_driver_cb *cb =
  82. (struct hv_driver_cb *)him->intarg;
  83. cb->callback(cb, him->intdata);
  84. __this_cpu_inc(irq_stat.irq_hv_msg_count);
  85. }
  86. }
  87. /*
  88. * We shouldn't have gotten a message downcall with no
  89. * messages available.
  90. */
  91. if (nmsgs == 0)
  92. panic("Message downcall invoked with no messages!");
  93. /*
  94. * Track time spent against the current process again and
  95. * process any softirqs if they are waiting.
  96. */
  97. irq_exit();
  98. set_irq_regs(old_regs);
  99. }