messaging.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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 <hv/hypervisor.h>
  21. #include <arch/interrupts.h>
  22. /* All messages are stored here */
  23. static DEFINE_PER_CPU(HV_MsgState, msg_state);
  24. void __cpuinit init_messaging()
  25. {
  26. /* Allocate storage for messages in kernel space */
  27. HV_MsgState *state = &__get_cpu_var(msg_state);
  28. int rc = hv_register_message_state(state);
  29. if (rc != HV_OK)
  30. panic("hv_register_message_state: error %d", rc);
  31. /* Make sure downcall interrupts will be enabled. */
  32. raw_local_irq_unmask(INT_INTCTRL_1);
  33. }
  34. void hv_message_intr(struct pt_regs *regs, int intnum)
  35. {
  36. /*
  37. * We enter with interrupts disabled and leave them disabled,
  38. * to match expectations of called functions (e.g.
  39. * do_ccupdate_local() in mm/slab.c). This is also consistent
  40. * with normal call entry for device interrupts.
  41. */
  42. int message[HV_MAX_MESSAGE_SIZE/sizeof(int)];
  43. HV_RcvMsgInfo rmi;
  44. int nmsgs = 0;
  45. /* Track time spent here in an interrupt context */
  46. struct pt_regs *old_regs = set_irq_regs(regs);
  47. irq_enter();
  48. #ifdef CONFIG_DEBUG_STACKOVERFLOW
  49. /* Debugging check for stack overflow: less than 1/8th stack free? */
  50. {
  51. long sp = stack_pointer - (long) current_thread_info();
  52. if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
  53. printk(KERN_EMERG "hv_message_intr: "
  54. "stack overflow: %ld\n",
  55. sp - sizeof(struct thread_info));
  56. dump_stack();
  57. }
  58. }
  59. #endif
  60. while (1) {
  61. rmi = hv_receive_message(__get_cpu_var(msg_state),
  62. (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. __get_cpu_var(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. }