Compare commits

...
333 Commits
Author SHA1 Message Date
(no author) efb602cda3 This commit was manufactured by cvs2svn to create tag
'release_0_9_0'.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/tags/release_0_9_0@2402 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 22:06:28 +00:00
bellard 26a16623b8 darwin fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2401 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 22:06:27 +00:00
bellard d8ecc0b913 Make cpu_signal_handler work on Mac OS X/Darwin x86
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2400 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 21:41:46 +00:00
bellard 19c80e50ee update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2399 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 21:22:42 +00:00
bellard a0f51eadc6 removed
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2398 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 21:09:14 +00:00
bellard b6aaab3b86 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2397 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 21:06:29 +00:00
bellard df517cec51 int conversion test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2396 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 20:52:39 +00:00
bellard 2afbeee757 update path
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2395 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 20:51:14 +00:00
bellard 7b9c30c5ee update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2394 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 20:46:55 +00:00
bellard c636bb66cc gdbserver fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2393 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 20:46:05 +00:00
bellard 84f2e8ef05 copyright update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2392 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 20:21:32 +00:00
bellard a9ce859052 info vnc command (Anthony Liguori)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2391 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 20:20:30 +00:00
bellard 564c337efd Mouse relative offset VNC extension (Anthony Liguori)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2390 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 20:14:10 +00:00
bellard 2a2528266e This patch fixes typos in the commpage definition (Pierre d'Herbemont).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2389 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 19:50:01 +00:00
bellard 263466f53a This patch cleans up target_mach_msg_trap(), removes unuseful do_pread, begins sysctl implementation and implements fcntl (Pierre d'Herbemont).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2388 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 19:47:42 +00:00
bellard 1e2bed4f7e Darwin cleanup usage (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2387 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 19:43:27 +00:00
bellard 831952376e Darwin user help (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2386 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 19:42:07 +00:00
bellard 4fe8b87a7c gcc version
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2385 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-05 19:38:35 +00:00
pbrook 1057eaa709 Fix 64-bit host register corruption.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2384 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-04 13:37:44 +00:00
ths d96372efaa sem* and msg* for qemu, part2, by Kirill Shutemov.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2383 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-02 22:05:44 +00:00
ths fa2948167f sem* and msg* for qemu, part1, by Kirill Shutemov.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2382 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-02 22:05:00 +00:00
ths b49d07ba03 Use target_ulong type for emulator registers.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2381 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-02 03:57:09 +00:00
ths 33ef55bd96 Mingw build fix, by Johannes Schindelin.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2380 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-02 03:30:54 +00:00
ths 3fffc2234f PIIX4 SMBus host, EEPROM device emulation, by Ed Swierk.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2379 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-02 03:13:18 +00:00
ths 4a109bfbca Update MIPS TODO.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2378 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-02 02:56:33 +00:00
ths 01d6a890b4 Sparc arm/mips/sparc register patch, by Martin Bochnig.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2377 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-02 01:03:34 +00:00
ths 6a1cbf68b7 script=no for the TUN/TAP net option, by Jean-Christian de Rivaz
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2376 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-02 00:37:56 +00:00
bellard c4e27dd441 64 bit syscall fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2375 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-01 22:12:43 +00:00
bellard d80c7d1c47 64 bit syscall fixes - more logical mwait/monitor ECX test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2374 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-01 22:12:19 +00:00
bellard 0499e4a02a cwde and cdq fix in 64 bit mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2373 c046a42c-6fe2-441c-8c8c-71466251a162
2007-02-01 22:11:07 +00:00
ths 0dcece76f0 Remove redundant ENOMEDIUM define.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2372 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-31 13:34:07 +00:00
ths 01feaa058e Save some vm space for the regular program loading zone, by
Pierre d'Herbemont


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2371 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-31 12:24:18 +00:00
ths bf53ca0190 Upgrade the apic version_id, by Don Laor.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2370 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-31 12:22:18 +00:00
ths 5a7b542bbd siginfo fix for Darwin/Mac OS X, by Pierre d'Herbemont.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2369 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-31 12:16:51 +00:00
ths fd6776422b Use Cocoa and CoreAudio backend by default on Darwin systems, by Pierre
d'Herbemont.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2368 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-31 12:10:07 +00:00
ths 46ea33974d Fix set_error return value, by Pierre d'Herbemont.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2367 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-31 12:08:13 +00:00
ths 90e950d17f Fix GT64120 mapping with REDBOOT, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2366 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-31 12:02:12 +00:00
ths 3ddd00658e Fix 64bit-induced MIPS Malta breakage, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2365 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-31 11:48:27 +00:00
pbrook a2d1ebaf89 GDB hosted syscalls.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2364 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-28 03:10:55 +00:00
pbrook 4046d9130e Use standard character device interface for gdbstub.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2363 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-28 01:53:16 +00:00
pbrook f749998939 Add nodelay option for TCP character devices.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2362 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-28 00:10:01 +00:00
pbrook e5b0bc445e Rearrange char event handlers to fix CHR_EVENT_RESET.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2361 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-27 23:46:43 +00:00
pbrook dff5efc848 Accept --foo as an alias for -foo.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2360 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-27 17:19:39 +00:00
pbrook 64423fb206 Accept -help.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2359 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-27 17:11:41 +00:00
ths 6c3675cac3 ENODEV works also for __sun__, the magic number 4097 stemmed from the
windows support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2358 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-26 17:18:49 +00:00
ths 71c2fd5cdf Define ENOMEDIUM to match ENODEV if it isn't available.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2357 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-26 15:37:46 +00:00
ths df5cf72160 Make the tarball's VERSION part overridable from make invocation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2356 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-24 22:56:36 +00:00
ths 44cbbf18b9 Fix malta emulation for 64bit qemu.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2355 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-24 22:00:13 +00:00
ths 6070dd07e9 Split out SDL X keymap, by Bernhard Fischer.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2354 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-24 21:40:21 +00:00
ths e6a71ae327 Add support for 82371FB (Step A1) and Improved support for 82371SB
(Function 1), by Carlo Marcelo Arenas Belon.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2353 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-24 21:35:22 +00:00
ths 5f4da8c0f3 New multiple snapshot support for VMDK, by Igor Lvovsky.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2352 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-24 21:05:24 +00:00
ths b29a0341d7 EBase is limited to KSEG0/KSEG1 even on 64bit CPUs.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2351 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-24 18:01:23 +00:00
ths 4de9b249d3 Reworking MIPS interrupt handling, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2350 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-24 01:47:51 +00:00
ths 30c4bbace1 Fix DMA timeouts on FreeBSD, by Carlo Marcelo Arenas Belon.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2349 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-24 01:12:42 +00:00
ths 9c2149c8e0 Implementing dmfc/dmtc.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2348 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-23 22:45:22 +00:00
ths 17c275d9ce Update .cvsignore.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2347 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-23 01:47:46 +00:00
ths 81e1e20979 Update TODO.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2346 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-22 20:57:17 +00:00
ths 3b1c8be4f4 Fix PageMask handling, second part.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2345 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-22 20:50:42 +00:00
ths c281868e26 Add dependency for fop_template.c.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2344 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-21 22:40:04 +00:00
pbrook 3c07f8e894 Don't resume guest when gdb connection terminates and -S specified.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2343 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-21 16:47:01 +00:00
ths 72f341ed1e TLB address wraparound hopefully fixed now.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2342 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-21 03:13:58 +00:00
ths bc814401c2 Bring TLB / PageSize handling in line with real hardware behaviour.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2341 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-21 03:12:25 +00:00
pbrook 8e71621f78 Add ARM Angel semihosting to system emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2340 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-20 17:12:09 +00:00
pbrook 57be54bb3e Fix "make test2".
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2339 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-20 16:52:55 +00:00
ths 5f12ab4b10 Add more ATAPI CDROM DMA support, by Juergen Keil.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2338 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-20 01:12:17 +00:00
ths af23902bd9 Fix typo.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2337 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-20 00:29:01 +00:00
ths 472c5273e2 Change display colors, the LED bar is green and the text display is red.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2336 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-20 00:27:42 +00:00
ths 15dcf5aa86 Note more issues.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2335 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-19 17:56:23 +00:00
ths 7f1c9da998 Darwin build fix, by Pierre d'Herbemont.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2334 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-18 22:43:16 +00:00
ths 284ec167e7 Add Darwin userspace emulation to Changelog.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2333 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-18 22:14:53 +00:00
ths 831b78254c Darwin userspace emulation, by Pierre d'Herbemont.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2332 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-18 20:06:33 +00:00
ths 54421cb17b Fix CDROM permission check, by Kazu <kazoo@r3.dion.ne.jp>.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2331 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-18 00:22:11 +00:00
ths 0da75eb135 Big endian support for Gallileo, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2330 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-17 23:35:01 +00:00
ths 605686cd7a Kqemu support for Solaris, by Ben Taylor.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2329 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-17 23:31:19 +00:00
ths 8182266352 Fix USB buffer size, by Herbert Xu.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2328 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-17 23:08:17 +00:00
ths 54fd9cdfb4 Slirp UDP fix, by Jason Wessel.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2327 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-17 22:47:40 +00:00
ths 9dbd25e664 Note newsworthy changes.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2326 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-17 21:32:49 +00:00
ths 2c52c8169a Keep track of mips related issues.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2325 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-17 20:03:15 +00:00
ths f1770b3e1f Disable Malta floppy controller for now, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2324 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-17 15:15:52 +00:00
pbrook 72742c8626 ARM boot fix (Jason Wessel).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2323 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-17 08:59:26 +00:00
ths adb4796796 Improved console handling, thanks Stefan Weil.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2322 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-16 23:02:36 +00:00
bellard dabd98ddf5 fixed movd mmx/sse insn
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2321 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-16 19:28:58 +00:00
pbrook daf90626be ARM ELF loader.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2320 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-16 18:54:31 +00:00
ths 5856de800d MIPS Malta system and devices support, by Aurelien Jarno and Stefan Weil.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2319 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-15 23:58:11 +00:00
ths fde7d5bd73 Gallileo GT64xxx support, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2318 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-15 18:32:02 +00:00
ths 5c2b87e34d PIIX4 support, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2317 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-15 17:08:08 +00:00
ths 567daa491f Increase MIPS BIOS from 128kB to 4MB, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2316 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-10 16:25:04 +00:00
ths 8f1c91d801 Devfn number for the PIIX3 southbridge, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2315 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-10 16:23:41 +00:00
ths abcebc7e80 Devfn number for network PCI cards, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2314 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-10 16:17:21 +00:00
ths f158755072 Restore SCSI disk attaching, by Igor Kovalenko.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2313 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-10 11:46:13 +00:00
bellard bf8c534200 ifname arg fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2312 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-09 19:44:41 +00:00
bellard 0178196398 win32: physical drive support (initial patch by kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2311 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-07 22:43:30 +00:00
bellard 18607dcb7c added cutils.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2310 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-07 22:04:40 +00:00
ths 96d30e4801 Revert -disk patch, as requested by Fabrice. The general idea of this
patch is sound, but the implementation is just too ugly.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2309 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-07 20:42:14 +00:00
pbrook 2f67a0d55a Script to check for missing FORCE_RET.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2308 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-07 19:38:08 +00:00
bellard 21664424ed path_is_absolute() fix for win32
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2307 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-07 18:22:37 +00:00
bellard 3b39528c15 removed redundant qemu_aio_flush()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2306 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-07 17:33:20 +00:00
bellard 3b9f94e1a8 win32 block device fixes (initial patch by kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2305 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-07 17:27:07 +00:00
bellard f5e25d7007 Japanese keyboard patch (kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2304 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-07 17:12:41 +00:00
ths 2909b29aee Unbreak the last patch.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2303 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-06 02:24:15 +00:00
ths f7bcd4e373 Different MIPS BIOS binary names per endianness, and more relaxed size
rules for the binaries, by Alec Voropay.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2302 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-06 01:37:51 +00:00
ths 43c1b7e4c3 Add new Etherboot ROMs for PXE boot.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2301 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 23:48:51 +00:00
ths 86e94dea5b Reinitialize monitor upon reconnect, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2300 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 22:01:59 +00:00
ths 8f28f3fbbe Configure check for alsa, by Bernhard Fischer.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2299 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 21:25:54 +00:00
ths 43f238d7b6 Support fcntl F_GETLK64, F_SETLK64, F_SETLKW64, by Kirill A. Shutemov.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2298 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 20:55:49 +00:00
ths 4dbb0f5006 Fix for hard disk translation hints, by Volker Ruppert.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2297 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 18:58:34 +00:00
ths 6850dd945e Support for Bochs "growing" images, by Volker Ruppert.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2296 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 18:56:04 +00:00
ths b92090309e Fix comment, by Volker Ruppert.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2295 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 18:52:57 +00:00
ths 2e9671daee patch for block-raw.c for Solaris, by Ben Taylor.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2294 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 17:44:41 +00:00
ths eec85c2a0d Add -boot n option for x86 using PXE, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2293 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 17:41:07 +00:00
ths 9ae0255520 Add -option-rom option to allow loading of PCI option ROMs, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2292 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 17:39:04 +00:00
ths a0ae05aa63 PPC32 Trace Exception and Trap instruction, by Jason Wessel.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2291 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 16:54:16 +00:00
ths 455204eb1a Dynamic handling of guest mice, by Lonnie Mendez.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2290 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 16:42:13 +00:00
ths 6f30fa853b Untangle the various CFLAGS/LDFLAGS flavours. Allow overriding the
optional flags at make time.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2289 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-05 01:00:47 +00:00
bellard b371dc594b memsave monitor command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2288 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-03 15:20:39 +00:00
bellard 2ee4aed86f moved invalidate_tlb() to helper.c as a work around for gcc 3.2.2 bug - suppressed invalid tb_invalidate_page_range() calls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2287 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-03 15:18:08 +00:00
pbrook df628ff14e Arm GIC stuck interrupt fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2286 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-02 19:33:15 +00:00
ths 240f24e013 Fix Makefile weirdness.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2285 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-01 21:31:01 +00:00
ths 0feef828e1 Fix bad data type.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2284 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-01 20:35:21 +00:00
ths 3a3f24fce8 Fix lwl/lwr for 64bit emulation, also debug output spec for 64bit emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2283 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-01 20:34:37 +00:00
ths 7495fd0f4a Simplify code and fix formatting.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2282 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-01 20:32:08 +00:00
ths f8c6ff6c3c Fix initrd load address.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2281 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-01 20:31:07 +00:00
pbrook 04e897efdd Remove duplicate TARGET_M68K case.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2280 c046a42c-6fe2-441c-8c8c-71466251a162
2007-01-01 14:14:34 +00:00
pbrook 388c45084d bFLT loader commandline fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2279 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-26 18:27:07 +00:00
ths fa1fb14cd2 Fix SCSI cdrom boot, thanks Blue Swirl.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2278 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-24 17:12:43 +00:00
ths 1f95844967 Null character instead of numeric null.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2277 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-23 22:51:27 +00:00
pbrook a14d6c8c65 Solaris SMBD hacks (Ben Taylor).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2276 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-23 15:37:33 +00:00
ths 04d4b0c33f Simplify error handling again.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2275 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-23 15:18:47 +00:00
ths 9042c0e20d Check ELF binaries for machine type and endianness.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2274 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-23 14:18:40 +00:00
ths 70ead43412 Use memory barriers in FORCE_RET / RETURN.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2273 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-23 00:49:32 +00:00
ths 5bf089345b Fix spelling.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2272 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-23 00:33:26 +00:00
ths eddbd288a0 More serial ports for the mips machine.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2271 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-23 00:23:19 +00:00
ths 28d657fc0b Fix build warning on Windows.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2270 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-23 00:03:15 +00:00
pbrook 4258b780af Sparc64 build fix (Igor Kovalenko).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2269 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-22 22:35:25 +00:00
ths 52f61fdeec Windows build fix, namespace cleanup, fix error message, by Stefan Weil.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2268 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-22 21:20:52 +00:00
ths c26c1c4b3d Support for unidirectional pipes, by Ed Swierk.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2267 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-22 19:25:31 +00:00
ths c032e2a98c Fix -cdrom breakage.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2266 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-22 17:29:05 +00:00
ths 42550fde7e SCSI emulation improvements, by Chuck Brazie.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2265 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-22 16:34:12 +00:00
ths 62ee021121 Build fix for AIO (-dummy) on Windows, by Stefan Weil.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2264 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-22 14:19:53 +00:00
ths fef3074347 Escape filname printout properly, by Anthony Liguori and Julian Seward.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2263 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-22 14:11:32 +00:00
ths bd491d6a4e Fix CDROM change, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2262 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-22 02:14:49 +00:00
ths 71e3ceb800 Daemonize option, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2261 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-22 02:11:31 +00:00
ths 73fc97427b Unix domain socket support for VNC, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2260 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-22 02:09:07 +00:00
ths ffd843bcdc Run monitor over unix domain sockets, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2259 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-21 19:46:43 +00:00
ths 1cb6c3fd38 Fix "inaccessible boot device" on FreeBSD, by Juergen Lock.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2258 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-21 19:14:11 +00:00
ths eaf7e70b01 Enable TCP_NODELAY, by Daniel Jacobowitz.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2257 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-21 19:10:59 +00:00
ths 8bdc2159db Don't cast lvalues, fixes compiler warning.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2256 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-21 17:24:45 +00:00
ths 416b5d366d Avoid "unused variable" compiler warning.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2255 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-21 17:23:49 +00:00
ths d8b20157fc Remove unused variable.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2254 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-21 16:50:54 +00:00
ths 92190c648a Silence a spurious gcc warning.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2253 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-21 16:50:09 +00:00
ths a86c8f29de Fix compiler warnings, add signed versions of some swab functions.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2252 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-21 16:49:27 +00:00
ths 5dc4b74480 Scrap SIGN_EXTEND32.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2251 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-21 13:48:28 +00:00
ths c570fd169c Preliminiary MIPS64 support, disabled by default due to performance impact.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2250 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-21 01:19:56 +00:00
pbrook 328a42406d Look for gcc3 (Anthony Liguori).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2249 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-19 03:31:34 +00:00
pbrook 67d3b957e6 Add unassigned memory debugging code.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2248 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-18 05:03:52 +00:00
ths 179e32bbcc Fix erraneous fallthrough in MIPS trap implementation, thanks Atsushi Nemoto.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2247 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-16 16:45:18 +00:00
ths e4630047e1 Simple test for mips/mipsel, based on a test by Alexander Voropay.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2246 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-14 14:48:11 +00:00
ths 73e14b623f Reduce VNC resize traffic, thanks Eduardo Felipe.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2245 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-14 13:36:01 +00:00
ths 768a4a36a4 Fix userland ELF loader for zero sized BSS.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2244 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-14 13:32:11 +00:00
ths 0d3267a728 MIPS has also a fixed MMAP_SHIFT of 12.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2243 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-11 22:04:25 +00:00
ths 8e33c08c84 MIPS FPU support for the gdb stub, by Daniel Jacobowitz.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2242 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-11 19:22:27 +00:00
ths 197ea35ab2 Fix addrlen size, by David Woodhouse.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2241 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-11 19:13:59 +00:00
ths 366dfc521e Spelling fixes, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2240 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-11 18:35:08 +00:00
ths 667accab8e Implement -no-quit option, by Xavier Gnata.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2239 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-11 02:08:05 +00:00
ths a2d4e44b48 Fix PCI config space overflow, by Herbert Xu.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2238 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-10 23:20:45 +00:00
ths 3bcb80f1af Fix sector size overflow, by Herbert Xu.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2237 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-10 23:07:39 +00:00
ths a42aa81571 Build fix for newer kernel headers, thanks Jason Wessel.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2236 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-10 22:11:04 +00:00
ths ca7c2b1b9f Handle invalid accesses as SIGILL for mips/mipsel userland emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2235 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-10 22:08:10 +00:00
ths 7d600c804d Fix fstat for MIPS userland emulation, and add support for a cacheflush
syscall, thanks to Dave Denholm.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2234 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-08 01:32:58 +00:00
ths 71fb7241c6 Fix build of MIPS target without FPU support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2233 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-07 20:07:37 +00:00
ths 9f08349345 Spelling fixes, thanks to Stefan Weil.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2232 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-07 18:28:42 +00:00
ths afdfa781e6 MIPS RTC emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2231 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-07 18:15:35 +00:00
ths cd75cf10ca .cvsignore m68k-user.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2230 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-07 17:18:01 +00:00
ths ea55ffb373 Move date/time init to the RTC implementation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2229 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-07 17:16:55 +00:00
ths aa328addc0 Fix reset handling, CP0 isn't enabled by default (a fact which doesn't
matter when running in kernel space).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2228 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-07 16:22:15 +00:00
ths e144966416 Simplify mask construction.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2227 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-07 00:30:19 +00:00
ths bb8a53ad91 Update copyright notice.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2226 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-06 23:12:49 +00:00
ths e16fe40c87 Move the MIPS CPU timer in a seperate file, by Alec Voropay.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2225 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-06 21:38:37 +00:00
ths 7a387fffce Add MIPS32R2 instructions, and generally straighten out the instruction
decoding. This is also the first percent towards MIPS64 support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2224 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-06 20:17:30 +00:00
ths 8c0fdd856c Dynamically translate MIPS mtc0 instructions.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2223 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-06 18:19:33 +00:00
ths 873eb01234 Dynamically translate MIPS mfc0 instructions.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2222 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-06 17:59:07 +00:00
ths 6ae817752b Halt/reboot support for Linux, by Daniel Jacobowitz. This is a band-aid
until we emulate real MIPS hardware with real firmware.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2221 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-06 17:48:52 +00:00
ths 814b9a4749 MIPS TLB performance improvements, by Daniel Jacobowitz.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2220 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-06 17:42:40 +00:00
ths ec2309289d sparc-softmmu build fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2219 c046a42c-6fe2-441c-8c8c-71466251a162
2006-12-06 15:51:39 +00:00
pbrook 29bfb11725 Add casts for 64-bit hosts.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2218 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-19 23:07:17 +00:00
pbrook 08f396d720 Add missing ARM syscall numbers.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2217 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-19 21:51:51 +00:00
pbrook 38d0662a4c Arm semihosted commandline support (Wolfgang Schildbach).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2216 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-19 20:29:35 +00:00
pbrook 1be9e1dc56 Remove do_socketcallwrapper.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2215 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-19 15:26:04 +00:00
pbrook ec2db7de7a ARM timer counts down, not up.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2214 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-14 21:13:53 +00:00
pbrook 417f38f066 MIPS FPU fixes (Daniel Jacobowitz).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2213 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-12 23:54:39 +00:00
pbrook 2d37be61e3 M68k build fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2212 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-12 21:31:18 +00:00
pbrook 483dcf538e Avoid redundant TLB flushes (Daniel Jacobowitz).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2211 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-12 20:55:05 +00:00
pbrook b362e5e067 Speed up tlb_flush_page (Daniel Jacobowitz).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2210 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-12 20:40:55 +00:00
pbrook d08b2a28e6 MIPS usermode debug exceptions (Dave Denholm).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2209 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-04 16:46:29 +00:00
bellard 597a0559fd update from latest Bochs BIOS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2208 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-01 19:19:17 +00:00
pbrook 188157fe87 Remove FD on close.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2207 c046a42c-6fe2-441c-8c8c-71466251a162
2006-11-01 01:44:16 +00:00
pbrook 58126404f5 Mips IDE support. (Aurelien Jarno)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2206 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-29 15:38:28 +00:00
bellard 569f5d668c compilation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2205 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-29 15:10:09 +00:00
bellard 750afe93fd avoid using char when it is not necessary
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2204 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-28 19:27:11 +00:00
bellard 00a67ba19a avoid regression on sparc-user and ppc-user
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2203 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-28 12:19:07 +00:00
bellard fafffaef4f removed invalid code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2202 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-28 12:09:16 +00:00
pbrook a94a6abff4 Fix ARM VFP debugging dumps.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2201 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-25 17:43:33 +00:00
bellard c688a6eb18 wrwim insn fix (Paul Robinson)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2200 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-23 21:37:34 +00:00
bellard 27908725b9 sparc64 syscall fix (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2199 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-23 21:31:01 +00:00
bellard dd016883fb add support for cvt.s.d and cvt.d.s (Aurelien Jarno)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2198 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-23 21:25:11 +00:00
pbrook d37aca6625 Fix comment typo.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2197 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-22 11:54:30 +00:00
pbrook e6e5906b6e ColdFire target.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2196 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-22 00:18:54 +00:00
pbrook 223b8a40d1 bFLT 64-bit host fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2195 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-21 23:43:02 +00:00
pbrook 1f9519c92d Fix typo in pixel conversion templates.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2194 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-18 21:16:44 +00:00
bellard b4511723bd APIC init fix + APIC get_irq fix (Juergen Keil)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2193 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-08 18:20:51 +00:00
bellard d1beab8220 no-reboot option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2192 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-02 19:44:22 +00:00
bellard e3e97e7c90 do not generate MP table if one CPU (no APIC in QEMU in this case) - added wbinvd (ignored in QEMU but useful on real hardware)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2191 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-02 18:35:39 +00:00
bellard 47d02f6d5c SMI enable bit support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2190 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-02 18:25:40 +00:00
bellard 93eac243d5 32 bit syscall fix (Juergen Keil)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2189 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-02 17:58:33 +00:00
bellard a7e6f8ba22 synced to Bochs BIOS - use 32 bit pushf/popf in 32 bit PCI bios - moved some useful defines in rombios.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2188 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-01 16:08:15 +00:00
pbrook 326199c270 ARM GIC bug.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2187 c046a42c-6fe2-441c-8c8c-71466251a162
2006-10-01 13:03:52 +00:00
bellard 8d7b0fbb3f 32 bit RSP update fix (aka Open Solaris x86_64 bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2186 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-29 20:01:17 +00:00
pbrook 5e966ce6f4 PCI IRC routing fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2185 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-28 19:52:59 +00:00
bellard 74ce674fa8 fixed user mode emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2184 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-27 21:31:59 +00:00
bellard 8988ae8945 SMM fix for x86_64
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2183 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-27 19:54:02 +00:00
bellard 69c3bcb48f enabled PSE36 for x86_64 (fix for OpenSolaris as guest)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2182 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-27 19:52:41 +00:00
bellard 42fc925ec0 VBE 4 bit bank selection fix (Volker Rupper)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2181 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-25 21:41:20 +00:00
bellard 6f15b608f2 removed unused code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2180 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-25 21:34:25 +00:00
bellard 17100159f1 fixed help info strings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2179 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-25 21:33:49 +00:00
bellard 79266dbd9e updated
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2178 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 19:36:49 +00:00
bellard 84631fd79c implement i440 instead of i450 ISA memory mappings to be compatible with Bochs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2177 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 19:31:43 +00:00
bellard 4f3baa4b36 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2176 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 18:49:55 +00:00
bellard f00fc47c15 moved PCI init to BIOS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2175 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 18:49:43 +00:00
bellard ee0ea1d0dd moved PCI init to BIOS - added ISA memory mapping registers and SMM support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2174 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 18:49:13 +00:00
bellard 02a1602e62 added cpu_smm_update()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2173 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 18:48:23 +00:00
bellard a5954d5c34 moved MP table init to BIOS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2172 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 18:48:00 +00:00
bellard f537a28c97 moved ACPI table init to BIOS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2171 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 18:45:28 +00:00
bellard ab1e34add6 moved ACPI table init to BIOS - preliminary SMM support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2170 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 18:44:17 +00:00
bellard 3b21e03e04 added SMM support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2169 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 18:41:56 +00:00
bellard ba86345802 added cpu_get_physical_page_desc()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2168 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 18:41:10 +00:00
bellard d4afc623ae moved PCI, MP and ACPI init to bios
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2167 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 18:38:12 +00:00
pbrook 80b3ada7dd Implement sun4u PCI IRQ routing.
Allow multiple PCI busses and PCI-PCI bridges.
Fix bugs in Versatile PCI implementation.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2166 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 17:01:44 +00:00
pbrook d2b5931756 PCI shared IRQ fix (original patch by andrzej zaborowski).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2165 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-24 00:16:34 +00:00
pbrook e69954b9fc Add ARM RealView Emulation Baseboard.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2164 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-23 17:40:58 +00:00
bellard 37dd208d38 VBE: 8 bit DACs + support for VBE BIOS IDs (Volker Ruppert)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2163 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-21 21:46:53 +00:00
pbrook 05f83f0f95 Update sparc bios image (Blue Swirl).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2162 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-21 20:34:50 +00:00
bellard df52b0009b sun4m halt support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2161 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-20 20:30:57 +00:00
bellard 8f40c388ef update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2160 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-20 20:28:05 +00:00
pbrook aef445bd7e Merge common ISA access routines.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2159 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-18 01:15:29 +00:00
pbrook 6787f5fae0 SPARC SCSI fixes.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2158 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-17 03:20:58 +00:00
bellard b8174937ed dummy cs4231 audio driver for sun4m (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2157 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-10 19:25:12 +00:00
pbrook 519945dfbe Avoid (repeatedly) trying to read stdin after it has closed.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2156 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-10 14:39:54 +00:00
pbrook 707b3ee068 ARM 64-bit host fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2155 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-09 23:35:22 +00:00
pbrook 78600320a8 Arm MMU fix (Justin Fletcher).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2154 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-09 14:36:26 +00:00
bellard 35db099ddb allow host serial port usage (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2153 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-09 12:17:15 +00:00
bellard 6bcb76c3b6 vvfat fixes (Roger Lathrop)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2152 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-09 12:03:20 +00:00
bellard e4a89056df fix serial irq logic (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2151 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-09 11:38:11 +00:00
bellard 715748fa08 added mouse protocol (Igor Kovalenko)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2150 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-09 11:35:47 +00:00
bellard 21206a104f more correct display functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2149 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-09 11:31:34 +00:00
bellard 094eed6ca5 two stop bits support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2148 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-09 11:10:18 +00:00
bellard 9b94dc325b better PCNET endianness support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2147 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-03 19:48:17 +00:00
bellard c6d46c200f typo
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2146 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-03 17:10:41 +00:00
bellard e17a36ce41 multi byte nop support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2145 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-03 17:09:02 +00:00
bellard 03c1847584 endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2144 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-03 16:40:12 +00:00
bellard 67e999be93 Separate the DMA controllers - Convert ESP to new DMA methods (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2143 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-03 16:09:07 +00:00
bellard 91cc029598 initial sparc32 lance and pcnet merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2142 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-03 16:07:02 +00:00
bellard c03b0f0fd8 allow disabling of serial or parallel devices (Stefan Weil)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2141 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-03 14:10:53 +00:00
pbrook 6192bc374f Flush IO requests before savevm (original patch by Blue Swirl).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2140 c046a42c-6fe2-441c-8c8c-71466251a162
2006-09-03 12:08:37 +00:00
pbrook a917d384ac SCSI TCQ support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2139 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-29 04:52:16 +00:00
bellard 508d92d057 16 bit divider
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2138 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-26 18:00:36 +00:00
bellard 64f5a135a7 signed fixes - VNC console switch (initial patch by Andrzej Zaborowski)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2137 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-24 20:36:44 +00:00
bellard a817d93656 fixed handling of relative filenames with -snapshot
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2136 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-24 19:53:37 +00:00
bellard fd44d81821 win32 aio emulation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2135 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-24 18:58:29 +00:00
bellard f45512feac win32 compilation fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2134 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-23 21:40:13 +00:00
bellard 6b21b973ab fixed error handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2133 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-23 21:14:37 +00:00
bellard 2192c33250 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2132 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-21 20:28:18 +00:00
bellard f542086dd4 spelling fixes (Stefan Weil)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2131 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-21 20:26:44 +00:00
bellard ee0f47514c removed outdated info
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2130 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-19 16:56:18 +00:00
bellard 60659e3b44 Japanese keyboard fixes (kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2129 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-19 14:27:31 +00:00
bellard f0e4217213 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2128 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-19 12:38:38 +00:00
bellard e6cda8e299 win32 tap poll suppression (kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2127 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-19 12:37:52 +00:00
bellard b56bdb328a delete block device
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2126 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-19 11:58:59 +00:00
bellard a9f277ba8f no need for bdrv_close()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2125 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-19 11:58:10 +00:00
bellard 19cb37389f better support of host drives
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2124 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-19 11:45:59 +00:00
bellard 66c6ef7678 better support of removable media
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2123 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-19 11:44:21 +00:00
bellard ea185bbda7 use bdrv_media_changed()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2122 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-19 11:43:22 +00:00
bellard 83acc96b23 fixed VGA resolutions with height > 1024
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2121 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-18 09:32:04 +00:00
bellard 6e1b3e4da4 disable -fomit-frame-pointer
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2120 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-17 17:41:26 +00:00
bellard 87b47350ed -L help
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2119 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-17 17:22:54 +00:00
bellard 243a273ee0 fd leak fix (Igor Kovalenko)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2118 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-17 16:19:07 +00:00
bellard c3d78997a3 minimal PCI IDE save/restore
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2117 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-17 10:48:35 +00:00
bellard e6cf6a8c7d save apic timer
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2116 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-17 10:48:06 +00:00
bellard 1941d19c65 PCI save/restore changes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2115 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-17 10:46:34 +00:00
bellard 89b6b50892 vga init changes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2114 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-17 10:45:20 +00:00
bellard d2269f6f64 save VGA PCI state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2113 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-17 10:44:00 +00:00
bellard dfd92d3a46 reset key modifiers when switching console (aka savevm keyboard bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2112 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-17 10:42:46 +00:00
bellard 4c279bdf3a win32 compilation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2111 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-17 09:43:50 +00:00
pbrook 3dc1cb3428 ESP DMA fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2110 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-15 22:57:33 +00:00
pbrook 35f1df84b6 scsi empty drive fix (Blue Swirl).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2109 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-14 15:08:12 +00:00
pbrook 69fba4a51e Remove OpenBIOS ESP patch. Merged upstream.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2108 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-13 14:20:43 +00:00
pbrook 4d611c9a2f SCSI and USB async IO support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2107 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-12 01:04:27 +00:00
pbrook 4ca9c76f36 Add SCSI controller class.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2106 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-10 01:03:35 +00:00
bellard 2a98c1981f removed tabs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2105 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-09 22:38:19 +00:00
bellard 35b961cf8d indent
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2104 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-09 21:55:55 +00:00
bellard 8ccad811e6 use AIO for DMA transfers - enabled DMA for CDROMs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2103 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-07 21:36:34 +00:00
bellard e84a4fedf7 mem leak fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2102 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-07 21:35:12 +00:00
bellard fb43f4dddc copyright update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2101 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-07 21:34:46 +00:00
bellard 19d36792c0 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2100 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-07 21:34:34 +00:00
bellard 90765429aa fixed aio emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2099 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-07 19:10:16 +00:00
pbrook ce1a14dc0d Dynamically allocate AIO Completion Blocks.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2098 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-07 02:38:06 +00:00
bellard 51d6bae7a8 removed duplicated line
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2097 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-06 21:13:56 +00:00
bellard 13a2e80f04 info about VM snapshots
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2096 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-06 14:50:31 +00:00
bellard c88676f89c use zlib to compress ram snapshots - correctly save qemu clock
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2095 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-06 13:36:11 +00:00
bellard d15a771da1 qcow2 is now used for '-snapshot' - keep BlockDriverState.total_sectors
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2094 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-06 13:35:09 +00:00
bellard a946592212 handle read outside the backing file
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2093 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-06 13:34:04 +00:00
pbrook 1aacf3489b Add missing #define.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2092 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-06 13:27:39 +00:00
pbrook 51c1ebb1bc Fix SCSI off-by-one device size.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2091 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-06 11:31:06 +00:00
bellard 6eb5733a3c fixed blocking io emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2090 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-06 09:51:25 +00:00
bellard 15e6690aca fixed disk image creation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2089 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-05 22:24:28 +00:00
bellard c47c33b098 block API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2088 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-05 21:32:10 +00:00
bellard e70332b376 use QEMUFile API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2087 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-05 21:31:46 +00:00
bellard faea38e786 multiple snapshot support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2086 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-05 21:31:00 +00:00
bellard 42ca638823 enable qcow2
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2085 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-05 21:29:27 +00:00
bellard 9ab8a34a18 O_LARGEFILE is not needed
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2084 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-05 21:27:55 +00:00
bellard 585f8587ad new qcow2 disk image format
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2083 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-05 21:14:20 +00:00
bellard 9e46cfa4c6 sparc64.ld file (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2082 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-04 21:55:15 +00:00
bellard e2f909bef9 swapped memset args (Charles Coffing)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2081 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-03 20:39:40 +00:00
bellard 7f1a8398ab removed unused code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2080 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-03 17:53:19 +00:00
bellard e7b81015e5 added missing returns
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2079 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-03 17:52:41 +00:00
bellard 436e15b827 win32 fixes (initial patch by kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2078 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-03 09:07:19 +00:00
bellard 550be12730 fixed refresh logic (initial patch by Igor Kovalenko)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2077 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-02 22:19:33 +00:00
bellard 979b67ad86 some compilation fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2076 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-02 22:02:08 +00:00
bellard 83f6409109 async file I/O API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2075 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-01 16:21:11 +00:00
bellard 7954c73498 commit to specific devices
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2074 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-01 15:52:40 +00:00
bellard 93b6b2a3cd show backing file name
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2073 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-01 15:51:11 +00:00
bellard d62ca2bb9b removed unused code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2072 c046a42c-6fe2-441c-8c8c-71466251a162
2006-08-01 15:50:14 +00:00
pbrook 4615218210 Rewrite Arm host support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2071 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-30 19:16:29 +00:00
pbrook f3a9676a60 Arm host build fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2070 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-29 19:09:31 +00:00
221 changed files with 33687 additions and 8450 deletions

No files matched your search

+12 -9
View File
@@ -1,14 +1,16 @@
arm-user
arm-linux-user
arm-softmmu
armeb-user
armeb-linux-user
config-host.*
dyngen
i386
i386-softmmu
i386-user
i386-darwin-user
i386-linux-user
ppc-softmmu
ppc64-softmmu
ppc-user
ppc-darwin-user
ppc-linux-user
qemu-doc.html
qemu-tech.html
qemu-doc.info
@@ -17,18 +19,19 @@ qemu.1
qemu.pod
qemu-img.1
qemu-img.pod
sparc-user
sparc-linux-user
qemu-img
sparc-softmmu
x86_64-softmmu
sparc64-user
sparc64-linux-user
sparc64-softmmu
mips-softmmu
mipsel-softmmu
mips-user
mipsel-user
mips-linux-user
mipsel-linux-user
m68k-linux-user
.gdbinit
sh4-user
sh4-linux-user
sh4-softmmu
*.aux
*.cp
+18
View File
@@ -1,3 +1,21 @@
version 0.9.0:
- Support for relative paths in backing files for disk images
- Async file I/O API
- New qcow2 disk image format
- Support of multiple VM snapshots
- Linux: specific host CDROM and floppy support
- SMM support
- Moved PCI init, MP table init and ACPI table init to Bochs BIOS
- Support for MIPS32 Release 2 instruction set (Thiemo Seufer)
- MIPS Malta system emulation (Aurelien Jarno, Stefan Weil)
- Darwin userspace emulation (Pierre d'Herbemont)
- m68k user support (Paul Brook)
- several x86 and x86_64 emulation fixes
- Mouse relative offset VNC extension (Anthony Liguori)
- PXE boot support (Anthony Liguori)
- '-daemonize' option (Anthony Liguori)
version 0.8.2:
- ACPI support
+9 -6
View File
@@ -1,11 +1,14 @@
The following points clarify the QEMU licenses:
The following points clarify the QEMU license:
1) The QEMU virtual CPU core library (libqemu.a) and the QEMU PC
system emulator are released under the GNU Lesser General Public
License.
1) QEMU as a whole is released under the GNU General Public License
2) The Linux user mode QEMU emulator is released under the GNU General
Public License.
2) Parts of QEMU have specific licenses which are compatible with the
GNU General Public License. Hence each source file contains its own
licensing information.
In particular, the QEMU virtual CPU core library (libqemu.a) is
released under the GNU Lesser General Public License. Many hardware
device emulation sources are released under the BSD license.
3) QEMU is a trademark of Fabrice Bellard.
+26 -14
View File
@@ -5,19 +5,18 @@ include config-host.mak
.PHONY: all clean distclean dvi info install install-doc tar tarbin \
speed test test2 html dvi info
CFLAGS=-Wall -O2 -g -fno-strict-aliasing -I.
ifdef CONFIG_DARWIN
CFLAGS+= -mdynamic-no-pic
endif
BASE_CFLAGS=
BASE_LDFLAGS=
BASE_CFLAGS += $(OS_CFLAGS)
ifeq ($(ARCH),sparc)
CFLAGS+=-mcpu=ultrasparc
BASE_CFLAGS += -mcpu=ultrasparc
endif
LDFLAGS=-g
CPPFLAGS += -I. -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
LIBS=
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
TOOLS=qemu-img$(EXESUF)
ifdef CONFIG_STATIC
LDFLAGS+=-static
BASE_LDFLAGS += -static
endif
ifdef BUILD_DOCS
DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1
@@ -25,18 +24,26 @@ else
DOCS=
endif
ifndef CONFIG_DARWIN
ifndef CONFIG_WIN32
ifndef CONFIG_SOLARIS
LIBS+=-lrt
endif
endif
endif
all: $(TOOLS) $(DOCS) recurse-all
subdir-%: dyngen$(EXESUF)
$(MAKE) -C $(subst subdir-,,$@) all
recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
$(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
qemu-img$(EXESUF): qemu-img.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c
$(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
dyngen$(EXESUF): dyngen.c
$(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^
$(HOST_CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -o $@ $^
clean:
# avoid old build problems by removing potentially incorrect old files
@@ -71,7 +78,8 @@ install: all $(if $(BUILD_DOCS),install-doc)
$(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
mkdir -p "$(DESTDIR)$(datadir)"
for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
video.x openbios-sparc32 linux_boot.bin; do \
video.x openbios-sparc32 linux_boot.bin pxe-ne2k_pci.bin \
pxe-rtl8139.bin pxe-pcnet.bin; do \
$(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
done
ifndef CONFIG_WIN32
@@ -120,7 +128,8 @@ dvi: qemu-doc.dvi qemu-tech.dvi
html: qemu-doc.html qemu-tech.html
FILE=qemu-$(shell cat VERSION)
VERSION ?= $(shell cat VERSION)
FILE = qemu-$(VERSION)
# tar release (use 'make -k tar' on a checkouted tree)
tar:
@@ -154,6 +163,9 @@ tarbin:
$(datadir)/video.x \
$(datadir)/openbios-sparc32 \
$(datadir)/linux_boot.bin \
$(datadir)/pxe-ne2k_pci.bin \
$(datadir)/pxe-rtl8139.bin \
$(datadir)/pxe-pcnet.bin \
$(docdir)/qemu-doc.html \
$(docdir)/qemu-tech.html \
$(mandir)/man1/qemu.1 $(mandir)/man1/qemu-img.1 )
+125 -79
View File
@@ -12,14 +12,18 @@ TARGET_BASE_ARCH:=sparc
endif
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
DEFINES=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
ifdef CONFIG_USER_ONLY
VPATH+=:$(SRC_PATH)/linux-user
DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
ifdef CONFIG_DARWIN_USER
VPATH+=:$(SRC_PATH)/darwin-user
CPPFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
endif
CFLAGS=-Wall -O2 -g -fno-strict-aliasing
ifdef CONFIG_LINUX_USER
VPATH+=:$(SRC_PATH)/linux-user
CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
endif
BASE_CFLAGS=
BASE_LDFLAGS=
#CFLAGS+=-Werror
LDFLAGS=-g
LIBS=
HELPER_CFLAGS=$(CFLAGS)
DYNGEN=../dyngen$(EXESUF)
@@ -62,18 +66,20 @@ endif
endif # !CONFIG_USER_ONLY
ifdef CONFIG_STATIC
LDFLAGS+=-static
BASE_LDFLAGS+=-static
endif
# We require -O2 to avoid the stack setup prologue in EXIT_TB
OP_CFLAGS = -Wall -O2 -g -fno-strict-aliasing
ifeq ($(ARCH),i386)
CFLAGS+=-fomit-frame-pointer
OP_CFLAGS=$(CFLAGS) -mpreferred-stack-boundary=2
HELPER_CFLAGS+=-fomit-frame-pointer
OP_CFLAGS+=-mpreferred-stack-boundary=2 -fomit-frame-pointer
ifeq ($(HAVE_GCC3_OPTIONS),yes)
OP_CFLAGS+= -falign-functions=0 -fno-gcse
else
OP_CFLAGS+= -malign-functions=0
endif
ifdef TARGET_GPROF
USE_I386_LD=y
endif
@@ -81,76 +87,80 @@ ifdef CONFIG_STATIC
USE_I386_LD=y
endif
ifdef USE_I386_LD
LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386.ld
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
else
ifdef CONFIG_LINUX_USER
# WARNING: this LDFLAGS is _very_ tricky : qemu is an ELF shared object
# that the kernel ELF loader considers as an executable. I think this
# is the simplest way to make it self virtualizable!
LDFLAGS+=-Wl,-shared
BASE_LDFLAGS+=-Wl,-shared
endif
endif
endif
ifeq ($(ARCH),x86_64)
OP_CFLAGS=$(CFLAGS) -falign-functions=0
LDFLAGS+=-Wl,-T,$(SRC_PATH)/x86_64.ld
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
endif
ifeq ($(ARCH),ppc)
CFLAGS+= -D__powerpc__
OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-T,$(SRC_PATH)/ppc.ld
CPPFLAGS+= -D__powerpc__
ifdef CONFIG_LINUX_USER
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
endif
endif
ifeq ($(ARCH),s390)
OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-T,$(SRC_PATH)/s390.ld
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
endif
ifeq ($(ARCH),sparc)
ifeq ($(CONFIG_SOLARIS),yes)
CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
LDFLAGS+=-m32
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
BASE_LDFLAGS+=-m32
OP_CFLAGS+=-fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
else
CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
LDFLAGS+=-m32
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
BASE_LDFLAGS+=-m32
OP_CFLAGS+=-fno-delayed-branch -ffixed-i0
HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
# -static is used to avoid g1/g3 usage by the dynamic linker
LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
endif
endif
ifeq ($(ARCH),sparc64)
CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
LDFLAGS+=-m64
LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
BASE_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
BASE_LDFLAGS+=-m64
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
OP_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7 -fno-delayed-branch -ffixed-i0
endif
ifeq ($(ARCH),alpha)
# -msmall-data is not used because we want two-instruction relocations
# for the constant constructions
OP_CFLAGS=-Wall -O2 -g
# -msmall-data is not used for OP_CFLAGS because we want two-instruction
# relocations for the constant constructions
# Ensure there's only a single GP
CFLAGS += -msmall-data
LDFLAGS+=-Wl,-T,$(SRC_PATH)/alpha.ld
BASE_CFLAGS+=-msmall-data
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
endif
ifeq ($(ARCH),ia64)
CFLAGS += -mno-sdata
OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
BASE_CFLAGS+=-mno-sdata
OP_CFLAGS+=-mno-sdata
BASE_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/$(ARCH).ld
endif
ifeq ($(ARCH),arm)
OP_CFLAGS=$(CFLAGS) -mno-sched-prolog -fno-omit-frame-pointer
LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld
OP_CFLAGS+=-mno-sched-prolog -fno-omit-frame-pointer
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
endif
ifeq ($(ARCH),m68k)
OP_CFLAGS=$(CFLAGS) -fomit-frame-pointer
LDFLAGS+=-Wl,-T,m68k.ld
OP_CFLAGS+=-fomit-frame-pointer
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
endif
ifeq ($(ARCH),mips)
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
endif
ifeq ($(HAVE_GCC3_OPTIONS),yes)
@@ -159,13 +169,19 @@ OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls
endif
ifeq ($(CONFIG_DARWIN),yes)
OP_CFLAGS+= -mdynamic-no-pic
LIBS+=-lmx
endif
ifdef CONFIG_DARWIN_USER
# Leave some space for the regular program loading zone
BASE_LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
endif
OP_CFLAGS+=$(OS_CFLAGS)
#########################################################
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
CPPFLAGS+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
LIBS+=-lm
ifndef CONFIG_USER_ONLY
LIBS+=-lz
@@ -179,10 +195,11 @@ endif
# profiling code
ifdef TARGET_GPROF
LDFLAGS+=-p
main.o: CFLAGS+=-p
BASE_LDFLAGS+=-p
main.o: BASE_CFLAGS+=-p
endif
ifdef CONFIG_LINUX_USER
OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \
elfload.o linuxload.o
ifdef TARGET_HAS_BFLT
@@ -197,6 +214,15 @@ OBJS+=nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \
nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \
nwfpe/double_cpdo.o nwfpe/extended_cpdo.o arm-semi.o
endif
ifeq ($(TARGET_ARCH), m68k)
OBJS+= m68k-sim.o m68k-semi.o
endif
endif #CONFIG_LINUX_USER
ifdef CONFIG_DARWIN_USER
OBJS= main.o commpage.o machload.o mmap.o osdep.o signal.o syscall.o thunk.o
endif
SRCS:= $(OBJS:.o=.c)
OBJS+= libqemu.a
@@ -208,7 +234,7 @@ LIBOBJS+=fpu/softfloat.o
else
LIBOBJS+=fpu/softfloat-native.o
endif
DEFINES+=-I$(SRC_PATH)/fpu
CPPFLAGS+=-I$(SRC_PATH)/fpu
ifeq ($(TARGET_ARCH), i386)
LIBOBJS+=helper.o helper2.o
@@ -241,6 +267,10 @@ ifeq ($(TARGET_BASE_ARCH), sh4)
LIBOBJS+= op_helper.o helper.o
endif
ifeq ($(TARGET_BASE_ARCH), m68k)
LIBOBJS+= helper.o
endif
# NOTE: the disassembler code is only needed for debugging
LIBOBJS+=disas.o
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
@@ -281,7 +311,7 @@ endif
all: $(PROGS)
$(QEMU_USER): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
$(CC) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ $(LIBS)
ifeq ($(ARCH),alpha)
# Mark as 32 bit binary, i. e. it will be mapped into the low 31 bit of
# the address space (31 bit so sign extending doesn't matter)
@@ -289,8 +319,10 @@ ifeq ($(ARCH),alpha)
endif
# must use static linking to avoid leaving stuff in virtual address space
VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o loader.o
VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o isa_mmio.o
VL_OBJS+=cutils.o
VL_OBJS+=block.o block-raw.o
VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o
ifdef CONFIG_WIN32
VL_OBJS+=tap-win32.o
endif
@@ -316,7 +348,7 @@ LIBS += -lole32 -ldxguid
endif
ifdef CONFIG_FMOD
AUDIODRV += fmodaudio.o
audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
audio.o fmodaudio.o: CPPFLAGS := -I$(CONFIG_FMOD_INC) $(CPPFLAGS)
LIBS += $(CONFIG_FMOD_LIB)
endif
ifdef CONFIG_ADLIB
@@ -338,19 +370,21 @@ ifeq ($(TARGET_BASE_ARCH), i386)
VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o acpi.o piix_pci.o
VL_OBJS+= usb-uhci.o
DEFINES += -DHAS_AUDIO
VL_OBJS+= usb-uhci.o smbus_eeprom.o
CPPFLAGS += -DHAS_AUDIO
endif
ifeq ($(TARGET_BASE_ARCH), ppc)
VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
DEFINES += -DHAS_AUDIO
CPPFLAGS += -DHAS_AUDIO
endif
ifeq ($(TARGET_ARCH), mips)
VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o
#VL_OBJS+= #ide.o pckbd.o fdc.o m48t59.o
VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o
VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
DEFINES += -DHAS_AUDIO
endif
ifeq ($(TARGET_BASE_ARCH), sparc)
ifeq ($(TARGET_ARCH), sparc64)
@@ -358,14 +392,17 @@ VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o
VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
VL_OBJS+= cirrus_vga.o parallel.o
else
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t59.o slavio_intctl.o
VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o
VL_OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o
VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o sparc32_dma.o
VL_OBJS+= cs4231.o
endif
endif
ifeq ($(TARGET_BASE_ARCH), arm)
VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl190.o
VL_OBJS+= versatile_pci.o
VL_OBJS+= arm_gic.o realview.o arm_sysctl.o
VL_OBJS+= arm-semi.o
endif
ifeq ($(TARGET_BASE_ARCH), sh4)
VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
@@ -374,7 +411,7 @@ ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o
endif
ifdef CONFIG_SDL
VL_OBJS+=sdl.o
VL_OBJS+=sdl.o x_keymap.o
endif
VL_OBJS+=vnc.o
ifdef CONFIG_COCOA
@@ -385,7 +422,7 @@ COCOA_LIBS+=-framework CoreAudio
endif
endif
ifdef CONFIG_SLIRP
DEFINES+=-I$(SRC_PATH)/slirp
CPPFLAGS+=-I$(SRC_PATH)/slirp
SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \
tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
@@ -408,7 +445,7 @@ endif
endif
endif
ifdef TARGET_GPROF
vl.o: CFLAGS+=-p
vl.o: BASE_CFLAGS+=-p
VL_LDFLAGS+=-p
endif
@@ -429,22 +466,22 @@ $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
cocoa.o: cocoa.m
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
sdl.o: sdl.c keymaps.c sdl_keysym.h
$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
$(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
sdlaudio.o: sdlaudio.c
$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
$(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
depend: $(SRCS)
$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
$(CC) -MM $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $^ 1>.depend
vldepend: $(VL_OBJS:.o=.c)
$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
$(CC) -MM $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $^ 1>.depend
# libqemu
@@ -468,10 +505,26 @@ gen-op.h: op.o $(DYNGEN)
$(DYNGEN) -g -o $@ $<
op.o: op.c
$(CC) $(OP_CFLAGS) $(DEFINES) -c -o $@ $<
$(CC) $(OP_CFLAGS) $(CPPFLAGS) -c -o $@ $<
# HELPER_CFLAGS is used for all the code compiled with static register
# variables
ifeq ($(TARGET_BASE_ARCH), i386)
# XXX: rename helper.c to op_helper.c
helper.o: helper.c
$(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $<
$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
else
op_helper.o: op_helper.c
$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
endif
cpu-exec.o: cpu-exec.c
$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in cpu-exec.c.
signal.o: signal.c
$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
ifeq ($(TARGET_BASE_ARCH), i386)
op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h ops_sse.h
@@ -494,19 +547,12 @@ translate.o: translate.c translate_init.c
endif
ifeq ($(TARGET_ARCH), mips)
op.o: op.c op_template.c op_mem.c
op.o: op.c op_template.c fop_template.c op_mem.c
op_helper.o: op_helper_mem.c
endif
loader.o: loader.c elf_ops.h
acpi.o: acpi.c acpi-dsdt.hex
ifdef BUILD_ACPI_TABLES
$(SRC_PATH)/hw/acpi-dsdt.hex: acpi-dsdt.dsl
iasl -tc -p $@ $<
endif
ifeq ($(TARGET_ARCH), sh4)
op.o: op.c op_mem.c cpu.h
op_helper.o: op_helper.c exec.h cpu.h
@@ -520,10 +566,10 @@ endif
$(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h
%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
%.o: %.S
$(CC) $(DEFINES) -c -o $@ $<
$(CC) $(CPPFLAGS) -c -o $@ $<
clean:
rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o
-16
View File
@@ -1,16 +0,0 @@
Information about the various packages used to build the current qemu
x86 binary distribution:
* gcc 2.95.2 was used for the build. A glibc 2.1.3 Debian distribution
was used to get most of the binary packages.
* wine-20020411 tarball
./configure --prefix=/usr/local/wine-i386
All exe and libs were stripped. Some compile time tools and the
includes were deleted.
* ldconfig was launched to build the library links:
qemu-i386 /usr/gnemul/qemu-i386/bin/ldconfig-i386 -C /usr/gnemul/qemu-i386/etc/ld.so.cache
+1 -1
View File
@@ -1 +1 @@
0.8.2
0.9.0
+458
View File
@@ -0,0 +1,458 @@
/*
* Arm "Angel" semihosting syscalls
*
* Copyright (c) 2005, 2007 CodeSourcery.
* Written by Paul Brook.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "cpu.h"
#ifdef CONFIG_USER_ONLY
#include "qemu.h"
#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
#else
#include "vl.h"
#endif
#define SYS_OPEN 0x01
#define SYS_CLOSE 0x02
#define SYS_WRITEC 0x03
#define SYS_WRITE0 0x04
#define SYS_WRITE 0x05
#define SYS_READ 0x06
#define SYS_READC 0x07
#define SYS_ISTTY 0x09
#define SYS_SEEK 0x0a
#define SYS_FLEN 0x0c
#define SYS_TMPNAM 0x0d
#define SYS_REMOVE 0x0e
#define SYS_RENAME 0x0f
#define SYS_CLOCK 0x10
#define SYS_TIME 0x11
#define SYS_SYSTEM 0x12
#define SYS_ERRNO 0x13
#define SYS_GET_CMDLINE 0x15
#define SYS_HEAPINFO 0x16
#define SYS_EXIT 0x18
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define GDB_O_RDONLY 0x000
#define GDB_O_WRONLY 0x001
#define GDB_O_RDWR 0x002
#define GDB_O_APPEND 0x008
#define GDB_O_CREAT 0x200
#define GDB_O_TRUNC 0x400
#define GDB_O_BINARY 0
static int gdb_open_modeflags[12] = {
GDB_O_RDONLY,
GDB_O_RDONLY | GDB_O_BINARY,
GDB_O_RDWR,
GDB_O_RDWR | GDB_O_BINARY,
GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY,
GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY
};
static int open_modeflags[12] = {
O_RDONLY,
O_RDONLY | O_BINARY,
O_RDWR,
O_RDWR | O_BINARY,
O_WRONLY | O_CREAT | O_TRUNC,
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
O_RDWR | O_CREAT | O_TRUNC,
O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
O_WRONLY | O_CREAT | O_APPEND,
O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
O_RDWR | O_CREAT | O_APPEND,
O_RDWR | O_CREAT | O_APPEND | O_BINARY
};
#ifdef CONFIG_USER_ONLY
static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
{
if (code == (uint32_t)-1)
ts->swi_errno = errno;
return code;
}
#else
static inline uint32_t set_swi_errno(CPUState *env, uint32_t code)
{
return code;
}
static uint32_t softmmu_tget32(CPUState *env, uint32_t addr)
{
uint32_t val;
cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 0);
return tswap32(val);
}
static uint32_t softmmu_tget8(CPUState *env, uint32_t addr)
{
uint8_t val;
cpu_memory_rw_debug(env, addr, &val, 1, 0);
return val;
}
#define tget32(p) softmmu_tget32(env, p)
#define tget8(p) softmmu_tget8(env, p)
static void *softmmu_lock_user(CPUState *env, uint32_t addr, uint32_t len,
int copy)
{
char *p;
/* TODO: Make this something that isn't fixed size. */
p = malloc(len);
if (copy)
cpu_memory_rw_debug(env, addr, p, len, 0);
return p;
}
#define lock_user(p, len, copy) softmmu_lock_user(env, p, len, copy)
static char *softmmu_lock_user_string(CPUState *env, uint32_t addr)
{
char *p;
char *s;
uint8_t c;
/* TODO: Make this something that isn't fixed size. */
s = p = malloc(1024);
do {
cpu_memory_rw_debug(env, addr, &c, 1, 0);
addr++;
*(p++) = c;
} while (c);
return s;
}
#define lock_user_string(p) softmmu_lock_user_string(env, p)
static void softmmu_unlock_user(CPUState *env, void *p, target_ulong addr,
target_ulong len)
{
if (len)
cpu_memory_rw_debug(env, addr, p, len, 1);
free(p);
}
#define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len)
#endif
static target_ulong arm_semi_syscall_len;
static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
{
#ifdef CONFIG_USER_ONLY
TaskState *ts = env->opaque;
#endif
if (ret == (target_ulong)-1) {
#ifdef CONFIG_USER_ONLY
ts->swi_errno = err;
#endif
env->regs[0] = ret;
} else {
/* Fixup syscalls that use nonstardard return conventions. */
switch (env->regs[0]) {
case SYS_WRITE:
case SYS_READ:
env->regs[0] = arm_semi_syscall_len - ret;
break;
case SYS_SEEK:
env->regs[0] = 0;
break;
default:
env->regs[0] = ret;
break;
}
}
}
#define ARG(n) tget32(args + (n) * 4)
#define SET_ARG(n, val) tput32(args + (n) * 4,val)
uint32_t do_arm_semihosting(CPUState *env)
{
target_ulong args;
char * s;
int nr;
uint32_t ret;
uint32_t len;
#ifdef CONFIG_USER_ONLY
TaskState *ts = env->opaque;
#else
CPUState *ts = env;
#endif
nr = env->regs[0];
args = env->regs[1];
switch (nr) {
case SYS_OPEN:
s = lock_user_string(ARG(0));
if (ARG(1) >= 12)
return (uint32_t)-1;
if (strcmp(s, ":tt") == 0) {
if (ARG(1) < 4)
return STDIN_FILENO;
else
return STDOUT_FILENO;
}
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), (int)ARG(2),
gdb_open_modeflags[ARG(1)]);
return env->regs[0];
} else {
ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
}
unlock_user(s, ARG(0), 0);
return ret;
case SYS_CLOSE:
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "close,%x", ARG(0));
return env->regs[0];
} else {
return set_swi_errno(ts, close(ARG(0)));
}
case SYS_WRITEC:
{
char c = tget8(args);
/* Write to debug console. stderr is near enough. */
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args);
return env->regs[0];
} else {
return write(STDERR_FILENO, &c, 1);
}
}
case SYS_WRITE0:
s = lock_user_string(args);
len = strlen(s);
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
ret = env->regs[0];
} else {
ret = write(STDERR_FILENO, s, len);
}
unlock_user(s, args, 0);
return ret;
case SYS_WRITE:
len = ARG(2);
if (use_gdb_syscalls()) {
arm_semi_syscall_len = len;
gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len);
return env->regs[0];
} else {
s = lock_user(ARG(1), len, 1);
ret = set_swi_errno(ts, write(ARG(0), s, len));
unlock_user(s, ARG(1), 0);
if (ret == (uint32_t)-1)
return -1;
return len - ret;
}
case SYS_READ:
len = ARG(2);
if (use_gdb_syscalls()) {
arm_semi_syscall_len = len;
gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len);
return env->regs[0];
} else {
s = lock_user(ARG(1), len, 0);
do
ret = set_swi_errno(ts, read(ARG(0), s, len));
while (ret == -1 && errno == EINTR);
unlock_user(s, ARG(1), len);
if (ret == (uint32_t)-1)
return -1;
return len - ret;
}
case SYS_READC:
/* XXX: Read from debug cosole. Not implemented. */
return 0;
case SYS_ISTTY:
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "isatty,%x", ARG(0));
return env->regs[0];
} else {
return isatty(ARG(0));
}
case SYS_SEEK:
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "fseek,%x,%x,0", ARG(0), ARG(1));
return env->regs[0];
} else {
ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
if (ret == (uint32_t)-1)
return -1;
return 0;
}
case SYS_FLEN:
if (use_gdb_syscalls()) {
/* TODO: Use stat syscall. */
return -1;
} else {
struct stat buf;
ret = set_swi_errno(ts, fstat(ARG(0), &buf));
if (ret == (uint32_t)-1)
return -1;
return buf.st_size;
}
case SYS_TMPNAM:
/* XXX: Not implemented. */
return -1;
case SYS_REMOVE:
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1));
ret = env->regs[0];
} else {
s = lock_user_string(ARG(0));
ret = set_swi_errno(ts, remove(s));
unlock_user(s, ARG(0), 0);
}
return ret;
case SYS_RENAME:
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "rename,%s,%s",
ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
return env->regs[0];
} else {
char *s2;
s = lock_user_string(ARG(0));
s2 = lock_user_string(ARG(2));
ret = set_swi_errno(ts, rename(s, s2));
unlock_user(s2, ARG(2), 0);
unlock_user(s, ARG(0), 0);
return ret;
}
case SYS_CLOCK:
return clock() / (CLOCKS_PER_SEC / 100);
case SYS_TIME:
return set_swi_errno(ts, time(NULL));
case SYS_SYSTEM:
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1));
return env->regs[0];
} else {
s = lock_user_string(ARG(0));
ret = set_swi_errno(ts, system(s));
unlock_user(s, ARG(0), 0);
}
case SYS_ERRNO:
#ifdef CONFIG_USER_ONLY
return ts->swi_errno;
#else
return 0;
#endif
case SYS_GET_CMDLINE:
#ifdef CONFIG_USER_ONLY
/* Build a commandline from the original argv. */
{
char **arg = ts->info->host_argv;
int len = ARG(1);
/* lock the buffer on the ARM side */
char *cmdline_buffer = (char*)lock_user(ARG(0), len, 0);
s = cmdline_buffer;
while (*arg && len > 2) {
int n = strlen(*arg);
if (s != cmdline_buffer) {
*(s++) = ' ';
len--;
}
if (n >= len)
n = len - 1;
memcpy(s, *arg, n);
s += n;
len -= n;
arg++;
}
/* Null terminate the string. */
*s = 0;
len = s - cmdline_buffer;
/* Unlock the buffer on the ARM side. */
unlock_user(cmdline_buffer, ARG(0), len);
/* Adjust the commandline length argument. */
SET_ARG(1, len);
/* Return success if commandline fit into buffer. */
return *arg ? -1 : 0;
}
#else
return -1;
#endif
case SYS_HEAPINFO:
{
uint32_t *ptr;
uint32_t limit;
#ifdef CONFIG_USER_ONLY
/* Some C libraries assume the heap immediately follows .bss, so
allocate it using sbrk. */
if (!ts->heap_limit) {
long ret;
ts->heap_base = do_brk(0);
limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
/* Try a big heap, and reduce the size if that fails. */
for (;;) {
ret = do_brk(limit);
if (ret != -1)
break;
limit = (ts->heap_base >> 1) + (limit >> 1);
}
ts->heap_limit = limit;
}
ptr = lock_user(ARG(0), 16, 0);
ptr[0] = tswap32(ts->heap_base);
ptr[1] = tswap32(ts->heap_limit);
ptr[2] = tswap32(ts->stack_base);
ptr[3] = tswap32(0); /* Stack limit. */
unlock_user(ptr, ARG(0), 16);
#else
limit = ram_size;
ptr = lock_user(ARG(0), 16, 0);
/* TODO: Make this use the limit of the loaded application. */
ptr[0] = tswap32(limit / 2);
ptr[1] = tswap32(limit);
ptr[2] = tswap32(limit); /* Stack base */
ptr[3] = tswap32(0); /* Stack limit. */
unlock_user(ptr, ARG(0), 16);
#endif
return 0;
}
case SYS_EXIT:
exit(0);
default:
fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
cpu_dump_state(env, stderr, fprintf, 0);
abort();
}
}
+25
View File
@@ -53,6 +53,10 @@ SECTIONS
.fini : { *(.fini) } =0x47ff041f
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
.rodata1 : { *(.rodata1) }
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) }
__exidx_start = .;
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
__exidx_end = .;
.reginfo : { *(.reginfo) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
@@ -63,7 +67,28 @@ SECTIONS
*(.gnu.linkonce.d*)
CONSTRUCTORS
}
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.data1 : { *(.data1) }
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
}
.ctors :
{
*(.ctors)
+2 -2
View File
@@ -605,11 +605,11 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
}
if (info->sign) {
memset (buf, len << info->shift, 0x00);
memset (buf, 0x00, len << info->shift);
}
else {
if (info->bits == 8) {
memset (buf, len << info->shift, 0x80);
memset (buf, 0x80, len << info->shift);
}
else {
int i;
+2 -2
View File
@@ -151,7 +151,7 @@ static int wav_init_out (HWVoiceOut *hw, audsettings_t *as)
le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
le_store (hdr + 32, 1 << (bits16 + stereo), 2);
wav->f = fopen (conf.wav_path, "wb");
wav->f = qemu_fopen (conf.wav_path, "wb");
if (!wav->f) {
dolog ("Failed to open wave file `%s'\nReason: %s\n",
conf.wav_path, strerror (errno));
@@ -185,7 +185,7 @@ static void wav_fini_out (HWVoiceOut *hw)
qemu_fseek (wav->f, 32, SEEK_CUR);
qemu_put_buffer (wav->f, dlen, 4);
fclose (wav->f);
qemu_fclose (wav->f);
wav->f = NULL;
qemu_free (wav->pcm_buf);
+15 -16
View File
@@ -34,22 +34,19 @@ static void wav_destroy (void *opaque)
uint32_t datalen = wav->bytes;
uint32_t rifflen = datalen + 36;
if (!wav->f) {
return;
}
le_store (rlen, rifflen, 4);
le_store (dlen, datalen, 4);
qemu_fseek (wav->f, 4, SEEK_SET);
qemu_put_buffer (wav->f, rlen, 4);
qemu_fseek (wav->f, 32, SEEK_CUR);
qemu_put_buffer (wav->f, dlen, 4);
fclose (wav->f);
if (wav->path) {
qemu_free (wav->path);
if (wav->f) {
le_store (rlen, rifflen, 4);
le_store (dlen, datalen, 4);
qemu_fseek (wav->f, 4, SEEK_SET);
qemu_put_buffer (wav->f, rlen, 4);
qemu_fseek (wav->f, 32, SEEK_CUR);
qemu_put_buffer (wav->f, dlen, 4);
qemu_fclose (wav->f);
}
qemu_free (wav->path);
}
static void wav_capture (void *opaque, void *buf, int size)
@@ -135,7 +132,7 @@ int wav_start_capture (CaptureState *s, const char *path, int freq,
le_store (hdr + 28, freq << shift, 4);
le_store (hdr + 32, 1 << shift, 2);
wav->f = fopen (path, "wb");
wav->f = qemu_fopen (path, "wb");
if (!wav->f) {
term_printf ("Failed to open wave file `%s'\nReason: %s\n",
path, strerror (errno));
@@ -153,6 +150,8 @@ int wav_start_capture (CaptureState *s, const char *path, int freq,
cap = AUD_add_capture (NULL, &as, &ops, wav);
if (!cap) {
term_printf ("Failed to add audio capture\n");
qemu_free (wav->path);
qemu_fclose (wav->f);
qemu_free (wav);
return -1;
}
+38 -8
View File
@@ -28,7 +28,8 @@
/**************************************************************/
#define HEADER_MAGIC "Bochs Virtual HD Image"
#define HEADER_VERSION 0x00010000
#define HEADER_VERSION 0x00020000
#define HEADER_V1 0x00010000
#define HEADER_SIZE 512
#define REDOLOG_TYPE "Redolog"
@@ -36,6 +37,26 @@
// not allocated: 0xffffffff
// always little-endian
struct bochs_header_v1 {
char magic[32]; // "Bochs Virtual HD Image"
char type[16]; // "Redolog"
char subtype[16]; // "Undoable" / "Volatile" / "Growing"
uint32_t version;
uint32_t header; // size of header
union {
struct {
uint32_t catalog; // num of entries
uint32_t bitmap; // bitmap size
uint32_t extent; // extent size
uint64_t disk; // disk size
char padding[HEADER_SIZE - 64 - 8 - 20];
} redolog;
char padding[HEADER_SIZE - 64 - 8];
} extra;
};
// always little-endian
struct bochs_header {
char magic[32]; // "Bochs Virtual HD Image"
@@ -49,8 +70,9 @@ struct bochs_header {
uint32_t catalog; // num of entries
uint32_t bitmap; // bitmap size
uint32_t extent; // extent size
uint32_t reserved; // for ???
uint64_t disk; // disk size
char padding[HEADER_SIZE - 64 - 8 - 20];
char padding[HEADER_SIZE - 64 - 8 - 24];
} redolog;
char padding[HEADER_SIZE - 64 - 8];
} extra;
@@ -79,21 +101,23 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
if (!strcmp(bochs->magic, HEADER_MAGIC) &&
!strcmp(bochs->type, REDOLOG_TYPE) &&
!strcmp(bochs->subtype, GROWING_TYPE) &&
(le32_to_cpu(bochs->version) == HEADER_VERSION))
((le32_to_cpu(bochs->version) == HEADER_VERSION) ||
(le32_to_cpu(bochs->version) == HEADER_V1)))
return 100;
return 0;
}
static int bochs_open(BlockDriverState *bs, const char *filename)
static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVBochsState *s = bs->opaque;
int fd, i;
struct bochs_header bochs;
struct bochs_header_v1 header_v1;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
fd = open(filename, O_RDWR | O_BINARY);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
return -1;
}
@@ -109,11 +133,17 @@ static int bochs_open(BlockDriverState *bs, const char *filename)
if (strcmp(bochs.magic, HEADER_MAGIC) ||
strcmp(bochs.type, REDOLOG_TYPE) ||
strcmp(bochs.subtype, GROWING_TYPE) ||
(le32_to_cpu(bochs.version) != HEADER_VERSION)) {
((le32_to_cpu(bochs.version) != HEADER_VERSION) &&
(le32_to_cpu(bochs.version) != HEADER_V1))) {
goto fail;
}
bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
if (le32_to_cpu(bochs.version) == HEADER_V1) {
memcpy(&header_v1, &bochs, sizeof(bochs));
bs->total_sectors = le64_to_cpu(header_v1.extra.redolog.disk) / 512;
} else {
bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
}
lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET);
+3 -3
View File
@@ -50,14 +50,14 @@ static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
return 0;
}
static int cloop_open(BlockDriverState *bs, const char *filename)
static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVCloopState *s = bs->opaque;
uint32_t offsets_size,max_compressed_block_size=1,i;
s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
s->fd = open(filename, O_RDONLY | O_BINARY);
if (s->fd < 0)
return -1;
return -errno;
bs->read_only = 1;
/* read header */
+17 -21
View File
@@ -62,7 +62,7 @@ static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
return 0;
}
static int cow_open(BlockDriverState *bs, const char *filename)
static int cow_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVCowState *s = bs->opaque;
int fd;
@@ -93,22 +93,6 @@ static int cow_open(BlockDriverState *bs, const char *filename)
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
cow_header.backing_file);
#if 0
if (cow_header.backing_file[0] != '\0') {
if (stat(cow_header.backing_file, &st) != 0) {
fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file);
goto fail;
}
if (st.st_mtime != be32_to_cpu(cow_header.mtime)) {
fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file);
goto fail;
}
fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE);
if (fd < 0)
goto fail;
bs->fd = fd;
}
#endif
/* mmap the bitmap */
s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size),
@@ -179,8 +163,15 @@ static int cow_read(BlockDriverState *bs, int64_t sector_num,
if (ret != n * 512)
return -1;
} else {
if (bs->backing_hd) {
/* read from the base image */
ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
if (ret < 0)
return -1;
} else {
memset(buf, 0, n * 512);
}
}
nb_sectors -= n;
sector_num += n;
buf += n * 512;
@@ -220,7 +211,7 @@ static int cow_create(const char *filename, int64_t image_sectors,
if (flags)
return -ENOTSUP;
cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
if (cow_fd < 0)
return -1;
@@ -228,18 +219,23 @@ static int cow_create(const char *filename, int64_t image_sectors,
cow_header.magic = cpu_to_be32(COW_MAGIC);
cow_header.version = cpu_to_be32(COW_VERSION);
if (image_filename) {
/* Note: if no file, we put a dummy mtime */
cow_header.mtime = cpu_to_be32(0);
fd = open(image_filename, O_RDONLY | O_BINARY);
if (fd < 0) {
close(cow_fd);
return -1;
goto mtime_fail;
}
if (fstat(fd, &st) != 0) {
close(fd);
return -1;
goto mtime_fail;
}
close(fd);
cow_header.mtime = cpu_to_be32(st.st_mtime);
realpath(image_filename, cow_header.backing_file);
mtime_fail:
pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
image_filename);
}
cow_header.sectorsize = cpu_to_be32(512);
cow_header.size = cpu_to_be64(image_sectors * 512);
+4 -4
View File
@@ -73,16 +73,16 @@ static off_t read_uint32(int fd)
return be32_to_cpu(buffer);
}
static int dmg_open(BlockDriverState *bs, const char *filename)
static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVDMGState *s = bs->opaque;
off_t info_begin,info_end,last_in_offset,last_out_offset;
uint32_t count;
uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
s->fd = open(filename, O_RDONLY | O_BINARY);
if (s->fd < 0)
return -1;
return -errno;
bs->read_only = 1;
s->n_chunks = 0;
s->offsets = s->lengths = s->sectors = s->sectorcounts = 0;
@@ -93,7 +93,7 @@ dmg_close:
close(s->fd);
/* open raw instead */
bs->drv=&bdrv_raw;
return bs->drv->bdrv_open(bs,filename);
return bs->drv->bdrv_open(bs, filename, flags);
}
info_begin=read_off(s->fd);
if(info_begin==0)
+282 -94
View File
@@ -1,7 +1,7 @@
/*
* Block driver for the QCOW format
*
* Copyright (c) 2004 Fabrice Bellard
* Copyright (c) 2004-2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -53,7 +53,7 @@ typedef struct QCowHeader {
#define L2_CACHE_SIZE 16
typedef struct BDRVQcowState {
int fd;
BlockDriverState *hd;
int cluster_bits;
int cluster_size;
int cluster_sectors;
@@ -89,20 +89,16 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
return 0;
}
static int qcow_open(BlockDriverState *bs, const char *filename)
static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVQcowState *s = bs->opaque;
int fd, len, i, shift;
int len, i, shift, ret;
QCowHeader header;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
}
s->fd = fd;
if (read(fd, &header, sizeof(header)) != sizeof(header))
ret = bdrv_file_open(&s->hd, filename, flags);
if (ret < 0)
return ret;
if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
goto fail;
be32_to_cpus(&header.magic);
be32_to_cpus(&header.version);
@@ -138,8 +134,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
if (!s->l1_table)
goto fail;
lseek(fd, s->l1_table_offset, SEEK_SET);
if (read(fd, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
s->l1_size * sizeof(uint64_t))
goto fail;
for(i = 0;i < s->l1_size; i++) {
@@ -162,8 +157,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
len = header.backing_file_size;
if (len > 1023)
len = 1023;
lseek(fd, header.backing_file_offset, SEEK_SET);
if (read(fd, bs->backing_file, len) != len)
if (bdrv_pread(s->hd, header.backing_file_offset, bs->backing_file, len) != len)
goto fail;
bs->backing_file[len] = '\0';
}
@@ -174,7 +168,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
qemu_free(s->l2_cache);
qemu_free(s->cluster_cache);
qemu_free(s->cluster_data);
close(fd);
bdrv_delete(s->hd);
return -1;
}
@@ -276,14 +270,14 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
if (!allocate)
return 0;
/* allocate a new l2 entry */
l2_offset = lseek(s->fd, 0, SEEK_END);
l2_offset = bdrv_getlength(s->hd);
/* round to cluster size */
l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1);
/* update the L1 entry */
s->l1_table[l1_index] = l2_offset;
tmp = cpu_to_be64(l2_offset);
lseek(s->fd, s->l1_table_offset + l1_index * sizeof(tmp), SEEK_SET);
if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
&tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
new_l2_table = 1;
}
@@ -309,14 +303,13 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
}
}
l2_table = s->l2_cache + (min_index << s->l2_bits);
lseek(s->fd, l2_offset, SEEK_SET);
if (new_l2_table) {
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
if (write(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
if (bdrv_pwrite(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return 0;
} else {
if (read(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return 0;
}
@@ -337,36 +330,35 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
overwritten */
if (decompress_cluster(s, cluster_offset) < 0)
return 0;
cluster_offset = lseek(s->fd, 0, SEEK_END);
cluster_offset = bdrv_getlength(s->hd);
cluster_offset = (cluster_offset + s->cluster_size - 1) &
~(s->cluster_size - 1);
/* write the cluster content */
lseek(s->fd, cluster_offset, SEEK_SET);
if (write(s->fd, s->cluster_cache, s->cluster_size) !=
if (bdrv_pwrite(s->hd, cluster_offset, s->cluster_cache, s->cluster_size) !=
s->cluster_size)
return -1;
} else {
cluster_offset = lseek(s->fd, 0, SEEK_END);
cluster_offset = bdrv_getlength(s->hd);
if (allocate == 1) {
/* round to cluster size */
cluster_offset = (cluster_offset + s->cluster_size - 1) &
~(s->cluster_size - 1);
ftruncate(s->fd, cluster_offset + s->cluster_size);
bdrv_truncate(s->hd, cluster_offset + s->cluster_size);
/* if encrypted, we must initialize the cluster
content which won't be written */
if (s->crypt_method &&
(n_end - n_start) < s->cluster_sectors) {
uint64_t start_sect;
start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
memset(s->cluster_data + 512, 0xaa, 512);
memset(s->cluster_data + 512, 0x00, 512);
for(i = 0; i < s->cluster_sectors; i++) {
if (i < n_start || i >= n_end) {
encrypt_sectors(s, start_sect + i,
s->cluster_data,
s->cluster_data + 512, 1, 1,
&s->aes_encrypt_key);
lseek(s->fd, cluster_offset + i * 512, SEEK_SET);
if (write(s->fd, s->cluster_data, 512) != 512)
if (bdrv_pwrite(s->hd, cluster_offset + i * 512,
s->cluster_data, 512) != 512)
return -1;
}
}
@@ -379,8 +371,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
/* update L2 table */
tmp = cpu_to_be64(cluster_offset);
l2_table[l2_index] = tmp;
lseek(s->fd, l2_offset + l2_index * sizeof(tmp), SEEK_SET);
if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
if (bdrv_pwrite(s->hd,
l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
}
return cluster_offset;
@@ -438,8 +430,7 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
if (s->cluster_cache_offset != coffset) {
csize = cluster_offset >> (63 - s->cluster_bits);
csize &= (s->cluster_size - 1);
lseek(s->fd, coffset, SEEK_SET);
ret = read(s->fd, s->cluster_data, csize);
ret = bdrv_pread(s->hd, coffset, s->cluster_data, csize);
if (ret != csize)
return -1;
if (decompress_buffer(s->cluster_cache, s->cluster_size,
@@ -451,6 +442,8 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
return 0;
}
#if 0
static int qcow_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
@@ -465,14 +458,20 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
if (n > nb_sectors)
n = nb_sectors;
if (!cluster_offset) {
memset(buf, 0, 512 * n);
if (bs->backing_hd) {
/* read from the base image */
ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
if (ret < 0)
return -1;
} else {
memset(buf, 0, 512 * n);
}
} else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
if (decompress_cluster(s, cluster_offset) < 0)
return -1;
memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
} else {
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
if (ret != n * 512)
return -1;
if (s->crypt_method) {
@@ -486,6 +485,7 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
}
return 0;
}
#endif
static int qcow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
@@ -504,13 +504,13 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
index_in_cluster + n);
if (!cluster_offset)
return -1;
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
if (s->crypt_method) {
encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
&s->aes_encrypt_key);
ret = write(s->fd, s->cluster_data, n * 512);
ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512,
s->cluster_data, n * 512);
} else {
ret = write(s->fd, buf, n * 512);
ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
}
if (ret != n * 512)
return -1;
@@ -522,6 +522,209 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
return 0;
}
typedef struct QCowAIOCB {
BlockDriverAIOCB common;
int64_t sector_num;
uint8_t *buf;
int nb_sectors;
int n;
uint64_t cluster_offset;
uint8_t *cluster_data;
BlockDriverAIOCB *hd_aiocb;
} QCowAIOCB;
static void qcow_aio_read_cb(void *opaque, int ret)
{
QCowAIOCB *acb = opaque;
BlockDriverState *bs = acb->common.bs;
BDRVQcowState *s = bs->opaque;
int index_in_cluster;
acb->hd_aiocb = NULL;
if (ret < 0) {
fail:
acb->common.cb(acb->common.opaque, ret);
qemu_aio_release(acb);
return;
}
redo:
/* post process the read buffer */
if (!acb->cluster_offset) {
/* nothing to do */
} else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
/* nothing to do */
} else {
if (s->crypt_method) {
encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf,
acb->n, 0,
&s->aes_decrypt_key);
}
}
acb->nb_sectors -= acb->n;
acb->sector_num += acb->n;
acb->buf += acb->n * 512;
if (acb->nb_sectors == 0) {
/* request completed */
acb->common.cb(acb->common.opaque, 0);
qemu_aio_release(acb);
return;
}
/* prepare next AIO request */
acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9,
0, 0, 0, 0);
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
acb->n = s->cluster_sectors - index_in_cluster;
if (acb->n > acb->nb_sectors)
acb->n = acb->nb_sectors;
if (!acb->cluster_offset) {
if (bs->backing_hd) {
/* read from the base image */
acb->hd_aiocb = bdrv_aio_read(bs->backing_hd,
acb->sector_num, acb->buf, acb->n, qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
goto fail;
} else {
/* Note: in this case, no need to wait */
memset(acb->buf, 0, 512 * acb->n);
goto redo;
}
} else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
/* add AIO support for compressed blocks ? */
if (decompress_cluster(s, acb->cluster_offset) < 0)
goto fail;
memcpy(acb->buf,
s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
goto redo;
} else {
if ((acb->cluster_offset & 511) != 0) {
ret = -EIO;
goto fail;
}
acb->hd_aiocb = bdrv_aio_read(s->hd,
(acb->cluster_offset >> 9) + index_in_cluster,
acb->buf, acb->n, qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
goto fail;
}
}
static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
int64_t sector_num, uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
QCowAIOCB *acb;
acb = qemu_aio_get(bs, cb, opaque);
if (!acb)
return NULL;
acb->hd_aiocb = NULL;
acb->sector_num = sector_num;
acb->buf = buf;
acb->nb_sectors = nb_sectors;
acb->n = 0;
acb->cluster_offset = 0;
qcow_aio_read_cb(acb, 0);
return &acb->common;
}
static void qcow_aio_write_cb(void *opaque, int ret)
{
QCowAIOCB *acb = opaque;
BlockDriverState *bs = acb->common.bs;
BDRVQcowState *s = bs->opaque;
int index_in_cluster;
uint64_t cluster_offset;
const uint8_t *src_buf;
acb->hd_aiocb = NULL;
if (ret < 0) {
fail:
acb->common.cb(acb->common.opaque, ret);
qemu_aio_release(acb);
return;
}
acb->nb_sectors -= acb->n;
acb->sector_num += acb->n;
acb->buf += acb->n * 512;
if (acb->nb_sectors == 0) {
/* request completed */
acb->common.cb(acb->common.opaque, 0);
qemu_aio_release(acb);
return;
}
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
acb->n = s->cluster_sectors - index_in_cluster;
if (acb->n > acb->nb_sectors)
acb->n = acb->nb_sectors;
cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0,
index_in_cluster,
index_in_cluster + acb->n);
if (!cluster_offset || (cluster_offset & 511) != 0) {
ret = -EIO;
goto fail;
}
if (s->crypt_method) {
if (!acb->cluster_data) {
acb->cluster_data = qemu_mallocz(s->cluster_size);
if (!acb->cluster_data) {
ret = -ENOMEM;
goto fail;
}
}
encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
acb->n, 1, &s->aes_encrypt_key);
src_buf = acb->cluster_data;
} else {
src_buf = acb->buf;
}
acb->hd_aiocb = bdrv_aio_write(s->hd,
(cluster_offset >> 9) + index_in_cluster,
src_buf, acb->n,
qcow_aio_write_cb, acb);
if (acb->hd_aiocb == NULL)
goto fail;
}
static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
int64_t sector_num, const uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVQcowState *s = bs->opaque;
QCowAIOCB *acb;
s->cluster_cache_offset = -1; /* disable compressed cache */
acb = qemu_aio_get(bs, cb, opaque);
if (!acb)
return NULL;
acb->hd_aiocb = NULL;
acb->sector_num = sector_num;
acb->buf = (uint8_t *)buf;
acb->nb_sectors = nb_sectors;
acb->n = 0;
qcow_aio_write_cb(acb, 0);
return &acb->common;
}
static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
{
QCowAIOCB *acb = (QCowAIOCB *)blockacb;
if (acb->hd_aiocb)
bdrv_aio_cancel(acb->hd_aiocb);
qemu_aio_release(acb);
}
static void qcow_close(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
@@ -529,7 +732,7 @@ static void qcow_close(BlockDriverState *bs)
qemu_free(s->l2_cache);
qemu_free(s->cluster_cache);
qemu_free(s->cluster_data);
close(s->fd);
bdrv_delete(s->hd);
}
static int qcow_create(const char *filename, int64_t total_size,
@@ -537,12 +740,9 @@ static int qcow_create(const char *filename, int64_t total_size,
{
int fd, header_size, backing_filename_len, l1_size, i, shift;
QCowHeader header;
char backing_filename[1024];
uint64_t tmp;
struct stat st;
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
0644);
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
if (fd < 0)
return -1;
memset(&header, 0, sizeof(header));
@@ -552,28 +752,11 @@ static int qcow_create(const char *filename, int64_t total_size,
header_size = sizeof(header);
backing_filename_len = 0;
if (backing_file) {
if (strcmp(backing_file, "fat:")) {
const char *p;
/* XXX: this is a hack: we do not attempt to check for URL
like syntax */
p = strchr(backing_file, ':');
if (p && (p - backing_file) >= 2) {
/* URL like but exclude "c:" like filenames */
pstrcpy(backing_filename, sizeof(backing_filename),
backing_file);
} else {
realpath(backing_file, backing_filename);
if (stat(backing_filename, &st) != 0) {
return -1;
}
}
header.backing_file_offset = cpu_to_be64(header_size);
backing_filename_len = strlen(backing_filename);
header.backing_file_size = cpu_to_be32(backing_filename_len);
header_size += backing_filename_len;
} else
backing_file = NULL;
header.mtime = cpu_to_be32(st.st_mtime);
header.backing_file_offset = cpu_to_be64(header_size);
backing_filename_len = strlen(backing_file);
header.backing_file_size = cpu_to_be32(backing_filename_len);
header_size += backing_filename_len;
header.mtime = cpu_to_be32(0);
header.cluster_bits = 9; /* 512 byte cluster to avoid copying
unmodifyed sectors */
header.l2_bits = 12; /* 32 KB L2 tables */
@@ -595,7 +778,7 @@ static int qcow_create(const char *filename, int64_t total_size,
/* write all the data */
write(fd, &header, sizeof(header));
if (backing_file) {
write(fd, backing_filename, backing_filename_len);
write(fd, backing_file, backing_filename_len);
}
lseek(fd, header_size, SEEK_SET);
tmp = 0;
@@ -606,16 +789,18 @@ static int qcow_create(const char *filename, int64_t total_size,
return 0;
}
int qcow_make_empty(BlockDriverState *bs)
static int qcow_make_empty(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
uint32_t l1_length = s->l1_size * sizeof(uint64_t);
int ret;
memset(s->l1_table, 0, l1_length);
lseek(s->fd, s->l1_table_offset, SEEK_SET);
if (write(s->fd, s->l1_table, l1_length) < 0)
if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
return -1;
ftruncate(s->fd, s->l1_table_offset + l1_length);
ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
if (ret < 0)
return ret;
memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
@@ -624,18 +809,10 @@ int qcow_make_empty(BlockDriverState *bs)
return 0;
}
int qcow_get_cluster_size(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
if (bs->drv != &bdrv_qcow)
return -1;
return s->cluster_size;
}
/* XXX: put compressed sectors first, then all the cluster aligned
tables to avoid losing bytes in alignment */
int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf)
static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
z_stream strm;
@@ -643,8 +820,8 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
uint8_t *out_buf;
uint64_t cluster_offset;
if (bs->drv != &bdrv_qcow)
return -1;
if (nb_sectors != s->cluster_sectors)
return -EINVAL;
out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);
if (!out_buf)
@@ -682,8 +859,7 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
out_len, 0, 0);
cluster_offset &= s->cluster_offset_mask;
lseek(s->fd, cluster_offset, SEEK_SET);
if (write(s->fd, out_buf, out_len) != out_len) {
if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
qemu_free(out_buf);
return -1;
}
@@ -696,7 +872,14 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
static void qcow_flush(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
fsync(s->fd);
bdrv_flush(s->hd);
}
static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BDRVQcowState *s = bs->opaque;
bdi->cluster_size = s->cluster_size;
return 0;
}
BlockDriver bdrv_qcow = {
@@ -704,14 +887,19 @@ BlockDriver bdrv_qcow = {
sizeof(BDRVQcowState),
qcow_probe,
qcow_open,
qcow_read,
qcow_write,
NULL,
NULL,
qcow_close,
qcow_create,
qcow_flush,
qcow_is_allocated,
qcow_set_key,
qcow_make_empty
qcow_make_empty,
.bdrv_aio_read = qcow_aio_read,
.bdrv_aio_write = qcow_aio_write,
.bdrv_aio_cancel = qcow_aio_cancel,
.aiocb_size = sizeof(QCowAIOCB),
.bdrv_write_compressed = qcow_write_compressed,
.bdrv_get_info = qcow_get_info,
};
+2246
View File
File diff suppressed because it is too large. Load diff
+1352
View File
File diff suppressed because it is too large. Load diff
+354 -46
View File
@@ -22,6 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
#include "block_int.h"
@@ -59,7 +60,7 @@ typedef struct {
#define L2_CACHE_SIZE 16
typedef struct BDRVVmdkState {
int fd;
BlockDriverState *hd;
int64_t l1_table_offset;
int64_t l1_backup_table_offset;
uint32_t *l1_table;
@@ -73,6 +74,7 @@ typedef struct BDRVVmdkState {
uint32_t l2_cache_counts[L2_CACHE_SIZE];
unsigned int cluster_sectors;
uint32_t parent_cid;
} BDRVVmdkState;
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
@@ -89,27 +91,278 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
return 0;
}
static int vmdk_open(BlockDriverState *bs, const char *filename)
#define CHECK_CID 1
#define SECTOR_SIZE 512
#define DESC_SIZE 20*SECTOR_SIZE // 20 sectors of 512 bytes each
#define HEADER_SIZE 512 // first sector of 512 bytes
static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
{
BDRVVmdkState *s = bs->opaque;
int fd, i;
uint32_t magic;
int l1_size;
char desc[DESC_SIZE];
uint32_t cid;
char *p_name, *cid_str;
size_t cid_str_size;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
bs->read_only = 1;
/* the descriptor offset = 0x200 */
if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
return 0;
if (parent) {
cid_str = "parentCID";
cid_str_size = sizeof("parentCID");
} else {
cid_str = "CID";
cid_str_size = sizeof("CID");
}
if (read(fd, &magic, sizeof(magic)) != sizeof(magic))
if ((p_name = strstr(desc,cid_str)) != 0) {
p_name += cid_str_size;
sscanf(p_name,"%x",&cid);
}
return cid;
}
static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
{
BDRVVmdkState *s = bs->opaque;
char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
char *p_name, *tmp_str;
/* the descriptor offset = 0x200 */
if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
return -1;
tmp_str = strstr(desc,"parentCID");
strcpy(tmp_desc, tmp_str);
if ((p_name = strstr(desc,"CID")) != 0) {
p_name += sizeof("CID");
sprintf(p_name,"%x\n",cid);
strcat(desc,tmp_desc);
}
if (bdrv_pwrite(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
return -1;
return 0;
}
static int vmdk_is_cid_valid(BlockDriverState *bs)
{
#ifdef CHECK_CID
BDRVVmdkState *s = bs->opaque;
BlockDriverState *p_bs = s->hd->backing_hd;
uint32_t cur_pcid;
if (p_bs) {
cur_pcid = vmdk_read_cid(p_bs,0);
if (s->parent_cid != cur_pcid)
// CID not valid
return 0;
}
#endif
// CID valid
return 1;
}
static int vmdk_snapshot_create(const char *filename, const char *backing_file)
{
int snp_fd, p_fd;
uint32_t p_cid;
char *p_name, *gd_buf, *rgd_buf;
const char *real_filename, *temp_str;
VMDK4Header header;
uint32_t gde_entries, gd_size;
int64_t gd_offset, rgd_offset, capacity, gt_size;
char p_desc[DESC_SIZE], s_desc[DESC_SIZE], hdr[HEADER_SIZE];
char *desc_template =
"# Disk DescriptorFile\n"
"version=1\n"
"CID=%x\n"
"parentCID=%x\n"
"createType=\"monolithicSparse\"\n"
"parentFileNameHint=\"%s\"\n"
"\n"
"# Extent description\n"
"RW %lu SPARSE \"%s\"\n"
"\n"
"# The Disk Data Base \n"
"#DDB\n"
"\n";
snp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
if (snp_fd < 0)
return -1;
p_fd = open(backing_file, O_RDONLY | O_BINARY | O_LARGEFILE);
if (p_fd < 0) {
close(snp_fd);
return -1;
}
/* read the header */
if (lseek(p_fd, 0x0, SEEK_SET) == -1)
goto fail;
if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE)
goto fail;
/* write the header */
if (lseek(snp_fd, 0x0, SEEK_SET) == -1)
goto fail;
if (write(snp_fd, hdr, HEADER_SIZE) == -1)
goto fail;
memset(&header, 0, sizeof(header));
memcpy(&header,&hdr[4], sizeof(header)); // skip the VMDK4_MAGIC
ftruncate(snp_fd, header.grain_offset << 9);
/* the descriptor offset = 0x200 */
if (lseek(p_fd, 0x200, SEEK_SET) == -1)
goto fail;
if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE)
goto fail;
if ((p_name = strstr(p_desc,"CID")) != 0) {
p_name += sizeof("CID");
sscanf(p_name,"%x",&p_cid);
}
real_filename = filename;
if ((temp_str = strrchr(real_filename, '\\')) != NULL)
real_filename = temp_str + 1;
if ((temp_str = strrchr(real_filename, '/')) != NULL)
real_filename = temp_str + 1;
if ((temp_str = strrchr(real_filename, ':')) != NULL)
real_filename = temp_str + 1;
sprintf(s_desc, desc_template, p_cid, p_cid, backing_file
, (uint32_t)header.capacity, real_filename);
/* write the descriptor */
if (lseek(snp_fd, 0x200, SEEK_SET) == -1)
goto fail;
if (write(snp_fd, s_desc, strlen(s_desc)) == -1)
goto fail;
gd_offset = header.gd_offset * SECTOR_SIZE; // offset of GD table
rgd_offset = header.rgd_offset * SECTOR_SIZE; // offset of RGD table
capacity = header.capacity * SECTOR_SIZE; // Extent size
/*
* Each GDE span 32M disk, means:
* 512 GTE per GT, each GTE points to grain
*/
gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE;
if (!gt_size)
goto fail;
gde_entries = (uint32_t)(capacity / gt_size); // number of gde/rgde
gd_size = gde_entries * sizeof(uint32_t);
/* write RGD */
rgd_buf = qemu_malloc(gd_size);
if (!rgd_buf)
goto fail;
if (lseek(p_fd, rgd_offset, SEEK_SET) == -1)
goto fail_rgd;
if (read(p_fd, rgd_buf, gd_size) != gd_size)
goto fail_rgd;
if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1)
goto fail_rgd;
if (write(snp_fd, rgd_buf, gd_size) == -1)
goto fail_rgd;
qemu_free(rgd_buf);
/* write GD */
gd_buf = qemu_malloc(gd_size);
if (!gd_buf)
goto fail_rgd;
if (lseek(p_fd, gd_offset, SEEK_SET) == -1)
goto fail_gd;
if (read(p_fd, gd_buf, gd_size) != gd_size)
goto fail_gd;
if (lseek(snp_fd, gd_offset, SEEK_SET) == -1)
goto fail_gd;
if (write(snp_fd, gd_buf, gd_size) == -1)
goto fail_gd;
qemu_free(gd_buf);
close(p_fd);
close(snp_fd);
return 0;
fail_gd:
qemu_free(gd_buf);
fail_rgd:
qemu_free(rgd_buf);
fail:
close(p_fd);
close(snp_fd);
return -1;
}
static void vmdk_parent_close(BlockDriverState *bs)
{
if (bs->backing_hd)
bdrv_close(bs->backing_hd);
}
static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
{
BDRVVmdkState *s = bs->opaque;
char *p_name;
char desc[DESC_SIZE];
char parent_img_name[1024];
/* the descriptor offset = 0x200 */
if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
return -1;
if ((p_name = strstr(desc,"parentFileNameHint")) != 0) {
char *end_name;
struct stat file_buf;
p_name += sizeof("parentFileNameHint") + 1;
if ((end_name = strchr(p_name,'\"')) == 0)
return -1;
strncpy(s->hd->backing_file, p_name, end_name - p_name);
if (stat(s->hd->backing_file, &file_buf) != 0) {
path_combine(parent_img_name, sizeof(parent_img_name),
filename, s->hd->backing_file);
} else {
strcpy(parent_img_name, s->hd->backing_file);
}
s->hd->backing_hd = bdrv_new("");
if (!s->hd->backing_hd) {
failure:
bdrv_close(s->hd);
return -1;
}
if (bdrv_open(s->hd->backing_hd, parent_img_name, 0) < 0)
goto failure;
}
return 0;
}
static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVVmdkState *s = bs->opaque;
uint32_t magic;
int l1_size, i, ret;
ret = bdrv_file_open(&s->hd, filename, flags);
if (ret < 0)
return ret;
if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))
goto fail;
magic = be32_to_cpu(magic);
if (magic == VMDK3_MAGIC) {
VMDK3Header header;
if (read(fd, &header, sizeof(header)) !=
sizeof(header))
if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
goto fail;
s->cluster_sectors = le32_to_cpu(header.granularity);
s->l2_size = 1 << 9;
@@ -120,8 +373,8 @@ static int vmdk_open(BlockDriverState *bs, const char *filename)
s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
} else if (magic == VMDK4_MAGIC) {
VMDK4Header header;
if (read(fd, &header, sizeof(header)) != sizeof(header))
if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
goto fail;
bs->total_sectors = le64_to_cpu(header.capacity);
s->cluster_sectors = le64_to_cpu(header.granularity);
@@ -133,17 +386,22 @@ static int vmdk_open(BlockDriverState *bs, const char *filename)
/ s->l1_entry_sectors;
s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
// try to open parent images, if exist
if (vmdk_parent_open(bs, filename) != 0)
goto fail;
// write the CID once after the image creation
s->parent_cid = vmdk_read_cid(bs,1);
} else {
goto fail;
}
/* read the L1 table */
l1_size = s->l1_size * sizeof(uint32_t);
s->l1_table = qemu_malloc(l1_size);
if (!s->l1_table)
goto fail;
if (lseek(fd, s->l1_table_offset, SEEK_SET) == -1)
goto fail;
if (read(fd, s->l1_table, l1_size) != l1_size)
if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, l1_size) != l1_size)
goto fail;
for(i = 0; i < s->l1_size; i++) {
le32_to_cpus(&s->l1_table[i]);
@@ -153,9 +411,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename)
s->l1_backup_table = qemu_malloc(l1_size);
if (!s->l1_backup_table)
goto fail;
if (lseek(fd, s->l1_backup_table_offset, SEEK_SET) == -1)
goto fail;
if (read(fd, s->l1_backup_table, l1_size) != l1_size)
if (bdrv_pread(s->hd, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size)
goto fail;
for(i = 0; i < s->l1_size; i++) {
le32_to_cpus(&s->l1_backup_table[i]);
@@ -165,16 +421,43 @@ static int vmdk_open(BlockDriverState *bs, const char *filename)
s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
if (!s->l2_cache)
goto fail;
s->fd = fd;
return 0;
fail:
qemu_free(s->l1_backup_table);
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
close(fd);
bdrv_delete(s->hd);
return -1;
}
static uint64_t get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate);
static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
uint64_t offset, int allocate)
{
uint64_t parent_cluster_offset;
BDRVVmdkState *s = bs->opaque;
uint8_t whole_grain[s->cluster_sectors*512]; // 128 sectors * 512 bytes each = grain size 64KB
// we will be here if it's first write on non-exist grain(cluster).
// try to read from parent image, if exist
if (s->hd->backing_hd) {
BDRVVmdkState *ps = s->hd->backing_hd->opaque;
if (!vmdk_is_cid_valid(bs))
return -1;
parent_cluster_offset = get_cluster_offset(s->hd->backing_hd, offset, allocate);
if (bdrv_pread(ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512) !=
ps->cluster_sectors*512)
return -1;
if (bdrv_pwrite(s->hd, cluster_offset << 9, whole_grain, sizeof(whole_grain)) !=
sizeof(whole_grain))
return -1;
}
return 0;
}
static uint64_t get_cluster_offset(BlockDriverState *bs,
uint64_t offset, int allocate)
{
@@ -212,34 +495,41 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
}
}
l2_table = s->l2_cache + (min_index * s->l2_size);
lseek(s->fd, (int64_t)l2_offset * 512, SEEK_SET);
if (read(s->fd, l2_table, s->l2_size * sizeof(uint32_t)) !=
s->l2_size * sizeof(uint32_t))
if (bdrv_pread(s->hd, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) !=
s->l2_size * sizeof(uint32_t))
return 0;
s->l2_cache_offsets[min_index] = l2_offset;
s->l2_cache_counts[min_index] = 1;
found:
l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
cluster_offset = le32_to_cpu(l2_table[l2_index]);
if (!cluster_offset) {
struct stat file_buf;
if (!allocate)
return 0;
cluster_offset = lseek(s->fd, 0, SEEK_END);
ftruncate(s->fd, cluster_offset + (s->cluster_sectors << 9));
stat(s->hd->filename, &file_buf);
cluster_offset = file_buf.st_size;
bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
cluster_offset >>= 9;
/* update L2 table */
tmp = cpu_to_le32(cluster_offset);
l2_table[l2_index] = tmp;
lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)),
&tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
/* update backup L2 table */
if (s->l1_backup_table_offset != 0) {
l2_offset = s->l1_backup_table[l1_index];
lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)),
&tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
}
if (get_whole_cluster(bs, cluster_offset, offset, allocate) == -1)
return 0;
}
cluster_offset <<= 9;
return cluster_offset;
@@ -265,9 +555,9 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVVmdkState *s = bs->opaque;
int ret, index_in_cluster, n;
int index_in_cluster, n, ret;
uint64_t cluster_offset;
while (nb_sectors > 0) {
cluster_offset = get_cluster_offset(bs, sector_num << 9, 0);
index_in_cluster = sector_num % s->cluster_sectors;
@@ -275,11 +565,18 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
if (n > nb_sectors)
n = nb_sectors;
if (!cluster_offset) {
memset(buf, 0, 512 * n);
// try to read from parent image, if exist
if (s->hd->backing_hd) {
if (!vmdk_is_cid_valid(bs))
return -1;
ret = bdrv_read(s->hd->backing_hd, sector_num, buf, n);
if (ret < 0)
return -1;
} else {
memset(buf, 0, 512 * n);
}
} else {
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
if (ret != n * 512)
if(bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
return -1;
}
nb_sectors -= n;
@@ -293,8 +590,9 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVVmdkState *s = bs->opaque;
int ret, index_in_cluster, n;
int index_in_cluster, n;
uint64_t cluster_offset;
static int cid_update = 0;
while (nb_sectors > 0) {
index_in_cluster = sector_num & (s->cluster_sectors - 1);
@@ -304,13 +602,17 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
cluster_offset = get_cluster_offset(bs, sector_num << 9, 1);
if (!cluster_offset)
return -1;
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
ret = write(s->fd, buf, n * 512);
if (ret != n * 512)
if (bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
return -1;
nb_sectors -= n;
sector_num += n;
buf += n * 512;
// update CID on the first write every time the virtual disk is opened
if (!cid_update) {
vmdk_write_cid(bs, time(NULL));
cid_update++;
}
}
return 0;
}
@@ -334,7 +636,7 @@ static int vmdk_create(const char *filename, int64_t total_size,
"# The Disk Data Base \n"
"#DDB\n"
"\n"
"ddb.virtualHWVersion = \"3\"\n"
"ddb.virtualHWVersion = \"4\"\n"
"ddb.geometry.cylinders = \"%lu\"\n"
"ddb.geometry.heads = \"16\"\n"
"ddb.geometry.sectors = \"63\"\n"
@@ -343,6 +645,9 @@ static int vmdk_create(const char *filename, int64_t total_size,
const char *real_filename, *temp_str;
/* XXX: add support for backing file */
if (backing_file) {
return vmdk_snapshot_create(filename, backing_file);
}
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
0644);
@@ -421,15 +726,18 @@ static int vmdk_create(const char *filename, int64_t total_size,
static void vmdk_close(BlockDriverState *bs)
{
BDRVVmdkState *s = bs->opaque;
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
close(s->fd);
bdrv_delete(s->hd);
// try to close parent image, if exist
vmdk_parent_close(s->hd);
}
static void vmdk_flush(BlockDriverState *bs)
{
BDRVVmdkState *s = bs->opaque;
fsync(s->fd);
bdrv_flush(s->hd);
}
BlockDriver bdrv_vmdk = {
+5 -8
View File
@@ -86,19 +86,16 @@ static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
return 0;
}
static int vpc_open(BlockDriverState *bs, const char *filename)
static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVVPCState *s = bs->opaque;
int fd, i;
struct vpc_subheader header;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
}
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
return -1;
bs->read_only = 1; // no write support yet
s->fd = fd;
+11 -15
View File
@@ -61,7 +61,7 @@ void nonono(const char* file, int line, const char* msg) {
exit(-5);
}
#undef assert
#define assert(a) if (!(a)) nonono(__FILE__, __LINE__, #a)
#define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0)
#endif
#else
@@ -351,13 +351,6 @@ typedef struct BDRVVVFATState {
} BDRVVVFATState;
static int vvfat_probe(const uint8_t *buf, int buf_size, const char *filename)
{
if (strstart(filename, "fat:", NULL))
return 100;
return 0;
}
static void init_mbr(BDRVVVFATState* s)
{
/* TODO: if the files mbr.img and bootsect.img exist, use them */
@@ -954,18 +947,22 @@ static int init_directories(BDRVVVFATState* s,
return 0;
}
#ifdef DEBUG
static BDRVVVFATState *vvv = NULL;
#endif
static int enable_write_target(BDRVVVFATState *s);
static int is_consistent(BDRVVVFATState *s);
static int vvfat_open(BlockDriverState *bs, const char* dirname)
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
{
BDRVVVFATState *s = bs->opaque;
int floppy = 0;
int i;
#ifdef DEBUG
vvv = s;
#endif
DLOG(if (stderr == NULL) {
stderr = fopen("vvfat.log", "a");
@@ -1040,7 +1037,6 @@ DLOG(if (stderr == NULL) {
bs->heads = bs->cyls = bs->secs = 0;
// assert(is_consistent(s));
return 0;
}
@@ -2178,7 +2174,7 @@ static int commit_one_file(BDRVVVFATState* s,
for (i = s->cluster_size; i < offset; i += s->cluster_size)
c = modified_fat_get(s, c);
fd = open(mapping->path, O_RDWR | O_CREAT, 0666);
fd = open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
if (fd < 0) {
fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
strerror(errno), errno);
@@ -2732,8 +2728,7 @@ static int enable_write_target(BDRVVVFATState *s)
array_init(&(s->commits), sizeof(commit_t));
s->qcow_filename = malloc(1024);
strcpy(s->qcow_filename, "/tmp/vl.XXXXXX");
get_tmp_filename(s->qcow_filename, strlen(s->qcow_filename) + 1);
get_tmp_filename(s->qcow_filename, 1024);
if (bdrv_create(&bdrv_qcow,
s->qcow_filename, s->sector_count, "fat:", 0) < 0)
return -1;
@@ -2767,14 +2762,15 @@ static void vvfat_close(BlockDriverState *bs)
BlockDriver bdrv_vvfat = {
"vvfat",
sizeof(BDRVVVFATState),
vvfat_probe,
NULL, /* no probe for protocols */
vvfat_open,
vvfat_read,
vvfat_write,
vvfat_close,
NULL, /* ??? Not sure if we can do any meaningful flushing. */
NULL,
vvfat_is_allocated
vvfat_is_allocated,
.protocol_name = "fat",
};
#ifdef DEBUG
+888 -398
View File
File diff suppressed because it is too large. Load diff
+56 -5
View File
@@ -28,7 +28,7 @@ struct BlockDriver {
const char *format_name;
int instance_size;
int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
int (*bdrv_open)(BlockDriverState *bs, const char *filename);
int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
@@ -41,13 +41,49 @@ struct BlockDriver {
int nb_sectors, int *pnum);
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
int (*bdrv_make_empty)(BlockDriverState *bs);
/* aio */
BlockDriverAIOCB *(*bdrv_aio_read)(BlockDriverState *bs,
int64_t sector_num, uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
BlockDriverAIOCB *(*bdrv_aio_write)(BlockDriverState *bs,
int64_t sector_num, const uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb);
int aiocb_size;
const char *protocol_name;
int (*bdrv_pread)(BlockDriverState *bs, int64_t offset,
uint8_t *buf, int count);
int (*bdrv_pwrite)(BlockDriverState *bs, int64_t offset,
const uint8_t *buf, int count);
int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
int64_t (*bdrv_getlength)(BlockDriverState *bs);
int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
int (*bdrv_snapshot_create)(BlockDriverState *bs,
QEMUSnapshotInfo *sn_info);
int (*bdrv_snapshot_goto)(BlockDriverState *bs,
const char *snapshot_id);
int (*bdrv_snapshot_delete)(BlockDriverState *bs, const char *snapshot_id);
int (*bdrv_snapshot_list)(BlockDriverState *bs,
QEMUSnapshotInfo **psn_info);
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
/* removable device specific */
int (*bdrv_is_inserted)(BlockDriverState *bs);
int (*bdrv_media_changed)(BlockDriverState *bs);
int (*bdrv_eject)(BlockDriverState *bs, int eject_flag);
int (*bdrv_set_locked)(BlockDriverState *bs, int locked);
BlockDriverAIOCB *free_aiocb;
struct BlockDriver *next;
};
struct BlockDriverState {
int64_t total_sectors;
int64_t total_sectors; /* if we are reading a disk image, give its
size in sectors */
int read_only; /* if true, the media is read only */
int inserted; /* if true, the media is present */
int removable; /* if true, the media can be removed */
int locked; /* if true, the media cannot temporarily be ejected */
int encrypted; /* if true, the media is encrypted */
@@ -55,7 +91,7 @@ struct BlockDriverState {
void (*change_cb)(void *opaque);
void *change_opaque;
BlockDriver *drv;
BlockDriver *drv; /* NULL means no media */
void *opaque;
int boot_sector_enabled;
@@ -65,8 +101,12 @@ struct BlockDriverState {
char backing_file[1024]; /* if non zero, the image is a diff of
this file image */
int is_temporary;
int media_changed;
BlockDriverState *backing_hd;
/* async read/write emulation */
void *sync_aiocb;
/* NOTE: the following infos are only hints for real hardware
drivers. They are not used by the block driver */
@@ -76,6 +116,17 @@ struct BlockDriverState {
BlockDriverState *next;
};
struct BlockDriverAIOCB {
BlockDriverState *bs;
BlockDriverCompletionFunc *cb;
void *opaque;
BlockDriverAIOCB *next;
};
void get_tmp_filename(char *filename, int size);
void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
void *opaque);
void qemu_aio_release(void *p);
#endif /* BLOCK_INT_H */
Executable
+47
View File
@@ -0,0 +1,47 @@
#! /bin/sh
# Script to check for duplicate function prologues in op.o
# Typically this indicates missing FORCE_RET();
# This script does not detect other errors that may be present.
# Usage: check_ops.sh [-m machine] [op.o]
# machine and op.o are guessed if not specified.
if [ "x$1" = "x-m" ]; then
machine=$2
shift 2
else
machine=`uname -m`
fi
if [ -z "$1" ]; then
for f in `find . -name op.o`; do
/bin/sh "$0" -m $machine $f
done
exit 0
fi
case $machine in
i?86)
ret='\tret'
;;
x86_64)
ret='\tretq'
;;
arm)
ret='\tldm.*pc'
;;
ppc* | powerpc*)
ret='\tblr'
;;
mips*)
ret='\tjr.*ra'
;;
*)
echo "Unknown machine `uname -m`"
;;
esac
echo $1
# op_exit_tb causes false positives on some hosts.
${CROSS}objdump -dr $1 | \
sed -e '/>:$\|'"$ret"'/!d' -e 's/.*<\(.*\)>:/~\1:/' -e 's/.*'"$ret"'.*/!/' | \
sed -e ':1;N;s/\n//;t1' | sed -e 's/~/\n/g' | grep -v '^op_exit_tb' | \
grep '^op_.*!!'
Vendored
+131 -45
View File
@@ -22,6 +22,8 @@ interp_prefix="/usr/gnemul/qemu-%M"
static="no"
cross_prefix=""
cc="gcc"
gcc3_search="yes"
gcc3_list="gcc-3.4 gcc34 gcc-3.3 gcc33 gcc-3.2 gcc32"
host_cc="gcc"
ar="ar"
make="make"
@@ -88,14 +90,13 @@ bsd="no"
linux="no"
kqemu="no"
profiler="no"
kernel_path=""
cocoa="no"
check_gfx="yes"
check_gcc="yes"
softmmu="yes"
user="no"
linux_user="no"
darwin_user="no"
build_docs="no"
build_acpi_tables="no"
uname_release=""
# OS specific
@@ -103,7 +104,7 @@ targetos=`uname -s`
case $targetos in
CYGWIN*)
mingw32="yes"
CFLAGS="-O2 -mno-cygwin"
OS_CFLAGS="-mno-cygwin"
;;
MINGW32*)
mingw32="yes"
@@ -126,6 +127,10 @@ oss="yes"
Darwin)
bsd="yes"
darwin="yes"
darwin_user="yes"
cocoa="yes"
coreaudio="yes"
OS_CFLAGS="-mdynamic-no-pic"
;;
SunOS)
solaris="yes"
@@ -133,7 +138,7 @@ solaris="yes"
*)
oss="yes"
linux="yes"
user="yes"
linux_user="yes"
if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
kqemu="yes"
fi
@@ -150,6 +155,11 @@ if [ "$solaris" = "yes" ] ; then
make="gmake"
install="ginstall"
solarisrev=`uname -r | cut -f2 -d.`
if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
if test "$solarisrev" -gt 10 ; then
kqemu="yes"
fi
fi
fi
# find source path
@@ -180,6 +190,7 @@ for opt do
--cross-prefix=*) cross_prefix="$optarg"
;;
--cc=*) cc="$optarg"
gcc3_search="no"
;;
--host-cc=*) host_cc="$optarg"
;;
@@ -223,8 +234,6 @@ for opt do
;;
--enable-profiler) profiler="yes"
;;
--kernel-path=*) kernel_path="$optarg"
;;
--enable-cocoa) cocoa="yes" ; coreaudio="yes" ; sdl="no"
;;
--disable-gfx-check) check_gfx="no"
@@ -235,21 +244,22 @@ for opt do
;;
--enable-system) softmmu="yes"
;;
--disable-user) user="no"
--disable-linux-user) linux_user="no"
;;
--enable-user) user="yes"
--enable-linux-user) linux_user="yes"
;;
--disable-darwin-user) darwin_user="no"
;;
--enable-darwin-user) darwin_user="yes"
;;
--enable-uname-release=*) uname_release="$optarg"
;;
--enable-iasl) build_acpi_tables="yes"
;;
esac
done
# Checking for CFLAGS
if test -z "$CFLAGS"; then
CFLAGS="-O2"
fi
# default flags for all hosts
CFLAGS="$CFLAGS -Wall -O2 -g -fno-strict-aliasing"
LDFLAGS="$LDFLAGS -g"
if test x"$show_help" = x"yes" ; then
cat << EOF
@@ -267,7 +277,6 @@ echo " --target-list=LIST set target list [$target_list]"
echo ""
echo "kqemu kernel acceleration support:"
echo " --disable-kqemu disable kqemu support"
echo " --kernel-path=PATH set the kernel path (configure probes it)"
echo ""
echo "Advanced options (experts only):"
echo " --source-path=PATH path of source code [$source_path]"
@@ -286,14 +295,15 @@ echo " --enable-fmod enable FMOD audio driver"
echo " --enabled-dsound enable DirectSound audio driver"
echo " --enable-system enable all system emulation targets"
echo " --disable-system disable all system emulation targets"
echo " --enable-user enable all linux usermode emulation targets"
echo " --disable-user disable all linux usermode emulation targets"
echo " --enable-linux-user enable all linux usermode emulation targets"
echo " --disable-linux-user disable all linux usermode emulation targets"
echo " --enable-darwin-user enable all darwin usermode emulation targets"
echo " --disable-darwin-user disable all darwin usermode emulation targets"
echo " --fmod-lib path to FMOD library"
echo " --fmod-inc path to FMOD includes"
echo " --enable-uname-release=R Return R for uname -r in usermode emulation"
echo " --enable-iasl compilation of ACPI tables with the IASL compiler"
echo ""
echo "NOTE: The object files are build at the place where configure is launched"
echo "NOTE: The object files are built at the place where configure is launched"
exit 1
fi
@@ -322,6 +332,45 @@ if test "$mingw32" = "yes" ; then
fi
fi
# Check for gcc4, error if pre-gcc4
if test "$check_gcc" = "yes" ; then
cat > $TMPC <<EOF
#if __GNUC__ < 4
#error gcc3
#endif
int main(){return 0;}
EOF
check_cc() {
which "$1" >&/dev/null
return $?
}
if "$cc" -o $TMPE $TMPC 2>/dev/null ; then
echo "WARNING: \"$cc\" looks like gcc 4.x"
found_compat_cc="no"
if test "$gcc3_search" = "yes" ; then
echo "Looking for gcc 3.x"
for compat_cc in $gcc3_list ; do
if check_cc "$compat_cc" ; then
echo "Found \"$compat_cc\""
cc="$compat_cc"
found_compat_cc="yes"
break
fi
done
if test "$found_compat_cc" = "no" ; then
echo "gcc 3.x not found!"
fi
fi
if test "$found_compat_cc" = "no" ; then
echo "QEMU is known to have problems when compiled with gcc 4.x"
echo "It is recommended that you use gcc 3.x to build QEMU"
echo "To use this compiler anyway, configure with --disable-gcc-check"
exit 1;
fi
fi
fi
#
# Solaris specific configure tool chain decisions
#
@@ -369,8 +418,12 @@ if test -z "$target_list" ; then
target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu"
fi
# the following are Linux specific
if [ "$user" = "yes" ] ; then
target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user $target_list"
if [ "$linux_user" = "yes" ] ; then
target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user ppc-linux-user mips-linux-user mipsel-linux-user m68k-linux-user $target_list"
fi
# the following are Darwin specific
if [ "$darwin_user" = "yes" ] ; then
target_list="i386-darwin-user ppc-darwin-user $target_list"
fi
else
target_list=`echo "$target_list" | sed -e 's/,/ /g'`
@@ -424,23 +477,6 @@ if $cc -fno-reorder-blocks -fno-optimize-sibling-calls -o $TMPO $TMPC 2> /dev/nu
have_gcc3_options="yes"
fi
# Check for gcc4, error if pre-gcc4
if test "$check_gcc" = "yes" ; then
cat > $TMPC <<EOF
#if __GNUC__ < 4
#error gcc3
#endif
int main(){return 0;}
EOF
if $cc -o $TMPO $TMPC 2>/dev/null ; then
echo "ERROR: \"$cc\" looks like gcc 4.x"
echo "QEMU is known to have problems when compiled with gcc 4.x"
echo "It is recommended that you use gcc 3.x to build QEMU"
echo "To use this compiler anyway, configure with --disable-gcc-check"
exit 1;
fi
fi
##########################################
# SDL probe
@@ -469,7 +505,9 @@ _sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'`
if test "$_sdlversion" -lt 121 ; then
sdl_too_old=yes
else
sdl=yes
if test "$cocoa" = "no" ; then
sdl=yes
fi
fi
# static link with sdl ?
@@ -490,8 +528,34 @@ fi # static link
fi # sdl compile test
fi # cross compilation
else
# Make sure to disable cocoa if sdl was set
if test "$sdl" = "yes" ; then
cocoa="no"
coreaudio="no"
fi
fi # -z $sdl
##########################################
# alsa sound support libraries
if test "$alsa" = "yes" ; then
cat > $TMPC << EOF
#include <alsa/asoundlib.h>
int main(void) { snd_pcm_t **handle; return snd_pcm_close(*handle); }
EOF
if $cc -o $TMPE $TMPC -lasound 2> /dev/null ; then
:
else
echo
echo "Error: Could not find alsa"
echo "Make sure to have the alsa libs and headers installed."
echo
exit 1
fi
fi
# Check if tools are available to build documentation.
if [ -x "`which texi2html`" ] && [ -x "`which pod2man`" ]; then
build_docs="yes"
@@ -593,6 +657,7 @@ fi
echo "HOST_CC=$host_cc" >> $config_mak
echo "AR=$ar" >> $config_mak
echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak
echo "OS_CFLAGS=$OS_CFLAGS" >> $config_mak
echo "CFLAGS=$CFLAGS" >> $config_mak
echo "LDFLAGS=$LDFLAGS" >> $config_mak
echo "EXESUF=$EXESUF" >> $config_mak
@@ -712,9 +777,6 @@ echo "TARGET_DIRS=$target_list" >> $config_mak
if [ "$build_docs" = "yes" ] ; then
echo "BUILD_DOCS=yes" >> $config_mak
fi
if [ "$build_acpi_tables" = "yes" ] ; then
echo "BUILD_ACPI_TABLES=yes" >> $config_mak
fi
# XXX: suppress that
if [ "$bsd" = "yes" ] ; then
@@ -738,6 +800,7 @@ target_bigendian="no"
[ "$target_cpu" = "ppc64" ] && target_bigendian=yes
[ "$target_cpu" = "mips" ] && target_bigendian=yes
[ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
[ "$target_cpu" = "m68k" ] && target_bigendian=yes
target_softmmu="no"
if expr $target : '.*-softmmu' > /dev/null ; then
target_softmmu="yes"
@@ -747,6 +810,16 @@ if expr $target : '.*-user' > /dev/null ; then
target_user_only="yes"
fi
target_linux_user="no"
if expr $target : '.*-linux-user' > /dev/null ; then
target_linux_user="yes"
fi
target_darwin_user="no"
if expr $target : '.*-darwin-user' > /dev/null ; then
target_darwin_user="yes"
fi
if test "$target_user_only" = "no" -a "$check_gfx" = "yes" \
-a "$sdl" = "no" -a "$cocoa" = "no" ; then
echo "ERROR: QEMU requires SDL or Cocoa for graphical output"
@@ -759,7 +832,7 @@ fi
mkdir -p $target_dir
mkdir -p $target_dir/fpu
if test "$target" = "arm-user" -o "$target" = "armeb-user" ; then
if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then
mkdir -p $target_dir/nwfpe
fi
if test "$target_user_only" = "no" ; then
@@ -833,6 +906,11 @@ elif test "$target_cpu" = "sh4" -o "$target_cpu" = "sh4eb" ; then
echo "#define TARGET_ARCH \"sh4\"" >> $config_h
echo "#define TARGET_SH4 1" >> $config_h
bflt="yes"
elif test "$target_cpu" = "m68k" ; then
echo "TARGET_ARCH=m68k" >> $config_mak
echo "#define TARGET_ARCH \"m68k\"" >> $config_h
echo "#define TARGET_M68K 1" >> $config_h
bflt="yes"
else
echo "Unsupported target CPU"
exit 1
@@ -849,8 +927,16 @@ if test "$target_user_only" = "yes" ; then
echo "CONFIG_USER_ONLY=yes" >> $config_mak
echo "#define CONFIG_USER_ONLY 1" >> $config_h
fi
if test "$target_linux_user" = "yes" ; then
echo "CONFIG_LINUX_USER=yes" >> $config_mak
echo "#define CONFIG_LINUX_USER 1" >> $config_h
fi
if test "$target_darwin_user" = "yes" ; then
echo "CONFIG_DARWIN_USER=yes" >> $config_mak
echo "#define CONFIG_DARWIN_USER 1" >> $config_h
fi
if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64"; then
if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
fi
+168 -42
View File
@@ -121,6 +121,7 @@ struct TextConsole {
int total_height;
int backscroll_height;
int x, y;
int x_saved, y_saved;
int y_displayed;
int y_base;
TextAttributes t_attrib_default; /* default text attributes */
@@ -131,10 +132,7 @@ struct TextConsole {
int esc_params[MAX_ESC_PARAMS];
int nb_esc_params;
/* kbd read handler */
IOCanRWHandler *fd_can_read;
IOReadHandler *fd_read;
void *fd_opaque;
CharDriverState *chr;
/* fifo for key pressed */
QEMUFIFO out_fifo;
uint8_t out_fifo_buf[16];
@@ -147,7 +145,7 @@ static int nb_consoles = 0;
void vga_hw_update(void)
{
if (active_console->hw_update)
if (active_console && active_console->hw_update)
active_console->hw_update(active_console->hw);
}
@@ -659,10 +657,6 @@ static void console_handle_escape(TextConsole *s)
{
int i;
if (s->nb_esc_params == 0) { /* ESC[m sets all attributes to default */
s->t_attrib = s->t_attrib_default;
return;
}
for (i=0; i<s->nb_esc_params; i++) {
switch (s->esc_params[i]) {
case 0: /* reset all console attributes to default */
@@ -752,10 +746,21 @@ static void console_handle_escape(TextConsole *s)
}
}
static void console_clear_xy(TextConsole *s, int x, int y)
{
int y1 = (s->y_base + y) % s->total_height;
TextCell *c = &s->cells[y1 * s->width + x];
c->ch = ' ';
c->t_attrib = s->t_attrib_default;
c++;
update_xy(s, x, y);
}
static void console_putchar(TextConsole *s, int ch)
{
TextCell *c;
int y1, i, x;
int y1, i;
int x, y;
switch(s->state) {
case TTY_STATE_NORM:
@@ -781,20 +786,31 @@ static void console_putchar(TextConsole *s, int ch)
case '\a': /* alert aka. bell */
/* TODO: has to be implemented */
break;
case 14:
/* SI (shift in), character set 0 (ignored) */
break;
case 15:
/* SO (shift out), character set 1 (ignored) */
break;
case 27: /* esc (introducing an escape sequence) */
s->state = TTY_STATE_ESC;
break;
default:
if (s->x >= s->width - 1) {
break;
}
y1 = (s->y_base + s->y) % s->total_height;
c = &s->cells[y1 * s->width + s->x];
c->ch = ch;
c->t_attrib = s->t_attrib;
update_xy(s, s->x, s->y);
s->x++;
#if 0 /* line wrap disabled */
if (s->x >= s->width) {
s->x = 0;
console_put_lf(s);
}
#endif
break;
}
break;
@@ -818,32 +834,150 @@ static void console_putchar(TextConsole *s, int ch)
s->nb_esc_params++;
if (ch == ';')
break;
#ifdef DEBUG_CONSOLE
fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
#endif
s->state = TTY_STATE_NORM;
switch(ch) {
case 'D':
if (s->x > 0)
s->x--;
break;
case 'C':
if (s->x < (s->width - 1))
s->x++;
break;
case 'K':
/* clear to eol */
y1 = (s->y_base + s->y) % s->total_height;
for(x = s->x; x < s->width; x++) {
c = &s->cells[y1 * s->width + x];
c->ch = ' ';
c->t_attrib = s->t_attrib_default;
c++;
update_xy(s, x, s->y);
case 'A':
/* move cursor up */
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->y -= s->esc_params[0];
if (s->y < 0) {
s->y = 0;
}
break;
default:
case 'B':
/* move cursor down */
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->y += s->esc_params[0];
if (s->y >= s->height) {
s->y = s->height - 1;
}
break;
case 'C':
/* move cursor right */
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->x += s->esc_params[0];
if (s->x >= s->width) {
s->x = s->width - 1;
}
break;
case 'D':
/* move cursor left */
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->x -= s->esc_params[0];
if (s->x < 0) {
s->x = 0;
}
break;
case 'G':
/* move cursor to column */
s->x = s->esc_params[0] - 1;
if (s->x < 0) {
s->x = 0;
}
break;
case 'f':
case 'H':
/* move cursor to row, column */
s->x = s->esc_params[1] - 1;
if (s->x < 0) {
s->x = 0;
}
s->y = s->esc_params[0] - 1;
if (s->y < 0) {
s->y = 0;
}
break;
case 'J':
switch (s->esc_params[0]) {
case 0:
/* clear to end of screen */
for (y = s->y; y < s->height; y++) {
for (x = 0; x < s->width; x++) {
if (y == s->y && x < s->x) {
continue;
}
console_clear_xy(s, x, y);
}
}
break;
case 1:
/* clear from beginning of screen */
for (y = 0; y <= s->y; y++) {
for (x = 0; x < s->width; x++) {
if (y == s->y && x > s->x) {
break;
}
console_clear_xy(s, x, y);
}
}
break;
case 2:
/* clear entire screen */
for (y = 0; y <= s->height; y++) {
for (x = 0; x < s->width; x++) {
console_clear_xy(s, x, y);
}
}
break;
}
case 'K':
switch (s->esc_params[0]) {
case 0:
/* clear to eol */
for(x = s->x; x < s->width; x++) {
console_clear_xy(s, x, s->y);
}
break;
case 1:
/* clear from beginning of line */
for (x = 0; x <= s->x; x++) {
console_clear_xy(s, x, s->y);
}
break;
case 2:
/* clear entire line */
for(x = 0; x < s->width; x++) {
console_clear_xy(s, x, s->y);
}
break;
}
break;
case 'm':
console_handle_escape(s);
break;
case 'n':
/* report cursor position */
/* TODO: send ESC[row;colR */
break;
case 's':
/* save cursor position */
s->x_saved = s->x;
s->y_saved = s->y;
break;
case 'u':
/* restore cursor position */
s->x = s->x_saved;
s->y = s->y_saved;
break;
default:
#ifdef DEBUG_CONSOLE
fprintf(stderr, "unhandled escape character '%c'\n", ch);
#endif
break;
}
break;
}
}
}
@@ -884,16 +1018,6 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
return len;
}
static void console_chr_add_read_handler(CharDriverState *chr,
IOCanRWHandler *fd_can_read,
IOReadHandler *fd_read, void *opaque)
{
TextConsole *s = chr->opaque;
s->fd_can_read = fd_can_read;
s->fd_read = fd_read;
s->fd_opaque = opaque;
}
static void console_send_event(CharDriverState *chr, int event)
{
TextConsole *s = chr->opaque;
@@ -915,14 +1039,14 @@ static void kbd_send_chars(void *opaque)
int len;
uint8_t buf[16];
len = s->fd_can_read(s->fd_opaque);
len = qemu_chr_can_read(s->chr);
if (len > s->out_fifo.count)
len = s->out_fifo.count;
if (len > 0) {
if (len > sizeof(buf))
len = sizeof(buf);
qemu_fifo_read(&s->out_fifo, buf, len);
s->fd_read(s->fd_opaque, buf, len);
qemu_chr_read(s->chr, buf, len);
}
/* characters are pending: we send them a bit later (XXX:
horrible, should change char device API) */
@@ -973,7 +1097,7 @@ void kbd_put_keysym(int keysym)
} else {
*q++ = keysym;
}
if (s->fd_read) {
if (s->chr->chr_read) {
qemu_fifo_write(&s->out_fifo, buf, q - buf);
kbd_send_chars(s);
}
@@ -1049,9 +1173,9 @@ CharDriverState *text_console_init(DisplayState *ds)
}
chr->opaque = s;
chr->chr_write = console_puts;
chr->chr_add_read_handler = console_chr_add_read_handler;
chr->chr_send_event = console_send_event;
s->chr = chr;
s->out_fifo.buf = s->out_fifo_buf;
s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
@@ -1086,5 +1210,7 @@ CharDriverState *text_console_init(DisplayState *ds)
s->t_attrib = s->t_attrib_default;
text_console_resize(s);
qemu_chr_reset(chr);
return chr;
}
+18
View File
@@ -725,6 +725,13 @@ void page_unprotect_range(target_ulong data, target_ulong data_size);
#define cpu_gen_code cpu_ppc_gen_code
#define cpu_signal_handler cpu_ppc_signal_handler
#elif defined(TARGET_M68K)
#define CPUState CPUM68KState
#define cpu_init cpu_m68k_init
#define cpu_exec cpu_m68k_exec
#define cpu_gen_code cpu_m68k_gen_code
#define cpu_signal_handler cpu_m68k_signal_handler
#elif defined(TARGET_MIPS)
#define CPUState CPUMIPSState
#define cpu_init cpu_mips_init
@@ -762,6 +769,7 @@ extern int code_copy_enabled;
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
#define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
#define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
#define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */
void cpu_interrupt(CPUState *s, int mask);
void cpu_reset_interrupt(CPUState *env, int mask);
@@ -839,6 +847,7 @@ typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
void cpu_register_physical_memory(target_phys_addr_t start_addr,
unsigned long size,
unsigned long phys_offset);
uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr);
int cpu_register_io_memory(int io_index,
CPUReadMemoryFunc **mem_read,
CPUWriteMemoryFunc **mem_write,
@@ -992,6 +1001,15 @@ static inline int64_t cpu_get_real_ticks (void)
return rval.i64;
#endif
}
#else
/* The host CPU doesn't have an easily accessible cycle counter.
Just return a monotonically increasing vlue. This will be totally wrong,
but hopefully better than nothing. */
static inline int64_t cpu_get_real_ticks (void)
{
static int64_t ticks = 0;
return ticks++;
}
#endif
/* profiling */
+8
View File
@@ -80,6 +80,14 @@ typedef unsigned long ram_addr_t;
#define TB_JMP_CACHE_BITS 12
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
/* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for
addresses on the same page. The top bits are the same. This allows
TLB invalidation to quickly clear a subset of the hash table. */
#define TB_JMP_PAGE_BITS (TB_JMP_CACHE_BITS / 2)
#define TB_JMP_PAGE_SIZE (1 << TB_JMP_PAGE_BITS)
#define TB_JMP_ADDR_MASK (TB_JMP_PAGE_SIZE - 1)
#define TB_JMP_PAGE_MASK (TB_JMP_CACHE_SIZE - TB_JMP_PAGE_SIZE)
#define CPU_TLB_BITS 8
#define CPU_TLB_SIZE (1 << CPU_TLB_BITS)
+120 -116
View File
@@ -40,14 +40,14 @@ int tb_invalidated_flag;
//#define DEBUG_EXEC
//#define DEBUG_SIGNAL
#if defined(TARGET_ARM) || defined(TARGET_SPARC)
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K)
/* XXX: unify with i386 target */
void cpu_loop_exit(void)
{
longjmp(env->jmp_env, 1);
}
#endif
#if !(defined(TARGET_SPARC) || defined(TARGET_SH4))
#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
#define reg_T2
#endif
@@ -194,6 +194,10 @@ static inline TranslationBlock *tb_find_fast(void)
flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
cs_base = 0;
pc = env->PC;
#elif defined(TARGET_M68K)
flags = env->fpcr & M68K_FPCR_PREC;
cs_base = 0;
pc = env->pc;
#elif defined(TARGET_SH4)
flags = env->sr & (SR_MD | SR_RB);
cs_base = 0; /* XXXXX */
@@ -222,43 +226,16 @@ static inline TranslationBlock *tb_find_fast(void)
int cpu_exec(CPUState *env1)
{
int saved_T0, saved_T1;
#if defined(reg_T2)
int saved_T2;
#endif
CPUState *saved_env;
#if defined(TARGET_I386)
#ifdef reg_EAX
int saved_EAX;
#endif
#ifdef reg_ECX
int saved_ECX;
#endif
#ifdef reg_EDX
int saved_EDX;
#endif
#ifdef reg_EBX
int saved_EBX;
#endif
#ifdef reg_ESP
int saved_ESP;
#endif
#ifdef reg_EBP
int saved_EBP;
#endif
#ifdef reg_ESI
int saved_ESI;
#endif
#ifdef reg_EDI
int saved_EDI;
#endif
#elif defined(TARGET_SPARC)
#define DECLARE_HOST_REGS 1
#include "hostregs_helper.h"
#if defined(TARGET_SPARC)
#if defined(reg_REGWPTR)
uint32_t *saved_regwptr;
#endif
#endif
#if defined(__sparc__) && !defined(HOST_SOLARIS)
int saved_i7, tmp_T0;
int saved_i7;
target_ulong tmp_T0;
#endif
int ret, interrupt_request;
void (*gen_func)(void);
@@ -320,44 +297,15 @@ int cpu_exec(CPUState *env1)
cpu_single_env = env1;
/* first we save global registers */
saved_env = env;
#define SAVE_HOST_REGS 1
#include "hostregs_helper.h"
env = env1;
saved_T0 = T0;
saved_T1 = T1;
#if defined(reg_T2)
saved_T2 = T2;
#endif
#if defined(__sparc__) && !defined(HOST_SOLARIS)
/* we also save i7 because longjmp may not restore it */
asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
#endif
#if defined(TARGET_I386)
#ifdef reg_EAX
saved_EAX = EAX;
#endif
#ifdef reg_ECX
saved_ECX = ECX;
#endif
#ifdef reg_EDX
saved_EDX = EDX;
#endif
#ifdef reg_EBX
saved_EBX = EBX;
#endif
#ifdef reg_ESP
saved_ESP = ESP;
#endif
#ifdef reg_EBP
saved_EBP = EBP;
#endif
#ifdef reg_ESI
saved_ESI = ESI;
#endif
#ifdef reg_EDI
saved_EDI = EDI;
#endif
env_to_regs();
/* put eflags in CPU temporary format */
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
@@ -370,6 +318,10 @@ int cpu_exec(CPUState *env1)
saved_regwptr = REGWPTR;
#endif
#elif defined(TARGET_PPC)
#elif defined(TARGET_M68K)
env->cc_op = CC_OP_FLAGS;
env->cc_dest = env->sr & 0xf;
env->cc_x = (env->sr >> 4) & 1;
#elif defined(TARGET_MIPS)
#elif defined(TARGET_SH4)
/* XXXXX */
@@ -390,7 +342,7 @@ int cpu_exec(CPUState *env1)
break;
} else if (env->user_mode_only) {
/* if user mode only, we simulate a fake exception
which will be hanlded outside the cpu execution
which will be handled outside the cpu execution
loop */
#if defined(TARGET_I386)
do_interrupt_user(env->exception_index,
@@ -458,8 +410,16 @@ int cpu_exec(CPUState *env1)
interrupt_request = env->interrupt_request;
if (__builtin_expect(interrupt_request, 0)) {
#if defined(TARGET_I386)
/* if hardware interrupt pending, we execute it */
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
!(env->hflags & HF_SMM_MASK)) {
env->interrupt_request &= ~CPU_INTERRUPT_SMI;
do_smm_enter();
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else
T0 = 0;
#endif
} else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
(env->eflags & IF_MASK) &&
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
int intno;
@@ -519,7 +479,6 @@ int cpu_exec(CPUState *env1)
env->exception_index = EXCP_EXT_INTERRUPT;
env->error_code = 0;
do_interrupt(env);
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else
@@ -548,8 +507,10 @@ int cpu_exec(CPUState *env1)
//do_interrupt(0, 0, 0, 0, 0);
env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
} else if (interrupt_request & CPU_INTERRUPT_HALT) {
env1->halted = 1;
return EXCP_HALTED;
env->interrupt_request &= ~CPU_INTERRUPT_HALT;
env->halted = 1;
env->exception_index = EXCP_HLT;
cpu_loop_exit();
}
#elif defined(TARGET_ARM)
if (interrupt_request & CPU_INTERRUPT_FIQ
@@ -622,6 +583,12 @@ int cpu_exec(CPUState *env1)
cpu_dump_state(env, logfile, fprintf, 0);
#elif defined(TARGET_PPC)
cpu_dump_state(env, logfile, fprintf, 0);
#elif defined(TARGET_M68K)
cpu_m68k_flush_flags(env, env->cc_op);
env->cc_op = CC_OP_FLAGS;
env->sr = (env->sr & 0xffe0)
| env->cc_dest | (env->cc_x << 4);
cpu_dump_state(env, logfile, fprintf, 0);
#elif defined(TARGET_MIPS)
cpu_dump_state(env, logfile, fprintf, 0);
#elif defined(TARGET_SH4)
@@ -803,32 +770,6 @@ int cpu_exec(CPUState *env1)
#endif
/* restore flags in standard format */
env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
/* restore global registers */
#ifdef reg_EAX
EAX = saved_EAX;
#endif
#ifdef reg_ECX
ECX = saved_ECX;
#endif
#ifdef reg_EDX
EDX = saved_EDX;
#endif
#ifdef reg_EBX
EBX = saved_EBX;
#endif
#ifdef reg_ESP
ESP = saved_ESP;
#endif
#ifdef reg_EBP
EBP = saved_EBP;
#endif
#ifdef reg_ESI
ESI = saved_ESI;
#endif
#ifdef reg_EDI
EDI = saved_EDI;
#endif
#elif defined(TARGET_ARM)
/* XXX: Save/restore host fpu exception state?. */
#elif defined(TARGET_SPARC)
@@ -836,21 +777,24 @@ int cpu_exec(CPUState *env1)
REGWPTR = saved_regwptr;
#endif
#elif defined(TARGET_PPC)
#elif defined(TARGET_M68K)
cpu_m68k_flush_flags(env, env->cc_op);
env->cc_op = CC_OP_FLAGS;
env->sr = (env->sr & 0xffe0)
| env->cc_dest | (env->cc_x << 4);
#elif defined(TARGET_MIPS)
#elif defined(TARGET_SH4)
/* XXXXX */
#else
#error unsupported target CPU
#endif
/* restore global registers */
#if defined(__sparc__) && !defined(HOST_SOLARIS)
asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
#endif
T0 = saved_T0;
T1 = saved_T1;
#if defined(reg_T2)
T2 = saved_T2;
#endif
env = saved_env;
#include "hostregs_helper.h"
/* fail safe : never use cpu_single_env outside cpu_exec() */
cpu_single_env = NULL;
return ret;
@@ -1093,6 +1037,45 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
return 1;
}
#elif defined(TARGET_M68K)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
int is_write, sigset_t *old_set,
void *puc)
{
TranslationBlock *tb;
int ret;
if (cpu_single_env)
env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
pc, address, is_write, *(unsigned long *)old_set);
#endif
/* XXX: locking issue */
if (is_write && page_unprotect(address, pc, puc)) {
return 1;
}
/* see if it is an MMU fault */
ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
return 1; /* the MMU fault was handled without causing real CPU fault */
/* now we have a real cpu fault */
tb = tb_find_pc(pc);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
cpu_restore_state(tb, env, pc, puc);
}
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
cpu_loop_exit();
/* never comes here */
return 1;
}
#elif defined (TARGET_MIPS)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
int is_write, sigset_t *old_set,
@@ -1193,6 +1176,18 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
#if defined(__i386__)
#if defined(__APPLE__)
# include <sys/ucontext.h>
# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
#else
# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
#endif
#if defined(USE_CODE_COPY)
static void cpu_send_trap(unsigned long pc, int trap,
struct ucontext *uc)
@@ -1213,9 +1208,10 @@ static void cpu_send_trap(unsigned long pc, int trap,
}
#endif
int cpu_signal_handler(int host_signum, struct siginfo *info,
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
int trapno;
@@ -1226,8 +1222,8 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
#define REG_ERR ERR
#define REG_TRAPNO TRAPNO
#endif
pc = uc->uc_mcontext.gregs[REG_EIP];
trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
pc = EIP_sig(uc);
trapno = TRAP_sig(uc);
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
if (trapno == 0x00 || trapno == 0x05) {
/* send division by zero or bound exception */
@@ -1237,15 +1233,16 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
#endif
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
trapno == 0xe ?
(uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
(ERROR_sig(uc) >> 1) & 1 : 0,
&uc->uc_sigmask, puc);
}
#elif defined(__x86_64__)
int cpu_signal_handler(int host_signum, struct siginfo *info,
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
@@ -1307,9 +1304,10 @@ typedef struct ucontext SIGCONTEXT;
# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
#endif /* __APPLE__ */
int cpu_signal_handler(int host_signum, struct siginfo *info,
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
int is_write;
@@ -1330,9 +1328,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
#elif defined(__alpha__)
int cpu_signal_handler(int host_signum, struct siginfo *info,
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
uint32_t *pc = uc->uc_mcontext.sc_pc;
uint32_t insn = *pc;
@@ -1359,9 +1358,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
}
#elif defined(__sparc__)
int cpu_signal_handler(int host_signum, struct siginfo *info,
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
uint32_t *regs = (uint32_t *)(info + 1);
void *sigmask = (regs + 20);
unsigned long pc;
@@ -1392,9 +1392,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
#elif defined(__arm__)
int cpu_signal_handler(int host_signum, struct siginfo *info,
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
int is_write;
@@ -1404,14 +1405,15 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
is_write = 0;
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write,
&uc->uc_sigmask);
&uc->uc_sigmask, puc);
}
#elif defined(__mc68000)
int cpu_signal_handler(int host_signum, struct siginfo *info,
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
int is_write;
@@ -1431,8 +1433,9 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
# define __ISR_VALID 1
#endif
int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long ip;
int is_write = 0;
@@ -1459,9 +1462,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
#elif defined(__s390__)
int cpu_signal_handler(int host_signum, struct siginfo *info,
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
int is_write;
+83
View File
@@ -0,0 +1,83 @@
/*
* Simple C functions to supplement the C library
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
void pstrcpy(char *buf, int buf_size, const char *str)
{
int c;
char *q = buf;
if (buf_size <= 0)
return;
for(;;) {
c = *str++;
if (c == 0 || q >= buf + buf_size - 1)
break;
*q++ = c;
}
*q = '\0';
}
/* strcat and truncate. */
char *pstrcat(char *buf, int buf_size, const char *s)
{
int len;
len = strlen(buf);
if (len < buf_size)
pstrcpy(buf + len, buf_size - len, s);
return buf;
}
int strstart(const char *str, const char *val, const char **ptr)
{
const char *p, *q;
p = str;
q = val;
while (*q != '\0') {
if (*p != *q)
return 0;
p++;
q++;
}
if (ptr)
*ptr = p;
return 1;
}
int stristart(const char *str, const char *val, const char **ptr)
{
const char *p, *q;
p = str;
q = val;
while (*q != '\0') {
if (toupper(*p) != toupper(*q))
return 0;
p++;
q++;
}
if (ptr)
*ptr = p;
return 1;
}
+358
View File
@@ -0,0 +1,358 @@
/*
* Commpage syscalls
*
* Copyright (c) 2006 Pierre d'Herbemont
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <mach/message.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <libkern/OSAtomic.h>
#include "qemu.h"
//#define DEBUG_COMMPAGE
#ifdef DEBUG_COMMPAGE
# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0)
#else
# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
#endif
/********************************************************************
* Commpage definitions
*/
#ifdef TARGET_I386
/* Reserve space for the commpage see xnu/osfmk/i386/cpu_capabilities.h */
# define COMMPAGE_START (-16 * 4096) /* base address is -20 * 4096 */
# define COMMPAGE_SIZE (0x1240) /* _COMM_PAGE_AREA_LENGTH is 19 * 4096 */
#elif defined(TARGET_PPC)
/* Reserve space for the commpage see xnu/osfmk/ppc/cpu_capabilities.h */
# define COMMPAGE_START (-8*4096)
# define COMMPAGE_SIZE (2*4096) /* its _COMM_PAGE_AREA_USED but _COMM_PAGE_AREA_LENGTH is 7*4096 */
#endif
void do_compare_and_swap32(void *cpu_env, int num);
void do_compare_and_swap64(void *cpu_env, int num);
void do_add_atomic_word32(void *cpu_env, int num);
void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1);
void do_nanotime(void *cpu_env, int num);
void unimpl_commpage(void *cpu_env, int num);
typedef void (*commpage_8args_function_t)(uint32_t arg1, uint32_t arg2, uint32_t arg3,
uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
uint32_t arg8);
typedef void (*commpage_indirect_function_t)(void *cpu_env, int num, uint32_t arg1,
uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5,
uint32_t arg6, uint32_t arg7, uint32_t arg8);
#define HAS_PTR 0x10
#define NO_PTR 0x20
#define CALL_DIRECT 0x1
#define CALL_INDIRECT 0x2
#define COMMPAGE_ENTRY(name, nargs, offset, func, options) \
{ #name, offset, nargs, options, (commpage_8args_function_t)func }
struct commpage_entry {
char * name;
int offset;
int nargs;
char options;
commpage_8args_function_t function;
};
static inline int commpage_code_num(struct commpage_entry *entry)
{
if((entry->options & HAS_PTR))
return entry->offset + 4;
else
return entry->offset;
}
static inline int commpage_is_indirect(struct commpage_entry *entry)
{
return !(entry->options & CALL_DIRECT);
}
/********************************************************************
* Commpage entry
*/
static struct commpage_entry commpage_entries[] =
{
COMMPAGE_ENTRY(compare_and_swap32, 0, 0x080, do_compare_and_swap32, CALL_INDIRECT | HAS_PTR),
COMMPAGE_ENTRY(compare_and_swap64, 0, 0x0c0, do_compare_and_swap64, CALL_INDIRECT | HAS_PTR),
COMMPAGE_ENTRY(enqueue, 0, 0x100, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(dequeue, 0, 0x140, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(memory_barrier, 0, 0x180, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(add_atomic_word32, 0, 0x1a0, do_add_atomic_word32, CALL_INDIRECT | HAS_PTR),
COMMPAGE_ENTRY(add_atomic_word64, 0, 0x1c0, unimpl_commpage, CALL_INDIRECT | HAS_PTR),
COMMPAGE_ENTRY(mach_absolute_time, 0, 0x200, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(spinlock_try, 1, 0x220, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(spinlock_lock, 1, 0x260, OSSpinLockLock, CALL_DIRECT),
COMMPAGE_ENTRY(spinlock_unlock, 1, 0x2a0, OSSpinLockUnlock, CALL_DIRECT),
COMMPAGE_ENTRY(pthread_getspecific, 0, 0x2c0, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(gettimeofday, 1, 0x2e0, do_cgettimeofday, CALL_INDIRECT),
COMMPAGE_ENTRY(sys_dcache_flush, 0, 0x4e0, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(sys_icache_invalidate, 0, 0x520, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(pthread_self, 0, 0x580, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(relinquish, 0, 0x5c0, unimpl_commpage, CALL_INDIRECT),
#ifdef TARGET_I386
COMMPAGE_ENTRY(bts, 0, 0x5e0, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(btc, 0, 0x5f0, unimpl_commpage, CALL_INDIRECT),
#endif
COMMPAGE_ENTRY(bzero, 2, 0x600, bzero, CALL_DIRECT),
COMMPAGE_ENTRY(bcopy, 3, 0x780, bcopy, CALL_DIRECT),
COMMPAGE_ENTRY(memcpy, 3, 0x7a0, memcpy, CALL_DIRECT),
#ifdef TARGET_I386
COMMPAGE_ENTRY(old_nanotime, 0, 0xf80, do_nanotime, CALL_INDIRECT),
COMMPAGE_ENTRY(memset_pattern, 0, 0xf80, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(long_copy, 0, 0x1200, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(sysintegrity, 0, 0x1600, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(nanotime, 0, 0x1700, do_nanotime, CALL_INDIRECT),
#elif TARGET_PPC
COMMPAGE_ENTRY(compare_and_swap32b, 0, 0xf80, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(compare_and_swap64b, 0, 0xfc0, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(memset_pattern, 0, 0x1000, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(bigcopy, 0, 0x1140, unimpl_commpage, CALL_INDIRECT),
#endif
};
/********************************************************************
* Commpage backdoor
*/
static inline void print_commpage_entry(struct commpage_entry entry)
{
printf("@0x%x %s\n", entry.offset, entry.name);
}
static inline void install_commpage_backdoor_for_entry(struct commpage_entry entry)
{
#ifdef TARGET_I386
char * commpage = (char*)(COMMPAGE_START+entry.offset);
int c = 0;
if(entry.options & HAS_PTR)
{
commpage[c++] = (COMMPAGE_START+entry.offset+4) & 0xff;
commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 8) & 0xff;
commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 16) & 0xff;
commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 24) & 0xff;
}
commpage[c++] = 0xcd;
commpage[c++] = 0x79; /* int 0x79 */
commpage[c++] = 0xc3; /* ret */
#else
qerror("can't install the commpage on this arch\n");
#endif
}
/********************************************************************
* Commpage initialization
*/
void commpage_init(void)
{
#if (defined(__i386__) ^ defined(TARGET_I386)) || (defined(__powerpc__) ^ defined(TARGET_PPC))
int i;
void * commpage = (void *)target_mmap( COMMPAGE_START, COMMPAGE_SIZE,
PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if((int)commpage != COMMPAGE_START)
qerror("can't allocate the commpage\n");
bzero(commpage, COMMPAGE_SIZE);
/* XXX: commpage data not handled */
for(i = 0; i < sizeof(commpage_entries)/sizeof(commpage_entries[0]); i++)
install_commpage_backdoor_for_entry(commpage_entries[i]);
#else
/* simply map our pages so they can be executed
XXX: we don't really want to do that since in the ppc on ppc situation we may
not able to run commpages host optimized instructions (like G5's on a G5),
hence this is sometimes a broken fix. */
page_set_flags(COMMPAGE_START, COMMPAGE_START+COMMPAGE_SIZE, PROT_EXEC | PROT_READ | PAGE_VALID);
#endif
}
/********************************************************************
* Commpage implementation
*/
void do_compare_and_swap32(void *cpu_env, int num)
{
#ifdef TARGET_I386
uint32_t old = ((CPUX86State*)cpu_env)->regs[R_EAX];
uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_ECX];
DPRINTF("commpage: compare_and_swap32(%x,new,%p)\n", old, value);
if(value && old == tswap32(*value))
{
uint32_t new = ((CPUX86State*)cpu_env)->regs[R_EDX];
*value = tswap32(new);
/* set zf flag */
((CPUX86State*)cpu_env)->eflags |= 0x40;
}
else
{
((CPUX86State*)cpu_env)->regs[R_EAX] = tswap32(*value);
/* unset zf flag */
((CPUX86State*)cpu_env)->eflags &= ~0x40;
}
#else
qerror("do_compare_and_swap32 unimplemented");
#endif
}
void do_compare_and_swap64(void *cpu_env, int num)
{
#ifdef TARGET_I386
/* OSAtomicCompareAndSwap64 is not available on non 64 bits ppc, here is a raw implementation */
uint64_t old, new, swapped_val;
uint64_t *value = (uint64_t*)((CPUX86State*)cpu_env)->regs[R_ESI];
old = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_EDX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EAX];
DPRINTF("commpage: compare_and_swap64(%llx,new,%p)\n", old, value);
swapped_val = tswap64(*value);
if(old == swapped_val)
{
new = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_ECX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EBX];
*value = tswap64(new);
/* set zf flag */
((CPUX86State*)cpu_env)->eflags |= 0x40;
}
else
{
((CPUX86State*)cpu_env)->regs[R_EAX] = (uint32_t)(swapped_val);
((CPUX86State*)cpu_env)->regs[R_EDX] = (uint32_t)(swapped_val >> 32);
/* unset zf flag */
((CPUX86State*)cpu_env)->eflags &= ~0x40;
}
#else
qerror("do_compare_and_swap64 unimplemented");
#endif
}
void do_add_atomic_word32(void *cpu_env, int num)
{
#ifdef TARGET_I386
uint32_t amt = ((CPUX86State*)cpu_env)->regs[R_EAX];
uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_EDX];
uint32_t swapped_value = tswap32(*value);
DPRINTF("commpage: add_atomic_word32(%x,%p)\n", amt, value);
/* old value in EAX */
((CPUX86State*)cpu_env)->regs[R_EAX] = swapped_value;
*value = tswap32(swapped_value + amt);
#else
qerror("do_add_atomic_word32 unimplemented");
#endif
}
void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1)
{
#ifdef TARGET_I386
extern int __commpage_gettimeofday(struct timeval *);
DPRINTF("commpage: gettimeofday(0x%x)\n", arg1);
struct timeval *time = (struct timeval *)arg1;
int ret = __commpage_gettimeofday(time);
tswap32s((uint32_t*)&time->tv_sec);
tswap32s((uint32_t*)&time->tv_usec);
((CPUX86State*)cpu_env)->regs[R_EAX] = ret; /* Success */
#else
qerror("do_gettimeofday unimplemented");
#endif
}
void do_nanotime(void *cpu_env, int num)
{
#ifdef TARGET_I386
uint64_t t = mach_absolute_time();
((CPUX86State*)cpu_env)->regs[R_EAX] = (int)(t & 0xffffffff);
((CPUX86State*)cpu_env)->regs[R_EDX] = (int)((t >> 32) & 0xffffffff);
#else
qerror("do_nanotime unimplemented");
#endif
}
void unimpl_commpage(void *cpu_env, int num)
{
qerror("qemu: commpage function 0x%x not implemented\n", num);
}
/********************************************************************
* do_commpage - called by the main cpu loop
*/
void
do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
uint32_t arg8)
{
int i, found = 0;
arg1 = tswap32(arg1);
arg2 = tswap32(arg2);
arg3 = tswap32(arg3);
arg4 = tswap32(arg4);
arg5 = tswap32(arg5);
arg6 = tswap32(arg6);
arg7 = tswap32(arg7);
arg8 = tswap32(arg8);
num = num-COMMPAGE_START-2;
for(i = 0; i < sizeof(commpage_entries)/sizeof(commpage_entries[0]); i++) {
if( num == commpage_code_num(&commpage_entries[i]) )
{
DPRINTF("commpage: %s %s\n", commpage_entries[i].name, commpage_is_indirect(&commpage_entries[i]) ? "[indirect]" : "[direct]");
found = 1;
if(commpage_is_indirect(&commpage_entries[i]))
{
commpage_indirect_function_t function = (commpage_indirect_function_t)commpage_entries[i].function;
function(cpu_env, num, arg1, arg2, arg3,
arg4, arg5, arg6, arg7, arg8);
}
else
{
commpage_entries[i].function(arg1, arg2, arg3,
arg4, arg5, arg6, arg7, arg8);
}
break;
}
}
if(!found)
{
gemu_log("qemu: commpage function 0x%x not defined\n", num);
gdb_handlesig (cpu_env, SIGTRAP);
exit(-1);
}
}
+4
View File
@@ -0,0 +1,4 @@
/* emulated ioctl list */
IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+1
View File
@@ -0,0 +1 @@
STRUCT(termios, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_CHAR, 20), TYPE_INT, TYPE_INT)
+903
View File
@@ -0,0 +1,903 @@
/*
* Mach-O object file loading
*
* Copyright (c) 2006 Pierre d'Herbemont
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>
#include "qemu.h"
#include "disas.h"
#include <mach-o/loader.h>
#include <mach-o/fat.h>
#include <mach-o/nlist.h>
#include <mach-o/reloc.h>
#include <mach-o/ppc/reloc.h>
//#define DEBUG_MACHLOAD
#ifdef DEBUG_MACHLOAD
# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0)
#else
# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
#endif
# define check_mach_header(x) (x.magic == MH_CIGAM)
extern const char *interp_prefix;
/* we don't have a good implementation for this */
#define DONT_USE_DYLD_SHARED_MAP
/* Pass extra arg to DYLD for debug */
//#define ACTIVATE_DYLD_TRACE
//#define OVERRIDE_DYLINKER
#ifdef OVERRIDE_DYLINKER
# ifdef TARGET_I386
# define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld"
# else
# define DYLINKER_NAME "/usr/lib/dyld"
# endif
#endif
/* XXX: in an include */
struct nlist_extended
{
union {
char *n_name;
long n_strx;
} n_un;
unsigned char n_type;
unsigned char n_sect;
short st_desc;
unsigned long st_value;
unsigned long st_size;
};
/* Print symbols in gdb */
void *macho_text_sect = 0;
int macho_offset = 0;
int load_object(const char *filename, struct target_pt_regs * regs, void ** mh);
void qerror(const char *format, ...);
#ifdef TARGET_I386
typedef struct mach_i386_thread_state {
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
unsigned int edi;
unsigned int esi;
unsigned int ebp;
unsigned int esp;
unsigned int ss;
unsigned int eflags;
unsigned int eip;
unsigned int cs;
unsigned int ds;
unsigned int es;
unsigned int fs;
unsigned int gs;
} mach_i386_thread_state_t;
void bswap_i386_thread_state(struct mach_i386_thread_state *ts)
{
bswap32s((uint32_t*)&ts->eax);
bswap32s((uint32_t*)&ts->ebx);
bswap32s((uint32_t*)&ts->ecx);
bswap32s((uint32_t*)&ts->edx);
bswap32s((uint32_t*)&ts->edi);
bswap32s((uint32_t*)&ts->esi);
bswap32s((uint32_t*)&ts->ebp);
bswap32s((uint32_t*)&ts->esp);
bswap32s((uint32_t*)&ts->ss);
bswap32s((uint32_t*)&ts->eflags);
bswap32s((uint32_t*)&ts->eip);
bswap32s((uint32_t*)&ts->cs);
bswap32s((uint32_t*)&ts->ds);
bswap32s((uint32_t*)&ts->es);
bswap32s((uint32_t*)&ts->fs);
bswap32s((uint32_t*)&ts->gs);
}
#define target_thread_state mach_i386_thread_state
#define TARGET_CPU_TYPE CPU_TYPE_I386
#define TARGET_CPU_NAME "i386"
#endif
#ifdef TARGET_PPC
struct mach_ppc_thread_state {
unsigned int srr0; /* Instruction address register (PC) */
unsigned int srr1; /* Machine state register (supervisor) */
unsigned int r0;
unsigned int r1;
unsigned int r2;
unsigned int r3;
unsigned int r4;
unsigned int r5;
unsigned int r6;
unsigned int r7;
unsigned int r8;
unsigned int r9;
unsigned int r10;
unsigned int r11;
unsigned int r12;
unsigned int r13;
unsigned int r14;
unsigned int r15;
unsigned int r16;
unsigned int r17;
unsigned int r18;
unsigned int r19;
unsigned int r20;
unsigned int r21;
unsigned int r22;
unsigned int r23;
unsigned int r24;
unsigned int r25;
unsigned int r26;
unsigned int r27;
unsigned int r28;
unsigned int r29;
unsigned int r30;
unsigned int r31;
unsigned int cr; /* Condition register */
unsigned int xer; /* User's integer exception register */
unsigned int lr; /* Link register */
unsigned int ctr; /* Count register */
unsigned int mq; /* MQ register (601 only) */
unsigned int vrsave; /* Vector Save Register */
};
void bswap_ppc_thread_state(struct mach_ppc_thread_state *ts)
{
bswap32s((uint32_t*)&ts->srr0);
bswap32s((uint32_t*)&ts->srr1);
bswap32s((uint32_t*)&ts->r0);
bswap32s((uint32_t*)&ts->r1);
bswap32s((uint32_t*)&ts->r2);
bswap32s((uint32_t*)&ts->r3);
bswap32s((uint32_t*)&ts->r4);
bswap32s((uint32_t*)&ts->r5);
bswap32s((uint32_t*)&ts->r6);
bswap32s((uint32_t*)&ts->r7);
bswap32s((uint32_t*)&ts->r8);
bswap32s((uint32_t*)&ts->r9);
bswap32s((uint32_t*)&ts->r10);
bswap32s((uint32_t*)&ts->r11);
bswap32s((uint32_t*)&ts->r12);
bswap32s((uint32_t*)&ts->r13);
bswap32s((uint32_t*)&ts->r14);
bswap32s((uint32_t*)&ts->r15);
bswap32s((uint32_t*)&ts->r16);
bswap32s((uint32_t*)&ts->r17);
bswap32s((uint32_t*)&ts->r18);
bswap32s((uint32_t*)&ts->r19);
bswap32s((uint32_t*)&ts->r20);
bswap32s((uint32_t*)&ts->r21);
bswap32s((uint32_t*)&ts->r22);
bswap32s((uint32_t*)&ts->r23);
bswap32s((uint32_t*)&ts->r24);
bswap32s((uint32_t*)&ts->r25);
bswap32s((uint32_t*)&ts->r26);
bswap32s((uint32_t*)&ts->r27);
bswap32s((uint32_t*)&ts->r28);
bswap32s((uint32_t*)&ts->r29);
bswap32s((uint32_t*)&ts->r30);
bswap32s((uint32_t*)&ts->r31);
bswap32s((uint32_t*)&ts->cr);
bswap32s((uint32_t*)&ts->xer);
bswap32s((uint32_t*)&ts->lr);
bswap32s((uint32_t*)&ts->ctr);
bswap32s((uint32_t*)&ts->mq);
bswap32s((uint32_t*)&ts->vrsave);
}
#define target_thread_state mach_ppc_thread_state
#define TARGET_CPU_TYPE CPU_TYPE_POWERPC
#define TARGET_CPU_NAME "PowerPC"
#endif
struct target_thread_command {
unsigned long cmd; /* LC_THREAD or LC_UNIXTHREAD */
unsigned long cmdsize; /* total size of this command */
unsigned long flavor; /* flavor of thread state */
unsigned long count; /* count of longs in thread state */
struct target_thread_state state; /* thread state for this flavor */
};
void bswap_tc(struct target_thread_command *tc)
{
bswap32s((uint32_t*)(&tc->flavor));
bswap32s((uint32_t*)&tc->count);
#if defined(TARGET_I386)
bswap_i386_thread_state(&tc->state);
#elif defined(TARGET_PPC)
bswap_ppc_thread_state(&tc->state);
#else
# error unknown TARGET_CPU_TYPE
#endif
}
void bswap_mh(struct mach_header *mh)
{
bswap32s((uint32_t*)(&mh->magic));
bswap32s((uint32_t*)&mh->cputype);
bswap32s((uint32_t*)&mh->cpusubtype);
bswap32s((uint32_t*)&mh->filetype);
bswap32s((uint32_t*)&mh->ncmds);
bswap32s((uint32_t*)&mh->sizeofcmds);
bswap32s((uint32_t*)&mh->flags);
}
void bswap_lc(struct load_command *lc)
{
bswap32s((uint32_t*)&lc->cmd);
bswap32s((uint32_t*)&lc->cmdsize);
}
void bswap_fh(struct fat_header *fh)
{
bswap32s((uint32_t*)&fh->magic);
bswap32s((uint32_t*)&fh->nfat_arch);
}
void bswap_fa(struct fat_arch *fa)
{
bswap32s((uint32_t*)&fa->cputype);
bswap32s((uint32_t*)&fa->cpusubtype);
bswap32s((uint32_t*)&fa->offset);
bswap32s((uint32_t*)&fa->size);
bswap32s((uint32_t*)&fa->align);
}
void bswap_segcmd(struct segment_command *sc)
{
bswap32s((uint32_t*)&sc->vmaddr);
bswap32s((uint32_t*)&sc->vmsize);
bswap32s((uint32_t*)&sc->fileoff);
bswap32s((uint32_t*)&sc->filesize);
bswap32s((uint32_t*)&sc->maxprot);
bswap32s((uint32_t*)&sc->initprot);
bswap32s((uint32_t*)&sc->nsects);
bswap32s((uint32_t*)&sc->flags);
}
void bswap_symtabcmd(struct symtab_command *stc)
{
bswap32s((uint32_t*)&stc->cmd);
bswap32s((uint32_t*)&stc->cmdsize);
bswap32s((uint32_t*)&stc->symoff);
bswap32s((uint32_t*)&stc->nsyms);
bswap32s((uint32_t*)&stc->stroff);
bswap32s((uint32_t*)&stc->strsize);
}
void bswap_sym(struct nlist *n)
{
bswap32s((uint32_t*)&n->n_un.n_strx);
bswap16s((uint16_t*)&n->n_desc);
bswap32s((uint32_t*)&n->n_value);
}
int load_thread(struct mach_header *mh, struct target_thread_command *tc, struct target_pt_regs * regs, int fd, int mh_pos, int need_bswap)
{
int entry;
if(need_bswap)
bswap_tc(tc);
#if defined(TARGET_I386)
entry = tc->state.eip;
DPRINTF(" eax 0x%.8x\n ebx 0x%.8x\n ecx 0x%.8x\n edx 0x%.8x\n edi 0x%.8x\n esi 0x%.8x\n ebp 0x%.8x\n esp 0x%.8x\n ss 0x%.8x\n eflags 0x%.8x\n eip 0x%.8x\n cs 0x%.8x\n ds 0x%.8x\n es 0x%.8x\n fs 0x%.8x\n gs 0x%.8x\n",
tc->state.eax, tc->state.ebx, tc->state.ecx, tc->state.edx, tc->state.edi, tc->state.esi, tc->state.ebp,
tc->state.esp, tc->state.ss, tc->state.eflags, tc->state.eip, tc->state.cs, tc->state.ds, tc->state.es,
tc->state.fs, tc->state.gs );
#define reg_copy(reg) regs->reg = tc->state.reg
if(regs)
{
reg_copy(eax);
reg_copy(ebx);
reg_copy(ecx);
reg_copy(edx);
reg_copy(edi);
reg_copy(esi);
reg_copy(ebp);
reg_copy(esp);
reg_copy(eflags);
reg_copy(eip);
/*
reg_copy(ss);
reg_copy(cs);
reg_copy(ds);
reg_copy(es);
reg_copy(fs);
reg_copy(gs);*/
}
#undef reg_copy
#elif defined(TARGET_PPC)
entry = tc->state.srr0;
#endif
DPRINTF("load_thread: entry 0x%x\n", entry);
return entry;
}
int load_dylinker(struct mach_header *mh, struct dylinker_command *dc, int fd, int mh_pos, int need_bswap)
{
int size;
char * dylinker_name;
size = dc->cmdsize - sizeof(struct dylinker_command);
if(need_bswap)
dylinker_name = (char*)(bswap_32(dc->name.offset)+(int)dc);
else
dylinker_name = (char*)((dc->name.offset)+(int)dc);
#ifdef OVERRIDE_DYLINKER
dylinker_name = DYLINKER_NAME;
#else
if(asprintf(&dylinker_name, "%s%s", interp_prefix, dylinker_name) == -1)
qerror("can't allocate the new dylinker name\n");
#endif
DPRINTF("dylinker_name %s\n", dylinker_name);
return load_object(dylinker_name, NULL, NULL);
}
int load_segment(struct mach_header *mh, struct segment_command *sc, int fd, int mh_pos, int need_bswap, int fixed, int slide)
{
unsigned long addr = sc->vmaddr;
unsigned long size = sc->filesize;
unsigned long error = 0;
if(need_bswap)
bswap_segcmd(sc);
if(sc->vmaddr == 0)
{
DPRINTF("load_segment: sc->vmaddr == 0 returning\n");
return -1;
}
if (strcmp(sc->segname, "__PAGEZERO") == 0)
{
DPRINTF("load_segment: __PAGEZERO returning\n");
return -1;
}
/* Right now mmap memory */
/* XXX: should check to see that the space is free, because MAP_FIXED is dangerous */
DPRINTF("load_segment: mmaping %s to 0x%x-(0x%x|0x%x) + 0x%x\n", sc->segname, sc->vmaddr, sc->filesize, sc->vmsize, slide);
if(sc->filesize > 0)
{
int opt = 0;
if(fixed)
opt |= MAP_FIXED;
DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide, sc->vmaddr, sc->vmaddr+slide);
addr = target_mmap(sc->vmaddr+slide, sc->filesize, sc->initprot, opt, fd, mh_pos + sc->fileoff);
if(addr==-1)
qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
error = addr-sc->vmaddr;
}
else
{
addr = sc->vmaddr+slide;
error = slide;
}
if(sc->vmsize > sc->filesize)
{
addr += sc->filesize;
size = sc->vmsize-sc->filesize;
addr = target_mmap(addr, size, sc->initprot, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if(addr==-1)
qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
}
return error;
}
void *load_data(int fd, long offset, unsigned int size)
{
char *data;
data = malloc(size);
if (!data)
return NULL;
lseek(fd, offset, SEEK_SET);
if (read(fd, data, size) != size) {
free(data);
return NULL;
}
return data;
}
/* load a mach-o object file */
int load_object(const char *filename, struct target_pt_regs * regs, void ** mh)
{
int need_bswap = 0;
int entry_point = 0;
int dyld_entry_point = 0;
int slide, mmapfixed;
int fd;
struct load_command *lcmds, *lc;
int is_fat = 0;
unsigned int i, magic;
int mach_hdr_pos = 0;
struct mach_header mach_hdr;
/* for symbol lookup whith -d flag. */
struct symtab_command * symtabcmd = 0;
struct nlist_extended *symtab, *sym;
struct nlist *symtab_std, *syment;
char *strtab;
fd = open(filename, O_RDONLY);
if (fd < 0)
qerror("can't open file '%s'", filename);
/* Read magic header. */
if (read(fd, &magic, sizeof (magic)) != sizeof (magic))
qerror("unable to read Magic of '%s'", filename);
/* Check Mach identification. */
if(magic == MH_MAGIC)
{
is_fat = 0;
need_bswap = 0;
} else if (magic == MH_CIGAM)
{
is_fat = 0;
need_bswap = 1;
} else if (magic == FAT_MAGIC)
{
is_fat = 1;
need_bswap = 0;
} else if (magic == FAT_CIGAM)
{
is_fat = 1;
need_bswap = 1;
}
else
qerror("Not a Mach-O file.", filename);
DPRINTF("loading %s %s...\n", filename, is_fat ? "[FAT]": "[REGULAR]");
if(is_fat)
{
int found = 0;
struct fat_header fh;
struct fat_arch *fa;
lseek(fd, 0, SEEK_SET);
/* Read Fat header. */
if (read(fd, &fh, sizeof (fh)) != sizeof (fh))
qerror("unable to read file header");
if(need_bswap)
bswap_fh(&fh);
/* Read Fat Arch. */
fa = malloc(sizeof(struct fat_arch)*fh.nfat_arch);
if (read(fd, fa, sizeof(struct fat_arch)*fh.nfat_arch) != sizeof(struct fat_arch)*fh.nfat_arch)
qerror("unable to read file header");
for( i = 0; i < fh.nfat_arch; i++, fa++)
{
if(need_bswap)
bswap_fa(fa);
if(fa->cputype == TARGET_CPU_TYPE)
{
mach_hdr_pos = fa->offset;
lseek(fd, mach_hdr_pos, SEEK_SET);
/* Read Mach header. */
if (read(fd, &mach_hdr, sizeof(struct mach_header)) != sizeof (struct mach_header))
qerror("unable to read file header");
if(mach_hdr.magic == MH_MAGIC)
need_bswap = 0;
else if (mach_hdr.magic == MH_CIGAM)
need_bswap = 1;
else
qerror("Invalid mach header in Fat Mach-O File");
found = 1;
break;
}
}
if(!found)
qerror("%s: No %s CPU found in FAT Header", filename, TARGET_CPU_NAME);
}
else
{
lseek(fd, 0, SEEK_SET);
/* Read Mach header */
if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
qerror("%s: unable to read file header", filename);
}
if(need_bswap)
bswap_mh(&mach_hdr);
if ((mach_hdr.cputype) != TARGET_CPU_TYPE)
qerror("%s: Unsupported CPU 0x%x (only 0x%x(%s) supported)", filename, mach_hdr.cputype, TARGET_CPU_TYPE, TARGET_CPU_NAME);
switch(mach_hdr.filetype)
{
case MH_EXECUTE: break;
case MH_FVMLIB:
case MH_DYLIB:
case MH_DYLINKER: break;
default:
qerror("%s: Unsupported Mach type (0x%x)", filename, mach_hdr.filetype);
}
/* read segment headers */
lcmds = malloc(mach_hdr.sizeofcmds);
if(read(fd, lcmds, mach_hdr.sizeofcmds) != mach_hdr.sizeofcmds)
qerror("%s: unable to read load_command", filename);
slide = 0;
mmapfixed = 0;
for(i=0, lc = lcmds; i < (mach_hdr.ncmds) ; i++)
{
if(need_bswap)
bswap_lc(lc);
switch(lc->cmd)
{
case LC_SEGMENT:
/* The main_exe can't be relocated */
if(mach_hdr.filetype == MH_EXECUTE)
mmapfixed = 1;
slide = load_segment(&mach_hdr, (struct segment_command*)lc, fd, mach_hdr_pos, need_bswap, mmapfixed, slide);
/* other segment must be mapped according to slide exactly, if load_segment did something */
if(slide != -1)
mmapfixed = 1;
else
slide = 0; /* load_segment didn't map the segment */
if(mach_hdr.filetype == MH_EXECUTE && slide != 0)
qerror("%s: Warning executable can't be mapped at the right address (offset: 0x%x)\n", filename, slide);
if(strcmp(((struct segment_command*)(lc))->segname, "__TEXT") == 0)
{
/* Text section */
if(mach_hdr.filetype == MH_EXECUTE)
{
/* return the mach_header */
*mh = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
}
else
{
/* it is dyld save the section for gdb, we will be interested in dyld symbol
while debuging */
macho_text_sect = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
macho_offset = slide;
}
}
break;
case LC_LOAD_DYLINKER:
dyld_entry_point = load_dylinker( &mach_hdr, (struct dylinker_command*)lc, fd, mach_hdr_pos, need_bswap );
break;
case LC_LOAD_DYLIB:
/* dyld will do that for us */
break;
case LC_THREAD:
case LC_UNIXTHREAD:
{
struct target_pt_regs * _regs;
if(mach_hdr.filetype == MH_DYLINKER)
_regs = regs;
else
_regs = 0;
entry_point = load_thread( &mach_hdr, (struct target_thread_command*)lc, _regs, fd, mach_hdr_pos, need_bswap );
}
break;
case LC_SYMTAB:
/* Save the symtab and strtab */
symtabcmd = (struct symtab_command *)lc;
break;
case LC_ID_DYLINKER:
case LC_ID_DYLIB:
case LC_UUID:
case LC_DYSYMTAB:
case LC_TWOLEVEL_HINTS:
case LC_PREBIND_CKSUM:
case LC_SUB_LIBRARY:
break;
default: fprintf(stderr, "warning: unkown command 0x%x in '%s'\n", lc->cmd, filename);
}
lc = (struct load_command*)((int)(lc)+(lc->cmdsize));
}
if(symtabcmd)
{
if(need_bswap)
bswap_symtabcmd(symtabcmd);
symtab_std = load_data(fd, symtabcmd->symoff+mach_hdr_pos, symtabcmd->nsyms * sizeof(struct nlist));
strtab = load_data(fd, symtabcmd->stroff+mach_hdr_pos, symtabcmd->strsize);
symtab = malloc(sizeof(struct nlist_extended) * symtabcmd->nsyms);
if(need_bswap)
{
for(i = 0, syment = symtab_std; i < symtabcmd->nsyms; i++, syment++)
bswap_sym(syment);
}
for(i = 0, sym = symtab, syment = symtab_std; i < symtabcmd->nsyms; i++, sym++, syment++)
{
struct nlist *sym_follow, *sym_next = 0;
unsigned int j;
memset(sym, 0, sizeof(*sym));
sym->n_type = syment->n_type;
if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
continue;
memcpy(sym, syment, sizeof(*syment));
/* Find the following symbol in order to get the current symbol size */
for(j = 0, sym_follow = symtab_std; j < symtabcmd->nsyms; j++, sym_follow++) {
if ( sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
continue;
if(!sym_next) {
sym_next = sym_follow;
continue;
}
if(!(sym_next->n_value > sym_follow->n_value))
continue;
sym_next = sym_follow;
}
if(sym_next)
sym->st_size = sym_next->n_value - sym->st_value;
else
sym->st_size = 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */
sym->st_value += slide;
}
free((void*)symtab_std);
{
DPRINTF("saving symtab of %s (%d symbol(s))\n", filename, symtabcmd->nsyms);
struct syminfo *s;
s = malloc(sizeof(*s));
s->disas_symtab = symtab;
s->disas_strtab = strtab;
s->disas_num_syms = symtabcmd->nsyms;
s->next = syminfos;
syminfos = s;
}
}
close(fd);
if(mach_hdr.filetype == MH_EXECUTE && dyld_entry_point)
return dyld_entry_point;
else
return entry_point+slide;
}
extern unsigned long stack_size;
unsigned long setup_arg_pages(void * mh, char ** argv, char ** env)
{
unsigned long stack_base, error, size;
int i;
int * stack;
int argc, envc;
/* Create enough stack to hold everything. If we don't use
* it for args, we'll use it for something else...
*/
size = stack_size;
error = target_mmap(0,
size + qemu_host_page_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if (error == -1)
qerror("stk mmap");
/* we reserve one extra page at the top of the stack as guard */
target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
stack_base = error + size;
stack = (void*)stack_base;
/*
* | STRING AREA |
* +-------------+
* | 0 |
* +-------------+
* | apple[n] |
* +-------------+
* :
* +-------------+
* | apple[0] |
* +-------------+
* | 0 |
* +-------------+
* | env[n] |
* +-------------+
* :
* :
* +-------------+
* | env[0] |
* +-------------+
* | 0 |
* +-------------+
* | arg[argc-1] |
* +-------------+
* :
* :
* +-------------+
* | arg[0] |
* +-------------+
* | argc |
* +-------------+
* sp-> | mh | address of where the a.out's file offset 0 is in memory
* +-------------+
*/
/* Construct the stack Stack grows down */
stack--;
/* XXX: string should go up there */
*stack = 0;
stack--;
/* Push the absolute path of our executable */
DPRINTF("pushing apple %s (0x%x)\n", (char*)argv[0], (int)argv[0]);
stl(stack, (int) argv[0]);
stack--;
stl(stack, 0);
stack--;
/* Get envc */
for(envc = 0; env[envc]; envc++);
for(i = envc-1; i >= 0; i--)
{
DPRINTF("pushing env %s (0x%x)\n", (char*)env[i], (int)env[i]);
stl(stack, (int)env[i]);
stack--;
/* XXX: remove that when string will be on top of the stack */
page_set_flags((int)env[i], (int)(env[i]+strlen(env[i])), PROT_READ | PAGE_VALID);
}
/* Add on the stack the interp_prefix choosen if so */
if(interp_prefix[0])
{
char *dyld_root;
asprintf(&dyld_root, "DYLD_ROOT_PATH=%s", interp_prefix);
page_set_flags((int)dyld_root, (int)(dyld_root+strlen(interp_prefix)+1), PROT_READ | PAGE_VALID);
stl(stack, (int)dyld_root);
stack--;
}
#ifdef DONT_USE_DYLD_SHARED_MAP
{
char *shared_map_mode;
asprintf(&shared_map_mode, "DYLD_SHARED_REGION=avoid");
page_set_flags((int)shared_map_mode, (int)(shared_map_mode+strlen(shared_map_mode)+1), PROT_READ | PAGE_VALID);
stl(stack, (int)shared_map_mode);
stack--;
}
#endif
#ifdef ACTIVATE_DYLD_TRACE
char * extra_env_static[] = {"DYLD_DEBUG_TRACE=yes",
"DYLD_PREBIND_DEBUG=3", "DYLD_UNKNOW_TRACE=yes",
"DYLD_PRINT_INITIALIZERS=yes",
"DYLD_PRINT_SEGMENTS=yes", "DYLD_PRINT_REBASINGS=yes", "DYLD_PRINT_BINDINGS=yes", "DYLD_PRINT_INITIALIZERS=yes", "DYLD_PRINT_WARNINGS=yes" };
char ** extra_env = malloc(sizeof(extra_env_static));
bcopy(extra_env_static, extra_env, sizeof(extra_env_static));
page_set_flags((int)extra_env, (int)((void*)extra_env+sizeof(extra_env_static)), PROT_READ | PAGE_VALID);
for(i = 0; i<9; i++)
{
DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env[i], (int)extra_env[i]);
stl(stack, (int) extra_env[i]);
stack--;
}
#endif
stl(stack, 0);
stack--;
/* Get argc */
for(argc = 0; argv[argc]; argc++);
for(i = argc-1; i >= 0; i--)
{
DPRINTF("pushing arg %s (0x%x)\n", (char*)argv[i], (int)argv[i]);
stl(stack, (int) argv[i]);
stack--;
/* XXX: remove that when string will be on top of the stack */
page_set_flags((int)argv[i], (int)(argv[i]+strlen(argv[i])), PROT_READ | PAGE_VALID);
}
DPRINTF("pushing argc %d \n", argc);
stl(stack, argc);
stack--;
DPRINTF("pushing mh 0x%x \n", (int)mh);
stl(stack, (int) mh);
/* Stack points on the mh */
return (unsigned long)stack;
}
int mach_exec(const char * filename, char ** argv, char ** envp,
struct target_pt_regs * regs)
{
int entrypoint, stack;
void * mh; /* the Mach Header that will be used by dyld */
DPRINTF("mach_exec at 0x%x\n", (int)mach_exec);
entrypoint = load_object(filename, regs, &mh);
stack = setup_arg_pages(mh, argv, envp);
#if defined(TARGET_I386)
regs->eip = entrypoint;
regs->esp = stack;
#elif defined(TARGET_PPC)
regs->nip = entrypoint;
regs->gpr[1] = stack;
#endif
DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint, stack, (int)mh);
if(!entrypoint)
qerror("%s: no entry point!\n", filename);
return 0;
}
+918
View File
@@ -0,0 +1,918 @@
/*
* qemu user main
*
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2006 Pierre d'Herbemont
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include "qemu.h"
#define DEBUG_LOGFILE "/tmp/qemu.log"
#ifdef __APPLE__
#include <crt_externs.h>
# define environ (*_NSGetEnviron())
#endif
#include <mach/mach_init.h>
#include <mach/vm_map.h>
const char *interp_prefix = "";
asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
we allocate a bigger stack. Need a better solution, for example
by remapping the process stack directly at the right place */
unsigned long stack_size = 512 * 1024;
void qerror(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
exit(1);
}
void gemu_log(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
void cpu_outb(CPUState *env, int addr, int val)
{
fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
}
void cpu_outw(CPUState *env, int addr, int val)
{
fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
}
void cpu_outl(CPUState *env, int addr, int val)
{
fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
}
int cpu_inb(CPUState *env, int addr)
{
fprintf(stderr, "inb: port=0x%04x\n", addr);
return 0;
}
int cpu_inw(CPUState *env, int addr)
{
fprintf(stderr, "inw: port=0x%04x\n", addr);
return 0;
}
int cpu_inl(CPUState *env, int addr)
{
fprintf(stderr, "inl: port=0x%04x\n", addr);
return 0;
}
int cpu_get_pic_interrupt(CPUState *env)
{
return -1;
}
#ifdef TARGET_PPC
static inline uint64_t cpu_ppc_get_tb (CPUState *env)
{
/* TO FIX */
return 0;
}
uint32_t cpu_ppc_load_tbl (CPUState *env)
{
return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
}
uint32_t cpu_ppc_load_tbu (CPUState *env)
{
return cpu_ppc_get_tb(env) >> 32;
}
static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
{
/* TO FIX */
}
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
{
cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
}
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
{
cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
}
uint32_t cpu_ppc_load_decr (CPUState *env)
{
/* TO FIX */
return -1;
}
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
{
/* TO FIX */
}
void cpu_loop(CPUPPCState *env)
{
int trapnr;
uint32_t ret;
target_siginfo_t info;
for(;;) {
trapnr = cpu_ppc_exec(env);
if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
trapnr != EXCP_TRACE) {
if (loglevel > 0) {
cpu_dump_state(env, logfile, fprintf, 0);
}
}
switch(trapnr) {
case EXCP_NONE:
break;
case EXCP_SYSCALL_USER:
/* system call */
if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
env->gpr[5], env->gpr[6], env->gpr[7],
env->gpr[8], env->gpr[9], env->gpr[10]*/);
else if(((int)env->gpr[0])<0)
ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
env->gpr[5], env->gpr[6], env->gpr[7],
env->gpr[8], env->gpr[9], env->gpr[10]);
else
ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
env->gpr[5], env->gpr[6], env->gpr[7],
env->gpr[8], env->gpr[9], env->gpr[10]);
/* Unix syscall error signaling */
if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
{
if( (int)ret < 0 )
env->nip += 0;
else
env->nip += 4;
}
/* Return value */
env->gpr[3] = ret;
break;
case EXCP_RESET:
/* Should not happen ! */
fprintf(stderr, "RESET asked... Stop emulation\n");
if (loglevel)
fprintf(logfile, "RESET asked... Stop emulation\n");
abort();
case EXCP_MACHINE_CHECK:
fprintf(stderr, "Machine check exeption... Stop emulation\n");
if (loglevel)
fprintf(logfile, "RESET asked... Stop emulation\n");
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_OBJERR;
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
case EXCP_DSI:
#ifndef DAR
/* To deal with multiple qemu header version as host for the darwin-user code */
# define DAR SPR_DAR
#endif
fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
if (loglevel) {
fprintf(logfile, "Invalid data memory access: 0x%08x\n",
env->spr[DAR]);
}
/* Handle this via the gdb */
gdb_handlesig (env, SIGSEGV);
info.si_addr = (void*)env->nip;
queue_signal(info.si_signo, &info);
break;
case EXCP_ISI:
fprintf(stderr, "Invalid instruction fetch\n");
if (loglevel)
fprintf(logfile, "Invalid instruction fetch\n");
/* Handle this via the gdb */
gdb_handlesig (env, SIGSEGV);
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
case EXCP_EXTERNAL:
/* Should not happen ! */
fprintf(stderr, "External interruption... Stop emulation\n");
if (loglevel)
fprintf(logfile, "External interruption... Stop emulation\n");
abort();
case EXCP_ALIGN:
fprintf(stderr, "Invalid unaligned memory access\n");
if (loglevel)
fprintf(logfile, "Invalid unaligned memory access\n");
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRALN;
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
case EXCP_PROGRAM:
switch (env->error_code & ~0xF) {
case EXCP_FP:
fprintf(stderr, "Program exception\n");
if (loglevel)
fprintf(logfile, "Program exception\n");
/* Set FX */
env->fpscr[7] |= 0x8;
/* Finally, update FEX */
if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
env->fpscr[7] |= 0x4;
info.si_signo = SIGFPE;
info.si_errno = 0;
switch (env->error_code & 0xF) {
case EXCP_FP_OX:
info.si_code = FPE_FLTOVF;
break;
case EXCP_FP_UX:
info.si_code = FPE_FLTUND;
break;
case EXCP_FP_ZX:
case EXCP_FP_VXZDZ:
info.si_code = FPE_FLTDIV;
break;
case EXCP_FP_XX:
info.si_code = FPE_FLTRES;
break;
case EXCP_FP_VXSOFT:
info.si_code = FPE_FLTINV;
break;
case EXCP_FP_VXNAN:
case EXCP_FP_VXISI:
case EXCP_FP_VXIDI:
case EXCP_FP_VXIMZ:
case EXCP_FP_VXVC:
case EXCP_FP_VXSQRT:
case EXCP_FP_VXCVI:
info.si_code = FPE_FLTSUB;
break;
default:
fprintf(stderr, "Unknown floating point exception "
"(%02x)\n", env->error_code);
if (loglevel) {
fprintf(logfile, "Unknown floating point exception "
"(%02x)\n", env->error_code & 0xF);
}
}
break;
case EXCP_INVAL:
fprintf(stderr, "Invalid instruction\n");
if (loglevel)
fprintf(logfile, "Invalid instruction\n");
info.si_signo = SIGILL;
info.si_errno = 0;
switch (env->error_code & 0xF) {
case EXCP_INVAL_INVAL:
info.si_code = ILL_ILLOPC;
break;
case EXCP_INVAL_LSWX:
info.si_code = ILL_ILLOPN;
break;
case EXCP_INVAL_SPR:
info.si_code = ILL_PRVREG;
break;
case EXCP_INVAL_FP:
info.si_code = ILL_COPROC;
break;
default:
fprintf(stderr, "Unknown invalid operation (%02x)\n",
env->error_code & 0xF);
if (loglevel) {
fprintf(logfile, "Unknown invalid operation (%02x)\n",
env->error_code & 0xF);
}
info.si_code = ILL_ILLADR;
break;
}
/* Handle this via the gdb */
gdb_handlesig (env, SIGSEGV);
break;
case EXCP_PRIV:
fprintf(stderr, "Privilege violation\n");
if (loglevel)
fprintf(logfile, "Privilege violation\n");
info.si_signo = SIGILL;
info.si_errno = 0;
switch (env->error_code & 0xF) {
case EXCP_PRIV_OPC:
info.si_code = ILL_PRVOPC;
break;
case EXCP_PRIV_REG:
info.si_code = ILL_PRVREG;
break;
default:
fprintf(stderr, "Unknown privilege violation (%02x)\n",
env->error_code & 0xF);
info.si_code = ILL_PRVOPC;
break;
}
break;
case EXCP_TRAP:
fprintf(stderr, "Tried to call a TRAP\n");
if (loglevel)
fprintf(logfile, "Tried to call a TRAP\n");
abort();
default:
/* Should not happen ! */
fprintf(stderr, "Unknown program exception (%02x)\n",
env->error_code);
if (loglevel) {
fprintf(logfile, "Unknwon program exception (%02x)\n",
env->error_code);
}
abort();
}
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
case EXCP_NO_FP:
fprintf(stderr, "No floating point allowed\n");
if (loglevel)
fprintf(logfile, "No floating point allowed\n");
info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = ILL_COPROC;
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
case EXCP_DECR:
/* Should not happen ! */
fprintf(stderr, "Decrementer exception\n");
if (loglevel)
fprintf(logfile, "Decrementer exception\n");
abort();
case EXCP_TRACE:
/* Pass to gdb: we use this to trace execution */
gdb_handlesig (env, SIGTRAP);
break;
case EXCP_FP_ASSIST:
/* Should not happen ! */
fprintf(stderr, "Floating point assist exception\n");
if (loglevel)
fprintf(logfile, "Floating point assist exception\n");
abort();
case EXCP_MTMSR:
/* We reloaded the msr, just go on */
if (msr_pr == 0) {
fprintf(stderr, "Tried to go into supervisor mode !\n");
if (loglevel)
fprintf(logfile, "Tried to go into supervisor mode !\n");
abort();
}
break;
case EXCP_BRANCH:
/* We stopped because of a jump... */
break;
case EXCP_INTERRUPT:
/* Don't know why this should ever happen... */
fprintf(stderr, "EXCP_INTERRUPT\n");
break;
case EXCP_DEBUG:
gdb_handlesig (env, SIGTRAP);
break;
default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
if (loglevel) {
fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
"0x%02x - aborting\n", trapnr, env->error_code);
}
abort();
}
process_pending_signals(env);
}
}
#endif
#ifdef TARGET_I386
/***********************************************************/
/* CPUX86 core interface */
uint64_t cpu_get_tsc(CPUX86State *env)
{
return cpu_get_real_ticks();
}
void
write_dt(void *ptr, unsigned long addr, unsigned long limit,
int flags)
{
unsigned int e1, e2;
e1 = (addr << 16) | (limit & 0xffff);
e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
e2 |= flags;
stl((uint8_t *)ptr, e1);
stl((uint8_t *)ptr + 4, e2);
}
static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
unsigned long addr, unsigned int sel)
{
unsigned int e1, e2;
e1 = (addr & 0xffff) | (sel << 16);
e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
stl((uint8_t *)ptr, e1);
stl((uint8_t *)ptr + 4, e2);
}
#define GDT_TABLE_SIZE 14
#define LDT_TABLE_SIZE 15
#define IDT_TABLE_SIZE 256
#define TSS_SIZE 104
uint64_t gdt_table[GDT_TABLE_SIZE];
uint64_t ldt_table[LDT_TABLE_SIZE];
uint64_t idt_table[IDT_TABLE_SIZE];
uint32_t tss[TSS_SIZE];
/* only dpl matters as we do only user space emulation */
static void set_idt(int n, unsigned int dpl)
{
set_gate(idt_table + n, 0, dpl, 0, 0);
}
/* ABI convention: after a syscall if there was an error the CF flag is set */
static inline void set_error(CPUX86State *env, int ret)
{
if(ret<0)
env->eflags = env->eflags | 0x1;
else
env->eflags &= ~0x1;
env->regs[R_EAX] = ret;
}
void cpu_loop(CPUX86State *env)
{
int trapnr;
int ret;
uint8_t *pc;
target_siginfo_t info;
for(;;) {
trapnr = cpu_x86_exec(env);
uint32_t *params = (uint32_t *)env->regs[R_ESP];
switch(trapnr) {
case 0x79: /* Our commpage hack back door exit is here */
do_commpage(env, env->eip, *(params + 1), *(params + 2),
*(params + 3), *(params + 4),
*(params + 5), *(params + 6),
*(params + 7), *(params + 8));
break;
case 0x81: /* mach syscall */
{
ret = do_mach_syscall(env, env->regs[R_EAX],
*(params + 1), *(params + 2),
*(params + 3), *(params + 4),
*(params + 5), *(params + 6),
*(params + 7), *(params + 8));
set_error(env, ret);
break;
}
case 0x90: /* unix backdoor */
{
/* after sysenter, stack is in R_ECX, new eip in R_EDX (sysexit will flip them back)*/
int saved_stack = env->regs[R_ESP];
env->regs[R_ESP] = env->regs[R_ECX];
ret = do_unix_syscall(env, env->regs[R_EAX]);
env->regs[R_ECX] = env->regs[R_ESP];
env->regs[R_ESP] = saved_stack;
set_error(env, ret);
break;
}
case 0x80: /* unix syscall */
{
ret = do_unix_syscall(env, env->regs[R_EAX]/*,
*(params + 1), *(params + 2),
*(params + 3), *(params + 4),
*(params + 5), *(params + 6),
*(params + 7), *(params + 8)*/);
set_error(env, ret);
break;
}
case 0x82: /* thread syscall */
{
ret = do_thread_syscall(env, env->regs[R_EAX],
*(params + 1), *(params + 2),
*(params + 3), *(params + 4),
*(params + 5), *(params + 6),
*(params + 7), *(params + 8));
set_error(env, ret);
break;
}
case EXCP0B_NOSEG:
case EXCP0C_STACK:
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_NOOP;
info.si_addr = 0;
gdb_handlesig (env, SIGBUS);
queue_signal(info.si_signo, &info);
break;
case EXCP0D_GPF:
info.si_signo = SIGSEGV;
info.si_errno = 0;
info.si_code = SEGV_NOOP;
info.si_addr = 0;
gdb_handlesig (env, SIGSEGV);
queue_signal(info.si_signo, &info);
break;
case EXCP0E_PAGE:
info.si_signo = SIGSEGV;
info.si_errno = 0;
if (!(env->error_code & 1))
info.si_code = SEGV_MAPERR;
else
info.si_code = SEGV_ACCERR;
info.si_addr = (void*)env->cr[2];
gdb_handlesig (env, SIGSEGV);
queue_signal(info.si_signo, &info);
break;
case EXCP00_DIVZ:
/* division by zero */
info.si_signo = SIGFPE;
info.si_errno = 0;
info.si_code = FPE_INTDIV;
info.si_addr = (void*)env->eip;
gdb_handlesig (env, SIGFPE);
queue_signal(info.si_signo, &info);
break;
case EXCP01_SSTP:
case EXCP03_INT3:
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_BRKPT;
info.si_addr = (void*)env->eip;
gdb_handlesig (env, SIGTRAP);
queue_signal(info.si_signo, &info);
break;
case EXCP04_INTO:
case EXCP05_BOUND:
info.si_signo = SIGSEGV;
info.si_errno = 0;
info.si_code = SEGV_NOOP;
info.si_addr = 0;
gdb_handlesig (env, SIGSEGV);
queue_signal(info.si_signo, &info);
break;
case EXCP06_ILLOP:
info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = ILL_ILLOPN;
info.si_addr = (void*)env->eip;
gdb_handlesig (env, SIGILL);
queue_signal(info.si_signo, &info);
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
case EXCP_DEBUG:
{
int sig;
sig = gdb_handlesig (env, SIGTRAP);
if (sig)
{
info.si_signo = sig;
info.si_errno = 0;
info.si_code = TRAP_BRKPT;
queue_signal(info.si_signo, &info);
}
}
break;
default:
pc = (void*)(env->segs[R_CS].base + env->eip);
fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
(long)pc, trapnr);
abort();
}
process_pending_signals(env);
}
}
#endif
void usage(void)
{
printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
"usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
"Darwin CPU emulator (compiled for %s emulation)\n"
"\n"
"-h print this help\n"
"-L path set the %s library path (default='%s')\n"
"-s size set the stack size in bytes (default=%ld)\n"
"\n"
"debug options:\n"
#ifdef USE_CODE_COPY
"-no-code-copy disable code copy acceleration\n"
#endif
"-d options activate log (logfile='%s')\n"
"-g wait for gdb on port 1234\n"
"-p pagesize set the host page size to 'pagesize'\n",
TARGET_ARCH,
TARGET_ARCH,
interp_prefix,
stack_size,
DEBUG_LOGFILE);
_exit(1);
}
/* XXX: currently only used for async signals (see signal.c) */
CPUState *global_env;
/* used only if single thread */
CPUState *cpu_single_env = NULL;
/* used to free thread contexts */
TaskState *first_task_state;
int main(int argc, char **argv)
{
const char *filename;
struct target_pt_regs regs1, *regs = &regs1;
TaskState ts1, *ts = &ts1;
CPUState *env;
int optind;
short use_gdbstub = 0;
const char *r;
if (argc <= 1)
usage();
/* init debug */
cpu_set_log_filename(DEBUG_LOGFILE);
optind = 1;
for(;;) {
if (optind >= argc)
break;
r = argv[optind];
if (r[0] != '-')
break;
optind++;
r++;
if (!strcmp(r, "-")) {
break;
} else if (!strcmp(r, "d")) {
int mask;
CPULogItem *item;
if (optind >= argc)
break;
r = argv[optind++];
mask = cpu_str_to_log_mask(r);
if (!mask) {
printf("Log items (comma separated):\n");
for(item = cpu_log_items; item->mask != 0; item++) {
printf("%-10s %s\n", item->name, item->help);
}
exit(1);
}
cpu_set_log(mask);
} else if (!strcmp(r, "s")) {
r = argv[optind++];
stack_size = strtol(r, (char **)&r, 0);
if (stack_size <= 0)
usage();
if (*r == 'M')
stack_size *= 1024 * 1024;
else if (*r == 'k' || *r == 'K')
stack_size *= 1024;
} else if (!strcmp(r, "L")) {
interp_prefix = argv[optind++];
} else if (!strcmp(r, "p")) {
qemu_host_page_size = atoi(argv[optind++]);
if (qemu_host_page_size == 0 ||
(qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
fprintf(stderr, "page size must be a power of two\n");
exit(1);
}
} else
if (!strcmp(r, "g")) {
use_gdbstub = 1;
} else
#ifdef USE_CODE_COPY
if (!strcmp(r, "no-code-copy")) {
code_copy_enabled = 0;
} else
#endif
{
usage();
}
}
if (optind >= argc)
usage();
filename = argv[optind];
/* Zero out regs */
memset(regs, 0, sizeof(struct target_pt_regs));
/* NOTE: we need to init the CPU at this stage to get
qemu_host_page_size */
env = cpu_init();
printf("Starting %s with qemu\n----------------\n", filename);
commpage_init();
if (mach_exec(filename, argv+optind, environ, regs) != 0) {
printf("Error loading %s\n", filename);
_exit(1);
}
syscall_init();
signal_init();
global_env = env;
/* build Task State */
memset(ts, 0, sizeof(TaskState));
env->opaque = ts;
ts->used = 1;
env->user_mode_only = 1;
#if defined(TARGET_I386)
cpu_x86_set_cpl(env, 3);
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK;
if (env->cpuid_features & CPUID_SSE) {
env->cr[4] |= CR4_OSFXSR_MASK;
env->hflags |= HF_OSFXSR_MASK;
}
/* flags setup : we activate the IRQs by default as in user mode */
env->eflags |= IF_MASK;
/* darwin register setup */
env->regs[R_EAX] = regs->eax;
env->regs[R_EBX] = regs->ebx;
env->regs[R_ECX] = regs->ecx;
env->regs[R_EDX] = regs->edx;
env->regs[R_ESI] = regs->esi;
env->regs[R_EDI] = regs->edi;
env->regs[R_EBP] = regs->ebp;
env->regs[R_ESP] = regs->esp;
env->eip = regs->eip;
/* Darwin LDT setup */
/* 2 - User code segment
3 - User data segment
4 - User cthread */
bzero(ldt_table, LDT_TABLE_SIZE * sizeof(ldt_table[0]));
env->ldt.base = (uint32_t) ldt_table;
env->ldt.limit = sizeof(ldt_table) - 1;
write_dt(ldt_table + 2, 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
write_dt(ldt_table + 3, 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
write_dt(ldt_table + 4, 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
/* Darwin GDT setup.
* has changed a lot between old Darwin/x86 (pre-Mac Intel) and Mac OS X/x86,
now everything is done via int 0x81(mach) int 0x82 (thread) and sysenter/sysexit(unix) */
bzero(gdt_table, sizeof(gdt_table));
env->gdt.base = (uint32_t)gdt_table;
env->gdt.limit = sizeof(gdt_table) - 1;
/* Set up a back door to handle sysenter syscalls (unix) */
char * syscallbackdoor = malloc(64);
page_set_flags((int)syscallbackdoor, (int)syscallbackdoor + 64, PROT_EXEC | PROT_READ | PAGE_VALID);
int i = 0;
syscallbackdoor[i++] = 0xcd;
syscallbackdoor[i++] = 0x90; /* int 0x90 */
syscallbackdoor[i++] = 0x0F;
syscallbackdoor[i++] = 0x35; /* sysexit */
/* Darwin sysenter/sysexit setup */
env->sysenter_cs = 0x1; //XXX
env->sysenter_eip = (int)syscallbackdoor;
env->sysenter_esp = (int)malloc(64);
/* Darwin TSS setup
This must match up with GDT[4] */
env->tr.base = (uint32_t) tss;
env->tr.limit = sizeof(tss) - 1;
env->tr.flags = DESC_P_MASK | (0x9 << DESC_TYPE_SHIFT);
stw(tss + 2, 0x10); // ss0 = 0x10 = GDT[2] = Kernel Data Segment
/* Darwin interrupt setup */
bzero(idt_table, sizeof(idt_table));
env->idt.base = (uint32_t) idt_table;
env->idt.limit = sizeof(idt_table) - 1;
set_idt(0, 0);
set_idt(1, 0);
set_idt(2, 0);
set_idt(3, 3);
set_idt(4, 3);
set_idt(5, 3);
set_idt(6, 0);
set_idt(7, 0);
set_idt(8, 0);
set_idt(9, 0);
set_idt(10, 0);
set_idt(11, 0);
set_idt(12, 0);
set_idt(13, 0);
set_idt(14, 0);
set_idt(15, 0);
set_idt(16, 0);
set_idt(17, 0);
set_idt(18, 0);
set_idt(19, 0);
/* Syscalls are done via
int 0x80 (unix) (rarely used)
int 0x81 (mach)
int 0x82 (thread)
int 0x83 (diag) (not handled here)
sysenter/sysexit (unix) -> we redirect that to int 0x90 */
set_idt(0x79, 3); /* Commpage hack, here is our backdoor interrupt */
set_idt(0x80, 3); /* Unix Syscall */
set_idt(0x81, 3); /* Mach Syscalls */
set_idt(0x82, 3); /* thread Syscalls */
set_idt(0x90, 3); /* qemu-darwin-user's Unix syscalls backdoor */
cpu_x86_load_seg(env, R_CS, __USER_CS);
cpu_x86_load_seg(env, R_DS, __USER_DS);
cpu_x86_load_seg(env, R_ES, __USER_DS);
cpu_x86_load_seg(env, R_SS, __USER_DS);
cpu_x86_load_seg(env, R_FS, __USER_DS);
cpu_x86_load_seg(env, R_GS, __USER_DS);
#elif defined(TARGET_PPC)
{
int i;
env->nip = regs->nip;
for(i = 0; i < 32; i++) {
env->gpr[i] = regs->gpr[i];
}
}
#else
#error unsupported target CPU
#endif
if (use_gdbstub) {
printf("Waiting for gdb Connection on port 1234...\n");
gdbserver_start (1234);
gdb_handlesig(env, 0);
}
cpu_loop(env);
/* never exits */
return 0;
}
+411
View File
@@ -0,0 +1,411 @@
/*
* mmap support for qemu
*
* Copyright (c) 2003 Fabrice Bellard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include "qemu.h"
//#define DEBUG_MMAP
/* NOTE: all the constants are the HOST ones */
int target_mprotect(unsigned long start, unsigned long len, int prot)
{
unsigned long end, host_start, host_end, addr;
int prot1, ret;
#ifdef DEBUG_MMAP
printf("mprotect: start=0x%lx len=0x%lx prot=%c%c%c\n", start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-');
#endif
if ((start & ~TARGET_PAGE_MASK) != 0)
return -EINVAL;
len = TARGET_PAGE_ALIGN(len);
end = start + len;
if (end < start)
return -EINVAL;
if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
return -EINVAL;
if (len == 0)
return 0;
host_start = start & qemu_host_page_mask;
host_end = HOST_PAGE_ALIGN(end);
if (start > host_start) {
/* handle host page containing start */
prot1 = prot;
for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
prot1 |= page_get_flags(addr);
}
if (host_end == host_start + qemu_host_page_size) {
for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
prot1 |= page_get_flags(addr);
}
end = host_end;
}
ret = mprotect((void *)host_start, qemu_host_page_size, prot1 & PAGE_BITS);
if (ret != 0)
return ret;
host_start += qemu_host_page_size;
}
if (end < host_end) {
prot1 = prot;
for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
prot1 |= page_get_flags(addr);
}
ret = mprotect((void *)(host_end - qemu_host_page_size), qemu_host_page_size,
prot1 & PAGE_BITS);
if (ret != 0)
return ret;
host_end -= qemu_host_page_size;
}
/* handle the pages in the middle */
if (host_start < host_end) {
ret = mprotect((void *)host_start, host_end - host_start, prot);
if (ret != 0)
return ret;
}
page_set_flags(start, start + len, prot | PAGE_VALID);
return 0;
}
/* map an incomplete host page */
int mmap_frag(unsigned long host_start,
unsigned long start, unsigned long end,
int prot, int flags, int fd, unsigned long offset)
{
unsigned long host_end, ret, addr;
int prot1, prot_new;
host_end = host_start + qemu_host_page_size;
/* get the protection of the target pages outside the mapping */
prot1 = 0;
for(addr = host_start; addr < host_end; addr++) {
if (addr < start || addr >= end)
prot1 |= page_get_flags(addr);
}
if (prot1 == 0) {
/* no page was there, so we allocate one */
ret = (long)mmap((void *)host_start, qemu_host_page_size, prot,
flags | MAP_ANONYMOUS, -1, 0);
if (ret == -1)
return ret;
}
prot1 &= PAGE_BITS;
prot_new = prot | prot1;
if (!(flags & MAP_ANONYMOUS)) {
/* msync() won't work here, so we return an error if write is
possible while it is a shared mapping */
#ifndef __APPLE__
if ((flags & MAP_TYPE) == MAP_SHARED &&
#else
if ((flags & MAP_SHARED) &&
#endif
(prot & PROT_WRITE))
return -EINVAL;
/* adjust protection to be able to read */
if (!(prot1 & PROT_WRITE))
mprotect((void *)host_start, qemu_host_page_size, prot1 | PROT_WRITE);
/* read the corresponding file data */
pread(fd, (void *)start, end - start, offset);
/* put final protection */
if (prot_new != (prot1 | PROT_WRITE))
mprotect((void *)host_start, qemu_host_page_size, prot_new);
} else {
/* just update the protection */
if (prot_new != prot1) {
mprotect((void *)host_start, qemu_host_page_size, prot_new);
}
}
return 0;
}
/* NOTE: all the constants are the HOST ones */
long target_mmap(unsigned long start, unsigned long len, int prot,
int flags, int fd, unsigned long offset)
{
unsigned long ret, end, host_start, host_end, retaddr, host_offset, host_len;
#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
static unsigned long last_start = 0x40000000;
#endif
#ifdef DEBUG_MMAP
{
printf("mmap: start=0x%lx len=0x%lx prot=%c%c%c flags=",
start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-');
if (flags & MAP_FIXED)
printf("MAP_FIXED ");
if (flags & MAP_ANONYMOUS)
printf("MAP_ANON ");
#ifndef MAP_TYPE
# define MAP_TYPE 0x3
#endif
switch(flags & MAP_TYPE) {
case MAP_PRIVATE:
printf("MAP_PRIVATE ");
break;
case MAP_SHARED:
printf("MAP_SHARED ");
break;
default:
printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
break;
}
printf("fd=%d offset=%lx\n", fd, offset);
}
#endif
if (offset & ~TARGET_PAGE_MASK)
return -EINVAL;
len = TARGET_PAGE_ALIGN(len);
if (len == 0)
return start;
host_start = start & qemu_host_page_mask;
if (!(flags & MAP_FIXED)) {
#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
/* tell the kenel to search at the same place as i386 */
if (host_start == 0) {
host_start = last_start;
last_start += HOST_PAGE_ALIGN(len);
}
#endif
if (qemu_host_page_size != qemu_real_host_page_size) {
/* NOTE: this code is only for debugging with '-p' option */
/* reserve a memory area */
host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE;
host_start = (long)mmap((void *)host_start, host_len, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (host_start == -1)
return host_start;
host_end = host_start + host_len;
start = HOST_PAGE_ALIGN(host_start);
end = start + HOST_PAGE_ALIGN(len);
if (start > host_start)
munmap((void *)host_start, start - host_start);
if (end < host_end)
munmap((void *)end, host_end - end);
/* use it as a fixed mapping */
flags |= MAP_FIXED;
} else {
/* if not fixed, no need to do anything */
host_offset = offset & qemu_host_page_mask;
host_len = len + offset - host_offset;
start = (long)mmap((void *)host_start, host_len,
prot, flags, fd, host_offset);
if (start == -1)
return start;
/* update start so that it points to the file position at 'offset' */
if (!(flags & MAP_ANONYMOUS))
start += offset - host_offset;
goto the_end1;
}
}
if (start & ~TARGET_PAGE_MASK)
return -EINVAL;
end = start + len;
host_end = HOST_PAGE_ALIGN(end);
/* worst case: we cannot map the file because the offset is not
aligned, so we read it */
if (!(flags & MAP_ANONYMOUS) &&
(offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
/* msync() won't work here, so we return an error if write is
possible while it is a shared mapping */
#ifndef __APPLE__
if ((flags & MAP_TYPE) == MAP_SHARED &&
#else
if ((flags & MAP_SHARED) &&
#endif
(prot & PROT_WRITE))
return -EINVAL;
retaddr = target_mmap(start, len, prot | PROT_WRITE,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if (retaddr == -1)
return retaddr;
pread(fd, (void *)start, len, offset);
if (!(prot & PROT_WRITE)) {
ret = target_mprotect(start, len, prot);
if (ret != 0)
return ret;
}
goto the_end;
}
/* handle the start of the mapping */
if (start > host_start) {
if (host_end == host_start + qemu_host_page_size) {
/* one single host page */
ret = mmap_frag(host_start, start, end,
prot, flags, fd, offset);
if (ret == -1)
return ret;
goto the_end1;
}
ret = mmap_frag(host_start, start, host_start + qemu_host_page_size,
prot, flags, fd, offset);
if (ret == -1)
return ret;
host_start += qemu_host_page_size;
}
/* handle the end of the mapping */
if (end < host_end) {
ret = mmap_frag(host_end - qemu_host_page_size,
host_end - qemu_host_page_size, host_end,
prot, flags, fd,
offset + host_end - qemu_host_page_size - start);
if (ret == -1)
return ret;
host_end -= qemu_host_page_size;
}
/* map the middle (easier) */
if (host_start < host_end) {
unsigned long offset1;
if (flags & MAP_ANONYMOUS)
offset1 = 0;
else
offset1 = offset + host_start - start;
ret = (long)mmap((void *)host_start, host_end - host_start,
prot, flags, fd, offset1);
if (ret == -1)
return ret;
}
the_end1:
page_set_flags(start, start + len, prot | PAGE_VALID);
the_end:
#ifdef DEBUG_MMAP
printf("target_mmap: ret=0x%lx\n", (long)start);
page_dump(stdout);
printf("\n");
#endif
return start;
}
int target_munmap(unsigned long start, unsigned long len)
{
unsigned long end, host_start, host_end, addr;
int prot, ret;
#ifdef DEBUG_MMAP
printf("munmap: start=0x%lx len=0x%lx\n", start, len);
#endif
if (start & ~TARGET_PAGE_MASK)
return -EINVAL;
len = TARGET_PAGE_ALIGN(len);
if (len == 0)
return -EINVAL;
end = start + len;
host_start = start & qemu_host_page_mask;
host_end = HOST_PAGE_ALIGN(end);
if (start > host_start) {
/* handle host page containing start */
prot = 0;
for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
if (host_end == host_start + qemu_host_page_size) {
for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
end = host_end;
}
if (prot != 0)
host_start += qemu_host_page_size;
}
if (end < host_end) {
prot = 0;
for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
if (prot != 0)
host_end -= qemu_host_page_size;
}
/* unmap what we can */
if (host_start < host_end) {
ret = munmap((void *)host_start, host_end - host_start);
if (ret != 0)
return ret;
}
page_set_flags(start, start + len, 0);
return 0;
}
/* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED
blocks which have been allocated starting on a host page */
long target_mremap(unsigned long old_addr, unsigned long old_size,
unsigned long new_size, unsigned long flags,
unsigned long new_addr)
{
#ifndef __APPLE__
/* XXX: use 5 args syscall */
new_addr = (long)mremap((void *)old_addr, old_size, new_size, flags);
if (new_addr == -1)
return new_addr;
prot = page_get_flags(old_addr);
page_set_flags(old_addr, old_addr + old_size, 0);
page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
return new_addr;
#else
qerror("target_mremap: unsupported\n");
#endif
}
int target_msync(unsigned long start, unsigned long len, int flags)
{
unsigned long end;
if (start & ~TARGET_PAGE_MASK)
return -EINVAL;
len = TARGET_PAGE_ALIGN(len);
end = start + len;
if (end < start)
return -EINVAL;
if (end == start)
return 0;
start &= qemu_host_page_mask;
return msync((void *)start, end - start, flags);
}
+179
View File
@@ -0,0 +1,179 @@
#ifndef GEMU_H
#define GEMU_H
#include "thunk.h"
#include <signal.h>
#include <string.h>
#include "cpu.h"
#include "gdbstub.h"
typedef siginfo_t target_siginfo_t;
#define target_sigaction sigaction
#ifdef TARGET_I386
struct target_pt_regs {
long ebx;
long ecx;
long edx;
long esi;
long edi;
long ebp;
long eax;
int xds;
int xes;
long orig_eax;
long eip;
int xcs;
long eflags;
long esp;
int xss;
};
struct target_sigcontext {
int sc_onstack;
int sc_mask;
int sc_eax;
int sc_ebx;
int sc_ecx;
int sc_edx;
int sc_edi;
int sc_esi;
int sc_ebp;
int sc_esp;
int sc_ss;
int sc_eflags;
int sc_eip;
int sc_cs;
int sc_ds;
int sc_es;
int sc_fs;
int sc_gs;
};
#define __USER_CS (0x17)
#define __USER_DS (0x1F)
#elif defined(TARGET_PPC)
struct target_pt_regs {
unsigned long gpr[32];
unsigned long nip;
unsigned long msr;
unsigned long orig_gpr3; /* Used for restarting system calls */
unsigned long ctr;
unsigned long link;
unsigned long xer;
unsigned long ccr;
unsigned long mq; /* 601 only (not used at present) */
/* Used on APUS to hold IPL value. */
unsigned long trap; /* Reason for being here */
unsigned long dar; /* Fault registers */
unsigned long dsisr;
unsigned long result; /* Result of a system call */
};
struct target_sigcontext {
int sc_onstack; /* sigstack state to restore */
int sc_mask; /* signal mask to restore */
int sc_ir; /* pc */
int sc_psw; /* processor status word */
int sc_sp; /* stack pointer if sc_regs == NULL */
void *sc_regs; /* (kernel private) saved state */
};
#endif
typedef struct TaskState {
struct TaskState *next;
int used; /* non zero if used */
uint8_t stack[0];
} __attribute__((aligned(16))) TaskState;
void syscall_init(void);
long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
long do_unix_syscall(void *cpu_env, int num);
int do_sigaction(int sig, const struct sigaction *act,
struct sigaction *oact);
int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss);
void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
void qerror(const char *fmt, ...);
void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags);
extern CPUState *global_env;
void cpu_loop(CPUState *env);
void init_paths(const char *prefix);
const char *path(const char *pathname);
extern int loglevel;
extern FILE *logfile;
/* commpage.c */
void commpage_init();
void do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
/* signal.c */
void process_pending_signals(void *cpu_env);
void signal_init(void);
int queue_signal(int sig, target_siginfo_t *info);
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
long do_sigreturn(CPUState *env, int num);
/* machload.c */
int mach_exec(const char * filename, char ** argv, char ** envp,
struct target_pt_regs * regs);
/* mmap.c */
int target_mprotect(unsigned long start, unsigned long len, int prot);
long target_mmap(unsigned long start, unsigned long len, int prot,
int flags, int fd, unsigned long offset);
int target_munmap(unsigned long start, unsigned long len);
long target_mremap(unsigned long old_addr, unsigned long old_size,
unsigned long new_size, unsigned long flags,
unsigned long new_addr);
int target_msync(unsigned long start, unsigned long len, int flags);
/* user access */
/* XXX: todo protect every memory access */
#define lock_user(x,y,z) (void*)(x)
#define unlock_user(x,y,z)
/* Mac OS X ABI arguments processing */
#ifdef TARGET_I386
static inline uint32_t get_int_arg(int *i, CPUX86State *cpu_env)
{
uint32_t *args = (uint32_t*)(cpu_env->regs[R_ESP] + 4 + *i);
*i+=4;
return tswap32(*args);
}
static inline uint64_t get_int64_arg(int *i, CPUX86State *cpu_env)
{
uint64_t *args = (uint64_t*)(cpu_env->regs[R_ESP] + 4 + *i);
*i+=8;
return tswap64(*args);
}
#elif defined(TARGET_PPC)
static inline uint32_t get_int_arg(int *i, CPUPPCState *cpu_env)
{
/* XXX: won't work when args goes on stack after gpr10 */
uint32_t args = (uint32_t)(cpu_env->gpr[3+(*i & 0xff)/4]);
*i+=4;
return tswap32(args);
}
static inline uint64_t get_int64_arg(int *i, CPUPPCState *cpu_env)
{
/* XXX: won't work when args goes on stack after gpr10 */
uint64_t args = (uint64_t)(cpu_env->fpr[1+(*i >> 8)/8]);
*i+=(8 << 8) + 8;
return tswap64(args);
}
#endif
#endif
+463
View File
@@ -0,0 +1,463 @@
/*
* Emulation of Linux signals
*
* Copyright (c) 2003 Fabrice Bellard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/ucontext.h>
#ifdef __ia64__
#undef uc_mcontext
#undef uc_sigmask
#undef uc_stack
#undef uc_link
#endif
#include <signal.h>
#include "qemu.h"
#define DEBUG_SIGNAL
#define MAX_SIGQUEUE_SIZE 1024
struct sigqueue {
struct sigqueue *next;
target_siginfo_t info;
};
struct emulated_sigaction {
struct target_sigaction sa;
int pending; /* true if signal is pending */
struct sigqueue *first;
struct sigqueue info; /* in order to always have memory for the
first signal, we put it here */
};
struct sigaltstack target_sigaltstack_used = {
0, 0, SA_DISABLE
};
static struct emulated_sigaction sigact_table[NSIG];
static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
static struct sigqueue *first_free; /* first free siginfo queue entry */
static int signal_pending; /* non zero if a signal may be pending */
static void host_signal_handler(int host_signum, siginfo_t *info,
void *puc);
static inline int host_to_target_signal(int sig)
{
return sig;
}
static inline int target_to_host_signal(int sig)
{
return sig;
}
/* siginfo conversion */
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
{
}
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
{
}
void signal_init(void)
{
struct sigaction act;
int i;
/* set all host signal handlers. ALL signals are blocked during
the handlers to serialize them. */
sigfillset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = host_signal_handler;
for(i = 1; i < NSIG; i++) {
sigaction(i, &act, NULL);
}
memset(sigact_table, 0, sizeof(sigact_table));
first_free = &sigqueue_table[0];
for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++)
sigqueue_table[i].next = &sigqueue_table[i + 1];
sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL;
}
/* signal queue handling */
static inline struct sigqueue *alloc_sigqueue(void)
{
struct sigqueue *q = first_free;
if (!q)
return NULL;
first_free = q->next;
return q;
}
static inline void free_sigqueue(struct sigqueue *q)
{
q->next = first_free;
first_free = q;
}
/* abort execution with signal */
void __attribute((noreturn)) force_sig(int sig)
{
int host_sig;
host_sig = target_to_host_signal(sig);
fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
sig, strsignal(host_sig));
_exit(-host_sig);
}
/* queue a signal so that it will be send to the virtual CPU as soon
as possible */
int queue_signal(int sig, target_siginfo_t *info)
{
struct emulated_sigaction *k;
struct sigqueue *q, **pq;
target_ulong handler;
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "queue_signal: sig=%d\n",
sig);
#endif
k = &sigact_table[sig - 1];
handler = (target_ulong)k->sa.sa_handler;
if (handler == SIG_DFL) {
/* default handler : ignore some signal. The other are fatal */
if (sig != SIGCHLD &&
sig != SIGURG &&
sig != SIGWINCH) {
force_sig(sig);
} else {
return 0; /* indicate ignored */
}
} else if (handler == host_to_target_signal(SIG_IGN)) {
/* ignore signal */
return 0;
} else if (handler == host_to_target_signal(SIG_ERR)) {
force_sig(sig);
} else {
pq = &k->first;
if (!k->pending) {
/* first signal */
q = &k->info;
} else {
q = alloc_sigqueue();
if (!q)
return -EAGAIN;
while (*pq != NULL)
pq = &(*pq)->next;
}
*pq = q;
q->info = *info;
q->next = NULL;
k->pending = 1;
/* signal that a new signal is pending */
signal_pending = 1;
return 1; /* indicates that the signal was queued */
}
}
static void host_signal_handler(int host_signum, siginfo_t *info,
void *puc)
{
int sig;
target_siginfo_t tinfo;
/* the CPU emulator uses some host signals to detect exceptions,
we we forward to it some signals */
if (host_signum == SIGSEGV || host_signum == SIGBUS
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
|| host_signum == SIGFPE
#endif
) {
if (cpu_signal_handler(host_signum, (void*)info, puc))
return;
}
/* get target signal number */
sig = host_to_target_signal(host_signum);
if (sig < 1 || sig > NSIG)
return;
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "qemu: got signal %d\n", sig);
#endif
if (queue_signal(sig, &tinfo) == 1) {
/* interrupt the virtual CPU as soon as possible */
cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
}
}
int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss)
{
/* XXX: test errors */
if(oss)
{
oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp);
oss->ss_size = tswap32(target_sigaltstack_used.ss_size);
oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags);
}
if(ss)
{
target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp);
target_sigaltstack_used.ss_size = tswap32(ss->ss_size);
target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags);
}
return 0;
}
int do_sigaction(int sig, const struct sigaction *act,
struct sigaction *oact)
{
struct emulated_sigaction *k;
struct sigaction act1;
int host_sig;
if (sig < 1 || sig > NSIG)
return -EINVAL;
k = &sigact_table[sig - 1];
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
sig, (int)act, (int)oact);
#endif
if (oact) {
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
sig, (int)act, (int)oact);
#endif
oact->sa_handler = tswapl(k->sa.sa_handler);
oact->sa_flags = tswapl(k->sa.sa_flags);
oact->sa_mask = tswapl(k->sa.sa_mask);
}
if (act) {
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n",
act->sa_handler, act->sa_flags, act->sa_mask);
#endif
k->sa.sa_handler = tswapl(act->sa_handler);
k->sa.sa_flags = tswapl(act->sa_flags);
k->sa.sa_mask = tswapl(act->sa_mask);
/* we update the host signal state */
host_sig = target_to_host_signal(sig);
if (host_sig != SIGSEGV && host_sig != SIGBUS) {
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "sigaction handler going to call sigaction\n",
act->sa_handler, act->sa_flags, act->sa_mask);
#endif
sigfillset(&act1.sa_mask);
act1.sa_flags = SA_SIGINFO;
if (k->sa.sa_flags & SA_RESTART)
act1.sa_flags |= SA_RESTART;
/* NOTE: it is important to update the host kernel signal
ignore state to avoid getting unexpected interrupted
syscalls */
if (k->sa.sa_handler == SIG_IGN) {
act1.sa_sigaction = (void *)SIG_IGN;
} else if (k->sa.sa_handler == SIG_DFL) {
act1.sa_sigaction = (void *)SIG_DFL;
} else {
act1.sa_sigaction = host_signal_handler;
}
sigaction(host_sig, &act1, NULL);
}
}
return 0;
}
#ifdef TARGET_I386
static inline void *
get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
{
/* XXX Fix that */
if(target_sigaltstack_used.ss_flags & SA_DISABLE)
{
int esp;
/* Default to using normal stack */
esp = env->regs[R_ESP];
return (void *)((esp - frame_size) & -8ul);
}
else
{
return target_sigaltstack_used.ss_sp;
}
}
static void setup_frame(int sig, struct emulated_sigaction *ka,
void *set, CPUState *env)
{
void *frame;
int i, err = 0;
fprintf(stderr, "setup_frame %d\n", sig);
frame = get_sigframe(ka, env, sizeof(*frame));
/* Set up registers for signal handler */
env->regs[R_ESP] = (unsigned long) frame;
env->eip = (unsigned long) ka->sa.sa_handler;
env->eflags &= ~TF_MASK;
return;
give_sigsegv:
if (sig == SIGSEGV)
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV /* , current */);
}
long do_sigreturn(CPUState *env, int num)
{
int i = 0;
struct target_sigcontext *scp = get_int_arg(&i, env);
/* XXX Get current signal number */
/* XXX Adjust accordin to sc_onstack, sc_mask */
if(tswapl(scp->sc_onstack) & 0x1)
target_sigaltstack_used.ss_flags |= ~SA_DISABLE;
else
target_sigaltstack_used.ss_flags &= SA_DISABLE;
int set = tswapl(scp->sc_eax);
sigprocmask(SIG_SETMASK, &set, NULL);
fprintf(stderr, "do_sigreturn: partially implemented %x EAX:%x EBX:%x\n", scp->sc_mask, tswapl(scp->sc_eax), tswapl(scp->sc_ebx));
fprintf(stderr, "ECX:%x EDX:%x EDI:%x\n", scp->sc_ecx, tswapl(scp->sc_edx), tswapl(scp->sc_edi));
fprintf(stderr, "EIP:%x\n", tswapl(scp->sc_eip));
env->regs[R_EAX] = tswapl(scp->sc_eax);
env->regs[R_EBX] = tswapl(scp->sc_ebx);
env->regs[R_ECX] = tswapl(scp->sc_ecx);
env->regs[R_EDX] = tswapl(scp->sc_edx);
env->regs[R_EDI] = tswapl(scp->sc_edi);
env->regs[R_ESI] = tswapl(scp->sc_esi);
env->regs[R_EBP] = tswapl(scp->sc_ebp);
env->regs[R_ESP] = tswapl(scp->sc_esp);
env->segs[R_SS].selector = (void*)tswapl(scp->sc_ss);
env->eflags = tswapl(scp->sc_eflags);
env->eip = tswapl(scp->sc_eip);
env->segs[R_CS].selector = (void*)tswapl(scp->sc_cs);
env->segs[R_DS].selector = (void*)tswapl(scp->sc_ds);
env->segs[R_ES].selector = (void*)tswapl(scp->sc_es);
env->segs[R_FS].selector = (void*)tswapl(scp->sc_fs);
env->segs[R_GS].selector = (void*)tswapl(scp->sc_gs);
/* Again, because our caller's caller will reset EAX */
return env->regs[R_EAX];
}
#else
static void setup_frame(int sig, struct emulated_sigaction *ka,
void *set, CPUState *env)
{
fprintf(stderr, "setup_frame: not implemented\n");
}
long do_sigreturn(CPUState *env, int num)
{
int i = 0;
struct target_sigcontext *scp = get_int_arg(&i, env);
fprintf(stderr, "do_sigreturn: not implemented\n");
return -ENOSYS;
}
#endif
void process_pending_signals(void *cpu_env)
{
struct emulated_sigaction *k;
struct sigqueue *q;
target_ulong handler;
int sig;
if (!signal_pending)
return;
k = sigact_table;
for(sig = 1; sig <= NSIG; sig++) {
if (k->pending)
goto handle_signal;
k++;
}
/* if no signal is pending, just return */
signal_pending = 0;
return;
handle_signal:
#ifdef DEBUG_SIGNAL
fprintf(stderr, "qemu: process signal %d\n", sig);
#endif
/* dequeue signal */
q = k->first;
k->first = q->next;
if (!k->first)
k->pending = 0;
sig = gdb_handlesig (cpu_env, sig);
if (!sig) {
fprintf (stderr, "Lost signal\n");
abort();
}
handler = k->sa.sa_handler;
if (handler == SIG_DFL) {
/* default handler : ignore some signal. The other are fatal */
if (sig != SIGCHLD &&
sig != SIGURG &&
sig != SIGWINCH) {
force_sig(sig);
}
} else if (handler == SIG_IGN) {
/* ignore sig */
} else if (handler == SIG_ERR) {
force_sig(sig);
} else {
setup_frame(sig, k, 0, cpu_env);
if (k->sa.sa_flags & SA_RESETHAND)
k->sa.sa_handler = SIG_DFL;
}
if (q != &k->info)
free_sigqueue(q);
}
File diff suppressed because it is too large. Load diff
+384
View File
@@ -0,0 +1,384 @@
/* generated from xnu/bsd/kern/syscalls.master */
ENTRY("syscall", SYS_syscall, do_unix_syscall_indirect, 0, CALL_INDIRECT, VOID) /* 0 indirect syscall */
ENTRY("exit", SYS_exit, do_exit, 1, CALL_DIRECT, INT) /* 1 */
ENTRY("fork", SYS_fork, fork, 0, CALL_NOERRNO, VOID) /* 2 */
ENTRY("read", SYS_read, do_read, 3, CALL_DIRECT, INT, PTR, SIZE) /* 3 */
ENTRY("write", SYS_write, write, 3, CALL_DIRECT, INT, PTR, SIZE) /* 4 */
ENTRY("open", SYS_open, do_open, 3, CALL_DIRECT, PTR, INT, INT) /* 5 */
ENTRY("close", SYS_close, close, 1, CALL_DIRECT, INT) /* 6 */
ENTRY("wait4", SYS_wait4, wait4, 4, CALL_DIRECT, INT, PTR, INT, PTR) /* 7 */
ENTRY("", 8, no_syscall, 0, CALL_INDIRECT, VOID) /* 8 old creat */
ENTRY("link", SYS_link, link, 2, CALL_DIRECT, PTR, PTR) /* 9 */
ENTRY("unlink", SYS_unlink, unlink, 1, CALL_DIRECT, PTR) /* 10 */
ENTRY("", 11, no_syscall, 0, CALL_INDIRECT, VOID) /* 11 old execv */
ENTRY("chdir", SYS_chdir, chdir, 1, CALL_DIRECT, PTR) /* 12 */
ENTRY("fchdir", SYS_fchdir, fchdir, 1, CALL_DIRECT, INT) /* 13 */
ENTRY("mknod", SYS_mknod, mknod, 3, CALL_DIRECT, PTR, INT, INT) /* 14 */
ENTRY("chmod", SYS_chmod, chmod, 2, CALL_DIRECT, PTR, INT) /* 15 */
ENTRY("chown", SYS_chown, chown, 3, CALL_DIRECT, PTR, INT, INT) /* 16 */
ENTRY("obreak", SYS_obreak, no_syscall, 1, CALL_INDIRECT, VOID) /* 17 old break */
ENTRY("ogetfsstat", 18, unimpl_unix_syscall, 3, CALL_INDIRECT, PTR, INT, INT) /* 18 */
ENTRY("", 19, no_syscall, 0, CALL_INDIRECT, VOID) /* 19 old lseek */
ENTRY("getpid", SYS_getpid, getpid, 0, CALL_NOERRNO, VOID) /* 20 */
ENTRY("", 21, no_syscall, 0, CALL_INDIRECT, VOID) /* 21 old mount */
ENTRY("", 22, no_syscall, 0, CALL_INDIRECT, VOID) /* 22 old umount */
ENTRY("setuid", SYS_setuid, setuid, 1, CALL_DIRECT, INT) /* 23 */
ENTRY("getuid", SYS_getuid, getuid, 0, CALL_NOERRNO, VOID) /* 24 */
ENTRY("geteuid", SYS_geteuid, geteuid, 0, CALL_NOERRNO, VOID) /* 25 */
ENTRY("ptrace", SYS_ptrace, ptrace, 4, CALL_DIRECT, INT, INT, PTR, INT) /* 26 */
ENTRY("recvmsg", SYS_recvmsg, recvmsg, 3, CALL_DIRECT, INT, PTR, INT) /* 27 */
ENTRY("sendmsg", SYS_sendmsg, sendmsg, 3, CALL_DIRECT, INT, PTR, INT) /* 28 */
ENTRY("recvfrom", SYS_recvfrom, recvfrom, 6, CALL_DIRECT, INT, PTR, INT, INT, PTR, PTR) /* 29 */
ENTRY("accept", SYS_accept, accept, 3, CALL_DIRECT, INT, PTR, PTR) /* 30 */
ENTRY("getpeername", SYS_getpeername, getpeername, 3, CALL_DIRECT, INT, PTR, PTR) /* 31 */
ENTRY("getsockname", SYS_getsockname, getsockname, 3, CALL_DIRECT, INT, PTR, PTR) /* 32 */
ENTRY("access", SYS_access, access, 2, CALL_DIRECT, PTR, INT) /* 33 */
ENTRY("chflags", SYS_chflags, chflags, 2, CALL_DIRECT, PTR, INT) /* 34 */
ENTRY("fchflags", SYS_fchflags, fchflags, 2, CALL_DIRECT, INT, INT) /* 35 */
ENTRY("sync", SYS_sync, do_sync, 0, CALL_INDIRECT, VOID) /* 36 */
ENTRY("kill", SYS_kill, kill, 2, CALL_DIRECT, INT, INT) /* 37 */
ENTRY("", 38, no_syscall, 0, CALL_INDIRECT, VOID) /* 38 old stat */
ENTRY("getppid", SYS_getppid, getppid, 0, CALL_DIRECT, VOID) /* 39 */
ENTRY("", 40, no_syscall, 0, CALL_INDIRECT, VOID) /* 40 old lstat */
ENTRY("dup", SYS_dup, dup, 1, CALL_DIRECT, INT) /* 41 */
ENTRY("pipe", SYS_pipe, unimpl_unix_syscall, 0, CALL_INDIRECT, PTR) /* 42 */
ENTRY("getegid", SYS_getegid, getegid, 0, CALL_NOERRNO, VOID) /* 43 */
ENTRY("profil", SYS_profil, profil, 4, CALL_DIRECT, PTR, SIZE, INT, INT) /* 44 */
ENTRY("ktrace", SYS_ktrace, no_syscall, 4, CALL_INDIRECT, VOID) /* 45 */
ENTRY("sigaction", SYS_sigaction, do_sigaction, 3, CALL_DIRECT, INT, PTR, PTR) /* 46 */
ENTRY("getgid", SYS_getgid, getgid, 0, CALL_NOERRNO, VOID) /* 47 */
ENTRY("sigprocmask", SYS_sigprocmask, do_sigprocmask, 3, CALL_DIRECT, INT, PTR, PTR) /* 48 */
ENTRY("getlogin", SYS_getlogin, do_getlogin, 2, CALL_DIRECT, PTR, UINT) /* 49 XXX */
ENTRY("setlogin", SYS_setlogin, setlogin, 1, CALL_DIRECT, PTR) /* 50 */
ENTRY("acct", SYS_acct, acct, 1, CALL_DIRECT, PTR) /* 51 */
ENTRY("sigpending", SYS_sigpending, sigpending, 1, CALL_DIRECT, PTR) /* 52 */
ENTRY("sigaltstack", SYS_sigaltstack, do_sigaltstack, 2, CALL_DIRECT, PTR, PTR) /* 53 */
ENTRY("ioctl", SYS_ioctl, do_ioctl, 3, CALL_DIRECT, INT, INT, INT) /* 54 */
ENTRY("reboot", SYS_reboot, unimpl_unix_syscall, 2, CALL_INDIRECT, INT, PTR) /* 55 */
ENTRY("revoke", SYS_revoke, revoke, 1, CALL_DIRECT, PTR) /* 56 */
ENTRY("symlink", SYS_symlink, symlink, 2, CALL_DIRECT, PTR, PTR) /* 57 */
ENTRY("readlink", SYS_readlink, readlink, 3, CALL_DIRECT, PTR, PTR, INT) /* 58 */
ENTRY("execve", SYS_execve, do_execve, 3, CALL_DIRECT, PTR, PTR, PTR) /* 59 */
ENTRY("umask", SYS_umask, umask, 1, CALL_DIRECT, INT) /* 60 */
ENTRY("chroot", SYS_chroot, chroot, 1, CALL_DIRECT, PTR) /* 61 */
ENTRY("", 62, no_syscall, 0, CALL_INDIRECT, VOID) /* 62 old fstat */
ENTRY("", 63, no_syscall, 0, CALL_INDIRECT, VOID) /* 63 used internally , reserved */
ENTRY("", 64, no_syscall, 0, CALL_INDIRECT, VOID) /* 64 old getpagesize */
ENTRY("msync", SYS_msync, target_msync, 3, CALL_DIRECT, UINT /*PTR*/, SIZE, INT) /* 65 */
ENTRY("vfork", SYS_vfork, vfork, 0, CALL_DIRECT, VOID) /* 66 */
ENTRY("", 67, no_syscall, 0, CALL_INDIRECT, VOID) /* 67 old vread */
ENTRY("", 68, no_syscall, 0, CALL_INDIRECT, VOID) /* 68 old vwrite */
ENTRY("sbrk", SYS_sbrk, sbrk, 1, CALL_DIRECT, INT) /* 69 */
ENTRY("sstk", SYS_sstk, no_syscall, 1, CALL_INDIRECT, VOID) /* 70 */
ENTRY("", 71, no_syscall, 0, CALL_INDIRECT, VOID) /* 71 old mmap */
ENTRY("ovadvise", SYS_ovadvise, no_syscall, 0, CALL_INDIRECT, VOID) /* 72 old vadvise */
ENTRY("munmap", SYS_munmap, target_munmap, 2, CALL_DIRECT, UINT /* PTR */, SIZE) /* 73 */
ENTRY("mprotect", SYS_mprotect, mprotect, 3, CALL_DIRECT, PTR, SIZE, INT) /* 74 */
ENTRY("madvise", SYS_madvise, madvise, 3, CALL_DIRECT, PTR, SIZE, INT) /* 75 */
ENTRY("", 76, no_syscall, 0, CALL_INDIRECT, VOID) /* 76 old vhangup */
ENTRY("", 77, no_syscall, 0, CALL_INDIRECT, VOID) /* 77 old vlimit */
ENTRY("mincore", SYS_mincore, mincore, 3, CALL_DIRECT, PTR, SIZE, PTR) /* 78 */
ENTRY("getgroups", SYS_getgroups, do_getgroups, 2, CALL_DIRECT, UINT, PTR) /* 79 */
ENTRY("setgroups", SYS_setgroups, setgroups, 2, CALL_DIRECT, UINT, PTR) /* 80 */
ENTRY("getpgrp", SYS_getpgrp, getpgrp, 0, CALL_DIRECT, VOID) /* 81 */
ENTRY("setpgid", SYS_setpgid, setpgid, 2, CALL_DIRECT, INT, INT) /* 82 */
ENTRY("setitimer", SYS_setitimer, setitimer, 3, CALL_DIRECT, INT, PTR, PTR) /* 83 */
ENTRY("", 84, no_syscall, 0, CALL_INDIRECT, VOID) /* 84 old wait */
ENTRY("swapon", SYS_swapon, unimpl_unix_syscall, 0, CALL_INDIRECT, VOID) /* 85 */
ENTRY("getitimer", SYS_getitimer, getitimer, 2, CALL_DIRECT, INT, PTR) /* 86 */
ENTRY("", 87, no_syscall, 0, CALL_INDIRECT, VOID) /* 87 old gethostname */
ENTRY("", 88, no_syscall, 0, CALL_INDIRECT, VOID) /* 88 old sethostname */
ENTRY("getdtablesize", SYS_getdtablesize, getdtablesize, 0, CALL_DIRECT, VOID) /* 89 */
ENTRY("dup2", SYS_dup2, dup2, 2, CALL_DIRECT, INT, INT) /* 90 */
ENTRY("", 91, no_syscall, 0, CALL_INDIRECT, VOID) /* 91 old getdopt */
ENTRY("fcntl", SYS_fcntl, do_fcntl, 3, CALL_DIRECT, INT, INT, INT) /* 92 */
ENTRY("select", SYS_select, select, 5, CALL_DIRECT, INT, PTR, PTR, PTR, PTR) /* 93 */
ENTRY("", 94, no_syscall, 0, CALL_INDIRECT, VOID) /* 94 old setdopt */
ENTRY("fsync", SYS_fsync, fsync, 1, CALL_DIRECT, INT) /* 95 */
ENTRY("setpriority", SYS_setpriority, setpriority, 3, CALL_DIRECT, INT, INT, INT) /* 96 */
ENTRY("socket", SYS_socket, socket, 3, CALL_DIRECT, INT, INT, INT) /* 97 */
ENTRY("connect", SYS_connect, connect, 3, CALL_DIRECT, INT, PTR, INT) /* 98 */
ENTRY("", 99, no_syscall, 0, CALL_INDIRECT, VOID) /* 99 old accept */
ENTRY("getpriority", SYS_getpriority, getpriority, 2, CALL_DIRECT, INT, INT) /* 100 */
ENTRY("", 101, no_syscall, 0, CALL_INDIRECT, VOID) /* 101 old send */
ENTRY("", 102, no_syscall, 0, CALL_INDIRECT, VOID) /* 102 old recv */
ENTRY("", 103, no_syscall, 0, CALL_INDIRECT, VOID) /* 103 old sigreturn */
ENTRY("bind", SYS_bind, bind, 3, CALL_DIRECT, INT, PTR, INT) /* 104 */
ENTRY("setsockopt", SYS_setsockopt, setsockopt, 5, CALL_DIRECT, INT, INT, INT, PTR, INT) /* 105 */
ENTRY("listen", SYS_listen, listen, 2, CALL_DIRECT, INT, INT) /* 106 */
ENTRY("", 107, no_syscall, 0, CALL_INDIRECT, VOID) /* 107 old vtimes */
ENTRY("", 108, no_syscall, 0, CALL_INDIRECT, VOID) /* 108 old sigvec */
ENTRY("", 109, no_syscall, 0, CALL_INDIRECT, VOID) /* 109 old sigblock */
ENTRY("", 110, no_syscall, 0, CALL_INDIRECT, VOID) /* 110 old sigsetmask */
ENTRY("sigsuspend", SYS_sigsuspend, unimpl_unix_syscall, 1, CALL_INDIRECT, INT) /* 111 */
ENTRY("", 112, no_syscall, 0, CALL_INDIRECT, VOID) /* 112 old sigstack */
ENTRY("", 113, no_syscall, 0, CALL_INDIRECT, VOID) /* 113 old recvmsg */
ENTRY("", 114, no_syscall, 0, CALL_INDIRECT, VOID) /* 114 old sendmsg */
ENTRY("", 115, no_syscall, 0, CALL_INDIRECT, VOID) /* 115 old vtrace */
ENTRY("gettimeofday", SYS_gettimeofday, do_gettimeofday, 2, CALL_DIRECT, PTR, PTR) /* 116 */
ENTRY("getrusage", SYS_getrusage, getrusage, 2, CALL_DIRECT, INT, PTR) /* 117 */
ENTRY("getsockopt", SYS_getsockopt, getsockopt, 5, CALL_DIRECT, INT, INT, INT, PTR, PTR) /* 118 */
ENTRY("", 119, no_syscall, 0, CALL_INDIRECT, VOID) /* 119 old resuba */
ENTRY("readv", SYS_readv, do_readv, 3, CALL_DIRECT, INT, PTR, UINT) /* 120 */
ENTRY("writev", SYS_writev, do_writev, 3, CALL_DIRECT, INT, PTR, UINT) /* 121 */
ENTRY("settimeofday", SYS_settimeofday, settimeofday, 2, CALL_DIRECT, PTR, PTR) /* 122 */
ENTRY("fchown", SYS_fchown, fchown, 3, CALL_DIRECT, INT, INT, INT) /* 123 */
ENTRY("fchmod", SYS_fchmod, fchmod, 2, CALL_DIRECT, INT, INT) /* 124 */
ENTRY("", 125, no_syscall, 0, CALL_INDIRECT, VOID) /* 125 old recvfrom */
ENTRY("", 126, no_syscall, 0, CALL_INDIRECT, VOID) /* 126 old setreuid */
ENTRY("", 127, no_syscall, 0, CALL_INDIRECT, VOID) /* 127 old setregid */
ENTRY("rename", SYS_rename, rename, 2, CALL_DIRECT, PTR, PTR) /* 128 */
ENTRY("", 129, no_syscall, 0, CALL_INDIRECT, VOID) /* 129 old truncate */
ENTRY("", 130, no_syscall, 0, CALL_INDIRECT, VOID) /* 130 old ftruncate */
ENTRY("flock", SYS_flock, flock, 2, CALL_DIRECT, INT, INT) /* 131 */
ENTRY("mkfifo", SYS_mkfifo, mkfifo, 2, CALL_DIRECT, PTR, INT) /* 132 */
ENTRY("sendto", SYS_sendto, sendto, 6, CALL_DIRECT, INT, PTR, SIZE, INT, PTR, INT) /* 133 */
ENTRY("shutdown", SYS_shutdown, shutdown, 2, CALL_DIRECT, INT, INT) /* 134 */
ENTRY("socketpair", SYS_socketpair, socketpair, 4, CALL_DIRECT, INT, INT, INT, PTR) /* 135 */
ENTRY("mkdir", SYS_mkdir, mkdir, 2, CALL_DIRECT, PTR, INT) /* 136 */
ENTRY("rmdir", SYS_rmdir, rmdir, 1, CALL_DIRECT, PTR) /* 137 */
ENTRY("utimes", SYS_utimes, do_utimes, 2, CALL_DIRECT, PTR, PTR) /* 138 */
ENTRY("futimes", SYS_futimes, do_futimes, 2, CALL_DIRECT, INT, PTR) /* 139 */
ENTRY("adjtime", SYS_adjtime, adjtime, 2, CALL_DIRECT, PTR, PTR) /* 140 */
ENTRY("", 141, no_syscall, 0, CALL_INDIRECT, VOID) /* 141 old getpeername */
ENTRY("", 142, no_syscall, 0, CALL_INDIRECT, VOID) /* 142 old gethostid */
ENTRY("", 143, no_syscall, 0, CALL_INDIRECT, VOID) /* 143 old sethostid */
ENTRY("", 144, no_syscall, 0, CALL_INDIRECT, VOID) /* 144 old getrlimit */
ENTRY("", 145, no_syscall, 0, CALL_INDIRECT, VOID) /* 145 old setrlimit */
ENTRY("", 146, no_syscall, 0, CALL_INDIRECT, VOID) /* 146 old killpg */
ENTRY("setsid", SYS_setsid, setsid, 0, CALL_DIRECT, VOID) /* 147 */
ENTRY("", 148, no_syscall, 0, CALL_INDIRECT, VOID) /* 148 old setquota */
ENTRY("", 149, no_syscall, 0, CALL_INDIRECT, VOID) /* 149 old qquota */
ENTRY("", 150, no_syscall, 0, CALL_INDIRECT, VOID) /* 150 old getsockname */
ENTRY("getpgid", SYS_getpgid, getpgid, 1, CALL_DIRECT, INT) /* 151 */
ENTRY("setprivexec", SYS_setprivexec, no_syscall, 1, CALL_INDIRECT, VOID) /* 152 */
ENTRY("pread", SYS_pread, do_pread, 4, CALL_DIRECT, INT, PTR, SIZE, OFFSET) /* 153 */
ENTRY("pwrite", SYS_pwrite, pwrite, 4, CALL_DIRECT, INT, PTR, SIZE, OFFSET) /* 154 */
#ifdef SYS_nfssvc
ENTRY("nfssvc", SYS_nfssvc, nfssvc, 2, CALL_DIRECT, INT, PTR) /* 155 */
#else
ENTRY("nfssvc", 155, no_syscall, 2, CALL_INDIRECT, VOID) /* 155 */
#endif
ENTRY("", 155, no_syscall, 0, CALL_INDIRECT, VOID) /* 155 */
ENTRY("", 156, no_syscall, 0, CALL_INDIRECT, VOID) /* 156 old getdirentries */
ENTRY("statfs", SYS_statfs, do_statfs, 2, CALL_DIRECT, PTR, PTR) /* 157 */
ENTRY("fstatfs", SYS_fstatfs, do_fstatfs, 2, CALL_DIRECT, INT, PTR) /* 158 */
ENTRY("unmount", SYS_unmount, unmount, 2, CALL_DIRECT, PTR, INT) /* 159 */
ENTRY("", 160, no_syscall, 0, CALL_INDIRECT, VOID) /* 160 old async_daemon */
ENTRY("", 161, no_syscall, 0, CALL_INDIRECT, VOID) /* 161 */
ENTRY("", 162, no_syscall, 0, CALL_INDIRECT, VOID) /* 162 old getdomainname */
ENTRY("", 163, no_syscall, 0, CALL_INDIRECT, VOID) /* 163 old setdomainname */
ENTRY("", 164, no_syscall, 0, CALL_INDIRECT, VOID) /* 164 */
ENTRY("quotactl", SYS_quotactl, no_syscall, 4, CALL_INDIRECT, VOID) /* 165 */
ENTRY("", 166, no_syscall, 0, CALL_INDIRECT, VOID) /* 166 old exportfs */
ENTRY("mount", SYS_mount, mount, 4, CALL_DIRECT, PTR, PTR, INT, PTR) /* 167 */
ENTRY("", 168, no_syscall, 0, CALL_INDIRECT, VOID) /* 168 old ustat */
ENTRY("", 169, no_syscall, 0, CALL_INDIRECT, VOID) /* 169 */
ENTRY("table", SYS_table, no_syscall, 0, CALL_INDIRECT, VOID) /* 170 old table */
ENTRY("", 171, no_syscall, 0, CALL_INDIRECT, VOID) /* 171 old wait3 */
ENTRY("", 172, no_syscall, 0, CALL_INDIRECT, VOID) /* 172 old rpause */
ENTRY("waitid", SYS_waitid, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 173 */
ENTRY("", 174, no_syscall, 0, CALL_INDIRECT, VOID) /* 174 old getdents */
ENTRY("", 175, no_syscall, 0, CALL_INDIRECT, VOID) /* 175 old gc_control */
ENTRY("add_profil", SYS_add_profil, add_profil, 4, CALL_DIRECT, PTR, SIZE, UINT, UINT) /* 176 */
ENTRY("", 177, no_syscall, 0, CALL_INDIRECT, VOID) /* 177 */
ENTRY("", 178, no_syscall, 0, CALL_INDIRECT, VOID) /* 178 */
ENTRY("", 179, no_syscall, 0, CALL_INDIRECT, VOID) /* 179 */
ENTRY("kdebug_trace", SYS_kdebug_trace, no_syscall, 6, CALL_INDIRECT, VOID) /* 180 */
ENTRY("setgid", SYS_setgid, setgid, 1, CALL_DIRECT, INT) /* 181 */
ENTRY("setegid", SYS_setegid, setegid, 1, CALL_DIRECT, INT) /* 182 */
ENTRY("seteuid", SYS_seteuid, seteuid, 1, CALL_DIRECT, INT) /* 183 */
ENTRY("sigreturn", SYS_sigreturn, do_sigreturn, 2, CALL_INDIRECT, PTR, INT) /* 184 */
ENTRY("chud", SYS_chud, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 185 */
ENTRY("", 186, no_syscall, 0, CALL_INDIRECT, VOID) /* 186 */
ENTRY("", 187, no_syscall, 0, CALL_INDIRECT, VOID) /* 187 */
ENTRY("stat", SYS_stat, do_stat, 2, CALL_DIRECT, PTR, PTR) /* 188 */
ENTRY("fstat", SYS_fstat, do_fstat, 2, CALL_DIRECT, INT, PTR) /* 189 */
ENTRY("lstat", SYS_lstat, do_lstat, 2, CALL_DIRECT, PTR, PTR) /* 190 */
ENTRY("pathconf", SYS_pathconf, pathconf, 2, CALL_DIRECT, PTR, INT) /* 191 */
ENTRY("fpathconf", SYS_fpathconf, fpathconf, 2, CALL_DIRECT, INT, INT) /* 192 */
ENTRY("getfsstat", SYS_getfsstat, do_getfsstat, 3, CALL_DIRECT, PTR, INT, INT) /* 193 */
ENTRY("", 193, no_syscall, 0, CALL_INDIRECT, VOID) /* 193 */
ENTRY("getrlimit", SYS_getrlimit, getrlimit, 2, CALL_DIRECT, UINT, PTR) /* 194 */
ENTRY("setrlimit", SYS_setrlimit, setrlimit, 2, CALL_DIRECT, UINT, PTR) /* 195 */
ENTRY("getdirentries", SYS_getdirentries, do_getdirentries, 4, CALL_DIRECT, INT, PTR, UINT, PTR) /* 196 */
ENTRY("mmap", SYS_mmap, target_mmap, 6, CALL_DIRECT, UINT /*PTR*/, SIZE, INT, INT, INT, OFFSET) /* 197 */
ENTRY("", 198, no_syscall, 0, CALL_INDIRECT, VOID) /* 198 __syscall */
ENTRY("lseek", SYS_lseek, do_lseek, 3, CALL_INDIRECT, INT, OFFSET, INT) /* 199 */
ENTRY("truncate", SYS_truncate, truncate, 2, CALL_DIRECT, PTR, OFFSET) /* 200 */
ENTRY("ftruncate", SYS_ftruncate, ftruncate, 2, CALL_DIRECT, INT, OFFSET) /* 201 */
ENTRY("__sysctl", SYS___sysctl, do___sysctl, 6, CALL_DIRECT, PTR, INT, PTR, PTR, PTR, SIZE) /* 202 */
ENTRY("mlock", SYS_mlock, mlock, 2, CALL_DIRECT, PTR, SIZE) /* 203 */
ENTRY("munlock", SYS_munlock, munlock, 2, CALL_DIRECT, PTR, SIZE) /* 204 */
ENTRY("undelete", SYS_undelete, undelete, 1, CALL_DIRECT, PTR) /* 205 */
ENTRY("ATsocket", SYS_ATsocket, no_syscall, 1, CALL_INDIRECT, VOID) /* 206 */
ENTRY("ATgetmsg", SYS_ATgetmsg, no_syscall, 4, CALL_INDIRECT, VOID) /* 207 */
ENTRY("ATputmsg", SYS_ATputmsg, no_syscall, 4, CALL_INDIRECT, VOID) /* 208 */
ENTRY("ATPsndreq", SYS_ATPsndreq, no_syscall, 4, CALL_INDIRECT, VOID) /* 209 */
ENTRY("ATPsndrsp", SYS_ATPsndrsp, no_syscall, 4, CALL_INDIRECT, VOID) /* 210 */
ENTRY("ATPgetreq", SYS_ATPgetreq, no_syscall, 3, CALL_INDIRECT, VOID) /* 211 */
ENTRY("ATPgetrsp", SYS_ATPgetrsp, no_syscall, 2, CALL_INDIRECT, VOID) /* 212 */
ENTRY("", 213, no_syscall, 0, CALL_INDIRECT, VOID) /* 213 Reserved for AppleTalk */
ENTRY("kqueue_from_portset_np", SYS_kqueue_from_portset_np, no_syscall, 1, CALL_INDIRECT, VOID) /* 214 */
ENTRY("kqueue_portset_np", SYS_kqueue_portset_np, no_syscall, 1, CALL_INDIRECT, VOID) /* 215 */
ENTRY("mkcomplex", SYS_mkcomplex, no_syscall, 3, CALL_INDIRECT, VOID) /* 216 soon to be obsolete */
ENTRY("statv", SYS_statv, no_syscall, 2, CALL_INDIRECT, VOID) /* 217 soon to be obsolete */
ENTRY("lstatv", SYS_lstatv, no_syscall, 2, CALL_INDIRECT, VOID) /* 218 soon to be obsolete */
ENTRY("fstatv", SYS_fstatv, no_syscall, 2, CALL_INDIRECT, VOID) /* 219 soon to be obsolete */
ENTRY("getattrlist", SYS_getattrlist, do_getattrlist, 5, CALL_DIRECT, PTR, PTR, PTR, SIZE, UINT) /* 220 */
ENTRY("setattrlist", SYS_setattrlist, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 221 */
ENTRY("getdirentriesattr", SYS_getdirentriesattr, do_getdirentriesattr, 8, CALL_DIRECT, INT, PTR, PTR, SIZE, PTR, PTR, PTR, UINT) /* 222 */
ENTRY("exchangedata", SYS_exchangedata, exchangedata, 3, CALL_DIRECT, PTR, PTR, UINT) /* 223 */
ENTRY("checkuseraccess", SYS_checkuseraccess, checkuseraccess, 6, CALL_DIRECT, PTR, INT, PTR, INT, INT, UINT) /* 224 */
ENTRY("", 224, no_syscall, 0, CALL_INDIRECT, VOID) /* 224 HFS checkuseraccess check access to a file */
ENTRY("searchfs", SYS_searchfs, searchfs, 6, CALL_DIRECT, PTR, PTR, PTR, UINT, UINT, PTR) /* 225 */
ENTRY("delete", SYS_delete, no_syscall, 1, CALL_INDIRECT, VOID) /* 226 private delete ( Carbon semantics ) */
ENTRY("copyfile", SYS_copyfile, no_syscall, 4, CALL_INDIRECT, VOID) /* 227 */
ENTRY("", 228, no_syscall, 0, CALL_INDIRECT, VOID) /* 228 */
ENTRY("", 229, no_syscall, 0, CALL_INDIRECT, VOID) /* 229 */
ENTRY("poll", SYS_poll, no_syscall, 3, CALL_INDIRECT, VOID) /* 230 */
ENTRY("watchevent", SYS_watchevent, no_syscall, 2, CALL_INDIRECT, VOID) /* 231 */
ENTRY("waitevent", SYS_waitevent, no_syscall, 2, CALL_INDIRECT, VOID) /* 232 */
ENTRY("modwatch", SYS_modwatch, no_syscall, 2, CALL_INDIRECT, VOID) /* 233 */
ENTRY("getxattr", SYS_getxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 234 */
ENTRY("fgetxattr", SYS_fgetxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 235 */
ENTRY("setxattr", SYS_setxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 236 */
ENTRY("fsetxattr", SYS_fsetxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 237 */
ENTRY("removexattr", SYS_removexattr, no_syscall, 3, CALL_INDIRECT, VOID) /* 238 */
ENTRY("fremovexattr", SYS_fremovexattr, no_syscall, 3, CALL_INDIRECT, VOID) /* 239 */
ENTRY("listxattr", SYS_listxattr, no_syscall, 4, CALL_INDIRECT, VOID) /* 240 */
ENTRY("flistxattr", SYS_flistxattr, no_syscall, 4, CALL_INDIRECT, VOID) /* 241 */
ENTRY("fsctl", SYS_fsctl, fsctl, 4, CALL_DIRECT, PTR, UINT, PTR, UINT) /* 242 */
ENTRY("initgroups", SYS_initgroups, unimpl_unix_syscall, 3, CALL_INDIRECT, UINT, PTR, INT) /* 243 */
ENTRY("", 244, no_syscall, 0, CALL_INDIRECT, VOID) /* 244 */
ENTRY("", 245, no_syscall, 0, CALL_INDIRECT, VOID) /* 245 */
ENTRY("", 246, no_syscall, 0, CALL_INDIRECT, VOID) /* 246 */
#ifdef SYS_nfsclnt
ENTRY("nfsclnt", SYS_nfsclnt, nfsclnt, 2, CALL_DIRECT, INT, PTR) /* 247 */
#else
ENTRY("nfsclnt", 247, no_syscall, 2, CALL_INDIRECT, VOID) /* 247 */
#endif
ENTRY("", 247, no_syscall, 0, CALL_INDIRECT, VOID) /* 247 */
ENTRY("", 248, no_syscall, 0, CALL_INDIRECT, VOID) /* 248 */
ENTRY("", 249, no_syscall, 0, CALL_INDIRECT, VOID) /* 249 */
ENTRY("minherit", SYS_minherit, minherit, 3, CALL_DIRECT, PTR, INT, INT) /* 250 */
ENTRY("semsys", SYS_semsys, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 251 */
ENTRY("msgsys", SYS_msgsys, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 252 */
ENTRY("shmsys", SYS_shmsys, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 253 */
ENTRY("semctl", SYS_semctl, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 254 */
ENTRY("semget", SYS_semget, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 255 */
ENTRY("semop", SYS_semop, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 256 */
ENTRY("", 257, no_syscall, 0, CALL_INDIRECT, VOID) /* 257 */
ENTRY("msgctl", SYS_msgctl, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 258 */
ENTRY("msgget", SYS_msgget, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 259 */
ENTRY("msgsnd", SYS_msgsnd, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 260 */
ENTRY("msgrcv", SYS_msgrcv, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 261 */
ENTRY("shmat", SYS_shmat, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 262 */
ENTRY("shmctl", SYS_shmctl, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 263 */
ENTRY("shmdt", SYS_shmdt, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 264 */
ENTRY("shmget", SYS_shmget, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 265 */
ENTRY("shm_open", SYS_shm_open, shm_open, 3, CALL_DIRECT, PTR, INT, INT) /* 266 */
ENTRY("shm_unlink", SYS_shm_unlink, shm_unlink, 1, CALL_DIRECT, PTR) /* 267 */
ENTRY("sem_open", SYS_sem_open, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 268 */
ENTRY("sem_close", SYS_sem_close, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 269 */
ENTRY("sem_unlink", SYS_sem_unlink, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 270 */
ENTRY("sem_wait", SYS_sem_wait, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 271 */
ENTRY("sem_trywait", SYS_sem_trywait, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 272 */
ENTRY("sem_post", SYS_sem_post, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 273 */
ENTRY("sem_getvalue", SYS_sem_getvalue, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 274 */
ENTRY("sem_init", SYS_sem_init, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 275 */
ENTRY("sem_destroy", SYS_sem_destroy, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 276 */
ENTRY("open_extended", SYS_open_extended, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 277 */
ENTRY("umask_extended", SYS_umask_extended, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 278 */
ENTRY("stat_extended", SYS_stat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 279 */
ENTRY("lstat_extended", SYS_lstat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 280 */
ENTRY("fstat_extended", SYS_fstat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 281 */
ENTRY("chmod_extended", SYS_chmod_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 282 */
ENTRY("fchmod_extended", SYS_fchmod_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 283 */
ENTRY("access_extended", SYS_access_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 284 */
ENTRY("settid", SYS_settid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 285 */
ENTRY("gettid", SYS_gettid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 286 */
ENTRY("setsgroups", SYS_setsgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 287 */
ENTRY("getsgroups", SYS_getsgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 288 */
ENTRY("setwgroups", SYS_setwgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 289 */
ENTRY("getwgroups", SYS_getwgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 290 */
ENTRY("mkfifo_extended", SYS_mkfifo_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 291 */
ENTRY("mkdir_extended", SYS_mkdir_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 292 */
ENTRY("identitysvc", SYS_identitysvc, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 293 */
ENTRY("", 294, no_syscall, 0, CALL_INDIRECT, VOID) /* 294 */
ENTRY("", 295, no_syscall, 0, CALL_INDIRECT, VOID) /* 295 */
ENTRY("load_shared_file", SYS_load_shared_file, unimpl_unix_syscall, 7, CALL_INDIRECT, VOID) /* 296 */
ENTRY("reset_shared_file", SYS_reset_shared_file, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 297 */
ENTRY("new_system_shared_regions", SYS_new_system_shared_regions, unimpl_unix_syscall, 0, CALL_INDIRECT, VOID) /* 298 */
ENTRY("shared_region_map_file_np", SYS_shared_region_map_file_np, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 299 */
ENTRY("shared_region_make_private_np", SYS_shared_region_make_private_np, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 300 */
ENTRY("", 301, no_syscall, 0, CALL_INDIRECT, VOID) /* 301 */
ENTRY("", 302, no_syscall, 0, CALL_INDIRECT, VOID) /* 302 */
ENTRY("", 303, no_syscall, 0, CALL_INDIRECT, VOID) /* 303 */
ENTRY("", 304, no_syscall, 0, CALL_INDIRECT, VOID) /* 304 */
ENTRY("", 305, no_syscall, 0, CALL_INDIRECT, VOID) /* 305 */
ENTRY("", 306, no_syscall, 0, CALL_INDIRECT, VOID) /* 306 */
ENTRY("", 307, no_syscall, 0, CALL_INDIRECT, VOID) /* 307 */
ENTRY("", 308, no_syscall, 0, CALL_INDIRECT, VOID) /* 308 */
ENTRY("", 309, no_syscall, 0, CALL_INDIRECT, VOID) /* 309 */
ENTRY("getsid", SYS_getsid, getsid, 1, CALL_DIRECT, INT) /* 310 */
ENTRY("settid_with_pid", SYS_settid_with_pid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 311 */
ENTRY("", 312, no_syscall, 0, CALL_INDIRECT, VOID) /* 312 */
ENTRY("aio_fsync", SYS_aio_fsync, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 313 */
ENTRY("aio_return", SYS_aio_return, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 314 */
ENTRY("aio_suspend", SYS_aio_suspend, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 315 */
ENTRY("aio_cancel", SYS_aio_cancel, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 316 */
ENTRY("aio_error", SYS_aio_error, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 317 */
ENTRY("aio_read", SYS_aio_read, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 318 */
ENTRY("aio_write", SYS_aio_write, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 319 */
ENTRY("lio_listio", SYS_lio_listio, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 320 */
ENTRY("", 321, no_syscall, 0, CALL_INDIRECT, VOID) /* 321 */
ENTRY("", 322, no_syscall, 0, CALL_INDIRECT, VOID) /* 322 */
ENTRY("", 323, no_syscall, 0, CALL_INDIRECT, VOID) /* 323 */
ENTRY("mlockall", SYS_mlockall, mlockall, 1, CALL_DIRECT, INT) /* 324 */
ENTRY("munlockall", SYS_munlockall, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 325 */
ENTRY("", 326, no_syscall, 0, CALL_INDIRECT, VOID) /* 326 */
ENTRY("issetugid", SYS_issetugid, issetugid, 0, CALL_DIRECT, VOID) /* 327 */
ENTRY("__pthread_kill", SYS___pthread_kill, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 328 */
ENTRY("pthread_sigmask", SYS_pthread_sigmask, pthread_sigmask, 3, CALL_DIRECT, INT, PTR, PTR) /* 329 */
ENTRY("sigwait", SYS_sigwait, sigwait, 2, CALL_DIRECT, PTR, PTR) /* 330 */
ENTRY("__disable_threadsignal", SYS___disable_threadsignal, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 331 */
ENTRY("__pthread_markcancel", SYS___pthread_markcancel, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 332 */
ENTRY("__pthread_canceled", SYS___pthread_canceled, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 333 */
ENTRY("__semwait_signal", SYS___semwait_signal, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 334 */
ENTRY("utrace", SYS_utrace, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 335 */
ENTRY("proc_info", SYS_proc_info, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 336 */
ENTRY("", 337, no_syscall, 0, CALL_INDIRECT, VOID) /* 337 */
ENTRY("", 338, no_syscall, 0, CALL_INDIRECT, VOID) /* 338 */
ENTRY("", 339, no_syscall, 0, CALL_INDIRECT, VOID) /* 339 */
ENTRY("", 340, no_syscall, 0, CALL_INDIRECT, VOID) /* 340 */
ENTRY("", 341, no_syscall, 0, CALL_INDIRECT, VOID) /* 341 */
ENTRY("", 342, no_syscall, 0, CALL_INDIRECT, VOID) /* 342 */
ENTRY("", 343, no_syscall, 0, CALL_INDIRECT, VOID) /* 343 */
ENTRY("", 344, no_syscall, 0, CALL_INDIRECT, VOID) /* 344 */
ENTRY("", 345, no_syscall, 0, CALL_INDIRECT, VOID) /* 345 */
ENTRY("", 346, no_syscall, 0, CALL_INDIRECT, VOID) /* 346 */
ENTRY("", 347, no_syscall, 0, CALL_INDIRECT, VOID) /* 347 */
ENTRY("", 348, no_syscall, 0, CALL_INDIRECT, VOID) /* 348 */
ENTRY("", 349, no_syscall, 0, CALL_INDIRECT, VOID) /* 349 */
ENTRY("audit", SYS_audit, audit, 2, CALL_DIRECT, PTR, INT) /* 350 */
ENTRY("auditon", SYS_auditon, auditon, 3, CALL_DIRECT, INT, PTR, INT) /* 351 */
ENTRY("", 352, no_syscall, 0, CALL_INDIRECT, VOID) /* 352 */
ENTRY("getauid", SYS_getauid, getauid, 1, CALL_DIRECT, PTR) /* 353 */
ENTRY("setauid", SYS_setauid, setauid, 1, CALL_DIRECT, PTR) /* 354 */
ENTRY("getaudit", SYS_getaudit, getaudit, 1, CALL_DIRECT, PTR) /* 355 */
ENTRY("setaudit", SYS_setaudit, setaudit, 1, CALL_DIRECT, PTR) /* 356 */
ENTRY("getaudit_addr", SYS_getaudit_addr, getaudit_addr, 2, CALL_DIRECT, PTR, INT) /* 357 */
ENTRY("setaudit_addr", SYS_setaudit_addr, setaudit_addr, 2, CALL_DIRECT, PTR, INT) /* 358 */
ENTRY("auditctl", SYS_auditctl, auditctl, 1, CALL_DIRECT, PTR) /* 359 */
ENTRY("", 360, no_syscall, 0, CALL_INDIRECT, VOID) /* 360 */
ENTRY("", 361, no_syscall, 0, CALL_INDIRECT, VOID) /* 361 */
ENTRY("kqueue", SYS_kqueue, kqueue, 0, CALL_DIRECT, VOID) /* 362 */
ENTRY("kevent", SYS_kevent, kevent, 6, CALL_DIRECT, INT, PTR, INT, PTR, INT, PTR) /* 363 */
ENTRY("lchown", SYS_lchown, lchown, 3, CALL_DIRECT, PTR, INT , INT) /* 364 */
ENTRY("stack_snapshot", SYS_stack_snapshot, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 365 */
ENTRY("", 366, no_syscall, 0, CALL_INDIRECT, VOID) /* 366 */
ENTRY("", 367, no_syscall, 0, CALL_INDIRECT, VOID) /* 367 */
ENTRY("", 368, no_syscall, 0, CALL_INDIRECT, VOID) /* 368 */
ENTRY("", 369, no_syscall, 0, CALL_INDIRECT, VOID) /* 369 */
+6 -8
View File
@@ -186,14 +186,14 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
disasm_info.mach = bfd_mach_ppc;
#endif
print_insn = print_insn_ppc;
#elif defined(TARGET_M68K)
print_insn = print_insn_m68k;
#elif defined(TARGET_MIPS)
#ifdef TARGET_WORDS_BIGENDIAN
print_insn = print_insn_big_mips;
#else
print_insn = print_insn_little_mips;
#endif
#elif defined(TARGET_M68K)
print_insn = print_insn_m68k;
#elif defined(TARGET_SH4)
disasm_info.mach = bfd_mach_sh4;
print_insn = print_insn_sh;
@@ -271,11 +271,9 @@ void disas(FILE *out, void *code, unsigned long size)
for (pc = (unsigned long)code; pc < (unsigned long)code + size; pc += count) {
fprintf(out, "0x%08lx: ", pc);
#ifdef __arm__
/* since data are included in the code, it is better to
/* since data is included in the code, it is better to
display code data too */
if (is_host) {
fprintf(out, "%08x ", (int)bfd_getl32((const bfd_byte *)pc));
}
fprintf(out, "%08x ", (int)bfd_getl32((const bfd_byte *)pc));
#endif
count = print_insn(pc, &disasm_info);
fprintf(out, "\n");
@@ -387,14 +385,14 @@ void monitor_disas(CPUState *env,
disasm_info.mach = bfd_mach_ppc;
#endif
print_insn = print_insn_ppc;
#elif defined(TARGET_M68K)
print_insn = print_insn_m68k;
#elif defined(TARGET_MIPS)
#ifdef TARGET_WORDS_BIGENDIAN
print_insn = print_insn_big_mips;
#else
print_insn = print_insn_little_mips;
#endif
#elif defined(TARGET_M68K)
print_insn = print_insn_m68k;
#else
term_printf("0x" TARGET_FMT_lx
": Asm output not supported on this arch\n", pc);
+4 -1
View File
@@ -62,6 +62,9 @@ typedef signed long long int64_t;
#endif
#endif
/* XXX: This may be wrong for 64-bit ILP32 hosts. */
typedef void * host_reg_t;
#define INT8_MIN (-128)
#define INT16_MIN (-32767-1)
#define INT32_MIN (-2147483647-1)
@@ -188,7 +191,7 @@ extern int printf(const char *, ...);
#endif
/* force GCC to generate only one epilog at the end of the function */
#define FORCE_RET() asm volatile ("");
#define FORCE_RET() __asm__ __volatile__("" : : : "memory");
#ifndef OPPROTO
#define OPPROTO
+226 -61
View File
@@ -127,10 +127,12 @@
typedef int32_t host_long;
typedef uint32_t host_ulong;
#define swabls(x) swab32s(x)
#define swablss(x) swab32ss(x)
#else
typedef int64_t host_long;
typedef uint64_t host_ulong;
#define swabls(x) swab64s(x)
#define swablss(x) swab64ss(x)
#endif
#ifdef ELF_USES_RELOCA
@@ -284,11 +286,21 @@ void swab32s(uint32_t *p)
*p = bswap32(*p);
}
void swab32ss(int32_t *p)
{
*p = bswap32(*p);
}
void swab64s(uint64_t *p)
{
*p = bswap64(*p);
}
void swab64ss(int64_t *p)
{
*p = bswap64(*p);
}
uint16_t get16(uint16_t *p)
{
uint16_t val;
@@ -397,7 +409,7 @@ void elf_swap_rel(ELF_RELOC *rel)
swabls(&rel->r_offset);
swabls(&rel->r_info);
#ifdef ELF_USES_RELOCA
swabls(&rel->r_addend);
swablss(&rel->r_addend);
#endif
}
@@ -505,7 +517,7 @@ int load_object(const char *filename)
}
sec = &shdr[ehdr.e_shstrndx];
shstr = sdata[ehdr.e_shstrndx];
shstr = (char *)sdata[ehdr.e_shstrndx];
/* swap relocations */
for(i = 0; i < ehdr.e_shnum; i++) {
@@ -541,7 +553,7 @@ int load_object(const char *filename)
strtab_sec = &shdr[symtab_sec->sh_link];
symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
strtab = sdata[symtab_sec->sh_link];
strtab = (char *)sdata[symtab_sec->sh_link];
nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
if (do_swap) {
@@ -1255,90 +1267,149 @@ int arm_emit_ldr_info(const char *name, unsigned long start_offset,
{
uint8_t *p;
uint32_t insn;
int offset, min_offset, pc_offset, data_size;
int offset, min_offset, pc_offset, data_size, spare, max_pool;
uint8_t data_allocated[1024];
unsigned int data_index;
int type;
memset(data_allocated, 0, sizeof(data_allocated));
p = p_start;
min_offset = p_end - p_start;
spare = 0x7fffffff;
while (p < p_start + min_offset) {
insn = get32((uint32_t *)p);
/* TODO: Armv5e ldrd. */
/* TODO: VFP load. */
if ((insn & 0x0d5f0000) == 0x051f0000) {
/* ldr reg, [pc, #im] */
offset = insn & 0xfff;
if (!(insn & 0x00800000))
offset = -offset;
offset = -offset;
max_pool = 4096;
type = 0;
} else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
/* FPA ldf. */
offset = (insn & 0xff) << 2;
if (!(insn & 0x00800000))
offset = -offset;
max_pool = 1024;
type = 1;
} else if ((insn & 0x0fff0000) == 0x028f0000) {
/* Some gcc load a doubleword immediate with
add regN, pc, #imm
ldmia regN, {regN, regM}
Hope and pray the compiler never generates somethin like
add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
int r;
r = (insn & 0xf00) >> 7;
offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
max_pool = 1024;
type = 2;
} else {
max_pool = 0;
type = -1;
}
if (type >= 0) {
/* PC-relative load needs fixing up. */
if (spare > max_pool - offset)
spare = max_pool - offset;
if ((offset & 3) !=0)
error("%s:%04x: ldr pc offset must be 32 bit aligned",
error("%s:%04x: pc offset must be 32 bit aligned",
name, start_offset + p - p_start);
if (offset < 0)
error("%s:%04x: Embedded literal value",
name, start_offset + p - p_start);
pc_offset = p - p_start + offset + 8;
if (pc_offset <= (p - p_start) ||
pc_offset >= (p_end - p_start))
error("%s:%04x: ldr pc offset must point inside the function code",
error("%s:%04x: pc offset must point inside the function code",
name, start_offset + p - p_start);
if (pc_offset < min_offset)
min_offset = pc_offset;
if (outfile) {
/* ldr position */
/* The intruction position */
fprintf(outfile, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
p - p_start);
/* ldr data index */
data_index = ((p_end - p_start) - pc_offset - 4) >> 2;
fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr + %d;\n",
/* The position of the constant pool data. */
data_index = ((p_end - p_start) - pc_offset) >> 2;
fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
data_index);
fprintf(outfile, " arm_ldr_ptr->type = %d;\n", type);
fprintf(outfile, " arm_ldr_ptr++;\n");
if (data_index >= sizeof(data_allocated))
error("%s: too many data", name);
if (!data_allocated[data_index]) {
ELF_RELOC *rel;
int i, addend, type;
const char *sym_name, *p;
char relname[1024];
data_allocated[data_index] = 1;
/* data value */
addend = get32((uint32_t *)(p_start + pc_offset));
relname[0] = '\0';
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset == (pc_offset + start_offset)) {
sym_name = get_rel_sym_name(rel);
/* the compiler leave some unnecessary references to the code */
get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF32_R_TYPE(rel->r_info);
if (type != R_ARM_ABS32)
error("%s: unsupported data relocation", name);
break;
}
}
fprintf(outfile, " arm_data_ptr[%d] = 0x%x",
data_index, addend);
if (relname[0] != '\0')
fprintf(outfile, " + %s", relname);
fprintf(outfile, ";\n");
}
}
}
p += 4;
}
/* Copy and relocate the constant pool data. */
data_size = (p_end - p_start) - min_offset;
if (data_size > 0 && outfile) {
fprintf(outfile, " arm_data_ptr += %d;\n", data_size >> 2);
spare += min_offset;
fprintf(outfile, " arm_data_ptr -= %d;\n", data_size >> 2);
fprintf(outfile, " arm_pool_ptr -= %d;\n", data_size);
fprintf(outfile, " if (arm_pool_ptr > gen_code_ptr + %d)\n"
" arm_pool_ptr = gen_code_ptr + %d;\n",
spare, spare);
data_index = 0;
for (pc_offset = min_offset;
pc_offset < p_end - p_start;
pc_offset += 4) {
ELF_RELOC *rel;
int i, addend, type;
const char *sym_name;
char relname[1024];
/* data value */
addend = get32((uint32_t *)(p_start + pc_offset));
relname[0] = '\0';
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset == (pc_offset + start_offset)) {
sym_name = get_rel_sym_name(rel);
/* the compiler leave some unnecessary references to the code */
get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF32_R_TYPE(rel->r_info);
if (type != R_ARM_ABS32)
error("%s: unsupported data relocation", name);
break;
}
}
fprintf(outfile, " arm_data_ptr[%d] = 0x%x",
data_index, addend);
if (relname[0] != '\0')
fprintf(outfile, " + %s", relname);
fprintf(outfile, ";\n");
data_index++;
}
}
/* the last instruction must be a mov pc, lr */
if (p == p_start)
goto arm_ret_error;
p -= 4;
insn = get32((uint32_t *)p);
if ((insn & 0xffff0000) != 0xe91b0000) {
/* The last instruction must be an ldm instruction. There are several
forms generated by gcc:
ldmib sp, {..., pc} (implies a sp adjustment of +4)
ldmia sp, {..., pc}
ldmea fp, {..., pc} */
if ((insn & 0xffff8000) == 0xe99d8000) {
if (outfile) {
fprintf(outfile,
" *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
p - p_start);
}
p += 4;
} else if ((insn & 0xffff8000) != 0xe89d8000
&& (insn & 0xffff8000) != 0xe91b8000) {
arm_ret_error:
if (!outfile)
printf("%s: invalid epilog\n", name);
}
return p - p_start;
return p - p_start;
}
#endif
@@ -1537,6 +1608,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
#elif defined(HOST_ARM)
{
uint32_t insn;
if ((p_end - p_start) <= 16)
error("%s: function too small", name);
if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
@@ -1545,6 +1618,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
error("%s: invalid prolog", name);
p_start += 12;
start_offset += 12;
insn = get32((uint32_t *)p_start);
if ((insn & 0xffffff00) == 0xe24dd000) {
/* Stack adjustment. Assume op uses the frame pointer. */
p_start -= 4;
start_offset -= 4;
}
copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
relocs, nb_relocs);
}
@@ -2282,7 +2361,37 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
int type;
int addend;
int reloc_offset;
uint32_t insn;
insn = get32((uint32_t *)(p_start + 4));
/* If prologue ends in sub sp, sp, #const then assume
op has a stack frame and needs the frame pointer. */
if ((insn & 0xffffff00) == 0xe24dd000) {
int i;
uint32_t opcode;
opcode = 0xe28db000; /* add fp, sp, #0. */
#if 0
/* ??? Need to undo the extra stack adjustment at the end of the op.
For now just leave the stack misaligned and hope it doesn't break anything
too important. */
if ((insn & 4) != 0) {
/* Preserve doubleword stack alignment. */
fprintf(outfile,
" *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
insn + 4);
opcode -= 4;
}
#endif
insn = get32((uint32_t *)(p_start - 4));
/* Calculate the size of the saved registers,
excluding pc. */
for (i = 0; i < 15; i++) {
if (insn & (1 << i))
opcode += 4;
}
fprintf(outfile,
" *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
}
arm_emit_ldr_info(name, start_offset, outfile, p_start, p_end,
relocs, nb_relocs);
@@ -2303,6 +2412,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
reloc_offset, name, addend);
break;
case R_ARM_PC24:
case R_ARM_JUMP24:
case R_ARM_CALL:
fprintf(outfile, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
reloc_offset, addend, name);
break;
@@ -2407,6 +2518,28 @@ int gen_file(FILE *outfile, int out_type)
} else {
/* generate big code generation switch */
#ifdef HOST_ARM
/* We need to know the size of all the ops so we can figure out when
to emit constant pools. This must be consistent with opc.h. */
fprintf(outfile,
"static const uint32_t arm_opc_size[] = {\n"
" 0,\n" /* end */
" 0,\n" /* nop */
" 0,\n" /* nop1 */
" 0,\n" /* nop2 */
" 0,\n"); /* nop3 */
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
const char *name;
name = get_sym_name(sym);
if (strstart(name, OP_PREFIX, NULL)) {
fprintf(outfile, " %d,\n", sym->st_size);
}
}
fprintf(outfile,
"};\n");
#endif
fprintf(outfile,
"int dyngen_code(uint8_t *gen_code_buf,\n"
" uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
@@ -2417,10 +2550,36 @@ fprintf(outfile,
" const uint32_t *opparam_ptr;\n");
#ifdef HOST_ARM
/* Arm is tricky because it uses constant pools for loading immediate values.
We assume (and require) each function is code followed by a constant pool.
All the ops are small so this should be ok. For each op we figure
out how much "spare" range we have in the load instructions. This allows
us to insert subsequent ops in between the op and the constant pool,
eliminating the neeed to jump around the pool.
We currently generate:
[ For this example we assume merging would move op1_pool out of range.
In practice we should be able to combine many ops before the offset
limits are reached. ]
op1_code;
op2_code;
goto op3;
op2_pool;
op1_pool;
op3:
op3_code;
ret;
op3_pool;
Ideally we'd put op1_pool before op2_pool, but that requires two passes.
*/
fprintf(outfile,
" uint8_t *last_gen_code_ptr = gen_code_buf;\n"
" LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
" uint32_t *arm_data_ptr = arm_data_table;\n");
" uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
/* Initialise the parmissible pool offset to an arbitary large value. */
" uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
#endif
#ifdef HOST_IA64
{
@@ -2489,9 +2648,23 @@ fprintf(outfile,
/* Generate prologue, if needed. */
fprintf(outfile,
" for(;;) {\n"
" switch(*opc_ptr++) {\n"
);
" for(;;) {\n");
#ifdef HOST_ARM
/* Generate constant pool if needed */
fprintf(outfile,
" if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
" gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
" last_gen_code_ptr = gen_code_ptr;\n"
" arm_ldr_ptr = arm_ldr_table;\n"
" arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
" arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
" }\n");
#endif
fprintf(outfile,
" switch(*opc_ptr++) {\n");
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
const char *name;
@@ -2525,17 +2698,6 @@ fprintf(outfile,
" goto the_end;\n"
" }\n");
#ifdef HOST_ARM
/* generate constant table if needed */
fprintf(outfile,
" if ((gen_code_ptr - last_gen_code_ptr) >= (MAX_FRAG_SIZE - MAX_OP_SIZE)) {\n"
" gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 1);\n"
" last_gen_code_ptr = gen_code_ptr;\n"
" arm_ldr_ptr = arm_ldr_table;\n"
" arm_data_ptr = arm_data_table;\n"
" }\n");
#endif
fprintf(outfile,
" }\n"
@@ -2553,7 +2715,10 @@ fprintf(outfile,
/* generate some code patching */
#ifdef HOST_ARM
fprintf(outfile, "gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 0);\n");
fprintf(outfile,
"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
" gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
#endif
/* flush instruction cache */
fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
+45 -15
View File
@@ -19,7 +19,7 @@
*/
int __op_param1, __op_param2, __op_param3;
#ifdef __sparc__
#if defined(__sparc__) || defined(__arm__)
void __op_gen_label1(){}
void __op_gen_label2(){}
void __op_gen_label3(){}
@@ -145,18 +145,16 @@ void fix_bsr(void *p, int offset) {
#ifdef __arm__
#define MAX_OP_SIZE (128 * 4) /* in bytes */
/* max size of the code that can be generated without calling arm_flush_ldr */
#define MAX_FRAG_SIZE (1024 * 4)
//#define MAX_FRAG_SIZE (135 * 4) /* for testing */
#define ARM_LDR_TABLE_SIZE 1024
typedef struct LDREntry {
uint8_t *ptr;
uint32_t *data_ptr;
unsigned type:2;
} LDREntry;
static LDREntry arm_ldr_table[1024];
static uint32_t arm_data_table[1024];
static uint32_t arm_data_table[ARM_LDR_TABLE_SIZE];
extern char exec_loop;
@@ -175,8 +173,9 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
int offset, data_size, target;
uint8_t *data_ptr;
uint32_t insn;
uint32_t mask;
data_size = (uint8_t *)data_end - (uint8_t *)data_start;
data_size = (data_end - data_start) << 2;
if (gen_jmp) {
/* generate branch to skip the data */
@@ -198,17 +197,48 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
offset = ((unsigned long)(le->data_ptr) - (unsigned long)data_start) +
(unsigned long)data_ptr -
(unsigned long)ptr - 8;
insn = *ptr & ~(0xfff | 0x00800000);
if (offset < 0) {
offset = - offset;
} else {
insn |= 0x00800000;
}
if (offset > 0xfff) {
fprintf(stderr, "Error ldr offset\n");
fprintf(stderr, "Negative constant pool offset\n");
abort();
}
insn |= offset;
switch (le->type) {
case 0: /* ldr */
mask = ~0x00800fff;
if (offset >= 4096) {
fprintf(stderr, "Bad ldr offset\n");
abort();
}
break;
case 1: /* ldc */
mask = ~0x008000ff;
if (offset >= 1024 ) {
fprintf(stderr, "Bad ldc offset\n");
abort();
}
break;
case 2: /* add */
mask = ~0xfff;
if (offset >= 1024 ) {
fprintf(stderr, "Bad add offset\n");
abort();
}
break;
default:
fprintf(stderr, "Bad pc relative fixup\n");
abort();
}
insn = *ptr & mask;
switch (le->type) {
case 0: /* ldr */
insn |= offset | 0x00800000;
break;
case 1: /* ldc */
insn |= (offset >> 2) | 0x00800000;
break;
case 2: /* add */
insn |= (offset >> 2) | 0xf00;
break;
}
*ptr = insn;
}
return gen_code_ptr;
+2
View File
@@ -502,6 +502,8 @@ typedef struct {
#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */
#define R_ARM_GOT32 26 /* 32 bit GOT entry */
#define R_ARM_PLT32 27 /* 32 bit PLT address */
#define R_ARM_CALL 28
#define R_ARM_JUMP24 29
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
+3 -1
View File
@@ -153,6 +153,9 @@ int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend,
glue(bswap_ehdr, SZ)(&ehdr);
}
if (ELF_MACHINE != ehdr.e_machine)
goto fail;
if (pentry)
*pentry = (uint64_t)ehdr.e_entry;
@@ -202,4 +205,3 @@ int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend,
qemu_free(phdr);
return -1;
}
+11 -1
View File
@@ -196,9 +196,19 @@ typedef struct TranslationBlock {
struct TranslationBlock *jmp_first;
} TranslationBlock;
static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
{
target_ulong tmp;
tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
return (tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK;
}
static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
{
return (pc ^ (pc >> TB_JMP_CACHE_BITS)) & (TB_JMP_CACHE_SIZE - 1);
target_ulong tmp;
tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
return (((tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK) |
(tmp & TB_JMP_ADDR_MASK));
}
static inline unsigned int tb_phys_hash_func(unsigned long pc)
+25 -8
View File
@@ -41,6 +41,7 @@
//#define DEBUG_TB_INVALIDATE
//#define DEBUG_FLUSH
//#define DEBUG_TLB
//#define DEBUG_UNASSIGNED
/* make various TB consistency checks */
//#define DEBUG_TB_CHECK
@@ -1288,14 +1289,13 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
tlb_flush_entry(&env->tlb_table[0][i], addr);
tlb_flush_entry(&env->tlb_table[1][i], addr);
for(i = 0; i < TB_JMP_CACHE_SIZE; i++) {
tb = env->tb_jmp_cache[i];
if (tb &&
((tb->pc & TARGET_PAGE_MASK) == addr ||
((tb->pc + tb->size - 1) & TARGET_PAGE_MASK) == addr)) {
env->tb_jmp_cache[i] = NULL;
}
}
/* Discard jump cache entries for any tb which might potentially
overlap the flushed page. */
i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
i = tb_jmp_cache_hash_page(addr);
memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
#if !defined(CONFIG_SOFTMMU)
if (addr < MMAP_AREA_END)
@@ -1801,13 +1801,30 @@ void cpu_register_physical_memory(target_phys_addr_t start_addr,
}
}
/* XXX: temporary until new memory mapping API */
uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr)
{
PhysPageDesc *p;
p = phys_page_find(addr >> TARGET_PAGE_BITS);
if (!p)
return IO_MEM_UNASSIGNED;
return p->phys_offset;
}
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem read 0x%08x\n", (int)addr);
#endif
return 0;
}
static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write 0x%08x = 0x%x\n", (int)addr, val);
#endif
}
static CPUReadMemoryFunc *unassigned_mem_read[3] = {
+25 -9
View File
@@ -149,7 +149,7 @@ float32 float32_sqrt( float32 a STATUS_PARAM)
{
return sqrtf(a);
}
char float32_compare( float32 a, float32 b STATUS_PARAM )
int float32_compare( float32 a, float32 b STATUS_PARAM )
{
if (a < b) {
return -1;
@@ -161,7 +161,7 @@ char float32_compare( float32 a, float32 b STATUS_PARAM )
return 2;
}
}
char float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
{
if (isless(a, b)) {
return -1;
@@ -173,7 +173,7 @@ char float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
return 2;
}
}
char float32_is_signaling_nan( float32 a1)
int float32_is_signaling_nan( float32 a1)
{
float32u u;
uint32_t a;
@@ -221,6 +221,11 @@ float128 float64_to_float128( float64 a STATUS_PARAM)
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision operations.
*----------------------------------------------------------------------------*/
float64 float64_trunc_to_int( float64 a STATUS_PARAM )
{
return trunc(a);
}
float64 float64_round_to_int( float64 a STATUS_PARAM )
{
#if defined(__arm__)
@@ -253,7 +258,7 @@ float64 float64_sqrt( float64 a STATUS_PARAM)
{
return sqrt(a);
}
char float64_compare( float64 a, float64 b STATUS_PARAM )
int float64_compare( float64 a, float64 b STATUS_PARAM )
{
if (a < b) {
return -1;
@@ -265,7 +270,7 @@ char float64_compare( float64 a, float64 b STATUS_PARAM )
return 2;
}
}
char float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
{
if (isless(a, b)) {
return -1;
@@ -277,7 +282,7 @@ char float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
return 2;
}
}
char float64_is_signaling_nan( float64 a1)
int float64_is_signaling_nan( float64 a1)
{
float64u u;
uint64_t a;
@@ -289,6 +294,17 @@ char float64_is_signaling_nan( float64 a1)
}
int float64_is_nan( float64 a1 )
{
float64u u;
uint64_t a;
u.f = a1;
a = u.i;
return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
@@ -334,7 +350,7 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
{
return sqrtl(a);
}
char floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
{
if (a < b) {
return -1;
@@ -346,7 +362,7 @@ char floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
return 2;
}
}
char floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
{
if (isless(a, b)) {
return -1;
@@ -358,7 +374,7 @@ char floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
return 2;
}
}
char floatx80_is_signaling_nan( floatx80 a1)
int floatx80_is_signaling_nan( floatx80 a1)
{
floatx80u u;
u.f = a1;
+32 -30
View File
@@ -152,38 +152,38 @@ INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM)
}
float32 float32_rem( float32, float32 STATUS_PARAM);
float32 float32_sqrt( float32 STATUS_PARAM);
INLINE char float32_eq( float32 a, float32 b STATUS_PARAM)
INLINE int float32_eq( float32 a, float32 b STATUS_PARAM)
{
return a == b;
}
INLINE char float32_le( float32 a, float32 b STATUS_PARAM)
INLINE int float32_le( float32 a, float32 b STATUS_PARAM)
{
return a <= b;
}
INLINE char float32_lt( float32 a, float32 b STATUS_PARAM)
INLINE int float32_lt( float32 a, float32 b STATUS_PARAM)
{
return a < b;
}
INLINE char float32_eq_signaling( float32 a, float32 b STATUS_PARAM)
INLINE int float32_eq_signaling( float32 a, float32 b STATUS_PARAM)
{
return a <= b && a >= b;
}
INLINE char float32_le_quiet( float32 a, float32 b STATUS_PARAM)
INLINE int float32_le_quiet( float32 a, float32 b STATUS_PARAM)
{
return islessequal(a, b);
}
INLINE char float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
INLINE int float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
{
return isless(a, b);
}
INLINE char float32_unordered( float32 a, float32 b STATUS_PARAM)
INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM)
{
return isunordered(a, b);
}
char float32_compare( float32, float32 STATUS_PARAM );
char float32_compare_quiet( float32, float32 STATUS_PARAM );
char float32_is_signaling_nan( float32 );
int float32_compare( float32, float32 STATUS_PARAM );
int float32_compare_quiet( float32, float32 STATUS_PARAM );
int float32_is_signaling_nan( float32 );
INLINE float32 float32_abs(float32 a)
{
@@ -214,6 +214,7 @@ float128 float64_to_float128( float64 STATUS_PARAM );
| Software IEC/IEEE double-precision operations.
*----------------------------------------------------------------------------*/
float64 float64_round_to_int( float64 STATUS_PARAM );
float64 float64_trunc_to_int( float64 STATUS_PARAM );
INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM)
{
return a + b;
@@ -232,39 +233,40 @@ INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM)
}
float64 float64_rem( float64, float64 STATUS_PARAM );
float64 float64_sqrt( float64 STATUS_PARAM );
INLINE char float64_eq( float64 a, float64 b STATUS_PARAM)
INLINE int float64_eq( float64 a, float64 b STATUS_PARAM)
{
return a == b;
}
INLINE char float64_le( float64 a, float64 b STATUS_PARAM)
INLINE int float64_le( float64 a, float64 b STATUS_PARAM)
{
return a <= b;
}
INLINE char float64_lt( float64 a, float64 b STATUS_PARAM)
INLINE int float64_lt( float64 a, float64 b STATUS_PARAM)
{
return a < b;
}
INLINE char float64_eq_signaling( float64 a, float64 b STATUS_PARAM)
INLINE int float64_eq_signaling( float64 a, float64 b STATUS_PARAM)
{
return a <= b && a >= b;
}
INLINE char float64_le_quiet( float64 a, float64 b STATUS_PARAM)
INLINE int float64_le_quiet( float64 a, float64 b STATUS_PARAM)
{
return islessequal(a, b);
}
INLINE char float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
INLINE int float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
{
return isless(a, b);
}
INLINE char float64_unordered( float64 a, float64 b STATUS_PARAM)
INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM)
{
return isunordered(a, b);
}
char float64_compare( float64, float64 STATUS_PARAM );
char float64_compare_quiet( float64, float64 STATUS_PARAM );
char float64_is_signaling_nan( float64 );
int float64_compare( float64, float64 STATUS_PARAM );
int float64_compare_quiet( float64, float64 STATUS_PARAM );
int float64_is_signaling_nan( float64 );
int float64_is_nan( float64 );
INLINE float64 float64_abs(float64 a)
{
@@ -313,39 +315,39 @@ INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM)
}
floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
INLINE char floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
INLINE int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
{
return a == b;
}
INLINE char floatx80_le( floatx80 a, floatx80 b STATUS_PARAM)
INLINE int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM)
{
return a <= b;
}
INLINE char floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
INLINE int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
{
return a < b;
}
INLINE char floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM)
INLINE int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM)
{
return a <= b && a >= b;
}
INLINE char floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM)
INLINE int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM)
{
return islessequal(a, b);
}
INLINE char floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
INLINE int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
{
return isless(a, b);
}
INLINE char floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
{
return isunordered(a, b);
}
char floatx80_compare( floatx80, floatx80 STATUS_PARAM );
char floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
char floatx80_is_signaling_nan( floatx80 );
int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_is_signaling_nan( floatx80 );
INLINE floatx80 floatx80_abs(floatx80 a)
{
+8 -8
View File
@@ -68,7 +68,7 @@ typedef struct {
| otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float32_is_nan( float32 a )
int float32_is_nan( float32 a )
{
return ( 0xFF000000 < (bits32) ( a<<1 ) );
@@ -80,7 +80,7 @@ flag float32_is_nan( float32 a )
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float32_is_signaling_nan( float32 a )
int float32_is_signaling_nan( float32 a )
{
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
@@ -161,7 +161,7 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
| otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float64_is_nan( float64 a )
int float64_is_nan( float64 a )
{
return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
@@ -173,7 +173,7 @@ flag float64_is_nan( float64 a )
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float64_is_signaling_nan( float64 a )
int float64_is_signaling_nan( float64 a )
{
return
@@ -264,7 +264,7 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag floatx80_is_nan( floatx80 a )
int floatx80_is_nan( floatx80 a )
{
return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
@@ -276,7 +276,7 @@ flag floatx80_is_nan( floatx80 a )
| signaling NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag floatx80_is_signaling_nan( floatx80 a )
int floatx80_is_signaling_nan( floatx80 a )
{
bits64 aLow;
@@ -371,7 +371,7 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
| otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float128_is_nan( float128 a )
int float128_is_nan( float128 a )
{
return
@@ -385,7 +385,7 @@ flag float128_is_nan( float128 a )
| signaling NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float128_is_signaling_nan( float128 a )
int float128_is_signaling_nan( float128 a )
{
return
+38 -27
View File
@@ -2023,7 +2023,7 @@ float32 float32_sqrt( float32 a STATUS_PARAM )
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_eq( float32 a, float32 b STATUS_PARAM )
int float32_eq( float32 a, float32 b STATUS_PARAM )
{
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
@@ -2045,7 +2045,7 @@ flag float32_eq( float32 a, float32 b STATUS_PARAM )
| Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_le( float32 a, float32 b STATUS_PARAM )
int float32_le( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -2068,7 +2068,7 @@ flag float32_le( float32 a, float32 b STATUS_PARAM )
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_lt( float32 a, float32 b STATUS_PARAM )
int float32_lt( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -2092,7 +2092,7 @@ flag float32_lt( float32 a, float32 b STATUS_PARAM )
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
{
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
@@ -2112,7 +2112,7 @@ flag float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_le_quiet( float32 a, float32 b STATUS_PARAM )
int float32_le_quiet( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -2138,7 +2138,7 @@ flag float32_le_quiet( float32 a, float32 b STATUS_PARAM )
| Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
int float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -2483,6 +2483,17 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
}
float64 float64_trunc_to_int( float64 a STATUS_PARAM)
{
int oldmode;
float64 res;
oldmode = STATUS(float_rounding_mode);
STATUS(float_rounding_mode) = float_round_to_zero;
res = float64_round_to_int(a STATUS_VAR);
STATUS(float_rounding_mode) = oldmode;
return res;
}
/*----------------------------------------------------------------------------
| Returns the result of adding the absolute values of the double-precision
| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
@@ -2941,7 +2952,7 @@ float64 float64_sqrt( float64 a STATUS_PARAM )
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float64_eq( float64 a, float64 b STATUS_PARAM )
int float64_eq( float64 a, float64 b STATUS_PARAM )
{
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
@@ -2963,7 +2974,7 @@ flag float64_eq( float64 a, float64 b STATUS_PARAM )
| Arithmetic.
*----------------------------------------------------------------------------*/
flag float64_le( float64 a, float64 b STATUS_PARAM )
int float64_le( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -2986,7 +2997,7 @@ flag float64_le( float64 a, float64 b STATUS_PARAM )
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float64_lt( float64 a, float64 b STATUS_PARAM )
int float64_lt( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -3010,7 +3021,7 @@ flag float64_lt( float64 a, float64 b STATUS_PARAM )
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
{
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
@@ -3030,7 +3041,7 @@ flag float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float64_le_quiet( float64 a, float64 b STATUS_PARAM )
int float64_le_quiet( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -3056,7 +3067,7 @@ flag float64_le_quiet( float64 a, float64 b STATUS_PARAM )
| Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
int float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -3879,7 +3890,7 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
| Arithmetic.
*----------------------------------------------------------------------------*/
flag floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
{
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
@@ -3909,7 +3920,7 @@ flag floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -3942,7 +3953,7 @@ flag floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
| Arithmetic.
*----------------------------------------------------------------------------*/
flag floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -3975,7 +3986,7 @@ flag floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
{
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
@@ -4002,7 +4013,7 @@ flag floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -4038,7 +4049,7 @@ flag floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -4999,7 +5010,7 @@ float128 float128_sqrt( float128 a STATUS_PARAM )
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float128_eq( float128 a, float128 b STATUS_PARAM )
int float128_eq( float128 a, float128 b STATUS_PARAM )
{
if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
@@ -5029,7 +5040,7 @@ flag float128_eq( float128 a, float128 b STATUS_PARAM )
| Arithmetic.
*----------------------------------------------------------------------------*/
flag float128_le( float128 a, float128 b STATUS_PARAM )
int float128_le( float128 a, float128 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -5061,7 +5072,7 @@ flag float128_le( float128 a, float128 b STATUS_PARAM )
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float128_lt( float128 a, float128 b STATUS_PARAM )
int float128_lt( float128 a, float128 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -5094,7 +5105,7 @@ flag float128_lt( float128 a, float128 b STATUS_PARAM )
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
int float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
{
if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
@@ -5121,7 +5132,7 @@ flag float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float128_le_quiet( float128 a, float128 b STATUS_PARAM )
int float128_le_quiet( float128 a, float128 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -5157,7 +5168,7 @@ flag float128_le_quiet( float128 a, float128 b STATUS_PARAM )
| Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float128_lt_quiet( float128 a, float128 b STATUS_PARAM )
int float128_lt_quiet( float128 a, float128 b STATUS_PARAM )
{
flag aSign, bSign;
@@ -5272,7 +5283,7 @@ unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM )
}
#define COMPARE(s, nan_exp) \
INLINE char float ## s ## _compare_internal( float ## s a, float ## s b, \
INLINE int float ## s ## _compare_internal( float ## s a, float ## s b, \
int is_quiet STATUS_PARAM ) \
{ \
flag aSign, bSign; \
@@ -5306,12 +5317,12 @@ INLINE char float ## s ## _compare_internal( float ## s a, float ## s b, \
} \
} \
\
char float ## s ## _compare( float ## s a, float ## s b STATUS_PARAM ) \
int float ## s ## _compare( float ## s a, float ## s b STATUS_PARAM ) \
{ \
return float ## s ## _compare_internal(a, b, 0 STATUS_VAR); \
} \
\
char float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
{ \
return float ## s ## _compare_internal(a, b, 1 STATUS_VAR); \
}
+35 -33
View File
@@ -43,7 +43,7 @@ these four paragraphs for those parts of this code that are retained.
| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
| to the same as `int'.
*----------------------------------------------------------------------------*/
typedef char flag;
typedef uint8_t flag;
typedef uint8_t uint8;
typedef int8_t int8;
typedef int uint16;
@@ -228,15 +228,16 @@ float32 float32_mul( float32, float32 STATUS_PARAM );
float32 float32_div( float32, float32 STATUS_PARAM );
float32 float32_rem( float32, float32 STATUS_PARAM );
float32 float32_sqrt( float32 STATUS_PARAM );
char float32_eq( float32, float32 STATUS_PARAM );
char float32_le( float32, float32 STATUS_PARAM );
char float32_lt( float32, float32 STATUS_PARAM );
char float32_eq_signaling( float32, float32 STATUS_PARAM );
char float32_le_quiet( float32, float32 STATUS_PARAM );
char float32_lt_quiet( float32, float32 STATUS_PARAM );
char float32_compare( float32, float32 STATUS_PARAM );
char float32_compare_quiet( float32, float32 STATUS_PARAM );
char float32_is_signaling_nan( float32 );
int float32_eq( float32, float32 STATUS_PARAM );
int float32_le( float32, float32 STATUS_PARAM );
int float32_lt( float32, float32 STATUS_PARAM );
int float32_eq_signaling( float32, float32 STATUS_PARAM );
int float32_le_quiet( float32, float32 STATUS_PARAM );
int float32_lt_quiet( float32, float32 STATUS_PARAM );
int float32_compare( float32, float32 STATUS_PARAM );
int float32_compare_quiet( float32, float32 STATUS_PARAM );
int float32_is_signaling_nan( float32 );
int float64_is_nan( float64 a );
INLINE float32 float32_abs(float32 a)
{
@@ -269,21 +270,22 @@ float128 float64_to_float128( float64 STATUS_PARAM );
| Software IEC/IEEE double-precision operations.
*----------------------------------------------------------------------------*/
float64 float64_round_to_int( float64 STATUS_PARAM );
float64 float64_trunc_to_int( float64 STATUS_PARAM );
float64 float64_add( float64, float64 STATUS_PARAM );
float64 float64_sub( float64, float64 STATUS_PARAM );
float64 float64_mul( float64, float64 STATUS_PARAM );
float64 float64_div( float64, float64 STATUS_PARAM );
float64 float64_rem( float64, float64 STATUS_PARAM );
float64 float64_sqrt( float64 STATUS_PARAM );
char float64_eq( float64, float64 STATUS_PARAM );
char float64_le( float64, float64 STATUS_PARAM );
char float64_lt( float64, float64 STATUS_PARAM );
char float64_eq_signaling( float64, float64 STATUS_PARAM );
char float64_le_quiet( float64, float64 STATUS_PARAM );
char float64_lt_quiet( float64, float64 STATUS_PARAM );
char float64_compare( float64, float64 STATUS_PARAM );
char float64_compare_quiet( float64, float64 STATUS_PARAM );
char float64_is_signaling_nan( float64 );
int float64_eq( float64, float64 STATUS_PARAM );
int float64_le( float64, float64 STATUS_PARAM );
int float64_lt( float64, float64 STATUS_PARAM );
int float64_eq_signaling( float64, float64 STATUS_PARAM );
int float64_le_quiet( float64, float64 STATUS_PARAM );
int float64_lt_quiet( float64, float64 STATUS_PARAM );
int float64_compare( float64, float64 STATUS_PARAM );
int float64_compare_quiet( float64, float64 STATUS_PARAM );
int float64_is_signaling_nan( float64 );
INLINE float64 float64_abs(float64 a)
{
@@ -320,13 +322,13 @@ floatx80 floatx80_mul( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_div( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
char floatx80_eq( floatx80, floatx80 STATUS_PARAM );
char floatx80_le( floatx80, floatx80 STATUS_PARAM );
char floatx80_lt( floatx80, floatx80 STATUS_PARAM );
char floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
char floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
char floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
char floatx80_is_signaling_nan( floatx80 );
int floatx80_eq( floatx80, floatx80 STATUS_PARAM );
int floatx80_le( floatx80, floatx80 STATUS_PARAM );
int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
int floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_is_signaling_nan( floatx80 );
INLINE floatx80 floatx80_abs(floatx80 a)
{
@@ -367,13 +369,13 @@ float128 float128_mul( float128, float128 STATUS_PARAM );
float128 float128_div( float128, float128 STATUS_PARAM );
float128 float128_rem( float128, float128 STATUS_PARAM );
float128 float128_sqrt( float128 STATUS_PARAM );
char float128_eq( float128, float128 STATUS_PARAM );
char float128_le( float128, float128 STATUS_PARAM );
char float128_lt( float128, float128 STATUS_PARAM );
char float128_eq_signaling( float128, float128 STATUS_PARAM );
char float128_le_quiet( float128, float128 STATUS_PARAM );
char float128_lt_quiet( float128, float128 STATUS_PARAM );
char float128_is_signaling_nan( float128 );
int float128_eq( float128, float128 STATUS_PARAM );
int float128_le( float128, float128 STATUS_PARAM );
int float128_lt( float128, float128 STATUS_PARAM );
int float128_eq_signaling( float128, float128 STATUS_PARAM );
int float128_le_quiet( float128, float128 STATUS_PARAM );
int float128_lt_quiet( float128, float128 STATUS_PARAM );
int float128_is_signaling_nan( float128 );
INLINE float128 float128_abs(float128 a)
{
+339 -68
View File
@@ -52,26 +52,30 @@ enum RSState {
RS_GETLINE,
RS_CHKSUM1,
RS_CHKSUM2,
RS_SYSCALL,
};
/* XXX: This is not thread safe. Do we care? */
static int gdbserver_fd = -1;
typedef struct GDBState {
CPUState *env; /* current CPU */
enum RSState state; /* parsing state */
int fd;
char line_buf[4096];
int line_buf_index;
int line_csum;
char last_packet[4100];
int last_packet_len;
#ifdef CONFIG_USER_ONLY
int fd;
int running_state;
#else
CharDriverState *chr;
#endif
} GDBState;
#ifdef CONFIG_USER_ONLY
/* XXX: This is not thread safe. Do we care? */
static int gdbserver_fd = -1;
/* XXX: remove this hack. */
static GDBState gdbserver_state;
#endif
static int get_char(GDBState *s)
{
@@ -91,9 +95,32 @@ static int get_char(GDBState *s)
}
return ch;
}
#endif
/* GDB stub state for use by semihosting syscalls. */
static GDBState *gdb_syscall_state;
static gdb_syscall_complete_cb gdb_current_syscall_cb;
enum {
GDB_SYS_UNKNOWN,
GDB_SYS_ENABLED,
GDB_SYS_DISABLED,
} gdb_syscall_mode;
/* If gdb is connected when the first semihosting syscall occurs then use
remote gdb syscalls. Otherwise use native file IO. */
int use_gdb_syscalls(void)
{
if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {
gdb_syscall_mode = (gdb_syscall_state ? GDB_SYS_ENABLED
: GDB_SYS_DISABLED);
}
return gdb_syscall_mode == GDB_SYS_ENABLED;
}
static void put_buffer(GDBState *s, const uint8_t *buf, int len)
{
#ifdef CONFIG_USER_ONLY
int ret;
while (len > 0) {
@@ -106,6 +133,9 @@ static void put_buffer(GDBState *s, const uint8_t *buf, int len)
len -= ret;
}
}
#else
qemu_chr_write(s->chr, buf, len);
#endif
}
static inline int fromhex(int v)
@@ -154,33 +184,39 @@ static void hextomem(uint8_t *mem, const char *buf, int len)
/* return -1 if error, 0 if OK */
static int put_packet(GDBState *s, char *buf)
{
char buf1[3];
int len, csum, ch, i;
int len, csum, i;
char *p;
#ifdef DEBUG_GDB
printf("reply='%s'\n", buf);
#endif
for(;;) {
buf1[0] = '$';
put_buffer(s, buf1, 1);
p = s->last_packet;
*(p++) = '$';
len = strlen(buf);
put_buffer(s, buf, len);
memcpy(p, buf, len);
p += len;
csum = 0;
for(i = 0; i < len; i++) {
csum += buf[i];
}
buf1[0] = '#';
buf1[1] = tohex((csum >> 4) & 0xf);
buf1[2] = tohex((csum) & 0xf);
*(p++) = '#';
*(p++) = tohex((csum >> 4) & 0xf);
*(p++) = tohex((csum) & 0xf);
put_buffer(s, buf1, 3);
s->last_packet_len = p - s->last_packet;
put_buffer(s, s->last_packet, s->last_packet_len);
ch = get_char(s);
if (ch < 0)
#ifdef CONFIG_USER_ONLY
i = get_char(s);
if (i < 0)
return -1;
if (ch == '+')
if (i == '+')
break;
#else
break;
#endif
}
return 0;
}
@@ -434,6 +470,73 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
ptr += 8 * 12 + 4;
cpsr_write (env, tswapl(*(uint32_t *)ptr), 0xffffffff);
}
#elif defined (TARGET_M68K)
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
int i;
uint8_t *ptr;
CPU_DoubleU u;
ptr = mem_buf;
/* D0-D7 */
for (i = 0; i < 8; i++) {
*(uint32_t *)ptr = tswapl(env->dregs[i]);
ptr += 4;
}
/* A0-A7 */
for (i = 0; i < 8; i++) {
*(uint32_t *)ptr = tswapl(env->aregs[i]);
ptr += 4;
}
*(uint32_t *)ptr = tswapl(env->sr);
ptr += 4;
*(uint32_t *)ptr = tswapl(env->pc);
ptr += 4;
/* F0-F7. The 68881/68040 have 12-bit extended precision registers.
ColdFire has 8-bit double precision registers. */
for (i = 0; i < 8; i++) {
u.d = env->fregs[i];
*(uint32_t *)ptr = tswap32(u.l.upper);
*(uint32_t *)ptr = tswap32(u.l.lower);
}
/* FP control regs (not implemented). */
memset (ptr, 0, 3 * 4);
ptr += 3 * 4;
return ptr - mem_buf;
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
int i;
uint8_t *ptr;
CPU_DoubleU u;
ptr = mem_buf;
/* D0-D7 */
for (i = 0; i < 8; i++) {
env->dregs[i] = tswapl(*(uint32_t *)ptr);
ptr += 4;
}
/* A0-A7 */
for (i = 0; i < 8; i++) {
env->aregs[i] = tswapl(*(uint32_t *)ptr);
ptr += 4;
}
env->sr = tswapl(*(uint32_t *)ptr);
ptr += 4;
env->pc = tswapl(*(uint32_t *)ptr);
ptr += 4;
/* F0-F7. The 68881/68040 have 12-bit extended precision registers.
ColdFire has 8-bit double precision registers. */
for (i = 0; i < 8; i++) {
u.l.upper = tswap32(*(uint32_t *)ptr);
u.l.lower = tswap32(*(uint32_t *)ptr);
env->fregs[i] = u.d;
}
/* FP control regs (not implemented). */
ptr += 3 * 4;
}
#elif defined (TARGET_MIPS)
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
@@ -465,11 +568,37 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
*(uint32_t *)ptr = tswapl(env->PC);
ptr += 4;
#ifdef MIPS_USES_FPU
for (i = 0; i < 32; i++)
{
*(uint32_t *)ptr = tswapl(FPR_W (env, i));
ptr += 4;
}
*(uint32_t *)ptr = tswapl(env->fcr31);
ptr += 4;
*(uint32_t *)ptr = tswapl(env->fcr0);
ptr += 4;
#endif
/* 32 FP registers, fsr, fir, fp. Not yet implemented. */
/* what's 'fp' mean here? */
return ptr - mem_buf;
}
/* convert MIPS rounding mode in FCR31 to IEEE library */
static unsigned int ieee_rm[] =
{
float_round_nearest_even,
float_round_to_zero,
float_round_up,
float_round_down
};
#define RESTORE_ROUNDING_MODE \
set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
int i;
@@ -499,6 +628,28 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
env->PC = tswapl(*(uint32_t *)ptr);
ptr += 4;
#ifdef MIPS_USES_FPU
for (i = 0; i < 32; i++)
{
FPR_W (env, i) = tswapl(*(uint32_t *)ptr);
ptr += 4;
}
env->fcr31 = tswapl(*(uint32_t *)ptr) & 0x0183FFFF;
ptr += 4;
env->fcr0 = tswapl(*(uint32_t *)ptr);
ptr += 4;
/* set rounding mode */
RESTORE_ROUNDING_MODE;
#ifndef CONFIG_SOFTFLOAT
/* no floating point exception for native float */
SET_FP_ENABLE(env->fcr31, 0);
#endif
#endif
}
#elif defined (TARGET_SH4)
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
@@ -626,6 +777,34 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
vm_start();
#endif
return RS_IDLE;
case 'F':
{
target_ulong ret;
target_ulong err;
ret = strtoull(p, (char **)&p, 16);
if (*p == ',') {
p++;
err = strtoull(p, (char **)&p, 16);
} else {
err = 0;
}
if (*p == ',')
p++;
type = *p;
if (gdb_current_syscall_cb)
gdb_current_syscall_cb(s->env, ret, err);
if (type == 'C') {
put_packet(s, "T02");
} else {
#ifdef CONFIG_USER_ONLY
s->running_state = 1;
#else
vm_start();
#endif
}
}
break;
case 'g':
reg_size = cpu_gdb_read_registers(env, mem_buf);
memtohex(buf, mem_buf, reg_size);
@@ -695,7 +874,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
goto breakpoint_error;
}
break;
#ifdef CONFIG_USER_ONLY
#ifdef CONFIG_LINUX_USER
case 'q':
if (strncmp(p, "Offsets", 7) == 0) {
TaskState *ts = env->opaque;
@@ -726,6 +905,9 @@ static void gdb_vm_stopped(void *opaque, int reason)
char buf[256];
int ret;
if (s->state == RS_SYSCALL)
return;
/* disable single step if it was enable */
cpu_single_step(s->env, 0);
@@ -742,6 +924,60 @@ static void gdb_vm_stopped(void *opaque, int reason)
}
#endif
/* Send a gdb syscall request.
This accepts limited printf-style format specifiers, specifically:
%x - target_ulong argument printed in hex.
%s - string pointer (target_ulong) and length (int) pair. */
void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...)
{
va_list va;
char buf[256];
char *p;
target_ulong addr;
GDBState *s;
s = gdb_syscall_state;
if (!s)
return;
gdb_current_syscall_cb = cb;
s->state = RS_SYSCALL;
#ifndef CONFIG_USER_ONLY
vm_stop(EXCP_DEBUG);
#endif
s->state = RS_IDLE;
va_start(va, fmt);
p = buf;
*(p++) = 'F';
while (*fmt) {
if (*fmt == '%') {
fmt++;
switch (*fmt++) {
case 'x':
addr = va_arg(va, target_ulong);
p += sprintf(p, TARGET_FMT_lx, addr);
break;
case 's':
addr = va_arg(va, target_ulong);
p += sprintf(p, TARGET_FMT_lx "/%x", addr, va_arg(va, int));
break;
default:
fprintf(stderr, "gdbstub: Bad syscall format string '%s'\n",
fmt - 1);
break;
}
} else {
*(p++) = *(fmt++);
}
}
va_end(va);
put_packet(s, buf);
#ifdef CONFIG_USER_ONLY
gdb_handlesig(s->env, 0);
#else
cpu_interrupt(s->env, CPU_INTERRUPT_EXIT);
#endif
}
static void gdb_read_byte(GDBState *s, int ch)
{
CPUState *env = s->env;
@@ -749,6 +985,26 @@ static void gdb_read_byte(GDBState *s, int ch)
char reply[1];
#ifndef CONFIG_USER_ONLY
if (s->last_packet_len) {
/* Waiting for a response to the last packet. If we see the start
of a new command then abandon the previous response. */
if (ch == '-') {
#ifdef DEBUG_GDB
printf("Got NACK, retransmitting\n");
#endif
put_buffer(s, s->last_packet, s->last_packet_len);
}
#ifdef DEBUG_GDB
else if (ch == '+')
printf("Got ACK\n");
else
printf("Got '%c' when expecting ACK/NACK\n", ch);
#endif
if (ch == '+' || ch == '$')
s->last_packet_len = 0;
if (ch != '$')
return;
}
if (vm_running) {
/* when the CPU is running, we cannot do anything except stop
it when receiving a char */
@@ -793,6 +1049,8 @@ static void gdb_read_byte(GDBState *s, int ch)
s->state = gdb_handle_packet(s, env, s->line_buf);
}
break;
default:
abort();
}
}
}
@@ -857,29 +1115,6 @@ void gdb_exit(CPUState *env, int code)
put_packet(s, buf);
}
#else
static void gdb_read(void *opaque)
{
GDBState *s = opaque;
int i, size;
uint8_t buf[4096];
size = recv(s->fd, buf, sizeof(buf), 0);
if (size < 0)
return;
if (size == 0) {
/* end of connection */
qemu_del_vm_stop_handler(gdb_vm_stopped, s);
qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
qemu_free(s);
vm_start();
} else {
for(i = 0; i < size; i++)
gdb_read_byte(s, buf[i]);
}
}
#endif
static void gdb_accept(void *opaque)
{
@@ -903,32 +1138,14 @@ static void gdb_accept(void *opaque)
val = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
#ifdef CONFIG_USER_ONLY
s = &gdbserver_state;
memset (s, 0, sizeof (GDBState));
#else
s = qemu_mallocz(sizeof(GDBState));
if (!s) {
close(fd);
return;
}
#endif
s->env = first_cpu; /* XXX: allow to change CPU */
s->fd = fd;
#ifdef CONFIG_USER_ONLY
gdb_syscall_state = s;
fcntl(fd, F_SETFL, O_NONBLOCK);
#else
socket_set_nonblock(fd);
/* stop the VM */
vm_stop(EXCP_INTERRUPT);
/* start handling I/O */
qemu_set_fd_handler(s->fd, gdb_read, NULL, s);
/* when the VM is stopped, the following callback is called */
qemu_add_vm_stop_handler(gdb_vm_stopped, s);
#endif
}
static int gdbserver_open(int port)
@@ -959,9 +1176,6 @@ static int gdbserver_open(int port)
perror("listen");
return -1;
}
#ifndef CONFIG_USER_ONLY
socket_set_nonblock(fd);
#endif
return fd;
}
@@ -971,10 +1185,67 @@ int gdbserver_start(int port)
if (gdbserver_fd < 0)
return -1;
/* accept connections */
#ifdef CONFIG_USER_ONLY
gdb_accept (NULL);
#else
qemu_set_fd_handler(gdbserver_fd, gdb_accept, NULL, NULL);
#endif
return 0;
}
#else
static int gdb_chr_can_recieve(void *opaque)
{
return 1;
}
static void gdb_chr_recieve(void *opaque, const uint8_t *buf, int size)
{
GDBState *s = opaque;
int i;
for (i = 0; i < size; i++) {
gdb_read_byte(s, buf[i]);
}
}
static void gdb_chr_event(void *opaque, int event)
{
switch (event) {
case CHR_EVENT_RESET:
vm_stop(EXCP_INTERRUPT);
gdb_syscall_state = opaque;
break;
default:
break;
}
}
int gdbserver_start(CharDriverState *chr)
{
GDBState *s;
if (!chr)
return -1;
s = qemu_mallocz(sizeof(GDBState));
if (!s) {
return -1;
}
s->env = first_cpu; /* XXX: allow to change CPU */
s->chr = chr;
qemu_chr_add_handlers(chr, gdb_chr_can_recieve, gdb_chr_recieve,
gdb_chr_event, s);
qemu_add_vm_stop_handler(gdb_vm_stopped, s);
return 0;
}
int gdbserver_start_port(int port)
{
CharDriverState *chr;
char gdbstub_port_name[128];
snprintf(gdbstub_port_name, sizeof(gdbstub_port_name),
"tcp::%d,nowait,nodelay,server", port);
chr = qemu_chr_open(gdbstub_port_name);
if (!chr)
return -EIO;
return gdbserver_start(chr);
}
#endif
+9 -1
View File
@@ -3,10 +3,18 @@
#define DEFAULT_GDBSTUB_PORT 1234
typedef void (*gdb_syscall_complete_cb)(CPUState *env,
target_ulong ret, target_ulong err);
void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...);
int use_gdb_syscalls(void);
#ifdef CONFIG_USER_ONLY
int gdb_handlesig (CPUState *, int);
void gdb_exit(CPUState *, int);
#endif
int gdbserver_start(int);
#else
int gdbserver_start(CharDriverState *chr);
int gdbserver_start_port(int port);
#endif
#endif
+98
View File
@@ -0,0 +1,98 @@
/*
* Save/restore host registrs.
*
* Copyright (c) 2007 CodeSourcery
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* The GCC global register vairable extension is used to reserve some
host registers for use by dyngen. However only the core parts of the
translation engine are compiled with these settings. We must manually
save/restore these registers when called from regular code.
It is not sufficient to save/restore T0 et. al. as these may be declared
with a datatype smaller than the actual register. */
#if defined(DECLARE_HOST_REGS)
#define DO_REG(REG) \
register host_reg_t reg_AREG##REG asm(AREG##REG); \
volatile host_reg_t saved_AREG##REG;
#elif defined(SAVE_HOST_REGS)
#define DO_REG(REG) \
__asm__ __volatile__ ("" : "=r" (reg_AREG##REG)); \
saved_AREG##REG = reg_AREG##REG;
#else
#define DO_REG(REG) \
reg_AREG##REG = saved_AREG##REG; \
__asm__ __volatile__ ("" : : "r" (reg_AREG##REG));
#endif
#ifdef AREG0
DO_REG(0)
#endif
#ifdef AREG1
DO_REG(1)
#endif
#ifdef AREG2
DO_REG(2)
#endif
#ifdef AREG3
DO_REG(3)
#endif
#ifdef AREG4
DO_REG(4)
#endif
#ifdef AREG5
DO_REG(5)
#endif
#ifdef AREG6
DO_REG(6)
#endif
#ifdef AREG7
DO_REG(7)
#endif
#ifdef AREG8
DO_REG(8)
#endif
#ifdef AREG9
DO_REG(9)
#endif
#ifdef AREG10
DO_REG(10)
#endif
#ifdef AREG11
DO_REG(11)
#endif
#undef SAVE_HOST_REGS
#undef DECLARE_HOST_REGS
#undef DO_REG
-559
View File
@@ -1,559 +0,0 @@
/*
* QEMU ACPI DSDT ASL definition
*
* Copyright (c) 2006 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
DefinitionBlock (
"acpi-dsdt.aml", // Output Filename
"DSDT", // Signature
0x01, // DSDT Compliance Revision
"QEMU", // OEMID
"QEMUDSDT", // TABLE ID
0x1 // OEM Revision
)
{
Scope (\)
{
/* CMOS memory access */
OperationRegion (CMS, SystemIO, 0x70, 0x02)
Field (CMS, ByteAcc, NoLock, Preserve)
{
CMSI, 8,
CMSD, 8
}
Method (CMRD, 1, NotSerialized)
{
Store (Arg0, CMSI)
Store (CMSD, Local0)
Return (Local0)
}
/* Debug Output */
OperationRegion (DBG, SystemIO, 0xb044, 0x04)
Field (DBG, DWordAcc, NoLock, Preserve)
{
DBGL, 32,
}
}
/* PCI Bus definition */
Scope(\_SB) {
Device(PCI0) {
Name (_HID, EisaId ("PNP0A03"))
Name (_ADR, 0x00)
Name (_UID, 1)
Name(_PRT, Package() {
/* PCI IRQ routing table, example from ACPI 2.0a specification,
section 6.2.8.1 */
/* Note: we provide the same info as the PCI routing
table of the Bochs BIOS */
// PCI Slot 0
Package() {0x0000ffff, 0, LNKD, 0},
Package() {0x0000ffff, 1, LNKA, 0},
Package() {0x0000ffff, 2, LNKB, 0},
Package() {0x0000ffff, 3, LNKC, 0},
// PCI Slot 1
Package() {0x0001ffff, 0, LNKA, 0},
Package() {0x0001ffff, 1, LNKB, 0},
Package() {0x0001ffff, 2, LNKC, 0},
Package() {0x0001ffff, 3, LNKD, 0},
// PCI Slot 2
Package() {0x0002ffff, 0, LNKB, 0},
Package() {0x0002ffff, 1, LNKC, 0},
Package() {0x0002ffff, 2, LNKD, 0},
Package() {0x0002ffff, 3, LNKA, 0},
// PCI Slot 3
Package() {0x0003ffff, 0, LNKC, 0},
Package() {0x0003ffff, 1, LNKD, 0},
Package() {0x0003ffff, 2, LNKA, 0},
Package() {0x0003ffff, 3, LNKB, 0},
// PCI Slot 4
Package() {0x0004ffff, 0, LNKD, 0},
Package() {0x0004ffff, 1, LNKA, 0},
Package() {0x0004ffff, 2, LNKB, 0},
Package() {0x0004ffff, 3, LNKC, 0},
// PCI Slot 5
Package() {0x0005ffff, 0, LNKA, 0},
Package() {0x0005ffff, 1, LNKB, 0},
Package() {0x0005ffff, 2, LNKC, 0},
Package() {0x0005ffff, 3, LNKD, 0},
})
Method (_CRS, 0, NotSerialized)
{
Name (MEMP, ResourceTemplate ()
{
WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
0x0000, // Address Space Granularity
0x0000, // Address Range Minimum
0x00FF, // Address Range Maximum
0x0000, // Address Translation Offset
0x0100, // Address Length
,, )
IO (Decode16,
0x0CF8, // Address Range Minimum
0x0CF8, // Address Range Maximum
0x01, // Address Alignment
0x08, // Address Length
)
WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, // Address Space Granularity
0x0000, // Address Range Minimum
0x0CF7, // Address Range Maximum
0x0000, // Address Translation Offset
0x0CF8, // Address Length
,, , TypeStatic)
WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, // Address Space Granularity
0x0D00, // Address Range Minimum
0xFFFF, // Address Range Maximum
0x0000, // Address Translation Offset
0xF300, // Address Length
,, , TypeStatic)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
0x00000000, // Address Space Granularity
0x000A0000, // Address Range Minimum
0x000BFFFF, // Address Range Maximum
0x00000000, // Address Translation Offset
0x00020000, // Address Length
,, , AddressRangeMemory, TypeStatic)
DWordMemory (ResourceProducer, PosDecode, MinNotFixed, MaxFixed, NonCacheable, ReadWrite,
0x00000000, // Address Space Granularity
0x00000000, // Address Range Minimum
0xFEBFFFFF, // Address Range Maximum
0x00000000, // Address Translation Offset
0x00000000, // Address Length
,, MEMF, AddressRangeMemory, TypeStatic)
})
CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._MIN, PMIN)
CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._MAX, PMAX)
CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._LEN, PLEN)
/* compute available RAM */
Add(CMRD(0x34), ShiftLeft(CMRD(0x35), 8), Local0)
ShiftLeft(Local0, 16, Local0)
Add(Local0, 0x1000000, Local0)
/* update field of last region */
Store(Local0, PMIN)
Subtract (PMAX, PMIN, PLEN)
Increment (PLEN)
Return (MEMP)
}
}
}
Scope(\_SB.PCI0) {
/* PIIX3 ISA bridge */
Device (ISA) {
Name (_ADR, 0x00010000)
/* PIIX PCI to ISA irq remapping */
OperationRegion (P40C, PCI_Config, 0x60, 0x04)
/* Keyboard seems to be important for WinXP install */
Device (KBD)
{
Name (_HID, EisaId ("PNP0303"))
Method (_STA, 0, NotSerialized)
{
Return (0x0f)
}
Method (_CRS, 0, NotSerialized)
{
Name (TMP, ResourceTemplate ()
{
IO (Decode16,
0x0060, // Address Range Minimum
0x0060, // Address Range Maximum
0x01, // Address Alignment
0x01, // Address Length
)
IO (Decode16,
0x0064, // Address Range Minimum
0x0064, // Address Range Maximum
0x01, // Address Alignment
0x01, // Address Length
)
IRQNoFlags ()
{1}
})
Return (TMP)
}
}
/* PS/2 mouse */
Device (MOU)
{
Name (_HID, EisaId ("PNP0F13"))
Method (_STA, 0, NotSerialized)
{
Return (0x0f)
}
Method (_CRS, 0, NotSerialized)
{
Name (TMP, ResourceTemplate ()
{
IRQNoFlags () {12}
})
Return (TMP)
}
}
/* PS/2 floppy controller */
Device (FDC0)
{
Name (_HID, EisaId ("PNP0700"))
Method (_STA, 0, NotSerialized)
{
Return (0x0F)
}
Method (_CRS, 0, NotSerialized)
{
Name (BUF0, ResourceTemplate ()
{
IO (Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
IO (Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
IRQNoFlags () {6}
DMA (Compatibility, NotBusMaster, Transfer8) {2}
})
Return (BUF0)
}
}
/* Parallel port */
Device (LPT)
{
Name (_HID, EisaId ("PNP0400"))
Method (_STA, 0, NotSerialized)
{
Store (\_SB.PCI0.PX13.DRSA, Local0)
And (Local0, 0x80000000, Local0)
If (LEqual (Local0, 0))
{
Return (0x00)
}
Else
{
Return (0x0F)
}
}
Method (_CRS, 0, NotSerialized)
{
Name (BUF0, ResourceTemplate ()
{
IO (Decode16, 0x0378, 0x0378, 0x08, 0x08)
IRQNoFlags () {7}
})
Return (BUF0)
}
}
/* Serial Ports */
Device (COM1)
{
Name (_HID, EisaId ("PNP0501"))
Name (_UID, 0x01)
Method (_STA, 0, NotSerialized)
{
Store (\_SB.PCI0.PX13.DRSC, Local0)
And (Local0, 0x08000000, Local0)
If (LEqual (Local0, 0))
{
Return (0x00)
}
Else
{
Return (0x0F)
}
}
Method (_CRS, 0, NotSerialized)
{
Name (BUF0, ResourceTemplate ()
{
IO (Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
IRQNoFlags () {4}
})
Return (BUF0)
}
}
Device (COM2)
{
Name (_HID, EisaId ("PNP0501"))
Name (_UID, 0x02)
Method (_STA, 0, NotSerialized)
{
Store (\_SB.PCI0.PX13.DRSC, Local0)
And (Local0, 0x80000000, Local0)
If (LEqual (Local0, 0))
{
Return (0x00)
}
Else
{
Return (0x0F)
}
}
Method (_CRS, 0, NotSerialized)
{
Name (BUF0, ResourceTemplate ()
{
IO (Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
IRQNoFlags () {3}
})
Return (BUF0)
}
}
}
/* PIIX4 PM */
Device (PX13) {
Name (_ADR, 0x00010003)
OperationRegion (P13C, PCI_Config, 0x5c, 0x24)
Field (P13C, DWordAcc, NoLock, Preserve)
{
DRSA, 32,
DRSB, 32,
DRSC, 32,
DRSE, 32,
DRSF, 32,
DRSG, 32,
DRSH, 32,
DRSI, 32,
DRSJ, 32
}
}
}
/* PCI IRQs */
Scope(\_SB) {
Field (\_SB.PCI0.ISA.P40C, ByteAcc, NoLock, Preserve)
{
PRQ0, 8,
PRQ1, 8,
PRQ2, 8,
PRQ3, 8
}
Device(LNKA){
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
Name(_UID, 1)
Name(_PRS, ResourceTemplate(){
IRQ (Level, ActiveLow, Shared)
{3,4,5,6,7,9,10,11,12}
})
Method (_STA, 0, NotSerialized)
{
Store (0x0B, Local0)
If (And (0x80, PRQ0, Local1))
{
Store (0x09, Local0)
}
Return (Local0)
}
Method (_DIS, 0, NotSerialized)
{
Or (PRQ0, 0x80, PRQ0)
}
Method (_CRS, 0, NotSerialized)
{
Name (PRR0, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared)
{1}
})
CreateWordField (PRR0, 0x01, TMP)
Store (PRQ0, Local0)
If (LLess (Local0, 0x80))
{
ShiftLeft (One, Local0, TMP)
}
Else
{
Store (Zero, TMP)
}
Return (PRR0)
}
Method (_SRS, 1, NotSerialized)
{
CreateWordField (Arg0, 0x01, TMP)
FindSetRightBit (TMP, Local0)
Decrement (Local0)
Store (Local0, PRQ0)
}
}
Device(LNKB){
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
Name(_UID, 2)
Name(_PRS, ResourceTemplate(){
IRQ (Level, ActiveLow, Shared)
{3,4,5,6,7,9,10,11,12}
})
Method (_STA, 0, NotSerialized)
{
Store (0x0B, Local0)
If (And (0x80, PRQ1, Local1))
{
Store (0x09, Local0)
}
Return (Local0)
}
Method (_DIS, 0, NotSerialized)
{
Or (PRQ1, 0x80, PRQ1)
}
Method (_CRS, 0, NotSerialized)
{
Name (PRR0, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared)
{1}
})
CreateWordField (PRR0, 0x01, TMP)
Store (PRQ1, Local0)
If (LLess (Local0, 0x80))
{
ShiftLeft (One, Local0, TMP)
}
Else
{
Store (Zero, TMP)
}
Return (PRR0)
}
Method (_SRS, 1, NotSerialized)
{
CreateWordField (Arg0, 0x01, TMP)
FindSetRightBit (TMP, Local0)
Decrement (Local0)
Store (Local0, PRQ1)
}
}
Device(LNKC){
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
Name(_UID, 3)
Name(_PRS, ResourceTemplate(){
IRQ (Level, ActiveLow, Shared)
{3,4,5,6,7,9,10,11,12}
})
Method (_STA, 0, NotSerialized)
{
Store (0x0B, Local0)
If (And (0x80, PRQ2, Local1))
{
Store (0x09, Local0)
}
Return (Local0)
}
Method (_DIS, 0, NotSerialized)
{
Or (PRQ2, 0x80, PRQ2)
}
Method (_CRS, 0, NotSerialized)
{
Name (PRR0, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared)
{1}
})
CreateWordField (PRR0, 0x01, TMP)
Store (PRQ2, Local0)
If (LLess (Local0, 0x80))
{
ShiftLeft (One, Local0, TMP)
}
Else
{
Store (Zero, TMP)
}
Return (PRR0)
}
Method (_SRS, 1, NotSerialized)
{
CreateWordField (Arg0, 0x01, TMP)
FindSetRightBit (TMP, Local0)
Decrement (Local0)
Store (Local0, PRQ2)
}
}
Device(LNKD){
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
Name(_UID, 4)
Name(_PRS, ResourceTemplate(){
IRQ (Level, ActiveLow, Shared)
{3,4,5,6,7,9,10,11,12}
})
Method (_STA, 0, NotSerialized)
{
Store (0x0B, Local0)
If (And (0x80, PRQ3, Local1))
{
Store (0x09, Local0)
}
Return (Local0)
}
Method (_DIS, 0, NotSerialized)
{
Or (PRQ3, 0x80, PRQ3)
}
Method (_CRS, 0, NotSerialized)
{
Name (PRR0, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared)
{1}
})
CreateWordField (PRR0, 0x01, TMP)
Store (PRQ3, Local0)
If (LLess (Local0, 0x80))
{
ShiftLeft (One, Local0, TMP)
}
Else
{
Store (Zero, TMP)
}
Return (PRR0)
}
Method (_SRS, 1, NotSerialized)
{
CreateWordField (Arg0, 0x01, TMP)
FindSetRightBit (TMP, Local0)
Decrement (Local0)
Store (Local0, PRQ3)
}
}
}
/* S5 = power off state */
Name (_S5, Package (4) {
0x00, // PM1a_CNT.SLP_TYP
0x00, // PM2a_CNT.SLP_TYP
0x00, // reserved
0x00, // reserved
})
}
-278
View File
@@ -1,278 +0,0 @@
/*
*
* Intel ACPI Component Architecture
* ASL Optimizing Compiler version 20060421 [Apr 29 2006]
* Copyright (C) 2000 - 2006 Intel Corporation
* Supports ACPI Specification Revision 3.0a
*
* Compilation of "/usr/local/home/bellard/qemu-current/hw/acpi-dsdt.dsl" - Wed Jun 14 20:09:53 2006
*
* C source code output
*
*/
unsigned char AmlCode[] =
{
0x44,0x53,0x44,0x54,0x32,0x08,0x00,0x00, /* 00000000 "DSDT2..." */
0x01,0x5B,0x51,0x45,0x4D,0x55,0x00,0x00, /* 00000008 ".[QEMU.." */
0x51,0x45,0x4D,0x55,0x44,0x53,0x44,0x54, /* 00000010 "QEMUDSDT" */
0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
0x21,0x04,0x06,0x20,0x10,0x4F,0x04,0x5C, /* 00000020 "!.. .O.\" */
0x00,0x5B,0x80,0x43,0x4D,0x53,0x5F,0x01, /* 00000028 ".[.CMS_." */
0x0A,0x70,0x0A,0x02,0x5B,0x81,0x10,0x43, /* 00000030 ".p..[..C" */
0x4D,0x53,0x5F,0x01,0x43,0x4D,0x53,0x49, /* 00000038 "MS_.CMSI" */
0x08,0x43,0x4D,0x53,0x44,0x08,0x14,0x14, /* 00000040 ".CMSD..." */
0x43,0x4D,0x52,0x44,0x01,0x70,0x68,0x43, /* 00000048 "CMRD.phC" */
0x4D,0x53,0x49,0x70,0x43,0x4D,0x53,0x44, /* 00000050 "MSIpCMSD" */
0x60,0xA4,0x60,0x5B,0x80,0x44,0x42,0x47, /* 00000058 "`.`[.DBG" */
0x5F,0x01,0x0B,0x44,0xB0,0x0A,0x04,0x5B, /* 00000060 "_..D...[" */
0x81,0x0B,0x44,0x42,0x47,0x5F,0x03,0x44, /* 00000068 "..DBG_.D" */
0x42,0x47,0x4C,0x20,0x10,0x4E,0x25,0x5F, /* 00000070 "BGL .N%_" */
0x53,0x42,0x5F,0x5B,0x82,0x46,0x25,0x50, /* 00000078 "SB_[.F%P" */
0x43,0x49,0x30,0x08,0x5F,0x48,0x49,0x44, /* 00000080 "CI0._HID" */
0x0C,0x41,0xD0,0x0A,0x03,0x08,0x5F,0x41, /* 00000088 ".A...._A" */
0x44,0x52,0x00,0x08,0x5F,0x55,0x49,0x44, /* 00000090 "DR.._UID" */
0x01,0x08,0x5F,0x50,0x52,0x54,0x12,0x47, /* 00000098 ".._PRT.G" */
0x15,0x18,0x12,0x0B,0x04,0x0B,0xFF,0xFF, /* 000000A0 "........" */
0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0B, /* 000000A8 ".LNKD..." */
0x04,0x0B,0xFF,0xFF,0x01,0x4C,0x4E,0x4B, /* 000000B0 ".....LNK" */
0x41,0x00,0x12,0x0C,0x04,0x0B,0xFF,0xFF, /* 000000B8 "A......." */
0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 000000C0 "..LNKB.." */
0x0C,0x04,0x0B,0xFF,0xFF,0x0A,0x03,0x4C, /* 000000C8 ".......L" */
0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 000000D0 "NKC....." */
0xFF,0xFF,0x01,0x00,0x00,0x4C,0x4E,0x4B, /* 000000D8 ".....LNK" */
0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000000E0 "A......." */
0x01,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00, /* 000000E8 "...LNKB." */
0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00, /* 000000F0 "........" */
0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 000000F8 "..LNKC.." */
0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A, /* 00000100 "........" */
0x03,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000108 ".LNKD..." */
0x04,0x0C,0xFF,0xFF,0x02,0x00,0x00,0x4C, /* 00000110 ".......L" */
0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C, /* 00000118 "NKB....." */
0xFF,0xFF,0x02,0x00,0x01,0x4C,0x4E,0x4B, /* 00000120 ".....LNK" */
0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000128 "C......." */
0x02,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44, /* 00000130 "....LNKD" */
0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02, /* 00000138 "........" */
0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00, /* 00000140 "...LNKA." */
0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x03,0x00, /* 00000148 "........" */
0x00,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D, /* 00000150 ".LNKC..." */
0x04,0x0C,0xFF,0xFF,0x03,0x00,0x01,0x4C, /* 00000158 ".......L" */
0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 00000160 "NKD....." */
0xFF,0xFF,0x03,0x00,0x0A,0x02,0x4C,0x4E, /* 00000168 "......LN" */
0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000170 "KA......" */
0xFF,0x03,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000178 ".....LNK" */
0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000180 "B......." */
0x04,0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00, /* 00000188 "...LNKD." */
0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x04,0x00, /* 00000190 "........" */
0x01,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 00000198 ".LNKA..." */
0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x02, /* 000001A0 "........" */
0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04, /* 000001A8 "LNKB...." */
0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x03,0x4C, /* 000001B0 ".......L" */
0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 000001B8 "NKC....." */
0xFF,0xFF,0x05,0x00,0x00,0x4C,0x4E,0x4B, /* 000001C0 ".....LNK" */
0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000001C8 "A......." */
0x05,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00, /* 000001D0 "...LNKB." */
0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x05,0x00, /* 000001D8 "........" */
0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 000001E0 "..LNKC.." */
0x0E,0x04,0x0C,0xFF,0xFF,0x05,0x00,0x0A, /* 000001E8 "........" */
0x03,0x4C,0x4E,0x4B,0x44,0x00,0x14,0x4C, /* 000001F0 ".LNKD..L" */
0x0D,0x5F,0x43,0x52,0x53,0x00,0x08,0x4D, /* 000001F8 "._CRS..M" */
0x45,0x4D,0x50,0x11,0x42,0x07,0x0A,0x6E, /* 00000200 "EMP.B..n" */
0x88,0x0D,0x00,0x02,0x0C,0x00,0x00,0x00, /* 00000208 "........" */
0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x01, /* 00000210 "........" */
0x47,0x01,0xF8,0x0C,0xF8,0x0C,0x01,0x08, /* 00000218 "G......." */
0x88,0x0D,0x00,0x01,0x0C,0x03,0x00,0x00, /* 00000220 "........" */
0x00,0x00,0xF7,0x0C,0x00,0x00,0xF8,0x0C, /* 00000228 "........" */
0x88,0x0D,0x00,0x01,0x0C,0x03,0x00,0x00, /* 00000230 "........" */
0x00,0x0D,0xFF,0xFF,0x00,0x00,0x00,0xF3, /* 00000238 "........" */
0x87,0x17,0x00,0x00,0x0C,0x03,0x00,0x00, /* 00000240 "........" */
0x00,0x00,0x00,0x00,0x0A,0x00,0xFF,0xFF, /* 00000248 "........" */
0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000250 "........" */
0x02,0x00,0x87,0x17,0x00,0x00,0x08,0x01, /* 00000258 "........" */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000260 "........" */
0xFF,0xFF,0xBF,0xFE,0x00,0x00,0x00,0x00, /* 00000268 "........" */
0x00,0x00,0x00,0x00,0x79,0x00,0x8A,0x4D, /* 00000270 "....y..M" */
0x45,0x4D,0x50,0x0A,0x5C,0x50,0x4D,0x49, /* 00000278 "EMP.\PMI" */
0x4E,0x8A,0x4D,0x45,0x4D,0x50,0x0A,0x60, /* 00000280 "N.MEMP.`" */
0x50,0x4D,0x41,0x58,0x8A,0x4D,0x45,0x4D, /* 00000288 "PMAX.MEM" */
0x50,0x0A,0x68,0x50,0x4C,0x45,0x4E,0x72, /* 00000290 "P.hPLENr" */
0x43,0x4D,0x52,0x44,0x0A,0x34,0x79,0x43, /* 00000298 "CMRD.4yC" */
0x4D,0x52,0x44,0x0A,0x35,0x0A,0x08,0x00, /* 000002A0 "MRD.5..." */
0x60,0x79,0x60,0x0A,0x10,0x60,0x72,0x60, /* 000002A8 "`y`..`r`" */
0x0C,0x00,0x00,0x00,0x01,0x60,0x70,0x60, /* 000002B0 ".....`p`" */
0x50,0x4D,0x49,0x4E,0x74,0x50,0x4D,0x41, /* 000002B8 "PMINtPMA" */
0x58,0x50,0x4D,0x49,0x4E,0x50,0x4C,0x45, /* 000002C0 "XPMINPLE" */
0x4E,0x75,0x50,0x4C,0x45,0x4E,0xA4,0x4D, /* 000002C8 "NuPLEN.M" */
0x45,0x4D,0x50,0x10,0x42,0x26,0x2E,0x5F, /* 000002D0 "EMP.B&._" */
0x53,0x42,0x5F,0x50,0x43,0x49,0x30,0x5B, /* 000002D8 "SB_PCI0[" */
0x82,0x43,0x20,0x49,0x53,0x41,0x5F,0x08, /* 000002E0 ".C ISA_." */
0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,0x01, /* 000002E8 "_ADR...." */
0x00,0x5B,0x80,0x50,0x34,0x30,0x43,0x02, /* 000002F0 ".[.P40C." */
0x0A,0x60,0x0A,0x04,0x5B,0x82,0x44,0x04, /* 000002F8 ".`..[.D." */
0x4B,0x42,0x44,0x5F,0x08,0x5F,0x48,0x49, /* 00000300 "KBD_._HI" */
0x44,0x0C,0x41,0xD0,0x03,0x03,0x14,0x09, /* 00000308 "D.A....." */
0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 00000310 "_STA...." */
0x14,0x29,0x5F,0x43,0x52,0x53,0x00,0x08, /* 00000318 ".)_CRS.." */
0x54,0x4D,0x50,0x5F,0x11,0x18,0x0A,0x15, /* 00000320 "TMP_...." */
0x47,0x01,0x60,0x00,0x60,0x00,0x01,0x01, /* 00000328 "G.`.`..." */
0x47,0x01,0x64,0x00,0x64,0x00,0x01,0x01, /* 00000330 "G.d.d..." */
0x22,0x02,0x00,0x79,0x00,0xA4,0x54,0x4D, /* 00000338 ""..y..TM" */
0x50,0x5F,0x5B,0x82,0x33,0x4D,0x4F,0x55, /* 00000340 "P_[.3MOU" */
0x5F,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000348 "_._HID.A" */
0xD0,0x0F,0x13,0x14,0x09,0x5F,0x53,0x54, /* 00000350 "....._ST" */
0x41,0x00,0xA4,0x0A,0x0F,0x14,0x19,0x5F, /* 00000358 "A......_" */
0x43,0x52,0x53,0x00,0x08,0x54,0x4D,0x50, /* 00000360 "CRS..TMP" */
0x5F,0x11,0x08,0x0A,0x05,0x22,0x00,0x10, /* 00000368 "_....".." */
0x79,0x00,0xA4,0x54,0x4D,0x50,0x5F,0x5B, /* 00000370 "y..TMP_[" */
0x82,0x47,0x04,0x46,0x44,0x43,0x30,0x08, /* 00000378 ".G.FDC0." */
0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x07, /* 00000380 "_HID.A.." */
0x00,0x14,0x09,0x5F,0x53,0x54,0x41,0x00, /* 00000388 "..._STA." */
0xA4,0x0A,0x0F,0x14,0x2C,0x5F,0x43,0x52, /* 00000390 "....,_CR" */
0x53,0x00,0x08,0x42,0x55,0x46,0x30,0x11, /* 00000398 "S..BUF0." */
0x1B,0x0A,0x18,0x47,0x01,0xF2,0x03,0xF2, /* 000003A0 "...G...." */
0x03,0x00,0x04,0x47,0x01,0xF7,0x03,0xF7, /* 000003A8 "...G...." */
0x03,0x00,0x01,0x22,0x40,0x00,0x2A,0x04, /* 000003B0 "..."@.*." */
0x00,0x79,0x00,0xA4,0x42,0x55,0x46,0x30, /* 000003B8 ".y..BUF0" */
0x5B,0x82,0x4B,0x05,0x4C,0x50,0x54,0x5F, /* 000003C0 "[.K.LPT_" */
0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 000003C8 "._HID.A." */
0x04,0x00,0x14,0x28,0x5F,0x53,0x54,0x41, /* 000003D0 "...(_STA" */
0x00,0x70,0x5E,0x5E,0x5E,0x2E,0x50,0x58, /* 000003D8 ".p^^^.PX" */
0x31,0x33,0x44,0x52,0x53,0x41,0x60,0x7B, /* 000003E0 "13DRSA`{" */
0x60,0x0C,0x00,0x00,0x00,0x80,0x60,0xA0, /* 000003E8 "`.....`." */
0x06,0x93,0x60,0x00,0xA4,0x00,0xA1,0x04, /* 000003F0 "..`....." */
0xA4,0x0A,0x0F,0x14,0x21,0x5F,0x43,0x52, /* 000003F8 "....!_CR" */
0x53,0x00,0x08,0x42,0x55,0x46,0x30,0x11, /* 00000400 "S..BUF0." */
0x10,0x0A,0x0D,0x47,0x01,0x78,0x03,0x78, /* 00000408 "...G.x.x" */
0x03,0x08,0x08,0x22,0x80,0x00,0x79,0x00, /* 00000410 "..."..y." */
0xA4,0x42,0x55,0x46,0x30,0x5B,0x82,0x41, /* 00000418 ".BUF0[.A" */
0x06,0x43,0x4F,0x4D,0x31,0x08,0x5F,0x48, /* 00000420 ".COM1._H" */
0x49,0x44,0x0C,0x41,0xD0,0x05,0x01,0x08, /* 00000428 "ID.A...." */
0x5F,0x55,0x49,0x44,0x01,0x14,0x28,0x5F, /* 00000430 "_UID..(_" */
0x53,0x54,0x41,0x00,0x70,0x5E,0x5E,0x5E, /* 00000438 "STA.p^^^" */
0x2E,0x50,0x58,0x31,0x33,0x44,0x52,0x53, /* 00000440 ".PX13DRS" */
0x43,0x60,0x7B,0x60,0x0C,0x00,0x00,0x00, /* 00000448 "C`{`...." */
0x08,0x60,0xA0,0x06,0x93,0x60,0x00,0xA4, /* 00000450 ".`...`.." */
0x00,0xA1,0x04,0xA4,0x0A,0x0F,0x14,0x21, /* 00000458 ".......!" */
0x5F,0x43,0x52,0x53,0x00,0x08,0x42,0x55, /* 00000460 "_CRS..BU" */
0x46,0x30,0x11,0x10,0x0A,0x0D,0x47,0x01, /* 00000468 "F0....G." */
0xF8,0x03,0xF8,0x03,0x00,0x08,0x22,0x10, /* 00000470 "......"." */
0x00,0x79,0x00,0xA4,0x42,0x55,0x46,0x30, /* 00000478 ".y..BUF0" */
0x5B,0x82,0x42,0x06,0x43,0x4F,0x4D,0x32, /* 00000480 "[.B.COM2" */
0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000488 "._HID.A." */
0x05,0x01,0x08,0x5F,0x55,0x49,0x44,0x0A, /* 00000490 "..._UID." */
0x02,0x14,0x28,0x5F,0x53,0x54,0x41,0x00, /* 00000498 "..(_STA." */
0x70,0x5E,0x5E,0x5E,0x2E,0x50,0x58,0x31, /* 000004A0 "p^^^.PX1" */
0x33,0x44,0x52,0x53,0x43,0x60,0x7B,0x60, /* 000004A8 "3DRSC`{`" */
0x0C,0x00,0x00,0x00,0x80,0x60,0xA0,0x06, /* 000004B0 ".....`.." */
0x93,0x60,0x00,0xA4,0x00,0xA1,0x04,0xA4, /* 000004B8 ".`......" */
0x0A,0x0F,0x14,0x21,0x5F,0x43,0x52,0x53, /* 000004C0 "...!_CRS" */
0x00,0x08,0x42,0x55,0x46,0x30,0x11,0x10, /* 000004C8 "..BUF0.." */
0x0A,0x0D,0x47,0x01,0xF8,0x02,0xF8,0x02, /* 000004D0 "..G....." */
0x00,0x08,0x22,0x08,0x00,0x79,0x00,0xA4, /* 000004D8 ".."..y.." */
0x42,0x55,0x46,0x30,0x5B,0x82,0x40,0x05, /* 000004E0 "BUF0[.@." */
0x50,0x58,0x31,0x33,0x08,0x5F,0x41,0x44, /* 000004E8 "PX13._AD" */
0x52,0x0C,0x03,0x00,0x01,0x00,0x5B,0x80, /* 000004F0 "R.....[." */
0x50,0x31,0x33,0x43,0x02,0x0A,0x5C,0x0A, /* 000004F8 "P13C..\." */
0x24,0x5B,0x81,0x33,0x50,0x31,0x33,0x43, /* 00000500 "$[.3P13C" */
0x03,0x44,0x52,0x53,0x41,0x20,0x44,0x52, /* 00000508 ".DRSA DR" */
0x53,0x42,0x20,0x44,0x52,0x53,0x43,0x20, /* 00000510 "SB DRSC " */
0x44,0x52,0x53,0x45,0x20,0x44,0x52,0x53, /* 00000518 "DRSE DRS" */
0x46,0x20,0x44,0x52,0x53,0x47,0x20,0x44, /* 00000520 "F DRSG D" */
0x52,0x53,0x48,0x20,0x44,0x52,0x53,0x49, /* 00000528 "RSH DRSI" */
0x20,0x44,0x52,0x53,0x4A,0x20,0x10,0x4F, /* 00000530 " DRSJ .O" */
0x2E,0x5F,0x53,0x42,0x5F,0x5B,0x81,0x24, /* 00000538 "._SB_[.$" */
0x2F,0x03,0x50,0x43,0x49,0x30,0x49,0x53, /* 00000540 "/.PCI0IS" */
0x41,0x5F,0x50,0x34,0x30,0x43,0x01,0x50, /* 00000548 "A_P40C.P" */
0x52,0x51,0x30,0x08,0x50,0x52,0x51,0x31, /* 00000550 "RQ0.PRQ1" */
0x08,0x50,0x52,0x51,0x32,0x08,0x50,0x52, /* 00000558 ".PRQ2.PR" */
0x51,0x33,0x08,0x5B,0x82,0x4E,0x0A,0x4C, /* 00000560 "Q3.[.N.L" */
0x4E,0x4B,0x41,0x08,0x5F,0x48,0x49,0x44, /* 00000568 "NKA._HID" */
0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000570 ".A...._U" */
0x49,0x44,0x01,0x08,0x5F,0x50,0x52,0x53, /* 00000578 "ID.._PRS" */
0x11,0x09,0x0A,0x06,0x23,0xF8,0x1E,0x18, /* 00000580 "....#..." */
0x79,0x00,0x14,0x1A,0x5F,0x53,0x54,0x41, /* 00000588 "y..._STA" */
0x00,0x70,0x0A,0x0B,0x60,0xA0,0x0D,0x7B, /* 00000590 ".p..`..{" */
0x0A,0x80,0x50,0x52,0x51,0x30,0x61,0x70, /* 00000598 "..PRQ0ap" */
0x0A,0x09,0x60,0xA4,0x60,0x14,0x11,0x5F, /* 000005A0 "..`.`.._" */
0x44,0x49,0x53,0x00,0x7D,0x50,0x52,0x51, /* 000005A8 "DIS.}PRQ" */
0x30,0x0A,0x80,0x50,0x52,0x51,0x30,0x14, /* 000005B0 "0..PRQ0." */
0x3F,0x5F,0x43,0x52,0x53,0x00,0x08,0x50, /* 000005B8 "?_CRS..P" */
0x52,0x52,0x30,0x11,0x09,0x0A,0x06,0x23, /* 000005C0 "RR0....#" */
0x02,0x00,0x18,0x79,0x00,0x8B,0x50,0x52, /* 000005C8 "...y..PR" */
0x52,0x30,0x01,0x54,0x4D,0x50,0x5F,0x70, /* 000005D0 "R0.TMP_p" */
0x50,0x52,0x51,0x30,0x60,0xA0,0x0C,0x95, /* 000005D8 "PRQ0`..." */
0x60,0x0A,0x80,0x79,0x01,0x60,0x54,0x4D, /* 000005E0 "`..y.`TM" */
0x50,0x5F,0xA1,0x07,0x70,0x00,0x54,0x4D, /* 000005E8 "P_..p.TM" */
0x50,0x5F,0xA4,0x50,0x52,0x52,0x30,0x14, /* 000005F0 "P_.PRR0." */
0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68, /* 000005F8 "._SRS..h" */
0x01,0x54,0x4D,0x50,0x5F,0x82,0x54,0x4D, /* 00000600 ".TMP_.TM" */
0x50,0x5F,0x60,0x76,0x60,0x70,0x60,0x50, /* 00000608 "P_`v`p`P" */
0x52,0x51,0x30,0x5B,0x82,0x4F,0x0A,0x4C, /* 00000610 "RQ0[.O.L" */
0x4E,0x4B,0x42,0x08,0x5F,0x48,0x49,0x44, /* 00000618 "NKB._HID" */
0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000620 ".A...._U" */
0x49,0x44,0x0A,0x02,0x08,0x5F,0x50,0x52, /* 00000628 "ID..._PR" */
0x53,0x11,0x09,0x0A,0x06,0x23,0xF8,0x1E, /* 00000630 "S....#.." */
0x18,0x79,0x00,0x14,0x1A,0x5F,0x53,0x54, /* 00000638 ".y..._ST" */
0x41,0x00,0x70,0x0A,0x0B,0x60,0xA0,0x0D, /* 00000640 "A.p..`.." */
0x7B,0x0A,0x80,0x50,0x52,0x51,0x31,0x61, /* 00000648 "{..PRQ1a" */
0x70,0x0A,0x09,0x60,0xA4,0x60,0x14,0x11, /* 00000650 "p..`.`.." */
0x5F,0x44,0x49,0x53,0x00,0x7D,0x50,0x52, /* 00000658 "_DIS.}PR" */
0x51,0x31,0x0A,0x80,0x50,0x52,0x51,0x31, /* 00000660 "Q1..PRQ1" */
0x14,0x3F,0x5F,0x43,0x52,0x53,0x00,0x08, /* 00000668 ".?_CRS.." */
0x50,0x52,0x52,0x30,0x11,0x09,0x0A,0x06, /* 00000670 "PRR0...." */
0x23,0x02,0x00,0x18,0x79,0x00,0x8B,0x50, /* 00000678 "#...y..P" */
0x52,0x52,0x30,0x01,0x54,0x4D,0x50,0x5F, /* 00000680 "RR0.TMP_" */
0x70,0x50,0x52,0x51,0x31,0x60,0xA0,0x0C, /* 00000688 "pPRQ1`.." */
0x95,0x60,0x0A,0x80,0x79,0x01,0x60,0x54, /* 00000690 ".`..y.`T" */
0x4D,0x50,0x5F,0xA1,0x07,0x70,0x00,0x54, /* 00000698 "MP_..p.T" */
0x4D,0x50,0x5F,0xA4,0x50,0x52,0x52,0x30, /* 000006A0 "MP_.PRR0" */
0x14,0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B, /* 000006A8 ".._SRS.." */
0x68,0x01,0x54,0x4D,0x50,0x5F,0x82,0x54, /* 000006B0 "h.TMP_.T" */
0x4D,0x50,0x5F,0x60,0x76,0x60,0x70,0x60, /* 000006B8 "MP_`v`p`" */
0x50,0x52,0x51,0x31,0x5B,0x82,0x4F,0x0A, /* 000006C0 "PRQ1[.O." */
0x4C,0x4E,0x4B,0x43,0x08,0x5F,0x48,0x49, /* 000006C8 "LNKC._HI" */
0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F, /* 000006D0 "D.A...._" */
0x55,0x49,0x44,0x0A,0x03,0x08,0x5F,0x50, /* 000006D8 "UID..._P" */
0x52,0x53,0x11,0x09,0x0A,0x06,0x23,0xF8, /* 000006E0 "RS....#." */
0x1E,0x18,0x79,0x00,0x14,0x1A,0x5F,0x53, /* 000006E8 "..y..._S" */
0x54,0x41,0x00,0x70,0x0A,0x0B,0x60,0xA0, /* 000006F0 "TA.p..`." */
0x0D,0x7B,0x0A,0x80,0x50,0x52,0x51,0x32, /* 000006F8 ".{..PRQ2" */
0x61,0x70,0x0A,0x09,0x60,0xA4,0x60,0x14, /* 00000700 "ap..`.`." */
0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50, /* 00000708 "._DIS.}P" */
0x52,0x51,0x32,0x0A,0x80,0x50,0x52,0x51, /* 00000710 "RQ2..PRQ" */
0x32,0x14,0x3F,0x5F,0x43,0x52,0x53,0x00, /* 00000718 "2.?_CRS." */
0x08,0x50,0x52,0x52,0x30,0x11,0x09,0x0A, /* 00000720 ".PRR0..." */
0x06,0x23,0x02,0x00,0x18,0x79,0x00,0x8B, /* 00000728 ".#...y.." */
0x50,0x52,0x52,0x30,0x01,0x54,0x4D,0x50, /* 00000730 "PRR0.TMP" */
0x5F,0x70,0x50,0x52,0x51,0x32,0x60,0xA0, /* 00000738 "_pPRQ2`." */
0x0C,0x95,0x60,0x0A,0x80,0x79,0x01,0x60, /* 00000740 "..`..y.`" */
0x54,0x4D,0x50,0x5F,0xA1,0x07,0x70,0x00, /* 00000748 "TMP_..p." */
0x54,0x4D,0x50,0x5F,0xA4,0x50,0x52,0x52, /* 00000750 "TMP_.PRR" */
0x30,0x14,0x1B,0x5F,0x53,0x52,0x53,0x01, /* 00000758 "0.._SRS." */
0x8B,0x68,0x01,0x54,0x4D,0x50,0x5F,0x82, /* 00000760 ".h.TMP_." */
0x54,0x4D,0x50,0x5F,0x60,0x76,0x60,0x70, /* 00000768 "TMP_`v`p" */
0x60,0x50,0x52,0x51,0x32,0x5B,0x82,0x4F, /* 00000770 "`PRQ2[.O" */
0x0A,0x4C,0x4E,0x4B,0x44,0x08,0x5F,0x48, /* 00000778 ".LNKD._H" */
0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08, /* 00000780 "ID.A...." */
0x5F,0x55,0x49,0x44,0x0A,0x04,0x08,0x5F, /* 00000788 "_UID..._" */
0x50,0x52,0x53,0x11,0x09,0x0A,0x06,0x23, /* 00000790 "PRS....#" */
0xF8,0x1E,0x18,0x79,0x00,0x14,0x1A,0x5F, /* 00000798 "...y..._" */
0x53,0x54,0x41,0x00,0x70,0x0A,0x0B,0x60, /* 000007A0 "STA.p..`" */
0xA0,0x0D,0x7B,0x0A,0x80,0x50,0x52,0x51, /* 000007A8 "..{..PRQ" */
0x33,0x61,0x70,0x0A,0x09,0x60,0xA4,0x60, /* 000007B0 "3ap..`.`" */
0x14,0x11,0x5F,0x44,0x49,0x53,0x00,0x7D, /* 000007B8 ".._DIS.}" */
0x50,0x52,0x51,0x33,0x0A,0x80,0x50,0x52, /* 000007C0 "PRQ3..PR" */
0x51,0x33,0x14,0x3F,0x5F,0x43,0x52,0x53, /* 000007C8 "Q3.?_CRS" */
0x00,0x08,0x50,0x52,0x52,0x30,0x11,0x09, /* 000007D0 "..PRR0.." */
0x0A,0x06,0x23,0x02,0x00,0x18,0x79,0x00, /* 000007D8 "..#...y." */
0x8B,0x50,0x52,0x52,0x30,0x01,0x54,0x4D, /* 000007E0 ".PRR0.TM" */
0x50,0x5F,0x70,0x50,0x52,0x51,0x33,0x60, /* 000007E8 "P_pPRQ3`" */
0xA0,0x0C,0x95,0x60,0x0A,0x80,0x79,0x01, /* 000007F0 "...`..y." */
0x60,0x54,0x4D,0x50,0x5F,0xA1,0x07,0x70, /* 000007F8 "`TMP_..p" */
0x00,0x54,0x4D,0x50,0x5F,0xA4,0x50,0x52, /* 00000800 ".TMP_.PR" */
0x52,0x30,0x14,0x1B,0x5F,0x53,0x52,0x53, /* 00000808 "R0.._SRS" */
0x01,0x8B,0x68,0x01,0x54,0x4D,0x50,0x5F, /* 00000810 "..h.TMP_" */
0x82,0x54,0x4D,0x50,0x5F,0x60,0x76,0x60, /* 00000818 ".TMP_`v`" */
0x70,0x60,0x50,0x52,0x51,0x33,0x08,0x5F, /* 00000820 "p`PRQ3._" */
0x53,0x35,0x5F,0x12,0x06,0x04,0x00,0x00, /* 00000828 "S5_....." */
0x00,0x00,
};
+282 -374
View File
@@ -23,18 +23,27 @@
/* i82731AB (PIIX4) compatible power management function */
#define PM_FREQ 3579545
/* XXX: make them variable */
#define PM_IO_BASE 0xb000
#define SMI_CMD_IO_ADDR 0xb040
#define ACPI_DBG_IO_ADDR 0xb044
#define SMB_IO_BASE 0xb100
typedef struct PIIX4PMState {
PCIDevice dev;
uint16_t pmsts;
uint16_t pmen;
uint16_t pmcntrl;
uint8_t apmc;
uint8_t apms;
QEMUTimer *tmr_timer;
int64_t tmr_overflow_time;
SMBusDevice *smb_dev[128];
uint8_t smb_stat;
uint8_t smb_ctl;
uint8_t smb_cmd;
uint8_t smb_addr;
uint8_t smb_data0;
uint8_t smb_data1;
uint8_t smb_data[32];
uint8_t smb_index;
} PIIX4PMState;
#define RTC_EN (1 << 10)
@@ -46,8 +55,15 @@ typedef struct PIIX4PMState {
#define SUS_EN (1 << 13)
/* Note: only used for ACPI bios init. Could be deleted when ACPI init
is integrated in Bochs BIOS */
#define SMBHSTSTS 0x00
#define SMBHSTCNT 0x02
#define SMBHSTCMD 0x03
#define SMBHSTADD 0x04
#define SMBHSTDAT0 0x05
#define SMBHSTDAT1 0x06
#define SMBBLKDAT 0x07
/* Note: only used for piix4_smbus_register_device */
static PIIX4PMState *piix4_pm_state;
static uint32_t get_pmtmr(PIIX4PMState *s)
@@ -195,22 +211,40 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
return val;
}
static void smi_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
static void pm_smi_writeb(void *opaque, uint32_t addr, uint32_t val)
{
PIIX4PMState *s = opaque;
addr &= 1;
#ifdef DEBUG
printf("SMI cmd val=0x%02x\n", val);
printf("pm_smi_writeb addr=0x%x val=0x%02x\n", addr, val);
#endif
switch(val) {
case 0xf0: /* ACPI disable */
s->pmcntrl &= ~SCI_EN;
break;
case 0xf1: /* ACPI enable */
s->pmcntrl |= SCI_EN;
break;
if (addr == 0) {
s->apmc = val;
if (s->dev.config[0x5b] & (1 << 1)) {
cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
}
} else {
s->apms = val;
}
}
static uint32_t pm_smi_readb(void *opaque, uint32_t addr)
{
PIIX4PMState *s = opaque;
uint32_t val;
addr &= 1;
if (addr == 0) {
val = s->apmc;
} else {
val = s->apms;
}
#ifdef DEBUG
printf("pm_smi_readb addr=0x%x val=0x%02x\n", addr, val);
#endif
return val;
}
static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
{
#if defined(DEBUG)
@@ -218,17 +252,232 @@ static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
#endif
}
/* XXX: we still add it to the PIIX3 and we count on the fact that
OSes are smart enough to accept this strange configuration */
static void smb_transaction(PIIX4PMState *s)
{
uint8_t prot = (s->smb_ctl >> 2) & 0x07;
uint8_t read = s->smb_addr & 0x01;
uint8_t cmd = s->smb_cmd;
uint8_t addr = s->smb_addr >> 1;
SMBusDevice *dev = s->smb_dev[addr];
#ifdef DEBUG
printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
#endif
if (!dev) goto error;
switch(prot) {
case 0x0:
if (!dev->quick_cmd) goto error;
(*dev->quick_cmd)(dev, read);
break;
case 0x1:
if (read) {
if (!dev->receive_byte) goto error;
s->smb_data0 = (*dev->receive_byte)(dev);
}
else {
if (!dev->send_byte) goto error;
(*dev->send_byte)(dev, cmd);
}
break;
case 0x2:
if (read) {
if (!dev->read_byte) goto error;
s->smb_data0 = (*dev->read_byte)(dev, cmd);
}
else {
if (!dev->write_byte) goto error;
(*dev->write_byte)(dev, cmd, s->smb_data0);
}
break;
case 0x3:
if (read) {
uint16_t val;
if (!dev->read_word) goto error;
val = (*dev->read_word)(dev, cmd);
s->smb_data0 = val;
s->smb_data1 = val >> 8;
}
else {
if (!dev->write_word) goto error;
(*dev->write_word)(dev, cmd, (s->smb_data1 << 8) | s->smb_data0);
}
break;
case 0x5:
if (read) {
if (!dev->read_block) goto error;
s->smb_data0 = (*dev->read_block)(dev, cmd, s->smb_data);
}
else {
if (!dev->write_block) goto error;
(*dev->write_block)(dev, cmd, s->smb_data0, s->smb_data);
}
break;
default:
goto error;
}
return;
error:
s->smb_stat |= 0x04;
}
static void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
{
PIIX4PMState *s = opaque;
addr &= 0x3f;
#ifdef DEBUG
printf("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
#endif
switch(addr) {
case SMBHSTSTS:
s->smb_stat = 0;
s->smb_index = 0;
break;
case SMBHSTCNT:
s->smb_ctl = val;
if (val & 0x40)
smb_transaction(s);
break;
case SMBHSTCMD:
s->smb_cmd = val;
break;
case SMBHSTADD:
s->smb_addr = val;
break;
case SMBHSTDAT0:
s->smb_data0 = val;
break;
case SMBHSTDAT1:
s->smb_data1 = val;
break;
case SMBBLKDAT:
s->smb_data[s->smb_index++] = val;
if (s->smb_index > 31)
s->smb_index = 0;
break;
default:
break;
}
}
static uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
{
PIIX4PMState *s = opaque;
uint32_t val;
addr &= 0x3f;
switch(addr) {
case SMBHSTSTS:
val = s->smb_stat;
break;
case SMBHSTCNT:
s->smb_index = 0;
val = s->smb_ctl & 0x1f;
break;
case SMBHSTCMD:
val = s->smb_cmd;
break;
case SMBHSTADD:
val = s->smb_addr;
break;
case SMBHSTDAT0:
val = s->smb_data0;
break;
case SMBHSTDAT1:
val = s->smb_data1;
break;
case SMBBLKDAT:
val = s->smb_data[s->smb_index++];
if (s->smb_index > 31)
s->smb_index = 0;
break;
default:
val = 0;
break;
}
#ifdef DEBUG
printf("SMB readb port=0x%04x val=0x%02x\n", addr, val);
#endif
return val;
}
static void pm_io_space_update(PIIX4PMState *s)
{
uint32_t pm_io_base;
if (s->dev.config[0x80] & 1) {
pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
pm_io_base &= 0xfffe;
/* XXX: need to improve memory and ioport allocation */
#if defined(DEBUG)
printf("PM: mapping to 0x%x\n", pm_io_base);
#endif
register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
}
}
static void pm_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
pci_default_write_config(d, address, val, len);
if (address == 0x80)
pm_io_space_update((PIIX4PMState *)d);
}
static void pm_save(QEMUFile* f,void *opaque)
{
PIIX4PMState *s = opaque;
pci_device_save(&s->dev, f);
qemu_put_be16s(f, &s->pmsts);
qemu_put_be16s(f, &s->pmen);
qemu_put_be16s(f, &s->pmcntrl);
qemu_put_8s(f, &s->apmc);
qemu_put_8s(f, &s->apms);
qemu_put_timer(f, s->tmr_timer);
qemu_put_be64s(f, &s->tmr_overflow_time);
}
static int pm_load(QEMUFile* f,void* opaque,int version_id)
{
PIIX4PMState *s = opaque;
int ret;
if (version_id > 1)
return -EINVAL;
ret = pci_device_load(&s->dev, f);
if (ret < 0)
return ret;
qemu_get_be16s(f, &s->pmsts);
qemu_get_be16s(f, &s->pmen);
qemu_get_be16s(f, &s->pmcntrl);
qemu_get_8s(f, &s->apmc);
qemu_get_8s(f, &s->apms);
qemu_get_timer(f, s->tmr_timer);
qemu_get_be64s(f, &s->tmr_overflow_time);
pm_io_space_update(s);
return 0;
}
void piix4_pm_init(PCIBus *bus, int devfn)
{
PIIX4PMState *s;
uint8_t *pci_conf;
uint32_t pm_io_base;
uint32_t pm_io_base, smb_io_base;
s = (PIIX4PMState *)pci_register_device(bus,
"PM", sizeof(PIIX4PMState),
devfn, NULL, NULL);
devfn, NULL, pm_write_config);
pci_conf = s->dev.config;
pci_conf[0x00] = 0x86;
pci_conf[0x01] = 0x80;
@@ -241,15 +490,11 @@ void piix4_pm_init(PCIBus *bus, int devfn)
pci_conf[0x0e] = 0x00; // header_type
pci_conf[0x3d] = 0x01; // interrupt pin 1
pm_io_base = PM_IO_BASE;
pci_conf[0x40] = pm_io_base | 1;
pci_conf[0x41] = pm_io_base >> 8;
register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
pci_conf[0x40] = 0x01; /* PM io base read only bit */
register_ioport_write(SMI_CMD_IO_ADDR, 1, 1, smi_cmd_writeb, s);
register_ioport_write(0xb2, 2, 1, pm_smi_writeb, s);
register_ioport_read(0xb2, 2, 1, pm_smi_readb, s);
register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
/* XXX: which specification is used ? The i82731AB has different
@@ -259,357 +504,20 @@ void piix4_pm_init(PCIBus *bus, int devfn)
pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
(serial_hds[1] != NULL ? 0x90 : 0);
smb_io_base = SMB_IO_BASE;
pci_conf[0x90] = smb_io_base | 1;
pci_conf[0x91] = smb_io_base >> 8;
pci_conf[0xd2] = 0x09;
register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, s);
register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, s);
s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s);
piix4_pm_state = s;
}
/* ACPI tables */
/* XXX: move them in the Bochs BIOS ? */
/*************************************************/
/* Table structure from Linux kernel (the ACPI tables are under the
BSD license) */
#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\
uint32_t length; /* Length of table, in bytes, including header */\
uint8_t revision; /* ACPI Specification minor version # */\
uint8_t checksum; /* To make sum of entire table == 0 */\
uint8_t oem_id [6]; /* OEM identification */\
uint8_t oem_table_id [8]; /* OEM table identification */\
uint32_t oem_revision; /* OEM revision number */\
uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\
uint32_t asl_compiler_revision; /* ASL compiler revision number */
struct acpi_table_header /* ACPI common table header */
void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr)
{
ACPI_TABLE_HEADER_DEF
};
struct rsdp_descriptor /* Root System Descriptor Pointer */
{
uint8_t signature [8]; /* ACPI signature, contains "RSD PTR " */
uint8_t checksum; /* To make sum of struct == 0 */
uint8_t oem_id [6]; /* OEM identification */
uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */
uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */
uint32_t length; /* XSDT Length in bytes including hdr */
uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */
uint8_t extended_checksum; /* Checksum of entire table */
uint8_t reserved [3]; /* Reserved field must be 0 */
};
/*
* ACPI 1.0 Root System Description Table (RSDT)
*/
struct rsdt_descriptor_rev1
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint32_t table_offset_entry [2]; /* Array of pointers to other */
/* ACPI tables */
};
/*
* ACPI 1.0 Firmware ACPI Control Structure (FACS)
*/
struct facs_descriptor_rev1
{
uint8_t signature[4]; /* ACPI Signature */
uint32_t length; /* Length of structure, in bytes */
uint32_t hardware_signature; /* Hardware configuration signature */
uint32_t firmware_waking_vector; /* ACPI OS waking vector */
uint32_t global_lock; /* Global Lock */
uint32_t S4bios_f : 1; /* Indicates if S4BIOS support is present */
uint32_t reserved1 : 31; /* Must be 0 */
uint8_t resverved3 [40]; /* Reserved - must be zero */
};
/*
* ACPI 1.0 Fixed ACPI Description Table (FADT)
*/
struct fadt_descriptor_rev1
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint32_t firmware_ctrl; /* Physical address of FACS */
uint32_t dsdt; /* Physical address of DSDT */
uint8_t model; /* System Interrupt Model */
uint8_t reserved1; /* Reserved */
uint16_t sci_int; /* System vector of SCI interrupt */
uint32_t smi_cmd; /* Port address of SMI command port */
uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */
uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */
uint8_t S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
uint8_t reserved2; /* Reserved - must be zero */
uint32_t pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
uint32_t pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
uint32_t gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
uint32_t gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */
uint8_t reserved3; /* Reserved */
uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
uint16_t flush_size; /* Size of area read to flush caches */
uint16_t flush_stride; /* Stride used in flushing caches */
uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */
uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */
uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
uint8_t century; /* Index to century in RTC CMOS RAM */
uint8_t reserved4; /* Reserved */
uint8_t reserved4a; /* Reserved */
uint8_t reserved4b; /* Reserved */
#if 0
uint32_t wb_invd : 1; /* The wbinvd instruction works properly */
uint32_t wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */
uint32_t proc_c1 : 1; /* All processors support C1 state */
uint32_t plvl2_up : 1; /* C2 state works on MP system */
uint32_t pwr_button : 1; /* Power button is handled as a generic feature */
uint32_t sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
uint32_t fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
uint32_t rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
uint32_t tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
uint32_t reserved5 : 23; /* Reserved - must be zero */
#else
uint32_t flags;
#endif
};
/*
* MADT values and structures
*/
/* Values for MADT PCATCompat */
#define DUAL_PIC 0
#define MULTIPLE_APIC 1
/* Master MADT */
struct multiple_apic_table
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint32_t local_apic_address; /* Physical address of local APIC */
#if 0
uint32_t PCATcompat : 1; /* A one indicates system also has dual 8259s */
uint32_t reserved1 : 31;
#else
uint32_t flags;
#endif
};
/* Values for Type in APIC_HEADER_DEF */
#define APIC_PROCESSOR 0
#define APIC_IO 1
#define APIC_XRUPT_OVERRIDE 2
#define APIC_NMI 3
#define APIC_LOCAL_NMI 4
#define APIC_ADDRESS_OVERRIDE 5
#define APIC_IO_SAPIC 6
#define APIC_LOCAL_SAPIC 7
#define APIC_XRUPT_SOURCE 8
#define APIC_RESERVED 9 /* 9 and greater are reserved */
/*
* MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
*/
#define APIC_HEADER_DEF /* Common APIC sub-structure header */\
uint8_t type; \
uint8_t length;
/* Sub-structures for MADT */
struct madt_processor_apic
{
APIC_HEADER_DEF
uint8_t processor_id; /* ACPI processor id */
uint8_t local_apic_id; /* Processor's local APIC id */
#if 0
uint32_t processor_enabled: 1; /* Processor is usable if set */
uint32_t reserved2 : 31; /* Reserved, must be zero */
#else
uint32_t flags;
#endif
};
struct madt_io_apic
{
APIC_HEADER_DEF
uint8_t io_apic_id; /* I/O APIC ID */
uint8_t reserved; /* Reserved - must be zero */
uint32_t address; /* APIC physical address */
uint32_t interrupt; /* Global system interrupt where INTI
* lines start */
};
#include "acpi-dsdt.hex"
static int acpi_checksum(const uint8_t *data, int len)
{
int sum, i;
sum = 0;
for(i = 0; i < len; i++)
sum += data[i];
return (-sum) & 0xff;
}
static void acpi_build_table_header(struct acpi_table_header *h,
char *sig, int len)
{
memcpy(h->signature, sig, 4);
h->length = cpu_to_le32(len);
h->revision = 0;
memcpy(h->oem_id, "QEMU ", 6);
memcpy(h->oem_table_id, "QEMU", 4);
memcpy(h->oem_table_id + 4, sig, 4);
h->oem_revision = cpu_to_le32(1);
memcpy(h->asl_compiler_id, "QEMU", 4);
h->asl_compiler_revision = cpu_to_le32(1);
h->checksum = acpi_checksum((void *)h, len);
}
#define ACPI_TABLES_BASE 0x000e8000
/* base_addr must be a multiple of 4KB */
void acpi_bios_init(void)
{
struct rsdp_descriptor *rsdp;
struct rsdt_descriptor_rev1 *rsdt;
struct fadt_descriptor_rev1 *fadt;
struct facs_descriptor_rev1 *facs;
struct multiple_apic_table *madt;
uint8_t *dsdt;
uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr;
uint32_t pm_io_base, acpi_tables_size, madt_addr, madt_size;
int i;
/* compute PCI I/O addresses */
pm_io_base = (piix4_pm_state->dev.config[0x40] |
(piix4_pm_state->dev.config[0x41] << 8)) & ~0x3f;
base_addr = ACPI_TABLES_BASE;
/* reserve memory space for tables */
addr = base_addr;
rsdp = (void *)(phys_ram_base + addr);
addr += sizeof(*rsdp);
rsdt_addr = addr;
rsdt = (void *)(phys_ram_base + addr);
addr += sizeof(*rsdt);
fadt_addr = addr;
fadt = (void *)(phys_ram_base + addr);
addr += sizeof(*fadt);
/* XXX: FACS should be in RAM */
addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */
facs_addr = addr;
facs = (void *)(phys_ram_base + addr);
addr += sizeof(*facs);
dsdt_addr = addr;
dsdt = (void *)(phys_ram_base + addr);
addr += sizeof(AmlCode);
addr = (addr + 7) & ~7;
madt_addr = addr;
madt_size = sizeof(*madt) +
sizeof(struct madt_processor_apic) * smp_cpus +
sizeof(struct madt_io_apic);
madt = (void *)(phys_ram_base + addr);
addr += madt_size;
acpi_tables_size = addr - base_addr;
cpu_register_physical_memory(base_addr, acpi_tables_size,
base_addr | IO_MEM_ROM);
/* RSDP */
memset(rsdp, 0, sizeof(*rsdp));
memcpy(rsdp->signature, "RSD PTR ", 8);
memcpy(rsdp->oem_id, "QEMU ", 6);
rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
rsdp->checksum = acpi_checksum((void *)rsdp, 20);
/* RSDT */
rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
acpi_build_table_header((struct acpi_table_header *)rsdt,
"RSDT", sizeof(*rsdt));
/* FADT */
memset(fadt, 0, sizeof(*fadt));
fadt->firmware_ctrl = cpu_to_le32(facs_addr);
fadt->dsdt = cpu_to_le32(dsdt_addr);
fadt->model = 1;
fadt->reserved1 = 0;
fadt->sci_int = cpu_to_le16(piix4_pm_state->dev.config[0x3c]);
fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR);
fadt->acpi_enable = 0xf1;
fadt->acpi_disable = 0xf0;
fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base);
fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04);
fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08);
fadt->pm1_evt_len = 4;
fadt->pm1_cnt_len = 2;
fadt->pm_tmr_len = 4;
fadt->plvl2_lat = cpu_to_le16(50);
fadt->plvl3_lat = cpu_to_le16(50);
fadt->plvl3_lat = cpu_to_le16(50);
/* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6));
acpi_build_table_header((struct acpi_table_header *)fadt, "FACP",
sizeof(*fadt));
/* FACS */
memset(facs, 0, sizeof(*facs));
memcpy(facs->signature, "FACS", 4);
facs->length = cpu_to_le32(sizeof(*facs));
/* DSDT */
memcpy(dsdt, AmlCode, sizeof(AmlCode));
/* MADT */
{
struct madt_processor_apic *apic;
struct madt_io_apic *io_apic;
memset(madt, 0, madt_size);
madt->local_apic_address = cpu_to_le32(0xfee00000);
madt->flags = cpu_to_le32(1);
apic = (void *)(madt + 1);
for(i=0;i<smp_cpus;i++) {
apic->type = APIC_PROCESSOR;
apic->length = sizeof(*apic);
apic->processor_id = i;
apic->local_apic_id = i;
apic->flags = cpu_to_le32(1);
apic++;
}
io_apic = (void *)apic;
io_apic->type = APIC_IO;
io_apic->length = sizeof(*io_apic);
io_apic->io_apic_id = smp_cpus;
io_apic->address = cpu_to_le32(0xfec00000);
io_apic->interrupt = cpu_to_le32(0);
acpi_build_table_header((struct acpi_table_header *)madt,
"APIC", madt_size);
}
piix4_pm_state->smb_dev[addr] = dev;
}
+1 -1
View File
@@ -406,5 +406,5 @@ void adb_mouse_init(ADBBusState *bus)
d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
adb_mouse_reset, s);
adb_mouse_reset(d);
qemu_add_mouse_event_handler(adb_mouse_event, d, 0);
qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
}
+34 -7
View File
@@ -21,6 +21,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* XXX This file and most of its contests are somewhat misnamed. The
Ultrasparc PCI host is called the PCI Bus Module (PBM). The APB is
the secondary PCI bridge. */
#include "vl.h"
typedef target_phys_addr_t pci_addr_t;
#include "pci_host.h"
@@ -179,10 +184,26 @@ static CPUReadMemoryFunc *pci_apb_ioread[] = {
&pci_apb_ioreadl,
};
/* ??? This is probably wrong. */
static void pci_apb_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
/* The APB host has an IRQ line for each IRQ line of each slot. */
static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
{
pic_set_irq_new(pic, d->config[PCI_INTERRUPT_LINE], level);
return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
}
static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
{
int bus_offset;
if (pci_dev->devfn & 1)
bus_offset = 16;
else
bus_offset = 0;
return bus_offset + irq_num;
}
static void pci_apb_set_irq(void *pic, int irq_num, int level)
{
/* PCI IRQ map onto the first 32 INO. */
pic_set_irq_new(pic, irq_num, level);
}
PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
@@ -191,10 +212,12 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
APBState *s;
PCIDevice *d;
int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
PCIDevice *apb;
PCIBus *secondary;
s = qemu_mallocz(sizeof(APBState));
/* Ultrasparc APB main bus */
s->bus = pci_register_bus(pci_apb_set_irq, pic, 0);
/* Ultrasparc PBM main bus */
s->bus = pci_register_bus(pci_apb_set_irq, pci_pbm_map_irq, pic, 0, 32);
pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
pci_apb_config_write, s);
@@ -211,7 +234,7 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
cpu_register_physical_memory(mem_base, 0x10000000, pci_mem_data); // XXX size should be 4G-prom
d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice),
-1, NULL, NULL);
0, NULL, NULL);
d->config[0x00] = 0x8e; // vendor_id : Sun
d->config[0x01] = 0x10;
d->config[0x02] = 0x00; // device_id
@@ -226,7 +249,11 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
d->config[0x0B] = 0x06; // class_base = PCI_bridge
d->config[0x0D] = 0x10; // latency_timer
d->config[0x0E] = 0x00; // header_type
return s->bus;
/* APB secondary busses */
secondary = pci_bridge_init(s->bus, 8, 0x108e5000, pci_apb_map_irq, "Advanced PCI Bus secondary bridge 1");
pci_bridge_init(s->bus, 9, 0x108e5000, pci_apb_map_irq, "Advanced PCI Bus secondary bridge 2");
return secondary;
}
+10 -6
View File
@@ -382,8 +382,6 @@ static void apic_init_ipi(APICState *s)
{
int i;
for(i = 0; i < APIC_LVT_NB; i++)
s->lvt[i] = 1 << 16; /* mask LVT */
s->tpr = 0;
s->spurious_vec = 0xff;
s->log_dest = 0;
@@ -391,7 +389,8 @@ static void apic_init_ipi(APICState *s)
memset(s->isr, 0, sizeof(s->isr));
memset(s->tmr, 0, sizeof(s->tmr));
memset(s->irr, 0, sizeof(s->irr));
memset(s->lvt, 0, sizeof(s->lvt));
for(i = 0; i < APIC_LVT_NB; i++)
s->lvt[i] = 1 << 16; /* mask LVT */
s->esr = 0;
memset(s->icr, 0, sizeof(s->icr));
s->divide_conf = 0;
@@ -477,9 +476,9 @@ int apic_get_interrupt(CPUState *env)
intno = get_highest_priority_int(s->irr);
if (intno < 0)
return -1;
reset_bit(s->irr, intno);
if (s->tpr && intno <= s->tpr)
return s->spurious_vec & 0xff;
reset_bit(s->irr, intno);
set_bit(s->isr, intno);
apic_update_irq(s);
return intno;
@@ -745,6 +744,8 @@ static void apic_save(QEMUFile *f, void *opaque)
qemu_put_be32s(f, &s->initial_count);
qemu_put_be64s(f, &s->initial_count_load_time);
qemu_put_be64s(f, &s->next_time);
qemu_put_timer(f, s->timer);
}
static int apic_load(QEMUFile *f, void *opaque, int version_id)
@@ -752,7 +753,7 @@ static int apic_load(QEMUFile *f, void *opaque, int version_id)
APICState *s = opaque;
int i;
if (version_id != 1)
if (version_id > 2)
return -EINVAL;
/* XXX: what if the base changes? (registered memory regions) */
@@ -779,6 +780,9 @@ static int apic_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_be32s(f, &s->initial_count);
qemu_get_be64s(f, &s->initial_count_load_time);
qemu_get_be64s(f, &s->next_time);
if (version_id >= 2)
qemu_get_timer(f, s->timer);
return 0;
}
@@ -827,7 +831,7 @@ int apic_init(CPUState *env)
}
s->timer = qemu_new_timer(vm_clock, apic_timer, s);
register_savevm("apic", 0, 1, apic_save, apic_load, s);
register_savevm("apic", 0, 2, apic_save, apic_load, s);
qemu_register_reset(apic_reset, s);
local_apics[s->id] = s;
+32 -22
View File
@@ -64,42 +64,52 @@ static void set_kernel_args(uint32_t ram_size, int initrd_size,
stl_raw(p++, 0);
}
void arm_load_kernel(int ram_size, const char *kernel_filename,
void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
const char *kernel_cmdline, const char *initrd_filename,
int board_id)
{
int kernel_size;
int initrd_size;
int n;
uint64_t entry;
/* Load the kernel. */
if (!kernel_filename) {
fprintf(stderr, "Kernel image must be specified\n");
exit(1);
}
kernel_size = load_image(kernel_filename,
phys_ram_base + KERNEL_LOAD_ADDR);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
exit(1);
}
if (initrd_filename) {
initrd_size = load_image(initrd_filename,
phys_ram_base + INITRD_LOAD_ADDR);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initrd '%s'\n",
initrd_filename);
kernel_size = load_elf(kernel_filename, 0, &entry);
if (kernel_size >= 0) {
/* An ELF image. Jump to the entry point. */
env->regs[15] = entry & 0xfffffffe;
env->thumb = entry & 1;
} else {
/* Raw binary image. Assume it is a Linux zImage. */
kernel_size = load_image(kernel_filename,
phys_ram_base + KERNEL_LOAD_ADDR);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
exit(1);
}
} else {
initrd_size = 0;
if (initrd_filename) {
initrd_size = load_image(initrd_filename,
phys_ram_base + INITRD_LOAD_ADDR);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initrd '%s'\n",
initrd_filename);
exit(1);
}
} else {
initrd_size = 0;
}
bootloader[1] |= board_id & 0xff;
bootloader[2] |= (board_id >> 8) & 0xff;
bootloader[5] = KERNEL_ARGS_ADDR;
bootloader[6] = KERNEL_LOAD_ADDR;
for (n = 0; n < sizeof(bootloader) / 4; n++)
stl_raw(phys_ram_base + (n * 4), bootloader[n]);
set_kernel_args(ram_size, initrd_size, kernel_cmdline);
}
bootloader[1] |= board_id & 0xff;
bootloader[2] |= (board_id >> 8) & 0xff;
bootloader[5] = KERNEL_ARGS_ADDR;
bootloader[6] = KERNEL_LOAD_ADDR;
for (n = 0; n < sizeof(bootloader) / 4; n++)
stl_raw(phys_ram_base + (n * 4), bootloader[n]);
set_kernel_args(ram_size, initrd_size, kernel_cmdline);
}
+547
View File
@@ -0,0 +1,547 @@
/*
* ARM AMBA Generic/Distributed Interrupt Controller
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licenced under the GPL.
*/
/* TODO: Some variants of this controller can handle multiple CPUs.
Currently only single CPU operation is implemented. */
#include "vl.h"
#include "arm_pic.h"
//#define DEBUG_GIC
#ifdef DEBUG_GIC
#define DPRINTF(fmt, args...) \
do { printf("arm_gic: " fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do {} while(0)
#endif
/* Distributed interrupt controller. */
static const uint8_t gic_id[] =
{ 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
#define GIC_NIRQ 96
typedef struct gic_irq_state
{
unsigned enabled:1;
unsigned pending:1;
unsigned active:1;
unsigned level:1;
unsigned model:1; /* 0 = 1:N, 1 = N:N */
unsigned trigger:1; /* nonzero = edge triggered. */
} gic_irq_state;
#define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1
#define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0
#define GIC_TEST_ENABLED(irq) s->irq_state[irq].enabled
#define GIC_SET_PENDING(irq) s->irq_state[irq].pending = 1
#define GIC_CLEAR_PENDING(irq) s->irq_state[irq].pending = 0
#define GIC_TEST_PENDING(irq) s->irq_state[irq].pending
#define GIC_SET_ACTIVE(irq) s->irq_state[irq].active = 1
#define GIC_CLEAR_ACTIVE(irq) s->irq_state[irq].active = 0
#define GIC_TEST_ACTIVE(irq) s->irq_state[irq].active
#define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
#define GIC_TEST_MODEL(irq) s->irq_state[irq].model
#define GIC_SET_LEVEL(irq) s->irq_state[irq].level = 1
#define GIC_CLEAR_LEVEL(irq) s->irq_state[irq].level = 0
#define GIC_TEST_LEVEL(irq) s->irq_state[irq].level
#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
#define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
typedef struct gic_state
{
arm_pic_handler handler;
uint32_t base;
void *parent;
int parent_irq;
int enabled;
int cpu_enabled;
gic_irq_state irq_state[GIC_NIRQ];
int irq_target[GIC_NIRQ];
int priority[GIC_NIRQ];
int last_active[GIC_NIRQ];
int priority_mask;
int running_irq;
int running_priority;
int current_pending;
} gic_state;
/* TODO: Many places that call this routine could be optimized. */
/* Update interrupt status after enabled or pending bits have been changed. */
static void gic_update(gic_state *s)
{
int best_irq;
int best_prio;
int irq;
s->current_pending = 1023;
if (!s->enabled || !s->cpu_enabled) {
pic_set_irq_new(s->parent, s->parent_irq, 0);
return;
}
best_prio = 0x100;
best_irq = 1023;
for (irq = 0; irq < 96; irq++) {
if (GIC_TEST_ENABLED(irq) && GIC_TEST_PENDING(irq)) {
if (s->priority[irq] < best_prio) {
best_prio = s->priority[irq];
best_irq = irq;
}
}
}
if (best_prio > s->priority_mask) {
pic_set_irq_new(s->parent, s->parent_irq, 0);
} else {
s->current_pending = best_irq;
if (best_prio < s->running_priority) {
DPRINTF("Raised pending IRQ %d\n", best_irq);
pic_set_irq_new(s->parent, s->parent_irq, 1);
}
}
}
static void gic_set_irq(void *opaque, int irq, int level)
{
gic_state *s = (gic_state *)opaque;
/* The first external input line is internal interrupt 32. */
irq += 32;
if (level == GIC_TEST_LEVEL(irq))
return;
if (level) {
GIC_SET_LEVEL(irq);
if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
DPRINTF("Set %d pending\n", irq);
GIC_SET_PENDING(irq);
}
} else {
GIC_CLEAR_LEVEL(irq);
}
gic_update(s);
}
static void gic_set_running_irq(gic_state *s, int irq)
{
s->running_irq = irq;
if (irq == 1023)
s->running_priority = 0x100;
else
s->running_priority = s->priority[irq];
gic_update(s);
}
static uint32_t gic_acknowledge_irq(gic_state *s)
{
int new_irq;
new_irq = s->current_pending;
if (new_irq == 1023 || s->priority[new_irq] >= s->running_priority) {
DPRINTF("ACK no pending IRQ\n");
return 1023;
}
pic_set_irq_new(s->parent, s->parent_irq, 0);
s->last_active[new_irq] = s->running_irq;
/* For level triggered interrupts we clear the pending bit while
the interrupt is active. */
GIC_CLEAR_PENDING(new_irq);
gic_set_running_irq(s, new_irq);
DPRINTF("ACK %d\n", new_irq);
return new_irq;
}
static void gic_complete_irq(gic_state * s, int irq)
{
int update = 0;
DPRINTF("EOI %d\n", irq);
if (s->running_irq == 1023)
return; /* No active IRQ. */
if (irq != 1023) {
/* Mark level triggered interrupts as pending if they are still
raised. */
if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq)
&& GIC_TEST_LEVEL(irq)) {
GIC_SET_PENDING(irq);
update = 1;
}
}
if (irq != s->running_irq) {
/* Complete an IRQ that is not currently running. */
int tmp = s->running_irq;
while (s->last_active[tmp] != 1023) {
if (s->last_active[tmp] == irq) {
s->last_active[tmp] = s->last_active[irq];
break;
}
tmp = s->last_active[tmp];
}
if (update) {
gic_update(s);
}
} else {
/* Complete the current running IRQ. */
gic_set_running_irq(s, s->last_active[s->running_irq]);
}
}
static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
{
gic_state *s = (gic_state *)opaque;
uint32_t res;
int irq;
int i;
offset -= s->base + 0x1000;
if (offset < 0x100) {
if (offset == 0)
return s->enabled;
if (offset == 4)
return (GIC_NIRQ / 32) - 1;
if (offset < 0x08)
return 0;
goto bad_reg;
} else if (offset < 0x200) {
/* Interrupt Set/Clear Enable. */
if (offset < 0x180)
irq = (offset - 0x100) * 8;
else
irq = (offset - 0x180) * 8;
if (irq >= GIC_NIRQ)
goto bad_reg;
res = 0;
for (i = 0; i < 8; i++) {
if (GIC_TEST_ENABLED(irq + i)) {
res |= (1 << i);
}
}
} else if (offset < 0x300) {
/* Interrupt Set/Clear Pending. */
if (offset < 0x280)
irq = (offset - 0x200) * 8;
else
irq = (offset - 0x280) * 8;
if (irq >= GIC_NIRQ)
goto bad_reg;
res = 0;
for (i = 0; i < 8; i++) {
if (GIC_TEST_PENDING(irq + i)) {
res |= (1 << i);
}
}
} else if (offset < 0x400) {
/* Interrupt Active. */
irq = (offset - 0x300) * 8;
if (irq >= GIC_NIRQ)
goto bad_reg;
res = 0;
for (i = 0; i < 8; i++) {
if (GIC_TEST_ACTIVE(irq + i)) {
res |= (1 << i);
}
}
} else if (offset < 0x800) {
/* Interrupt Priority. */
irq = offset - 0x400;
if (irq >= GIC_NIRQ)
goto bad_reg;
res = s->priority[irq];
} else if (offset < 0xc00) {
/* Interrupt CPU Target. */
irq = offset - 0x800;
if (irq >= GIC_NIRQ)
goto bad_reg;
res = s->irq_target[irq];
} else if (offset < 0xf00) {
/* Interrupt Configuration. */
irq = (offset - 0xc00) * 2;
if (irq >= GIC_NIRQ)
goto bad_reg;
res = 0;
for (i = 0; i < 4; i++) {
if (GIC_TEST_MODEL(irq + i))
res |= (1 << (i * 2));
if (GIC_TEST_TRIGGER(irq + i))
res |= (2 << (i * 2));
}
} else if (offset < 0xfe0) {
goto bad_reg;
} else /* offset >= 0xfe0 */ {
if (offset & 3) {
res = 0;
} else {
res = gic_id[(offset - 0xfe0) >> 2];
}
}
return res;
bad_reg:
cpu_abort (cpu_single_env, "gic_dist_readb: Bad offset %x\n", offset);
return 0;
}
static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset)
{
uint32_t val;
val = gic_dist_readb(opaque, offset);
val |= gic_dist_readb(opaque, offset + 1) << 8;
return val;
}
static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
{
uint32_t val;
val = gic_dist_readw(opaque, offset);
val |= gic_dist_readw(opaque, offset + 2) << 16;
return val;
}
static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
gic_state *s = (gic_state *)opaque;
int irq;
int i;
offset -= s->base + 0x1000;
if (offset < 0x100) {
if (offset == 0) {
s->enabled = (value & 1);
DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
} else if (offset < 4) {
/* ignored. */
} else {
goto bad_reg;
}
} else if (offset < 0x180) {
/* Interrupt Set Enable. */
irq = (offset - 0x100) * 8;
if (irq >= GIC_NIRQ)
goto bad_reg;
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
if (!GIC_TEST_ENABLED(irq + i))
DPRINTF("Enabled IRQ %d\n", irq + i);
GIC_SET_ENABLED(irq + i);
/* If a raised level triggered IRQ enabled then mark
is as pending. */
if (GIC_TEST_LEVEL(irq + i) && !GIC_TEST_TRIGGER(irq + i))
GIC_SET_PENDING(irq + i);
}
}
} else if (offset < 0x200) {
/* Interrupt Clear Enable. */
irq = (offset - 0x180) * 8;
if (irq >= GIC_NIRQ)
goto bad_reg;
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
if (GIC_TEST_ENABLED(irq + i))
DPRINTF("Disabled IRQ %d\n", irq + i);
GIC_CLEAR_ENABLED(irq + i);
}
}
} else if (offset < 0x280) {
/* Interrupt Set Pending. */
irq = (offset - 0x200) * 8;
if (irq >= GIC_NIRQ)
goto bad_reg;
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
GIC_SET_PENDING(irq + i);
}
}
} else if (offset < 0x300) {
/* Interrupt Clear Pending. */
irq = (offset - 0x280) * 8;
if (irq >= GIC_NIRQ)
goto bad_reg;
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
GIC_CLEAR_PENDING(irq + i);
}
}
} else if (offset < 0x400) {
/* Interrupt Active. */
goto bad_reg;
} else if (offset < 0x800) {
/* Interrupt Priority. */
irq = offset - 0x400;
if (irq >= GIC_NIRQ)
goto bad_reg;
s->priority[irq] = value;
} else if (offset < 0xc00) {
/* Interrupt CPU Target. */
irq = offset - 0x800;
if (irq >= GIC_NIRQ)
goto bad_reg;
s->irq_target[irq] = value;
} else if (offset < 0xf00) {
/* Interrupt Configuration. */
irq = (offset - 0xc00) * 4;
if (irq >= GIC_NIRQ)
goto bad_reg;
for (i = 0; i < 4; i++) {
if (value & (1 << (i * 2))) {
GIC_SET_MODEL(irq + i);
} else {
GIC_CLEAR_MODEL(irq + i);
}
if (value & (2 << (i * 2))) {
GIC_SET_TRIGGER(irq + i);
} else {
GIC_CLEAR_TRIGGER(irq + i);
}
}
} else {
/* 0xf00 is only handled for word writes. */
goto bad_reg;
}
gic_update(s);
return;
bad_reg:
cpu_abort (cpu_single_env, "gic_dist_writeb: Bad offset %x\n", offset);
}
static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
gic_state *s = (gic_state *)opaque;
if (offset - s->base == 0xf00) {
GIC_SET_PENDING(value & 0x3ff);
gic_update(s);
return;
}
gic_dist_writeb(opaque, offset, value & 0xff);
gic_dist_writeb(opaque, offset + 1, value >> 8);
}
static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
gic_dist_writew(opaque, offset, value & 0xffff);
gic_dist_writew(opaque, offset + 2, value >> 16);
}
static CPUReadMemoryFunc *gic_dist_readfn[] = {
gic_dist_readb,
gic_dist_readw,
gic_dist_readl
};
static CPUWriteMemoryFunc *gic_dist_writefn[] = {
gic_dist_writeb,
gic_dist_writew,
gic_dist_writel
};
static uint32_t gic_cpu_read(void *opaque, target_phys_addr_t offset)
{
gic_state *s = (gic_state *)opaque;
offset -= s->base;
switch (offset) {
case 0x00: /* Control */
return s->cpu_enabled;
case 0x04: /* Priority mask */
return s->priority_mask;
case 0x08: /* Binary Point */
/* ??? Not implemented. */
return 0;
case 0x0c: /* Acknowledge */
return gic_acknowledge_irq(s);
case 0x14: /* Runing Priority */
return s->running_priority;
case 0x18: /* Highest Pending Interrupt */
return s->current_pending;
default:
cpu_abort (cpu_single_env, "gic_cpu_writeb: Bad offset %x\n", offset);
return 0;
}
}
static void gic_cpu_write(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
gic_state *s = (gic_state *)opaque;
offset -= s->base;
switch (offset) {
case 0x00: /* Control */
s->cpu_enabled = (value & 1);
DPRINTF("CPU %sabled\n", s->cpu_enabled ? "En" : "Dis");
break;
case 0x04: /* Priority mask */
s->priority_mask = (value & 0x3ff);
break;
case 0x08: /* Binary Point */
/* ??? Not implemented. */
break;
case 0x10: /* End Of Interrupt */
return gic_complete_irq(s, value & 0x3ff);
default:
cpu_abort (cpu_single_env, "gic_cpu_writeb: Bad offset %x\n", offset);
return;
}
gic_update(s);
}
static CPUReadMemoryFunc *gic_cpu_readfn[] = {
gic_cpu_read,
gic_cpu_read,
gic_cpu_read
};
static CPUWriteMemoryFunc *gic_cpu_writefn[] = {
gic_cpu_write,
gic_cpu_write,
gic_cpu_write
};
static void gic_reset(gic_state *s)
{
int i;
memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
s->priority_mask = 0xf0;
s->current_pending = 1023;
s->running_irq = 1023;
s->running_priority = 0x100;
for (i = 0; i < 15; i++) {
GIC_SET_ENABLED(i);
GIC_SET_TRIGGER(i);
}
s->enabled = 0;
s->cpu_enabled = 0;
}
void *arm_gic_init(uint32_t base, void *parent, int parent_irq)
{
gic_state *s;
int iomemtype;
s = (gic_state *)qemu_mallocz(sizeof(gic_state));
if (!s)
return NULL;
s->handler = gic_set_irq;
s->parent = parent;
s->parent_irq = parent_irq;
if (base != 0xffffffff) {
iomemtype = cpu_register_io_memory(0, gic_cpu_readfn,
gic_cpu_writefn, s);
cpu_register_physical_memory(base, 0x00000fff, iomemtype);
iomemtype = cpu_register_io_memory(0, gic_dist_readfn,
gic_dist_writefn, s);
cpu_register_physical_memory(base + 0x1000, 0x00000fff, iomemtype);
s->base = base;
} else {
s->base = 0;
}
gic_reset(s);
return s;
}
+208
View File
@@ -0,0 +1,208 @@
/*
* Status and system control registers for ARM RealView/Versatile boards.
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licenced under the GPL.
*/
#include "vl.h"
#include "arm_pic.h"
#define LOCK_VALUE 0xa05f
typedef struct {
uint32_t base;
uint32_t sys_id;
uint32_t leds;
uint16_t lockval;
uint32_t cfgdata1;
uint32_t cfgdata2;
uint32_t flags;
uint32_t nvflags;
uint32_t resetlevel;
} arm_sysctl_state;
static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
{
arm_sysctl_state *s = (arm_sysctl_state *)opaque;
offset -= s->base;
switch (offset) {
case 0x00: /* ID */
return s->sys_id;
case 0x04: /* SW */
/* General purpose hardware switches.
We don't have a useful way of exposing these to the user. */
return 0;
case 0x08: /* LED */
return s->leds;
case 0x20: /* LOCK */
return s->lockval;
case 0x0c: /* OSC0 */
case 0x10: /* OSC1 */
case 0x14: /* OSC2 */
case 0x18: /* OSC3 */
case 0x1c: /* OSC4 */
case 0x24: /* 100HZ */
/* ??? Implement these. */
return 0;
case 0x28: /* CFGDATA1 */
return s->cfgdata1;
case 0x2c: /* CFGDATA2 */
return s->cfgdata2;
case 0x30: /* FLAGS */
return s->flags;
case 0x38: /* NVFLAGS */
return s->nvflags;
case 0x40: /* RESETCTL */
return s->resetlevel;
case 0x44: /* PCICTL */
return 1;
case 0x48: /* MCI */
return 0;
case 0x4c: /* FLASH */
return 0;
case 0x50: /* CLCD */
return 0x1000;
case 0x54: /* CLCDSER */
return 0;
case 0x58: /* BOOTCS */
return 0;
case 0x5c: /* 24MHz */
/* ??? not implemented. */
return 0;
case 0x60: /* MISC */
return 0;
case 0x84: /* PROCID0 */
/* ??? Don't know what the proper value for the core tile ID is. */
return 0x02000000;
case 0x88: /* PROCID1 */
return 0xff000000;
case 0x64: /* DMAPSR0 */
case 0x68: /* DMAPSR1 */
case 0x6c: /* DMAPSR2 */
case 0x70: /* IOSEL */
case 0x74: /* PLDCTL */
case 0x80: /* BUSID */
case 0x8c: /* OSCRESET0 */
case 0x90: /* OSCRESET1 */
case 0x94: /* OSCRESET2 */
case 0x98: /* OSCRESET3 */
case 0x9c: /* OSCRESET4 */
case 0xc0: /* SYS_TEST_OSC0 */
case 0xc4: /* SYS_TEST_OSC1 */
case 0xc8: /* SYS_TEST_OSC2 */
case 0xcc: /* SYS_TEST_OSC3 */
case 0xd0: /* SYS_TEST_OSC4 */
return 0;
default:
printf ("arm_sysctl_read: Bad register offset 0x%x\n", (int)offset);
return 0;
}
}
static void arm_sysctl_write(void *opaque, target_phys_addr_t offset,
uint32_t val)
{
arm_sysctl_state *s = (arm_sysctl_state *)opaque;
offset -= s->base;
switch (offset) {
case 0x08: /* LED */
s->leds = val;
case 0x0c: /* OSC0 */
case 0x10: /* OSC1 */
case 0x14: /* OSC2 */
case 0x18: /* OSC3 */
case 0x1c: /* OSC4 */
/* ??? */
break;
case 0x20: /* LOCK */
if (val == LOCK_VALUE)
s->lockval = val;
else
s->lockval = val & 0x7fff;
break;
case 0x28: /* CFGDATA1 */
/* ??? Need to implement this. */
s->cfgdata1 = val;
break;
case 0x2c: /* CFGDATA2 */
/* ??? Need to implement this. */
s->cfgdata2 = val;
break;
case 0x30: /* FLAGSSET */
s->flags |= val;
break;
case 0x34: /* FLAGSCLR */
s->flags &= ~val;
break;
case 0x38: /* NVFLAGSSET */
s->nvflags |= val;
break;
case 0x3c: /* NVFLAGSCLR */
s->nvflags &= ~val;
break;
case 0x40: /* RESETCTL */
if (s->lockval == LOCK_VALUE) {
s->resetlevel = val;
if (val & 0x100)
cpu_abort(cpu_single_env, "Board reset\n");
}
break;
case 0x44: /* PCICTL */
/* nothing to do. */
break;
case 0x4c: /* FLASH */
case 0x50: /* CLCD */
case 0x54: /* CLCDSER */
case 0x64: /* DMAPSR0 */
case 0x68: /* DMAPSR1 */
case 0x6c: /* DMAPSR2 */
case 0x70: /* IOSEL */
case 0x74: /* PLDCTL */
case 0x80: /* BUSID */
case 0x84: /* PROCID0 */
case 0x88: /* PROCID1 */
case 0x8c: /* OSCRESET0 */
case 0x90: /* OSCRESET1 */
case 0x94: /* OSCRESET2 */
case 0x98: /* OSCRESET3 */
case 0x9c: /* OSCRESET4 */
break;
default:
printf ("arm_sysctl_write: Bad register offset 0x%x\n", (int)offset);
return;
}
}
static CPUReadMemoryFunc *arm_sysctl_readfn[] = {
arm_sysctl_read,
arm_sysctl_read,
arm_sysctl_read
};
static CPUWriteMemoryFunc *arm_sysctl_writefn[] = {
arm_sysctl_write,
arm_sysctl_write,
arm_sysctl_write
};
void arm_sysctl_init(uint32_t base, uint32_t sys_id)
{
arm_sysctl_state *s;
int iomemtype;
s = (arm_sysctl_state *)qemu_mallocz(sizeof(arm_sysctl_state));
if (!s)
return;
s->base = base;
s->sys_id = sys_id;
iomemtype = cpu_register_io_memory(0, arm_sysctl_readfn,
arm_sysctl_writefn, s);
cpu_register_physical_memory(base, 0x00000fff, iomemtype);
/* ??? Save/restore. */
}
+5 -5
View File
@@ -107,29 +107,29 @@ static void arm_timer_update(arm_timer_state *s, int64_t now)
/* Return the current value of the timer. */
static uint32_t arm_timer_getcount(arm_timer_state *s, int64_t now)
{
int64_t elapsed;
int64_t left;
int64_t period;
if (s->count == 0)
return 0;
if ((s->control & TIMER_CTRL_ENABLE) == 0)
return s->count;
elapsed = now - s->loaded;
left = s->expires - now;
period = s->expires - s->loaded;
/* If the timer should have expired then return 0. This can happen
when the host timer signal doesnt occur immediately. It's better to
have a timer appear to sit at zero for a while than have it wrap
around before the guest interrupt is raised. */
/* ??? Could we trigger the interrupt here? */
if (elapsed > period)
if (left < 0)
return 0;
/* We need to calculate count * elapsed / period without overfowing.
Scale both elapsed and period so they fit in a 32-bit int. */
while (period != (int32_t)period) {
period >>= 1;
elapsed >>= 1;
left >>= 1;
}
return ((uint64_t)s->count * (uint64_t)(int32_t)elapsed)
return ((uint64_t)s->count * (uint64_t)(int32_t)left)
/ (int32_t)period;
}
+22 -6
View File
@@ -1000,12 +1000,12 @@ static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
***************************************/
static void cirrus_get_offsets(VGAState *s1,
uint32_t *pline_offset,
uint32_t *pstart_addr)
uint32_t *pline_offset,
uint32_t *pstart_addr,
uint32_t *pline_compare)
{
CirrusVGAState * s = (CirrusVGAState *)s1;
uint32_t start_addr;
uint32_t line_offset;
uint32_t start_addr, line_offset, line_compare;
line_offset = s->cr[0x13]
| ((s->cr[0x1b] & 0x10) << 4);
@@ -1018,6 +1018,11 @@ static void cirrus_get_offsets(VGAState *s1,
| ((s->cr[0x1b] & 0x0c) << 15)
| ((s->cr[0x1d] & 0x80) << 12);
*pstart_addr = start_addr;
line_compare = s->cr[0x18] |
((s->cr[0x07] & 0x10) << 4) |
((s->cr[0x09] & 0x40) << 3);
*pline_compare = line_compare;
}
static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
@@ -2905,6 +2910,9 @@ static void cirrus_vga_save(QEMUFile *f, void *opaque)
{
CirrusVGAState *s = opaque;
if (s->pci_dev)
pci_device_save(s->pci_dev, f);
qemu_put_be32s(f, &s->latch);
qemu_put_8s(f, &s->sr_index);
qemu_put_buffer(f, s->sr, 256);
@@ -2943,10 +2951,17 @@ static void cirrus_vga_save(QEMUFile *f, void *opaque)
static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
{
CirrusVGAState *s = opaque;
int ret;
if (version_id != 1)
if (version_id > 2)
return -EINVAL;
if (s->pci_dev && version_id >= 2) {
ret = pci_device_load(s->pci_dev, f);
if (ret < 0)
return ret;
}
qemu_get_be32s(f, &s->latch);
qemu_get_8s(f, &s->sr_index);
qemu_get_buffer(f, s->sr, 256);
@@ -3100,7 +3115,7 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
s->cursor_invalidate = cirrus_cursor_invalidate;
s->cursor_draw_line = cirrus_cursor_draw_line;
register_savevm("cirrus_vga", 0, 1, cirrus_vga_save, cirrus_vga_load, s);
register_savevm("cirrus_vga", 0, 2, cirrus_vga_save, cirrus_vga_load, s);
}
/***************************************
@@ -3178,6 +3193,7 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
vga_common_init((VGAState *)s,
ds, vga_ram_base, vga_ram_offset, vga_ram_size);
cirrus_init_common(s, device_id, 1);
s->pci_dev = (PCIDevice *)d;
/* setup memory space */
/* memory #0 LFB */
+183
View File
@@ -0,0 +1,183 @@
/*
* QEMU Crystal CS4231 audio chip emulation
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
/* debug CS4231 */
//#define DEBUG_CS
/*
* In addition to Crystal CS4231 there is a DMA controller on Sparc.
*/
#define CS_MAXADDR 0x3f
#define CS_REGS 16
#define CS_DREGS 32
#define CS_MAXDREG (CS_DREGS - 1)
typedef struct CSState {
uint32_t regs[CS_REGS];
uint8_t dregs[CS_DREGS];
void *intctl;
} CSState;
#define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG)
#define CS_VER 0xa0
#define CS_CDC_VER 0x8a
#ifdef DEBUG_CS
#define DPRINTF(fmt, args...) \
do { printf("CS: " fmt , ##args); } while (0)
#define pic_set_irq_new(intctl, irq, level) \
do { printf("CS: set_irq(%d): %d\n", (irq), (level)); \
pic_set_irq_new((intctl), (irq),(level));} while (0)
#else
#define DPRINTF(fmt, args...)
#endif
static void cs_reset(void *opaque)
{
CSState *s = opaque;
memset(s->regs, 0, CS_REGS * 4);
memset(s->dregs, 0, CS_DREGS);
s->dregs[12] = CS_CDC_VER;
s->dregs[25] = CS_VER;
}
static uint32_t cs_mem_readl(void *opaque, target_phys_addr_t addr)
{
CSState *s = opaque;
uint32_t saddr, ret;
saddr = (addr & CS_MAXADDR) >> 2;
switch (saddr) {
case 1:
switch (CS_RAP(s)) {
case 3: // Write only
ret = 0;
break;
default:
ret = s->dregs[CS_RAP(s)];
break;
}
DPRINTF("read dreg[%d]: 0x%8.8x\n", CS_RAP(s), ret);
break;
default:
ret = s->regs[saddr];
DPRINTF("read reg[%d]: 0x%8.8x\n", saddr, ret);
break;
}
return ret;
}
static void cs_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
CSState *s = opaque;
uint32_t saddr;
saddr = (addr & CS_MAXADDR) >> 2;
DPRINTF("write reg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->regs[saddr], val);
switch (saddr) {
case 1:
DPRINTF("write dreg[%d]: 0x%2.2x -> 0x%2.2x\n", CS_RAP(s), s->dregs[CS_RAP(s)], val);
switch(CS_RAP(s)) {
case 11:
case 25: // Read only
break;
case 12:
val &= 0x40;
val |= CS_CDC_VER; // Codec version
s->dregs[CS_RAP(s)] = val;
break;
default:
s->dregs[CS_RAP(s)] = val;
break;
}
break;
case 2: // Read only
break;
case 4:
if (val & 1)
cs_reset(s);
val &= 0x7f;
s->regs[saddr] = val;
break;
default:
s->regs[saddr] = val;
break;
}
}
static CPUReadMemoryFunc *cs_mem_read[3] = {
cs_mem_readl,
cs_mem_readl,
cs_mem_readl,
};
static CPUWriteMemoryFunc *cs_mem_write[3] = {
cs_mem_writel,
cs_mem_writel,
cs_mem_writel,
};
static void cs_save(QEMUFile *f, void *opaque)
{
CSState *s = opaque;
unsigned int i;
for (i = 0; i < CS_REGS; i++)
qemu_put_be32s(f, &s->regs[i]);
qemu_put_buffer(f, s->dregs, CS_DREGS);
}
static int cs_load(QEMUFile *f, void *opaque, int version_id)
{
CSState *s = opaque;
unsigned int i;
if (version_id > 1)
return -EINVAL;
for (i = 0; i < CS_REGS; i++)
qemu_get_be32s(f, &s->regs[i]);
qemu_get_buffer(f, s->dregs, CS_DREGS);
return 0;
}
void cs_init(target_phys_addr_t base, int irq, void *intctl)
{
int cs_io_memory;
CSState *s;
s = qemu_mallocz(sizeof(CSState));
if (!s)
return;
cs_io_memory = cpu_register_io_memory(0, cs_mem_read, cs_mem_write, s);
cpu_register_physical_memory(base, CS_MAXADDR, cs_io_memory);
register_savevm("cs4231", base, 1, cs_save, cs_load, s);
qemu_register_reset(cs_reset, s);
cs_reset(s);
}
+191 -187
View File
@@ -1,5 +1,5 @@
/*
* QEMU ESP emulation
* QEMU ESP/NCR53C9x emulation
*
* Copyright (c) 2005-2006 Fabrice Bellard
*
@@ -26,33 +26,33 @@
/* debug ESP card */
//#define DEBUG_ESP
/*
* On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O), also
* produced as NCR89C100. See
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
* and
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
*/
#ifdef DEBUG_ESP
#define DPRINTF(fmt, args...) \
do { printf("ESP: " fmt , ##args); } while (0)
#define pic_set_irq(irq, level) \
do { printf("ESP: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
#else
#define DPRINTF(fmt, args...)
#endif
#define ESPDMA_REGS 4
#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
#define ESP_MAXREG 0x3f
#define TI_BUFSZ 32
#define DMA_VER 0xa0000000
#define DMA_INTR 1
#define DMA_INTREN 0x10
#define DMA_WRITE_MEM 0x100
#define DMA_LOADED 0x04000000
/* The HBA is ID 7, so for simplicitly limit to 7 devices. */
#define ESP_MAX_DEVS 7
typedef struct ESPState ESPState;
struct ESPState {
BlockDriverState **bd;
uint8_t rregs[ESP_MAXREG];
uint8_t wregs[ESP_MAXREG];
int irq;
uint32_t espdmaregs[ESPDMA_REGS];
uint32_t ti_size;
int32_t ti_size;
uint32_t ti_rptr, ti_wptr;
uint8_t ti_buf[TI_BUFSZ];
int sense;
@@ -62,6 +62,15 @@ struct ESPState {
uint8_t cmdbuf[TI_BUFSZ];
int cmdlen;
int do_cmd;
/* The amount of data left in the current DMA transfer. */
uint32_t dma_left;
/* The size of the current DMA transfer. Zero if no transfer is in
progress. */
uint32_t dma_counter;
uint8_t *async_buf;
uint32_t async_len;
void *dma_opaque;
};
#define STAT_DO 0x00
@@ -72,6 +81,8 @@ struct ESPState {
#define STAT_MO 0x07
#define STAT_TC 0x10
#define STAT_PE 0x20
#define STAT_GE 0x40
#define STAT_IN 0x80
#define INTR_FC 0x08
@@ -84,17 +95,14 @@ struct ESPState {
static int get_cmd(ESPState *s, uint8_t *buf)
{
uint32_t dmaptr, dmalen;
uint32_t dmalen;
int target;
dmalen = s->wregs[0] | (s->wregs[1] << 8);
dmalen = s->rregs[0] | (s->rregs[1] << 8);
target = s->wregs[4] & 7;
DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr);
cpu_physical_memory_read(dmaptr, buf, dmalen);
espdma_memory_read(s->dma_opaque, buf, dmalen);
} else {
buf[0] = 0;
memcpy(&buf[1], s->ti_buf, dmalen);
@@ -105,13 +113,18 @@ static int get_cmd(ESPState *s, uint8_t *buf)
s->ti_rptr = 0;
s->ti_wptr = 0;
if (target >= 4 || !s->scsi_dev[target]) {
if (s->current_dev) {
/* Started a new command before the old one finished. Cancel it. */
scsi_cancel_io(s->current_dev, 0);
s->async_len = 0;
}
if (target >= MAX_DISKS || !s->scsi_dev[target]) {
// No such drive
s->rregs[4] = STAT_IN;
s->rregs[5] = INTR_DC;
s->rregs[6] = SEQ_0;
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
espdma_raise_irq(s->dma_opaque);
return 0;
}
s->current_dev = s->scsi_dev[target];
@@ -126,22 +139,22 @@ static void do_cmd(ESPState *s, uint8_t *buf)
DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
lun = buf[0] & 7;
datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
if (datalen == 0) {
s->ti_size = 0;
} else {
s->ti_size = datalen;
if (datalen != 0) {
s->rregs[4] = STAT_IN | STAT_TC;
s->dma_left = 0;
s->dma_counter = 0;
if (datalen > 0) {
s->rregs[4] |= STAT_DI;
s->ti_size = datalen;
scsi_read_data(s->current_dev, 0);
} else {
s->rregs[4] |= STAT_DO;
s->ti_size = -datalen;
scsi_write_data(s->current_dev, 0);
}
}
s->rregs[5] = INTR_BS | INTR_FC;
s->rregs[6] = SEQ_CD;
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
espdma_raise_irq(s->dma_opaque);
}
static void handle_satn(ESPState *s)
@@ -160,27 +173,20 @@ static void handle_satn_stop(ESPState *s)
if (s->cmdlen) {
DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
s->do_cmd = 1;
s->espdmaregs[1] += s->cmdlen;
s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
s->rregs[5] = INTR_BS | INTR_FC;
s->rregs[6] = SEQ_CD;
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
espdma_raise_irq(s->dma_opaque);
}
}
static void write_response(ESPState *s)
{
uint32_t dmaptr;
DPRINTF("Transfer status (sense=%d)\n", s->sense);
s->ti_buf[0] = s->sense;
s->ti_buf[1] = 0;
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
DPRINTF("DMA Direction: %c\n",
s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r');
cpu_physical_memory_write(dmaptr, s->ti_buf, 2);
espdma_memory_write(s->dma_opaque, s->ti_buf, 2);
s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
s->rregs[5] = INTR_BS | INTR_FC;
s->rregs[6] = SEQ_CD;
@@ -190,84 +196,127 @@ static void write_response(ESPState *s)
s->ti_wptr = 0;
s->rregs[7] = 2;
}
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
espdma_raise_irq(s->dma_opaque);
}
static void esp_command_complete(void *opaque, uint32_t tag, int sense)
static void esp_dma_done(ESPState *s)
{
s->rregs[4] |= STAT_IN | STAT_TC;
s->rregs[5] = INTR_BS;
s->rregs[6] = 0;
s->rregs[7] = 0;
s->rregs[0] = 0;
s->rregs[1] = 0;
espdma_raise_irq(s->dma_opaque);
}
static void esp_do_dma(ESPState *s)
{
uint32_t len;
int to_device;
to_device = (s->ti_size < 0);
len = s->dma_left;
if (s->do_cmd) {
DPRINTF("command len %d + %d\n", s->cmdlen, len);
espdma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
s->ti_size = 0;
s->cmdlen = 0;
s->do_cmd = 0;
do_cmd(s, s->cmdbuf);
return;
}
if (s->async_len == 0) {
/* Defer until data is available. */
return;
}
if (len > s->async_len) {
len = s->async_len;
}
if (to_device) {
espdma_memory_read(s->dma_opaque, s->async_buf, len);
} else {
espdma_memory_write(s->dma_opaque, s->async_buf, len);
}
s->dma_left -= len;
s->async_buf += len;
s->async_len -= len;
if (to_device)
s->ti_size += len;
else
s->ti_size -= len;
if (s->async_len == 0) {
if (to_device) {
// ti_size is negative
scsi_write_data(s->current_dev, 0);
} else {
scsi_read_data(s->current_dev, 0);
/* If there is still data to be read from the device then
complete the DMA operation immeriately. Otherwise defer
until the scsi layer has completed. */
if (s->dma_left == 0 && s->ti_size > 0) {
esp_dma_done(s);
}
}
} else {
/* Partially filled a scsi buffer. Complete immediately. */
esp_dma_done(s);
}
}
static void esp_command_complete(void *opaque, int reason, uint32_t tag,
uint32_t arg)
{
ESPState *s = (ESPState *)opaque;
DPRINTF("SCSI Command complete\n");
if (s->ti_size != 0)
DPRINTF("SCSI command completed unexpectedly\n");
s->ti_size = 0;
if (sense)
DPRINTF("Command failed\n");
s->sense = sense;
s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
if (reason == SCSI_REASON_DONE) {
DPRINTF("SCSI Command complete\n");
if (s->ti_size != 0)
DPRINTF("SCSI command completed unexpectedly\n");
s->ti_size = 0;
s->dma_left = 0;
s->async_len = 0;
if (arg)
DPRINTF("Command failed\n");
s->sense = arg;
s->rregs[4] = STAT_ST;
esp_dma_done(s);
s->current_dev = NULL;
} else {
DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
s->async_len = arg;
s->async_buf = scsi_get_buf(s->current_dev, 0);
if (s->dma_left) {
esp_do_dma(s);
} else if (s->dma_counter != 0 && s->ti_size <= 0) {
/* If this was the last part of a DMA transfer then the
completion interrupt is deferred to here. */
esp_dma_done(s);
}
}
}
static void handle_ti(ESPState *s)
{
uint32_t dmaptr, dmalen, minlen, len, from, to;
unsigned int i;
int to_device;
uint8_t buf[TARGET_PAGE_SIZE];
uint32_t dmalen, minlen;
dmalen = s->wregs[0] | (s->wregs[1] << 8);
dmalen = s->rregs[0] | (s->rregs[1] << 8);
if (dmalen==0) {
dmalen=0x10000;
}
s->dma_counter = dmalen;
if (s->do_cmd)
minlen = (dmalen < 32) ? dmalen : 32;
else if (s->ti_size < 0)
minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
else
minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
DPRINTF("Transfer Information len %d\n", minlen);
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
/* Check if the transfer writes to to reads from the device. */
to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0;
DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x\n",
to_device ? 'r': 'w', dmaptr, s->ti_size);
from = s->espdmaregs[1];
to = from + minlen;
for (i = 0; i < minlen; i += len, from += len) {
dmaptr = iommu_translate(s->espdmaregs[1] + i);
if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
} else {
len = to - from;
}
DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
s->ti_size -= len;
if (s->do_cmd) {
DPRINTF("command len %d + %d\n", s->cmdlen, len);
cpu_physical_memory_read(dmaptr, &s->cmdbuf[s->cmdlen], len);
s->ti_size = 0;
s->cmdlen = 0;
s->do_cmd = 0;
do_cmd(s, s->cmdbuf);
return;
} else {
if (to_device) {
cpu_physical_memory_read(dmaptr, buf, len);
scsi_write_data(s->current_dev, buf, len);
} else {
scsi_read_data(s->current_dev, buf, len);
cpu_physical_memory_write(dmaptr, buf, len);
}
}
}
if (s->ti_size) {
s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI);
}
s->rregs[5] = INTR_BS;
s->rregs[6] = 0;
s->rregs[7] = 0;
s->espdmaregs[0] |= DMA_INTR;
s->dma_left = minlen;
s->rregs[4] &= ~STAT_TC;
esp_do_dma(s);
} else if (s->do_cmd) {
DPRINTF("command len %d\n", s->cmdlen);
s->ti_size = 0;
@@ -276,16 +325,15 @@ static void handle_ti(ESPState *s)
do_cmd(s, s->cmdbuf);
return;
}
pic_set_irq(s->irq, 1);
}
static void esp_reset(void *opaque)
void esp_reset(void *opaque)
{
ESPState *s = opaque;
memset(s->rregs, 0, ESP_MAXREG);
memset(s->wregs, 0, ESP_MAXREG);
s->rregs[0x0e] = 0x4; // Indicate fas100a
memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
s->ti_size = 0;
s->ti_rptr = 0;
s->ti_wptr = 0;
@@ -307,11 +355,12 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
s->ti_size--;
if ((s->rregs[4] & 6) == 0) {
/* Data in/out. */
scsi_read_data(s->current_dev, &s->rregs[2], 0);
fprintf(stderr, "esp: PIO data read not implemented\n");
s->rregs[2] = 0;
} else {
s->rregs[2] = s->ti_buf[s->ti_rptr++];
}
pic_set_irq(s->irq, 1);
espdma_raise_irq(s->dma_opaque);
}
if (s->ti_size == 0) {
s->ti_rptr = 0;
@@ -320,10 +369,9 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
break;
case 5:
// interrupt
// Clear status bits except TC
s->rregs[4] &= STAT_TC;
pic_set_irq(s->irq, 0);
s->espdmaregs[0] &= ~DMA_INTR;
// Clear interrupt/error status bits
s->rregs[4] &= ~(STAT_IN | STAT_GE | STAT_PE);
espdma_clear_irq(s->dma_opaque);
break;
default:
break;
@@ -341,7 +389,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
switch (saddr) {
case 0:
case 1:
s->rregs[saddr] = val;
s->rregs[4] &= ~STAT_TC;
break;
case 2:
// FIFO
@@ -351,7 +399,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
uint8_t buf;
buf = val & 0xff;
s->ti_size--;
scsi_write_data(s->current_dev, &buf, 0);
fprintf(stderr, "esp: PIO data write not implemented\n");
} else {
s->ti_size++;
s->ti_buf[s->ti_wptr++] = val & 0xff;
@@ -362,6 +410,9 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
// Command
if (val & 0x80) {
s->dma = 1;
/* Reload DMA counter. */
s->rregs[0] = s->wregs[0];
s->rregs[1] = s->wregs[1];
} else {
s->dma = 0;
}
@@ -383,8 +434,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
DPRINTF("Bus reset (%2.2x)\n", val);
s->rregs[5] = INTR_RST;
if (!(s->wregs[8] & 0x40)) {
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
espdma_raise_irq(s->dma_opaque);
}
break;
case 0x10:
@@ -447,68 +497,12 @@ static CPUWriteMemoryFunc *esp_mem_write[3] = {
esp_mem_writeb,
};
static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
{
ESPState *s = opaque;
uint32_t saddr;
saddr = (addr & ESPDMA_MAXADDR) >> 2;
DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
return s->espdmaregs[saddr];
}
static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
ESPState *s = opaque;
uint32_t saddr;
saddr = (addr & ESPDMA_MAXADDR) >> 2;
DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
switch (saddr) {
case 0:
if (!(val & DMA_INTREN))
pic_set_irq(s->irq, 0);
if (val & 0x80) {
esp_reset(s);
} else if (val & 0x40) {
val &= ~0x40;
} else if (val == 0)
val = 0x40;
val &= 0x0fffffff;
val |= DMA_VER;
break;
case 1:
s->espdmaregs[0] |= DMA_LOADED;
break;
default:
break;
}
s->espdmaregs[saddr] = val;
}
static CPUReadMemoryFunc *espdma_mem_read[3] = {
espdma_mem_readl,
espdma_mem_readl,
espdma_mem_readl,
};
static CPUWriteMemoryFunc *espdma_mem_write[3] = {
espdma_mem_writel,
espdma_mem_writel,
espdma_mem_writel,
};
static void esp_save(QEMUFile *f, void *opaque)
{
ESPState *s = opaque;
unsigned int i;
qemu_put_buffer(f, s->rregs, ESP_MAXREG);
qemu_put_buffer(f, s->wregs, ESP_MAXREG);
qemu_put_be32s(f, &s->irq);
for (i = 0; i < ESPDMA_REGS; i++)
qemu_put_be32s(f, &s->espdmaregs[i]);
qemu_put_be32s(f, &s->ti_size);
qemu_put_be32s(f, &s->ti_rptr);
qemu_put_be32s(f, &s->ti_wptr);
@@ -519,16 +513,12 @@ static void esp_save(QEMUFile *f, void *opaque)
static int esp_load(QEMUFile *f, void *opaque, int version_id)
{
ESPState *s = opaque;
unsigned int i;
if (version_id != 1)
return -EINVAL;
if (version_id != 2)
return -EINVAL; // Cannot emulate 1
qemu_get_buffer(f, s->rregs, ESP_MAXREG);
qemu_get_buffer(f, s->wregs, ESP_MAXREG);
qemu_get_be32s(f, &s->irq);
for (i = 0; i < ESPDMA_REGS; i++)
qemu_get_be32s(f, &s->espdmaregs[i]);
qemu_get_be32s(f, &s->ti_size);
qemu_get_be32s(f, &s->ti_rptr);
qemu_get_be32s(f, &s->ti_wptr);
@@ -538,34 +528,48 @@ static int esp_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id)
{
ESPState *s = (ESPState *)opaque;
if (id < 0) {
for (id = 0; id < ESP_MAX_DEVS; id++) {
if (s->scsi_dev[id] == NULL)
break;
}
}
if (id >= ESP_MAX_DEVS) {
DPRINTF("Bad Device ID %d\n", id);
return;
}
if (s->scsi_dev[id]) {
DPRINTF("Destroying device %d\n", id);
scsi_disk_destroy(s->scsi_dev[id]);
}
DPRINTF("Attaching block device %d\n", id);
/* Command queueing is not implemented. */
s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
}
void *esp_init(BlockDriverState **bd, uint32_t espaddr, void *dma_opaque)
{
ESPState *s;
int esp_io_memory, espdma_io_memory;
int i;
int esp_io_memory;
s = qemu_mallocz(sizeof(ESPState));
if (!s)
return;
return NULL;
s->bd = bd;
s->irq = irq;
s->dma_opaque = dma_opaque;
esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
esp_reset(s);
register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
register_savevm("esp", espaddr, 2, esp_save, esp_load, s);
qemu_register_reset(esp_reset, s);
for (i = 0; i < MAX_DISKS; i++) {
if (bs_table[i]) {
s->scsi_dev[i] =
scsi_disk_init(bs_table[i], esp_command_complete, s);
}
}
}
return s;
}
+18 -27
View File
@@ -66,7 +66,6 @@ typedef enum fdrive_type_t {
typedef enum fdrive_flags_t {
FDRIVE_MOTOR_ON = 0x01, /* motor on/off */
FDRIVE_REVALIDATE = 0x02, /* Revalidated */
} fdrive_flags_t;
typedef enum fdisk_flags_t {
@@ -236,7 +235,6 @@ static void fd_revalidate (fdrive_t *drv)
int nb_heads, max_track, last_sect, ro;
FLOPPY_DPRINTF("revalidate\n");
drv->drflags &= ~FDRIVE_REVALIDATE;
if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
ro = bdrv_is_read_only(drv->bs);
bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
@@ -291,7 +289,6 @@ static void fd_revalidate (fdrive_t *drv)
drv->max_track = 0;
drv->flags &= ~FDISK_DBL_SIDES;
}
drv->drflags |= FDRIVE_REVALIDATE;
}
/* Motor control */
@@ -488,19 +485,6 @@ static CPUWriteMemoryFunc *fdctrl_mem_write[3] = {
fdctrl_write_mem,
};
static void fd_change_cb (void *opaque)
{
fdrive_t *drv = opaque;
FLOPPY_DPRINTF("disk change\n");
fd_revalidate(drv);
#if 0
fd_recalibrate(drv);
fdctrl_reset_fifo(drv->fdctrl);
fdctrl_raise_irq(drv->fdctrl, 0x20);
#endif
}
fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
uint32_t io_base,
BlockDriverState **fds)
@@ -529,10 +513,6 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
}
for (i = 0; i < 2; i++) {
fd_init(&fdctrl->drives[i], fds[i]);
if (fds[i]) {
bdrv_set_change_cb(fds[i],
&fd_change_cb, &fdctrl->drives[i]);
}
}
fdctrl_reset(fdctrl, 0);
fdctrl->state = FD_CTRL_ACTIVE;
@@ -760,18 +740,28 @@ static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
// fdctrl.precomp = (value >> 2) & 0x07;
}
static int fdctrl_media_changed(fdrive_t *drv)
{
int ret;
if (!drv->bs)
return 0;
ret = bdrv_media_changed(drv->bs);
if (ret) {
fd_revalidate(drv);
}
return ret;
}
/* Digital input register : 0x07 (read-only) */
static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl)
{
uint32_t retval = 0;
if (drv0(fdctrl)->drflags & FDRIVE_REVALIDATE ||
drv1(fdctrl)->drflags & FDRIVE_REVALIDATE)
if (fdctrl_media_changed(drv0(fdctrl)) ||
fdctrl_media_changed(drv1(fdctrl)))
retval |= 0x80;
if (retval != 0)
FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
drv0(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;
drv1(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;
return retval;
}
@@ -898,7 +888,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
fdctrl->data_len = fdctrl->fifo[8];
} else {
int tmp;
fdctrl->data_len = 128 << fdctrl->fifo[5];
fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]);
tmp = (cur_drv->last_sect - ks + 1);
if (fdctrl->fifo[0] & 0x80)
tmp += cur_drv->last_sect;
@@ -1683,8 +1673,9 @@ enqueue:
#else
cur_drv->last_sect = fdctrl->fifo[3];
#endif
/* Bochs BIOS is buggy and don't send format informations
* for each sector. So, pretend all's done right now...
/* TODO: implement format using DMA expected by the Bochs BIOS
* and Linux fdformat (read 3 bytes per sector via DMA and fill
* the sector with the specified fill byte
*/
fdctrl->data_state &= ~FD_STATE_FORMAT;
fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+10 -5
View File
@@ -74,11 +74,15 @@ static CPUReadMemoryFunc *pci_grackle_read[] = {
&pci_host_data_readl,
};
/* XXX: we do not simulate the hardware - we rely on the BIOS to
set correctly for irq line field */
static void pci_grackle_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
/* Don't know if this matches real hardware, but it agrees with OHW. */
static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
{
heathrow_pic_set_irq(pic, d->config[PCI_INTERRUPT_LINE], level);
return (irq_num + (pci_dev->devfn >> 3)) & 3;
}
static void pci_grackle_set_irq(void *pic, int irq_num, int level)
{
heathrow_pic_set_irq(pic, irq_num + 8, level);
}
PCIBus *pci_grackle_init(uint32_t base, void *pic)
@@ -88,7 +92,8 @@ PCIBus *pci_grackle_init(uint32_t base, void *pic)
int pci_mem_config, pci_mem_data;
s = qemu_mallocz(sizeof(GrackleState));
s->bus = pci_register_bus(pci_grackle_set_irq, pic, 0);
s->bus = pci_register_bus(pci_grackle_set_irq, pci_grackle_map_irq,
pic, 0, 0);
pci_mem_config = cpu_register_io_memory(0, pci_grackle_config_read,
pci_grackle_config_write, s);
+648
View File
@@ -0,0 +1,648 @@
/*
* QEMU GT64120 PCI host
*
* Copyright (c) 2006,2007 Aurelien Jarno
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
typedef target_phys_addr_t pci_addr_t;
#include "pci_host.h"
#define GT_REGS (0x1000 >> 2)
/* CPU Configuration */
#define GT_CPU (0x000 >> 2)
#define GT_MULTI (0x120 >> 2)
/* CPU Address Decode */
#define GT_SCS10LD (0x008 >> 2)
#define GT_SCS10HD (0x010 >> 2)
#define GT_SCS32LD (0x018 >> 2)
#define GT_SCS32HD (0x020 >> 2)
#define GT_CS20LD (0x028 >> 2)
#define GT_CS20HD (0x030 >> 2)
#define GT_CS3BOOTLD (0x038 >> 2)
#define GT_CS3BOOTHD (0x040 >> 2)
#define GT_PCI0IOLD (0x048 >> 2)
#define GT_PCI0IOHD (0x050 >> 2)
#define GT_PCI0M0LD (0x058 >> 2)
#define GT_PCI0M0HD (0x060 >> 2)
#define GT_ISD (0x068 >> 2)
#define GT_PCI0M1LD (0x080 >> 2)
#define GT_PCI0M1HD (0x088 >> 2)
#define GT_PCI1IOLD (0x090 >> 2)
#define GT_PCI1IOHD (0x098 >> 2)
#define GT_PCI1M0LD (0x0a0 >> 2)
#define GT_PCI1M0HD (0x0a8 >> 2)
#define GT_PCI1M1LD (0x0b0 >> 2)
#define GT_PCI1M1HD (0x0b8 >> 2)
#define GT_PCI1M1LD (0x0b0 >> 2)
#define GT_PCI1M1HD (0x0b8 >> 2)
#define GT_SCS10AR (0x0d0 >> 2)
#define GT_SCS32AR (0x0d8 >> 2)
#define GT_CS20R (0x0e0 >> 2)
#define GT_CS3BOOTR (0x0e8 >> 2)
#define GT_PCI0IOREMAP (0x0f0 >> 2)
#define GT_PCI0M0REMAP (0x0f8 >> 2)
#define GT_PCI0M1REMAP (0x100 >> 2)
#define GT_PCI1IOREMAP (0x108 >> 2)
#define GT_PCI1M0REMAP (0x110 >> 2)
#define GT_PCI1M1REMAP (0x118 >> 2)
/* CPU Error Report */
#define GT_CPUERR_ADDRLO (0x070 >> 2)
#define GT_CPUERR_ADDRHI (0x078 >> 2)
#define GT_CPUERR_DATALO (0x128 >> 2) /* GT-64120A only */
#define GT_CPUERR_DATAHI (0x130 >> 2) /* GT-64120A only */
#define GT_CPUERR_PARITY (0x138 >> 2) /* GT-64120A only */
/* CPU Sync Barrier */
#define GT_PCI0SYNC (0x0c0 >> 2)
#define GT_PCI1SYNC (0x0c8 >> 2)
/* SDRAM and Device Address Decode */
#define GT_SCS0LD (0x400 >> 2)
#define GT_SCS0HD (0x404 >> 2)
#define GT_SCS1LD (0x408 >> 2)
#define GT_SCS1HD (0x40c >> 2)
#define GT_SCS2LD (0x410 >> 2)
#define GT_SCS2HD (0x414 >> 2)
#define GT_SCS3LD (0x418 >> 2)
#define GT_SCS3HD (0x41c >> 2)
#define GT_CS0LD (0x420 >> 2)
#define GT_CS0HD (0x424 >> 2)
#define GT_CS1LD (0x428 >> 2)
#define GT_CS1HD (0x42c >> 2)
#define GT_CS2LD (0x430 >> 2)
#define GT_CS2HD (0x434 >> 2)
#define GT_CS3LD (0x438 >> 2)
#define GT_CS3HD (0x43c >> 2)
#define GT_BOOTLD (0x440 >> 2)
#define GT_BOOTHD (0x444 >> 2)
#define GT_ADERR (0x470 >> 2)
/* SDRAM Configuration */
#define GT_SDRAM_CFG (0x448 >> 2)
#define GT_SDRAM_OPMODE (0x474 >> 2)
#define GT_SDRAM_BM (0x478 >> 2)
#define GT_SDRAM_ADDRDECODE (0x47c >> 2)
/* SDRAM Parameters */
#define GT_SDRAM_B0 (0x44c >> 2)
#define GT_SDRAM_B1 (0x450 >> 2)
#define GT_SDRAM_B2 (0x454 >> 2)
#define GT_SDRAM_B3 (0x458 >> 2)
/* Device Parameters */
#define GT_DEV_B0 (0x45c >> 2)
#define GT_DEV_B1 (0x460 >> 2)
#define GT_DEV_B2 (0x464 >> 2)
#define GT_DEV_B3 (0x468 >> 2)
#define GT_DEV_BOOT (0x46c >> 2)
/* ECC */
#define GT_ECC_ERRDATALO (0x480 >> 2) /* GT-64120A only */
#define GT_ECC_ERRDATAHI (0x484 >> 2) /* GT-64120A only */
#define GT_ECC_MEM (0x488 >> 2) /* GT-64120A only */
#define GT_ECC_CALC (0x48c >> 2) /* GT-64120A only */
#define GT_ECC_ERRADDR (0x490 >> 2) /* GT-64120A only */
/* DMA Record */
#define GT_DMA0_CNT (0x800 >> 2)
#define GT_DMA1_CNT (0x804 >> 2)
#define GT_DMA2_CNT (0x808 >> 2)
#define GT_DMA3_CNT (0x80c >> 2)
#define GT_DMA0_SA (0x810 >> 2)
#define GT_DMA1_SA (0x814 >> 2)
#define GT_DMA2_SA (0x818 >> 2)
#define GT_DMA3_SA (0x81c >> 2)
#define GT_DMA0_DA (0x820 >> 2)
#define GT_DMA1_DA (0x824 >> 2)
#define GT_DMA2_DA (0x828 >> 2)
#define GT_DMA3_DA (0x82c >> 2)
#define GT_DMA0_NEXT (0x830 >> 2)
#define GT_DMA1_NEXT (0x834 >> 2)
#define GT_DMA2_NEXT (0x838 >> 2)
#define GT_DMA3_NEXT (0x83c >> 2)
#define GT_DMA0_CUR (0x870 >> 2)
#define GT_DMA1_CUR (0x874 >> 2)
#define GT_DMA2_CUR (0x878 >> 2)
#define GT_DMA3_CUR (0x87c >> 2)
/* DMA Channel Control */
#define GT_DMA0_CTRL (0x840 >> 2)
#define GT_DMA1_CTRL (0x844 >> 2)
#define GT_DMA2_CTRL (0x848 >> 2)
#define GT_DMA3_CTRL (0x84c >> 2)
/* DMA Arbiter */
#define GT_DMA_ARB (0x860 >> 2)
/* Timer/Counter */
#define GT_TC0 (0x850 >> 2)
#define GT_TC1 (0x854 >> 2)
#define GT_TC2 (0x858 >> 2)
#define GT_TC3 (0x85c >> 2)
#define GT_TC_CONTROL (0x864 >> 2)
/* PCI Internal */
#define GT_PCI0_CMD (0xc00 >> 2)
#define GT_PCI0_TOR (0xc04 >> 2)
#define GT_PCI0_BS_SCS10 (0xc08 >> 2)
#define GT_PCI0_BS_SCS32 (0xc0c >> 2)
#define GT_PCI0_BS_CS20 (0xc10 >> 2)
#define GT_PCI0_BS_CS3BT (0xc14 >> 2)
#define GT_PCI1_IACK (0xc30 >> 2)
#define GT_PCI0_IACK (0xc34 >> 2)
#define GT_PCI0_BARE (0xc3c >> 2)
#define GT_PCI0_PREFMBR (0xc40 >> 2)
#define GT_PCI0_SCS10_BAR (0xc48 >> 2)
#define GT_PCI0_SCS32_BAR (0xc4c >> 2)
#define GT_PCI0_CS20_BAR (0xc50 >> 2)
#define GT_PCI0_CS3BT_BAR (0xc54 >> 2)
#define GT_PCI0_SSCS10_BAR (0xc58 >> 2)
#define GT_PCI0_SSCS32_BAR (0xc5c >> 2)
#define GT_PCI0_SCS3BT_BAR (0xc64 >> 2)
#define GT_PCI1_CMD (0xc80 >> 2)
#define GT_PCI1_TOR (0xc84 >> 2)
#define GT_PCI1_BS_SCS10 (0xc88 >> 2)
#define GT_PCI1_BS_SCS32 (0xc8c >> 2)
#define GT_PCI1_BS_CS20 (0xc90 >> 2)
#define GT_PCI1_BS_CS3BT (0xc94 >> 2)
#define GT_PCI1_BARE (0xcbc >> 2)
#define GT_PCI1_PREFMBR (0xcc0 >> 2)
#define GT_PCI1_SCS10_BAR (0xcc8 >> 2)
#define GT_PCI1_SCS32_BAR (0xccc >> 2)
#define GT_PCI1_CS20_BAR (0xcd0 >> 2)
#define GT_PCI1_CS3BT_BAR (0xcd4 >> 2)
#define GT_PCI1_SSCS10_BAR (0xcd8 >> 2)
#define GT_PCI1_SSCS32_BAR (0xcdc >> 2)
#define GT_PCI1_SCS3BT_BAR (0xce4 >> 2)
#define GT_PCI1_CFGADDR (0xcf0 >> 2)
#define GT_PCI1_CFGDATA (0xcf4 >> 2)
#define GT_PCI0_CFGADDR (0xcf8 >> 2)
#define GT_PCI0_CFGDATA (0xcfc >> 2)
/* Interrupts */
#define GT_INTRCAUSE (0xc18 >> 2)
#define GT_INTRMASK (0xc1c >> 2)
#define GT_PCI0_ICMASK (0xc24 >> 2)
#define GT_PCI0_SERR0MASK (0xc28 >> 2)
#define GT_CPU_INTSEL (0xc70 >> 2)
#define GT_PCI0_INTSEL (0xc74 >> 2)
#define GT_HINTRCAUSE (0xc98 >> 2)
#define GT_HINTRMASK (0xc9c >> 2)
#define GT_PCI0_HICMASK (0xca4 >> 2)
#define GT_PCI1_SERR1MASK (0xca8 >> 2)
typedef PCIHostState GT64120PCIState;
typedef struct GT64120State {
GT64120PCIState *pci;
uint32_t regs[GT_REGS];
} GT64120State;
static void gt64120_pci_mapping(GT64120State *s)
{
target_phys_addr_t start, length;
/* Update IO mapping */
if ((s->regs[GT_PCI0IOLD] & 0x7f) <= s->regs[GT_PCI0IOHD])
{
start = s->regs[GT_PCI0IOLD] << 21;
length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21;
isa_mmio_init(start, length);
}
}
static void gt64120_writel (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
GT64120State *s = opaque;
uint32_t saddr;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
saddr = (addr & 0xfff) >> 2;
switch (saddr) {
/* CPU Configuration */
case GT_CPU:
s->regs[GT_CPU] = val;
break;
case GT_MULTI:
/* Read-only register as only one GT64xxx is present on the CPU bus */
break;
/* CPU Address Decode */
case GT_PCI0IOLD:
s->regs[GT_PCI0IOLD] = val & 0x00007fff;
s->regs[GT_PCI0IOREMAP] = val & 0x000007ff;
gt64120_pci_mapping(s);
break;
case GT_PCI0M0LD:
s->regs[GT_PCI0M0LD] = val & 0x00007fff;
s->regs[GT_PCI0M0REMAP] = val & 0x000007ff;
gt64120_pci_mapping(s);
break;
case GT_PCI0M1LD:
s->regs[GT_PCI0M1LD] = val & 0x00007fff;
s->regs[GT_PCI0M1REMAP] = val & 0x000007ff;
gt64120_pci_mapping(s);
break;
case GT_PCI1IOLD:
s->regs[GT_PCI1IOLD] = val & 0x00007fff;
s->regs[GT_PCI1IOREMAP] = val & 0x000007ff;
gt64120_pci_mapping(s);
break;
case GT_PCI1M0LD:
s->regs[GT_PCI1M0LD] = val & 0x00007fff;
s->regs[GT_PCI1M0REMAP] = val & 0x000007ff;
gt64120_pci_mapping(s);
break;
case GT_PCI1M1LD:
s->regs[GT_PCI1M1LD] = val & 0x00007fff;
s->regs[GT_PCI1M1REMAP] = val & 0x000007ff;
gt64120_pci_mapping(s);
break;
case GT_PCI0IOHD:
case GT_PCI0M0HD:
case GT_PCI0M1HD:
case GT_PCI1IOHD:
case GT_PCI1M0HD:
case GT_PCI1M1HD:
s->regs[saddr] = val & 0x0000007f;
gt64120_pci_mapping(s);
break;
case GT_PCI0IOREMAP:
case GT_PCI0M0REMAP:
case GT_PCI0M1REMAP:
case GT_PCI1IOREMAP:
case GT_PCI1M0REMAP:
case GT_PCI1M1REMAP:
s->regs[saddr] = val & 0x000007ff;
gt64120_pci_mapping(s);
break;
/* CPU Error Report */
case GT_CPUERR_ADDRLO:
case GT_CPUERR_ADDRHI:
case GT_CPUERR_DATALO:
case GT_CPUERR_DATAHI:
case GT_CPUERR_PARITY:
/* Read-only registers, do nothing */
break;
/* CPU Sync Barrier */
case GT_PCI0SYNC:
case GT_PCI1SYNC:
/* Read-only registers, do nothing */
break;
/* ECC */
case GT_ECC_ERRDATALO:
case GT_ECC_ERRDATAHI:
case GT_ECC_MEM:
case GT_ECC_CALC:
case GT_ECC_ERRADDR:
/* Read-only registers, do nothing */
break;
/* PCI Internal */
case GT_PCI0_CMD:
case GT_PCI1_CMD:
s->regs[saddr] = val & 0x0401fc0f;
break;
case GT_PCI0_CFGADDR:
s->pci->config_reg = val & 0x80fffffc;
break;
case GT_PCI0_CFGDATA:
pci_host_data_writel(s->pci, 0, val);
break;
/* SDRAM Parameters */
case GT_SDRAM_B0:
case GT_SDRAM_B1:
case GT_SDRAM_B2:
case GT_SDRAM_B3:
/* We don't simulate electrical parameters of the SDRAM.
Accept, but ignore the values. */
s->regs[saddr] = val;
break;
default:
#if 0
printf ("gt64120_writel: Bad register offset 0x%x\n", (int)addr);
#endif
break;
}
}
static uint32_t gt64120_readl (void *opaque,
target_phys_addr_t addr)
{
GT64120State *s = opaque;
uint32_t val;
uint32_t saddr;
val = 0;
saddr = (addr & 0xfff) >> 2;
switch (saddr) {
/* CPU Configuration */
case GT_MULTI:
/* Only one GT64xxx is present on the CPU bus, return
the initial value */
val = s->regs[saddr];
break;
/* CPU Error Report */
case GT_CPUERR_ADDRLO:
case GT_CPUERR_ADDRHI:
case GT_CPUERR_DATALO:
case GT_CPUERR_DATAHI:
case GT_CPUERR_PARITY:
/* Emulated memory has no error, always return the initial
values */
val = s->regs[saddr];
break;
/* CPU Sync Barrier */
case GT_PCI0SYNC:
case GT_PCI1SYNC:
/* Reading those register should empty all FIFO on the PCI
bus, which are not emulated. The return value should be
a random value that should be ignored. */
val = 0xc000ffee;
break;
/* ECC */
case GT_ECC_ERRDATALO:
case GT_ECC_ERRDATAHI:
case GT_ECC_MEM:
case GT_ECC_CALC:
case GT_ECC_ERRADDR:
/* Emulated memory has no error, always return the initial
values */
val = s->regs[saddr];
break;
case GT_CPU:
case GT_PCI0IOLD:
case GT_PCI0M0LD:
case GT_PCI0M1LD:
case GT_PCI1IOLD:
case GT_PCI1M0LD:
case GT_PCI1M1LD:
case GT_PCI0IOHD:
case GT_PCI0M0HD:
case GT_PCI0M1HD:
case GT_PCI1IOHD:
case GT_PCI1M0HD:
case GT_PCI1M1HD:
case GT_PCI0_CMD:
case GT_PCI1_CMD:
case GT_PCI0IOREMAP:
case GT_PCI0M0REMAP:
case GT_PCI0M1REMAP:
case GT_PCI1IOREMAP:
case GT_PCI1M0REMAP:
case GT_PCI1M1REMAP:
val = s->regs[saddr];
break;
case GT_PCI0_IACK:
/* Read the IRQ number */
val = pic_read_irq(isa_pic);
break;
/* SDRAM Parameters */
case GT_SDRAM_B0:
case GT_SDRAM_B1:
case GT_SDRAM_B2:
case GT_SDRAM_B3:
/* We don't simulate electrical parameters of the SDRAM.
Just return the last written value. */
val = s->regs[saddr];
break;
/* PCI Internal */
case GT_PCI0_CFGADDR:
val = s->pci->config_reg;
break;
case GT_PCI0_CFGDATA:
val = pci_host_data_readl(s->pci, 0);
break;
default:
val = s->regs[saddr];
#if 0
printf ("gt64120_readl: Bad register offset 0x%x\n", (int)addr);
#endif
break;
}
#ifdef TARGET_WORDS_BIGENDIAN
return bswap32(val);
#else
return val;
#endif
}
static CPUWriteMemoryFunc *gt64120_write[] = {
&gt64120_writel,
&gt64120_writel,
&gt64120_writel,
};
static CPUReadMemoryFunc *gt64120_read[] = {
&gt64120_readl,
&gt64120_readl,
&gt64120_readl,
};
static int pci_gt64120_map_irq(PCIDevice *pci_dev, int irq_num)
{
int slot;
slot = (pci_dev->devfn >> 3);
switch (slot) {
/* PIIX4 USB */
case 10:
return 3;
/* AMD 79C973 Ethernet */
case 11:
return 0;
/* Crystal 4281 Sound */
case 12:
return 0;
/* PCI slot 1 to 4 */
case 18 ... 21:
return ((slot - 18) + irq_num) & 0x03;
/* Unknown device, don't do any translation */
default:
return irq_num;
}
}
extern PCIDevice *piix4_dev;
static int pci_irq_levels[4];
static void pci_gt64120_set_irq(void *pic, int irq_num, int level)
{
int i, pic_irq, pic_level;
pci_irq_levels[irq_num] = level;
/* now we change the pic irq level according to the piix irq mappings */
/* XXX: optimize */
pic_irq = piix4_dev->config[0x60 + irq_num];
if (pic_irq < 16) {
/* The pic level is the logical OR of all the PCI irqs mapped
to it */
pic_level = 0;
for (i = 0; i < 4; i++) {
if (pic_irq == piix4_dev->config[0x60 + i])
pic_level |= pci_irq_levels[i];
}
pic_set_irq(pic_irq, pic_level);
}
}
void gt64120_reset(void *opaque)
{
GT64120State *s = opaque;
/* CPU Configuration */
#ifdef TARGET_WORDS_BIGENDIAN
s->regs[GT_CPU] = 0x00000000;
#else
s->regs[GT_CPU] = 0x00000800;
#endif
s->regs[GT_MULTI] = 0x00000000;
/* CPU Address decode FIXME: not complete*/
s->regs[GT_PCI0IOLD] = 0x00000080;
s->regs[GT_PCI0IOHD] = 0x0000000f;
s->regs[GT_PCI0M0LD] = 0x00000090;
s->regs[GT_PCI0M0HD] = 0x0000001f;
s->regs[GT_PCI0M1LD] = 0x00000790;
s->regs[GT_PCI0M1HD] = 0x0000001f;
s->regs[GT_PCI1IOLD] = 0x00000100;
s->regs[GT_PCI1IOHD] = 0x0000000f;
s->regs[GT_PCI1M0LD] = 0x00000110;
s->regs[GT_PCI1M0HD] = 0x0000001f;
s->regs[GT_PCI1M1LD] = 0x00000120;
s->regs[GT_PCI1M1HD] = 0x0000002f;
s->regs[GT_PCI0IOREMAP] = 0x00000080;
s->regs[GT_PCI0M0REMAP] = 0x00000090;
s->regs[GT_PCI0M1REMAP] = 0x00000790;
s->regs[GT_PCI1IOREMAP] = 0x00000100;
s->regs[GT_PCI1M0REMAP] = 0x00000110;
s->regs[GT_PCI1M1REMAP] = 0x00000120;
/* CPU Error Report */
s->regs[GT_CPUERR_ADDRLO] = 0x00000000;
s->regs[GT_CPUERR_ADDRHI] = 0x00000000;
s->regs[GT_CPUERR_DATALO] = 0xffffffff;
s->regs[GT_CPUERR_DATAHI] = 0xffffffff;
s->regs[GT_CPUERR_PARITY] = 0x000000ff;
/* ECC */
s->regs[GT_ECC_ERRDATALO] = 0x00000000;
s->regs[GT_ECC_ERRDATAHI] = 0x00000000;
s->regs[GT_ECC_MEM] = 0x00000000;
s->regs[GT_ECC_CALC] = 0x00000000;
s->regs[GT_ECC_ERRADDR] = 0x00000000;
/* SDRAM Parameters */
s->regs[GT_SDRAM_B0] = 0x00000005;
s->regs[GT_SDRAM_B1] = 0x00000005;
s->regs[GT_SDRAM_B2] = 0x00000005;
s->regs[GT_SDRAM_B3] = 0x00000005;
/* PCI Internal FIXME: not complete*/
#ifdef TARGET_WORDS_BIGENDIAN
s->regs[GT_PCI0_CMD] = 0x00000000;
s->regs[GT_PCI1_CMD] = 0x00000000;
#else
s->regs[GT_PCI0_CMD] = 0x00010001;
s->regs[GT_PCI1_CMD] = 0x00010001;
#endif
s->regs[GT_PCI0_IACK] = 0x00000000;
s->regs[GT_PCI1_IACK] = 0x00000000;
gt64120_pci_mapping(s);
}
PCIBus *pci_gt64120_init(void *pic)
{
GT64120State *s;
PCIDevice *d;
int gt64120;
s = qemu_mallocz(sizeof(GT64120State));
s->pci = qemu_mallocz(sizeof(GT64120PCIState));
gt64120_reset(s);
s->pci->bus = pci_register_bus(pci_gt64120_set_irq, pci_gt64120_map_irq,
pic, 144, 4);
gt64120 = cpu_register_io_memory(0, gt64120_read,
gt64120_write, s);
cpu_register_physical_memory(0x1be00000LL, 0x1000, gt64120);
d = pci_register_device(s->pci->bus, "GT64120 PCI Bus", sizeof(PCIDevice),
0, NULL, NULL);
d->config[0x00] = 0xab; // vendor_id
d->config[0x01] = 0x11;
d->config[0x02] = 0x46; // device_id
d->config[0x03] = 0x20;
d->config[0x04] = 0x06;
d->config[0x05] = 0x00;
d->config[0x06] = 0x80;
d->config[0x07] = 0xa2;
d->config[0x08] = 0x10;
d->config[0x09] = 0x00;
d->config[0x0A] = 0x80;
d->config[0x0B] = 0x05;
d->config[0x0C] = 0x08;
d->config[0x0D] = 0x40;
d->config[0x0E] = 0x00;
d->config[0x0F] = 0x00;
d->config[0x17] = 0x08;
d->config[0x1B] = 0x1c;
d->config[0x1F] = 0x1f;
d->config[0x23] = 0x14;
d->config[0x27] = 0x14;
d->config[0x3D] = 0x01;
return s->pci->bus;
}
+7
View File
@@ -161,6 +161,13 @@ void pic_update_irq(PicState2 *s)
#endif
s->irq_request(s->irq_request_opaque, 1);
}
/* all targets should do this rather than acking the IRQ in the cpu */
#if defined(TARGET_MIPS)
else {
s->irq_request(s->irq_request_opaque, 0);
}
#endif
}
#ifdef DEBUG_IRQ_LATENCY
+501 -243
View File
File diff suppressed because it is too large. Load diff
+3 -3
View File
@@ -325,7 +325,7 @@ static uint32_t icp_pic_read(void *opaque, target_phys_addr_t offset)
case 5: /* INT_SOFTCLR */
case 11: /* FRQ_ENABLECLR */
default:
printf ("icp_pic_read: Bad register offset 0x%x\n", offset);
printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
return 0;
}
}
@@ -362,7 +362,7 @@ static void icp_pic_write(void *opaque, target_phys_addr_t offset,
case 8: /* FRQ_STATUS */
case 9: /* FRQ_RAWSTAT */
default:
printf ("icp_pic_write: Bad register offset 0x%x\n", offset);
printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
return;
}
icp_pic_update(s);
@@ -509,7 +509,7 @@ static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
}
pl110_init(ds, 0xc0000000, pic, 22, 0);
arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
initrd_filename, 0x113);
}
+38 -5
View File
@@ -186,21 +186,54 @@ static CPUWriteMemoryFunc *iommu_mem_write[3] = {
iommu_mem_writew,
};
uint32_t iommu_translate_local(void *opaque, uint32_t addr)
static uint32_t iommu_page_get_flags(IOMMUState *s, uint32_t addr)
{
IOMMUState *s = opaque;
uint32_t iopte, pa, tmppte;
uint32_t iopte;
iopte = s->regs[1] << 4;
addr &= ~s->iostart;
iopte += (addr >> (PAGE_SHIFT - 2)) & ~3;
pa = ldl_phys(iopte);
return ldl_phys(iopte);
}
static uint32_t iommu_translate_pa(IOMMUState *s, uint32_t addr, uint32_t pa)
{
uint32_t tmppte;
tmppte = pa;
pa = ((pa & IOPTE_PAGE) << 4) + (addr & PAGE_MASK);
DPRINTF("xlate dva %x => pa %x (iopte[%x] = %x)\n", addr, pa, iopte, tmppte);
DPRINTF("xlate dva %x => pa %x (iopte = %x)\n", addr, pa, tmppte);
return pa;
}
void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int is_write)
{
int l, flags;
target_ulong page, phys_addr;
while (len > 0) {
page = addr & TARGET_PAGE_MASK;
l = (page + TARGET_PAGE_SIZE) - addr;
if (l > len)
l = len;
flags = iommu_page_get_flags(opaque, page);
if (!(flags & IOPTE_VALID))
return;
phys_addr = iommu_translate_pa(opaque, addr, flags);
if (is_write) {
if (!(flags & IOPTE_WRITE))
return;
cpu_physical_memory_write(phys_addr, buf, len);
} else {
cpu_physical_memory_read(phys_addr, buf, len);
}
len -= l;
buf += l;
addr += l;
}
}
static void iommu_save(QEMUFile *f, void *opaque)
{
IOMMUState *s = opaque;
+102
View File
@@ -0,0 +1,102 @@
/*
* Memory mapped access to ISA IO space.
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
static void isa_mmio_writeb (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
cpu_outb(NULL, addr & 0xffff, val);
}
static void isa_mmio_writew (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
cpu_outw(NULL, addr & 0xffff, val);
}
static void isa_mmio_writel (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
cpu_outl(NULL, addr & 0xffff, val);
}
static uint32_t isa_mmio_readb (void *opaque, target_phys_addr_t addr)
{
uint32_t val;
val = cpu_inb(NULL, addr & 0xffff);
return val;
}
static uint32_t isa_mmio_readw (void *opaque, target_phys_addr_t addr)
{
uint32_t val;
val = cpu_inw(NULL, addr & 0xffff);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
return val;
}
static uint32_t isa_mmio_readl (void *opaque, target_phys_addr_t addr)
{
uint32_t val;
val = cpu_inl(NULL, addr & 0xffff);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
return val;
}
static CPUWriteMemoryFunc *isa_mmio_write[] = {
&isa_mmio_writeb,
&isa_mmio_writew,
&isa_mmio_writel,
};
static CPUReadMemoryFunc *isa_mmio_read[] = {
&isa_mmio_readb,
&isa_mmio_readw,
&isa_mmio_readl,
};
static int isa_mmio_iomemtype = 0;
void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size)
{
if (!isa_mmio_iomemtype) {
isa_mmio_iomemtype = cpu_register_io_memory(0, isa_mmio_read,
isa_mmio_write, NULL);
}
cpu_register_physical_memory(base, size, isa_mmio_iomemtype);
}
-462
View File
@@ -1,462 +0,0 @@
/*
* QEMU Lance emulation
*
* Copyright (c) 2003-2005 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
/* debug LANCE card */
//#define DEBUG_LANCE
#ifdef DEBUG_LANCE
#define DPRINTF(fmt, args...) \
do { printf("LANCE: " fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...)
#endif
#ifndef LANCE_LOG_TX_BUFFERS
#define LANCE_LOG_TX_BUFFERS 4
#define LANCE_LOG_RX_BUFFERS 4
#endif
#define LE_CSR0 0
#define LE_CSR1 1
#define LE_CSR2 2
#define LE_CSR3 3
#define LE_NREGS (LE_CSR3 + 1)
#define LE_MAXREG LE_CSR3
#define LE_RDP 0
#define LE_RAP 1
#define LE_MO_PROM 0x8000 /* Enable promiscuous mode */
#define LE_C0_ERR 0x8000 /* Error: set if BAB, SQE, MISS or ME is set */
#define LE_C0_BABL 0x4000 /* BAB: Babble: tx timeout. */
#define LE_C0_CERR 0x2000 /* SQE: Signal quality error */
#define LE_C0_MISS 0x1000 /* MISS: Missed a packet */
#define LE_C0_MERR 0x0800 /* ME: Memory error */
#define LE_C0_RINT 0x0400 /* Received interrupt */
#define LE_C0_TINT 0x0200 /* Transmitter Interrupt */
#define LE_C0_IDON 0x0100 /* IFIN: Init finished. */
#define LE_C0_INTR 0x0080 /* Interrupt or error */
#define LE_C0_INEA 0x0040 /* Interrupt enable */
#define LE_C0_RXON 0x0020 /* Receiver on */
#define LE_C0_TXON 0x0010 /* Transmitter on */
#define LE_C0_TDMD 0x0008 /* Transmitter demand */
#define LE_C0_STOP 0x0004 /* Stop the card */
#define LE_C0_STRT 0x0002 /* Start the card */
#define LE_C0_INIT 0x0001 /* Init the card */
#define LE_C3_BSWP 0x4 /* SWAP */
#define LE_C3_ACON 0x2 /* ALE Control */
#define LE_C3_BCON 0x1 /* Byte control */
/* Receive message descriptor 1 */
#define LE_R1_OWN 0x80 /* Who owns the entry */
#define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */
#define LE_R1_FRA 0x20 /* FRA: Frame error */
#define LE_R1_OFL 0x10 /* OFL: Frame overflow */
#define LE_R1_CRC 0x08 /* CRC error */
#define LE_R1_BUF 0x04 /* BUF: Buffer error */
#define LE_R1_SOP 0x02 /* Start of packet */
#define LE_R1_EOP 0x01 /* End of packet */
#define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */
#define LE_T1_OWN 0x80 /* Lance owns the packet */
#define LE_T1_ERR 0x40 /* Error summary */
#define LE_T1_EMORE 0x10 /* Error: more than one retry needed */
#define LE_T1_EONE 0x08 /* Error: one retry needed */
#define LE_T1_EDEF 0x04 /* Error: deferred */
#define LE_T1_SOP 0x02 /* Start of packet */
#define LE_T1_EOP 0x01 /* End of packet */
#define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */
#define LE_T3_BUF 0x8000 /* Buffer error */
#define LE_T3_UFL 0x4000 /* Error underflow */
#define LE_T3_LCOL 0x1000 /* Error late collision */
#define LE_T3_CLOS 0x0800 /* Error carrier loss */
#define LE_T3_RTY 0x0400 /* Error retry */
#define LE_T3_TDR 0x03ff /* Time Domain Reflectometry counter */
#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
#define PKT_BUF_SZ 1544
#define RX_BUFF_SIZE PKT_BUF_SZ
#define TX_BUFF_SIZE PKT_BUF_SZ
struct lance_rx_desc {
unsigned short rmd0; /* low address of packet */
unsigned char rmd1_bits; /* descriptor bits */
unsigned char rmd1_hadr; /* high address of packet */
short length; /* This length is 2s complement (negative)!
* Buffer length
*/
unsigned short mblength; /* This is the actual number of bytes received */
};
struct lance_tx_desc {
unsigned short tmd0; /* low address of packet */
unsigned char tmd1_bits; /* descriptor bits */
unsigned char tmd1_hadr; /* high address of packet */
short length; /* Length is 2s complement (negative)! */
unsigned short misc;
};
/* The LANCE initialization block, described in databook. */
/* On the Sparc, this block should be on a DMA region */
struct lance_init_block {
unsigned short mode; /* Pre-set mode (reg. 15) */
unsigned char phys_addr[6]; /* Physical ethernet address */
unsigned filter[2]; /* Multicast filter. */
/* Receive and transmit ring base, along with extra bits. */
unsigned short rx_ptr; /* receive descriptor addr */
unsigned short rx_len; /* receive len and high addr */
unsigned short tx_ptr; /* transmit descriptor addr */
unsigned short tx_len; /* transmit len and high addr */
/* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
struct lance_rx_desc brx_ring[RX_RING_SIZE];
struct lance_tx_desc btx_ring[TX_RING_SIZE];
char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
char pad[2]; /* align rx_buf for copy_and_sum(). */
char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
};
#define LEDMA_REGS 4
#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1)
typedef struct LANCEState {
VLANClientState *vc;
uint8_t macaddr[6]; /* init mac address */
uint32_t leptr;
uint16_t addr;
uint16_t regs[LE_NREGS];
uint8_t phys[6]; /* mac address */
int irq;
unsigned int rxptr, txptr;
uint32_t ledmaregs[LEDMA_REGS];
} LANCEState;
static void lance_send(void *opaque);
static void lance_reset(void *opaque)
{
LANCEState *s = opaque;
memcpy(s->phys, s->macaddr, 6);
s->rxptr = 0;
s->txptr = 0;
memset(s->regs, 0, LE_NREGS * 2);
s->regs[LE_CSR0] = LE_C0_STOP;
memset(s->ledmaregs, 0, LEDMA_REGS * 4);
}
static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
{
LANCEState *s = opaque;
uint32_t saddr;
saddr = addr & LE_MAXREG;
switch (saddr >> 1) {
case LE_RDP:
DPRINTF("read dreg[%d] = %4.4x\n", s->addr, s->regs[s->addr]);
return s->regs[s->addr];
case LE_RAP:
DPRINTF("read areg = %4.4x\n", s->addr);
return s->addr;
default:
DPRINTF("read unknown(%d)\n", saddr>>1);
break;
}
return 0;
}
static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
LANCEState *s = opaque;
uint32_t saddr;
uint16_t reg;
saddr = addr & LE_MAXREG;
switch (saddr >> 1) {
case LE_RDP:
DPRINTF("write dreg[%d] = %4.4x\n", s->addr, val);
switch(s->addr) {
case LE_CSR0:
if (val & LE_C0_STOP) {
s->regs[LE_CSR0] = LE_C0_STOP;
break;
}
reg = s->regs[LE_CSR0];
// 1 = clear for some bits
reg &= ~(val & 0x7f00);
// generated bits
reg &= ~(LE_C0_ERR | LE_C0_INTR);
if (reg & 0x7100)
reg |= LE_C0_ERR;
if (reg & 0x7f00)
reg |= LE_C0_INTR;
// direct bit
reg &= ~LE_C0_INEA;
reg |= val & LE_C0_INEA;
// exclusive bits
if (val & LE_C0_INIT) {
reg |= LE_C0_IDON | LE_C0_INIT;
reg &= ~LE_C0_STOP;
}
else if (val & LE_C0_STRT) {
reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON;
reg &= ~LE_C0_STOP;
}
s->regs[LE_CSR0] = reg;
break;
case LE_CSR1:
s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff);
s->regs[s->addr] = val;
break;
case LE_CSR2:
s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16);
s->regs[s->addr] = val;
break;
case LE_CSR3:
s->regs[s->addr] = val;
break;
}
break;
case LE_RAP:
DPRINTF("write areg = %4.4x\n", val);
if (val < LE_NREGS)
s->addr = val;
break;
default:
DPRINTF("write unknown(%d) = %4.4x\n", saddr>>1, val);
break;
}
lance_send(s);
}
static CPUReadMemoryFunc *lance_mem_read[3] = {
lance_mem_readw,
lance_mem_readw,
lance_mem_readw,
};
static CPUWriteMemoryFunc *lance_mem_write[3] = {
lance_mem_writew,
lance_mem_writew,
lance_mem_writew,
};
#define MIN_BUF_SIZE 60
static int lance_can_receive(void *opaque)
{
return 1;
}
static void lance_receive(void *opaque, const uint8_t *buf, int size)
{
LANCEState *s = opaque;
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
struct lance_init_block *ib;
unsigned int i, old_rxptr;
uint16_t temp16;
uint8_t temp8;
DPRINTF("receive size %d\n", size);
if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
return;
ib = (void *) iommu_translate(dmaptr);
old_rxptr = s->rxptr;
for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
if (temp8 == (LE_R1_OWN)) {
s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK;
temp16 = size + 4;
bswap16s(&temp16);
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp16, 2);
cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size);
temp8 = LE_R1_POK;
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
if (s->regs[LE_CSR0] & LE_C0_INEA)
pic_set_irq(s->irq, 1);
DPRINTF("got packet, len %d\n", size);
return;
}
}
}
static void lance_send(void *opaque)
{
LANCEState *s = opaque;
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
struct lance_init_block *ib;
unsigned int i, old_txptr;
uint16_t temp16;
uint8_t temp8;
char pkt_buf[PKT_BUF_SZ];
DPRINTF("sending packet? (csr0 %4.4x)\n", s->regs[LE_CSR0]);
if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
return;
ib = (void *) iommu_translate(dmaptr);
DPRINTF("sending packet? (dmaptr %8.8x) (ib %p) (btx_ring %p)\n", dmaptr, ib, &ib->btx_ring);
old_txptr = s->txptr;
for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
if (temp8 == (LE_T1_POK|LE_T1_OWN)) {
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp16, 2);
bswap16s(&temp16);
temp16 = (~temp16) + 1;
cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp16);
DPRINTF("sending packet, len %d\n", temp16);
qemu_send_packet(s->vc, pkt_buf, temp16);
temp8 = LE_T1_POK;
cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK;
s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
}
}
if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
pic_set_irq(s->irq, 1);
}
static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
{
LANCEState *s = opaque;
uint32_t saddr;
saddr = (addr & LEDMA_MAXADDR) >> 2;
return s->ledmaregs[saddr];
}
static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
LANCEState *s = opaque;
uint32_t saddr;
saddr = (addr & LEDMA_MAXADDR) >> 2;
s->ledmaregs[saddr] = val;
}
static CPUReadMemoryFunc *ledma_mem_read[3] = {
ledma_mem_readl,
ledma_mem_readl,
ledma_mem_readl,
};
static CPUWriteMemoryFunc *ledma_mem_write[3] = {
ledma_mem_writel,
ledma_mem_writel,
ledma_mem_writel,
};
static void lance_save(QEMUFile *f, void *opaque)
{
LANCEState *s = opaque;
int i;
qemu_put_be32s(f, &s->leptr);
qemu_put_be16s(f, &s->addr);
for (i = 0; i < LE_NREGS; i ++)
qemu_put_be16s(f, &s->regs[i]);
qemu_put_buffer(f, s->phys, 6);
qemu_put_be32s(f, &s->irq);
for (i = 0; i < LEDMA_REGS; i ++)
qemu_put_be32s(f, &s->ledmaregs[i]);
}
static int lance_load(QEMUFile *f, void *opaque, int version_id)
{
LANCEState *s = opaque;
int i;
if (version_id != 1)
return -EINVAL;
qemu_get_be32s(f, &s->leptr);
qemu_get_be16s(f, &s->addr);
for (i = 0; i < LE_NREGS; i ++)
qemu_get_be16s(f, &s->regs[i]);
qemu_get_buffer(f, s->phys, 6);
qemu_get_be32s(f, &s->irq);
for (i = 0; i < LEDMA_REGS; i ++)
qemu_get_be32s(f, &s->ledmaregs[i]);
return 0;
}
void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
{
LANCEState *s;
int lance_io_memory, ledma_io_memory;
s = qemu_mallocz(sizeof(LANCEState));
if (!s)
return;
s->irq = irq;
lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
cpu_register_physical_memory(leaddr, 4, lance_io_memory);
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s);
cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
memcpy(s->macaddr, nd->macaddr, 6);
lance_reset(s);
s->vc = qemu_new_vlan_client(nd->vlan, lance_receive, lance_can_receive, s);
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
"lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
s->macaddr[0],
s->macaddr[1],
s->macaddr[2],
s->macaddr[3],
s->macaddr[4],
s->macaddr[5]);
register_savevm("lance", leaddr, 1, lance_save, lance_load, s);
qemu_register_reset(lance_reset, s);
}
+393 -100
View File
@@ -19,11 +19,11 @@
#define DPRINTF(fmt, args...) \
do { printf("lsi_scsi: " fmt , ##args); } while (0)
#define BADF(fmt, args...) \
do { fprintf(stderr, "lsi_scsi: " fmt , ##args); exit(1);} while (0)
do { fprintf(stderr, "lsi_scsi: error: " fmt , ##args); exit(1);} while (0)
#else
#define DPRINTF(fmt, args...) do {} while(0)
#define BADF(fmt, args...) \
do { fprintf(stderr, "lsi_scsi: " fmt , ##args); } while (0)
do { fprintf(stderr, "lsi_scsi: error: " fmt , ##args);} while (0)
#endif
#define LSI_SCNTL0_TRG 0x01
@@ -152,21 +152,46 @@ do { fprintf(stderr, "lsi_scsi: " fmt , ##args); } while (0)
/* The HBA is ID 7, so for simplicitly limit to 7 devices. */
#define LSI_MAX_DEVS 7
/* Maximum length of MSG IN data. */
#define LSI_MAX_MSGIN_LEN 8
/* Flag set if this is a tagged command. */
#define LSI_TAG_VALID (1 << 16)
typedef struct {
uint32_t tag;
uint32_t pending;
int out;
} lsi_queue;
typedef struct {
PCIDevice pci_dev;
int mmio_io_addr;
int ram_io_addr;
uint32_t script_ram_base;
uint32_t data_len;
int carry; /* ??? Should this be an a visible register somewhere? */
int sense;
uint8_t msg;
/* Nonzero if a Wait Reselect instruction has been issued. */
/* Action to take at the end of a MSG IN phase.
0 = COMMAND, 1 = disconect, 2 = DATA OUT, 3 = DATA IN. */
int msg_action;
int msg_len;
uint8_t msg[LSI_MAX_MSGIN_LEN];
/* 0 if SCRIPTS are running or stopped.
* 1 if a Wait Reselect instruction has been issued.
* 2 if processing DMA from lsi_execute_script.
* 3 if a DMA operation is in progress. */
int waiting;
SCSIDevice *scsi_dev[LSI_MAX_DEVS];
SCSIDevice *current_dev;
int current_lun;
/* The tag is a combination of the device ID and the SCSI tag. */
uint32_t current_tag;
uint32_t current_dma_len;
uint8_t *dma_buf;
lsi_queue *queue;
int queue_len;
int active_commands;
uint32_t dsa;
uint32_t temp;
@@ -203,10 +228,12 @@ typedef struct {
uint8_t sxfer;
uint8_t socl;
uint8_t sdid;
uint8_t ssid;
uint8_t sfbr;
uint8_t stest1;
uint8_t stest2;
uint8_t stest3;
uint8_t sidl;
uint8_t stime0;
uint8_t respid0;
uint8_t respid1;
@@ -274,6 +301,7 @@ static void lsi_soft_reset(LSIState *s)
s->stest1 = 0;
s->stest2 = 0;
s->stest3 = 0;
s->sidl = 0;
s->stime0 = 0;
s->respid0 = 0x80;
s->respid1 = 0;
@@ -295,6 +323,7 @@ static void lsi_soft_reset(LSIState *s)
static uint8_t lsi_reg_readb(LSIState *s, int offset);
static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val);
static void lsi_execute_script(LSIState *s);
static inline uint32_t read_dword(LSIState *s, uint32_t addr)
{
@@ -402,44 +431,196 @@ static void lsi_bad_phase(LSIState *s, int out, int new_phase)
lsi_set_phase(s, new_phase);
}
static void lsi_do_dma(LSIState *s, int out)
/* Resume SCRIPTS execution after a DMA operation. */
static void lsi_resume_script(LSIState *s)
{
uint8_t buf[TARGET_PAGE_SIZE];
uint32_t addr;
uint32_t count;
int n;
count = s->dbc;
addr = s->dnad;
DPRINTF("DMA %s addr=0x%08x len=%d avail=%d\n", out ? "out" : "in",
addr, count, s->data_len);
/* ??? Too long transfers are truncated. Don't know if this is the
correct behavior. */
if (count > s->data_len) {
/* If the DMA length is greater then the device data length then
a phase mismatch will occur. */
count = s->data_len;
s->dbc = count;
lsi_bad_phase(s, out, PHASE_ST);
}
s->csbc += count;
/* ??? Set SFBR to first data byte. */
while (count) {
n = (count > TARGET_PAGE_SIZE) ? TARGET_PAGE_SIZE : count;
if (out) {
cpu_physical_memory_read(addr, buf, n);
scsi_write_data(s->current_dev, buf, n);
} else {
scsi_read_data(s->current_dev, buf, n);
cpu_physical_memory_write(addr, buf, n);
}
addr += n;
count -= n;
if (s->waiting != 2) {
s->waiting = 0;
lsi_execute_script(s);
} else {
s->waiting = 0;
}
}
/* Initiate a SCSI layer data transfer. */
static void lsi_do_dma(LSIState *s, int out)
{
uint32_t count;
uint32_t addr;
if (!s->current_dma_len) {
/* Wait until data is available. */
DPRINTF("DMA no data available\n");
return;
}
count = s->dbc;
if (count > s->current_dma_len)
count = s->current_dma_len;
DPRINTF("DMA addr=0x%08x len=%d\n", s->dnad, count);
addr = s->dnad;
s->csbc += count;
s->dnad += count;
s->dbc -= count;
if (s->dma_buf == NULL) {
s->dma_buf = scsi_get_buf(s->current_dev, s->current_tag);
}
/* ??? Set SFBR to first data byte. */
if (out) {
cpu_physical_memory_read(addr, s->dma_buf, count);
} else {
cpu_physical_memory_write(addr, s->dma_buf, count);
}
s->current_dma_len -= count;
if (s->current_dma_len == 0) {
s->dma_buf = NULL;
if (out) {
/* Write the data. */
scsi_write_data(s->current_dev, s->current_tag);
} else {
/* Request any remaining data. */
scsi_read_data(s->current_dev, s->current_tag);
}
} else {
s->dma_buf += count;
lsi_resume_script(s);
}
}
/* Add a command to the queue. */
static void lsi_queue_command(LSIState *s)
{
lsi_queue *p;
DPRINTF("Queueing tag=0x%x\n", s->current_tag);
if (s->queue_len == s->active_commands) {
s->queue_len++;
s->queue = realloc(s->queue, s->queue_len * sizeof(lsi_queue));
}
p = &s->queue[s->active_commands++];
p->tag = s->current_tag;
p->pending = 0;
p->out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
}
/* Queue a byte for a MSG IN phase. */
static void lsi_add_msg_byte(LSIState *s, uint8_t data)
{
if (s->msg_len >= LSI_MAX_MSGIN_LEN) {
BADF("MSG IN data too long\n");
} else {
DPRINTF("MSG IN 0x%02x\n", data);
s->msg[s->msg_len++] = data;
}
}
/* Perform reselection to continue a command. */
static void lsi_reselect(LSIState *s, uint32_t tag)
{
lsi_queue *p;
int n;
int id;
p = NULL;
for (n = 0; n < s->active_commands; n++) {
p = &s->queue[n];
if (p->tag == tag)
break;
}
if (n == s->active_commands) {
BADF("Reselected non-existant command tag=0x%x\n", tag);
return;
}
id = (tag >> 8) & 0xf;
s->ssid = id | 0x80;
DPRINTF("Reselected target %d\n", id);
s->current_dev = s->scsi_dev[id];
s->current_tag = tag;
s->scntl1 |= LSI_SCNTL1_CON;
lsi_set_phase(s, PHASE_MI);
s->msg_action = p->out ? 2 : 3;
s->current_dma_len = p->pending;
s->dma_buf = NULL;
lsi_add_msg_byte(s, 0x80);
if (s->current_tag & LSI_TAG_VALID) {
lsi_add_msg_byte(s, 0x20);
lsi_add_msg_byte(s, tag & 0xff);
}
s->active_commands--;
if (n != s->active_commands) {
s->queue[n] = s->queue[s->active_commands];
}
}
/* Record that data is available for a queued command. Returns zero if
the device was reselected, nonzero if the IO is deferred. */
static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg)
{
lsi_queue *p;
int i;
for (i = 0; i < s->active_commands; i++) {
p = &s->queue[i];
if (p->tag == tag) {
if (p->pending) {
BADF("Multiple IO pending for tag %d\n", tag);
}
p->pending = arg;
if (s->waiting == 1) {
/* Reselect device. */
lsi_reselect(s, tag);
return 0;
} else {
DPRINTF("Queueing IO tag=0x%x\n", tag);
p->pending = arg;
return 1;
}
}
}
BADF("IO with unknown tag %d\n", tag);
return 1;
}
/* Callback to indicate that the SCSI layer has completed a transfer. */
static void lsi_command_complete(void *opaque, int reason, uint32_t tag,
uint32_t arg)
{
LSIState *s = (LSIState *)opaque;
int out;
out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
if (reason == SCSI_REASON_DONE) {
DPRINTF("Command complete sense=%d\n", (int)arg);
s->sense = arg;
if (s->waiting && s->dbc != 0) {
/* Raise phase mismatch for short transfers. */
lsi_bad_phase(s, out, PHASE_ST);
} else {
lsi_set_phase(s, PHASE_ST);
}
lsi_resume_script(s);
return;
}
if (s->waiting == 1 || tag != s->current_tag) {
if (lsi_queue_tag(s, tag, arg))
return;
}
DPRINTF("Data ready tag=0x%x len=%d\n", tag, arg);
s->current_dma_len = arg;
if (!s->waiting)
return;
if (s->waiting == 1 || s->dbc == 0) {
lsi_resume_script(s);
} else {
lsi_do_dma(s, out);
}
}
static void lsi_do_command(LSIState *s)
{
@@ -451,36 +632,37 @@ static void lsi_do_command(LSIState *s)
s->dbc = 16;
cpu_physical_memory_read(s->dnad, buf, s->dbc);
s->sfbr = buf[0];
n = scsi_send_command(s->current_dev, 0, buf, s->current_lun);
n = scsi_send_command(s->current_dev, s->current_tag, buf, s->current_lun);
if (n > 0) {
s->data_len = n;
lsi_set_phase(s, PHASE_DI);
scsi_read_data(s->current_dev, s->current_tag);
} else if (n < 0) {
s->data_len = -n;
lsi_set_phase(s, PHASE_DO);
scsi_write_data(s->current_dev, s->current_tag);
}
if (n && s->current_dma_len == 0) {
/* Command did not complete immediately so disconnect. */
lsi_add_msg_byte(s, 2); /* SAVE DATA POINTER */
lsi_add_msg_byte(s, 4); /* DISCONNECT */
lsi_set_phase(s, PHASE_MI);
s->msg_action = 1;
lsi_queue_command(s);
}
}
static void lsi_command_complete(void *opaque, uint32_t tag, int sense)
{
LSIState *s = (LSIState *)opaque;
DPRINTF("Command complete sense=%d\n", sense);
s->sense = sense;
lsi_set_phase(s, PHASE_ST);
}
static void lsi_do_status(LSIState *s)
{
uint8_t sense;
DPRINTF("Get status len=%d sense=%d\n", s->dbc, s->sense);
if (s->dbc != 1)
BADF("Bad Status move\n");
s->dbc = 1;
s->msg = s->sense;
cpu_physical_memory_write(s->dnad, &s->msg, 1);
s->sfbr = s->msg;
sense = s->sense;
s->sfbr = sense;
cpu_physical_memory_write(s->dnad, &sense, 1);
lsi_set_phase(s, PHASE_MI);
s->msg = 0; /* COMMAND COMPLETE */
s->msg_action = 1;
lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */
}
static void lsi_disconnect(LSIState *s)
@@ -491,55 +673,114 @@ static void lsi_disconnect(LSIState *s)
static void lsi_do_msgin(LSIState *s)
{
DPRINTF("Message in len=%d\n", s->dbc);
s->dbc = 1;
s->sfbr = s->msg;
cpu_physical_memory_write(s->dnad, &s->msg, 1);
if (s->msg == 0) {
lsi_disconnect(s);
int len;
DPRINTF("Message in len=%d/%d\n", s->dbc, s->msg_len);
s->sfbr = s->msg[0];
len = s->msg_len;
if (len > s->dbc)
len = s->dbc;
cpu_physical_memory_write(s->dnad, s->msg, len);
/* Linux drivers rely on the last byte being in the SIDL. */
s->sidl = s->msg[len - 1];
s->msg_len -= len;
if (s->msg_len) {
memmove(s->msg, s->msg + len, s->msg_len);
} else {
/* ??? Check if ATN (not yet implemented) is asserted and maybe
switch to PHASE_MO. */
lsi_set_phase(s, PHASE_CMD);
switch (s->msg_action) {
case 0:
lsi_set_phase(s, PHASE_CMD);
break;
case 1:
lsi_disconnect(s);
break;
case 2:
lsi_set_phase(s, PHASE_DO);
break;
case 3:
lsi_set_phase(s, PHASE_DI);
break;
default:
abort();
}
}
}
/* Read the next byte during a MSGOUT phase. */
static uint8_t lsi_get_msgbyte(LSIState *s)
{
uint8_t data;
cpu_physical_memory_read(s->dnad, &data, 1);
s->dnad++;
s->dbc--;
return data;
}
static void lsi_do_msgout(LSIState *s)
{
uint8_t msg;
int len;
DPRINTF("MSG out len=%d\n", s->dbc);
if (s->dbc != 1) {
/* Multibyte messages not implemented. */
s->msg = 7; /* MESSAGE REJECT */
//s->dbc = 1;
//lsi_bad_phase(s, 1, PHASE_MI);
lsi_set_phase(s, PHASE_MI);
return;
}
cpu_physical_memory_read(s->dnad, &msg, 1);
s->sfbr = msg;
s->dnad++;
while (s->dbc) {
msg = lsi_get_msgbyte(s);
s->sfbr = msg;
switch (msg) {
case 0x00:
DPRINTF("Got Disconnect\n");
lsi_disconnect(s);
return;
case 0x08:
DPRINTF("Got No Operation\n");
lsi_set_phase(s, PHASE_CMD);
return;
switch (msg) {
case 0x00:
DPRINTF("MSG: Disconnect\n");
lsi_disconnect(s);
break;
case 0x08:
DPRINTF("MSG: No Operation\n");
lsi_set_phase(s, PHASE_CMD);
break;
case 0x01:
len = lsi_get_msgbyte(s);
msg = lsi_get_msgbyte(s);
DPRINTF("Extended message 0x%x (len %d)\n", msg, len);
switch (msg) {
case 1:
DPRINTF("SDTR (ignored)\n");
s->dbc -= 2;
break;
case 3:
DPRINTF("WDTR (ignored)\n");
s->dbc -= 1;
break;
default:
goto bad;
}
break;
case 0x20: /* SIMPLE queue */
s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
DPRINTF("SIMPLE queue tag=0x%x\n", s->current_tag & 0xff);
break;
case 0x21: /* HEAD of queue */
BADF("HEAD queue not implemented\n");
s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
break;
case 0x22: /* ORDERED queue */
BADF("ORDERED queue not implemented\n");
s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
break;
default:
if ((msg & 0x80) == 0) {
goto bad;
}
s->current_lun = msg & 7;
DPRINTF("Select LUN %d\n", s->current_lun);
lsi_set_phase(s, PHASE_CMD);
break;
}
}
if ((msg & 0x80) == 0) {
DPRINTF("Unimplemented message 0x%d\n", msg);
s->msg = 7; /* MESSAGE REJECT */
lsi_bad_phase(s, 1, PHASE_MI);
return;
}
s->current_lun = msg & 7;
DPRINTF("Select LUN %d\n", s->current_lun);
lsi_set_phase(s, PHASE_CMD);
return;
bad:
BADF("Unimplemented message 0x%02x\n", msg);
lsi_set_phase(s, PHASE_MI);
lsi_add_msg_byte(s, 7); /* MESSAGE REJECT */
s->msg_action = 0;
}
/* Sign extend a 24-bit value. */
@@ -564,6 +805,23 @@ static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count)
}
}
static void lsi_wait_reselect(LSIState *s)
{
int i;
DPRINTF("Wait Reselect\n");
if (s->current_dma_len)
BADF("Reselect with pending DMA\n");
for (i = 0; i < s->active_commands; i++) {
if (s->queue[i].pending) {
lsi_reselect(s, s->queue[i].tag);
break;
}
}
if (s->current_dma_len == 0) {
s->waiting = 1;
}
}
static void lsi_execute_script(LSIState *s)
{
uint32_t insn;
@@ -608,10 +866,16 @@ again:
s->dnad = addr;
switch (s->sstat1 & 0x7) {
case PHASE_DO:
s->waiting = 2;
lsi_do_dma(s, 1);
if (s->waiting)
s->waiting = 3;
break;
case PHASE_DI:
s->waiting = 2;
lsi_do_dma(s, 0);
if (s->waiting)
s->waiting = 3;
break;
case PHASE_CMD:
lsi_do_command(s);
@@ -655,9 +919,13 @@ again:
s->dnad = addr;
switch (opcode) {
case 0: /* Select */
s->sdid = id;
if (s->current_dma_len && (s->ssid & 0xf) == id) {
DPRINTF("Already reselected by target %d\n", id);
break;
}
s->sstat0 |= LSI_SSTAT0_WOA;
s->scntl1 &= ~LSI_SCNTL1_IARB;
s->sdid = id;
if (id >= LSI_MAX_DEVS || !s->scsi_dev[id]) {
DPRINTF("Selected absent target %d\n", id);
lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO);
@@ -670,6 +938,7 @@ again:
it only applies in low-level mode (unimplemented).
lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */
s->current_dev = s->scsi_dev[id];
s->current_tag = id << 8;
s->scntl1 |= LSI_SCNTL1_CON;
if (insn & (1 << 3)) {
s->socl |= LSI_SOCL_ATN;
@@ -681,8 +950,7 @@ again:
s->scntl1 &= ~LSI_SCNTL1_CON;
break;
case 2: /* Wait Reselect */
DPRINTF("Wait Reselect\n");
s->waiting = 1;
lsi_wait_reselect(s);
break;
case 3: /* Set */
DPRINTF("Set%s%s%s%s\n",
@@ -731,9 +999,9 @@ again:
data8 = (insn >> 8) & 0xff;
opcode = (insn >> 27) & 7;
operator = (insn >> 24) & 7;
DPRINTF("%s reg 0x%x %s data8 %d%s\n",
DPRINTF("%s reg 0x%x %s data8=0x%02x sfbr=0x%02x%s\n",
opcode_names[opcode - 5], reg,
operator_names[operator], data8,
operator_names[operator], data8, s->sfbr,
(insn & (1 << 23)) ? " SFBR" : "");
op0 = op1 = 0;
switch (opcode) {
@@ -899,8 +1167,9 @@ again:
n = (insn & 7);
reg = (insn >> 16) & 0xff;
if (insn & (1 << 24)) {
DPRINTF("Load reg 0x%x size %d addr 0x%08x\n", reg, n, addr);
cpu_physical_memory_read(addr, data, n);
DPRINTF("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n,
addr, *(int *)data);
for (i = 0; i < n; i++) {
lsi_reg_writeb(s, reg + i, data[i]);
}
@@ -953,6 +1222,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
return s->sdid;
case 0x07: /* GPREG0 */
return 0x7f;
case 0xa: /* SSID */
return s->ssid;
case 0xb: /* SBCL */
/* ??? This is not correct. However it's (hopefully) only
used for diagnostics, so should be ok. */
@@ -1041,13 +1312,22 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
return s->stest2;
case 0x4f: /* STEST3 */
return s->stest3;
case 0x50: /* SIDL */
/* This is needed by the linux drivers. We currently only update it
during the MSG IN phase. */
return s->sidl;
case 0x52: /* STEST4 */
return 0xe0;
case 0x56: /* CCNTL0 */
return s->ccntl0;
case 0x57: /* CCNTL1 */
return s->ccntl1;
case 0x58: case 0x59: /* SBDL */
case 0x58: /* SBDL */
/* Some drivers peek at the data bus during the MSG IN phase. */
if ((s->sstat1 & PHASE_MASK) == PHASE_MI)
return s->msg[0];
return 0;
case 0x59: /* SBDL high */
return 0;
CASE_GET_REG32(mmrs, 0xa0)
CASE_GET_REG32(mmws, 0xa4)
@@ -1119,8 +1399,18 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
case 0x05: /* SXFER */
s->sxfer = val;
break;
case 0x06: /* SDID */
if ((val & 0xf) != (s->ssid & 0xf))
BADF("Destination ID does not match SSID\n");
s->sdid = val & 0xf;
break;
case 0x07: /* GPREG0 */
break;
case 0x08: /* SFBR */
/* The CPU is not allowed to write to this register. However the
SCRIPTS register move instructions are. */
s->sfbr = val;
break;
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
/* Linux writes to these readonly registers on startup. */
return;
@@ -1134,7 +1424,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
s->istat0 &= ~LSI_ISTAT0_INTF;
lsi_update_irq(s);
}
if (s->waiting && val & LSI_ISTAT0_SIGP) {
if (s->waiting == 1 && val & LSI_ISTAT0_SIGP) {
DPRINTF("Woken by SIGP\n");
s->waiting = 0;
s->dsp = s->dnad;
@@ -1531,7 +1821,7 @@ void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id)
scsi_disk_destroy(s->scsi_dev[id]);
}
DPRINTF("Attaching block device %d\n", id);
s->scsi_dev[id] = scsi_disk_init(bd, lsi_command_complete, s);
s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
}
void *lsi_scsi_init(PCIBus *bus, int devfn)
@@ -1563,6 +1853,9 @@ void *lsi_scsi_init(PCIBus *bus, int devfn)
PCI_ADDRESS_SPACE_MEM, lsi_mmio_mapfunc);
pci_register_io_region((struct PCIDevice *)s, 2, 0x2000,
PCI_ADDRESS_SPACE_MEM, lsi_ram_mapfunc);
s->queue = qemu_malloc(sizeof(lsi_queue));
s->queue_len = 1;
s->active_commands = 0;
lsi_soft_reset(s);
+25
View File
@@ -380,6 +380,29 @@ void rtc_set_date(RTCState *s, const struct tm *tm)
rtc_copy_date(s);
}
/* PC cmos mappings */
#define REG_IBM_CENTURY_BYTE 0x32
#define REG_IBM_PS2_CENTURY_BYTE 0x37
void rtc_set_date_from_host(RTCState *s)
{
time_t ti;
struct tm *tm;
int val;
/* set the CMOS date */
time(&ti);
if (rtc_utc)
tm = gmtime(&ti);
else
tm = localtime(&ti);
rtc_set_date(s, tm);
val = to_bcd(s, (tm->tm_year / 100) + 19);
rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
}
static void rtc_save(QEMUFile *f, void *opaque)
{
RTCState *s = opaque;
@@ -444,6 +467,8 @@ RTCState *rtc_init(int base, int irq)
s->cmos_data[RTC_REG_C] = 0x00;
s->cmos_data[RTC_REG_D] = 0x80;
rtc_set_date_from_host(s);
s->periodic_timer = qemu_new_timer(vm_clock,
rtc_periodic_timer, s);
s->second_timer = qemu_new_timer(vm_clock,
+39
View File
@@ -0,0 +1,39 @@
#include "vl.h"
#include "cpu.h"
/* Raise IRQ to CPU if necessary. It must be called every time the active
IRQ may change */
void cpu_mips_update_irq(CPUState *env)
{
if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
(env->CP0_Status & (1 << CP0St_IE)) &&
!(env->hflags & MIPS_HFLAG_EXL) &&
!(env->hflags & MIPS_HFLAG_ERL) &&
!(env->hflags & MIPS_HFLAG_DM)) {
if (! (env->interrupt_request & CPU_INTERRUPT_HARD)) {
cpu_interrupt(env, CPU_INTERRUPT_HARD);
}
} else {
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
}
}
void cpu_mips_irq_request(void *opaque, int irq, int level)
{
CPUState *env = first_cpu;
uint32_t mask;
if (irq >= 16)
return;
mask = 1 << (irq + CP0Ca_IP);
if (level) {
env->CP0_Cause |= mask;
} else {
env->CP0_Cause &= ~mask;
}
cpu_mips_update_irq(env);
}
+590
View File
@@ -0,0 +1,590 @@
/*
* QEMU Malta board support
*
* Copyright (c) 2006 Aurelien Jarno
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
#ifdef TARGET_WORDS_BIGENDIAN
#define BIOS_FILENAME "mips_bios.bin"
#else
#define BIOS_FILENAME "mipsel_bios.bin"
#endif
#ifdef MIPS_HAS_MIPS64
#define INITRD_LOAD_ADDR (int64_t)0x80800000
#else
#define INITRD_LOAD_ADDR (int32_t)0x80800000
#endif
#define ENVP_ADDR (int32_t)0x80002000
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
#define ENVP_NB_ENTRIES 16
#define ENVP_ENTRY_SIZE 256
extern FILE *logfile;
typedef struct {
uint32_t leds;
uint32_t brk;
uint32_t gpout;
uint32_t i2coe;
uint32_t i2cout;
uint32_t i2csel;
CharDriverState *display;
char display_text[9];
} MaltaFPGAState;
static PITState *pit;
/* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
static void pic_irq_request(void *opaque, int level)
{
cpu_mips_irq_request(opaque, 2, level);
}
/* Malta FPGA */
static void malta_fpga_update_display(void *opaque)
{
char leds_text[9];
int i;
MaltaFPGAState *s = opaque;
for (i = 7 ; i >= 0 ; i--) {
if (s->leds & (1 << i))
leds_text[i] = '#';
else
leds_text[i] = ' ';
}
leds_text[8] = '\0';
qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
}
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
{
MaltaFPGAState *s = opaque;
uint32_t val = 0;
uint32_t saddr;
saddr = (addr & 0xfffff);
switch (saddr) {
/* SWITCH Register */
case 0x00200:
val = 0x00000000; /* All switches closed */
break;
/* STATUS Register */
case 0x00208:
#ifdef TARGET_WORDS_BIGENDIAN
val = 0x00000012;
#else
val = 0x00000010;
#endif
break;
/* JMPRS Register */
case 0x00210:
val = 0x00;
break;
/* LEDBAR Register */
case 0x00408:
val = s->leds;
break;
/* BRKRES Register */
case 0x00508:
val = s->brk;
break;
/* GPOUT Register */
case 0x00a00:
val = s->gpout;
break;
/* XXX: implement a real I2C controller */
/* GPINP Register */
case 0x00a08:
/* IN = OUT until a real I2C control is implemented */
if (s->i2csel)
val = s->i2cout;
else
val = 0x00;
break;
/* I2CINP Register */
case 0x00b00:
val = 0x00000003;
break;
/* I2COE Register */
case 0x00b08:
val = s->i2coe;
break;
/* I2COUT Register */
case 0x00b10:
val = s->i2cout;
break;
/* I2CSEL Register */
case 0x00b18:
val = s->i2cout;
break;
default:
#if 0
printf ("malta_fpga_read: Bad register offset 0x" TLSZ "\n",
addr);
#endif
break;
}
return val;
}
static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
MaltaFPGAState *s = opaque;
uint32_t saddr;
saddr = (addr & 0xfffff);
switch (saddr) {
/* SWITCH Register */
case 0x00200:
break;
/* JMPRS Register */
case 0x00210:
break;
/* LEDBAR Register */
/* XXX: implement a 8-LED array */
case 0x00408:
s->leds = val & 0xff;
break;
/* ASCIIWORD Register */
case 0x00410:
snprintf(s->display_text, 9, "%08X", val);
malta_fpga_update_display(s);
break;
/* ASCIIPOS0 to ASCIIPOS7 Registers */
case 0x00418:
case 0x00420:
case 0x00428:
case 0x00430:
case 0x00438:
case 0x00440:
case 0x00448:
case 0x00450:
s->display_text[(saddr - 0x00418) >> 3] = (char) val;
malta_fpga_update_display(s);
break;
/* SOFTRES Register */
case 0x00500:
if (val == 0x42)
qemu_system_reset_request ();
break;
/* BRKRES Register */
case 0x00508:
s->brk = val & 0xff;
break;
/* GPOUT Register */
case 0x00a00:
s->gpout = val & 0xff;
break;
/* I2COE Register */
case 0x00b08:
s->i2coe = val & 0x03;
break;
/* I2COUT Register */
case 0x00b10:
s->i2cout = val & 0x03;
break;
/* I2CSEL Register */
case 0x00b18:
s->i2cout = val & 0x01;
break;
default:
#if 0
printf ("malta_fpga_write: Bad register offset 0x" TLSZ "\n",
addr);
#endif
break;
}
}
static CPUReadMemoryFunc *malta_fpga_read[] = {
malta_fpga_readl,
malta_fpga_readl,
malta_fpga_readl
};
static CPUWriteMemoryFunc *malta_fpga_write[] = {
malta_fpga_writel,
malta_fpga_writel,
malta_fpga_writel
};
void malta_fpga_reset(void *opaque)
{
MaltaFPGAState *s = opaque;
s->leds = 0x00;
s->brk = 0x0a;
s->gpout = 0x00;
s->i2coe = 0x0;
s->i2cout = 0x3;
s->i2csel = 0x1;
s->display_text[8] = '\0';
snprintf(s->display_text, 9, " ");
malta_fpga_update_display(s);
}
MaltaFPGAState *malta_fpga_init(target_phys_addr_t base)
{
MaltaFPGAState *s;
int malta;
s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
malta = cpu_register_io_memory(0, malta_fpga_read,
malta_fpga_write, s);
cpu_register_physical_memory(base, 0x100000, malta);
s->display = qemu_chr_open("vc");
qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
qemu_chr_printf(s->display, "+--------+\r\n");
qemu_chr_printf(s->display, "+ +\r\n");
qemu_chr_printf(s->display, "+--------+\r\n");
qemu_chr_printf(s->display, "\n");
qemu_chr_printf(s->display, "Malta ASCII\r\n");
qemu_chr_printf(s->display, "+--------+\r\n");
qemu_chr_printf(s->display, "+ +\r\n");
qemu_chr_printf(s->display, "+--------+\r\n");
malta_fpga_reset(s);
qemu_register_reset(malta_fpga_reset, s);
return s;
}
/* Audio support */
#ifdef HAS_AUDIO
static void audio_init (PCIBus *pci_bus)
{
struct soundhw *c;
int audio_enabled = 0;
for (c = soundhw; !audio_enabled && c->name; ++c) {
audio_enabled = c->enabled;
}
if (audio_enabled) {
AudioState *s;
s = AUD_init ();
if (s) {
for (c = soundhw; c->name; ++c) {
if (c->enabled) {
if (c->isa) {
fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);
exit(1);
}
else {
if (pci_bus) {
c->init.init_pci (pci_bus, s);
}
}
}
}
}
}
}
#endif
/* Network support */
static void network_init (PCIBus *pci_bus)
{
int i;
NICInfo *nd;
for(i = 0; i < nb_nics; i++) {
nd = &nd_table[i];
if (!nd->model) {
nd->model = "pcnet";
}
if (i == 0 && strcmp(nd->model, "pcnet") == 0) {
/* The malta board has a PCNet card using PCI SLOT 11 */
pci_nic_init(pci_bus, nd, 88);
} else {
pci_nic_init(pci_bus, nd, -1);
}
}
}
/* ROM and pseudo bootloader
The following code implements a very very simple bootloader. It first
loads the registers a0 to a3 to the values expected by the OS, and
then jump at the kernel address.
The bootloader should pass the locations of the kernel arguments and
environment variables tables. Those tables contain the 32-bit address
of NULL terminated strings. The environment variables table should be
terminated by a NULL address.
For a simpler implementation, the number of kernel arguments is fixed
to two (the name of the kernel and the command line), and the two
tables are actually the same one.
The registers a0 to a3 should contain the following values:
a0 - number of kernel arguments
a1 - 32-bit address of the kernel arguments table
a2 - 32-bit address of the environment variables table
a3 - RAM size in bytes
*/
static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_addr)
{
uint32_t *p;
/* Small bootloader */
p = (uint32_t *) (phys_ram_base + bios_offset);
stl_raw(p++, 0x0bf00010); /* j 0x1fc00040 */
stl_raw(p++, 0x00000000); /* nop */
/* Second part of the bootloader */
p = (uint32_t *) (phys_ram_base + bios_offset + 0x040);
stl_raw(p++, 0x3c040000); /* lui a0, 0 */
stl_raw(p++, 0x34840002); /* ori a0, a0, 2 */
stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); /* lui a1, high(ENVP_ADDR) */
stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); /* ori a1, a0, low(ENVP_ADDR) */
stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
stl_raw(p++, 0x3c070000 | (env->ram_size >> 16)); /* lui a3, high(env->ram_size) */
stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff)); /* ori a3, a3, low(env->ram_size) */
stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff)); /* lui ra, high(kernel_addr) */;
stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff)); /* ori ra, ra, low(kernel_addr) */
stl_raw(p++, 0x03e00008); /* jr ra */
stl_raw(p++, 0x00000000); /* nop */
}
static void prom_set(int index, const char *string, ...)
{
va_list ap;
int32_t *p;
int32_t table_addr;
char *s;
if (index >= ENVP_NB_ENTRIES)
return;
p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
p += index;
if (string == NULL) {
stl_raw(p, 0);
return;
}
table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
stl_raw(p, table_addr);
va_start(ap, string);
vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
va_end(ap);
}
/* Kernel */
static int64_t load_kernel (CPUState *env)
{
int64_t kernel_addr = 0;
int index = 0;
long initrd_size;
if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND, &kernel_addr) < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
env->kernel_filename);
exit(1);
}
/* load initrd */
initrd_size = 0;
if (env->initrd_filename) {
initrd_size = load_image(env->initrd_filename,
phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
if (initrd_size == (target_ulong) -1) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
env->initrd_filename);
exit(1);
}
}
/* Store command line. */
prom_set(index++, env->kernel_filename);
if (initrd_size > 0)
prom_set(index++, "rd_start=0x" TLSZ " rd_size=%li %s", INITRD_LOAD_ADDR, initrd_size, env->kernel_cmdline);
else
prom_set(index++, env->kernel_cmdline);
/* Setup minimum environment variables */
prom_set(index++, "memsize");
prom_set(index++, "%i", env->ram_size);
prom_set(index++, "modetty0");
prom_set(index++, "38400n8r");
prom_set(index++, NULL);
return kernel_addr;
}
static void main_cpu_reset(void *opaque)
{
CPUState *env = opaque;
cpu_reset(env);
/* The bootload does not need to be rewritten as it is located in a
read only location. The kernel location and the arguments table
location does not change. */
if (env->kernel_filename)
load_kernel (env);
}
void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
char buf[1024];
unsigned long bios_offset;
int64_t kernel_addr;
PCIBus *pci_bus;
CPUState *env;
RTCState *rtc_state;
/* fdctrl_t *floppy_controller; */
MaltaFPGAState *malta_fpga;
int ret;
env = cpu_init();
register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
qemu_register_reset(main_cpu_reset, env);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
/* Map the bios at two physical locations, as on the real board */
bios_offset = ram_size + vga_ram_size;
cpu_register_physical_memory(0x1e000000LL,
BIOS_SIZE, bios_offset | IO_MEM_ROM);
cpu_register_physical_memory(0x1fc00000LL,
BIOS_SIZE, bios_offset | IO_MEM_ROM);
/* Load a BIOS image except if a kernel image has been specified. In
the later case, just write a small bootloader to the flash
location. */
if (kernel_filename) {
env->ram_size = ram_size;
env->kernel_filename = kernel_filename;
env->kernel_cmdline = kernel_cmdline;
env->initrd_filename = initrd_filename;
kernel_addr = load_kernel(env);
write_bootloader(env, bios_offset, kernel_addr);
} else {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
ret = load_image(buf, phys_ram_base + bios_offset);
if (ret != BIOS_SIZE) {
fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
buf);
exit(1);
}
}
/* Board ID = 0x420 (Malta Board with CoreLV)
XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
map to the board ID. */
stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
/* Init internal devices */
cpu_mips_clock_init(env);
cpu_mips_irqctrl_init();
/* FPGA */
malta_fpga = malta_fpga_init(0x1f000000LL);
/* Interrupt controller */
isa_pic = pic_init(pic_irq_request, env);
/* Northbridge */
pci_bus = pci_gt64120_init(isa_pic);
/* Southbridge */
piix4_init(pci_bus, 80);
pci_piix3_ide_init(pci_bus, bs_table, 81);
usb_uhci_init(pci_bus, 82);
piix4_pm_init(pci_bus, 83);
pit = pit_init(0x40, 0);
DMA_init(0);
/* Super I/O */
kbd_init();
rtc_state = rtc_init(0x70, 8);
serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
parallel_init(0x378, 7, parallel_hds[0]);
/* XXX: The floppy controller does not work correctly, something is
probably wrong.
floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); */
/* Sound card */
#ifdef HAS_AUDIO
audio_init(pci_bus);
#endif
/* Network card */
network_init(pci_bus);
}
QEMUMachine mips_malta_machine = {
"malta",
"MIPS Malta Core LV",
mips_malta_init,
};
+144 -214
View File
@@ -1,222 +1,165 @@
/*
* QEMU/MIPS pseudo-board
*
* emulates a simple machine with ISA-like bus.
* ISA IO space mapped to the 0x14000000 (PHYS) and
* ISA memory at the 0x10000000 (PHYS, 16Mb in size).
* All peripherial devices are attached to this "bus" with
* the standard PC ISA addresses.
*/
#include "vl.h"
#ifdef TARGET_WORDS_BIGENDIAN
#define BIOS_FILENAME "mips_bios.bin"
//#define BIOS_FILENAME "system.bin"
#define KERNEL_LOAD_ADDR 0x80010000
#define INITRD_LOAD_ADDR 0x80800000
#else
#define BIOS_FILENAME "mipsel_bios.bin"
#endif
#define VIRT_TO_PHYS_ADDEND (-0x80000000LL)
#ifdef MIPS_HAS_MIPS64
#define INITRD_LOAD_ADDR (int64_t)(int32_t)0x80800000
#else
#define INITRD_LOAD_ADDR (int32_t)0x80800000
#endif
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
static const int ide_irq[2] = { 14, 15 };
static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
extern FILE *logfile;
static PITState *pit;
static PITState *pit; /* PIT i8254 */
/*i8254 PIT is attached to the IRQ0 at PIC i8259 */
/*The PIC is attached to the MIPS CPU INT0 pin */
static void pic_irq_request(void *opaque, int level)
{
CPUState *env = first_cpu;
if (level) {
env->CP0_Cause |= 0x00000400;
cpu_interrupt(env, CPU_INTERRUPT_HARD);
cpu_mips_irq_request(opaque, 2, level);
}
static void mips_qemu_writel (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
if ((addr & 0xffff) == 0 && val == 42)
qemu_system_reset_request ();
else if ((addr & 0xffff) == 4 && val == 42)
qemu_system_shutdown_request ();
}
static uint32_t mips_qemu_readl (void *opaque, target_phys_addr_t addr)
{
return 0;
}
static CPUWriteMemoryFunc *mips_qemu_write[] = {
&mips_qemu_writel,
&mips_qemu_writel,
&mips_qemu_writel,
};
static CPUReadMemoryFunc *mips_qemu_read[] = {
&mips_qemu_readl,
&mips_qemu_readl,
&mips_qemu_readl,
};
static int mips_qemu_iomemtype = 0;
void load_kernel (CPUState *env, int ram_size, const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename)
{
int64_t entry = 0;
long kernel_size, initrd_size;
kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry;
env->PC = entry;
} else {
env->CP0_Cause &= ~0x00000400;
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
}
void cpu_mips_irqctrl_init (void)
{
}
/* XXX: do not use a global */
uint32_t cpu_mips_get_random (CPUState *env)
{
static uint32_t seed = 0;
uint32_t idx;
seed = seed * 314159 + 1;
idx = (seed >> 16) % (MIPS_TLB_NB - env->CP0_Wired) + env->CP0_Wired;
return idx;
}
/* MIPS R4K timer */
uint32_t cpu_mips_get_count (CPUState *env)
{
return env->CP0_Count +
(uint32_t)muldiv64(qemu_get_clock(vm_clock),
100 * 1000 * 1000, ticks_per_sec);
}
static void cpu_mips_update_count (CPUState *env, uint32_t count,
uint32_t compare)
{
uint64_t now, next;
uint32_t tmp;
tmp = count;
if (count == compare)
tmp++;
now = qemu_get_clock(vm_clock);
next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000);
if (next == now)
next++;
#if 0
if (logfile) {
fprintf(logfile, "%s: 0x%08" PRIx64 " %08x %08x => 0x%08" PRIx64 "\n",
__func__, now, count, compare, next - now);
/* load initrd */
initrd_size = 0;
if (initrd_filename) {
initrd_size = load_image(initrd_filename,
phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
if (initrd_size == (target_ulong) -1) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
}
#endif
/* Store new count and compare registers */
env->CP0_Compare = compare;
env->CP0_Count =
count - (uint32_t)muldiv64(now, 100 * 1000 * 1000, ticks_per_sec);
/* Adjust timer */
qemu_mod_timer(env->timer, next);
}
void cpu_mips_store_count (CPUState *env, uint32_t value)
{
cpu_mips_update_count(env, value, env->CP0_Compare);
}
void cpu_mips_store_compare (CPUState *env, uint32_t value)
{
cpu_mips_update_count(env, cpu_mips_get_count(env), value);
env->CP0_Cause &= ~0x00008000;
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
}
static void mips_timer_cb (void *opaque)
{
CPUState *env;
env = opaque;
#if 0
if (logfile) {
fprintf(logfile, "%s\n", __func__);
/* Store command line. */
if (initrd_size > 0) {
int ret;
ret = sprintf(phys_ram_base + (16 << 20) - 256,
"rd_start=0x" TLSZ " rd_size=%li ",
INITRD_LOAD_ADDR,
initrd_size);
strcpy (phys_ram_base + (16 << 20) - 256 + ret, kernel_cmdline);
}
#endif
cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
env->CP0_Cause |= 0x00008000;
cpu_interrupt(env, CPU_INTERRUPT_HARD);
else {
strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
}
*(int32_t *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
*(int32_t *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
}
void cpu_mips_clock_init (CPUState *env)
static void main_cpu_reset(void *opaque)
{
env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
env->CP0_Compare = 0;
cpu_mips_update_count(env, 1, 0);
CPUState *env = opaque;
cpu_reset(env);
if (env->kernel_filename)
load_kernel (env, env->ram_size, env->kernel_filename,
env->kernel_cmdline, env->initrd_filename);
}
static void io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
#endif
cpu_outb(NULL, addr & 0xffff, value);
}
static uint32_t io_readb (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inb(NULL, addr & 0xffff);
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
#endif
return ret;
}
static void io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
#endif
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap16(value);
#endif
cpu_outw(NULL, addr & 0xffff, value);
}
static uint32_t io_readw (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inw(NULL, addr & 0xffff);
#ifdef TARGET_WORDS_BIGENDIAN
ret = bswap16(ret);
#endif
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
#endif
return ret;
}
static void io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
#endif
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap32(value);
#endif
cpu_outl(NULL, addr & 0xffff, value);
}
static uint32_t io_readl (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inl(NULL, addr & 0xffff);
#ifdef TARGET_WORDS_BIGENDIAN
ret = bswap32(ret);
#endif
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
#endif
return ret;
}
CPUWriteMemoryFunc *io_write[] = {
&io_writeb,
&io_writew,
&io_writel,
};
CPUReadMemoryFunc *io_read[] = {
&io_readb,
&io_readw,
&io_readl,
};
void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
char buf[1024];
int64_t entry = 0;
unsigned long bios_offset;
int io_memory;
int ret;
int bios_size;
CPUState *env;
long kernel_size;
static RTCState *rtc_state;
int i;
env = cpu_init();
register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
qemu_register_reset(main_cpu_reset, env);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
if (!mips_qemu_iomemtype) {
mips_qemu_iomemtype = cpu_register_io_memory(0, mips_qemu_read,
mips_qemu_write, NULL);
}
cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype);
/* Try to load a BIOS image. If this fails, we continue regardless,
but initialize the hardware ourselves. When a kernel gets
preloaded we also initialize the hardware, since the BIOS wasn't
run. */
bios_offset = ram_size + vga_ram_size;
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
ret = load_image(buf, phys_ram_base + bios_offset);
if (ret == BIOS_SIZE) {
cpu_register_physical_memory((uint32_t)(0x1fc00000),
bios_size = load_image(buf, phys_ram_base + bios_offset);
if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
cpu_register_physical_memory(0x1fc00000,
BIOS_SIZE, bios_offset | IO_MEM_ROM);
} else {
/* not fatal */
@@ -224,54 +167,37 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
buf);
}
kernel_size = 0;
if (kernel_filename) {
kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry);
if (kernel_size >= 0)
env->PC = entry;
else {
kernel_size = load_image(kernel_filename,
phys_ram_base + KERNEL_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
env->PC = KERNEL_LOAD_ADDR;
}
/* load initrd */
if (initrd_filename) {
if (load_image(initrd_filename,
phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND)
== (target_ulong) -1) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
}
/* Store command line. */
strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
/* FIXME: little endian support */
*(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
*(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
load_kernel (env, ram_size, kernel_filename, kernel_cmdline,
initrd_filename);
env->ram_size = ram_size;
env->kernel_filename = kernel_filename;
env->kernel_cmdline = kernel_cmdline;
env->initrd_filename = initrd_filename;
}
/* Init internal devices */
/* Init CPU internal devices */
cpu_mips_clock_init(env);
cpu_mips_irqctrl_init();
rtc_state = rtc_init(0x70, 8);
/* Register 64 KB of ISA IO space at 0x14000000 */
io_memory = cpu_register_io_memory(0, io_read, io_write, NULL);
cpu_register_physical_memory(0x14000000, 0x00010000, io_memory);
isa_mmio_init(0x14000000, 0x00010000);
isa_mem_base = 0x10000000;
isa_pic = pic_init(pic_irq_request, env);
pit = pit_init(0x40, 0);
serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
vga_initialize(NULL, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size, 0, 0);
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {
serial_init(&pic_set_irq_new, isa_pic,
serial_io[i], serial_irq[i], serial_hds[i]);
}
}
isa_vga_init(ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
if (nd_table[0].vlan) {
if (nd_table[0].model == NULL
@@ -282,6 +208,10 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
exit (1);
}
}
for(i = 0; i < 2; i++)
isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
bs_table[2 * i], bs_table[2 * i + 1]);
}
QEMUMachine mips_machine = {
+83
View File
@@ -0,0 +1,83 @@
#include "vl.h"
void cpu_mips_irqctrl_init (void)
{
}
/* XXX: do not use a global */
uint32_t cpu_mips_get_random (CPUState *env)
{
static uint32_t seed = 0;
uint32_t idx;
seed = seed * 314159 + 1;
idx = (seed >> 16) % (MIPS_TLB_NB - env->CP0_Wired) + env->CP0_Wired;
return idx;
}
/* MIPS R4K timer */
uint32_t cpu_mips_get_count (CPUState *env)
{
return env->CP0_Count +
(uint32_t)muldiv64(qemu_get_clock(vm_clock),
100 * 1000 * 1000, ticks_per_sec);
}
static void cpu_mips_update_count (CPUState *env, uint32_t count,
uint32_t compare)
{
uint64_t now, next;
uint32_t tmp;
tmp = count;
if (count == compare)
tmp++;
now = qemu_get_clock(vm_clock);
next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000);
if (next == now)
next++;
#if 0
if (logfile) {
fprintf(logfile, "%s: 0x%08" PRIx64 " %08x %08x => 0x%08" PRIx64 "\n",
__func__, now, count, compare, next - now);
}
#endif
/* Store new count and compare registers */
env->CP0_Compare = compare;
env->CP0_Count =
count - (uint32_t)muldiv64(now, 100 * 1000 * 1000, ticks_per_sec);
/* Adjust timer */
qemu_mod_timer(env->timer, next);
}
void cpu_mips_store_count (CPUState *env, uint32_t value)
{
cpu_mips_update_count(env, value, env->CP0_Compare);
}
void cpu_mips_store_compare (CPUState *env, uint32_t value)
{
cpu_mips_update_count(env, cpu_mips_get_count(env), value);
cpu_mips_irq_request(env, 7, 0);
}
static void mips_timer_cb (void *opaque)
{
CPUState *env;
env = opaque;
#if 0
if (logfile) {
fprintf(logfile, "%s\n", __func__);
}
#endif
cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
cpu_mips_irq_request(env, 7, 1);
}
void cpu_mips_clock_init (CPUState *env)
{
env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
env->CP0_Compare = 0;
cpu_mips_update_count(env, 1, 0);
}
+20 -11
View File
@@ -312,7 +312,7 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
}
s->curpag = next >> 8;
/* now we can signal we have receive something */
/* now we can signal we have received something */
s->isr |= ENISR_RX;
ne2000_update_irq(s);
}
@@ -648,6 +648,9 @@ static void ne2000_save(QEMUFile* f,void* opaque)
{
NE2000State* s=(NE2000State*)opaque;
if (s->pci_dev)
pci_device_save(s->pci_dev, f);
qemu_put_8s(f, &s->rxcr);
qemu_put_8s(f, &s->cmd);
@@ -673,13 +676,21 @@ static void ne2000_save(QEMUFile* f,void* opaque)
static int ne2000_load(QEMUFile* f,void* opaque,int version_id)
{
NE2000State* s=(NE2000State*)opaque;
int ret;
if (version_id == 2) {
qemu_get_8s(f, &s->rxcr);
} else if (version_id == 1) {
s->rxcr = 0x0c;
} else {
if (version_id > 3)
return -EINVAL;
if (s->pci_dev && version_id >= 3) {
ret = pci_device_load(s->pci_dev, f);
if (ret < 0)
return ret;
}
if (version_id >= 2) {
qemu_get_8s(f, &s->rxcr);
} else {
s->rxcr = 0x0c;
}
qemu_get_8s(f, &s->cmd);
@@ -770,7 +781,7 @@ static void ne2000_map(PCIDevice *pci_dev, int region_num,
register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
}
void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
{
PCINE2000State *d;
NE2000State *s;
@@ -778,7 +789,7 @@ void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
d = (PCINE2000State *)pci_register_device(bus,
"NE2000", sizeof(PCINE2000State),
-1,
devfn,
NULL, NULL);
pci_conf = d->dev.config;
pci_conf[0x00] = 0xec; // Realtek 8029
@@ -810,7 +821,5 @@ void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
s->macaddr[5]);
/* XXX: instance number ? */
register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load,
&d->dev);
register_savevm("ne2000", 0, 3, ne2000_save, ne2000_load, s);
}
+48 -190
View File
@@ -40,6 +40,7 @@ static fdctrl_t *floppy_controller;
static RTCState *rtc_state;
static PITState *pit;
static IOAPICState *ioapic;
static PCIDevice *i440fx_state;
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
{
@@ -73,6 +74,14 @@ uint64_t cpu_get_tsc(CPUX86State *env)
}
}
/* SMM support */
void cpu_smm_update(CPUState *env)
{
if (i440fx_state && env == first_cpu)
i440fx_set_smm(i440fx_state, (env->hflags >> HF_SMM_SHIFT) & 1);
}
/* IRQ handling */
int cpu_get_pic_interrupt(CPUState *env)
{
@@ -102,14 +111,6 @@ static void pic_irq_request(void *opaque, int level)
/* PC cmos mappings */
#define REG_EQUIPMENT_BYTE 0x14
#define REG_IBM_CENTURY_BYTE 0x32
#define REG_IBM_PS2_CENTURY_BYTE 0x37
static inline int to_bcd(RTCState *s, int a)
{
return ((a / 10) << 4) | (a % 10);
}
static int cmos_get_fd_drive_type(int fd0)
{
@@ -158,22 +159,8 @@ static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table
RTCState *s = rtc_state;
int val;
int fd0, fd1, nb;
time_t ti;
struct tm *tm;
int i;
/* set the CMOS date */
time(&ti);
if (rtc_utc)
tm = gmtime(&ti);
else
tm = localtime(&ti);
rtc_set_date(s, tm);
val = to_bcd(s, (tm->tm_year / 100) + 19);
rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
/* various important CMOS locations needed by PC/Bochs bios */
/* memory size */
@@ -398,156 +385,6 @@ static void main_cpu_reset(void *opaque)
cpu_reset(env);
}
/*************************************************/
static void putb(uint8_t **pp, int val)
{
uint8_t *q;
q = *pp;
*q++ = val;
*pp = q;
}
static void putstr(uint8_t **pp, const char *str)
{
uint8_t *q;
q = *pp;
while (*str)
*q++ = *str++;
*pp = q;
}
static void putle16(uint8_t **pp, int val)
{
uint8_t *q;
q = *pp;
*q++ = val;
*q++ = val >> 8;
*pp = q;
}
static void putle32(uint8_t **pp, int val)
{
uint8_t *q;
q = *pp;
*q++ = val;
*q++ = val >> 8;
*q++ = val >> 16;
*q++ = val >> 24;
*pp = q;
}
static int mpf_checksum(const uint8_t *data, int len)
{
int sum, i;
sum = 0;
for(i = 0; i < len; i++)
sum += data[i];
return sum & 0xff;
}
/* Build the Multi Processor table in the BIOS. Same values as Bochs. */
static void bios_add_mptable(uint8_t *bios_data)
{
uint8_t *mp_config_table, *q, *float_pointer_struct;
int ioapic_id, offset, i, len;
if (smp_cpus <= 1)
return;
mp_config_table = bios_data + 0xb000;
q = mp_config_table;
putstr(&q, "PCMP"); /* "PCMP signature */
putle16(&q, 0); /* table length (patched later) */
putb(&q, 4); /* spec rev */
putb(&q, 0); /* checksum (patched later) */
putstr(&q, "QEMUCPU "); /* OEM id */
putstr(&q, "0.1 "); /* vendor id */
putle32(&q, 0); /* OEM table ptr */
putle16(&q, 0); /* OEM table size */
putle16(&q, 20); /* entry count */
putle32(&q, 0xfee00000); /* local APIC addr */
putle16(&q, 0); /* ext table length */
putb(&q, 0); /* ext table checksum */
putb(&q, 0); /* reserved */
for(i = 0; i < smp_cpus; i++) {
putb(&q, 0); /* entry type = processor */
putb(&q, i); /* APIC id */
putb(&q, 0x11); /* local APIC version number */
if (i == 0)
putb(&q, 3); /* cpu flags: enabled, bootstrap cpu */
else
putb(&q, 1); /* cpu flags: enabled */
putb(&q, 0); /* cpu signature */
putb(&q, 6);
putb(&q, 0);
putb(&q, 0);
putle16(&q, 0x201); /* feature flags */
putle16(&q, 0);
putle16(&q, 0); /* reserved */
putle16(&q, 0);
putle16(&q, 0);
putle16(&q, 0);
}
/* isa bus */
putb(&q, 1); /* entry type = bus */
putb(&q, 0); /* bus ID */
putstr(&q, "ISA ");
/* ioapic */
ioapic_id = smp_cpus;
putb(&q, 2); /* entry type = I/O APIC */
putb(&q, ioapic_id); /* apic ID */
putb(&q, 0x11); /* I/O APIC version number */
putb(&q, 1); /* enable */
putle32(&q, 0xfec00000); /* I/O APIC addr */
/* irqs */
for(i = 0; i < 16; i++) {
putb(&q, 3); /* entry type = I/O interrupt */
putb(&q, 0); /* interrupt type = vectored interrupt */
putb(&q, 0); /* flags: po=0, el=0 */
putb(&q, 0);
putb(&q, 0); /* source bus ID = ISA */
putb(&q, i); /* source bus IRQ */
putb(&q, ioapic_id); /* dest I/O APIC ID */
putb(&q, i); /* dest I/O APIC interrupt in */
}
/* patch length */
len = q - mp_config_table;
mp_config_table[4] = len;
mp_config_table[5] = len >> 8;
mp_config_table[7] = -mpf_checksum(mp_config_table, q - mp_config_table);
/* align to 16 */
offset = q - bios_data;
offset = (offset + 15) & ~15;
float_pointer_struct = bios_data + offset;
/* floating pointer structure */
q = float_pointer_struct;
putstr(&q, "_MP_");
/* pointer to MP config table */
putle32(&q, mp_config_table - bios_data + 0x000f0000);
putb(&q, 1); /* length in 16 byte units */
putb(&q, 4); /* MP spec revision */
putb(&q, 0); /* checksum (patched later) */
putb(&q, 0); /* MP feature byte 1 */
putb(&q, 0);
putb(&q, 0);
putb(&q, 0);
putb(&q, 0);
float_pointer_struct[10] =
-mpf_checksum(float_pointer_struct, q - float_pointer_struct);
}
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
static const int ide_irq[2] = { 14, 15 };
@@ -614,7 +451,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
{
char buf[1024];
int ret, linux_boot, initrd_size, i;
unsigned long bios_offset, vga_bios_offset;
unsigned long bios_offset, vga_bios_offset, option_rom_offset;
int bios_size, isa_bios_size;
PCIBus *pci_bus;
int piix3_devfn = -1;
@@ -632,7 +469,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
/* XXX: enable it in all cases */
env->cpuid_features |= CPUID_APIC;
}
register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
register_savevm("cpu", i, 4, cpu_save, cpu_load, env);
qemu_register_reset(main_cpu_reset, env);
if (pci_enabled) {
apic_init(env);
@@ -659,9 +496,6 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf);
exit(1);
}
if (bios_size == 65536) {
bios_add_mptable(phys_ram_base + bios_offset);
}
/* VGA BIOS load */
if (cirrus_vga_enabled) {
@@ -684,6 +518,23 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
cpu_register_physical_memory(0x100000 - isa_bios_size,
isa_bios_size,
(bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
option_rom_offset = 0;
for (i = 0; i < nb_option_roms; i++) {
int offset = bios_offset + bios_size + option_rom_offset;
int size;
size = load_image(option_rom[i], phys_ram_base + offset);
if ((size + option_rom_offset) > 0x10000) {
fprintf(stderr, "Too many option ROMS\n");
exit(1);
}
cpu_register_physical_memory(0xd0000 + option_rom_offset,
size, offset | IO_MEM_ROM);
option_rom_offset += size + 2047;
option_rom_offset -= (option_rom_offset % 2048);
}
/* map all the bios at the top of memory */
cpu_register_physical_memory((uint32_t)(-bios_size),
bios_size, bios_offset | IO_MEM_ROM);
@@ -747,8 +598,8 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
}
if (pci_enabled) {
pci_bus = i440fx_init();
piix3_devfn = piix3_init(pci_bus);
pci_bus = i440fx_init(&i440fx_state);
piix3_devfn = piix3_init(pci_bus, -1);
} else {
pci_bus = NULL;
}
@@ -768,8 +619,13 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
vga_ram_size);
}
} else {
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size, 0, 0);
if (pci_enabled) {
pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size, 0, 0);
} else {
isa_vga_init(ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
}
}
rtc_state = rtc_init(0x70, 8);
@@ -812,7 +668,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
if (strcmp(nd->model, "ne2k_isa") == 0) {
pc_init_ne2k_isa(nd);
} else if (pci_enabled) {
pci_nic_init(pci_bus, nd);
pci_nic_init(pci_bus, nd, -1);
} else {
fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
exit(1);
@@ -843,9 +699,18 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
}
if (pci_enabled && acpi_enabled) {
uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
piix4_pm_init(pci_bus, piix3_devfn + 3);
for (i = 0; i < 8; i++) {
SMBusDevice *eeprom = smbus_eeprom_device_init(0x50 + i,
eeprom_buf + (i * 256));
piix4_smbus_register_device(eeprom, 0x50 + i);
}
}
if (i440fx_state) {
i440fx_init_memory_mappings(i440fx_state);
}
#if 0
/* ??? Need to figure out some way for the user to
specify SCSI devices. */
@@ -863,13 +728,6 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
lsi_scsi_attach(scsi, bdrv, -1);
}
#endif
/* must be done after all PCI devices are instanciated */
/* XXX: should be done in the Bochs BIOS */
if (pci_enabled) {
pci_bios_init();
if (acpi_enabled)
acpi_bios_init();
}
}
static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device,
+131 -27
View File
@@ -29,48 +29,68 @@ struct PCIBus {
int bus_num;
int devfn_min;
pci_set_irq_fn set_irq;
pci_map_irq_fn map_irq;
uint32_t config_reg; /* XXX: suppress */
/* low level pic */
SetIRQFunc *low_set_irq;
void *irq_opaque;
PCIDevice *devices[256];
PCIDevice *parent_dev;
PCIBus *next;
/* The bus IRQ state is the logical OR of the connected devices.
Keep a count of the number of devices with raised IRQs. */
int irq_count[];
};
static void pci_update_mappings(PCIDevice *d);
target_phys_addr_t pci_mem_base;
static int pci_irq_index;
static PCIBus *first_bus;
PCIBus *pci_register_bus(pci_set_irq_fn set_irq, void *pic, int devfn_min)
PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *pic, int devfn_min, int nirq)
{
PCIBus *bus;
bus = qemu_mallocz(sizeof(PCIBus));
bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
bus->set_irq = set_irq;
bus->map_irq = map_irq;
bus->irq_opaque = pic;
bus->devfn_min = devfn_min;
first_bus = bus;
return bus;
}
PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq)
{
PCIBus *bus;
bus = qemu_mallocz(sizeof(PCIBus));
bus->map_irq = map_irq;
bus->parent_dev = dev;
bus->next = dev->bus->next;
dev->bus->next = bus;
return bus;
}
int pci_bus_num(PCIBus *s)
{
return s->bus_num;
}
void generic_pci_save(QEMUFile* f, void *opaque)
void pci_device_save(PCIDevice *s, QEMUFile *f)
{
PCIDevice* s=(PCIDevice*)opaque;
qemu_put_be32(f, 1); /* PCI device version */
qemu_put_buffer(f, s->config, 256);
}
int generic_pci_load(QEMUFile* f, void *opaque, int version_id)
int pci_device_load(PCIDevice *s, QEMUFile *f)
{
PCIDevice* s=(PCIDevice*)opaque;
uint32_t version_id;
version_id = qemu_get_be32(f);
if (version_id != 1)
return -EINVAL;
qemu_get_buffer(f, s->config, 256);
pci_update_mappings(s);
return 0;
}
@@ -99,6 +119,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
pci_dev->bus = bus;
pci_dev->devfn = devfn;
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
if (!config_read)
config_read = pci_default_read_config;
@@ -221,16 +242,23 @@ uint32_t pci_default_read_config(PCIDevice *d,
uint32_t address, int len)
{
uint32_t val;
switch(len) {
case 1:
val = d->config[address];
break;
case 2:
val = le16_to_cpu(*(uint16_t *)(d->config + address));
break;
default:
case 4:
val = le32_to_cpu(*(uint32_t *)(d->config + address));
if (address <= 0xfc) {
val = le32_to_cpu(*(uint32_t *)(d->config + address));
break;
}
/* fall through */
case 2:
if (address <= 0xfe) {
val = le16_to_cpu(*(uint16_t *)(d->config + address));
break;
}
/* fall through */
case 1:
val = d->config[address];
break;
}
return val;
@@ -320,7 +348,8 @@ void pci_default_write_config(PCIDevice *d,
if (can_write) {
d->config[addr] = val;
}
addr++;
if (++addr > 0xff)
break;
val >>= 8;
}
@@ -342,7 +371,9 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
addr, val, len);
#endif
bus_num = (addr >> 16) & 0xff;
if (bus_num != 0)
while (s && s->bus_num != bus_num)
s = s->next;
if (!s)
return;
pci_dev = s->devices[(addr >> 8) & 0xff];
if (!pci_dev)
@@ -363,7 +394,9 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
uint32_t val;
bus_num = (addr >> 16) & 0xff;
if (bus_num != 0)
while (s && s->bus_num != bus_num)
s= s->next;
if (!s)
goto fail;
pci_dev = s->devices[(addr >> 8) & 0xff];
if (!pci_dev) {
@@ -402,8 +435,23 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
/* 0 <= irq_num <= 3. level must be 0 or 1 */
void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
{
PCIBus *bus = pci_dev->bus;
bus->set_irq(pci_dev, bus->irq_opaque, irq_num, level);
PCIBus *bus;
int change;
change = level - pci_dev->irq_state[irq_num];
if (!change)
return;
pci_dev->irq_state[irq_num] = level;
for (;;) {
bus = pci_dev->bus;
irq_num = bus->map_irq(pci_dev, irq_num);
if (bus->set_irq)
break;
pci_dev = bus->parent_dev;
}
bus->irq_count[irq_num] += change;
bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
}
/***********************************************************/
@@ -416,6 +464,7 @@ typedef struct {
static pci_class_desc pci_class_descriptions[] =
{
{ 0x0100, "SCSI controller"},
{ 0x0101, "IDE controller"},
{ 0x0200, "Ethernet controller"},
{ 0x0300, "VGA controller"},
@@ -451,6 +500,9 @@ static void pci_info_device(PCIDevice *d)
if (d->config[PCI_INTERRUPT_PIN] != 0) {
term_printf(" IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]);
}
if (class == 0x0604) {
term_printf(" BUS %d.\n", d->config[0x19]);
}
for(i = 0;i < PCI_NUM_REGIONS; i++) {
r = &d->io_regions[i];
if (r->size != 0) {
@@ -464,14 +516,19 @@ static void pci_info_device(PCIDevice *d)
}
}
}
if (class == 0x0604 && d->config[0x19] != 0) {
pci_for_each_device(d->config[0x19], pci_info_device);
}
}
void pci_for_each_device(void (*fn)(PCIDevice *d))
void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
{
PCIBus *bus = first_bus;
PCIDevice *d;
int devfn;
while (bus && bus->bus_num != bus_num)
bus = bus->next;
if (bus) {
for(devfn = 0; devfn < 256; devfn++) {
d = bus->devices[devfn];
@@ -483,21 +540,68 @@ void pci_for_each_device(void (*fn)(PCIDevice *d))
void pci_info(void)
{
pci_for_each_device(pci_info_device);
pci_for_each_device(0, pci_info_device);
}
/* Initialize a PCI NIC. */
void pci_nic_init(PCIBus *bus, NICInfo *nd)
void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
{
if (strcmp(nd->model, "ne2k_pci") == 0) {
pci_ne2000_init(bus, nd);
pci_ne2000_init(bus, nd, devfn);
} else if (strcmp(nd->model, "rtl8139") == 0) {
pci_rtl8139_init(bus, nd);
pci_rtl8139_init(bus, nd, devfn);
} else if (strcmp(nd->model, "pcnet") == 0) {
pci_pcnet_init(bus, nd);
pci_pcnet_init(bus, nd, devfn);
} else {
fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
exit (1);
}
}
typedef struct {
PCIDevice dev;
PCIBus *bus;
} PCIBridge;
void pci_bridge_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
PCIBridge *s = (PCIBridge *)d;
if (address == 0x19 || (address == 0x18 && len > 1)) {
if (address == 0x19)
s->bus->bus_num = val & 0xff;
else
s->bus->bus_num = (val >> 8) & 0xff;
#if defined(DEBUG_PCI)
printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
#endif
}
pci_default_write_config(d, address, val, len);
}
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
pci_map_irq_fn map_irq, const char *name)
{
PCIBridge *s;
s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
devfn, NULL, pci_bridge_write_config);
s->dev.config[0x00] = id >> 16;
s->dev.config[0x01] = id > 24;
s->dev.config[0x02] = id; // device_id
s->dev.config[0x03] = id >> 8;
s->dev.config[0x04] = 0x06; // command = bus master, pci mem
s->dev.config[0x05] = 0x00;
s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
s->dev.config[0x07] = 0x00; // status = fast devsel
s->dev.config[0x08] = 0x00; // revision
s->dev.config[0x09] = 0x00; // programming i/f
s->dev.config[0x0A] = 0x04; // class_sub = PCI to PCI bridge
s->dev.config[0x0B] = 0x06; // class_base = PCI_bridge
s->dev.config[0x0D] = 0x10; // latency_timer
s->dev.config[0x0E] = 0x81; // header_type
s->dev.config[0x1E] = 0xa0; // secondary status
s->bus = pci_register_secondary_bus(&s->dev, map_irq);
return s->bus;
}
+385 -186
View File
@@ -27,6 +27,16 @@
* AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000
*/
/*
* On Sparc32, this is the Lance (Am7990) part of chip STP2000 (Master I/O), also
* produced as NCR89C100. See
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
* and
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt
*/
/* TODO: remove little endian host assumptions */
#include "vl.h"
//#define PCNET_DEBUG
@@ -46,11 +56,12 @@ typedef struct PCNetState_st PCNetState;
struct PCNetState_st {
PCIDevice dev;
PCIDevice *pci_dev;
VLANClientState *vc;
NICInfo *nd;
QEMUTimer *poll_timer;
int mmio_io_addr, rap, isr, lnkst;
target_phys_addr_t rdra, tdra;
int mmio_index, rap, isr, lnkst;
uint32_t rdra, tdra;
uint8_t prom[16];
uint16_t csr[128];
uint16_t bcr[32];
@@ -58,6 +69,12 @@ struct PCNetState_st {
int xmit_pos, recv_pos;
uint8_t buffer[4096];
int tx_busy;
void (*set_irq_cb)(void *s, int isr);
void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap);
void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap);
void *dma_opaque;
};
/* XXX: using bitfields for target memory structures is almost surely
@@ -99,6 +116,7 @@ struct qemu_ether_header {
#define CSR_TXON(S) !!(((S)->csr[0])&0x0010)
#define CSR_RXON(S) !!(((S)->csr[0])&0x0020)
#define CSR_INEA(S) !!(((S)->csr[0])&0x0040)
#define CSR_BSWP(S) !!(((S)->csr[3])&0x0004)
#define CSR_LAPPEN(S) !!(((S)->csr[3])&0x0020)
#define CSR_DXSUFLO(S) !!(((S)->csr[3])&0x0040)
#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
@@ -147,35 +165,19 @@ struct qemu_ether_header {
struct pcnet_initblk16 {
uint16_t mode;
uint16_t padr1;
uint16_t padr2;
uint16_t padr3;
uint16_t ladrf1;
uint16_t ladrf2;
uint16_t ladrf3;
uint16_t ladrf4;
unsigned PACKED_FIELD(rdra:24);
unsigned PACKED_FIELD(res1:5);
unsigned PACKED_FIELD(rlen:3);
unsigned PACKED_FIELD(tdra:24);
unsigned PACKED_FIELD(res2:5);
unsigned PACKED_FIELD(tlen:3);
uint16_t padr[3];
uint16_t ladrf[4];
uint32_t rdra;
uint32_t tdra;
};
struct pcnet_initblk32 {
uint16_t mode;
unsigned PACKED_FIELD(res1:4);
unsigned PACKED_FIELD(rlen:4);
unsigned PACKED_FIELD(res2:4);
unsigned PACKED_FIELD(tlen:4);
uint16_t padr1;
uint16_t padr2;
uint16_t padr3;
uint8_t rlen;
uint8_t tlen;
uint16_t padr[3];
uint16_t _res;
uint16_t ladrf1;
uint16_t ladrf2;
uint16_t ladrf3;
uint16_t ladrf4;
uint16_t ladrf[4];
uint32_t rdra;
uint32_t tdra;
};
@@ -251,112 +253,153 @@ struct pcnet_RMD {
(R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt, \
(R)->rmd2.zeros)
static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd1,
target_phys_addr_t addr)
{
if (!BCR_SWSTYLE(s)) {
uint16_t xda[4];
cpu_physical_memory_read(addr,
(void *)&xda[0], sizeof(xda));
((uint32_t *)tmd)[0] = (xda[0]&0xffff) |
((xda[1]&0x00ff) << 16);
((uint32_t *)tmd)[1] = (xda[2]&0xffff)|
((xda[1] & 0xff00) << 16);
((uint32_t *)tmd)[2] =
(xda[3] & 0xffff) << 16;
((uint32_t *)tmd)[3] = 0;
}
else
if (BCR_SWSTYLE(s) != 3)
cpu_physical_memory_read(addr, (void *)tmd, 16);
else {
uint32_t xda[4];
cpu_physical_memory_read(addr,
(void *)&xda[0], sizeof(xda));
((uint32_t *)tmd)[0] = xda[2];
((uint32_t *)tmd)[1] = xda[1];
((uint32_t *)tmd)[2] = xda[0];
((uint32_t *)tmd)[3] = xda[3];
}
}
uint32_t *tmd = (uint32_t *)tmd1;
static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
{
if (!BCR_SWSTYLE(s)) {
uint16_t xda[4];
xda[0] = ((uint32_t *)tmd)[0] & 0xffff;
xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) |
((((uint32_t *)tmd)[1]>>16)&0xff00);
xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
xda[3] = ((uint32_t *)tmd)[2] >> 16;
cpu_physical_memory_write(addr,
(void *)&xda[0], sizeof(xda));
}
else {
if (BCR_SWSTYLE(s) != 3)
cpu_physical_memory_write(addr, (void *)tmd, 16);
else {
uint32_t xda[4];
xda[0] = ((uint32_t *)tmd)[2];
xda[1] = ((uint32_t *)tmd)[1];
xda[2] = ((uint32_t *)tmd)[0];
xda[3] = ((uint32_t *)tmd)[3];
cpu_physical_memory_write(addr,
(void *)&xda[0], sizeof(xda));
s->phys_mem_read(s->dma_opaque, addr,
(void *)&xda[0], sizeof(xda), 0);
le16_to_cpus(&xda[0]);
le16_to_cpus(&xda[1]);
le16_to_cpus(&xda[2]);
le16_to_cpus(&xda[3]);
tmd[0] = (xda[0]&0xffff) |
((xda[1]&0x00ff) << 16);
tmd[1] = (xda[2]&0xffff)|
((xda[1] & 0xff00) << 16);
tmd[2] =
(xda[3] & 0xffff) << 16;
tmd[3] = 0;
} else {
uint32_t xda[4];
s->phys_mem_read(s->dma_opaque, addr,
(void *)&xda[0], sizeof(xda), 0);
le32_to_cpus(&xda[0]);
le32_to_cpus(&xda[1]);
le32_to_cpus(&xda[2]);
le32_to_cpus(&xda[3]);
if (BCR_SWSTYLE(s) != 3) {
memcpy(tmd, xda, sizeof(xda));
} else {
tmd[0] = xda[2];
tmd[1] = xda[1];
tmd[2] = xda[0];
tmd[3] = xda[3];
}
}
}
static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd1,
target_phys_addr_t addr)
{
const uint32_t *tmd = (const uint32_t *)tmd1;
if (!BCR_SWSTYLE(s)) {
uint16_t xda[4];
xda[0] = tmd[0] & 0xffff;
xda[1] = ((tmd[0]>>16)&0x00ff) |
((tmd[1]>>16)&0xff00);
xda[2] = tmd[1] & 0xffff;
xda[3] = tmd[2] >> 16;
cpu_to_le16s(&xda[0]);
cpu_to_le16s(&xda[1]);
cpu_to_le16s(&xda[2]);
cpu_to_le16s(&xda[3]);
s->phys_mem_write(s->dma_opaque, addr,
(void *)&xda[0], sizeof(xda), 0);
} else {
uint32_t xda[4];
if (BCR_SWSTYLE(s) != 3) {
memcpy(xda, tmd, sizeof(xda));
} else {
xda[0] = tmd[2];
xda[1] = tmd[1];
xda[2] = tmd[0];
xda[3] = tmd[3];
}
cpu_to_le32s(&xda[0]);
cpu_to_le32s(&xda[1]);
cpu_to_le32s(&xda[2]);
cpu_to_le32s(&xda[3]);
s->phys_mem_write(s->dma_opaque, addr,
(void *)&xda[0], sizeof(xda), 0);
}
}
static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd1,
target_phys_addr_t addr)
{
uint32_t *rmd = (uint32_t *)rmd1;
if (!BCR_SWSTYLE(s)) {
uint16_t rda[4];
cpu_physical_memory_read(addr,
(void *)&rda[0], sizeof(rda));
((uint32_t *)rmd)[0] = (rda[0]&0xffff)|
((rda[1] & 0x00ff) << 16);
((uint32_t *)rmd)[1] = (rda[2]&0xffff)|
((rda[1] & 0xff00) << 16);
((uint32_t *)rmd)[2] = rda[3] & 0xffff;
((uint32_t *)rmd)[3] = 0;
}
else
if (BCR_SWSTYLE(s) != 3)
cpu_physical_memory_read(addr, (void *)rmd, 16);
else {
s->phys_mem_read(s->dma_opaque, addr,
(void *)&rda[0], sizeof(rda), 0);
le16_to_cpus(&rda[0]);
le16_to_cpus(&rda[1]);
le16_to_cpus(&rda[2]);
le16_to_cpus(&rda[3]);
rmd[0] = (rda[0]&0xffff)|
((rda[1] & 0x00ff) << 16);
rmd[1] = (rda[2]&0xffff)|
((rda[1] & 0xff00) << 16);
rmd[2] = rda[3] & 0xffff;
rmd[3] = 0;
} else {
uint32_t rda[4];
cpu_physical_memory_read(addr,
(void *)&rda[0], sizeof(rda));
((uint32_t *)rmd)[0] = rda[2];
((uint32_t *)rmd)[1] = rda[1];
((uint32_t *)rmd)[2] = rda[0];
((uint32_t *)rmd)[3] = rda[3];
s->phys_mem_read(s->dma_opaque, addr,
(void *)&rda[0], sizeof(rda), 0);
le32_to_cpus(&rda[0]);
le32_to_cpus(&rda[1]);
le32_to_cpus(&rda[2]);
le32_to_cpus(&rda[3]);
if (BCR_SWSTYLE(s) != 3) {
memcpy(rmd, rda, sizeof(rda));
} else {
rmd[0] = rda[2];
rmd[1] = rda[1];
rmd[2] = rda[0];
rmd[3] = rda[3];
}
}
}
static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd1,
target_phys_addr_t addr)
{
const uint32_t *rmd = (const uint32_t *)rmd1;
if (!BCR_SWSTYLE(s)) {
uint16_t rda[4]; \
rda[0] = ((uint32_t *)rmd)[0] & 0xffff; \
rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)|\
((((uint32_t *)rmd)[1]>>16)&0xff00);\
rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \
rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \
cpu_physical_memory_write(addr, \
(void *)&rda[0], sizeof(rda)); \
}
else {
if (BCR_SWSTYLE(s) != 3)
cpu_physical_memory_write(addr, (void *)rmd, 16);
else {
uint32_t rda[4];
rda[0] = ((uint32_t *)rmd)[2];
rda[1] = ((uint32_t *)rmd)[1];
rda[2] = ((uint32_t *)rmd)[0];
rda[3] = ((uint32_t *)rmd)[3];
cpu_physical_memory_write(addr,
(void *)&rda[0], sizeof(rda));
uint16_t rda[4];
rda[0] = rmd[0] & 0xffff;
rda[1] = ((rmd[0]>>16)&0xff)|
((rmd[1]>>16)&0xff00);
rda[2] = rmd[1] & 0xffff;
rda[3] = rmd[2] & 0xffff;
cpu_to_le16s(&rda[0]);
cpu_to_le16s(&rda[1]);
cpu_to_le16s(&rda[2]);
cpu_to_le16s(&rda[3]);
s->phys_mem_write(s->dma_opaque, addr,
(void *)&rda[0], sizeof(rda), 0);
} else {
uint32_t rda[4];
if (BCR_SWSTYLE(s) != 3) {
memcpy(rda, rmd, sizeof(rda));
} else {
rda[0] = rmd[2];
rda[1] = rmd[1];
rda[2] = rmd[0];
rda[3] = rmd[3];
}
cpu_to_le32s(&rda[0]);
cpu_to_le32s(&rda[1]);
cpu_to_le32s(&rda[2]);
cpu_to_le32s(&rda[3]);
s->phys_mem_write(s->dma_opaque, addr,
(void *)&rda[0], sizeof(rda), 0);
}
}
@@ -391,8 +434,8 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
case 0x00: \
do { \
uint16_t rda[4]; \
cpu_physical_memory_read((ADDR), \
(void *)&rda[0], sizeof(rda)); \
s->phys_mem_read(s->dma_opaque, (ADDR), \
(void *)&rda[0], sizeof(rda), 0); \
(RES) |= (rda[2] & 0xf000)!=0xf000; \
(RES) |= (rda[3] & 0xf000)!=0x0000; \
} while (0); \
@@ -401,8 +444,8 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
case 0x02: \
do { \
uint32_t rda[4]; \
cpu_physical_memory_read((ADDR), \
(void *)&rda[0], sizeof(rda)); \
s->phys_mem_read(s->dma_opaque, (ADDR), \
(void *)&rda[0], sizeof(rda), 0); \
(RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
(RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
} while (0); \
@@ -410,8 +453,8 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
case 0x03: \
do { \
uint32_t rda[4]; \
cpu_physical_memory_read((ADDR), \
(void *)&rda[0], sizeof(rda)); \
s->phys_mem_read(s->dma_opaque, (ADDR), \
(void *)&rda[0], sizeof(rda), 0); \
(RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
(RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
} while (0); \
@@ -424,8 +467,8 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
case 0x00: \
do { \
uint16_t xda[4]; \
cpu_physical_memory_read((ADDR), \
(void *)&xda[0], sizeof(xda)); \
s->phys_mem_read(s->dma_opaque, (ADDR), \
(void *)&xda[0], sizeof(xda), 0); \
(RES) |= (xda[2] & 0xf000)!=0xf000;\
} while (0); \
break; \
@@ -434,8 +477,8 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
case 0x03: \
do { \
uint32_t xda[4]; \
cpu_physical_memory_read((ADDR), \
(void *)&xda[0], sizeof(xda)); \
s->phys_mem_read(s->dma_opaque, (ADDR), \
(void *)&xda[0], sizeof(xda), 0); \
(RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
} while (0); \
break; \
@@ -448,13 +491,12 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
struct qemu_ether_header *hdr = (void *)(BUF); \
printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
"shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
"type=0x%04x (bcast=%d)\n", \
"type=0x%04x\n", \
hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
be16_to_cpu(hdr->ether_type), \
!!ETHER_IS_MULTICAST(hdr->ether_dhost)); \
be16_to_cpu(hdr->ether_type)); \
} while (0)
#define MULTICAST_FILTER_LEN 8
@@ -571,7 +613,7 @@ static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
{
static uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static const uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
struct qemu_ether_header *hdr = (void *)buf;
int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
#ifdef PCNET_DEBUG_MATCH
@@ -721,51 +763,65 @@ static void pcnet_update_irq(PCNetState *s)
printf("pcnet: INTA=%d\n", isr);
#endif
}
pci_set_irq(&s->dev, 0, isr);
s->isr = isr;
s->set_irq_cb(s, isr);
s->isr = isr;
}
static void pcnet_init(PCNetState *s)
{
int rlen, tlen;
uint16_t *padr, *ladrf, mode;
uint32_t rdra, tdra;
#ifdef PCNET_DEBUG
printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
#endif
#define PCNET_INIT() do { \
cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)), \
(uint8_t *)&initblk, sizeof(initblk)); \
s->csr[15] = le16_to_cpu(initblk.mode); \
CSR_RCVRL(s) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512; \
CSR_XMTRL(s) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512; \
s->csr[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8); \
s->csr[ 8] = le16_to_cpu(initblk.ladrf1); \
s->csr[ 9] = le16_to_cpu(initblk.ladrf2); \
s->csr[10] = le16_to_cpu(initblk.ladrf3); \
s->csr[11] = le16_to_cpu(initblk.ladrf4); \
s->csr[12] = le16_to_cpu(initblk.padr1); \
s->csr[13] = le16_to_cpu(initblk.padr2); \
s->csr[14] = le16_to_cpu(initblk.padr3); \
s->rdra = PHYSADDR(s,initblk.rdra); \
s->tdra = PHYSADDR(s,initblk.tdra); \
} while (0)
if (BCR_SSIZE32(s)) {
struct pcnet_initblk32 initblk;
PCNET_INIT();
#ifdef PCNET_DEBUG
printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
initblk.rlen, initblk.tlen);
#endif
s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
(uint8_t *)&initblk, sizeof(initblk), 0);
mode = initblk.mode;
rlen = initblk.rlen >> 4;
tlen = initblk.tlen >> 4;
ladrf = initblk.ladrf;
padr = initblk.padr;
rdra = le32_to_cpu(initblk.rdra);
tdra = le32_to_cpu(initblk.tdra);
s->rdra = PHYSADDR(s,initblk.rdra);
s->tdra = PHYSADDR(s,initblk.tdra);
} else {
struct pcnet_initblk16 initblk;
PCNET_INIT();
#ifdef PCNET_DEBUG
printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
initblk.rlen, initblk.tlen);
#endif
s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
(uint8_t *)&initblk, sizeof(initblk), 0);
mode = initblk.mode;
ladrf = initblk.ladrf;
padr = initblk.padr;
rdra = le32_to_cpu(initblk.rdra);
tdra = le32_to_cpu(initblk.tdra);
rlen = rdra >> 29;
tlen = tdra >> 29;
rdra &= 0x00ffffff;
tdra &= 0x00ffffff;
}
#undef PCNET_INIT
#if defined(PCNET_DEBUG)
printf("rlen=%d tlen=%d\n",
rlen, tlen);
#endif
CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
s->csr[ 6] = (tlen << 12) | (rlen << 8);
s->csr[15] = le16_to_cpu(mode);
s->csr[ 8] = le16_to_cpu(ladrf[0]);
s->csr[ 9] = le16_to_cpu(ladrf[1]);
s->csr[10] = le16_to_cpu(ladrf[2]);
s->csr[11] = le16_to_cpu(ladrf[3]);
s->csr[12] = le16_to_cpu(padr[0]);
s->csr[13] = le16_to_cpu(padr[1]);
s->csr[14] = le16_to_cpu(padr[2]);
s->rdra = PHYSADDR(s, rdra);
s->tdra = PHYSADDR(s, tdra);
CSR_RCVRC(s) = CSR_RCVRL(s);
CSR_XMTRC(s) = CSR_XMTRL(s);
@@ -1035,7 +1091,7 @@ static void pcnet_receive(void *opaque, const uint8_t *buf, int size)
#define PCNET_RECV_STORE() do { \
int count = MIN(4096 - rmd.rmd1.bcnt,size); \
target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr); \
cpu_physical_memory_write(rbadr, src, count); \
s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \
src += count; size -= count; \
rmd.rmd2.mcnt = count; rmd.rmd1.own = 0; \
RMDSTORE(&rmd, PHYSADDR(s,crda)); \
@@ -1125,15 +1181,17 @@ static void pcnet_transmit(PCNetState *s)
if (tmd.tmd1.stp) {
s->xmit_pos = 0;
if (!tmd.tmd1.enp) {
cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
s->buffer, 4096 - tmd.tmd1.bcnt);
s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr),
s->buffer, 4096 - tmd.tmd1.bcnt,
CSR_BSWP(s));
s->xmit_pos += 4096 - tmd.tmd1.bcnt;
}
xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
}
if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr),
s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt,
CSR_BSWP(s));
s->xmit_pos += 4096 - tmd.tmd1.bcnt;
#ifdef PCNET_DEBUG
printf("pcnet_transmit size=%d\n", s->xmit_pos);
@@ -1426,8 +1484,9 @@ static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
return val;
}
static void pcnet_h_reset(PCNetState *s)
void pcnet_h_reset(void *opaque)
{
PCNetState *s = opaque;
int i;
uint16_t checksum;
@@ -1703,6 +1762,90 @@ static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
}
static void pcnet_save(QEMUFile *f, void *opaque)
{
PCNetState *s = opaque;
unsigned int i;
if (s->pci_dev)
pci_device_save(s->pci_dev, f);
qemu_put_be32s(f, &s->rap);
qemu_put_be32s(f, &s->isr);
qemu_put_be32s(f, &s->lnkst);
qemu_put_be32s(f, &s->rdra);
qemu_put_be32s(f, &s->tdra);
qemu_put_buffer(f, s->prom, 16);
for (i = 0; i < 128; i++)
qemu_put_be16s(f, &s->csr[i]);
for (i = 0; i < 32; i++)
qemu_put_be16s(f, &s->bcr[i]);
qemu_put_be64s(f, &s->timer);
qemu_put_be32s(f, &s->xmit_pos);
qemu_put_be32s(f, &s->recv_pos);
qemu_put_buffer(f, s->buffer, 4096);
qemu_put_be32s(f, &s->tx_busy);
qemu_put_timer(f, s->poll_timer);
}
static int pcnet_load(QEMUFile *f, void *opaque, int version_id)
{
PCNetState *s = opaque;
int i, ret;
if (version_id != 2)
return -EINVAL;
if (s->pci_dev) {
ret = pci_device_load(s->pci_dev, f);
if (ret < 0)
return ret;
}
qemu_get_be32s(f, &s->rap);
qemu_get_be32s(f, &s->isr);
qemu_get_be32s(f, &s->lnkst);
qemu_get_be32s(f, &s->rdra);
qemu_get_be32s(f, &s->tdra);
qemu_get_buffer(f, s->prom, 16);
for (i = 0; i < 128; i++)
qemu_get_be16s(f, &s->csr[i]);
for (i = 0; i < 32; i++)
qemu_get_be16s(f, &s->bcr[i]);
qemu_get_be64s(f, &s->timer);
qemu_get_be32s(f, &s->xmit_pos);
qemu_get_be32s(f, &s->recv_pos);
qemu_get_buffer(f, s->buffer, 4096);
qemu_get_be32s(f, &s->tx_busy);
qemu_get_timer(f, s->poll_timer);
return 0;
}
static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str)
{
d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
d->nd = nd;
d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive,
pcnet_can_receive, d);
snprintf(d->vc->info_str, sizeof(d->vc->info_str),
"pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
d->nd->macaddr[0],
d->nd->macaddr[1],
d->nd->macaddr[2],
d->nd->macaddr[3],
d->nd->macaddr[4],
d->nd->macaddr[5]);
pcnet_h_reset(d);
register_savevm("pcnet", 0, 2, pcnet_save, pcnet_load, d);
}
/* PCI interface */
static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
(CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
(CPUWriteMemoryFunc *)&pcnet_mmio_writew,
@@ -1724,10 +1867,29 @@ static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
#endif
cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr);
cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_index);
}
void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
static void pcnet_pci_set_irq_cb(void *opaque, int isr)
{
PCNetState *s = opaque;
pci_set_irq(&s->dev, 0, isr);
}
static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap)
{
cpu_physical_memory_write(addr, buf, len);
}
static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap)
{
cpu_physical_memory_read(addr, buf, len);
}
void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
{
PCNetState *d;
uint8_t *pci_conf;
@@ -1738,7 +1900,7 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
#endif
d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
-1, NULL, NULL);
devfn, NULL, NULL);
pci_conf = d->dev.config;
@@ -1760,7 +1922,7 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
pci_conf[0x3f] = 0xff;
/* Handler for memory-mapped I/O */
d->mmio_io_addr =
d->mmio_index =
cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE,
@@ -1769,21 +1931,58 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE,
PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
d->set_irq_cb = pcnet_pci_set_irq_cb;
d->phys_mem_read = pci_physical_memory_read;
d->phys_mem_write = pci_physical_memory_write;
d->pci_dev = &d->dev;
d->nd = nd;
d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive,
pcnet_can_receive, d);
snprintf(d->vc->info_str, sizeof(d->vc->info_str),
"pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
d->nd->macaddr[0],
d->nd->macaddr[1],
d->nd->macaddr[2],
d->nd->macaddr[3],
d->nd->macaddr[4],
d->nd->macaddr[5]);
pcnet_h_reset(d);
pcnet_common_init(d, nd, "pcnet");
}
/* SPARC32 interface */
#if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) // Avoid compile failure
static CPUReadMemoryFunc *lance_mem_read[3] = {
(CPUReadMemoryFunc *)&pcnet_ioport_readw,
(CPUReadMemoryFunc *)&pcnet_ioport_readw,
(CPUReadMemoryFunc *)&pcnet_ioport_readw,
};
static CPUWriteMemoryFunc *lance_mem_write[3] = {
(CPUWriteMemoryFunc *)&pcnet_ioport_writew,
(CPUWriteMemoryFunc *)&pcnet_ioport_writew,
(CPUWriteMemoryFunc *)&pcnet_ioport_writew,
};
static void pcnet_sparc_set_irq_cb(void *opaque, int isr)
{
PCNetState *s = opaque;
ledma_set_irq(s->dma_opaque, isr);
}
void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque)
{
PCNetState *d;
int lance_io_memory;
d = qemu_mallocz(sizeof(PCNetState));
if (!d)
return NULL;
lance_io_memory =
cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d);
d->dma_opaque = dma_opaque;
cpu_register_physical_memory(leaddr, 4, lance_io_memory);
d->set_irq_cb = pcnet_sparc_set_irq_cb;
d->phys_mem_read = ledma_memory_read;
d->phys_mem_write = ledma_memory_write;
pcnet_common_init(d, nd, "lance");
return d;
}
#endif /* TARGET_SPARC */
-1
View File
@@ -135,7 +135,6 @@ static uint32_t pflash_read (pflash_t *pfl, target_ulong offset, int width)
#else
ret = p[offset];
ret |= p[offset + 1] << 8;
ret |= p[offset + 1] << 8;
ret |= p[offset + 2] << 16;
ret |= p[offset + 3] << 24;
#endif
+232 -267
View File
@@ -40,16 +40,129 @@ static uint32_t i440fx_addr_readl(void* opaque, uint32_t addr)
return s->config_reg;
}
static void piix3_set_irq(PCIDevice *pci_dev, void *pic, int irq_num, int level);
static void piix3_set_irq(void *pic, int irq_num, int level);
PCIBus *i440fx_init(void)
/* return the global irq number corresponding to a given device irq
pin. We could also use the bus number to have a more precise
mapping. */
static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
{
int slot_addend;
slot_addend = (pci_dev->devfn >> 3) - 1;
return (irq_num + slot_addend) & 3;
}
static uint32_t isa_page_descs[384 / 4];
static uint8_t smm_enabled;
static void update_pam(PCIDevice *d, uint32_t start, uint32_t end, int r)
{
uint32_t addr;
// printf("ISA mapping %08x-0x%08x: %d\n", start, end, r);
switch(r) {
case 3:
/* RAM */
cpu_register_physical_memory(start, end - start,
start);
break;
case 1:
/* ROM (XXX: not quite correct) */
cpu_register_physical_memory(start, end - start,
start | IO_MEM_ROM);
break;
case 2:
case 0:
/* XXX: should distinguish read/write cases */
for(addr = start; addr < end; addr += 4096) {
cpu_register_physical_memory(addr, 4096,
isa_page_descs[(addr - 0xa0000) >> 12]);
}
break;
}
}
static void i440fx_update_memory_mappings(PCIDevice *d)
{
int i, r;
uint32_t smram, addr;
update_pam(d, 0xf0000, 0x100000, (d->config[0x59] >> 4) & 3);
for(i = 0; i < 12; i++) {
r = (d->config[(i >> 1) + 0x5a] >> ((i & 1) * 4)) & 3;
update_pam(d, 0xc0000 + 0x4000 * i, 0xc0000 + 0x4000 * (i + 1), r);
}
smram = d->config[0x72];
if ((smm_enabled && (smram & 0x08)) || (smram & 0x40)) {
cpu_register_physical_memory(0xa0000, 0x20000, 0xa0000);
} else {
for(addr = 0xa0000; addr < 0xc0000; addr += 4096) {
cpu_register_physical_memory(addr, 4096,
isa_page_descs[(addr - 0xa0000) >> 12]);
}
}
}
void i440fx_set_smm(PCIDevice *d, int val)
{
val = (val != 0);
if (smm_enabled != val) {
smm_enabled = val;
i440fx_update_memory_mappings(d);
}
}
/* XXX: suppress when better memory API. We make the assumption that
no device (in particular the VGA) changes the memory mappings in
the 0xa0000-0x100000 range */
void i440fx_init_memory_mappings(PCIDevice *d)
{
int i;
for(i = 0; i < 96; i++) {
isa_page_descs[i] = cpu_get_physical_page_desc(0xa0000 + i * 0x1000);
}
}
static void i440fx_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
/* XXX: implement SMRAM.D_LOCK */
pci_default_write_config(d, address, val, len);
if ((address >= 0x59 && address <= 0x5f) || address == 0x72)
i440fx_update_memory_mappings(d);
}
static void i440fx_save(QEMUFile* f, void *opaque)
{
PCIDevice *d = opaque;
pci_device_save(d, f);
qemu_put_8s(f, &smm_enabled);
}
static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
{
PCIDevice *d = opaque;
int ret;
if (version_id != 1)
return -EINVAL;
ret = pci_device_load(d, f);
if (ret < 0)
return ret;
i440fx_update_memory_mappings(d);
qemu_get_8s(f, &smm_enabled);
return 0;
}
PCIBus *i440fx_init(PCIDevice **pi440fx_state)
{
PCIBus *b;
PCIDevice *d;
I440FXState *s;
s = qemu_mallocz(sizeof(I440FXState));
b = pci_register_bus(piix3_set_irq, NULL, 0);
b = pci_register_bus(piix3_set_irq, pci_slot_get_pirq, NULL, 0, 4);
s->bus = b;
register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
@@ -63,7 +176,7 @@ PCIBus *i440fx_init(void)
register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0,
NULL, NULL);
NULL, i440fx_write_config);
d->config[0x00] = 0x86; // vendor_id
d->config[0x01] = 0x80;
@@ -73,75 +186,41 @@ PCIBus *i440fx_init(void)
d->config[0x0a] = 0x00; // class_sub = host2pci
d->config[0x0b] = 0x06; // class_base = PCI_bridge
d->config[0x0e] = 0x00; // header_type
d->config[0x72] = 0x02; /* SMRAM */
register_savevm("I440FX", 0, 1, i440fx_save, i440fx_load, d);
*pi440fx_state = d;
return b;
}
/* PIIX3 PCI to ISA bridge */
static PCIDevice *piix3_dev;
PCIDevice *piix3_dev;
PCIDevice *piix4_dev;
/* just used for simpler irq handling. */
#define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32)
static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS];
static int pci_irq_levels[4];
/* return the global irq number corresponding to a given device irq
pin. We could also use the bus number to have a more precise
mapping. */
static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
static void piix3_set_irq(void *pic, int irq_num, int level)
{
int slot_addend;
slot_addend = (pci_dev->devfn >> 3) - 1;
return (irq_num + slot_addend) & 3;
}
int i, pic_irq, pic_level;
static inline int get_pci_irq_level(int irq_num)
{
int pic_level;
#if (PCI_IRQ_WORDS == 2)
pic_level = ((pci_irq_levels[irq_num][0] |
pci_irq_levels[irq_num][1]) != 0);
#else
{
int i;
pic_level = 0;
for(i = 0; i < PCI_IRQ_WORDS; i++) {
if (pci_irq_levels[irq_num][i]) {
pic_level = 1;
break;
}
}
}
#endif
return pic_level;
}
static void piix3_set_irq(PCIDevice *pci_dev, void *pic, int irq_num, int level)
{
int irq_index, shift, pic_irq, pic_level;
uint32_t *p;
irq_num = pci_slot_get_pirq(pci_dev, irq_num);
irq_index = pci_dev->irq_index;
p = &pci_irq_levels[irq_num][irq_index >> 5];
shift = (irq_index & 0x1f);
*p = (*p & ~(1 << shift)) | (level << shift);
pci_irq_levels[irq_num] = level;
/* now we change the pic irq level according to the piix irq mappings */
/* XXX: optimize */
pic_irq = piix3_dev->config[0x60 + irq_num];
if (pic_irq < 16) {
/* the pic level is the logical OR of all the PCI irqs mapped
/* The pic level is the logical OR of all the PCI irqs mapped
to it */
pic_level = 0;
if (pic_irq == piix3_dev->config[0x60])
pic_level |= get_pci_irq_level(0);
if (pic_irq == piix3_dev->config[0x61])
pic_level |= get_pci_irq_level(1);
if (pic_irq == piix3_dev->config[0x62])
pic_level |= get_pci_irq_level(2);
if (pic_irq == piix3_dev->config[0x63])
pic_level |= get_pci_irq_level(3);
for (i = 0; i < 4; i++) {
if (pic_irq == piix3_dev->config[0x60 + i])
pic_level |= pci_irq_levels[i];
}
pic_set_irq(pic_irq, pic_level);
}
}
@@ -167,6 +246,42 @@ static void piix3_reset(PCIDevice *d)
pci_conf[0x80] = 0x00;
pci_conf[0x82] = 0x00;
pci_conf[0xa0] = 0x08;
pci_conf[0xa2] = 0x00;
pci_conf[0xa3] = 0x00;
pci_conf[0xa4] = 0x00;
pci_conf[0xa5] = 0x00;
pci_conf[0xa6] = 0x00;
pci_conf[0xa7] = 0x00;
pci_conf[0xa8] = 0x0f;
pci_conf[0xaa] = 0x00;
pci_conf[0xab] = 0x00;
pci_conf[0xac] = 0x00;
pci_conf[0xae] = 0x00;
}
static void piix4_reset(PCIDevice *d)
{
uint8_t *pci_conf = d->config;
pci_conf[0x04] = 0x07; // master, memory and I/O
pci_conf[0x05] = 0x00;
pci_conf[0x06] = 0x00;
pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
pci_conf[0x4c] = 0x4d;
pci_conf[0x4e] = 0x03;
pci_conf[0x4f] = 0x00;
pci_conf[0x60] = 0x0a; // PCI A -> IRQ 10
pci_conf[0x61] = 0x0a; // PCI B -> IRQ 10
pci_conf[0x62] = 0x0b; // PCI C -> IRQ 11
pci_conf[0x63] = 0x0b; // PCI D -> IRQ 11
pci_conf[0x69] = 0x02;
pci_conf[0x70] = 0x80;
pci_conf[0x76] = 0x0c;
pci_conf[0x77] = 0x0c;
pci_conf[0x78] = 0x02;
pci_conf[0x79] = 0x00;
pci_conf[0x80] = 0x00;
pci_conf[0x82] = 0x00;
pci_conf[0xa0] = 0x08;
pci_conf[0xa2] = 0x00;
pci_conf[0xa3] = 0x00;
@@ -181,14 +296,53 @@ static void piix3_reset(PCIDevice *d)
pci_conf[0xae] = 0x00;
}
int piix3_init(PCIBus *bus)
static void piix_save(QEMUFile* f, void *opaque)
{
PCIDevice *d = opaque;
pci_device_save(d, f);
}
static int piix_load(QEMUFile* f, void *opaque, int version_id)
{
PCIDevice *d = opaque;
if (version_id != 2)
return -EINVAL;
return pci_device_load(d, f);
}
int piix_init(PCIBus *bus, int devfn)
{
PCIDevice *d;
uint8_t *pci_conf;
d = pci_register_device(bus, "PIIX", sizeof(PCIDevice),
devfn, NULL, NULL);
register_savevm("PIIX", 0, 2, piix_save, piix_load, d);
piix3_dev = d;
pci_conf = d->config;
pci_conf[0x00] = 0x86; // Intel
pci_conf[0x01] = 0x80;
pci_conf[0x02] = 0x2E; // 82371FB PIIX PCI-to-ISA bridge
pci_conf[0x03] = 0x12;
pci_conf[0x08] = 0x02; // Step A1
pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
piix3_reset(d);
return d->devfn;
}
int piix3_init(PCIBus *bus, int devfn)
{
PCIDevice *d;
uint8_t *pci_conf;
d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
-1, NULL, NULL);
register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d);
devfn, NULL, NULL);
register_savevm("PIIX3", 0, 2, piix_save, piix_load, d);
piix3_dev = d;
pci_conf = d->config;
@@ -205,215 +359,26 @@ int piix3_init(PCIBus *bus)
return d->devfn;
}
/***********************************************************/
/* XXX: the following should be moved to the PC BIOS */
static __attribute__((unused)) uint32_t isa_inb(uint32_t addr)
int piix4_init(PCIBus *bus, int devfn)
{
return cpu_inb(NULL, addr);
PCIDevice *d;
uint8_t *pci_conf;
d = pci_register_device(bus, "PIIX4", sizeof(PCIDevice),
devfn, NULL, NULL);
register_savevm("PIIX4", 0, 2, piix_save, piix_load, d);
piix4_dev = d;
pci_conf = d->config;
pci_conf[0x00] = 0x86; // Intel
pci_conf[0x01] = 0x80;
pci_conf[0x02] = 0x10; // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
pci_conf[0x03] = 0x71;
pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
piix4_reset(d);
return d->devfn;
}
static void isa_outb(uint32_t val, uint32_t addr)
{
cpu_outb(NULL, addr, val);
}
static __attribute__((unused)) uint32_t isa_inw(uint32_t addr)
{
return cpu_inw(NULL, addr);
}
static __attribute__((unused)) void isa_outw(uint32_t val, uint32_t addr)
{
cpu_outw(NULL, addr, val);
}
static __attribute__((unused)) uint32_t isa_inl(uint32_t addr)
{
return cpu_inl(NULL, addr);
}
static __attribute__((unused)) void isa_outl(uint32_t val, uint32_t addr)
{
cpu_outl(NULL, addr, val);
}
static uint32_t pci_bios_io_addr;
static uint32_t pci_bios_mem_addr;
/* host irqs corresponding to PCI irqs A-D */
static uint8_t pci_irqs[4] = { 11, 9, 11, 9 };
static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
pci_data_write(s, addr, val, 4);
}
static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
pci_data_write(s, addr, val, 2);
}
static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
pci_data_write(s, addr, val, 1);
}
static __attribute__((unused)) uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
return pci_data_read(s, addr, 4);
}
static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
return pci_data_read(s, addr, 2);
}
static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
return pci_data_read(s, addr, 1);
}
static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
{
PCIIORegion *r;
uint16_t cmd;
uint32_t ofs;
if ( region_num == PCI_ROM_SLOT ) {
ofs = 0x30;
}else{
ofs = 0x10 + region_num * 4;
}
pci_config_writel(d, ofs, addr);
r = &d->io_regions[region_num];
/* enable memory mappings */
cmd = pci_config_readw(d, PCI_COMMAND);
if ( region_num == PCI_ROM_SLOT )
cmd |= 2;
else if (r->type & PCI_ADDRESS_SPACE_IO)
cmd |= 1;
else
cmd |= 2;
pci_config_writew(d, PCI_COMMAND, cmd);
}
static void pci_bios_init_device(PCIDevice *d)
{
int class;
PCIIORegion *r;
uint32_t *paddr;
int i, pin, pic_irq, vendor_id, device_id;
class = pci_config_readw(d, PCI_CLASS_DEVICE);
vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
device_id = pci_config_readw(d, PCI_DEVICE_ID);
switch(class) {
case 0x0101:
if (vendor_id == 0x8086 && device_id == 0x7010) {
/* PIIX3 IDE */
pci_config_writew(d, 0x40, 0x8000); // enable IDE0
pci_config_writew(d, 0x42, 0x8000); // enable IDE1
goto default_map;
} else {
/* IDE: we map it as in ISA mode */
pci_set_io_region_addr(d, 0, 0x1f0);
pci_set_io_region_addr(d, 1, 0x3f4);
pci_set_io_region_addr(d, 2, 0x170);
pci_set_io_region_addr(d, 3, 0x374);
}
break;
case 0x0300:
if (vendor_id != 0x1234)
goto default_map;
/* VGA: map frame buffer to default Bochs VBE address */
pci_set_io_region_addr(d, 0, 0xE0000000);
break;
case 0x0800:
/* PIC */
vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
device_id = pci_config_readw(d, PCI_DEVICE_ID);
if (vendor_id == 0x1014) {
/* IBM */
if (device_id == 0x0046 || device_id == 0xFFFF) {
/* MPIC & MPIC2 */
pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
}
}
break;
case 0xff00:
if (vendor_id == 0x0106b &&
(device_id == 0x0017 || device_id == 0x0022)) {
/* macio bridge */
pci_set_io_region_addr(d, 0, 0x80800000);
}
break;
default:
default_map:
/* default memory mappings */
for(i = 0; i < PCI_NUM_REGIONS; i++) {
r = &d->io_regions[i];
if (r->size) {
if (r->type & PCI_ADDRESS_SPACE_IO)
paddr = &pci_bios_io_addr;
else
paddr = &pci_bios_mem_addr;
*paddr = (*paddr + r->size - 1) & ~(r->size - 1);
pci_set_io_region_addr(d, i, *paddr);
*paddr += r->size;
}
}
break;
}
/* map the interrupt */
pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
if (pin != 0) {
pin = pci_slot_get_pirq(d, pin - 1);
pic_irq = pci_irqs[pin];
pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
}
}
/*
* This function initializes the PCI devices as a normal PCI BIOS
* would do. It is provided just in case the BIOS has no support for
* PCI.
*/
void pci_bios_init(void)
{
int i, irq;
uint8_t elcr[2];
pci_bios_io_addr = 0xc000;
pci_bios_mem_addr = 0xf0000000;
/* activate IRQ mappings */
elcr[0] = 0x00;
elcr[1] = 0x00;
for(i = 0; i < 4; i++) {
irq = pci_irqs[i];
/* set to trigger level */
elcr[irq >> 3] |= (1 << (irq & 7));
/* activate irq remapping in PIIX */
pci_config_writeb(piix3_dev, 0x60 + i, irq);
}
isa_outb(elcr[0], 0x4d0);
isa_outb(elcr[1], 0x4d1);
pci_for_each_device(pci_bios_init_device);
}
+2 -2
View File
@@ -243,8 +243,8 @@ void pl011_init(uint32_t base, void *pic, int irq,
s->cr = 0x300;
s->flags = 0x90;
if (chr){
qemu_chr_add_read_handler(chr, pl011_can_recieve, pl011_recieve, s);
qemu_chr_add_event_handler(chr, pl011_event);
qemu_chr_add_handlers(chr, pl011_can_recieve, pl011_recieve,
pl011_event, s);
}
/* ??? Save/restore. */
}
+24 -8
View File
@@ -1,5 +1,5 @@
/*
* Arm PrimeCell PL080 DMA controller
* Arm PrimeCell PL080/PL081 DMA controller
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
@@ -9,7 +9,7 @@
#include "vl.h"
#define PL080_NUM_CHANNELS 8
#define PL080_MAX_CHANNELS 8
#define PL080_CONF_E 0x1
#define PL080_CONF_M1 0x2
#define PL080_CONF_M2 0x4
@@ -45,7 +45,8 @@ typedef struct {
uint32_t sync;
uint32_t req_single;
uint32_t req_burst;
pl080_channel chan[PL080_NUM_CHANNELS];
pl080_channel chan[PL080_MAX_CHANNELS];
int nchannels;
/* Flag to avoid recursive DMA invocations. */
int running;
void *pic;
@@ -55,6 +56,9 @@ typedef struct {
static const unsigned char pl080_id[] =
{ 0x80, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
static const unsigned char pl081_id[] =
{ 0x81, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
static void pl080_update(pl080_state *s)
{
if ((s->tc_int & s->tc_mask)
@@ -80,7 +84,7 @@ static void pl080_run(pl080_state *s)
uint32_t req;
s->tc_mask = 0;
for (c = 0; c < PL080_NUM_CHANNELS; c++) {
for (c = 0; c < s->nchannels; c++) {
if (s->chan[c].conf & PL080_CCONF_ITC)
s->tc_mask |= 1 << c;
if (s->chan[c].conf & PL080_CCONF_IE)
@@ -99,7 +103,7 @@ cpu_abort(cpu_single_env, "DMA active\n");
}
s->running = 1;
while (s->running) {
for (c = 0; c < PL080_NUM_CHANNELS; c++) {
for (c = 0; c < s->nchannels; c++) {
ch = &s->chan[c];
again:
/* Test if thiws channel has any pending DMA requests. */
@@ -185,10 +189,16 @@ static uint32_t pl080_read(void *opaque, target_phys_addr_t offset)
offset -= s->base;
if (offset >= 0xfe0 && offset < 0x1000) {
return pl080_id[(offset - 0xfe0) >> 2];
if (s->nchannels == 8) {
return pl080_id[(offset - 0xfe0) >> 2];
} else {
return pl081_id[(offset - 0xfe0) >> 2];
}
}
if (offset >= 0x100 && offset < 0x200) {
i = (offset & 0xe0) >> 5;
if (i >= s->nchannels)
goto bad_offset;
switch (offset >> 2) {
case 0: /* SrcAddr */
return s->chan[i].src;
@@ -217,7 +227,7 @@ static uint32_t pl080_read(void *opaque, target_phys_addr_t offset)
return s->err_int;
case 7: /* EnbldChns */
mask = 0;
for (i = 0; i < PL080_NUM_CHANNELS; i++) {
for (i = 0; i < s->nchannels; i++) {
if (s->chan[i].conf & PL080_CCONF_E)
mask |= 1 << i;
}
@@ -248,6 +258,8 @@ static void pl080_write(void *opaque, target_phys_addr_t offset,
offset -= s->base;
if (offset >= 0x100 && offset < 0x200) {
i = (offset & 0xe0) >> 5;
if (i >= s->nchannels)
goto bad_offset;
switch (offset >> 2) {
case 0: /* SrcAddr */
s->chan[i].src = value;
@@ -293,6 +305,7 @@ static void pl080_write(void *opaque, target_phys_addr_t offset,
s->sync = value;
break;
default:
bad_offset:
cpu_abort(cpu_single_env, "pl080_write: Bad offset %x\n", offset);
}
pl080_update(s);
@@ -310,7 +323,9 @@ static CPUWriteMemoryFunc *pl080_writefn[] = {
pl080_write
};
void *pl080_init(uint32_t base, void *pic, int irq)
/* The PL080 and PL081 are the same except for the number of channels
they implement (8 and 2 respectively). */
void *pl080_init(uint32_t base, void *pic, int irq, int nchannels)
{
int iomemtype;
pl080_state *s;
@@ -322,6 +337,7 @@ void *pl080_init(uint32_t base, void *pic, int irq)
s->base = base;
s->pic = pic;
s->irq = irq;
s->nchannels = nchannels;
/* ??? Save/restore. */
return s;
}
+3 -2
View File
@@ -185,10 +185,11 @@ static void pl110_update_display(void *opaque)
addr = base;
dirty = cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG);
new_dirty = dirty;
for (i = 0; i < s->rows; i++) {
new_dirty = 0;
if ((addr & TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) {
if ((addr & ~TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) {
uint32_t tmp;
new_dirty = 0;
for (tmp = 0; tmp < src_width; tmp += TARGET_PAGE_SIZE) {
new_dirty |= cpu_physical_memory_get_dirty(addr + tmp,
VGA_DIRTY_FLAG);
+1 -1
View File
@@ -79,7 +79,7 @@ static drawfn glue(pl110_draw_fn_,BITS)[18] =
#endif
#define FN_2(x, y) FN(x, y) FN(x+1, y)
#define FN_4(x, y) FN_2(x, y) FN_2(x+1, y)
#define FN_4(x, y) FN_2(x, y) FN_2(x+2, y)
#define FN_8(y) FN_4(0, y) FN_4(4, y)
static void glue(pl110_draw_line1_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
-58
View File
@@ -201,64 +201,6 @@ void cpu_ppc_reset (CPUState *env)
}
#endif
static void PPC_io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
cpu_outb(NULL, addr & 0xffff, value);
}
static uint32_t PPC_io_readb (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inb(NULL, addr & 0xffff);
return ret;
}
static void PPC_io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap16(value);
#endif
cpu_outw(NULL, addr & 0xffff, value);
}
static uint32_t PPC_io_readw (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inw(NULL, addr & 0xffff);
#ifdef TARGET_WORDS_BIGENDIAN
ret = bswap16(ret);
#endif
return ret;
}
static void PPC_io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap32(value);
#endif
cpu_outl(NULL, addr & 0xffff, value);
}
static uint32_t PPC_io_readl (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inl(NULL, addr & 0xffff);
#ifdef TARGET_WORDS_BIGENDIAN
ret = bswap32(ret);
#endif
return ret;
}
CPUWriteMemoryFunc *PPC_io_write[] = {
&PPC_io_writeb,
&PPC_io_writew,
&PPC_io_writel,
};
CPUReadMemoryFunc *PPC_io_read[] = {
&PPC_io_readb,
&PPC_io_readw,
&PPC_io_readl,
};
/*****************************************************************************/
/* Debug port */
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
+12 -14
View File
@@ -305,7 +305,7 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
SetIRQFunc *set_irq;
void *pic;
m48t59_t *nvram;
int PPC_io_memory, unin_memory;
int unin_memory;
int linux_boot, i;
unsigned long bios_offset, vga_bios_offset;
uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
@@ -417,16 +417,15 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
isa_mem_base = 0x80000000;
/* Register 2 MB of ISA IO space */
PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
cpu_register_physical_memory(0xfe000000, 0x00200000, PPC_io_memory);
isa_mmio_init(0xfe000000, 0x00200000);
/* init basic PC hardware */
pic = heathrow_pic_init(&heathrow_pic_mem_index);
set_irq = heathrow_pic_set_irq;
pci_bus = pci_grackle_init(0xfec00000, pic);
vga_initialize(pci_bus, ds, phys_ram_base + ram_size,
ram_size, vga_ram_size,
vga_bios_offset, vga_bios_size);
pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
ram_size, vga_ram_size,
vga_bios_offset, vga_bios_size);
/* XXX: suppress that */
isa_pic = pic_init(pic_irq_request, NULL);
@@ -437,7 +436,7 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
for(i = 0; i < nb_nics; i++) {
if (!nd_table[i].model)
nd_table[i].model = "ne2k_pci";
pci_nic_init(pci_bus, &nd_table[i]);
pci_nic_init(pci_bus, &nd_table[i], -1);
}
pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
@@ -463,8 +462,7 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
isa_mem_base = 0x80000000;
/* Register 8 MB of ISA IO space */
PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
cpu_register_physical_memory(0xF2000000, 0x00800000, PPC_io_memory);
isa_mmio_init(0xf2000000, 0x00800000);
/* UniN init */
unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
@@ -474,9 +472,9 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
set_irq = openpic_set_irq;
pci_bus = pci_pmac_init(pic);
/* init basic PC hardware */
vga_initialize(pci_bus, ds, phys_ram_base + ram_size,
ram_size, vga_ram_size,
vga_bios_offset, vga_bios_size);
pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
ram_size, vga_ram_size,
vga_bios_offset, vga_bios_size);
/* XXX: suppress that */
isa_pic = pic_init(pic_irq_request, NULL);
@@ -485,7 +483,7 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
for(i = 0; i < nb_nics; i++) {
pci_ne2000_init(pci_bus, &nd_table[i]);
pci_ne2000_init(pci_bus, &nd_table[i], -1);
}
#if 1
+2 -3
View File
@@ -525,7 +525,6 @@ static void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
{
CPUState *env;
char buf[1024];
SetIRQFunc *set_irq;
m48t59_t *nvram;
int PPC_io_memory;
int linux_boot, i, nb_nics1, bios_size;
@@ -612,8 +611,8 @@ static void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
/* init basic PC hardware */
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size, 0, 0);
pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size, 0, 0);
rtc_init(0x70, 8);
// openpic = openpic_init(0x00000000, 0xF0000000, 1);
isa_pic = pic_init(pic_irq_request, first_cpu);
+9 -5
View File
@@ -117,11 +117,15 @@ static CPUReadMemoryFunc *PPC_PCIIO_read[] = {
&PPC_PCIIO_readl,
};
static void prep_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
/* Don't know if this matches real hardware, but it agrees with OHW. */
static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
{
/* XXX: we do not simulate the hardware - we rely on the BIOS to
set correctly for irq line field */
pic_set_irq(d->config[PCI_INTERRUPT_LINE], level);
return (irq_num + (pci_dev->devfn >> 3)) & 1;
}
static void prep_set_irq(void *pic, int irq_num, int level)
{
pic_set_irq(irq_num ? 11 : 9, level);
}
PCIBus *pci_prep_init(void)
@@ -131,7 +135,7 @@ PCIBus *pci_prep_init(void)
int PPC_io_memory;
s = qemu_mallocz(sizeof(PREPPCIState));
s->bus = pci_register_bus(prep_set_irq, NULL, 0);
s->bus = pci_register_bus(prep_set_irq, prep_map_irq, NULL, 0, 2);
register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
+1 -1
View File
@@ -560,7 +560,7 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
s->common.update_arg = update_arg;
ps2_reset(&s->common);
register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
qemu_add_mouse_event_handler(ps2_mouse_event, s, 0);
qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
qemu_register_reset(ps2_reset, &s->common);
return s;
}
Loaded 100 of 221 files, more files were not shown because too many files have changed in this diff. Show more