debuggers.hg

view tools/ioemu/iodev/cpu.cc @ 3677:f89816eaeaad

bitkeeper revision 1.1159.241.1 (4202bb72zRYg-QWeXrkKfXwmuL5I3A)

Add checking ISA DMA flag in cpu_loop. Also need to do bios_init manually
for now. With this change, floppy is functional.

Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Signed-off-by: Arun Sharma <arun.sharma@intel.com>
Signed-off-by: ian.pratt@cl.cam.ac.uk
author iap10@labyrinth.cl.cam.ac.uk
date Fri Feb 04 00:01:54 2005 +0000 (2005-02-04)
parents 5e111ac8c357
children 26a00896163a
line source
1 /*
2 * Main cpu loop for handling I/O requests coming from a virtual machine
3 * Copyright © 2004, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU Lesser General Public License,
7 * version 2.1, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA.
17 */
19 #include "bochs.h"
20 #include <cpu/cpu.h>
21 #ifdef BX_USE_VMX
22 #include <sys/ioctl.h>
23 /* According to POSIX 1003.1-2001 */
24 #include <sys/select.h>
26 /* According to earlier standards */
27 #include <sys/time.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <values.h>
31 #endif
33 #define LOG_THIS BX_CPU_THIS_PTR
35 #ifdef BX_USE_VMX
37 //the evtchn fd for polling
38 int evtchn_fd = -1;
39 //the evtchn port for polling the notification, should be inputed as bochs's parameter
40 u16 ioreq_port = 0;
42 void *shared_page = NULL;
44 //some functions to handle the io req packet
46 //get the ioreq packets from share mem
47 ioreq_t* bx_cpu_c::__get_ioreq(void)
48 {
49 ioreq_t *req;
50 req = &((vcpu_iodata_t *) shared_page)->vp_ioreq;
51 if (req->state == STATE_IOREQ_READY) {
52 req->state = STATE_IOREQ_INPROCESS;
53 } else {
54 BX_INFO(("False I/O requrest ... in-service already: %lx, pvalid: %lx,port: %lx, data: %lx, count: %lx, size: %lx\n", req->state, req->pdata_valid, req->addr, req->u.data, req->count, req->size));
55 req = NULL;
56 }
58 return req;
59 }
61 //use poll to get the port notification
62 //ioreq_vec--out,the
63 //retval--the number of ioreq packet
64 ioreq_t* bx_cpu_c::get_ioreq(void)
65 {
66 ioreq_t *req;
67 int rc;
68 u16 buf[2];
69 rc = read(evtchn_fd, buf, 2);
70 if (rc == 2 && buf[0] == ioreq_port){//got only one matched 16bit port index
71 // unmask the wanted port again
72 write(evtchn_fd, &ioreq_port, 2);
74 //get the io packet from shared memory
75 return __get_ioreq();
76 }
78 //read error or read nothing
79 return NULL;
80 }
82 //send the ioreq to device model
83 void bx_cpu_c::dispatch_ioreq(ioreq_t *req)
84 {
85 int ret, i;
86 int sign;
88 sign = (req->df) ? -1 : 1;
90 if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) {
91 if (req->size != 4) {
92 // Bochs expects higher bits to be 0
93 req->u.data &= (1UL << (8 * req->size))-1;
94 }
95 }
96 if (req->port_mm == 0){//port io
97 if(req->dir == IOREQ_READ){//read
98 if (!req->pdata_valid)
99 req->u.data = BX_INP(req->addr, req->size);
100 else {
101 unsigned long tmp;
103 for (i = 0; i < req->count; i++) {
104 tmp = BX_INP(req->addr, req->size);
105 BX_MEM_WRITE_PHYSICAL((Bit32u) req->u.pdata + (sign * i * req->size),
106 req->size, &tmp);
107 }
108 }
109 } else if(req->dir == IOREQ_WRITE) {
110 if (!req->pdata_valid) {
111 BX_OUTP(req->addr, (Bit32u) req->u.data, req->size);
112 } else {
113 for (i = 0; i < req->count; i++) {
114 unsigned long tmp;
116 BX_MEM_READ_PHYSICAL((Bit32u) req->u.pdata + (sign * i * req->size), req->size,
117 &tmp);
118 BX_OUTP(req->addr, (Bit32u) tmp, req->size);
119 }
120 }
122 }
123 } else if (req->port_mm == 1){//memory map io
124 if (!req->pdata_valid) {
125 if(req->dir == IOREQ_READ){//read
126 BX_MEM_READ_PHYSICAL(req->addr, req->size, &req->u.data);
127 } else if(req->dir == IOREQ_WRITE)//write
128 BX_MEM_WRITE_PHYSICAL(req->addr, req->size, &req->u.data);
129 } else {
130 //handle movs
131 unsigned long tmp;
132 if (req->dir == IOREQ_READ) {
133 //BX_INFO(("<READ>addr:%llx, pdata:%llx, size: %x, count: %x\n", req->addr, req->u.pdata, req->size, req->count));
134 for (i = 0; i < req->count; i++) {
135 BX_MEM_READ_PHYSICAL(req->addr + (sign * i * req->size), req->size, &tmp);
136 BX_MEM_WRITE_PHYSICAL((Bit32u) req->u.pdata + (sign * i * req->size), req->size, &tmp);
137 }
138 } else if (req->dir == IOREQ_WRITE) {
139 //BX_INFO(("<WRITE>addr:%llx, pdata:%llx, size: %x, count: %x\n", req->addr, req->u.pdata, req->size, req->count));
140 for (i = 0; i < req->count; i++) {
141 BX_MEM_READ_PHYSICAL((Bit32u)req->u.pdata + (sign * i * req->size), req->size, &tmp);
142 BX_MEM_WRITE_PHYSICAL(req->addr + (sign * i * req->size), req->size, &tmp);
143 }
144 }
145 }
146 }
147 req->state = STATE_IORESP_READY;
148 send_event = 1;
149 }
151 void
152 bx_cpu_c::handle_ioreq(void)
153 {
154 ioreq_t *req = get_ioreq();
155 if (req)
156 dispatch_ioreq(req);
157 }
159 void
160 bx_cpu_c::timer_handler(void)
161 {
162 handle_ioreq();
163 }
165 #endif
167 #define rdtscl(low) \
168 __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
170 void
171 bx_cpu_c::cpu_loop(int max_instr_count)
172 {
173 Bit8u vector;
174 fd_set rfds;
175 unsigned long stime_usec;
176 struct timeval tv;
177 int retval;
179 /* Watch stdin (fd 0) to see when it has input. */
180 FD_ZERO(&rfds);
182 while (1) {
183 unsigned long t1, t2;
185 /* Wait up to one seconds. */
186 tv.tv_sec = 0;
187 tv.tv_usec = 100000;
188 FD_SET(evtchn_fd, &rfds);
190 send_event = 0;
191 rdtscl(t1);
192 retval = select(evtchn_fd+1, &rfds, NULL, NULL, &tv);
193 rdtscl(t2);
194 if (retval == -1) {
195 perror("select");
196 return;
197 }
198 //stime_usec = 1000000 * (1 - tv.tv_sec) - tv.tv_usec;
199 if (t2 > t1)
200 BX_TICKN((t2 - t1) / 2000); // should match ips in bochsrc
201 else
202 BX_TICKN((MAXINT - t1 + t2) / 2000); // should match ips in bochsrc
203 timer_handler();
204 if (BX_CPU_INTR) {
205 #if BX_SUPPORT_APIC
206 if (BX_CPU_THIS_PTR local_apic.INTR)
207 vector = BX_CPU_THIS_PTR local_apic.acknowledge_int ();
208 else
209 vector = DEV_pic_iac(); // may set INTR with next interrupt
210 #else
211 // if no local APIC, always acknowledge the PIC.
212 vector = DEV_pic_iac(); // may set INTR with next interrupt
213 #endif
214 interrupt(vector);
215 }
216 /* we check DMA after interrupt check*/
217 while(BX_HRQ){
218 DEV_dma_raise_hlda();
219 }
221 if (send_event) {
222 int ret;
223 ret = xc_evtchn_send(xc_handle, ioreq_port);
224 if (ret == -1) {
225 BX_ERROR(("evtchn_send failed on port: %d\n", ioreq_port));
226 }
227 }
228 }
229 }
231 static __inline__ void set_bit(long nr, volatile void *addr)
232 {
233 __asm__ __volatile__( "lock ; "
234 "btsl %1,%0"
235 :"=m" ((*(volatile long *)addr))
236 :"Ir" (nr));
238 return;
239 }
241 void
242 bx_cpu_c::interrupt(Bit8u vector)
243 {
244 unsigned long *intr, tscl;
245 int ret;
247 // Send a message on the event channel. Add the vector to the shared mem
248 // page.
250 rdtscl(tscl);
251 BX_INFO(("%lx: injecting vector: %x\n", tscl, vector));
252 intr = &(((vcpu_iodata_t *) shared_page)->vp_intr[0]);
253 set_bit(vector, intr);
255 send_event = 1;
256 }
258 void
259 bx_cpu_c::init(bx_mem_c*)
260 {
261 #ifdef BX_USE_VMX
262 if (evtchn_fd != -1)//the evtchn has been opened by another cpu object
263 return;
265 //use nonblock reading not polling, may change in future.
266 evtchn_fd = open("/dev/xen/evtchn", O_RDWR|O_NONBLOCK);
267 if (evtchn_fd == -1) {
268 perror("open");
269 return;
270 }
272 BX_INFO(("listening to port: %d\n", ioreq_port));
273 /*unmask the wanted port -- bind*/
274 if (ioctl(evtchn_fd, ('E'<<8)|2, ioreq_port) == -1) {
275 perror("ioctl");
276 return;
277 }
279 #if 0
280 //register the reading evtchn function as timer
281 bx_pc_system.register_timer(this, timer_handler, 1000,//1000 us, may change
282 1,//continuous timer
283 1,//active
284 "cpu reading evtchn handler");
285 #endif
287 #endif
288 }
290 void
291 bx_cpu_c::reset(unsigned)
292 {
293 }
295 void
296 bx_cpu_c::atexit()
297 {
298 }
300 void
301 bx_cpu_c::set_INTR(unsigned value)
302 {
303 BX_CPU_THIS_PTR INTR = value;
304 }
306 void
307 bx_cpu_c::pagingA20Changed()
308 {
309 }
311 bx_cpu_c::bx_cpu_c()
312 {
313 }
315 bx_cpu_c::~bx_cpu_c()
316 {
317 }