debuggers.hg

view xen/arch/x86/hvm/vmsi.c @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children 5c0bf00e371d
line source
1 /*
2 * Copyright (C) 2001 MandrakeSoft S.A.
3 *
4 * MandrakeSoft S.A.
5 * 43, rue d'Aboukir
6 * 75002 Paris - France
7 * http://www.linux-mandrake.com/
8 * http://www.mandrakesoft.com/
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Support for virtual MSI logic
25 * Will be merged it with virtual IOAPIC logic, since most is the same
26 */
28 #include <xen/config.h>
29 #include <xen/types.h>
30 #include <xen/mm.h>
31 #include <xen/xmalloc.h>
32 #include <xen/lib.h>
33 #include <xen/errno.h>
34 #include <xen/sched.h>
35 #include <public/hvm/ioreq.h>
36 #include <asm/hvm/io.h>
37 #include <asm/hvm/vpic.h>
38 #include <asm/hvm/vlapic.h>
39 #include <asm/hvm/support.h>
40 #include <asm/current.h>
41 #include <asm/event.h>
43 static uint32_t vmsi_get_delivery_bitmask(
44 struct domain *d, uint16_t dest, uint8_t dest_mode)
45 {
46 uint32_t mask = 0;
47 struct vcpu *v;
49 HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
50 "dest %d dest_mode %d\n", dest, dest_mode);
52 if ( dest_mode == 0 ) /* Physical mode. */
53 {
54 if ( dest == 0xFF ) /* Broadcast. */
55 {
56 for_each_vcpu ( d, v )
57 mask |= 1 << v->vcpu_id;
58 goto out;
59 }
61 for_each_vcpu ( d, v )
62 {
63 if ( VLAPIC_ID(vcpu_vlapic(v)) == dest )
64 {
65 mask = 1 << v->vcpu_id;
66 break;
67 }
68 }
69 }
70 else if ( dest != 0 ) /* Logical mode, MDA non-zero. */
71 {
72 for_each_vcpu ( d, v )
73 if ( vlapic_match_logical_addr(vcpu_vlapic(v), dest) )
74 mask |= 1 << v->vcpu_id;
75 }
77 out:
78 HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask mask %x\n",
79 mask);
80 return mask;
81 }
83 static void vmsi_inj_irq(
84 struct domain *d,
85 struct vlapic *target,
86 uint8_t vector,
87 uint8_t trig_mode,
88 uint8_t delivery_mode)
89 {
90 HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_inj_irq "
91 "irq %d trig %d delive mode %d\n",
92 vector, trig_mode, delivery_mode);
94 switch ( delivery_mode )
95 {
96 case dest_Fixed:
97 case dest_LowestPrio:
98 if ( vlapic_set_irq(target, vector, trig_mode) )
99 vcpu_kick(vlapic_vcpu(target));
100 break;
101 default:
102 gdprintk(XENLOG_WARNING, "error delivery mode %d\n", delivery_mode);
103 break;
104 }
105 }
107 #define VMSI_DEST_ID_MASK 0xff
108 #define VMSI_RH_MASK 0x100
109 #define VMSI_DM_MASK 0x200
110 #define VMSI_DELIV_MASK 0x7000
111 #define VMSI_TRIG_MODE 0x8000
113 int vmsi_deliver(struct domain *d, int pirq)
114 {
115 struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
116 uint32_t flags = hvm_irq_dpci->mirq[pirq].gmsi.gflags;
117 int vector = hvm_irq_dpci->mirq[pirq].gmsi.gvec;
118 uint16_t dest = flags & VMSI_DEST_ID_MASK;
119 uint8_t dest_mode = flags & VMSI_DM_MASK;
120 uint8_t delivery_mode = flags & VMSI_DELIV_MASK;
121 uint8_t trig_mode = flags & VMSI_TRIG_MODE;
122 uint32_t deliver_bitmask;
123 struct vlapic *target;
124 struct vcpu *v;
126 HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
127 "msi: dest=%x dest_mode=%x delivery_mode=%x "
128 "vector=%x trig_mode=%x\n",
129 dest, dest_mode, delivery_mode, vector, trig_mode);
131 if ( !(hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_MSI) )
132 {
133 gdprintk(XENLOG_WARNING, "pirq %x not msi \n", pirq);
134 return 0;
135 }
137 deliver_bitmask = vmsi_get_delivery_bitmask(d, dest, dest_mode);
138 if ( !deliver_bitmask )
139 {
140 HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver "
141 "no target on destination\n");
142 return 0;
143 }
145 switch ( delivery_mode )
146 {
147 case dest_LowestPrio:
148 {
149 target = apic_round_robin(d, vector, deliver_bitmask);
150 if ( target != NULL )
151 vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode);
152 else
153 HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "null round robin: "
154 "mask=%x vector=%x delivery_mode=%x\n",
155 deliver_bitmask, vector, dest_LowestPrio);
156 break;
157 }
159 case dest_Fixed:
160 case dest_ExtINT:
161 {
162 uint8_t bit;
163 for ( bit = 0; deliver_bitmask != 0; bit++ )
164 {
165 if ( !(deliver_bitmask & (1 << bit)) )
166 continue;
167 deliver_bitmask &= ~(1 << bit);
168 v = d->vcpu[bit];
169 if ( v != NULL )
170 {
171 target = vcpu_vlapic(v);
172 vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode);
173 }
174 }
175 break;
176 }
178 case dest_SMI:
179 case dest_NMI:
180 case dest_INIT:
181 case dest__reserved_2:
182 default:
183 gdprintk(XENLOG_WARNING, "Unsupported delivery mode %d\n",
184 delivery_mode);
185 break;
186 }
187 return 1;
188 }