source: trunk/packages/xen-3.1/xen-3.1/xen/arch/powerpc/external.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 7.0 KB
Line 
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
15 *
16 * Copyright (C) IBM Corp. 2005, 2006
17 *
18 * Authors: Jimi Xenidis <jimix@watson.ibm.com>
19 */
20
21#include <xen/config.h>
22#include <xen/types.h>
23#include <xen/sched.h>
24#include <xen/lib.h>
25#include <xen/event.h>
26#include <xen/irq.h>
27#include <public/xen.h>
28#include <asm/current.h>
29#include <asm/hardirq.h>
30#include <asm/mpic.h>
31#include "mpic_init.h"
32#include "exceptions.h"
33
34#undef DEBUG
35#ifdef DEBUG
36#define DBG(fmt...) printk(fmt)
37#else
38#define DBG(fmt...)
39#endif
40
41int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
42
43unsigned long io_apic_irqs;
44int ioapic_ack_new = 1;
45
46static struct hw_interrupt_type *hc_irq;
47
48/* deliver_ee: called with interrupts off when resuming every vcpu */
49void deliver_ee(struct cpu_user_regs *regs)
50{
51    const ulong srr_mask = ~(MSR_IR | MSR_DR | MSR_FE0 | MSR_FE1 | MSR_EE |
52                             MSR_RI |
53                             MSR_BE | MSR_FP | MSR_PMM | MSR_PR | MSR_SE);
54
55    BUG_ON(mfmsr() & MSR_EE);
56    BUG_ON(regs->msr & MSR_HV);
57
58    if (!local_events_need_delivery())
59        return;
60
61    /* XXX OS error: EE was set but RI was not. We could trigger a machine
62     * check, or kill the domain... for now just crash Xen so we notice. */
63    BUG_ON(!(regs->msr & MSR_RI));
64
65    regs->srr0 = regs->pc;
66    /* zero SRR1[33:36] and SRR1[42:47] */
67    regs->srr1 = regs->msr & ~0x00000000783f0000;
68    regs->pc = 0x500;
69    regs->msr &= srr_mask;
70    regs->msr |= MSR_SF | MSR_ME;
71
72    DBG("<HV: pc=0x%lx, msr=0x%lx\n", regs->pc, regs->msr);
73}
74
75void do_external(struct cpu_user_regs *regs)
76{
77    int vec;
78    static unsigned spur_count;
79
80    BUG_ON(!(regs->msr & MSR_EE));
81    BUG_ON(mfmsr() & MSR_EE);
82
83    vec = xen_mpic_get_irq(regs);
84
85    if (irq_desc[vec].status & IRQ_PER_CPU) {
86        /* x86 do_IRQ does not respect the per cpu flag.  */
87        irq_desc_t *desc = &irq_desc[vec];
88        regs->entry_vector = vec;
89        desc->handler->ack(vec);
90        desc->action->handler(vector_to_irq(vec), desc->action->dev_id, regs);
91        desc->handler->end(vec);
92    } else if (vec != -1) {
93        DBG("EE:0x%lx isrc: %d\n", regs->msr, vec);
94        regs->entry_vector = vec;
95        do_IRQ(regs);
96
97        BUG_ON(mfmsr() & MSR_EE);
98        spur_count = 0;
99    } else {
100        ++spur_count;
101        if (spur_count > 100)
102            panic("Too many (%d) spurrious interrupts in a row\n"
103                  "  Known problem, please halt and let machine idle/cool "
104                  "  then reboot\n",
105                  100);
106    }
107}
108
109static int xen_local_irq(unsigned int irq)
110{
111    irq_desc_t *desc;
112    unsigned int vector;
113
114    vector = irq_to_vector(irq);
115    desc = &irq_desc[vector];
116
117    return !(desc->status & IRQ_GUEST);
118}
119
120static unsigned int xen_startup_irq(unsigned int irq)
121{
122    DBG("%s(%d)\n", __func__, irq);
123    if (xen_local_irq(irq)) {
124        return hc_irq->startup(irq);
125    }
126    return 0;
127}
128
129static void xen_shutdown_irq(unsigned int irq)
130{
131    DBG("%s(%d)\n", __func__, irq);
132    if (xen_local_irq(irq)) {
133        hc_irq->shutdown(irq);
134    }
135}
136
137static void xen_enable_irq(unsigned int irq)
138{
139    DBG("%s(%d)\n", __func__, irq);
140    if (xen_local_irq(irq)) {
141        hc_irq->enable(irq);
142    }
143}
144
145static void xen_disable_irq(unsigned int irq)
146{
147    DBG("%s(%d)\n", __func__, irq);
148    if (xen_local_irq(irq)) {
149        hc_irq->disable(irq);
150    }
151}
152   
153static void xen_ack_irq(unsigned int irq)
154{
155    DBG("%s(%d)\n", __func__, irq);
156    if (xen_local_irq(irq)) {
157        if (hc_irq->ack) hc_irq->ack(irq);
158    }
159}
160
161static void xen_end_irq(unsigned int irq)
162{
163    DBG("%s(%d)\n", __func__, irq);
164    if (xen_local_irq(irq)) {
165        hc_irq->end(irq);
166    }
167}
168
169static void xen_set_affinity(unsigned int irq, cpumask_t mask)
170{
171    DBG("%s(%d)\n", __func__, irq);
172    if (xen_local_irq(irq)) {
173        if (hc_irq->set_affinity) hc_irq->set_affinity(irq, mask);
174    }
175}
176
177static struct hw_interrupt_type xen_irq = {
178    .startup = xen_startup_irq,
179    .enable = xen_enable_irq,
180    .disable = xen_disable_irq,
181    .shutdown = xen_shutdown_irq,
182    .ack = xen_ack_irq,
183    .end = xen_end_irq,
184    .set_affinity = xen_set_affinity,
185};
186
187void init_IRQ(void)
188{
189    hc_irq = xen_mpic_init(&xen_irq);
190}
191
192void ack_APIC_irq(void)
193{
194    panic("%s: EOI the whole MPIC?\n", __func__);
195}
196
197void ack_bad_irq(unsigned int irq)
198{
199    printk("unexpected IRQ trap at vector %02x\n", irq);
200    /*
201     * Currently unexpected vectors happen only on SMP and APIC.
202     * We _must_ ack these because every local APIC has only N
203     * irq slots per priority level, and a 'hanging, unacked' IRQ
204     * holds up an irq slot - in excessive cases (when multiple
205     * unexpected vectors occur) that might lock up the APIC
206     * completely.
207     */
208    ack_APIC_irq();
209}
210
211extern void dump_ioapic_irq_info(void);
212void dump_ioapic_irq_info(void)
213{
214    printk("%s: can't dump yet\n", __func__);
215}
216
217/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
218u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
219int assign_irq_vector(int irq)
220{
221    static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
222
223    BUG_ON(irq >= NR_IRQ_VECTORS);
224    if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
225        return IO_APIC_VECTOR(irq);
226next:
227    current_vector += 8;
228
229    /* Skip the hypercall vector. */
230    if (current_vector == HYPERCALL_VECTOR)
231        goto next;
232
233    /* Skip the Linux/BSD fast-trap vector. */
234    if (current_vector == FAST_TRAP)
235        goto next;
236
237    if (current_vector >= FIRST_SYSTEM_VECTOR) {
238        offset++;
239        if (!(offset%8))
240            return -ENOSPC;
241        current_vector = FIRST_DEVICE_VECTOR + offset;
242    }
243
244    vector_irq[current_vector] = irq;
245    if (irq != AUTO_ASSIGN)
246        IO_APIC_VECTOR(irq) = current_vector;
247
248    return current_vector;
249}
250
251int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval)
252{
253    BUG_ON(pval != pval);
254
255    return 0;
256}
257
258int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
259{
260    BUG_ON(val != val);
261    return 0;
262}
263
264void send_IPI_mask(cpumask_t mask, int vector)
265{
266    unsigned int cpus;
267    int const bits = 8 * sizeof(cpus);
268
269    switch(vector) {
270    case CALL_FUNCTION_VECTOR:
271    case EVENT_CHECK_VECTOR:
272        break;
273    default:
274        BUG();
275        return;
276    }
277
278    BUG_ON(NR_CPUS > bits);
279    BUG_ON(fls(mask.bits[0]) > bits);
280
281    cpus = mask.bits[0];
282    mpic_send_ipi(vector, cpus);
283}
Note: See TracBrowser for help on using the repository browser.