summaryrefslogtreecommitdiff
path: root/core/minute-ia/interrupts.c
diff options
context:
space:
mode:
authorHyungwoo Yang <hyungwoo.yang@intel.com>2019-04-15 22:17:11 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-04-26 04:19:18 -0700
commitf730c0c1ab2cadb820676ef09ebb57888d48cb96 (patch)
tree8953f42e6776f828c0f55cc2c01d44c087a43511 /core/minute-ia/interrupts.c
parent6549da39d519b4d07e8bca7bef0393549765412b (diff)
downloadchrome-ec-f730c0c1ab2cadb820676ef09ebb57888d48cb96.tar.gz
ish: fix s/w generated interrupt request
Current s/w generated IRQ uses LAPIC's ICR but it causes pending interrupts for other IRQs in IOAPIC and leads LVT error with illegal vector. So instead of using ICR, we use "int" instruction. BRANCH=none BUG=b:129937881,b:124128140 TEST=Tested on Arcada platform Change-Id: I49c4120e7355f9a98d20d5ed259c4fdf6bad5196 Signed-off-by: Hyungwoo Yang <hyungwoo.yang@intel.com> Signed-off-by: Jett Rink <jettrink@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1568786 Commit-Ready: Jack Rosenthal <jrosenth@chromium.org> Reviewed-by: Jack Rosenthal <jrosenth@chromium.org>
Diffstat (limited to 'core/minute-ia/interrupts.c')
-rw-r--r--core/minute-ia/interrupts.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/core/minute-ia/interrupts.c b/core/minute-ia/interrupts.c
index 87926a9736..a08e02de90 100644
--- a/core/minute-ia/interrupts.c
+++ b/core/minute-ia/interrupts.c
@@ -349,6 +349,11 @@ __asm__ (
"movl %esp, %eax\n"
"movl $stack_end, %esp\n"
"push %eax\n"
+#ifdef CONFIG_TASK_PROFILING
+ "push $" STRINGIFY(CONFIG_IRQ_COUNT) "\n"
+ "call task_start_irq_handler\n"
+ "addl $0x04, %esp\n"
+#endif
"call handle_lapic_lvt_error\n"
"pop %esp\n"
"movl $0x00, (0xFEE000B0)\n" /* Set EOI for LAPIC */
@@ -369,6 +374,30 @@ void unhandled_vector(void)
/* This needs to be moved to link_defs.h */
extern const struct irq_data __irq_data[], __irq_data_end[];
+/**
+ * Called from SOFTIRQ_VECTOR when software is trigger an IRQ manually
+ *
+ * If IRQ is out of range, then no routine should be called
+ */
+void call_irq_service_routine(uint32_t irq)
+{
+ const struct irq_data *p = __irq_data;
+
+ /* If just rescheduling a task, we won't have a routine to call */
+ if (irq >= CONFIG_IRQ_COUNT)
+ return;
+
+ for (; p < __irq_data_end; p++) {
+ if (p->irq == irq) {
+ p->routine();
+ break;
+ }
+ }
+
+ if (p == __irq_data_end)
+ CPRINTS("IRQ %d routine not found!", irq);
+}
+
void init_interrupts(void)
{
unsigned entry;
@@ -378,7 +407,11 @@ void init_interrupts(void)
/* Setup gates for IRQs declared by drivers using DECLARE_IRQ */
for (; p < __irq_data_end; p++)
- set_interrupt_gate(IRQ_TO_VEC(p->irq), p->routine, IDT_DESC_FLAGS);
+ set_interrupt_gate(IRQ_TO_VEC(p->irq), p->ioapic_routine,
+ IDT_DESC_FLAGS);
+
+ /* Software generated IRQ */
+ set_interrupt_gate(SOFTIRQ_VECTOR, sw_irq_handler, IDT_DESC_FLAGS);
/* Setup gate for LAPIC_LVT_ERROR vector; clear any remnant error. */
REG32(LAPIC_ESR_REG) = 0;